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
diff --git a/Makefile.am b/Makefile.am
index 536b3f4..c5c3137 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -17,7 +17,7 @@
 	$(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
diff --git a/configure.ac b/configure.ac
index 80f50e8..5482b8c 100644
--- a/configure.ac
+++ b/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 @@
 
 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 @@
 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 @@
    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 @@
 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
diff --git a/contrib/a-link/sccp-split-by-con.lua b/contrib/a-link/sccp-split-by-con.lua
deleted file mode 100644
index f5d5502..0000000
--- a/contrib/a-link/sccp-split-by-con.lua
+++ /dev/null
@@ -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
diff --git a/contrib/bsc-test/README b/contrib/bsc-test/README
deleted file mode 100644
index adb222e..0000000
--- a/contrib/bsc-test/README
+++ /dev/null
@@ -1 +0,0 @@
-Some crazy scripts call testing... and MSC link failure simulation
diff --git a/contrib/bsc-test/all_dial b/contrib/bsc-test/all_dial
deleted file mode 100644
index 96e5f00..0000000
--- a/contrib/bsc-test/all_dial
+++ /dev/null
@@ -1,8 +0,0 @@
-ABORT BUSY
-ABORT 'NO CARRIER'
-ABORT 'OK'
-
-'' AT
-SAY "Dialing a number\n"
-'OK' ATD05660066;
-
diff --git a/contrib/bsc-test/dial.sh b/contrib/bsc-test/dial.sh
deleted file mode 100755
index e5e19f6..0000000
--- a/contrib/bsc-test/dial.sh
+++ /dev/null
@@ -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
-
diff --git a/contrib/bsc-test/drop-oml.sh b/contrib/bsc-test/drop-oml.sh
deleted file mode 100755
index 84eead7..0000000
--- a/contrib/bsc-test/drop-oml.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-sleep 3
-echo "enable"
-sleep 1
-echo "drop bts connection 0 oml"
-sleep 1
diff --git a/contrib/bsc-test/drop.sh b/contrib/bsc-test/drop.sh
deleted file mode 100755
index c7b66ba..0000000
--- a/contrib/bsc-test/drop.sh
+++ /dev/null
@@ -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
diff --git a/contrib/bsc-test/hangup b/contrib/bsc-test/hangup
deleted file mode 100644
index cad6870..0000000
--- a/contrib/bsc-test/hangup
+++ /dev/null
@@ -1,4 +0,0 @@
-TIMEOUT 10
-'' ^Z
-SAY "Waiting for hangup confirm\n"
-'' ATH;
diff --git a/contrib/bsc-test/msc.sh b/contrib/bsc-test/msc.sh
deleted file mode 100755
index bec011d..0000000
--- a/contrib/bsc-test/msc.sh
+++ /dev/null
@@ -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
diff --git a/contrib/bsc_control.py b/contrib/bsc_control.py
deleted file mode 100755
index c1b09ce..0000000
--- a/contrib/bsc_control.py
+++ /dev/null
@@ -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()
diff --git a/contrib/bt.py b/contrib/bt.py
deleted file mode 100755
index 1b111ef..0000000
--- a/contrib/bt.py
+++ /dev/null
@@ -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))
-
-
-
diff --git a/contrib/convert_to_enum.py b/contrib/convert_to_enum.py
deleted file mode 100755
index bcd6f2c..0000000
--- a/contrib/convert_to_enum.py
+++ /dev/null
@@ -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]
diff --git a/contrib/ctrl2sse.py b/contrib/ctrl2sse.py
deleted file mode 100755
index 8b630ec..0000000
--- a/contrib/ctrl2sse.py
+++ /dev/null
@@ -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()
diff --git a/contrib/gprs/gb-proxy-unblock-bug.py b/contrib/gprs/gb-proxy-unblock-bug.py
deleted file mode 100755
index 0cd4b87..0000000
--- a/contrib/gprs/gb-proxy-unblock-bug.py
+++ /dev/null
@@ -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"
diff --git a/contrib/gprs/gprs-bssgp-histogram.lua b/contrib/gprs/gprs-bssgp-histogram.lua
deleted file mode 100644
index b1ab5df..0000000
--- a/contrib/gprs/gprs-bssgp-histogram.lua
+++ /dev/null
@@ -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
diff --git a/contrib/gprs/gprs-buffer-count.lua b/contrib/gprs/gprs-buffer-count.lua
deleted file mode 100644
index ca8864a..0000000
--- a/contrib/gprs/gprs-buffer-count.lua
+++ /dev/null
@@ -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
diff --git a/contrib/gprs/gprs-split-trace-by-tlli.lua b/contrib/gprs/gprs-split-trace-by-tlli.lua
deleted file mode 100644
index 018c377..0000000
--- a/contrib/gprs/gprs-split-trace-by-tlli.lua
+++ /dev/null
@@ -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
diff --git a/contrib/gprs/gprs-verify-nu.lua b/contrib/gprs/gprs-verify-nu.lua
deleted file mode 100644
index e44fdd1..0000000
--- a/contrib/gprs/gprs-verify-nu.lua
+++ /dev/null
@@ -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
-
diff --git a/contrib/hlr-remove-old.sql b/contrib/hlr-remove-old.sql
deleted file mode 100644
index 626a331..0000000
--- a/contrib/hlr-remove-old.sql
+++ /dev/null
@@ -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;
diff --git a/contrib/hlrsync/hlrsync.py b/contrib/hlrsync/hlrsync.py
deleted file mode 100755
index e4a4955..0000000
--- a/contrib/hlrsync/hlrsync.py
+++ /dev/null
@@ -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()
-
diff --git a/contrib/jenkins.sh b/contrib/jenkins.sh
index 2b667ad..22b962e 100755
--- a/contrib/jenkins.sh
+++ b/contrib/jenkins.sh
@@ -26,31 +26,22 @@
 
 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
diff --git a/contrib/nat/test_regexp.c b/contrib/nat/test_regexp.c
deleted file mode 100644
index 808a703..0000000
--- a/contrib/nat/test_regexp.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* make test_regexp */
-#include <sys/types.h>
-#include <regex.h>
-#include <stdio.h>
-
-
-int main(int argc, char **argv)
-{
-	regex_t reg;
-	regmatch_t matches[2];
-
-	if (argc != 4) {
-		printf("Invoke with: test_regexp REGEXP REPLACE NR\n");
-		return -1;
-	}
-
-	if (regcomp(&reg, argv[1], REG_EXTENDED) != 0) {
-		fprintf(stderr, "Regexp '%s' is not valid.\n", argv[1]);
-		return -1;
-	}
-
-	if (regexec(&reg, argv[3], 2, matches, 0) == 0 && matches[1].rm_eo != -1)
-		printf("New Number: %s%s\n", argv[2], &argv[3][matches[1].rm_so]);
-	else
-		printf("No match.\n");
-
-	regfree(&reg);
-
-	return 0;
-}
diff --git a/contrib/nat/ussd_example.py b/contrib/nat/ussd_example.py
deleted file mode 100644
index 8f7a58d..0000000
--- a/contrib/nat/ussd_example.py
+++ /dev/null
@@ -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)
diff --git a/contrib/rtp/gen_rtp_header.erl b/contrib/rtp/gen_rtp_header.erl
deleted file mode 100755
index 47839c1..0000000
--- a/contrib/rtp/gen_rtp_header.erl
+++ /dev/null
@@ -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.
diff --git a/contrib/rtp/rtp_replay.st b/contrib/rtp/rtp_replay.st
deleted file mode 100644
index e26d073..0000000
--- a/contrib/rtp/rtp_replay.st
+++ /dev/null
@@ -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.
-]
diff --git a/contrib/rtp/rtp_replay_shared.st b/contrib/rtp/rtp_replay_shared.st
deleted file mode 100644
index 7b68c0f..0000000
--- a/contrib/rtp/rtp_replay_shared.st
+++ /dev/null
@@ -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.
-                ]
-        ]
-    ]
-]
-
diff --git a/contrib/rtp/rtp_replay_sip.st b/contrib/rtp/rtp_replay_sip.st
deleted file mode 100644
index 5f844df..0000000
--- a/contrib/rtp/rtp_replay_sip.st
+++ /dev/null
@@ -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.
-]
diff --git a/contrib/rtp/timestamp_rtp.lua b/contrib/rtp/timestamp_rtp.lua
deleted file mode 100644
index c18a06b..0000000
--- a/contrib/rtp/timestamp_rtp.lua
+++ /dev/null
@@ -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
diff --git a/contrib/sms/fill-hlr.st b/contrib/sms/fill-hlr.st
deleted file mode 100644
index da0643e..0000000
--- a/contrib/sms/fill-hlr.st
+++ /dev/null
@@ -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.
-
-]
diff --git a/contrib/sms/hlr-query.st b/contrib/sms/hlr-query.st
deleted file mode 100644
index bd3f97a..0000000
--- a/contrib/sms/hlr-query.st
+++ /dev/null
@@ -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.
-].
-]
diff --git a/contrib/sms/sqlite-probe.tap.d b/contrib/sms/sqlite-probe.tap.d
deleted file mode 100644
index e75cdfc..0000000
--- a/contrib/sms/sqlite-probe.tap.d
+++ /dev/null
@@ -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);
-}
diff --git a/contrib/soap.py b/contrib/soap.py
deleted file mode 100755
index 4d0a023..0000000
--- a/contrib/soap.py
+++ /dev/null
@@ -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()
diff --git a/contrib/systemd/osmo-bsc.service b/contrib/systemd/osmo-bsc.service
deleted file mode 100644
index 4047fef..0000000
--- a/contrib/systemd/osmo-bsc.service
+++ /dev/null
@@ -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
diff --git a/contrib/systemd/osmo-gbproxy.service b/contrib/systemd/osmo-gbproxy.service
deleted file mode 100644
index a0b7829..0000000
--- a/contrib/systemd/osmo-gbproxy.service
+++ /dev/null
@@ -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
diff --git a/contrib/systemd/osmo-msc.service b/contrib/systemd/osmo-msc.service
deleted file mode 100644
index 7cebb14..0000000
--- a/contrib/systemd/osmo-msc.service
+++ /dev/null
@@ -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
diff --git a/contrib/systemd/osmo-nitb.service b/contrib/systemd/osmo-nitb.service
deleted file mode 100644
index 377497e..0000000
--- a/contrib/systemd/osmo-nitb.service
+++ /dev/null
@@ -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
diff --git a/contrib/systemd/osmo-sgsn.service b/contrib/systemd/osmo-sgsn.service
deleted file mode 100644
index bf6a8e0..0000000
--- a/contrib/systemd/osmo-sgsn.service
+++ /dev/null
@@ -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
diff --git a/contrib/testconv/Makefile b/contrib/testconv/Makefile
deleted file mode 100644
index bb856f7..0000000
--- a/contrib/testconv/Makefile
+++ /dev/null
@@ -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 $@ $<
diff --git a/contrib/testconv/testconv_main.c b/contrib/testconv/testconv_main.c
deleted file mode 100644
index 6c95c55..0000000
--- a/contrib/testconv/testconv_main.c
+++ /dev/null
@@ -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;
-}
-
diff --git a/contrib/twisted_ipa.py b/contrib/twisted_ipa.py
deleted file mode 100755
index e6d7b1a..0000000
--- a/contrib/twisted_ipa.py
+++ /dev/null
@@ -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.")
diff --git a/include/Makefile.am b/include/Makefile.am
index 3234e62..73b1b3e 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -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)
diff --git a/include/compat_af_isdn.h b/include/compat_af_isdn.h
deleted file mode 100644
index 56cbfb3..0000000
--- a/include/compat_af_isdn.h
+++ /dev/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
diff --git a/include/mISDNif.h b/include/mISDNif.h
deleted file mode 100644
index 8e065d2..0000000
--- a/include/mISDNif.h
+++ /dev/null
@@ -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 */
diff --git a/include/openbsc/Makefile.am b/include/openbsc/Makefile.am
deleted file mode 100644
index 89e0338..0000000
--- a/include/openbsc/Makefile.am
+++ /dev/null
@@ -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
diff --git a/include/openbsc/a_iface.h b/include/openbsc/a_iface.h
deleted file mode 100644
index 149f1c7..0000000
--- a/include/openbsc/a_iface.h
+++ /dev/null
@@ -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);
diff --git a/include/openbsc/a_iface_bssap.h b/include/openbsc/a_iface_bssap.h
deleted file mode 100644
index 237c618..0000000
--- a/include/openbsc/a_iface_bssap.h
+++ /dev/null
@@ -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);
-
diff --git a/include/openbsc/a_reset.h b/include/openbsc/a_reset.h
deleted file mode 100644
index 7aaab06..0000000
--- a/include/openbsc/a_reset.h
+++ /dev/null
@@ -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);
diff --git a/include/openbsc/abis_nm.h b/include/openbsc/abis_nm.h
deleted file mode 100644
index db2a659..0000000
--- a/include/openbsc/abis_nm.h
+++ /dev/null
@@ -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 */
diff --git a/include/openbsc/abis_om2000.h b/include/openbsc/abis_om2000.h
deleted file mode 100644
index b093a03..0000000
--- a/include/openbsc/abis_om2000.h
+++ /dev/null
@@ -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 */
diff --git a/include/openbsc/abis_rsl.h b/include/openbsc/abis_rsl.h
deleted file mode 100644
index f983fce..0000000
--- a/include/openbsc/abis_rsl.h
+++ /dev/null
@@ -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 */
-
diff --git a/include/openbsc/arfcn_range_encode.h b/include/openbsc/arfcn_range_encode.h
deleted file mode 100644
index 7ec710c..0000000
--- a/include/openbsc/arfcn_range_encode.h
+++ /dev/null
@@ -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
diff --git a/include/openbsc/auth.h b/include/openbsc/auth.h
deleted file mode 100644
index b314bbf..0000000
--- a/include/openbsc/auth.h
+++ /dev/null
@@ -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 */
diff --git a/include/openbsc/bsc_api.h b/include/openbsc/bsc_api.h
deleted file mode 100644
index 40068d6..0000000
--- a/include/openbsc/bsc_api.h
+++ /dev/null
@@ -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
diff --git a/include/openbsc/bsc_msc.h b/include/openbsc/bsc_msc.h
deleted file mode 100644
index 380eb17..0000000
--- a/include/openbsc/bsc_msc.h
+++ /dev/null
@@ -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
diff --git a/include/openbsc/bsc_msc_data.h b/include/openbsc/bsc_msc_data.h
deleted file mode 100644
index 4a283d1..0000000
--- a/include/openbsc/bsc_msc_data.h
+++ /dev/null
@@ -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
diff --git a/include/openbsc/bsc_msg_filter.h b/include/openbsc/bsc_msg_filter.h
deleted file mode 100644
index a9dedf4..0000000
--- a/include/openbsc/bsc_msg_filter.h
+++ /dev/null
@@ -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);
diff --git a/include/openbsc/bsc_nat.h b/include/openbsc/bsc_nat.h
deleted file mode 100644
index 94ab0e5..0000000
--- a/include/openbsc/bsc_nat.h
+++ /dev/null
@@ -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
diff --git a/include/openbsc/bsc_nat_callstats.h b/include/openbsc/bsc_nat_callstats.h
deleted file mode 100644
index 64f9bfc..0000000
--- a/include/openbsc/bsc_nat_callstats.h
+++ /dev/null
@@ -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
diff --git a/include/openbsc/bsc_nat_sccp.h b/include/openbsc/bsc_nat_sccp.h
deleted file mode 100644
index 0824664..0000000
--- a/include/openbsc/bsc_nat_sccp.h
+++ /dev/null
@@ -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
diff --git a/include/openbsc/bsc_rll.h b/include/openbsc/bsc_rll.h
deleted file mode 100644
index 729ba60..0000000
--- a/include/openbsc/bsc_rll.h
+++ /dev/null
@@ -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 */
diff --git a/include/openbsc/bsc_subscriber.h b/include/openbsc/bsc_subscriber.h
deleted file mode 100644
index 324734f..0000000
--- a/include/openbsc/bsc_subscriber.h
+++ /dev/null
@@ -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);
diff --git a/include/openbsc/bss.h b/include/openbsc/bss.h
deleted file mode 100644
index 9f16bf7..0000000
--- a/include/openbsc/bss.h
+++ /dev/null
@@ -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
diff --git a/include/openbsc/bts_ipaccess_nanobts_omlattr.h b/include/openbsc/bts_ipaccess_nanobts_omlattr.h
deleted file mode 100644
index bc7860b..0000000
--- a/include/openbsc/bts_ipaccess_nanobts_omlattr.h
+++ /dev/null
@@ -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);
diff --git a/include/openbsc/chan_alloc.h b/include/openbsc/chan_alloc.h
deleted file mode 100644
index 7388e14..0000000
--- a/include/openbsc/chan_alloc.h
+++ /dev/null
@@ -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 */
diff --git a/include/openbsc/common.h b/include/openbsc/common.h
deleted file mode 100644
index d91b3d3..0000000
--- a/include/openbsc/common.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#pragma once
-
-enum nsap_addr_enc {
-	NSAP_ADDR_ENC_X213,
-	NSAP_ADDR_ENC_V4RAW,
-};
diff --git a/include/openbsc/common_bsc.h b/include/openbsc/common_bsc.h
deleted file mode 100644
index 7960383..0000000
--- a/include/openbsc/common_bsc.h
+++ /dev/null
@@ -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);
diff --git a/include/openbsc/common_cs.h b/include/openbsc/common_cs.h
deleted file mode 100644
index 6dc956f..0000000
--- a/include/openbsc/common_cs.h
+++ /dev/null
@@ -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);
diff --git a/include/openbsc/crc24.h b/include/openbsc/crc24.h
deleted file mode 100644
index 756638c..0000000
--- a/include/openbsc/crc24.h
+++ /dev/null
@@ -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
diff --git a/include/openbsc/ctrl.h b/include/openbsc/ctrl.h
deleted file mode 100644
index c5ac210..0000000
--- a/include/openbsc/ctrl.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-
-struct ctrl_handle *bsc_controlif_setup(struct gsm_network *net,
-					const char *bind_addr, uint16_t port);
diff --git a/include/openbsc/db.h b/include/openbsc/db.h
deleted file mode 100644
index 988c9bd..0000000
--- a/include/openbsc/db.h
+++ /dev/null
@@ -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 */
diff --git a/include/openbsc/debug.h b/include/openbsc/debug.h
deleted file mode 100644
index 65e197d..0000000
--- a/include/openbsc/debug.h
+++ /dev/null
@@ -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;
diff --git a/include/openbsc/e1_config.h b/include/openbsc/e1_config.h
deleted file mode 100644
index 538c0b0..0000000
--- a/include/openbsc/e1_config.h
+++ /dev/null
@@ -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 */
-
diff --git a/include/openbsc/gb_proxy.h b/include/openbsc/gb_proxy.h
deleted file mode 100644
index e10894f..0000000
--- a/include/openbsc/gb_proxy.h
+++ /dev/null
@@ -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
diff --git a/include/openbsc/gprs_gb_parse.h b/include/openbsc/gprs_gb_parse.h
deleted file mode 100644
index 2468392..0000000
--- a/include/openbsc/gprs_gb_parse.h
+++ /dev/null
@@ -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);
diff --git a/include/openbsc/gprs_gmm.h b/include/openbsc/gprs_gmm.h
deleted file mode 100644
index c38e49f..0000000
--- a/include/openbsc/gprs_gmm.h
+++ /dev/null
@@ -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 */
diff --git a/include/openbsc/gprs_llc.h b/include/openbsc/gprs_llc.h
deleted file mode 100644
index 8bc2267..0000000
--- a/include/openbsc/gprs_llc.h
+++ /dev/null
@@ -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
diff --git a/include/openbsc/gprs_llc_xid.h b/include/openbsc/gprs_llc_xid.h
deleted file mode 100644
index d340d40..0000000
--- a/include/openbsc/gprs_llc_xid.h
+++ /dev/null
@@ -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);
-
diff --git a/include/openbsc/gprs_sgsn.h b/include/openbsc/gprs_sgsn.h
deleted file mode 100644
index 57995e0..0000000
--- a/include/openbsc/gprs_sgsn.h
+++ /dev/null
@@ -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 */
diff --git a/include/openbsc/gprs_sndcp.h b/include/openbsc/gprs_sndcp.h
deleted file mode 100644
index d970240..0000000
--- a/include/openbsc/gprs_sndcp.h
+++ /dev/null
@@ -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 */
diff --git a/include/openbsc/gprs_sndcp_comp.h b/include/openbsc/gprs_sndcp_comp.h
deleted file mode 100644
index 87ab638..0000000
--- a/include/openbsc/gprs_sndcp_comp.h
+++ /dev/null
@@ -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);
diff --git a/include/openbsc/gprs_sndcp_dcomp.h b/include/openbsc/gprs_sndcp_dcomp.h
deleted file mode 100644
index a76b4a4..0000000
--- a/include/openbsc/gprs_sndcp_dcomp.h
+++ /dev/null
@@ -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);
diff --git a/include/openbsc/gprs_sndcp_pcomp.h b/include/openbsc/gprs_sndcp_pcomp.h
deleted file mode 100644
index 4e15b9b..0000000
--- a/include/openbsc/gprs_sndcp_pcomp.h
+++ /dev/null
@@ -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);
diff --git a/include/openbsc/gprs_sndcp_xid.h b/include/openbsc/gprs_sndcp_xid.h
deleted file mode 100644
index e64bc52..0000000
--- a/include/openbsc/gprs_sndcp_xid.h
+++ /dev/null
@@ -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);
-
diff --git a/include/openbsc/gprs_subscriber.h b/include/openbsc/gprs_subscriber.h
deleted file mode 100644
index be78feb..0000000
--- a/include/openbsc/gprs_subscriber.h
+++ /dev/null
@@ -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__)
diff --git a/include/openbsc/gprs_utils.h b/include/openbsc/gprs_utils.h
deleted file mode 100644
index 574f5c5..0000000
--- a/include/openbsc/gprs_utils.h
+++ /dev/null
@@ -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);
diff --git a/include/openbsc/gsm_04_08.h b/include/openbsc/gsm_04_08.h
deleted file mode 100644
index ca251b0..0000000
--- a/include/openbsc/gsm_04_08.h
+++ /dev/null
@@ -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
diff --git a/include/openbsc/gsm_04_11.h b/include/openbsc/gsm_04_11.h
deleted file mode 100644
index 3305e3e..0000000
--- a/include/openbsc/gsm_04_11.h
+++ /dev/null
@@ -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
diff --git a/include/openbsc/gsm_04_80.h b/include/openbsc/gsm_04_80.h
deleted file mode 100644
index d65f640..0000000
--- a/include/openbsc/gsm_04_80.h
+++ /dev/null
@@ -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
diff --git a/include/openbsc/gsm_data.h b/include/openbsc/gsm_data.h
deleted file mode 100644
index 6079900..0000000
--- a/include/openbsc/gsm_data.h
+++ /dev/null
@@ -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 */
diff --git a/include/openbsc/gsm_data_shared.h b/include/openbsc/gsm_data_shared.h
deleted file mode 100644
index bed46d2..0000000
--- a/include/openbsc/gsm_data_shared.h
+++ /dev/null
@@ -1,1003 +0,0 @@
-#ifndef _GSM_DATA_SHAREDH
-#define _GSM_DATA_SHAREDH
-
-#include <regex.h>
-#include <stdbool.h>
-#include <stdint.h>
-
-#include <osmocom/core/timer.h>
-#include <osmocom/core/bitvec.h>
-#include <osmocom/core/statistics.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/gsm/rxlev_stat.h>
-#include <osmocom/gsm/sysinfo.h>
-#include <osmocom/gsm/meas_rep.h>
-#include <osmocom/gsm/protocol/gsm_04_08.h>
-#include <osmocom/gsm/protocol/gsm_08_58.h>
-#include <osmocom/gsm/protocol/gsm_12_21.h>
-
-#include <osmocom/abis/e1_input.h>
-
-#ifndef ROLE_BSC
-#include <osmocom/gsm/lapdm.h>
-#endif
-
-#include <openbsc/common_cs.h>
-
-/* 16 is the max. number of SI2quater messages according to 3GPP TS 44.018 Table 10.5.2.33b.1:
-   4-bit index is used (2#1111 = 10#15) */
-#define SI2Q_MAX_NUM 16
-/* length in bits (for single SI2quater message) */
-#define SI2Q_MAX_LEN 160
-#define SI2Q_MIN_LEN 18
-
-struct osmo_bsc_data;
-
-struct osmo_bsc_sccp_con;
-struct gsm_sms_queue;
-
-/* RRLP mode of operation */
-enum rrlp_mode {
-	RRLP_MODE_NONE,
-	RRLP_MODE_MS_BASED,
-	RRLP_MODE_MS_PREF,
-	RRLP_MODE_ASS_PREF,
-};
-
-/* Channel Request reason */
-enum gsm_chreq_reason_t {
-	GSM_CHREQ_REASON_EMERG,
-	GSM_CHREQ_REASON_PAG,
-	GSM_CHREQ_REASON_CALL,
-	GSM_CHREQ_REASON_LOCATION_UPD,
-	GSM_CHREQ_REASON_OTHER,
-	GSM_CHREQ_REASON_PDCH,
-};
-
-/* lchans 0..3 are SDCCH in combined channel configuration,
-   use 4 as magic number for BCCH hack - see osmo-bts-../oml.c:opstart_compl() */
-#define CCCH_LCHAN 4
-
-#define TRX_NR_TS	8
-#define TS_MAX_LCHAN	8
-
-#define HARDCODED_ARFCN 123
-#define HARDCODED_BSIC	0x3f	/* NCC = 7 / BCC = 7 */
-
-/* for multi-drop config */
-#define HARDCODED_BTS0_TS	1
-#define HARDCODED_BTS1_TS	6
-#define HARDCODED_BTS2_TS	11
-
-#define MAX_VERSION_LENGTH 64
-
-#define MAX_BTS_FEATURES 128
-
-enum gsm_hooks {
-	GSM_HOOK_NM_SWLOAD,
-	GSM_HOOK_RR_PAGING,
-	GSM_HOOK_RR_SECURITY,
-};
-
-enum gsm_paging_event {
-	GSM_PAGING_SUCCEEDED,
-	GSM_PAGING_EXPIRED,
-	GSM_PAGING_OOM,
-	GSM_PAGING_BUSY,
-};
-
-enum bts_gprs_mode {
-	BTS_GPRS_NONE = 0,
-	BTS_GPRS_GPRS = 1,
-	BTS_GPRS_EGPRS = 2,
-};
-
-struct gsm_lchan;
-struct gsm_mncc;
-struct osmo_rtp_socket;
-struct rtp_socket;
-struct bsc_api;
-
-/* Network Management State */
-struct gsm_nm_state {
-	uint8_t operational;
-	uint8_t administrative;
-	uint8_t availability;
-};
-
-struct gsm_abis_mo {
-	uint8_t obj_class;
-	uint8_t procedure_pending;
-	struct abis_om_obj_inst obj_inst;
-	const char *name;
-	struct gsm_nm_state nm_state;
-	struct tlv_parsed *nm_attr;
-	struct gsm_bts *bts;
-};
-
-/* Ericsson OM2000 Managed Object */
-struct abis_om2k_mo {
-	uint8_t class;
-	uint8_t bts;
-	uint8_t assoc_so;
-	uint8_t inst;
-} __attribute__ ((packed));
-
-struct om2k_mo {
-	struct abis_om2k_mo addr;
-	struct osmo_fsm_inst *fsm;
-};
-
-#define A38_XOR_MIN_KEY_LEN	12
-#define A38_XOR_MAX_KEY_LEN	16
-#define A38_COMP128_KEY_LEN	16
-#define RSL_ENC_ALG_A5(x)	(x+1)
-#define MAX_EARFCN_LIST 32
-
-/* is the data link established? who established it? */
-#define LCHAN_SAPI_UNUSED	0
-#define LCHAN_SAPI_MS		1
-#define LCHAN_SAPI_NET		2
-#define LCHAN_SAPI_REL		3
-
-/* state of a logical channel */
-enum gsm_lchan_state {
-	LCHAN_S_NONE,		/* channel is not active */
-	LCHAN_S_ACT_REQ,	/* channel activation requested */
-	LCHAN_S_ACTIVE,		/* channel is active and operational */
-	LCHAN_S_REL_REQ,	/* channel release has been requested */
-	LCHAN_S_REL_ERR,	/* channel is in an error state */
-	LCHAN_S_BROKEN,		/* channel is somehow unusable */
-	LCHAN_S_INACTIVE,	/* channel is set inactive */
-};
-
-/* BTS ONLY */
-#define MAX_NUM_UL_MEAS	104
-#define LC_UL_M_F_L1_VALID	(1 << 0)
-#define LC_UL_M_F_RES_VALID	(1 << 1)
-
-struct bts_ul_meas {
-	/* BER in units of 0.01%: 10.000 == 100% ber, 0 == 0% ber */
-	uint16_t ber10k;
-	/* timing advance offset (in quarter bits) */
-	int16_t ta_offs_qbits;
-	/* C/I ratio in dB */
-	float c_i;
-	/* flags */
-	uint8_t is_sub:1;
-	/* RSSI in dBm * -1 */
-	uint8_t inv_rssi;
-};
-
-struct bts_codec_conf {
-	uint8_t hr;
-	uint8_t efr;
-	uint8_t amr;
-};
-
-struct amr_mode {
-	uint8_t mode;
-	uint8_t threshold;
-	uint8_t hysteresis;
-};
-
-struct amr_multirate_conf {
-	uint8_t gsm48_ie[2];
-	struct amr_mode ms_mode[4];
-	struct amr_mode bts_mode[4];
-	uint8_t num_modes;
-};
-/* /BTS ONLY */
-
-enum lchan_csd_mode {
-	LCHAN_CSD_M_NT,
-	LCHAN_CSD_M_T_1200_75,
-	LCHAN_CSD_M_T_600,
-	LCHAN_CSD_M_T_1200,
-	LCHAN_CSD_M_T_2400,
-	LCHAN_CSD_M_T_9600,
-	LCHAN_CSD_M_T_14400,
-	LCHAN_CSD_M_T_29000,
-	LCHAN_CSD_M_T_32000,
-};
-
-/* State of the SAPIs in the lchan */
-enum lchan_sapi_state {
-	LCHAN_SAPI_S_NONE,
-	LCHAN_SAPI_S_REQ,
-	LCHAN_SAPI_S_ASSIGNED,
-	LCHAN_SAPI_S_REL,
-	LCHAN_SAPI_S_ERROR,
-};
-
-struct gsm_lchan {
-	/* The TS that we're part of */
-	struct gsm_bts_trx_ts *ts;
-	/* The logical subslot number in the TS */
-	uint8_t nr;
-	/* The logical channel type */
-	enum gsm_chan_t type;
-	/* RSL channel mode */
-	enum rsl_cmod_spd rsl_cmode;
-	/* If TCH, traffic channel mode */
-	enum gsm48_chan_mode tch_mode;
-	enum lchan_csd_mode csd_mode;
-	/* State */
-	enum gsm_lchan_state state;
-	const char *broken_reason;
-	/* Power levels for MS and BTS */
-	uint8_t bs_power;
-	uint8_t ms_power;
-	/* Encryption information */
-	struct gsm_encr encr;
-
-	/* AMR bits */
-	uint8_t mr_ms_lv[7];
-	uint8_t mr_bts_lv[7];
-
-	/* Established data link layer services */
-	uint8_t sapis[8];
-	int sacch_deact;
-
-	struct {
-		uint32_t bound_ip;
-		uint32_t connect_ip;
-		uint16_t bound_port;
-		uint16_t connect_port;
-		uint16_t conn_id;
-		uint8_t rtp_payload;
-		uint8_t rtp_payload2;
-		uint8_t speech_mode;
-#ifdef ROLE_BSC
-		struct rtp_socket *rtp_socket;
-
-		/* info we need to postpone the AoIP
-		 * assignment completed message */
-		struct {
-			uint8_t rr_cause;
-			uint8_t chosen_channel;
-			uint8_t encr_alg_id;
-			uint8_t speech_mode;
-			bool valid;
-		} ass_compl;
-#else
-		struct osmo_rtp_socket *rtp_socket;
-#endif
-	} abis_ip;
-
-	uint8_t rqd_ta;
-
-	char *name;
-
-#ifdef ROLE_BSC
-	struct osmo_timer_list T3101;
-	struct osmo_timer_list T3109;
-	struct osmo_timer_list T3111;
-	struct osmo_timer_list error_timer;
-	struct osmo_timer_list act_timer;
-	struct osmo_timer_list rel_work;
-	uint8_t error_cause;
-
-	/* table of neighbor cell measurements */
-	struct neigh_meas_proc neigh_meas[MAX_NEIGH_MEAS];
-
-	/* cache of last measurement reports on this lchan */
-	struct gsm_meas_rep meas_rep[6];
-	int meas_rep_idx;
-
-	/* GSM Random Access data */
-	struct gsm48_req_ref *rqd_ref;
-
-	struct gsm_subscriber_connection *conn;
-
-	struct {
-		/* channel activation type and handover ref */
-		uint8_t act_type;
-		uint8_t ho_ref;
-		struct gsm48_req_ref *rqd_ref;
-		uint8_t rqd_ta;
-	} dyn;
-#else
-	/* Number of different GsmL1_Sapi_t used in osmo_bts_sysmo is 23.
-	 * Currently we don't share these headers so this is a magic number. */
-	struct llist_head sapi_cmds;
-	uint8_t sapis_dl[23];
-	uint8_t sapis_ul[23];
-	struct lapdm_channel lapdm_ch;
-	struct llist_head dl_tch_queue;
-	struct {
-		/* bitmask of all SI that are present/valid in si_buf */
-		uint32_t valid;
-		uint32_t last;
-		/* buffers where we put the pre-computed SI:
-		   SI2Q_MAX_NUM is the max number of SI2quater messages (see 3GPP TS 44.018) */
-		sysinfo_buf_t buf[_MAX_SYSINFO_TYPE][SI2Q_MAX_NUM];
-	} si;
-	struct {
-		uint8_t flags;
-		/* RSL measurment result number, 0 at lchan_act */
-		uint8_t res_nr;
-		/* current Tx power level of the BTS */
-		uint8_t bts_tx_pwr;
-		/* number of measurements stored in array below */
-		uint8_t num_ul_meas;
-		struct bts_ul_meas uplink[MAX_NUM_UL_MEAS];
-		/* last L1 header from the MS */
-		uint8_t l1_info[2];
-		struct gsm_meas_rep_unidir ul_res;
-	} meas;
-	struct {
-		struct amr_multirate_conf amr_mr;
-		struct {
-			struct osmo_fsm_inst *dl_amr_fsm;
-			/* TCH cache */
-			uint8_t cache[20];
-			/* FACCH cache */
-			uint8_t facch[GSM_MACBLOCK_LEN];
-			uint8_t len;
-			uint32_t fn;
-			bool is_update;
-			/* set for each SID frame to detect talkspurt for codecs
-			   without explicit ONSET event */
-			bool ul_sid;
-			/* indicates if DTXd was active during DL measurement
-			   period */
-			bool dl_active;
-		} dtx;
-		uint8_t last_cmr;
-		uint32_t last_fn;
-	} tch;
-
-	/* 3GPP TS 48.058 § 9.3.37: [0; 255] ok, -1 means invalid*/
-	int16_t ms_t_offs;
-	/* 3GPP TS 45.010 § 1.2 round trip propagation delay (in symbols) or -1 */
-	int16_t p_offs;
-
-	/* BTS-side ciphering state (rx only, bi-directional, ...) */
-	uint8_t ciph_state;
-	uint8_t ciph_ns;
-	uint8_t loopback;
-	struct {
-		uint8_t active;
-		uint8_t ref;
-		/* T3105: PHYS INF retransmission */
-		struct osmo_timer_list t3105;
-		/* counts up to Ny1 */
-		unsigned int phys_info_count;
-	} ho;
-	/* S counter for link loss */
-	int s;
-	/* Kind of the release/activation. E.g. RSL or PCU */
-	int rel_act_kind;
-	/* RTP header Marker bit to indicate beginning of speech after pause  */
-	bool rtp_tx_marker;
-	/* power handling */
-	struct {
-		uint8_t current;
-		uint8_t fixed;
-	} ms_power_ctrl;
-
-	struct msgb *pending_rel_ind_msg;
-#endif
-};
-
-enum {
-	TS_F_PDCH_ACTIVE =		0x1000,
-	TS_F_PDCH_ACT_PENDING =		0x2000,
-	TS_F_PDCH_DEACT_PENDING =	0x4000,
-	TS_F_PDCH_PENDING_MASK =	0x6000 /*<
-			TS_F_PDCH_ACT_PENDING | TS_F_PDCH_DEACT_PENDING */
-} gsm_bts_trx_ts_flags;
-
-/* One Timeslot in a TRX */
-struct gsm_bts_trx_ts {
-	struct gsm_bts_trx *trx;
-	/* number of this timeslot at the TRX */
-	uint8_t nr;
-
-	enum gsm_phys_chan_config pchan;
-
-	struct {
-		enum gsm_phys_chan_config pchan_is;
-		enum gsm_phys_chan_config pchan_want;
-		struct msgb *pending_chan_activ;
-	} dyn;
-
-	unsigned int flags;
-	struct gsm_abis_mo mo;
-	struct tlv_parsed nm_attr;
-	uint8_t nm_chan_comb;
-	int tsc;		/* -1 == use BTS TSC */
-
-	struct {
-		/* Parameters below are configured by VTY */
-		int enabled;
-		uint8_t maio;
-		uint8_t hsn;
-		struct bitvec arfcns;
-		uint8_t arfcns_data[1024/8];
-		/* This is the pre-computed MA for channel assignments */
-		struct bitvec ma;
-		uint8_t ma_len;	/* part of ma_data that is used */
-		uint8_t ma_data[8];	/* 10.5.2.21: max 8 bytes value part */
-	} hopping;
-
-	/* To which E1 subslot are we connected */
-	struct gsm_e1_subslot e1_link;
-
-	union {
-		struct {
-			struct om2k_mo om2k_mo;
-		} rbs2000;
-	};
-
-	struct gsm_lchan lchan[TS_MAX_LCHAN];
-};
-
-/* One TRX in a BTS */
-struct gsm_bts_trx {
-	/* list header in bts->trx_list */
-	struct llist_head list;
-
-	struct gsm_bts *bts;
-	/* number of this TRX in the BTS */
-	uint8_t nr;
-	/* human readable name / description */
-	char *description;
-	/* how do we talk RSL with this TRX? */
-	struct gsm_e1_subslot rsl_e1_link;
-	uint8_t rsl_tei;
-	struct e1inp_sign_link *rsl_link;
-
-	/* Some BTS (specifically Ericsson RBS) have a per-TRX OML Link */
-	struct e1inp_sign_link *oml_link;
-
-	struct gsm_abis_mo mo;
-	struct tlv_parsed nm_attr;
-	struct {
-		struct gsm_abis_mo mo;
-	} bb_transc;
-
-	uint16_t arfcn;
-	int nominal_power;		/* in dBm */
-	unsigned int max_power_red;	/* in actual dB */
-
-#ifndef ROLE_BSC
-	struct trx_power_params power_params;
-	int ms_power_control;
-
-	struct {
-		void *l1h;
-	} role_bts;
-#endif
-
-	union {
-		struct {
-			struct {
-				struct gsm_abis_mo mo;
-			} bbsig;
-			struct {
-				struct gsm_abis_mo mo;
-			} pa;
-		} bs11;
-		struct {
-			unsigned int test_state;
-			uint8_t test_nr;
-			struct rxlev_stats rxlev_stat;
-		} ipaccess;
-		struct {
-			struct {
-				struct om2k_mo om2k_mo;
-			} trxc;
-			struct {
-				struct om2k_mo om2k_mo;
-			} rx;
-			struct {
-				struct om2k_mo om2k_mo;
-			} tx;
-		} rbs2000;
-	};
-	struct gsm_bts_trx_ts ts[TRX_NR_TS];
-};
-
-#define GSM_BTS_SI2Q(bts, i)   (struct gsm48_system_information_type_2quater *)((bts)->si_buf[SYSINFO_TYPE_2quater][i])
-#define GSM_BTS_HAS_SI(bts, i) ((bts)->si_valid & (1 << i))
-#define GSM_BTS_SI(bts, i)     (void *)((bts)->si_buf[i][0])
-#define GSM_LCHAN_SI(lchan, i) (void *)((lchan)->si.buf[i][0])
-
-enum gsm_bts_type {
-	GSM_BTS_TYPE_UNKNOWN,
-	GSM_BTS_TYPE_BS11,
-	GSM_BTS_TYPE_NANOBTS,
-	GSM_BTS_TYPE_RBS2000,
-	GSM_BTS_TYPE_NOKIA_SITE,
-	GSM_BTS_TYPE_OSMOBTS,
-	_NUM_GSM_BTS_TYPE
-};
-
-enum gsm_bts_type_variant {
-	BTS_UNKNOWN,
-	BTS_OSMO_LITECELL15,
-	BTS_OSMO_OCTPHY,
-	BTS_OSMO_SYSMO,
-	BTS_OSMO_TRX,
-	_NUM_BTS_VARIANT
-};
-
-/* Used by OML layer for BTS Attribute reporting */
-enum bts_attribute {
-	BTS_TYPE_VARIANT,
-	BTS_SUB_MODEL,
-	TRX_PHY_VERSION,
-};
-
-struct vty;
-
-struct gsm_bts_model {
-	struct llist_head list;
-
-	enum gsm_bts_type type;
-	enum gsm_bts_type_variant variant;
-	const char *name;
-
-	bool started;
-	int (*start)(struct gsm_network *net);
-	int (*oml_rcvmsg)(struct msgb *msg);
-
-	void (*e1line_bind_ops)(struct e1inp_line *line);
-
-	void (*config_write_bts)(struct vty *vty, struct gsm_bts *bts);
-	void (*config_write_trx)(struct vty *vty, struct gsm_bts_trx *trx);
-	void (*config_write_ts)(struct vty *vty, struct gsm_bts_trx_ts *ts);
-
-	struct tlv_definition nm_att_tlvdef;
-
-	/* features of a given BTS model set via gsm_bts_model_register() locally */
-	struct bitvec features;
-	uint8_t _features_data[MAX_BTS_FEATURES/8];
-};
-
-/* N. B: always add new features to the end of the list (right before _NUM_BTS_FEAT) to avoid breaking compatibility
-   with BTS compiled against earlier version of this header */
-enum gsm_bts_features {
-	BTS_FEAT_HSCSD,
-	BTS_FEAT_GPRS,
-	BTS_FEAT_EGPRS,
-	BTS_FEAT_ECSD,
-	BTS_FEAT_HOPPING,
-	BTS_FEAT_MULTI_TSC,
-	BTS_FEAT_OML_ALERTS,
-	BTS_FEAT_AGCH_PCH_PROP,
-	BTS_FEAT_CBCH,
-	_NUM_BTS_FEAT
-};
-
-extern const struct value_string gsm_bts_features_descs[];
-
-/*
- * This keeps track of the paging status of one BTS. It
- * includes a number of pending requests, a back pointer
- * to the gsm_bts, a timer and some more state.
- */
-struct gsm_bts_paging_state {
-	/* pending requests */
-	struct llist_head pending_requests;
-	struct gsm_bts *bts;
-
-	struct osmo_timer_list work_timer;
-	struct osmo_timer_list credit_timer;
-
-	/* free chans needed */
-	int free_chans_need;
-
-	/* load */
-	uint16_t available_slots;
-};
-
-struct gsm_envabtse {
-	struct gsm_abis_mo mo;
-};
-
-struct gsm_bts_gprs_nsvc {
-	struct gsm_bts *bts;
-	/* data read via VTY config file, to configure the BTS
-	 * via OML from BSC */
-	int id;
-	uint16_t nsvci;
-	uint16_t local_port;	/* on the BTS */
-	uint16_t remote_port;	/* on the SGSN */
-	uint32_t remote_ip;	/* on the SGSN */
-
-	struct gsm_abis_mo mo;
-};
-
-enum gprs_rlc_par {
-	RLC_T3142,
-	RLC_T3169,
-	RLC_T3191,
-	RLC_T3193,
-	RLC_T3195,
-	RLC_N3101,
-	RLC_N3103,
-	RLC_N3105,
-	CV_COUNTDOWN,
-	T_DL_TBF_EXT,	/* ms */
-	T_UL_TBF_EXT,	/* ms */
-	_NUM_RLC_PAR
-};
-
-enum gprs_cs {
-	GPRS_CS1,
-	GPRS_CS2,
-	GPRS_CS3,
-	GPRS_CS4,
-	GPRS_MCS1,
-	GPRS_MCS2,
-	GPRS_MCS3,
-	GPRS_MCS4,
-	GPRS_MCS5,
-	GPRS_MCS6,
-	GPRS_MCS7,
-	GPRS_MCS8,
-	GPRS_MCS9,
-	_NUM_GRPS_CS
-};
-
-struct gprs_rlc_cfg {
-	uint16_t parameter[_NUM_RLC_PAR];
-	struct {
-		uint16_t repeat_time; /* ms */
-		uint8_t repeat_count;
-	} paging;
-	uint32_t cs_mask; /* bitmask of gprs_cs */
-	uint8_t initial_cs;
-	uint8_t initial_mcs;
-};
-
-
-enum neigh_list_manual_mode {
-	NL_MODE_AUTOMATIC = 0,
-	NL_MODE_MANUAL = 1,
-	NL_MODE_MANUAL_SI5SEP = 2, /* SI2 and SI5 have separate neighbor lists */
-};
-
-enum bts_loc_fix {
-	BTS_LOC_FIX_INVALID = 0,
-	BTS_LOC_FIX_2D = 1,
-	BTS_LOC_FIX_3D = 2,
-};
-
-extern const struct value_string bts_loc_fix_names[];
-
-struct bts_location {
-	struct llist_head list;
-	time_t tstamp;
-	enum bts_loc_fix valid;
-	double lat;
-	double lon;
-	double height;
-};
-
-/* One BTS */
-struct gsm_bts {
-	/* list header in net->bts_list */
-	struct llist_head list;
-
-	/* Geographical location of the BTS */
-	struct llist_head loc_list;
-
-	/* number of ths BTS in network */
-	uint8_t nr;
-	/* human readable name / description */
-	char *description;
-	/* Cell Identity */
-	uint16_t cell_identity;
-	/* location area code of this BTS */
-	uint16_t location_area_code;
-	/* Base Station Identification Code (BSIC), lower 3 bits is BCC,
-	 * which is used as TSC for the CCCH */
-	uint8_t bsic;
-	/* type of BTS */
-	enum gsm_bts_type type;
-	enum gsm_bts_type_variant variant;
-	struct gsm_bts_model *model;
-	enum gsm_band band;
-	char version[MAX_VERSION_LENGTH];
-	char sub_model[MAX_VERSION_LENGTH];
-
-	/* features of a given BTS set/reported via OML */
-	struct bitvec features;
-	uint8_t _features_data[MAX_BTS_FEATURES/8];
-
-	/* Connected PCU version (if any) */
-	char pcu_version[MAX_VERSION_LENGTH];
-
-	/* maximum Tx power that the MS is permitted to use in this cell */
-	int ms_max_power;
-
-	/* how do we talk OML with this TRX? */
-	struct gsm_e1_subslot oml_e1_link;
-	uint8_t oml_tei;
-	struct e1inp_sign_link *oml_link;
-
-	/* Abis network management O&M handle */
-	struct abis_nm_h *nmh;
-
-	struct gsm_abis_mo mo;
-
-	/* number of this BTS on given E1 link */
-	uint8_t bts_nr;
-
-	/* DTX features of this BTS */
-	enum gsm48_dtx_mode dtxu;
-	bool dtxd;
-
-	/* paging state and control */
-	struct gsm_bts_paging_state paging;
-
-	/* CCCH is on C0 */
-	struct gsm_bts_trx *c0;
-
-	struct {
-		struct gsm_abis_mo mo;
-	} site_mgr;
-
-	/* bitmask of all SI that are present/valid in si_buf */
-	uint32_t si_valid;
-	/* 3GPP TS 44.018 Table 10.5.2.33b.1 INDEX and COUNT for SI2quater */
-	uint8_t si2q_index; /* distinguish individual SI2quater messages */
-	uint8_t si2q_count; /* si2q_index for the last (highest indexed) individual SI2quater message */
-	/* buffers where we put the pre-computed SI */
-	sysinfo_buf_t si_buf[_MAX_SYSINFO_TYPE][SI2Q_MAX_NUM];
-	/* offsets used while generating SI2quater */
-	size_t e_offset;
-	size_t u_offset;
-
-	/* ip.accesss Unit ID's have Site/BTS/TRX layout */
-	union {
-		struct {
-			uint16_t site_id;
-			uint16_t bts_id;
-			uint32_t flags;
-			uint32_t rsl_ip;
-		} ip_access;
-		struct {
-			struct {
-				struct gsm_abis_mo mo;
-			} cclk;
-			struct {
-				struct gsm_abis_mo mo;
-			} rack;
-			struct gsm_envabtse envabtse[4];
-		} bs11;
-		struct {
-			struct {
-				struct om2k_mo om2k_mo;
-				struct gsm_abis_mo mo;
-				struct llist_head conn_groups;
-			} cf;
-			struct {
-				struct om2k_mo om2k_mo;
-				struct gsm_abis_mo mo;
-				struct llist_head conn_groups;
-			} is;
-			struct {
-				struct om2k_mo om2k_mo;
-				struct gsm_abis_mo mo;
-				struct llist_head conn_groups;
-			} con;
-			struct {
-				struct om2k_mo om2k_mo;
-				struct gsm_abis_mo mo;
-			} dp;
-			struct {
-				struct om2k_mo om2k_mo;
-				struct gsm_abis_mo mo;
-			} tf;
-			uint32_t use_superchannel:1;
-		} rbs2000;
-		struct {
-			uint8_t bts_type;
-			unsigned int configured:1,
-				skip_reset:1,
-				no_loc_rel_cnf:1,
-				bts_reset_timer_cnf,
-				did_reset:1,
-				wait_reset:1;
-			struct osmo_timer_list reset_timer;
-		} nokia;
-	};
-
-	/* Not entirely sure how ip.access specific this is */
-	struct {
-		uint8_t supports_egprs_11bit_rach;
-		enum bts_gprs_mode mode;
-		struct {
-			struct gsm_abis_mo mo;
-			uint16_t nsei;
-			uint8_t timer[7];
-		} nse;
-		struct {
-			struct gsm_abis_mo mo;
-			uint16_t bvci;
-			uint8_t timer[11];
-			struct gprs_rlc_cfg rlc_cfg;
-		} cell;
-		struct gsm_bts_gprs_nsvc nsvc[2];
-		uint8_t rac;
-		uint8_t net_ctrl_ord;
-		bool ctrl_ack_type_use_block;
-	} gprs;
-
-	/* RACH NM values */
-	int rach_b_thresh;
-	int rach_ldavg_slots;
-
-	/* transceivers */
-	int num_trx;
-	struct llist_head trx_list;
-
-	/* SI related items */
-	int force_combined_si;
-	int bcch_change_mark;
-
-#ifdef ROLE_BSC
-	/* Abis NM queue */
-	struct llist_head abis_queue;
-	int abis_nm_pend;
-
-	struct gsm_network *network;
-
-	/* should the channel allocator allocate channels from high TRX to TRX0,
-	 * rather than starting from TRX0 and go upwards? */
-	int chan_alloc_reverse;
-
-	enum neigh_list_manual_mode neigh_list_manual_mode;
-	/* parameters from which we build SYSTEM INFORMATION */
-	struct {
-		struct gsm48_rach_control rach_control;
-		uint8_t ncc_permitted;
-		struct gsm48_cell_sel_par cell_sel_par;
-		struct gsm48_si_selection_params cell_ro_sel_par; /* rest octet */
-		struct gsm48_cell_options cell_options;
-		struct gsm48_control_channel_descr chan_desc;
-		struct bitvec neigh_list;
-		struct bitvec cell_alloc;
-		struct bitvec si5_neigh_list;
-		struct osmo_earfcn_si2q si2quater_neigh_list;
-		size_t uarfcn_length; /* index for uarfcn and scramble lists */
-		struct {
-			/* bitmask large enough for all possible ARFCN's */
-			uint8_t neigh_list[1024/8];
-			uint8_t cell_alloc[1024/8];
-			/* If the user wants a different neighbor list in SI5 than in SI2 */
-			uint8_t si5_neigh_list[1024/8];
-			uint8_t meas_bw_list[MAX_EARFCN_LIST];
-			uint16_t earfcn_list[MAX_EARFCN_LIST];
-			uint16_t uarfcn_list[MAX_EARFCN_LIST];
-			uint16_t scramble_list[MAX_EARFCN_LIST];
-		} data;
-	} si_common;
-	bool early_classmark_allowed;
-	/* for testing only: Have an infinitely long radio link timeout */
-	bool infinite_radio_link_timeout;
-
-	/* do we use static (user-defined) system information messages? (bitmask) */
-	uint32_t si_mode_static;
-
-	/* exclude the BTS from the global RF Lock handling */
-	int excl_from_rf_lock;
-
-	/* supported codecs beside FR */
-	struct bts_codec_conf codec;
-
-	/* BTS dependencies bit field */
-	uint32_t depends_on[256/(8*4)];
-
-	/* full and half rate multirate config */
-	struct amr_multirate_conf mr_full;
-	struct amr_multirate_conf mr_half;
-
-	/* PCU socket state */
-	char *pcu_sock_path;
-	struct pcu_sock_state *pcu_state;
-
-#endif /* ROLE_BSC */
-	void *role;
-};
-
-
-struct gsm_bts *gsm_bts_alloc(void *talloc_ctx, uint8_t bts_num);
-struct gsm_bts *gsm_bts_num(struct gsm_network *net, int num);
-
-struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts);
-struct gsm_bts_trx *gsm_bts_trx_num(const struct gsm_bts *bts, int num);
-
-enum gsm_bts_type str2btstype(const char *arg);
-const char *btstype2str(enum gsm_bts_type type);
-
-enum bts_attribute str2btsattr(const char *s);
-const char *btsatttr2str(enum bts_attribute v);
-
-enum gsm_bts_type_variant str2btsvariant(const char *arg);
-const char *btsvariant2str(enum gsm_bts_type_variant v);
-
-extern const struct value_string gsm_chreq_descs[];
-const struct value_string gsm_pchant_names[13];
-const struct value_string gsm_pchant_descs[13];
-const char *gsm_pchan_name(enum gsm_phys_chan_config c);
-enum gsm_phys_chan_config gsm_pchan_parse(const char *name);
-const char *gsm_lchant_name(enum gsm_chan_t c);
-const char *gsm_chreq_name(enum gsm_chreq_reason_t c);
-char *gsm_trx_name(const struct gsm_bts_trx *trx);
-char *gsm_ts_name(const struct gsm_bts_trx_ts *ts);
-char *gsm_ts_and_pchan_name(const struct gsm_bts_trx_ts *ts);
-char *gsm_lchan_name_compute(const struct gsm_lchan *lchan);
-const char *gsm_lchans_name(enum gsm_lchan_state s);
-
-static inline char *gsm_lchan_name(const struct gsm_lchan *lchan)
-{
-	return lchan->name;
-}
-
-static inline int gsm_bts_set_feature(struct gsm_bts *bts, enum gsm_bts_features feat)
-{
-	OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES);
-	return bitvec_set_bit_pos(&bts->features, feat, 1);
-}
-
-static inline bool gsm_bts_has_feature(const struct gsm_bts *bts, enum gsm_bts_features feat)
-{
-	OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES);
-	return bitvec_get_bit_pos(&bts->features, feat);
-}
-
-void gsm_abis_mo_reset(struct gsm_abis_mo *mo);
-
-struct gsm_abis_mo *
-gsm_objclass2mo(struct gsm_bts *bts, uint8_t obj_class,
-	    const struct abis_om_obj_inst *obj_inst);
-
-struct gsm_nm_state *
-gsm_objclass2nmstate(struct gsm_bts *bts, uint8_t obj_class,
-		 const struct abis_om_obj_inst *obj_inst);
-void *
-gsm_objclass2obj(struct gsm_bts *bts, uint8_t obj_class,
-	     const struct abis_om_obj_inst *obj_inst);
-
-/* reset the state of all MO in the BTS */
-void gsm_bts_mo_reset(struct gsm_bts *bts);
-
-uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan,
-			  uint8_t ts_nr, uint8_t lchan_nr);
-uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan);
-uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan,
-				   enum gsm_phys_chan_config as_pchan);
-
-/* return the gsm_lchan for the CBCH (if it exists at all) */
-struct gsm_lchan *gsm_bts_get_cbch(struct gsm_bts *bts);
-
-/*
- * help with parsing regexps
- */
-int gsm_parse_reg(void *ctx, regex_t *reg, char **str,
-		int argc, const char **argv) __attribute__ ((warn_unused_result));
-
-static inline uint8_t gsm_ts_tsc(const struct gsm_bts_trx_ts *ts)
-{
-	if (ts->tsc != -1)
-		return ts->tsc;
-	else
-		return ts->trx->bts->bsic & 7;
-}
-
-struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,
-				   int *rc);
-
-enum gsm_phys_chan_config ts_pchan(struct gsm_bts_trx_ts *ts);
-uint8_t ts_subslots(struct gsm_bts_trx_ts *ts);
-bool ts_is_tch(struct gsm_bts_trx_ts *ts);
-
-#endif
diff --git a/include/openbsc/gsm_subscriber.h b/include/openbsc/gsm_subscriber.h
deleted file mode 100644
index d88e32a..0000000
--- a/include/openbsc/gsm_subscriber.h
+++ /dev/null
@@ -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 */
diff --git a/include/openbsc/gsup_client.h b/include/openbsc/gsup_client.h
deleted file mode 100644
index 4a25490..0000000
--- a/include/openbsc/gsup_client.h
+++ /dev/null
@@ -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);
-
diff --git a/include/openbsc/gtphub.h b/include/openbsc/gtphub.h
deleted file mode 100644
index 9cb7605..0000000
--- a/include/openbsc/gtphub.h
+++ /dev/null
@@ -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);
diff --git a/include/openbsc/handover.h b/include/openbsc/handover.h
deleted file mode 100644
index 3fe71a2..0000000
--- a/include/openbsc/handover.h
+++ /dev/null
@@ -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 */
diff --git a/include/openbsc/handover_decision.h b/include/openbsc/handover_decision.h
deleted file mode 100644
index 81078b0..0000000
--- a/include/openbsc/handover_decision.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _HANDOVER_DECISION_H
-#define _HANDOVER_DECISION_H
-
-void on_dso_load_ho_dec(void);
-
-#endif /* _HANDOVER_DECISION_H */
-
diff --git a/include/openbsc/ipaccess.h b/include/openbsc/ipaccess.h
deleted file mode 100644
index 82e89c2..0000000
--- a/include/openbsc/ipaccess.h
+++ /dev/null
@@ -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 */
diff --git a/include/openbsc/iucs.h b/include/openbsc/iucs.h
deleted file mode 100644
index b7d6064..0000000
--- a/include/openbsc/iucs.h
+++ /dev/null
@@ -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);
diff --git a/include/openbsc/iucs_ranap.h b/include/openbsc/iucs_ranap.h
deleted file mode 100644
index c2ff5f9..0000000
--- a/include/openbsc/iucs_ranap.h
+++ /dev/null
@@ -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);
diff --git a/include/openbsc/meas_feed.h b/include/openbsc/meas_feed.h
deleted file mode 100644
index f77ee07..0000000
--- a/include/openbsc/meas_feed.h
+++ /dev/null
@@ -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
diff --git a/include/openbsc/meas_rep.h b/include/openbsc/meas_rep.h
deleted file mode 100644
index b0c03f0..0000000
--- a/include/openbsc/meas_rep.h
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef _MEAS_REP_H
-#define _MEAS_REP_H
-
-#include <stdint.h>
-
-#include <osmocom/gsm/meas_rep.h>
-
-#define MRC_F_PROCESSED	0x0001
-
-/* extracted from a L3 measurement report IE */
-struct gsm_meas_rep_cell {
-	uint8_t rxlev;
-	uint8_t bsic;
-	uint8_t neigh_idx;
-	uint16_t arfcn;
-	unsigned int flags;
-};
-
-#define MEAS_REP_F_UL_DTX	0x01
-#define MEAS_REP_F_DL_VALID	0x02
-#define MEAS_REP_F_BA1		0x04
-#define MEAS_REP_F_DL_DTX	0x08
-#define MEAS_REP_F_MS_TO	0x10
-#define MEAS_REP_F_MS_L1	0x20
-#define MEAS_REP_F_FPC		0x40
-
-/* parsed uplink and downlink measurement result */
-struct gsm_meas_rep {
-	/* back-pointer to the logical channel */
-	struct gsm_lchan *lchan;
-
-	/* number of the measurement report */
-	uint8_t nr;
-	/* flags, see MEAS_REP_F_* */
-	unsigned int flags;
-
-	/* uplink and downlink rxlev, rxqual; full and sub */
-	struct gsm_meas_rep_unidir ul;
-	struct gsm_meas_rep_unidir dl;
-
-	uint8_t bs_power;
-	/* according to 3GPP TS 48.058 § MS Timing Offset [-63; 192] */
-	int16_t ms_timing_offset;
-	struct {
-		int8_t pwr;	/* MS power in dBm */
-		uint8_t ta;	/* MS timing advance */
-	} ms_l1;
-
-	/* neighbor measurement reports for up to 6 cells */
-	int num_cell;
-	struct gsm_meas_rep_cell cell[6];
-};
-
-/* obtain an average over the last 'num' fields in the meas reps */
-int get_meas_rep_avg(const struct gsm_lchan *lchan,
-		     enum meas_rep_field field, unsigned int num);
-
-/* Check if N out of M last values for FIELD are >= bd */
-int meas_rep_n_out_of_m_be(const struct gsm_lchan *lchan,
-			enum meas_rep_field field,
-			unsigned int n, unsigned int m, int be);
-
-unsigned int calc_initial_idx(unsigned int array_size,
-			      unsigned int meas_rep_idx,
-			      unsigned int num_values);
-
-#endif /* _MEAS_REP_H */
diff --git a/include/openbsc/mgcp.h b/include/openbsc/mgcp.h
deleted file mode 100644
index 7cf83b2..0000000
--- a/include/openbsc/mgcp.h
+++ /dev/null
@@ -1,300 +0,0 @@
-/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
-
-/*
- * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-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 OPENBSC_MGCP_H
-#define OPENBSC_MGCP_H
-
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/write_queue.h>
-#include <osmocom/core/timer.h>
-
-#include "debug.h"
-
-#include <arpa/inet.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#define RTP_PORT_DEFAULT 4000
-#define RTP_PORT_NET_DEFAULT 16000
-
-/**
- * Calculate the RTP audio port for the given multiplex
- * and the direction. This allows a semi static endpoint
- * to port calculation removing the need for the BSC
- * and the MediaGateway to communicate.
- *
- * Port usage explained:
- *       base + (multiplex * 2) + 0 == local port to wait for network packets
- *       base + (multiplex * 2) + 1 == local port for rtcp
- *
- * The above port will receive packets from the BTS that need
- * to be patched and forwarded to the network.
- * The above port will receive packets from the network that
- * need to be patched and forwarded to the BTS.
- *
- * We assume to have a static BTS IP address so we can differentiate
- * network and BTS.
- *
- */
-static inline int rtp_calculate_port(int multiplex, int base)
-{
-	return base + (multiplex * 2);
-}
-
-
-/*
- * Handling of MGCP Endpoints and the MGCP Config
- */
-struct mgcp_endpoint;
-struct mgcp_config;
-struct mgcp_trunk_config;
-struct mgcp_rtp_end;
-
-#define MGCP_ENDP_CRCX 1
-#define MGCP_ENDP_DLCX 2
-#define MGCP_ENDP_MDCX 3
-
-/*
- * what to do with the msg?
- *	- continue as usual?
- *	- reject and send a failure code?
- *	- defer? do not send anything
- */
-#define MGCP_POLICY_CONT	4
-#define MGCP_POLICY_REJECT	5
-#define MGCP_POLICY_DEFER	6
-
-typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint);
-typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state);
-typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id);
-typedef int (*mgcp_reset)(struct mgcp_trunk_config *cfg);
-typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone);
-
-/**
- * Return:
- *   <  0 in case no audio was processed
- *   >= 0 in case audio was processed. The remaining payload
- *   length will be returned.
- */
-typedef int (*mgcp_processing)(struct mgcp_endpoint *endp,
-			       struct mgcp_rtp_end *dst_end,
-			       char *data, int *len, int buf_size);
-typedef int (*mgcp_processing_setup)(struct mgcp_endpoint *endp,
-				     struct mgcp_rtp_end *dst_end,
-				     struct mgcp_rtp_end *src_end);
-
-typedef void (*mgcp_get_format)(struct mgcp_endpoint *endp,
-				int *payload_type,
-				const char**subtype_name,
-				const char**fmtp_extra);
-
-#define PORT_ALLOC_STATIC	0
-#define PORT_ALLOC_DYNAMIC	1
-
-/**
- * This holds information on how to allocate ports
- */
-struct mgcp_port_range {
-	int mode;
-
-	/* addr or NULL to fall-back to default */
-	char *bind_addr;
-
-	/* pre-allocated from a base? */
-	int base_port;
-
-	/* dynamically allocated */
-	int range_start;
-	int range_end;
-	int last_port;
-};
-
-#define MGCP_KEEPALIVE_ONCE (-1)
-
-struct mgcp_trunk_config {
-	struct llist_head entry;
-
-	struct mgcp_config *cfg;
-
-	int trunk_nr;
-	int trunk_type;
-
-	char *audio_fmtp_extra;
-	char *audio_name;
-	int audio_payload;
-	int audio_send_ptime;
-	int audio_send_name;
-	int audio_loop;
-
-	int no_audio_transcoding;
-
-	int omit_rtcp;
-	int keepalive_interval;
-
-	/* RTP patching */
-	int force_constant_ssrc; /* 0: don't, 1: once */
-	int force_aligned_timing;
-
-	/* spec handling */
-	int force_realloc;
-
-	/* timer */
-	struct osmo_timer_list keepalive_timer;
-
-	unsigned int number_endpoints;
-	struct mgcp_endpoint *endpoints;
-};
-
-enum mgcp_role {
-	MGCP_BSC = 0,
-	MGCP_BSC_NAT,
-};
-
-enum mgcp_connection_mode {
-	MGCP_CONN_NONE = 0,
-	MGCP_CONN_RECV_ONLY = 1,
-	MGCP_CONN_SEND_ONLY = 2,
-	MGCP_CONN_RECV_SEND = MGCP_CONN_RECV_ONLY | MGCP_CONN_SEND_ONLY,
-	MGCP_CONN_LOOPBACK  = 4 | MGCP_CONN_RECV_SEND,
-};
-
-extern const struct value_string mgcp_connection_mode_strs[];
-
-static inline const char *mgcp_cmode_name(enum mgcp_connection_mode mode)
-{
-	return get_value_string(mgcp_connection_mode_strs, mode);
-}
-
-struct mgcp_config {
-	int source_port;
-	char *local_ip;
-	char *source_addr;
-	char *bts_ip;
-	char *call_agent_addr;
-
-	struct in_addr bts_in;
-
-	/* transcoder handling */
-	char *transcoder_ip;
-	struct in_addr transcoder_in;
-	int transcoder_remote_base;
-
-	/* RTP processing */
-	mgcp_processing rtp_processing_cb;
-	mgcp_processing_setup setup_rtp_processing_cb;
-
-	mgcp_get_format get_net_downlink_format_cb;
-
-	struct osmo_wqueue gw_fd;
-
-	struct mgcp_port_range bts_ports;
-	struct mgcp_port_range net_ports;
-	struct mgcp_port_range transcoder_ports;
-	int endp_dscp;
-
-	int bts_force_ptime;
-
-	mgcp_change change_cb;
-	mgcp_policy policy_cb;
-	mgcp_reset reset_cb;
-	mgcp_realloc realloc_cb;
-	mgcp_rqnt rqnt_cb;
-	void *data;
-
-	uint32_t last_call_id;
-
-	/* trunk handling */
-	struct mgcp_trunk_config trunk;
-	struct llist_head trunks;
-
-	/* only used for start with a static configuration */
-	int last_net_port;
-	int last_bts_port;
-
-	enum mgcp_role role;
-
-	/* osmux translator: 0 means disabled, 1 means enabled */
-	int osmux;
-	/* addr to bind the server to */
-	char *osmux_addr;
-	/* The BSC-NAT may ask for enabling osmux on demand. This tells us if
-	 * the osmux socket is already initialized.
-	 */
-	int osmux_init;
-	/* osmux batch factor: from 1 to 4 maximum */
-	int osmux_batch;
-	/* osmux batch size (in bytes) */
-	int osmux_batch_size;
-	/* osmux port */
-	uint16_t osmux_port;
-	/* Pad circuit with dummy messages until we see the first voice
-	 * message.
-	 */
-	uint16_t osmux_dummy;
-};
-
-/* config management */
-struct mgcp_config *mgcp_config_alloc(void);
-int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
-		      enum mgcp_role role);
-int mgcp_vty_init(void);
-int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg);
-void mgcp_release_endp(struct mgcp_endpoint *endp);
-void mgcp_initialize_endp(struct mgcp_endpoint *endp);
-int mgcp_reset_transcoder(struct mgcp_config *cfg);
-void mgcp_format_stats(struct mgcp_endpoint *endp, char *stats, size_t size);
-int mgcp_parse_stats(struct msgb *msg, uint32_t *ps, uint32_t *os, uint32_t *pr, uint32_t *_or, int *loss, uint32_t *jitter);
-
-void mgcp_trunk_set_keepalive(struct mgcp_trunk_config *tcfg, int interval);
-
-/*
- * format helper functions
- */
-struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
-
-/* adc helper */
-static inline int mgcp_timeslot_to_endpoint(int multiplex, int timeslot)
-{
-	if (timeslot == 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Timeslot should not be 0\n");
-		timeslot = 255;
-	}
-
-	return timeslot + (32 * multiplex);
-}
-
-static inline void mgcp_endpoint_to_timeslot(int endpoint, int *multiplex, int *timeslot)
-{
-	*multiplex = endpoint / 32;
-	*timeslot = endpoint % 32;
-}
-
-int mgcp_send_reset_ep(struct mgcp_endpoint *endp, int endpoint);
-int mgcp_send_reset_all(struct mgcp_config *cfg);
-
-
-int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port);
-int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp, struct sockaddr_in *addr, char *buf, int rc);
-int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len);
-
-#endif
diff --git a/include/openbsc/mgcp_internal.h b/include/openbsc/mgcp_internal.h
deleted file mode 100644
index b2c2408..0000000
--- a/include/openbsc/mgcp_internal.h
+++ /dev/null
@@ -1,337 +0,0 @@
-/* MGCP Private Data */
-
-/*
- * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-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/>.
- *
- */
-
-#pragma once
-
-#include <string.h>
-
-#include <osmocom/core/select.h>
-
-#define CI_UNUSED 0
-
-enum mgcp_trunk_type {
-	MGCP_TRUNK_VIRTUAL,
-	MGCP_TRUNK_E1,
-};
-
-struct mgcp_rtp_stream_state {
-	uint32_t ssrc;
-	uint16_t last_seq;
-	uint32_t last_timestamp;
-	uint32_t err_ts_counter;
-	int32_t last_tsdelta;
-	uint32_t last_arrival_time;
-};
-
-struct mgcp_rtp_state {
-	int initialized;
-	int patch_ssrc;
-
-	uint32_t orig_ssrc;
-
-	int seq_offset;
-
-	int32_t  timestamp_offset;
-	uint32_t packet_duration;
-
-	struct mgcp_rtp_stream_state in_stream;
-	struct mgcp_rtp_stream_state out_stream;
-
-	/* jitter and packet loss calculation */
-	int stats_initialized;
-	uint16_t stats_base_seq;
-	uint16_t stats_max_seq;
-	uint32_t stats_ssrc;
-	uint32_t stats_jitter;
-	int32_t stats_transit;
-	int stats_cycles;
-	bool patched_first_rtp_payload; /* FIXME: drop this, see OS#2459 */
-};
-
-struct mgcp_rtp_codec {
-	uint32_t rate;
-	int channels;
-	uint32_t frame_duration_num;
-	uint32_t frame_duration_den;
-
-	int payload_type;
-	char *audio_name;
-	char *subtype_name;
-};
-
-struct mgcp_rtp_end {
-	/* statistics */
-	unsigned int packets;
-	unsigned int octets;
-	unsigned int dropped_packets;
-	struct in_addr addr;
-
-	/* in network byte order */
-	int rtp_port, rtcp_port;
-
-	/* audio codec information */
-	struct mgcp_rtp_codec codec;
-	struct mgcp_rtp_codec alt_codec; /* TODO/XXX: make it generic */
-
-	/* per endpoint data */
-	int  frames_per_packet;
-	uint32_t packet_duration_ms;
-	char *fmtp_extra;
-	int output_enabled;
-	int force_output_ptime;
-
-	/* RTP patching */
-	int force_constant_ssrc; /* -1: always, 0: don't, 1: once */
-	int force_aligned_timing;
-	void *rtp_process_data;
-
-	/*
-	 * Each end has a socket...
-	 */
-	struct osmo_fd rtp;
-	struct osmo_fd rtcp;
-
-	int local_port;
-	int local_alloc;
-};
-
-enum {
-	MGCP_TAP_BTS_IN,
-	MGCP_TAP_BTS_OUT,
-	MGCP_TAP_NET_IN,
-	MGCP_TAP_NET_OUT,
-
-	/* last element */
-	MGCP_TAP_COUNT
-};
-
-struct mgcp_rtp_tap {
-	int enabled;
-	struct sockaddr_in forward;
-};
-
-struct mgcp_lco {
-	char *string;
-	char *codec;
-	int pkt_period_min; /* time in ms */
-	int pkt_period_max; /* time in ms */
-};
-
-enum mgcp_type {
-	MGCP_RTP_DEFAULT	= 0,
-	MGCP_RTP_TRANSCODED,
-	MGCP_OSMUX_BSC,
-	MGCP_OSMUX_BSC_NAT,
-};
-
-#include <openbsc/osmux.h>
-
-struct mgcp_endpoint {
-	int allocated;
-	uint32_t ci;
-	char *callid;
-	struct mgcp_lco local_options;
-	int conn_mode;
-	int orig_mode;
-
-	/* backpointer */
-	struct mgcp_config *cfg;
-	struct mgcp_trunk_config *tcfg;
-
-	/* port status for bts/net */
-	struct mgcp_rtp_end bts_end;
-	struct mgcp_rtp_end net_end;
-
-	/*
-	 * For transcoding we will send from the local_port
-	 * of trans_bts and it will arrive at trans_net from
-	 * where we will forward it to the network.
-	 */
-	struct mgcp_rtp_end trans_bts;
-	struct mgcp_rtp_end trans_net;
-	enum mgcp_type type;
-
-	/* sequence bits */
-	struct mgcp_rtp_state net_state;
-	struct mgcp_rtp_state bts_state;
-
-	/* fields for re-transmission */
-	char *last_trans;
-	char *last_response;
-
-	/* tap for the endpoint */
-	struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
-
-	struct {
-		/* Osmux state: disabled, activating, active */
-		enum osmux_state state;
-		/* Allocated Osmux circuit ID for this endpoint */
-		int allocated_cid;
-		/* Used Osmux circuit ID for this endpoint */
-		uint8_t cid;
-		/* handle to batch messages */
-		struct osmux_in_handle *in;
-		/* handle to unbatch messages */
-		struct osmux_out_handle out;
-		/* statistics */
-		struct {
-			uint32_t chunks;
-			uint32_t octets;
-		} stats;
-	} osmux;
-};
-
-#define for_each_line(line, save)			\
-	for (line = strline_r(NULL, &save); line;\
-	     line = strline_r(NULL, &save))
-
-static inline char *strline_r(char *str, char **saveptr)
-{
-	char *result;
-
-	if (str)
-		*saveptr = str;
-
-	result = *saveptr;
-
-	if (*saveptr != NULL) {
-		*saveptr = strpbrk(*saveptr, "\r\n");
-
-		if (*saveptr != NULL) {
-			char *eos = *saveptr;
-
-			if ((*saveptr)[0] == '\r' && (*saveptr)[1] == '\n')
-				(*saveptr)++;
-			(*saveptr)++;
-			if ((*saveptr)[0] == '\0')
-				*saveptr = NULL;
-
-			*eos = '\0';
-		}
-	}
-
-	return result;
-}
-
-
-
-#define ENDPOINT_NUMBER(endp) abs((int)(endp - endp->tcfg->endpoints))
-
-/**
- * Internal structure while parsing a request
- */
-struct mgcp_parse_data {
-	struct mgcp_config *cfg;
-	struct mgcp_endpoint *endp;
-	char *trans;
-	char *save;
-	int found;
-};
-
-int mgcp_send_dummy(struct mgcp_endpoint *endp);
-int mgcp_bind_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
-int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
-int mgcp_bind_trans_bts_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
-int mgcp_bind_trans_net_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
-int mgcp_free_rtp_port(struct mgcp_rtp_end *end);
-
-/* For transcoding we need to manage an in and an output that are connected */
-static inline int endp_back_channel(int endpoint)
-{
-	return endpoint + 60;
-}
-
-struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index);
-struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
-
-void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
-			 struct mgcp_rtp_end *rtp);
-uint32_t mgcp_rtp_packet_duration(struct mgcp_endpoint *endp,
-				  struct mgcp_rtp_end *rtp);
-
-void mgcp_state_calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *,
-			uint32_t *expected, int *loss);
-uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *);
-
-/* payload processing default functions */
-int mgcp_rtp_processing_default(struct mgcp_endpoint *endp, struct mgcp_rtp_end *dst_end,
-				char *data, int *len, int buf_size);
-
-int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
-				      struct mgcp_rtp_end *dst_end,
-				      struct mgcp_rtp_end *src_end);
-
-void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
-					  int *payload_type,
-					  const char**subtype_name,
-					  const char**fmtp_extra);
-
-/* internal RTP Annex A counting */
-void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
-			const uint16_t seq, const int32_t transit,
-			const uint32_t ssrc);
-
-int mgcp_set_ip_tos(int fd, int tos);
-
-enum {
-	MGCP_DEST_NET = 0,
-	MGCP_DEST_BTS,
-};
-
-
-#define MGCP_DUMMY_LOAD 0x23
-
-
-/**
- * SDP related information
- */
-/* Assume audio frame length of 20ms */
-#define DEFAULT_RTP_AUDIO_FRAME_DUR_NUM 20
-#define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000
-#define DEFAULT_RTP_AUDIO_PACKET_DURATION_MS 20
-#define DEFAULT_RTP_AUDIO_DEFAULT_RATE  8000
-#define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1
-
-#define PTYPE_UNDEFINED (-1)
-int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p);
-int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
-			int payload_type, const char *audio_name);
-
-
-/**
- * Internal network related
- */
-static inline const char *mgcp_net_src_addr(struct mgcp_endpoint *endp)
-{
-	if (endp->cfg->net_ports.bind_addr)
-		return endp->cfg->net_ports.bind_addr;
-	return endp->cfg->source_addr;
-}
-
-static inline const char *mgcp_bts_src_addr(struct mgcp_endpoint *endp)
-{
-	if (endp->cfg->bts_ports.bind_addr)
-		return endp->cfg->bts_ports.bind_addr;
-	return endp->cfg->source_addr;
-}
-
-int mgcp_msg_terminate_nul(struct msgb *msg);
diff --git a/include/openbsc/mgcpgw_client.h b/include/openbsc/mgcpgw_client.h
deleted file mode 100644
index b1b5fd4..0000000
--- a/include/openbsc/mgcpgw_client.h
+++ /dev/null
@@ -1,111 +0,0 @@
-#pragma once
-
-#include <stdint.h>
-
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/write_queue.h>
-
-enum mgcp_connection_mode;
-
-struct msgb;
-struct vty;
-
-#define MGCPGW_CLIENT_LOCAL_ADDR_DEFAULT "0.0.0.0"
-#define MGCPGW_CLIENT_LOCAL_PORT_DEFAULT 0
-#define MGCPGW_CLIENT_REMOTE_ADDR_DEFAULT "127.0.0.1"
-#define MGCPGW_CLIENT_REMOTE_PORT_DEFAULT 2427
-
-#define MSGB_CB_MGCP_TRANS_ID 0
-
-typedef unsigned int mgcp_trans_id_t;
-
-struct mgcpgw_client_conf {
-	const char *local_addr;
-	int local_port;
-	const char *remote_addr;
-	int remote_port;
-	uint16_t first_endpoint;
-	uint16_t last_endpoint;
-	uint16_t bts_base;
-};
-
-struct mgcp_response_head {
-       int response_code;
-       mgcp_trans_id_t trans_id;
-       const char *comment;
-};
-
-struct mgcp_response {
-	char *body;
-	struct mgcp_response_head head;
-	uint16_t audio_port;
-};
-
-struct mgcpgw_client {
-	struct mgcpgw_client_conf actual;
-	uint32_t remote_addr;
-	struct osmo_wqueue wq;
-	mgcp_trans_id_t next_trans_id;
-	struct llist_head responses_pending;
-	struct llist_head inuse_endpoints;
-};
-
-struct mgcp_inuse_endpoint {
-	struct llist_head entry;
-	uint16_t id;
-};
-
-/* Invoked when an MGCP response is received or sending failed.  When the
- * response is passed as NULL, this indicates failure during transmission. */
-typedef void (* mgcp_response_cb_t )(struct mgcp_response *response, void *priv);
-
-struct mgcp_response_pending {
-	struct llist_head entry;
-
-	mgcp_trans_id_t trans_id;
-	mgcp_response_cb_t response_cb;
-	void *priv;
-};
-
-
-void mgcpgw_client_conf_init(struct mgcpgw_client_conf *conf);
-
-struct mgcpgw_client *mgcpgw_client_init(void *ctx,
-					 struct mgcpgw_client_conf *conf);
-int mgcpgw_client_connect(struct mgcpgw_client *mgcp);
-
-const char *mgcpgw_client_remote_addr_str(struct mgcpgw_client *mgcp);
-uint16_t mgcpgw_client_remote_port(struct mgcpgw_client *mgcp);
-uint32_t mgcpgw_client_remote_addr_n(struct mgcpgw_client *mgcp);
-
-/* Find and seize an unsused endpoint id */
-int mgcpgw_client_next_endpoint(struct mgcpgw_client *client);
-
-/* Release a seized endpoint id to make it available again for other calls */
-void mgcpgw_client_release_endpoint(uint16_t id, struct mgcpgw_client *client);
-
-int mgcp_response_parse_params(struct mgcp_response *r);
-
-int mgcpgw_client_tx(struct mgcpgw_client *mgcp, struct msgb *msg,
-		     mgcp_response_cb_t response_cb, void *priv);
-
-struct msgb *mgcp_msg_crcx(struct mgcpgw_client *mgcp,
-			   uint16_t rtp_endpoint, unsigned int call_id,
-			   enum mgcp_connection_mode mode);
-
-struct msgb *mgcp_msg_mdcx(struct mgcpgw_client *mgcp,
-			   uint16_t rtp_endpoint, const char *rtp_conn_addr,
-			   uint16_t rtp_port, enum mgcp_connection_mode mode);
-
-struct msgb *mgcp_msg_dlcx(struct mgcpgw_client *mgcp, uint16_t rtp_endpoint,
-			   unsigned int call_id);
-
-void mgcpgw_client_vty_init(int node, struct mgcpgw_client_conf *conf);
-int mgcpgw_client_config_write(struct vty *vty, const char *indent);
-
-struct mgcp_response_pending * mgcpgw_client_pending_add(
-					struct mgcpgw_client *mgcp,
-					mgcp_trans_id_t trans_id,
-					mgcp_response_cb_t response_cb,
-					void *priv);
-int mgcpgw_client_rx(struct mgcpgw_client *mgcp, struct msgb *msg);
diff --git a/include/openbsc/misdn.h b/include/openbsc/misdn.h
deleted file mode 100644
index 9851ad3..0000000
--- a/include/openbsc/misdn.h
+++ /dev/null
@@ -1,27 +0,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 MISDN_H
-#define MISDN_H
-
-#include <osmocom/abis/e1_input.h>
-
-int mi_setup(int cardnr,  struct e1inp_line *line, int release_l2);
-int mi_e1_line_update(struct e1inp_line *line);
-
-#endif
diff --git a/include/openbsc/mncc.h b/include/openbsc/mncc.h
deleted file mode 100644
index 881e041..0000000
--- a/include/openbsc/mncc.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface 
- * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
-
-/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2008, 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 _MNCC_H
-#define _MNCC_H
-
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/gsm/mncc.h>
-
-#include <stdint.h>
-
-struct gsm_network;
-struct msgb;
-
-
-/* One end of a call */
-struct gsm_call {
-	struct llist_head entry;
-
-	/* network handle */
-	void *net;
-
-	/* the 'local' transaction */
-	uint32_t callref;
-	/* the 'remote' transaction */
-	uint32_t remote_ref;
-};
-
-#define MNCC_SETUP_REQ		0x0101
-#define MNCC_SETUP_IND		0x0102
-#define MNCC_SETUP_RSP		0x0103
-#define MNCC_SETUP_CNF		0x0104
-#define MNCC_SETUP_COMPL_REQ	0x0105
-#define MNCC_SETUP_COMPL_IND	0x0106
-/* MNCC_REJ_* is perfomed via MNCC_REL_* */
-#define MNCC_CALL_CONF_IND	0x0107
-#define MNCC_CALL_PROC_REQ	0x0108
-#define MNCC_PROGRESS_REQ	0x0109
-#define MNCC_ALERT_REQ		0x010a
-#define MNCC_ALERT_IND		0x010b
-#define MNCC_NOTIFY_REQ		0x010c
-#define MNCC_NOTIFY_IND		0x010d
-#define MNCC_DISC_REQ		0x010e
-#define MNCC_DISC_IND		0x010f
-#define MNCC_REL_REQ		0x0110
-#define MNCC_REL_IND		0x0111
-#define MNCC_REL_CNF		0x0112
-#define MNCC_FACILITY_REQ	0x0113
-#define MNCC_FACILITY_IND	0x0114
-#define MNCC_START_DTMF_IND	0x0115
-#define MNCC_START_DTMF_RSP	0x0116
-#define MNCC_START_DTMF_REJ	0x0117
-#define MNCC_STOP_DTMF_IND	0x0118
-#define MNCC_STOP_DTMF_RSP	0x0119
-#define MNCC_MODIFY_REQ		0x011a
-#define MNCC_MODIFY_IND		0x011b
-#define MNCC_MODIFY_RSP		0x011c
-#define MNCC_MODIFY_CNF		0x011d
-#define MNCC_MODIFY_REJ		0x011e
-#define MNCC_HOLD_IND		0x011f
-#define MNCC_HOLD_CNF		0x0120
-#define MNCC_HOLD_REJ		0x0121
-#define MNCC_RETRIEVE_IND	0x0122
-#define MNCC_RETRIEVE_CNF	0x0123
-#define MNCC_RETRIEVE_REJ	0x0124
-#define MNCC_USERINFO_REQ	0x0125
-#define MNCC_USERINFO_IND	0x0126
-#define MNCC_REJ_REQ		0x0127
-#define MNCC_REJ_IND		0x0128
-
-#define MNCC_BRIDGE		0x0200
-#define MNCC_FRAME_RECV		0x0201
-#define MNCC_FRAME_DROP		0x0202
-#define MNCC_LCHAN_MODIFY	0x0203
-#define MNCC_RTP_CREATE		0x0204
-#define MNCC_RTP_CONNECT	0x0205
-#define MNCC_RTP_FREE		0x0206
-
-#define GSM_TCHF_FRAME		0x0300
-#define GSM_TCHF_FRAME_EFR	0x0301
-#define GSM_TCHH_FRAME		0x0302
-#define GSM_TCH_FRAME_AMR	0x0303
-#define GSM_BAD_FRAME		0x03ff
-
-#define MNCC_SOCKET_HELLO	0x0400
-
-#define GSM_MAX_FACILITY	128
-#define GSM_MAX_SSVERSION	128
-#define GSM_MAX_USERUSER	128
-
-#define	MNCC_F_BEARER_CAP	0x0001
-#define MNCC_F_CALLED		0x0002
-#define MNCC_F_CALLING		0x0004
-#define MNCC_F_REDIRECTING	0x0008
-#define MNCC_F_CONNECTED	0x0010
-#define MNCC_F_CAUSE		0x0020
-#define MNCC_F_USERUSER		0x0040
-#define MNCC_F_PROGRESS		0x0080
-#define MNCC_F_EMERGENCY	0x0100
-#define MNCC_F_FACILITY		0x0200
-#define MNCC_F_SSVERSION	0x0400
-#define MNCC_F_CCCAP		0x0800
-#define MNCC_F_KEYPAD		0x1000
-#define MNCC_F_SIGNAL		0x2000
-
-struct gsm_mncc {
-	/* context based information */
-	uint32_t	msg_type;
-	uint32_t	callref;
-
-	/* which fields are present */
-	uint32_t	fields;
-
-	/* data derived informations (MNCC_F_ based) */
-	struct gsm_mncc_bearer_cap	bearer_cap;
-	struct gsm_mncc_number		called;
-	struct gsm_mncc_number		calling;
-	struct gsm_mncc_number		redirecting;
-	struct gsm_mncc_number		connected;
-	struct gsm_mncc_cause		cause;
-	struct gsm_mncc_progress	progress;
-	struct gsm_mncc_useruser	useruser;
-	struct gsm_mncc_facility	facility;
-	struct gsm_mncc_cccap		cccap;
-	struct gsm_mncc_ssversion	ssversion;
-	struct	{
-		int		sup;
-		int		inv;
-	} clir;
-	int		signal;
-
-	/* data derived information, not MNCC_F based */
-	int		keypad;
-	int		more;
-	int		notify; /* 0..127 */
-	int		emergency;
-	char		imsi[16];
-};
-
-struct gsm_data_frame {
-	uint32_t	msg_type;
-	uint32_t	callref;
-	unsigned char	data[0];
-};
-
-#define MNCC_SOCK_VERSION	5
-struct gsm_mncc_hello {
-	uint32_t	msg_type;
-	uint32_t	version;
-
-	/* send the sizes of the structs */
-	uint32_t	mncc_size;
-	uint32_t	data_frame_size;
-
-	/* send some offsets */
-	uint32_t	called_offset;
-	uint32_t	signal_offset;
-	uint32_t	emergency_offset;
-};
-
-struct gsm_mncc_rtp {
-	uint32_t	msg_type;
-	uint32_t	callref;
-	uint32_t	ip;
-	uint16_t	port;
-	uint32_t	payload_type;
-	uint32_t	payload_msg_type;
-};
-
-struct gsm_mncc_bridge {
-	uint32_t	msg_type;
-	uint32_t	callref[2];
-};
-
-const char *get_mncc_name(int value);
-void mncc_set_cause(struct gsm_mncc *data, int loc, int val);
-void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg);
-
-/* input from CC code into mncc_builtin */
-int int_mncc_recv(struct gsm_network *net, struct msgb *msg);
-
-/* input from CC code into mncc_sock */
-int mncc_sock_from_cc(struct gsm_network *net, struct msgb *msg);
-
-int mncc_sock_init(struct gsm_network *net, const char *sock_path);
-
-#define mncc_is_data_frame(msg_type) \
-	(msg_type == GSM_TCHF_FRAME \
-		|| msg_type == GSM_TCHF_FRAME_EFR \
-		|| msg_type == GSM_TCHH_FRAME \
-		|| msg_type == GSM_TCH_FRAME_AMR \
-		|| msg_type == GSM_BAD_FRAME)
-
-
-#endif
diff --git a/include/openbsc/mncc_int.h b/include/openbsc/mncc_int.h
deleted file mode 100644
index 213ce14..0000000
--- a/include/openbsc/mncc_int.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _MNCC_INT_H
-#define _MNCC_INT_H
-
-#include <stdint.h>
-
-struct mncc_int {
-	uint8_t def_codec[2];
-};
-
-extern struct mncc_int mncc_int;
-
-uint8_t mncc_codec_for_mode(int lchan_type);
-
-#endif
diff --git a/include/openbsc/msc_ifaces.h b/include/openbsc/msc_ifaces.h
deleted file mode 100644
index a1071ae..0000000
--- a/include/openbsc/msc_ifaces.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#pragma once
-
-#include <osmocom/core/msgb.h>
-#include <openbsc/gsm_data.h>
-
-/* These are the interfaces of the MSC layer towards (from?) the BSC and RNC,
- * i.e. in the direction towards the mobile device (MS aka UE).
- *
- * 2G will use the A-interface,
- * 3G aka UMTS will use the Iu-interface (for the MSC, it's IuCS).
- *
- * To allow linking parts of the MSC code without having to include entire
- * infrastructures of external libraries, the core transmitting and receiving
- * functions are left unimplemented. For example, a unit test does not need to
- * link against external ASN1 libraries if it is never going to encode actual
- * outgoing messages. It is up to each building scope to implement real world
- * functions or to plug mere dummy implementations.
- *
- * For example, msc_tx_dtap(conn, msg), depending on conn->via_iface, will call
- * either iu_tx() or a_tx() [note: at time of writing, the A-interface is not
- * yet implemented]. When you try to link against libmsc, you will find that
- * the compiler complains about an undefined reference to iu_tx(). If you,
- * however, link against libiu as well as the osmo-iuh libs (etc.), iu_tx() is
- * available. A unit test may instead simply implement a dummy iu_tx() function
- * and not link against osmo-iuh, see tests/libiudummy/.
- */
-
-/* Each main linkage must implement this function (see comment above). */
-extern int iu_tx(struct msgb *msg, uint8_t sapi);
-
-int msc_tx_dtap(struct gsm_subscriber_connection *conn,
-		struct msgb *msg);
-
-int msc_gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn);
-int msc_gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
-			     enum gsm48_reject_value value);
-
-int msc_tx_common_id(struct gsm_subscriber_connection *conn);
-int msc_call_assignment(struct gsm_trans *trans);
-int msc_call_bridge(struct gsm_trans *trans1, struct gsm_trans *trans2);
-void msc_call_release(struct gsm_trans *trans);
-int msc_call_connect(struct gsm_trans *trans, uint16_t port, uint32_t ip);
diff --git a/include/openbsc/nat_rewrite_trie.h b/include/openbsc/nat_rewrite_trie.h
deleted file mode 100644
index 0571099..0000000
--- a/include/openbsc/nat_rewrite_trie.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * (C) 2013 by On-Waves
- * (C) 2013 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 NAT_REWRITE_FILE_H
-#define NAT_REWRITE_FILE_H
-
-#include <osmocom/core/linuxrbtree.h>
-
-struct vty;
-
-struct nat_rewrite_rule {
-	/* For digits 0-9 and + */
-	struct nat_rewrite_rule *rules[11];
-
-	char empty;
-	char prefix[14];
-	char rewrite[6];
-};
-
-struct nat_rewrite {
-	struct nat_rewrite_rule rule;
-	size_t prefixes;
-};
-
-
-struct nat_rewrite *nat_rewrite_parse(void *ctx, const char *filename);
-struct nat_rewrite_rule *nat_rewrite_lookup(struct nat_rewrite *, const char *prefix);
-void nat_rewrite_dump(struct nat_rewrite *rewr);
-void nat_rewrite_dump_vty(struct vty *vty, struct nat_rewrite *rewr);
-
-#endif
diff --git a/include/openbsc/network_listen.h b/include/openbsc/network_listen.h
deleted file mode 100644
index 67d1f4e..0000000
--- a/include/openbsc/network_listen.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _OPENBSC_NWL_H
-#define _OPENBSC_NWL_H
-
-#include <stdint.h>
-#include <openbsc/gsm_data.h>
-
-void ipac_nwl_init(void);
-
-/* Start a NWL test.  It will raise the S_IPAC_TEST_COMPLETE signal. */
-int ipac_nwl_test_start(struct gsm_bts_trx *trx, uint8_t testnr,
-			const uint8_t *phys_conf, unsigned int phys_conf_len);
-
-int ipac_rxlevstat2whitelist(uint16_t *buf, const struct rxlev_stats *st, uint8_t min_rxlev,
-			     uint16_t max_num_arfcns);
-
-#endif /* _OPENBSC_NWL_H */
diff --git a/include/openbsc/oap_client.h b/include/openbsc/oap_client.h
deleted file mode 100644
index 80c86d5..0000000
--- a/include/openbsc/oap_client.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* Osmocom Authentication Protocol API */
-
-/* (C) 2015 by Sysmocom s.f.m.c. GmbH
- * 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>
-
-struct msgb;
-struct osmo_oap_message;
-
-/* This is the config part for vty. It is essentially copied in
- * oap_client_state, where values are copied over once the config is
- * considered valid. */
-struct oap_client_config {
-	uint16_t client_id;
-	int secret_k_present;
-	uint8_t secret_k[16];
-	int secret_opc_present;
-	uint8_t secret_opc[16];
-};
-
-/* The runtime state of the OAP client. client_id and the secrets are in fact
- * duplicated from oap_client_config, so that a separate validation of the
- * config data is possible, and so that only a struct oap_client_state* is
- * passed around. */
-struct oap_client_state {
-	enum {
-		OAP_UNINITIALIZED = 0,	/* just allocated. */
-		OAP_DISABLED,		/* disabled by config. */
-		OAP_INITIALIZED,	/* enabled, config is valid. */
-		OAP_REQUESTED_CHALLENGE,
-		OAP_SENT_CHALLENGE_RESULT,
-		OAP_REGISTERED
-	} state;
-	uint16_t client_id;
-	uint8_t secret_k[16];
-	uint8_t secret_opc[16];
-	int registration_failures;
-};
-
-/* From config, initialize state. Return 0 on success. */
-int oap_client_init(struct oap_client_config *config,
-		    struct oap_client_state *state);
-
-/* Construct an OAP registration message and return in *msg_tx. Use
- * state->client_id and update state->state.
- * Return 0 on success, or a negative value on error.
- * If an error is returned, *msg_tx is guaranteed to be NULL. */
-int oap_client_register(struct oap_client_state *state, struct msgb **msg_tx);
-
-/* Decode and act on a received OAP message msg_rx. Update state->state.  If a
- * non-NULL pointer is returned in *msg_tx, that msgb should be sent to the OAP
- * server (and freed) by the caller. The received msg_rx is not freed.
- * Return 0 on success, or a negative value on error.
- * If an error is returned, *msg_tx is guaranteed to be NULL. */
-int oap_client_handle(struct oap_client_state *state,
-		      const struct msgb *msg_rx, struct msgb **msg_tx);
-
-/* Allocate a msgb and in it, return the encoded oap_client_msg. Return
- * NULL on error. (Like oap_client_encode(), but also allocates a msgb.)
- * About the name: the idea is do_something(oap_client_encoded(my_struct))
- */
-struct msgb *oap_client_encoded(const struct osmo_oap_message *oap_client_msg);
diff --git a/include/openbsc/openbscdefines.h b/include/openbsc/openbscdefines.h
deleted file mode 100644
index c6ac153..0000000
--- a/include/openbsc/openbscdefines.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* 
- * (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 OPENBSCDEFINES_H
-#define OPENBSCDEFINES_H
-
-#ifdef BUILDING_ON_WINDOWS
-    #ifdef BUILDING_OPENBSC
-        #define BSC_API __declspec(dllexport)
-    #else
-        #define BSC_API __declspec(dllimport)
-    #endif
-#else
-    #define BSC_API __attribute__((visibility("default")))
-#endif
-
-#endif
diff --git a/include/openbsc/osmo_bsc.h b/include/openbsc/osmo_bsc.h
deleted file mode 100644
index 5ebea50..0000000
--- a/include/openbsc/osmo_bsc.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* OpenBSC BSC code */
-
-#ifndef OSMO_BSC_H
-#define OSMO_BSC_H
-
-#include "bsc_api.h"
-#include "bsc_msg_filter.h"
-
-#define BSS_SEND_USSD 1
-
-enum bsc_con {
-	BSC_CON_SUCCESS,
-	BSC_CON_REJECT_NO_LINK,
-	BSC_CON_REJECT_RF_GRACE,
-	BSC_CON_NO_MEM,
-};
-
-struct sccp_connection;
-struct bsc_msc_data;
-struct bsc_msc_connection;
-
-struct osmo_bsc_sccp_con {
-	struct llist_head entry;
-
-	int ciphering_handled;
-
-	/* for audio handling */
-	uint16_t cic;
-	uint32_t rtp_ip;
-	int rtp_port;
-
-	/* for advanced ping/pong */
-	int send_ping;
-
-	/* SCCP connection realted */
-	struct sccp_connection *sccp;
-	struct bsc_msc_data *msc;
-	struct osmo_timer_list sccp_it_timeout;
-	struct osmo_timer_list sccp_cc_timeout;
-
-	struct llist_head sccp_queue;
-	unsigned int sccp_queue_size;
-
-	struct gsm_subscriber_connection *conn;
-	uint8_t new_subscriber;
-
-	struct bsc_filter_state filter_state;
-
-	/* Sigtran connection ID */
-	int conn_id;
-};
-
-struct bsc_api *osmo_bsc_api();
-
-int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg);
-int bsc_open_connection(struct osmo_bsc_sccp_con *sccp, struct msgb *msg);
-enum bsc_con bsc_create_new_connection(struct gsm_subscriber_connection *conn,
-				       struct bsc_msc_data *msc, int send_ping);
-int bsc_delete_connection(struct osmo_bsc_sccp_con *sccp);
-
-struct bsc_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn, struct msgb *);
-int bsc_scan_bts_msg(struct gsm_subscriber_connection *conn, struct msgb *msg);
-int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg);
-int bsc_send_welcome_ussd(struct gsm_subscriber_connection *conn);
-
-int bsc_handle_udt(struct bsc_msc_data *msc, struct msgb *msg, unsigned int length);
-int bsc_handle_dt(struct osmo_bsc_sccp_con *conn, struct msgb *msg, unsigned int len);
-
-int bsc_ctrl_cmds_install();
-
-void bsc_gen_location_state_trap(struct gsm_bts *bts);
-
-struct llist_head *bsc_access_lists(void);
-
-#endif
diff --git a/include/openbsc/osmo_bsc_grace.h b/include/openbsc/osmo_bsc_grace.h
deleted file mode 100644
index 5a81cd1..0000000
--- a/include/openbsc/osmo_bsc_grace.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * (C) 2010-2013 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2013 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 OSMO_BSC_GRACE_H
-#define OSMO_BSC_GRACE_H
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/signal.h>
-
-struct bsc_msc_data;
-
-int bsc_grace_allow_new_connection(struct gsm_network *net, struct gsm_bts *bts);
-int bsc_grace_paging_request(enum signal_rf rf_policy,
-			     struct bsc_subscr *subscr,
-			     int chan_needed,
-			     struct bsc_msc_data *msc);
-
-#endif
diff --git a/include/openbsc/osmo_bsc_reset.h b/include/openbsc/osmo_bsc_reset.h
deleted file mode 100644
index 578f763..0000000
--- a/include/openbsc/osmo_bsc_reset.h
+++ /dev/null
@@ -1,34 +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/>.
- *
- */
-
-/* Create and start state machine which handles the reset/reset-ack procedure */
-void start_reset_fsm(struct bsc_msc_data *msc);
-
-/* Confirm that we sucessfully received a reset acknowlege message */
-void reset_ack_confirm(struct bsc_msc_data *msc);
-
-/* Report a failed connection */
-void report_conn_fail(struct bsc_msc_data *msc);
-
-/* Report a successful connection */
-void report_conn_success(struct bsc_msc_data *msc);
-
-/* Check if we have a connection to a specified msc */
-bool sccp_conn_ready(struct bsc_msc_data *msc);
diff --git a/include/openbsc/osmo_bsc_rf.h b/include/openbsc/osmo_bsc_rf.h
deleted file mode 100644
index 19ccd08..0000000
--- a/include/openbsc/osmo_bsc_rf.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef OSMO_BSC_RF
-#define OSMO_BSC_RF
-
-#include <openbsc/gsm_data.h>
-#include <osmocom/core/write_queue.h>
-#include <osmocom/core/timer.h>
-
-enum osmo_bsc_rf_opstate {
-	OSMO_BSC_RF_OPSTATE_INOPERATIONAL,
-	OSMO_BSC_RF_OPSTATE_OPERATIONAL,
-};
-
-enum osmo_bsc_rf_adminstate {
-	OSMO_BSC_RF_ADMINSTATE_UNLOCKED,
-	OSMO_BSC_RF_ADMINSTATE_LOCKED,
-};
-
-enum osmo_bsc_rf_policy {
-	OSMO_BSC_RF_POLICY_OFF,
-	OSMO_BSC_RF_POLICY_ON,
-	OSMO_BSC_RF_POLICY_GRACE,
-	OSMO_BSC_RF_POLICY_UNKNOWN,
-};
-
-
-struct gsm_network;
-
-struct osmo_bsc_rf {
-	/* the value of signal.h */
-	int policy;
-	struct osmo_fd listen;
-	struct gsm_network *gsm_network;
-
-	const char *last_state_command;
-
-	char *last_rf_lock_ctrl_command;
-
-	/* delay the command */
-	char last_request;
-	struct osmo_timer_list delay_cmd;
-
-	/* verify that RF is up as it should be */
-	struct osmo_timer_list rf_check;
-
-	/* some handling for the automatic grace switch */
-	struct osmo_timer_list grace_timeout;
-
-	/* auto RF switch-off due lack of MSC connection */
-	struct osmo_timer_list auto_off_timer;
-};
-
-struct osmo_bsc_rf_conn {
-	struct osmo_wqueue queue;
-	struct osmo_bsc_rf *rf;
-};
-
-const char *osmo_bsc_rf_get_opstate_name(enum osmo_bsc_rf_opstate opstate);
-const char *osmo_bsc_rf_get_adminstate_name(enum osmo_bsc_rf_adminstate adminstate);
-const char *osmo_bsc_rf_get_policy_name(enum osmo_bsc_rf_policy policy);
-enum osmo_bsc_rf_opstate osmo_bsc_rf_get_opstate_by_bts(struct gsm_bts *bts);
-enum osmo_bsc_rf_adminstate osmo_bsc_rf_get_adminstate_by_bts(struct gsm_bts *bts);
-enum osmo_bsc_rf_policy osmo_bsc_rf_get_policy_by_bts(struct gsm_bts *bts);
-struct osmo_bsc_rf *osmo_bsc_rf_create(const char *path, struct gsm_network *net);
-void osmo_bsc_rf_schedule_lock(struct osmo_bsc_rf *rf, char cmd);
-
-#endif
diff --git a/include/openbsc/osmo_bsc_sigtran.h b/include/openbsc/osmo_bsc_sigtran.h
deleted file mode 100644
index fbcfcb3..0000000
--- a/include/openbsc/osmo_bsc_sigtran.h
+++ /dev/null
@@ -1,48 +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/gsm_data.h>
-#include <openbsc/bsc_msc_data.h>
-
-/* Allocate resources to make a new connection oriented sigtran connection
- * (not the connection ittself!) */
-enum bsc_con osmo_bsc_sigtran_new_conn(struct gsm_subscriber_connection *conn, struct bsc_msc_data *msc);
-
-/* Open a new connection oriented sigtran connection */
-int osmo_bsc_sigtran_open_conn(const struct osmo_bsc_sccp_con *conn, struct msgb *msg);
-
-/* Send data to MSC */
-int osmo_bsc_sigtran_send(const struct osmo_bsc_sccp_con *conn, struct msgb *msg);
-
-/* Delete a connection from the list with open connections
- * (called by osmo_bsc_api.c on failing open connections and
- * locally, when a connection is closed by the MSC */
-int osmo_bsc_sigtran_del_conn(struct osmo_bsc_sccp_con *sccp);
-
-/* Initalize osmo sigtran backhaul */
-int osmo_bsc_sigtran_init(struct llist_head *mscs);
-
-/* Close all open sigtran connections and channels */
-void osmo_bsc_sigtran_reset(const struct bsc_msc_data *msc);
-
-/* Send reset-ack to MSC */
-void osmo_bsc_sigtran_tx_reset_ack(const struct bsc_msc_data *msc);
diff --git a/include/openbsc/osmo_msc.h b/include/openbsc/osmo_msc.h
deleted file mode 100644
index cdfd27f..0000000
--- a/include/openbsc/osmo_msc.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* Routines for the MSC handling */
-
-#ifndef OSMO_MSC_H
-#define OSMO_MSC_H
-
-#include <osmocom/core/fsm.h>
-#include <osmocom/gsm/gsup.h>
-
-#include <openbsc/gsm_data.h>
-
-#include "bsc_api.h"
-
-#define MSC_HLR_REMOTE_IP_DEFAULT "127.0.0.1"
-#define MSC_HLR_REMOTE_PORT_DEFAULT OSMO_GSUP_PORT
-
-enum subscr_conn_fsm_event {
-	/* Mark 0 as invalid to catch uninitialized vars */
-	SUBSCR_CONN_E_INVALID = 0,
-	/* Timeout on connection establishment starts */
-	SUBSCR_CONN_E_START,
-	/* LU or Process Access FSM has determined that this conn is good */
-	SUBSCR_CONN_E_ACCEPTED,
-	/* received first reply from MS in "real" CC, SMS, USSD communication */
-	SUBSCR_CONN_E_COMMUNICATING,
-	/* Some async action has completed, check again whether all is done */
-	SUBSCR_CONN_E_BUMP,
-	/* MS/BTS/BSC originated close request */
-	SUBSCR_CONN_E_MO_CLOSE,
-	/* MSC originated close request, e.g. failed authentication */
-	SUBSCR_CONN_E_CN_CLOSE,
-};
-
-enum subscr_conn_fsm_state {
-	SUBSCR_CONN_S_INIT,
-	SUBSCR_CONN_S_NEW,
-	SUBSCR_CONN_S_ACCEPTED,
-	SUBSCR_CONN_S_COMMUNICATING,
-	SUBSCR_CONN_S_RELEASED,
-};
-
-enum subscr_conn_from {
-	SUBSCR_CONN_FROM_INVALID,
-	SUBSCR_CONN_FROM_LU,
-	SUBSCR_CONN_FROM_CM_SERVICE_REQ,
-	SUBSCR_CONN_FROM_PAGING_RESP,
-};
-
-extern const struct value_string subscr_conn_from_names[];
-static inline const char *subscr_conn_from_name(enum subscr_conn_from val)
-{
-	return get_value_string(subscr_conn_from_names, val);
-}
-
-enum msc_compl_l3_rc {
-	MSC_CONN_ACCEPT = 0,
-	MSC_CONN_REJECT = 1,
-};
-
-struct bsc_api *msc_bsc_api();
-
-int msc_create_conn_fsm(struct gsm_subscriber_connection *conn, const char *id);
-
-int msc_vlr_alloc(struct gsm_network *net);
-int msc_vlr_start(struct gsm_network *net);
-
-void msc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci);
-int msc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause);
-int msc_compl_l3(struct gsm_subscriber_connection *conn,
-		 struct msgb *msg, uint16_t chosen_channel);
-void msc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id,
-	      struct msgb *msg);
-void msc_cipher_mode_compl(struct gsm_subscriber_connection *conn,
-			   struct msgb *msg, uint8_t alg_id);
-void msc_rx_sec_mode_compl(struct gsm_subscriber_connection *conn);
-void msc_classmark_chg(struct gsm_subscriber_connection *conn,
-		       const uint8_t *cm2, uint8_t cm2_len,
-		       const uint8_t *cm3, uint8_t cm3_len);
-void msc_assign_fail(struct gsm_subscriber_connection *conn,
-		     uint8_t cause, uint8_t *rr_cause);
-
-void msc_subscr_conn_init(void);
-bool msc_subscr_conn_is_accepted(struct gsm_subscriber_connection *conn);
-void msc_subscr_conn_communicating(struct gsm_subscriber_connection *conn);
-void msc_subscr_conn_close(struct gsm_subscriber_connection *conn,
-			   uint32_t cause);
-
-#define msc_subscr_conn_get(conn) \
-	_msc_subscr_conn_get(conn, __BASE_FILE__, __LINE__)
-#define msc_subscr_conn_put(conn) \
-	_msc_subscr_conn_put(conn, __BASE_FILE__, __LINE__)
-struct gsm_subscriber_connection *
-_msc_subscr_conn_get(struct gsm_subscriber_connection *conn,
-		     const char *file, int line);
-void _msc_subscr_conn_put(struct gsm_subscriber_connection *conn,
-			  const char *file, int line);
-
-void msc_stop_paging(struct vlr_subscr *vsub);
-
-#endif
diff --git a/include/openbsc/paging.h b/include/openbsc/paging.h
deleted file mode 100644
index 7dd8500..0000000
--- a/include/openbsc/paging.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Paging helper and manager.... */
-/* (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 PAGING_H
-#define PAGING_H
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/timer.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/bsc_subscriber.h>
-
-/**
- * A pending paging request
- */
-struct gsm_paging_request {
-	/* list_head for list of all paging requests */
-	struct llist_head entry;
-	/* the subscriber which we're paging. Later gsm_paging_request
-	 * should probably become a part of the bsc_subsrc struct? */
-	struct bsc_subscr *bsub;
-	/* back-pointer to the BTS on which we are paging */
-	struct gsm_bts *bts;
-	/* what kind of channel type do we ask the MS to establish */
-	int chan_type;
-
-	/* Timer 3113: how long do we try to page? */
-	struct osmo_timer_list T3113;
-
-	/* How often did we ask the BTS to page? */
-	int attempts;
-
-	/* callback to be called in case paging completes */
-	gsm_cbfn *cbfn;
-	void *cbfn_param;
-};
-
-/* schedule paging request */
-int paging_request(struct gsm_network *network, struct bsc_subscr *bsub,
-		   int type, gsm_cbfn *cbfn, void *data);
-int paging_request_bts(struct gsm_bts *bts, struct bsc_subscr *bsub,
-		       int type, gsm_cbfn *cbfn, void *data);
-
-/* stop paging requests */
-void paging_request_stop(struct llist_head *bts_list,
-			 struct gsm_bts *_bts, struct bsc_subscr *bsub,
-			 struct gsm_subscriber_connection *conn,
-			 struct msgb *msg);
-
-/* update paging load */
-void paging_update_buffer_space(struct gsm_bts *bts, uint16_t);
-
-/* pending paging requests */
-unsigned int paging_pending_requests_nr(struct gsm_bts *bts);
-
-void *paging_get_data(struct gsm_bts *bts, struct bsc_subscr *bsub);
-
-#endif
diff --git a/include/openbsc/pcu_if.h b/include/openbsc/pcu_if.h
deleted file mode 100644
index 1f398b4..0000000
--- a/include/openbsc/pcu_if.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef _PCU_IF_H
-#define _PCU_IF_H
-
-#include <osmocom/gsm/l1sap.h>
-
-extern int pcu_direct;
-
-struct pcu_sock_state {
-	struct gsm_network *net;
-	struct osmo_fd listen_bfd;	/* fd for listen socket */
-	struct osmo_fd conn_bfd;	/* fd for connection to lcr */
-	struct llist_head upqueue;	/* queue for sending messages */
-};
-
-/* PCU relevant information has changed; Inform PCU (if connected) */
-void pcu_info_update(struct gsm_bts *bts);
-
-/* Forward rach indication to PCU */
-int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint16_t ra, uint32_t fn,
-	uint8_t is_11bit, enum ph_burst_type burst_type);
-
-/* Confirm the sending of an immediate assignment to the pcu */
-int pcu_tx_imm_ass_sent(struct gsm_bts *bts, uint32_t tlli);
-
-
-/* Confirm the sending of an immediate assignment to the pcu */
-int pcu_tx_imm_ass_sent(struct gsm_bts *bts, uint32_t tlli);
-
-/* Open connection to PCU */
-int pcu_sock_init(const char *path, struct gsm_bts *bts);
-
-/* Close connection to PCU */
-void pcu_sock_exit(struct gsm_bts *bts);
-
-#endif /* _PCU_IF_H */
diff --git a/include/openbsc/pcuif_proto.h b/include/openbsc/pcuif_proto.h
deleted file mode 100644
index eb28d66..0000000
--- a/include/openbsc/pcuif_proto.h
+++ /dev/null
@@ -1,176 +0,0 @@
-#ifndef _PCUIF_PROTO_H
-#define _PCUIF_PROTO_H
-
-#define PCU_IF_VERSION		0x08
-
-/* msg_type */
-#define PCU_IF_MSG_DATA_REQ	0x00	/* send data to given channel */
-#define PCU_IF_MSG_DATA_CNF	0x01	/* confirm (e.g. transmission on PCH) */
-#define PCU_IF_MSG_DATA_IND	0x02	/* receive data from given channel */
-#define PCU_IF_MSG_DATA_CNF_DT	0x11	/* confirm (with direct tlli) */
-#define PCU_IF_MSG_RTS_REQ	0x10	/* ready to send request */
-#define PCU_IF_MSG_RACH_IND	0x22	/* receive RACH */
-#define PCU_IF_MSG_INFO_IND	0x32	/* retrieve BTS info */
-#define PCU_IF_MSG_ACT_REQ	0x40	/* activate/deactivate PDCH */
-#define PCU_IF_MSG_TIME_IND	0x52	/* GSM time indication */
-#define PCU_IF_MSG_PAG_REQ	0x60	/* paging request */
-
-/* sapi */
-#define PCU_IF_SAPI_RACH	0x01	/* channel request on CCCH */
-#define PCU_IF_SAPI_AGCH	0x02	/* assignment on AGCH */
-#define PCU_IF_SAPI_PCH		0x03	/* paging/assignment on PCH */
-#define PCU_IF_SAPI_BCCH	0x04	/* SI on BCCH */
-#define PCU_IF_SAPI_PDTCH	0x05	/* packet data/control/ccch block */
-#define PCU_IF_SAPI_PRACH	0x06	/* packet random access channel */
-#define PCU_IF_SAPI_PTCCH	0x07	/* packet TA control channel */
-#define PCU_IF_SAPI_AGCH_DT	0x08	/* assignment on AGCH but with additional TLLI */
-
-/* flags */
-#define PCU_IF_FLAG_ACTIVE	(1 << 0)/* BTS is active */
-#define PCU_IF_FLAG_SYSMO	(1 << 1)/* access PDCH of sysmoBTS directly */
-#define PCU_IF_FLAG_CS1		(1 << 16)
-#define PCU_IF_FLAG_CS2		(1 << 17)
-#define PCU_IF_FLAG_CS3		(1 << 18)
-#define PCU_IF_FLAG_CS4		(1 << 19)
-#define PCU_IF_FLAG_MCS1	(1 << 20)
-#define PCU_IF_FLAG_MCS2	(1 << 21)
-#define PCU_IF_FLAG_MCS3	(1 << 22)
-#define PCU_IF_FLAG_MCS4	(1 << 23)
-#define PCU_IF_FLAG_MCS5	(1 << 24)
-#define PCU_IF_FLAG_MCS6	(1 << 25)
-#define PCU_IF_FLAG_MCS7	(1 << 26)
-#define PCU_IF_FLAG_MCS8	(1 << 27)
-#define PCU_IF_FLAG_MCS9	(1 << 28)
-
-struct gsm_pcu_if_data {
-	uint8_t		sapi;
-	uint8_t		len;
-	uint8_t		data[162];
-	uint32_t	fn;
-	uint16_t	arfcn;
-	uint8_t		trx_nr;
-	uint8_t		ts_nr;
-	uint8_t		block_nr;
-	int8_t		rssi;
-	uint16_t	ber10k;		/*!< \brief BER in units of 0.01% */
-	int16_t		ta_offs_qbits;	/* !< \brief Burst TA Offset in quarter bits */
-	int16_t		lqual_cb;	/* !< \brief Link quality in centiBel */
-} __attribute__ ((packed));
-
-/* data confirmation with direct tlli (instead of raw mac block with tlli) */
-struct gsm_pcu_if_data_cnf_dt {
-	uint8_t		sapi;
-	uint32_t	tlli;
-	uint32_t	fn;
-	uint16_t	arfcn;
-	uint8_t		trx_nr;
-	uint8_t		ts_nr;
-	uint8_t		block_nr;
-	int8_t		rssi;
-	uint16_t ber10k;	/*!< \brief BER in units of 0.01% */
-	int16_t ta_offs_qbits;	/* !< \brief Burst TA Offset in quarter bits */
-	int16_t lqual_cb;	/* !< \brief Link quality in centiBel */
-} __attribute__ ((packed));
-
-struct gsm_pcu_if_rts_req {
-	uint8_t		sapi;
-	uint8_t		spare[3];
-	uint32_t	fn;
-	uint16_t	arfcn;
-	uint8_t		trx_nr;
-	uint8_t		ts_nr;
-	uint8_t		block_nr;
-} __attribute__ ((packed));
-
-struct gsm_pcu_if_rach_ind {
-	uint8_t		sapi;
-	uint16_t	ra;
-	int16_t		qta;
-	uint32_t	fn;
-	uint16_t	arfcn;
-	uint8_t		is_11bit;
-	uint8_t 	burst_type;
-} __attribute__ ((packed));
-
-struct gsm_pcu_if_info_trx {
-	uint16_t	arfcn;
-	uint8_t		pdch_mask;		/* PDCH channels per TS */
-	uint8_t		spare;
-	uint8_t		tsc[8];			/* TSC per channel */
-	uint32_t	hlayer1;
-} __attribute__ ((packed));
-
-struct gsm_pcu_if_info_ind {
-	uint32_t	version;
-	uint32_t	flags;
-	struct gsm_pcu_if_info_trx trx[8];	/* TRX infos per BTS */
-	uint8_t		bsic;
-	/* RAI */
-	uint16_t	mcc, mnc, lac, rac;
-	/* NSE */
-	uint16_t	nsei;
-	uint8_t		nse_timer[7];
-	uint8_t		cell_timer[11];
-	/* cell */
-	uint16_t	cell_id;
-	uint16_t	repeat_time;
-	uint8_t		repeat_count;
-	uint16_t	bvci;
-	uint8_t		t3142;
-	uint8_t		t3169;
-	uint8_t		t3191;
-	uint8_t		t3193_10ms;
-	uint8_t		t3195;
-	uint8_t		n3101;
-	uint8_t		n3103;
-	uint8_t		n3105;
-	uint8_t		cv_countdown;
-	uint16_t	dl_tbf_ext;
-	uint16_t	ul_tbf_ext;
-	uint8_t		initial_cs;
-	uint8_t		initial_mcs;
-	/* NSVC */
-	uint16_t	nsvci[2];
-	uint16_t	local_port[2];
-	uint16_t	remote_port[2];
-	uint32_t	remote_ip[2];
-} __attribute__ ((packed));
-
-struct gsm_pcu_if_act_req {
-	uint8_t		activate;
-	uint8_t		trx_nr;
-	uint8_t		ts_nr;
-	uint8_t		spare;
-} __attribute__ ((packed));
-
-struct gsm_pcu_if_time_ind {
-	uint32_t	fn;
-} __attribute__ ((packed));
-
-struct gsm_pcu_if_pag_req {
-	uint8_t		sapi;
-	uint8_t		chan_needed;
-	uint8_t		identity_lv[9];
-} __attribute__ ((packed));
-
-struct gsm_pcu_if {
-	/* context based information */
-	uint8_t		msg_type;	/* message type */
-	uint8_t		bts_nr;		/* bts number */
-	uint8_t		spare[2];
-
-	union {
-		struct gsm_pcu_if_data		data_req;
-		struct gsm_pcu_if_data		data_cnf;
-		struct gsm_pcu_if_data_cnf_dt	data_cnf_dt;
-		struct gsm_pcu_if_data		data_ind;
-		struct gsm_pcu_if_rts_req	rts_req;
-		struct gsm_pcu_if_rach_ind	rach_ind;
-		struct gsm_pcu_if_info_ind	info_ind;
-		struct gsm_pcu_if_act_req	act_req;
-		struct gsm_pcu_if_time_ind	time_ind;
-		struct gsm_pcu_if_pag_req	pag_req;
-	} u;
-} __attribute__ ((packed));
-
-#endif /* _PCUIF_PROTO_H */
diff --git a/include/openbsc/rest_octets.h b/include/openbsc/rest_octets.h
deleted file mode 100644
index 49a2312..0000000
--- a/include/openbsc/rest_octets.h
+++ /dev/null
@@ -1,139 +0,0 @@
-#ifndef _REST_OCTETS_H
-#define _REST_OCTETS_H
-
-#include <stdbool.h>
-#include <openbsc/gsm_04_08.h>
-#include <osmocom/gsm/sysinfo.h>
-
-/* generate SI1 rest octets */
-int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net);
-int rest_octets_si2quater(uint8_t *data, struct gsm_bts *bts);
-int rest_octets_si6(uint8_t *data, bool is1800_net);
-
-struct gsm48_si_selection_params {
-	uint16_t penalty_time:5,
-		  temp_offs:3,
-		  cell_resel_off:6,
-		  cbq:1,
-		  present:1;
-};
-
-struct gsm48_si_power_offset {
-	uint8_t power_offset:2,
-		 present:1;
-};
-
-struct gsm48_si3_gprs_ind {
-	uint8_t si13_position:1,
-		 ra_colour:3,
-		 present:1;
-};
-
-struct gsm48_lsa_params {
-	uint32_t prio_thr:3,
-		 lsa_offset:3,
-		 mcc:12,
-		 mnc:12;
-	unsigned int present;
-};
-
-struct gsm48_si_ro_info {
-	struct gsm48_si_selection_params selection_params;
-	struct gsm48_si_power_offset power_offset;
-	uint8_t si2ter_indicator;
-	uint8_t early_cm_ctrl;
-	struct {
-		uint8_t where:3,
-			 present:1;
-	} scheduling;
-	struct gsm48_si3_gprs_ind gprs_ind;
-	/* SI 3 specific */
-	uint8_t si2quater_indicator;
-	/* SI 4 specific */
-	struct gsm48_lsa_params lsa_params;
-	uint16_t cell_id;
-	uint8_t break_ind;	/* do we have SI7 + SI8 ? */
-};
-
-
-/* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */
-int rest_octets_si3(uint8_t *data, const struct gsm48_si_ro_info *si3);
-
-/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
-int rest_octets_si4(uint8_t *data, const struct gsm48_si_ro_info *si4, int len);
-
-enum pbcch_carrier_type {
-	PBCCH_BCCH,
-	PBCCH_ARFCN,
-	PBCCH_MAIO
-};
-
-/* TS 03.60 Chapter 6.3.3.1: Network Mode of Operation */
-enum gprs_nmo {
-	GPRS_NMO_I	= 0,	/* CS pagin on GPRS paging or traffic channel */
-	GPRS_NMO_II	= 1,	/* all paging on CCCH */
-	GPRS_NMO_III	= 2,	/* no paging coordination */
-};
-
-/* TS 04.60 12.24 */
-struct gprs_cell_options {
-	enum gprs_nmo nmo;
-	/* T3168: wait for packet uplink assignment message */
-	uint32_t t3168;	/* in milliseconds */
-	/* T3192: wait for release of the TBF after reception of the final block */
-	uint32_t t3192;	/* in milliseconds */
-	uint32_t drx_timer_max;/* in seconds */
-	uint32_t bs_cv_max;
-	uint8_t  supports_egprs_11bit_rach;
-	bool ctrl_ack_type_use_block; /* use PACKET CONTROL ACKNOWLEDGMENT */
-
-	uint8_t ext_info_present;
-	struct {
-		uint8_t egprs_supported;
-			uint8_t use_egprs_p_ch_req;
-			uint8_t bep_period;
-		uint8_t pfc_supported;
-		uint8_t dtm_supported;
-		uint8_t bss_paging_coordination;
-	} ext_info;
-};
-
-/* TS 04.60 Table 12.9.2 */
-struct gprs_power_ctrl_pars {
-	uint8_t alpha;
-	uint8_t t_avg_w;
-	uint8_t t_avg_t;
-	uint8_t pc_meas_chan;
-	uint8_t n_avg_i;
-};
-
-struct gsm48_si13_info {
-	struct gprs_cell_options cell_opts;
-	struct gprs_power_ctrl_pars pwr_ctrl_pars;
-	uint8_t bcch_change_mark;
-	uint8_t si_change_field;
-	uint8_t pbcch_present;
-
-	union {
-		struct {
-			uint8_t rac;
-			uint8_t spgc_ccch_sup;
-			uint8_t net_ctrl_ord;
-			uint8_t prio_acc_thr;
-		} no_pbcch;
-		struct {
-			uint8_t psi1_rep_per;
-			uint8_t pb;
-			uint8_t tsc;
-			uint8_t tn;
-			enum pbcch_carrier_type carrier_type;
-			uint16_t arfcn;
-			uint8_t maio;
-		} pbcch;
-	};
-};
-
-/* Generate SI13 Rest Octests (Chapter 10.5.2.37b) */
-int rest_octets_si13(uint8_t *data, const struct gsm48_si13_info *si13);
-
-#endif /* _REST_OCTETS_H */
diff --git a/include/openbsc/rrlp.h b/include/openbsc/rrlp.h
deleted file mode 100644
index c89402a..0000000
--- a/include/openbsc/rrlp.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _RRLP_H
-#define _RRLP_H
-
-void on_dso_load_rrlp(void);
-
-#endif /* _RRLP_H */
-
diff --git a/include/openbsc/rs232.h b/include/openbsc/rs232.h
deleted file mode 100644
index 61187ca..0000000
--- a/include/openbsc/rs232.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _RS232_H
-#define _RS232_H
-
-int rs232_setup(const char *serial_port, unsigned int delay_ms,
-		struct gsm_bts *bts);
-
-int handle_serial_msg(struct msgb *msg);
-
-#endif /* _RS232_H */
diff --git a/include/openbsc/rtp_proxy.h b/include/openbsc/rtp_proxy.h
deleted file mode 100644
index 52ffefd..0000000
--- a/include/openbsc/rtp_proxy.h
+++ /dev/null
@@ -1,95 +0,0 @@
-#ifndef _RTP_PROXY_H
-#define _RTP_PROXY_H
-
-/* RTP proxy handling for ip.access nanoBTS */
-
-/* (C) 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/>.
- *
- */
-
-
-#include <netinet/in.h>
-
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/select.h>
-
-#include <openbsc/mncc.h>
-
-#define RTP_PT_GSM_FULL 3
-#define RTP_PT_GSM_HALF 96
-#define RTP_PT_GSM_EFR 97
-#define RTP_PT_AMR 98
-#define RTP_LEN_GSM_FULL 33
-#define RTP_LEN_GSM_HALF 15
-#define RTP_LEN_GSM_EFR 31
-#define RTP_GSM_DURATION 160
-
-enum rtp_rx_action {
-	RTP_NONE,
-	RTP_PROXY,
-	RTP_RECV_UPSTREAM,
-};
-
-enum rtp_tx_action {
-	RTP_SEND_NONE,
-	RTP_SEND_DOWNSTREAM,
-};
-
-struct rtp_sub_socket {
-	struct sockaddr_in sin_local;
-	struct sockaddr_in sin_remote;
-
-	struct osmo_fd bfd;
-	/* linked list of to-be-transmitted msgb's */
-	struct llist_head tx_queue;
-};
-
-struct rtp_socket {
-	struct llist_head list;
-
-	struct rtp_sub_socket rtp;
-	struct rtp_sub_socket rtcp;
-
-	/* what should we do on receive? */
-	enum rtp_rx_action rx_action;
-	union {
-		struct {
-			struct rtp_socket *other_sock;
-		} proxy;
-		struct {
-			struct gsm_network *net;
-			uint32_t callref;
-		} receive;
-	};
-	enum rtp_tx_action tx_action;
-	struct {
-		uint16_t sequence;
-		uint32_t timestamp;
-		uint32_t ssrc;
-		struct timeval last_tv;
-	} transmit;
-};
-
-struct rtp_socket *rtp_socket_create(void);
-int rtp_socket_bind(struct rtp_socket *rs, uint32_t ip);
-int rtp_socket_connect(struct rtp_socket *rs, uint32_t ip, uint16_t port);
-int rtp_socket_proxy(struct rtp_socket *this, struct rtp_socket *other);
-int rtp_socket_upstream(struct rtp_socket *this, struct gsm_network *net, uint32_t callref);
-int rtp_socket_free(struct rtp_socket *rs);
-int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame);
-
-#endif /* _RTP_PROXY_H */
diff --git a/include/openbsc/sgsn.h b/include/openbsc/sgsn.h
deleted file mode 100644
index f371dc6..0000000
--- a/include/openbsc/sgsn.h
+++ /dev/null
@@ -1,191 +0,0 @@
-#ifndef _SGSN_H
-#define _SGSN_H
-
-
-#include <osmocom/core/msgb.h>
-#include <osmocom/crypt/gprs_cipher.h>
-#include <osmocom/gprs/gprs_ns.h>
-#include <openbsc/gprs_sgsn.h>
-#include <openbsc/oap_client.h>
-#include <openbsc/common.h>
-
-#include <ares.h>
-
-struct gprs_gsup_client;
-struct hostent;
-
-enum sgsn_auth_policy {
-	SGSN_AUTH_POLICY_OPEN,
-	SGSN_AUTH_POLICY_CLOSED,
-	SGSN_AUTH_POLICY_ACL_ONLY,
-	SGSN_AUTH_POLICY_REMOTE
-};
-
-
-enum sgsn_rate_ctr_keys {
-	CTR_LLC_DL_BYTES,
-	CTR_LLC_UL_BYTES,
-	CTR_LLC_DL_PACKETS,
-	CTR_LLC_UL_PACKETS,
-	CTR_GPRS_ATTACH_REQUEST,
-	CTR_GPRS_ATTACH_ACKED,
-	CTR_GPRS_ATTACH_REJECTED,
-	CTR_GPRS_DETACH_REQUEST,
-	CTR_GPRS_DETACH_ACKED,
-	CTR_GPRS_ROUTING_AREA_REQUEST,
-	CTR_GPRS_ROUTING_AREA_ACKED,
-	CTR_GPRS_ROUTING_AREA_REJECT,
-	/* PDP single packet counter / GSM 04.08 9.5.1 - 9.5.9 */
-	CTR_PDP_ACTIVATE_REQUEST,
-	CTR_PDP_ACTIVATE_REJECT,
-	CTR_PDP_ACTIVATE_ACCEPT,
-	CTR_PDP_REQUEST_ACTIVATE, /* unused */
-	CTR_PDP_REQUEST_ACTIVATE_REJ, /* unused */
-	CTR_PDP_MODIFY_REQUEST, /* unsued */
-	CTR_PDP_MODIFY_ACCEPT, /* unused */
-	CTR_PDP_DL_DEACTIVATE_REQUEST,
-	CTR_PDP_DL_DEACTIVATE_ACCEPT,
-	CTR_PDP_UL_DEACTIVATE_REQUEST,
-	CTR_PDP_UL_DEACTIVATE_ACCEPT,
-};
-
-struct sgsn_cdr {
-	char *filename;
-	int interval;
-};
-
-struct sgsn_config {
-	/* parsed from config file */
-
-	char *gtp_statedir;
-	struct sockaddr_in gtp_listenaddr;
-
-	/* misc */
-	struct gprs_ns_inst *nsi;
-
-	enum sgsn_auth_policy auth_policy;
-	enum gprs_ciph_algo cipher;
-	struct llist_head imsi_acl;
-
-	struct sockaddr_in gsup_server_addr;
-	int gsup_server_port;
-
-	int require_authentication;
-	int require_update_location;
-
-	/* CDR configuration */
-	struct sgsn_cdr cdr;
-
-	struct {
-		int T3312;
-		int T3322;
-		int T3350;
-		int T3360;
-		int T3370;
-		int T3313;
-		int T3314;
-		int T3316;
-		int T3385;
-		int T3386;
-		int T3395;
-		int T3397;
-	} timers;
-
-	int dynamic_lookup;
-
-	struct oap_client_config oap;
-
-	/* RFC1144 TCP/IP header compression */
-	struct {
-		int active;
-		int passive;
-		int s01;
-	} pcomp_rfc1144;
-
-	/* V.42vis data compression */
-	struct {
-		int active;
-		int passive;
-		int p0;
-		int p1;
-		int p2;
-	} dcomp_v42bis;
-
-	struct {
-		int rab_assign_addr_enc;
-	} iu;
-};
-
-struct sgsn_instance {
-	char *config_file;
-	struct sgsn_config cfg;
-	/* File descriptor wrappers for LibGTP */
-	struct osmo_fd gtp_fd0;
-	struct osmo_fd gtp_fd1c;
-	struct osmo_fd gtp_fd1u;
-	/* Timer for libGTP */
-	struct osmo_timer_list gtp_timer;
-	/* GSN instance for libgtp */
-	struct gsn_t *gsn;
-	/* Subscriber */
-	struct gsup_client *gsup_client;
-	/* LLME inactivity timer */
-	struct osmo_timer_list llme_timer;
-
-	/* c-ares event loop integration */
-	struct osmo_timer_list ares_timer;
-	struct llist_head ares_fds;
-	ares_channel ares_channel;
-	struct ares_addr_node *ares_servers;
-
-	struct rate_ctr_group *rate_ctrs;
-};
-
-extern struct sgsn_instance *sgsn;
-
-/* sgsn_vty.c */
-
-int sgsn_vty_init(struct sgsn_config *cfg);
-int sgsn_parse_config(const char *config_file);
-
-/* sgsn.c */
-
-/* Main input function for Gb proxy */
-int sgsn_rcvmsg(struct msgb *msg, struct gprs_nsvc *nsvc, uint16_t ns_bvci);
-
-
-struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
-					 struct sgsn_mm_ctx *mmctx,
-					 uint16_t nsapi,
-					 struct tlv_parsed *tp);
-int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx);
-void sgsn_pdp_upd_gtp_u(struct sgsn_pdp_ctx *pdp, void *addr, size_t alen);
-
-/* gprs_sndcp.c */
-
-/* Entry point for the SNSM-ACTIVATE.indication */
-int sndcp_sm_activate_ind(struct gprs_llc_lle *lle, uint8_t nsapi);
-/* Entry point for the SNSM-DEACTIVATE.indication */
-int sndcp_sm_deactivate_ind(struct gprs_llc_lle *lle, uint8_t nsapi);
-/* Called by SNDCP when it has received/re-assembled a N-PDU */
-int sgsn_rx_sndcp_ud_ind(struct gprs_ra_id *ra_id, int32_t tlli, uint8_t nsapi,
-			 struct msgb *msg, uint32_t npdu_len, uint8_t *npdu);
-int sndcp_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi,
-			void *mmcontext);
-int sndcp_llunitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
-			 uint8_t *hdr, uint16_t len);
-
-
-/*
- * CDR related functionality
- */
-int sgsn_cdr_init(struct sgsn_instance *sgsn);
-
-
-/*
- * C-ARES related functionality
- */
-int sgsn_ares_init(struct sgsn_instance *sgsn);
-int sgsn_ares_query(struct sgsn_instance *sgsm, const char *name, ares_host_callback cb, void *data);
-
-#endif
diff --git a/include/openbsc/signal.h b/include/openbsc/signal.h
deleted file mode 100644
index 49f86d6..0000000
--- a/include/openbsc/signal.h
+++ /dev/null
@@ -1,260 +0,0 @@
-/* Generic signalling/notification infrastructure */
-/* (C) 2009-2010, 2015 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009 by Harald Welte <laforge@gnumonks.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 OPENBSC_SIGNAL_H
-#define OPENBSC_SIGNAL_H
-
-#include <stdlib.h>
-#include <errno.h>
-
-#include <openbsc/gsm_data.h>
-
-#include <osmocom/core/signal.h>
-
-/*
- * Signalling subsystems
- */
-enum signal_subsystems {
-	SS_PAGING,
-	SS_SMS,
-	SS_ABISIP,
-	SS_NM,
-	SS_LCHAN,
-	SS_SUBSCR,
-	SS_SCALL,
-	SS_CHALLOC,
-	SS_IPAC_NWL,
-	SS_RF,
-	SS_MSC,
-	SS_HO,
-	SS_CCCH,
-	SS_SGSN,
-};
-
-/* SS_PAGING signals */
-enum signal_paging {
-	S_PAGING_SUCCEEDED,
-	S_PAGING_EXPIRED,
-};
-
-/* SS_SMS signals */
-enum signal_sms {
-	S_SMS_SUBMITTED,	/* A SMS has been successfully submitted to us */
-	S_SMS_DELIVERED,	/* A SMS has been successfully delivered to a MS */
-	S_SMS_SMMA,		/* A MS tells us it has more space available */
-	S_SMS_MEM_EXCEEDED,	/* A MS tells us it has no more space available */
-	S_SMS_UNKNOWN_ERROR,	/* A MS tells us it has an error */
-};
-
-/* SS_ABISIP signals */
-enum signal_abisip {
-	S_ABISIP_CRCX_ACK,
-	S_ABISIP_MDCX_ACK,
-	S_ABISIP_DLCX_IND,
-};
-
-/* SS_NM signals */
-enum signal_nm {
-	S_NM_SW_ACTIV_REP,	/* GSM 12.21 software activated report */
-	S_NM_FAIL_REP,		/* GSM 12.21 failure event report */
-	S_NM_NACK,		/* GSM 12.21 various NM_MT_*_NACK happened */
-	S_NM_IPACC_NACK,	/* GSM 12.21 nanoBTS extensions NM_MT_IPACC_*_*_NACK happened */
-	S_NM_IPACC_ACK,		/* GSM 12.21 nanoBTS extensions NM_MT_IPACC_*_*_ACK happened */
-	S_NM_IPACC_RESTART_ACK, /* nanoBTS has send a restart ack */
-	S_NM_IPACC_RESTART_NACK,/* nanoBTS has send a restart ack */
-	S_NM_TEST_REP,		/* GSM 12.21 Test Report */
-	S_NM_STATECHG_OPER,	/* Operational State changed*/
-	S_NM_STATECHG_ADM,	/* Administrative State changed */
-	S_NM_OM2K_CONF_RES,	/* OM2K Configuration Result */
-};
-
-/* SS_LCHAN signals */
-enum signal_lchan {
-	/*
-	 * The lchan got freed with an use_count != 0 and error
-	 * recovery needs to be carried out from within the
-	 * signal handler.
-	 */
-	S_LCHAN_UNEXPECTED_RELEASE,
-	S_LCHAN_ACTIVATE_ACK,		/* 08.58 Channel Activate ACK */
-	S_LCHAN_ACTIVATE_NACK,		/* 08.58 Channel Activate NACK */
-	S_LCHAN_HANDOVER_COMPL,		/* 04.08 Handover Completed */
-	S_LCHAN_HANDOVER_FAIL,		/* 04.08 Handover Failed */
-	S_LCHAN_HANDOVER_DETECT,	/* 08.58 Handover Detect */
-	S_LCHAN_MEAS_REP,		/* 08.58 Measurement Report */
-};
-
-/* SS_CHALLOC signals */
-enum signal_challoc {
-	S_CHALLOC_ALLOC_FAIL,	/* allocation of lchan has failed */
-	S_CHALLOC_FREED,	/* lchan has been successfully freed */
-};
-
-/* SS_SUBSCR signals */
-enum signal_subscr {
-	S_SUBSCR_ATTACHED,
-	S_SUBSCR_DETACHED,
-	S_SUBSCR_IDENTITY,		/* we've received some identity information */
-};
-
-/* SS_SCALL signals */
-enum signal_scall {
-	S_SCALL_SUCCESS,
-	S_SCALL_EXPIRED,
-	S_SCALL_DETACHED,
-};
-
-/* SS_IPAC_NWL signals */
-enum signal_ipaccess {
-	S_IPAC_NWL_COMPLETE,
-};
-
-enum signal_global {
-	S_GLOBAL_BTS_CLOSE_OM,
-};
-
-/* SS_RF signals */
-enum signal_rf {
-	S_RF_OFF,
-	S_RF_ON,
-	S_RF_GRACE,
-};
-
-struct paging_signal_data {
-	struct vlr_subscr *vsub;
-	struct gsm_bts *bts;
-
-	int paging_result;
-
-	/* NULL in case the paging didn't work */
-	struct gsm_subscriber_connection *conn;
-};
-
-struct scall_signal_data {
-	struct gsm_subscriber_connection *conn;
-	void *data;
-};
-
-struct ipacc_ack_signal_data {
-	struct gsm_bts_trx *trx;
-	uint8_t msg_type;
-};
-
-struct abis_om2k_mo;
-
-struct nm_statechg_signal_data {
-	struct gsm_bts *bts;
-	uint8_t obj_class;
-	void *obj;
-	struct gsm_nm_state *old_state;
-	struct gsm_nm_state *new_state;
-
-	/* This pointer is vaold for TS 12.21 MO */
-	struct abis_om_obj_inst *obj_inst;
-	/* This pointer is vaold for RBS2000 MO */
-	struct abis_om2k_mo *om2k_mo;
-};
-
-struct nm_om2k_signal_data {
-	struct gsm_bts *bts;
-	void *obj;
-	struct abis_om2k_mo *om2k_mo;
-
-	uint8_t accordance_ind;
-};
-
-struct nm_nack_signal_data {
-	struct msgb *msg;
-	struct gsm_bts *bts;
-	uint8_t mt;
-};
-
-struct challoc_signal_data {
-	struct gsm_bts *bts;
-	struct gsm_lchan *lchan;
-	enum gsm_chan_t type;
-};
-
-struct rf_signal_data {
-	struct gsm_network *net;
-};
-
-struct sms_signal_data {
-	/* The transaction where this occured */
-	struct gsm_trans *trans;
-	/* Can be NULL for SMMA */
-	struct gsm_sms *sms;
-	/* int paging result. Only the ones with > 0 */
-	int paging_result;
-};
-
-struct lchan_signal_data {
-	/* The lchan the signal happened on */
-	struct gsm_lchan *lchan;
-	/* Measurement reports on this lchan */
-	struct gsm_meas_rep *mr;
-};
-
-/* MSC signals */
-enum signal_msc {
-	S_MSC_LOST,
-	S_MSC_CONNECTED,
-	S_MSC_AUTHENTICATED,
-};
-
-struct bsc_msc_data;
-struct msc_signal_data {
-	struct bsc_msc_data *data;
-};
-
-/* SS_CCCH signals */
-enum signal_ccch {
-	S_CCCH_PAGING_LOAD,
-	S_CCCH_RACH_LOAD,
-};
-
-struct ccch_signal_data {
-	struct gsm_bts *bts;
-	uint16_t pg_buf_space;
-	uint16_t rach_slot_count;
-	uint16_t rach_busy_count;
-	uint16_t rach_access_count;
-};
-
-/* GPRS SGSN signals SS_SGSN */
-enum signal_sgsn {
-	S_SGSN_ATTACH,
-	S_SGSN_DETACH,
-	S_SGSN_UPDATE,
-	S_SGSN_PDP_ACT,
-	S_SGSN_PDP_DEACT,
-	S_SGSN_PDP_TERMINATE,
-	S_SGSN_PDP_FREE,
-	S_SGSN_MM_FREE,
-};
-
-struct sgsn_mm_ctx;
-struct sgsn_signal_data {
-	struct sgsn_mm_ctx *mm;
-	struct sgsn_pdp_ctx *pdp;	/* non-NULL for PDP_ACT, PDP_DEACT, PDP_FREE */
-};
-
-#endif
diff --git a/include/openbsc/silent_call.h b/include/openbsc/silent_call.h
deleted file mode 100644
index 5fec77b..0000000
--- a/include/openbsc/silent_call.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef _SILENT_CALL_H
-#define _SILENT_CALL_H
-
-struct gsm_subscriber_connection;
-
-extern int gsm_silent_call_start(struct vlr_subscr *vsub,
-                                 void *data, int type);
-extern int gsm_silent_call_stop(struct vlr_subscr *vsub);
-
-#if 0
-extern int silent_call_rx(struct gsm_subscriber_connection *conn, struct msgb *msg);
-extern int silent_call_reroute(struct gsm_subscriber_connection *conn, struct msgb *msg);
-#endif
-
-#endif /* _SILENT_CALL_H */
diff --git a/include/openbsc/slhc.h b/include/openbsc/slhc.h
deleted file mode 100644
index cd5a47c..0000000
--- a/include/openbsc/slhc.h
+++ /dev/null
@@ -1,187 +0,0 @@
-#ifndef _SLHC_H
-#define _SLHC_H
-/*
- * Definitions for tcp compression routines.
- *
- * $Header: slcompress.h,v 1.10 89/12/31 08:53:02 van Exp $
- *
- * Copyright (c) 1989 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- *	Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
- *	- Initial distribution.
- *
- *
- * modified for KA9Q Internet Software Package by
- * Katie Stevens (dkstevens@ucdavis.edu)
- * University of California, Davis
- * Computing Services
- *	- 01-31-90	initial adaptation
- *
- *	- Feb 1991	Bill_Simpson@um.cc.umich.edu
- *			variable number of conversation slots
- *			allow zero or one slots
- *			separate routines
- *			status display
- */
-
-/*
- * Compressed packet format:
- *
- * The first octet contains the packet type (top 3 bits), TCP
- * 'push' bit, and flags that indicate which of the 4 TCP sequence
- * numbers have changed (bottom 5 bits).  The next octet is a
- * conversation number that associates a saved IP/TCP header with
- * the compressed packet.  The next two octets are the TCP checksum
- * from the original datagram.  The next 0 to 15 octets are
- * sequence number changes, one change per bit set in the header
- * (there may be no changes and there are two special cases where
- * the receiver implicitly knows what changed -- see below).
- *
- * There are 5 numbers which can change (they are always inserted
- * in the following order): TCP urgent pointer, window,
- * acknowledgment, sequence number and IP ID.  (The urgent pointer
- * is different from the others in that its value is sent, not the
- * change in value.)  Since typical use of SLIP links is biased
- * toward small packets (see comments on MTU/MSS below), changes
- * use a variable length coding with one octet for numbers in the
- * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the
- * range 256 - 65535 or 0.  (If the change in sequence number or
- * ack is more than 65535, an uncompressed packet is sent.)
- */
-
-/*
- * Packet types (must not conflict with IP protocol version)
- *
- * The top nibble of the first octet is the packet type.  There are
- * three possible types: IP (not proto TCP or tcp with one of the
- * control flags set); uncompressed TCP (a normal IP/TCP packet but
- * with the 8-bit protocol field replaced by an 8-bit connection id --
- * this type of packet syncs the sender & receiver); and compressed
- * TCP (described above).
- *
- * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and
- * is logically part of the 4-bit "changes" field that follows.  Top
- * three bits are actual packet type.  For backward compatibility
- * and in the interest of conserving bits, numbers are chosen so the
- * IP protocol version number (4) which normally appears in this nibble
- * means "IP packet".
- */
-
-
-#include <linux/ip.h>
-#include <linux/tcp.h>
-
-/* SLIP compression masks for len/vers byte */
-#define SL_TYPE_IP 0x40
-#define SL_TYPE_UNCOMPRESSED_TCP 0x70
-#define SL_TYPE_COMPRESSED_TCP 0x80
-#define SL_TYPE_ERROR 0x00
-
-/* Bits in first octet of compressed packet */
-#define NEW_C	0x40	/* flag bits for what changed in a packet */
-#define NEW_I	0x20
-#define NEW_S	0x08
-#define NEW_A	0x04
-#define NEW_W	0x02
-#define NEW_U	0x01
-
-/* reserved, special-case values of above */
-#define SPECIAL_I (NEW_S|NEW_W|NEW_U)		/* echoed interactive traffic */
-#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U)	/* unidirectional data */
-#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U)
-
-#define TCP_PUSH_BIT 0x10
-
-/*
- * data type and sizes conversion assumptions:
- *
- *	VJ code		KA9Q style	generic
- *	u_char		byte_t		unsigned char	 8 bits
- *	u_short		int16		unsigned short	16 bits
- *	u_int		int16		unsigned short	16 bits
- *	u_long		unsigned long	unsigned long	32 bits
- *	int		int32		long		32 bits
- */
-
-typedef __u8 byte_t;
-typedef __u32 int32;
-
-/*
- * "state" data for each active tcp conversation on the wire.  This is
- * basically a copy of the entire IP/TCP header from the last packet
- * we saw from the conversation together with a small identifier
- * the transmit & receive ends of the line use to locate saved header.
- */
-struct cstate {
-	byte_t	cs_this;	/* connection id number (xmit) */
-	struct cstate *next;	/* next in ring (xmit) */
-	struct iphdr cs_ip;	/* ip/tcp hdr from most recent packet */
-	struct tcphdr cs_tcp;
-	unsigned char cs_ipopt[64];
-	unsigned char cs_tcpopt[64];
-	int cs_hsize;
-};
-#define NULLSLSTATE	(struct cstate *)0
-
-/*
- * all the state data for one serial line (we need one of these per line).
- */
-struct slcompress {
-	struct cstate *tstate;	/* transmit connection states (array)*/
-	struct cstate *rstate;	/* receive connection states (array)*/
-
-	byte_t tslot_limit;	/* highest transmit slot id (0-l)*/
-	byte_t rslot_limit;	/* highest receive slot id (0-l)*/
-
-	byte_t xmit_oldest;	/* oldest xmit in ring */
-	byte_t xmit_current;	/* most recent xmit id */
-	byte_t recv_current;	/* most recent rcvd id */
-
-	byte_t flags;
-#define SLF_TOSS	0x01	/* tossing rcvd frames until id received */
-
-	int32 sls_o_nontcp;	/* outbound non-TCP packets */
-	int32 sls_o_tcp;	/* outbound TCP packets */
-	int32 sls_o_uncompressed;	/* outbound uncompressed packets */
-	int32 sls_o_compressed;	/* outbound compressed packets */
-	int32 sls_o_searches;	/* searches for connection state */
-	int32 sls_o_misses;	/* times couldn't find conn. state */
-
-	int32 sls_i_uncompressed;	/* inbound uncompressed packets */
-	int32 sls_i_compressed;	/* inbound compressed packets */
-	int32 sls_i_error;	/* inbound error packets */
-	int32 sls_i_tossed;	/* inbound packets tossed because of error */
-
-	int32 sls_i_runt;
-	int32 sls_i_badcheck;
-};
-#define NULLSLCOMPR	(struct slcompress *)0
-
-/* In slhc.c: */
-struct slcompress *slhc_init(const void *ctx, int rslots, int tslots);
-
-void slhc_free(struct slcompress *comp);
-
-int slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
-		  unsigned char *ocp, unsigned char **cpp, int compress_cid);
-int slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize);
-int slhc_remember(struct slcompress *comp, unsigned char *icp, int isize);
-int slhc_toss(struct slcompress *comp);
-
-void slhc_i_status(struct slcompress *comp);
-void slhc_o_status(struct slcompress *comp);
-
-#endif	/* _SLHC_H */
diff --git a/include/openbsc/smpp.h b/include/openbsc/smpp.h
deleted file mode 100644
index bcdac8f..0000000
--- a/include/openbsc/smpp.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-
-int smpp_openbsc_alloc_init(void *ctx);
-int smpp_openbsc_start(struct gsm_network *net);
diff --git a/include/openbsc/sms_queue.h b/include/openbsc/sms_queue.h
deleted file mode 100644
index 2a8bd58..0000000
--- a/include/openbsc/sms_queue.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef SMS_QUEUE_H
-#define SMS_QUEUE_H
-
-struct gsm_network;
-struct gsm_sms_queue;
-struct vty;
-
-int sms_queue_start(struct gsm_network *, int in_flight);
-int sms_queue_trigger(struct gsm_sms_queue *);
-
-/* vty helper functions */
-int sms_queue_stats(struct gsm_sms_queue *, struct vty* vty);
-int sms_queue_set_max_pending(struct gsm_sms_queue *, int max);
-int sms_queue_set_max_failure(struct gsm_sms_queue *, int fail);
-int sms_queue_clear(struct gsm_sms_queue *);
-
-#endif
diff --git a/include/openbsc/socket.h b/include/openbsc/socket.h
deleted file mode 100644
index 0fd85f1..0000000
--- a/include/openbsc/socket.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _BSC_SOCKET_H
-#define _BSC_SOCKET_H
-
-#include <osmocom/core/select.h>
-
-#ifndef IPPROTO_GRE
-#define IPPROTO_GRE 47
-#endif
-
-int make_sock(struct osmo_fd *bfd, int proto,
-	      uint32_t ip, uint16_t port, int priv_nr,
-	      int (*cb)(struct osmo_fd *fd, unsigned int what), void *data);
-
-#endif /* _BSC_SOCKET_H */
diff --git a/include/openbsc/system_information.h b/include/openbsc/system_information.h
deleted file mode 100644
index 71bea26..0000000
--- a/include/openbsc/system_information.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef _SYSTEM_INFO_H
-#define _SYSTEM_INFO_H
-
-#include <osmocom/gsm/sysinfo.h>
-
-#include <openbsc/arfcn_range_encode.h>
-
-struct gsm_bts;
-
-int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type type);
-size_t si2q_earfcn_count(const struct osmo_earfcn_si2q *e);
-unsigned range1024_p(unsigned n);
-unsigned range512_q(unsigned m);
-int range_encode(enum gsm48_range r, int *arfcns, int arfcns_used, int *w,
-		 int f0, uint8_t *chan_list);
-uint8_t si2q_num(struct gsm_bts *bts);
-int bts_earfcn_add(struct gsm_bts *bts, uint16_t earfcn, uint8_t thresh_hi, uint8_t thresh_lo, uint8_t prio,
-		   uint8_t qrx, uint8_t meas_bw);
-int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble);
-int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble,
-		   bool diversity);
-#endif
diff --git a/include/openbsc/transaction.h b/include/openbsc/transaction.h
deleted file mode 100644
index 4930fbd..0000000
--- a/include/openbsc/transaction.h
+++ /dev/null
@@ -1,103 +0,0 @@
-#ifndef _TRANSACT_H
-#define _TRANSACT_H
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_subscriber.h>
-#include <osmocom/core/linuxlist.h>
-#include <openbsc/gsm_04_11.h>
-#include <openbsc/mncc.h>
-#include <osmocom/gsm/gsm0411_smc.h>
-#include <osmocom/gsm/gsm0411_smr.h>
-
-enum bridge_state {
-	BRIDGE_STATE_NONE,
-	BRIDGE_STATE_LOOPBACK_PENDING,
-	BRIDGE_STATE_LOOPBACK_ESTABLISHED,
-	BRIDGE_STATE_BRIDGE_PENDING,
-	BRIDGE_STATE_BRIDGE_ESTABLISHED,
-};
-
-/* One transaction */
-struct gsm_trans {
-	/* Entry in list of all transactions */
-	struct llist_head entry;
-
-	/* Back pointer to the network struct */
-	struct gsm_network *net;
-
-	/* The protocol within which we live */
-	uint8_t protocol;
-
-	/* The current transaction ID */
-	uint8_t transaction_id;
-
-	/* To whom we belong, unique identifier of remote MM entity */
-	struct vlr_subscr *vsub;
-
-	/* The associated connection we are using to transmit messages */
-	struct gsm_subscriber_connection *conn;
-
-	/* reference from MNCC or other application */
-	uint32_t callref;
-
-	/* if traffic channel receive was requested */
-	int tch_recv;
-
-	/* is thats one paging? */
-	struct subscr_request *paging_request;
-
-	/* bearer capabilities (rate and codec) */
-	struct gsm_mncc_bearer_cap bearer_cap;
-
-	/* status of the assignment, true when done */
-	bool assignment_done;
-
-	/* if true, TCH_RTP_CREATE is sent after the
-	 * assignment is done */
-	bool tch_rtp_create;
-
-	union {
-		struct {
-
-			/* current call state */
-			int state;
-
-			/* current timer and message queue */
-			int Tcurrent;		/* current CC timer */
-			int T308_second;	/* used to send release again */
-			struct osmo_timer_list timer;
-			struct gsm_mncc msg;	/* stores setup/disconnect/release message */
-		} cc;
-		struct {
-			struct gsm411_smc_inst smc_inst;
-			struct gsm411_smr_inst smr_inst;
-
-			struct gsm_sms *sms;
-		} sms;
-	};
-
-	struct {
-		struct gsm_trans *peer;
-		enum bridge_state state;
-	} bridge;
-};
-
-
-
-struct gsm_trans *trans_find_by_id(struct gsm_subscriber_connection *conn,
-				   uint8_t proto, uint8_t trans_id);
-struct gsm_trans *trans_find_by_callref(struct gsm_network *net,
-					uint32_t callref);
-
-struct gsm_trans *trans_alloc(struct gsm_network *net,
-			      struct vlr_subscr *vsub,
-			      uint8_t protocol, uint8_t trans_id,
-			      uint32_t callref);
-void trans_free(struct gsm_trans *trans);
-
-int trans_assign_trans_id(struct gsm_network *net, struct vlr_subscr *vsub,
-			  uint8_t protocol, uint8_t ti_flag);
-struct gsm_trans *trans_has_conn(const struct gsm_subscriber_connection *conn);
-void trans_conn_closed(struct gsm_subscriber_connection *conn);
-
-#endif
diff --git a/include/openbsc/trau_mux.h b/include/openbsc/trau_mux.h
deleted file mode 100644
index 75c359b..0000000
--- a/include/openbsc/trau_mux.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Simple TRAU frame reflector to route voice calls */
-
-/* (C) 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/>.
- *
- */
-
-/* The "TRAU mux map" defines which particular 16kbit sub-slot (in which E1
- * timeslot on which E1 interface) should be directly muxed to which other 
- * sub-slot.  Entries in the mux map are always bi-directional. 
- *
- * The idea of all this is to directly switch voice channels in the BSC
- * from one phone to another.  We do this right now since we don't support
- * any external interface for voice channels, and in the future as an
- * optimization to routing them externally.
- */
-
-#include <stdint.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/mncc.h>
-
-struct decoded_trau_frame;
-
-/* map a TRAU mux map entry */
-int trau_mux_map(const struct gsm_e1_subslot *src,
-		 const struct gsm_e1_subslot *dst);
-int trau_mux_map_lchan(const struct gsm_lchan *src,	
-			const struct gsm_lchan *dst);
-
-/* unmap a TRAU mux map entry */
-int trau_mux_unmap(const struct gsm_e1_subslot *ss, uint32_t callref);
-
-/* we get called by subchan_demux */
-int trau_mux_input(struct gsm_e1_subslot *src_e1_ss,
-		   const uint8_t *trau_bits, int num_bits);
-
-/* add a trau receiver */
-int trau_recv_lchan(struct gsm_lchan *lchan, uint32_t callref);
-
-/* send trau from application */
-int trau_send_frame(struct gsm_lchan *lchan, struct gsm_data_frame *frame);
-
-/* switch trau muxer to new lchan */
-int switch_trau_mux(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan);
-
-/* callback invoked if we receive TRAU frames */
-int subch_cb(struct subch_demux *dmx, int ch, uint8_t *data, int len, void *_priv);
-
-/* TRAU frame transcoding */
-struct msgb *trau_decode_fr(uint32_t callref,
-	const struct decoded_trau_frame *tf);
-struct msgb *trau_decode_efr(uint32_t callref,
-	const struct decoded_trau_frame *tf);
-void trau_encode_fr(struct decoded_trau_frame *tf,
-	const unsigned char *data);
-void trau_encode_efr(struct decoded_trau_frame *tf,
-	const unsigned char *data);
diff --git a/include/openbsc/trau_upqueue.h b/include/openbsc/trau_upqueue.h
deleted file mode 100644
index ecc7658..0000000
--- a/include/openbsc/trau_upqueue.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _TRAU_UPQUEUE_H
-#define _TRAU_UPQUEUE_H
-
-void trau_tx_to_mncc(struct gsm_network *net, struct msgb *msg);
-
-#endif /* _TRAU_UPQUEUE_H */
-
diff --git a/include/openbsc/ussd.h b/include/openbsc/ussd.h
deleted file mode 100644
index 2665468..0000000
--- a/include/openbsc/ussd.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _USSD_H
-#define _USSD_H
-
-/* Handler function for mobile-originated USSD messages */
-
-#include <osmocom/core/msgb.h>
-
-int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg);
-
-#endif
diff --git a/include/openbsc/v42bis.h b/include/openbsc/v42bis.h
deleted file mode 100644
index 607a58e..0000000
--- a/include/openbsc/v42bis.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * SpanDSP - a series of DSP components for telephony
- *
- * v42bis.h
- *
- * Written by Steve Underwood <steveu@coppice.org>
- *
- * Copyright (C) 2005, 2011 Steve Underwood
- *
- * All rights reserved.
- *
- * This program 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 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*! \page v42bis_page V.42bis modem data compression
-\section v42bis_page_sec_1 What does it do?
-The v.42bis specification defines a data compression scheme, to work in
-conjunction with the error correction scheme defined in V.42.
-
-\section v42bis_page_sec_2 How does it work?
-*/
-
-#include <stdint.h>
-
-#if !defined(_SPANDSP_V42BIS_H_)
-#define _SPANDSP_V42BIS_H_
-
-#define SPAN_DECLARE(x) x
-
-#define V42BIS_MIN_STRING_SIZE      6
-#define V42BIS_MAX_STRING_SIZE      250
-#define V42BIS_MIN_DICTIONARY_SIZE  512
-#define V42BIS_MAX_BITS             12
-#define V42BIS_MAX_CODEWORDS        4096    /* 2^V42BIS_MAX_BITS */
-#define V42BIS_MAX_OUTPUT_LENGTH    1024
-
-enum
-{
-    V42BIS_P0_NEITHER_DIRECTION = 0,
-    V42BIS_P0_INITIATOR_RESPONDER,
-    V42BIS_P0_RESPONDER_INITIATOR,
-    V42BIS_P0_BOTH_DIRECTIONS
-};
-
-enum
-{
-    V42BIS_COMPRESSION_MODE_DYNAMIC = 0,
-    V42BIS_COMPRESSION_MODE_ALWAYS,
-    V42BIS_COMPRESSION_MODE_NEVER
-};
-
-typedef void (*put_msg_func_t)(void *user_data, const uint8_t *msg, int len);
-
-/*!
-    V.42bis compression/decompression descriptor. This defines the working state for a
-    single instance of V.42bis compress/decompression.
-*/
-typedef struct v42bis_state_s v42bis_state_t;
-
-#if defined(__cplusplus)
-extern "C"
-{
-#endif
-
-/*! Compress a block of octets.
-    \param s The V.42bis context.
-    \param buf The data to be compressed.
-    \param len The length of the data buffer.
-    \return 0 */
-SPAN_DECLARE(int) v42bis_compress(v42bis_state_t *s, const uint8_t buf[], int len);
-
-/*! Flush out any data remaining in a compression buffer.
-    \param s The V.42bis context.
-    \return 0 */
-SPAN_DECLARE(int) v42bis_compress_flush(v42bis_state_t *s);
-
-/*! Decompress a block of octets.
-    \param s The V.42bis context.
-    \param buf The data to be decompressed.
-    \param len The length of the data buffer.
-    \return 0 */
-SPAN_DECLARE(int) v42bis_decompress(v42bis_state_t *s, const uint8_t buf[], int len);
-    
-/*! Flush out any data remaining in the decompression buffer.
-    \param s The V.42bis context.
-    \return 0 */
-SPAN_DECLARE(int) v42bis_decompress_flush(v42bis_state_t *s);
-
-/*! Set the compression mode.
-    \param s The V.42bis context.
-    \param mode One of the V.42bis compression modes -
-            V42BIS_COMPRESSION_MODE_DYNAMIC,
-            V42BIS_COMPRESSION_MODE_ALWAYS,
-            V42BIS_COMPRESSION_MODE_NEVER */
-SPAN_DECLARE(void) v42bis_compression_control(v42bis_state_t *s, int mode);
-
-/*! Initialise a V.42bis context.
-    \param s The V.42bis context.
-    \param negotiated_p0 The negotiated P0 parameter, from the V.42bis spec.
-    \param negotiated_p1 The negotiated P1 parameter, from the V.42bis spec.
-    \param negotiated_p2 The negotiated P2 parameter, from the V.42bis spec.
-    \param encode_handler Encode callback handler.
-    \param encode_user_data An opaque pointer passed to the encode callback handler.
-    \param max_encode_len The maximum length that should be passed to the encode handler.
-    \param decode_handler Decode callback handler.
-    \param decode_user_data An opaque pointer passed to the decode callback handler.
-    \param max_decode_len The maximum length that should be passed to the decode handler.
-    \return The V.42bis context. */
-SPAN_DECLARE(v42bis_state_t *) v42bis_init(const void *ctx,
-                                           v42bis_state_t *s,
-                                           int negotiated_p0,
-                                           int negotiated_p1,
-                                           int negotiated_p2,
-                                           put_msg_func_t encode_handler,
-                                           void *encode_user_data,
-                                           int max_encode_len,
-                                           put_msg_func_t decode_handler,
-                                           void *decode_user_data,
-                                           int max_decode_len);
-
-/*! Release a V.42bis context.
-    \param s The V.42bis context.
-    \return 0 if OK */
-SPAN_DECLARE(int) v42bis_release(v42bis_state_t *s);
-
-/*! Free a V.42bis context.
-    \param s The V.42bis context.
-    \return 0 if OK */
-SPAN_DECLARE(int) v42bis_free(v42bis_state_t *s);
-
-#if defined(__cplusplus)
-}
-#endif
-
-#endif
-/*- End of file ------------------------------------------------------------*/
diff --git a/include/openbsc/v42bis_private.h b/include/openbsc/v42bis_private.h
deleted file mode 100644
index daa5ea3..0000000
--- a/include/openbsc/v42bis_private.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * SpanDSP - a series of DSP components for telephony
- *
- * private/v42bis.h
- *
- * Written by Steve Underwood <steveu@coppice.org>
- *
- * Copyright (C) 2005 Steve Underwood
- *
- * All rights reserved.
- *
- * This program 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 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#if !defined(_SPANDSP_PRIVATE_V42BIS_H_)
-#define _SPANDSP_PRIVATE_V42BIS_H_
-
-/*!
-    V.42bis dictionary node.
-    Note that 0 is not a valid node to point to (0 is always a control code), so 0 is used
-    as a "no such value" marker in this structure.
-*/
-typedef struct
-{
-    /*! \brief The value of the octet represented by the current dictionary node */
-    uint8_t node_octet;
-    /*! \brief The parent of this node */
-    uint16_t parent;
-    /*! \brief The first child of this node */
-    uint16_t child;
-    /*! \brief The next node at the same depth */
-    uint16_t next;
-} v42bis_dict_node_t;
-
-/*!
-    V.42bis compression or decompression. This defines the working state for a single instance
-    of V.42bis compression or decompression.
-*/
-typedef struct
-{
-    /*! \brief Compression enabled. */
-    int v42bis_parm_p0;
-    /*! \brief Compression mode. */
-    int compression_mode;
-    /*! \brief Callback function to handle output data. */
-    put_msg_func_t handler;
-    /*! \brief An opaque pointer passed in calls to the data handler. */
-    void *user_data;
-    /*! \brief The maximum amount to be passed to the data handler. */
-    int max_output_len;
-
-    /*! \brief TRUE if we are in transparent (i.e. uncompressable) mode */
-    int transparent;
-    /*! \brief Next empty dictionary entry */
-    uint16_t v42bis_parm_c1;
-    /*! \brief Current codeword size */
-    uint16_t v42bis_parm_c2;
-    /*! \brief Threshold for codeword size change */
-    uint16_t v42bis_parm_c3;
-    /*! \brief The current update point in the dictionary */
-    uint16_t update_at;
-    /*! \brief The last entry matched in the dictionary */
-    uint16_t last_matched;
-    /*! \brief The last entry added to the dictionary */
-    uint16_t last_added;
-    /*! \brief Total number of codewords in the dictionary */
-    int v42bis_parm_n2;
-    /*! \brief Maximum permitted string length */
-    int v42bis_parm_n7;
-    /*! \brief The dictionary */
-    v42bis_dict_node_t dict[V42BIS_MAX_CODEWORDS];
-
-    /*! \brief The octet string in progress */
-    uint8_t string[V42BIS_MAX_STRING_SIZE];
-    /*! \brief The current length of the octet string in progress */
-    int string_length;
-    /*! \brief The amount of the octet string in progress which has already
-        been flushed out of the buffer */
-    int flushed_length;
-
-    /*! \brief Compression performance metric */
-    uint16_t compression_performance;
-
-    /*! \brief Outgoing bit buffer (compression), or incoming bit buffer (decompression) */ 
-    uint32_t bit_buffer;
-    /*! \brief Outgoing bit count (compression), or incoming bit count (decompression) */ 
-    int bit_count;
-
-    /*! \brief The output composition buffer */
-    uint8_t output_buf[V42BIS_MAX_OUTPUT_LENGTH];
-    /*! \brief The length of the contents of the output composition buffer */    
-    int output_octet_count;
-
-    /*! \brief The current value of the escape code */
-    uint8_t escape_code;
-    /*! \brief TRUE if we just hit an escape code, and are waiting for the following octet */
-    int escaped;
-} v42bis_comp_state_t;
-
-/*!
-    V.42bis compression/decompression descriptor. This defines the working state for a
-    single instance of V.42bis compress/decompression.
-*/
-struct v42bis_state_s
-{
-    /*! \brief Compression state. */
-    v42bis_comp_state_t compress;
-    /*! \brief Decompression state. */
-    v42bis_comp_state_t decompress;
-
-    /*! \brief Error and flow logging control */
-};
-
-#endif
-/*- End of file ------------------------------------------------------------*/
diff --git a/include/openbsc/vlr.h b/include/openbsc/vlr.h
deleted file mode 100644
index 619971a..0000000
--- a/include/openbsc/vlr.h
+++ /dev/null
@@ -1,422 +0,0 @@
-#pragma once
-
-#include <stdint.h>
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/fsm.h>
-#include <osmocom/core/logging.h>
-#include <osmocom/gsm/protocol/gsm_23_003.h>
-#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
-#include <osmocom/gsm/gsm23003.h>
-#include <openbsc/gsm_data.h>
-// for GSM_NAME_LENGTH
-#include <openbsc/gsm_subscriber.h>
-
-struct log_target;
-
-/* from 3s to 10s */
-#define GSM_29002_TIMER_S	10
-/* from 15s to 30s */
-#define GSM_29002_TIMER_M	30
-/* from 1min to 10min */
-#define GSM_29002_TIMER_ML	(10*60)
-/* from 28h to 38h */
-#define GSM_29002_TIMER_L	(32*60*60)
-
-/* VLR subscriber authentication state */
-enum vlr_subscr_auth_state {
-	/* subscriber needs to be autenticated */
-	VLR_SUB_AS_NEEDS_AUTH,
-	/* waiting for AuthInfo from HLR/AUC */
-	VLR_SUB_AS_NEEDS_AUTH_WAIT_AI,
-	/* waiting for response from subscriber */
-	VLR_SUB_AS_WAIT_RESP,
-	/* successfully authenticated */
-	VLR_SUB_AS_AUTHENTICATED,
-	/* subscriber needs re-sync */
-	VLR_SUB_AS_NEEDS_RESYNC,
-	/* waiting for AuthInfo with ReSync */
-	VLR_SUB_AS_NEEDS_AUTH_WAIT_SAI_RESYNC,
-	/* waiting for response from subscr, resync case */
-	VLR_SUB_AS_WAIT_RESP_RESYNC,
-	/* waiting for IMSI from subscriber */
-	VLR_SUB_AS_WAIT_ID_IMSI,
-	/* authentication has failed */
-	VLR_SUB_AS_AUTH_FAILED,
-};
-
-enum vlr_lu_event {
-	VLR_ULA_E_UPDATE_LA,	/* Initial trigger (LU from MS) */
-	VLR_ULA_E_SEND_ID_ACK,	/* Result of Send-ID from PVLR */
-	VLR_ULA_E_SEND_ID_NACK,	/* Result of Send-ID from PVLR */
-	VLR_ULA_E_AUTH_RES,	/* Result of auth procedure */
-	VLR_ULA_E_CIPH_RES,	/* Result of Ciphering Mode Command */
-	VLR_ULA_E_ID_IMSI,	/* IMSI recieved from MS */
-	VLR_ULA_E_ID_IMEI,	/* IMEI received from MS */
-	VLR_ULA_E_ID_IMEISV,	/* IMEISV received from MS */
-	VLR_ULA_E_HLR_LU_RES,	/* HLR UpdateLocation result */
-	VLR_ULA_E_UPD_HLR_COMPL,/* UpdatE_HLR_VLR result */
-	VLR_ULA_E_LU_COMPL_SUCCESS,/* Location_Update_Completion_VLR result */
-	VLR_ULA_E_LU_COMPL_FAILURE,/* Location_Update_Completion_VLR result */
-	VLR_ULA_E_NEW_TMSI_ACK,	/* TMSI Reallocation Complete */
-};
-
-enum vlr_ciph_result_cause {
-	VLR_CIPH_REJECT, /* ? */
-	VLR_CIPH_COMPL,
-};
-
-struct vlr_ciph_result {
-	enum vlr_ciph_result_cause cause;
-	const char *imeisv;
-};
-
-enum vlr_subscr_security_context {
-	VLR_SEC_CTX_NONE,
-	VLR_SEC_CTX_GSM,
-	VLR_SEC_CTX_UMTS,
-};
-
-enum vlr_lu_type {
-	VLR_LU_TYPE_PERIODIC,
-	VLR_LU_TYPE_IMSI_ATTACH,
-	VLR_LU_TYPE_REGULAR,
-};
-
-#define OSMO_LBUF_DECL(name, xlen)		\
-	struct {				\
-		uint8_t buf[xlen];		\
-		size_t len;			\
-	} name
-
-struct sgsn_mm_ctx;
-struct vlr_instance;
-
-/* The VLR subscriber is the part of the GSM subscriber state in VLR (CS) or
- * SGSN (PS), particularly while interacting with the HLR via GSUP */
-struct vlr_subscr {
-	struct llist_head list;
-	struct vlr_instance *vlr;
-
-	/* TODO either populate from HLR or drop this completely? */
-	long long unsigned int id;
-
-	/* Data from HLR */				/* 3GPP TS 23.008 */
-	/* Always use vlr_subscr_set_imsi() to write to imsi[] */
-	char imsi[GSM23003_IMSI_MAX_DIGITS+1];		/* 2.1.1.1 */
-	char msisdn[GSM_EXTENSION_LENGTH+1];		/* 2.1.2 */
-	char name[GSM_NAME_LENGTH+1];			/* proprietary */
-	OSMO_LBUF_DECL(hlr, 16);			/* 2.4.7 */
-	uint32_t periodic_lu_timer;			/* 2.4.24 */
-	uint32_t age_indicator;				/* 2.17.1 */
-
-	/* Authentication Data */
-	struct gsm_auth_tuple auth_tuples[5];		/* 2.3.1-2.3.4 */
-	struct gsm_auth_tuple *last_tuple;
-	enum vlr_subscr_security_context sec_ctx;
-
-	/* Data local to VLR is below */
-	uint32_t tmsi;					/* 2.1.4 */
-	/* Newly allocated TMSI that was not yet acked by MS */
-	uint32_t tmsi_new;
-
-	/* some redundancy in information below? */
-	struct osmo_cell_global_id cgi;			/* 2.4.16 */
-	uint16_t lac;					/* 2.4.2 */
-
-	char imeisv[GSM23003_IMEISV_NUM_DIGITS+1];	/* 2.2.3 */
-	char imei[GSM23003_IMEISV_NUM_DIGITS+1];	/* 2.1.9 */
-	bool imsi_detached_flag;			/* 2.7.1 */
-	bool conf_by_radio_contact_ind;			/* 2.7.4.1 */
-	bool sub_dataconf_by_hlr_ind;			/* 2.7.4.2 */
-	bool loc_conf_in_hlr_ind;			/* 2.7.4.3 */
-	bool dormant_ind;				/* 2.7.8 */
-	bool cancel_loc_rx;				/* 2.7.8A */
-	bool ms_not_reachable_flag;			/* 2.10.2 (MNRF) */
-	bool la_allowed;
-
-	int use_count;
-	time_t expire_lu;	/* FIXME: overlap with periodic_lu_timer/age_indicator */
-
-	struct osmo_fsm_inst *lu_fsm;
-	struct osmo_fsm_inst *auth_fsm;
-	struct osmo_fsm_inst *proc_arq_fsm;
-
-	bool lu_complete;
-
-	void *msc_conn_ref;
-
-	/* PS (SGSN) specific parts */
-	struct {
-		struct llist_head pdp_list;
-		uint8_t rac;
-		uint8_t sac;
-		struct gprs_mm_ctx *mmctx;
-	} ps;
-	/* CS (NITB/CSCN) specific parts */
-	struct {
-		/* pending requests */
-		bool is_paging;
-		/* list of struct subscr_request */
-		struct llist_head requests;
-		uint8_t lac;
-		enum ran_type attached_via_ran;
-	} cs;
-};
-
-enum vlr_proc_arq_result;
-
-enum vlr_ciph {
-	VLR_CIPH_NONE, /*< A5/0, no encryption */
-	VLR_CIPH_A5_1, /*< A5/1, encryption */
-	VLR_CIPH_A5_2, /*< A5/2, deprecated export-grade encryption */
-	VLR_CIPH_A5_3, /*< A5/3, 'new secure' encryption */
-};
-
-struct vlr_ops {
-	/* encode + transmit an AUTH REQ towards the MS.
-	 * \param[in] at  auth tuple providing rand, key_seq and autn.
-	 * \param[in] send_autn  True to send AUTN, for r99 UMTS auth.
-	 */
-	int (*tx_auth_req)(void *msc_conn_ref, struct gsm_auth_tuple *at,
-			   bool send_autn);
-	/* encode + transmit an AUTH REJECT towards the MS */
-	int (*tx_auth_rej)(void *msc_conn_ref);
-
-	/* encode + transmit an IDENTITY REQUEST towards the MS */
-	int (*tx_id_req)(void *msc_conn_ref, uint8_t mi_type);
-
-	int (*tx_lu_acc)(void *msc_conn_ref, uint32_t send_tmsi);
-	int (*tx_lu_rej)(void *msc_conn_ref, uint8_t cause);
-	int (*tx_cm_serv_acc)(void *msc_conn_ref);
-	int (*tx_cm_serv_rej)(void *msc_conn_ref, enum vlr_proc_arq_result result);
-
-	int (*set_ciph_mode)(void *msc_conn_ref, enum vlr_ciph ciph_mode,
-			     bool retrieve_imeisv);
-
-	/* UTRAN: send Common Id (when auth+ciph are complete) */
-	int (*tx_common_id)(void *msc_conn_ref);
-
-
-	/* notify MSC/SGSN that the subscriber data in VLR has been updated */
-	void (*subscr_update)(struct vlr_subscr *vsub);
-	/* notify MSC/SGSN that the given subscriber has been associated
-	 * with this msc_conn_ref */
-	void (*subscr_assoc)(void *msc_conn_ref, struct vlr_subscr *vsub);
-};
-
-enum vlr_timer {
-	VLR_T_3250,
-	VLR_T_3260,
-	VLR_T_3270,
-	_NUM_VLR_TIMERS
-};
-
-/* An instance of the VLR codebase */
-struct vlr_instance {
-	struct llist_head subscribers;
-	struct llist_head operations;
-	struct gsup_client *gsup_client;
-	struct vlr_ops ops;
-	struct {
-		bool retrieve_imeisv_early;
-		bool retrieve_imeisv_ciphered;
-		bool assign_tmsi;
-		bool check_imei_rqd;
-		int auth_tuple_max_use_count;
-		bool auth_reuse_old_sets_on_error;
-		bool parq_retrieve_imsi;
-		bool is_ps;
-		uint32_t timer[_NUM_VLR_TIMERS];
-	} cfg;
-	/* A free-form pointer for use by the caller */
-	void *user_ctx;
-};
-
-extern const struct value_string vlr_ciph_names[];
-static inline const char *vlr_ciph_name(enum vlr_ciph val)
-{
-	return get_value_string(vlr_ciph_names, val);
-}
-
-/* Location Updating request */
-struct osmo_fsm_inst *
-vlr_loc_update(struct osmo_fsm_inst *parent,
-	       uint32_t parent_event_success,
-	       uint32_t parent_event_failure,
-	       void *parent_event_data,
-	       struct vlr_instance *vlr, void *msc_conn_ref,
-	       enum vlr_lu_type type, uint32_t tmsi, const char *imsi,
-	       const struct osmo_location_area_id *old_lai,
-	       const struct osmo_location_area_id *new_lai,
-	       bool authentication_required,
-	       enum vlr_ciph ciphering_required,
-	       bool is_r99, bool is_utran,
-	       bool assign_tmsi);
-
-void vlr_loc_update_conn_timeout(struct osmo_fsm_inst *fi);
-
-/* tell the VLR that the subscriber connection is gone */
-int vlr_subscr_disconnected(struct vlr_subscr *vsub);
-
-int vlr_subscr_rx_id_resp(struct vlr_subscr *vsub, const uint8_t *mi, size_t mi_len);
-int vlr_subscr_rx_auth_resp(struct vlr_subscr *vsub, bool is_r99, bool is_utran,
-			    const uint8_t *res, uint8_t res_len);
-int vlr_subscr_rx_auth_fail(struct vlr_subscr *vsub, const uint8_t *auts);
-int vlr_subscr_tx_auth_fail_rep(struct vlr_subscr *vsub);
-void vlr_subscr_rx_ciph_res(struct vlr_subscr *vsub, struct vlr_ciph_result *res);
-int vlr_subscr_rx_tmsi_reall_compl(struct vlr_subscr *vsub);
-int vlr_subscr_rx_imsi_detach(struct vlr_subscr *vsub);
-void vlr_subscr_conn_timeout(struct vlr_subscr *vsub);
-
-struct vlr_instance *vlr_alloc(void *ctx, const struct vlr_ops *ops);
-int vlr_start(const char *gsup_unit_name, struct vlr_instance *vlr,
-	      const char *gsup_server_addr_str, uint16_t gsup_server_port);
-
-/* internal use only */
-
-struct osmo_fsm_inst *sub_pres_vlr_fsm_start(struct osmo_fsm_inst *parent,
-					     struct vlr_subscr *vsub,
-					     uint32_t term_event);
-struct osmo_fsm_inst *
-upd_hlr_vlr_proc_start(struct osmo_fsm_inst *parent,
-		       struct vlr_subscr *vsub,
-		       uint32_t parent_event);
-
-struct osmo_fsm_inst *
-lu_compl_vlr_proc_start(struct osmo_fsm_inst *parent,
-			struct vlr_subscr *vsub,
-			void *msc_conn_ref,
-			uint32_t parent_event_success,
-			uint32_t parent_event_failure);
-
-
-const char *vlr_subscr_name(struct vlr_subscr *vsub);
-const char *vlr_subscr_msisdn_or_name(struct vlr_subscr *vsub);
-
-#define vlr_subscr_find_by_imsi(vlr, imsi) \
-	_vlr_subscr_find_by_imsi(vlr, imsi, __BASE_FILE__, __LINE__)
-#define vlr_subscr_find_or_create_by_imsi(vlr, imsi, created) \
-	_vlr_subscr_find_or_create_by_imsi(vlr, imsi, created, \
-					   __BASE_FILE__, __LINE__)
-
-#define vlr_subscr_find_by_tmsi(vlr, tmsi) \
-	_vlr_subscr_find_by_tmsi(vlr, tmsi, __BASE_FILE__, __LINE__)
-#define vlr_subscr_find_or_create_by_tmsi(vlr, tmsi, created) \
-	_vlr_subscr_find_or_create_by_tmsi(vlr, tmsi, created, \
-					   __BASE_FILE__, __LINE__)
-
-#define vlr_subscr_find_by_msisdn(vlr, msisdn) \
-	_vlr_subscr_find_by_msisdn(vlr, msisdn, __BASE_FILE__, __LINE__)
-
-struct vlr_subscr *_vlr_subscr_find_by_imsi(struct vlr_instance *vlr,
-					    const char *imsi,
-					    const char *file, int line);
-struct vlr_subscr *_vlr_subscr_find_or_create_by_imsi(struct vlr_instance *vlr,
-						      const char *imsi,
-						      bool *created,
-						      const char *file,
-						      int line);
-
-struct vlr_subscr *_vlr_subscr_find_by_tmsi(struct vlr_instance *vlr,
-					    uint32_t tmsi,
-					    const char *file, int line);
-struct vlr_subscr *_vlr_subscr_find_or_create_by_tmsi(struct vlr_instance *vlr,
-						      uint32_t tmsi,
-						      bool *created,
-						      const char *file,
-						      int line);
-
-struct vlr_subscr *_vlr_subscr_find_by_msisdn(struct vlr_instance *vlr,
-					      const char *msisdn,
-					      const char *file, int line);
-
-#define vlr_subscr_get(sub) _vlr_subscr_get(sub, __BASE_FILE__, __LINE__)
-#define vlr_subscr_put(sub) _vlr_subscr_put(sub, __BASE_FILE__, __LINE__)
-struct vlr_subscr *_vlr_subscr_get(struct vlr_subscr *sub, const char *file, int line);
-struct vlr_subscr *_vlr_subscr_put(struct vlr_subscr *sub, const char *file, int line);
-
-struct vlr_subscr *vlr_subscr_alloc(struct vlr_instance *vlr);
-void vlr_subscr_free(struct vlr_subscr *vsub);
-int vlr_subscr_alloc_tmsi(struct vlr_subscr *vsub);
-
-void vlr_subscr_set_imsi(struct vlr_subscr *vsub, const char *imsi);
-void vlr_subscr_set_imei(struct vlr_subscr *vsub, const char *imei);
-void vlr_subscr_set_imeisv(struct vlr_subscr *vsub, const char *imeisv);
-void vlr_subscr_set_msisdn(struct vlr_subscr *vsub, const char *msisdn);
-
-bool vlr_subscr_matches_imsi(struct vlr_subscr *vsub, const char *imsi);
-bool vlr_subscr_matches_tmsi(struct vlr_subscr *vsub, uint32_t tmsi);
-bool vlr_subscr_matches_msisdn(struct vlr_subscr *vsub, const char *msisdn);
-bool vlr_subscr_matches_imei(struct vlr_subscr *vsub, const char *imei);
-
-uint32_t vlr_timer(struct vlr_instance *vlr, uint32_t timer);
-
-int vlr_subscr_changed(struct vlr_subscr *vsub);
-int vlr_subscr_purge(struct vlr_subscr *vsub);
-void vlr_subscr_cancel(struct vlr_subscr *vsub, enum gsm48_gmm_cause cause);
-
-
-/* Process Acccess Request FSM */
-
-enum vlr_proc_arq_result {
-	VLR_PR_ARQ_RES_NONE,
-	VLR_PR_ARQ_RES_SYSTEM_FAILURE,
-	VLR_PR_ARQ_RES_ILLEGAL_SUBSCR,
-	VLR_PR_ARQ_RES_UNIDENT_SUBSCR,
-	VLR_PR_ARQ_RES_ROAMING_NOTALLOWED,
-	VLR_PR_ARQ_RES_ILLEGAL_EQUIP,
-	VLR_PR_ARQ_RES_UNKNOWN_ERROR,
-	VLR_PR_ARQ_RES_TIMEOUT,
-	VLR_PR_ARQ_RES_PASSED,
-};
-
-extern const struct value_string vlr_proc_arq_result_names[];
-static inline const char *vlr_proc_arq_result_name(enum vlr_proc_arq_result res)
-{
-	return get_value_string(vlr_proc_arq_result_names, res);
-}
-
-enum proc_arq_vlr_event {
-	PR_ARQ_E_START,
-	PR_ARQ_E_ID_IMSI,
-	PR_ARQ_E_AUTH_RES,
-	PR_ARQ_E_CIPH_RES,
-	PR_ARQ_E_UPD_LOC_RES,
-	PR_ARQ_E_TRACE_RES,
-	PR_ARQ_E_IMEI_RES,
-	PR_ARQ_E_PRES_RES,
-	PR_ARQ_E_TMSI_ACK,
-};
-
-enum vlr_parq_type {
-	VLR_PR_ARQ_T_INVALID = 0, /* to guard against unset vars */
-	VLR_PR_ARQ_T_CM_SERV_REQ,
-	VLR_PR_ARQ_T_PAGING_RESP,
-	/* FIXME: differentiate between services of 24.008 10.5.3.3 */
-};
-
-/* Process Access Request (CM SERV REQ / PAGING RESP) */
-void
-vlr_proc_acc_req(struct osmo_fsm_inst *parent,
-		 uint32_t parent_event_success,
-		 uint32_t parent_event_failure,
-		 void *parent_event_data,
-		 struct vlr_instance *vlr, void *msc_conn_ref,
-		 enum vlr_parq_type type, const uint8_t *mi_lv,
-		 const struct osmo_location_area_id *lai,
-		 bool authentication_required,
-		 enum vlr_ciph ciphering_required,
-		 bool is_r99, bool is_utran);
-
-void vlr_parq_conn_timeout(struct osmo_fsm_inst *fi);
-
-void vlr_parq_fsm_init(void);
-
-int vlr_set_ciph_mode(struct vlr_instance *vlr,
-		      struct osmo_fsm_inst *fi,
-		      void *msc_conn_ref,
-		      enum vlr_ciph ciph_mode,
-		      bool retrieve_imeisv);
-
-void log_set_filter_vlr_subscr(struct log_target *target,
-			       struct vlr_subscr *vlr_subscr);
diff --git a/include/openbsc/vty.h b/include/openbsc/vty.h
deleted file mode 100644
index f705601..0000000
--- a/include/openbsc/vty.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef OPENBSC_VTY_H
-#define OPENBSC_VTY_H
-
-#include <osmocom/vty/vty.h>
-#include <osmocom/vty/buffer.h>
-#include <osmocom/vty/command.h>
-
-struct gsm_network;
-struct vty;
-
-void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *);
-
-struct buffer *vty_argv_to_buffer(int argc, const char *argv[], int base);
-
-extern struct cmd_element cfg_description_cmd;
-extern struct cmd_element cfg_no_description_cmd;
-
-enum bsc_vty_node {
-	GSMNET_NODE = _LAST_OSMOVTY_NODE + 1,
-	BTS_NODE,
-	TRX_NODE,
-	TS_NODE,
-	SUBSCR_NODE,
-	MGCP_NODE,
-	GBPROXY_NODE,
-	SGSN_NODE,
-	OML_NODE,
-	NAT_NODE,
-	NAT_BSC_NODE,
-	MSC_NODE,
-	OM2K_NODE,
-	OM2K_CON_GROUP_NODE,
-	TRUNK_NODE,
-	PGROUP_NODE,
-	MNCC_INT_NODE,
-	NITB_NODE,
-	BSC_NODE,
-	SMPP_NODE,
-	SMPP_ESME_NODE,
-	GTPHUB_NODE,
-	HLR_NODE,
-};
-
-extern int bsc_vty_is_config_node(struct vty *vty, int node);
-
-struct log_info;
-int bsc_vty_init(struct gsm_network *network);
-int bsc_vty_init_extra(void);
-
-void msc_vty_init(struct gsm_network *msc_network);
-
-struct gsm_network *gsmnet_from_vty(struct vty *vty);
-
-#endif
diff --git a/include/osmocom/Makefile.am b/include/osmocom/Makefile.am
new file mode 100644
index 0000000..6514436
--- /dev/null
+++ b/include/osmocom/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = \
+	legacy_mgcp \
+	$(NULL)
diff --git a/include/osmocom/legacy_mgcp/Makefile.am b/include/osmocom/legacy_mgcp/Makefile.am
new file mode 100644
index 0000000..52f0b5b
--- /dev/null
+++ b/include/osmocom/legacy_mgcp/Makefile.am
@@ -0,0 +1,5 @@
+noinst_HEADERS = \
+	mgcpgw_client_internal.h \
+	mgcp_transcode.h \
+	vty.h \
+	$(NULL)
diff --git a/include/osmocom/legacy_mgcp/mgcp.h b/include/osmocom/legacy_mgcp/mgcp.h
new file mode 100644
index 0000000..c017faf
--- /dev/null
+++ b/include/osmocom/legacy_mgcp/mgcp.h
@@ -0,0 +1,299 @@
+/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
+
+/*
+ * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-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 OPENBSC_MGCP_H
+#define OPENBSC_MGCP_H
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/write_queue.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/core/logging.h>
+
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#define RTP_PORT_DEFAULT 4000
+#define RTP_PORT_NET_DEFAULT 16000
+
+/**
+ * Calculate the RTP audio port for the given multiplex
+ * and the direction. This allows a semi static endpoint
+ * to port calculation removing the need for the BSC
+ * and the MediaGateway to communicate.
+ *
+ * Port usage explained:
+ *       base + (multiplex * 2) + 0 == local port to wait for network packets
+ *       base + (multiplex * 2) + 1 == local port for rtcp
+ *
+ * The above port will receive packets from the BTS that need
+ * to be patched and forwarded to the network.
+ * The above port will receive packets from the network that
+ * need to be patched and forwarded to the BTS.
+ *
+ * We assume to have a static BTS IP address so we can differentiate
+ * network and BTS.
+ *
+ */
+static inline int rtp_calculate_port(int multiplex, int base)
+{
+	return base + (multiplex * 2);
+}
+
+
+/*
+ * Handling of MGCP Endpoints and the MGCP Config
+ */
+struct mgcp_endpoint;
+struct mgcp_config;
+struct mgcp_trunk_config;
+struct mgcp_rtp_end;
+
+#define MGCP_ENDP_CRCX 1
+#define MGCP_ENDP_DLCX 2
+#define MGCP_ENDP_MDCX 3
+
+/*
+ * what to do with the msg?
+ *	- continue as usual?
+ *	- reject and send a failure code?
+ *	- defer? do not send anything
+ */
+#define MGCP_POLICY_CONT	4
+#define MGCP_POLICY_REJECT	5
+#define MGCP_POLICY_DEFER	6
+
+typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint);
+typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state);
+typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id);
+typedef int (*mgcp_reset)(struct mgcp_trunk_config *cfg);
+typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone);
+
+/**
+ * Return:
+ *   <  0 in case no audio was processed
+ *   >= 0 in case audio was processed. The remaining payload
+ *   length will be returned.
+ */
+typedef int (*mgcp_processing)(struct mgcp_endpoint *endp,
+			       struct mgcp_rtp_end *dst_end,
+			       char *data, int *len, int buf_size);
+typedef int (*mgcp_processing_setup)(struct mgcp_endpoint *endp,
+				     struct mgcp_rtp_end *dst_end,
+				     struct mgcp_rtp_end *src_end);
+
+typedef void (*mgcp_get_format)(struct mgcp_endpoint *endp,
+				int *payload_type,
+				const char**subtype_name,
+				const char**fmtp_extra);
+
+#define PORT_ALLOC_STATIC	0
+#define PORT_ALLOC_DYNAMIC	1
+
+/**
+ * This holds information on how to allocate ports
+ */
+struct mgcp_port_range {
+	int mode;
+
+	/* addr or NULL to fall-back to default */
+	char *bind_addr;
+
+	/* pre-allocated from a base? */
+	int base_port;
+
+	/* dynamically allocated */
+	int range_start;
+	int range_end;
+	int last_port;
+};
+
+#define MGCP_KEEPALIVE_ONCE (-1)
+
+struct mgcp_trunk_config {
+	struct llist_head entry;
+
+	struct mgcp_config *cfg;
+
+	int trunk_nr;
+	int trunk_type;
+
+	char *audio_fmtp_extra;
+	char *audio_name;
+	int audio_payload;
+	int audio_send_ptime;
+	int audio_send_name;
+	int audio_loop;
+
+	int no_audio_transcoding;
+
+	int omit_rtcp;
+	int keepalive_interval;
+
+	/* RTP patching */
+	int force_constant_ssrc; /* 0: don't, 1: once */
+	int force_aligned_timing;
+
+	/* spec handling */
+	int force_realloc;
+
+	/* timer */
+	struct osmo_timer_list keepalive_timer;
+
+	unsigned int number_endpoints;
+	struct mgcp_endpoint *endpoints;
+};
+
+enum mgcp_role {
+	MGCP_BSC = 0,
+	MGCP_BSC_NAT,
+};
+
+enum mgcp_connection_mode {
+	MGCP_CONN_NONE = 0,
+	MGCP_CONN_RECV_ONLY = 1,
+	MGCP_CONN_SEND_ONLY = 2,
+	MGCP_CONN_RECV_SEND = MGCP_CONN_RECV_ONLY | MGCP_CONN_SEND_ONLY,
+	MGCP_CONN_LOOPBACK  = 4 | MGCP_CONN_RECV_SEND,
+};
+
+extern const struct value_string mgcp_connection_mode_strs[];
+
+static inline const char *mgcp_cmode_name(enum mgcp_connection_mode mode)
+{
+	return get_value_string(mgcp_connection_mode_strs, mode);
+}
+
+struct mgcp_config {
+	int source_port;
+	char *local_ip;
+	char *source_addr;
+	char *bts_ip;
+	char *call_agent_addr;
+
+	struct in_addr bts_in;
+
+	/* transcoder handling */
+	char *transcoder_ip;
+	struct in_addr transcoder_in;
+	int transcoder_remote_base;
+
+	/* RTP processing */
+	mgcp_processing rtp_processing_cb;
+	mgcp_processing_setup setup_rtp_processing_cb;
+
+	mgcp_get_format get_net_downlink_format_cb;
+
+	struct osmo_wqueue gw_fd;
+
+	struct mgcp_port_range bts_ports;
+	struct mgcp_port_range net_ports;
+	struct mgcp_port_range transcoder_ports;
+	int endp_dscp;
+
+	int bts_force_ptime;
+
+	mgcp_change change_cb;
+	mgcp_policy policy_cb;
+	mgcp_reset reset_cb;
+	mgcp_realloc realloc_cb;
+	mgcp_rqnt rqnt_cb;
+	void *data;
+
+	uint32_t last_call_id;
+
+	/* trunk handling */
+	struct mgcp_trunk_config trunk;
+	struct llist_head trunks;
+
+	/* only used for start with a static configuration */
+	int last_net_port;
+	int last_bts_port;
+
+	enum mgcp_role role;
+
+	/* osmux translator: 0 means disabled, 1 means enabled */
+	int osmux;
+	/* addr to bind the server to */
+	char *osmux_addr;
+	/* The BSC-NAT may ask for enabling osmux on demand. This tells us if
+	 * the osmux socket is already initialized.
+	 */
+	int osmux_init;
+	/* osmux batch factor: from 1 to 4 maximum */
+	int osmux_batch;
+	/* osmux batch size (in bytes) */
+	int osmux_batch_size;
+	/* osmux port */
+	uint16_t osmux_port;
+	/* Pad circuit with dummy messages until we see the first voice
+	 * message.
+	 */
+	uint16_t osmux_dummy;
+};
+
+/* config management */
+struct mgcp_config *mgcp_config_alloc(void);
+int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
+		      enum mgcp_role role);
+int mgcp_vty_init(void);
+int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg);
+void mgcp_release_endp(struct mgcp_endpoint *endp);
+void mgcp_initialize_endp(struct mgcp_endpoint *endp);
+int mgcp_reset_transcoder(struct mgcp_config *cfg);
+void mgcp_format_stats(struct mgcp_endpoint *endp, char *stats, size_t size);
+int mgcp_parse_stats(struct msgb *msg, uint32_t *ps, uint32_t *os, uint32_t *pr, uint32_t *_or, int *loss, uint32_t *jitter);
+
+void mgcp_trunk_set_keepalive(struct mgcp_trunk_config *tcfg, int interval);
+
+/*
+ * format helper functions
+ */
+struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
+
+/* adc helper */
+static inline int mgcp_timeslot_to_endpoint(int multiplex, int timeslot)
+{
+	if (timeslot == 0) {
+		LOGP(DLMGCP, LOGL_ERROR, "Timeslot should not be 0\n");
+		timeslot = 255;
+	}
+
+	return timeslot + (32 * multiplex);
+}
+
+static inline void mgcp_endpoint_to_timeslot(int endpoint, int *multiplex, int *timeslot)
+{
+	*multiplex = endpoint / 32;
+	*timeslot = endpoint % 32;
+}
+
+int mgcp_send_reset_ep(struct mgcp_endpoint *endp, int endpoint);
+int mgcp_send_reset_all(struct mgcp_config *cfg);
+
+
+int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port);
+int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp, struct sockaddr_in *addr, char *buf, int rc);
+int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len);
+
+#endif
diff --git a/include/osmocom/legacy_mgcp/mgcp_internal.h b/include/osmocom/legacy_mgcp/mgcp_internal.h
new file mode 100644
index 0000000..dcc75f1
--- /dev/null
+++ b/include/osmocom/legacy_mgcp/mgcp_internal.h
@@ -0,0 +1,337 @@
+/* MGCP Private Data */
+
+/*
+ * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-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/>.
+ *
+ */
+
+#pragma once
+
+#include <string.h>
+
+#include <osmocom/core/select.h>
+
+#define CI_UNUSED 0
+
+enum mgcp_trunk_type {
+	MGCP_TRUNK_VIRTUAL,
+	MGCP_TRUNK_E1,
+};
+
+struct mgcp_rtp_stream_state {
+	uint32_t ssrc;
+	uint16_t last_seq;
+	uint32_t last_timestamp;
+	uint32_t err_ts_counter;
+	int32_t last_tsdelta;
+	uint32_t last_arrival_time;
+};
+
+struct mgcp_rtp_state {
+	int initialized;
+	int patch_ssrc;
+
+	uint32_t orig_ssrc;
+
+	int seq_offset;
+
+	int32_t  timestamp_offset;
+	uint32_t packet_duration;
+
+	struct mgcp_rtp_stream_state in_stream;
+	struct mgcp_rtp_stream_state out_stream;
+
+	/* jitter and packet loss calculation */
+	int stats_initialized;
+	uint16_t stats_base_seq;
+	uint16_t stats_max_seq;
+	uint32_t stats_ssrc;
+	uint32_t stats_jitter;
+	int32_t stats_transit;
+	int stats_cycles;
+	bool patched_first_rtp_payload; /* FIXME: drop this, see OS#2459 */
+};
+
+struct mgcp_rtp_codec {
+	uint32_t rate;
+	int channels;
+	uint32_t frame_duration_num;
+	uint32_t frame_duration_den;
+
+	int payload_type;
+	char *audio_name;
+	char *subtype_name;
+};
+
+struct mgcp_rtp_end {
+	/* statistics */
+	unsigned int packets;
+	unsigned int octets;
+	unsigned int dropped_packets;
+	struct in_addr addr;
+
+	/* in network byte order */
+	int rtp_port, rtcp_port;
+
+	/* audio codec information */
+	struct mgcp_rtp_codec codec;
+	struct mgcp_rtp_codec alt_codec; /* TODO/XXX: make it generic */
+
+	/* per endpoint data */
+	int  frames_per_packet;
+	uint32_t packet_duration_ms;
+	char *fmtp_extra;
+	int output_enabled;
+	int force_output_ptime;
+
+	/* RTP patching */
+	int force_constant_ssrc; /* -1: always, 0: don't, 1: once */
+	int force_aligned_timing;
+	void *rtp_process_data;
+
+	/*
+	 * Each end has a socket...
+	 */
+	struct osmo_fd rtp;
+	struct osmo_fd rtcp;
+
+	int local_port;
+	int local_alloc;
+};
+
+enum {
+	MGCP_TAP_BTS_IN,
+	MGCP_TAP_BTS_OUT,
+	MGCP_TAP_NET_IN,
+	MGCP_TAP_NET_OUT,
+
+	/* last element */
+	MGCP_TAP_COUNT
+};
+
+struct mgcp_rtp_tap {
+	int enabled;
+	struct sockaddr_in forward;
+};
+
+struct mgcp_lco {
+	char *string;
+	char *codec;
+	int pkt_period_min; /* time in ms */
+	int pkt_period_max; /* time in ms */
+};
+
+enum mgcp_type {
+	MGCP_RTP_DEFAULT	= 0,
+	MGCP_RTP_TRANSCODED,
+	MGCP_OSMUX_BSC,
+	MGCP_OSMUX_BSC_NAT,
+};
+
+#include <osmocom/legacy_mgcp/osmux.h>
+
+struct mgcp_endpoint {
+	int allocated;
+	uint32_t ci;
+	char *callid;
+	struct mgcp_lco local_options;
+	int conn_mode;
+	int orig_mode;
+
+	/* backpointer */
+	struct mgcp_config *cfg;
+	struct mgcp_trunk_config *tcfg;
+
+	/* port status for bts/net */
+	struct mgcp_rtp_end bts_end;
+	struct mgcp_rtp_end net_end;
+
+	/*
+	 * For transcoding we will send from the local_port
+	 * of trans_bts and it will arrive at trans_net from
+	 * where we will forward it to the network.
+	 */
+	struct mgcp_rtp_end trans_bts;
+	struct mgcp_rtp_end trans_net;
+	enum mgcp_type type;
+
+	/* sequence bits */
+	struct mgcp_rtp_state net_state;
+	struct mgcp_rtp_state bts_state;
+
+	/* fields for re-transmission */
+	char *last_trans;
+	char *last_response;
+
+	/* tap for the endpoint */
+	struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
+
+	struct {
+		/* Osmux state: disabled, activating, active */
+		enum osmux_state state;
+		/* Allocated Osmux circuit ID for this endpoint */
+		int allocated_cid;
+		/* Used Osmux circuit ID for this endpoint */
+		uint8_t cid;
+		/* handle to batch messages */
+		struct osmux_in_handle *in;
+		/* handle to unbatch messages */
+		struct osmux_out_handle out;
+		/* statistics */
+		struct {
+			uint32_t chunks;
+			uint32_t octets;
+		} stats;
+	} osmux;
+};
+
+#define for_each_line(line, save)			\
+	for (line = strline_r(NULL, &save); line;\
+	     line = strline_r(NULL, &save))
+
+static inline char *strline_r(char *str, char **saveptr)
+{
+	char *result;
+
+	if (str)
+		*saveptr = str;
+
+	result = *saveptr;
+
+	if (*saveptr != NULL) {
+		*saveptr = strpbrk(*saveptr, "\r\n");
+
+		if (*saveptr != NULL) {
+			char *eos = *saveptr;
+
+			if ((*saveptr)[0] == '\r' && (*saveptr)[1] == '\n')
+				(*saveptr)++;
+			(*saveptr)++;
+			if ((*saveptr)[0] == '\0')
+				*saveptr = NULL;
+
+			*eos = '\0';
+		}
+	}
+
+	return result;
+}
+
+
+
+#define ENDPOINT_NUMBER(endp) abs((int)(endp - endp->tcfg->endpoints))
+
+/**
+ * Internal structure while parsing a request
+ */
+struct mgcp_parse_data {
+	struct mgcp_config *cfg;
+	struct mgcp_endpoint *endp;
+	char *trans;
+	char *save;
+	int found;
+};
+
+int mgcp_send_dummy(struct mgcp_endpoint *endp);
+int mgcp_bind_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
+int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
+int mgcp_bind_trans_bts_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
+int mgcp_bind_trans_net_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
+int mgcp_free_rtp_port(struct mgcp_rtp_end *end);
+
+/* For transcoding we need to manage an in and an output that are connected */
+static inline int endp_back_channel(int endpoint)
+{
+	return endpoint + 60;
+}
+
+struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index);
+struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
+
+void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
+			 struct mgcp_rtp_end *rtp);
+uint32_t mgcp_rtp_packet_duration(struct mgcp_endpoint *endp,
+				  struct mgcp_rtp_end *rtp);
+
+void mgcp_state_calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *,
+			uint32_t *expected, int *loss);
+uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *);
+
+/* payload processing default functions */
+int mgcp_rtp_processing_default(struct mgcp_endpoint *endp, struct mgcp_rtp_end *dst_end,
+				char *data, int *len, int buf_size);
+
+int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
+				      struct mgcp_rtp_end *dst_end,
+				      struct mgcp_rtp_end *src_end);
+
+void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
+					  int *payload_type,
+					  const char**subtype_name,
+					  const char**fmtp_extra);
+
+/* internal RTP Annex A counting */
+void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
+			const uint16_t seq, const int32_t transit,
+			const uint32_t ssrc);
+
+int mgcp_set_ip_tos(int fd, int tos);
+
+enum {
+	MGCP_DEST_NET = 0,
+	MGCP_DEST_BTS,
+};
+
+
+#define MGCP_DUMMY_LOAD 0x23
+
+
+/**
+ * SDP related information
+ */
+/* Assume audio frame length of 20ms */
+#define DEFAULT_RTP_AUDIO_FRAME_DUR_NUM 20
+#define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000
+#define DEFAULT_RTP_AUDIO_PACKET_DURATION_MS 20
+#define DEFAULT_RTP_AUDIO_DEFAULT_RATE  8000
+#define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1
+
+#define PTYPE_UNDEFINED (-1)
+int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p);
+int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
+			int payload_type, const char *audio_name);
+
+
+/**
+ * Internal network related
+ */
+static inline const char *mgcp_net_src_addr(struct mgcp_endpoint *endp)
+{
+	if (endp->cfg->net_ports.bind_addr)
+		return endp->cfg->net_ports.bind_addr;
+	return endp->cfg->source_addr;
+}
+
+static inline const char *mgcp_bts_src_addr(struct mgcp_endpoint *endp)
+{
+	if (endp->cfg->bts_ports.bind_addr)
+		return endp->cfg->bts_ports.bind_addr;
+	return endp->cfg->source_addr;
+}
+
+int mgcp_msg_terminate_nul(struct msgb *msg);
diff --git a/include/openbsc/mgcp_transcode.h b/include/osmocom/legacy_mgcp/mgcp_transcode.h
similarity index 100%
rename from include/openbsc/mgcp_transcode.h
rename to include/osmocom/legacy_mgcp/mgcp_transcode.h
diff --git a/include/osmocom/legacy_mgcp/mgcpgw_client.h b/include/osmocom/legacy_mgcp/mgcpgw_client.h
new file mode 100644
index 0000000..09db816
--- /dev/null
+++ b/include/osmocom/legacy_mgcp/mgcpgw_client.h
@@ -0,0 +1,73 @@
+#pragma once
+
+#include <stdint.h>
+
+#define MGCPGW_CLIENT_LOCAL_ADDR_DEFAULT "0.0.0.0"
+#define MGCPGW_CLIENT_LOCAL_PORT_DEFAULT 0
+#define MGCPGW_CLIENT_REMOTE_ADDR_DEFAULT "127.0.0.1"
+#define MGCPGW_CLIENT_REMOTE_PORT_DEFAULT 2427
+
+struct msgb;
+struct vty;
+struct mgcpgw_client;
+
+struct mgcpgw_client_conf {
+	const char *local_addr;
+	int local_port;
+	const char *remote_addr;
+	int remote_port;
+	uint16_t first_endpoint;
+	uint16_t last_endpoint;
+	uint16_t bts_base;
+};
+
+typedef unsigned int mgcp_trans_id_t;
+
+struct mgcp_response_head {
+       int response_code;
+       mgcp_trans_id_t trans_id;
+       const char *comment;
+};
+
+struct mgcp_response {
+	char *body;
+	struct mgcp_response_head head;
+	uint16_t audio_port;
+};
+
+void mgcpgw_client_conf_init(struct mgcpgw_client_conf *conf);
+void mgcpgw_client_vty_init(void *talloc_ctx, int node, struct mgcpgw_client_conf *conf);
+int mgcpgw_client_config_write(struct vty *vty, const char *indent);
+struct mgcpgw_client_conf *mgcpgw_client_conf_actual(struct mgcpgw_client *mgcp);
+
+struct mgcpgw_client *mgcpgw_client_init(void *ctx,
+					 struct mgcpgw_client_conf *conf);
+int mgcpgw_client_connect(struct mgcpgw_client *mgcp);
+
+const char *mgcpgw_client_remote_addr_str(struct mgcpgw_client *mgcp);
+uint16_t mgcpgw_client_remote_port(struct mgcpgw_client *mgcp);
+uint32_t mgcpgw_client_remote_addr_n(struct mgcpgw_client *mgcp);
+
+int mgcpgw_client_next_endpoint(struct mgcpgw_client *client);
+void mgcpgw_client_release_endpoint(uint16_t id, struct mgcpgw_client *client);
+
+/* Invoked when an MGCP response is received or sending failed.  When the
+ * response is passed as NULL, this indicates failure during transmission. */
+typedef void (* mgcp_response_cb_t )(struct mgcp_response *response, void *priv);
+int mgcp_response_parse_params(struct mgcp_response *r);
+
+int mgcpgw_client_tx(struct mgcpgw_client *mgcp, struct msgb *msg,
+		     mgcp_response_cb_t response_cb, void *priv);
+
+enum mgcp_connection_mode;
+
+struct msgb *mgcp_msg_crcx(struct mgcpgw_client *mgcp,
+			   uint16_t rtp_endpoint, unsigned int call_id,
+			   enum mgcp_connection_mode mode);
+
+struct msgb *mgcp_msg_mdcx(struct mgcpgw_client *mgcp,
+			   uint16_t rtp_endpoint, const char *rtp_conn_addr,
+			   uint16_t rtp_port, enum mgcp_connection_mode mode);
+
+struct msgb *mgcp_msg_dlcx(struct mgcpgw_client *mgcp, uint16_t rtp_endpoint,
+			   unsigned int call_id);
diff --git a/include/osmocom/legacy_mgcp/mgcpgw_client_internal.h b/include/osmocom/legacy_mgcp/mgcpgw_client_internal.h
new file mode 100644
index 0000000..d3a7849
--- /dev/null
+++ b/include/osmocom/legacy_mgcp/mgcpgw_client_internal.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#define MSGB_CB_MGCP_TRANS_ID 0
+
+struct mgcpgw_client {
+	struct mgcpgw_client_conf actual;
+	uint32_t remote_addr;
+	struct osmo_wqueue wq;
+	mgcp_trans_id_t next_trans_id;
+	struct llist_head responses_pending;
+	struct llist_head inuse_endpoints;
+};
+
+struct mgcp_inuse_endpoint {
+	struct llist_head entry;
+	uint16_t id;
+};
+
+struct mgcp_response_pending {
+	struct llist_head entry;
+
+	mgcp_trans_id_t trans_id;
+	mgcp_response_cb_t response_cb;
+	void *priv;
+};
+
+int mgcpgw_client_rx(struct mgcpgw_client *mgcp, struct msgb *msg);
+
+struct mgcp_response_pending * mgcpgw_client_pending_add(
+					struct mgcpgw_client *mgcp,
+					mgcp_trans_id_t trans_id,
+					mgcp_response_cb_t response_cb,
+					void *priv);
diff --git a/include/openbsc/osmux.h b/include/osmocom/legacy_mgcp/osmux.h
similarity index 100%
rename from include/openbsc/osmux.h
rename to include/osmocom/legacy_mgcp/osmux.h
diff --git a/include/osmocom/legacy_mgcp/vty.h b/include/osmocom/legacy_mgcp/vty.h
new file mode 100644
index 0000000..c277c0a
--- /dev/null
+++ b/include/osmocom/legacy_mgcp/vty.h
@@ -0,0 +1,31 @@
+#ifndef OPENBSC_VTY_H
+#define OPENBSC_VTY_H
+
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/buffer.h>
+#include <osmocom/vty/command.h>
+
+struct gsm_network;
+struct vty;
+
+void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *);
+
+struct buffer *vty_argv_to_buffer(int argc, const char *argv[], int base);
+
+extern struct cmd_element cfg_description_cmd;
+extern struct cmd_element cfg_no_description_cmd;
+
+enum mgcp_vty_node {
+	MGCP_NODE = _LAST_OSMOVTY_NODE + 1,
+	TRUNK_NODE,
+};
+
+struct log_info;
+int bsc_vty_init(struct gsm_network *network);
+int bsc_vty_init_extra(void);
+
+void msc_vty_init(struct gsm_network *msc_network);
+
+struct gsm_network *gsmnet_from_vty(struct vty *vty);
+
+#endif
diff --git a/libosmo-legacy-mgcp.pc.in b/libosmo-legacy-mgcp.pc.in
new file mode 100644
index 0000000..62d9edc
--- /dev/null
+++ b/libosmo-legacy-mgcp.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Osmocom legacy Media Gateway Control Protocol library
+Description: C Utility Library
+Version: @VERSION@
+Libs: -L${libdir} -losmo-legacy-mgcp
+Cflags: -I${includedir}/
diff --git a/openbsc.pc.in b/openbsc.pc.in
deleted file mode 100644
index 17e265d..0000000
--- a/openbsc.pc.in
+++ /dev/null
@@ -1,10 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@/
-
-Name: OpenBSC
-Description: OpenBSC base station controller
-Requires:
-Version: @VERSION@
-Cflags: -I${includedir}
diff --git a/osmoappdesc.py b/osmoappdesc.py
index 170c83b..69b15b0 100644
--- a/osmoappdesc.py
+++ b/osmoappdesc.py
@@ -15,40 +15,14 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>
 
 
-# Most systems won't be able to use these, so they're separated out
-nitb_e1_configs = [
-    "doc/examples/osmo-nitb/bs11/openbsc-2bts-2trx.cfg",
-    "doc/examples/osmo-nitb/bs11/openbsc-1bts-2trx-hopping.cfg",
-    "doc/examples/osmo-nitb/bs11/openbsc-1bts-2trx.cfg",
-    "doc/examples/osmo-nitb/bs11/openbsc.cfg",
-    "doc/examples/osmo-nitb/nokia/openbsc_nokia_3trx.cfg",
-    "doc/examples/osmo-nitb/nanobts/openbsc-multitrx.cfg",
-    "doc/examples/osmo-nitb/rbs2308/openbsc.cfg"
-]
-
-
 app_configs = {
-    "osmo-bsc": ["doc/examples/osmo-bsc/osmo-bsc.cfg"],
-    "nat": ["doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg"],
     "mgcp": ["doc/examples/osmo-bsc_mgcp/mgcp.cfg"],
-    "gbproxy": ["doc/examples/osmo-gbproxy/osmo-gbproxy.cfg",
-             "doc/examples/osmo-gbproxy/osmo-gbproxy-legacy.cfg"],
-    "sgsn": ["doc/examples/osmo-sgsn/osmo-sgsn.cfg"],
-    "msc": ["doc/examples/osmo-msc/osmo-msc.cfg"],
-    "gtphub": ["doc/examples/osmo-gtphub/osmo-gtphub-1iface.cfg"]
 }
 
-
-apps = [(4242, "src/osmo-bsc/osmo-bsc", "OsmoBSC", "osmo-bsc"),
-        (4244, "src/osmo-bsc_nat/osmo-bsc_nat",  "OsmoBSCNAT", "nat"),
-        (4243, "src/osmo-bsc_mgcp/osmo-bsc_mgcp", "OpenBSC MGCP", "mgcp"),
-        (4246, "src/gprs/osmo-gbproxy", "OsmoGbProxy", "gbproxy"),
-        (4245, "src/gprs/osmo-sgsn", "OsmoSGSN", "sgsn"),
-        (4254, "src/osmo-msc/osmo-msc", "OsmoMSC", "msc"),
-        (4253, "src/gprs/osmo-gtphub", "OsmoGTPhub", "gtphub")
+apps = [(4243, "src/osmo-bsc_mgcp/osmo-bsc_mgcp", "OpenBSC MGCP", "mgcp"),
         ]
 
-vty_command = ["./src/osmo-msc/osmo-msc", "-c",
-               "doc/examples/osmo-msc/osmo-msc.cfg"]
+vty_command = ["./src/osmo-bsc_mgcp/osmo-bsc_mgcp", "-c",
+               "doc/examples/osmo-bsc_mgcp/mgcp.cfg"]
 
-vty_app = apps[5] # reference apps[] entry for osmo-nitb
+vty_app = apps[0]
diff --git a/src/Makefile.am b/src/Makefile.am
index bd69738..f47bc00 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,34 +21,10 @@
 
 # Libraries
 SUBDIRS = \
-	libcommon \
-	libvlr \
-	libmgcp \
-	libbsc \
-	libmsc \
-	libtrau \
-	libfilter \
-	libcommon-cs \
+	libosmo-legacy-mgcp \
 	$(NULL)
 
 # Programs
 SUBDIRS += \
-	osmo-msc \
 	osmo-bsc_mgcp \
-	utils \
-	ipaccess \
-	gprs \
 	$(NULL)
-
-# Conditional Programs
-if BUILD_NAT
-SUBDIRS += \
-	osmo-bsc_nat \
-	$(NULL)
-endif
-
-if BUILD_BSC
-SUBDIRS += \
-	osmo-bsc \
-	$(NULL)
-endif
diff --git a/src/gprs/.gitignore b/src/gprs/.gitignore
deleted file mode 100644
index 7cfefba..0000000
--- a/src/gprs/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-gsn_restart
-osmo_*.cfg*
diff --git a/src/gprs/Makefile.am b/src/gprs/Makefile.am
deleted file mode 100644
index 39a4c12..0000000
--- a/src/gprs/Makefile.am
+++ /dev/null
@@ -1,133 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	-I$(top_builddir) \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	-fno-strict-aliasing \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOVTY_CFLAGS) \
-	$(LIBOSMOCTRL_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(LIBOSMOGB_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(LIBCARES_CFLAGS) \
-	$(LIBCRYPTO_CFLAGS) \
-	$(LIBGTP_CFLAGS) \
-	$(NULL)
-if BUILD_IU
-AM_CFLAGS += \
-	$(LIBASN1C_CFLAGS) \
-	$(LIBOSMOSIGTRAN_CFLAGS) \
-	$(LIBOSMORANAP_CFLAGS) \
-	$(NULL)
-endif
-
-OSMO_LIBS = \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOVTY_LIBS) \
-	$(LIBOSMOCTRL_LIBS) \
-	$(LIBOSMOGB_LIBS) \
-	$(LIBGTP_LIBS) \
-	$(LIBOSMOSIGTRAN_LIBS) \
-	$(NULL)
-
-bin_PROGRAMS = \
-	osmo-gbproxy \
-	$(NULL)
-if HAVE_LIBGTP
-if HAVE_LIBCARES
-bin_PROGRAMS += \
-	osmo-sgsn \
-	osmo-gtphub \
-	$(NULL)
-endif
-endif
-
-osmo_gbproxy_SOURCES = \
-	gb_proxy.c \
-	gb_proxy_main.c \
-	gb_proxy_vty.c \
-	gb_proxy_patch.c \
-	gb_proxy_tlli.c \
-	gb_proxy_peer.c \
-	gprs_gb_parse.c \
-	gprs_llc_parse.c \
-	crc24.c \
-	gprs_utils.c \
-	$(NULL)
-osmo_gbproxy_LDADD = \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(OSMO_LIBS) \
-	$(LIBCRYPTO_LIBS) \
-	-lrt \
-	$(NULL)
-
-osmo_sgsn_SOURCES = \
-	gprs_gmm.c \
-	gprs_sgsn.c \
-	gprs_sndcp.c \
-	gprs_sndcp_comp.c \
-	gprs_sndcp_dcomp.c \
-	gprs_sndcp_pcomp.c \
-	gprs_sndcp_vty.c \
-	gprs_sndcp_xid.c \
-	sgsn_main.c \
-	sgsn_vty.c \
-	sgsn_libgtp.c \
-	gprs_llc.c \
-	gprs_llc_parse.c \
-	gprs_llc_vty.c \
-	crc24.c \
-	sgsn_ctrl.c \
-	sgsn_auth.c \
-	gprs_subscriber.c \
-	gprs_utils.c \
-	sgsn_cdr.c \
-	sgsn_ares.c \
-	slhc.c \
-	gprs_llc_xid.c \
-	v42bis.c \
-	$(NULL)
-osmo_sgsn_LDADD = \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(OSMO_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	$(LIBCARES_LIBS) \
-	$(LIBCRYPTO_LIBS) \
-	$(LIBGTP_LIBS) \
-	-lrt \
-	-lm \
-	$(NULL)
-if BUILD_IU
-osmo_sgsn_LDADD += \
-	$(LIBOSMOSIGTRAN_LIBS) \
-	$(LIBOSMORANAP_LIBS) \
-	$(LIBASN1C_LIBS) \
-	$(NULL)
-endif
-
-osmo_gtphub_SOURCES = \
-	gtphub_main.c \
-	gtphub.c \
-	gtphub_sock.c \
-	gtphub_ares.c \
-	gtphub_vty.c \
-	sgsn_ares.c \
-	gprs_utils.c \
-	$(NULL)
-osmo_gtphub_LDADD = \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOVTY_LIBS) \
-	$(LIBCARES_LIBS) \
-	$(LIBGTP_LIBS) \
-	$(LIBOSMOSIGTRAN_LIBS) \
-	-lrt \
-	$(NULL)
diff --git a/src/gprs/crc24.c b/src/gprs/crc24.c
deleted file mode 100644
index 1a420ed..0000000
--- a/src/gprs/crc24.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* GPRS LLC CRC-24 Implementation */
-
-/* (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/>.
- *
- */
-
-#include <openbsc/crc24.h>
-
-/* CRC24 table - FCS */
-static const uint32_t tbl_crc24[256] = {
-	0x00000000, 0x00d6a776, 0x00f64557, 0x0020e221, 0x00b78115, 0x00612663, 0x0041c442, 0x00976334,
-	0x00340991, 0x00e2aee7, 0x00c24cc6, 0x0014ebb0, 0x00838884, 0x00552ff2, 0x0075cdd3, 0x00a36aa5,
-	0x00681322, 0x00beb454, 0x009e5675, 0x0048f103, 0x00df9237, 0x00093541, 0x0029d760, 0x00ff7016,
-	0x005c1ab3, 0x008abdc5, 0x00aa5fe4, 0x007cf892, 0x00eb9ba6, 0x003d3cd0, 0x001ddef1, 0x00cb7987,
-	0x00d02644, 0x00068132, 0x00266313, 0x00f0c465, 0x0067a751, 0x00b10027, 0x0091e206, 0x00474570,
-	0x00e42fd5, 0x003288a3, 0x00126a82, 0x00c4cdf4, 0x0053aec0, 0x008509b6, 0x00a5eb97, 0x00734ce1,
-	0x00b83566, 0x006e9210, 0x004e7031, 0x0098d747, 0x000fb473, 0x00d91305, 0x00f9f124, 0x002f5652,
-	0x008c3cf7, 0x005a9b81, 0x007a79a0, 0x00acded6, 0x003bbde2, 0x00ed1a94, 0x00cdf8b5, 0x001b5fc3,
-	0x00fb4733, 0x002de045, 0x000d0264, 0x00dba512, 0x004cc626, 0x009a6150, 0x00ba8371, 0x006c2407,
-	0x00cf4ea2, 0x0019e9d4, 0x00390bf5, 0x00efac83, 0x0078cfb7, 0x00ae68c1, 0x008e8ae0, 0x00582d96,
-	0x00935411, 0x0045f367, 0x00651146, 0x00b3b630, 0x0024d504, 0x00f27272, 0x00d29053, 0x00043725,
-	0x00a75d80, 0x0071faf6, 0x005118d7, 0x0087bfa1, 0x0010dc95, 0x00c67be3, 0x00e699c2, 0x00303eb4,
-	0x002b6177, 0x00fdc601, 0x00dd2420, 0x000b8356, 0x009ce062, 0x004a4714, 0x006aa535, 0x00bc0243,
-	0x001f68e6, 0x00c9cf90, 0x00e92db1, 0x003f8ac7, 0x00a8e9f3, 0x007e4e85, 0x005eaca4, 0x00880bd2,
-	0x00437255, 0x0095d523, 0x00b53702, 0x00639074, 0x00f4f340, 0x00225436, 0x0002b617, 0x00d41161,
-	0x00777bc4, 0x00a1dcb2, 0x00813e93, 0x005799e5, 0x00c0fad1, 0x00165da7, 0x0036bf86, 0x00e018f0,
-	0x00ad85dd, 0x007b22ab, 0x005bc08a, 0x008d67fc, 0x001a04c8, 0x00cca3be, 0x00ec419f, 0x003ae6e9,
-	0x00998c4c, 0x004f2b3a, 0x006fc91b, 0x00b96e6d, 0x002e0d59, 0x00f8aa2f, 0x00d8480e, 0x000eef78,
-	0x00c596ff, 0x00133189, 0x0033d3a8, 0x00e574de, 0x007217ea, 0x00a4b09c, 0x008452bd, 0x0052f5cb,
-	0x00f19f6e, 0x00273818, 0x0007da39, 0x00d17d4f, 0x00461e7b, 0x0090b90d, 0x00b05b2c, 0x0066fc5a,
-	0x007da399, 0x00ab04ef, 0x008be6ce, 0x005d41b8, 0x00ca228c, 0x001c85fa, 0x003c67db, 0x00eac0ad,
-	0x0049aa08, 0x009f0d7e, 0x00bfef5f, 0x00694829, 0x00fe2b1d, 0x00288c6b, 0x00086e4a, 0x00dec93c,
-	0x0015b0bb, 0x00c317cd, 0x00e3f5ec, 0x0035529a, 0x00a231ae, 0x007496d8, 0x005474f9, 0x0082d38f,
-	0x0021b92a, 0x00f71e5c, 0x00d7fc7d, 0x00015b0b, 0x0096383f, 0x00409f49, 0x00607d68, 0x00b6da1e,
-	0x0056c2ee, 0x00806598, 0x00a087b9, 0x007620cf, 0x00e143fb, 0x0037e48d, 0x001706ac, 0x00c1a1da,
-	0x0062cb7f, 0x00b46c09, 0x00948e28, 0x0042295e, 0x00d54a6a, 0x0003ed1c, 0x00230f3d, 0x00f5a84b,
-	0x003ed1cc, 0x00e876ba, 0x00c8949b, 0x001e33ed, 0x008950d9, 0x005ff7af, 0x007f158e, 0x00a9b2f8,
-	0x000ad85d, 0x00dc7f2b, 0x00fc9d0a, 0x002a3a7c, 0x00bd5948, 0x006bfe3e, 0x004b1c1f, 0x009dbb69,
-	0x0086e4aa, 0x005043dc, 0x0070a1fd, 0x00a6068b, 0x003165bf, 0x00e7c2c9, 0x00c720e8, 0x0011879e,
-	0x00b2ed3b, 0x00644a4d, 0x0044a86c, 0x00920f1a, 0x00056c2e, 0x00d3cb58, 0x00f32979, 0x00258e0f,
-	0x00eef788, 0x003850fe, 0x0018b2df, 0x00ce15a9, 0x0059769d, 0x008fd1eb, 0x00af33ca, 0x007994bc,
-	0x00dafe19, 0x000c596f, 0x002cbb4e, 0x00fa1c38, 0x006d7f0c, 0x00bbd87a, 0x009b3a5b, 0x004d9d2d
-};
-
-#define INIT_CRC24	0xffffff
-
-uint32_t crc24_calc(uint32_t fcs, uint8_t *cp, unsigned int len)
-{
-	while (len--)
-		fcs = (fcs >> 8) ^ tbl_crc24[(fcs ^ *cp++) & 0xff];
-	return fcs;
-}
diff --git a/src/gprs/gb_proxy.c b/src/gprs/gb_proxy.c
deleted file mode 100644
index cd38d23..0000000
--- a/src/gprs/gb_proxy.c
+++ /dev/null
@@ -1,1438 +0,0 @@
-/* NS-over-IP proxy */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2010-2013 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/>.
- *
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <errno.h>
-#include <sys/fcntl.h>
-#include <sys/stat.h>
-#include <arpa/inet.h>
-#include <time.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/core/stats.h>
-
-#include <osmocom/gprs/gprs_ns.h>
-#include <osmocom/gprs/gprs_bssgp.h>
-
-#include <osmocom/gsm/gsm_utils.h>
-
-#include <openbsc/signal.h>
-#include <openbsc/debug.h>
-#include <openbsc/gprs_gb_parse.h>
-#include <openbsc/gb_proxy.h>
-
-#include <openbsc/gprs_llc.h>
-#include <openbsc/gsm_04_08.h>
-#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
-#include <openbsc/gprs_utils.h>
-
-#include <openssl/rand.h>
-
-static const struct rate_ctr_desc global_ctr_description[] = {
-	{ "inv-bvci",	    "Invalid BVC Identifier          " },
-	{ "inv-lai",	    "Invalid Location Area Identifier" },
-	{ "inv-rai",	    "Invalid Routing Area Identifier " },
-	{ "inv-nsei",	    "No BVC established for NSEI     " },
-	{ "proto-err.bss",  "BSSGP protocol error      (BSS )" },
-	{ "proto-err.sgsn", "BSSGP protocol error      (SGSN)" },
-	{ "not-supp.bss",   "Feature not supported     (BSS )" },
-	{ "not-supp.sgsn",  "Feature not supported     (SGSN)" },
-	{ "restart.sgsn",   "Restarted RESET procedure (SGSN)" },
-	{ "tx-err.sgsn",    "NS Transmission error     (SGSN)" },
-	{ "error",          "Other error                     " },
-	{ "mod-peer-err",   "Patch error: no peer            " },
-};
-
-static const struct rate_ctr_group_desc global_ctrg_desc = {
-	.group_name_prefix = "gbproxy.global",
-	.group_description = "GBProxy Global Statistics",
-	.num_ctr = ARRAY_SIZE(global_ctr_description),
-	.ctr_desc = global_ctr_description,
-	.class_id = OSMO_STATS_CLASS_GLOBAL,
-};
-
-static int gbprox_relay2peer(struct msgb *old_msg, struct gbproxy_peer *peer,
-			  uint16_t ns_bvci);
-static int gbprox_relay2sgsn(struct gbproxy_config *cfg, struct msgb *old_msg,
-			     uint16_t ns_bvci, uint16_t sgsn_nsei);
-static void gbproxy_reset_imsi_acquisition(struct gbproxy_link_info* link_info);
-
-static int check_peer_nsei(struct gbproxy_peer *peer, uint16_t nsei)
-{
-	if (peer->nsei != nsei) {
-		LOGP(DGPRS, LOGL_NOTICE, "Peer entry doesn't match current NSEI "
-		     "BVCI=%u via NSEI=%u (expected NSEI=%u)\n",
-		     peer->bvci, nsei, peer->nsei);
-		rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_INV_NSEI]);
-		return 0;
-	}
-
-	return 1;
-}
-
-/* strip off the NS header */
-static void strip_ns_hdr(struct msgb *msg)
-{
-	int strip_len = msgb_bssgph(msg) - msg->data;
-	msgb_pull(msg, strip_len);
-}
-
-/* Transmit Chapter 9.2.10 Identity Request */
-static void gprs_put_identity_req(struct msgb *msg, uint8_t id_type)
-{
-	struct gsm48_hdr *gh;
-
-	id_type &= GSM_MI_TYPE_MASK;
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
-	gh->proto_discr = GSM48_PDISC_MM_GPRS;
-	gh->msg_type = GSM48_MT_GMM_ID_REQ;
-	gh->data[0] = id_type;
-}
-
-/* Transmit Chapter 9.4.6.2 Detach Accept (mobile originated detach) */
-static void gprs_put_mo_detach_acc(struct msgb *msg)
-{
-	struct gsm48_hdr *gh;
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
-	gh->proto_discr = GSM48_PDISC_MM_GPRS;
-	gh->msg_type = GSM48_MT_GMM_DETACH_ACK;
-	gh->data[0] = 0; /* no force to standby */
-}
-
-static void gprs_push_llc_ui(struct msgb *msg,
-			     int is_uplink, unsigned sapi, unsigned nu)
-{
-	const uint8_t e_bit = 0;
-	const uint8_t pm_bit = 1;
-	const uint8_t cr_bit = is_uplink ? 0 : 1;
-	uint8_t *llc;
-	uint8_t *fcs_field;
-	uint32_t fcs;
-
-	nu &= 0x01ff; /* 9 Bit */
-
-	llc = msgb_push(msg, 3);
-	llc[0] = (cr_bit << 6) | (sapi & 0x0f);
-	llc[1] = 0xc0 | (nu >> 6); /* UI frame */
-	llc[2] = (nu << 2) | ((e_bit & 1) << 1) | (pm_bit & 1);
-
-	fcs = gprs_llc_fcs(llc, msgb_length(msg));
-	fcs_field = msgb_put(msg, 3);
-	fcs_field[0] = (uint8_t)(fcs >> 0);
-	fcs_field[1] = (uint8_t)(fcs >> 8);
-	fcs_field[2] = (uint8_t)(fcs >> 16);
-}
-
-static void gprs_push_bssgp_dl_unitdata(struct msgb *msg,
-					uint32_t tlli)
-{
-	struct bssgp_ud_hdr *budh;
-	uint8_t *llc = msgb_data(msg);
-	size_t llc_size = msgb_length(msg);
-	const size_t llc_ie_hdr_size = 3;
-	const uint8_t qos_profile[] = {0x00, 0x50, 0x20}; /* hard-coded */
-	const uint8_t lifetime[] = {0x02, 0x58}; /* 6s hard-coded */
-
-	const size_t bssgp_overhead = sizeof(*budh) +
-		TVLV_GROSS_LEN(sizeof(lifetime)) + llc_ie_hdr_size;
-	uint8_t *ie;
-	uint32_t tlli_be = htonl(tlli);
-
-	budh = (struct bssgp_ud_hdr *)msgb_push(msg, bssgp_overhead);
-
-	budh->pdu_type = BSSGP_PDUT_DL_UNITDATA;
-	memcpy(&budh->tlli, &tlli_be, sizeof(budh->tlli));
-	memcpy(&budh->qos_profile, qos_profile, sizeof(budh->qos_profile));
-
-	ie = budh->data;
-	tvlv_put(ie, BSSGP_IE_PDU_LIFETIME, sizeof(lifetime), lifetime);
-	ie += TVLV_GROSS_LEN(sizeof(lifetime));
-
-	/* Note: Add alignment before the LLC IE if inserting other IE */
-
-	*(ie++) = BSSGP_IE_LLC_PDU;
-	*(ie++) = llc_size / 256;
-	*(ie++) = llc_size % 256;
-
-	OSMO_ASSERT(ie == llc);
-
-	msgb_bssgph(msg) = (uint8_t *)budh;
-	msgb_tlli(msg) = tlli;
-}
-
-/* update peer according to the BSS message */
-static void gbprox_update_current_raid(uint8_t *raid_enc,
-				       struct gbproxy_peer *peer,
-				       const char *log_text)
-{
-	struct gbproxy_patch_state *state = &peer->patch_state;
-	const int old_local_mcc = state->local_mcc;
-	const int old_local_mnc = state->local_mnc;
-	struct gprs_ra_id raid;
-
-	if (!raid_enc)
-		return;
-
-	gsm48_parse_ra(&raid, raid_enc);
-
-	/* save source side MCC/MNC */
-	if (!peer->cfg->core_mcc || raid.mcc == peer->cfg->core_mcc) {
-		state->local_mcc = 0;
-	} else {
-		state->local_mcc = raid.mcc;
-	}
-
-	if (!peer->cfg->core_mnc || raid.mnc == peer->cfg->core_mnc) {
-		state->local_mnc = 0;
-	} else {
-		state->local_mnc = raid.mnc;
-	}
-
-	if (old_local_mcc != state->local_mcc ||
-	    old_local_mnc != state->local_mnc)
-		LOGP(DGPRS, LOGL_NOTICE,
-		     "Patching RAID %sactivated, msg: %s, "
-		     "local: %d-%d, core: %d-%d\n",
-		     state->local_mcc || state->local_mnc ?
-		     "" : "de",
-		     log_text,
-		     state->local_mcc, state->local_mnc,
-		     peer->cfg->core_mcc, peer->cfg->core_mnc);
-}
-
-uint32_t gbproxy_make_bss_ptmsi(struct gbproxy_peer *peer,
-				uint32_t sgsn_ptmsi)
-{
-	uint32_t bss_ptmsi;
-	int max_retries = 23;
-	if (!peer->cfg->patch_ptmsi) {
-		bss_ptmsi = sgsn_ptmsi;
-	} else {
-		do {
-			if (RAND_bytes((uint8_t *) &bss_ptmsi, sizeof(bss_ptmsi)) != 1) {
-				bss_ptmsi = GSM_RESERVED_TMSI;
-				break;
-			}
-
-			bss_ptmsi = bss_ptmsi | 0xC0000000;
-
-			if (gbproxy_link_info_by_ptmsi(peer, bss_ptmsi))
-				bss_ptmsi = GSM_RESERVED_TMSI;
-		} while (bss_ptmsi == GSM_RESERVED_TMSI && max_retries--);
-	}
-
-	if (bss_ptmsi == GSM_RESERVED_TMSI)
-		LOGP(DGPRS, LOGL_ERROR, "Failed to allocate a BSS P-TMSI\n");
-
-	return bss_ptmsi;
-}
-
-uint32_t gbproxy_make_sgsn_tlli(struct gbproxy_peer *peer,
-				struct gbproxy_link_info *link_info,
-				uint32_t bss_tlli)
-{
-	uint32_t sgsn_tlli;
-	int max_retries = 23;
-	if (!peer->cfg->patch_ptmsi) {
-		sgsn_tlli = bss_tlli;
-	} else if (link_info->sgsn_tlli.ptmsi != GSM_RESERVED_TMSI &&
-		   gprs_tlli_type(bss_tlli) == TLLI_FOREIGN) {
-		sgsn_tlli = gprs_tmsi2tlli(link_info->sgsn_tlli.ptmsi,
-					   TLLI_FOREIGN);
-	} else if (link_info->sgsn_tlli.ptmsi != GSM_RESERVED_TMSI &&
-		   gprs_tlli_type(bss_tlli) == TLLI_LOCAL) {
-		sgsn_tlli = gprs_tmsi2tlli(link_info->sgsn_tlli.ptmsi,
-					   TLLI_LOCAL);
-	} else {
-		do {
-			/* create random TLLI, 0b01111xxx... */
-			if (RAND_bytes((uint8_t *) &sgsn_tlli, sizeof(sgsn_tlli)) != 1) {
-				sgsn_tlli = 0;
-				break;
-			}
-
-			sgsn_tlli = (sgsn_tlli & 0x7fffffff) | 0x78000000;
-
-			if (gbproxy_link_info_by_any_sgsn_tlli(peer, sgsn_tlli))
-				sgsn_tlli = 0;
-		} while (!sgsn_tlli && max_retries--);
-	}
-
-	if (!sgsn_tlli)
-		LOGP(DGPRS, LOGL_ERROR, "Failed to allocate an SGSN TLLI\n");
-
-	return sgsn_tlli;
-}
-
-void gbproxy_reset_link(struct gbproxy_link_info *link_info)
-{
-	gbproxy_reset_imsi_acquisition(link_info);
-}
-
-/* Returns != 0 iff IMSI acquisition was in progress */
-static int gbproxy_restart_imsi_acquisition(struct gbproxy_link_info* link_info)
-{
-	int in_progress = 0;
-	if (!link_info)
-		return 0;
-
-	if (link_info->imsi_acq_pending)
-		in_progress = 1;
-
-	gbproxy_link_info_discard_messages(link_info);
-	link_info->imsi_acq_pending = 0;
-
-	return in_progress;
-}
-
-static void gbproxy_reset_imsi_acquisition(struct gbproxy_link_info* link_info)
-{
-	gbproxy_restart_imsi_acquisition(link_info);
-	link_info->vu_gen_tx_bss = GBPROXY_INIT_VU_GEN_TX;
-}
-
-static int gbproxy_flush_stored_messages(struct gbproxy_peer *peer,
-					  struct msgb *msg,
-					  time_t now,
-					  struct gbproxy_link_info* link_info,
-					  struct gprs_gb_parse_context *parse_ctx)
-{
-	int rc;
-	struct msgb *stored_msg;
-	/* Got identity response with IMSI, assuming the request had
-	 * been generated by the gbproxy */
-
-	LOGP(DLLC, LOGL_DEBUG,
-	     "NSEI=%d(BSS) IMSI acquisition succeeded, "
-	     "flushing stored messages\n",
-	     msgb_nsei(msg));
-
-	/* Patch and flush stored messages towards the SGSN */
-	while ((stored_msg = msgb_dequeue(&link_info->stored_msgs))) {
-		struct gprs_gb_parse_context tmp_parse_ctx = {0};
-		tmp_parse_ctx.to_bss = 0;
-		tmp_parse_ctx.peer_nsei = msgb_nsei(stored_msg);
-		int len_change = 0;
-
-		gprs_gb_parse_bssgp(msgb_bssgph(stored_msg),
-				    msgb_bssgp_len(stored_msg),
-				    &tmp_parse_ctx);
-		gbproxy_patch_bssgp(msg, msgb_bssgph(stored_msg),
-				    msgb_bssgp_len(stored_msg),
-				    peer, link_info, &len_change,
-				    &tmp_parse_ctx);
-
-		rc = gbproxy_update_link_state_after(peer, link_info, now,
-				&tmp_parse_ctx);
-		if (rc == 1) {
-			LOGP(DLLC, LOGL_NOTICE, "link_info deleted while flushing stored messages\n");
-			msgb_free(stored_msg);
-			return -1;
-		}
-
-		rc = gbprox_relay2sgsn(peer->cfg, stored_msg,
-				       msgb_bvci(msg), link_info->sgsn_nsei);
-
-		if (rc < 0)
-			LOGP(DLLC, LOGL_ERROR,
-			     "NSEI=%d(BSS) failed to send stored message "
-			     "(%s)\n",
-			     msgb_nsei(msg),
-			     parse_ctx->llc_msg_name ?
-			     parse_ctx->llc_msg_name : "BSSGP");
-		msgb_free(stored_msg);
-	}
-
-	return 0;
-}
-
-static int gbproxy_gsm48_to_peer(struct gbproxy_peer *peer,
-				 struct gbproxy_link_info* link_info,
-				 uint16_t bvci,
-				 struct msgb *msg /* Takes msg ownership */)
-{
-	int rc;
-
-	/* Workaround to avoid N(U) collisions and to enable a restart
-	 * of the IMSI acquisition procedure. This will work unless the
-	 * SGSN has an initial V(UT) within [256-32, 256+n_retries]
-	 * (see GSM 04.64, 8.4.2). */
-	gprs_push_llc_ui(msg, 0, GPRS_SAPI_GMM, link_info->vu_gen_tx_bss);
-	link_info->vu_gen_tx_bss = (link_info->vu_gen_tx_bss + 1) % 512;
-
-	gprs_push_bssgp_dl_unitdata(msg, link_info->tlli.current);
-	rc = gbprox_relay2peer(msg, peer, bvci);
-	msgb_free(msg);
-	return rc;
-}
-
-static void gbproxy_acquire_imsi(struct gbproxy_peer *peer,
-				 struct gbproxy_link_info* link_info,
-				 uint16_t bvci)
-{
-	struct msgb *idreq_msg;
-
-	/* Send IDENT REQ */
-	idreq_msg = gsm48_msgb_alloc_name("GSM 04.08 ACQ IMSI");
-	gprs_put_identity_req(idreq_msg, GSM_MI_TYPE_IMSI);
-	gbproxy_gsm48_to_peer(peer, link_info, bvci, idreq_msg);
-}
-
-static void gbproxy_tx_detach_acc(struct gbproxy_peer *peer,
-				  struct gbproxy_link_info* link_info,
-				  uint16_t bvci)
-{
-	struct msgb *detacc_msg;
-
-	/* Send DETACH ACC */
-	detacc_msg = gsm48_msgb_alloc_name("GSM 04.08 DET ACC");
-	gprs_put_mo_detach_acc(detacc_msg);
-	gbproxy_gsm48_to_peer(peer, link_info, bvci, detacc_msg);
-}
-
-/* Return != 0 iff msg still needs to be processed */
-static int gbproxy_imsi_acquisition(struct gbproxy_peer *peer,
-				    struct msgb *msg,
-				    time_t now,
-				    struct gbproxy_link_info* link_info,
-				    struct gprs_gb_parse_context *parse_ctx)
-{
-	struct msgb *stored_msg;
-
-	if (!link_info)
-		return 1;
-
-	if (!link_info->imsi_acq_pending && link_info->imsi_len > 0)
-		return 1;
-
-	if (parse_ctx->g48_hdr)
-		switch (parse_ctx->g48_hdr->msg_type)
-		{
-		case GSM48_MT_GMM_RA_UPD_REQ:
-		case GSM48_MT_GMM_ATTACH_REQ:
-			if (gbproxy_restart_imsi_acquisition(link_info)) {
-				LOGP(DLLC, LOGL_INFO,
-				     "NSEI=%d(BSS) IMSI acquisition was in progress "
-				     "when receiving an %s.\n",
-				     msgb_nsei(msg), parse_ctx->llc_msg_name);
-			}
-			break;
-		case GSM48_MT_GMM_DETACH_REQ:
-			/* Nothing has been sent to the SGSN yet */
-			if (link_info->imsi_acq_pending) {
-				LOGP(DLLC, LOGL_INFO,
-				     "NSEI=%d(BSS) IMSI acquisition was in progress "
-				     "when receiving a DETACH_REQ.\n",
-				     msgb_nsei(msg));
-			}
-			if (!parse_ctx->invalidate_tlli) {
-				LOGP(DLLC, LOGL_INFO,
-				     "NSEI=%d(BSS) IMSI not yet acquired, "
-				     "faking a DETACH_ACC.\n",
-				     msgb_nsei(msg));
-				gbproxy_tx_detach_acc(peer, link_info, msgb_bvci(msg));
-				parse_ctx->invalidate_tlli = 1;
-			}
-			gbproxy_reset_imsi_acquisition(link_info);
-			gbproxy_update_link_state_after(peer, link_info, now,
-							parse_ctx);
-			return 0;
-		}
-
-	if (link_info->imsi_acq_pending && link_info->imsi_len > 0) {
-		int is_ident_resp =
-			parse_ctx->g48_hdr &&
-			gsm48_hdr_pdisc(parse_ctx->g48_hdr) == GSM48_PDISC_MM_GPRS &&
-			gsm48_hdr_msg_type(parse_ctx->g48_hdr) == GSM48_MT_GMM_ID_RESP;
-
-		/* The IMSI is now available. If flushing the messages fails,
-		 * then link_info has been deleted and we should return
-		 * immediately. */
-		if (gbproxy_flush_stored_messages(peer, msg, now, link_info,
-					      parse_ctx) < 0)
-			return 0;
-
-		gbproxy_reset_imsi_acquisition(link_info);
-
-		/* This message is most probably the response to the ident
-		 * request sent by gbproxy_acquire_imsi(). Don't forward it to
-		 * the SGSN. */
-		return !is_ident_resp;
-	}
-
-	/* The message cannot be processed since the IMSI is still missing */
-
-	/* Enqueue unpatched messages */
-	LOGP(DLLC, LOGL_INFO,
-	     "NSEI=%d(BSS) IMSI acquisition in progress, "
-	     "storing message (%s)\n",
-	     msgb_nsei(msg),
-	     parse_ctx->llc_msg_name ? parse_ctx->llc_msg_name : "BSSGP");
-
-	stored_msg = gprs_msgb_copy(msg, "process_bssgp_ul");
-	msgb_enqueue(&link_info->stored_msgs, stored_msg);
-
-	if (!link_info->imsi_acq_pending) {
-		LOGP(DLLC, LOGL_INFO,
-		     "NSEI=%d(BSS) IMSI is required but not available, "
-		     "initiating identification procedure (%s)\n",
-		     msgb_nsei(msg),
-		     parse_ctx->llc_msg_name ? parse_ctx->llc_msg_name : "BSSGP");
-
-		gbproxy_acquire_imsi(peer, link_info, msgb_bvci(msg));
-
-		/* There is no explicit retransmission handling, the
-		 * implementation relies on the MS doing proper retransmissions
-		 * of the triggering message instead */
-
-		link_info->imsi_acq_pending = 1;
-	}
-
-	return 0;
-}
-
-struct gbproxy_peer *gbproxy_find_peer(struct gbproxy_config *cfg,
-				       struct msgb *msg,
-				       struct gprs_gb_parse_context *parse_ctx)
-{
-	struct gbproxy_peer *peer = NULL;
-
-	if (msgb_bvci(msg) >= 2)
-		peer = gbproxy_peer_by_bvci(cfg, msgb_bvci(msg));
-
-	if (!peer && !parse_ctx->to_bss)
-		peer = gbproxy_peer_by_nsei(cfg, msgb_nsei(msg));
-
-	if (!peer)
-		peer = gbproxy_peer_by_bssgp_tlv(cfg, &parse_ctx->bssgp_tp);
-
-	if (!peer) {
-		LOGP(DLLC, LOGL_INFO,
-		     "NSEI=%d(%s) patching: didn't find peer for message, "
-		     "PDU %d\n",
-		     msgb_nsei(msg), parse_ctx->to_bss ? "BSS" : "SGSN",
-		     parse_ctx->pdu_type);
-		/* Increment counter */
-		rate_ctr_inc(&cfg->ctrg->ctr[GBPROX_GLOB_CTR_PATCH_PEER_ERR]);
-	}
-	return peer;
-}
-
-/* patch BSSGP message */
-static int gbprox_process_bssgp_ul(struct gbproxy_config *cfg,
-				   struct msgb *msg,
-				   struct gbproxy_peer *peer)
-{
-	struct gprs_gb_parse_context parse_ctx = {0};
-	int rc;
-	int len_change = 0;
-	time_t now;
-	struct timespec ts = {0,};
-	struct gbproxy_link_info *link_info = NULL;
-	uint32_t sgsn_nsei = cfg->nsip_sgsn_nsei;
-
-	if (!cfg->core_mcc && !cfg->core_mnc && !cfg->core_apn &&
-	    !cfg->acquire_imsi && !cfg->patch_ptmsi && !cfg->route_to_sgsn2)
-		return 1;
-
-	parse_ctx.to_bss = 0;
-	parse_ctx.peer_nsei = msgb_nsei(msg);
-
-	/* Parse BSSGP/LLC */
-	rc = gprs_gb_parse_bssgp(msgb_bssgph(msg), msgb_bssgp_len(msg),
-				 &parse_ctx);
-
-	if (!rc && !parse_ctx.need_decryption) {
-		LOGP(DGPRS, LOGL_ERROR,
-		     "NSEI=%u(BSS) patching: failed to parse invalid %s message\n",
-		     msgb_nsei(msg), gprs_gb_message_name(&parse_ctx, "NS_UNITDATA"));
-		gprs_gb_log_parse_context(LOGL_NOTICE, &parse_ctx, "NS_UNITDATA");
-		LOGP(DGPRS, LOGL_NOTICE,
-		     "NSEI=%u(BSS) invalid message was: %s\n",
-		     msgb_nsei(msg), msgb_hexdump(msg));
-		return 0;
-	}
-
-	/* Get peer */
-	if (!peer)
-		peer = gbproxy_find_peer(cfg, msg, &parse_ctx);
-
-	if (!peer)
-		return 0;
-
-
-	clock_gettime(CLOCK_MONOTONIC, &ts);
-	now = ts.tv_sec;
-
-	gbprox_update_current_raid(parse_ctx.bssgp_raid_enc, peer,
-				   parse_ctx.llc_msg_name);
-
-	gprs_gb_log_parse_context(LOGL_DEBUG, &parse_ctx, "NS_UNITDATA");
-
-	link_info = gbproxy_update_link_state_ul(peer, now, &parse_ctx);
-
-	if (parse_ctx.g48_hdr) {
-		switch (parse_ctx.g48_hdr->msg_type) {
-		case GSM48_MT_GMM_ATTACH_REQ:
-			rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_ATTACH_REQS]);
-			break;
-		case GSM48_MT_GMM_DETACH_REQ:
-			rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_DETACH_REQS]);
-			break;
-		case GSM48_MT_GMM_ATTACH_COMPL:
-			rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_ATTACH_COMPLS]);
-			break;
-		case GSM48_MT_GMM_RA_UPD_REQ:
-			rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_RA_UPD_REQS]);
-			break;
-		case GSM48_MT_GMM_RA_UPD_COMPL:
-			rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_RA_UPD_COMPLS]);
-			break;
-		case GSM48_MT_GMM_STATUS:
-			rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_GMM_STATUS_BSS]);
-			break;
-		case GSM48_MT_GSM_ACT_PDP_REQ:
-			rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_PDP_ACT_REQS]);
-			break;
-		case GSM48_MT_GSM_DEACT_PDP_REQ:
-			rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_PDP_DEACT_REQS]);
-			break;
-
-		default:
-			break;
-		}
-	}
-
-	if (link_info && cfg->route_to_sgsn2) {
-		if (cfg->acquire_imsi && link_info->imsi_len == 0)
-			sgsn_nsei = 0xffff;
-		else if (gbproxy_imsi_matches(cfg, GBPROX_MATCH_ROUTING,
-					      link_info))
-			sgsn_nsei = cfg->nsip_sgsn2_nsei;
-	}
-
-	if (link_info)
-		link_info->sgsn_nsei = sgsn_nsei;
-
-	/* Handle IMSI acquisition */
-	if (cfg->acquire_imsi) {
-		rc = gbproxy_imsi_acquisition(peer, msg, now, link_info,
-					      &parse_ctx);
-		if (rc <= 0)
-			return rc;
-	}
-
-	gbproxy_patch_bssgp(msg, msgb_bssgph(msg), msgb_bssgp_len(msg),
-			    peer, link_info, &len_change, &parse_ctx);
-
-	gbproxy_update_link_state_after(peer, link_info, now, &parse_ctx);
-
-	if (sgsn_nsei != cfg->nsip_sgsn_nsei) {
-		/* Send message directly to the selected SGSN */
-		rc = gbprox_relay2sgsn(cfg, msg, msgb_bvci(msg), sgsn_nsei);
-		/* Don't let the calling code handle the transmission */
-		return 0;
-	}
-
-	return 1;
-}
-
-/* patch BSSGP message to use core_mcc/mnc on the SGSN side */
-static void gbprox_process_bssgp_dl(struct gbproxy_config *cfg,
-				    struct msgb *msg,
-				    struct gbproxy_peer *peer)
-{
-	struct gprs_gb_parse_context parse_ctx = {0};
-	int rc;
-	int len_change = 0;
-	time_t now;
-	struct timespec ts = {0,};
-	struct gbproxy_link_info *link_info = NULL;
-
-	if (!cfg->core_mcc && !cfg->core_mnc && !cfg->core_apn &&
-	    !cfg->acquire_imsi && !cfg->patch_ptmsi && !cfg->route_to_sgsn2)
-		return;
-
-	parse_ctx.to_bss = 1;
-	parse_ctx.peer_nsei = msgb_nsei(msg);
-
-	rc = gprs_gb_parse_bssgp(msgb_bssgph(msg), msgb_bssgp_len(msg),
-				 &parse_ctx);
-
-	if (!rc && !parse_ctx.need_decryption) {
-		LOGP(DGPRS, LOGL_ERROR,
-		     "NSEI=%u(SGSN) patching: failed to parse invalid %s message\n",
-		     msgb_nsei(msg), gprs_gb_message_name(&parse_ctx, "NS_UNITDATA"));
-		gprs_gb_log_parse_context(LOGL_NOTICE, &parse_ctx, "NS_UNITDATA");
-		LOGP(DGPRS, LOGL_NOTICE,
-		     "NSEI=%u(SGSN) invalid message was: %s\n",
-		     msgb_nsei(msg), msgb_hexdump(msg));
-		return;
-	}
-
-	/* Get peer */
-	if (!peer)
-		peer = gbproxy_find_peer(cfg, msg, &parse_ctx);
-
-	if (!peer)
-		return;
-
-	clock_gettime(CLOCK_MONOTONIC, &ts);
-	now = ts.tv_sec;
-
-	if (parse_ctx.g48_hdr) {
-		switch (parse_ctx.g48_hdr->msg_type) {
-		case GSM48_MT_GMM_ATTACH_ACK:
-			rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_ATTACH_ACKS]);
-			break;
-		case GSM48_MT_GMM_ATTACH_REJ:
-			rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_ATTACH_REJS]);
-			break;
-		case GSM48_MT_GMM_DETACH_ACK:
-			rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_DETACH_ACKS]);
-			break;
-		case GSM48_MT_GMM_RA_UPD_ACK:
-			rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_RA_UPD_ACKS]);
-			break;
-		case GSM48_MT_GMM_RA_UPD_REJ:
-			rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_RA_UPD_REJS]);
-			break;
-		case GSM48_MT_GMM_STATUS:
-			rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_GMM_STATUS_SGSN]);
-			break;
-		case GSM48_MT_GSM_ACT_PDP_ACK:
-			rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_PDP_ACT_ACKS]);
-			break;
-		case GSM48_MT_GSM_ACT_PDP_REJ:
-			rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_PDP_ACT_REJS]);
-			break;
-		case GSM48_MT_GSM_DEACT_PDP_ACK:
-			rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_PDP_DEACT_ACKS]);
-			break;
-
-		default:
-			break;
-		}
-	}
-
-	gprs_gb_log_parse_context(LOGL_DEBUG, &parse_ctx, "NS_UNITDATA");
-
-	link_info = gbproxy_update_link_state_dl(peer, now, &parse_ctx);
-
-	gbproxy_patch_bssgp(msg, msgb_bssgph(msg), msgb_bssgp_len(msg),
-			    peer, link_info, &len_change, &parse_ctx);
-
-	gbproxy_update_link_state_after(peer, link_info, now, &parse_ctx);
-
-	return;
-}
-
-/* feed a message down the NS-VC associated with the specified peer */
-static int gbprox_relay2sgsn(struct gbproxy_config *cfg, struct msgb *old_msg,
-			     uint16_t ns_bvci, uint16_t sgsn_nsei)
-{
-	/* create a copy of the message so the old one can
-	 * be free()d safely when we return from gbprox_rcvmsg() */
-	struct msgb *msg = gprs_msgb_copy(old_msg, "msgb_relay2sgsn");
-	int rc;
-
-	DEBUGP(DGPRS, "NSEI=%u proxying BTS->SGSN (NS_BVCI=%u, NSEI=%u)\n",
-		msgb_nsei(msg), ns_bvci, sgsn_nsei);
-
-	msgb_bvci(msg) = ns_bvci;
-	msgb_nsei(msg) = sgsn_nsei;
-
-	strip_ns_hdr(msg);
-
-	rc = gprs_ns_sendmsg(bssgp_nsi, msg);
-	if (rc < 0)
-		rate_ctr_inc(&cfg->ctrg->ctr[GBPROX_GLOB_CTR_TX_ERR_SGSN]);
-
-	return rc;
-}
-
-/* feed a message down the NS-VC associated with the specified peer */
-static int gbprox_relay2peer(struct msgb *old_msg, struct gbproxy_peer *peer,
-			  uint16_t ns_bvci)
-{
-	/* create a copy of the message so the old one can
-	 * be free()d safely when we return from gbprox_rcvmsg() */
-	struct msgb *msg = gprs_msgb_copy(old_msg, "msgb_relay2peer");
-	int rc;
-
-	DEBUGP(DGPRS, "NSEI=%u proxying SGSN->BSS (NS_BVCI=%u, NSEI=%u)\n",
-		msgb_nsei(msg), ns_bvci, peer->nsei);
-
-	msgb_bvci(msg) = ns_bvci;
-	msgb_nsei(msg) = peer->nsei;
-
-	/* Strip the old NS header, it will be replaced with a new one */
-	strip_ns_hdr(msg);
-
-	rc = gprs_ns_sendmsg(bssgp_nsi, msg);
-	if (rc < 0)
-		rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_TX_ERR]);
-
-	return rc;
-}
-
-static int block_unblock_peer(struct gbproxy_config *cfg, uint16_t ptp_bvci, uint8_t pdu_type)
-{
-	struct gbproxy_peer *peer;
-
-	peer = gbproxy_peer_by_bvci(cfg, ptp_bvci);
-	if (!peer) {
-		LOGP(DGPRS, LOGL_ERROR, "BVCI=%u: Cannot find BSS\n",
-			ptp_bvci);
-		rate_ctr_inc(&cfg->ctrg->ctr[GBPROX_GLOB_CTR_INV_BVCI]);
-		return -ENOENT;
-	}
-
-	switch (pdu_type) {
-	case BSSGP_PDUT_BVC_BLOCK_ACK:
-		peer->blocked = 1;
-		rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_BLOCKED]);
-		break;
-	case BSSGP_PDUT_BVC_UNBLOCK_ACK:
-		peer->blocked = 0;
-		rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_UNBLOCKED]);
-		break;
-	default:
-		break;
-	}
-	return 0;
-}
-
-/* Send a message to a peer identified by ptp_bvci but using ns_bvci
- * in the NS hdr */
-static int gbprox_relay2bvci(struct gbproxy_config *cfg, struct msgb *msg, uint16_t ptp_bvci,
-			  uint16_t ns_bvci)
-{
-	struct gbproxy_peer *peer;
-
-	peer = gbproxy_peer_by_bvci(cfg, ptp_bvci);
-	if (!peer) {
-		LOGP(DGPRS, LOGL_ERROR, "BVCI=%u: Cannot find BSS\n",
-			ptp_bvci);
-		rate_ctr_inc(&cfg->ctrg->ctr[GBPROX_GLOB_CTR_INV_BVCI]);
-		return -ENOENT;
-	}
-
-	return gbprox_relay2peer(msg, peer, ns_bvci);
-}
-
-int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
-{
-	return 0;
-}
-
-/* Receive an incoming PTP message from a BSS-side NS-VC */
-static int gbprox_rx_ptp_from_bss(struct gbproxy_config *cfg,
-				  struct msgb *msg, uint16_t nsei,
-				  uint16_t nsvci, uint16_t ns_bvci)
-{
-	struct gbproxy_peer *peer;
-	struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg);
-	uint8_t pdu_type = bgph->pdu_type;
-	int rc;
-
-	peer = gbproxy_peer_by_bvci(cfg, ns_bvci);
-	if (!peer) {
-		LOGP(DGPRS, LOGL_NOTICE, "Didn't find peer for "
-		     "BVCI=%u for PTP message from NSVC=%u/NSEI=%u (BSS), "
-		     "discarding message\n",
-		     ns_bvci, nsvci, nsei);
-		return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI,
-				       &ns_bvci, msg);
-	}
-
-	check_peer_nsei(peer, nsei);
-
-	rc = gbprox_process_bssgp_ul(cfg, msg, peer);
-	if (!rc)
-		return 0;
-
-	switch (pdu_type) {
-	case BSSGP_PDUT_FLOW_CONTROL_BVC:
-		if (!cfg->route_to_sgsn2)
-			break;
-
-		/* Send a copy to the secondary SGSN */
-		gbprox_relay2sgsn(cfg, msg, ns_bvci, cfg->nsip_sgsn2_nsei);
-		break;
-	default:
-		break;
-	}
-
-
-	return gbprox_relay2sgsn(cfg, msg, ns_bvci, cfg->nsip_sgsn_nsei);
-}
-
-/* Receive an incoming PTP message from a SGSN-side NS-VC */
-static int gbprox_rx_ptp_from_sgsn(struct gbproxy_config *cfg,
-				   struct msgb *msg, uint16_t nsei,
-				   uint16_t nsvci, uint16_t ns_bvci)
-{
-	struct gbproxy_peer *peer;
-	struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg);
-	uint8_t pdu_type = bgph->pdu_type;
-
-	peer = gbproxy_peer_by_bvci(cfg, ns_bvci);
-
-	/* Send status messages before patching */
-
-	if (!peer) {
-		LOGP(DGPRS, LOGL_INFO, "Didn't find peer for "
-		     "BVCI=%u for message from NSVC=%u/NSEI=%u (SGSN)\n",
-		     ns_bvci, nsvci, nsei);
-		rate_ctr_inc(&cfg->ctrg->
-			     ctr[GBPROX_GLOB_CTR_INV_BVCI]);
-		return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI,
-				       &ns_bvci, msg);
-	}
-
-	if (peer->blocked) {
-		LOGP(DGPRS, LOGL_NOTICE, "Dropping PDU for "
-		     "blocked BVCI=%u via NSVC=%u/NSEI=%u\n",
-		     ns_bvci, nsvci, nsei);
-		rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_DROPPED]);
-		return bssgp_tx_status(BSSGP_CAUSE_BVCI_BLOCKED, &ns_bvci, msg);
-	}
-
-	switch (pdu_type) {
-	case BSSGP_PDUT_FLOW_CONTROL_BVC_ACK:
-	case BSSGP_PDUT_BVC_BLOCK_ACK:
-	case BSSGP_PDUT_BVC_UNBLOCK_ACK:
-		if (cfg->route_to_sgsn2 && nsei == cfg->nsip_sgsn2_nsei)
-			/* Hide ACKs from the secondary SGSN, the primary SGSN
-			 * is responsible to send them. */
-			return 0;
-		break;
-	default:
-		break;
-	}
-
-	/* Optionally patch the message */
-	gbprox_process_bssgp_dl(cfg, msg, peer);
-
-	return gbprox_relay2peer(msg, peer, ns_bvci);
-}
-
-/* Receive an incoming signalling message from a BSS-side NS-VC */
-static int gbprox_rx_sig_from_bss(struct gbproxy_config *cfg,
-				  struct msgb *msg, uint16_t nsei,
-				  uint16_t ns_bvci)
-{
-	struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg);
-	struct tlv_parsed tp;
-	uint8_t pdu_type = bgph->pdu_type;
-	int data_len = msgb_bssgp_len(msg) - sizeof(*bgph);
-	struct gbproxy_peer *from_peer = NULL;
-	struct gprs_ra_id raid;
-	int copy_to_sgsn2 = 0;
-	int rc;
-
-	if (ns_bvci != 0 && ns_bvci != 1) {
-		LOGP(DGPRS, LOGL_NOTICE, "NSEI=%u BVCI=%u is not signalling\n",
-			nsei, ns_bvci);
-		return -EINVAL;
-	}
-
-	/* we actually should never see those two for BVCI == 0, but double-check
-	 * just to make sure  */
-	if (pdu_type == BSSGP_PDUT_UL_UNITDATA ||
-	    pdu_type == BSSGP_PDUT_DL_UNITDATA) {
-		LOGP(DGPRS, LOGL_NOTICE, "NSEI=%u UNITDATA not allowed in "
-			"signalling\n", nsei);
-		return -EINVAL;
-	}
-
-	bssgp_tlv_parse(&tp, bgph->data, data_len);
-
-	switch (pdu_type) {
-	case BSSGP_PDUT_SUSPEND:
-	case BSSGP_PDUT_RESUME:
-		/* We implement RAI snooping during SUSPEND/RESUME, since it
-		 * establishes a relationsip between BVCI/peer and the routeing
-		 * area identification.  The snooped information is then used
-		 * for routing the {SUSPEND,RESUME}_[N]ACK back to the correct
-		 * BSSGP */
-		if (!TLVP_PRESENT(&tp, BSSGP_IE_ROUTEING_AREA))
-			goto err_mand_ie;
-		from_peer = gbproxy_peer_by_nsei(cfg, nsei);
-		if (!from_peer)
-			goto err_no_peer;
-		memcpy(from_peer->ra, TLVP_VAL(&tp, BSSGP_IE_ROUTEING_AREA),
-			sizeof(from_peer->ra));
-		gsm48_parse_ra(&raid, from_peer->ra);
-		LOGP(DGPRS, LOGL_INFO, "NSEI=%u BSSGP SUSPEND/RESUME "
-			"RAI snooping: RAI %u-%u-%u-%u behind BVCI=%u\n",
-			nsei, raid.mcc, raid.mnc, raid.lac,
-			raid.rac , from_peer->bvci);
-		/* FIXME: This only supports one BSS per RA */
-		break;
-	case BSSGP_PDUT_BVC_RESET:
-		/* If we receive a BVC reset on the signalling endpoint, we
-		 * don't want the SGSN to reset, as the signalling endpoint
-		 * is common for all point-to-point BVCs (and thus all BTS) */
-		if (TLVP_PRESENT(&tp, BSSGP_IE_BVCI)) {
-			uint16_t bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI));
-			LOGP(DGPRS, LOGL_INFO, "NSEI=%u Rx BVC RESET (BVCI=%u)\n",
-				nsei, bvci);
-			if (bvci == 0) {
-				/* FIXME: only do this if SGSN is alive! */
-				LOGP(DGPRS, LOGL_INFO, "NSEI=%u Tx fake "
-					"BVC RESET ACK of BVCI=0\n", nsei);
-				return bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_RESET_ACK,
-							    nsei, 0, ns_bvci);
-			}
-			from_peer = gbproxy_peer_by_bvci(cfg, bvci);
-			if (!from_peer) {
-				/* if a PTP-BVC is reset, and we don't know that
-				 * PTP-BVCI yet, we should allocate a new peer */
-				LOGP(DGPRS, LOGL_INFO, "Allocationg new peer for "
-				     "BVCI=%u via NSEI=%u\n", bvci, nsei);
-				from_peer = gbproxy_peer_alloc(cfg, bvci);
-				from_peer->nsei = nsei;
-			}
-
-			if (!check_peer_nsei(from_peer, nsei))
-				from_peer->nsei = nsei;
-
-			if (TLVP_PRESENT(&tp, BSSGP_IE_CELL_ID)) {
-				struct gprs_ra_id raid;
-				/* We have a Cell Identifier present in this
-				 * PDU, this means we can extend our local
-				 * state information about this particular cell
-				 * */
-				memcpy(from_peer->ra,
-					TLVP_VAL(&tp, BSSGP_IE_CELL_ID),
-					sizeof(from_peer->ra));
-				gsm48_parse_ra(&raid, from_peer->ra);
-				LOGP(DGPRS, LOGL_INFO, "NSEI=%u/BVCI=%u "
-				     "Cell ID %u-%u-%u-%u\n", nsei,
-				     bvci, raid.mcc, raid.mnc, raid.lac,
-				     raid.rac);
-			}
-			if (cfg->route_to_sgsn2)
-				copy_to_sgsn2 = 1;
-		}
-		break;
-	}
-
-	/* Normally, we can simply pass on all signalling messages from BSS to
-	 * SGSN */
-	rc = gbprox_process_bssgp_ul(cfg, msg, from_peer);
-	if (!rc)
-		return 0;
-
-	if (copy_to_sgsn2)
-		gbprox_relay2sgsn(cfg, msg, ns_bvci, cfg->nsip_sgsn2_nsei);
-
-	return gbprox_relay2sgsn(cfg, msg, ns_bvci, cfg->nsip_sgsn_nsei);
-err_no_peer:
-	LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) cannot find peer based on NSEI\n",
-		nsei);
-	rate_ctr_inc(&cfg->ctrg->ctr[GBPROX_GLOB_CTR_INV_NSEI]);
-	return bssgp_tx_status(BSSGP_CAUSE_INV_MAND_INF, NULL, msg);
-err_mand_ie:
-	LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) missing mandatory RA IE\n",
-		nsei);
-	rate_ctr_inc(&cfg->ctrg->ctr[GBPROX_GLOB_CTR_PROTO_ERR_BSS]);
-	return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg);
-}
-
-/* Receive paging request from SGSN, we need to relay to proper BSS */
-static int gbprox_rx_paging(struct gbproxy_config *cfg, struct msgb *msg, struct tlv_parsed *tp,
-			    uint32_t nsei, uint16_t ns_bvci)
-{
-	struct gbproxy_peer *peer = NULL;
-	int errctr = GBPROX_GLOB_CTR_PROTO_ERR_SGSN;
-
-	LOGP(DGPRS, LOGL_INFO, "NSEI=%u(SGSN) BSSGP PAGING ",
-		nsei);
-	if (TLVP_PRESENT(tp, BSSGP_IE_BVCI)) {
-		uint16_t bvci = ntohs(tlvp_val16_unal(tp, BSSGP_IE_BVCI));
-		LOGPC(DGPRS, LOGL_INFO, "routing by BVCI to peer BVCI=%u\n",
-			bvci);
-		errctr = GBPROX_GLOB_CTR_OTHER_ERR;
-	} else if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA)) {
-		peer = gbproxy_peer_by_rai(cfg, TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA));
-		LOGPC(DGPRS, LOGL_INFO, "routing by RAI to peer BVCI=%u\n",
-			peer ? peer->bvci : -1);
-		errctr = GBPROX_GLOB_CTR_INV_RAI;
-	} else if (TLVP_PRESENT(tp, BSSGP_IE_LOCATION_AREA)) {
-		peer = gbproxy_peer_by_lai(cfg, TLVP_VAL(tp, BSSGP_IE_LOCATION_AREA));
-		LOGPC(DGPRS, LOGL_INFO, "routing by LAI to peer BVCI=%u\n",
-			peer ? peer->bvci : -1);
-		errctr = GBPROX_GLOB_CTR_INV_LAI;
-	} else
-		LOGPC(DGPRS, LOGL_INFO, "\n");
-
-	if (!peer) {
-		LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) BSSGP PAGING: "
-			"unable to route, missing IE\n", nsei);
-		rate_ctr_inc(&cfg->ctrg->ctr[errctr]);
-		return -EINVAL;
-	}
-	return gbprox_relay2peer(msg, peer, ns_bvci);
-}
-
-/* Receive an incoming BVC-RESET message from the SGSN */
-static int rx_reset_from_sgsn(struct gbproxy_config *cfg,
-			struct msgb *orig_msg,
-			struct msgb *msg, struct tlv_parsed *tp,
-			uint32_t nsei, uint16_t ns_bvci)
-{
-	struct gbproxy_peer *peer;
-	uint16_t ptp_bvci;
-
-	if (!TLVP_PRESENT(tp, BSSGP_IE_BVCI)) {
-		rate_ctr_inc(&cfg->ctrg->
-			     ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]);
-		return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE,
-				       NULL, orig_msg);
-	}
-	ptp_bvci = ntohs(tlvp_val16_unal(tp, BSSGP_IE_BVCI));
-
-	if (ptp_bvci >= 2) {
-		/* A reset for a PTP BVC was received, forward it to its
-		 * respective peer */
-		peer = gbproxy_peer_by_bvci(cfg, ptp_bvci);
-		if (!peer) {
-			LOGP(DGPRS, LOGL_ERROR, "NSEI=%u BVCI=%u: Cannot find BSS\n",
-				nsei, ptp_bvci);
-			rate_ctr_inc(&cfg->ctrg->
-				     ctr[GBPROX_GLOB_CTR_INV_BVCI]);
-			return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI,
-					       &ptp_bvci, orig_msg);
-		}
-		return gbprox_relay2peer(msg, peer, ns_bvci);
-	}
-
-	/* A reset for the Signalling entity has been received
-	 * from the SGSN.  As the signalling BVCI is shared
-	 * among all the BSS's that we multiplex, it needs to
-	 * be relayed  */
-	llist_for_each_entry(peer, &cfg->bts_peers, list)
-		gbprox_relay2peer(msg, peer, ns_bvci);
-
-	return 0;
-}
-
-/* Receive an incoming signalling message from the SGSN-side NS-VC */
-static int gbprox_rx_sig_from_sgsn(struct gbproxy_config *cfg,
-				struct msgb *orig_msg, uint32_t nsei,
-				uint16_t ns_bvci)
-{
-	struct bssgp_normal_hdr *bgph =
-		(struct bssgp_normal_hdr *) msgb_bssgph(orig_msg);
-	struct tlv_parsed tp;
-	uint8_t pdu_type = bgph->pdu_type;
-	int data_len;
-	struct gbproxy_peer *peer;
-	uint16_t bvci;
-	struct msgb *msg;
-	int rc = 0;
-	int cause;
-
-	if (ns_bvci != 0 && ns_bvci != 1) {
-		LOGP(DGPRS, LOGL_NOTICE, "NSEI=%u(SGSN) BVCI=%u is not "
-			"signalling\n", nsei, ns_bvci);
-		/* FIXME: Send proper error message */
-		return -EINVAL;
-	}
-
-	/* we actually should never see those two for BVCI == 0, but double-check
-	 * just to make sure  */
-	if (pdu_type == BSSGP_PDUT_UL_UNITDATA ||
-	    pdu_type == BSSGP_PDUT_DL_UNITDATA) {
-		LOGP(DGPRS, LOGL_NOTICE, "NSEI=%u(SGSN) UNITDATA not allowed in "
-			"signalling\n", nsei);
-		return bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, orig_msg);
-	}
-
-	msg = gprs_msgb_copy(orig_msg, "rx_sig_from_sgsn");
-	gbprox_process_bssgp_dl(cfg, msg, NULL);
-	/* Update message info */
-	bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg);
-	data_len = msgb_bssgp_len(orig_msg) - sizeof(*bgph);
-	rc = bssgp_tlv_parse(&tp, bgph->data, data_len);
-
-	switch (pdu_type) {
-	case BSSGP_PDUT_BVC_RESET:
-		rc = rx_reset_from_sgsn(cfg, msg, orig_msg, &tp, nsei, ns_bvci);
-		break;
-	case BSSGP_PDUT_BVC_RESET_ACK:
-		if (cfg->route_to_sgsn2 && nsei == cfg->nsip_sgsn2_nsei)
-			break;
-		/* fall through */
-	case BSSGP_PDUT_FLUSH_LL:
-		/* simple case: BVCI IE is mandatory */
-		if (!TLVP_PRESENT(&tp, BSSGP_IE_BVCI))
-			goto err_mand_ie;
-		bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI));
-		rc = gbprox_relay2bvci(cfg, msg, bvci, ns_bvci);
-		break;
-	case BSSGP_PDUT_PAGING_PS:
-	case BSSGP_PDUT_PAGING_CS:
-		/* process the paging request (LAI/RAI lookup) */
-		rc = gbprox_rx_paging(cfg, msg, &tp, nsei, ns_bvci);
-		break;
-	case BSSGP_PDUT_STATUS:
-		/* Some exception has occurred */
-		LOGP(DGPRS, LOGL_NOTICE,
-			"NSEI=%u(SGSN) BSSGP STATUS ", nsei);
-		if (!TLVP_PRESENT(&tp, BSSGP_IE_CAUSE)) {
-			LOGPC(DGPRS, LOGL_NOTICE, "\n");
-			goto err_mand_ie;
-		}
-		cause = *TLVP_VAL(&tp, BSSGP_IE_CAUSE);
-		LOGPC(DGPRS, LOGL_NOTICE,
-			"cause=0x%02x(%s) ", *TLVP_VAL(&tp, BSSGP_IE_CAUSE),
-			bssgp_cause_str(cause));
-		if (TLVP_PRESENT(&tp, BSSGP_IE_BVCI)) {
-			bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI));
-			LOGPC(DGPRS, LOGL_NOTICE, "BVCI=%u\n", bvci);
-
-			if (cause == BSSGP_CAUSE_UNKNOWN_BVCI)
-				rc = gbprox_relay2bvci(cfg, msg, bvci, ns_bvci);
-		} else
-			LOGPC(DGPRS, LOGL_NOTICE, "\n");
-		break;
-	/* those only exist in the SGSN -> BSS direction */
-	case BSSGP_PDUT_SUSPEND_ACK:
-	case BSSGP_PDUT_SUSPEND_NACK:
-	case BSSGP_PDUT_RESUME_ACK:
-	case BSSGP_PDUT_RESUME_NACK:
-		/* RAI IE is mandatory */
-		if (!TLVP_PRESENT(&tp, BSSGP_IE_ROUTEING_AREA))
-			goto err_mand_ie;
-		peer = gbproxy_peer_by_rai(cfg, TLVP_VAL(&tp, BSSGP_IE_ROUTEING_AREA));
-		if (!peer)
-			goto err_no_peer;
-		rc = gbprox_relay2peer(msg, peer, ns_bvci);
-		break;
-	case BSSGP_PDUT_BVC_BLOCK_ACK:
-	case BSSGP_PDUT_BVC_UNBLOCK_ACK:
-		if (!TLVP_PRESENT(&tp, BSSGP_IE_BVCI))
-			goto err_mand_ie;
-		bvci = ntohs(tlvp_val16_unal(&tp, BSSGP_IE_BVCI));
-		if (bvci == 0) {
-			LOGP(DGPRS, LOGL_NOTICE, "NSEI=%u(SGSN) BSSGP "
-			     "%sBLOCK_ACK for signalling BVCI ?!?\n", nsei,
-			     pdu_type == BSSGP_PDUT_BVC_UNBLOCK_ACK ? "UN":"");
-			/* should we send STATUS ? */
-			rate_ctr_inc(&cfg->ctrg->
-				     ctr[GBPROX_GLOB_CTR_INV_BVCI]);
-		} else {
-			/* Mark BVC as (un)blocked */
-			block_unblock_peer(cfg, bvci, pdu_type);
-		}
-		rc = gbprox_relay2bvci(cfg, msg, bvci, ns_bvci);
-		break;
-	case BSSGP_PDUT_SGSN_INVOKE_TRACE:
-		LOGP(DGPRS, LOGL_ERROR,
-		     "NSEI=%u(SGSN) BSSGP INVOKE TRACE not supported\n",nsei);
-		rate_ctr_inc(&cfg->ctrg->
-			     ctr[GBPROX_GLOB_CTR_NOT_SUPPORTED_SGSN]);
-		rc = bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_FEAT, NULL, orig_msg);
-		break;
-	default:
-		LOGP(DGPRS, LOGL_NOTICE, "BSSGP PDU type %s not supported\n", bssgp_pdu_str(pdu_type));
-		rate_ctr_inc(&cfg->ctrg->
-			     ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]);
-		rc = bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, orig_msg);
-		break;
-	}
-
-	msgb_free(msg);
-
-	return rc;
-err_mand_ie:
-	LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) missing mandatory IE\n",
-		nsei);
-	rate_ctr_inc(&cfg->ctrg->
-		     ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]);
-	msgb_free(msg);
-	return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, orig_msg);
-err_no_peer:
-	LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) cannot find peer based on RAI\n",
-		nsei);
-	rate_ctr_inc(&cfg->ctrg-> ctr[GBPROX_GLOB_CTR_INV_RAI]);
-	msgb_free(msg);
-	return bssgp_tx_status(BSSGP_CAUSE_INV_MAND_INF, NULL, orig_msg);
-}
-
-static int gbproxy_is_sgsn_nsei(struct gbproxy_config *cfg, uint16_t nsei)
-{
-	return nsei == cfg->nsip_sgsn_nsei ||
-		(cfg->route_to_sgsn2 && nsei == cfg->nsip_sgsn2_nsei);
-}
-
-/* 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 rc;
-	int remote_end_is_sgsn = gbproxy_is_sgsn_nsei(cfg, nsei);
-
-	/* Only BVCI=0 messages need special treatment */
-	if (ns_bvci == 0 || ns_bvci == 1) {
-		if (remote_end_is_sgsn)
-			rc = gbprox_rx_sig_from_sgsn(cfg, msg, nsei, ns_bvci);
-		else
-			rc = gbprox_rx_sig_from_bss(cfg, msg, nsei, ns_bvci);
-	} else {
-		/* All other BVCI are PTP */
-		if (remote_end_is_sgsn)
-			rc = gbprox_rx_ptp_from_sgsn(cfg, msg, nsei, nsvci,
-						     ns_bvci);
-		else
-			rc = gbprox_rx_ptp_from_bss(cfg, msg, nsei, nsvci,
-						    ns_bvci);
-	}
-
-	return rc;
-}
-
-int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi)
-{
-	struct gprs_nsvc *nsvc;
-
-	llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
-		if (!nsvc->persistent)
-			continue;
-		gprs_nsvc_reset(nsvc, NS_CAUSE_OM_INTERVENTION);
-	}
-	return 0;
-}
-
-/* Signal handler for signals from NS layer */
-int gbprox_signal(unsigned int subsys, unsigned int signal,
-		  void *handler_data, void *signal_data)
-{
-	struct gbproxy_config *cfg = handler_data;
-	struct ns_signal_data *nssd = signal_data;
-	struct gprs_nsvc *nsvc = nssd->nsvc;
-	struct gbproxy_peer *peer;
-	int remote_end_is_sgsn = gbproxy_is_sgsn_nsei(cfg, nsvc->nsei);
-
-	if (subsys != SS_L_NS)
-		return 0;
-
-	if (signal == S_NS_RESET && remote_end_is_sgsn) {
-		/* We have received a NS-RESET from the NSEI and NSVC
-		 * of the SGSN.  This might happen with SGSN that start
-		 * their own NS-RESET procedure without waiting for our
-		 * NS-RESET */
-		nsvc->remote_end_is_sgsn = 1;
-	}
-
-	if (signal == S_NS_ALIVE_EXP && nsvc->remote_end_is_sgsn) {
-		LOGP(DGPRS, LOGL_NOTICE, "Tns alive expired too often, "
-			"re-starting RESET procedure\n");
-		rate_ctr_inc(&cfg->ctrg->
-			     ctr[GBPROX_GLOB_CTR_RESTART_RESET_SGSN]);
-		gprs_ns_nsip_connect(nsvc->nsi, &nsvc->ip.bts_addr,
-				  nsvc->nsei, nsvc->nsvci);
-	}
-
-	if (!nsvc->remote_end_is_sgsn) {
-		/* from BSS to SGSN */
-		peer = gbproxy_peer_by_nsei(cfg, nsvc->nsei);
-		if (!peer) {
-			LOGP(DGPRS, LOGL_NOTICE, "signal '%s' for unknown peer NSEI=%u/NSVCI=%u\n",
-			     get_value_string(gprs_ns_signal_ns_names, signal), nsvc->nsei, nsvc->nsvci);
-			return 0;
-		}
-		switch (signal) {
-		case S_NS_RESET:
-		case S_NS_BLOCK:
-			if (!peer->blocked)
-				break;
-			LOGP(DGPRS, LOGL_NOTICE, "Converting '%s' from NSEI=%u/NSVCI=%u into BSSGP_BVC_BLOCK to SGSN\n",
-			     get_value_string(gprs_ns_signal_ns_names, signal), nsvc->nsei, nsvc->nsvci);
-			bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_BLOCK, nsvc->nsei,
-					     peer->bvci, 0);
-			break;
-		}
-	} else {
-		/* Forward this message to all NS-VC to BSS */
-		struct gprs_ns_inst *nsi = cfg->nsi;
-		struct gprs_nsvc *next_nsvc;
-
-		llist_for_each_entry(next_nsvc, &nsi->gprs_nsvcs, list) {
-			if (next_nsvc->remote_end_is_sgsn)
-				continue;
-
-			/* Note that the following does not start the full
-			 * procedures including timer based retransmissions. */
-			switch (signal) {
-			case S_NS_RESET:
-				gprs_ns_tx_reset(next_nsvc, nssd->cause);
-				break;
-			case S_NS_BLOCK:
-				gprs_ns_tx_block(next_nsvc, nssd->cause);
-				break;
-			case S_NS_UNBLOCK:
-				gprs_ns_tx_unblock(next_nsvc);
-				break;
-			}
-		}
-	}
-	return 0;
-}
-
-void gbprox_reset(struct gbproxy_config *cfg)
-{
-	struct gbproxy_peer *peer, *tmp;
-
-	llist_for_each_entry_safe(peer, tmp, &cfg->bts_peers, list)
-		gbproxy_peer_free(peer);
-
-	rate_ctr_group_free(cfg->ctrg);
-	gbproxy_init_config(cfg);
-}
-
-int gbproxy_init_config(struct gbproxy_config *cfg)
-{
-	struct timespec tp;
-
-	INIT_LLIST_HEAD(&cfg->bts_peers);
-	cfg->ctrg = rate_ctr_group_alloc(tall_bsc_ctx, &global_ctrg_desc, 0);
-	if (!cfg->ctrg) {
-		LOGP(DGPRS, LOGL_ERROR, "Cannot allocate global counter group!\n");
-		return -1;
-	}
-	clock_gettime(CLOCK_REALTIME, &tp);
-
-	return 0;
-}
diff --git a/src/gprs/gb_proxy_main.c b/src/gprs/gb_proxy_main.c
deleted file mode 100644
index caff27f..0000000
--- a/src/gprs/gb_proxy_main.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/* NS-over-IP proxy */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.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/>.
- *
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <errno.h>
-#include <signal.h>
-#include <sys/fcntl.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/core/stats.h>
-
-#include <osmocom/gprs/gprs_ns.h>
-#include <osmocom/gprs/gprs_bssgp.h>
-
-#include <openbsc/signal.h>
-#include <openbsc/debug.h>
-#include <openbsc/vty.h>
-#include <openbsc/gb_proxy.h>
-
-#include <osmocom/vty/command.h>
-#include <osmocom/vty/telnet_interface.h>
-#include <osmocom/vty/logging.h>
-#include <osmocom/vty/stats.h>
-#include <osmocom/vty/ports.h>
-
-#include "../../bscconfig.h"
-
-#define _GNU_SOURCE
-#include <getopt.h>
-
-void *tall_bsc_ctx;
-
-const char *openbsc_copyright =
-	"Copyright (C) 2010 Harald Welte and On-Waves\r\n"
-	"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
-	"This is free software: you are free to change and redistribute it.\r\n"
-	"There is NO WARRANTY, to the extent permitted by law.\r\n";
-
-static char *config_file = "osmo_gbproxy.cfg";
-struct gbproxy_config gbcfg = {0};
-static int daemonize = 0;
-
-/* Pointer to the SGSN peer */
-extern struct gbprox_peer *gbprox_peer_sgsn;
-
-/* call-back function for the NS protocol */
-static int proxy_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
-		      struct msgb *msg, uint16_t bvci)
-{
-	int rc = 0;
-
-	switch (event) {
-	case GPRS_NS_EVT_UNIT_DATA:
-		rc = gbprox_rcvmsg(&gbcfg, msg, nsvc->nsei, bvci, nsvc->nsvci);
-		break;
-	default:
-		LOGP(DGPRS, LOGL_ERROR, "SGSN: Unknown event %u from NS\n", event);
-		if (msg)
-			msgb_free(msg);
-		rc = -EIO;
-		break;
-	}
-	return rc;
-}
-
-static void signal_handler(int signal)
-{
-	fprintf(stdout, "signal %u received\n", signal);
-
-	switch (signal) {
-	case SIGINT:
-	case SIGTERM:
-		osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL);
-		sleep(1);
-		exit(0);
-		break;
-	case SIGABRT:
-		/* in case of abort, we want to obtain a talloc report
-		 * and then return to the caller, who will abort the process */
-	case SIGUSR1:
-		talloc_report(tall_vty_ctx, stderr);
-		talloc_report_full(tall_bsc_ctx, stderr);
-		break;
-	case SIGUSR2:
-		talloc_report_full(tall_vty_ctx, stderr);
-		break;
-	default:
-		break;
-	}
-}
-
-static void print_usage()
-{
-	printf("Usage: bsc_hack\n");
-}
-
-static void print_help()
-{
-	printf("  Some useful help...\n");
-	printf("  -h --help this text\n");
-	printf("  -d option --debug=DNS:DGPRS,0:0 enable debugging\n");
-	printf("  -D --daemonize Fork the process into a background daemon\n");
-	printf("  -c --config-file filename The config file to use.\n");
-	printf("  -s --disable-color\n");
-	printf("  -T --timestamp Prefix every log line with a timestamp\n");
-	printf("  -V --version. Print the version of OpenBSC.\n");
-	printf("  -e --log-level number. Set a global loglevel.\n");
-}
-
-static void handle_options(int argc, char **argv)
-{
-	while (1) {
-		int option_index = 0, c;
-		static struct option long_options[] = {
-			{ "help", 0, 0, 'h' },
-			{ "debug", 1, 0, 'd' },
-			{ "daemonize", 0, 0, 'D' },
-			{ "config-file", 1, 0, 'c' },
-			{ "disable-color", 0, 0, 's' },
-			{ "timestamp", 0, 0, 'T' },
-			{ "version", 0, 0, 'V' },
-			{ "log-level", 1, 0, 'e' },
-			{ 0, 0, 0, 0 }
-		};
-
-		c = getopt_long(argc, argv, "hd:Dc:sTVe:",
-				long_options, &option_index);
-		if (c == -1)
-			break;
-
-		switch (c) {
-		case 'h':
-			print_usage();
-			print_help();
-			exit(0);
-		case 's':
-			log_set_use_color(osmo_stderr_target, 0);
-			break;
-		case 'd':
-			log_parse_category_mask(osmo_stderr_target, optarg);
-			break;
-		case 'D':
-			daemonize = 1;
-			break;
-		case 'c':
-			config_file = optarg;
-			break;
-		case 'T':
-			log_set_print_timestamp(osmo_stderr_target, 1);
-			break;
-		case 'e':
-			log_set_log_level(osmo_stderr_target, atoi(optarg));
-			break;
-		case 'V':
-			print_version(1);
-			exit(0);
-			break;
-		default:
-			break;
-		}
-	}
-}
-
-extern int bsc_vty_go_parent(struct vty *vty);
-
-static struct vty_app_info vty_info = {
-	.name 		= "OsmoGbProxy",
-	.version	= PACKAGE_VERSION,
-	.go_parent_cb	= bsc_vty_go_parent,
-	.is_config_node	= bsc_vty_is_config_node,
-};
-
-/* default categories */
-static struct log_info_cat gprs_categories[] = {
-	[DGPRS] = {
-		.name = "DGPRS",
-		.description = "GPRS Packet Service",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DNS] = {
-		.name = "DNS",
-		.description = "GPRS Network Service (NS)",
-		.enabled = 1, .loglevel = LOGL_INFO,
-	},
-	[DBSSGP] = {
-		.name = "DBSSGP",
-		.description = "GPRS BSS Gateway Protocol (BSSGP)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-};
-
-static const struct log_info gprs_log_info = {
-	.filter_fn = gprs_log_filter_fn,
-	.cat = gprs_categories,
-	.num_cat = ARRAY_SIZE(gprs_categories),
-};
-
-int main(int argc, char **argv)
-{
-	struct gsm_network dummy_network;
-	int rc;
-
-	tall_bsc_ctx = talloc_named_const(NULL, 0, "nsip_proxy");
-	msgb_talloc_ctx_init(tall_bsc_ctx, 0);
-
-	signal(SIGINT, &signal_handler);
-	signal(SIGTERM, &signal_handler);
-	signal(SIGABRT, &signal_handler);
-	signal(SIGUSR1, &signal_handler);
-	signal(SIGUSR2, &signal_handler);
-	osmo_init_ignore_signals();
-
-	osmo_init_logging(&gprs_log_info);
-
-	vty_info.copyright = openbsc_copyright;
-	vty_init(&vty_info);
-	logging_vty_add_cmds(NULL);
-	osmo_stats_vty_add_cmds(&gprs_log_info);
-	gbproxy_vty_init();
-
-	handle_options(argc, argv);
-
-	rate_ctr_init(tall_bsc_ctx);
-	osmo_stats_init(tall_bsc_ctx);
-
-	bssgp_nsi = gprs_ns_instantiate(&proxy_ns_cb, tall_bsc_ctx);
-	if (!bssgp_nsi) {
-		LOGP(DGPRS, LOGL_ERROR, "Unable to instantiate NS\n");
-		exit(1);
-	}
-	gbproxy_init_config(&gbcfg);
-	gbcfg.nsi = bssgp_nsi;
-	gprs_ns_vty_init(bssgp_nsi);
-	gprs_ns_set_log_ss(DNS);
-	bssgp_set_log_ss(DBSSGP);
-	osmo_signal_register_handler(SS_L_NS, &gbprox_signal, &gbcfg);
-
-	rc = gbproxy_parse_config(config_file, &gbcfg);
-	if (rc < 0) {
-		LOGP(DGPRS, LOGL_FATAL, "Cannot parse config file\n");
-		exit(2);
-	}
-
-	/* start telnet after reading config for vty_get_bind_addr() */
-	rc = telnet_init_dynif(tall_bsc_ctx, &dummy_network,
-			       vty_get_bind_addr(), OSMO_VTY_PORT_GBPROXY);
-	if (rc < 0)
-		exit(1);
-
-	if (!gprs_nsvc_by_nsei(gbcfg.nsi, gbcfg.nsip_sgsn_nsei)) {
-		LOGP(DGPRS, LOGL_FATAL, "You cannot proxy to NSEI %u "
-			"without creating that NSEI before\n",
-			gbcfg.nsip_sgsn_nsei);
-		exit(2);
-	}
-
-	rc = gprs_ns_nsip_listen(bssgp_nsi);
-	if (rc < 0) {
-		LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen on NSIP socket\n");
-		exit(2);
-	}
-
-	rc = gprs_ns_frgre_listen(bssgp_nsi);
-	if (rc < 0) {
-		LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen GRE "
-			"socket. Do you have CAP_NET_RAW?\n");
-		exit(2);
-	}
-
-	if (daemonize) {
-		rc = osmo_daemonize();
-		if (rc < 0) {
-			perror("Error during daemonize");
-			exit(1);
-		}
-	}
-
-	/* Reset all the persistent NS-VCs that we've read from the config */
-	gbprox_reset_persistent_nsvcs(bssgp_nsi);
-
-	while (1) {
-		rc = osmo_select_main(0);
-		if (rc < 0)
-			exit(3);
-	}
-
-	exit(0);
-}
diff --git a/src/gprs/gb_proxy_patch.c b/src/gprs/gb_proxy_patch.c
deleted file mode 100644
index 210fb2b..0000000
--- a/src/gprs/gb_proxy_patch.c
+++ /dev/null
@@ -1,459 +0,0 @@
-/* Gb-proxy message patching */
-
-/* (C) 2014 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/>.
- *
- */
-
-#include <openbsc/gb_proxy.h>
-
-#include <openbsc/gprs_utils.h>
-#include <openbsc/gprs_gb_parse.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/debug.h>
-
-#include <osmocom/gprs/protocol/gsm_08_18.h>
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/gsm/apn.h>
-
-/* patch RA identifier in place */
-static void gbproxy_patch_raid(uint8_t *raid_enc, struct gbproxy_peer *peer,
-			       int to_bss, const char *log_text)
-{
-	struct gbproxy_patch_state *state = &peer->patch_state;
-	int old_mcc;
-	int old_mnc;
-	struct gprs_ra_id raid;
-	enum gbproxy_peer_ctr counter =
-		to_bss ?
-		GBPROX_PEER_CTR_RAID_PATCHED_SGSN :
-		GBPROX_PEER_CTR_RAID_PATCHED_BSS;
-
-	if (!state->local_mcc || !state->local_mnc)
-		return;
-
-	gsm48_parse_ra(&raid, raid_enc);
-
-	old_mcc = raid.mcc;
-	old_mnc = raid.mnc;
-
-	if (!to_bss) {
-		/* BSS -> SGSN */
-		if (state->local_mcc)
-			raid.mcc = peer->cfg->core_mcc;
-
-		if (state->local_mnc)
-			raid.mnc = peer->cfg->core_mnc;
-	} else {
-		/* SGSN -> BSS */
-		if (state->local_mcc)
-			raid.mcc = state->local_mcc;
-
-		if (state->local_mnc)
-			raid.mnc = state->local_mnc;
-	}
-
-	LOGP(DGPRS, LOGL_DEBUG,
-	     "Patching %s to %s: "
-	     "%d-%d-%d-%d -> %d-%d-%d-%d\n",
-	     log_text,
-	     to_bss ? "BSS" : "SGSN",
-	     old_mcc, old_mnc, raid.lac, raid.rac,
-	     raid.mcc, raid.mnc, raid.lac, raid.rac);
-
-	gsm48_construct_ra(raid_enc, &raid);
-	rate_ctr_inc(&peer->ctrg->ctr[counter]);
-}
-
-static void gbproxy_patch_apn_ie(struct msgb *msg,
-				 uint8_t *apn_ie, size_t apn_ie_len,
-				 struct gbproxy_peer *peer,
-				 size_t *new_apn_ie_len, const char *log_text)
-{
-	struct apn_ie_hdr {
-		uint8_t iei;
-		uint8_t apn_len;
-		uint8_t apn[0];
-	} *hdr = (void *)apn_ie;
-
-	size_t apn_len = hdr->apn_len;
-	uint8_t *apn = hdr->apn;
-
-	OSMO_ASSERT(apn_ie_len == apn_len + sizeof(struct apn_ie_hdr));
-	OSMO_ASSERT(apn_ie_len > 2 && apn_ie_len <= 102);
-
-	if (peer->cfg->core_apn_size == 0) {
-		char str1[110];
-		/* Remove the IE */
-		LOGP(DGPRS, LOGL_DEBUG,
-		     "Patching %s to SGSN: Removing APN '%s'\n",
-		     log_text,
-		     osmo_apn_to_str(str1, apn, apn_len));
-
-		*new_apn_ie_len = 0;
-		gprs_msgb_resize_area(msg, apn_ie, apn_ie_len, 0);
-	} else {
-		/* Resize the IE */
-		char str1[110];
-		char str2[110];
-
-		OSMO_ASSERT(peer->cfg->core_apn_size <= 100);
-
-		LOGP(DGPRS, LOGL_DEBUG,
-		     "Patching %s to SGSN: "
-		     "Replacing APN '%s' -> '%s'\n",
-		     log_text,
-		     osmo_apn_to_str(str1, apn, apn_len),
-		     osmo_apn_to_str(str2, peer->cfg->core_apn,
-				       peer->cfg->core_apn_size));
-
-		*new_apn_ie_len = peer->cfg->core_apn_size + 2;
-		gprs_msgb_resize_area(msg, apn, apn_len, peer->cfg->core_apn_size);
-		memcpy(apn, peer->cfg->core_apn, peer->cfg->core_apn_size);
-		hdr->apn_len = peer->cfg->core_apn_size;
-	}
-
-	rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_APN_PATCHED]);
-}
-
-static int gbproxy_patch_tlli(uint8_t *tlli_enc,
-			      struct gbproxy_peer *peer,
-			      uint32_t new_tlli,
-			      int to_bss, const char *log_text)
-{
-	uint32_t tlli_be;
-	uint32_t tlli;
-	enum gbproxy_peer_ctr counter =
-		to_bss ?
-		GBPROX_PEER_CTR_TLLI_PATCHED_SGSN :
-		GBPROX_PEER_CTR_TLLI_PATCHED_BSS;
-
-	memcpy(&tlli_be, tlli_enc, sizeof(tlli_be));
-	tlli = ntohl(tlli_be);
-
-	if (tlli == new_tlli)
-		return 0;
-
-	LOGP(DGPRS, LOGL_DEBUG,
-	     "Patching %ss: "
-	     "Replacing %08x -> %08x\n",
-	     log_text, tlli, new_tlli);
-
-	tlli_be = htonl(new_tlli);
-	memcpy(tlli_enc, &tlli_be, sizeof(tlli_be));
-
-	rate_ctr_inc(&peer->ctrg->ctr[counter]);
-
-	return 1;
-}
-
-static int gbproxy_patch_ptmsi(uint8_t *ptmsi_enc,
-			       struct gbproxy_peer *peer,
-			       uint32_t new_ptmsi,
-			       int to_bss, const char *log_text)
-{
-	uint32_t ptmsi_be;
-	uint32_t ptmsi;
-	enum gbproxy_peer_ctr counter =
-		to_bss ?
-		GBPROX_PEER_CTR_PTMSI_PATCHED_SGSN :
-		GBPROX_PEER_CTR_PTMSI_PATCHED_BSS;
-	memcpy(&ptmsi_be, ptmsi_enc, sizeof(ptmsi_be));
-	ptmsi = ntohl(ptmsi_be);
-
-	if (ptmsi == new_ptmsi)
-		return 0;
-
-	LOGP(DGPRS, LOGL_DEBUG,
-	     "Patching %ss: "
-	     "Replacing %08x -> %08x\n",
-	     log_text, ptmsi, new_ptmsi);
-
-	ptmsi_be = htonl(new_ptmsi);
-	memcpy(ptmsi_enc, &ptmsi_be, sizeof(ptmsi_be));
-
-	rate_ctr_inc(&peer->ctrg->ctr[counter]);
-
-	return 1;
-}
-
-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)
-{
-	struct gprs_llc_hdr_parsed *ghp = &parse_ctx->llc_hdr_parsed;
-	int have_patched = 0;
-	int fcs;
-	struct gbproxy_config *cfg = peer->cfg;
-
-	if (parse_ctx->ptmsi_enc && link_info &&
-	    !parse_ctx->old_raid_is_foreign && peer->cfg->patch_ptmsi) {
-		uint32_t ptmsi;
-		if (parse_ctx->to_bss)
-			ptmsi = link_info->tlli.ptmsi;
-		else
-			ptmsi = link_info->sgsn_tlli.ptmsi;
-
-		if (ptmsi != GSM_RESERVED_TMSI) {
-			if (gbproxy_patch_ptmsi(parse_ctx->ptmsi_enc, peer,
-						ptmsi, parse_ctx->to_bss, "P-TMSI"))
-				have_patched = 1;
-		} else {
-			/* TODO: invalidate old RAI if present (see below) */
-		}
-	}
-
-	if (parse_ctx->new_ptmsi_enc && link_info && cfg->patch_ptmsi) {
-		uint32_t ptmsi;
-		if (parse_ctx->to_bss)
-			ptmsi = link_info->tlli.ptmsi;
-		else
-			ptmsi = link_info->sgsn_tlli.ptmsi;
-
-		OSMO_ASSERT(ptmsi);
-		if (gbproxy_patch_ptmsi(parse_ctx->new_ptmsi_enc, peer,
-					ptmsi, parse_ctx->to_bss, "new P-TMSI"))
-			have_patched = 1;
-	}
-
-	if (parse_ctx->raid_enc) {
-		gbproxy_patch_raid(parse_ctx->raid_enc, peer, parse_ctx->to_bss,
-				   parse_ctx->llc_msg_name);
-		have_patched = 1;
-	}
-
-	if (parse_ctx->old_raid_enc && !parse_ctx->old_raid_is_foreign) {
-		/* TODO: Patch to invalid if P-TMSI unknown. */
-		gbproxy_patch_raid(parse_ctx->old_raid_enc, peer, parse_ctx->to_bss,
-				   parse_ctx->llc_msg_name);
-		have_patched = 1;
-	}
-
-	if (parse_ctx->apn_ie &&
-	    cfg->core_apn &&
-	    !parse_ctx->to_bss &&
-	    gbproxy_imsi_matches(cfg, GBPROX_MATCH_PATCHING, link_info) &&
-	    cfg->core_apn) {
-		size_t new_len;
-		gbproxy_patch_apn_ie(msg,
-				     parse_ctx->apn_ie, parse_ctx->apn_ie_len,
-				     peer, &new_len, parse_ctx->llc_msg_name);
-		*len_change += (int)new_len - (int)parse_ctx->apn_ie_len;
-
-		have_patched = 1;
-	}
-
-	if (have_patched) {
-		llc_len += *len_change;
-		ghp->crc_length += *len_change;
-
-		/* Fix FCS */
-		fcs = gprs_llc_fcs(llc, ghp->crc_length);
-		LOGP(DLLC, LOGL_DEBUG, "Updated LLC message, CRC: %06x -> %06x\n",
-		     ghp->fcs, fcs);
-
-		llc[llc_len - 3] = fcs & 0xff;
-		llc[llc_len - 2] = (fcs >> 8) & 0xff;
-		llc[llc_len - 1] = (fcs >> 16) & 0xff;
-	}
-
-	return have_patched;
-}
-
-/* patch BSSGP message to use core_mcc/mnc on the SGSN side */
-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)
-{
-	const char *err_info = NULL;
-	int err_ctr = -1;
-
-	if (parse_ctx->bssgp_raid_enc)
-		gbproxy_patch_raid(parse_ctx->bssgp_raid_enc, peer,
-				   parse_ctx->to_bss, "BSSGP");
-
-	if (parse_ctx->need_decryption &&
-	    (peer->cfg->patch_ptmsi || peer->cfg->core_apn)) {
-		/* Patching LLC messages has been requested
-		 * explicitly, but the message (including the
-		 * type) is encrypted, so we possibly fail to
-		 * patch the LLC part of the message. */
-		err_ctr = GBPROX_PEER_CTR_PATCH_CRYPT_ERR;
-		err_info = "GMM message is encrypted";
-		goto patch_error;
-	}
-
-	if (!link_info && parse_ctx->tlli_enc && parse_ctx->to_bss) {
-		/* Happens with unknown (not cached) TLLI coming from
-		 * the SGSN */
-		/* TODO: What shall be done with the message in this case? */
-		err_ctr = GBPROX_PEER_CTR_TLLI_UNKNOWN;
-		err_info = "TLLI sent by the SGSN is unknown";
-		goto patch_error;
-	}
-
-	if (!link_info)
-		return;
-
-	if (parse_ctx->tlli_enc && peer->cfg->patch_ptmsi) {
-		uint32_t tlli = gbproxy_map_tlli(parse_ctx->tlli,
-						 link_info, parse_ctx->to_bss);
-
-		if (tlli) {
-			gbproxy_patch_tlli(parse_ctx->tlli_enc, peer, tlli,
-					   parse_ctx->to_bss, "TLLI");
-			parse_ctx->tlli = tlli;
-		} else {
-			/* Internal error */
-			err_ctr = GBPROX_PEER_CTR_PATCH_ERR;
-			err_info = "Replacement TLLI is 0";
-			goto patch_error;
-		}
-	}
-
-	if (parse_ctx->bssgp_ptmsi_enc && peer->cfg->patch_ptmsi) {
-		uint32_t ptmsi;
-		if (parse_ctx->to_bss)
-			ptmsi = link_info->tlli.ptmsi;
-		else
-			ptmsi = link_info->sgsn_tlli.ptmsi;
-
-		if (ptmsi != GSM_RESERVED_TMSI)
-			gbproxy_patch_ptmsi(
-				parse_ctx->bssgp_ptmsi_enc, peer,
-				ptmsi, parse_ctx->to_bss, "BSSGP P-TMSI");
-	}
-
-	if (parse_ctx->llc) {
-		uint8_t *llc = parse_ctx->llc;
-		size_t llc_len = parse_ctx->llc_len;
-		int llc_len_change = 0;
-
-		gbproxy_patch_llc(msg, llc, llc_len, peer, link_info,
-				  &llc_len_change, parse_ctx);
-		/* Note that the APN might have been resized here, but no
-		 * pointer int the parse_ctx will refer to an adress after the
-		 * APN. So it's possible to patch first and do the TLLI
-		 * handling afterwards. */
-
-		if (llc_len_change) {
-			llc_len += llc_len_change;
-
-			/* Fix LLC IE len */
-			/* TODO: This is a kludge, but the a pointer to the
-			 * start of the IE is not available here */
-			if (llc[-2] == BSSGP_IE_LLC_PDU && llc[-1] & 0x80) {
-				/* most probably a one byte length */
-				if (llc_len > 127) {
-					err_info = "Cannot increase size";
-					err_ctr = GBPROX_PEER_CTR_PATCH_ERR;
-					goto patch_error;
-				}
-				llc[-1] = llc_len | 0x80;
-			} else {
-				llc[-2] = (llc_len >> 8) & 0x7f;
-				llc[-1] = llc_len & 0xff;
-			}
-			*len_change += llc_len_change;
-		}
-		/* Note that the tp struct might contain invalid pointers here
-		 * if the LLC field has changed its size */
-		parse_ctx->llc_len = llc_len;
-	}
-	return;
-
-patch_error:
-	OSMO_ASSERT(err_ctr >= 0);
-	rate_ctr_inc(&peer->ctrg->ctr[err_ctr]);
-	LOGP(DGPRS, LOGL_ERROR,
-	     "NSEI=%u(%s) failed to patch BSSGP message as requested: %s.\n",
-	     msgb_nsei(msg), parse_ctx->to_bss ? "SGSN" : "BSS",
-	     err_info);
-}
-
-void gbproxy_clear_patch_filter(struct gbproxy_match *match)
-{
-	if (match->enable) {
-		regfree(&match->re_comp);
-		match->enable = 0;
-	}
-	talloc_free(match->re_str);
-	match->re_str = NULL;
-}
-
-int gbproxy_set_patch_filter(struct gbproxy_match *match, const char *filter,
-		const char **err_msg)
-{
-	static char err_buf[300];
-	int rc;
-
-	gbproxy_clear_patch_filter(match);
-
-	if (!filter)
-		return 0;
-
-	rc = regcomp(&match->re_comp, filter,
-		     REG_EXTENDED | REG_NOSUB | REG_ICASE);
-
-	if (rc == 0) {
-		match->enable = 1;
-		match->re_str = talloc_strdup(tall_bsc_ctx, filter);
-		return 0;
-	}
-
-	if (err_msg) {
-		regerror(rc, &match->re_comp,
-			 err_buf, sizeof(err_buf));
-		*err_msg = err_buf;
-	}
-
-	return -1;
-}
-
-int gbproxy_check_imsi(struct gbproxy_match *match,
-		       const uint8_t *imsi, size_t imsi_len)
-{
-	char mi_buf[200];
-	int rc;
-
-	if (!match->enable)
-		return 1;
-
-	rc = gprs_is_mi_imsi(imsi, imsi_len);
-	if (rc > 0)
-		rc = gsm48_mi_to_string(mi_buf, sizeof(mi_buf), imsi, imsi_len);
-	if (rc <= 0) {
-		LOGP(DGPRS, LOGL_NOTICE, "Invalid IMSI %s\n",
-		     osmo_hexdump(imsi, imsi_len));
-		return -1;
-	}
-
-	LOGP(DGPRS, LOGL_DEBUG, "Checking IMSI '%s' (%d)\n", mi_buf, rc);
-
-	rc = regexec(&match->re_comp, mi_buf, 0, NULL, 0);
-	if (rc == REG_NOMATCH) {
-		LOGP(DGPRS, LOGL_INFO,
-		       "IMSI '%s' doesn't match pattern '%s'\n",
-		       mi_buf, match->re_str);
-		return 0;
-	}
-
-	return 1;
-}
-
diff --git a/src/gprs/gb_proxy_peer.c b/src/gprs/gb_proxy_peer.c
deleted file mode 100644
index 8909687..0000000
--- a/src/gprs/gb_proxy_peer.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/* Gb proxy peer handling */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2010-2013 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/>.
- *
- */
-
-#include <openbsc/gb_proxy.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_data_shared.h>
-#include <openbsc/debug.h>
-
-#include <osmocom/gprs/protocol/gsm_08_18.h>
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/core/stats.h>
-#include <osmocom/core/talloc.h>
-
-#include <string.h>
-
-static const struct rate_ctr_desc peer_ctr_description[] = {
-	{ "blocked",	   "BVC Block                       " },
-	{ "unblocked",	   "BVC Unblock                     " },
-	{ "dropped",	   "BVC blocked, dropped packet     " },
-	{ "inv-nsei",	   "NSEI mismatch                   " },
-	{ "tx-err",	   "NS Transmission error           " },
-	{ "raid-mod.bss",  "RAID patched              (BSS )" },
-	{ "raid-mod.sgsn", "RAID patched              (SGSN)" },
-	{ "apn-mod.sgsn",  "APN patched                     " },
-	{ "tlli-mod.bss",  "TLLI patched              (BSS )" },
-	{ "tlli-mod.sgsn", "TLLI patched              (SGSN)" },
-	{ "ptmsi-mod.bss", "P-TMSI patched            (BSS )" },
-	{ "ptmsi-mod.sgsn","P-TMSI patched            (SGSN)" },
-	{ "mod-crypt-err", "Patch error: encrypted          " },
-	{ "mod-err",	   "Patch error: other              " },
-	{ "attach-reqs",   "Attach Request count            " },
-	{ "attach-rejs",   "Attach Reject count             " },
-	{ "attach-acks",   "Attach Accept count             " },
-	{ "attach-cpls",   "Attach Completed count          " },
-	{ "ra-upd-reqs",   "RoutingArea Update Request count" },
-	{ "ra-upd-rejs",   "RoutingArea Update Reject count " },
-	{ "ra-upd-acks",   "RoutingArea Update Accept count " },
-	{ "ra-upd-cpls",   "RoutingArea Update Compltd count" },
-	{ "gmm-status",    "GMM Status count           (BSS)" },
-	{ "gmm-status",    "GMM Status count          (SGSN)" },
-	{ "detach-reqs",   "Detach Request count            " },
-	{ "detach-acks",   "Detach Accept count             " },
-	{ "pdp-act-reqs",  "PDP Activation Request count    " },
-	{ "pdp-act-rejs",  "PDP Activation Reject count     " },
-	{ "pdp-act-acks",  "PDP Activation Accept count     " },
-	{ "pdp-deact-reqs","PDP Deactivation Request count  " },
-	{ "pdp-deact-acks","PDP Deactivation Accept count   " },
-	{ "tlli-unknown",  "TLLI from SGSN unknown          " },
-	{ "tlli-cache",    "TLLI cache size                 " },
-};
-
-osmo_static_assert(ARRAY_SIZE(peer_ctr_description) == GBPROX_PEER_CTR_LAST, everything_described);
-
-static const struct rate_ctr_group_desc peer_ctrg_desc = {
-	.group_name_prefix = "gbproxy.peer",
-	.group_description = "GBProxy Peer Statistics",
-	.num_ctr = ARRAY_SIZE(peer_ctr_description),
-	.ctr_desc = peer_ctr_description,
-	.class_id = OSMO_STATS_CLASS_PEER,
-};
-
-
-/* Find the gbprox_peer by its BVCI */
-struct gbproxy_peer *gbproxy_peer_by_bvci(struct gbproxy_config *cfg, uint16_t bvci)
-{
-	struct gbproxy_peer *peer;
-	llist_for_each_entry(peer, &cfg->bts_peers, list) {
-		if (peer->bvci == bvci)
-			return peer;
-	}
-	return NULL;
-}
-
-/* Find the gbprox_peer by its NSEI */
-struct gbproxy_peer *gbproxy_peer_by_nsei(struct gbproxy_config *cfg,
-					  uint16_t nsei)
-{
-	struct gbproxy_peer *peer;
-	llist_for_each_entry(peer, &cfg->bts_peers, list) {
-		if (peer->nsei == nsei)
-			return peer;
-	}
-	return NULL;
-}
-
-/* look-up a peer by its Routeing Area Identification (RAI) */
-struct gbproxy_peer *gbproxy_peer_by_rai(struct gbproxy_config *cfg,
-					 const uint8_t *ra)
-{
-	struct gbproxy_peer *peer;
-	llist_for_each_entry(peer, &cfg->bts_peers, list) {
-		if (!memcmp(peer->ra, ra, 6))
-			return peer;
-	}
-	return NULL;
-}
-
-/* look-up a peer by its Location Area Identification (LAI) */
-struct gbproxy_peer *gbproxy_peer_by_lai(struct gbproxy_config *cfg,
-					 const uint8_t *la)
-{
-	struct gbproxy_peer *peer;
-	llist_for_each_entry(peer, &cfg->bts_peers, list) {
-		if (!memcmp(peer->ra, la, 5))
-			return peer;
-	}
-	return NULL;
-}
-
-/* look-up a peer by its Location Area Code (LAC) */
-struct gbproxy_peer *gbproxy_peer_by_lac(struct gbproxy_config *cfg,
-					 const uint8_t *la)
-{
-	struct gbproxy_peer *peer;
-	llist_for_each_entry(peer, &cfg->bts_peers, list) {
-		if (!memcmp(peer->ra + 3, la + 3, 2))
-			return peer;
-	}
-	return NULL;
-}
-
-struct gbproxy_peer *gbproxy_peer_by_bssgp_tlv(struct gbproxy_config *cfg,
-					       struct tlv_parsed *tp)
-{
-	if (TLVP_PRESENT(tp, BSSGP_IE_BVCI)) {
-		uint16_t bvci;
-
-		bvci = ntohs(tlvp_val16_unal(tp, BSSGP_IE_BVCI));
-		if (bvci >= 2)
-			return gbproxy_peer_by_bvci(cfg, bvci);
-	}
-
-	if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA)) {
-		uint8_t *rai = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA);
-		/* Only compare LAC part, since MCC/MNC are possibly patched.
-		 * Since the LAC of different BSS must be different when
-		 * MCC/MNC are patched, collisions shouldn't happen. */
-		return gbproxy_peer_by_lac(cfg, rai);
-	}
-
-	if (TLVP_PRESENT(tp, BSSGP_IE_LOCATION_AREA)) {
-		uint8_t *lai = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_LOCATION_AREA);
-		return gbproxy_peer_by_lac(cfg, lai);
-	}
-
-	return NULL;
-}
-
-
-struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_config *cfg, uint16_t bvci)
-{
-	struct gbproxy_peer *peer;
-
-	peer = talloc_zero(tall_bsc_ctx, struct gbproxy_peer);
-	if (!peer)
-		return NULL;
-
-	peer->bvci = bvci;
-	peer->ctrg = rate_ctr_group_alloc(peer, &peer_ctrg_desc, bvci);
-	if (!peer->ctrg) {
-		talloc_free(peer);
-		return NULL;
-	}
-	peer->cfg = cfg;
-
-	llist_add(&peer->list, &cfg->bts_peers);
-
-	INIT_LLIST_HEAD(&peer->patch_state.logical_links);
-
-	return peer;
-}
-
-void gbproxy_peer_free(struct gbproxy_peer *peer)
-{
-	llist_del(&peer->list);
-
-	gbproxy_delete_link_infos(peer);
-
-	rate_ctr_group_free(peer->ctrg);
-	peer->ctrg = NULL;
-
-	talloc_free(peer);
-}
-
-int gbproxy_cleanup_peers(struct gbproxy_config *cfg, uint16_t nsei, uint16_t bvci)
-{
-	int counter = 0;
-	struct gbproxy_peer *peer, *tmp;
-
-	llist_for_each_entry_safe(peer, tmp, &cfg->bts_peers, list) {
-		if (peer->nsei != nsei)
-			continue;
-		if (bvci && peer->bvci != bvci)
-			continue;
-
-		gbproxy_peer_free(peer);
-		counter += 1;
-	}
-
-	return counter;
-}
-
diff --git a/src/gprs/gb_proxy_tlli.c b/src/gprs/gb_proxy_tlli.c
deleted file mode 100644
index 3b3b976..0000000
--- a/src/gprs/gb_proxy_tlli.c
+++ /dev/null
@@ -1,723 +0,0 @@
-/* Gb-proxy TLLI state handling */
-
-/* (C) 2014 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/>.
- *
- */
-
-#include <osmocom/gsm/gsm48.h>
-
-#include <openbsc/gb_proxy.h>
-
-#include <openbsc/gprs_utils.h>
-#include <openbsc/gprs_gb_parse.h>
-
-#include <openbsc/debug.h>
-
-#include <osmocom/gsm/gsm_utils.h>
-
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/core/talloc.h>
-
-struct gbproxy_link_info *gbproxy_link_info_by_tlli(struct gbproxy_peer *peer,
-					    uint32_t tlli)
-{
-	struct gbproxy_link_info *link_info;
-	struct gbproxy_patch_state *state = &peer->patch_state;
-
-	if (!tlli)
-		return NULL;
-
-	llist_for_each_entry(link_info, &state->logical_links, list)
-		if (link_info->tlli.current == tlli ||
-		    link_info->tlli.assigned == tlli)
-			return link_info;
-
-	return NULL;
-}
-
-struct gbproxy_link_info *gbproxy_link_info_by_ptmsi(
-	struct gbproxy_peer *peer,
-	uint32_t ptmsi)
-{
-	struct gbproxy_link_info *link_info;
-	struct gbproxy_patch_state *state = &peer->patch_state;
-
-	if (ptmsi == GSM_RESERVED_TMSI)
-		return NULL;
-
-	llist_for_each_entry(link_info, &state->logical_links, list)
-		if (link_info->tlli.ptmsi == ptmsi)
-			return link_info;
-
-	return NULL;
-}
-
-struct gbproxy_link_info *gbproxy_link_info_by_any_sgsn_tlli(
-	struct gbproxy_peer *peer,
-	uint32_t tlli)
-{
-	struct gbproxy_link_info *link_info;
-	struct gbproxy_patch_state *state = &peer->patch_state;
-
-	if (!tlli)
-		return NULL;
-
-	/* Don't care about the NSEI */
-	llist_for_each_entry(link_info, &state->logical_links, list)
-		if (link_info->sgsn_tlli.current == tlli ||
-		     link_info->sgsn_tlli.assigned == tlli)
-			return link_info;
-
-	return NULL;
-}
-
-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 *link_info;
-	struct gbproxy_patch_state *state = &peer->patch_state;
-
-	if (!tlli)
-		return NULL;
-
-	llist_for_each_entry(link_info, &state->logical_links, list)
-		if ((link_info->sgsn_tlli.current == tlli ||
-		     link_info->sgsn_tlli.assigned == tlli) &&
-		    link_info->sgsn_nsei == sgsn_nsei)
-			return link_info;
-
-	return NULL;
-}
-
-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 *link_info;
-	struct gbproxy_patch_state *state = &peer->patch_state;
-
-	if (!gprs_is_mi_imsi(imsi, imsi_len))
-		return NULL;
-
-	llist_for_each_entry(link_info, &state->logical_links, list) {
-		if (link_info->imsi_len != imsi_len)
-			continue;
-		if (memcmp(link_info->imsi, imsi, imsi_len) != 0)
-			continue;
-
-		return link_info;
-	}
-
-	return NULL;
-}
-
-void gbproxy_link_info_discard_messages(struct gbproxy_link_info *link_info)
-{
-	struct msgb *msg, *nxt;
-
-	llist_for_each_entry_safe(msg, nxt, &link_info->stored_msgs, list) {
-		llist_del(&msg->list);
-		msgb_free(msg);
-	}
-}
-
-void gbproxy_delete_link_info(struct gbproxy_peer *peer,
-			 struct gbproxy_link_info *link_info)
-{
-	struct gbproxy_patch_state *state = &peer->patch_state;
-
-	gbproxy_link_info_discard_messages(link_info);
-
-	llist_del(&link_info->list);
-	talloc_free(link_info);
-	state->logical_link_count -= 1;
-
-	peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
-		state->logical_link_count;
-}
-
-void gbproxy_delete_link_infos(struct gbproxy_peer *peer)
-{
-	struct gbproxy_link_info *link_info, *nxt;
-	struct gbproxy_patch_state *state = &peer->patch_state;
-
-	llist_for_each_entry_safe(link_info, nxt, &state->logical_links, list)
-		gbproxy_delete_link_info(peer, link_info);
-
-	OSMO_ASSERT(state->logical_link_count == 0);
-	OSMO_ASSERT(llist_empty(&state->logical_links));
-}
-
-void gbproxy_attach_link_info(struct gbproxy_peer *peer, time_t now,
-			      struct gbproxy_link_info *link_info)
-{
-	struct gbproxy_patch_state *state = &peer->patch_state;
-
-	link_info->timestamp = now;
-	llist_add(&link_info->list, &state->logical_links);
-	state->logical_link_count += 1;
-
-	peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
-		state->logical_link_count;
-}
-
-int gbproxy_remove_stale_link_infos(struct gbproxy_peer *peer, time_t now)
-{
-	struct gbproxy_patch_state *state = &peer->patch_state;
-	int exceeded_max_len = 0;
-	int deleted_count = 0;
-	int check_for_age;
-
-	if (peer->cfg->tlli_max_len > 0)
-		exceeded_max_len =
-			state->logical_link_count - peer->cfg->tlli_max_len;
-
-	check_for_age = peer->cfg->tlli_max_age > 0;
-
-	for (; exceeded_max_len > 0; exceeded_max_len--) {
-		struct gbproxy_link_info *link_info;
-		OSMO_ASSERT(!llist_empty(&state->logical_links));
-		link_info = llist_entry(state->logical_links.prev,
-					struct gbproxy_link_info,
-					list);
-		LOGP(DGPRS, LOGL_INFO,
-		     "Removing TLLI %08x from list "
-		     "(stale, length %d, max_len exceeded)\n",
-		     link_info->tlli.current, state->logical_link_count);
-
-		gbproxy_delete_link_info(peer, link_info);
-		deleted_count += 1;
-	}
-
-	while (check_for_age && !llist_empty(&state->logical_links)) {
-		time_t age;
-		struct gbproxy_link_info *link_info;
-		link_info = llist_entry(state->logical_links.prev,
-					struct gbproxy_link_info,
-					list);
-		age = now - link_info->timestamp;
-		/* age < 0 only happens after system time jumps, discard entry */
-		if (age <= peer->cfg->tlli_max_age && age >= 0) {
-			check_for_age = 0;
-			continue;
-		}
-
-		LOGP(DGPRS, LOGL_INFO,
-		     "Removing TLLI %08x from list "
-		     "(stale, age %d, max_age exceeded)\n",
-		     link_info->tlli.current, (int)age);
-
-		gbproxy_delete_link_info(peer, link_info);
-		deleted_count += 1;
-	}
-
-	return deleted_count;
-}
-
-struct gbproxy_link_info *gbproxy_link_info_alloc( struct gbproxy_peer *peer)
-{
-	struct gbproxy_link_info *link_info;
-
-	link_info = talloc_zero(peer, struct gbproxy_link_info);
-	link_info->tlli.ptmsi = GSM_RESERVED_TMSI;
-	link_info->sgsn_tlli.ptmsi = GSM_RESERVED_TMSI;
-
-	link_info->vu_gen_tx_bss = GBPROXY_INIT_VU_GEN_TX;
-
-	INIT_LLIST_HEAD(&link_info->stored_msgs);
-
-	return link_info;
-}
-
-void gbproxy_detach_link_info(
-	struct gbproxy_peer *peer,
-	struct gbproxy_link_info *link_info)
-{
-	struct gbproxy_patch_state *state = &peer->patch_state;
-
-	llist_del(&link_info->list);
-	OSMO_ASSERT(state->logical_link_count > 0);
-	state->logical_link_count -= 1;
-
-	peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
-		state->logical_link_count;
-}
-
-void gbproxy_update_link_info(struct gbproxy_link_info *link_info,
-			      const uint8_t *imsi, size_t imsi_len)
-{
-	if (!gprs_is_mi_imsi(imsi, imsi_len))
-		return;
-
-	link_info->imsi_len = imsi_len;
-	link_info->imsi =
-		talloc_realloc_size(link_info, link_info->imsi, imsi_len);
-	OSMO_ASSERT(link_info->imsi != NULL);
-	memcpy(link_info->imsi, imsi, imsi_len);
-}
-
-void gbproxy_reassign_tlli(struct gbproxy_tlli_state *tlli_state,
-			   struct gbproxy_peer *peer, uint32_t new_tlli)
-{
-	if (new_tlli == tlli_state->current)
-		return;
-
-	LOGP(DGPRS, LOGL_INFO,
-	     "The TLLI has been reassigned from %08x to %08x\n",
-	     tlli_state->current, new_tlli);
-
-	/* Remember assigned TLLI */
-	tlli_state->assigned = new_tlli;
-	tlli_state->bss_validated = 0;
-	tlli_state->net_validated = 0;
-}
-
-uint32_t gbproxy_map_tlli(uint32_t other_tlli,
-			  struct gbproxy_link_info *link_info, int to_bss)
-{
-	uint32_t tlli = 0;
-	struct gbproxy_tlli_state *src, *dst;
-	if (to_bss) {
-		src = &link_info->sgsn_tlli;
-		dst = &link_info->tlli;
-	} else {
-		src = &link_info->tlli;
-		dst = &link_info->sgsn_tlli;
-	}
-	if (src->current == other_tlli)
-		tlli = dst->current;
-	else if (src->assigned == other_tlli)
-		tlli = dst->assigned;
-
-	return tlli;
-}
-
-static void gbproxy_validate_tlli(struct gbproxy_tlli_state *tlli_state,
-				  uint32_t tlli, int to_bss)
-{
-	LOGP(DGPRS, LOGL_DEBUG,
-	     "%s({current = %08x, assigned = %08x, net_vld = %d, bss_vld = %d}, %08x)\n",
-	     __func__, tlli_state->current, tlli_state->assigned,
-	     tlli_state->net_validated, tlli_state->bss_validated, tlli);
-
-	if (!tlli_state->assigned || tlli_state->assigned != tlli)
-		return;
-
-	/* TODO: Is this ok? Check spec */
-	if (gprs_tlli_type(tlli) != TLLI_LOCAL)
-		return;
-
-	/* See GSM 04.08, 4.7.1.5 */
-	if (to_bss)
-		tlli_state->net_validated = 1;
-	else
-		tlli_state->bss_validated = 1;
-
-	if (!tlli_state->bss_validated || !tlli_state->net_validated)
-		return;
-
-	LOGP(DGPRS, LOGL_INFO,
-	     "The TLLI %08x has been validated (was %08x)\n",
-	     tlli_state->assigned, tlli_state->current);
-
-	tlli_state->current = tlli;
-	tlli_state->assigned = 0;
-}
-
-static void gbproxy_touch_link_info(struct gbproxy_peer *peer,
-				    struct gbproxy_link_info *link_info,
-				    time_t now)
-{
-	gbproxy_detach_link_info(peer, link_info);
-	gbproxy_attach_link_info(peer, now, link_info);
-}
-
-static int gbproxy_unregister_link_info(struct gbproxy_peer *peer,
-					 struct gbproxy_link_info *link_info)
-{
-	if (!link_info)
-		return 1;
-
-	if (link_info->tlli.ptmsi == GSM_RESERVED_TMSI && !link_info->imsi_len) {
-		LOGP(DGPRS, LOGL_INFO,
-		     "Removing TLLI %08x from list (P-TMSI or IMSI are not set)\n",
-		     link_info->tlli.current);
-		gbproxy_delete_link_info(peer, link_info);
-		return 1;
-	}
-
-	link_info->tlli.current = 0;
-	link_info->tlli.assigned = 0;
-	link_info->sgsn_tlli.current = 0;
-	link_info->sgsn_tlli.assigned = 0;
-
-	link_info->is_deregistered = 1;
-
-	gbproxy_reset_link(link_info);
-
-	return 0;
-}
-
-int gbproxy_imsi_matches(struct gbproxy_config *cfg,
-			 enum gbproxy_match_id match_id,
-			 struct gbproxy_link_info *link_info)
-{
-	struct gbproxy_match *match;
-	OSMO_ASSERT(match_id >= 0 && match_id < ARRAY_SIZE(cfg->matches));
-
-	match = &cfg->matches[match_id];
-	if (!match->enable)
-		return 1;
-
-	return link_info != NULL && link_info->is_matching[match_id];
-}
-
-void gbproxy_assign_imsi(struct gbproxy_peer *peer,
-			 struct gbproxy_link_info *link_info,
-			 struct gprs_gb_parse_context *parse_ctx)
-{
-	int imsi_matches;
-	struct gbproxy_link_info *other_link_info;
-	enum gbproxy_match_id match_id;
-
-	/* Make sure that there is a second entry with the same IMSI */
-	other_link_info = gbproxy_link_info_by_imsi(
-		peer, parse_ctx->imsi, parse_ctx->imsi_len);
-
-	if (other_link_info && other_link_info != link_info) {
-		char mi_buf[200];
-		mi_buf[0] = '\0';
-		gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
-				   parse_ctx->imsi, parse_ctx->imsi_len);
-		LOGP(DGPRS, LOGL_INFO,
-		     "Removing TLLI %08x from list (IMSI %s re-used)\n",
-		     other_link_info->tlli.current, mi_buf);
-		gbproxy_delete_link_info(peer, other_link_info);
-	}
-
-	/* Update the IMSI field */
-	gbproxy_update_link_info(link_info,
-				 parse_ctx->imsi, parse_ctx->imsi_len);
-
-	/* Check, whether the IMSI matches */
-	OSMO_ASSERT(ARRAY_SIZE(link_info->is_matching) ==
-		    ARRAY_SIZE(peer->cfg->matches));
-	for (match_id = 0; match_id < ARRAY_SIZE(link_info->is_matching);
-	     ++match_id) {
-		imsi_matches = gbproxy_check_imsi(
-			&peer->cfg->matches[match_id],
-			parse_ctx->imsi, parse_ctx->imsi_len);
-		if (imsi_matches >= 0)
-			link_info->is_matching[match_id] = imsi_matches;
-	}
-}
-
-static int gbproxy_tlli_match(const struct gbproxy_tlli_state *a,
-			      const struct gbproxy_tlli_state *b)
-{
-	if (a->current && a->current == b->current)
-		return 1;
-
-	if (a->assigned && a->assigned == b->assigned)
-		return 1;
-
-	if (a->ptmsi != GSM_RESERVED_TMSI && a->ptmsi == b->ptmsi)
-		return 1;
-
-	return 0;
-}
-
-static void gbproxy_remove_matching_link_infos(
-	struct gbproxy_peer *peer, struct gbproxy_link_info *link_info)
-{
-	struct gbproxy_link_info *info, *nxt;
-	struct gbproxy_patch_state *state = &peer->patch_state;
-
-	/* Make sure that there is no second entry with the same P-TMSI or TLLI */
-	llist_for_each_entry_safe(info, nxt, &state->logical_links, list) {
-		if (info == link_info)
-			continue;
-
-		if (!gbproxy_tlli_match(&link_info->tlli, &info->tlli) &&
-		    (link_info->sgsn_nsei != info->sgsn_nsei ||
-		     !gbproxy_tlli_match(&link_info->sgsn_tlli, &info->sgsn_tlli)))
-			continue;
-
-		LOGP(DGPRS, LOGL_INFO,
-		     "Removing TLLI %08x from list (P-TMSI/TLLI re-used)\n",
-		     info->tlli.current);
-		gbproxy_delete_link_info(peer, info);
-	}
-}
-
-static struct gbproxy_link_info *gbproxy_get_link_info_ul(
-	struct gbproxy_peer *peer,
-	int *tlli_is_valid,
-	struct gprs_gb_parse_context *parse_ctx)
-{
-	struct gbproxy_link_info *link_info = NULL;
-
-	if (parse_ctx->tlli_enc) {
-		link_info = gbproxy_link_info_by_tlli(peer, parse_ctx->tlli);
-
-		if (link_info) {
-			*tlli_is_valid = 1;
-			return link_info;
-		}
-	}
-
-	*tlli_is_valid = 0;
-
-	if (!link_info && parse_ctx->imsi) {
-		link_info = gbproxy_link_info_by_imsi(
-			peer, parse_ctx->imsi, parse_ctx->imsi_len);
-	}
-
-	if (!link_info && parse_ctx->ptmsi_enc && !parse_ctx->old_raid_is_foreign) {
-		uint32_t bss_ptmsi;
-		gprs_parse_tmsi(parse_ctx->ptmsi_enc, &bss_ptmsi);
-		link_info = gbproxy_link_info_by_ptmsi(peer, bss_ptmsi);
-	}
-
-	if (!link_info)
-		return NULL;
-
-	link_info->is_deregistered = 0;
-
-	return link_info;
-}
-
-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 *link_info;
-	int tlli_is_valid;
-
-	link_info = gbproxy_get_link_info_ul(peer, &tlli_is_valid, parse_ctx);
-
-	if (parse_ctx->tlli_enc && parse_ctx->llc) {
-		uint32_t sgsn_tlli;
-
-		if (!link_info) {
-			LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list\n",
-			    parse_ctx->tlli);
-			link_info = gbproxy_link_info_alloc(peer);
-			gbproxy_attach_link_info(peer, now, link_info);
-
-			/* Setup TLLIs */
-			sgsn_tlli = gbproxy_make_sgsn_tlli(peer, link_info,
-							   parse_ctx->tlli);
-			link_info->sgsn_tlli.current = sgsn_tlli;
-			link_info->tlli.current = parse_ctx->tlli;
-		} else if (!tlli_is_valid) {
-			/* New TLLI (info found by IMSI or P-TMSI) */
-			link_info->tlli.current = parse_ctx->tlli;
-			link_info->tlli.assigned = 0;
-			link_info->sgsn_tlli.current =
-				gbproxy_make_sgsn_tlli(peer, link_info,
-						       parse_ctx->tlli);
-			link_info->sgsn_tlli.assigned = 0;
-			gbproxy_touch_link_info(peer, link_info, now);
-		} else {
-			sgsn_tlli = gbproxy_map_tlli(parse_ctx->tlli, link_info, 0);
-			if (!sgsn_tlli)
-				sgsn_tlli = gbproxy_make_sgsn_tlli(peer, link_info,
-								   parse_ctx->tlli);
-
-			gbproxy_validate_tlli(&link_info->tlli,
-					      parse_ctx->tlli, 0);
-			gbproxy_validate_tlli(&link_info->sgsn_tlli,
-					      sgsn_tlli, 0);
-			gbproxy_touch_link_info(peer, link_info, now);
-		}
-	} else if (link_info) {
-		gbproxy_touch_link_info(peer, link_info, now);
-	}
-
-	if (parse_ctx->imsi && link_info && link_info->imsi_len == 0)
-		gbproxy_assign_imsi(peer, link_info, parse_ctx);
-
-	return link_info;
-}
-
-static struct gbproxy_link_info *gbproxy_get_link_info_dl(
-	struct gbproxy_peer *peer,
-	struct gprs_gb_parse_context *parse_ctx)
-{
-	struct gbproxy_link_info *link_info = NULL;
-
-	/* Which key to use depends on its availability only, if that fails, do
-	 * not retry it with another key (e.g. IMSI). */
-	if (parse_ctx->tlli_enc)
-		link_info = gbproxy_link_info_by_sgsn_tlli(peer, parse_ctx->tlli,
-							   parse_ctx->peer_nsei);
-
-	/* TODO: Get link_info by (SGSN) P-TMSI if that is available (see
-	 * GSM 08.18, 7.2) instead of using the IMSI as key. */
-	else if (parse_ctx->imsi)
-		link_info = gbproxy_link_info_by_imsi(
-			peer, parse_ctx->imsi, parse_ctx->imsi_len);
-
-	if (link_info)
-		link_info->is_deregistered = 0;
-
-	return link_info;
-}
-
-struct gbproxy_link_info *gbproxy_update_link_state_dl(
-	struct gbproxy_peer *peer,
-	time_t now,
-	struct gprs_gb_parse_context *parse_ctx)
-{
-	struct gbproxy_link_info *link_info = NULL;
-
-	link_info = gbproxy_get_link_info_dl(peer, parse_ctx);
-
-	if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && link_info) {
-		/* A new P-TMSI has been signalled in the message,
-		 * register new TLLI */
-		uint32_t new_sgsn_ptmsi;
-		uint32_t new_bss_ptmsi = GSM_RESERVED_TMSI;
-		gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_sgsn_ptmsi);
-
-		if (link_info->sgsn_tlli.ptmsi == new_sgsn_ptmsi)
-			new_bss_ptmsi = link_info->tlli.ptmsi;
-
-		if (new_bss_ptmsi == GSM_RESERVED_TMSI)
-			new_bss_ptmsi = gbproxy_make_bss_ptmsi(peer, new_sgsn_ptmsi);
-
-		LOGP(DGPRS, LOGL_INFO,
-		     "Got new PTMSI %08x from SGSN, using %08x for BSS\n",
-		     new_sgsn_ptmsi, new_bss_ptmsi);
-		/* Setup PTMSIs */
-		link_info->sgsn_tlli.ptmsi = new_sgsn_ptmsi;
-		link_info->tlli.ptmsi = new_bss_ptmsi;
-	} else if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && !link_info &&
-		   !peer->cfg->patch_ptmsi) {
-		/* A new P-TMSI has been signalled in the message with an unknown
-		 * TLLI, create a new link_info */
-		/* TODO: Add a test case for this branch */
-		uint32_t new_ptmsi;
-		gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
-
-		LOGP(DGPRS, LOGL_INFO,
-		     "Adding TLLI %08x to list (SGSN, new P-TMSI is %08x)\n",
-		     parse_ctx->tlli, new_ptmsi);
-
-		link_info = gbproxy_link_info_alloc(peer);
-		link_info->sgsn_tlli.current = parse_ctx->tlli;
-		link_info->tlli.current = parse_ctx->tlli;
-		link_info->sgsn_tlli.ptmsi = new_ptmsi;
-		link_info->tlli.ptmsi = new_ptmsi;
-		gbproxy_attach_link_info(peer, now, link_info);
-	} else if (parse_ctx->tlli_enc && parse_ctx->llc && !link_info &&
-		   !peer->cfg->patch_ptmsi) {
-		/* Unknown SGSN TLLI, create a new link_info */
-		uint32_t new_ptmsi;
-		link_info = gbproxy_link_info_alloc(peer);
-		LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list (SGSN)\n",
-		     parse_ctx->tlli);
-
-		gbproxy_attach_link_info(peer, now, link_info);
-
-		/* Setup TLLIs */
-		link_info->sgsn_tlli.current = parse_ctx->tlli;
-		link_info->tlli.current = parse_ctx->tlli;
-
-		if (!parse_ctx->new_ptmsi_enc)
-			return link_info;
-		/* A new P-TMSI has been signalled in the message */
-
-		gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
-		LOGP(DGPRS, LOGL_INFO,
-		     "Assigning new P-TMSI %08x\n", new_ptmsi);
-		/* Setup P-TMSIs */
-		link_info->sgsn_tlli.ptmsi = new_ptmsi;
-		link_info->tlli.ptmsi = new_ptmsi;
-	} else if (parse_ctx->tlli_enc && parse_ctx->llc && link_info) {
-		uint32_t bss_tlli = gbproxy_map_tlli(parse_ctx->tlli,
-						     link_info, 1);
-		gbproxy_validate_tlli(&link_info->sgsn_tlli, parse_ctx->tlli, 1);
-		gbproxy_validate_tlli(&link_info->tlli, bss_tlli, 1);
-		gbproxy_touch_link_info(peer, link_info, now);
-	} else if (link_info) {
-		gbproxy_touch_link_info(peer, link_info, now);
-	}
-
-	if (parse_ctx->imsi && link_info && link_info->imsi_len == 0)
-		gbproxy_assign_imsi(peer, link_info, parse_ctx);
-
-	return link_info;
-}
-
-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 rc = 0;
-	if (parse_ctx->invalidate_tlli && link_info) {
-		int keep_info =
-			peer->cfg->keep_link_infos == GBPROX_KEEP_ALWAYS ||
-			(peer->cfg->keep_link_infos == GBPROX_KEEP_REATTACH &&
-			 parse_ctx->await_reattach) ||
-			(peer->cfg->keep_link_infos == GBPROX_KEEP_IDENTIFIED &&
-			 link_info->imsi_len > 0);
-		if (keep_info) {
-			LOGP(DGPRS, LOGL_INFO, "Unregistering TLLI %08x\n",
-			     link_info->tlli.current);
-			rc = gbproxy_unregister_link_info(peer, link_info);
-		} else {
-			LOGP(DGPRS, LOGL_INFO, "Removing TLLI %08x from list\n",
-			     link_info->tlli.current);
-			gbproxy_delete_link_info(peer, link_info);
-			rc = 1;
-		}
-	} else if (parse_ctx->to_bss && parse_ctx->tlli_enc &&
-		   parse_ctx->new_ptmsi_enc && link_info) {
-		/* A new PTMSI has been signaled in the message,
-		 * register new TLLI */
-		uint32_t new_sgsn_ptmsi = link_info->sgsn_tlli.ptmsi;
-		uint32_t new_bss_ptmsi = link_info->tlli.ptmsi;
-		uint32_t new_sgsn_tlli;
-		uint32_t new_bss_tlli = 0;
-
-		new_sgsn_tlli = gprs_tmsi2tlli(new_sgsn_ptmsi, TLLI_LOCAL);
-		if (new_bss_ptmsi != GSM_RESERVED_TMSI)
-			new_bss_tlli = gprs_tmsi2tlli(new_bss_ptmsi, TLLI_LOCAL);
-		LOGP(DGPRS, LOGL_INFO,
-		     "Assigning new TLLI %08x to SGSN, %08x to BSS\n",
-		     new_sgsn_tlli, new_bss_tlli);
-
-		gbproxy_reassign_tlli(&link_info->sgsn_tlli,
-				      peer, new_sgsn_tlli);
-		gbproxy_reassign_tlli(&link_info->tlli,
-				      peer, new_bss_tlli);
-		gbproxy_remove_matching_link_infos(peer, link_info);
-	}
-
-	gbproxy_remove_stale_link_infos(peer, now);
-
-	return rc;
-}
-
-
diff --git a/src/gprs/gb_proxy_vty.c b/src/gprs/gb_proxy_vty.c
deleted file mode 100644
index 86d65a8..0000000
--- a/src/gprs/gb_proxy_vty.c
+++ /dev/null
@@ -1,853 +0,0 @@
-/*
- * (C) 2010 by Harald Welte <laforge@gnumonks.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/>.
- *
- */
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <time.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/rate_ctr.h>
-
-#include <openbsc/gsm_04_08.h>
-#include <osmocom/gprs/gprs_ns.h>
-#include <osmocom/gsm/apn.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/gb_proxy.h>
-#include <openbsc/gprs_utils.h>
-#include <openbsc/vty.h>
-
-#include <osmocom/vty/command.h>
-#include <osmocom/vty/vty.h>
-#include <osmocom/vty/misc.h>
-
-static struct gbproxy_config *g_cfg = NULL;
-
-/*
- * vty code for mgcp below
- */
-static struct cmd_node gbproxy_node = {
-	GBPROXY_NODE,
-	"%s(config-gbproxy)# ",
-	1,
-};
-
-static const struct value_string keep_modes[] = {
-	{GBPROX_KEEP_NEVER, "never"},
-	{GBPROX_KEEP_REATTACH, "re-attach"},
-	{GBPROX_KEEP_IDENTIFIED, "identified"},
-	{GBPROX_KEEP_ALWAYS, "always"},
-	{0, NULL}
-};
-
-static const struct value_string match_ids[] = {
-	{GBPROX_MATCH_PATCHING, "patching"},
-	{GBPROX_MATCH_ROUTING, "routing"},
-	{0, NULL}
-};
-
-static void gbprox_vty_print_peer(struct vty *vty, struct gbproxy_peer *peer)
-{
-	struct gprs_ra_id raid;
-	gsm48_parse_ra(&raid, peer->ra);
-
-	vty_out(vty, "NSEI %5u, PTP-BVCI %5u, "
-		"RAI %u-%u-%u-%u",
-		peer->nsei, peer->bvci,
-		raid.mcc, raid.mnc, raid.lac, raid.rac);
-	if (peer->blocked)
-		vty_out(vty, " [BVC-BLOCKED]");
-
-	vty_out(vty, "%s", VTY_NEWLINE);
-}
-
-static int config_write_gbproxy(struct vty *vty)
-{
-	enum gbproxy_match_id match_id;
-
-	vty_out(vty, "gbproxy%s", VTY_NEWLINE);
-
-	vty_out(vty, " sgsn nsei %u%s", g_cfg->nsip_sgsn_nsei,
-		VTY_NEWLINE);
-
-	if (g_cfg->core_mcc > 0)
-		vty_out(vty, " core-mobile-country-code %d%s",
-			g_cfg->core_mcc, VTY_NEWLINE);
-	if (g_cfg->core_mnc > 0)
-		vty_out(vty, " core-mobile-network-code %d%s",
-			g_cfg->core_mnc, VTY_NEWLINE);
-
-	for (match_id = 0; match_id < ARRAY_SIZE(g_cfg->matches); ++match_id) {
-		struct gbproxy_match *match = &g_cfg->matches[match_id];
-		if (match->re_str)
-			vty_out(vty, " match-imsi %s %s%s",
-				get_value_string(match_ids, match_id),
-				match->re_str, VTY_NEWLINE);
-	}
-
-	if (g_cfg->core_apn != NULL) {
-	       if (g_cfg->core_apn_size > 0) {
-		       char str[500] = {0};
-		       vty_out(vty, " core-access-point-name %s%s",
-			       osmo_apn_to_str(str, g_cfg->core_apn,
-						 g_cfg->core_apn_size),
-			       VTY_NEWLINE);
-	       } else {
-		       vty_out(vty, " core-access-point-name none%s",
-			       VTY_NEWLINE);
-	       }
-	}
-
-	if (g_cfg->route_to_sgsn2)
-		vty_out(vty, " secondary-sgsn nsei %u%s", g_cfg->nsip_sgsn2_nsei,
-			VTY_NEWLINE);
-
-	if (g_cfg->tlli_max_age > 0)
-		vty_out(vty, " link-list max-age %d%s",
-			g_cfg->tlli_max_age, VTY_NEWLINE);
-	if (g_cfg->tlli_max_len > 0)
-		vty_out(vty, " link-list max-length %d%s",
-			g_cfg->tlli_max_len, VTY_NEWLINE);
-	vty_out(vty, " link-list keep-mode %s%s",
-		get_value_string(keep_modes, g_cfg->keep_link_infos),
-		VTY_NEWLINE);
-
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gbproxy,
-      cfg_gbproxy_cmd,
-      "gbproxy",
-      "Configure the Gb proxy")
-{
-	vty->node = GBPROXY_NODE;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nsip_sgsn_nsei,
-      cfg_nsip_sgsn_nsei_cmd,
-      "sgsn nsei <0-65534>",
-      "SGSN information\n"
-      "NSEI to be used in the connection with the SGSN\n"
-      "The NSEI\n")
-{
-	unsigned int nsei = atoi(argv[0]);
-
-	if (g_cfg->route_to_sgsn2 && g_cfg->nsip_sgsn2_nsei == nsei) {
-		vty_out(vty, "SGSN NSEI %d conflicts with secondary SGSN NSEI%s",
-			nsei, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	g_cfg->nsip_sgsn_nsei = nsei;
-	return CMD_SUCCESS;
-}
-
-#define GBPROXY_CORE_MNC_STR "Use this network code for the core network\n"
-
-DEFUN(cfg_gbproxy_core_mnc,
-      cfg_gbproxy_core_mnc_cmd,
-      "core-mobile-network-code <1-999>",
-      GBPROXY_CORE_MNC_STR "NCC value\n")
-{
-	g_cfg->core_mnc = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gbproxy_no_core_mnc,
-      cfg_gbproxy_no_core_mnc_cmd,
-      "no core-mobile-network-code",
-      NO_STR GBPROXY_CORE_MNC_STR)
-{
-	g_cfg->core_mnc = 0;
-	return CMD_SUCCESS;
-}
-
-#define GBPROXY_CORE_MCC_STR "Use this country code for the core network\n"
-
-DEFUN(cfg_gbproxy_core_mcc,
-      cfg_gbproxy_core_mcc_cmd,
-      "core-mobile-country-code <1-999>",
-      GBPROXY_CORE_MCC_STR "MCC value\n")
-{
-	g_cfg->core_mcc = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gbproxy_no_core_mcc,
-      cfg_gbproxy_no_core_mcc_cmd,
-      "no core-mobile-country-code",
-      NO_STR GBPROXY_CORE_MCC_STR)
-{
-	g_cfg->core_mcc = 0;
-	return CMD_SUCCESS;
-}
-
-#define GBPROXY_MATCH_IMSI_STR "Restrict actions to certain IMSIs\n"
-
-DEFUN(cfg_gbproxy_match_imsi,
-      cfg_gbproxy_match_imsi_cmd,
-      "match-imsi (patching|routing) .REGEXP",
-      GBPROXY_MATCH_IMSI_STR
-      "Patch MS related information elements on match only\n"
-      "Route to the secondary SGSN on match only\n"
-      "Regular expression for the IMSI match\n")
-{
-	const char *filter = argv[1];
-	const char *err_msg = NULL;
-	struct gbproxy_match *match;
-	enum gbproxy_match_id match_id = get_string_value(match_ids, argv[0]);
-
-	OSMO_ASSERT(match_id >= GBPROX_MATCH_PATCHING &&
-		    match_id < GBPROX_MATCH_LAST);
-	match = &g_cfg->matches[match_id];
-
-	if (gbproxy_set_patch_filter(match, filter, &err_msg) != 0) {
-		vty_out(vty, "Match expression invalid: %s%s",
-			err_msg, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	g_cfg->acquire_imsi = 1;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gbproxy_no_match_imsi,
-      cfg_gbproxy_no_match_imsi_cmd,
-      "no match-imsi",
-      NO_STR GBPROXY_MATCH_IMSI_STR)
-{
-	enum gbproxy_match_id match_id;
-
-	for (match_id = 0; match_id < ARRAY_SIZE(g_cfg->matches); ++match_id)
-		gbproxy_clear_patch_filter(&g_cfg->matches[match_id]);
-
-	g_cfg->acquire_imsi = 0;
-
-	return CMD_SUCCESS;
-}
-
-#define GBPROXY_CORE_APN_STR "Use this access point name (APN) for the backbone\n"
-#define GBPROXY_CORE_APN_ARG_STR "Replace APN by this string\n" "Remove APN\n"
-
-static int set_core_apn(struct vty *vty, const char *apn)
-{
-	int apn_len;
-
-	if (!apn) {
-		talloc_free(g_cfg->core_apn);
-		g_cfg->core_apn = NULL;
-		g_cfg->core_apn_size = 0;
-		return CMD_SUCCESS;
-	}
-
-	apn_len = strlen(apn);
-
-	if (apn_len >= 100) {
-		vty_out(vty, "APN string too long (max 99 chars)%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (apn_len == 0) {
-		talloc_free(g_cfg->core_apn);
-		/* TODO: replace NULL */
-		g_cfg->core_apn = talloc_zero_size(NULL, 2);
-		g_cfg->core_apn_size = 0;
-	} else {
-		/* TODO: replace NULL */
-		g_cfg->core_apn =
-			talloc_realloc_size(NULL, g_cfg->core_apn, apn_len + 1);
-		g_cfg->core_apn_size =
-			gprs_str_to_apn(g_cfg->core_apn, apn_len + 1, apn);
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gbproxy_core_apn,
-      cfg_gbproxy_core_apn_cmd,
-      "core-access-point-name (APN|none)",
-      GBPROXY_CORE_APN_STR GBPROXY_CORE_APN_ARG_STR)
-{
-	if (strcmp(argv[0], "none") == 0)
-		return set_core_apn(vty, "");
-	else
-		return set_core_apn(vty, argv[0]);
-}
-
-DEFUN(cfg_gbproxy_no_core_apn,
-      cfg_gbproxy_no_core_apn_cmd,
-      "no core-access-point-name",
-      NO_STR GBPROXY_CORE_APN_STR)
-{
-	return set_core_apn(vty, NULL);
-}
-
-/* TODO: Remove the patch-ptmsi command, since P-TMSI patching is enabled
- * automatically when needed. This command is only left for manual testing
- * (e.g. doing P-TMSI patching without using a secondary SGSN)
- */
-#define GBPROXY_PATCH_PTMSI_STR "Patch P-TMSI/TLLI\n"
-
-DEFUN(cfg_gbproxy_patch_ptmsi,
-      cfg_gbproxy_patch_ptmsi_cmd,
-      "patch-ptmsi",
-      GBPROXY_PATCH_PTMSI_STR)
-{
-	g_cfg->patch_ptmsi = 1;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gbproxy_no_patch_ptmsi,
-      cfg_gbproxy_no_patch_ptmsi_cmd,
-      "no patch-ptmsi",
-      NO_STR GBPROXY_PATCH_PTMSI_STR)
-{
-	g_cfg->patch_ptmsi = 0;
-
-	return CMD_SUCCESS;
-}
-
-/* TODO: Remove the acquire-imsi command, since that feature is enabled
- * automatically when IMSI matching is enabled. This command is only left for
- * manual testing (e.g. doing IMSI acquisition without IMSI based patching)
- */
-#define GBPROXY_ACQUIRE_IMSI_STR "Acquire the IMSI before establishing a LLC connection (Experimental)\n"
-
-DEFUN(cfg_gbproxy_acquire_imsi,
-      cfg_gbproxy_acquire_imsi_cmd,
-      "acquire-imsi",
-      GBPROXY_ACQUIRE_IMSI_STR)
-{
-	g_cfg->acquire_imsi = 1;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gbproxy_no_acquire_imsi,
-      cfg_gbproxy_no_acquire_imsi_cmd,
-      "no acquire-imsi",
-      NO_STR GBPROXY_ACQUIRE_IMSI_STR)
-{
-	g_cfg->acquire_imsi = 0;
-
-	return CMD_SUCCESS;
-}
-
-#define GBPROXY_SECOND_SGSN_STR "Route matching LLC connections to a second SGSN (Experimental)\n"
-
-DEFUN(cfg_gbproxy_secondary_sgsn,
-      cfg_gbproxy_secondary_sgsn_cmd,
-      "secondary-sgsn nsei <0-65534>",
-      GBPROXY_SECOND_SGSN_STR
-      "NSEI to be used in the connection with the SGSN\n"
-      "The NSEI\n")
-{
-	unsigned int nsei = atoi(argv[0]);
-
-	if (g_cfg->nsip_sgsn_nsei == nsei) {
-		vty_out(vty, "Secondary SGSN NSEI %d conflicts with primary SGSN NSEI%s",
-			nsei, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	g_cfg->route_to_sgsn2 = 1;
-	g_cfg->nsip_sgsn2_nsei = nsei;
-
-	g_cfg->patch_ptmsi = 1;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gbproxy_no_secondary_sgsn,
-      cfg_gbproxy_no_secondary_sgsn_cmd,
-      "no secondary-sgsn",
-      NO_STR GBPROXY_SECOND_SGSN_STR)
-{
-	g_cfg->route_to_sgsn2 = 0;
-	g_cfg->nsip_sgsn2_nsei = 0xFFFF;
-
-	g_cfg->patch_ptmsi = 0;
-
-	return CMD_SUCCESS;
-}
-
-#define GBPROXY_LINK_LIST_STR "Set TLLI list parameters\n"
-#define GBPROXY_MAX_AGE_STR "Limit maximum age\n"
-
-DEFUN(cfg_gbproxy_link_list_max_age,
-      cfg_gbproxy_link_list_max_age_cmd,
-      "link-list max-age <1-999999>",
-      GBPROXY_LINK_LIST_STR GBPROXY_MAX_AGE_STR
-      "Maximum age in seconds\n")
-{
-	g_cfg->tlli_max_age = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gbproxy_link_list_no_max_age,
-      cfg_gbproxy_link_list_no_max_age_cmd,
-      "no link-list max-age",
-      NO_STR GBPROXY_LINK_LIST_STR GBPROXY_MAX_AGE_STR)
-{
-	g_cfg->tlli_max_age = 0;
-
-	return CMD_SUCCESS;
-}
-
-#define GBPROXY_MAX_LEN_STR "Limit list length\n"
-
-DEFUN(cfg_gbproxy_link_list_max_len,
-      cfg_gbproxy_link_list_max_len_cmd,
-      "link-list max-length <1-99999>",
-      GBPROXY_LINK_LIST_STR GBPROXY_MAX_LEN_STR
-      "Maximum number of logical links in the list\n")
-{
-	g_cfg->tlli_max_len = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gbproxy_link_list_no_max_len,
-      cfg_gbproxy_link_list_no_max_len_cmd,
-      "no link-list max-length",
-      NO_STR GBPROXY_LINK_LIST_STR GBPROXY_MAX_LEN_STR)
-{
-	g_cfg->tlli_max_len = 0;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gbproxy_link_list_keep_mode,
-      cfg_gbproxy_link_list_keep_mode_cmd,
-      "link-list keep-mode (never|re-attach|identified|always)",
-      GBPROXY_LINK_LIST_STR "How to keep entries for detached logical links\n"
-      "Discard entry immediately after detachment\n"
-      "Keep entry if a re-attachment has be requested\n"
-      "Keep entry if it associated with an IMSI\n"
-      "Don't discard entries after detachment\n")
-{
-	int val = get_string_value(keep_modes, argv[0]);
-	OSMO_ASSERT(val >= GBPROX_KEEP_NEVER && val <= GBPROX_KEEP_ALWAYS);
-	g_cfg->keep_link_infos = val;
-
-	return CMD_SUCCESS;
-}
-
-
-DEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]",
-       SHOW_STR "Display information about the Gb proxy\n" "Show statistics\n")
-{
-	struct gbproxy_peer *peer;
-	int show_stats = argc >= 1;
-
-	if (show_stats)
-		vty_out_rate_ctr_group(vty, "", g_cfg->ctrg);
-
-	llist_for_each_entry(peer, &g_cfg->bts_peers, list) {
-		gbprox_vty_print_peer(vty, peer);
-
-		if (show_stats)
-			vty_out_rate_ctr_group(vty, "  ", peer->ctrg);
-	}
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_gbproxy_links, show_gbproxy_links_cmd, "show gbproxy links",
-       SHOW_STR "Display information about the Gb proxy\n" "Show logical links\n")
-{
-	struct gbproxy_peer *peer;
-	char mi_buf[200];
-	time_t now;
-	struct timespec ts = {0,};
-
-	clock_gettime(CLOCK_MONOTONIC, &ts);
-	now = ts.tv_sec;
-
-	llist_for_each_entry(peer, &g_cfg->bts_peers, list) {
-		struct gbproxy_link_info *link_info;
-		struct gbproxy_patch_state *state = &peer->patch_state;
-
-		gbprox_vty_print_peer(vty, peer);
-
-		llist_for_each_entry(link_info, &state->logical_links, list) {
-			time_t age = now - link_info->timestamp;
-			int stored_msgs = 0;
-			struct llist_head *iter;
-			llist_for_each(iter, &link_info->stored_msgs)
-				stored_msgs++;
-
-			if (link_info->imsi > 0) {
-				snprintf(mi_buf, sizeof(mi_buf), "(invalid)");
-				gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
-						   link_info->imsi,
-						   link_info->imsi_len);
-			} else {
-				snprintf(mi_buf, sizeof(mi_buf), "(none)");
-			}
-			vty_out(vty, "  TLLI %08x, IMSI %s, AGE %d",
-				link_info->tlli.current, mi_buf, (int)age);
-
-			if (stored_msgs)
-				vty_out(vty, ", STORED %d", stored_msgs);
-
-			if (g_cfg->route_to_sgsn2)
-				vty_out(vty, ", SGSN NSEI %d",
-					link_info->sgsn_nsei);
-
-			if (link_info->is_deregistered)
-				vty_out(vty, ", DE-REGISTERED");
-
-			vty_out(vty, "%s", VTY_NEWLINE);
-		}
-	}
-	return CMD_SUCCESS;
-}
-
-DEFUN(delete_gb_bvci, delete_gb_bvci_cmd,
-	"delete-gbproxy-peer <0-65534> bvci <2-65534>",
-	"Delete a GBProxy peer by NSEI and optionally BVCI\n"
-	"NSEI number\n"
-	"Only delete peer with a matching BVCI\n"
-	"BVCI number\n")
-{
-	const uint16_t nsei = atoi(argv[0]);
-	const uint16_t bvci = atoi(argv[1]);
-	int counter;
-
-	counter = gbproxy_cleanup_peers(g_cfg, nsei, bvci);
-
-	if (counter == 0) {
-		vty_out(vty, "BVC not found%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(delete_gb_nsei, delete_gb_nsei_cmd,
-	"delete-gbproxy-peer <0-65534> (only-bvc|only-nsvc|all) [dry-run]",
-	"Delete a GBProxy peer by NSEI and optionally BVCI\n"
-	"NSEI number\n"
-	"Only delete BSSGP connections (BVC)\n"
-	"Only delete dynamic NS connections (NS-VC)\n"
-	"Delete BVC and dynamic NS connections\n"
-	"Show what would be deleted instead of actually deleting\n"
-	)
-{
-	const uint16_t nsei = atoi(argv[0]);
-	const char *mode = argv[1];
-	int dry_run = argc > 2;
-	int delete_bvc = 0;
-	int delete_nsvc = 0;
-	int counter;
-
-	if (strcmp(mode, "only-bvc") == 0)
-		delete_bvc = 1;
-	else if (strcmp(mode, "only-nsvc") == 0)
-		delete_nsvc = 1;
-	else
-		delete_bvc = delete_nsvc = 1;
-
-	if (delete_bvc) {
-		if (!dry_run)
-			counter = gbproxy_cleanup_peers(g_cfg, nsei, 0);
-		else {
-			struct gbproxy_peer *peer;
-			counter = 0;
-			llist_for_each_entry(peer, &g_cfg->bts_peers, list) {
-				if (peer->nsei != nsei)
-					continue;
-
-				vty_out(vty, "BVC: ");
-				gbprox_vty_print_peer(vty, peer);
-				counter += 1;
-			}
-		}
-		vty_out(vty, "%sDeleted %d BVC%s",
-			dry_run ? "Not " : "", counter, VTY_NEWLINE);
-	}
-
-	if (delete_nsvc) {
-		struct gprs_ns_inst *nsi = g_cfg->nsi;
-		struct gprs_nsvc *nsvc, *nsvc2;
-
-		counter = 0;
-		llist_for_each_entry_safe(nsvc, nsvc2, &nsi->gprs_nsvcs, list) {
-			if (nsvc->nsei != nsei)
-				continue;
-			if (nsvc->persistent)
-				continue;
-
-			if (!dry_run)
-				gprs_nsvc_delete(nsvc);
-			else
-				vty_out(vty, "NS-VC: NSEI %5u, NS-VCI %5u, "
-					"remote %s%s",
-					nsvc->nsei, nsvc->nsvci,
-					gprs_ns_ll_str(nsvc), VTY_NEWLINE);
-			counter += 1;
-		}
-		vty_out(vty, "%sDeleted %d NS-VC%s",
-			dry_run ? "Not " : "", counter, VTY_NEWLINE);
-	}
-
-	return CMD_SUCCESS;
-}
-
-#define GBPROXY_DELETE_LINK_STR \
-	"Delete a GBProxy logical link entry by NSEI and identification\nNSEI number\n"
-
-DEFUN(delete_gb_link_by_id, delete_gb_link_by_id_cmd,
-	"delete-gbproxy-link <0-65534> (tlli|imsi|sgsn-nsei) IDENT",
-	GBPROXY_DELETE_LINK_STR
-	"Delete entries with a matching TLLI (hex)\n"
-	"Delete entries with a matching IMSI\n"
-	"Delete entries with a matching SGSN NSEI\n"
-	"Identification to match\n")
-{
-	const uint16_t nsei = atoi(argv[0]);
-	enum {MATCH_TLLI = 't', MATCH_IMSI = 'i', MATCH_SGSN = 's'} match;
-	uint32_t ident = 0;
-	const char *imsi = NULL;
-	struct gbproxy_peer *peer = 0;
-	struct gbproxy_link_info *link_info, *nxt;
-	struct gbproxy_patch_state *state;
-	char mi_buf[200];
-	int found = 0;
-
-	match = argv[1][0];
-
-	switch (match) {
-	case MATCH_TLLI: ident = strtoll(argv[2], NULL, 16); break;
-	case MATCH_IMSI: imsi = argv[2]; break;
-	case MATCH_SGSN: ident = strtoll(argv[2], NULL, 0); break;
-	};
-
-	peer = gbproxy_peer_by_nsei(g_cfg, nsei);
-	if (!peer) {
-		vty_out(vty, "Didn't find peer with NSEI %d%s",
-			nsei, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	state = &peer->patch_state;
-
-	llist_for_each_entry_safe(link_info, nxt, &state->logical_links, list) {
-		switch (match) {
-		case MATCH_TLLI:
-			if (link_info->tlli.current != ident)
-				continue;
-			break;
-		case MATCH_SGSN:
-			if (link_info->sgsn_nsei != ident)
-				continue;
-			break;
-		case MATCH_IMSI:
-			if (!link_info->imsi)
-				continue;
-			mi_buf[0] = '\0';
-			gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
-					   link_info->imsi,
-					   link_info->imsi_len);
-
-			if (strcmp(mi_buf, imsi) != 0)
-				continue;
-			break;
-		}
-
-		vty_out(vty, "Deleting link with TLLI %08x%s", link_info->tlli.current,
-			VTY_NEWLINE);
-		gbproxy_delete_link_info(peer, link_info);
-		found += 1;
-	}
-
-	if (!found && argc >= 2) {
-		vty_out(vty, "Didn't find link entry with %s %s%s",
-			argv[1], argv[2], VTY_NEWLINE);
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(delete_gb_link, delete_gb_link_cmd,
-	"delete-gbproxy-link <0-65534> (stale|de-registered)",
-	GBPROXY_DELETE_LINK_STR
-	"Delete stale entries\n"
-	"Delete de-registered entries\n")
-{
-	const uint16_t nsei = atoi(argv[0]);
-	enum {MATCH_STALE = 's', MATCH_DEREGISTERED = 'd'} match;
-	struct gbproxy_peer *peer = 0;
-	struct gbproxy_link_info *link_info, *nxt;
-	struct gbproxy_patch_state *state;
-	time_t now;
-	struct timespec ts = {0,};
-
-	int found = 0;
-
-	match = argv[1][0];
-
-	peer = gbproxy_peer_by_nsei(g_cfg, nsei);
-	if (!peer) {
-		vty_out(vty, "Didn't find peer with NSEI %d%s",
-			nsei, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	state = &peer->patch_state;
-
-	clock_gettime(CLOCK_MONOTONIC, &ts);
-	now = ts.tv_sec;
-
-	if (match == MATCH_STALE) {
-		found = gbproxy_remove_stale_link_infos(peer, now);
-		if (found)
-			vty_out(vty, "Deleted %d stale logical link%s%s",
-				found, found == 1 ? "" : "s", VTY_NEWLINE);
-	} else {
-		llist_for_each_entry_safe(link_info, nxt,
-					  &state->logical_links, list) {
-			if (!link_info->is_deregistered)
-				continue;
-
-			gbproxy_delete_link_info(peer, link_info);
-			found += 1;
-		}
-	}
-
-	if (found)
-		vty_out(vty, "Deleted %d %s logical link%s%s",
-			found, argv[1], found == 1 ? "" : "s", VTY_NEWLINE);
-
-	return CMD_SUCCESS;
-}
-
-/*
- * legacy commands to provide an upgrade path from "broken" releases
- * or pre-releases
- */
-DEFUN_DEPRECATED(cfg_gbproxy_broken_apn_match,
-      cfg_gbproxy_broken_apn_match_cmd,
-      "core-access-point-name none match-imsi .REGEXP",
-      GBPROXY_CORE_APN_STR GBPROXY_MATCH_IMSI_STR "Remove APN\n"
-      "Patch MS related information elements on match only\n"
-      "Route to the secondary SGSN on match only\n"
-      "Regular expression for the IMSI match\n")
-{
-	const char *filter = argv[0];
-	const char *err_msg = NULL;
-	struct gbproxy_match *match;
-	enum gbproxy_match_id match_id = get_string_value(match_ids, "patching");
-
-	/* apply APN none */
-	set_core_apn(vty, "");
-
-	/* do the matching... with copy and paste */
-	OSMO_ASSERT(match_id >= GBPROX_MATCH_PATCHING &&
-		    match_id < GBPROX_MATCH_LAST);
-	match = &g_cfg->matches[match_id];
-
-	if (gbproxy_set_patch_filter(match, filter, &err_msg) != 0) {
-		vty_out(vty, "Match expression invalid: %s%s",
-			err_msg, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	g_cfg->acquire_imsi = 1;
-
-	return CMD_SUCCESS;
-}
-
-#define GBPROXY_TLLI_LIST_STR "Set TLLI list parameters\n"
-#define GBPROXY_MAX_LEN_STR "Limit list length\n"
-DEFUN_DEPRECATED(cfg_gbproxy_depr_tlli_list_max_len,
-      cfg_gbproxy_depr_tlli_list_max_len_cmd,
-      "tlli-list max-length <1-99999>",
-      GBPROXY_TLLI_LIST_STR GBPROXY_MAX_LEN_STR
-      "Maximum number of TLLIs in the list\n")
-{
-	g_cfg->tlli_max_len = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-int gbproxy_vty_init(void)
-{
-	install_element_ve(&show_gbproxy_cmd);
-	install_element_ve(&show_gbproxy_links_cmd);
-
-	install_element(ENABLE_NODE, &delete_gb_bvci_cmd);
-	install_element(ENABLE_NODE, &delete_gb_nsei_cmd);
-	install_element(ENABLE_NODE, &delete_gb_link_by_id_cmd);
-	install_element(ENABLE_NODE, &delete_gb_link_cmd);
-
-	install_element(CONFIG_NODE, &cfg_gbproxy_cmd);
-	install_node(&gbproxy_node, config_write_gbproxy);
-	vty_install_default(GBPROXY_NODE);
-	install_element(GBPROXY_NODE, &cfg_nsip_sgsn_nsei_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_core_mcc_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_core_mnc_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_match_imsi_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_core_apn_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_secondary_sgsn_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_patch_ptmsi_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_acquire_imsi_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_max_age_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_max_len_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_keep_mode_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mcc_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mnc_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_no_match_imsi_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_apn_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_no_secondary_sgsn_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_no_patch_ptmsi_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_no_acquire_imsi_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_max_age_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_max_len_cmd);
-
-	/* broken or deprecated to allow an upgrade path */
-	install_element(GBPROXY_NODE, &cfg_gbproxy_broken_apn_match_cmd);
-	install_element(GBPROXY_NODE, &cfg_gbproxy_depr_tlli_list_max_len_cmd);
-
-	return 0;
-}
-
-int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg)
-{
-	int rc;
-
-	g_cfg = cfg;
-	rc = vty_read_config_file(config_file, NULL);
-	if (rc < 0) {
-		fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
-		return rc;
-	}
-
-	return 0;
-}
-
diff --git a/src/gprs/gprs_gb_parse.c b/src/gprs/gprs_gb_parse.c
deleted file mode 100644
index d5a122b..0000000
--- a/src/gprs/gprs_gb_parse.c
+++ /dev/null
@@ -1,636 +0,0 @@
-/* GPRS Gb message parser */
-
-/* (C) 2014 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/>.
- *
- */
-
-#include <osmocom/gsm/gsm48.h>
-#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
-
-#include <openbsc/gprs_gb_parse.h>
-
-#include <openbsc/gprs_utils.h>
-
-#include <openbsc/debug.h>
-
-#include <osmocom/gprs/gprs_bssgp.h>
-
-static int gprs_gb_parse_gmm_attach_req(uint8_t *data, size_t data_len,
-					struct gprs_gb_parse_context *parse_ctx)
-{
-	uint8_t *value;
-	size_t value_len;
-
-	parse_ctx->llc_msg_name = "ATTACH_REQ";
-
-	/* Skip MS network capability */
-	if (osmo_shift_lv(&data, &data_len, NULL, &value_len) <= 0 ||
-	    value_len < 1 || value_len > 8)
-		/* invalid */
-		return 0;
-
-	/* Skip Attach type */
-	/* Skip Ciphering key sequence number */
-	/* Skip DRX parameter */
-	osmo_shift_v_fixed(&data, &data_len, 3, NULL);
-
-	/* Get Mobile identity */
-	if (osmo_shift_lv(&data, &data_len, &value, &value_len) <= 0 ||
-	    value_len < 5 || value_len > 8)
-		/* invalid */
-		return 0;
-
-	if (gprs_is_mi_tmsi(value, value_len)) {
-		parse_ctx->ptmsi_enc = value + 1;
-	} else if (gprs_is_mi_imsi(value, value_len)) {
-		parse_ctx->imsi = value;
-		parse_ctx->imsi_len = value_len;
-	}
-
-	if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
-		return 0;
-
-	parse_ctx->old_raid_enc = value;
-
-	return 1;
-}
-
-static int gprs_gb_parse_gmm_attach_ack(uint8_t *data, size_t data_len,
-					struct gprs_gb_parse_context *parse_ctx)
-{
-	uint8_t *value;
-	size_t value_len;
-
-	parse_ctx->llc_msg_name = "ATTACH_ACK";
-
-	/* Skip Attach result */
-	/* Skip Force to standby */
-	/* Skip Periodic RA update timer */
-	/* Skip Radio priority for SMS */
-	/* Skip Spare half octet */
-	osmo_shift_v_fixed(&data, &data_len, 3, NULL);
-
-	if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
-		return 0;
-
-	parse_ctx->raid_enc = value;
-
-	/* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */
-	osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
-
-	/* Skip Negotiated READY timer value (GPRS timer, opt, TV, length 2) */
-	osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_TIMER_READY, 1, NULL);
-
-	/* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */
-	if (osmo_match_shift_tlv(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
-		      &value, &value_len) > 0 &&
-	    gprs_is_mi_tmsi(value, value_len))
-		parse_ctx->new_ptmsi_enc = value + 1;
-	return 1;
-}
-
-static int gprs_gb_parse_gmm_attach_rej(uint8_t *data, size_t data_len,
-					struct gprs_gb_parse_context *parse_ctx)
-{
-	uint8_t *value;
-
-	parse_ctx->llc_msg_name = "ATTACH_REJ";
-
-	/* GMM cause */
-	if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
-		return 0;
-
-	parse_ctx->invalidate_tlli = 1;
-
-	return 1;
-}
-
-
-static int gprs_gb_parse_gmm_detach_req(uint8_t *data, size_t data_len,
-					struct gprs_gb_parse_context *parse_ctx)
-{
-	uint8_t *value;
-	size_t value_len;
-	int detach_type;
-	int power_off;
-
-	parse_ctx->llc_msg_name = "DETACH_REQ";
-
-	/* Skip spare half octet */
-	/* Get Detach type */
-	if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
-		/* invalid */
-		return 0;
-
-	detach_type = *value & 0x07;
-	power_off = *value & 0x08 ? 1 : 0;
-
-	if (parse_ctx->to_bss) {
-		/* Network originated */
-		if (detach_type == GPRS_DET_T_MT_REATT_REQ)
-			parse_ctx->await_reattach = 1;
-	} else {
-		/* Mobile originated */
-
-		if (power_off)
-			parse_ctx->invalidate_tlli = 1;
-
-		/* Get P-TMSI (Mobile identity), see GSM 24.008, 9.4.5.2 */
-		if (osmo_match_shift_tlv(&data, &data_len,
-			      GSM48_IE_GMM_ALLOC_PTMSI, &value, &value_len) > 0)
-		{
-			if (gprs_is_mi_tmsi(value, value_len))
-				parse_ctx->ptmsi_enc = value + 1;
-		}
-	}
-
-	return 1;
-}
-
-static int gprs_gb_parse_gmm_ra_upd_req(uint8_t *data, size_t data_len,
-					struct gprs_gb_parse_context *parse_ctx)
-{
-	uint8_t *value;
-
-	parse_ctx->llc_msg_name = "RA_UPD_REQ";
-
-	/* Skip Update type */
-	/* Skip GPRS ciphering key sequence number */
-	osmo_shift_v_fixed(&data, &data_len, 1, NULL);
-
-	if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
-		return 0;
-
-	parse_ctx->old_raid_enc = value;
-
-	return 1;
-}
-
-static int gprs_gb_parse_gmm_ra_upd_rej(uint8_t *data, size_t data_len,
-					struct gprs_gb_parse_context *parse_ctx)
-{
-	uint8_t *value;
-	uint8_t cause;
-	int force_standby;
-
-	parse_ctx->llc_msg_name = "RA_UPD_REJ";
-
-	/* GMM cause */
-	if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
-		return 0;
-
-	cause = value[0];
-
-	/* Force to standby, 1/2 */
-	/* spare bits, 1/2 */
-	if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
-		return 0;
-
-	force_standby = (value[0] & 0x07) == 0x01;
-
-	if (cause == GMM_CAUSE_IMPL_DETACHED && !force_standby)
-		parse_ctx->await_reattach = 1;
-
-	parse_ctx->invalidate_tlli = 1;
-
-	return 1;
-}
-
-static int gprs_gb_parse_gmm_ra_upd_ack(uint8_t *data, size_t data_len,
-					struct gprs_gb_parse_context *parse_ctx)
-{
-	uint8_t *value;
-	size_t value_len;
-
-	parse_ctx->llc_msg_name = "RA_UPD_ACK";
-
-	/* Skip Force to standby */
-	/* Skip Update result */
-	/* Skip Periodic RA update timer */
-	osmo_shift_v_fixed(&data, &data_len, 2, NULL);
-
-	if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
-		return 0;
-
-	parse_ctx->raid_enc = value;
-
-	/* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */
-	osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
-
-	/* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */
-	if (osmo_match_shift_tlv(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
-		      &value, &value_len) > 0 &&
-	    gprs_is_mi_tmsi(value, value_len))
-		parse_ctx->new_ptmsi_enc = value + 1;
-
-	return 1;
-}
-
-static int gprs_gb_parse_gmm_ptmsi_reall_cmd(uint8_t *data, size_t data_len,
-					     struct gprs_gb_parse_context *parse_ctx)
-{
-	uint8_t *value;
-	size_t value_len;
-
-	parse_ctx->llc_msg_name = "PTMSI_REALL_CMD";
-
-	LOGP(DLLC, LOGL_NOTICE,
-	     "Got P-TMSI Reallocation Command which is not covered by unit tests yet.\n");
-
-	/* Allocated P-TMSI */
-	if (osmo_shift_lv(&data, &data_len, &value, &value_len) > 0 &&
-	    gprs_is_mi_tmsi(value, value_len))
-		parse_ctx->new_ptmsi_enc = value + 1;
-
-	if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
-		return 0;
-
-	parse_ctx->raid_enc = value;
-
-	return 1;
-}
-
-static int gprs_gb_parse_gmm_id_resp(uint8_t *data, size_t data_len,
-				     struct gprs_gb_parse_context *parse_ctx)
-{
-	uint8_t *value;
-	size_t value_len;
-
-	parse_ctx->llc_msg_name = "ID_RESP";
-
-	/* Mobile identity, Mobile identity 10.5.1.4, M LV 2-10 */
-	if (osmo_shift_lv(&data, &data_len, &value, &value_len) <= 0 ||
-	    value_len < 1 || value_len > 9)
-		/* invalid */
-		return 0;
-
-	if (gprs_is_mi_tmsi(value, value_len)) {
-		parse_ctx->ptmsi_enc = value + 1;
-	} else if (gprs_is_mi_imsi(value, value_len)) {
-		parse_ctx->imsi = value;
-		parse_ctx->imsi_len = value_len;
-	}
-
-	return 1;
-}
-
-static int gprs_gb_parse_gsm_act_pdp_req(uint8_t *data, size_t data_len,
-					 struct gprs_gb_parse_context *parse_ctx)
-{
-	ssize_t old_len;
-	uint8_t *value;
-	size_t value_len;
-
-	parse_ctx->llc_msg_name = "ACT_PDP_REQ";
-
-	/* Skip Requested NSAPI */
-	/* Skip Requested LLC SAPI */
-	osmo_shift_v_fixed(&data, &data_len, 2, NULL);
-
-	/* Skip Requested QoS (support 04.08 and 24.008) */
-	if (osmo_shift_lv(&data, &data_len, NULL, &value_len) <= 0 ||
-	    value_len < 4 || value_len > 14)
-		/* invalid */
-		return 0;
-
-	/* Skip Requested PDP address */
-	if (osmo_shift_lv(&data, &data_len, NULL, &value_len) <= 0 ||
-	    value_len < 2 || value_len > 18)
-		/* invalid */
-		return 0;
-
-	/* Access point name */
-	old_len = osmo_match_shift_tlv(&data, &data_len,
-			    GSM48_IE_GSM_APN, &value, &value_len);
-
-	if (old_len > 0 && value_len >=1 && value_len <= 100) {
-		parse_ctx->apn_ie = data - old_len;
-		parse_ctx->apn_ie_len = old_len;
-	}
-
-	return 1;
-}
-
-int gprs_gb_parse_dtap(uint8_t *data, size_t data_len,
-		       struct gprs_gb_parse_context *parse_ctx)
-{
-	struct gsm48_hdr *g48h;
-	uint8_t pdisc;
-	uint8_t msg_type;
-
-	if (osmo_shift_v_fixed(&data, &data_len, sizeof(*g48h), (uint8_t **)&g48h) <= 0)
-		return 0;
-
-	parse_ctx->g48_hdr = g48h;
-
-	pdisc = gsm48_hdr_pdisc(g48h);
-	if (pdisc != GSM48_PDISC_MM_GPRS && pdisc != GSM48_PDISC_SM_GPRS)
-		return 1;
-
-	msg_type = gsm48_hdr_msg_type(g48h);
-	switch (msg_type) {
-	case GSM48_MT_GMM_ATTACH_REQ:
-		return gprs_gb_parse_gmm_attach_req(data, data_len, parse_ctx);
-
-	case GSM48_MT_GMM_ATTACH_REJ:
-		return gprs_gb_parse_gmm_attach_rej(data, data_len, parse_ctx);
-
-	case GSM48_MT_GMM_ATTACH_ACK:
-		return gprs_gb_parse_gmm_attach_ack(data, data_len, parse_ctx);
-
-	case GSM48_MT_GMM_RA_UPD_REQ:
-		return gprs_gb_parse_gmm_ra_upd_req(data, data_len, parse_ctx);
-
-	case GSM48_MT_GMM_RA_UPD_REJ:
-		return gprs_gb_parse_gmm_ra_upd_rej(data, data_len, parse_ctx);
-
-	case GSM48_MT_GMM_RA_UPD_ACK:
-		return gprs_gb_parse_gmm_ra_upd_ack(data, data_len, parse_ctx);
-
-	case GSM48_MT_GMM_PTMSI_REALL_CMD:
-		return gprs_gb_parse_gmm_ptmsi_reall_cmd(data, data_len, parse_ctx);
-
-	case GSM48_MT_GSM_ACT_PDP_REQ:
-		return gprs_gb_parse_gsm_act_pdp_req(data, data_len, parse_ctx);
-
-	case GSM48_MT_GMM_ID_RESP:
-		return gprs_gb_parse_gmm_id_resp(data, data_len, parse_ctx);
-
-	case GSM48_MT_GMM_DETACH_REQ:
-		return gprs_gb_parse_gmm_detach_req(data, data_len, parse_ctx);
-
-	case GSM48_MT_GMM_DETACH_ACK:
-		parse_ctx->llc_msg_name = "DETACH_ACK";
-		parse_ctx->invalidate_tlli = 1;
-		break;
-
-	default:
-		LOGP(DLLC, LOGL_NOTICE,
-		     "Unhandled GSM 04.08 message type %s for protocol discriminator %s.\n",
-		     get_value_string(gprs_msgt_gmm_names, msg_type), get_value_string(gsm48_pdisc_names, pdisc));
-		break;
-	};
-
-	return 1;
-}
-
-int gprs_gb_parse_llc(uint8_t *llc, size_t llc_len,
-		      struct gprs_gb_parse_context *parse_ctx)
-{
-	struct gprs_llc_hdr_parsed *ghp = &parse_ctx->llc_hdr_parsed;
-	int rc;
-	int fcs;
-
-	/* parse LLC */
-	rc = gprs_llc_hdr_parse(ghp, llc, llc_len);
-	gprs_llc_hdr_dump(ghp, NULL);
-	if (rc != 0) {
-		LOGP(DLLC, LOGL_NOTICE, "Error during LLC header parsing\n");
-		return 0;
-	}
-
-	fcs = gprs_llc_fcs(llc, ghp->crc_length);
-	LOGP(DLLC, LOGL_DEBUG, "Got LLC message, CRC: %06x (computed %06x)\n",
-	     ghp->fcs, fcs);
-
-	if (!ghp->data)
-		return 0;
-
-	if (ghp->sapi != GPRS_SAPI_GMM)
-		return 1;
-
-	if (ghp->cmd != GPRS_LLC_UI)
-		return 1;
-
-	if (ghp->is_encrypted) {
-		parse_ctx->need_decryption = 1;
-		return 0;
-	}
-
-	return gprs_gb_parse_dtap(ghp->data, ghp->data_len, parse_ctx);
-}
-
-int gprs_gb_parse_bssgp(uint8_t *bssgp, size_t bssgp_len,
-			struct gprs_gb_parse_context *parse_ctx)
-{
-	struct bssgp_normal_hdr *bgph;
-	struct bssgp_ud_hdr *budh = NULL;
-	struct tlv_parsed *tp = &parse_ctx->bssgp_tp;
-	uint8_t pdu_type;
-	uint8_t *data;
-	size_t data_len;
-	int rc;
-
-	if (bssgp_len < sizeof(struct bssgp_normal_hdr))
-		return 0;
-
-	bgph = (struct bssgp_normal_hdr *)bssgp;
-	pdu_type = bgph->pdu_type;
-
-	if (pdu_type == BSSGP_PDUT_UL_UNITDATA ||
-	    pdu_type == BSSGP_PDUT_DL_UNITDATA) {
-		if (bssgp_len < sizeof(struct bssgp_ud_hdr))
-			return 0;
-		budh = (struct bssgp_ud_hdr *)bssgp;
-		bgph = NULL;
-		data = budh->data;
-		data_len = bssgp_len - sizeof(*budh);
-	} else {
-		data = bgph->data;
-		data_len = bssgp_len - sizeof(*bgph);
-	}
-
-	parse_ctx->pdu_type = pdu_type;
-	parse_ctx->bud_hdr = budh;
-	parse_ctx->bgp_hdr = bgph;
-	parse_ctx->bssgp_data = data;
-	parse_ctx->bssgp_data_len = data_len;
-
-	if (bssgp_tlv_parse(tp, data, data_len) < 0)
-		return 0;
-
-	if (budh)
-		parse_ctx->tlli_enc = (uint8_t *)&budh->tlli;
-
-	if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA))
-		parse_ctx->bssgp_raid_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA);
-
-	if (TLVP_PRESENT(tp, BSSGP_IE_CELL_ID))
-		parse_ctx->bssgp_raid_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_CELL_ID);
-
-	if (TLVP_PRESENT(tp, BSSGP_IE_IMSI)) {
-		parse_ctx->imsi = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_IMSI);
-		parse_ctx->imsi_len = TLVP_LEN(tp, BSSGP_IE_IMSI);
-	}
-
-	if (TLVP_PRESENT(tp, BSSGP_IE_TLLI)) {
-		if (parse_ctx->tlli_enc)
-			/* This is TLLI old, don't confuse it with TLLI current */
-			parse_ctx->old_tlli_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TLLI);
-		else
-			parse_ctx->tlli_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TLLI);
-	}
-
-	if (TLVP_PRESENT(tp, BSSGP_IE_TMSI) && pdu_type == BSSGP_PDUT_PAGING_PS)
-		parse_ctx->bssgp_ptmsi_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TMSI);
-
-	if (TLVP_PRESENT(tp, BSSGP_IE_LLC_PDU)) {
-		uint8_t *llc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_LLC_PDU);
-		size_t llc_len = TLVP_LEN(tp, BSSGP_IE_LLC_PDU);
-
-		rc = gprs_gb_parse_llc(llc, llc_len, parse_ctx);
-		if (!rc)
-			return 0;
-
-		parse_ctx->llc = llc;
-		parse_ctx->llc_len = llc_len;
-	}
-
-	if (parse_ctx->tlli_enc) {
-		uint32_t tmp_tlli;
-		memcpy(&tmp_tlli, parse_ctx->tlli_enc, sizeof(tmp_tlli));
-		parse_ctx->tlli = ntohl(tmp_tlli);
-	}
-
-	if (parse_ctx->bssgp_raid_enc && parse_ctx->old_raid_enc &&
-	    memcmp(parse_ctx->bssgp_raid_enc, parse_ctx->old_raid_enc, 6) != 0)
-		parse_ctx->old_raid_is_foreign = 1;
-
-	return 1;
-}
-
-void gprs_gb_log_parse_context(int log_level,
-			       struct gprs_gb_parse_context *parse_ctx,
-			       const char *default_msg_name)
-{
-	const char *msg_name;
-	const char *sep = "";
-
-	if (!parse_ctx->tlli_enc &&
-	    !parse_ctx->ptmsi_enc &&
-	    !parse_ctx->new_ptmsi_enc &&
-	    !parse_ctx->bssgp_ptmsi_enc &&
-	    !parse_ctx->imsi)
-		return;
-
-	msg_name = gprs_gb_message_name(parse_ctx, default_msg_name);
-
-	if (parse_ctx->llc_msg_name)
-		msg_name = parse_ctx->llc_msg_name;
-
-	LOGP(DGPRS, log_level, "%s: Got", msg_name);
-
-	if (parse_ctx->tlli_enc) {
-		LOGPC(DGPRS, log_level, "%s TLLI %08x", sep, parse_ctx->tlli);
-		sep = ",";
-	}
-
-	if (parse_ctx->old_tlli_enc) {
-		LOGPC(DGPRS, log_level, "%s old TLLI %02x%02x%02x%02x", sep,
-		     parse_ctx->old_tlli_enc[0],
-		     parse_ctx->old_tlli_enc[1],
-		     parse_ctx->old_tlli_enc[2],
-		     parse_ctx->old_tlli_enc[3]);
-		sep = ",";
-	}
-
-	if (parse_ctx->bssgp_raid_enc) {
-		struct gprs_ra_id raid;
-		gsm48_parse_ra(&raid, parse_ctx->bssgp_raid_enc);
-		LOGPC(DGPRS, log_level, "%s BSSGP RAID %u-%u-%u-%u", sep,
-		     raid.mcc, raid.mnc, raid.lac, raid.rac);
-		sep = ",";
-	}
-
-	if (parse_ctx->raid_enc) {
-		struct gprs_ra_id raid;
-		gsm48_parse_ra(&raid, parse_ctx->raid_enc);
-		LOGPC(DGPRS, log_level, "%s RAID %u-%u-%u-%u", sep,
-		     raid.mcc, raid.mnc, raid.lac, raid.rac);
-		sep = ",";
-	}
-
-	if (parse_ctx->old_raid_enc) {
-		struct gprs_ra_id raid;
-		gsm48_parse_ra(&raid, parse_ctx->old_raid_enc);
-		LOGPC(DGPRS, log_level, "%s old RAID %u-%u-%u-%u", sep,
-		     raid.mcc, raid.mnc, raid.lac, raid.rac);
-		sep = ",";
-	}
-
-	if (parse_ctx->bssgp_ptmsi_enc) {
-		uint32_t ptmsi = GSM_RESERVED_TMSI;
-		gprs_parse_tmsi(parse_ctx->bssgp_ptmsi_enc, &ptmsi);
-		LOGPC(DGPRS, log_level, "%s BSSGP PTMSI %08x", sep, ptmsi);
-		sep = ",";
-	}
-
-	if (parse_ctx->ptmsi_enc) {
-		uint32_t ptmsi = GSM_RESERVED_TMSI;
-		gprs_parse_tmsi(parse_ctx->ptmsi_enc, &ptmsi);
-		LOGPC(DGPRS, log_level, "%s PTMSI %08x", sep, ptmsi);
-		sep = ",";
-	}
-
-	if (parse_ctx->new_ptmsi_enc) {
-		uint32_t new_ptmsi = GSM_RESERVED_TMSI;
-		gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
-		LOGPC(DGPRS, log_level, "%s new PTMSI %08x", sep, new_ptmsi);
-		sep = ",";
-	}
-
-	if (parse_ctx->imsi) {
-		char mi_buf[200];
-		mi_buf[0] = '\0';
-		gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
-				   parse_ctx->imsi, parse_ctx->imsi_len);
-		LOGPC(DGPRS, log_level, "%s IMSI %s",
-		     sep, mi_buf);
-		sep = ",";
-	}
-	if (parse_ctx->invalidate_tlli) {
-		LOGPC(DGPRS, log_level, "%s invalidate", sep);
-		sep = ",";
-	}
-	if (parse_ctx->await_reattach) {
-		LOGPC(DGPRS, log_level, "%s re-attach", sep);
-		sep = ",";
-	}
-
-	LOGPC(DGPRS, log_level, "\n");
-}
-
-const char *gprs_gb_message_name(const struct gprs_gb_parse_context *parse_ctx,
-				 const char *default_msg_name)
-{
-	if (parse_ctx->llc_msg_name)
-		return parse_ctx->llc_msg_name;
-
-	if (parse_ctx->g48_hdr)
-		return "GMM";
-
-	if (parse_ctx->llc)
-		return "LLC";
-
-	if (parse_ctx->bud_hdr)
-		return "BSSGP-UNITDATA";
-
-	if (parse_ctx->bgp_hdr)
-		return "BSSGP";
-
-	return "unknown";
-}
diff --git a/src/gprs/gprs_gmm.c b/src/gprs/gprs_gmm.c
deleted file mode 100644
index 032137f..0000000
--- a/src/gprs/gprs_gmm.c
+++ /dev/null
@@ -1,2937 +0,0 @@
-/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
- * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
-
-/* (C) 2009-2015 by Harald Welte <laforge@gnumonks.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/>.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-
-#include <openssl/rand.h>
-
-#include "bscconfig.h"
-
-#include <openbsc/db.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/core/signal.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/crypt/auth.h>
-#include <osmocom/gsm/apn.h>
-#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
-
-#include <osmocom/gprs/gprs_bssgp.h>
-
-#ifdef BUILD_IU
-#include <osmocom/ranap/ranap_ies_defs.h>
-#include <osmocom/ranap/ranap_msg_factory.h>
-#include <osmocom/ranap/iu_client.h>
-#endif
-
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/paging.h>
-#include <openbsc/transaction.h>
-#include <openbsc/gprs_llc.h>
-#include <openbsc/gprs_sgsn.h>
-#include <openbsc/gprs_gmm.h>
-#include <openbsc/gprs_utils.h>
-#include <openbsc/gprs_subscriber.h>
-#include <openbsc/sgsn.h>
-#include <openbsc/signal.h>
-#include <openbsc/gprs_sndcp.h>
-
-#include <pdp.h>
-
-#define PTMSI_ALLOC
-
-extern struct sgsn_instance *sgsn;
-
-static const struct tlv_definition gsm48_gmm_att_tlvdef = {
-	.def = {
-		[GSM48_IE_GMM_CIPH_CKSN]	= { TLV_TYPE_FIXED, 1 },
-		[GSM48_IE_GMM_TIMER_READY]	= { TLV_TYPE_TV, 1 },
-		[GSM48_IE_GMM_ALLOC_PTMSI]	= { TLV_TYPE_TLV, 0 },
-		[GSM48_IE_GMM_PTMSI_SIG]	= { TLV_TYPE_FIXED, 3 },
-		[GSM48_IE_GMM_AUTH_RAND]	= { TLV_TYPE_FIXED, 16 },
-		[GSM48_IE_GMM_AUTH_SRES]	= { TLV_TYPE_FIXED, 4 },
-		[GSM48_IE_GMM_AUTH_RES_EXT]	= { TLV_TYPE_TLV, 0 },
-		[GSM48_IE_GMM_AUTH_FAIL_PAR]	= { TLV_TYPE_TLV, 0 },
-		[GSM48_IE_GMM_IMEISV]		= { TLV_TYPE_TLV, 0 },
-		[GSM48_IE_GMM_DRX_PARAM]	= { TLV_TYPE_FIXED, 2 },
-		[GSM48_IE_GMM_MS_NET_CAPA]	= { TLV_TYPE_TLV, 0 },
-		[GSM48_IE_GMM_PDP_CTX_STATUS]	= { TLV_TYPE_TLV, 0 },
-		[GSM48_IE_GMM_PS_LCS_CAPA]	= { TLV_TYPE_TLV, 0 },
-		[GSM48_IE_GMM_GMM_MBMS_CTX_ST]	= { TLV_TYPE_TLV, 0 },
-	},
-};
-
-static const struct tlv_definition gsm48_sm_att_tlvdef = {
-	.def = {
-		[GSM48_IE_GSM_APN]		= { TLV_TYPE_TLV, 0 },
-		[GSM48_IE_GSM_PROTO_CONF_OPT]	= { TLV_TYPE_TLV, 0 },
-		[GSM48_IE_GSM_PDP_ADDR]		= { TLV_TYPE_TLV, 0 },
-		[GSM48_IE_GSM_AA_TMR]		= { TLV_TYPE_TV, 1 },
-		[GSM48_IE_GSM_NAME_FULL]	= { TLV_TYPE_TLV, 0 },
-		[GSM48_IE_GSM_NAME_SHORT]	= { TLV_TYPE_TLV, 0 },
-		[GSM48_IE_GSM_TIMEZONE]		= { TLV_TYPE_FIXED, 1 },
-		[GSM48_IE_GSM_UTC_AND_TZ]	= { TLV_TYPE_FIXED, 7 },
-		[GSM48_IE_GSM_LSA_ID]		= { TLV_TYPE_TLV, 0 },
-	},
-};
-
-static const struct value_string gprs_pmm_state_names[] = {
-	{ PMM_DETACHED,		"PMM DETACH" },
-	{ PMM_CONNECTED,	"PMM CONNECTED" },
-	{ PMM_IDLE,		"PMM IDLE" },
-	{ MM_IDLE,		"MM IDLE" },
-	{ MM_READY,		"MM READY" },
-	{ MM_STANDBY,		"MM STANDBY" },
-	{ 0, NULL }
-};
-
-static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx);
-
-static void mmctx_change_gtpu_endpoints_to_sgsn(struct sgsn_mm_ctx *mm_ctx)
-{
-	struct sgsn_pdp_ctx *pdp;
-	llist_for_each_entry(pdp, &mm_ctx->pdp_list, list) {
-		sgsn_pdp_upd_gtp_u(pdp,
-				   &sgsn->cfg.gtp_listenaddr.sin_addr,
-				   sizeof(sgsn->cfg.gtp_listenaddr.sin_addr));
-	}
-}
-
-void mmctx_set_pmm_state(struct sgsn_mm_ctx *ctx, enum gprs_pmm_state state)
-{
-	if (ctx->ran_type != MM_CTX_T_UTRAN_Iu)
-		return;
-
-	if (ctx->pmm_state == state)
-		return;
-
-	LOGMMCTXP(LOGL_INFO, ctx, "Changing PMM state from %s to %s\n",
-		  get_value_string(gprs_pmm_state_names, ctx->pmm_state),
-		  get_value_string(gprs_pmm_state_names, state));
-
-	switch (state) {
-	case PMM_IDLE:
-		/* TODO: start RA Upd timer */
-		mmctx_change_gtpu_endpoints_to_sgsn(ctx);
-		break;
-	case PMM_CONNECTED:
-		break;
-	default:
-		break;
-	}
-
-	ctx->pmm_state = state;
-}
-
-void mmctx_set_mm_state(struct sgsn_mm_ctx *ctx, enum gprs_pmm_state state)
-{
-	if (ctx->ran_type != MM_CTX_T_GERAN_Gb)
-		return;
-
-	if (ctx->pmm_state == state)
-		return;
-
-	LOGMMCTXP(LOGL_INFO, ctx, "Changing MM state from %s to %s\n",
-		  get_value_string(gprs_pmm_state_names, ctx->pmm_state),
-		  get_value_string(gprs_pmm_state_names, state));
-
-	ctx->pmm_state = state;
-}
-
-#ifdef BUILD_IU
-int sgsn_ranap_rab_ass_resp(struct sgsn_mm_ctx *ctx, RANAP_RAB_SetupOrModifiedItemIEs_t *setup_ies);
-int sgsn_ranap_iu_event(struct ranap_ue_conn_ctx *ctx, enum ranap_iu_event_type type, void *data)
-{
-	struct sgsn_mm_ctx *mm;
-	int rc = -1;
-
-	mm = sgsn_mm_ctx_by_ue_ctx(ctx);
-
-#define REQUIRE_MM \
-	if (!mm) { \
-		LOGP(DRANAP, LOGL_NOTICE, "Cannot find mm ctx for IU event %d\n", type); \
-		return rc; \
-	}
-
-	switch (type) {
-	case RANAP_IU_EVENT_RAB_ASSIGN:
-		REQUIRE_MM
-		rc = sgsn_ranap_rab_ass_resp(mm, (RANAP_RAB_SetupOrModifiedItemIEs_t *)data);
-		break;
-	case RANAP_IU_EVENT_IU_RELEASE:
-		/* fall thru */
-	case RANAP_IU_EVENT_LINK_INVALIDATED:
-		/* Clean up ranap_ue_conn_ctx here */
-		if (mm)
-			LOGMMCTXP(LOGL_INFO, mm, "IU release for imsi %s\n", mm->imsi);
-		else
-			LOGMMCTXP(LOGL_INFO, mm, "IU release for UE conn 0x%x\n",
-				  ctx->conn_id);
-		if (mm && mm->pmm_state == PMM_CONNECTED)
-			mmctx_set_pmm_state(mm, PMM_IDLE);
-		rc = 0;
-		break;
-	case RANAP_IU_EVENT_SECURITY_MODE_COMPLETE:
-		REQUIRE_MM
-		/* Continue authentication here */
-		mm->iu.ue_ctx->integrity_active = 1;
-		rc = gsm48_gmm_authorize(mm);
-		break;
-	default:
-		LOGP(DRANAP, LOGL_NOTICE, "Unknown event received: %i\n", type);
-		rc = -1;
-		break;
-	}
-	return rc;
-}
-#endif
-
-
-/* Our implementation, should be kept in SGSN */
-
-static void mmctx_timer_cb(void *_mm);
-
-static void mmctx_timer_start(struct sgsn_mm_ctx *mm, unsigned int T,
-				unsigned int seconds)
-{
-	if (osmo_timer_pending(&mm->timer))
-		LOGMMCTXP(LOGL_ERROR, mm, "Starting MM timer %u while old "
-			"timer %u pending\n", T, mm->T);
-	mm->T = T;
-	mm->num_T_exp = 0;
-
-	/* FIXME: we should do this only once ? */
-	osmo_timer_setup(&mm->timer, mmctx_timer_cb, mm);
-	osmo_timer_schedule(&mm->timer, seconds, 0);
-}
-
-static void mmctx_timer_stop(struct sgsn_mm_ctx *mm, unsigned int T)
-{
-	if (mm->T != T)
-		LOGMMCTXP(LOGL_ERROR, mm, "Stopping MM timer %u but "
-			"%u is running\n", T, mm->T);
-	osmo_timer_del(&mm->timer);
-}
-
-time_t gprs_max_time_to_idle(void)
-{
-	return sgsn->cfg.timers.T3314 + (sgsn->cfg.timers.T3312 + 4 * 60);
-}
-
-/* Send a message through the underlying layer.
- * For param encryptable, see 3GPP TS 24.008 § 4.7.1.2 and
- * gsm48_hdr_gmm_cipherable(). Pass false for not cipherable messages. */
-static int gsm48_gmm_sendmsg(struct msgb *msg, int command,
-			     struct sgsn_mm_ctx *mm, bool encryptable)
-{
-	if (mm) {
-		rate_ctr_inc(&mm->ctrg->ctr[GMM_CTR_PKTS_SIG_OUT]);
-#ifdef BUILD_IU
-		if (mm->ran_type == MM_CTX_T_UTRAN_Iu)
-			return ranap_iu_tx(msg, GPRS_SAPI_GMM);
-#endif
-	}
-
-#ifdef BUILD_IU
-	/* In Iu mode, msg->dst contains the ranap_ue_conn_ctx pointer, in Gb mode
-	 * dst is empty. */
-	/* FIXME: have a more explicit indicator for Iu messages */
-	if (msg->dst)
-		return ranap_iu_tx(msg, GPRS_SAPI_GMM);
-#endif
-
-	/* caller needs to provide TLLI, BVCI and NSEI */
-	return gprs_llc_tx_ui(msg, GPRS_SAPI_GMM, command, mm, encryptable);
-}
-
-/* copy identifiers from old message to new message, this
- * is required so lower layers can route it correctly */
-static void gmm_copy_id(struct msgb *msg, const struct msgb *old)
-{
-	msgb_tlli(msg) = msgb_tlli(old);
-	msgb_bvci(msg) = msgb_bvci(old);
-	msgb_nsei(msg) = msgb_nsei(old);
-	msg->dst = old->dst;
-}
-
-/* Store BVCI/NSEI in MM context */
-static void msgid2mmctx(struct sgsn_mm_ctx *mm, const struct msgb *msg)
-{
-	mm->gb.bvci = msgb_bvci(msg);
-	mm->gb.nsei = msgb_nsei(msg);
-	/* In case a Iu connection is reconnected we need to update the ue ctx */
-	mm->iu.ue_ctx = msg->dst;
-	if (mm->ran_type == MM_CTX_T_UTRAN_Iu
-	    && mm->iu.ue_ctx) {
-#ifdef BUILD_IU
-		mm->iu.ue_ctx->rab_assign_addr_enc =
-			sgsn->cfg.iu.rab_assign_addr_enc;
-#endif
-	}
-}
-
-/* Store BVCI/NSEI in MM context */
-static void mmctx2msgid(struct msgb *msg, const struct sgsn_mm_ctx *mm)
-{
-	msgb_tlli(msg) = mm->gb.tlli;
-	msgb_bvci(msg) = mm->gb.bvci;
-	msgb_nsei(msg) = mm->gb.nsei;
-	msg->dst = mm->iu.ue_ctx;
-}
-
-static void mm_ctx_cleanup_free(struct sgsn_mm_ctx *ctx, const char *log_text)
-{
-	LOGMMCTXP(LOGL_INFO, ctx, "Cleaning MM context due to %s\n", log_text);
-
-	/* Mark MM state as deregistered */
-	ctx->gmm_state = GMM_DEREGISTERED;
-	mmctx_set_pmm_state(ctx, PMM_DETACHED);
-	mmctx_set_pmm_state(ctx, MM_IDLE);
-
-	sgsn_mm_ctx_cleanup_free(ctx);
-}
-
-/* Chapter 9.4.18 */
-static int _tx_status(struct msgb *msg, uint8_t cause,
-		      struct sgsn_mm_ctx *mmctx, int sm)
-{
-	struct gsm48_hdr *gh;
-
-	/* MMCTX might be NULL! */
-
-	DEBUGP(DMM, "<- GPRS MM STATUS (cause: %s)\n",
-		get_value_string(gsm48_gmm_cause_names, cause));
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
-	if (sm) {
-		gh->proto_discr = GSM48_PDISC_SM_GPRS;
-		gh->msg_type = GSM48_MT_GSM_STATUS;
-	} else {
-		gh->proto_discr = GSM48_PDISC_MM_GPRS;
-		gh->msg_type = GSM48_MT_GMM_STATUS;
-	}
-	gh->data[0] = cause;
-
-	return gsm48_gmm_sendmsg(msg, 0, mmctx, true);
-}
-
-static int gsm48_tx_gmm_status(struct sgsn_mm_ctx *mmctx, uint8_t cause)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 GMM STATUS");
-
-	mmctx2msgid(msg, mmctx);
-	return _tx_status(msg, cause, mmctx, 0);
-}
-
-static int gsm48_tx_sm_status(struct sgsn_mm_ctx *mmctx, uint8_t cause)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SM STATUS");
-
-	mmctx2msgid(msg, mmctx);
-	return _tx_status(msg, cause, mmctx, 1);
-}
-
-static int _tx_detach_req(struct msgb *msg, uint8_t detach_type, uint8_t cause,
-			  struct sgsn_mm_ctx *mmctx)
-{
-	struct gsm48_hdr *gh;
-
-	/* MMCTX might be NULL! */
-
-	DEBUGP(DMM, "<- GPRS MM DETACH REQ (type: %s, cause: %s)\n",
-		get_value_string(gprs_det_t_mt_strs, detach_type),
-		get_value_string(gsm48_gmm_cause_names, cause));
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
-
-	gh->proto_discr = GSM48_PDISC_MM_GPRS;
-	gh->msg_type = GSM48_MT_GMM_DETACH_REQ;
-	gh->data[0] = detach_type & 0x07;
-
-	msgb_tv_put(msg, GSM48_IE_GMM_CAUSE, cause);
-
-	return gsm48_gmm_sendmsg(msg, 0, mmctx, true);
-}
-
-static int gsm48_tx_gmm_detach_req(struct sgsn_mm_ctx *mmctx,
-				   uint8_t detach_type, uint8_t cause)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 DET REQ");
-
-	mmctx2msgid(msg, mmctx);
-	return _tx_detach_req(msg, detach_type, cause, mmctx);
-}
-
-static int gsm48_tx_gmm_detach_req_oldmsg(struct msgb *oldmsg,
-					  uint8_t detach_type, uint8_t cause)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 DET OLD");
-
-	gmm_copy_id(msg, oldmsg);
-	return _tx_detach_req(msg, detach_type, cause, NULL);
-}
-
-static struct gsm48_qos default_qos = {
-	.delay_class = 4,	/* best effort */
-	.reliab_class = GSM48_QOS_RC_LLC_UN_RLC_ACK_DATA_PROT,
-	.peak_tput = GSM48_QOS_PEAK_TPUT_32000bps,
-	.preced_class = GSM48_QOS_PC_NORMAL,
-	.mean_tput = GSM48_QOS_MEAN_TPUT_BEST_EFFORT,
-	.traf_class = GSM48_QOS_TC_INTERACTIVE,
-	.deliv_order = GSM48_QOS_DO_UNORDERED,
-	.deliv_err_sdu = GSM48_QOS_ERRSDU_YES,
-	.max_sdu_size = GSM48_QOS_MAXSDU_1520,
-	.max_bitrate_up = GSM48_QOS_MBRATE_63k,
-	.max_bitrate_down = GSM48_QOS_MBRATE_63k,
-	.resid_ber = GSM48_QOS_RBER_5e_2,
-	.sdu_err_ratio = GSM48_QOS_SERR_1e_2,
-	.handling_prio = 3,
-	.xfer_delay = 0x10,	/* 200ms */
-	.guar_bitrate_up = GSM48_QOS_MBRATE_0k,
-	.guar_bitrate_down = GSM48_QOS_MBRATE_0k,
-	.sig_ind = 0,	/* not optimised for signalling */
-	.max_bitrate_down_ext = 0,	/* use octet 9 */
-	.guar_bitrate_down_ext = 0,	/* use octet 13 */
-};
-
-/* Chapter 9.4.2: Attach accept */
-static int gsm48_tx_gmm_att_ack(struct sgsn_mm_ctx *mm)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ATT ACK");
-	struct gsm48_hdr *gh;
-	struct gsm48_attach_ack *aa;
-	uint8_t *mid;
-#if 0
-	uint8_t *ptsig;
-#endif
-
-	LOGMMCTXP(LOGL_INFO, mm, "<- GPRS ATTACH ACCEPT (new P-TMSI=0x%08x)\n", mm->p_tmsi);
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ATTACH_ACKED]);
-
-	mmctx2msgid(msg, mm);
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	gh->proto_discr = GSM48_PDISC_MM_GPRS;
-	gh->msg_type = GSM48_MT_GMM_ATTACH_ACK;
-
-	aa = (struct gsm48_attach_ack *) msgb_put(msg, sizeof(*aa));
-	aa->force_stby = 0;	/* not indicated */
-	aa->att_result = 1;	/* GPRS only */
-	aa->ra_upd_timer = gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3312);
-	aa->radio_prio = 4;	/* lowest */
-	gsm48_construct_ra(aa->ra_id.digits, &mm->ra);
-
-#if 0
-	/* Optional: P-TMSI signature */
-	msgb_v_put(msg, GSM48_IE_GMM_PTMSI_SIG);
-	ptsig = msgb_put(msg, 3);
-	ptsig[0] = mm->p_tmsi_sig >> 16;
-	ptsig[1] = mm->p_tmsi_sig >> 8;
-	ptsig[2] = mm->p_tmsi_sig & 0xff;
-
-#endif
-	/* Optional: Negotiated Ready timer value
-	 * (fixed 44s, default value, GSM 04.08, table 11.4a) to safely limit
-	 * the inactivity time READY->STANDBY.
-	 */
-	msgb_tv_put(msg, GSM48_IE_GMM_TIMER_READY,
-		    gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3314));
-
-#ifdef PTMSI_ALLOC
-	/* Optional: Allocated P-TMSI */
-	mid = msgb_put(msg, GSM48_MID_TMSI_LEN);
-	gsm48_generate_mid_from_tmsi(mid, mm->p_tmsi);
-	mid[0] = GSM48_IE_GMM_ALLOC_PTMSI;
-#endif
-
-	/* Optional: MS-identity (combined attach) */
-	/* Optional: GMM cause (partial attach result for combined attach) */
-
-	return gsm48_gmm_sendmsg(msg, 0, mm, true);
-}
-
-/* Chapter 9.4.5: Attach reject */
-static int _tx_gmm_att_rej(struct msgb *msg, uint8_t gmm_cause,
-			   const struct sgsn_mm_ctx *mm)
-{
-	struct gsm48_hdr *gh;
-
-	LOGMMCTXP(LOGL_NOTICE, mm, "<- GPRS ATTACH REJECT: %s\n",
-		  get_value_string(gsm48_gmm_cause_names, gmm_cause));
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ATTACH_REJECTED]);
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
-	gh->proto_discr = GSM48_PDISC_MM_GPRS;
-	gh->msg_type = GSM48_MT_GMM_ATTACH_REJ;
-	gh->data[0] = gmm_cause;
-
-	return gsm48_gmm_sendmsg(msg, 0, NULL, false);
-}
-static int gsm48_tx_gmm_att_rej_oldmsg(const struct msgb *old_msg,
-					uint8_t gmm_cause)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ATT REJ OLD");
-	gmm_copy_id(msg, old_msg);
-	return _tx_gmm_att_rej(msg, gmm_cause, NULL);
-}
-static int gsm48_tx_gmm_att_rej(struct sgsn_mm_ctx *mm,
-				uint8_t gmm_cause)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ATT REJ");
-	mmctx2msgid(msg, mm);
-	return _tx_gmm_att_rej(msg, gmm_cause, mm);
-}
-
-/* Chapter 9.4.6.2 Detach accept */
-static int _tx_detach_ack(struct msgb *msg, uint8_t force_stby,
-			  struct sgsn_mm_ctx *mm)
-{
-	struct gsm48_hdr *gh;
-
-	/* MMCTX might be NULL! */
-
-	DEBUGP(DMM, "<- GPRS MM DETACH ACC (force-standby: %d)\n", force_stby);
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_DETACH_ACKED]);
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
-	gh->proto_discr = GSM48_PDISC_MM_GPRS;
-	gh->msg_type = GSM48_MT_GMM_DETACH_ACK;
-	gh->data[0] = force_stby;
-
-	return gsm48_gmm_sendmsg(msg, 0, mm, true);
-}
-
-static int gsm48_tx_gmm_det_ack(struct sgsn_mm_ctx *mm, uint8_t force_stby)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 DET ACK");
-
-	mmctx2msgid(msg, mm);
-	return _tx_detach_ack(msg, force_stby, mm);
-}
-
-static int gsm48_tx_gmm_det_ack_oldmsg(struct msgb *oldmsg, uint8_t force_stby)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 DET ACK OLD");
-
-	gmm_copy_id(msg, oldmsg);
-	return _tx_detach_ack(msg, force_stby, NULL);
-}
-
-/* Transmit Chapter 9.4.12 Identity Request */
-static int gsm48_tx_gmm_id_req(struct sgsn_mm_ctx *mm, uint8_t id_type)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ID REQ");
-	struct gsm48_hdr *gh;
-
-	LOGMMCTXP(LOGL_DEBUG, mm, "<- GPRS IDENTITY REQUEST: mi_type=%s\n",
-		  gsm48_mi_type_name(id_type));
-
-	mmctx2msgid(msg, mm);
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
-	gh->proto_discr = GSM48_PDISC_MM_GPRS;
-	gh->msg_type = GSM48_MT_GMM_ID_REQ;
-	/* 10.5.5.9 ID type 2 + identity type and 10.5.5.7 'force to standby' IE */
-	gh->data[0] = id_type & 0xf;
-
-	return gsm48_gmm_sendmsg(msg, 1, mm, false);
-}
-
-/* determine if the MS/UE supports R99 or later */
-static bool mmctx_is_r99(const struct sgsn_mm_ctx *mm)
-{
-	if (mm->ms_network_capa.len < 1)
-		return false;
-	if (mm->ms_network_capa.buf[0] & 0x01)
-		return true;
-	return false;
-}
-
-/* 3GPP TS 24.008 Section 9.4.9: Authentication and Ciphering Request */
-static int gsm48_tx_gmm_auth_ciph_req(struct sgsn_mm_ctx *mm,
-				      const struct osmo_auth_vector *vec,
-				      uint8_t key_seq, bool force_standby)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 AUTH CIPH REQ");
-	struct gsm48_hdr *gh;
-	struct gsm48_auth_ciph_req *acreq;
-	uint8_t *m_rand, *m_cksn, rbyte;
-
-	LOGMMCTXP(LOGL_INFO, mm, "<- GPRS AUTH AND CIPHERING REQ (rand = %s",
-		  osmo_hexdump(vec->rand, sizeof(vec->rand)));
-	if (mmctx_is_r99(mm) && vec
-	    && (vec->auth_types & OSMO_AUTH_TYPE_UMTS)) {
-		LOGPC(DMM, LOGL_INFO, ", autn = %s)\n",
-		      osmo_hexdump(vec->autn, sizeof(vec->autn)));
-	} else
-		LOGPC(DMM, LOGL_INFO, ")\n");
-
-	mmctx2msgid(msg, mm);
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	gh->proto_discr = GSM48_PDISC_MM_GPRS;
-	gh->msg_type = GSM48_MT_GMM_AUTH_CIPH_REQ;
-
-	acreq = (struct gsm48_auth_ciph_req *) msgb_put(msg, sizeof(*acreq));
-	acreq->ciph_alg = mm->ciph_algo & 0xf;
-	/* § 10.5.5.10: */
-	acreq->imeisv_req = 0x1;
-	/* § 10.5.5.7: */
-	acreq->force_stby = force_standby;
-	/* 3GPP TS 24.008 § 10.5.5.19: */
-	if (RAND_bytes(&rbyte, 1) != 1) {
-		LOGP(DMM, LOGL_NOTICE, "RAND_bytes failed for A&C ref, falling "
-		     "back to rand()\n");
-		acreq->ac_ref_nr = rand();
-	} else
-		acreq->ac_ref_nr = rbyte;
-	mm->ac_ref_nr_used = acreq->ac_ref_nr;
-
-	/* Only if authentication is requested we need to set RAND + CKSN */
-	if (vec) {
-		m_rand = msgb_put(msg, sizeof(vec->rand) + 1);
-		m_rand[0] = GSM48_IE_GMM_AUTH_RAND;
-		memcpy(m_rand + 1, vec->rand, sizeof(vec->rand));
-
-		/* § 10.5.1.2: */
-		m_cksn = msgb_put(msg, 1);
-		m_cksn[0] = (GSM48_IE_GMM_CIPH_CKSN << 4) | (key_seq & 0x07);
-
-		/* A Release99 or higher MS/UE must be able to handle
-		 * the optional AUTN IE.  If a classic GSM SIM is
-		 * inserted, it will simply ignore AUTN and just use
-		 * RAND */
-		if (mmctx_is_r99(mm) &&
-		    (vec->auth_types & OSMO_AUTH_TYPE_UMTS)) {
-			msgb_tlv_put(msg, GSM48_IE_GMM_AUTN,
-				     sizeof(vec->autn), vec->autn);
-		}
-	}
-
-	return gsm48_gmm_sendmsg(msg, 1, mm, false);
-}
-
-/* Section 9.4.11: Authentication and Ciphering Reject */
-static int gsm48_tx_gmm_auth_ciph_rej(struct sgsn_mm_ctx *mm)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 AUTH CIPH REJ");
-	struct gsm48_hdr *gh;
-
-	LOGMMCTXP(LOGL_NOTICE, mm, "<- GPRS AUTH AND CIPH REJECT\n");
-
-	mmctx2msgid(msg, mm);
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	gh->proto_discr = GSM48_PDISC_MM_GPRS;
-	gh->msg_type = GSM48_MT_GMM_AUTH_CIPH_REJ;
-
-	return gsm48_gmm_sendmsg(msg, 0, mm, false);
-}
-
-/* check if the received authentication response matches */
-static bool check_auth_resp(struct sgsn_mm_ctx *ctx,
-			    bool is_utran,
-			    const struct osmo_auth_vector *vec,
-			    const uint8_t *res, uint8_t res_len)
-{
-	const uint8_t *expect_res;
-	uint8_t expect_res_len;
-	enum osmo_sub_auth_type expect_type;
-	const char *expect_str;
-
-	if (!vec)
-		return true; /* really!? */
-
-	/* On UTRAN (3G) we always expect UMTS AKA. On GERAN (2G) we sent AUTN
-	 * and expect UMTS AKA if there is R99 capability and our vector
-	 * supports UMTS AKA, otherwise we expect GSM AKA. */
-	if (is_utran
-	    || (mmctx_is_r99(ctx) && (vec->auth_types & OSMO_AUTH_TYPE_UMTS))) {
-		expect_type = OSMO_AUTH_TYPE_UMTS;
-		expect_str = "UMTS RES";
-		expect_res = vec->res;
-		expect_res_len = vec->res_len;
-	} else {
-		expect_type = OSMO_AUTH_TYPE_GSM;
-		expect_str = "GSM SRES";
-		expect_res = vec->sres;
-		expect_res_len = sizeof(vec->sres);
-	}
-	
-	if (!(vec->auth_types & expect_type)) {
-		LOGMMCTXP(LOGL_ERROR, ctx, "Auth error: auth vector does"
-			  " not provide the expected auth type:"
-			  " expected %s = 0x%x, auth_types are 0x%x\n",
-			  expect_str, expect_type, vec->auth_types);
-		return false;
-	}
-
-	if (!res)
-		goto auth_mismatch;
-
-	if (res_len != expect_res_len)
-		goto auth_mismatch;
-
-	if (memcmp(res, expect_res, res_len) != 0)
-		goto auth_mismatch;
-
-	/* Authorized! */
-	return true;
-
-auth_mismatch:
-	LOGMMCTXP(LOGL_ERROR, ctx, "Auth mismatch: expected %s = %s\n",
-		  expect_str, osmo_hexdump_nospc(expect_res, expect_res_len));
-	return false;
-}
-
-/* Section 9.4.10: Authentication and Ciphering Response */
-static int gsm48_rx_gmm_auth_ciph_resp(struct sgsn_mm_ctx *ctx,
-					struct msgb *msg)
-{
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
-	struct gsm48_auth_ciph_resp *acr = (struct gsm48_auth_ciph_resp *)gh->data;
-	struct tlv_parsed tp;
-	struct gsm_auth_tuple *at;
-	const char *res_name = "(no response)";
-	uint8_t res[16];
-	uint8_t res_len;
-	int rc;
-
-	LOGMMCTXP(LOGL_INFO, ctx, "-> GPRS AUTH AND CIPH RESPONSE\n");
-
-	if (ctx->auth_triplet.key_seq == GSM_KEY_SEQ_INVAL) {
-		LOGMMCTXP(LOGL_NOTICE, ctx,
-			  "Unexpected Auth & Ciph Response (ignored)\n");
-		return 0;
-	}
-
-	if (acr->ac_ref_nr != ctx->ac_ref_nr_used) {
-		LOGMMCTXP(LOGL_NOTICE, ctx, "Reference mismatch for Auth & Ciph"
-			  " Response: %u received, %u expected\n",
-			  acr->ac_ref_nr, ctx->ac_ref_nr_used);
-		return 0;
-	}
-
-	/* Stop T3360 */
-	mmctx_timer_stop(ctx, 3360);
-
-	tlv_parse(&tp, &gsm48_gmm_att_tlvdef, acr->data,
-			(msg->data + msg->len) - acr->data, 0, 0);
-
-	if (!TLVP_PRESENT(&tp, GSM48_IE_GMM_AUTH_SRES) ||
-	    !TLVP_PRESENT(&tp, GSM48_IE_GMM_IMEISV) ||
-	    TLVP_LEN(&tp,GSM48_IE_GMM_AUTH_SRES) != 4) {
-		/* TODO: missing mandatory IE, return STATUS or REJ? */
-		LOGMMCTXP(LOGL_ERROR, ctx, "Missing mandantory IE\n");
-		return -EINVAL;
-	}
-
-	/* Start with the good old 4-byte SRES */
-	memcpy(res, TLVP_VAL(&tp, GSM48_IE_GMM_AUTH_SRES), 4);
-	res_len = 4;
-	res_name = "GSM SRES";
-
-	/* Append extended RES as part of UMTS AKA, if any */
-	if (TLVP_PRESENT(&tp, GSM48_IE_GMM_AUTH_RES_EXT)) {
-		unsigned int l = TLVP_LEN(&tp, GSM48_IE_GMM_AUTH_RES_EXT);
-		if (l > sizeof(res)-4)
-			l = sizeof(res)-4;
-		memcpy(res+4, TLVP_VAL(&tp, GSM48_IE_GMM_AUTH_RES_EXT), l);
-		res_len += l;
-		res_name = "UMTS RES";
-	}
-
-	at = &ctx->auth_triplet;
-
-	LOGMMCTXP(LOGL_DEBUG, ctx, "checking auth: received %s = %s\n",
-		  res_name, osmo_hexdump(res, res_len));
-	rc = check_auth_resp(ctx, false, &at->vec, res, res_len);
-	if (!rc) {
-		rc = gsm48_tx_gmm_auth_ciph_rej(ctx);
-		mm_ctx_cleanup_free(ctx, "GPRS AUTH AND CIPH REJECT");
-		return rc;
-	}
-
-	ctx->is_authenticated = 1;
-
-	if (ctx->ran_type == MM_CTX_T_UTRAN_Iu)
-		ctx->iu.new_key = 1;
-
-	/* FIXME: enable LLC cipheirng */
-
-	/* Check if we can let the mobile station enter */
-	return gsm48_gmm_authorize(ctx);
-}
-
-/* Section 9.4.10: Authentication and Ciphering Failure */
-static int gsm48_rx_gmm_auth_ciph_fail(struct sgsn_mm_ctx *ctx,
-					struct msgb *msg)
-{
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
-	struct tlv_parsed tp;
-	const uint8_t gmm_cause = gh->data[0];
-	const uint8_t *auts;
-	int rc;
-
-	LOGMMCTXP(LOGL_INFO, ctx, "-> GPRS AUTH AND CIPH FAILURE (cause = %s)\n",
-		  get_value_string(gsm48_gmm_cause_names, gmm_cause));
-
-	tlv_parse(&tp, &gsm48_gmm_att_tlvdef, gh->data+1, msg->len - 1, 0, 0);
-
-	/* Only if GMM cause is present and the AUTS is provided, we can
-	 * start re-sync procedure */
-	if (gmm_cause == GMM_CAUSE_SYNC_FAIL &&
-	    TLVP_PRESENT(&tp, GSM48_IE_GMM_AUTH_FAIL_PAR)) {
-		if (TLVP_LEN(&tp, GSM48_IE_GMM_AUTH_FAIL_PAR) != 14) {
-			LOGMMCTXP(LOGL_ERROR, ctx, "AUTS IE has wrong size:"
-				  " expected %d, got %u\n", 14,
-				  TLVP_LEN(&tp, GSM48_IE_GMM_AUTH_FAIL_PAR));
-			return -EINVAL;
-		}
-		auts = TLVP_VAL(&tp, GSM48_IE_GMM_AUTH_FAIL_PAR);
-
-		LOGMMCTXP(LOGL_INFO, ctx,
-			  "R99 AUTHENTICATION SYNCH (AUTS = %s)\n",
-			  osmo_hexdump_nospc(auts, 14));
-
-		/* make sure we'll refresh the auth_triplet in
-		 * sgsn_auth_update() */
-		ctx->auth_triplet.key_seq = GSM_KEY_SEQ_INVAL;
-
-		/* make sure we'll retry authentication after the resync */
-		ctx->auth_state = SGSN_AUTH_UMTS_RESYNC;
-
-		/* Send AUTS to HLR and wait for new Auth Info Result */
-		rc = gprs_subscr_request_auth_info(ctx, auts,
-						   ctx->auth_triplet.vec.rand);
-		if (!rc)
-			return 0;
-		/* on error, fall through to send a reject */
-		LOGMMCTXP(LOGL_ERROR, ctx,
-			  "Sending AUTS to HLR failed (rc = %d)\n", rc);
-	}
-
-	LOGMMCTXP(LOGL_NOTICE, ctx, "Authentication failed\n");
-	rc = gsm48_tx_gmm_auth_ciph_rej(ctx);
-	mm_ctx_cleanup_free(ctx, "GPRS AUTH FAILURE");
-	return rc;
-}
-
-static void extract_subscr_msisdn(struct sgsn_mm_ctx *ctx)
-{
-	struct gsm_mncc_number called;
-	uint8_t msisdn[sizeof(ctx->subscr->sgsn_data->msisdn) + 1];
-
-	/* Convert MSISDN from encoded to string.. */
-	if (!ctx->subscr)
-		return;
-
-	if (ctx->subscr->sgsn_data->msisdn_len < 1)
-		return;
-
-	/* prepare the data for the decoder */
-	memset(&called, 0, sizeof(called));
-	msisdn[0] = ctx->subscr->sgsn_data->msisdn_len;
-	memcpy(&msisdn[1], ctx->subscr->sgsn_data->msisdn,
-		ctx->subscr->sgsn_data->msisdn_len);
-
-	/* decode the string now */
-	gsm48_decode_called(&called, msisdn);
-
-	/* Prepend a '+' for international numbers */
-	if (called.plan == 1 && called.type == 1) {
-		ctx->msisdn[0] = '+';
-		osmo_strlcpy(&ctx->msisdn[1], called.number,
-			     sizeof(ctx->msisdn));
-	} else {
-		osmo_strlcpy(ctx->msisdn, called.number, sizeof(ctx->msisdn));
-	}
-}
-
-static void extract_subscr_hlr(struct sgsn_mm_ctx *ctx)
-{
-	struct gsm_mncc_number called;
-	uint8_t hlr_number[sizeof(ctx->subscr->sgsn_data->hlr) + 1];
-
-	if (!ctx->subscr)
-		return;
-
-	if (ctx->subscr->sgsn_data->hlr_len < 1)
-		return;
-
-	/* prepare the data for the decoder */
-	memset(&called, 0, sizeof(called));
-	hlr_number[0] = ctx->subscr->sgsn_data->hlr_len;
-	memcpy(&hlr_number[1], ctx->subscr->sgsn_data->hlr,
-		ctx->subscr->sgsn_data->hlr_len);
-
-	/* decode the string now */
-	gsm48_decode_called(&called, hlr_number);
-
-	if (called.plan != 1) {
-		LOGMMCTXP(LOGL_ERROR, ctx,
-				"Numbering plan(%d) not allowed\n",
-				called.plan);
-		return;
-	}
-
-	if (called.type != 1) {
-		LOGMMCTXP(LOGL_ERROR, ctx,
-				"Numbering type(%d) not allowed\n",
-				called.type);
-		return;
-	}
-
-	osmo_strlcpy(ctx->hlr, called.number, sizeof(ctx->hlr));
-}
-
-#ifdef BUILD_IU
-/* Chapter 9.4.21: Service accept */
-static int gsm48_tx_gmm_service_ack(struct sgsn_mm_ctx *mm)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SERVICE ACK");
-	struct gsm48_hdr *gh;
-
-	LOGMMCTXP(LOGL_INFO, mm, "<- GPRS SERVICE ACCEPT (P-TMSI=0x%08x)\n", mm->p_tmsi);
-
-	mmctx2msgid(msg, mm);
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	gh->proto_discr = GSM48_PDISC_MM_GPRS;
-	gh->msg_type = GSM48_MT_GMM_SERVICE_ACK;
-
-	/* Optional: PDP context status */
-	/* Optional: MBMS context status */
-
-	return gsm48_gmm_sendmsg(msg, 0, mm, false);
-}
-#endif
-
-/* Chapter 9.4.22: Service reject */
-static int _tx_gmm_service_rej(struct msgb *msg, uint8_t gmm_cause,
-			   const struct sgsn_mm_ctx *mm)
-{
-	struct gsm48_hdr *gh;
-
-	LOGMMCTXP(LOGL_NOTICE, mm, "<- GPRS SERVICE REJECT: %s\n",
-		  get_value_string(gsm48_gmm_cause_names, gmm_cause));
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
-	gh->proto_discr = GSM48_PDISC_MM_GPRS;
-	gh->msg_type = GSM48_MT_GMM_SERVICE_REJ;
-	gh->data[0] = gmm_cause;
-
-	return gsm48_gmm_sendmsg(msg, 0, NULL, true);
-}
-static int gsm48_tx_gmm_service_rej_oldmsg(const struct msgb *old_msg,
-					uint8_t gmm_cause)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SERVICE REJ OLD");
-	gmm_copy_id(msg, old_msg);
-	return _tx_gmm_service_rej(msg, gmm_cause, NULL);
-}
-#if 0
--- currently unused --
-static int gsm48_tx_gmm_service_rej(struct sgsn_mm_ctx *mm,
-				uint8_t gmm_cause)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SERVICE REJ");
-	mmctx2msgid(msg, mm);
-	return _tx_gmm_service_rej(msg, gmm_cause, mm);
-}
-#endif
-
-static int gsm48_tx_gmm_ra_upd_ack(struct sgsn_mm_ctx *mm);
-
-#ifdef BUILD_IU
-/* Send RAB activation requests for all PDP contexts */
-void activate_pdp_rabs(struct sgsn_mm_ctx *ctx)
-{
-	struct sgsn_pdp_ctx *pdp;
-	if (ctx->ran_type != MM_CTX_T_UTRAN_Iu)
-		return;
-	llist_for_each_entry(pdp, &ctx->pdp_list, list) {
-		iu_rab_act_ps(pdp->nsapi, pdp);
-	}
-}
-#endif
-
-/* Check if we can already authorize a subscriber */
-static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx)
-{
-#ifdef BUILD_IU
-	int rc;
-#endif
-#ifndef PTMSI_ALLOC
-	struct sgsn_signal_data sig_data;
-#endif
-
-	/* Request IMSI and IMEI from the MS if they are unknown */
-	if (!strlen(ctx->imei)) {
-		ctx->t3370_id_type = GSM_MI_TYPE_IMEI;
-		mmctx_timer_start(ctx, 3370, sgsn->cfg.timers.T3370);
-		return gsm48_tx_gmm_id_req(ctx, GSM_MI_TYPE_IMEI);
-	}
-	if (!strlen(ctx->imsi)) {
-		ctx->t3370_id_type = GSM_MI_TYPE_IMSI;
-		mmctx_timer_start(ctx, 3370, sgsn->cfg.timers.T3370);
-		return gsm48_tx_gmm_id_req(ctx, GSM_MI_TYPE_IMSI);
-	}
-
-	/* All information required for authentication is available */
-	ctx->t3370_id_type = GSM_MI_TYPE_NONE;
-
-	if (ctx->auth_state == SGSN_AUTH_UNKNOWN) {
-		/* Request authorization, this leads to a call to
-		 * sgsn_auth_update which in turn calls
-		 * gsm0408_gprs_access_granted or gsm0408_gprs_access_denied */
-
-		sgsn_auth_request(ctx);
-		/* Note that gsm48_gmm_authorize can be called recursively via
-		 * sgsn_auth_request iff ctx->auth_info changes to AUTH_ACCEPTED
-		 */
-		return 0;
-	}
-
-	if (ctx->auth_state == SGSN_AUTH_AUTHENTICATE && !ctx->is_authenticated) {
-		struct gsm_auth_tuple *at = &ctx->auth_triplet;
-
-		mmctx_timer_start(ctx, 3360, sgsn->cfg.timers.T3360);
-		return gsm48_tx_gmm_auth_ciph_req(ctx, &at->vec, at->key_seq,
-						  false);
-	}
-
-	if (ctx->auth_state == SGSN_AUTH_AUTHENTICATE && ctx->is_authenticated &&
-	    ctx->auth_triplet.key_seq != GSM_KEY_SEQ_INVAL) {
-		/* Check again for authorization */
-		sgsn_auth_request(ctx);
-		return 0;
-	}
-
-	if (ctx->auth_state != SGSN_AUTH_ACCEPTED) {
-		LOGMMCTXP(LOGL_NOTICE, ctx,
-			  "authorization is denied, aborting procedure\n");
-		return -EACCES;
-	}
-
-	/* The MS is authorized */
-#ifdef BUILD_IU
-	if (ctx->ran_type == MM_CTX_T_UTRAN_Iu && !ctx->iu.ue_ctx->integrity_active) {
-		rc = ranap_iu_tx_sec_mode_cmd(ctx->iu.ue_ctx, &ctx->auth_triplet.vec, 0, ctx->iu.new_key);
-		ctx->iu.new_key = 0;
-		return rc;
-	}
-#endif
-
-	switch (ctx->pending_req) {
-	case 0:
-		LOGMMCTXP(LOGL_INFO, ctx,
-			  "no pending request, authorization completed\n");
-		break;
-	case GSM48_MT_GMM_ATTACH_REQ:
-		ctx->pending_req = 0;
-
-		extract_subscr_msisdn(ctx);
-		extract_subscr_hlr(ctx);
-#ifdef PTMSI_ALLOC
-		/* Start T3350 and re-transmit up to 5 times until ATTACH COMPLETE */
-		mmctx_timer_start(ctx, 3350, sgsn->cfg.timers.T3350);
-		ctx->t3350_mode = GMM_T3350_MODE_ATT;
-#else
-		memset(&sig_data, 0, sizeof(sig_data));
-		sig_data.mm = mmctx;
-		osmo_signal_dispatch(SS_SGSN, S_SGSN_ATTACH, &sig_data);
-		ctx->gmm_state = GMM_REGISTERED_NORMAL;
-#endif
-
-		return gsm48_tx_gmm_att_ack(ctx);
-#ifdef BUILD_IU
-	case GSM48_MT_GMM_SERVICE_REQ:
-		ctx->pending_req = 0;
-		mmctx_set_pmm_state(ctx, PMM_CONNECTED);
-		rc = gsm48_tx_gmm_service_ack(ctx);
-
-		if (ctx->iu.service.type != GPRS_SERVICE_T_SIGNALLING)
-			activate_pdp_rabs(ctx);
-
-		return rc;
-#endif
-	case GSM48_MT_GMM_RA_UPD_REQ:
-		ctx->pending_req = 0;
-		/* Send RA UPDATE ACCEPT */
-		return gsm48_tx_gmm_ra_upd_ack(ctx);
-
-	default:
-		LOGMMCTXP(LOGL_ERROR, ctx,
-			  "only Attach Request is supported yet, "
-			  "got request type %u\n", ctx->pending_req);
-		break;
-	}
-
-	return 0;
-}
-
-void gsm0408_gprs_authenticate(struct sgsn_mm_ctx *ctx)
-{
-	ctx->is_authenticated = 0;
-
-	gsm48_gmm_authorize(ctx);
-}
-
-void gsm0408_gprs_access_granted(struct sgsn_mm_ctx *ctx)
-{
-	switch (ctx->gmm_state) {
-	case GMM_COMMON_PROC_INIT:
-		LOGMMCTXP(LOGL_NOTICE, ctx,
-		     "Authorized, continuing procedure, IMSI=%s\n",
-		     ctx->imsi);
-		/* Continue with the authorization */
-		gsm48_gmm_authorize(ctx);
-		break;
-	default:
-		LOGMMCTXP(LOGL_INFO, ctx,
-		     "Authorized, ignored, IMSI=%s\n",
-		     ctx->imsi);
-	}
-}
-
-void gsm0408_gprs_access_denied(struct sgsn_mm_ctx *ctx, int gmm_cause)
-{
-	if (gmm_cause == SGSN_ERROR_CAUSE_NONE)
-		gmm_cause = GMM_CAUSE_GPRS_NOTALLOWED;
-
-	switch (ctx->gmm_state) {
-	case GMM_COMMON_PROC_INIT:
-		LOGMMCTXP(LOGL_NOTICE, ctx,
-			  "Not authorized, rejecting ATTACH REQUEST "
-			  "with cause '%s' (%d)\n",
-			  get_value_string(gsm48_gmm_cause_names, gmm_cause),
-			  gmm_cause);
-		gsm48_tx_gmm_att_rej(ctx, gmm_cause);
-		mm_ctx_cleanup_free(ctx, "GPRS ATTACH REJECT");
-		break;
-	case GMM_REGISTERED_NORMAL:
-	case GMM_REGISTERED_SUSPENDED:
-		LOGMMCTXP(LOGL_NOTICE, ctx,
-			  "Authorization lost, detaching "
-			  "with cause '%s' (%d)\n",
-			  get_value_string(gsm48_gmm_cause_names, gmm_cause),
-			  gmm_cause);
-		gsm48_tx_gmm_detach_req(
-			ctx, GPRS_DET_T_MT_REATT_NOTREQ, gmm_cause);
-
-		mm_ctx_cleanup_free(ctx, "auth lost");
-		break;
-	default:
-		LOGMMCTXP(LOGL_INFO, ctx,
-			  "Authorization lost, cause is '%s' (%d)\n",
-			  get_value_string(gsm48_gmm_cause_names, gmm_cause),
-			  gmm_cause);
-		mm_ctx_cleanup_free(ctx, "auth lost");
-	}
-}
-
-void gsm0408_gprs_access_cancelled(struct sgsn_mm_ctx *ctx, int gmm_cause)
-{
-	if (gmm_cause != SGSN_ERROR_CAUSE_NONE) {
-		LOGMMCTXP(LOGL_INFO, ctx,
-			  "Cancelled with cause '%s' (%d), deleting context\n",
-			  get_value_string(gsm48_gmm_cause_names, gmm_cause),
-			  gmm_cause);
-		gsm0408_gprs_access_denied(ctx, gmm_cause);
-		return;
-	}
-
-	LOGMMCTXP(LOGL_INFO, ctx, "Cancelled, deleting context silently\n");
-	mm_ctx_cleanup_free(ctx, "access cancelled");
-}
-
-/* Parse Chapter 9.4.13 Identity Response */
-static int gsm48_rx_gmm_id_resp(struct sgsn_mm_ctx *ctx, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
-	uint8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
-	char mi_string[GSM48_MI_SIZE];
-
-	gsm48_mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
-	if (!ctx) {
-		DEBUGP(DMM, "from unknown TLLI 0x%08x?!? This should not happen\n", msgb_tlli(msg));
-		return -EINVAL;
-	}
-
-	LOGMMCTXP(LOGL_DEBUG, ctx, "-> GMM IDENTITY RESPONSE: MI(%s)=%s\n",
-		gsm48_mi_type_name(mi_type), mi_string);
-
-	if (ctx->t3370_id_type == GSM_MI_TYPE_NONE) {
-		LOGMMCTXP(LOGL_NOTICE, ctx,
-			  "Got unexpected IDENTITY RESPONSE: MI(%s)=%s, "
-			  "ignoring message\n",
-			  gsm48_mi_type_name(mi_type), mi_string);
-		return -EINVAL;
-	}
-
-	if (mi_type == ctx->t3370_id_type)
-		mmctx_timer_stop(ctx, 3370);
-
-	switch (mi_type) {
-	case GSM_MI_TYPE_IMSI:
-		/* we already have a mm context with current TLLI, but no
-		 * P-TMSI / IMSI yet.  What we now need to do is to fill
-		 * this initial context with data from the HLR */
-		if (strlen(ctx->imsi) == 0) {
-			/* Check if we already have a MM context for this IMSI */
-			struct sgsn_mm_ctx *ictx;
-			ictx = sgsn_mm_ctx_by_imsi(mi_string);
-			if (ictx) {
-				/* Handle it like in gsm48_rx_gmm_det_req,
-				 * except that no messages are sent to the BSS */
-
-				LOGMMCTXP(LOGL_NOTICE, ctx, "Deleting old MM Context for same IMSI "
-				       "p_tmsi_old=0x%08x\n",
-					ictx->p_tmsi);
-
-				mm_ctx_cleanup_free(ictx, "GPRS IMSI re-use");
-			}
-		}
-		osmo_strlcpy(ctx->imsi, mi_string, sizeof(ctx->imsi));
-		break;
-	case GSM_MI_TYPE_IMEI:
-		osmo_strlcpy(ctx->imei, mi_string, sizeof(ctx->imei));
-		break;
-	case GSM_MI_TYPE_IMEISV:
-		break;
-	}
-
-	/* Check if we can let the mobile station enter */
-	return gsm48_gmm_authorize(ctx);
-}
-
-/* Section 9.4.1 Attach request */
-static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
-				struct gprs_llc_llme *llme)
-{
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
-	uint8_t *cur = gh->data, *msnc, *mi, *ms_ra_acc_cap;
-	uint8_t msnc_len, att_type, mi_len, mi_type, ms_ra_acc_cap_len;
-	uint16_t drx_par;
-	uint32_t tmsi;
-	char mi_string[GSM48_MI_SIZE];
-	struct gprs_ra_id ra_id;
-	uint16_t cid = 0;
-	enum gsm48_gmm_cause reject_cause;
-	int rc;
-
-	LOGMMCTXP(LOGL_INFO, ctx, "-> GMM ATTACH REQUEST ");
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ATTACH_REQUEST]);
-
-	/* As per TS 04.08 Chapter 4.7.1.4, the attach request arrives either
-	 * with a foreign TLLI (P-TMSI that was allocated to the MS before),
-	 * or with random TLLI. */
-
-	/* In Iu mode, msg->dst contains the ranap_ue_conn_ctx pointer, in Gb mode
-	 * dst is empty. */
-	/* FIXME: have a more explicit indicator for Iu messages */
-	if (!msg->dst) {
-		/* Gb mode */
-		cid = bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
-	} else {
-#ifdef BUILD_IU
-		ra_id = ((struct ranap_ue_conn_ctx*)msg->dst)->ra_id;
-#else
-		LOGMMCTXP(LOGL_ERROR, ctx, "Cannot handle Iu Attach Request, built without Iu support\n");
-		return -ENOTSUP;
-#endif
-	}
-
-	/* MS network capability 10.5.5.12 */
-	msnc_len = *cur++;
-	msnc = cur;
-	if (msnc_len > sizeof(ctx->ms_network_capa.buf))
-		goto err_inval;
-	cur += msnc_len;
-
-	/* TODO: In iu mode - handle follow-on request */
-
-	/* aTTACH Type 10.5.5.2 */
-	att_type = *cur++ & 0x07;
-
-	/* DRX parameter 10.5.5.6 */
-	drx_par = *cur++ << 8;
-	drx_par |= *cur++;
-
-	/* Mobile Identity (P-TMSI or IMSI) 10.5.1.4 */
-	mi_len = *cur++;
-	mi = cur;
-	if (mi_len > 8)
-		goto err_inval;
-	mi_type = *mi & GSM_MI_TYPE_MASK;
-	cur += mi_len;
-
-	gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
-
-	DEBUGPC(DMM, "MI(%s) type=\"%s\" ", mi_string,
-		get_value_string(gprs_att_t_strs, att_type));
-
-	/* Old routing area identification 10.5.5.15. Skip it */
-	cur += 6;
-
-	/* MS Radio Access Capability 10.5.5.12a */
-	ms_ra_acc_cap_len = *cur++;
-	ms_ra_acc_cap = cur;
-	if (ms_ra_acc_cap_len > sizeof(ctx->ms_radio_access_capa.buf))
-		goto err_inval;
-	cur += ms_ra_acc_cap_len;
-
-	LOGPC(DMM, LOGL_INFO, "\n");
-
-	/* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status */
-
-	switch (mi_type) {
-	case GSM_MI_TYPE_IMSI:
-		/* Try to find MM context based on IMSI */
-		if (!ctx)
-			ctx = sgsn_mm_ctx_by_imsi(mi_string);
-		if (!ctx) {
-#if 0
-			return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_IMSI_UNKNOWN);
-#else
-			if (msg->dst)
-				ctx = sgsn_mm_ctx_alloc_iu(msg->dst);
-			else
-				ctx = sgsn_mm_ctx_alloc_gb(0, &ra_id);
-			if (!ctx) {
-				reject_cause = GMM_CAUSE_NET_FAIL;
-				goto rejected;
-			}
-			osmo_strlcpy(ctx->imsi, mi_string, sizeof(ctx->imsi));
-#endif
-		}
-		if (ctx->ran_type == MM_CTX_T_GERAN_Gb) {
-			ctx->gb.tlli = msgb_tlli(msg);
-			ctx->gb.llme = llme;
-		}
-		msgid2mmctx(ctx, msg);
-		break;
-	case GSM_MI_TYPE_TMSI:
-		memcpy(&tmsi, mi+1, 4);
-		tmsi = ntohl(tmsi);
-		/* Try to find MM context based on P-TMSI */
-		if (!ctx)
-			ctx = sgsn_mm_ctx_by_ptmsi(tmsi);
-		if (!ctx) {
-			/* Allocate a context as most of our code expects one.
-			 * Context will not have an IMSI ultil ID RESP is received */
-			if (msg->dst)
-				ctx = sgsn_mm_ctx_alloc_iu(msg->dst);
-			else
-				ctx = sgsn_mm_ctx_alloc_gb(msgb_tlli(msg), &ra_id);
-			ctx->p_tmsi = tmsi;
-		}
-		if (ctx->ran_type == MM_CTX_T_GERAN_Gb) {
-			ctx->gb.tlli = msgb_tlli(msg);
-			ctx->gb.llme = llme;
-		}
-		msgid2mmctx(ctx, msg);
-		break;
-	default:
-		LOGMMCTXP(LOGL_NOTICE, ctx, "Rejecting ATTACH REQUEST with "
-			"MI type %s\n", gsm48_mi_type_name(mi_type));
-		reject_cause = GMM_CAUSE_MS_ID_NOT_DERIVED;
-		goto rejected;
-	}
-	/* Update MM Context with currient RA and Cell ID */
-	ctx->ra = ra_id;
-	if (ctx->ran_type == MM_CTX_T_GERAN_Gb)
-		ctx->gb.cell_id = cid;
-
-	/* Update MM Context with other data */
-	ctx->drx_parms = drx_par;
-	ctx->ms_radio_access_capa.len = ms_ra_acc_cap_len;
-	memcpy(ctx->ms_radio_access_capa.buf, ms_ra_acc_cap,
-		ctx->ms_radio_access_capa.len);
-	ctx->ms_network_capa.len = msnc_len;
-	memcpy(ctx->ms_network_capa.buf, msnc, msnc_len);
-	if (!gprs_ms_net_cap_gea_supported(ctx->ms_network_capa.buf, msnc_len,
-					   ctx->ciph_algo)) {
-		reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
-		LOGMMCTXP(LOGL_NOTICE, ctx, "Rejecting ATTACH REQUEST with MI "
-			  "type %s because MS do not support required %s "
-			  "encryption\n", gsm48_mi_type_name(mi_type),
-			  get_value_string(gprs_cipher_names,ctx->ciph_algo));
-		goto rejected;
-	}
-#ifdef PTMSI_ALLOC
-	/* Allocate a new P-TMSI (+ P-TMSI signature) and update TLLI */
-	/* Don't change the P-TMSI if a P-TMSI re-assignment is under way */
-	if (ctx->gmm_state != GMM_COMMON_PROC_INIT) {
-		ctx->p_tmsi_old = ctx->p_tmsi;
-		ctx->p_tmsi = sgsn_alloc_ptmsi();
-	}
-	ctx->gmm_state = GMM_COMMON_PROC_INIT;
-#endif
-
-	if (ctx->ran_type == MM_CTX_T_GERAN_Gb) {
-		/* Even if there is no P-TMSI allocated, the MS will
-		 * switch from foreign TLLI to local TLLI */
-		ctx->gb.tlli_new = gprs_tmsi2tlli(ctx->p_tmsi, TLLI_LOCAL);
-
-		/* Inform LLC layer about new TLLI but keep old active */
-		if (ctx->is_authenticated)
-			gprs_llme_copy_key(ctx, ctx->gb.llme);
-
-		gprs_llgmm_assign(ctx->gb.llme, ctx->gb.tlli, ctx->gb.tlli_new);
-	}
-
-	ctx->pending_req = GSM48_MT_GMM_ATTACH_REQ;
-	return gsm48_gmm_authorize(ctx);
-
-err_inval:
-	LOGPC(DMM, LOGL_INFO, "\n");
-	reject_cause = GMM_CAUSE_SEM_INCORR_MSG;
-
-rejected:
-	/* Send ATTACH REJECT */
-	LOGMMCTXP(LOGL_NOTICE, ctx,
-		  "Rejecting Attach Request with cause '%s' (%d)\n",
-		  get_value_string(gsm48_gmm_cause_names, reject_cause), reject_cause);
-	rc = gsm48_tx_gmm_att_rej_oldmsg(msg, reject_cause);
-	if (ctx)
-		mm_ctx_cleanup_free(ctx, "GPRS ATTACH REJ");
-	else
-		gprs_llgmm_unassign(llme);
-
-	return rc;
-
-}
-
-/* Section 4.7.4.1 / 9.4.5.2 MO Detach request */
-static int gsm48_rx_gmm_det_req(struct sgsn_mm_ctx *ctx, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
-	uint8_t detach_type, power_off;
-	int rc = 0;
-
-	detach_type = gh->data[0] & 0x7;
-	power_off = gh->data[0] & 0x8;
-
-	/* FIXME: In 24.008 there is an optional P-TMSI and P-TMSI signature IE */
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_DETACH_REQUEST]);
-	LOGMMCTXP(LOGL_INFO, ctx, "-> GMM DETACH REQUEST TLLI=0x%08x type=%s %s\n",
-		msgb_tlli(msg), get_value_string(gprs_det_t_mo_strs, detach_type),
-		power_off ? "Power-off" : "");
-
-	/* Only send the Detach Accept (MO) if power off isn't indicated,
-	 * see 04.08, 4.7.4.1.2/3 for details */
-	if (!power_off) {
-		/* force_stby = 0 */
-		if (ctx)
-			rc = gsm48_tx_gmm_det_ack(ctx, 0);
-		else
-			rc = gsm48_tx_gmm_det_ack_oldmsg(msg, 0);
-	}
-
-	if (ctx) {
-		struct sgsn_signal_data sig_data;
-		memset(&sig_data, 0, sizeof(sig_data));
-		sig_data.mm = ctx;
-		osmo_signal_dispatch(SS_SGSN, S_SGSN_DETACH, &sig_data);
-		mm_ctx_cleanup_free(ctx, "GPRS DETACH REQUEST");
-	}
-
-	return rc;
-}
-
-/* Chapter 9.4.15: Routing area update accept */
-static int gsm48_tx_gmm_ra_upd_ack(struct sgsn_mm_ctx *mm)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 UPD ACK");
-	struct gsm48_hdr *gh;
-	struct gsm48_ra_upd_ack *rua;
-	uint8_t *mid;
-
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ROUTING_AREA_ACKED]);
-	LOGMMCTXP(LOGL_INFO, mm, "<- ROUTING AREA UPDATE ACCEPT\n");
-
-	mmctx2msgid(msg, mm);
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	gh->proto_discr = GSM48_PDISC_MM_GPRS;
-	gh->msg_type = GSM48_MT_GMM_RA_UPD_ACK;
-
-	rua = (struct gsm48_ra_upd_ack *) msgb_put(msg, sizeof(*rua));
-	rua->force_stby = 0;	/* not indicated */
-	rua->upd_result = 0;	/* RA updated */
-	rua->ra_upd_timer = gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3312);
-
-	gsm48_construct_ra(rua->ra_id.digits, &mm->ra);
-
-#if 0
-	/* Optional: P-TMSI signature */
-	msgb_v_put(msg, GSM48_IE_GMM_PTMSI_SIG);
-	ptsig = msgb_put(msg, 3);
-	ptsig[0] = mm->p_tmsi_sig >> 16;
-	ptsig[1] = mm->p_tmsi_sig >> 8;
-	ptsig[2] = mm->p_tmsi_sig & 0xff;
-#endif
-
-#ifdef PTMSI_ALLOC
-	/* Optional: Allocated P-TMSI */
-	mid = msgb_put(msg, GSM48_MID_TMSI_LEN);
-	gsm48_generate_mid_from_tmsi(mid, mm->p_tmsi);
-	mid[0] = GSM48_IE_GMM_ALLOC_PTMSI;
-#endif
-
-	/* Optional: Negotiated READY timer value */
-	msgb_tv_put(msg, GSM48_IE_GMM_TIMER_READY,
-		    gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3314));
-
-	/* Option: MS ID, ... */
-	return gsm48_gmm_sendmsg(msg, 0, mm, true);
-}
-
-/* Chapter 9.4.17: Routing area update reject */
-static int gsm48_tx_gmm_ra_upd_rej(struct msgb *old_msg, uint8_t cause)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 RA UPD REJ");
-	struct gsm48_hdr *gh;
-
-	LOGP(DMM, LOGL_NOTICE, "<- ROUTING AREA UPDATE REJECT\n");
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ROUTING_AREA_REJECT]);
-
-	gmm_copy_id(msg, old_msg);
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 2);
-	gh->proto_discr = GSM48_PDISC_MM_GPRS;
-	gh->msg_type = GSM48_MT_GMM_RA_UPD_REJ;
-	gh->data[0] = cause;
-	gh->data[1] = 0; /* ? */
-
-	/* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
-	return gsm48_gmm_sendmsg(msg, 0, NULL, false);
-}
-
-static void process_ms_ctx_status(struct sgsn_mm_ctx *mmctx,
-				  const uint8_t *pdp_status)
-{
-	struct sgsn_pdp_ctx *pdp, *pdp2;
-	/* 24.008 4.7.5.1.3: If the PDP context status information element is
-	 * included in ROUTING AREA UPDATE REQUEST message, then the network
-	 * shall deactivate all those PDP contexts locally (without peer to
-	 * peer signalling between the MS and the network), which are not in SM
-	 * state PDP-INACTIVE on network side but are indicated by the MS as
-	 * being in state PDP-INACTIVE. */
-
-	llist_for_each_entry_safe(pdp, pdp2, &mmctx->pdp_list, list) {
-		if (pdp->nsapi < 8) {
-			if (!(pdp_status[0] & (1 << pdp->nsapi))) {
-				LOGMMCTXP(LOGL_NOTICE, mmctx, "Dropping PDP context for NSAPI=%u "
-					"due to PDP CTX STATUS IE= 0x%02x%02x\n",
-					pdp->nsapi, pdp_status[1], pdp_status[0]);
-				sgsn_delete_pdp_ctx(pdp);
-			}
-		} else {
-			if (!(pdp_status[1] & (1 << (pdp->nsapi - 8)))) {
-				LOGMMCTXP(LOGL_NOTICE, mmctx, "Dropping PDP context for NSAPI=%u "
-					"due to PDP CTX STATUS IE= 0x%02x%02x\n",
-					pdp->nsapi, pdp_status[1], pdp_status[0]);
-				sgsn_delete_pdp_ctx(pdp);
-			}
-		}
-	}
-}
-
-/* Chapter 9.4.14: Routing area update request */
-static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
-				   struct gprs_llc_llme *llme)
-{
-#ifndef PTMSI_ALLOC
-	struct sgsn_signal_data sig_data;
-#endif
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
-	uint8_t *cur = gh->data;
-	uint8_t ms_ra_acc_cap_len;
-	struct gprs_ra_id old_ra_id;
-	struct tlv_parsed tp;
-	uint8_t upd_type;
-	enum gsm48_gmm_cause reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
-	int rc;
-
-	/* TODO: In iu mode - handle follow-on request */
-
-	/* Update Type 10.5.5.18 */
-	upd_type = *cur++ & 0x07;
-
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ROUTING_AREA_REQUEST]);
-	LOGP(DMM, LOGL_INFO, "-> GMM RA UPDATE REQUEST type=\"%s\"\n",
-		get_value_string(gprs_upd_t_strs, upd_type));
-
-	/* Old routing area identification 10.5.5.15 */
-	gsm48_parse_ra(&old_ra_id, cur);
-	cur += 6;
-
-	/* MS Radio Access Capability 10.5.5.12a */
-	ms_ra_acc_cap_len = *cur++;
-	if (ms_ra_acc_cap_len > 52) {
-		reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
-		goto rejected;
-	}
-	cur += ms_ra_acc_cap_len;
-
-	/* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status,
-	 * DRX parameter, MS network capability */
-	tlv_parse(&tp, &gsm48_gmm_att_tlvdef, cur,
-			(msg->data + msg->len) - cur, 0, 0);
-
-	switch (upd_type) {
-	case GPRS_UPD_T_RA_LA:
-	case GPRS_UPD_T_RA_LA_IMSI_ATT:
-		LOGP(DMM, LOGL_NOTICE, "Update type %i unsupported in Mode III, is your SI13 corrupt?\n", upd_type);
-		reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
-		goto rejected;
-	case GPRS_UPD_T_RA:
-	case GPRS_UPD_T_PERIODIC:
-		break;
-	}
-
-	if (!mmctx) {
-		/* BSSGP doesn't give us an mmctx */
-
-		/* TODO: Check if there is an MM CTX with old_ra_id and
-		 * the P-TMSI (if given, reguired for UMTS) or as last resort
-		 * if the TLLI matches foreign_tlli (P-TMSI). Note that this
-		 * is an optimization to avoid the RA reject (impl detached)
-		 * below, which will cause a new attach cycle. */
-		/* Look-up the MM context based on old RA-ID and TLLI */
-		/* In Iu mode, msg->dst contains the ranap_ue_conn_ctx pointer, in Gb
-		 * mode dst is empty. */
-		/* FIXME: have a more explicit indicator for Iu messages */
-		if (!msg->dst) {
-			mmctx = sgsn_mm_ctx_by_tlli_and_ptmsi(msgb_tlli(msg), &old_ra_id);
-		} else if (TLVP_PRESENT(&tp, GSM48_IE_GMM_ALLOC_PTMSI)) {
-#ifdef BUILD_IU
-			/* In Iu mode search only for ptmsi */
-			char mi_string[GSM48_MI_SIZE];
-			uint8_t mi_len = TLVP_LEN(&tp, GSM48_IE_GMM_ALLOC_PTMSI);
-			uint8_t *mi = TLVP_VAL(&tp, GSM48_IE_GMM_ALLOC_PTMSI);
-			uint8_t mi_type = *mi & GSM_MI_TYPE_MASK;
-			uint32_t tmsi;
-
-			gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
-
-			if (mi_type == GSM_MI_TYPE_TMSI) {
-				memcpy(&tmsi, mi+1, 4);
-				tmsi = ntohl(tmsi);
-				mmctx = sgsn_mm_ctx_by_ptmsi(tmsi);
-			}
-#else
-			goto rejected;
-#endif
-		}
-		if (mmctx) {
-			LOGMMCTXP(LOGL_INFO, mmctx,
-				"Looked up by matching TLLI and P_TMSI. "
-				"BSSGP TLLI: %08x, P-TMSI: %08x (%08x), "
-				"TLLI: %08x (%08x), RA: %d-%d-%d-%d\n",
-				msgb_tlli(msg),
-				mmctx->p_tmsi, mmctx->p_tmsi_old,
-				mmctx->gb.tlli, mmctx->gb.tlli_new,
-				mmctx->ra.mcc, mmctx->ra.mnc,
-				mmctx->ra.lac, mmctx->ra.rac);
-
-			mmctx->gmm_state = GMM_COMMON_PROC_INIT;
-		}
-	} else if (!gprs_ra_id_equals(&mmctx->ra, &old_ra_id) ||
-		mmctx->gmm_state == GMM_DEREGISTERED)
-	{
-		/* We cannot use the mmctx */
-		LOGMMCTXP(LOGL_INFO, mmctx,
-			"The MM context cannot be used, RA: %d-%d-%d-%d\n",
-			mmctx->ra.mcc, mmctx->ra.mnc,
-			mmctx->ra.lac, mmctx->ra.rac);
-		mmctx = NULL;
-	}
-
-	if (!mmctx) {
-		if (llme) {
-			/* send a XID reset to re-set all LLC sequence numbers
-			 * in the MS */
-			LOGMMCTXP(LOGL_NOTICE, mmctx, "LLC XID RESET\n");
-			gprs_llgmm_reset(llme);
-		}
-		/* The MS has to perform GPRS attach */
-		/* Device is still IMSI attached for CS but initiate GPRS ATTACH,
-		 * see GSM 04.08, 4.7.5.1.4 and G.6 */
-		reject_cause = GMM_CAUSE_IMPL_DETACHED;
-		goto rejected;
-	}
-
-	/* Store new BVCI/NSEI in MM context (FIXME: delay until we ack?) */
-	msgid2mmctx(mmctx, msg);
-	/* Bump the statistics of received signalling msgs for this MM context */
-	rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PKTS_SIG_IN]);
-
-	/* Update the MM context with the new RA-ID */
-	if (mmctx->ran_type == MM_CTX_T_GERAN_Gb) {
-		bssgp_parse_cell_id(&mmctx->ra, msgb_bcid(msg));
-		/* Update the MM context with the new (i.e. foreign) TLLI */
-		mmctx->gb.tlli = msgb_tlli(msg);
-	}
-	/* FIXME: Update the MM context with the MS radio acc capabilities */
-	/* FIXME: Update the MM context with the MS network capabilities */
-
-	rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_RA_UPDATE]);
-
-#ifdef PTMSI_ALLOC
-	/* Don't change the P-TMSI if a P-TMSI re-assignment is under way */
-	if (mmctx->gmm_state != GMM_COMMON_PROC_INIT) {
-		mmctx->p_tmsi_old = mmctx->p_tmsi;
-		mmctx->p_tmsi = sgsn_alloc_ptmsi();
-	}
-	/* Start T3350 and re-transmit up to 5 times until ATTACH COMPLETE */
-	mmctx->t3350_mode = GMM_T3350_MODE_RAU;
-	mmctx_timer_start(mmctx, 3350, sgsn->cfg.timers.T3350);
-
-	mmctx->gmm_state = GMM_COMMON_PROC_INIT;
-#else
-	/* Make sure we are NORMAL (i.e. not SUSPENDED anymore) */
-	mmctx->gmm_state = GMM_REGISTERED_NORMAL;
-
-	memset(&sig_data, 0, sizeof(sig_data));
-	sig_data.mm = mmctx;
-	osmo_signal_dispatch(SS_SGSN, S_SGSN_UPDATE, &sig_data);
-#endif
-	if (mmctx->ran_type == MM_CTX_T_GERAN_Gb) {
-		/* Even if there is no P-TMSI allocated, the MS will switch from
-	 	* foreign TLLI to local TLLI */
-		mmctx->gb.tlli_new = gprs_tmsi2tlli(mmctx->p_tmsi, TLLI_LOCAL);
-
-		/* Inform LLC layer about new TLLI but keep old active */
-		gprs_llgmm_assign(mmctx->gb.llme, mmctx->gb.tlli,
-				  mmctx->gb.tlli_new);
-	}
-
-	/* Look at PDP Context Status IE and see if MS's view of
-	 * activated/deactivated NSAPIs agrees with our view */
-	if (TLVP_PRESENT(&tp, GSM48_IE_GMM_PDP_CTX_STATUS)) {
-		const uint8_t *pdp_status = TLVP_VAL(&tp, GSM48_IE_GMM_PDP_CTX_STATUS);
-		process_ms_ctx_status(mmctx, pdp_status);
-	}
-
-	/* Send RA UPDATE ACCEPT. In Iu, the RA upd request can be called from
-	 * a new Iu connection, so we might need to re-authenticate the
-	 * connection as well as turn on integrity protection. */
-	mmctx->pending_req = GSM48_MT_GMM_RA_UPD_REQ;
-	return gsm48_gmm_authorize(mmctx);
-
-rejected:
-	/* Send RA UPDATE REJECT */
-	LOGMMCTXP(LOGL_NOTICE, mmctx,
-		  "Rejecting RA Update Request with cause '%s' (%d)\n",
-		  get_value_string(gsm48_gmm_cause_names, reject_cause), reject_cause);
-	rc = gsm48_tx_gmm_ra_upd_rej(msg, reject_cause);
-	if (mmctx)
-		mm_ctx_cleanup_free(mmctx, "GPRS RA UPDATE REJ");
-	else {
-		if (llme)
-			gprs_llgmm_unassign(llme);
-	}
-
-	return rc;
-}
-
-/* 3GPP TS 24.008 Section 9.4.20 Service request.
- * In Iu, a UE in PMM-IDLE mode can use GSM48_MT_GMM_SERVICE_REQ to switch back
- * to PMM-CONNECTED mode. */
-static int gsm48_rx_gmm_service_req(struct sgsn_mm_ctx *ctx, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
-	uint8_t *cur = gh->data, *mi;
-	uint8_t ciph_seq_nr, service_type, mi_len, mi_type;
-	uint32_t tmsi;
-	struct tlv_parsed tp;
-	char mi_string[GSM48_MI_SIZE];
-	enum gsm48_gmm_cause reject_cause;
-	int rc;
-
-	LOGMMCTXP(LOGL_INFO, ctx, "-> GMM SERVICE REQUEST ");
-
-	/* This message is only valid in Iu mode */
-	if (!msg->dst) {
-		LOGPC(DMM, LOGL_INFO, "Invalid if not in Iu mode\n");
-		return -1;
-	}
-
-	/* Skip Ciphering key sequence number 10.5.1.2 */
-	ciph_seq_nr = *cur & 0x07;
-
-	/* Service type 10.5.5.20 */
-	service_type = (*cur++ >> 4) & 0x07;
-
-	/* Mobile Identity (P-TMSI or IMSI) 10.5.1.4 */
-	mi_len = *cur++;
-	mi = cur;
-	if (mi_len > 8)
-		goto err_inval;
-	mi_type = *mi & GSM_MI_TYPE_MASK;
-	cur += mi_len;
-
-	gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
-
-	DEBUGPC(DMM, "MI(%s) type=\"%s\" ", mi_string,
-		get_value_string(gprs_service_t_strs, service_type));
-
-	LOGPC(DMM, LOGL_INFO, "\n");
-
-	/* Optional: PDP context status, MBMS context status, Uplink data status, Device properties */
-	tlv_parse(&tp, &gsm48_gmm_att_tlvdef, cur, (msg->data + msg->len) - cur, 0, 0);
-
-	switch (mi_type) {
-	case GSM_MI_TYPE_IMSI:
-		/* Try to find MM context based on IMSI */
-		if (!ctx)
-			ctx = sgsn_mm_ctx_by_imsi(mi_string);
-		if (!ctx) {
-			/* FIXME: We need to have a context for service request? */
-			reject_cause = GMM_CAUSE_NET_FAIL;
-			goto rejected;
-		}
-		msgid2mmctx(ctx, msg);
-		break;
-	case GSM_MI_TYPE_TMSI:
-		memcpy(&tmsi, mi+1, 4);
-		tmsi = ntohl(tmsi);
-		/* Try to find MM context based on P-TMSI */
-		if (!ctx)
-			ctx = sgsn_mm_ctx_by_ptmsi(tmsi);
-		if (!ctx) {
-			/* FIXME: We need to have a context for service request? */
-			reject_cause = GMM_CAUSE_NET_FAIL;
-			goto rejected;
-		}
-		msgid2mmctx(ctx, msg);
-		break;
-	default:
-		LOGMMCTXP(LOGL_NOTICE, ctx, "Rejecting SERVICE REQUEST with "
-			"MI type %s\n", gsm48_mi_type_name(mi_type));
-		reject_cause = GMM_CAUSE_MS_ID_NOT_DERIVED;
-		goto rejected;
-	}
-
-	ctx->gmm_state = GMM_COMMON_PROC_INIT;
-
-	ctx->iu.service.type = service_type;
-
-	/* TODO: Handle those only in case of accept? */
-	/* Look at PDP Context Status IE and see if MS's view of
-	 * activated/deactivated NSAPIs agrees with our view */
-	if (TLVP_PRESENT(&tp, GSM48_IE_GMM_PDP_CTX_STATUS)) {
-		const uint8_t *pdp_status = TLVP_VAL(&tp, GSM48_IE_GMM_PDP_CTX_STATUS);
-		process_ms_ctx_status(ctx, pdp_status);
-	}
-
-
-	ctx->pending_req = GSM48_MT_GMM_SERVICE_REQ;
-	return gsm48_gmm_authorize(ctx);
-
-err_inval:
-	LOGPC(DMM, LOGL_INFO, "\n");
-	reject_cause = GMM_CAUSE_SEM_INCORR_MSG;
-
-rejected:
-	/* Send SERVICE REJECT */
-	LOGMMCTXP(LOGL_NOTICE, ctx,
-		  "Rejecting Service Request with cause '%s' (%d)\n",
-		  get_value_string(gsm48_gmm_cause_names, reject_cause), reject_cause);
-	rc = gsm48_tx_gmm_service_rej_oldmsg(msg, reject_cause);
-
-	return rc;
-
-}
-
-
-static int gsm48_rx_gmm_status(struct sgsn_mm_ctx *mmctx, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-
-	LOGMMCTXP(LOGL_INFO, mmctx, "-> GPRS MM STATUS (cause: %s)\n",
-		get_value_string(gsm48_gmm_cause_names, gh->data[0]));
-
-	return 0;
-}
-
-/* GPRS Mobility Management */
-static int gsm0408_rcv_gmm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
-			   struct gprs_llc_llme *llme, bool drop_cipherable)
-{
-	struct sgsn_signal_data sig_data;
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
-	int rc;
-
-	/* MMCTX can be NULL when called */
-	if (drop_cipherable && gsm48_hdr_gmm_cipherable(gh)) {
-		LOGMMCTXP(LOGL_NOTICE, mmctx, "Dropping cleartext GMM %s which "
-			  "is expected to be encrypted for TLLI 0x%08x\n",
-			  get_value_string(gprs_msgt_gmm_names, gh->msg_type),
-			  llme->tlli);
-		return -EBADMSG;
-	}
-
-	if (llme && !mmctx &&
-	    gh->msg_type != GSM48_MT_GMM_ATTACH_REQ &&
-	    gh->msg_type != GSM48_MT_GMM_RA_UPD_REQ) {
-		LOGP(DMM, LOGL_NOTICE, "Cannot handle GMM for unknown MM CTX\n");
-		/* 4.7.10 */
-		if (gh->msg_type == GSM48_MT_GMM_STATUS) {
-			/* TLLI unassignment */
-			gprs_llgmm_unassign(llme);
-			return 0;
-		}
-
-		/* Don't reply or establish a LLME on DETACH_ACK */
-		if (gh->msg_type == GSM48_MT_GMM_DETACH_ACK)
-			return gprs_llgmm_unassign(llme);
-
-		gprs_llgmm_reset(llme);
-
-		/* Don't force it into re-attachment */
-		if (gh->msg_type == GSM48_MT_GMM_DETACH_REQ) {
-			/* Handle Detach Request */
-			rc = gsm48_rx_gmm_det_req(NULL, msg);
-
-			/* TLLI unassignment */
-			gprs_llgmm_unassign(llme);
-			return rc;
-		}
-
-		/* Force the MS to re-attach */
-		rc = gsm0408_gprs_force_reattach_oldmsg(msg, llme);
-
-		/* TLLI unassignment */
-		gprs_llgmm_unassign(llme);
-		return rc;
-	}
-
-	/*
-	 * For a few messages, mmctx may be NULL. For most, we want to ensure a
-	 * non-NULL mmctx. At the same time, we want to keep the message
-	 * validity check intact, so that all message types appear in the
-	 * switch statement and the default case thus means "unknown message".
-	 * If we split the switch in two parts to check non-NULL halfway, the
-	 * unknown-message check breaks, or we'd need to duplicate the switch
-	 * cases in both parts. Just keep one large switch and add some gotos.
-	 */
-	switch (gh->msg_type) {
-	case GSM48_MT_GMM_RA_UPD_REQ:
-		rc = gsm48_rx_gmm_ra_upd_req(mmctx, msg, llme);
-		break;
-	case GSM48_MT_GMM_ATTACH_REQ:
-		rc = gsm48_rx_gmm_att_req(mmctx, msg, llme);
-		break;
-	case GSM48_MT_GMM_SERVICE_REQ:
-		rc = gsm48_rx_gmm_service_req(mmctx, msg);
-		break;
-	/* For all the following types mmctx can not be NULL */
-	case GSM48_MT_GMM_ID_RESP:
-		if (!mmctx)
-			goto null_mmctx;
-		rc = gsm48_rx_gmm_id_resp(mmctx, msg);
-		break;
-	case GSM48_MT_GMM_STATUS:
-		if (!mmctx)
-			goto null_mmctx;
-		rc = gsm48_rx_gmm_status(mmctx, msg);
-		break;
-	case GSM48_MT_GMM_DETACH_REQ:
-		if (!mmctx)
-			goto null_mmctx;
-		rc = gsm48_rx_gmm_det_req(mmctx, msg);
-		break;
-	case GSM48_MT_GMM_DETACH_ACK:
-		if (!mmctx)
-			goto null_mmctx;
-		LOGMMCTXP(LOGL_INFO, mmctx, "-> DETACH ACK\n");
-		mm_ctx_cleanup_free(mmctx, "GPRS DETACH ACK");
-		rc = 0;
-		break;
-	case GSM48_MT_GMM_ATTACH_COMPL:
-		if (!mmctx)
-			goto null_mmctx;
-		/* only in case SGSN offered new P-TMSI */
-		LOGMMCTXP(LOGL_INFO, mmctx, "-> ATTACH COMPLETE\n");
-		mmctx_timer_stop(mmctx, 3350);
-		mmctx->t3350_mode = GMM_T3350_MODE_NONE;
-		mmctx->p_tmsi_old = 0;
-		mmctx->pending_req = 0;
-		if (mmctx->ran_type == MM_CTX_T_GERAN_Gb) {
-			/* Unassign the old TLLI */
-			mmctx->gb.tlli = mmctx->gb.tlli_new;
-			gprs_llme_copy_key(mmctx, mmctx->gb.llme);
-			gprs_llgmm_assign(mmctx->gb.llme, 0xffffffff,
-					  mmctx->gb.tlli_new);
-		}
-		mmctx->gmm_state = GMM_REGISTERED_NORMAL;
-		mmctx_set_pmm_state(mmctx, PMM_CONNECTED);
-		mmctx_set_mm_state(mmctx, MM_READY);
-		rc = 0;
-
-		memset(&sig_data, 0, sizeof(sig_data));
-		sig_data.mm = mmctx;
-		osmo_signal_dispatch(SS_SGSN, S_SGSN_ATTACH, &sig_data);
-		break;
-	case GSM48_MT_GMM_RA_UPD_COMPL:
-		if (!mmctx)
-			goto null_mmctx;
-		/* only in case SGSN offered new P-TMSI */
-		LOGMMCTXP(LOGL_INFO, mmctx, "-> ROUTING AREA UPDATE COMPLETE\n");
-		mmctx_timer_stop(mmctx, 3350);
-		mmctx->t3350_mode = GMM_T3350_MODE_NONE;
-		mmctx->p_tmsi_old = 0;
-		mmctx->pending_req = 0;
-		if (mmctx->ran_type == MM_CTX_T_GERAN_Gb) {
-			/* Unassign the old TLLI */
-			mmctx->gb.tlli = mmctx->gb.tlli_new;
-			gprs_llgmm_assign(mmctx->gb.llme, 0xffffffff,
-					  mmctx->gb.tlli_new);
-		}
-		mmctx->gmm_state = GMM_REGISTERED_NORMAL;
-		mmctx_set_pmm_state(mmctx, PMM_CONNECTED);
-		mmctx_set_mm_state(mmctx, MM_READY);
-		rc = 0;
-
-		memset(&sig_data, 0, sizeof(sig_data));
-		sig_data.mm = mmctx;
-		osmo_signal_dispatch(SS_SGSN, S_SGSN_UPDATE, &sig_data);
-		break;
-	case GSM48_MT_GMM_PTMSI_REALL_COMPL:
-		if (!mmctx)
-			goto null_mmctx;
-		LOGMMCTXP(LOGL_INFO, mmctx, "-> PTMSI REALLLICATION COMPLETE\n");
-		mmctx_timer_stop(mmctx, 3350);
-		mmctx->t3350_mode = GMM_T3350_MODE_NONE;
-		mmctx->p_tmsi_old = 0;
-		mmctx->pending_req = 0;
-		if (mmctx->ran_type == MM_CTX_T_GERAN_Gb) {
-			/* Unassign the old TLLI */
-			mmctx->gb.tlli = mmctx->gb.tlli_new;
-			//gprs_llgmm_assign(mmctx->gb.llme, 0xffffffff, mmctx->gb.tlli_new, GPRS_ALGO_GEA0, NULL);
-		}
-		rc = 0;
-		break;
-	case GSM48_MT_GMM_AUTH_CIPH_RESP:
-		if (!mmctx)
-			goto null_mmctx;
-		rc = gsm48_rx_gmm_auth_ciph_resp(mmctx, msg);
-		break;
-	case GSM48_MT_GMM_AUTH_CIPH_FAIL:
-		rc = gsm48_rx_gmm_auth_ciph_fail(mmctx, msg);
-		break;
-	default:
-		LOGMMCTXP(LOGL_NOTICE, mmctx, "Unknown GSM 04.08 GMM msg type 0x%02x\n",
-			gh->msg_type);
-		if (mmctx)
-			rc = gsm48_tx_gmm_status(mmctx, GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
-		else
-			rc = -EINVAL;
-		break;
-	}
-
-	return rc;
-
-null_mmctx:
-	LOGP(DMM, LOGL_ERROR,
-	     "Received GSM 04.08 message type 0x%02x,"
-	     " but no MM context available\n",
-	     gh->msg_type);
-	return -EINVAL;
-}
-
-static void mmctx_timer_cb(void *_mm)
-{
-	struct sgsn_mm_ctx *mm = _mm;
-	struct gsm_auth_tuple *at;
-
-	mm->num_T_exp++;
-
-	switch (mm->T) {
-	case 3350:	/* waiting for ATTACH COMPLETE */
-		if (mm->num_T_exp >= 5) {
-			LOGMMCTXP(LOGL_NOTICE, mm, "T3350 expired >= 5 times\n");
-			mm_ctx_cleanup_free(mm, "T3350");
-			/* FIXME: should we return some error? */
-			break;
-		}
-		/* re-transmit the respective msg and re-start timer */
-		switch (mm->t3350_mode) {
-		case GMM_T3350_MODE_ATT:
-			gsm48_tx_gmm_att_ack(mm);
-			break;
-		case GMM_T3350_MODE_RAU:
-			gsm48_tx_gmm_ra_upd_ack(mm);
-			break;
-		case GMM_T3350_MODE_PTMSI_REALL:
-			/* FIXME */
-			break;
-		case GMM_T3350_MODE_NONE:
-			LOGMMCTXP(LOGL_NOTICE, mm,
-				  "T3350 mode wasn't set, ignoring timeout\n");
-			break;
-		}
-		osmo_timer_schedule(&mm->timer, sgsn->cfg.timers.T3350, 0);
-		break;
-	case 3360:	/* waiting for AUTH AND CIPH RESP */
-		if (mm->num_T_exp >= 5) {
-			LOGMMCTXP(LOGL_NOTICE, mm, "T3360 expired >= 5 times\n");
-			mm_ctx_cleanup_free(mm, "T3360");
-			break;
-		}
-		/* Re-transmit the respective msg and re-start timer */
-		if (mm->auth_triplet.key_seq == GSM_KEY_SEQ_INVAL) {
-			LOGMMCTXP(LOGL_ERROR, mm,
-				  "timeout: invalid auth triplet reference\n");
-			mm_ctx_cleanup_free(mm, "T3360");
-			break;
-		}
-		at = &mm->auth_triplet;
-
-		gsm48_tx_gmm_auth_ciph_req(mm, &at->vec, at->key_seq, false);
-		osmo_timer_schedule(&mm->timer, sgsn->cfg.timers.T3360, 0);
-		break;
-	case 3370:	/* waiting for IDENTITY RESPONSE */
-		if (mm->num_T_exp >= 5) {
-			LOGMMCTXP(LOGL_NOTICE, mm, "T3370 expired >= 5 times\n");
-			gsm48_tx_gmm_att_rej(mm, GMM_CAUSE_MS_ID_NOT_DERIVED);
-			mm_ctx_cleanup_free(mm, "GPRS ATTACH REJECT (T3370)");
-			break;
-		}
-		/* re-tranmit IDENTITY REQUEST and re-start timer */
-		gsm48_tx_gmm_id_req(mm, mm->t3370_id_type);
-		osmo_timer_schedule(&mm->timer, sgsn->cfg.timers.T3370, 0);
-		break;
-	default:
-		LOGMMCTXP(LOGL_ERROR, mm, "timer expired in unknown mode %u\n",
-			mm->T);
-	}
-}
-
-/* GPRS SESSION MANAGEMENT */
-
-static void pdpctx_timer_cb(void *_mm);
-
-static void pdpctx_timer_start(struct sgsn_pdp_ctx *pdp, unsigned int T,
-				unsigned int seconds)
-{
-	if (osmo_timer_pending(&pdp->timer))
-		LOGPDPCTXP(LOGL_ERROR, pdp, "Starting PDP timer %u while old "
-			"timer %u pending\n", T, pdp->T);
-	pdp->T = T;
-	pdp->num_T_exp = 0;
-
-	/* FIXME: we should do this only once ? */
-	osmo_timer_setup(&pdp->timer, pdpctx_timer_cb, pdp);
-	osmo_timer_schedule(&pdp->timer, seconds, 0);
-}
-
-static void pdpctx_timer_stop(struct sgsn_pdp_ctx *pdp, unsigned int T)
-{
-	if (pdp->T != T)
-		LOGPDPCTXP(LOGL_ERROR, pdp, "Stopping PDP timer %u but "
-			"%u is running\n", T, pdp->T);
-	osmo_timer_del(&pdp->timer);
-}
-
-#if 0
-static void msgb_put_pdp_addr_ipv4(struct msgb *msg, uint32_t ipaddr)
-{
-	uint8_t v[6];
-
-	v[0] = PDP_TYPE_ORG_IETF;
-	v[1] = PDP_TYPE_N_IETF_IPv4;
-	*(uint32_t *)(v+2) = htonl(ipaddr);
-
-	msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR, sizeof(v), v);
-}
-
-static void msgb_put_pdp_addr_ppp(struct msgb *msg)
-{
-	uint8_t v[2];
-
-	v[0] = PDP_TYPE_ORG_ETSI;
-	v[1] = PDP_TYPE_N_ETSI_PPP;
-
-	msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR, sizeof(v), v);
-}
-#endif
-
-/* Section 9.5.2: Activate PDP Context Accept */
-int gsm48_tx_gsm_act_pdp_acc(struct sgsn_pdp_ctx *pdp)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 PDP ACC");
-	struct gsm48_hdr *gh;
-	uint8_t transaction_id = pdp->ti ^ 0x8; /* flip */
-
-	LOGPDPCTXP(LOGL_INFO, pdp, "<- ACTIVATE PDP CONTEXT ACK\n");
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_ACTIVATE_ACCEPT]);
-
-	mmctx2msgid(msg, pdp->mm);
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
-	gh->msg_type = GSM48_MT_GSM_ACT_PDP_ACK;
-
-	/* Negotiated LLC SAPI */
-	msgb_v_put(msg, pdp->sapi);
-
-	/* FIXME: copy QoS parameters from original request */
-	//msgb_lv_put(msg, pdp->lib->qos_neg.l, pdp->lib->qos_neg.v);
-	msgb_lv_put(msg, sizeof(default_qos), (uint8_t *)&default_qos);
-
-	/* Radio priority 10.5.7.2 */
-	msgb_v_put(msg, pdp->lib->radio_pri);
-
-	/* PDP address */
-	/* Highest 4 bits of first byte need to be set to 1, otherwise
-	 * the IE is identical with the 04.08 PDP Address IE */
-	pdp->lib->eua.v[0] &= ~0xf0;
-	msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR,
-		     pdp->lib->eua.l, pdp->lib->eua.v);
-	pdp->lib->eua.v[0] |= 0xf0;
-
-	/* Optional: Protocol configuration options (FIXME: why 'req') */
-	if (pdp->lib->pco_req.l)
-		msgb_tlv_put(msg, GSM48_IE_GSM_PROTO_CONF_OPT,
-			     pdp->lib->pco_req.l, pdp->lib->pco_req.v);
-
-	/* Optional: Packet Flow Identifier */
-
-	return gsm48_gmm_sendmsg(msg, 0, pdp->mm, true);
-}
-
-/* Section 9.5.3: Activate PDP Context reject */
-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)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 PDP REJ");
-	struct gsm48_hdr *gh;
-	uint8_t transaction_id = tid ^ 0x8; /* flip */
-
-	LOGMMCTXP(LOGL_NOTICE, mm, "<- ACTIVATE PDP CONTEXT REJ(cause=%u)\n", cause);
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_ACTIVATE_REJECT]);
-
-	mmctx2msgid(msg, mm);
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
-	gh->msg_type = GSM48_MT_GSM_ACT_PDP_REJ;
-
-	msgb_v_put(msg, cause);
-	if (pco_len && pco_v)
-		msgb_tlv_put(msg, GSM48_IE_GSM_PROTO_CONF_OPT, pco_len, pco_v);
-
-	return gsm48_gmm_sendmsg(msg, 0, mm, true);
-}
-
-/* Section 9.5.8: Deactivate PDP Context Request */
-static int _gsm48_tx_gsm_deact_pdp_req(struct sgsn_mm_ctx *mm, uint8_t tid,
-					uint8_t sm_cause)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 PDP DET REQ");
-	struct gsm48_hdr *gh;
-	uint8_t transaction_id = tid ^ 0x8; /* flip */
-
-	LOGMMCTXP(LOGL_INFO, mm, "<- DEACTIVATE PDP CONTEXT REQ\n");
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_DL_DEACTIVATE_REQUEST]);
-
-	mmctx2msgid(msg, mm);
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
-	gh->msg_type = GSM48_MT_GSM_DEACT_PDP_REQ;
-
-	msgb_v_put(msg, sm_cause);
-
-	return gsm48_gmm_sendmsg(msg, 0, mm, true);
-}
-int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause)
-{
-	pdpctx_timer_start(pdp, 3395, sgsn->cfg.timers.T3395);
-
-	return _gsm48_tx_gsm_deact_pdp_req(pdp->mm, pdp->ti, sm_cause);
-}
-
-/* Section 9.5.9: Deactivate PDP Context Accept */
-static int _gsm48_tx_gsm_deact_pdp_acc(struct sgsn_mm_ctx *mm, uint8_t tid)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 PDP DET ACC");
-	struct gsm48_hdr *gh;
-	uint8_t transaction_id = tid ^ 0x8; /* flip */
-
-	LOGMMCTXP(LOGL_INFO, mm, "<- DEACTIVATE PDP CONTEXT ACK\n");
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_DL_DEACTIVATE_ACCEPT]);
-
-	mmctx2msgid(msg, mm);
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
-	gh->msg_type = GSM48_MT_GSM_DEACT_PDP_ACK;
-
-	return gsm48_gmm_sendmsg(msg, 0, mm, true);
-}
-int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp)
-{
-	return _gsm48_tx_gsm_deact_pdp_acc(pdp->mm, pdp->ti);
-}
-
-static int activate_ggsn(struct sgsn_mm_ctx *mmctx,
-		struct sgsn_ggsn_ctx *ggsn, const uint8_t transaction_id,
-		const uint8_t req_nsapi, const uint8_t req_llc_sapi,
-		struct tlv_parsed *tp, int destroy_ggsn)
-{
-	struct sgsn_pdp_ctx *pdp;
-
-	LOGMMCTXP(LOGL_DEBUG, mmctx, "Using GGSN %u\n", ggsn->id);
-	ggsn->gsn = sgsn->gsn;
-	pdp = sgsn_create_pdp_ctx(ggsn, mmctx, req_nsapi, tp);
-	if (!pdp)
-		return -1;
-
-	/* Store SAPI and Transaction Identifier */
-	pdp->sapi = req_llc_sapi;
-	pdp->ti = transaction_id;
-	pdp->destroy_ggsn = destroy_ggsn;
-
-	return 0;
-}
-
-static void ggsn_lookup_cb(void *arg, int status, int timeouts, struct hostent *hostent)
-{
-	struct sgsn_ggsn_ctx *ggsn;
-	struct sgsn_ggsn_lookup *lookup = arg;
-	struct in_addr *addr = NULL;
-
-	/* The context is gone while we made a request */
-	if (!lookup->mmctx) {
-		talloc_free(lookup->orig_msg);
-		talloc_free(lookup);
-		return;
-	}
-
-	if (status != ARES_SUCCESS) {
-		struct sgsn_mm_ctx *mmctx = lookup->mmctx;
-
-		LOGMMCTXP(LOGL_ERROR, mmctx, "DNS query failed.\n");
-
-		/* Need to try with three digits now */
-		if (lookup->state == SGSN_GGSN_2DIGIT) {
-			char *hostname;
-			int rc;
-
-			lookup->state = SGSN_GGSN_3DIGIT;
-			hostname = osmo_apn_qualify_from_imsi(mmctx->imsi,
-					lookup->apn_str, 1);
-			LOGMMCTXP(LOGL_DEBUG, mmctx,
-				"Going to query %s\n", hostname);
-			rc = sgsn_ares_query(sgsn, hostname,
-					ggsn_lookup_cb, lookup);
-			if (rc != 0) {
-				LOGMMCTXP(LOGL_ERROR, mmctx, "Couldn't start GGSN\n");
-				goto reject_due_failure;
-			}
-			return;
-		}
-
-		LOGMMCTXP(LOGL_ERROR, mmctx, "Couldn't resolve GGSN\n");
-		goto reject_due_failure;
-	}
-
-	if (hostent->h_length != sizeof(struct in_addr)) {
-		LOGMMCTXP(LOGL_ERROR, lookup->mmctx,
-			"Wrong addr size(%zu)\n", sizeof(struct in_addr));
-		goto reject_due_failure;
-	}
-
-	/* Get the first addr from the list */
-	addr = (struct in_addr *) hostent->h_addr_list[0];
-	if (!addr) {
-		LOGMMCTXP(LOGL_ERROR, lookup->mmctx, "No host address.\n");
-		goto reject_due_failure;
-	}
-
-	ggsn = sgsn_ggsn_ctx_alloc(UINT32_MAX);
-	if (!ggsn) {
-		LOGMMCTXP(LOGL_ERROR, lookup->mmctx, "Failed to create ggsn.\n");
-		goto reject_due_failure;
-	}
-	ggsn->remote_addr = *addr;
-	LOGMMCTXP(LOGL_NOTICE, lookup->mmctx,
-		"Selected %s as GGSN.\n", inet_ntoa(*addr));
-
-	/* forget about the ggsn look-up */
-	lookup->mmctx->ggsn_lookup = NULL;
-
-	activate_ggsn(lookup->mmctx, ggsn, lookup->ti, lookup->nsapi,
-			lookup->sapi, &lookup->tp, 1);
-
-	/* Now free it */
-	talloc_free(lookup->orig_msg);
-	talloc_free(lookup);
-	return;
-
-reject_due_failure:
-	gsm48_tx_gsm_act_pdp_rej(lookup->mmctx, lookup->ti,
-				GMM_CAUSE_NET_FAIL, 0, NULL);
-	lookup->mmctx->ggsn_lookup = NULL;
-	talloc_free(lookup->orig_msg);
-	talloc_free(lookup);
-}
-
-static int do_act_pdp_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg, bool *delete)
-{
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
-	struct gsm48_act_pdp_ctx_req *act_req = (struct gsm48_act_pdp_ctx_req *) gh->data;
-	uint8_t req_qos_len, req_pdpa_len;
-	uint8_t *req_qos, *req_pdpa;
-	struct tlv_parsed tp;
-	uint8_t transaction_id = gsm48_hdr_trans_id(gh);
-	struct sgsn_ggsn_ctx *ggsn;
-	struct sgsn_pdp_ctx *pdp;
-	enum gsm48_gsm_cause gsm_cause;
-	char apn_str[GSM_APN_LENGTH] = { 0, };
-	char *hostname;
-	int rc;
-	struct gprs_llc_lle *lle;
-
-	LOGMMCTXP(LOGL_INFO, mmctx, "-> ACTIVATE PDP CONTEXT REQ: SAPI=%u NSAPI=%u ",
-		act_req->req_llc_sapi, act_req->req_nsapi);
-
-	/* FIXME: length checks! */
-	req_qos_len = act_req->data[0];
-	req_qos = act_req->data + 1;	/* 10.5.6.5 */
-	req_pdpa_len = act_req->data[1 + req_qos_len];
-	req_pdpa = act_req->data + 1 + req_qos_len + 1;	/* 10.5.6.4 */
-
-	switch (req_pdpa[0] & 0xf) {
-	case 0x0:
-		DEBUGPC(DMM, "ETSI ");
-		break;
-	case 0x1:
-		DEBUGPC(DMM, "IETF ");
-		break;
-	case 0xf:
-		DEBUGPC(DMM, "Empty ");
-		break;
-	}
-
-	switch (req_pdpa[1]) {
-	case 0x21:
-		DEBUGPC(DMM, "IPv4 ");
-		if (req_pdpa_len >= 6) {
-			struct in_addr ia;
-			ia.s_addr = ntohl(*((uint32_t *) (req_pdpa+2)));
-			DEBUGPC(DMM, "%s ", inet_ntoa(ia));
-		}
-		break;
-	case 0x57:
-		DEBUGPC(DMM, "IPv6 ");
-		if (req_pdpa_len >= 18) {
-			/* FIXME: print IPv6 address */
-		}
-		break;
-	default:	
-		DEBUGPC(DMM, "0x%02x ", req_pdpa[1]);
-		break;
-	}
-
-	LOGPC(DMM, LOGL_INFO, "\n");
-
-	/* Check if NSAPI is out of range (TS 04.65 / 7.2) */
-	if (act_req->req_nsapi < 5 || act_req->req_nsapi > 15) {
-		/* Send reject with GSM_CAUSE_INV_MAND_INFO */
-		return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
-						GSM_CAUSE_INV_MAND_INFO,
-						0, NULL);
-	}
-
-	/* Optional: Access Point Name, Protocol Config Options */
-	if (req_pdpa + req_pdpa_len < msg->data + msg->len)
-		tlv_parse(&tp, &gsm48_sm_att_tlvdef, req_pdpa + req_pdpa_len,
-			  (msg->data + msg->len) - (req_pdpa + req_pdpa_len), 0, 0);
-	else
-		memset(&tp, 0, sizeof(tp));
-
-
-	/* put the non-TLV elements in the TLV parser structure to
-	 * pass them on to the SGSN / GTP code */
-	tp.lv[OSMO_IE_GSM_REQ_QOS].len = req_qos_len;
-	tp.lv[OSMO_IE_GSM_REQ_QOS].val = req_qos;
-	tp.lv[OSMO_IE_GSM_REQ_PDP_ADDR].len = req_pdpa_len;
-	tp.lv[OSMO_IE_GSM_REQ_PDP_ADDR].val = req_pdpa;
-
-	/* Check if NSAPI is already in use */
-	pdp = sgsn_pdp_ctx_by_nsapi(mmctx, act_req->req_nsapi);
-	if (pdp) {
-		/* We already have a PDP context for this TLLI + NSAPI tuple */
-		if (pdp->sapi == act_req->req_llc_sapi &&
-		    pdp->ti == transaction_id) {
-			/* This apparently is a re-transmission of a PDP CTX
-			 * ACT REQ (our ACT ACK must have got dropped) */
-			rc = gsm48_tx_gsm_act_pdp_acc(pdp);
-			if (rc < 0)
-				return rc;
-
-			if (pdp->mm->ran_type == MM_CTX_T_GERAN_Gb) {
-				/* Also re-transmit the SNDCP XID message */
-				lle = &pdp->mm->gb.llme->lle[pdp->sapi];
-				rc = sndcp_sn_xid_req(lle,pdp->nsapi);
-				if (rc < 0)
-					return rc;
-			}
-
-			return 0;
-		}
-
-		/* Send reject with GSM_CAUSE_NSAPI_IN_USE */
-		return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
-						GSM_CAUSE_NSAPI_IN_USE,
-						0, NULL);
-	}
-
-	if (mmctx->ggsn_lookup) {
-		if (mmctx->ggsn_lookup->sapi == act_req->req_llc_sapi &&
-			mmctx->ggsn_lookup->ti == transaction_id) {
-			LOGMMCTXP(LOGL_NOTICE, mmctx,
-				"Re-transmission while doing look-up. Ignoring.\n");
-			return 0;
-		}
-	}
-
-	/* Only increment counter for a real activation, after we checked
-	 * for re-transmissions */
-	rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PDP_CTX_ACT]);
-
-	/* Determine GGSN based on APN and subscription options */
-	ggsn = sgsn_mm_ctx_find_ggsn_ctx(mmctx, &tp, &gsm_cause, apn_str);
-	if (ggsn)
-		return activate_ggsn(mmctx, ggsn, transaction_id,
-				act_req->req_nsapi, act_req->req_llc_sapi,
-				&tp, 0);
-
-	if (strlen(apn_str) == 0)
-		goto no_context;
-	if (!sgsn->cfg.dynamic_lookup)
-		goto no_context;
-
-	/* schedule a dynamic look-up */
-	mmctx->ggsn_lookup = talloc_zero(tall_bsc_ctx, struct sgsn_ggsn_lookup);
-	if (!mmctx->ggsn_lookup)
-		goto no_context;
-
-	mmctx->ggsn_lookup->state = SGSN_GGSN_2DIGIT;
-	mmctx->ggsn_lookup->mmctx = mmctx;
-	strcpy(mmctx->ggsn_lookup->apn_str, apn_str);
-
-	mmctx->ggsn_lookup->orig_msg = msg;
-	mmctx->ggsn_lookup->tp = tp;
-
-	mmctx->ggsn_lookup->ti = transaction_id;
-	mmctx->ggsn_lookup->nsapi = act_req->req_nsapi;
-	mmctx->ggsn_lookup->sapi = act_req->req_llc_sapi;
-
-	hostname = osmo_apn_qualify_from_imsi(mmctx->imsi,
-				mmctx->ggsn_lookup->apn_str, 0);
-
-	LOGMMCTXP(LOGL_DEBUG, mmctx, "Going to query %s\n", hostname);
-	rc = sgsn_ares_query(sgsn, hostname,
-				ggsn_lookup_cb, mmctx->ggsn_lookup);
-	if (rc != 0) {
-		LOGMMCTXP(LOGL_ERROR, mmctx, "Failed to start ares query.\n");
-		goto no_context;
-	}
-	*delete = 0;
-
-	return 0;
-
-no_context:
-	LOGMMCTXP(LOGL_ERROR, mmctx, "No GGSN context found!\n");
-	return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
-					gsm_cause, 0, NULL);
-}
-
-/* Section 9.5.1: Activate PDP Context Request */
-static int gsm48_rx_gsm_act_pdp_req(struct sgsn_mm_ctx *mmctx,
-				    struct msgb *_msg)
-{
-	bool delete = 1;
-	struct msgb *msg;
-	int rc;
-
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_ACTIVATE_REQUEST]);
-
-	/*
-	 * This is painful. We might not have a static GGSN
-	 * configuration and then would need to copy the msg
-	 * and re-do most of this routine (or call it again
-	 * and make sure it only goes through the dynamic
-	 * resolving. The question is what to optimize for
-	 * and the dynamic resolution will be the right thing
-	 * in the long run.
-	 */
-	msg = gprs_msgb_copy(_msg, __func__);
-	if (!msg) {
-		struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(_msg);
-		uint8_t transaction_id = gsm48_hdr_trans_id(gh);
-
-		LOGMMCTXP(LOGL_ERROR, mmctx, "-> ACTIVATE PDP CONTEXT REQ failed copy.\n");
-		/* Send reject with GSM_CAUSE_INV_MAND_INFO */
-		return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
-						GSM_CAUSE_NET_FAIL,
-						0, NULL);
-	}
-
-	rc = do_act_pdp_req(mmctx, msg, &delete);
-	if (delete)
-		msgb_free(msg);
-	return rc;
-}
-
-/* Section 9.5.8: Deactivate PDP Context Request */
-static int gsm48_rx_gsm_deact_pdp_req(struct sgsn_mm_ctx *mm, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
-	uint8_t transaction_id = gsm48_hdr_trans_id(gh);
-	struct sgsn_pdp_ctx *pdp;
-
-	LOGMMCTXP(LOGL_INFO, mm, "-> DEACTIVATE PDP CONTEXT REQ (cause: %s)\n",
-		get_value_string(gsm48_gsm_cause_names, gh->data[0]));
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_UL_DEACTIVATE_REQUEST]);
-
-	pdp = sgsn_pdp_ctx_by_tid(mm, transaction_id);
-	if (!pdp) {
-		LOGMMCTXP(LOGL_NOTICE, mm, "Deactivate PDP Context Request for "
-			"non-existing PDP Context (IMSI=%s, TI=%u)\n",
-			mm->imsi, transaction_id);
-		return _gsm48_tx_gsm_deact_pdp_acc(mm, transaction_id);
-	}
-
-	return sgsn_delete_pdp_ctx(pdp);
-}
-
-/* Section 9.5.9: Deactivate PDP Context Accept */
-static int gsm48_rx_gsm_deact_pdp_ack(struct sgsn_mm_ctx *mm, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
-	uint8_t transaction_id = gsm48_hdr_trans_id(gh);
-	struct sgsn_pdp_ctx *pdp;
-
-	LOGMMCTXP(LOGL_INFO, mm, "-> DEACTIVATE PDP CONTEXT ACK\n");
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_UL_DEACTIVATE_ACCEPT]);
-
-	pdp = sgsn_pdp_ctx_by_tid(mm, transaction_id);
-	if (!pdp) {
-		LOGMMCTXP(LOGL_NOTICE, mm, "Deactivate PDP Context Accept for "
-			"non-existing PDP Context (IMSI=%s, TI=%u)\n",
-			mm->imsi, transaction_id);
-		return 0;
-	}
-	/* stop timer 3395 */
-	pdpctx_timer_stop(pdp, 3395);
-	return sgsn_delete_pdp_ctx(pdp);
-}
-
-static int gsm48_rx_gsm_status(struct sgsn_mm_ctx *ctx, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-
-	LOGMMCTXP(LOGL_INFO, ctx, "-> GPRS SM STATUS (cause: %s)\n",
-		get_value_string(gsm48_gsm_cause_names, gh->data[0]));
-
-	return 0;
-}
-
-static void pdpctx_timer_cb(void *_pdp)
-{
-	struct sgsn_pdp_ctx *pdp = _pdp;
-
-	pdp->num_T_exp++;
-
-	switch (pdp->T) {
-	case 3395:	/* waiting for PDP CTX DEACT ACK */
-		if (pdp->num_T_exp >= 4) {
-			LOGPDPCTXP(LOGL_NOTICE, pdp, "T3395 expired >= 5 times\n");
-			pdp->state = PDP_STATE_INACTIVE;
-			sgsn_delete_pdp_ctx(pdp);
-			break;
-		}
-		gsm48_tx_gsm_deact_pdp_req(pdp, GSM_CAUSE_NET_FAIL);
-		break;
-	default:
-		LOGPDPCTXP(LOGL_ERROR, pdp, "timer expired in unknown mode %u\n",
-			pdp->T);
-	}
-}
-
-
-/* GPRS Session Management */
-static int gsm0408_rcv_gsm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
-			   struct gprs_llc_llme *llme)
-{
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
-	int rc;
-
-	/* MMCTX can be NULL when called */
-
-	if (!mmctx) {
-		LOGP(DMM, LOGL_NOTICE, "Cannot handle SM for unknown MM CTX\n");
-		/* 6.1.3.6 */
-		if (gh->msg_type == GSM48_MT_GSM_STATUS)
-			return 0;
-
-		return gsm0408_gprs_force_reattach_oldmsg(msg, llme);
-	}
-
-	switch (gh->msg_type) {
-	case GSM48_MT_GSM_ACT_PDP_REQ:
-		rc = gsm48_rx_gsm_act_pdp_req(mmctx, msg);
-		break;
-	case GSM48_MT_GSM_DEACT_PDP_REQ:
-		rc = gsm48_rx_gsm_deact_pdp_req(mmctx, msg);
-		break;
-	case GSM48_MT_GSM_DEACT_PDP_ACK:
-		rc = gsm48_rx_gsm_deact_pdp_ack(mmctx, msg);
-		break;
-	case GSM48_MT_GSM_STATUS:
-		rc = gsm48_rx_gsm_status(mmctx, msg);
-		break;
-	case GSM48_MT_GSM_REQ_PDP_ACT_REJ:
-	case GSM48_MT_GSM_ACT_AA_PDP_REQ:
-	case GSM48_MT_GSM_DEACT_AA_PDP_REQ:
-		LOGMMCTXP(LOGL_NOTICE, mmctx, "Unimplemented GSM 04.08 GSM msg type 0x%02x: %s\n",
-			gh->msg_type, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
-		rc = gsm48_tx_sm_status(mmctx, GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
-		break;
-	default:
-		LOGMMCTXP(LOGL_NOTICE, mmctx, "Unknown GSM 04.08 GSM msg type 0x%02x: %s\n",
-			gh->msg_type, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
-		rc = gsm48_tx_sm_status(mmctx, GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
-		break;
-
-	}
-
-	return rc;
-}
-
-int gsm0408_gprs_force_reattach_oldmsg(struct msgb *msg,
-				       struct gprs_llc_llme *llme)
-{
-	int rc;
-	if (llme)
-		gprs_llgmm_reset_oldmsg(msg, GPRS_SAPI_GMM, llme);
-
-	rc = gsm48_tx_gmm_detach_req_oldmsg(
-		msg, GPRS_DET_T_MT_REATT_REQ, GMM_CAUSE_IMPL_DETACHED);
-
-	return rc;
-}
-
-int gsm0408_gprs_force_reattach(struct sgsn_mm_ctx *mmctx)
-{
-	int rc;
-	if (mmctx->ran_type == MM_CTX_T_GERAN_Gb)
-		gprs_llgmm_reset(mmctx->gb.llme);
-
-	rc = gsm48_tx_gmm_detach_req(
-		mmctx, GPRS_DET_T_MT_REATT_REQ, GMM_CAUSE_IMPL_DETACHED);
-
-	mm_ctx_cleanup_free(mmctx, "forced reattach");
-
-	return rc;
-}
-
-/* Main entry point for incoming 04.08 GPRS messages from Iu */
-int gsm0408_gprs_rcvmsg_iu(struct msgb *msg, struct gprs_ra_id *ra_id,
-			   uint16_t *sai)
-{
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
-	uint8_t pdisc = gsm48_hdr_pdisc(gh);
-	struct sgsn_mm_ctx *mmctx;
-	int rc = -EINVAL;
-
-	mmctx = sgsn_mm_ctx_by_ue_ctx(msg->dst);
-	if (mmctx) {
-		rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PKTS_SIG_IN]);
-		if (ra_id)
-			memcpy(&mmctx->ra, ra_id, sizeof(mmctx->ra));
-	}
-
-	/* MMCTX can be NULL */
-
-	switch (pdisc) {
-	case GSM48_PDISC_MM_GPRS:
-		rc = gsm0408_rcv_gmm(mmctx, msg, NULL, false);
-#warning "set drop_cipherable arg for gsm0408_rcv_gmm() from IuPS?"
-		break;
-	case GSM48_PDISC_SM_GPRS:
-		rc = gsm0408_rcv_gsm(mmctx, msg, NULL);
-		break;
-	default:
-		LOGMMCTXP(LOGL_NOTICE, mmctx,
-			"Unknown GSM 04.08 discriminator 0x%02x: %s\n",
-			pdisc, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
-		/* FIXME: return status message */
-		break;
-	}
-
-	/* MMCTX can be invalid */
-
-	return rc;
-}
-
-/* Main entry point for incoming 04.08 GPRS messages from Gb */
-int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
-			   bool drop_cipherable)
-{
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
-	uint8_t pdisc = gsm48_hdr_pdisc(gh);
-	struct sgsn_mm_ctx *mmctx;
-	struct gprs_ra_id ra_id;
-	int rc = -EINVAL;
-
-	bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
-	mmctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &ra_id);
-	if (mmctx) {
-		msgid2mmctx(mmctx, msg);
-		rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PKTS_SIG_IN]);
-		mmctx->gb.llme = llme;
-	}
-
-	/* MMCTX can be NULL */
-
-	switch (pdisc) {
-	case GSM48_PDISC_MM_GPRS:
-		rc = gsm0408_rcv_gmm(mmctx, msg, llme, drop_cipherable);
-		break;
-	case GSM48_PDISC_SM_GPRS:
-		rc = gsm0408_rcv_gsm(mmctx, msg, llme);
-		break;
-	default:
-		LOGMMCTXP(LOGL_NOTICE, mmctx,
-			"Unknown GSM 04.08 discriminator 0x%02x: %s\n",
-			pdisc, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
-		/* FIXME: return status message */
-		break;
-	}
-
-	/* MMCTX can be invalid */
-
-	return rc;
-}
-
-int gprs_gmm_rx_suspend(struct gprs_ra_id *raid, uint32_t tlli)
-{
-	struct sgsn_mm_ctx *mmctx;
-
-	mmctx = sgsn_mm_ctx_by_tlli(tlli, raid);
-	if (!mmctx) {
-		LOGP(DMM, LOGL_NOTICE, "SUSPEND request for unknown "
-			"TLLI=%08x\n", tlli);
-		return -EINVAL;
-	}
-
-	if (mmctx->gmm_state != GMM_REGISTERED_NORMAL &&
-	    mmctx->gmm_state != GMM_REGISTERED_SUSPENDED) {
-		LOGMMCTXP(LOGL_NOTICE, mmctx, "SUSPEND request while state "
-			"!= REGISTERED (TLLI=%08x)\n", tlli);
-		return -EINVAL;
-	}
-
-	/* Transition from REGISTERED_NORMAL to REGISTERED_SUSPENDED */
-	mmctx->gmm_state = GMM_REGISTERED_SUSPENDED;
-	return 0;
-}
-
-int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli,
-		       uint8_t suspend_ref)
-{
-	struct sgsn_mm_ctx *mmctx;
-
-	/* FIXME: make use of suspend reference? */
-
-	mmctx = sgsn_mm_ctx_by_tlli(tlli, raid);
-	if (!mmctx) {
-		LOGP(DMM, LOGL_NOTICE, "RESUME request for unknown "
-			"TLLI=%08x\n", tlli);
-		return -EINVAL;
-	}
-
-	if (mmctx->gmm_state != GMM_REGISTERED_NORMAL &&
-	    mmctx->gmm_state != GMM_REGISTERED_SUSPENDED) {
-		LOGMMCTXP(LOGL_NOTICE, mmctx, "RESUME request while state "
-			"!= SUSPENDED (TLLI=%08x)\n", tlli);
-		/* FIXME: should we not simply ignore it? */
-		return -EINVAL;
-	}
-
-	/* Transition from SUSPENDED to NORMAL */
-	mmctx->gmm_state = GMM_REGISTERED_NORMAL;
-	return 0;
-}
-
-#ifdef BUILD_IU
-int iu_rab_act_ps(uint8_t rab_id, struct sgsn_pdp_ctx *pdp)
-{
-	struct msgb *msg;
-	struct sgsn_mm_ctx *mm = pdp->mm;
-	struct ranap_ue_conn_ctx *uectx;
-	uint32_t ggsn_ip;
-	bool use_x213_nsap;
-
-	uectx = mm->iu.ue_ctx;
-	use_x213_nsap = (uectx->rab_assign_addr_enc == RANAP_NSAP_ADDR_ENC_X213);
-
-	/* Get the IP address for ggsn user plane */
-	memcpy(&ggsn_ip, pdp->lib->gsnru.v, pdp->lib->gsnru.l);
-	ggsn_ip = htonl(ggsn_ip);
-
-	LOGP(DRANAP, LOGL_DEBUG, "Assigning RAB: rab_id=%d, ggsn_ip=%x,"
-	     " teid_gn=%x, use_x213_nsap=%d\n",
-	     rab_id, ggsn_ip, pdp->lib->teid_gn, use_x213_nsap);
-
-	msg = ranap_new_msg_rab_assign_data(rab_id, ggsn_ip,
-					    pdp->lib->teid_gn, use_x213_nsap);
-	msg->l2h = msg->data;
-	return ranap_iu_rab_act(uectx, msg);
-}
-#endif
diff --git a/src/gprs/gprs_llc.c b/src/gprs/gprs_llc.c
deleted file mode 100644
index 2be663f..0000000
--- a/src/gprs/gprs_llc.c
+++ /dev/null
@@ -1,1132 +0,0 @@
-/* GPRS LLC protocol implementation as per 3GPP TS 04.64 */
-
-/* (C) 2009-2010 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/>.
- *
- */
-
-#include <errno.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-#include <openssl/rand.h>
-
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/timer.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/gprs/gprs_bssgp.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/debug.h>
-#include <openbsc/gprs_sgsn.h>
-#include <openbsc/gprs_gmm.h>
-#include <openbsc/gprs_llc.h>
-#include <openbsc/crc24.h>
-#include <openbsc/sgsn.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/gprs_llc_xid.h>
-#include <openbsc/gprs_sndcp_comp.h>
-#include <openbsc/gprs_sndcp.h>
-
-static struct gprs_llc_llme *llme_alloc(uint32_t tlli);
-static int gprs_llc_tx_xid(struct gprs_llc_lle *lle, struct msgb *msg,
-			   int command);
-static int gprs_llc_tx_u(struct msgb *msg, uint8_t sapi,
-			 int command, enum gprs_llc_u_cmd u_cmd, int pf_bit);
-
-/* BEGIN XID RELATED */
-
-/* Generate XID message */
-static int gprs_llc_generate_xid(uint8_t *bytes, int bytes_len,
-				 struct gprs_llc_xid_field *l3_xid_field,
-				 struct gprs_llc_llme *llme)
-{
-	/* Note: Called by gprs_ll_xid_req() */
-
-	LLIST_HEAD(xid_fields);
-
-	struct gprs_llc_xid_field xid_version;
-	struct gprs_llc_xid_field xid_n201u;
-	struct gprs_llc_xid_field xid_n201i;
-
-	xid_version.type = GPRS_LLC_XID_T_VERSION;
-	xid_version.data = (uint8_t *) "\x00";
-	xid_version.data_len = 1;
-
-	xid_n201u.type = GPRS_LLC_XID_T_N201_U;
-	xid_n201u.data = (uint8_t *) "\x05\xf0";
-	xid_n201u.data_len = 2;
-
-	xid_n201i.type = GPRS_LLC_XID_T_N201_I;
-	xid_n201i.data = (uint8_t *) "\x05\xf0";
-	xid_n201i.data_len = 2;
-
-	/* Add locally managed XID Fields */
-	llist_add(&xid_version.list, &xid_fields);
-	llist_add(&xid_n201u.list, &xid_fields);
-	llist_add(&xid_n201i.list, &xid_fields);
-
-	/* Append layer 3 XID field (if present) */
-	if (l3_xid_field) {
-		/* Enforce layer 3 XID type (just to be sure) */
-		l3_xid_field->type = GPRS_LLC_XID_T_L3_PAR;
-
-		/* Add Layer 3 XID field to the list */
-		llist_add(&l3_xid_field->list, &xid_fields);
-	}
-
-	/* Store generated XID for later reference */
-	talloc_free(llme->xid);
-	llme->xid = gprs_llc_copy_xid(llme, &xid_fields);
-
-	return gprs_llc_compile_xid(bytes, bytes_len, &xid_fields);
-}
-
-/* Generate XID message that will cause the GMM to reset */
-static int gprs_llc_generate_xid_for_gmm_reset(uint8_t *bytes,
-					       int bytes_len, uint32_t iov_ui,
-					       struct gprs_llc_llme *llme)
-{
-	/* Called by gprs_llgmm_reset() and
-	 * gprs_llgmm_reset_oldmsg() */
-
-	LLIST_HEAD(xid_fields);
-
-	struct gprs_llc_xid_field xid_reset;
-	struct gprs_llc_xid_field xid_iovui;
-
-	/* First XID component must be RESET */
-	xid_reset.type = GPRS_LLC_XID_T_RESET;
-	xid_reset.data = NULL;
-	xid_reset.data_len = 0;
-
-	/* Add new IOV-UI */
-	xid_iovui.type = GPRS_LLC_XID_T_IOV_UI;
-	xid_iovui.data = (uint8_t *) & iov_ui;
-	xid_iovui.data_len = 4;
-
-	/* Add locally managed XID Fields */
-	llist_add(&xid_iovui.list, &xid_fields);
-	llist_add(&xid_reset.list, &xid_fields);
-
-	/* Store generated XID for later reference */
-	talloc_free(llme->xid);
-	llme->xid = gprs_llc_copy_xid(llme, &xid_fields);
-
-	return gprs_llc_compile_xid(bytes, bytes_len, &xid_fields);
-}
-
-/* Process an incoming XID confirmation */
-static int gprs_llc_process_xid_conf(uint8_t *bytes, int bytes_len,
-				     struct gprs_llc_lle *lle)
-{
-	/* Note: This function handles the response of a network originated
-	 * XID-Request. There XID messages reflected by the MS are analyzed
-	 * and processed here. The caller is called by rx_llc_xid(). */
-
-	struct llist_head *xid_fields;
-	struct gprs_llc_xid_field *xid_field;
-	struct gprs_llc_xid_field *xid_field_request;
-	struct gprs_llc_xid_field *xid_field_request_l3 = NULL;
-
-	/* Pick layer3 XID from the XID request we have sent last */
-	if (lle->llme->xid) {
-		llist_for_each_entry(xid_field_request, lle->llme->xid, list) {
-			if (xid_field_request->type == GPRS_LLC_XID_T_L3_PAR)
-				xid_field_request_l3 = xid_field_request;
-		}
-	}
-
-	/* Parse and analyze XID-Response */
-	xid_fields = gprs_llc_parse_xid(NULL, bytes, bytes_len);
-
-	if (xid_fields) {
-
-		gprs_llc_dump_xid_fields(xid_fields, LOGL_DEBUG);
-		llist_for_each_entry(xid_field, xid_fields, list) {
-
-			/* Forward SNDCP-XID fields to Layer 3 (SNDCP) */
-			if (xid_field->type == GPRS_LLC_XID_T_L3_PAR &&
-			    xid_field_request_l3) {
-				sndcp_sn_xid_conf(xid_field,
-						  xid_field_request_l3, lle);
-			}
-
-			/* Process LLC-XID fields: */
-			else {
-
-				/* FIXME: Do something more useful with the
-				 * echoed XID-Information. Currently we
-				 * just ignore the response completely and
-				 * by doing so we blindly accept any changes
-				 * the MS might have done to the our XID
-				 * inquiry. There is a remainig risk of
-				 * malfunction! */
-				LOGP(DLLC, LOGL_NOTICE,
-				     "Ignoring XID-Field: XID: type %s, data_len=%d, data=%s\n",
-				     get_value_string(gprs_llc_xid_type_names,
-						      xid_field->type),
-				     xid_field->data_len,
-				     osmo_hexdump_nospc(xid_field->data,
-				     xid_field->data_len));
-			}
-		}
-		talloc_free(xid_fields);
-	}
-
-	/* Flush pending XID fields */
-	talloc_free(lle->llme->xid);
-	lle->llme->xid = NULL;
-
-	return 0;
-}
-
-/* Process an incoming XID indication and generate an appropiate response */
-static int gprs_llc_process_xid_ind(uint8_t *bytes_request,
-				    int bytes_request_len,
-				    uint8_t *bytes_response,
-				    int bytes_response_maxlen,
-				    struct gprs_llc_lle *lle)
-{
-	/* Note: This function computes the response that is sent back to the
-	 * MS when a mobile originated XID is received. The function is
-	 * called by rx_llc_xid() */
-
-	int rc = -EINVAL;
-
-	struct llist_head *xid_fields;
-	struct llist_head *xid_fields_response;
-
-	struct gprs_llc_xid_field *xid_field;
-	struct gprs_llc_xid_field *xid_field_response;
-
-	/* Parse and analyze XID-Request */
-	xid_fields =
-	    gprs_llc_parse_xid(lle->llme, bytes_request, bytes_request_len);
-	if (xid_fields) {
-		xid_fields_response = talloc_zero(lle->llme, struct llist_head);
-		INIT_LLIST_HEAD(xid_fields_response);
-		gprs_llc_dump_xid_fields(xid_fields, LOGL_DEBUG);
-
-		/* Process LLC-XID fields: */
-		llist_for_each_entry(xid_field, xid_fields, list) {
-
-			if (xid_field->type != GPRS_LLC_XID_T_L3_PAR) {
-				/* FIXME: Check the incoming XID parameters for
-				 * for validity. Currently we just blindly
-				 * accept all XID fields by just echoing them.
-				 * There is a remaining risk of malfunction
-				 * when a MS submits values which defer from
-				 * the default! */
-				LOGP(DLLC, LOGL_NOTICE,
-				     "Echoing XID-Field: XID: type %s, data_len=%d, data=%s\n",
-				     get_value_string(gprs_llc_xid_type_names,
-						      xid_field->type),
-				     xid_field->data_len,
-				     osmo_hexdump_nospc(xid_field->data,
-							xid_field->data_len));
-				xid_field_response =
-				    gprs_llc_dup_xid_field
-				    (lle->llme, xid_field);
-				llist_add(&xid_field_response->list,
-					  xid_fields_response);
-			}
-		}
-
-		/* Forward SNDCP-XID fields to Layer 3 (SNDCP) */
-		llist_for_each_entry(xid_field, xid_fields, list) {
-			if (xid_field->type == GPRS_LLC_XID_T_L3_PAR) {
-
-				xid_field_response =
-				    talloc_zero(lle->llme,
-						struct gprs_llc_xid_field);
-				rc = sndcp_sn_xid_ind(xid_field,
-						      xid_field_response, lle);
-				if (rc == 0)
-					llist_add(&xid_field_response->list,
-						  xid_fields_response);
-				else
-					talloc_free(xid_field_response);
-			}
-		}
-
-		rc = gprs_llc_compile_xid(bytes_response,
-					  bytes_response_maxlen,
-					  xid_fields_response);
-		talloc_free(xid_fields_response);
-		talloc_free(xid_fields);
-	}
-
-	return rc;
-}
-
-/* Dispatch XID indications and responses comming from the MS */
-static void rx_llc_xid(struct gprs_llc_lle *lle,
-		       struct gprs_llc_hdr_parsed *gph)
-{
-	uint8_t response[1024];
-	int response_len;
-
-	/* FIXME: 8.5.3.3: check if XID is invalid */
-	if (gph->is_cmd) {
-		LOGP(DLLC, LOGL_NOTICE,
-		     "Received XID indication from MS.\n");
-
-		struct msgb *resp;
-		uint8_t *xid;
-		resp = msgb_alloc_headroom(4096, 1024, "LLC_XID");
-
-		response_len =
-		    gprs_llc_process_xid_ind(gph->data, gph->data_len,
-					     response, sizeof(response),
-					     lle);
-		if (response_len < 0) {
-			LOGP(DLLC, LOGL_ERROR,
-			     "invalid XID indication received!\n");
-		} else {
-			xid = msgb_put(resp, response_len);
-			memcpy(xid, response, response_len);
-		}
-		gprs_llc_tx_xid(lle, resp, 0);
-	} else {
-		LOGP(DLLC, LOGL_NOTICE,
-		     "Received XID confirmation from MS.\n");
-		gprs_llc_process_xid_conf(gph->data, gph->data_len, lle);
-		/* FIXME: if we had sent a XID reset, send
-		 * LLGMM-RESET.conf to GMM */
-	}
-}
-
-/* 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)
-{
-	/* Note: This functions is calle from gprs_sndcp.c */
-
-	uint8_t xid_bytes[1024];;
-	int xid_bytes_len;
-	uint8_t *xid;
-	struct msgb *msg;
-	const char *ftype;
-
-	/* Generate XID */
-	xid_bytes_len =
-	    gprs_llc_generate_xid(xid_bytes, sizeof(xid_bytes),
-				  l3_xid_field, lle->llme);
-
-	/* Only perform XID sending if the XID message contains something */
-	if (xid_bytes_len > 0) {
-		/* Transmit XID bytes */
-		msg = msgb_alloc_headroom(4096, 1024, "LLC_XID");
-		xid = msgb_put(msg, xid_bytes_len);
-		memcpy(xid, xid_bytes, xid_bytes_len);
-		if (l3_xid_field)
-			ftype = get_value_string(gprs_llc_xid_type_names,
-						 l3_xid_field->type);
-		else
-			ftype = "NULL";
-		LOGP(DLLC, LOGL_NOTICE, "Sending XID type %s (%d bytes) request"
-		     " to MS...\n", ftype, xid_bytes_len);
-		gprs_llc_tx_xid(lle, msg, 1);
-	} else {
-		LOGP(DLLC, LOGL_ERROR,
-		     "XID-Message generation failed, XID not sent!\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-/* END XID RELATED */
-
-
-
-
-/* Entry function from upper level (LLC), asking us to transmit a BSSGP PDU
- * to a remote MS (identified by TLLI) at a BTS identified by its BVCI and NSEI */
-static int _bssgp_tx_dl_ud(struct msgb *msg, struct sgsn_mm_ctx *mmctx)
-{
-	struct bssgp_dl_ud_par dup;
-	const uint8_t qos_profile_default[3] = { 0x00, 0x00, 0x20 };
-
-	memset(&dup, 0, sizeof(dup));
-	/* before we have received some identity from the MS, we might
-	 * not yet have a MMC context (e.g. XID negotiation of primarly
-	 * LLC connection from GMM sapi). */
-	if (mmctx) {
-		dup.imsi = mmctx->imsi;
-		dup.drx_parms = mmctx->drx_parms;
-		dup.ms_ra_cap.len = mmctx->ms_radio_access_capa.len;
-		dup.ms_ra_cap.v = mmctx->ms_radio_access_capa.buf;
-
-		/* make sure we only send it to the right llme */
-		OSMO_ASSERT(msgb_tlli(msg) == mmctx->gb.llme->tlli
-				|| msgb_tlli(msg) == mmctx->gb.llme->old_tlli);
-	}
-	memcpy(&dup.qos_profile, qos_profile_default,
-		sizeof(qos_profile_default));
-
-	return bssgp_tx_dl_ud(msg, 1000, &dup);
-}
-
-
-/* Section 8.9.9 LLC layer parameter default values */
-static const struct gprs_llc_params llc_default_params[NUM_SAPIS] = {
-	[1] = {
-		.t200_201	= 5,
-		.n200		= 3,
-		.n201_u		= 400,
-	},
-	[2] = {
-		.t200_201	= 5,
-		.n200		= 3,
-		.n201_u		= 270,
-	},
-	[3] = {
-		.iov_i_exp	= 27,
-		.t200_201	= 5,
-		.n200		= 3,
-		.n201_u		= 500,
-		.n201_i		= 1503,
-		.mD		= 1520,
-		.mU		= 1520,
-		.kD		= 16,
-		.kU		= 16,
-	},
-	[5] = {
-		.iov_i_exp	= 27,
-		.t200_201	= 10,
-		.n200		= 3,
-		.n201_u		= 500,
-		.n201_i		= 1503,
-		.mD		= 760,
-		.mU		= 760,
-		.kD		= 8,
-		.kU		= 8,
-	},
-	[7] = {
-		.t200_201	= 20,
-		.n200		= 3,
-		.n201_u		= 270,
-	},
-	[8] = {
-		.t200_201	= 20,
-		.n200		= 3,
-		.n201_u		= 270,
-	},
-	[9] = {
-		.iov_i_exp	= 27,
-		.t200_201	= 20,
-		.n200		= 3,
-		.n201_u		= 500,
-		.n201_i		= 1503,
-		.mD		= 380,
-		.mU		= 380,
-		.kD		= 4,
-		.kU		= 4,
-	},
-	[11] = {
-		.iov_i_exp	= 27,
-		.t200_201	= 40,
-		.n200		= 3,
-		.n201_u		= 500,
-		.n201_i		= 1503,
-		.mD		= 190,
-		.mU		= 190,
-		.kD		= 2,
-		.kU		= 2,
-	},
-};
-
-LLIST_HEAD(gprs_llc_llmes);
-void *llc_tall_ctx;
-
-/* lookup LLC Entity based on DLCI (TLLI+SAPI tuple) */
-static struct gprs_llc_lle *lle_by_tlli_sapi(const uint32_t tlli, uint8_t sapi)
-{
-	struct gprs_llc_llme *llme;
-
-	llist_for_each_entry(llme, &gprs_llc_llmes, list) {
-		if (llme->tlli == tlli || llme->old_tlli == tlli)
-			return &llme->lle[sapi];
-	}
-	return NULL;
-}
-
-struct gprs_llc_lle *gprs_lle_get_or_create(const uint32_t tlli, uint8_t sapi)
-{
-	struct gprs_llc_llme *llme;
-	struct gprs_llc_lle *lle;
-
-	lle = lle_by_tlli_sapi(tlli, sapi);
-	if (lle)
-		return lle;
-
-	LOGP(DLLC, LOGL_NOTICE, "LLC: unknown TLLI 0x%08x, "
-		"creating LLME on the fly\n", tlli);
-	llme = llme_alloc(tlli);
-	lle = &llme->lle[sapi];
-	return lle;
-}
-
-struct llist_head *gprs_llme_list(void)
-{
-	return &gprs_llc_llmes;
-}
-
-/* lookup LLC Entity for RX based on DLCI (TLLI+SAPI tuple) */
-static struct gprs_llc_lle *lle_for_rx_by_tlli_sapi(const uint32_t tlli,
-					uint8_t sapi, enum gprs_llc_cmd cmd)
-{
-	struct gprs_llc_lle *lle;
-
-	/* We already know about this TLLI */
-	lle = lle_by_tlli_sapi(tlli, sapi);
-	if (lle)
-		return lle;
-
-	/* Maybe it is a routing area update but we already know this sapi? */
-	if (gprs_tlli_type(tlli) == TLLI_FOREIGN) {
-		lle = lle_by_tlli_sapi(tlli, sapi);
-		if (lle) {
-			LOGP(DLLC, LOGL_NOTICE,
-				"LLC RX: Found a local entry for TLLI 0x%08x\n",
-				tlli);
-			return lle;
-		}
-	}
-
-	/* 7.2.1.1 LLC belonging to unassigned TLLI+SAPI shall be discarded,
-	 * except UID and XID frames with SAPI=1 */
-	if (sapi == GPRS_SAPI_GMM &&
-		    (cmd == GPRS_LLC_XID || cmd == GPRS_LLC_UI)) {
-		struct gprs_llc_llme *llme;
-		/* FIXME: don't use the TLLI but the 0xFFFF unassigned? */
-		llme = llme_alloc(tlli);
-		LOGP(DLLC, LOGL_NOTICE, "LLC RX: unknown TLLI 0x%08x, "
-			"creating LLME on the fly\n", tlli);
-		lle = &llme->lle[sapi];
-		return lle;
-	}
-	
-	LOGP(DLLC, LOGL_NOTICE,
-		"unknown TLLI(0x%08x)/SAPI(%d): Silently dropping\n",
-		tlli, sapi);
-	return NULL;
-}
-
-static void lle_init(struct gprs_llc_llme *llme, uint8_t sapi)
-{
-	struct gprs_llc_lle *lle = &llme->lle[sapi];
-
-	lle->llme = llme;
-	lle->sapi = sapi;
-	lle->state = GPRS_LLES_UNASSIGNED;
-
-	/* Initialize according to parameters */
-	memcpy(&lle->params, &llc_default_params[sapi], sizeof(lle->params));
-}
-
-static struct gprs_llc_llme *llme_alloc(uint32_t tlli)
-{
-	struct gprs_llc_llme *llme;
-	uint32_t i;
-
-	llme = talloc_zero(llc_tall_ctx, struct gprs_llc_llme);
-	if (!llme)
-		return NULL;
-
-	llme->tlli = tlli;
-	llme->old_tlli = 0xffffffff;
-	llme->state = GPRS_LLMS_UNASSIGNED;
-	llme->age_timestamp = GPRS_LLME_RESET_AGE;
-	llme->cksn = GSM_KEY_SEQ_INVAL;
-
-	for (i = 0; i < ARRAY_SIZE(llme->lle); i++)
-		lle_init(llme, i);
-
-	llist_add(&llme->list, &gprs_llc_llmes);
-
-	llme->comp.proto = gprs_sndcp_comp_alloc(llme);
-	llme->comp.data = gprs_sndcp_comp_alloc(llme);
-
-	return llme;
-}
-
-static void llme_free(struct gprs_llc_llme *llme)
-{
-	gprs_sndcp_comp_free(llme->comp.proto);
-	gprs_sndcp_comp_free(llme->comp.data);
-	talloc_free(llme->xid);
-	llist_del(&llme->list);
-	talloc_free(llme);
-}
-
-#if 0
-/* FIXME: Unused code... */
-static void t200_expired(void *data)
-{
-	struct gprs_llc_lle *lle = data;
-
-	/* 8.5.1.3: Expiry of T200 */
-
-	if (lle->retrans_ctr >= lle->params.n200) {
-		/* FIXME: LLGM-STATUS-IND, LL-RELEASE-IND/CNF */
-		lle->state = GPRS_LLES_ASSIGNED_ADM;
-	}
-
-	switch (lle->state) {
-	case GPRS_LLES_LOCAL_EST:
-		/* FIXME: retransmit SABM */
-		/* FIXME: re-start T200 */
-		lle->retrans_ctr++;
-		break;
-	case GPRS_LLES_LOCAL_REL:
-		/* FIXME: retransmit DISC */
-		/* FIXME: re-start T200 */
-		lle->retrans_ctr++;
-		break;
-	default:
-		LOGP(DLLC, LOGL_ERROR, "LLC unhandled state: %d\n", lle->state);
-		break;
-	}
-
-}
-
-static void t201_expired(void *data)
-{
-	struct gprs_llc_lle *lle = data;
-
-	if (lle->retrans_ctr < lle->params.n200) {
-		/* FIXME: transmit apropriate supervisory frame (8.6.4.1) */
-		/* FIXME: set timer T201 */
-		lle->retrans_ctr++;
-	}
-}
-#endif
-
-int gprs_llc_tx_u(struct msgb *msg, uint8_t sapi, int command,
-		  enum gprs_llc_u_cmd u_cmd, int pf_bit)
-{
-	uint8_t *fcs, *llch;
-	uint8_t addr, ctrl;
-	uint32_t fcs_calc;
-
-	/* Identifiers from UP: (TLLI, SAPI) + (BVCI, NSEI) */
-
-	/* Address Field */
-	addr = sapi & 0xf;
-	if (command)
-		addr |= 0x40;
-
-	/* 6.3 Figure 8 */
-	ctrl = 0xe0 | u_cmd;
-	if (pf_bit)
-		ctrl |= 0x10;
-
-	/* prepend LLC UI header */
-	llch = msgb_push(msg, 2);
-	llch[0] = addr;
-	llch[1] = ctrl;
-
-	/* append FCS to end of frame */
-	fcs = msgb_put(msg, 3);
-	fcs_calc = gprs_llc_fcs(llch, fcs - llch);
-	fcs[0] = fcs_calc & 0xff;
-	fcs[1] = (fcs_calc >> 8) & 0xff;
-	fcs[2] = (fcs_calc >> 16) & 0xff;
-
-	/* Identifiers passed down: (BVCI, NSEI) */
-
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_LLC_DL_PACKETS]);
-	rate_ctr_add(&sgsn->rate_ctrs->ctr[CTR_LLC_DL_BYTES], msg->len);
-
-	/* Send BSSGP-DL-UNITDATA.req */
-	return _bssgp_tx_dl_ud(msg, NULL);
-}
-
-/* Send XID response to LLE */
-static int gprs_llc_tx_xid(struct gprs_llc_lle *lle, struct msgb *msg,
-			   int command)
-{
-	/* copy identifiers from LLE to ensure lower layers can route */
-	msgb_tlli(msg) = lle->llme->tlli;
-	msgb_bvci(msg) = lle->llme->bvci;
-	msgb_nsei(msg) = lle->llme->nsei;
-
-	return gprs_llc_tx_u(msg, lle->sapi, command, GPRS_LLC_U_XID, 1);
-}
-
-/* encrypt information field + FCS, if needed! */
-static int apply_gea(struct gprs_llc_lle *lle, uint16_t crypt_len, uint16_t nu,
-		     uint32_t oc, uint8_t sapi, uint8_t *fcs, uint8_t *data)
-{
-	uint8_t cipher_out[GSM0464_CIPH_MAX_BLOCK];
-
-	if (lle->llme->algo == GPRS_ALGO_GEA0)
-		return -EINVAL;
-
-	/* Compute the 'Input' Paraemeter */
-	uint32_t fcs_calc, iv = gprs_cipher_gen_input_ui(lle->llme->iov_ui, sapi,
-							 nu, oc);
-	/* Compute gamma that we need to XOR with the data */
-	int r = gprs_cipher_run(cipher_out, crypt_len, lle->llme->algo,
-				lle->llme->kc, iv,
-				fcs ? GPRS_CIPH_SGSN2MS : GPRS_CIPH_MS2SGSN);
-	if (r < 0) {
-		LOGP(DLLC, LOGL_ERROR, "Error producing %s gamma for UI "
-		     "frame: %d\n", get_value_string(gprs_cipher_names,
-						     lle->llme->algo), r);
-		return -ENOMSG;
-	}
-
-	if (fcs) {
-		/* Mark frame as encrypted and update FCS */
-		data[2] |= 0x02;
-		fcs_calc = gprs_llc_fcs(data, fcs - data);
-		fcs[0] = fcs_calc & 0xff;
-		fcs[1] = (fcs_calc >> 8) & 0xff;
-		fcs[2] = (fcs_calc >> 16) & 0xff;
-		data += 3;
-	}
-
-	/* XOR the cipher output with the data */
-	for (r = 0; r < crypt_len; r++)
-		*(data + r) ^= cipher_out[r];
-
-	return 0;
-}
-
-/* Transmit a UI frame over the given SAPI:
-   'encryptable' indicates whether particular message can be encrypted according
-   to 3GPP TS 24.008 § 4.7.1.2
- */
-int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command,
-		   struct sgsn_mm_ctx *mmctx, bool encryptable)
-{
-	struct gprs_llc_lle *lle;
-	uint8_t *fcs, *llch;
-	uint8_t addr, ctrl[2];
-	uint32_t fcs_calc;
-	uint16_t nu = 0;
-	uint32_t oc;
-
-	/* Identifiers from UP: (TLLI, SAPI) + (BVCI, NSEI) */
-
-	/* look-up or create the LL Entity for this (TLLI, SAPI) tuple */
-	lle = gprs_lle_get_or_create(msgb_tlli(msg), sapi);
-
-	if (msg->len > lle->params.n201_u) {
-		LOGP(DLLC, LOGL_ERROR, "Cannot Tx %u bytes (N201-U=%u)\n",
-			msg->len, lle->params.n201_u);
-		msgb_free(msg);
-		return -EFBIG;
-	}
-
-	gprs_llme_copy_key(mmctx, lle->llme);
-
-	/* Update LLE's (BVCI, NSEI) tuple */
-	lle->llme->bvci = msgb_bvci(msg);
-	lle->llme->nsei = msgb_nsei(msg);
-
-	/* Obtain current values for N(u) and OC */
-	nu = lle->vu_send;
-	oc = lle->oc_ui_send;
-	/* Increment V(U) */
-	lle->vu_send = (lle->vu_send + 1) % 512;
-	/* Increment Overflow Counter, if needed */
-	if ((lle->vu_send + 1) / 512)
-		lle->oc_ui_send += 512;
-
-	/* Address Field */
-	addr = sapi & 0xf;
-	if (command)
-		addr |= 0x40;
-
-	/* Control Field */
-	ctrl[0] = 0xc0;
-	ctrl[0] |= nu >> 6;
-	ctrl[1] = (nu << 2) & 0xfc;
-	ctrl[1] |= 0x01; /* Protected Mode */
-
-	/* prepend LLC UI header */
-	llch = msgb_push(msg, 3);
-	llch[0] = addr;
-	llch[1] = ctrl[0];
-	llch[2] = ctrl[1];
-
-	/* append FCS to end of frame */
-	fcs = msgb_put(msg, 3);
-	fcs_calc = gprs_llc_fcs(llch, fcs - llch);
-	fcs[0] = fcs_calc & 0xff;
-	fcs[1] = (fcs_calc >> 8) & 0xff;
-	fcs[2] = (fcs_calc >> 16) & 0xff;
-
-	if (lle->llme->algo != GPRS_ALGO_GEA0 && encryptable) {
-		int rc = apply_gea(lle, fcs - llch, nu, oc, sapi, fcs, llch);
-		if (rc < 0) {
-			msgb_free(msg);
-			return rc;
-		}
-	}
-
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_LLC_DL_PACKETS]);
-	rate_ctr_add(&sgsn->rate_ctrs->ctr[CTR_LLC_DL_BYTES], msg->len);
-
-	/* Identifiers passed down: (BVCI, NSEI) */
-
-	/* Send BSSGP-DL-UNITDATA.req */
-	return _bssgp_tx_dl_ud(msg, mmctx);
-}
-
-static int gprs_llc_hdr_rx(struct gprs_llc_hdr_parsed *gph,
-			   struct gprs_llc_lle *lle)
-{
-	switch (gph->cmd) {
-	case GPRS_LLC_SABM: /* Section 6.4.1.1 */
-		lle->v_sent = lle->v_ack = lle->v_recv = 0;
-		if (lle->state == GPRS_LLES_ASSIGNED_ADM) {
-			/* start re-establishment (8.7.1) */
-		}
-		lle->state = GPRS_LLES_REMOTE_EST;
-		/* FIXME: Send UA */
-		lle->state = GPRS_LLES_ABM;
-		/* FIXME: process data */
-		break;
-	case GPRS_LLC_DISC: /* Section 6.4.1.2 */
-		/* FIXME: Send UA */
-		/* terminate ABM */
-		lle->state = GPRS_LLES_ASSIGNED_ADM;
-		break;
-	case GPRS_LLC_UA: /* Section 6.4.1.3 */
-		if (lle->state == GPRS_LLES_LOCAL_EST)
-			lle->state = GPRS_LLES_ABM;
-		break;
-	case GPRS_LLC_DM: /* Section 6.4.1.4: ABM cannot be performed */
-		if (lle->state == GPRS_LLES_LOCAL_EST)
-			lle->state = GPRS_LLES_ASSIGNED_ADM;
-		break;
-	case GPRS_LLC_FRMR: /* Section 6.4.1.5 */
-		break;
-	case GPRS_LLC_XID: /* Section 6.4.1.6 */
-		rx_llc_xid(lle, gph);
-		break;
-	case GPRS_LLC_UI:
-		if (gprs_llc_is_retransmit(gph->seq_tx, lle->vu_recv)) {
-			LOGP(DLLC, LOGL_NOTICE,
-				"TLLI=%08x dropping UI, N(U=%d) not in window V(URV(UR:%d).\n",
-				lle->llme ? lle->llme->tlli : -1,
-				gph->seq_tx, lle->vu_recv);
-
-			/* HACK: non-standard recovery handling.  If remote LLE
-			 * is re-transmitting the same sequence number for
-			 * three times, don't discard the frame but pass it on
-			 * and 'learn' the new sequence number */
-			if (gph->seq_tx != lle->vu_recv_last) {
-				lle->vu_recv_last = gph->seq_tx;
-				lle->vu_recv_duplicates = 0;
-			} else {
-				lle->vu_recv_duplicates++;
-				if (lle->vu_recv_duplicates < 3)
-					return -EIO;
-				LOGP(DLLC, LOGL_NOTICE, "TLLI=%08x recovering "
-				     "N(U=%d) after receiving %u duplicates\n",
-					lle->llme ? lle->llme->tlli : -1,
-					gph->seq_tx, lle->vu_recv_duplicates);
-			}
-		}
-		/* Increment the sequence number that we expect in the next frame */
-		lle->vu_recv = (gph->seq_tx + 1) % 512;
-		/* Increment Overflow Counter */
-		if ((gph->seq_tx + 1) / 512)
-			lle->oc_ui_recv += 512;
-		break;
-	default:
-		LOGP(DLLC, LOGL_NOTICE, "Unhandled command: %d\n", gph->cmd);
-		break;
-	}
-
-	return 0;
-}
-
-/* receive an incoming LLC PDU (BSSGP-UL-UNITDATA-IND, 7.2.4.2) */
-int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv)
-{
-	struct gprs_llc_hdr *lh = (struct gprs_llc_hdr *) msgb_llch(msg);
-	struct gprs_llc_hdr_parsed llhp;
-	struct gprs_llc_lle *lle = NULL;
-	bool drop_cipherable = false;
-	int rc = 0;
-
-	/* Identifiers from DOWN: NSEI, BVCI, TLLI */
-
-	memset(&llhp, 0, sizeof(llhp));
-	rc = gprs_llc_hdr_parse(&llhp, (uint8_t *) lh, TLVP_LEN(tv, BSSGP_IE_LLC_PDU));
-	if (rc < 0) {
-		LOGP(DLLC, LOGL_NOTICE, "Error during LLC header parsing\n");
-		return rc;
-	}
-
-	switch (gprs_tlli_type(msgb_tlli(msg))) {
-	case TLLI_LOCAL:
-	case TLLI_FOREIGN:
-	case TLLI_RANDOM:
-	case TLLI_AUXILIARY:
-		break;
-	default:
-		LOGP(DLLC, LOGL_ERROR,
-			"Discarding frame with strange TLLI type\n");
-		break;
-	}
-
-	/* find the LLC Entity for this TLLI+SAPI tuple */
-	lle = lle_for_rx_by_tlli_sapi(msgb_tlli(msg), llhp.sapi, llhp.cmd);
-	if (!lle) {
-		switch (llhp.sapi) {
-		case GPRS_SAPI_SNDCP3:
-		case GPRS_SAPI_SNDCP5:
-		case GPRS_SAPI_SNDCP9:
-		case GPRS_SAPI_SNDCP11:
-			/* Ask an upper layer for help. */
-			return gsm0408_gprs_force_reattach_oldmsg(msg, NULL);
-		default:
-			break;
-		}
-		return 0;
-	}
-	gprs_llc_hdr_dump(&llhp, lle);
-	/* reset age computation */
-	lle->llme->age_timestamp = GPRS_LLME_RESET_AGE;
-
-	/* decrypt information field + FCS, if needed! */
-	if (llhp.is_encrypted) {
-		if (lle->llme->algo != GPRS_ALGO_GEA0) {
-			rc = apply_gea(lle, llhp.data_len + 3, llhp.seq_tx,
-				       lle->oc_ui_recv, lle->sapi, NULL,
-				       llhp.data);
-			if (rc < 0)
-				return rc;
-		llhp.fcs = *(llhp.data + llhp.data_len);
-		llhp.fcs |= *(llhp.data + llhp.data_len + 1) << 8;
-		llhp.fcs |= *(llhp.data + llhp.data_len + 2) << 16;
-		} else {
-			LOGP(DLLC, LOGL_NOTICE, "encrypted frame for LLC that "
-				"has no KC/Algo! Dropping.\n");
-			return 0;
-		}
-	} else {
-		if (lle->llme->algo != GPRS_ALGO_GEA0 &&
-		    lle->llme->cksn != GSM_KEY_SEQ_INVAL)
-			drop_cipherable = true;
-	}
-
-	/* We have to do the FCS check _after_ decryption */
-	llhp.fcs_calc = gprs_llc_fcs((uint8_t *)lh, llhp.crc_length);
-	if (llhp.fcs != llhp.fcs_calc) {
-		LOGP(DLLC, LOGL_INFO, "Dropping frame with invalid FCS\n");
-		return -EIO;
-	}
-
-	/* Update LLE's (BVCI, NSEI) tuple */
-	lle->llme->bvci = msgb_bvci(msg);
-	lle->llme->nsei = msgb_nsei(msg);
-
-	/* Receive and Process the actual LLC frame */
-	rc = gprs_llc_hdr_rx(&llhp, lle);
-	if (rc < 0)
-		return rc;
-
-	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_LLC_UL_PACKETS]);
-	rate_ctr_add(&sgsn->rate_ctrs->ctr[CTR_LLC_UL_BYTES], msg->len);
-
-	/* llhp.data is only set when we need to send LL_[UNIT]DATA_IND up */
-	if (llhp.cmd == GPRS_LLC_UI && llhp.data && llhp.data_len) {
-		msgb_gmmh(msg) = llhp.data;
-		switch (llhp.sapi) {
-		case GPRS_SAPI_GMM:
-			/* send LL_UNITDATA_IND to GMM */
-			rc = gsm0408_gprs_rcvmsg_gb(msg, lle->llme,
-						    drop_cipherable);
-			break;
-		case GPRS_SAPI_SNDCP3:
-		case GPRS_SAPI_SNDCP5:
-		case GPRS_SAPI_SNDCP9:
-		case GPRS_SAPI_SNDCP11:
-			/* send LL_DATA_IND/LL_UNITDATA_IND to SNDCP */
-			rc = sndcp_llunitdata_ind(msg, lle, llhp.data, llhp.data_len);
-			break;
-		case GPRS_SAPI_SMS:
-			/* FIXME */
-		case GPRS_SAPI_TOM2:
-		case GPRS_SAPI_TOM8:
-			/* FIXME: send LL_DATA_IND/LL_UNITDATA_IND to TOM */
-		default:
-			LOGP(DLLC, LOGL_NOTICE, "Unsupported SAPI %u\n", llhp.sapi);
-			rc = -EINVAL;
-			break;
-		}
-	}
-
-	return rc;
-}
-
-/* Propagate crypto parameters MM -> LLME */
-void gprs_llme_copy_key(struct sgsn_mm_ctx *mm, struct gprs_llc_llme *llme)
-{
-	if (!mm)
-		return;
-	if (mm->ciph_algo != GPRS_ALGO_GEA0) {
-		llme->algo = mm->ciph_algo;
-		if (llme->cksn != mm->auth_triplet.key_seq &&
-		    mm->auth_triplet.key_seq != GSM_KEY_SEQ_INVAL) {
-			memcpy(llme->kc, mm->auth_triplet.vec.kc,
-			       gprs_cipher_key_length(mm->ciph_algo));
-			llme->cksn = mm->auth_triplet.key_seq;
-		}
-	} else
-		llme->cksn = GSM_KEY_SEQ_INVAL;
-}
-
-/* 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)
-{
-	unsigned int i;
-
-	if (old_tlli == 0xffffffff && new_tlli != 0xffffffff) {
-		/* TLLI Assignment 8.3.1 */
-		/* New TLLI shall be assigned and used when (re)transmitting LLC frames */
-		/* If old TLLI != 0xffffffff was assigned to LLME, then TLLI
-		 * old is unassigned.  Only TLLI new shall be accepted when
-		 * received from peer. */
-		if (llme->old_tlli != 0xffffffff) {
-			llme->old_tlli = 0xffffffff;
-			llme->tlli = new_tlli;
-		} else {
-			/* If TLLI old == 0xffffffff was assigned to LLME, then this is
-			 * TLLI assignmemt according to 8.3.1 */
-			llme->old_tlli = 0xffffffff;
-			llme->tlli = new_tlli;
-			llme->state = GPRS_LLMS_ASSIGNED;
-			/* 8.5.3.1 For all LLE's */
-			for (i = 0; i < ARRAY_SIZE(llme->lle); i++) {
-				struct gprs_llc_lle *l = &llme->lle[i];
-				l->vu_send = l->vu_recv = 0;
-				l->retrans_ctr = 0;
-				l->state = GPRS_LLES_ASSIGNED_ADM;
-				/* FIXME Set parameters according to table 9 */
-			}
-		}
-	} else if (old_tlli != 0xffffffff && new_tlli != 0xffffffff) {
-		/* TLLI Change 8.3.2 */
-		/* Both TLLI Old and TLLI New are assigned; use New when
-		 * (re)transmitting.  Accept both Old and New on Rx */
-		llme->old_tlli = old_tlli;
-		llme->tlli = new_tlli;
-		llme->state = GPRS_LLMS_ASSIGNED;
-	} else if (old_tlli != 0xffffffff && new_tlli == 0xffffffff) {
-		/* TLLI Unassignment 8.3.3) */
-		llme->tlli = llme->old_tlli = 0;
-		llme->state = GPRS_LLMS_UNASSIGNED;
-		for (i = 0; i < ARRAY_SIZE(llme->lle); i++) {
-			struct gprs_llc_lle *l = &llme->lle[i];
-			l->state = GPRS_LLES_UNASSIGNED;
-		}
-		llme_free(llme);
-	} else
-		return -EINVAL;
-
-	return 0;
-}
-
-/* TLLI unassignment */
-int gprs_llgmm_unassign(struct gprs_llc_llme *llme)
-{
-	return gprs_llgmm_assign(llme, llme->tlli, 0xffffffff);
-}
-
-/* Chapter 7.2.1.2 LLGMM-RESET.req */
-int gprs_llgmm_reset(struct gprs_llc_llme *llme)
-{
-	struct msgb *msg = msgb_alloc_headroom(4096, 1024, "LLC_XID");
-	struct gprs_llc_lle *lle = &llme->lle[1];
-	uint8_t xid_bytes[1024];
-	int xid_bytes_len;
-	uint8_t *xid;
-
-	LOGP(DLLC, LOGL_NOTICE, "LLGM Reset\n");
-	if (RAND_bytes((uint8_t *) &llme->iov_ui, 4) != 1) {
-		LOGP(DLLC, LOGL_NOTICE, "RAND_bytes failed for LLC XID reset, "
-		     "falling back to rand()\n");
-		llme->iov_ui = rand();
-	}
-
-	/* Generate XID message */
-	xid_bytes_len = gprs_llc_generate_xid_for_gmm_reset(xid_bytes,
-					sizeof(xid_bytes),llme->iov_ui,llme);
-	if (xid_bytes_len < 0)
-		return -EINVAL;
-	xid = msgb_put(msg, xid_bytes_len);
-	memcpy(xid, xid_bytes, xid_bytes_len);
-
-	/* Reset some of the LLC parameters. See GSM 04.64, 8.5.3.1 */
-	lle->vu_recv = 0;
-	lle->vu_send = 0;
-	lle->oc_ui_send = 0;
-	lle->oc_ui_recv = 0;
-
-	/* FIXME: Start T200, wait for XID response */
-	return gprs_llc_tx_xid(lle, msg, 1);
-}
-
-int gprs_llgmm_reset_oldmsg(struct msgb* oldmsg, uint8_t sapi,
-			    struct gprs_llc_llme *llme)
-{
-	struct msgb *msg = msgb_alloc_headroom(4096, 1024, "LLC_XID");
-	uint8_t xid_bytes[1024];
-	int xid_bytes_len;
-	uint8_t *xid;
-
-	LOGP(DLLC, LOGL_NOTICE, "LLGM Reset\n");
-	if (RAND_bytes((uint8_t *) &llme->iov_ui, 4) != 1) {
-		LOGP(DLLC, LOGL_NOTICE, "RAND_bytes failed for LLC XID reset, "
-		     "falling back to rand()\n");
-		llme->iov_ui = rand();
-	}
-
-	/* Generate XID message */
-	xid_bytes_len = gprs_llc_generate_xid_for_gmm_reset(xid_bytes,
-					sizeof(xid_bytes),llme->iov_ui,llme);
-	if (xid_bytes_len < 0)
-		return -EINVAL;
-	xid = msgb_put(msg, xid_bytes_len);
-	memcpy(xid, xid_bytes, xid_bytes_len);
-
-	/* FIXME: Start T200, wait for XID response */
-
-	msgb_tlli(msg) = msgb_tlli(oldmsg);
-	msgb_bvci(msg) = msgb_bvci(oldmsg);
-	msgb_nsei(msg) = msgb_nsei(oldmsg);
-
-	return gprs_llc_tx_u(msg, sapi, 1, GPRS_LLC_U_XID, 1);
-}
-
-int gprs_llc_init(const char *cipher_plugin_path)
-{
-	return gprs_cipher_load(cipher_plugin_path);
-}
diff --git a/src/gprs/gprs_llc_parse.c b/src/gprs/gprs_llc_parse.c
deleted file mode 100644
index a5a7a71..0000000
--- a/src/gprs/gprs_llc_parse.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/* GPRS LLC protocol implementation as per 3GPP TS 04.64 */
-
-/* (C) 2009-2010 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/>.
- *
- */
-
-#include <errno.h>
-#include <stdint.h>
-
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/timer.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/gprs/gprs_bssgp.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/debug.h>
-#include <openbsc/gprs_sgsn.h>
-#include <openbsc/gprs_gmm.h>
-#include <openbsc/gprs_llc.h>
-#include <openbsc/crc24.h>
-
-static const struct value_string llc_cmd_strs[] = {
-	{ GPRS_LLC_NULL,	"NULL" },
-	{ GPRS_LLC_RR,		"RR" },
-	{ GPRS_LLC_ACK,		"ACK" },
-	{ GPRS_LLC_RNR,		"RNR" },
-	{ GPRS_LLC_SACK,	"SACK" },
-	{ GPRS_LLC_DM,		"DM" },
-	{ GPRS_LLC_DISC,	"DISC" },
-	{ GPRS_LLC_UA,		"UA" },
-	{ GPRS_LLC_SABM,	"SABM" },
-	{ GPRS_LLC_FRMR,	"FRMR" },
-	{ GPRS_LLC_XID,		"XID" },
-	{ GPRS_LLC_UI,		"UI" },
-	{ 0, NULL }
-};
-
-#define LLC_ALLOC_SIZE 16384
-#define UI_HDR_LEN	3
-#define N202		4
-#define CRC24_LENGTH	3
-
-int gprs_llc_fcs(uint8_t *data, unsigned int len)
-{
-	uint32_t fcs_calc;
-
-	fcs_calc = crc24_calc(INIT_CRC24, data, len);
-	fcs_calc = ~fcs_calc;
-	fcs_calc &= 0xffffff;
-
-	return fcs_calc;
-}
-
-void gprs_llc_hdr_dump(struct gprs_llc_hdr_parsed *gph, struct gprs_llc_lle *lle)
-{
-	const char *gea;
-	uint32_t iov_ui = 0;
-	if (lle) {
-		gea = get_value_string(gprs_cipher_names, lle->llme->algo);
-		iov_ui = lle->llme->iov_ui;
-	} else
-		gea = "GEA?";
-	DEBUGP(DLLC, "LLC SAPI=%u %c %c %c %s IOV-UI=0x%06x FCS=0x%06x ",
-	       gph->sapi, gph->is_cmd ? 'C' : 'R', gph->ack_req ? 'A' : ' ',
-	       gph->is_encrypted ? 'E' : 'U',
-	       gea, iov_ui, gph->fcs);
-
-	if (gph->cmd)
-		DEBUGPC(DLLC, "CMD=%s ", get_value_string(llc_cmd_strs, gph->cmd));
-
-	if (gph->data)
-		DEBUGPC(DLLC, "DATA ");
-
-	DEBUGPC(DLLC, "\n");
-}
-
-/* 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)
-{
-	uint8_t *ctrl = llc_hdr+1;
-
-	if (len <= CRC24_LENGTH)
-		return -EIO;
-
-	ghp->crc_length = len - CRC24_LENGTH;
-
-	ghp->ack_req = 0;
-
-	/* Section 5.5: FCS */
-	ghp->fcs = *(llc_hdr + len - 3);
-	ghp->fcs |= *(llc_hdr + len - 2) << 8;
-	ghp->fcs |= *(llc_hdr + len - 1) << 16;
-
-	/* Section 6.2.1: invalid PD field */
-	if (llc_hdr[0] & 0x80)
-		return -EIO;
-
-	/* This only works for the MS->SGSN direction */
-	if (llc_hdr[0] & 0x40)
-		ghp->is_cmd = 0;
-	else
-		ghp->is_cmd = 1;
-
-	ghp->sapi = llc_hdr[0] & 0xf;
-
-	/* Section 6.2.3: check for reserved SAPI */
-	switch (ghp->sapi) {
-	case 0:
-	case 4:
-	case 6:
-	case 0xa:
-	case 0xc:
-	case 0xd:
-	case 0xf:
-		return -EINVAL;
-	}
-
-	if ((ctrl[0] & 0x80) == 0) {
-		/* I (Information transfer + Supervisory) format */
-		uint8_t k;
-
-		ghp->data = ctrl + 3;
-
-		if (ctrl[0] & 0x40)
-			ghp->ack_req = 1;
-
-		ghp->seq_tx  = (ctrl[0] & 0x1f) << 4;
-		ghp->seq_tx |= (ctrl[1] >> 4);
-
-		ghp->seq_rx  = (ctrl[1] & 0x7) << 6;
-		ghp->seq_rx |= (ctrl[2] >> 2);
-
-		switch (ctrl[2] & 0x03) {
-		case 0:
-			ghp->cmd = GPRS_LLC_RR;
-			break;
-		case 1:
-			ghp->cmd = GPRS_LLC_ACK;
-			break;
-		case 2:
-			ghp->cmd = GPRS_LLC_RNR;
-			break;
-		case 3:
-			ghp->cmd = GPRS_LLC_SACK;
-			k = ctrl[3] & 0x1f;
-			ghp->data += 1 + k;
-			break;
-		}
-		ghp->data_len = (llc_hdr + len - 3) - ghp->data;
-	} else if ((ctrl[0] & 0xc0) == 0x80) {
-		/* S (Supervisory) format */
-		ghp->data = NULL;
-		ghp->data_len = 0;
-
-		if (ctrl[0] & 0x20)
-			ghp->ack_req = 1;
-		ghp->seq_rx  = (ctrl[0] & 0x7) << 6;
-		ghp->seq_rx |= (ctrl[1] >> 2);
-
-		switch (ctrl[1] & 0x03) {
-		case 0:
-			ghp->cmd = GPRS_LLC_RR;
-			break;
-		case 1:
-			ghp->cmd = GPRS_LLC_ACK;
-			break;
-		case 2:
-			ghp->cmd = GPRS_LLC_RNR;
-			break;
-		case 3:
-			ghp->cmd = GPRS_LLC_SACK;
-			break;
-		}
-	} else if ((ctrl[0] & 0xe0) == 0xc0) {
-		/* UI (Unconfirmed Inforamtion) format */
-		ghp->cmd = GPRS_LLC_UI;
-		ghp->data = ctrl + 2;
-		ghp->data_len = (llc_hdr + len - 3) - ghp->data;
-
-		ghp->seq_tx  = (ctrl[0] & 0x7) << 6;
-		ghp->seq_tx |= (ctrl[1] >> 2);
-		if (ctrl[1] & 0x02) {
-			ghp->is_encrypted = 1;
-			/* FIXME: encryption */
-		}
-		if (ctrl[1] & 0x01) {
-			/* FCS over hdr + all inf fields */
-		} else {
-			/* FCS over hdr + N202 octets (4) */
-			if (ghp->crc_length > UI_HDR_LEN + N202)
-				ghp->crc_length = UI_HDR_LEN + N202;
-		}
-	} else {
-		/* U (Unnumbered) format: 1 1 1 P/F M4 M3 M2 M1 */
-		ghp->data = NULL;
-		ghp->data_len = 0;
-
-		switch (ctrl[0] & 0xf) {
-		case GPRS_LLC_U_NULL_CMD:
-			ghp->cmd = GPRS_LLC_NULL;
-			break;
-		case GPRS_LLC_U_DM_RESP:
-			ghp->cmd = GPRS_LLC_DM;
-			break;
-		case GPRS_LLC_U_DISC_CMD:
-			ghp->cmd = GPRS_LLC_DISC;
-			break;
-		case GPRS_LLC_U_UA_RESP:
-			ghp->cmd = GPRS_LLC_UA;
-			break;
-		case GPRS_LLC_U_SABM_CMD:
-			ghp->cmd = GPRS_LLC_SABM;
-			break;
-		case GPRS_LLC_U_FRMR_RESP:
-			ghp->cmd = GPRS_LLC_FRMR;
-			break;
-		case GPRS_LLC_U_XID:
-			ghp->cmd = GPRS_LLC_XID;
-			ghp->data = ctrl + 1;
-			ghp->data_len = (llc_hdr + len - 3) - ghp->data;
-			break;
-		default:
-			return -EIO;
-		}
-	}
-
-	/* FIXME: parse sack frame */
-	if (ghp->cmd == GPRS_LLC_SACK) {
-		LOGP(DLLC, LOGL_NOTICE, "Unsupported SACK frame\n");
-		return -EIO;
-	}
-
-	return 0;
-}
diff --git a/src/gprs/gprs_llc_vty.c b/src/gprs/gprs_llc_vty.c
deleted file mode 100644
index bf34e97..0000000
--- a/src/gprs/gprs_llc_vty.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/* VTY interface for our GPRS LLC implementation */
-
-/* (C) 2010 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/>.
- *
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdint.h>
-#include <time.h>
-
-#include <arpa/inet.h>
-
-#include <openbsc/gsm_data.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/rate_ctr.h>
-#include <openbsc/debug.h>
-#include <openbsc/signal.h>
-#include <openbsc/gprs_llc.h>
-
-#include <osmocom/vty/vty.h>
-#include <osmocom/vty/command.h>
-
-struct value_string gprs_llc_state_strs[] = {
-	{ GPRS_LLES_UNASSIGNED, 	"TLLI Unassigned" },
-	{ GPRS_LLES_ASSIGNED_ADM,	"TLLI Assigned" },
-	{ GPRS_LLES_LOCAL_EST,		"Local Establishment" },
-	{ GPRS_LLES_REMOTE_EST,		"Remote Establishment" },
-	{ GPRS_LLES_ABM,		"Asynchronous Balanced Mode" },
-	{ GPRS_LLES_LOCAL_REL,		"Local Release" },
-	{ GPRS_LLES_TIMER_REC,		"Timer Recovery" },
-	{ 0, NULL }
-};
-
-static void vty_dump_lle(struct vty *vty, struct gprs_llc_lle *lle)
-{
-	struct gprs_llc_params *par = &lle->params;
-	vty_out(vty, " SAPI %2u State %s VUsend=%u, VUrecv=%u", lle->sapi, 
-		get_value_string(gprs_llc_state_strs, lle->state),
-		lle->vu_send, lle->vu_recv);
-	vty_out(vty, " Vsent=%u Vack=%u Vrecv=%u, RetransCtr=%u%s",
-		lle->v_sent, lle->v_ack, lle->v_recv,
-		lle->retrans_ctr, VTY_NEWLINE);
-	vty_out(vty, "  T200=%u, N200=%u, N201-U=%u, N201-I=%u, mD=%u, "
-		"mU=%u, kD=%u, kU=%u%s", par->t200_201, par->n200,
-		par->n201_u, par->n201_i, par->mD, par->mU, par->kD,
-		par->kU, VTY_NEWLINE);
-}
-
-static uint8_t valid_sapis[] = { 1, 2, 3, 5, 7, 8, 9, 11 };
-
-static void vty_dump_llme(struct vty *vty, struct gprs_llc_llme *llme)
-{
-	unsigned int i;
-	struct timespec now_tp = {0};
-	clock_gettime(CLOCK_MONOTONIC, &now_tp);
-
-	vty_out(vty, "TLLI %08x (Old TLLI %08x) BVCI=%u NSEI=%u %s: "
-		"IOV-UI=0x%06x CKSN=%d Age=%d: State %s%s", llme->tlli,
-		llme->old_tlli, llme->bvci, llme->nsei,
-		get_value_string(gprs_cipher_names, llme->algo), llme->iov_ui,
-		llme->cksn, llme->age_timestamp == GPRS_LLME_RESET_AGE ? 0 :
-		(int)(now_tp.tv_sec - (time_t)llme->age_timestamp),
-		get_value_string(gprs_llc_state_strs, llme->state), VTY_NEWLINE);
-
-	for (i = 0; i < ARRAY_SIZE(valid_sapis); i++) {
-		struct gprs_llc_lle *lle;
-		uint8_t sapi = valid_sapis[i];
-
-		if (sapi >= ARRAY_SIZE(llme->lle))
-			continue;
-
-		lle = &llme->lle[sapi];
-		vty_dump_lle(vty, lle);
-	}
-}
-
-
-DEFUN(show_llc, show_llc_cmd,
-	"show llc",
-	SHOW_STR "Display information about the LLC protocol")
-{
-	struct gprs_llc_llme *llme;
-
-	vty_out(vty, "State of LLC Entities%s", VTY_NEWLINE);
-	llist_for_each_entry(llme, &gprs_llc_llmes, list) {
-		vty_dump_llme(vty, llme);
-	}
-	return CMD_SUCCESS;
-}
-
-int gprs_llc_vty_init(void)
-{
-	install_element_ve(&show_llc_cmd);
-
-	return 0;
-}
diff --git a/src/gprs/gprs_llc_xid.c b/src/gprs/gprs_llc_xid.c
deleted file mode 100644
index fe63171..0000000
--- a/src/gprs/gprs_llc_xid.c
+++ /dev/null
@@ -1,281 +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/>.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <errno.h>
-
-#include <osmocom/core/utils.h>
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/talloc.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/gprs_llc.h>
-#include <openbsc/sgsn.h>
-#include <openbsc/gprs_llc_xid.h>
-
-const struct value_string gprs_llc_xid_type_names[] = {
-	{ GPRS_LLC_XID_T_VERSION,	"VERSION"},
-	{ GPRS_LLC_XID_T_IOV_UI,	"IOV_UI"},
-	{ GPRS_LLC_XID_T_IOV_I,		"IOV_I"},
-	{ GPRS_LLC_XID_T_T200,		"T200"},
-	{ GPRS_LLC_XID_T_N200,		"N200"},
-	{ GPRS_LLC_XID_T_N201_U,	"N201_"},
-	{ GPRS_LLC_XID_T_N201_I,	"N201_I"},
-	{ GPRS_LLC_XID_T_mD,		"mD"},
-	{ GPRS_LLC_XID_T_mU,		"mU"},
-	{ GPRS_LLC_XID_T_kD,		"kD"},
-	{ GPRS_LLC_XID_T_kU,		"kU"},
-	{ GPRS_LLC_XID_T_L3_PAR,	"L3_PAR"},
-	{ GPRS_LLC_XID_T_RESET,		"RESET"},
-	{ 0, NULL },
-};
-
-/* Parse XID parameter field */
-static int decode_xid_field(struct gprs_llc_xid_field *xid_field,
-			    const uint8_t *src, uint8_t src_len)
-{
-	uint8_t xl;
-	uint8_t type;
-	uint8_t len;
-	int src_counter = 0;
-
-	/* Exit immediately if it is clear that no
-	 * parseable data is present */
-	if (src_len < 1 || !src)
-		return -EINVAL;
-
-	/* Extract header info */
-	xl = (*src >> 7) & 1;
-	type = (*src >> 2) & 0x1F;
-
-	/* Extract length field */
-	len = (*src) & 0x3;
-	src++;
-	src_counter++;
-	if (xl) {
-		if (src_len < 2)
-			return -EINVAL;
-		len = (len << 6) & 0xC0;
-		len |= ((*src) >> 2) & 0x3F;
-		src++;
-		src_counter++;
-	}
-
-	/* Fill out struct */
-	xid_field->type = type;
-	xid_field->data_len = len;
-	if (len > 0) {
-		if (src_len < src_counter + len)
-			return -EINVAL;
-		xid_field->data =
-			talloc_memdup(xid_field,src,xid_field->data_len);
-	} else
-		xid_field->data = NULL;
-
-	/* Return consumed length */
-	return src_counter + len;
-}
-
-/* Encode XID parameter field */
-static int encode_xid_field(uint8_t *dst, int dst_maxlen,
-			    const struct gprs_llc_xid_field *xid_field)
-{
-	int xl = 0;
-
-	/* When the length does not fit into 2 bits,
-	 * we need extended length fields */
-	if (xid_field->data_len > 3)
-		xl = 1;
-
-	/* Exit immediately if it is clear that no
-	 * encoding result can be stored */
-	if (dst_maxlen < xid_field->data_len + 1 + xl)
-		return -EINVAL;
-
-	/* There are only 5 bits reserved for the type, exit on exceed */
-	if (xid_field->type > 31)
-		return -EINVAL;
-
-	/* Encode header */
-	memset(dst, 0, dst_maxlen);
-	if (xl)
-		dst[0] |= 0x80;
-	dst[0] |= (((xid_field->type) & 0x1F) << 2);
-
-	if (xl) {
-		dst[0] |= (((xid_field->data_len) >> 6) & 0x03);
-		dst[1] = ((xid_field->data_len) << 2) & 0xFC;
-	} else
-		dst[0] |= ((xid_field->data_len) & 0x03);
-
-	/* Append payload data */
-	if (xid_field->data && xid_field->data_len)
-		memcpy(dst + 1 + xl, xid_field->data, xid_field->data_len);
-
-	/* Return generated length */
-	return xid_field->data_len + 1 + xl;
-}
-
-/* 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)
-{
-	struct gprs_llc_xid_field *xid_field;
-	int rc;
-	int byte_counter = 0;
-
-	OSMO_ASSERT(xid_fields);
-	OSMO_ASSERT(dst);
-
-	llist_for_each_entry_reverse(xid_field, xid_fields, list) {
-		/* Encode XID-Field */
-		rc = encode_xid_field(dst, dst_maxlen, xid_field);
-		if (rc < 0)
-			return -EINVAL;
-
-		/* Advance pointer and lower maxlen for the
-		 * next encoding round */
-		dst += rc;
-		byte_counter += rc;
-		dst_maxlen -= rc;
-	}
-
-	/* Return generated length */
-	return byte_counter;
-}
-
-/* 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)
-{
-	struct gprs_llc_xid_field *xid_field;
-	struct llist_head *xid_fields;
-
-	int rc;
-	int max_loops = src_len;
-
-	OSMO_ASSERT(src);
-
-	xid_fields = talloc_zero(ctx, struct llist_head);
-	INIT_LLIST_HEAD(xid_fields);
-
-	while (1) {
-		/* Bail in case decode_xid_field() constantly returns zero */
-		if (max_loops <= 0) {
-			talloc_free(xid_fields);
-			return NULL;
-		}
-
-		/* Decode XID field */
-		xid_field = talloc_zero(xid_fields, struct gprs_llc_xid_field);
-		rc = decode_xid_field(xid_field, src, src_len);
-
-		/* Immediately stop on error */
-		if (rc < 0) {
-			talloc_free(xid_fields);
-			return NULL;
-		}
-
-		/* Add parsed XID field to list */
-		llist_add(&xid_field->list, xid_fields);
-
-		/* Advance pointer and lower dst_len for the next
-		 * decoding round */
-		src += rc;
-		src_len -= rc;
-
-		/* We are (scuccessfully) done when no further byes are left */
-		if (src_len == 0)
-			return xid_fields;
-
-		max_loops--;
-	}
-}
-
-/* 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)
-{
-	struct gprs_llc_xid_field *dup;
-
-	OSMO_ASSERT(xid_field);
-
-	/* Create a copy of the XID field in memory */
-	dup = talloc_memdup(ctx, xid_field, sizeof(*xid_field));
-	dup->data = talloc_memdup(ctx, xid_field->data, xid_field->data_len);
-
-	/* Unlink duplicate from source list */
-	INIT_LLIST_HEAD(&dup->list);
-
-	return dup;
-}
-
-/* Copy an llist with xid fields */
-struct llist_head *gprs_llc_copy_xid(const void *ctx,
-				     const struct llist_head *xid_fields)
-{
-	struct gprs_llc_xid_field *xid_field;
-	struct llist_head *xid_fields_copy;
-
-	OSMO_ASSERT(xid_fields);
-
-	xid_fields_copy = talloc_zero(ctx, struct llist_head);
-	INIT_LLIST_HEAD(xid_fields_copy);
-
-	/* Create duplicates and add them to the target list */
-	llist_for_each_entry(xid_field, xid_fields, list) {
-		llist_add(&gprs_llc_dup_xid_field(ctx, xid_field)->list,
-			  xid_fields_copy);
-	}
-
-	return xid_fields_copy;
-}
-
-/* Dump a list with XID fields (Debug) */
-void gprs_llc_dump_xid_fields(const struct llist_head *xid_fields,
-			      unsigned int logl)
-{
-	struct gprs_llc_xid_field *xid_field;
-
-	OSMO_ASSERT(xid_fields);
-
-	llist_for_each_entry(xid_field, xid_fields, list) {
-		if (xid_field->data_len) {
-			OSMO_ASSERT(xid_field->data);
-			LOGP(DLLC, logl,
-			     "XID: type %s, data_len=%d, data=%s\n",
-			     get_value_string(gprs_llc_xid_type_names,
-					      xid_field->type),
-			     xid_field->data_len,
-			     osmo_hexdump_nospc(xid_field->data,
-						xid_field->data_len));
-		} else {
-			LOGP(DLLC, logl,
-			     "XID: type=%d, data_len=%d, data=NULL\n",
-			     xid_field->type, xid_field->data_len);
-		}
-	}
-}
diff --git a/src/gprs/gprs_sgsn.c b/src/gprs/gprs_sgsn.c
deleted file mode 100644
index de79afb..0000000
--- a/src/gprs/gprs_sgsn.c
+++ /dev/null
@@ -1,933 +0,0 @@
-/* GPRS SGSN functionality */
-
-/* (C) 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/>.
- *
- */
-
-#include <stdint.h>
-
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/timer.h>
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/core/stats.h>
-#include <osmocom/core/backtrace.h>
-#include <osmocom/gprs/gprs_ns.h>
-#include <osmocom/gprs/gprs_bssgp.h>
-#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
-#include <osmocom/gsm/apn.h>
-
-#include <openbsc/gprs_subscriber.h>
-#include <openbsc/debug.h>
-#include <openbsc/gprs_sgsn.h>
-#include <openbsc/sgsn.h>
-#include <openbsc/gprs_gmm.h>
-#include <openbsc/gprs_utils.h>
-#include <openbsc/signal.h>
-#include "openbsc/gprs_llc.h"
-
-#include <pdp.h>
-
-#include <time.h>
-
-#include <openssl/rand.h>
-
-#include "../../bscconfig.h"
-
-#if BUILD_IU
-#include <osmocom/ranap/iu_client.h>
-#endif
-
-#define GPRS_LLME_CHECK_TICK 30
-
-extern struct sgsn_instance *sgsn;
-
-LLIST_HEAD(sgsn_mm_ctxts);
-LLIST_HEAD(sgsn_ggsn_ctxts);
-LLIST_HEAD(sgsn_apn_ctxts);
-LLIST_HEAD(sgsn_pdp_ctxts);
-
-static const struct rate_ctr_desc mmctx_ctr_description[] = {
-	{ "sign.packets.in",	"Signalling Messages ( In)" },
-	{ "sign.packets.out",	"Signalling Messages (Out)" },
-	{ "udata.packets.in",	"User Data  Messages ( In)" },
-	{ "udata.packets.out",	"User Data  Messages (Out)" },
-	{ "udata.bytes.in",	"User Data  Bytes    ( In)" },
-	{ "udata.bytes.out",	"User Data  Bytes    (Out)" },
-	{ "pdp_ctx_act",	"PDP Context Activations  " },
-	{ "suspend",		"SUSPEND Count            " },
-	{ "paging.ps",		"Paging Packet Switched   " },
-	{ "paging.cs",		"Paging Circuit Switched  " },
-	{ "ra_update",		"Routing Area Update      " },
-};
-
-static const struct rate_ctr_group_desc mmctx_ctrg_desc = {
-	.group_name_prefix = "sgsn.mmctx",
-	.group_description = "SGSN MM Context Statistics",
-	.num_ctr = ARRAY_SIZE(mmctx_ctr_description),
-	.ctr_desc = mmctx_ctr_description,
-	.class_id = OSMO_STATS_CLASS_SUBSCRIBER,
-};
-
-static const struct rate_ctr_desc pdpctx_ctr_description[] = {
-	{ "udata.packets.in",	"User Data  Messages ( In)" },
-	{ "udata.packets.out",	"User Data  Messages (Out)" },
-	{ "udata.bytes.in",	"User Data  Bytes    ( In)" },
-	{ "udata.bytes.out",	"User Data  Bytes    (Out)" },
-};
-
-static const struct rate_ctr_group_desc pdpctx_ctrg_desc = {
-	.group_name_prefix = "sgsn.pdpctx",
-	.group_description = "SGSN PDP Context Statistics",
-	.num_ctr = ARRAY_SIZE(pdpctx_ctr_description),
-	.ctr_desc = pdpctx_ctr_description,
-	.class_id = OSMO_STATS_CLASS_SUBSCRIBER,
-};
-
-static const struct rate_ctr_desc sgsn_ctr_description[] = {
-	{ "llc.dl_bytes", "Count sent LLC bytes before giving it to the bssgp layer" },
-	{ "llc.ul_bytes", "Count sucessful received LLC bytes (encrypt & fcs correct)" },
-	{ "llc.dl_packets", "Count sucessful sent LLC packets before giving it to the bssgp layer" },
-	{ "llc.ul_packets", "Count sucessful received LLC packets (encrypt & fcs correct)" },
-	{ "gprs.attach_requested", "Received attach requests" },
-	{ "gprs.attach_accepted", "Sent attach accepts" },
-	{ "gprs.attach_rejected", "Sent attach rejects" },
-	{ "gprs.detach_requested", "Received detach requests" },
-	{ "gprs.detach_acked", "Sent detach acks" },
-	{ "gprs.routing_area_requested", "Received routing area requests" },
-	{ "gprs.routing_area_requested", "Sent routing area acks" },
-	{ "gprs.routing_area_requested", "Sent routing area rejects" },
-	{ "pdp.activate_requested", "Received activate requests" },
-	{ "pdp.activate_rejected", "Sent activate rejects" },
-	{ "pdp.activate_accepted", "Sent activate accepts" },
-	{ "pdp.request_activated", "unused" },
-	{ "pdp.request_activate_rejected", "unused" },
-	{ "pdp.modify_requested", "unused" },
-	{ "pdp.modify_accepted", "unused" },
-	{ "pdp.dl_deactivate_requested", "Sent deactivate requests" },
-	{ "pdp.dl_deactivate_accepted", "Sent deactivate accepted" },
-	{ "pdp.ul_deactivate_requested", "Received deactivate requests" },
-	{ "pdp.ul_deactivate_accepted", "Received deactivate accepts" },
-};
-
-static const struct rate_ctr_group_desc sgsn_ctrg_desc = {
-	"sgsn",
-	"SGSN Overall Statistics",
-	OSMO_STATS_CLASS_GLOBAL,
-	ARRAY_SIZE(sgsn_ctr_description),
-	sgsn_ctr_description,
-};
-
-void sgsn_rate_ctr_init() {
-	sgsn->rate_ctrs = rate_ctr_group_alloc(tall_bsc_ctx, &sgsn_ctrg_desc, 0);
-	OSMO_ASSERT(sgsn->rate_ctrs);
-}
-
-/* look-up an SGSN MM context based on Iu UE context (struct ue_conn_ctx)*/
-struct sgsn_mm_ctx *sgsn_mm_ctx_by_ue_ctx(const void *uectx)
-{
-	struct sgsn_mm_ctx *ctx;
-
-	llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
-		if (ctx->ran_type == MM_CTX_T_UTRAN_Iu
-		    && uectx == ctx->iu.ue_ctx)
-			return ctx;
-	}
-
-	return NULL;
-}
-
-/* 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 *ctx;
-
-	llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
-		if ((tlli == ctx->gb.tlli || tlli == ctx->gb.tlli_new) &&
-		    gprs_ra_id_equals(raid, &ctx->ra))
-			return ctx;
-	}
-
-	return NULL;
-}
-
-struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli_and_ptmsi(uint32_t tlli,
-					const struct gprs_ra_id *raid)
-{
-	struct sgsn_mm_ctx *ctx;
-	int tlli_type;
-
-	/* TODO: Also check the P_TMSI signature to be safe. That signature
-	 * should be different (at least with a sufficiently high probability)
-	 * after SGSN restarts and for multiple SGSN instances.
-	 */
-
-	tlli_type = gprs_tlli_type(tlli);
-	if (tlli_type != TLLI_FOREIGN && tlli_type != TLLI_LOCAL)
-		return NULL;
-
-	llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
-		if ((gprs_tmsi2tlli(ctx->p_tmsi, tlli_type) == tlli ||
-		     gprs_tmsi2tlli(ctx->p_tmsi_old, tlli_type) == tlli) &&
-		    gprs_ra_id_equals(raid, &ctx->ra))
-			return ctx;
-	}
-
-	return NULL;
-}
-
-struct sgsn_mm_ctx *sgsn_mm_ctx_by_ptmsi(uint32_t p_tmsi)
-{
-	struct sgsn_mm_ctx *ctx;
-
-	llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
-		if (p_tmsi == ctx->p_tmsi ||
-		    (ctx->p_tmsi_old && ctx->p_tmsi_old == p_tmsi))
-			return ctx;
-	}
-	return NULL;
-}
-
-struct sgsn_mm_ctx *sgsn_mm_ctx_by_imsi(const char *imsi)
-{
-	struct sgsn_mm_ctx *ctx;
-
-	llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
-		if (!strcmp(imsi, ctx->imsi))
-			return ctx;
-	}
-	return NULL;
-
-}
-
-/* Allocate a new SGSN MM context for GERAN_Gb */
-struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_gb(uint32_t tlli,
-					const struct gprs_ra_id *raid)
-{
-	struct sgsn_mm_ctx *ctx;
-
-	ctx = talloc_zero(tall_bsc_ctx, struct sgsn_mm_ctx);
-	if (!ctx)
-		return NULL;
-
-	memcpy(&ctx->ra, raid, sizeof(ctx->ra));
-	ctx->ran_type = MM_CTX_T_GERAN_Gb;
-	ctx->gb.tlli = tlli;
-	ctx->gmm_state = GMM_DEREGISTERED;
-	ctx->pmm_state = MM_IDLE;
-	ctx->auth_triplet.key_seq = GSM_KEY_SEQ_INVAL;
-	ctx->ciph_algo = sgsn->cfg.cipher;
-	LOGMMCTXP(LOGL_DEBUG, ctx, "Allocated with %s cipher.\n",
-		  get_value_string(gprs_cipher_names, ctx->ciph_algo));
-	ctx->ctrg = rate_ctr_group_alloc(ctx, &mmctx_ctrg_desc, tlli);
-	if (!ctx->ctrg) {
-		LOGMMCTXP(LOGL_ERROR, ctx, "Cannot allocate counter group\n");
-		talloc_free(ctx);
-		return NULL;
-	}
-	INIT_LLIST_HEAD(&ctx->pdp_list);
-
-	llist_add(&ctx->list, &sgsn_mm_ctxts);
-
-	return ctx;
-}
-
-/* Allocate a new SGSN MM context */
-struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_iu(void *uectx)
-{
-#if BUILD_IU
-	struct sgsn_mm_ctx *ctx;
-
-	ctx = talloc_zero(tall_bsc_ctx, struct sgsn_mm_ctx);
-	if (!ctx)
-		return NULL;
-
-	ctx->ran_type = MM_CTX_T_UTRAN_Iu;
-	ctx->iu.ue_ctx = uectx;
-	ctx->iu.ue_ctx->rab_assign_addr_enc = sgsn->cfg.iu.rab_assign_addr_enc;
-	ctx->iu.new_key = 1;
-	ctx->gmm_state = GMM_DEREGISTERED;
-	ctx->pmm_state = PMM_DETACHED;
-	ctx->auth_triplet.key_seq = GSM_KEY_SEQ_INVAL;
-	ctx->ctrg = rate_ctr_group_alloc(ctx, &mmctx_ctrg_desc, 0);
-	if (!ctx->ctrg) {
-		LOGMMCTXP(LOGL_ERROR, ctx, "Cannot allocate counter group\n");
-		talloc_free(ctx);
-		return NULL;
-	}
-
-	/* Need to get RAID from IU conn */
-	ctx->ra = ctx->iu.ue_ctx->ra_id;
-
-	INIT_LLIST_HEAD(&ctx->pdp_list);
-
-	llist_add(&ctx->list, &sgsn_mm_ctxts);
-
-	return ctx;
-#else
-	return NULL;
-#endif
-}
-
-
-/* this is a hard _free_ function, it doesn't clean up the PDP contexts
- * in libgtp! */
-static void sgsn_mm_ctx_free(struct sgsn_mm_ctx *mm)
-{
-	struct sgsn_pdp_ctx *pdp, *pdp2;
-
-	/* Unlink from global list of MM contexts */
-	llist_del(&mm->list);
-
-	/* Free all PDP contexts */
-	llist_for_each_entry_safe(pdp, pdp2, &mm->pdp_list, list)
-		sgsn_pdp_ctx_free(pdp);
-
-	rate_ctr_group_free(mm->ctrg);
-
-	talloc_free(mm);
-}
-
-void sgsn_mm_ctx_cleanup_free(struct sgsn_mm_ctx *mm)
-{
-	struct gprs_llc_llme *llme = NULL;
-	uint32_t tlli = mm->gb.tlli;
-	struct sgsn_pdp_ctx *pdp, *pdp2;
-	struct sgsn_signal_data sig_data;
-
-	if (mm->ran_type == MM_CTX_T_GERAN_Gb)
-		llme = mm->gb.llme;
-	else
-		OSMO_ASSERT(mm->gb.llme == NULL);
-
-	/* Forget about ongoing look-ups */
-	if (mm->ggsn_lookup) {
-		LOGMMCTXP(LOGL_NOTICE, mm,
-			"Cleaning mmctx with on-going query.\n");
-		mm->ggsn_lookup->mmctx = NULL;
-		mm->ggsn_lookup = NULL;
-	}
-
-	/* delete all existing PDP contexts for this MS */
-	llist_for_each_entry_safe(pdp, pdp2, &mm->pdp_list, list) {
-		LOGMMCTXP(LOGL_NOTICE, mm,
-			  "Dropping PDP context for NSAPI=%u\n", pdp->nsapi);
-		sgsn_pdp_ctx_terminate(pdp);
-	}
-
-	if (osmo_timer_pending(&mm->timer)) {
-		LOGMMCTXP(LOGL_INFO, mm, "Cancelling MM timer %u\n", mm->T);
-		osmo_timer_del(&mm->timer);
-	}
-
-	memset(&sig_data, 0, sizeof(sig_data));
-	sig_data.mm = mm;
-	osmo_signal_dispatch(SS_SGSN, S_SGSN_MM_FREE, &sig_data);
-
-
-	/* Detach from subscriber which is possibly freed then */
-	if (mm->subscr) {
-		struct gprs_subscr *subscr = gprs_subscr_get(mm->subscr);
-		gprs_subscr_cleanup(subscr);
-		gprs_subscr_put(subscr);
-	}
-
-	sgsn_mm_ctx_free(mm);
-	mm = NULL;
-
-	if (llme) {
-		/* TLLI unassignment, must be called after sgsn_mm_ctx_free */
-		gprs_llgmm_assign(llme, tlli, 0xffffffff);
-	}
-}
-
-
-/* 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)
-{
-	struct sgsn_pdp_ctx *pdp;
-
-	llist_for_each_entry(pdp, &mm->pdp_list, list) {
-		if (pdp->nsapi == nsapi)
-			return pdp;
-	}
-	return NULL;
-}
-
-/* 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 *pdp;
-
-	llist_for_each_entry(pdp, &mm->pdp_list, list) {
-		if (pdp->ti == tid)
-			return pdp;
-	}
-	return NULL;
-}
-
-/* you don't want to use this directly, call sgsn_create_pdp_ctx() */
-struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
-					uint8_t nsapi)
-{
-	struct sgsn_pdp_ctx *pdp;
-
-	pdp = sgsn_pdp_ctx_by_nsapi(mm, nsapi);
-	if (pdp)
-		return NULL;
-
-	pdp = talloc_zero(tall_bsc_ctx, struct sgsn_pdp_ctx);
-	if (!pdp)
-		return NULL;
-
-	pdp->mm = mm;
-	pdp->nsapi = nsapi;
-	pdp->ctrg = rate_ctr_group_alloc(pdp, &pdpctx_ctrg_desc, nsapi);
-	if (!pdp->ctrg) {
-		LOGPDPCTXP(LOGL_ERROR, pdp, "Error allocation counter group\n");
-		talloc_free(pdp);
-		return NULL;
-	}
-	llist_add(&pdp->list, &mm->pdp_list);
-	llist_add(&pdp->g_list, &sgsn_pdp_ctxts);
-
-	return pdp;
-}
-
-/*
- * This function will not trigger any GSM DEACT PDP ACK messages, so you
- * probably want to call sgsn_delete_pdp_ctx() instead if the connection
- * isn't detached already.
- */
-void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp)
-{
-	struct sgsn_signal_data sig_data;
-
-	OSMO_ASSERT(pdp->mm != NULL);
-
-	/* There might still be pending callbacks in libgtp. So the parts of
-	 * this object relevant to GTP need to remain intact in this case. */
-
-	LOGPDPCTXP(LOGL_INFO, pdp, "Forcing release of PDP context\n");
-
-	if (pdp->mm->ran_type == MM_CTX_T_GERAN_Gb) {
-		/* Force the deactivation of the SNDCP layer */
-		sndcp_sm_deactivate_ind(&pdp->mm->gb.llme->lle[pdp->sapi], pdp->nsapi);
-	}
-
-	memset(&sig_data, 0, sizeof(sig_data));
-	sig_data.pdp = pdp;
-	osmo_signal_dispatch(SS_SGSN, S_SGSN_PDP_TERMINATE, &sig_data);
-
-	/* Detach from MM context */
-	llist_del(&pdp->list);
-	pdp->mm = NULL;
-
-	sgsn_delete_pdp_ctx(pdp);
-}
-
-/*
- * Don't call this function directly unless you know what you are doing.
- * In normal conditions use sgsn_delete_pdp_ctx and in unspecified or
- * implementation dependent abnormal ones sgsn_pdp_ctx_terminate.
- */
-void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp)
-{
-	struct sgsn_signal_data sig_data;
-
-	memset(&sig_data, 0, sizeof(sig_data));
-	sig_data.pdp = pdp;
-	osmo_signal_dispatch(SS_SGSN, S_SGSN_PDP_FREE, &sig_data);
-
-	rate_ctr_group_free(pdp->ctrg);
-	if (pdp->mm)
-		llist_del(&pdp->list);
-	llist_del(&pdp->g_list);
-
-	/* _if_ we still have a library handle, at least set it to NULL
-	 * to avoid any dereferences of the now-deleted PDP context from
-	 * sgsn_libgtp:cb_data_ind() */
-	if (pdp->lib) {
-		struct pdp_t *lib = pdp->lib;
-		LOGPDPCTXP(LOGL_NOTICE, pdp, "freeing PDP context that still "
-		     "has a libgtp handle attached to it, this shouldn't "
-		     "happen!\n");
-		osmo_generate_backtrace();
-		lib->priv = NULL;
-	}
-
-	if (pdp->destroy_ggsn)
-		sgsn_ggsn_ctx_free(pdp->ggsn);
-	talloc_free(pdp);
-}
-
-/* GGSN contexts */
-
-struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id)
-{
-	struct sgsn_ggsn_ctx *ggc;
-
-	ggc = talloc_zero(tall_bsc_ctx, struct sgsn_ggsn_ctx);
-	if (!ggc)
-		return NULL;
-
-	ggc->id = id;
-	ggc->gtp_version = 1;
-	ggc->remote_restart_ctr = -1;
-	/* if we are called from config file parse, this gsn doesn't exist yet */
-	ggc->gsn = sgsn->gsn;
-	llist_add(&ggc->list, &sgsn_ggsn_ctxts);
-
-	return ggc;
-}
-
-void sgsn_ggsn_ctx_free(struct sgsn_ggsn_ctx *ggc)
-{
-	llist_del(&ggc->list);
-	talloc_free(ggc);
-}
-
-struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(uint32_t id)
-{
-	struct sgsn_ggsn_ctx *ggc;
-
-	llist_for_each_entry(ggc, &sgsn_ggsn_ctxts, list) {
-		if (id == ggc->id)
-			return ggc;
-	}
-	return NULL;
-}
-
-struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct in_addr *addr)
-{
-	struct sgsn_ggsn_ctx *ggc;
-
-	llist_for_each_entry(ggc, &sgsn_ggsn_ctxts, list) {
-		if (!memcmp(addr, &ggc->remote_addr, sizeof(*addr)))
-			return ggc;
-	}
-	return NULL;
-}
-
-
-struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(uint32_t id)
-{
-	struct sgsn_ggsn_ctx *ggc;
-
-	ggc = sgsn_ggsn_ctx_by_id(id);
-	if (!ggc)
-		ggc = sgsn_ggsn_ctx_alloc(id);
-	return ggc;
-}
-
-/* APN contexts */
-
-static struct apn_ctx *sgsn_apn_ctx_alloc(const char *ap_name, const char *imsi_prefix)
-{
-	struct apn_ctx *actx;
-
-	actx = talloc_zero(tall_bsc_ctx, struct apn_ctx);
-	if (!actx)
-		return NULL;
-	actx->name = talloc_strdup(actx, ap_name);
-	actx->imsi_prefix = talloc_strdup(actx, imsi_prefix);
-
-	llist_add_tail(&actx->list, &sgsn_apn_ctxts);
-
-	return actx;
-}
-
-void sgsn_apn_ctx_free(struct apn_ctx *actx)
-{
-	llist_del(&actx->list);
-	talloc_free(actx);
-}
-
-struct apn_ctx *sgsn_apn_ctx_match(const char *name, const char *imsi)
-{
-	struct apn_ctx *actx;
-	struct apn_ctx *found_actx = NULL;
-	size_t imsi_prio = 0;
-	size_t name_prio = 0;
-	size_t name_req_len = strlen(name);
-
-	llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
-		size_t name_ref_len, imsi_ref_len;
-		const char *name_ref_start, *name_match_start;
-
-		imsi_ref_len = strlen(actx->imsi_prefix);
-		if (strncmp(actx->imsi_prefix, imsi, imsi_ref_len) != 0)
-			continue;
-
-		if (imsi_ref_len < imsi_prio)
-			continue;
-
-		/* IMSI matches */
-
-		name_ref_start = &actx->name[0];
-		if (name_ref_start[0] == '*') {
-			/* Suffix match */
-			name_ref_start += 1;
-			name_ref_len = strlen(name_ref_start);
-			if (name_ref_len > name_req_len)
-				continue;
-		} else {
-			name_ref_len = strlen(name_ref_start);
-			if (name_ref_len != name_req_len)
-				continue;
-		}
-
-		name_match_start = name + (name_req_len - name_ref_len);
-		if (strcasecmp(name_match_start, name_ref_start) != 0)
-			continue;
-
-		/* IMSI and name match */
-
-		if (imsi_ref_len == imsi_prio && name_ref_len < name_prio)
-			/* Lower priority, skip */
-			continue;
-
-		imsi_prio = imsi_ref_len;
-		name_prio = name_ref_len;
-		found_actx = actx;
-	}
-	return found_actx;
-}
-
-struct apn_ctx *sgsn_apn_ctx_by_name(const char *name, const char *imsi_prefix)
-{
-	struct apn_ctx *actx;
-
-	llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
-		if (strcasecmp(name, actx->name) == 0 &&
-		    strcasecmp(imsi_prefix, actx->imsi_prefix) == 0)
-			return actx;
-	}
-	return NULL;
-}
-
-struct apn_ctx *sgsn_apn_ctx_find_alloc(const char *name, const char *imsi_prefix)
-{
-	struct apn_ctx *actx;
-
-	actx = sgsn_apn_ctx_by_name(name, imsi_prefix);
-	if (!actx)
-		actx = sgsn_apn_ctx_alloc(name, imsi_prefix);
-
-	return actx;
-}
-
-uint32_t sgsn_alloc_ptmsi(void)
-{
-	struct sgsn_mm_ctx *mm;
-	uint32_t ptmsi = 0xdeadbeef;
-	int max_retries = 100;
-
-restart:
-	if (RAND_bytes((uint8_t *) &ptmsi, sizeof(ptmsi)) != 1)
-		goto failed;
-
-	/* Enforce that the 2 MSB are set without loosing the distance between
-	 * identical values. Since rand() has no duplicate values within a
-	 * period (because the size of the state is the same like the size of
-	 * the random value), this leads to a distance of period/4 when the
-	 * distribution of the 2 MSB is uniform. This approach fails with a
-	 * probability of (3/4)^max_retries, only 1% of the approaches will
-	 * need more than 16 numbers (even distribution assumed).
-	 *
-	 * Alternatively, a freeze list could be used if another PRNG is used
-	 * or when this approach proves to be not sufficient.
-	 */
-	if (ptmsi >= 0xC0000000) {
-		if (!max_retries--)
-			goto failed;
-		goto restart;
-	}
-	ptmsi |= 0xC0000000;
-
-	if (ptmsi == GSM_RESERVED_TMSI) {
-		if (!max_retries--)
-			goto failed;
-		goto restart;
-	}
-
-	llist_for_each_entry(mm, &sgsn_mm_ctxts, list) {
-		if (mm->p_tmsi == ptmsi) {
-			if (!max_retries--)
-				goto failed;
-			goto restart;
-		}
-	}
-
-	return ptmsi;
-
-failed:
-	LOGP(DGPRS, LOGL_ERROR, "Failed to allocate a P-TMSI\n");
-	return GSM_RESERVED_TMSI;
-}
-
-static void drop_one_pdp(struct sgsn_pdp_ctx *pdp)
-{
-	if (pdp->mm->gmm_state == GMM_REGISTERED_NORMAL)
-		gsm48_tx_gsm_deact_pdp_req(pdp, GSM_CAUSE_NET_FAIL);
-	else  {
-		/* FIXME: GPRS paging in case MS is SUSPENDED */
-		LOGPDPCTXP(LOGL_NOTICE, pdp, "Hard-dropping PDP ctx due to GGSN "
-			"recovery\n");
-		/* FIXME: how to tell this to libgtp? */
-		sgsn_pdp_ctx_free(pdp);
-	}
-}
-
-/* High-level function to be called in case a GGSN has disappeared or
- * otherwise lost state (recovery procedure) */
-int drop_all_pdp_for_ggsn(struct sgsn_ggsn_ctx *ggsn)
-{
-	struct sgsn_mm_ctx *mm;
-	int num = 0;
-
-	llist_for_each_entry(mm, &sgsn_mm_ctxts, list) {
-		struct sgsn_pdp_ctx *pdp;
-		llist_for_each_entry(pdp, &mm->pdp_list, list) {
-			if (pdp->ggsn == ggsn) {
-				drop_one_pdp(pdp);
-				num++;
-			}
-		}
-	}
-
-	return num;
-}
-
-void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
-{
-	OSMO_ASSERT(mmctx != NULL);
-	LOGMMCTXP(LOGL_INFO, mmctx, "Subscriber data update\n");
-
-	sgsn_auth_update(mmctx);
-}
-
-static void insert_extra(struct tlv_parsed *tp,
-			struct sgsn_subscriber_data *data,
-			struct sgsn_subscriber_pdp_data *pdp)
-{
-	tp->lv[OSMO_IE_GSM_SUB_QOS].len = pdp->qos_subscribed_len;
-	tp->lv[OSMO_IE_GSM_SUB_QOS].val = pdp->qos_subscribed;
-
-	/* Prefer PDP charging characteristics of per subscriber one */
-	if (pdp->has_pdp_charg) {
-		tp->lv[OSMO_IE_GSM_CHARG_CHAR].len = sizeof(pdp->pdp_charg);
-		tp->lv[OSMO_IE_GSM_CHARG_CHAR].val = &pdp->pdp_charg[0];
-	} else if (data->has_pdp_charg) {
-		tp->lv[OSMO_IE_GSM_CHARG_CHAR].len = sizeof(data->pdp_charg);
-		tp->lv[OSMO_IE_GSM_CHARG_CHAR].val = &data->pdp_charg[0];
-	}
-}
-
-/**
- * The tlv_parsed tp parameter will be modified to insert a
- * OSMO_IE_GSM_SUB_QOS in case the data is available in the
- * PDP context handling.
- */
-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 *out_apn_str)
-{
-	char req_apn_str[GSM_APN_LENGTH] = {0};
-	const struct apn_ctx *apn_ctx = NULL;
-	const char *selected_apn_str = NULL;
-	struct sgsn_subscriber_pdp_data *pdp;
-	struct sgsn_ggsn_ctx *ggsn = NULL;
-	int allow_any_apn = 0;
-
-	out_apn_str[0] = '\0';
-
-	if (TLVP_PRESENT(tp, GSM48_IE_GSM_APN)) {
-		if (TLVP_LEN(tp, GSM48_IE_GSM_APN) >= GSM_APN_LENGTH - 1) {
-			LOGMMCTXP(LOGL_ERROR, mmctx, "APN IE too long\n");
-			*gsm_cause = GSM_CAUSE_INV_MAND_INFO;
-			return NULL;
-		}
-
-		osmo_apn_to_str(req_apn_str,
-				TLVP_VAL(tp, GSM48_IE_GSM_APN),
-				TLVP_LEN(tp, GSM48_IE_GSM_APN));
-
-		if (strcmp(req_apn_str, "*") == 0)
-			req_apn_str[0] = 0;
-	}
-
-	if (mmctx->subscr == NULL)
-		allow_any_apn = 1;
-
-	if (strlen(req_apn_str) == 0 && !allow_any_apn) {
-		/* No specific APN requested, check for an APN that is both
-		 * granted and configured */
-
-		llist_for_each_entry(pdp, &mmctx->subscr->sgsn_data->pdp_list, list) {
-			if (strcmp(pdp->apn_str, "*") == 0)
-			{
-				allow_any_apn = 1;
-				selected_apn_str = "";
-				insert_extra(tp, mmctx->subscr->sgsn_data, pdp);
-				continue;
-			}
-			if (!llist_empty(&sgsn_apn_ctxts)) {
-				apn_ctx = sgsn_apn_ctx_match(req_apn_str, mmctx->imsi);
-				/* Not configured */
-				if (apn_ctx == NULL)
-					continue;
-			}
-			insert_extra(tp, mmctx->subscr->sgsn_data, pdp);
-			selected_apn_str = pdp->apn_str;
-			break;
-		}
-	} else if (!allow_any_apn) {
-		/* Check whether the given APN is granted */
-		llist_for_each_entry(pdp, &mmctx->subscr->sgsn_data->pdp_list, list) {
-			if (strcmp(pdp->apn_str, "*") == 0) {
-				insert_extra(tp, mmctx->subscr->sgsn_data, pdp);
-				selected_apn_str = req_apn_str;
-				allow_any_apn = 1;
-				continue;
-			}
-			if (strcasecmp(pdp->apn_str, req_apn_str) == 0) {
-				insert_extra(tp, mmctx->subscr->sgsn_data, pdp);
-				selected_apn_str = req_apn_str;
-				break;
-			}
-		}
-	} else if (strlen(req_apn_str) != 0) {
-		/* Any APN is allowed */
-		selected_apn_str = req_apn_str;
-	} else {
-		/* Prefer the GGSN associated with the wildcard APN */
-		selected_apn_str = "";
-	}
-
-	if (!allow_any_apn && selected_apn_str == NULL) {
-		/* Access not granted */
-		LOGMMCTXP(LOGL_NOTICE, mmctx,
-			  "The requested APN '%s' is not allowed\n",
-			  req_apn_str);
-		*gsm_cause = GSM_CAUSE_REQ_SERV_OPT_NOTSUB;
-		return NULL;
-	}
-
-	/* copy the selected apn_str */
-	if (selected_apn_str)
-		strcpy(out_apn_str, selected_apn_str);
-	else
-		out_apn_str[0] = '\0';
-
-	if (apn_ctx == NULL && selected_apn_str)
-		apn_ctx = sgsn_apn_ctx_match(selected_apn_str, mmctx->imsi);
-
-	if (apn_ctx != NULL) {
-		ggsn = apn_ctx->ggsn;
-	} else if (llist_empty(&sgsn_apn_ctxts)) {
-		/* No configuration -> use GGSN 0 */
-		ggsn = sgsn_ggsn_ctx_by_id(0);
-	} else if (allow_any_apn &&
-		   (selected_apn_str == NULL || strlen(selected_apn_str) == 0)) {
-		/* No APN given and no default configuration -> Use GGSN 0 */
-		ggsn = sgsn_ggsn_ctx_by_id(0);
-	} else {
-		/* No matching configuration found */
-		LOGMMCTXP(LOGL_NOTICE, mmctx,
-			  "The selected APN '%s' has not been configured\n",
-			  selected_apn_str);
-		*gsm_cause = GSM_CAUSE_MISSING_APN;
-		return NULL;
-	}
-
-	if (!ggsn) {
-		LOGMMCTXP(LOGL_NOTICE, mmctx,
-			"No static GGSN configured. Selected APN '%s'\n",
-			selected_apn_str);
-			return NULL;
-	}
-
-	LOGMMCTXP(LOGL_INFO, mmctx,
-		  "Found GGSN %d for APN '%s' (requested '%s')\n",
-		  ggsn->id, selected_apn_str ? selected_apn_str : "---",
-		  req_apn_str);
-
-	return ggsn;
-}
-
-static void sgsn_llme_cleanup_free(struct gprs_llc_llme *llme)
-{
-	struct sgsn_mm_ctx *mmctx = NULL;
-
-	llist_for_each_entry(mmctx, &sgsn_mm_ctxts, list) {
-		if (llme == mmctx->gb.llme) {
-			gsm0408_gprs_access_cancelled(mmctx, SGSN_ERROR_CAUSE_NONE);
-			return;
-		}
-	}
-
-	/* No MM context found */
-	LOGP(DGPRS, LOGL_INFO, "Deleting orphaned LLME, TLLI 0x%08x\n",
-	     llme->tlli);
-	gprs_llgmm_unassign(llme);
-}
-
-static void sgsn_llme_check_cb(void *data_)
-{
-	struct gprs_llc_llme *llme, *llme_tmp;
-	struct timespec now_tp;
-	time_t now, age;
-	time_t max_age = gprs_max_time_to_idle();
-
-	int rc;
-
-	rc = clock_gettime(CLOCK_MONOTONIC, &now_tp);
-	OSMO_ASSERT(rc >= 0);
-	now = now_tp.tv_sec;
-
-	LOGP(DGPRS, LOGL_DEBUG,
-	     "Checking for inactive LLMEs, time = %u\n", (unsigned)now);
-
-	llist_for_each_entry_safe(llme, llme_tmp, &gprs_llc_llmes, list) {
-		if (llme->age_timestamp == GPRS_LLME_RESET_AGE)
-			llme->age_timestamp = now;
-
-		age = now - llme->age_timestamp;
-
-		if (age > max_age || age < 0) {
-			LOGP(DGPRS, LOGL_INFO,
-			     "Inactivity timeout for TLLI 0x%08x, age %d\n",
-			     llme->tlli, (int)age);
-			sgsn_llme_cleanup_free(llme);
-		}
-	}
-
-	osmo_timer_schedule(&sgsn->llme_timer, GPRS_LLME_CHECK_TICK, 0);
-}
-
-void sgsn_inst_init()
-{
-	osmo_timer_setup(&sgsn->llme_timer, sgsn_llme_check_cb, NULL);
-	osmo_timer_schedule(&sgsn->llme_timer, GPRS_LLME_CHECK_TICK, 0);
-}
-
diff --git a/src/gprs/gprs_sndcp.c b/src/gprs/gprs_sndcp.c
deleted file mode 100644
index a18998f..0000000
--- a/src/gprs/gprs_sndcp.c
+++ /dev/null
@@ -1,1258 +0,0 @@
-/* GPRS SNDCP protocol implementation as per 3GPP TS 04.65 */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.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/>.
- *
- */
-
-#include <errno.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/timer.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/gprs/gprs_bssgp.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/debug.h>
-#include <openbsc/gprs_llc.h>
-#include <openbsc/sgsn.h>
-#include <openbsc/gprs_sndcp.h>
-#include <openbsc/gprs_llc_xid.h>
-#include <openbsc/gprs_sndcp_xid.h>
-#include <openbsc/gprs_sndcp_pcomp.h>
-#include <openbsc/gprs_sndcp_dcomp.h>
-#include <openbsc/gprs_sndcp_comp.h>
-
-#define DEBUG_IP_PACKETS 0	/* 0=Disabled, 1=Enabled */
-
-#if DEBUG_IP_PACKETS == 1
-/* Calculate TCP/IP checksum */
-static uint16_t calc_ip_csum(uint8_t *data, int len)
-{
-	int i;
-	uint32_t accumulator = 0;
-	uint16_t *pointer = (uint16_t *) data;
-
-	for (i = len; i > 1; i -= 2) {
-		accumulator += *pointer;
-		pointer++;
-	}
-
-	if (len % 2)
-		accumulator += *pointer;
-
-	accumulator = (accumulator & 0xffff) + ((accumulator >> 16) & 0xffff);
-	accumulator += (accumulator >> 16) & 0xffff;
-	return (~accumulator);
-}
-
-/* Calculate TCP/IP checksum */
-static uint16_t calc_tcpip_csum(const void *ctx, uint8_t *packet, int len)
-{
-	uint8_t *buf;
-	uint16_t csum;
-
-	buf = talloc_zero_size(ctx, len);
-	memset(buf, 0, len);
-	memcpy(buf, packet + 12, 8);
-	buf[9] = packet[9];
-	buf[11] = (len - 20) & 0xFF;
-	buf[10] = (len - 20) >> 8 & 0xFF;
-	memcpy(buf + 12, packet + 20, len - 20);
-	csum = calc_ip_csum(buf, len - 20 + 12);
-	talloc_free(buf);
-	return csum;
-}
-
-/* Show some ip packet details */
-static void debug_ip_packet(uint8_t *data, int len, int dir, char *info)
-{
-	uint8_t tcp_flags;
-	char flags_debugmsg[256];
-	int len_short;
-	static unsigned int packet_count = 0;
-	static unsigned int tcp_csum_err_count = 0;
-	static unsigned int ip_csum_err_count = 0;
-
-	packet_count++;
-
-	if (len > 80)
-		len_short = 80;
-	else
-		len_short = len;
-
-	if (dir)
-		DEBUGP(DSNDCP, "%s: MS => SGSN: %s\n", info,
-		       osmo_hexdump_nospc(data, len_short));
-	else
-		DEBUGP(DSNDCP, "%s: MS <= SGSN: %s\n", info,
-		       osmo_hexdump_nospc(data, len_short));
-
-	DEBUGP(DSNDCP, "%s: Length.: %d\n", info, len);
-	DEBUGP(DSNDCP, "%s: NO.: %d\n", info, packet_count);
-
-	if (len < 20) {
-		DEBUGP(DSNDCP, "%s: Error: Short IP packet!\n", info);
-		return;
-	}
-
-	if (calc_ip_csum(data, 20) != 0) {
-		DEBUGP(DSNDCP, "%s: Bad IP-Header checksum!\n", info);
-		ip_csum_err_count++;
-	} else
-		DEBUGP(DSNDCP, "%s: IP-Header checksum ok.\n", info);
-
-	if (data[9] == 0x06) {
-		if (len < 40) {
-			DEBUGP(DSNDCP, "%s: Error: Short TCP packet!\n", info);
-			return;
-		}
-
-		DEBUGP(DSNDCP, "%s: Protocol type: TCP\n", info);
-		tcp_flags = data[33];
-
-		if (calc_tcpip_csum(NULL, data, len) != 0) {
-			DEBUGP(DSNDCP, "%s: Bad TCP checksum!\n", info);
-			tcp_csum_err_count++;
-		} else
-			DEBUGP(DSNDCP, "%s: TCP checksum ok.\n", info);
-
-		memset(flags_debugmsg, 0, sizeof(flags_debugmsg));
-		if (tcp_flags & 1)
-			strcat(flags_debugmsg, "FIN ");
-		if (tcp_flags & 2)
-			strcat(flags_debugmsg, "SYN ");
-		if (tcp_flags & 4)
-			strcat(flags_debugmsg, "RST ");
-		if (tcp_flags & 8)
-			strcat(flags_debugmsg, "PSH ");
-		if (tcp_flags & 16)
-			strcat(flags_debugmsg, "ACK ");
-		if (tcp_flags & 32)
-			strcat(flags_debugmsg, "URG ");
-		DEBUGP(DSNDCP, "%s: FLAGS: %s\n", info, flags_debugmsg);
-	} else if (data[9] == 0x11) {
-		DEBUGP(DSNDCP, "%s: Protocol type: UDP\n", info);
-	} else {
-		DEBUGP(DSNDCP, "%s: Protocol type: (%02x)\n", info, data[9]);
-	}
-
-	DEBUGP(DSNDCP, "%s: IP-Header checksum errors: %d\n", info,
-	       ip_csum_err_count);
-	DEBUGP(DSNDCP, "%s: TCP-Checksum errors: %d\n", info,
-	       tcp_csum_err_count);
-}
-#endif
-
-/* Chapter 7.2: SN-PDU Formats */
-struct sndcp_common_hdr {
-	/* octet 1 */
-	uint8_t nsapi:4;
-	uint8_t more:1;
-	uint8_t type:1;
-	uint8_t first:1;
-	uint8_t spare:1;
-} __attribute__((packed));
-
-/* PCOMP / DCOMP only exist in first fragment */
-struct sndcp_comp_hdr {
-	/* octet 2 */
-	uint8_t pcomp:4;
-	uint8_t dcomp:4;
-} __attribute__((packed));
-
-struct sndcp_udata_hdr {
-	/* octet 3 */
-	uint8_t npdu_high:4;
-	uint8_t seg_nr:4;
-	/* octet 4 */
-	uint8_t npdu_low;
-} __attribute__((packed));
-
-
-static void *tall_sndcp_ctx;
-
-/* A fragment queue entry, containing one framgent of a N-PDU */
-struct defrag_queue_entry {
-	struct llist_head list;
-	/* segment number of this fragment */
-	uint32_t seg_nr;
-	/* length of the data area of this fragment */
-	uint32_t data_len;
-	/* pointer to the data of this fragment */
-	uint8_t *data;
-};
-
-LLIST_HEAD(gprs_sndcp_entities);
-
-/* Check if any compression parameters are set in the sgsn configuration */
-static inline int any_pcomp_or_dcomp_active(struct sgsn_instance *sgsn) {
-	if (sgsn->cfg.pcomp_rfc1144.active || sgsn->cfg.pcomp_rfc1144.passive ||
-	    sgsn->cfg.dcomp_v42bis.active || sgsn->cfg.dcomp_v42bis.passive)
-		return true;
-	else
-		return false;
-}
-
-/* Enqueue a fragment into the defragment queue */
-static int defrag_enqueue(struct gprs_sndcp_entity *sne, uint8_t seg_nr,
-			  uint8_t *data, uint32_t data_len)
-{
-	struct defrag_queue_entry *dqe;
-
-	dqe = talloc_zero(tall_sndcp_ctx, struct defrag_queue_entry);
-	if (!dqe)
-		return -ENOMEM;
-	dqe->data = talloc_zero_size(dqe, data_len);
-	if (!dqe->data) {
-		talloc_free(dqe);
-		return -ENOMEM;
-	}
-	dqe->seg_nr = seg_nr;
-	dqe->data_len = data_len;
-
-	llist_add(&dqe->list, &sne->defrag.frag_list);
-
-	if (seg_nr > sne->defrag.highest_seg)
-		sne->defrag.highest_seg = seg_nr;
-
-	sne->defrag.seg_have |= (1 << seg_nr);
-	sne->defrag.tot_len += data_len;
-
-	memcpy(dqe->data, data, data_len);
-
-	return 0;
-}
-
-/* return if we have all segments of this N-PDU */
-static int defrag_have_all_segments(struct gprs_sndcp_entity *sne)
-{
-	uint32_t seg_needed = 0;
-	unsigned int i;
-
-	/* create a bitmask of needed segments */
-	for (i = 0; i <= sne->defrag.highest_seg; i++)
-		seg_needed |= (1 << i);
-
-	if (seg_needed == sne->defrag.seg_have)
-		return 1;
-
-	return 0;
-}
-
-static struct defrag_queue_entry *defrag_get_seg(struct gprs_sndcp_entity *sne,
-						 uint32_t seg_nr)
-{
-	struct defrag_queue_entry *dqe;
-
-	llist_for_each_entry(dqe, &sne->defrag.frag_list, list) {
-		if (dqe->seg_nr == seg_nr) {
-			llist_del(&dqe->list);
-			return dqe;
-		}
-	}
-	return NULL;
-}
-
-/* Perform actual defragmentation and create an output packet */
-static int defrag_segments(struct gprs_sndcp_entity *sne)
-{
-	struct msgb *msg;
-	unsigned int seg_nr;
-	uint8_t *npdu;
-	int npdu_len;
-	int rc;
-	uint8_t *expnd = NULL;
-
-	LOGP(DSNDCP, LOGL_DEBUG, "TLLI=0x%08x NSAPI=%u: Defragment output PDU %u "
-		"num_seg=%u tot_len=%u\n", sne->lle->llme->tlli, sne->nsapi,
-		sne->defrag.npdu, sne->defrag.highest_seg, sne->defrag.tot_len);
-	msg = msgb_alloc_headroom(sne->defrag.tot_len+256, 128, "SNDCP Defrag");
-	if (!msg)
-		return -ENOMEM;
-
-	/* FIXME: message headers + identifiers */
-
-	npdu = msg->data;
-
-	for (seg_nr = 0; seg_nr <= sne->defrag.highest_seg; seg_nr++) {
-		struct defrag_queue_entry *dqe;
-		uint8_t *data;
-
-		dqe = defrag_get_seg(sne, seg_nr);
-		if (!dqe) {
-			LOGP(DSNDCP, LOGL_ERROR, "Segment %u missing\n", seg_nr);
-			msgb_free(msg);
-			return -EIO;
-		}
-		/* actually append the segment to the N-PDU */
-		data = msgb_put(msg, dqe->data_len);
-		memcpy(data, dqe->data, dqe->data_len);
-
-		/* release memory for the fragment queue entry */
-		talloc_free(dqe);
-	}
-
-	npdu_len = sne->defrag.tot_len;
-
-	/* FIXME: cancel timer */
-
-	/* actually send the N-PDU to the SGSN core code, which then
-	 * hands it off to the correct GTP tunnel + GGSN via gtp_data_req() */
-
-	/* Decompress packet */
-#if DEBUG_IP_PACKETS == 1
-	DEBUGP(DSNDCP, "                                                   \n");
-	DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
-	DEBUGP(DSNDCP, "===================================================\n");
-#endif
-	if (any_pcomp_or_dcomp_active(sgsn)) {
-
-		expnd = talloc_zero_size(msg, npdu_len * MAX_DATADECOMPR_FAC +
-					 MAX_HDRDECOMPR_INCR);
-		memcpy(expnd, npdu, npdu_len);
-
-		/* Apply data decompression */
-		rc = gprs_sndcp_dcomp_expand(expnd, npdu_len, sne->defrag.dcomp,
-					     sne->defrag.data);
-		if (rc < 0) {
-			LOGP(DSNDCP, LOGL_ERROR,
-			     "Data decompression failed!\n");
-			talloc_free(expnd);
-			return -EIO;
-		}
-
-		/* Apply header decompression */
-		rc = gprs_sndcp_pcomp_expand(expnd, rc, sne->defrag.pcomp,
-					     sne->defrag.proto);
-		if (rc < 0) {
-			LOGP(DSNDCP, LOGL_ERROR,
-			     "TCP/IP Header decompression failed!\n");
-			talloc_free(expnd);
-			return -EIO;
-		}
-
-		/* Modify npu length, expnd is handed directly handed
-		 * over to gsn_rx_sndcp_ud_ind(), see below */
-		npdu_len = rc;
-	} else
-		expnd = npdu;
-#if DEBUG_IP_PACKETS == 1
-	debug_ip_packet(expnd, npdu_len, 1, "defrag_segments()");
-	DEBUGP(DSNDCP, "===================================================\n");
-	DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
-	DEBUGP(DSNDCP, "                                                   \n");
-#endif
-
-	/* Hand off packet to gtp */
-	rc = sgsn_rx_sndcp_ud_ind(&sne->ra_id, sne->lle->llme->tlli,
-				  sne->nsapi, msg, npdu_len, expnd);
-
-	if (any_pcomp_or_dcomp_active(sgsn))
-		talloc_free(expnd);
-
-	return rc;
-}
-
-static int defrag_input(struct gprs_sndcp_entity *sne, struct msgb *msg,
-			uint8_t *hdr, unsigned int len)
-{
-	struct sndcp_common_hdr *sch;
-	struct sndcp_udata_hdr *suh;
-	uint16_t npdu_num;
-	uint8_t *data;
-	int rc;
-
-	sch = (struct sndcp_common_hdr *) hdr;
-	if (sch->first) {
-		suh = (struct sndcp_udata_hdr *) (hdr + 1 + sizeof(struct sndcp_common_hdr));
-	} else
-		suh = (struct sndcp_udata_hdr *) (hdr + sizeof(struct sndcp_common_hdr));
-
-	data = (uint8_t *)suh + sizeof(struct sndcp_udata_hdr);
-
-	npdu_num = (suh->npdu_high << 8) | suh->npdu_low;
-
-	LOGP(DSNDCP, LOGL_DEBUG, "TLLI=0x%08x NSAPI=%u: Input PDU %u Segment %u "
-		"Length %u %s %s\n", sne->lle->llme->tlli, sne->nsapi, npdu_num,
-		suh->seg_nr, len, sch->first ? "F " : "", sch->more ? "M" : "");
-
-	if (sch->first) {
-		/* first segment of a new packet.  Discard all leftover fragments of
-		 * previous packet */
-		if (!llist_empty(&sne->defrag.frag_list)) {
-			struct defrag_queue_entry *dqe, *dqe2;
-			LOGP(DSNDCP, LOGL_INFO, "TLLI=0x%08x NSAPI=%u: Dropping "
-			     "SN-PDU %u due to insufficient segments (%04x)\n",
-			     sne->lle->llme->tlli, sne->nsapi, sne->defrag.npdu,
-			     sne->defrag.seg_have);
-			llist_for_each_entry_safe(dqe, dqe2, &sne->defrag.frag_list, list) {
-				llist_del(&dqe->list);
-				talloc_free(dqe);
-			}
-		}
-		/* store the currently de-fragmented PDU number */
-		sne->defrag.npdu = npdu_num;
-
-		/* Re-set fragmentation state */
-		sne->defrag.no_more = sne->defrag.highest_seg = sne->defrag.seg_have = 0;
-		sne->defrag.tot_len = 0;
-		/* FIXME: (re)start timer */
-	}
-
-	if (sne->defrag.npdu != npdu_num) {
-		LOGP(DSNDCP, LOGL_INFO, "Segment for different SN-PDU "
-			"(%u != %u)\n", npdu_num, sne->defrag.npdu);
-		/* FIXME */
-	}
-
-	/* FIXME: check if seg_nr already exists */
-	/* make sure to subtract length of SNDCP header from 'len' */
-	rc = defrag_enqueue(sne, suh->seg_nr, data, len - (data - hdr));
-	if (rc < 0)
-		return rc;
-
-	if (!sch->more) {
-		/* this is suppsed to be the last segment of the N-PDU, but it
-		 * might well be not the last to arrive */
-		sne->defrag.no_more = 1;
-	}
-
-	if (sne->defrag.no_more) {
-		/* we have already received the last segment before, let's check
-		 * if all the previous segments exist */
-		if (defrag_have_all_segments(sne))
-			return defrag_segments(sne);
-	}
-
-	return 0;
-}
-
-static struct gprs_sndcp_entity *gprs_sndcp_entity_by_lle(const struct gprs_llc_lle *lle,
-						uint8_t nsapi)
-{
-	struct gprs_sndcp_entity *sne;
-
-	llist_for_each_entry(sne, &gprs_sndcp_entities, list) {
-		if (sne->lle == lle && sne->nsapi == nsapi)
-			return sne;
-	}
-	return NULL;
-}
-
-static struct gprs_sndcp_entity *gprs_sndcp_entity_alloc(struct gprs_llc_lle *lle,
-						uint8_t nsapi)
-{
-	struct gprs_sndcp_entity *sne;
-
-	sne = talloc_zero(tall_sndcp_ctx, struct gprs_sndcp_entity);
-	if (!sne)
-		return NULL;
-
-	sne->lle = lle;
-	sne->nsapi = nsapi;
-	sne->defrag.timer.data = sne;
-	//sne->fqueue.timer.cb = FIXME;
-	sne->rx_state = SNDCP_RX_S_FIRST;
-	INIT_LLIST_HEAD(&sne->defrag.frag_list);
-
-	llist_add(&sne->list, &gprs_sndcp_entities);
-
-	return sne;
-}
-
-/* Entry point for the SNSM-ACTIVATE.indication */
-int sndcp_sm_activate_ind(struct gprs_llc_lle *lle, uint8_t nsapi)
-{
-	LOGP(DSNDCP, LOGL_INFO, "SNSM-ACTIVATE.ind (lle=%p TLLI=%08x, "
-	     "SAPI=%u, NSAPI=%u)\n", lle, lle->llme->tlli, lle->sapi, nsapi);
-
-	if (gprs_sndcp_entity_by_lle(lle, nsapi)) {
-		LOGP(DSNDCP, LOGL_ERROR, "Trying to ACTIVATE "
-			"already-existing entity (TLLI=%08x, NSAPI=%u)\n",
-			lle->llme->tlli, nsapi);
-		return -EEXIST;
-	}
-
-	if (!gprs_sndcp_entity_alloc(lle, nsapi)) {
-		LOGP(DSNDCP, LOGL_ERROR, "Out of memory during ACTIVATE\n");
-		return -ENOMEM;
-	}
-
-	return 0;
-}
-
-/* Entry point for the SNSM-DEACTIVATE.indication */
-int sndcp_sm_deactivate_ind(struct gprs_llc_lle *lle, uint8_t nsapi)
-{
-	struct gprs_sndcp_entity *sne;
-
-	LOGP(DSNDCP, LOGL_INFO, "SNSM-DEACTIVATE.ind (lle=%p, TLLI=%08x, "
-	     "SAPI=%u, NSAPI=%u)\n", lle, lle->llme->tlli, lle->sapi, nsapi);
-
-	sne = gprs_sndcp_entity_by_lle(lle, nsapi);
-	if (!sne) {
-		LOGP(DSNDCP, LOGL_ERROR, "SNSM-DEACTIVATE.ind for non-"
-		     "existing TLLI=%08x SAPI=%u NSAPI=%u\n", lle->llme->tlli,
-		     lle->sapi, nsapi);
-		return -ENOENT;
-	}
-	llist_del(&sne->list);
-	/* frag queue entries are hierarchically allocated, so no need to
-	 * free them explicitly here */
-	talloc_free(sne);
-
-	return 0;
-}
-
-/* Fragmenter state */
-struct sndcp_frag_state {
-	uint8_t frag_nr;
-	struct msgb *msg;	/* original message */
-	uint8_t *next_byte;	/* first byte of next fragment */
-
-	struct gprs_sndcp_entity *sne;
-	void *mmcontext;
-};
-
-/* returns '1' if there are more fragments to send, '0' if none */
-static int sndcp_send_ud_frag(struct sndcp_frag_state *fs,
-			      uint8_t pcomp, uint8_t dcomp)
-{
-	struct gprs_sndcp_entity *sne = fs->sne;
-	struct gprs_llc_lle *lle = sne->lle;
-	struct sndcp_common_hdr *sch;
-	struct sndcp_comp_hdr *scomph;
-	struct sndcp_udata_hdr *suh;
-	struct msgb *fmsg;
-	unsigned int max_payload_len;
-	unsigned int len;
-	uint8_t *data;
-	int rc, more;
-
-	fmsg = msgb_alloc_headroom(fs->sne->lle->params.n201_u+256, 128,
-				   "SNDCP Frag");
-	if (!fmsg) {
-		msgb_free(fs->msg);
-		return -ENOMEM;
-	}
-
-	/* make sure lower layers route the fragment like the original */
-	msgb_tlli(fmsg) = msgb_tlli(fs->msg);
-	msgb_bvci(fmsg) = msgb_bvci(fs->msg);
-	msgb_nsei(fmsg) = msgb_nsei(fs->msg);
-
-	/* prepend common SNDCP header */
-	sch = (struct sndcp_common_hdr *) msgb_put(fmsg, sizeof(*sch));
-	sch->nsapi = sne->nsapi;
-	/* Set FIRST bit if we are the first fragment in a series */
-	if (fs->frag_nr == 0)
-		sch->first = 1;
-	sch->type = 1;
-
-	/* append the compression header for first fragment */
-	if (sch->first) {
-		scomph = (struct sndcp_comp_hdr *)
-				msgb_put(fmsg, sizeof(*scomph));
-		scomph->pcomp = pcomp;
-		scomph->dcomp = dcomp;
-	}
-
-	/* append the user-data header */
-	suh = (struct sndcp_udata_hdr *) msgb_put(fmsg, sizeof(*suh));
-	suh->npdu_low = sne->tx_npdu_nr & 0xff;
-	suh->npdu_high = (sne->tx_npdu_nr >> 8) & 0xf;
-	suh->seg_nr = fs->frag_nr % 0xf;
-
-	/* calculate remaining length to be sent */
-	len = (fs->msg->data + fs->msg->len) - fs->next_byte;
-	/* how much payload can we actually send via LLC? */
-	max_payload_len = lle->params.n201_u - (sizeof(*sch) + sizeof(*suh));
-	if (sch->first)
-		max_payload_len -= sizeof(*scomph);
-	/* check if we're exceeding the max */
-	if (len > max_payload_len)
-		len = max_payload_len;
-
-	/* copy the actual fragment data into our fmsg */
-	data = msgb_put(fmsg, len);
-	memcpy(data, fs->next_byte, len);
-
-	/* Increment fragment number and data pointer to next fragment */
-	fs->frag_nr++;
-	fs->next_byte += len;
-
-	/* determine if we have more fragemnts to send */
-	if ((fs->msg->data + fs->msg->len) <= fs->next_byte)
-		more = 0;
-	else
-		more = 1;
-
-	/* set the MORE bit of the SNDCP header accordingly */
-	sch->more = more;
-
-	rc = gprs_llc_tx_ui(fmsg, lle->sapi, 0, fs->mmcontext, true);
-	/* abort in case of error, do not advance frag_nr / next_byte */
-	if (rc < 0) {
-		msgb_free(fs->msg);
-		return rc;
-	}
-
-	if (!more) {
-		/* we've sent all fragments */
-		msgb_free(fs->msg);
-		memset(fs, 0, sizeof(*fs));
-		/* increment NPDU number for next frame */
-		sne->tx_npdu_nr = (sne->tx_npdu_nr + 1) % 0xfff;
-		return 0;
-	}
-
-	/* default: more fragments to send */
-	return 1;
-}
-
-/* Request transmission of a SN-PDU over specified LLC Entity + SAPI */
-int sndcp_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi,
-			void *mmcontext)
-{
-	struct gprs_sndcp_entity *sne;
-	struct sndcp_common_hdr *sch;
-	struct sndcp_comp_hdr *scomph;
-	struct sndcp_udata_hdr *suh;
-	struct sndcp_frag_state fs;
-	uint8_t pcomp = 0;
-	uint8_t dcomp = 0;
-	int rc;
-
-	/* Identifiers from UP: (TLLI, SAPI) + (BVCI, NSEI) */
-
-	/* Compress packet */
-#if DEBUG_IP_PACKETS == 1
-	DEBUGP(DSNDCP, "                                                   \n");
-	DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
-	DEBUGP(DSNDCP, "===================================================\n");
-	debug_ip_packet(msg->data, msg->len, 0, "sndcp_initdata_req()");
-#endif
-	if (any_pcomp_or_dcomp_active(sgsn)) {
-
-		/* Apply header compression */
-		rc = gprs_sndcp_pcomp_compress(msg->data, msg->len, &pcomp,
-					       lle->llme->comp.proto, nsapi);
-		if (rc < 0) {
-			LOGP(DSNDCP, LOGL_ERROR,
-			     "TCP/IP Header compression failed!\n");
-			return -EIO;
-		}
-
-		/* Fixup pointer locations and sizes in message buffer to match
-		 * the new, compressed buffer size */
-		msgb_get(msg, msg->len);
-		msgb_put(msg, rc);
-
-		/* Apply data compression */
-		rc = gprs_sndcp_dcomp_compress(msg->data, msg->len, &dcomp,
-					       lle->llme->comp.data, nsapi);
-		if (rc < 0) {
-			LOGP(DSNDCP, LOGL_ERROR, "Data compression failed!\n");
-			return -EIO;
-		}
-
-		/* Fixup pointer locations and sizes in message buffer to match
-		 * the new, compressed buffer size */
-		msgb_get(msg, msg->len);
-		msgb_put(msg, rc);
-	}
-#if DEBUG_IP_PACKETS == 1
-	DEBUGP(DSNDCP, "===================================================\n");
-	DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
-	DEBUGP(DSNDCP, "                                                   \n");
-#endif
-
-	sne = gprs_sndcp_entity_by_lle(lle, nsapi);
-	if (!sne) {
-		LOGP(DSNDCP, LOGL_ERROR, "Cannot find SNDCP Entity\n");
-		msgb_free(msg);
-		return -EIO;
-	}
-
-	/* Check if we need to fragment this N-PDU into multiple SN-PDUs */
-	if (msg->len > lle->params.n201_u - 
-			(sizeof(*sch) + sizeof(*suh) + sizeof(*scomph))) {
-		/* initialize the fragmenter state */
-		fs.msg = msg;
-		fs.frag_nr = 0;
-		fs.next_byte = msg->data;
-		fs.sne = sne;
-		fs.mmcontext = mmcontext;
-
-		/* call function to generate and send fragments until all
-		 * of the N-PDU has been sent */
-		while (1) {
-			int rc = sndcp_send_ud_frag(&fs,pcomp,dcomp);
-			if (rc == 0)
-				return 0;
-			if (rc < 0)
-				return rc;
-		}
-		/* not reached */
-		return 0;
-	}
-
-	/* this is the non-fragmenting case where we only build 1 SN-PDU */
-
-	/* prepend the user-data header */
-	suh = (struct sndcp_udata_hdr *) msgb_push(msg, sizeof(*suh));
-	suh->npdu_low = sne->tx_npdu_nr & 0xff;
-	suh->npdu_high = (sne->tx_npdu_nr >> 8) & 0xf;
-	suh->seg_nr = 0;
-	sne->tx_npdu_nr = (sne->tx_npdu_nr + 1) % 0xfff;
-
-	scomph = (struct sndcp_comp_hdr *) msgb_push(msg, sizeof(*scomph));
-	scomph->pcomp = pcomp;
-	scomph->dcomp = dcomp;
-
-	/* prepend common SNDCP header */
-	sch = (struct sndcp_common_hdr *) msgb_push(msg, sizeof(*sch));
-	sch->first = 1;
-	sch->type = 1;
-	sch->nsapi = nsapi;
-
-	return gprs_llc_tx_ui(msg, lle->sapi, 0, mmcontext, true);
-}
-
-/* Section 5.1.2.17 LL-UNITDATA.ind */
-int sndcp_llunitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
-			 uint8_t *hdr, uint16_t len)
-{
-	struct gprs_sndcp_entity *sne;
-	struct sndcp_common_hdr *sch = (struct sndcp_common_hdr *)hdr;
-	struct sndcp_comp_hdr *scomph = NULL;
-	struct sndcp_udata_hdr *suh;
-	uint8_t *npdu;
-	uint16_t npdu_num __attribute__((unused));
-	int npdu_len;
-	int rc;
-	uint8_t *expnd = NULL;
-
-	sch = (struct sndcp_common_hdr *) hdr;
-	if (sch->first) {
-		scomph = (struct sndcp_comp_hdr *) (hdr + 1);
-		suh = (struct sndcp_udata_hdr *) (hdr + 1 + sizeof(struct sndcp_common_hdr));
-	} else
-		suh = (struct sndcp_udata_hdr *) (hdr + sizeof(struct sndcp_common_hdr));
-
-	if (sch->type == 0) {
-		LOGP(DSNDCP, LOGL_ERROR, "SN-DATA PDU at unitdata_ind() function\n");
-		return -EINVAL;
-	}
-
-	if (len < sizeof(*sch) + sizeof(*suh)) {
-		LOGP(DSNDCP, LOGL_ERROR, "SN-UNITDATA PDU too short (%u)\n", len);
-		return -EIO;
-	}
-
-	sne = gprs_sndcp_entity_by_lle(lle, sch->nsapi);
-	if (!sne) {
-		LOGP(DSNDCP, LOGL_ERROR, "Message for non-existing SNDCP Entity "
-			"(lle=%p, TLLI=%08x, SAPI=%u, NSAPI=%u)\n", lle,
-			lle->llme->tlli, lle->sapi, sch->nsapi);
-		return -EIO;
-	}
-	/* FIXME: move this RA_ID up to the LLME or even higher */
-	bssgp_parse_cell_id(&sne->ra_id, msgb_bcid(msg));
-
-	if (scomph) {
-		sne->defrag.pcomp = scomph->pcomp;
-		sne->defrag.dcomp = scomph->dcomp;
-		sne->defrag.proto = lle->llme->comp.proto;
-		sne->defrag.data = lle->llme->comp.data;
-	}
-
-	/* any non-first segment is by definition something to defragment
-	 * as is any segment that tells us there are more segments */
-	if (!sch->first || sch->more)
-		return defrag_input(sne, msg, hdr, len);
-
-	npdu_num = (suh->npdu_high << 8) | suh->npdu_low;
-	npdu = (uint8_t *)suh + sizeof(*suh);
-	npdu_len = (msg->data + msg->len) - npdu - 3;	/* -3 'removes' the FCS */
-
-	if (npdu_len <= 0) {
-		LOGP(DSNDCP, LOGL_ERROR, "Short SNDCP N-PDU: %d\n", npdu_len);
-		return -EIO;
-	}
-	/* actually send the N-PDU to the SGSN core code, which then
-	 * hands it off to the correct GTP tunnel + GGSN via gtp_data_req() */
-
-	/* Decompress packet */
-#if DEBUG_IP_PACKETS == 1
-	DEBUGP(DSNDCP, "                                                   \n");
-	DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
-	DEBUGP(DSNDCP, "===================================================\n");
-#endif
-	if (any_pcomp_or_dcomp_active(sgsn)) {
-
-		expnd = talloc_zero_size(msg, npdu_len * MAX_DATADECOMPR_FAC +
-					 MAX_HDRDECOMPR_INCR);
-		memcpy(expnd, npdu, npdu_len);
-
-		/* Apply data decompression */
-		rc = gprs_sndcp_dcomp_expand(expnd, npdu_len, sne->defrag.dcomp,
-					     sne->defrag.data);
-		if (rc < 0) {
-			LOGP(DSNDCP, LOGL_ERROR,
-			     "Data decompression failed!\n");
-			talloc_free(expnd);
-			return -EIO;
-		}
-
-		/* Apply header decompression */
-		rc = gprs_sndcp_pcomp_expand(expnd, rc, sne->defrag.pcomp,
-					     sne->defrag.proto);
-		if (rc < 0) {
-			LOGP(DSNDCP, LOGL_ERROR,
-			     "TCP/IP Header decompression failed!\n");
-			talloc_free(expnd);
-			return -EIO;
-		}
-
-		/* Modify npu length, expnd is handed directly handed
-		 * over to gsn_rx_sndcp_ud_ind(), see below */
-		npdu_len = rc;
-	} else
-		expnd = npdu;
-#if DEBUG_IP_PACKETS == 1
-	debug_ip_packet(expnd, npdu_len, 1, "sndcp_llunitdata_ind()");
-	DEBUGP(DSNDCP, "===================================================\n");
-	DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
-	DEBUGP(DSNDCP, "                                                   \n");
-#endif
-
-	/* Hand off packet to gtp */
-	rc = sgsn_rx_sndcp_ud_ind(&sne->ra_id, lle->llme->tlli,
-				  sne->nsapi, msg, npdu_len, expnd);
-
-	if (any_pcomp_or_dcomp_active(sgsn))
-		talloc_free(expnd);
-
-	return rc;
-}
-
-#if 0
-/* Section 5.1.2.1 LL-RESET.ind */
-static int sndcp_ll_reset_ind(struct gprs_sndcp_entity *se)
-{
-	/* treat all outstanding SNDCP-LLC request type primitives as not sent */
-	/* reset all SNDCP XID parameters to default values */
-	LOGP(DSNDCP, LOGL_NOTICE, "not implemented.\n");
-	return 0;
-}
-
-static int sndcp_ll_status_ind()
-{
-	/* inform the SM sub-layer by means of SNSM-STATUS.req */
-	LOGP(DSNDCP, LOGL_NOTICE, "not implemented.\n");
-	return 0;
-}
-
-static struct sndcp_state_list {{
-	uint32_t	states;
-	unsigned int	type;
-	int		(*rout)(struct gprs_sndcp_entity *se, struct msgb *msg);
-} sndcp_state_list[] = {
-	{ ALL_STATES,
-	  LL_RESET_IND, sndcp_ll_reset_ind },
-	{ ALL_STATES,
-	  LL_ESTABLISH_IND, sndcp_ll_est_ind },
-	{ SBIT(SNDCP_S_EST_RQD),
-	  LL_ESTABLISH_RESP, sndcp_ll_est_ind },
-	{ SBIT(SNDCP_S_EST_RQD),
-	  LL_ESTABLISH_CONF, sndcp_ll_est_conf },
-	{ SBIT(SNDCP_S_
-};
-
-static int sndcp_rx_llc_prim()
-{
-	case LL_ESTABLISH_REQ:
-	case LL_RELEASE_REQ:
-	case LL_XID_REQ:
-	case LL_DATA_REQ:
-	LL_UNITDATA_REQ,	/* TLLI, SN-PDU, Ref, QoS, Radio Prio, Ciph */
-
-	switch (prim) {
-	case LL_RESET_IND:
-	case LL_ESTABLISH_IND:
-	case LL_ESTABLISH_RESP:
-	case LL_ESTABLISH_CONF:
-	case LL_RELEASE_IND:
-	case LL_RELEASE_CONF:
-	case LL_XID_IND:
-	case LL_XID_RESP:
-	case LL_XID_CONF:
-	case LL_DATA_IND:
-	case LL_DATA_CONF:
-	case LL_UNITDATA_IND:
-	case LL_STATUS_IND:
-	}
-}
-#endif
-
-/* Generate SNDCP-XID message */
-static int gprs_llc_gen_sndcp_xid(uint8_t *bytes, int bytes_len, uint8_t nsapi)
-{
-	int entity = 0;
-	LLIST_HEAD(comp_fields);
-	struct gprs_sndcp_pcomp_rfc1144_params rfc1144_params;
-	struct gprs_sndcp_comp_field rfc1144_comp_field;
-	struct gprs_sndcp_dcomp_v42bis_params v42bis_params;
-	struct gprs_sndcp_comp_field v42bis_comp_field;
-
-	memset(&rfc1144_comp_field, 0, sizeof(struct gprs_sndcp_comp_field));
-	memset(&v42bis_comp_field, 0, sizeof(struct gprs_sndcp_comp_field));
-
-	/* Setup rfc1144 */
-	if (sgsn->cfg.pcomp_rfc1144.active) {
-		rfc1144_params.nsapi[0] = nsapi;
-		rfc1144_params.nsapi_len = 1;
-		rfc1144_params.s01 = sgsn->cfg.pcomp_rfc1144.s01;
-		rfc1144_comp_field.p = 1;
-		rfc1144_comp_field.entity = entity;
-		rfc1144_comp_field.algo = RFC_1144;
-		rfc1144_comp_field.comp[RFC1144_PCOMP1] = 1;
-		rfc1144_comp_field.comp[RFC1144_PCOMP2] = 2;
-		rfc1144_comp_field.comp_len = RFC1144_PCOMP_NUM;
-		rfc1144_comp_field.rfc1144_params = &rfc1144_params;
-		entity++;
-		llist_add(&rfc1144_comp_field.list, &comp_fields);
-	}
-
-	/* Setup V.42bis */
-	if (sgsn->cfg.dcomp_v42bis.active) {
-		v42bis_params.nsapi[0] = nsapi;
-		v42bis_params.nsapi_len = 1;
-		v42bis_params.p0 = sgsn->cfg.dcomp_v42bis.p0;
-		v42bis_params.p1 = sgsn->cfg.dcomp_v42bis.p1;
-		v42bis_params.p2 = sgsn->cfg.dcomp_v42bis.p2;
-		v42bis_comp_field.p = 1;
-		v42bis_comp_field.entity = entity;
-		v42bis_comp_field.algo = V42BIS;
-		v42bis_comp_field.comp[V42BIS_DCOMP1] = 1;
-		v42bis_comp_field.comp_len = V42BIS_DCOMP_NUM;
-		v42bis_comp_field.v42bis_params = &v42bis_params;
-		entity++;
-		llist_add(&v42bis_comp_field.list, &comp_fields);
-	}
-
-	/* Do not attempt to compile anything if there is no data in the list */
-	if (llist_empty(&comp_fields))
-		return 0;
-
-	/* Compile bytestream */
-	return gprs_sndcp_compile_xid(bytes, bytes_len, &comp_fields,
-				      DEFAULT_SNDCP_VERSION);
-}
-
-/* Set of SNDCP-XID bnegotiation (See also: TS 144 065,
- * Section 6.8 XID parameter negotiation) */
-int sndcp_sn_xid_req(struct gprs_llc_lle *lle, uint8_t nsapi)
-{
-	/* Note: The specification requires the SNDCP-User to set of an
-	 * SNDCP xid request. See also 3GPP TS 44.065, 6.8 XID parameter
-	 * negotiation, Figure 11: SNDCP XID negotiation procedure. In
-	 * our case the SNDCP-User is sgsn_libgtp.c, which calls
-	 * sndcp_sn_xid_req directly. */
-
-	uint8_t l3params[1024];
-	int xid_len;
-	struct gprs_llc_xid_field xid_field_request;
-
-	/* Wipe off all compression entities and their states to
-	 * get rid of possible leftovers from a previous session */
-	gprs_sndcp_comp_free(lle->llme->comp.proto);
-	gprs_sndcp_comp_free(lle->llme->comp.data);
-	lle->llme->comp.proto = gprs_sndcp_comp_alloc(lle->llme);
-	lle->llme->comp.data = gprs_sndcp_comp_alloc(lle->llme);
-	talloc_free(lle->llme->xid);
-	lle->llme->xid = NULL;
-
-	/* Generate compression parameter bytestream */
-	xid_len = gprs_llc_gen_sndcp_xid(l3params, sizeof(l3params), nsapi);
-
-	/* Send XID with the SNDCP-XID bytetsream included */
-	if (xid_len > 0) {
-		xid_field_request.type = GPRS_LLC_XID_T_L3_PAR;
-		xid_field_request.data = l3params;
-		xid_field_request.data_len = xid_len;
-		return gprs_ll_xid_req(lle, &xid_field_request);
-	}
-
-	/* When bytestream can not be generated, proceed without SNDCP-XID */
-	return gprs_ll_xid_req(lle, NULL);
-
-}
-
-/* Handle header compression entites */
-static int handle_pcomp_entities(struct gprs_sndcp_comp_field *comp_field,
-				 struct gprs_llc_lle *lle)
-{
-	/* Note: This functions also transforms the comp_field into its
-	 * echo form (strips comp values, resets propose bit etc...)
-	 * the processed comp_fields can then be sent back as XID-
-	 * Response without further modification. */
-
-	/* Delete propose bit */
-	comp_field->p = 0;
-
-	/* Process proposed parameters */
-	switch (comp_field->algo) {
-	case RFC_1144:
-		if (sgsn->cfg.pcomp_rfc1144.passive
-		    && comp_field->rfc1144_params->nsapi_len > 0) {
-			DEBUGP(DSNDCP,
-			       "Accepting RFC1144 header compression...\n");
-			gprs_sndcp_comp_add(lle->llme, lle->llme->comp.proto,
-					    comp_field);
-		} else {
-			DEBUGP(DSNDCP,
-			       "Rejecting RFC1144 header compression...\n");
-			gprs_sndcp_comp_delete(lle->llme->comp.proto,
-					       comp_field->entity);
-			comp_field->rfc1144_params->nsapi_len = 0;
-		}
-		break;
-	case RFC_2507:
-		/* RFC 2507 is not yet supported,
-		 * so we set applicable nsapis to zero */
-		DEBUGP(DSNDCP, "Rejecting RFC2507 header compression...\n");
-		comp_field->rfc2507_params->nsapi_len = 0;
-		gprs_sndcp_comp_delete(lle->llme->comp.proto,
-				       comp_field->entity);
-		break;
-	case ROHC:
-		/* ROHC is not yet supported,
-		 * so we set applicable nsapis to zero */
-		DEBUGP(DSNDCP, "Rejecting ROHC header compression...\n");
-		comp_field->rohc_params->nsapi_len = 0;
-		gprs_sndcp_comp_delete(lle->llme->comp.proto,
-				       comp_field->entity);
-		break;
-	}
-
-	return 0;
-}
-
-/* Hanle data compression entites */
-static int handle_dcomp_entities(struct gprs_sndcp_comp_field *comp_field,
-				 struct gprs_llc_lle *lle)
-{
-	/* See note in handle_pcomp_entities() */
-
-	/* Delete propose bit */
-	comp_field->p = 0;
-
-	/* Process proposed parameters */
-	switch (comp_field->algo) {
-	case V42BIS:
-		if (sgsn->cfg.dcomp_v42bis.passive &&
-		    comp_field->v42bis_params->nsapi_len > 0) {
-			DEBUGP(DSNDCP,
-			       "Accepting V.42bis data compression...\n");
-			gprs_sndcp_comp_add(lle->llme, lle->llme->comp.data,
-					    comp_field);
-		} else {
-			LOGP(DSNDCP, LOGL_DEBUG,
-			     "Rejecting V.42bis data compression...\n");
-			gprs_sndcp_comp_delete(lle->llme->comp.data,
-					       comp_field->entity);
-			comp_field->v42bis_params->nsapi_len = 0;
-		}
-		break;
-	case V44:
-		/* V44 is not yet supported,
-		 * so we set applicable nsapis to zero */
-		DEBUGP(DSNDCP, "Rejecting V.44 data compression...\n");
-		comp_field->v44_params->nsapi_len = 0;
-		gprs_sndcp_comp_delete(lle->llme->comp.data,
-				       comp_field->entity);
-		break;
-	}
-
-	return 0;
-
-}
-
-/* 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)
-{
-	/* Note: This function computes the SNDCP-XID response that is sent
-	 * back to the ms when a ms originated XID is received. The
-	 * Input XID fields are directly processed and the result is directly
-	 * handed back. */
-
-	int rc;
-	int compclass;
-	int version;
-
-	struct llist_head *comp_fields;
-	struct gprs_sndcp_comp_field *comp_field;
-
-	OSMO_ASSERT(xid_field_indication);
-	OSMO_ASSERT(xid_field_response);
-	OSMO_ASSERT(lle);
-
-	/* Parse SNDCP-CID XID-Field */
-	comp_fields = gprs_sndcp_parse_xid(&version, lle->llme,
-					   xid_field_indication->data,
-					   xid_field_indication->data_len,
-					   NULL);
-	if (!comp_fields)
-		return -EINVAL;
-
-	/* Handle compression entites */
-	DEBUGP(DSNDCP, "SNDCP-XID-IND (ms):\n");
-	gprs_sndcp_dump_comp_fields(comp_fields, LOGL_DEBUG);
-
-	llist_for_each_entry(comp_field, comp_fields, list) {
-		compclass = gprs_sndcp_get_compression_class(comp_field);
-		if (compclass == SNDCP_XID_PROTOCOL_COMPRESSION)
-			rc = handle_pcomp_entities(comp_field, lle);
-		else if (compclass == SNDCP_XID_DATA_COMPRESSION)
-			rc = handle_dcomp_entities(comp_field, lle);
-		else {
-			gprs_sndcp_comp_delete(lle->llme->comp.proto,
-					       comp_field->entity);
-			gprs_sndcp_comp_delete(lle->llme->comp.data,
-					       comp_field->entity);
-			rc = 0;
-		}
-
-		if (rc < 0) {
-			talloc_free(comp_fields);
-			return -EINVAL;
-		}
-	}
-
-	DEBUGP(DSNDCP, "SNDCP-XID-RES (sgsn):\n");
-	gprs_sndcp_dump_comp_fields(comp_fields, LOGL_DEBUG);
-
-	/* Reserve some memory to store the modified SNDCP-XID bytes */
-	xid_field_response->data =
-	    talloc_zero_size(lle->llme, xid_field_indication->data_len);
-
-	/* Set Type flag for response */
-	xid_field_response->type = GPRS_LLC_XID_T_L3_PAR;
-
-	/* Compile modified SNDCP-XID bytes */
-	rc = gprs_sndcp_compile_xid(xid_field_response->data,
-				    xid_field_indication->data_len,
-				    comp_fields, 0);
-
-	if (rc > 0)
-		xid_field_response->data_len = rc;
-	else {
-		talloc_free(xid_field_response->data);
-		xid_field_response->data = NULL;
-		xid_field_response->data_len = 0;
-		return -EINVAL;
-	}
-
-	talloc_free(comp_fields);
-
-	return 0;
-}
-
-/* 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)
-{
-	/* Note: This function handles an incomming SNDCP-XID confirmiation.
-	 * Since the confirmation fields may lack important parameters we
-	 * will reconstruct these missing fields using the original request
-	 * we have sent. After that we will create (or delete) the
-	 * compression entites */
-
-	struct llist_head *comp_fields_req;
-	struct llist_head *comp_fields_conf;
-	struct gprs_sndcp_comp_field *comp_field;
-	int rc;
-	int compclass;
-
-	/* We need both, the confirmation that is sent back by the ms,
-	 * and the original request we have sent. If one of this is missing
-	 * we can not process the confirmation, the caller must check if
-	 * request and confirmation fields are available. */
-	OSMO_ASSERT(xid_field_conf);
-	OSMO_ASSERT(xid_field_request);
-
-	/* Parse SNDCP-CID XID-Field */
-	comp_fields_req = gprs_sndcp_parse_xid(NULL, lle->llme,
-					       xid_field_request->data,
-					       xid_field_request->data_len,
-					       NULL);
-	if (!comp_fields_req)
-		return -EINVAL;
-
-	DEBUGP(DSNDCP, "SNDCP-XID-REQ (sgsn):\n");
-	gprs_sndcp_dump_comp_fields(comp_fields_req, LOGL_DEBUG);
-
-	/* Parse SNDCP-CID XID-Field */
-	comp_fields_conf = gprs_sndcp_parse_xid(NULL, lle->llme,
-						xid_field_conf->data,
-						xid_field_conf->data_len,
-						comp_fields_req);
-	if (!comp_fields_conf)
-		return -EINVAL;
-
-	DEBUGP(DSNDCP, "SNDCP-XID-CONF (ms):\n");
-	gprs_sndcp_dump_comp_fields(comp_fields_conf, LOGL_DEBUG);
-
-	/* Handle compression entites */
-	llist_for_each_entry(comp_field, comp_fields_conf, list) {
-		compclass = gprs_sndcp_get_compression_class(comp_field);
-		if (compclass == SNDCP_XID_PROTOCOL_COMPRESSION)
-			rc = handle_pcomp_entities(comp_field, lle);
-		else if (compclass == SNDCP_XID_DATA_COMPRESSION)
-			rc = handle_dcomp_entities(comp_field, lle);
-		else {
-			gprs_sndcp_comp_delete(lle->llme->comp.proto,
-					       comp_field->entity);
-			gprs_sndcp_comp_delete(lle->llme->comp.data,
-					       comp_field->entity);
-			rc = 0;
-		}
-
-		if (rc < 0) {
-			talloc_free(comp_fields_req);
-			talloc_free(comp_fields_conf);
-			return -EINVAL;
-		}
-	}
-
-	talloc_free(comp_fields_req);
-	talloc_free(comp_fields_conf);
-
-	return 0;
-}
diff --git a/src/gprs/gprs_sndcp_comp.c b/src/gprs/gprs_sndcp_comp.c
deleted file mode 100644
index a12c39a..0000000
--- a/src/gprs/gprs_sndcp_comp.c
+++ /dev/null
@@ -1,323 +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/>.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <math.h>
-#include <errno.h>
-#include <stdbool.h>
-
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/gprs_sndcp_xid.h>
-#include <openbsc/gprs_sndcp_comp.h>
-#include <openbsc/gprs_sndcp_pcomp.h>
-#include <openbsc/gprs_sndcp_dcomp.h>
-
-/* Create a new compression entity from a XID-Field */
-static struct gprs_sndcp_comp *gprs_sndcp_comp_create(const void *ctx,
-						      const struct
-						      gprs_sndcp_comp_field
-						      *comp_field)
-{
-	struct gprs_sndcp_comp *comp_entity;
-	comp_entity = talloc_zero(ctx, struct gprs_sndcp_comp);
-
-	/* Copy relevant information from the SNDCP-XID field */
-	comp_entity->entity = comp_field->entity;
-	comp_entity->comp_len = comp_field->comp_len;
-	memcpy(comp_entity->comp, comp_field->comp, sizeof(comp_entity->comp));
-
-	if (comp_field->rfc1144_params) {
-		comp_entity->nsapi_len = comp_field->rfc1144_params->nsapi_len;
-		memcpy(comp_entity->nsapi,
-		       comp_field->rfc1144_params->nsapi,
-		       sizeof(comp_entity->nsapi));
-	} else if (comp_field->rfc2507_params) {
-		comp_entity->nsapi_len = comp_field->rfc2507_params->nsapi_len;
-		memcpy(comp_entity->nsapi,
-		       comp_field->rfc2507_params->nsapi,
-		       sizeof(comp_entity->nsapi));
-	} else if (comp_field->rohc_params) {
-		comp_entity->nsapi_len = comp_field->rohc_params->nsapi_len;
-		memcpy(comp_entity->nsapi, comp_field->rohc_params->nsapi,
-		       sizeof(comp_entity->nsapi));
-	} else if (comp_field->v42bis_params) {
-		comp_entity->nsapi_len = comp_field->v42bis_params->nsapi_len;
-		memcpy(comp_entity->nsapi,
-		       comp_field->v42bis_params->nsapi,
-		       sizeof(comp_entity->nsapi));
-	} else if (comp_field->v44_params) {
-		comp_entity->nsapi_len = comp_field->v44_params->nsapi_len;
-		memcpy(comp_entity->nsapi,
-		       comp_field->v44_params->nsapi,
-		       sizeof(comp_entity->nsapi));
-	} else {
-		/* The caller is expected to check carefully if the all
-		 * data fields required for compression entity creation
-		 * are present. Otherwise we blow an assertion here */
-		OSMO_ASSERT(false);
-	}
-	comp_entity->algo = comp_field->algo;
-
-	/* Check if an NSAPI is selected, if not, it does not make sense
-	 * to create the compression entity, since the caller should
-	 * have checked the presence of the NSAPI, we blow an assertion
-	 * in case of missing NSAPIs */
-	OSMO_ASSERT(comp_entity->nsapi_len > 0);
-
-	/* Determine of which class our compression entity will be
-	 * (Protocol or Data compresson ?) */
-	comp_entity->compclass = gprs_sndcp_get_compression_class(comp_field);
-
-	OSMO_ASSERT(comp_entity->compclass != -1);
-
-	/* Create an algorithm specific compression context */
-	if (comp_entity->compclass == SNDCP_XID_PROTOCOL_COMPRESSION) {
-		if (gprs_sndcp_pcomp_init(ctx, comp_entity, comp_field) != 0) {
-			talloc_free(comp_entity);
-			comp_entity = NULL;
-		}
-	} else {
-		if (gprs_sndcp_dcomp_init(ctx, comp_entity, comp_field) != 0) {
-			talloc_free(comp_entity);
-			comp_entity = NULL;
-		}
-	}
-
-	/* Bail on failure */
-	if (comp_entity == NULL) {
-		LOGP(DSNDCP, LOGL_ERROR,
-		     "Compression entity creation failed!\n");
-		return NULL;
-	}
-
-	/* Display info message */
-	if (comp_entity->compclass == SNDCP_XID_PROTOCOL_COMPRESSION) {
-		LOGP(DSNDCP, LOGL_INFO,
-		     "New header compression entity (%d) created.\n",
-		     comp_entity->entity);
-	} else {
-		LOGP(DSNDCP, LOGL_INFO,
-		     "New data compression entity (%d) created.\n",
-		     comp_entity->entity);
-	}
-
-	return comp_entity;
-}
-
-/* Allocate a compression enitiy list */
-struct llist_head *gprs_sndcp_comp_alloc(const void *ctx)
-{
-	struct llist_head *lh;
-
-	lh = talloc_zero(ctx, struct llist_head);
-	INIT_LLIST_HEAD(lh);
-
-	return lh;
-}
-
-/* Free a compression entitiy list */
-void gprs_sndcp_comp_free(struct llist_head *comp_entities)
-{
-	struct gprs_sndcp_comp *comp_entity;
-
-	/* We expect the caller to take care of allocating a
-	 * compression entity list properly. Attempting to
-	 * free a non existing list clearly points out
-	 * a malfunction. */
-	OSMO_ASSERT(comp_entities);
-
-	llist_for_each_entry(comp_entity, comp_entities, list) {
-		/* Free compression entity */
-		if (comp_entity->compclass == SNDCP_XID_PROTOCOL_COMPRESSION) {
-			LOGP(DSNDCP, LOGL_INFO,
-			     "Deleting header compression entity %d ...\n",
-			     comp_entity->entity);
-			gprs_sndcp_pcomp_term(comp_entity);
-		} else {
-			LOGP(DSNDCP, LOGL_INFO,
-			     "Deleting data compression entity %d ...\n",
-			     comp_entity->entity);
-			gprs_sndcp_dcomp_term(comp_entity);
-		}
-	}
-
-	talloc_free(comp_entities);
-}
-
-/* Delete a compression entity */
-void gprs_sndcp_comp_delete(struct llist_head *comp_entities,
-			    unsigned int entity)
-{
-	struct gprs_sndcp_comp *comp_entity;
-	struct gprs_sndcp_comp *comp_entity_to_delete = NULL;
-
-	OSMO_ASSERT(comp_entities);
-
-	llist_for_each_entry(comp_entity, comp_entities, list) {
-		if (comp_entity->entity == entity) {
-			comp_entity_to_delete = comp_entity;
-			break;
-		}
-	}
-
-	if (!comp_entity_to_delete)
-		return;
-
-	if (comp_entity_to_delete->compclass == SNDCP_XID_PROTOCOL_COMPRESSION) {
-		LOGP(DSNDCP, LOGL_INFO,
-		     "Deleting header compression entity %d ...\n",
-		     comp_entity_to_delete->entity);
-		gprs_sndcp_pcomp_term(comp_entity_to_delete);
-	} else {
-		LOGP(DSNDCP, LOGL_INFO,
-		     "Deleting data compression entity %d ...\n",
-		     comp_entity_to_delete->entity);
-	}
-
-	/* Delete compression entity */
-	llist_del(&comp_entity_to_delete->list);
-	talloc_free(comp_entity_to_delete);
-}
-
-/* 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)
-{
-	struct gprs_sndcp_comp *comp_entity;
-
-	OSMO_ASSERT(comp_entities);
-	OSMO_ASSERT(comp_field);
-
-	/* Just to be sure, if the entity is already in
-	 * the list it will be deleted now */
-	gprs_sndcp_comp_delete(comp_entities, comp_field->entity);
-
-	/* Create and add a new entity to the list */
-	comp_entity = gprs_sndcp_comp_create(ctx, comp_field);
-
-	if (!comp_entity)
-		return NULL;
-
-	llist_add(&comp_entity->list, comp_entities);
-	return comp_entity;
-}
-
-/* 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)
-{
-	struct gprs_sndcp_comp *comp_entity;
-	int i;
-
-	OSMO_ASSERT(comp_entities);
-
-	llist_for_each_entry(comp_entity, comp_entities, list) {
-		for (i = 0; i < comp_entity->comp_len; i++) {
-			if (comp_entity->comp[i] == comp)
-				return comp_entity;
-		}
-	}
-
-	LOGP(DSNDCP, LOGL_ERROR,
-	     "Could not find a matching compression entity for given pcomp/dcomp value %d.\n",
-	     comp);
-	return NULL;
-}
-
-/* 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)
-{
-	struct gprs_sndcp_comp *comp_entity;
-	int i;
-
-	OSMO_ASSERT(comp_entities);
-
-	llist_for_each_entry(comp_entity, comp_entities, list) {
-		for (i = 0; i < comp_entity->nsapi_len; i++) {
-			if (comp_entity->nsapi[i] == nsapi)
-				return comp_entity;
-		}
-	}
-
-	return NULL;
-}
-
-/* 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)
-{
-	/* Note: This function returns a normalized version of the comp value,
-	 * which matches up with the position of the comp field. Since comp=0
-	 * is reserved for "no compression", the index value starts counting
-	 * at one. The return value is the PCOMPn/DCOMPn value one can find
-	 * in the Specification (see e.g. 3GPP TS 44.065, 6.5.3.2, Table 7) */
-
-	int i;
-	OSMO_ASSERT(comp_entity);
-
-	/* A pcomp/dcomp value of zero is reserved for "no comproession",
-	 * So we just bail and return zero in this case */
-	if (comp == 0)
-		return 0;
-
-	/* Look in the pcomp/dcomp list for the index */
-	for (i = 0; i < comp_entity->comp_len; i++) {
-		if (comp_entity->comp[i] == comp)
-			return i + 1;
-	}
-
-	LOGP(DSNDCP, LOGL_ERROR,
-	     "Could not find a matching comp_index for given pcomp/dcomp value %d\n",
-	     comp);
-	return 0;
-}
-
-/* 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)
-{
-	OSMO_ASSERT(comp_entity);
-
-	/* A comp_index of zero translates to zero right away. */
-	if (comp_index == 0)
-		return 0;
-
-	if (comp_index > comp_entity->comp_len) {
-		LOGP(DSNDCP, LOGL_ERROR,
-		     "Could not find a matching pcomp/dcomp value for given comp_index value %d.\n",
-		     comp_index);
-		return 0;
-	}
-
-	/* Look in the pcomp/dcomp list for the comp_index, see
-	 * note in gprs_sndcp_comp_get_idx() */
-	return comp_entity->comp[comp_index - 1];
-}
diff --git a/src/gprs/gprs_sndcp_dcomp.c b/src/gprs/gprs_sndcp_dcomp.c
deleted file mode 100644
index b0f95b4..0000000
--- a/src/gprs/gprs_sndcp_dcomp.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/* GPRS SNDCP data compression handler */
-
-/* (C) 2016 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/>.
- *
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <math.h>
-#include <errno.h>
-#include <stdbool.h>
-
-#include <osmocom/core/utils.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/gsm/tlv.h>
-
-#include <openbsc/gprs_llc.h>
-#include <openbsc/sgsn.h>
-#include <openbsc/gprs_sndcp_xid.h>
-#include <openbsc/v42bis.h>
-#include <openbsc/v42bis_private.h>
-#include <openbsc/debug.h>
-#include <openbsc/gprs_sndcp_comp.h>
-#include <openbsc/gprs_sndcp_dcomp.h>
-
-/* A struct to capture the output data of compressor and decompressor */
-struct v42bis_output_buffer {
-	uint8_t *buf;
-	uint8_t *buf_pointer;
-	int len;
-};
-
-/* Handler to capture the output data from the compressor */
-void tx_v42bis_frame_handler(void *user_data, const uint8_t *pkt, int len)
-{
-	struct v42bis_output_buffer *output_buffer =
-	    (struct v42bis_output_buffer *)user_data;
-	memcpy(output_buffer->buf_pointer, pkt, len);
-	output_buffer->buf_pointer += len;
-	output_buffer->len += len;
-	return;
-}
-
-/* Handler to capture the output data from the decompressor */
-void rx_v42bis_data_handler(void *user_data, const uint8_t *buf, int len)
-{
-	struct v42bis_output_buffer *output_buffer =
-	    (struct v42bis_output_buffer *)user_data;
-	memcpy(output_buffer->buf_pointer, buf, len);
-	output_buffer->buf_pointer += len;
-	output_buffer->len += len;
-	return;
-}
-
-/* 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)
-{
-	/* Note: This function is automatically called from
-	 * gprs_sndcp_comp.c when a new data compression
-	 * entity is created by gprs_sndcp.c */
-
-	OSMO_ASSERT(comp_entity);
-	OSMO_ASSERT(comp_field);
-
-	if (comp_entity->compclass == SNDCP_XID_DATA_COMPRESSION
-	    && comp_entity->algo == V42BIS) {
-		OSMO_ASSERT(comp_field->v42bis_params);
-		comp_entity->state =
-		    v42bis_init(ctx, NULL, comp_field->v42bis_params->p0,
-				comp_field->v42bis_params->p1,
-				comp_field->v42bis_params->p2,
-				&tx_v42bis_frame_handler, NULL,
-				V42BIS_MAX_OUTPUT_LENGTH,
-				&rx_v42bis_data_handler, NULL,
-				V42BIS_MAX_OUTPUT_LENGTH);
-		LOGP(DSNDCP, LOGL_INFO,
-		     "V.42bis data compression initalized.\n");
-		return 0;
-	}
-
-	/* Just in case someone tries to initalize an unknown or unsupported
-	 * data compresson. Since everything is checked during the SNDCP
-	 * negotiation process, this should never happen! */
-	OSMO_ASSERT(false);
-}
-
-/* Terminate data compression */
-void gprs_sndcp_dcomp_term(struct gprs_sndcp_comp *comp_entity)
-{
-	/* Note: This function is automatically called from
-	 * gprs_sndcp_comp.c when a data compression
-	 * entity is deleted by gprs_sndcp.c */
-
-	OSMO_ASSERT(comp_entity);
-
-	if (comp_entity->compclass == SNDCP_XID_DATA_COMPRESSION
-	    && comp_entity->algo == V42BIS) {
-		if (comp_entity->state) {
-			v42bis_free((v42bis_state_t *) comp_entity->state);
-			comp_entity->state = NULL;
-		}
-		LOGP(DSNDCP, LOGL_INFO,
-		     "V.42bis data compression terminated.\n");
-		return;
-	}
-
-	/* Just in case someone tries to terminate an unknown or unsupported
-	 * data compresson. Since everything is checked during the SNDCP
-	 * negotiation process, this should never happen! */
-	OSMO_ASSERT(false);
-}
-
-/* Perform a full reset of the V.42bis compression state */
-static void v42bis_reset(v42bis_state_t *comp)
-{
-	/* This function performs a complete reset of the V.42bis compression
-	 * state by reinitalizing the state withe the previously negotiated
-	 * parameters. */
-
-	int p0, p1, p2;
-	p0 = comp->decompress.v42bis_parm_p0 | comp->compress.v42bis_parm_p0;
-	p1 = comp->decompress.v42bis_parm_n2;
-	p2 = comp->decompress.v42bis_parm_n7;
-
-	DEBUGP(DSNDCP, "Resetting compression state: %p, p0=%d, p1=%d, p2=%d\n",
-	       comp, p0, p1, p2);
-
-	v42bis_init(NULL, comp, p0, p1, p2, &tx_v42bis_frame_handler, NULL,
-		    V42BIS_MAX_OUTPUT_LENGTH, &rx_v42bis_data_handler, NULL,
-		    V42BIS_MAX_OUTPUT_LENGTH);
-}
-
-/* Compress a packet using V.42bis data compression */
-static int v42bis_compress_unitdata(uint8_t *pcomp_index, uint8_t *data,
-				    unsigned int len, v42bis_state_t *comp)
-{
-	/* Note: This implementation may only be used to compress SN_UNITDATA
-	 * packets, since it resets the compression state for each NPDU. */
-
-	uint8_t *data_o;
-	int rc;
-	int skip = 0;
-	struct v42bis_output_buffer compressed_data;
-
-	/* Don't bother with short packets */
-	if (len < MIN_COMPR_PAYLOAD)
-		skip = 1;
-
-	/* Skip if compression is not enabled for TX direction */
-	if (!comp->compress.v42bis_parm_p0)
-		skip = 1;
-
-	/* Skip compression */
-	if (skip) {
-		*pcomp_index = 0;
-		return len;
-	}
-
-	/* Reset V.42bis compression state */
-	v42bis_reset(comp);
-
-	/* Run compressor */
-	data_o = talloc_zero_size(comp, len * MAX_DATADECOMPR_FAC);
-	compressed_data.buf = data_o;
-	compressed_data.buf_pointer = data_o;
-	compressed_data.len = 0;
-	comp->compress.user_data = (&compressed_data);
-	rc = v42bis_compress(comp, data, len);
-	if (rc < 0) {
-		LOGP(DSNDCP, LOGL_ERROR,
-		     "Data compression failed, skipping...\n");
-		skip = 1;
-	}
-	rc = v42bis_compress_flush(comp);
-	if (rc < 0) {
-		LOGP(DSNDCP, LOGL_ERROR,
-		     "Data compression failed, skipping...\n");
-		skip = 1;
-	}
-
-	/* The compressor might yield negative compression gain, in
-	 * this case, we just decide to send the packat as normal,
-	 * uncompressed payload => skip compresssion */
-	if (compressed_data.len >= len) {
-		LOGP(DSNDCP, LOGL_ERROR,
-		     "Data compression ineffective, skipping...\n");
-		skip = 1;
-	}
-
-	/* Skip compression */
-	if (skip) {
-		*pcomp_index = 0;
-		talloc_free(data_o);
-		return len;
-	}
-
-	*pcomp_index = 1;
-	memcpy(data, data_o, compressed_data.len);
-	talloc_free(data_o);
-
-	return compressed_data.len;
-}
-
-/* Expand a packet using V.42bis data compression */
-static int v42bis_expand_unitdata(uint8_t *data, unsigned int len,
-				  uint8_t pcomp_index, v42bis_state_t *comp)
-{
-	/* Note: This implementation may only be used to compress SN_UNITDATA
-	 * packets, since it resets the compression state for each NPDU. */
-
-	int rc;
-	struct v42bis_output_buffer uncompressed_data;
-	uint8_t *data_i;
-
-	/* Skip when the packet is marked as uncompressed */
-	if (pcomp_index == 0) {
-		return len;
-	}
-
-	/* Reset V.42bis compression state */
-	v42bis_reset(comp);
-
-	/* Decompress packet */
-	data_i = talloc_zero_size(comp, len);
-	memcpy(data_i, data, len);
-	uncompressed_data.buf = data;
-	uncompressed_data.buf_pointer = data;
-	uncompressed_data.len = 0;
-	comp->decompress.user_data = (&uncompressed_data);
-	rc = v42bis_decompress(comp, data_i, len);
-	talloc_free(data_i);
-	if (rc < 0)
-		return -EINVAL;
-	rc = v42bis_decompress_flush(comp);
-	if (rc < 0)
-		return -EINVAL;
-
-	return uncompressed_data.len;
-}
-
-/* Expand packet */
-int gprs_sndcp_dcomp_expand(uint8_t *data, unsigned int len, uint8_t pcomp,
-			    const struct llist_head *comp_entities)
-{
-	int rc;
-	uint8_t pcomp_index = 0;
-	struct gprs_sndcp_comp *comp_entity;
-
-	OSMO_ASSERT(data);
-	OSMO_ASSERT(comp_entities);
-
-	LOGP(DSNDCP, LOGL_DEBUG,
-	     "Data compression entity list: comp_entities=%p\n", comp_entities);
-
-	LOGP(DSNDCP, LOGL_DEBUG, "Data compression mode: dcomp=%d\n", pcomp);
-
-	/* Skip on pcomp=0 */
-	if (pcomp == 0) {
-		return len;
-	}
-
-	/* Find out which compression entity handles the data */
-	comp_entity = gprs_sndcp_comp_by_comp(comp_entities, pcomp);
-
-	/* Skip compression if no suitable compression entity can be found */
-	if (!comp_entity) {
-		return len;
-	}
-
-	/* Note: Only data compression entities may appear in
-	 * data compression context */
-	OSMO_ASSERT(comp_entity->compclass == SNDCP_XID_DATA_COMPRESSION);
-
-	/* Note: Currently V42BIS is the only compression method we
-	 * support, so the only allowed algorithm is V42BIS */
-	OSMO_ASSERT(comp_entity->algo == V42BIS);
-
-	/* Find pcomp_index */
-	pcomp_index = gprs_sndcp_comp_get_idx(comp_entity, pcomp);
-
-	/* Run decompression algo */
-	rc = v42bis_expand_unitdata(data, len, pcomp_index, comp_entity->state);
-
-	LOGP(DSNDCP, LOGL_DEBUG,
-	     "Data expansion done, old length=%d, new length=%d, entity=%p\n",
-	     len, rc, comp_entity);
-
-	return rc;
-}
-
-/* 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)
-{
-	int rc;
-	uint8_t pcomp_index = 0;
-	struct gprs_sndcp_comp *comp_entity;
-
-	OSMO_ASSERT(data);
-	OSMO_ASSERT(pcomp);
-	OSMO_ASSERT(comp_entities);
-
-	LOGP(DSNDCP, LOGL_DEBUG,
-	     "Data compression entity list: comp_entities=%p\n", comp_entities);
-
-	/* Find out which compression entity handles the data */
-	comp_entity = gprs_sndcp_comp_by_nsapi(comp_entities, nsapi);
-
-	/* Skip compression if no suitable compression entity can be found */
-	if (!comp_entity) {
-		*pcomp = 0;
-		return len;
-	}
-
-	/* Note: Only data compression entities may appear in
-	 * data compression context */
-	OSMO_ASSERT(comp_entity->compclass == SNDCP_XID_DATA_COMPRESSION);
-
-	/* Note: Currently V42BIS is the only compression method we
-	 * support, so the only allowed algorithm is V42BIS */
-	OSMO_ASSERT(comp_entity->algo == V42BIS);
-
-	/* Run compression algo */
-	rc = v42bis_compress_unitdata(&pcomp_index, data, len,
-				      comp_entity->state);
-
-	/* Find pcomp value */
-	*pcomp = gprs_sndcp_comp_get_comp(comp_entity, pcomp_index);
-
-	LOGP(DSNDCP, LOGL_DEBUG, "Data compression mode: dcomp=%d\n", *pcomp);
-
-	LOGP(DSNDCP, LOGL_DEBUG,
-	     "Data compression done, old length=%d, new length=%d, entity=%p\n",
-	     len, rc, comp_entity);
-
-	return rc;
-}
diff --git a/src/gprs/gprs_sndcp_pcomp.c b/src/gprs/gprs_sndcp_pcomp.c
deleted file mode 100644
index a2236c3..0000000
--- a/src/gprs/gprs_sndcp_pcomp.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/* GPRS SNDCP header compression handler */
-
-/* (C) 2016 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/>.
- *
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <math.h>
-#include <errno.h>
-#include <stdbool.h>
-
-#include <osmocom/core/utils.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/gsm/tlv.h>
-
-#include <openbsc/gprs_llc.h>
-#include <openbsc/sgsn.h>
-#include <openbsc/gprs_sndcp_xid.h>
-#include <openbsc/slhc.h>
-#include <openbsc/debug.h>
-#include <openbsc/gprs_sndcp_comp.h>
-#include <openbsc/gprs_sndcp_pcomp.h>
-
-/* 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)
-{
-	/* Note: This function is automatically called from
-	 * gprs_sndcp_comp.c when a new header compression
-	 * entity is created by gprs_sndcp.c */
-
-	OSMO_ASSERT(comp_entity);
-	OSMO_ASSERT(comp_field);
-
-	if (comp_entity->compclass == SNDCP_XID_PROTOCOL_COMPRESSION
-	    && comp_entity->algo == RFC_1144) {
-		OSMO_ASSERT(comp_field->rfc1144_params);
-		comp_entity->state =
-		    slhc_init(ctx, comp_field->rfc1144_params->s01 + 1,
-			      comp_field->rfc1144_params->s01 + 1);
-		LOGP(DSNDCP, LOGL_INFO,
-		     "RFC1144 header compression initalized.\n");
-		return 0;
-	}
-
-	/* Just in case someone tries to initalize an unknown or unsupported
-	 * header compresson. Since everything is checked during the SNDCP
-	 * negotiation process, this should never happen! */
-	OSMO_ASSERT(false);
-}
-
-/* Terminate header compression */
-void gprs_sndcp_pcomp_term(struct gprs_sndcp_comp *comp_entity)
-{
-	/* Note: This function is automatically called from
-	 * gprs_sndcp_comp.c when a header compression
-	 * entity is deleted by gprs_sndcp.c */
-
-	OSMO_ASSERT(comp_entity);
-
-	if (comp_entity->compclass == SNDCP_XID_PROTOCOL_COMPRESSION
-	    && comp_entity->algo == RFC_1144) {
-		if (comp_entity->state) {
-			slhc_free((struct slcompress *)comp_entity->state);
-			comp_entity->state = NULL;
-		}
-		LOGP(DSNDCP, LOGL_INFO,
-		     "RFC1144 header compression terminated.\n");
-		return;
-	}
-
-	/* Just in case someone tries to terminate an unknown or unsupported
-	 * data compresson. Since everything is checked during the SNDCP
-	 * negotiation process, this should never happen! */
-	OSMO_ASSERT(false);
-}
-
-/* Compress a packet using Van Jacobson RFC1144 header compression */
-static int rfc1144_compress(uint8_t *pcomp_index, uint8_t *data,
-			    unsigned int len, struct slcompress *comp)
-{
-	uint8_t *comp_ptr;
-	int compr_len;
-	uint8_t *data_o;
-
-	/* Create a working copy of the incoming data */
-	data_o = talloc_zero_size(comp, len);
-	memcpy(data_o, data, len);
-
-	/* Run compressor */
-	compr_len = slhc_compress(comp, data, len, data_o, &comp_ptr, 0);
-
-	/* Generate pcomp_index */
-	if (data_o[0] & SL_TYPE_COMPRESSED_TCP) {
-		*pcomp_index = 2;
-		data_o[0] &= ~SL_TYPE_COMPRESSED_TCP;
-		memcpy(data, data_o, compr_len);
-	} else if ((data_o[0] & SL_TYPE_UNCOMPRESSED_TCP) ==
-		   SL_TYPE_UNCOMPRESSED_TCP) {
-		*pcomp_index = 1;
-		data_o[0] &= 0x4F;
-		memcpy(data, data_o, compr_len);
-	} else
-		*pcomp_index = 0;
-
-	talloc_free(data_o);
-	return compr_len;
-}
-
-/* Expand a packet using Van Jacobson RFC1144 header compression */
-static int rfc1144_expand(uint8_t *data, unsigned int len, uint8_t pcomp_index,
-			  struct slcompress *comp)
-{
-	int data_decompressed_len;
-	int type;
-
-	/* Note: this function should never be called with pcomp_index=0,
-	 * since this condition is already filtered
-	 * out by gprs_sndcp_pcomp_expand() */
-
-	/* Determine the data type by the PCOMP index */
-	switch (pcomp_index) {
-	case 0:
-		type = SL_TYPE_IP;
-		break;
-	case 1:
-		type = SL_TYPE_UNCOMPRESSED_TCP;
-		break;
-	case 2:
-		type = SL_TYPE_COMPRESSED_TCP;
-		break;
-	default:
-		LOGP(DSNDCP, LOGL_ERROR,
-		     "rfc1144_expand() Invalid pcomp_index value (%d) detected, assuming no compression!\n",
-		     pcomp_index);
-		type = SL_TYPE_IP;
-		break;
-	}
-
-	/* Restore the original version nibble on
-	 * marked uncompressed packets */
-	if (type == SL_TYPE_UNCOMPRESSED_TCP) {
-		/* Just in case the phone tags uncompressed tcp-data
-		 * (normally this is handled by pcomp so there is
-		 * no need for tagging the data) */
-		data[0] &= 0x4F;
-		data_decompressed_len = slhc_remember(comp, data, len);
-		return data_decompressed_len;
-	}
-
-	/* Uncompress compressed packets */
-	else if (type == SL_TYPE_COMPRESSED_TCP) {
-		data_decompressed_len = slhc_uncompress(comp, data, len);
-		return data_decompressed_len;
-	}
-
-	/* Regular or unknown packets will not be touched */
-	return len;
-}
-
-/* Expand packet header */
-int gprs_sndcp_pcomp_expand(uint8_t *data, unsigned int len, uint8_t pcomp,
-			    const struct llist_head *comp_entities)
-{
-	int rc;
-	uint8_t pcomp_index = 0;
-	struct gprs_sndcp_comp *comp_entity;
-
-	OSMO_ASSERT(data);
-	OSMO_ASSERT(comp_entities);
-
-	LOGP(DSNDCP, LOGL_DEBUG,
-	     "Header compression entity list: comp_entities=%p\n",
-	     comp_entities);
-
-	LOGP(DSNDCP, LOGL_DEBUG, "Header compression mode: pcomp=%d\n", pcomp);
-
-	/* Skip on pcomp=0 */
-	if (pcomp == 0) {
-		return len;
-	}
-
-	/* Find out which compression entity handles the data */
-	comp_entity = gprs_sndcp_comp_by_comp(comp_entities, pcomp);
-
-	/* Skip compression if no suitable compression entity can be found */
-	if (!comp_entity) {
-		return len;
-	}
-
-	/* Note: Only protocol compression entities may appear in
-	 * protocol compression context */
-	OSMO_ASSERT(comp_entity->compclass == SNDCP_XID_PROTOCOL_COMPRESSION);
-
-	/* Note: Currently RFC1144 is the only compression method we
-	 * support, so the only allowed algorithm is RFC1144 */
-	OSMO_ASSERT(comp_entity->algo == RFC_1144);
-
-	/* Find pcomp_index */
-	pcomp_index = gprs_sndcp_comp_get_idx(comp_entity, pcomp);
-
-	/* Run decompression algo */
-	rc = rfc1144_expand(data, len, pcomp_index, comp_entity->state);
-	slhc_i_status(comp_entity->state);
-	slhc_o_status(comp_entity->state);
-
-	LOGP(DSNDCP, LOGL_DEBUG,
-	     "Header expansion done, old length=%d, new length=%d, entity=%p\n",
-	     len, rc, comp_entity);
-
-	return rc;
-}
-
-/* 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)
-{
-	int rc;
-	uint8_t pcomp_index = 0;
-	struct gprs_sndcp_comp *comp_entity;
-
-	OSMO_ASSERT(data);
-	OSMO_ASSERT(pcomp);
-	OSMO_ASSERT(comp_entities);
-
-	LOGP(DSNDCP, LOGL_DEBUG,
-	     "Header compression entity list: comp_entities=%p\n",
-	     comp_entities);
-
-	/* Find out which compression entity handles the data */
-	comp_entity = gprs_sndcp_comp_by_nsapi(comp_entities, nsapi);
-
-	/* Skip compression if no suitable compression entity can be found */
-	if (!comp_entity) {
-		*pcomp = 0;
-		return len;
-	}
-
-	/* Note: Only protocol compression entities may appear in
-	 * protocol compression context */
-	OSMO_ASSERT(comp_entity->compclass == SNDCP_XID_PROTOCOL_COMPRESSION);
-
-	/* Note: Currently RFC1144 is the only compression method we
-	 * support, so the only allowed algorithm is RFC1144 */
-	OSMO_ASSERT(comp_entity->algo == RFC_1144);
-
-	/* Run compression algo */
-	rc = rfc1144_compress(&pcomp_index, data, len, comp_entity->state);
-	slhc_i_status(comp_entity->state);
-	slhc_o_status(comp_entity->state);
-
-	/* Find pcomp value */
-	*pcomp = gprs_sndcp_comp_get_comp(comp_entity, pcomp_index);
-
-	LOGP(DSNDCP, LOGL_DEBUG, "Header compression mode: pcomp=%d\n", *pcomp);
-
-	LOGP(DSNDCP, LOGL_DEBUG,
-	     "Header compression done, old length=%d, new length=%d, entity=%p\n",
-	     len, rc, comp_entity);
-	return rc;
-}
diff --git a/src/gprs/gprs_sndcp_vty.c b/src/gprs/gprs_sndcp_vty.c
deleted file mode 100644
index 430881f..0000000
--- a/src/gprs/gprs_sndcp_vty.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/* VTY interface for our GPRS SNDCP implementation */
-
-/* (C) 2010 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/>.
- *
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdint.h>
-
-#include <arpa/inet.h>
-
-#include <openbsc/gsm_data.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/rate_ctr.h>
-#include <openbsc/debug.h>
-#include <openbsc/signal.h>
-#include <openbsc/gprs_llc.h>
-#include <openbsc/gprs_sndcp.h>
-
-#include <osmocom/vty/vty.h>
-#include <osmocom/vty/command.h>
-
-static void vty_dump_sne(struct vty *vty, struct gprs_sndcp_entity *sne)
-{
-	vty_out(vty, " TLLI %08x SAPI=%u NSAPI=%u:%s",
-		sne->lle->llme->tlli, sne->lle->sapi, sne->nsapi, VTY_NEWLINE);
-	vty_out(vty, "  Defrag: npdu=%u highest_seg=%u seg_have=0x%08x tot_len=%u%s",
-		sne->defrag.npdu, sne->defrag.highest_seg, sne->defrag.seg_have,
-		sne->defrag.tot_len, VTY_NEWLINE);
-}
-
-
-DEFUN(show_sndcp, show_sndcp_cmd,
-	"show sndcp",
-	SHOW_STR "Display information about the SNDCP protocol")
-{
-	struct gprs_sndcp_entity *sne;
-
-	vty_out(vty, "State of SNDCP Entities%s", VTY_NEWLINE);
-	llist_for_each_entry(sne, &gprs_sndcp_entities, list)
-		vty_dump_sne(vty, sne);
-
-	return CMD_SUCCESS;
-}
-
-int gprs_sndcp_vty_init(void)
-{
-	install_element_ve(&show_sndcp_cmd);
-
-	return 0;
-}
diff --git a/src/gprs/gprs_sndcp_xid.c b/src/gprs/gprs_sndcp_xid.c
deleted file mode 100644
index dfea5fe..0000000
--- a/src/gprs/gprs_sndcp_xid.c
+++ /dev/null
@@ -1,1822 +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/>.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <math.h>
-#include <errno.h>
-
-#include <osmocom/core/utils.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/gsm/tlv.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/gprs_llc.h>
-#include <openbsc/sgsn.h>
-#include <openbsc/gprs_sndcp_xid.h>
-
-/* When the propose bit in an SNDCP-XID compression field is set to zero,
- * the algorithm identifier is stripped. The algoritm parameters are specific
- * for each algorithms. The following struct is used to pass the information
- * about the referenced algorithm to the parser. */
-struct entity_algo_table {
-	unsigned int entity;	/* see also: 6.5.1.1.3 and 6.6.1.1.3 */
-	unsigned int algo;	/* see also: 6.5.1.1.4 and 6.6.1.1.4 */
-	unsigned int compclass;	/* Can be either SNDCP_XID_DATA_COMPRESSION or
-				   SNDCP_XID_PROTOCOL_COMPRESSION */
-};
-
-/* FUNCTIONS RELATED TO SNDCP-XID ENCODING */
-
-/* Encode applicable sapis (works the same in all three compression schemes) */
-static int encode_pcomp_applicable_sapis(uint8_t *dst,
-					 const uint8_t *nsapis,
-					 uint8_t nsapis_len)
-{
-	/* NOTE: Buffer *dst needs offer at 2 bytes
-	 * of space to store the generation results */
-
-	uint16_t blob;
-	uint8_t nsapi;
-	int i;
-
-	/* Bail if number of possible nsapis exceeds valid range
-	 * (Only 11 nsapis possible for PDP-Contexts) */
-	OSMO_ASSERT(nsapis_len <= 11);
-
-	/* Encode applicable SAPIs */
-	blob = 0;
-	for (i = 0; i < nsapis_len; i++) {
-		nsapi = nsapis[i];
-		/* Only NSAPI 5 to 15 are applicable for user traffic (PDP-
-		 * contexts). Only for these NSAPIs SNDCP-XID parameters
-		 * can apply. See also 3GPP TS 44.065, 5.1 Service primitives */
-		OSMO_ASSERT(nsapi >= 5 && nsapi <= 15);
-		blob |= (1 << nsapi);
-	}
-
-	/* Store result */
-	*dst = (blob >> 8) & 0xFF;
-	dst++;
-	*dst = blob & 0xFF;
-
-	return 2;
-}
-
-/* Encode rfc1144 parameter field
- * (see also: 3GPP TS 44.065, 6.5.2.1, Table 5) */
-static int encode_pcomp_rfc1144_params(uint8_t *dst, unsigned int dst_maxlen,
-				       const struct
-				       gprs_sndcp_pcomp_rfc1144_params *params)
-{
-	/* NOTE: Buffer *dst should offer at least 3 bytes
-	 * of space to store the generation results */
-
-	int dst_counter = 0;
-	int rc;
-
-	OSMO_ASSERT(dst_maxlen >= 3);
-
-	/* Zero out buffer */
-	memset(dst, 0, dst_maxlen);
-
-	/* Encode applicable SAPIs */
-	rc = encode_pcomp_applicable_sapis(dst, params->nsapi,
-					   params->nsapi_len);
-	dst += rc;
-	dst_counter += rc;
-
-	/* Encode s01 (see also: 3GPP TS 44.065, 6.5.2.1, Table 5) */
-	OSMO_ASSERT(params->s01 >= 0);
-	OSMO_ASSERT(params->s01 <= 255);
-	*dst = params->s01;
-	dst++;
-	dst_counter++;
-
-	/* Return generated length */
-	return dst_counter;
-}
-
-/*
- * Encode rfc2507 parameter field
- * (see also: 3GPP TS 44.065, 6.5.3.1, Table 6)
- */
-static int encode_pcomp_rfc2507_params(uint8_t *dst, unsigned int dst_maxlen,
-				       const struct
-				       gprs_sndcp_pcomp_rfc2507_params *params)
-{
-	/* NOTE: Buffer *dst should offer at least 3 bytes
-	 * of space to store the generation results */
-
-	int dst_counter = 0;
-	int rc;
-
-	OSMO_ASSERT(dst_maxlen >= 9);
-
-	/* Zero out buffer */
-	memset(dst, 0, dst_maxlen);
-
-	/* Encode applicable SAPIs */
-	rc = encode_pcomp_applicable_sapis(dst, params->nsapi,
-					   params->nsapi_len);
-	dst += rc;
-	dst_counter += rc;
-
-	/* Encode F_MAX_PERIOD (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
-	OSMO_ASSERT(params->f_max_period >= 1);
-	OSMO_ASSERT(params->f_max_period <= 65535);
-	*dst = (params->f_max_period >> 8) & 0xFF;
-	dst++;
-	dst_counter++;
-	*dst = (params->f_max_period) & 0xFF;
-	dst++;
-	dst_counter++;
-
-	/* Encode F_MAX_TIME (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
-	OSMO_ASSERT(params->f_max_time >= 1);
-	OSMO_ASSERT(params->f_max_time <= 255);
-	*dst = params->f_max_time;
-	dst++;
-	dst_counter++;
-
-	/* Encode MAX_HEADER (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
-	OSMO_ASSERT(params->max_header >= 60);
-	OSMO_ASSERT(params->max_header <= 255);
-	*dst = params->max_header;
-	dst++;
-	dst_counter++;
-
-	/* Encode TCP_SPACE (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
-	OSMO_ASSERT(params->tcp_space >= 3);
-	OSMO_ASSERT(params->tcp_space <= 255);
-	*dst = params->tcp_space;
-	dst++;
-	dst_counter++;
-
-	/* Encode NON_TCP_SPACE (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
-	OSMO_ASSERT(params->non_tcp_space >= 3);
-	OSMO_ASSERT(params->non_tcp_space <= 65535);
-	*dst = (params->non_tcp_space >> 8) & 0xFF;
-	dst++;
-	dst_counter++;
-	*dst = (params->non_tcp_space) & 0xFF;
-	dst++;
-	dst_counter++;
-
-	/* Return generated length */
-	return dst_counter;
-}
-
-/* Encode ROHC parameter field
- * (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
-static int encode_pcomp_rohc_params(uint8_t *dst, unsigned int dst_maxlen,
-				    const struct gprs_sndcp_pcomp_rohc_params
-				    *params)
-{
-	/* NOTE: Buffer *dst should offer at least 36
-	 * (2 * 16 Profiles + 2 * 3 Parameter) bytes
-	 * of memory space to store generation results */
-
-	int i;
-	int dst_counter = 0;
-	int rc;
-
-	OSMO_ASSERT(dst_maxlen >= 38);
-
-	/* Bail if number of ROHC profiles exceeds limit
-	 * (ROHC supports only a maximum of 16 different profiles) */
-	OSMO_ASSERT(params->profile_len <= 16);
-
-	/* Zero out buffer */
-	memset(dst, 0, dst_maxlen);
-
-	/* Encode applicable SAPIs */
-	rc = encode_pcomp_applicable_sapis(dst, params->nsapi,
-					   params->nsapi_len);
-	dst += rc;
-	dst_counter += rc;
-
-	/* Encode MAX_CID (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
-	OSMO_ASSERT(params->max_cid >= 0);
-	OSMO_ASSERT(params->max_cid <= 16383);
-	*dst = (params->max_cid >> 8) & 0xFF;
-	dst++;
-	*dst = params->max_cid & 0xFF;
-	dst++;
-	dst_counter += 2;
-
-	/* Encode MAX_HEADER (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
-	OSMO_ASSERT(params->max_header >= 60);
-	OSMO_ASSERT(params->max_header <= 255);
-	*dst = (params->max_header >> 8) & 0xFF;
-	dst++;
-	*dst = params->max_header & 0xFF;
-	dst++;
-	dst_counter += 2;
-
-	/* Encode ROHC Profiles (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
-	for (i = 0; i < params->profile_len; i++) {
-		*dst = (params->profile[i] >> 8) & 0xFF;
-		dst++;
-		*dst = params->profile[i] & 0xFF;
-		dst++;
-		dst_counter += 2;
-	}
-
-	/* Return generated length */
-	return dst_counter;
-}
-
-/* Encode V.42bis parameter field
- * (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
-static int encode_dcomp_v42bis_params(uint8_t *dst, unsigned int dst_maxlen,
-				      const struct
-				      gprs_sndcp_dcomp_v42bis_params *params)
-{
-	/* NOTE: Buffer *dst should offer at least 6 bytes
-	 * of space to store the generation results */
-
-	int dst_counter = 0;
-	int rc;
-
-	OSMO_ASSERT(dst_maxlen >= 6);
-
-	/* Zero out buffer */
-	memset(dst, 0, dst_maxlen);
-
-	/* Encode applicable SAPIs */
-	rc = encode_pcomp_applicable_sapis(dst, params->nsapi,
-					   params->nsapi_len);
-	dst += rc;
-	dst_counter += rc;
-
-	/* Encode P0 (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
-	OSMO_ASSERT(params->p0 >= 0);
-	OSMO_ASSERT(params->p0 <= 3);
-	*dst = params->p0 & 0x03;
-	dst++;
-	dst_counter++;
-
-	/* Encode P1 (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
-	OSMO_ASSERT(params->p1 >= 512);
-	OSMO_ASSERT(params->p1 <= 65535);
-	*dst = (params->p1 >> 8) & 0xFF;
-	dst++;
-	*dst = params->p1 & 0xFF;
-	dst++;
-	dst_counter += 2;
-
-	/* Encode P2 (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
-	OSMO_ASSERT(params->p2 >= 6);
-	OSMO_ASSERT(params->p2 <= 250);
-	*dst = params->p2;
-	dst++;
-	dst_counter++;
-
-	/* Return generated length */
-	return dst_counter;
-}
-
-/* Encode V44 parameter field
- * (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
-static int encode_dcomp_v44_params(uint8_t *dst, unsigned int dst_maxlen,
-				   const struct gprs_sndcp_dcomp_v44_params
-				   *params)
-{
-	/* NOTE: Buffer *dst should offer at least 12 bytes
-	 * of space to store the generation results */
-
-	int dst_counter = 0;
-	int rc;
-
-	OSMO_ASSERT(dst_maxlen >= 12);
-
-	/* Zero out buffer */
-	memset(dst, 0, dst_maxlen);
-
-	/* Encode applicable SAPIs */
-	rc = encode_pcomp_applicable_sapis(dst, params->nsapi,
-					   params->nsapi_len);
-	dst += rc;
-	dst_counter += rc;
-
-	/* Encode C0 (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
-	OSMO_ASSERT(params->c0 == 0x80 || params->c0 == 0xC0);
-	*dst = params->c0 & 0xC0;
-	dst++;
-	dst_counter++;
-
-	/* Encode P0 (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
-	OSMO_ASSERT(params->p0 >= 0);
-	OSMO_ASSERT(params->p0 <= 3);
-	*dst = params->p0 & 0x03;
-	dst++;
-	dst_counter++;
-
-	/* Encode P1T (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
-	OSMO_ASSERT(params->p1t >= 256);
-	OSMO_ASSERT(params->p1t <= 65535);
-	*dst = (params->p1t >> 8) & 0xFF;
-	dst++;
-	*dst = params->p1t & 0xFF;
-	dst++;
-	dst_counter += 2;
-
-	/* Encode P1R (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
-	OSMO_ASSERT(params->p1r >= 256);
-	OSMO_ASSERT(params->p1r <= 65535);
-	*dst = (params->p1r >> 8) & 0xFF;
-	dst++;
-	*dst = params->p1r & 0xFF;
-	dst++;
-	dst_counter += 2;
-
-	/* Encode P3T (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
-	OSMO_ASSERT(params->p3t >= 0);
-	OSMO_ASSERT(params->p3t <= 65535);
-	OSMO_ASSERT(params->p3t >= 2 * params->p1t);
-	*dst = (params->p3t >> 8) & 0xFF;
-	dst++;
-	*dst = params->p3t & 0xFF;
-	dst++;
-	dst_counter += 2;
-
-	/* Encode P3R (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
-	OSMO_ASSERT(params->p3r >= 0);
-	OSMO_ASSERT(params->p3r <= 65535);
-	OSMO_ASSERT(params->p3r >= 2 * params->p1r);
-	*dst = (params->p3r >> 8) & 0xFF;
-	dst++;
-	*dst = params->p3r & 0xFF;
-	dst++;
-	dst_counter += 2;
-
-	/* Return generated length */
-	return dst_counter;
-}
-
-/* Encode data or protocol control information compression field
- * (see also: 3GPP TS 44.065, 6.6.1.1, Figure 9 and
- *            3GPP TS 44.065, 6.5.1.1, Figure 7) */
-static int encode_comp_field(uint8_t *dst, unsigned int dst_maxlen,
-			     const struct gprs_sndcp_comp_field *comp_field)
-{
-	int dst_counter = 0;
-	int len;
-	int expected_length;
-	int i;
-
-	uint8_t payload_bytes[256];
-	int payload_bytes_len = -1;
-
-	/* If possible, try do encode payload bytes first */
-	if (comp_field->rfc1144_params) {
-		payload_bytes_len =
-		    encode_pcomp_rfc1144_params(payload_bytes,
-						sizeof(payload_bytes),
-						comp_field->rfc1144_params);
-	} else if (comp_field->rfc2507_params) {
-		payload_bytes_len =
-		    encode_pcomp_rfc2507_params(payload_bytes,
-						sizeof(payload_bytes),
-						comp_field->rfc2507_params);
-	} else if (comp_field->rohc_params) {
-		payload_bytes_len =
-		    encode_pcomp_rohc_params(payload_bytes,
-					     sizeof(payload_bytes),
-					     comp_field->rohc_params);
-	} else if (comp_field->v42bis_params) {
-		payload_bytes_len =
-		    encode_dcomp_v42bis_params(payload_bytes,
-					       sizeof(payload_bytes),
-					       comp_field->v42bis_params);
-	} else if (comp_field->v44_params) {
-		payload_bytes_len =
-		    encode_dcomp_v44_params(payload_bytes,
-					    sizeof(payload_bytes),
-					    comp_field->v44_params);
-	} else
-		OSMO_ASSERT(false);
-
-	/* Bail immediately if payload byte generation failed */
-	OSMO_ASSERT(payload_bytes_len >= 0);
-
-	/* Bail if comp_len is out of bounds */
-	OSMO_ASSERT(comp_field->comp_len <= sizeof(comp_field->comp));
-
-	/* Calculate length field of the data block */
-	if (comp_field->p) {
-		len =
-		    payload_bytes_len +
-		    ceil((double)(comp_field->comp_len) / 2.0);
-		expected_length = len + 3;
-	} else {
-		len = payload_bytes_len;
-		expected_length = len + 2;
-	}
-
-	/* Bail immediately if no sufficient memory space is supplied */
-	OSMO_ASSERT(dst_maxlen >= expected_length);
-
-	/* Check if the entity number is within bounds */
-	OSMO_ASSERT(comp_field->entity <= 0x1f);
-
-	/* Check if the algorithm number is within bounds */
-	OSMO_ASSERT(comp_field->algo >= 0 || comp_field->algo <= 0x1f);
-
-	/* Zero out buffer */
-	memset(dst, 0, dst_maxlen);
-
-	/* Encode Propose bit */
-	if (comp_field->p)
-		*dst |= (1 << 7);
-
-	/* Encode entity number */
-	*dst |= comp_field->entity & 0x1F;
-	dst++;
-	dst_counter++;
-
-	/* Encode algorithm number */
-	if (comp_field->p) {
-		*dst |= comp_field->algo & 0x1F;
-		dst++;
-		dst_counter++;
-	}
-
-	/* Encode length field */
-	*dst |= len & 0xFF;
-	dst++;
-	dst_counter++;
-
-	/* Encode PCOMP/DCOMP values */
-	if (comp_field->p) {
-		for (i = 0; i < comp_field->comp_len; i++) {
-			/* Check if submitted PCOMP/DCOMP
-			   values are within bounds */
-			if (comp_field->comp[i] > 0x0F)
-				return -EINVAL;
-
-			if (i & 1) {
-				*dst |= comp_field->comp[i] & 0x0F;
-				dst++;
-				dst_counter++;
-			} else
-				*dst |= (comp_field->comp[i] << 4) & 0xF0;
-		}
-
-		if (i & 1) {
-			dst++;
-			dst_counter++;
-		}
-	}
-
-	/* Append payload bytes */
-	memcpy(dst, payload_bytes, payload_bytes_len);
-	dst_counter += payload_bytes_len;
-
-	/* Return generated length */
-	return dst_counter;
-}
-
-/* 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)
-{
-	OSMO_ASSERT(comp_field);
-
-	if (comp_field->rfc1144_params)
-		return SNDCP_XID_PROTOCOL_COMPRESSION;
-	else if (comp_field->rfc2507_params)
-		return SNDCP_XID_PROTOCOL_COMPRESSION;
-	else if (comp_field->rohc_params)
-		return SNDCP_XID_PROTOCOL_COMPRESSION;
-	else if (comp_field->v42bis_params)
-		return SNDCP_XID_DATA_COMPRESSION;
-	else if (comp_field->v44_params)
-		return SNDCP_XID_DATA_COMPRESSION;
-	else
-		return -EINVAL;
-}
-
-/* Convert all compression fields to bytstreams */
-static int gprs_sndcp_pack_fields(const struct llist_head *comp_fields,
-				  uint8_t *dst,
-				  unsigned int dst_maxlen, int class)
-{
-	struct gprs_sndcp_comp_field *comp_field;
-	int byte_counter = 0;
-	int rc;
-
-	llist_for_each_entry_reverse(comp_field, comp_fields, list) {
-		if (class == gprs_sndcp_get_compression_class(comp_field)) {
-			rc = encode_comp_field(dst + byte_counter,
-					       dst_maxlen - byte_counter,
-					       comp_field);
-
-			/* When input data is correct, there is
-			 * no reason for the encoder to fail! */
-			OSMO_ASSERT(rc >= 0);
-
-			byte_counter += rc;
-		}
-	}
-
-	/* Return generated length */
-	return byte_counter;
-}
-
-/* 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)
-{
-	int rc;
-	int byte_counter = 0;
-	uint8_t comp_bytes[512];
-	uint8_t xid_version_number[1];
-
-	OSMO_ASSERT(comp_fields);
-	OSMO_ASSERT(dst);
-	OSMO_ASSERT(dst_maxlen >= 2 + sizeof(xid_version_number));
-
-	/* Prepend header with version number */
-	if (version >= 0) {
-		xid_version_number[0] = (uint8_t) (version & 0xff);
-		dst =
-		    tlv_put(dst, SNDCP_XID_VERSION_NUMBER,
-			    sizeof(xid_version_number), xid_version_number);
-		byte_counter += (sizeof(xid_version_number) + 2);
-	}
-
-	/* Stop if there is no compression fields supplied */
-	if (llist_empty(comp_fields))
-		return byte_counter;
-
-	/* Add data compression fields */
-	rc = gprs_sndcp_pack_fields(comp_fields, comp_bytes,
-				    sizeof(comp_bytes),
-				    SNDCP_XID_DATA_COMPRESSION);
-	OSMO_ASSERT(rc >= 0);
-
-	if (rc > 0) {
-		dst = tlv_put(dst, SNDCP_XID_DATA_COMPRESSION, rc, comp_bytes);
-		byte_counter += rc + 2;
-	}
-
-	/* Add header compression fields */
-	rc = gprs_sndcp_pack_fields(comp_fields, comp_bytes,
-				    sizeof(comp_bytes),
-				    SNDCP_XID_PROTOCOL_COMPRESSION);
-	OSMO_ASSERT(rc >= 0);
-
-	if (rc > 0) {
-		dst = tlv_put(dst, SNDCP_XID_PROTOCOL_COMPRESSION, rc,
-			      comp_bytes);
-		byte_counter += rc + 2;
-	}
-
-	/* Return generated length */
-	return byte_counter;
-}
-
-/* FUNCTIONS RELATED TO SNDCP-XID DECODING */
-
-/* Decode applicable sapis (works the same in all three compression schemes) */
-static int decode_pcomp_applicable_sapis(uint8_t *nsapis,
-					 uint8_t *nsapis_len,
-					 const uint8_t *src,
-					 unsigned int src_len)
-{
-	uint16_t blob;
-	int i;
-	int nsapi_len = 0;
-
-	/* Exit immediately if no result can be stored */
-	if (!nsapis)
-		return -EINVAL;
-
-	/* Exit immediately if not enough input data is available */
-	if (src_len < 2)
-		return -EINVAL;
-
-	/* Read bitmask */
-	blob = *src;
-	blob = (blob << 8) & 0xFF00;
-	src++;
-	blob |= (*src) & 0xFF;
-	blob = (blob >> 5);
-
-	/* Decode applicable SAPIs */
-	for (i = 0; i < 15; i++) {
-		if ((blob >> i) & 1) {
-			nsapis[nsapi_len] = i + 5;
-			nsapi_len++;
-		}
-	}
-
-	/* Return consumed length */
-	*nsapis_len = nsapi_len;
-	return 2;
-}
-
-/* Decode 16 bit field */
-static int decode_pcomp_16_bit_field(int *value_int, uint16_t * value_uint16,
-				     const uint8_t *src,
-				     unsigned int src_len,
-				     int value_min, int value_max)
-{
-	uint16_t blob;
-
-	/* Reset values to zero (just to be sure) */
-	if (value_int)
-		*value_int = -1;
-	if (value_uint16)
-		*value_uint16 = 0;
-
-	/* Exit if not enough src are available */
-	if (src_len < 2)
-		return -EINVAL;
-
-	/* Decode bit value */
-	blob = *src;
-	blob = (blob << 8) & 0xFF00;
-	src++;
-	blob |= *src;
-
-	/* Check if parsed value is within bounds */
-	if (blob < value_min)
-		return -EINVAL;
-	if (blob > value_max)
-		return -EINVAL;
-
-	/* Hand back results to the caller */
-	if (value_int)
-		*value_int = blob;
-	if (value_uint16)
-		*value_uint16 = blob;
-
-	/* Return consumed length */
-	return 2;
-}
-
-/* Decode 8 bit field */
-static int decode_pcomp_8_bit_field(int *value_int, uint8_t *value_uint8,
-				    const uint8_t *src,
-				    unsigned int src_len,
-				    int value_min, int value_max)
-{
-	uint8_t blob;
-
-	/* Reset values to invalid (just to be sure) */
-	if (value_int)
-		*value_int = -1;
-	if (value_uint8)
-		*value_uint8 = 0;
-
-	/* Exit if not enough src are available */
-	if (src_len < 1)
-		return -EINVAL;
-
-	/* Decode bit value */
-	blob = *src;
-
-	/* Check if parsed value is within bounds */
-	if (blob < value_min)
-		return -EINVAL;
-	if (blob > value_max)
-		return -EINVAL;
-
-	/* Hand back results to the caller */
-	if (value_int)
-		*value_int = blob;
-	if (value_uint8)
-		*value_uint8 = blob;
-
-	/* Return consumed length */
-	return 1;
-}
-
-/* Decode rfc1144 parameter field see also: 3GPP TS 44.065, 6.5.2.1, Table 5) */
-static int decode_pcomp_rfc1144_params(struct gprs_sndcp_pcomp_rfc1144_params
-				       *params, const uint8_t *src,
-				       unsigned int src_len)
-{
-	int rc;
-	int byte_counter = 0;
-
-	/* Mark all optional parameters invalid by default */
-	params->s01 = -1;
-
-	/* Decode applicable SAPIs */
-	rc = decode_pcomp_applicable_sapis(params->nsapi, &params->nsapi_len,
-					   src, src_len);
-	if (rc > 0) {
-		byte_counter += rc;
-		src += rc;
-	} else
-		return byte_counter;
-
-	/* Decode parameter S0 -1
-	 * (see also: 3GPP TS 44.065, 6.5.2.1, Table 5) */
-	rc = decode_pcomp_8_bit_field(&params->s01, NULL, src,
-				      src_len - byte_counter, 0, 255);
-	if (rc <= 0)
-		return byte_counter;
-	byte_counter += rc;
-	src += rc;
-
-	/* Return consumed length */
-	return byte_counter;
-}
-
-/* Decode rfc2507 parameter field
- * (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
-static int decode_pcomp_rfc2507_params(struct gprs_sndcp_pcomp_rfc2507_params
-				       *params, const uint8_t *src,
-				       unsigned int src_len)
-{
-	int rc;
-	int byte_counter = 0;
-
-	/* Mark all optional parameters invalid by default */
-	params->f_max_period = -1;
-	params->f_max_time = -1;
-	params->max_header = -1;
-	params->tcp_space = -1;
-	params->non_tcp_space = -1;
-
-	/* Decode applicable SAPIs */
-	rc = decode_pcomp_applicable_sapis(params->nsapi, &params->nsapi_len,
-					   src, src_len);
-	if (rc > 0) {
-		byte_counter += rc;
-		src += rc;
-	} else
-		return byte_counter;
-
-	/* Decode F_MAX_PERIOD (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
-	rc = decode_pcomp_16_bit_field(&params->f_max_period, NULL, src,
-				       src_len - byte_counter, 1, 65535);
-	if (rc <= 0)
-		return byte_counter;
-	byte_counter += rc;
-	src += rc;
-
-	/* Decode F_MAX_TIME (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
-	rc = decode_pcomp_8_bit_field(&params->f_max_time, NULL, src,
-				      src_len - byte_counter, 1, 255);
-	if (rc <= 0)
-		return byte_counter;
-	byte_counter += rc;
-	src += rc;
-
-	/* Decode MAX_HEADER (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
-	rc = decode_pcomp_8_bit_field(&params->max_header, NULL, src,
-				      src_len - byte_counter, 60, 255);
-	if (rc <= 0)
-		return byte_counter;
-	byte_counter += rc;
-	src += rc;
-
-	/* Decode TCP_SPACE (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
-	rc = decode_pcomp_8_bit_field(&params->tcp_space, NULL, src,
-				      src_len - byte_counter, 3, 255);
-	if (rc <= 0)
-		return byte_counter;
-	byte_counter += rc;
-	src += rc;
-
-	/* Decode NON_TCP_SPACE (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
-	rc = decode_pcomp_16_bit_field(&params->non_tcp_space, NULL, src,
-				       src_len - byte_counter, 3, 65535);
-	if (rc <= 0)
-		return byte_counter;
-	byte_counter += rc;
-	src += rc;
-
-	/* Return consumed length */
-	return byte_counter;
-}
-
-/* Decode ROHC parameter field (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
-static int decode_pcomp_rohc_params(struct gprs_sndcp_pcomp_rohc_params *params,
-				    const uint8_t *src, unsigned int src_len)
-{
-	int rc;
-	int byte_counter = 0;
-	int i;
-
-	/* Mark all optional parameters invalid by default */
-	params->max_cid = -1;
-	params->max_header = -1;
-
-	/* Decode applicable SAPIs */
-	rc = decode_pcomp_applicable_sapis(params->nsapi, &params->nsapi_len,
-					   src, src_len);
-	if (rc <= 0)
-		return byte_counter;
-	byte_counter += rc;
-	src += rc;
-
-	/* Decode MAX_CID (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
-	rc = decode_pcomp_16_bit_field(&params->max_cid, NULL, src,
-				       src_len - byte_counter, 0, 16383);
-	if (rc <= 0)
-		return byte_counter;
-	byte_counter += rc;
-	src += rc;
-
-	/* Decode MAX_HEADER (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
-	rc = decode_pcomp_16_bit_field(&params->max_header, NULL, src,
-				       src_len - byte_counter, 60, 255);
-	if (rc <= 0)
-		return byte_counter;
-	byte_counter += rc;
-	src += rc;
-
-	/* Decode Profiles (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
-	for (i = 0; i < 16; i++) {
-		params->profile_len = 0;
-		rc = decode_pcomp_16_bit_field(NULL, &params->profile[i], src,
-					       src_len - byte_counter, 0,
-					       65535);
-		if (rc <= 0)
-			return byte_counter;
-		byte_counter += rc;
-		src += rc;
-		params->profile_len = i + 1;
-	}
-
-	/* Return consumed length */
-	return byte_counter;
-}
-
-/* Decode V.42bis parameter field
- * (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
-static int decode_dcomp_v42bis_params(struct gprs_sndcp_dcomp_v42bis_params
-				      *params, const uint8_t *src,
-				      unsigned int src_len)
-{
-	int rc;
-	int byte_counter = 0;
-
-	/* Mark all optional parameters invalid by default */
-	params->p0 = -1;
-	params->p1 = -1;
-	params->p2 = -1;
-
-	/* Decode applicable SAPIs */
-	rc = decode_pcomp_applicable_sapis(params->nsapi, &params->nsapi_len,
-					   src, src_len);
-	if (rc > 0) {
-		byte_counter += rc;
-		src += rc;
-	} else
-		return byte_counter;
-
-	/* Decode P0 (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
-	rc = decode_pcomp_8_bit_field(&params->p0, NULL, src,
-				      src_len - byte_counter, 0, 3);
-	if (rc <= 0)
-		return byte_counter;
-	byte_counter += rc;
-	src += rc;
-
-	/* Decode P1 (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
-	rc = decode_pcomp_16_bit_field(&params->p1, NULL, src,
-				       src_len - byte_counter, 512, 65535);
-	if (rc <= 0)
-		return byte_counter;
-	byte_counter += rc;
-	src += rc;
-
-	/* Decode P2 (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
-	rc = decode_pcomp_8_bit_field(&params->p2, NULL, src,
-				      src_len - byte_counter, 6, 250);
-	if (rc <= 0)
-		return byte_counter;
-	byte_counter += rc;
-	src += rc;
-
-	/* Return consumed length */
-	return byte_counter;
-}
-
-/* Decode V44 parameter field (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
-static int decode_dcomp_v44_params(struct gprs_sndcp_dcomp_v44_params *params,
-				   const uint8_t *src, unsigned int src_len)
-{
-	int rc;
-	int byte_counter = 0;
-
-	/* Mark all optional parameters invalid by default */
-	params->c0 = -1;
-	params->p0 = -1;
-	params->p1t = -1;
-	params->p1r = -1;
-	params->p3t = -1;
-	params->p3r = -1;
-
-	/* Decode applicable SAPIs */
-	rc = decode_pcomp_applicable_sapis(params->nsapi, &params->nsapi_len,
-					   src, src_len);
-	if (rc > 0) {
-		byte_counter += rc;
-		src += rc;
-	} else
-		return byte_counter;
-
-	/* Decode C0 (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
-	rc = decode_pcomp_8_bit_field(&params->c0, NULL, src,
-				      src_len - byte_counter, 0, 255);
-	if (rc <= 0)
-		return byte_counter;
-	if ((params->c0 != 0x80) && (params->c0 != 0xC0))
-		return -EINVAL;
-	byte_counter += rc;
-	src += rc;
-
-	/* Decode P0 (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
-	rc = decode_pcomp_8_bit_field(&params->p0, NULL, src,
-				      src_len - byte_counter, 0, 3);
-	if (rc <= 0)
-		return byte_counter;
-	byte_counter += rc;
-	src += rc;
-
-	/* Decode P1T (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
-	rc = decode_pcomp_16_bit_field(&params->p1t, NULL, src,
-				       src_len - byte_counter, 265, 65535);
-	if (rc <= 0)
-		return byte_counter;
-	byte_counter += rc;
-	src += rc;
-
-	/* Decode P1R (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
-	rc = decode_pcomp_16_bit_field(&params->p1r, NULL, src,
-				       src_len - byte_counter, 265, 65535);
-	if (rc <= 0)
-		return byte_counter;
-	byte_counter += rc;
-	src += rc;
-
-	/* Decode P3T (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
-	rc = decode_pcomp_16_bit_field(&params->p3t, NULL, src,
-				       src_len - byte_counter, 265, 65535);
-	if (rc <= 0)
-		return byte_counter;
-	if (params->p3t < 2 * params->p1t)
-		return -EINVAL;
-	byte_counter += rc;
-	src += rc;
-
-	/* Decode P3R (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
-	rc = decode_pcomp_16_bit_field(&params->p3r, NULL, src,
-				       src_len - byte_counter, 265, 65535);
-	if (rc <= 0)
-		return byte_counter;
-	if (params->p3r < 2 * params->p1r)
-		return -EINVAL;
-	byte_counter += rc;
-	src += rc;
-
-	/* Return consumed length */
-	return byte_counter;
-}
-
-/* Lookup algorithm identfier by entity ID */
-static int lookup_algorithm_identifier(int entity, const struct
-				       entity_algo_table
-				       *lt, unsigned int lt_len, int compclass)
-{
-	int i;
-
-	if (!lt)
-		return -1;
-
-	for (i = 0; i < lt_len; i++) {
-		if ((lt[i].entity == entity)
-		    && (lt[i].compclass == compclass))
-			return lt[i].algo;
-	}
-
-	return -1;
-}
-
-/* Helper function for decode_comp_field(), decodes
- * numeric pcomp/dcomp values */
-static int decode_comp_values(struct gprs_sndcp_comp_field *comp_field,
-			      const uint8_t *src, int compclass)
-{
-	int src_counter = 0;
-	int i;
-
-	if (comp_field->p) {
-		/* Determine the number of expected PCOMP/DCOMP values */
-		if (compclass == SNDCP_XID_PROTOCOL_COMPRESSION) {
-			/* For protocol compression */
-			switch (comp_field->algo) {
-			case RFC_1144:
-				comp_field->comp_len = RFC1144_PCOMP_NUM;
-				break;
-			case RFC_2507:
-				comp_field->comp_len = RFC2507_PCOMP_NUM;
-				break;
-			case ROHC:
-				comp_field->comp_len = ROHC_PCOMP_NUM;
-				break;
-
-				/* Exit if the algorithem type encodes
-				   something unknown / unspecified */
-			default:
-				return -EINVAL;
-			}
-		} else {
-			/* For data compression */
-			switch (comp_field->algo) {
-			case V42BIS:
-				comp_field->comp_len = V42BIS_DCOMP_NUM;
-				break;
-			case V44:
-				comp_field->comp_len = V44_DCOMP_NUM;
-				break;
-
-				/* Exit if the algorithem type encodes
-				   something unknown / unspecified */
-			default:
-				return -EINVAL;
-			}
-		}
-
-		for (i = 0; i < comp_field->comp_len; i++) {
-			if (i & 1) {
-				comp_field->comp[i] = (*src) & 0x0F;
-				src++;
-				src_counter++;
-			} else
-				comp_field->comp[i] = ((*src) >> 4) & 0x0F;
-		}
-
-		if (i & 1) {
-			src++;
-			src_counter++;
-		}
-	}
-
-	return src_counter;
-}
-
-/* Helper function for decode_comp_field(), decodes the parameters
- * which are protocol compression specific */
-static int decode_pcomp_params(struct gprs_sndcp_comp_field *comp_field,
-			       const uint8_t *src, int src_len)
-{
-	int rc;
-
-	switch (comp_field->algo) {
-	case RFC_1144:
-		comp_field->rfc1144_params = talloc_zero(comp_field, struct
-					gprs_sndcp_pcomp_rfc1144_params);
-		rc = decode_pcomp_rfc1144_params(comp_field->rfc1144_params,
-						 src, src_len);
-		if (rc < 0)
-			talloc_free(comp_field->rfc1144_params);
-		break;
-	case RFC_2507:
-		comp_field->rfc2507_params = talloc_zero(comp_field, struct
-					gprs_sndcp_pcomp_rfc2507_params);
-		rc = decode_pcomp_rfc2507_params(comp_field->rfc2507_params,
-						 src, src_len);
-		if (rc < 0)
-			talloc_free(comp_field->rfc1144_params);
-		break;
-	case ROHC:
-		comp_field->rohc_params = talloc_zero(comp_field, struct
-					gprs_sndcp_pcomp_rohc_params);
-		rc = decode_pcomp_rohc_params(comp_field->rohc_params, src,
-					      src_len);
-		if (rc < 0)
-			talloc_free(comp_field->rohc_params);
-		break;
-
-		/* If no suitable decoder is detected,
-		   leave the remaining bytes undecoded */
-	default:
-		rc = src_len;
-	}
-
-	if (rc < 0) {
-		comp_field->rfc1144_params = NULL;
-		comp_field->rfc2507_params = NULL;
-		comp_field->rohc_params = NULL;
-	}
-
-	return rc;
-}
-
-/* Helper function for decode_comp_field(), decodes the parameters
- * which are data compression specific */
-static int decode_dcomp_params(struct gprs_sndcp_comp_field *comp_field,
-			       const uint8_t *src, int src_len)
-{
-	int rc;
-
-	switch (comp_field->algo) {
-	case V42BIS:
-		comp_field->v42bis_params = talloc_zero(comp_field, struct
-					gprs_sndcp_dcomp_v42bis_params);
-		rc = decode_dcomp_v42bis_params(comp_field->v42bis_params, src,
-						src_len);
-		if (rc < 0)
-			talloc_free(comp_field->v42bis_params);
-		break;
-	case V44:
-		comp_field->v44_params = talloc_zero(comp_field, struct
-					gprs_sndcp_dcomp_v44_params);
-		rc = decode_dcomp_v44_params(comp_field->v44_params, src,
-					     src_len);
-		if (rc < 0)
-			talloc_free(comp_field->v44_params);
-		break;
-
-		/* If no suitable decoder is detected,
-		 * leave the remaining bytes undecoded */
-	default:
-		rc = src_len;
-	}
-
-	if (rc < 0) {
-		comp_field->v42bis_params = NULL;
-		comp_field->v44_params = NULL;
-	}
-
-	return rc;
-}
-
-/* Decode data or protocol control information compression field
- * (see also: 3GPP TS 44.065, 6.6.1.1, Figure 9 and
- *            3GPP TS 44.065, 6.5.1.1, Figure 7) */
-static int decode_comp_field(struct gprs_sndcp_comp_field *comp_field,
-			     const uint8_t *src, unsigned int src_len,
-			     const struct entity_algo_table *lt,
-			     unsigned int lt_len, int compclass)
-{
-	int src_counter = 0;
-	unsigned int len;
-	int rc;
-
-	OSMO_ASSERT(comp_field);
-
-	/* Exit immediately if it is clear that no
-	   parseable data is present */
-	if (src_len < 1 || !src)
-		return -EINVAL;
-
-	/* Zero out target struct */
-	memset(comp_field, 0, sizeof(struct gprs_sndcp_comp_field));
-
-	/* Decode Propose bit and Entity number */
-	if ((*src) & 0x80)
-		comp_field->p = 1;
-	comp_field->entity = (*src) & 0x1F;
-	src_counter++;
-	src++;
-
-	/* Decode algorithm number (if present) */
-	if (comp_field->p) {
-		comp_field->algo = (*src) & 0x1F;
-		src_counter++;
-		src++;
-	}
-	/* Alternatively take the information from the lookup table */
-	else
-		comp_field->algo =
-		    lookup_algorithm_identifier(comp_field->entity, lt,
-						lt_len, compclass);
-
-	/* Decode length field */
-	len = *src;
-	src_counter++;
-	src++;
-
-	/* Decode PCOMP/DCOMP values */
-	rc = decode_comp_values(comp_field, src, compclass);
-	if (rc < 0)
-		return -EINVAL;
-	src_counter += rc;
-	src += rc;
-	len -= rc;
-
-	/* Decode algorithm specific payload data */
-	if (compclass == SNDCP_XID_PROTOCOL_COMPRESSION)
-		rc = decode_pcomp_params(comp_field, src, len);
-	else if (compclass == SNDCP_XID_DATA_COMPRESSION)
-		rc = decode_dcomp_params(comp_field, src, len);
-	else
-		return -EINVAL;
-
-	if (rc >= 0)
-		src_counter += rc;
-	else
-		return -EINVAL;
-
-	/* Return consumed length */
-	return src_counter;
-}
-
-/* Helper function for gprs_sndcp_decode_xid() to decode XID blocks */
-static int decode_xid_block(struct llist_head *comp_fields, uint8_t tag,
-			    uint16_t tag_len, const uint8_t *val,
-			    const struct entity_algo_table *lt,
-			    unsigned int lt_len)
-{
-	struct gprs_sndcp_comp_field *comp_field;
-	int byte_counter = 0;
-	int comp_field_count = 0;
-	int rc;
-
-	byte_counter = 0;
-	do {
-		/* Bail if more than the maximum number of
-		   comp_fields is generated */
-		if (comp_field_count > MAX_ENTITIES * 2) {
-			return -EINVAL;
-		}
-
-		/* Parse and add comp_field */
-		comp_field =
-		    talloc_zero(comp_fields, struct gprs_sndcp_comp_field);
-
-		rc = decode_comp_field(comp_field, val + byte_counter,
-				       tag_len - byte_counter, lt, lt_len, tag);
-
-		if (rc < 0) {
-			talloc_free(comp_field);
-			return -EINVAL;
-		}
-
-		byte_counter += rc;
-		llist_add(&comp_field->list, comp_fields);
-		comp_field_count++;
-	}
-	while (tag_len - byte_counter > 0);
-
-	return byte_counter;
-}
-
-/* Transform an SNDCP-XID message (src) into a list of SNDCP-XID fields */
-static int gprs_sndcp_decode_xid(int *version, struct llist_head *comp_fields,
-				 const uint8_t *src, unsigned int src_len,
-				 const struct entity_algo_table *lt,
-				 unsigned int lt_len)
-{
-	int src_pos = 0;
-	uint8_t tag;
-	uint16_t tag_len;
-	const uint8_t *val;
-	int byte_counter = 0;
-	int rc;
-	int tlv_count = 0;
-
-	/* Preset version value as invalid */
-	if (version)
-		*version = -1;
-
-	/* Valid TLV-Tag and types */
-	static const struct tlv_definition sndcp_xid_def = {
-		.def = {
-			[SNDCP_XID_VERSION_NUMBER] = {TLV_TYPE_TLV,},
-			[SNDCP_XID_DATA_COMPRESSION] = {TLV_TYPE_TLV,},
-			[SNDCP_XID_PROTOCOL_COMPRESSION] = {TLV_TYPE_TLV,},
-			},
-	};
-
-	/* Parse TLV-Encoded SNDCP-XID message and defer payload
-	   to the apporpiate sub-parser functions */
-	while (1) {
-
-		/* Bail if an the maximum number of TLV fields
-		 * have been parsed */
-		if (tlv_count >= 3) {
-			talloc_free(comp_fields);
-			return -EINVAL;
-		}
-
-		/* Parse TLV field */
-		rc = tlv_parse_one(&tag, &tag_len, &val, &sndcp_xid_def,
-				   src + src_pos, src_len - src_pos);
-		if (rc > 0)
-			src_pos += rc;
-		else {
-			talloc_free(comp_fields);
-			return -EINVAL;
-		}
-
-		/* Decode sndcp xid version number */
-		if (version && tag == SNDCP_XID_VERSION_NUMBER)
-			*version = val[0];
-
-		/* Decode compression parameters */
-		if ((tag == SNDCP_XID_PROTOCOL_COMPRESSION)
-		    || (tag == SNDCP_XID_DATA_COMPRESSION)) {
-			rc = decode_xid_block(comp_fields, tag, tag_len, val,
-					      lt, lt_len);
-
-			if (rc < 0) {
-				talloc_free(comp_fields);
-				return -EINVAL;
-			} else
-				byte_counter += rc;
-		}
-
-		/* Stop when no further TLV elements can be expected */
-		if (src_len - src_pos <= 2)
-			break;
-
-		tlv_count++;
-	}
-
-	return 0;
-}
-
-/* Fill up lookutable from a list with comression entitiy fields */
-static int gprs_sndcp_fill_table(struct
-				 entity_algo_table *lt,
-				 unsigned int lt_len,
-				 const struct llist_head *comp_fields)
-{
-	struct gprs_sndcp_comp_field *comp_field;
-	int i = 0;
-	int rc;
-
-	if (!comp_fields)
-		return -EINVAL;
-	if (!lt)
-		return -EINVAL;
-
-	memset(lt, 0, sizeof(*lt));
-
-	llist_for_each_entry(comp_field, comp_fields, list) {
-		if (comp_field->algo >= 0) {
-			lt[i].entity = comp_field->entity;
-			lt[i].algo = comp_field->algo;
-			rc = gprs_sndcp_get_compression_class(comp_field);
-
-			if (rc < 0) {
-				memset(lt, 0, sizeof(*lt));
-				return -EINVAL;
-			}
-
-			lt[i].compclass = rc;
-			i++;
-		}
-	}
-
-	return i;
-}
-
-/* Complete comp field params
- * (if a param (dst) is not valid, it will be copied from source (src) */
-static int complete_comp_field_params(struct gprs_sndcp_comp_field
-				      *comp_field_dst, const struct
-				      gprs_sndcp_comp_field *comp_field_src)
-{
-	if (comp_field_dst->algo < 0)
-		return -EINVAL;
-
-	if (comp_field_dst->rfc1144_params && comp_field_src->rfc1144_params) {
-		if (comp_field_dst->rfc1144_params->s01 < 0) {
-			comp_field_dst->rfc1144_params->s01 =
-			    comp_field_src->rfc1144_params->s01;
-		}
-		return 0;
-	}
-
-	if (comp_field_dst->rfc2507_params && comp_field_src->rfc2507_params) {
-
-		if (comp_field_dst->rfc2507_params->f_max_period < 0) {
-			comp_field_dst->rfc2507_params->f_max_period =
-			    comp_field_src->rfc2507_params->f_max_period;
-		}
-		if (comp_field_dst->rfc2507_params->f_max_time < 0) {
-			comp_field_dst->rfc2507_params->f_max_time =
-			    comp_field_src->rfc2507_params->f_max_time;
-		}
-		if (comp_field_dst->rfc2507_params->max_header < 0) {
-			comp_field_dst->rfc2507_params->max_header =
-			    comp_field_src->rfc2507_params->max_header;
-		}
-		if (comp_field_dst->rfc2507_params->tcp_space < 0) {
-			comp_field_dst->rfc2507_params->tcp_space =
-			    comp_field_src->rfc2507_params->tcp_space;
-		}
-		if (comp_field_dst->rfc2507_params->non_tcp_space < 0) {
-			comp_field_dst->rfc2507_params->non_tcp_space =
-			    comp_field_src->rfc2507_params->non_tcp_space;
-		}
-		return 0;
-	}
-
-	if (comp_field_dst->rohc_params && comp_field_src->rohc_params) {
-		if (comp_field_dst->rohc_params->max_cid < 0) {
-			comp_field_dst->rohc_params->max_cid =
-			    comp_field_src->rohc_params->max_cid;
-		}
-		if (comp_field_dst->rohc_params->max_header < 0) {
-			comp_field_dst->rohc_params->max_header =
-			    comp_field_src->rohc_params->max_header;
-		}
-		if (comp_field_dst->rohc_params->profile_len > 0) {
-			memcpy(comp_field_dst->rohc_params->profile,
-			       comp_field_src->rohc_params->profile,
-			       sizeof(comp_field_dst->rohc_params->profile));
-			comp_field_dst->rohc_params->profile_len =
-			    comp_field_src->rohc_params->profile_len;
-		}
-
-		return 0;
-	}
-
-	if (comp_field_dst->v42bis_params && comp_field_src->v42bis_params) {
-		if (comp_field_dst->v42bis_params->p0 < 0) {
-			comp_field_dst->v42bis_params->p0 =
-			    comp_field_src->v42bis_params->p0;
-		}
-		if (comp_field_dst->v42bis_params->p1 < 0) {
-			comp_field_dst->v42bis_params->p1 =
-			    comp_field_src->v42bis_params->p1;
-		}
-		if (comp_field_dst->v42bis_params->p2 < 0) {
-			comp_field_dst->v42bis_params->p2 =
-			    comp_field_src->v42bis_params->p2;
-		}
-		return 0;
-	}
-
-	if (comp_field_dst->v44_params && comp_field_src->v44_params) {
-		if (comp_field_dst->v44_params->c0 < 0) {
-			comp_field_dst->v44_params->c0 =
-			    comp_field_src->v44_params->c0;
-		}
-		if (comp_field_dst->v44_params->p0 < 0) {
-			comp_field_dst->v44_params->p0 =
-			    comp_field_src->v44_params->p0;
-		}
-		if (comp_field_dst->v44_params->p1t < 0) {
-			comp_field_dst->v44_params->p1t =
-			    comp_field_src->v44_params->p1t;
-		}
-		if (comp_field_dst->v44_params->p1r < 0) {
-			comp_field_dst->v44_params->p1r =
-			    comp_field_src->v44_params->p1r;
-		}
-		if (comp_field_dst->v44_params->p3t < 0) {
-			comp_field_dst->v44_params->p3t =
-			    comp_field_src->v44_params->p3t;
-		}
-		if (comp_field_dst->v44_params->p3r < 0) {
-			comp_field_dst->v44_params->p3r =
-			    comp_field_src->v44_params->p3r;
-		}
-		return 0;
-	}
-
-	/* There should be at least exist one param set
-	 * in the destination struct, otherwise something
-	 * must be wrong! */
-	return -EINVAL;
-}
-
-/* Complete missing parameters in a comp_field */
-static int gprs_sndcp_complete_comp_field(struct gprs_sndcp_comp_field
-					  *comp_field, const struct llist_head
-					  *comp_fields)
-{
-	struct gprs_sndcp_comp_field *comp_field_src;
-	int rc = 0;
-
-	llist_for_each_entry(comp_field_src, comp_fields, list) {
-		if (comp_field_src->entity == comp_field->entity) {
-
-			/* Complete header fields */
-			if (comp_field_src->comp_len > 0) {
-				memcpy(comp_field->comp,
-				       comp_field_src->comp,
-				       sizeof(comp_field_src->comp));
-				comp_field->comp_len = comp_field_src->comp_len;
-			}
-
-			/* Complete parameter fields */
-			rc = complete_comp_field_params(comp_field,
-							comp_field_src);
-		}
-	}
-
-	return rc;
-}
-
-/* Complete missing parameters of all comp_field in a list */
-static int gprs_sndcp_complete_comp_fields(struct llist_head
-					   *comp_fields_incomplete,
-					   const struct llist_head *comp_fields)
-{
-	struct gprs_sndcp_comp_field *comp_field_incomplete;
-	int rc;
-
-	llist_for_each_entry(comp_field_incomplete, comp_fields_incomplete,
-			     list) {
-
-		rc = gprs_sndcp_complete_comp_field(comp_field_incomplete,
-						    comp_fields);
-		if (rc < 0)
-			return -EINVAL;
-
-	}
-
-	return 0;
-}
-
-/* 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)
-{
-	int rc;
-	int lt_len;
-	struct llist_head *comp_fields;
-	struct entity_algo_table lt[MAX_ENTITIES * 2];
-
-	/* In case of a zero length field, just exit */
-	if (src_len == 0)
-		return NULL;
-
-	/* We should go any further if we have a field length greater
-	 * zero and a null pointer as buffer! */
-	OSMO_ASSERT(src);
-
-	comp_fields = talloc_zero(ctx, struct llist_head);
-	INIT_LLIST_HEAD(comp_fields);
-
-	if (comp_fields_req) {
-		/* Generate lookup table */
-		lt_len =
-		    gprs_sndcp_fill_table(lt, MAX_ENTITIES * 2,
-					  comp_fields_req);
-		if (lt_len < 0) {
-			talloc_free(comp_fields);
-			return NULL;
-		}
-
-		/* Parse SNDCP-CID XID-Field */
-		rc = gprs_sndcp_decode_xid(version, comp_fields, src, src_len,
-					   lt, lt_len);
-		if (rc < 0) {
-			talloc_free(comp_fields);
-			return NULL;
-		}
-
-		rc = gprs_sndcp_complete_comp_fields(comp_fields,
-						     comp_fields_req);
-		if (rc < 0) {
-			talloc_free(comp_fields);
-			return NULL;
-		}
-
-	} else {
-		/* Parse SNDCP-CID XID-Field */
-		rc = gprs_sndcp_decode_xid(version, comp_fields, src, src_len,
-					   NULL, 0);
-		if (rc < 0) {
-			talloc_free(comp_fields);
-			return NULL;
-		}
-	}
-
-	return comp_fields;
-}
-
-/* Helper for gprs_sndcp_dump_comp_fields(),
- * dumps protocol compression parameters */
-static void dump_pcomp_params(const struct gprs_sndcp_comp_field
-			      *comp_field, unsigned int logl)
-{
-	int i;
-
-	switch (comp_field->algo) {
-	case RFC_1144:
-		if (comp_field->rfc1144_params == NULL) {
-			LOGP(DSNDCP, logl,
-			     "   gprs_sndcp_pcomp_rfc1144_params=NULL\n");
-			break;
-		}
-		LOGP(DSNDCP, logl, "   gprs_sndcp_pcomp_rfc1144_params {\n");
-		LOGP(DSNDCP, logl,
-		     "      nsapi_len=%d;\n",
-		     comp_field->rfc1144_params->nsapi_len);
-		if (comp_field->rfc1144_params->nsapi_len == 0)
-			LOGP(DSNDCP, logl, "      nsapi[] = NULL;\n");
-		for (i = 0; i < comp_field->rfc1144_params->nsapi_len; i++) {
-			LOGP(DSNDCP, logl,
-			     "      nsapi[%d]=%d;\n", i,
-			     comp_field->rfc1144_params->nsapi[i]);
-		}
-		LOGP(DSNDCP, logl, "      s01=%d;\n",
-		     comp_field->rfc1144_params->s01);
-		LOGP(DSNDCP, logl, "   }\n");
-		break;
-	case RFC_2507:
-		if (comp_field->rfc2507_params == NULL) {
-			LOGP(DSNDCP, logl,
-			     "   gprs_sndcp_pcomp_rfc2507_params=NULL\n");
-			break;
-		}
-		LOGP(DSNDCP, logl, "   gprs_sndcp_pcomp_rfc2507_params {\n");
-		LOGP(DSNDCP, logl,
-		     "      nsapi_len=%d;\n",
-		     comp_field->rfc2507_params->nsapi_len);
-		if (comp_field->rfc2507_params->nsapi_len == 0)
-			LOGP(DSNDCP, logl, "      nsapi[] = NULL;\n");
-		for (i = 0; i < comp_field->rfc2507_params->nsapi_len; i++) {
-			LOGP(DSNDCP, logl,
-			     "      nsapi[%d]=%d;\n", i,
-			     comp_field->rfc2507_params->nsapi[i]);
-		}
-		LOGP(DSNDCP, logl,
-		     "      f_max_period=%d;\n",
-		     comp_field->rfc2507_params->f_max_period);
-		LOGP(DSNDCP, logl,
-		     "      f_max_time=%d;\n",
-		     comp_field->rfc2507_params->f_max_time);
-		LOGP(DSNDCP, logl,
-		     "      max_header=%d;\n",
-		     comp_field->rfc2507_params->max_header);
-		LOGP(DSNDCP, logl,
-		     "      tcp_space=%d;\n",
-		     comp_field->rfc2507_params->tcp_space);
-		LOGP(DSNDCP, logl,
-		     "      non_tcp_space=%d;\n",
-		     comp_field->rfc2507_params->non_tcp_space);
-		LOGP(DSNDCP, logl, "   }\n");
-		break;
-	case ROHC:
-		if (comp_field->rohc_params == NULL) {
-			LOGP(DSNDCP, logl,
-			     "   gprs_sndcp_pcomp_rohc_params=NULL\n");
-			break;
-		}
-		LOGP(DSNDCP, logl, "   gprs_sndcp_pcomp_rohc_params {\n");
-		LOGP(DSNDCP, logl,
-		     "      nsapi_len=%d;\n",
-		     comp_field->rohc_params->nsapi_len);
-		if (comp_field->rohc_params->nsapi_len == 0)
-			LOGP(DSNDCP, logl, "      nsapi[] = NULL;\n");
-		for (i = 0; i < comp_field->rohc_params->nsapi_len; i++) {
-			LOGP(DSNDCP, logl,
-			     "      nsapi[%d]=%d;\n", i,
-			     comp_field->rohc_params->nsapi[i]);
-		}
-		LOGP(DSNDCP, logl,
-		     "      max_cid=%d;\n", comp_field->rohc_params->max_cid);
-		LOGP(DSNDCP, logl,
-		     "      max_header=%d;\n",
-		     comp_field->rohc_params->max_header);
-		LOGP(DSNDCP, logl,
-		     "      profile_len=%d;\n",
-		     comp_field->rohc_params->profile_len);
-		if (comp_field->rohc_params->profile_len == 0)
-			LOGP(DSNDCP, logl, "      profile[] = NULL;\n");
-		for (i = 0; i < comp_field->rohc_params->profile_len; i++)
-			LOGP(DSNDCP, logl,
-			     "      profile[%d]=%04x;\n",
-			     i, comp_field->rohc_params->profile[i]);
-		LOGP(DSNDCP, logl, "   }\n");
-		break;
-	}
-
-}
-
-/* Helper for gprs_sndcp_dump_comp_fields(),
- * data protocol compression parameters */
-static void dump_dcomp_params(const struct gprs_sndcp_comp_field
-			      *comp_field, unsigned int logl)
-{
-	int i;
-
-	switch (comp_field->algo) {
-	case V42BIS:
-		if (comp_field->v42bis_params == NULL) {
-			LOGP(DSNDCP, logl,
-			     "   gprs_sndcp_dcomp_v42bis_params=NULL\n");
-			break;
-		}
-		LOGP(DSNDCP, logl, "   gprs_sndcp_dcomp_v42bis_params {\n");
-		LOGP(DSNDCP, logl,
-		     "      nsapi_len=%d;\n",
-		     comp_field->v42bis_params->nsapi_len);
-		if (comp_field->v42bis_params->nsapi_len == 0)
-			LOGP(DSNDCP, logl, "      nsapi[] = NULL;\n");
-		for (i = 0; i < comp_field->v42bis_params->nsapi_len; i++)
-			LOGP(DSNDCP, logl,
-			     "      nsapi[%d]=%d;\n", i,
-			     comp_field->v42bis_params->nsapi[i]);
-		LOGP(DSNDCP, logl, "      p0=%d;\n",
-		     comp_field->v42bis_params->p0);
-		LOGP(DSNDCP, logl, "      p1=%d;\n",
-		     comp_field->v42bis_params->p1);
-		LOGP(DSNDCP, logl, "      p2=%d;\n",
-		     comp_field->v42bis_params->p2);
-		LOGP(DSNDCP, logl, "   }\n");
-		break;
-	case V44:
-		if (comp_field->v44_params == NULL) {
-			LOGP(DSNDCP, logl,
-			     "   gprs_sndcp_dcomp_v44_params=NULL\n");
-			break;
-		}
-		LOGP(DSNDCP, logl, "   gprs_sndcp_dcomp_v44_params {\n");
-		LOGP(DSNDCP, logl,
-		     "      nsapi_len=%d;\n",
-		     comp_field->v44_params->nsapi_len);
-		if (comp_field->v44_params->nsapi_len == 0)
-			LOGP(DSNDCP, logl, "      nsapi[] = NULL;\n");
-		for (i = 0; i < comp_field->v44_params->nsapi_len; i++) {
-			LOGP(DSNDCP, logl,
-			     "      nsapi[%d]=%d;\n", i,
-			     comp_field->v44_params->nsapi[i]);
-		}
-		LOGP(DSNDCP, logl, "      c0=%d;\n",
-		     comp_field->v44_params->c0);
-		LOGP(DSNDCP, logl, "      p0=%d;\n",
-		     comp_field->v44_params->p0);
-		LOGP(DSNDCP, logl, "      p1t=%d;\n",
-		     comp_field->v44_params->p1t);
-		LOGP(DSNDCP, logl, "      p1r=%d;\n",
-		     comp_field->v44_params->p1r);
-		LOGP(DSNDCP, logl, "      p3t=%d;\n",
-		     comp_field->v44_params->p3t);
-		LOGP(DSNDCP, logl, "      p3r=%d;\n",
-		     comp_field->v44_params->p3r);
-		LOGP(DSNDCP, logl, "   }\n");
-		break;
-	}
-}
-
-/* Dump a list with SNDCP-XID fields (Debug) */
-void gprs_sndcp_dump_comp_fields(const struct llist_head *comp_fields,
-				 unsigned int logl)
-{
-	struct gprs_sndcp_comp_field *comp_field;
-	int i;
-	int compclass;
-
-	OSMO_ASSERT(comp_fields);
-
-	llist_for_each_entry(comp_field, comp_fields, list) {
-		LOGP(DSNDCP, logl, "SNDCP-XID:\n");
-		LOGP(DSNDCP, logl, "struct gprs_sndcp_comp_field {\n");
-		LOGP(DSNDCP, logl, "   entity=%d;\n", comp_field->entity);
-		LOGP(DSNDCP, logl, "   algo=%d;\n", comp_field->algo);
-		LOGP(DSNDCP, logl, "   comp_len=%d;\n", comp_field->comp_len);
-		if (comp_field->comp_len == 0)
-			LOGP(DSNDCP, logl, "   comp[] = NULL;\n");
-		for (i = 0; i < comp_field->comp_len; i++) {
-			LOGP(DSNDCP, logl, "   comp[%d]=%d;\n", i,
-			     comp_field->comp[i]);
-		}
-
-		compclass = gprs_sndcp_get_compression_class(comp_field);
-
-		if (compclass == SNDCP_XID_PROTOCOL_COMPRESSION) {
-			dump_pcomp_params(comp_field, logl);
-		} else if (compclass == SNDCP_XID_DATA_COMPRESSION) {
-			dump_dcomp_params(comp_field, logl);
-		}
-
-		LOGP(DSNDCP, logl, "}\n");
-	}
-
-}
diff --git a/src/gprs/gprs_subscriber.c b/src/gprs/gprs_subscriber.c
deleted file mode 100644
index 94297d0..0000000
--- a/src/gprs/gprs_subscriber.c
+++ /dev/null
@@ -1,937 +0,0 @@
-/* MS subscriber data handling */
-
-/* (C) 2014 by sysmocom s.f.m.c. GmbH
- * (C) 2015 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/>.
- *
- */
-
-#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
-#include <osmocom/gsm/gsup.h>
-#include <osmocom/gsm/apn.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/logging.h>
-#include <openbsc/gprs_subscriber.h>
-#include <openbsc/gsup_client.h>
-
-#include <openbsc/sgsn.h>
-#include <openbsc/gprs_sgsn.h>
-#include <openbsc/gprs_gmm.h>
-#include <openbsc/gprs_utils.h>
-
-#include <openbsc/debug.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <limits.h>
-
-#define SGSN_SUBSCR_MAX_RETRIES 3
-#define SGSN_SUBSCR_RETRY_INTERVAL 10
-
-#define LOGGSUPP(level, gsup, fmt, args...) \
-	LOGP(DGPRS, level, "GSUP(%s) " fmt, \
-	     (gsup)->imsi, \
-	     ## args)
-
-extern void *tall_bsc_ctx;
-
-LLIST_HEAD(_gprs_subscribers);
-struct llist_head * const gprs_subscribers = &_gprs_subscribers;
-
-static int gsup_read_cb(struct gsup_client *gsupc, struct msgb *msg);
-
-/* TODO: Some functions are specific to the SGSN, but this file is more general
- * (it has gprs_* name). Either move these functions elsewhere, split them and
- * move a part, or replace the gprs_ prefix by sgsn_. The applies to
- * gprs_subscr_init, gsup_read_cb, and gprs_subscr_tx_gsup_message.
- */
-
-int gprs_subscr_init(struct sgsn_instance *sgi)
-{
-	const char *addr_str;
-
-	if (!sgi->cfg.gsup_server_addr.sin_addr.s_addr)
-		return 0;
-
-	addr_str = inet_ntoa(sgi->cfg.gsup_server_addr.sin_addr);
-
-	sgi->gsup_client = gsup_client_create(
-		"SGSN",
-		addr_str, sgi->cfg.gsup_server_port,
-		&gsup_read_cb,
-		&sgi->cfg.oap);
-
-	if (!sgi->gsup_client)
-		return -1;
-
-	return 1;
-}
-
-static int gsup_read_cb(struct gsup_client *gsupc, struct msgb *msg)
-{
-	int rc;
-
-	rc = gprs_subscr_rx_gsup_message(msg);
-	msgb_free(msg);
-	if (rc < 0)
-		return -1;
-
-	return rc;
-}
-
-int gprs_subscr_purge(struct gprs_subscr *subscr);
-
-static struct sgsn_subscriber_data *sgsn_subscriber_data_alloc(void *ctx)
-{
-	struct sgsn_subscriber_data *sdata;
-	int idx;
-
-	sdata = talloc_zero(ctx, struct sgsn_subscriber_data);
-
-	sdata->error_cause = SGSN_ERROR_CAUSE_NONE;
-
-	for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
-	     sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
-
-	INIT_LLIST_HEAD(&sdata->pdp_list);
-
-	return sdata;
-}
-
-struct sgsn_subscriber_pdp_data* sgsn_subscriber_pdp_data_alloc(
-	struct sgsn_subscriber_data *sdata)
-{
-	struct sgsn_subscriber_pdp_data* pdata;
-
-	pdata = talloc_zero(sdata, struct sgsn_subscriber_pdp_data);
-
-	llist_add_tail(&pdata->list, &sdata->pdp_list);
-
-	return pdata;
-}
-
-struct gprs_subscr *gprs_subscr_get_by_imsi(const char *imsi)
-{
-	struct gprs_subscr *gsub;
-
-	if (!imsi || !*imsi)
-		return NULL;
-
-	llist_for_each_entry(gsub, gprs_subscribers, entry) {
-		if (!strcmp(gsub->imsi, imsi))
-			return gprs_subscr_get(gsub);
-	}
-	return NULL;
-}
-
-static struct gprs_subscr *gprs_subscr_alloc(void)
-{
-	struct gprs_subscr *gsub;
-	gsub = talloc_zero(tall_bsc_ctx, struct gprs_subscr);
-	if (!gsub)
-		return NULL;
-	llist_add_tail(&gsub->entry, gprs_subscribers);
-	gsub->use_count = 1;
-	gsub->tmsi = GSM_RESERVED_TMSI;
-	return gsub;
-}
-
-struct gprs_subscr *gprs_subscr_get_or_create(const char *imsi)
-{
-	struct gprs_subscr *gsub;
-
-	gsub = gprs_subscr_get_by_imsi(imsi);
-	if (!gsub) {
-		gsub = gprs_subscr_alloc();
-		if (!gsub)
-			return NULL;
-		osmo_strlcpy(gsub->imsi, imsi, sizeof(gsub->imsi));
-	}
-
-	if (!gsub->sgsn_data)
-		gsub->sgsn_data = sgsn_subscriber_data_alloc(gsub);
-	return gsub;
-}
-
-void gprs_subscr_cleanup(struct gprs_subscr *subscr)
-{
-	if (subscr->sgsn_data->mm) {
-		gprs_subscr_put(subscr->sgsn_data->mm->subscr);
-		subscr->sgsn_data->mm->subscr = NULL;
-		subscr->sgsn_data->mm = NULL;
-	}
-
-	if (subscr->flags & GPRS_SUBSCRIBER_ENABLE_PURGE) {
-		gprs_subscr_purge(subscr);
-		subscr->flags &= ~GPRS_SUBSCRIBER_ENABLE_PURGE;
-	}
-}
-
-void gprs_subscr_cancel(struct gprs_subscr *subscr)
-{
-	subscr->authorized = 0;
-	subscr->flags |= GPRS_SUBSCRIBER_CANCELLED;
-	subscr->flags &= ~GPRS_SUBSCRIBER_ENABLE_PURGE;
-
-	gprs_subscr_update(subscr);
-	gprs_subscr_cleanup(subscr);
-}
-
-static int gprs_subscr_tx_gsup_message(struct gprs_subscr *subscr,
-				       struct osmo_gsup_message *gsup_msg)
-{
-	struct msgb *msg = gsup_client_msgb_alloc();
-
-	if (strlen(gsup_msg->imsi) == 0 && subscr)
-		osmo_strlcpy(gsup_msg->imsi, subscr->imsi,
-			     sizeof(gsup_msg->imsi));
-	gsup_msg->cn_domain = OSMO_GSUP_CN_DOMAIN_PS;
-	osmo_gsup_encode(msg, gsup_msg);
-
-	LOGGSUBSCRP(LOGL_INFO, subscr,
-		    "Sending GSUP, will send: %s\n", msgb_hexdump(msg));
-
-	if (!sgsn->gsup_client) {
-		msgb_free(msg);
-		return -ENOTSUP;
-	}
-
-	return gsup_client_send(sgsn->gsup_client, msg);
-}
-
-static int gprs_subscr_tx_gsup_error_reply(struct gprs_subscr *subscr,
-					   struct osmo_gsup_message *gsup_orig,
-					   enum gsm48_gmm_cause cause)
-{
-	struct osmo_gsup_message gsup_reply = {0};
-
-	osmo_strlcpy(gsup_reply.imsi, gsup_orig->imsi,
-		     sizeof(gsup_reply.imsi));
-	gsup_reply.cause = cause;
-	gsup_reply.message_type =
-		OSMO_GSUP_TO_MSGT_ERROR(gsup_orig->message_type);
-
-	return gprs_subscr_tx_gsup_message(subscr, &gsup_reply);
-}
-
-static int gprs_subscr_handle_gsup_auth_res(struct gprs_subscr *subscr,
-					    struct osmo_gsup_message *gsup_msg)
-{
-	unsigned idx;
-	struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
-
-	LOGGSUBSCRP(LOGL_INFO, subscr,
-		"Got SendAuthenticationInfoResult, num_auth_vectors = %zu\n",
-		gsup_msg->num_auth_vectors);
-
-	if (gsup_msg->num_auth_vectors > 0) {
-		memset(sdata->auth_triplets, 0, sizeof(sdata->auth_triplets));
-
-		for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
-			sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
-	}
-
-	for (idx = 0; idx < gsup_msg->num_auth_vectors; idx++) {
-		size_t key_seq = idx;
-		LOGGSUBSCRP(LOGL_DEBUG, subscr,
-			"Adding auth tuple, cksn = %zu\n", key_seq);
-		if (key_seq >= ARRAY_SIZE(sdata->auth_triplets)) {
-			LOGGSUBSCRP(LOGL_NOTICE, subscr,
-				"Skipping auth triplet with invalid cksn %zu\n",
-				key_seq);
-			continue;
-		}
-		sdata->auth_triplets[key_seq].vec = gsup_msg->auth_vectors[idx];
-		sdata->auth_triplets[key_seq].key_seq = key_seq;
-	}
-
-	sdata->auth_triplets_updated = 1;
-	sdata->error_cause = SGSN_ERROR_CAUSE_NONE;
-
-	gprs_subscr_update_auth_info(subscr);
-
-	return 0;
-}
-
-static int gprs_subscr_pdp_data_clear(struct gprs_subscr *subscr)
-{
-	struct sgsn_subscriber_pdp_data *pdp, *pdp2;
-	int count = 0;
-
-	llist_for_each_entry_safe(pdp, pdp2, &subscr->sgsn_data->pdp_list, list) {
-		llist_del(&pdp->list);
-		talloc_free(pdp);
-		count += 1;
-	}
-
-	return count;
-}
-
-static struct sgsn_subscriber_pdp_data *gprs_subscr_pdp_data_get_by_id(
-	struct gprs_subscr *subscr, unsigned context_id)
-{
-	struct sgsn_subscriber_pdp_data *pdp;
-
-	llist_for_each_entry(pdp, &subscr->sgsn_data->pdp_list, list) {
-		if (pdp->context_id == context_id)
-			return pdp;
-	}
-
-	return NULL;
-}
-
-
-static void gprs_subscr_gsup_insert_data(struct gprs_subscr *subscr,
-					 struct osmo_gsup_message *gsup_msg)
-{
-	struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
-	unsigned idx;
-	int rc;
-
-	if (gsup_msg->msisdn_enc) {
-		if (gsup_msg->msisdn_enc_len > sizeof(sdata->msisdn)) {
-			LOGP(DGPRS, LOGL_ERROR, "MSISDN too long (%zu)\n",
-				gsup_msg->msisdn_enc_len);
-			sdata->msisdn_len = 0;
-		} else {
-			memcpy(sdata->msisdn, gsup_msg->msisdn_enc,
-				gsup_msg->msisdn_enc_len);
-			sdata->msisdn_len = gsup_msg->msisdn_enc_len;
-		}
-	}
-
-	if (gsup_msg->hlr_enc) {
-		if (gsup_msg->hlr_enc_len > sizeof(sdata->hlr)) {
-			LOGP(DGPRS, LOGL_ERROR, "HLR-Number too long (%zu)\n",
-				gsup_msg->hlr_enc_len);
-			sdata->hlr_len = 0;
-		} else {
-			memcpy(sdata->hlr, gsup_msg->hlr_enc,
-				gsup_msg->hlr_enc_len);
-			sdata->hlr_len = gsup_msg->hlr_enc_len;
-		}
-	}
-
-	if (gsup_msg->pdp_charg_enc && gsup_msg->pdp_charg_enc_len >= sizeof(sdata->pdp_charg)) {
-		memcpy(&sdata->pdp_charg, gsup_msg->pdp_charg_enc, sizeof(sdata->pdp_charg));
-		sdata->has_pdp_charg = 1;
-	} else {
-		sdata->has_pdp_charg = 0;
-	}
-
-	if (gsup_msg->pdp_info_compl) {
-		rc = gprs_subscr_pdp_data_clear(subscr);
-		if (rc > 0)
-			LOGP(DGPRS, LOGL_INFO, "Cleared existing PDP info\n");
-	}
-
-	for (idx = 0; idx < gsup_msg->num_pdp_infos; idx++) {
-		struct osmo_gsup_pdp_info *pdp_info = &gsup_msg->pdp_infos[idx];
-		size_t ctx_id = pdp_info->context_id;
-		struct sgsn_subscriber_pdp_data *pdp_data;
-
-		if (pdp_info->apn_enc_len >= sizeof(pdp_data->apn_str)-1) {
-			LOGGSUBSCRP(LOGL_ERROR, subscr,
-			     "APN too long, context id = %zu, APN = %s\n",
-			     ctx_id, osmo_hexdump(pdp_info->apn_enc,
-						  pdp_info->apn_enc_len));
-			continue;
-		}
-
-		if (pdp_info->qos_enc_len > sizeof(pdp_data->qos_subscribed)) {
-			LOGGSUBSCRP(LOGL_ERROR, subscr,
-				"QoS info too long (%zu)\n",
-				pdp_info->qos_enc_len);
-			continue;
-		}
-
-		LOGGSUBSCRP(LOGL_INFO, subscr,
-		     "Will set PDP info, context id = %zu, APN = %s\n",
-		     ctx_id, osmo_hexdump(pdp_info->apn_enc, pdp_info->apn_enc_len));
-
-		/* Set PDP info [ctx_id] */
-		pdp_data = gprs_subscr_pdp_data_get_by_id(subscr, ctx_id);
-		if (!pdp_data) {
-			pdp_data = sgsn_subscriber_pdp_data_alloc(subscr->sgsn_data);
-			pdp_data->context_id = ctx_id;
-		}
-
-		OSMO_ASSERT(pdp_data != NULL);
-		pdp_data->pdp_type = pdp_info->pdp_type;
-		osmo_apn_to_str(pdp_data->apn_str,
-				pdp_info->apn_enc, pdp_info->apn_enc_len);
-		memcpy(pdp_data->qos_subscribed, pdp_info->qos_enc, pdp_info->qos_enc_len);
-		pdp_data->qos_subscribed_len = pdp_info->qos_enc_len;
-
-		if (pdp_info->pdp_charg_enc && pdp_info->pdp_charg_enc_len >= sizeof(pdp_data->pdp_charg)) {
-			memcpy(&pdp_data->pdp_charg, pdp_info->pdp_charg_enc, sizeof(pdp_data->pdp_charg));
-			pdp_data->has_pdp_charg = 1;
-		} else {
-			pdp_data->has_pdp_charg = 0;
-		}
-	}
-}
-
-static int gprs_subscr_handle_gsup_upd_loc_res(struct gprs_subscr *subscr,
-					       struct osmo_gsup_message *gsup_msg)
-{
-	/* contrary to MAP, we allow piggy-backing subscriber data onto
-	 * the UPDATE LOCATION RESULT, and don't mandate the use of a
-	 * separate nested INSERT SUBSCRIBER DATA transaction */
-	gprs_subscr_gsup_insert_data(subscr, gsup_msg);
-
-	subscr->authorized = 1;
-	subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
-
-	subscr->flags |= GPRS_SUBSCRIBER_ENABLE_PURGE;
-
-	gprs_subscr_update(subscr);
-	return 0;
-}
-
-static int gprs_subscr_handle_gsup_dsd_req(struct gprs_subscr *subscr,
-					   struct osmo_gsup_message *gsup_msg)
-{
-	struct osmo_gsup_message gsup_reply = {0};
-
-	if (gsup_msg->cn_domain != OSMO_GSUP_CN_DOMAIN_PS) {
-		LOGGSUBSCRP(LOGL_ERROR, subscr,
-			    "Rx GSUP message %s not supported for CS\n",
-			    osmo_gsup_message_type_name(gsup_msg->message_type));
-		gsup_reply.cause = GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
-		gsup_reply.message_type = OSMO_GSUP_MSGT_DELETE_DATA_ERROR;
-	} else {
-		gsm0408_gprs_access_cancelled(subscr->sgsn_data->mm,
-					      GMM_CAUSE_GPRS_NOTALLOWED);
-		gsup_reply.message_type = OSMO_GSUP_MSGT_DELETE_DATA_RESULT;
-	}
-
-	return gprs_subscr_tx_gsup_message(subscr, &gsup_reply);
-}
-
-static int gprs_subscr_handle_gsup_isd_req(struct gprs_subscr *subscr,
-					   struct osmo_gsup_message *gsup_msg)
-{
-	struct osmo_gsup_message gsup_reply = {0};
-
-	gprs_subscr_gsup_insert_data(subscr, gsup_msg);
-
-	subscr->authorized = 1;
-	subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
-	subscr->flags |= GPRS_SUBSCRIBER_ENABLE_PURGE;
-	gprs_subscr_update(subscr);
-
-	gsup_reply.message_type = OSMO_GSUP_MSGT_INSERT_DATA_RESULT;
-	return gprs_subscr_tx_gsup_message(subscr, &gsup_reply);
-}
-
-static int check_cause(int cause)
-{
-	switch (cause) {
-	case GMM_CAUSE_IMSI_UNKNOWN ... GMM_CAUSE_ILLEGAL_ME:
-	case GMM_CAUSE_GPRS_NOTALLOWED ... GMM_CAUSE_NO_GPRS_PLMN:
-		return EACCES;
-
-	case GMM_CAUSE_MSC_TEMP_NOTREACH ... GMM_CAUSE_CONGESTION:
-		return EHOSTUNREACH;
-
-	case GMM_CAUSE_SEM_INCORR_MSG ... GMM_CAUSE_PROTO_ERR_UNSPEC:
-	default:
-		return EINVAL;
-	}
-}
-
-static int gprs_subscr_handle_gsup_auth_err(struct gprs_subscr *subscr,
-					    struct osmo_gsup_message *gsup_msg)
-{
-	unsigned idx;
-	struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
-	int cause_err;
-
-	cause_err = check_cause(gsup_msg->cause);
-
-	LOGGSUBSCRP(LOGL_DEBUG, subscr,
-		"Send authentication info has failed with cause %d, "
-		"handled as: %s\n",
-		gsup_msg->cause, strerror(cause_err));
-
-	switch (cause_err) {
-	case EACCES:
-		LOGGSUBSCRP(LOGL_NOTICE, subscr,
-			"GPRS send auth info req failed, access denied, "
-			"GMM cause = '%s' (%d)\n",
-			get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
-			gsup_msg->cause);
-		/* Clear auth tuples */
-		memset(sdata->auth_triplets, 0, sizeof(sdata->auth_triplets));
-		for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
-			sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
-
-		subscr->authorized = 0;
-		sdata->error_cause = gsup_msg->cause;
-		gprs_subscr_update_auth_info(subscr);
-		break;
-
-	case EHOSTUNREACH:
-		LOGGSUBSCRP(LOGL_NOTICE, subscr,
-			"GPRS send auth info req failed, GMM cause = '%s' (%d)\n",
-			get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
-			gsup_msg->cause);
-
-		sdata->error_cause = gsup_msg->cause;
-		gprs_subscr_update_auth_info(subscr);
-		break;
-
-	default:
-	case EINVAL:
-		LOGGSUBSCRP(LOGL_ERROR, subscr,
-			"GSUP protocol remote error, GMM cause = '%s' (%d)\n",
-			get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
-			gsup_msg->cause);
-		break;
-	}
-
-	return -gsup_msg->cause;
-}
-
-static int gprs_subscr_handle_gsup_upd_loc_err(struct gprs_subscr *subscr,
-					       struct osmo_gsup_message *gsup_msg)
-{
-	int cause_err;
-
-	cause_err = check_cause(gsup_msg->cause);
-
-	LOGGSUBSCRP(LOGL_DEBUG, subscr,
-		"Update location has failed with cause %d, handled as: %s\n",
-		gsup_msg->cause, strerror(cause_err));
-
-	switch (cause_err) {
-	case EACCES:
-		LOGGSUBSCRP(LOGL_NOTICE, subscr,
-			"GPRS update location failed, access denied, "
-			"GMM cause = '%s' (%d)\n",
-			get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
-			gsup_msg->cause);
-
-		subscr->authorized = 0;
-		subscr->sgsn_data->error_cause = gsup_msg->cause;
-		gprs_subscr_update_auth_info(subscr);
-		break;
-
-	case EHOSTUNREACH:
-		LOGGSUBSCRP(LOGL_NOTICE, subscr,
-			"GPRS update location failed, GMM cause = '%s' (%d)\n",
-			get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
-			gsup_msg->cause);
-
-		subscr->sgsn_data->error_cause = gsup_msg->cause;
-		gprs_subscr_update_auth_info(subscr);
-		break;
-
-	default:
-	case EINVAL:
-		LOGGSUBSCRP(LOGL_ERROR, subscr,
-			"GSUP protocol remote error, GMM cause = '%s' (%d)\n",
-			get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
-			gsup_msg->cause);
-		break;
-	}
-
-	return -gsup_msg->cause;
-}
-
-static int gprs_subscr_handle_gsup_purge_no_subscr(
-	struct osmo_gsup_message *gsup_msg)
-{
-	if (OSMO_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) {
-		LOGGSUPP(LOGL_NOTICE, gsup_msg,
-			 "Purge MS has failed with cause '%s' (%d)\n",
-			 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
-			 gsup_msg->cause);
-		return -gsup_msg->cause;
-	}
-
-	LOGGSUPP(LOGL_INFO, gsup_msg, "Completing purge MS\n");
-	return 0;
-}
-
-static int gprs_subscr_handle_gsup_purge_res(struct gprs_subscr *subscr,
-					     struct osmo_gsup_message *gsup_msg)
-{
-	LOGGSUBSCRP(LOGL_INFO, subscr, "Completing purge MS\n");
-
-	/* Force silent cancellation */
-	subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
-	gprs_subscr_cancel(subscr);
-
-	return 0;
-}
-
-static int gprs_subscr_handle_gsup_purge_err(struct gprs_subscr *subscr,
-					     struct osmo_gsup_message *gsup_msg)
-{
-	LOGGSUBSCRP(LOGL_NOTICE, subscr,
-		    "Purge MS has failed with cause '%s' (%d)\n",
-		    get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
-		    gsup_msg->cause);
-
-	/* In GSM 09.02, 19.1.4.4, the text and the SDL diagram imply that
-	 * the subscriber data is not removed if the request has failed. On the
-	 * other hand, keeping the subscriber data in either error case
-	 * (subscriber unknown, syntactical message error, connection error)
-	 * doesn't seem to give any advantage, since the data will be restored
-	 * on the next Attach Request anyway.
-	 * This approach ensures, that the subscriber record will not stick if
-	 * an error happens.
-	 */
-
-	/* TODO: Check whether this behaviour is acceptable and either just
-	 * remove this TODO-notice or change the implementation to not delete
-	 * the subscriber data (eventually resetting the ENABLE_PURGE flag and
-	 * restarting the expiry timer based on the cause).
-	 *
-	 * Subscriber Unknown: cancel subscr
-	 * Temporary network problems: do nothing (handled by timer based retry)
-	 * Message problems (syntax, nyi, ...): cancel subscr (retry won't help)
-	 */
-
-	gprs_subscr_handle_gsup_purge_res(subscr, gsup_msg);
-
-	return -gsup_msg->cause;
-}
-
-static int gprs_subscr_handle_loc_cancel_req(struct gprs_subscr *subscr,
-					     struct osmo_gsup_message *gsup_msg)
-{
-	struct osmo_gsup_message gsup_reply = {0};
-	int is_update_procedure = !gsup_msg->cancel_type ||
-		gsup_msg->cancel_type == OSMO_GSUP_CANCEL_TYPE_UPDATE;
-
-	LOGGSUBSCRP(LOGL_INFO, subscr, "Cancelling MS subscriber (%s)\n",
-		    is_update_procedure ?
-		    "update procedure" : "subscription withdraw");
-
-	gsup_reply.message_type = OSMO_GSUP_MSGT_LOCATION_CANCEL_RESULT;
-	gprs_subscr_tx_gsup_message(subscr, &gsup_reply);
-
-	if (is_update_procedure)
-		subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
-	else
-		/* Since a withdraw cause is not specified, just abort the
-		 * current attachment. The following re-attachment should then
-		 * be rejected with a proper cause value.
-		 */
-		subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
-
-	gprs_subscr_cancel(subscr);
-
-	return 0;
-}
-
-static int gprs_subscr_handle_unknown_imsi(struct osmo_gsup_message *gsup_msg)
-{
-	if (OSMO_GSUP_IS_MSGT_REQUEST(gsup_msg->message_type)) {
-		gprs_subscr_tx_gsup_error_reply(NULL, gsup_msg,
-						GMM_CAUSE_IMSI_UNKNOWN);
-		LOGP(DGPRS, LOGL_NOTICE,
-		     "Unknown IMSI %s, discarding GSUP request "
-		     "of type 0x%02x\n",
-		     gsup_msg->imsi, gsup_msg->message_type);
-	} else if (OSMO_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) {
-		LOGP(DGPRS, LOGL_NOTICE,
-		     "Unknown IMSI %s, discarding GSUP error "
-		     "of type 0x%02x, cause '%s' (%d)\n",
-		     gsup_msg->imsi, gsup_msg->message_type,
-		     get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
-		     gsup_msg->cause);
-	} else {
-		LOGP(DGPRS, LOGL_NOTICE,
-		     "Unknown IMSI %s, discarding GSUP response "
-		     "of type 0x%02x\n",
-		     gsup_msg->imsi, gsup_msg->message_type);
-	}
-
-	return -GMM_CAUSE_IMSI_UNKNOWN;
-}
-
-int gprs_subscr_rx_gsup_message(struct msgb *msg)
-{
-	uint8_t *data = msgb_l2(msg);
-	size_t data_len = msgb_l2len(msg);
-	int rc = 0;
-
-	struct osmo_gsup_message gsup_msg = {0};
-	struct gprs_subscr *subscr;
-
-	rc = osmo_gsup_decode(data, data_len, &gsup_msg);
-	if (rc < 0) {
-		LOGP(DGPRS, LOGL_ERROR,
-		     "decoding GSUP message fails with error '%s' (%d)\n",
-		     get_value_string(gsm48_gmm_cause_names, -rc), -rc);
-		return rc;
-	}
-
-	if (!gsup_msg.imsi[0]) {
-		LOGP(DGPRS, LOGL_ERROR, "Missing IMSI in GSUP message\n");
-
-		if (OSMO_GSUP_IS_MSGT_REQUEST(gsup_msg.message_type))
-			gprs_subscr_tx_gsup_error_reply(NULL, &gsup_msg,
-							GMM_CAUSE_INV_MAND_INFO);
-		return -GMM_CAUSE_INV_MAND_INFO;
-	}
-
-	if (!gsup_msg.cause && OSMO_GSUP_IS_MSGT_ERROR(gsup_msg.message_type))
-		gsup_msg.cause = GMM_CAUSE_NET_FAIL;
-
-	subscr = gprs_subscr_get_by_imsi(gsup_msg.imsi);
-
-	if (!subscr) {
-		switch (gsup_msg.message_type) {
-		case OSMO_GSUP_MSGT_PURGE_MS_RESULT:
-		case OSMO_GSUP_MSGT_PURGE_MS_ERROR:
-			return gprs_subscr_handle_gsup_purge_no_subscr(&gsup_msg);
-		default:
-			return gprs_subscr_handle_unknown_imsi(&gsup_msg);
-		}
-	}
-
-	LOGGSUBSCRP(LOGL_INFO, subscr,
-		    "Received GSUP message %s\n",
-		    osmo_gsup_message_type_name(gsup_msg.message_type));
-
-	switch (gsup_msg.message_type) {
-	case OSMO_GSUP_MSGT_LOCATION_CANCEL_REQUEST:
-		rc = gprs_subscr_handle_loc_cancel_req(subscr, &gsup_msg);
-		break;
-
-	case OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT:
-		rc = gprs_subscr_handle_gsup_auth_res(subscr, &gsup_msg);
-		break;
-
-	case OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR:
-		rc = gprs_subscr_handle_gsup_auth_err(subscr, &gsup_msg);
-		break;
-
-	case OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT:
-		rc = gprs_subscr_handle_gsup_upd_loc_res(subscr, &gsup_msg);
-		break;
-
-	case OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR:
-		rc = gprs_subscr_handle_gsup_upd_loc_err(subscr, &gsup_msg);
-		break;
-
-	case OSMO_GSUP_MSGT_PURGE_MS_ERROR:
-		rc = gprs_subscr_handle_gsup_purge_err(subscr, &gsup_msg);
-		break;
-
-	case OSMO_GSUP_MSGT_PURGE_MS_RESULT:
-		rc = gprs_subscr_handle_gsup_purge_res(subscr, &gsup_msg);
-		break;
-
-	case OSMO_GSUP_MSGT_INSERT_DATA_REQUEST:
-		rc = gprs_subscr_handle_gsup_isd_req(subscr, &gsup_msg);
-		break;
-
-	case OSMO_GSUP_MSGT_DELETE_DATA_REQUEST:
-		rc = gprs_subscr_handle_gsup_dsd_req(subscr, &gsup_msg);
-		break;
-
-	default:
-		LOGGSUBSCRP(LOGL_ERROR, subscr,
-			    "Rx GSUP message %s not valid at SGSN\n",
-			    osmo_gsup_message_type_name(gsup_msg.message_type));
-		if (OSMO_GSUP_IS_MSGT_REQUEST(gsup_msg.message_type))
-			gprs_subscr_tx_gsup_error_reply(
-				subscr, &gsup_msg, GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
-		rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
-		break;
-	};
-
-	gprs_subscr_put(subscr);
-
-	return rc;
-}
-
-int gprs_subscr_purge(struct gprs_subscr *subscr)
-{
-	struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
-	struct osmo_gsup_message gsup_msg = {0};
-
-	LOGGSUBSCRP(LOGL_INFO, subscr, "purging MS subscriber\n");
-
-	gsup_msg.message_type = OSMO_GSUP_MSGT_PURGE_MS_REQUEST;
-
-	/* Provide the HLR number in case it is known */
-	gsup_msg.hlr_enc_len = sdata->hlr_len;
-	gsup_msg.hlr_enc = sdata->hlr;
-
-	return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
-}
-
-static int gprs_subscr_query_auth_info(struct gprs_subscr *subscr,
-				       const uint8_t *auts,
-				       const uint8_t *auts_rand)
-{
-	struct osmo_gsup_message gsup_msg = {0};
-
-	/* Make sure we have a complete resync or clearly no resync. */
-	OSMO_ASSERT((auts != NULL) == (auts_rand != NULL));
-
-	LOGGSUBSCRP(LOGL_INFO, subscr, "requesting auth info%s\n",
-		    auts ? " with AUTS (UMTS Resynch)" : "");
-
-	gsup_msg.message_type = OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST;
-	gsup_msg.auts = auts;
-	gsup_msg.rand = auts_rand;
-	return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
-}
-
-int gprs_subscr_location_update(struct gprs_subscr *subscr)
-{
-	struct osmo_gsup_message gsup_msg = {0};
-
-	LOGGSUBSCRP(LOGL_INFO, subscr,
-		"subscriber data is not available\n");
-
-	gsup_msg.message_type = OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST;
-	return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
-}
-
-void gprs_subscr_update(struct gprs_subscr *subscr)
-{
-	LOGGSUBSCRP(LOGL_DEBUG, subscr, "Updating subscriber data\n");
-
-	subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
-	subscr->flags &= ~GPRS_SUBSCRIBER_FIRST_CONTACT;
-
-	if (subscr->sgsn_data->mm)
-		sgsn_update_subscriber_data(subscr->sgsn_data->mm);
-}
-
-void gprs_subscr_update_auth_info(struct gprs_subscr *subscr)
-{
-	LOGGSUBSCRP(LOGL_DEBUG, subscr,
-		"Updating subscriber authentication info\n");
-
-	subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
-	subscr->flags &= ~GPRS_SUBSCRIBER_FIRST_CONTACT;
-
-	if (subscr->sgsn_data->mm)
-		sgsn_update_subscriber_data(subscr->sgsn_data->mm);
-}
-
-struct gprs_subscr *gprs_subscr_get_or_create_by_mmctx(struct sgsn_mm_ctx *mmctx)
-{
-	struct gprs_subscr *subscr = NULL;
-
-	if (mmctx->subscr)
-		return gprs_subscr_get(mmctx->subscr);
-
-	if (mmctx->imsi[0])
-		subscr = gprs_subscr_get_by_imsi(mmctx->imsi);
-
-	if (!subscr) {
-		subscr = gprs_subscr_get_or_create(mmctx->imsi);
-		subscr->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
-		subscr->flags &= ~GPRS_SUBSCRIBER_ENABLE_PURGE;
-	}
-
-	osmo_strlcpy(subscr->imei, mmctx->imei, sizeof(subscr->imei));
-
-	if (subscr->lac != mmctx->ra.lac)
-		subscr->lac = mmctx->ra.lac;
-
-	subscr->sgsn_data->mm = mmctx;
-	mmctx->subscr = gprs_subscr_get(subscr);
-
-	return subscr;
-}
-
-int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx)
-{
-	struct gprs_subscr *subscr = NULL;
-	int rc;
-
-	LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber data update\n");
-
-	subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
-
-	subscr->flags |= GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
-
-	rc = gprs_subscr_location_update(subscr);
-	gprs_subscr_put(subscr);
-	return rc;
-}
-
-/*! \brief Send Update Auth Info request via GSUP, with or without resync.
- *  \param[in] mmctx  MM context to request authentication tuples for.
- *  \param[in] auts  14 octet AUTS token for UMTS resync, or NULL.
- *  \param[in] auts_rand  16 octet Random token for UMTS resync, or NULL.
- * In case of normal Authentication Info request, both \a auts and \a auts_rand
- * must be NULL. For resync, both must be non-NULL.
- */
-int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx,
-				  const uint8_t *auts,
-				  const uint8_t *auts_rand)
-{
-	struct gprs_subscr *subscr = NULL;
-	int rc;
-
-	LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber authentication info\n");
-
-	subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
-
-	subscr->flags |= GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
-
-	rc = gprs_subscr_query_auth_info(subscr, auts, auts_rand);
-	gprs_subscr_put(subscr);
-	return rc;
-}
-
-static void gprs_subscr_free(struct gprs_subscr *gsub)
-{
-	llist_del(&gsub->entry);
-	talloc_free(gsub);
-}
-
-struct gprs_subscr *_gprs_subscr_get(struct gprs_subscr *gsub,
-				     const char *file, int line)
-{
-	OSMO_ASSERT(gsub->use_count < INT_MAX);
-	gsub->use_count++;
-	LOGPSRC(DREF, LOGL_DEBUG, file, line,
-		"subscr %s usage increases to: %d\n",
-		gsub->imsi, gsub->use_count);
-	return gsub;
-}
-
-struct gprs_subscr *_gprs_subscr_put(struct gprs_subscr *gsub,
-				     const char *file, int line)
-{
-	gsub->use_count--;
-	LOGPSRC(DREF, gsub->use_count >= 0? LOGL_DEBUG : LOGL_ERROR,
-		file, line,
-		"subscr %s usage decreases to: %d%s\n",
-		gsub->imsi, gsub->use_count,
-		gsub->keep_in_ram? ", keep-in-ram flag is set" : "");
-	if (gsub->use_count > 0)
-		return gsub;
-	if (gsub->keep_in_ram)
-		return gsub;
-	gprs_subscr_free(gsub);
-	return NULL;
-}
diff --git a/src/gprs/gprs_utils.c b/src/gprs/gprs_utils.c
deleted file mode 100644
index 91a09d2..0000000
--- a/src/gprs/gprs_utils.c
+++ /dev/null
@@ -1,246 +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/>.
- *
- */
-#include <openbsc/gprs_utils.h>
-
-#include <osmocom/core/msgb.h>
-#include <osmocom/gprs/gprs_ns.h>
-
-#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
-#include <osmocom/gsm/protocol/gsm_04_08.h>
-#include <osmocom/gsm/gsm48.h>
-
-#include <string.h>
-
-/* FIXME: this needs to go to libosmocore/msgb.c */
-struct msgb *gprs_msgb_copy(const struct msgb *msg, const char *name)
-{
-	struct libgb_msgb_cb *old_cb, *new_cb;
-	struct msgb *new_msg;
-
-	new_msg = msgb_alloc(msg->data_len, name);
-	if (!new_msg)
-		return NULL;
-
-	/* copy data */
-	memcpy(new_msg->_data, msg->_data, new_msg->data_len);
-
-	/* copy header */
-	new_msg->len = msg->len;
-	new_msg->data += msg->data - msg->_data;
-	new_msg->head += msg->head - msg->_data;
-	new_msg->tail += msg->tail - msg->_data;
-
-	if (msg->l1h)
-		new_msg->l1h = new_msg->_data + (msg->l1h - msg->_data);
-	if (msg->l2h)
-		new_msg->l2h = new_msg->_data + (msg->l2h - msg->_data);
-	if (msg->l3h)
-		new_msg->l3h = new_msg->_data + (msg->l3h - msg->_data);
-	if (msg->l4h)
-		new_msg->l4h = new_msg->_data + (msg->l4h - msg->_data);
-
-	/* copy GB specific data */
-	old_cb = LIBGB_MSGB_CB(msg);
-	new_cb = LIBGB_MSGB_CB(new_msg);
-
-	if (old_cb->bssgph)
-		new_cb->bssgph = new_msg->_data + (old_cb->bssgph - msg->_data);
-	if (old_cb->llch)
-		new_cb->llch = new_msg->_data + (old_cb->llch - msg->_data);
-
-	/* bssgp_cell_id is a pointer into the old msgb, so we need to make
-	 * it a pointer into the new msgb */
-	if (old_cb->bssgp_cell_id)
-		new_cb->bssgp_cell_id = new_msg->_data +
-			(old_cb->bssgp_cell_id - msg->_data);
-	new_cb->nsei = old_cb->nsei;
-	new_cb->bvci = old_cb->bvci;
-	new_cb->tlli = old_cb->tlli;
-
-	return new_msg;
-}
-
-/* TODO: Move this to libosmocore/msgb.c */
-int gprs_msgb_resize_area(struct msgb *msg, uint8_t *area,
-			    size_t old_size, size_t new_size)
-{
-	int rc;
-	uint8_t *rest = area + old_size;
-	int rest_len = msg->len - old_size - (area - msg->data);
-	int delta_size = (int)new_size - (int)old_size;
-
-	if (delta_size == 0)
-		return 0;
-
-	if (delta_size > 0) {
-		rc = msgb_trim(msg, msg->len + delta_size);
-		if (rc < 0)
-			return rc;
-	}
-
-	memmove(area + new_size, area + old_size, rest_len);
-
-	if (msg->l1h >= rest)
-		msg->l1h += delta_size;
-	if (msg->l2h >= rest)
-		msg->l2h += delta_size;
-	if (msg->l3h >= rest)
-		msg->l3h += delta_size;
-	if (msg->l4h >= rest)
-		msg->l4h += delta_size;
-
-	if (delta_size < 0)
-		msgb_trim(msg, msg->len + delta_size);
-
-	return 0;
-}
-
-int gprs_str_to_apn(uint8_t *apn_enc, size_t max_len, const char *str)
-{
-	uint8_t *last_len_field;
-	int len;
-
-	/* Can we even write the length field to the output? */
-	if (max_len == 0)
-		return -1;
-
-	/* Remember where we need to put the length once we know it */
-	last_len_field = apn_enc;
-	len = 1;
-	apn_enc += 1;
-
-	while (str[0]) {
-		if (len >= max_len)
-			return -1;
-
-		if (str[0] == '.') {
-			*last_len_field = (apn_enc - last_len_field) - 1;
-			last_len_field = apn_enc;
-		} else {
-			*apn_enc = str[0];
-		}
-		apn_enc += 1;
-		str += 1;
-		len += 1;
-	}
-
-	*last_len_field = (apn_enc - last_len_field) - 1;
-
-	return len;
-}
-
-/* GSM 04.08, 10.5.7.3 GPRS Timer */
-int gprs_tmr_to_secs(uint8_t tmr)
-{
-	switch (tmr & GPRS_TMR_UNIT_MASK) {
-	case GPRS_TMR_2SECONDS:
-		return 2 * (tmr & GPRS_TMR_FACT_MASK);
-	default:
-	case GPRS_TMR_MINUTE:
-		return 60 * (tmr & GPRS_TMR_FACT_MASK);
-	case GPRS_TMR_6MINUTE:
-		return 360 * (tmr & GPRS_TMR_FACT_MASK);
-	case GPRS_TMR_DEACTIVATED:
-		return -1;
-	}
-}
-
-/* This functions returns a tmr value such that
- *   - f is monotonic
- *   - f(s) <= s
- *   - f(s) == s if a tmr exists with s = gprs_tmr_to_secs(tmr)
- *   - the best possible resolution is used
- * where
- *   f(s) = gprs_tmr_to_secs(gprs_secs_to_tmr_floor(s))
- */
-uint8_t gprs_secs_to_tmr_floor(int secs)
-{
-	if (secs < 0)
-		return GPRS_TMR_DEACTIVATED;
-	if (secs < 2 * 32)
-		return GPRS_TMR_2SECONDS | (secs / 2);
-	if (secs < 60 * 2)
-		/* Ensure monotonicity */
-		return GPRS_TMR_2SECONDS | GPRS_TMR_FACT_MASK;
-	if (secs < 60 * 32)
-		return GPRS_TMR_MINUTE | (secs / 60);
-	if (secs < 360 * 6)
-		/* Ensure monotonicity */
-		return GPRS_TMR_MINUTE | GPRS_TMR_FACT_MASK;
-	if (secs < 360 * 32)
-		return GPRS_TMR_6MINUTE | (secs / 360);
-
-	return GPRS_TMR_6MINUTE | GPRS_TMR_FACT_MASK;
-}
-
-/* GSM 04.08, 10.5.1.4 */
-int gprs_is_mi_tmsi(const uint8_t *value, size_t value_len)
-{
-	if (value_len != GSM48_TMSI_LEN)
-		return 0;
-
-	if (!value || (value[0] & GSM_MI_TYPE_MASK) != GSM_MI_TYPE_TMSI)
-		return 0;
-
-	return 1;
-}
-
-/* GSM 04.08, 10.5.1.4 */
-int gprs_is_mi_imsi(const uint8_t *value, size_t value_len)
-{
-	if (value_len == 0)
-		return 0;
-
-	if (!value || (value[0] & GSM_MI_TYPE_MASK) != GSM_MI_TYPE_IMSI)
-		return 0;
-
-	return 1;
-}
-
-int gprs_parse_mi_tmsi(const uint8_t *value, size_t value_len, uint32_t *tmsi)
-{
-	uint32_t tmsi_be;
-
-	if (!gprs_is_mi_tmsi(value, value_len))
-		return 0;
-
-	memcpy(&tmsi_be, value + 1, sizeof(tmsi_be));
-
-	*tmsi = ntohl(tmsi_be);
-	return 1;
-}
-
-void gprs_parse_tmsi(const uint8_t *value, uint32_t *tmsi)
-{
-	uint32_t tmsi_be;
-
-	memcpy(&tmsi_be, value, sizeof(tmsi_be));
-
-	*tmsi = ntohl(tmsi_be);
-}
-
-int gprs_ra_id_equals(const struct gprs_ra_id *id1,
-			const struct gprs_ra_id *id2)
-{
-	return (id1->mcc == id2->mcc && id1->mnc == id2->mnc &&
-		id1->lac == id2->lac && id1->rac == id2->rac);
-}
diff --git a/src/gprs/gtphub.c b/src/gprs/gtphub.c
deleted file mode 100644
index 0a8e375..0000000
--- a/src/gprs/gtphub.c
+++ /dev/null
@@ -1,2937 +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/>.
- */
-
-#include <string.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <time.h>
-#include <limits.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <gtp.h>
-#include <gtpie.h>
-
-#include <openbsc/gtphub.h>
-#include <openbsc/debug.h>
-#include <openbsc/gprs_utils.h>
-
-#include <osmocom/core/utils.h>
-#include <osmocom/core/logging.h>
-#include <osmocom/core/socket.h>
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/core/stats.h>
-
-#include <osmocom/gsm/apn.h>
-
-
-static const int GTPH_GC_TICK_SECONDS = 1;
-
-void *osmo_gtphub_ctx;
-
-/* Convenience makro, note: only within this C file. */
-#define LOG(level, fmt, args...) \
-	LOGP(DGTPHUB, level, fmt, ##args)
-
-#define ZERO_STRUCT(struct_pointer) memset(struct_pointer, '\0', \
-					   sizeof(*(struct_pointer)))
-
-/* TODO move this to osmocom/core/select.h ? */
-typedef int (*osmo_fd_cb_t)(struct osmo_fd *fd, unsigned int what);
-
-/* TODO move this to osmocom/core/linuxlist.h ? */
-#define __llist_first(head) (((head)->next == (head)) ? NULL : (head)->next)
-#define llist_first(head, type, entry) \
-	llist_entry(__llist_first(head), type, entry)
-
-#define __llist_last(head) (((head)->next == (head)) ? NULL : (head)->prev)
-#define llist_last(head, type, entry) \
-	llist_entry(__llist_last(head), type, entry)
-
-/* TODO move GTP header stuff to openggsn/gtp/ ? See gtp_decaps*() */
-
-enum gtp_rc {
-	GTP_RC_UNKNOWN = 0,
-	GTP_RC_TINY = 1,    /* no IEs (like ping/pong) */
-	GTP_RC_PDU_C = 2,     /* a real packet with IEs */
-	GTP_RC_PDU_U = 3,     /* a real packet with User data */
-
-	GTP_RC_TOOSHORT = -1,
-	GTP_RC_UNSUPPORTED_VERSION = -2,
-	GTP_RC_INVALID_IE = -3,
-};
-
-struct gtp_packet_desc {
-	union gtp_packet *data;
-	int data_len;
-	int header_len;
-	int version;
-	uint8_t type;
-	uint16_t seq;
-	uint32_t header_tei_rx;
-	uint32_t header_tei;
-	int rc; /* enum gtp_rc */
-	unsigned int plane_idx;
-	unsigned int side_idx;
-	struct gtphub_tunnel *tun;
-	time_t timestamp;
-	union gtpie_member *ie[GTPIE_SIZE];
-};
-
-struct pending_delete {
-	struct llist_head entry;
-	struct expiring_item expiry_entry;
-
-	struct gtphub_tunnel *tun;
-	uint8_t teardown_ind;
-	uint8_t nsapi;
-};
-
-
-/* counters */
-
-enum gtphub_counters_io {
-	GTPH_CTR_PKTS_IN = 0,
-	GTPH_CTR_PKTS_OUT,
-	GTPH_CTR_BYTES_IN,
-	GTPH_CTR_BYTES_OUT
-};
-
-static const struct rate_ctr_desc gtphub_counters_io_desc[] = {
-	{ "packets.in",  "Packets ( In)" },
-	{ "packets.out", "Packets (Out)" },
-	{ "bytes.in",    "Bytes   ( In)" },
-	{ "bytes.out",   "Bytes   (Out)" },
-};
-
-static const struct rate_ctr_group_desc gtphub_ctrg_io_desc = {
-	.group_name_prefix = "gtphub.bind",
-	.group_description = "I/O Statistics",
-	.num_ctr = ARRAY_SIZE(gtphub_counters_io_desc),
-	.ctr_desc = gtphub_counters_io_desc,
-	.class_id = OSMO_STATS_CLASS_GLOBAL,
-};
-
-
-/* support */
-
-static const char *gtp_type_str(uint8_t type)
-{
-	switch (type) {
-	case 1:
-		return " (Echo Request)";
-	case 2:
-		return " (Echo Response)";
-	case 16:
-		return " (Create PDP Ctx Request)";
-	case 17:
-		return " (Create PDP Ctx Response)";
-	case 18:
-		return " (Update PDP Ctx Request)";
-	case 19:
-		return " (Update PDP Ctx Response)";
-	case 20:
-		return " (Delete PDP Ctx Request)";
-	case 21:
-		return " (Delete PDP Ctx Response)";
-	case 255:
-		return " (User Data)";
-	default:
-		return "";
-	}
-}
-
-void gsn_addr_copy(struct gsn_addr *gsna, const struct gsn_addr *src)
-{
-	*gsna = *src;
-}
-
-int gsn_addr_from_sockaddr(struct gsn_addr *gsna, uint16_t *port,
-			   const struct osmo_sockaddr *sa)
-{
-	char addr_str[256];
-	char port_str[6];
-
-	if (osmo_sockaddr_to_strs(addr_str, sizeof(addr_str),
-				  port_str, sizeof(port_str),
-				  sa, (NI_NUMERICHOST | NI_NUMERICSERV))
-	    != 0) {
-		return -1;
-	}
-
-	if (port)
-		*port = atoi(port_str);
-
-	return gsn_addr_from_str(gsna, addr_str);
-}
-
-int gsn_addr_from_str(struct gsn_addr *gsna, const char *numeric_addr_str)
-{
-	if ((!gsna) || (!numeric_addr_str))
-		return -1;
-
-	int af = AF_INET;
-	gsna->len = 4;
-	const char *pos = numeric_addr_str;
-	for (; *pos; pos++) {
-		if (*pos == ':') {
-			af = AF_INET6;
-			gsna->len = 16;
-			break;
-		}
-	}
-
-	int rc = inet_pton(af, numeric_addr_str, gsna->buf);
-	if (rc != 1) {
-		LOG(LOGL_ERROR, "Cannot resolve numeric address: '%s'\n",
-		    numeric_addr_str);
-		return -1;
-	}
-	return 0;
-}
-
-const char *gsn_addr_to_str(const struct gsn_addr *gsna)
-{
-	static char buf[INET6_ADDRSTRLEN + 1];
-	return gsn_addr_to_strb(gsna, buf, sizeof(buf));
-}
-
-const char *gsn_addr_to_strb(const struct gsn_addr *gsna,
-			     char *strbuf,
-			     int strbuf_len)
-{
-	int af;
-	switch (gsna->len) {
-	case 4:
-		af = AF_INET;
-		break;
-	case 16:
-		af = AF_INET6;
-		break;
-	default:
-		return NULL;
-	}
-
-	const char *r = inet_ntop(af, gsna->buf, strbuf, strbuf_len);
-	if (!r) {
-		LOG(LOGL_ERROR, "Cannot convert gsn_addr to string:"
-		    " %s: len=%d, buf=%s\n",
-		    strerror(errno),
-		    (int)gsna->len,
-		    osmo_hexdump(gsna->buf, sizeof(gsna->buf)));
-	}
-	return r;
-}
-
-int gsn_addr_same(const struct gsn_addr *a, const struct gsn_addr *b)
-{
-	if (a == b)
-		return 1;
-	if ((!a) || (!b))
-		return 0;
-	if (a->len != b->len)
-		return 0;
-	return (memcmp(a->buf, b->buf, a->len) == 0)? 1 : 0;
-}
-
-static int gsn_addr_get(struct gsn_addr *gsna, const struct gtp_packet_desc *p,
-			int idx)
-{
-	if (p->rc != GTP_RC_PDU_C)
-		return -1;
-
-	unsigned int len;
-	/* gtpie.h fails to declare gtpie_gettlv()'s first arg as const. */
-	if (gtpie_gettlv((union gtpie_member**)p->ie, GTPIE_GSN_ADDR, idx,
-			 &len, gsna->buf, sizeof(gsna->buf))
-	    != 0)
-		return -1;
-	gsna->len = len;
-	return 0;
-}
-
-static int gsn_addr_put(const struct gsn_addr *gsna, struct gtp_packet_desc *p,
-			int idx)
-{
-	if (p->rc != GTP_RC_PDU_C)
-		return -1;
-
-	int ie_idx;
-	ie_idx = gtpie_getie(p->ie, GTPIE_GSN_ADDR, idx);
-
-	if (ie_idx < 0)
-		return -1;
-
-	struct gtpie_tlv *ie = &p->ie[ie_idx]->tlv;
-	int ie_l = ntoh16(ie->l);
-	if (ie_l != gsna->len) {
-		LOG(LOGL_ERROR, "Not implemented:"
-		    " replace an IE address of different size:"
-		    " replace %d with %d\n", (int)ie_l, (int)gsna->len);
-		return -1;
-	}
-
-	memcpy(ie->v, gsna->buf, (int)ie_l);
-	return 0;
-}
-
-/* Validate GTP version 0 data; analogous to validate_gtp1_header(), see there.
- */
-void validate_gtp0_header(struct gtp_packet_desc *p)
-{
-	const struct gtp0_header *pheader = &(p->data->gtp0.h);
-	p->rc = GTP_RC_UNKNOWN;
-	p->header_len = 0;
-
-	OSMO_ASSERT(p->data_len >= 1);
-	OSMO_ASSERT(p->version == 0);
-
-	if (p->data_len < GTP0_HEADER_SIZE) {
-		LOG(LOGL_ERROR, "GTP0 packet too short: %d\n", p->data_len);
-		p->rc = GTP_RC_TOOSHORT;
-		return;
-	}
-
-	p->type = ntoh8(pheader->type);
-	p->seq = ntoh16(pheader->seq);
-	p->header_tei_rx = 0; /* TODO */
-	p->header_tei = p->header_tei_rx;
-
-	if (p->data_len == GTP0_HEADER_SIZE) {
-		p->rc = GTP_RC_TINY;
-		p->header_len = GTP0_HEADER_SIZE;
-		return;
-	}
-
-	/* Check packet length field versus length of packet */
-	if (p->data_len != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
-		LOG(LOGL_ERROR, "GTP packet length field (%d + %d) does not"
-		    " match actual length (%d)\n",
-		    GTP0_HEADER_SIZE, (int)ntoh16(pheader->length),
-		    p->data_len);
-		p->rc = GTP_RC_TOOSHORT;
-		return;
-	}
-
-	LOG(LOGL_DEBUG, "GTP v0 TID = %" PRIu64 "\n", pheader->tid);
-	p->header_len = GTP0_HEADER_SIZE;
-	p->rc = GTP_RC_PDU_C;
-}
-
-/* Validate GTP version 1 data, and update p->rc with the result, as well as
- * p->header_len in case of a valid header. */
-void validate_gtp1_header(struct gtp_packet_desc *p)
-{
-	const struct gtp1_header_long *pheader = &(p->data->gtp1l.h);
-	p->rc = GTP_RC_UNKNOWN;
-	p->header_len = 0;
-
-	OSMO_ASSERT(p->data_len >= 1);
-	OSMO_ASSERT(p->version == 1);
-
-	if ((p->data_len < GTP1_HEADER_SIZE_LONG)
-	    && (p->data_len != GTP1_HEADER_SIZE_SHORT)){
-		LOG(LOGL_ERROR, "GTP packet too short: %d\n", p->data_len);
-		p->rc = GTP_RC_TOOSHORT;
-		return;
-	}
-
-	p->type = ntoh8(pheader->type);
-	p->header_tei_rx = ntoh32(pheader->tei);
-	p->header_tei = p->header_tei_rx;
-	p->seq = ntoh16(pheader->seq);
-
-	LOG(LOGL_DEBUG, "| GTPv1\n");
-	LOG(LOGL_DEBUG, "| type = %" PRIu8 " 0x%02" PRIx8 "\n", p->type, p->type);
-	LOG(LOGL_DEBUG, "| length = %" PRIu16 " 0x%04" PRIx16 "\n", ntoh16(pheader->length), ntoh16(pheader->length));
-	LOG(LOGL_DEBUG, "| TEI = %" PRIu32 " 0x%08" PRIx32 "\n", p->header_tei_rx, p->header_tei_rx);
-	LOG(LOGL_DEBUG, "| seq = %" PRIu16 " 0x%04" PRIx16 "\n", p->seq, p->seq);
-	LOG(LOGL_DEBUG, "| npdu = %" PRIu8 " 0x%02" PRIx8 "\n", pheader->npdu, pheader->npdu);
-	LOG(LOGL_DEBUG, "| next = %" PRIu8 " 0x%02" PRIx8 "\n", pheader->next, pheader->next);
-
-	if (p->data_len <= GTP1_HEADER_SIZE_LONG) {
-		p->rc = GTP_RC_TINY;
-		p->header_len = GTP1_HEADER_SIZE_SHORT;
-		return;
-	}
-
-	/* Check packet length field versus length of packet */
-	int announced_len = ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT;
-	if (p->data_len != announced_len) {
-		LOG(LOGL_ERROR, "GTP packet length field (%d + %d) does not"
-		    " match actual length (%d)\n",
-		    GTP1_HEADER_SIZE_SHORT, (int)ntoh16(pheader->length),
-		    p->data_len);
-		p->rc = GTP_RC_TOOSHORT;
-		return;
-	}
-
-	p->rc = GTP_RC_PDU_C;
-	p->header_len = GTP1_HEADER_SIZE_LONG;
-}
-
-/* Examine whether p->data of size p->data_len has a valid GTP header. Set
- * p->version, p->rc and p->header_len. On error, p->rc <= 0 (see enum
- * gtp_rc). p->data must point at a buffer with p->data_len set. */
-void validate_gtp_header(struct gtp_packet_desc *p)
-{
-	p->rc = GTP_RC_UNKNOWN;
-
-	/* Need at least 1 byte in order to check version */
-	if (p->data_len < 1) {
-		LOG(LOGL_ERROR, "Discarding packet - too small: %d\n",
-		    p->data_len);
-		p->rc = GTP_RC_TOOSHORT;
-		return;
-	}
-
-	p->version = p->data->flags >> 5;
-
-	switch (p->version) {
-	case 0:
-		validate_gtp0_header(p);
-		break;
-	case 1:
-		validate_gtp1_header(p);
-		break;
-	default:
-		LOG(LOGL_ERROR, "Unsupported GTP version: %d\n", p->version);
-		p->rc = GTP_RC_UNSUPPORTED_VERSION;
-		break;
-	}
-}
-
-
-/* Return the value of the i'th IMSI IEI by copying to *imsi.
- * The first IEI is reached by passing i = 0.
- * imsi must point at allocated space of (at least) 8 bytes.
- * Return 1 on success, or 0 if not found. */
-static int get_ie_imsi(union gtpie_member *ie[], int i, uint8_t *imsi)
-{
-	return gtpie_gettv0(ie, GTPIE_IMSI, i, imsi, 8) == 0;
-}
-
-/* Analogous to get_ie_imsi(). nsapi must point at a single uint8_t. */
-static int get_ie_nsapi(union gtpie_member *ie[], int i, uint8_t *nsapi)
-{
-	return gtpie_gettv1(ie, GTPIE_NSAPI, i, nsapi) == 0;
-}
-
-static char imsi_digit_to_char(uint8_t nibble)
-{
-	nibble &= 0x0f;
-	if (nibble > 9)
-		return (nibble == 0x0f) ? '\0' : '?';
-	return '0' + nibble;
-}
-
-/* Return a human readable IMSI string, in a static buffer.
- * imsi must point at 8 octets of IMSI IE encoded IMSI data. */
-static int imsi_to_str(uint8_t *imsi, const char **imsi_str)
-{
-	static char str[17];
-	int i;
-
-	for (i = 0; i < 8; i++) {
-		char c;
-		c = imsi_digit_to_char(imsi[i]);
-		if (c == '?')
-			return -1;
-		str[2*i] = c;
-
-		c = imsi_digit_to_char(imsi[i] >> 4);
-		if (c == '?')
-			return -1;
-		str[2*i + 1] = c;
-	}
-	str[16] = '\0';
-	*imsi_str = str;
-	return 1;
-}
-
-/* Return 0 if not present, 1 if present and decoded successfully, -1 if
- * present but cannot be decoded. */
-static int get_ie_imsi_str(union gtpie_member *ie[], int i,
-			   const char **imsi_str)
-{
-	uint8_t imsi_buf[8];
-	if (!get_ie_imsi(ie, i, imsi_buf))
-		return 0;
-	return imsi_to_str(imsi_buf, imsi_str);
-}
-
-/* Return 0 if not present, 1 if present and decoded successfully, -1 if
- * present but cannot be decoded. */
-static int get_ie_apn_str(union gtpie_member *ie[], const char **apn_str)
-{
-	static char apn_buf[GSM_APN_LENGTH];
-	unsigned int len;
-	if (gtpie_gettlv(ie, GTPIE_APN, 0,
-			 &len, apn_buf, sizeof(apn_buf)) != 0)
-		return 0;
-
-	if (len < 2) {
-		LOG(LOGL_ERROR, "APN IE: invalid length: %d\n",
-		    (int)len);
-		return -1;
-	}
-
-	if (len > (sizeof(apn_buf) - 1))
-		len = sizeof(apn_buf) - 1;
-	apn_buf[len] = '\0';
-
-	*apn_str = osmo_apn_to_str(apn_buf, (uint8_t*)apn_buf, len);
-	if (!(*apn_str)) {
-		LOG(LOGL_ERROR, "APN IE: present but cannot be decoded: %s\n",
-		    osmo_hexdump((uint8_t*)apn_buf, len));
-		return -1;
-	}
-	return 1;
-}
-
-
-/* Validate header, and index information elements. Write decoded packet
- * information to *res. res->data will point at the given data buffer. On
- * error, p->rc is set <= 0 (see enum gtp_rc). */
-static void gtp_decode(const uint8_t *data, int data_len,
-		       unsigned int from_side_idx,
-		       unsigned int from_plane_idx,
-		       struct gtp_packet_desc *res,
-		       time_t now)
-{
-	ZERO_STRUCT(res);
-	res->data = (union gtp_packet*)data;
-	res->data_len = data_len;
-	res->side_idx = from_side_idx;
-	res->plane_idx = from_plane_idx;
-	res->timestamp = now;
-
-	validate_gtp_header(res);
-
-	if (res->rc <= 0)
-		return;
-
-	LOG(LOGL_DEBUG, "Valid GTP header (v%d)\n", res->version);
-
-	if (from_plane_idx == GTPH_PLANE_USER) {
-		res->rc = GTP_RC_PDU_U;
-		return;
-	}
-
-	if (res->rc != GTP_RC_PDU_C) {
-		LOG(LOGL_DEBUG, "no IEs in this GTP packet\n");
-		return;
-	}
-
-	if (gtpie_decaps(res->ie, res->version,
-			 (void*)(data + res->header_len),
-			 res->data_len - res->header_len) != 0) {
-		res->rc = GTP_RC_INVALID_IE;
-		LOG(LOGL_ERROR, "INVALID: cannot decode IEs."
-		    " Dropping GTP packet%s.\n",
-		    gtp_type_str(res->type)
-		    );
-		return;
-	}
-
-#if 1
-	/* TODO if (<loglevel is debug>)
-	   (waiting for a commit from jerlbeck) */
-	int i;
-
-	for (i = 0; i < 10; i++) {
-		const char *imsi;
-		if (get_ie_imsi_str(res->ie, i, &imsi) < 1)
-			break;
-		LOG(LOGL_DEBUG, "| IMSI %s\n", imsi);
-	}
-
-	for (i = 0; i < 10; i++) {
-		uint8_t nsapi;
-		if (!get_ie_nsapi(res->ie, i, &nsapi))
-			break;
-		LOG(LOGL_DEBUG, "| NSAPI %d\n", (int)nsapi);
-	}
-
-	for (i = 0; i < 2; i++) {
-		struct gsn_addr addr;
-		if (gsn_addr_get(&addr, res, i) == 0)
-			LOG(LOGL_DEBUG, "| addr %s\n", gsn_addr_to_str(&addr));
-	}
-
-	for (i = 0; i < 10; i++) {
-		uint32_t tei;
-		if (gtpie_gettv4(res->ie, GTPIE_TEI_DI, i, &tei) != 0)
-			break;
-		LOG(LOGL_DEBUG, "| TEI DI (USER) %" PRIu32 " 0x%08" PRIx32 "\n",
-		    tei, tei);
-	}
-
-	for (i = 0; i < 10; i++) {
-		uint32_t tei;
-		if (gtpie_gettv4(res->ie, GTPIE_TEI_C, i, &tei) != 0)
-			break;
-		LOG(LOGL_DEBUG, "| TEI (CTRL) %" PRIu32 " 0x%08" PRIx32 "\n",
-		    tei, tei);
-	}
-#endif
-}
-
-
-/* expiry */
-
-void expiry_init(struct expiry *exq, int expiry_in_seconds)
-{
-	ZERO_STRUCT(exq);
-	exq->expiry_in_seconds = expiry_in_seconds;
-	INIT_LLIST_HEAD(&exq->items);
-}
-
-void expiry_add(struct expiry *exq, struct expiring_item *item, time_t now)
-{
-	item->expiry = now + exq->expiry_in_seconds;
-
-	OSMO_ASSERT(llist_empty(&exq->items)
-		    || (item->expiry
-			>= llist_last(&exq->items, struct expiring_item, entry)->expiry));
-
-	/* Add/move to the tail to always sort by expiry, ascending. */
-	llist_del(&item->entry);
-	llist_add_tail(&item->entry, &exq->items);
-}
-
-int expiry_tick(struct expiry *exq, time_t now)
-{
-	int expired = 0;
-	struct expiring_item *m, *n;
-	llist_for_each_entry_safe(m, n, &exq->items, entry) {
-		if (m->expiry <= now) {
-			expiring_item_del(m);
-			expired ++;
-		} else {
-			/* The items are added sorted by expiry. So when we hit
-			 * an unexpired entry, only more unexpired ones will
-			 * follow. */
-			break;
-		}
-	}
-	return expired;
-}
-
-void expiry_clear(struct expiry *exq)
-{
-	struct expiring_item *m, *n;
-	llist_for_each_entry_safe(m, n, &exq->items, entry) {
-		expiring_item_del(m);
-	}
-}
-
-void expiring_item_init(struct expiring_item *item)
-{
-	ZERO_STRUCT(item);
-	INIT_LLIST_HEAD(&item->entry);
-}
-
-void expiring_item_del(struct expiring_item *item)
-{
-	OSMO_ASSERT(item);
-	llist_del(&item->entry);
-	INIT_LLIST_HEAD(&item->entry);
-	if (item->del_cb) {
-		/* avoid loops */
-		del_cb_t del_cb = item->del_cb;
-		item->del_cb = 0;
-		(del_cb)(item);
-	}
-}
-
-
-/* nr_map, nr_pool */
-
-void nr_pool_init(struct nr_pool *pool, nr_t nr_min, nr_t nr_max)
-{
-	*pool = (struct nr_pool){
-		.nr_min = nr_min,
-		.nr_max = nr_max,
-		.last_nr = nr_max
-	};
-}
-
-nr_t nr_pool_next(struct nr_pool *pool)
-{
-	if (pool->last_nr >= pool->nr_max)
-		pool->last_nr = pool->nr_min;
-	else
-		pool->last_nr ++;
-
-	return pool->last_nr;
-}
-
-void nr_map_init(struct nr_map *map, struct nr_pool *pool,
-		 struct expiry *exq)
-{
-	ZERO_STRUCT(map);
-	map->pool = pool;
-	map->add_items_to_expiry = exq;
-	INIT_LLIST_HEAD(&map->mappings);
-}
-
-void nr_mapping_init(struct nr_mapping *m)
-{
-	ZERO_STRUCT(m);
-	INIT_LLIST_HEAD(&m->entry);
-	expiring_item_init(&m->expiry_entry);
-}
-
-void nr_map_add(struct nr_map *map, struct nr_mapping *mapping, time_t now)
-{
-	/* Generate a mapped number */
-	mapping->repl = nr_pool_next(map->pool);
-
-	/* Add to the tail to always yield a list sorted by expiry, in
-	 * ascending order. */
-	llist_add_tail(&mapping->entry, &map->mappings);
-	nr_map_refresh(map, mapping, now);
-}
-
-void nr_map_refresh(struct nr_map *map, struct nr_mapping *mapping, time_t now)
-{
-	if (!map->add_items_to_expiry)
-		return;
-	expiry_add(map->add_items_to_expiry,
-		   &mapping->expiry_entry,
-		   now);
-}
-
-void nr_map_clear(struct nr_map *map)
-{
-	struct nr_mapping *m;
-	struct nr_mapping *n;
-	llist_for_each_entry_safe(m, n, &map->mappings, entry) {
-		nr_mapping_del(m);
-	}
-}
-
-int nr_map_empty(const struct nr_map *map)
-{
-	return llist_empty(&map->mappings);
-}
-
-struct nr_mapping *nr_map_get(const struct nr_map *map,
-			      void *origin, nr_t nr_orig)
-{
-	struct nr_mapping *mapping;
-	llist_for_each_entry(mapping, &map->mappings, entry) {
-		if ((mapping->origin == origin)
-		    && (mapping->orig == nr_orig))
-			return mapping;
-	}
-	/* Not found. */
-	return NULL;
-}
-
-struct nr_mapping *nr_map_get_inv(const struct nr_map *map, nr_t nr_repl)
-{
-	struct nr_mapping *mapping;
-	llist_for_each_entry(mapping, &map->mappings, entry) {
-		if (mapping->repl == nr_repl) {
-			return mapping;
-		}
-	}
-	/* Not found. */
-	return NULL;
-}
-
-void nr_mapping_del(struct nr_mapping *mapping)
-{
-	OSMO_ASSERT(mapping);
-	llist_del(&mapping->entry);
-	INIT_LLIST_HEAD(&mapping->entry);
-	expiring_item_del(&mapping->expiry_entry);
-}
-
-
-/* gtphub */
-
-const char* const gtphub_plane_idx_names[GTPH_PLANE_N] = {
-	"CTRL",
-	"USER",
-};
-
-const uint16_t gtphub_plane_idx_default_port[GTPH_PLANE_N] = {
-	2123,
-	2152,
-};
-
-const char* const gtphub_side_idx_names[GTPH_SIDE_N] = {
-	"SGSN",
-	"GGSN",
-};
-
-time_t gtphub_now(void)
-{
-	struct timespec now_tp;
-	OSMO_ASSERT(clock_gettime(CLOCK_MONOTONIC, &now_tp) >= 0);
-	return now_tp.tv_sec;
-}
-
-/* Remove a gtphub_peer from its list and free it. */
-static void gtphub_peer_del(struct gtphub_peer *peer)
-{
-	OSMO_ASSERT(llist_empty(&peer->addresses));
-	nr_map_clear(&peer->seq_map);
-	llist_del(&peer->entry);
-	talloc_free(peer);
-}
-
-static void gtphub_peer_addr_del(struct gtphub_peer_addr *pa)
-{
-	OSMO_ASSERT(llist_empty(&pa->ports));
-	llist_del(&pa->entry);
-	talloc_free(pa);
-}
-
-static void gtphub_peer_port_del(struct gtphub_peer_port *pp)
-{
-	OSMO_ASSERT(pp->ref_count == 0);
-	llist_del(&pp->entry);
-	rate_ctr_group_free(pp->counters_io);
-	talloc_free(pp);
-}
-
-/* From the information in the gtp_packet_desc, return the address of a GGSN.
- * Return -1 on error. */
-static int gtphub_resolve_ggsn(struct gtphub *hub,
-			       struct gtp_packet_desc *p,
-			       struct gtphub_peer_port **pp);
-
-/* See gtphub_ext.c (wrapped by unit test) */
-struct gtphub_peer_port *gtphub_resolve_ggsn_addr(struct gtphub *hub,
-						  const char *imsi_str,
-						  const char *apn_ni_str);
-int gtphub_ares_init(struct gtphub *hub);
-
-static void gtphub_zero(struct gtphub *hub)
-{
-	ZERO_STRUCT(hub);
-	INIT_LLIST_HEAD(&hub->ggsn_lookups);
-	INIT_LLIST_HEAD(&hub->resolved_ggsns);
-}
-
-static int gtphub_sock_init(struct osmo_fd *ofd,
-			    const struct gtphub_cfg_addr *addr,
-			    osmo_fd_cb_t cb,
-			    void *data,
-			    int ofd_id)
-{
-	if (!addr->addr_str) {
-		LOG(LOGL_FATAL, "Cannot bind: empty address.\n");
-		return -1;
-	}
-	if (!addr->port) {
-		LOG(LOGL_FATAL, "Cannot bind: zero port not permitted.\n");
-		return -1;
-	}
-
-	ofd->when = BSC_FD_READ;
-	ofd->cb = cb;
-	ofd->data = data;
-	ofd->priv_nr = ofd_id;
-
-	int rc;
-	rc = osmo_sock_init_ofd(ofd,
-				AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP,
-				addr->addr_str, addr->port,
-				OSMO_SOCK_F_BIND);
-	if (rc < 1) {
-		LOG(LOGL_FATAL, "Cannot bind to %s port %d (rc %d)\n",
-		    addr->addr_str, (int)addr->port, rc);
-		return -1;
-	}
-
-	return 0;
-}
-
-static void gtphub_sock_close(struct osmo_fd *ofd)
-{
-	close(ofd->fd);
-	osmo_fd_unregister(ofd);
-	ofd->cb = NULL;
-}
-
-static void gtphub_bind_init(struct gtphub_bind *b)
-{
-	ZERO_STRUCT(b);
-
-	INIT_LLIST_HEAD(&b->peers);
-
-	b->counters_io = rate_ctr_group_alloc(osmo_gtphub_ctx,
-					      &gtphub_ctrg_io_desc, 0);
-	OSMO_ASSERT(b->counters_io);
-}
-
-static int gtphub_bind_start(struct gtphub_bind *b,
-			     const struct gtphub_cfg_bind *cfg,
-			     osmo_fd_cb_t cb, void *cb_data,
-			     unsigned int ofd_id)
-{
-	LOG(LOGL_DEBUG, "Starting bind %s\n", b->label);
-	if (gsn_addr_from_str(&b->local_addr, cfg->bind.addr_str) != 0) {
-		LOG(LOGL_FATAL, "Invalid bind address for %s: %s\n",
-		    b->label, cfg->bind.addr_str);
-		return -1;
-	}
-	if (gtphub_sock_init(&b->ofd, &cfg->bind, cb, cb_data, ofd_id) != 0) {
-		LOG(LOGL_FATAL, "Cannot bind for %s: %s\n",
-		    b->label, cfg->bind.addr_str);
-		return -1;
-	}
-	b->local_port = cfg->bind.port;
-	return 0;
-}
-
-static void gtphub_bind_free(struct gtphub_bind *b)
-{
-	OSMO_ASSERT(llist_empty(&b->peers));
-	rate_ctr_group_free(b->counters_io);
-}
-
-static void gtphub_bind_stop(struct gtphub_bind *b) {
-	gtphub_sock_close(&b->ofd);
-	gtphub_bind_free(b);
-}
-
-/* Recv datagram from from->fd, write sender's address to *from_addr.
- * Return the number of bytes read, zero on error. */
-static int gtphub_read(const struct osmo_fd *from,
-		       struct osmo_sockaddr *from_addr,
-		       uint8_t *buf, size_t buf_len)
-{
-	OSMO_ASSERT(from_addr);
-
-	/* recvfrom requires the available length set in *from_addr_len. */
-	from_addr->l = sizeof(from_addr->a);
-	errno = 0;
-	ssize_t received = recvfrom(from->fd, buf, buf_len, 0,
-				    (struct sockaddr*)&from_addr->a,
-				    &from_addr->l);
-	/* TODO use recvmsg and get a MSG_TRUNC flag to make sure the message
-	 * is not truncated. Then maybe reduce buf's size. */
-
-	if (received <= 0) {
-		LOG((errno == EAGAIN? LOGL_DEBUG : LOGL_ERROR),
-		    "error: %s\n", strerror(errno));
-		return 0;
-	}
-
-	LOG(LOGL_DEBUG, "Received %d bytes from %s: %s%s\n",
-	    (int)received, osmo_sockaddr_to_str(from_addr),
-	    osmo_hexdump(buf, received > 1000? 1000 : received),
-	    received > 1000 ? "..." : "");
-
-	return received;
-}
-
-static inline void gtphub_port_ref_count_inc(struct gtphub_peer_port *pp)
-{
-	OSMO_ASSERT(pp);
-	OSMO_ASSERT(pp->ref_count < UINT_MAX);
-	pp->ref_count++;
-}
-
-static inline void gtphub_port_ref_count_dec(struct gtphub_peer_port *pp)
-{
-	OSMO_ASSERT(pp);
-	OSMO_ASSERT(pp->ref_count > 0);
-	pp->ref_count--;
-}
-
-static inline void set_seq(struct gtp_packet_desc *p, uint16_t seq)
-{
-	OSMO_ASSERT(p->version == 1);
-	p->data->gtp1l.h.seq = hton16(seq);
-	p->seq = seq;
-}
-
-static inline void set_tei(struct gtp_packet_desc *p, uint32_t tei)
-{
-	OSMO_ASSERT(p->version == 1);
-	p->data->gtp1l.h.tei = hton32(tei);
-	p->header_tei = tei;
-}
-
-static void gtphub_mapping_del_cb(struct expiring_item *expi);
-
-static struct nr_mapping *gtphub_mapping_new()
-{
-	struct nr_mapping *nrm;
-	nrm = talloc_zero(osmo_gtphub_ctx, struct nr_mapping);
-	OSMO_ASSERT(nrm);
-
-	nr_mapping_init(nrm);
-	nrm->expiry_entry.del_cb = gtphub_mapping_del_cb;
-	return nrm;
-}
-
-
-#define APPEND(args...) \
-		l = snprintf(pos, left, args); \
-		pos += l; \
-		left -= l
-
-static const char *gtphub_tunnel_side_str(struct gtphub_tunnel *tun,
-					  int side_idx)
-{
-	static char buf[256];
-	char *pos = buf;
-	int left = sizeof(buf);
-	int l;
-	                 
-	struct gtphub_tunnel_endpoint *c, *u;
-	c = &tun->endpoint[side_idx][GTPH_PLANE_CTRL];
-	u = &tun->endpoint[side_idx][GTPH_PLANE_USER];
-
-	/* print both only if they differ. */
-	if (!c->peer) {
-		APPEND("(uninitialized)");
-	} else {
-		APPEND("%s", gsn_addr_to_str(&c->peer->peer_addr->addr));
-	}
-
-	if (!u->peer) {
-		if (c->peer) {
-			APPEND("/(uninitialized)");
-		}
-	} else if ((!c->peer)
-		   || (!gsn_addr_same(&u->peer->peer_addr->addr,
-				      &c->peer->peer_addr->addr))) {
-		APPEND("/%s", gsn_addr_to_str(&u->peer->peer_addr->addr));
-	}
-
-	APPEND(" (TEI C=%x U=%x)",
-	       c->tei_orig,
-	       u->tei_orig);
-	return buf;
-}
-
-const char *gtphub_tunnel_str(struct gtphub_tunnel *tun)
-{
-	static char buf[512];
-	char *pos = buf;
-	int left = sizeof(buf);
-	int l;
-
-	if (!tun)
-		return "null-tunnel";
-
-	APPEND("TEI=%x: ", tun->tei_repl);
-	APPEND("%s", gtphub_tunnel_side_str(tun, GTPH_SIDE_SGSN));
-	APPEND(" <-> %s", gtphub_tunnel_side_str(tun, GTPH_SIDE_GGSN));
-
-	return buf;
-}
-
-#undef APPEND
-
-void gtphub_tunnel_endpoint_set_peer(struct gtphub_tunnel_endpoint *te,
-				     struct gtphub_peer_port *pp)
-{
-	if (te->peer)
-		gtphub_port_ref_count_dec(te->peer);
-	te->peer = pp;
-	if (te->peer)
-		gtphub_port_ref_count_inc(te->peer);
-}
-
-int gtphub_tunnel_complete(struct gtphub_tunnel *tun)
-{
-	if (!tun)
-		return 0;
-	if (!tun->tei_repl)
-		return 0;
-	int side_idx;
-	int plane_idx;
-	for_each_side_and_plane(side_idx, plane_idx) {
-		struct gtphub_tunnel_endpoint *te =
-			&tun->endpoint[side_idx][plane_idx];
-		if (!(te->peer && te->tei_orig))
-			return 0;
-	}
-	return 1;
-}
-
-static void gtphub_tunnel_del_cb(struct expiring_item *expi)
-{
-	struct gtphub_tunnel *tun = container_of(expi,
-						 struct gtphub_tunnel,
-						 expiry_entry);
-	LOG(LOGL_DEBUG, "expired: %s\n", gtphub_tunnel_str(tun));
-
-	llist_del(&tun->entry);
-	INIT_LLIST_HEAD(&tun->entry); /* mark unused */
-
-	expi->del_cb = 0; /* avoid recursion loops */
-	expiring_item_del(&tun->expiry_entry); /* usually already done, but make sure. */
-
-	int side_idx;
-	int plane_idx;
-	for_each_side_and_plane(side_idx, plane_idx) {
-		struct gtphub_tunnel_endpoint *te = &tun->endpoint[side_idx][plane_idx];
-
-		/* clear ref count */
-		gtphub_tunnel_endpoint_set_peer(te, NULL);
-
-		rate_ctr_group_free(te->counters_io);
-	}
-
-	talloc_free(tun);
-}
-
-static struct gtphub_tunnel *gtphub_tunnel_new()
-{
-	struct gtphub_tunnel *tun;
-	tun = talloc_zero(osmo_gtphub_ctx, struct gtphub_tunnel);
-	OSMO_ASSERT(tun);
-
-	INIT_LLIST_HEAD(&tun->entry);
-	expiring_item_init(&tun->expiry_entry);
-
-	int side_idx, plane_idx;
-	for_each_side_and_plane(side_idx, plane_idx) {
-		struct gtphub_tunnel_endpoint *te = &tun->endpoint[side_idx][plane_idx];
-		te->counters_io = rate_ctr_group_alloc(osmo_gtphub_ctx,
-						       &gtphub_ctrg_io_desc,
-						       0);
-		OSMO_ASSERT(te->counters_io);
-	}
-
-	tun->expiry_entry.del_cb = gtphub_tunnel_del_cb;
-	return tun;
-}
-
-static const char *gtphub_peer_strb(struct gtphub_peer *peer, char *buf,
-				    int buflen)
-{
-	if (llist_empty(&peer->addresses))
-		return "(addressless)";
-
-	struct gtphub_peer_addr *a = llist_first(&peer->addresses,
-						 struct gtphub_peer_addr,
-						 entry);
-	return gsn_addr_to_strb(&a->addr, buf, buflen);
-}
-
-static const char *gtphub_port_strb(struct gtphub_peer_port *port, char *buf,
-				    int buflen)
-{
-	if (!port)
-		return "(null port)";
-
-	snprintf(buf, buflen, "%s port %d",
-		 gsn_addr_to_str(&port->peer_addr->addr),
-		 (int)port->port);
-	return buf;
-}
-
-const char *gtphub_peer_str(struct gtphub_peer *peer)
-{
-	static char buf[256];
-	return gtphub_peer_strb(peer, buf, sizeof(buf));
-}
-
-const char *gtphub_port_str(struct gtphub_peer_port *port)
-{
-	static char buf[256];
-	return gtphub_port_strb(port, buf, sizeof(buf));
-}
-
-static const char *gtphub_port_str2(struct gtphub_peer_port *port)
-{
-	static char buf[256];
-	return gtphub_port_strb(port, buf, sizeof(buf));
-}
-
-static void gtphub_mapping_del_cb(struct expiring_item *expi)
-{
-	expi->del_cb = 0; /* avoid recursion loops */
-	expiring_item_del(expi); /* usually already done, but make sure. */
-
-	struct nr_mapping *nrm = container_of(expi,
-					      struct nr_mapping,
-					      expiry_entry);
-	llist_del(&nrm->entry);
-	INIT_LLIST_HEAD(&nrm->entry); /* mark unused */
-
-	/* Just for log */
-	struct gtphub_peer_port *from = nrm->origin;
-	OSMO_ASSERT(from);
-	LOG(LOGL_DEBUG, "expired: %d: nr mapping from %s: %u->%u\n",
-	    (int)nrm->expiry_entry.expiry,
-	    gtphub_port_str(from),
-	    (unsigned int)nrm->orig, (unsigned int)nrm->repl);
-
-	gtphub_port_ref_count_dec(from);
-
-	talloc_free(nrm);
-}
-
-static struct nr_mapping *gtphub_mapping_have(struct nr_map *map,
-					      struct gtphub_peer_port *from,
-					      nr_t orig_nr,
-					      time_t now)
-{
-	struct nr_mapping *nrm;
-
-	nrm = nr_map_get(map, from, orig_nr);
-
-	if (!nrm) {
-		nrm = gtphub_mapping_new();
-		nrm->orig = orig_nr;
-		nrm->origin = from;
-		nr_map_add(map, nrm, now);
-		gtphub_port_ref_count_inc(from);
-		LOG(LOGL_DEBUG, "peer %s: sequence map %d --> %d\n",
-		    gtphub_port_str(from),
-		    (int)(nrm->orig), (int)(nrm->repl));
-	} else {
-		nr_map_refresh(map, nrm, now);
-	}
-
-	OSMO_ASSERT(nrm);
-	return nrm;
-}
-
-static void gtphub_map_seq(struct gtp_packet_desc *p,
-			   struct gtphub_peer_port *from_port,
-			   struct gtphub_peer_port *to_port)
-{
-	/* Store a mapping in to_peer's map, so when we later receive a GTP
-	 * packet back from to_peer, the seq nr can be unmapped back to its
-	 * origin (from_peer here). */
-	struct nr_mapping *nrm;
-	nrm = gtphub_mapping_have(&to_port->peer_addr->peer->seq_map,
-				  from_port, p->seq, p->timestamp);
-
-	/* Change the GTP packet to yield the new, mapped seq nr */
-	set_seq(p, nrm->repl);
-}
-
-static struct gtphub_peer_port *gtphub_unmap_seq(struct gtp_packet_desc *p,
-						 struct gtphub_peer_port *responding_port)
-{
-	OSMO_ASSERT(p->version == 1);
-	struct nr_mapping *nrm =
-		nr_map_get_inv(&responding_port->peer_addr->peer->seq_map,
-			       p->seq);
-	if (!nrm)
-		return NULL;
-	LOG(LOGL_DEBUG, "peer %p: sequence unmap %d <-- %d\n",
-	    nrm->origin, (int)(nrm->orig), (int)(nrm->repl));
-	set_seq(p, nrm->orig);
-	return nrm->origin;
-}
-
-static int gtphub_check_mapped_tei(struct gtphub_tunnel *new_tun,
-				   struct gtphub_tunnel *iterated_tun,
-				   uint32_t *tei_min,
-				   uint32_t *tei_max)
-{
-	if (!new_tun->tei_repl || !iterated_tun->tei_repl)
-		return 1;
-
-	*tei_min = (*tei_min < iterated_tun->tei_repl)? *tei_min : iterated_tun->tei_repl;
-	*tei_max = (*tei_max > iterated_tun->tei_repl)? *tei_max : iterated_tun->tei_repl;
-
-	if (new_tun->tei_repl != iterated_tun->tei_repl)
-		return 1;
-
-	/* new_tun->tei_repl is already taken. Try to find one out of the known
-	 * range. */
-	LOG(LOGL_DEBUG, "TEI replacement %d already taken.\n", new_tun->tei_repl);
-
-	if ((*tei_max) < 0xffffffff) {
-		(*tei_max)++;
-		new_tun->tei_repl = *tei_max;
-		LOG(LOGL_DEBUG, "Using TEI %d instead.\n", new_tun->tei_repl);
-		return 1;
-	} else if ((*tei_min) > 1) {
-		(*tei_min)--;
-		new_tun->tei_repl = *tei_min;
-		LOG(LOGL_DEBUG, "Using TEI %d instead.\n", new_tun->tei_repl);
-		return 1;
-	}
-
-	/* None seems to be available. */
-	return 0;
-}
-
-static int gtphub_check_reused_teis(struct gtphub *hub,
-				    struct gtphub_tunnel *new_tun)
-{
-	uint32_t tei_min = 0xffffffff;
-	uint32_t tei_max = 0;
-	int side_idx;
-	int plane_idx;
-	struct gtphub_tunnel_endpoint *te;
-	struct gtphub_tunnel_endpoint *te2;
-
-	struct gtphub_tunnel *tun, *ntun;
-
-	llist_for_each_entry_safe(tun, ntun, &hub->tunnels, entry) {
-		if (tun == new_tun)
-			continue;
-
-		/* Check whether the GSN sent a TEI that it is reusing from a
-		 * previous tunnel. */
-		int tun_continue = 0;
-		for_each_side(side_idx) {
-			for_each_plane(plane_idx) {
-				te = &tun->endpoint[side_idx][plane_idx];
-				te2 = &new_tun->endpoint[side_idx][plane_idx];
-				if ((te->tei_orig == 0)
-				    || (te->tei_orig != te2->tei_orig)
-				    || (!te->peer)
-				    || (!te2->peer)
-				    || !gsn_addr_same(&te->peer->peer_addr->addr,
-						      &te2->peer->peer_addr->addr))
-					continue;
-
-				/* The peer is reusing a TEI that I believe to
-				 * be part of another tunnel. The other tunnel
-				 * must be stale, then. */
-				LOG(LOGL_NOTICE,
-				    "Expiring tunnel due to reused TEI:"
-				    " %s peer %s sent %s TEI %x,"
-				    " previously used by tunnel %s...\n",
-				    gtphub_side_idx_names[side_idx],
-				    gtphub_port_str(te->peer),
-				    gtphub_plane_idx_names[plane_idx],
-				    te->tei_orig,
-				    gtphub_tunnel_str(tun));
-				LOG(LOGL_NOTICE, "...while establishing tunnel %s\n",
-				    gtphub_tunnel_str(new_tun));
-
-				expiring_item_del(&tun->expiry_entry);
-				/* continue to find more matches. There shouldn't be
-				 * any, but let's make sure. However, tun is deleted,
-				 * so we need to skip to the next tunnel. */
-				tun_continue = 1;
-				break;
-			}
-			if (tun_continue)
-				break;
-		}
-		if (tun_continue)
-			continue;
-
-		/* Check whether the mapped TEI is already used by another
-		 * tunnel. */
-		if (!gtphub_check_mapped_tei(new_tun, tun, &tei_min, &tei_max)) {
-			LOG(LOGL_ERROR,
-			    "No mapped TEI is readily available."
-			    " Searching for holes between occupied"
-			    " TEIs not implemented.");
-			return 0;
-		}
-
-	}
-
-	return 1;
-}
-
-static void gtphub_tunnel_refresh(struct gtphub *hub,
-				  struct gtphub_tunnel *tun,
-				  time_t now)
-{
-	expiry_add(&hub->expire_slowly,
-		   &tun->expiry_entry,
-		   now);
-}
-
-static struct gtphub_tunnel_endpoint *gtphub_unmap_tei(struct gtphub *hub,
-						       struct gtp_packet_desc *p,
-						       struct gtphub_peer_port *from,
-						       struct gtphub_tunnel **unmapped_from_tun)
-{
-	OSMO_ASSERT(from);
-	int other_side = other_side_idx(p->side_idx);
-
-	struct gtphub_tunnel *tun;
-	llist_for_each_entry(tun, &hub->tunnels, entry) {
-		struct gtphub_tunnel_endpoint *te_from =
-			&tun->endpoint[p->side_idx][p->plane_idx];
-		struct gtphub_tunnel_endpoint *te_to =
-			&tun->endpoint[other_side][p->plane_idx];
-		if ((tun->tei_repl == p->header_tei_rx)
-		    && te_from->peer
-		    && gsn_addr_same(&te_from->peer->peer_addr->addr,
-				     &from->peer_addr->addr)) {
-			gtphub_tunnel_refresh(hub, tun, p->timestamp);
-			if (unmapped_from_tun)
-				*unmapped_from_tun = tun;
-			return te_to;
-		}
-	}
-
-	if (unmapped_from_tun)
-		*unmapped_from_tun = NULL;
-	return NULL;
-}
-
-static void gtphub_map_restart_counter(struct gtphub *hub,
-				       struct gtp_packet_desc *p)
-{
-	if (p->rc != GTP_RC_PDU_C)
-		return;
-
-	int ie_idx;
-	ie_idx = gtpie_getie(p->ie, GTPIE_RECOVERY, 0);
-	if (ie_idx < 0)
-		return;
-
-	/* Always send gtphub's own restart counter */
-	p->ie[ie_idx]->tv1.v = hton8(hub->restart_counter);
-}
-
-static int gtphub_unmap_header_tei(struct gtphub_peer_port **to_port_p,
-				   struct gtphub_tunnel **unmapped_from_tun,
-				   struct gtphub *hub,
-				   struct gtp_packet_desc *p,
-				   struct gtphub_peer_port *from_port)
-{
-	OSMO_ASSERT(p->version == 1);
-	*to_port_p = NULL;
-	if (unmapped_from_tun)
-		*unmapped_from_tun = NULL;
-
-	/* If the header's TEI is zero, no PDP context has been established
-	 * yet. If nonzero, a mapping should actually already exist for this
-	 * TEI, since it must have been announced in a PDP context creation. */
-	if (!p->header_tei_rx)
-		return 0;
-
-	/* to_peer has previously announced a TEI, which was stored and
-	 * mapped in a tunnel struct. */
-	struct gtphub_tunnel_endpoint *to;
-	to = gtphub_unmap_tei(hub, p, from_port, unmapped_from_tun);
-	if (!to) {
-		LOG(LOGL_ERROR, "Received unknown TEI %" PRIx32 " from %s\n",
-		    p->header_tei_rx, gtphub_port_str(from_port));
-		return -1;
-	}
-
-	if (unmapped_from_tun) {
-		OSMO_ASSERT(*unmapped_from_tun);
-		LOG(LOGL_DEBUG, "Unmapped TEI coming from: %s\n",
-		    gtphub_tunnel_str(*unmapped_from_tun));
-	}
-
-	uint32_t unmapped_tei = to->tei_orig;
-	set_tei(p, unmapped_tei);
-
-	/* May be NULL for an invalidated tunnel. */
-	*to_port_p = to->peer;
-
-	return 0;
-}
-
-static int gtphub_handle_create_pdp_ctx(struct gtphub *hub,
-					struct gtp_packet_desc *p,
-					struct gtphub_peer_port *from_ctrl,
-					struct gtphub_peer_port *to_ctrl)
-{
-	int plane_idx;
-
-	osmo_static_assert((GTPH_PLANE_CTRL == 0) && (GTPH_PLANE_USER == 1),
-			   plane_nrs_match_GSN_addr_IE_indices);
-
-	struct gtphub_tunnel *tun = p->tun;
-
-	if (p->type == GTP_CREATE_PDP_REQ) {
-		if (p->side_idx != GTPH_SIDE_SGSN) {
-			LOG(LOGL_ERROR, "Wrong side: Create PDP Context"
-			    " Request from the GGSN side: %s",
-			    gtphub_port_str(from_ctrl));
-			return -1;
-		}
-
-		if (tun) {
-			LOG(LOGL_ERROR, "Not implemented: Received"
-			    " Create PDP Context Request for an already"
-			    " established tunnel:"
-			    " from %s, tunnel %s\n",
-			    gtphub_port_str(from_ctrl),
-			    gtphub_tunnel_str(p->tun));
-			return -1;
-		}
-
-		/* A new tunnel. */
-		p->tun = tun = gtphub_tunnel_new();
-
-		/* Create TEI mapping */
-		tun->tei_repl = nr_pool_next(&hub->tei_pool);
-
-		llist_add(&tun->entry, &hub->tunnels);
-		gtphub_tunnel_refresh(hub, tun, p->timestamp);
-		/* The endpoint peers on this side (SGSN) will be set from IEs
-		 * below. Also set the GGSN Ctrl endpoint, for logging. */
-		gtphub_tunnel_endpoint_set_peer(&tun->endpoint[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL],
-						to_ctrl);
-	} else if (p->type == GTP_CREATE_PDP_RSP) {
-		if (p->side_idx != GTPH_SIDE_GGSN) {
-			LOG(LOGL_ERROR, "Wrong side: Create PDP Context"
-			    " Response from the SGSN side: %s",
-			    gtphub_port_str(from_ctrl));
-			return -1;
-		}
-
-		/* The tunnel should already have been resolved from the header
-		 * TEI and be available in tun (== p->tun). Just fill in the
-		 * GSN Addresses below.*/
-		OSMO_ASSERT(tun);
-		OSMO_ASSERT(tun->tei_repl == p->header_tei_rx);
-		OSMO_ASSERT(to_ctrl);
-	}
-
-	uint8_t ie_type[] = { GTPIE_TEI_C, GTPIE_TEI_DI };
-	int ie_mandatory = (p->type == GTP_CREATE_PDP_REQ);
-	unsigned int side_idx = p->side_idx;
-
-	for (plane_idx = 0; plane_idx < 2; plane_idx++) {
-		int rc;
-		struct gsn_addr use_addr;
-		uint16_t use_port;
-		uint32_t tei_from_ie;
-		int ie_idx;
-
-		/* Fetch GSN Address and TEI from IEs. As ensured by above
-		 * static asserts, plane_idx corresponds to the GSN Address IE
-		 * index (the first one = 0 = ctrl, second one = 1 = user). */
-		rc = gsn_addr_get(&use_addr, p, plane_idx);
-		if (rc) {
-			LOG(LOGL_ERROR, "Cannot read %s GSN Address IE\n",
-			    gtphub_plane_idx_names[plane_idx]);
-			return -1;
-		}
-		LOG(LOGL_DEBUG, "Read %s GSN addr %s (%d)\n",
-		    gtphub_plane_idx_names[plane_idx],
-		    gsn_addr_to_str(&use_addr),
-		    use_addr.len);
-
-		ie_idx = gtpie_getie(p->ie, ie_type[plane_idx], 0);
-		if (ie_idx < 0) {
-			if (ie_mandatory) {
-				LOG(LOGL_ERROR,
-				    "Create PDP Context message invalid:"
-				    " missing IE %d\n",
-				    (int)ie_type[plane_idx]);
-				return -1;
-			}
-			tei_from_ie = 0;
-		}
-		else
-			tei_from_ie = ntoh32(p->ie[ie_idx]->tv4.v);
-
-		/* Make sure an entry for this peer address with default port
-		 * exists.
-		 *
-		 * Exception: if sgsn_use_sender is set, instead use the
-		 * sender's address and port for Ctrl -- the User port is not
-		 * known until the first User packet arrives.
-		 *
-		 * Note: doing this here is just an optimization, because
-		 * gtphub_handle_buf() has code to replace the tunnel
-		 * endpoints' addresses with the sender (needed for User
-		 * plane). We could just ignore sgsn_use_sender here. But if we
-		 * set up a default port here and replace it in
-		 * gtphub_handle_buf(), we'd be creating a peer port just to
-		 * expire it right away. */
-		if (hub->sgsn_use_sender && (side_idx == GTPH_SIDE_SGSN)) {
-			gsn_addr_from_sockaddr(&use_addr, &use_port, &from_ctrl->sa);
-		} else {
-			use_port = gtphub_plane_idx_default_port[plane_idx];
-
-		}
-
-		struct gtphub_peer_port *peer_from_ie;
-		peer_from_ie = gtphub_port_have(hub,
-						&hub->to_gsns[side_idx][plane_idx],
-						&use_addr, use_port);
-
-		gtphub_tunnel_endpoint_set_peer(&tun->endpoint[side_idx][plane_idx],
-						peer_from_ie);
-
-		if (!tei_from_ie &&
-		    !tun->endpoint[side_idx][plane_idx].tei_orig) {
-			LOG(LOGL_ERROR,
-			    "Create PDP Context message omits %s TEI, but"
-			    " no TEI has been announced for this tunnel: %s\n",
-			    gtphub_plane_idx_names[plane_idx],
-			    gtphub_tunnel_str(tun));
-			return -1;
-		}
-
-		if (tei_from_ie) {
-			/* Replace TEI in GTP packet IE */
-			tun->endpoint[side_idx][plane_idx].tei_orig = tei_from_ie;
-			p->ie[ie_idx]->tv4.v = hton32(tun->tei_repl);
-
-			if (!gtphub_check_reused_teis(hub, tun)) {
-				/* It's highly unlikely that all TEIs are
-				 * taken. But the code looking for an unused
-				 * TEI is, at the time of writing this comment,
-				 * not able to find gaps in the TEI space. To
-				 * explicitly alert the user of this problem,
-				 * rather abort than carry on. */
-				LOG(LOGL_FATAL, "TEI range exhausted. Cannot create TEI mapping, aborting.\n");
-				abort();
-			}
-		}
-
-		/* Replace the GSN address to reflect gtphub. */
-		rc = gsn_addr_put(&hub->to_gsns[other_side_idx(side_idx)][plane_idx].local_addr,
-				  p, plane_idx);
-		if (rc) {
-			LOG(LOGL_ERROR, "Cannot write %s GSN Address IE\n",
-			    gtphub_plane_idx_names[plane_idx]);
-			return -1;
-		}
-	}
-
-	if (p->type == GTP_CREATE_PDP_REQ) {
-		LOG(LOGL_DEBUG, "New tunnel, first half: %s\n",
-		    gtphub_tunnel_str(tun));
-	} else if (p->type == GTP_CREATE_PDP_RSP) {
-		LOG(LOGL_DEBUG, "New tunnel: %s\n",
-		    gtphub_tunnel_str(tun));
-	}
-
-	return 0;
-}
-
-static void pending_delete_del_cb(struct expiring_item *expi)
-{
-	struct pending_delete *pd;
-	pd = container_of(expi, struct pending_delete, expiry_entry);
-
-	llist_del(&pd->entry);
-	INIT_LLIST_HEAD(&pd->entry);
-
-	pd->expiry_entry.del_cb = 0;
-	expiring_item_del(&pd->expiry_entry);
-
-	talloc_free(pd);
-}
-
-static struct pending_delete *pending_delete_new(void)
-{
-	struct pending_delete *pd = talloc_zero(osmo_gtphub_ctx, struct pending_delete);
-	INIT_LLIST_HEAD(&pd->entry);
-	expiring_item_init(&pd->expiry_entry);
-	pd->expiry_entry.del_cb = pending_delete_del_cb;
-	return pd;
-}
-
-static int gtphub_handle_delete_pdp_ctx(struct gtphub *hub,
-					struct gtp_packet_desc *p,
-					struct gtphub_peer_port *from_ctrl,
-					struct gtphub_peer_port *to_ctrl)
-{
-	struct gtphub_tunnel *known_tun = p->tun;
-
-	if (p->type == GTP_DELETE_PDP_REQ) {
-		if (!known_tun) {
-			LOG(LOGL_ERROR, "Cannot find tunnel for Delete PDP Context Request.\n");
-			return -1;
-		}
-
-		/* Store the Delete Request until a successful Response is seen. */
-		uint8_t teardown_ind;
-		uint8_t nsapi;
-
-		if (gtpie_gettv1(p->ie, GTPIE_TEARDOWN, 0, &teardown_ind) != 0) {
-			LOG(LOGL_ERROR, "Missing Teardown Ind IE in Delete PDP Context Request.\n");
-			return -1;
-		}
-
-		if (gtpie_gettv1(p->ie, GTPIE_NSAPI, 0, &nsapi) != 0) {
-			LOG(LOGL_ERROR, "Missing NSAPI IE in Delete PDP Context Request.\n");
-			return -1;
-		}
-
-		struct pending_delete *pd = NULL;
-
-		struct pending_delete *pdi = NULL;
-		llist_for_each_entry(pdi, &hub->pending_deletes, entry) {
-			if ((pdi->tun == known_tun)
-			    && (pdi->teardown_ind == teardown_ind)
-			    && (pdi->nsapi == nsapi)) {
-				pd = pdi;
-				break;
-			}
-		}
-
-		if (!pd) {
-			pd = pending_delete_new();
-			pd->tun = known_tun;
-			pd->teardown_ind = teardown_ind;
-			pd->nsapi = nsapi;
-
-			LOG(LOGL_DEBUG, "Tunnel delete pending: %s\n",
-			    gtphub_tunnel_str(known_tun));
-			llist_add(&pd->entry, &hub->pending_deletes);
-		}
-
-		/* Add or refresh timeout. */
-		expiry_add(&hub->expire_quickly, &pd->expiry_entry, p->timestamp);
-
-		/* If a pending_delete should expire before the response to
-		 * indicate success comes in, the responding peer will have the
-		 * tunnel deactivated, while the requesting peer gets no reply
-		 * and keeps the tunnel. The hope is that the requesting peer
-		 * will try again and get a useful response. */
-	} else if (p->type == GTP_DELETE_PDP_RSP) {
-		/* Find the Delete Request for this Response. */
-		struct pending_delete *pd = NULL;
-
-		struct pending_delete *pdi;
-		llist_for_each_entry(pdi, &hub->pending_deletes, entry) {
-			if (known_tun == pdi->tun) {
-				pd = pdi;
-				break;
-			}
-		}
-
-		if (!pd) {
-			LOG(LOGL_ERROR, "Delete PDP Context Response:"
-			    " Cannot find matching request.");
-			/* If we delete the tunnel now, anyone can send a
-			 * Delete response to kill tunnels at will. */
-			return -1;
-		}
-
-		/* TODO handle teardown_ind and nsapi */
-
-		expiring_item_del(&pd->expiry_entry);
-
-		uint8_t cause;
-		if (gtpie_gettv1(p->ie, GTPIE_CAUSE, 0, &cause) != 0) {
-			LOG(LOGL_ERROR, "Delete PDP Context Response:"
-			    " Missing Cause IE.");
-			/* If we delete the tunnel now, at least one of the
-			 * peers may still think it is active. */
-			return -1;
-		}
-
-		if (cause != GTPCAUSE_ACC_REQ) {
-			LOG(LOGL_NOTICE,
-			    "Delete PDP Context Response indicates failure;"
-			    "for %s\n",
-			    gtphub_tunnel_str(known_tun));
-			return -1;
-		}
-
-		LOG(LOGL_DEBUG, "Delete PDP Context: removing tunnel %s\n",
-		    gtphub_tunnel_str(known_tun));
-		p->tun = NULL;
-		expiring_item_del(&known_tun->expiry_entry);
-	}
-
-	return 0;
-}
-
-static int gtphub_handle_update_pdp_ctx(struct gtphub *hub,
-					struct gtp_packet_desc *p,
-					struct gtphub_peer_port *from_ctrl,
-					struct gtphub_peer_port *to_ctrl)
-{
-	/* TODO */
-	return 0;
-}
-
-/* Read GSN address IEs from p, and make sure these peer addresses exist in
- * bind[plane_idx] with default ports, in their respective planes (both Ctrl
- * and User). Map TEIs announced in IEs, and write mapped TEIs in-place into
- * the packet p. */
-static int gtphub_handle_pdp_ctx(struct gtphub *hub,
-				 struct gtp_packet_desc *p,
-				 struct gtphub_peer_port *from_ctrl,
-				 struct gtphub_peer_port *to_ctrl)
-{
-	OSMO_ASSERT(p->plane_idx == GTPH_PLANE_CTRL);
-
-	switch (p->type) {
-	case GTP_CREATE_PDP_REQ:
-	case GTP_CREATE_PDP_RSP:
-		return gtphub_handle_create_pdp_ctx(hub, p,
-						    from_ctrl, to_ctrl);
-
-	case GTP_DELETE_PDP_REQ:
-	case GTP_DELETE_PDP_RSP:
-		return gtphub_handle_delete_pdp_ctx(hub, p,
-						    from_ctrl, to_ctrl);
-
-	case GTP_UPDATE_PDP_REQ:
-	case GTP_UPDATE_PDP_RSP:
-		return gtphub_handle_update_pdp_ctx(hub, p,
-						    from_ctrl, to_ctrl);
-
-	default:
-		/* Nothing to do for this message type. */
-		return 0;
-	}
-
-}
-
-static int gtphub_send_del_pdp_ctx(struct gtphub *hub,
-				   struct gtphub_tunnel *tun,
-				   int to_side)
-{
-	static uint8_t del_ctx_msg[16] = {
-		0x32,	/* GTP v1 flags */
-		GTP_DELETE_PDP_REQ,
-		0x00, 0x08, /* Length in network byte order */
-		0x00, 0x00, 0x00, 0x00,	/* TEI to be replaced */
-		0, 0,	/* Seq, to be replaced */
-		0, 0,	/* no extensions */
-		0x13, 0xff,  /* 19: Teardown ind = 1 */
-		0x14, 0	/* 20: NSAPI = 0 */
-	};
-
-	uint32_t *tei = (uint32_t*)&del_ctx_msg[4];
-	uint16_t *seq = (uint16_t*)&del_ctx_msg[8];
-
-	struct gtphub_tunnel_endpoint *te =
-		&tun->endpoint[to_side][GTPH_PLANE_CTRL];
-
-	if (! te->peer)
-		return 0;
-
-	*tei = hton32(te->tei_orig);
-	*seq = hton16(nr_pool_next(&te->peer->peer_addr->peer->seq_pool));
-
-	struct gtphub_bind *to_bind = &hub->to_gsns[to_side][GTPH_PLANE_CTRL];
-	int rc = gtphub_write(&to_bind->ofd, &te->peer->sa,
-			      del_ctx_msg, sizeof(del_ctx_msg));
-	if (rc != 0) {
-		LOG(LOGL_ERROR,
-		    "Failed to send out-of-band Delete PDP Context Request to %s\n",
-		    gtphub_port_str(te->peer));
-	}
-	return rc;
-}
-
-/* Tell all peers on the other end of tunnels that PDP contexts are void. */
-static void gtphub_restarted(struct gtphub *hub,
-			     struct gtp_packet_desc *p,
-			     struct gtphub_peer_port *pp)
-{
-	LOG(LOGL_NOTICE, "Peer has restarted: %s\n",
-	    gtphub_port_str(pp));
-
-	int deleted_count = 0;
-	struct gtphub_tunnel *tun;
-	llist_for_each_entry(tun, &hub->tunnels, entry) {
-		int side_idx;
-		for_each_side(side_idx) {
-			struct gtphub_tunnel_endpoint *te = &tun->endpoint[side_idx][GTPH_PLANE_CTRL];
-			struct gtphub_tunnel_endpoint *te2 = &tun->endpoint[other_side_idx(side_idx)][GTPH_PLANE_CTRL];
-			if ((!te->peer)
-			    || (!te2->tei_orig)
-			    || (pp->peer_addr->peer != te->peer->peer_addr->peer))
-				continue;
-
-			LOG(LOGL_DEBUG, "Deleting tunnel due to peer restart: %s\n",
-			    gtphub_tunnel_str(tun));
-			deleted_count ++;
-
-			/* Send a Delete PDP Context Request to the
-			 * peer on the other side, remember the pending
-			 * delete and wait for the response to delete
-			 * the tunnel. Clear this side of the tunnel to
-			 * make sure it isn't used.
-			 *
-			 * Should the delete message send fail, or if no
-			 * response is received, this tunnel will expire. If
-			 * its TEIs come up in a new PDP Context Request, it
-			 * will be removed. If messages for this tunnel should
-			 * come in (from the not restarted side), they will be
-			 * dropped because the tunnel is rendered unusable. */
-			gtphub_send_del_pdp_ctx(hub, tun, other_side_idx(side_idx));
-
-			gtphub_tunnel_endpoint_set_peer(&tun->endpoint[side_idx][GTPH_PLANE_CTRL],
-							NULL);
-			gtphub_tunnel_endpoint_set_peer(&tun->endpoint[side_idx][GTPH_PLANE_USER],
-							NULL);
-		}
-	}
-
-	if (deleted_count)
-		LOG(LOGL_NOTICE, "Deleting %d tunnels due to restart of: %s\n",
-		    deleted_count,
-		    gtphub_port_str(pp));
-}
-
-static int get_restart_count(struct gtp_packet_desc *p)
-{
-	int ie_idx;
-	ie_idx = gtpie_getie(p->ie, GTPIE_RECOVERY, 0);
-	if (ie_idx < 0)
-		return -1;
-	return ntoh8(p->ie[ie_idx]->tv1.v);
-}
-
-static void gtphub_check_restart_counter(struct gtphub *hub,
-					 struct gtp_packet_desc *p,
-					 struct gtphub_peer_port *from)
-{
-	/* If the peer is sending a Recovery IE (7.7.11) with a restart counter
-	 * that doesn't match the peer's previously sent restart counter, clear
-	 * that peer and cancel PDP contexts. */
-
-	int restart = get_restart_count(p);
-
-	if ((restart < 0) || (restart > 255))
-		return;
-
-	if ((from->last_restart_count >= 0) && (from->last_restart_count <= 255)) {
-		if (from->last_restart_count != restart) {
-			gtphub_restarted(hub, p, from);
-		}
-	}
-
-	from->last_restart_count = restart;
-}
-
-static int from_sgsns_read_cb(struct osmo_fd *from_sgsns_ofd, unsigned int what)
-{
-	unsigned int plane_idx = from_sgsns_ofd->priv_nr;
-	OSMO_ASSERT(plane_idx < GTPH_PLANE_N);
-	LOG(LOGL_DEBUG, "=== reading from SGSN (%s)\n",
-	    gtphub_plane_idx_names[plane_idx]);
-
-	if (!(what & BSC_FD_READ))
-		return 0;
-
-	struct gtphub *hub = from_sgsns_ofd->data;
-
-	static uint8_t buf[4096];
-	struct osmo_sockaddr from_addr;
-	struct osmo_sockaddr to_addr;
-	struct osmo_fd *to_ofd;
-	int len;
-	uint8_t *reply_buf;
-
-	len = gtphub_read(from_sgsns_ofd, &from_addr, buf, sizeof(buf));
-	if (len < 1)
-		return 0;
-
-	len = gtphub_handle_buf(hub, GTPH_SIDE_SGSN, plane_idx, &from_addr,
-				buf, len, gtphub_now(),
-				&reply_buf, &to_ofd, &to_addr);
-	if (len < 1)
-		return 0;
-
-	return gtphub_write(to_ofd, &to_addr, reply_buf, len);
-}
-
-static int from_ggsns_read_cb(struct osmo_fd *from_ggsns_ofd, unsigned int what)
-{
-	unsigned int plane_idx = from_ggsns_ofd->priv_nr;
-	OSMO_ASSERT(plane_idx < GTPH_PLANE_N);
-	LOG(LOGL_DEBUG, "=== reading from GGSN (%s)\n",
-	    gtphub_plane_idx_names[plane_idx]);
-	if (!(what & BSC_FD_READ))
-		return 0;
-
-	struct gtphub *hub = from_ggsns_ofd->data;
-
-	static uint8_t buf[4096];
-	struct osmo_sockaddr from_addr;
-	struct osmo_sockaddr to_addr;
-	struct osmo_fd *to_ofd;
-	int len;
-	uint8_t *reply_buf;
-
-	len = gtphub_read(from_ggsns_ofd, &from_addr, buf, sizeof(buf));
-	if (len < 1)
-		return 0;
-
-	len = gtphub_handle_buf(hub, GTPH_SIDE_GGSN, plane_idx, &from_addr,
-				buf, len, gtphub_now(),
-				&reply_buf, &to_ofd, &to_addr);
-	if (len < 1)
-		return 0;
-
-	return gtphub_write(to_ofd, &to_addr, reply_buf, len);
-}
-
-static int gtphub_unmap(struct gtphub *hub,
-			struct gtp_packet_desc *p,
-			struct gtphub_peer_port *from,
-			struct gtphub_peer_port *to_proxy,
-			struct gtphub_peer_port **final_unmapped,
-			struct gtphub_peer_port **unmapped_from_seq)
-{
-	/* Always (try to) unmap sequence and TEI numbers, which need to be
-	 * replaced in the packet. Either way, give precedence to the proxy, if
-	 * configured. */
-
-	if (unmapped_from_seq)
-		*unmapped_from_seq = NULL;
-	if (final_unmapped)
-		*final_unmapped = NULL;
-	p->tun = NULL;
-
-	struct gtphub_peer_port *from_seq = NULL;
-	struct gtphub_peer_port *from_tei = NULL;
-	struct gtphub_peer_port *unmapped = NULL;
-
-	from_seq = gtphub_unmap_seq(p, from);
-
-	if (gtphub_unmap_header_tei(&from_tei, &p->tun, hub, p, from) < 0)
-		return -1;
-
-	struct gtphub_peer *from_peer = from->peer_addr->peer;
-	if (from_seq && from_tei && (from_seq != from_tei)) {
-		LOG(LOGL_DEBUG,
-		    "Seq unmap and TEI unmap yield two different peers."
-		    " Using seq unmap."
-		    " (from %s %s: seq %d yields %s, tei %u yields %s)\n",
-		    gtphub_plane_idx_names[p->plane_idx],
-		    gtphub_peer_str(from_peer),
-		    (int)p->seq,
-		    gtphub_port_str(from_seq),
-		    (unsigned int)p->header_tei_rx,
-		    gtphub_port_str2(from_tei)
-		   );
-	}
-	unmapped = (from_seq? from_seq : from_tei);
-
-	if (unmapped && to_proxy && (unmapped != to_proxy)) {
-		LOG(LOGL_NOTICE,
-		    "Unmap yields a different peer than the configured proxy."
-		    " Using proxy."
-		    " unmapped: %s  proxy: %s\n",
-		    gtphub_port_str(unmapped),
-		    gtphub_port_str2(to_proxy)
-		   );
-	}
-	unmapped = (to_proxy? to_proxy : unmapped);
-
-	if (!unmapped) {
-		/* Return no error, but returned pointers are all NULL. */
-		return 0;
-	}
-
-	if (unmapped_from_seq)
-		*unmapped_from_seq = from_seq;
-	if (final_unmapped)
-		*final_unmapped = unmapped;
-	return 0;
-}
-
-static int gsn_addr_to_sockaddr(struct gsn_addr *src,
-				uint16_t port,
-				struct osmo_sockaddr *dst)
-{
-	return osmo_sockaddr_init_udp(dst, gsn_addr_to_str(src), port);
-}
-
-/* If p is an Echo request, replace p's data with the matching response and
- * return 1. If p is no Echo request, return 0, or -1 if an invalid packet is
- * detected. */
-static int gtphub_handle_echo_req(struct gtphub *hub, struct gtp_packet_desc *p,
-				  uint8_t **reply_buf)
-{
-	if (p->type != GTP_ECHO_REQ)
-		return 0;
-
-	static uint8_t echo_response_data[14] = {
-		0x32,	/* GTP v1 flags */
-		GTP_ECHO_RSP,
-		0x00, 14 - 8, /* Length in network byte order */
-		0x00, 0x00, 0x00, 0x00,	/* Zero TEI */
-		0, 0,	/* Seq, to be replaced */
-		0, 0,	/* no extensions */
-		0x0e,	/* Recovery IE */
-		0	/* Restart counter, to be replaced */
-	};
-	uint16_t *seq = (uint16_t*)&echo_response_data[8];
-	uint8_t *recovery = &echo_response_data[13];
-
-	*seq = hton16(p->seq);
-	*recovery = hub->restart_counter;
-
-	*reply_buf = echo_response_data;
-
-	return sizeof(echo_response_data);
-}
-
-struct gtphub_peer_port *gtphub_known_addr_have_port(const struct gtphub_bind *bind,
-						     const struct osmo_sockaddr *addr);
-
-/* Parse buffer as GTP packet, replace elements in-place and return the ofd and
- * address to forward to. Return a pointer to the osmo_fd, but copy the
- * sockaddr to *to_addr. The reason for this is that the sockaddr may expire at
- * any moment, while the osmo_fd is guaranteed to persist. Return the number of
- * bytes to forward, 0 or less on failure. */
-int gtphub_handle_buf(struct gtphub *hub,
-		      unsigned int side_idx,
-		      unsigned int plane_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_bind *from_bind = &hub->to_gsns[side_idx][plane_idx];
-	struct gtphub_bind *to_bind = &hub->to_gsns[other_side_idx(side_idx)][plane_idx];
-
-	rate_ctr_add(&from_bind->counters_io->ctr[GTPH_CTR_BYTES_IN],
-		     received);
-
-	struct gtp_packet_desc p;
-	gtp_decode(buf, received, side_idx, plane_idx, &p, now);
-
-	LOG(LOGL_DEBUG, "%s rx %s from %s %s%s\n",
-	    (side_idx == GTPH_SIDE_GGSN)? "<-" : "->",
-	    gtphub_plane_idx_names[plane_idx],
-	    gtphub_side_idx_names[side_idx],
-	    osmo_sockaddr_to_str(from_addr),
-	    gtp_type_str(p.type));
-
-	if (p.rc <= 0) {
-		LOG(LOGL_ERROR, "INVALID: dropping GTP packet%s from %s %s %s\n",
-		    gtp_type_str(p.type),
-		    gtphub_side_idx_names[side_idx],
-		    gtphub_plane_idx_names[plane_idx],
-		    osmo_sockaddr_to_str(from_addr));
-		return -1;
-	}
-
-	rate_ctr_inc(&from_bind->counters_io->ctr[GTPH_CTR_PKTS_IN]);
-
-	int reply_len;
-	reply_len = gtphub_handle_echo_req(hub, &p, reply_buf);
-	if (reply_len > 0) {
-		/* It was an echo. Nothing left to do. */
-		osmo_sockaddr_copy(to_addr, from_addr);
-		*to_ofd = &from_bind->ofd;
-
-		rate_ctr_inc(&from_bind->counters_io->ctr[GTPH_CTR_PKTS_OUT]);
-		rate_ctr_add(&from_bind->counters_io->ctr[GTPH_CTR_BYTES_OUT],
-			     reply_len);
-		LOG(LOGL_DEBUG, "%s Echo response to %s: %d bytes to %s\n",
-		    (side_idx == GTPH_SIDE_GGSN)? "-->" : "<--",
-		    gtphub_side_idx_names[side_idx],
-		    (int)reply_len, osmo_sockaddr_to_str(to_addr));
-		return reply_len;
-	}
-	if (reply_len < 0)
-		return -1;
-
-	*to_ofd = &to_bind->ofd;
-
-	/* If a proxy is configured, check that it's indeed that proxy talking
-	 * to us. A proxy is a forced 1:1 connection, e.g. to another gtphub,
-	 * so no-one else is allowed to talk to us from that side. */
-	struct gtphub_peer_port *from_peer = hub->proxy[side_idx][plane_idx];
-	if (from_peer) {
-		if (osmo_sockaddr_cmp(&from_peer->sa, from_addr) != 0) {
-			LOG(LOGL_ERROR,
-			    "Rejecting: %s proxy configured, but GTP packet"
-			    " received on %s bind is from another sender:"
-			    " proxy: %s  sender: %s\n",
-			    gtphub_side_idx_names[side_idx],
-			    gtphub_side_idx_names[side_idx],
-			    gtphub_port_str(from_peer),
-			    osmo_sockaddr_to_str(from_addr));
-			return -1;
-		}
-	}
-
-	if (!from_peer) {
-		/* Find or create a peer with a matching address. The sender's
-		 * port may in fact differ. */
-		from_peer = gtphub_known_addr_have_port(from_bind, from_addr);
-	}
-
-	/* If any PDP context has been created, we already have an entry for
-	 * this GSN. If we don't have an entry, a GGSN has nothing to tell us
-	 * about, while an SGSN may initiate a PDP context. */
-	if (!from_peer) {
-		if (side_idx == GTPH_SIDE_GGSN) {
-			LOG(LOGL_ERROR, "Dropping packet%s: unknown GGSN peer: %s\n",
-			    gtp_type_str(p.type),
-			    osmo_sockaddr_to_str(from_addr));
-			return -1;
-		} else {
-			/* SGSN */
-			/* A new peer. If this is on the Ctrl plane, an SGSN
-			 * may make first contact without being known yet, so
-			 * create the peer struct for the current sender. */
-			if (plane_idx != GTPH_PLANE_CTRL) {
-				LOG(LOGL_ERROR,
-				    "Dropping packet%s: User plane peer was not"
-				    "announced by PDP Context: %s\n",
-				    gtp_type_str(p.type),
-				    osmo_sockaddr_to_str(from_addr));
-				return -1;
-			}
-
-			struct gsn_addr from_gsna;
-			uint16_t from_port;
-			if (gsn_addr_from_sockaddr(&from_gsna, &from_port, from_addr) != 0)
-				return -1;
-
-			from_peer = gtphub_port_have(hub, from_bind, &from_gsna, from_port);
-		}
-	}
-
-	if (!from_peer) {
-		/* This could theoretically happen for invalid address data or
-		 * somesuch. */
-		LOG(LOGL_ERROR, "Dropping packet%s: invalid %s peer: %s\n",
-		    gtp_type_str(p.type),
-		    gtphub_side_idx_names[side_idx],
-		    osmo_sockaddr_to_str(from_addr));
-		return -1;
-	}
-
-	rate_ctr_add(&from_peer->counters_io->ctr[GTPH_CTR_BYTES_IN],
-		     received);
-	rate_ctr_inc(&from_peer->counters_io->ctr[GTPH_CTR_PKTS_IN]);
-
-	LOG(LOGL_DEBUG, "from %s peer: %s\n", gtphub_side_idx_names[side_idx],
-	    gtphub_port_str(from_peer));
-
-	gtphub_check_restart_counter(hub, &p, from_peer);
-	gtphub_map_restart_counter(hub, &p);
-
-	struct gtphub_peer_port *to_peer_from_seq;
-	struct gtphub_peer_port *to_peer;
-	if (gtphub_unmap(hub, &p, from_peer,
-			 hub->proxy[other_side_idx(side_idx)][plane_idx],
-			 &to_peer, &to_peer_from_seq)
-	    != 0) {
-		return -1;
-	}
-
-	if (p.tun) {
-		struct gtphub_tunnel_endpoint *te = &p.tun->endpoint[p.side_idx][p.plane_idx];
-		rate_ctr_add(&te->counters_io->ctr[GTPH_CTR_BYTES_IN],
-			     received);
-		rate_ctr_inc(&te->counters_io->ctr[GTPH_CTR_PKTS_IN]);
-	}
-
-	if ((!to_peer) && (side_idx == GTPH_SIDE_SGSN)) {
-		if (gtphub_resolve_ggsn(hub, &p, &to_peer) < 0)
-			return -1;
-	}
-
-	if (!to_peer && p.tun && p.type == GTP_DELETE_PDP_RSP) {
-		/* It's a delete confirmation for a tunnel that is partly
-		 * invalid, probably marked unsuable due to a restarted peer.
-		 * Remove the tunnel and be happy without forwarding. */
-		expiring_item_del(&p.tun->expiry_entry);
-		p.tun = NULL;
-		return 0;
-	}
-
-	if (!to_peer) {
-		LOG(LOGL_ERROR, "No %s to send to. Dropping packet%s"
-		    " (type=%" PRIu8 ", header-TEI=%" PRIx32 ", seq=%" PRIx16 ").\n",
-		    gtphub_side_idx_names[other_side_idx(side_idx)],
-		    gtp_type_str(p.type),
-		    p.type, p.header_tei_rx, p.seq
-		    );
-		return -1;
-	}
-
-	if (plane_idx == GTPH_PLANE_CTRL) {
-		/* This may be a Create PDP Context response. If it is, there
-		 * are other addresses in the GTP message to set up apart from
-		 * the sender. */
-		if (gtphub_handle_pdp_ctx(hub, &p, from_peer, to_peer)
-		    != 0)
-			return -1;
-	}
-	
-	/* Either to_peer was resolved from an existing tunnel,
-	 * or a PDP Ctx and thus a tunnel has just been created,
-	 * or the tunnel has been deleted due to this message. */
-	OSMO_ASSERT(p.tun || (p.type == GTP_DELETE_PDP_RSP));
-
-	/* If the GGSN is replying to an SGSN request, the sequence nr has
-	 * already been unmapped above (to_peer_from_seq != NULL), and we need not
-	 * create a new mapping. */
-	if (!to_peer_from_seq)
-		gtphub_map_seq(&p, from_peer, to_peer);
-
-	osmo_sockaddr_copy(to_addr, &to_peer->sa);
-
-	*reply_buf = (uint8_t*)p.data;
-
-	if (received) {
-		rate_ctr_inc(&to_bind->counters_io->ctr[GTPH_CTR_PKTS_OUT]);
-		rate_ctr_add(&to_bind->counters_io->ctr[GTPH_CTR_BYTES_OUT],
-			     received);
-
-		rate_ctr_inc(&to_peer->counters_io->ctr[GTPH_CTR_PKTS_OUT]);
-		rate_ctr_add(&to_peer->counters_io->ctr[GTPH_CTR_BYTES_OUT],
-			     received);
-	}
-
-	if (p.tun) {
-		struct gtphub_tunnel_endpoint *te = &p.tun->endpoint[other_side_idx(p.side_idx)][p.plane_idx];
-		rate_ctr_inc(&te->counters_io->ctr[GTPH_CTR_PKTS_OUT]);
-		rate_ctr_add(&te->counters_io->ctr[GTPH_CTR_BYTES_OUT],
-			     received);
-	}
-
-	LOG(LOGL_DEBUG, "%s Forward to %s:"
-	    " header-TEI %" PRIx32", seq %" PRIx16", %d bytes to %s\n",
-	    (side_idx == GTPH_SIDE_SGSN)? "-->" : "<--",
-	    gtphub_side_idx_names[other_side_idx(side_idx)],
-	    p.header_tei, p.seq,
-	    (int)received, osmo_sockaddr_to_str(to_addr));
-	return received;
-}
-
-static void resolved_gssn_del_cb(struct expiring_item *expi)
-{
-	struct gtphub_resolved_ggsn *ggsn;
-	ggsn = container_of(expi, struct gtphub_resolved_ggsn, expiry_entry);
-
-	gtphub_port_ref_count_dec(ggsn->peer);
-	llist_del(&ggsn->entry);
-
-	ggsn->expiry_entry.del_cb = 0;
-	expiring_item_del(&ggsn->expiry_entry);
-
-	talloc_free(ggsn);
-}
-
-void gtphub_resolved_ggsn(struct gtphub *hub, const char *apn_oi_str,
-			  struct gsn_addr *resolved_addr,
-			  time_t now)
-{
-	struct gtphub_peer_port *pp;
-	struct gtphub_resolved_ggsn *ggsn;
-
-	LOG(LOGL_DEBUG, "Resolved GGSN callback: %s %s\n",
-	    apn_oi_str, osmo_hexdump((unsigned char*)resolved_addr,
-				     sizeof(*resolved_addr)));
-
-	pp = gtphub_port_have(hub, &hub->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL],
-			      resolved_addr, 2123);
-	if (!pp) {
-		LOG(LOGL_ERROR, "Internal: Cannot create/find peer '%s'\n",
-		    gsn_addr_to_str(resolved_addr));
-		return;
-	}
-
-	ggsn = talloc_zero(osmo_gtphub_ctx, struct gtphub_resolved_ggsn);
-	OSMO_ASSERT(ggsn);
-	INIT_LLIST_HEAD(&ggsn->entry);
-	expiring_item_init(&ggsn->expiry_entry);
-
-	ggsn->peer = pp;
-	gtphub_port_ref_count_inc(pp);
-
-	osmo_strlcpy(ggsn->apn_oi_str, apn_oi_str, sizeof(ggsn->apn_oi_str));
-
-	ggsn->expiry_entry.del_cb = resolved_gssn_del_cb;
-	expiry_add(&hub->expire_slowly, &ggsn->expiry_entry, now);
-
-	llist_add(&ggsn->entry, &hub->resolved_ggsns);
-}
-
-static int gtphub_gc_peer_port(struct gtphub_peer_port *pp)
-{
-	return pp->ref_count == 0;
-}
-
-static int gtphub_gc_peer_addr(struct gtphub_peer_addr *pa)
-{
-	struct gtphub_peer_port *pp, *npp;
-	llist_for_each_entry_safe(pp, npp, &pa->ports, entry) {
-		if (gtphub_gc_peer_port(pp)) {
-			LOG(LOGL_DEBUG, "expired: peer %s\n",
-			    gtphub_port_str(pp));
-			gtphub_peer_port_del(pp);
-		}
-	}
-	return llist_empty(&pa->ports);
-}
-
-static int gtphub_gc_peer(struct gtphub_peer *p)
-{
-	struct gtphub_peer_addr *pa, *npa;
-	llist_for_each_entry_safe(pa, npa, &p->addresses, entry) {
-		if (gtphub_gc_peer_addr(pa)) {
-			gtphub_peer_addr_del(pa);
-		}
-	}
-
-	/* Note that there's a ref_count in each gtphub_peer_port instance
-	 * listed within p->addresses, referenced by TEI mappings from
-	 * hub->tei_map. As long as those don't expire, this peer will stay. */
-
-	return llist_empty(&p->addresses)
-		&& nr_map_empty(&p->seq_map);
-}
-
-static void gtphub_gc_bind(struct gtphub_bind *b)
-{
-	struct gtphub_peer *p, *n;
-	llist_for_each_entry_safe(p, n, &b->peers, entry) {
-		if (gtphub_gc_peer(p)) {
-			gtphub_peer_del(p);
-		}
-	}
-}
-
-void gtphub_gc(struct gtphub *hub, time_t now)
-{
-	int expired;
-	expired = expiry_tick(&hub->expire_quickly, now);
-	expired += expiry_tick(&hub->expire_slowly, now);
-
-	/* ... */
-
-	if (expired) {
-		int s, p;
-		for_each_side_and_plane(s, p) {
-			gtphub_gc_bind(&hub->to_gsns[s][p]);
-		}
-	}
-}
-
-static void gtphub_gc_cb(void *data)
-{
-	struct gtphub *hub = data;
-	gtphub_gc(hub, gtphub_now());
-	osmo_timer_schedule(&hub->gc_timer, GTPH_GC_TICK_SECONDS, 0);
-}
-
-static void gtphub_gc_start(struct gtphub *hub)
-{
-	osmo_timer_setup(&hub->gc_timer, gtphub_gc_cb, hub);
-	osmo_timer_schedule(&hub->gc_timer, GTPH_GC_TICK_SECONDS, 0);
-}
-
-/* called by unit tests */
-void gtphub_init(struct gtphub *hub)
-{
-	gtphub_zero(hub);
-
-	INIT_LLIST_HEAD(&hub->tunnels);
-	INIT_LLIST_HEAD(&hub->pending_deletes);
-
-	expiry_init(&hub->expire_quickly, GTPH_EXPIRE_QUICKLY_SECS);
-	expiry_init(&hub->expire_slowly, GTPH_EXPIRE_SLOWLY_MINUTES * 60);
-
-	nr_pool_init(&hub->tei_pool, 1, 0xffffffff);
-
-	int side_idx;
-	int plane_idx;
-	for_each_side_and_plane(side_idx, plane_idx) {
-		gtphub_bind_init(&hub->to_gsns[side_idx][plane_idx]);
-	}
-
-	hub->to_gsns[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].label = "SGSN Ctrl";
-	hub->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].label = "GGSN Ctrl";
-	hub->to_gsns[GTPH_SIDE_SGSN][GTPH_PLANE_USER].label = "SGSN User";
-	hub->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_USER].label = "GGSN User";
-}
-
-/* For the test suite, this is kept separate from gtphub_stop(), which also
- * closes sockets. The test suite avoids using sockets and would cause
- * segfaults when trying to close uninitialized ofds. */
-void gtphub_free(struct gtphub *hub)
-{
-	/* By expiring all mappings, a garbage collection should free
-	 * everything else. A gtphub_bind_free() will assert that everything is
-	 * indeed empty. */
-	expiry_clear(&hub->expire_quickly);
-	expiry_clear(&hub->expire_slowly);
-
-	int side_idx;
-	int plane_idx;
-	for_each_side_and_plane(side_idx, plane_idx) {
-		gtphub_gc_bind(&hub->to_gsns[side_idx][plane_idx]);
-		gtphub_bind_free(&hub->to_gsns[side_idx][plane_idx]);
-	}
-}
-
-void gtphub_stop(struct gtphub *hub)
-{
-	int side_idx;
-	int plane_idx;
-	for_each_side_and_plane(side_idx, plane_idx) {
-		gtphub_bind_stop(&hub->to_gsns[side_idx][plane_idx]);
-	}
-	gtphub_free(hub);
-}
-
-static int gtphub_make_proxy(struct gtphub *hub,
-			     struct gtphub_peer_port **pp,
-			     struct gtphub_bind *bind,
-			     const struct gtphub_cfg_addr *addr)
-{
-	if (!addr->addr_str)
-		return 0;
-
-	struct gsn_addr gsna;
-	if (gsn_addr_from_str(&gsna, addr->addr_str) != 0)
-		return -1;
-
-	*pp = gtphub_port_have(hub, bind, &gsna, addr->port);
-
-	/* This is *the* proxy. Make sure it is never expired. */
-	gtphub_port_ref_count_inc(*pp);
-	return 0;
-}
-
-int gtphub_start(struct gtphub *hub, struct gtphub_cfg *cfg,
-		 uint8_t restart_counter)
-{
-	gtphub_init(hub);
-
-	hub->restart_counter = restart_counter;
-	hub->sgsn_use_sender = cfg->sgsn_use_sender? 1 : 0;
-
-	/* If a Ctrl plane proxy is configured, ares will never be used. */
-	if (!cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].addr_str) {
-		if (gtphub_ares_init(hub) != 0) {
-			LOG(LOGL_FATAL, "Failed to initialize ares\n");
-			return -1;
-		}
-	}
-
-	int side_idx;
-	int plane_idx;
-	for_each_side_and_plane(side_idx, plane_idx) {
-		int rc;
-		rc = gtphub_bind_start(&hub->to_gsns[side_idx][plane_idx],
-				       &cfg->to_gsns[side_idx][plane_idx],
-				       (side_idx == GTPH_SIDE_SGSN)
-					       ? from_sgsns_read_cb
-					       : from_ggsns_read_cb,
-				       hub, plane_idx);
-		if (rc) {
-			LOG(LOGL_FATAL, "Failed to bind for %ss (%s)\n",
-			    gtphub_side_idx_names[side_idx],
-			    gtphub_plane_idx_names[plane_idx]);
-			return rc;
-		}
-	}
-
-	for_each_side_and_plane(side_idx, plane_idx) {
-		if (gtphub_make_proxy(hub,
-				      &hub->proxy[side_idx][plane_idx],
-				      &hub->to_gsns[side_idx][plane_idx],
-				      &cfg->proxy[side_idx][plane_idx])
-		    != 0) {
-			LOG(LOGL_FATAL, "Cannot configure %s proxy"
-			    " %s port %d.\n",
-			    gtphub_side_idx_names[side_idx],
-			    cfg->proxy[side_idx][plane_idx].addr_str,
-			    (int)cfg->proxy[side_idx][plane_idx].port);
-			return -1;
-		}
-	}
-
-	for_each_side_and_plane(side_idx, plane_idx) {
-		if (hub->proxy[side_idx][plane_idx])
-			LOG(LOGL_NOTICE, "Using %s %s proxy %s\n",
-			    gtphub_side_idx_names[side_idx],
-			    gtphub_plane_idx_names[plane_idx],
-			    gtphub_port_str(hub->proxy[side_idx][plane_idx]));
-	}
-
-	if (hub->sgsn_use_sender)
-		LOG(LOGL_NOTICE, "Using sender address and port for SGSN instead of GSN Addr IE and default ports.\n");
-
-	gtphub_gc_start(hub);
-	return 0;
-}
-
-static struct gtphub_peer_addr *gtphub_peer_find_addr(const struct gtphub_peer *peer,
-						      const struct gsn_addr *addr)
-{
-	struct gtphub_peer_addr *a;
-	llist_for_each_entry(a, &peer->addresses, entry) {
-		if (gsn_addr_same(&a->addr, addr))
-			return a;
-	}
-	return NULL;
-}
-
-static struct gtphub_peer_port *gtphub_addr_find_port(const struct gtphub_peer_addr *a,
-						      uint16_t port)
-{
-	OSMO_ASSERT(port);
-	struct gtphub_peer_port *pp;
-	llist_for_each_entry(pp, &a->ports, entry) {
-		if (pp->port == port)
-			return pp;
-	}
-	return NULL;
-}
-
-static struct gtphub_peer_addr *gtphub_addr_find(const struct gtphub_bind *bind,
-						 const struct gsn_addr *addr)
-{
-	struct gtphub_peer *peer;
-	llist_for_each_entry(peer, &bind->peers, entry) {
-		struct gtphub_peer_addr *a = gtphub_peer_find_addr(peer, addr);
-		if (a)
-			return a;
-	}
-	return NULL;
-}
-
-static struct gtphub_peer_port *gtphub_port_find(const struct gtphub_bind *bind,
-						 const struct gsn_addr *addr,
-						 uint16_t port)
-{
-	struct gtphub_peer_addr *a = gtphub_addr_find(bind, addr);
-	if (!a)
-		return NULL;
-	return gtphub_addr_find_port(a, port);
-}
-
-struct gtphub_peer_port *gtphub_port_find_sa(const struct gtphub_bind *bind,
-					     const struct osmo_sockaddr *addr)
-{
-	struct gsn_addr gsna;
-	uint16_t port;
-	gsn_addr_from_sockaddr(&gsna, &port, addr);
-	return gtphub_port_find(bind, &gsna, port);
-}
-
-static struct gtphub_peer *gtphub_peer_new(struct gtphub *hub,
-					   struct gtphub_bind *bind)
-{
-	struct gtphub_peer *peer = talloc_zero(osmo_gtphub_ctx,
-					       struct gtphub_peer);
-	OSMO_ASSERT(peer);
-
-	INIT_LLIST_HEAD(&peer->addresses);
-
-	nr_pool_init(&peer->seq_pool, 0, 0xffff);
-	nr_map_init(&peer->seq_map, &peer->seq_pool, &hub->expire_quickly);
-
-	/* TODO use something random to pick the initial sequence nr.
-	   0x6d31 produces the ASCII character sequence 'm1', currently used in
-	   gtphub_nc_test.sh. */
-	peer->seq_pool.last_nr = 0x6d31 - 1;
-
-	llist_add(&peer->entry, &bind->peers);
-	return peer;
-}
-
-static struct gtphub_peer_addr *gtphub_peer_add_addr(struct gtphub_peer *peer,
-						     const struct gsn_addr *addr)
-{
-	struct gtphub_peer_addr *a;
-	a = talloc_zero(osmo_gtphub_ctx, struct gtphub_peer_addr);
-	OSMO_ASSERT(a);
-	a->peer = peer;
-	gsn_addr_copy(&a->addr, addr);
-	INIT_LLIST_HEAD(&a->ports);
-	llist_add(&a->entry, &peer->addresses);
-
-	return a;
-}
-
-static struct gtphub_peer_addr *gtphub_addr_have(struct gtphub *hub,
-						 struct gtphub_bind *bind,
-						 const struct gsn_addr *addr)
-{
-	struct gtphub_peer_addr *a = gtphub_addr_find(bind, addr);
-	if (a)
-		return a;
-
-	/* If we haven't found an address, that means we need to create an
-	 * entirely new peer for the new address. More addresses may be added
-	 * to this peer later, but not via this function. */
-	struct gtphub_peer *peer = gtphub_peer_new(hub, bind);
-
-	a = gtphub_peer_add_addr(peer, addr);
-	
-	LOG(LOGL_DEBUG, "New peer address: %s %s\n",
-	    bind->label,
-	    gsn_addr_to_str(&a->addr));
-
-	return a;
-}
-
-static struct gtphub_peer_port *gtphub_addr_add_port(struct gtphub_peer_addr *a,
-						     uint16_t port)
-{
-	struct gtphub_peer_port *pp;
-
-	pp = talloc_zero(osmo_gtphub_ctx, struct gtphub_peer_port);
-	OSMO_ASSERT(pp);
-	pp->peer_addr = a;
-	pp->port = port;
-	pp->last_restart_count = -1;
-
-	if (gsn_addr_to_sockaddr(&a->addr, port, &pp->sa) != 0) {
-		talloc_free(pp);
-		return NULL;
-	}
-
-	pp->counters_io = rate_ctr_group_alloc(osmo_gtphub_ctx,
-					       &gtphub_ctrg_io_desc, 0);
-	if (!pp->counters_io) {
-		talloc_free(pp);
-		return NULL;
-	}
-
-	llist_add(&pp->entry, &a->ports);
-
-	LOG(LOGL_DEBUG, "New peer port: %s port %d\n",
-	    gsn_addr_to_str(&a->addr),
-	    (int)port);
-
-	return pp;
-}
-
-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_addr *a = gtphub_addr_have(hub, bind, addr);
-
-	struct gtphub_peer_port *pp = gtphub_addr_find_port(a, port);
-	if (pp)
-		return pp;
-
-	return gtphub_addr_add_port(a, port);
-}
-
-/* Find a GGSN peer with a matching address. If the address is known but the
- * port not, create a new port for that peer address. */
-struct gtphub_peer_port *gtphub_known_addr_have_port(const struct gtphub_bind *bind,
-						     const struct osmo_sockaddr *addr)
-{
-	struct gtphub_peer_addr *pa;
-	struct gtphub_peer_port *pp;
-
-	struct gsn_addr gsna;
-	uint16_t port;
-	gsn_addr_from_sockaddr(&gsna, &port, addr);
-
-	pa = gtphub_addr_find(bind, &gsna);
-	if (!pa)
-		return NULL;
-
-	pp = gtphub_addr_find_port(pa, port);
-
-	if (!pp)
-		pp = gtphub_addr_add_port(pa, port);
-
-	return pp;
-}
-
-
-/* Return 0 if the message in p is not applicable for GGSN resolution, -1 if
- * resolution should be possible but failed, and 1 if resolution was
- * successful. *pp will be set to NULL if <1 is returned. */
-static int gtphub_resolve_ggsn(struct gtphub *hub,
-			       struct gtp_packet_desc *p,
-			       struct gtphub_peer_port **pp)
-{
-	*pp = NULL;
-
-	/* TODO determine from message type whether IEs should be present? */
-
-	int rc;
-	const char *imsi_str;
-	rc = get_ie_imsi_str(p->ie, 0, &imsi_str);
-	if (rc < 1)
-		return rc;
-	OSMO_ASSERT(imsi_str);
-
-	const char *apn_str;
-	rc = get_ie_apn_str(p->ie, &apn_str);
-	if (rc < 1)
-		return rc;
-	OSMO_ASSERT(apn_str);
-
-	*pp = gtphub_resolve_ggsn_addr(hub, imsi_str, apn_str);
-	return (*pp)? 1 : -1;
-}
-
-
-/* TODO move to osmocom/core/socket.c ? */
-/* use this in osmo_sock_init() to remove dup. */
-/* Internal: call getaddrinfo for osmo_sockaddr_init(). The caller is required
-   to call freeaddrinfo(*result), iff zero is returned. */
-static int _osmo_getaddrinfo(struct addrinfo **result,
-			     uint16_t family, uint16_t type, uint8_t proto,
-			     const char *host, uint16_t port)
-{
-	struct addrinfo hints;
-	char portbuf[16];
-
-	sprintf(portbuf, "%u", port);
-	memset(&hints, '\0', sizeof(struct addrinfo));
-	hints.ai_family = family;
-	if (type == SOCK_RAW) {
-		/* Workaround for glibc, that returns EAI_SERVICE (-8) if
-		 * SOCK_RAW and IPPROTO_GRE is used.
-		 */
-		hints.ai_socktype = SOCK_DGRAM;
-		hints.ai_protocol = IPPROTO_UDP;
-	} else {
-		hints.ai_socktype = type;
-		hints.ai_protocol = proto;
-	}
-
-	return getaddrinfo(host, portbuf, &hints, result);
-}
-
-/* TODO move to osmocom/core/socket.c ? */
-int osmo_sockaddr_init(struct osmo_sockaddr *addr,
-		       uint16_t family, uint16_t type, uint8_t proto,
-		       const char *host, uint16_t port)
-{
-	struct addrinfo *res;
-	int rc;
-	rc = _osmo_getaddrinfo(&res, family, type, proto, host, port);
-
-	if (rc != 0) {
-		LOG(LOGL_ERROR, "getaddrinfo returned error %d\n", (int)rc);
-		return -EINVAL;
-	}
-
-	OSMO_ASSERT(res->ai_addrlen <= sizeof(addr->a));
-	memcpy(&addr->a, res->ai_addr, res->ai_addrlen);
-	addr->l = res->ai_addrlen;
-	freeaddrinfo(res);
-
-	return 0;
-}
-
-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)
-{
-       int rc;
-
-       if ((addr->l < 1) || (addr->l > sizeof(addr->a))) {
-	       LOGP(DGTPHUB, LOGL_ERROR, "Invalid address size: %d\n", addr->l);
-	       return -1;
-       }
-
-       if (addr->l > sizeof(addr->a)) {
-	       LOGP(DGTPHUB, LOGL_ERROR, "Invalid address: too long: %d\n",
-		    addr->l);
-	       return -1;
-       }
-
-       rc = getnameinfo((struct sockaddr*)&addr->a, addr->l,
-			addr_str, addr_str_len,
-			port_str, port_str_len,
-			flags);
-
-       if (rc)
-	       LOGP(DGTPHUB, LOGL_ERROR, "Invalid address: %s: %s\n",
-		    gai_strerror(rc), osmo_hexdump((uint8_t*)&addr->a,
-						   addr->l));
-
-       return rc;
-}
-
-const char *osmo_sockaddr_to_strb(const struct osmo_sockaddr *addr,
-				  char *buf, size_t buf_len)
-{
-	const int portbuf_len = 6;
-	OSMO_ASSERT(buf_len > portbuf_len);
-	char *portbuf = buf + buf_len - portbuf_len;
-	buf_len -= portbuf_len;
-	if (osmo_sockaddr_to_strs(buf, buf_len,
-				  portbuf, portbuf_len,
-				  addr,
-				  NI_NUMERICHOST | NI_NUMERICSERV))
-		return NULL;
-
-	char *pos = buf + strnlen(buf, buf_len-1);
-	size_t len = buf_len - (pos - buf);
-
-	snprintf(pos, len, " port %s", portbuf);
-	buf[buf_len-1] = '\0';
-
-	return buf;
-}
-
-const char *osmo_sockaddr_to_str(const struct osmo_sockaddr *addr)
-{
-	static char buf[256];
-	const char *result = osmo_sockaddr_to_strb(addr, buf, sizeof(buf));
-	if (! result)
-		return "(invalid)";
-	return result;
-}
-
-int osmo_sockaddr_cmp(const struct osmo_sockaddr *a,
-		      const struct osmo_sockaddr *b)
-{
-	if (a == b)
-		return 0;
-	if (!a)
-		return -1;
-	if (!b)
-		return 1;
-	if (a->l != b->l) {
-		/* Lengths are not the same, but determine the order. Will
-		 * anyone ever sort a list by osmo_sockaddr though...? */
-		int cmp = memcmp(&a->a, &b->a, (a->l < b->l)? a->l : b->l);
-		if (cmp == 0) {
-			if (a->l < b->l)
-				return -1;
-			else
-				return 1;
-		}
-		return cmp;
-	}
-	return memcmp(&a->a, &b->a, a->l);
-}
-
-void osmo_sockaddr_copy(struct osmo_sockaddr *dst,
-			const struct osmo_sockaddr *src)
-{
-	OSMO_ASSERT(src->l <= sizeof(dst->a));
-	memcpy(&dst->a, &src->a, src->l);
-	dst->l = src->l;
-}
diff --git a/src/gprs/gtphub_ares.c b/src/gprs/gtphub_ares.c
deleted file mode 100644
index afeeda6..0000000
--- a/src/gprs/gtphub_ares.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/* GTP Hub Implementation */
-
-/* (C) 2015 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- * All Rights Reserved
- *
- * gtphub_ares.c.
- *
- * This file is kept separate so that these functions can be wrapped for
- * gtphub_test.c. When a function and its callers are in the same compilational
- * unit, the wrappability may be optimized away.
- *
- * 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/>.
- */
-
-#include <string.h>
-#include <unistd.h>
-
-#include <openbsc/gtphub.h>
-#include <openbsc/debug.h>
-
-#include <osmocom/core/utils.h>
-#include <osmocom/gsm/apn.h>
-
-/* TODO split GRX ares from sgsn into a separate struct and allow use without
- * globals. */
-#include <openbsc/sgsn.h>
-extern struct sgsn_instance *sgsn;
-
-struct sgsn_instance sgsn_inst = { 0 };
-struct sgsn_instance *sgsn = &sgsn_inst;
-
-extern void *osmo_gtphub_ctx;
-
-int gtphub_ares_init(struct gtphub *hub)
-{
-	return sgsn_ares_init(sgsn);
-}
-
-struct ggsn_lookup {
-	struct llist_head entry;
-	struct expiring_item expiry_entry;
-
-	struct gtphub *hub;
-
-	char imsi_str[GSM23003_IMSI_MAX_DIGITS+1];
-	char apn_ni_str[GSM_APN_LENGTH];
-	char apn_oi_str[GSM_APN_LENGTH];
-	int have_3dig_mnc;
-};
-
-static int start_ares_query(struct ggsn_lookup *lookup);
-
-static void ggsn_lookup_cb(void *arg, int status, int timeouts,
-			   struct hostent *hostent)
-{
-	struct ggsn_lookup *lookup = arg;
-	LOGP(DGTPHUB, LOGL_NOTICE, "ggsn_lookup_cb(%p / %p)", lookup,
-	     &lookup->expiry_entry);
-
-	if (status != ARES_SUCCESS) {
-		LOGP(DGTPHUB, LOGL_ERROR, "DNS query failed.\n");
-
-		/* Need to try with three digits now */
-		if (!lookup->have_3dig_mnc) {
-			lookup->have_3dig_mnc = 1;
-			if (start_ares_query(lookup) == 0)
-				return;
-		}
-
-		LOGP(DGTPHUB, LOGL_ERROR, "Failed to resolve GGSN. (%p)\n",
-		     lookup);
-		goto remove_from_queue;
-	}
-
-	struct gsn_addr resolved_addr;
-	if (hostent->h_length > sizeof(resolved_addr.buf)) {
-		LOGP(DGTPHUB, LOGL_ERROR, "Addr size too large: %d > %d\n",
-		     (int)hostent->h_length, (int)sizeof(resolved_addr.buf));
-		goto remove_from_queue;
-	}
-
-	/* Get the first addr from the list */
-	char *addr0 = hostent->h_addr_list[0];
-	if (!addr0) {
-		LOGP(DGTPHUB, LOGL_ERROR, "No host address.\n");
-		goto remove_from_queue;
-	}
-
-	memcpy(resolved_addr.buf, addr0, hostent->h_length);
-	resolved_addr.len = hostent->h_length;
-
-	LOGP(DGTPHUB, LOGL_NOTICE, "resolved addr %s\n",
-	     osmo_hexdump((unsigned char*)&resolved_addr,
-			  sizeof(resolved_addr)));
-
-	gtphub_resolved_ggsn(lookup->hub, lookup->apn_oi_str, &resolved_addr,
-			     gtphub_now());
-
-remove_from_queue:
-	LOGP(DGTPHUB, LOGL_ERROR, "Removing GGSN lookup. (%p / %p)\n", lookup,
-	     &lookup->expiry_entry);
-	expiring_item_del(&lookup->expiry_entry);
-}
-
-static void make_addr_str(struct ggsn_lookup *lookup)
-{
-	char *apn_oi_str;
-	apn_oi_str = osmo_apn_qualify_from_imsi(lookup->imsi_str,
-						lookup->apn_ni_str,
-						lookup->have_3dig_mnc);
-	osmo_strlcpy(lookup->apn_oi_str, apn_oi_str,
-		     sizeof(lookup->apn_oi_str));
-}
-
-static int start_ares_query(struct ggsn_lookup *lookup)
-{
-	LOGP(DGTPHUB, LOGL_DEBUG, "Going to query %s (%p / %p)\n",
-	     lookup->apn_oi_str, lookup, &lookup->expiry_entry);
-
-	int rc = sgsn_ares_query(sgsn, lookup->apn_oi_str, ggsn_lookup_cb,
-				 lookup);
-	if (rc != 0)
-		LOGP(DGTPHUB, LOGL_ERROR, "Failed to start ares query.\n");
-	return rc;
-}
-
-static void ggsn_lookup_del_cb(struct expiring_item *expi)
-{
-	struct ggsn_lookup *lookup;
-	lookup = container_of(expi, struct ggsn_lookup, expiry_entry);
-
-	LOGP(DGTPHUB, LOGL_NOTICE, "ggsn_lookup_del_cb(%p / %p)\n", lookup,
-	     expi);
-
-	lookup->expiry_entry.del_cb = 0;
-	expiring_item_del(expi);
-
-	llist_del(&lookup->entry);
-	talloc_free(lookup);
-}
-
-struct gtphub_peer_port *gtphub_resolve_ggsn_addr(struct gtphub *hub,
-						  const char *imsi_str,
-						  const char *apn_ni_str)
-{
-	OSMO_ASSERT(imsi_str);
-	OSMO_ASSERT(apn_ni_str);
-
-	struct ggsn_lookup *lookup = talloc_zero(osmo_gtphub_ctx,
-						 struct ggsn_lookup);
-	OSMO_ASSERT(lookup);
-
-	LOGP(DGTPHUB, LOGL_DEBUG, "Request to resolve IMSI"
-	     " '%s' with APN-NI '%s' (%p / %p)\n",
-	     imsi_str, apn_ni_str, lookup, &lookup->expiry_entry);
-
-	expiring_item_init(&lookup->expiry_entry);
-	lookup->hub = hub;
-
-	osmo_strlcpy(lookup->imsi_str, imsi_str, sizeof(lookup->imsi_str));
-	osmo_strlcpy(lookup->apn_ni_str, apn_ni_str,
-		     sizeof(lookup->apn_ni_str));
-
-	make_addr_str(lookup);
-
-	struct ggsn_lookup *active;
-	llist_for_each_entry(active, &hub->ggsn_lookups, entry) {
-		if (strncmp(active->apn_oi_str, lookup->apn_oi_str,
-			    sizeof(lookup->apn_oi_str)) == 0) {
-			LOGP(DGTPHUB, LOGL_DEBUG,
-			     "Query already pending for %s\n",
-			     lookup->apn_oi_str);
-			/* A query already pending. Just tip our hat. */
-			return NULL;
-		}
-	}
-
-	struct gtphub_resolved_ggsn *resolved;
-	llist_for_each_entry(resolved, &hub->resolved_ggsns, entry) {
-		if (strncmp(resolved->apn_oi_str, lookup->apn_oi_str,
-			    sizeof(lookup->apn_oi_str)) == 0) {
-			LOGP(DGTPHUB, LOGL_DEBUG,
-			     "GGSN resolved from cache: %s -> %s\n",
-			     lookup->apn_oi_str,
-			     gtphub_port_str(resolved->peer));
-			return resolved->peer;
-		}
-	}
-
-	/* Kick off a resolution, but so far return nothing. The hope is that
-	 * the peer will resend the request (a couple of times), and by then
-	 * the GGSN will be resolved. */
-	LOGP(DGTPHUB, LOGL_DEBUG,
-	     "Sending out DNS query for %s..."
-	     " (Returning failure, hoping for a retry once resolution"
-	     " has concluded)\n",
-	     lookup->apn_oi_str);
-
-	llist_add(&lookup->entry, &hub->ggsn_lookups);
-
-	lookup->expiry_entry.del_cb = ggsn_lookup_del_cb;
-	expiry_add(&hub->expire_quickly, &lookup->expiry_entry, gtphub_now());
-
-	start_ares_query(lookup);
-
-	return NULL;
-}
diff --git a/src/gprs/gtphub_main.c b/src/gprs/gtphub_main.c
deleted file mode 100644
index 2b87d19..0000000
--- a/src/gprs/gtphub_main.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/* GTP Hub main program */
-
-/* (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/>.
- */
-
-#include <unistd.h>
-#include <signal.h>
-#include <string.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <sys/stat.h>
-
-#define _GNU_SOURCE
-#include <getopt.h>
-
-#include <osmocom/core/signal.h>
-#include <osmocom/core/application.h>
-#include <osmocom/core/logging.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/rate_ctr.h>
-
-#include <osmocom/vty/logging.h>
-#include <osmocom/vty/telnet_interface.h>
-#include <osmocom/vty/ports.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/gtphub.h>
-#include <openbsc/vty.h>
-
-#include "../../bscconfig.h"
-
-extern void *osmo_gtphub_ctx;
-
-
-const char *gtphub_copyright =
-	"Copyright (C) 2015 sysmocom s.f.m.c GmbH <info@sysmocom.de>\r\n"
-	"License AGPLv3+: GNU AGPL version 2 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
-	"This is free software: you are free to change and redistribute it.\r\n"
-	"There is NO WARRANTY, to the extent permitted by law.\r\n";
-
-static struct log_info_cat gtphub_categories[] = {
-	[DGTPHUB] = {
-		.name = "DGTPHUB",
-		.description = "GTP Hub",
-		.color = "\033[1;33m",
-		.enabled = 1,
-		.loglevel = LOGL_INFO,
-	},
-};
-
-int gtphub_log_filter_fn(const struct log_context *ctx,
-			 struct log_target *tar)
-{
-	return 0;
-}
-
-static const struct log_info gtphub_log_info = {
-	.filter_fn = gtphub_log_filter_fn,
-	.cat = gtphub_categories,
-	.num_cat = ARRAY_SIZE(gtphub_categories),
-};
-
-void log_cfg(struct gtphub_cfg *cfg)
-{
-	int side_idx, plane_idx;
-	for_each_side_and_plane(side_idx, plane_idx) {
-		struct gtphub_cfg_addr *a;
-		a = &cfg->to_gsns[side_idx][plane_idx].bind;
-		LOGP(DGTPHUB, LOGL_NOTICE,
-		     "to-%ss bind, %s: %s port %d\n",
-		     gtphub_side_idx_names[side_idx],
-		     gtphub_plane_idx_names[plane_idx],
-		     a->addr_str, a->port);
-	}
-}
-
-static void signal_handler(int signal)
-{
-	fprintf(stdout, "signal %d received\n", signal);
-
-	switch (signal) {
-	case SIGINT:
-	case SIGTERM:
-		osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL);
-		sleep(1);
-		exit(0);
-		break;
-	case SIGABRT:
-		/* in case of abort, we want to obtain a talloc report
-		 * and then return to the caller, who will abort the process */
-	case SIGUSR1:
-	case SIGUSR2:
-		talloc_report_full(osmo_gtphub_ctx, stderr);
-		break;
-	default:
-		break;
-	}
-}
-
-extern int bsc_vty_go_parent(struct vty *vty);
-
-static struct vty_app_info vty_info = {
-	.name 		= "OsmoGTPhub",
-	.version	= PACKAGE_VERSION,
-	.go_parent_cb	= bsc_vty_go_parent,
-	.is_config_node	= bsc_vty_is_config_node,
-};
-
-struct cmdline_cfg {
-	const char *config_file;
-	const char *restart_counter_file;
-	int daemonize;
-};
-
-static uint8_t next_restart_count(const char *path)
-{
-	int umask_was = umask(022);
-
-	uint8_t counter = 0;
-
-	FILE *f = fopen(path, "r");
-	if (f) {
-		int rc = fscanf(f, "%hhu", &counter);
-
-		if (rc != 1)
-			goto failed_to_read;
-
-		char c;
-		while (fread(&c, 1, 1, f) > 0) {
-			switch (c) {
-			case ' ':
-			case '\t':
-			case '\n':
-			case '\r':
-				break;
-			default:
-				goto failed_to_read;
-			}
-		}
-		fclose(f);
-	}
-
-	counter ++;
-
-	f = fopen(path, "w");
-	if (!f)
-		goto failed_to_write;
-	if (fprintf(f, "%" PRIu8 "\n", counter) < 2)
-		goto failed_to_write;
-	if (fclose(f)) {
-		f = NULL;
-		goto failed_to_write;
-	}
-
-	umask(umask_was);
-
-	LOGP(DGTPHUB, LOGL_NOTICE, "Restarted with counter %hhu\n", counter);
-	return counter;
-
-failed_to_read:
-	fclose(f);
-	umask(umask_was);
-	LOGP(DGTPHUB, LOGL_FATAL, "Restart counter file cannot be parsed:"
-	     " %s\n", path);
-	exit(1);
-
-failed_to_write:
-	if (f)
-		fclose(f);
-	umask(umask_was);
-	LOGP(DGTPHUB, LOGL_FATAL, "Restart counter file cannot be written:"
-	     " %s\n", path);
-	exit(1);
-}
-
-static void print_help(struct cmdline_cfg *ccfg)
-{
-	printf("gtphub commandline options\n");
-	printf("  -h,--help            This text.\n");
-	printf("  -D,--daemonize       Fork the process into a background daemon.\n");
-	printf("  -d,--debug <cat>     Enable Debugging for this category.\n");
-	printf("                       Pass '-d list' to get a category listing.\n");
-	printf("  -s,--disable-color\n");
-	printf("  -c,--config-file <path>  The config file to use [%s].\n",
-	       ccfg->config_file);
-	printf("  -e,--log-level <nr>      Set a global log level.\n");
-	printf("  -r,--restart-file <path> File for counting restarts [%s].\n",
-	       ccfg->restart_counter_file);
-}
-
-static void list_categories(void)
-{
-	printf("Avaliable debug categories:\n");
-	int i;
-	for (i = 0; i < gtphub_log_info.num_cat; ++i) {
-		if (!gtphub_log_info.cat[i].name)
-			continue;
-
-		printf("%s\n", gtphub_log_info.cat[i].name);
-	}
-}
-
-static void handle_options(struct cmdline_cfg *ccfg, int argc, char **argv)
-{
-	while (1) {
-		int option_index = 0, c;
-		static struct option long_options[] = {
-			{"help", 0, 0, 'h'},
-			{"debug", 1, 0, 'd'},
-			{"daemonize", 0, 0, 'D'},
-			{"config-file", 1, 0, 'c'},
-			{"disable-color", 0, 0, 's'},
-			{"timestamp", 0, 0, 'T'},
-			{"log-level", 1, 0, 'e'},
-			{"restart-file", 1, 0, 'r'},
-			{NULL, 0, 0, 0}
-		};
-
-		c = getopt_long(argc, argv, "hd:Dc:sTe:r:",
-				long_options, &option_index);
-		if (c == -1) {
-			if (optind < argc) {
-				LOGP(DGTPHUB, LOGL_FATAL,
-				     "Excess commandline arguments ('%s').\n",
-				     argv[optind]);
-				exit(2);
-			}
-			break;
-		}
-
-		switch (c) {
-		case 'h':
-			//print_usage();
-			print_help(ccfg);
-			exit(0);
-		case 's':
-			log_set_use_color(osmo_stderr_target, 0);
-			break;
-		case 'd':
-			if (strcmp("list", optarg) == 0) {
-				list_categories();
-				exit(0);
-			} else
-				log_parse_category_mask(osmo_stderr_target, optarg);
-			break;
-		case 'D':
-			ccfg->daemonize = 1;
-			break;
-		case 'c':
-			ccfg->config_file = optarg;
-			break;
-		case 'T':
-			log_set_print_timestamp(osmo_stderr_target, 1);
-			break;
-		case 'e':
-			log_set_log_level(osmo_stderr_target, atoi(optarg));
-			break;
-		case 'r':
-			ccfg->restart_counter_file = optarg;
-			break;
-		default:
-			LOGP(DGTPHUB, LOGL_FATAL, "Invalid command line argument, abort.\n");
-			exit(1);
-			break;
-		}
-	}
-}
-
-int main(int argc, char **argv)
-{
-	int rc;
-
-	struct cmdline_cfg _ccfg;
-	struct cmdline_cfg *ccfg = &_ccfg;
-	memset(ccfg, '\0', sizeof(*ccfg));
-	ccfg->config_file = "./gtphub.conf";
-	ccfg->restart_counter_file = "./gtphub_restart_count";
-
-	struct gtphub_cfg _cfg;
-	struct gtphub_cfg *cfg = &_cfg;
-	memset(cfg, '\0', sizeof(*cfg));
-
-	struct gtphub _hub;
-	struct gtphub *hub = &_hub;
-
-	osmo_gtphub_ctx = talloc_named_const(NULL, 0, "osmo_gtphub");
-	msgb_talloc_ctx_init(osmo_gtphub_ctx, 0);
-
-	signal(SIGINT, &signal_handler);
-	signal(SIGTERM, &signal_handler);
-	signal(SIGABRT, &signal_handler);
-	signal(SIGUSR1, &signal_handler);
-	signal(SIGUSR2, &signal_handler);
-	osmo_init_ignore_signals();
-
-	osmo_init_logging(&gtphub_log_info);
-
-	vty_info.copyright = gtphub_copyright;
-	vty_init(&vty_info);
-	logging_vty_add_cmds(NULL);
-        gtphub_vty_init(hub, cfg);
-
-	rate_ctr_init(osmo_gtphub_ctx);
-
-	handle_options(ccfg, argc, argv);
-
-	rc = gtphub_cfg_read(cfg, ccfg->config_file);
-	if (rc < 0) {
-		LOGP(DGTPHUB, LOGL_FATAL, "Cannot parse config file '%s'\n",
-		     ccfg->config_file);
-		exit(2);
-	}
-
-	/* start telnet after reading config for vty_get_bind_addr() */
-	rc = telnet_init_dynif(osmo_gtphub_ctx, 0, vty_get_bind_addr(),
-			       OSMO_VTY_PORT_GTPHUB);
-	if (rc < 0)
-		exit(1);
-
-	if (gtphub_start(hub, cfg,
-			 next_restart_count(ccfg->restart_counter_file))
-	    != 0)
-		return -1;
-
-	log_cfg(cfg);
-
-	if (ccfg->daemonize) {
-		rc = osmo_daemonize();
-		if (rc < 0) {
-			LOGP(DGTPHUB, LOGL_FATAL, "Error during daemonize");
-			exit(1);
-		}
-	}
-
-	while (1) {
-		rc = osmo_select_main(0);
-		if (rc < 0)
-			exit(3);
-	}
-
-	/* not reached */
-	exit(0);
-}
diff --git a/src/gprs/gtphub_sock.c b/src/gprs/gtphub_sock.c
deleted file mode 100644
index 60bebaa..0000000
--- a/src/gprs/gtphub_sock.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/* GTP Hub Implementation */
-
-/* (C) 2015 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- * All Rights Reserved
- *
- * gtphub_sock.c.
- *
- * This file is kept separate so that these functions can be wrapped for
- * gtphub_test.c. When a function and its callers are in the same compilational
- * unit, the wrappability may be optimized away.
- *
- * 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/>.
- */
-
-#include <openbsc/gtphub.h>
-#include <openbsc/debug.h>
-
-/* Convenience makro, note: only within this C file. */
-#define LOG(level, fmt, args...) \
-	LOGP(DGTPHUB, level, fmt, ##args)
-
-int gtphub_write(const struct osmo_fd *to,
-		 const struct osmo_sockaddr *to_addr,
-		 const uint8_t *buf, size_t buf_len)
-{
-	errno = 0;
-	ssize_t sent = sendto(to->fd, buf, buf_len, 0,
-			      (struct sockaddr*)&to_addr->a, to_addr->l);
-	LOG(LOGL_DEBUG, "to %s\n", osmo_sockaddr_to_str(to_addr));
-
-	if (sent == -1) {
-		LOG(LOGL_ERROR, "error: %s\n", strerror(errno));
-		return -EINVAL;
-	}
-
-	if (sent != buf_len)
-		LOG(LOGL_ERROR, "sent(%d) != data_len(%d)\n",
-		    (int)sent, (int)buf_len);
-	else
-		LOG(LOGL_DEBUG, "Sent %d: %s%s\n",
-		    (int)sent,
-		    osmo_hexdump(buf, sent > 1000? 1000 : sent),
-		    sent > 1000 ? "..." : "");
-
-	return 0;
-}
-
diff --git a/src/gprs/gtphub_vty.c b/src/gprs/gtphub_vty.c
deleted file mode 100644
index a30ad2a..0000000
--- a/src/gprs/gtphub_vty.c
+++ /dev/null
@@ -1,613 +0,0 @@
-/* (C) 2015 by sysmocom s.f.m.c. GmbH
- * 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/>.
- *
- */
-
-#include <string.h>
-#include <inttypes.h>
-
-#include <ares.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/vty/command.h>
-#include <osmocom/vty/misc.h>
-
-#include <openbsc/vty.h>
-#include <openbsc/gtphub.h>
-
-/* TODO split GRX ares from sgsn into a separate struct and allow use without
- * globals. */
-#include <openbsc/sgsn.h>
-extern struct sgsn_instance *sgsn;
-
-static struct gtphub *g_hub = 0;
-static struct gtphub_cfg *g_cfg = 0;
-
-static struct cmd_node gtphub_node = {
-	GTPHUB_NODE,
-	"%s(config-gtphub)# ",
-	1,
-};
-
-#define GTPH_DEFAULT_CONTROL_PORT 2123
-#define GTPH_DEFAULT_USER_PORT 2152
-
-static void write_addrs(struct vty *vty, const char *name,
-			struct gtphub_cfg_addr *c, struct gtphub_cfg_addr *u)
-{
-	if ((c->port == GTPH_DEFAULT_CONTROL_PORT)
-	    && (u->port == GTPH_DEFAULT_USER_PORT)
-	    && (strcmp(c->addr_str, u->addr_str) == 0)) {
-		/* Default port numbers and same IP address: write "short"
-		 * variant. */
-		vty_out(vty, " %s %s%s",
-			name,
-			c->addr_str,
-			VTY_NEWLINE);
-		return;
-	}
-
-	vty_out(vty, " %s ctrl %s %d user %s %d%s",
-		name,
-		c->addr_str, (int)c->port,
-		u->addr_str, (int)u->port,
-		VTY_NEWLINE);
-
-	struct ares_addr_node *server;
-	for (server = sgsn->ares_servers; server; server = server->next)
-		vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
-}
-
-static int config_write_gtphub(struct vty *vty)
-{
-	vty_out(vty, "gtphub%s", VTY_NEWLINE);
-
-	write_addrs(vty, "bind-to-sgsns",
-		    &g_cfg->to_gsns[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].bind,
-		    &g_cfg->to_gsns[GTPH_SIDE_SGSN][GTPH_PLANE_USER].bind);
-
-	write_addrs(vty, "bind-to-ggsns",
-		    &g_cfg->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].bind,
-		    &g_cfg->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_USER].bind);
-
-	if (g_cfg->sgsn_use_sender) {
-		vty_out(vty, "sgsn-use-sender%s", VTY_NEWLINE);
-	}
-
-	if (g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].addr_str) {
-		write_addrs(vty, "sgsn-proxy",
-			    &g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL],
-			    &g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_USER]);
-	}
-
-	if (g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].addr_str) {
-		write_addrs(vty, "ggsn-proxy",
-			    &g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL],
-			    &g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_USER]);
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gtphub, cfg_gtphub_cmd,
-      "gtphub",
-      "Configure the GTP hub\n")
-{
-	vty->node = GTPHUB_NODE;
-	return CMD_SUCCESS;
-}
-
-#define BIND_ARGS  "ctrl ADDR <0-65535> user ADDR <0-65535>"
-#define BIND_DOCS  \
-	"Set GTP-C bind\n" \
-	"GTP-C local IP address (v4 or v6)\n" \
-	"GTP-C local port\n" \
-	"Set GTP-U bind\n" \
-	"GTP-U local IP address (v4 or v6)\n" \
-	"GTP-U local port\n"
-
-
-DEFUN(cfg_gtphub_bind_to_sgsns_short, cfg_gtphub_bind_to_sgsns_short_cmd,
-	"bind-to-sgsns ADDR",
-	"GTP Hub Parameters\n"
-	"Set the local bind address to listen for SGSNs, for both GTP-C and GTP-U\n"
-	"Local IP address (v4 or v6)\n"
-	)
-{
-	int i;
-	for_each_plane(i)
-		g_cfg->to_gsns[GTPH_SIDE_SGSN][i].bind.addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
-	g_cfg->to_gsns[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].bind.port = GTPH_DEFAULT_CONTROL_PORT;
-	g_cfg->to_gsns[GTPH_SIDE_SGSN][GTPH_PLANE_USER].bind.port = GTPH_DEFAULT_USER_PORT;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gtphub_bind_to_ggsns_short, cfg_gtphub_bind_to_ggsns_short_cmd,
-	"bind-to-ggsns ADDR",
-	"GTP Hub Parameters\n"
-	"Set the local bind address to listen for GGSNs, for both GTP-C and GTP-U\n"
-	"Local IP address (v4 or v6)\n"
-	)
-{
-	int i;
-	for_each_plane(i)
-		g_cfg->to_gsns[GTPH_SIDE_GGSN][i].bind.addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
-	g_cfg->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].bind.port = GTPH_DEFAULT_CONTROL_PORT;
-	g_cfg->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_USER].bind.port = GTPH_DEFAULT_USER_PORT;
-	return CMD_SUCCESS;
-}
-
-
-static int handle_binds(struct gtphub_cfg_bind *b, const char **argv)
-{
-	b[GTPH_PLANE_CTRL].bind.addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
-	b[GTPH_PLANE_CTRL].bind.port = atoi(argv[1]);
-	b[GTPH_PLANE_USER].bind.addr_str = talloc_strdup(tall_vty_ctx, argv[2]);
-	b[GTPH_PLANE_USER].bind.port = atoi(argv[3]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gtphub_bind_to_sgsns, cfg_gtphub_bind_to_sgsns_cmd,
-	"bind-to-sgsns " BIND_ARGS,
-	"GTP Hub Parameters\n"
-	"Set the local bind addresses and ports to listen for SGSNs\n"
-	BIND_DOCS
-	)
-{
-	return handle_binds(g_cfg->to_gsns[GTPH_SIDE_SGSN], argv);
-}
-
-DEFUN(cfg_gtphub_bind_to_ggsns, cfg_gtphub_bind_to_ggsns_cmd,
-	"bind-to-ggsns " BIND_ARGS,
-	"GTP Hub Parameters\n"
-	"Set the local bind addresses and ports to listen for GGSNs\n"
-	BIND_DOCS
-	)
-{
-	return handle_binds(g_cfg->to_gsns[GTPH_SIDE_GGSN], argv);
-}
-
-DEFUN(cfg_gtphub_ggsn_proxy_short, cfg_gtphub_ggsn_proxy_short_cmd,
-	"ggsn-proxy ADDR",
-	"GTP Hub Parameters\n"
-	"Redirect all GGSN bound traffic to default ports on this address (another gtphub)\n"
-	"Remote IP address (v4 or v6)\n"
-	)
-{
-	g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
-	g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].port = GTPH_DEFAULT_CONTROL_PORT;
-	g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_USER].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
-	g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_USER].port = GTPH_DEFAULT_USER_PORT;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gtphub_ggsn_proxy, cfg_gtphub_ggsn_proxy_cmd,
-	"ggsn-proxy " BIND_ARGS,
-	"GTP Hub Parameters\n"
-	"Redirect all GGSN bound traffic to these addresses and ports (another gtphub)\n"
-	BIND_DOCS
-	)
-{
-	g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
-	g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].port = atoi(argv[1]);
-	g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_USER].addr_str = talloc_strdup(tall_vty_ctx, argv[2]);
-	g_cfg->proxy[GTPH_SIDE_GGSN][GTPH_PLANE_USER].port = atoi(argv[3]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gtphub_sgsn_proxy_short, cfg_gtphub_sgsn_proxy_short_cmd,
-	"sgsn-proxy ADDR",
-	"GTP Hub Parameters\n"
-	"Redirect all SGSN bound traffic to default ports on this address (another gtphub)\n"
-	"Remote IP address (v4 or v6)\n"
-	)
-{
-	g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
-	g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].port = GTPH_DEFAULT_CONTROL_PORT;
-	g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_USER].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
-	g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_USER].port = GTPH_DEFAULT_USER_PORT;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gtphub_sgsn_proxy, cfg_gtphub_sgsn_proxy_cmd,
-	"sgsn-proxy " BIND_ARGS,
-	"GTP Hub Parameters\n"
-	"Redirect all SGSN bound traffic to these addresses and ports (another gtphub)\n"
-	BIND_DOCS
-	)
-{
-	g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
-	g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].port = atoi(argv[1]);
-	g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_USER].addr_str = talloc_strdup(tall_vty_ctx, argv[2]);
-	g_cfg->proxy[GTPH_SIDE_SGSN][GTPH_PLANE_USER].port = atoi(argv[3]);
-	return CMD_SUCCESS;
-}
-
-
-#define SGSN_USE_SENDER_STR \
-	"Ignore SGSN's Address IEs, use sender address and port (useful over NAT)\n"
-
-DEFUN(cfg_gtphub_sgsn_use_sender,
-      cfg_gtphub_sgsn_use_sender_cmd,
-      "sgsn-use-sender",
-      SGSN_USE_SENDER_STR)
-{
-	g_cfg->sgsn_use_sender = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gtphub_no_sgsn_use_sender,
-      cfg_gtphub_no_sgsn_use_sender_cmd,
-      "no sgsn-use-sender",
-      NO_STR SGSN_USE_SENDER_STR)
-{
-	g_cfg->sgsn_use_sender = 0;
-	return CMD_SUCCESS;
-}
-
-
-/* Copied from sgsn_vty.h */
-DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
-	"grx-dns-add A.B.C.D",
-	"Add DNS server\nIPv4 address\n")
-{
-	struct ares_addr_node *node = talloc_zero(tall_bsc_ctx, struct ares_addr_node);
-	node->family = AF_INET;
-	inet_aton(argv[0], &node->addr.addr4);
-
-	node->next = sgsn->ares_servers;
-	sgsn->ares_servers = node;
-	return CMD_SUCCESS;
-}
-
-
-static void show_bind_stats_all(struct vty *vty)
-{
-	int plane_idx;
-	for_each_plane(plane_idx) {
-		vty_out(vty, "- %s Plane:%s",
-			gtphub_plane_idx_names[plane_idx], VTY_NEWLINE);
-
-		int side_idx;
-		for_each_side(side_idx) {
-			struct gtphub_bind *b = &g_hub->to_gsns[side_idx][plane_idx];
-			vty_out(vty, "  - local addr to/from %ss: %s port %d%s",
-				gtphub_side_idx_names[side_idx],
-				gsn_addr_to_str(&b->local_addr), (int)b->local_port,
-				VTY_NEWLINE);
-			vty_out_rate_ctr_group(vty, "    ", b->counters_io);
-		}
-	}
-}
-
-static void show_tunnel_stats(struct vty *vty, struct gtphub_tunnel *tun)
-{
-	int plane_idx;
-	for_each_plane(plane_idx) {
-		vty_out(vty, "- %s Plane:%s",
-			gtphub_plane_idx_names[plane_idx], VTY_NEWLINE);
-
-		int side_idx;
-		for_each_side(side_idx) {
-			struct gtphub_tunnel_endpoint *te = &tun->endpoint[side_idx][plane_idx];
-			vty_out(vty, "  - to/from %s:%s",
-				gtphub_side_idx_names[side_idx],
-				VTY_NEWLINE);
-			vty_out_rate_ctr_group(vty, "    ", te->counters_io);
-		}
-	}
-}
-
-static void show_peer_summary(struct vty *vty, const char *prefix,
-			      int side_idx, int plane_idx,
-			      struct gtphub_peer *p, int with_io_stats)
-{
-	struct gtphub_peer_addr *pa;
-	int p2l = strlen(prefix) + 4 + 1;
-	char prefix2[p2l];
-	memset(prefix2, ' ', p2l - 1);
-	prefix2[p2l - 1] = '\0';
-
-	if (with_io_stats) {
-		llist_for_each_entry(pa, &p->addresses, entry) {
-			vty_out(vty, "%s- %s %s %s%s", prefix,
-				gtphub_side_idx_names[side_idx],
-				gtphub_plane_idx_names[plane_idx],
-				gsn_addr_to_str(&pa->addr),
-				VTY_NEWLINE);
-
-
-			struct gtphub_peer_port *pp;
-			llist_for_each_entry(pp, &pa->ports, entry) {
-				vty_out(vty, "%s  Port %" PRIu16 "%s", prefix, pp->port, VTY_NEWLINE);
-				vty_out_rate_ctr_group(vty, prefix2, pp->counters_io);
-			}
-		}
-	} else {
-		llist_for_each_entry(pa, &p->addresses, entry) {
-			vty_out(vty, "%s- %s %s %s", prefix,
-				gtphub_side_idx_names[side_idx],
-				gtphub_plane_idx_names[plane_idx],
-				gsn_addr_to_str(&pa->addr));
-			struct gtphub_peer_port *pp;
-			llist_for_each_entry(pp, &pa->ports, entry) {
-				vty_out(vty, ":%" PRIu16, pp->port);
-			}
-			vty_out(vty, VTY_NEWLINE);
-		}
-	}
-}
-
-static void show_peers_summary(struct vty *vty)
-{
-	int side_idx;
-	int plane_idx;
-
-	int count[GTPH_SIDE_N][GTPH_PLANE_N] = {{0}};
-
-	for_each_side(side_idx) {
-		for_each_plane(plane_idx) {
-			struct gtphub_peer *p;
-			llist_for_each_entry(p, &g_hub->to_gsns[side_idx][plane_idx].peers, entry) {
-				count[side_idx][plane_idx] ++;
-			}
-		}
-	}
-
-	vty_out(vty, "Peers Count:%s", VTY_NEWLINE);
-	for_each_side_and_plane(side_idx, plane_idx) {
-		vty_out(vty, "  %s %s peers: %d%s",
-			gtphub_side_idx_names[side_idx],
-			gtphub_plane_idx_names[plane_idx],
-			count[side_idx][plane_idx],
-			VTY_NEWLINE);
-	}
-}
-
-static void show_peers_all(struct vty *vty, int with_io_stats)
-{
-	int side_idx;
-	int plane_idx;
-
-	int count[GTPH_SIDE_N][GTPH_PLANE_N] = {{0}};
-
-	vty_out(vty, "All Peers%s%s",
-		with_io_stats? " with I/O stats" : "",
-		VTY_NEWLINE);
-	for_each_side(side_idx) {
-		vty_out(vty, "- %s%s", gtphub_side_idx_names[side_idx], VTY_NEWLINE);
-		for_each_plane(plane_idx) {
-			struct gtphub_peer *p;
-			llist_for_each_entry(p, &g_hub->to_gsns[side_idx][plane_idx].peers, entry) {
-				count[side_idx][plane_idx] ++;
-				show_peer_summary(vty, "    ", side_idx, plane_idx, p, with_io_stats);
-			}
-		}
-	}
-	for_each_side_and_plane(side_idx, plane_idx) {
-		vty_out(vty, "%s %s peers: %d%s",
-			gtphub_side_idx_names[side_idx],
-			gtphub_plane_idx_names[plane_idx],
-			count[side_idx][plane_idx],
-			VTY_NEWLINE);
-	}
-}
-
-
-static void show_tunnels_summary(struct vty *vty)
-{
-	time_t now = gtphub_now();
-
-	const int w = 36;
-	int max_expiry = g_hub->expire_slowly.expiry_in_seconds;
-	float seconds_per_step = ((float)max_expiry) / w;
-
-	/* Print TEI mapping expiry in an ASCII histogram, like:
-	     TEI map summary
-	       Legend:  '_'=0  '.'<=1%  ':'<=2%  '|'<=10%  '#'>10%  (10.0 m/step)
-	       CTRL: 30 mappings, valid for 360m[#  :.    |   .    :  .              ]1m
-	       USER: 30 mappings, valid for 360m[#  :.    |   .    :  .              ]1m
-	       4 TEI mappings in total, last expiry in 359.4 min
-	 */
-	vty_out(vty,
-		"Tunnels summary%s"
-		"  Legend:  ' '=0  '.'<=1%%  ':'<=2%%  '|'<=10%%  '#'>10%%  (%.1f m/step)%s",
-		VTY_NEWLINE,
-		seconds_per_step / 60.,
-		VTY_NEWLINE);
-
-	int last_expiry = 0;
-
-	unsigned int count = 0;
-
-	int histogram[w];
-	memset(histogram, 0, sizeof(histogram));
-
-	struct gtphub_tunnel *t;
-	llist_for_each_entry(t, &g_hub->tunnels, entry) {
-		count ++;
-		int expiry = t->expiry_entry.expiry - now;
-		last_expiry = (last_expiry > expiry) ? last_expiry : expiry;
-
-		int hi = ((float)expiry) / seconds_per_step;
-		if (hi < 0)
-			hi = 0;
-		if (hi > (w - 1))
-			hi = w - 1;
-		histogram[hi] ++;
-	}
-
-	vty_out(vty,
-		"  %u tunnels, valid for %dm[",
-		count, max_expiry / 60);
-
-	int i;
-	for (i = w - 1; i >= 0; i--) {
-		char c;
-		int val = histogram[i];
-		int percent = 100. * val / count;
-		if (!val)
-			c = ' ';
-		else if (percent <= 1)
-			c = '.';
-		else if (percent <= 2)
-			c = ':';
-		else if (percent <= 10)
-			c = '|';
-		else c = '#';
-		vty_out(vty, "%c", c);
-	}
-	vty_out(vty, "]1m%s", VTY_NEWLINE);
-
-	vty_out(vty, "  last expiry in %.1f min%s",
-		((float)last_expiry) / 60.,
-		VTY_NEWLINE);
-}
-
-static void show_tunnels_all(struct vty *vty, int with_io_stats)
-{
-	time_t now = gtphub_now();
-
-	vty_out(vty, "All tunnels%s:%s"
-		"Legend: TEI=<hex>: SGSN <-> GGSN (expiry in minutes), with each:%s"
-		"        <IP-Ctrl>[/<IP-User>] (TEI C=<TEI-Ctrl-hex> U=<TEI-User-hex>)%s",
-		with_io_stats? "with I/O stats" : "",
-		VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
-
-	unsigned int count = 0;
-	unsigned int incomplete = 0;
-	struct gtphub_tunnel *tun;
-	llist_for_each_entry(tun, &g_hub->tunnels, entry) {
-		vty_out(vty,
-			"%s (expiry in %dm)%s",
-			gtphub_tunnel_str(tun),
-			(int)((tun->expiry_entry.expiry - now) / 60),
-			VTY_NEWLINE);
-		count ++;
-		if (!gtphub_tunnel_complete(tun))
-			incomplete ++;
-		if (with_io_stats)
-			show_tunnel_stats(vty, tun);
-	}
-	vty_out(vty, "Total: %u tunnels (of which %u incomplete)%s",
-		count, incomplete, VTY_NEWLINE);
-}
-
-#define SHOW_GTPHUB_STRS   SHOW_STR "Show info on running GTP hub\n"
-#define SHOW_GTPHUB_PEERS_STRS  SHOW_GTPHUB_STRS "Active peers\n"
-#define SHOW_GTPHUB_TUNS_STRS  SHOW_GTPHUB_STRS "Active tunnels\n"
-
-DEFUN(show_gtphub_peers_summary, show_gtphub_peers_summary_cmd, "show gtphub peers summary",
-      SHOW_GTPHUB_PEERS_STRS "Summary of all peers\n")
-{
-	show_peers_summary(vty);
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_gtphub_peers_list, show_gtphub_peers_list_cmd, "show gtphub peers list",
-      SHOW_GTPHUB_PEERS_STRS "List all peers\n")
-{
-	show_peers_all(vty, 0);
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_gtphub_peers_stats, show_gtphub_peers_stats_cmd, "show gtphub peers stats",
-      SHOW_GTPHUB_PEERS_STRS "List all peers with I/O stats\n")
-{
-	show_peers_all(vty, 1);
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_gtphub_tunnels_summary, show_gtphub_tunnels_summary_cmd, "show gtphub tunnels summary",
-      SHOW_GTPHUB_TUNS_STRS "Summary of all tunnels\n")
-{
-	show_tunnels_summary(vty);
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_gtphub_tunnels_list, show_gtphub_tunnels_list_cmd, "show gtphub tunnels list",
-      SHOW_GTPHUB_TUNS_STRS "List all tunnels\n")
-{
-	show_tunnels_all(vty, 0);
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_gtphub_tunnels_stats, show_gtphub_tunnels_stats_cmd, "show gtphub tunnels stats",
-      SHOW_GTPHUB_TUNS_STRS "List all tunnels with I/O stats\n")
-{
-	show_tunnels_all(vty, 1);
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_gtphub, show_gtphub_cmd, "show gtphub all",
-      SHOW_GTPHUB_STRS "Summarize everything about the GTP hub\n")
-{
-	show_bind_stats_all(vty);
-	show_peers_summary(vty);
-	show_tunnels_summary(vty);
-	return CMD_SUCCESS;
-}
-
-
-int gtphub_vty_init(struct gtphub *global_hub, struct gtphub_cfg *global_cfg)
-{
-	g_hub = global_hub;
-	g_cfg = global_cfg;
-
-	install_element_ve(&show_gtphub_cmd);
-	install_element_ve(&show_gtphub_peers_summary_cmd);
-	install_element_ve(&show_gtphub_peers_list_cmd);
-	install_element_ve(&show_gtphub_peers_stats_cmd);
-	install_element_ve(&show_gtphub_tunnels_summary_cmd);
-	install_element_ve(&show_gtphub_tunnels_list_cmd);
-	install_element_ve(&show_gtphub_tunnels_stats_cmd);
-
-	install_element(CONFIG_NODE, &cfg_gtphub_cmd);
-	install_node(&gtphub_node, config_write_gtphub);
-	vty_install_default(GTPHUB_NODE);
-
-	install_element(GTPHUB_NODE, &cfg_gtphub_bind_to_sgsns_short_cmd);
-	install_element(GTPHUB_NODE, &cfg_gtphub_bind_to_sgsns_cmd);
-	install_element(GTPHUB_NODE, &cfg_gtphub_bind_to_ggsns_short_cmd);
-	install_element(GTPHUB_NODE, &cfg_gtphub_bind_to_ggsns_cmd);
-	install_element(GTPHUB_NODE, &cfg_gtphub_ggsn_proxy_short_cmd);
-	install_element(GTPHUB_NODE, &cfg_gtphub_ggsn_proxy_cmd);
-	install_element(GTPHUB_NODE, &cfg_gtphub_sgsn_proxy_short_cmd);
-	install_element(GTPHUB_NODE, &cfg_gtphub_sgsn_proxy_cmd);
-	install_element(GTPHUB_NODE, &cfg_gtphub_sgsn_use_sender_cmd);
-	install_element(GTPHUB_NODE, &cfg_gtphub_no_sgsn_use_sender_cmd);
-	install_element(GTPHUB_NODE, &cfg_grx_ggsn_cmd);
-
-	return 0;
-}
-
-int gtphub_cfg_read(struct gtphub_cfg *cfg, const char *config_file)
-{
-	int rc;
-
-	rc = vty_read_config_file(config_file, NULL);
-	if (rc < 0) {
-		fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
-		return rc;
-	}
-
-	return 0;
-}
diff --git a/src/gprs/osmo_sgsn.cfg b/src/gprs/osmo_sgsn.cfg
deleted file mode 100644
index c4c9ec1..0000000
--- a/src/gprs/osmo_sgsn.cfg
+++ /dev/null
@@ -1,23 +0,0 @@
-!
-! Osmocom SGSN (0.9.0.474-0ede2) configuration saved from vty
-!!
-!
-line vty
- no login
-!
-sgsn
- gtp local-ip 192.168.100.11
- ggsn 0 remote-ip 192.168.100.239
- ggsn 0 gtp-version 1
-ns
- timer tns-block 3
- timer tns-block-retries 3
- timer tns-reset 3
- timer tns-reset-retries 3
- timer tns-test 30
- timer tns-alive 3
- timer tns-alive-retries 10
- encapsulation udp local-ip 192.168.100.11
- encapsulation udp local-port 23000
- encapsulation framerelay-gre enabled 0
-bssgp
diff --git a/src/gprs/sgsn_ares.c b/src/gprs/sgsn_ares.c
deleted file mode 100644
index d94d184..0000000
--- a/src/gprs/sgsn_ares.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/* C-ARES DNS resolver integration */
-
-/*
- * (C) 2015 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/>.
- *
- */
-
-#include <openbsc/sgsn.h>
-#include <openbsc/debug.h>
-
-#include <netdb.h>
-
-struct cares_event_fd {
-	struct llist_head head;
-	struct osmo_fd fd;
-};
-
-struct cares_cb_data {
-	ares_host_callback cb;
-	void *data;
-};
-
-static void osmo_ares_reschedule(struct sgsn_instance *sgsn);
-static void ares_cb(void *_arg, int status, int timeouts, struct hostent *hostent)
-{
-	struct cares_cb_data *arg = _arg;
-
-	arg->cb(arg->data, status, timeouts, hostent);
-	osmo_ares_reschedule(sgsn);
-	talloc_free(arg);
-}
-
-static int ares_osmo_fd_cb(struct osmo_fd *fd, unsigned int what)
-{
-	LOGP(DGPRS, LOGL_DEBUG, "C-ares fd(%d) ready(%d)\n", fd->fd, what);
-
-	ares_process_fd(sgsn->ares_channel,
-			(what & BSC_FD_READ) ? fd->fd : ARES_SOCKET_BAD,
-			(what & BSC_FD_WRITE) ? fd->fd : ARES_SOCKET_BAD);
-	osmo_ares_reschedule(sgsn);
-	return 0;
-}
-
-static void ares_timeout_cb(void *data)
-{
-	struct sgsn_instance *sgsn = data;
-
-	LOGP(DGPRS, LOGL_DEBUG, "C-ares triggering timeout\n");
-	ares_process_fd(sgsn->ares_channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
-	osmo_ares_reschedule(sgsn);
-}
-
-static void osmo_ares_reschedule(struct sgsn_instance *sgsn)
-{
-	struct timeval *timeout, tv;
-
-	osmo_timer_del(&sgsn->ares_timer);
-	timeout = ares_timeout(sgsn->ares_channel, NULL, &tv);
-	if (timeout) {
-		LOGP(DGPRS, LOGL_DEBUG, "C-ares scheduling timeout %llu.%llu\n",
-			(unsigned long long) tv.tv_sec,
-			(unsigned long long) tv.tv_usec);
-		osmo_timer_setup(&sgsn->ares_timer, ares_timeout_cb, sgsn);
-		osmo_timer_schedule(&sgsn->ares_timer, tv.tv_sec, tv.tv_usec);
-	}
-}
-
-static void setup_ares_osmo_fd(void *data, int fd, int read, int write)
-{
-	struct cares_event_fd *ufd, *tmp;
-
-	/* delete the entry */
-	if (read == 0 && write == 0) {
-		llist_for_each_entry_safe(ufd, tmp, &sgsn->ares_fds, head) {
-			if (ufd->fd.fd != fd)
-				continue;
-
-			LOGP(DGPRS, LOGL_DEBUG,
-				"Removing C-ares watched fd (%d)\n", fd);
-			osmo_fd_unregister(&ufd->fd);
-			llist_del(&ufd->head);
-			talloc_free(ufd);
-			return;
-		}
-	}
-
-	/* Search for the fd or create a new one */
-	llist_for_each_entry(ufd, &sgsn->ares_fds, head) {
-		if (ufd->fd.fd != fd)
-			continue;
-
-		LOGP(DGPRS, LOGL_DEBUG, "Updating C-ares fd (%d)\n", fd);
-		goto update_fd;
-	}
-
-	LOGP(DGPRS, LOGL_DEBUG, "Registering C-ares fd (%d)\n", fd);
-	ufd = talloc_zero(tall_bsc_ctx, struct cares_event_fd);
-	ufd->fd.fd = fd;
-	ufd->fd.cb = ares_osmo_fd_cb;
-	ufd->fd.data = data;
-	if (osmo_fd_register(&ufd->fd) != 0)
-		LOGP(DGPRS, LOGL_ERROR, "Failed to register C-ares fd (%d)\n", fd);
-	llist_add(&ufd->head, &sgsn->ares_fds);
-
-update_fd:
-	if (read)
-		ufd->fd.when |= BSC_FD_READ;
-	else
-		ufd->fd.when &= ~BSC_FD_READ;
-
-	if (write)
-		ufd->fd.when |= BSC_FD_WRITE;
-	else
-		ufd->fd.when &= ~BSC_FD_WRITE;
-
-	osmo_ares_reschedule(sgsn);
-}
-
-int sgsn_ares_query(struct sgsn_instance *sgsn, const char *name,
-			ares_host_callback cb, void *data)
-{
-	struct cares_cb_data *cb_data;
-
-	cb_data = talloc_zero(tall_bsc_ctx, struct cares_cb_data);
-	cb_data->cb = cb;
-	cb_data->data = data;
-	ares_gethostbyname(sgsn->ares_channel, name, AF_INET, ares_cb, cb_data);
-	osmo_ares_reschedule(sgsn);
-	return 0;
-}
-
-int sgsn_ares_init(struct sgsn_instance *sgsn)
-{
-	struct ares_options options;
-	int optmask;
-	int rc;
-
-	INIT_LLIST_HEAD(&sgsn->ares_fds);
-	memset(&options, 0, sizeof(options));
-	options.sock_state_cb = setup_ares_osmo_fd;
-	options.sock_state_cb_data = sgsn;
-
-	optmask = ARES_OPT_FLAGS | ARES_OPT_SOCK_STATE_CB | ARES_OPT_DOMAINS;
-
-	if (sgsn->ares_servers)
-		optmask |= ARES_OPT_SERVERS;
-
-	ares_library_init(ARES_LIB_INIT_ALL);
-	rc = ares_init_options(&sgsn->ares_channel, &options, optmask);
-	if (rc != ARES_SUCCESS)
-		return rc;
-
-	if (sgsn->ares_servers)
-		rc = ares_set_servers(sgsn->ares_channel, sgsn->ares_servers);
-
-	return rc;
-}
-
-osmo_static_assert(ARES_SUCCESS == 0, ares_success_zero);
diff --git a/src/gprs/sgsn_auth.c b/src/gprs/sgsn_auth.c
deleted file mode 100644
index a64339c..0000000
--- a/src/gprs/sgsn_auth.c
+++ /dev/null
@@ -1,312 +0,0 @@
-/* MS authorization and subscriber data handling */
-
-/* (C) 2009-2010 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/>.
- *
- */
-
-#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
-#include <osmocom/core/utils.h>
-#include <openbsc/sgsn.h>
-#include <openbsc/gprs_sgsn.h>
-#include <openbsc/gprs_gmm.h>
-#include <openbsc/gprs_subscriber.h>
-#include <openbsc/debug.h>
-
-const struct value_string auth_state_names[] = {
-	{ SGSN_AUTH_ACCEPTED,	"accepted"},
-	{ SGSN_AUTH_REJECTED,	"rejected"},
-	{ SGSN_AUTH_UNKNOWN,	"unknown"},
-	{ SGSN_AUTH_AUTHENTICATE, "authenticate" },
-	{ SGSN_AUTH_UMTS_RESYNC, "UMTS-resync" },
-	{ 0, NULL }
-};
-
-const struct value_string *sgsn_auth_state_names = auth_state_names;
-
-void sgsn_auth_init(void)
-{
-	INIT_LLIST_HEAD(&sgsn->cfg.imsi_acl);
-}
-
-/* temporary IMSI ACL hack */
-struct imsi_acl_entry *sgsn_acl_lookup(const char *imsi, struct sgsn_config *cfg)
-{
-	struct imsi_acl_entry *acl;
-	llist_for_each_entry(acl, &cfg->imsi_acl, list) {
-		if (!strcmp(imsi, acl->imsi))
-			return acl;
-	}
-	return NULL;
-}
-
-int sgsn_acl_add(const char *imsi, struct sgsn_config *cfg)
-{
-	struct imsi_acl_entry *acl;
-
-	if (sgsn_acl_lookup(imsi, cfg))
-		return -EEXIST;
-
-	acl = talloc_zero(NULL, struct imsi_acl_entry);
-	if (!acl)
-		return -ENOMEM;
-	osmo_strlcpy(acl->imsi, imsi, sizeof(acl->imsi));
-
-	llist_add(&acl->list, &cfg->imsi_acl);
-
-	return 0;
-}
-
-int sgsn_acl_del(const char *imsi, struct sgsn_config *cfg)
-{
-	struct imsi_acl_entry *acl;
-
-	acl = sgsn_acl_lookup(imsi, cfg);
-	if (!acl)
-		return -ENODEV;
-
-	llist_del(&acl->list);
-	talloc_free(acl);
-
-	return 0;
-}
-
-enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mmctx)
-{
-	char mccmnc[16];
-	int check_net = 0;
-	int check_acl = 0;
-
-	OSMO_ASSERT(mmctx);
-
-	switch (sgsn->cfg.auth_policy) {
-	case SGSN_AUTH_POLICY_OPEN:
-		return SGSN_AUTH_ACCEPTED;
-
-	case SGSN_AUTH_POLICY_CLOSED:
-		check_net = 1;
-		check_acl = 1;
-		break;
-
-	case SGSN_AUTH_POLICY_ACL_ONLY:
-		check_acl = 1;
-		break;
-
-	case SGSN_AUTH_POLICY_REMOTE:
-		if (!mmctx->subscr)
-			return mmctx->auth_state;
-
-		if (mmctx->subscr->flags & GPRS_SUBSCRIBER_UPDATE_PENDING_MASK)
-			return mmctx->auth_state;
-
-		if (sgsn->cfg.require_authentication &&
-		    (!mmctx->is_authenticated ||
-		     mmctx->subscr->sgsn_data->auth_triplets_updated))
-			return SGSN_AUTH_AUTHENTICATE;
-
-		if (mmctx->subscr->authorized)
-			return SGSN_AUTH_ACCEPTED;
-
-		return SGSN_AUTH_REJECTED;
-	}
-
-	if (!strlen(mmctx->imsi)) {
-		LOGMMCTXP(LOGL_NOTICE, mmctx,
-			  "Missing IMSI, authorization state not known\n");
-		return SGSN_AUTH_UNKNOWN;
-	}
-
-	if (check_net) {
-		/* We simply assume that the IMSI exists, as long as it is part
-		 * of 'our' network */
-		snprintf(mccmnc, sizeof(mccmnc), "%03d%02d",
-			 mmctx->ra.mcc, mmctx->ra.mnc);
-		if (strncmp(mccmnc, mmctx->imsi, 5) == 0)
-			return SGSN_AUTH_ACCEPTED;
-	}
-
-	if (check_acl && sgsn_acl_lookup(mmctx->imsi, &sgsn->cfg))
-		return SGSN_AUTH_ACCEPTED;
-
-	return SGSN_AUTH_REJECTED;
-}
-
-/*
- * This function is directly called by e.g. the GMM layer. It returns either
- * after calling sgsn_auth_update directly or after triggering an asynchronous
- * procedure which will call sgsn_auth_update later on.
- */
-int sgsn_auth_request(struct sgsn_mm_ctx *mmctx)
-{
-	struct gprs_subscr *subscr;
-	struct gsm_auth_tuple *at;
-	int need_update_location;
-	int rc;
-
-	LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting authorization\n");
-
-	if (sgsn->cfg.auth_policy != SGSN_AUTH_POLICY_REMOTE) {
-		sgsn_auth_update(mmctx);
-		return 0;
-	}
-
-	need_update_location = sgsn->cfg.require_update_location &&
-		(mmctx->subscr == NULL ||
-		 mmctx->pending_req == GSM48_MT_GMM_ATTACH_REQ);
-
-	/* This has the side effect of registering the subscr with the mmctx */
-	subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
-	gprs_subscr_put(subscr);
-
-	OSMO_ASSERT(mmctx->subscr != NULL);
-
-	if (sgsn->cfg.require_authentication && !mmctx->is_authenticated) {
-		/* Find next tuple */
-		at = sgsn_auth_get_tuple(mmctx, mmctx->auth_triplet.key_seq);
-
-		if (!at) {
-			/* No valid tuple found, request fresh ones */
-			mmctx->auth_triplet.key_seq = GSM_KEY_SEQ_INVAL;
-			LOGMMCTXP(LOGL_INFO, mmctx,
-				  "Requesting authentication tuples\n");
-			rc = gprs_subscr_request_auth_info(mmctx, NULL, NULL);
-			if (rc >= 0)
-				return 0;
-
-			return rc;
-		}
-
-		mmctx->auth_triplet = *at;
-	} else if (need_update_location) {
-		LOGMMCTXP(LOGL_INFO, mmctx,
-			  "Missing information, requesting subscriber data\n");
-		rc = gprs_subscr_request_update_location(mmctx);
-		if (rc >= 0)
-			return 0;
-
-		return rc;
-	}
-
-	sgsn_auth_update(mmctx);
-	return 0;
-}
-
-void sgsn_auth_update(struct sgsn_mm_ctx *mmctx)
-{
-	enum sgsn_auth_state auth_state;
-	struct gprs_subscr *subscr = mmctx->subscr;
-	struct gsm_auth_tuple *at;
-	int gmm_cause;
-
-	auth_state = sgsn_auth_state(mmctx);
-
-	LOGMMCTXP(LOGL_DEBUG, mmctx, "Updating authorization (%s -> %s)\n",
-		  get_value_string(sgsn_auth_state_names, mmctx->auth_state),
-		  get_value_string(sgsn_auth_state_names, auth_state));
-
-	if (auth_state == SGSN_AUTH_UNKNOWN && subscr &&
-	    !(subscr->flags & GPRS_SUBSCRIBER_UPDATE_PENDING_MASK)) {
-		/* Reject requests if gprs_subscr_request_update_location fails */
-		LOGMMCTXP(LOGL_ERROR, mmctx,
-			  "Missing information, authorization not possible\n");
-		auth_state = SGSN_AUTH_REJECTED;
-	}
-
-	if (auth_state == SGSN_AUTH_AUTHENTICATE &&
-	    mmctx->auth_triplet.key_seq == GSM_KEY_SEQ_INVAL) {
-		/* The current tuple is not valid, but we are possibly called
-		 * because new auth tuples have been received */
-		at = sgsn_auth_get_tuple(mmctx, mmctx->auth_triplet.key_seq);
-		if (!at) {
-			LOGMMCTXP(LOGL_ERROR, mmctx,
-				  "Missing auth tuples, authorization not possible\n");
-			auth_state = SGSN_AUTH_REJECTED;
-		} else {
-			mmctx->auth_triplet = *at;
-		}
-	}
-
-	if (mmctx->auth_state == auth_state)
-		return;
-
-	LOGMMCTXP(LOGL_INFO, mmctx, "Got authorization update: state %s -> %s\n",
-		  get_value_string(sgsn_auth_state_names, mmctx->auth_state),
-		  get_value_string(sgsn_auth_state_names, auth_state));
-
-	mmctx->auth_state = auth_state;
-
-	switch (auth_state) {
-	case SGSN_AUTH_AUTHENTICATE:
-		if (subscr)
-			subscr->sgsn_data->auth_triplets_updated = 0;
-
-		gsm0408_gprs_authenticate(mmctx);
-		break;
-	case SGSN_AUTH_ACCEPTED:
-		gsm0408_gprs_access_granted(mmctx);
-		break;
-	case SGSN_AUTH_REJECTED:
-		gmm_cause =
-			subscr ? subscr->sgsn_data->error_cause :
-			SGSN_ERROR_CAUSE_NONE;
-
-		if (subscr && (subscr->flags & GPRS_SUBSCRIBER_CANCELLED) != 0)
-			gsm0408_gprs_access_cancelled(mmctx, gmm_cause);
-		else
-			gsm0408_gprs_access_denied(mmctx, gmm_cause);
-		break;
-	default:
-		break;
-	}
-}
-
-struct gsm_auth_tuple *sgsn_auth_get_tuple(struct sgsn_mm_ctx *mmctx,
-					   unsigned key_seq)
-{
-	unsigned count;
-	unsigned idx;
-	struct gsm_auth_tuple *at = NULL;
-
-	struct sgsn_subscriber_data *sdata;
-
-	if (!mmctx->subscr)
-		return NULL;
-
-	if (key_seq == GSM_KEY_SEQ_INVAL)
-		/* Start with 0 after increment module array size */
-		idx = ARRAY_SIZE(sdata->auth_triplets) - 1;
-	else
-		idx = key_seq;
-
-	sdata = mmctx->subscr->sgsn_data;
-
-	/* Find next tuple */
-	for (count = ARRAY_SIZE(sdata->auth_triplets); count > 0; count--) {
-		idx = (idx + 1) % ARRAY_SIZE(sdata->auth_triplets);
-
-		if (sdata->auth_triplets[idx].key_seq == GSM_KEY_SEQ_INVAL)
-			continue;
-
-		if (sdata->auth_triplets[idx].use_count == 0) {
-			at = &sdata->auth_triplets[idx];
-			at->use_count = 1;
-			return at;
-		}
-	}
-
-	return NULL;
-}
diff --git a/src/gprs/sgsn_cdr.c b/src/gprs/sgsn_cdr.c
deleted file mode 100644
index 16ea9d4..0000000
--- a/src/gprs/sgsn_cdr.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/* GPRS SGSN CDR dumper */
-
-/* (C) 2015 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/>.
- *
- */
-
-#include <openbsc/sgsn.h>
-#include <openbsc/signal.h>
-#include <openbsc/gprs_utils.h>
-#include <openbsc/debug.h>
-#include <osmocom/gsm/apn.h>
-
-#include <openbsc/vty.h>
-
-#include <gtp.h>
-#include <pdp.h>
-
-#include <arpa/inet.h>
-
-#include <time.h>
-
-#include <stdio.h>
-#include <inttypes.h>
-
-/* TODO...avoid going through a global */
-extern struct sgsn_instance *sgsn;
-
-/**
- * The CDR module will generate an entry like:
- *
- * IMSI, # Subscriber IMSI
- * IMEI, # Subscriber IMEI
- * MSISDN, # Subscriber MISDN
- * Charging_Timestamp, # Event start Time
- * Charging_UTC, # Time zone of event start time
- * Duration, # Session DURATION
- * Cell_Id, # CELL_ID
- * Location_Area, # LAC
- * GGSN_ADDR, # GGSN_ADDR
- * SGSN_ADDR, # SGSN_ADDR
- * APNI, # APNI
- * PDP_ADDR, # PDP_ADDR
- * VOL_IN, # VOL_IN in Bytes
- * VOL_OUT, # VOL_OUT in Bytes
- * CAUSE_FOR_TERM, # CAUSE_FOR_TERM
- */
-
-
-static void maybe_print_header(FILE *cdr_file)
-{
-	if (ftell(cdr_file) != 0)
-		return;
-
-	fprintf(cdr_file, "timestamp,imsi,imei,msisdn,cell_id,lac,hlr,event,pdp_duration,ggsn_addr,sgsn_addr,apni,eua_addr,vol_in,vol_out,charging_id\n");
-}
-
-static void cdr_log_mm(struct sgsn_instance *inst, const char *ev,
-			struct sgsn_mm_ctx *mmctx)
-{
-	FILE *cdr_file;
-	struct tm tm;
-	struct timeval tv;
-
-	if (!inst->cfg.cdr.filename)
-		return;
-
-	cdr_file = fopen(inst->cfg.cdr.filename, "a");
-	if (!cdr_file) {
-		LOGP(DGPRS, LOGL_ERROR, "Failed to open %s\n",
-			inst->cfg.cdr.filename);
-		return;
-	}
-
-	maybe_print_header(cdr_file);
-	gettimeofday(&tv, NULL);
-	gmtime_r(&tv.tv_sec, &tm);
-	fprintf(cdr_file, "%04d%02d%02d%02d%02d%02d%03d,%s,%s,%s,%d,%d,%s,%s\n",
-		tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-		tm.tm_hour, tm.tm_min, tm.tm_sec,
-		(int)(tv.tv_usec / 1000),
-		mmctx->imsi,
-		mmctx->imei,
-		mmctx->msisdn,
-		mmctx->gb.cell_id,
-		mmctx->ra.lac,
-		mmctx->hlr,
-		ev);
-
-	fclose(cdr_file);
-}
-
-static void extract_eua(struct ul66_t *eua, char *eua_addr)
-{
-	if (eua->l < 2)
-		return;
-
-	/* there is no addr for ETSI/PPP */
-	if ((eua->v[0] & 0x0F) != 1) {
-		strcpy(eua_addr, "ETSI");
-		return;
-	}
-
-	if (eua->v[1] == 0x21 && eua->l == 6)
-		inet_ntop(AF_INET, &eua->v[2], eua_addr, INET_ADDRSTRLEN);
-	else if (eua->v[1] == 0x57 && eua->l == 18)
-		inet_ntop(AF_INET6, &eua->v[2], eua_addr, INET6_ADDRSTRLEN);
-	else {
-		/* e.g. both IPv4 and IPv6 */
-		strcpy(eua_addr, "Unknown address");
-	}
-}
-
-static void cdr_log_pdp(struct sgsn_instance *inst, const char *ev,
-			struct sgsn_pdp_ctx *pdp)
-{
-	FILE *cdr_file;
-	char apni[(pdp->lib ? pdp->lib->apn_use.l : 0) + 1];
-	char ggsn_addr[INET_ADDRSTRLEN + 1];
-	char sgsn_addr[INET_ADDRSTRLEN + 1];
-	char eua_addr[INET6_ADDRSTRLEN + 1];
-	struct tm tm;
-	struct timeval tv;
-	time_t duration;
-	struct timespec tp;
-
-	if (!inst->cfg.cdr.filename)
-		return;
-
-	memset(apni, 0, sizeof(apni));
-	memset(ggsn_addr, 0, sizeof(ggsn_addr));
-	memset(eua_addr, 0, sizeof(eua_addr));
-
-
-	if (pdp->lib) {
-		osmo_apn_to_str(apni, pdp->lib->apn_use.v, pdp->lib->apn_use.l);
-		inet_ntop(AF_INET, &pdp->lib->hisaddr0.s_addr, ggsn_addr, sizeof(ggsn_addr));
-		extract_eua(&pdp->lib->eua, eua_addr);
-	}
-
-	if (pdp->ggsn)
-		inet_ntop(AF_INET, &pdp->ggsn->gsn->gsnc.s_addr, sgsn_addr, sizeof(sgsn_addr));
-
-	cdr_file = fopen(inst->cfg.cdr.filename, "a");
-	if (!cdr_file) {
-		LOGP(DGPRS, LOGL_ERROR, "Failed to open %s\n",
-			inst->cfg.cdr.filename);
-		return;
-	}
-
-	maybe_print_header(cdr_file);
-
-	clock_gettime(CLOCK_MONOTONIC, &tp);
-	gettimeofday(&tv, NULL);
-
-	/* convert the timestamp to UTC */
-	gmtime_r(&tv.tv_sec, &tm);
-
-	/* Check the duration of the PDP context */
-	duration = tp.tv_sec - pdp->cdr_start.tv_sec;
-
-	fprintf(cdr_file,
-		"%04d%02d%02d%02d%02d%02d%03d,%s,%s,%s,%d,%d,%s,%s,%ld,%s,%s,%s,%s,%" PRIu64 ",%" PRIu64 ",%u\n",
-		tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-		tm.tm_hour, tm.tm_min, tm.tm_sec,
-		(int)(tv.tv_usec / 1000),
-		pdp->mm ? pdp->mm->imsi : "N/A",
-		pdp->mm ? pdp->mm->imei : "N/A",
-		pdp->mm ? pdp->mm->msisdn : "N/A",
-		pdp->mm ? pdp->mm->gb.cell_id : -1,
-		pdp->mm ? pdp->mm->ra.lac : -1,
-		pdp->mm ? pdp->mm->hlr : "N/A",
-		ev,
-		(unsigned long ) duration,
-		ggsn_addr,
-		sgsn_addr,
-		apni,
-		eua_addr,
-		pdp->cdr_bytes_in,
-		pdp->cdr_bytes_out,
-		pdp->cdr_charging_id);
-	fclose(cdr_file);
-}
-
-static void cdr_pdp_timeout(void *_data)
-{
-	struct sgsn_pdp_ctx *pdp = _data;
-	cdr_log_pdp(sgsn, "pdp-periodic", pdp);
-	osmo_timer_schedule(&pdp->cdr_timer, sgsn->cfg.cdr.interval, 0);
-}
-
-static int handle_sgsn_sig(unsigned int subsys, unsigned int signal,
-			void *handler_data, void *_signal_data)
-{
-	struct sgsn_signal_data *signal_data = _signal_data;
-	struct sgsn_instance *inst = handler_data;
-
-	if (subsys != SS_SGSN)
-		return 0;
-
-	switch (signal) {
-	case S_SGSN_ATTACH:
-		cdr_log_mm(inst, "attach", signal_data->mm);
-		break;
-	case S_SGSN_UPDATE:
-		cdr_log_mm(inst, "update", signal_data->mm);
-		break;
-	case S_SGSN_DETACH:
-		cdr_log_mm(inst, "detach", signal_data->mm);
-		break;
-	case S_SGSN_MM_FREE:
-		cdr_log_mm(inst, "free", signal_data->mm);
-		break;
-	case S_SGSN_PDP_ACT:
-		clock_gettime(CLOCK_MONOTONIC, &signal_data->pdp->cdr_start);
-		signal_data->pdp->cdr_charging_id = signal_data->pdp->lib->cid;
-		cdr_log_pdp(inst, "pdp-act", signal_data->pdp);
-		osmo_timer_setup(&signal_data->pdp->cdr_timer, cdr_pdp_timeout,
-				 signal_data->pdp);
-		osmo_timer_schedule(&signal_data->pdp->cdr_timer, inst->cfg.cdr.interval, 0);
-		break;
-	case S_SGSN_PDP_DEACT:
-		cdr_log_pdp(inst, "pdp-deact", signal_data->pdp);
-		osmo_timer_del(&signal_data->pdp->cdr_timer);
-		break;
-	case S_SGSN_PDP_TERMINATE:
-		cdr_log_pdp(inst, "pdp-terminate", signal_data->pdp);
-		osmo_timer_del(&signal_data->pdp->cdr_timer);
-		break;
-	case S_SGSN_PDP_FREE:
-		cdr_log_pdp(inst, "pdp-free", signal_data->pdp);
-		osmo_timer_del(&signal_data->pdp->cdr_timer);
-		break;
-	}
-
-	return 0;
-}
-
-int sgsn_cdr_init(struct sgsn_instance *sgsn)
-{
-	/* register for CDR related events */
-	sgsn->cfg.cdr.interval = 10 * 60;
-	osmo_signal_register_handler(SS_SGSN, handle_sgsn_sig, sgsn);
-
-	return 0;
-}
diff --git a/src/gprs/sgsn_ctrl.c b/src/gprs/sgsn_ctrl.c
deleted file mode 100644
index 31ac74f..0000000
--- a/src/gprs/sgsn_ctrl.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Control Interface Implementation for the SGSN */
-/*
- * (C) 2014 by Holger Hans Peter Freyther
- * (C) 2014 by 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 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/>.
- *
- */
-
-#include <osmocom/ctrl/control_if.h>
-#include <osmocom/ctrl/control_cmd.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/gprs_sgsn.h>
-#include <openbsc/sgsn.h>
-#include <openbsc/debug.h>
-
-#include <pdp.h>
-
-extern vector ctrl_node_vec;
-
-static int get_subscriber_list(struct ctrl_cmd *cmd, void *d)
-{
-	struct sgsn_mm_ctx *mm;
-
-	cmd->reply = talloc_strdup(cmd, "");
-	llist_for_each_entry(mm, &sgsn_mm_ctxts, list) {
-		char *addr = NULL;
-		struct sgsn_pdp_ctx *pdp;
-
-		if (strlen(mm->imsi) == 0)
-			continue;
-
-		llist_for_each_entry(pdp, &mm->pdp_list, list)
-			addr = gprs_pdpaddr2str(pdp->lib->eua.v,
-						pdp->lib->eua.l);
-
-		cmd->reply = talloc_asprintf_append(
-					cmd->reply,
-					"%s,%s\n", mm->imsi, addr ? addr : "");
-	}
-
-	return CTRL_CMD_REPLY;
-}
-CTRL_CMD_DEFINE_RO(subscriber_list, "subscriber-list-active-v1");
-
-int sgsn_ctrl_cmds_install(void)
-{
-	int rc = 0;
-	rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_subscriber_list);
-	return rc;
-}
-
-struct ctrl_handle *sgsn_controlif_setup(struct gsm_network *net,
-					 const char *bind_addr, uint16_t port)
-{
-	return ctrl_interface_setup_dynip(net, bind_addr, port, NULL);
-}
diff --git a/src/gprs/sgsn_libgtp.c b/src/gprs/sgsn_libgtp.c
deleted file mode 100644
index 90b4d16..0000000
--- a/src/gprs/sgsn_libgtp.c
+++ /dev/null
@@ -1,885 +0,0 @@
-/* GPRS SGSN integration with libgtp of OpenGGSN */
-/* libgtp implements the GPRS Tunelling Protocol GTP per TS 09.60 / 29.060 */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2010 by On-Waves
- * (C) 2015 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/>.
- *
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <errno.h>
-#include <signal.h>
-#include <sys/fcntl.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include "bscconfig.h"
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/gprs/gprs_bssgp.h>
-#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
-
-#include <openbsc/signal.h>
-#include <openbsc/debug.h>
-#include <openbsc/sgsn.h>
-#include <openbsc/gprs_llc.h>
-#include <openbsc/gprs_sgsn.h>
-#include <openbsc/gprs_gmm.h>
-#include <openbsc/gprs_subscriber.h>
-#include <openbsc/gprs_sndcp.h>
-
-#ifdef BUILD_IU
-#include <osmocom/ranap/iu_client.h>
-#include <osmocom/ranap/ranap_ies_defs.h>
-#endif
-
-#include <gtp.h>
-#include <pdp.h>
-
-/* TS 23.003: The MSISDN shall take the dummy MSISDN value composed of
- * 15 digits set to 0 (encoded as an E.164 international number) when
- * the MSISDN is not available in messages in which the presence of the
- * MSISDN parameter */
-static const uint8_t dummy_msisdn[] =
-	{ 0x91, /* No extension, international, E.164 */
-	  0, 0, 0, 0, 0, 0, 0, /* 14 digits of zeroes */
-	  0xF0 /* 15th digit of zero + padding */ };
-
-const struct value_string gtp_cause_strs[] = {
-	{ GTPCAUSE_REQ_IMSI, "Request IMSI" },
-	{ GTPCAUSE_REQ_IMEI, "Request IMEI" },
-	{ GTPCAUSE_REQ_IMSI_IMEI, "Request IMSI and IMEI" },
-	{ GTPCAUSE_NO_ID_NEEDED, "No identity needed" },
-	{ GTPCAUSE_MS_REFUSES_X, "MS refuses" },
-	{ GTPCAUSE_MS_NOT_RESP_X, "MS is not GPRS responding" },
-	{ GTPCAUSE_ACC_REQ, "Request accepted" },
-	{ GTPCAUSE_NON_EXIST, "Non-existent" },
-	{ GTPCAUSE_INVALID_MESSAGE, "Invalid message format" },
-	{ GTPCAUSE_IMSI_NOT_KNOWN, "IMSI not known" },
-	{ GTPCAUSE_MS_DETACHED, "MS is GPRS detached" },
-	{ GTPCAUSE_MS_NOT_RESP, "MS is not GPRS responding" },
-	{ GTPCAUSE_MS_REFUSES, "MS refuses" },
-	{ GTPCAUSE_NO_RESOURCES, "No resources available" },
-	{ GTPCAUSE_NOT_SUPPORTED, "Service not supported" },
-	{ GTPCAUSE_MAN_IE_INCORRECT, "Mandatory IE incorrect" },
-	{ GTPCAUSE_MAN_IE_MISSING, "Mandatory IE missing" },
-	{ GTPCAUSE_OPT_IE_INCORRECT, "Optional IE incorrect" },
-	{ GTPCAUSE_SYS_FAIL, "System failure" },
-	{ GTPCAUSE_ROAMING_REST, "Roaming restrictions" },
-	{ GTPCAUSE_PTIMSI_MISMATCH, "P-TMSI Signature mismatch" },
-	{ GTPCAUSE_CONN_SUSP, "GPRS connection suspended" },
-	{ GTPCAUSE_AUTH_FAIL, "Authentication failure" },
-	{ GTPCAUSE_USER_AUTH_FAIL, "User authentication failed" },
-	{ GTPCAUSE_CONTEXT_NOT_FOUND, "Context not found" },
-	{ GTPCAUSE_ADDR_OCCUPIED, "All dynamic PDP addresses occupied" },
-	{ GTPCAUSE_NO_MEMORY, "No memory is available" },
-	{ GTPCAUSE_RELOC_FAIL, "Relocation failure" },
-	{ GTPCAUSE_UNKNOWN_MAN_EXTHEADER, "Unknown mandatory ext. header" },
-	{ GTPCAUSE_SEM_ERR_TFT, "Semantic error in TFT operation" },
-	{ GTPCAUSE_SYN_ERR_TFT, "Syntactic error in TFT operation" },
-	{ GTPCAUSE_SEM_ERR_FILTER, "Semantic errors in packet filter" },
-	{ GTPCAUSE_SYN_ERR_FILTER, "Syntactic errors in packet filter" },
-	{ GTPCAUSE_MISSING_APN, "Missing or unknown APN" },
-	{ GTPCAUSE_UNKNOWN_PDP, "Unknown PDP address or PDP type" },
-	{ 0, NULL }
-};
-
-/* Generate the GTP IMSI IE according to 09.60 Section 7.9.2 */
-static uint64_t imsi_str2gtp(char *str)
-{
-	uint64_t imsi64 = 0;
-	unsigned int n;
-	unsigned int imsi_len = strlen(str);
-
-	if (imsi_len > 16) {
-		LOGP(DGPRS, LOGL_NOTICE, "IMSI length > 16 not supported!\n");
-		return 0;
-	}
-
-	for (n = 0; n < 16; n++) {
-		uint64_t val;
-		if (n < imsi_len)
-			val = (str[n]-'0') & 0xf;
-		else
-			val = 0xf;
-		imsi64 |= (val << (n*4));
-	}
-	return imsi64;
-}
-
-/* generate a PDP context based on the IE's from the 04.08 message,
- * and send the GTP create pdp context request to the GGSN */
-struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
-					 struct sgsn_mm_ctx *mmctx,
-					 uint16_t nsapi,
-					 struct tlv_parsed *tp)
-{
-	struct gprs_ra_id raid;
-	struct sgsn_pdp_ctx *pctx;
-	struct pdp_t *pdp;
-	uint64_t imsi_ui64;
-	size_t qos_len;
-	const uint8_t *qos;
-	int rc;
-
-	LOGP(DGPRS, LOGL_ERROR, "Create PDP Context\n");
-	pctx = sgsn_pdp_ctx_alloc(mmctx, nsapi);
-	if (!pctx) {
-		LOGP(DGPRS, LOGL_ERROR, "Couldn't allocate PDP Ctx\n");
-		return NULL;
-	}
-
-	imsi_ui64 = imsi_str2gtp(mmctx->imsi);
-
-	rc = pdp_newpdp(&pdp, imsi_ui64, nsapi, NULL);
-	if (rc) {
-		LOGP(DGPRS, LOGL_ERROR, "Out of libgtp PDP Contexts\n");
-		return NULL;
-	}
-	pdp->priv = pctx;
-	pctx->lib = pdp;
-	pctx->ggsn = ggsn;
-
-	//pdp->peer =	/* sockaddr_in of GGSN (receive) */
-	//pdp->ipif =	/* not used by library */
-	pdp->version = ggsn->gtp_version;
-	pdp->hisaddr0 =	ggsn->remote_addr;
-	pdp->hisaddr1 = ggsn->remote_addr;
-	//pdp->cch_pdp = 512;	/* Charging Flat Rate */
-
-	/* MS provided APN, subscription was verified by the caller */
-	pdp->selmode = 0xFC | 0x00;
-
-	/* IMSI, TEID/TEIC, FLLU/FLLC, TID, NSAPI set in pdp_newpdp */
-
-	/* Put the MSISDN in case we have it */
-	if (mmctx->subscr && mmctx->subscr->sgsn_data->msisdn_len) {
-		pdp->msisdn.l = mmctx->subscr->sgsn_data->msisdn_len;
-		if (pdp->msisdn.l > sizeof(pdp->msisdn.v))
-			pdp->msisdn.l = sizeof(pdp->msisdn.v);
-		memcpy(pdp->msisdn.v, mmctx->subscr->sgsn_data->msisdn,
-			pdp->msisdn.l);
-	} else {
-		/* use the dummy 15-digits-zero MSISDN value */
-		pdp->msisdn.l = sizeof(dummy_msisdn);
-		memcpy(pdp->msisdn.v, dummy_msisdn, pdp->msisdn.l);
-	}
-
-	/* End User Address from GMM requested PDP address */
-	pdp->eua.l = TLVP_LEN(tp, OSMO_IE_GSM_REQ_PDP_ADDR);
-	if (pdp->eua.l > sizeof(pdp->eua.v))
-		pdp->eua.l = sizeof(pdp->eua.v);
-	memcpy(pdp->eua.v, TLVP_VAL(tp, OSMO_IE_GSM_REQ_PDP_ADDR),
-		pdp->eua.l);
-	/* Highest 4 bits of first byte need to be set to 1, otherwise
-	 * the IE is identical with the 04.08 PDP Address IE */
-	pdp->eua.v[0] |= 0xf0;
-
-	/* APN name from GMM */
-	pdp->apn_use.l = TLVP_LEN(tp, GSM48_IE_GSM_APN);
-	if (pdp->apn_use.l > sizeof(pdp->apn_use.v))
-		pdp->apn_use.l = sizeof(pdp->apn_use.v);
-	memcpy(pdp->apn_use.v, TLVP_VAL(tp, GSM48_IE_GSM_APN),
-		pdp->apn_use.l);
-
-	/* Protocol Configuration Options from GMM */
-	pdp->pco_req.l = TLVP_LEN(tp, GSM48_IE_GSM_PROTO_CONF_OPT);
-	if (pdp->pco_req.l > sizeof(pdp->pco_req.v))
-		pdp->pco_req.l = sizeof(pdp->pco_req.v);
-	memcpy(pdp->pco_req.v, TLVP_VAL(tp, GSM48_IE_GSM_PROTO_CONF_OPT),
-		pdp->pco_req.l);
-
-	/* QoS options from GMM or remote */
-	if (TLVP_LEN(tp, OSMO_IE_GSM_SUB_QOS) > 0) {
-		qos_len = TLVP_LEN(tp, OSMO_IE_GSM_SUB_QOS);
-		qos = TLVP_VAL(tp, OSMO_IE_GSM_SUB_QOS);
-	} else {
-		qos_len = TLVP_LEN(tp, OSMO_IE_GSM_REQ_QOS);
-		qos = TLVP_VAL(tp, OSMO_IE_GSM_REQ_QOS);
-	}
-
-	if (qos_len <= 3) {
-		pdp->qos_req.l = qos_len + 1;
-		if (pdp->qos_req.l > sizeof(pdp->qos_req.v))
-			pdp->qos_req.l = sizeof(pdp->qos_req.v);
-		pdp->qos_req.v[0] = 0; /* Allocation/Retention policy */
-		memcpy(&pdp->qos_req.v[1], qos, pdp->qos_req.l - 1);
-	} else {
-		pdp->qos_req.l = qos_len;
-		if (pdp->qos_req.l > sizeof(pdp->qos_req.v))
-			pdp->qos_req.l = sizeof(pdp->qos_req.v);
-		memcpy(pdp->qos_req.v, qos, pdp->qos_req.l);
-	}
-
-	/* charging characteristics if present */
-	if (TLVP_LEN(tp, OSMO_IE_GSM_CHARG_CHAR) >= sizeof(pdp->cch_pdp))
-		pdp->cch_pdp = tlvp_val16be(tp, OSMO_IE_GSM_CHARG_CHAR);
-
-	/* SGSN address for control plane */
-	pdp->gsnlc.l = sizeof(sgsn->cfg.gtp_listenaddr.sin_addr);
-	memcpy(pdp->gsnlc.v, &sgsn->cfg.gtp_listenaddr.sin_addr,
-		sizeof(sgsn->cfg.gtp_listenaddr.sin_addr));
-
-	/* SGSN address for user plane
-	 * Default to the control plane addr for now. If we are connected to a
-	 * hnbgw via IuPS we'll need to send a PDP context update with the
-	 * correct IP address after the RAB Assignment is complete */
-	pdp->gsnlu.l = sizeof(sgsn->cfg.gtp_listenaddr.sin_addr);
-	memcpy(pdp->gsnlu.v, &sgsn->cfg.gtp_listenaddr.sin_addr,
-		sizeof(sgsn->cfg.gtp_listenaddr.sin_addr));
-
-	/* Encode RAT Type according to TS 29.060 7.7.50 */
-	pdp->rattype.l = 1;
-	if (mmctx->ran_type == MM_CTX_T_UTRAN_Iu)
-		pdp->rattype.v[0] = 1;
-	else
-		pdp->rattype.v[0] = 2;
-	pdp->rattype_given = 1;
-
-	/* Include RAI and ULI all the time */
-	pdp->rai_given = 1;
-	pdp->rai.l = 6;
-
-	/* Routing Area Identifier with LAC and RAC fixed values, as
-	 * requested in 29.006 7.3.1 */
-	raid = mmctx->ra;
-	raid.lac = 0xFFFE;
-	raid.rac = 0xFF;
-	gsm48_construct_ra(pdp->rai.v, &raid);
-
-	/* Encode User Location Information accordint to TS 29.060 7.7.51 */
-	pdp->userloc_given = 1;
-	pdp->userloc.l = 8;
-	switch (mmctx->ran_type) {
-	case MM_CTX_T_GERAN_Gb:
-	case MM_CTX_T_GERAN_Iu:
-		pdp->rattype.v[0] = 2;
-		/* User Location Information */
-		pdp->userloc_given = 1;
-		pdp->userloc.l = 8;
-		pdp->userloc.v[0] = 0; /* CGI for GERAN */
-		bssgp_create_cell_id(&pdp->userloc.v[1], &mmctx->ra, mmctx->gb.cell_id);
-		break;
-	case MM_CTX_T_UTRAN_Iu:
-		pdp->userloc.v[0] = 1; /* SAI for UTRAN */
-		/* SAI is like CGI but with SAC instead of CID, so we can abuse this function */
-		bssgp_create_cell_id(&pdp->userloc.v[1], &mmctx->ra, mmctx->iu.sac);
-		break;
-	}
-
-	/* include the IMEI(SV) */
-	pdp->imeisv_given = 1;
-	gsm48_encode_bcd_number(&pdp->imeisv.v[0], 8, 0, mmctx->imei);
-	pdp->imeisv.l = pdp->imeisv.v[0];
-	memmove(&pdp->imeisv.v[0], &pdp->imeisv.v[1], 8);
-
-	/* change pdp state to 'requested' */
-	pctx->state = PDP_STATE_CR_REQ;
-
-	rc = gtp_create_context_req(ggsn->gsn, pdp, pctx);
-	/* FIXME */
-
-	return pctx;
-}
-
-/* SGSN wants to delete a PDP context */
-int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx)
-{
-	LOGPDPCTXP(LOGL_ERROR, pctx, "Delete PDP Context\n");
-
-	/* FIXME: decide if we need teardown or not ! */
-	return gtp_delete_context_req(pctx->ggsn->gsn, pctx->lib, pctx, 1);
-}
-
-struct cause_map {
-	uint8_t cause_in;
-	uint8_t cause_out;
-};
-
-static uint8_t cause_map(const struct cause_map *map, uint8_t in, uint8_t deflt)
-{
-	const struct cause_map *m;
-
-	for (m = map; m->cause_in && m->cause_out; m++) {
-		if (m->cause_in == in)
-			return m->cause_out;
-	}
-	return deflt;
-}
-
-/* how do we map from gtp cause to SM cause */
-static const struct cause_map gtp2sm_cause_map[] = {
-	{ GTPCAUSE_NO_RESOURCES, 	GSM_CAUSE_INSUFF_RSRC },
-	{ GTPCAUSE_NOT_SUPPORTED,	GSM_CAUSE_SERV_OPT_NOTSUPP },
-	{ GTPCAUSE_MAN_IE_INCORRECT,	GSM_CAUSE_INV_MAND_INFO },
-	{ GTPCAUSE_MAN_IE_MISSING,	GSM_CAUSE_INV_MAND_INFO },
-	{ GTPCAUSE_OPT_IE_INCORRECT,	GSM_CAUSE_PROTO_ERR_UNSPEC },
-	{ GTPCAUSE_SYS_FAIL,		GSM_CAUSE_NET_FAIL },
-	{ GTPCAUSE_ROAMING_REST,	GSM_CAUSE_REQ_SERV_OPT_NOTSUB },
-	{ GTPCAUSE_PTIMSI_MISMATCH,	GSM_CAUSE_PROTO_ERR_UNSPEC },
-	{ GTPCAUSE_CONN_SUSP,		GSM_CAUSE_PROTO_ERR_UNSPEC },
-	{ GTPCAUSE_AUTH_FAIL,		GSM_CAUSE_AUTH_FAILED },
-	{ GTPCAUSE_USER_AUTH_FAIL,	GSM_CAUSE_ACT_REJ_GGSN },
-	{ GTPCAUSE_CONTEXT_NOT_FOUND,	GSM_CAUSE_PROTO_ERR_UNSPEC },
-	{ GTPCAUSE_ADDR_OCCUPIED,	GSM_CAUSE_INSUFF_RSRC },
-	{ GTPCAUSE_NO_MEMORY,		GSM_CAUSE_INSUFF_RSRC },
-	{ GTPCAUSE_RELOC_FAIL,		GSM_CAUSE_PROTO_ERR_UNSPEC },
-	{ GTPCAUSE_UNKNOWN_MAN_EXTHEADER, GSM_CAUSE_PROTO_ERR_UNSPEC },
-	{ GTPCAUSE_MISSING_APN,		GSM_CAUSE_MISSING_APN },
-	{ GTPCAUSE_UNKNOWN_PDP,		GSM_CAUSE_UNKNOWN_PDP },
-	{ 0, 0 }
-};
-
-static int send_act_pdp_cont_acc(struct sgsn_pdp_ctx *pctx)
-{
-	struct sgsn_signal_data sig_data;
-	int rc;
-	struct gprs_llc_lle *lle;
-
-	/* Inform others about it */
-	memset(&sig_data, 0, sizeof(sig_data));
-	sig_data.pdp = pctx;
-	osmo_signal_dispatch(SS_SGSN, S_SGSN_PDP_ACT, &sig_data);
-
-	/* Send PDP CTX ACT to MS */
-	rc = gsm48_tx_gsm_act_pdp_acc(pctx);
-	if (rc < 0)
-		return rc;
-
-	if (pctx->mm->ran_type == MM_CTX_T_GERAN_Gb) {
-		/* Send SNDCP XID to MS */
-		lle = &pctx->mm->gb.llme->lle[pctx->sapi];
-		rc = sndcp_sn_xid_req(lle,pctx->nsapi);
-		if (rc < 0)
-			return rc;
-	}
-
-	return 0;
-}
-
-/* The GGSN has confirmed the creation of a PDP Context */
-static int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
-{
-	struct sgsn_pdp_ctx *pctx = cbp;
-	uint8_t reject_cause;
-
-	LOGPDPCTXP(LOGL_INFO, pctx, "Received CREATE PDP CTX CONF, cause=%d(%s)\n",
-		cause, get_value_string(gtp_cause_strs, cause));
-
-	if (!pctx->mm) {
-		LOGP(DGPRS, LOGL_INFO,
-		     "No MM context, aborting CREATE PDP CTX CONF\n");
-		return -EIO;
-	}
-
-	/* Check for cause value if it was really successful */
-	if (cause < 0) {
-		LOGP(DGPRS, LOGL_NOTICE, "Create PDP ctx req timed out\n");
-		if (pdp && pdp->version == 1) {
-			pdp->version = 0;
-			gtp_create_context_req(sgsn->gsn, pdp, cbp);
-			return 0;
-		} else {
-			reject_cause = GSM_CAUSE_NET_FAIL;
-			goto reject;
-		}
-	}
-
-	/* Check for cause value if it was really successful */
-	if (cause != GTPCAUSE_ACC_REQ) {
-		reject_cause = cause_map(gtp2sm_cause_map, cause,
-					 GSM_CAUSE_ACT_REJ_GGSN);
-		goto reject;
-	}
-
-	if (pctx->mm->ran_type == MM_CTX_T_GERAN_Gb) {
-		/* Activate the SNDCP layer */
-		sndcp_sm_activate_ind(&pctx->mm->gb.llme->lle[pctx->sapi], pctx->nsapi);
-		return send_act_pdp_cont_acc(pctx);
-	} else if (pctx->mm->ran_type == MM_CTX_T_UTRAN_Iu) {
-#ifdef BUILD_IU
-		/* Activate a radio bearer */
-		iu_rab_act_ps(pdp->nsapi, pctx);
-		return 0;
-#else
-		return -ENOTSUP;
-#endif
-	}
-
-	LOGP(DGPRS, LOGL_ERROR, "Unknown ran_type %d\n",
-	     pctx->mm->ran_type);
-	reject_cause = GSM_CAUSE_PROTO_ERR_UNSPEC;
-
-reject:
-	/*
-	 * In case of a timeout pdp will be NULL but we have a valid pointer
-	 * in pctx->lib. For other rejects pctx->lib and pdp might be the
-	 * same.
-	 */
-	pctx->state = PDP_STATE_NONE;
-	if (pctx->lib && pctx->lib != pdp)
-		pdp_freepdp(pctx->lib);
-	pctx->lib = NULL;
-
-	if (pdp)
-		pdp_freepdp(pdp);
-	/* Send PDP CTX ACT REJ to MS */
-	gsm48_tx_gsm_act_pdp_rej(pctx->mm, pctx->ti, reject_cause,
-					0, NULL);
-	sgsn_pdp_ctx_free(pctx);
-
-	return EOF;
-}
-
-void sgsn_pdp_upd_gtp_u(struct sgsn_pdp_ctx *pdp, void *addr, size_t alen)
-{
-	pdp->lib->gsnlu.l = alen;
-	memcpy(pdp->lib->gsnlu.v, addr, alen);
-	gtp_update_context(pdp->ggsn->gsn, pdp->lib, pdp, &pdp->lib->hisaddr0);
-}
-
-#ifdef BUILD_IU
-/* Callback for RAB assignment response */
-int sgsn_ranap_rab_ass_resp(struct sgsn_mm_ctx *ctx, RANAP_RAB_SetupOrModifiedItemIEs_t *setup_ies)
-{
-	uint8_t rab_id;
-	bool require_pdp_update = false;
-	struct sgsn_pdp_ctx *pdp = NULL;
-	RANAP_RAB_SetupOrModifiedItem_t *item = &setup_ies->raB_SetupOrModifiedItem;
-
-	rab_id = item->rAB_ID.buf[0];
-
-	pdp = sgsn_pdp_ctx_by_nsapi(ctx, rab_id);
-	if (!pdp) {
-		LOGP(DRANAP, LOGL_ERROR, "RAB Assignment Response for unknown RAB/NSAPI=%u\n", rab_id);
-		return -1;
-	}
-
-	if (item->transportLayerAddress) {
-		LOGPC(DRANAP, LOGL_INFO, " Setup: (%u/%s)", rab_id, osmo_hexdump(item->transportLayerAddress->buf,
-								     item->transportLayerAddress->size));
-		switch (item->transportLayerAddress->size) {
-		case 7:
-			/* It must be IPv4 inside a X213 NSAP */
-			memcpy(pdp->lib->gsnlu.v, &item->transportLayerAddress->buf[3], 4);
-			break;
-		case 4:
-			/* It must be a raw IPv4 address */
-			memcpy(pdp->lib->gsnlu.v, item->transportLayerAddress->buf, 4);
-			break;
-		case 16:
-			/* TODO: It must be a raw IPv6 address */
-		case 19:
-			/* TODO: It must be IPv6 inside a X213 NSAP */
-		default:
-			LOGP(DRANAP, LOGL_ERROR, "RAB Assignment Resp: Unknown "
-				"transport layer address size %u\n",
-				item->transportLayerAddress->size);
-			return -1;
-		}
-		require_pdp_update = true;
-	}
-
-	/* The TEI on the RNC side might have changed, too */
-	if (item->iuTransportAssociation &&
-	    item->iuTransportAssociation->present == RANAP_IuTransportAssociation_PR_gTP_TEI &&
-	    item->iuTransportAssociation->choice.gTP_TEI.buf &&
-	    item->iuTransportAssociation->choice.gTP_TEI.size >= 4) {
-		uint32_t tei = osmo_load32be(item->iuTransportAssociation->choice.gTP_TEI.buf);
-		LOGP(DRANAP, LOGL_DEBUG, "Updating TEID on RNC side from 0x%08x to 0x%08x\n",
-			pdp->lib->teid_own, tei);
-		pdp->lib->teid_own = tei;
-		require_pdp_update = true;
-	}
-
-	if (require_pdp_update)
-		gtp_update_context(pdp->ggsn->gsn, pdp->lib, pdp, &pdp->lib->hisaddr0);
-
-	if (pdp->state != PDP_STATE_CR_CONF) {
-		send_act_pdp_cont_acc(pdp);
-		pdp->state = PDP_STATE_CR_CONF;
-	}
-	return 0;
-
-}
-#endif
-
-/* Confirmation of a PDP Context Delete */
-static int delete_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
-{
-	struct sgsn_signal_data sig_data;
-	struct sgsn_pdp_ctx *pctx = cbp;
-	int rc = 0;
-
-	LOGPDPCTXP(LOGL_INFO, pctx, "Received DELETE PDP CTX CONF, cause=%d(%s)\n",
-		cause, get_value_string(gtp_cause_strs, cause));
-
-	memset(&sig_data, 0, sizeof(sig_data));
-	sig_data.pdp = pctx;
-	osmo_signal_dispatch(SS_SGSN, S_SGSN_PDP_DEACT, &sig_data);
-
-	if (pctx->mm) {
-		if (pctx->mm->ran_type == MM_CTX_T_GERAN_Gb) {
-			/* Deactivate the SNDCP layer */
-			sndcp_sm_deactivate_ind(&pctx->mm->gb.llme->lle[pctx->sapi], pctx->nsapi);
-		} else {
-#ifdef BUILD_IU
-			/* Deactivate radio bearer */
-			ranap_iu_rab_deact(pctx->mm->iu.ue_ctx, 1);
-#else
-			return -ENOTSUP;
-#endif
-		}
-
-		/* Confirm deactivation of PDP context to MS */
-		rc = gsm48_tx_gsm_deact_pdp_acc(pctx);
-	} else {
-		LOGPDPCTXP(LOGL_NOTICE, pctx,
-			   "Not deactivating SNDCP layer since the MM context "
-			   "is not available\n");
-	}
-
-	/* unlink the now non-existing library handle from the pdp
-	 * context */
-	pctx->lib = NULL;
-
-	sgsn_pdp_ctx_free(pctx);
-
-	return rc;
-}
-
-/* Confirmation of an GTP ECHO request */
-static int echo_conf(struct pdp_t *pdp, void *cbp, int recovery)
-{
-	if (recovery < 0) {
-		LOGP(DGPRS, LOGL_NOTICE, "GTP Echo Request timed out\n");
-		/* FIXME: if version == 1, retry with version 0 */
-	} else {
-		DEBUGP(DGPRS, "GTP Rx Echo Response\n");
-	}
-	return 0;
-}
-
-/* Any message received by GGSN contains a recovery IE */
-static int cb_recovery(struct sockaddr_in *peer, uint8_t recovery)
-{
-	struct sgsn_ggsn_ctx *ggsn;
-	
-	ggsn = sgsn_ggsn_ctx_by_addr(&peer->sin_addr);
-	if (!ggsn) {
-		LOGP(DGPRS, LOGL_NOTICE, "Received Recovery IE for unknown GGSN\n");
-		return -EINVAL;
-	}
-
-	if (ggsn->remote_restart_ctr == -1) {
-		/* First received ECHO RESPONSE, note the restart ctr */
-		ggsn->remote_restart_ctr = recovery;
-	} else if (ggsn->remote_restart_ctr != recovery) {
-		/* counter has changed (GGSN restart): release all PDP */
-		LOGP(DGPRS, LOGL_NOTICE, "GGSN recovery (%u->%u), "
-		     "releasing all PDP contexts\n",
-		     ggsn->remote_restart_ctr, recovery);
-		ggsn->remote_restart_ctr = recovery;
-		drop_all_pdp_for_ggsn(ggsn);
-	}
-	return 0;
-}
-
-/* libgtp callback for confirmations */
-static int cb_conf(int type, int cause, struct pdp_t *pdp, void *cbp)
-{
-	DEBUGP(DGPRS, "libgtp cb_conf(type=%d, cause=%d, pdp=%p, cbp=%p)\n",
-		type, cause, pdp, cbp);
-
-	if (cause == EOF)
-		LOGP(DGPRS, LOGL_ERROR, "libgtp EOF (type=%u, pdp=%p, cbp=%p)\n",
-			type, pdp, cbp);
-
-	switch (type) {
-	case GTP_ECHO_REQ:
-		/* libgtp hands us the RECOVERY number instead of a cause */
-		return echo_conf(pdp, cbp, cause);
-	case GTP_CREATE_PDP_REQ:
-		return create_pdp_conf(pdp, cbp, cause);
-	case GTP_DELETE_PDP_REQ:
-		return delete_pdp_conf(pdp, cbp, cause);
-	default:
-		break;
-	}
-	return 0;
-}
-
-/* Called whenever a PDP context is deleted for any reason */
-static int cb_delete_context(struct pdp_t *pdp)
-{
-	LOGP(DGPRS, LOGL_INFO, "PDP Context was deleted\n");
-	return 0;
-}
-
-/* Called when we receive a Version Not Supported message */
-static int cb_unsup_ind(struct sockaddr_in *peer)
-{
-	LOGP(DGPRS, LOGL_INFO, "GTP Version not supported Indication "
-		"from %s:%u\n", inet_ntoa(peer->sin_addr),
-		ntohs(peer->sin_port));
-	return 0;
-}
-
-/* Called when we receive a Supported Ext Headers Notification */
-static int cb_extheader_ind(struct sockaddr_in *peer)
-{
-	LOGP(DGPRS, LOGL_INFO, "GTP Supported Ext Headers Noficiation "
-		"from %s:%u\n", inet_ntoa(peer->sin_addr),
-		ntohs(peer->sin_port));
-	return 0;
-}
-
-/* Called whenever we recive a DATA packet */
-static int cb_data_ind(struct pdp_t *lib, void *packet, unsigned int len)
-{
-	struct bssgp_paging_info pinfo;
-	struct sgsn_pdp_ctx *pdp;
-	struct sgsn_mm_ctx *mm;
-	struct msgb *msg;
-	uint8_t *ud;
-
-	pdp = lib->priv;
-	if (!pdp) {
-		LOGP(DGPRS, LOGL_NOTICE,
-		     "GTP DATA IND from GGSN for unknown PDP\n");
-		return -EIO;
-	}
-	mm = pdp->mm;
-	if (!mm) {
-		LOGP(DGPRS, LOGL_ERROR,
-		     "PDP context (address=%u) without MM context!\n",
-		     pdp->address);
-		return -EIO;
-	}
-
-	DEBUGP(DGPRS, "GTP DATA IND from GGSN for %s, length=%u\n", mm->imsi,
-	       len);
-
-	if (mm->ran_type == MM_CTX_T_UTRAN_Iu) {
-#ifdef BUILD_IU
-		/* Ignore the packet for now and page the UE to get the RAB
-		 * reestablished */
-		ranap_iu_page_ps(mm->imsi, &mm->p_tmsi, mm->ra.lac, mm->ra.rac);
-
-		return 0;
-#else
-		return -ENOTSUP;
-#endif
-	}
-
-	msg = msgb_alloc_headroom(len+256, 128, "GTP->SNDCP");
-	ud = msgb_put(msg, len);
-	memcpy(ud, packet, len);
-
-	msgb_tlli(msg) = mm->gb.tlli;
-	msgb_bvci(msg) = mm->gb.bvci;
-	msgb_nsei(msg) = mm->gb.nsei;
-
-	switch (mm->gmm_state) {
-	case GMM_REGISTERED_SUSPENDED:
-		/* initiate PS PAGING procedure */
-		memset(&pinfo, 0, sizeof(pinfo));
-		pinfo.mode = BSSGP_PAGING_PS;
-		pinfo.scope = BSSGP_PAGING_BVCI;
-		pinfo.bvci = mm->gb.bvci;
-		pinfo.imsi = mm->imsi;
-		pinfo.ptmsi = &mm->p_tmsi;
-		pinfo.drx_params = mm->drx_parms;
-		pinfo.qos[0] = 0; // FIXME
-		bssgp_tx_paging(mm->gb.nsei, 0, &pinfo);
-		rate_ctr_inc(&mm->ctrg->ctr[GMM_CTR_PAGING_PS]);
-		/* FIXME: queue the packet we received from GTP */
-		break;
-	case GMM_REGISTERED_NORMAL:
-		break;
-	default:
-		LOGP(DGPRS, LOGL_ERROR, "GTP DATA IND for TLLI %08X in state "
-			"%u\n", mm->gb.tlli, mm->gmm_state);
-		msgb_free(msg);
-		return -1;
-	}
-
-	rate_ctr_inc(&pdp->ctrg->ctr[PDP_CTR_PKTS_UDATA_OUT]);
-	rate_ctr_add(&pdp->ctrg->ctr[PDP_CTR_BYTES_UDATA_OUT], len);
-	rate_ctr_inc(&mm->ctrg->ctr[GMM_CTR_PKTS_UDATA_OUT]);
-	rate_ctr_add(&mm->ctrg->ctr[GMM_CTR_BYTES_UDATA_OUT], len);
-
-	/* It is easier to have a global count */
-	pdp->cdr_bytes_out += len;
-
-	return sndcp_unitdata_req(msg, &mm->gb.llme->lle[pdp->sapi],
-				  pdp->nsapi, mm);
-}
-
-/* Called by SNDCP when it has received/re-assembled a N-PDU */
-int sgsn_rx_sndcp_ud_ind(struct gprs_ra_id *ra_id, int32_t tlli, uint8_t nsapi,
-			 struct msgb *msg, uint32_t npdu_len, uint8_t *npdu)
-{
-	struct sgsn_mm_ctx *mmctx;
-	struct sgsn_pdp_ctx *pdp;
-
-	/* look-up the MM context for this message */
-	mmctx = sgsn_mm_ctx_by_tlli(tlli, ra_id);
-	if (!mmctx) {
-		LOGP(DGPRS, LOGL_ERROR,
-			"Cannot find MM CTX for TLLI %08x\n", tlli);
-		return -EIO;
-	}
-	/* look-up the PDP context for this message */
-	pdp = sgsn_pdp_ctx_by_nsapi(mmctx, nsapi);
-	if (!pdp) {
-		LOGP(DGPRS, LOGL_ERROR, "Cannot find PDP CTX for "
-			"TLLI=%08x, NSAPI=%u\n", tlli, nsapi);
-		return -EIO;
-	}
-	if (!pdp->lib) {
-		LOGP(DGPRS, LOGL_ERROR, "PDP CTX without libgtp\n");
-		return -EIO;
-	}
-
-	rate_ctr_inc(&pdp->ctrg->ctr[PDP_CTR_PKTS_UDATA_IN]);
-	rate_ctr_add(&pdp->ctrg->ctr[PDP_CTR_BYTES_UDATA_IN], npdu_len);
-	rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PKTS_UDATA_IN]);
-	rate_ctr_add(&mmctx->ctrg->ctr[GMM_CTR_BYTES_UDATA_IN], npdu_len);
-
-	/* It is easier to have a global count */
-	pdp->cdr_bytes_in += npdu_len;
-
-	return gtp_data_req(pdp->ggsn->gsn, pdp->lib, npdu, npdu_len);
-}
-
-/* libgtp select loop integration */
-static int sgsn_gtp_fd_cb(struct osmo_fd *fd, unsigned int what)
-{
-	struct sgsn_instance *sgi = fd->data;
-	int rc;
-
-	if (!(what & BSC_FD_READ))
-		return 0;
-
-	switch (fd->priv_nr) {
-	case 0:
-		rc = gtp_decaps0(sgi->gsn);
-		break;
-	case 1:
-		rc = gtp_decaps1c(sgi->gsn);
-		break;
-	case 2:
-		rc = gtp_decaps1u(sgi->gsn);
-		break;
-	default:
-		rc = -EINVAL;
-		break;
-	}
-	return rc;
-}
-
-static void sgsn_gtp_tmr_start(struct sgsn_instance *sgi)
-{
-	struct timeval next;
-
-	/* Retrieve next retransmission as struct timeval */
-	gtp_retranstimeout(sgi->gsn, &next);
-
-	/* re-schedule the timer */
-	osmo_timer_schedule(&sgi->gtp_timer, next.tv_sec, next.tv_usec/1000);
-}
-
-/* timer callback for libgtp retransmissions and ping */
-static void sgsn_gtp_tmr_cb(void *data)
-{
-	struct sgsn_instance *sgi = data;
-
-	/* Do all the retransmissions as needed */
-	gtp_retrans(sgi->gsn);
-
-	sgsn_gtp_tmr_start(sgi);
-}
-
-int sgsn_gtp_init(struct sgsn_instance *sgi)
-{
-	int rc;
-	struct gsn_t *gsn;
-
-	rc = gtp_new(&sgi->gsn, sgi->cfg.gtp_statedir,
-		     &sgi->cfg.gtp_listenaddr.sin_addr, GTP_MODE_SGSN);
-	if (rc) {
-		LOGP(DGPRS, LOGL_ERROR, "Failed to create GTP: %d\n", rc);
-		return rc;
-	}
-	gsn = sgi->gsn;
-
-	sgi->gtp_fd0.fd = gsn->fd0;
-	sgi->gtp_fd0.priv_nr = 0;
-	sgi->gtp_fd0.data = sgi;
-	sgi->gtp_fd0.when = BSC_FD_READ;
-	sgi->gtp_fd0.cb = sgsn_gtp_fd_cb;
-	rc = osmo_fd_register(&sgi->gtp_fd0);
-	if (rc < 0)
-		return rc;
-
-	sgi->gtp_fd1c.fd = gsn->fd1c;
-	sgi->gtp_fd1c.priv_nr = 1;
-	sgi->gtp_fd1c.data = sgi;
-	sgi->gtp_fd1c.when = BSC_FD_READ;
-	sgi->gtp_fd1c.cb = sgsn_gtp_fd_cb;
-	rc = osmo_fd_register(&sgi->gtp_fd1c);
-	if (rc < 0) {
-		osmo_fd_unregister(&sgi->gtp_fd0);
-		return rc;
-	}
-
-	sgi->gtp_fd1u.fd = gsn->fd1u;
-	sgi->gtp_fd1u.priv_nr = 2;
-	sgi->gtp_fd1u.data = sgi;
-	sgi->gtp_fd1u.when = BSC_FD_READ;
-	sgi->gtp_fd1u.cb = sgsn_gtp_fd_cb;
-	rc = osmo_fd_register(&sgi->gtp_fd1u);
-	if (rc < 0) {
-		osmo_fd_unregister(&sgi->gtp_fd0);
-		osmo_fd_unregister(&sgi->gtp_fd1c);
-		return rc;
-	}
-
-	/* Start GTP re-transmission timer */
-	osmo_timer_setup(&sgi->gtp_timer, sgsn_gtp_tmr_cb, sgi);
-	sgsn_gtp_tmr_start(sgi);
-
-	/* Register callbackcs with libgtp */
-	gtp_set_cb_delete_context(gsn, cb_delete_context);
-	gtp_set_cb_conf(gsn, cb_conf);
-	gtp_set_cb_recovery(gsn, cb_recovery);
-	gtp_set_cb_data_ind(gsn, cb_data_ind);
-	gtp_set_cb_unsup_ind(gsn, cb_unsup_ind);
-	gtp_set_cb_extheader_ind(gsn, cb_extheader_ind);
-
-	return 0;
-}
diff --git a/src/gprs/sgsn_main.c b/src/gprs/sgsn_main.c
deleted file mode 100644
index 25ee632..0000000
--- a/src/gprs/sgsn_main.c
+++ /dev/null
@@ -1,476 +0,0 @@
-/* GPRS SGSN Implementation */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.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/>.
- *
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <time.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <errno.h>
-#include <signal.h>
-#include <sys/fcntl.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/core/logging.h>
-#include <osmocom/core/stats.h>
-
-#include <osmocom/gsm/gsup.h>
-
-#include <osmocom/gprs/gprs_ns.h>
-#include <osmocom/gprs/gprs_bssgp.h>
-
-#include <osmocom/vty/telnet_interface.h>
-#include <osmocom/vty/logging.h>
-#include <osmocom/vty/stats.h>
-#include <osmocom/vty/ports.h>
-
-#include <osmocom/ctrl/control_vty.h>
-
-#include <openbsc/signal.h>
-#include <openbsc/debug.h>
-#include <openbsc/vty.h>
-#include <openbsc/sgsn.h>
-#include <openbsc/gprs_llc.h>
-#include <openbsc/gprs_gmm.h>
-
-#include <osmocom/ctrl/control_if.h>
-#include <osmocom/ctrl/ports.h>
-
-#include <osmocom/sigtran/protocol/m3ua.h>
-
-#include <gtp.h>
-
-#include "../../bscconfig.h"
-
-#if BUILD_IU
-#include <osmocom/ranap/iu_client.h>
-#endif
-
-#define _GNU_SOURCE
-#include <getopt.h>
-
-void *tall_bsc_ctx;
-
-struct gprs_ns_inst *sgsn_nsi;
-static int daemonize = 0;
-const char *openbsc_copyright =
-	"Copyright (C) 2010 Harald Welte and On-Waves\r\n"
-	"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
-	"This is free software: you are free to change and redistribute it.\r\n"
-	"There is NO WARRANTY, to the extent permitted by law.\r\n";
-
-static struct sgsn_instance sgsn_inst = {
-	.config_file = "osmo_sgsn.cfg",
-	.cfg = {
-		.gtp_statedir = "./",
-		.auth_policy = SGSN_AUTH_POLICY_CLOSED,
-		.gsup_server_port = OSMO_GSUP_PORT,
-	},
-};
-struct sgsn_instance *sgsn = &sgsn_inst;
-
-/* call-back function for the NS protocol */
-static int sgsn_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
-		      struct msgb *msg, uint16_t bvci)
-{
-	int rc = 0;
-
-	switch (event) {
-	case GPRS_NS_EVT_UNIT_DATA:
-		/* hand the message into the BSSGP implementation */
-		rc = bssgp_rcvmsg(msg);
-		break;
-	default:
-		LOGP(DGPRS, LOGL_ERROR, "SGSN: Unknown event %u from NS\n", event);
-		if (msg)
-			msgb_free(msg);
-		rc = -EIO;
-		break;
-	}
-	return rc;
-}
-
-/* call-back function for the BSSGP protocol */
-int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
-{
-	struct osmo_bssgp_prim *bp;
-	bp = container_of(oph, struct osmo_bssgp_prim, oph);
-
-	switch (oph->sap) {
-	case SAP_BSSGP_LL:
-		switch (oph->primitive) {
-		case PRIM_BSSGP_UL_UD:
-			return gprs_llc_rcvmsg(oph->msg, bp->tp);
-		}
-		break;
-	case SAP_BSSGP_GMM:
-		switch (oph->primitive) {
-		case PRIM_BSSGP_GMM_SUSPEND:
-			return gprs_gmm_rx_suspend(bp->ra_id, bp->tlli);
-		case PRIM_BSSGP_GMM_RESUME:
-			return gprs_gmm_rx_resume(bp->ra_id, bp->tlli,
-						  bp->u.resume.suspend_ref);
-		}
-		break;
-	case SAP_BSSGP_NM:
-		break;
-	}
-	return 0;
-}
-
-static void signal_handler(int signal)
-{
-	fprintf(stdout, "signal %u received\n", signal);
-
-	switch (signal) {
-	case SIGINT:
-	case SIGTERM:
-		osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL);
-		sleep(1);
-		exit(0);
-		break;
-	case SIGABRT:
-		/* in case of abort, we want to obtain a talloc report
-		 * and then return to the caller, who will abort the process */
-	case SIGUSR1:
-		talloc_report(tall_vty_ctx, stderr);
-		talloc_report_full(tall_bsc_ctx, stderr);
-		break;
-	case SIGUSR2:
-		talloc_report_full(tall_vty_ctx, stderr);
-		break;
-	default:
-		break;
-	}
-}
-
-/* NSI that BSSGP uses when transmitting on NS */
-extern struct gprs_ns_inst *bssgp_nsi;
-
-extern int bsc_vty_go_parent(struct vty *vty);
-
-static struct vty_app_info vty_info = {
-	.name 		= "OsmoSGSN",
-	.version	= PACKAGE_VERSION,
-	.go_parent_cb	= bsc_vty_go_parent,
-	.is_config_node	= bsc_vty_is_config_node,
-};
-
-static void print_help(void)
-{
-	printf("Some useful help...\n");
-	printf("  -h --help\tthis text\n");
-	printf("  -D --daemonize\tFork the process into a background daemon\n");
-	printf("  -d option --debug\tenable Debugging\n");
-	printf("  -s --disable-color\n");
-	printf("  -c --config-file\tThe config file to use [%s]\n", sgsn->config_file);
-	printf("  -e --log-level number\tSet a global log level\n");
-}
-
-static void handle_options(int argc, char **argv)
-{
-	while (1) {
-		int option_index = 0, c;
-		static struct option long_options[] = {
-			{"help", 0, 0, 'h'},
-			{"debug", 1, 0, 'd'},
-			{"daemonize", 0, 0, 'D'},
-			{"config-file", 1, 0, 'c'},
-			{"disable-color", 0, 0, 's'},
-			{"timestamp", 0, 0, 'T'},
-			{ "version", 0, 0, 'V' },
-			{"log-level", 1, 0, 'e'},
-			{NULL, 0, 0, 0}
-		};
-
-		c = getopt_long(argc, argv, "hd:Dc:sTVe:",
-				long_options, &option_index);
-		if (c == -1)
-			break;
-
-		switch (c) {
-		case 'h':
-			//print_usage();
-			print_help();
-			exit(0);
-		case 's':
-			log_set_use_color(osmo_stderr_target, 0);
-			break;
-		case 'd':
-			log_parse_category_mask(osmo_stderr_target, optarg);
-			break;
-		case 'D':
-			daemonize = 1;
-			break;
-		case 'c':
-			sgsn_inst.config_file = strdup(optarg);
-			break;
-		case 'T':
-			log_set_print_timestamp(osmo_stderr_target, 1);
-			break;
-		case 'V':
-			print_version(1);
-			exit(0);
-			break;
-		case 'e':
-			log_set_log_level(osmo_stderr_target, atoi(optarg));
-			break;
-		default:
-			/* ignore */
-			break;
-		}
-	}
-}
-
-/* default categories */
-static struct log_info_cat gprs_categories[] = {
-	[DMM] = {
-		.name = "DMM",
-		.description = "Layer3 Mobility Management (MM)",
-		.color = "\033[1;33m",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DPAG]	= {
-		.name = "DPAG",
-		.description = "Paging Subsystem",
-		.color = "\033[1;38m",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DMEAS] = {
-		.name = "DMEAS",
-		.description = "Radio Measurement Processing",
-		.enabled = 0, .loglevel = LOGL_NOTICE,
-	},
-	[DREF] = {
-		.name = "DREF",
-		.description = "Reference Counting",
-		.enabled = 0, .loglevel = LOGL_NOTICE,
-	},
-	[DGPRS] = {
-		.name = "DGPRS",
-		.description = "GPRS Packet Service",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DNS] = {
-		.name = "DNS",
-		.description = "GPRS Network Service (NS)",
-		.enabled = 1, .loglevel = LOGL_INFO,
-	},
-	[DBSSGP] = {
-		.name = "DBSSGP",
-		.description = "GPRS BSS Gateway Protocol (BSSGP)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DLLC] = {
-		.name = "DLLC",
-		.description = "GPRS Logical Link Control Protocol (LLC)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DSNDCP] = {
-		.name = "DSNDCP",
-		.description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DRANAP] = {
-		.name = "DRANAP",
-		.description = "RAN Application Part (RANAP)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DSUA] = {
-		.name = "DSUA",
-		.description = "SCCP User Adaptation (SUA)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DSLHC] = {
-		.name = "DSLHC",
-		.description = "RFC1144 TCP/IP Header compression (SLHC)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DV42BIS] = {
-		.name = "DV42BIS",
-		.description = "V.42bis data compression (SNDCP)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	}
-};
-
-static const struct log_info gprs_log_info = {
-	.filter_fn = gprs_log_filter_fn,
-	.cat = gprs_categories,
-	.num_cat = ARRAY_SIZE(gprs_categories),
-};
-
-int sgsn_ranap_iu_event(struct ue_conn_ctx *ctx, enum ranap_iu_event_type type, void *data);
-
-int main(int argc, char **argv)
-{
-	struct ctrl_handle *ctrl;
-	struct gsm_network dummy_network;
-	struct osmo_sccp_instance *sccp;
-	int rc;
-
-	srand(time(NULL));
-	tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
-	msgb_talloc_ctx_init(tall_bsc_ctx, 0);
-
-	signal(SIGINT, &signal_handler);
-	signal(SIGTERM, &signal_handler);
-	signal(SIGABRT, &signal_handler);
-	signal(SIGUSR1, &signal_handler);
-	signal(SIGUSR2, &signal_handler);
-
-	osmo_init_ignore_signals();
-	osmo_init_logging(&gprs_log_info);
-	osmo_stats_init(tall_bsc_ctx);
-
-	vty_info.copyright = openbsc_copyright;
-	vty_init(&vty_info);
-	logging_vty_add_cmds(NULL);
-	osmo_stats_vty_add_cmds(&gprs_log_info);
-	sgsn_vty_init(&sgsn_inst.cfg);
-	ctrl_vty_init(tall_bsc_ctx);
-	osmo_ss7_init();
-
-	handle_options(argc, argv);
-
-	rate_ctr_init(tall_bsc_ctx);
-
-	gprs_ns_set_log_ss(DNS);
-	bssgp_set_log_ss(DBSSGP);
-
-	sgsn_nsi = gprs_ns_instantiate(&sgsn_ns_cb, tall_bsc_ctx);
-	if (!sgsn_nsi) {
-		LOGP(DGPRS, LOGL_ERROR, "Unable to instantiate NS\n");
-		exit(1);
-	}
-	bssgp_nsi = sgsn_inst.cfg.nsi = sgsn_nsi;
-
-	gprs_llc_init("/usr/local/lib/osmocom/crypt/");
-	sgsn_rate_ctr_init();
-	sgsn_inst_init();
-
-	gprs_ns_vty_init(bssgp_nsi);
-	bssgp_vty_init();
-	gprs_llc_vty_init();
-	gprs_sndcp_vty_init();
-	sgsn_auth_init();
-	sgsn_cdr_init(&sgsn_inst);
-	/* FIXME: register signal handler for SS_L_NS */
-
-	rc = sgsn_parse_config(sgsn_inst.config_file);
-	if (rc < 0) {
-		LOGP(DGPRS, LOGL_FATAL, "Error in config file\n");
-		exit(2);
-	}
-
-	/* start telnet after reading config for vty_get_bind_addr() */
-	rc = telnet_init_dynif(tall_bsc_ctx, &dummy_network,
-			       vty_get_bind_addr(), OSMO_VTY_PORT_SGSN);
-	if (rc < 0)
-		exit(1);
-
-	/* start control interface after reading config for
-	 * ctrl_vty_get_bind_addr() */
-	ctrl = sgsn_controlif_setup(NULL, ctrl_vty_get_bind_addr(),
-				    OSMO_CTRL_PORT_SGSN);
-	if (!ctrl) {
-		LOGP(DGPRS, LOGL_ERROR, "Failed to create CTRL interface.\n");
-		exit(1);
-	}
-
-	if (sgsn_ctrl_cmds_install() != 0) {
-		LOGP(DGPRS, LOGL_ERROR, "Failed to install CTRL commands.\n");
-		exit(1);
-	}
-
-
-	rc = sgsn_gtp_init(&sgsn_inst);
-	if (rc) {
-		LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen on GTP socket\n");
-		exit(2);
-	}
-
-	rc = gprs_subscr_init(&sgsn_inst);
-	if (rc < 0) {
-		LOGP(DGPRS, LOGL_FATAL, "Cannot set up subscriber management\n");
-		exit(2);
-	}
-
-	rc = gprs_ns_nsip_listen(sgsn_nsi);
-	if (rc < 0) {
-		LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen on NSIP socket\n");
-		exit(2);
-	}
-
-	rc = gprs_ns_frgre_listen(sgsn_nsi);
-	if (rc < 0) {
-		LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen GRE "
-			"socket. Do you have CAP_NET_RAW?\n");
-		exit(2);
-	}
-
-	if (sgsn->cfg.dynamic_lookup) {
-		if (sgsn_ares_init(sgsn) != 0) {
-			LOGP(DGPRS, LOGL_FATAL,
-				"Failed to initialize c-ares(%d)\n", rc);
-			exit(4);
-		}
-	}
-
-#ifdef BUILD_IU
-	sccp = osmo_sccp_simple_client(tall_bsc_ctx, "OsmoSGSN",
-				       2 /* FIXME: configurable */,
-				       OSMO_SS7_ASP_PROT_M3UA, 0,
-				       "127.0.0.4" /* FIXME: configurable */,
-				       M3UA_PORT,
-				       "127.0.0.1" /* FIXME: configurable */);
-	if (!sccp) {
-		printf("Setting up SCCP client failed.\n");
-		return 8;
-	}
-
-	ranap_iu_init(tall_bsc_ctx, DRANAP, "OsmoSGSN-IuPS", sccp, gsm0408_gprs_rcvmsg_iu, sgsn_ranap_iu_event);
-#endif
-
-	if (daemonize) {
-		rc = osmo_daemonize();
-		if (rc < 0) {
-			perror("Error during daemonize");
-			exit(1);
-		}
-	}
-
-	while (1) {
-		rc = osmo_select_main(0);
-		if (rc < 0)
-			exit(3);
-	}
-
-	/* not reached */
-	exit(0);
-}
diff --git a/src/gprs/sgsn_vty.c b/src/gprs/sgsn_vty.c
deleted file mode 100644
index 3a5b2ca..0000000
--- a/src/gprs/sgsn_vty.c
+++ /dev/null
@@ -1,1329 +0,0 @@
-/*
- * (C) 2010-2016 by Harald Welte <laforge@gnumonks.org>
- * (C) 2010 by On-Waves
- * (C) 2015 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/>.
- *
- */
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <time.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
-#include <osmocom/gsm/apn.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/sgsn.h>
-#include <osmocom/gprs/gprs_ns.h>
-#include <openbsc/gprs_sgsn.h>
-#include <openbsc/vty.h>
-#include <openbsc/gsup_client.h>
-
-#include <osmocom/vty/command.h>
-#include <osmocom/vty/vty.h>
-#include <osmocom/vty/misc.h>
-#include <osmocom/crypt/gprs_cipher.h>
-#include <osmocom/abis/ipa.h>
-
-#include <pdp.h>
-
-#include "../../bscconfig.h"
-
-#ifdef BUILD_IU
-#include <osmocom/ranap/iu_client.h>
-#endif
-
-static struct sgsn_config *g_cfg = NULL;
-
-const struct value_string sgsn_auth_pol_strs[] = {
-	{ SGSN_AUTH_POLICY_OPEN,	"accept-all" },
-	{ SGSN_AUTH_POLICY_CLOSED,	"closed" },
-	{ SGSN_AUTH_POLICY_ACL_ONLY,    "acl-only" },
-	{ SGSN_AUTH_POLICY_REMOTE,      "remote" },
-	{ 0, NULL }
-};
-
-/* Section 11.2.2 / Table 11.3a GPRS Mobility management timers – MS side */
-#define GSM0408_T3312_SECS	(10*60)	/* periodic RAU interval, default 54min */
-
-/* Section 11.2.2 / Table 11.4 MM timers netwokr side */
-#define GSM0408_T3322_SECS	6	/* DETACH_REQ -> DETACH_ACC */
-#define GSM0408_T3350_SECS	6	/* waiting for ATT/RAU/TMSI COMPL */
-#define GSM0408_T3360_SECS	6	/* waiting for AUTH/CIPH RESP */
-#define GSM0408_T3370_SECS	6	/* waiting for ID RESP */
-
-/* Section 11.2.2 / Table 11.4a MM timers network side */
-#define GSM0408_T3313_SECS	30	/* waiting for paging response */
-#define GSM0408_T3314_SECS	44	/* force to STBY on expiry, Ready timer */
-#define GSM0408_T3316_SECS	44
-
-/* Section 11.3 / Table 11.2d Timers of Session Management - network side */
-#define GSM0408_T3385_SECS	8	/* wait for ACT PDP CTX REQ */
-#define GSM0408_T3386_SECS	8	/* wait for MODIFY PDP CTX ACK */
-#define GSM0408_T3395_SECS	8	/* wait for DEACT PDP CTX ACK */
-#define GSM0408_T3397_SECS	8	/* wait for DEACT AA PDP CTX ACK */
-
-#define DECLARE_TIMER(number, doc) \
-    DEFUN(cfg_sgsn_T##number,					\
-      cfg_sgsn_T##number##_cmd,					\
-      "timer t" #number  " <0-65535>",				\
-      "Configure GPRS Timers\n"					\
-      doc "\nTimer Value in seconds\n")				\
-{								\
-	int value = atoi(argv[0]);				\
-								\
-	if (value < 0 || value > 65535) {			\
-		vty_out(vty, "Timer value %s out of range.%s",	\
-		        argv[0], VTY_NEWLINE);			\
-		return CMD_WARNING;				\
-	}							\
-								\
-	g_cfg->timers.T##number = value;			\
-	return CMD_SUCCESS;					\
-}
-
-DECLARE_TIMER(3312, "Periodic RA Update timer (s)")
-DECLARE_TIMER(3322, "Detach request -> accept timer (s)")
-DECLARE_TIMER(3350, "Waiting for ATT/RAU/TMSI_COMPL timer (s)")
-DECLARE_TIMER(3360, "Waiting for AUTH/CIPH response timer (s)")
-DECLARE_TIMER(3370, "Waiting for IDENTITY response timer (s)")
-
-DECLARE_TIMER(3313, "Waiting for paging response timer (s)")
-DECLARE_TIMER(3314, "Force to STANDBY on expiry timer (s)")
-DECLARE_TIMER(3316, "AA-Ready timer (s)")
-
-DECLARE_TIMER(3385, "Wait for ACT PDP CTX REQ timer (s)")
-DECLARE_TIMER(3386, "Wait for MODIFY PDP CTX ACK timer (s)")
-DECLARE_TIMER(3395, "Wait for DEACT PDP CTX ACK timer (s)")
-DECLARE_TIMER(3397, "Wait for DEACT AA PDP CTX ACK timer (s)")
-
-
-#define GSM48_MAX_APN_LEN	102	/* 10.5.6.1 */
-/** Copy apn to a static buffer, replacing the length octets in apn_enc with '.'
- * and terminating with a '\0'. Return the static buffer.
- * len: the length of the encoded APN (which has no terminating zero).
- */
-static char *gprs_apn2str(uint8_t *apn, unsigned int len)
-{
-	static char apnbuf[GSM48_MAX_APN_LEN+1];
-
-	if (!apn)
-		return "";
-	osmo_apn_to_str(apnbuf, apn, len);
-
-	return apnbuf+1;
-}
-
-char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
-{
-	static char str[INET6_ADDRSTRLEN + 10];
-
-	if (!pdpa || len < 2)
-		return "none";
-
-	switch (pdpa[0] & 0x0f) {
-	case PDP_TYPE_ORG_IETF:
-		switch (pdpa[1]) {
-		case PDP_TYPE_N_IETF_IPv4:
-			if (len < 2 + 4)
-				break;
-			strcpy(str, "IPv4 ");
-			inet_ntop(AF_INET, pdpa+2, str+5, sizeof(str)-5);
-			return str;
-		case PDP_TYPE_N_IETF_IPv6:
-			if (len < 2 + 8)
-				break;
-			strcpy(str, "IPv6 ");
-			inet_ntop(AF_INET6, pdpa+2, str+5, sizeof(str)-5);
-			return str;
-		default:
-			break;
-		}
-		break;
-	case PDP_TYPE_ORG_ETSI:
-		if (pdpa[1] == PDP_TYPE_N_ETSI_PPP)
-			return "PPP";
-		break;
-	default:
-		break;
-	}
-
-	return "invalid";
-}
-
-static struct cmd_node sgsn_node = {
-	SGSN_NODE,
-	"%s(config-sgsn)# ",
-	1,
-};
-
-static int config_write_sgsn(struct vty *vty)
-{
-	struct sgsn_ggsn_ctx *gctx;
-	struct imsi_acl_entry *acl;
-	struct apn_ctx *actx;
-	struct ares_addr_node *server;
-
-	vty_out(vty, "sgsn%s", VTY_NEWLINE);
-
-	vty_out(vty, " gtp local-ip %s%s",
-		inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
-
-	llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
-		if (gctx->id == UINT32_MAX)
-			continue;
-
-		vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
-			inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
-		vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
-			gctx->gtp_version, VTY_NEWLINE);
-	}
-
-	if (sgsn->cfg.dynamic_lookup)
-		vty_out(vty, " ggsn dynamic%s", VTY_NEWLINE);
-
-	for (server = sgsn->ares_servers; server; server = server->next)
-		vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
-
-	if (g_cfg->cipher != GPRS_ALGO_GEA0)
-		vty_out(vty, " encryption %s%s",
-			get_value_string(gprs_cipher_names, g_cfg->cipher),
-			VTY_NEWLINE);
-	if (g_cfg->gsup_server_addr.sin_addr.s_addr)
-		vty_out(vty, " gsup remote-ip %s%s",
-			inet_ntoa(g_cfg->gsup_server_addr.sin_addr), VTY_NEWLINE);
-	if (g_cfg->gsup_server_port)
-		vty_out(vty, " gsup remote-port %d%s",
-			g_cfg->gsup_server_port, VTY_NEWLINE);
-	vty_out(vty, " auth-policy %s%s",
-		get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
-		VTY_NEWLINE);
-
-	vty_out(vty, " gsup oap-id %d%s",
-		(int)g_cfg->oap.client_id, VTY_NEWLINE);
-	if (g_cfg->oap.secret_k_present != 0)
-		vty_out(vty, " gsup oap-k %s%s",
-			osmo_hexdump_nospc(g_cfg->oap.secret_k, sizeof(g_cfg->oap.secret_k)),
-			VTY_NEWLINE);
-	if (g_cfg->oap.secret_opc_present != 0)
-		vty_out(vty, " gsup oap-opc %s%s",
-			osmo_hexdump_nospc(g_cfg->oap.secret_opc, sizeof(g_cfg->oap.secret_opc)),
-			VTY_NEWLINE);
-
-	llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
-		vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
-
-	if (llist_empty(&sgsn_apn_ctxts))
-		vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
-	llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
-		if (strlen(actx->imsi_prefix) > 0)
-			vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
-				actx->name, actx->imsi_prefix, actx->ggsn->id,
-				VTY_NEWLINE);
-		else
-			vty_out(vty, " apn %s ggsn %u%s", actx->name,
-				actx->ggsn->id, VTY_NEWLINE);
-	}
-
-	if (g_cfg->cdr.filename)
-		vty_out(vty, " cdr filename %s%s", g_cfg->cdr.filename, VTY_NEWLINE);
-	else
-		vty_out(vty, " no cdr filename%s", VTY_NEWLINE);
-	vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
-
-	vty_out(vty, " timer t3312 %d%s", g_cfg->timers.T3312, VTY_NEWLINE);
-	vty_out(vty, " timer t3322 %d%s", g_cfg->timers.T3322, VTY_NEWLINE);
-	vty_out(vty, " timer t3350 %d%s", g_cfg->timers.T3350, VTY_NEWLINE);
-	vty_out(vty, " timer t3360 %d%s", g_cfg->timers.T3360, VTY_NEWLINE);
-	vty_out(vty, " timer t3370 %d%s", g_cfg->timers.T3370, VTY_NEWLINE);
-	vty_out(vty, " timer t3313 %d%s", g_cfg->timers.T3313, VTY_NEWLINE);
-	vty_out(vty, " timer t3314 %d%s", g_cfg->timers.T3314, VTY_NEWLINE);
-	vty_out(vty, " timer t3316 %d%s", g_cfg->timers.T3316, VTY_NEWLINE);
-	vty_out(vty, " timer t3385 %d%s", g_cfg->timers.T3385, VTY_NEWLINE);
-	vty_out(vty, " timer t3386 %d%s", g_cfg->timers.T3386, VTY_NEWLINE);
-	vty_out(vty, " timer t3395 %d%s", g_cfg->timers.T3395, VTY_NEWLINE);
-	vty_out(vty, " timer t3397 %d%s", g_cfg->timers.T3397, VTY_NEWLINE);
-
-	if (g_cfg->pcomp_rfc1144.active) {
-		vty_out(vty, " compression rfc1144 active slots %d%s",
-			g_cfg->pcomp_rfc1144.s01 + 1, VTY_NEWLINE);
-	} else if (g_cfg->pcomp_rfc1144.passive) {
-		vty_out(vty, " compression rfc1144 passive%s", VTY_NEWLINE);
-	} else
-		vty_out(vty, " no compression rfc1144%s", VTY_NEWLINE);
-
-	if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 1) {
-		vty_out(vty,
-			" compression v42bis active direction sgsn codewords %d strlen %d%s",
-			g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
-			VTY_NEWLINE);
-	} else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 2) {
-		vty_out(vty,
-			" compression v42bis active direction ms codewords %d strlen %d%s",
-			g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
-			VTY_NEWLINE);
-	} else if (g_cfg->dcomp_v42bis.active && g_cfg->dcomp_v42bis.p0 == 3) {
-		vty_out(vty,
-			" compression v42bis active direction both codewords %d strlen %d%s",
-			g_cfg->dcomp_v42bis.p1, g_cfg->dcomp_v42bis.p2,
-			VTY_NEWLINE);
-	} else if (g_cfg->dcomp_v42bis.passive) {
-		vty_out(vty, " compression v42bis passive%s", VTY_NEWLINE);
-	} else
-		vty_out(vty, " no compression v42bis%s", VTY_NEWLINE);
-
-#ifdef BUILD_IU
-	ranap_iu_vty_config_write(vty, " ");
-#endif
-
-	return CMD_SUCCESS;
-}
-
-#define SGSN_STR	"Configure the SGSN\n"
-#define GGSN_STR	"Configure the GGSN information\n"
-
-DEFUN(cfg_sgsn, cfg_sgsn_cmd,
-	"sgsn",
-	SGSN_STR)
-{
-	vty->node = SGSN_NODE;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
-	"gtp local-ip A.B.C.D",
-	"GTP Parameters\n"
-	"Set the IP address for the local GTP bind\n"
-	"IPv4 Address\n")
-{
-	inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
-	"ggsn <0-255> remote-ip A.B.C.D",
-	GGSN_STR "GGSN Number\n" IP_STR "IPv4 Address\n")
-{
-	uint32_t id = atoi(argv[0]);
-	struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
-
-	inet_aton(argv[1], &ggc->remote_addr);
-
-	return CMD_SUCCESS;
-}
-
-#if 0
-DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
-	"ggsn <0-255> remote-port <0-65535>",
-	"")
-{
-	uint32_t id = atoi(argv[0]);
-	struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
-	uint16_t port = atoi(argv[1]);
-
-}
-#endif
-
-DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
-	"ggsn <0-255> gtp-version (0|1)",
-	GGSN_STR "GGSN Number\n" "GTP Version\n"
-	"Version 0\n" "Version 1\n")
-{
-	uint32_t id = atoi(argv[0]);
-	struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
-
-	if (atoi(argv[1]))
-		ggc->gtp_version = 1;
-	else
-		ggc->gtp_version = 0;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_ggsn_dynamic_lookup, cfg_ggsn_dynamic_lookup_cmd,
-	"ggsn dynamic",
-	GGSN_STR "Enable dynamic GRX based look-up (requires restart)\n")
-{
-	sgsn->cfg.dynamic_lookup = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
-	"grx-dns-add A.B.C.D",
-	"Add DNS server\nIPv4 address\n")
-{
-	struct ares_addr_node *node = talloc_zero(tall_bsc_ctx, struct ares_addr_node);
-	node->family = AF_INET;
-	inet_aton(argv[0], &node->addr.addr4);
-
-	node->next = sgsn->ares_servers;
-	sgsn->ares_servers = node;
-	return CMD_SUCCESS;
-}
-
-#define APN_STR	"Configure the information per APN\n"
-#define APN_GW_STR "The APN gateway name optionally prefixed by '*' (wildcard)\n"
-
-static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
-				const char *imsi_prefix, int ggsn_id)
-{
-	struct apn_ctx *actx;
-	struct sgsn_ggsn_ctx *ggsn;
-
-	ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
-	if (ggsn == NULL) {
-		vty_out(vty, "%% a GGSN with id %d has not been defined%s",
-			ggsn_id, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	actx = sgsn_apn_ctx_find_alloc(apn_str, imsi_prefix);
-	if (!actx) {
-		vty_out(vty, "%% unable to create APN context for %s/%s%s",
-			apn_str, imsi_prefix, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	actx->ggsn = ggsn;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
-	"apn APNAME ggsn <0-255>",
-	APN_STR APN_GW_STR
-	"Select the GGSN to use when the APN gateway prefix matches\n"
-	"The GGSN id")
-{
-
-	return add_apn_ggsn_mapping(vty, argv[0], "", atoi(argv[1]));
-}
-
-DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
-	"apn APNAME imsi-prefix IMSIPRE ggsn <0-255>",
-	APN_STR APN_GW_STR
-	"Restrict rule to a certain IMSI prefix\n"
-	"An IMSI prefix\n"
-	"Select the GGSN to use when APN gateway and IMSI prefix match\n"
-	"The GGSN id")
-{
-
-	return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
-}
-
-const struct value_string gprs_mm_st_strs[] = {
-	{ GMM_DEREGISTERED, "DEREGISTERED" },
-	{ GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },
-	{ GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },
-	{ GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
-	{ GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
-	{ 0, NULL }
-};
-
-static char *gtp_ntoa(struct ul16_t *ul)
-{
-	if (ul->l == 4) {
-		struct in_addr *ia = (struct in_addr *) ul;
-		return inet_ntoa(*ia);
-	} else {
-		return "UNKNOWN";
-	}
-}
-
-static void vty_dump_pdp(struct vty *vty, const char *pfx,
-			 struct sgsn_pdp_ctx *pdp)
-{
-	const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
-	vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u, TI: %u%s",
-		pfx, imsi, pdp->sapi, pdp->nsapi, pdp->ti, VTY_NEWLINE);
-	if (pdp->lib) {
-		vty_out(vty, "%s  APN: %s%s", pfx,
-			gprs_apn2str(pdp->lib->apn_use.v, pdp->lib->apn_use.l),
-			VTY_NEWLINE);
-		vty_out(vty, "%s  PDP Address: %s%s", pfx,
-			gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
-			VTY_NEWLINE);
-		vty_out(vty, "%s  GTP Local Control(%s / TEIC: 0x%08x) ", pfx,
-			gtp_ntoa(&pdp->lib->gsnlc), pdp->lib->teic_own);
-		vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
-			gtp_ntoa(&pdp->lib->gsnlu), pdp->lib->teid_own, VTY_NEWLINE);
-		vty_out(vty, "%s  GTP Remote Control(%s / TEIC: 0x%08x) ", pfx,
-			gtp_ntoa(&pdp->lib->gsnrc), pdp->lib->teic_gn);
-		vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
-			gtp_ntoa(&pdp->lib->gsnru), pdp->lib->teid_gn, VTY_NEWLINE);
-	}
-
-	vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
-}
-
-static void vty_dump_mmctx(struct vty *vty, const char *pfx,
-			   struct sgsn_mm_ctx *mm, int pdp)
-{
-	vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
-		pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
-	vty_out(vty, "%s  MSISDN: %s, TLLI: %08x%s HLR: %s",
-		pfx, mm->msisdn, mm->gb.tlli, mm->hlr, VTY_NEWLINE);
-	vty_out(vty, "%s  MM State: %s, Routeing Area: %u-%u-%u-%u, "
-		"Cell ID: %u%s", pfx,
-		get_value_string(gprs_mm_st_strs, mm->gmm_state),
-		mm->ra.mcc, mm->ra.mnc, mm->ra.lac, mm->ra.rac,
-		mm->gb.cell_id, VTY_NEWLINE);
-
-	vty_out_rate_ctr_group(vty, " ", mm->ctrg);
-
-	if (pdp) {
-		struct sgsn_pdp_ctx *pdp;
-
-		llist_for_each_entry(pdp, &mm->pdp_list, list)
-			vty_dump_pdp(vty, "  ", pdp);
-	}
-}
-
-DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
-      SHOW_STR "Display information about the SGSN")
-{
-	if (sgsn->gsup_client) {
-		struct ipa_client_conn *link = sgsn->gsup_client->link;
-		vty_out(vty,
-			"  Remote authorization: %sconnected to %s:%d via GSUP%s",
-			sgsn->gsup_client->is_connected ? "" : "not ",
-			link->addr, link->port,
-			VTY_NEWLINE);
-	}
-	/* FIXME: statistics */
-	return CMD_SUCCESS;
-}
-
-#define MMCTX_STR "MM Context\n"
-#define INCLUDE_PDP_STR "Include PDP Context Information\n"
-
-#if 0
-DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
-	"show mm-context tlli HEX [pdp]",
-	SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
-{
-	uint32_t tlli;
-	struct sgsn_mm_ctx *mm;
-
-	tlli = strtoul(argv[0], NULL, 16);
-	mm = sgsn_mm_ctx_by_tlli(tlli);
-	if (!mm) {
-		vty_out(vty, "No MM context for TLLI %08x%s",
-			tlli, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-	vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
-	return CMD_SUCCESS;
-}
-#endif
-
-DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
-	"show mm-context imsi IMSI [pdp]",
-	SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
-	INCLUDE_PDP_STR)
-{
-	struct sgsn_mm_ctx *mm;
-
-	mm = sgsn_mm_ctx_by_imsi(argv[0]);
-	if (!mm) {
-		vty_out(vty, "No MM context for IMSI %s%s",
-			argv[0], VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-	vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
-	return CMD_SUCCESS;
-}
-
-DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
-	"show mm-context all [pdp]",
-	SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
-{
-	struct sgsn_mm_ctx *mm;
-
-	llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
-		vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
-	"show pdp-context all",
-	SHOW_STR "Display information on PDP Context\n" "Show everything\n")
-{
-	struct sgsn_pdp_ctx *pdp;
-
-	llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
-		vty_dump_pdp(vty, "", pdp);
-
-	return CMD_SUCCESS;
-}
-
-
-DEFUN(imsi_acl, cfg_imsi_acl_cmd,
-	"imsi-acl (add|del) IMSI",
-	"Access Control List of foreign IMSIs\n"
-	"Add IMSI to ACL\n"
-	"Remove IMSI from ACL\n"
-	"IMSI of subscriber\n")
-{
-	char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS+1];
-	const char *op = argv[0];
-	const char *imsi = imsi_sanitized;
-	int rc;
-
-	/* Sanitize IMSI */
-	if (strlen(argv[1]) > GSM23003_IMSI_MAX_DIGITS) {
-		vty_out(vty, "%% IMSI (%s) too long -- ignored!%s",
-			argv[1], VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-	memset(imsi_sanitized, '0', sizeof(imsi_sanitized));
-	strcpy(imsi_sanitized+GSM23003_IMSI_MAX_DIGITS-strlen(argv[1]),argv[1]);
-
-	if (!strcmp(op, "add"))
-		rc = sgsn_acl_add(imsi, g_cfg);
-	else
-		rc = sgsn_acl_del(imsi, g_cfg);
-
-	if (rc < 0) {
-		vty_out(vty, "%% unable to %s ACL%s", op, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_encrypt, cfg_encrypt_cmd,
-      "encryption (GEA0|GEA1|GEA2|GEA3|GEA4)",
-      "Set encryption algorithm for SGSN\n"
-      "Use GEA0 (no encryption)\n"
-      "Use GEA1\nUse GEA2\nUse GEA3\nUse GEA4\n")
-{
-	enum gprs_ciph_algo c = get_string_value(gprs_cipher_names, argv[0]);
-	if (c != GPRS_ALGO_GEA0) {
-		if (!gprs_cipher_supported(c)) {
-			vty_out(vty, "%% cipher %s is unsupported in current version%s", argv[0], VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-
-		if (!g_cfg->require_authentication) {
-			vty_out(vty, "%% unable to use encryption %s without authentication: please adjust auth-policy%s",
-				argv[0], VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-	}
-
-	g_cfg->cipher = c;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
-	"auth-policy (accept-all|closed|acl-only|remote)",
-	"Autorization Policy of SGSN\n"
-	"Accept all IMSIs (DANGEROUS)\n"
-	"Accept only home network subscribers or those in the ACL\n"
-	"Accept only subscribers in the ACL\n"
-	"Use remote subscription data only (HLR)\n")
-{
-	int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
-	OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
-	g_cfg->auth_policy = val;
-	g_cfg->require_authentication = (val == SGSN_AUTH_POLICY_REMOTE);
-	g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
-
-	return CMD_SUCCESS;
-}
-
-/* Subscriber */
-#include <openbsc/gprs_subscriber.h>
-
-static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int pending)
-{
-#if 0
-	char expire_time[200];
-#endif
-	struct gsm_auth_tuple *at;
-	int at_idx;
-	struct sgsn_subscriber_pdp_data *pdp;
-
-	vty_out(vty, "    Authorized: %d%s",
-		gsub->authorized, VTY_NEWLINE);
-	vty_out(vty, "    LAC: %d/0x%x%s",
-		gsub->lac, gsub->lac, VTY_NEWLINE);
-	vty_out(vty, "    IMSI: %s%s", gsub->imsi, VTY_NEWLINE);
-	if (gsub->tmsi != GSM_RESERVED_TMSI)
-		vty_out(vty, "    TMSI: %08X%s", gsub->tmsi,
-			VTY_NEWLINE);
-	if (gsub->sgsn_data->msisdn_len > 0)
-		vty_out(vty, "    MSISDN (BCD): %s%s",
-			osmo_hexdump(gsub->sgsn_data->msisdn,
-				     gsub->sgsn_data->msisdn_len),
-			VTY_NEWLINE);
-
-	if (strlen(gsub->imei) > 0)
-		vty_out(vty, "    IMEI: %s%s", gsub->imei, VTY_NEWLINE);
-
-	for (at_idx = 0; at_idx < ARRAY_SIZE(gsub->sgsn_data->auth_triplets);
-	     at_idx++) {
-		at = &gsub->sgsn_data->auth_triplets[at_idx];
-		if (at->key_seq == GSM_KEY_SEQ_INVAL)
-			continue;
-
-		vty_out(vty, "    A3A8 tuple (used %d times): ",
-			at->use_count);
-		vty_out(vty, "     CKSN: %d, ",
-			at->key_seq);
-		if (at->vec.auth_types & OSMO_AUTH_TYPE_GSM) {
-			vty_out(vty, "RAND: %s, ",
-				osmo_hexdump(at->vec.rand,
-					     sizeof(at->vec.rand)));
-			vty_out(vty, "SRES: %s, ",
-				osmo_hexdump(at->vec.sres,
-					     sizeof(at->vec.sres)));
-			vty_out(vty, "Kc: %s%s",
-				osmo_hexdump(at->vec.kc,
-					     sizeof(at->vec.kc)), VTY_NEWLINE);
-		}
-		if (at->vec.auth_types & OSMO_AUTH_TYPE_UMTS) {
-			vty_out(vty, "     AUTN: %s, ",
-				osmo_hexdump(at->vec.autn,
-					     sizeof(at->vec.autn)));
-			vty_out(vty, "RES: %s, ",
-				osmo_hexdump(at->vec.res, at->vec.res_len));
-			vty_out(vty, "IK: %s, ",
-				osmo_hexdump(at->vec.ik, sizeof(at->vec.ik)));
-			vty_out(vty, "CK: %s, ",
-				osmo_hexdump(at->vec.ck, sizeof(at->vec.ck)));
-		}
-	}
-
-	llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
-		vty_out(vty, "    PDP info: Id: %d, Type: 0x%04x, APN: '%s' QoS: %s%s",
-			pdp->context_id, pdp->pdp_type, pdp->apn_str,
-			osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len),
-			VTY_NEWLINE);
-	}
-
-#if 0
-	/* print the expiration time of a subscriber */
-	if (gsub->expire_lu) {
-		strftime(expire_time, sizeof(expire_time),
-			 "%a, %d %b %Y %T %z", localtime(&gsub->expire_lu));
-		expire_time[sizeof(expire_time) - 1] = '\0';
-		vty_out(vty, "    Expiration Time: %s%s", expire_time, VTY_NEWLINE);
-	}
-#endif
-
-	if (gsub->flags)
-		vty_out(vty, "    Flags: %s%s%s%s%s%s",
-			gsub->flags & GPRS_SUBSCRIBER_FIRST_CONTACT ?
-			"FIRST_CONTACT " : "",
-			gsub->flags & GPRS_SUBSCRIBER_CANCELLED ?
-			"CANCELLED " : "",
-			gsub->flags & GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING ?
-			"UPDATE_LOCATION_PENDING " : "",
-			gsub->flags & GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING ?
-			"AUTH_INFO_PENDING " : "",
-			gsub->flags & GPRS_SUBSCRIBER_ENABLE_PURGE ?
-			"ENABLE_PURGE " : "",
-			VTY_NEWLINE);
-
-	vty_out(vty, "    Use count: %u%s", gsub->use_count, VTY_NEWLINE);
-}
-
-DEFUN(show_subscr_cache,
-      show_subscr_cache_cmd,
-      "show subscriber cache",
-	SHOW_STR "Show information about subscribers\n"
-	"Display contents of subscriber cache\n")
-{
-	struct gprs_subscr *subscr;
-
-	llist_for_each_entry(subscr, gprs_subscribers, entry) {
-		vty_out(vty, "  Subscriber:%s", VTY_NEWLINE);
-		subscr_dump_full_vty(vty, subscr, 0);
-	}
-
-	return CMD_SUCCESS;
-}
-
-#define UPDATE_SUBSCR_STR "update-subscriber imsi IMSI "
-#define UPDATE_SUBSCR_HELP "Update subscriber list\n" \
-	"Use the IMSI to select the subscriber\n" \
-	"The IMSI\n"
-
-#define UPDATE_SUBSCR_INSERT_HELP "Insert data into the subscriber record\n"
-
-DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
-	UPDATE_SUBSCR_STR "insert auth-triplet <1-5> sres SRES rand RAND kc KC",
-	UPDATE_SUBSCR_HELP
-	UPDATE_SUBSCR_INSERT_HELP
-	"Update authentication triplet\n"
-	"Triplet index\n"
-	"Set SRES value\nSRES value (4 byte) in hex\n"
-	"Set RAND value\nRAND value (16 byte) in hex\n"
-	"Set Kc value\nKc value (8 byte) in hex\n")
-{
-	const char *imsi = argv[0];
-	const int cksn = atoi(argv[1]) - 1;
-	const char *sres_str = argv[2];
-	const char *rand_str = argv[3];
-	const char *kc_str = argv[4];
-	struct gsm_auth_tuple at = {0,};
-
-	struct gprs_subscr *subscr;
-
-	subscr = gprs_subscr_get_by_imsi(imsi);
-	if (!subscr) {
-		vty_out(vty, "%% unable get subscriber record for %s%s",
-			imsi, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	OSMO_ASSERT(subscr->sgsn_data);
-
-	if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
-		vty_out(vty, "%% invalid SRES value '%s'%s",
-			sres_str, VTY_NEWLINE);
-		goto failed;
-	}
-	if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
-		vty_out(vty, "%% invalid RAND value '%s'%s",
-			rand_str, VTY_NEWLINE);
-		goto failed;
-	}
-	if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
-		vty_out(vty, "%% invalid Kc value '%s'%s",
-			kc_str, VTY_NEWLINE);
-		goto failed;
-	}
-	at.key_seq = cksn;
-
-	subscr->sgsn_data->auth_triplets[cksn] = at;
-	subscr->sgsn_data->auth_triplets_updated = 1;
-
-	gprs_subscr_put(subscr);
-
-	return CMD_SUCCESS;
-
-failed:
-	gprs_subscr_put(subscr);
-	return CMD_SUCCESS;
-}
-
-DEFUN(update_subscr_cancel, update_subscr_cancel_cmd,
-	UPDATE_SUBSCR_STR "cancel (update-procedure|subscription-withdraw)",
-	UPDATE_SUBSCR_HELP
-	"Cancel (remove) subscriber record\n"
-	"The MS moved to another SGSN\n"
-	"The subscription is no longer valid\n")
-{
-	const char *imsi = argv[0];
-	const char *cancel_type = argv[1];
-
-	struct gprs_subscr *subscr;
-
-	subscr = gprs_subscr_get_by_imsi(imsi);
-	if (!subscr) {
-		vty_out(vty, "%% no subscriber record for %s%s",
-			imsi, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (strcmp(cancel_type, "update-procedure") == 0)
-		subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
-	else
-		subscr->sgsn_data->error_cause = GMM_CAUSE_IMPL_DETACHED;
-
-	gprs_subscr_cancel(subscr);
-	gprs_subscr_put(subscr);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(update_subscr_create, update_subscr_create_cmd,
-	UPDATE_SUBSCR_STR "create",
-	UPDATE_SUBSCR_HELP
-	"Create a subscriber entry\n")
-{
-	const char *imsi = argv[0];
-
-	struct gprs_subscr *subscr;
-
-	subscr = gprs_subscr_get_by_imsi(imsi);
-	if (subscr) {
-		vty_out(vty, "%% subscriber record already exists for %s%s",
-			imsi, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	subscr = gprs_subscr_get_or_create(imsi);
-	subscr->keep_in_ram = 1;
-	gprs_subscr_put(subscr);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(update_subscr_destroy, update_subscr_destroy_cmd,
-	UPDATE_SUBSCR_STR "destroy",
-	UPDATE_SUBSCR_HELP
-	"Destroy a subscriber entry\n")
-{
-	const char *imsi = argv[0];
-
-	struct gprs_subscr *subscr;
-
-	subscr = gprs_subscr_get_by_imsi(imsi);
-	if (!subscr) {
-		vty_out(vty, "%% subscriber record does not exist for %s%s",
-			imsi, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	subscr->keep_in_ram = 0;
-	subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
-	gprs_subscr_cancel(subscr);
-	if (subscr->use_count > 1)
-		vty_out(vty, "%% subscriber is still in use%s",
-			VTY_NEWLINE);
-	gprs_subscr_put(subscr);
-
-	return CMD_SUCCESS;
-}
-
-#define UL_ERR_STR "system-failure|data-missing|unexpected-data-value|" \
-		   "unknown-subscriber|roaming-not-allowed"
-
-#define UL_ERR_HELP \
-		"Force error code SystemFailure\n" \
-		"Force error code DataMissing\n" \
-		"Force error code UnexpectedDataValue\n" \
-		"Force error code UnknownSubscriber\n" \
-		"Force error code RoamingNotAllowed\n"
-
-DEFUN(update_subscr_update_location_result, update_subscr_update_location_result_cmd,
-	UPDATE_SUBSCR_STR "update-location-result (ok|" UL_ERR_STR ")",
-	UPDATE_SUBSCR_HELP
-	"Complete the update location procedure\n"
-	"The update location request succeeded\n"
-	UL_ERR_HELP)
-{
-	const char *imsi = argv[0];
-	const char *ret_code_str = argv[1];
-
-	struct gprs_subscr *subscr;
-
-	const struct value_string cause_mapping[] = {
-		{ GMM_CAUSE_NET_FAIL,		"system-failure" },
-		{ GMM_CAUSE_INV_MAND_INFO,	"data-missing" },
-		{ GMM_CAUSE_PROTO_ERR_UNSPEC,   "unexpected-data-value" },
-		{ GMM_CAUSE_IMSI_UNKNOWN,       "unknown-subscriber" },
-		{ GMM_CAUSE_GPRS_NOTALLOWED,    "roaming-not-allowed" },
-		{ 0, NULL }
-	};
-
-	subscr = gprs_subscr_get_by_imsi(imsi);
-	if (!subscr) {
-		vty_out(vty, "%% unable to get subscriber record for %s%s",
-			imsi, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (strcmp(ret_code_str, "ok") == 0) {
-		subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
-		subscr->authorized = 1;
-	} else {
-		subscr->sgsn_data->error_cause =
-			get_string_value(cause_mapping, ret_code_str);
-		subscr->authorized = 0;
-	}
-
-	gprs_subscr_update(subscr);
-
-	gprs_subscr_put(subscr);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(update_subscr_update_auth_info, update_subscr_update_auth_info_cmd,
-	UPDATE_SUBSCR_STR "update-auth-info",
-	UPDATE_SUBSCR_HELP
-	"Complete the send authentication info procedure\n")
-{
-	const char *imsi = argv[0];
-
-	struct gprs_subscr *subscr;
-
-	subscr = gprs_subscr_get_by_imsi(imsi);
-	if (!subscr) {
-		vty_out(vty, "%% unable to get subscriber record for %s%s",
-			imsi, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	gprs_subscr_update_auth_info(subscr);
-
-	gprs_subscr_put(subscr);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gsup_remote_ip, cfg_gsup_remote_ip_cmd,
-	"gsup remote-ip A.B.C.D",
-	"GSUP Parameters\n"
-	"Set the IP address of the remote GSUP server\n"
-	"IPv4 Address\n")
-{
-	inet_aton(argv[0], &g_cfg->gsup_server_addr.sin_addr);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd,
-	"gsup remote-port <0-65535>",
-	"GSUP Parameters\n"
-	"Set the TCP port of the remote GSUP server\n"
-	"Remote TCP port\n")
-{
-	g_cfg->gsup_server_port = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd,
-	"gsup oap-id <0-65535>",
-	"GSUP Parameters\n"
-	"Set the SGSN's OAP client ID\nOAP client ID (0 == disabled)\n")
-{
-	/* VTY ensures range */
-	g_cfg->oap.client_id = (uint16_t)atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd,
-	"gsup oap-k K",
-	"GSUP Parameters\n"
-	"Set the OAP shared secret K\nK value (16 byte) hex\n")
-{
-	const char *k = argv[0];
-
-	g_cfg->oap.secret_k_present = 0;
-
-	if ((!k) || (strlen(k) == 0))
-		goto disable;
-
-	int k_len = osmo_hexparse(k,
-				  g_cfg->oap.secret_k,
-				  sizeof(g_cfg->oap.secret_k));
-	if (k_len != 16) {
-		vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s",
-			k_len, VTY_NEWLINE);
-		goto disable;
-	}
-
-	g_cfg->oap.secret_k_present = 1;
-	return CMD_SUCCESS;
-
-disable:
-	if (g_cfg->oap.client_id > 0) {
-		vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd,
-	"gsup oap-opc OPC",
-	"GSUP Parameters\n"
-	"Set the OAP shared secret OPC\nOPC value (16 byte) hex\n")
-{
-	const char *opc = argv[0];
-
-	g_cfg->oap.secret_opc_present = 0;
-
-	if ((!opc) || (strlen(opc) == 0))
-		goto disable;
-
-	int opc_len = osmo_hexparse(opc,
-				    g_cfg->oap.secret_opc,
-				    sizeof(g_cfg->oap.secret_opc));
-	if (opc_len != 16) {
-		vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s",
-			opc_len, VTY_NEWLINE);
-		goto disable;
-	}
-
-	g_cfg->oap.secret_opc_present = 1;
-	return CMD_SUCCESS;
-
-disable:
-	if (g_cfg->oap.client_id > 0) {
-		vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_apn_name, cfg_apn_name_cmd,
-	"access-point-name NAME",
-	"Configure a global list of allowed APNs\n"
-	"Add this NAME to the list\n")
-{
-	return add_apn_ggsn_mapping(vty, argv[0], "", 0);
-}
-
-DEFUN(cfg_no_apn_name, cfg_no_apn_name_cmd,
-	"no access-point-name NAME",
-	NO_STR "Configure a global list of allowed APNs\n"
-	"Remove entry with NAME\n")
-{
-	struct apn_ctx *apn_ctx = sgsn_apn_ctx_by_name(argv[0], "");
-	if (!apn_ctx)
-		return CMD_SUCCESS;
-
-	sgsn_apn_ctx_free(apn_ctx);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_cdr_filename, cfg_cdr_filename_cmd,
-	"cdr filename NAME",
-	"CDR\nSet filename\nname\n")
-{
-	talloc_free(g_cfg->cdr.filename);
-	g_cfg->cdr.filename = talloc_strdup(tall_vty_ctx, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_no_cdr_filename, cfg_no_cdr_filename_cmd,
-	"no cdr filename",
-	NO_STR "CDR\nDisable CDR generation\n")
-{
-	talloc_free(g_cfg->cdr.filename);
-	g_cfg->cdr.filename = NULL;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_cdr_interval, cfg_cdr_interval_cmd,
-	"cdr interval <1-2147483647>",
-	"CDR\nPDP periodic log interval\nSeconds\n")
-{
-	g_cfg->cdr.interval = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-#define COMPRESSION_STR "Configure compression\n"
-DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
-      "no compression rfc1144",
-      NO_STR COMPRESSION_STR "disable rfc1144 TCP/IP header compression\n")
-{
-	g_cfg->pcomp_rfc1144.active = 0;
-	g_cfg->pcomp_rfc1144.passive = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
-      "compression rfc1144 active slots <1-256>",
-      COMPRESSION_STR
-      "RFC1144 Header compresion scheme\n"
-      "Compression is actively proposed\n"
-      "Number of compression state slots\n"
-      "Number of compression state slots\n")
-{
-	g_cfg->pcomp_rfc1144.active = 1;
-	g_cfg->pcomp_rfc1144.passive = 1;
-	g_cfg->pcomp_rfc1144.s01 = atoi(argv[0]) - 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
-      "compression rfc1144 passive",
-      COMPRESSION_STR
-      "RFC1144 Header compresion scheme\n"
-      "Compression is available on request\n")
-{
-	g_cfg->pcomp_rfc1144.active = 0;
-	g_cfg->pcomp_rfc1144.passive = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
-      "no compression v42bis",
-      NO_STR COMPRESSION_STR "disable V.42bis data compression\n")
-{
-	g_cfg->dcomp_v42bis.active = 0;
-	g_cfg->dcomp_v42bis.passive = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
-      "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
-      COMPRESSION_STR
-      "V.42bis data compresion scheme\n"
-      "Compression is actively proposed\n"
-      "Direction in which the compression shall be active (p0)\n"
-      "Compress ms->sgsn direction only\n"
-      "Compress sgsn->ms direction only\n"
-      "Both directions\n"
-      "Number of codewords (p1)\n"
-      "Number of codewords\n"
-      "Maximum string length (p2)\n" "Maximum string length\n")
-{
-	g_cfg->dcomp_v42bis.active = 1;
-	g_cfg->dcomp_v42bis.passive = 1;
-
-	switch (argv[0][0]) {
-	case 'm':
-		g_cfg->dcomp_v42bis.p0 = 1;
-		break;
-	case 's':
-		g_cfg->dcomp_v42bis.p0 = 2;
-		break;
-	case 'b':
-		g_cfg->dcomp_v42bis.p0 = 3;
-		break;
-	}
-
-	g_cfg->dcomp_v42bis.p1 = atoi(argv[1]);
-	g_cfg->dcomp_v42bis.p2 = atoi(argv[2]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
-      "compression v42bis passive",
-      COMPRESSION_STR
-      "V.42bis data compresion scheme\n"
-      "Compression is available on request\n")
-{
-	g_cfg->dcomp_v42bis.active = 0;
-	g_cfg->dcomp_v42bis.passive = 1;
-	return CMD_SUCCESS;
-}
-
-int sgsn_vty_init(struct sgsn_config *cfg)
-{
-	g_cfg = cfg;
-
-	install_element_ve(&show_sgsn_cmd);
-	//install_element_ve(&show_mmctx_tlli_cmd);
-	install_element_ve(&show_mmctx_imsi_cmd);
-	install_element_ve(&show_mmctx_all_cmd);
-	install_element_ve(&show_pdpctx_all_cmd);
-	install_element_ve(&show_subscr_cache_cmd);
-
-	install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
-	install_element(ENABLE_NODE, &update_subscr_create_cmd);
-	install_element(ENABLE_NODE, &update_subscr_destroy_cmd);
-	install_element(ENABLE_NODE, &update_subscr_cancel_cmd);
-	install_element(ENABLE_NODE, &update_subscr_update_location_result_cmd);
-	install_element(ENABLE_NODE, &update_subscr_update_auth_info_cmd);
-
-	install_element(CONFIG_NODE, &cfg_sgsn_cmd);
-	install_node(&sgsn_node, config_write_sgsn);
-	vty_install_default(SGSN_NODE);
-	install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
-	install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
-	//install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
-	install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
-	install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
-	install_element(SGSN_NODE, &cfg_auth_policy_cmd);
-	install_element(SGSN_NODE, &cfg_encrypt_cmd);
-	install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
-	install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd);
-	install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd);
-	install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd);
-	install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd);
-	install_element(SGSN_NODE, &cfg_apn_ggsn_cmd);
-	install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd);
-	install_element(SGSN_NODE, &cfg_apn_name_cmd);
-	install_element(SGSN_NODE, &cfg_no_apn_name_cmd);
-	install_element(SGSN_NODE, &cfg_cdr_filename_cmd);
-	install_element(SGSN_NODE, &cfg_no_cdr_filename_cmd);
-	install_element(SGSN_NODE, &cfg_cdr_interval_cmd);
-	install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
-	install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
-
-	install_element(SGSN_NODE, &cfg_sgsn_T3312_cmd);
-	install_element(SGSN_NODE, &cfg_sgsn_T3322_cmd);
-	install_element(SGSN_NODE, &cfg_sgsn_T3350_cmd);
-	install_element(SGSN_NODE, &cfg_sgsn_T3360_cmd);
-	install_element(SGSN_NODE, &cfg_sgsn_T3370_cmd);
-	install_element(SGSN_NODE, &cfg_sgsn_T3313_cmd);
-	install_element(SGSN_NODE, &cfg_sgsn_T3314_cmd);
-	install_element(SGSN_NODE, &cfg_sgsn_T3316_cmd);
-	install_element(SGSN_NODE, &cfg_sgsn_T3385_cmd);
-	install_element(SGSN_NODE, &cfg_sgsn_T3386_cmd);
-	install_element(SGSN_NODE, &cfg_sgsn_T3395_cmd);
-	install_element(SGSN_NODE, &cfg_sgsn_T3397_cmd);
-
-	install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
-	install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
-	install_element(SGSN_NODE, &cfg_comp_rfc1144p_cmd);
-	install_element(SGSN_NODE, &cfg_no_comp_v42bis_cmd);
-	install_element(SGSN_NODE, &cfg_comp_v42bis_cmd);
-	install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
-
-#ifdef BUILD_IU
-	ranap_iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
-#endif
-	return 0;
-}
-
-int sgsn_parse_config(const char *config_file)
-{
-	int rc;
-
-	/* make sure sgsn_vty_init() was called before this */
-	OSMO_ASSERT(g_cfg);
-
-	g_cfg->timers.T3312 = GSM0408_T3312_SECS;
-	g_cfg->timers.T3322 = GSM0408_T3322_SECS;
-	g_cfg->timers.T3350 = GSM0408_T3350_SECS;
-	g_cfg->timers.T3360 = GSM0408_T3360_SECS;
-	g_cfg->timers.T3370 = GSM0408_T3370_SECS;
-	g_cfg->timers.T3313 = GSM0408_T3313_SECS;
-	g_cfg->timers.T3314 = GSM0408_T3314_SECS;
-	g_cfg->timers.T3316 = GSM0408_T3316_SECS;
-	g_cfg->timers.T3385 = GSM0408_T3385_SECS;
-	g_cfg->timers.T3386 = GSM0408_T3386_SECS;
-	g_cfg->timers.T3395 = GSM0408_T3395_SECS;
-	g_cfg->timers.T3397 = GSM0408_T3397_SECS;
-
-	rc = vty_read_config_file(config_file, NULL);
-	if (rc < 0) {
-		fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
-		return rc;
-	}
-
-	if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE
-	    && !(g_cfg->gsup_server_addr.sin_addr.s_addr
-		 && g_cfg->gsup_server_port)) {
-		fprintf(stderr, "Configuration error:"
-			" 'auth-policy remote' requires both"
-			" 'gsup remote-ip' and 'gsup remote-port'\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
diff --git a/src/gprs/slhc.c b/src/gprs/slhc.c
deleted file mode 100644
index cbdf8db..0000000
--- a/src/gprs/slhc.c
+++ /dev/null
@@ -1,813 +0,0 @@
-/*
- * Routines to compress and uncompress tcp packets (for transmission
- * over low speed serial lines).
- *
- * Copyright (c) 1989 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- *	Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
- *	- Initial distribution.
- *
- *
- * modified for KA9Q Internet Software Package by
- * Katie Stevens (dkstevens@ucdavis.edu)
- * University of California, Davis
- * Computing Services
- *	- 01-31-90	initial adaptation (from 1.19)
- *	PPP.05	02-15-90 [ks]
- *	PPP.08	05-02-90 [ks]	use PPP protocol field to signal compression
- *	PPP.15	09-90	 [ks]	improve mbuf handling
- *	PPP.16	11-02	 [karn]	substantially rewritten to use NOS facilities
- *
- *	- Feb 1991	Bill_Simpson@um.cc.umich.edu
- *			variable number of conversation slots
- *			allow zero or one slots
- *			separate routines
- *			status display
- *	- Jul 1994	Dmitry Gorodchanin
- *			Fixes for memory leaks.
- *      - Oct 1994      Dmitry Gorodchanin
- *                      Modularization.
- *	- Jan 1995	Bjorn Ekwall
- *			Use ip_fast_csum from ip.h
- *	- July 1995	Christos A. Polyzols
- *			Spotted bug in tcp option checking
- *
- *
- *	This module is a difficult issue. It's clearly inet code but it's also clearly
- *	driver code belonging close to PPP and SLIP
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <stdint.h>
-#include <arpa/inet.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/talloc.h>
-#include <openbsc/slhc.h>
-#include <openbsc/debug.h>
-
-#define ERR_PTR(x) x
-
-
-static unsigned char *encode(unsigned char *cp, unsigned short n);
-static long decode(unsigned char **cpp);
-static unsigned char * put16(unsigned char *cp, unsigned short x);
-static unsigned short pull16(unsigned char **cpp);
-
-/* Replacement for kernel space function ip_fast_csum() */
-static uint16_t ip_fast_csum(uint8_t *iph, int ihl)
-{
-	int i;
-	uint16_t temp;
-	uint32_t accumulator = 0xFFFF;
-
-	for(i=0;i<ihl*2;i++)
-	{
-		temp = ((*iph) << 8)&0xFF00;
-		iph++;
-		temp |= (*iph)&0xFF;
-		iph++;
-
-		accumulator+=temp;
-		if(accumulator>0xFFFF)
-		{
-			accumulator++;
-			accumulator&=0xFFFF;
-		}
-	}
-
-    return (uint16_t)(htons(~accumulator)&0xFFFF);
-}
-
-/* Replacement for kernel space function put_unaligned() */
-static void put_unaligned(uint16_t val, void *ptr)
-{
-	memcpy(ptr,&val,sizeof(val));
-}
-
-
-/* Allocate compression data structure
- *	slots must be in range 0 to 255 (zero meaning no compression)
- * Returns pointer to structure or ERR_PTR() on error.
- */
-struct slcompress *
-slhc_init(const void *ctx, int rslots, int tslots)
-{
-	register short i;
-	register struct cstate *ts;
-	struct slcompress *comp;
-
-	if (rslots < 0 || rslots > 255 || tslots < 0 || tslots > 255)
-		return NULL;
-
-	comp = (struct slcompress *)talloc_zero_size(ctx,sizeof(struct slcompress));
-	if (! comp)
-		goto out_fail;
-
-	if (rslots > 0) {
-		size_t rsize = rslots * sizeof(struct cstate);
-		comp->rstate = (struct cstate *) talloc_zero_size(ctx, rsize);
-		if (! comp->rstate)
-			goto out_free;
-		comp->rslot_limit = rslots - 1;
-	}
-
-	if (tslots > 0) {
-		size_t tsize = tslots * sizeof(struct cstate);
-		comp->tstate = (struct cstate *) talloc_zero_size(ctx, tsize);
-		if (! comp->tstate)
-			goto out_free2;
-		comp->tslot_limit = tslots - 1;
-	}
-
-	comp->xmit_oldest = 0;
-	comp->xmit_current = 255;
-	comp->recv_current = 255;
-	/*
-	 * don't accept any packets with implicit index until we get
-	 * one with an explicit index.  Otherwise the uncompress code
-	 * will try to use connection 255, which is almost certainly
-	 * out of range
-	 */
-	comp->flags |= SLF_TOSS;
-
-	if ( tslots > 0 ) {
-		ts = comp->tstate;
-		for(i = comp->tslot_limit; i > 0; --i){
-			ts[i].cs_this = i;
-			ts[i].next = &(ts[i - 1]);
-		}
-		ts[0].next = &(ts[comp->tslot_limit]);
-		ts[0].cs_this = 0;
-	}
-	return comp;
-
-out_free2:
-	talloc_free(comp->rstate);
-out_free:
-	talloc_free(comp);
-out_fail:
-	return NULL;
-}
-
-
-/* Free a compression data structure */
-void
-slhc_free(struct slcompress *comp)
-{
-	DEBUGP(DSLHC, "slhc_free(): Freeing compression states...\n");
-
-	if ( comp == NULLSLCOMPR )
-		return;
-
-	if ( comp->tstate != NULLSLSTATE )
-		talloc_free(comp->tstate );
-
-	if ( comp->rstate != NULLSLSTATE )
-		talloc_free( comp->rstate );
-
-	talloc_free( comp );
-}
-
-
-/* Put a short in host order into a char array in network order */
-static inline unsigned char *
-put16(unsigned char *cp, unsigned short x)
-{
-	*cp++ = x >> 8;
-	*cp++ = x;
-
-	return cp;
-}
-
-
-/* Encode a number */
-static unsigned char *
-encode(unsigned char *cp, unsigned short n)
-{
-	if(n >= 256 || n == 0){
-		*cp++ = 0;
-		cp = put16(cp,n);
-	} else {
-		*cp++ = n;
-	}
-
-	DEBUGP(DSLHC, "encode(): n=%04x\n",n);
-	return cp;
-}
-
-/* Pull a 16-bit integer in host order from buffer in network byte order */
-static unsigned short
-pull16(unsigned char **cpp)
-{
-	short rval;
-
-	rval = *(*cpp)++;
-	rval <<= 8;
-	rval |= *(*cpp)++;
-	return rval;
-}
-
-/* Decode a number */
-static long
-decode(unsigned char **cpp)
-{
-	register int x;
-
-	x = *(*cpp)++;
-	if(x == 0){
-		return pull16(cpp) & 0xffff;	/* pull16 returns -1 on error */
-	} else {
-		return x & 0xff;		/* -1 if PULLCHAR returned error */
-	}
-}
-
-/*
- * icp and isize are the original packet.
- * ocp is a place to put a copy if necessary.
- * cpp is initially a pointer to icp.  If the copy is used,
- *    change it to ocp.
- */
-
-int
-slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
-	unsigned char *ocp, unsigned char **cpp, int compress_cid)
-{
-	register struct cstate *ocs = &(comp->tstate[comp->xmit_oldest]);
-	register struct cstate *lcs = ocs;
-	register struct cstate *cs = lcs->next;
-	register unsigned long deltaS, deltaA;
-	register short changes = 0;
-	int hlen;
-	unsigned char new_seq[16];
-	register unsigned char *cp = new_seq;
-	struct iphdr *ip;
-	struct tcphdr *th, *oth;
-	__sum16 csum;
-
-
-	/*
-	 *	Don't play with runt packets.
-	 */
-
-	if(isize<sizeof(struct iphdr))
-		return isize;
-
-	ip = (struct iphdr *) icp;
-
-	/* Bail if this packet isn't TCP, or is an IP fragment */
-	if (ip->protocol != IPPROTO_TCP || (ntohs(ip->frag_off) & 0x3fff)) {
-		/* Send as regular IP */
-		if(ip->protocol != IPPROTO_TCP)
-			comp->sls_o_nontcp++;
-		else
-			comp->sls_o_tcp++;
-		DEBUGP(DSLHC, "slhc_compress(): Not a TCP packat, will not touch...\n");
-		return isize;
-	}
-	/* Extract TCP header */
-
-	th = (struct tcphdr *)(((unsigned char *)ip) + ip->ihl*4);
-	hlen = ip->ihl*4 + th->doff*4;
-
-	/*  Bail if the TCP packet isn't `compressible' (i.e., ACK isn't set or
-	 *  some other control bit is set). Also uncompressible if
-	 *  it's a runt.
-	 */
-	if(hlen > isize || th->syn || th->fin || th->rst ||
-	    ! (th->ack)){
-		/* TCP connection stuff; send as regular IP */
-		comp->sls_o_tcp++;
-		DEBUGP(DSLHC, "slhc_compress(): Packet is part of a TCP connection, will not touch...\n");
-		return isize;
-	}
-	/*
-	 * Packet is compressible -- we're going to send either a
-	 * COMPRESSED_TCP or UNCOMPRESSED_TCP packet.  Either way,
-	 * we need to locate (or create) the connection state.
-	 *
-	 * States are kept in a circularly linked list with
-	 * xmit_oldest pointing to the end of the list.  The
-	 * list is kept in lru order by moving a state to the
-	 * head of the list whenever it is referenced.  Since
-	 * the list is short and, empirically, the connection
-	 * we want is almost always near the front, we locate
-	 * states via linear search.  If we don't find a state
-	 * for the datagram, the oldest state is (re-)used.
-	 */
-
-	DEBUGP(DSLHC, "slhc_compress(): Compressible packet detected!\n");
-
-	for ( ; ; ) {
-		if( ip->saddr == cs->cs_ip.saddr
-		 && ip->daddr == cs->cs_ip.daddr
-		 && th->source == cs->cs_tcp.source
-		 && th->dest == cs->cs_tcp.dest)
-			goto found;
-
-		/* if current equal oldest, at end of list */
-		if ( cs == ocs )
-			break;
-		lcs = cs;
-		cs = cs->next;
-		comp->sls_o_searches++;
-	}
-	/*
-	 * Didn't find it -- re-use oldest cstate.  Send an
-	 * uncompressed packet that tells the other side what
-	 * connection number we're using for this conversation.
-	 *
-	 * Note that since the state list is circular, the oldest
-	 * state points to the newest and we only need to set
-	 * xmit_oldest to update the lru linkage.
-	 */
-
-	DEBUGP(DSLHC, "slhc_compress(): Header not yet seen, will memorize header for the next turn...\n");
-	comp->sls_o_misses++;
-	comp->xmit_oldest = lcs->cs_this;
-	goto uncompressed;
-
-found:
-		DEBUGP(DSLHC, "slhc_compress(): Header already seen, trying to compress...\n");
-	/*
-	 * Found it -- move to the front on the connection list.
-	 */
-	if(lcs == ocs) {
- 		/* found at most recently used */
-	} else if (cs == ocs) {
-		/* found at least recently used */
-		comp->xmit_oldest = lcs->cs_this;
-	} else {
-		/* more than 2 elements */
-		lcs->next = cs->next;
-		cs->next = ocs->next;
-		ocs->next = cs;
-	}
-
-	/*
-	 * Make sure that only what we expect to change changed.
-	 * Check the following:
-	 * IP protocol version, header length & type of service.
-	 * The "Don't fragment" bit.
-	 * The time-to-live field.
-	 * The TCP header length.
-	 * IP options, if any.
-	 * TCP options, if any.
-	 * If any of these things are different between the previous &
-	 * current datagram, we send the current datagram `uncompressed'.
-	 */
-	oth = &cs->cs_tcp;
-
-	/* Display a little more debug information about which of the
-	 * header fields changed unexpectedly */
-	if(ip->version != cs->cs_ip.version)
-		DEBUGP(DSLHC, "slhc_compress(): Unexpected change: ip->version != cs->cs_ip.version\n");
-	if(ip->ihl != cs->cs_ip.ihl)
-		DEBUGP(DSLHC, "slhc_compress(): Unexpected change: ip->ihl != cs->cs_ip.ihl\n");
-	if(ip->tos != cs->cs_ip.tos)
-		DEBUGP(DSLHC, "slhc_compress(): Unexpected change: ip->tos != cs->cs_ip.tos\n");
-	if((ip->frag_off & htons(0x4000)) != (cs->cs_ip.frag_off & htons(0x4000)))
-		DEBUGP(DSLHC, "slhc_compress(): Unexpected change: (ip->frag_off & htons(0x4000)) != (cs->cs_ip.frag_off & htons(0x4000))\n");
-	if(ip->ttl != cs->cs_ip.ttl)
-		DEBUGP(DSLHC, "slhc_compress(): Unexpected change: ip->ttl != cs->cs_ip.ttl\n");
-	if(th->doff != cs->cs_tcp.doff)
-		DEBUGP(DSLHC, "slhc_compress(): Unexpected change: th->doff != cs->cs_tcp.doff\n");
-	if(ip->ihl > 5 && memcmp(ip+1,cs->cs_ipopt,((ip->ihl)-5)*4) != 0) {
-		DEBUGP(DSLHC, "slhc_compress(): Unexpected change: (ip->ihl > 5 && memcmp(ip+1,cs->cs_ipopt,((ip->ihl)-5)*4) != 0)\n");
-		DEBUGP(DSLHC, "slhc_compress(): ip->ihl = %i\n", ip->ihl);
-		DEBUGP(DSLHC, "slhc_compress(): ip+1 =          %s\n",
-		       osmo_hexdump_nospc((uint8_t*)(ip+1),((ip->ihl)-5)*4));
-		DEBUGP(DSLHC, "slhc_compress(): Unexpected change: cs->cs_ipopt =  %s\n",
-		       osmo_hexdump_nospc((uint8_t*)(cs->cs_ipopt),((ip->ihl)-5)*4));
-	}
-	if(th->doff > 5 && memcmp(th+1,cs->cs_tcpopt,((th->doff)-5)*4) != 0) {
-		DEBUGP(DSLHC, "slhc_compress(): Unexpected change: (th->doff > 5 && memcmp(th+1,cs->cs_tcpopt,((th->doff)-5)*4) != 0)\n");
-		DEBUGP(DSLHC, "slhc_compress(): th->doff = %i\n", th->doff);
-		DEBUGP(DSLHC, "slhc_compress(): th+1 =          %s\n",
-		       osmo_hexdump_nospc((uint8_t*)(th+1),((th->doff)-5)*4));
-		DEBUGP(DSLHC, "slhc_compress(): cs->cs_tcpopt = %s\n",
-		       osmo_hexdump_nospc((uint8_t*)cs->cs_tcpopt,
-					  ((th->doff)-5)*4));
-	}
-
-
-	if(ip->version != cs->cs_ip.version || ip->ihl != cs->cs_ip.ihl
-	 || ip->tos != cs->cs_ip.tos
-	 || (ip->frag_off & htons(0x4000)) != (cs->cs_ip.frag_off & htons(0x4000))
-	 || ip->ttl != cs->cs_ip.ttl
-	 || th->doff != cs->cs_tcp.doff
-	 || (ip->ihl > 5 && memcmp(ip+1,cs->cs_ipopt,((ip->ihl)-5)*4) != 0)
-	 || (th->doff > 5 && memcmp(th+1,cs->cs_tcpopt,((th->doff)-5)*4) != 0)){
-		DEBUGP(DSLHC, "slhc_compress(): The header contains unexpected changes, can't compress...\n");
-		goto uncompressed;
-	}
-
-	/*
-	 * Figure out which of the changing fields changed.  The
-	 * receiver expects changes in the order: urgent, window,
-	 * ack, seq (the order minimizes the number of temporaries
-	 * needed in this section of code).
-	 */
-	if(th->urg){
-		deltaS = ntohs(th->urg_ptr);
-		DEBUGP(DSLHC, "slhc_compress(): flag: Urgent Pointer (U) = 1\n");
-		cp = encode(cp,deltaS);
-		changes |= NEW_U;
-	} else if(th->urg_ptr != oth->urg_ptr){
-		/* argh! URG not set but urp changed -- a sensible
-		 * implementation should never do this but RFC793
-		 * doesn't prohibit the change so we have to deal
-		 * with it. */
-		DEBUGP(DSLHC, "slhc_compress(): URG not set but urp changed, can't compress...\n");
-		goto uncompressed;
-	}
-	if((deltaS = ntohs(th->window) - ntohs(oth->window)) != 0){
-		DEBUGP(DSLHC, "slhc_compress(): flag: Delta Window (W) = 1\n");
-		cp = encode(cp,deltaS);
-		changes |= NEW_W;
-	}
-	if((deltaA = ntohl(th->ack_seq) - ntohl(oth->ack_seq)) != 0L){
-		if(deltaA > 0x0000ffff)	{
-			DEBUGP(DSLHC, "slhc_compress(): (deltaA = ntohl(th->ack_seq) - ntohl(oth->ack_seq)) != 0L, can't compress...\n");
-			goto uncompressed;
-		}
-		DEBUGP(DSLHC, "slhc_compress(): flag: Delta Ack (A) = 1\n");
-		cp = encode(cp,deltaA);
-		changes |= NEW_A;
-	}
-	if((deltaS = ntohl(th->seq) - ntohl(oth->seq)) != 0L){
-		if(deltaS > 0x0000ffff)	{
-			DEBUGP(DSLHC, "slhc_compress(): (deltaS = ntohl(th->seq) - ntohl(oth->seq)) != 0L, can't compress...\n");
-			goto uncompressed;
-		}
-		DEBUGP(DSLHC, "slhc_compress(): flag: Delta Sequence (S) = 1\n");
-		cp = encode(cp,deltaS);
-		changes |= NEW_S;
-	}
-
-	switch(changes){
-	case 0:	/* Nothing changed. If this packet contains data and the
-		 * last one didn't, this is probably a data packet following
-		 * an ack (normal on an interactive connection) and we send
-		 * it compressed.  Otherwise it's probably a retransmit,
-		 * retransmitted ack or window probe.  Send it uncompressed
-		 * in case the other side missed the compressed version.
-		 */
-		if(ip->tot_len != cs->cs_ip.tot_len &&
-		   ntohs(cs->cs_ip.tot_len) == hlen)
-			break;
-		DEBUGP(DSLHC, "slhc_compress(): Retransmitted packet detected, can't compress...\n");
-		goto uncompressed;
-	case SPECIAL_I:
-	case SPECIAL_D:
-		/* actual changes match one of our special case encodings --
-		 * send packet uncompressed.
-		 */
-		DEBUGP(DSLHC, "slhc_compress(): Special case detected, can't compress...\n");
-		goto uncompressed;
-	case NEW_S|NEW_A:
-		if(deltaS == deltaA &&
-		    deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
-			/* special case for echoed terminal traffic */
-			DEBUGP(DSLHC, "slhc_compress(): Special case for echoed terminal traffic detected...\n");
-			DEBUGP(DSLHC, "slhc_compress(): flag: Delta Sequence (S) = 1, Delta Window (W) = 1, Urgent Pointer (U) = 1\n");
-			changes = SPECIAL_I;
-			cp = new_seq;
-		}
-		break;
-	case NEW_S:
-		if(deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
-			/* special case for data xfer */
-			DEBUGP(DSLHC, "slhc_compress(): Special case for data xfer detected...\n");
-			DEBUGP(DSLHC, "slhc_compress(): flag: Delta Sequence (S) = 1, Delta Ack (A) = 1, Delta Window (W) = 1, Urgent Pointer (U) = 1\n");
-			changes = SPECIAL_D;
-			cp = new_seq;
-		}
-		break;
-	}
-	deltaS = ntohs(ip->id) - ntohs(cs->cs_ip.id);
-	if(deltaS != 1){
-		DEBUGP(DSLHC, "slhc_compress(): flag: Delta IP ID (I) = 1\n");
-		cp = encode(cp,deltaS);
-		changes |= NEW_I;
-	}
-	if(th->psh) {
-		DEBUGP(DSLHC, "slhc_compress(): flag: Push (P) = 1\n");
-		changes |= TCP_PUSH_BIT;
-	}
-	/* Grab the cksum before we overwrite it below.  Then update our
-	 * state with this packet's header.
-	 */
-	csum = th->check;
-	memcpy(&cs->cs_ip,ip,20);
-	memcpy(&cs->cs_tcp,th,20);
-	/* We want to use the original packet as our compressed packet.
-	 * (cp - new_seq) is the number of bytes we need for compressed
-	 * sequence numbers.  In addition we need one byte for the change
-	 * mask, one for the connection id and two for the tcp checksum.
-	 * So, (cp - new_seq) + 4 bytes of header are needed.
-	 */
-	deltaS = cp - new_seq;
-	if(compress_cid == 0 || comp->xmit_current != cs->cs_this){
-		cp = ocp;
-		*cpp = ocp;
-		DEBUGP(DSLHC, "slhc_compress(): flag: Connection number (C) = 1\n");
-		*cp++ = changes | NEW_C;
-		*cp++ = cs->cs_this;
-		comp->xmit_current = cs->cs_this;
-	} else {
-		cp = ocp;
-		*cpp = ocp;
-		*cp++ = changes;
-	}
-	*(__sum16 *)cp = csum;
-	cp += 2;
-/* deltaS is now the size of the change section of the compressed header */
-
-	DEBUGP(DSLHC, "slhc_compress(): Delta-list length (deltaS) = %li\n",deltaS);
-	DEBUGP(DSLHC, "slhc_compress(): Original header len (hlen) = %i\n",hlen);
-
-	memcpy(cp,new_seq,deltaS);	/* Write list of deltas */
-	memcpy(cp+deltaS,icp+hlen,isize-hlen);
-	comp->sls_o_compressed++;
-	ocp[0] |= SL_TYPE_COMPRESSED_TCP;
-	return isize - hlen + deltaS + (cp - ocp);
-
-	/* Update connection state cs & send uncompressed packet (i.e.,
-	 * a regular ip/tcp packet but with the 'conversation id' we hope
-	 * to use on future compressed packets in the protocol field).
-	 */
-uncompressed:
-	DEBUGP(DSLHC, "slhc_compress(): Packet will be sent uncompressed...\n");
-	memcpy(&cs->cs_ip,ip,20);
-	memcpy(&cs->cs_tcp,th,20);
-	if (ip->ihl > 5)
-	  memcpy(cs->cs_ipopt, ip+1, ((ip->ihl) - 5) * 4);
-	if (th->doff > 5)
-	  memcpy(cs->cs_tcpopt, th+1, ((th->doff) - 5) * 4);
-	comp->xmit_current = cs->cs_this;
-	comp->sls_o_uncompressed++;
-	memcpy(ocp, icp, isize);
-	*cpp = ocp;
-	ocp[9] = cs->cs_this;
-	ocp[0] |= SL_TYPE_UNCOMPRESSED_TCP;
-	return isize;
-}
-
-
-int
-slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
-{
-	register int changes;
-	long x;
-	register struct tcphdr *thp;
-	register struct iphdr *ip;
-	register struct cstate *cs;
-	int len, hdrlen;
-	unsigned char *cp = icp;
-
-	/* We've got a compressed packet; read the change byte */
-	comp->sls_i_compressed++;
-	if(isize < 3){
-		comp->sls_i_error++;
-		return 0;
-	}
-	changes = *cp++;
-	if(changes & NEW_C){
-		/* Make sure the state index is in range, then grab the state.
-		 * If we have a good state index, clear the 'discard' flag.
-		 */
-		x = *cp++;	/* Read conn index */
-		if(x < 0 || x > comp->rslot_limit)
-			goto bad;
-
-		comp->flags &=~ SLF_TOSS;
-		comp->recv_current = x;
-	} else {
-		/* this packet has an implicit state index.  If we've
-		 * had a line error since the last time we got an
-		 * explicit state index, we have to toss the packet. */
-		if(comp->flags & SLF_TOSS){
-			comp->sls_i_tossed++;
-			return 0;
-		}
-	}
-	cs = &comp->rstate[comp->recv_current];
-	thp = &cs->cs_tcp;
-	ip = &cs->cs_ip;
-
-	thp->check = *(__sum16 *)cp;
-	cp += 2;
-
-	thp->psh = (changes & TCP_PUSH_BIT) ? 1 : 0;
-/*
- * we can use the same number for the length of the saved header and
- * the current one, because the packet wouldn't have been sent
- * as compressed unless the options were the same as the previous one
- */
-
-	hdrlen = ip->ihl * 4 + thp->doff * 4;
-
-	switch(changes & SPECIALS_MASK){
-	case SPECIAL_I:		/* Echoed terminal traffic */
-		DEBUGP(DSLHC, "slhc_uncompress(): Echoed terminal traffic detected\n");
-
-		{
-		register short i;
-		i = ntohs(ip->tot_len) - hdrlen;
-		thp->ack_seq = htonl( ntohl(thp->ack_seq) + i);
-		thp->seq = htonl( ntohl(thp->seq) + i);
-		}
-		break;
-
-	case SPECIAL_D:			/* Unidirectional data */
-		DEBUGP(DSLHC, "slhc_uncompress(): Unidirectional data detected\n");
-		thp->seq = htonl( ntohl(thp->seq) +
-				  ntohs(ip->tot_len) - hdrlen);
-		break;
-
-	default:
-		DEBUGP(DSLHC, "slhc_uncompress(): default packet type detected\n");
-		if(changes & NEW_U){
-			thp->urg = 1;
-			if((x = decode(&cp)) == -1) {
-				goto bad;
-			}
-			thp->urg_ptr = htons(x);
-		} else
-			thp->urg = 0;
-		if(changes & NEW_W){
-			if((x = decode(&cp)) == -1) {
-				goto bad;
-			}
-			thp->window = htons( ntohs(thp->window) + x);
-		}
-		if(changes & NEW_A){
-			if((x = decode(&cp)) == -1) {
-				goto bad;
-			}
-			thp->ack_seq = htonl( ntohl(thp->ack_seq) + x);
-		}
-		if(changes & NEW_S){
-			if((x = decode(&cp)) == -1) {
-				goto bad;
-			}
-			thp->seq = htonl( ntohl(thp->seq) + x);
-		}
-		break;
-	}
-	if(changes & NEW_I){
-		if((x = decode(&cp)) == -1) {
-			goto bad;
-		}
-		ip->id = htons (ntohs (ip->id) + x);
-	} else
-		ip->id = htons (ntohs (ip->id) + 1);
-
-	/*
-	 * At this point, cp points to the first byte of data in the
-	 * packet.  Put the reconstructed TCP and IP headers back on the
-	 * packet.  Recalculate IP checksum (but not TCP checksum).
-	 */
-
-	len = isize - (cp - icp);
-	if (len < 0)
-		goto bad;
-	len += hdrlen;
-	ip->tot_len = htons(len);
-	ip->check = 0;
-
-	DEBUGP(DSLHC, "slhc_uncompress(): making space for the reconstructed header...\n");
-	memmove(icp + hdrlen, cp, len - hdrlen);
-
-	cp = icp;
-	memcpy(cp, ip, 20);
-	cp += 20;
-
-	if (ip->ihl > 5) {
-	  memcpy(cp, cs->cs_ipopt, (ip->ihl - 5) * 4);
-	  cp += (ip->ihl - 5) * 4;
-	}
-
-	put_unaligned(ip_fast_csum(icp, ip->ihl),
-		      &((struct iphdr *)icp)->check);
-
-	memcpy(cp, thp, 20);
-	cp += 20;
-
-	if (thp->doff > 5) {
-	  memcpy(cp, cs->cs_tcpopt, ((thp->doff) - 5) * 4);
-	  cp += ((thp->doff) - 5) * 4;
-	}
-
-	return len;
-bad:
-	DEBUGP(DSLHC, "slhc_uncompress(): bad packet detected!\n");
-	comp->sls_i_error++;
-	return slhc_toss( comp );
-}
-
-
-int
-slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
-{
-	register struct cstate *cs;
-	unsigned ihl;
-
-	unsigned char index;
-
-	if(isize < 20) {
-		/* The packet is shorter than a legal IP header */
-		comp->sls_i_runt++;
-		DEBUGP(DSLHC, "slhc_remember(): The packet is shorter than a legal IP header ==> slhc_toss()\n");
-		return slhc_toss( comp );
-	}
-	/* Peek at the IP header's IHL field to find its length */
-	ihl = icp[0] & 0xf;
-	if(ihl < 20 / 4){
-		/* The IP header length field is too small */
-		comp->sls_i_runt++;
-		DEBUGP(DSLHC, "slhc_remember(): The IP header length field is too small ==> slhc_toss()\n");
-		return slhc_toss( comp );
-	}
-	index = icp[9];
-	icp[9] = IPPROTO_TCP;
-
-	if (ip_fast_csum(icp, ihl)) {
-		/* Bad IP header checksum; discard */
-		comp->sls_i_badcheck++;
-		DEBUGP(DSLHC, "slhc_remember(): Bad IP header checksum; discard ==> slhc_toss()\n");
-		return slhc_toss( comp );
-	}
-	if(index > comp->rslot_limit) {
-		comp->sls_i_error++;
-		DEBUGP(DSLHC, "slhc_remember(): index > comp->rslot_limit ==> slhc_toss()\n");
-		return slhc_toss(comp);
-	}
-
-	/* Update local state */
-	cs = &comp->rstate[comp->recv_current = index];
-	comp->flags &=~ SLF_TOSS;
-	memcpy(&cs->cs_ip,icp,20);
-	memcpy(&cs->cs_tcp,icp + ihl*4,20);
-	if (ihl > 5)
-	  memcpy(cs->cs_ipopt, icp + sizeof(struct iphdr), (ihl - 5) * 4);
-	if (cs->cs_tcp.doff > 5)
-	  memcpy(cs->cs_tcpopt, icp + ihl*4 + sizeof(struct tcphdr), (cs->cs_tcp.doff - 5) * 4);
-	cs->cs_hsize = ihl*2 + cs->cs_tcp.doff*2;
-	/* Put headers back on packet
-	 * Neither header checksum is recalculated
-	 */
-	comp->sls_i_uncompressed++;
-	return isize;
-}
-
-int
-slhc_toss(struct slcompress *comp)
-{
-	DEBUGP(DSLHC, "slhc_toss(): Reset compression state...\n");
-	if ( comp == NULLSLCOMPR )
-		return 0;
-
-	comp->flags |= SLF_TOSS;
-	return 0;
-}
-
-void slhc_i_status(struct slcompress *comp)
-{
-	if (comp != NULLSLCOMPR) {
-		DEBUGP(DSLHC, "slhc_i_status(): %d Cmp, %d Uncmp, %d Bad, %d Tossed\n",
-			comp->sls_i_compressed,
-			comp->sls_i_uncompressed,
-			comp->sls_i_error,
-			comp->sls_i_tossed);
-	}
-}
-
-void slhc_o_status(struct slcompress *comp)
-{
-	if (comp != NULLSLCOMPR) {
-		DEBUGP(DSLHC, "slhc_o_status(): %d Cmp, %d Uncmp, %d AsIs, %d NotTCP %d Searches, %d Misses\n",
-			comp->sls_o_compressed,
-			comp->sls_o_uncompressed,
-			comp->sls_o_tcp,
-			comp->sls_o_nontcp,
-			comp->sls_o_searches,
-			comp->sls_o_misses);
-	}
-}
-
diff --git a/src/gprs/v42bis.c b/src/gprs/v42bis.c
deleted file mode 100644
index a04b0af..0000000
--- a/src/gprs/v42bis.c
+++ /dev/null
@@ -1,767 +0,0 @@
-/*
- * SpanDSP - a series of DSP components for telephony
- *
- * v42bis.c
- *
- * Written by Steve Underwood <steveu@coppice.org>
- *
- * Copyright (C) 2005, 2011 Steve Underwood
- *
- * All rights reserved.
- *
- * This program 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 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* THIS IS A WORK IN PROGRESS. IT IS NOT FINISHED. 
-   Currently it performs the core compression and decompression functions OK.
-   However, a number of the bells and whistles in V.42bis are incomplete. */
-
-/*! \file */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include <openbsc/v42bis.h>
-#include <openbsc/v42bis_private.h>
-#include <openbsc/debug.h>
-#include <osmocom/core/talloc.h>
-
-
-#define span_log(x,y,msg, ...) DEBUGP(DV42BIS,msg, ##__VA_ARGS__)
-#define span_log_init(x,y,z)
-#define span_log_set_protocol(x,y)
-
-
-#define FALSE 0
-#define TRUE 1
-
-/* Fixed parameters from the spec. */
-/* Character size (bits) */
-#define V42BIS_N3                           8
-/* Number of characters in the alphabet */
-#define V42BIS_N4                           256
-/* Index number of first dictionary entry used to store a string */
-#define V42BIS_N5                           (V42BIS_N4 + V42BIS_N6)
-/* Number of control codewords */
-#define V42BIS_N6                           3 
-/* V.42bis/9.2 */
-#define V42BIS_ESC_STEP                     51
-
-/* Compreeibility monitoring parameters for assessing automated switches between
-   transparent and compressed mode */
-#define COMPRESSIBILITY_MONITOR             (256*V42BIS_N3)
-#define COMPRESSIBILITY_MONITOR_HYSTERESIS  11
-
-/* Control code words in compressed mode */
-enum
-{
-    V42BIS_ETM = 0,         /* Enter transparent mode */
-    V42BIS_FLUSH = 1,       /* Flush data */
-    V42BIS_STEPUP = 2       /* Step up codeword size */
-};
-
-/* Command codes in transparent mode */
-enum
-{
-    V42BIS_ECM = 0,         /* Enter compression mode */
-    V42BIS_EID = 1,         /* Escape character in data */
-    V42BIS_RESET = 2        /* Force reinitialisation */
-};
-
-static __inline__ void push_octet(v42bis_comp_state_t *s, int octet)
-{
-    s->output_buf[s->output_octet_count++] = (uint8_t) octet;
-    if (s->output_octet_count >= s->max_output_len)
-    {
-        s->handler(s->user_data, s->output_buf, s->output_octet_count);
-        s->output_octet_count = 0;
-    }
-}
-/*- End of function --------------------------------------------------------*/
-
-static __inline__ void push_octets(v42bis_comp_state_t *s, const uint8_t buf[], int len)
-{
-    int i;
-    int chunk;
-
-    i = 0;
-    while ((s->output_octet_count + len - i) >= s->max_output_len)
-    {
-        chunk = s->max_output_len - s->output_octet_count;
-        memcpy(&s->output_buf[s->output_octet_count], &buf[i], chunk);
-        s->handler(s->user_data, s->output_buf, s->max_output_len);
-        s->output_octet_count = 0;
-        i += chunk;
-    }
-    chunk = len - i;
-    if (chunk > 0)
-    {
-        memcpy(&s->output_buf[s->output_octet_count], &buf[i], chunk);
-        s->output_octet_count += chunk;
-    }
-}
-/*- End of function --------------------------------------------------------*/
-
-static __inline__ void push_compressed_code(v42bis_comp_state_t *s, int code)
-{
-    s->bit_buffer |= code << s->bit_count;
-    s->bit_count += s->v42bis_parm_c2;
-    while (s->bit_count >= 8)
-    {
-        push_octet(s, s->bit_buffer & 0xFF);
-        s->bit_buffer >>= 8;
-        s->bit_count -= 8;
-    }
-}
-/*- End of function --------------------------------------------------------*/
-
-static __inline__ void push_octet_alignment(v42bis_comp_state_t *s)
-{
-    if ((s->bit_count & 7))
-    {
-        s->bit_count += (8 - (s->bit_count & 7));
-        while (s->bit_count >= 8)
-        {
-            push_octet(s, s->bit_buffer & 0xFF);
-            s->bit_buffer >>= 8;
-            s->bit_count -= 8;
-        }
-    }
-}
-/*- End of function --------------------------------------------------------*/
-
-static __inline__ void flush_octets(v42bis_comp_state_t *s)
-{
-    if (s->output_octet_count > 0)
-    {
-        s->handler(s->user_data, s->output_buf, s->output_octet_count);
-        s->output_octet_count = 0;
-    }
-}
-/*- End of function --------------------------------------------------------*/
-
-static void dictionary_init(v42bis_comp_state_t *s)
-{
-    int i;
-
-    memset(s->dict, 0, sizeof(s->dict));
-    for (i = 0;  i < V42BIS_N4;  i++)
-        s->dict[i + V42BIS_N6].node_octet = i;
-    s->v42bis_parm_c1 = V42BIS_N5;
-    s->v42bis_parm_c2 = V42BIS_N3 + 1;
-    s->v42bis_parm_c3 = V42BIS_N4 << 1;
-    s->last_matched = 0;
-    s->update_at = 0;
-    s->last_added = 0;
-    s->bit_buffer = 0;
-    s->bit_count = 0;
-    s->flushed_length = 0;
-    s->string_length = 0;
-    s->escape_code = 0;
-    s->transparent = TRUE;
-    s->escaped = FALSE;
-    s->compression_performance = COMPRESSIBILITY_MONITOR;
-}
-/*- End of function --------------------------------------------------------*/
-
-static uint16_t match_octet(v42bis_comp_state_t *s, uint16_t at, uint8_t octet)
-{
-    uint16_t e;
-
-    if (at == 0)
-        return octet + V42BIS_N6;
-    e = s->dict[at].child;
-    while (e)
-    {
-        if (s->dict[e].node_octet == octet)
-            return e;
-        e = s->dict[e].next;
-    }
-    return 0;
-}
-/*- End of function --------------------------------------------------------*/
-
-static uint16_t add_octet_to_dictionary(v42bis_comp_state_t *s, uint16_t at, uint8_t octet)
-{
-    uint16_t newx;
-    uint16_t next;
-    uint16_t e;
-
-    newx = s->v42bis_parm_c1;
-    s->dict[newx].node_octet = octet;
-    s->dict[newx].parent = at;
-    s->dict[newx].child = 0;
-    s->dict[newx].next = s->dict[at].child;
-    s->dict[at].child = newx;
-    next = newx;
-    /* 6.5 Recovering a dictionary entry to use next */
-    do
-    {
-        /* 6.5(a) and (b) */
-        if (++next == s->v42bis_parm_n2)
-            next = V42BIS_N5;
-    }
-    while (s->dict[next].child);
-    /* 6.5(c) We need to reuse a leaf node */
-    if (s->dict[next].parent)
-    {
-        /* 6.5(d) Detach the leaf node from its parent, and re-use it */
-        e = s->dict[next].parent;
-        if (s->dict[e].child == next)
-        {
-            s->dict[e].child = s->dict[next].next;
-        }
-        else
-        {
-            e = s->dict[e].child;
-            while (s->dict[e].next != next)
-                e = s->dict[e].next;
-            s->dict[e].next = s->dict[next].next;
-        }
-    }
-    s->v42bis_parm_c1 = next;
-    return newx;
-}
-/*- End of function --------------------------------------------------------*/
-
-static void send_string(v42bis_comp_state_t *s)
-{
-    push_octets(s, s->string, s->string_length);
-    s->string_length = 0;
-    s->flushed_length = 0;
-}
-/*- End of function --------------------------------------------------------*/
-
-static void expand_codeword_to_string(v42bis_comp_state_t *s, uint16_t code)
-{
-    int i;
-    uint16_t p;
-
-    /* Work out the length */
-    for (i = 0, p = code;  p;  i++)
-        p = s->dict[p].parent;
-    s->string_length += i;
-    /* Now expand the known length of string */
-    i = s->string_length - 1;
-    for (p = code;  p;  )
-    {
-        s->string[i--] = s->dict[p].node_octet;
-        p = s->dict[p].parent;
-    }
-}
-/*- End of function --------------------------------------------------------*/
-
-static void send_encoded_data(v42bis_comp_state_t *s, uint16_t code)
-{
-    int i;
-
-    /* Update compressibility metric */
-    /* Integrate at the compressed bit rate, and leak at the pre-compression bit rate */
-    s->compression_performance += (s->v42bis_parm_c2 - s->compression_performance*s->string_length*V42BIS_N3/COMPRESSIBILITY_MONITOR);
-    if (s->transparent)
-    {
-        for (i = 0;  i < s->string_length;  i++)
-        {
-            push_octet(s, s->string[i]);
-            if (s->string[i] == s->escape_code)
-            {
-                push_octet(s, V42BIS_EID);
-                s->escape_code += V42BIS_ESC_STEP;
-            }
-        }
-    }
-    else
-    {
-        /* Allow for any escape octets in the string */
-        for (i = 0;  i < s->string_length;  i++)
-        {
-            if (s->string[i] == s->escape_code)
-                s->escape_code += V42BIS_ESC_STEP;
-        }
-        /* 7.4 Encoding - we now have the longest matchable string, and will need to output the code for it. */
-        while (code >= s->v42bis_parm_c3)
-        {
-            /* We need to increase the codeword size */
-            /* 7.4(a) */
-            push_compressed_code(s, V42BIS_STEPUP);
-            /* 7.4(b) */
-            s->v42bis_parm_c2++;
-            /* 7.4(c) */
-            s->v42bis_parm_c3 <<= 1;
-            /* 7.4(d) this might need to be repeated, so we loop */
-        }
-        /* 7.5 Transfer - output the last state of the string */
-        push_compressed_code(s, code);
-    }
-    s->string_length = 0;
-    s->flushed_length = 0;
-}
-/*- End of function --------------------------------------------------------*/
-
-static void go_compressed(v42bis_state_t *ss)
-{
-    v42bis_comp_state_t *s;
-
-    s = &ss->compress;
-    if (!s->transparent)
-        return;
-    span_log(&ss->logging, SPAN_LOG_FLOW, "Changing to compressed mode\n");
-    /* Switch out of transparent now, between codes. We need to send the octet which did not
-       match, just before switching. */
-    if (s->last_matched)
-    {
-        s->update_at = s->last_matched;
-        send_encoded_data(s, s->last_matched);
-        s->last_matched = 0;
-    }
-    push_octet(s, s->escape_code);
-    push_octet(s, V42BIS_ECM);
-    s->bit_buffer = 0;
-    s->transparent = FALSE;
-}
-/*- End of function --------------------------------------------------------*/
-
-static void go_transparent(v42bis_state_t *ss)
-{
-    v42bis_comp_state_t *s;
-
-    s = &ss->compress;
-    if (s->transparent)
-        return;
-    span_log(&ss->logging, SPAN_LOG_FLOW, "Changing to transparent mode\n");
-    /* Switch into transparent now, between codes, and the unmatched octet should
-       go out in transparent mode, just below */
-    if (s->last_matched)
-    {
-        s->update_at = s->last_matched;
-        send_encoded_data(s, s->last_matched);
-        s->last_matched = 0;
-    }
-    s->last_added = 0;
-    push_compressed_code(s, V42BIS_ETM);
-    push_octet_alignment(s);
-    s->transparent = TRUE;
-}
-/*- End of function --------------------------------------------------------*/
-
-static void monitor_for_mode_change(v42bis_state_t *ss)
-{
-    v42bis_comp_state_t *s;
-
-    s = &ss->compress;
-    switch (s->compression_mode)
-    {
-    case V42BIS_COMPRESSION_MODE_DYNAMIC:
-        /* 7.8 Data compressibility test */
-        if (s->transparent)
-        {
-            if (s->compression_performance < COMPRESSIBILITY_MONITOR - COMPRESSIBILITY_MONITOR_HYSTERESIS)
-            {
-                /* 7.8.1 Transition to compressed mode */
-                go_compressed(ss);
-            }
-        }
-        else
-        {
-            if (s->compression_performance > COMPRESSIBILITY_MONITOR)
-            {
-                /* 7.8.2 Transition to transparent mode */
-                go_transparent(ss);
-            }
-        }
-        /* 7.8.3 Reset function - TODO */
-        break;
-    case V42BIS_COMPRESSION_MODE_ALWAYS:
-        if (s->transparent)
-            go_compressed(ss);
-        break;
-    case V42BIS_COMPRESSION_MODE_NEVER:
-        if (!s->transparent)
-            go_transparent(ss);
-        break;
-    }
-}
-/*- End of function --------------------------------------------------------*/
-
-static int v42bis_comp_init(v42bis_comp_state_t *s,
-                            int p1,
-                            int p2,
-                            put_msg_func_t handler,
-                            void *user_data,
-                            int max_output_len)
-{
-    memset(s, 0, sizeof(*s));
-    s->v42bis_parm_n2 = p1;
-    s->v42bis_parm_n7 = p2;
-    s->handler = handler;
-    s->user_data = user_data;
-    s->max_output_len = (max_output_len < V42BIS_MAX_OUTPUT_LENGTH)  ?  max_output_len  :  V42BIS_MAX_OUTPUT_LENGTH;
-    s->output_octet_count = 0;
-    dictionary_init(s);
-    return 0;
-}
-/*- End of function --------------------------------------------------------*/
-
-static int comp_exit(v42bis_comp_state_t *s)
-{
-    s->v42bis_parm_n2 = 0;
-    return 0;
-}
-/*- End of function --------------------------------------------------------*/
-
-SPAN_DECLARE(int) v42bis_compress(v42bis_state_t *ss, const uint8_t buf[], int len)
-{
-    v42bis_comp_state_t *s;
-    int i;
-    uint16_t code;
-
-    s = &ss->compress;
-    if (!s->v42bis_parm_p0)
-    {
-        /* Compression is off - just push the incoming data out */
-        push_octets(s, buf, len);
-        return 0;
-    }
-    for (i = 0;  i < len;  )
-    {
-        /* 6.4 Add the string to the dictionary */
-        if (s->update_at)
-        {
-            if (match_octet(s, s->update_at, buf[i]) == 0)
-                s->last_added = add_octet_to_dictionary(s, s->update_at, buf[i]);
-            s->update_at = 0;
-        }
-        /* Match string */
-        while (i < len)
-        {
-            code = match_octet(s, s->last_matched, buf[i]);
-            if (code == 0)
-            {
-                s->update_at = s->last_matched;
-                send_encoded_data(s, s->last_matched);
-                s->last_matched = 0;
-                break;
-            }
-            if (code == s->last_added)
-            {
-                s->last_added = 0;
-                send_encoded_data(s, s->last_matched);
-                s->last_matched = 0;
-                break;
-            }
-            s->last_matched = code;
-            /* 6.3(b) If the string matches a dictionary entry, and the entry is not that entry
-                      created by the last invocation of the string matching procedure, then the
-                      next character shall be read and appended to the string and this step
-                      repeated. */
-            s->string[s->string_length++] = buf[i++];
-            /* 6.4(a) The string must not exceed N7 in length */
-            if (s->string_length + s->flushed_length == s->v42bis_parm_n7)
-            {
-                send_encoded_data(s, s->last_matched);
-                s->last_matched = 0;
-                break;
-            }
-        }
-        monitor_for_mode_change(ss);
-    }
-    return 0;
-}
-/*- End of function --------------------------------------------------------*/
-
-SPAN_DECLARE(int) v42bis_compress_flush(v42bis_state_t *ss)
-{
-    v42bis_comp_state_t *s;
-    int len;
-    
-    s = &ss->compress;
-    if (s->update_at)
-        return 0;
-    if (s->last_matched)
-    {
-        len = s->string_length;
-        send_encoded_data(s, s->last_matched);
-        s->flushed_length += len;
-    }
-    if (!s->transparent)
-    {
-        s->update_at = s->last_matched;
-        s->last_matched = 0;
-        s->flushed_length = 0;
-        push_compressed_code(s, V42BIS_FLUSH);
-        push_octet_alignment(s);
-    }
-    flush_octets(s);
-    return 0;
-}
-/*- End of function --------------------------------------------------------*/
-
-SPAN_DECLARE(int) v42bis_decompress(v42bis_state_t *ss, const uint8_t buf[], int len)
-{
-    v42bis_comp_state_t *s;
-    int i;
-    int j;
-    int yyy;
-    uint16_t code;
-    uint16_t p;
-    uint8_t ch;
-    uint8_t in;
-
-    s = &ss->decompress;
-    if (!s->v42bis_parm_p0)
-    {
-        /* Compression is off - just push the incoming data out */
-        push_octets(s, buf, len);
-        return 0;
-    }
-    for (i = 0;  i < len;  )
-    {
-        if (s->transparent)
-        {
-            in = buf[i];
-            if (s->escaped)
-            {
-                /* Command */
-                s->escaped = FALSE;
-                switch (in)
-                {
-                case V42BIS_ECM:
-                    /* Enter compressed mode */
-                    span_log(&ss->logging, SPAN_LOG_FLOW, "Hit V42BIS_ECM\n");
-                    send_string(s);
-                    s->transparent = FALSE;
-                    s->update_at = s->last_matched;
-                    s->last_matched = 0;
-                    i++;
-                    continue;
-                case V42BIS_EID:
-                    /* Escape symbol */
-                    span_log(&ss->logging, SPAN_LOG_FLOW, "Hit V42BIS_EID\n");
-                    in = s->escape_code;
-                    s->escape_code += V42BIS_ESC_STEP;
-                    break;
-                case V42BIS_RESET:
-                    /* Reset dictionary */
-                    span_log(&ss->logging, SPAN_LOG_FLOW, "Hit V42BIS_RESET\n");
-                    /* TODO: */
-                    send_string(s);
-                    dictionary_init(s);
-                    i++;
-                    continue;
-                default:
-                    span_log(&ss->logging, SPAN_LOG_FLOW, "Hit V42BIS_???? - %" PRIu32 "\n", in);
-                    return -1;
-                }
-            }
-            else if (in == s->escape_code)
-            {
-                s->escaped = TRUE;
-                i++;
-                continue;
-            }
-
-            yyy = TRUE;
-            for (j = 0;  j < 2  &&  yyy;  j++)
-            {
-                if (s->update_at)
-                {
-                    if (match_octet(s, s->update_at, in) == 0)
-                        s->last_added = add_octet_to_dictionary(s, s->update_at, in);
-                    s->update_at = 0;
-                }
-
-                code = match_octet(s, s->last_matched, in);
-                if (code == 0)
-                {
-                    s->update_at = s->last_matched;
-                    send_string(s);
-                    s->last_matched = 0;
-                }
-                else if (code == s->last_added)
-                {
-                    s->last_added = 0;
-                    send_string(s);
-                    s->last_matched = 0;
-                }
-                else
-                {
-                    s->last_matched = code;
-                    s->string[s->string_length++] = in;
-                    if (s->string_length + s->flushed_length == s->v42bis_parm_n7)
-                    {
-                        send_string(s);
-                        s->last_matched = 0;
-                    }
-                    i++;
-                    yyy = FALSE;
-                }
-            }
-        }
-        else
-        {
-            /* Get code from input */
-            while (s->bit_count < s->v42bis_parm_c2  &&  i < len)
-            {
-                s->bit_buffer |= buf[i++] << s->bit_count;
-                s->bit_count += 8;
-            }
-            if (s->bit_count < s->v42bis_parm_c2)
-                continue;
-            code = s->bit_buffer & ((1 << s->v42bis_parm_c2) - 1);
-            s->bit_buffer >>= s->v42bis_parm_c2;
-            s->bit_count -= s->v42bis_parm_c2;
-
-            if (code < V42BIS_N6)
-            {
-                /* We have a control code. */
-                switch (code)
-                {
-                case V42BIS_ETM:
-                    /* Enter transparent mode */
-                    span_log(&ss->logging, SPAN_LOG_FLOW, "Hit V42BIS_ETM\n");
-                    s->bit_count = 0;
-                    s->transparent = TRUE;
-                    s->last_matched = 0;
-                    s->last_added = 0;
-                    break;
-                case V42BIS_FLUSH:
-                    /* Flush signal */
-                    span_log(&ss->logging, SPAN_LOG_FLOW, "Hit V42BIS_FLUSH\n");
-                    s->bit_count = 0;
-                    break;
-                case V42BIS_STEPUP:
-                    /* Increase code word size */
-                    span_log(&ss->logging, SPAN_LOG_FLOW, "Hit V42BIS_STEPUP\n");
-                    s->v42bis_parm_c2++;
-                    s->v42bis_parm_c3 <<= 1;
-                    if (s->v42bis_parm_c2 > (s->v42bis_parm_n2 >> 3))
-                        return -1;
-                    break;
-                }
-                continue;
-            }
-            /* Regular codeword */
-            if (code == s->v42bis_parm_c1)
-                return -1;
-            expand_codeword_to_string(s, code);
-            if (s->update_at)
-            {
-                ch = s->string[0];
-                if ((p = match_octet(s, s->update_at, ch)) == 0)
-                {
-                    s->last_added = add_octet_to_dictionary(s, s->update_at, ch);
-                    if (code == s->v42bis_parm_c1)
-                        return -1;
-                }
-                else if (p == s->last_added)
-                {
-                    s->last_added = 0;
-                }
-            }
-            s->update_at = ((s->string_length + s->flushed_length) == s->v42bis_parm_n7)  ?  0  :  code;
-            /* Allow for any escapes which may be in this string */
-            for (j = 0;  j < s->string_length;  j++)
-            {
-                if (s->string[j] == s->escape_code)
-                    s->escape_code += V42BIS_ESC_STEP;
-            }
-            send_string(s);
-        }
-    }
-    return 0;
-}
-/*- End of function --------------------------------------------------------*/
-
-SPAN_DECLARE(int) v42bis_decompress_flush(v42bis_state_t *ss)
-{
-    v42bis_comp_state_t *s;
-    int len;
-    
-    s = &ss->decompress;
-    len = s->string_length;
-    send_string(s);
-    s->flushed_length += len;
-    flush_octets(s);
-    return 0;
-}
-/*- End of function --------------------------------------------------------*/
-
-SPAN_DECLARE(void) v42bis_compression_control(v42bis_state_t *s, int mode)
-{
-    s->compress.compression_mode = mode;
-}
-/*- End of function --------------------------------------------------------*/
-
-SPAN_DECLARE(v42bis_state_t *) v42bis_init(const void *ctx,
-                                           v42bis_state_t *s,
-                                           int negotiated_p0,
-                                           int negotiated_p1,
-                                           int negotiated_p2,
-                                           put_msg_func_t encode_handler,
-                                           void *encode_user_data,
-                                           int max_encode_len,
-                                           put_msg_func_t decode_handler,
-                                           void *decode_user_data,
-                                           int max_decode_len)
-{
-    int ret;
-
-    if (negotiated_p1 < V42BIS_MIN_DICTIONARY_SIZE  ||  negotiated_p1 > 65535)
-        return NULL;
-    if (negotiated_p2 < V42BIS_MIN_STRING_SIZE  ||  negotiated_p2 > V42BIS_MAX_STRING_SIZE)
-        return NULL;
-    if (s == NULL)
-    {
-        if ((s = (v42bis_state_t *) talloc_zero_size(ctx,sizeof(*s))) == NULL)
-            return NULL;
-    }
-    memset(s, 0, sizeof(*s));
-    span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
-    span_log_set_protocol(&s->logging, "V.42bis");
-
-    if ((ret = v42bis_comp_init(&s->compress, negotiated_p1, negotiated_p2, encode_handler, encode_user_data, max_encode_len)))
-        return NULL;
-    if ((ret = v42bis_comp_init(&s->decompress, negotiated_p1, negotiated_p2, decode_handler, decode_user_data, max_decode_len)))
-    {
-        comp_exit(&s->compress);
-        return NULL;
-    }
-    s->compress.v42bis_parm_p0 = negotiated_p0 & 2;
-    s->decompress.v42bis_parm_p0 = negotiated_p0 & 1;
-
-    return s;
-}
-/*- End of function --------------------------------------------------------*/
-
-SPAN_DECLARE(int) v42bis_release(v42bis_state_t *s)
-{
-    return 0;
-}
-/*- End of function --------------------------------------------------------*/
-
-SPAN_DECLARE(int) v42bis_free(v42bis_state_t *s)
-{
-    comp_exit(&s->compress);
-    comp_exit(&s->decompress);
-    talloc_free(s);
-    return 0;
-}
-/*- End of function --------------------------------------------------------*/
-/*- End of file ------------------------------------------------------------*/
diff --git a/src/ipaccess/Makefile.am b/src/ipaccess/Makefile.am
deleted file mode 100644
index 4dfe247..0000000
--- a/src/ipaccess/Makefile.am
+++ /dev/null
@@ -1,66 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	-I$(top_builddir) \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(COVERAGE_LDFLAGS) \
-	$(NULL)
-
-OSMO_LIBS = \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	$(NULL)
-
-bin_PROGRAMS = \
-	abisip-find \
-	ipaccess-config \
-	ipaccess-proxy \
-	$(NULL)
-
-abisip_find_LDADD = \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(OSMO_LIBS) \
-	$(NULL)
-
-abisip_find_SOURCES = \
-	abisip-find.c \
-	$(NULL)
-
-ipaccess_config_SOURCES = \
-	ipaccess-config.c \
-	ipaccess-firmware.c \
-	network_listen.c \
-	$(NULL)
-
-# FIXME: resolve the bogus dependencies patched around here:
-ipaccess_config_LDADD = \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(OSMO_LIBS) \
-	$(NULL)
-
-ipaccess_proxy_SOURCES = \
-	ipaccess-proxy.c \
-	$(NULL)
-
-ipaccess_proxy_LDADD = \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(OSMO_LIBS) \
-	$(NULL)
diff --git a/src/ipaccess/abisip-find.c b/src/ipaccess/abisip-find.c
deleted file mode 100644
index 21d9f22..0000000
--- a/src/ipaccess/abisip-find.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/* ip.access nanoBTS configuration tool */
-
-/* (C) 2009-2010 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/>.
- *
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-
-#include <osmocom/core/select.h>
-#include <osmocom/core/timer.h>
-#include <osmocom/gsm/protocol/ipaccess.h>
-#include <osmocom/gsm/ipa.h>
-#include <openbsc/gsm_data.h>
-
-static int udp_sock(const char *ifname)
-{
-	int fd, rc, bc = 1;
-	struct sockaddr_in sa;
-
-	fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
-	if (fd < 0)
-		return fd;
-
-	if (ifname) {
-#ifdef __FreeBSD__
-		rc = setsockopt(fd, SOL_SOCKET, IP_RECVIF, ifname,
-				strlen(ifname));
-#else
-		rc = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
-				strlen(ifname));
-#endif
-		if (rc < 0)
-			goto err;
-	}
-
-	memset(&sa, 0, sizeof(sa));
-	sa.sin_family = AF_INET;
-	sa.sin_port = htons(3006);
-	sa.sin_addr.s_addr = INADDR_ANY;
-
-	rc = bind(fd, (struct sockaddr *)&sa, sizeof(sa));
-	if (rc < 0)
-		goto err;
-
-	rc = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &bc, sizeof(bc));
-	if (rc < 0)
-		goto err;
-
-#if 0
-	/* we cannot bind, since the response packets don't come from
-	 * the broadcast address */
-	sa.sin_family = AF_INET;
-	sa.sin_port = htons(3006);
-	inet_aton("255.255.255.255", &sa.sin_addr);
-
-	rc = connect(fd, (struct sockaddr *)&sa, sizeof(sa));
-	if (rc < 0)
-		goto err;
-#endif
-	return fd;
-
-err:
-	close(fd);
-	return rc;
-}
-
-const unsigned char find_pkt[] = { 0x00, 0x0b+8, IPAC_PROTO_IPACCESS, 0x00,
-				IPAC_MSGT_ID_GET,
-					0x01, IPAC_IDTAG_MACADDR,
-					0x01, IPAC_IDTAG_IPADDR,
-					0x01, IPAC_IDTAG_UNIT,
-					0x01, IPAC_IDTAG_LOCATION1,
-					0x01, IPAC_IDTAG_LOCATION2,
-					0x01, IPAC_IDTAG_EQUIPVERS,
-					0x01, IPAC_IDTAG_SWVERSION,
-					0x01, IPAC_IDTAG_UNITNAME,
-					0x01, IPAC_IDTAG_SERNR,
-				};
-
-
-static int bcast_find(int fd)
-{
-	struct sockaddr_in sa;
-
-	sa.sin_family = AF_INET;
-	sa.sin_port = htons(3006);
-	inet_aton("255.255.255.255", &sa.sin_addr);
-
-	return sendto(fd, find_pkt, sizeof(find_pkt), 0, (struct sockaddr *) &sa, sizeof(sa));
-}
-
-static int parse_response(unsigned char *buf, int len)
-{
-	uint8_t t_len;
-	uint8_t t_tag;
-	uint8_t *cur = buf;
-
-	while (cur < buf + len) {
-		t_len = *cur++;
-		t_tag = *cur++;
-		
-		printf("%s='%s'  ", ipa_ccm_idtag_name(t_tag), cur);
-
-		cur += t_len;
-	}
-	printf("\n");
-	return 0;
-}
-
-static int read_response(int fd)
-{
-	unsigned char buf[255];
-	struct sockaddr_in sa;
-	int len;
-	socklen_t sa_len = sizeof(sa);
-
-	len = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sa, &sa_len);
-	if (len < 0)
-		return len;
-
-	/* 2 bytes length, 1 byte protocol */
-	if (buf[2] != IPAC_PROTO_IPACCESS)
-		return 0;
-
-	if (buf[4] != IPAC_MSGT_ID_RESP)
-		return 0;
-
-	return parse_response(buf+6, len-6);
-}
-
-static int bfd_cb(struct osmo_fd *bfd, unsigned int flags)
-{
-	if (flags & BSC_FD_READ)
-		return read_response(bfd->fd);
-	if (flags & BSC_FD_WRITE) {
-		bfd->when &= ~BSC_FD_WRITE;
-		return bcast_find(bfd->fd);
-	}
-	return 0;
-}
-
-static struct osmo_timer_list timer;
-
-static void timer_cb(void *_data)
-{
-	struct osmo_fd *bfd = _data;
-
-	bfd->when |= BSC_FD_WRITE;
-
-	osmo_timer_schedule(&timer, 5, 0);
-}
-
-int main(int argc, char **argv)
-{
-	struct osmo_fd bfd;
-	char *ifname = NULL;
-	int rc;
-
-	printf("abisip-find (C) 2009 by Harald Welte\n");
-	printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
-
-	if (argc < 2) {
-		fprintf(stdout, "you might need to specify the outgoing\n"
-			" network interface, e.g. ``%s eth0''\n", argv[0]);
-	} else {
-		ifname = argv[1];
-	}
-
-	bfd.cb = bfd_cb;
-	bfd.when = BSC_FD_READ | BSC_FD_WRITE;
-	bfd.fd = udp_sock(ifname);
-	if (bfd.fd < 0) {
-		perror("Cannot create local socket for broadcast udp");
-		exit(1);
-	}
-
-	rc = osmo_fd_register(&bfd);
-	if (rc < 0) {
-		fprintf(stderr, "Cannot register FD\n");
-		exit(1);
-	}
-
-	osmo_timer_setup(&timer, timer_cb, &bfd);
-	osmo_timer_schedule(&timer, 5, 0);
-
-	printf("Trying to find ip.access BTS by broadcast UDP...\n");
-
-	while (1) {
-		rc = osmo_select_main(0);
-		if (rc < 0)
-			exit(3);
-	}
-
-	exit(0);
-}
-
diff --git a/src/ipaccess/ipaccess-config.c b/src/ipaccess/ipaccess-config.c
deleted file mode 100644
index 6822c06..0000000
--- a/src/ipaccess/ipaccess-config.c
+++ /dev/null
@@ -1,1019 +0,0 @@
-/* ip.access nanoBTS configuration tool */
-
-/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009-2011 by Holger Hans Peter Freyther
- * (C) 2009-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/>.
- *
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <errno.h>
-#include <sys/fcntl.h>
-#include <sys/stat.h>
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/timer.h>
-#include <openbsc/ipaccess.h>
-#include <openbsc/common_bsc.h>
-#include <osmocom/abis/e1_input.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/signal.h>
-#include <openbsc/debug.h>
-#include <openbsc/network_listen.h>
-#include <osmocom/abis/ipaccess.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/signal.h>
-#include <openbsc/debug.h>
-#include <openbsc/network_listen.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/abis/abis.h>
-#include <osmocom/gsm/protocol/gsm_12_21.h>
-
-struct gsm_network *bsc_gsmnet;
-
-static int net_listen_testnr;
-static int restart;
-static char *prim_oml_ip;
-static char *bts_ip_addr, *bts_ip_mask, *bts_ip_gw;
-static char *unit_id;
-static uint16_t nv_flags;
-static uint16_t nv_mask;
-static char *software = NULL;
-static int sw_load_state = 0;
-static int oml_state = 0;
-static int dump_files = 0;
-static char *firmware_analysis = NULL;
-static int found_trx = 0;
-static int loop_tests = 0;
-
-static void *tall_ctx_config = NULL;
-static struct abis_nm_sw_desc *sw_load1 = NULL;
-static struct abis_nm_sw_desc *sw_load2 = NULL;
-
-/*
-static uint8_t prim_oml_attr[] = { 0x95, 0x00, 7, 0x88, 192, 168, 100, 11, 0x00, 0x00 };
-static uint8_t unit_id_attr[] = { 0x91, 0x00, 9, '2', '3', '4', '2', '/' , '0', '/', '0', 0x00 };
-*/
-
-extern int ipaccess_fd_cb(struct osmo_fd *bfd, unsigned int what);
-extern struct e1inp_line_ops ipaccess_e1inp_line_ops;
-
-/* Actively connect to a BTS.  Currently used by ipaccess-config.c */
-static int ipaccess_connect(struct e1inp_line *line, struct sockaddr_in *sa)
-{
-	struct e1inp_ts *e1i_ts = &line->ts[0];
-	struct osmo_fd *bfd = &e1i_ts->driver.ipaccess.fd;
-	int ret, on = 1;
-
-	bfd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-	bfd->cb = ipaccess_fd_cb;
-	bfd->when = BSC_FD_READ | BSC_FD_WRITE;
-	bfd->data = line;
-	bfd->priv_nr = E1INP_SIGN_OML;
-
-	if (bfd->fd < 0) {
-		LOGP(DLINP, LOGL_ERROR, "could not create TCP socket.\n");
-		return -EIO;
-	}
-
-	ret = setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-	if (ret < 0) {
-		LOGP(DLINP, LOGL_ERROR, "could not set socket option\n");
-		close(bfd->fd);
-		return -EIO;
-	}
-
-	ret = connect(bfd->fd, (struct sockaddr *) sa, sizeof(*sa));
-	if (ret < 0) {
-		LOGP(DLINP, LOGL_ERROR, "could not connect socket\n");
-		close(bfd->fd);
-		return ret;
-	}
-
-	ret = osmo_fd_register(bfd);
-	if (ret < 0) {
-		close(bfd->fd);
-		return ret;
-	}
-	return ret;
-	//return e1inp_line_register(line);
-}
-
-/* configure pseudo E1 line in ip.access style and connect to BTS */
-static int ia_config_connect(struct gsm_bts *bts, struct sockaddr_in *sin)
-{
-	struct e1inp_line *line;
-	struct e1inp_ts *sign_ts, *rsl_ts;
-	struct e1inp_sign_link *oml_link, *rsl_link;
-
-	line = talloc_zero(tall_bsc_ctx, struct e1inp_line);
-	if (!line)
-		return -ENOMEM;
-
-	line->driver = e1inp_driver_find("ipa");
-	if (!line->driver) {
-		fprintf(stderr, "cannot `ipa' driver, giving up.\n");
-		return -EINVAL;
-	}
-	line->ops = &ipaccess_e1inp_line_ops;
-
-	/* create E1 timeslots for signalling and TRAU frames */
-	e1inp_ts_config_sign(&line->ts[1-1], line);
-	e1inp_ts_config_sign(&line->ts[2-1], line);
-
-	/* create signalling links for TS1 */
-	sign_ts = &line->ts[1-1];
-	rsl_ts = &line->ts[2-1];
-	oml_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OML,
-					  bts->c0, 0xff, 0);
-	rsl_link = e1inp_sign_link_create(rsl_ts, E1INP_SIGN_RSL,
-					  bts->c0, 0, 0);
-
-	/* create back-links from bts/trx */
-	bts->oml_link = oml_link;
-	bts->c0->rsl_link = rsl_link;
-
-	/* default port at BTS for incoming connections is 3006 */
-	if (sin->sin_port == 0)
-		sin->sin_port = htons(3006);
-
-	return ipaccess_connect(line, sin);
-}
-
-/*
- * Callback function for NACK on the OML NM
- *
- * Currently we send the config requests but don't check the
- * result. The nanoBTS will send us a NACK when we did something the
- * BTS didn't like.
- */
-static int ipacc_msg_nack(uint8_t mt)
-{
-	fprintf(stderr, "Failure to set attribute. This seems fatal\n");
-	exit(-1);
-	return 0;
-}
-
-static void check_restart_or_exit(struct gsm_bts_trx *trx)
-{
-	if (restart) {
-		abis_nm_ipaccess_restart(trx);
-	} else {
-		exit(0);
-	}
-}
-
-static int ipacc_msg_ack(uint8_t mt, struct gsm_bts_trx *trx)
-{
-	if (sw_load_state == 1) {
-		fprintf(stderr, "The new software is activaed.\n");
-		check_restart_or_exit(trx);
-	} else if (oml_state == 1) {
-		fprintf(stderr, "Set the NV Attributes.\n");
-		check_restart_or_exit(trx);
-	}
-
-	return 0;
-}
-
-static const uint8_t phys_conf_min[] = { 0x02 };
-
-static uint16_t build_physconf(uint8_t *physconf_buf, const struct rxlev_stats *st)
-{
-	uint16_t *whitelist = (uint16_t *) (physconf_buf + 4);
-	int num_arfcn;
-	unsigned int arfcnlist_size;
-
-	/* Create whitelist from rxlevels */
-	physconf_buf[0] = phys_conf_min[0];
-	physconf_buf[1] = NM_IPAC_EIE_ARFCN_WHITE;
-	num_arfcn = ipac_rxlevstat2whitelist(whitelist, st, 0, 100);
-	arfcnlist_size = num_arfcn * 2;
-	*((uint16_t *) (physconf_buf+2)) = htons(arfcnlist_size);
-	DEBUGP(DNM, "physconf_buf (%s)\n", osmo_hexdump(physconf_buf, arfcnlist_size+4));
-	return arfcnlist_size+4;
-}
-
-static int nwl_sig_cb(unsigned int subsys, unsigned int signal,
-		      void *handler_data, void *signal_data)
-{
-	struct gsm_bts_trx *trx;
-	uint8_t physconf_buf[2*NUM_ARFCNS+16];
-	uint16_t physconf_len;
-
-	switch (signal) {
-	case S_IPAC_NWL_COMPLETE:
-		trx = signal_data;
-		DEBUGP(DNM, "received S_IPAC_NWL_COMPLETE signal\n");
-		switch (trx->ipaccess.test_nr) {
-		case NM_IPACC_TESTNO_CHAN_USAGE:
-			/* Dump RxLev results */
-			//rxlev_stat_dump(&trx->ipaccess.rxlev_stat);
-			/* Create whitelist from results */
-			physconf_len = build_physconf(physconf_buf,
-						      &trx->ipaccess.rxlev_stat);
-			/* Start next test abbout BCCH channel usage */
-			ipac_nwl_test_start(trx, NM_IPACC_TESTNO_BCCH_CHAN_USAGE,
-					    physconf_buf, physconf_len);
-			break;
-		case NM_IPACC_TESTNO_BCCH_CHAN_USAGE:
-			/* Dump BCCH RxLev results */
-			//rxlev_stat_dump(&trx->ipaccess.rxlev_stat);
-			/* Create whitelist from results */
-			physconf_len = build_physconf(physconf_buf,
-						      &trx->ipaccess.rxlev_stat);
-			/* Start next test about BCCH info */
-			ipac_nwl_test_start(trx, NM_IPACC_TESTNO_BCCH_INFO,
-					    physconf_buf, physconf_len);
-			break;
-		case NM_IPACC_TESTNO_BCCH_INFO:
-			/* re-start full process with CHAN_USAGE */
-			if (loop_tests) {
-				DEBUGP(DNM, "starting next test cycle\n");
-				ipac_nwl_test_start(trx, net_listen_testnr, phys_conf_min,
-						    sizeof(phys_conf_min));
-			} else {
-				exit(0);
-			}
-			break;
-		}
-		break;
-	}
-	return 0;
-}
-
-static int nm_state_event(int evt, uint8_t obj_class, void *obj,
-			  struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
-			  struct abis_om_obj_inst *obj_inst);
-
-static int nm_sig_cb(unsigned int subsys, unsigned int signal,
-		     void *handler_data, void *signal_data)
-{
-	struct ipacc_ack_signal_data *ipacc_data;
-	struct nm_statechg_signal_data *nsd;
-
-	switch (signal) {
-	case S_NM_IPACC_NACK:
-		ipacc_data = signal_data;
-		return ipacc_msg_nack(ipacc_data->msg_type);
-	case S_NM_IPACC_ACK:
-		ipacc_data = signal_data;
-		return ipacc_msg_ack(ipacc_data->msg_type, ipacc_data->trx);
-	case S_NM_IPACC_RESTART_ACK:
-		printf("The BTS has acked the restart. Exiting.\n");
-		exit(0);
-		break;
-	case S_NM_IPACC_RESTART_NACK:
-		printf("The BTS has nacked the restart. Exiting.\n");
-		exit(0);
-		break;
-	case S_NM_STATECHG_OPER:
-	case S_NM_STATECHG_ADM:
-		nsd = signal_data;
-		nm_state_event(signal, nsd->obj_class, nsd->obj, nsd->old_state,
-				nsd->new_state, nsd->obj_inst);
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-/* callback function passed to the ABIS OML code */
-static int percent;
-static int percent_old;
-static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *_msg,
-		       void *data, void *param)
-{
-	struct msgb *msg;
-	struct gsm_bts_trx *trx;
-
-	if (hook != GSM_HOOK_NM_SWLOAD)
-		return 0;
-
-	trx = (struct gsm_bts_trx *) data;
-
-	switch (event) {
-	case NM_MT_LOAD_INIT_ACK:
-		fprintf(stdout, "Software Load Initiate ACK\n");
-		break;
-	case NM_MT_LOAD_INIT_NACK:
-		fprintf(stderr, "ERROR: Software Load Initiate NACK\n");
-		exit(5);
-		break;
-	case NM_MT_LOAD_END_ACK:
-		fprintf(stderr, "LOAD END ACK...");
-		/* now make it the default */
-		sw_load_state = 1;
-
-		msg = msgb_alloc(1024, "sw: nvattr");
-		msg->l2h = msgb_put(msg, 3);
-		msg->l3h = &msg->l2h[3];
-
-		/* activate software */
-		if (sw_load1)
-			abis_nm_put_sw_desc(msg, sw_load1, true);
-
-		if (sw_load2)
-			abis_nm_put_sw_desc(msg, sw_load2, true);
-
-		/* fill in the data */
-		msg->l2h[0] = NM_ATT_IPACC_CUR_SW_CFG;
-		msg->l2h[1] = msgb_l3len(msg) >> 8;
-		msg->l2h[2] = msgb_l3len(msg) & 0xff;
-		printf("Foo l2h: %p l3h: %p... length l2: %u  l3: %u\n", msg->l2h, msg->l3h, msgb_l2len(msg), msgb_l3len(msg));
-		abis_nm_ipaccess_set_nvattr(trx, msg->l2h, msgb_l2len(msg));
-		msgb_free(msg);
-		break;
-	case NM_MT_LOAD_END_NACK:
-		fprintf(stderr, "ERROR: Software Load End NACK\n");
-		exit(3);
-		break;
-	case NM_MT_ACTIVATE_SW_NACK:
-		fprintf(stderr, "ERROR: Activate Software NACK\n");
-		exit(4);
-		break;
-	case NM_MT_ACTIVATE_SW_ACK:
-		break;
-	case NM_MT_LOAD_SEG_ACK:
-		percent = abis_nm_software_load_status(trx->bts);
-		if (percent > percent_old)
-			printf("Software Download Progress: %d%%\n", percent);
-		percent_old = percent;
-		break;
-	case NM_MT_LOAD_ABORT:
-		fprintf(stderr, "ERROR: Load aborted by the BTS.\n");
-		exit(6);
-		break;
-	}
-	return 0;
-}
-
-static void nv_put_ip_if_cfg(struct msgb *nmsg, uint32_t ip, uint32_t mask)
-{
-	msgb_put_u8(nmsg, NM_ATT_IPACC_IP_IF_CFG);
-
-	msgb_put_u32(nmsg, ip);
-	msgb_put_u32(nmsg, mask);
-}
-
-static void nv_put_gw_cfg(struct msgb *nmsg, uint32_t addr, uint32_t mask, uint32_t gw)
-{
-	msgb_put_u8(nmsg, NM_ATT_IPACC_IP_GW_CFG);
-	msgb_put_u32(nmsg, addr);
-	msgb_put_u32(nmsg, mask);
-	msgb_put_u32(nmsg, gw);
-}
-
-static void nv_put_unit_id(struct msgb *nmsg, const char *unit_id)
-{
-	msgb_tl16v_put(nmsg, NM_ATT_IPACC_UNIT_ID, strlen(unit_id)+1,
-			(const uint8_t *)unit_id);
-}
-
-static void nv_put_prim_oml(struct msgb *nmsg, uint32_t ip, uint16_t port)
-{
-	int len;
-
-	/* 0x88 + IP + port */
-	len = 1 + sizeof(ip) + sizeof(port);
-
-	msgb_put_u8(nmsg, NM_ATT_IPACC_PRIM_OML_CFG_LIST);
-	msgb_put_u16(nmsg, len);
-
-	msgb_put_u8(nmsg, 0x88);
-
-	/* IP address */
-	msgb_put_u32(nmsg, ip);
-
-	/* port number */
-	msgb_put_u16(nmsg, port);
-}
-
-static void nv_put_flags(struct msgb *nmsg, uint16_t nv_flags, uint16_t nv_mask)
-{
-	msgb_put_u8(nmsg, NM_ATT_IPACC_NV_FLAGS);
-	msgb_put_u16(nmsg, sizeof(nv_flags) + sizeof(nv_mask));
-	msgb_put_u8(nmsg, nv_flags & 0xff);
-	msgb_put_u8(nmsg, nv_mask & 0xff);
-	msgb_put_u8(nmsg, nv_flags >> 8);
-	msgb_put_u8(nmsg, nv_mask >> 8);
-}
-
-/* human-readable test names for the ip.access tests */
-static const struct value_string ipa_test_strs[] = {
-	{ 64, "ccch-usage" },
-	{ 65, "bcch-usage" },
-	{ 66, "freq-sync" },
-	{ 67, "rtp-usage" },
-	{ 68, "rtp-perf" },
-	{ 69, "gprs-ccch" },
-	{ 70, "pccch-usage" },
-	{ 71, "gprs-usage" },
-	{ 72, "esta-mf" },
-	{ 73, "uplink-mf" },
-	{ 74, "dolink-mf" },
-	{ 75, "tbf-details" },
-	{ 76, "tbf-usage" },
-	{ 77, "llc-data" },
-	{ 78, "pdch-usage" },
-	{ 79, "power-control" },
-	{ 80, "link-adaption" },
-	{ 81, "tch-usage" },
-	{ 82, "amr-mf" },
-	{ 83, "rtp-multiplex-perf" },
-	{ 84, "rtp-multiplex-usage" },
-	{ 85, "srtp-multiplex-usage" },
-	{ 86, "abis-traffic" },
-	{ 89, "gprs-multiplex-perf" },
-	{ 90, "gprs-multiplex-usage" },
-	{ 0, NULL },
-};
-
-/* human-readable names for the ip.access nanoBTS NVRAM Flags */
-static const struct value_string ipa_nvflag_strs[] = {
-	{ 0x0001, "static-ip" },
-	{ 0x0002, "static-gw" },
-	{ 0x0004, "no-dhcp-vsi" },
-	{ 0x0008, "dhcp-enabled" },
-	{ 0x0040, "led-disabled" },
-	{ 0x0100, "secondary-oml-enabled" },
-	{ 0x0200, "diag-enabled" },
-	{ 0x0400, "cli-enabled" },
-	{ 0x0800, "http-enabled" },
-	{ 0x1000, "post-enabled" },
-	{ 0x2000, "snmp-enabled" },
-	{ 0, NULL }
-};
-
-/* set the flags in flags/mask according to a string-identified flag and 'enable' */
-static int ipa_nvflag_set(uint16_t *flags, uint16_t *mask, const char *name, int en)
-{
-	int rc;
-	rc = get_string_value(ipa_nvflag_strs, name);
-	if (rc < 0)
-		return rc;
-
-	*mask |= rc;
-	if (en)
-		*flags |= rc;
-	else
-		*flags &= ~rc;
-
-	return 0;
-}
-
-static void bootstrap_om(struct gsm_bts_trx *trx)
-{
-	struct msgb *nmsg = msgb_alloc(1024, "nested msgb");
-	int need_to_set_attr = 0;
-	int len;
-
-	printf("OML link established using TRX %d\n", trx->nr);
-
-	if (unit_id) {
-		len = strlen(unit_id);
-		if (len > nmsg->data_len-10)
-			goto out_err;
-		printf("setting Unit ID to '%s'\n", unit_id);
-		nv_put_unit_id(nmsg, unit_id);
-		need_to_set_attr = 1;
-	}
-	if (prim_oml_ip) {
-		struct in_addr ia;
-
-		if (!inet_aton(prim_oml_ip, &ia)) {
-			fprintf(stderr, "invalid IP address: %s\n",
-				prim_oml_ip);
-			goto out_err;
-		}
-
-		printf("setting primary OML link IP to '%s'\n", inet_ntoa(ia));
-		nv_put_prim_oml(nmsg, ntohl(ia.s_addr), 0);
-		need_to_set_attr = 1;
-	}
-	if (nv_mask) {
-		printf("setting NV Flags/Mask to 0x%04x/0x%04x\n",
-			nv_flags, nv_mask);
-		nv_put_flags(nmsg, nv_flags, nv_mask);
-		need_to_set_attr = 1;
-	}
-	if (bts_ip_addr && bts_ip_mask) {
-		struct in_addr ia_addr, ia_mask;
-
-		if (!inet_aton(bts_ip_addr, &ia_addr)) {
-			fprintf(stderr, "invalid IP address: %s\n",
-				bts_ip_addr);
-			goto out_err;
-		}
-
-		if (!inet_aton(bts_ip_mask, &ia_mask)) {
-			fprintf(stderr, "invalid IP address: %s\n",
-				bts_ip_mask);
-			goto out_err;
-		}
-
-		printf("setting static IP Address/Mask\n");
-		nv_put_ip_if_cfg(nmsg, ntohl(ia_addr.s_addr), ntohl(ia_mask.s_addr));
-		need_to_set_attr = 1;
-	}
-	if (bts_ip_gw) {
-		struct in_addr ia_gw;
-
-		if (!inet_aton(bts_ip_gw, &ia_gw)) {
-			fprintf(stderr, "invalid IP address: %s\n",
-				bts_ip_gw);
-			goto out_err;
-		}
-
-		printf("setting static IP Gateway\n");
-		/* we only set the default gateway with zero addr/mask */
-		nv_put_gw_cfg(nmsg, 0, 0, ntohl(ia_gw.s_addr));
-		need_to_set_attr = 1;
-	}
-
-	if (need_to_set_attr) {
-		abis_nm_ipaccess_set_nvattr(trx, nmsg->head, nmsg->len);
-		oml_state = 1;
-	}
-
-	if (restart && !prim_oml_ip && !software) {
-		printf("restarting BTS\n");
-		abis_nm_ipaccess_restart(trx);
-	}
-
-out_err:
-	msgb_free(nmsg);
-}
-
-static int nm_state_event(int evt, uint8_t obj_class, void *obj,
-			  struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
-			  struct abis_om_obj_inst *obj_inst)
-{
-	if (obj_class == NM_OC_BASEB_TRANSC) {
-		if (!found_trx && obj_inst->trx_nr != 0xff) {
-			struct gsm_bts_trx *trx = container_of(obj, struct gsm_bts_trx, bb_transc);
-			bootstrap_om(trx);
-			found_trx = 1;
-		}
-	} else if (evt == S_NM_STATECHG_OPER &&
-	    obj_class == NM_OC_RADIO_CARRIER &&
-	    new_state->availability == 3) {
-		struct gsm_bts_trx *trx = obj;
-
-		if (net_listen_testnr)
-			ipac_nwl_test_start(trx, net_listen_testnr,
-					    phys_conf_min, sizeof(phys_conf_min));
-		else if (software) {
-			int rc;
-			printf("Attempting software upload with '%s'\n", software);
-			rc = abis_nm_software_load(trx->bts, trx->nr, software, 19, 0, swload_cbfn, trx);
-			if (rc < 0) {
-				fprintf(stderr, "Failed to start software load\n");
-				exit(-3);
-			}
-		}
-	}
-	return 0;
-}
-
-static struct abis_nm_sw_desc *create_swload(struct sdp_header *header)
-{
-	struct abis_nm_sw_desc *load;
-
-	load = talloc_zero(tall_ctx_config, struct abis_nm_sw_desc);
-
-	osmo_strlcpy((char *)load->file_id, header->firmware_info.sw_part,
-		     sizeof(load->file_id));
-	load->file_id_len = strlen((char*)load->file_id) + 1;
-
-	osmo_strlcpy((char *)load->file_version, header->firmware_info.version,
-		     sizeof(load->file_version));
-	load->file_version_len = strlen((char*)load->file_version) + 1;
-
-	return load;
-}
-
-static int find_sw_load_params(const char *filename)
-{
-	struct stat stat;
-	struct sdp_header *header;
-	struct llist_head *entry;
-	int fd;
-	void *tall_firm_ctx = 0;
-
-	entry = talloc_zero(tall_firm_ctx, struct llist_head);
-	INIT_LLIST_HEAD(entry);
-
-	fd = open(filename, O_RDONLY);
-	if (!fd) {
-		perror("nada");
-		return -1;
-	}
-
-	/* verify the file */
-	if (fstat(fd, &stat) == -1) {
-		perror("Can not stat the file");
-		close(fd);
-		return -1;
-	}
-
-	ipaccess_analyze_file(fd, stat.st_size, 0, entry);
-	if (close(fd) != 0) {
-		perror("Close failed.\n");
-		return -1;
-	}
-
-	/* try to find what we are looking for */
-	llist_for_each_entry(header, entry, entry) {
-		if (ntohs(header->firmware_info.more_more_magic) == 0x1000) {
-			sw_load1 = create_swload(header);
-		} else if (ntohs(header->firmware_info.more_more_magic) == 0x2001) {
-			sw_load2 = create_swload(header);
-		}
-	}
-
-	if (!sw_load1 || !sw_load2) {
-		fprintf(stderr, "Did not find data.\n");
-		talloc_free(tall_firm_ctx);
-		return -1;
-        }
-
-	talloc_free(tall_firm_ctx);
-	return 0;
-}
-
-static void dump_entry(struct sdp_header_item *sub_entry, int part, int fd)
-{
-	int out_fd;
-	int copied;
-	char filename[4096];
-	off_t target;
-
-	if (!dump_files)
-		return;
-
-	if (sub_entry->header_entry.something1 == 0)
-		return;
-
-	snprintf(filename, sizeof(filename), "part.%d", part++);
-	out_fd = open(filename, O_WRONLY | O_CREAT, 0660);
-	if (out_fd < 0) {
-		perror("Can not dump firmware");
-		return;
-	}
-
-	target = sub_entry->absolute_offset + ntohl(sub_entry->header_entry.start) + 4;
-	if (lseek(fd, target, SEEK_SET) != target) {
-		perror("seek failed");
-		close(out_fd);
-		return;
-	}
-
-	for (copied = 0; copied < ntohl(sub_entry->header_entry.length); ++copied) {
-		char c;
-		if (read(fd, &c, sizeof(c)) != sizeof(c)) {
-			perror("copy failed");
-			break;
-		}
-
-		if (write(out_fd, &c, sizeof(c)) != sizeof(c)) {
-			perror("write failed");
-			break;
-		}
-	}
-
-	close(out_fd);
-}
-
-static void analyze_firmware(const char *filename)
-{
-	struct stat stat;
-	struct sdp_header *header;
-	struct sdp_header_item *sub_entry;
-	struct llist_head *entry;
-	int fd;
-	void *tall_firm_ctx = 0;
-	int part = 0;
-
-	entry = talloc_zero(tall_firm_ctx, struct llist_head);
-	INIT_LLIST_HEAD(entry);
-
-	printf("Opening possible firmware '%s'\n", filename);
-	fd = open(filename, O_RDONLY);
-	if (!fd) {
-		perror("nada");
-		return;
-	}
-
-	/* verify the file */
-	if (fstat(fd, &stat) == -1) {
-		perror("Can not stat the file");
-		close(fd);
-		return;
-	}
-
-	ipaccess_analyze_file(fd, stat.st_size, 0, entry);
-
-	llist_for_each_entry(header, entry, entry) {
-		printf("Printing header information:\n");
-		printf("more_more_magic: 0x%x\n", ntohs(header->firmware_info.more_more_magic));
-		printf("header_length: %u\n", ntohl(header->firmware_info.header_length));
-		printf("file_length: %u\n", ntohl(header->firmware_info.file_length));
-		printf("sw_part: %.20s\n", header->firmware_info.sw_part);
-		printf("text1: %.64s\n", header->firmware_info.text1);
-		printf("time: %.12s\n", header->firmware_info.time);
-		printf("date: %.14s\n", header->firmware_info.date);
-		printf("text2: %.10s\n", header->firmware_info.text2);
-		printf("version: %.20s\n", header->firmware_info.version);
-		printf("subitems...\n");
-
-		llist_for_each_entry(sub_entry, &header->header_list, entry) {
-			printf("\tsomething1: %u\n", sub_entry->header_entry.something1);
-			printf("\ttext1: %.64s\n", sub_entry->header_entry.text1);
-			printf("\ttime: %.12s\n", sub_entry->header_entry.time);
-			printf("\tdate: %.14s\n", sub_entry->header_entry.date);
-			printf("\ttext2: %.10s\n", sub_entry->header_entry.text2);
-			printf("\tversion: %.20s\n", sub_entry->header_entry.version);
-			printf("\tlength: %u\n", ntohl(sub_entry->header_entry.length));
-			printf("\taddr1: 0x%x\n", ntohl(sub_entry->header_entry.addr1));
-			printf("\taddr2: 0x%x\n", ntohl(sub_entry->header_entry.addr2));
-			printf("\tstart: 0x%x\n", ntohl(sub_entry->header_entry.start));
-			printf("\tabs. offset: 0x%lx\n", sub_entry->absolute_offset);
-			printf("\n\n");
-
-			dump_entry(sub_entry, part++, fd);
-		}
-		printf("\n\n");
-	}
-
-	if (close(fd) != 0) {
-		perror("Close failed.\n");
-		return;
-	}
-
-	talloc_free(tall_firm_ctx);
-}
-
-static void print_usage(void)
-{
-	printf("Usage: ipaccess-config IP_OF_BTS\n");
-}
-
-static void print_help(void)
-{
-#if 0
-	printf("Commands for reading from the BTS:\n");
-	printf("  -D --dump\t\t\tDump the BTS configuration\n");
-	printf("\n");
-#endif
-	printf("Commands for writing to the BTS:\n");
-	printf("  -u --unit-id UNIT_ID\t\tSet the Unit ID of the BTS\n");
-	printf("  -o --oml-ip IP\t\tSet primary OML IP (IP of your BSC)\n");
-	printf("  -i --ip-address IP/MASK\tSet static IP address + netmask of BTS\n");
-	printf("  -g --ip-gateway IP\t\tSet static IP gateway of BTS\n");
-	printf("  -r --restart\t\t\tRestart the BTS (after other operations)\n");
-	printf("  -n --nvram-flags FLAGS/MASK\tSet NVRAM attributes\n");
-	printf("  -S --nvattr-set FLAG\tSet one additional NVRAM attribute\n");
-	printf("  -U --nvattr-unset FLAG\tSet one additional NVRAM attribute\n");
-	printf("  -l --listen TESTNR\t\tPerform specified test number\n");
-	printf("  -L --Listen TEST_NAME\t\tPerform specified test\n");
-	printf("  -s --stream-id ID\t\tSet the IPA Stream Identifier for OML\n");
-	printf("  -d --software FIRMWARE\tDownload firmware into BTS\n");
-	printf("\n");
-	printf("Miscellaneous commands:\n");
-	printf("  -h --help\t\t\tthis text\n");
-	printf("  -H --HELP\t\t\tPrint parameter details.\n");
-	printf("  -f --firmware FIRMWARE\tProvide firmware information\n");
-	printf("  -w --write-firmware\t\tThis will dump the firmware parts to the filesystem. Use with -f.\n");
-	printf("  -p --loop\t\t\tLoop the tests executed with the --listen command.\n");
-}
-
-static void print_value_string(const struct value_string *val, int size)
-{
-	int i;
-
-	for (i = 0; i < size - 1; ++i) {
-		char sep = val[i + 1].str == NULL ? '.' : ',';
-		printf("%s%c ", val[i].str, sep);
-	}
-	printf("\n");
-}
-
-static void print_options(void)
-{
-
-	printf("Options for NVRAM (-S,-U):\n  ");
-	print_value_string(&ipa_nvflag_strs[0], ARRAY_SIZE(ipa_nvflag_strs));
-
-	printf("Options for Tests (-L):\n ");
-	print_value_string(&ipa_test_strs[0], ARRAY_SIZE(ipa_test_strs));
-}
-
-extern void bts_model_nanobts_init();
-
-int main(int argc, char **argv)
-{
-	struct gsm_bts *bts;
-	struct sockaddr_in sin;
-	int rc, option_index = 0, stream_id = 0xff;
-
-	tall_ctx_config = talloc_named_const(NULL, 0, "ipaccess-config");
-	msgb_talloc_ctx_init(tall_ctx_config, 0);
-
-	osmo_init_logging(&log_info);
-	log_parse_category_mask(osmo_stderr_target, "DNM,0");
-	bts_model_nanobts_init();
-
-	printf("ipaccess-config (C) 2009-2010 by Harald Welte and others\n");
-	printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
-
-	while (1) {
-		int c;
-		unsigned long ul;
-		char *slash;
-		static struct option long_options[] = {
-			{ "unit-id", 1, 0, 'u' },
-			{ "oml-ip", 1, 0, 'o' },
-			{ "ip-address", 1, 0, 'i' },
-			{ "ip-gateway", 1, 0, 'g' },
-			{ "restart", 0, 0, 'r' },
-			{ "nvram-flags", 1, 0, 'n' },
-			{ "nvattr-set", 1, 0, 'S' },
-			{ "nvattr-unset", 1, 0, 'U' },
-			{ "help", 0, 0, 'h' },
-			{ "HELP", 0, 0, 'H' },
-			{ "listen", 1, 0, 'l' },
-			{ "Listen", 1, 0, 'L' },
-			{ "stream-id", 1, 0, 's' },
-			{ "software", 1, 0, 'd' },
-			{ "firmware", 1, 0, 'f' },
-			{ "write-firmware", 0, 0, 'w' },
-			{ "disable-color", 0, 0, 'c'},
-			{ "loop", 0, 0, 'p' },
-			{ 0, 0, 0, 0 },
-		};
-
-		c = getopt_long(argc, argv, "u:o:i:g:rn:S:U:l:L:hs:d:f:wcpH", long_options,
-				&option_index);
-
-		if (c == -1)
-			break;
-
-		switch (c) {
-		case 'u':
-			unit_id = optarg;
-			break;
-		case 'o':
-			prim_oml_ip = optarg;
-			break;
-		case 'i':
-			slash = strchr(optarg, '/');
-			if (!slash)
-				exit(2);
-			bts_ip_addr = optarg;
-			*slash = 0;
-			bts_ip_mask = slash+1;
-			break;
-		case 'g':
-			bts_ip_gw = optarg;
-			break;
-		case 'r':
-			restart = 1;
-			break;
-		case 'n':
-			slash = strchr(optarg, '/');
-			if (!slash)
-				exit(2);
-			ul = strtoul(optarg, NULL, 16);
-			nv_flags = ul & 0xffff;
-			ul = strtoul(slash+1, NULL, 16);
-			nv_mask = ul & 0xffff;
-			break;
-		case 'S':
-			if (ipa_nvflag_set(&nv_flags, &nv_mask, optarg, 1) < 0)
-				exit(2);
-			break;
-		case 'U':
-			if (ipa_nvflag_set(&nv_flags, &nv_mask, optarg, 0) < 0)
-				exit(2);
-			break;
-		case 'l':
-			net_listen_testnr = atoi(optarg);
-			break;
-		case 'L':
-			net_listen_testnr = get_string_value(ipa_test_strs,
-							     optarg);
-			if (net_listen_testnr < 0) {
-				fprintf(stderr,
-					"The test '%s' is not known. Use -H to"
-					" see available tests.\n", optarg);
-				exit(2);
-			}
-			break;
-		case 's':
-			stream_id = atoi(optarg);
-			break;
-		case 'd':
-			software = strdup(optarg);
-			if (find_sw_load_params(optarg) != 0)
-				exit(0);
-			break;
-		case 'f':
-			firmware_analysis = optarg;
-			break;
-		case 'w':
-			dump_files = 1;
-			break;
-		case 'c':
-			log_set_use_color(osmo_stderr_target, 0);
-			break;
-		case 'p':
-			loop_tests = 1;
-			break;
-		case 'h':
-			print_usage();
-			print_help();
-			exit(0);
-		case 'H':
-			print_options();
-			exit(0);
-		}
-	};
-
-	if (firmware_analysis)
-		analyze_firmware(firmware_analysis);
-
-	if (optind >= argc) {
-		/* only warn if we have not done anything else */
-		if (!firmware_analysis)
-			fprintf(stderr, "you have to specify the IP address of the BTS. Use --help for more information\n");
-		exit(2);
-	}
-	libosmo_abis_init(tall_ctx_config);
-
-	bsc_gsmnet = bsc_network_init(tall_bsc_ctx, 1, 1, NULL);
-	if (!bsc_gsmnet)
-		exit(1);
-
-	bts = gsm_bts_alloc_register(bsc_gsmnet, GSM_BTS_TYPE_NANOBTS,
-				     HARDCODED_BSIC);
-	/* ip.access supports up to 4 chained TRX */
-	gsm_bts_trx_alloc(bts);
-	gsm_bts_trx_alloc(bts);
-	gsm_bts_trx_alloc(bts);
-	bts->oml_tei = stream_id;
-	
-	osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL);
-	osmo_signal_register_handler(SS_IPAC_NWL, nwl_sig_cb, NULL);
-
-	ipac_nwl_init();
-
-	printf("Trying to connect to ip.access BTS ...\n");
-
-	memset(&sin, 0, sizeof(sin));
-	sin.sin_family = AF_INET;
-	inet_aton(argv[optind], &sin.sin_addr);
-	rc = ia_config_connect(bts, &sin);
-	if (rc < 0) {
-		perror("Error connecting to the BTS");
-		exit(1);
-	}
-	
-	bts->oml_link->ts->sign.delay = 10;
-	bts->c0->rsl_link->ts->sign.delay = 10;
-	while (1) {
-		rc = osmo_select_main(0);
-		if (rc < 0)
-			exit(3);
-	}
-
-	exit(0);
-}
-
diff --git a/src/ipaccess/ipaccess-firmware.c b/src/ipaccess/ipaccess-firmware.c
deleted file mode 100644
index 5f55bb5..0000000
--- a/src/ipaccess/ipaccess-firmware.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/* Routines for parsing an ipacces SDP firmware file */
-
-/* (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/>.
- *
- */
-
-#include <openbsc/debug.h>
-#include <openbsc/ipaccess.h>
-#include <osmocom/core/talloc.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#define PART_LENGTH 138
-
-osmo_static_assert(sizeof(struct sdp_header_entry) == 138, right_entry);
-osmo_static_assert(sizeof(struct sdp_firmware) == 158, _right_header_length);
-
-/* more magic, the second "int" in the header */
-static char more_magic[] = { 0x10, 0x02 };
-
-int ipaccess_analyze_file(int fd, const unsigned int st_size, const unsigned int base_offset, struct llist_head *list)
-{
-	struct sdp_firmware *firmware_header = 0;
-	struct sdp_header *header;
-	char buf[4096];
-	int rc, i;
-	uint16_t table_size;
-	uint16_t table_offset;
-	off_t table_start;
-
-
-	rc = read(fd, buf, sizeof(*firmware_header));
-	if (rc < 0) {
-		perror("Can not read header start.");
-		return -1;
-	}
-
-	firmware_header = (struct sdp_firmware *) &buf[0];
-	if (strncmp(firmware_header->magic, " SDP", 4) != 0) {
-		fprintf(stderr, "Wrong magic.\n");
-		return -1;
-	}
-
-	if (memcmp(firmware_header->more_magic, more_magic, 2) != 0) {
-		fprintf(stderr, "Wrong more magic. Got: 0x%x 0x%x vs. 0x%x 0x%x\n",
-			firmware_header->more_magic[0] & 0xff, firmware_header->more_magic[1] & 0xff,
-			more_magic[0], more_magic[1]);
-		return -1;
-	}
-
-
-	if (ntohl(firmware_header->file_length) != st_size) {
-		fprintf(stderr, "The filesize and the header do not match.\n");
-		return -1;
-	}
-
-	/* add the firmware */
-	header = talloc_zero(list, struct sdp_header);
-	header->firmware_info = *firmware_header;
-	INIT_LLIST_HEAD(&header->header_list);
-	llist_add(&header->entry, list);
-
-	table_offset = ntohs(firmware_header->table_offset);
-	table_start = lseek(fd, table_offset, SEEK_CUR);
-	if (table_start == -1) {
-		fprintf(stderr, "Failed to seek to the rel position: 0x%x\n", table_offset);
-		return -1;
-	}
-
-	if (read(fd, &table_size, sizeof(table_size)) != sizeof(table_size)) {
-		fprintf(stderr, "The table size could not be read.\n");
-		return -1;
-	}
-
-	table_size = ntohs(table_size);
-
-	if (table_size % PART_LENGTH != 0) {
-		fprintf(stderr, "The part length seems to be wrong: 0x%x\n", table_size);
-		return -1;
-	}
-
-	/* look into each firmware now */
-	for (i = 0; i < table_size / PART_LENGTH; ++i) {
-		struct sdp_header_entry entry;
-		struct sdp_header_item *header_entry;
-		unsigned int offset = table_start + 2;
-		offset += i * 138;
-
-		if (lseek(fd, offset, SEEK_SET) != offset) {
-			fprintf(stderr, "Can not seek to the offset: %u.\n", offset);
-			return -1;
-		}
-
-		rc = read(fd, &entry, sizeof(entry));
-		if (rc != sizeof(entry)) {
-			fprintf(stderr, "Can not read the header entry.\n");
-			return -1;
-		}
-
-		header_entry = talloc_zero(header,  struct sdp_header_item);
-		header_entry->header_entry = entry;
-		header_entry->absolute_offset = base_offset;
-		llist_add(&header_entry->entry, &header->header_list);
-
-		/* now we need to find the SDP file... */
-		offset = ntohl(entry.start) + 4 + base_offset;
-		if (lseek(fd, offset, SEEK_SET) != offset) {
-			perror("can't seek to sdp");
-			return -1;
-		}
-
-
-		ipaccess_analyze_file(fd, ntohl(entry.length), offset, list);
-	}
-
-	return 0;
-}
-
diff --git a/src/ipaccess/ipaccess-proxy.c b/src/ipaccess/ipaccess-proxy.c
deleted file mode 100644
index d367442..0000000
--- a/src/ipaccess/ipaccess-proxy.c
+++ /dev/null
@@ -1,1226 +0,0 @@
-/* OpenBSC Abis/IP proxy ip.access nanoBTS */
-
-/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2010 by On-Waves
- * (C) 2010 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/>.
- *
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <time.h>
-#include <sys/fcntl.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-
-#define _GNU_SOURCE
-#include <getopt.h>
-
-#include <openbsc/gsm_data.h>
-#include <osmocom/core/application.h>
-#include <osmocom/core/select.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/gsm/ipa.h>
-#include <osmocom/abis/ipa.h>
-#include <osmocom/abis/ipaccess.h>
-#include <openbsc/debug.h>
-#include <openbsc/ipaccess.h>
-#include <openbsc/socket.h>
-#include <osmocom/core/talloc.h>
-
-/* one instance of an ip.access protocol proxy */
-struct ipa_proxy {
-	/* socket where we listen for incoming OML from BTS */
-	struct osmo_fd oml_listen_fd;
-	/* socket where we listen for incoming RSL from BTS */
-	struct osmo_fd rsl_listen_fd;
-	/* list of BTS's (struct ipa_bts_conn */
-	struct llist_head bts_list;
-	/* the BSC reconnect timer */
-	struct osmo_timer_list reconn_timer;
-	/* global GPRS NS data */
-	struct in_addr gprs_addr;
-	struct in_addr listen_addr;
-};
-
-/* global pointer to the proxy structure */
-static struct ipa_proxy *ipp;
-
-struct ipa_proxy_conn {
-	struct osmo_fd fd;
-	struct llist_head tx_queue;
-	struct ipa_bts_conn *bts_conn;
-};
-#define MAX_TRX 4
-
-/* represents a particular BTS in our proxy */
-struct ipa_bts_conn {
-	/* list of BTS's (ipa_proxy->bts_list) */
-	struct llist_head list;
-	/* back pointer to the proxy which we belong to */
-	struct ipa_proxy *ipp;
-	/* the unit ID as determined by CCM */
-	struct {
-		uint16_t site_id;
-		uint16_t bts_id;
-	} unit_id;
-
-	/* incoming connections from BTS */
-	struct ipa_proxy_conn *oml_conn;
-	struct ipa_proxy_conn *rsl_conn[MAX_TRX];
-
-	/* outgoing connections to BSC */
-	struct ipa_proxy_conn *bsc_oml_conn;
-	struct ipa_proxy_conn *bsc_rsl_conn[MAX_TRX];
-
-	/* UDP sockets for BTS and BSC injection */
-	struct osmo_fd udp_bts_fd;
-	struct osmo_fd udp_bsc_fd;
-
-	/* NS data */
-	struct in_addr bts_addr;
-	struct osmo_fd gprs_ns_fd;
-	int gprs_local_port;
-	uint16_t gprs_orig_port;
-	uint32_t gprs_orig_ip;
-
-	char *id_tags[256];
-	uint8_t *id_resp;
-	unsigned int id_resp_len;
-};
-
-enum ipp_fd_type {
-	OML_FROM_BTS = 1,
-	RSL_FROM_BTS = 2,
-	OML_TO_BSC = 3,
-	RSL_TO_BSC = 4,
-	UDP_TO_BTS = 5,
-	UDP_TO_BSC = 6,
-};
-
-/* some of the code against we link from OpenBSC needs this */
-void *tall_bsc_ctx;
-
-static char *listen_ipaddr;
-static char *bsc_ipaddr;
-static char *gprs_ns_ipaddr;
-
-static int gprs_ns_cb(struct osmo_fd *bfd, unsigned int what);
-
-#define PROXY_ALLOC_SIZE	1200
-
-static struct ipa_bts_conn *find_bts_by_unitid(struct ipa_proxy *ipp,
-						uint16_t site_id,
-						uint16_t bts_id)
-{
-	struct ipa_bts_conn *ipbc;
-
-	llist_for_each_entry(ipbc, &ipp->bts_list, list) {
-		if (ipbc->unit_id.site_id == site_id &&
-		    ipbc->unit_id.bts_id == bts_id)
-			return ipbc;
-	}
-
-	return NULL;
-}
-
-struct ipa_proxy_conn *alloc_conn(void)
-{
-	struct ipa_proxy_conn *ipc;
-
-	ipc = talloc_zero(tall_bsc_ctx, struct ipa_proxy_conn);
-	if (!ipc)
-		return NULL;
-
-	INIT_LLIST_HEAD(&ipc->tx_queue);
-
-	return ipc;
-}
-
-static int store_idtags(struct ipa_bts_conn *ipbc, struct tlv_parsed *tlvp)
-{
-	unsigned int i, len;
-
-	for (i = 0; i <= 0xff; i++) {
-		if (!TLVP_PRESENT(tlvp, i))
-			continue;
-
-		len = TLVP_LEN(tlvp, i);
-#if 0
-		if (!ipbc->id_tags[i])
-			ipbc->id_tags[i] = talloc_size(tall_bsc_ctx, len);
-		else
-#endif
-			ipbc->id_tags[i] = talloc_realloc_size(ipbc,
-							  ipbc->id_tags[i], len);
-		if (!ipbc->id_tags[i])
-			return -ENOMEM;
-
-		memset(ipbc->id_tags[i], 0, len);
-		//memcpy(ipbc->id_tags[i], TLVP_VAL(tlvp, i), len);
-	}
-	return 0;
-}
-
-
-static struct ipa_proxy_conn *connect_bsc(struct sockaddr_in *sa, int priv_nr, void *data);
-
-#define logp_ipbc_uid(ss, lvl, ipbc, trx_id) _logp_ipbc_uid(ss, lvl, __FILE__, __LINE__, ipbc, trx_id)
-
-static void _logp_ipbc_uid(unsigned int ss, unsigned int lvl, char *file, int line,
-			   struct ipa_bts_conn *ipbc, uint8_t trx_id)
-{
-	if (ipbc)
-		logp2(ss, lvl, file, line, 0, "(%u/%u/%u) ", ipbc->unit_id.site_id,
-		     ipbc->unit_id.bts_id, trx_id);
-	else
-		logp2(ss, lvl, file, line, 0, "unknown ");
-}
-
-static int handle_udp_read(struct osmo_fd *bfd)
-{
-	struct ipa_bts_conn *ipbc = bfd->data;
-	struct ipa_proxy_conn *other_conn = NULL;
-	struct msgb *msg = msgb_alloc(PROXY_ALLOC_SIZE, "Abis/IP UDP");
-	struct ipaccess_head *hh;
-	int ret;
-
-	/* with UDP sockets, we cannot read partial packets but have to read
-	 * all of it in one go */
-	hh = (struct ipaccess_head *) msg->data;
-	ret = recv(bfd->fd, msg->data, msg->data_len, 0);
-	if (ret < 0) {
-		if (errno != EAGAIN)
-			LOGP(DLINP, LOGL_ERROR, "recv error  %s\n", strerror(errno));
-		msgb_free(msg);
-		return ret;
-	}
-	if (ret == 0) {
-		DEBUGP(DLINP, "UDP peer disappeared, dead socket\n");
-		osmo_fd_unregister(bfd);
-		close(bfd->fd);
-		bfd->fd = -1;
-		msgb_free(msg);
-		return -EIO;
-	}
-	if (ret < sizeof(*hh)) {
-		DEBUGP(DLINP, "could not even read header!?!\n");
-		msgb_free(msg);
-		return -EIO;
-	}
-	msgb_put(msg, ret);
-	msg->l2h = msg->data + sizeof(*hh);
-	DEBUGP(DLMI, "UDP RX: %s\n", osmo_hexdump(msg->data, msg->len));
-
-	if (hh->len != msg->len - sizeof(*hh)) {
-		DEBUGP(DLINP, "length (%u/%u) disagrees with header(%u)\n",
-			msg->len, msg->len - 3, hh->len);
-		msgb_free(msg);
-		return -EIO;
-	}
-
-	switch (bfd->priv_nr & 0xff) {
-	case UDP_TO_BTS:
-		/* injection towards BTS */
-		switch (hh->proto) {
-		case IPAC_PROTO_RSL:
-			/* FIXME: what to do about TRX > 0 */
-			other_conn = ipbc->rsl_conn[0];
-			break;
-		default:
-			DEBUGP(DLINP, "Unknown protocol 0x%02x, sending to "
-				"OML FD\n", hh->proto);
-			/* fall through */
-		case IPAC_PROTO_IPACCESS:
-		case IPAC_PROTO_OML:
-			other_conn = ipbc->oml_conn;
-			break;
-		}
-		break;
-	case UDP_TO_BSC:
-		/* injection towards BSC */
-		switch (hh->proto) {
-		case IPAC_PROTO_RSL:
-			/* FIXME: what to do about TRX > 0 */
-			other_conn = ipbc->bsc_rsl_conn[0];
-			break;
-		default:
-			DEBUGP(DLINP, "Unknown protocol 0x%02x, sending to "
-				"OML FD\n", hh->proto);
-			/* fall through */
-		case IPAC_PROTO_IPACCESS:
-		case IPAC_PROTO_OML:
-			other_conn = ipbc->bsc_oml_conn;
-			break;
-		}
-		break;
-	default:
-		DEBUGP(DLINP, "Unknown filedescriptor priv_nr=%04x\n", bfd->priv_nr);
-		break;
-	}
-
-	if (other_conn) {
-		/* enqueue the message for TX on the respective FD */
-		msgb_enqueue(&other_conn->tx_queue, msg);
-		other_conn->fd.when |= BSC_FD_WRITE;
-	} else
-		msgb_free(msg);
-
-	return 0;
-}
-
-static int handle_udp_write(struct osmo_fd *bfd)
-{
-	/* not implemented yet */
-	bfd->when &= ~BSC_FD_WRITE;
-
-	return -EIO;
-}
-
-/* callback from select.c in case one of the fd's can be read/written */
-static int udp_fd_cb(struct osmo_fd *bfd, unsigned int what)
-{
-	int rc = 0;
-
-	if (what & BSC_FD_READ)
-		rc = handle_udp_read(bfd);
-	if (what & BSC_FD_WRITE)
-		rc = handle_udp_write(bfd);
-
-	return rc;
-}
-
-
-static int ipbc_alloc_connect(struct ipa_proxy_conn *ipc, struct osmo_fd *bfd,
-			      uint16_t site_id, uint16_t bts_id,
-			      uint16_t trx_id, struct tlv_parsed *tlvp,
-			      struct msgb *msg)
-{
-	struct ipa_bts_conn *ipbc;
-	uint16_t udp_port;
-	int ret = 0;
-	struct sockaddr_in sin;
-
-	memset(&sin, 0, sizeof(sin));
-	sin.sin_family = AF_INET;
-	inet_aton(bsc_ipaddr, &sin.sin_addr);
-
-	DEBUGP(DLINP, "(%u/%u/%u) New BTS connection: ",
-		site_id, bts_id, trx_id);
-
-	/* OML needs to be established before RSL */
-	if ((bfd->priv_nr & 0xff) != OML_FROM_BTS) {
-		DEBUGPC(DLINP, "Not a OML connection ?!?\n");
-		return -EIO;
-	}
-
-	/* allocate new BTS connection data structure */
-	ipbc = talloc_zero(tall_bsc_ctx, struct ipa_bts_conn);
-	if (!ipbc) {
-		ret = -ENOMEM;
-		goto err_out;
-	}
-
-	DEBUGPC(DLINP, "Created BTS Conn data structure\n");
-	ipbc->ipp = ipp;
-	ipbc->unit_id.site_id = site_id;
-	ipbc->unit_id.bts_id = bts_id;
-	ipbc->oml_conn = ipc;
-	ipc->bts_conn = ipbc;
-
-	/* store the content of the ID TAGS for later reference */
-	store_idtags(ipbc, tlvp);
-	ipbc->id_resp_len = msg->len;
-	ipbc->id_resp = talloc_size(tall_bsc_ctx, ipbc->id_resp_len);
-	memcpy(ipbc->id_resp, msg->data, ipbc->id_resp_len);
-
-	/* Create OML TCP connection towards BSC */
-	sin.sin_port = htons(IPA_TCP_PORT_OML);
-	ipbc->bsc_oml_conn = connect_bsc(&sin, OML_TO_BSC, ipbc);
-	if (!ipbc->bsc_oml_conn) {
-		ret = -EIO;
-		goto err_bsc_conn;
-	}
-
-	DEBUGP(DLINP, "(%u/%u/%u) OML Connected to BSC\n",
-		site_id, bts_id, trx_id);
-
-	/* Create UDP socket for BTS packet injection */
-	udp_port = 10000 + (site_id % 1000)*100 + (bts_id % 100);
-	ret = make_sock(&ipbc->udp_bts_fd, IPPROTO_UDP, INADDR_ANY, udp_port,
-			UDP_TO_BTS, udp_fd_cb, ipbc);
-	if (ret < 0)
-		goto err_udp_bts;
-	DEBUGP(DLINP, "(%u/%u/%u) Created UDP socket for injection "
-		"towards BTS at port %u\n", site_id, bts_id, trx_id, udp_port);
-
-	/* Create UDP socket for BSC packet injection */
-	udp_port = 20000 + (site_id % 1000)*100 + (bts_id % 100);
-	ret = make_sock(&ipbc->udp_bsc_fd, IPPROTO_UDP, INADDR_ANY, udp_port,
-			UDP_TO_BSC, udp_fd_cb, ipbc);
-	if (ret < 0)
-		goto err_udp_bsc;
-	DEBUGP(DLINP, "(%u/%u/%u) Created UDP socket for injection "
-		"towards BSC at port %u\n", site_id, bts_id, trx_id, udp_port);
-
-
-	/* GPRS NS related code */
-	if (gprs_ns_ipaddr) {
-		struct sockaddr_in sock;
-		socklen_t len = sizeof(sock);
-		struct in_addr addr;
-		uint32_t ip;
-
-		inet_aton(listen_ipaddr, &addr);
-		ip = ntohl(addr.s_addr); /* make_sock() needs host byte order */
-		ret = make_sock(&ipbc->gprs_ns_fd, IPPROTO_UDP, ip, 0, 0,
-				gprs_ns_cb, ipbc);
-		if (ret < 0) {
-			LOGP(DLINP, LOGL_ERROR, "Creating the GPRS socket failed.\n");
-			goto err_udp_bsc;
-		}
-
-		ret = getsockname(ipbc->gprs_ns_fd.fd, (struct sockaddr* ) &sock, &len);
-		ipbc->gprs_local_port = ntohs(sock.sin_port);
-		LOGP(DLINP, LOGL_NOTICE,
-			"Created GPRS NS Socket. Listening on: %s:%d\n",
-			inet_ntoa(sock.sin_addr), ipbc->gprs_local_port);
-
-		ret = getpeername(bfd->fd, (struct sockaddr* ) &sock, &len);
-		ipbc->bts_addr = sock.sin_addr;
-	}
-
-	llist_add(&ipbc->list, &ipp->bts_list);
-
-	return 0;
-
-err_udp_bsc:
-	osmo_fd_unregister(&ipbc->udp_bts_fd);
-err_udp_bts:
-	osmo_fd_unregister(&ipbc->bsc_oml_conn->fd);
-	close(ipbc->bsc_oml_conn->fd.fd);
-	talloc_free(ipbc->bsc_oml_conn);
-	ipbc->bsc_oml_conn = NULL;
-err_bsc_conn:
-	talloc_free(ipbc->id_resp);
-	talloc_free(ipbc);
-#if 0
-	osmo_fd_unregister(bfd);
-	close(bfd->fd);
-	talloc_free(bfd);
-#endif
-err_out:
-	return ret;
-}
-
-static int ipaccess_rcvmsg(struct ipa_proxy_conn *ipc, struct msgb *msg,
-			   struct osmo_fd *bfd)
-{
-	struct tlv_parsed tlvp;
-	uint8_t msg_type = *(msg->l2h);
-	struct ipaccess_unit unit_data;
-	struct ipa_bts_conn *ipbc;
-	int ret = 0;
-
-	switch (msg_type) {
-	case IPAC_MSGT_PING:
-		ret = ipa_ccm_send_pong(bfd->fd);
-		break;
-	case IPAC_MSGT_PONG:
-		DEBUGP(DLMI, "PONG!\n");
-		break;
-	case IPAC_MSGT_ID_RESP:
-		DEBUGP(DLMI, "ID_RESP ");
-		/* parse tags, search for Unit ID */
-		ipa_ccm_idtag_parse(&tlvp, (uint8_t *)msg->l2h + 2,
-				     msgb_l2len(msg)-2);
-		DEBUGP(DLMI, "\n");
-
-		if (!TLVP_PRESENT(&tlvp, IPAC_IDTAG_UNIT)) {
-			LOGP(DLINP, LOGL_ERROR, "No Unit ID in ID RESPONSE !?!\n");
-			return -EIO;
-		}
-
-		/* lookup BTS, create sign_link, ... */
-		memset(&unit_data, 0, sizeof(unit_data));
-		ipa_parse_unitid((char *)TLVP_VAL(&tlvp, IPAC_IDTAG_UNIT),
-				      &unit_data);
-		ipbc = find_bts_by_unitid(ipp, unit_data.site_id, unit_data.bts_id);
-		if (!ipbc) {
-			/* We have not found an ipbc (per-bts proxy instance)
-			 * for this BTS yet.  The first connection of a new BTS must
-			 * be a OML connection.  We allocate the associated data structures,
-			 * and try to connect to the remote end */
-
-			return ipbc_alloc_connect(ipc, bfd, unit_data.site_id,
-						  unit_data.bts_id,
-						  unit_data.trx_id, &tlvp, msg);
-			/* if this fails, the caller will clean up bfd */
-		} else {
-			struct sockaddr_in sin;
-			memset(&sin, 0, sizeof(sin));
-			sin.sin_family = AF_INET;
-			inet_aton(bsc_ipaddr, &sin.sin_addr);
-
-			DEBUGP(DLINP, "Identified BTS %u/%u/%u\n",
-				unit_data.site_id, unit_data.bts_id, unit_data.trx_id);
-
-			if ((bfd->priv_nr & 0xff) != RSL_FROM_BTS) {
-				LOGP(DLINP, LOGL_ERROR, "Second OML connection from "
-				     "same BTS ?!?\n");
-				return 0;
-			}
-
-			if (unit_data.trx_id >= MAX_TRX) {
-				LOGP(DLINP, LOGL_ERROR, "We don't support more "
-				     "than %u TRX\n", MAX_TRX);
-				return -EINVAL;
-			}
-
-			ipc->bts_conn = ipbc;
-			/* store TRX number in higher 8 bit of the bfd private number */
-			bfd->priv_nr |= unit_data.trx_id << 8;
-			ipbc->rsl_conn[unit_data.trx_id] = ipc;
-
-			/* Create RSL TCP connection towards BSC */
-			sin.sin_port = htons(IPA_TCP_PORT_RSL);
-			ipbc->bsc_rsl_conn[unit_data.trx_id] =
-				connect_bsc(&sin, RSL_TO_BSC | (unit_data.trx_id << 8), ipbc);
-			if (!ipbc->bsc_oml_conn)
-				return -EIO;
-			DEBUGP(DLINP, "(%u/%u/%u) Connected RSL to BSC\n",
-				unit_data.site_id, unit_data.bts_id, unit_data.trx_id);
-		}
-		break;
-	case IPAC_MSGT_ID_GET:
-		DEBUGP(DLMI, "ID_GET\n");
-		if ((bfd->priv_nr & 0xff) != OML_TO_BSC &&
-		    (bfd->priv_nr & 0xff) != RSL_TO_BSC) {
-			DEBUGP(DLINP, "IDentity REQuest from BTS ?!?\n");
-			return -EIO;
-		}
-		ipbc = ipc->bts_conn;
-		if (!ipbc) {
-			DEBUGP(DLINP, "ID_GET from BSC before we have ID_RESP from BTS\n");
-			return -EIO;
-		}
-		ret = write(bfd->fd, ipbc->id_resp, ipbc->id_resp_len);
-		if (ret != ipbc->id_resp_len) {
-			LOGP(DLINP, LOGL_ERROR, "Partial write: %d of %d\n",
-			     ret, ipbc->id_resp_len);
-			return -EIO;
-		}
-		ret = 0;
-		break;
-	case IPAC_MSGT_ID_ACK:
-		DEBUGP(DLMI, "ID_ACK? -> ACK!\n");
-		ret = ipa_ccm_send_id_ack(bfd->fd);
-		break;
-	default:
-		LOGP(DLMI, LOGL_ERROR, "Unhandled IPA type; %d\n", msg_type);
-		return 1;
-		break;
-	}
-	return ret;
-}
-
-struct msgb *ipaccess_proxy_read_msg(struct osmo_fd *bfd, int *error)
-{
-	struct msgb *msg = msgb_alloc(PROXY_ALLOC_SIZE, "Abis/IP");
-	struct ipaccess_head *hh;
-	int len, ret = 0;
-
-	if (!msg) {
-		*error = -ENOMEM;
-		return NULL;
-	}
-
-	/* first read our 3-byte header */
-	hh = (struct ipaccess_head *) msg->data;
-	ret = recv(bfd->fd, msg->data, 3, 0);
-	if (ret < 0) {
-		if (errno != EAGAIN)
-			LOGP(DLINP, LOGL_ERROR, "recv error: %s\n", strerror(errno));
-		msgb_free(msg);
-		*error = ret;
-		return NULL;
-	} else if (ret == 0) {
-		msgb_free(msg);
-		*error = ret;
-		return NULL;
-	}
-
-	msgb_put(msg, ret);
-
-	/* then read te length as specified in header */
-	msg->l2h = msg->data + sizeof(*hh);
-	len = ntohs(hh->len);
-	ret = recv(bfd->fd, msg->l2h, len, 0);
-	if (ret < len) {
-		LOGP(DLINP, LOGL_ERROR, "short read!\n");
-		msgb_free(msg);
-		*error = -EIO;
-		return NULL;
-	}
-	msgb_put(msg, ret);
-
-	return msg;
-}
-
-static struct ipa_proxy_conn *ipc_by_priv_nr(struct ipa_bts_conn *ipbc,
-					     unsigned int priv_nr)
-{
-	struct ipa_proxy_conn *bsc_conn;
-	unsigned int trx_id = priv_nr >> 8;
-
-	switch (priv_nr & 0xff) {
-	case OML_FROM_BTS: /* incoming OML data from BTS, forward to BSC OML */
-		bsc_conn = ipbc->bsc_oml_conn;
-		break;
-	case RSL_FROM_BTS: /* incoming RSL data from BTS, forward to BSC RSL */
-		bsc_conn = ipbc->bsc_rsl_conn[trx_id];
-		break;
-	case OML_TO_BSC: /* incoming OML data from BSC, forward to BTS OML */
-		bsc_conn = ipbc->oml_conn;
-		break;
-	case RSL_TO_BSC: /* incoming RSL data from BSC, forward to BTS RSL */
-		bsc_conn = ipbc->rsl_conn[trx_id];
-		break;
-	default:
-		bsc_conn = NULL;
-		break;
-	}
-	return bsc_conn;
-}
-
-static void reconn_tmr_cb(void *data)
-{
-	struct ipa_proxy *ipp = data;
-	struct ipa_bts_conn *ipbc;
-	struct sockaddr_in sin;
-	int i;
-
-	DEBUGP(DLINP, "Running reconnect timer\n");
-
-	memset(&sin, 0, sizeof(sin));
-	sin.sin_family = AF_INET;
-	inet_aton(bsc_ipaddr, &sin.sin_addr);
-
-	llist_for_each_entry(ipbc, &ipp->bts_list, list) {
-		/* if OML to BSC is dead, try to restore it */
-		if (ipbc->oml_conn && !ipbc->bsc_oml_conn) {
-			sin.sin_port = htons(IPA_TCP_PORT_OML);
-			logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, 0);
-			LOGPC(DLINP, LOGL_NOTICE, "OML Trying to reconnect\n");
-			ipbc->bsc_oml_conn = connect_bsc(&sin, OML_TO_BSC, ipbc);
-			if (!ipbc->bsc_oml_conn)
-				goto reschedule;
-			logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, 0);
-			LOGPC(DLINP, LOGL_NOTICE, "OML Reconnected\n");
-		}
-		/* if we (still) don't have a OML connection, skip RSL */
-		if (!ipbc->oml_conn || !ipbc->bsc_oml_conn)
-			continue;
-
-		for (i = 0; i < ARRAY_SIZE(ipbc->rsl_conn); i++) {
-			unsigned int priv_nr;
-			/* don't establish RSL links which we don't have */
-			if (!ipbc->rsl_conn[i])
-				continue;
-			if (ipbc->bsc_rsl_conn[i])
-				continue;
-			priv_nr = ipbc->rsl_conn[i]->fd.priv_nr;
-			priv_nr &= ~0xff;
-			priv_nr |= RSL_TO_BSC;
-			sin.sin_port = htons(IPA_TCP_PORT_RSL);
-			logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, priv_nr >> 8);
-			LOGPC(DLINP, LOGL_NOTICE, "RSL Trying to reconnect\n");
-			ipbc->bsc_rsl_conn[i] = connect_bsc(&sin, priv_nr, ipbc);
-			if (!ipbc->bsc_rsl_conn[i])
-				goto reschedule;
-			logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, priv_nr >> 8);
-			LOGPC(DLINP, LOGL_NOTICE, "RSL Reconnected\n");
-		}
-	}
-	return;
-
-reschedule:
-	osmo_timer_schedule(&ipp->reconn_timer, 5, 0);
-}
-
-static void handle_dead_socket(struct osmo_fd *bfd)
-{
-	struct ipa_proxy_conn *ipc = bfd->data;		/* local conn */
-	struct ipa_proxy_conn *bsc_conn;		/* remote conn */
-	struct ipa_bts_conn *ipbc = ipc->bts_conn;
-	unsigned int trx_id = bfd->priv_nr >> 8;
-	struct msgb *msg, *msg2;
-
-	osmo_fd_unregister(bfd);
-	close(bfd->fd);
-	bfd->fd = -1;
-
-	/* FIXME: clear tx_queue, remove all references, etc. */
-	llist_for_each_entry_safe(msg, msg2, &ipc->tx_queue, list)
-		msgb_free(msg);
-
-	switch (bfd->priv_nr & 0xff) {
-	case OML_FROM_BTS: /* incoming OML data from BTS, forward to BSC OML */
-		/* The BTS started a connection with us but we got no
-		 * IPAC_MSGT_ID_RESP message yet, in that scenario we did not
-		 * allocate the ipa_bts_conn structure. */
-		if (ipbc == NULL)
-			break;
-		ipbc->oml_conn = NULL;
-		bsc_conn = ipbc->bsc_oml_conn;
-		/* close the connection to the BSC */
-		osmo_fd_unregister(&bsc_conn->fd);
-		close(bsc_conn->fd.fd);
-		llist_for_each_entry_safe(msg, msg2, &bsc_conn->tx_queue, list)
-			msgb_free(msg);
-		talloc_free(bsc_conn);
-		ipbc->bsc_oml_conn = NULL;
-		/* FIXME: do we need to delete the entire ipbc ? */
-		break;
-	case RSL_FROM_BTS: /* incoming RSL data from BTS, forward to BSC RSL */
-		ipbc->rsl_conn[trx_id] = NULL;
-		bsc_conn = ipbc->bsc_rsl_conn[trx_id];
-		/* close the connection to the BSC */
-		osmo_fd_unregister(&bsc_conn->fd);
-		close(bsc_conn->fd.fd);
-		llist_for_each_entry_safe(msg, msg2, &bsc_conn->tx_queue, list)
-			msgb_free(msg);
-		talloc_free(bsc_conn);
-		ipbc->bsc_rsl_conn[trx_id] = NULL;
-		break;
-	case OML_TO_BSC: /* incoming OML data from BSC, forward to BTS OML */
-		ipbc->bsc_oml_conn = NULL;
-		bsc_conn = ipbc->oml_conn;
-		/* start reconnect timer */
-		osmo_timer_schedule(&ipp->reconn_timer, 5, 0);
-		break;
-	case RSL_TO_BSC: /* incoming RSL data from BSC, forward to BTS RSL */
-		ipbc->bsc_rsl_conn[trx_id] = NULL;
-		bsc_conn = ipbc->rsl_conn[trx_id];
-		/* start reconnect timer */
-		osmo_timer_schedule(&ipp->reconn_timer, 5, 0);
-		break;
-	default:
-		bsc_conn = NULL;
-		break;
-	}
-
-	talloc_free(ipc);
-}
-
-static void patch_gprs_msg(struct ipa_bts_conn *ipbc, int priv_nr, struct msgb *msg)
-{
-	uint8_t *nsvci;
-
-	if ((priv_nr & 0xff) != OML_FROM_BTS && (priv_nr & 0xff) != OML_TO_BSC)
-		return;
-
-	if (msgb_l2len(msg) != 39)
-		return;
-
-	/*
-	 * Check if this is a IPA Set Attribute or IPA Set Attribute ACK
-	 * and if the FOM Class is GPRS NSVC0 and then we will patch it.
-	 *
-	 * The patch assumes the message looks like the one from the trace
-	 * but we only match messages with a specific size anyway... So
-	 * this hack should work just fine.
-	 */
-
-	if (msg->l2h[0] == 0x10 && msg->l2h[1] == 0x80 &&
-	    msg->l2h[2] == 0x00 && msg->l2h[3] == 0x15 &&
-	    msg->l2h[18] == 0xf5 && msg->l2h[19] == 0xf2) {
-		nsvci = &msg->l2h[23];
-		ipbc->gprs_orig_port =  *(uint16_t *)(nsvci+8);
-		ipbc->gprs_orig_ip = *(uint32_t *)(nsvci+10);
-		*(uint16_t *)(nsvci+8) = htons(ipbc->gprs_local_port);
-		*(uint32_t *)(nsvci+10) = ipbc->ipp->listen_addr.s_addr;
-	} else if (msg->l2h[0] == 0x10 && msg->l2h[1] == 0x80 &&
-	    msg->l2h[2] == 0x00 && msg->l2h[3] == 0x15 &&
-	    msg->l2h[18] == 0xf6 && msg->l2h[19] == 0xf2) {
-		nsvci = &msg->l2h[23];
-		*(uint16_t *)(nsvci+8) = ipbc->gprs_orig_port;
-		*(uint32_t *)(nsvci+10) = ipbc->gprs_orig_ip;
-	}
-}
-
-static int handle_tcp_read(struct osmo_fd *bfd)
-{
-	struct ipa_proxy_conn *ipc = bfd->data;
-	struct ipa_bts_conn *ipbc = ipc->bts_conn;
-	struct ipa_proxy_conn *bsc_conn;
-	struct msgb *msg;
-	struct ipaccess_head *hh;
-	int ret = 0;
-	char *btsbsc;
-
-	if ((bfd->priv_nr & 0xff) <= 2)
-		btsbsc = "BTS";
-	else
-		btsbsc = "BSC";
-
-	msg = ipaccess_proxy_read_msg(bfd, &ret);
-	if (!msg) {
-		if (ret == 0) {
-			logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, bfd->priv_nr >> 8);
-			LOGPC(DLINP, LOGL_NOTICE, "%s disappeared, "
-			     "dead socket\n", btsbsc);
-			handle_dead_socket(bfd);
-		}
-		return ret;
-	}
-
-	msgb_put(msg, ret);
-	logp_ipbc_uid(DLMI, LOGL_DEBUG, ipbc, bfd->priv_nr >> 8);
-	DEBUGPC(DLMI, "RX<-%s: %s\n", btsbsc, osmo_hexdump(msg->data, msg->len));
-
-	hh = (struct ipaccess_head *) msg->data;
-	if (hh->proto == IPAC_PROTO_IPACCESS) {
-		ret = ipaccess_rcvmsg(ipc, msg, bfd);
-		if (ret < 0) {
-			osmo_fd_unregister(bfd);
-			close(bfd->fd);
-			bfd->fd = -1;
-			talloc_free(bfd);
-			msgb_free(msg);
-			return ret;
-		} else if (ret == 0) {
-			/* we do not forward parts of the CCM protocol
-			 * through the proxy but rather terminate it ourselves. */
-			msgb_free(msg);
-			return ret;
-		}
-	}
-
-	if (!ipbc) {
-		LOGP(DLINP, LOGL_ERROR,
-		     "received %s packet but no ipc->bts_conn?!?\n", btsbsc);
-		msgb_free(msg);
-		return -EIO;
-	}
-
-	bsc_conn = ipc_by_priv_nr(ipbc, bfd->priv_nr);
-	if (bsc_conn) {
-		if (gprs_ns_ipaddr)
-			patch_gprs_msg(ipbc, bfd->priv_nr, msg);
-		/* enqueue packet towards BSC */
-		msgb_enqueue(&bsc_conn->tx_queue, msg);
-		/* mark respective filedescriptor as 'we want to write' */
-		bsc_conn->fd.when |= BSC_FD_WRITE;
-	} else {
-		logp_ipbc_uid(DLINP, LOGL_INFO, ipbc, bfd->priv_nr >> 8);
-		LOGPC(DLINP, LOGL_INFO, "Dropping packet from %s, "
-		     "since remote connection is dead\n", btsbsc);
-		msgb_free(msg);
-	}
-
-	return ret;
-}
-
-/* a TCP socket is ready to be written to */
-static int handle_tcp_write(struct osmo_fd *bfd)
-{
-	struct ipa_proxy_conn *ipc = bfd->data;
-	struct ipa_bts_conn *ipbc = ipc->bts_conn;
-	struct llist_head *lh;
-	struct msgb *msg;
-	char *btsbsc;
-	int ret;
-
-	if ((bfd->priv_nr & 0xff) <= 2)
-		btsbsc = "BTS";
-	else
-		btsbsc = "BSC";
-
-
-	/* get the next msg for this timeslot */
-	if (llist_empty(&ipc->tx_queue)) {
-		bfd->when &= ~BSC_FD_WRITE;
-		return 0;
-	}
-	lh = ipc->tx_queue.next;
-	llist_del(lh);
-	msg = llist_entry(lh, struct msgb, list);
-
-	logp_ipbc_uid(DLMI, LOGL_DEBUG, ipbc, bfd->priv_nr >> 8);
-	DEBUGPC(DLMI, "TX %04x: %s\n", bfd->priv_nr,
-		osmo_hexdump(msg->data, msg->len));
-
-	ret = send(bfd->fd, msg->data, msg->len, 0);
-	msgb_free(msg);
-
-	if (ret == 0) {
-		logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, bfd->priv_nr >> 8);
-		LOGP(DLINP, LOGL_NOTICE, "%s disappeared, dead socket\n", btsbsc);
-		handle_dead_socket(bfd);
-	}
-
-	return ret;
-}
-
-/* callback from select.c in case one of the fd's can be read/written */
-static int proxy_ipaccess_fd_cb(struct osmo_fd *bfd, unsigned int what)
-{
-	int rc = 0;
-
-	if (what & BSC_FD_READ) {
-		rc = handle_tcp_read(bfd);
-		if (rc < 0)
-			return rc;
-	}
-	if (what & BSC_FD_WRITE)
-		rc = handle_tcp_write(bfd);
-
-	return rc;
-}
-
-/* callback of the listening filedescriptor */
-static int listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what)
-{
-	int ret;
-	struct ipa_proxy_conn *ipc;
-	struct osmo_fd *bfd;
-	struct sockaddr_in sa;
-	socklen_t sa_len = sizeof(sa);
-
-	if (!(what & BSC_FD_READ))
-		return 0;
-
-	ret = accept(listen_bfd->fd, (struct sockaddr *) &sa, &sa_len);
-	if (ret < 0) {
-		perror("accept");
-		return ret;
-	}
-	DEBUGP(DLINP, "accept()ed new %s link from %s\n",
-		(listen_bfd->priv_nr & 0xff) == OML_FROM_BTS ? "OML" : "RSL",
-		inet_ntoa(sa.sin_addr));
-
-	ipc = alloc_conn();
-	if (!ipc) {
-		close(ret);
-		return -ENOMEM;
-	}
-
-	bfd = &ipc->fd;
-	bfd->fd = ret;
-	bfd->data = ipc;
-	bfd->priv_nr = listen_bfd->priv_nr;
-	bfd->cb = proxy_ipaccess_fd_cb;
-	bfd->when = BSC_FD_READ;
-	ret = osmo_fd_register(bfd);
-	if (ret < 0) {
-		LOGP(DLINP, LOGL_ERROR, "could not register FD\n");
-		close(bfd->fd);
-		talloc_free(ipc);
-		return ret;
-	}
-
-	/* Request ID. FIXME: request LOCATION, HW/SW VErsion, Unit Name, Serno */
-	ret = ipa_ccm_send_id_req(bfd->fd);
-
-	return 0;
-}
-
-static void send_ns(int fd, const char *buf, int size, struct in_addr ip, int port)
-{
-	int ret;
-	struct sockaddr_in addr;
-	socklen_t len = sizeof(addr);
-	memset(&addr, 0, sizeof(addr));
-
-	addr.sin_family = AF_INET;
-	addr.sin_port = htons(port);
-	addr.sin_addr = ip;
-
-	ret = sendto(fd, buf, size, 0, (struct sockaddr *) &addr, len);
-	if (ret < 0) {
-		LOGP(DLINP, LOGL_ERROR, "Failed to forward GPRS message.\n");
-	}
-}
-
-static int gprs_ns_cb(struct osmo_fd *bfd, unsigned int what)
-{
-	struct ipa_bts_conn *bts;
-	char buf[4096];
-	int ret;
-	struct sockaddr_in sock;
-	socklen_t len = sizeof(sock);
-
-	/* 1. get the data... */
-	ret = recvfrom(bfd->fd, buf, sizeof(buf), 0, (struct sockaddr *) &sock, &len);
-	if (ret < 0) {
-		LOGP(DLINP, LOGL_ERROR, "Failed to recv GPRS NS msg: %s.\n", strerror(errno));
-		return -1;
-	}
-
-	bts = bfd->data;
-
-	/* 2. figure out where to send it to */
-	if (memcmp(&sock.sin_addr, &ipp->gprs_addr, sizeof(sock.sin_addr)) == 0) {
-		LOGP(DLINP, LOGL_DEBUG, "GPRS NS msg from network.\n");
-		send_ns(bfd->fd, buf, ret, bts->bts_addr, 23000);
-	} else if (memcmp(&sock.sin_addr, &bts->bts_addr, sizeof(sock.sin_addr)) == 0) {
-		LOGP(DLINP, LOGL_DEBUG, "GPRS NS msg from BTS.\n");
-		send_ns(bfd->fd, buf, ret, ipp->gprs_addr, 23000);
-	} else {
-		LOGP(DLINP, LOGL_ERROR, "Unknown GPRS source: %s\n", inet_ntoa(sock.sin_addr));
-	}
-
-	return 0;
-}
-
-/* Actively connect to a BSC.  */
-static struct ipa_proxy_conn *connect_bsc(struct sockaddr_in *sa, int priv_nr, void *data)
-{
-	struct ipa_proxy_conn *ipc;
-	struct osmo_fd *bfd;
-	int ret, on = 1;
-
-	ipc = alloc_conn();
-	if (!ipc)
-		return NULL;
-
-	ipc->bts_conn = data;
-
-	bfd = &ipc->fd;
-	bfd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-	bfd->cb = ipaccess_fd_cb;
-	bfd->when = BSC_FD_READ | BSC_FD_WRITE;
-	bfd->data = ipc;
-	bfd->priv_nr = priv_nr;
-
-	if (bfd->fd < 0) {
-		LOGP(DLINP, LOGL_ERROR, "Could not create socket: %s\n",
-			strerror(errno));
-		talloc_free(ipc);
-		return NULL;
-	}
-
-	ret = setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-	if (ret < 0) {
-		LOGP(DLINP, LOGL_ERROR, "Could not set socket option\n");
-		close(bfd->fd);
-		talloc_free(ipc);
-		return NULL;
-	}
-
-	ret = connect(bfd->fd, (struct sockaddr *) sa, sizeof(*sa));
-	if (ret < 0) {
-		LOGP(DLINP, LOGL_ERROR, "Could not connect socket: %s\n",
-		     inet_ntoa(sa->sin_addr));
-		close(bfd->fd);
-		talloc_free(ipc);
-		return NULL;
-	}
-
-	/* pre-fill tx_queue with identity request */
-	ret = osmo_fd_register(bfd);
-	if (ret < 0) {
-		close(bfd->fd);
-		talloc_free(ipc);
-		return NULL;
-	}
-
-	return ipc;
-}
-
-static int ipaccess_proxy_setup(void)
-{
-	int ret;
-
-	ipp = talloc_zero(tall_bsc_ctx, struct ipa_proxy);
-	if (!ipp)
-		return -ENOMEM;
-	INIT_LLIST_HEAD(&ipp->bts_list);
-	osmo_timer_setup(&ipp->reconn_timer, reconn_tmr_cb, ipp);
-
-	/* Listen for OML connections */
-	ret = make_sock(&ipp->oml_listen_fd, IPPROTO_TCP, INADDR_ANY,
-			IPA_TCP_PORT_OML, OML_FROM_BTS, listen_fd_cb, NULL);
-	if (ret < 0)
-		return ret;
-
-	/* Listen for RSL connections */
-	ret = make_sock(&ipp->rsl_listen_fd, IPPROTO_TCP, INADDR_ANY,
-			IPA_TCP_PORT_RSL, RSL_FROM_BTS, listen_fd_cb, NULL);
-
-	if (ret < 0)
-		return ret;
-
-	/* Connect the GPRS NS Socket */
-	if (gprs_ns_ipaddr) {
-		inet_aton(gprs_ns_ipaddr, &ipp->gprs_addr);
-		inet_aton(listen_ipaddr, &ipp->listen_addr);
-	}
-
-	return ret;
-}
-
-static void signal_handler(int signal)
-{
-	fprintf(stdout, "signal %u received\n", signal);
-
-	switch (signal) {
-	case SIGABRT:
-		/* in case of abort, we want to obtain a talloc report
-		 * and then return to the caller, who will abort the process */
-	case SIGUSR1:
-		talloc_report_full(tall_bsc_ctx, stderr);
-		break;
-	default:
-		break;
-	}
-}
-
-static void print_help(void)
-{
-	printf(" ipaccess-proxy is a proxy BTS.\n");
-	printf(" -h --help. This help text.\n");
-	printf(" -l --listen IP. The ip to listen to.\n");
-	printf(" -b --bsc IP. The BSC IP address.\n");
-	printf(" -g --gprs IP. Take GPRS NS from that IP.\n");
-	printf("\n");
-	printf(" -s --disable-color. Disable the color inside the logging message.\n");
-	printf(" -e --log-level number. Set the global loglevel.\n");
-	printf(" -T --timestamp. Prefix every log message with a timestamp.\n");
-	printf(" -V --version. Print the version of OpenBSC.\n");
-}
-
-static void print_usage(void)
-{
-	printf("Usage: ipaccess-proxy [options]\n");
-}
-
-enum {
-	IPA_PROXY_OPT_LISTEN_NONE	= 0,
-	IPA_PROXY_OPT_LISTEN_IP		= (1 << 0),
-	IPA_PROXY_OPT_BSC_IP		= (1 << 1),
-};
-
-static void handle_options(int argc, char** argv)
-{
-	int options_mask = 0;
-
-	/* disable explicit missing arguments error output from getopt_long */
-	opterr = 0;
-
-	while (1) {
-		int option_index = 0, c;
-		static struct option long_options[] = {
-			{"help", 0, 0, 'h'},
-			{"disable-color", 0, 0, 's'},
-			{"timestamp", 0, 0, 'T'},
-			{"log-level", 1, 0, 'e'},
-			{"listen", 1, 0, 'l'},
-			{"bsc", 1, 0, 'b'},
-			{0, 0, 0, 0}
-		};
-
-		c = getopt_long(argc, argv, "hsTe:l:b:g:",
-				long_options, &option_index);
-		if (c == -1)
-			break;
-
-		switch (c) {
-		case 'h':
-			print_usage();
-			print_help();
-			exit(0);
-		case 'l':
-			listen_ipaddr = optarg;
-			options_mask |= IPA_PROXY_OPT_LISTEN_IP;
-			break;
-		case 'b':
-			bsc_ipaddr = optarg;
-			options_mask |= IPA_PROXY_OPT_BSC_IP;
-			break;
-		case 'g':
-			gprs_ns_ipaddr = optarg;
-			break;
-		case 's':
-			log_set_use_color(osmo_stderr_target, 0);
-			break;
-		case 'T':
-			log_set_print_timestamp(osmo_stderr_target, 1);
-			break;
-		case 'e':
-			log_set_log_level(osmo_stderr_target, atoi(optarg));
-			break;
-		case '?':
-			if (optopt) {
-				printf("ERROR: missing mandatory argument "
-				       "for `%s' option\n", argv[optind-1]);
-			} else {
-				printf("ERROR: unknown option `%s'\n",
-					argv[optind-1]);
-			}
-			print_usage();
-			print_help();
-			exit(EXIT_FAILURE);
-			break;
-		default:
-			/* ignore */
-			break;
-		}
-	}
-	if ((options_mask & (IPA_PROXY_OPT_LISTEN_IP | IPA_PROXY_OPT_BSC_IP))
-		 != (IPA_PROXY_OPT_LISTEN_IP | IPA_PROXY_OPT_BSC_IP)) {
-		printf("ERROR: You have to specify `--listen' and `--bsc' "
-		       "options at least.\n");
-		print_usage();
-		print_help();
-		exit(EXIT_FAILURE);
-	}
-}
-
-int main(int argc, char **argv)
-{
-	int rc;
-
-	tall_bsc_ctx = talloc_named_const(NULL, 1, "ipaccess-proxy");
-	msgb_talloc_ctx_init(tall_bsc_ctx, 0);
-
-	osmo_init_logging(&log_info);
-	log_parse_category_mask(osmo_stderr_target, "DLINP:DLMI");
-
-	handle_options(argc, argv);
-
-	rc = ipaccess_proxy_setup();
-	if (rc < 0)
-		exit(1);
-
-	signal(SIGUSR1, &signal_handler);
-	signal(SIGABRT, &signal_handler);
-	osmo_init_ignore_signals();
-
-	while (1) {
-		osmo_select_main(0);
-	}
-}
diff --git a/src/ipaccess/network_listen.c b/src/ipaccess/network_listen.c
deleted file mode 100644
index 3b44ceb..0000000
--- a/src/ipaccess/network_listen.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/* ip.access nanoBTS network listen mode */
-
-/* (C) 2009-2010 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/>.
- *
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <stdint.h>
-
-#include <arpa/inet.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/timer.h>
-#include <osmocom/gsm/rxlev_stat.h>
-#include <osmocom/gsm/gsm48_ie.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/signal.h>
-#include <openbsc/debug.h>
-#include <osmocom/abis/e1_input.h>
-
-#define WHITELIST_MAX_SIZE ((NUM_ARFCNS*2)+2+1)
-
-int ipac_rxlevstat2whitelist(uint16_t *buf, const struct rxlev_stats *st, uint8_t min_rxlev,
-			     uint16_t max_num_arfcns)
-{
-	int i;
-	unsigned int num_arfcn = 0;
-
-	for (i = NUM_RXLEVS-1; i >= min_rxlev; i--) {
-		int16_t arfcn = -1;
-
-		while ((arfcn = rxlev_stat_get_next(st, i, arfcn)) >= 0) {
-			*buf++ = htons(arfcn);
-			num_arfcn++;
-
-		}
-
-		if (num_arfcn > max_num_arfcns)
-			break;
-	}
-
-	return num_arfcn;
-}
-
-enum ipac_test_state {
-	IPAC_TEST_S_IDLE,
-	IPAC_TEST_S_RQD,
-	IPAC_TEST_S_EXEC,
-	IPAC_TEST_S_PARTIAL,
-};
-
-int ipac_nwl_test_start(struct gsm_bts_trx *trx, uint8_t testnr,
-			const uint8_t *phys_conf, unsigned int phys_conf_len)
-{
-	struct msgb *msg;
-
-	if (trx->ipaccess.test_state != IPAC_TEST_S_IDLE) {
-		fprintf(stderr, "Cannot start test in state %u\n", trx->ipaccess.test_state);
-		return -EINVAL;
-	}
-
-	switch (testnr) {
-	case NM_IPACC_TESTNO_CHAN_USAGE:
-	case NM_IPACC_TESTNO_BCCH_CHAN_USAGE:
-		rxlev_stat_reset(&trx->ipaccess.rxlev_stat);
-		break;
-	}
-
-	msg = msgb_alloc_headroom(phys_conf_len+256, 128, "OML");
-
-	if (phys_conf && phys_conf_len) {
-		uint8_t *payload;
-		/* first put the phys conf header */
-		msgb_tv16_put(msg, NM_ATT_PHYS_CONF, phys_conf_len);
-		payload = msgb_put(msg, phys_conf_len);
-		memcpy(payload, phys_conf, phys_conf_len);
-	}
-
-	abis_nm_perform_test(trx->bts, NM_OC_RADIO_CARRIER, 0, trx->nr, 0xff,
-			     testnr, 1, msg);
-	trx->ipaccess.test_nr = testnr;
-
-	/* FIXME: start safety timer until when test is supposed to complete */
-
-	return 0;
-}
-
-static uint16_t last_arfcn;
-static struct gsm_sysinfo_freq nwl_si_freq[1024];
-#define FREQ_TYPE_NCELL_2	0x04 /* sub channel of SI 2 */
-#define FREQ_TYPE_NCELL_2bis	0x08 /* sub channel of SI 2bis */
-#define FREQ_TYPE_NCELL_2ter	0x10 /* sub channel of SI 2ter */
-
-struct ipacc_ferr_elem {
-	int16_t freq_err;
-	uint8_t freq_qual;
-	uint8_t arfcn;
-} __attribute__((packed));
-
-struct ipacc_cusage_elem {
-	uint16_t arfcn:10,
-		  rxlev:6;
-} __attribute__ ((packed));
-
-static int test_rep(void *_msg)
-{
-	struct msgb *msg = _msg;
-	struct abis_om_fom_hdr *foh = msgb_l3(msg);
-	uint16_t test_rep_len, ferr_list_len;
-	struct ipacc_ferr_elem *ife;
-	struct ipac_bcch_info binfo;
-	struct e1inp_sign_link *sign_link = (struct e1inp_sign_link *)msg->dst;
-	int i, rc;
-
-	DEBUGP(DNM, "TEST REPORT: ");
-
-	if (foh->data[0] != NM_ATT_TEST_NO ||
-	    foh->data[2] != NM_ATT_TEST_REPORT)
-		return -EINVAL;
-
-	DEBUGPC(DNM, "test_no=0x%02x ", foh->data[1]);
-	/* data[2] == NM_ATT_TEST_REPORT */
-	/* data[3..4]: test_rep_len */
-	memcpy(&test_rep_len, &foh->data[3], sizeof(uint16_t));
-	test_rep_len = ntohs(test_rep_len);
-	/* data[5]: ip.access test result */
-	DEBUGPC(DNM, "tst_res=%s\n", ipacc_testres_name(foh->data[5]));
-
-	/* data[6]: ip.access nested IE. 3 == freq_err_list */
-	switch (foh->data[6]) {
-	case NM_IPAC_EIE_FREQ_ERR_LIST:
-		/* data[7..8]: length of ferr_list */
-		memcpy(&ferr_list_len, &foh->data[7], sizeof(uint16_t));
-		ferr_list_len = ntohs(ferr_list_len);
-
-		/* data[9...]: frequency error list elements */
-		for (i = 0; i < ferr_list_len; i+= sizeof(*ife)) {
-			ife = (struct ipacc_ferr_elem *) (foh->data + 9 + i);
-			DEBUGP(DNM, "==> ARFCN %4u, Frequency Error %6hd\n",
-			ife->arfcn, ntohs(ife->freq_err));
-		}
-		break;
-	case NM_IPAC_EIE_CHAN_USE_LIST:
-		/* data[7..8]: length of ferr_list */
-		memcpy(&ferr_list_len, &foh->data[7], sizeof(uint16_t));
-		ferr_list_len = ntohs(ferr_list_len);
-
-		/* data[9...]: channel usage list elements */
-		for (i = 0; i < ferr_list_len; i+= 2) {
-			uint16_t *cu_ptr = (uint16_t *)(foh->data + 9 + i);
-			uint16_t cu = ntohs(*cu_ptr);
-			uint16_t arfcn = cu & 0x3ff;
-			uint8_t rxlev = cu >> 10;
-			DEBUGP(DNM, "==> ARFCN %4u, RxLev %2u\n", arfcn, rxlev);
-			rxlev_stat_input(&sign_link->trx->ipaccess.rxlev_stat,
-					 arfcn, rxlev);
-		}
-		break;
-	case NM_IPAC_EIE_BCCH_INFO_TYPE:
-		break;
-	case NM_IPAC_EIE_BCCH_INFO:
-		rc = ipac_parse_bcch_info(&binfo, foh->data+6);
-		if (rc < 0) {
-			DEBUGP(DNM, "BCCH Info parsing failed\n");
-			break;
-		}
-		DEBUGP(DNM, "==> ARFCN %u, RxLev %2u, RxQual %2u: %3d-%d, LAC %d CI %d BSIC %u\n",
-			binfo.arfcn, binfo.rx_lev, binfo.rx_qual,
-			binfo.cgi.mcc, binfo.cgi.mnc,
-			binfo.cgi.lac, binfo.cgi.ci, binfo.bsic);
-
-		if (binfo.arfcn != last_arfcn) {
-			/* report is on a new arfcn, need to clear channel list */
-			memset(nwl_si_freq, 0, sizeof(nwl_si_freq));
-			last_arfcn = binfo.arfcn;
-		}
-		if (binfo.info_type & IPAC_BINF_NEIGH_BA_SI2) {
-			DEBUGP(DNM, "BA SI2: %s\n", osmo_hexdump(binfo.ba_list_si2, sizeof(binfo.ba_list_si2)));
-			gsm48_decode_freq_list(nwl_si_freq, binfo.ba_list_si2, sizeof(binfo.ba_list_si2),
-						0x8c, FREQ_TYPE_NCELL_2);
-		}
-		if (binfo.info_type & IPAC_BINF_NEIGH_BA_SI2bis) {
-			DEBUGP(DNM, "BA SI2bis: %s\n", osmo_hexdump(binfo.ba_list_si2bis, sizeof(binfo.ba_list_si2bis)));
-			gsm48_decode_freq_list(nwl_si_freq, binfo.ba_list_si2bis, sizeof(binfo.ba_list_si2bis),
-						0x8e, FREQ_TYPE_NCELL_2bis);
-		}
-		if (binfo.info_type & IPAC_BINF_NEIGH_BA_SI2ter) {
-			DEBUGP(DNM, "BA SI2ter: %s\n", osmo_hexdump(binfo.ba_list_si2ter, sizeof(binfo.ba_list_si2ter)));
-			gsm48_decode_freq_list(nwl_si_freq, binfo.ba_list_si2ter, sizeof(binfo.ba_list_si2ter),
-						0x8e, FREQ_TYPE_NCELL_2ter);
-		}
-		for (i = 0; i < ARRAY_SIZE(nwl_si_freq); i++) {
-			if (nwl_si_freq[i].mask)
-				DEBUGP(DNM, "Neighbor Cell on ARFCN %u\n", i);
-		}
-		break;
-	default:
-		break;
-	}
-
-	switch (foh->data[5]) {
-	case NM_IPACC_TESTRES_SUCCESS:
-	case NM_IPACC_TESTRES_STOPPED:
-	case NM_IPACC_TESTRES_TIMEOUT:
-	case NM_IPACC_TESTRES_NO_CHANS:
-		sign_link->trx->ipaccess.test_state = IPAC_TEST_S_IDLE;
-		/* Send signal to notify higher layers of test completion */
-		DEBUGP(DNM, "dispatching S_IPAC_NWL_COMPLETE signal\n");
-		osmo_signal_dispatch(SS_IPAC_NWL, S_IPAC_NWL_COMPLETE,
-					sign_link->trx);
-		break;
-	case NM_IPACC_TESTRES_PARTIAL:
-		sign_link->trx->ipaccess.test_state = IPAC_TEST_S_PARTIAL;
-		break;
-	}
-
-	return 0;
-}
-
-static int nwl_sig_cb(unsigned int subsys, unsigned int signal,
-		     void *handler_data, void *signal_data)
-{
-	switch (signal) {
-	case S_NM_TEST_REP:
-		return test_rep(signal_data);
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-void ipac_nwl_init(void)
-{
-	osmo_signal_register_handler(SS_NM, nwl_sig_cb, NULL);
-}
diff --git a/src/libbsc/Makefile.am b/src/libbsc/Makefile.am
deleted file mode 100644
index e78bde6..0000000
--- a/src/libbsc/Makefile.am
+++ /dev/null
@@ -1,57 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	-I$(top_builddir) \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOVTY_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(NULL)
-
-noinst_LIBRARIES = \
-	libbsc.a \
-	$(NULL)
-
-libbsc_a_SOURCES = \
-	abis_nm.c \
-	abis_nm_vty.c \
-	abis_om2000.c \
-	abis_om2000_vty.c \
-	abis_rsl.c \
-	bsc_rll.c \
-	bsc_subscriber.c \
-	paging.c \
-	bts_ericsson_rbs2000.c \
-	bts_ipaccess_nanobts.c \
-	bts_siemens_bs11.c \
-	bts_nokia_site.c \
-	bts_unknown.c \
-	bts_sysmobts.c \
-	chan_alloc.c \
-	handover_decision.c \
-	handover_logic.c \
-	meas_rep.c \
-	pcu_sock.c \
-	rest_octets.c \
-	system_information.c \
-	e1_config.c \
-	bsc_api.c \
-	bsc_msc.c bsc_vty.c \
-	gsm_04_08_utils.c \
-	gsm_04_80_utils.c \
-	bsc_init.c \
-	bts_init.c \
-	bsc_rf_ctrl.c \
-	arfcn_range_encode.c \
-	bsc_ctrl_commands.c \
-	bsc_ctrl_lookup.c \
-	net_init.c \
-	bsc_dyn_ts.c \
-	bts_ipaccess_nanobts_omlattr.c \
-	$(NULL)
-
diff --git a/src/libbsc/abis_nm.c b/src/libbsc/abis_nm.c
deleted file mode 100644
index cf20d7c..0000000
--- a/src/libbsc/abis_nm.c
+++ /dev/null
@@ -1,2924 +0,0 @@
-/* GSM Network Management (OML) 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/>.
- *
- */
-
-
-#include <errno.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <libgen.h>
-#include <time.h>
-#include <limits.h>
-
-#include <sys/stat.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/debug.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/gsm/protocol/gsm_12_21.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/gsm/abis_nm.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/misdn.h>
-#include <openbsc/signal.h>
-#include <osmocom/abis/e1_input.h>
-
-#define OM_ALLOC_SIZE		1024
-#define OM_HEADROOM_SIZE	128
-#define IPACC_SEGMENT_SIZE	245
-
-int abis_nm_tlv_parse(struct tlv_parsed *tp, struct gsm_bts *bts, const uint8_t *buf, int len)
-{
-	if (!bts->model)
-		return -EIO;
-	return tlv_parse(tp, &bts->model->nm_att_tlvdef, buf, len, 0, 0);
-}
-
-static int is_in_arr(enum abis_nm_msgtype mt, const enum abis_nm_msgtype *arr, int size)
-{
-	int i;
-
-	for (i = 0; i < size; i++) {
-		if (arr[i] == mt)
-			return 1;
-	}
-
-	return 0;
-}
-
-#if 0
-/* is this msgtype the usual ACK/NACK type ? */
-static int is_ack_nack(enum abis_nm_msgtype mt)
-{
-	return !is_in_arr(mt, no_ack_nack, ARRAY_SIZE(no_ack_nack));
-}
-#endif
-
-/* is this msgtype a report ? */
-static int is_report(enum abis_nm_msgtype mt)
-{
-	return is_in_arr(mt, abis_nm_reports, ARRAY_SIZE(abis_nm_reports));
-}
-
-#define MT_ACK(x)	(x+1)
-#define MT_NACK(x)	(x+2)
-
-static void fill_om_hdr(struct abis_om_hdr *oh, uint8_t len)
-{
-	oh->mdisc = ABIS_OM_MDISC_FOM;
-	oh->placement = ABIS_OM_PLACEMENT_ONLY;
-	oh->sequence = 0;
-	oh->length = len;
-}
-
-static struct abis_om_fom_hdr *fill_om_fom_hdr(struct abis_om_hdr *oh, uint8_t len,
-			    uint8_t msg_type, uint8_t obj_class,
-			    uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr)
-{
-	struct abis_om_fom_hdr *foh =
-			(struct abis_om_fom_hdr *) oh->data;
-
-	fill_om_hdr(oh, len+sizeof(*foh));
-	foh->msg_type = msg_type;
-	foh->obj_class = obj_class;
-	foh->obj_inst.bts_nr = bts_nr;
-	foh->obj_inst.trx_nr = trx_nr;
-	foh->obj_inst.ts_nr = ts_nr;
-	return foh;
-}
-
-static struct msgb *nm_msgb_alloc(void)
-{
-	return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE,
-				   "OML");
-}
-
-int _abis_nm_sendmsg(struct msgb *msg)
-{
-	msg->l2h = msg->data;
-
-	if (!msg->dst) {
-		LOGP(DNM, LOGL_ERROR, "%s: msg->dst == NULL\n", __func__);
-		return -EINVAL;
-	}
-
-	return abis_sendmsg(msg);
-}
-
-/* Send a OML NM Message from BSC to BTS */
-static int abis_nm_queue_msg(struct gsm_bts *bts, struct msgb *msg)
-{
-	msg->dst = bts->oml_link;
-
-	/* queue OML messages */
-	if (llist_empty(&bts->abis_queue) && !bts->abis_nm_pend) {
-		bts->abis_nm_pend = OBSC_NM_W_ACK_CB(msg);
-		return _abis_nm_sendmsg(msg);
-	} else {
-		msgb_enqueue(&bts->abis_queue, msg);
-		return 0;
-	}
-
-}
-
-int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg)
-{
-	OBSC_NM_W_ACK_CB(msg) = 1;
-	return abis_nm_queue_msg(bts, msg);
-}
-
-static int abis_nm_sendmsg_direct(struct gsm_bts *bts, struct msgb *msg)
-{
-	OBSC_NM_W_ACK_CB(msg) = 0;
-	return abis_nm_queue_msg(bts, msg);
-}
-
-static int abis_nm_rcvmsg_sw(struct msgb *mb);
-
-int nm_is_running(struct gsm_nm_state *s) {
-	return (s->operational == NM_OPSTATE_ENABLED) && (
-		(s->availability == NM_AVSTATE_OK) ||
-		(s->availability == 0xff)
-	);
-}
-
-/* Update the administrative state of a given object in our in-memory data
- * structures and send an event to the higher layer */
-static int update_admstate(struct gsm_bts *bts, uint8_t obj_class,
-			   struct abis_om_obj_inst *obj_inst, uint8_t adm_state)
-{
-	struct gsm_nm_state *nm_state, new_state;
-	struct nm_statechg_signal_data nsd;
-
-	memset(&nsd, 0, sizeof(nsd));
-
-	nsd.obj = gsm_objclass2obj(bts, obj_class, obj_inst);
-	if (!nsd.obj)
-		return -EINVAL;
-	nm_state = gsm_objclass2nmstate(bts, obj_class, obj_inst);
-	if (!nm_state)
-		return -1;
-
-	new_state = *nm_state;
-	new_state.administrative = adm_state;
-
-	nsd.bts = bts;
-	nsd.obj_class = obj_class;
-	nsd.old_state = nm_state;
-	nsd.new_state = &new_state;
-	nsd.obj_inst = obj_inst;
-	osmo_signal_dispatch(SS_NM, S_NM_STATECHG_ADM, &nsd);
-
-	nm_state->administrative = adm_state;
-
-	return 0;
-}
-
-static int abis_nm_rx_statechg_rep(struct msgb *mb)
-{
-	struct abis_om_hdr *oh = msgb_l2(mb);
-	struct abis_om_fom_hdr *foh = msgb_l3(mb);
-	struct e1inp_sign_link *sign_link = mb->dst;
-	struct gsm_bts *bts = sign_link->trx->bts;
-	struct tlv_parsed tp;
-	struct gsm_nm_state *nm_state, new_state;
-
-	DEBUGPC(DNM, "STATE CHG: ");
-
-	memset(&new_state, 0, sizeof(new_state));
-
-	nm_state = gsm_objclass2nmstate(bts, foh->obj_class, &foh->obj_inst);
-	if (!nm_state) {
-		DEBUGPC(DNM, "unknown object class\n");
-		return -EINVAL;
-	}
-
-	new_state = *nm_state;
-	
-	abis_nm_tlv_parse(&tp, bts, foh->data, oh->length-sizeof(*foh));
-	if (TLVP_PRESENT(&tp, NM_ATT_OPER_STATE)) {
-		new_state.operational = *TLVP_VAL(&tp, NM_ATT_OPER_STATE);
-		DEBUGPC(DNM, "OP_STATE=%s ",
-			abis_nm_opstate_name(new_state.operational));
-	}
-	if (TLVP_PRESENT(&tp, NM_ATT_AVAIL_STATUS)) {
-		if (TLVP_LEN(&tp, NM_ATT_AVAIL_STATUS) == 0)
-			new_state.availability = 0xff;
-		else
-			new_state.availability = *TLVP_VAL(&tp, NM_ATT_AVAIL_STATUS);
-		DEBUGPC(DNM, "AVAIL=%s(%02x) ",
-			abis_nm_avail_name(new_state.availability),
-			new_state.availability);
-	} else
-		new_state.availability = 0xff;
-	if (TLVP_PRESENT(&tp, NM_ATT_ADM_STATE)) {
-		new_state.administrative = *TLVP_VAL(&tp, NM_ATT_ADM_STATE);
-		DEBUGPC(DNM, "ADM=%2s ",
-			get_value_string(abis_nm_adm_state_names,
-					 new_state.administrative));
-	}
-	DEBUGPC(DNM, "\n");
-
-	if ((new_state.administrative != 0 && nm_state->administrative == 0) ||
-	    new_state.operational != nm_state->operational ||
-	    new_state.availability != nm_state->availability) {
-		/* Update the operational state of a given object in our in-memory data
- 		* structures and send an event to the higher layer */
-		struct nm_statechg_signal_data nsd;
-		nsd.obj = gsm_objclass2obj(bts, foh->obj_class, &foh->obj_inst);
-		nsd.obj_class = foh->obj_class;
-		nsd.old_state = nm_state;
-		nsd.new_state = &new_state;
-		nsd.obj_inst = &foh->obj_inst;
-		nsd.bts = bts;
-		osmo_signal_dispatch(SS_NM, S_NM_STATECHG_OPER, &nsd);
-		nm_state->operational = new_state.operational;
-		nm_state->availability = new_state.availability;
-		if (nm_state->administrative == 0)
-			nm_state->administrative = new_state.administrative;
-	}
-#if 0
-	if (op_state == 1) {
-		/* try to enable objects that are disabled */
-		abis_nm_opstart(bts, foh->obj_class,
-				foh->obj_inst.bts_nr,
-				foh->obj_inst.trx_nr,
-				foh->obj_inst.ts_nr);
-	}
-#endif
-	return 0;
-}
-
-static inline void log_oml_fail_rep(const struct gsm_bts *bts, const char *type,
-				    const char *severity, const uint8_t *p_val,
-				    const char *text)
-{
-	enum abis_nm_pcause_type pcause = p_val[0];
-	enum abis_mm_event_causes cause = osmo_load16be(p_val + 1);
-
-	LOGPC(DNM, LOGL_ERROR, "BTS %u: Failure Event Report: ", bts->nr);
-	if (type)
-		LOGPC(DNM, LOGL_ERROR, "Type=%s, ", type);
-	if (severity)
-		LOGPC(DNM, LOGL_ERROR, "Severity=%s, ", severity);
-
-	LOGPC(DNM, LOGL_ERROR, "Probable cause=%s: ",
-	      get_value_string(abis_nm_pcause_type_names, pcause));
-
-	if (pcause == NM_PCAUSE_T_MANUF)
-		LOGPC(DNM, LOGL_ERROR, "%s, ",
-		      get_value_string(abis_mm_event_cause_names, cause));
-	else
-		LOGPC(DNM, LOGL_ERROR, "%02X %02X ", p_val[1], p_val[2]);
-
-	if (text) {
-		LOGPC(DNM, LOGL_ERROR, "Additional Text=%s. ", text);
-	}
-
-	LOGPC(DNM, LOGL_ERROR, "\n");
-}
-
-static inline void handle_manufact_report(struct gsm_bts *bts, const uint8_t *p_val, const char *type,
-					  const char *severity, const char *text)
-{
-	enum abis_mm_event_causes cause = osmo_load16be(p_val + 1);
-
-	switch (cause) {
-	case OSMO_EVT_PCU_VERS:
-		if (text) {
-			LOGPC(DNM, LOGL_NOTICE, "BTS %u reported connected PCU version %s\n", bts->nr, text);
-			osmo_strlcpy(bts->pcu_version, text, sizeof(bts->pcu_version));
-		} else {
-			LOGPC(DNM, LOGL_ERROR, "BTS %u reported PCU disconnection.\n", bts->nr);
-			bts->pcu_version[0] = '\0';
-		}
-		break;
-	default:
-		log_oml_fail_rep(bts, type, severity, p_val, text);
-	};
-}
-
-static int rx_fail_evt_rep(struct msgb *mb, struct gsm_bts *bts)
-{
-	struct abis_om_hdr *oh = msgb_l2(mb);
-	struct abis_om_fom_hdr *foh = msgb_l3(mb);
-	struct e1inp_sign_link *sign_link = mb->dst;
-	struct tlv_parsed tp;
-	int rc = 0;
-	const uint8_t *p_val = NULL;
-	char *p_text = NULL;
-	const char *e_type = NULL, *severity = NULL;
-
-	abis_nm_tlv_parse(&tp, sign_link->trx->bts, foh->data,
-			  oh->length-sizeof(*foh));
-
-	if (TLVP_PRESENT(&tp, NM_ATT_ADD_TEXT)) {
-		p_val = TLVP_VAL(&tp, NM_ATT_ADD_TEXT);
-		p_text = talloc_strndup(tall_bsc_ctx, (const char *) p_val,
-					TLVP_LEN(&tp, NM_ATT_ADD_TEXT));
-	}
-
-	if (TLVP_PRESENT(&tp, NM_ATT_EVENT_TYPE))
-		e_type = abis_nm_event_type_name(*TLVP_VAL(&tp,
-							   NM_ATT_EVENT_TYPE));
-
-	if (TLVP_PRESENT(&tp, NM_ATT_SEVERITY))
-		severity = abis_nm_severity_name(*TLVP_VAL(&tp,
-							   NM_ATT_SEVERITY));
-
-	if (TLVP_PRESENT(&tp, NM_ATT_PROB_CAUSE)) {
-		p_val = TLVP_VAL(&tp, NM_ATT_PROB_CAUSE);
-
-		switch (p_val[0]) {
-		case NM_PCAUSE_T_MANUF:
-			handle_manufact_report(bts, p_val, e_type, severity,
-					       p_text);
-			break;
-		default:
-			log_oml_fail_rep(bts, e_type, severity, p_val, p_text);
-		};
-	} else {
-		LOGPC(DNM, LOGL_ERROR, "BTS%u: Failure Event Report without "
-		      "Probable Cause?!\n", bts->nr);
-		rc = -EINVAL;
-	}
-
-	if (p_text)
-		talloc_free(p_text);
-
-	return rc;
-}
-
-static int abis_nm_rcvmsg_report(struct msgb *mb, struct gsm_bts *bts)
-{
-	struct abis_om_fom_hdr *foh = msgb_l3(mb);
-	uint8_t mt = foh->msg_type;
-
-	abis_nm_debugp_foh(DNM, foh);
-
-	//nmh->cfg->report_cb(mb, foh);
-
-	switch (mt) {
-	case NM_MT_STATECHG_EVENT_REP:
-		return abis_nm_rx_statechg_rep(mb);
-		break;
-	case NM_MT_SW_ACTIVATED_REP:
-		DEBUGPC(DNM, "Software Activated Report\n");
-		osmo_signal_dispatch(SS_NM, S_NM_SW_ACTIV_REP, mb);
-		break;
-	case NM_MT_FAILURE_EVENT_REP:
-		rx_fail_evt_rep(mb, bts);
-		osmo_signal_dispatch(SS_NM, S_NM_FAIL_REP, mb);
-		break;
-	case NM_MT_TEST_REP:
-		DEBUGPC(DNM, "Test Report\n");
-		osmo_signal_dispatch(SS_NM, S_NM_TEST_REP, mb);
-		break;
-	default:
-		DEBUGPC(DNM, "reporting NM MT 0x%02x\n", mt);
-		break;
-		
-	};
-
-	return 0;
-}
-
-/* Activate the specified software into the BTS */
-static int ipacc_sw_activate(struct gsm_bts *bts, uint8_t obj_class, uint8_t i0, uint8_t i1,
-			     uint8_t i2, const struct abis_nm_sw_desc *sw_desc)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	uint16_t len = abis_nm_sw_desc_len(sw_desc, true);
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, len, NM_MT_ACTIVATE_SW, obj_class, i0, i1, i2);
-	abis_nm_put_sw_desc(msg, sw_desc, true);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-int abis_nm_select_newest_sw(const struct abis_nm_sw_desc *sw_descr,
-			     const size_t size)
-{
-	int res = 0;
-	int i;
-
-	for (i = 1; i < size; ++i) {
-		if (memcmp(sw_descr[res].file_version, sw_descr[i].file_version,
-			   OSMO_MIN(sw_descr[i].file_version_len,
-				    sw_descr[res].file_version_len)) < 0) {
-			res = i;
-		}
-	}
-
-	return res;
-}
-
-static inline bool handle_attr(const struct gsm_bts *bts, enum bts_attribute id, uint8_t *val, uint8_t len)
-{
-	switch (id) {
-	case BTS_TYPE_VARIANT:
-		LOGP(DNM, LOGL_NOTICE, "BTS%u reported variant: %s\n", bts->nr, val);
-		break;
-	case BTS_SUB_MODEL:
-		LOGP(DNM, LOGL_NOTICE, "BTS%u reported submodel: %s\n", bts->nr, val);
-		break;
-	default:
-		return false;
-	}
-	return true;
-}
-
-/* Parse Attribute Response Info - return pointer to the actual content */
-static inline uint8_t *parse_attr_resp_info_unreported(uint8_t bts_nr, uint8_t *ari, uint16_t ari_len, uint16_t *out_len)
-{
-	uint8_t num_unreported = ari[0], i;
-
-	DEBUGP(DNM, "BTS%u Get Attributes Response Info: %u bytes total with %u unreported attributes\n",
-	       bts_nr, ari_len, num_unreported);
-
-	/* +1 because we have to account for number of unreported attributes, prefixing the list: */
-	for (i = 0; i < num_unreported; i++)
-		LOGP(DNM, LOGL_ERROR, "BTS%u Attribute %s is unreported\n",
-		     bts_nr, get_value_string(abis_nm_att_names, ari[i + 1]));
-
-	/* the data starts right after the list of unreported attributes + space for length of that list */
-	*out_len = ari_len - (num_unreported + 2);
-
-	return ari + num_unreported + 1; /* we have to account for 1st byte with number of unreported attributes */
-}
-
-/* Parse Attribute Response Info content for 3GPP TS 52.021 §9.4.30 Manufacturer Id */
-static inline uint8_t *parse_attr_resp_info_manuf_id(struct gsm_bts *bts, uint8_t *data, uint16_t *data_len)
-{
-	struct tlv_parsed tp;
-	uint16_t m_id_len = 0;
-	uint8_t adjust = 0, i;
-
-	abis_nm_tlv_parse(&tp, bts, data, *data_len);
-	if (TLVP_PRES_LEN(&tp, NM_ATT_MANUF_ID, 2)) {
-		m_id_len = TLVP_LEN(&tp, NM_ATT_MANUF_ID);
-
-		/* log potential BTS feature vector overflow */
-		if (m_id_len > sizeof(bts->_features_data))
-			LOGP(DNM, LOGL_NOTICE, "BTS%u Get Attributes Response: feature vector is truncated to %u bytes\n",
-			     bts->nr, MAX_BTS_FEATURES/8);
-
-		/* check that max. expected BTS attribute is above given feature vector length */
-		if (m_id_len > OSMO_BYTES_FOR_BITS(_NUM_BTS_FEAT))
-			LOGP(DNM, LOGL_NOTICE, "BTS%u Get Attributes Response: reported unexpectedly long (%u bytes) "
-			     "feature vector - most likely it was compiled against newer BSC headers. "
-			     "Consider upgrading your BSC to later version.\n",
-			     bts->nr, m_id_len);
-
-		memcpy(bts->_features_data, TLVP_VAL(&tp, NM_ATT_MANUF_ID), sizeof(bts->_features_data));
-		adjust = m_id_len + 3; /* adjust for parsed TL16V struct */
-
-		for (i = 0; i < _NUM_BTS_FEAT; i++)
-			if (gsm_bts_has_feature(bts, i) != gsm_btsmodel_has_feature(bts->model, i))
-				LOGP(DNM, LOGL_NOTICE, "BTS%u feature '%s' reported via OML does not match statically "
-				     "set feature: %u != %u. Please fix.\n", bts->nr,
-				     get_value_string(gsm_bts_features_descs, i),
-				     gsm_bts_has_feature(bts, i), gsm_btsmodel_has_feature(bts->model, i));
-	}
-
-	*data_len -= adjust;
-
-	return data + adjust;
-}
-
-/* Parse Attribute Response Info content for 3GPP TS 52.021 §9.4.28 Manufacturer Dependent State */
-static inline uint8_t *parse_attr_resp_info_manuf_state(const struct gsm_bts_trx *trx, uint8_t *data, uint16_t *data_len)
-{
-	struct tlv_parsed tp;
-	const uint8_t *power;
-	uint8_t adjust = 0;
-
-	if (!trx) /* this attribute does not make sense on BTS level, only on TRX level */
-		return data;
-
-	abis_nm_tlv_parse(&tp, trx->bts, data, *data_len);
-	if (TLVP_PRES_LEN(&tp, NM_ATT_MANUF_STATE, 1)) {
-		power = TLVP_VAL(&tp, NM_ATT_MANUF_STATE);
-		LOGP(DNM, LOGL_NOTICE, "%s Get Attributes Response: nominal power is %u\n", gsm_trx_name(trx), *power);
-		adjust = 2; /* adjust for parsed TV struct */
-	}
-
-	*data_len -= adjust;
-
-	return data + adjust;
-}
-
-/* Handle 3GPP TS 52.021 §9.4.64 Get Attribute Response Info */
-static int abis_nm_rx_get_attr_resp(struct msgb *mb, const struct gsm_bts_trx *trx)
-{
-	struct abis_om_hdr *oh = msgb_l2(mb);
-	struct abis_om_fom_hdr *foh = msgb_l3(mb);
-	struct e1inp_sign_link *sign_link = mb->dst;
-	struct gsm_bts *bts = trx ? trx->bts : sign_link->trx->bts;
-	struct tlv_parsed tp;
-	uint8_t *data, i;
-	uint16_t data_len;
-	int rc;
-	struct abis_nm_sw_desc sw_descr[MAX_BTS_ATTR];
-
-	abis_nm_debugp_foh(DNM, foh);
-
-	DEBUGPC(DNM, "Get Attributes Response for BTS%u\n", bts->nr);
-
-	abis_nm_tlv_parse(&tp, bts, foh->data, oh->length-sizeof(*foh));
-	if (!TLVP_PRES_LEN(&tp, NM_ATT_GET_ARI, 1)) {
-		LOGP(DNM, LOGL_ERROR, "BTS%u: Get Attributes Response without Response Info?!\n", bts->nr);
-		return -EINVAL;
-	}
-
-	data = parse_attr_resp_info_unreported(bts->nr, TLVP_VAL(&tp, NM_ATT_GET_ARI), TLVP_LEN(&tp, NM_ATT_GET_ARI),
-					       &data_len);
-
-	data = parse_attr_resp_info_manuf_state(trx, data, &data_len);
-	data = parse_attr_resp_info_manuf_id(bts, data, &data_len);
-
-	/* after parsing manufacturer-specific attributes there's list of replies in form of sw-conf structure: */
-	rc = abis_nm_get_sw_conf(data, data_len, &sw_descr[0], ARRAY_SIZE(sw_descr));
-	if (rc > 0) {
-		for (i = 0; i < rc; i++) {
-			if (!handle_attr(bts, str2btsattr((const char *)sw_descr[i].file_id),
-					 sw_descr[i].file_version, sw_descr[i].file_version_len))
-				LOGP(DNM, LOGL_NOTICE, "BTS%u: ARI reported sw[%d/%d]: %s is %s\n",
-				     bts->nr, i, rc, sw_descr[i].file_id, sw_descr[i].file_version);
-		}
-	} else
-		LOGP(DNM, LOGL_ERROR, "BTS%u: failed to parse SW-Config part of Get Attribute Response Info: %s\n",
-		     bts->nr, strerror(-rc));
-
-	return 0;
-}
-
-/* 3GPP TS 52.021 §6.2.5 */
-static int abis_nm_rx_sw_act_req(struct msgb *mb)
-{
-	struct abis_om_hdr *oh = msgb_l2(mb);
-	struct abis_om_fom_hdr *foh = msgb_l3(mb);
-	struct e1inp_sign_link *sign_link = mb->dst;
-	struct tlv_parsed tp;
-	const uint8_t *sw_config;
-	int ret, sw_config_len, len;
-	struct abis_nm_sw_desc sw_descr[MAX_BTS_ATTR];
-
-	abis_nm_debugp_foh(DNM, foh);
-
-	DEBUGPC(DNM, "SW Activate Request: ");
-
-	DEBUGP(DNM, "Software Activate Request, ACKing and Activating\n");
-
-	ret = abis_nm_sw_act_req_ack(sign_link->trx->bts, foh->obj_class,
-				      foh->obj_inst.bts_nr,
-				      foh->obj_inst.trx_nr,
-				      foh->obj_inst.ts_nr, 0,
-				      foh->data, oh->length-sizeof(*foh));
-	if (ret != 0) {
-		LOGP(DNM, LOGL_ERROR,
-			"Sending SW ActReq ACK failed: %d\n", ret);
-		return ret;
-	}
-
-	abis_nm_tlv_parse(&tp, sign_link->trx->bts, foh->data, oh->length-sizeof(*foh));
-	sw_config = TLVP_VAL(&tp, NM_ATT_SW_CONFIG);
-	sw_config_len = TLVP_LEN(&tp, NM_ATT_SW_CONFIG);
-	if (!TLVP_PRESENT(&tp, NM_ATT_SW_CONFIG)) {
-		LOGP(DNM, LOGL_ERROR,
-			"SW config not found! Can't continue.\n");
-		return -EINVAL;
-	} else {
-		DEBUGP(DNM, "Found SW config: %s\n", osmo_hexdump(sw_config, sw_config_len));
-	}
-
-	/* Parse up to two sw descriptions from the data */
-	len = abis_nm_get_sw_conf(sw_config, sw_config_len, &sw_descr[0],
-				  ARRAY_SIZE(sw_descr));
-	if (len <= 0) {
-		LOGP(DNM, LOGL_ERROR, "Failed to parse SW Config.\n");
-		return -EINVAL;
-	}
-
-	ret = abis_nm_select_newest_sw(&sw_descr[0], len);
-	DEBUGP(DNM, "Selected sw description %d of %d\n", ret, len);
-
-	return ipacc_sw_activate(sign_link->trx->bts, foh->obj_class,
-				 foh->obj_inst.bts_nr,
-				 foh->obj_inst.trx_nr,
-				 foh->obj_inst.ts_nr,
-				 &sw_descr[ret]);
-}
-
-/* Receive a CHANGE_ADM_STATE_ACK, parse the TLV and update local state */
-static int abis_nm_rx_chg_adm_state_ack(struct msgb *mb)
-{
-	struct abis_om_hdr *oh = msgb_l2(mb);
-	struct abis_om_fom_hdr *foh = msgb_l3(mb);
-	struct e1inp_sign_link *sign_link = mb->dst;
-	struct tlv_parsed tp;
-	uint8_t adm_state;
-
-	abis_nm_tlv_parse(&tp, sign_link->trx->bts, foh->data, oh->length-sizeof(*foh));
-	if (!TLVP_PRESENT(&tp, NM_ATT_ADM_STATE))
-		return -EINVAL;
-
-	adm_state = *TLVP_VAL(&tp, NM_ATT_ADM_STATE);
-
-	return update_admstate(sign_link->trx->bts, foh->obj_class, &foh->obj_inst, adm_state);
-}
-
-static int abis_nm_rx_lmt_event(struct msgb *mb)
-{
-	struct abis_om_hdr *oh = msgb_l2(mb);
-	struct abis_om_fom_hdr *foh = msgb_l3(mb);
-	struct e1inp_sign_link *sign_link = mb->dst;
-	struct tlv_parsed tp;
-
-	DEBUGP(DNM, "LMT Event ");
-	abis_nm_tlv_parse(&tp, sign_link->trx->bts, foh->data, oh->length-sizeof(*foh));
-	if (TLVP_PRESENT(&tp, NM_ATT_BS11_LMT_LOGON_SESSION) &&
-	    TLVP_LEN(&tp, NM_ATT_BS11_LMT_LOGON_SESSION) >= 1) {
-		uint8_t onoff = *TLVP_VAL(&tp, NM_ATT_BS11_LMT_LOGON_SESSION);
-		DEBUGPC(DNM, "LOG%s ", onoff ? "ON" : "OFF");
-	}
-	if (TLVP_PRESENT(&tp, NM_ATT_BS11_LMT_USER_ACC_LEV) &&
-	    TLVP_LEN(&tp, NM_ATT_BS11_LMT_USER_ACC_LEV) >= 1) {
-		uint8_t level = *TLVP_VAL(&tp, NM_ATT_BS11_LMT_USER_ACC_LEV);
-		DEBUGPC(DNM, "Level=%u ", level);
-	}
-	if (TLVP_PRESENT(&tp, NM_ATT_BS11_LMT_USER_NAME) &&
-	    TLVP_LEN(&tp, NM_ATT_BS11_LMT_USER_NAME) >= 1) {
-		char *name = (char *) TLVP_VAL(&tp, NM_ATT_BS11_LMT_USER_NAME);
-		DEBUGPC(DNM, "Username=%s ", name);
-	}
-	DEBUGPC(DNM, "\n");
-	/* FIXME: parse LMT LOGON TIME */
-	return 0;
-}
-
-void abis_nm_queue_send_next(struct gsm_bts *bts)
-{
-	int wait = 0;
-	struct msgb *msg;
-	/* the queue is empty */
-	while (!llist_empty(&bts->abis_queue)) {
-		msg = msgb_dequeue(&bts->abis_queue);
-		wait = OBSC_NM_W_ACK_CB(msg);
-		_abis_nm_sendmsg(msg);
-
-		if (wait)
-			break;
-	}
-
-	bts->abis_nm_pend = wait;
-}
-
-/* Receive a OML NM Message from BTS */
-static int abis_nm_rcvmsg_fom(struct msgb *mb)
-{
-	struct abis_om_hdr *oh = msgb_l2(mb);
-	struct abis_om_fom_hdr *foh = msgb_l3(mb);
-	struct e1inp_sign_link *sign_link = mb->dst;
-	uint8_t mt = foh->msg_type;
-	/* sign_link might get deleted via osmo_signal_dispatch -> save bts */
-	struct gsm_bts *bts = sign_link->trx->bts;
-	int ret = 0;
-
-	/* check for unsolicited message */
-	if (is_report(mt))
-		return abis_nm_rcvmsg_report(mb, bts);
-
-	if (is_in_arr(mt, abis_nm_sw_load_msgs, ARRAY_SIZE(abis_nm_sw_load_msgs)))
-		return abis_nm_rcvmsg_sw(mb);
-
-	if (is_in_arr(mt, abis_nm_nacks, ARRAY_SIZE(abis_nm_nacks))) {
-		struct nm_nack_signal_data nack_data;
-		struct tlv_parsed tp;
-
-		abis_nm_debugp_foh(DNM, foh);
-
-		DEBUGPC(DNM, "%s NACK ", abis_nm_nack_name(mt));
-
-		abis_nm_tlv_parse(&tp, bts, foh->data, oh->length-sizeof(*foh));
-		if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
-			DEBUGPC(DNM, "CAUSE=%s\n",
-				abis_nm_nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
-		else
-			DEBUGPC(DNM, "\n");
-
-		nack_data.msg = mb;
-		nack_data.mt = mt;
-		nack_data.bts = bts;
-		osmo_signal_dispatch(SS_NM, S_NM_NACK, &nack_data);
-		abis_nm_queue_send_next(bts);
-		return 0;
-	}
-#if 0
-	/* check if last message is to be acked */
-	if (is_ack_nack(nmh->last_msgtype)) {
-		if (mt == MT_ACK(nmh->last_msgtype)) {
-			DEBUGP(DNM, "received ACK (0x%x)\n", foh->msg_type);
-			/* we got our ACK, continue sending the next msg */
-		} else if (mt == MT_NACK(nmh->last_msgtype)) {
-			/* we got a NACK, signal this to the caller */
-			DEBUGP(DNM, "received NACK (0x%x)\n", foh->msg_type);
-			/* FIXME: somehow signal this to the caller */
-		} else {
-			/* really strange things happen */
-			return -EINVAL;
-		}
-	}
-#endif
-
-	switch (mt) {
-	case NM_MT_CHG_ADM_STATE_ACK:
-		ret = abis_nm_rx_chg_adm_state_ack(mb);
-		break;
-	case NM_MT_SW_ACT_REQ:
-		ret = abis_nm_rx_sw_act_req(mb);
-		break;
-	case NM_MT_BS11_LMT_SESSION:
-		ret = abis_nm_rx_lmt_event(mb);
-		break;
-	case NM_MT_OPSTART_ACK:
-		abis_nm_debugp_foh(DNM, foh);
-		DEBUGPC(DNM, "Opstart ACK\n");
-		break;
-	case NM_MT_SET_CHAN_ATTR_ACK:
-		abis_nm_debugp_foh(DNM, foh);
-		DEBUGPC(DNM, "Set Channel Attributes ACK\n");
-		break;
-	case NM_MT_SET_RADIO_ATTR_ACK:
-		abis_nm_debugp_foh(DNM, foh);
-		DEBUGPC(DNM, "Set Radio Carrier Attributes ACK\n");
-		break;
-	case NM_MT_CONN_MDROP_LINK_ACK:
-		abis_nm_debugp_foh(DNM, foh);
-		DEBUGPC(DNM, "CONN MDROP LINK ACK\n");
-		break;
-	case NM_MT_IPACC_RESTART_ACK:
-		osmo_signal_dispatch(SS_NM, S_NM_IPACC_RESTART_ACK, NULL);
-		break;
-	case NM_MT_IPACC_RESTART_NACK:
-		osmo_signal_dispatch(SS_NM, S_NM_IPACC_RESTART_NACK, NULL);
-		break;
-	case NM_MT_SET_BTS_ATTR_ACK:
-		break;
-	case NM_MT_GET_ATTR_RESP:
-		ret = abis_nm_rx_get_attr_resp(mb, gsm_bts_trx_num(bts, (foh)->obj_inst.trx_nr));
-		break;
-	default:
-		abis_nm_debugp_foh(DNM, foh);
-		LOGPC(DNM, LOGL_ERROR, "Unhandled message %s\n",
-		      get_value_string(abis_nm_msgtype_names, mt));
-	}
-
-	abis_nm_queue_send_next(bts);
-	return ret;
-}
-
-static int abis_nm_rx_ipacc(struct msgb *mb);
-
-static int abis_nm_rcvmsg_manuf(struct msgb *mb)
-{
-	int rc;
-	struct e1inp_sign_link *sign_link = mb->dst;
-	int bts_type = sign_link->trx->bts->type;
-
-	switch (bts_type) {
-	case GSM_BTS_TYPE_NANOBTS:
-	case GSM_BTS_TYPE_OSMOBTS:
-		rc = abis_nm_rx_ipacc(mb);
-		abis_nm_queue_send_next(sign_link->trx->bts);
-		break;
-	default:
-		LOGP(DNM, LOGL_ERROR, "don't know how to parse OML for this "
-		     "BTS type (%u)\n", bts_type);
-		rc = 0;
-		break;
-	}
-
-	return rc;
-}
-
-/* High-Level API */
-/* Entry-point where L2 OML from BTS enters the NM code */
-int abis_nm_rcvmsg(struct msgb *msg)
-{
-	struct abis_om_hdr *oh = msgb_l2(msg);
-	int rc = 0;
-
-	/* Various consistency checks */
-	if (oh->placement != ABIS_OM_PLACEMENT_ONLY) {
-		LOGP(DNM, LOGL_ERROR, "ABIS OML placement 0x%x not supported\n",
-			oh->placement);
-		if (oh->placement != ABIS_OM_PLACEMENT_FIRST) {
-			rc = -EINVAL;
-			goto err;
-		}
-	}
-	if (oh->sequence != 0) {
-		LOGP(DNM, LOGL_ERROR, "ABIS OML sequence 0x%x != 0x00\n",
-			oh->sequence);
-		rc = -EINVAL;
-		goto err;
-	}
-#if 0
-	unsigned int l2_len = msg->tail - (uint8_t *)msgb_l2(msg);
-	unsigned int hlen = sizeof(*oh) + sizeof(struct abis_om_fom_hdr);
-	if (oh->length + hlen > l2_len) {
-		LOGP(DNM, LOGL_ERROR, "ABIS OML truncated message (%u > %u)\n",
-			oh->length + sizeof(*oh), l2_len);
-		return -EINVAL;
-	}
-	if (oh->length + hlen < l2_len)
-		LOGP(DNM, LOGL_ERROR, "ABIS OML message with extra trailer?!? (oh->len=%d, sizeof_oh=%d l2_len=%d\n", oh->length, sizeof(*oh), l2_len);
-#endif
-	msg->l3h = (unsigned char *)oh + sizeof(*oh);
-
-	switch (oh->mdisc) {
-	case ABIS_OM_MDISC_FOM:
-		rc = abis_nm_rcvmsg_fom(msg);
-		break;
-	case ABIS_OM_MDISC_MANUF:
-		rc = abis_nm_rcvmsg_manuf(msg);
-		break;
-	case ABIS_OM_MDISC_MMI:
-	case ABIS_OM_MDISC_TRAU:
-		LOGP(DNM, LOGL_ERROR, "unimplemented ABIS OML message discriminator 0x%x\n",
-			oh->mdisc);
-		break;
-	default:
-		LOGP(DNM, LOGL_ERROR, "unknown ABIS OML message discriminator 0x%x\n",
-			oh->mdisc);
-		rc = -EINVAL;
-		break;
-	}
-err:
-	msgb_free(msg);
-	return rc;
-}
-
-#if 0
-/* initialized all resources */
-struct abis_nm_h *abis_nm_init(struct abis_nm_cfg *cfg)
-{
-	struct abis_nm_h *nmh;
-
-	nmh = malloc(sizeof(*nmh));
-	if (!nmh)
-		return NULL;
-
-	nmh->cfg = cfg;
-
-	return nmh;
-}
-
-/* free all resources */
-void abis_nm_fini(struct abis_nm_h *nmh)
-{
-	free(nmh);
-}
-#endif
-
-/* Here we are trying to define a high-level API that can be used by
- * the actual BSC implementation.  However, the architecture is currently
- * still under design.  Ideally the calls to this API would be synchronous,
- * while the underlying stack behind the APi runs in a traditional select
- * based state machine.
- */
-
-/* 6.2 Software Load: */
-enum sw_state {
-	SW_STATE_NONE,
-	SW_STATE_WAIT_INITACK,
-	SW_STATE_WAIT_SEGACK,
-	SW_STATE_WAIT_ENDACK,
-	SW_STATE_WAIT_ACTACK,
-	SW_STATE_ERROR,
-};
-
-struct abis_nm_sw {
-	struct gsm_bts *bts;
-	int trx_nr;
-	gsm_cbfn *cbfn;
-	void *cb_data;
-	int forced;
-
-	/* this will become part of the SW LOAD INITIATE */
-	uint8_t obj_class;
-	uint8_t obj_instance[3];
-
-	uint8_t file_id[255];
-	uint8_t file_id_len;
-
-	uint8_t file_version[255];
-	uint8_t file_version_len;
-
-	uint8_t window_size;
-	uint8_t seg_in_window;
-
-	int fd;
-	FILE *stream;
-	enum sw_state state;
-	int last_seg;
-};
-
-static struct abis_nm_sw g_sw;
-
-static void sw_add_file_id_and_ver(struct abis_nm_sw *sw, struct msgb *msg)
-{
-	if (sw->bts->type == GSM_BTS_TYPE_NANOBTS) {
-		msgb_v_put(msg, NM_ATT_SW_DESCR);
-		msgb_tl16v_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id);
-		msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len,
-			       sw->file_version);
-	} else if (sw->bts->type == GSM_BTS_TYPE_BS11) {
-		msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id);
-		msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len,
-			     sw->file_version);
-	} else {
-		LOGP(DNM, LOGL_ERROR, "Please implement this for the BTS.\n");
-	}
-}
-
-/* 6.2.1 / 8.3.1: Load Data Initiate */
-static int sw_load_init(struct abis_nm_sw *sw)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	uint8_t len = 3*2 + sw->file_id_len + sw->file_version_len;
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, len, NM_MT_LOAD_INIT, sw->obj_class,
-			sw->obj_instance[0], sw->obj_instance[1],
-			sw->obj_instance[2]);
-
-	sw_add_file_id_and_ver(sw, msg);
-	msgb_tv_put(msg, NM_ATT_WINDOW_SIZE, sw->window_size);
-	
-	return abis_nm_sendmsg(sw->bts, msg);
-}
-
-static int is_last_line(FILE *stream)
-{
-	char next_seg_buf[256];
-	long pos;
-
-	/* check if we're sending the last line */
-	pos = ftell(stream);
-
-	/* Did ftell fail? Then we are at the end for sure */
-	if (pos < 0)
-		return 1;
-
-	if (!fgets(next_seg_buf, sizeof(next_seg_buf)-2, stream)) {
-		int rc = fseek(stream, pos, SEEK_SET);
-		if (rc < 0)
-			return rc;
-		return 1;
-	}
-
-	fseek(stream, pos, SEEK_SET);
-	return 0;
-}
-
-/* 6.2.2 / 8.3.2 Load Data Segment */
-static int sw_load_segment(struct abis_nm_sw *sw)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	char seg_buf[256];
-	char *line_buf = seg_buf+2;
-	unsigned char *tlv;
-	int len;
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-
-	switch (sw->bts->type) {
-	case GSM_BTS_TYPE_BS11:
-		if (fgets(line_buf, sizeof(seg_buf)-2, sw->stream) == NULL) {
-			perror("fgets reading segment");
-			return -EINVAL;
-		}
-		seg_buf[0] = 0x00;
-
-		/* check if we're sending the last line */
-		sw->last_seg = is_last_line(sw->stream);
-		if (sw->last_seg)
-			seg_buf[1] = 0;
-		else
-			seg_buf[1] = 1 + sw->seg_in_window++;
-
-		len = strlen(line_buf) + 2;
-		tlv = msgb_put(msg, TLV_GROSS_LEN(len));
-		tlv_put(tlv, NM_ATT_BS11_FILE_DATA, len, (uint8_t *)seg_buf);
-		/* BS11 wants CR + LF in excess of the TLV length !?! */
-		tlv[1] -= 2;
-
-		/* we only now know the exact length for the OM hdr */
-		len = strlen(line_buf)+2;
-		break;
-	case GSM_BTS_TYPE_NANOBTS: {
-		osmo_static_assert(sizeof(seg_buf) >= IPACC_SEGMENT_SIZE, buffer_big_enough);
-		len = read(sw->fd, &seg_buf, IPACC_SEGMENT_SIZE);
-		if (len < 0) {
-			perror("read failed");
-			return -EINVAL;
-		}
-
-		if (len != IPACC_SEGMENT_SIZE)
-			sw->last_seg = 1;
-
-		++sw->seg_in_window;
-		msgb_tl16v_put(msg, NM_ATT_IPACC_FILE_DATA, len, (const uint8_t *) seg_buf);
-		len += 3;
-		break;
-	}
-	default:
-		LOGP(DNM, LOGL_ERROR, "sw_load_segment needs implementation for the BTS.\n");
-		/* FIXME: Other BTS types */
-		return -1;
-	}
-
-	fill_om_fom_hdr(oh, len, NM_MT_LOAD_SEG, sw->obj_class,
-			sw->obj_instance[0], sw->obj_instance[1],
-			sw->obj_instance[2]);
-
-	return abis_nm_sendmsg_direct(sw->bts, msg);
-}
-
-/* 6.2.4 / 8.3.4 Load Data End */
-static int sw_load_end(struct abis_nm_sw *sw)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	uint8_t len = 2*2 + sw->file_id_len + sw->file_version_len;
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, len, NM_MT_LOAD_END, sw->obj_class,
-			sw->obj_instance[0], sw->obj_instance[1],
-			sw->obj_instance[2]);
-
-	sw_add_file_id_and_ver(sw, msg);
-	return abis_nm_sendmsg(sw->bts, msg);
-}
-
-/* Activate the specified software into the BTS */
-static int sw_activate(struct abis_nm_sw *sw)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	uint8_t len = 2*2 + sw->file_id_len + sw->file_version_len;
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, len, NM_MT_ACTIVATE_SW, sw->obj_class,
-			sw->obj_instance[0], sw->obj_instance[1],
-			sw->obj_instance[2]);
-
-	/* FIXME: this is BS11 specific format */
-	msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id);
-	msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len,
-		     sw->file_version);
-
-	return abis_nm_sendmsg(sw->bts, msg);
-}
-
-struct sdp_firmware {
-	char magic[4];
-	char more_magic[4];
-	unsigned int header_length;
-	unsigned int file_length;
-} __attribute__ ((packed));
-
-static int parse_sdp_header(struct abis_nm_sw *sw)
-{
-	struct sdp_firmware firmware_header;
-	int rc;
-	struct stat stat;
-
-	rc = read(sw->fd, &firmware_header, sizeof(firmware_header));
-	if (rc != sizeof(firmware_header)) {
-		LOGP(DNM, LOGL_ERROR, "Could not read SDP file header.\n");
-		return -1;
-	}
-
-	if (strncmp(firmware_header.magic, " SDP", 4) != 0) {
-		LOGP(DNM, LOGL_ERROR, "The magic number1 is wrong.\n");
-		return -1;
-	}
-
-	if (firmware_header.more_magic[0] != 0x10 ||
-	    firmware_header.more_magic[1] != 0x02 ||
-	    firmware_header.more_magic[2] != 0x00 ||
-	    firmware_header.more_magic[3] != 0x00) {
-		LOGP(DNM, LOGL_ERROR, "The more magic number is wrong.\n");
-		return -1;
-	}
-
-
-	if (fstat(sw->fd, &stat) == -1) {
-		LOGP(DNM, LOGL_ERROR, "Could not stat the file.\n");
-		return -1;
-	}
-
-	if (ntohl(firmware_header.file_length) != stat.st_size) {
-		LOGP(DNM, LOGL_ERROR, "The filesizes do not match.\n");
-		return -1;
-	}
-
-	/* go back to the start as we checked the whole filesize.. */
-	lseek(sw->fd, 0l, SEEK_SET);
-	LOGP(DNM, LOGL_NOTICE, "The ipaccess SDP header is not fully understood.\n"
-			       "There might be checksums in the file that are not\n"
-			       "verified and incomplete firmware might be flashed.\n"
-			       "There is absolutely no WARRANTY that flashing will\n"
-			       "work.\n");
-	return 0;
-}
-
-static int sw_open_file(struct abis_nm_sw *sw, const char *fname)
-{
-	char file_id[12+1];
-	char file_version[80+1];
-	int rc;
-
-	sw->fd = open(fname, O_RDONLY);
-	if (sw->fd < 0)
-		return sw->fd;
-
-	switch (sw->bts->type) {
-	case GSM_BTS_TYPE_BS11:
-		sw->stream = fdopen(sw->fd, "r");
-		if (!sw->stream) {
-			perror("fdopen");
-			return -1;
-		}
-		/* read first line and parse file ID and VERSION */
-		rc = fscanf(sw->stream, "@(#)%12s:%80s\r\n",
-			    file_id, file_version);
-		if (rc != 2) {
-			perror("parsing header line of software file");
-			return -1;
-		}
-		strcpy((char *)sw->file_id, file_id);
-		sw->file_id_len = strlen(file_id);
-		strcpy((char *)sw->file_version, file_version);
-		sw->file_version_len = strlen(file_version);
-		/* rewind to start of file */
-		rewind(sw->stream);
-		break;	
-	case GSM_BTS_TYPE_NANOBTS:
-		/* TODO: extract that from the filename or content */
-		rc = parse_sdp_header(sw);
-		if (rc < 0) {
-			fprintf(stderr, "Could not parse the ipaccess SDP header\n");
-			return -1;
-		}
-
-		strcpy((char *)sw->file_id, "id");
-		sw->file_id_len = 3;
-		strcpy((char *)sw->file_version, "version");
-		sw->file_version_len = 8;
-		break;
-	default:
-		/* We don't know how to treat them yet */
-		close(sw->fd);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-	
-static void sw_close_file(struct abis_nm_sw *sw)
-{
-	switch (sw->bts->type) {
-	case GSM_BTS_TYPE_BS11:
-		fclose(sw->stream);
-		break;
-	default:
-		close(sw->fd);
-		break;
-	}
-}
-
-/* Fill the window */
-static int sw_fill_window(struct abis_nm_sw *sw)
-{
-	int rc;
-
-	while (sw->seg_in_window < sw->window_size) {
-		rc = sw_load_segment(sw);
-		if (rc < 0)
-			return rc;
-		if (sw->last_seg)
-			break;
-	}
-	return 0;
-}
-
-/* callback function from abis_nm_rcvmsg() handler */
-static int abis_nm_rcvmsg_sw(struct msgb *mb)
-{
-	struct abis_om_fom_hdr *foh = msgb_l3(mb);
-	struct e1inp_sign_link *sign_link = mb->dst;
-	int rc = -1;
-	struct abis_nm_sw *sw = &g_sw;
-	enum sw_state old_state = sw->state;
-	
-	//DEBUGP(DNM, "state %u, NM MT 0x%02x\n", sw->state, foh->msg_type);
-
-	switch (sw->state) {
-	case SW_STATE_WAIT_INITACK:
-		switch (foh->msg_type) {
-		case NM_MT_LOAD_INIT_ACK:
-			/* fill window with segments */
-			if (sw->cbfn)
-				sw->cbfn(GSM_HOOK_NM_SWLOAD,
-					 NM_MT_LOAD_INIT_ACK, mb,
-					 sw->cb_data, NULL);
-			rc = sw_fill_window(sw);
-			sw->state = SW_STATE_WAIT_SEGACK;
-			abis_nm_queue_send_next(sign_link->trx->bts);
-			break;
-		case NM_MT_LOAD_INIT_NACK:
-			if (sw->forced) {
-				DEBUGP(DNM, "FORCED: Ignoring Software Load "
-					"Init NACK\n");
-				if (sw->cbfn)
-					sw->cbfn(GSM_HOOK_NM_SWLOAD,
-						 NM_MT_LOAD_INIT_ACK, mb,
-						 sw->cb_data, NULL);
-				rc = sw_fill_window(sw);
-				sw->state = SW_STATE_WAIT_SEGACK;
-			} else {
-				DEBUGP(DNM, "Software Load Init NACK\n");
-				/* FIXME: cause */
-				if (sw->cbfn)
-					sw->cbfn(GSM_HOOK_NM_SWLOAD,
-						 NM_MT_LOAD_INIT_NACK, mb,
-						 sw->cb_data, NULL);
-				sw->state = SW_STATE_ERROR;
-			}
-			abis_nm_queue_send_next(sign_link->trx->bts);
-			break;
-		}
-		break;
-	case SW_STATE_WAIT_SEGACK:
-		switch (foh->msg_type) {
-		case NM_MT_LOAD_SEG_ACK:
-			if (sw->cbfn)
-				sw->cbfn(GSM_HOOK_NM_SWLOAD,
-					 NM_MT_LOAD_SEG_ACK, mb,
-					 sw->cb_data, NULL);
-			sw->seg_in_window = 0;
-			if (!sw->last_seg) {
-				/* fill window with more segments */
-				rc = sw_fill_window(sw);
-				sw->state = SW_STATE_WAIT_SEGACK;
-			} else {
-				/* end the transfer */
-				sw->state = SW_STATE_WAIT_ENDACK;
-				rc = sw_load_end(sw);
-			}
-			abis_nm_queue_send_next(sign_link->trx->bts);
-			break;
-		case NM_MT_LOAD_ABORT:
-			if (sw->cbfn)
-				sw->cbfn(GSM_HOOK_NM_SWLOAD,
-					 NM_MT_LOAD_ABORT, mb,
-					 sw->cb_data, NULL);
-			break;
-		}
-		break;
-	case SW_STATE_WAIT_ENDACK:
-		switch (foh->msg_type) {
-		case NM_MT_LOAD_END_ACK:
-			sw_close_file(sw);
-			DEBUGP(DNM, "Software Load End (BTS %u)\n",
-				sw->bts->nr);
-			sw->state = SW_STATE_NONE;
-			if (sw->cbfn)
-				sw->cbfn(GSM_HOOK_NM_SWLOAD,
-					 NM_MT_LOAD_END_ACK, mb,
-					 sw->cb_data, NULL);
-			rc = 0;
-			abis_nm_queue_send_next(sign_link->trx->bts);
-			break;
-		case NM_MT_LOAD_END_NACK:
-			if (sw->forced) {
-				DEBUGP(DNM, "FORCED: Ignoring Software Load"
-					"End NACK\n");
-				sw->state = SW_STATE_NONE;
-				if (sw->cbfn)
-					sw->cbfn(GSM_HOOK_NM_SWLOAD,
-						 NM_MT_LOAD_END_ACK, mb,
-						 sw->cb_data, NULL);
-			} else {
-				DEBUGP(DNM, "Software Load End NACK\n");
-				/* FIXME: cause */
-				sw->state = SW_STATE_ERROR;
-				if (sw->cbfn)
-					sw->cbfn(GSM_HOOK_NM_SWLOAD,
-						 NM_MT_LOAD_END_NACK, mb,
-						 sw->cb_data, NULL);
-			}
-			abis_nm_queue_send_next(sign_link->trx->bts);
-			break;
-		}
-	case SW_STATE_WAIT_ACTACK:
-		switch (foh->msg_type) {
-		case NM_MT_ACTIVATE_SW_ACK:
-			/* we're done */
-			DEBUGP(DNM, "Activate Software DONE!\n");
-			sw->state = SW_STATE_NONE;
-			rc = 0;
-			if (sw->cbfn)
-				sw->cbfn(GSM_HOOK_NM_SWLOAD,
-					 NM_MT_ACTIVATE_SW_ACK, mb,
-					 sw->cb_data, NULL);
-			abis_nm_queue_send_next(sign_link->trx->bts);
-			break;
-		case NM_MT_ACTIVATE_SW_NACK:
-			DEBUGP(DNM, "Activate Software NACK\n");
-			/* FIXME: cause */
-			sw->state = SW_STATE_ERROR;
-			if (sw->cbfn)
-				sw->cbfn(GSM_HOOK_NM_SWLOAD,
-					 NM_MT_ACTIVATE_SW_NACK, mb,
-					 sw->cb_data, NULL);
-			abis_nm_queue_send_next(sign_link->trx->bts);
-			break;
-		}
-	case SW_STATE_NONE:
-		switch (foh->msg_type) {
-		case NM_MT_ACTIVATE_SW_ACK:
-			rc = 0;
-			break;
-		}
-		break;
-	case SW_STATE_ERROR:
-		break;
-	}
-
-	if (rc)
-		DEBUGP(DNM, "unexpected NM MT 0x%02x in state %u -> %u\n",
-			foh->msg_type, old_state, sw->state);
-
-	return rc;
-}
-
-/* Load the specified software into the 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)
-{
-	struct abis_nm_sw *sw = &g_sw;
-	int rc;
-
-	DEBUGP(DNM, "Software Load (BTS %u, File \"%s\")\n",
-		bts->nr, fname);
-
-	if (sw->state != SW_STATE_NONE)
-		return -EBUSY;
-
-	sw->bts = bts;
-	sw->trx_nr = trx_nr;
-
-	switch (bts->type) {
-	case GSM_BTS_TYPE_BS11:
-		sw->obj_class = NM_OC_SITE_MANAGER;
-		sw->obj_instance[0] = 0xff;
-		sw->obj_instance[1] = 0xff;
-		sw->obj_instance[2] = 0xff;
-		break;
-	case GSM_BTS_TYPE_NANOBTS:
-		sw->obj_class = NM_OC_BASEB_TRANSC;
-		sw->obj_instance[0] = sw->bts->nr;
-		sw->obj_instance[1] = sw->trx_nr;
-		sw->obj_instance[2] = 0xff;
-		break;
-	case GSM_BTS_TYPE_UNKNOWN:
-	default:
-		LOGPC(DNM, LOGL_ERROR, "Software Load not properly implemented.\n");
-		return -1;
-		break;
-	}
-	sw->window_size = win_size;
-	sw->state = SW_STATE_WAIT_INITACK;
-	sw->cbfn = cbfn;
-	sw->cb_data = cb_data;
-	sw->forced = forced;
-
-	rc = sw_open_file(sw, fname);
-	if (rc < 0) {
-		sw->state = SW_STATE_NONE;
-		return rc;
-	}
-
-	return sw_load_init(sw);
-}
-
-int abis_nm_software_load_status(struct gsm_bts *bts)
-{
-	struct abis_nm_sw *sw = &g_sw;
-	struct stat st;
-	int rc, percent;
-
-	rc = fstat(sw->fd, &st);
-	if (rc < 0) {
-		perror("ERROR during stat");
-		return rc;
-	}
-
-	if (sw->stream)
-		percent = (ftell(sw->stream) * 100) / st.st_size;
-	else
-		percent = (lseek(sw->fd, 0, SEEK_CUR) * 100) / st.st_size;
-	return percent;
-}
-
-/* Activate the specified software into the BTS */
-int abis_nm_software_activate(struct gsm_bts *bts, const char *fname,
-			      gsm_cbfn *cbfn, void *cb_data)
-{
-	struct abis_nm_sw *sw = &g_sw;
-	int rc;
-
-	DEBUGP(DNM, "Activating Software (BTS %u, File \"%s\")\n",
-		bts->nr, fname);
-
-	if (sw->state != SW_STATE_NONE)
-		return -EBUSY;
-
-	sw->bts = bts;
-	sw->obj_class = NM_OC_SITE_MANAGER;
-	sw->obj_instance[0] = 0xff;
-	sw->obj_instance[1] = 0xff;
-	sw->obj_instance[2] = 0xff;
-	sw->state = SW_STATE_WAIT_ACTACK;
-	sw->cbfn = cbfn;
-	sw->cb_data = cb_data;
-
-	/* Open the file in order to fill some sw struct members */
-	rc = sw_open_file(sw, fname);
-	if (rc < 0) {
-		sw->state = SW_STATE_NONE;
-		return rc;
-	}
-	sw_close_file(sw);
-
-	return sw_activate(sw);
-}
-
-static void fill_nm_channel(struct abis_nm_channel *ch, uint8_t bts_port,
-		       uint8_t ts_nr, uint8_t subslot_nr)
-{
-	ch->attrib = NM_ATT_ABIS_CHANNEL;
-	ch->bts_port = bts_port;
-	ch->timeslot = ts_nr;
-	ch->subslot = subslot_nr;	
-}
-
-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)
-{
-	struct abis_om_hdr *oh;
-	struct abis_nm_channel *ch;
-	uint8_t len = sizeof(*ch) + 2;
-	struct msgb *msg = nm_msgb_alloc();
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, len, NM_MT_ESTABLISH_TEI, NM_OC_RADIO_CARRIER,
-			bts->bts_nr, trx_nr, 0xff);
-	
-	msgb_tv_put(msg, NM_ATT_TEI, tei);
-
-	ch = (struct abis_nm_channel *) msgb_put(msg, sizeof(*ch));
-	fill_nm_channel(ch, e1_port, e1_timeslot, e1_subslot);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-/* connect signalling of one (BTS,TRX) to a particular timeslot on the E1 */
-int abis_nm_conn_terr_sign(struct gsm_bts_trx *trx,
-			   uint8_t e1_port, uint8_t e1_timeslot, uint8_t e1_subslot)
-{
-	struct gsm_bts *bts = trx->bts;
-	struct abis_om_hdr *oh;
-	struct abis_nm_channel *ch;
-	struct msgb *msg = nm_msgb_alloc();
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, sizeof(*ch), NM_MT_CONN_TERR_SIGN,
-			NM_OC_RADIO_CARRIER, bts->bts_nr, trx->nr, 0xff);
-	
-	ch = (struct abis_nm_channel *) msgb_put(msg, sizeof(*ch));
-	fill_nm_channel(ch, e1_port, e1_timeslot, e1_subslot);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-#if 0
-int abis_nm_disc_terr_sign(struct abis_nm_h *h, struct abis_om_obj_inst *inst,
-			   struct abis_nm_abis_channel *chan)
-{
-}
-#endif
-
-int abis_nm_conn_terr_traf(struct gsm_bts_trx_ts *ts,
-			   uint8_t e1_port, uint8_t e1_timeslot,
-			   uint8_t e1_subslot)
-{
-	struct gsm_bts *bts = ts->trx->bts;
-	struct abis_om_hdr *oh;
-	struct abis_nm_channel *ch;
-	struct msgb *msg = nm_msgb_alloc();
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, sizeof(*ch), NM_MT_CONN_TERR_TRAF,
-			NM_OC_CHANNEL, bts->bts_nr, ts->trx->nr, ts->nr);
-
-	ch = (struct abis_nm_channel *) msgb_put(msg, sizeof(*ch));
-	fill_nm_channel(ch, e1_port, e1_timeslot, e1_subslot);
-
-	DEBUGP(DNM, "CONNECT TERR TRAF Um=%s E1=(%u,%u,%u)\n",
-		gsm_ts_name(ts),
-		e1_port, e1_timeslot, e1_subslot);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-#if 0
-int abis_nm_disc_terr_traf(struct abis_nm_h *h, struct abis_om_obj_inst *inst,
-			   struct abis_nm_abis_channel *chan,
-			   uint8_t subchan)
-{
-}
-#endif
-
-/* 3GPP TS 52.021 § 8.11.1 */
-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)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg;
-
-	if (bts->type != GSM_BTS_TYPE_OSMOBTS) {
-		LOGPC(DNM, LOGL_NOTICE, "Getting attributes from BTS%d type %s is not supported.\n",
-		      bts->nr, btstype2str(bts->type));
-		return -EINVAL;
-	}
-
-	DEBUGP(DNM, "Get Attr (bts=%d)\n", bts->nr);
-
-	msg = nm_msgb_alloc();
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, attr_len, NM_MT_GET_ATTR, obj_class,
-			bts_nr, trx_nr, ts_nr);
-	msgb_tl16v_put(msg, NM_ATT_LIST_REQ_ATTR, attr_len, attr);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-/* Chapter 8.6.1 */
-int abis_nm_set_bts_attr(struct gsm_bts *bts, uint8_t *attr, int attr_len)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	uint8_t *cur;
-
-	DEBUGP(DNM, "Set BTS Attr (bts=%d)\n", bts->nr);
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, attr_len, NM_MT_SET_BTS_ATTR, NM_OC_BTS, bts->bts_nr, 0xff, 0xff);
-	cur = msgb_put(msg, attr_len);
-	memcpy(cur, attr, attr_len);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-/* Chapter 8.6.2 */
-int abis_nm_set_radio_attr(struct gsm_bts_trx *trx, uint8_t *attr, int attr_len)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	uint8_t *cur;
-
-	DEBUGP(DNM, "Set TRX Attr (bts=%d,trx=%d)\n", trx->bts->nr, trx->nr);
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, attr_len, NM_MT_SET_RADIO_ATTR, NM_OC_RADIO_CARRIER,
-			trx->bts->bts_nr, trx->nr, 0xff);
-	cur = msgb_put(msg, attr_len);
-	memcpy(cur, attr, attr_len);
-
-	return abis_nm_sendmsg(trx->bts, msg);
-}
-
-int abis_nm_update_max_power_red(struct gsm_bts_trx *trx)
-{
-	uint8_t attr[] = { NM_ATT_RF_MAXPOWR_R, trx->max_power_red / 2 };
-	return abis_nm_set_radio_attr(trx, attr, ARRAY_SIZE(attr));
-}
-
-static int verify_chan_comb(struct gsm_bts_trx_ts *ts, uint8_t chan_comb,
-			const char **reason)
-{
-	int i;
-
-	*reason = "Reason unknown";
-
-	/* As it turns out, the BS-11 has some very peculiar restrictions
-	 * on the channel combinations it allows */
-	switch (ts->trx->bts->type) {
-	case GSM_BTS_TYPE_BS11:
-		switch (chan_comb) {
-		case NM_CHANC_TCHHalf:
-		case NM_CHANC_TCHHalf2:
-		case NM_CHANC_OSMO_TCHFull_TCHHalf_PDCH:
-			/* not supported */
-			*reason = "TCH/H is not supported.";
-			return -EINVAL;
-		case NM_CHANC_SDCCH:
-			/* only one SDCCH/8 per TRX */
-			for (i = 0; i < TRX_NR_TS; i++) {
-				if (i == ts->nr)
-					continue;
-				if (ts->trx->ts[i].nm_chan_comb ==
-				    NM_CHANC_SDCCH) {
-					*reason = "Only one SDCCH/8 per TRX allowed.";
-					return -EINVAL;
-				}
-			}
-			/* not allowed for TS0 of BCCH-TRX */
-			if (ts->trx == ts->trx->bts->c0 &&
-			    ts->nr == 0) {
-				*reason = "SDCCH/8 must be on TS0.";
-				return -EINVAL;
-			}
-
-			/* not on the same TRX that has a BCCH+SDCCH4
-			 * combination */
-			if (ts->trx != ts->trx->bts->c0 &&
-			    (ts->trx->ts[0].nm_chan_comb == 5 ||
-			     ts->trx->ts[0].nm_chan_comb == 8)) {
-				*reason = "SDCCH/8 and BCCH must be on the same TRX.";
-				return -EINVAL;
-			}
-			break;
-		case NM_CHANC_mainBCCH:
-		case NM_CHANC_BCCHComb:
-			/* allowed only for TS0 of C0 */
-			if (ts->trx != ts->trx->bts->c0 || ts->nr != 0) {
-				*reason = "Main BCCH must be on TS0.";
-				return -EINVAL;
-			}
-			break;
-		case NM_CHANC_BCCH:
-			/* allowed only for TS 2/4/6 of C0 */
-			if (ts->trx != ts->trx->bts->c0) {
-				*reason = "BCCH must be on C0.";
-				return -EINVAL;
-			}
-			if (ts->nr != 2 && ts->nr != 4 && ts->nr != 6) {
-				*reason = "BCCH must be on TS 2/4/6.";
-				return -EINVAL;
-			}
-			break;
-		case 8: /* this is not like 08.58, but in fact
-			 * FCCH+SCH+BCCH+CCCH+SDCCH/4+SACCH/C4+CBCH */
-			/* FIXME: only one CBCH allowed per cell */
-			break;
-		}
-		break;
-	case GSM_BTS_TYPE_NANOBTS:
-		switch (ts->nr) {
-		case 0:
-			if (ts->trx->nr == 0) {
-				/* only on TRX0 */
-				switch (chan_comb) {
-				case NM_CHANC_BCCH:
-				case NM_CHANC_mainBCCH:
-				case NM_CHANC_BCCHComb:
-					return 0;
-					break;
-				default:
-					*reason = "TS0 of TRX0 must carry a BCCH.";
-					return -EINVAL;
-				}
-			} else {
-				switch (chan_comb) {
-				case NM_CHANC_TCHFull:
-				case NM_CHANC_TCHHalf:
-				case NM_CHANC_IPAC_TCHFull_TCHHalf:
-					return 0;
-				default:
-					*reason = "TS0 must carry a TCH/F or TCH/H.";
-					return -EINVAL;
-				}
-			}
-			break;
-		case 1:
-			if (ts->trx->nr == 0) {
-				switch (chan_comb) {
-				case NM_CHANC_SDCCH_CBCH:
-					if (ts->trx->ts[0].nm_chan_comb ==
-					    NM_CHANC_mainBCCH)
-						return 0;
-					*reason = "TS0 must be the main BCCH for CBCH.";
-					return -EINVAL;
-				case NM_CHANC_SDCCH:
-				case NM_CHANC_TCHFull:
-				case NM_CHANC_TCHHalf:
-				case NM_CHANC_IPAC_TCHFull_TCHHalf:
-				case NM_CHANC_IPAC_TCHFull_PDCH:
-				case NM_CHANC_OSMO_TCHFull_TCHHalf_PDCH:
-					return 0;
-				default:
-					*reason = "TS1 must carry a CBCH, SDCCH or TCH.";
-					return -EINVAL;
-				}
-			} else {
-				switch (chan_comb) {
-				case NM_CHANC_SDCCH:
-				case NM_CHANC_TCHFull:
-				case NM_CHANC_TCHHalf:
-				case NM_CHANC_IPAC_TCHFull_TCHHalf:
-					return 0;
-				default:
-					*reason = "TS1 must carry a SDCCH or TCH.";
-					return -EINVAL;
-				}
-			}
-			break;
-		case 2:
-		case 3:
-		case 4:
-		case 5:
-		case 6:
-		case 7:
-			switch (chan_comb) {
-			case NM_CHANC_TCHFull:
-			case NM_CHANC_TCHHalf:
-			case NM_CHANC_IPAC_TCHFull_TCHHalf:
-				return 0;
-			case NM_CHANC_IPAC_PDCH:
-			case NM_CHANC_IPAC_TCHFull_PDCH:
-			case NM_CHANC_OSMO_TCHFull_TCHHalf_PDCH:
-				if (ts->trx->nr == 0)
-					return 0;
-				else {
-					*reason = "PDCH must be on TRX0.";
-					return -EINVAL;
-				}
-			}
-			break;
-		}
-		*reason = "Unknown combination";
-		return -EINVAL;
-	case GSM_BTS_TYPE_OSMOBTS:
-		/* no known restrictions */
-		return 0;
-	default:
-		/* unknown BTS type */
-		return 0;
-	}
-	return 0;
-}
-
-/* Chapter 8.6.3 */
-int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, uint8_t chan_comb)
-{
-	struct gsm_bts *bts = ts->trx->bts;
-	struct abis_om_hdr *oh;
-	uint8_t zero = 0x00;
-	struct msgb *msg = nm_msgb_alloc();
-	uint8_t len = 2 + 2;
-	const char *reason = NULL;
-
-	if (bts->type == GSM_BTS_TYPE_BS11)
-		len += 4 + 2 + 2 + 3;
-
-	DEBUGP(DNM, "Set Chan Attr %s\n", gsm_ts_name(ts));
-	if (verify_chan_comb(ts, chan_comb, &reason) < 0) {
-		msgb_free(msg);
-		LOGP(DNM, LOGL_ERROR,
-			"Invalid Channel Combination %d on %s. Reason: %s\n",
-			chan_comb, gsm_ts_name(ts), reason);
-		return -EINVAL;
-	}
-	ts->nm_chan_comb = chan_comb;
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, len, NM_MT_SET_CHAN_ATTR,
-			NM_OC_CHANNEL, bts->bts_nr,
-			ts->trx->nr, ts->nr);
-	msgb_tv_put(msg, NM_ATT_CHAN_COMB, chan_comb);
-	if (ts->hopping.enabled) {
-		unsigned int i;
-		uint8_t *len;
-
-		msgb_tv_put(msg, NM_ATT_HSN, ts->hopping.hsn);
-		msgb_tv_put(msg, NM_ATT_MAIO, ts->hopping.maio);
-
-		/* build the ARFCN list */
-		msgb_put_u8(msg, NM_ATT_ARFCN_LIST);
-		len = msgb_put(msg, 1);
-		*len = 0;
-		for (i = 0; i < ts->hopping.arfcns.data_len*8; i++) {
-			if (bitvec_get_bit_pos(&ts->hopping.arfcns, i)) {
-				msgb_put_u16(msg, i);
-				/* At least BS-11 wants a TLV16 here */
-				if (bts->type == GSM_BTS_TYPE_BS11)
-					*len += 1;
-				else
-					*len += sizeof(uint16_t);
-			}
-		}
-	}
-	msgb_tv_put(msg, NM_ATT_TSC, gsm_ts_tsc(ts));	/* training sequence */
-	if (bts->type == GSM_BTS_TYPE_BS11)
-		msgb_tlv_put(msg, 0x59, 1, &zero);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-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)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	uint8_t msgtype = NM_MT_SW_ACT_REQ_ACK;
-	uint8_t len = att_len;
-
-	if (nack) {
-		len += 2;
-		msgtype = NM_MT_SW_ACT_REQ_NACK;
-	}
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, att_len, msgtype, obj_class, i1, i2, i3);
-
-	if (attr) {
-		uint8_t *ptr = msgb_put(msg, att_len);
-		memcpy(ptr, attr, att_len);
-	}
-	if (nack)
-		msgb_tv_put(msg, NM_ATT_NACK_CAUSES, NM_NACK_OBJCLASS_NOTSUPP);
-
-	return abis_nm_sendmsg_direct(bts, msg);
-}
-
-int abis_nm_raw_msg(struct gsm_bts *bts, int len, uint8_t *rawmsg)
-{
-	struct msgb *msg = nm_msgb_alloc();
-	struct abis_om_hdr *oh;
-	uint8_t *data;
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, sizeof(*oh));
-	fill_om_hdr(oh, len);
-	data = msgb_put(msg, len);
-	memcpy(data, rawmsg, len);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-/* Siemens specific commands */
-static int __simple_cmd(struct gsm_bts *bts, uint8_t msg_type)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 0, msg_type, NM_OC_SITE_MANAGER,
-			0xff, 0xff, 0xff);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-/* Chapter 8.9.2 */
-int abis_nm_opstart(struct gsm_bts *bts, uint8_t obj_class, uint8_t i0, uint8_t i1, uint8_t i2)
-{
-	struct abis_om_hdr *oh;
-	struct abis_om_fom_hdr *foh;
-	struct msgb *msg = nm_msgb_alloc();
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	foh = fill_om_fom_hdr(oh, 0, NM_MT_OPSTART, obj_class, i0, i1, i2);
-
-	abis_nm_debugp_foh(DNM, foh);
-	DEBUGPC(DNM, "Sending OPSTART\n");
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-/* Chapter 8.8.5 */
-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)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 2, NM_MT_CHG_ADM_STATE, obj_class, i0, i1, i2);
-	msgb_tv_put(msg, NM_ATT_ADM_STATE, adm_state);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-int abis_nm_conn_mdrop_link(struct gsm_bts *bts, uint8_t e1_port0, uint8_t ts0,
-			    uint8_t e1_port1, uint8_t ts1)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	uint8_t *attr;
-
-	DEBUGP(DNM, "CONNECT MDROP LINK E1=(%u,%u) -> E1=(%u, %u)\n",
-		e1_port0, ts0, e1_port1, ts1);
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 6, NM_MT_CONN_MDROP_LINK,
-			NM_OC_SITE_MANAGER, 0x00, 0x00, 0x00);
-
-	attr = msgb_put(msg, 3);
-	attr[0] = NM_ATT_MDROP_LINK;
-	attr[1] = e1_port0;
-	attr[2] = ts0;
-
-	attr = msgb_put(msg, 3);
-	attr[0] = NM_ATT_MDROP_NEXT;
-	attr[1] = e1_port1;
-	attr[2] = ts1;
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-/* Chapter 8.7.1 */
-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)
-{
-	struct abis_om_hdr *oh;
-
-	DEBUGP(DNM, "PEFORM TEST %s\n", abis_nm_test_name(test_nr));
-
-	if (!msg)
-		msg = nm_msgb_alloc();
-
-	msgb_tv_push(msg, NM_ATT_AUTON_REPORT, auton_report);
-	msgb_tv_push(msg, NM_ATT_TEST_NO, test_nr);
-	oh = (struct abis_om_hdr *) msgb_push(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, msgb_l3len(msg), NM_MT_PERF_TEST,
-			obj_class, bts_nr, trx_nr, ts_nr);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-int abis_nm_event_reports(struct gsm_bts *bts, int on)
-{
-	if (on == 0)
-		return __simple_cmd(bts, NM_MT_STOP_EVENT_REP);
-	else
-		return __simple_cmd(bts, NM_MT_REST_EVENT_REP);
-}
-
-/* Siemens (or BS-11) specific commands */
-
-int abis_nm_bs11_bsc_disconnect(struct gsm_bts *bts, int reconnect)
-{
-	if (reconnect == 0)
-		return __simple_cmd(bts, NM_MT_BS11_DISCONNECT);
-	else
-		return __simple_cmd(bts, NM_MT_BS11_RECONNECT);
-}
-
-int abis_nm_bs11_restart(struct gsm_bts *bts)
-{
-	return __simple_cmd(bts, NM_MT_BS11_RESTART);
-}
-
-
-struct bs11_date_time {
-	uint16_t	year;
-	uint8_t	month;
-	uint8_t	day;
-	uint8_t	hour;
-	uint8_t	min;
-	uint8_t	sec;
-} __attribute__((packed));
-
-
-void get_bs11_date_time(struct bs11_date_time *aet)
-{
-	time_t t;
-	struct tm *tm;
-
-	t = time(NULL);
-	tm = localtime(&t);
-	aet->sec = tm->tm_sec;
-	aet->min = tm->tm_min;
-	aet->hour = tm->tm_hour;
-	aet->day = tm->tm_mday;
-	aet->month = tm->tm_mon;
-	aet->year = htons(1900 + tm->tm_year);
-}
-
-int abis_nm_bs11_reset_resource(struct gsm_bts *bts)
-{
-	return __simple_cmd(bts, NM_MT_BS11_RESET_RESOURCE);
-}
-
-int abis_nm_bs11_db_transmission(struct gsm_bts *bts, int begin)
-{
-	if (begin)
-		return __simple_cmd(bts, NM_MT_BS11_BEGIN_DB_TX);
-	else
-		return __simple_cmd(bts, NM_MT_BS11_END_DB_TX);
-}
-
-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)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	uint8_t *cur;
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, attr_len, NM_MT_BS11_CREATE_OBJ,
-			NM_OC_BS11, type, 0, idx);
-	cur = msgb_put(msg, attr_len);
-	memcpy(cur, attr, attr_len);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-int abis_nm_bs11_delete_object(struct gsm_bts *bts,
-				enum abis_bs11_objtype type, uint8_t idx)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 0, NM_MT_BS11_DELETE_OBJ,
-			NM_OC_BS11, type, 0, idx);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-int abis_nm_bs11_create_envaBTSE(struct gsm_bts *bts, uint8_t idx)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	uint8_t zero = 0x00;
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 3, NM_MT_BS11_CREATE_OBJ,
-			NM_OC_BS11_ENVABTSE, 0, idx, 0xff);
-	msgb_tlv_put(msg, 0x99, 1, &zero);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-int abis_nm_bs11_create_bport(struct gsm_bts *bts, uint8_t idx)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 0, NM_MT_BS11_CREATE_OBJ, NM_OC_BS11_BPORT,
-			idx, 0xff, 0xff);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-int abis_nm_bs11_delete_bport(struct gsm_bts *bts, uint8_t idx)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 0, NM_MT_BS11_DELETE_OBJ, NM_OC_BS11_BPORT,
-			idx, 0xff, 0xff);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-static const uint8_t sm_attr[] = { NM_ATT_TEI, NM_ATT_ABIS_CHANNEL };
-int abis_nm_bs11_get_oml_tei_ts(struct gsm_bts *bts)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 2+sizeof(sm_attr), NM_MT_GET_ATTR, NM_OC_SITE_MANAGER,
-			0xff, 0xff, 0xff);
-	msgb_tlv_put(msg, NM_ATT_LIST_REQ_ATTR, sizeof(sm_attr), sm_attr);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-/* like abis_nm_conn_terr_traf + set_tei */
-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)
-{
-	struct abis_om_hdr *oh;
-	struct abis_nm_channel *ch;
-	struct msgb *msg = nm_msgb_alloc();
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, sizeof(*ch)+2, NM_MT_BS11_SET_ATTR,
-			NM_OC_SITE_MANAGER, 0xff, 0xff, 0xff);
-
-	ch = (struct abis_nm_channel *) msgb_put(msg, sizeof(*ch));
-	fill_nm_channel(ch, e1_port, e1_timeslot, e1_subslot);
-	msgb_tv_put(msg, NM_ATT_TEI, tei);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-int abis_nm_bs11_set_trx_power(struct gsm_bts_trx *trx, uint8_t level)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 3, NM_MT_BS11_SET_ATTR,
-			NM_OC_BS11, BS11_OBJ_PA, 0x00, trx->nr);
-	msgb_tlv_put(msg, NM_ATT_BS11_TXPWR, 1, &level);
-
-	return abis_nm_sendmsg(trx->bts, msg);
-}
-
-int abis_nm_bs11_get_trx_power(struct gsm_bts_trx *trx)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	uint8_t attr = NM_ATT_BS11_TXPWR;
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 2+sizeof(attr), NM_MT_GET_ATTR,
-			NM_OC_BS11, BS11_OBJ_PA, 0x00, trx->nr);
-	msgb_tlv_put(msg, NM_ATT_LIST_REQ_ATTR, sizeof(attr), &attr);
-
-	return abis_nm_sendmsg(trx->bts, msg);
-}
-
-int abis_nm_bs11_get_pll_mode(struct gsm_bts *bts)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	uint8_t attr[] = { NM_ATT_BS11_PLL_MODE };
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 2+sizeof(attr), NM_MT_GET_ATTR,
-			NM_OC_BS11, BS11_OBJ_LI, 0x00, 0x00);
-	msgb_tlv_put(msg, NM_ATT_LIST_REQ_ATTR, sizeof(attr), attr);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-int abis_nm_bs11_get_cclk(struct gsm_bts *bts)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	uint8_t attr[] = { NM_ATT_BS11_CCLK_ACCURACY,
-			    NM_ATT_BS11_CCLK_TYPE };
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 2+sizeof(attr), NM_MT_GET_ATTR,
-			NM_OC_BS11, BS11_OBJ_CCLK, 0x00, 0x00);
-	msgb_tlv_put(msg, NM_ATT_LIST_REQ_ATTR, sizeof(attr), attr);
-
-	return abis_nm_sendmsg(bts, msg);
-
-}
-
-//static const uint8_t bs11_logon_c7[] = { 0x07, 0xd9, 0x01, 0x11, 0x0d, 0x10, 0x20 };
-
-int abis_nm_bs11_factory_logon(struct gsm_bts *bts, int on)
-{
-	return abis_nm_bs11_logon(bts, 0x02, "FACTORY", on);
-}
-
-int abis_nm_bs11_infield_logon(struct gsm_bts *bts, int on)
-{
-	return abis_nm_bs11_logon(bts, 0x03, "FIELD  ", on);
-}
-
-int abis_nm_bs11_logon(struct gsm_bts *bts, uint8_t level, const char *name, int on)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	struct bs11_date_time bdt;
-
-	get_bs11_date_time(&bdt);
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	if (on) {
-		uint8_t len = 3*2 + sizeof(bdt)
-				+ 1 + strlen(name);
-		fill_om_fom_hdr(oh, len, NM_MT_BS11_LMT_LOGON,
-				NM_OC_BS11_BTSE, 0xff, 0xff, 0xff);
-		msgb_tlv_put(msg, NM_ATT_BS11_LMT_LOGIN_TIME,
-			     sizeof(bdt), (uint8_t *) &bdt);
-		msgb_tlv_put(msg, NM_ATT_BS11_LMT_USER_ACC_LEV,
-			     1, &level);
-		msgb_tlv_put(msg, NM_ATT_BS11_LMT_USER_NAME,
-			     strlen(name), (uint8_t *)name);
-	} else {
-		fill_om_fom_hdr(oh, 0, NM_MT_BS11_LMT_LOGOFF,
-				NM_OC_BS11_BTSE, 0xff, 0xff, 0xff);
-	}
-	
-	return abis_nm_sendmsg(bts, msg);
-}
-
-int abis_nm_bs11_set_trx1_pw(struct gsm_bts *bts, const char *password)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg;
-
-	if (strlen(password) != 10)
-		return -EINVAL;
-
- 	msg = nm_msgb_alloc();
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 2+strlen(password), NM_MT_BS11_SET_ATTR,
-			NM_OC_BS11, BS11_OBJ_TRX1, 0x00, 0x00);
-	msgb_tlv_put(msg, NM_ATT_BS11_PASSWORD, 10, (const uint8_t *)password);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-/* change the BS-11 PLL Mode to either locked (E1 derived) or standalone */
-int abis_nm_bs11_set_pll_locked(struct gsm_bts *bts, int locked)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg;
-	uint8_t tlv_value;
-	
-	msg = nm_msgb_alloc();
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 3, NM_MT_BS11_SET_ATTR, NM_OC_BS11,
-			BS11_OBJ_LI, 0x00, 0x00);
-
-	if (locked)
-		tlv_value = BS11_LI_PLL_LOCKED;
-	else
-		tlv_value = BS11_LI_PLL_STANDALONE;
-	
-	msgb_tlv_put(msg, NM_ATT_BS11_PLL_MODE, 1, &tlv_value);
-	
-	return abis_nm_sendmsg(bts, msg);
-}
-
-/* Set the calibration value of the PLL (work value/set value)
- * It depends on the login which one is changed */
-int abis_nm_bs11_set_pll(struct gsm_bts *bts, int value)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg;
-	uint8_t tlv_value[2];
-
-	msg = nm_msgb_alloc();
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 3, NM_MT_BS11_SET_ATTR, NM_OC_BS11,
-			BS11_OBJ_TRX1, 0x00, 0x00);
-
-	tlv_value[0] = value>>8;
-	tlv_value[1] = value&0xff;
-
-	msgb_tlv_put(msg, NM_ATT_BS11_PLL, 2, tlv_value);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-int abis_nm_bs11_get_state(struct gsm_bts *bts)
-{
-	return __simple_cmd(bts, NM_MT_BS11_GET_STATE);
-}
-
-/* BS11 SWL */
-
-void *tall_fle_ctx;
-
-struct abis_nm_bs11_sw {
-	struct gsm_bts *bts;
-	char swl_fname[PATH_MAX];
-	uint8_t win_size;
-	int forced;
-	struct llist_head file_list;
-	gsm_cbfn *user_cb;	/* specified by the user */
-};
-static struct abis_nm_bs11_sw _g_bs11_sw, *g_bs11_sw = &_g_bs11_sw;
-
-struct file_list_entry {
-	struct llist_head list;
-	char fname[PATH_MAX];
-};
-
-struct file_list_entry *fl_dequeue(struct llist_head *queue)
-{
-	struct llist_head *lh;
-
-	if (llist_empty(queue))
-		return NULL;
-
-	lh = queue->next;
-	llist_del(lh);
-	
-	return llist_entry(lh, struct file_list_entry, list);
-}
-
-static int bs11_read_swl_file(struct abis_nm_bs11_sw *bs11_sw)
-{
-	char linebuf[255];
-	struct llist_head *lh, *lh2;
-	FILE *swl;
-	int rc = 0;
-
-	swl = fopen(bs11_sw->swl_fname, "r");
-	if (!swl)
-		return -ENODEV;
-
-	/* zero the stale file list, if any */
-	llist_for_each_safe(lh, lh2, &bs11_sw->file_list) {
-		llist_del(lh);
-		talloc_free(lh);
-	}
-
-	while (fgets(linebuf, sizeof(linebuf), swl)) {
-		char file_id[12+1];
-		char file_version[80+1];
-		struct file_list_entry *fle;
-		static char dir[PATH_MAX];
-
-		if (strlen(linebuf) < 4)
-			continue;
-	
-		rc = sscanf(linebuf+4, "%12s:%80s\r\n", file_id, file_version);
-		if (rc < 0) {
-			perror("ERR parsing SWL file");
-			rc = -EINVAL;
-			goto out;
-		}
-		if (rc < 2)
-			continue;
-
-		fle = talloc_zero(tall_fle_ctx, struct file_list_entry);
-		if (!fle) {
-			rc = -ENOMEM;
-			goto out;
-		}
-
-		/* construct new filename */
-		osmo_strlcpy(dir, bs11_sw->swl_fname, sizeof(dir));
-		strncat(fle->fname, dirname(dir), sizeof(fle->fname) - 1);
-		strcat(fle->fname, "/");
-		strncat(fle->fname, file_id, sizeof(fle->fname) - 1 -strlen(fle->fname));
-		
-		llist_add_tail(&fle->list, &bs11_sw->file_list);
-	}
-
-out:
-	fclose(swl);
-	return rc;
-}
-
-/* bs11 swload specific callback, passed to abis_nm core swload */
-static int bs11_swload_cbfn(unsigned int hook, unsigned int event,
-			    struct msgb *msg, void *data, void *param)
-{
-	struct abis_nm_bs11_sw *bs11_sw = data;
-	struct file_list_entry *fle;
-	int rc = 0;
-
-	switch (event) {
-	case NM_MT_LOAD_END_ACK:
-		fle = fl_dequeue(&bs11_sw->file_list);
-		if (fle) {
-			/* start download the next file of our file list */
-			rc = abis_nm_software_load(bs11_sw->bts, 0xff, fle->fname,
-						   bs11_sw->win_size,
-						   bs11_sw->forced,
-						   &bs11_swload_cbfn, bs11_sw);
-			talloc_free(fle);
-		} else {
-			/* activate the SWL */
-			rc = abis_nm_software_activate(bs11_sw->bts,
-							bs11_sw->swl_fname,
-							bs11_swload_cbfn,
-							bs11_sw);
-		}
-		break;
-	case NM_MT_LOAD_SEG_ACK:
-	case NM_MT_LOAD_END_NACK:
-	case NM_MT_LOAD_INIT_ACK:
-	case NM_MT_LOAD_INIT_NACK:
-	case NM_MT_ACTIVATE_SW_NACK:
-	case NM_MT_ACTIVATE_SW_ACK:
-	default:
-		/* fallthrough to the user callback */
-		if (bs11_sw->user_cb)
-			rc = bs11_sw->user_cb(hook, event, msg, NULL, NULL);
-		break;
-	}
-
-	return rc;
-}
-
-/* Siemens provides a SWL file that is a mere listing of all the other
- * files that are part of a software release.  We need to upload first
- * the list file, and then each file that is listed in the list file */
-int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname,
-			  uint8_t win_size, int forced, gsm_cbfn *cbfn)
-{
-	struct abis_nm_bs11_sw *bs11_sw = g_bs11_sw;
-	struct file_list_entry *fle;
-	int rc = 0;
-
-	INIT_LLIST_HEAD(&bs11_sw->file_list);
-	bs11_sw->bts = bts;
-	bs11_sw->win_size = win_size;
-	bs11_sw->user_cb = cbfn;
-	bs11_sw->forced = forced;
-
-	osmo_strlcpy(bs11_sw->swl_fname, fname, sizeof(bs11_sw->swl_fname));
-	rc = bs11_read_swl_file(bs11_sw);
-	if (rc < 0)
-		return rc;
-
-	/* dequeue next item in file list */
-	fle = fl_dequeue(&bs11_sw->file_list);
-	if (!fle)
-		return -EINVAL;
-
-	/* start download the next file of our file list */
-	rc = abis_nm_software_load(bts, 0xff, fle->fname, win_size, forced,
-				   bs11_swload_cbfn, bs11_sw);
-	talloc_free(fle);
-	return rc;
-}
-
-#if 0
-static uint8_t req_attr_btse[] = {
-	NM_ATT_ADM_STATE, NM_ATT_BS11_LMT_LOGON_SESSION,
-	NM_ATT_BS11_LMT_LOGIN_TIME, NM_ATT_BS11_LMT_USER_ACC_LEV,
-	NM_ATT_BS11_LMT_USER_NAME,
-
-	0xaf, NM_ATT_BS11_RX_OFFSET, NM_ATT_BS11_VENDOR_NAME,
-
-	NM_ATT_BS11_SW_LOAD_INTENDED, NM_ATT_BS11_SW_LOAD_SAFETY,
-
-	NM_ATT_BS11_SW_LOAD_STORED };
-
-static uint8_t req_attr_btsm[] = {
-	NM_ATT_ABIS_CHANNEL, NM_ATT_TEI, NM_ATT_BS11_ABIS_EXT_TIME,
-	NM_ATT_ADM_STATE, NM_ATT_AVAIL_STATUS, 0xce, NM_ATT_FILE_ID,
-	NM_ATT_FILE_VERSION, NM_ATT_OPER_STATE, 0xe8, NM_ATT_BS11_ALL_TEST_CATG,
-	NM_ATT_SW_DESCR, NM_ATT_GET_ARI };
-#endif
-	
-static uint8_t req_attr[] = {
-	NM_ATT_ADM_STATE, NM_ATT_AVAIL_STATUS, 0xa8, NM_ATT_OPER_STATE,
-	0xd5, 0xa1, NM_ATT_BS11_ESN_FW_CODE_NO, NM_ATT_BS11_ESN_HW_CODE_NO,
-	0x42, NM_ATT_BS11_ESN_PCB_SERIAL, NM_ATT_BS11_PLL };
-
-int abis_nm_bs11_get_serno(struct gsm_bts *bts)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	/* SiemensHW CCTRL object */
-	fill_om_fom_hdr(oh, 2+sizeof(req_attr), NM_MT_GET_ATTR, NM_OC_BS11,
-			0x03, 0x00, 0x00);
-	msgb_tlv_put(msg, NM_ATT_LIST_REQ_ATTR, sizeof(req_attr), req_attr);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-int abis_nm_bs11_set_ext_time(struct gsm_bts *bts)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	struct bs11_date_time aet;
-
-	get_bs11_date_time(&aet);
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	/* SiemensHW CCTRL object */
-	fill_om_fom_hdr(oh, 2+sizeof(aet), NM_MT_BS11_SET_ATTR, NM_OC_SITE_MANAGER,
-			0xff, 0xff, 0xff);
-	msgb_tlv_put(msg, NM_ATT_BS11_ABIS_EXT_TIME, sizeof(aet), (uint8_t *) &aet);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-int abis_nm_bs11_get_bport_line_cfg(struct gsm_bts *bts, uint8_t bport)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	uint8_t attr = NM_ATT_BS11_LINE_CFG;
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 2+sizeof(attr), NM_MT_GET_ATTR,
-			NM_OC_BS11_BPORT, bport, 0xff, 0x02);
-	msgb_tlv_put(msg, NM_ATT_LIST_REQ_ATTR, sizeof(attr), &attr);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-int abis_nm_bs11_set_bport_line_cfg(struct gsm_bts *bts, uint8_t bport, enum abis_bs11_line_cfg line_cfg)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-	struct bs11_date_time aet;
-
-	get_bs11_date_time(&aet);
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 2, NM_MT_BS11_SET_ATTR, NM_OC_BS11_BPORT,
-			bport, 0xff, 0x02);
-	msgb_tv_put(msg, NM_ATT_BS11_LINE_CFG, line_cfg);
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-/* ip.access nanoBTS specific commands */
-static const char ipaccess_magic[] = "com.ipaccess";
-
-
-static int abis_nm_rx_ipacc(struct msgb *msg)
-{
-	struct in_addr addr;
-	struct abis_om_hdr *oh = msgb_l2(msg);
-	struct abis_om_fom_hdr *foh;
-	uint8_t idstrlen = oh->data[0];
-	struct tlv_parsed tp;
-	struct ipacc_ack_signal_data signal;
-	struct e1inp_sign_link *sign_link = msg->dst;
-
-	if (strncmp((char *)&oh->data[1], ipaccess_magic, idstrlen)) {
-		LOGP(DNM, LOGL_ERROR, "id string is not com.ipaccess !?!\n");
-		return -EINVAL;
-	}
-
-	foh = (struct abis_om_fom_hdr *) (oh->data + 1 + idstrlen);
-	abis_nm_tlv_parse(&tp, sign_link->trx->bts, foh->data, oh->length-sizeof(*foh));
-
-	abis_nm_debugp_foh(DNM, foh);
-
-	DEBUGPC(DNM, "IPACCESS(0x%02x): ", foh->msg_type);
-
-	switch (foh->msg_type) {
-	case NM_MT_IPACC_RSL_CONNECT_ACK:
-		DEBUGPC(DNM, "RSL CONNECT ACK ");
-		if (TLVP_PRESENT(&tp, NM_ATT_IPACC_DST_IP)) {
-			memcpy(&addr,
-				TLVP_VAL(&tp, NM_ATT_IPACC_DST_IP), sizeof(addr));
-
-			DEBUGPC(DNM, "IP=%s ", inet_ntoa(addr));
-		}
-		if (TLVP_PRESENT(&tp, NM_ATT_IPACC_DST_IP_PORT))
-			DEBUGPC(DNM, "PORT=%u ",
-				ntohs(*((uint16_t *)
-					TLVP_VAL(&tp, NM_ATT_IPACC_DST_IP_PORT))));
-		if (TLVP_PRESENT(&tp, NM_ATT_IPACC_STREAM_ID))
-			DEBUGPC(DNM, "STREAM=0x%02x ",
-					*TLVP_VAL(&tp, NM_ATT_IPACC_STREAM_ID));
-		DEBUGPC(DNM, "\n");
-		break;
-	case NM_MT_IPACC_RSL_CONNECT_NACK:
-		LOGP(DNM, LOGL_ERROR, "RSL CONNECT NACK ");
-		if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
-			LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n",
-				abis_nm_nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
-		else
-			LOGPC(DNM, LOGL_ERROR, "\n");
-		break;
-	case NM_MT_IPACC_SET_NVATTR_ACK:
-		DEBUGPC(DNM, "SET NVATTR ACK\n");
-		/* FIXME: decode and show the actual attributes */
-		break;
-	case NM_MT_IPACC_SET_NVATTR_NACK:
-		LOGP(DNM, LOGL_ERROR, "SET NVATTR NACK ");
-		if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
-			LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n",
-				abis_nm_nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
-		else
-			LOGPC(DNM, LOGL_ERROR, "\n");
-		break;
-	case NM_MT_IPACC_GET_NVATTR_ACK:
-		DEBUGPC(DNM, "GET NVATTR ACK\n");
-		/* FIXME: decode and show the actual attributes */
-		break;
-	case NM_MT_IPACC_GET_NVATTR_NACK:
-		LOGPC(DNM, LOGL_ERROR, "GET NVATTR NACK ");
-		if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
-			LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n",
-				abis_nm_nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
-		else
-			LOGPC(DNM, LOGL_ERROR, "\n");
-		break;
-	case NM_MT_IPACC_SET_ATTR_ACK:
-		DEBUGPC(DNM, "SET ATTR ACK\n");
-		break;
-	case NM_MT_IPACC_SET_ATTR_NACK:
-		LOGPC(DNM, LOGL_ERROR, "SET ATTR NACK ");
-		if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
-			LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n",
-				abis_nm_nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
-		else
-			LOGPC(DNM, LOGL_ERROR, "\n");
-		break;
-	default:
-		DEBUGPC(DNM, "unknown\n");
-		break;
-	}
-
-	/* signal handling */
-	switch  (foh->msg_type) {
-	case NM_MT_IPACC_RSL_CONNECT_NACK:
-	case NM_MT_IPACC_SET_NVATTR_NACK:
-	case NM_MT_IPACC_GET_NVATTR_NACK:
-		signal.trx = gsm_bts_trx_by_nr(sign_link->trx->bts, foh->obj_inst.trx_nr);
-		signal.msg_type = foh->msg_type;
-		osmo_signal_dispatch(SS_NM, S_NM_IPACC_NACK, &signal);
-		break;
-	case NM_MT_IPACC_SET_NVATTR_ACK:
-		signal.trx = gsm_bts_trx_by_nr(sign_link->trx->bts, foh->obj_inst.trx_nr);
-		signal.msg_type = foh->msg_type;
-		osmo_signal_dispatch(SS_NM, S_NM_IPACC_ACK, &signal);
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-/* send an ip-access manufacturer specific message */
-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)
-{
-	struct msgb *msg = nm_msgb_alloc();
-	struct abis_om_hdr *oh;
-	struct abis_om_fom_hdr *foh;
-	uint8_t *data;
-
-	/* construct the 12.21 OM header, observe the erroneous length */
-	oh = (struct abis_om_hdr *) msgb_put(msg, sizeof(*oh));
-	fill_om_hdr(oh, sizeof(*foh) + attr_len);
-	oh->mdisc = ABIS_OM_MDISC_MANUF;
-
-	/* add the ip.access magic */
-	data = msgb_put(msg, sizeof(ipaccess_magic)+1);
-	*data++ = sizeof(ipaccess_magic);
-	memcpy(data, ipaccess_magic, sizeof(ipaccess_magic));
-
-	/* fill the 12.21 FOM header */
-	foh = (struct abis_om_fom_hdr *) msgb_put(msg, sizeof(*foh));
-	foh->msg_type = msg_type;
-	foh->obj_class = obj_class;
-	foh->obj_inst.bts_nr = bts_nr;
-	foh->obj_inst.trx_nr = trx_nr;
-	foh->obj_inst.ts_nr = ts_nr;
-
-	if (attr && attr_len) {
-		data = msgb_put(msg, attr_len);
-		memcpy(data, attr, attr_len);
-	}
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-/* set some attributes in NVRAM */
-int abis_nm_ipaccess_set_nvattr(struct gsm_bts_trx *trx, uint8_t *attr,
-				int attr_len)
-{
-	return abis_nm_ipaccess_msg(trx->bts, NM_MT_IPACC_SET_NVATTR,
-				    NM_OC_BASEB_TRANSC, 0, trx->nr, 0xff, attr,
-				    attr_len);
-}
-
-int abis_nm_ipaccess_rsl_connect(struct gsm_bts_trx *trx,
-				 uint32_t ip, uint16_t port, uint8_t stream)
-{
-	struct in_addr ia;
-	uint8_t attr[] = { NM_ATT_IPACC_STREAM_ID, 0,
-			    NM_ATT_IPACC_DST_IP_PORT, 0, 0,
-			    NM_ATT_IPACC_DST_IP, 0, 0, 0, 0 };
-
-	int attr_len = sizeof(attr);
-
-	ia.s_addr = htonl(ip);
-	attr[1] = stream;
-	attr[3] = port >> 8;
-	attr[4] = port & 0xff;
-	*(uint32_t *)(attr+6) = ia.s_addr;
-
-	/* if ip == 0, we use the default IP */
-	if (ip == 0)
-		attr_len -= 5;
-
-	DEBUGP(DNM, "ip.access RSL CONNECT IP=%s PORT=%u STREAM=0x%02x\n",
-		inet_ntoa(ia), port, stream);
-
-	return abis_nm_ipaccess_msg(trx->bts, NM_MT_IPACC_RSL_CONNECT,
-				    NM_OC_BASEB_TRANSC, trx->bts->bts_nr,
-				    trx->nr, 0xff, attr, attr_len);
-}
-
-/* restart / reboot an ip.access nanoBTS */
-int abis_nm_ipaccess_restart(struct gsm_bts_trx *trx)
-{
-	struct abis_om_hdr *oh;
-	struct msgb *msg = nm_msgb_alloc();
-
-	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, 0, NM_MT_IPACC_RESTART, NM_OC_BASEB_TRANSC,
-			trx->bts->nr, trx->nr, 0xff);
-
-	return abis_nm_sendmsg_direct(trx->bts, msg);
-}
-
-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)
-{
-	return abis_nm_ipaccess_msg(bts, NM_MT_IPACC_SET_ATTR,
-				    obj_class, bts_nr, trx_nr, ts_nr,
-				     attr, attr_len);
-}
-
-void abis_nm_ipaccess_cgi(uint8_t *buf, struct gsm_bts *bts)
-{
-	/* we simply reuse the GSM48 function and overwrite the RAC
-	 * with the Cell ID */
-	gsm48_ra_id_by_bts(buf, bts);
-	*((uint16_t *)(buf + 5)) = htons(bts->cell_identity);
-}
-
-void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked)
-{
-	int new_state = locked ? NM_STATE_LOCKED : NM_STATE_UNLOCKED;
-
-	trx->mo.nm_state.administrative = new_state;
-	if (!trx->bts || !trx->bts->oml_link)
-		return;
-
-	abis_nm_chg_adm_state(trx->bts, NM_OC_RADIO_CARRIER,
-			      trx->bts->bts_nr, trx->nr, 0xff,
-			      new_state);
-}
-
-static const struct value_string ipacc_testres_names[] = {
-	{ NM_IPACC_TESTRES_SUCCESS,	"SUCCESS" },
-	{ NM_IPACC_TESTRES_TIMEOUT,	"TIMEOUT" },
-	{ NM_IPACC_TESTRES_NO_CHANS,	"NO CHANNELS" },
-	{ NM_IPACC_TESTRES_PARTIAL,	"PARTIAL" },
-	{ NM_IPACC_TESTRES_STOPPED,	"STOPPED" },
-	{ 0,				NULL }
-};
-
-const char *ipacc_testres_name(uint8_t res)
-{
-	return get_value_string(ipacc_testres_names, res);
-}
-
-void ipac_parse_cgi(struct cell_global_id *cid, const uint8_t *buf)
-{
-	cid->mcc = (buf[0] & 0xf) * 100;
-	cid->mcc += (buf[0] >> 4) *  10;
-	cid->mcc += (buf[1] & 0xf) *  1;
-
-	if (buf[1] >> 4 == 0xf) {
-		cid->mnc = (buf[2] & 0xf) * 10;
-		cid->mnc += (buf[2] >> 4) *  1;
-	} else {
-		cid->mnc = (buf[2] & 0xf) * 100;
-		cid->mnc += (buf[2] >> 4) *  10;
-		cid->mnc += (buf[1] >> 4) *   1;
-	}
-
-	cid->lac = ntohs(*((uint16_t *)&buf[3]));
-	cid->ci = ntohs(*((uint16_t *)&buf[5]));
-}
-
-/* parse BCCH information IEI from wire format to struct ipac_bcch_info */
-int ipac_parse_bcch_info(struct ipac_bcch_info *binf, uint8_t *buf)
-{
-	uint8_t *cur = buf;
-	uint16_t len __attribute__((unused));
-
-	memset(binf, 0, sizeof(*binf));
-
-	if (cur[0] != NM_IPAC_EIE_BCCH_INFO)
-		return -EINVAL;
-	cur++;
-
-	len = ntohs(*(uint16_t *)cur);
-	cur += 2;
-
-	binf->info_type = ntohs(*(uint16_t *)cur);
-	cur += 2;
-
-	if (binf->info_type & IPAC_BINF_FREQ_ERR_QUAL)
-		binf->freq_qual = *cur >> 2;
-
-	binf->arfcn = (*cur++ & 3) << 8;
-	binf->arfcn |= *cur++;
-
-	if (binf->info_type & IPAC_BINF_RXLEV)
-		binf->rx_lev = *cur & 0x3f;
-	cur++;
-
-	if (binf->info_type & IPAC_BINF_RXQUAL)
-		binf->rx_qual = *cur & 0x7;
-	cur++;
-
-	if (binf->info_type & IPAC_BINF_FREQ_ERR_QUAL)
-		binf->freq_err = ntohs(*(uint16_t *)cur);
-	cur += 2;
-
-	if (binf->info_type & IPAC_BINF_FRAME_OFFSET)
-		binf->frame_offset = ntohs(*(uint16_t *)cur);
-	cur += 2;
-
-	if (binf->info_type & IPAC_BINF_FRAME_NR_OFFSET)
-		binf->frame_nr_offset = ntohl(*(uint32_t *)cur);
-	cur += 4;
-
-#if 0
-	/* Somehow this is not set correctly */
-	if (binf->info_type & IPAC_BINF_BSIC)
-#endif
-		binf->bsic = *cur & 0x3f;
-	cur++;
-
-	ipac_parse_cgi(&binf->cgi, cur);
-	cur += 7;
-
-	if (binf->info_type & IPAC_BINF_NEIGH_BA_SI2) {
-		memcpy(binf->ba_list_si2, cur, sizeof(binf->ba_list_si2));
-		cur += sizeof(binf->ba_list_si2);
-	}
-
-	if (binf->info_type & IPAC_BINF_NEIGH_BA_SI2bis) {
-		memcpy(binf->ba_list_si2bis, cur,
-			sizeof(binf->ba_list_si2bis));
-		cur += sizeof(binf->ba_list_si2bis);
-	}
-
-	if (binf->info_type & IPAC_BINF_NEIGH_BA_SI2ter) {
-		memcpy(binf->ba_list_si2ter, cur,
-			sizeof(binf->ba_list_si2ter));
-		cur += sizeof(binf->ba_list_si2ter);
-	}
-
-	return 0;
-}
-
-void abis_nm_clear_queue(struct gsm_bts *bts)
-{
-	struct msgb *msg;
-
-	while (!llist_empty(&bts->abis_queue)) {
-		msg = msgb_dequeue(&bts->abis_queue);
-		msgb_free(msg);
-	}
-
-	bts->abis_nm_pend = 0;
-}
diff --git a/src/libbsc/abis_nm_ipaccess.c b/src/libbsc/abis_nm_ipaccess.c
deleted file mode 100644
index b822538..0000000
--- a/src/libbsc/abis_nm_ipaccess.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/* GSM Network Management (OML) messages on the A-bis interface 
- * Extensions for the ip.access A-bis over IP protocol*/
-
-/* (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/>.
- *
- */
-
-/* A list of all the 'embedded' attributes of ip.access */
-enum ipa_embedded_att {
-	IPA_ATT_ARFCN_WHITELIST		= 0x01,
-	IPA_ATT_ARFCN_BLACKLIST		= 0x02,
-	IPA_ATT_FREQ_ERR_LIST		= 0x03,
-	IPA_ATT_CHAN_USAGE_LIST		= 0x04,
-	IPA_ATT_BCCH_INF_TYPE		= 0x05,
-	IPA_ATT_BCCH_INF		= 0x06,
-	IPA_ATT_CONFIG			= 0x07,
-	IPA_ATT_RESULT_DETAILS		= 0x08,
-	IPA_ATT_RXLEV_THRESH		= 0x09,
-	IPA_ATT_FREQ_SYNC_OPT		= 0x0a,
-	IPA_ATT_MAC_ADDR		= 0x0b,
-	IPA_ATT_HW_SW_COMPAT_NR		= 0x0c,
-	IPA_ATT_MANUF_SER_NR		= 0x0d,
-	IPA_ATT_OEM_ID			= 0x0e,
-	IPA_ATT_DATETIME_MANUF		= 0x0f,
-	IPA_ATT_DATETIME_CALIB		= 0x10,
-	IPA_ATT_BEACON_INF		= 0x11,
-	IPA_ATT_FREQ_ERR		= 0x12,
-	IPA_ATT_SNMP_COMM_STRING	= 0x13,
-	IPA_ATT_SNMP_TRAP_ADDR		= 0x14,
-	IPA_ATT_SNMP_TRAP_PORT		= 0x15,
-	IPA_ATT_SNMP_MAN_ADDR		= 0x16,
-	IPA_ATT_SNMP_SYS_CONTACT	= 0x17,
-	IPA_ATT_FACTORY_ID		= 0x18,
-	IPA_ATT_FACTORY_SERIAL		= 0x19,
-	IPA_ATT_LOGGED_EVT_IND		= 0x1a,
-	IPA_ATT_LOCAL_ADD_TEXT		= 0x1b,
-	IPA_ATT_FREQ_BANDS		= 0x1c,
-	IPA_ATT_MAX_TA			= 0x1d,
-	IPA_ATT_CIPH_ALG		= 0x1e,
-	IPA_ATT_CHAN_TYPES		= 0x1f,
-	IPA_ATT_CHAN_MODES		= 0x20,
-	IPA_ATT_GPRS_CODING_SCHEMES	= 0x21,
-	IPA_ATT_RTP_FEATURES		= 0x22,
-	IPA_ATT_RSL_FEATURES		= 0x23,
-	IPA_ATT_BTS_HW_CLASS		= 0x24,
-	IPA_ATT_BTS_ID			= 0x25,
-	IPA_ATT_BCAST_L2_MSG		= 0x26,
-};
-
-/* append an ip.access channel list to the given msgb */
-static int ipa_chan_list_append(struct msgb *msg, uint8_t ie,
-				uint16_t *arfcns, int arfcn_count)
-{
-	int i;
-	uint8_t *u8;
-	uint16_t *u16;
-
-	/* tag */
-	u8 = msgb_push(msg, 1);
-	*u8 = ie;
-
-	/* length in octets */
-	u16 = msgb_push(msg, 2);
-	*u16 = htons(arfcn_count * 2);
-
-	for (i = 0; i < arfcn_count; i++) {
-		u16 = msgb_push(msg, 2);
-		*u16 = htons(arfcns[i]);
-	}
-
-	return 0;
-}
diff --git a/src/libbsc/abis_nm_vty.c b/src/libbsc/abis_nm_vty.c
deleted file mode 100644
index 6ec0a4a..0000000
--- a/src/libbsc/abis_nm_vty.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/* VTY interface for A-bis OML (Netowrk Management) */
-
-/* (C) 2009-2010 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/>.
- *
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdint.h>
-
-#include <arpa/inet.h>
-
-#include <osmocom/gsm/abis_nm.h>
-
-#include <openbsc/gsm_data.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/core/talloc.h>
-#include <openbsc/debug.h>
-#include <openbsc/signal.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/vty.h>
-
-#include <osmocom/vty/vty.h>
-#include <osmocom/vty/command.h>
-#include <osmocom/vty/logging.h>
-#include <osmocom/vty/telnet_interface.h>
-
-extern struct gsm_network *bsc_gsmnet;
-
-static struct cmd_node oml_node = {
-	OML_NODE,
-	"%s(oml)# ",
-	1,
-};
-
-struct oml_node_state {
-	struct gsm_bts *bts;
-	uint8_t obj_class;
-	uint8_t obj_inst[3];
-};
-
-static int dummy_config_write(struct vty *v)
-{
-	return CMD_SUCCESS;
-}
-
-/* FIXME: auto-generate those strings from the value_string lists */
-#define NM_OBJCLASS_VTY "(site-manager|bts|radio-carrier|baseband-transceiver|channel|adjc|handover|power-contorl|btse|rack|test|envabtse|bport|gprs-nse|gprs-cell|gprs-nsvc|siemenshw)"
-#define NM_OBJCLASS_VTY_HELP	"Site Manager Object\n"			\
-				"BTS Object\n"				\
-				"Radio Carrier Object\n"		\
-				"Baseband Transceiver Object\n"		\
-				"Channel (Timeslot) Object\n"		\
-				"Adjacent Object (Siemens)\n"		\
-				"Handover Object (Siemens)\n"		\
-				"Power Control Object (Siemens)\n"	\
-				"BTSE Object (Siemens)\n"		\
-				"Rack Object (Siemens)\n"		\
-				"Test Object (Siemens)\n"		\
-				"ENVABTSE Object (Siemens)\n"		\
-				"BPORT Object (Siemens)\n"		\
-				"GPRS NSE Object (ip.access/osmo-bts)\n"	\
-				"GPRS Cell Object (ip.acecss/osmo-bts)\n"	\
-				"GPRS NSVC Object (ip.acecss/osmo-bts)\n"	\
-				"SIEMENSHW Object (Siemens)\n"
-
-
-DEFUN(oml_class_inst, oml_class_inst_cmd,
-	"bts <0-255> oml class " NM_OBJCLASS_VTY
-					" instance <0-255> <0-255> <0-255>",
-	"BTS related commands\n" "BTS Number\n"
-	"Manipulate the OML managed objects\n"
-	"Object Class\n" 	NM_OBJCLASS_VTY_HELP
-	"Object Instance\n" "BTS Number\n" "TRX Number\n" "TS Number\n")
-{
-	struct gsm_bts *bts;
-	struct oml_node_state *oms;
-	int bts_nr = atoi(argv[0]);
-
-	bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr);
-	if (!bts) {
-		vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
-	if (!oms)
-		return CMD_WARNING;
-
-	oms->bts = bts;
-	oms->obj_class = get_string_value(abis_nm_obj_class_names, argv[1]);
-	oms->obj_inst[0] = atoi(argv[2]);
-	oms->obj_inst[1] = atoi(argv[3]);
-	oms->obj_inst[2] = atoi(argv[4]);
-
-	vty->index = oms;
-	vty->node = OML_NODE;
-
-	return CMD_SUCCESS;
-
-}
-
-DEFUN(oml_classnum_inst, oml_classnum_inst_cmd,
-	"bts <0-255> oml class <0-255> instance <0-255> <0-255> <0-255>",
-	"BTS related commands\n" "BTS Number\n"
-	"Manipulate the OML managed objects\n"
-	"Object Class\n" "Object Class\n"
-	"Object Instance\n" "BTS Number\n" "TRX Number\n" "TS Number\n")
-{
-	struct gsm_bts *bts;
-	struct oml_node_state *oms;
-	int bts_nr = atoi(argv[0]);
-
-	bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr);
-	if (!bts) {
-		vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
-	if (!oms)
-		return CMD_WARNING;
-
-	oms->bts = bts;
-	oms->obj_class = atoi(argv[1]);
-	oms->obj_inst[0] = atoi(argv[2]);
-	oms->obj_inst[1] = atoi(argv[3]);
-	oms->obj_inst[2] = atoi(argv[4]);
-
-	vty->index = oms;
-	vty->node = OML_NODE;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(oml_chg_adm_state, oml_chg_adm_state_cmd,
-	"change-adm-state (locked|unlocked|shutdown|null)",
-	"Change the Administrative State\n"
-	"Locked\n" "Unlocked\n" "Shutdown\n" "NULL\n")
-{
-	struct oml_node_state *oms = vty->index;
-	enum abis_nm_adm_state state;
-
-	state = get_string_value(abis_nm_adm_state_names, argv[0]);
-
-	abis_nm_chg_adm_state(oms->bts, oms->obj_class, oms->obj_inst[0],
-			      oms->obj_inst[1], oms->obj_inst[2], state);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(oml_opstart, oml_opstart_cmd,
-	"opstart", "Send an OPSTART message to the object")
-{
-	struct oml_node_state *oms = vty->index;
-
-	abis_nm_opstart(oms->bts, oms->obj_class, oms->obj_inst[0],
-			oms->obj_inst[1], oms->obj_inst[2]);
-
-	return CMD_SUCCESS;
-}
-
-int abis_nm_vty_init(void)
-{
-	install_element(ENABLE_NODE, &oml_class_inst_cmd);
-	install_element(ENABLE_NODE, &oml_classnum_inst_cmd);
-	install_node(&oml_node, dummy_config_write);
-
-	vty_install_default(OML_NODE);
-	install_element(OML_NODE, &oml_chg_adm_state_cmd);
-	install_element(OML_NODE, &oml_opstart_cmd);
-
-	return 0;
-}
diff --git a/src/libbsc/abis_om2000.c b/src/libbsc/abis_om2000.c
deleted file mode 100644
index 82a14b2..0000000
--- a/src/libbsc/abis_om2000.c
+++ /dev/null
@@ -1,2776 +0,0 @@
-/* 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,2016 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/>.
- *
- */
-
-
-#include <errno.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <stdint.h>
-
-#include <arpa/inet.h>
-
-#include <osmocom/core/msgb.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/fsm.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/debug.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/abis_om2000.h>
-#include <openbsc/signal.h>
-#include <osmocom/abis/e1_input.h>
-
-/* FIXME: move to libosmocore */
-struct osmo_fsm_inst *osmo_fsm_inst_alloc_child_id(struct osmo_fsm *fsm,
-						   struct osmo_fsm_inst *parent,
-						   uint32_t parent_term_event,
-						   const char *id)
-{
-	struct osmo_fsm_inst *fi;
-
-	fi = osmo_fsm_inst_alloc(fsm, parent, NULL, parent->log_level,
-				 id ? id : parent->id);
-	if (!fi) {
-		/* indicate immediate termination to caller */
-		osmo_fsm_inst_dispatch(parent, parent_term_event, NULL);
-		return NULL;
-	}
-
-	LOGPFSM(fi, "is child of %s\n", osmo_fsm_inst_name(parent));
-
-	fi->proc.parent = parent;
-	fi->proc.parent_term_event = parent_term_event;
-	llist_add(&fi->proc.child, &parent->proc.children);
-
-	return fi;
-}
-
-
-#define OM_ALLOC_SIZE		1024
-#define OM_HEADROOM_SIZE	128
-
-#define OM2K_TIMEOUT	10
-#define TRX_FSM_TIMEOUT	60
-#define BTS_FSM_TIMEOUT	60
-
-/* use following functions from abis_nm.c:
-	* om2k_msgb_alloc()
-	* abis_om2k_sendmsg()
- */
-
-struct abis_om2k_hdr {
-	struct abis_om_hdr om;
-	uint16_t msg_type;
-	struct abis_om2k_mo mo;
-	uint8_t data[0];
-} __attribute__ ((packed));
-
-enum abis_om2k_msgtype {
-	OM2K_MSGT_ABORT_SP_CMD			= 0x0000,
-	OM2K_MSGT_ABORT_SP_COMPL		= 0x0002,
-	OM2K_MSGT_ALARM_REP_ACK			= 0x0004,
-	OM2K_MSGT_ALARM_REP_NACK		= 0x0005,
-	OM2K_MSGT_ALARM_REP			= 0x0006,
-	OM2K_MSGT_ALARM_STATUS_REQ		= 0x0008,
-	OM2K_MSGT_ALARM_STATUS_REQ_ACK		= 0x000a,
-	OM2K_MSGT_ALARM_STATUS_REQ_REJ		= 0x000b,
-	OM2K_MSGT_ALARM_STATUS_RES_ACK		= 0x000c,
-	OM2K_MSGT_ALARM_STATUS_RES_NACK		= 0x000d,
-	OM2K_MSGT_ALARM_STATUS_RES		= 0x000e,
-	OM2K_MSGT_CAL_TIME_RESP			= 0x0010,
-	OM2K_MSGT_CAL_TIME_REJ			= 0x0011,
-	OM2K_MSGT_CAL_TIME_REQ			= 0x0012,
-
-	OM2K_MSGT_CON_CONF_REQ			= 0x0014,
-	OM2K_MSGT_CON_CONF_REQ_ACK		= 0x0016,
-	OM2K_MSGT_CON_CONF_REQ_REJ		= 0x0017,
-	OM2K_MSGT_CON_CONF_RES_ACK		= 0x0018,
-	OM2K_MSGT_CON_CONF_RES_NACK		= 0x0019,
-	OM2K_MSGT_CON_CONF_RES			= 0x001a,
-
-	OM2K_MSGT_CONNECT_CMD			= 0x001c,
-	OM2K_MSGT_CONNECT_COMPL			= 0x001e,
-	OM2K_MSGT_CONNECT_REJ			= 0x001f,
-
-	OM2K_MSGT_DISABLE_REQ			= 0x0028,
-	OM2K_MSGT_DISABLE_REQ_ACK		= 0x002a,
-	OM2K_MSGT_DISABLE_REQ_REJ		= 0x002b,
-	OM2K_MSGT_DISABLE_RES_ACK		= 0x002c,
-	OM2K_MSGT_DISABLE_RES_NACK		= 0x002d,
-	OM2K_MSGT_DISABLE_RES			= 0x002e,
-	OM2K_MSGT_DISCONNECT_CMD		= 0x0030,
-	OM2K_MSGT_DISCONNECT_COMPL		= 0x0032,
-	OM2K_MSGT_DISCONNECT_REJ		= 0x0033,
-	OM2K_MSGT_ENABLE_REQ			= 0x0034,
-	OM2K_MSGT_ENABLE_REQ_ACK		= 0x0036,
-	OM2K_MSGT_ENABLE_REQ_REJ		= 0x0037,
-	OM2K_MSGT_ENABLE_RES_ACK		= 0x0038,
-	OM2K_MSGT_ENABLE_RES_NACK		= 0x0039,
-	OM2K_MSGT_ENABLE_RES			= 0x003a,
-
-	OM2K_MSGT_FAULT_REP_ACK			= 0x0040,
-	OM2K_MSGT_FAULT_REP_NACK		= 0x0041,
-	OM2K_MSGT_FAULT_REP			= 0x0042,
-
-	OM2K_MSGT_IS_CONF_REQ			= 0x0060,
-	OM2K_MSGT_IS_CONF_REQ_ACK		= 0x0062,
-	OM2K_MSGT_IS_CONF_REQ_REJ		= 0x0063,
-	OM2K_MSGT_IS_CONF_RES_ACK		= 0x0064,
-	OM2K_MSGT_IS_CONF_RES_NACK		= 0x0065,
-	OM2K_MSGT_IS_CONF_RES			= 0x0066,
-
-	OM2K_MSGT_OP_INFO			= 0x0074,
-	OM2K_MSGT_OP_INFO_ACK			= 0x0076,
-	OM2K_MSGT_OP_INFO_REJ			= 0x0077,
-	OM2K_MSGT_RESET_CMD		 	= 0x0078,
-	OM2K_MSGT_RESET_COMPL			= 0x007a,
-	OM2K_MSGT_RESET_REJ			= 0x007b,
-	OM2K_MSGT_RX_CONF_REQ			= 0x007c,
-	OM2K_MSGT_RX_CONF_REQ_ACK		= 0x007e,
-	OM2K_MSGT_RX_CONF_REQ_REJ		= 0x007f,
-	OM2K_MSGT_RX_CONF_RES_ACK		= 0x0080,
-	OM2K_MSGT_RX_CONF_RES_NACK		= 0x0081,
-	OM2K_MSGT_RX_CONF_RES			= 0x0082,
-	OM2K_MSGT_START_REQ			= 0x0084,
-	OM2K_MSGT_START_REQ_ACK			= 0x0086,
-	OM2K_MSGT_START_REQ_REJ			= 0x0087,
-	OM2K_MSGT_START_RES_ACK			= 0x0088,
-	OM2K_MSGT_START_RES_NACK		= 0x0089,
-	OM2K_MSGT_START_RES			= 0x008a,
-	OM2K_MSGT_STATUS_REQ			= 0x008c,
-	OM2K_MSGT_STATUS_RESP			= 0x008e,
-	OM2K_MSGT_STATUS_REJ			= 0x008f,
-
-	OM2K_MSGT_TEST_REQ			= 0x0094,
-	OM2K_MSGT_TEST_REQ_ACK			= 0x0096,
-	OM2K_MSGT_TEST_REQ_REJ			= 0x0097,
-	OM2K_MSGT_TEST_RES_ACK			= 0x0098,
-	OM2K_MSGT_TEST_RES_NACK			= 0x0099,
-	OM2K_MSGT_TEST_RES			= 0x009a,
-
-	OM2K_MSGT_TF_CONF_REQ			= 0x00a0,
-	OM2K_MSGT_TF_CONF_REQ_ACK		= 0x00a2,
-	OM2K_MSGT_TF_CONF_REQ_REJ		= 0x00a3,
-	OM2K_MSGT_TF_CONF_RES_ACK		= 0x00a4,
-	OM2K_MSGT_TF_CONF_RES_NACK		= 0x00a5,
-	OM2K_MSGT_TF_CONF_RES			= 0x00a6,
-	OM2K_MSGT_TS_CONF_REQ			= 0x00a8,
-	OM2K_MSGT_TS_CONF_REQ_ACK		= 0x00aa,
-	OM2K_MSGT_TS_CONF_REQ_REJ		= 0x00ab,
-	OM2K_MSGT_TS_CONF_RES_ACK		= 0x00ac,
-	OM2K_MSGT_TS_CONF_RES_NACK		= 0x00ad,
-	OM2K_MSGT_TS_CONF_RES			= 0x00ae,
-	OM2K_MSGT_TX_CONF_REQ			= 0x00b0,
-	OM2K_MSGT_TX_CONF_REQ_ACK		= 0x00b2,
-	OM2K_MSGT_TX_CONF_REQ_REJ		= 0x00b3,
-	OM2K_MSGT_TX_CONF_RES_ACK		= 0x00b4,
-	OM2K_MSGT_TX_CONF_RES_NACK		= 0x00b5,
-	OM2K_MSGT_TX_CONF_RES			= 0x00b6,
-
-	OM2K_MSGT_CAPA_REQ			= 0x00e8,
-	OM2K_MSGT_CAPA_REQ_ACK			= 0x00ea,
-	OM2K_MSGT_CAPA_REQ_REJ			= 0x00eb,
-	OM2K_MSGT_CAPA_RES			= 0x00ee,
-	OM2K_MSGT_CAPA_RES_ACK			= 0x00ec,
-	OM2K_MSGT_CAPA_RES_NACK			= 0x00ed,
-
-	OM2K_MSGT_NEGOT_REQ_ACK			= 0x0104,
-	OM2K_MSGT_NEGOT_REQ_NACK		= 0x0105,
-	OM2K_MSGT_NEGOT_REQ			= 0x0106,
-};
-
-enum abis_om2k_dei {
-	OM2K_DEI_ACCORDANCE_IND			= 0x00,
-	OM2K_DEI_BCC				= 0x06,
-	OM2K_DEI_BS_AG_BKS_RES			= 0x07,
-	OM2K_DEI_BSIC				= 0x09,
-	OM2K_DEI_BA_PA_MFRMS			= 0x0a,
-	OM2K_DEI_CBCH_INDICATOR			= 0x0b,
-	OM2K_DEI_CCCH_OPTIONS			= 0x0c,
-	OM2K_DEI_CAL_TIME			= 0x0d,
-	OM2K_DEI_COMBINATION			= 0x0f,
-	OM2K_DEI_CON_CONN_LIST			= 0x10,
-	OM2K_DEI_DRX_DEV_MAX			= 0x12,
-	OM2K_DEI_END_LIST_NR			= 0x13,
-	OM2K_DEI_EXT_COND_MAP_1			= 0x14,
-	OM2K_DEI_EXT_COND_MAP_2			= 0x15,
-	OM2K_DEI_FILLING_MARKER			= 0x1c,
-	OM2K_DEI_FN_OFFSET			= 0x1d,
-	OM2K_DEI_FREQ_LIST			= 0x1e,
-	OM2K_DEI_FREQ_SPEC_RX			= 0x1f,
-	OM2K_DEI_FREQ_SPEC_TX			= 0x20,
-	OM2K_DEI_HSN				= 0x21,
-	OM2K_DEI_ICM_INDICATOR			= 0x22,
-	OM2K_DEI_INT_FAULT_MAP_1A		= 0x23,
-	OM2K_DEI_INT_FAULT_MAP_1B		= 0x24,
-	OM2K_DEI_INT_FAULT_MAP_2A		= 0x25,
-	OM2K_DEI_INT_FAULT_MAP_2A_EXT		= 0x26,
-	OM2K_DEI_IS_CONN_LIST			= 0x27,
-	OM2K_DEI_LIST_NR			= 0x28,
-	OM2K_DEI_LOCAL_ACCESS			= 0x2a,
-	OM2K_DEI_MAIO				= 0x2b,
-	OM2K_DEI_MO_STATE			= 0x2c,
-	OM2K_DEI_NY1				= 0x2d,
-	OM2K_DEI_OP_INFO			= 0x2e,
-	OM2K_DEI_POWER				= 0x2f,
-	OM2K_DEI_REASON_CODE			= 0x32,
-	OM2K_DEI_RX_DIVERSITY			= 0x33,
-	OM2K_DEI_REPL_UNIT_MAP			= 0x34,
-	OM2K_DEI_RESULT_CODE			= 0x35,
-	OM2K_DEI_T3105				= 0x38,
-	OM2K_DEI_TF_MODE			= 0x3a,
-	OM2K_DEI_TS_NR				= 0x3c,
-	OM2K_DEI_TSC				= 0x3d,
-	OM2K_DEI_BTS_VERSION			= 0x40,
-	OM2K_DEI_OML_IWD_VERSION		= 0x41,
-	OM2K_DEI_RSL_IWD_VERSION		= 0x42,
-	OM2K_DEI_OML_FUNC_MAP_1			= 0x43,
-	OM2K_DEI_OML_FUNC_MAP_2			= 0x44,
-	OM2K_DEI_RSL_FUNC_MAP_1			= 0x45,
-	OM2K_DEI_RSL_FUNC_MAP_2			= 0x46,
-	OM2K_DEI_EXT_RANGE			= 0x47,
-	OM2K_DEI_REQ_IND			= 0x48,
-	OM2K_DEI_REPL_UNIT_MAP_EXT		= 0x50,
-	OM2K_DEI_ICM_BOUND_PARAMS		= 0x74,
-	OM2K_DEI_LSC				= 0x79,
-	OM2K_DEI_LSC_FILT_TIME			= 0x7a,
-	OM2K_DEI_CALL_SUPV_TIME			= 0x7b,
-	OM2K_DEI_ICM_CHAN_RATE			= 0x7e,
-	OM2K_DEI_HW_INFO_SIG			= 0x84,
-	OM2K_DEI_TF_SYNC_SRC			= 0x86,
-	OM2K_DEI_TTA				= 0x87,
-	OM2K_DEI_CAPA_SIG			= 0x8a,
-	OM2K_DEI_NEGOT_REC1			= 0x90,
-	OM2K_DEI_NEGOT_REC2			= 0x91,
-	OM2K_DEI_ENCR_ALG			= 0x92,
-	OM2K_DEI_INTERF_REJ_COMB		= 0x94,
-	OM2K_DEI_FS_OFFSET			= 0x98,
-	OM2K_DEI_EXT_COND_MAP_2_EXT		= 0x9c,
-	OM2K_DEI_TSS_MO_STATE			= 0x9d,
-};
-
-const struct tlv_definition om2k_att_tlvdef = {
-	.def = {
-		[OM2K_DEI_ACCORDANCE_IND] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_BCC] =		{ TLV_TYPE_TV },
-		[OM2K_DEI_BS_AG_BKS_RES] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_BSIC] =		{ TLV_TYPE_TV },
-		[OM2K_DEI_BA_PA_MFRMS] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_CBCH_INDICATOR] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_INT_FAULT_MAP_1A] =	{ TLV_TYPE_FIXED, 6 },
-		[OM2K_DEI_INT_FAULT_MAP_1B] =	{ TLV_TYPE_FIXED, 6 },
-		[OM2K_DEI_INT_FAULT_MAP_2A] =	{ TLV_TYPE_FIXED, 6 },
-		[OM2K_DEI_INT_FAULT_MAP_2A_EXT]={ TLV_TYPE_FIXED, 6 },
-		[OM2K_DEI_CCCH_OPTIONS] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_CAL_TIME] =		{ TLV_TYPE_FIXED, 6 },
-		[OM2K_DEI_COMBINATION] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_CON_CONN_LIST] =	{ TLV_TYPE_TLV },
-		[OM2K_DEI_DRX_DEV_MAX] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_END_LIST_NR] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_EXT_COND_MAP_1] =	{ TLV_TYPE_FIXED, 2 },
-		[OM2K_DEI_EXT_COND_MAP_2] =	{ TLV_TYPE_FIXED, 2 },
-		[OM2K_DEI_FILLING_MARKER] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_FN_OFFSET] =		{ TLV_TYPE_FIXED, 2 },
-		[OM2K_DEI_FREQ_LIST] =		{ TLV_TYPE_TLV },
-		[OM2K_DEI_FREQ_SPEC_RX] =	{ TLV_TYPE_FIXED, 2 },
-		[OM2K_DEI_FREQ_SPEC_TX] =	{ TLV_TYPE_FIXED, 2 },
-		[OM2K_DEI_HSN] =		{ TLV_TYPE_TV },
-		[OM2K_DEI_ICM_INDICATOR] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_IS_CONN_LIST] =	{ TLV_TYPE_TLV },
-		[OM2K_DEI_LIST_NR] =		{ TLV_TYPE_TV },
-		[OM2K_DEI_LOCAL_ACCESS] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_MAIO] =		{ TLV_TYPE_TV },
-		[OM2K_DEI_MO_STATE] =		{ TLV_TYPE_TV },
-		[OM2K_DEI_NY1] =		{ TLV_TYPE_TV },
-		[OM2K_DEI_OP_INFO] =		{ TLV_TYPE_TV },
-		[OM2K_DEI_POWER] =		{ TLV_TYPE_TV },
-		[OM2K_DEI_REASON_CODE] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_RX_DIVERSITY] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_RESULT_CODE] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_T3105] = 		{ TLV_TYPE_TV },
-		[OM2K_DEI_TF_MODE] =		{ TLV_TYPE_TV },
-		[OM2K_DEI_TS_NR] =		{ TLV_TYPE_TV },
-		[OM2K_DEI_TSC] =		{ TLV_TYPE_TV },
-		[OM2K_DEI_BTS_VERSION] =	{ TLV_TYPE_FIXED, 12 },
-		[OM2K_DEI_OML_IWD_VERSION] =	{ TLV_TYPE_FIXED, 6 },
-		[OM2K_DEI_RSL_IWD_VERSION] =	{ TLV_TYPE_FIXED, 6 },
-		[OM2K_DEI_OML_FUNC_MAP_1] =	{ TLV_TYPE_TLV },
-		[OM2K_DEI_OML_FUNC_MAP_2] =	{ TLV_TYPE_TLV },
-		[OM2K_DEI_RSL_FUNC_MAP_1] =	{ TLV_TYPE_TLV },
-		[OM2K_DEI_RSL_FUNC_MAP_2] =	{ TLV_TYPE_TLV },
-		[OM2K_DEI_EXT_RANGE] =		{ TLV_TYPE_TV },
-		[OM2K_DEI_REQ_IND] =		{ TLV_TYPE_TV },
-		[OM2K_DEI_REPL_UNIT_MAP] =	{ TLV_TYPE_FIXED, 6 },
-		[OM2K_DEI_REPL_UNIT_MAP_EXT] =	{TLV_TYPE_FIXED, 6},
-		[OM2K_DEI_ICM_BOUND_PARAMS] =	{ TLV_TYPE_FIXED, 5 },
-		[OM2K_DEI_LSC] =		{ TLV_TYPE_TV },
-		[OM2K_DEI_LSC_FILT_TIME] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_CALL_SUPV_TIME] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_ICM_CHAN_RATE] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_HW_INFO_SIG] =	{ TLV_TYPE_FIXED, 2 },
-		[OM2K_DEI_TF_SYNC_SRC] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_TTA] =		{ TLV_TYPE_TV },
-		[OM2K_DEI_CAPA_SIG] =		{ TLV_TYPE_FIXED, 2 },
-		[OM2K_DEI_NEGOT_REC1] =		{ TLV_TYPE_TLV },
-		[OM2K_DEI_NEGOT_REC2] =		{ TLV_TYPE_TLV },
-		[OM2K_DEI_ENCR_ALG] =		{ TLV_TYPE_TV },
-		[OM2K_DEI_INTERF_REJ_COMB] =	{ TLV_TYPE_TV },
-		[OM2K_DEI_FS_OFFSET] =		{ TLV_TYPE_FIXED, 5 },
-		[OM2K_DEI_EXT_COND_MAP_2_EXT] = { TLV_TYPE_FIXED, 4 },
-		[OM2K_DEI_TSS_MO_STATE] = 	{ TLV_TYPE_FIXED, 4 },
-	},
-};
-
-static const struct value_string om2k_msgcode_vals[] = {
-	{ 0x0000, "Abort SP Command" },
-	{ 0x0002, "Abort SP Complete" },
-	{ 0x0004, "Alarm Report ACK" },
-	{ 0x0005, "Alarm Report NACK" },
-	{ 0x0006, "Alarm Report" },
-	{ 0x0008, "Alarm Status Request" },
-	{ 0x000a, "Alarm Status Request Accept" },
-	{ 0x000b, "Alarm Status Request Reject" },
-	{ 0x000c, "Alarm Status Result ACK" },
-	{ 0x000d, "Alarm Status Result NACK" },
-	{ 0x000e, "Alarm Status Result" },
-	{ 0x0010, "Calendar Time Response" },
-	{ 0x0011, "Calendar Time Reject" },
-	{ 0x0012, "Calendar Time Request" },
-	{ 0x0014, "CON Configuration Request" },
-	{ 0x0016, "CON Configuration Request Accept" },
-	{ 0x0017, "CON Configuration Request Reject" },
-	{ 0x0018, "CON Configuration Result ACK" },
-	{ 0x0019, "CON Configuration Result NACK" },
-	{ 0x001a, "CON Configuration Result" },
-	{ 0x001c, "Connect Command" },
-	{ 0x001e, "Connect Complete" },
-	{ 0x001f, "Connect Reject" },
-	{ 0x0028, "Disable Request" },
-	{ 0x002a, "Disable Request Accept" },
-	{ 0x002b, "Disable Request Reject" },
-	{ 0x002c, "Disable Result ACK" },
-	{ 0x002d, "Disable Result NACK" },
-	{ 0x002e, "Disable Result" },
-	{ 0x0030, "Disconnect Command" },
-	{ 0x0032, "Disconnect Complete" },
-	{ 0x0033, "Disconnect Reject" },
-	{ 0x0034, "Enable Request" },
-	{ 0x0036, "Enable Request Accept" },
-	{ 0x0037, "Enable Request Reject" },
-	{ 0x0038, "Enable Result ACK" },
-	{ 0x0039, "Enable Result NACK" },
-	{ 0x003a, "Enable Result" },
-	{ 0x003c, "Escape Downlink Normal" },
-	{ 0x003d, "Escape Downlink NACK" },
-	{ 0x003e, "Escape Uplink Normal" },
-	{ 0x003f, "Escape Uplink NACK" },
-	{ 0x0040, "Fault Report ACK" },
-	{ 0x0041, "Fault Report NACK" },
-	{ 0x0042, "Fault Report" },
-	{ 0x0044, "File Package End Command" },
-	{ 0x0046, "File Package End Result" },
-	{ 0x0047, "File Package End Reject" },
-	{ 0x0048, "File Relation Request" },
-	{ 0x004a, "File Relation Response" },
-	{ 0x004b, "File Relation Request Reject" },
-	{ 0x004c, "File Segment Transfer" },
-	{ 0x004e, "File Segment Transfer Complete" },
-	{ 0x004f, "File Segment Transfer Reject" },
-	{ 0x0050, "HW Information Request" },
-	{ 0x0052, "HW Information Request Accept" },
-	{ 0x0053, "HW Information Request Reject" },
-	{ 0x0054, "HW Information Result ACK" },
-	{ 0x0055, "HW Information Result NACK" },
-	{ 0x0056, "HW Information Result" },
-	{ 0x0060, "IS Configuration Request" },
-	{ 0x0062, "IS Configuration Request Accept" },
-	{ 0x0063, "IS Configuration Request Reject" },
-	{ 0x0064, "IS Configuration Result ACK" },
-	{ 0x0065, "IS Configuration Result NACK" },
-	{ 0x0066, "IS Configuration Result" },
-	{ 0x0068, "Load Data End" },
-	{ 0x006a, "Load Data End Result" },
-	{ 0x006b, "Load Data End Reject" },
-	{ 0x006c, "Load Data Init" },
-	{ 0x006e, "Load Data Init Accept" },
-	{ 0x006f, "Load Data Init Reject" },
-	{ 0x0070, "Loop Control Command" },
-	{ 0x0072, "Loop Control Complete" },
-	{ 0x0073, "Loop Control Reject" },
-	{ 0x0074, "Operational Information" },
-	{ 0x0076, "Operational Information Accept" },
-	{ 0x0077, "Operational Information Reject" },
-	{ 0x0078, "Reset Command" },
-	{ 0x007a, "Reset Complete" },
-	{ 0x007b, "Reset Reject" },
-	{ 0x007c, "RX Configuration Request" },
-	{ 0x007e, "RX Configuration Request Accept" },
-	{ 0x007f, "RX Configuration Request Reject" },
-	{ 0x0080, "RX Configuration Result ACK" },
-	{ 0x0081, "RX Configuration Result NACK" },
-	{ 0x0082, "RX Configuration Result" },
-	{ 0x0084, "Start Request" },
-	{ 0x0086, "Start Request Accept" },
-	{ 0x0087, "Start Request Reject" },
-	{ 0x0088, "Start Result ACK" },
-	{ 0x0089, "Start Result NACK" },
-	{ 0x008a, "Start Result" },
-	{ 0x008c, "Status Request" },
-	{ 0x008e, "Status Response" },
-	{ 0x008f, "Status Reject" },
-	{ 0x0094, "Test Request" },
-	{ 0x0096, "Test Request Accept" },
-	{ 0x0097, "Test Request Reject" },
-	{ 0x0098, "Test Result ACK" },
-	{ 0x0099, "Test Result NACK" },
-	{ 0x009a, "Test Result" },
-	{ 0x00a0, "TF Configuration Request" },
-	{ 0x00a2, "TF Configuration Request Accept" },
-	{ 0x00a3, "TF Configuration Request Reject" },
-	{ 0x00a4, "TF Configuration Result ACK" },
-	{ 0x00a5, "TF Configuration Result NACK" },
-	{ 0x00a6, "TF Configuration Result" },
-	{ 0x00a8, "TS Configuration Request" },
-	{ 0x00aa, "TS Configuration Request Accept" },
-	{ 0x00ab, "TS Configuration Request Reject" },
-	{ 0x00ac, "TS Configuration Result ACK" },
-	{ 0x00ad, "TS Configuration Result NACK" },
-	{ 0x00ae, "TS Configuration Result" },
-	{ 0x00b0, "TX Configuration Request" },
-	{ 0x00b2, "TX Configuration Request Accept" },
-	{ 0x00b3, "TX Configuration Request Reject" },
-	{ 0x00b4, "TX Configuration Result ACK" },
-	{ 0x00b5, "TX Configuration Result NACK" },
-	{ 0x00b6, "TX Configuration Result" },
-	{ 0x00bc, "DIP Alarm Report ACK" },
-	{ 0x00bd, "DIP Alarm Report NACK" },
-	{ 0x00be, "DIP Alarm Report" },
-	{ 0x00c0, "DIP Alarm Status Request" },
-	{ 0x00c2, "DIP Alarm Status Response" },
-	{ 0x00c3, "DIP Alarm Status Reject" },
-	{ 0x00c4, "DIP Quality Report I ACK" },
-	{ 0x00c5, "DIP Quality Report I NACK" },
-	{ 0x00c6, "DIP Quality Report I" },
-	{ 0x00c8, "DIP Quality Report II ACK" },
-	{ 0x00c9, "DIP Quality Report II NACK" },
-	{ 0x00ca, "DIP Quality Report II" },
-	{ 0x00dc, "DP Configuration Request" },
-	{ 0x00de, "DP Configuration Request Accept" },
-	{ 0x00df, "DP Configuration Request Reject" },
-	{ 0x00e0, "DP Configuration Result ACK" },
-	{ 0x00e1, "DP Configuration Result NACK" },
-	{ 0x00e2, "DP Configuration Result" },
-	{ 0x00e4, "Capabilities HW Info Report ACK" },
-	{ 0x00e5, "Capabilities HW Info Report NACK" },
-	{ 0x00e6, "Capabilities HW Info Report" },
-	{ 0x00e8, "Capabilities Request" },
-	{ 0x00ea, "Capabilities Request Accept" },
-	{ 0x00eb, "Capabilities Request Reject" },
-	{ 0x00ec, "Capabilities Result ACK" },
-	{ 0x00ed, "Capabilities Result NACK" },
-	{ 0x00ee, "Capabilities Result" },
-	{ 0x00f0, "FM Configuration Request" },
-	{ 0x00f2, "FM Configuration Request Accept" },
-	{ 0x00f3, "FM Configuration Request Reject" },
-	{ 0x00f4, "FM Configuration Result ACK" },
-	{ 0x00f5, "FM Configuration Result NACK" },
-	{ 0x00f6, "FM Configuration Result" },
-	{ 0x00f8, "FM Report Request" },
-	{ 0x00fa, "FM Report Response" },
-	{ 0x00fb, "FM Report Reject" },
-	{ 0x00fc, "FM Start Command" },
-	{ 0x00fe, "FM Start Complete" },
-	{ 0x00ff, "FM Start Reject" },
-	{ 0x0100, "FM Stop Command" },
-	{ 0x0102, "FM Stop Complete" },
-	{ 0x0103, "FM Stop Reject" },
-	{ 0x0104, "Negotiation Request ACK" },
-	{ 0x0105, "Negotiation Request NACK" },
-	{ 0x0106, "Negotiation Request" },
-	{ 0x0108, "BTS Initiated Request ACK" },
-	{ 0x0109, "BTS Initiated Request NACK" },
-	{ 0x010a, "BTS Initiated Request" },
-	{ 0x010c, "Radio Channels Release Command" },
-	{ 0x010e, "Radio Channels Release Complete" },
-	{ 0x010f, "Radio Channels Release Reject" },
-	{ 0x0118, "Feature Control Command" },
-	{ 0x011a, "Feature Control Complete" },
-	{ 0x011b, "Feature Control Reject" },
-
-	{ 0, NULL }
-};
-
-/* TS 12.21 Section 9.4: Attributes */
-static const struct value_string om2k_attr_vals[] = {
-	{ 0x00, "Accordance indication" },
-	{ 0x01, "Alarm Id" },
-	{ 0x02, "Alarm Data" },
-	{ 0x03, "Alarm Severity" },
-	{ 0x04, "Alarm Status" },
-	{ 0x05, "Alarm Status Type" },
-	{ 0x06, "BCC" },
-	{ 0x07, "BS_AG_BKS_RES" },
-	{ 0x09, "BSIC" },
-	{ 0x0a, "BA_PA_MFRMS" },
-	{ 0x0b, "CBCH Indicator" },
-	{ 0x0c, "CCCH Options" },
-	{ 0x0d, "Calendar Time" },
-	{ 0x0f, "Channel Combination" },
-	{ 0x10, "CON Connection List" },
-	{ 0x11, "Data End Indication" },
-	{ 0x12, "DRX_DEV_MAX" },
-	{ 0x13, "End List Number" },
-	{ 0x14, "External Condition Map Class 1" },
-	{ 0x15, "External Condition Map Class 2" },
-	{ 0x16, "File Relation Indication" },
-	{ 0x17, "File Revision" },
-	{ 0x18, "File Segment Data" },
-	{ 0x19, "File Segment Length" },
-	{ 0x1a, "File Segment Sequence Number" },
-	{ 0x1b, "File Size" },
-	{ 0x1c, "Filling Marker" },
-	{ 0x1d, "FN Offset" },
-	{ 0x1e, "Frequency List" },
-	{ 0x1f, "Frequency Specifier RX" },
-	{ 0x20, "Frequency Specifier TX" },
-	{ 0x21, "HSN" },
-	{ 0x22, "ICM Indicator" },
-	{ 0x23, "Internal Fault Map Class 1A" },
-	{ 0x24, "Internal Fault Map Class 1B" },
-	{ 0x25, "Internal Fault Map Class 2A" },
-	{ 0x26, "Internal Fault Map Class 2A Extension" },
-	{ 0x27, "IS Connection List" },
-	{ 0x28, "List Number" },
-	{ 0x29, "File Package State Indication" },
-	{ 0x2a, "Local Access State" },
-	{ 0x2b, "MAIO" },
-	{ 0x2c, "MO State" },
-	{ 0x2d, "Ny1" },
-	{ 0x2e, "Operational Information" },
-	{ 0x2f, "Power" },
-	{ 0x30, "RU Position Data" },
-	{ 0x31, "Protocol Error" },
-	{ 0x32, "Reason Code" },
-	{ 0x33, "Receiver Diversity" },
-	{ 0x34, "Replacement Unit Map" },
-	{ 0x35, "Result Code" },
-	{ 0x36, "RU Revision Data" },
-	{ 0x38, "T3105" },
-	{ 0x39, "Test Loop Setting" },
-	{ 0x3a, "TF Mode" },
-	{ 0x3b, "TF Compensation Value" },
-	{ 0x3c, "Time Slot Number" },
-	{ 0x3d, "TSC" },
-	{ 0x3e, "RU Logical Id" },
-	{ 0x3f, "RU Serial Number Data" },
-	{ 0x40, "BTS Version" },
-	{ 0x41, "OML IWD Version" },
-	{ 0x42, "RWL IWD Version" },
-	{ 0x43, "OML Function Map 1" },
-	{ 0x44, "OML Function Map 2" },
-	{ 0x45, "RSL Function Map 1" },
-	{ 0x46, "RSL Function Map 2" },
-	{ 0x47, "Extended Range Indicator" },
-	{ 0x48, "Request Indicators" },
-	{ 0x49, "DIP Alarm Condition Map" },
-	{ 0x4a, "ES Incoming" },
-	{ 0x4b, "ES Outgoing" },
-	{ 0x4e, "SES Incoming" },
-	{ 0x4f, "SES Outgoing" },
-	{ 0x50, "Replacement Unit Map Extension" },
-	{ 0x52, "UAS Incoming" },
-	{ 0x53, "UAS Outgoing" },
-	{ 0x58, "DF Incoming" },
-	{ 0x5a, "DF Outgoing" },
-	{ 0x5c, "SF" },
-	{ 0x60, "S Bits Setting" },
-	{ 0x61, "CRC-4 Use Option" },
-	{ 0x62, "T Parameter" },
-	{ 0x63, "N Parameter" },
-	{ 0x64, "N1 Parameter" },
-	{ 0x65, "N3 Parameter" },
-	{ 0x66, "N4 Parameter" },
-	{ 0x67, "P Parameter" },
-	{ 0x68, "Q Parameter" },
-	{ 0x69, "BI_Q1" },
-	{ 0x6a, "BI_Q2" },
-	{ 0x74, "ICM Boundary Parameters" },
-	{ 0x77, "AFT" },
-	{ 0x78, "AFT RAI" },
-	{ 0x79, "Link Supervision Control" },
-	{ 0x7a, "Link Supervision Filtering Time" },
-	{ 0x7b, "Call Supervision Time" },
-	{ 0x7c, "Interval Length UAS Incoming" },
-	{ 0x7d, "Interval Length UAS Outgoing" },
-	{ 0x7e, "ICM Channel Rate" },
-	{ 0x7f, "Attribute Identifier" },
-	{ 0x80, "FM Frequency List" },
-	{ 0x81, "FM Frequency Report" },
-	{ 0x82, "FM Percentile" },
-	{ 0x83, "FM Clear Indication" },
-	{ 0x84, "HW Info Signature" },
-	{ 0x85, "MO Record" },
-	{ 0x86, "TF Synchronisation Source" },
-	{ 0x87, "TTA" },
-	{ 0x88, "End Segment Number" },
-	{ 0x89, "Segment Number" },
-	{ 0x8a, "Capabilities Signature" },
-	{ 0x8c, "File Relation List" },
-	{ 0x90, "Negotiation Record I" },
-	{ 0x91, "Negotiation Record II" },
-	{ 0x92, "Encryption Algorithm" },
-	{ 0x94, "Interference Rejection Combining" },
-	{ 0x95, "Dedication Information" },
-	{ 0x97, "Feature Code" },
-	{ 0x98, "FS Offset" },
-	{ 0x99, "ESB Timeslot" },
-	{ 0x9a, "Master TG Instance" },
-	{ 0x9b, "Master TX Chain Delay" },
-	{ 0x9c, "External Condition Class 2 Extension" },
-	{ 0x9d, "TSs MO State" },
-	{ 0, NULL }
-};
-
-const struct value_string om2k_mo_class_short_vals[] = {
-	{ 0x01, "TRXC" },
-	{ 0x03, "TS" },
-	{ 0x04, "TF" },
-	{ 0x05, "IS" },
-	{ 0x06, "CON" },
-	{ 0x07, "DP" },
-	{ 0x0a, "CF" },
-	{ 0x0b, "TX" },
-	{ 0x0c, "RX" },
-	{ 0, NULL }
-};
-
-const struct value_string om2k_result_strings[] = {
-	{ 0x02, "Wrong state or out of sequence" },
-	{ 0x03, "File error" },
-	{ 0x04, "Fault, unspecified" },
-	{ 0x05, "Tuning fault" },
-	{ 0x06, "Protocol error" },
-	{ 0x07, "MO not connected" },
-	{ 0x08, "Parameter error" },
-	{ 0x09, "Optional function not supported" },
-	{ 0x0a, "Local access state LOCALLY DISCONNECTED" },
-	{ 0, NULL }
-};
-
-const struct value_string om2k_accordance_strings[] = {
-	{ 0x00, "Data according to request" },
-	{ 0x01, "Data not according to request" },
-	{ 0x02, "Inconsistent MO data" },
-	{ 0x03, "Capability constraint violation" },
-	{ 0, NULL }
-};
-
-const struct value_string om2k_mostate_vals[] = {
-	{ 0x00, "RESET" },
-	{ 0x01, "STARTED" },
-	{ 0x02, "ENABLED" },
-	{ 0x03, "DISABLED" },
-	{ 0, NULL }
-};
-
-/* entire decoded OM2K message (header + parsed TLV) */
-struct om2k_decoded_msg {
-	struct abis_om2k_hdr o2h;
-	uint16_t msg_type;
-	struct tlv_parsed tp;
-};
-
-/* resolve the OM2000 Managed Object by BTS + MO Address */
-static struct om2k_mo *
-get_om2k_mo(struct gsm_bts *bts, const struct abis_om2k_mo *abis_mo)
-{
-	struct om2k_mo *mo = NULL;
-	struct gsm_bts_trx *trx;
-
-	switch (abis_mo->class) {
-	case OM2K_MO_CLS_CF:
-		mo = &bts->rbs2000.cf.om2k_mo;
-		break;
-	case OM2K_MO_CLS_CON:
-		mo = &bts->rbs2000.con.om2k_mo;
-		break;
-	case OM2K_MO_CLS_IS:
-		mo = &bts->rbs2000.is.om2k_mo;
-		break;
-	case OM2K_MO_CLS_TF:
-		mo = &bts->rbs2000.tf.om2k_mo;
-		break;
-
-	case OM2K_MO_CLS_TRXC:
-		trx = gsm_bts_trx_num(bts, abis_mo->inst);
-		if (!trx)
-			return NULL;
-		mo = &trx->rbs2000.trxc.om2k_mo;
-		break;
-	case OM2K_MO_CLS_TX:
-		trx = gsm_bts_trx_num(bts, abis_mo->inst);
-		if (!trx)
-			return NULL;
-		mo = &trx->rbs2000.tx.om2k_mo;
-		break;
-	case OM2K_MO_CLS_RX:
-		trx = gsm_bts_trx_num(bts, abis_mo->inst);
-		if (!trx)
-			return NULL;
-		mo = &trx->rbs2000.rx.om2k_mo;
-		break;
-	case OM2K_MO_CLS_TS:
-		trx = gsm_bts_trx_num(bts, abis_mo->assoc_so);
-		if (!trx)
-			return NULL;
-		if (abis_mo->inst >= ARRAY_SIZE(trx->ts))
-			return NULL;
-		mo = &trx->ts[abis_mo->inst].rbs2000.om2k_mo;
-		break;
-	default:
-		return NULL;
-	};
-
-	return mo;
-}
-
-static struct msgb *om2k_msgb_alloc(void)
-{
-	return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE,
-				   "OM2000");
-}
-
-static int abis_om2k_tlv_parse(struct tlv_parsed *tp, const uint8_t *buf, int len)
-{
-	return tlv_parse(tp, &om2k_att_tlvdef, buf, len, 0, 0);
-}
-
-static int abis_om2k_msg_tlv_parse(struct tlv_parsed *tp, struct abis_om2k_hdr *oh)
-{
-	return abis_om2k_tlv_parse(tp, oh->data, oh->om.length - 6);
-}
-
-/* decode/parse the message */
-static int om2k_decode_msg(struct om2k_decoded_msg *odm, struct msgb *msg)
-{
-	struct abis_om2k_hdr *o2h = msgb_l2(msg);
-	odm->msg_type = ntohs(o2h->msg_type);
-	odm->o2h = *o2h;
-	return abis_om2k_msg_tlv_parse(&odm->tp, o2h);
-}
-
-static char *om2k_mo_name(const struct abis_om2k_mo *mo)
-{
-	static char mo_buf[64];
-
-	memset(mo_buf, 0, sizeof(mo_buf));
-	snprintf(mo_buf, sizeof(mo_buf), "%s/%02x/%02x/%02x",
-		 get_value_string(om2k_mo_class_short_vals, mo->class),
-		 mo->bts, mo->assoc_so, mo->inst);
-	return mo_buf;
-}
-
-/* resolve the gsm_nm_state data structure for a given MO */
-static struct gsm_nm_state *
-mo2nm_state(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
-{
-	struct gsm_bts_trx *trx;
-	struct gsm_nm_state *nm_state = NULL;
-
-	switch (mo->class) {
-	case OM2K_MO_CLS_TRXC:
-		trx = gsm_bts_trx_num(bts, mo->inst);
-		if (!trx)
-			return NULL;
-		nm_state = &trx->mo.nm_state;
-		break;
-	case OM2K_MO_CLS_TS:
-		trx = gsm_bts_trx_num(bts, mo->assoc_so);
-		if (!trx)
-			return NULL;
-		if (mo->inst >= ARRAY_SIZE(trx->ts))
-			return NULL;
-		nm_state = &trx->ts[mo->inst].mo.nm_state;
-		break;
-	case OM2K_MO_CLS_TF:
-		nm_state = &bts->rbs2000.tf.mo.nm_state;
-		break;
-	case OM2K_MO_CLS_IS:
-		nm_state = &bts->rbs2000.is.mo.nm_state;
-		break;
-	case OM2K_MO_CLS_CON:
-		nm_state = &bts->rbs2000.con.mo.nm_state;
-		break;
-	case OM2K_MO_CLS_DP:
-		nm_state = &bts->rbs2000.con.mo.nm_state;
-		break;
-	case OM2K_MO_CLS_CF:
-		nm_state = &bts->mo.nm_state;
-		break;
-	case OM2K_MO_CLS_TX:
-		trx = gsm_bts_trx_num(bts, mo->inst);
-		if (!trx)
-			return NULL;
-		/* FIXME */
-		break;
-	case OM2K_MO_CLS_RX:
-		trx = gsm_bts_trx_num(bts, mo->inst);
-		if (!trx)
-			return NULL;
-		/* FIXME */
-		break;
-	}
-
-	return nm_state;
-}
-
-static void *mo2obj(struct gsm_bts *bts, struct abis_om2k_mo *mo)
-{
-	struct gsm_bts_trx *trx;
-
-	switch (mo->class) {
-	case OM2K_MO_CLS_TX:
-	case OM2K_MO_CLS_RX:
-	case OM2K_MO_CLS_TRXC:
-		return gsm_bts_trx_num(bts, mo->inst);
-	case OM2K_MO_CLS_TS:
-		trx = gsm_bts_trx_num(bts, mo->assoc_so);
-		if (!trx)
-			return NULL;
-		if (mo->inst >= ARRAY_SIZE(trx->ts))
-			return NULL;
-		return &trx->ts[mo->inst];
-	case OM2K_MO_CLS_TF:
-	case OM2K_MO_CLS_IS:
-	case OM2K_MO_CLS_CON:
-	case OM2K_MO_CLS_DP:
-	case OM2K_MO_CLS_CF:
-		return bts;
-	}
-
-	return NULL;
-}
-
-static void update_mo_state(struct gsm_bts *bts, struct abis_om2k_mo *mo,
-			    uint8_t mo_state)
-{
-	struct gsm_nm_state *nm_state = mo2nm_state(bts, mo);
-	struct gsm_nm_state new_state;
-	struct nm_statechg_signal_data nsd;
-
-	if (!nm_state)
-		return;
-
-	new_state = *nm_state;
-	/* NOTICE: 12.21 Availability state values != OM2000 */
-	new_state.availability = mo_state;
-
-	memset(&nsd, 0, sizeof(nsd));
-
-	nsd.bts = bts;
-	nsd.obj = mo2obj(bts, mo);
-	nsd.old_state = nm_state;
-	nsd.new_state = &new_state;
-	nsd.om2k_mo = mo;
-
-	osmo_signal_dispatch(SS_NM, S_NM_STATECHG_ADM, &nsd);
-
-	nm_state->availability = new_state.availability;
-}
-
-static void update_op_state(struct gsm_bts *bts, const struct abis_om2k_mo *mo,
-			    uint8_t op_state)
-{
-	struct gsm_nm_state *nm_state = mo2nm_state(bts, mo);
-	struct gsm_nm_state new_state;
-
-	if (!nm_state)
-		return;
-
-	new_state = *nm_state;
-	switch (op_state) {
-	case 1:
-		new_state.operational = NM_OPSTATE_ENABLED;
-		break;
-	case 0:
-		new_state.operational = NM_OPSTATE_DISABLED;
-		break;
-	default:
-		new_state.operational = NM_OPSTATE_NULL;
-		break;
-	}
-
-	nm_state->operational = new_state.operational;
-}
-
-static int abis_om2k_sendmsg(struct gsm_bts *bts, struct msgb *msg)
-{
-	struct abis_om2k_hdr *o2h;
-	struct gsm_bts_trx *trx;
-
-	msg->l2h = msg->data;
-	o2h = (struct abis_om2k_hdr *) msg->l2h;
-
-	/* Compute the length in the OML header */
-	o2h->om.length = 6 + msgb_l2len(msg)-sizeof(*o2h);
-
-	switch (o2h->mo.class) {
-	case OM2K_MO_CLS_TRXC:
-	case OM2K_MO_CLS_TX:
-	case OM2K_MO_CLS_RX:
-		/* Route through per-TRX OML Link to the appropriate TRX */
-		trx = gsm_bts_trx_by_nr(bts, o2h->mo.inst);
-		if (!trx) {
-			LOGP(DNM, LOGL_ERROR, "MO=%s Tx Dropping msg to "
-				"non-existing TRX\n", om2k_mo_name(&o2h->mo));
-			return -ENODEV;
-		}
-		msg->dst = trx->oml_link;
-		break;
-	case OM2K_MO_CLS_TS:
-		/* Route through per-TRX OML Link to the appropriate TRX */
-		trx = gsm_bts_trx_by_nr(bts, o2h->mo.assoc_so);
-		if (!trx) {
-			LOGP(DNM, LOGL_ERROR, "MO=%s Tx Dropping msg to "
-				"non-existing TRX\n", om2k_mo_name(&o2h->mo));
-			return -ENODEV;
-		}
-		msg->dst = trx->oml_link;
-		break;
-	default:
-		/* Route through the IXU/DXU OML Link */
-		msg->dst = bts->oml_link;
-		break;
-	}
-
-	return _abis_nm_sendmsg(msg);
-}
-
-static void fill_om2k_hdr(struct abis_om2k_hdr *o2h, const struct abis_om2k_mo *mo,
-			  uint16_t msg_type)
-{
-	o2h->om.mdisc = ABIS_OM_MDISC_FOM;
-	o2h->om.placement = ABIS_OM_PLACEMENT_ONLY;
-	o2h->om.sequence = 0;
-	/* We fill o2h->om.length later during om2k_sendmsg() */
-	o2h->msg_type = htons(msg_type);
-	memcpy(&o2h->mo, mo, sizeof(o2h->mo));
-}
-
-static int abis_om2k_cal_time_resp(struct gsm_bts *bts)
-{
-	struct msgb *msg = om2k_msgb_alloc();
-	struct abis_om2k_hdr *o2k;
-	time_t tm_t;
-	struct tm *tm;
-
-	o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
-	fill_om2k_hdr(o2k, &bts->rbs2000.cf.om2k_mo.addr,
-			OM2K_MSGT_CAL_TIME_RESP);
-
-	tm_t = time(NULL);
-	tm = localtime(&tm_t);
-
-	msgb_put_u8(msg, OM2K_DEI_CAL_TIME);
-	msgb_put_u8(msg, tm->tm_year % 100);
-	msgb_put_u8(msg, tm->tm_mon + 1);
-	msgb_put_u8(msg, tm->tm_mday);
-	msgb_put_u8(msg, tm->tm_hour);
-	msgb_put_u8(msg, tm->tm_min);
-	msgb_put_u8(msg, tm->tm_sec);
-
-	return abis_om2k_sendmsg(bts, msg);
-}
-
-static int abis_om2k_tx_simple(struct gsm_bts *bts, const struct abis_om2k_mo *mo,
-				uint8_t msg_type)
-{
-	struct msgb *msg = om2k_msgb_alloc();
-	struct abis_om2k_hdr *o2k;
-
-	o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
-	fill_om2k_hdr(o2k, mo, msg_type);
-
-	DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(mo),
-		get_value_string(om2k_msgcode_vals, msg_type));
-
-	return abis_om2k_sendmsg(bts, msg);
-}
-
-int abis_om2k_tx_reset_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
-{
-	return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_RESET_CMD);
-}
-
-int abis_om2k_tx_start_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
-{
-	return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_START_REQ);
-}
-
-int abis_om2k_tx_status_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
-{
-	return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_STATUS_REQ);
-}
-
-int abis_om2k_tx_connect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
-{
-	return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_CONNECT_CMD);
-}
-
-int abis_om2k_tx_disconnect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
-{
-	return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_DISCONNECT_CMD);
-}
-
-int abis_om2k_tx_test_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
-{
-	return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_TEST_REQ);
-}
-
-int abis_om2k_tx_enable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
-{
-	return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_ENABLE_REQ);
-}
-
-int abis_om2k_tx_disable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
-{
-	return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_DISABLE_REQ);
-}
-
-int abis_om2k_tx_op_info(struct gsm_bts *bts, const struct abis_om2k_mo *mo,
-			 uint8_t operational)
-{
-	struct msgb *msg = om2k_msgb_alloc();
-	struct abis_om2k_hdr *o2k;
-
-	o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
-	fill_om2k_hdr(o2k, mo, OM2K_MSGT_OP_INFO);
-
-	msgb_tv_put(msg, OM2K_DEI_OP_INFO, operational);
-
-	DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(mo),
-		get_value_string(om2k_msgcode_vals, OM2K_MSGT_OP_INFO));
-
-	/* we update the state here... and send the signal at ACK */
-	update_op_state(bts, mo, operational);
-
-	return abis_om2k_sendmsg(bts, msg);
-}
-
-int abis_om2k_tx_cap_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo)
-{
-	return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_CAPA_REQ);
-}
-
-static void om2k_fill_is_conn_grp(struct om2k_is_conn_grp *grp, uint16_t icp1,
-				  uint16_t icp2, uint8_t cont_idx)
-{
-	grp->icp1 = htons(icp1);
-	grp->icp2 = htons(icp2);
-	grp->cont_idx = cont_idx;
-}
-
-int abis_om2k_tx_is_conf_req(struct gsm_bts *bts)
-{
-	struct msgb *msg = om2k_msgb_alloc();
-	struct abis_om2k_hdr *o2k;
-	struct is_conn_group *grp;
-	unsigned int num_grps = 0, i = 0;
-	struct om2k_is_conn_grp *cg;
-
-	/* count number of groups in linked list */
-	llist_for_each_entry(grp, &bts->rbs2000.is.conn_groups, list)
-		num_grps++;
-
-	if (!num_grps)
-		return -EINVAL;
-
-	/* allocate buffer for oml group array */
-	cg = talloc_zero_array(bts, struct om2k_is_conn_grp, num_grps);
-
-	/* fill array with data from linked list */
-	llist_for_each_entry(grp, &bts->rbs2000.is.conn_groups, list)
-		om2k_fill_is_conn_grp(&cg[i++], grp->icp1, grp->icp2, grp->ci);
-
-	o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
-	fill_om2k_hdr(o2k, &bts->rbs2000.is.om2k_mo.addr,
-			OM2K_MSGT_IS_CONF_REQ);
-
-	msgb_tv_put(msg, OM2K_DEI_LIST_NR, 1);
-	msgb_tv_put(msg, OM2K_DEI_END_LIST_NR, 1);
-
-	msgb_tlv_put(msg, OM2K_DEI_IS_CONN_LIST,
-		     num_grps * sizeof(*cg), (uint8_t *)cg);
-
-	talloc_free(cg);
-
-	DEBUGP(DNM, "Tx MO=%s %s\n",
-		om2k_mo_name(&bts->rbs2000.is.om2k_mo.addr),
-		get_value_string(om2k_msgcode_vals, OM2K_MSGT_IS_CONF_REQ));
-
-	return abis_om2k_sendmsg(bts, msg);
-}
-
-int abis_om2k_tx_con_conf_req(struct gsm_bts *bts)
-{
-	struct msgb *msg = om2k_msgb_alloc();
-	struct abis_om2k_hdr *o2k;
-	struct con_group *grp;
-	unsigned int num_grps = 0;
-
-	/* count number of groups in linked list */
-	llist_for_each_entry(grp, &bts->rbs2000.con.conn_groups, list)
-		num_grps++;
-
-	if (!num_grps)
-		return -EINVAL;
-
-	/* first build the value part of the OM2K_DEI_CON_CONN_LIST DEI */
-	msgb_put_u8(msg, num_grps);
-	llist_for_each_entry(grp, &bts->rbs2000.con.conn_groups, list) {
-		struct con_path *cp;
-		unsigned int num_paths = 0;
-		llist_for_each_entry(cp, &grp->paths, list)
-			num_paths++;
-		msgb_put_u8(msg, num_paths);
-		llist_for_each_entry(cp, &grp->paths, list) {
-			struct om2k_con_path *om2k_cp;
-			om2k_cp = (struct om2k_con_path *) msgb_put(msg, sizeof(*om2k_cp));
-			om2k_cp->ccp = htons(cp->ccp);
-			om2k_cp->ci = cp->ci;
-			om2k_cp->tag = cp->tag;
-			om2k_cp->tei = cp->tei;
-		}
-	}
-	msgb_push_u8(msg, msgb_length(msg));
-	msgb_push_u8(msg, OM2K_DEI_CON_CONN_LIST);
-
-	/* pre-pend the list number DEIs */
-	msgb_tv_push(msg, OM2K_DEI_END_LIST_NR, 1);
-	msgb_tv_push(msg, OM2K_DEI_LIST_NR, 1);
-
-	/* pre-pend the OM2K header */
-	o2k = (struct abis_om2k_hdr *) msgb_push(msg, sizeof(*o2k));
-	fill_om2k_hdr(o2k, &bts->rbs2000.con.om2k_mo.addr,
-			OM2K_MSGT_CON_CONF_REQ);
-
-	DEBUGP(DNM, "Tx MO=%s %s\n",
-		om2k_mo_name(&bts->rbs2000.con.om2k_mo.addr),
-		get_value_string(om2k_msgcode_vals, OM2K_MSGT_CON_CONF_REQ));
-
-	return abis_om2k_sendmsg(bts, msg);
-}
-
-static void om2k_trx_to_mo(struct abis_om2k_mo *mo,
-			   const struct gsm_bts_trx *trx,
-			   enum abis_om2k_mo_cls cls)
-{
-	mo->class = cls;
-	mo->bts = 0;
-	mo->inst = trx->nr;
-	mo->assoc_so = 255;
-}
-
-static void om2k_ts_to_mo(struct abis_om2k_mo *mo,
-			  const struct gsm_bts_trx_ts *ts)
-{
-	mo->class = OM2K_MO_CLS_TS;
-	mo->bts = 0;
-	mo->inst = ts->nr;
-	mo->assoc_so = ts->trx->nr;
-}
-
-/* Configure a Receiver MO */
-int abis_om2k_tx_rx_conf_req(struct gsm_bts_trx *trx)
-{
-	struct msgb *msg = om2k_msgb_alloc();
-	struct abis_om2k_hdr *o2k;
-	struct abis_om2k_mo mo;
-
-	om2k_trx_to_mo(&mo, trx, OM2K_MO_CLS_RX);
-
-	o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
-	fill_om2k_hdr(o2k, &mo, OM2K_MSGT_RX_CONF_REQ);
-
-	msgb_tv16_put(msg, OM2K_DEI_FREQ_SPEC_RX, trx->arfcn);
-	msgb_tv_put(msg, OM2K_DEI_RX_DIVERSITY, 0x02); /* A */
-
-	return abis_om2k_sendmsg(trx->bts, msg);
-}
-
-/* Configure a Transmitter MO */
-int abis_om2k_tx_tx_conf_req(struct gsm_bts_trx *trx)
-{
-	struct msgb *msg = om2k_msgb_alloc();
-	struct abis_om2k_hdr *o2k;
-	struct abis_om2k_mo mo;
-
-	om2k_trx_to_mo(&mo, trx, OM2K_MO_CLS_TX);
-
-	o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
-	fill_om2k_hdr(o2k, &mo, OM2K_MSGT_TX_CONF_REQ);
-
-	msgb_tv16_put(msg, OM2K_DEI_FREQ_SPEC_TX, trx->arfcn);
-	msgb_tv_put(msg, OM2K_DEI_POWER, trx->nominal_power-trx->max_power_red);
-	msgb_tv_put(msg, OM2K_DEI_FILLING_MARKER, 0);	/* Filling enabled */
-	msgb_tv_put(msg, OM2K_DEI_BCC, trx->bts->bsic & 0x7);
-	/* Dedication Information is optional */
-
-	return abis_om2k_sendmsg(trx->bts, msg);
-}
-
-enum abis_om2k_tf_mode {
-	OM2K_TF_MODE_MASTER	= 0x00,
-	OM2K_TF_MODE_STANDALONE	= 0x01,
-	OM2K_TF_MODE_SLAVE	= 0x02,
-	OM2K_TF_MODE_UNDEFINED	= 0xff,
-};
-
-static const uint8_t fs_offset_undef[5] = { 0xff, 0xff, 0xff, 0xff, 0xff };
-
-int abis_om2k_tx_tf_conf_req(struct gsm_bts *bts)
-{
-	struct msgb *msg = om2k_msgb_alloc();
-	struct abis_om2k_hdr *o2k;
-
-	o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
-	fill_om2k_hdr(o2k, &bts->rbs2000.tf.om2k_mo.addr,
-			OM2K_MSGT_TF_CONF_REQ);
-
-	msgb_tv_put(msg, OM2K_DEI_TF_MODE, OM2K_TF_MODE_STANDALONE);
-	msgb_tv_put(msg, OM2K_DEI_TF_SYNC_SRC, 0x00);
-	msgb_tv_fixed_put(msg, OM2K_DEI_FS_OFFSET,
-			  sizeof(fs_offset_undef), fs_offset_undef);
-
-	DEBUGP(DNM, "Tx MO=%s %s\n",
-		om2k_mo_name(&bts->rbs2000.tf.om2k_mo.addr),
-		get_value_string(om2k_msgcode_vals, OM2K_MSGT_TF_CONF_REQ));
-
-	return abis_om2k_sendmsg(bts, msg);
-}
-
-static uint8_t pchan2comb(enum gsm_phys_chan_config pchan)
-{
-	switch (pchan) {
-	case GSM_PCHAN_CCCH:
-		return 4;
-	case GSM_PCHAN_CCCH_SDCCH4:
-		return 5;
-	case GSM_PCHAN_SDCCH8_SACCH8C:
-		return 3;
-	case GSM_PCHAN_TCH_F:
-	case GSM_PCHAN_TCH_H:
-	case GSM_PCHAN_PDCH:
-	case GSM_PCHAN_TCH_F_PDCH:
-	case GSM_PCHAN_TCH_F_TCH_H_PDCH:
-		return 8;
-	default:
-		return 0;
-	}
-}
-
-static uint8_t ts2comb(struct gsm_bts_trx_ts *ts)
-{
-	switch (ts->pchan) {
-	case GSM_PCHAN_TCH_F_PDCH:
-		LOGP(DNM, LOGL_ERROR, "%s pchan %s not intended for use"
-		     " with OM2000, use %s instead\n",
-		     gsm_ts_and_pchan_name(ts),
-		     gsm_pchan_name(GSM_PCHAN_TCH_F_PDCH),
-		     gsm_pchan_name(GSM_PCHAN_TCH_F_TCH_H_PDCH));
-		/* If we allowed initialization of TCH/F_PDCH, it would fail
-		 * when we try to send the ip.access specific RSL PDCH Act
-		 * message for it. Rather fail completely right now: */
-		return 0;
-	case GSM_PCHAN_TCH_F_TCH_H_PDCH:
-		return pchan2comb(GSM_PCHAN_TCH_F);
-	default:
-		return pchan2comb(ts->pchan);
-	}
-}
-
-static int put_freq_list(uint8_t *buf, uint16_t arfcn)
-{
-	buf[0] = 0x00; /* TX/RX address */
-	buf[1] = (arfcn >> 8);
-	buf[2] = (arfcn & 0xff);
-
-	return 3;
-}
-
-/* Compute a frequency list in OM2000 fomrmat */
-static int om2k_gen_freq_list(uint8_t *list, struct gsm_bts_trx_ts *ts)
-{
-	uint8_t *cur = list;
-	int len;
-
-	if (ts->hopping.enabled) {
-		unsigned int i;
-		for (i = 0; i < ts->hopping.arfcns.data_len*8; i++) {
-			if (bitvec_get_bit_pos(&ts->hopping.arfcns, i))
-				cur += put_freq_list(cur, i);
-		}
-	} else
-		cur += put_freq_list(cur, ts->trx->arfcn);
-
-	len = cur - list;
-
-	return len;
-}
-
-const uint8_t icm_bound_params[] = { 0x02, 0x06, 0x0c, 0x16, 0x06 };
-
-int abis_om2k_tx_ts_conf_req(struct gsm_bts_trx_ts *ts)
-{
-	struct msgb *msg = om2k_msgb_alloc();
-	struct abis_om2k_hdr *o2k;
-	struct abis_om2k_mo mo;
-	uint8_t freq_list[64*3]; /* BA max size: 64 ARFCN */
-	int freq_list_len;
-
-	om2k_ts_to_mo(&mo, ts);
-
-	memset(freq_list, 0, sizeof(freq_list));
-	freq_list_len = om2k_gen_freq_list(freq_list, ts);
-	if (freq_list_len < 0)
-		return freq_list_len;
-
-	o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
-	fill_om2k_hdr(o2k, &mo, OM2K_MSGT_TS_CONF_REQ);
-
-	msgb_tv_put(msg, OM2K_DEI_COMBINATION, ts2comb(ts));
-	msgb_tv_put(msg, OM2K_DEI_TS_NR, ts->nr);
-	msgb_tlv_put(msg, OM2K_DEI_FREQ_LIST, freq_list_len, freq_list);
-	msgb_tv_put(msg, OM2K_DEI_HSN, ts->hopping.hsn);
-	msgb_tv_put(msg, OM2K_DEI_MAIO, ts->hopping.maio);
-	msgb_tv_put(msg, OM2K_DEI_BSIC, ts->trx->bts->bsic);
-	msgb_tv_put(msg, OM2K_DEI_RX_DIVERSITY, 0x02); /* A */
-	msgb_tv16_put(msg, OM2K_DEI_FN_OFFSET, 0);
-	msgb_tv_put(msg, OM2K_DEI_EXT_RANGE, 0); /* Off */
-	/* Optional: Interference Rejection Combining */
-	msgb_tv_put(msg, OM2K_DEI_INTERF_REJ_COMB, 0x00);
-	switch (ts->pchan) {
-	case GSM_PCHAN_CCCH:
-		msgb_tv_put(msg, OM2K_DEI_BA_PA_MFRMS, 0x06);
-		msgb_tv_put(msg, OM2K_DEI_BS_AG_BKS_RES, 0x01);
-		msgb_tv_put(msg, OM2K_DEI_DRX_DEV_MAX, 0x05);
-		/* Repeat Paging/IMM.ASS: True, Allow Paging Type 3: Yes, Page for 5 seconds (default) */
-		msgb_tv_put(msg, OM2K_DEI_CCCH_OPTIONS, 0x01);
-		break;
-	case GSM_PCHAN_CCCH_SDCCH4:
-		msgb_tv_put(msg, OM2K_DEI_T3105, ts->trx->bts->network->T3105 / 10);
-		msgb_tv_put(msg, OM2K_DEI_NY1, 35);
-		msgb_tv_put(msg, OM2K_DEI_BA_PA_MFRMS, 0x06);
-		msgb_tv_put(msg, OM2K_DEI_CBCH_INDICATOR, 0);
-		msgb_tv_put(msg, OM2K_DEI_TSC, gsm_ts_tsc(ts));
-		msgb_tv_put(msg, OM2K_DEI_BS_AG_BKS_RES, 0x01);
-		msgb_tv_put(msg, OM2K_DEI_ICM_INDICATOR, 0);
-		msgb_tv_put(msg, OM2K_DEI_DRX_DEV_MAX, 0x05);
-		/* Repeat Paging/IMM.ASS: True, Allow Paging Type 3: Yes, Page for 5 seconds (default) */
-		msgb_tv_put(msg, OM2K_DEI_CCCH_OPTIONS, 0x01);
-		msgb_tv_fixed_put(msg, OM2K_DEI_ICM_BOUND_PARAMS,
-				  sizeof(icm_bound_params), icm_bound_params);
-		break;
-	case GSM_PCHAN_SDCCH8_SACCH8C:
-		msgb_tv_put(msg, OM2K_DEI_T3105, ts->trx->bts->network->T3105 / 10);
-		msgb_tv_put(msg, OM2K_DEI_NY1, 35);
-		msgb_tv_put(msg, OM2K_DEI_CBCH_INDICATOR, 0);
-		msgb_tv_put(msg, OM2K_DEI_TSC, gsm_ts_tsc(ts));
-		/* Disable RF RESOURCE INDICATION on idle channels */
-		msgb_tv_put(msg, OM2K_DEI_ICM_INDICATOR, 0);
-		msgb_tv_fixed_put(msg, OM2K_DEI_ICM_BOUND_PARAMS,
-				  sizeof(icm_bound_params), icm_bound_params);
-		break;
-	default:
-		msgb_tv_put(msg, OM2K_DEI_T3105, ts->trx->bts->network->T3105 / 10);
-		msgb_tv_put(msg, OM2K_DEI_NY1, 35);
-		msgb_tv_put(msg, OM2K_DEI_TSC, gsm_ts_tsc(ts));
-		/* Disable RF RESOURCE INDICATION on idle channels */
-		msgb_tv_put(msg, OM2K_DEI_ICM_INDICATOR, 0);
-		msgb_tv_fixed_put(msg, OM2K_DEI_ICM_BOUND_PARAMS,
-				  sizeof(icm_bound_params), icm_bound_params);
-		msgb_tv_put(msg, OM2K_DEI_TTA, 10); /* Timer for Time Alignment */
-		if (ts->pchan == GSM_PCHAN_TCH_H)
-			msgb_tv_put(msg, OM2K_DEI_ICM_CHAN_RATE, 1); /* TCH/H */
-		else
-			msgb_tv_put(msg, OM2K_DEI_ICM_CHAN_RATE, 0); /* TCH/F */
-		msgb_tv_put(msg, OM2K_DEI_LSC, 1); /* enabled */
-		msgb_tv_put(msg, OM2K_DEI_LSC_FILT_TIME, 10);	/* units of 100ms */
-		msgb_tv_put(msg, OM2K_DEI_CALL_SUPV_TIME, 8);
-		msgb_tv_put(msg, OM2K_DEI_ENCR_ALG, 0x00);
-		/* Not sure what those below mean */
-		msgb_tv_put(msg, 0x9e, 0x00);
-		msgb_tv_put(msg, 0x9f, 0x37);
-		msgb_tv_put(msg, 0xa0, 0x01);
-		break;
-	}
-
-	DEBUGP(DNM, "Tx MO=%s %s\n",
-		om2k_mo_name(&mo),
-		get_value_string(om2k_msgcode_vals, OM2K_MSGT_TS_CONF_REQ));
-
-	return abis_om2k_sendmsg(ts->trx->bts, msg);
-}
-
-
-/***********************************************************************
- * OM2000 Managed Object (MO) FSM
- ***********************************************************************/
-
-#define S(x)	(1 << (x))
-
-enum om2k_event_name {
-	OM2K_MO_EVT_START,
-	OM2K_MO_EVT_RX_CONN_COMPL,
-	OM2K_MO_EVT_RX_RESET_COMPL,
-	OM2K_MO_EVT_RX_START_REQ_ACCEPT,
-	OM2K_MO_EVT_RX_START_RES,
-	OM2K_MO_EVT_RX_CFG_REQ_ACCEPT,
-	OM2K_MO_EVT_RX_CFG_RES,
-	OM2K_MO_EVT_RX_ENA_REQ_ACCEPT,
-	OM2K_MO_EVT_RX_ENA_RES,
-	OM2K_MO_EVT_RX_OPINFO_ACC,
-};
-
-static const struct value_string om2k_event_names[] = {
-	{ OM2K_MO_EVT_START,			"START" },
-	{ OM2K_MO_EVT_RX_CONN_COMPL,		"RX-CONN-COMPL" },
-	{ OM2K_MO_EVT_RX_RESET_COMPL,		"RX-RESET-COMPL" },
-	{ OM2K_MO_EVT_RX_START_REQ_ACCEPT,	"RX-RESET-REQ-ACCEPT" },
-	{ OM2K_MO_EVT_RX_START_RES,		"RX-START-RESULT" },
-	{ OM2K_MO_EVT_RX_CFG_REQ_ACCEPT,	"RX-CFG-REQ-ACCEPT" },
-	{ OM2K_MO_EVT_RX_CFG_RES,		"RX-CFG-RESULT" },
-	{ OM2K_MO_EVT_RX_ENA_REQ_ACCEPT,	"RX-ENABLE-REQ-ACCEPT" },
-	{ OM2K_MO_EVT_RX_ENA_RES,		"RX-ENABLE-RESULT" },
-	{ OM2K_MO_EVT_RX_OPINFO_ACC,		"RX-OPINFO-ACCEPT" },
-	{ 0, NULL }
-};
-
-enum om2k_mo_fsm_state {
-	OM2K_ST_INIT,
-	OM2K_ST_WAIT_CONN_COMPL,
-	OM2K_ST_WAIT_RES_COMPL,
-	OM2K_ST_WAIT_START_ACCEPT,
-	OM2K_ST_WAIT_START_RES,
-	OM2K_ST_WAIT_CFG_ACCEPT,
-	OM2K_ST_WAIT_CFG_RES,
-	OM2K_ST_WAIT_ENABLE_ACCEPT,
-	OM2K_ST_WAIT_ENABLE_RES,
-	OM2K_ST_WAIT_OPINFO_ACCEPT,
-	OM2K_ST_DONE,
-	OM2K_ST_ERROR,
-};
-
-struct om2k_mo_fsm_priv {
-	struct gsm_bts_trx *trx;
-	struct om2k_mo *mo;
-	uint8_t ts_nr;
-};
-
-static void om2k_mo_st_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_mo_fsm_priv *omfp = fi->priv;
-
-	OSMO_ASSERT(event == OM2K_MO_EVT_START);
-
-	switch (omfp->mo->addr.class) {
-	case OM2K_MO_CLS_CF:
-		/* no Connect required, is always connected */
-		osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_START_ACCEPT,
-					OM2K_TIMEOUT, 0);
-		abis_om2k_tx_start_req(omfp->trx->bts, &omfp->mo->addr);
-		break;
-	case OM2K_MO_CLS_TRXC:
-		/* no Connect required, start with Reset */
-		osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_RES_COMPL,
-					OM2K_TIMEOUT, 0);
-		abis_om2k_tx_reset_cmd(omfp->trx->bts, &omfp->mo->addr);
-		break;
-	default:
-		/* start with Connect */
-		osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_CONN_COMPL,
-					OM2K_TIMEOUT, 0);
-		abis_om2k_tx_connect_cmd(omfp->trx->bts, &omfp->mo->addr);
-		break;
-	}
-}
-
-static void om2k_mo_st_wait_conn_compl(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_mo_fsm_priv *omfp = fi->priv;
-
-	switch (omfp->mo->addr.class) {
-#if 0
-	case OM2K_MO_CLS_TF:
-		/* skip the reset, hope that helps */
-		osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_START_ACCEPT,
-					OM2K_TIMEOUT, 0);
-		abis_om2k_tx_start_req(omfp->trx->bts, &omfp->mo->addr);
-		break;
-#endif
-	default:
-		osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_RES_COMPL,
-					OM2K_TIMEOUT, 0);
-		abis_om2k_tx_reset_cmd(omfp->trx->bts, &omfp->mo->addr);
-		break;
-	}
-}
-
-static void om2k_mo_st_wait_res_compl(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_mo_fsm_priv *omfp = fi->priv;
-
-	osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_START_ACCEPT,
-				OM2K_TIMEOUT, 0);
-	abis_om2k_tx_start_req(omfp->trx->bts, &omfp->mo->addr);
-}
-
-static void om2k_mo_st_wait_start_accept(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_decoded_msg *omd = data;
-
-	switch (omd->msg_type) {
-	case OM2K_MSGT_START_REQ_ACK:
-		osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_START_RES,
-					OM2K_TIMEOUT, 0);
-		break;
-	case OM2K_MSGT_START_REQ_REJ:
-		osmo_fsm_inst_state_chg(fi, OM2K_ST_ERROR, 0, 0);
-		break;
-	}
-}
-
-static void om2k_mo_st_wait_start_res(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_mo_fsm_priv *omfp = fi->priv;
-	struct gsm_bts_trx_ts *ts;
-
-	switch (omfp->mo->addr.class) {
-	case OM2K_MO_CLS_CF:
-	case OM2K_MO_CLS_TRXC:
-		/* Transition directly to Operational Info */
-		osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_OPINFO_ACCEPT,
-				OM2K_TIMEOUT, 0);
-		abis_om2k_tx_op_info(omfp->trx->bts, &omfp->mo->addr, 1);
-		return;
-	case OM2K_MO_CLS_DP:
-		/* Transition directoy to WAIT_ENABLE_ACCEPT */
-		osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_ENABLE_ACCEPT,
-					OM2K_TIMEOUT, 0);
-		abis_om2k_tx_enable_req(omfp->trx->bts, &omfp->mo->addr);
-		return;
-#if 0
-	case OM2K_MO_CLS_TF:
-		/* skip the config, hope that helps speeding things up */
-		osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_ENABLE_ACCEPT,
-					OM2K_TIMEOUT, 0);
-		abis_om2k_tx_enable_req(omfp->trx->bts, &omfp->mo->addr);
-		return;
-#endif
-	}
-
-	osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_CFG_ACCEPT,
-				OM2K_TIMEOUT, 0);
-	switch (omfp->mo->addr.class) {
-	case OM2K_MO_CLS_TF:
-		abis_om2k_tx_tf_conf_req(omfp->trx->bts);
-		break;
-	case OM2K_MO_CLS_IS:
-		abis_om2k_tx_is_conf_req(omfp->trx->bts);
-		break;
-	case OM2K_MO_CLS_CON:
-		abis_om2k_tx_con_conf_req(omfp->trx->bts);
-		break;
-	case OM2K_MO_CLS_TX:
-		abis_om2k_tx_tx_conf_req(omfp->trx);
-		break;
-	case OM2K_MO_CLS_RX:
-		abis_om2k_tx_rx_conf_req(omfp->trx);
-		break;
-	case OM2K_MO_CLS_TS:
-		ts = mo2obj(omfp->trx->bts, &omfp->mo->addr);
-		abis_om2k_tx_ts_conf_req(ts);
-		break;
-	}
-}
-
-static void om2k_mo_st_wait_cfg_accept(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_mo_fsm_priv *omfp = fi->priv;
-	uint32_t timeout = OM2K_TIMEOUT;
-
-	if (omfp->mo->addr.class == OM2K_MO_CLS_TF)
-		timeout = 600;
-
-	osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_CFG_RES, timeout, 0);
-}
-
-static void om2k_mo_st_wait_cfg_res(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_mo_fsm_priv *omfp = fi->priv;
-	struct om2k_decoded_msg *omd = data;
-	uint8_t accordance;
-
-	if (!TLVP_PRESENT(&omd->tp, OM2K_DEI_ACCORDANCE_IND)) {
-		osmo_fsm_inst_state_chg(fi, OM2K_ST_ERROR, 0, 0);
-		return;
-	}
-	accordance = *TLVP_VAL(&omd->tp, OM2K_DEI_ACCORDANCE_IND);
-
-	if (accordance != 0) {
-		/* accordance not OK */
-		osmo_fsm_inst_state_chg(fi, OM2K_ST_ERROR, 0, 0);
-		return;
-	}
-
-	osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_ENABLE_ACCEPT,
-				OM2K_TIMEOUT, 0);
-	abis_om2k_tx_enable_req(omfp->trx->bts, &omfp->mo->addr);
-}
-
-static void om2k_mo_st_wait_enable_accept(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_mo_fsm_priv *omfp = fi->priv;
-	struct om2k_decoded_msg *omd = data;
-
-	switch (omd->msg_type) {
-	case OM2K_MSGT_ENABLE_REQ_REJ:
-		osmo_fsm_inst_state_chg(fi, OM2K_ST_ERROR, 0, 0);
-		break;
-	case OM2K_MSGT_ENABLE_REQ_ACK:
-		if (omfp->mo->addr.class == OM2K_MO_CLS_IS &&
-		    omfp->trx->bts->rbs2000.use_superchannel)
-			e1inp_ericsson_set_altc(omfp->trx->bts->oml_link->ts->line, 1);
-		osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_ENABLE_RES,
-					OM2K_TIMEOUT, 0);
-	}
-}
-
-static void om2k_mo_st_wait_enable_res(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_mo_fsm_priv *omfp = fi->priv;
-	//struct om2k_decoded_msg *omd = data;
-	/* TODO: check if state is actually enabled now? */
-
-	osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_OPINFO_ACCEPT,
-				OM2K_TIMEOUT, 0);
-	abis_om2k_tx_op_info(omfp->trx->bts, &omfp->mo->addr, 1);
-}
-
-static void om2k_mo_st_wait_opinfo_accept(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_mo_fsm_priv *omfp = fi->priv;
-
-	/* if we have just received opinfo accept for the timeslot,
-	 * start dynamic TCH switching procedures */
-	if (omfp->mo->addr.class == OM2K_MO_CLS_TS) {
-		struct gsm_bts_trx_ts *ts;
-		ts = mo2obj(omfp->trx->bts, &omfp->mo->addr);
-		dyn_ts_init(ts);
-	}
-	osmo_fsm_inst_state_chg(fi, OM2K_ST_DONE, 0, 0);
-}
-
-static void om2k_mo_s_done_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
-{
-	struct om2k_mo_fsm_priv *omfp = fi->priv;
-	omfp->mo->fsm = NULL;
-	osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
-}
-
-static void om2k_mo_s_error_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
-{
-	struct om2k_mo_fsm_priv *omfp = fi->priv;
-
-	omfp->mo->fsm = NULL;
-	osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL);
-}
-
-static const struct osmo_fsm_state om2k_is_states[] = {
-	[OM2K_ST_INIT] = {
-		.name = "INIT",
-		.in_event_mask = S(OM2K_MO_EVT_START),
-		.out_state_mask = S(OM2K_ST_DONE) |
-				  S(OM2K_ST_ERROR) |
-				  S(OM2K_ST_WAIT_CONN_COMPL) |
-				  S(OM2K_ST_WAIT_START_ACCEPT) |
-				  S(OM2K_ST_WAIT_RES_COMPL),
-		.action = om2k_mo_st_init,
-	},
-	[OM2K_ST_WAIT_CONN_COMPL] = {
-		.name = "WAIT-CONN-COMPL",
-		.in_event_mask = S(OM2K_MO_EVT_RX_CONN_COMPL),
-		.out_state_mask = S(OM2K_ST_DONE) |
-				  S(OM2K_ST_ERROR) |
-				  S(OM2K_ST_WAIT_START_ACCEPT) |
-				  S(OM2K_ST_WAIT_RES_COMPL),
-		.action = om2k_mo_st_wait_conn_compl,
-	},
-	[OM2K_ST_WAIT_RES_COMPL] = {
-		.name = "WAIT-RES-COMPL",
-		.in_event_mask = S(OM2K_MO_EVT_RX_RESET_COMPL),
-		.out_state_mask = S(OM2K_ST_DONE) |
-				  S(OM2K_ST_ERROR) |
-				  S(OM2K_ST_WAIT_START_ACCEPT),
-		.action = om2k_mo_st_wait_res_compl,
-	},
-	[OM2K_ST_WAIT_START_ACCEPT] = {
-		.name = "WAIT-START-ACCEPT",
-		.in_event_mask = S(OM2K_MO_EVT_RX_START_REQ_ACCEPT),
-		.out_state_mask = S(OM2K_ST_DONE) |
-				  S(OM2K_ST_ERROR) |
-				  S(OM2K_ST_WAIT_START_RES),
-		.action =om2k_mo_st_wait_start_accept,
-	},
-	[OM2K_ST_WAIT_START_RES] = {
-		.name = "WAIT-START-RES",
-		.in_event_mask = S(OM2K_MO_EVT_RX_START_RES),
-		.out_state_mask = S(OM2K_ST_DONE) |
-				  S(OM2K_ST_ERROR) |
-				  S(OM2K_ST_WAIT_CFG_ACCEPT) |
-				  S(OM2K_ST_WAIT_OPINFO_ACCEPT),
-		.action = om2k_mo_st_wait_start_res,
-	},
-	[OM2K_ST_WAIT_CFG_ACCEPT] = {
-		.name = "WAIT-CFG-ACCEPT",
-		.in_event_mask = S(OM2K_MO_EVT_RX_CFG_REQ_ACCEPT),
-		.out_state_mask = S(OM2K_ST_DONE) |
-				  S(OM2K_ST_ERROR) |
-				  S(OM2K_ST_WAIT_CFG_RES),
-		.action = om2k_mo_st_wait_cfg_accept,
-	},
-	[OM2K_ST_WAIT_CFG_RES] = {
-		.name = "WAIT-CFG-RES",
-		.in_event_mask = S(OM2K_MO_EVT_RX_CFG_RES),
-		.out_state_mask = S(OM2K_ST_DONE) |
-				  S(OM2K_ST_ERROR) |
-				  S(OM2K_ST_WAIT_ENABLE_ACCEPT),
-		.action = om2k_mo_st_wait_cfg_res,
-	},
-	[OM2K_ST_WAIT_ENABLE_ACCEPT] = {
-		.name = "WAIT-ENABLE-ACCEPT",
-		.in_event_mask = S(OM2K_MO_EVT_RX_ENA_REQ_ACCEPT),
-		.out_state_mask = S(OM2K_ST_DONE) |
-				  S(OM2K_ST_ERROR) |
-				  S(OM2K_ST_WAIT_ENABLE_RES),
-		.action = om2k_mo_st_wait_enable_accept,
-	},
-	[OM2K_ST_WAIT_ENABLE_RES] = {
-		.name = "WAIT-ENABLE-RES",
-		.in_event_mask = S(OM2K_MO_EVT_RX_ENA_RES),
-		.out_state_mask = S(OM2K_ST_DONE) |
-				  S(OM2K_ST_ERROR) |
-				  S(OM2K_ST_WAIT_OPINFO_ACCEPT),
-		.action = om2k_mo_st_wait_enable_res,
-	},
-	[OM2K_ST_WAIT_OPINFO_ACCEPT] = {
-		.name = "WAIT-OPINFO-ACCEPT",
-		.in_event_mask = S(OM2K_MO_EVT_RX_OPINFO_ACC),
-		.out_state_mask = S(OM2K_ST_DONE) |
-				  S(OM2K_ST_ERROR),
-		.action = om2k_mo_st_wait_opinfo_accept,
-	},
-	[OM2K_ST_DONE] = {
-		.name = "DONE",
-		.in_event_mask = 0,
-		.out_state_mask = 0,
-		.onenter = om2k_mo_s_done_onenter,
-	},
-	[OM2K_ST_ERROR] = {
-		.name = "ERROR",
-		.in_event_mask = 0,
-		.out_state_mask = 0,
-		.onenter = om2k_mo_s_error_onenter,
-	},
-
-};
-
-static int om2k_mo_timer_cb(struct osmo_fsm_inst *fi)
-{
-	osmo_fsm_inst_state_chg(fi, OM2K_ST_ERROR, 0, 0);
-	return 0;
-}
-
-static struct osmo_fsm om2k_mo_fsm = {
-	.name = "OM2000-MO",
-	.states = om2k_is_states,
-	.num_states = ARRAY_SIZE(om2k_is_states),
-	.log_subsys = DNM,
-	.event_names = om2k_event_names,
-	.timer_cb = om2k_mo_timer_cb,
-};
-
-struct osmo_fsm_inst *om2k_mo_fsm_start(struct osmo_fsm_inst *parent,
-					uint32_t term_event,
-					struct gsm_bts_trx *trx, struct om2k_mo *mo)
-{
-	struct osmo_fsm_inst *fi;
-	struct om2k_mo_fsm_priv *omfp;
-	char idbuf[64];
-
-	snprintf(idbuf, sizeof(idbuf), "%s-%s", parent->id,
-		 om2k_mo_name(&mo->addr));
-
-	fi = osmo_fsm_inst_alloc_child_id(&om2k_mo_fsm, parent,
-					  term_event, idbuf);
-	if (!fi)
-		return NULL;
-
-	mo->fsm = fi;
-	omfp = talloc_zero(fi, struct om2k_mo_fsm_priv);
-	omfp->mo = mo;
-	omfp->trx = trx;
-	fi->priv = omfp;
-
-	osmo_fsm_inst_dispatch(fi, OM2K_MO_EVT_START, NULL);
-
-	return fi;
-}
-
-int om2k_mo_fsm_recvmsg(struct gsm_bts *bts, struct om2k_mo *mo,
-			struct om2k_decoded_msg *odm)
-{
-	switch (odm->msg_type) {
-	case OM2K_MSGT_CONNECT_COMPL:
-	case OM2K_MSGT_CONNECT_REJ:
-		osmo_fsm_inst_dispatch(mo->fsm,
-				OM2K_MO_EVT_RX_CONN_COMPL, odm);
-		break;
-
-	case OM2K_MSGT_RESET_COMPL:
-	case OM2K_MSGT_RESET_REJ:
-		osmo_fsm_inst_dispatch(mo->fsm,
-				OM2K_MO_EVT_RX_RESET_COMPL, odm);
-		break;
-
-	case OM2K_MSGT_START_REQ_ACK:
-	case OM2K_MSGT_START_REQ_REJ:
-		osmo_fsm_inst_dispatch(mo->fsm,
-				OM2K_MO_EVT_RX_START_REQ_ACCEPT, odm);
-		break;
-
-	case OM2K_MSGT_START_RES:
-		osmo_fsm_inst_dispatch(mo->fsm,
-				OM2K_MO_EVT_RX_START_RES, odm);
-		break;
-
-	case OM2K_MSGT_CON_CONF_REQ_ACK:
-	case OM2K_MSGT_IS_CONF_REQ_ACK:
-	case OM2K_MSGT_RX_CONF_REQ_ACK:
-	case OM2K_MSGT_TF_CONF_REQ_ACK:
-	case OM2K_MSGT_TS_CONF_REQ_ACK:
-	case OM2K_MSGT_TX_CONF_REQ_ACK:
-		osmo_fsm_inst_dispatch(mo->fsm,
-				OM2K_MO_EVT_RX_CFG_REQ_ACCEPT, odm);
-		break;
-
-	case OM2K_MSGT_CON_CONF_RES:
-	case OM2K_MSGT_IS_CONF_RES:
-	case OM2K_MSGT_RX_CONF_RES:
-	case OM2K_MSGT_TF_CONF_RES:
-	case OM2K_MSGT_TS_CONF_RES:
-	case OM2K_MSGT_TX_CONF_RES:
-		osmo_fsm_inst_dispatch(mo->fsm,
-				OM2K_MO_EVT_RX_CFG_RES, odm);
-		break;
-
-	case OM2K_MSGT_ENABLE_REQ_ACK:
-	case OM2K_MSGT_ENABLE_REQ_REJ:
-		osmo_fsm_inst_dispatch(mo->fsm,
-				OM2K_MO_EVT_RX_ENA_REQ_ACCEPT, odm);
-		break;
-	case OM2K_MSGT_ENABLE_RES:
-		osmo_fsm_inst_dispatch(mo->fsm,
-				OM2K_MO_EVT_RX_ENA_RES, odm);
-		break;
-
-	case OM2K_MSGT_OP_INFO_ACK:
-	case OM2K_MSGT_OP_INFO_REJ:
-		osmo_fsm_inst_dispatch(mo->fsm,
-				OM2K_MO_EVT_RX_OPINFO_ACC, odm);
-		break;
-	default:
-		return -1;
-	}
-
-	return 0;
-}
-
-/***********************************************************************
- * OM2000 TRX Finite State Machine, initializes TRXC and all siblings
- ***********************************************************************/
-
-enum om2k_trx_event {
-	OM2K_TRX_EVT_START,
-	OM2K_TRX_EVT_TRXC_DONE,
-	OM2K_TRX_EVT_TX_DONE,
-	OM2K_TRX_EVT_RX_DONE,
-	OM2K_TRX_EVT_TS_DONE,
-	OM2K_TRX_EVT_STOP,
-};
-
-static struct value_string om2k_trx_events[] = {
-	{ OM2K_TRX_EVT_START,		"START" },
-	{ OM2K_TRX_EVT_TRXC_DONE,	"TRXC-DONE" },
-	{ OM2K_TRX_EVT_TX_DONE,		"TX-DONE" },
-	{ OM2K_TRX_EVT_RX_DONE,		"RX-DONE" },
-	{ OM2K_TRX_EVT_TS_DONE,		"TS-DONE" },
-	{ OM2K_TRX_EVT_STOP,		"STOP" },
-	{ 0, NULL }
-};
-
-enum om2k_trx_state {
-	 OM2K_TRX_S_INIT,
-	 OM2K_TRX_S_WAIT_TRXC,
-	 OM2K_TRX_S_WAIT_TX,
-	 OM2K_TRX_S_WAIT_RX,
-	 OM2K_TRX_S_WAIT_TS,
-	 OM2K_TRX_S_DONE,
-	 OM2K_TRX_S_ERROR
-};
-
-struct om2k_trx_fsm_priv {
-	struct gsm_bts_trx *trx;
-	uint8_t next_ts_nr;
-};
-
-static void om2k_trx_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_trx_fsm_priv *otfp = fi->priv;
-
-	/* First initialize TRXC */
-	osmo_fsm_inst_state_chg(fi, OM2K_TRX_S_WAIT_TRXC,
-				TRX_FSM_TIMEOUT, 0);
-	om2k_mo_fsm_start(fi, OM2K_TRX_EVT_TRXC_DONE, otfp->trx,
-			  &otfp->trx->rbs2000.trxc.om2k_mo);
-}
-
-static void om2k_trx_s_wait_trxc(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_trx_fsm_priv *otfp = fi->priv;
-
-	/* Initialize TX after TRXC */
-	osmo_fsm_inst_state_chg(fi, OM2K_TRX_S_WAIT_TX,
-				TRX_FSM_TIMEOUT, 0);
-	om2k_mo_fsm_start(fi, OM2K_TRX_EVT_TX_DONE, otfp->trx,
-			  &otfp->trx->rbs2000.tx.om2k_mo);
-}
-
-static void om2k_trx_s_wait_tx(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_trx_fsm_priv *otfp = fi->priv;
-
-	/* Initialize RX after TX */
-	osmo_fsm_inst_state_chg(fi, OM2K_TRX_S_WAIT_RX,
-				TRX_FSM_TIMEOUT, 0);
-	om2k_mo_fsm_start(fi, OM2K_TRX_EVT_RX_DONE, otfp->trx,
-			  &otfp->trx->rbs2000.rx.om2k_mo);
-}
-
-static void om2k_trx_s_wait_rx(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_trx_fsm_priv *otfp = fi->priv;
-	struct gsm_bts_trx_ts *ts;
-
-	/* Initialize Timeslots after TX */
-	osmo_fsm_inst_state_chg(fi, OM2K_TRX_S_WAIT_TS,
-				TRX_FSM_TIMEOUT, 0);
-	otfp->next_ts_nr = 0;
-	ts = &otfp->trx->ts[otfp->next_ts_nr++];
-	om2k_mo_fsm_start(fi, OM2K_TRX_EVT_TS_DONE, otfp->trx,
-			  &ts->rbs2000.om2k_mo);
-}
-
-static void om2k_trx_s_wait_ts(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_trx_fsm_priv *otfp = fi->priv;
-	struct gsm_bts_trx_ts *ts;
-
-	if (otfp->next_ts_nr < 8) {
-		/* iterate to the next timeslot */
-		ts = &otfp->trx->ts[otfp->next_ts_nr++];
-		om2k_mo_fsm_start(fi, OM2K_TRX_EVT_TS_DONE, otfp->trx,
-				  &ts->rbs2000.om2k_mo);
-	} else {
-		/* only after all 8 TS */
-		osmo_fsm_inst_state_chg(fi, OM2K_TRX_S_DONE, 0, 0);
-	}
-}
-
-static void om2k_trx_s_done_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
-{
-	struct om2k_trx_fsm_priv *otfp = fi->priv;
-	gsm_bts_trx_set_system_infos(otfp->trx);
-	osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
-}
-
-static const struct osmo_fsm_state om2k_trx_states[] = {
-	[OM2K_TRX_S_INIT] = {
-		.in_event_mask = S(OM2K_TRX_EVT_START),
-		.out_state_mask = S(OM2K_TRX_S_WAIT_TRXC),
-		.name = "INIT",
-		.action = om2k_trx_s_init,
-	},
-	[OM2K_TRX_S_WAIT_TRXC] = {
-		.in_event_mask = S(OM2K_TRX_EVT_TRXC_DONE),
-		.out_state_mask = S(OM2K_TRX_S_ERROR) |
-				  S(OM2K_TRX_S_WAIT_TX),
-		.name = "WAIT-TRXC",
-		.action = om2k_trx_s_wait_trxc,
-	},
-	[OM2K_TRX_S_WAIT_TX] = {
-		.in_event_mask = S(OM2K_TRX_EVT_TX_DONE),
-		.out_state_mask = S(OM2K_TRX_S_ERROR) |
-				  S(OM2K_TRX_S_WAIT_RX),
-		.name = "WAIT-TX",
-		.action = om2k_trx_s_wait_tx,
-	},
-	[OM2K_TRX_S_WAIT_RX] = {
-		.in_event_mask = S(OM2K_TRX_EVT_RX_DONE),
-		.out_state_mask = S(OM2K_TRX_S_ERROR) |
-				  S(OM2K_TRX_S_WAIT_TS),
-		.name = "WAIT-RX",
-		.action = om2k_trx_s_wait_rx,
-	},
-	[OM2K_TRX_S_WAIT_TS] = {
-		.in_event_mask = S(OM2K_TRX_EVT_TS_DONE),
-		.out_state_mask = S(OM2K_TRX_S_ERROR) |
-				  S(OM2K_TRX_S_DONE),
-		.name = "WAIT-TS",
-		.action = om2k_trx_s_wait_ts,
-	},
-	[OM2K_TRX_S_DONE] = {
-		.name = "DONE",
-		.onenter = om2k_trx_s_done_onenter,
-	},
-	[OM2K_TRX_S_ERROR] = {
-		.name = "ERROR",
-	},
-};
-
-static int om2k_trx_timer_cb(struct osmo_fsm_inst *fi)
-{
-	osmo_fsm_inst_state_chg(fi, OM2K_TRX_S_ERROR, 0, 0);
-	return 0;
-}
-
-static struct osmo_fsm om2k_trx_fsm = {
-	.name = "OM2000-TRX",
-	.states = om2k_trx_states,
-	.num_states = ARRAY_SIZE(om2k_trx_states),
-	.log_subsys = DNM,
-	.event_names = om2k_trx_events,
-	.timer_cb = om2k_trx_timer_cb,
-};
-
-struct osmo_fsm_inst *om2k_trx_fsm_start(struct osmo_fsm_inst *parent,
-					 struct gsm_bts_trx *trx,
-					 uint32_t term_event)
-{
-	struct osmo_fsm_inst *fi;
-	struct om2k_trx_fsm_priv *otfp;
-	char idbuf[32];
-
-	snprintf(idbuf, sizeof(idbuf), "%u/%u", trx->bts->nr, trx->nr);
-
-	fi = osmo_fsm_inst_alloc_child_id(&om2k_trx_fsm, parent, term_event,
-					  idbuf);
-	if (!fi)
-		return NULL;
-
-	otfp = talloc_zero(fi, struct om2k_trx_fsm_priv);
-	otfp->trx = trx;
-	fi->priv = otfp;
-
-	osmo_fsm_inst_dispatch(fi, OM2K_TRX_EVT_START, NULL);
-
-	return fi;
-}
-
-
-/***********************************************************************
- * OM2000 BTS Finite State Machine, initializes CF and all siblings
- ***********************************************************************/
-
-enum om2k_bts_event {
-	OM2K_BTS_EVT_START,
-	OM2K_BTS_EVT_CF_DONE,
-	OM2K_BTS_EVT_IS_DONE,
-	OM2K_BTS_EVT_CON_DONE,
-	OM2K_BTS_EVT_TF_DONE,
-	OM2K_BTS_EVT_TRX_DONE,
-	OM2K_BTS_EVT_STOP,
-};
-
-static const struct value_string om2k_bts_events[] = {
-	{ OM2K_BTS_EVT_START,		"START" },
-	{ OM2K_BTS_EVT_CF_DONE,		"CF-DONE" },
-	{ OM2K_BTS_EVT_IS_DONE,		"IS-DONE" },
-	{ OM2K_BTS_EVT_CON_DONE,	"CON-DONE" },
-	{ OM2K_BTS_EVT_TF_DONE,		"TF-DONE" },
-	{ OM2K_BTS_EVT_TRX_DONE,	"TRX-DONE" },
-	{ OM2K_BTS_EVT_STOP,		"STOP" },
-	{ 0, NULL }
-};
-
-enum om2k_bts_state {
-	OM2K_BTS_S_INIT,
-	OM2K_BTS_S_WAIT_CF,
-	OM2K_BTS_S_WAIT_IS,
-	OM2K_BTS_S_WAIT_CON,
-	OM2K_BTS_S_WAIT_TF,
-	OM2K_BTS_S_WAIT_TRX,
-	OM2K_BTS_S_DONE,
-	OM2K_BTS_S_ERROR,
-};
-
-struct om2k_bts_fsm_priv {
-	struct gsm_bts *bts;
-	uint8_t next_trx_nr;
-};
-
-static void om2k_bts_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_bts_fsm_priv *obfp = fi->priv;
-	struct gsm_bts *bts = obfp->bts;
-
-	OSMO_ASSERT(event == OM2K_BTS_EVT_START);
-	osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_CF,
-				BTS_FSM_TIMEOUT, 0);
-	om2k_mo_fsm_start(fi, OM2K_BTS_EVT_CF_DONE, bts->c0,
-			  &bts->rbs2000.cf.om2k_mo);
-}
-
-static void om2k_bts_s_wait_cf(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_bts_fsm_priv *obfp = fi->priv;
-	struct gsm_bts *bts = obfp->bts;
-
-	OSMO_ASSERT(event == OM2K_BTS_EVT_CF_DONE);
-	/* TF can take a long time to initialize, wait for 10min */
-	osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_TF, 600, 0);
-	om2k_mo_fsm_start(fi, OM2K_BTS_EVT_TF_DONE, bts->c0,
-			  &bts->rbs2000.tf.om2k_mo);
-}
-
-static void om2k_bts_s_wait_tf(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_bts_fsm_priv *obfp = fi->priv;
-	struct gsm_bts *bts = obfp->bts;
-
-	OSMO_ASSERT(event == OM2K_BTS_EVT_TF_DONE);
-
-	osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_CON,
-				BTS_FSM_TIMEOUT, 0);
-	om2k_mo_fsm_start(fi, OM2K_BTS_EVT_CON_DONE, bts->c0,
-			  &bts->rbs2000.con.om2k_mo);
-}
-
-static void om2k_bts_s_wait_con(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_bts_fsm_priv *obfp = fi->priv;
-	struct gsm_bts *bts = obfp->bts;
-
-	OSMO_ASSERT(event == OM2K_BTS_EVT_CON_DONE);
-
-	osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_IS,
-				BTS_FSM_TIMEOUT, 0);
-	om2k_mo_fsm_start(fi, OM2K_BTS_EVT_IS_DONE, bts->c0,
-			  &bts->rbs2000.is.om2k_mo);
-}
-
-static void om2k_bts_s_wait_is(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_bts_fsm_priv *obfp = fi->priv;
-	struct gsm_bts_trx *trx;
-
-	OSMO_ASSERT(event == OM2K_BTS_EVT_IS_DONE);
-
-	osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_TRX,
-				BTS_FSM_TIMEOUT, 0);
-	obfp->next_trx_nr = 0;
-	trx = gsm_bts_trx_num(obfp->bts, obfp->next_trx_nr++);
-	om2k_trx_fsm_start(fi, trx, OM2K_BTS_EVT_TRX_DONE);
-}
-
-static void om2k_bts_s_wait_trx(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct om2k_bts_fsm_priv *obfp = fi->priv;
-
-	OSMO_ASSERT(event == OM2K_BTS_EVT_TRX_DONE);
-
-	if (obfp->next_trx_nr < obfp->bts->num_trx) {
-		struct gsm_bts_trx *trx;
-		trx = gsm_bts_trx_num(obfp->bts, obfp->next_trx_nr++);
-		om2k_trx_fsm_start(fi, trx, OM2K_BTS_EVT_TRX_DONE);
-	} else {
-		osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_DONE, 0, 0);
-	}
-}
-
-static void om2k_bts_s_done_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
-{
-	osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
-}
-
-static const struct osmo_fsm_state om2k_bts_states[] = {
-	[OM2K_BTS_S_INIT] = {
-		.in_event_mask = S(OM2K_BTS_EVT_START),
-		.out_state_mask = S(OM2K_BTS_S_WAIT_CF),
-		.name = "INIT",
-		.action = om2k_bts_s_init,
-	},
-	[OM2K_BTS_S_WAIT_CF] = {
-		.in_event_mask = S(OM2K_BTS_EVT_CF_DONE),
-		.out_state_mask = S(OM2K_BTS_S_ERROR) |
-				  S(OM2K_BTS_S_WAIT_TF),
-		.name = "WAIT-CF",
-		.action = om2k_bts_s_wait_cf,
-	},
-	[OM2K_BTS_S_WAIT_TF] = {
-		.in_event_mask = S(OM2K_BTS_EVT_TF_DONE),
-		.out_state_mask = S(OM2K_BTS_S_ERROR) |
-				  S(OM2K_BTS_S_WAIT_CON),
-		.name = "WAIT-TF",
-		.action = om2k_bts_s_wait_tf,
-	},
-	[OM2K_BTS_S_WAIT_CON] = {
-		.in_event_mask = S(OM2K_BTS_EVT_CON_DONE),
-		.out_state_mask = S(OM2K_BTS_S_ERROR) |
-				  S(OM2K_BTS_S_WAIT_IS),
-		.name = "WAIT-CON",
-		.action = om2k_bts_s_wait_con,
-	},
-	[OM2K_BTS_S_WAIT_IS] = {
-		.in_event_mask = S(OM2K_BTS_EVT_IS_DONE),
-		.out_state_mask = S(OM2K_BTS_S_ERROR) |
-				  S(OM2K_BTS_S_WAIT_TRX),
-		.name = "WAIT-IS",
-		.action = om2k_bts_s_wait_is,
-	},
-	[OM2K_BTS_S_WAIT_TRX] = {
-		.in_event_mask = S(OM2K_BTS_EVT_TRX_DONE),
-		.out_state_mask = S(OM2K_BTS_S_ERROR) |
-				  S(OM2K_BTS_S_DONE),
-		.name = "WAIT-TRX",
-		.action = om2k_bts_s_wait_trx,
-	},
-	[OM2K_BTS_S_DONE] = {
-		.name = "DONE",
-		.onenter = om2k_bts_s_done_onenter,
-	},
-	[OM2K_BTS_S_ERROR] = {
-		.name = "ERROR",
-	},
-};
-
-static int om2k_bts_timer_cb(struct osmo_fsm_inst *fi)
-{
-	osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_ERROR, 0, 0);
-	return 0;
-}
-
-static struct osmo_fsm om2k_bts_fsm = {
-	.name = "OM2000-BTS",
-	.states = om2k_bts_states,
-	.num_states = ARRAY_SIZE(om2k_bts_states),
-	.log_subsys = DNM,
-	.event_names = om2k_bts_events,
-	.timer_cb = om2k_bts_timer_cb,
-};
-
-struct osmo_fsm_inst *
-om2k_bts_fsm_start(struct gsm_bts *bts)
-{
-	struct osmo_fsm_inst *fi;
-	struct om2k_bts_fsm_priv *obfp;
-	char idbuf[16];
-
-	snprintf(idbuf, sizeof(idbuf), "%u", bts->nr);
-
-	fi = osmo_fsm_inst_alloc(&om2k_bts_fsm, bts, NULL,
-				 LOGL_DEBUG, idbuf);
-	if (!fi)
-		return NULL;
-	fi->priv = obfp = talloc_zero(fi, struct om2k_bts_fsm_priv);
-	obfp->bts = bts;
-
-	osmo_fsm_inst_dispatch(fi, OM2K_BTS_EVT_START, NULL);
-
-	return fi;
-}
-
-
-/***********************************************************************
- * OM2000 Negotiation
- ***********************************************************************/
-
-static int abis_om2k_tx_negot_req_ack(struct gsm_bts *bts, const struct abis_om2k_mo *mo,
-				      uint8_t *data, unsigned int len)
-{
-	struct msgb *msg = om2k_msgb_alloc();
-	struct abis_om2k_hdr *o2k;
-
-	o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
-	fill_om2k_hdr(o2k, mo, OM2K_MSGT_NEGOT_REQ_ACK);
-
-	msgb_tlv_put(msg, OM2K_DEI_NEGOT_REC2, len, data);
-
-	DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(mo),
-		get_value_string(om2k_msgcode_vals, OM2K_MSGT_NEGOT_REQ_ACK));
-
-	return abis_om2k_sendmsg(bts, msg);
-}
-
-struct iwd_version {
-	uint8_t gen_char[3+1];
-	uint8_t rev_char[3+1];
-};
-
-struct iwd_type {
-	uint8_t num_vers;
-	struct iwd_version v[8];
-};
-
-static int om2k_rx_negot_req(struct msgb *msg)
-{
-	struct e1inp_sign_link *sign_link = (struct e1inp_sign_link *)msg->dst;
-	struct abis_om2k_hdr *o2h = msgb_l2(msg);
-	struct iwd_type iwd_types[16];
-	uint8_t num_iwd_types = o2h->data[2];
-	uint8_t *cur = o2h->data+3;
-	unsigned int i, v;
-
-	uint8_t out_buf[1024];
-	uint8_t *out_cur = out_buf+1;
-	uint8_t out_num_types = 0;
-
-	memset(iwd_types, 0, sizeof(iwd_types));
-
-	/* Parse the RBS-supported IWD versions into iwd_types array */
-	for (i = 0; i < num_iwd_types; i++) {
-		uint8_t num_versions = *cur++;
-		uint8_t iwd_type = *cur++;
-
-		iwd_types[iwd_type].num_vers = num_versions;
-
-		for (v = 0; v < num_versions; v++) {
-			struct iwd_version *iwd_v = &iwd_types[iwd_type].v[v];
-
-			memcpy(iwd_v->gen_char, cur, 3);
-			cur += 3;
-			memcpy(iwd_v->rev_char, cur, 3);
-			cur += 3;
-
-			DEBUGP(DNM, "\tIWD Type %u Gen %s Rev %s\n", iwd_type,
-				iwd_v->gen_char, iwd_v->rev_char);
-		}
-	}
-
-	/* Select the last version for each IWD type */
-	for (i = 0; i < ARRAY_SIZE(iwd_types); i++) {
-		struct iwd_type *type = &iwd_types[i];
-		struct iwd_version *last_v;
-
-		if (type->num_vers == 0)
-			continue;
-
-		out_num_types++;
-
-		last_v = &type->v[type->num_vers-1];
-
-		*out_cur++ = i;
-		memcpy(out_cur, last_v->gen_char, 3);
-		out_cur += 3;
-		memcpy(out_cur, last_v->rev_char, 3);
-		out_cur += 3;
-	}
-
-	out_buf[0] = out_num_types;
-
-	return abis_om2k_tx_negot_req_ack(sign_link->trx->bts, &o2h->mo, out_buf, out_cur - out_buf);
-}
-
-
-/***********************************************************************
- * OM2000 Receive Message Handler
- ***********************************************************************/
-
-static int om2k_rx_nack(struct msgb *msg)
-{
-	struct abis_om2k_hdr *o2h = msgb_l2(msg);
-	uint16_t msg_type = ntohs(o2h->msg_type);
-	struct tlv_parsed tp;
-
-	LOGP(DNM, LOGL_ERROR, "Rx MO=%s %s", om2k_mo_name(&o2h->mo),
-		get_value_string(om2k_msgcode_vals, msg_type));
-
-	abis_om2k_msg_tlv_parse(&tp, o2h);
-	if (TLVP_PRESENT(&tp, OM2K_DEI_REASON_CODE))
-		LOGPC(DNM, LOGL_ERROR, ", Reason 0x%02x",
-			*TLVP_VAL(&tp, OM2K_DEI_REASON_CODE));
-
-	if (TLVP_PRESENT(&tp, OM2K_DEI_RESULT_CODE))
-		LOGPC(DNM, LOGL_ERROR, ", Result %s",
-			get_value_string(om2k_result_strings,
-					 *TLVP_VAL(&tp, OM2K_DEI_RESULT_CODE)));
-	LOGPC(DNM, LOGL_ERROR, "\n");
-
-	return 0;
-}
-
-static int process_mo_state(struct gsm_bts *bts, struct om2k_decoded_msg *odm)
-{
-	uint8_t mo_state;
-
-	if (!TLVP_PRESENT(&odm->tp, OM2K_DEI_MO_STATE))
-		return -EIO;
-	mo_state = *TLVP_VAL(&odm->tp, OM2K_DEI_MO_STATE);
-
-	LOGP(DNM, LOGL_DEBUG, "Rx MO=%s %s, MO State: %s\n",
-		om2k_mo_name(&odm->o2h.mo),
-		get_value_string(om2k_msgcode_vals, odm->msg_type),
-		get_value_string(om2k_mostate_vals, mo_state));
-
-	/* Throw error message in case we see an enable rsponse that does
-	 * not yield an enabled mo-state */
-	if (odm->msg_type == OM2K_MSGT_ENABLE_RES
-	    && mo_state != OM2K_MO_S_ENABLED) {
-		LOGP(DNM, LOGL_ERROR,
-		     "Rx MO=%s %s Failed to enable MO State!\n",
-		     om2k_mo_name(&odm->o2h.mo),
-		     get_value_string(om2k_msgcode_vals, odm->msg_type));
-	}
-
-	update_mo_state(bts, &odm->o2h.mo, mo_state);
-
-	return 0;
-}
-
-/* Display fault report bits (helper function of display_fault_maps()) */
-static bool display_fault_bits(const uint8_t *vect, uint16_t len,
-			       uint8_t dei, const struct abis_om2k_mo *mo)
-{
-	uint16_t i;
-	int k;
-	bool faults_present = false;
-	int first = 1;
-	char string[255];
-
-	/* Check if errors are present at all */
-	for (i = 0; i < len; i++)
-		if (vect[i])
-			faults_present = true;
-	if (!faults_present)
-		return false;
-
-	sprintf(string, "Fault Report: %s (",
-		get_value_string(om2k_attr_vals, dei));
-
-	for (i = 0; i < len; i++) {
-		for (k = 0; k < 8; k++) {
-			if ((vect[i] >> k) & 1) {
-				if (!first)
-					sprintf(string + strlen(string), ",");
-				sprintf(string + strlen(string), "%d", k + i*8);
-				first = 0;
-			}
-		}
-	}
-
-	sprintf(string + strlen(string), ")\n");
-	DEBUGP(DNM, "Rx MO=%s %s", om2k_mo_name(mo), string);
-
-	return true;
-}
-
-/* Display fault report maps */
-static void display_fault_maps(const uint8_t *src, unsigned int src_len,
-			       const struct abis_om2k_mo *mo)
-{
-	uint8_t tag;
-	uint16_t tag_len;
-	const uint8_t *val;
-	int src_pos = 0;
-	int rc;
-	int tlv_count = 0;
-	uint16_t msg_code;
-	bool faults_present = false;
-
-	/* Chop off header */
-	src+=4;
-	src_len-=4;
-
-	/* Check message type */
-	msg_code = (*src & 0xff) << 8;
-	src++;
-	src_len--;
-	msg_code |= (*src & 0xff);
-	src++;
-	src_len--;
-	if (msg_code != OM2K_MSGT_FAULT_REP) {
-		LOGP(DNM, LOGL_ERROR, "Rx MO=%s Fault report: invalid message code!\n",
-		     om2k_mo_name(mo));
-		return;
-	}
-
-	/* Chop off mo-interface */
-	src += 4;
-	src_len -= 4;
-
-	/* Iterate over each TLV element */
-	while (1) {
-
-		/* Bail if an the maximum number of TLV fields
-		 * have been parsed */
-		if (tlv_count >= 11) {
-			LOGP(DNM, LOGL_ERROR,
-			     "Rx MO=%s Fault Report: too many tlv elements!\n",
-			     om2k_mo_name(mo));
-			return;
-		}
-
-		/* Parse TLV field */
-		rc = tlv_parse_one(&tag, &tag_len, &val, &om2k_att_tlvdef,
-				   src + src_pos, src_len - src_pos);
-		if (rc > 0)
-			src_pos += rc;
-		else {
-			LOGP(DNM, LOGL_ERROR,
-			     "Rx MO=%s Fault Report: invalid tlv element!\n",
-			     om2k_mo_name(mo));
-			return;
-		}
-
-		switch (tag) {
-		case OM2K_DEI_INT_FAULT_MAP_1A:
-		case OM2K_DEI_INT_FAULT_MAP_1B:
-		case OM2K_DEI_INT_FAULT_MAP_2A:
-		case OM2K_DEI_EXT_COND_MAP_1:
-		case OM2K_DEI_EXT_COND_MAP_2:
-		case OM2K_DEI_REPL_UNIT_MAP:
-		case OM2K_DEI_INT_FAULT_MAP_2A_EXT:
-		case OM2K_DEI_EXT_COND_MAP_2_EXT:
-		case OM2K_DEI_REPL_UNIT_MAP_EXT:
-			faults_present |= display_fault_bits(val, tag_len,
-							     tag, mo);
-			break;
-		}
-
-		/* Stop when no further TLV elements can be expected */
-		if (src_len - src_pos < 2)
-			break;
-
-		tlv_count++;
-	}
-
-	if (!faults_present) {
-		DEBUGP(DNM, "Rx MO=%s Fault Report: All faults ceased!\n",
-		       om2k_mo_name(mo));
-	}
-}
-
-int abis_om2k_rcvmsg(struct msgb *msg)
-{
-	struct e1inp_sign_link *sign_link = (struct e1inp_sign_link *)msg->dst;
-	struct gsm_bts *bts = sign_link->trx->bts;
-	struct abis_om2k_hdr *o2h = msgb_l2(msg);
-	struct abis_om_hdr *oh = &o2h->om;
-	uint16_t msg_type = ntohs(o2h->msg_type);
-	struct om2k_decoded_msg odm;
-	struct om2k_mo *mo;
-	int rc = 0;
-
-	/* Various consistency checks */
-	if (oh->placement != ABIS_OM_PLACEMENT_ONLY) {
-		LOGP(DNM, LOGL_ERROR, "ABIS OML placement 0x%x not supported\n",
-			oh->placement);
-		if (oh->placement != ABIS_OM_PLACEMENT_FIRST)
-			return -EINVAL;
-	}
-	if (oh->sequence != 0) {
-		LOGP(DNM, LOGL_ERROR, "ABIS OML sequence 0x%x != 0x00\n",
-			oh->sequence);
-		return -EINVAL;
-	}
-
-	msg->l3h = (unsigned char *)o2h + sizeof(*o2h);
-
-	if (oh->mdisc != ABIS_OM_MDISC_FOM) {
-		LOGP(DNM, LOGL_ERROR, "unknown ABIS OM2000 message discriminator 0x%x\n",
-			oh->mdisc);
-		return -EINVAL;
-	}
-
-	DEBUGP(DNM, "Rx MO=%s %s (%s)\n", om2k_mo_name(&o2h->mo),
-		get_value_string(om2k_msgcode_vals, msg_type),
-		osmo_hexdump(msg->l2h, msgb_l2len(msg)));
-
-	om2k_decode_msg(&odm, msg);
-
-	process_mo_state(bts, &odm);
-
-	switch (msg_type) {
-	case OM2K_MSGT_CAL_TIME_REQ:
-		rc = abis_om2k_cal_time_resp(bts);
-		break;
-	case OM2K_MSGT_FAULT_REP:
-		display_fault_maps(msg->l2h, msgb_l2len(msg), &o2h->mo);
-		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_FAULT_REP_ACK);
-		break;
-	case OM2K_MSGT_NEGOT_REQ:
-		rc = om2k_rx_negot_req(msg);
-		break;
-	case OM2K_MSGT_START_RES:
-		/* common processing here */
-		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_START_RES_ACK);
-		/* below we dispatch into MO */
-		break;
-	case OM2K_MSGT_IS_CONF_RES:
-		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_IS_CONF_RES_ACK);
-		break;
-	case OM2K_MSGT_CON_CONF_RES:
-		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_CON_CONF_RES_ACK);
-		break;
-	case OM2K_MSGT_TX_CONF_RES:
-		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TX_CONF_RES_ACK);
-		break;
-	case OM2K_MSGT_RX_CONF_RES:
-		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_RX_CONF_RES_ACK);
-		break;
-	case OM2K_MSGT_TS_CONF_RES:
-		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TS_CONF_RES_ACK);
-		break;
-	case OM2K_MSGT_TF_CONF_RES:
-		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TF_CONF_RES_ACK);
-		break;
-	case OM2K_MSGT_ENABLE_RES:
-		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_ENABLE_RES_ACK);
-		break;
-	case OM2K_MSGT_DISABLE_RES:
-		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_DISABLE_RES_ACK);
-		break;
-	case OM2K_MSGT_TEST_RES:
-		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TEST_RES_ACK);
-		break;
-	case OM2K_MSGT_CAPA_RES:
-		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_CAPA_RES_ACK);
-		break;
-	/* ERrors */
-	case OM2K_MSGT_START_REQ_REJ:
-	case OM2K_MSGT_CONNECT_REJ:
-	case OM2K_MSGT_OP_INFO_REJ:
-	case OM2K_MSGT_DISCONNECT_REJ:
-	case OM2K_MSGT_TEST_REQ_REJ:
-	case OM2K_MSGT_CON_CONF_REQ_REJ:
-	case OM2K_MSGT_IS_CONF_REQ_REJ:
-	case OM2K_MSGT_TX_CONF_REQ_REJ:
-	case OM2K_MSGT_RX_CONF_REQ_REJ:
-	case OM2K_MSGT_TS_CONF_REQ_REJ:
-	case OM2K_MSGT_TF_CONF_REQ_REJ:
-	case OM2K_MSGT_ENABLE_REQ_REJ:
-	case OM2K_MSGT_ALARM_STATUS_REQ_REJ:
-	case OM2K_MSGT_DISABLE_REQ_REJ:
-		rc = om2k_rx_nack(msg);
-		break;
-	}
-
-	/* Resolve the MO for this message */
-	mo = get_om2k_mo(bts, &o2h->mo);
-	if (!mo) {
-		LOGP(DNM, LOGL_ERROR, "Couldn't resolve MO for OM2K msg "
-		     "%s: %s\n", get_value_string(om2k_msgcode_vals, msg_type),
-		     msgb_hexdump(msg));
-		return 0;
-	}
-	if (!mo->fsm) {
-		LOGP(DNM, LOGL_ERROR, "MO object should not generate any message. fsm == NULL "
-		     "%s: %s\n", get_value_string(om2k_msgcode_vals, msg_type),
-		     msgb_hexdump(msg));
-		return 0;
-	}
-
-	/* Dispatch message to that MO */
-	om2k_mo_fsm_recvmsg(bts, mo, &odm);
-
-	msgb_free(msg);
-	return rc;
-}
-
-static void om2k_mo_init(struct om2k_mo *mo, uint8_t class,
-			 uint8_t bts_nr, uint8_t assoc_so, uint8_t inst)
-{
-	mo->addr.class = class;
-	mo->addr.bts = bts_nr;
-	mo->addr.assoc_so = assoc_so;
-	mo->addr.inst = inst;
-}
-
-/* initialize the OM2K_MO members of gsm_bts_trx and its timeslots */
-void abis_om2k_trx_init(struct gsm_bts_trx *trx)
-{
-	struct gsm_bts *bts = trx->bts;
-	unsigned int i;
-
-	OSMO_ASSERT(bts->type == GSM_BTS_TYPE_RBS2000);
-
-	om2k_mo_init(&trx->rbs2000.trxc.om2k_mo, OM2K_MO_CLS_TRXC,
-		     bts->nr, 255, trx->nr);
-	om2k_mo_init(&trx->rbs2000.tx.om2k_mo, OM2K_MO_CLS_TX,
-		     bts->nr, 255, trx->nr);
-	om2k_mo_init(&trx->rbs2000.rx.om2k_mo, OM2K_MO_CLS_RX,
-		     bts->nr, 255, trx->nr);
-
-	for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
-		om2k_mo_init(&trx->ts[i].rbs2000.om2k_mo, OM2K_MO_CLS_TS,
-				bts->nr, trx->nr, i);
-	}
-}
-
-/* initialize the OM2K_MO members of gsm_bts */
-void abis_om2k_bts_init(struct gsm_bts *bts)
-{
-	OSMO_ASSERT(bts->type == GSM_BTS_TYPE_RBS2000);
-
-	om2k_mo_init(&bts->rbs2000.cf.om2k_mo, OM2K_MO_CLS_CF,
-			bts->nr, 0xFF, 0);
-	om2k_mo_init(&bts->rbs2000.is.om2k_mo, OM2K_MO_CLS_IS,
-			bts->nr, 0xFF, 0);
-	om2k_mo_init(&bts->rbs2000.con.om2k_mo, OM2K_MO_CLS_CON,
-			bts->nr, 0xFF, 0);
-	om2k_mo_init(&bts->rbs2000.dp.om2k_mo, OM2K_MO_CLS_DP,
-			bts->nr, 0xFF, 0);
-	om2k_mo_init(&bts->rbs2000.tf.om2k_mo, OM2K_MO_CLS_TF,
-			bts->nr, 0xFF, 0);
-}
-
-static __attribute__((constructor)) void abis_om2k_init(void)
-{
-	osmo_fsm_register(&om2k_mo_fsm);
-	osmo_fsm_register(&om2k_bts_fsm);
-	osmo_fsm_register(&om2k_trx_fsm);
-}
diff --git a/src/libbsc/abis_om2000_vty.c b/src/libbsc/abis_om2000_vty.c
deleted file mode 100644
index a6bc4c7..0000000
--- a/src/libbsc/abis_om2000_vty.c
+++ /dev/null
@@ -1,609 +0,0 @@
-/* VTY interface for A-bis OM2000 */
-
-/* (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/>.
- *
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdint.h>
-
-#include <arpa/inet.h>
-
-#include <openbsc/gsm_data.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/core/talloc.h>
-#include <openbsc/debug.h>
-#include <openbsc/signal.h>
-#include <openbsc/abis_om2000.h>
-#include <openbsc/vty.h>
-
-#include <osmocom/vty/vty.h>
-#include <osmocom/vty/command.h>
-#include <osmocom/vty/logging.h>
-#include <osmocom/vty/telnet_interface.h>
-
-extern struct gsm_network *bsc_gsmnet;
-
-static struct cmd_node om2k_node = {
-	OM2K_NODE,
-	"%s(om2k)# ",
-	1,
-};
-
-static struct cmd_node om2k_con_group_node = {
-	OM2K_CON_GROUP_NODE,
-	"%s(om2k-con-group)# ",
-	1,
-};
-
-struct con_group;
-
-struct oml_node_state {
-	struct gsm_bts *bts;
-	struct abis_om2k_mo mo;
-	struct con_group *cg;
-};
-
-static int dummy_config_write(struct vty *v)
-{
-	return CMD_SUCCESS;
-}
-
-/* FIXME: auto-generate those strings from the value_string lists */
-#define OM2K_OBJCLASS_VTY "(trxc|ts|tf|is|con|dp|cf|tx|rx)"
-#define OM2K_OBJCLASS_VTY_HELP 	"TRX Controller\n"	\
-				"Timeslot\n"		\
-				"Timing Function\n"	\
-				"Interface Switch\n"	\
-				"Abis Concentrator\n"	\
-				"Digital Path\n"	\
-				"Central Function\n"	\
-				"Transmitter\n"		\
-				"Receiver\n"
-
-DEFUN(om2k_class_inst, om2k_class_inst_cmd,
-	"bts <0-255> om2000 class " OM2K_OBJCLASS_VTY
-					" <0-255> <0-255> <0-255>",
-	"BTS related commands\n" "BTS Number\n"
-	"Manipulate the OM2000 managed objects\n"
-	"Object Class\n" 	OM2K_OBJCLASS_VTY_HELP
-	"BTS Number\n" "Associated SO Instance\n" "Instance Number\n")
-{
-	struct gsm_bts *bts;
-	struct oml_node_state *oms;
-	int bts_nr = atoi(argv[0]);
-
-	bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr);
-	if (!bts) {
-		vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (bts->type != GSM_BTS_TYPE_RBS2000) {
-		vty_out(vty, "%% BTS %d not an Ericsson RBS%s",
-			bts_nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
-	if (!oms)
-		return CMD_WARNING;
-
-	oms->bts = bts;
-	oms->mo.class = get_string_value(om2k_mo_class_short_vals, argv[1]);
-	oms->mo.bts = atoi(argv[2]);
-	oms->mo.assoc_so = atoi(argv[3]);
-	oms->mo.inst = atoi(argv[4]);
-
-	vty->index = oms;
-	vty->node = OM2K_NODE;
-
-	return CMD_SUCCESS;
-
-}
-
-DEFUN(om2k_classnum_inst, om2k_classnum_inst_cmd,
-	"bts <0-255> om2000 class <0-255> <0-255> <0-255> <0-255>",
-	"BTS related commands\n" "BTS Number\n"
-	"Manipulate the OML managed objects\n"
-	"Object Class\n" "Object Class\n"
-	"BTS Number\n" "Associated SO Instance\n" "Instance Number\n")
-{
-	struct gsm_bts *bts;
-	struct oml_node_state *oms;
-	int bts_nr = atoi(argv[0]);
-
-	bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr);
-	if (!bts) {
-		vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
-	if (!oms)
-		return CMD_WARNING;
-
-	oms->bts = bts;
-	oms->mo.class = atoi(argv[1]);
-	oms->mo.bts = atoi(argv[2]);
-	oms->mo.assoc_so = atoi(argv[3]);
-	oms->mo.inst = atoi(argv[4]);
-
-	vty->index = oms;
-	vty->node = OM2K_NODE;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(om2k_reset, om2k_reset_cmd,
-	"reset-command",
-	"Reset the MO\n")
-{
-	struct oml_node_state *oms = vty->index;
-
-	abis_om2k_tx_reset_cmd(oms->bts, &oms->mo);
-	return CMD_SUCCESS;
-}
-
-DEFUN(om2k_start, om2k_start_cmd,
-	"start-request",
-	"Start the MO\n")
-{
-	struct oml_node_state *oms = vty->index;
-
-	abis_om2k_tx_start_req(oms->bts, &oms->mo);
-	return CMD_SUCCESS;
-}
-
-DEFUN(om2k_status, om2k_status_cmd,
-	"status-request",
-	"Get the MO Status\n")
-{
-	struct oml_node_state *oms = vty->index;
-
-	abis_om2k_tx_status_req(oms->bts, &oms->mo);
-	return CMD_SUCCESS;
-}
-
-DEFUN(om2k_connect, om2k_connect_cmd,
-	"connect-command",
-	"Connect the MO\n")
-{
-	struct oml_node_state *oms = vty->index;
-
-	abis_om2k_tx_connect_cmd(oms->bts, &oms->mo);
-	return CMD_SUCCESS;
-}
-
-DEFUN(om2k_disconnect, om2k_disconnect_cmd,
-	"disconnect-command",
-	"Disconnect the MO\n")
-{
-	struct oml_node_state *oms = vty->index;
-
-	abis_om2k_tx_disconnect_cmd(oms->bts, &oms->mo);
-	return CMD_SUCCESS;
-}
-
-DEFUN(om2k_enable, om2k_enable_cmd,
-	"enable-request",
-	"Enable the MO\n")
-{
-	struct oml_node_state *oms = vty->index;
-
-	abis_om2k_tx_enable_req(oms->bts, &oms->mo);
-	return CMD_SUCCESS;
-}
-
-DEFUN(om2k_disable, om2k_disable_cmd,
-	"disable-request",
-	"Disable the MO\n")
-{
-	struct oml_node_state *oms = vty->index;
-
-	abis_om2k_tx_disable_req(oms->bts, &oms->mo);
-	return CMD_SUCCESS;
-}
-
-DEFUN(om2k_op_info, om2k_op_info_cmd,
-	"operational-info <0-1>",
-	"Set operational information\n"
-	"Set operational info to 0 or 1\n")
-{
-	struct oml_node_state *oms = vty->index;
-	int oper = atoi(argv[0]);
-
-	abis_om2k_tx_op_info(oms->bts, &oms->mo, oper);
-	return CMD_SUCCESS;
-}
-
-DEFUN(om2k_test, om2k_test_cmd,
-	"test-request",
-	"Test the MO\n")
-{
-	struct oml_node_state *oms = vty->index;
-
-	abis_om2k_tx_test_req(oms->bts, &oms->mo);
-	return CMD_SUCCESS;
-}
-
-DEFUN(om2k_cap_req, om2k_cap_req_cmd,
-	"capabilities-request",
-	"Request MO capabilities\n")
-{
-	struct oml_node_state *oms = vty->index;
-
-	abis_om2k_tx_cap_req(oms->bts, &oms->mo);
-	return CMD_SUCCESS;
-}
-
-static struct con_group *con_group_find_or_create(struct gsm_bts *bts, uint8_t cg)
-{
-	struct con_group *ent;
-
-	llist_for_each_entry(ent, &bts->rbs2000.con.conn_groups, list) {
-		if (ent->cg == cg)
-			return ent;
-	}
-
-	ent = talloc_zero(bts, struct con_group);
-	ent->bts = bts;
-	ent->cg = cg;
-	INIT_LLIST_HEAD(&ent->paths);
-	llist_add_tail(&ent->list, &bts->rbs2000.con.conn_groups);
-
-	return ent;
-}
-
-static int con_group_del(struct gsm_bts *bts, uint8_t cg_id)
-{
-	struct con_group *cg, *cg2;
-
-	llist_for_each_entry_safe(cg, cg2, &bts->rbs2000.con.conn_groups, list) {
-		if (cg->cg == cg_id) {
-			llist_del(&cg->list);
-			talloc_free(cg);
-			return 0;
-		};
-	}
-	return -ENOENT;
-}
-
-static void con_group_add_path(struct con_group *cg, uint16_t ccp,
-				uint8_t ci, uint8_t tag, uint8_t tei)
-{
-	struct con_path *cp = talloc_zero(cg, struct con_path);
-
-	cp->ccp = ccp;
-	cp->ci = ci;
-	cp->tag = tag;
-	cp->tei = tei;
-	llist_add(&cp->list, &cg->paths);
-}
-
-static int con_group_del_path(struct con_group *cg, uint16_t ccp,
-				uint8_t ci, uint8_t tag, uint8_t tei)
-{
-	struct con_path *cp, *cp2;
-	llist_for_each_entry_safe(cp, cp2, &cg->paths, list) {
-		if (cp->ccp == ccp && cp->ci == ci && cp->tag == tag &&
-		    cp->tei == tei) {
-			llist_del(&cp->list);
-			talloc_free(cp);
-			return 0;
-		}
-	}
-	return -ENOENT;
-}
-
-DEFUN(cfg_om2k_con_group, cfg_om2k_con_group_cmd,
-	"con-connection-group <1-31>",
-	"Configure a CON (Concentrator) Connection Group\n"
-	"CON Connection Group Number\n")
-{
-	struct gsm_bts *bts = vty->index;
-	struct con_group *cg;
-	uint8_t cgid = atoi(argv[0]);
-
-	if (bts->type != GSM_BTS_TYPE_RBS2000) {
-		vty_out(vty, "%% CON MO only exists in RBS2000%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	cg = con_group_find_or_create(bts, cgid);
-	if (!cg) {
-		vty_out(vty, "%% Cannot create CON Group%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	vty->node = OM2K_CON_GROUP_NODE;
-	vty->index = cg;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(del_om2k_con_group, del_om2k_con_group_cmd,
-	"del-connection-group <1-31>",
-	"Delete a CON (Concentrator) Connection Group\n"
-	"CON Connection Group Number\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int rc;
-	uint8_t cgid = atoi(argv[0]);
-
-	if (bts->type != GSM_BTS_TYPE_RBS2000) {
-		vty_out(vty, "%% CON MO only exists in RBS2000%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	rc = con_group_del(bts, cgid);
-	if (rc != 0) {
-		vty_out(vty, "%% Cannot delete CON Group%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	return CMD_SUCCESS;
-}
-
-#define CON_PATH_HELP	"CON Path (In/Out)\n"				\
-			"Add CON Path to Concentration Group\n"		\
-			"Delete CON Path from Concentration Group\n"	\
-			"CON Conection Point\n"				\
-			"Contiguity Index\n"				\
-
-DEFUN(cfg_om2k_con_path_dec, cfg_om2k_con_path_dec_cmd,
-	"con-path (add|del) <0-2047> <0-255> deconcentrated <0-63>",
-	CON_PATH_HELP "De-concentrated in/outlet\n" "TEI Value\n")
-{
-	struct con_group *cg = vty->index;
-	uint16_t ccp = atoi(argv[1]);
-	uint8_t ci = atoi(argv[2]);
-	uint8_t tei = atoi(argv[3]);
-
-	if (!strcmp(argv[0], "add"))
-		con_group_add_path(cg, ccp, ci, 0, tei);
-	else {
-		if (con_group_del_path(cg, ccp, ci, 0, tei) < 0) {
-			vty_out(vty, "%% No matching CON Path%s",
-				VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_om2k_con_path_conc, cfg_om2k_con_path_conc_cmd,
-	"con-path (add|del) <0-2047> <0-255> concentrated <1-16>",
-	CON_PATH_HELP "Concentrated in/outlet\n" "Tag Number\n")
-{
-	struct con_group *cg = vty->index;
-	uint16_t ccp = atoi(argv[1]);
-	uint8_t ci = atoi(argv[2]);
-	uint8_t tag = atoi(argv[3]);
-
-	if (!strcmp(argv[0], "add"))
-		con_group_add_path(cg, ccp, ci, tag, 0xff);
-	else {
-		if (con_group_del_path(cg, ccp, ci, tag, 0xff) < 0) {
-			vty_out(vty, "%% No matching CON list entry%s",
-				VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_alt_mode, cfg_bts_alt_mode_cmd,
-	"abis-lower-transport (single-timeslot|super-channel)",
-	"Configure thee Abis Lower Transport\n"
-	"Single Timeslot (classic Abis)\n"
-	"SuperChannel (Packet Abis)\n")
-{
-	struct gsm_bts *bts = vty->index;
-	struct con_group *cg;
-
-	if (bts->type != GSM_BTS_TYPE_RBS2000) {
-		vty_out(vty, "%% Command only works for RBS2000%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (!strcmp(argv[0], "super-channel"))
-		bts->rbs2000.use_superchannel = 1;
-	else
-		bts->rbs2000.use_superchannel = 0;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_is_conn_list, cfg_bts_is_conn_list_cmd,
-	"is-connection-list (add|del) <0-2047> <0-2047> <0-255>",
-	"Interface Switch Connection List\n"
-	"Add to IS list\n" "Delete from IS list\n"
-	"ICP1\n" "ICP2\n" "Contiguity Index\n")
-{
-	struct gsm_bts *bts = vty->index;
-	uint16_t icp1 = atoi(argv[1]);
-	uint16_t icp2 = atoi(argv[2]);
-	uint8_t ci = atoi(argv[3]);
-	struct is_conn_group *grp, *grp2;
-
-	if (bts->type != GSM_BTS_TYPE_RBS2000) {
-		vty_out(vty, "%% IS MO only exists in RBS2000%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (!strcmp(argv[0], "add")) {
-		grp = talloc_zero(bts, struct is_conn_group);
-		grp->icp1 = icp1;
-		grp->icp2 = icp2;
-		grp->ci = ci;
-		llist_add_tail(&grp->list, &bts->rbs2000.is.conn_groups);
-	} else {
-		llist_for_each_entry_safe(grp, grp2, &bts->rbs2000.is.conn_groups, list) {
-			if (grp->icp1 == icp1 && grp->icp2 == icp2
-			    && grp->ci == ci) {
-				llist_del(&grp->list);
-				talloc_free(grp);
-				return CMD_SUCCESS;
-			}
-		}
-		vty_out(vty, "%% No matching IS Conn Group found!%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	return CMD_SUCCESS;
-}
-
-
-DEFUN(om2k_conf_req, om2k_conf_req_cmd,
-	"configuration-request",
-	"Send the configuration request for current MO\n")
-{
-	struct oml_node_state *oms = vty->index;
-	struct gsm_bts *bts = oms->bts;
-	struct gsm_bts_trx *trx = NULL;
-	struct gsm_bts_trx_ts *ts = NULL;
-
-	switch (oms->mo.class) {
-	case OM2K_MO_CLS_IS:
-		abis_om2k_tx_is_conf_req(bts);
-		break;
-	case OM2K_MO_CLS_TS:
-		trx = gsm_bts_trx_by_nr(bts, oms->mo.assoc_so);
-		if (!trx) {
-			vty_out(vty, "%% BTS %u has no TRX %u%s", bts->nr,
-				oms->mo.assoc_so, VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-		if (oms->mo.inst >= ARRAY_SIZE(trx->ts)) {
-			vty_out(vty, "%% Timeslot %u out of range%s",
-				oms->mo.inst, VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-		ts = &trx->ts[oms->mo.inst];
-		abis_om2k_tx_ts_conf_req(ts);
-		break;
-	case OM2K_MO_CLS_RX:
-	case OM2K_MO_CLS_TX:
-	case OM2K_MO_CLS_TRXC:
-		trx = gsm_bts_trx_by_nr(bts, oms->mo.inst);
-		if (!trx) {
-			vty_out(vty, "%% BTS %u has no TRX %u%s", bts->nr,
-				oms->mo.inst, VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-		switch (oms->mo.class) {
-		case OM2K_MO_CLS_RX:
-			abis_om2k_tx_rx_conf_req(trx);
-			break;
-		case OM2K_MO_CLS_TX:
-			abis_om2k_tx_tx_conf_req(trx);
-			break;
-		default:
-			break;
-		}
-		break;
-	case OM2K_MO_CLS_TF:
-		abis_om2k_tx_tf_conf_req(bts);
-		break;
-	default:
-		vty_out(vty, "%% Don't know how to configure MO%s",
-			VTY_NEWLINE);
-	}
-
-	return CMD_SUCCESS;
-}
-
-static void dump_con_group(struct vty *vty, struct con_group *cg)
-{
-	struct con_path *cp;
-
-	llist_for_each_entry(cp, &cg->paths, list) {
-		vty_out(vty, "   con-path add %u %u ", cp->ccp, cp->ci);
-		if (cp->tei == 0xff) {
-			vty_out(vty, "concentrated %u%s", cp->tag,
-				VTY_NEWLINE);
-		} else {
-			vty_out(vty, "deconcentrated %u%s", cp->tei,
-				VTY_NEWLINE);
-		}
-	}
-}
-
-void abis_om2k_config_write_bts(struct vty *vty, struct gsm_bts *bts)
-{
-	struct is_conn_group *igrp;
-	struct con_group *cgrp;
-
-	llist_for_each_entry(igrp, &bts->rbs2000.is.conn_groups, list)
-		vty_out(vty, "  is-connection-list add %u %u %u%s",
-			igrp->icp1, igrp->icp2, igrp->ci, VTY_NEWLINE);
-
-	llist_for_each_entry(cgrp, &bts->rbs2000.con.conn_groups, list) {
-		vty_out(vty, "  con-connection-group %u%s", cgrp->cg,
-			VTY_NEWLINE);
-		dump_con_group(vty, cgrp);
-	}
-	if (bts->rbs2000.use_superchannel)
-		vty_out(vty, "  abis-lower-transport super-channel%s",
-			VTY_NEWLINE);
-}
-
-int abis_om2k_vty_init(void)
-{
-	install_element(ENABLE_NODE, &om2k_class_inst_cmd);
-	install_element(ENABLE_NODE, &om2k_classnum_inst_cmd);
-	install_node(&om2k_node, dummy_config_write);
-
-	vty_install_default(OM2K_NODE);
-	install_element(OM2K_NODE, &om2k_reset_cmd);
-	install_element(OM2K_NODE, &om2k_start_cmd);
-	install_element(OM2K_NODE, &om2k_status_cmd);
-	install_element(OM2K_NODE, &om2k_connect_cmd);
-	install_element(OM2K_NODE, &om2k_disconnect_cmd);
-	install_element(OM2K_NODE, &om2k_enable_cmd);
-	install_element(OM2K_NODE, &om2k_disable_cmd);
-	install_element(OM2K_NODE, &om2k_op_info_cmd);
-	install_element(OM2K_NODE, &om2k_test_cmd);
-	install_element(OM2K_NODE, &om2k_cap_req_cmd);
-	install_element(OM2K_NODE, &om2k_conf_req_cmd);
-
-	install_node(&om2k_con_group_node, dummy_config_write);
-	vty_install_default(OM2K_CON_GROUP_NODE);
-	install_element(OM2K_CON_GROUP_NODE, &cfg_om2k_con_path_dec_cmd);
-	install_element(OM2K_CON_GROUP_NODE, &cfg_om2k_con_path_conc_cmd);
-
-	install_element(BTS_NODE, &cfg_bts_is_conn_list_cmd);
-	install_element(BTS_NODE, &cfg_bts_alt_mode_cmd);
-	install_element(BTS_NODE, &cfg_om2k_con_group_cmd);
-	install_element(BTS_NODE, &del_om2k_con_group_cmd);
-
-	return 0;
-}
diff --git a/src/libbsc/abis_rsl.c b/src/libbsc/abis_rsl.c
deleted file mode 100644
index 66cda82..0000000
--- a/src/libbsc/abis_rsl.c
+++ /dev/null
@@ -1,2939 +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-2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2012 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/>.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_04_08.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/chan_alloc.h>
-#include <openbsc/bsc_rll.h>
-#include <openbsc/debug.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/gsm/protocol/gsm_04_08.h>
-#include <osmocom/gsm/protocol/gsm_08_58.h>
-#include <openbsc/paging.h>
-#include <openbsc/signal.h>
-#include <openbsc/meas_rep.h>
-#include <openbsc/rtp_proxy.h>
-#include <openbsc/gsm_subscriber.h>
-#include <osmocom/abis/e1_input.h>
-#include <osmocom/gsm/rsl.h>
-#include <osmocom/core/talloc.h>
-#include <openbsc/pcu_if.h>
-
-#define RSL_ALLOC_SIZE		1024
-#define RSL_ALLOC_HEADROOM	128
-
-enum sacch_deact {
-	SACCH_NONE,
-	SACCH_DEACTIVATE,
-};
-
-static int rsl_send_imm_assignment(struct gsm_lchan *lchan);
-static void error_timeout_cb(void *data);
-static int dyn_ts_switchover_continue(struct gsm_bts_trx_ts *ts);
-static int dyn_ts_switchover_failed(struct gsm_bts_trx_ts *ts, int rc);
-static void dyn_ts_switchover_complete(struct gsm_lchan *lchan);
-
-static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan,
-			      struct gsm_meas_rep *resp)
-{
-	struct lchan_signal_data sig;
-	sig.lchan = lchan;
-	sig.mr = resp;
-	osmo_signal_dispatch(SS_LCHAN, sig_no, &sig);
-}
-
-static void do_lchan_free(struct gsm_lchan *lchan)
-{
-	/* We start the error timer to make the channel available again */
-	if (lchan->state == LCHAN_S_REL_ERR) {
-		osmo_timer_setup(&lchan->error_timer, error_timeout_cb, lchan);
-		osmo_timer_schedule(&lchan->error_timer,
-				   lchan->ts->trx->bts->network->T3111 + 2, 0);
-	} else {
-		rsl_lchan_set_state(lchan, LCHAN_S_NONE);
-	}
-	lchan_free(lchan);
-}
-
-static void count_codecs(struct gsm_bts *bts, struct gsm_lchan *lchan)
-{
-	OSMO_ASSERT(bts);
-
-	if (lchan->type == GSM_LCHAN_TCH_H) {
-		switch (lchan->tch_mode) {
-		case GSM48_CMODE_SPEECH_AMR:
-			rate_ctr_inc(&bts->network->bsc_ctrs->ctr[BSC_CTR_CODEC_AMR_H]);
-			break;
-		case GSM48_CMODE_SPEECH_V1:
-			rate_ctr_inc(&bts->network->bsc_ctrs->ctr[BSC_CTR_CODEC_V1_HR]);
-			break;
-		default:
-			break;
-		}
-	} else if (lchan->type == GSM_LCHAN_TCH_F) {
-		switch (lchan->tch_mode) {
-		case GSM48_CMODE_SPEECH_AMR:
-			rate_ctr_inc(&bts->network->bsc_ctrs->ctr[BSC_CTR_CODEC_AMR_F]);
-			break;
-		case GSM48_CMODE_SPEECH_V1:
-			rate_ctr_inc(&bts->network->bsc_ctrs->ctr[BSC_CTR_CODEC_V1_FR]);
-			break;
-		case GSM48_CMODE_SPEECH_EFR:
-			rate_ctr_inc(&bts->network->bsc_ctrs->ctr[BSC_CTR_CODEC_EFR]);
-			break;
-		default:
-			break;
-		}
-	}
-}
-
-static uint8_t mdisc_by_msgtype(uint8_t msg_type)
-{
-	/* mask off the transparent bit ? */
-	msg_type &= 0xfe;
-
-	if ((msg_type & 0xf0) == 0x00)
-		return ABIS_RSL_MDISC_RLL;
-	if ((msg_type & 0xf0) == 0x10) {
-		if (msg_type >= 0x19 && msg_type <= 0x22)
-			return ABIS_RSL_MDISC_TRX;
-		else
-			return ABIS_RSL_MDISC_COM_CHAN;
-	}
-	if ((msg_type & 0xe0) == 0x20)
-		return ABIS_RSL_MDISC_DED_CHAN;
-	
-	return ABIS_RSL_MDISC_LOC;
-}
-
-static inline void init_dchan_hdr(struct abis_rsl_dchan_hdr *dh,
-				  uint8_t msg_type)
-{
-	dh->c.msg_discr = mdisc_by_msgtype(msg_type);
-	dh->c.msg_type = msg_type;
-	dh->ie_chan = RSL_IE_CHAN_NR;
-}
-
-/* call rsl_lchan_lookup and set the log context */
-static struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,
-				      const char *log_name)
-{
-	int rc;
-	struct gsm_lchan *lchan = rsl_lchan_lookup(trx, chan_nr, &rc);
-
-	if (!lchan) {
-		LOGP(DRSL, LOGL_ERROR, "%sunknown chan_nr=0x%02x\n",
-		     log_name, chan_nr);
-		return NULL;
-	}
-
-	if (rc < 0)
-		LOGP(DRSL, LOGL_ERROR, "%s %smismatching chan_nr=0x%02x\n",
-		     gsm_ts_and_pchan_name(lchan->ts), log_name, chan_nr);
-
-	if (lchan->conn)
-		log_set_context(LOG_CTX_VLR_SUBSCR, lchan->conn->vsub);
-
-	return lchan;
-}
-
-/* As per TS 03.03 Section 2.2, the IMSI has 'not more than 15 digits' */
-uint64_t str_to_imsi(const char *imsi_str)
-{
-	uint64_t ret;
-
-	ret = strtoull(imsi_str, NULL, 10);
-
-	return ret;
-}
-
-static struct msgb *rsl_msgb_alloc(void)
-{
-	return msgb_alloc_headroom(RSL_ALLOC_SIZE, RSL_ALLOC_HEADROOM,
-				   "RSL");
-}
-
-static void pad_macblock(uint8_t *out, const uint8_t *in, int len)
-{
-	memcpy(out, in, len);
-
-	if (len < GSM_MACBLOCK_LEN)
-		memset(out+len, 0x2b, GSM_MACBLOCK_LEN - len);
-}
-
-/* Chapter 9.3.7: Encryption Information */
-static int build_encr_info(uint8_t *out, struct gsm_lchan *lchan)
-{
-	*out++ = lchan->encr.alg_id & 0xff;
-	if (lchan->encr.key_len)
-		memcpy(out, lchan->encr.key, lchan->encr.key_len);
-	return lchan->encr.key_len + 1;
-}
-
-static void print_rsl_cause(int lvl, const uint8_t *cause_v, uint8_t cause_len)
-{
-	int i;
-
-	LOGPC(DRSL, lvl, "CAUSE=0x%02x(%s) ",
-		cause_v[0], rsl_err_name(cause_v[0]));
-	for (i = 1; i < cause_len-1; i++)
-		LOGPC(DRSL, lvl, "%02x ", cause_v[i]);
-}
-
-static void lchan_act_tmr_cb(void *data)
-{
-	struct gsm_lchan *lchan = data;
-
-	rsl_lchan_mark_broken(lchan, "activation timeout");
-	lchan_free(lchan);
-}
-
-static void lchan_deact_tmr_cb(void *data)
-{
-	struct gsm_lchan *lchan = data;
-
-	rsl_lchan_mark_broken(lchan, "de-activation timeout");
-	lchan_free(lchan);
-}
-
-
-/* Send a BCCH_INFO message as per Chapter 8.5.1 */
-int rsl_bcch_info(const struct gsm_bts_trx *trx, enum osmo_sysinfo_type si_type, const uint8_t *data, int len)
-{
-	struct abis_rsl_dchan_hdr *dh;
-	const struct gsm_bts *bts = trx->bts;
-	struct msgb *msg = rsl_msgb_alloc();
-	uint8_t type = osmo_sitype2rsl(si_type);
-
-	if (bts->c0 != trx)
-		LOGP(DRR, LOGL_ERROR, "Attempting to set BCCH SI%s on wrong BTS%u/TRX%u\n",
-		     get_value_string(osmo_sitype_strs, si_type), bts->nr, trx->nr);
-
-	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof*dh);
-	init_dchan_hdr(dh, RSL_MT_BCCH_INFO);
-	dh->chan_nr = RSL_CHAN_BCCH;
-
-	if (trx->bts->type == GSM_BTS_TYPE_RBS2000
-	    && type == RSL_SYSTEM_INFO_13) {
-		/* Ericsson proprietary encoding of SI13 */
-		msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, RSL_ERIC_SYSTEM_INFO_13);
-		if (data)
-			msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
-		msgb_tv_put(msg, RSL_IE_ERIC_BCCH_MAPPING, 0x00);
-	} else {
-		/* Normal encoding */
-		msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
-		if (data)
-			msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
-	}
-
-	msg->dst = trx->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type,
-		      const uint8_t *data, int len)
-{
-	struct abis_rsl_common_hdr *ch;
-	struct msgb *msg = rsl_msgb_alloc();
-
-	ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
-	ch->msg_discr = ABIS_RSL_MDISC_TRX;
-	ch->msg_type = RSL_MT_SACCH_FILL;
-
-	msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
-	if (data)
-		msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
-
-	msg->dst = trx->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-int rsl_sacch_info_modify(struct gsm_lchan *lchan, uint8_t type,
-			  const uint8_t *data, int len)
-{
-	struct abis_rsl_dchan_hdr *dh;
-	struct msgb *msg = rsl_msgb_alloc();
-	uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
-
-	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
-	init_dchan_hdr(dh, RSL_MT_SACCH_INFO_MODIFY);
-	dh->chan_nr = chan_nr;
-
-	msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
-	if (data)
-		msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
-
-	msg->dst = lchan->ts->trx->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
-{
-	struct abis_rsl_dchan_hdr *dh;
-	struct msgb *msg;
-	uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
-
-	db = abs(db);
-	if (db > 30)
-		return -EINVAL;
-
-	msg = rsl_msgb_alloc();
-
-	lchan->bs_power = db/2;
-	if (fpc)
-		lchan->bs_power |= 0x10;
-	
-	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
-	init_dchan_hdr(dh, RSL_MT_BS_POWER_CONTROL);
-	dh->chan_nr = chan_nr;
-
-	msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
-
-	msg->dst = lchan->ts->trx->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm)
-{
-	struct abis_rsl_dchan_hdr *dh;
-	struct msgb *msg;
-	uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
-	int ctl_lvl;
-
-	ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, dbm);
-	if (ctl_lvl < 0)
-		return ctl_lvl;
-
-	msg = rsl_msgb_alloc();
-
-	lchan->ms_power = ctl_lvl;
-
-	if (fpc)
-		lchan->ms_power |= 0x20;
-	
-	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
-	init_dchan_hdr(dh, RSL_MT_MS_POWER_CONTROL);
-	dh->chan_nr = chan_nr;
-
-	msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
-
-	msg->dst = lchan->ts->trx->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
-				   struct gsm_lchan *lchan)
-{
-	memset(cm, 0, sizeof(*cm));
-
-	/* FIXME: what to do with data calls ? */
-	cm->dtx_dtu = 0;
-	if (lchan->ts->trx->bts->dtxu != GSM48_DTX_SHALL_NOT_BE_USED)
-		cm->dtx_dtu |= RSL_CMOD_DTXu;
-	if (lchan->ts->trx->bts->dtxd)
-		cm->dtx_dtu |= RSL_CMOD_DTXd;
-
-	/* set TCH Speech/Data */
-	cm->spd_ind = lchan->rsl_cmode;
-
-	if (lchan->rsl_cmode == RSL_CMOD_SPD_SIGN &&
-	    lchan->tch_mode != GSM48_CMODE_SIGN)
-		LOGP(DRSL, LOGL_ERROR, "unsupported: rsl_mode == signalling, "
-			"but tch_mode != signalling\n");
-
-	switch (lchan->type) {
-	case GSM_LCHAN_SDCCH:
-		cm->chan_rt = RSL_CMOD_CRT_SDCCH;
-		break;
-	case GSM_LCHAN_TCH_F:
-		cm->chan_rt = RSL_CMOD_CRT_TCH_Bm;
-		break;
-	case GSM_LCHAN_TCH_H:
-		cm->chan_rt = RSL_CMOD_CRT_TCH_Lm;
-		break;
-	case GSM_LCHAN_NONE:
-	case GSM_LCHAN_UNKNOWN:
-	default:
-		LOGP(DRSL, LOGL_ERROR,
-		     "unsupported activation lchan->type %u %s\n",
-		     lchan->type, gsm_lchant_name(lchan->type));
-		return -EINVAL;
-	}
-
-	switch (lchan->tch_mode) {
-	case GSM48_CMODE_SIGN:
-		cm->chan_rate = 0;
-		break;
-	case GSM48_CMODE_SPEECH_V1:
-		cm->chan_rate = RSL_CMOD_SP_GSM1;
-		break;
-	case GSM48_CMODE_SPEECH_EFR:
-		cm->chan_rate = RSL_CMOD_SP_GSM2;
-		break;
-	case GSM48_CMODE_SPEECH_AMR:
-		cm->chan_rate = RSL_CMOD_SP_GSM3;
-		break;
-	case GSM48_CMODE_DATA_14k5:
-	case GSM48_CMODE_DATA_12k0:
-	case GSM48_CMODE_DATA_6k0:
-		switch (lchan->csd_mode) {
-		case LCHAN_CSD_M_NT:
-			/* non-transparent CSD with RLP */
-			switch (lchan->tch_mode) {
-			case GSM48_CMODE_DATA_14k5:
-				cm->chan_rate = RSL_CMOD_SP_NT_14k5;
-				break;
-			case GSM48_CMODE_DATA_12k0:
-				cm->chan_rate = RSL_CMOD_SP_NT_12k0;
-				break;
-			case GSM48_CMODE_DATA_6k0:
-				cm->chan_rate = RSL_CMOD_SP_NT_6k0;
-				break;
-			default:
-				LOGP(DRSL, LOGL_ERROR,
-				     "unsupported lchan->tch_mode %u\n",
-				     lchan->tch_mode);
-				return -EINVAL;
-			}
-			break;
-			/* transparent data services below */
-		case LCHAN_CSD_M_T_1200_75:
-			cm->chan_rate = RSL_CMOD_CSD_T_1200_75;
-			break;
-		case LCHAN_CSD_M_T_600:
-			cm->chan_rate = RSL_CMOD_CSD_T_600;
-			break;
-		case LCHAN_CSD_M_T_1200:
-			cm->chan_rate = RSL_CMOD_CSD_T_1200;
-			break;
-		case LCHAN_CSD_M_T_2400:
-			cm->chan_rate = RSL_CMOD_CSD_T_2400;
-			break;
-		case LCHAN_CSD_M_T_9600:
-			cm->chan_rate = RSL_CMOD_CSD_T_9600;
-			break;
-		case LCHAN_CSD_M_T_14400:
-			cm->chan_rate = RSL_CMOD_CSD_T_14400;
-			break;
-		case LCHAN_CSD_M_T_29000:
-			cm->chan_rate = RSL_CMOD_CSD_T_29000;
-			break;
-		case LCHAN_CSD_M_T_32000:
-			cm->chan_rate = RSL_CMOD_CSD_T_32000;
-			break;
-		default:
-			LOGP(DRSL, LOGL_ERROR,
-			     "unsupported lchan->csd_mode %u\n",
-			     lchan->csd_mode);
-			return -EINVAL;
-		}
-		break;
-	default:
-		LOGP(DRSL, LOGL_ERROR,
-		     "unsupported lchan->tch_mode %u\n",
-		     lchan->tch_mode);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static void mr_config_for_bts(struct gsm_lchan *lchan, struct msgb *msg)
-{
-	if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
-		msgb_tlv_put(msg, RSL_IE_MR_CONFIG, lchan->mr_bts_lv[0],
-			     lchan->mr_bts_lv + 1);
-}
-
-static enum gsm_phys_chan_config pchan_for_lchant(enum gsm_chan_t type)
-{
-	switch (type) {
-	case GSM_LCHAN_TCH_F:
-		return GSM_PCHAN_TCH_F;
-	case GSM_LCHAN_TCH_H:
-		return GSM_PCHAN_TCH_H;
-	case GSM_LCHAN_NONE:
-	case GSM_LCHAN_PDTCH:
-		/* TODO: so far lchan->type is NONE in PDCH mode. PDTCH is only
-		 * used in osmo-bts. Maybe set PDTCH and drop the NONE case
-		 * here. */
-		return GSM_PCHAN_PDCH;
-	default:
-		return GSM_PCHAN_UNKNOWN;
-	}
-}
-
-/*! Tx simplified channel activation message for non-standard PDCH type. */
-static int rsl_chan_activate_lchan_as_pdch(struct gsm_lchan *lchan)
-{
-	struct msgb *msg;
-	struct abis_rsl_dchan_hdr *dh;
-
-	/* This might be called after release of the second lchan of a TCH/H,
-	 * but PDCH activation must always happen on the first lchan. Make sure
-	 * the calling code passes the correct lchan. */
-	OSMO_ASSERT(lchan == lchan->ts->lchan);
-
-	rsl_lchan_set_state(lchan, LCHAN_S_ACT_REQ);
-
-	msg = rsl_msgb_alloc();
-	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
-	init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
-	dh->chan_nr = gsm_lchan_as_pchan2chan_nr(lchan, GSM_PCHAN_PDCH);
-
-	msgb_tv_put(msg, RSL_IE_ACT_TYPE, RSL_ACT_OSMO_PDCH);
-
-	if (lchan->ts->trx->bts->type == GSM_BTS_TYPE_RBS2000 &&
-	    lchan->ts->trx->bts->rbs2000.use_superchannel) {
-		const uint8_t eric_pgsl_tmr[] = { 30, 1 };
-		msgb_tv_fixed_put(msg, RSL_IE_ERIC_PGSL_TIMERS,
-				  sizeof(eric_pgsl_tmr), eric_pgsl_tmr);
-	}
-
-	msg->dst = lchan->ts->trx->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-/* Chapter 8.4.1 */
-int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type,
-			    uint8_t ho_ref)
-{
-	struct abis_rsl_dchan_hdr *dh;
-	struct msgb *msg;
-	int rc;
-	uint8_t *len;
-	uint8_t ta;
-
-	struct rsl_ie_chan_mode cm;
-	struct gsm48_chan_desc cd;
-
-	/* If a TCH_F/PDCH TS is in PDCH mode, deactivate PDCH first. */
-	if (lchan->ts->pchan == GSM_PCHAN_TCH_F_PDCH
-	    && (lchan->ts->flags & TS_F_PDCH_ACTIVE)) {
-		/* store activation type and handover reference */
-		lchan->dyn.act_type = act_type;
-		lchan->dyn.ho_ref = ho_ref;
-		return rsl_ipacc_pdch_activate(lchan->ts, 0);
-	}
-
-	/*
-	 * If necessary, release PDCH on dynamic TS. Note that sending a
-	 * release here is only necessary when in PDCH mode; for TCH types, an
-	 * RSL RF Chan Release is initiated by the BTS when a voice call ends,
-	 * so when we reach this, it will already be released. If a dyn TS is
-	 * in PDCH mode, it is still active and we need to initiate a release
-	 * from the BSC side here.
-	 *
-	 * If pchan_is != pchan_want, the PDCH has already been taken down and
-	 * the switchover now needs to enable the TCH lchan.
-	 *
-	 * To switch a dyn TS between TCH/H and TCH/F, it is sufficient to send
-	 * a chan activ with the new lchan type, because it will already be
-	 * released.
-	 */
-	if (lchan->ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH
-	    && lchan->ts->dyn.pchan_is == GSM_PCHAN_PDCH
-	    && lchan->ts->dyn.pchan_is == lchan->ts->dyn.pchan_want) {
-		enum gsm_phys_chan_config pchan_want;
-		pchan_want = pchan_for_lchant(lchan->type);
-		if (lchan->ts->dyn.pchan_is != pchan_want) {
-			/*
-			 * Make sure to record on lchan[0] so that we'll find
-			 * it after the PDCH release.
-			 */
-			struct gsm_lchan *lchan0 = lchan->ts->lchan;
-			lchan0->dyn.act_type = act_type,
-			lchan0->dyn.ho_ref = ho_ref;
-			lchan0->dyn.rqd_ref = lchan->rqd_ref;
-			lchan0->dyn.rqd_ta = lchan->rqd_ta;
-			lchan->rqd_ref = NULL;
-			lchan->rqd_ta = 0;
-			DEBUGP(DRSL, "%s saved rqd_ref=%p ta=%u\n",
-			       gsm_lchan_name(lchan0), lchan0->rqd_ref,
-			       lchan0->rqd_ta);
-			return dyn_ts_switchover_start(lchan->ts, pchan_want);
-		}
-	}
-
-	DEBUGP(DRSL, "%s Tx RSL Channel Activate with act_type=%s\n",
-	       gsm_ts_and_pchan_name(lchan->ts),
-	       rsl_act_type_name(act_type));
-
-	if (act_type == RSL_ACT_OSMO_PDCH) {
-		if (lchan->ts->pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH) {
-			LOGP(DRSL, LOGL_ERROR,
-			     "%s PDCH channel activation only allowed on %s\n",
-			     gsm_ts_and_pchan_name(lchan->ts),
-			     gsm_pchan_name(GSM_PCHAN_TCH_F_TCH_H_PDCH));
-			return -EINVAL;
-		}
-		return rsl_chan_activate_lchan_as_pdch(lchan);
-	}
-
-	if (lchan->ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH
-	    && lchan->ts->dyn.pchan_want == GSM_PCHAN_PDCH) {
-		LOGP(DRSL, LOGL_ERROR,
-		     "%s Expected PDCH activation kind\n",
-		     gsm_ts_and_pchan_name(lchan->ts));
-		return -EINVAL;
-	}
-
-	rc = channel_mode_from_lchan(&cm, lchan);
-	if (rc < 0) {
-		LOGP(DRSL, LOGL_ERROR,
-		     "%s Cannot find channel mode from lchan type\n",
-		     gsm_ts_and_pchan_name(lchan->ts));
-		return rc;
-	}
-
-	rsl_lchan_set_state(lchan, LCHAN_S_ACT_REQ);
-
-	ta = lchan->rqd_ta;
-
-	/* BS11 requires TA shifted by 2 bits */
-	if (lchan->ts->trx->bts->type == GSM_BTS_TYPE_BS11)
-		ta <<= 2;
-
-	memset(&cd, 0, sizeof(cd));
-	gsm48_lchan2chan_desc(&cd, lchan);
-
-	msg = rsl_msgb_alloc();
-	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
-	init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
-
-	if (lchan->ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH)
-		dh->chan_nr = gsm_lchan_as_pchan2chan_nr(
-					lchan, lchan->ts->dyn.pchan_want);
-	else
-		dh->chan_nr = gsm_lchan2chan_nr(lchan);
-
-	msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
-	msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
-		     (uint8_t *) &cm);
-
-	/*
-	 * The Channel Identification is needed for Phase1 phones
-	 * and it contains the GSM48 Channel Description and the
-	 * Mobile Allocation. The GSM 08.58 asks for the Mobile
-	 * Allocation to have a length of zero. We are using the
-	 * msgb_l3len to calculate the length of both messages.
-	 */
-	msgb_v_put(msg, RSL_IE_CHAN_IDENT);
-	len = msgb_put(msg, 1);
-	msgb_tv_fixed_put(msg, GSM48_IE_CHANDESC_2, sizeof(cd), (const uint8_t *) &cd);
-
-	if (lchan->ts->hopping.enabled)
-		msgb_tlv_put(msg, GSM48_IE_MA_AFTER, lchan->ts->hopping.ma_len,
-			     lchan->ts->hopping.ma_data);
-	else
-		msgb_tlv_put(msg, GSM48_IE_MA_AFTER, 0, NULL);
-
-	/* update the calculated size */
-	msg->l3h = len + 1;
-	*len = msgb_l3len(msg);
-
-	if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
-		uint8_t encr_info[MAX_A5_KEY_LEN+2];
-		rc = build_encr_info(encr_info, lchan);
-		if (rc > 0)
-			msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
-	}
-
-	switch (act_type) {
-	case RSL_ACT_INTER_ASYNC:
-	case RSL_ACT_INTER_SYNC:
-		msgb_tv_put(msg, RSL_IE_HANDO_REF, ho_ref);
-		break;
-	default:
-		break;
-	}
-
-	msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
-	msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
-	msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
-	mr_config_for_bts(lchan, msg);
-
-	msg->dst = lchan->ts->trx->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-/* Chapter 8.4.9: Modify channel mode on BTS side */
-int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
-{
-	struct abis_rsl_dchan_hdr *dh;
-	struct msgb *msg;
-	int rc;
-
-	uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
-	struct rsl_ie_chan_mode cm;
-
-	rc = channel_mode_from_lchan(&cm, lchan);
-	if (rc < 0)
-		return rc;
-
-	msg = rsl_msgb_alloc();
-	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
-	init_dchan_hdr(dh, RSL_MT_MODE_MODIFY_REQ);
-	dh->chan_nr = chan_nr;
-
-	msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
-		     (uint8_t *) &cm);
-
-	if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
-		uint8_t encr_info[MAX_A5_KEY_LEN+2];
-		rc = build_encr_info(encr_info, lchan);
-		if (rc > 0)
-			msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
-	}
-
-	mr_config_for_bts(lchan, msg);
-
-	msg->dst = lchan->ts->trx->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-/* Chapter 8.4.6: Send the encryption command with given L3 info */
-int rsl_encryption_cmd(struct msgb *msg)
-{
-	struct abis_rsl_dchan_hdr *dh;
-	struct gsm_lchan *lchan = msg->lchan;
-	uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
-	uint8_t encr_info[MAX_A5_KEY_LEN+2];
-	uint8_t l3_len = msg->len;
-	int rc;
-
-	/* First push the L3 IE tag and length */
-	msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
-
-	/* then the link identifier (SAPI0, main sign link) */
-	msgb_tv_push(msg, RSL_IE_LINK_IDENT, 0);
-
-	/* then encryption information */
-	rc = build_encr_info(encr_info, lchan);
-	if (rc <= 0)
-		return rc;
-	msgb_tlv_push(msg, RSL_IE_ENCR_INFO, rc, encr_info);
-
-	/* and finally the DCHAN header */
-	dh = (struct abis_rsl_dchan_hdr *) msgb_push(msg, sizeof(*dh));
-	init_dchan_hdr(dh, RSL_MT_ENCR_CMD);
-	dh->chan_nr = chan_nr;
-
-	msg->dst = lchan->ts->trx->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-/* Chapter 8.4.5 / 4.6: Deactivate the SACCH after 04.08 RR CHAN RELEASE */
-int rsl_deact_sacch(struct gsm_lchan *lchan)
-{
-	struct abis_rsl_dchan_hdr *dh;
-	struct msgb *msg = rsl_msgb_alloc();
-
-	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
-	init_dchan_hdr(dh, RSL_MT_DEACTIVATE_SACCH);
-	dh->chan_nr = gsm_lchan2chan_nr(lchan);
-
-	msg->lchan = lchan;
-	msg->dst = lchan->ts->trx->rsl_link;
-
-	DEBUGP(DRSL, "%s DEACTivate SACCH CMD\n", gsm_lchan_name(lchan));
-
-	return abis_rsl_sendmsg(msg);
-}
-
-static bool dyn_ts_should_switch_to_pdch(struct gsm_bts_trx_ts *ts)
-{
-	int ss;
-
-	if (ts->pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH)
-		return false;
-
-	if (ts->trx->bts->gprs.mode == BTS_GPRS_NONE)
-		return false;
-
-	/* Already in PDCH mode? */
-	if (ts->dyn.pchan_is == GSM_PCHAN_PDCH)
-		return false;
-
-	/* See if all lchans are released. */
-	for (ss = 0; ss < ts_subslots(ts); ss++) {
-		struct gsm_lchan *lc = &ts->lchan[ss];
-		if (lc->state != LCHAN_S_NONE) {
-			DEBUGP(DRSL, "%s lchan %u still in use"
-			       " (type=%s,state=%s)\n",
-			       gsm_ts_and_pchan_name(ts), lc->nr,
-			       gsm_lchant_name(lc->type),
-			       gsm_lchans_name(lc->state));
-			/* An lchan is still used. */
-			return false;
-		}
-	}
-
-	/* All channels are released, go to PDCH mode. */
-	DEBUGP(DRSL, "%s back to PDCH\n",
-	       gsm_ts_and_pchan_name(ts));
-	return true;
-}
-
-static void error_timeout_cb(void *data)
-{
-	struct gsm_lchan *lchan = data;
-	if (lchan->state != LCHAN_S_REL_ERR) {
-		LOGP(DRSL, LOGL_ERROR, "%s error timeout but not in error state: %d\n",
-		     gsm_lchan_name(lchan), lchan->state);
-		return;
-	}
-
-	/* go back to the none state */
-	LOGP(DRSL, LOGL_INFO, "%s is back in operation.\n", gsm_lchan_name(lchan));
-	rsl_lchan_set_state(lchan, LCHAN_S_NONE);
-
-	/* Put PDCH channel back into PDCH mode, if GPRS is enabled */
-	if (lchan->ts->pchan == GSM_PCHAN_TCH_F_PDCH
-	    && lchan->ts->trx->bts->gprs.mode != BTS_GPRS_NONE)
-		rsl_ipacc_pdch_activate(lchan->ts, 1);
-
-	if (dyn_ts_should_switch_to_pdch(lchan->ts))
-		dyn_ts_switchover_start(lchan->ts, GSM_PCHAN_PDCH);
-}
-
-static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan);
-
-/* Chapter 8.4.14 / 4.7: Tell BTS to release the radio channel */
-static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error,
-				enum sacch_deact deact_sacch)
-{
-	struct abis_rsl_dchan_hdr *dh;
-	struct msgb *msg;
-	int rc;
-
-	/* Stop timers that should lead to a channel release */
-	osmo_timer_del(&lchan->T3109);
-
-	if (lchan->state == LCHAN_S_REL_ERR) {
-		LOGP(DRSL, LOGL_NOTICE, "%s is in error state, not sending release.\n",
-		     gsm_lchan_name(lchan));
-		return -1;
-	}
-
-	msg = rsl_msgb_alloc();
-	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
-	init_dchan_hdr(dh, RSL_MT_RF_CHAN_REL);
-	dh->chan_nr = gsm_lchan2chan_nr(lchan);
-
-	msg->lchan = lchan;
-	msg->dst = lchan->ts->trx->rsl_link;
-
-	if (error)
-		DEBUGP(DRSL, "%s RF Channel Release due to error: %d\n",
-		       gsm_lchan_name(lchan), error);
-	else
-		DEBUGP(DRSL, "%s RF Channel Release\n", gsm_lchan_name(lchan));
-
-	if (error) {
-		/*
-		 * FIXME: GSM 04.08 gives us two options for the abnormal
-		 * chanel release. This can be either like in the non-existent
-		 * sub-lcuase 3.5.1 or for the main signalling link deactivate
-		 * the SACCH, start timer T3109 and consider the channel as
-		 * released.
-		 *
-		 * This code is doing the later for all raido links and not
-		 * only the main link. Right now all SAPIs are released on the
-		 * local end, the SACCH will be de-activated and right now the
-		 * T3111 will be started. First T3109 should be started and then
-		 * the T3111.
-		 *
-		 * TODO: Move this out of the function.
-		 */
-
-		/*
-		 * sacch de-activate and "local end release"
-		 */
-		if (deact_sacch == SACCH_DEACTIVATE)
-			rsl_deact_sacch(lchan);
-		rsl_release_sapis_from(lchan, 0, RSL_REL_LOCAL_END);
-
-		/*
-		 * TODO: start T3109 now.
-		 */
-		rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
-	}
-
-	/* Start another timer or assume the BTS sends a ACK/NACK? */
-	osmo_timer_setup(&lchan->act_timer, lchan_deact_tmr_cb, lchan);
-	osmo_timer_schedule(&lchan->act_timer, 4, 0);
-
-	rc =  abis_rsl_sendmsg(msg);
-
-	/* BTS will respond by RF CHAN REL ACK */
-	return rc;
-}
-
-/*
- * Special handling for channel releases in the error case.
- */
-static int rsl_rf_chan_release_err(struct gsm_lchan *lchan)
-{
-	enum sacch_deact sacch_deact;
-	if (lchan->state != LCHAN_S_ACTIVE)
-		return 0;
-	switch (ts_pchan(lchan->ts)) {
-	case GSM_PCHAN_TCH_F:
-	case GSM_PCHAN_TCH_H:
-	case GSM_PCHAN_CCCH_SDCCH4:
-	case GSM_PCHAN_CCCH_SDCCH4_CBCH:
-	case GSM_PCHAN_SDCCH8_SACCH8C:
-	case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:
-		sacch_deact = SACCH_DEACTIVATE;
-		break;
-	default:
-		sacch_deact = SACCH_NONE;
-		break;
-	}
-	return rsl_rf_chan_release(lchan, 1, sacch_deact);
-}
-
-static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan)
-{
-	struct gsm_bts_trx_ts *ts = lchan->ts;
-
-	DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", gsm_lchan_name(lchan));
-
-	/* Stop all pending timers */
-	osmo_timer_del(&lchan->act_timer);
-	osmo_timer_del(&lchan->T3111);
-
-	/*
-	 * The BTS didn't respond within the timeout to our channel
-	 * release request and we have marked the channel as broken.
-	 * Now we do receive an ACK and let's be conservative. If it
-	 * is a sysmoBTS we know that only one RF Channel Release ACK
-	 * will be sent. So let's "repair" the channel.
-	 */
-	if (lchan->state == LCHAN_S_BROKEN) {
-		int do_free = is_sysmobts_v2(ts->trx->bts);
-		LOGP(DRSL, LOGL_NOTICE,
-			"%s CHAN REL ACK for broken channel. %s.\n",
-			gsm_lchan_name(lchan),
-			do_free ? "Releasing it" : "Keeping it broken");
-		if (do_free)
-			do_lchan_free(lchan);
-		if (dyn_ts_should_switch_to_pdch(lchan->ts))
-			dyn_ts_switchover_start(lchan->ts, GSM_PCHAN_PDCH);
-		return 0;
-	}
-
-	if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR)
-		LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
-			gsm_lchan_name(lchan),
-			gsm_lchans_name(lchan->state));
-
-	do_lchan_free(lchan);
-
-	/*
-	 * Check Osmocom RSL CHAN ACT style dynamic TCH/F_TCH/H_PDCH TS for pending
-	 * transitions in these cases:
-	 *
-	 * a) after PDCH was released due to switchover request, activate TCH.
-	 *    BSC initiated this switchover, so dyn.pchan_is != pchan_want and
-	 *    lchan->type has been set to the desired GSM_LCHAN_*.
-	 *
-	 * b) Voice call ended and a TCH is released. If the TS is now unused,
-	 *    switch to PDCH. Here still dyn.pchan_is == dyn.pchan_want because
-	 *    we're only just notified and may decide to switch to PDCH now.
-	 */
-	if (ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) {
-		DEBUGP(DRSL, "%s Rx RSL Channel Release ack for lchan %u\n",
-		       gsm_ts_and_pchan_name(ts), lchan->nr);
-
-		/* (a) */
-		if (ts->dyn.pchan_is != ts->dyn.pchan_want)
-			return dyn_ts_switchover_continue(ts);
-		
-		/* (b) */
-		if (dyn_ts_should_switch_to_pdch(ts))
-			return dyn_ts_switchover_start(ts, GSM_PCHAN_PDCH);
-	}
-
-	/*
-	 * Put a dynamic TCH/F_PDCH channel back to PDCH mode iff it was
-	 * released successfully. If in error, the PDCH ACT will follow after
-	 * T3111 in error_timeout_cb().
-	 *
-	 * Any state other than LCHAN_S_REL_ERR became LCHAN_S_NONE after above
-	 * do_lchan_free(). Assert this, because that's what ensures a PDCH ACT
-	 * on a TCH/F_PDCH TS in all cases.
-	 *
-	 * If GPRS is disabled, always skip the PDCH ACT.
-	 */
-	OSMO_ASSERT(lchan->state == LCHAN_S_NONE
-		    || lchan->state == LCHAN_S_REL_ERR);
-	if (ts->trx->bts->gprs.mode == BTS_GPRS_NONE)
-		return 0;
-	if (ts->pchan == GSM_PCHAN_TCH_F_PDCH
-	    && lchan->state == LCHAN_S_NONE)
-		return rsl_ipacc_pdch_activate(ts, 1);
-	return 0;
-}
-
-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)
-{
-	struct abis_rsl_dchan_hdr *dh;
-	struct msgb *msg = rsl_msgb_alloc();
-
-	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
-	init_dchan_hdr(dh, RSL_MT_PAGING_CMD);
-	dh->chan_nr = RSL_CHAN_PCH_AGCH;
-
-	msgb_tv_put(msg, RSL_IE_PAGING_GROUP, paging_group);
-	msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len-2, ms_ident+2);
-	msgb_tv_put(msg, RSL_IE_CHAN_NEEDED, chan_needed);
-
-	/* Ericsson wants to have this IE in case a paging message
-	 * relates to packet paging */
-	if (bts->type == GSM_BTS_TYPE_RBS2000 && is_gprs)
-		msgb_tv_put(msg, RSL_IE_ERIC_PACKET_PAG_IND, 0);
-
-	msg->dst = bts->c0->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-int imsi_str2bcd(uint8_t *bcd_out, const char *str_in)
-{
-	int i, len = strlen(str_in);
-
-	for (i = 0; i < len; i++) {
-		int num = str_in[i] - 0x30;
-		if (num < 0 || num > 9)
-			return -1;
-		if (i % 2 == 0)
-			bcd_out[i/2] = num;
-		else
-			bcd_out[i/2] |= (num << 4);
-	}
-
-	return 0;
-}
-
-/* Chapter 8.5.6 */
-struct msgb *rsl_imm_assign_cmd_common(struct gsm_bts *bts, uint8_t len, uint8_t *val)
-{
-	struct msgb *msg = rsl_msgb_alloc();
-	struct abis_rsl_dchan_hdr *dh;
-	uint8_t buf[GSM_MACBLOCK_LEN];
-
-	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
-	init_dchan_hdr(dh, RSL_MT_IMMEDIATE_ASSIGN_CMD);
-	dh->chan_nr = RSL_CHAN_PCH_AGCH;
-
-	switch (bts->type) {
-	case GSM_BTS_TYPE_BS11:
-		msgb_tlv_put(msg, RSL_IE_IMM_ASS_INFO, len, val);
-		break;
-	default:
-		/* If phase 2, construct a FULL_IMM_ASS_INFO */
-		pad_macblock(buf, val, len);
-		msgb_tlv_put(msg, RSL_IE_FULL_IMM_ASS_INFO, GSM_MACBLOCK_LEN,
-			     buf);
-		break;
-	}
-
-	msg->dst = bts->c0->rsl_link;
-	return msg;
-}
-
-/* Chapter 8.5.6 */
-int rsl_imm_assign_cmd(struct gsm_bts *bts, uint8_t len, uint8_t *val)
-{
-	struct msgb *msg = rsl_imm_assign_cmd_common(bts, len, val);
-	if (!msg)
-		return 1;
-	return abis_rsl_sendmsg(msg);
-}
-
-/* Chapter 8.5.6 */
-int rsl_ericsson_imm_assign_cmd(struct gsm_bts *bts, uint32_t tlli, uint8_t len, uint8_t *val)
-{
-	struct msgb *msg = rsl_imm_assign_cmd_common(bts, len, val);
-	if (!msg)
-		return 1;
-
-	/* ericsson can handle a reference at the end of the message which is used in
-	 * the confirm message. The confirm message is only sent if the trailer is present */
-	msgb_put_u8(msg, RSL_IE_ERIC_MOBILE_ID);
-	msgb_put_u32(msg, tlli);
-
-	return abis_rsl_sendmsg(msg);
-}
-
-/* Send Siemens specific MS RF Power Capability Indication */
-int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci)
-{
-	struct msgb *msg = rsl_msgb_alloc();
-	struct abis_rsl_dchan_hdr *dh;
-
-	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
-	init_dchan_hdr(dh, RSL_MT_SIEMENS_MRPCI);
-	dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
-	dh->chan_nr = gsm_lchan2chan_nr(lchan);
-	msgb_tv_put(msg, RSL_IE_SIEMENS_MRPCI, *(uint8_t *)mrpci);
-
-	DEBUGP(DRSL, "%s TX Siemens MRPCI 0x%02x\n",
-		gsm_lchan_name(lchan), *(uint8_t *)mrpci);
-
-	msg->dst = lchan->ts->trx->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-
-/* Send "DATA REQUEST" message with given L3 Info payload */
-/* Chapter 8.3.1 */
-int rsl_data_request(struct msgb *msg, uint8_t link_id)
-{
-	if (msg->lchan == NULL) {
-		LOGP(DRSL, LOGL_ERROR, "cannot send DATA REQUEST to unknown lchan\n");
-		return -EINVAL;
-	}
-
-	rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, gsm_lchan2chan_nr(msg->lchan),
-			link_id, 1);
-
-	msg->dst = msg->lchan->ts->trx->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-/* Send "ESTABLISH REQUEST" message with given L3 Info payload */
-/* Chapter 8.3.1 */
-int rsl_establish_request(struct gsm_lchan *lchan, uint8_t link_id)
-{
-	struct msgb *msg;
-
-	msg = rsl_rll_simple(RSL_MT_EST_REQ, gsm_lchan2chan_nr(lchan),
-			     link_id, 0);
-	msg->dst = lchan->ts->trx->rsl_link;
-
-	DEBUGP(DRLL, "%s RSL RLL ESTABLISH REQ (link_id=0x%02x)\n",
-		gsm_lchan_name(lchan), link_id);
-
-	return abis_rsl_sendmsg(msg);
-}
-
-static void rsl_handle_release(struct gsm_lchan *lchan);
-
-/* Special work handler to handle missing RSL_MT_REL_CONF message from
- * Nokia InSite BTS */
-static void lchan_rel_work_cb(void *data)
-{
-	struct gsm_lchan *lchan = data;
-	int sapi;
-
-	for (sapi = 0; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
-		if (lchan->sapis[sapi] == LCHAN_SAPI_REL)
-			lchan->sapis[sapi] = LCHAN_SAPI_UNUSED;
-	}
-	rsl_handle_release(lchan);
-}
-
-/* Chapter 8.3.7 Request the release of multiframe mode of RLL connection.
-   This is what higher layers should call.  The BTS then responds with
-   RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
-   which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
-   lchan_free() */
-int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id,
-			enum rsl_rel_mode release_mode)
-{
-
-	struct msgb *msg;
-
-	msg = rsl_rll_simple(RSL_MT_REL_REQ, gsm_lchan2chan_nr(lchan),
-			     link_id, 0);
-	/* 0 is normal release, 1 is local end */
-	msgb_tv_put(msg, RSL_IE_RELEASE_MODE, release_mode);
-
-	/* FIXME: start some timer in case we don't receive a REL ACK ? */
-
-	msg->dst = lchan->ts->trx->rsl_link;
-
-	DEBUGP(DRLL, "%s RSL RLL RELEASE REQ (link_id=0x%02x, reason=%u)\n",
-		gsm_lchan_name(lchan), link_id, release_mode);
-
-	abis_rsl_sendmsg(msg);
-
-	/* Do not wait for Nokia BTS to send the confirm. */
-	if (is_nokia_bts(lchan->ts->trx->bts)
-	 && lchan->ts->trx->bts->nokia.no_loc_rel_cnf
-	 && release_mode == RSL_REL_LOCAL_END) {
-		DEBUGP(DRLL, "Scheduling release, becasuse Nokia InSite BTS does not send a RELease CONFirm.\n");
-		lchan->sapis[link_id & 0x7] = LCHAN_SAPI_REL;
-		osmo_timer_setup(&lchan->rel_work, lchan_rel_work_cb, lchan);
-		osmo_timer_schedule(&lchan->rel_work, 0, 0);
-	}
-
-	return 0;
-}
-
-int rsl_lchan_mark_broken(struct gsm_lchan *lchan, const char *reason)
-{
-	LOGP(DRSL, LOGL_ERROR, "%s %s lchan broken: %s\n",
-	     gsm_lchan_name(lchan), gsm_lchant_name(lchan->type), reason);
-	rsl_lchan_set_state(lchan, LCHAN_S_BROKEN);
-	lchan->broken_reason = reason;
-	return 0;
-}
-
-int rsl_lchan_set_state(struct gsm_lchan *lchan, int state)
-{
-	DEBUGP(DRSL, "%s state %s -> %s\n",
-	       gsm_lchan_name(lchan), gsm_lchans_name(lchan->state),
-	       gsm_lchans_name(state));
-	lchan->state = state;
-	return 0;
-}
-
-/* Chapter 8.4.2: Channel Activate Acknowledge */
-static int rsl_rx_chan_act_ack(struct msgb *msg)
-{
-	struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
-	struct gsm_lchan *lchan = msg->lchan;
-	struct gsm_bts_trx_ts *ts = lchan->ts;
-
-	/* BTS has confirmed channel activation, we now need
-	 * to assign the activated channel to the MS */
-	if (rslh->ie_chan != RSL_IE_CHAN_NR)
-		return -EINVAL;
-
-	osmo_timer_del(&lchan->act_timer);
-
-	if (lchan->state == LCHAN_S_BROKEN) {
-		int do_release = is_sysmobts_v2(ts->trx->bts);
-		LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK for broken channel. %s\n",
-			gsm_lchan_name(lchan),
-			do_release ? "Releasing it" : "Keeping it broken");
-		if (do_release) {
-			talloc_free(lchan->rqd_ref);
-			lchan->rqd_ref = NULL;
-			lchan->rqd_ta = 0;
-			rsl_lchan_set_state(msg->lchan, LCHAN_S_ACTIVE);
-			if (ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) {
-				/*
-				 * lchan_act_tmr_cb() already called
-				 * lchan_free() and cleared the lchan->type, so
-				 * calling dyn_ts_switchover_complete() here
-				 * would not have the desired effect of
-				 * mimicking an activated lchan that we can
-				 * release. Instead hack the dyn ts state to
-				 * make sure that rsl_rx_rf_chan_rel_ack() will
-				 * switch back to PDCH, i.e. have pchan_is ==
-				 * pchan_want, both != GSM_PCHAN_PDCH:
-				 */
-				ts->dyn.pchan_is = GSM_PCHAN_NONE;
-				ts->dyn.pchan_want = GSM_PCHAN_NONE;
-			}
-			rsl_rf_chan_release(msg->lchan, 0, SACCH_NONE);
-		}
-		return 0;
-	}
-
-	if (lchan->state != LCHAN_S_ACT_REQ)
-		LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK, but state %s\n",
-			gsm_lchan_name(lchan),
-			gsm_lchans_name(lchan->state));
-	rsl_lchan_set_state(lchan, LCHAN_S_ACTIVE);
-
-	if (ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH)
-		dyn_ts_switchover_complete(lchan);
-
-	if (lchan->rqd_ref) {
-		rsl_send_imm_assignment(lchan);
-		talloc_free(lchan->rqd_ref);
-		lchan->rqd_ref = NULL;
-		lchan->rqd_ta = 0;
-	}
-
-	send_lchan_signal(S_LCHAN_ACTIVATE_ACK, lchan, NULL);
-
-	/* Update bts attributes inside the PCU */
-	if (ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH ||
-	    ts->pchan == GSM_PCHAN_TCH_F_PDCH ||
-	    ts->pchan == GSM_PCHAN_PDCH)
-		pcu_info_update(ts->trx->bts);
-
-	return 0;
-}
-
-/* Chapter 8.4.3: Channel Activate NACK */
-static int rsl_rx_chan_act_nack(struct msgb *msg)
-{
-	struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
-	struct tlv_parsed tp;
-
-	osmo_timer_del(&msg->lchan->act_timer);
-
-	if (msg->lchan->state == LCHAN_S_BROKEN) {
-		LOGP(DRSL, LOGL_ERROR,
-			"%s CHANNEL ACTIVATE NACK for broken channel.\n",
-			gsm_lchan_name(msg->lchan));
-		return -1;
-	}
-
-	LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK ",
-		gsm_lchan_name(msg->lchan));
-
-	/* BTS has rejected channel activation ?!? */
-	if (dh->ie_chan != RSL_IE_CHAN_NR)
-		return -EINVAL;
-
-	rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
-	if (TLVP_PRESENT(&tp, RSL_IE_CAUSE)) {
-		const uint8_t *cause = TLVP_VAL(&tp, RSL_IE_CAUSE);
-		print_rsl_cause(LOGL_ERROR, cause,
-				TLVP_LEN(&tp, RSL_IE_CAUSE));
-		msg->lchan->error_cause = *cause;
-		if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC) {
-			rsl_lchan_mark_broken(msg->lchan, "NACK on activation");
-		} else
-			rsl_rf_chan_release(msg->lchan, 1, SACCH_DEACTIVATE);
-
-	} else {
-		rsl_lchan_mark_broken(msg->lchan, "NACK on activation no IE");
-	}
-
-	LOGPC(DRSL, LOGL_ERROR, "\n");
-
-	send_lchan_signal(S_LCHAN_ACTIVATE_NACK, msg->lchan, NULL);
-	return 0;
-}
-
-/* Chapter 8.4.4: Connection Failure Indication */
-static int rsl_rx_conn_fail(struct msgb *msg)
-{
-	struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
-	struct tlv_parsed tp;
-
-	LOGP(DRSL, LOGL_NOTICE, "%s CONNECTION FAIL: RELEASING state %s ",
-	     gsm_lchan_name(msg->lchan),
-	     gsm_lchans_name(msg->lchan->state));
-
-	rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
-
-	if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
-		print_rsl_cause(LOGL_NOTICE, TLVP_VAL(&tp, RSL_IE_CAUSE),
-				TLVP_LEN(&tp, RSL_IE_CAUSE));
-
-	LOGPC(DRSL, LOGL_NOTICE, "\n");
-	rate_ctr_inc(&msg->lchan->ts->trx->bts->network->bsc_ctrs->ctr[BSC_CTR_CHAN_RF_FAIL]);
-	return rsl_rf_chan_release_err(msg->lchan);
-}
-
-static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru,
-				const char *prefix)
-{
-	DEBUGPC(DMEAS, "RXL-FULL-%s=%3ddBm RXL-SUB-%s=%3ddBm ",
-		prefix, rxlev2dbm(mru->full.rx_lev),
-		prefix, rxlev2dbm(mru->sub.rx_lev));
-	DEBUGPC(DMEAS, "RXQ-FULL-%s=%d RXQ-SUB-%s=%d ",
-		prefix, mru->full.rx_qual, prefix, mru->sub.rx_qual);
-}
-
-static void print_meas_rep(struct gsm_lchan *lchan, struct gsm_meas_rep *mr)
-{
-	int i;
-	const char *name = "";
-
-	if (lchan && lchan->conn) {
-		if (lchan->conn->bsub)
-			name = bsc_subscr_name(lchan->conn->bsub);
-		else
-			name = lchan->name;
-	}
-
-	DEBUGP(DMEAS, "[%s] MEASUREMENT RESULT NR=%d ", name, mr->nr);
-
-	if (mr->flags & MEAS_REP_F_DL_DTX)
-		DEBUGPC(DMEAS, "DTXd ");
-
-	print_meas_rep_uni(&mr->ul, "ul");
-	DEBUGPC(DMEAS, "BS_POWER=%d ", mr->bs_power);
-
-	if (mr->flags & MEAS_REP_F_MS_TO)
-		DEBUGPC(DMEAS, "MS_TO=%d ", mr->ms_timing_offset);
-
-	if (mr->flags & MEAS_REP_F_MS_L1) {
-		DEBUGPC(DMEAS, "L1_MS_PWR=%3ddBm ", mr->ms_l1.pwr);
-		DEBUGPC(DMEAS, "L1_FPC=%u ",
-			mr->flags & MEAS_REP_F_FPC ? 1 : 0);
-		DEBUGPC(DMEAS, "L1_TA=%u ", mr->ms_l1.ta);
-	}
-
-	if (mr->flags & MEAS_REP_F_UL_DTX)
-		DEBUGPC(DMEAS, "DTXu ");
-	if (mr->flags & MEAS_REP_F_BA1)
-		DEBUGPC(DMEAS, "BA1 ");
-	if (!(mr->flags & MEAS_REP_F_DL_VALID))
-		DEBUGPC(DMEAS, "NOT VALID ");
-	else
-		print_meas_rep_uni(&mr->dl, "dl");
-
-	DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", mr->num_cell);
-	if (mr->num_cell == 7)
-		return;
-	for (i = 0; i < mr->num_cell; i++) {
-		struct gsm_meas_rep_cell *mrc = &mr->cell[i];
-		DEBUGP(DMEAS, "IDX=%u ARFCN=%u BSIC=%u => %d dBm\n",
-			mrc->neigh_idx, mrc->arfcn, mrc->bsic, rxlev2dbm(mrc->rxlev));
-	}
-}
-
-static struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan)
-{
-	struct gsm_meas_rep *meas_rep;
-
-	meas_rep = &lchan->meas_rep[lchan->meas_rep_idx];
-	memset(meas_rep, 0, sizeof(*meas_rep));
-	meas_rep->lchan = lchan;
-	lchan->meas_rep_idx = (lchan->meas_rep_idx + 1)
-					% ARRAY_SIZE(lchan->meas_rep);
-
-	return meas_rep;
-}
-
-static int rsl_rx_meas_res(struct msgb *msg)
-{
-	struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
-	struct tlv_parsed tp;
-	struct gsm_meas_rep *mr = lchan_next_meas_rep(msg->lchan);
-	uint8_t len;
-	const uint8_t *val;
-	int rc;
-
-	/* check if this channel is actually active */
-	/* FIXME: maybe this check should be way more generic/centralized */
-	if (msg->lchan->state != LCHAN_S_ACTIVE) {
-		LOGP(DRSL, LOGL_DEBUG, "%s: MEAS RES for inactive channel\n",
-			gsm_lchan_name(msg->lchan));
-		return 0;
-	}
-
-	memset(mr, 0, sizeof(*mr));
-	mr->lchan = msg->lchan;
-
-	rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
-
-	if (!TLVP_PRESENT(&tp, RSL_IE_MEAS_RES_NR) ||
-	    !TLVP_PRESENT(&tp, RSL_IE_UPLINK_MEAS) ||
-	    !TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
-		return -EIO;
-
-	/* Mandatory Parts */
-	mr->nr = *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR);
-
-	len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
-	val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
-	if (len >= 3) {
-		if (val[0] & 0x40)
-			mr->flags |= MEAS_REP_F_DL_DTX;
-		mr->ul.full.rx_lev = val[0] & 0x3f;
-		mr->ul.sub.rx_lev = val[1] & 0x3f;
-		mr->ul.full.rx_qual = val[2]>>3 & 0x7;
-		mr->ul.sub.rx_qual = val[2] & 0x7;
-	}
-
-	mr->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
-
-	/* Optional Parts */
-	if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET)) {
-		/* According to 3GPP TS 48.058 § MS Timing Offset = Timing Offset field - 63 */
-		mr->ms_timing_offset = *TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET) - 63;
-		mr->flags |= MEAS_REP_F_MS_TO;
-	}
-
-	if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
-		struct e1inp_sign_link *sign_link = msg->dst;
-
-		val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
-		mr->flags |= MEAS_REP_F_MS_L1;
-		mr->ms_l1.pwr = ms_pwr_dbm(sign_link->trx->bts->band, val[0] >> 3);
-		if (val[0] & 0x04)
-			mr->flags |= MEAS_REP_F_FPC;
-		mr->ms_l1.ta = val[1];
-		/* BS11 and Nokia reports TA shifted by 2 bits */
-		if (msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_BS11
-		 || msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE)
-			mr->ms_l1.ta >>= 2;
-	}
-	if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
-		msg->l3h = (uint8_t *) TLVP_VAL(&tp, RSL_IE_L3_INFO);
-		rc = gsm48_parse_meas_rep(mr, msg);
-		if (rc < 0)
-			return rc;
-	}
-
-	print_meas_rep(msg->lchan, mr);
-
-	send_lchan_signal(S_LCHAN_MEAS_REP, msg->lchan, mr);
-
-	return 0;
-}
-
-/* Chapter 8.4.7 */
-static int rsl_rx_hando_det(struct msgb *msg)
-{
-	struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
-	struct tlv_parsed tp;
-
-	DEBUGP(DRSL, "%s HANDOVER DETECT ", gsm_lchan_name(msg->lchan));
-
-	rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
-
-	if (TLVP_PRESENT(&tp, RSL_IE_ACCESS_DELAY))
-		DEBUGPC(DRSL, "access delay = %u\n",
-			*TLVP_VAL(&tp, RSL_IE_ACCESS_DELAY));
-	else
-		DEBUGPC(DRSL, "\n");
-
-	send_lchan_signal(S_LCHAN_HANDOVER_DETECT, msg->lchan, NULL);
-
-	return 0;
-}
-
-static bool lchan_may_change_pdch(struct gsm_lchan *lchan, bool pdch_act)
-{
-	struct gsm_bts_trx_ts *ts;
-
-	OSMO_ASSERT(lchan);
-
-	ts = lchan->ts;
-	OSMO_ASSERT(ts);
-	OSMO_ASSERT(ts->trx);
-	OSMO_ASSERT(ts->trx->bts);
-
-	if (lchan->ts->pchan != GSM_PCHAN_TCH_F_PDCH) {
-		LOGP(DRSL, LOGL_ERROR, "%s pchan=%s Rx PDCH %s ACK"
-		     " for channel that is no TCH/F_PDCH\n",
-		     gsm_lchan_name(lchan),
-		     gsm_pchan_name(ts->pchan),
-		     pdch_act? "ACT" : "DEACT");
-		return false;
-	}
-
-	if (lchan->state != LCHAN_S_NONE) {
-		LOGP(DRSL, LOGL_ERROR, "%s pchan=%s Rx PDCH %s ACK"
-		     " in unexpected state: %s\n",
-		     gsm_lchan_name(lchan),
-		     gsm_pchan_name(ts->pchan),
-		     pdch_act? "ACT" : "DEACT",
-		     gsm_lchans_name(lchan->state));
-		return false;
-	}
-	return true;
-}
-
-static int rsl_rx_pdch_act_ack(struct msgb *msg)
-{
-	if (!lchan_may_change_pdch(msg->lchan, true))
-		return -EINVAL;
-
-	msg->lchan->ts->flags |= TS_F_PDCH_ACTIVE;
-	msg->lchan->ts->flags &= ~TS_F_PDCH_ACT_PENDING;
-
-	return 0;
-}
-
-static int rsl_rx_pdch_deact_ack(struct msgb *msg)
-{
-	if (!lchan_may_change_pdch(msg->lchan, false))
-		return -EINVAL;
-
-	msg->lchan->ts->flags &= ~TS_F_PDCH_ACTIVE;
-	msg->lchan->ts->flags &= ~TS_F_PDCH_DEACT_PENDING;
-
-	rsl_chan_activate_lchan(msg->lchan, msg->lchan->dyn.act_type,
-				msg->lchan->dyn.ho_ref);
-
-	return 0;
-}
-
-static int abis_rsl_rx_dchan(struct msgb *msg)
-{
-	struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
-	int rc = 0;
-	char *ts_name;
-	struct e1inp_sign_link *sign_link = msg->dst;
-
-	msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr,
-				  "Abis RSL rx DCHAN: ");
-	if (!msg->lchan)
-		return -1;
-	ts_name = gsm_lchan_name(msg->lchan);
-
-	switch (rslh->c.msg_type) {
-	case RSL_MT_CHAN_ACTIV_ACK:
-		DEBUGP(DRSL, "%s CHANNEL ACTIVATE ACK\n", ts_name);
-		rc = rsl_rx_chan_act_ack(msg);
-		count_codecs(sign_link->trx->bts, msg->lchan);
-		break;
-	case RSL_MT_CHAN_ACTIV_NACK:
-		rc = rsl_rx_chan_act_nack(msg);
-		break;
-	case RSL_MT_CONN_FAIL:
-		rc = rsl_rx_conn_fail(msg);
-		break;
-	case RSL_MT_MEAS_RES:
-		rc = rsl_rx_meas_res(msg);
-		break;
-	case RSL_MT_HANDO_DET:
-		rc = rsl_rx_hando_det(msg);
-		break;
-	case RSL_MT_RF_CHAN_REL_ACK:
-		rc = rsl_rx_rf_chan_rel_ack(msg->lchan);
-		break;
-	case RSL_MT_MODE_MODIFY_ACK:
-		count_codecs(sign_link->trx->bts, msg->lchan);
-		DEBUGP(DRSL, "%s CHANNEL MODE MODIFY ACK\n", ts_name);
-		break;
-	case RSL_MT_MODE_MODIFY_NACK:
-		LOGP(DRSL, LOGL_ERROR, "%s CHANNEL MODE MODIFY NACK\n", ts_name);
-		break;
-	case RSL_MT_IPAC_PDCH_ACT_ACK:
-		DEBUGP(DRSL, "%s IPAC PDCH ACT ACK\n", ts_name);
-		rc = rsl_rx_pdch_act_ack(msg);
-		break;
-	case RSL_MT_IPAC_PDCH_ACT_NACK:
-		LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH ACT NACK\n", ts_name);
-		break;
-	case RSL_MT_IPAC_PDCH_DEACT_ACK:
-		DEBUGP(DRSL, "%s IPAC PDCH DEACT ACK\n", ts_name);
-		rc = rsl_rx_pdch_deact_ack(msg);
-		break;
-	case RSL_MT_IPAC_PDCH_DEACT_NACK:
-		LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH DEACT NACK\n", ts_name);
-		break;
-	case RSL_MT_PHY_CONTEXT_CONF:
-	case RSL_MT_PREPROC_MEAS_RES:
-	case RSL_MT_TALKER_DET:
-	case RSL_MT_LISTENER_DET:
-	case RSL_MT_REMOTE_CODEC_CONF_REP:
-	case RSL_MT_MR_CODEC_MOD_ACK:
-	case RSL_MT_MR_CODEC_MOD_NACK:
-	case RSL_MT_MR_CODEC_MOD_PER:
-		LOGP(DRSL, LOGL_NOTICE, "%s Unimplemented Abis RSL DChan "
-			"msg 0x%02x\n", ts_name, rslh->c.msg_type);
-		break;
-	default:
-		LOGP(DRSL, LOGL_NOTICE, "%s unknown Abis RSL DChan msg 0x%02x\n",
-			ts_name, rslh->c.msg_type);
-		return -EINVAL;
-	}
-
-	return rc;
-}
-
-static int rsl_rx_error_rep(struct msgb *msg)
-{
-	struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
-	struct tlv_parsed tp;
-	struct e1inp_sign_link *sign_link = msg->dst;
-
-	LOGP(DRSL, LOGL_ERROR, "%s ERROR REPORT ", gsm_trx_name(sign_link->trx));
-
-	rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
-
-	if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
-		print_rsl_cause(LOGL_ERROR, TLVP_VAL(&tp, RSL_IE_CAUSE),
-				TLVP_LEN(&tp, RSL_IE_CAUSE));
-
-	LOGPC(DRSL, LOGL_ERROR, "\n");
-
-	return 0;
-}
-
-static int abis_rsl_rx_trx(struct msgb *msg)
-{
-	struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
-	struct e1inp_sign_link *sign_link = msg->dst;
-	int rc = 0;
-
-	switch (rslh->msg_type) {
-	case RSL_MT_ERROR_REPORT:
-		rc = rsl_rx_error_rep(msg);
-		break;
-	case RSL_MT_RF_RES_IND:
-		/* interference on idle channels of TRX */
-		//DEBUGP(DRSL, "%s RF Resource Indication\n", gsm_trx_name(sign_link->trx));
-		break;
-	case RSL_MT_OVERLOAD:
-		/* indicate CCCH / ACCH / processor overload */
-		LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n",
-		     gsm_trx_name(sign_link->trx));
-		break;
-	case 0x42: /* Nokia specific: SI End ACK */
-		LOGP(DRSL, LOGL_INFO, "Nokia SI End ACK\n");
-		break;
-	case 0x43: /* Nokia specific: SI End NACK */
-		LOGP(DRSL, LOGL_INFO, "Nokia SI End NACK\n");
-		break;
-	default:
-		LOGP(DRSL, LOGL_NOTICE, "%s Unknown Abis RSL TRX message "
-			"type 0x%02x\n", gsm_trx_name(sign_link->trx), rslh->msg_type);
-		return -EINVAL;
-	}
-	return rc;
-}
-
-/* If T3101 expires, we never received a response to IMMEDIATE ASSIGN */
-static void t3101_expired(void *data)
-{
-	struct gsm_lchan *lchan = data;
-	LOGP(DRSL, LOGL_NOTICE,
-	     "%s T3101 expired: no response to IMMEDIATE ASSIGN\n",
-	     gsm_lchan_name(lchan));
-	rsl_rf_chan_release(lchan, 1, SACCH_DEACTIVATE);
-}
-
-/* If T3111 expires, we will send the RF Channel Request */
-static void t3111_expired(void *data)
-{
-	struct gsm_lchan *lchan = data;
-	LOGP(DRSL, LOGL_NOTICE,
-	     "%s T3111 expired: releasing RF Channel\n",
-	     gsm_lchan_name(lchan));
-	rsl_rf_chan_release(lchan, 0, SACCH_NONE);
-}
-
-/* If T3109 expires the MS has not send a UA/UM do the error release */
-static void t3109_expired(void *data)
-{
-	struct gsm_lchan *lchan = data;
-
-	LOGP(DRSL, LOGL_ERROR,
-		"%s SACCH deactivation timeout.\n", gsm_lchan_name(lchan));
-	rsl_rf_chan_release(lchan, 1, SACCH_NONE);
-}
-
-/* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */
-static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
-				unsigned int num_req_refs,
-				struct gsm48_req_ref *rqd_refs,
-				uint8_t wait_ind)
-{
-	uint8_t buf[GSM_MACBLOCK_LEN];
-	struct gsm48_imm_ass_rej *iar = (struct gsm48_imm_ass_rej *)buf;
-
-	/* create IMMEDIATE ASSIGN REJECT 04.08 message */
-	memset(iar, 0, sizeof(*iar));
-	iar->proto_discr = GSM48_PDISC_RR;
-	iar->msg_type = GSM48_MT_RR_IMM_ASS_REJ;
-	iar->page_mode = GSM48_PM_SAME;
-
-	memcpy(&iar->req_ref1, &rqd_refs[0], sizeof(iar->req_ref1));
-	iar->wait_ind1 = wait_ind;
-
-	if (num_req_refs >= 2)
-		memcpy(&iar->req_ref2, &rqd_refs[1], sizeof(iar->req_ref2));
-	else
-		memcpy(&iar->req_ref2, &rqd_refs[0], sizeof(iar->req_ref2));
-	iar->wait_ind2 = wait_ind;
-
-	if (num_req_refs >= 3)
-		memcpy(&iar->req_ref3, &rqd_refs[2], sizeof(iar->req_ref3));
-	else
-		memcpy(&iar->req_ref3, &rqd_refs[0], sizeof(iar->req_ref3));
-	iar->wait_ind3 = wait_ind;
-
-	if (num_req_refs >= 4)
-		memcpy(&iar->req_ref4, &rqd_refs[3], sizeof(iar->req_ref4));
-	else
-		memcpy(&iar->req_ref4, &rqd_refs[0], sizeof(iar->req_ref4));
-	iar->wait_ind4 = wait_ind;
-
-	/* we need to subtract 1 byte from sizeof(*iar) since ia includes the l2_plen field */
-	iar->l2_plen = GSM48_LEN2PLEN((sizeof(*iar)-1));
-
-	return rsl_imm_assign_cmd(bts, sizeof(*iar), (uint8_t *) iar);
-}
-
-/* Handle packet channel rach requests */
-static int rsl_rx_pchan_rqd(struct msgb *msg, struct gsm_bts *bts)
-{
-	struct gsm48_req_ref *rqd_ref;
-	struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
-	rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
-	uint8_t ra = rqd_ref->ra;
-	uint8_t t1, t2, t3;
-	uint32_t fn;
-	uint8_t rqd_ta;
-	uint8_t is_11bit;
-
-	/* Process rach request and forward contained information to PCU */
-	if (ra == 0x7F) {
-		is_11bit = 1;
-
-		/* FIXME: Also handle 11 bit rach requests */
-		LOGP(DRSL, LOGL_ERROR, "BTS %d eleven bit access burst not supported yet!\n",bts->nr);
-		return -EINVAL;
-	} else {
-		is_11bit = 0;
-		t1 = rqd_ref->t1;
-		t2 = rqd_ref->t2;
-		t3 = rqd_ref->t3_low | (rqd_ref->t3_high << 3);
-		fn = (51 * ((t3-t2) % 26) + t3 + 51 * 26 * t1);
-
-		rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
-	}
-
-	return pcu_tx_rach_ind(bts, rqd_ta, ra, fn, is_11bit,
-			       GSM_L1_BURST_TYPE_ACCESS_0);
-}
-
-/* MS has requested a channel on the RACH */
-static int rsl_rx_chan_rqd(struct msgb *msg)
-{
-	struct e1inp_sign_link *sign_link = msg->dst;
-	struct gsm_bts *bts = sign_link->trx->bts;
-	struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
-	struct gsm48_req_ref *rqd_ref;
-	enum gsm_chan_t lctype;
-	enum gsm_chreq_reason_t chreq_reason;
-	struct gsm_lchan *lchan;
-	uint8_t rqd_ta;
-	int is_lu;
-
-	uint16_t arfcn;
-	uint8_t subch;
-
-	/* parse request reference to be used in immediate assign */
-	if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
-		return -EINVAL;
-
-	rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
-
-	/* parse access delay and use as TA */
-	if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
-		return -EINVAL;
-	rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
-
-	/* Determine channel request cause code */
-	chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
-	LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: reason: %s (ra=0x%02x, neci=0x%02x, chreq_reason=0x%02x)\n",
-	     msg->lchan->ts->trx->bts->nr,
-	     get_value_string(gsm_chreq_descs, chreq_reason),
-	     rqd_ref->ra, bts->network->neci, chreq_reason);
-
-	/* Handle PDCH related rach requests (in case of BSC-co-located-PCU */
-	if (chreq_reason == GSM_CHREQ_REASON_PDCH)
-		return rsl_rx_pchan_rqd(msg, bts);
-
-	/* determine channel type (SDCCH/TCH_F/TCH_H) based on
-	 * request reference RA */
-	lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
-
-	rate_ctr_inc(&bts->network->bsc_ctrs->ctr[BSC_CTR_CHREQ_TOTAL]);
-
-	/*
-	 * We want LOCATION UPDATES to succeed and will assign a TCH
-	 * if we have no SDCCH available.
-	 */
-	is_lu = !!(chreq_reason == GSM_CHREQ_REASON_LOCATION_UPD);
-
-	/* check availability / allocate channel */
-	lchan = lchan_alloc(bts, lctype, is_lu);
-	if (!lchan) {
-		LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
-		     msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
-		rate_ctr_inc(&bts->network->bsc_ctrs->ctr[BSC_CTR_CHREQ_NO_CHANNEL]);
-		/* FIXME gather multiple CHAN RQD and reject up to 4 at the same time */
-		if (bts->network->T3122)
-			rsl_send_imm_ass_rej(bts, 1, rqd_ref, bts->network->T3122 & 0xff);
-		return 0;
-	}
-
-	/*
-	 * Expecting lchan state to be NONE, except for dyn TS in PDCH mode.
-	 * Those are expected to be ACTIVE: the PDCH release will be sent from
-	 * rsl_chan_activate_lchan() below.
-	 */
-	if (lchan->state != LCHAN_S_NONE
-	    && !(lchan->ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH
-		 && lchan->ts->dyn.pchan_is == GSM_PCHAN_PDCH
-		 && lchan->state == LCHAN_S_ACTIVE))
-		LOGP(DRSL, LOGL_NOTICE, "%s lchan_alloc() returned channel "
-		     "in state %s\n", gsm_lchan_name(lchan),
-		     gsm_lchans_name(lchan->state));
-
-	/* save the RACH data as we need it after the CHAN ACT ACK */
-	lchan->rqd_ref = talloc_zero(bts, struct gsm48_req_ref);
-	if (!lchan->rqd_ref) {
-		LOGP(DRSL, LOGL_ERROR, "Failed to allocate gsm48_req_ref.\n");
-		lchan_free(lchan);
-		return -ENOMEM;
-	}
-
-	memcpy(lchan->rqd_ref, rqd_ref, sizeof(*rqd_ref));
-	lchan->rqd_ta = rqd_ta;
-
-	arfcn = lchan->ts->trx->arfcn;
-	subch = lchan->nr;
-	
-	lchan->encr.alg_id = RSL_ENC_ALG_A5(0);	/* no encryption */
-	lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
-	lchan->bs_power = 0; /* 0dB reduction, output power = Pn */
-	lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
-	lchan->tch_mode = GSM48_CMODE_SIGN;
-
-	/* Start another timer or assume the BTS sends a ACK/NACK? */
-	osmo_timer_setup(&lchan->act_timer, lchan_act_tmr_cb, lchan);
-	osmo_timer_schedule(&lchan->act_timer, 4, 0);
-
-	DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s "
-		"r=%s ra=0x%02x ta=%d\n", gsm_lchan_name(lchan), arfcn, subch,
-		gsm_lchant_name(lchan->type), gsm_chreq_name(chreq_reason),
-		rqd_ref->ra, rqd_ta);
-
-	rsl_chan_activate_lchan(lchan, RSL_ACT_INTRA_IMM_ASS, 0);
-
-	return 0;
-}
-
-static int rsl_send_imm_assignment(struct gsm_lchan *lchan)
-{
-	struct gsm_bts *bts = lchan->ts->trx->bts;
-	uint8_t buf[GSM_MACBLOCK_LEN];
-	struct gsm48_imm_ass *ia = (struct gsm48_imm_ass *) buf;
-
-	/* create IMMEDIATE ASSIGN 04.08 messge */
-	memset(ia, 0, sizeof(*ia));
-	/* we set ia->l2_plen once we know the length of the MA below */
-	ia->proto_discr = GSM48_PDISC_RR;
-	ia->msg_type = GSM48_MT_RR_IMM_ASS;
-	ia->page_mode = GSM48_PM_SAME;
-	gsm48_lchan2chan_desc(&ia->chan_desc, lchan);
-
-	/* use request reference extracted from CHAN_RQD */
-	memcpy(&ia->req_ref, lchan->rqd_ref, sizeof(ia->req_ref));
-	ia->timing_advance = lchan->rqd_ta;
-	if (!lchan->ts->hopping.enabled) {
-		ia->mob_alloc_len = 0;
-	} else {
-		ia->mob_alloc_len = lchan->ts->hopping.ma_len;
-		memcpy(ia->mob_alloc, lchan->ts->hopping.ma_data, ia->mob_alloc_len);
-	}
-	/* we need to subtract 1 byte from sizeof(*ia) since ia includes the l2_plen field */
-	ia->l2_plen = GSM48_LEN2PLEN((sizeof(*ia)-1) + ia->mob_alloc_len);
-
-	/* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
-	osmo_timer_setup(&lchan->T3101, t3101_expired, lchan);
-	osmo_timer_schedule(&lchan->T3101, bts->network->T3101, 0);
-
-	/* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
-	return rsl_imm_assign_cmd(bts, sizeof(*ia)+ia->mob_alloc_len, (uint8_t *) ia);
-}
-
-/* current load on the CCCH */
-static int rsl_rx_ccch_load(struct msgb *msg)
-{
-	struct e1inp_sign_link *sign_link = msg->dst;
-	struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
-	struct ccch_signal_data sd;
-
-	sd.bts = sign_link->trx->bts;
-	sd.rach_slot_count = -1;
-	sd.rach_busy_count = -1;
-	sd.rach_access_count = -1;
-
-	switch (rslh->data[0]) {
-	case RSL_IE_PAGING_LOAD:
-		sd.pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
-		if (is_ipaccess_bts(sign_link->trx->bts) && sd.pg_buf_space == 0xffff) {
-			/* paging load below configured threshold, use 50 as default */
-			sd.pg_buf_space = 50;
-		}
-		paging_update_buffer_space(sign_link->trx->bts, sd.pg_buf_space);
-		osmo_signal_dispatch(SS_CCCH, S_CCCH_PAGING_LOAD, &sd);
-		break;
-	case RSL_IE_RACH_LOAD:
-		if (msg->data_len >= 7) {
-			sd.rach_slot_count = rslh->data[2] << 8 | rslh->data[3];
-			sd.rach_busy_count = rslh->data[4] << 8 | rslh->data[5];
-			sd.rach_access_count = rslh->data[6] << 8 | rslh->data[7];
-			osmo_signal_dispatch(SS_CCCH, S_CCCH_RACH_LOAD, &sd);
-		}
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int abis_rsl_rx_cchan(struct msgb *msg)
-{
-	struct e1inp_sign_link *sign_link = msg->dst;
-	struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
-	int rc = 0;
-	uint32_t tlli;
-
-	msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr,
-				  "Abis RSL rx CCHAN: ");
-
-	switch (rslh->c.msg_type) {
-	case RSL_MT_CHAN_RQD:
-		/* MS has requested a channel on the RACH */
-		rc = rsl_rx_chan_rqd(msg);
-		break;
-	case RSL_MT_CCCH_LOAD_IND:
-		/* current load on the CCCH */
-		rc = rsl_rx_ccch_load(msg);
-		break;
-	case RSL_MT_DELETE_IND:
-		/* CCCH overloaded, IMM_ASSIGN was dropped */
-	case RSL_MT_CBCH_LOAD_IND:
-		/* current load on the CBCH */
-		LOGP(DRSL, LOGL_NOTICE, "Unimplemented Abis RSL TRX message "
-			"type 0x%02x\n", rslh->c.msg_type);
-		break;
-	case 0x10: /* Ericsson specific: Immediate Assign Sent */
-		/* FIXME: Replace the messy message parsing below
-		 * with proper TV parser */
-		LOGP(DRSL, LOGL_INFO, "IMM.ass sent\n");
-		if(msg->len < 9)
-			LOGP(DRSL, LOGL_ERROR, "short IMM.ass sent message!\n");
-		else if(msg->data[4] != 0xf1)
-			LOGP(DRSL, LOGL_ERROR, "unsupported IMM.ass message format! (please fix)\n");
-		else {
-			msgb_pull(msg, 5); /* drop previous data to use msg_pull_u32 */
-			tlli = msgb_pull_u32(msg);
-			pcu_tx_imm_ass_sent(sign_link->trx->bts, tlli);
-		}
-		break;
-	default:
-		LOGP(DRSL, LOGL_NOTICE, "Unknown Abis RSL TRX message type "
-			"0x%02x\n", rslh->c.msg_type);
-		return -EINVAL;
-	}
-
-	return rc;
-}
-
-static int rsl_rx_rll_err_ind(struct msgb *msg)
-{
-	struct tlv_parsed tp;
-	struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
-	uint8_t rlm_cause;
-
-	rsl_tlv_parse(&tp, rllh->data, msgb_l2len(msg) - sizeof(*rllh));
-	if (!TLVP_PRESENT(&tp, RSL_IE_RLM_CAUSE)) {
-		LOGP(DRLL, LOGL_ERROR,
-			"%s ERROR INDICATION without mandantory cause.\n",
-			gsm_lchan_name(msg->lchan));
-		return -1;
-	}
-
-	rlm_cause = *TLVP_VAL(&tp, RSL_IE_RLM_CAUSE);
-	LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s in state=%s\n",
-		gsm_lchan_name(msg->lchan),
-		rsl_rlm_cause_name(rlm_cause),
-		gsm_lchans_name(msg->lchan->state));
-
-	rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
-
-	if (rlm_cause == RLL_CAUSE_T200_EXPIRED) {
-		rate_ctr_inc(&msg->lchan->ts->trx->bts->network->bsc_ctrs->ctr[BSC_CTR_CHAN_RLL_ERR]);
-		return rsl_rf_chan_release_err(msg->lchan);
-	}
-
-	return 0;
-}
-
-static void rsl_handle_release(struct gsm_lchan *lchan)
-{
-	int sapi;
-	struct gsm_bts *bts;
-
-	/*
-	 * Maybe only one link/SAPI was releasd or the error handling
-	 * was activated. Just return now and let the other code handle
-	 * it.
-	 */
-	if (lchan->state != LCHAN_S_REL_REQ)
-		return;
-
-	for (sapi = 0; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
-		if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
-			continue;
-		LOGP(DRSL, LOGL_DEBUG, "%s waiting for SAPI=%d to be released.\n",
-		     gsm_lchan_name(lchan), sapi);
-		return;
-	}
-
-
-	/* Stop T3109 and wait for T3111 before re-using the channel */
-	osmo_timer_del(&lchan->T3109);
-	osmo_timer_setup(&lchan->T3111, t3111_expired, lchan);
-	bts = lchan->ts->trx->bts;
-	osmo_timer_schedule(&lchan->T3111, bts->network->T3111, 0);
-}
-
-/*	ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
-	0x02, 0x06,
-	0x01, 0x20,
-	0x02, 0x00,
-	0x0b, 0x00, 0x0f, 0x05, 0x08, ... */
-
-static int abis_rsl_rx_rll(struct msgb *msg)
-{
-	struct e1inp_sign_link *sign_link = msg->dst;
-	struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
-	int rc = 0;
-	char *ts_name;
-	uint8_t sapi = rllh->link_id & 7;
-
-	msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr,
-				  "Abis RSL rx RLL: ");
-	ts_name = gsm_lchan_name(msg->lchan);
-	DEBUGP(DRLL, "%s SAPI=%u ", ts_name, sapi);
-	
-	switch (rllh->c.msg_type) {
-	case RSL_MT_DATA_IND:
-		DEBUGPC(DRLL, "DATA INDICATION\n");
-		if (msgb_l2len(msg) >
-		    sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
-		    rllh->data[0] == RSL_IE_L3_INFO) {
-			msg->l3h = &rllh->data[3];
-			return gsm0408_rcvmsg(msg, rllh->link_id);
-		}
-		break;
-	case RSL_MT_EST_IND:
-		DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
-		/* lchan is established, stop T3101 */
-		msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_MS;
-		osmo_timer_del(&msg->lchan->T3101);
-		if (msgb_l2len(msg) >
-		    sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
-		    rllh->data[0] == RSL_IE_L3_INFO) {
-			msg->l3h = &rllh->data[3];
-			return gsm0408_rcvmsg(msg, rllh->link_id);
-		}
-		break;
-	case RSL_MT_EST_CONF:
-		DEBUGPC(DRLL, "ESTABLISH CONFIRM\n");
-		msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_NET;
-		rll_indication(msg->lchan, rllh->link_id,
-				  BSC_RLLR_IND_EST_CONF);
-		break;
-	case RSL_MT_REL_IND:
-		/* BTS informs us of having received  DISC from MS */
-		DEBUGPC(DRLL, "RELEASE INDICATION\n");
-		msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
-		rll_indication(msg->lchan, rllh->link_id,
-				  BSC_RLLR_IND_REL_IND);
-		rsl_handle_release(msg->lchan);
-		break;
-	case RSL_MT_REL_CONF:
-		/* BTS informs us of having received UA from MS,
-		 * in response to DISC that we've sent earlier */
-		DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
-		msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
-		rsl_handle_release(msg->lchan);
-		break;
-	case RSL_MT_ERROR_IND:
-		DEBUGPC(DRLL, "ERROR INDICATION\n");
-		rc = rsl_rx_rll_err_ind(msg);
-		break;
-	case RSL_MT_UNIT_DATA_IND:
-		DEBUGPC(DRLL, "UNIT DATA INDICATION\n");
-		LOGP(DRLL, LOGL_NOTICE, "unimplemented Abis RLL message "
-			"type 0x%02x\n", rllh->c.msg_type);
-		break;
-	default:
-		DEBUGPC(DRLL, "UNKNOWN\n");
-		LOGP(DRLL, LOGL_NOTICE, "unknown Abis RLL message "
-			"type 0x%02x\n", rllh->c.msg_type);
-	}
-	return rc;
-}
-
-static uint8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
-{
-	switch (lchan->tch_mode) {
-	case GSM48_CMODE_SPEECH_V1:
-		switch (lchan->type) {
-		case GSM_LCHAN_TCH_F:
-			return 0x00;
-		case GSM_LCHAN_TCH_H:
-			return 0x03;
-		default:
-			break;
-		}
-		break;
-	case GSM48_CMODE_SPEECH_EFR:
-		switch (lchan->type) {
-		case GSM_LCHAN_TCH_F:
-			return 0x01;
-		/* there's no half-rate EFR */
-		default:
-			break;
-		}
-		break;
-	case GSM48_CMODE_SPEECH_AMR:
-		switch (lchan->type) {
-		case GSM_LCHAN_TCH_F:
-			return 0x02;
-		case GSM_LCHAN_TCH_H:
-			return 0x05;
-		default:
-			break;
-		}
-		break;
-	default:
-		break;
-	}
-	LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access speech mode for "
-		"tch_mode == 0x%02x\n", lchan->tch_mode);
-	return 0;
-}
-
-static uint8_t ipa_rtp_pt_for_lchan(struct gsm_lchan *lchan)
-{
-	switch (lchan->tch_mode) {
-	case GSM48_CMODE_SPEECH_V1:
-		switch (lchan->type) {
-		case GSM_LCHAN_TCH_F:
-			return RTP_PT_GSM_FULL;
-		case GSM_LCHAN_TCH_H:
-			return RTP_PT_GSM_HALF;
-		default:
-			break;
-		}
-		break;
-	case GSM48_CMODE_SPEECH_EFR:
-		switch (lchan->type) {
-		case GSM_LCHAN_TCH_F:
-			return RTP_PT_GSM_EFR;
-		/* there's no half-rate EFR */
-		default:
-			break;
-		}
-		break;
-	case GSM48_CMODE_SPEECH_AMR:
-		switch (lchan->type) {
-		case GSM_LCHAN_TCH_F:
-		case GSM_LCHAN_TCH_H:
-			return RTP_PT_AMR;
-		default:
-			break;
-		}
-		break;
-	default:
-		break;
-	}
-	LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access rtp payload type for "
-		"tch_mode == 0x%02x\n & lchan_type == %d",
-		lchan->tch_mode, lchan->type);
-	return 0;
-}
-
-/* ip.access specific RSL extensions */
-static void ipac_parse_rtp(struct gsm_lchan *lchan, struct tlv_parsed *tv)
-{
-	struct in_addr ip;
-	uint16_t port, conn_id;
-
-	if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_IP)) {
-		ip.s_addr = tlvp_val32_unal(tv, RSL_IE_IPAC_LOCAL_IP);
-		DEBUGPC(DRSL, "LOCAL_IP=%s ", inet_ntoa(ip));
-		lchan->abis_ip.bound_ip = ntohl(ip.s_addr);
-	}
-
-	if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_PORT)) {
-		port = tlvp_val16_unal(tv, RSL_IE_IPAC_LOCAL_PORT);
-		port = ntohs(port);
-		DEBUGPC(DRSL, "LOCAL_PORT=%u ", port);
-		lchan->abis_ip.bound_port = port;
-	}
-
-	if (TLVP_PRESENT(tv, RSL_IE_IPAC_CONN_ID)) {
-		conn_id = tlvp_val16_unal(tv, RSL_IE_IPAC_CONN_ID);
-		conn_id = ntohs(conn_id);
-		DEBUGPC(DRSL, "CON_ID=%u ", conn_id);
-		lchan->abis_ip.conn_id = conn_id;
-	}
-
-	if (TLVP_PRESENT(tv, RSL_IE_IPAC_RTP_PAYLOAD2)) {
-		lchan->abis_ip.rtp_payload2 =
-				*TLVP_VAL(tv, RSL_IE_IPAC_RTP_PAYLOAD2);
-		DEBUGPC(DRSL, "RTP_PAYLOAD2=0x%02x ",
-			lchan->abis_ip.rtp_payload2);
-	}
-
-	if (TLVP_PRESENT(tv, RSL_IE_IPAC_SPEECH_MODE)) {
-		lchan->abis_ip.speech_mode =
-				*TLVP_VAL(tv, RSL_IE_IPAC_SPEECH_MODE);
-		DEBUGPC(DRSL, "speech_mode=0x%02x ",
-			lchan->abis_ip.speech_mode);
-	}
-
-	if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_IP)) {
-		ip.s_addr = tlvp_val32_unal(tv, RSL_IE_IPAC_REMOTE_IP);
-		DEBUGPC(DRSL, "REMOTE_IP=%s ", inet_ntoa(ip));
-		lchan->abis_ip.connect_ip = ntohl(ip.s_addr);
-	}
-
-	if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_PORT)) {
-		port = tlvp_val16_unal(tv, RSL_IE_IPAC_REMOTE_PORT);
-		port = ntohs(port);
-		DEBUGPC(DRSL, "REMOTE_PORT=%u ", port);
-		lchan->abis_ip.connect_port = port;
-	}
-
-	DEBUGPC(DRSL, "\n");
-}
-
-/*! \brief Issue IPA RSL CRCX to configure RTP on BTS side
- *  \param[in] lchan Logical Channel for which we issue CRCX
- */
-int rsl_ipacc_crcx(struct gsm_lchan *lchan)
-{
-	struct msgb *msg = rsl_msgb_alloc();
-	struct abis_rsl_dchan_hdr *dh;
-
-	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
-	init_dchan_hdr(dh, RSL_MT_IPAC_CRCX);
-	dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
-	dh->chan_nr = gsm_lchan2chan_nr(lchan);
-
-	/* 0x1- == receive-only, 0x-1 == EFR codec */
-	lchan->abis_ip.speech_mode = 0x10 | ipa_smod_s_for_lchan(lchan);
-	lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
-	msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
-	msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
-
-	DEBUGP(DRSL, "%s IPAC_BIND speech_mode=0x%02x RTP_PAYLOAD=%d\n",
-		gsm_lchan_name(lchan), lchan->abis_ip.speech_mode,
-		lchan->abis_ip.rtp_payload);
-
-	msg->dst = lchan->ts->trx->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-/*! \brief Issue IPA RSL MDCX to configure MGW-side of RTP
- *  \param[in] lchan Logical Channel for which we issue MDCX
- *  \param[in] ip Remote (MGW) IP address for RTP
- *  \param[in] port Remote (MGW) UDP port number for RTP
- *  \param[in] rtp_payload2 Contents of RTP PAYLOAD 2 IE
- */
-int rsl_ipacc_mdcx(struct gsm_lchan *lchan, uint32_t ip, uint16_t port,
-		   uint8_t rtp_payload2)
-{
-	struct msgb *msg = rsl_msgb_alloc();
-	struct abis_rsl_dchan_hdr *dh;
-	uint32_t *att_ip;
-	struct in_addr ia;
-
-	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
-	init_dchan_hdr(dh, RSL_MT_IPAC_MDCX);
-	dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
-	dh->chan_nr = gsm_lchan2chan_nr(lchan);
-
-	/* we need to store these now as MDCX_ACK does not return them :( */
-	lchan->abis_ip.rtp_payload2 = rtp_payload2;
-	lchan->abis_ip.connect_port = port;
-	lchan->abis_ip.connect_ip = ip;
-
-	/* 0x0- == both directions, 0x-1 == EFR codec */
-	lchan->abis_ip.speech_mode = 0x00 | ipa_smod_s_for_lchan(lchan);
-	lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
-
-	ia.s_addr = htonl(ip);
-	DEBUGP(DRSL, "%s IPAC_MDCX IP=%s PORT=%d RTP_PAYLOAD=%d RTP_PAYLOAD2=%d "
-		"CONN_ID=%d speech_mode=0x%02x\n", gsm_lchan_name(lchan),
-		inet_ntoa(ia), port, lchan->abis_ip.rtp_payload, rtp_payload2,
-		lchan->abis_ip.conn_id, lchan->abis_ip.speech_mode);
-
-	msgb_tv16_put(msg, RSL_IE_IPAC_CONN_ID, lchan->abis_ip.conn_id);
-	msgb_v_put(msg, RSL_IE_IPAC_REMOTE_IP);
-	att_ip = (uint32_t *) msgb_put(msg, sizeof(ip));
-	*att_ip = ia.s_addr;
-	msgb_tv16_put(msg, RSL_IE_IPAC_REMOTE_PORT, port);
-	msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
-	msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
-	if (rtp_payload2)
-		msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
-
-	msg->dst = lchan->ts->trx->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-/* tell BTS to connect RTP stream to our local RTP socket */
-int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan)
-{
-	struct rtp_socket *rs = lchan->abis_ip.rtp_socket;
-	int rc;
-
-	rc = rsl_ipacc_mdcx(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
-				ntohs(rs->rtp.sin_local.sin_port),
-			/* FIXME: use RTP payload of bound socket, not BTS*/
-				lchan->abis_ip.rtp_payload2);
-
-	return rc;
-}
-
-int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act)
-{
-	struct msgb *msg = rsl_msgb_alloc();
-	struct abis_rsl_dchan_hdr *dh;
-	uint8_t msg_type;
-
-	if (ts->flags & TS_F_PDCH_PENDING_MASK) {
-		LOGP(DRSL, LOGL_ERROR,
-		     "%s PDCH %s requested, but a PDCH%s%s is still pending\n",
-		     gsm_ts_name(ts),
-		     act ? "ACT" : "DEACT",
-		     ts->flags & TS_F_PDCH_ACT_PENDING? " ACT" : "",
-		     ts->flags & TS_F_PDCH_DEACT_PENDING? " DEACT" : "");
-		return -EINVAL;
-	}
-
-	if (act){
-		/* Callers should heed the GPRS mode. */
-		OSMO_ASSERT(ts->trx->bts->gprs.mode != BTS_GPRS_NONE);
-		msg_type = RSL_MT_IPAC_PDCH_ACT;
-		ts->flags |= TS_F_PDCH_ACT_PENDING;
-	} else {
-		msg_type = RSL_MT_IPAC_PDCH_DEACT;
-		ts->flags |= TS_F_PDCH_DEACT_PENDING;
-	}
-	/* TODO add timeout to cancel PDCH DE/ACT */
-
-	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
-	init_dchan_hdr(dh, msg_type);
-	dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
-	dh->chan_nr = gsm_pchan2chan_nr(GSM_PCHAN_TCH_F, ts->nr, 0);
-
-	DEBUGP(DRSL, "%s IPAC PDCH %sACT\n", gsm_ts_name(ts),
-		act ? "" : "DE");
-
-	msg->dst = ts->trx->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-static int abis_rsl_rx_ipacc_crcx_ack(struct msgb *msg)
-{
-	struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
-	struct tlv_parsed tv;
-	struct gsm_lchan *lchan = msg->lchan;
-
-	/* the BTS has acknowledged a local bind, it now tells us the IP
-	* address and port number to which it has bound the given logical
-	* channel */
-
-	rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
-	if (!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_PORT) ||
-	    !TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_IP) ||
-	    !TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
-		LOGP(DRSL, LOGL_NOTICE, "mandatory IE missing");
-		return -EINVAL;
-	}
-
-	ipac_parse_rtp(lchan, &tv);
-
-	osmo_signal_dispatch(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
-
-	return 0;
-}
-
-static int abis_rsl_rx_ipacc_mdcx_ack(struct msgb *msg)
-{
-	struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
-	struct tlv_parsed tv;
-	struct gsm_lchan *lchan = msg->lchan;
-
-	/* the BTS has acknowledged a remote connect request and
-	 * it now tells us the IP address and port number to which it has
-	 * connected the given logical channel */
-
-	rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
-	ipac_parse_rtp(lchan, &tv);
-	osmo_signal_dispatch(SS_ABISIP, S_ABISIP_MDCX_ACK, msg->lchan);
-
-	return 0;
-}
-
-static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
-{
-	struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
-	struct tlv_parsed tv;
-
-	rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
-
-	if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
-		print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
-				TLVP_LEN(&tv, RSL_IE_CAUSE));
-
-	osmo_signal_dispatch(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
-
-	return 0;
-}
-
-static int abis_rsl_rx_ipacc(struct msgb *msg)
-{
-	struct e1inp_sign_link *sign_link = msg->dst;
-	struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
-	char *ts_name;
-	int rc = 0;
-
-	msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr,
-				  "Abis RSL rx IPACC: ");
-	ts_name = gsm_lchan_name(msg->lchan);
-	
-	switch (rllh->c.msg_type) {
-	case RSL_MT_IPAC_CRCX_ACK:
-		DEBUGP(DRSL, "%s IPAC_CRCX_ACK ", ts_name);
-		rc = abis_rsl_rx_ipacc_crcx_ack(msg);
-		break;
-	case RSL_MT_IPAC_CRCX_NACK:
-		/* somehow the BTS was unable to bind the lchan to its local
-		 * port?!? */
-		LOGP(DRSL, LOGL_ERROR, "%s IPAC_CRCX_NACK\n", ts_name);
-		break;
-	case RSL_MT_IPAC_MDCX_ACK:
-		/* the BTS tells us that a connect operation was successful */
-		DEBUGP(DRSL, "%s IPAC_MDCX_ACK ", ts_name);
-		rc = abis_rsl_rx_ipacc_mdcx_ack(msg);
-		break;
-	case RSL_MT_IPAC_MDCX_NACK:
-		/* somehow the BTS was unable to connect the lchan to a remote
-		 * port */
-		LOGP(DRSL, LOGL_ERROR, "%s IPAC_MDCX_NACK\n", ts_name);
-		break;
-	case RSL_MT_IPAC_DLCX_IND:
-		DEBUGP(DRSL, "%s IPAC_DLCX_IND ", ts_name);
-		rc = abis_rsl_rx_ipacc_dlcx_ind(msg);
-		break;
-	default:
-		LOGP(DRSL, LOGL_NOTICE, "Unknown ip.access msg_type 0x%02x\n",
-			rllh->c.msg_type);
-		break;
-	}
-
-	return rc;
-}
-
-int dyn_ts_switchover_start(struct gsm_bts_trx_ts *ts,
-			    enum gsm_phys_chan_config to_pchan)
-{
-	int ss;
-	int rc = -EIO;
-
-	OSMO_ASSERT(ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH);
-	DEBUGP(DRSL, "%s starting switchover to %s\n",
-	       gsm_ts_and_pchan_name(ts), gsm_pchan_name(to_pchan));
-
-	if (ts->dyn.pchan_is != ts->dyn.pchan_want) {
-		LOGP(DRSL, LOGL_ERROR,
-		     "%s: Attempt to switch dynamic channel to %s,"
-		     " but is already in switchover.\n",
-		     gsm_ts_and_pchan_name(ts),
-		     gsm_pchan_name(to_pchan));
-		return ts->dyn.pchan_want == to_pchan? 0 : -EAGAIN;
-	}
-
-	if (ts->dyn.pchan_is == to_pchan) {
-		LOGP(DRSL, LOGL_INFO,
-		     "%s %s Already is in %s mode, cannot switchover.\n",
-		     gsm_ts_name(ts), gsm_pchan_name(ts->pchan),
-		     gsm_pchan_name(to_pchan));
-		return -EINVAL;
-	}
-
-	/* Paranoia: let's make sure all is indeed released. */
-	for (ss = 0; ss < ts_subslots(ts); ss++) {
-		struct gsm_lchan *lc = &ts->lchan[ss];
-		if (lc->state != LCHAN_S_NONE) {
-			LOGP(DRSL, LOGL_ERROR,
-			     "%s Attempt to switch dynamic channel to %s,"
-			     " but is not fully released.\n",
-			     gsm_ts_and_pchan_name(ts),
-			     gsm_pchan_name(to_pchan));
-			return -EAGAIN;
-		}
-	}
-
-	/* Record that we're busy switching. */
-	ts->dyn.pchan_want = to_pchan;
-
-	/*
-	 * To switch from PDCH, we need to initiate the release from the BSC
-	 * side. dyn_ts_switchover_continue() will be called from
-	 * rsl_rx_rf_chan_rel_ack(). PDCH is always on lchan[0].
-	 */
-	if (ts->dyn.pchan_is == GSM_PCHAN_PDCH) {
-		rsl_lchan_set_state(ts->lchan, LCHAN_S_REL_REQ);
-		rc = rsl_rf_chan_release(ts->lchan, 0, SACCH_NONE);
-		if (rc) {
-			LOGP(DRSL, LOGL_ERROR,
-			     "%s RSL RF Chan Release failed\n",
-			     gsm_ts_and_pchan_name(ts));
-			return dyn_ts_switchover_failed(ts, rc);
-		}
-		return 0;
-	}
-
-	/*
-	 * To switch from TCH/F and TCH/H pchans, this has been called from
-	 * rsl_rx_rf_chan_rel_ack(), i.e. release is complete. Go ahead and
-	 * activate as new type. This will always be PDCH.
-	 */
-	return dyn_ts_switchover_continue(ts);
-}
-
-static int dyn_ts_switchover_continue(struct gsm_bts_trx_ts *ts)
-{
-	int rc;
-	uint8_t act_type;
-	uint8_t ho_ref;
-	int ss;
-	struct gsm_lchan *lchan;
-
-	OSMO_ASSERT(ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH);
-	DEBUGP(DRSL, "%s switchover: release complete,"
-	       " activating new pchan type\n",
-	       gsm_ts_and_pchan_name(ts));
-
-	if (ts->dyn.pchan_is == ts->dyn.pchan_want) {
-		LOGP(DRSL, LOGL_ERROR,
-		     "%s Requested to switchover dynamic channel to the"
-		     " same type it is already in.\n",
-		     gsm_ts_and_pchan_name(ts));
-		return 0;
-	}
-
-	for (ss = 0; ss < ts_subslots(ts); ss++) {
-		lchan = &ts->lchan[ss];
-		if (lchan->rqd_ref) {
-			LOGP(DRSL, LOGL_ERROR,
-			     "%s During dyn TS switchover, expecting no"
-			     " Request Reference to be pending. Discarding!\n",
-			     gsm_lchan_name(lchan));
-			talloc_free(lchan->rqd_ref);
-			lchan->rqd_ref = NULL;
-		}
-	}
-
-	/*
-	 * When switching pchan modes, all lchans are unused. So always
-	 * activate whatever wants to be activated on the first lchan.  (We
-	 * wouldn't remember to use lchan[1] across e.g. a PDCH deact anyway)
-	 */
-	lchan = ts->lchan;
-	
-	/*
-	 * For TCH/x, the lchan->type has been set in lchan_alloc(), but it may
-	 * have been lost during channel release due to dynamic switchover.
-	 *
-	 * For PDCH, the lchan->type will actually remain NONE.
-	 * TODO: set GSM_LCHAN_PDTCH?
-	 */
-	switch (ts->dyn.pchan_want) {
-	case GSM_PCHAN_TCH_F:
-		lchan->type = GSM_LCHAN_TCH_F;
-		break;
-	case GSM_PCHAN_TCH_H:
-		lchan->type = GSM_LCHAN_TCH_H;
-		break;
-	case GSM_PCHAN_PDCH:
-		lchan->type = GSM_LCHAN_NONE;
-		break;
-	default:
-		LOGP(DRSL, LOGL_ERROR,
-		     "%s Invalid target pchan for dynamic TS\n",
-		     gsm_ts_and_pchan_name(ts));
-	}
-
-	act_type = (ts->dyn.pchan_want == GSM_PCHAN_PDCH)
-		? RSL_ACT_OSMO_PDCH
-		: lchan->dyn.act_type;
-	ho_ref = (ts->dyn.pchan_want == GSM_PCHAN_PDCH)
-		? 0
-		: lchan->dyn.ho_ref;
-
-	/* Fetch the rqd_ref back from before switchover started. */
-	lchan->rqd_ref = lchan->dyn.rqd_ref;
-	lchan->rqd_ta = lchan->dyn.rqd_ta;
-	lchan->dyn.rqd_ref = NULL;
-	lchan->dyn.rqd_ta = 0;
-
-	/* During switchover, we have received a release ack, which means that
-	 * the act_timer has been stopped. Start the timer again so we mark
-	 * this channel broken if the activation ack comes too late. */
-	osmo_timer_setup(&lchan->act_timer, lchan_act_tmr_cb, lchan);
-	osmo_timer_schedule(&lchan->act_timer, 4, 0);
-
-	rc = rsl_chan_activate_lchan(lchan, act_type, ho_ref);
-	if (rc) {
-		LOGP(DRSL, LOGL_ERROR,
-		     "%s RSL Chan Activate failed\n",
-		     gsm_ts_and_pchan_name(ts));
-		return dyn_ts_switchover_failed(ts, rc);
-	}
-	return 0;
-}
-
-static int dyn_ts_switchover_failed(struct gsm_bts_trx_ts *ts, int rc)
-{
-	ts->dyn.pchan_want = ts->dyn.pchan_is;
-	LOGP(DRSL, LOGL_ERROR, "%s Error %d during dynamic channel switchover."
-	     " Going back to previous pchan.\n", gsm_ts_and_pchan_name(ts),
-	     rc);
-	return rc;
-}
-
-static void dyn_ts_switchover_complete(struct gsm_lchan *lchan)
-{
-	enum gsm_phys_chan_config pchan_act;
-	enum gsm_phys_chan_config pchan_was;
-	struct gsm_bts_trx_ts *ts = lchan->ts;
-
-	OSMO_ASSERT(ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH);
-
-	pchan_act = pchan_for_lchant(lchan->type);
-	/*
-	 * Paranoia: do the types match?
-	 * In case of errors: we've received an act ack already, so what to do
-	 * about it? Logging the error should suffice for now.
-	 */
-	if (pchan_act != ts->dyn.pchan_want)
-		LOGP(DRSL, LOGL_ERROR,
-		     "%s Requested transition does not match lchan type %s\n",
-		     gsm_ts_and_pchan_name(ts),
-		     gsm_lchant_name(lchan->type));
-
-	pchan_was = ts->dyn.pchan_is;
-	ts->dyn.pchan_is = ts->dyn.pchan_want = pchan_act;
-
-	if (pchan_was != ts->dyn.pchan_is)
-		LOGP(DRSL, LOGL_INFO, "%s switchover from %s complete.\n",
-		     gsm_ts_and_pchan_name(ts), gsm_pchan_name(pchan_was));
-}
-
-/* Entry-point where L2 RSL from BTS enters */
-int abis_rsl_rcvmsg(struct msgb *msg)
-{
-	struct abis_rsl_common_hdr *rslh;
-	int rc = 0;
-
-	if (!msg) {
-		DEBUGP(DRSL, "Empty RSL msg?..\n");
-		return -1;
-	}
-
-	if (msgb_l2len(msg) < sizeof(*rslh)) {
-		DEBUGP(DRSL, "Truncated RSL message with l2len: %u\n", msgb_l2len(msg));
-		msgb_free(msg);
-		return -1;
-	}
-
-	rslh = msgb_l2(msg);
-
-	switch (rslh->msg_discr & 0xfe) {
-	case ABIS_RSL_MDISC_RLL:
-		rc = abis_rsl_rx_rll(msg);
-		break;
-	case ABIS_RSL_MDISC_DED_CHAN:
-		rc = abis_rsl_rx_dchan(msg);
-		break;
-	case ABIS_RSL_MDISC_COM_CHAN:
-		rc = abis_rsl_rx_cchan(msg);
-		break;
-	case ABIS_RSL_MDISC_TRX:
-		rc = abis_rsl_rx_trx(msg);
-		break;
-	case ABIS_RSL_MDISC_LOC:
-		LOGP(DRSL, LOGL_NOTICE, "unimplemented RSL msg disc 0x%02x\n",
-			rslh->msg_discr);
-		break;
-	case ABIS_RSL_MDISC_IPACCESS:
-		rc = abis_rsl_rx_ipacc(msg);
-		break;
-	default:
-		LOGP(DRSL, LOGL_NOTICE, "unknown RSL message discriminator "
-			"0x%02x\n", rslh->msg_discr);
-		rc = -EINVAL;
-	}
-	msgb_free(msg);
-	return rc;
-}
-
-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)
-{
-	struct abis_rsl_dchan_hdr *dh;
-	struct msgb *cb_cmd;
-
-	cb_cmd = rsl_msgb_alloc();
-	if (!cb_cmd)
-		return -1;
-
-	dh = (struct abis_rsl_dchan_hdr *) msgb_put(cb_cmd, sizeof(*dh));
-	init_dchan_hdr(dh, RSL_MT_SMS_BC_CMD);
-	dh->c.msg_discr = ABIS_RSL_MDISC_COM_CHAN;
-	dh->chan_nr = chan_number; /* TODO: check the chan config */
-
-	msgb_tv_put(cb_cmd, RSL_IE_CB_CMD_TYPE, *(uint8_t*)&cb_command);
-	msgb_tlv_put(cb_cmd, RSL_IE_SMSCB_MSG, len, data);
-
-	cb_cmd->dst = bts->c0->rsl_link;
-
-	return abis_rsl_sendmsg(cb_cmd);
-}
-
-int rsl_nokia_si_begin(struct gsm_bts_trx *trx)
-{
-	struct abis_rsl_common_hdr *ch;
-	struct msgb *msg = rsl_msgb_alloc();
-
-	ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
-	ch->msg_discr = ABIS_RSL_MDISC_TRX;
-	ch->msg_type = 0x40; /* Nokia SI Begin */
-
-	msg->dst = trx->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-int rsl_nokia_si_end(struct gsm_bts_trx *trx)
-{
-	struct abis_rsl_common_hdr *ch;
-	struct msgb *msg = rsl_msgb_alloc();
-
-	ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
-	ch->msg_discr = ABIS_RSL_MDISC_TRX;
-	ch->msg_type = 0x41;  /* Nokia SI End */
-
-	msgb_tv_put(msg, 0xFD, 0x00); /* Nokia Pagemode Info, No paging reorganisation required */
-
-	msg->dst = trx->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction)
-{
-	struct abis_rsl_common_hdr *ch;
-	struct msgb *msg = rsl_msgb_alloc();
-
-	ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
-	ch->msg_discr = ABIS_RSL_MDISC_DED_CHAN;
-	ch->msg_type = RSL_MT_BS_POWER_CONTROL;
-
-	msgb_tv_put(msg, RSL_IE_CHAN_NR, channel);
-	msgb_tv_put(msg, RSL_IE_BS_POWER, reduction); /* reduction in 2dB steps */
-
-	msg->dst = trx->rsl_link;
-
-	return abis_rsl_sendmsg(msg);
-}
-
-/**
- * Release all allocated SAPIs starting from @param start and
- * release them with the given release mode. Once the release
- * confirmation arrives it will be attempted to release the
- * the RF channel.
- */
-int rsl_release_sapis_from(struct gsm_lchan *lchan, int start,
-			enum rsl_rel_mode release_mode)
-{
-	int no_sapi = 1;
-	int sapi;
-
-	for (sapi = start; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
-		uint8_t link_id;
-		if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
-			continue;
-
-		link_id = sapi;
-		if (lchan->type == GSM_LCHAN_TCH_F || lchan->type == GSM_LCHAN_TCH_H)
-			link_id |= 0x40;
-		rsl_release_request(lchan, link_id, release_mode);
-		no_sapi = 0;
-	}
-
-	return no_sapi;
-}
-
-int rsl_start_t3109(struct gsm_lchan *lchan)
-{
-	struct gsm_bts *bts = lchan->ts->trx->bts;
-
-	osmo_timer_setup(&lchan->T3109, t3109_expired, lchan);
-	osmo_timer_schedule(&lchan->T3109, bts->network->T3109, 0);
-	return 0;
-}
-
-/**
- * \brief directly RF Channel Release the lchan
- *
- * When no SAPI was allocated, directly release the logical channel. This
- * should only be called from chan_alloc.c on channel release handling. In
- * case no SAPI was established the RF Channel can be directly released,
- */
-int rsl_direct_rf_release(struct gsm_lchan *lchan)
-{
-	int i;
-	for (i = 0; i < ARRAY_SIZE(lchan->sapis); ++i) {
-		if (lchan->sapis[i] != LCHAN_SAPI_UNUSED) {
-			LOGP(DRSL, LOGL_ERROR, "%s SAPI(%d) still allocated.\n",
-				gsm_lchan_name(lchan), i);
-			return -1;
-		}
-	}
-
-	/* Now release it */
-	return rsl_rf_chan_release(lchan, 0, SACCH_NONE);
-}
diff --git a/src/libbsc/arfcn_range_encode.c b/src/libbsc/arfcn_range_encode.c
deleted file mode 100644
index 9ca4840..0000000
--- a/src/libbsc/arfcn_range_encode.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/* gsm 04.08 system information (si) encoding and decoding
- * 3gpp ts 04.08 version 7.21.0 release 1998 / etsi ts 100 940 v7.21.0 */
-
-/*
- * (C) 2012 Holger Hans Peter Freyther
- * (C) 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/>.
- */
-
-#include <openbsc/arfcn_range_encode.h>
-#include <openbsc/debug.h>
-
-#include <osmocom/gsm/protocol/gsm_04_08.h>
-
-#include <osmocom/core/utils.h>
-
-#include <errno.h>
-
-static inline int greatest_power_of_2_lesser_or_equal_to(int index)
-{
-	int power_of_2 = 1;
-
-	do {
-		power_of_2 *= 2;
-	} while (power_of_2 <= index);
-
-	/* now go back one step */
-	return power_of_2 / 2;
-}
-
-static inline int mod(int data, int range)
-{
-	int res = data % range;
-	while (res < 0)
-		res += range;
-	return res;
-}
-
-/**
- * Determine at which index to split the ARFCNs to create an
- * equally size partition for the given range. Return -1 if
- * no such partition exists.
- */
-int range_enc_find_index(enum gsm48_range range, const int *freqs, const int size)
-{
-	int i, j, n;
-
-	const int RANGE_DELTA = (range - 1) / 2;
-
-	for (i = 0; i < size; ++i) {
-		n = 0;
-		for (j = 0; j < size; ++j) {
-			if (mod(freqs[j] - freqs[i], range) <= RANGE_DELTA)
-				n += 1;
-		}
-
-		if (n - 1 == (size - 1) / 2)
-			return i;
-	}
-
-	return -1;
-}
-
-/**
- * Range encode the ARFCN list.
- * \param range The range to use.
- * \param arfcns The list of ARFCNs
- * \param size The size of the list of ARFCNs
- * \param out Place to store the W(i) output.
- */
-int range_enc_arfcns(enum gsm48_range range,
-		const int *arfcns, int size, int *out,
-		const int index)
-{
-	int split_at;
-	int i;
-
-	/*
-	 * The below is a GNU extension and we can remove it when
-	 * we move to a quicksort like in-situ swap with the pivot.
-	 */
-	int arfcns_left[size / 2];
-	int arfcns_right[size / 2];
-	int l_size;
-	int r_size;
-	int l_origin;
-	int r_origin;
-
-
-	/* Test the two recursion anchors and stop processing */
-	if (size == 0)
-		return 0;
-
-	if (size == 1) {
-		out[index] = 1 + arfcns[0];
-		return 0;
-	}
-
-	/* Now do the processing */
-	split_at = range_enc_find_index(range, arfcns, size);
-	if (split_at < 0)
-		return -EINVAL;
-
-	/* we now know where to split */
-	out[index] = 1 + arfcns[split_at];
-
-	/* calculate the work that needs to be done for the leafs */
-	l_origin = mod(arfcns[split_at] + ((range - 1) / 2) + 1, range);
-	r_origin = mod(arfcns[split_at] + 1, range);
-	for (i = 0, l_size = 0, r_size = 0; i < size; ++i) {
-		if (mod(arfcns[i] - l_origin, range) < range / 2)
-			arfcns_left[l_size++] = mod(arfcns[i] - l_origin, range);
-		if (mod(arfcns[i] - r_origin, range) < range / 2)
-			arfcns_right[r_size++] = mod(arfcns[i] - r_origin, range);
-	}
-
-	/*
-	 * Now recurse and we need to make this iterative... but as the
-	 * tree is balanced the stack will not be too deep.
-	 */
-	if (l_size)
-		range_enc_arfcns(range / 2, arfcns_left, l_size,
-			out, index + greatest_power_of_2_lesser_or_equal_to(index + 1));
-	if (r_size)
-		range_enc_arfcns((range - 1) / 2, arfcns_right, r_size,
-			 out, index + (2 * greatest_power_of_2_lesser_or_equal_to(index + 1)));
-	return 0;
-}
-
-/*
- * The easiest is to use f0 == arfcns[0]. This means that under certain
- * circumstances we can encode less ARFCNs than possible with an optimal f0.
- *
- * TODO: Solve the optimisation problem and pick f0 so that the max distance
- * is the smallest. Taking into account the modulo operation. I think picking
- * size/2 will be the optimal arfcn.
- */
-/**
- * This implements the range determination as described in GSM 04.08 J4. The
- * result will be a base frequency f0 and the range to use. Note that for range
- * 1024 encoding f0 always refers to ARFCN 0 even if it is not an element of
- * the arfcns list.
- *
- * \param[in] arfcns The input frequencies, they must be sorted, lowest number first
- * \param[in] size The length of the array
- * \param[out] f0 The selected F0 base frequency. It might not be inside the list
- */
-int range_enc_determine_range(const int *arfcns, const int size, int *f0)
-{
-	int max = 0;
-
-	/*
-	 * Go for the easiest. And pick arfcns[0] == f0.
-	 */
-	max = arfcns[size - 1] - arfcns[0];
-	*f0 = arfcns[0];
-
-	if (max < 128 && size <= 29)
-		return ARFCN_RANGE_128;
-	if (max < 256 && size <= 22)
-		return ARFCN_RANGE_256;
-	if (max < 512 && size <= 18)
-		return ARFCN_RANGE_512;
-	if (max < 1024 && size <= 17) {
-		*f0 = 0;
-		return ARFCN_RANGE_1024;
-	}
-
-	return ARFCN_RANGE_INVALID;
-}
-
-static void write_orig_arfcn(uint8_t *chan_list, int f0)
-{
-	chan_list[0] |= (f0 >> 9) & 1;
-	chan_list[1] = (f0 >> 1);
-	chan_list[2] = (f0 & 1) << 7;
-}
-
-static void write_all_wn(uint8_t *chan_list, int bit_offs,
-			 int *w, int w_size, int w1_len)
-{
-	int octet_offs = 0; /* offset into chan_list */
-	int wk_len = w1_len; /* encoding size in bits of w[k] */
-	int k; /* 1 based */
-	int level = 0; /* tree level, top level = 0 */
-	int lvl_left = 1; /* nodes per tree level */
-
-	/* W(2^i) to W(2^(i+1)-1) are on w1_len-i bits when present */
-
-	for (k = 1; k <= w_size; k++) {
-		int wk_left = wk_len;
-		DEBUGP(DRR,
-		       "k=%d, wk_len=%d, offs=%d:%d, level=%d, "
-		       "lvl_left=%d\n",
-		       k, wk_len, octet_offs, bit_offs, level, lvl_left);
-
-		while (wk_left > 0) {
-			int cur_bits = 8 - bit_offs;
-			int cur_mask;
-			int wk_slice;
-
-			if (cur_bits > wk_left)
-				cur_bits = wk_left;
-
-			cur_mask = ((1 << cur_bits) - 1);
-
-			DEBUGP(DRR,
-			       " wk_left=%d, cur_bits=%d, offs=%d:%d\n",
-			       wk_left, cur_bits, octet_offs, bit_offs);
-
-			/* advance */
-			wk_left -= cur_bits;
-			bit_offs += cur_bits;
-
-			/* right aligned wk data for current out octet */
-			wk_slice = (w[k-1] >> wk_left) & cur_mask;
-
-			/* cur_bits now contains the number of bits
-			 * that are to be copied from wk to the chan_list.
-			 * wk_left is set to the number of bits that must
-			 * not yet be copied.
-			 * bit_offs points after the bit area that is going to
-			 * be overwritten:
-			 *
-			 *          wk_left
-			 *             |
-			 *             v
-			 * wk: WWWWWWWWWWW
-			 *        |||||<-- wk_slice, cur_bits=5
-			 *      --WWWWW-
-			 *             ^
-			 *             |
-			 *           bit_offs
-			 */
-
-			DEBUGP(DRR,
-			       " wk=%02x, slice=%02x/%02x, cl=%02x\n",
-			       w[k-1], wk_slice, cur_mask, wk_slice << (8 - bit_offs));
-
-			chan_list[octet_offs] &= ~(cur_mask << (8 - bit_offs));
-			chan_list[octet_offs] |= wk_slice << (8 - bit_offs);
-
-			/* adjust output */
-			if (bit_offs == 8) {
-				bit_offs = 0;
-				octet_offs += 1;
-			}
-		}
-
-		/* adjust bit sizes */
-		lvl_left -= 1;
-		if (!lvl_left) {
-			/* completed tree level, advance to next */
-			level += 1;
-			lvl_left = 1 << level;
-			wk_len -= 1;
-		}
-	}
-}
-
-int range_enc_range128(uint8_t *chan_list, int f0, int *w)
-{
-	chan_list[0] = 0x8C;
-	write_orig_arfcn(chan_list, f0);
-
-	write_all_wn(&chan_list[2], 1, w, 28, 7);
-	return 0;
-}
-
-int range_enc_range256(uint8_t *chan_list, int f0, int *w)
-{
-	chan_list[0] = 0x8A;
-	write_orig_arfcn(chan_list, f0);
-
-	write_all_wn(&chan_list[2], 1, w, 21, 8);
-	return 0;
-}
-
-int range_enc_range512(uint8_t *chan_list, int f0, int *w)
-{
-	chan_list[0] = 0x88;
-	write_orig_arfcn(chan_list, f0);
-
-	write_all_wn(&chan_list[2], 1, w, 17, 9);
-	return 0;
-}
-
-int range_enc_range1024(uint8_t *chan_list, int f0, int f0_included, int *w)
-{
-	chan_list[0] = 0x80 | (f0_included << 2);
-
-	write_all_wn(&chan_list[0], 6, w, 16, 10);
-	return 0;
-}
-
-int range_enc_filter_arfcns(int *arfcns,
-			    const int size, const int f0, int *f0_included)
-{
-	int i, j = 0;
-	*f0_included = 0;
-
-	for (i = 0; i < size; ++i) {
-		/*
-		 * Appendix J.4 says the following:
-		 * All frequencies except F(0), minus F(0) + 1.
-		 * I assume we need to exclude it here.
-		 */
-		if (arfcns[i] == f0) {
-			*f0_included = 1;
-			continue;
-		}
-
-		arfcns[j++] = mod(arfcns[i] - (f0 + 1), 1024);
-	}
-
-	return j;
-}
diff --git a/src/libbsc/bsc_api.c b/src/libbsc/bsc_api.c
deleted file mode 100644
index c60f818..0000000
--- a/src/libbsc/bsc_api.c
+++ /dev/null
@@ -1,897 +0,0 @@
-/* GSM 08.08 like API for OpenBSC. The bridge from MSC to BSC */
-
-/* (C) 2010-2011 by Holger Hans Peter Freyther
- * (C) 2010-2011 by On-Waves
- * (C) 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/>.
- *
- */
-
-#include <openbsc/bsc_api.h>
-#include <openbsc/bsc_rll.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/signal.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/chan_alloc.h>
-#include <openbsc/handover.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/trau_mux.h>
-#include <openbsc/vlr.h>
-
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-#include <osmocom/gsm/gsm48.h>
-
-#include <osmocom/core/talloc.h>
-
-#define GSM0808_T10_VALUE    6, 0
-
-
-static void rll_ind_cb(struct gsm_lchan *, uint8_t, void *, enum bsc_rllr_ind);
-static void send_sapi_reject(struct gsm_subscriber_connection *conn, int link_id);
-static void handle_release(struct gsm_subscriber_connection *conn, struct bsc_api *bsc, struct  gsm_lchan *lchan);
-static void handle_chan_ack(struct gsm_subscriber_connection *conn, struct bsc_api *bsc, struct  gsm_lchan *lchan);
-static void handle_chan_nack(struct gsm_subscriber_connection *conn, struct bsc_api *bsc, struct  gsm_lchan *lchan);
-
-/* GSM 08.08 3.2.2.33 */
-static uint8_t lchan_to_chosen_channel(struct gsm_lchan *lchan)
-{
-	uint8_t channel_mode = 0, channel = 0;
-
-	switch (lchan->tch_mode) {
-	case GSM48_CMODE_SPEECH_V1:
-	case GSM48_CMODE_SPEECH_EFR:
-	case GSM48_CMODE_SPEECH_AMR:
-		channel_mode = 0x9;
-		break;
-	case GSM48_CMODE_SIGN:
-		channel_mode = 0x8;
-		break;
-	case GSM48_CMODE_DATA_14k5:
-		channel_mode = 0xe;
-		break;
-	case GSM48_CMODE_DATA_12k0:
-		channel_mode = 0xb;
-		break;
-	case GSM48_CMODE_DATA_6k0:
-		channel_mode = 0xc;
-		break;
-	case GSM48_CMODE_DATA_3k6:
-		channel_mode = 0xd;
-		break;
-	}
-
-	switch (lchan->type) {
-	case GSM_LCHAN_NONE:
-		channel = 0x0;
-		break;
-	case GSM_LCHAN_SDCCH:
-		channel = 0x1;
-		break;
-	case GSM_LCHAN_TCH_F:
-		channel = 0x8;
-		break;
-	case GSM_LCHAN_TCH_H:
-		channel = 0x9;
-		break;
-	case GSM_LCHAN_UNKNOWN:
-	default:
-		LOGP(DMSC, LOGL_ERROR, "Unknown lchan type: %p\n", lchan);
-		break;
-	}
-
-	return channel_mode << 4 | channel;
-}
-
-static uint8_t chan_mode_to_speech(struct gsm_lchan *lchan)
-{
-	int mode = 0;
-
-	switch (lchan->tch_mode) {
-	case GSM48_CMODE_SPEECH_V1:
-		mode = 1;
-		break;
-	case GSM48_CMODE_SPEECH_EFR:
-		mode = 0x11;
-		break;
-	case GSM48_CMODE_SPEECH_AMR:
-		mode = 0x21;
-		break;
-	case GSM48_CMODE_SIGN:
-	case GSM48_CMODE_DATA_14k5:
-	case GSM48_CMODE_DATA_12k0:
-	case GSM48_CMODE_DATA_6k0:
-	case GSM48_CMODE_DATA_3k6:
-	default:
-		LOGP(DMSC, LOGL_ERROR, "Using non speech mode: %d\n", mode);
-		return 0;
-		break;
-	}
-
-	/* assume to always do AMR HR on any TCH type */
-	if (lchan->type == GSM_LCHAN_TCH_H ||
-	    lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
-		mode |= 0x4;
-
-        return mode;
-}
-
-static void assignment_t10_timeout(void *_conn)
-{
-	struct bsc_api *api;
-	struct gsm_subscriber_connection *conn =
-		(struct gsm_subscriber_connection *) _conn;
-
-	LOGP(DMSC, LOGL_ERROR, "Assignment T10 timeout on %p\n", conn);
-
-	/*
-	 * normal release on the secondary channel but only if the
-	 * secondary_channel has not been released by the handle_chan_nack.
-	 */
-	if (conn->secondary_lchan)
-		lchan_release(conn->secondary_lchan, 0, RSL_REL_LOCAL_END);
-	conn->secondary_lchan = NULL;
-
-	/* inform them about the failure */
-	api = conn->network->bsc_api;
-	api->assign_fail(conn, GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL);
-}
-
-/*! \brief Determine and apply AMR multi-rate configuration to lchan
- *  Determine which AMR multi-rate configuration to use and apply it to
- *  the lchan (so it can be communicated to BTS and MS during channel
- *  activation.
- *  \param[in] conn subscriber connection (used to resolve bsc_api)
- *  \param[out] lchan logical channel to which to apply mr config
- *  \param[in] full_rate whether to use full-rate (1) or half-rate (0) config
- */
-static void handle_mr_config(struct gsm_subscriber_connection *conn,
-			     struct gsm_lchan *lchan, int full_rate)
-{
-	struct bsc_api *api;
-	api = conn->network->bsc_api;
-	struct amr_multirate_conf *mr;
-	struct gsm48_multi_rate_conf *mr_conf;
-
-	/* BSC api override for this method, used in OsmoBSC mode with
-	 * bsc_mr_config() to use MSC-specific/specified configuration */
-	if (api->mr_config)
-		return api->mr_config(conn, lchan, full_rate);
-
-	/* NITB case: use the BTS-specic multi-rate configuration from
-	 * the vty/configuration file */
-	if (full_rate)
-		mr = &lchan->ts->trx->bts->mr_full;
-	else
-		mr = &lchan->ts->trx->bts->mr_half;
-
-	mr_conf = (struct gsm48_multi_rate_conf *) mr->gsm48_ie;
-	mr_conf->ver = 1;
-
-	/* default, if no AMR codec defined */
-	if (!mr->gsm48_ie[1]) {
-		mr_conf->icmi = 1;
-		mr_conf->m5_90 = 1;
-	}
-	/* store encoded MR config IE lchan for both MS (uplink) and BTS
-	 * (downlink) directions */
-	gsm48_multirate_config(lchan->mr_ms_lv, mr, mr->ms_mode);
-	gsm48_multirate_config(lchan->mr_bts_lv, mr, mr->bts_mode);
-}
-
-/*
- * Start a new assignment and make sure that it is completed within T10 either
- * positively, negatively or by the timeout.
- *
- *  1.) allocate a new lchan
- *  2.) copy the encryption key and other data from the
- *      old to the new channel.
- *  3.) RSL Channel Activate this channel and wait
- *
- * -> Signal handler for the LCHAN
- *  4.) Send GSM 04.08 assignment command to the MS
- *
- * -> Assignment Complete/Assignment Failure
- *  5.) Release the SDCCH, continue signalling on the new link
- */
-static int handle_new_assignment(struct gsm_subscriber_connection *conn, int chan_mode, int full_rate)
-{
-	struct gsm_lchan *new_lchan;
-	int chan_type;
-
-	chan_type = full_rate ? GSM_LCHAN_TCH_F : GSM_LCHAN_TCH_H;
-
-	new_lchan = lchan_alloc(conn->bts, chan_type, 0);
-
-	if (!new_lchan) {
-		LOGP(DMSC, LOGL_NOTICE, "No free channel.\n");
-		return -1;
-	}
-
-	/* copy old data to the new channel */
-	memcpy(&new_lchan->encr, &conn->lchan->encr, sizeof(new_lchan->encr));
-	new_lchan->ms_power = conn->lchan->ms_power;
-	new_lchan->bs_power = conn->lchan->bs_power;
-	new_lchan->rqd_ta = conn->lchan->rqd_ta;
-
-	/* copy new data to it */
-	new_lchan->tch_mode = chan_mode;
-	new_lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
-
-	/* handle AMR correctly */
-	if (chan_mode == GSM48_CMODE_SPEECH_AMR)
-		handle_mr_config(conn, new_lchan, full_rate);
-
-	if (rsl_chan_activate_lchan(new_lchan, 0x1, 0) < 0) {
-		LOGP(DHO, LOGL_ERROR, "could not activate channel\n");
-		lchan_free(new_lchan);
-		return -1;
-	}
-
-	/* remember that we have the channel */
-	conn->secondary_lchan = new_lchan;
-	new_lchan->conn = conn;
-
-	rsl_lchan_set_state(new_lchan, LCHAN_S_ACT_REQ);
-	return 0;
-}
-
-struct gsm_subscriber_connection *bsc_subscr_con_allocate(struct gsm_lchan *lchan)
-{
-	struct gsm_subscriber_connection *conn;
-	struct gsm_network *net = lchan->ts->trx->bts->network;
-
-	conn = talloc_zero(net, struct gsm_subscriber_connection);
-	if (!conn)
-		return NULL;
-
-	conn->network = net;
-	conn->lchan = lchan;
-	conn->bts = lchan->ts->trx->bts;
-	conn->via_ran = RAN_GERAN_A;
-	conn->lac = conn->bts->location_area_code;
-	lchan->conn = conn;
-	llist_add_tail(&conn->entry, &net->subscr_conns);
-	return conn;
-}
-
-void bsc_subscr_con_free(struct gsm_subscriber_connection *conn)
-{
-	if (!conn)
-		return;
-
-	if (conn->network->bsc_api->conn_cleanup)
-		conn->network->bsc_api->conn_cleanup(conn);
-
-	if (conn->vsub) {
-		LOGP(DNM, LOGL_ERROR, "conn->vsub should have been cleared.\n");
-		conn->vsub = NULL;
-	}
-
-	if (conn->ho_lchan) {
-		LOGP(DNM, LOGL_ERROR, "The ho_lchan should have been cleared.\n");
-		conn->ho_lchan->conn = NULL;
-	}
-
-	if (conn->lchan) {
-		LOGP(DNM, LOGL_ERROR, "The lchan should have been cleared.\n");
-		conn->lchan->conn = NULL;
-	}
-
-	if (conn->secondary_lchan) {
-		LOGP(DNM, LOGL_ERROR, "The secondary_lchan should have been cleared.\n");
-		conn->secondary_lchan->conn = NULL;
-	}
-
-	llist_del(&conn->entry);
-	talloc_free(conn);
-}
-
-int bsc_api_init(struct gsm_network *network, struct bsc_api *api)
-{
-	network->bsc_api = api;
-	return 0;
-}
-
-/*! \brief process incoming 08.08 DTAP from MSC (send via BTS to MS) */
-int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn,
-			struct msgb *msg, int link_id, int allow_sacch)
-{
-	uint8_t sapi;
-
-
-	if (!conn->lchan) {
-		LOGP(DMSC, LOGL_ERROR,
-		     "Called submit dtap without an lchan.\n");
-		msgb_free(msg);
-		return -1;
-	}
-
-	sapi = link_id & 0x7;
-	msg->lchan = conn->lchan;
-	msg->dst = msg->lchan->ts->trx->rsl_link;
-
-	/* If we are on a TCH and need to submit a SMS (on SAPI=3) we need to use the SACH */
-	if (allow_sacch && sapi != 0) {
-		if (conn->lchan->type == GSM_LCHAN_TCH_F || conn->lchan->type == GSM_LCHAN_TCH_H)
-			link_id |= 0x40;
-	}
-
-	msg->l3h = msg->data;
-	/* is requested SAPI already up? */
-	if (conn->lchan->sapis[sapi] == LCHAN_SAPI_UNUSED) {
-		/* Establish L2 for additional SAPI */
-		OBSC_LINKID_CB(msg) = link_id;
-		if (rll_establish(msg->lchan, sapi, rll_ind_cb, msg) != 0) {
-			msgb_free(msg);
-			send_sapi_reject(conn, link_id);
-			return -1;
-		}
-		return 0;
-	} else {
-		/* Directly forward via RLL/RSL to BTS */
-		return rsl_data_request(msg, link_id);
-	}
-}
-
-/*
- * \brief Check if the given channel is compatible with the mode/fullrate
- */
-static int chan_compat_with_mode(struct gsm_lchan *lchan, int chan_mode, int full_rate)
-{
-	switch (chan_mode) {
-	case GSM48_CMODE_SIGN:
-		/* signalling is always possible */
-		return 1;
-	case GSM48_CMODE_SPEECH_V1:
-	case GSM48_CMODE_SPEECH_AMR:
-	case GSM48_CMODE_DATA_3k6:
-	case GSM48_CMODE_DATA_6k0:
-		/* these services can all run on TCH/H, but we may have
-		 * an explicit override by the 'full_rate' argument */
-		switch (lchan->type) {
-		case GSM_LCHAN_TCH_F:
-			return 1;
-		case GSM_LCHAN_TCH_H:
-			if (full_rate)
-				return 0;
-			else
-				return 1;
-			break;
-		default:
-			return 0;
-		}
-		break;
-	case GSM48_CMODE_DATA_12k0:
-	case GSM48_CMODE_DATA_14k5:
-	case GSM48_CMODE_SPEECH_EFR:
-		/* these services all explicitly require a TCH/F */
-		if (lchan->type == GSM_LCHAN_TCH_F)
-			return 1;
-		else
-			return 0;
-		break;
-	}
-
-	return 0;
-}
-
-/**
- * Send a GSM08.08 Assignment Request. Right now this does not contain the
- * audio codec type or the allowed rates for the config. It is assumed that
- * this is for audio handling only. In case the current channel does not allow
- * the selected mode a new one will be allocated.
- *
- * TODO: Add multirate configuration, make it work for more than audio.
- */
-int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, int full_rate)
-{
-	struct bsc_api *api;
-	api = conn->network->bsc_api;
-
-	if (!chan_compat_with_mode(conn->lchan, chan_mode, full_rate)) {
-		if (handle_new_assignment(conn, chan_mode, full_rate) != 0)
-			goto error;
-	} else {
-		if (chan_mode == GSM48_CMODE_SPEECH_AMR)
-			handle_mr_config(conn, conn->lchan, full_rate);
-
-		LOGP(DMSC, LOGL_NOTICE,
-		     "Sending %s ChanModify for speech: %s on channel %s\n",
-		     gsm_lchan_name(conn->lchan),
-		     get_value_string(gsm48_chan_mode_names, chan_mode),
-		     get_value_string(gsm_chan_t_names, conn->lchan->type));
-		gsm48_lchan_modify(conn->lchan, chan_mode);
-	}
-
-	/* we will now start the timer to complete the assignment */
-	osmo_timer_setup(&conn->T10, assignment_t10_timeout, conn);
-	osmo_timer_schedule(&conn->T10, GSM0808_T10_VALUE);
-	return 0;
-
-error:
-	api->assign_fail(conn, 0, NULL);
-	return -1;
-}
-
-int gsm0808_page(struct gsm_bts *bts, unsigned int page_group, unsigned int mi_len,
-		 uint8_t *mi, int chan_type)
-{
-	return rsl_paging_cmd(bts, page_group, mi_len, mi, chan_type, false);
-}
-
-static void handle_ass_compl(struct gsm_subscriber_connection *conn,
-			     struct msgb *msg)
-{
-	struct gsm48_hdr *gh;
-	struct bsc_api *api = conn->network->bsc_api;
-
-	if (conn->secondary_lchan != msg->lchan) {
-		LOGP(DMSC, LOGL_ERROR, "Assignment Compl should occur on second lchan.\n");
-		return;
-	}
-
-	gh = msgb_l3(msg);
-	if (msgb_l3len(msg) - sizeof(*gh) != 1) {
-		LOGP(DMSC, LOGL_ERROR, "Assignment Compl invalid: %zu\n",
-		     msgb_l3len(msg) - sizeof(*gh));
-		return;
-	}
-
-	/* switch TRAU muxer for E1 based BTS from one channel to another */
-	if (is_e1_bts(conn->bts))
-		switch_trau_mux(conn->lchan, conn->secondary_lchan);
-
-	/* swap channels */
-	osmo_timer_del(&conn->T10);
-
-	lchan_release(conn->lchan, 0, RSL_REL_LOCAL_END);
-	conn->lchan = conn->secondary_lchan;
-	conn->secondary_lchan = NULL;
-
-	if (is_ipaccess_bts(conn->bts) && conn->lchan->tch_mode != GSM48_CMODE_SIGN)
-		rsl_ipacc_crcx(conn->lchan);
-
-	api->assign_compl(conn, gh->data[0],
-			  lchan_to_chosen_channel(conn->lchan),
-			  conn->lchan->encr.alg_id,
-			  chan_mode_to_speech(conn->lchan));
-}
-
-static void handle_ass_fail(struct gsm_subscriber_connection *conn,
-			    struct msgb *msg)
-{
-	struct bsc_api *api = conn->network->bsc_api;
-	uint8_t *rr_failure;
-	struct gsm48_hdr *gh;
-
-
-	if (conn->lchan != msg->lchan) {
-		LOGP(DMSC, LOGL_ERROR, "Assignment failure should occur on primary lchan.\n");
-		return;
-	}
-
-	/* stop the timer and release it */
-	osmo_timer_del(&conn->T10);
-	lchan_release(conn->secondary_lchan, 0, RSL_REL_LOCAL_END);
-	conn->secondary_lchan = NULL;
-
-	gh = msgb_l3(msg);
-	if (msgb_l3len(msg) - sizeof(*gh) != 1) {
-		LOGP(DMSC, LOGL_ERROR, "assignment failure unhandled: %zu\n",
-		     msgb_l3len(msg) - sizeof(*gh));
-		rr_failure = NULL;
-	} else {
-		rr_failure = &gh->data[0];
-	}
-
-	api->assign_fail(conn,
-			 GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE,
-			 rr_failure);
-}
-
-static void handle_classmark_chg(struct gsm_subscriber_connection *conn,
-				 struct msgb *msg)
-{
-	struct bsc_api *api = msg->lchan->ts->trx->bts->network->bsc_api;
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
-	uint8_t cm2_len, cm3_len = 0;
-	uint8_t *cm2, *cm3 = NULL;
-
-	DEBUGP(DRR, "CLASSMARK CHANGE ");
-
-	/* classmark 2 */
-	cm2_len = gh->data[0];
-	cm2 = &gh->data[1];
-	DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
-
-	if (payload_len > cm2_len + 1) {
-		/* we must have a classmark3 */
-		if (gh->data[cm2_len+1] != 0x20) {
-			DEBUGPC(DRR, "ERR CM3 TAG\n");
-			return;
-		}
-		if (cm2_len > 3) {
-			DEBUGPC(DRR, "CM2 too long!\n");
-			return;
-		}
-
-		cm3_len = gh->data[cm2_len+2];
-		cm3 = &gh->data[cm2_len+3];
-		if (cm3_len > 14) {
-			DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
-			return;
-		}
-		DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
-	}
-	api->classmark_chg(conn, cm2, cm2_len, cm3, cm3_len);
-}
-
-/* Chapter 9.1.16 Handover complete */
-static void handle_rr_ho_compl(struct msgb *msg)
-{
-	struct lchan_signal_data sig;
-	struct gsm48_hdr *gh = msgb_l3(msg);
-
-	DEBUGP(DRR, "HANDOVER COMPLETE cause = %s\n",
-		rr_cause_name(gh->data[0]));
-
-	sig.lchan = msg->lchan;
-	sig.mr = NULL;
-	osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_COMPL, &sig);
-	/* FIXME: release old channel */
-}
-
-/* Chapter 9.1.17 Handover Failure */
-static void handle_rr_ho_fail(struct msgb *msg)
-{
-	struct lchan_signal_data sig;
-	struct gsm48_hdr *gh = msgb_l3(msg);
-
-	DEBUGP(DRR, "HANDOVER FAILED cause = %s\n",
-		rr_cause_name(gh->data[0]));
-
-	sig.lchan = msg->lchan;
-	sig.mr = NULL;
-	osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_FAIL, &sig);
-	/* FIXME: release allocated new channel */
-}
-
-
-static void dispatch_dtap(struct gsm_subscriber_connection *conn,
-			  uint8_t link_id, struct msgb *msg)
-{
-	struct bsc_api *api = msg->lchan->ts->trx->bts->network->bsc_api;
-	struct gsm48_hdr *gh;
-	uint8_t pdisc;
-	uint8_t msg_type;
-	int rc;
-
-	if (msgb_l3len(msg) < sizeof(*gh)) {
-		LOGP(DMSC, LOGL_ERROR, "Message too short for a GSM48 header.\n");
-		return;
-	}
-
-	gh = msgb_l3(msg);
-	pdisc = gsm48_hdr_pdisc(gh);
-	msg_type = gsm48_hdr_msg_type(gh);
-
-	/* the idea is to handle all RR messages here, and only hand
-	 * MM/CC/SMS-CP/LCS up to the MSC.  Some messages like PAGING
-	 * RESPONSE or CM SERVICE REQUEST will not be covered here, as
-	 * they are only possible in the first L3 message of each L2
-	 * channel, i.e. 'conn' will not exist and gsm0408_rcvmsg()
-	 * will call api->compl_l3() for it */
-	switch (pdisc) {
-	case GSM48_PDISC_RR:
-		switch (msg_type) {
-		case GSM48_MT_RR_GPRS_SUSP_REQ:
-			DEBUGP(DRR, "%s\n",
-			       gsm48_rr_msg_name(GSM48_MT_RR_GPRS_SUSP_REQ));
-			break;
-		case GSM48_MT_RR_STATUS:
-			LOGP(DRR, LOGL_NOTICE, "%s (cause: %s)\n",
-			     gsm48_rr_msg_name(GSM48_MT_RR_STATUS),
-			     rr_cause_name(gh->data[0]));
-			break;
-		case GSM48_MT_RR_MEAS_REP:
-			/* This shouldn't actually end up here, as RSL treats
-			* L3 Info of 08.58 MEASUREMENT REPORT different by calling
-			* directly into gsm48_parse_meas_rep */
-			LOGP(DMEAS, LOGL_ERROR, "DIRECT GSM48 MEASUREMENT REPORT ?!? ");
-			break;
-		case GSM48_MT_RR_HANDO_COMPL:
-			handle_rr_ho_compl(msg);
-			break;
-		case GSM48_MT_RR_HANDO_FAIL:
-			handle_rr_ho_fail(msg);
-			break;
-		case GSM48_MT_RR_CIPH_M_COMPL:
-			if (api->cipher_mode_compl)
-				api->cipher_mode_compl(conn, msg,
-						conn->lchan->encr.alg_id);
-			break;
-		case GSM48_MT_RR_ASS_COMPL:
-			handle_ass_compl(conn, msg);
-			break;
-		case GSM48_MT_RR_ASS_FAIL:
-			handle_ass_fail(conn, msg);
-			break;
-		case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
-			osmo_timer_del(&conn->T10);
-			rc = gsm48_rx_rr_modif_ack(msg);
-			if (rc < 0) {
-				api->assign_fail(conn,
-						 GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE,
-						 NULL);
-			} else if (rc >= 0) {
-				api->assign_compl(conn, 0,
-						  lchan_to_chosen_channel(conn->lchan),
-						  conn->lchan->encr.alg_id,
-						  chan_mode_to_speech(conn->lchan));
-			}
-			break;
-		case GSM48_MT_RR_CLSM_CHG:
-			handle_classmark_chg(conn, msg);
-			break;
-		case GSM48_MT_RR_APP_INFO:
-			/* Passing RR APP INFO to MSC, not quite
-			 * according to spec */
-			if (api->dtap)
-				api->dtap(conn, link_id, msg);
-			break;
-		default:
-			/* Normally, a MSC should never receive RR
-			 * messages, but we'd rather forward what we
-			 * don't know than drop it... */
-			LOGP(DRR, LOGL_NOTICE,
-			     "BSC: Passing %s 04.08 RR message to MSC\n",
-			     gsm48_rr_msg_name(msg_type));
-			if (api->dtap)
-				api->dtap(conn, link_id, msg);
-		}
-		break;
-	default:
-		if (api->dtap)
-			api->dtap(conn, link_id, msg);
-		break;
-	}
-}
-
-/*! \brief RSL has received a DATA INDICATION with L3 from MS */
-int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id)
-{
-	int rc;
-	struct bsc_api *api = msg->lchan->ts->trx->bts->network->bsc_api;
-	struct gsm_lchan *lchan;
-
-	lchan = msg->lchan;
-	if (lchan->state != LCHAN_S_ACTIVE) {
-		LOGP(DRSL, LOGL_INFO, "Got data in non active state(%s), "
-		     "discarding.\n", gsm_lchans_name(lchan->state));
-		return -1;
-	}
-
-
-	if (lchan->conn) {
-		/* if we already have a connection, forward via DTAP to
-		 * MSC */
-		dispatch_dtap(lchan->conn, link_id, msg);
-	} else {
-		/* allocate a new connection */
-		rc = BSC_API_CONN_POL_REJECT;
-		lchan->conn = bsc_subscr_con_allocate(msg->lchan);
-		if (!lchan->conn) {
-			lchan_release(lchan, 1, RSL_REL_NORMAL);
-			return -1;
-		}
-
-		/* fwd via bsc_api to send COMPLETE L3 INFO to MSC */
-		rc = api->compl_l3(lchan->conn, msg, 0);
-
-		if (rc != BSC_API_CONN_POL_ACCEPT) {
-			lchan->conn->lchan = NULL;
-			bsc_subscr_con_free(lchan->conn);
-			lchan_release(lchan, 1, RSL_REL_NORMAL);
-		}
-	}
-
-	return 0;
-}
-
-/*! \brief We received a GSM 08.08 CIPHER MODE from the MSC */
-int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,
-			const uint8_t *key, int len, int include_imeisv)
-{
-	if (cipher > 0 && key == NULL) {
-		LOGP(DRSL, LOGL_ERROR, "Need to have an encrytpion key.\n");
-		return -1;
-	}
-
-	if (len > MAX_A5_KEY_LEN) {
-		LOGP(DRSL, LOGL_ERROR, "The key is too long: %d\n", len);
-		return -1;
-	}
-
-	conn->lchan->encr.alg_id = RSL_ENC_ALG_A5(cipher);
-	if (key) {
-		conn->lchan->encr.key_len = len;
-		memcpy(conn->lchan->encr.key, key, len);
-	}
-
-	return gsm48_send_rr_ciph_mode(conn->lchan, include_imeisv);
-}
-
-/*
- * Release all occupied RF Channels but stay around for more.
- */
-int gsm0808_clear(struct gsm_subscriber_connection *conn)
-{
-	if (conn->ho_lchan)
-		bsc_clear_handover(conn, 1);
-
-	if (conn->secondary_lchan)
-		lchan_release(conn->secondary_lchan, 0, RSL_REL_LOCAL_END);
-
-	if (conn->lchan)
-		lchan_release(conn->lchan, 1, RSL_REL_NORMAL);
-
-	conn->lchan = NULL;
-	conn->secondary_lchan = NULL;
-	conn->ho_lchan = NULL;
-	conn->bts = NULL;
-
-	osmo_timer_del(&conn->T10);
-
-	return 0;
-}
-
-static void send_sapi_reject(struct gsm_subscriber_connection *conn, int link_id)
-{
-	struct bsc_api *api;
-
-	if (!conn)
-		return;
-
-	api = conn->network->bsc_api;
-	if (!api || !api->sapi_n_reject)
-		return;
-
-	api->sapi_n_reject(conn, link_id);
-}
-
-static void rll_ind_cb(struct gsm_lchan *lchan, uint8_t link_id, void *_data, enum bsc_rllr_ind rllr_ind)
-{
-	struct msgb *msg = _data;
-
-	/*
-	 * There seems to be a small window that the RLL timer can
-	 * fire after a lchan_release call and before the S_CHALLOC_FREED
-	 * is called. Check if a conn is set before proceeding.
-	 */
-	if (!lchan->conn)
-		return;
-
-	switch (rllr_ind) {
-	case BSC_RLLR_IND_EST_CONF:
-		rsl_data_request(msg, OBSC_LINKID_CB(msg));
-		break;
-	case BSC_RLLR_IND_REL_IND:
-	case BSC_RLLR_IND_ERR_IND:
-	case BSC_RLLR_IND_TIMEOUT:
-		send_sapi_reject(lchan->conn, OBSC_LINKID_CB(msg));
-		msgb_free(msg);
-		break;
-	}
-}
-
-static int bsc_handle_lchan_signal(unsigned int subsys, unsigned int signal,
-				   void *handler_data, void *signal_data)
-{
-	struct bsc_api *bsc;
-	struct gsm_lchan *lchan;
-	struct lchan_signal_data *lchan_data;
-
-	if (subsys != SS_LCHAN)
-		return 0;
-
-
-	lchan_data = signal_data;
-	if (!lchan_data->lchan || !lchan_data->lchan->conn)
-		return 0;
-
-	lchan = lchan_data->lchan;
-	bsc = lchan->ts->trx->bts->network->bsc_api;
-	if (!bsc)
-		return 0;
-
-	switch (signal) {
-	case S_LCHAN_UNEXPECTED_RELEASE:
-		handle_release(lchan->conn, bsc, lchan);
-		break;
-	case S_LCHAN_ACTIVATE_ACK:
-		handle_chan_ack(lchan->conn, bsc, lchan);
-		break;
-	case S_LCHAN_ACTIVATE_NACK:
-		handle_chan_nack(lchan->conn, bsc, lchan);
-		break;
-	}
-
-	return 0;
-}
-
-static void handle_release(struct gsm_subscriber_connection *conn,
-			   struct bsc_api *bsc, struct gsm_lchan *lchan)
-{
-	int destruct = 1;
-
-	if (conn->secondary_lchan == lchan) {
-		osmo_timer_del(&conn->T10);
-		conn->secondary_lchan = NULL;
-
-		bsc->assign_fail(conn,
-				 GSM0808_CAUSE_RADIO_INTERFACE_FAILURE,
-				 NULL);
-	}
-
-	/* clear the connection now */
-	if (bsc->clear_request)
-		destruct = bsc->clear_request(conn, 0);
-
-	/* now give up all channels */
-	if (conn->lchan == lchan)
-		conn->lchan = NULL;
-	if (conn->ho_lchan == lchan) {
-		bsc_clear_handover(conn, 0);
-		conn->ho_lchan = NULL;
-	}
-	lchan->conn = NULL;
-
-	gsm0808_clear(conn);
-
-	if (destruct)
-		bsc_subscr_con_free(conn);
-}
-
-static void handle_chan_ack(struct gsm_subscriber_connection *conn,
-			    struct bsc_api *api, struct gsm_lchan *lchan)
-{
-	if (conn->secondary_lchan != lchan)
-		return;
-
-	LOGP(DMSC, LOGL_NOTICE, "Sending assignment on chan: %p\n", lchan);
-	gsm48_send_rr_ass_cmd(conn->lchan, lchan, lchan->ms_power);
-}
-
-static void handle_chan_nack(struct gsm_subscriber_connection *conn,
-			     struct bsc_api *api, struct gsm_lchan *lchan)
-{
-	if (conn->secondary_lchan != lchan)
-		return;
-
-	LOGP(DMSC, LOGL_ERROR, "Channel activation failed. Waiting for timeout now\n");
-	conn->secondary_lchan->conn = NULL;
-	conn->secondary_lchan = NULL;
-}
-
-static __attribute__((constructor)) void on_dso_load_bsc(void)
-{
-	osmo_signal_register_handler(SS_LCHAN, bsc_handle_lchan_signal, NULL);
-}
-
diff --git a/src/libbsc/bsc_ctrl_commands.c b/src/libbsc/bsc_ctrl_commands.c
deleted file mode 100644
index 641fe2b..0000000
--- a/src/libbsc/bsc_ctrl_commands.c
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * (C) 2013-2015 by Holger Hans Peter Freyther
- * (C) 2013-2015 by 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 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/>.
- *
- */
-#include <errno.h>
-#include <time.h>
-
-#include <osmocom/ctrl/control_cmd.h>
-#include <openbsc/ipaccess.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/debug.h>
-#include <openbsc/chan_alloc.h>
-#include <openbsc/osmo_bsc_rf.h>
-#include <openbsc/bsc_msc_data.h>
-
-#define CTRL_CMD_VTY_STRING(cmdname, cmdstr, dtype, element) \
-	CTRL_HELPER_GET_STRING(cmdname, dtype, element) \
-	CTRL_HELPER_SET_STRING(cmdname, dtype, element) \
-static struct ctrl_cmd_element cmd_##cmdname = { \
-	.name = cmdstr, \
-	.get = get_##cmdname, \
-	.set = set_##cmdname, \
-	.verify = verify_vty_description_string, \
-}
-
-/**
- * Check that there are no newlines or comments or other things
- * that could make the VTY configuration unparsable.
- */
-static int verify_vty_description_string(struct ctrl_cmd *cmd,
-			const char *value, void *data)
-{
-	int i;
-	const size_t len = strlen(value);
-
-	for (i = 0; i < len; ++i) {
-		switch(value[i]) {
-		case '#':
-		case '\n':
-		case '\r':
-			cmd->reply = "String includes illegal character";
-			return -1;
-		default:
-			break;
-		}
-	}
-
-	return 0;
-}
-
-CTRL_CMD_DEFINE_RANGE(net_mnc, "mnc", struct gsm_network, network_code, 0, 999);
-CTRL_CMD_DEFINE_RANGE(net_mcc, "mcc", struct gsm_network, country_code, 1, 999);
-CTRL_CMD_VTY_STRING(net_short_name, "short-name", struct gsm_network, name_short);
-CTRL_CMD_VTY_STRING(net_long_name, "long-name", struct gsm_network, name_long);
-
-static int set_net_apply_config(struct ctrl_cmd *cmd, void *data)
-{
-	struct gsm_network *net = cmd->node;
-	struct gsm_bts *bts;
-
-	llist_for_each_entry(bts, &net->bts_list, list) {
-		if (!is_ipaccess_bts(bts))
-			continue;
-
-		/*
-		 * The ip.access nanoBTS seems to be unrelaible on BSSGP
-		 * so let's us just reboot it. For the sysmoBTS we can just
-		 * restart the process as all state is gone.
-		 */
-		if (!is_sysmobts_v2(bts) && strcmp(cmd->value, "restart") == 0) {
-			struct gsm_bts_trx *trx;
-			llist_for_each_entry_reverse(trx, &bts->trx_list, list)
-				abis_nm_ipaccess_restart(trx);
-		} else
-			ipaccess_drop_oml(bts);
-	}
-
-	cmd->reply = "Tried to drop the BTS";
-	return CTRL_CMD_REPLY;
-}
-
-CTRL_CMD_DEFINE_WO_NOVRF(net_apply_config, "apply-configuration");
-
-static int verify_net_mcc_mnc_apply(struct ctrl_cmd *cmd, const char *value, void *d)
-{
-	char *tmp, *saveptr, *mcc, *mnc;
-
-	tmp = talloc_strdup(cmd, value);
-	if (!tmp)
-		return 1;
-
-	mcc = strtok_r(tmp, ",", &saveptr);
-	mnc = strtok_r(NULL, ",", &saveptr);
-	talloc_free(tmp);
-
-	if (!mcc || !mnc)
-		return 1;
-	return 0;
-}
-
-static int set_net_mcc_mnc_apply(struct ctrl_cmd *cmd, void *data)
-{
-	struct gsm_network *net = cmd->node;
-	char *tmp, *saveptr, *mcc_str, *mnc_str;
-	int mcc, mnc;
-
-	tmp = talloc_strdup(cmd, cmd->value);
-	if (!tmp)
-		goto oom;
-
-
-	mcc_str = strtok_r(tmp, ",", &saveptr);
-	mnc_str = strtok_r(NULL, ",", &saveptr);
-
-	mcc = atoi(mcc_str);
-	mnc = atoi(mnc_str);
-
-	talloc_free(tmp);
-
-	if (net->network_code == mnc && net->country_code == mcc) {
-		cmd->reply = "Nothing changed";
-		return CTRL_CMD_REPLY;
-	}
-
-	net->network_code = mnc;
-	net->country_code = mcc;
-
-	return set_net_apply_config(cmd, data);
-
-oom:
-	cmd->reply = "OOM";
-	return CTRL_CMD_ERROR;
-}
-CTRL_CMD_DEFINE_WO(net_mcc_mnc_apply, "mcc-mnc-apply");
-
-/* BTS related commands below */
-CTRL_CMD_DEFINE_RANGE(bts_lac, "location-area-code", struct gsm_bts, location_area_code, 0, 65535);
-CTRL_CMD_DEFINE_RANGE(bts_ci, "cell-identity", struct gsm_bts, cell_identity, 0, 65535);
-
-static int set_bts_apply_config(struct ctrl_cmd *cmd, void *data)
-{
-	struct gsm_bts *bts = cmd->node;
-
-	if (!is_ipaccess_bts(bts)) {
-		cmd->reply = "BTS is not IP based";
-		return CTRL_CMD_ERROR;
-	}
-
-	ipaccess_drop_oml(bts);
-	cmd->reply = "Tried to drop the BTS";
-	return CTRL_CMD_REPLY;
-}
-
-CTRL_CMD_DEFINE_WO_NOVRF(bts_apply_config, "apply-configuration");
-
-static int set_bts_si(struct ctrl_cmd *cmd, void *data)
-{
-	struct gsm_bts *bts = cmd->node;
-	int rc;
-
-	rc = gsm_bts_set_system_infos(bts);
-	if (rc != 0) {
-		cmd->reply = "Failed to generate SI";
-		return CTRL_CMD_ERROR;
-	}
-
-	cmd->reply = "Generated new System Information";
-	return CTRL_CMD_REPLY;
-}
-CTRL_CMD_DEFINE_WO_NOVRF(bts_si, "send-new-system-informations");
-
-static int get_bts_chan_load(struct ctrl_cmd *cmd, void *data)
-{
-	int i;
-	struct pchan_load pl;
-	struct gsm_bts *bts;
-	const char *space = "";
-
-	bts = cmd->node;
-	memset(&pl, 0, sizeof(pl));
-	bts_chan_load(&pl, bts);
-
-	cmd->reply = talloc_strdup(cmd, "");
-
-	for (i = 0; i < ARRAY_SIZE(pl.pchan); ++i) {
-		const struct load_counter *lc = &pl.pchan[i];
-
-		/* These can never have user load */
-		if (i == GSM_PCHAN_NONE)
-			continue;
-		if (i == GSM_PCHAN_CCCH)
-			continue;
-		if (i == GSM_PCHAN_PDCH)
-			continue;
-		if (i == GSM_PCHAN_UNKNOWN)
-			continue;
-
-		cmd->reply = talloc_asprintf_append(cmd->reply,
-					"%s%s,%u,%u",
-					space, gsm_pchan_name(i), lc->used, lc->total);
-		if (!cmd->reply)
-			goto error;
-		space = " ";
-	}
-
-	return CTRL_CMD_REPLY;
-
-error:
-	cmd->reply = "Memory allocation failure";
-	return CTRL_CMD_ERROR;
-}
-
-CTRL_CMD_DEFINE_RO(bts_chan_load, "channel-load");
-
-static int get_bts_oml_conn(struct ctrl_cmd *cmd, void *data)
-{
-	struct gsm_bts *bts = cmd->node;
-
-	cmd->reply = bts->oml_link ? "connected" : "disconnected";
-	return CTRL_CMD_REPLY;
-}
-
-CTRL_CMD_DEFINE_RO(bts_oml_conn, "oml-connection-state");
-
-static int verify_bts_gprs_mode(struct ctrl_cmd *cmd, const char *value, void *_data)
-{
-	int valid;
-	enum bts_gprs_mode mode;
-	struct gsm_bts *bts = cmd->node;
-
-	mode = bts_gprs_mode_parse(value, &valid);
-	if (!valid) {
-		cmd->reply = "Mode is not known";
-		return 1;
-	}
-
-	if (!bts_gprs_mode_is_compat(bts, mode)) {
-		cmd->reply = "bts does not support this mode";
-		return 1;
-	}
-
-	return 0;
-}
-
-static int get_bts_gprs_mode(struct ctrl_cmd *cmd, void *data)
-{
-	struct gsm_bts *bts = cmd->node;
-
-	cmd->reply = talloc_strdup(cmd, bts_gprs_mode_name(bts->gprs.mode));
-	return CTRL_CMD_REPLY;
-}
-
-static int set_bts_gprs_mode(struct ctrl_cmd *cmd, void *data)
-{
-	struct gsm_bts *bts = cmd->node;
-
-	bts->gprs.mode = bts_gprs_mode_parse(cmd->value, NULL);
-	return get_bts_gprs_mode(cmd, data);
-}
-
-CTRL_CMD_DEFINE(bts_gprs_mode, "gprs-mode");
-
-static int get_bts_rf_state(struct ctrl_cmd *cmd, void *data)
-{
-	const char *oper, *admin, *policy;
-	struct gsm_bts *bts = cmd->node;
-
-	if (!bts) {
-		cmd->reply = "bts not found.";
-		return CTRL_CMD_ERROR;
-	}
-
-	oper = osmo_bsc_rf_get_opstate_name(osmo_bsc_rf_get_opstate_by_bts(bts));
-	admin = osmo_bsc_rf_get_adminstate_name(osmo_bsc_rf_get_adminstate_by_bts(bts));
-	policy = osmo_bsc_rf_get_policy_name(osmo_bsc_rf_get_policy_by_bts(bts));
-
-	cmd->reply = talloc_asprintf(cmd, "%s,%s,%s", oper, admin, policy);
-	if (!cmd->reply) {
-		cmd->reply = "OOM.";
-		return CTRL_CMD_ERROR;
-	}
-
-	return CTRL_CMD_REPLY;
-}
-CTRL_CMD_DEFINE_RO(bts_rf_state, "rf_state");
-
-static int get_net_rf_lock(struct ctrl_cmd *cmd, void *data)
-{
-	struct gsm_network *net = cmd->node;
-	struct gsm_bts *bts;
-	const char *policy_name;
-
-	policy_name = osmo_bsc_rf_get_policy_name(net->bsc_data->rf_ctrl->policy);
-
-	llist_for_each_entry(bts, &net->bts_list, list) {
-		struct gsm_bts_trx *trx;
-
-		/* Exclude the BTS from the global lock */
-		if (bts->excl_from_rf_lock)
-			continue;
-
-		llist_for_each_entry(trx, &bts->trx_list, list) {
-			if (trx->mo.nm_state.availability == NM_AVSTATE_OK &&
-			    trx->mo.nm_state.operational != NM_OPSTATE_DISABLED) {
-				cmd->reply = talloc_asprintf(cmd,
-						"state=on,policy=%s,bts=%u,trx=%u",
-						policy_name, bts->nr, trx->nr);
-				return CTRL_CMD_REPLY;
-			}
-		}
-	}
-
-	cmd->reply = talloc_asprintf(cmd, "state=off,policy=%s",
-			policy_name);
-	return CTRL_CMD_REPLY;
-}
-
-#define TIME_FORMAT_RFC2822 "%a, %d %b %Y %T %z"
-
-static int set_net_rf_lock(struct ctrl_cmd *cmd, void *data)
-{
-	int locked = atoi(cmd->value);
-	struct gsm_network *net = cmd->node;
-	time_t now = time(NULL);
-	char now_buf[64];
-	struct osmo_bsc_rf *rf;
-
-	if (!net) {
-		cmd->reply = "net not found.";
-		return CTRL_CMD_ERROR;
-	}
-
-	rf = net->bsc_data->rf_ctrl;
-
-	if (!rf) {
-		cmd->reply = "RF Ctrl is not enabled in the BSC Configuration";
-		return CTRL_CMD_ERROR;
-	}
-
-	talloc_free(rf->last_rf_lock_ctrl_command);
-	strftime(now_buf, sizeof(now_buf), TIME_FORMAT_RFC2822, gmtime(&now));
-	rf->last_rf_lock_ctrl_command =
-		talloc_asprintf(rf, "rf_locked %u (%s)", locked, now_buf);
-
-	osmo_bsc_rf_schedule_lock(rf, locked == 1 ? '0' : '1');
-
-	cmd->reply = talloc_asprintf(cmd, "%u", locked);
-	if (!cmd->reply) {
-		cmd->reply = "OOM.";
-		return CTRL_CMD_ERROR;
-	}
-
-	return CTRL_CMD_REPLY;
-}
-
-static int verify_net_rf_lock(struct ctrl_cmd *cmd, const char *value, void *data)
-{
-	int locked = atoi(cmd->value);
-
-	if ((locked != 0) && (locked != 1))
-		return 1;
-
-	return 0;
-}
-CTRL_CMD_DEFINE(net_rf_lock, "rf_locked");
-
-static int get_net_bts_num(struct ctrl_cmd *cmd, void *data)
-{
-	struct gsm_network *net = cmd->node;
-
-	cmd->reply = talloc_asprintf(cmd, "%u", net->num_bts);
-	return CTRL_CMD_REPLY;
-}
-CTRL_CMD_DEFINE_RO(net_bts_num, "number-of-bts");
-
-/* TRX related commands below here */
-CTRL_HELPER_GET_INT(trx_max_power, struct gsm_bts_trx, max_power_red);
-static int verify_trx_max_power(struct ctrl_cmd *cmd, const char *value, void *_data)
-{
-	int tmp = atoi(value);
-
-	if (tmp < 0 || tmp > 22) {
-		cmd->reply = "Value must be between 0 and 22";
-		return -1;
-	}
-
-	if (tmp & 1) {
-		cmd->reply = "Value must be even";
-		return -1;
-	}
-
-	return 0;
-}
-CTRL_CMD_DEFINE_RANGE(trx_arfcn, "arfcn", struct gsm_bts_trx, arfcn, 0, 1023);
-
-static int set_trx_max_power(struct ctrl_cmd *cmd, void *_data)
-{
-	struct gsm_bts_trx *trx = cmd->node;
-	int old_power;
-
-	/* remember the old value, set the new one */
-	old_power = trx->max_power_red;
-	trx->max_power_red = atoi(cmd->value);
-
-	/* Maybe update the value */
-	if (old_power != trx->max_power_red) {
-		LOGP(DCTRL, LOGL_NOTICE,
-			"%s updating max_pwr_red(%d)\n",
-			gsm_trx_name(trx), trx->max_power_red);
-		abis_nm_update_max_power_red(trx);
-	}
-
-	return get_trx_max_power(cmd, _data);
-}
-CTRL_CMD_DEFINE(trx_max_power, "max-power-reduction");
-
-int bsc_base_ctrl_cmds_install(void)
-{
-	int rc = 0;
-	rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_mnc);
-	rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_mcc);
-	rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_short_name);
-	rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_long_name);
-	rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_apply_config);
-	rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_mcc_mnc_apply);
-	rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_rf_lock);
-	rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_bts_num);
-
-	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_lac);
-	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_ci);
-	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_apply_config);
-	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_si);
-	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_chan_load);
-	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_oml_conn);
-	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_gprs_mode);
-	rc |= ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_rf_state);
-
-	rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_max_power);
-	rc |= ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_arfcn);
-
-	return rc;
-}
diff --git a/src/libbsc/bsc_ctrl_lookup.c b/src/libbsc/bsc_ctrl_lookup.c
deleted file mode 100644
index a8a8cf5..0000000
--- a/src/libbsc/bsc_ctrl_lookup.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/* SNMP-like status interface. Look-up of BTS/TRX
- *
- * (C) 2010-2011 by Daniel Willmann <daniel@totalueberwachung.de>
- * (C) 2010-2011 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 General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * 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.
- *
- */
-
-#include <errno.h>
-
-#include <osmocom/vty/command.h>
-#include <osmocom/ctrl/control_if.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-
-extern vector ctrl_node_vec;
-
-/*! \brief control interface lookup function for bsc/bts gsm_data
- * \param[in] data Private data passed to controlif_setup()
- * \param[in] vline Vector of the line holding the command string
- * \param[out] node_type type (CTRL_NODE_) that was determined
- * \param[out] node_data private dta of node that was determined
- * \param i Current index into vline, up to which it is parsed
- */
-static int bsc_ctrl_node_lookup(void *data, vector vline, int *node_type,
-				void **node_data, int *i)
-{
-	struct gsm_network *net = data;
-	struct gsm_bts *bts = NULL;
-	struct gsm_bts_trx *trx = NULL;
-	struct gsm_bts_trx_ts *ts = NULL;
-	char *token = vector_slot(vline, *i);
-	long num;
-
-	/* TODO: We need to make sure that the following chars are digits
-	 * and/or use strtol to check if number conversion was successful
-	 * Right now something like net.bts_stats will not work */
-	if (!strcmp(token, "bts")) {
-		if (*node_type != CTRL_NODE_ROOT || !net)
-			goto err_missing;
-		(*i)++;
-		if (!ctrl_parse_get_num(vline, *i, &num))
-			goto err_index;
-
-		bts = gsm_bts_num(net, num);
-		if (!bts)
-			goto err_missing;
-		*node_data = bts;
-		*node_type = CTRL_NODE_BTS;
-	} else if (!strcmp(token, "trx")) {
-		if (*node_type != CTRL_NODE_BTS || !*node_data)
-			goto err_missing;
-		bts = *node_data;
-		(*i)++;
-		if (!ctrl_parse_get_num(vline, *i, &num))
-			goto err_index;
-
-		trx = gsm_bts_trx_num(bts, num);
-		if (!trx)
-			goto err_missing;
-		*node_data = trx;
-		*node_type = CTRL_NODE_TRX;
-	} else if (!strcmp(token, "ts")) {
-		if (*node_type != CTRL_NODE_TRX || !*node_data)
-			goto err_missing;
-		trx = *node_data;
-		(*i)++;
-		if (!ctrl_parse_get_num(vline, *i, &num))
-			goto err_index;
-
-		if ((num >= 0) && (num < TRX_NR_TS))
-			ts = &trx->ts[num];
-		if (!ts)
-			goto err_missing;
-		*node_data = ts;
-		*node_type = CTRL_NODE_TS;
-	} else
-		return 0;
-
-	return 1;
-err_missing:
-	return -ENODEV;
-err_index:
-	return -ERANGE;
-}
-
-struct ctrl_handle *bsc_controlif_setup(struct gsm_network *net,
-					const char *bind_addr, uint16_t port)
-{
-	return ctrl_interface_setup_dynip(net, bind_addr, port,
-					  bsc_ctrl_node_lookup);
-}
diff --git a/src/libbsc/bsc_dyn_ts.c b/src/libbsc/bsc_dyn_ts.c
deleted file mode 100644
index e5422fc..0000000
--- a/src/libbsc/bsc_dyn_ts.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Dynamic PDCH initialisation implementation shared across NM and RSL */
-
-/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- * 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/>.
- *
- */
-
-#include <osmocom/core/logging.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/abis_rsl.h>
-
-void tchf_pdch_ts_init(struct gsm_bts_trx_ts *ts)
-{
-	int rc;
-
-	if (ts->trx->bts->gprs.mode == BTS_GPRS_NONE) {
-		LOGP(DRSL, LOGL_NOTICE, "%s: GPRS mode is 'none':"
-		     " not activating PDCH.\n",
-		     gsm_ts_and_pchan_name(ts));
-		return;
-	}
-
-	LOGP(DRSL, LOGL_DEBUG, "%s: trying to PDCH ACT\n",
-	     gsm_ts_and_pchan_name(ts));
-
-	rc = rsl_ipacc_pdch_activate(ts, 1);
-	if (rc != 0)
-		LOGP(DRSL, LOGL_ERROR, "%s %s: PDCH ACT failed\n",
-		     gsm_ts_name(ts), gsm_pchan_name(ts->pchan));
-}
-
-void tchf_tchh_pdch_ts_init(struct gsm_bts_trx_ts *ts)
-{
-	if (ts->trx->bts->gprs.mode == BTS_GPRS_NONE) {
-		LOGP(DRSL, LOGL_NOTICE, "%s: GPRS mode is 'none':"
-		     " not activating PDCH.\n",
-		     gsm_ts_and_pchan_name(ts));
-		return;
-	}
-
-	dyn_ts_switchover_start(ts, GSM_PCHAN_PDCH);
-}
-
-void dyn_ts_init(struct gsm_bts_trx_ts *ts)
-{
-	/* Clear all TCH/F_PDCH flags */
-	ts->flags &= ~(TS_F_PDCH_PENDING_MASK | TS_F_PDCH_ACTIVE);
-
-	/* Clear TCH/F_TCH/H_PDCH state */
-	ts->dyn.pchan_is = ts->dyn.pchan_want = GSM_PCHAN_NONE;
-	ts->dyn.pending_chan_activ = NULL;
-
-	switch (ts->pchan) {
-	case GSM_PCHAN_TCH_F_PDCH:
-		tchf_pdch_ts_init(ts);
-		break;
-	case GSM_PCHAN_TCH_F_TCH_H_PDCH:
-		tchf_tchh_pdch_ts_init(ts);
-		break;
-	default:
-		break;
-	}
-}
diff --git a/src/libbsc/bsc_init.c b/src/libbsc/bsc_init.c
deleted file mode 100644
index 78ca2ab..0000000
--- a/src/libbsc/bsc_init.c
+++ /dev/null
@@ -1,567 +0,0 @@
-/* A hackish minimal BSC (+MSC +HLR) implementation */
-
-/* (C) 2008-2010 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/>.
- *
- */
-
-#include <openbsc/gsm_data.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/debug.h>
-#include <openbsc/misdn.h>
-#include <osmocom/vty/telnet_interface.h>
-#include <osmocom/vty/ports.h>
-#include <openbsc/system_information.h>
-#include <openbsc/paging.h>
-#include <openbsc/signal.h>
-#include <openbsc/chan_alloc.h>
-#include <osmocom/core/talloc.h>
-#include <openbsc/ipaccess.h>
-#include <osmocom/gsm/sysinfo.h>
-#include <openbsc/e1_config.h>
-#include <openbsc/common_bsc.h>
-#include <openbsc/pcu_if.h>
-#include <openbsc/osmo_msc.h>
-#include <limits.h>
-
-/* global pointer to the gsm network data structure */
-extern struct gsm_network *bsc_gsmnet;
-
-/* Callback function for NACK on the OML NM */
-static int oml_msg_nack(struct nm_nack_signal_data *nack)
-{
-	if (nack->mt == NM_MT_GET_ATTR_NACK) {
-		LOGP(DNM, LOGL_ERROR, "BTS%u does not support Get Attributes "
-		     "OML message.\n", nack->bts->nr);
-		return 0;
-	}
-
-	if (nack->mt == NM_MT_SET_BTS_ATTR_NACK)
-		LOGP(DNM, LOGL_ERROR, "Failed to set BTS attributes. That is fatal. "
-		     "Was the bts type and frequency properly specified?\n");
-	else
-		LOGP(DNM, LOGL_ERROR, "Got %s NACK going to drop the OML links.\n",
-		     abis_nm_nack_name(nack->mt));
-
-	if (!nack->bts) {
-		LOGP(DNM, LOGL_ERROR, "Unknown bts. Can not drop it.\n");
-		return 0;
-	}
-
-	if (is_ipaccess_bts(nack->bts))
-		ipaccess_drop_oml(nack->bts);
-
-	return 0;
-}
-
-/* Callback function to be called every time we receive a signal from NM */
-static int nm_sig_cb(unsigned int subsys, unsigned int signal,
-		     void *handler_data, void *signal_data)
-{
-	struct nm_nack_signal_data *nack;
-
-	switch (signal) {
-	case S_NM_NACK:
-		nack = signal_data;
-		return oml_msg_nack(nack);
-	default:
-		break;
-	}
-	return 0;
-}
-
-int bsc_shutdown_net(struct gsm_network *net)
-{
-	struct gsm_bts *bts;
-
-	llist_for_each_entry(bts, &net->bts_list, list) {
-		LOGP(DNM, LOGL_NOTICE, "shutting down OML for BTS %u\n", bts->nr);
-		osmo_signal_dispatch(SS_L_GLOBAL, S_GLOBAL_BTS_CLOSE_OM, bts);
-	}
-
-	return 0;
-}
-
-static int rsl_si(struct gsm_bts_trx *trx, enum osmo_sysinfo_type i, int si_len)
-{
-	struct gsm_bts *bts = trx->bts;
-	int rc, j;
-
-	if (si_len) {
-		DEBUGP(DRR, "SI%s: %s\n", get_value_string(osmo_sitype_strs, i),
-			osmo_hexdump(GSM_BTS_SI(bts, i), GSM_MACBLOCK_LEN));
-	} else
-		DEBUGP(DRR, "SI%s: OFF\n", get_value_string(osmo_sitype_strs, i));
-
-	switch (i) {
-	case SYSINFO_TYPE_5:
-	case SYSINFO_TYPE_5bis:
-	case SYSINFO_TYPE_5ter:
-	case SYSINFO_TYPE_6:
-		rc = rsl_sacch_filling(trx, osmo_sitype2rsl(i),
-				       si_len ? GSM_BTS_SI(bts, i) : NULL, si_len);
-		break;
-	case SYSINFO_TYPE_2quater:
-		if (si_len == 0) {
-			rc = rsl_bcch_info(trx, i, NULL, 0);
-			break;
-		}
-		for (j = 0; j <= bts->si2q_count; j++)
-			rc = rsl_bcch_info(trx, i, (const uint8_t *)GSM_BTS_SI2Q(bts, j), GSM_MACBLOCK_LEN);
-		break;
-	default:
-		rc = rsl_bcch_info(trx, i, si_len ? GSM_BTS_SI(bts, i) : NULL, si_len);
-		break;
-	}
-
-	return rc;
-}
-
-/* set all system information types for a TRX */
-int gsm_bts_trx_set_system_infos(struct gsm_bts_trx *trx)
-{
-	int i, rc;
-	struct gsm_bts *bts = trx->bts;
-	uint8_t gen_si[_MAX_SYSINFO_TYPE], n_si = 0, n;
-	int si_len[_MAX_SYSINFO_TYPE];
-
-	bts->si_common.cell_sel_par.ms_txpwr_max_ccch =
-			ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
-	bts->si_common.cell_sel_par.neci = bts->network->neci;
-
-	/* Zero/forget the state of the dynamically computed SIs, leeping the static ones */
-	bts->si_valid = bts->si_mode_static;
-
-	/* First, we determine which of the SI messages we actually need */
-
-	if (trx == bts->c0) {
-		/* 1...4 are always present on a C0 TRX */
-		gen_si[n_si++] = SYSINFO_TYPE_1;
-		gen_si[n_si++] = SYSINFO_TYPE_2;
-		gen_si[n_si++] = SYSINFO_TYPE_2bis;
-		gen_si[n_si++] = SYSINFO_TYPE_2ter;
-		gen_si[n_si++] = SYSINFO_TYPE_2quater;
-		gen_si[n_si++] = SYSINFO_TYPE_3;
-		gen_si[n_si++] = SYSINFO_TYPE_4;
-
-		/* 13 is always present on a C0 TRX of a GPRS BTS */
-		if (bts->gprs.mode != BTS_GPRS_NONE)
-			gen_si[n_si++] = SYSINFO_TYPE_13;
-	}
-
-	/* 5 and 6 are always present on every TRX */
-	gen_si[n_si++] = SYSINFO_TYPE_5;
-	gen_si[n_si++] = SYSINFO_TYPE_5bis;
-	gen_si[n_si++] = SYSINFO_TYPE_5ter;
-	gen_si[n_si++] = SYSINFO_TYPE_6;
-
-	/* Second, we generate the selected SI via RSL */
-
-	for (n = 0; n < n_si; n++) {
-		i = gen_si[n];
-		/* Only generate SI if this SI is not in "static" (user-defined) mode */
-		if (!(bts->si_mode_static & (1 << i))) {
-			/* Set SI as being valid. gsm_generate_si() might unset
-			 * it, if SI is not required. */
-			bts->si_valid |= (1 << i);
-			rc = gsm_generate_si(bts, i);
-			if (rc < 0)
-				goto err_out;
-			si_len[i] = rc;
-		} else {
-			if (i == SYSINFO_TYPE_5 || i == SYSINFO_TYPE_5bis
-			 || i == SYSINFO_TYPE_5ter)
-				si_len[i] = 18;
-			else if (i == SYSINFO_TYPE_6)
-				si_len[i] = 11;
-			else
-				si_len[i] = 23;
-		}
-	}
-
-	/* Third, we send the selected SI via RSL */
-
-	for (n = 0; n < n_si; n++) {
-		i = gen_si[n];
-		/* if we don't currently have this SI, we send a zero-length
-		 * RSL BCCH FILLING / SACCH FILLING * in order to deactivate
-		 * the SI, in case it might have previously been active */
-		if (!GSM_BTS_HAS_SI(bts, i))
-			rc = rsl_si(trx, i, 0);
-		else
-			rc = rsl_si(trx, i, si_len[i]);
-		if (rc < 0)
-			return rc;
-	}
-
-	/* Make sure the PCU is aware (in case anything GPRS related has
-	 * changed in SI */
-	pcu_info_update(bts);
-
-	return 0;
-err_out:
-	LOGP(DRR, LOGL_ERROR, "Cannot generate SI%s for BTS %u: error <%s>, "
-	     "most likely a problem with neighbor cell list generation\n",
-	     get_value_string(osmo_sitype_strs, i), bts->nr, strerror(-rc));
-	return rc;
-}
-
-/* set all system information types for a BTS */
-int gsm_bts_set_system_infos(struct gsm_bts *bts)
-{
-	struct gsm_bts_trx *trx;
-
-	/* Generate a new ID */
-	bts->bcch_change_mark += 1;
-	bts->bcch_change_mark %= 0x7;
-
-	llist_for_each_entry(trx, &bts->trx_list, list) {
-		int rc;
-
-		rc = gsm_bts_trx_set_system_infos(trx);
-		if (rc != 0)
-			return rc;
-	}
-
-	return 0;
-}
-
-/* Produce a MA as specified in 10.5.2.21 */
-static int generate_ma_for_ts(struct gsm_bts_trx_ts *ts)
-{
-	/* we have three bitvecs: the per-timeslot ARFCNs, the cell chan ARFCNs
-	 * and the MA */
-	struct bitvec *cell_chan = &ts->trx->bts->si_common.cell_alloc;
-	struct bitvec *ts_arfcn = &ts->hopping.arfcns;
-	struct bitvec *ma = &ts->hopping.ma;
-	unsigned int num_cell_arfcns, bitnum, n_chan;
-	int i;
-
-	/* re-set the MA to all-zero */
-	ma->cur_bit = 0;
-	ts->hopping.ma_len = 0;
-	memset(ma->data, 0, ma->data_len);
-
-	if (!ts->hopping.enabled)
-		return 0;
-
-	/* count the number of ARFCNs in the cell channel allocation */
-	num_cell_arfcns = 0;
-	for (i = 0; i < 1024; i++) {
-		if (bitvec_get_bit_pos(cell_chan, i))
-			num_cell_arfcns++;
-	}
-
-	/* pad it to octet-aligned number of bits */
-	ts->hopping.ma_len = num_cell_arfcns / 8;
-	if (num_cell_arfcns % 8)
-		ts->hopping.ma_len++;
-
-	n_chan = 0;
-	for (i = 0; i < 1024; i++) {
-		if (!bitvec_get_bit_pos(cell_chan, i))
-			continue;
-		/* set the corresponding bit in the MA */
-		bitnum = (ts->hopping.ma_len * 8) - 1 - n_chan;
-		if (bitvec_get_bit_pos(ts_arfcn, i))
-			bitvec_set_bit_pos(ma, bitnum, 1);
-		else
-			bitvec_set_bit_pos(ma, bitnum, 0);
-		n_chan++;
-	}
-
-	/* ARFCN 0 is special: It is coded last in the bitmask */
-	if (bitvec_get_bit_pos(cell_chan, 0)) {
-		n_chan++;
-		/* set the corresponding bit in the MA */
-		bitnum = (ts->hopping.ma_len * 8) - 1 - n_chan;
-		if (bitvec_get_bit_pos(ts_arfcn, 0))
-			bitvec_set_bit_pos(ma, bitnum, 1);
-		else
-			bitvec_set_bit_pos(ma, bitnum, 0);
-	}
-
-	return 0;
-}
-
-static void bootstrap_rsl(struct gsm_bts_trx *trx)
-{
-	unsigned int i;
-
-	LOGP(DRSL, LOGL_NOTICE, "bootstrapping RSL for BTS/TRX (%u/%u) "
-		"on ARFCN %u using MCC=%u MNC=%u LAC=%u CID=%u BSIC=%u\n",
-		trx->bts->nr, trx->nr, trx->arfcn, bsc_gsmnet->country_code,
-		bsc_gsmnet->network_code, trx->bts->location_area_code,
-		trx->bts->cell_identity, trx->bts->bsic);
-
-	if (trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE) {
-		rsl_nokia_si_begin(trx);
-	}
-
-	gsm_bts_trx_set_system_infos(trx);
-
-	if (trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE) {
-		/* channel unspecific, power reduction in 2 dB steps */
-		rsl_bs_power_control(trx, 0xFF, trx->max_power_red / 2);
-		rsl_nokia_si_end(trx);
-	}
-
-	for (i = 0; i < ARRAY_SIZE(trx->ts); i++)
-		generate_ma_for_ts(&trx->ts[i]);
-}
-
-/* Callback function to be called every time we receive a signal from INPUT */
-static int inp_sig_cb(unsigned int subsys, unsigned int signal,
-		      void *handler_data, void *signal_data)
-{
-	struct input_signal_data *isd = signal_data;
-	struct gsm_bts_trx *trx = isd->trx;
-	int ts_no, lchan_no;
-	/* N. B: we rely on attribute order when parsing response in abis_nm_rx_get_attr_resp() */
-	const uint8_t bts_attr[] = { NM_ATT_MANUF_ID, NM_ATT_SW_CONFIG, };
-	const uint8_t trx_attr[] = { NM_ATT_MANUF_STATE, NM_ATT_SW_CONFIG, };
-
-	/* we should not request more attributes than we're ready to handle */
-	OSMO_ASSERT(sizeof(bts_attr) < MAX_BTS_ATTR);
-	OSMO_ASSERT(sizeof(trx_attr) < MAX_BTS_ATTR);
-
-	if (subsys != SS_L_INPUT)
-		return -EINVAL;
-
-	LOGP(DLMI, LOGL_DEBUG, "%s(): Input signal '%s' received\n", __func__,
-		get_value_string(e1inp_signal_names, signal));
-	switch (signal) {
-	case S_L_INP_TEI_UP:
-		if (isd->link_type == E1INP_SIGN_OML) {
-			/* TODO: this is required for the Nokia BTS, hopping is configured
-			   during OML, other MA is not set.  */
-			struct gsm_bts_trx *cur_trx;
-			/* was static in system_information.c */
-			extern int generate_cell_chan_list(uint8_t *chan_list, struct gsm_bts *bts);
-			uint8_t ca[20];
-			/* has to be called before generate_ma_for_ts to
-			  set bts->si_common.cell_alloc */
-			generate_cell_chan_list(ca, trx->bts);
-
-			/* Request generic BTS-level attributes */
-			abis_nm_get_attr(trx->bts, NM_OC_BTS, 0xFF, 0xFF, 0xFF, bts_attr, sizeof(bts_attr));
-
-			llist_for_each_entry(cur_trx, &trx->bts->trx_list, list) {
-				int i;
-				/* Request TRX-level attributes */
-				abis_nm_get_attr(cur_trx->bts, NM_OC_BASEB_TRANSC, 0, cur_trx->nr, 0xFF,
-						 trx_attr, sizeof(trx_attr));
-				for (i = 0; i < ARRAY_SIZE(cur_trx->ts); i++)
-					generate_ma_for_ts(&cur_trx->ts[i]);
-			}
-		}
-		if (isd->link_type == E1INP_SIGN_RSL)
-			bootstrap_rsl(trx);
-		break;
-	case S_L_INP_TEI_DN:
-		LOGP(DLMI, LOGL_ERROR, "Lost some E1 TEI link: %d %p\n", isd->link_type, trx);
-
-		if (isd->link_type == E1INP_SIGN_OML)
-			rate_ctr_inc(&trx->bts->network->bsc_ctrs->ctr[BSC_CTR_BTS_OML_FAIL]);
-		else if (isd->link_type == E1INP_SIGN_RSL)
-			rate_ctr_inc(&trx->bts->network->bsc_ctrs->ctr[BSC_CTR_BTS_RSL_FAIL]);
-
-		/*
-		 * free all allocated channels. change the nm_state so the
-		 * trx and trx_ts becomes unusable and chan_alloc.c can not
-		 * allocate from it.
-		 */
-		for (ts_no = 0; ts_no < ARRAY_SIZE(trx->ts); ++ts_no) {
-			struct gsm_bts_trx_ts *ts = &trx->ts[ts_no];
-
-			for (lchan_no = 0; lchan_no < ARRAY_SIZE(ts->lchan); ++lchan_no) {
-				if (ts->lchan[lchan_no].state != LCHAN_S_NONE)
-					lchan_free(&ts->lchan[lchan_no]);
-				lchan_reset(&ts->lchan[lchan_no]);
-			}
-		}
-
-		gsm_bts_mo_reset(trx->bts);
-
-		abis_nm_clear_queue(trx->bts);
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int bootstrap_bts(struct gsm_bts *bts)
-{
-	int i, n;
-
-	if (!bts->model)
-		return -EFAULT;
-
-	if (bts->model->start && !bts->model->started) {
-		int ret = bts->model->start(bts->network);
-		if (ret < 0)
-			return ret;
-
-		bts->model->started = true;
-	}
-
-	/* FIXME: What about secondary TRX of a BTS?  What about a BTS that has TRX
-	 * in different bands? Why is 'band' a parameter of the BTS and not of the TRX? */
-	switch (bts->band) {
-	case GSM_BAND_1800:
-		if (bts->c0->arfcn < 512 || bts->c0->arfcn > 885) {
-			LOGP(DNM, LOGL_ERROR, "GSM1800 channel must be between 512-885.\n");
-			return -EINVAL;
-		}
-		break;
-	case GSM_BAND_1900:
-		if (bts->c0->arfcn < 512 || bts->c0->arfcn > 810) {
-			LOGP(DNM, LOGL_ERROR, "GSM1900 channel must be between 512-810.\n");
-			return -EINVAL;
-		}
-		break;
-	case GSM_BAND_900:
-		if ((bts->c0->arfcn > 124 && bts->c0->arfcn < 955) ||
-		    bts->c0->arfcn > 1023)  {
-			LOGP(DNM, LOGL_ERROR, "GSM900 channel must be between 0-124, 955-1023.\n");
-			return -EINVAL;
-		}
-		break;
-	case GSM_BAND_850:
-		if (bts->c0->arfcn < 128 || bts->c0->arfcn > 251) {
-			LOGP(DNM, LOGL_ERROR, "GSM850 channel must be between 128-251.\n");
-			return -EINVAL;
-		}
-		break;
-	default:
-		LOGP(DNM, LOGL_ERROR, "Unsupported frequency band.\n");
-		return -EINVAL;
-	}
-
-	if (bts->network->auth_policy == GSM_AUTH_POLICY_ACCEPT_ALL &&
-	    !bts->si_common.rach_control.cell_bar)
-		LOGP(DNM, LOGL_ERROR, "\nWARNING: You are running an 'accept-all' "
-			"network on a BTS that is not barred.  This "
-			"configuration is likely to interfere with production "
-			"GSM networks and should only be used in a RF "
-			"shielded environment such as a faraday cage!\n\n");
-
-	/* Control Channel Description is set from vty/config */
-
-	/* T3212 is set from vty/config */
-
-	/* Set ccch config by looking at ts config */
-	for (n=0, i=0; i<8; i++)
-		n += bts->c0->ts[i].pchan == GSM_PCHAN_CCCH ? 1 : 0;
-
-	/* Indicate R99 MSC in SI3 */
-	bts->si_common.chan_desc.mscr = 1;
-
-	switch (n) {
-	case 0:
-		bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_1_C;
-		/* Limit reserved block to 2 on combined channel according to
-		   3GPP TS 44.018 Table 10.5.2.11.1 */
-		if (bts->si_common.chan_desc.bs_ag_blks_res > 2) {
-			LOGP(DNM, LOGL_NOTICE, "CCCH is combined with SDCCHs, "
-			     "reducing BS-AG-BLKS-RES value %d -> 2\n",
-			     bts->si_common.chan_desc.bs_ag_blks_res);
-			bts->si_common.chan_desc.bs_ag_blks_res = 2;
-		}
-		break;
-	case 1:
-		bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_1_NC;
-		break;
-	case 2:
-		bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_2_NC;
-		break;
-	case 3:
-		bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_3_NC;
-		break;
-	case 4:
-		bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_4_NC;
-		break;
-	default:
-		LOGP(DNM, LOGL_ERROR, "Unsupported CCCH timeslot configuration\n");
-		return -EINVAL;
-	}
-
-	bts->si_common.cell_options.pwrc = 0; /* PWRC not set */
-
-	bts->si_common.cell_sel_par.acs = 0;
-
-	bts->si_common.ncc_permitted = 0xff;
-
-	/* Initialize the BTS state */
-	gsm_bts_mo_reset(bts);
-
-	return 0;
-}
-
-int bsc_network_alloc(mncc_recv_cb_t mncc_recv)
-{
-	/* initialize our data structures */
-	bsc_gsmnet = bsc_network_init(tall_bsc_ctx, 1, 1, mncc_recv);
-	if (!bsc_gsmnet)
-		return -ENOMEM;
-
-	bsc_gsmnet->name_long = talloc_strdup(bsc_gsmnet, "OpenBSC");
-	bsc_gsmnet->name_short = talloc_strdup(bsc_gsmnet, "OpenBSC");
-
-	return 0;
-}
-
-int bsc_network_configure(const char *config_file)
-{
-	struct gsm_bts *bts;
-	int rc;
-
-	rc = vty_read_config_file(config_file, NULL);
-	if (rc < 0) {
-		LOGP(DNM, LOGL_FATAL, "Failed to parse the config file: '%s'\n", config_file);
-		return rc;
-	}
-
-	/* start telnet after reading config for vty_get_bind_addr() */
-	rc = telnet_init_dynif(tall_bsc_ctx, bsc_gsmnet, vty_get_bind_addr(),
-			       OSMO_VTY_PORT_NITB_BSC);
-	if (rc < 0)
-		return rc;
-
-	osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL);
-	osmo_signal_register_handler(SS_L_INPUT, inp_sig_cb, NULL);
-
-	llist_for_each_entry(bts, &bsc_gsmnet->bts_list, list) {
-		rc = bootstrap_bts(bts);
-		if (rc < 0) {
-			LOGP(DNM, LOGL_FATAL, "Error bootstrapping BTS\n");
-			return rc;
-		}
-		rc = e1_reconfig_bts(bts);
-		if (rc < 0) {
-			LOGP(DNM, LOGL_FATAL, "Error enabling E1 input driver\n");
-			return rc;
-		}
-	}
-
-	return 0;
-}
diff --git a/src/libbsc/bsc_msc.c b/src/libbsc/bsc_msc.c
deleted file mode 100644
index 82a572d..0000000
--- a/src/libbsc/bsc_msc.c
+++ /dev/null
@@ -1,320 +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/>.
- *
- */
-
-#include <openbsc/bsc_msc.h>
-#include <openbsc/debug.h>
-#include <osmocom/abis/ipaccess.h>
-
-#include <osmocom/core/write_queue.h>
-#include <osmocom/core/talloc.h>
-
-#include <osmocom/gsm/tlv.h>
-
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-static void connection_loss(struct bsc_msc_connection *con)
-{
-	struct osmo_fd *fd;
-
-	fd = &con->write_queue.bfd;
-
-	if (con->pending_msg) {
-		LOGP(DMSC, LOGL_ERROR,
-		     "MSC(%s) dropping incomplete message.\n", con->name);
-		msgb_free(con->pending_msg);
-		con->pending_msg = NULL;
-	}
-
-	close(fd->fd);
-	fd->fd = -1;
-	fd->cb = osmo_wqueue_bfd_cb;
-	fd->when = 0;
-
-	con->is_connected = 0;
-	con->first_contact = 0;
-	con->connection_loss(con);
-}
-
-static void msc_con_timeout(void *_con)
-{
-	struct bsc_msc_connection *con = _con;
-
-	LOGP(DMSC, LOGL_ERROR,
-		"MSC(%s) Connection timeout.\n", con->name);
-	bsc_msc_lost(con);
-}
-
-/* called in the case of a non blocking connect */
-static int msc_connection_connect(struct osmo_fd *fd, unsigned int what)
-{
-	int rc;
-	int val;
-	struct bsc_msc_connection *con;
-	struct osmo_wqueue *queue;
-
-	socklen_t len = sizeof(val);
-
-	queue = container_of(fd, struct osmo_wqueue, bfd);
-	con = container_of(queue, struct bsc_msc_connection, write_queue);
-
-	if ((what & BSC_FD_WRITE) == 0) {
-		LOGP(DMSC, LOGL_ERROR,
-			"MSC(%s) Callback but not writable.\n", con->name);
-		return -1;
-	}
-
-	/* From here on we will either be connected or reconnect */
-	osmo_timer_del(&con->timeout_timer);
-
-	/* check the socket state */
-	rc = getsockopt(fd->fd, SOL_SOCKET, SO_ERROR, &val, &len);
-	if (rc != 0) {
-		LOGP(DMSC, LOGL_ERROR,
-			"getsockopt for the MSC(%s) socket failed.\n", con->name);
-		goto error;
-	}
-	if (val != 0) {
-		LOGP(DMSC, LOGL_ERROR,
-			"Not connected to the MSC(%s): %d\n",
-			con->name, val);
-		goto error;
-	}
-
-
-	/* go to full operation */
-	fd->cb = osmo_wqueue_bfd_cb;
-	fd->when = BSC_FD_READ | BSC_FD_EXCEPT;
-
-	con->is_connected = 1;
-	LOGP(DMSC, LOGL_NOTICE,
-		"(Re)Connected to the MSC(%s).\n", con->name);
-	if (con->connected)
-		con->connected(con);
-	return 0;
-
-error:
-	osmo_fd_unregister(fd);
-	connection_loss(con);
-	return -1;
-}
-static void setnonblocking(struct osmo_fd *fd)
-{
-	int flags;
-
-	flags = fcntl(fd->fd, F_GETFL);
-	if (flags < 0) {
-		perror("fcntl get failed");
-		close(fd->fd);
-		fd->fd = -1;
-		return;
-	}
-
-	flags |= O_NONBLOCK;
-	flags = fcntl(fd->fd, F_SETFL, flags);
-	if (flags < 0) {
-		perror("fcntl get failed");
-		close(fd->fd);
-		fd->fd = -1;
-		return;
-	}
-}
-
-int bsc_msc_connect(struct bsc_msc_connection *con)
-{
-	struct bsc_msc_dest *dest;
-	struct osmo_fd *fd;
-	struct sockaddr_in sin;
-	int on = 1, ret;
-
-	if (llist_empty(con->dests)) {
-		LOGP(DMSC, LOGL_ERROR,
-			"No MSC(%s) connections configured.\n",
-			con->name);
-		connection_loss(con);
-		return -1;
-	}
-
-	/* TODO: Why are we not using the libosmocore soecket
-	 * abstraction, or libosmo-netif? */
-
-	/* move to the next connection */
-	dest = (struct bsc_msc_dest *) con->dests->next;
-	llist_del(&dest->list);
-	llist_add_tail(&dest->list, con->dests);
-
-	LOGP(DMSC, LOGL_NOTICE,
-		"Attempting to connect MSC(%s) at %s:%d\n",
-		con->name, dest->ip, dest->port);
-
-	con->is_connected = 0;
-
-	msgb_free(con->pending_msg);
-	con->pending_msg = NULL;
-
-	fd = &con->write_queue.bfd;
-	fd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-	fd->priv_nr = 1;
-
-	if (fd->fd < 0) {
-		perror("Creating TCP socket failed");
-		return fd->fd;
-	}
-
-	/* make it non blocking */
-	setnonblocking(fd);
-
-	/* set the socket priority */
-	ret = setsockopt(fd->fd, IPPROTO_IP, IP_TOS,
-			 &dest->dscp, sizeof(dest->dscp));
-	if (ret != 0)
-		LOGP(DMSC, LOGL_ERROR,
-			"Failed to set DSCP to %d on MSC(%s). %s\n",
-			dest->dscp, con->name, strerror(errno));
-
-	memset(&sin, 0, sizeof(sin));
-	sin.sin_family = AF_INET;
-	sin.sin_port = htons(dest->port);
-	inet_aton(dest->ip, &sin.sin_addr);
-
-	ret = setsockopt(fd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-	if (ret != 0)
-		LOGP(DMSC, LOGL_ERROR,
-		     "Failed to set SO_REUSEADDR socket option\n");
-	ret = connect(fd->fd, (struct sockaddr *) &sin, sizeof(sin));
-
-	if (ret == -1 && errno == EINPROGRESS) {
-		LOGP(DMSC, LOGL_ERROR,
-			"MSC(%s) Connection in progress\n", con->name);
-		fd->when = BSC_FD_WRITE;
-		fd->cb = msc_connection_connect;
-		osmo_timer_setup(&con->timeout_timer, msc_con_timeout, con);
-		osmo_timer_schedule(&con->timeout_timer, 20, 0);
-	} else if (ret < 0) {
-		perror("Connection failed");
-		connection_loss(con);
-		return ret;
-	} else {
-		fd->when = BSC_FD_READ | BSC_FD_EXCEPT;
-		fd->cb = osmo_wqueue_bfd_cb;
-		con->is_connected = 1;
-		if (con->connected)
-			con->connected(con);
-	}
-
-	ret = osmo_fd_register(fd);
-	if (ret < 0) {
-		perror("Registering the fd failed");
-		close(fd->fd);
-		return ret;
-	}
-
-	return ret;
-}
-
-struct bsc_msc_connection *bsc_msc_create(void *ctx, struct llist_head *dests)
-{
-	struct bsc_msc_connection *con;
-
-	con = talloc_zero(NULL, struct bsc_msc_connection);
-	if (!con) {
-		LOGP(DMSC, LOGL_FATAL, "Failed to create the MSC connection.\n");
-		return NULL;
-	}
-
-	con->dests = dests;
-	con->write_queue.bfd.fd = -1;
-	con->name = "";
-	osmo_wqueue_init(&con->write_queue, 100);
-	return con;
-}
-
-void bsc_msc_lost(struct bsc_msc_connection *con)
-{
-	osmo_wqueue_clear(&con->write_queue);
-	osmo_timer_del(&con->timeout_timer);
-	osmo_timer_del(&con->reconnect_timer);
-
-	if (con->write_queue.bfd.fd >= 0)
-		osmo_fd_unregister(&con->write_queue.bfd);
-	connection_loss(con);
-}
-
-static void reconnect_msc(void *_msc)
-{
-	struct bsc_msc_connection *con = _msc;
-
-	LOGP(DMSC, LOGL_NOTICE,
-		"Attempting to reconnect to the MSC(%s).\n", con->name);
-	bsc_msc_connect(con);
-}
-
-void bsc_msc_schedule_connect(struct bsc_msc_connection *con)
-{
-	LOGP(DMSC, LOGL_NOTICE,
-		"Attempting to reconnect to the MSC(%s)\n", con->name);
-	osmo_timer_setup(&con->reconnect_timer, reconnect_msc, con);
-	osmo_timer_schedule(&con->reconnect_timer, 5, 0);
-}
-
-struct msgb *bsc_msc_id_get_resp(int fixed, const char *token, const uint8_t *res, int len)
-{
-	struct msgb *msg;
-
-	if (!token) {
-		LOGP(DMSC, LOGL_ERROR, "No token specified.\n");
-		return NULL;
-	}
-
-	msg = msgb_alloc_headroom(4096, 128, "id resp");
-	if (!msg) {
-		LOGP(DMSC, LOGL_ERROR, "Failed to create the message.\n");
-		return NULL;
-	}
-
-	/*
-	 * The situation is bizarre. The encoding doesn't follow the
-	 * TLV structure. It is more like a LV and old versions had
-	 * it wrong but we want new versions to old servers so we
-	 * introduce the quirk here.
-	 */
-	msg->l2h = msgb_v_put(msg, IPAC_MSGT_ID_RESP);
-	if (fixed) {
-		msgb_put_u8(msg, 0);
-		msgb_put_u8(msg, strlen(token) + 2);
-		msgb_tv_fixed_put(msg, IPAC_IDTAG_UNITNAME, strlen(token) + 1, (uint8_t *) token);
-		if (len > 0) {
-			msgb_put_u8(msg, 0);
-			msgb_put_u8(msg, len + 1);
-			msgb_tv_fixed_put(msg, 0x24, len, res);
-		}
-	} else {
-		msgb_l16tv_put(msg, strlen(token) + 1,
-			IPAC_IDTAG_UNITNAME, (uint8_t *) token);
-	}
-
-	return msg;
-}
diff --git a/src/libbsc/bsc_rf_ctrl.c b/src/libbsc/bsc_rf_ctrl.c
deleted file mode 100644
index b7b6fc8..0000000
--- a/src/libbsc/bsc_rf_ctrl.c
+++ /dev/null
@@ -1,534 +0,0 @@
-/* RF Ctl handling socket */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2010-2014 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2014 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/>.
- *
- */
-
-#include <openbsc/osmo_bsc_rf.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/signal.h>
-#include <openbsc/bsc_msc_data.h>
-#include <openbsc/ipaccess.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/gsm/protocol/gsm_12_21.h>
-
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <errno.h>
-#include <unistd.h>
-
-#define RF_CMD_QUERY '?'
-#define RF_CMD_OFF   '0'
-#define RF_CMD_ON    '1'
-#define RF_CMD_D_OFF 'd'
-#define RF_CMD_ON_G  'g'
-
-static const struct value_string opstate_names[] = {
-	{ OSMO_BSC_RF_OPSTATE_INOPERATIONAL, "inoperational" },
-	{ OSMO_BSC_RF_OPSTATE_OPERATIONAL, "operational" },
-	{ 0, NULL }
-};
-
-static const struct value_string adminstate_names[] = {
-	{ OSMO_BSC_RF_ADMINSTATE_UNLOCKED, "unlocked" },
-	{ OSMO_BSC_RF_ADMINSTATE_LOCKED, "locked" },
-	{ 0, NULL }
-};
-
-static const struct value_string policy_names[] = {
-	{ OSMO_BSC_RF_POLICY_OFF, "off" },
-	{ OSMO_BSC_RF_POLICY_ON, "on" },
-	{ OSMO_BSC_RF_POLICY_GRACE, "grace" },
-	{ OSMO_BSC_RF_POLICY_UNKNOWN, "unknown" },
-	{ 0, NULL }
-};
-
-const char *osmo_bsc_rf_get_opstate_name(enum osmo_bsc_rf_opstate opstate)
-{
-	return get_value_string(opstate_names, opstate);
-}
-
-const char *osmo_bsc_rf_get_adminstate_name(enum osmo_bsc_rf_adminstate adminstate)
-{
-	return get_value_string(adminstate_names, adminstate);
-}
-
-const char *osmo_bsc_rf_get_policy_name(enum osmo_bsc_rf_policy policy)
-{
-	return get_value_string(policy_names, policy);
-}
-
-enum osmo_bsc_rf_opstate osmo_bsc_rf_get_opstate_by_bts(struct gsm_bts *bts)
-{
-	struct gsm_bts_trx *trx;
-
-	llist_for_each_entry(trx, &bts->trx_list, list) {
-		if (trx->mo.nm_state.operational == NM_OPSTATE_ENABLED)
-			return OSMO_BSC_RF_OPSTATE_OPERATIONAL;
-	}
-
-	/* No trx were active, so this bts is disabled */
-	return OSMO_BSC_RF_OPSTATE_INOPERATIONAL;
-}
-
-enum osmo_bsc_rf_adminstate osmo_bsc_rf_get_adminstate_by_bts(struct gsm_bts *bts)
-{
-	struct gsm_bts_trx *trx;
-
-	llist_for_each_entry(trx, &bts->trx_list, list) {
-		if (trx->mo.nm_state.administrative == NM_STATE_UNLOCKED)
-			return OSMO_BSC_RF_ADMINSTATE_UNLOCKED;
-	}
-
-	/* All trx administrative states were locked */
-	return OSMO_BSC_RF_ADMINSTATE_LOCKED;
-}
-
-enum osmo_bsc_rf_policy osmo_bsc_rf_get_policy_by_bts(struct gsm_bts *bts)
-{
-	struct osmo_bsc_data *bsc_data = bts->network->bsc_data;
-
-	if (!bsc_data)
-		return OSMO_BSC_RF_POLICY_UNKNOWN;
-
-	switch (bsc_data->rf_ctrl->policy) {
-	case S_RF_ON:
-		return OSMO_BSC_RF_POLICY_ON;
-	case S_RF_OFF:
-		return OSMO_BSC_RF_POLICY_OFF;
-	case S_RF_GRACE:
-		return OSMO_BSC_RF_POLICY_GRACE;
-	default:
-		return OSMO_BSC_RF_POLICY_UNKNOWN;
-	}
-}
-
-static int lock_each_trx(struct gsm_network *net, int lock)
-{
-	struct gsm_bts *bts;
-
-	llist_for_each_entry(bts, &net->bts_list, list) {
-		struct gsm_bts_trx *trx;
-
-		/* Exclude the BTS from the global lock */
-		if (bts->excl_from_rf_lock) {
-			LOGP(DLINP, LOGL_DEBUG,
-				"Excluding BTS(%d) from trx lock.\n", bts->nr);
-			continue;
-		}
-
-		llist_for_each_entry(trx, &bts->trx_list, list) {
-			gsm_trx_lock_rf(trx, lock);
-		}
-	}
-
-	return 0;
-}
-
-static void send_resp(struct osmo_bsc_rf_conn *conn, char send)
-{
-	struct msgb *msg;
-
-	msg = msgb_alloc(10, "RF Query");
-	if (!msg) {
-		LOGP(DLINP, LOGL_ERROR, "Failed to allocate response msg.\n");
-		return;
-	}
-
-	msg->l2h = msgb_put(msg, 1);
-	msg->l2h[0] = send;
-
-	if (osmo_wqueue_enqueue(&conn->queue, msg) != 0) {
-		LOGP(DLINP, LOGL_ERROR, "Failed to enqueue the answer.\n");
-		msgb_free(msg);
-		return;
-	}
-
-	return;
-}
-
-
-/*
- * Send a
- *    'g' when we are in grace mode
- *    '1' when one TRX is online,
- *    '0' otherwise
- */
-static void handle_query(struct osmo_bsc_rf_conn *conn)
-{
-	struct gsm_bts *bts;
-	char send = RF_CMD_OFF;
-
-	if (conn->rf->policy == S_RF_GRACE)
-		return send_resp(conn, RF_CMD_ON_G);
-
-	llist_for_each_entry(bts, &conn->rf->gsm_network->bts_list, list) {
-		struct gsm_bts_trx *trx;
-
-		/* Exclude the BTS from the global lock */
-		if (bts->excl_from_rf_lock) {
-			LOGP(DLINP, LOGL_DEBUG,
-				"Excluding BTS(%d) from query.\n", bts->nr);
-			continue;
-		}
-		llist_for_each_entry(trx, &bts->trx_list, list) {
-			if (trx->mo.nm_state.availability == NM_AVSTATE_OK &&
-			    trx->mo.nm_state.operational != NM_OPSTATE_DISABLED) {
-					send = RF_CMD_ON;
-					break;
-			}
-		}
-	}
-
-	send_resp(conn, send);
-}
-
-static void rf_check_cb(void *_data)
-{
-	struct gsm_bts *bts;
-	struct osmo_bsc_rf *rf = _data;
-
-	llist_for_each_entry(bts, &rf->gsm_network->bts_list, list) {
-		struct gsm_bts_trx *trx;
-
-		/* don't bother to check a booting or missing BTS */
-		if (!bts->oml_link || !is_ipaccess_bts(bts))
-			continue;
-
-		/* Exclude the BTS from the global lock */
-		if (bts->excl_from_rf_lock) {
-			LOGP(DLINP, LOGL_DEBUG,
-				"Excluding BTS(%d) from query.\n", bts->nr);
-			continue;
-		}
-
-		llist_for_each_entry(trx, &bts->trx_list, list) {
-			if (trx->mo.nm_state.availability != NM_AVSTATE_OK ||
-			    trx->mo.nm_state.operational != NM_OPSTATE_ENABLED ||
-			    trx->mo.nm_state.administrative != NM_STATE_UNLOCKED) {
-				LOGP(DNM, LOGL_ERROR, "RF activation failed. Starting again.\n");
-				ipaccess_drop_oml(bts);
-				break;
-			}
-		}
-	}
-}
-
-static void send_signal(struct osmo_bsc_rf *rf, int val)
-{
-	struct rf_signal_data sig;
-	sig.net = rf->gsm_network;
-
-	rf->policy = val;
-	osmo_signal_dispatch(SS_RF, val, &sig);
-}
-
-static int switch_rf_off(struct osmo_bsc_rf *rf)
-{
-	lock_each_trx(rf->gsm_network, 1);
-	send_signal(rf, S_RF_OFF);
-
-	return 0;
-}
-
-static void grace_timeout(void *_data)
-{
-	struct osmo_bsc_rf *rf = (struct osmo_bsc_rf *) _data;
-
-	LOGP(DLINP, LOGL_NOTICE, "Grace timeout. Going to disable all BTS/TRX.\n");
-	switch_rf_off(rf);
-}
-
-static int enter_grace(struct osmo_bsc_rf *rf)
-{
-	if (osmo_timer_pending(&rf->grace_timeout)) {
-		LOGP(DLINP, LOGL_NOTICE, "RF Grace timer is pending. Not restarting.\n");
-		return 0;
-	}
-
-	osmo_timer_setup(&rf->grace_timeout, grace_timeout, rf);
-	osmo_timer_schedule(&rf->grace_timeout, rf->gsm_network->bsc_data->mid_call_timeout, 0);
-	LOGP(DLINP, LOGL_NOTICE, "Going to switch RF off in %d seconds.\n",
-	     rf->gsm_network->bsc_data->mid_call_timeout);
-
-	send_signal(rf, S_RF_GRACE);
-	return 0;
-}
-
-static void rf_delay_cmd_cb(void *data)
-{
-	struct osmo_bsc_rf *rf = data;
-
-	switch (rf->last_request) {
-	case RF_CMD_D_OFF:
-		rf->last_state_command = "RF Direct Off";
-		osmo_timer_del(&rf->rf_check);
-		osmo_timer_del(&rf->grace_timeout);
-		switch_rf_off(rf);
-		break;
-	case RF_CMD_ON:
-		rf->last_state_command = "RF Direct On";
-		osmo_timer_del(&rf->grace_timeout);
-		lock_each_trx(rf->gsm_network, 0);
-		send_signal(rf, S_RF_ON);
-		osmo_timer_schedule(&rf->rf_check, 3, 0);
-		break;
-	case RF_CMD_OFF:
-		rf->last_state_command = "RF Scheduled Off";
-		osmo_timer_del(&rf->rf_check);
-		enter_grace(rf);
-		break;
-	}
-}
-
-static int rf_read_cmd(struct osmo_fd *fd)
-{
-	struct osmo_bsc_rf_conn *conn = fd->data;
-	char buf[1];
-	int rc;
-
-	rc = read(fd->fd, buf, sizeof(buf));
-	if (rc != sizeof(buf)) {
-		LOGP(DLINP, LOGL_ERROR, "Short read %d/%s\n", errno, strerror(errno));
-		osmo_fd_unregister(fd);
-		close(fd->fd);
-		osmo_wqueue_clear(&conn->queue);
-		talloc_free(conn);
-		return -1;
-	}
-
-	switch (buf[0]) {
-	case RF_CMD_QUERY:
-		handle_query(conn);
-		break;
-	case RF_CMD_D_OFF:
-	case RF_CMD_ON:
-	case RF_CMD_OFF:
-		osmo_bsc_rf_schedule_lock(conn->rf, buf[0]);
-		break;
-	default:
-		conn->rf->last_state_command = "Unknown command";
-		LOGP(DLINP, LOGL_ERROR, "Unknown command %d\n", buf[0]);
-		break;
-	}
-
-	return 0;
-}
-
-static int rf_write_cmd(struct osmo_fd *fd, struct msgb *msg)
-{
-	int rc;
-
-	rc = write(fd->fd, msg->data, msg->len);
-	if (rc != msg->len) {
-		LOGP(DLINP, LOGL_ERROR, "Short write %d/%s\n", errno, strerror(errno));
-		return -1;
-	}
-
-	return 0;
-}
-
-static int rf_ctrl_accept(struct osmo_fd *bfd, unsigned int what)
-{
-	struct osmo_bsc_rf_conn *conn;
-	struct osmo_bsc_rf *rf = bfd->data;
-	struct sockaddr_un addr;
-	socklen_t len = sizeof(addr);
-	int fd;
-
-	fd = accept(bfd->fd, (struct sockaddr *) &addr, &len);
-	if (fd < 0) {
-		LOGP(DLINP, LOGL_ERROR, "Failed to accept. errno: %d/%s\n",
-		     errno, strerror(errno));
-		return -1;
-	}
-
-	conn = talloc_zero(rf, struct osmo_bsc_rf_conn);
-	if (!conn) {
-		LOGP(DLINP, LOGL_ERROR, "Failed to allocate mem.\n");
-		close(fd);
-		return -1;
-	}
-
-	osmo_wqueue_init(&conn->queue, 10);
-	conn->queue.bfd.data = conn;
-	conn->queue.bfd.fd = fd;
-	conn->queue.bfd.when = BSC_FD_READ | BSC_FD_WRITE;
-	conn->queue.read_cb = rf_read_cmd;
-	conn->queue.write_cb = rf_write_cmd;
-	conn->rf = rf;
-
-	if (osmo_fd_register(&conn->queue.bfd) != 0) {
-		close(fd);
-		talloc_free(conn);
-		return -1;
-	}
-
-	return 0;
-}
-
-static void rf_auto_off_cb(void *_timer)
-{
-	struct osmo_bsc_rf *rf = _timer;
-
-	LOGP(DLINP, LOGL_NOTICE,
-		"Going to switch off RF due lack of a MSC connection.\n");
-	osmo_bsc_rf_schedule_lock(rf, RF_CMD_D_OFF);
-}
-
-static int msc_signal_handler(unsigned int subsys, unsigned int signal,
-			void *handler_data, void *signal_data)
-{
-	struct gsm_network *net;
-	struct msc_signal_data *msc;
-	struct osmo_bsc_rf *rf;
-
-	/* check if we want to handle this signal */
-	if (subsys != SS_MSC)
-		return 0;
-
-	net = handler_data;
-	msc = signal_data;
-
-	/* check if we have the needed information */
-	if (!net->bsc_data)
-		return 0;
-	if (msc->data->type != MSC_CON_TYPE_NORMAL)
-		return 0;
-
-	rf = net->bsc_data->rf_ctrl;
-	switch (signal) {
-	case S_MSC_LOST:
-		if (net->bsc_data->auto_off_timeout < 0)
-			return 0;
-		if (osmo_timer_pending(&rf->auto_off_timer))
-			return 0;
-		osmo_timer_schedule(&rf->auto_off_timer,
-				net->bsc_data->auto_off_timeout, 0);
-		break;
-	case S_MSC_CONNECTED:
-		osmo_timer_del(&rf->auto_off_timer);
-		break;
-	}
-
-	return 0;
-}
-
-static int rf_create_socket(struct osmo_bsc_rf *rf, const char *path)
-{
-	unsigned int namelen;
-	struct sockaddr_un local;
-	struct osmo_fd *bfd;
-	int rc;
-
-	bfd = &rf->listen;
-	bfd->fd = socket(AF_UNIX, SOCK_STREAM, 0);
-	if (bfd->fd < 0) {
-		LOGP(DLINP, LOGL_ERROR, "Can not create socket. %d/%s\n",
-		     errno, strerror(errno));
-		return -1;
-	}
-
-	local.sun_family = AF_UNIX;
-	osmo_strlcpy(local.sun_path, path, sizeof(local.sun_path));
-	unlink(local.sun_path);
-
-	/* we use the same magic that X11 uses in Xtranssock.c for
-	 * calculating the proper length of the sockaddr */
-#if defined(BSD44SOCKETS) || defined(__UNIXWARE__)
-	local.sun_len = strlen(local.sun_path);
-#endif
-#if defined(BSD44SOCKETS) || defined(SUN_LEN)
-	namelen = SUN_LEN(&local);
-#else
-	namelen = strlen(local.sun_path) +
-		  offsetof(struct sockaddr_un, sun_path);
-#endif
-
-	rc = bind(bfd->fd, (struct sockaddr *) &local, namelen);
-	if (rc != 0) {
-		LOGP(DLINP, LOGL_ERROR, "Failed to bind '%s' errno: %d/%s\n",
-		     local.sun_path, errno, strerror(errno));
-		close(bfd->fd);
-		return -1;
-	}
-
-	if (listen(bfd->fd, 0) != 0) {
-		LOGP(DLINP, LOGL_ERROR, "Failed to listen: %d/%s\n", errno, strerror(errno));
-		close(bfd->fd);
-		return -1;
-	}
-
-	bfd->when = BSC_FD_READ;
-	bfd->cb = rf_ctrl_accept;
-	bfd->data = rf;
-
-	if (osmo_fd_register(bfd) != 0) {
-		LOGP(DLINP, LOGL_ERROR, "Failed to register bfd.\n");
-		close(bfd->fd);
-		return -1;
-	}
-
-	return 0;
-}
-
-struct osmo_bsc_rf *osmo_bsc_rf_create(const char *path, struct gsm_network *net)
-{
-	struct osmo_bsc_rf *rf;
-
-	rf = talloc_zero(NULL, struct osmo_bsc_rf);
-	if (!rf) {
-		LOGP(DLINP, LOGL_ERROR, "Failed to create osmo_bsc_rf.\n");
-		return NULL;
-	}
-
-	if (path && rf_create_socket(rf, path) != 0) {
-		talloc_free(rf);
-		return NULL;
-	}
-
-	rf->gsm_network = net;
-	rf->policy = S_RF_ON;
-	rf->last_state_command = "";
-	rf->last_rf_lock_ctrl_command = talloc_strdup(rf, "");
-
-	/* check the rf state */
-	osmo_timer_setup(&rf->rf_check, rf_check_cb, rf);
-
-	/* delay cmd handling */
-	osmo_timer_setup(&rf->delay_cmd, rf_delay_cmd_cb, rf);
-
-	osmo_timer_setup(&rf->auto_off_timer, rf_auto_off_cb, rf);
-
-	/* listen to RF signals */
-	osmo_signal_register_handler(SS_MSC, msc_signal_handler, net);
-
-	return rf;
-}
-
-void osmo_bsc_rf_schedule_lock(struct osmo_bsc_rf *rf, char cmd)
-{
-	rf->last_request = cmd;
-	if (!osmo_timer_pending(&rf->delay_cmd))
-		osmo_timer_schedule(&rf->delay_cmd, 1, 0);
-}
diff --git a/src/libbsc/bsc_rll.c b/src/libbsc/bsc_rll.c
deleted file mode 100644
index bb488da..0000000
--- a/src/libbsc/bsc_rll.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/* GSM BSC Radio Link Layer API
- * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
-
-/* (C) 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/>.
- *
- */
-
-#include <errno.h>
-
-#include <openbsc/debug.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/timer.h>
-#include <osmocom/core/linuxlist.h>
-#include <openbsc/bsc_rll.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/chan_alloc.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/signal.h>
-
-struct bsc_rll_req {
-	struct llist_head list;
-	struct osmo_timer_list timer;
-
-	struct gsm_lchan *lchan;
-	uint8_t link_id;
-
-	void (*cb)(struct gsm_lchan *lchan, uint8_t link_id,
-		   void *data, enum bsc_rllr_ind);
-	void *data;
-};
-
-/* we only compare C1, C2 and SAPI */
-#define LINKID_MASK	0xC7
-
-static LLIST_HEAD(bsc_rll_reqs);
-
-static void complete_rllr(struct bsc_rll_req *rllr, enum bsc_rllr_ind type)
-{
-	llist_del(&rllr->list);
-	rllr->cb(rllr->lchan, rllr->link_id, rllr->data, type);
-	talloc_free(rllr);
-}
-
-static void timer_cb(void *_rllr)
-{
-	struct bsc_rll_req *rllr = _rllr;
-
-	complete_rllr(rllr, BSC_RLLR_IND_TIMEOUT);
-}
-
-/* establish a RLL connection with given SAPI / priority */
-int rll_establish(struct gsm_lchan *lchan, uint8_t sapi,
-		  void (*cb)(struct gsm_lchan *, uint8_t, void *,
-			     enum bsc_rllr_ind),
-		  void *data)
-{
-	struct bsc_rll_req *rllr = talloc_zero(tall_bsc_ctx, struct bsc_rll_req);
-	uint8_t link_id;
-	if (!rllr)
-		return -ENOMEM;
-
-	link_id = sapi;
-
-	/* If we are a TCH and not in signalling mode, we need to
-	 * indicate that the new RLL connection is to be made on the SACCH */
-	if ((lchan->type == GSM_LCHAN_TCH_F ||
-	     lchan->type == GSM_LCHAN_TCH_H) && sapi != 0)
-		link_id |= 0x40;
-
-	rllr->lchan = lchan;
-	rllr->link_id = link_id;
-	rllr->cb = cb;
-	rllr->data = data;
-
-	llist_add(&rllr->list, &bsc_rll_reqs);
-
-	osmo_timer_setup(&rllr->timer, timer_cb, rllr);
-	osmo_timer_schedule(&rllr->timer, 7, 0);
-
-	/* send the RSL RLL ESTablish REQuest */
-	return rsl_establish_request(rllr->lchan, rllr->link_id);
-}
-
-/* Called from RSL code in case we have received an indication regarding
- * any RLL link */
-void rll_indication(struct gsm_lchan *lchan, uint8_t link_id, uint8_t type)
-{
-	struct bsc_rll_req *rllr, *rllr2;
-
-	llist_for_each_entry_safe(rllr, rllr2, &bsc_rll_reqs, list) {
-		if (rllr->lchan == lchan &&
-		    (rllr->link_id & LINKID_MASK) == (link_id & LINKID_MASK)) {
-			osmo_timer_del(&rllr->timer);
-			complete_rllr(rllr, type);
-			return;
-		}
-	}
-}
-
-static int rll_lchan_signal(unsigned int subsys, unsigned int signal,
-			    void *handler_data, void *signal_data)
-{
-	struct challoc_signal_data *challoc;
-	struct bsc_rll_req *rllr, *rllr2;
-
-	if (subsys != SS_CHALLOC || signal != S_CHALLOC_FREED)
-		return 0;
-
-	challoc = (struct challoc_signal_data *) signal_data;
-
-	llist_for_each_entry_safe(rllr, rllr2, &bsc_rll_reqs, list) {
-		if (rllr->lchan == challoc->lchan) {
-			osmo_timer_del(&rllr->timer);
-			complete_rllr(rllr, BSC_RLLR_IND_ERR_IND);
-		}
-	}
-
-	return 0;
-}
-
-static __attribute__((constructor)) void on_dso_load_rll(void)
-{
-	osmo_signal_register_handler(SS_CHALLOC, rll_lchan_signal, NULL);
-}
diff --git a/src/libbsc/bsc_subscriber.c b/src/libbsc/bsc_subscriber.c
deleted file mode 100644
index 73e61e8..0000000
--- a/src/libbsc/bsc_subscriber.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/* GSM subscriber details for use in BSC land */
-
-/*
- * (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- *
- * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
- *
- * 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/>.
- *
- */
-
-#include <talloc.h>
-#include <string.h>
-#include <limits.h>
-
-#include <osmocom/gsm/gsm48.h>
-#include <osmocom/core/logging.h>
-
-#include <openbsc/bsc_subscriber.h>
-#include <openbsc/debug.h>
-
-static struct bsc_subscr *bsc_subscr_alloc(struct llist_head *list)
-{
-	struct bsc_subscr *bsub;
-
-	bsub = talloc_zero(list, struct bsc_subscr);
-	if (!bsub)
-		return NULL;
-
-	llist_add_tail(&bsub->entry, list);
-	bsub->use_count = 1;
-
-	return bsub;
-}
-
-struct bsc_subscr *bsc_subscr_find_by_imsi(struct llist_head *list,
-					   const char *imsi)
-{
-	struct bsc_subscr *bsub;
-
-	if (!imsi || !*imsi)
-		return NULL;
-
-	llist_for_each_entry(bsub, list, entry) {
-		if (!strcmp(bsub->imsi, imsi))
-			return bsc_subscr_get(bsub);
-	}
-	return NULL;
-}
-
-struct bsc_subscr *bsc_subscr_find_by_tmsi(struct llist_head *list,
-					   uint32_t tmsi)
-{
-	struct bsc_subscr *bsub;
-
-	if (tmsi == GSM_RESERVED_TMSI)
-		return NULL;
-
-	llist_for_each_entry(bsub, list, entry) {
-		if (bsub->tmsi == tmsi)
-			return bsc_subscr_get(bsub);
-	}
-	return NULL;
-}
-
-void bsc_subscr_set_imsi(struct bsc_subscr *bsub, const char *imsi)
-{
-	if (!bsub)
-		return;
-	osmo_strlcpy(bsub->imsi, imsi, sizeof(bsub->imsi));
-}
-
-struct bsc_subscr *bsc_subscr_find_or_create_by_imsi(struct llist_head *list,
-						     const char *imsi)
-{
-	struct bsc_subscr *bsub;
-	bsub = bsc_subscr_find_by_imsi(list, imsi);
-	if (bsub)
-		return bsub;
-	bsub = bsc_subscr_alloc(list);
-	bsc_subscr_set_imsi(bsub, imsi);
-	return bsub;
-}
-
-struct bsc_subscr *bsc_subscr_find_or_create_by_tmsi(struct llist_head *list,
-						     uint32_t tmsi)
-{
-	struct bsc_subscr *bsub;
-	bsub = bsc_subscr_find_by_tmsi(list, tmsi);
-	if (bsub)
-		return bsub;
-	bsub = bsc_subscr_alloc(list);
-	bsub->tmsi = tmsi;
-	return bsub;
-}
-
-const char *bsc_subscr_name(struct bsc_subscr *bsub)
-{
-	static char buf[32];
-	if (!bsub)
-		return "unknown";
-	if (bsub->imsi[0])
-		snprintf(buf, sizeof(buf), "IMSI:%s", bsub->imsi);
-	else
-		snprintf(buf, sizeof(buf), "TMSI:0x%08x", bsub->tmsi);
-	return buf;
-}
-
-static void bsc_subscr_free(struct bsc_subscr *bsub)
-{
-	llist_del(&bsub->entry);
-	talloc_free(bsub);
-}
-
-struct bsc_subscr *_bsc_subscr_get(struct bsc_subscr *bsub,
-				   const char *file, int line)
-{
-	OSMO_ASSERT(bsub->use_count < INT_MAX);
-	bsub->use_count++;
-	LOGPSRC(DREF, LOGL_DEBUG, file, line,
-		"BSC subscr %s usage increases to: %d\n",
-		bsc_subscr_name(bsub), bsub->use_count);
-	return bsub;
-}
-
-struct bsc_subscr *_bsc_subscr_put(struct bsc_subscr *bsub,
-				   const char *file, int line)
-{
-	bsub->use_count--;
-	LOGPSRC(DREF, bsub->use_count >= 0? LOGL_DEBUG : LOGL_ERROR,
-		file, line,
-		"BSC subscr %s usage decreases to: %d\n",
-		bsc_subscr_name(bsub), bsub->use_count);
-	if (bsub->use_count <= 0)
-		bsc_subscr_free(bsub);
-	return NULL;
-}
-
-void log_set_filter_bsc_subscr(struct log_target *target,
-			       struct bsc_subscr *bsc_subscr)
-{
-	struct bsc_subscr **fsub = (void*)&target->filter_data[LOG_FLT_BSC_SUBSCR];
-
-	/* free the old data */
-	if (*fsub) {
-		bsc_subscr_put(*fsub);
-		*fsub = NULL;
-	}
-
-	if (bsc_subscr) {
-		target->filter_map |= (1 << LOG_FLT_BSC_SUBSCR);
-		*fsub = bsc_subscr_get(bsc_subscr);
-	} else
-		target->filter_map &= ~(1 << LOG_FLT_BSC_SUBSCR);
-}
diff --git a/src/libbsc/bsc_vty.c b/src/libbsc/bsc_vty.c
deleted file mode 100644
index d55c6eb..0000000
--- a/src/libbsc/bsc_vty.c
+++ /dev/null
@@ -1,4412 +0,0 @@
-/* OpenBSC interface to quagga VTY */
-/* (C) 2009-2010 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/>.
- *
- */
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <unistd.h>
-
-#include <osmocom/vty/command.h>
-#include <osmocom/vty/buffer.h>
-#include <osmocom/vty/vty.h>
-#include <osmocom/vty/logging.h>
-#include <osmocom/vty/stats.h>
-#include <osmocom/vty/telnet_interface.h>
-#include <osmocom/vty/misc.h>
-#include <osmocom/gsm/protocol/gsm_04_08.h>
-#include <osmocom/gsm/gsm0502.h>
-#include <osmocom/ctrl/control_if.h>
-
-#include <arpa/inet.h>
-
-#include <osmocom/core/linuxlist.h>
-#include <openbsc/gsm_data.h>
-#include <osmocom/abis/e1_input.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/abis_om2000.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/gsm/abis_nm.h>
-#include <openbsc/chan_alloc.h>
-#include <openbsc/meas_rep.h>
-#include <openbsc/db.h>
-#include <openbsc/vty.h>
-#include <osmocom/gprs/gprs_ns.h>
-#include <openbsc/system_information.h>
-#include <openbsc/debug.h>
-#include <openbsc/paging.h>
-#include <openbsc/ipaccess.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/bsc_msc_data.h>
-#include <openbsc/osmo_bsc_rf.h>
-#include <openbsc/pcu_if.h>
-#include <openbsc/common_cs.h>
-#include <openbsc/vlr.h>
-#include <openbsc/handover.h>
-
-#include <inttypes.h>
-
-#include "../../bscconfig.h"
-
-
-#define LCHAN_NR_STR "Logical Channel Number\n"
-
-
-/* FIXME: this should go to some common file */
-static const struct value_string gprs_ns_timer_strs[] = {
-	{ 0, "tns-block" },
-	{ 1, "tns-block-retries" },
-	{ 2, "tns-reset" },
-	{ 3, "tns-reset-retries" },
-	{ 4, "tns-test" },
-	{ 5, "tns-alive" },
-	{ 6, "tns-alive-retries" },
-	{ 0, NULL }
-};
-
-static const struct value_string gprs_bssgp_cfg_strs[] = {
-	{ 0,	"blocking-timer" },
-	{ 1,	"blocking-retries" },
-	{ 2,	"unblocking-retries" },
-	{ 3,	"reset-timer" },
-	{ 4,	"reset-retries" },
-	{ 5,	"suspend-timer" },
-	{ 6,	"suspend-retries" },
-	{ 7,	"resume-timer" },
-	{ 8,	"resume-retries" },
-	{ 9,	"capability-update-timer" },
-	{ 10,	"capability-update-retries" },
-	{ 0,	NULL }
-};
-
-static const struct value_string bts_neigh_mode_strs[] = {
-	{ NL_MODE_AUTOMATIC, "automatic" },
-	{ NL_MODE_MANUAL, "manual" },
-	{ NL_MODE_MANUAL_SI5SEP, "manual-si5" },
-	{ 0, NULL }
-};
-
-const struct value_string bts_loc_fix_names[] = {
-	{ BTS_LOC_FIX_INVALID,	"invalid" },
-	{ BTS_LOC_FIX_2D,	"fix2d" },
-	{ BTS_LOC_FIX_3D,	"fix3d" },
-	{ 0, NULL }
-};
-
-struct cmd_node bts_node = {
-	BTS_NODE,
-	"%s(config-net-bts)# ",
-	1,
-};
-
-struct cmd_node trx_node = {
-	TRX_NODE,
-	"%s(config-net-bts-trx)# ",
-	1,
-};
-
-struct cmd_node ts_node = {
-	TS_NODE,
-	"%s(config-net-bts-trx-ts)# ",
-	1,
-};
-
-static int dummy_config_write(struct vty *v)
-{
-	return CMD_SUCCESS;
-}
-
-static void net_dump_nmstate(struct vty *vty, struct gsm_nm_state *nms)
-{
-	vty_out(vty,"Oper '%s', Admin '%s', Avail '%s'%s",
-		abis_nm_opstate_name(nms->operational),
-		get_value_string(abis_nm_adm_state_names, nms->administrative),
-		abis_nm_avail_name(nms->availability), VTY_NEWLINE);
-}
-
-static void dump_pchan_load_vty(struct vty *vty, char *prefix,
-				const struct pchan_load *pl)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(pl->pchan); i++) {
-		const struct load_counter *lc = &pl->pchan[i];
-		unsigned int percent;
-
-		if (lc->total == 0)
-			continue;
-
-		percent = (lc->used * 100) / lc->total;
-
-		vty_out(vty, "%s%20s: %3u%% (%u/%u)%s", prefix,
-			gsm_pchan_name(i), percent, lc->used, lc->total,
-			VTY_NEWLINE);
-	}
-}
-
-static void net_dump_vty(struct vty *vty, struct gsm_network *net)
-{
-	struct pchan_load pl;
-
-	vty_out(vty, "BSC is on Country Code %u, Network Code %u "
-		"and has %u BTS%s", net->country_code, net->network_code,
-		net->num_bts, VTY_NEWLINE);
-	vty_out(vty, "  Long network name: '%s'%s",
-		net->name_long, VTY_NEWLINE);
-	vty_out(vty, "  Short network name: '%s'%s",
-		net->name_short, VTY_NEWLINE);
-	vty_out(vty, "  Authentication policy: %s",
-		gsm_auth_policy_name(net->auth_policy));
-	if (net->authorized_reg_str)
-		vty_out(vty, ", authorized regexp: %s", net->authorized_reg_str);
-	vty_out(vty, "%s", VTY_NEWLINE);
-	vty_out(vty, "  Location updating reject cause: %u%s",
-		net->reject_cause, VTY_NEWLINE);
-	vty_out(vty, "  Encryption: A5/%u%s", net->a5_encryption,
-		VTY_NEWLINE);
-	vty_out(vty, "  NECI (TCH/H): %u%s", net->neci,
-		VTY_NEWLINE);
-	vty_out(vty, "  Use TCH for Paging any: %d%s", net->pag_any_tch,
-		VTY_NEWLINE);
-	vty_out(vty, "  RRLP Mode: %s%s", rrlp_mode_name(net->rrlp.mode),
-		VTY_NEWLINE);
-	vty_out(vty, "  MM Info: %s%s", net->send_mm_info ? "On" : "Off",
-		VTY_NEWLINE);
-	vty_out(vty, "  Handover: %s%s", net->handover.active ? "On" : "Off",
-		VTY_NEWLINE);
-	network_chan_load(&pl, net);
-	vty_out(vty, "  Current Channel Load:%s", VTY_NEWLINE);
-	dump_pchan_load_vty(vty, "    ", &pl);
-
-	/* show rf */
-	if (net->bsc_data)
-		vty_out(vty, "  Last RF Command: %s%s",
-			net->bsc_data->rf_ctrl->last_state_command,
-			VTY_NEWLINE);
-	if (net->bsc_data)
-		vty_out(vty, "  Last RF Lock Command: %s%s",
-			net->bsc_data->rf_ctrl->last_rf_lock_ctrl_command,
-			VTY_NEWLINE);
-}
-
-DEFUN(bsc_show_net, bsc_show_net_cmd, "show network",
-	SHOW_STR "Display information about a GSM NETWORK\n")
-{
-	struct gsm_network *net = gsmnet_from_vty(vty);
-	net_dump_vty(vty, net);
-
-	return CMD_SUCCESS;
-}
-
-static void e1isl_dump_vty(struct vty *vty, struct e1inp_sign_link *e1l)
-{
-	struct e1inp_line *line;
-
-	if (!e1l) {
-		vty_out(vty, "   None%s", VTY_NEWLINE);
-		return;
-	}
-
-	line = e1l->ts->line;
-
-	vty_out(vty, "    E1 Line %u, Type %s: Timeslot %u, Mode %s%s",
-		line->num, line->driver->name, e1l->ts->num,
-		e1inp_signtype_name(e1l->type), VTY_NEWLINE);
-	vty_out(vty, "    E1 TEI %u, SAPI %u%s",
-		e1l->tei, e1l->sapi, VTY_NEWLINE);
-}
-
-static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
-{
-	struct pchan_load pl;
-
-	vty_out(vty, "BTS %u is of %s type in band %s, has CI %u LAC %u, "
-		"BSIC %u (NCC=%u, BCC=%u) and %u TRX%s",
-		bts->nr, btstype2str(bts->type), gsm_band_name(bts->band),
-		bts->cell_identity,
-		bts->location_area_code, bts->bsic,
-		bts->bsic >> 3, bts->bsic & 7,
-		bts->num_trx, VTY_NEWLINE);
-	vty_out(vty, "Description: %s%s",
-		bts->description ? bts->description : "(null)", VTY_NEWLINE);
-	if (strnlen(bts->pcu_version, MAX_VERSION_LENGTH))
-		vty_out(vty, "PCU version %s connected%s", bts->pcu_version,
-			VTY_NEWLINE);
-	vty_out(vty, "MS Max power: %u dBm%s", bts->ms_max_power, VTY_NEWLINE);
-	vty_out(vty, "Minimum Rx Level for Access: %i dBm%s",
-		rxlev2dbm(bts->si_common.cell_sel_par.rxlev_acc_min),
-		VTY_NEWLINE);
-	vty_out(vty, "Cell Reselection Hysteresis: %u dBm%s",
-		bts->si_common.cell_sel_par.cell_resel_hyst*2, VTY_NEWLINE);
-	vty_out(vty, "RACH TX-Integer: %u%s", bts->si_common.rach_control.tx_integer,
-		VTY_NEWLINE);
-	vty_out(vty, "RACH Max transmissions: %u%s",
-		rach_max_trans_raw2val(bts->si_common.rach_control.max_trans),
-		VTY_NEWLINE);
-	if (bts->si_common.rach_control.cell_bar)
-		vty_out(vty, "  CELL IS BARRED%s", VTY_NEWLINE);
-	if (bts->dtxu != GSM48_DTX_SHALL_NOT_BE_USED)
-		vty_out(vty, "Uplink DTX: %s%s",
-			(bts->dtxu != GSM48_DTX_SHALL_BE_USED) ?
-			"enabled" : "forced", VTY_NEWLINE);
-	else
-		vty_out(vty, "Uplink DTX: not enabled%s", VTY_NEWLINE);
-	vty_out(vty, "Downlink DTX: %senabled%s", bts->dtxd ? "" : "not ",
-		VTY_NEWLINE);
-	vty_out(vty, "Channel Description Attachment: %s%s",
-		(bts->si_common.chan_desc.att) ? "yes" : "no", VTY_NEWLINE);
-	vty_out(vty, "Channel Description BS-PA-MFRMS: %u%s",
-		bts->si_common.chan_desc.bs_pa_mfrms + 2, VTY_NEWLINE);
-	vty_out(vty, "Channel Description BS-AG_BLKS-RES: %u%s",
-		bts->si_common.chan_desc.bs_ag_blks_res, VTY_NEWLINE);
-	vty_out(vty, "System Information present: 0x%08x, static: 0x%08x%s",
-		bts->si_valid, bts->si_mode_static, VTY_NEWLINE);
-	vty_out(vty, "Early Classmark Sending: %s%s",
-		bts->early_classmark_allowed ? "allowed" : "forbidden",
-		VTY_NEWLINE);
-	if (bts->pcu_sock_path)
-		vty_out(vty, "PCU Socket Path: %s%s", bts->pcu_sock_path, VTY_NEWLINE);
-	if (is_ipaccess_bts(bts))
-		vty_out(vty, "  Unit ID: %u/%u/0, OML Stream ID 0x%02x%s",
-			bts->ip_access.site_id, bts->ip_access.bts_id,
-			bts->oml_tei, VTY_NEWLINE);
-	else if (bts->type == GSM_BTS_TYPE_NOKIA_SITE)
-		vty_out(vty, "  Skip Reset: %d%s",
-			bts->nokia.skip_reset, VTY_NEWLINE);
-	vty_out(vty, "  NM State: ");
-	net_dump_nmstate(vty, &bts->mo.nm_state);
-	vty_out(vty, "  Site Mgr NM State: ");
-	net_dump_nmstate(vty, &bts->site_mgr.mo.nm_state);
-	vty_out(vty, "  GPRS NSE: ");
-	net_dump_nmstate(vty, &bts->gprs.nse.mo.nm_state);
-	vty_out(vty, "  GPRS CELL: ");
-	net_dump_nmstate(vty, &bts->gprs.cell.mo.nm_state);
-	vty_out(vty, "  GPRS NSVC0: ");
-	net_dump_nmstate(vty, &bts->gprs.nsvc[0].mo.nm_state);
-	vty_out(vty, "  GPRS NSVC1: ");
-	net_dump_nmstate(vty, &bts->gprs.nsvc[1].mo.nm_state);
-	vty_out(vty, "  Paging: %u pending requests, %u free slots%s",
-		paging_pending_requests_nr(bts),
-		bts->paging.available_slots, VTY_NEWLINE);
-	if (is_ipaccess_bts(bts)) {
-		vty_out(vty, "  OML Link state: %s.%s",
-			bts->oml_link ? "connected" : "disconnected", VTY_NEWLINE);
-	} else {
-		vty_out(vty, "  E1 Signalling Link:%s", VTY_NEWLINE);
-		e1isl_dump_vty(vty, bts->oml_link);
-	}
-
-	/* FIXME: chan_desc */
-	memset(&pl, 0, sizeof(pl));
-	bts_chan_load(&pl, bts);
-	vty_out(vty, "  Current Channel Load:%s", VTY_NEWLINE);
-	dump_pchan_load_vty(vty, "    ", &pl);
-}
-
-DEFUN(show_bts, show_bts_cmd, "show bts [<0-255>]",
-	SHOW_STR "Display information about a BTS\n"
-		"BTS number")
-{
-	struct gsm_network *net = gsmnet_from_vty(vty);
-	int bts_nr;
-
-	if (argc != 0) {
-		/* use the BTS number that the user has specified */
-		bts_nr = atoi(argv[0]);
-		if (bts_nr >= net->num_bts) {
-			vty_out(vty, "%% can't find BTS '%s'%s", argv[0],
-				VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-		bts_dump_vty(vty, gsm_bts_num(net, bts_nr));
-		return CMD_SUCCESS;
-	}
-	/* print all BTS's */
-	for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++)
-		bts_dump_vty(vty, gsm_bts_num(net, bts_nr));
-
-	return CMD_SUCCESS;
-}
-
-/* utility functions */
-static void parse_e1_link(struct gsm_e1_subslot *e1_link, const char *line,
-			  const char *ts, const char *ss)
-{
-	e1_link->e1_nr = atoi(line);
-	e1_link->e1_ts = atoi(ts);
-	if (!strcmp(ss, "full"))
-		e1_link->e1_ts_ss = 255;
-	else
-		e1_link->e1_ts_ss = atoi(ss);
-}
-
-static void config_write_e1_link(struct vty *vty, struct gsm_e1_subslot *e1_link,
-				 const char *prefix)
-{
-	if (!e1_link->e1_ts)
-		return;
-
-	if (e1_link->e1_ts_ss == 255)
-		vty_out(vty, "%se1 line %u timeslot %u sub-slot full%s",
-			prefix, e1_link->e1_nr, e1_link->e1_ts, VTY_NEWLINE);
-	else
-		vty_out(vty, "%se1 line %u timeslot %u sub-slot %u%s",
-			prefix, e1_link->e1_nr, e1_link->e1_ts,
-			e1_link->e1_ts_ss, VTY_NEWLINE);
-}
-
-
-static void config_write_ts_single(struct vty *vty, struct gsm_bts_trx_ts *ts)
-{
-	vty_out(vty, "   timeslot %u%s", ts->nr, VTY_NEWLINE);
-	if (ts->tsc != -1)
-		vty_out(vty, "    training_sequence_code %u%s", ts->tsc, VTY_NEWLINE);
-	if (ts->pchan != GSM_PCHAN_NONE)
-		vty_out(vty, "    phys_chan_config %s%s",
-			gsm_pchan_name(ts->pchan), VTY_NEWLINE);
-	vty_out(vty, "    hopping enabled %u%s",
-		ts->hopping.enabled, VTY_NEWLINE);
-	if (ts->hopping.enabled) {
-		unsigned int i;
-		vty_out(vty, "    hopping sequence-number %u%s",
-			ts->hopping.hsn, VTY_NEWLINE);
-		vty_out(vty, "    hopping maio %u%s",
-			ts->hopping.maio, VTY_NEWLINE);
-		for (i = 0; i < ts->hopping.arfcns.data_len*8; i++) {
-			if (!bitvec_get_bit_pos(&ts->hopping.arfcns, i))
-				continue;
-			vty_out(vty, "    hopping arfcn add %u%s",
-				i, VTY_NEWLINE);
-		}
-	}
-	config_write_e1_link(vty, &ts->e1_link, "    ");
-
-	if (ts->trx->bts->model->config_write_ts)
-		ts->trx->bts->model->config_write_ts(vty, ts);
-}
-
-static void config_write_trx_single(struct vty *vty, struct gsm_bts_trx *trx)
-{
-	int i;
-
-	vty_out(vty, "  trx %u%s", trx->nr, VTY_NEWLINE);
-	if (trx->description)
-		vty_out(vty, "   description %s%s", trx->description,
-			VTY_NEWLINE);
-	vty_out(vty, "   rf_locked %u%s",
-		trx->mo.nm_state.administrative == NM_STATE_LOCKED ? 1 : 0,
-		VTY_NEWLINE);
-	vty_out(vty, "   arfcn %u%s", trx->arfcn, VTY_NEWLINE);
-	vty_out(vty, "   nominal power %u%s", trx->nominal_power, VTY_NEWLINE);
-	vty_out(vty, "   max_power_red %u%s", trx->max_power_red, VTY_NEWLINE);
-	config_write_e1_link(vty, &trx->rsl_e1_link, "   rsl ");
-	vty_out(vty, "   rsl e1 tei %u%s", trx->rsl_tei, VTY_NEWLINE);
-
-	if (trx->bts->model->config_write_trx)
-		trx->bts->model->config_write_trx(vty, trx);
-
-	for (i = 0; i < TRX_NR_TS; i++)
-		config_write_ts_single(vty, &trx->ts[i]);
-}
-
-static void config_write_bts_gprs(struct vty *vty, struct gsm_bts *bts)
-{
-	unsigned int i;
-	vty_out(vty, "  gprs mode %s%s", bts_gprs_mode_name(bts->gprs.mode),
-		VTY_NEWLINE);
-	if (bts->gprs.mode == BTS_GPRS_NONE)
-		return;
-
-	vty_out(vty, "  gprs 11bit_rach_support_for_egprs %u%s",
-		bts->gprs.supports_egprs_11bit_rach, VTY_NEWLINE);
-
-	vty_out(vty, "  gprs routing area %u%s", bts->gprs.rac,
-		VTY_NEWLINE);
-	vty_out(vty, "  gprs network-control-order nc%u%s",
-		bts->gprs.net_ctrl_ord, VTY_NEWLINE);
-	if (!bts->gprs.ctrl_ack_type_use_block)
-		vty_out(vty, "  gprs control-ack-type-rach%s", VTY_NEWLINE);
-	vty_out(vty, "  gprs cell bvci %u%s", bts->gprs.cell.bvci,
-		VTY_NEWLINE);
-	for (i = 0; i < ARRAY_SIZE(bts->gprs.cell.timer); i++)
-		vty_out(vty, "  gprs cell timer %s %u%s",
-			get_value_string(gprs_bssgp_cfg_strs, i),
-			bts->gprs.cell.timer[i], VTY_NEWLINE);
-	vty_out(vty, "  gprs nsei %u%s", bts->gprs.nse.nsei,
-		VTY_NEWLINE);
-	for (i = 0; i < ARRAY_SIZE(bts->gprs.nse.timer); i++)
-		vty_out(vty, "  gprs ns timer %s %u%s",
-			get_value_string(gprs_ns_timer_strs, i),
-			bts->gprs.nse.timer[i], VTY_NEWLINE);
-	for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) {
-		struct gsm_bts_gprs_nsvc *nsvc =
-					&bts->gprs.nsvc[i];
-		struct in_addr ia;
-
-		ia.s_addr = htonl(nsvc->remote_ip);
-		vty_out(vty, "  gprs nsvc %u nsvci %u%s", i,
-			nsvc->nsvci, VTY_NEWLINE);
-		vty_out(vty, "  gprs nsvc %u local udp port %u%s", i,
-			nsvc->local_port, VTY_NEWLINE);
-		vty_out(vty, "  gprs nsvc %u remote udp port %u%s", i,
-			nsvc->remote_port, VTY_NEWLINE);
-		vty_out(vty, "  gprs nsvc %u remote ip %s%s", i,
-			inet_ntoa(ia), VTY_NEWLINE);
-	}
-}
-
-/* Write the model data if there is one */
-static void config_write_bts_model(struct vty *vty, struct gsm_bts *bts)
-{
-	struct gsm_bts_trx *trx;
-
-	if (!bts->model)
-		return;
-
-	if (bts->model->config_write_bts)
-		bts->model->config_write_bts(vty, bts);
-
-	llist_for_each_entry(trx, &bts->trx_list, list)
-		config_write_trx_single(vty, trx);
-}
-
-static void write_amr_modes(struct vty *vty, const char *prefix,
-	const char *name, struct amr_mode *modes, int num)
-{
-	int i;
-
-	vty_out(vty, "  %s threshold %s", prefix, name);
-	for (i = 0; i < num - 1; i++)
-		vty_out(vty, " %d", modes[i].threshold);
-	vty_out(vty, "%s", VTY_NEWLINE);
-	vty_out(vty, "  %s hysteresis %s", prefix, name);
-	for (i = 0; i < num - 1; i++)
-		vty_out(vty, " %d", modes[i].hysteresis);
-	vty_out(vty, "%s", VTY_NEWLINE);
-}
-
-static void config_write_bts_amr(struct vty *vty, struct gsm_bts *bts,
-	struct amr_multirate_conf *mr, int full)
-{
-	struct gsm48_multi_rate_conf *mr_conf;
-	const char *prefix = (full) ? "amr tch-f" : "amr tch-h";
-	int i, num;
-
-	if (!(mr->gsm48_ie[1]))
-		return;
-
-	mr_conf = (struct gsm48_multi_rate_conf *) mr->gsm48_ie;
-
-	num = 0;
-	vty_out(vty, "  %s modes", prefix);
-	for (i = 0; i < ((full) ? 8 : 6); i++) {
-		if ((mr->gsm48_ie[1] & (1 << i))) {
-			vty_out(vty, " %d", i);
-			num++;
-		}
-	}
-	vty_out(vty, "%s", VTY_NEWLINE);
-	if (num > 4)
-		num = 4;
-	if (num > 1) {
-		write_amr_modes(vty, prefix, "ms", mr->ms_mode, num);
-		write_amr_modes(vty, prefix, "bts", mr->bts_mode, num);
-	}
-	vty_out(vty, "  %s start-mode ", prefix);
-	if (mr_conf->icmi) {
-		num = 0;
-		for (i = 0; i < ((full) ? 8 : 6) && num < 4; i++) {
-			if ((mr->gsm48_ie[1] & (1 << i)))
-				num++;
-			if (mr_conf->smod == num - 1) {
-				vty_out(vty, "%d%s", num, VTY_NEWLINE);
-				break;
-			}
-		}
-	} else
-		vty_out(vty, "auto%s", VTY_NEWLINE);
-}
-
-static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
-{
-	int i;
-	uint8_t tmp;
-
-	vty_out(vty, " bts %u%s", bts->nr, VTY_NEWLINE);
-	vty_out(vty, "  type %s%s", btstype2str(bts->type), VTY_NEWLINE);
-	if (bts->description)
-		vty_out(vty, "  description %s%s", bts->description, VTY_NEWLINE);
-	vty_out(vty, "  band %s%s", gsm_band_name(bts->band), VTY_NEWLINE);
-	vty_out(vty, "  cell_identity %u%s", bts->cell_identity, VTY_NEWLINE);
-	vty_out(vty, "  location_area_code %u%s", bts->location_area_code,
-		VTY_NEWLINE);
-	if (bts->dtxu != GSM48_DTX_SHALL_NOT_BE_USED)
-		vty_out(vty, "  dtx uplink%s%s",
-			(bts->dtxu != GSM48_DTX_SHALL_BE_USED) ? "" : " force",
-			VTY_NEWLINE);
-	if (bts->dtxd)
-		vty_out(vty, "  dtx downlink%s", VTY_NEWLINE);
-	vty_out(vty, "  base_station_id_code %u%s", bts->bsic, VTY_NEWLINE);
-	vty_out(vty, "  ms max power %u%s", bts->ms_max_power, VTY_NEWLINE);
-	vty_out(vty, "  cell reselection hysteresis %u%s",
-		bts->si_common.cell_sel_par.cell_resel_hyst*2, VTY_NEWLINE);
-	vty_out(vty, "  rxlev access min %u%s",
-		bts->si_common.cell_sel_par.rxlev_acc_min, VTY_NEWLINE);
-
-	if (bts->si_common.cell_ro_sel_par.present) {
-		struct gsm48_si_selection_params *sp;
-		sp = &bts->si_common.cell_ro_sel_par;
-
-		if (sp->cbq)
-			vty_out(vty, "  cell bar qualify %u%s",
-				sp->cbq, VTY_NEWLINE);
-
-		if (sp->cell_resel_off)
-			vty_out(vty, "  cell reselection offset %u%s",
-				sp->cell_resel_off*2, VTY_NEWLINE);
-
-		if (sp->temp_offs == 7)
-			vty_out(vty, "  temporary offset infinite%s",
-				VTY_NEWLINE);
-		else if (sp->temp_offs)
-			vty_out(vty, "  temporary offset %u%s",
-				sp->temp_offs*10, VTY_NEWLINE);
-
-		if (sp->penalty_time == 31)
-			vty_out(vty, "  penalty time reserved%s",
-				VTY_NEWLINE);
-		else if (sp->penalty_time)
-			vty_out(vty, "  penalty time %u%s",
-				(sp->penalty_time*20)+20, VTY_NEWLINE);
-	}
-
-	if (gsm_bts_get_radio_link_timeout(bts) < 0)
-		vty_out(vty, "  radio-link-timeout infinite%s", VTY_NEWLINE);
-	else
-		vty_out(vty, "  radio-link-timeout %d%s",
-			gsm_bts_get_radio_link_timeout(bts), VTY_NEWLINE);
-	
-	vty_out(vty, "  channel allocator %s%s",
-		bts->chan_alloc_reverse ? "descending" : "ascending",
-		VTY_NEWLINE);
-	vty_out(vty, "  rach tx integer %u%s",
-		bts->si_common.rach_control.tx_integer, VTY_NEWLINE);
-	vty_out(vty, "  rach max transmission %u%s",
-		rach_max_trans_raw2val(bts->si_common.rach_control.max_trans),
-		VTY_NEWLINE);
-
-	vty_out(vty, "  channel-descrption attach %u%s",
-		bts->si_common.chan_desc.att, VTY_NEWLINE);
-	vty_out(vty, "  channel-descrption bs-pa-mfrms %u%s",
-		bts->si_common.chan_desc.bs_pa_mfrms + 2, VTY_NEWLINE);
-	vty_out(vty, "  channel-descrption bs-ag-blks-res %u%s",
-		bts->si_common.chan_desc.bs_ag_blks_res, VTY_NEWLINE);
-
-	if (bts->rach_b_thresh != -1)
-		vty_out(vty, "  rach nm busy threshold %u%s",
-			bts->rach_b_thresh, VTY_NEWLINE);
-	if (bts->rach_ldavg_slots != -1)
-		vty_out(vty, "  rach nm load average %u%s",
-			bts->rach_ldavg_slots, VTY_NEWLINE);
-	if (bts->si_common.rach_control.cell_bar)
-		vty_out(vty, "  cell barred 1%s", VTY_NEWLINE);
-	if ((bts->si_common.rach_control.t2 & 0x4) == 0)
-		vty_out(vty, "  rach emergency call allowed 1%s", VTY_NEWLINE);
-	if ((bts->si_common.rach_control.t3) != 0)
-		for (i = 0; i < 8; i++)
-			if (bts->si_common.rach_control.t3 & (0x1 << i))
-				vty_out(vty, "  rach access-control-class %d barred%s", i, VTY_NEWLINE);
-	if ((bts->si_common.rach_control.t2 & 0xfb) != 0)
-		for (i = 0; i < 8; i++)
-			if ((i != 2) && (bts->si_common.rach_control.t2 & (0x1 << i)))
-				vty_out(vty, "  rach access-control-class %d barred%s", i+8, VTY_NEWLINE);
-	for (i = SYSINFO_TYPE_1; i < _MAX_SYSINFO_TYPE; i++) {
-		if (bts->si_mode_static & (1 << i)) {
-			vty_out(vty, "  system-information %s mode static%s",
-				get_value_string(osmo_sitype_strs, i), VTY_NEWLINE);
-			vty_out(vty, "  system-information %s static %s%s",
-				get_value_string(osmo_sitype_strs, i),
-				osmo_hexdump_nospc(GSM_BTS_SI(bts, i), GSM_MACBLOCK_LEN),
-				VTY_NEWLINE);
-		}
-	}
-	vty_out(vty, "  early-classmark-sending %s%s",
-		bts->early_classmark_allowed ? "allowed" : "forbidden", VTY_NEWLINE);
-	switch (bts->type) {
-	case GSM_BTS_TYPE_NANOBTS:
-	case GSM_BTS_TYPE_OSMOBTS:
-		vty_out(vty, "  ip.access unit_id %u %u%s",
-			bts->ip_access.site_id, bts->ip_access.bts_id, VTY_NEWLINE);
-		if (bts->ip_access.rsl_ip) {
-			struct in_addr ia;
-			ia.s_addr = htonl(bts->ip_access.rsl_ip);
-			vty_out(vty, "  ip.access rsl-ip %s%s", inet_ntoa(ia),
-				VTY_NEWLINE);
-		}
-		vty_out(vty, "  oml ip.access stream_id %u line %u%s",
-			bts->oml_tei, bts->oml_e1_link.e1_nr, VTY_NEWLINE);
-		break;
-	case GSM_BTS_TYPE_NOKIA_SITE:
-		vty_out(vty, "  nokia_site skip-reset %d%s", bts->nokia.skip_reset, VTY_NEWLINE);
-		vty_out(vty, "  nokia_site no-local-rel-conf %d%s",
-			bts->nokia.no_loc_rel_cnf, VTY_NEWLINE);
-		vty_out(vty, "  nokia_site bts-reset-timer %d%s", bts->nokia.bts_reset_timer_cnf, VTY_NEWLINE);
-		/* fall through: Nokia requires "oml e1" parameters also */
-	default:
-		config_write_e1_link(vty, &bts->oml_e1_link, "  oml ");
-		vty_out(vty, "  oml e1 tei %u%s", bts->oml_tei, VTY_NEWLINE);
-		break;
-	}
-
-	/* if we have a limit, write it */
-	if (bts->paging.free_chans_need >= 0)
-		vty_out(vty, "  paging free %d%s", bts->paging.free_chans_need, VTY_NEWLINE);
-
-	vty_out(vty, "  neighbor-list mode %s%s",
-		get_value_string(bts_neigh_mode_strs, bts->neigh_list_manual_mode), VTY_NEWLINE);
-	if (bts->neigh_list_manual_mode != NL_MODE_AUTOMATIC) {
-		for (i = 0; i < 1024; i++) {
-			if (bitvec_get_bit_pos(&bts->si_common.neigh_list, i))
-				vty_out(vty, "  neighbor-list add arfcn %u%s",
-					i, VTY_NEWLINE);
-		}
-	}
-	if (bts->neigh_list_manual_mode == NL_MODE_MANUAL_SI5SEP) {
-		for (i = 0; i < 1024; i++) {
-			if (bitvec_get_bit_pos(&bts->si_common.si5_neigh_list, i))
-				vty_out(vty, "  si5 neighbor-list add arfcn %u%s",
-					i, VTY_NEWLINE);
-		}
-	}
-
-	for (i = 0; i < MAX_EARFCN_LIST; i++) {
-		struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list;
-		if (e->arfcn[i] != OSMO_EARFCN_INVALID) {
-			vty_out(vty, "  si2quater neighbor-list add earfcn %u "
-				"thresh-hi %u", e->arfcn[i], e->thresh_hi);
-
-			vty_out(vty, " thresh-lo %u",
-				e->thresh_lo_valid ? e->thresh_lo : 32);
-
-			vty_out(vty, " prio %u",
-				e->prio_valid ? e->prio : 8);
-
-			vty_out(vty, " qrxlv %u",
-				e->qrxlm_valid ? e->qrxlm : 32);
-
-			tmp = e->meas_bw[i];
-			vty_out(vty, " meas %u",
-				(tmp != OSMO_EARFCN_MEAS_INVALID) ? tmp : 8);
-
-			vty_out(vty, "%s", VTY_NEWLINE);
-		}
-	}
-
-	for (i = 0; i < bts->si_common.uarfcn_length; i++) {
-		vty_out(vty, "  si2quater neighbor-list add uarfcn %u %u %u%s",
-			bts->si_common.data.uarfcn_list[i],
-			bts->si_common.data.scramble_list[i] & ~(1 << 9),
-			(bts->si_common.data.scramble_list[i] >> 9) & 1,
-			VTY_NEWLINE);
-	}
-
-	vty_out(vty, "  codec-support fr");
-	if (bts->codec.hr)
-		vty_out(vty, " hr");
-	if (bts->codec.efr)
-		vty_out(vty, " efr");
-	if (bts->codec.amr)
-		vty_out(vty, " amr");
-	vty_out(vty, "%s", VTY_NEWLINE);
-
-	config_write_bts_amr(vty, bts, &bts->mr_full, 1);
-	config_write_bts_amr(vty, bts, &bts->mr_half, 0);
-
-	config_write_bts_gprs(vty, bts);
-
-	if (bts->excl_from_rf_lock)
-		vty_out(vty, "  rf-lock-exclude%s", VTY_NEWLINE);
-
-	vty_out(vty, "  %sforce-combined-si%s",
-		bts->force_combined_si ? "" : "no ", VTY_NEWLINE);
-
-	for (i = 0; i < ARRAY_SIZE(bts->depends_on); ++i) {
-		int j;
-
-		if (bts->depends_on[i] == 0)
-			continue;
-
-		for (j = 0; j < sizeof(bts->depends_on[i]) * 8; ++j) {
-			int bts_nr;
-
-			if ((bts->depends_on[i] & (1<<j)) == 0)
-				continue;
-
-			bts_nr = (i * sizeof(bts->depends_on[i]) * 8) + j;
-			vty_out(vty, "  depends-on-bts %d%s", bts_nr, VTY_NEWLINE);
-		}
-	}
-	if (bts->pcu_sock_path)
-		vty_out(vty, "  pcu-socket %s%s", bts->pcu_sock_path, VTY_NEWLINE);
-
-	config_write_bts_model(vty, bts);
-}
-
-static int config_write_bts(struct vty *v)
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(v);
-	struct gsm_bts *bts;
-
-	llist_for_each_entry(bts, &gsmnet->bts_list, list)
-		config_write_bts_single(v, bts);
-
-	return CMD_SUCCESS;
-}
-
-/* small helper macro for conditional dumping of timer */
-#define VTY_OUT_TIMER(number)	\
-	if (gsmnet->T##number != GSM_T##number##_DEFAULT)	\
-		vty_out(vty, " timer t"#number" %u%s", gsmnet->T##number, VTY_NEWLINE)
-
-static int config_write_net(struct vty *vty)
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-
-	vty_out(vty, "network%s", VTY_NEWLINE);
-	vty_out(vty, " network country code %u%s", gsmnet->country_code, VTY_NEWLINE);
-	vty_out(vty, " mobile network code %u%s", gsmnet->network_code, VTY_NEWLINE);
-	vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
-	vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
-	vty_out(vty, " auth policy %s%s", gsm_auth_policy_name(gsmnet->auth_policy), VTY_NEWLINE);
-	if (gsmnet->authorized_reg_str)
-		vty_out(vty, " authorized-regexp %s%s", gsmnet->authorized_reg_str, VTY_NEWLINE);
-	vty_out(vty, " location updating reject cause %u%s",
-		gsmnet->reject_cause, VTY_NEWLINE);
-	vty_out(vty, " encryption a5 %u%s", gsmnet->a5_encryption, VTY_NEWLINE);
-	vty_out(vty, " authentication %s%s",
-		gsmnet->authentication_required ?  "required" : "optional",
-		VTY_NEWLINE);
-	vty_out(vty, " neci %u%s", gsmnet->neci, VTY_NEWLINE);
-	vty_out(vty, " paging any use tch %d%s", gsmnet->pag_any_tch, VTY_NEWLINE);
-	vty_out(vty, " rrlp mode %s%s", rrlp_mode_name(gsmnet->rrlp.mode),
-		VTY_NEWLINE);
-	vty_out(vty, " mm info %u%s", gsmnet->send_mm_info, VTY_NEWLINE);
-	vty_out(vty, " handover %u%s", gsmnet->handover.active, VTY_NEWLINE);
-	vty_out(vty, " handover window rxlev averaging %u%s",
-		gsmnet->handover.win_rxlev_avg, VTY_NEWLINE);
-	vty_out(vty, " handover window rxqual averaging %u%s",
-		gsmnet->handover.win_rxqual_avg, VTY_NEWLINE);
-	vty_out(vty, " handover window rxlev neighbor averaging %u%s",
-		gsmnet->handover.win_rxlev_avg_neigh, VTY_NEWLINE);
-	vty_out(vty, " handover power budget interval %u%s",
-		gsmnet->handover.pwr_interval, VTY_NEWLINE);
-	vty_out(vty, " handover power budget hysteresis %u%s",
-		gsmnet->handover.pwr_hysteresis, VTY_NEWLINE);
-	vty_out(vty, " handover maximum distance %u%s",
-		gsmnet->handover.max_distance, VTY_NEWLINE);
-	VTY_OUT_TIMER(3101);
-	VTY_OUT_TIMER(3103);
-	VTY_OUT_TIMER(3105);
-	VTY_OUT_TIMER(3107);
-	VTY_OUT_TIMER(3109);
-	VTY_OUT_TIMER(3111);
-	VTY_OUT_TIMER(3113);
-	VTY_OUT_TIMER(3115);
-	VTY_OUT_TIMER(3117);
-	VTY_OUT_TIMER(3119);
-	VTY_OUT_TIMER(3122);
-	VTY_OUT_TIMER(3141);
-	vty_out(vty, " dyn_ts_allow_tch_f %d%s",
-		gsmnet->dyn_ts_allow_tch_f ? 1 : 0, VTY_NEWLINE);
-	if (gsmnet->tz.override != 0) {
-		if (gsmnet->tz.dst)
-			vty_out(vty, " timezone %d %d %d%s",
-				gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
-				VTY_NEWLINE);
-		else
-			vty_out(vty, " timezone %d %d%s",
-				gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
-	}
-	if (gsmnet->t3212 == 0)
-		vty_out(vty, " no periodic location update%s", VTY_NEWLINE);
-	else
-		vty_out(vty, " periodic location update %u%s",
-			gsmnet->t3212 * 6, VTY_NEWLINE);
-
-	return CMD_SUCCESS;
-}
-
-static void trx_dump_vty(struct vty *vty, struct gsm_bts_trx *trx)
-{
-	vty_out(vty, "TRX %u of BTS %u is on ARFCN %u%s",
-		trx->nr, trx->bts->nr, trx->arfcn, VTY_NEWLINE);
-	vty_out(vty, "Description: %s%s",
-		trx->description ? trx->description : "(null)", VTY_NEWLINE);
-	vty_out(vty, "  RF Nominal Power: %d dBm, reduced by %u dB, "
-		"resulting BS power: %d dBm%s",
-		trx->nominal_power, trx->max_power_red,
-		trx->nominal_power - trx->max_power_red, VTY_NEWLINE);
-	vty_out(vty, "  NM State: ");
-	net_dump_nmstate(vty, &trx->mo.nm_state);
-	vty_out(vty, "  Baseband Transceiver NM State: ");
-	net_dump_nmstate(vty, &trx->bb_transc.mo.nm_state);
-	if (is_ipaccess_bts(trx->bts)) {
-		vty_out(vty, "  ip.access stream ID: 0x%02x%s",
-			trx->rsl_tei, VTY_NEWLINE);
-	} else {
-		vty_out(vty, "  E1 Signalling Link:%s", VTY_NEWLINE);
-		e1isl_dump_vty(vty, trx->rsl_link);
-	}
-}
-
-DEFUN(show_trx,
-      show_trx_cmd,
-      "show trx [<0-255>] [<0-255>]",
-	SHOW_STR "Display information about a TRX\n"
-	"BTS Number\n"
-	"TRX Number\n")
-{
-	struct gsm_network *net = gsmnet_from_vty(vty);
-	struct gsm_bts *bts = NULL;
-	struct gsm_bts_trx *trx;
-	int bts_nr, trx_nr;
-
-	if (argc >= 1) {
-		/* use the BTS number that the user has specified */
-		bts_nr = atoi(argv[0]);
-		if (bts_nr >= net->num_bts) {
-			vty_out(vty, "%% can't find BTS '%s'%s", argv[0],
-				VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-		bts = gsm_bts_num(net, bts_nr);
-	}
-	if (argc >= 2) {
-		trx_nr = atoi(argv[1]);
-		if (trx_nr >= bts->num_trx) {
-			vty_out(vty, "%% can't find TRX '%s'%s", argv[1],
-				VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-		trx = gsm_bts_trx_num(bts, trx_nr);
-		trx_dump_vty(vty, trx);
-		return CMD_SUCCESS;
-	}
-	if (bts) {
-		/* print all TRX in this BTS */
-		for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) {
-			trx = gsm_bts_trx_num(bts, trx_nr);
-			trx_dump_vty(vty, trx);
-		}
-		return CMD_SUCCESS;
-	}
-
-	for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) {
-		bts = gsm_bts_num(net, bts_nr);
-		for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) {
-			trx = gsm_bts_trx_num(bts, trx_nr);
-			trx_dump_vty(vty, trx);
-		}
-	}
-
-	return CMD_SUCCESS;
-}
-
-
-static void ts_dump_vty(struct vty *vty, struct gsm_bts_trx_ts *ts)
-{
-	vty_out(vty, "BTS %u, TRX %u, Timeslot %u, phys cfg %s, TSC %u",
-		ts->trx->bts->nr, ts->trx->nr, ts->nr,
-		gsm_pchan_name(ts->pchan), gsm_ts_tsc(ts));
-	if (ts->pchan == GSM_PCHAN_TCH_F_PDCH)
-		vty_out(vty, " (%s mode)",
-			ts->flags & TS_F_PDCH_ACTIVE ? "PDCH" : "TCH/F");
-	vty_out(vty, "%s", VTY_NEWLINE);
-	vty_out(vty, "  NM State: ");
-	net_dump_nmstate(vty, &ts->mo.nm_state);
-	if (!is_ipaccess_bts(ts->trx->bts))
-		vty_out(vty, "  E1 Line %u, Timeslot %u, Subslot %u%s",
-			ts->e1_link.e1_nr, ts->e1_link.e1_ts,
-			ts->e1_link.e1_ts_ss, VTY_NEWLINE);
-}
-
-DEFUN(show_ts,
-      show_ts_cmd,
-      "show timeslot [<0-255>] [<0-255>] [<0-7>]",
-	SHOW_STR "Display information about a TS\n"
-	"BTS Number\n" "TRX Number\n" "Timeslot Number\n")
-{
-	struct gsm_network *net = gsmnet_from_vty(vty);
-	struct gsm_bts *bts = NULL;
-	struct gsm_bts_trx *trx = NULL;
-	struct gsm_bts_trx_ts *ts = NULL;
-	int bts_nr, trx_nr, ts_nr;
-
-	if (argc >= 1) {
-		/* use the BTS number that the user has specified */
-		bts_nr = atoi(argv[0]);
-		if (bts_nr >= net->num_bts) {
-			vty_out(vty, "%% can't find BTS '%s'%s", argv[0],
-				VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-		bts = gsm_bts_num(net, bts_nr);
-	}
-	if (argc >= 2) {
-		trx_nr = atoi(argv[1]);
-		if (trx_nr >= bts->num_trx) {
-			vty_out(vty, "%% can't find TRX '%s'%s", argv[1],
-				VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-		trx = gsm_bts_trx_num(bts, trx_nr);
-	}
-	if (argc >= 3) {
-		ts_nr = atoi(argv[2]);
-		if (ts_nr >= TRX_NR_TS) {
-			vty_out(vty, "%% can't find TS '%s'%s", argv[2],
-				VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-		/* Fully Specified: print and exit */
-		ts = &trx->ts[ts_nr];
-		ts_dump_vty(vty, ts);
-		return CMD_SUCCESS;
-	}
-
-	if (bts && trx) {
-		/* Iterate over all TS in this TRX */
-		for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) {
-			ts = &trx->ts[ts_nr];
-			ts_dump_vty(vty, ts);
-		}
-	} else if (bts) {
-		/* Iterate over all TRX in this BTS, TS in each TRX */
-		for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) {
-			trx = gsm_bts_trx_num(bts, trx_nr);
-			for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) {
-				ts = &trx->ts[ts_nr];
-				ts_dump_vty(vty, ts);
-			}
-		}
-	} else {
-		/* Iterate over all BTS, TRX in each BTS, TS in each TRX */
-		for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) {
-			bts = gsm_bts_num(net, bts_nr);
-			for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) {
-				trx = gsm_bts_trx_num(bts, trx_nr);
-				for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) {
-					ts = &trx->ts[ts_nr];
-					ts_dump_vty(vty, ts);
-				}
-			}
-		}
-	}
-
-	return CMD_SUCCESS;
-}
-
-static void subscr_dump_vty(struct vty *vty, struct vlr_subscr *vsub)
-{
-	OSMO_ASSERT(vsub);
-	if (strlen(vsub->name))
-		vty_out(vty, "    Name: '%s'%s", vsub->name, VTY_NEWLINE);
-	if (strlen(vsub->msisdn))
-		vty_out(vty, "    Extension: %s%s", vsub->msisdn,
-			VTY_NEWLINE);
-	if (strlen(vsub->imsi))
-		vty_out(vty, "    IMSI: %s%s", vsub->imsi, VTY_NEWLINE);
-	if (vsub->tmsi != GSM_RESERVED_TMSI)
-		vty_out(vty, "    TMSI: %08X%s", vsub->tmsi,
-			VTY_NEWLINE);
-	if (vsub->tmsi_new != GSM_RESERVED_TMSI)
-		vty_out(vty, "    new TMSI: %08X%s", vsub->tmsi_new,
-			VTY_NEWLINE);
-
-	vty_out(vty, "    Use count: %u%s", vsub->use_count, VTY_NEWLINE);
-}
-
-static void bsc_subscr_dump_vty(struct vty *vty, struct bsc_subscr *bsub)
-{
-	if (strlen(bsub->imsi))
-		vty_out(vty, "    IMSI: %s%s", bsub->imsi, VTY_NEWLINE);
-	if (bsub->tmsi != GSM_RESERVED_TMSI)
-		vty_out(vty, "    TMSI: 0x%08x%s", bsub->tmsi,
-			VTY_NEWLINE);
-	vty_out(vty, "    Use count: %d%s", bsub->use_count, VTY_NEWLINE);
-}
-
-static void meas_rep_dump_uni_vty(struct vty *vty,
-				  struct gsm_meas_rep_unidir *mru,
-				  const char *prefix,
-				  const char *dir)
-{
-	vty_out(vty, "%s  RXL-FULL-%s: %4d dBm, RXL-SUB-%s: %4d dBm ",
-		prefix, dir, rxlev2dbm(mru->full.rx_lev),
-			dir, rxlev2dbm(mru->sub.rx_lev));
-	vty_out(vty, "RXQ-FULL-%s: %d, RXQ-SUB-%s: %d%s",
-		dir, mru->full.rx_qual, dir, mru->sub.rx_qual,
-		VTY_NEWLINE);
-}
-
-static void meas_rep_dump_vty(struct vty *vty, struct gsm_meas_rep *mr,
-			      const char *prefix)
-{
-	vty_out(vty, "%sMeasurement Report:%s", prefix, VTY_NEWLINE);
-	vty_out(vty, "%s  Flags: %s%s%s%s%s", prefix,
-			mr->flags & MEAS_REP_F_UL_DTX ? "DTXu " : "",
-			mr->flags & MEAS_REP_F_DL_DTX ? "DTXd " : "",
-			mr->flags & MEAS_REP_F_FPC ? "FPC " : "",
-			mr->flags & MEAS_REP_F_DL_VALID ? " " : "DLinval ",
-			VTY_NEWLINE);
-	if (mr->flags & MEAS_REP_F_MS_TO)
-		vty_out(vty, "%s  MS Timing Offset: %d%s", prefix, mr->ms_timing_offset, VTY_NEWLINE);
-	if (mr->flags & MEAS_REP_F_MS_L1)
-		vty_out(vty, "%s  L1 MS Power: %u dBm, Timing Advance: %u%s",
-			prefix, mr->ms_l1.pwr, mr->ms_l1.ta, VTY_NEWLINE);
-	if (mr->flags & MEAS_REP_F_DL_VALID)
-		meas_rep_dump_uni_vty(vty, &mr->dl, prefix, "dl");
-	meas_rep_dump_uni_vty(vty, &mr->ul, prefix, "ul");
-}
-
-/* FIXME: move this to libosmogsm */
-static const struct value_string gsm48_cmode_names[] = {
-	{ GSM48_CMODE_SIGN,		"signalling" },
-	{ GSM48_CMODE_SPEECH_V1,	"FR or HR" },
-	{ GSM48_CMODE_SPEECH_EFR,	"EFR" },
-	{ GSM48_CMODE_SPEECH_AMR,	"AMR" },
-	{ GSM48_CMODE_DATA_14k5,	"CSD(14k5)" },
-	{ GSM48_CMODE_DATA_12k0,	"CSD(12k0)" },
-	{ GSM48_CMODE_DATA_6k0,		"CSD(6k0)" },
-	{ GSM48_CMODE_DATA_3k6,		"CSD(3k6)" },
-	{ 0, NULL }
-};
-
-/* call vty_out() to print a string like " as TCH/H" for dynamic timeslots.
- * Don't do anything if the ts is not dynamic. */
-static void vty_out_dyn_ts_status(struct vty *vty, struct gsm_bts_trx_ts *ts)
-{
-	switch (ts->pchan) {
-	case GSM_PCHAN_TCH_F_TCH_H_PDCH:
-		if (ts->dyn.pchan_is == ts->dyn.pchan_want)
-			vty_out(vty, " as %s",
-				gsm_pchan_name(ts->dyn.pchan_is));
-		else
-			vty_out(vty, " switching %s -> %s",
-				gsm_pchan_name(ts->dyn.pchan_is),
-				gsm_pchan_name(ts->dyn.pchan_want));
-		break;
-	case GSM_PCHAN_TCH_F_PDCH:
-		if ((ts->flags & TS_F_PDCH_PENDING_MASK) == 0)
-			vty_out(vty, " as %s",
-				(ts->flags & TS_F_PDCH_ACTIVE)? "PDCH"
-							      : "TCH/F");
-		else
-			vty_out(vty, " switching %s -> %s",
-				(ts->flags & TS_F_PDCH_ACTIVE)? "PDCH"
-							      : "TCH/F",
-				(ts->flags & TS_F_PDCH_ACT_PENDING)? "PDCH"
-								   : "TCH/F");
-		break;
-	default:
-		/* no dyn ts */
-		break;
-	}
-}
-
-static void lchan_dump_full_vty(struct vty *vty, struct gsm_lchan *lchan)
-{
-	int idx;
-
-	vty_out(vty, "BTS %u, TRX %u, Timeslot %u, Lchan %u: Type %s%s",
-		lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
-		lchan->nr, gsm_lchant_name(lchan->type), VTY_NEWLINE);
-	/* show dyn TS details, if applicable */
-	switch (lchan->ts->pchan) {
-	case GSM_PCHAN_TCH_F_TCH_H_PDCH:
-		vty_out(vty, "  Osmocom Dyn TS:");
-		vty_out_dyn_ts_status(vty, lchan->ts);
-		vty_out(vty, VTY_NEWLINE);
-		break;
-	case GSM_PCHAN_TCH_F_PDCH:
-		vty_out(vty, "  IPACC Dyn PDCH TS:");
-		vty_out_dyn_ts_status(vty, lchan->ts);
-		vty_out(vty, VTY_NEWLINE);
-		break;
-	default:
-		/* no dyn ts */
-		break;
-	}
-	vty_out(vty, "  Connection: %u, State: %s%s%s%s",
-		lchan->conn ? 1: 0,
-		gsm_lchans_name(lchan->state),
-		lchan->state == LCHAN_S_BROKEN ? " Error reason: " : "",
-		lchan->state == LCHAN_S_BROKEN ? lchan->broken_reason : "",
-		VTY_NEWLINE);
-	vty_out(vty, "  BS Power: %u dBm, MS Power: %u dBm%s",
-		lchan->ts->trx->nominal_power - lchan->ts->trx->max_power_red
-		- lchan->bs_power*2,
-		ms_pwr_dbm(lchan->ts->trx->bts->band, lchan->ms_power),
-		VTY_NEWLINE);
-	vty_out(vty, "  Channel Mode / Codec: %s%s",
-		get_value_string(gsm48_cmode_names, lchan->tch_mode),
-		VTY_NEWLINE);
-	if (lchan->conn && lchan->conn->vsub) {
-		vty_out(vty, "  Subscriber:%s", VTY_NEWLINE);
-		subscr_dump_vty(vty, lchan->conn->vsub);
-	} else
-		vty_out(vty, "  No Subscriber%s", VTY_NEWLINE);
-	if (is_ipaccess_bts(lchan->ts->trx->bts)) {
-		struct in_addr ia;
-		ia.s_addr = htonl(lchan->abis_ip.bound_ip);
-		vty_out(vty, "  Bound IP: %s Port %u RTP_TYPE2=%u CONN_ID=%u%s",
-			inet_ntoa(ia), lchan->abis_ip.bound_port,
-			lchan->abis_ip.rtp_payload2, lchan->abis_ip.conn_id,
-			VTY_NEWLINE);
-	}
-
-	/* we want to report the last measurement report */
-	idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep),
-			       lchan->meas_rep_idx, 1);
-	meas_rep_dump_vty(vty, &lchan->meas_rep[idx], "  ");
-}
-
-static void lchan_dump_short_vty(struct vty *vty, struct gsm_lchan *lchan)
-{
-	struct gsm_meas_rep *mr;
-	int idx;
-
-	/* we want to report the last measurement report */
-	idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep),
-			       lchan->meas_rep_idx, 1);
-	mr =  &lchan->meas_rep[idx];
-
-	vty_out(vty, "BTS %u, TRX %u, Timeslot %u %s",
-		lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
-		gsm_pchan_name(lchan->ts->pchan));
-	vty_out_dyn_ts_status(vty, lchan->ts);
-	vty_out(vty, ", Lchan %u, Type %s, State %s - "
-		"L1 MS Power: %u dBm RXL-FULL-dl: %4d dBm RXL-FULL-ul: %4d dBm%s",
-		lchan->nr,
-		gsm_lchant_name(lchan->type), gsm_lchans_name(lchan->state),
-		mr->ms_l1.pwr,
-		rxlev2dbm(mr->dl.full.rx_lev),
-		rxlev2dbm(mr->ul.full.rx_lev),
-		VTY_NEWLINE);
-}
-
-
-static int dump_lchan_trx_ts(struct gsm_bts_trx_ts *ts, struct vty *vty,
-			     void (*dump_cb)(struct vty *, struct gsm_lchan *))
-{
-	int lchan_nr;
-	for (lchan_nr = 0; lchan_nr < TS_MAX_LCHAN; lchan_nr++) {
-		struct gsm_lchan *lchan = &ts->lchan[lchan_nr];
-		if ((lchan->type == GSM_LCHAN_NONE) && (lchan->state == LCHAN_S_NONE))
-			continue;
-		dump_cb(vty, lchan);
-	}
-
-	return CMD_SUCCESS;
-}
-
-static int dump_lchan_trx(struct gsm_bts_trx *trx, struct vty *vty,
-			  void (*dump_cb)(struct vty *, struct gsm_lchan *))
-{
-	int ts_nr;
-
-	for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) {
-		struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
-		dump_lchan_trx_ts(ts, vty, dump_cb);
-	}
-
-	return CMD_SUCCESS;
-}
-
-static int dump_lchan_bts(struct gsm_bts *bts, struct vty *vty,
-			  void (*dump_cb)(struct vty *, struct gsm_lchan *))
-{
-	int trx_nr;
-
-	for (trx_nr = 0; trx_nr < bts->num_trx; trx_nr++) {
-		struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, trx_nr);
-		dump_lchan_trx(trx, vty, dump_cb);
-	}
-
-	return CMD_SUCCESS;
-}
-
-static int lchan_summary(struct vty *vty, int argc, const char **argv,
-			 void (*dump_cb)(struct vty *, struct gsm_lchan *))
-{
-	struct gsm_network *net = gsmnet_from_vty(vty);
-	struct gsm_bts *bts;
-	struct gsm_bts_trx *trx;
-	struct gsm_bts_trx_ts *ts;
-	struct gsm_lchan *lchan;
-	int bts_nr, trx_nr, ts_nr, lchan_nr;
-
-	if (argc >= 1) {
-		/* use the BTS number that the user has specified */
-		bts_nr = atoi(argv[0]);
-		if (bts_nr >= net->num_bts) {
-			vty_out(vty, "%% can't find BTS %s%s", argv[0],
-				VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-		bts = gsm_bts_num(net, bts_nr);
-
-		if (argc == 1)
-			return dump_lchan_bts(bts, vty, dump_cb);
-	}
-	if (argc >= 2) {
-		trx_nr = atoi(argv[1]);
-		if (trx_nr >= bts->num_trx) {
-			vty_out(vty, "%% can't find TRX %s%s", argv[1],
-				VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-		trx = gsm_bts_trx_num(bts, trx_nr);
-
-		if (argc == 2)
-			return dump_lchan_trx(trx, vty, dump_cb);
-	}
-	if (argc >= 3) {
-		ts_nr = atoi(argv[2]);
-		if (ts_nr >= TRX_NR_TS) {
-			vty_out(vty, "%% can't find TS %s%s", argv[2],
-				VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-		ts = &trx->ts[ts_nr];
-
-		if (argc == 3)
-			return dump_lchan_trx_ts(ts, vty, dump_cb);
-	}
-	if (argc >= 4) {
-		lchan_nr = atoi(argv[3]);
-		if (lchan_nr >= TS_MAX_LCHAN) {
-			vty_out(vty, "%% can't find LCHAN %s%s", argv[3],
-				VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-		lchan = &ts->lchan[lchan_nr];
-		dump_cb(vty, lchan);
-		return CMD_SUCCESS;
-	}
-
-
-	for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) {
-		bts = gsm_bts_num(net, bts_nr);
-		dump_lchan_bts(bts, vty, dump_cb);
-	}
-
-	return CMD_SUCCESS;
-}
-
-
-DEFUN(show_lchan,
-      show_lchan_cmd,
-      "show lchan [<0-255>] [<0-255>] [<0-7>] [lchan_nr]",
-	SHOW_STR "Display information about a logical channel\n"
-	"BTS Number\n" "TRX Number\n" "Timeslot Number\n"
-	LCHAN_NR_STR)
-
-{
-	return lchan_summary(vty, argc, argv, lchan_dump_full_vty);
-}
-
-DEFUN(show_lchan_summary,
-      show_lchan_summary_cmd,
-      "show lchan summary [<0-255>] [<0-255>] [<0-7>] [lchan_nr]",
-	SHOW_STR "Display information about a logical channel\n"
-        "Short summary\n"
-	"BTS Number\n" "TRX Number\n" "Timeslot Number\n"
-        LCHAN_NR_STR)
-{
-	return lchan_summary(vty, argc, argv, lchan_dump_short_vty);
-}
-
-DEFUN(show_subscr_conn,
-      show_subscr_conn_cmd,
-      "show conns",
-      SHOW_STR "Display currently active subscriber connections\n")
-{
-	struct gsm_subscriber_connection *conn;
-	struct gsm_network *net = gsmnet_from_vty(vty);
-	bool no_conns = true;
-	unsigned int count = 0;
-
-	vty_out(vty, "Active subscriber connections: %s", VTY_NEWLINE);
-
-	llist_for_each_entry(conn, &net->subscr_conns, entry) {
-		vty_out(vty, "conn nr #%u:%s", count, VTY_NEWLINE);
-		lchan_dump_full_vty(vty, conn->lchan);
-		no_conns = false;
-		count++;
-	}
-
-	if (no_conns)
-		vty_out(vty, "None%s", VTY_NEWLINE);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(handover_subscr_conn,
-      handover_subscr_conn_cmd,
-      "handover <0-255> <0-255> <0-7> LCHAN_NR <0-255>",
-      "Handover subscriber connection to other BTS\n"
-      "BTS Number (current)\n" "TRX Number\n" "Timeslot Number\n"
-      LCHAN_NR_STR "BTS Number (new)\n")
-{
-	struct gsm_network *net = gsmnet_from_vty(vty);
-	struct gsm_subscriber_connection *conn;
-	struct gsm_bts *bts;
-	struct gsm_bts *new_bts = NULL;
-	unsigned int bts_nr = atoi(argv[0]);
-	unsigned int trx_nr = atoi(argv[1]);
-	unsigned int ts_nr = atoi(argv[2]);
-	unsigned int ss_nr = atoi(argv[3]);
-	unsigned int bts_nr_new = atoi(argv[4]);
-
-	/* Lookup the BTS where we want to handover to */
-	llist_for_each_entry(bts, &net->bts_list, list) {
-		if (bts->nr == bts_nr_new) {
-			new_bts = bts;
-			break;
-		}
-	}
-
-	if (!new_bts) {
-		vty_out(vty, "Unable to trigger handover,"
-			"specified bts #%u does not exist %s", bts_nr_new,
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	/* Find the connection/lchan that we want to handover */
-	llist_for_each_entry(conn, &net->subscr_conns, entry) {
-		if (conn->bts->nr == bts_nr &&
-		    conn->lchan->ts->trx->nr == trx_nr &&
-		    conn->lchan->ts->nr == ts_nr && conn->lchan->nr == ss_nr) {
-			vty_out(vty, "starting handover for lchan %s...%s",
-				conn->lchan->name, VTY_NEWLINE);
-			lchan_dump_full_vty(vty, conn->lchan);
-			bsc_handover_start(conn->lchan, new_bts);
-			return CMD_SUCCESS;
-		}
-	}
-
-	vty_out(vty, "Unable to trigger handover,"
-		"specified connection (bts=%u,trx=%u,ts=%u,ss=%u) does not exist%s",
-		bts_nr, trx_nr, ts_nr, ss_nr, VTY_NEWLINE);
-
-	return CMD_WARNING;
-}
-
-static void paging_dump_vty(struct vty *vty, struct gsm_paging_request *pag)
-{
-	vty_out(vty, "Paging on BTS %u%s", pag->bts->nr, VTY_NEWLINE);
-	bsc_subscr_dump_vty(vty, pag->bsub);
-}
-
-static void bts_paging_dump_vty(struct vty *vty, struct gsm_bts *bts)
-{
-	struct gsm_paging_request *pag;
-
-	if (!bts->paging.bts)
-		return;
-
-	llist_for_each_entry(pag, &bts->paging.pending_requests, entry)
-		paging_dump_vty(vty, pag);
-}
-
-DEFUN(show_paging,
-      show_paging_cmd,
-      "show paging [<0-255>]",
-	SHOW_STR "Display information about paging reuqests of a BTS\n"
-	"BTS Number\n")
-{
-	struct gsm_network *net = gsmnet_from_vty(vty);
-	struct gsm_bts *bts;
-	int bts_nr;
-
-	if (argc >= 1) {
-		/* use the BTS number that the user has specified */
-		bts_nr = atoi(argv[0]);
-		if (bts_nr >= net->num_bts) {
-			vty_out(vty, "%% can't find BTS %s%s", argv[0],
-				VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-		bts = gsm_bts_num(net, bts_nr);
-		bts_paging_dump_vty(vty, bts);
-		
-		return CMD_SUCCESS;
-	}
-	for (bts_nr = 0; bts_nr < net->num_bts; bts_nr++) {
-		bts = gsm_bts_num(net, bts_nr);
-		bts_paging_dump_vty(vty, bts);
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_paging_group,
-      show_paging_group_cmd,
-      "show paging-group <0-255> IMSI",
-      SHOW_STR "Display the paging group\n"
-      "BTS Number\n" "IMSI\n")
-{
-	struct gsm_network *net = gsmnet_from_vty(vty);
-	struct gsm_bts *bts;
-	unsigned int page_group;
-	int bts_nr = atoi(argv[0]);
-
-	if (bts_nr >= net->num_bts) {
-		vty_out(vty, "%% can't find BTS %s%s", argv[0], VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts = gsm_bts_num(net, bts_nr);
-	if (!bts) {
-		vty_out(vty, "%% can't find BTS %s%s", argv[0], VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	page_group = gsm0502_calc_paging_group(&bts->si_common.chan_desc,
-						str_to_imsi(argv[1]));
-	vty_out(vty, "%%Paging group for IMSI %" PRIu64 " on BTS #%d is %u%s",
-		str_to_imsi(argv[1]), bts->nr,
-		page_group, VTY_NEWLINE);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_neci,
-      cfg_net_neci_cmd,
-      "neci (0|1)",
-	"New Establish Cause Indication\n"
-	"Don't set the NECI bit\n" "Set the NECI bit\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-
-	gsmnet->neci = atoi(argv[0]);
-	gsm_net_update_ctype(gsmnet);
-	return CMD_SUCCESS;
-}
-
-#define HANDOVER_STR	"Handover Options\n"
-
-DEFUN(cfg_net_handover, cfg_net_handover_cmd,
-      "handover (0|1)",
-	HANDOVER_STR
-	"Don't perform in-call handover\n"
-	"Perform in-call handover\n")
-{
-	int enable = atoi(argv[0]);
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-
-	if (enable && ipacc_rtp_direct) {
-		vty_out(vty, "%% Cannot enable handover unless RTP Proxy mode "
-			"is enabled by using the -P command line option%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-	gsmnet->handover.active = enable;
-
-	return CMD_SUCCESS;
-}
-
-#define HO_WIN_STR HANDOVER_STR "Measurement Window\n"
-#define HO_WIN_RXLEV_STR HO_WIN_STR "Received Level Averaging\n"
-#define HO_WIN_RXQUAL_STR HO_WIN_STR "Received Quality Averaging\n"
-#define HO_PBUDGET_STR HANDOVER_STR "Power Budget\n"
-#define HO_AVG_COUNT_STR "Amount to use for Averaging\n"
-
-DEFUN(cfg_net_ho_win_rxlev_avg, cfg_net_ho_win_rxlev_avg_cmd,
-      "handover window rxlev averaging <1-10>",
-	HO_WIN_RXLEV_STR
-	"How many RxLev measurements are used for averaging\n"
-	HO_AVG_COUNT_STR)
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	gsmnet->handover.win_rxlev_avg = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_ho_win_rxqual_avg, cfg_net_ho_win_rxqual_avg_cmd,
-      "handover window rxqual averaging <1-10>",
-	HO_WIN_RXQUAL_STR
-	"How many RxQual measurements are used for averaging\n"
-	HO_AVG_COUNT_STR)
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	gsmnet->handover.win_rxqual_avg = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_ho_win_rxlev_neigh_avg, cfg_net_ho_win_rxlev_avg_neigh_cmd,
-      "handover window rxlev neighbor averaging <1-10>",
-	HO_WIN_RXLEV_STR "Neighbor\n"
-	"How many RxQual measurements are used for averaging\n"
-	HO_AVG_COUNT_STR)
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	gsmnet->handover.win_rxlev_avg_neigh = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_ho_pwr_interval, cfg_net_ho_pwr_interval_cmd,
-      "handover power budget interval <1-99>",
-	HO_PBUDGET_STR
-	"How often to check if we have a better cell (SACCH frames)\n"
-	"Interval\n" "Number\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	gsmnet->handover.pwr_interval = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_ho_pwr_hysteresis, cfg_net_ho_pwr_hysteresis_cmd,
-      "handover power budget hysteresis <0-999>",
-	HO_PBUDGET_STR
-	"How many dB does a neighbor to be stronger to become a HO candidate\n"
-	"Hysteresis\n" "Number\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	gsmnet->handover.pwr_hysteresis = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_ho_max_distance, cfg_net_ho_max_distance_cmd,
-      "handover maximum distance <0-9999>",
-	HANDOVER_STR
-	"How big is the maximum timing advance before HO is forced\n"
-	"Distance\n" "Number\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	gsmnet->handover.max_distance = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_pag_any_tch,
-      cfg_net_pag_any_tch_cmd,
-      "paging any use tch (0|1)",
-      "Assign a TCH when receiving a Paging Any request\n"
-      "Any Channel\n" "Use\n" "TCH\n"
-      "Do not use TCH for Paging Request Any\n"
-      "Do use TCH for Paging Request Any\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	gsmnet->pag_any_tch = atoi(argv[0]);
-	gsm_net_update_ctype(gsmnet);
-	return CMD_SUCCESS;
-}
-
-#define DEFAULT_TIMER(number) GSM_T##number##_DEFAULT
-/* Add another expansion so that DEFAULT_TIMER() becomes its value */
-#define EXPAND_AND_STRINGIFY(x) OSMO_STRINGIFY(x)
-
-#define DECLARE_TIMER(number, doc) \
-    DEFUN(cfg_net_T##number,					\
-      cfg_net_T##number##_cmd,					\
-      "timer t" #number  " (default|<1-65535>)",		\
-      "Configure GSM Timers\n"					\
-      doc " (default: " EXPAND_AND_STRINGIFY(DEFAULT_TIMER(number)) " seconds)\n" \
-      "Set to default timer value"				\
-	  " (" EXPAND_AND_STRINGIFY(DEFAULT_TIMER(number)) " seconds)\n" \
-      "Timer Value in seconds\n")				\
-{								\
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);	\
-	int value;						\
-	if (strcmp(argv[0], "default") == 0)			\
-		value = DEFAULT_TIMER(number);			\
-	else							\
-		value = atoi(argv[0]);				\
-								\
-	gsmnet->T##number = value;				\
-	return CMD_SUCCESS;					\
-}
-
-DECLARE_TIMER(3101, "Set the timeout value for IMMEDIATE ASSIGNMENT")
-DECLARE_TIMER(3103, "Set the timeout value for HANDOVER")
-DECLARE_TIMER(3105, "Set the timer for repetition of PHYSICAL INFORMATION")
-DECLARE_TIMER(3107, "Currently not used")
-DECLARE_TIMER(3109, "Set the RSL SACCH deactivation timeout")
-DECLARE_TIMER(3111, "Set the RSL timeout to wait before releasing the RF Channel")
-DECLARE_TIMER(3113, "Set the time to try paging a subscriber")
-DECLARE_TIMER(3115, "Currently not used")
-DECLARE_TIMER(3117, "Currently not used")
-DECLARE_TIMER(3119, "Currently not used")
-DECLARE_TIMER(3122, "Waiting time (seconds) after IMM ASS REJECT")
-DECLARE_TIMER(3141, "Currently not used")
-
-DEFUN_DEPRECATED(cfg_net_dtx,
-		 cfg_net_dtx_cmd,
-		 "dtx-used (0|1)",
-		 ".HIDDEN\n""Obsolete\n""Obsolete\n")
-{
-	vty_out(vty, "%% 'dtx-used' is now deprecated: use dtx * "
-		"configuration options of BTS instead%s", VTY_NEWLINE);
-       return CMD_SUCCESS;
-}
-
-/* per-BTS configuration */
-DEFUN(cfg_bts,
-      cfg_bts_cmd,
-      "bts <0-255>",
-      "Select a BTS to configure\n"
-	"BTS Number\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	int bts_nr = atoi(argv[0]);
-	struct gsm_bts *bts;
-
-	if (bts_nr > gsmnet->num_bts) {
-		vty_out(vty, "%% The next unused BTS number is %u%s",
-			gsmnet->num_bts, VTY_NEWLINE);
-		return CMD_WARNING;
-	} else if (bts_nr == gsmnet->num_bts) {
-		/* allocate a new one */
-		bts = gsm_bts_alloc_register(gsmnet, GSM_BTS_TYPE_UNKNOWN,
-					     HARDCODED_BSIC);
-	} else
-		bts = gsm_bts_num(gsmnet, bts_nr);
-
-	if (!bts) {
-		vty_out(vty, "%% Unable to allocate BTS %u%s",
-			gsmnet->num_bts, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	vty->index = bts;
-	vty->index_sub = &bts->description;
-	vty->node = BTS_NODE;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_type,
-      cfg_bts_type_cmd,
-      "type TYPE", /* dynamically created */
-      "Set the BTS type\n" "Type\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int rc;
-
-	rc = gsm_set_bts_type(bts, str2btstype(argv[0]));
-	if (rc < 0)
-		return CMD_WARNING;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_band,
-      cfg_bts_band_cmd,
-      "band BAND",
-      "Set the frequency band of this BTS\n" "Frequency band\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int band = gsm_band_parse(argv[0]);
-
-	if (band < 0) {
-		vty_out(vty, "%% BAND %d is not a valid GSM band%s",
-			band, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts->band = band;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_dtxu, cfg_bts_dtxu_cmd, "dtx uplink [force]",
-      "Configure discontinuous transmission\n"
-      "Enable Uplink DTX for this BTS\n"
-      "MS 'shall' use DTXu instead of 'may' use (might not be supported by "
-      "older phones).\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	bts->dtxu = (argc > 0) ? GSM48_DTX_SHALL_BE_USED : GSM48_DTX_MAY_BE_USED;
-	if (!is_ipaccess_bts(bts))
-		vty_out(vty, "%% DTX enabled on non-IP BTS: this configuration "
-			"neither supported nor tested!%s", VTY_NEWLINE);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_no_dtxu, cfg_bts_no_dtxu_cmd, "no dtx uplink",
-      NO_STR
-      "Configure discontinuous transmission\n"
-      "Disable Uplink DTX for this BTS\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	bts->dtxu = GSM48_DTX_SHALL_NOT_BE_USED;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_dtxd, cfg_bts_dtxd_cmd, "dtx downlink",
-      "Configure discontinuous transmission\n"
-      "Enable Downlink DTX for this BTS\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	bts->dtxd = true;
-	if (!is_ipaccess_bts(bts))
-		vty_out(vty, "%% DTX enabled on non-IP BTS: this configuration "
-			"neither supported nor tested!%s", VTY_NEWLINE);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_no_dtxd, cfg_bts_no_dtxd_cmd, "no dtx downlink",
-      NO_STR
-      "Configure discontinuous transmission\n"
-      "Disable Downlink DTX for this BTS\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	bts->dtxd = false;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ci,
-      cfg_bts_ci_cmd,
-      "cell_identity <0-65535>",
-      "Set the Cell identity of this BTS\n" "Cell Identity\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int ci = atoi(argv[0]);
-
-	if (ci < 0 || ci > 0xffff) {
-		vty_out(vty, "%% CI %d is not in the valid range (0-65535)%s",
-			ci, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-	bts->cell_identity = ci;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_lac,
-      cfg_bts_lac_cmd,
-      "location_area_code <0-65535>",
-      "Set the Location Area Code (LAC) of this BTS\n" "LAC\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int lac = atoi(argv[0]);
-
-	if (lac < 0 || lac > 0xffff) {
-		vty_out(vty, "%% LAC %d is not in the valid range (0-65535)%s",
-			lac, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (lac == GSM_LAC_RESERVED_DETACHED || lac == GSM_LAC_RESERVED_ALL_BTS) {
-		vty_out(vty, "%% LAC %d is reserved by GSM 04.08%s",
-			lac, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts->location_area_code = lac;
-
-	return CMD_SUCCESS;
-}
-
-
-/* compatibility wrapper for old config files */
-DEFUN_HIDDEN(cfg_bts_tsc,
-      cfg_bts_tsc_cmd,
-      "training_sequence_code <0-7>",
-      "Set the Training Sequence Code (TSC) of this BTS\n" "TSC\n")
-{
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_bsic,
-      cfg_bts_bsic_cmd,
-      "base_station_id_code <0-63>",
-      "Set the Base Station Identity Code (BSIC) of this BTS\n"
-      "BSIC of this BTS\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int bsic = atoi(argv[0]);
-
-	if (bsic < 0 || bsic > 0x3f) {
-		vty_out(vty, "%% BSIC %d is not in the valid range (0-255)%s",
-			bsic, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-	bts->bsic = bsic;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_unit_id,
-      cfg_bts_unit_id_cmd,
-      "ip.access unit_id <0-65534> <0-255>",
-      "Abis/IP specific options\n"
-      "Set the IPA BTS Unit ID\n"
-      "Unit ID (Site)\n"
-      "Unit ID (BTS)\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int site_id = atoi(argv[0]);
-	int bts_id = atoi(argv[1]);
-
-	if (!is_ipaccess_bts(bts)) {
-		vty_out(vty, "%% BTS is not of ip.access type%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts->ip_access.site_id = site_id;
-	bts->ip_access.bts_id = bts_id;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_rsl_ip,
-      cfg_bts_rsl_ip_cmd,
-      "ip.access rsl-ip A.B.C.D",
-      "Abis/IP specific options\n"
-      "Set the IPA RSL IP Address of the BSC\n"
-      "Destination IP address for RSL connection\n")
-{
-	struct gsm_bts *bts = vty->index;
-	struct in_addr ia;
-
-	if (!is_ipaccess_bts(bts)) {
-		vty_out(vty, "%% BTS is not of ip.access type%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	inet_aton(argv[0], &ia);
-	bts->ip_access.rsl_ip = ntohl(ia.s_addr);
-
-	return CMD_SUCCESS;
-}
-
-#define NOKIA_STR "Nokia *Site related commands\n"
-
-DEFUN(cfg_bts_nokia_site_skip_reset,
-      cfg_bts_nokia_site_skip_reset_cmd,
-      "nokia_site skip-reset (0|1)",
-      NOKIA_STR
-      "Skip the reset step during bootstrap process of this BTS\n"
-      "Do NOT skip the reset\n" "Skip the reset\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	if (bts->type != GSM_BTS_TYPE_NOKIA_SITE) {
-		vty_out(vty, "%% BTS is not of Nokia *Site type%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts->nokia.skip_reset = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_nokia_site_no_loc_rel_cnf,
-      cfg_bts_nokia_site_no_loc_rel_cnf_cmd,
-      "nokia_site no-local-rel-conf (0|1)",
-      NOKIA_STR
-      "Do not wait for RELease CONFirm message when releasing channel locally\n"
-      "Wait for RELease CONFirm\n" "Do not wait for RELease CONFirm\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	if (!is_nokia_bts(bts)) {
-		vty_out(vty, "%% BTS is not of Nokia *Site type%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts->nokia.no_loc_rel_cnf = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_nokia_site_bts_reset_timer_cnf,
-      cfg_bts_nokia_site_bts_reset_timer_cnf_cmd,
-      "nokia_site bts-reset-timer  <15-100>",
-      NOKIA_STR
-      "The amount of time (in sec.) between BTS_RESET is sent,\n"
-      "and the BTS is being bootstrapped.\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	if (!is_nokia_bts(bts)) {
-		vty_out(vty, "%% BTS is not of Nokia *Site type%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts->nokia.bts_reset_timer_cnf = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-#define OML_STR	"Organization & Maintenance Link\n"
-#define IPA_STR "A-bis/IP Specific Options\n"
-
-DEFUN(cfg_bts_stream_id,
-      cfg_bts_stream_id_cmd,
-      "oml ip.access stream_id <0-255> line E1_LINE",
-	OML_STR IPA_STR
-      "Set the ip.access Stream ID of the OML link of this BTS\n"
-      "Stream Identifier\n" "Virtual E1 Line Number\n" "Virtual E1 Line Number\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int stream_id = atoi(argv[0]), linenr = atoi(argv[1]);
-
-	if (!is_ipaccess_bts(bts)) {
-		vty_out(vty, "%% BTS is not of ip.access type%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts->oml_tei = stream_id;
-	/* This is used by e1inp_bind_ops callback for each BTS model. */
-	bts->oml_e1_link.e1_nr = linenr;
-
-	return CMD_SUCCESS;
-}
-
-#define OML_E1_STR OML_STR "OML E1/T1 Configuration\n"
-
-DEFUN(cfg_bts_oml_e1,
-      cfg_bts_oml_e1_cmd,
-      "oml e1 line E1_LINE timeslot <1-31> sub-slot (0|1|2|3|full)",
-	OML_E1_STR
-      "E1/T1 line number to be used for OML\n"
-      "E1/T1 line number to be used for OML\n"
-      "E1/T1 timeslot to be used for OML\n"
-      "E1/T1 timeslot to be used for OML\n"
-      "E1/T1 sub-slot to be used for OML\n"
-      "Use E1/T1 sub-slot 0\n"
-      "Use E1/T1 sub-slot 1\n"
-      "Use E1/T1 sub-slot 2\n"
-      "Use E1/T1 sub-slot 3\n"
-      "Use full E1 slot 3\n"
-      )
-{
-	struct gsm_bts *bts = vty->index;
-
-	parse_e1_link(&bts->oml_e1_link, argv[0], argv[1], argv[2]);
-
-	return CMD_SUCCESS;
-}
-
-
-DEFUN(cfg_bts_oml_e1_tei,
-      cfg_bts_oml_e1_tei_cmd,
-      "oml e1 tei <0-63>",
-	OML_E1_STR
-      "Set the TEI to be used for OML\n"
-      "TEI Number\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	bts->oml_tei = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_challoc, cfg_bts_challoc_cmd,
-      "channel allocator (ascending|descending)",
-	"Channnel Allocator\n" "Channel Allocator\n"
-	"Allocate Timeslots and Transceivers in ascending order\n"
-	"Allocate Timeslots and Transceivers in descending order\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	if (!strcmp(argv[0], "ascending"))
-		bts->chan_alloc_reverse = 0;
-	else
-		bts->chan_alloc_reverse = 1;
-
-	return CMD_SUCCESS;
-}
-
-#define RACH_STR "Random Access Control Channel\n"
-
-DEFUN(cfg_bts_rach_tx_integer,
-      cfg_bts_rach_tx_integer_cmd,
-      "rach tx integer <0-15>",
-	RACH_STR
-      "Set the raw tx integer value in RACH Control parameters IE\n"
-      "Set the raw tx integer value in RACH Control parameters IE\n"
-      "Raw tx integer value in RACH Control parameters IE\n")
-{
-	struct gsm_bts *bts = vty->index;
-	bts->si_common.rach_control.tx_integer = atoi(argv[0]) & 0xf;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_rach_max_trans,
-      cfg_bts_rach_max_trans_cmd,
-      "rach max transmission (1|2|4|7)",
-	RACH_STR
-      "Set the maximum number of RACH burst transmissions\n"
-      "Set the maximum number of RACH burst transmissions\n"
-      "Maximum number of 1 RACH burst transmissions\n"
-      "Maximum number of 2 RACH burst transmissions\n"
-      "Maximum number of 4 RACH burst transmissions\n"
-      "Maximum number of 7 RACH burst transmissions\n")
-{
-	struct gsm_bts *bts = vty->index;
-	bts->si_common.rach_control.max_trans = rach_max_trans_val2raw(atoi(argv[0]));
-	return CMD_SUCCESS;
-}
-
-#define CD_STR "Channel Description\n"
-
-DEFUN(cfg_bts_chan_desc_att,
-      cfg_bts_chan_desc_att_cmd,
-      "channel-descrption attach (0|1)",
-	CD_STR
-      "Set if attachment is required\n"
-      "Attachment is NOT required\n"
-      "Attachment is required (standard)\n")
-{
-	struct gsm_bts *bts = vty->index;
-	bts->si_common.chan_desc.att = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_chan_desc_bs_pa_mfrms,
-      cfg_bts_chan_desc_bs_pa_mfrms_cmd,
-      "channel-descrption bs-pa-mfrms <2-9>",
-	CD_STR
-      "Set number of multiframe periods for paging groups\n"
-      "Number of multiframe periods for paging groups\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int bs_pa_mfrms = atoi(argv[0]);
-
-	bts->si_common.chan_desc.bs_pa_mfrms = bs_pa_mfrms - 2;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_chan_desc_bs_ag_blks_res,
-      cfg_bts_chan_desc_bs_ag_blks_res_cmd,
-      "channel-descrption bs-ag-blks-res <0-7>",
-	CD_STR
-      "Set number of blocks reserved for access grant\n"
-      "Number of blocks reserved for access grant\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int bs_ag_blks_res = atoi(argv[0]);
-
-	bts->si_common.chan_desc.bs_ag_blks_res = bs_ag_blks_res;
-	return CMD_SUCCESS;
-}
-
-#define NM_STR "Network Management\n"
-
-DEFUN(cfg_bts_rach_nm_b_thresh,
-      cfg_bts_rach_nm_b_thresh_cmd,
-      "rach nm busy threshold <0-255>",
-	RACH_STR NM_STR
-      "Set the NM Busy Threshold\n"
-      "Set the NM Busy Threshold\n"
-      "NM Busy Threshold in dB")
-{
-	struct gsm_bts *bts = vty->index;
-	bts->rach_b_thresh = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_rach_nm_ldavg,
-      cfg_bts_rach_nm_ldavg_cmd,
-      "rach nm load average <0-65535>",
-	RACH_STR NM_STR
-      "Set the NM Loadaverage Slots value\n"
-      "Set the NM Loadaverage Slots value\n"
-      "NM Loadaverage Slots value\n")
-{
-	struct gsm_bts *bts = vty->index;
-	bts->rach_ldavg_slots = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_cell_barred, cfg_bts_cell_barred_cmd,
-      "cell barred (0|1)",
-      "Should this cell be barred from access?\n"
-      "Should this cell be barred from access?\n"
-      "Cell should NOT be barred\n"
-      "Cell should be barred\n")
-
-{
-	struct gsm_bts *bts = vty->index;
-
-	bts->si_common.rach_control.cell_bar = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_rach_ec_allowed, cfg_bts_rach_ec_allowed_cmd,
-      "rach emergency call allowed (0|1)",
-      RACH_STR
-      "Should this cell allow emergency calls?\n"
-      "Should this cell allow emergency calls?\n"
-      "Should this cell allow emergency calls?\n"
-      "Do NOT allow emergency calls\n"
-      "Allow emergency calls\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	if (atoi(argv[0]) == 0)
-		bts->si_common.rach_control.t2 |= 0x4;
-	else
-		bts->si_common.rach_control.t2 &= ~0x4;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_rach_ac_class, cfg_bts_rach_ac_class_cmd,
-      "rach access-control-class (0|1|2|3|4|5|6|7|8|9|11|12|13|14|15) (barred|allowed)",
-      RACH_STR
-      "Set access control class\n"
-      "Access control class 0\n"
-      "Access control class 1\n"
-      "Access control class 2\n"
-      "Access control class 3\n"
-      "Access control class 4\n"
-      "Access control class 5\n"
-      "Access control class 6\n"
-      "Access control class 7\n"
-      "Access control class 8\n"
-      "Access control class 9\n"
-      "Access control class 11 for PLMN use\n"
-      "Access control class 12 for security services\n"
-      "Access control class 13 for public utilities (e.g. water/gas suppliers)\n"
-      "Access control class 14 for emergency services\n"
-      "Access control class 15 for PLMN staff\n"
-      "barred to use access control class\n"
-      "allowed to use access control class\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	uint8_t control_class;
-	uint8_t allowed = 0;
-
-	if (strcmp(argv[1], "allowed") == 0)
-		allowed = 1;
-
-	control_class = atoi(argv[0]);
-	if (control_class < 8)
-		if (allowed)
-			bts->si_common.rach_control.t3 &= ~(0x1 << control_class);
-		else
-			bts->si_common.rach_control.t3 |= (0x1 << control_class);
-	else
-		if (allowed)
-			bts->si_common.rach_control.t2 &= ~(0x1 << (control_class - 8));
-		else
-			bts->si_common.rach_control.t2 |= (0x1 << (control_class - 8));
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ms_max_power, cfg_bts_ms_max_power_cmd,
-      "ms max power <0-40>",
-      "MS Options\n"
-      "Maximum transmit power of the MS\n"
-      "Maximum transmit power of the MS\n"
-      "Maximum transmit power of the MS in dBm")
-{
-	struct gsm_bts *bts = vty->index;
-
-	bts->ms_max_power = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-#define CELL_STR "Cell Parameters\n"
-
-DEFUN(cfg_bts_cell_resel_hyst, cfg_bts_cell_resel_hyst_cmd,
-      "cell reselection hysteresis <0-14>",
-      CELL_STR "Cell re-selection parameters\n"
-      "Cell Re-Selection Hysteresis in dB\n"
-      "Cell Re-Selection Hysteresis in dB")
-{
-	struct gsm_bts *bts = vty->index;
-
-	bts->si_common.cell_sel_par.cell_resel_hyst = atoi(argv[0])/2;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_rxlev_acc_min, cfg_bts_rxlev_acc_min_cmd,
-      "rxlev access min <0-63>",
-      "Minimum RxLev needed for cell access\n"
-      "Minimum RxLev needed for cell access\n"
-      "Minimum RxLev needed for cell access\n"
-      "Minimum RxLev needed for cell access (better than -110dBm)")
-{
-	struct gsm_bts *bts = vty->index;
-
-	bts->si_common.cell_sel_par.rxlev_acc_min = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_cell_bar_qualify, cfg_bts_cell_bar_qualify_cmd,
-	"cell bar qualify (0|1)",
-	CELL_STR "Cell Bar Qualify\n" "Cell Bar Qualify\n"
-	"Set CBQ to 0\n" "Set CBQ to 1\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	bts->si_common.cell_ro_sel_par.present = 1;
-	bts->si_common.cell_ro_sel_par.cbq = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_cell_resel_ofs, cfg_bts_cell_resel_ofs_cmd,
-	"cell reselection offset <0-126>",
-	CELL_STR "Cell Re-Selection Parameters\n"
-	"Cell Re-Selection Offset (CRO) in dB\n"
-	"Cell Re-Selection Offset (CRO) in dB\n"
-	)
-{
-	struct gsm_bts *bts = vty->index;
-
-	bts->si_common.cell_ro_sel_par.present = 1;
-	bts->si_common.cell_ro_sel_par.cell_resel_off = atoi(argv[0])/2;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_temp_ofs, cfg_bts_temp_ofs_cmd,
-	"temporary offset <0-60>",
-	"Cell selection temporary negative offset\n"
-	"Cell selection temporary negative offset\n"
-	"Cell selection temporary negative offset in dB")
-{
-	struct gsm_bts *bts = vty->index;
-
-	bts->si_common.cell_ro_sel_par.present = 1;
-	bts->si_common.cell_ro_sel_par.temp_offs = atoi(argv[0])/10;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_temp_ofs_inf, cfg_bts_temp_ofs_inf_cmd,
-	"temporary offset infinite",
-	"Cell selection temporary negative offset\n"
-	"Cell selection temporary negative offset\n"
-	"Sets cell selection temporary negative offset to infinity")
-{
-	struct gsm_bts *bts = vty->index;
-
-	bts->si_common.cell_ro_sel_par.present = 1;
-	bts->si_common.cell_ro_sel_par.temp_offs = 7;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_penalty_time, cfg_bts_penalty_time_cmd,
-	"penalty time <20-620>",
-	"Cell selection penalty time\n"
-	"Cell selection penalty time\n"
-	"Cell selection penalty time in seconds (by 20s increments)\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	bts->si_common.cell_ro_sel_par.present = 1;
-	bts->si_common.cell_ro_sel_par.penalty_time = (atoi(argv[0])-20)/20;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_penalty_time_rsvd, cfg_bts_penalty_time_rsvd_cmd,
-	"penalty time reserved",
-	"Cell selection penalty time\n"
-	"Cell selection penalty time\n"
-	"Set cell selection penalty time to reserved value 31, "
-		"(indicate that CELL_RESELECT_OFFSET is subtracted from C2 "
-		"and TEMPORARY_OFFSET is ignored)")
-{
-	struct gsm_bts *bts = vty->index;
-
-	bts->si_common.cell_ro_sel_par.present = 1;
-	bts->si_common.cell_ro_sel_par.penalty_time = 31;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_radio_link_timeout, cfg_bts_radio_link_timeout_cmd,
-	"radio-link-timeout <4-64>",
-	"Radio link timeout criterion (BTS side)\n"
-	"Radio link timeout value (lost SACCH block)\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	gsm_bts_set_radio_link_timeout(bts, atoi(argv[0]));
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_radio_link_timeout_inf, cfg_bts_radio_link_timeout_inf_cmd,
-	"radio-link-timeout infinite",
-	"Radio link timeout criterion (BTS side)\n"
-	"Infinite Radio link timeout value (use only for BTS RF testing)\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	if (bts->type != GSM_BTS_TYPE_OSMOBTS) {
-		vty_out(vty, "%% infinite radio link timeout not supported by this BTS%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	vty_out(vty, "%% INFINITE RADIO LINK TIMEOUT, USE ONLY FOR BTS RF TESTING%s", VTY_NEWLINE);
-	gsm_bts_set_radio_link_timeout(bts, -1);
-
-	return CMD_SUCCESS;
-}
-
-#define GPRS_TEXT	"GPRS Packet Network\n"
-
-DEFUN(cfg_bts_prs_bvci, cfg_bts_gprs_bvci_cmd,
-	"gprs cell bvci <2-65535>",
-	GPRS_TEXT
-	"GPRS Cell Settings\n"
-	"GPRS BSSGP VC Identifier\n"
-	"GPRS BSSGP VC Identifier")
-{
-	struct gsm_bts *bts = vty->index;
-
-	if (bts->gprs.mode == BTS_GPRS_NONE) {
-		vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts->gprs.cell.bvci = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_gprs_nsei, cfg_bts_gprs_nsei_cmd,
-	"gprs nsei <0-65535>",
-	GPRS_TEXT
-	"GPRS NS Entity Identifier\n"
-	"GPRS NS Entity Identifier")
-{
-	struct gsm_bts *bts = vty->index;
-
-	if (bts->gprs.mode == BTS_GPRS_NONE) {
-		vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts->gprs.nse.nsei = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-#define NSVC_TEXT "Network Service Virtual Connection (NS-VC)\n" \
-		"NSVC Logical Number\n"
-
-DEFUN(cfg_bts_gprs_nsvci, cfg_bts_gprs_nsvci_cmd,
-	"gprs nsvc <0-1> nsvci <0-65535>",
-	GPRS_TEXT NSVC_TEXT
-	"NS Virtual Connection Identifier\n"
-	"GPRS NS VC Identifier")
-{
-	struct gsm_bts *bts = vty->index;
-	int idx = atoi(argv[0]);
-
-	if (bts->gprs.mode == BTS_GPRS_NONE) {
-		vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts->gprs.nsvc[idx].nsvci = atoi(argv[1]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_gprs_nsvc_lport, cfg_bts_gprs_nsvc_lport_cmd,
-	"gprs nsvc <0-1> local udp port <0-65535>",
-	GPRS_TEXT NSVC_TEXT
-	"GPRS NS Local UDP Port\n"
-	"GPRS NS Local UDP Port\n"
-	"GPRS NS Local UDP Port\n"
-	"GPRS NS Local UDP Port Number\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int idx = atoi(argv[0]);
-
-	if (bts->gprs.mode == BTS_GPRS_NONE) {
-		vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts->gprs.nsvc[idx].local_port = atoi(argv[1]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_gprs_nsvc_rport, cfg_bts_gprs_nsvc_rport_cmd,
-	"gprs nsvc <0-1> remote udp port <0-65535>",
-	GPRS_TEXT NSVC_TEXT
-	"GPRS NS Remote UDP Port\n"
-	"GPRS NS Remote UDP Port\n"
-	"GPRS NS Remote UDP Port\n"
-	"GPRS NS Remote UDP Port Number\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int idx = atoi(argv[0]);
-
-	if (bts->gprs.mode == BTS_GPRS_NONE) {
-		vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts->gprs.nsvc[idx].remote_port = atoi(argv[1]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_gprs_nsvc_rip, cfg_bts_gprs_nsvc_rip_cmd,
-	"gprs nsvc <0-1> remote ip A.B.C.D",
-	GPRS_TEXT NSVC_TEXT
-	"GPRS NS Remote IP Address\n"
-	"GPRS NS Remote IP Address\n"
-	"GPRS NS Remote IP Address\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int idx = atoi(argv[0]);
-	struct in_addr ia;
-
-	if (bts->gprs.mode == BTS_GPRS_NONE) {
-		vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	inet_aton(argv[1], &ia);
-	bts->gprs.nsvc[idx].remote_ip = ntohl(ia.s_addr);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_pag_free, cfg_bts_pag_free_cmd,
-      "paging free <-1-1024>",
-      "Paging options\n"
-      "Only page when having a certain amount of free slots\n"
-      "amount of required free paging slots. -1 to disable\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	bts->paging.free_chans_need = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_gprs_ns_timer, cfg_bts_gprs_ns_timer_cmd,
-	"gprs ns timer " NS_TIMERS " <0-255>",
-	GPRS_TEXT "Network Service\n"
-	"Network Service Timer\n"
-	NS_TIMERS_HELP "Timer Value\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int idx = get_string_value(gprs_ns_timer_strs, argv[0]);
-	int val = atoi(argv[1]);
-
-	if (bts->gprs.mode == BTS_GPRS_NONE) {
-		vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (idx < 0 || idx >= ARRAY_SIZE(bts->gprs.nse.timer))
-		return CMD_WARNING;
-
-	bts->gprs.nse.timer[idx] = val;
-
-	return CMD_SUCCESS;
-}
-
-#define BSSGP_TIMERS "(blocking-timer|blocking-retries|unblocking-retries|reset-timer|reset-retries|suspend-timer|suspend-retries|resume-timer|resume-retries|capability-update-timer|capability-update-retries)"
-#define BSSGP_TIMERS_HELP	\
-	"Tbvc-block timeout\n"			\
-	"Tbvc-block retries\n"			\
-	"Tbvc-unblock retries\n"		\
-	"Tbvcc-reset timeout\n"			\
-	"Tbvc-reset retries\n"			\
-	"Tbvc-suspend timeout\n"		\
-	"Tbvc-suspend retries\n"		\
-	"Tbvc-resume timeout\n"			\
-	"Tbvc-resume retries\n"			\
-	"Tbvc-capa-update timeout\n"		\
-	"Tbvc-capa-update retries\n"
-
-DEFUN(cfg_bts_gprs_cell_timer, cfg_bts_gprs_cell_timer_cmd,
-	"gprs cell timer " BSSGP_TIMERS " <0-255>",
-	GPRS_TEXT "Cell / BSSGP\n"
-	"Cell/BSSGP Timer\n"
-	BSSGP_TIMERS_HELP "Timer Value\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int idx = get_string_value(gprs_bssgp_cfg_strs, argv[0]);
-	int val = atoi(argv[1]);
-
-	if (bts->gprs.mode == BTS_GPRS_NONE) {
-		vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (idx < 0 || idx >= ARRAY_SIZE(bts->gprs.cell.timer))
-		return CMD_WARNING;
-
-	bts->gprs.cell.timer[idx] = val;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_gprs_rac, cfg_bts_gprs_rac_cmd,
-	"gprs routing area <0-255>",
-	GPRS_TEXT
-	"GPRS Routing Area Code\n"
-	"GPRS Routing Area Code\n"
-	"GPRS Routing Area Code\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	if (bts->gprs.mode == BTS_GPRS_NONE) {
-		vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts->gprs.rac = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_gprs_ctrl_ack, cfg_bts_gprs_ctrl_ack_cmd,
-	"gprs control-ack-type-rach", GPRS_TEXT
-	"Set GPRS Control Ack Type for PACKET CONTROL ACKNOWLEDGMENT message to "
-	"four access bursts format instead of default RLC/MAC control block\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	if (bts->gprs.mode == BTS_GPRS_NONE) {
-		vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts->gprs.ctrl_ack_type_use_block = false;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_no_bts_gprs_ctrl_ack, cfg_no_bts_gprs_ctrl_ack_cmd,
-	"no gprs control-ack-type-rach", NO_STR GPRS_TEXT
-	"Set GPRS Control Ack Type for PACKET CONTROL ACKNOWLEDGMENT message to "
-	"four access bursts format instead of default RLC/MAC control block\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	if (bts->gprs.mode == BTS_GPRS_NONE) {
-		vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts->gprs.ctrl_ack_type_use_block = true;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_gprs_net_ctrl_ord, cfg_bts_gprs_net_ctrl_ord_cmd,
-	"gprs network-control-order (nc0|nc1|nc2)",
-	GPRS_TEXT
-	"GPRS Network Control Order\n"
-	"MS controlled cell re-selection, no measurement reporting\n"
-	"MS controlled cell re-selection, MS sends measurement reports\n"
-	"Network controlled cell re-selection, MS sends measurement reports\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	if (bts->gprs.mode == BTS_GPRS_NONE) {
-		vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts->gprs.net_ctrl_ord = atoi(argv[0] + 2);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_gprs_mode, cfg_bts_gprs_mode_cmd,
-	"gprs mode (none|gprs|egprs)",
-	GPRS_TEXT
-	"GPRS Mode for this BTS\n"
-	"GPRS Disabled on this BTS\n"
-	"GPRS Enabled on this BTS\n"
-	"EGPRS (EDGE) Enabled on this BTS\n")
-{
-	struct gsm_bts *bts = vty->index;
-	enum bts_gprs_mode mode = bts_gprs_mode_parse(argv[0], NULL);
-
-	if (!bts_gprs_mode_is_compat(bts, mode)) {
-		vty_out(vty, "This BTS type does not support %s%s", argv[0],
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts->gprs.mode = mode;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_gprs_11bit_rach_support_for_egprs,
-	cfg_bts_gprs_11bit_rach_support_for_egprs_cmd,
-	"gprs 11bit_rach_support_for_egprs (0|1)",
-	GPRS_TEXT "11 bit RACH options\n"
-	"Disable 11 bit RACH for EGPRS\n"
-	"Enable 11 bit RACH for EGPRS")
-{
-	struct gsm_bts *bts = vty->index;
-
-	bts->gprs.supports_egprs_11bit_rach = atoi(argv[0]);
-
-	if (bts->gprs.supports_egprs_11bit_rach > 1) {
-		vty_out(vty, "Error in RACH type%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if ((bts->gprs.mode == BTS_GPRS_NONE) &&
-		(bts->gprs.supports_egprs_11bit_rach == 1)) {
-		vty_out(vty, "Error:gprs mode is none and 11bit rach is"
-			" enabled%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	return CMD_SUCCESS;
-}
-
-#define SI_TEXT		"System Information Messages\n"
-#define SI_TYPE_TEXT "(1|2|3|4|5|6|7|8|9|10|13|16|17|18|19|20|2bis|2ter|2quater|5bis|5ter)"
-#define SI_TYPE_HELP 	"System Information Type 1\n"	\
-			"System Information Type 2\n"	\
-			"System Information Type 3\n"	\
-			"System Information Type 4\n"	\
-			"System Information Type 5\n"	\
-			"System Information Type 6\n"	\
-			"System Information Type 7\n"	\
-			"System Information Type 8\n"	\
-			"System Information Type 9\n"	\
-			"System Information Type 10\n"	\
-			"System Information Type 13\n"	\
-			"System Information Type 16\n"	\
-			"System Information Type 17\n"	\
-			"System Information Type 18\n"	\
-			"System Information Type 19\n"	\
-			"System Information Type 20\n"	\
-			"System Information Type 2bis\n"	\
-			"System Information Type 2ter\n"	\
-			"System Information Type 2quater\n"	\
-			"System Information Type 5bis\n"	\
-			"System Information Type 5ter\n"
-
-DEFUN(cfg_bts_si_mode, cfg_bts_si_mode_cmd,
-	"system-information " SI_TYPE_TEXT " mode (static|computed)",
-	SI_TEXT SI_TYPE_HELP
-	"System Information Mode\n"
-	"Static user-specified\n"
-	"Dynamic, BSC-computed\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int type;
-
-	type = get_string_value(osmo_sitype_strs, argv[0]);
-	if (type < 0) {
-		vty_out(vty, "Error SI Type%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (!strcmp(argv[1], "static"))
-		bts->si_mode_static |= (1 << type);
-	else
-		bts->si_mode_static &= ~(1 << type);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_si_static, cfg_bts_si_static_cmd,
-	"system-information " SI_TYPE_TEXT " static HEXSTRING",
-	SI_TEXT SI_TYPE_HELP
-	"Static System Information filling\n"
-	"Static user-specified SI content in HEX notation\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int rc, type;
-
-	type = get_string_value(osmo_sitype_strs, argv[0]);
-	if (type < 0) {
-		vty_out(vty, "Error SI Type%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (!(bts->si_mode_static & (1 << type))) {
-		vty_out(vty, "SI Type %s is not configured in static mode%s",
-			get_value_string(osmo_sitype_strs, type), VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	/* Fill buffer with padding pattern */
-	memset(GSM_BTS_SI(bts, type), 0x2b, GSM_MACBLOCK_LEN);
-
-	/* Parse the user-specified SI in hex format, [partially] overwriting padding */
-	rc = osmo_hexparse(argv[1], GSM_BTS_SI(bts, type), GSM_MACBLOCK_LEN);
-	if (rc < 0 || rc > GSM_MACBLOCK_LEN) {
-		vty_out(vty, "Error parsing HEXSTRING%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	/* Mark this SI as present */
-	bts->si_valid |= (1 << type);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_early_cm, cfg_bts_early_cm_cmd,
-	"early-classmark-sending (allowed|forbidden)",
-	"Early Classmark Sending\n"
-	"Early Classmark Sending is allowed\n"
-	"Early Classmark Sending is forbidden\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	if (!strcmp(argv[0], "allowed"))
-		bts->early_classmark_allowed = true;
-	else
-		bts->early_classmark_allowed = false;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_neigh_mode, cfg_bts_neigh_mode_cmd,
-	"neighbor-list mode (automatic|manual|manual-si5)",
-	"Neighbor List\n" "Mode of Neighbor List generation\n"
-	"Automatically from all BTS in this OpenBSC\n" "Manual\n"
-	"Manual with different lists for SI2 and SI5\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int mode = get_string_value(bts_neigh_mode_strs, argv[0]);
-
-	switch (mode) {
-	case NL_MODE_MANUAL_SI5SEP:
-	case NL_MODE_MANUAL:
-		/* make sure we clear the current list when switching to
-		 * manual mode */
-		if (bts->neigh_list_manual_mode == 0)
-			memset(&bts->si_common.data.neigh_list, 0,
-				sizeof(bts->si_common.data.neigh_list));
-		break;
-	default:
-		break;
-	}
-
-	bts->neigh_list_manual_mode = mode;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_neigh, cfg_bts_neigh_cmd,
-	"neighbor-list (add|del) arfcn <0-1023>",
-	"Neighbor List\n" "Add to manual neighbor list\n"
-	"Delete from manual neighbor list\n" "ARFCN of neighbor\n"
-	"ARFCN of neighbor\n")
-{
-	struct gsm_bts *bts = vty->index;
-	struct bitvec *bv = &bts->si_common.neigh_list;
-	uint16_t arfcn = atoi(argv[1]);
-
-	if (!bts->neigh_list_manual_mode) {
-		vty_out(vty, "%% Cannot configure neighbor list in "
-			"automatic mode%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (!strcmp(argv[0], "add"))
-		bitvec_set_bit_pos(bv, arfcn, 1);
-	else
-		bitvec_set_bit_pos(bv, arfcn, 0);
-
-	return CMD_SUCCESS;
-}
-
-/* help text should be kept in sync with EARFCN_*_INVALID defines */
-DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd,
-      "si2quater neighbor-list add earfcn <0-65535> thresh-hi <0-31> "
-      "thresh-lo <0-32> prio <0-8> qrxlv <0-32> meas <0-8>",
-      "SI2quater Neighbor List\n" "SI2quater Neighbor List\n"
-      "Add to manual SI2quater neighbor list\n"
-      "EARFCN of neighbor\n" "EARFCN of neighbor\n"
-      "threshold high bits\n" "threshold high bits\n"
-      "threshold low bits\n" "threshold low bits (32 means NA)\n"
-      "priority\n" "priority (8 means NA)\n"
-      "QRXLEVMIN\n" "QRXLEVMIN (32 means NA)\n"
-      "measurement bandwidth\n" "measurement bandwidth (8 means NA)\n")
-{
-	struct gsm_bts *bts = vty->index;
-	struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list;
-	uint16_t arfcn = atoi(argv[0]);
-	uint8_t thresh_hi = atoi(argv[1]), thresh_lo = atoi(argv[2]),
-		prio = atoi(argv[3]), qrx = atoi(argv[4]), meas = atoi(argv[5]);
-	int r = bts_earfcn_add(bts, arfcn, thresh_hi, thresh_lo, prio, qrx, meas);
-
-	switch (r) {
-	case 1:
-		vty_out(vty, "Warning: multiple threshold-high are not supported, overriding with %u%s",
-			thresh_hi, VTY_NEWLINE);
-		break;
-	case EARFCN_THRESH_LOW_INVALID:
-		vty_out(vty, "Warning: multiple threshold-low are not supported, overriding with %u%s",
-			thresh_lo, VTY_NEWLINE);
-		break;
-	case EARFCN_QRXLV_INVALID + 1:
-		vty_out(vty, "Warning: multiple QRXLEVMIN are not supported, overriding with %u%s",
-			qrx, VTY_NEWLINE);
-		break;
-	case EARFCN_PRIO_INVALID:
-		vty_out(vty, "Warning: multiple priorities are not supported, overriding with %u%s",
-			prio, VTY_NEWLINE);
-		break;
-	default:
-		if (r < 0) {
-			vty_out(vty, "Unable to add ARFCN %u: %s%s", arfcn, strerror(-r), VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-	}
-
-	if (si2q_num(bts) <= SI2Q_MAX_NUM)
-		return CMD_SUCCESS;
-
-	vty_out(vty, "Warning: not enough space in SI2quater (%u/%u used) for a given EARFCN %u%s",
-		bts->si2q_count, SI2Q_MAX_NUM, arfcn, VTY_NEWLINE);
-	osmo_earfcn_del(e, arfcn);
-
-	return CMD_WARNING;
-}
-
-DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd,
-	"si2quater neighbor-list del earfcn <0-65535>",
-	"SI2quater Neighbor List\n"
-	"SI2quater Neighbor List\n"
-	"Delete from SI2quater manual neighbor list\n"
-	"EARFCN of neighbor\n"
-	"EARFCN\n")
-{
-	struct gsm_bts *bts = vty->index;
-	struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list;
-	uint16_t arfcn = atoi(argv[0]);
-	int r = osmo_earfcn_del(e, arfcn);
-	if (r < 0) {
-		vty_out(vty, "Unable to delete arfcn %u: %s%s", arfcn,
-			strerror(-r), VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd,
-      "si2quater neighbor-list add uarfcn <0-16383> <0-511> <0-1>",
-      "SI2quater Neighbor List\n"
-      "SI2quater Neighbor List\n" "Add to manual SI2quater neighbor list\n"
-      "UARFCN of neighbor\n" "UARFCN of neighbor\n" "scrambling code\n"
-      "diversity bit\n")
-{
-	struct gsm_bts *bts = vty->index;
-	uint16_t arfcn = atoi(argv[0]), scramble = atoi(argv[1]);
-
-	switch(bts_uarfcn_add(bts, arfcn, scramble, atoi(argv[2]))) {
-	case -ENOMEM:
-		vty_out(vty, "Unable to add UARFCN: max number of UARFCNs (%u) reached%s", MAX_EARFCN_LIST, VTY_NEWLINE);
-		return CMD_WARNING;
-	case -ENOSPC:
-		vty_out(vty, "Warning: not enough space in SI2quater for a given UARFCN (%u, %u)%s",
-			arfcn, scramble, VTY_NEWLINE);
-		return CMD_WARNING;
-	case -EADDRINUSE:
-		vty_out(vty, "Unable to add UARFCN: (%u, %u) is already added%s", arfcn, scramble, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_si2quater_uarfcn_del, cfg_bts_si2quater_uarfcn_del_cmd,
-      "si2quater neighbor-list del uarfcn <0-16383> <0-511>",
-      "SI2quater Neighbor List\n"
-      "SI2quater Neighbor List\n"
-      "Delete from SI2quater manual neighbor list\n"
-      "UARFCN of neighbor\n"
-      "UARFCN\n"
-      "scrambling code\n")
-{
-	struct gsm_bts *bts = vty->index;
-
-	if (bts_uarfcn_del(bts, atoi(argv[0]), atoi(argv[1])) < 0) {
-		vty_out(vty, "Unable to delete uarfcn: pair not found%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_si5_neigh, cfg_bts_si5_neigh_cmd,
-	"si5 neighbor-list (add|del) arfcn <0-1023>",
-	"SI5 Neighbor List\n"
-	"SI5 Neighbor List\n" "Add to manual SI5 neighbor list\n"
-	"Delete from SI5 manual neighbor list\n" "ARFCN of neighbor\n"
-	"ARFCN of neighbor\n")
-{
-	struct gsm_bts *bts = vty->index;
-	struct bitvec *bv = &bts->si_common.si5_neigh_list;
-	uint16_t arfcn = atoi(argv[1]);
-
-	if (!bts->neigh_list_manual_mode) {
-		vty_out(vty, "%% Cannot configure neighbor list in "
-			"automatic mode%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (!strcmp(argv[0], "add"))
-		bitvec_set_bit_pos(bv, arfcn, 1);
-	else
-		bitvec_set_bit_pos(bv, arfcn, 0);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_pcu_sock, cfg_bts_pcu_sock_cmd,
-	"pcu-socket PATH",
-	"PCU Socket Path for using OsmoPCU co-located with BSC (legacy BTS)\n"
-	"Path in the file system for the unix-domain PCU socket\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int rc;
-
-	osmo_talloc_replace_string(bts, &bts->pcu_sock_path, argv[0]);
-	pcu_sock_exit(bts);
-	rc = pcu_sock_init(bts->pcu_sock_path, bts);
-	if (rc < 0) {
-		vty_out(vty, "%% Error creating PCU socket `%s' for BTS %u%s",
-			bts->pcu_sock_path, bts->nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	return CMD_SUCCESS;
-}
-
-#define EXCL_RFLOCK_STR "Exclude this BTS from the global RF Lock\n"
-
-DEFUN(cfg_bts_excl_rf_lock,
-      cfg_bts_excl_rf_lock_cmd,
-      "rf-lock-exclude",
-      EXCL_RFLOCK_STR)
-{
-	struct gsm_bts *bts = vty->index;
-	bts->excl_from_rf_lock = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_no_excl_rf_lock,
-      cfg_bts_no_excl_rf_lock_cmd,
-      "no rf-lock-exclude",
-      NO_STR EXCL_RFLOCK_STR)
-{
-	struct gsm_bts *bts = vty->index;
-	bts->excl_from_rf_lock = 0;
-	return CMD_SUCCESS;
-}
-
-#define FORCE_COMB_SI_STR "Force the generation of a single SI (no ter/bis)\n"
-
-DEFUN(cfg_bts_force_comb_si,
-      cfg_bts_force_comb_si_cmd,
-      "force-combined-si",
-      FORCE_COMB_SI_STR)
-{
-	struct gsm_bts *bts = vty->index;
-	bts->force_combined_si = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_no_force_comb_si,
-      cfg_bts_no_force_comb_si_cmd,
-      "no force-combined-si",
-      NO_STR FORCE_COMB_SI_STR)
-{
-	struct gsm_bts *bts = vty->index;
-	bts->force_combined_si = 0;
-	return CMD_SUCCESS;
-}
-
-static void _get_codec_from_arg(struct vty *vty, int argc, const char *argv[])
-{
-	struct gsm_bts *bts = vty->index;
-	struct bts_codec_conf *codec = &bts->codec;
-	int i;
-
-	codec->hr = 0;
-	codec->efr = 0;
-	codec->amr = 0;
-	for (i = 0; i < argc; i++) {
-		if (!strcmp(argv[i], "hr"))
-			codec->hr = 1;
-		if (!strcmp(argv[i], "efr"))
-			codec->efr = 1;
-		if (!strcmp(argv[i], "amr"))
-			codec->amr = 1;
-	}
-}
-
-#define CODEC_PAR_STR	" (hr|efr|amr)"
-#define CODEC_HELP_STR	"Half Rate\n" \
-			"Enhanced Full Rate\nAdaptive Multirate\n"
-
-DEFUN(cfg_bts_codec0, cfg_bts_codec0_cmd,
-	"codec-support fr",
-	"Codec Support settings\nFullrate\n")
-{
-	_get_codec_from_arg(vty, 0, argv);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_codec1, cfg_bts_codec1_cmd,
-	"codec-support fr" CODEC_PAR_STR,
-	"Codec Support settings\nFullrate\n"
-	CODEC_HELP_STR)
-{
-	_get_codec_from_arg(vty, 1, argv);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_codec2, cfg_bts_codec2_cmd,
-	"codec-support fr" CODEC_PAR_STR CODEC_PAR_STR,
-	"Codec Support settings\nFullrate\n"
-	CODEC_HELP_STR CODEC_HELP_STR)
-{
-	_get_codec_from_arg(vty, 2, argv);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_codec3, cfg_bts_codec3_cmd,
-	"codec-support fr" CODEC_PAR_STR CODEC_PAR_STR CODEC_PAR_STR,
-	"Codec Support settings\nFullrate\n"
-	CODEC_HELP_STR CODEC_HELP_STR CODEC_HELP_STR)
-{
-	_get_codec_from_arg(vty, 3, argv);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_codec4, cfg_bts_codec4_cmd,
-	"codec-support fr" CODEC_PAR_STR CODEC_PAR_STR CODEC_PAR_STR CODEC_PAR_STR,
-	"Codec Support settings\nFullrate\n"
-	CODEC_HELP_STR CODEC_HELP_STR CODEC_HELP_STR CODEC_HELP_STR)
-{
-	_get_codec_from_arg(vty, 4, argv);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_depends_on, cfg_bts_depends_on_cmd,
-	"depends-on-bts <0-255>",
-	"This BTS can only be started if another one is up\n" "BTS Number\n")
-{
-	struct gsm_bts *bts = vty->index;
-	struct gsm_bts *other_bts;
-	int dep = atoi(argv[0]);
-
-
-	if (!is_ipaccess_bts(bts)) {
-		vty_out(vty, "This feature is only available for IP systems.%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	other_bts = gsm_bts_num(bts->network, dep);
-	if (!other_bts || !is_ipaccess_bts(other_bts)) {
-		vty_out(vty, "This feature is only available for IP systems.%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (dep >= bts->nr) {
-		vty_out(vty, "%%Need to depend on an already declared unit.%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts_depend_mark(bts, dep);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_no_depends_on, cfg_bts_no_depends_on_cmd,
-	"depeneds-on-bts <0-255>",
-	NO_STR "This BTS can only be started if another one is up\n"
-	"BTS Number\n")
-{
-	struct gsm_bts *bts = vty->index;
-	int dep = atoi(argv[0]);
-
-	bts_depend_clear(bts, dep);
-	return CMD_SUCCESS;
-}
-
-#define AMR_TEXT "Adaptive Multi Rate settings\n"
-#define AMR_MODE_TEXT "Codec modes to use with AMR codec\n"
-#define AMR_START_TEXT "Initial codec to use with AMR\n" \
-	"Automatically\nFirst codec\nSecond codec\nThird codec\nFourth codec\n"
-#define AMR_TH_TEXT "AMR threshold between codecs\nMS side\nBTS side\n"
-#define AMR_HY_TEXT "AMR hysteresis between codecs\nMS side\nBTS side\n"
-
-static void get_amr_from_arg(struct vty *vty, int argc, const char *argv[], int full)
-{
-	struct gsm_bts *bts = vty->index;
-	struct amr_multirate_conf *mr = (full) ? &bts->mr_full: &bts->mr_half;
-	struct gsm48_multi_rate_conf *mr_conf =
-				(struct gsm48_multi_rate_conf *) mr->gsm48_ie;
-	int i;
-
-	mr->gsm48_ie[1] = 0;
-	for (i = 0; i < argc; i++)
-		mr->gsm48_ie[1] |= 1 << atoi(argv[i]);
-	mr_conf->icmi = 0;
-}
-
-static void get_amr_th_from_arg(struct vty *vty, int argc, const char *argv[], int full)
-{
-	struct gsm_bts *bts = vty->index;
-	struct amr_multirate_conf *mr = (full) ? &bts->mr_full: &bts->mr_half;
-	struct amr_mode *modes;
-	int i;
-
-	modes = argv[0][0]=='m' ? mr->ms_mode : mr->bts_mode;
-	for (i = 0; i < argc - 1; i++)
-		modes[i].threshold = atoi(argv[i + 1]);
-}
-
-static void get_amr_hy_from_arg(struct vty *vty, int argc, const char *argv[], int full)
-{
-	struct gsm_bts *bts = vty->index;
-	struct amr_multirate_conf *mr = (full) ? &bts->mr_full: &bts->mr_half;
-	struct amr_mode *modes;
-	int i;
-
-	modes = argv[0][0]=='m' ? mr->ms_mode : mr->bts_mode;
-	for (i = 0; i < argc - 1; i++)
-		modes[i].hysteresis = atoi(argv[i + 1]);
-}
-
-static void get_amr_start_from_arg(struct vty *vty, const char *argv[], int full)
-{
-	struct gsm_bts *bts = vty->index;
-	struct amr_multirate_conf *mr = (full) ? &bts->mr_full: &bts->mr_half;
-	struct gsm48_multi_rate_conf *mr_conf =
-				(struct gsm48_multi_rate_conf *) mr->gsm48_ie;
-	int num = 0, i;
-
-	for (i = 0; i < ((full) ? 8 : 6); i++) {
-		if ((mr->gsm48_ie[1] & (1 << i))) {
-			num++;
-		}
-	}
-
-	if (argv[0][0] == 'a' || num == 0)
-		mr_conf->icmi = 0;
-	else {
-		mr_conf->icmi = 1;
-		if (num < atoi(argv[0]))
-			mr_conf->smod = num - 1;
-		else
-			mr_conf->smod = atoi(argv[0]) - 1;
-	}
-}
-
-#define AMR_TCHF_PAR_STR " (0|1|2|3|4|5|6|7)"
-#define AMR_TCHF_HELP_STR "4,75k\n5,15k\n5,90k\n6,70k\n7,40k\n7,95k\n" \
-	"10,2k\n12,2k\n"
-
-#define AMR_TCHH_PAR_STR " (0|1|2|3|4|5)"
-#define AMR_TCHH_HELP_STR "4,75k\n5,15k\n5,90k\n6,70k\n7,40k\n7,95k\n"
-
-#define	AMR_TH_HELP_STR "Threshold between codec 1 and 2\n"
-#define	AMR_HY_HELP_STR "Hysteresis between codec 1 and 2\n"
-
-DEFUN(cfg_bts_amr_fr_modes1, cfg_bts_amr_fr_modes1_cmd,
-	"amr tch-f modes" AMR_TCHF_PAR_STR,
-	AMR_TEXT "Full Rate\n" AMR_MODE_TEXT
-	AMR_TCHF_HELP_STR)
-{
-	get_amr_from_arg(vty, 1, argv, 1);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_fr_modes2, cfg_bts_amr_fr_modes2_cmd,
-	"amr tch-f modes" AMR_TCHF_PAR_STR AMR_TCHF_PAR_STR,
-	AMR_TEXT "Full Rate\n" AMR_MODE_TEXT
-	AMR_TCHF_HELP_STR AMR_TCHF_HELP_STR)
-{
-	get_amr_from_arg(vty, 2, argv, 1);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_fr_modes3, cfg_bts_amr_fr_modes3_cmd,
-	"amr tch-f modes" AMR_TCHF_PAR_STR AMR_TCHF_PAR_STR AMR_TCHF_PAR_STR,
-	AMR_TEXT "Full Rate\n" AMR_MODE_TEXT
-	AMR_TCHF_HELP_STR AMR_TCHF_HELP_STR AMR_TCHF_HELP_STR)
-{
-	get_amr_from_arg(vty, 3, argv, 1);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_fr_modes4, cfg_bts_amr_fr_modes4_cmd,
-	"amr tch-f modes" AMR_TCHF_PAR_STR AMR_TCHF_PAR_STR AMR_TCHF_PAR_STR AMR_TCHF_PAR_STR,
-	AMR_TEXT "Full Rate\n" AMR_MODE_TEXT
-	AMR_TCHF_HELP_STR AMR_TCHF_HELP_STR AMR_TCHF_HELP_STR AMR_TCHF_HELP_STR)
-{
-	get_amr_from_arg(vty, 4, argv, 1);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_fr_start_mode, cfg_bts_amr_fr_start_mode_cmd,
-	"amr tch-f start-mode (auto|1|2|3|4)",
-	AMR_TEXT "Full Rate\n" AMR_START_TEXT)
-{
-	get_amr_start_from_arg(vty, argv, 1);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_fr_thres1, cfg_bts_amr_fr_thres1_cmd,
-	"amr tch-f threshold (ms|bts) <0-63>",
-	AMR_TEXT "Full Rate\n" AMR_TH_TEXT
-	AMR_TH_HELP_STR)
-{
-	get_amr_th_from_arg(vty, 2, argv, 1);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_fr_thres2, cfg_bts_amr_fr_thres2_cmd,
-	"amr tch-f threshold (ms|bts) <0-63> <0-63>",
-	AMR_TEXT "Full Rate\n" AMR_TH_TEXT
-	AMR_TH_HELP_STR AMR_TH_HELP_STR)
-{
-	get_amr_th_from_arg(vty, 3, argv, 1);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_fr_thres3, cfg_bts_amr_fr_thres3_cmd,
-	"amr tch-f threshold (ms|bts) <0-63> <0-63> <0-63>",
-	AMR_TEXT "Full Rate\n" AMR_TH_TEXT
-	AMR_TH_HELP_STR AMR_TH_HELP_STR AMR_TH_HELP_STR)
-{
-	get_amr_th_from_arg(vty, 4, argv, 1);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_fr_hyst1, cfg_bts_amr_fr_hyst1_cmd,
-	"amr tch-f hysteresis (ms|bts) <0-15>",
-	AMR_TEXT "Full Rate\n" AMR_HY_TEXT
-	AMR_HY_HELP_STR)
-{
-	get_amr_hy_from_arg(vty, 2, argv, 1);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_fr_hyst2, cfg_bts_amr_fr_hyst2_cmd,
-	"amr tch-f hysteresis (ms|bts) <0-15> <0-15>",
-	AMR_TEXT "Full Rate\n" AMR_HY_TEXT
-	AMR_HY_HELP_STR AMR_HY_HELP_STR)
-{
-	get_amr_hy_from_arg(vty, 3, argv, 1);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_fr_hyst3, cfg_bts_amr_fr_hyst3_cmd,
-	"amr tch-f hysteresis (ms|bts) <0-15> <0-15> <0-15>",
-	AMR_TEXT "Full Rate\n" AMR_HY_TEXT
-	AMR_HY_HELP_STR AMR_HY_HELP_STR AMR_HY_HELP_STR)
-{
-	get_amr_hy_from_arg(vty, 4, argv, 1);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_hr_modes1, cfg_bts_amr_hr_modes1_cmd,
-	"amr tch-h modes" AMR_TCHH_PAR_STR,
-	AMR_TEXT "Half Rate\n" AMR_MODE_TEXT
-	AMR_TCHH_HELP_STR)
-{
-	get_amr_from_arg(vty, 1, argv, 0);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_hr_modes2, cfg_bts_amr_hr_modes2_cmd,
-	"amr tch-h modes" AMR_TCHH_PAR_STR AMR_TCHH_PAR_STR,
-	AMR_TEXT "Half Rate\n" AMR_MODE_TEXT
-	AMR_TCHH_HELP_STR AMR_TCHH_HELP_STR)
-{
-	get_amr_from_arg(vty, 2, argv, 0);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_hr_modes3, cfg_bts_amr_hr_modes3_cmd,
-	"amr tch-h modes" AMR_TCHH_PAR_STR AMR_TCHH_PAR_STR AMR_TCHH_PAR_STR,
-	AMR_TEXT "Half Rate\n" AMR_MODE_TEXT
-	AMR_TCHH_HELP_STR AMR_TCHH_HELP_STR AMR_TCHH_HELP_STR)
-{
-	get_amr_from_arg(vty, 3, argv, 0);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_hr_modes4, cfg_bts_amr_hr_modes4_cmd,
-	"amr tch-h modes" AMR_TCHH_PAR_STR AMR_TCHH_PAR_STR AMR_TCHH_PAR_STR AMR_TCHH_PAR_STR,
-	AMR_TEXT "Half Rate\n" AMR_MODE_TEXT
-	AMR_TCHH_HELP_STR AMR_TCHH_HELP_STR AMR_TCHH_HELP_STR AMR_TCHH_HELP_STR)
-{
-	get_amr_from_arg(vty, 4, argv, 0);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_hr_start_mode, cfg_bts_amr_hr_start_mode_cmd,
-	"amr tch-h start-mode (auto|1|2|3|4)",
-	AMR_TEXT "Half Rate\n" AMR_START_TEXT)
-{
-	get_amr_start_from_arg(vty, argv, 0);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_hr_thres1, cfg_bts_amr_hr_thres1_cmd,
-	"amr tch-h threshold (ms|bts) <0-63>",
-	AMR_TEXT "Half Rate\n" AMR_TH_TEXT
-	AMR_TH_HELP_STR)
-{
-	get_amr_th_from_arg(vty, 2, argv, 0);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_hr_thres2, cfg_bts_amr_hr_thres2_cmd,
-	"amr tch-h threshold (ms|bts) <0-63> <0-63>",
-	AMR_TEXT "Half Rate\n" AMR_TH_TEXT
-	AMR_TH_HELP_STR AMR_TH_HELP_STR)
-{
-	get_amr_th_from_arg(vty, 3, argv, 0);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_hr_thres3, cfg_bts_amr_hr_thres3_cmd,
-	"amr tch-h threshold (ms|bts) <0-63> <0-63> <0-63>",
-	AMR_TEXT "Half Rate\n" AMR_TH_TEXT
-	AMR_TH_HELP_STR AMR_TH_HELP_STR AMR_TH_HELP_STR)
-{
-	get_amr_th_from_arg(vty, 4, argv, 0);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_hr_hyst1, cfg_bts_amr_hr_hyst1_cmd,
-	"amr tch-h hysteresis (ms|bts) <0-15>",
-	AMR_TEXT "Half Rate\n" AMR_HY_TEXT
-	AMR_HY_HELP_STR)
-{
-	get_amr_hy_from_arg(vty, 2, argv, 0);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_hr_hyst2, cfg_bts_amr_hr_hyst2_cmd,
-	"amr tch-h hysteresis (ms|bts) <0-15> <0-15>",
-	AMR_TEXT "Half Rate\n" AMR_HY_TEXT
-	AMR_HY_HELP_STR AMR_HY_HELP_STR)
-{
-	get_amr_hy_from_arg(vty, 3, argv, 0);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_amr_hr_hyst3, cfg_bts_amr_hr_hyst3_cmd,
-	"amr tch-h hysteresis (ms|bts) <0-15> <0-15> <0-15>",
-	AMR_TEXT "Half Rate\n" AMR_HY_TEXT
-	AMR_HY_HELP_STR AMR_HY_HELP_STR AMR_HY_HELP_STR)
-{
-	get_amr_hy_from_arg(vty, 4, argv, 0);
-	return CMD_SUCCESS;
-}
-
-#define TRX_TEXT "Radio Transceiver\n"
-
-/* per TRX configuration */
-DEFUN(cfg_trx,
-      cfg_trx_cmd,
-      "trx <0-255>",
-	TRX_TEXT
-      "Select a TRX to configure")
-{
-	int trx_nr = atoi(argv[0]);
-	struct gsm_bts *bts = vty->index;
-	struct gsm_bts_trx *trx;
-
-	if (trx_nr > bts->num_trx) {
-		vty_out(vty, "%% The next unused TRX number in this BTS is %u%s",
-			bts->num_trx, VTY_NEWLINE);
-		return CMD_WARNING;
-	} else if (trx_nr == bts->num_trx) {
-		/* we need to allocate a new one */
-		trx = gsm_bts_trx_alloc(bts);
-	} else
-		trx = gsm_bts_trx_num(bts, trx_nr);
-
-	if (!trx)
-		return CMD_WARNING;
-
-	vty->index = trx;
-	vty->index_sub = &trx->description;
-	vty->node = TRX_NODE;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trx_arfcn,
-      cfg_trx_arfcn_cmd,
-      "arfcn <0-1023>",
-      "Set the ARFCN for this TRX\n"
-      "Absolute Radio Frequency Channel Number\n")
-{
-	int arfcn = atoi(argv[0]);
-	struct gsm_bts_trx *trx = vty->index;
-
-	/* FIXME: check if this ARFCN is supported by this TRX */
-
-	trx->arfcn = arfcn;
-
-	/* FIXME: patch ARFCN into SYSTEM INFORMATION */
-	/* FIXME: use OML layer to update the ARFCN */
-	/* FIXME: use RSL layer to update SYSTEM INFORMATION */
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trx_nominal_power,
-      cfg_trx_nominal_power_cmd,
-      "nominal power <0-100>",
-      "Nominal TRX RF Power in dBm\n"
-      "Nominal TRX RF Power in dBm\n"
-      "Nominal TRX RF Power in dBm\n")
-{
-	struct gsm_bts_trx *trx = vty->index;
-
-	trx->nominal_power = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trx_max_power_red,
-      cfg_trx_max_power_red_cmd,
-      "max_power_red <0-100>",
-      "Reduction of maximum BS RF Power (relative to nominal power)\n"
-      "Reduction of maximum BS RF Power in dB\n")
-{
-	int maxpwr_r = atoi(argv[0]);
-	struct gsm_bts_trx *trx = vty->index;
-	int upper_limit = 24;	/* default 12.21 max power red. */
-
-	/* FIXME: check if our BTS type supports more than 12 */
-	if (maxpwr_r < 0 || maxpwr_r > upper_limit) {
-		vty_out(vty, "%% Power %d dB is not in the valid range%s",
-			maxpwr_r, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-	if (maxpwr_r & 1) {
-		vty_out(vty, "%% Power %d dB is not an even value%s",
-			maxpwr_r, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	trx->max_power_red = maxpwr_r;
-
-	/* FIXME: make sure we update this using OML */
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trx_rsl_e1,
-      cfg_trx_rsl_e1_cmd,
-      "rsl e1 line E1_LINE timeslot <1-31> sub-slot (0|1|2|3|full)",
-      "RSL Parameters\n"
-      "E1/T1 interface to be used for RSL\n"
-      "E1/T1 interface to be used for RSL\n"
-      "E1/T1 Line Number to be used for RSL\n"
-      "E1/T1 Timeslot to be used for RSL\n"
-      "E1/T1 Timeslot to be used for RSL\n"
-      "E1/T1 Sub-slot to be used for RSL\n"
-      "E1/T1 Sub-slot 0 is to be used for RSL\n"
-      "E1/T1 Sub-slot 1 is to be used for RSL\n"
-      "E1/T1 Sub-slot 2 is to be used for RSL\n"
-      "E1/T1 Sub-slot 3 is to be used for RSL\n"
-      "E1/T1 full timeslot is to be used for RSL\n")
-{
-	struct gsm_bts_trx *trx = vty->index;
-
-	parse_e1_link(&trx->rsl_e1_link, argv[0], argv[1], argv[2]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trx_rsl_e1_tei,
-      cfg_trx_rsl_e1_tei_cmd,
-      "rsl e1 tei <0-63>",
-      "RSL Parameters\n"
-      "Set the TEI to be used for RSL\n"
-      "Set the TEI to be used for RSL\n"
-      "TEI to be used for RSL\n")
-{
-	struct gsm_bts_trx *trx = vty->index;
-
-	trx->rsl_tei = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trx_rf_locked,
-      cfg_trx_rf_locked_cmd,
-      "rf_locked (0|1)",
-      "Set or unset the RF Locking (Turn off RF of the TRX)\n"
-      "TRX is NOT RF locked (active)\n"
-      "TRX is RF locked (turned off)\n")
-{
-	int locked = atoi(argv[0]);
-	struct gsm_bts_trx *trx = vty->index;
-
-	gsm_trx_lock_rf(trx, locked);
-	return CMD_SUCCESS;
-}
-
-/* per TS configuration */
-DEFUN(cfg_ts,
-      cfg_ts_cmd,
-      "timeslot <0-7>",
-      "Select a Timeslot to configure\n"
-      "Timeslot number\n")
-{
-	int ts_nr = atoi(argv[0]);
-	struct gsm_bts_trx *trx = vty->index;
-	struct gsm_bts_trx_ts *ts;
-
-	if (ts_nr >= TRX_NR_TS) {
-		vty_out(vty, "%% A GSM TRX only has %u Timeslots per TRX%s",
-			TRX_NR_TS, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	ts = &trx->ts[ts_nr];
-
-	vty->index = ts;
-	vty->node = TS_NODE;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_ts_pchan,
-      cfg_ts_pchan_cmd,
-      "phys_chan_config PCHAN", /* dynamically generated! */
-      "Physical Channel configuration (TCH/SDCCH/...)\n" "Physical Channel\n")
-{
-	struct gsm_bts_trx_ts *ts = vty->index;
-	int pchanc;
-
-	pchanc = gsm_pchan_parse(argv[0]);
-	if (pchanc < 0)
-		return CMD_WARNING;
-
-	ts->pchan = pchanc;
-
-	return CMD_SUCCESS;
-}
-
-/* used for backwards compatibility with old config files that still
- * have uppercase pchan type names */
-DEFUN_HIDDEN(cfg_ts_pchan_compat,
-      cfg_ts_pchan_compat_cmd,
-      "phys_chan_config PCHAN",
-      "Physical Channel configuration (TCH/SDCCH/...)\n" "Physical Channel\n")
-{
-	struct gsm_bts_trx_ts *ts = vty->index;
-	int pchanc;
-
-	pchanc = gsm_pchan_parse(argv[0]);
-	if (pchanc < 0)
-		return CMD_WARNING;
-
-	ts->pchan = pchanc;
-
-	return CMD_SUCCESS;
-}
-
-
-
-DEFUN(cfg_ts_tsc,
-      cfg_ts_tsc_cmd,
-      "training_sequence_code <0-7>",
-      "Training Sequence Code of the Timeslot\n" "TSC\n")
-{
-	struct gsm_bts_trx_ts *ts = vty->index;
-
-	if (!gsm_btsmodel_has_feature(ts->trx->bts->model, BTS_FEAT_MULTI_TSC)) {
-		vty_out(vty, "%% This BTS does not support a TSC != BCC, "
-			"falling back to BCC%s", VTY_NEWLINE);
-		ts->tsc = -1;
-		return CMD_WARNING;
-	}
-
-	ts->tsc = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-#define HOPPING_STR "Configure frequency hopping\n"
-
-DEFUN(cfg_ts_hopping,
-      cfg_ts_hopping_cmd,
-      "hopping enabled (0|1)",
-	HOPPING_STR "Enable or disable frequency hopping\n"
-      "Disable frequency hopping\n" "Enable frequency hopping\n")
-{
-	struct gsm_bts_trx_ts *ts = vty->index;
-	int enabled = atoi(argv[0]);
-
-	if (enabled && !gsm_btsmodel_has_feature(ts->trx->bts->model, BTS_FEAT_HOPPING)) {
-		vty_out(vty, "BTS model does not support hopping%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	ts->hopping.enabled = enabled;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_ts_hsn,
-      cfg_ts_hsn_cmd,
-      "hopping sequence-number <0-63>",
-	HOPPING_STR
-      "Which hopping sequence to use for this channel\n"
-      "Hopping Sequence Number (HSN)\n")
-{
-	struct gsm_bts_trx_ts *ts = vty->index;
-
-	ts->hopping.hsn = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_ts_maio,
-      cfg_ts_maio_cmd,
-      "hopping maio <0-63>",
-	HOPPING_STR
-      "Which hopping MAIO to use for this channel\n"
-      "Mobile Allocation Index Offset (MAIO)\n")
-{
-	struct gsm_bts_trx_ts *ts = vty->index;
-
-	ts->hopping.maio = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_ts_arfcn_add,
-      cfg_ts_arfcn_add_cmd,
-      "hopping arfcn add <0-1023>",
-	HOPPING_STR "Configure hopping ARFCN list\n"
-      "Add an entry to the hopping ARFCN list\n" "ARFCN\n")
-{
-	struct gsm_bts_trx_ts *ts = vty->index;
-	int arfcn = atoi(argv[0]);
-
-	bitvec_set_bit_pos(&ts->hopping.arfcns, arfcn, 1);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_ts_arfcn_del,
-      cfg_ts_arfcn_del_cmd,
-      "hopping arfcn del <0-1023>",
-	HOPPING_STR "Configure hopping ARFCN list\n"
-      "Delete an entry to the hopping ARFCN list\n" "ARFCN\n")
-{
-	struct gsm_bts_trx_ts *ts = vty->index;
-	int arfcn = atoi(argv[0]);
-
-	bitvec_set_bit_pos(&ts->hopping.arfcns, arfcn, 0);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_ts_e1_subslot,
-      cfg_ts_e1_subslot_cmd,
-      "e1 line E1_LINE timeslot <1-31> sub-slot (0|1|2|3|full)",
-      "E1/T1 channel connected to this on-air timeslot\n"
-      "E1/T1 channel connected to this on-air timeslot\n"
-      "E1/T1 line connected to this on-air timeslot\n"
-      "E1/T1 timeslot connected to this on-air timeslot\n"
-      "E1/T1 timeslot connected to this on-air timeslot\n"
-      "E1/T1 sub-slot connected to this on-air timeslot\n"
-      "E1/T1 sub-slot 0 connected to this on-air timeslot\n"
-      "E1/T1 sub-slot 1 connected to this on-air timeslot\n"
-      "E1/T1 sub-slot 2 connected to this on-air timeslot\n"
-      "E1/T1 sub-slot 3 connected to this on-air timeslot\n"
-      "Full E1/T1 timeslot connected to this on-air timeslot\n")
-{
-	struct gsm_bts_trx_ts *ts = vty->index;
-
-	parse_e1_link(&ts->e1_link, argv[0], argv[1], argv[2]);
-
-	return CMD_SUCCESS;
-}
-
-void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *net)
-{
-	vty_out(vty, "Channel Requests        : %lu total, %lu no channel%s",
-		net->bsc_ctrs->ctr[BSC_CTR_CHREQ_TOTAL].current,
-		net->bsc_ctrs->ctr[BSC_CTR_CHREQ_NO_CHANNEL].current,
-		VTY_NEWLINE);
-	vty_out(vty, "Channel Failures        : %lu rf_failures, %lu rll failures%s",
-		net->bsc_ctrs->ctr[BSC_CTR_CHAN_RF_FAIL].current,
-		net->bsc_ctrs->ctr[BSC_CTR_CHAN_RLL_ERR].current,
-		VTY_NEWLINE);
-	vty_out(vty, "Paging                  : %lu attempted, %lu complete, %lu expired%s",
-		net->bsc_ctrs->ctr[BSC_CTR_PAGING_ATTEMPTED].current,
-		net->bsc_ctrs->ctr[BSC_CTR_PAGING_COMPLETED].current,
-		net->bsc_ctrs->ctr[BSC_CTR_PAGING_EXPIRED].current,
-		VTY_NEWLINE);
-	vty_out(vty, "BTS failures            : %lu OML, %lu RSL%s",
-		net->bsc_ctrs->ctr[BSC_CTR_BTS_OML_FAIL].current,
-		net->bsc_ctrs->ctr[BSC_CTR_BTS_RSL_FAIL].current,
-		VTY_NEWLINE);
-}
-
-DEFUN(drop_bts,
-      drop_bts_cmd,
-      "drop bts connection <0-65535> (oml|rsl)",
-      "Debug/Simulation command to drop Abis/IP BTS\n"
-      "Debug/Simulation command to drop Abis/IP BTS\n"
-      "Debug/Simulation command to drop Abis/IP BTS\n"
-      "BTS NR\n" "Drop OML Connection\n" "Drop RSL Connection\n")
-{
-	struct gsm_network *gsmnet;
-	struct gsm_bts_trx *trx;
-	struct gsm_bts *bts;
-	unsigned int bts_nr;
-
-	gsmnet = gsmnet_from_vty(vty);
-
-	bts_nr = atoi(argv[0]);
-	if (bts_nr >= gsmnet->num_bts) {
-		vty_out(vty, "BTS number must be between 0 and %d. It was %d.%s",
-			gsmnet->num_bts, bts_nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts = gsm_bts_num(gsmnet, bts_nr);
-	if (!bts) {
-		vty_out(vty, "BTS Nr. %d could not be found.%s", bts_nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (!is_ipaccess_bts(bts)) {
-		vty_out(vty, "This command only works for ipaccess.%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-
-	/* close all connections */
-	if (strcmp(argv[1], "oml") == 0) {
-		ipaccess_drop_oml(bts);
-	} else if (strcmp(argv[1], "rsl") == 0) {
-		/* close all rsl connections */
-		llist_for_each_entry(trx, &bts->trx_list, list) {
-			ipaccess_drop_rsl(trx);
-		}
-	} else {
-		vty_out(vty, "Argument must be 'oml# or 'rsl'.%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(restart_bts, restart_bts_cmd,
-      "restart-bts <0-65535>",
-      "Restart ip.access nanoBTS through OML\n"
-      "BTS Number\n")
-{
-	struct gsm_network *gsmnet;
-	struct gsm_bts_trx *trx;
-	struct gsm_bts *bts;
-	unsigned int bts_nr;
-
-	gsmnet = gsmnet_from_vty(vty);
-
-	bts_nr = atoi(argv[0]);
-	if (bts_nr >= gsmnet->num_bts) {
-		vty_out(vty, "BTS number must be between 0 and %d. It was %d.%s",
-			gsmnet->num_bts, bts_nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts = gsm_bts_num(gsmnet, bts_nr);
-	if (!bts) {
-		vty_out(vty, "BTS Nr. %d could not be found.%s", bts_nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (!is_ipaccess_bts(bts) || is_sysmobts_v2(bts)) {
-		vty_out(vty, "This command only works for ipaccess nanoBTS.%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	/* go from last TRX to c0 */
-	llist_for_each_entry_reverse(trx, &bts->trx_list, list)
-		abis_nm_ipaccess_restart(trx);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(bts_resend, bts_resend_cmd,
-      "bts <0-255> resend-system-information",
-      "BTS Specific Commands\n" "BTS Number\n"
-      "Re-generate + re-send BCCH SYSTEM INFORMATION\n")
-{
-	struct gsm_network *gsmnet;
-	struct gsm_bts_trx *trx;
-	struct gsm_bts *bts;
-	unsigned int bts_nr;
-
-	gsmnet = gsmnet_from_vty(vty);
-
-	bts_nr = atoi(argv[0]);
-	if (bts_nr >= gsmnet->num_bts) {
-		vty_out(vty, "BTS number must be between 0 and %d. It was %d.%s",
-			gsmnet->num_bts, bts_nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts = gsm_bts_num(gsmnet, bts_nr);
-	if (!bts) {
-		vty_out(vty, "BTS Nr. %d could not be found.%s", bts_nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	llist_for_each_entry_reverse(trx, &bts->trx_list, list)
-		gsm_bts_trx_set_system_infos(trx);
-
-	return CMD_SUCCESS;
-}
-
-
-DEFUN(smscb_cmd, smscb_cmd_cmd,
-	"bts <0-255> smscb-command <1-4> HEXSTRING",
-	"BTS related commands\n" "BTS Number\n"
-	"SMS Cell Broadcast\n" "Last Valid Block\n"
-	"Hex Encoded SMSCB message (up to 88 octets)\n")
-{
-	struct gsm_bts *bts;
-	int bts_nr = atoi(argv[0]);
-	int last_block = atoi(argv[1]);
-	struct rsl_ie_cb_cmd_type cb_cmd;
-	uint8_t buf[88];
-	int rc;
-
-	bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr);
-	if (!bts) {
-		vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-	rc = osmo_hexparse(argv[2], buf, sizeof(buf));
-	if (rc < 0 || rc > sizeof(buf)) {
-		vty_out(vty, "Error parsing HEXSTRING%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	cb_cmd.spare = 0;
-	cb_cmd.def_bcast = 0;
-	cb_cmd.command = RSL_CB_CMD_TYPE_NORMAL;
-
-	switch (last_block) {
-	case 1:
-		cb_cmd.last_block = RSL_CB_CMD_LASTBLOCK_1;
-		break;
-	case 2:
-		cb_cmd.last_block = RSL_CB_CMD_LASTBLOCK_2;
-		break;
-	case 3:
-		cb_cmd.last_block = RSL_CB_CMD_LASTBLOCK_3;
-		break;
-	case 4:
-		cb_cmd.last_block = RSL_CB_CMD_LASTBLOCK_4;
-		break;
-	}
-
-	rsl_sms_cb_command(bts, RSL_CHAN_SDCCH4_ACCH, cb_cmd, buf, rc);
-
-	return CMD_SUCCESS;
-}
-
-/* resolve a gsm_bts_trx_ts basd on the given numeric identifiers */
-static struct gsm_bts_trx_ts *vty_get_ts(struct vty *vty, const char *bts_str, const char *trx_str,
-					 const char *ts_str)
-{
-	int bts_nr = atoi(bts_str);
-	int trx_nr = atoi(trx_str);
-	int ts_nr = atoi(ts_str);
-	struct gsm_bts *bts;
-	struct gsm_bts_trx *trx;
-	struct gsm_bts_trx_ts *ts;
-
-	bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr);
-	if (!bts) {
-		vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
-		return NULL;
-	}
-
-	trx = gsm_bts_trx_num(bts, trx_nr);
-	if (!trx) {
-		vty_out(vty, "%% No such TRX (%d)%s", trx_nr, VTY_NEWLINE);
-		return NULL;
-	}
-
-	ts = &trx->ts[ts_nr];
-
-	return ts;
-}
-
-DEFUN(pdch_act, pdch_act_cmd,
-	"bts <0-255> trx <0-255> timeslot <0-7> pdch (activate|deactivate)",
-	"BTS related commands\n" "BTS Number\n" "Transceiver\n" "Transceiver Number\n"
-	"TRX Timeslot\n" "Timeslot Number\n" "Packet Data Channel\n"
-	"Activate Dynamic PDCH/TCH (-> PDCH mode)\n"
-	"Deactivate Dynamic PDCH/TCH (-> TCH mode)\n")
-{
-	struct gsm_bts_trx_ts *ts;
-	int activate;
-
-	ts = vty_get_ts(vty, argv[0], argv[1], argv[2]);
-	if (!ts)
-		return CMD_WARNING;
-
-	if (!is_ipaccess_bts(ts->trx->bts)) {
-		vty_out(vty, "%% This command only works for ipaccess BTS%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (ts->pchan != GSM_PCHAN_TCH_F_PDCH) {
-		vty_out(vty, "%% Timeslot %u is not in dynamic TCH_F/PDCH "
-			"mode%s", ts->nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (!strcmp(argv[3], "activate"))
-		activate = 1;
-	else
-		activate = 0;
-
-	rsl_ipacc_pdch_activate(ts, activate);
-
-	return CMD_SUCCESS;
-
-}
-
-/* determine the logical channel type based on the physical channel type */
-static int lchan_type_by_pchan(enum gsm_phys_chan_config pchan)
-{
-	switch (pchan) {
-	case GSM_PCHAN_TCH_F:
-		return GSM_LCHAN_TCH_F;
-	case GSM_PCHAN_TCH_H:
-		return GSM_LCHAN_TCH_H;
-	case GSM_PCHAN_SDCCH8_SACCH8C:
-	case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:
-	case GSM_PCHAN_CCCH_SDCCH4:
-	case GSM_PCHAN_CCCH_SDCCH4_CBCH:
-		return GSM_LCHAN_SDCCH;
-	default:
-		return -1;
-	}
-}
-
-/* configure the lchan for a single AMR mode (as specified) */
-static int lchan_set_single_amr_mode(struct gsm_lchan *lchan, uint8_t amr_mode)
-{
-	struct amr_multirate_conf mr;
-	struct gsm48_multi_rate_conf *mr_conf;
-	mr_conf = (struct gsm48_multi_rate_conf *) &mr.gsm48_ie;
-
-	if (amr_mode > 7)
-		return -1;
-
-	memset(&mr, 0, sizeof(mr));
-	mr_conf->ver = 1;
-	/* bit-mask of supported modes, only one bit is set. Reflects
-	 * Figure 10.5.2.47a where there are no thershold and only a
-	 * single mode */
-	mr.gsm48_ie[1] = 1 << amr_mode;
-
-	mr.ms_mode[0].mode = amr_mode;
-	mr.bts_mode[0].mode = amr_mode;
-
-	/* encode this configuration into the lchan for both uplink and
-	 * downlink direction */
-	gsm48_multirate_config(lchan->mr_ms_lv, &mr, mr.ms_mode);
-	gsm48_multirate_config(lchan->mr_bts_lv, &mr, mr.bts_mode);
-
-	return 0;
-}
-
-/* Debug/Measurement command to activate a given logical channel
- * manually in a given mode/codec.  This is useful for receiver
- * performance testing (FER/RBER/...) */
-DEFUN(lchan_act, lchan_act_cmd,
-	"bts <0-255> trx <0-255> timeslot <0-7> sub-slot <0-7> (activate|deactivate) (hr|fr|efr|amr) [<0-7>]",
-	"BTS related commands\n" "BTS Number\n" "Transceiver\n" "Transceiver Number\n"
-	"TRX Timeslot\n" "Timeslot Number\n" "Sub-Slot Number\n" "Sub-Slot Number\n"
-	"Manual Channel Activation (e.g. for BER test)\n"
-	"Manual Channel Deactivation (e.g. for BER test)\n"
-	"Half-Rate v1\n" "Full-Rate\n" "Enhanced Full Rate\n" "Adaptive Multi-Rate\n" "AMR Mode\n")
-{
-	struct gsm_bts_trx_ts *ts;
-	struct gsm_lchan *lchan;
-	int ss_nr = atoi(argv[3]);
-	const char *act_str = argv[4];
-	const char *codec_str = argv[5];
-	int activate;
-
-	ts = vty_get_ts(vty, argv[0], argv[1], argv[2]);
-	if (!ts)
-		return CMD_WARNING;
-
-	lchan = &ts->lchan[ss_nr];
-
-	if (!strcmp(act_str, "activate"))
-		activate = 1;
-	else
-		activate = 0;
-
-	if (ss_nr >= ts_subslots(ts)) {
-		vty_out(vty, "%% subslot %d >= permitted %d for physical channel %s%s",
-			ss_nr, ts_subslots(ts), gsm_pchan_name(ts->pchan), VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (activate) {
-		int lchan_t;
-		if (lchan->state != LCHAN_S_NONE) {
-			vty_out(vty, "%% Cannot activate: Channel busy!%s", VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-		lchan_t = lchan_type_by_pchan(ts->pchan);
-		if (lchan_t < 0)
-			return CMD_WARNING;
-		/* configure the lchan */
-		lchan->type = lchan_t;
-		lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
-		if (!strcmp(codec_str, "hr") || !strcmp(codec_str, "fr"))
-			lchan->tch_mode = GSM48_CMODE_SPEECH_V1;
-		else if (!strcmp(codec_str, "efr"))
-			lchan->tch_mode = GSM48_CMODE_SPEECH_EFR;
-		else if (!strcmp(codec_str, "amr")) {
-			int amr_mode;
-			if (argc < 7) {
-				vty_out(vty, "%% AMR requires specification of AMR mode%s", VTY_NEWLINE);
-				return CMD_WARNING;
-			}
-			amr_mode = atoi(argv[6]);
-			lchan->tch_mode = GSM48_CMODE_SPEECH_AMR;
-			lchan_set_single_amr_mode(lchan, amr_mode);
-		}
-		vty_out(vty, "%% activating lchan %s%s", gsm_lchan_name(lchan), VTY_NEWLINE);
-		rsl_chan_activate_lchan(lchan, RSL_ACT_TYPE_INITIAL, 0);
-		rsl_ipacc_crcx(lchan);
-	} else {
-		rsl_direct_rf_release(lchan);
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(lchan_mdcx, lchan_mdcx_cmd,
-	"bts <0-255> trx <0-255> timeslot <0-7> sub-slot <0-7> mdcx A.B.C.D <0-65535>",
-	"BTS related commands\n" "BTS Number\n" "Transceiver\n" "Transceiver Number\n"
-	"TRX Timeslot\n" "Timeslot Number\n" "Sub-Slot\n" "Sub-Slot Number\n"
-	"Modify RTP Connection\n" "MGW IP Address\n" "MGW UDP Port\n")
-{
-	struct gsm_bts_trx_ts *ts;
-	struct gsm_lchan *lchan;
-	int ss_nr = atoi(argv[3]);
-	int port = atoi(argv[5]);
-	struct in_addr ia;
-	inet_aton(argv[4], &ia);
-
-	ts = vty_get_ts(vty, argv[0], argv[1], argv[2]);
-	if (!ts)
-		return CMD_WARNING;
-
-	lchan = &ts->lchan[ss_nr];
-
-	if (ss_nr >= ts_subslots(ts)) {
-		vty_out(vty, "%% subslot %d >= permitted %d for physical channel %s%s",
-			ss_nr, ts_subslots(ts), gsm_pchan_name(ts->pchan), VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	vty_out(vty, "%% connecting RTP of %s to %s:%u%s", gsm_lchan_name(lchan),
-		inet_ntoa(ia), port, VTY_NEWLINE);
-	rsl_ipacc_mdcx(lchan, ntohl(ia.s_addr), port, 0);
-	return CMD_SUCCESS;
-}
-
-DEFUN(ctrl_trap, ctrl_trap_cmd,
-	"ctrl-interface generate-trap TRAP VALUE",
-	"Commands related to the CTRL Interface\n"
-	"Generate a TRAP for test purpose\n"
-	"Identity/Name of the TRAP variable\n"
-	"Value of the TRAP variable\n")
-{
-	struct gsm_network *net = gsmnet_from_vty(vty);
-
-	ctrl_cmd_send_trap(net->ctrl, argv[0], (char *) argv[1]);
-	return CMD_SUCCESS;
-}
-
-extern int bsc_vty_init_extra(void);
-
-int bsc_vty_init(struct gsm_network *network)
-{
-	cfg_ts_pchan_cmd.string =
-		vty_cmd_string_from_valstr(tall_bsc_ctx,
-					   gsm_pchant_names,
-					   "phys_chan_config (", "|", ")",
-					   VTY_DO_LOWER);
-	cfg_ts_pchan_cmd.doc =
-		vty_cmd_string_from_valstr(tall_bsc_ctx,
-					   gsm_pchant_descs,
-					   "Physical Channel Combination\n",
-					   "\n", "", 0);
-
-	cfg_bts_type_cmd.string =
-		vty_cmd_string_from_valstr(tall_bsc_ctx,
-					   bts_type_names,
-					   "type (", "|", ")",
-					   VTY_DO_LOWER);
-	cfg_bts_type_cmd.doc =
-		vty_cmd_string_from_valstr(tall_bsc_ctx,
-					   bts_type_descs,
-					   "BTS Vendor/Type\n",
-					   "\n", "", 0);
-
-	common_cs_vty_init(network, config_write_net);
-
-	install_element_ve(&bsc_show_net_cmd);
-	install_element_ve(&show_bts_cmd);
-	install_element_ve(&show_trx_cmd);
-	install_element_ve(&show_ts_cmd);
-	install_element_ve(&show_lchan_cmd);
-	install_element_ve(&show_lchan_summary_cmd);
-
-	install_element_ve(&show_subscr_conn_cmd);
-	install_element_ve(&handover_subscr_conn_cmd);
-
-	install_element_ve(&show_paging_cmd);
-	install_element_ve(&show_paging_group_cmd);
-
-	logging_vty_add_cmds(NULL);
-
-	install_element(GSMNET_NODE, &cfg_net_neci_cmd);
-	install_element(GSMNET_NODE, &cfg_net_handover_cmd);
-	install_element(GSMNET_NODE, &cfg_net_ho_win_rxlev_avg_cmd);
-	install_element(GSMNET_NODE, &cfg_net_ho_win_rxqual_avg_cmd);
-	install_element(GSMNET_NODE, &cfg_net_ho_win_rxlev_avg_neigh_cmd);
-	install_element(GSMNET_NODE, &cfg_net_ho_pwr_interval_cmd);
-	install_element(GSMNET_NODE, &cfg_net_ho_pwr_hysteresis_cmd);
-	install_element(GSMNET_NODE, &cfg_net_ho_max_distance_cmd);
-	install_element(GSMNET_NODE, &cfg_net_T3101_cmd);
-	install_element(GSMNET_NODE, &cfg_net_T3103_cmd);
-	install_element(GSMNET_NODE, &cfg_net_T3105_cmd);
-	install_element(GSMNET_NODE, &cfg_net_T3107_cmd);
-	install_element(GSMNET_NODE, &cfg_net_T3109_cmd);
-	install_element(GSMNET_NODE, &cfg_net_T3111_cmd);
-	install_element(GSMNET_NODE, &cfg_net_T3113_cmd);
-	install_element(GSMNET_NODE, &cfg_net_T3115_cmd);
-	install_element(GSMNET_NODE, &cfg_net_T3117_cmd);
-	install_element(GSMNET_NODE, &cfg_net_T3119_cmd);
-	install_element(GSMNET_NODE, &cfg_net_T3122_cmd);
-	install_element(GSMNET_NODE, &cfg_net_T3141_cmd);
-	install_element(GSMNET_NODE, &cfg_net_dtx_cmd);
-	install_element(GSMNET_NODE, &cfg_net_pag_any_tch_cmd);
-
-	install_element(GSMNET_NODE, &cfg_bts_cmd);
-	install_node(&bts_node, config_write_bts);
-	vty_install_default(BTS_NODE);
-	install_element(BTS_NODE, &cfg_bts_type_cmd);
-	install_element(BTS_NODE, &cfg_description_cmd);
-	install_element(BTS_NODE, &cfg_no_description_cmd);
-	install_element(BTS_NODE, &cfg_bts_band_cmd);
-	install_element(BTS_NODE, &cfg_bts_ci_cmd);
-	install_element(BTS_NODE, &cfg_bts_dtxu_cmd);
-	install_element(BTS_NODE, &cfg_bts_dtxd_cmd);
-	install_element(BTS_NODE, &cfg_bts_no_dtxu_cmd);
-	install_element(BTS_NODE, &cfg_bts_no_dtxd_cmd);
-	install_element(BTS_NODE, &cfg_bts_lac_cmd);
-	install_element(BTS_NODE, &cfg_bts_tsc_cmd);
-	install_element(BTS_NODE, &cfg_bts_bsic_cmd);
-	install_element(BTS_NODE, &cfg_bts_unit_id_cmd);
-	install_element(BTS_NODE, &cfg_bts_rsl_ip_cmd);
-	install_element(BTS_NODE, &cfg_bts_nokia_site_skip_reset_cmd);
-	install_element(BTS_NODE, &cfg_bts_nokia_site_no_loc_rel_cnf_cmd);
-	install_element(BTS_NODE, &cfg_bts_nokia_site_bts_reset_timer_cnf_cmd);
-	install_element(BTS_NODE, &cfg_bts_stream_id_cmd);
-	install_element(BTS_NODE, &cfg_bts_oml_e1_cmd);
-	install_element(BTS_NODE, &cfg_bts_oml_e1_tei_cmd);
-	install_element(BTS_NODE, &cfg_bts_challoc_cmd);
-	install_element(BTS_NODE, &cfg_bts_rach_tx_integer_cmd);
-	install_element(BTS_NODE, &cfg_bts_rach_max_trans_cmd);
-	install_element(BTS_NODE, &cfg_bts_chan_desc_att_cmd);
-	install_element(BTS_NODE, &cfg_bts_chan_desc_bs_pa_mfrms_cmd);
-	install_element(BTS_NODE, &cfg_bts_chan_desc_bs_ag_blks_res_cmd);
-	install_element(BTS_NODE, &cfg_bts_rach_nm_b_thresh_cmd);
-	install_element(BTS_NODE, &cfg_bts_rach_nm_ldavg_cmd);
-	install_element(BTS_NODE, &cfg_bts_cell_barred_cmd);
-	install_element(BTS_NODE, &cfg_bts_rach_ec_allowed_cmd);
-	install_element(BTS_NODE, &cfg_bts_rach_ac_class_cmd);
-	install_element(BTS_NODE, &cfg_bts_ms_max_power_cmd);
-	install_element(BTS_NODE, &cfg_bts_cell_resel_hyst_cmd);
-	install_element(BTS_NODE, &cfg_bts_rxlev_acc_min_cmd);
-	install_element(BTS_NODE, &cfg_bts_cell_bar_qualify_cmd);
-	install_element(BTS_NODE, &cfg_bts_cell_resel_ofs_cmd);
-	install_element(BTS_NODE, &cfg_bts_temp_ofs_cmd);
-	install_element(BTS_NODE, &cfg_bts_temp_ofs_inf_cmd);
-	install_element(BTS_NODE, &cfg_bts_penalty_time_cmd);
-	install_element(BTS_NODE, &cfg_bts_penalty_time_rsvd_cmd);
-	install_element(BTS_NODE, &cfg_bts_radio_link_timeout_cmd);
-	install_element(BTS_NODE, &cfg_bts_radio_link_timeout_inf_cmd);
-	install_element(BTS_NODE, &cfg_bts_gprs_mode_cmd);
-	install_element(BTS_NODE, &cfg_bts_gprs_11bit_rach_support_for_egprs_cmd);
-	install_element(BTS_NODE, &cfg_bts_gprs_ns_timer_cmd);
-	install_element(BTS_NODE, &cfg_bts_gprs_rac_cmd);
-	install_element(BTS_NODE, &cfg_bts_gprs_net_ctrl_ord_cmd);
-	install_element(BTS_NODE, &cfg_bts_gprs_ctrl_ack_cmd);
-	install_element(BTS_NODE, &cfg_no_bts_gprs_ctrl_ack_cmd);
-	install_element(BTS_NODE, &cfg_bts_gprs_bvci_cmd);
-	install_element(BTS_NODE, &cfg_bts_gprs_cell_timer_cmd);
-	install_element(BTS_NODE, &cfg_bts_gprs_nsei_cmd);
-	install_element(BTS_NODE, &cfg_bts_gprs_nsvci_cmd);
-	install_element(BTS_NODE, &cfg_bts_gprs_nsvc_lport_cmd);
-	install_element(BTS_NODE, &cfg_bts_gprs_nsvc_rport_cmd);
-	install_element(BTS_NODE, &cfg_bts_gprs_nsvc_rip_cmd);
-	install_element(BTS_NODE, &cfg_bts_pag_free_cmd);
-	install_element(BTS_NODE, &cfg_bts_si_mode_cmd);
-	install_element(BTS_NODE, &cfg_bts_si_static_cmd);
-	install_element(BTS_NODE, &cfg_bts_early_cm_cmd);
-	install_element(BTS_NODE, &cfg_bts_neigh_mode_cmd);
-	install_element(BTS_NODE, &cfg_bts_neigh_cmd);
-	install_element(BTS_NODE, &cfg_bts_si5_neigh_cmd);
-	install_element(BTS_NODE, &cfg_bts_si2quater_neigh_add_cmd);
-	install_element(BTS_NODE, &cfg_bts_si2quater_neigh_del_cmd);
-	install_element(BTS_NODE, &cfg_bts_si2quater_uarfcn_add_cmd);
-	install_element(BTS_NODE, &cfg_bts_si2quater_uarfcn_del_cmd);
-	install_element(BTS_NODE, &cfg_bts_excl_rf_lock_cmd);
-	install_element(BTS_NODE, &cfg_bts_no_excl_rf_lock_cmd);
-	install_element(BTS_NODE, &cfg_bts_force_comb_si_cmd);
-	install_element(BTS_NODE, &cfg_bts_no_force_comb_si_cmd);
-	install_element(BTS_NODE, &cfg_bts_codec0_cmd);
-	install_element(BTS_NODE, &cfg_bts_codec1_cmd);
-	install_element(BTS_NODE, &cfg_bts_codec2_cmd);
-	install_element(BTS_NODE, &cfg_bts_codec3_cmd);
-	install_element(BTS_NODE, &cfg_bts_codec4_cmd);
-	install_element(BTS_NODE, &cfg_bts_depends_on_cmd);
-	install_element(BTS_NODE, &cfg_bts_no_depends_on_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_fr_modes1_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_fr_modes2_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_fr_modes3_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_fr_modes4_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_fr_thres1_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_fr_thres2_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_fr_thres3_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_fr_hyst1_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_fr_hyst2_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_fr_hyst3_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_fr_start_mode_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_hr_modes1_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_hr_modes2_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_hr_modes3_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_hr_modes4_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_hr_thres1_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_hr_thres2_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_hr_thres3_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_hr_hyst1_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_hr_hyst2_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_hr_hyst3_cmd);
-	install_element(BTS_NODE, &cfg_bts_amr_hr_start_mode_cmd);
-	install_element(BTS_NODE, &cfg_bts_pcu_sock_cmd);
-
-	install_element(BTS_NODE, &cfg_trx_cmd);
-	install_node(&trx_node, dummy_config_write);
-	vty_install_default(TRX_NODE);
-	install_element(TRX_NODE, &cfg_trx_arfcn_cmd);
-	install_element(TRX_NODE, &cfg_description_cmd);
-	install_element(TRX_NODE, &cfg_no_description_cmd);
-	install_element(TRX_NODE, &cfg_trx_nominal_power_cmd);
-	install_element(TRX_NODE, &cfg_trx_max_power_red_cmd);
-	install_element(TRX_NODE, &cfg_trx_rsl_e1_cmd);
-	install_element(TRX_NODE, &cfg_trx_rsl_e1_tei_cmd);
-	install_element(TRX_NODE, &cfg_trx_rf_locked_cmd);
-
-	install_element(TRX_NODE, &cfg_ts_cmd);
-	install_node(&ts_node, dummy_config_write);
-	vty_install_default(TS_NODE);
-	install_element(TS_NODE, &cfg_ts_pchan_cmd);
-	install_element(TS_NODE, &cfg_ts_pchan_compat_cmd);
-	install_element(TS_NODE, &cfg_ts_tsc_cmd);
-	install_element(TS_NODE, &cfg_ts_hopping_cmd);
-	install_element(TS_NODE, &cfg_ts_hsn_cmd);
-	install_element(TS_NODE, &cfg_ts_maio_cmd);
-	install_element(TS_NODE, &cfg_ts_arfcn_add_cmd);
-	install_element(TS_NODE, &cfg_ts_arfcn_del_cmd);
-	install_element(TS_NODE, &cfg_ts_e1_subslot_cmd);
-
-	install_element(ENABLE_NODE, &drop_bts_cmd);
-	install_element(ENABLE_NODE, &restart_bts_cmd);
-	install_element(ENABLE_NODE, &bts_resend_cmd);
-	install_element(ENABLE_NODE, &pdch_act_cmd);
-	install_element(ENABLE_NODE, &lchan_act_cmd);
-	install_element(ENABLE_NODE, &lchan_mdcx_cmd);
-	install_element(ENABLE_NODE, &smscb_cmd_cmd);
-	install_element(ENABLE_NODE, &ctrl_trap_cmd);
-
-	abis_nm_vty_init();
-	abis_om2k_vty_init();
-	e1inp_vty_init();
-	osmo_fsm_vty_add_cmds();
-
-	bsc_vty_init_extra();
-
-	return 0;
-}
diff --git a/src/libbsc/bts_ericsson_rbs2000.c b/src/libbsc/bts_ericsson_rbs2000.c
deleted file mode 100644
index 99da4e7..0000000
--- a/src/libbsc/bts_ericsson_rbs2000.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/* Ericsson RBS-2xxx specific code */
-
-/* (C) 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/>.
- *
- */
-
-
-#include <osmocom/gsm/tlv.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/abis_om2000.h>
-#include <openbsc/abis_nm.h>
-#include <osmocom/abis/e1_input.h>
-#include <openbsc/signal.h>
-
-#include <osmocom/abis/lapd.h>
-
-static void bootstrap_om_bts(struct gsm_bts *bts)
-{
-	LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr);
-
-	/* FIXME: this is global init, not bootstrapping */
-	abis_om2k_bts_init(bts);
-	abis_om2k_trx_init(bts->c0);
-
-	/* TODO: Should we wait for a Failure report? */
-	om2k_bts_fsm_start(bts);
-}
-
-static void bootstrap_om_trx(struct gsm_bts_trx *trx)
-{
-	LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for TRX %u/%u\n",
-	     trx->bts->nr, trx->nr);
-	/* FIXME */
-}
-
-static int shutdown_om(struct gsm_bts *bts)
-{
-	/* FIXME */
-	return 0;
-}
-
-
-/* Tell LAPD to start start the SAP (send SABM requests) for all signalling
- * timeslots in this line */
-static void start_sabm_in_line(struct e1inp_line *line, int start)
-{
-	struct e1inp_sign_link *link;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(line->ts); i++) {
-		struct e1inp_ts *ts = &line->ts[i];
-
-		if (ts->type != E1INP_TS_TYPE_SIGN)
-			continue;
-
-		llist_for_each_entry(link, &ts->sign.sign_links, list) {
-			if (!ts->lapd)
-				continue;
-			lapd_instance_set_profile(ts->lapd,
-						  &lapd_profile_abis_ericsson);
-
-			if (start)
-				lapd_sap_start(ts->lapd, link->tei, link->sapi);
-			else
-				lapd_sap_stop(ts->lapd, link->tei, link->sapi);
-		}
-	}
-}
-
-/* Callback function to be called every time we receive a signal from INPUT */
-static int gbl_sig_cb(unsigned int subsys, unsigned int signal,
-		      void *handler_data, void *signal_data)
-{
-	struct gsm_bts *bts;
-
-	if (subsys != SS_L_GLOBAL)
-		return 0;
-
-	switch (signal) {
-	case S_GLOBAL_BTS_CLOSE_OM:
-		bts = signal_data;
-		if (bts->type == GSM_BTS_TYPE_RBS2000)
-			shutdown_om(signal_data);
-		break;
-	}
-
-	return 0;
-}
-
-/* Callback function to be called every time we receive a signal from INPUT */
-static int inp_sig_cb(unsigned int subsys, unsigned int signal,
-		      void *handler_data, void *signal_data)
-{
-	struct input_signal_data *isd = signal_data;
-	struct e1inp_ts *e1i_ts;
-
-	if (subsys != SS_L_INPUT)
-		return 0;
-
-	LOGP(DNM, LOGL_DEBUG, "%s(): Input signal '%s' received\n", __func__,
-			get_value_string(e1inp_signal_names, signal));
-	switch (signal) {
-	case S_L_INP_TEI_UP:
-		switch (isd->link_type) {
-		case E1INP_SIGN_OML:
-			if (isd->trx->bts->type != GSM_BTS_TYPE_RBS2000)
-				break;
-			if (isd->tei == isd->trx->bts->oml_tei)
-				bootstrap_om_bts(isd->trx->bts);
-			else
-				bootstrap_om_trx(isd->trx);
-			break;
-		}
-		break;
-	case S_L_INP_TEI_DN:
-		if (isd->trx->bts->type != GSM_BTS_TYPE_RBS2000)
-			break;
-		LOGP(DNM, LOGL_NOTICE, "Line-%u TS-%u TEI-%u SAPI-%u: Link "
-		     "Lost for Ericsson RBS2000. Re-starting DL Establishment\n",
-		     isd->line->num, isd->ts_nr, isd->tei, isd->sapi);
-		/* Some datalink for a given TEI/SAPI went down, try to re-start it */
-		e1i_ts = &isd->line->ts[isd->ts_nr-1];
-		OSMO_ASSERT(e1i_ts->type == E1INP_TS_TYPE_SIGN);
-		lapd_sap_start(e1i_ts->lapd, isd->tei, isd->sapi);
-		break;
-	case S_L_INP_LINE_INIT:
-	case S_L_INP_LINE_NOALARM:
-		if (strcasecmp(isd->line->driver->name, "DAHDI")
-		 && strcasecmp(isd->line->driver->name, "MISDN_LAPD")
-		 && strcasecmp(isd->line->driver->name, "UNIXSOCKET"))
-			break;
-		start_sabm_in_line(isd->line, 1);
-		break;
-	case S_L_INP_LINE_ALARM:
-		if (strcasecmp(isd->line->driver->name, "DAHDI")
-		 && strcasecmp(isd->line->driver->name, "MISDN_LAPD")
-		 && strcasecmp(isd->line->driver->name, "UNIXSOCKET"))
-			break;
-		start_sabm_in_line(isd->line, 0);
-		break;
-	}
-
-	return 0;
-}
-
-static void config_write_bts(struct vty *vty, struct gsm_bts *bts)
-{
-	abis_om2k_config_write_bts(vty, bts);
-}
-
-static int bts_model_rbs2k_start(struct gsm_network *net);
-
-static void bts_model_rbs2k_e1line_bind_ops(struct e1inp_line *line)
-{
-	e1inp_line_bind_ops(line, &bts_isdn_e1inp_line_ops);
-}
-
-static struct gsm_bts_model model_rbs2k = {
-	.type = GSM_BTS_TYPE_RBS2000,
-	.name = "rbs2000",
-	.start = bts_model_rbs2k_start,
-	.oml_rcvmsg = &abis_om2k_rcvmsg,
-	.config_write_bts = &config_write_bts,
-	.e1line_bind_ops = &bts_model_rbs2k_e1line_bind_ops,
-};
-
-static int bts_model_rbs2k_start(struct gsm_network *net)
-{
-	model_rbs2k.features.data = &model_rbs2k._features_data[0];
-	model_rbs2k.features.data_len = sizeof(model_rbs2k._features_data);
-
-	gsm_btsmodel_set_feature(&model_rbs2k, BTS_FEAT_GPRS);
-	gsm_btsmodel_set_feature(&model_rbs2k, BTS_FEAT_EGPRS);
-	gsm_btsmodel_set_feature(&model_rbs2k, BTS_FEAT_HOPPING);
-	gsm_btsmodel_set_feature(&model_rbs2k, BTS_FEAT_HSCSD);
-	gsm_btsmodel_set_feature(&model_rbs2k, BTS_FEAT_MULTI_TSC);
-
-	osmo_signal_register_handler(SS_L_INPUT, inp_sig_cb, NULL);
-	osmo_signal_register_handler(SS_L_GLOBAL, gbl_sig_cb, NULL);
-
-	return 0;
-}
-
-int bts_model_rbs2k_init(void)
-{
-	return gsm_bts_model_register(&model_rbs2k);
-}
diff --git a/src/libbsc/bts_init.c b/src/libbsc/bts_init.c
deleted file mode 100644
index d6b152a..0000000
--- a/src/libbsc/bts_init.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* (C) 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/>.
- *
- */
-#include <openbsc/bss.h>
-
-int bts_init(void)
-{
-	bts_model_bs11_init();
-	bts_model_rbs2k_init();
-	bts_model_nanobts_init();
-	bts_model_nokia_site_init();
-	bts_model_sysmobts_init();
-	/* Your new BTS here. */
-	return 0;
-}
diff --git a/src/libbsc/bts_ipaccess_nanobts.c b/src/libbsc/bts_ipaccess_nanobts.c
deleted file mode 100644
index a1bde77..0000000
--- a/src/libbsc/bts_ipaccess_nanobts.c
+++ /dev/null
@@ -1,520 +0,0 @@
-/* ip.access nanoBTS specific code */
-
-/* (C) 2009-2010 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/>.
- *
- */
-
-#include <arpa/inet.h>
-
-#include <osmocom/gsm/tlv.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/signal.h>
-#include <openbsc/abis_nm.h>
-#include <osmocom/abis/e1_input.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/talloc.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/debug.h>
-#include <osmocom/abis/subchan_demux.h>
-#include <osmocom/gsm/ipa.h>
-#include <osmocom/abis/ipaccess.h>
-#include <osmocom/core/logging.h>
-#include <openbsc/ipaccess.h>
-#include <openbsc/bts_ipaccess_nanobts_omlattr.h>
-
-extern struct gsm_network *bsc_gsmnet;
-
-static int bts_model_nanobts_start(struct gsm_network *net);
-static void bts_model_nanobts_e1line_bind_ops(struct e1inp_line *line);
-
-struct gsm_bts_model bts_model_nanobts = {
-	.type = GSM_BTS_TYPE_NANOBTS,
-	.name = "nanobts",
-	.start = bts_model_nanobts_start,
-	.oml_rcvmsg = &abis_nm_rcvmsg,
-	.e1line_bind_ops = bts_model_nanobts_e1line_bind_ops, 
-	.nm_att_tlvdef = {
-		.def = {
-			/* ip.access specifics */
-			[NM_ATT_IPACC_DST_IP] =		{ TLV_TYPE_FIXED, 4 },
-			[NM_ATT_IPACC_DST_IP_PORT] =	{ TLV_TYPE_FIXED, 2 },
-			[NM_ATT_IPACC_STREAM_ID] =	{ TLV_TYPE_TV, },
-			[NM_ATT_IPACC_SEC_OML_CFG] =	{ TLV_TYPE_FIXED, 6 },
-			[NM_ATT_IPACC_IP_IF_CFG] =	{ TLV_TYPE_FIXED, 8 },
-			[NM_ATT_IPACC_IP_GW_CFG] =	{ TLV_TYPE_FIXED, 12 },
-			[NM_ATT_IPACC_IN_SERV_TIME] =	{ TLV_TYPE_FIXED, 4 },
-			[NM_ATT_IPACC_LOCATION] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_PAGING_CFG] =	{ TLV_TYPE_FIXED, 2 },
-			[NM_ATT_IPACC_UNIT_ID] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_UNIT_NAME] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_SNMP_CFG] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_PRIM_OML_CFG_LIST] = { TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_NV_FLAGS] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_FREQ_CTRL] =	{ TLV_TYPE_FIXED, 2 },
-			[NM_ATT_IPACC_PRIM_OML_FB_TOUT] = { TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_CUR_SW_CFG] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_TIMING_BUS] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_CGI] =		{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_RAC] =		{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_OBJ_VERSION] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_GPRS_PAGING_CFG]= { TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_NSEI] =		{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_BVCI] =		{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_NSVCI] =		{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_NS_CFG] =		{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_BSSGP_CFG] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_NS_LINK_CFG] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_RLC_CFG] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_ALM_THRESH_LIST]=	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_MONIT_VAL_LIST] = { TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_TIB_CONTROL] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_SUPP_FEATURES] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_CODING_SCHEMES] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_RLC_CFG_2] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_HEARTB_TOUT] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_UPTIME] =		{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_RLC_CFG_3] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_SSL_CFG] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_SEC_POSSIBLE] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_IML_SSL_STATE] =	{ TLV_TYPE_TL16V },
-			[NM_ATT_IPACC_REVOC_DATE] =	{ TLV_TYPE_TL16V },
-		},
-	},
-};
-
-
-/* Callback function to be called whenever we get a GSM 12.21 state change event */
-static int nm_statechg_event(int evt, struct nm_statechg_signal_data *nsd)
-{
-	uint8_t obj_class = nsd->obj_class;
-	void *obj = nsd->obj;
-	struct gsm_nm_state *new_state = nsd->new_state;
-
-	struct gsm_bts *bts;
-	struct gsm_bts_trx *trx;
-	struct gsm_bts_trx_ts *ts;
-	struct gsm_bts_gprs_nsvc *nsvc;
-
-	struct msgb *msgb;
-
-	if (!is_ipaccess_bts(nsd->bts))
-		return 0;
-
-	/* This event-driven BTS setup is currently only required on nanoBTS */
-
-	/* S_NM_STATECHG_ADM is called after we call chg_adm_state() and would create
-	 * endless loop */
-	if (evt != S_NM_STATECHG_OPER)
-		return 0;
-
-	switch (obj_class) {
-	case NM_OC_SITE_MANAGER:
-		bts = container_of(obj, struct gsm_bts, site_mgr);
-		if ((new_state->operational == NM_OPSTATE_ENABLED &&
-		     new_state->availability == NM_AVSTATE_OK) ||
-		    (new_state->operational == NM_OPSTATE_DISABLED &&
-		     new_state->availability == NM_AVSTATE_OFF_LINE))
-			abis_nm_opstart(bts, obj_class, 0xff, 0xff, 0xff);
-		break;
-	case NM_OC_BTS:
-		bts = obj;
-		if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
-			msgb = nanobts_attr_bts_get(bts);
-			abis_nm_set_bts_attr(bts, msgb->data, msgb->len);
-			msgb_free(msgb);
-			abis_nm_chg_adm_state(bts, obj_class,
-					      bts->bts_nr, 0xff, 0xff,
-					      NM_STATE_UNLOCKED);
-			abis_nm_opstart(bts, obj_class,
-					bts->bts_nr, 0xff, 0xff);
-		}
-		break;
-	case NM_OC_CHANNEL:
-		ts = obj;
-		trx = ts->trx;
-		if (new_state->operational == NM_OPSTATE_DISABLED &&
-		    new_state->availability == NM_AVSTATE_DEPENDENCY) {
-			enum abis_nm_chan_comb ccomb =
-						abis_nm_chcomb4pchan(ts->pchan);
-			if (abis_nm_set_channel_attr(ts, ccomb) == -EINVAL) {
-				ipaccess_drop_oml(trx->bts);
-				return -1;
-			}
-			abis_nm_chg_adm_state(trx->bts, obj_class,
-					      trx->bts->bts_nr, trx->nr, ts->nr,
-					      NM_STATE_UNLOCKED);
-			abis_nm_opstart(trx->bts, obj_class,
-					trx->bts->bts_nr, trx->nr, ts->nr);
-		}
-		if (new_state->operational == NM_OPSTATE_ENABLED
-		    && new_state->availability == NM_AVSTATE_OK)
-			dyn_ts_init(ts);
-		break;
-	case NM_OC_RADIO_CARRIER:
-		trx = obj;
-		if (new_state->operational == NM_OPSTATE_DISABLED &&
-		    new_state->availability == NM_AVSTATE_OK)
-			abis_nm_opstart(trx->bts, obj_class, trx->bts->bts_nr,
-					trx->nr, 0xff);
-		break;
-	case NM_OC_GPRS_NSE:
-		bts = container_of(obj, struct gsm_bts, gprs.nse);
-		if (bts->gprs.mode == BTS_GPRS_NONE)
-			break;
-		if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
-			msgb = nanobts_attr_nse_get(bts);
-			abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
-						  0xff, 0xff, msgb->data,
-						  msgb->len);
-			msgb_free(msgb);
-			abis_nm_opstart(bts, obj_class, bts->bts_nr,
-					0xff, 0xff);
-		}
-		break;
-	case NM_OC_GPRS_CELL:
-		bts = container_of(obj, struct gsm_bts, gprs.cell);
-		if (bts->gprs.mode == BTS_GPRS_NONE)
-			break;
-		if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
-			msgb = nanobts_attr_cell_get(bts);
-			abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
-						  0, 0xff, msgb->data,
-						  msgb->len);
-			msgb_free(msgb);
-			abis_nm_opstart(bts, obj_class, bts->bts_nr,
-					0, 0xff);
-			abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
-					      0, 0xff, NM_STATE_UNLOCKED);
-			abis_nm_chg_adm_state(bts, NM_OC_GPRS_NSE, bts->bts_nr,
-					      0xff, 0xff, NM_STATE_UNLOCKED);
-		}
-		break;
-	case NM_OC_GPRS_NSVC:
-		nsvc = obj;
-		bts = nsvc->bts;
-		if (bts->gprs.mode == BTS_GPRS_NONE)
-			break;
-		/* We skip NSVC1 since we only use NSVC0 */
-		if (nsvc->id == 1)
-			break;
-		if ((new_state->availability == NM_AVSTATE_OFF_LINE) ||
-		    (new_state->availability == NM_AVSTATE_DEPENDENCY)) {
-			msgb = nanobts_attr_nscv_get(bts);
-			abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
-						  nsvc->id, 0xff,
-						  msgb->data, msgb->len);
-			msgb_free(msgb);
-			abis_nm_opstart(bts, obj_class, bts->bts_nr,
-					nsvc->id, 0xff);
-			abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
-					      nsvc->id, 0xff,
-					      NM_STATE_UNLOCKED);
-		}
-	default:
-		break;
-	}
-	return 0;
-}
-
-/* Callback function to be called every time we receive a 12.21 SW activated report */
-static int sw_activ_rep(struct msgb *mb)
-{
-	struct abis_om_fom_hdr *foh = msgb_l3(mb);
-	struct e1inp_sign_link *sign_link = mb->dst;
-	struct gsm_bts *bts = sign_link->trx->bts;
-	struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
-
-	if (!trx)
-		return -EINVAL;
-
-	if (!is_ipaccess_bts(trx->bts))
-		return 0;
-
-	switch (foh->obj_class) {
-	case NM_OC_BASEB_TRANSC:
-		abis_nm_chg_adm_state(trx->bts, foh->obj_class,
-				      trx->bts->bts_nr, trx->nr, 0xff,
-				      NM_STATE_UNLOCKED);
-		abis_nm_opstart(trx->bts, foh->obj_class,
-				trx->bts->bts_nr, trx->nr, 0xff);
-		/* TRX software is active, tell it to initiate RSL Link */
-		abis_nm_ipaccess_rsl_connect(trx, trx->bts->ip_access.rsl_ip,
-					     3003, trx->rsl_tei);
-		break;
-	case NM_OC_RADIO_CARRIER: {
-		/*
-		 * Locking the radio carrier will make it go
-		 * offline again and we would come here. The
-		 * framework should determine that there was
-		 * no change and avoid recursion.
-		 *
-		 * This code is here to make sure that on start
-		 * a TRX remains locked.
-		 */
-		int rc_state = trx->mo.nm_state.administrative;
-		/* Patch ARFCN into radio attribute */
-		struct msgb *msgb = nanobts_attr_radio_get(trx->bts, trx);
-		abis_nm_set_radio_attr(trx, msgb->data, msgb->len);
-		msgb_free(msgb);
-		abis_nm_chg_adm_state(trx->bts, foh->obj_class,
-				      trx->bts->bts_nr, trx->nr, 0xff,
-				      rc_state);
-		abis_nm_opstart(trx->bts, foh->obj_class, trx->bts->bts_nr,
-				trx->nr, 0xff);
-		break;
-		}
-	}
-	return 0;
-}
-
-/* Callback function to be called every time we receive a signal from NM */
-static int bts_ipa_nm_sig_cb(unsigned int subsys, unsigned int signal,
-		     void *handler_data, void *signal_data)
-{
-	if (subsys != SS_NM)
-		return 0;
-
-	switch (signal) {
-	case S_NM_SW_ACTIV_REP:
-		return sw_activ_rep(signal_data);
-	case S_NM_STATECHG_OPER:
-	case S_NM_STATECHG_ADM:
-		return nm_statechg_event(signal, signal_data);
-	default:
-		break;
-	}
-	return 0;
-}
-
-static int bts_model_nanobts_start(struct gsm_network *net)
-{
-	osmo_signal_unregister_handler(SS_NM, bts_ipa_nm_sig_cb, NULL);
-	osmo_signal_register_handler(SS_NM, bts_ipa_nm_sig_cb, NULL);
-	return 0;
-}
-
-int bts_model_nanobts_init(void)
-{
-	bts_model_nanobts.features.data = &bts_model_nanobts._features_data[0];
-	bts_model_nanobts.features.data_len =
-				sizeof(bts_model_nanobts._features_data);
-
-	gsm_btsmodel_set_feature(&bts_model_nanobts, BTS_FEAT_GPRS);
-	gsm_btsmodel_set_feature(&bts_model_nanobts, BTS_FEAT_EGPRS);
-	gsm_btsmodel_set_feature(&bts_model_nanobts, BTS_FEAT_MULTI_TSC);
-
-	return gsm_bts_model_register(&bts_model_nanobts);
-}
-
-#define OML_UP         0x0001
-#define RSL_UP         0x0002
-
-static struct gsm_bts *
-find_bts_by_unitid(struct gsm_network *net, uint16_t site_id, uint16_t bts_id)
-{
-	struct gsm_bts *bts;
-
-	llist_for_each_entry(bts, &net->bts_list, list) {
-		if (!is_ipaccess_bts(bts))
-			continue;
-
-		if (bts->ip_access.site_id == site_id &&
-		    bts->ip_access.bts_id == bts_id)
-			return bts;
-	}
-	return NULL;
-}
-
-/* These are exported because they are used by the VTY interface. */
-void ipaccess_drop_rsl(struct gsm_bts_trx *trx)
-{
-	if (!trx->rsl_link)
-		return;
-
-	e1inp_sign_link_destroy(trx->rsl_link);
-	trx->rsl_link = NULL;
-}
-
-void ipaccess_drop_oml(struct gsm_bts *bts)
-{
-	struct gsm_bts *rdep_bts;
-	struct gsm_bts_trx *trx;
-
-	if (!bts->oml_link)
-		return;
-
-	e1inp_sign_link_destroy(bts->oml_link);
-	bts->oml_link = NULL;
-
-	/* we have issues reconnecting RSL, drop everything. */
-	llist_for_each_entry(trx, &bts->trx_list, list)
-		ipaccess_drop_rsl(trx);
-
-	bts->ip_access.flags = 0;
-
-	/*
-	 * Go through the list and see if we are the depndency of a BTS
-	 * and then drop the BTS. This can lead to some recursion but it
-	 * should be fine in userspace.
-	 * The oml_link is serving as recursion anchor for us and
-	 * it is set to NULL some lines above.
-	 */
-	llist_for_each_entry(rdep_bts, &bts->network->bts_list, list) {
-		if (!bts_depend_is_depedency(rdep_bts, bts))
-			continue;
-		LOGP(DLINP, LOGL_NOTICE, "Dropping BTS(%u) due BTS(%u).\n",
-			rdep_bts->nr, bts->nr);
-		ipaccess_drop_oml(rdep_bts);
-	}
-}
-
-/* This function is called once the OML/RSL link becomes up. */
-static struct e1inp_sign_link *
-ipaccess_sign_link_up(void *unit_data, struct e1inp_line *line,
-		      enum e1inp_sign_type type)
-{
-	struct gsm_bts *bts;
-	struct ipaccess_unit *dev = unit_data;
-	struct e1inp_sign_link *sign_link = NULL;
-
-	bts = find_bts_by_unitid(bsc_gsmnet, dev->site_id, dev->bts_id);
-	if (!bts) {
-		LOGP(DLINP, LOGL_ERROR, "Unable to find BTS configuration for "
-			" %u/%u/%u, disconnecting\n", dev->site_id,
-			dev->bts_id, dev->trx_id);
-		return NULL;
-	}
-	DEBUGP(DLINP, "Identified BTS %u/%u/%u\n",
-			dev->site_id, dev->bts_id, dev->trx_id);
-
-	switch(type) {
-	case E1INP_SIGN_OML:
-		/* remove old OML signal link for this BTS. */
-		ipaccess_drop_oml(bts);
-
-		if (!bts_depend_check(bts)) {
-			LOGP(DLINP, LOGL_NOTICE,
-				"Dependency not full-filled for %u/%u/%u\n",
-				dev->site_id, dev->bts_id, dev->trx_id);
-			return NULL;
-		}
-
-		/* create new OML link. */
-		sign_link = bts->oml_link =
-			e1inp_sign_link_create(&line->ts[E1INP_SIGN_OML - 1],
-						E1INP_SIGN_OML, bts->c0,
-						bts->oml_tei, 0);
-		break;
-	case E1INP_SIGN_RSL: {
-		struct e1inp_ts *ts;
-		struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, dev->trx_id);
-
-		/* no OML link set yet? give up. */
-		if (!bts->oml_link || !trx)
-			return NULL;
-
-		/* remove old RSL link for this TRX. */
-		ipaccess_drop_rsl(trx);
-
-		/* set new RSL link for this TRX. */
-		line = bts->oml_link->ts->line;
-		ts = &line->ts[E1INP_SIGN_RSL + dev->trx_id - 1];
-		e1inp_ts_config_sign(ts, line);
-		sign_link = trx->rsl_link =
-				e1inp_sign_link_create(ts, E1INP_SIGN_RSL,
-						       trx, trx->rsl_tei, 0);
-		trx->rsl_link->ts->sign.delay = 0;
-		break;
-	}
-	default:
-		break;
-	}
-	return sign_link;
-}
-
-static void ipaccess_sign_link_down(struct e1inp_line *line)
-{
-	/* No matter what link went down, we close both signal links. */
-	struct e1inp_ts *ts = &line->ts[E1INP_SIGN_OML-1];
-	struct e1inp_sign_link *link;
-
-	llist_for_each_entry(link, &ts->sign.sign_links, list) {
-		struct gsm_bts *bts = link->trx->bts;
-
-		ipaccess_drop_oml(bts);
-		/* Yes, we only use the first element of the list. */
-		break;
-	}
-}
-
-/* This function is called if we receive one OML/RSL message. */
-static int ipaccess_sign_link(struct msgb *msg)
-{
-	int ret = 0;
-	struct e1inp_sign_link *link = msg->dst;
-	struct e1inp_ts *e1i_ts = link->ts;
-
-	switch (link->type) {
-	case E1INP_SIGN_RSL:
-		if (!(link->trx->bts->ip_access.flags &
-					(RSL_UP << link->trx->nr))) {
-			e1inp_event(e1i_ts, S_L_INP_TEI_UP,
-					link->tei, link->sapi);
-			link->trx->bts->ip_access.flags |=
-					(RSL_UP << link->trx->nr);
-		}
-	        ret = abis_rsl_rcvmsg(msg);
-	        break;
-	case E1INP_SIGN_OML:
-		if (!(link->trx->bts->ip_access.flags & OML_UP)) {
-			e1inp_event(e1i_ts, S_L_INP_TEI_UP,
-					link->tei, link->sapi);
-			link->trx->bts->ip_access.flags |= OML_UP;
-		}
-	        ret = abis_nm_rcvmsg(msg);
-	        break;
-	default:
-		LOGP(DLINP, LOGL_ERROR, "Unknown signal link type %d\n",
-			link->type);
-		msgb_free(msg);
-		break;
-	}
-	return ret;
-}
-
-/* not static, ipaccess-config needs it. */
-struct e1inp_line_ops ipaccess_e1inp_line_ops = {
-	.cfg = {
-		.ipa = {
-			.addr = "0.0.0.0",
-			.role = E1INP_LINE_R_BSC,
-		},
-	},
-	.sign_link_up	= ipaccess_sign_link_up,
-	.sign_link_down	= ipaccess_sign_link_down,
-	.sign_link	= ipaccess_sign_link,
-};
-
-static void bts_model_nanobts_e1line_bind_ops(struct e1inp_line *line)
-{
-        e1inp_line_bind_ops(line, &ipaccess_e1inp_line_ops);
-}
diff --git a/src/libbsc/bts_ipaccess_nanobts_omlattr.c b/src/libbsc/bts_ipaccess_nanobts_omlattr.c
deleted file mode 100644
index 473e1ca..0000000
--- a/src/libbsc/bts_ipaccess_nanobts_omlattr.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/* ip.access nanoBTS specific code, OML attribute table generator */
-
-/* (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/>.
- */
-
-#include <arpa/inet.h>
-#include <osmocom/core/msgb.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/abis_nm.h>
-
-static void patch_16(uint8_t *data, const uint16_t val)
-{
-	memcpy(data, &val, sizeof(val));
-}
-
-static void patch_32(uint8_t *data, const uint32_t val)
-{
-	memcpy(data, &val, sizeof(val));
-}
-
-struct msgb *nanobts_attr_bts_get(struct gsm_bts *bts)
-{
-	struct msgb *msgb;
-	uint8_t buf[256];
-	int rlt;
-	msgb = msgb_alloc(1024, "nanobts_attr_bts");
-
-	memcpy(buf, "\x55\x5b\x61\x67\x6d\x73", 6);
-	msgb_tv_fixed_put(msgb, NM_ATT_INTERF_BOUND, 6, buf);
-
-	/* interference avg. period in numbers of SACCH multifr */
-	msgb_tv_put(msgb, NM_ATT_INTAVE_PARAM, 0x06);
-
-	rlt = gsm_bts_get_radio_link_timeout(bts);
-	if (rlt == -1) {
-		/* Osmocom extension: Use infinite radio link timeout */
-		buf[0] = 0xFF;
-		buf[1] = 0x00;
-	} else {
-		/* conn fail based on SACCH error rate */
-		buf[0] = 0x01;
-		buf[1] = rlt;
-	}
-	msgb_tl16v_put(msgb, NM_ATT_CONN_FAIL_CRIT, 2, buf);
-
-	memcpy(buf, "\x1e\x24\x24\xa8\x34\x21\xa8", 7);
-	msgb_tv_fixed_put(msgb, NM_ATT_T200, 7, buf);
-
-	msgb_tv_put(msgb, NM_ATT_MAX_TA, 0x3f);
-
-	/* seconds */
-	memcpy(buf, "\x00\x01\x0a", 3);
-	msgb_tv_fixed_put(msgb, NM_ATT_OVERL_PERIOD, 3, buf);
-
-	/* percent */
-	msgb_tv_put(msgb, NM_ATT_CCCH_L_T, 10);
-
-	/* seconds */
-	msgb_tv_put(msgb, NM_ATT_CCCH_L_I_P, 1);
-
-	/* busy threshold in - dBm */
-	buf[0] = 10;
-	if (bts->rach_b_thresh != -1)
-		buf[0] = bts->rach_b_thresh & 0xff;
-	msgb_tv_put(msgb, NM_ATT_RACH_B_THRESH, buf[0]);
-
-	/* rach load averaging 1000 slots */
-	buf[0] = 0x03;
-	buf[1] = 0xe8;
-	if (bts->rach_ldavg_slots != -1) {
-		buf[0] = (bts->rach_ldavg_slots >> 8) & 0x0f;
-		buf[1] = bts->rach_ldavg_slots & 0xff;
-	}
-	msgb_tv_fixed_put(msgb, NM_ATT_LDAVG_SLOTS, 2, buf);
-
-	/* miliseconds */
-	msgb_tv_put(msgb, NM_ATT_BTS_AIR_TIMER, 128);
-
-	/* 10 retransmissions of physical config */
-	msgb_tv_put(msgb, NM_ATT_NY1, 10);
-
-	buf[0] = (bts->c0->arfcn >> 8) & 0x0f;
-	buf[1] = bts->c0->arfcn & 0xff;
-	msgb_tv_fixed_put(msgb, NM_ATT_BCCH_ARFCN, 2, buf);
-
-	msgb_tv_put(msgb, NM_ATT_BSIC, bts->bsic);
-
-	abis_nm_ipaccess_cgi(buf, bts);
-	msgb_tl16v_put(msgb, NM_ATT_IPACC_CGI, 7, buf);
-
-	return msgb;
-}
-
-struct msgb *nanobts_attr_nse_get(struct gsm_bts *bts)
-{
-	struct msgb *msgb;
-	uint8_t buf[256];
-	msgb = msgb_alloc(1024, "nanobts_attr_bts");
-
-	/* NSEI 925 */
-	buf[0] = bts->gprs.nse.nsei >> 8;
-	buf[1] = bts->gprs.nse.nsei & 0xff;
-	msgb_tl16v_put(msgb, NM_ATT_IPACC_NSEI, 2, buf);
-
-	/* all timers in seconds */
-	OSMO_ASSERT(ARRAY_SIZE(bts->gprs.nse.timer) < sizeof(buf));
-	memcpy(buf, bts->gprs.nse.timer, ARRAY_SIZE(bts->gprs.nse.timer));
-	msgb_tl16v_put(msgb, NM_ATT_IPACC_NS_CFG, 7, buf);
-
-	/* all timers in seconds */
-	buf[0] = 3;	/* blockimg timer (T1) */
-	buf[1] = 3;	/* blocking retries */
-	buf[2] = 3;	/* unblocking retries */
-	buf[3] = 3;	/* reset timer (T2) */
-	buf[4] = 3;	/* reset retries */
-	buf[5] = 10;	/* suspend timer (T3) in 100ms */
-	buf[6] = 3;	/* suspend retries */
-	buf[7] = 10;	/* resume timer (T4) in 100ms */
-	buf[8] = 3;	/* resume retries */
-	buf[9] = 10;	/* capability update timer (T5) */
-	buf[10] = 3;	/* capability update retries */
-
-	OSMO_ASSERT(ARRAY_SIZE(bts->gprs.cell.timer) < sizeof(buf));
-	memcpy(buf, bts->gprs.cell.timer, ARRAY_SIZE(bts->gprs.cell.timer));
-	msgb_tl16v_put(msgb, NM_ATT_IPACC_BSSGP_CFG, 11, buf);
-
-	return msgb;
-}
-
-struct msgb *nanobts_attr_cell_get(struct gsm_bts *bts)
-{
-	struct msgb *msgb;
-	uint8_t buf[256];
-	msgb = msgb_alloc(1024, "nanobts_attr_bts");
-
-	/* routing area code */
-	buf[0] = bts->gprs.rac;
-	msgb_tl16v_put(msgb, NM_ATT_IPACC_RAC, 1, buf);
-
-	buf[0] = 5;	/* repeat time (50ms) */
-	buf[1] = 3;	/* repeat count */
-	msgb_tl16v_put(msgb, NM_ATT_IPACC_GPRS_PAGING_CFG, 2, buf);
-
-	/* BVCI 925 */
-	buf[0] = bts->gprs.cell.bvci >> 8;
-	buf[1] = bts->gprs.cell.bvci & 0xff;
-	msgb_tl16v_put(msgb, NM_ATT_IPACC_BVCI, 2, buf);
-
-	/* all timers in seconds, unless otherwise stated */
-	buf[0] = 20;	/* T3142 */
-	buf[1] = 5;	/* T3169 */
-	buf[2] = 5;	/* T3191 */
-	buf[3] = 160;	/* T3193 (units of 10ms) */
-	buf[4] = 5;	/* T3195 */
-	buf[5] = 10;	/* N3101 */
-	buf[6] = 4;	/* N3103 */
-	buf[7] = 8;	/* N3105 */
-	buf[8] = 15;	/* RLC CV countdown */
-	msgb_tl16v_put(msgb, NM_ATT_IPACC_RLC_CFG, 9, buf);
-
-	if (bts->gprs.mode == BTS_GPRS_EGPRS) {
-		buf[0] = 0x8f;
-		buf[1] = 0xff;
-	} else {
-		buf[0] = 0x0f;
-		buf[1] = 0x00;
-	}
-	msgb_tl16v_put(msgb, NM_ATT_IPACC_CODING_SCHEMES, 2, buf);
-
-	buf[0] = 0;	/* T downlink TBF extension (0..500, high byte) */
-	buf[1] = 250;	/* T downlink TBF extension (0..500, low byte) */
-	buf[2] = 0;	/* T uplink TBF extension (0..500, high byte) */
-	buf[3] = 250;	/* T uplink TBF extension (0..500, low byte) */
-	buf[4] = 2;	/* CS2 */
-	msgb_tl16v_put(msgb, NM_ATT_IPACC_RLC_CFG_2, 5, buf);
-
-#if 0
-	/* EDGE model only, breaks older models.
-	 * Should inquire the BTS capabilities */
-	buf[0] = 2;		/* MCS2 */
-	msgb_tl16v_put(msgb, NM_ATT_IPACC_RLC_CFG_3, 1, buf);
-#endif
-
-	return msgb;
-}
-
-struct msgb *nanobts_attr_nscv_get(struct gsm_bts *bts)
-{
-	struct msgb *msgb;
-	uint8_t buf[256];
-	msgb = msgb_alloc(1024, "nanobts_attr_bts");
-
-	/* 925 */
-	buf[0] = bts->gprs.nsvc[0].nsvci >> 8;
-	buf[1] = bts->gprs.nsvc[0].nsvci & 0xff;
-	msgb_tl16v_put(msgb, NM_ATT_IPACC_NSVCI, 2, buf);
-
-	/* remote udp port */
-	patch_16(&buf[0], htons(bts->gprs.nsvc[0].remote_port));
-	/* remote ip address */
-	patch_32(&buf[2], htonl(bts->gprs.nsvc[0].remote_ip));
-	/* local udp port */
-	patch_16(&buf[6], htons(bts->gprs.nsvc[0].local_port));
-	msgb_tl16v_put(msgb, NM_ATT_IPACC_NS_LINK_CFG, 8, buf);
-
-	return msgb;
-}
-
-struct msgb *nanobts_attr_radio_get(struct gsm_bts *bts,
-				    struct gsm_bts_trx *trx)
-{
-	struct msgb *msgb;
-	uint8_t buf[256];
-	msgb = msgb_alloc(1024, "nanobts_attr_bts");
-
-	/* number of -2dB reduction steps / Pn */
-	msgb_tv_put(msgb, NM_ATT_RF_MAXPOWR_R, trx->max_power_red / 2);
-
-	buf[0] = trx->arfcn >> 8;
-	buf[1] = trx->arfcn & 0xff;
-	msgb_tl16v_put(msgb, NM_ATT_ARFCN_LIST, 2, buf);
-
-	return msgb;
-}
diff --git a/src/libbsc/bts_nokia_site.c b/src/libbsc/bts_nokia_site.c
deleted file mode 100644
index 3ca76c0..0000000
--- a/src/libbsc/bts_nokia_site.c
+++ /dev/null
@@ -1,1739 +0,0 @@
-/* Nokia XXXsite family specific code */
-
-/* (C) 2011 by Dieter Spaar <spaar@mirider.augusta.de>
- *
- * 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/>.
- *
- */
-
-/*
-  TODO: Attention: There are some static variables used for states during
-  configuration. Those variables have to be moved to a BTS specific context,
-  otherwise there will most certainly be problems if more than one Nokia BTS
-  is used.
-*/
-
-#include <time.h>
-
-#include <osmocom/gsm/tlv.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/abis_nm.h>
-#include <osmocom/abis/e1_input.h>
-#include <openbsc/signal.h>
-
-#include <osmocom/core/timer.h>
-
-#include <osmocom/abis/lapd.h>
-
-/* TODO: put in a separate file ? */
-
-extern int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg);
-/* was static in system_information.c */
-extern int generate_cell_chan_list(uint8_t * chan_list, struct gsm_bts *bts);
-
-static void nokia_abis_nm_queue_send_next(struct gsm_bts *bts);
-static void reset_timer_cb(void *_bts);
-static int abis_nm_reset(struct gsm_bts *bts, uint16_t ref);
-static int dump_elements(uint8_t * data, int len) __attribute__((unused));
-
-static void bootstrap_om_bts(struct gsm_bts *bts)
-{
-	LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr);
-
-	if (!bts->nokia.skip_reset) {
-		if (!bts->nokia.did_reset)
-			abis_nm_reset(bts, 1);
-	} else
-		bts->nokia.did_reset = 1;
-}
-
-static void bootstrap_om_trx(struct gsm_bts_trx *trx)
-{
-	LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for TRX %u/%u\n",
-	     trx->bts->nr, trx->nr);
-}
-
-static int shutdown_om(struct gsm_bts *bts)
-{
-	/* TODO !? */
-	return 0;
-}
-
-#define SAPI_OML    62
-#define SAPI_RSL    0
-
-/*
-
-  Tell LAPD to start start the SAP (send SABM requests) for all signalling
-  timeslots in this line
-
-  Attention: this has to be adapted for mISDN
-*/
-
-static void start_sabm_in_line(struct e1inp_line *line, int start, int sapi)
-{
-	struct e1inp_sign_link *link;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(line->ts); i++) {
-		struct e1inp_ts *ts = &line->ts[i];
-
-		if (ts->type != E1INP_TS_TYPE_SIGN)
-			continue;
-
-		llist_for_each_entry(link, &ts->sign.sign_links, list) {
-			if (sapi != -1 && link->sapi != sapi)
-				continue;
-
-#if 0				/* debugging */
-			printf("sap start/stop (%d): %d tei=%d sapi=%d\n",
-			       start, i + 1, link->tei, link->sapi);
-#endif
-
-			if (start) {
-				ts->lapd->profile.t200_sec = 1;
-				ts->lapd->profile.t200_usec = 0;
-				lapd_sap_start(ts->lapd, link->tei,
-					       link->sapi);
-			} else
-				lapd_sap_stop(ts->lapd, link->tei,
-					      link->sapi);
-		}
-	}
-}
-
-/* Callback function to be called every time we receive a signal from INPUT */
-static int gbl_sig_cb(unsigned int subsys, unsigned int signal,
-		      void *handler_data, void *signal_data)
-{
-	struct gsm_bts *bts;
-
-	if (subsys != SS_L_GLOBAL)
-		return 0;
-
-	switch (signal) {
-	case S_GLOBAL_BTS_CLOSE_OM:
-		bts = signal_data;
-		if (bts->type == GSM_BTS_TYPE_NOKIA_SITE)
-			shutdown_om(signal_data);
-		break;
-	}
-
-	return 0;
-}
-
-/* Callback function to be called every time we receive a signal from INPUT */
-static int inp_sig_cb(unsigned int subsys, unsigned int signal,
-		      void *handler_data, void *signal_data)
-{
-	struct input_signal_data *isd = signal_data;
-
-	if (subsys != SS_L_INPUT)
-		return 0;
-
-	switch (signal) {
-	case S_L_INP_LINE_INIT:
-		start_sabm_in_line(isd->line, 1, SAPI_OML);	/* start only OML */
-		break;
-	case S_L_INP_TEI_DN:
-		break;
-	case S_L_INP_TEI_UP:
-		switch (isd->link_type) {
-		case E1INP_SIGN_OML:
-			if (isd->trx->bts->type != GSM_BTS_TYPE_NOKIA_SITE)
-				break;
-
-			if (isd->tei == isd->trx->bts->oml_tei)
-				bootstrap_om_bts(isd->trx->bts);
-			else
-				bootstrap_om_trx(isd->trx);
-			break;
-		}
-		break;
-	case S_L_INP_TEI_UNKNOWN:
-		/* We are receiving LAPD frames with one TEI that we do not
-		 * seem to know, likely that we (the BSC) stopped working
-		 * and lost our local states. However, the BTS is already
-		 * configured, we try to take over the RSL links. */
-		start_sabm_in_line(isd->line, 1, SAPI_RSL);
-		break;
-	}
-
-	return 0;
-}
-
-static void nm_statechg_evt(unsigned int signal,
-			    struct nm_statechg_signal_data *nsd)
-{
-	if (nsd->bts->type != GSM_BTS_TYPE_NOKIA_SITE)
-		return;
-}
-
-static int nm_sig_cb(unsigned int subsys, unsigned int signal,
-		     void *handler_data, void *signal_data)
-{
-	if (subsys != SS_NM)
-		return 0;
-
-	switch (signal) {
-	case S_NM_STATECHG_OPER:
-	case S_NM_STATECHG_ADM:
-		nm_statechg_evt(signal, signal_data);
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-/* TODO: put in a separate file ? */
-
-static const struct value_string nokia_msgt_name[] = {
-	{ 0x80, "NOKIA_BTS_CONF_DATA" },
-	{ 0x81, "NOKIA_BTS_ACK" },
-	{ 0x82, "NOKIA_BTS_OMU_STARTED" },
-	{ 0x83, "NOKIA_BTS_START_DOWNLOAD_REQ" },
-	{ 0x84, "NOKIA_BTS_MF_REQ" },
-	{ 0x85, "NOKIA_BTS_AF_REQ" },
-	{ 0x86, "NOKIA_BTS_RESET_REQ" },
-	{ 0x87, "NOKIA_reserved" },
-	{ 0x88, "NOKIA_BTS_CONF_REQ" },
-	{ 0x89, "NOKIA_BTS_TEST_REQ" },
-	{ 0x8A, "NOKIA_BTS_TEST_REPORT" },
-	{ 0x8B, "NOKIA_reserved" },
-	{ 0x8C, "NOKIA_reserved" },
-	{ 0x8D, "NOKIA_reserved" },
-	{ 0x8E, "NOKIA_BTS_CONF_COMPL" },
-	{ 0x8F, "NOKIA_reserved" },
-	{ 0x90, "NOKIA_BTS_STM_TEST_REQ" },
-	{ 0x91, "NOKIA_BTS_STM_TEST_REPORT" },
-	{ 0x92, "NOKIA_BTS_TRANSMISSION_COMMAND" },
-	{ 0x93, "NOKIA_BTS_TRANSMISSION_ANSWER" },
-	{ 0x94, "NOKIA_BTS_HW_DB_UPLOAD_REQ" },
-	{ 0x95, "NOKIA_BTS_START_HW_DB_DOWNLOAD_REQ" },
-	{ 0x96, "NOKIA_BTS_HW_DB_SAVE_REQ" },
-	{ 0x97, "NOKIA_BTS_FLASH_ERASURE_REQ" },
-	{ 0x98, "NOKIA_BTS_HW_DB_DOWNLOAD_REQ" },
-	{ 0x99, "NOKIA_BTS_PWR_SUPPLY_CONTROL" },
-	{ 0x9A, "NOKIA_BTS_ATTRIBUTE_REQ" },
-	{ 0x9B, "NOKIA_BTS_ATTRIBUTE_REPORT" },
-	{ 0x9C, "NOKIA_BTS_HW_REQ" },
-	{ 0x9D, "NOKIA_BTS_HW_REPORT" },
-	{ 0x9E, "NOKIA_BTS_RTE_TEST_REQ" },
-	{ 0x9F, "NOKIA_BTS_RTE_TEST_REPORT" },
-	{ 0xA0, "NOKIA_BTS_HW_DB_VERIFICATION_REQ" },
-	{ 0xA1, "NOKIA_BTS_CLOCK_REQ" },
-	{ 0xA2, "NOKIA_AC_CIRCUIT_REQ_NACK" },
-	{ 0xA3, "NOKIA_AC_INTERRUPTED" },
-	{ 0xA4, "NOKIA_BTS_NEW_TRE_INFO" },
-	{ 0xA5, "NOKIA_AC_BSC_CIRCUITS_ALLOCATED" },
-	{ 0xA6, "NOKIA_BTS_TRE_POLL_LIST" },
-	{ 0xA7, "NOKIA_AC_CIRCUIT_REQ" },
-	{ 0xA8, "NOKIA_BTS_BLOCK_CTRL_REQ" },
-	{ 0xA9, "NOKIA_BTS_GSM_TIME_REQ" },
-	{ 0xAA, "NOKIA_BTS_GSM_TIME" },
-	{ 0xAB, "NOKIA_BTS_OUTPUT_CONTROL" },
-	{ 0xAC, "NOKIA_BTS_STATE_CHANGED" },
-	{ 0xAD, "NOKIA_BTS_SW_SAVE_REQ" },
-	{ 0xAE, "NOKIA_BTS_ALARM" },
-	{ 0xAF, "NOKIA_BTS_CHA_ADM_STATE" },
-	{ 0xB0, "NOKIA_AC_POOL_SIZE_REPORT" },
-	{ 0xB1, "NOKIA_AC_POOL_SIZE_INQUIRY" },
-	{ 0xB2, "NOKIA_BTS_COMMISS_TEST_COMPLETED" },
-	{ 0xB3, "NOKIA_BTS_COMMISS_TEST_REQ" },
-	{ 0xB4, "NOKIA_BTS_TRANSP_BTS_TO_BSC" },
-	{ 0xB5, "NOKIA_BTS_TRANSP_BSC_TO_BTS" },
-	{ 0xB6, "NOKIA_BTS_LCS_COMMAND" },
-	{ 0xB7, "NOKIA_BTS_LCS_ANSWER" },
-	{ 0xB8, "NOKIA_BTS_LMU_FN_OFFSET_COMMAND" },
-	{ 0xB9, "NOKIA_BTS_LMU_FN_OFFSET_ANSWER" },
-	{ 0, NULL }
-};
-
-static const char *get_msg_type_name_string(uint8_t msg_type)
-{
-	return get_value_string(nokia_msgt_name, msg_type);
-}
-
-static const struct value_string nokia_element_name[] = {
-	{ 0x01, "Ny1" },
-	{ 0x02, "T3105_F" },
-	{ 0x03, "Interference band limits" },
-	{ 0x04, "Interference report timer in secs" },
-	{ 0x05, "Channel configuration per TS" },
-	{ 0x06, "BSIC" },
-	{ 0x07, "RACH report timer in secs" },
-	{ 0x08, "Hardware database status" },
-	{ 0x09, "BTS RX level" },
-	{ 0x0A, "ARFN" },
-	{ 0x0B, "STM antenna attenuation" },
-	{ 0x0C, "Cell allocation bitmap" },
-	{ 0x0D, "Radio definition per TS" },
-	{ 0x0E, "Frame number" },
-	{ 0x0F, "Antenna diversity" },
-	{ 0x10, "T3105_D" },
-	{ 0x11, "File format" },
-	{ 0x12, "Last File" },
-	{ 0x13, "BTS type" },
-	{ 0x14, "Erasure mode" },
-	{ 0x15, "Hopping mode" },
-	{ 0x16, "Floating TRX" },
-	{ 0x17, "Power supplies" },
-	{ 0x18, "Reset type" },
-	{ 0x19, "Averaging period" },
-	{ 0x1A, "RBER2" },
-	{ 0x1B, "LAC" },
-	{ 0x1C, "CI" },
-	{ 0x1D, "Failure parameters" },
-	{ 0x1E, "(RF max power reduction)" },
-	{ 0x1F, "Measured RX_SENS" },
-	{ 0x20, "Extended cell radius" },
-	{ 0x21, "reserved" },
-	{ 0x22, "Success-Failure" },
-	{ 0x23, "Ack-Nack" },
-	{ 0x24, "OMU test results" },
-	{ 0x25, "File identity" },
-	{ 0x26, "Generation and version code" },
-	{ 0x27, "SW description" },
-	{ 0x28, "BCCH LEV" },
-	{ 0x29, "Test type" },
-	{ 0x2A, "Subscriber number" },
-	{ 0x2B, "reserved" },
-	{ 0x2C, "HSN" },
-	{ 0x2D, "reserved" },
-	{ 0x2E, "MS RXLEV" },
-	{ 0x2F, "MS TXLEV" },
-	{ 0x30, "RXQUAL" },
-	{ 0x31, "RX SENS" },
-	{ 0x32, "Alarm block" },
-	{ 0x33, "Neighbouring BCCH levels" },
-	{ 0x34, "STM report type" },
-	{ 0x35, "MA" },
-	{ 0x36, "MAIO" },
-	{ 0x37, "H_FLAG" },
-	{ 0x38, "TCH_ARFN" },
-	{ 0x39, "Clock output" },
-	{ 0x3A, "Transmitted power" },
-	{ 0x3B, "Clock sync" },
-	{ 0x3C, "TMS protocol discriminator" },
-	{ 0x3D, "TMS protocol data" },
-	{ 0x3E, "FER" },
-	{ 0x3F, "SWR result" },
-	{ 0x40, "Object identity" },
-	{ 0x41, "STM RX Antenna Test" },
-	{ 0x42, "reserved" },
-	{ 0x43, "reserved" },
-	{ 0x44, "Object current state" },
-	{ 0x45, "reserved" },
-	{ 0x46, "FU channel configuration" },
-	{ 0x47, "reserved" },
-	{ 0x48, "ARFN of a CU" },
-	{ 0x49, "FU radio definition" },
-	{ 0x4A, "reserved" },
-	{ 0x4B, "Severity" },
-	{ 0x4C, "Diversity selection" },
-	{ 0x4D, "RX antenna test" },
-	{ 0x4E, "RX antenna supervision period" },
-	{ 0x4F, "RX antenna state" },
-	{ 0x50, "Sector configuration" },
-	{ 0x51, "Additional info" },
-	{ 0x52, "SWR parameters" },
-	{ 0x53, "HW inquiry mode" },
-	{ 0x54, "reserved" },
-	{ 0x55, "Availability status" },
-	{ 0x56, "reserved" },
-	{ 0x57, "EAC inputs" },
-	{ 0x58, "EAC outputs" },
-	{ 0x59, "reserved" },
-	{ 0x5A, "Position" },
-	{ 0x5B, "HW unit identity" },
-	{ 0x5C, "RF test signal attenuation" },
-	{ 0x5D, "Operational state" },
-	{ 0x5E, "Logical object identity" },
-	{ 0x5F, "reserved" },
-	{ 0x60, "BS_TXPWR_OM" },
-	{ 0x61, "Loop_Duration" },
-	{ 0x62, "LNA_Path_Selection" },
-	{ 0x63, "Serial number" },
-	{ 0x64, "HW version" },
-	{ 0x65, "Obj. identity and obj. state" },
-	{ 0x66, "reserved" },
-	{ 0x67, "EAC input definition" },
-	{ 0x68, "EAC id and text" },
-	{ 0x69, "HW unit status" },
-	{ 0x6A, "SW release version" },
-	{ 0x6B, "FW version" },
-	{ 0x6C, "Bit_Error_Ratio" },
-	{ 0x6D, "RXLEV_with_Attenuation" },
-	{ 0x6E, "RXLEV_without_Attenuation" },
-	{ 0x6F, "reserved" },
-	{ 0x70, "CU_Results" },
-	{ 0x71, "reserved" },
-	{ 0x72, "LNA_Path_Results" },
-	{ 0x73, "RTE Results" },
-	{ 0x74, "Real Time" },
-	{ 0x75, "RX diversity selection" },
-	{ 0x76, "EAC input config" },
-	{ 0x77, "Feature support" },
-	{ 0x78, "File version" },
-	{ 0x79, "Outputs" },
-	{ 0x7A, "FU parameters" },
-	{ 0x7B, "Diagnostic info" },
-	{ 0x7C, "FU BSIC" },
-	{ 0x7D, "TRX Configuration" },
-	{ 0x7E, "Download status" },
-	{ 0x7F, "RX difference limit" },
-	{ 0x80, "TRX HW capability" },
-	{ 0x81, "Common HW config" },
-	{ 0x82, "Autoconfiguration pool size" },
-	{ 0x83, "TRE diagnostic info" },
-	{ 0x84, "TRE object identity" },
-	{ 0x85, "New TRE Info" },
-	{ 0x86, "Acknowledgement period" },
-	{ 0x87, "Synchronization mode" },
-	{ 0x88, "reserved" },
-	{ 0x89, "Block Control Data" },
-	{ 0x8A, "SW load mode" },
-	{ 0x8B, "Recommended recovery action" },
-	{ 0x8C, "BSC BCF id" },
-	{ 0x8D, "Q1 baud rate" },
-	{ 0x8E, "Allocation status" },
-	{ 0x8F, "Functional entity number" },
-	{ 0x90, "Transmission delay" },
-	{ 0x91, "Loop Duration ms" },
-	{ 0x92, "Logical channel" },
-	{ 0x93, "Q1 address" },
-	{ 0x94, "Alarm detail" },
-	{ 0x95, "Cabinet type" },
-	{ 0x96, "HW unit existence" },
-	{ 0x97, "RF power parameters" },
-	{ 0x98, "Message scenario" },
-	{ 0x99, "HW unit max amount" },
-	{ 0x9A, "Master TRX" },
-	{ 0x9B, "Transparent data" },
-	{ 0x9C, "BSC topology info" },
-	{ 0x9D, "Air i/f modulation" },
-	{ 0x9E, "LCS Q1 command data" },
-	{ 0x9F, "Frame number offset" },
-	{ 0xA0, "Abis TSL" },
-	{ 0xA1, "Dynamic pool info" },
-	{ 0xA2, "LCS LLP data" },
-	{ 0xA3, "LCS Q1 answer data" },
-	{ 0xA4, "DFCA FU Radio Definition" },
-	{ 0xA5, "Antenna hopping" },
-	{ 0xA6, "Field record sequence number" },
-	{ 0xA7, "Timeslot offslot" },
-	{ 0xA8, "EPCR capability" },
-	{ 0xA9, "Connectsite optional element" },
-	{ 0xAA, "TSC" },
-	{ 0xAB, "Special TX Power Setting" },
-	{ 0xAC, "Optional sync settings" },
-	{ 0xFA, "Abis If parameters" },
-	{ 0, NULL }
-};
-
-static const char *get_element_name_string(uint16_t element)
-{
-	return get_value_string(nokia_element_name, element);
-}
-
-static const struct value_string nokia_bts_types[] = {
-	{ 0x0a, 	"MetroSite GSM 900" },
-	{ 0x0b,		"MetroSite GSM 1800" },
-	{ 0x0c,		"MetroSite GSM 1900 (PCS)" },
-	{ 0x0d,		"MetroSite GSM 900 & 1800" },
-	{ 0x0e,		"InSite GSM 900" },
-	{ 0x0f,		"InSite GSM 1800" },
-	{ 0x10,		"InSite GSM 1900" },
-	{ 0x11,		"UltraSite GSM 900" },
-	{ 0x12,		"UltraSite GSM 1800" },
-	{ 0x13,		"UltraSite GSM/US-TDMA 1900" },
-	{ 0x14,		"UltraSite GSM 900 & 1800" },
-	{ 0x16,		"UltraSite GSM/US-TDMA 850" },
-	{ 0x18,		"MetroSite GSM/US-TDMA 850" },
-	{ 0x19,		"UltraSite GSM 800/1900" },
-	{ 0, 		NULL }
-};
-
-static const char *get_bts_type_string(uint8_t type)
-{
-	return get_value_string(nokia_bts_types, type);
-}
-
-static const struct value_string nokia_severity[] = {
-	{ 0,	"indeterminate" },
-	{ 1,	"critical" },
-	{ 2,	"major" },
-	{ 3,	"minor" },
-	{ 4,	"warning" },
-	{ 0,	NULL }
-};
-
-static const char *get_severity_string(uint8_t severity)
-{
-	return get_value_string(nokia_severity, severity);
-}
-
-/* TODO: put in a separate file ? */
-
-/* some message IDs */
-
-#define NOKIA_MSG_CONF_DATA             128
-#define NOKIA_MSG_ACK                   129
-#define NOKIA_MSG_OMU_STARTED           130
-#define NOKIA_MSG_START_DOWNLOAD_REQ    131
-#define NOKIA_MSG_MF_REQ                132
-#define NOKIA_MSG_RESET_REQ             134
-#define NOKIA_MSG_CONF_REQ              136
-#define NOKIA_MSG_CONF_COMPLETE         142
-#define NOKIA_MSG_BLOCK_CTRL_REQ        168
-#define NOKIA_MSG_STATE_CHANGED         172
-#define NOKIA_MSG_ALARM                 174
-
-/* some element IDs */
-
-#define NOKIA_EI_BTS_TYPE       0x13
-#define NOKIA_EI_ACK            0x23
-#define NOKIA_EI_ADD_INFO       0x51
-#define NOKIA_EI_SEVERITY       0x4B
-#define NOKIA_EI_ALARM_DETAIL   0x94
-
-#define OM_ALLOC_SIZE       1024
-#define OM_HEADROOM_SIZE    128
-
-static uint8_t fu_config_template[] = {
-	0x7F, 0x7A, 0x39,
-	/* ID = 0x7A (FU parameters) ## constructed ## */
-	/* length = 57 */
-	/* [3] */
-
-	0x5F, 0x40, 0x04,
-	/* ID = 0x40 (Object identity) */
-	/* length = 4 */
-	/* [6] */
-	0x00, 0x07, 0x01, 0xFF,
-
-	0x41, 0x02,
-	/* ID = 0x01 (Ny1) */
-	/* length = 2 */
-	/* [12] */
-	0x00, 0x05,
-
-	0x42, 0x02,
-	/* ID = 0x02 (T3105_F) */
-	/* length = 2 */
-	/* [16] */
-	0x00, 0x28, /* FIXME: use net->T3105 */
-
-	0x50, 0x02,
-	/* ID = 0x10 (T3105_D) */
-	/* length = 2 */
-	/* [20] */
-	0x00, 0x28, /* FIXME: use net->T3105 */
-
-	0x43, 0x05,
-	/* ID = 0x03 (Interference band limits) */
-	/* length = 5 */
-	/* [24] */
-	0x0F, 0x1B, 0x27, 0x33, 0x3F,
-
-	0x44, 0x02,
-	/* ID = 0x04 (Interference report timer in secs) */
-	/* length = 2 */
-	/* [31] */
-	0x00, 0x10,
-
-	0x47, 0x01,
-	/* ID = 0x07 (RACH report timer in secs) */
-	/* length = 1 */
-	/* [35] */
-	0x1E,
-
-	0x4C, 0x10,
-	/* ID = 0x0C (Cell allocation bitmap) ####### */
-	/* length = 16 */
-	/* [38] */
-	0x8F, 0xB1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-	0x59, 0x01,
-	/* ID = 0x19 (Averaging period) */
-	/* length = 1 */
-	/* [56] */
-	0x01,
-
-	0x5E, 0x01,
-	/* ID = 0x1E ((RF max power reduction)) */
-	/* length = 1 */
-	/* [59] */
-	0x00,
-
-	0x7F, 0x46, 0x11,
-	/* ID = 0x46 (FU channel configuration) ## constructed ## */
-	/* length = 17 */
-	/* [63] */
-
-	0x5F, 0x40, 0x04,
-	/* ID = 0x40 (Object identity) */
-	/* length = 4 */
-	/* [66] */
-	0x00, 0x07, 0x01, 0xFF,
-
-	0x45, 0x08,
-	/* ID = 0x05 (Channel configuration per TS) */
-	/* length = 8 */
-	/* [72] */
-	0x01, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
-
-	0x7F, 0x65, 0x0B,
-	/* ID = 0x65 (Obj. identity and obj. state) ## constructed ## */
-	/* length = 11 */
-	/* [83] */
-
-	0x5F, 0x40, 0x04,
-	/* ID = 0x40 (Object identity) */
-	/* length = 4 */
-	/* [86] */
-	0x00, 0x04, 0x01, 0xFF,
-
-	0x5F, 0x44, 0x01,
-	/* ID = 0x44 (Object current state) */
-	/* length = 1 */
-	/* [93] */
-	0x03,
-
-	0x7F, 0x7C, 0x0A,
-	/* ID = 0x7C (FU BSIC) ## constructed ## */
-	/* length = 10 */
-	/* [97] */
-
-	0x5F, 0x40, 0x04,
-	/* ID = 0x40 (Object identity) */
-	/* length = 4 */
-	/* [100] */
-	0x00, 0x07, 0x01, 0xFF,
-
-	0x46, 0x01,
-	/* ID = 0x06 (BSIC) */
-	/* length = 1 */
-	/* [106] */
-	0x00,
-
-	0x7F, 0x48, 0x0B,
-	/* ID = 0x48 (ARFN of a CU) ## constructed ## */
-	/* length = 11 */
-	/* [110] */
-
-	0x5F, 0x40, 0x04,
-	/* ID = 0x40 (Object identity) */
-	/* length = 4 */
-	/* [113] */
-	0x00, 0x08, 0x01, 0xFF,
-
-	0x4A, 0x02,
-	/* ID = 0x0A (ARFN) ####### */
-	/* length = 2 */
-	/* [119] */
-	0x03, 0x62,
-
-	0x7F, 0x49, 0x59,
-	/* ID = 0x49 (FU radio definition) ## constructed ## */
-	/* length = 89 */
-	/* [124] */
-
-	0x5F, 0x40, 0x04,
-	/* ID = 0x40 (Object identity) */
-	/* length = 4 */
-	/* [127] */
-	0x00, 0x07, 0x01, 0xFF,
-
-	0x4D, 0x50,
-	/* ID = 0x0D (Radio definition per TS) ####### */
-	/* length = 80 */
-	/* [133] */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* MA */
-	0x03, 0x62,		/* HSN, MAIO or ARFCN if no hopping */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x03, 0x62,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x03, 0x62,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x03, 0x62,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x03, 0x62,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x03, 0x62,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x03, 0x62,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x03, 0x62,
-};
-
-/* TODO: put in a separate file ? */
-
-/*
-  build the configuration for each TRX
-*/
-
-static int make_fu_config(struct gsm_bts_trx *trx, uint8_t id,
-			  uint8_t * fu_config, int *hopping)
-{
-	int i;
-
-	*hopping = 0;
-
-	memcpy(fu_config, fu_config_template, sizeof(fu_config_template));
-
-	/* set ID */
-
-	fu_config[6 + 2] = id;
-	fu_config[66 + 2] = id;
-	fu_config[86 + 2] = id;
-	fu_config[100 + 2] = id;
-	fu_config[113 + 2] = id;
-	fu_config[127 + 2] = id;
-
-	/* set ARFCN */
-
-	uint16_t arfcn = trx->arfcn;
-
-	fu_config[119] = arfcn >> 8;
-	fu_config[119 + 1] = arfcn & 0xFF;
-
-	for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
-		struct gsm_bts_trx_ts *ts = &trx->ts[i];
-
-		if (ts->hopping.enabled) {
-			/* reverse order */
-			int j;
-			for (j = 0; j < ts->hopping.ma_len; j++)
-				fu_config[133 + (i * 10) + (7 - j)] =
-				    ts->hopping.ma_data[j];
-			fu_config[133 + 8 + (i * 10)] = ts->hopping.hsn;
-			fu_config[133 + 8 + 1 + (i * 10)] = ts->hopping.maio;
-			*hopping = 1;
-		} else {
-			fu_config[133 + 8 + (i * 10)] = arfcn >> 8;
-			fu_config[133 + 8 + 1 + (i * 10)] = arfcn & 0xFF;
-		}
-	}
-
-	/* set BSIC */
-
-	/*
-	   Attention: all TRX except the first one seem to get the TSC
-	   from the CHANNEL ACTIVATION command (in CHANNEL IDENTIFICATION,
-	   GSM 04.08 CHANNEL DESCRIPTION).
-	   There was a bug in rsl_chan_activate_lchan() setting this parameter.
-	 */
-
-	uint8_t bsic = trx->bts->bsic;
-
-	fu_config[106] = bsic;
-
-	/* set CA */
-
-	if (generate_cell_chan_list(&fu_config[38], trx->bts) != 0) {
-		fprintf(stderr, "generate_cell_chan_list failed\n");
-		return 0;
-	}
-
-	/* set channel configuration */
-
-	for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
-		struct gsm_bts_trx_ts *ts = &trx->ts[i];
-		uint8_t chan_config;
-
-		/*
-		   0 = FCCH + SCH + BCCH + CCCH
-		   1 = FCCH + SCH + BCCH + CCCH + SDCCH/4 + SACCH/4
-		   2 = BCCH + CCCH (This combination is not used in any BTS)
-		   3 = FCCH + SCH + BCCH + CCCH + SDCCH/4 with SDCCH2 used as CBCH
-		   4 = SDCCH/8 + SACCH/8
-		   5 = SDCCH/8 with SDCCH2 used as CBCH
-		   6 = TCH/F + FACCH/F + SACCH/F
-		   7 = E-RACH (Talk family)
-		   9 = Dual rate (capability for TCH/F and TCH/H)
-		   10 = reserved for BTS internal use
-		   11 = PBCCH + PCCCH + PDTCH + PACCH + PTCCH (can be used in GPRS release 2).
-		   0xFF = spare TS
-		 */
-
-		if (ts->pchan == GSM_PCHAN_NONE)
-			chan_config = 0xFF;
-		else if (ts->pchan == GSM_PCHAN_CCCH)
-			chan_config = 0;
-		else if (ts->pchan == GSM_PCHAN_CCCH_SDCCH4)
-			chan_config = 1;
-		else if (ts->pchan == GSM_PCHAN_TCH_F)
-			chan_config = 6;	/* 9 should work too */
-		else if (ts->pchan == GSM_PCHAN_TCH_H)
-			chan_config = 9;
-		else if (ts->pchan == GSM_PCHAN_SDCCH8_SACCH8C)
-			chan_config = 4;
-		else if (ts->pchan == GSM_PCHAN_PDCH)
-			chan_config = 11;
-		else {
-			fprintf(stderr,
-				"unsupported channel config %d for timeslot %d\n",
-				ts->pchan, i);
-			return 0;
-		}
-
-		fu_config[72 + i] = chan_config;
-	}
-	return sizeof(fu_config_template);
-}
-
-/* TODO: put in a separate file ? */
-
-static uint8_t bts_config_1[] = {
-	0x4E, 0x02,
-	/* ID = 0x0E (Frame number) */
-	/* length = 2 */
-	/* [2] */
-	0xFF, 0xFF,
-
-	0x5F, 0x4E, 0x02,
-	/* ID = 0x4E (RX antenna supervision period) */
-	/* length = 2 */
-	/* [7] */
-	0xFF, 0xFF,
-
-	0x5F, 0x50, 0x02,
-	/* ID = 0x50 (Sector configuration) */
-	/* length = 2 */
-	/* [12] */
-	0x01, 0x01,
-};
-
-static uint8_t bts_config_2[] = {
-	0x55, 0x02,
-	/* ID = 0x15 (Hopping mode) */
-	/* length = 2 */
-	/* [2] */
-	0x01, 0x00,
-
-	0x5F, 0x75, 0x02,
-	/* ID = 0x75 (RX diversity selection) */
-	/* length = 2 */
-	/* [7] */
-	0x01, 0x01,
-};
-
-static uint8_t bts_config_3[] = {
-	0x5F, 0x20, 0x02,
-	/* ID = 0x20 (Extended cell radius) */
-	/* length = 2 */
-	/* [3] */
-	0x01, 0x00,
-};
-
-static uint8_t bts_config_4[] = {
-	0x5F, 0x74, 0x09,
-	/* ID = 0x74 (Real Time) */
-	/* length = 9 */
-	/* [3] year-high, year-low, month, day, hour, minute, second, msec-high, msec-low */
-	0x07, 0xDB, 0x06, 0x02, 0x0B, 0x20, 0x0C, 0x00,
-	0x00,
-
-	0x5F, 0x76, 0x03,
-	/* ID = 0x76 (EAC input config) */
-	/* length = 3 */
-	/* [15] */
-	0x01, 0x01, 0x00,
-
-	0x5F, 0x76, 0x03,
-	/* ID = 0x76 (EAC input config) */
-	/* length = 3 */
-	/* [21] */
-	0x02, 0x01, 0x00,
-
-	0x5F, 0x76, 0x03,
-	/* ID = 0x76 (EAC input config) */
-	/* length = 3 */
-	/* [27] */
-	0x03, 0x01, 0x00,
-
-	0x5F, 0x76, 0x03,
-	/* ID = 0x76 (EAC input config) */
-	/* length = 3 */
-	/* [33] */
-	0x04, 0x01, 0x00,
-
-	0x5F, 0x76, 0x03,
-	/* ID = 0x76 (EAC input config) */
-	/* length = 3 */
-	/* [39] */
-	0x05, 0x01, 0x00,
-
-	0x5F, 0x76, 0x03,
-	/* ID = 0x76 (EAC input config) */
-	/* length = 3 */
-	/* [45] */
-	0x06, 0x01, 0x00,
-
-	0x5F, 0x76, 0x03,
-	/* ID = 0x76 (EAC input config) */
-	/* length = 3 */
-	/* [51] */
-	0x07, 0x01, 0x00,
-
-	0x5F, 0x76, 0x03,
-	/* ID = 0x76 (EAC input config) */
-	/* length = 3 */
-	/* [57] */
-	0x08, 0x01, 0x00,
-
-	0x5F, 0x76, 0x03,
-	/* ID = 0x76 (EAC input config) */
-	/* length = 3 */
-	/* [63] */
-	0x09, 0x01, 0x00,
-
-	0x5F, 0x76, 0x03,
-	/* ID = 0x76 (EAC input config) */
-	/* length = 3 */
-	/* [69] */
-	0x0A, 0x01, 0x00,
-};
-
-static uint8_t bts_config_insite[] = {
-	0x4E, 0x02,
-	/* ID = 0x0E (Frame number) */
-	/* length = 2 */
-	/* [2] */
-	0xFF, 0xFF,
-
-	0x5F, 0x4E, 0x02,
-	/* ID = 0x4E (RX antenna supervision period) */
-	/* length = 2 */
-	/* [7] */
-	0xFF, 0xFF,
-
-	0x5F, 0x50, 0x02,
-	/* ID = 0x50 (Sector configuration) */
-	/* length = 2 */
-	/* [12] */
-	0x01, 0x01,
-
-	0x55, 0x02,
-	/* ID = 0x15 (Hopping mode) */
-	/* length = 2 */
-	/* [16] */
-	0x01, 0x00,
-
-	0x5F, 0x20, 0x02,
-	/* ID = 0x20 (Extended cell radius) */
-	/* length = 2 */
-	/* [21] */
-	0x01, 0x00,
-
-	0x5F, 0x74, 0x09,
-	/* ID = 0x74 (Real Time) */
-	/* length = 9 */
-	/* [26] */
-	0x07, 0xDB, 0x07, 0x0A, 0x0F, 0x09, 0x0B, 0x00,
-	0x00,
-};
-
-void set_real_time(uint8_t * real_time)
-{
-	time_t t;
-	struct tm *tm;
-
-	t = time(NULL);
-	tm = localtime(&t);
-
-	/* year-high, year-low, month, day, hour, minute, second, msec-high, msec-low */
-
-	real_time[0] = (1900 + tm->tm_year) >> 8;
-	real_time[1] = (1900 + tm->tm_year) & 0xFF;
-	real_time[2] = tm->tm_mon + 1;
-	real_time[3] = tm->tm_mday;
-	real_time[4] = tm->tm_hour;
-	real_time[5] = tm->tm_min;
-	real_time[6] = tm->tm_sec;
-	real_time[7] = 0;
-	real_time[8] = 0;
-}
-
-/* TODO: put in a separate file ? */
-
-/*
-  build the configuration data
-*/
-
-static int make_bts_config(uint8_t bts_type, int n_trx, uint8_t * fu_config,
-			   int need_hopping)
-{
-	/* is it an InSite BTS ? */
-	if (bts_type == 0x0E || bts_type == 0x0F || bts_type == 0x10) {	/* TODO */
-		if (n_trx != 1) {
-			fprintf(stderr, "InSite has only one TRX\n");
-			return 0;
-		}
-		if (need_hopping != 0) {
-			fprintf(stderr, "InSite does not support hopping\n");
-			return 0;
-		}
-		memcpy(fu_config, bts_config_insite, sizeof(bts_config_insite));
-		set_real_time(&fu_config[26]);
-		return sizeof(bts_config_insite);
-	}
-
-	int len = 0;
-	int i;
-
-	memcpy(fu_config + len, bts_config_1, sizeof(bts_config_1));
-
-	/* set sector configuration */
-	fu_config[len + 12 - 1] = 1 + n_trx;	/* len */
-	for (i = 0; i < n_trx; i++)
-		fu_config[len + 12 + 1 + i] = ((i + 1) & 0xFF);
-
-	len += (sizeof(bts_config_1) + (n_trx - 1));
-
-	memcpy(fu_config + len, bts_config_2, sizeof(bts_config_2));
-	/* set hopping mode (Baseband and RF hopping work for the MetroSite) */
-	if (need_hopping)
-		fu_config[len + 2 + 1] = 1;	/* 0: no hopping, 1: Baseband hopping, 2: RF hopping */
-	len += sizeof(bts_config_2);
-
-	/* set extended cell radius for each TRX */
-	for (i = 0; i < n_trx; i++) {
-		memcpy(fu_config + len, bts_config_3, sizeof(bts_config_3));
-		fu_config[len + 3] = ((i + 1) & 0xFF);
-		len += sizeof(bts_config_3);
-	}
-
-	memcpy(fu_config + len, bts_config_4, sizeof(bts_config_4));
-	set_real_time(&fu_config[len + 3]);
-	len += sizeof(bts_config_4);
-
-	return len;
-}
-
-/* TODO: put in a separate file ? */
-
-static struct msgb *nm_msgb_alloc(void)
-{
-	return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML");
-}
-
-/* TODO: put in a separate file ? */
-
-struct abis_om_nokia_hdr {
-	uint8_t msg_type;
-	uint8_t spare;
-	uint16_t reference;
-	uint8_t data[0];
-} __attribute__ ((packed));
-
-#define ABIS_OM_NOKIA_HDR_SIZE (sizeof(struct abis_om_hdr) + sizeof(struct abis_om_nokia_hdr))
-
-static int abis_nm_send(struct gsm_bts *bts, uint8_t msg_type, uint16_t ref,
-			uint8_t * data, int len_data)
-{
-	struct abis_om_hdr *oh;
-	struct abis_om_nokia_hdr *noh;
-	struct msgb *msg = nm_msgb_alloc();
-
-	oh = (struct abis_om_hdr *)msgb_put(msg,
-					    ABIS_OM_NOKIA_HDR_SIZE + len_data);
-
-	oh->mdisc = ABIS_OM_MDISC_FOM;
-	oh->placement = ABIS_OM_PLACEMENT_ONLY;
-	oh->sequence = 0;
-	oh->length = sizeof(struct abis_om_nokia_hdr) + len_data;
-
-	noh = (struct abis_om_nokia_hdr *)oh->data;
-
-	noh->msg_type = msg_type;
-	noh->spare = 0;
-	noh->reference = htons(ref);
-	memcpy(noh->data, data, len_data);
-
-	DEBUGPC(DNM, "Sending %s\n", get_msg_type_name_string(msg_type));
-
-	return abis_nm_sendmsg(bts, msg);
-}
-
-/* TODO: put in a separate file ? */
-
-static uint8_t download_req[] = {
-	0x5F, 0x25, 0x0B,
-	/* ID = 0x25 (File identity) */
-	/* length = 11 */
-	/* [3] */
-	0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
-	0x2A, 0x2A, 0x2A,
-
-	0x5F, 0x78, 0x03,
-	/* ID = 0x78 (File version) */
-	/* length = 3 */
-	/* [17] */
-	0x2A, 0x2A, 0x2A,
-
-	0x5F, 0x81, 0x0A, 0x01,
-	/* ID = 0x8A (SW load mode) */
-	/* length = 1 */
-	/* [24] */
-	0x01,
-
-	0x5F, 0x81, 0x06, 0x01,
-	/* ID = 0x86 (Acknowledgement period) */
-	/* length = 1 */
-	/* [29] */
-	0x01,
-};
-
-static int abis_nm_download_req(struct gsm_bts *bts, uint16_t ref)
-{
-	uint8_t *data = download_req;
-	int len_data = sizeof(download_req);
-
-	return abis_nm_send(bts, NOKIA_MSG_START_DOWNLOAD_REQ, ref, data,
-			    len_data);
-}
-
-/* TODO: put in a separate file ? */
-
-static uint8_t ack[] = {
-	0x5F, 0x23, 0x01,
-	/* ID = 0x23 (Ack-Nack) */
-	/* length = 1 */
-	/* [3] */
-	0x01,
-};
-
-static int abis_nm_ack(struct gsm_bts *bts, uint16_t ref)
-{
-	uint8_t *data = ack;
-	int len_data = sizeof(ack);
-
-	return abis_nm_send(bts, NOKIA_MSG_ACK, ref, data, len_data);
-}
-
-/* TODO: put in a separate file ? */
-
-static uint8_t reset[] = {
-	0x5F, 0x40, 0x04,
-	/* ID = 0x40 (Object identity) */
-	/* length = 4 */
-	/* [3] */
-	0x00, 0x01, 0xFF, 0xFF,
-};
-
-static int abis_nm_reset(struct gsm_bts *bts, uint16_t ref)
-{
-	uint8_t *data = reset;
-	int len_data = sizeof(reset);
-	LOGP(DLINP, LOGL_INFO, "Nokia BTS reset timer: %d\n", bts->nokia.bts_reset_timer_cnf);
-	return abis_nm_send(bts, NOKIA_MSG_RESET_REQ, ref, data, len_data);
-}
-
-/* TODO: put in a separate file ? */
-
-static int abis_nm_send_multi_segments(struct gsm_bts *bts, uint8_t msg_type,
-				       uint16_t ref, uint8_t * data, int len)
-{
-	int len_remain, len_to_send, max_send;
-	int seq = 0;
-	int ret;
-
-	len_remain = len;
-
-	while (len_remain) {
-		struct abis_om_hdr *oh;
-		struct abis_om_nokia_hdr *noh;
-		struct msgb *msg = nm_msgb_alloc();
-
-		if (seq == 0)
-			max_send = 256 - sizeof(struct abis_om_nokia_hdr);
-		else
-			max_send = 256;
-
-		if (len_remain > max_send) {
-			len_to_send = max_send;
-
-			if (seq == 0) {
-				/* first segment */
-				oh = (struct abis_om_hdr *)msgb_put(msg,
-								    ABIS_OM_NOKIA_HDR_SIZE
-								    +
-								    len_to_send);
-
-				oh->mdisc = ABIS_OM_MDISC_FOM;
-				oh->placement = ABIS_OM_PLACEMENT_FIRST;	/* first segment of multi-segment message */
-				oh->sequence = seq;
-				oh->length = 0;	/* 256 bytes */
-
-				noh = (struct abis_om_nokia_hdr *)oh->data;
-
-				noh->msg_type = msg_type;
-				noh->spare = 0;
-				noh->reference = htons(ref);
-				memcpy(noh->data, data, len_to_send);
-			} else {
-				/* segment in between */
-				oh = (struct abis_om_hdr *)msgb_put(msg,
-								    sizeof
-								    (struct
-								     abis_om_hdr)
-								    +
-								    len_to_send);
-
-				oh->mdisc = ABIS_OM_MDISC_FOM;
-				oh->placement = ABIS_OM_PLACEMENT_MIDDLE;	/* segment of multi-segment message */
-				oh->sequence = seq;
-				oh->length = 0;	/* 256 bytes */
-
-				memcpy(oh->data, data, len_to_send);
-			}
-		} else {
-
-			len_to_send = len_remain;
-
-			/* check if message fits in a single segment */
-
-			if (seq == 0)
-				return abis_nm_send(bts, msg_type, ref, data,
-						    len_to_send);
-
-			/* last segment */
-
-			oh = (struct abis_om_hdr *)msgb_put(msg,
-							    sizeof(struct
-								   abis_om_hdr)
-							    + len_to_send);
-
-			oh->mdisc = ABIS_OM_MDISC_FOM;
-			oh->placement = ABIS_OM_PLACEMENT_LAST;	/* last segment of multi-segment message */
-			oh->sequence = seq;
-			oh->length = len_to_send;
-
-			memcpy(oh->data, data, len_to_send);
-		}
-
-		DEBUGPC(DNM, "Sending multi-segment %d\n", seq);
-
-		ret = abis_nm_sendmsg(bts, msg);
-		if (ret < 0)
-			return ret;
-
-		nokia_abis_nm_queue_send_next(bts);
-
-		/* next segment */
-		len_remain -= len_to_send;
-		data += len_to_send;
-		seq++;
-	}
-	return ret;
-}
-
-/* TODO: put in a separate file ? */
-
-static int abis_nm_send_config(struct gsm_bts *bts, uint8_t bts_type)
-{
-	struct gsm_bts_trx *trx;
-	uint8_t config[2048];	/* TODO: might be too small if lots of TRX are used */
-	int len = 0;
-	int idx = 0;
-	int ret;
-	int hopping = 0;
-	int need_hopping = 0;
-
-	memset(config, 0, sizeof(config));
-
-	llist_for_each_entry(trx, &bts->trx_list, list) {
-#if 0				/* debugging */
-		printf("TRX\n");
-		printf("  arfcn: %d\n", trx->arfcn);
-		printf("  bsic: %d\n", trx->bts->bsic);
-		uint8_t ca[20];
-		memset(ca, 0xFF, sizeof(ca));
-		ret = generate_cell_chan_list(ca, trx->bts);
-		printf("  ca (%d): %s\n", ret, osmo_hexdump(ca, sizeof(ca)));
-		int i;
-		for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
-			struct gsm_bts_trx_ts *ts = &trx->ts[i];
-
-			printf("  pchan %d: %d\n", i, ts->pchan);
-		}
-#endif
-		ret = make_fu_config(trx, idx + 1, config + len, &hopping);
-		need_hopping |= hopping;
-		len += ret;
-
-		idx++;
-	}
-
-	ret = make_bts_config(bts_type, idx, config + len, need_hopping);
-	len += ret;
-
-#if 0				/* debugging */
-	dump_elements(config, len);
-#endif
-
-	return abis_nm_send_multi_segments(bts, NOKIA_MSG_CONF_DATA, 1, config,
-					   len);
-}
-
-#define GET_NEXT_BYTE if(idx >= len) return 0; \
-                        ub = data[idx++];
-
-static int find_element(uint8_t * data, int len, uint16_t id, uint8_t * value,
-			int max_value)
-{
-	uint8_t ub;
-	int idx = 0;
-	int found = 0;
-	int constructed __attribute__((unused));
-	uint16_t id_value;
-
-	for (;;) {
-
-		GET_NEXT_BYTE;
-
-		/* encoding bit, construced means that other elements are contained */
-		constructed = ((ub & 0x20) ? 1 : 0);
-
-		if ((ub & 0x1F) == 0x1F) {
-			/* fixed pattern, ID follows */
-			GET_NEXT_BYTE;	/* ID */
-			id_value = ub & 0x7F;
-			if (ub & 0x80) {
-				/* extension bit */
-				GET_NEXT_BYTE;	/* ID low part */
-				id_value = (id_value << 7) | (ub & 0x7F);
-			}
-			if (id_value == id)
-				found = 1;
-		} else {
-			id_value = (ub & 0x3F);
-			if (id_value == id)
-				found = 1;
-		}
-
-		GET_NEXT_BYTE;	/* length */
-
-		if (found) {
-			/* get data */
-			uint8_t n = ub;
-			uint8_t i;
-			for (i = 0; i < n; i++) {
-				GET_NEXT_BYTE;
-				if (max_value <= 0)
-					return -1;	/* buffer too small */
-				*value = ub;
-				value++;
-				max_value--;
-			}
-			return n;	/* length */
-		} else {
-			/* skip data */
-			uint8_t n = ub;
-			uint8_t i;
-			for (i = 0; i < n; i++) {
-				GET_NEXT_BYTE;
-			}
-		}
-	}
-	return 0;		/* not found */
-}
-
-static int dump_elements(uint8_t * data, int len)
-{
-	uint8_t ub;
-	int idx = 0;
-	int constructed;
-	uint16_t id_value;
-	static char indent[100] = "";	/* TODO: move static to BTS context */
-
-	for (;;) {
-
-		GET_NEXT_BYTE;
-
-		/* encoding bit, construced means that other elements are contained */
-		constructed = ((ub & 0x20) ? 1 : 0);
-
-		if ((ub & 0x1F) == 0x1F) {
-			/* fixed pattern, ID follows */
-			GET_NEXT_BYTE;	/* ID */
-			id_value = ub & 0x7F;
-			if (ub & 0x80) {
-				/* extension bit */
-				GET_NEXT_BYTE;	/* ID low part */
-				id_value = (id_value << 7) | (ub & 0x7F);
-			}
-
-		} else {
-			id_value = (ub & 0x3F);
-		}
-
-		GET_NEXT_BYTE;	/* length */
-
-		printf("%s--ID = 0x%02X (%s) %s\n", indent, id_value,
-		       get_element_name_string(id_value),
-		       constructed ? "** constructed **" : "");
-		printf("%s  length = %d\n", indent, ub);
-		printf("%s  %s\n", indent, osmo_hexdump(data + idx, ub));
-
-		if (constructed) {
-			int indent_len = strlen(indent);
-			strcat(indent, "   ");
-
-			dump_elements(data + idx, ub);
-
-			indent[indent_len] = 0;
-		}
-		/* skip data */
-		uint8_t n = ub;
-		uint8_t i;
-		for (i = 0; i < n; i++) {
-			GET_NEXT_BYTE;
-		}
-	}
-	return 0;
-}
-
-/* TODO: put in a separate file ? */
-
-/* taken from abis_nm.c */
-
-static void nokia_abis_nm_queue_send_next(struct gsm_bts *bts)
-{
-	int wait = 0;
-	struct msgb *msg;
-	/* the queue is empty */
-	while (!llist_empty(&bts->abis_queue)) {
-		msg = msgb_dequeue(&bts->abis_queue);
-		wait = OBSC_NM_W_ACK_CB(msg);
-		abis_sendmsg(msg);
-
-		if (wait)
-			break;
-	}
-
-	bts->abis_nm_pend = wait;
-}
-
-/* TODO: put in a separate file ? */
-
-/* timer for restarting OML after BTS reset */
-
-static void reset_timer_cb(void *_bts)
-{
-	struct gsm_bts *bts = _bts;
-	struct gsm_e1_subslot *e1_link = &bts->oml_e1_link;
-	struct e1inp_line *line;
-
-	bts->nokia.wait_reset = 0;
-
-	/* OML link */
-	line = e1inp_line_find(e1_link->e1_nr);
-	if (!line) {
-		LOGP(DLINP, LOGL_ERROR, "BTS %u OML link referring to "
-		     "non-existing E1 line %u\n", bts->nr, e1_link->e1_nr);
-		return;
-	}
-
-	start_sabm_in_line(line, 0, -1);	/* stop all first */
-	start_sabm_in_line(line, 1, SAPI_OML);	/* start only OML */
-}
-
-/* TODO: put in a separate file ? */
-
-/*
-  This is how the configuration is done:
-  - start OML link
-  - reset BTS
-  - receive ACK, wait some time and restart OML link
-  - receive OMU STARTED message, send START DOWNLOAD REQ
-  - receive CNF REQ message, send CONF DATA
-  - receive ACK, start RSL link(s)
-  ACK some other messages received from the BTS.
-
-  Probably its also possible to configure the BTS without a reset, this 
-  has not been tested yet.
-*/
-
-static int abis_nm_rcvmsg_fom(struct msgb *mb)
-{
-	struct e1inp_sign_link *sign_link = (struct e1inp_sign_link *)mb->dst;
-	struct gsm_bts *bts = sign_link->trx->bts;
-	struct abis_om_hdr *oh = msgb_l2(mb);
-	struct abis_om_nokia_hdr *noh = msgb_l3(mb);
-	uint8_t mt = noh->msg_type;
-	int ret = 0;
-	uint16_t ref = ntohs(noh->reference);
-	uint8_t info[256];
-	uint8_t ack = 0xFF;
-	uint8_t severity = 0xFF;
-	int str_len;
-	int len_data;
-
-	if (bts->nokia.wait_reset) {
-		LOGP(DNM, LOGL_INFO,
-		     "Ignore message while waiting for reset\n");
-		return ret;
-	}
-
-	if (oh->length < sizeof(struct abis_om_nokia_hdr)) {
-		LOGP(DNM, LOGL_ERROR, "Message too short\n");
-		return -EINVAL;
-	}
-
-	len_data = oh->length - sizeof(struct abis_om_nokia_hdr);
-	LOGP(DNM, LOGL_INFO, "(0x%02X) %s\n", mt, get_msg_type_name_string(mt));
-#if 0				/* debugging */
-	dump_elements(noh->data, len_data);
-#endif
-
-	switch (mt) {
-	case NOKIA_MSG_OMU_STARTED:
-		if (find_element(noh->data, len_data,
-				 NOKIA_EI_BTS_TYPE, &bts->nokia.bts_type,
-				 sizeof(uint8_t)) == sizeof(uint8_t))
-			LOGP(DNM, LOGL_INFO, "BTS type = %d (%s)\n",
-			     bts->nokia.bts_type,
-			     get_bts_type_string(bts->nokia.bts_type));
-		else
-			LOGP(DNM, LOGL_ERROR, "BTS type not found\n");
-		/* send START_DOWNLOAD_REQ */
-		abis_nm_download_req(bts, ref);
-		break;
-	case NOKIA_MSG_MF_REQ:
-		break;
-	case NOKIA_MSG_CONF_REQ:
-		/* send ACK */
-		abis_nm_ack(bts, ref);
-		nokia_abis_nm_queue_send_next(bts);
-		/* send CONF_DATA */
-		abis_nm_send_config(bts, bts->nokia.bts_type);
-		bts->nokia.configured = 1;
-		break;
-	case NOKIA_MSG_ACK:
-		if (find_element
-		    (noh->data, len_data, NOKIA_EI_ACK, &ack,
-		     sizeof(uint8_t)) == sizeof(uint8_t)) {
-			LOGP(DNM, LOGL_INFO, "ACK = %d\n", ack);
-			if (ack != 1) {
-				LOGP(DNM, LOGL_ERROR, "No ACK received (%d)\n",
-				     ack);
-				/* TODO: properly handle failures (NACK) */
-			}
-		} else
-			LOGP(DNM, LOGL_ERROR, "ACK not found\n");
-
-		/* TODO: the assumption for the following is that no NACK was received */
-
-		/* ACK for reset message ? */
-		if (!bts->nokia.did_reset) {
-			bts->nokia.did_reset = 1;
-
-			/* 
-			   TODO: For the InSite processing the received data is 
-			   blocked in the driver during reset.
-			   Otherwise the LAPD module might assert because the InSite
-			   sends garbage on the E1 line during reset.
-			   This is done by looking at "wait_reset" in the driver
-			   (function handle_ts1_read()) and ignoring the received data.
-			   It seems to be necessary for the MetroSite too.
-			 */
-			bts->nokia.wait_reset = 1;
-
-			osmo_timer_setup(&bts->nokia.reset_timer,
-					 reset_timer_cb, bts);
-			osmo_timer_schedule(&bts->nokia.reset_timer, bts->nokia.bts_reset_timer_cnf, 0);
-
-			struct gsm_e1_subslot *e1_link = &bts->oml_e1_link;
-			struct e1inp_line *line;
-			/* OML link */
-			line = e1inp_line_find(e1_link->e1_nr);
-			if (!line) {
-				LOGP(DLINP, LOGL_ERROR,
-				     "BTS %u OML link referring to "
-				     "non-existing E1 line %u\n", bts->nr,
-				     e1_link->e1_nr);
-				return -ENOMEM;
-			}
-
-			start_sabm_in_line(line, 0, -1);	/* stop all first */
-		}
-
-		/* ACK for CONF DATA message ? */
-		if (bts->nokia.configured != 0) {
-			/* start TRX  (RSL link) */
-
-			struct gsm_e1_subslot *e1_link =
-					&sign_link->trx->rsl_e1_link;
-			struct e1inp_line *line;
-
-			bts->nokia.configured = 0;
-
-			/* RSL Link */
-			line = e1inp_line_find(e1_link->e1_nr);
-			if (!line) {
-				LOGP(DLINP, LOGL_ERROR,
-				     "TRX (%u/%u) RSL link referring "
-				     "to non-existing E1 line %u\n",
-				     sign_link->trx->bts->nr, sign_link->trx->nr,
-				     e1_link->e1_nr);
-				return -ENOMEM;
-			}
-			/* start TRX */
-			start_sabm_in_line(line, 1, SAPI_RSL);	/* start only RSL */
-		}
-		break;
-	case NOKIA_MSG_STATE_CHANGED:
-		/* send ACK */
-		abis_nm_ack(bts, ref);
-		break;
-	case NOKIA_MSG_CONF_COMPLETE:
-		/* send ACK */
-		abis_nm_ack(bts, ref);
-		break;
-	case NOKIA_MSG_BLOCK_CTRL_REQ:	/* seems to be send when something goes wrong !? */
-		/* send ACK (do we have to send an ACK ?) */
-		abis_nm_ack(bts, ref);
-		break;
-	case NOKIA_MSG_ALARM:
-		find_element(noh->data, len_data, NOKIA_EI_SEVERITY, &severity,
-			     sizeof(severity));
-		/* TODO: there might be alarms with both elements set */
-		str_len =
-		    find_element(noh->data, len_data, NOKIA_EI_ADD_INFO, info,
-				 sizeof(info));
-		if (str_len > 0) {
-			info[str_len] = 0;
-			LOGP(DNM, LOGL_INFO, "ALARM Severity %s (%d) : %s\n",
-			     get_severity_string(severity), severity, info);
-		} else {	/* nothing found, try details */
-			str_len =
-			    find_element(noh->data, len_data,
-					 NOKIA_EI_ALARM_DETAIL, info,
-					 sizeof(info));
-			if (str_len > 0) {
-				uint16_t code;
-				info[str_len] = 0;
-				code = (info[0] << 8) + info[1];
-				LOGP(DNM, LOGL_INFO,
-				     "ALARM Severity %s (%d), code 0x%X : %s\n",
-				     get_severity_string(severity), severity,
-				     code, info + 2);
-			}
-		}
-		/* send ACK */
-		abis_nm_ack(bts, ref);
-		break;
-	}
-
-	nokia_abis_nm_queue_send_next(bts);
-
-	return ret;
-}
-
-/* TODO: put in a separate file ? */
-
-int abis_nokia_rcvmsg(struct msgb *msg)
-{
-	struct abis_om_hdr *oh = msgb_l2(msg);
-	int rc = 0;
-
-	/* Various consistency checks */
-	if (oh->placement != ABIS_OM_PLACEMENT_ONLY) {
-		LOGP(DNM, LOGL_ERROR, "ABIS OML placement 0x%x not supported\n",
-		     oh->placement);
-		if (oh->placement != ABIS_OM_PLACEMENT_FIRST)
-			return -EINVAL;
-	}
-	if (oh->sequence != 0) {
-		LOGP(DNM, LOGL_ERROR, "ABIS OML sequence 0x%x != 0x00\n",
-		     oh->sequence);
-		return -EINVAL;
-	}
-	msg->l3h = (unsigned char *)oh + sizeof(*oh);
-
-	switch (oh->mdisc) {
-	case ABIS_OM_MDISC_FOM:
-		LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_FOM\n");
-		rc = abis_nm_rcvmsg_fom(msg);
-		break;
-	case ABIS_OM_MDISC_MANUF:
-		LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_MANUF\n");
-		break;
-	case ABIS_OM_MDISC_MMI:
-	case ABIS_OM_MDISC_TRAU:
-		LOGP(DNM, LOGL_ERROR,
-		     "unimplemented ABIS OML message discriminator 0x%x\n",
-		     oh->mdisc);
-		break;
-	default:
-		LOGP(DNM, LOGL_ERROR,
-		     "unknown ABIS OML message discriminator 0x%x\n",
-		     oh->mdisc);
-		return -EINVAL;
-	}
-
-	msgb_free(msg);
-	return rc;
-}
-
-static int bts_model_nokia_site_start(struct gsm_network *net);
-
-static void bts_model_nokia_site_e1line_bind_ops(struct e1inp_line *line)
-{
-	e1inp_line_bind_ops(line, &bts_isdn_e1inp_line_ops);
-}
-
-static struct gsm_bts_model model_nokia_site = {
-	.type = GSM_BTS_TYPE_NOKIA_SITE,
-	.name = "nokia_site",
-	.start = bts_model_nokia_site_start,
-	.oml_rcvmsg = &abis_nokia_rcvmsg,
-	.e1line_bind_ops = &bts_model_nokia_site_e1line_bind_ops,
-};
-
-static struct gsm_network *my_net;
-
-static int bts_model_nokia_site_start(struct gsm_network *net)
-{
-	model_nokia_site.features.data = &model_nokia_site._features_data[0];
-	model_nokia_site.features.data_len =
-	    sizeof(model_nokia_site._features_data);
-
-	gsm_btsmodel_set_feature(&model_nokia_site, BTS_FEAT_HOPPING);
-	gsm_btsmodel_set_feature(&model_nokia_site, BTS_FEAT_HSCSD);
-	gsm_btsmodel_set_feature(&model_nokia_site, BTS_FEAT_MULTI_TSC);
-
-	osmo_signal_register_handler(SS_L_INPUT, inp_sig_cb, NULL);
-	osmo_signal_register_handler(SS_L_GLOBAL, gbl_sig_cb, NULL);
-	osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL);
-
-	my_net = net;
-
-	return 0;
-}
-
-int bts_model_nokia_site_init(void)
-{
-	return gsm_bts_model_register(&model_nokia_site);
-}
diff --git a/src/libbsc/bts_siemens_bs11.c b/src/libbsc/bts_siemens_bs11.c
deleted file mode 100644
index c083b1e..0000000
--- a/src/libbsc/bts_siemens_bs11.c
+++ /dev/null
@@ -1,602 +0,0 @@
-/* Siemens BS-11 specific code */
-
-/* (C) 2009-2010 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/>.
- *
- */
-
-
-#include <osmocom/gsm/tlv.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/abis_nm.h>
-#include <osmocom/abis/e1_input.h>
-#include <openbsc/signal.h>
-
-static int bts_model_bs11_start(struct gsm_network *net);
-
-static void bts_model_bs11_e1line_bind_ops(struct e1inp_line *line)
-{
-	e1inp_line_bind_ops(line, &bts_isdn_e1inp_line_ops);
-}
-
-static struct gsm_bts_model model_bs11 = {
-	.type = GSM_BTS_TYPE_BS11,
-	.name = "bs11",
-	.start = bts_model_bs11_start,
-	.oml_rcvmsg = &abis_nm_rcvmsg,
-	.e1line_bind_ops = bts_model_bs11_e1line_bind_ops,
-	.nm_att_tlvdef = {
-		.def = {
-			[NM_ATT_AVAIL_STATUS] =		{ TLV_TYPE_TLV },
-			/* BS11 specifics */
-			[NM_ATT_BS11_ESN_FW_CODE_NO] =	{ TLV_TYPE_TLV },
-			[NM_ATT_BS11_ESN_HW_CODE_NO] =	{ TLV_TYPE_TLV },
-			[NM_ATT_BS11_ESN_PCB_SERIAL] =	{ TLV_TYPE_TLV },
-			[NM_ATT_BS11_BOOT_SW_VERS] =	{ TLV_TYPE_TLV },
-			[0xd5] =			{ TLV_TYPE_TLV },
-			[0xa8] =			{ TLV_TYPE_TLV },
-			[NM_ATT_BS11_PASSWORD] =	{ TLV_TYPE_TLV },
-			[NM_ATT_BS11_TXPWR] =		{ TLV_TYPE_TLV },
-			[NM_ATT_BS11_RSSI_OFFS] =	{ TLV_TYPE_TLV },
-			[NM_ATT_BS11_LINE_CFG] = 	{ TLV_TYPE_TV },
-			[NM_ATT_BS11_L1_PROT_TYPE] =	{ TLV_TYPE_TV },
-			[NM_ATT_BS11_BIT_ERR_THESH] =	{ TLV_TYPE_FIXED, 2 },
-			[NM_ATT_BS11_DIVERSITY] =	{ TLV_TYPE_TLV },
-			[NM_ATT_BS11_LMT_LOGON_SESSION]={ TLV_TYPE_TLV },	
-			[NM_ATT_BS11_LMT_LOGIN_TIME] =	{ TLV_TYPE_TLV },
-			[NM_ATT_BS11_LMT_USER_ACC_LEV] ={ TLV_TYPE_TLV },
-			[NM_ATT_BS11_LMT_USER_NAME] =	{ TLV_TYPE_TLV },
-			[NM_ATT_BS11_BTS_STATE]	=	{ TLV_TYPE_TLV },
-			[NM_ATT_BS11_E1_STATE]	=	{ TLV_TYPE_TLV },
-			[NM_ATT_BS11_PLL_MODE]	=	{ TLV_TYPE_TLV },
-			[NM_ATT_BS11_PLL]	=	{ TLV_TYPE_TLV },
-			[NM_ATT_BS11_CCLK_ACCURACY] =	{ TLV_TYPE_TV },
-			[NM_ATT_BS11_CCLK_TYPE] =	{ TLV_TYPE_TV },
-			[0x95] =			{ TLV_TYPE_FIXED, 2 },
-		},
-	},
-};
-
-/* The following definitions are for OM and NM packets that we cannot yet
- * generate by code but we just pass on */
-
-// BTS Site Manager, SET ATTRIBUTES
-
-/*
-  Object Class: BTS Site Manager
-  Instance 1: FF
-  Instance 2: FF
-  Instance 3: FF
-SET ATTRIBUTES
-  sAbisExternalTime: 2007/09/08   14:36:11
-  omLAPDRelTimer: 30sec
-  shortLAPDIntTimer: 5sec
-  emergencyTimer1: 10 minutes
-  emergencyTimer2: 0 minutes
-*/
-
-unsigned char msg_1[] =
-{
-	NM_MT_BS11_SET_ATTR, NM_OC_SITE_MANAGER, 0xFF, 0xFF, 0xFF,
-		NM_ATT_BS11_ABIS_EXT_TIME, 0x07,
-			0xD7, 0x09, 0x08, 0x0E, 0x24, 0x0B, 0xCE,
-		0x02,
-			0x00, 0x1E,
-		NM_ATT_BS11_SH_LAPD_INT_TIMER,
-			0x01, 0x05,
-		0x42, 0x02, 0x00, 0x0A,
-		0x44, 0x02, 0x00, 0x00
-};
-
-// BTS, SET BTS ATTRIBUTES
-
-/*
-  Object Class: BTS
-  BTS relat. Number: 0
-  Instance 2: FF
-  Instance 3: FF
-SET BTS ATTRIBUTES
-  bsIdentityCode / BSIC:
-    PLMN_colour_code: 7h
-    BS_colour_code:   7h
-  BTS Air Timer T3105: 4  ,unit 10 ms
-  btsIsHopping: FALSE
-  periodCCCHLoadIndication: 1sec
-  thresholdCCCHLoadIndication: 0%
-  cellAllocationNumber: 00h = GSM 900
-  enableInterferenceClass: 00h =  Disabled
-  fACCHQual: 6 (FACCH stealing flags minus 1)
-  intaveParameter: 31 SACCH multiframes
-  interferenceLevelBoundaries:
-    Interference Boundary 1: 0Ah
-    Interference Boundary 2: 0Fh
-    Interference Boundary 3: 14h
-    Interference Boundary 4: 19h
-    Interference Boundary 5: 1Eh
-  mSTxPwrMax: 11
-      GSM range:     2=39dBm, 15=13dBm, stepsize 2 dBm
-      DCS1800 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
-      PCS1900 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
-                    30=33dBm, 31=32dBm
-  ny1:
-    Maximum number of repetitions for PHYSICAL INFORMATION message (GSM 04.08): 20
-  powerOutputThresholds:
-    Out Power Fault Threshold:     -10 dB
-    Red Out Power Threshold:       - 6 dB
-    Excessive Out Power Threshold:   5 dB
-  rACHBusyThreshold: -127 dBm
-  rACHLoadAveragingSlots: 250 ,number of RACH burst periods
-  rfResourceIndicationPeriod: 125  SACCH multiframes
-  T200:
-    SDCCH:                044 in  5 ms
-    FACCH/Full rate:      031 in  5 ms
-    FACCH/Half rate:      041 in  5 ms
-    SACCH with TCH SAPI0: 090 in 10 ms
-    SACCH with SDCCH:     090 in 10 ms
-    SDCCH with SAPI3:     090 in  5 ms
-    SACCH with TCH SAPI3: 135 in 10 ms
-  tSync: 9000 units of 10 msec
-  tTrau: 9000 units of 10 msec
-  enableUmLoopTest: 00h =  disabled
-  enableExcessiveDistance: 00h =  Disabled
-  excessiveDistance: 64km
-  hoppingMode: 00h = baseband hopping
-  cellType: 00h =  Standard Cell
-  BCCH ARFCN / bCCHFrequency: 1
-*/
-
-static unsigned char bs11_attr_bts[] =
-{
-		NM_ATT_BSIC, HARDCODED_BSIC,
-		NM_ATT_BTS_AIR_TIMER, 0x04,
-		NM_ATT_BS11_BTSLS_HOPPING, 0x00,
-		NM_ATT_CCCH_L_I_P, 0x01,
-		NM_ATT_CCCH_L_T, 0x00,
-		NM_ATT_BS11_CELL_ALLOC_NR, NM_BS11_CANR_GSM,
-		NM_ATT_BS11_ENA_INTERF_CLASS, 0x01,
-		NM_ATT_BS11_FACCH_QUAL, 0x06,
-		/* interference avg. period in numbers of SACCH multifr */
-		NM_ATT_INTAVE_PARAM, 0x1F,
-		NM_ATT_INTERF_BOUND, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x7B,
-		NM_ATT_CCCH_L_T, 0x23,
-		NM_ATT_GSM_TIME, 0x28, 0x00,
-		NM_ATT_ADM_STATE, 0x03,
-		NM_ATT_RACH_B_THRESH, 0x7F,
-		NM_ATT_LDAVG_SLOTS, 0x00, 0xFA,
-		NM_ATT_BS11_RF_RES_IND_PER, 0x7D,
-		NM_ATT_T200, 0x2C, 0x1F, 0x29, 0x5A, 0x5A, 0x5A, 0x87,
-		NM_ATT_BS11_TSYNC, 0x23, 0x28,
-		NM_ATT_BS11_TTRAU, 0x23, 0x28,
-		NM_ATT_TEST_DUR, 0x01, 0x00,
-		NM_ATT_OUTST_ALARM, 0x01, 0x00,
-		NM_ATT_BS11_EXCESSIVE_DISTANCE, 0x01, 0x40,
-		NM_ATT_BS11_HOPPING_MODE, 0x01, 0x00,
-		NM_ATT_BS11_PLL, 0x01, 0x00,
-		NM_ATT_BCCH_ARFCN, 0x00, HARDCODED_ARFCN/*0x01*/,
-};
-
-// Handover Recognition, SET ATTRIBUTES
-
-/*
-Illegal Contents GSM Formatted O&M Msg
-  Object Class: Handover Recognition
-  BTS relat. Number: 0
-  Instance 2: FF
-  Instance 3: FF
-SET ATTRIBUTES
-  enableDelayPowerBudgetHO: 00h = Disabled
-  enableDistanceHO: 00h =  Disabled
-  enableInternalInterCellHandover: 00h = Disabled
-  enableInternalIntraCellHandover: 00h =  Disabled
-  enablePowerBudgetHO: 00h = Disabled
-  enableRXLEVHO: 00h =  Disabled
-  enableRXQUALHO: 00h =  Disabled
-  hoAveragingDistance: 8  SACCH multiframes
-  hoAveragingLev:
-    A_LEV_HO: 8  SACCH multiframes
-    W_LEV_HO: 1  SACCH multiframes
-  hoAveragingPowerBudget:  16  SACCH multiframes
-  hoAveragingQual:
-    A_QUAL_HO: 8  SACCH multiframes
-    W_QUAL_HO: 2  SACCH multiframes
-  hoLowerThresholdLevDL: (10 - 110) dBm
-  hoLowerThresholdLevUL: (5 - 110) dBm
-  hoLowerThresholdQualDL: 06h =   6.4% < BER < 12.8%
-  hoLowerThresholdQualUL: 06h =   6.4% < BER < 12.8%
-  hoThresholdLevDLintra : (20 - 110) dBm
-  hoThresholdLevULintra: (20 - 110) dBm
-  hoThresholdMsRangeMax: 20 km
-  nCell: 06h
-  timerHORequest: 3  ,unit 2 SACCH multiframes
-*/
-
-unsigned char msg_3[] =
-{
-	NM_MT_BS11_SET_ATTR, NM_OC_BS11_HANDOVER, 0x00, 0xFF, 0xFF,
-		0xD0, 0x00,		/* enableDelayPowerBudgetHO */
-		0x64, 0x00,		/* enableDistanceHO */
-		0x67, 0x00,		/* enableInternalInterCellHandover */
-		0x68, 0x00,		/* enableInternalInterCellHandover */
-		0x6A, 0x00,		/* enablePowerBudgetHO */
-		0x6C, 0x00,		/* enableRXLEVHO */
-		0x6D, 0x00,		/* enableRXQUALHO */
-		0x6F, 0x08,		/* hoAveragingDistance */
-		0x70, 0x08, 0x01,	/* hoAveragingLev */
-		0x71, 0x10, 0x10, 0x10,
-		0x72, 0x08, 0x02,	/* hoAveragingQual */
-		0x73, 0x0A,		/* hoLowerThresholdLevDL */
-		0x74, 0x05,		/* hoLowerThresholdLevUL */
-		0x75, 0x06,		/* hoLowerThresholdQualDL */
-		0x76, 0x06,		/* hoLowerThresholdQualUL */
-		0x78, 0x14,		/* hoThresholdLevDLintra */
-		0x79, 0x14,		/* hoThresholdLevULintra */
-		0x7A, 0x14,		/* hoThresholdMsRangeMax */
-		0x7D, 0x06,		/* nCell */
-		NM_ATT_BS11_TIMER_HO_REQUEST, 0x03,
-		0x20, 0x01, 0x00,
-		0x45, 0x01, 0x00,
-		0x48, 0x01, 0x00,
-		0x5A, 0x01, 0x00,
-		0x5B, 0x01, 0x05,
-		0x5E, 0x01, 0x1A,
-		0x5F, 0x01, 0x20,
-		0x9D, 0x01, 0x00,
-		0x47, 0x01, 0x00,
-		0x5C, 0x01, 0x64,
-		0x5D, 0x01, 0x1E,
-		0x97, 0x01, 0x20,
-		0xF7, 0x01, 0x3C,
-};
-
-// Power Control, SET ATTRIBUTES
-
-/*
-  Object Class: Power Control
-  BTS relat. Number: 0
-  Instance 2: FF
-  Instance 3: FF
-SET ATTRIBUTES
-  enableMsPowerControl: 00h =  Disabled
-  enablePowerControlRLFW: 00h =  Disabled
-  pcAveragingLev:
-    A_LEV_PC: 4  SACCH multiframes
-    W_LEV_PC: 1  SACCH multiframes
-  pcAveragingQual:
-    A_QUAL_PC: 4  SACCH multiframes
-    W_QUAL_PC: 2  SACCH multiframes
-  pcLowerThresholdLevDL: 0Fh
-  pcLowerThresholdLevUL: 0Ah
-  pcLowerThresholdQualDL: 05h =   3.2% < BER <  6.4%
-  pcLowerThresholdQualUL: 05h =   3.2% < BER <  6.4%
-  pcRLFThreshold: 0Ch
-  pcUpperThresholdLevDL: 14h
-  pcUpperThresholdLevUL: 0Fh
-  pcUpperThresholdQualDL: 04h =   1.6% < BER <  3.2%
-  pcUpperThresholdQualUL: 04h =   1.6% < BER <  3.2%
-  powerConfirm: 2  ,unit 2 SACCH multiframes
-  powerControlInterval: 2  ,unit 2 SACCH multiframes
-  powerIncrStepSize: 02h = 4 dB
-  powerRedStepSize: 01h = 2 dB
-  radioLinkTimeoutBs: 64  SACCH multiframes
-  enableBSPowerControl: 00h =  disabled
-*/
-
-unsigned char msg_4[] =
-{
-	NM_MT_BS11_SET_ATTR, NM_OC_BS11_PWR_CTRL, 0x00, 0xFF, 0xFF,
-		NM_ATT_BS11_ENA_MS_PWR_CTRL, 0x00,
-		NM_ATT_BS11_ENA_PWR_CTRL_RLFW, 0x00,
-		0x7E, 0x04, 0x01,	/* pcAveragingLev */
-		0x7F, 0x04, 0x02,	/* pcAveragingQual */
-		0x80, 0x0F,		/* pcLowerThresholdLevDL */
-		0x81, 0x0A,		/* pcLowerThresholdLevUL */
-		0x82, 0x05,		/* pcLowerThresholdQualDL */
-		0x83, 0x05,		/* pcLowerThresholdQualUL */
-		0x84, 0x0C, 		/* pcRLFThreshold */
-		0x85, 0x14, 		/* pcUpperThresholdLevDL */
-		0x86, 0x0F, 		/* pcUpperThresholdLevUL */
-		0x87, 0x04,		/* pcUpperThresholdQualDL */
-		0x88, 0x04,		/* pcUpperThresholdQualUL */
-		0x89, 0x02,		/* powerConfirm */
-		0x8A, 0x02,		/* powerConfirmInterval */
-		0x8B, 0x02,		/* powerIncrStepSize */
-		0x8C, 0x01,		/* powerRedStepSize */
-		0x8D, 0x40,		/* radioLinkTimeoutBs */
-		0x65, 0x01, 0x00 // set to 0x01 to enable BSPowerControl
-};
-
-
-// Transceiver, SET TRX ATTRIBUTES (TRX 0)
-
-/*
-  Object Class: Transceiver
-  BTS relat. Number: 0
-  Tranceiver number: 0
-  Instance 3: FF
-SET TRX ATTRIBUTES
-  aRFCNList (HEX):  0001
-  txPwrMaxReduction: 00h =   30dB
-  radioMeasGran: 254  SACCH multiframes
-  radioMeasRep: 01h =  enabled
-  memberOfEmergencyConfig: 01h =  TRUE
-  trxArea: 00h = TRX doesn't belong to a concentric cell
-*/
-
-static unsigned char bs11_attr_radio[] =
-{
-		NM_ATT_ARFCN_LIST, 0x01, 0x00, HARDCODED_ARFCN /*0x01*/,
-		NM_ATT_RF_MAXPOWR_R, 0x00,
-		NM_ATT_BS11_RADIO_MEAS_GRAN, 0x01, 0x05,
-		NM_ATT_BS11_RADIO_MEAS_REP, 0x01, 0x01,
-		NM_ATT_BS11_EMRG_CFG_MEMBER, 0x01, 0x01,
-		NM_ATT_BS11_TRX_AREA, 0x01, 0x00,
-};
-
-/*
- * Patch the various SYSTEM INFORMATION tables to update
- * the LAI
- */
-static void patch_nm_tables(struct gsm_bts *bts)
-{
-	uint8_t arfcn_low = bts->c0->arfcn & 0xff;
-	uint8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f;
-
-	/* T3105 attribute in units of 10ms */
-	bs11_attr_bts[2] = bts->network->T3105 / 10;
-
-	/* patch ARFCN into BTS Attributes */
-	bs11_attr_bts[69] &= 0xf0;
-	bs11_attr_bts[69] |= arfcn_high;
-	bs11_attr_bts[70] = arfcn_low;
-
-	/* patch ARFCN into TRX Attributes */
-	bs11_attr_radio[2] &= 0xf0;
-	bs11_attr_radio[2] |= arfcn_high;
-	bs11_attr_radio[3] = arfcn_low;
-
-	/* patch the RACH attributes */
-	if (bts->rach_b_thresh != -1)
-		bs11_attr_bts[33] = bts->rach_b_thresh & 0xff;
-
-	if (bts->rach_ldavg_slots != -1) {
-		uint8_t avg_high = bts->rach_ldavg_slots & 0xff;
-		uint8_t avg_low = (bts->rach_ldavg_slots >> 8) & 0x0f;
-
-		bs11_attr_bts[35] = avg_high;
-		bs11_attr_bts[36] = avg_low;
-	}
-
-	/* patch BSIC */
-	bs11_attr_bts[1] = bts->bsic;
-
-	/* patch the power reduction */
-	bs11_attr_radio[5] = bts->c0->max_power_red / 2;
-}
-
-
-static void nm_reconfig_ts(struct gsm_bts_trx_ts *ts)
-{
-	enum abis_nm_chan_comb ccomb = abis_nm_chcomb4pchan(ts->pchan);
-	struct gsm_e1_subslot *e1l = &ts->e1_link;
-
-	abis_nm_set_channel_attr(ts, ccomb);
-
-	if (is_ipaccess_bts(ts->trx->bts))
-		return;
-
-	if (ts_is_tch(ts))
-		abis_nm_conn_terr_traf(ts, e1l->e1_nr, e1l->e1_ts,
-					e1l->e1_ts_ss);
-}
-
-static void nm_reconfig_trx(struct gsm_bts_trx *trx)
-{
-	struct gsm_e1_subslot *e1l = &trx->rsl_e1_link;
-	int i;
-
-	patch_nm_tables(trx->bts);
-
-	switch (trx->bts->type) {
-	case GSM_BTS_TYPE_BS11:
-		/* FIXME: discover this by fetching an attribute */
-#if 0
-		trx->nominal_power = 15; /* 15dBm == 30mW PA configuration */
-#else
-		trx->nominal_power = 24; /* 24dBm == 250mW PA configuration */
-#endif
-		abis_nm_conn_terr_sign(trx, e1l->e1_nr, e1l->e1_ts,
-					e1l->e1_ts_ss);
-		abis_nm_establish_tei(trx->bts, trx->nr, e1l->e1_nr,
-				      e1l->e1_ts, e1l->e1_ts_ss, trx->rsl_tei);
-
-		/* Set Radio Attributes */
-		if (trx == trx->bts->c0)
-			abis_nm_set_radio_attr(trx, bs11_attr_radio,
-					       sizeof(bs11_attr_radio));
-		else {
-			uint8_t trx1_attr_radio[sizeof(bs11_attr_radio)];
-			uint8_t arfcn_low = trx->arfcn & 0xff;
-			uint8_t arfcn_high = (trx->arfcn >> 8) & 0x0f;
-			memcpy(trx1_attr_radio, bs11_attr_radio,
-				sizeof(trx1_attr_radio));
-
-			/* patch ARFCN into TRX Attributes */
-			trx1_attr_radio[2] &= 0xf0;
-			trx1_attr_radio[2] |= arfcn_high;
-			trx1_attr_radio[3] = arfcn_low;
-
-			abis_nm_set_radio_attr(trx, trx1_attr_radio,
-					       sizeof(trx1_attr_radio));
-		}
-		break;
-	case GSM_BTS_TYPE_NANOBTS:
-		switch (trx->bts->band) {
-		case GSM_BAND_850:
-		case GSM_BAND_900:
-			trx->nominal_power = 20;
-			break;
-		case GSM_BAND_1800:
-		case GSM_BAND_1900:
-			trx->nominal_power = 23;
-			break;
-		default:
-			LOGP(DNM, LOGL_ERROR, "Unsupported nanoBTS GSM band %s\n",
-				gsm_band_name(trx->bts->band));
-			break;
-		}
-		break;
-	default:
-		break;
-	}
-
-	for (i = 0; i < TRX_NR_TS; i++)
-		nm_reconfig_ts(&trx->ts[i]);
-}
-
-static void nm_reconfig_bts(struct gsm_bts *bts)
-{
-	struct gsm_bts_trx *trx;
-
-	switch (bts->type) {
-	case GSM_BTS_TYPE_BS11:
-		patch_nm_tables(bts);
-		abis_nm_raw_msg(bts, sizeof(msg_1), msg_1); /* set BTS SiteMgr attr*/
-		abis_nm_set_bts_attr(bts, bs11_attr_bts, sizeof(bs11_attr_bts));
-		abis_nm_raw_msg(bts, sizeof(msg_3), msg_3); /* set BTS handover attr */
-		abis_nm_raw_msg(bts, sizeof(msg_4), msg_4); /* set BTS power control attr */
-		break;
-	default:
-		break;
-	}
-
-	llist_for_each_entry(trx, &bts->trx_list, list)
-		nm_reconfig_trx(trx);
-}
-
-
-static void bootstrap_om_bs11(struct gsm_bts *bts)
-{
-	LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr);
-
-	/* stop sending event reports */
-	abis_nm_event_reports(bts, 0);
-
-	/* begin DB transmission */
-	abis_nm_bs11_db_transmission(bts, 1);
-
-	/* end DB transmission */
-	abis_nm_bs11_db_transmission(bts, 0);
-
-	/* Reset BTS Site manager resource */
-	abis_nm_bs11_reset_resource(bts);
-
-	/* begin DB transmission */
-	abis_nm_bs11_db_transmission(bts, 1);
-
-	/* reconfigure BTS with all TRX and all TS */
-	nm_reconfig_bts(bts);
-
-	/* end DB transmission */
-	abis_nm_bs11_db_transmission(bts, 0);
-
-	/* Reset BTS Site manager resource */
-	abis_nm_bs11_reset_resource(bts);
-
-	/* restart sending event reports */
-	abis_nm_event_reports(bts, 1);
-}
-
-static int shutdown_om(struct gsm_bts *bts)
-{
-	/* stop sending event reports */
-	abis_nm_event_reports(bts, 0);
-
-	/* begin DB transmission */
-	abis_nm_bs11_db_transmission(bts, 1);
-
-	/* end DB transmission */
-	abis_nm_bs11_db_transmission(bts, 0);
-
-	/* Reset BTS Site manager resource */
-	abis_nm_bs11_reset_resource(bts);
-
-	return 0;
-}
-
-/* Callback function to be called every time we receive a signal from INPUT */
-static int gbl_sig_cb(unsigned int subsys, unsigned int signal,
-		      void *handler_data, void *signal_data)
-{
-	struct gsm_bts *bts;
-
-	if (subsys != SS_L_GLOBAL)
-		return 0;
-
-	switch (signal) {
-	case S_GLOBAL_BTS_CLOSE_OM:
-		bts = signal_data;
-		if (bts->type == GSM_BTS_TYPE_BS11)
-			shutdown_om(signal_data);
-		break;
-	}
-
-	return 0;
-}
-
-/* Callback function to be called every time we receive a signal from INPUT */
-static int inp_sig_cb(unsigned int subsys, unsigned int signal,
-		      void *handler_data, void *signal_data)
-{
-	struct input_signal_data *isd = signal_data;
-
-	if (subsys != SS_L_INPUT)
-		return 0;
-
-	switch (signal) {
-	case S_L_INP_TEI_UP:
-		switch (isd->link_type) {
-		case E1INP_SIGN_OML:
-			if (isd->trx->bts->type == GSM_BTS_TYPE_BS11)
-				bootstrap_om_bs11(isd->trx->bts);
-			break;
-		}
-	}
-
-	return 0;
-}
-
-static int bts_model_bs11_start(struct gsm_network *net)
-{
-	model_bs11.features.data = &model_bs11._features_data[0];
-	model_bs11.features.data_len = sizeof(model_bs11._features_data);
-
-	gsm_btsmodel_set_feature(&model_bs11, BTS_FEAT_HOPPING);
-	gsm_btsmodel_set_feature(&model_bs11, BTS_FEAT_HSCSD);
-	gsm_btsmodel_set_feature(&model_bs11, BTS_FEAT_MULTI_TSC);
-
-	osmo_signal_register_handler(SS_L_INPUT, inp_sig_cb, NULL);
-	osmo_signal_register_handler(SS_L_GLOBAL, gbl_sig_cb, NULL);
-
-	return 0;
-}
-
-int bts_model_bs11_init(void)
-{
-	return gsm_bts_model_register(&model_bs11);
-}
diff --git a/src/libbsc/bts_sysmobts.c b/src/libbsc/bts_sysmobts.c
deleted file mode 100644
index e4b6cdc..0000000
--- a/src/libbsc/bts_sysmobts.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/* sysmocom sysmoBTS specific code */
-
-/* (C) 2010-2012 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/>.
- *
- */
-
-#include <arpa/inet.h>
-
-#include <osmocom/gsm/tlv.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/signal.h>
-#include <openbsc/abis_nm.h>
-#include <osmocom/abis/e1_input.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/talloc.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/debug.h>
-#include <osmocom/abis/subchan_demux.h>
-#include <osmocom/abis/ipaccess.h>
-#include <osmocom/core/logging.h>
-
-extern struct gsm_bts_model bts_model_nanobts;
-
-static struct gsm_bts_model model_sysmobts;
-
-int bts_model_sysmobts_init(void)
-{
-	model_sysmobts = bts_model_nanobts;
-	model_sysmobts.name = "sysmobts";
-	model_sysmobts.type = GSM_BTS_TYPE_OSMOBTS;
-
-	model_sysmobts.features.data = &model_sysmobts._features_data[0];
-	model_sysmobts.features.data_len =
-				sizeof(model_sysmobts._features_data);
-	memset(model_sysmobts.features.data, 0, sizeof(model_sysmobts.features.data_len));
-
-	gsm_btsmodel_set_feature(&model_sysmobts, BTS_FEAT_GPRS);
-	gsm_btsmodel_set_feature(&model_sysmobts, BTS_FEAT_EGPRS);
-
-	return gsm_bts_model_register(&model_sysmobts);
-}
diff --git a/src/libbsc/bts_unknown.c b/src/libbsc/bts_unknown.c
deleted file mode 100644
index f113529..0000000
--- a/src/libbsc/bts_unknown.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Generic BTS - VTY code tries to allocate this BTS before type is known */
-
-/* (C) 2010 by Daniel Willmann <daniel@totalueberwachung.de>
- *
- * 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/>.
- *
- */
-
-
-#include <openbsc/gsm_data.h>
-#include <osmocom/gsm/tlv.h>
-#include <openbsc/abis_nm.h>
-
-static struct gsm_bts_model model_unknown = {
-	.type = GSM_BTS_TYPE_UNKNOWN,
-	.name = "unknown",
-	.oml_rcvmsg = &abis_nm_rcvmsg,
-	.nm_att_tlvdef = {
-		.def = {
-		},
-	},
-};
-
-int bts_model_unknown_init(void)
-{
-	return gsm_bts_model_register(&model_unknown);
-}
diff --git a/src/libbsc/chan_alloc.c b/src/libbsc/chan_alloc.c
deleted file mode 100644
index 33b79a0..0000000
--- a/src/libbsc/chan_alloc.c
+++ /dev/null
@@ -1,543 +0,0 @@
-/* GSM Channel allocation routines
- *
- * (C) 2008 by Harald Welte <laforge@gnumonks.org>
- * (C) 2008, 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/>.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/chan_alloc.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/debug.h>
-#include <openbsc/rtp_proxy.h>
-#include <openbsc/signal.h>
-
-#include <osmocom/core/talloc.h>
-
-static int ts_is_usable(struct gsm_bts_trx_ts *ts)
-{
-	/* FIXME: How does this behave for BS-11 ? */
-	if (is_ipaccess_bts(ts->trx->bts)) {
-		if (!nm_is_running(&ts->mo.nm_state))
-			return 0;
-	}
-
-	/* If a TCH/F_PDCH TS is busy changing, it is already taken or not
-	 * yet available. */
-	if (ts->pchan == GSM_PCHAN_TCH_F_PDCH) {
-		if (ts->flags & TS_F_PDCH_PENDING_MASK)
-			return 0;
-	}
-
-	/* If a dynamic channel is busy changing, it is already taken or not
-	 * yet available. */
-	if (ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) {
-		if (ts->dyn.pchan_is != ts->dyn.pchan_want)
-			return 0;
-	}
-
-	return 1;
-}
-
-int trx_is_usable(struct gsm_bts_trx *trx)
-{
-	/* FIXME: How does this behave for BS-11 ? */
-	if (is_ipaccess_bts(trx->bts)) {
-		if (!nm_is_running(&trx->mo.nm_state) ||
-		    !nm_is_running(&trx->bb_transc.mo.nm_state))
-			return 0;
-	}
-
-	return 1;
-}
-
-static struct gsm_lchan *
-_lc_find_trx(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan,
-	     enum gsm_phys_chan_config dyn_as_pchan)
-{
-	struct gsm_bts_trx_ts *ts;
-	int j, start, stop, dir, ss;
-	int check_subslots;
-
-	if (!trx_is_usable(trx))
-		return NULL;
-
-	if (trx->bts->chan_alloc_reverse) {
-		/* check TS 7..0 */
-		start = 7;
-		stop = -1;
-		dir = -1;
-	} else {
-		/* check TS 0..7 */
-		start = 0;
-		stop = 8;
-		dir = 1;
-	}
-
-	for (j = start; j != stop; j += dir) {
-		ts = &trx->ts[j];
-		if (!ts_is_usable(ts))
-			continue;
-		if (ts->pchan != pchan)
-			continue;
-
-		/*
-		 * Allocation for fully dynamic timeslots
-		 * (does not apply for ip.access style GSM_PCHAN_TCH_F_PDCH)
-		 *
-		 * Note the special nature of a dynamic timeslot in PDCH mode:
-		 * in PDCH mode, typically, lchan->type is GSM_LCHAN_NONE and
-		 * lchan->state is LCHAN_S_NONE -- an otherwise unused slot
-		 * becomes PDCH implicitly. In the same sense, this channel
-		 * allocator will never be asked to find an available PDCH
-		 * slot; only TCH/F or TCH/H will be requested, and PDCH mode
-		 * means that it is available for switchover.
-		 *
-		 * A dynamic timeslot in PDCH mode may be switched to TCH/F or
-		 * TCH/H. If a dyn TS is already in TCH/F or TCH/H mode, it
-		 * means that it is in use and its mode can't be switched.
-		 *
-		 * The logic concerning channels for TCH/F is trivial: there is
-		 * only one channel, so a dynamic TS in TCH/F mode is already
-		 * taken and not available for allocation. For TCH/H, we need
-		 * to check whether a dynamic timeslot is already in TCH/H mode
-		 * and whether one of the two channels is still available.
-		 */
-		switch (pchan) {
-		case GSM_PCHAN_TCH_F_TCH_H_PDCH:
-			if (ts->dyn.pchan_is != ts->dyn.pchan_want) {
-				/* The TS's mode is being switched. Not
-				 * available anymore/yet. */
-				DEBUGP(DRLL, "%s already in switchover\n",
-				       gsm_ts_and_pchan_name(ts));
-				continue;
-			}
-			if (ts->dyn.pchan_is == GSM_PCHAN_PDCH) {
-				/* This slot is available. Still check for
-				 * error states to be sure; in all cases the
-				 * first lchan will be used. */
-				if (ts->lchan->state != LCHAN_S_NONE
-				    && ts->lchan->state != LCHAN_S_ACTIVE)
-					continue;
-				return ts->lchan;
-			}
-			if (ts->dyn.pchan_is != dyn_as_pchan)
-				/* not applicable. */
-				continue;
-			/* The requested type matches the dynamic timeslot's
-			 * current mode. A channel may still be available
-			 * (think TCH/H). */
-			check_subslots = ts_subslots(ts);
-			break;
-
-		case GSM_PCHAN_TCH_F_PDCH:
-			/* Available for voice when in PDCH mode */
-			if (ts_pchan(ts) != GSM_PCHAN_PDCH)
-				continue;
-			/* Subslots of a PDCH ts don't need to be checked. */
-			return ts->lchan;
-
-		default:
-			/* Not a dynamic channel, there is only one pchan kind: */
-			check_subslots = ts_subslots(ts);
-			break;
-		}
-
-		/* Is a sub-slot still available? */
-		for (ss = 0; ss < check_subslots; ss++) {
-			struct gsm_lchan *lc = &ts->lchan[ss];
-			if (lc->type == GSM_LCHAN_NONE &&
-			    lc->state == LCHAN_S_NONE)
-				return lc;
-		}
-	}
-
-	return NULL;
-}
-
-static struct gsm_lchan *
-_lc_dyn_find_bts(struct gsm_bts *bts, enum gsm_phys_chan_config pchan,
-		 enum gsm_phys_chan_config dyn_as_pchan)
-{
-	struct gsm_bts_trx *trx;
-	struct gsm_lchan *lc;
-
-	if (bts->chan_alloc_reverse) {
-		llist_for_each_entry_reverse(trx, &bts->trx_list, list) {
-			lc = _lc_find_trx(trx, pchan, dyn_as_pchan);
-			if (lc)
-				return lc;
-		}
-	} else {
-		llist_for_each_entry(trx, &bts->trx_list, list) {
-			lc = _lc_find_trx(trx, pchan, dyn_as_pchan);
-			if (lc)
-				return lc;
-		}
-	}
-
-	return NULL;
-}
-
-static struct gsm_lchan *
-_lc_find_bts(struct gsm_bts *bts, enum gsm_phys_chan_config pchan)
-{
-	return _lc_dyn_find_bts(bts, pchan, GSM_PCHAN_NONE);
-}
-
-/* Allocate a logical channel.
- *
- * Dynamic channel types: we always prefer a dedicated TS, and only pick +
- * switch a dynamic TS if no pure TS of the requested PCHAN is available.
- *
- * TCH_F/PDCH: if we pick a PDCH ACT style dynamic TS as TCH/F channel, PDCH
- * will be disabled in rsl_chan_activate_lchan(); there is no need to check
- * whether PDCH mode is currently active, here.
- */
-struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type,
-			      int allow_bigger)
-{
-	struct gsm_lchan *lchan = NULL;
-	enum gsm_phys_chan_config first, first_cbch, second, second_cbch;
-
-	switch (type) {
-	case GSM_LCHAN_SDCCH:
-		if (bts->chan_alloc_reverse) {
-			first = GSM_PCHAN_SDCCH8_SACCH8C;
-			first_cbch = GSM_PCHAN_SDCCH8_SACCH8C_CBCH;
-			second = GSM_PCHAN_CCCH_SDCCH4;
-			second_cbch = GSM_PCHAN_CCCH_SDCCH4_CBCH;
-		} else {
-			first = GSM_PCHAN_CCCH_SDCCH4;
-			first_cbch = GSM_PCHAN_CCCH_SDCCH4_CBCH;
-			second = GSM_PCHAN_SDCCH8_SACCH8C;
-			second_cbch = GSM_PCHAN_SDCCH8_SACCH8C_CBCH;
-		}
-
-		lchan = _lc_find_bts(bts, first);
-		if (lchan == NULL)
-			lchan = _lc_find_bts(bts, first_cbch);
-		if (lchan == NULL)
-			lchan = _lc_find_bts(bts, second);
-		if (lchan == NULL)
-			lchan = _lc_find_bts(bts, second_cbch);
-
-		/* allow to assign bigger channels */
-		if (allow_bigger) {
-			if (lchan == NULL) {
-				lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_H);
-				if (lchan)
-					type = GSM_LCHAN_TCH_H;
-			}
-
-			if (lchan == NULL) {
-				lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F);
-				if (lchan)
-					type = GSM_LCHAN_TCH_F;
-			}
-
-			/* try dynamic TCH/F_PDCH */
-			if (lchan == NULL) {
-				lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F_PDCH);
-				/* TCH/F_PDCH will be used as TCH/F */
-				if (lchan)
-					type = GSM_LCHAN_TCH_F;
-			}
-
-			/* try fully dynamic TCH/F_TCH/H_PDCH */
-			if (lchan == NULL) {
-				lchan = _lc_dyn_find_bts(bts, GSM_PCHAN_TCH_F_TCH_H_PDCH,
-							 GSM_PCHAN_TCH_H);
-				if (lchan)
-					type = GSM_LCHAN_TCH_H;
-			}
-			/*
-			 * No need to check fully dynamic channels for TCH/F:
-			 * if no TCH/H was available, neither will be TCH/F.
-			 */
-		}
-		break;
-	case GSM_LCHAN_TCH_F:
-		lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F);
-		/* If we don't have TCH/F available, fall-back to TCH/H */
-		if (!lchan) {
-			lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_H);
-			if (lchan)
-				type = GSM_LCHAN_TCH_H;
-		}
-		/* If we don't have TCH/H either, try dynamic TCH/F_PDCH */
-		if (!lchan) {
-			lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F_PDCH);
-			/* TCH/F_PDCH used as TCH/F -- here, type is already
-			 * set to GSM_LCHAN_TCH_F, but for clarity's sake... */
-			if (lchan)
-				type = GSM_LCHAN_TCH_F;
-		}
-
-		/* Try fully dynamic TCH/F_TCH/H_PDCH as TCH/F... */
-		if (!lchan && bts->network->dyn_ts_allow_tch_f) {
-			lchan = _lc_dyn_find_bts(bts,
-						 GSM_PCHAN_TCH_F_TCH_H_PDCH,
-						 GSM_PCHAN_TCH_F);
-			if (lchan)
-				type = GSM_LCHAN_TCH_F;
-		}
-		/* ...and as TCH/H. */
-		if (!lchan) {
-			lchan = _lc_dyn_find_bts(bts,
-						 GSM_PCHAN_TCH_F_TCH_H_PDCH,
-						 GSM_PCHAN_TCH_H);
-			if (lchan)
-				type = GSM_LCHAN_TCH_H;
-		}
-		break;
-	case GSM_LCHAN_TCH_H:
-		lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_H);
-		/* If we don't have TCH/H available, fall-back to TCH/F */
-		if (!lchan) {
-			lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F);
-			if (lchan)
-				type = GSM_LCHAN_TCH_F;
-		}
-		/* No dedicated TCH/x available -- try fully dynamic
-		 * TCH/F_TCH/H_PDCH */
-		if (!lchan) {
-			lchan = _lc_dyn_find_bts(bts,
-						 GSM_PCHAN_TCH_F_TCH_H_PDCH,
-						 GSM_PCHAN_TCH_H);
-			if (lchan)
-				type = GSM_LCHAN_TCH_H;
-		}
-		/*
-		 * No need to check TCH/F_TCH/H_PDCH channels for TCH/F:
-		 * if no TCH/H was available, neither will be TCH/F.
-		 */
-		/* If we don't have TCH/F either, try dynamic TCH/F_PDCH */
-		if (!lchan) {
-			lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F_PDCH);
-			if (lchan)
-				type = GSM_LCHAN_TCH_F;
-		}
-		break;
-	default:
-		LOGP(DRLL, LOGL_ERROR, "Unknown gsm_chan_t %u\n", type);
-	}
-
-	if (lchan) {
-		lchan->type = type;
-
-		LOGP(DRLL, LOGL_INFO, "%s Allocating lchan=%u as %s\n",
-		     gsm_ts_and_pchan_name(lchan->ts),
-		     lchan->nr, gsm_lchant_name(lchan->type));
-
-		/* clear sapis */
-		memset(lchan->sapis, 0, ARRAY_SIZE(lchan->sapis));
-
-		/* clear multi rate config */
-		memset(&lchan->mr_ms_lv, 0, sizeof(lchan->mr_ms_lv));
-		memset(&lchan->mr_bts_lv, 0, sizeof(lchan->mr_bts_lv));
-		lchan->broken_reason = "";
-	} else {
-		struct challoc_signal_data sig;
-
-		LOGP(DRLL, LOGL_ERROR, "Failed to allocate %s channel\n",
-		     gsm_lchant_name(type));
-
-		sig.bts = bts;
-		sig.type = type;
-		osmo_signal_dispatch(SS_CHALLOC, S_CHALLOC_ALLOC_FAIL, &sig);
-	}
-
-	return lchan;
-}
-
-/* Free a logical channel */
-void lchan_free(struct gsm_lchan *lchan)
-{
-	struct challoc_signal_data sig;
-	int i;
-
-	sig.type = lchan->type;
-	lchan->type = GSM_LCHAN_NONE;
-
-
-	if (lchan->conn) {
-		struct lchan_signal_data sig;
-
-		/* We might kill an active channel... */
-		sig.lchan = lchan;
-		sig.mr = NULL;
-		osmo_signal_dispatch(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, &sig);
-	}
-
-	if (lchan->abis_ip.rtp_socket) {
-		LOGP(DRLL, LOGL_ERROR, "%s RTP Proxy Socket remained open.\n",
-			gsm_lchan_name(lchan));
-		rtp_socket_free(lchan->abis_ip.rtp_socket);
-		lchan->abis_ip.rtp_socket = NULL;
-	}
-
-	/* stop the timer */
-	osmo_timer_del(&lchan->T3101);
-
-	/* clear cached measuement reports */
-	lchan->meas_rep_idx = 0;
-	for (i = 0; i < ARRAY_SIZE(lchan->meas_rep); i++) {
-		lchan->meas_rep[i].flags = 0;
-		lchan->meas_rep[i].nr = 0;
-	}
-	for (i = 0; i < ARRAY_SIZE(lchan->neigh_meas); i++)
-		lchan->neigh_meas[i].arfcn = 0;
-
-	if (lchan->rqd_ref) {
-		talloc_free(lchan->rqd_ref);
-		lchan->rqd_ref = NULL;
-		lchan->rqd_ta = 0;
-	}
-
-	sig.lchan = lchan;
-	sig.bts = lchan->ts->trx->bts;
-	osmo_signal_dispatch(SS_CHALLOC, S_CHALLOC_FREED, &sig);
-
-	if (lchan->conn) {
-		LOGP(DRLL, LOGL_ERROR, "the subscriber connection should be gone.\n");
-		lchan->conn = NULL;
-	}
-
-	/* FIXME: ts_free() the timeslot, if we're the last logical
-	 * channel using it */
-}
-
-/*
- * There was an error with the TRX and we need to forget
- * any state so that a lchan can be allocated again after
- * the trx is fully usable.
- *
- * This should be called after lchan_free to force a channel
- * be available for allocation again. This means that this
- * method will stop the "delay after error"-timer and set the
- * state to LCHAN_S_NONE.
- */
-void lchan_reset(struct gsm_lchan *lchan)
-{
-	osmo_timer_del(&lchan->T3101);
-	osmo_timer_del(&lchan->T3109);
-	osmo_timer_del(&lchan->T3111);
-	osmo_timer_del(&lchan->error_timer);
-
-	lchan->type = GSM_LCHAN_NONE;
-	lchan->state = LCHAN_S_NONE;
-
-	if (lchan->abis_ip.rtp_socket) {
-		rtp_socket_free(lchan->abis_ip.rtp_socket);
-		lchan->abis_ip.rtp_socket = NULL;
-	}
-}
-
-/* Drive the release process of the lchan */
-static void _lchan_handle_release(struct gsm_lchan *lchan,
-				  int sacch_deact, int mode)
-{
-	/* Release all SAPIs on the local end and continue */
-	rsl_release_sapis_from(lchan, 1, RSL_REL_LOCAL_END);
-
-	/*
-	 * Shall we send a RR Release, start T3109 and wait for the
-	 * release indication from the BTS or just take it down (e.g.
-	 * on assignment requests)
-	 */
-	if (sacch_deact) {
-		gsm48_send_rr_release(lchan);
-
-		/* Deactivate the SACCH on the BTS side */
-		rsl_deact_sacch(lchan);
-		rsl_start_t3109(lchan);
-	} else if (lchan->sapis[0] == LCHAN_SAPI_UNUSED) {
-		rsl_direct_rf_release(lchan);
-	} else {
-		rsl_release_request(lchan, 0, mode);
-	}
-}
-
-/* Consider releasing the channel now */
-int lchan_release(struct gsm_lchan *lchan, int sacch_deact, enum rsl_rel_mode mode)
-{
-	DEBUGP(DRLL, "%s starting release sequence\n", gsm_lchan_name(lchan));
-	rsl_lchan_set_state(lchan, LCHAN_S_REL_REQ);
-
-	lchan->conn = NULL;
-	_lchan_handle_release(lchan, sacch_deact, mode);
-	return 1;
-}
-
-void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts)
-{
-	struct gsm_bts_trx *trx;
-
-	llist_for_each_entry(trx, &bts->trx_list, list) {
-		int i;
-
-		/* skip administratively deactivated tranxsceivers */
-		if (!nm_is_running(&trx->mo.nm_state) ||
-		    !nm_is_running(&trx->bb_transc.mo.nm_state))
-			continue;
-
-		for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
-			struct gsm_bts_trx_ts *ts = &trx->ts[i];
-			struct load_counter *pl = &cl->pchan[ts->pchan];
-			int j;
-			int subslots;
-
-			/* skip administratively deactivated timeslots */
-			if (!nm_is_running(&ts->mo.nm_state))
-				continue;
-
-			subslots = ts_subslots(ts);
-			for (j = 0; j < subslots; j++) {
-				struct gsm_lchan *lchan = &ts->lchan[j];
-
-				pl->total++;
-
-				switch (lchan->state) {
-				case LCHAN_S_NONE:
-					break;
-				default:
-					pl->used++;
-					break;
-				}
-			}
-		}
-	}
-}
-
-void network_chan_load(struct pchan_load *pl, struct gsm_network *net)
-{
-	struct gsm_bts *bts;
-
-	memset(pl, 0, sizeof(*pl));
-
-	llist_for_each_entry(bts, &net->bts_list, list)
-		bts_chan_load(pl, bts);
-}
-
diff --git a/src/libbsc/e1_config.c b/src/libbsc/e1_config.c
deleted file mode 100644
index d57dec5..0000000
--- a/src/libbsc/e1_config.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/* OpenBSC E1 Input code */
-
-/* (C) 2008-2010 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/>.
- *
- */
-
-#include <string.h>
-#include <errno.h>
-
-#include <netinet/in.h>
-
-#include <openbsc/gsm_data.h>
-#include <osmocom/abis/e1_input.h>
-#include <osmocom/abis/trau_frame.h>
-#include <openbsc/trau_mux.h>
-#include <openbsc/misdn.h>
-#include <osmocom/abis/ipaccess.h>
-#include <osmocom/core/talloc.h>
-#include <openbsc/debug.h>
-#include <openbsc/abis_rsl.h>
-
-#define SAPI_L2ML	0
-#define SAPI_OML	62
-#define SAPI_RSL	0	/* 63 ? */
-
-/* The e1_reconfig_*() functions below take the configuration present in the
- * bts/trx/ts data structures and ensure the E1 configuration reflects the
- * timeslot/subslot/TEI configuration */
-
-int e1_reconfig_ts(struct gsm_bts_trx_ts *ts)
-{
-	struct gsm_e1_subslot *e1_link = &ts->e1_link;
-	struct e1inp_line *line;
-	struct e1inp_ts *e1_ts;
-
-	DEBUGP(DLMI, "e1_reconfig_ts(%u,%u,%u)\n", ts->trx->bts->nr, ts->trx->nr, ts->nr);
-
-	if (!e1_link->e1_ts) {
-		LOGP(DLINP, LOGL_ERROR, "TS (%u/%u/%u) without E1 timeslot?\n",
-		     ts->nr, ts->trx->nr, ts->trx->bts->nr);
-		return 0;
-	}
-
-	line = e1inp_line_find(e1_link->e1_nr);
-	if (!line) {
-		LOGP(DLINP, LOGL_ERROR, "TS (%u/%u/%u) referring to "
-		     "non-existing E1 line %u\n", ts->nr, ts->trx->nr,
-		     ts->trx->bts->nr, e1_link->e1_nr);
-		return -ENOMEM;
-	}
-
-	if (ts_is_tch(ts)) {
-		e1_ts = &line->ts[e1_link->e1_ts-1];
-		e1inp_ts_config_trau(e1_ts, line, subch_cb);
-		subch_demux_activate(&e1_ts->trau.demux, e1_link->e1_ts_ss);
-	}
-
-	return 0;
-}
-
-int e1_reconfig_trx(struct gsm_bts_trx *trx)
-{
-	struct gsm_e1_subslot *e1_link = &trx->rsl_e1_link;
-	struct e1inp_ts *sign_ts;
-	struct e1inp_line *line;
-	struct e1inp_sign_link *rsl_link;
-	int i;
-
-	if (!e1_link->e1_ts) {
-		LOGP(DLINP, LOGL_ERROR, "TRX (%u/%u) RSL link without "
-		     "timeslot?\n", trx->bts->nr, trx->nr);
-		return -EINVAL;
-	}
-
-	/* RSL Link */
-	line = e1inp_line_find(e1_link->e1_nr);
-	if (!line) {
-		LOGP(DLINP, LOGL_ERROR, "TRX (%u/%u) RSL link referring "
-		     "to non-existing E1 line %u\n", trx->bts->nr,
-		     trx->nr, e1_link->e1_nr);
-		return -ENOMEM;
-	}
-	sign_ts = &line->ts[e1_link->e1_ts-1];
-	e1inp_ts_config_sign(sign_ts, line);
-	/* Ericsson RBS have a per-TRX OML link in parallel to RSL */
-	if (trx->bts->type == GSM_BTS_TYPE_RBS2000) {
-		struct e1inp_sign_link *oml_link;
-		oml_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OML, trx,
-						  trx->rsl_tei, SAPI_OML);
-		if (!oml_link) {
-			LOGP(DLINP, LOGL_ERROR, "TRX (%u/%u) OML link creation "
-				"failed\n", trx->bts->nr, trx->nr);
-			return -ENOMEM;
-		}
-		if (trx->oml_link)
-			e1inp_sign_link_destroy(trx->oml_link);
-		trx->oml_link = oml_link;
-	}
-	rsl_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_RSL,
-					  trx, trx->rsl_tei, SAPI_RSL);
-	if (!rsl_link) {
-		LOGP(DLINP, LOGL_ERROR, "TRX (%u/%u) RSL link creation "
-		     "failed\n", trx->bts->nr, trx->nr);
-		return -ENOMEM;
-	}
-	if (trx->rsl_link)
-		e1inp_sign_link_destroy(trx->rsl_link);
-	trx->rsl_link = rsl_link;
-
-	for (i = 0; i < TRX_NR_TS; i++)
-		e1_reconfig_ts(&trx->ts[i]);
-
-	return 0;
-}
-
-/* this is the generic callback for all ISDN-based BTS. */
-static int bts_isdn_sign_link(struct msgb *msg)
-{
-	int ret = -EINVAL;
-	struct e1inp_sign_link *link = msg->dst;
-	struct gsm_bts *bts;
-
-	switch (link->type) {
-	case E1INP_SIGN_OML:
-		bts = link->trx->bts;
-		ret = bts->model->oml_rcvmsg(msg);
-		break;
-	case E1INP_SIGN_RSL:
-		ret = abis_rsl_rcvmsg(msg);
-		break;
-	default:
-		LOGP(DLMI, LOGL_ERROR, "unknown link type %u\n", link->type);
-		break;
-	}
-	return ret;
-}
-
-struct e1inp_line_ops bts_isdn_e1inp_line_ops = {
-	.sign_link	= bts_isdn_sign_link,
-};
-
-int e1_reconfig_bts(struct gsm_bts *bts)
-{
-	struct gsm_e1_subslot *e1_link = &bts->oml_e1_link;
-	struct e1inp_ts *sign_ts;
-	struct e1inp_line *line;
-	struct e1inp_sign_link *oml_link;
-	struct gsm_bts_trx *trx;
-
-	DEBUGP(DLMI, "e1_reconfig_bts(%u)\n", bts->nr);
-
-	line = e1inp_line_find(e1_link->e1_nr);
-	if (!line) {
-		LOGP(DLINP, LOGL_ERROR, "BTS %u OML link referring to "
-		     "non-existing E1 line %u\n", bts->nr, e1_link->e1_nr);
-		return -ENOMEM;
-	}
-
-	if (!bts->model->e1line_bind_ops) {
-		LOGP(DLINP, LOGL_ERROR, "no callback to bind E1 line operations\n");
-		return -EINVAL;
-	}
-	if (!line->ops)
-		bts->model->e1line_bind_ops(line);
-
-	/* skip signal link initialization, this is done later for these BTS. */
-	if (bts->type == GSM_BTS_TYPE_NANOBTS ||
-	    bts->type == GSM_BTS_TYPE_OSMOBTS)
-		return e1inp_line_update(line);
-
-	/* OML link */
-	if (!e1_link->e1_ts) {
-		LOGP(DLINP, LOGL_ERROR, "BTS %u OML link without timeslot?\n",
-		     bts->nr);
-		return -EINVAL;
-	}
-
-	sign_ts = &line->ts[e1_link->e1_ts-1];
-	e1inp_ts_config_sign(sign_ts, line);
-	oml_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OML,
-					  bts->c0, bts->oml_tei, SAPI_OML);
-	if (!oml_link) {
-		LOGP(DLINP, LOGL_ERROR, "BTS %u OML link creation failed\n",
-		     bts->nr);
-		return -ENOMEM;
-	}
-	if (bts->oml_link)
-		e1inp_sign_link_destroy(bts->oml_link);
-	bts->oml_link = oml_link;
-
-	llist_for_each_entry(trx, &bts->trx_list, list)
-		e1_reconfig_trx(trx);
-
-	/* notify E1 input something has changed */
-	return e1inp_line_update(line);
-}
-
-#if 0
-/* do some compiled-in configuration for our BTS/E1 setup */
-int e1_config(struct gsm_bts *bts, int cardnr, int release_l2)
-{
-	struct e1inp_line *line;
-	struct e1inp_ts *sign_ts;
-	struct e1inp_sign_link *oml_link, *rsl_link;
-	struct gsm_bts_trx *trx = bts->c0;
-	int base_ts;
-
-	switch (bts->nr) {
-	case 0:
-		/* First BTS uses E1 TS 01,02,03,04,05 */
-		base_ts = HARDCODED_BTS0_TS - 1;
-		break;
-	case 1:
-		/* Second BTS uses E1 TS 06,07,08,09,10 */
-		base_ts = HARDCODED_BTS1_TS - 1;
-		break;
-	case 2:
-		/* Third BTS uses E1 TS 11,12,13,14,15 */
-		base_ts = HARDCODED_BTS2_TS - 1;
-	default:
-		return -EINVAL;
-	}
-
-	line = talloc_zero(tall_bsc_ctx, struct e1inp_line);
-	if (!line)
-		return -ENOMEM;
-
-	/* create E1 timeslots for signalling and TRAU frames */
-	e1inp_ts_config(&line->ts[base_ts+1-1], line, E1INP_TS_TYPE_SIGN);
-	e1inp_ts_config(&line->ts[base_ts+2-1], line, E1INP_TS_TYPE_TRAU);
-	e1inp_ts_config(&line->ts[base_ts+3-1], line, E1INP_TS_TYPE_TRAU);
-
-	/* create signalling links for TS1 */
-	sign_ts = &line->ts[base_ts+1-1];
-	oml_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OML,
-					  trx, TEI_OML, SAPI_OML);
-	rsl_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_RSL,
-					  trx, TEI_RSL, SAPI_RSL);
-
-	/* create back-links from bts/trx */
-	bts->oml_link = oml_link;
-	trx->rsl_link = rsl_link;
-
-	/* enable subchannel demuxer on TS2 */
-	subch_demux_activate(&line->ts[base_ts+2-1].trau.demux, 1);
-	subch_demux_activate(&line->ts[base_ts+2-1].trau.demux, 2);
-	subch_demux_activate(&line->ts[base_ts+2-1].trau.demux, 3);
-
-	/* enable subchannel demuxer on TS3 */
-	subch_demux_activate(&line->ts[base_ts+3-1].trau.demux, 0);
-	subch_demux_activate(&line->ts[base_ts+3-1].trau.demux, 1);
-	subch_demux_activate(&line->ts[base_ts+3-1].trau.demux, 2);
-	subch_demux_activate(&line->ts[base_ts+3-1].trau.demux, 3);
-
-	trx = gsm_bts_trx_num(bts, 1);
-	if (trx) {
-		/* create E1 timeslots for TRAU frames of TRX1 */
-		e1inp_ts_config(&line->ts[base_ts+4-1], line, E1INP_TS_TYPE_TRAU);
-		e1inp_ts_config(&line->ts[base_ts+5-1], line, E1INP_TS_TYPE_TRAU);
-
-		/* create RSL signalling link for TRX1 */
-		sign_ts = &line->ts[base_ts+1-1];
-		rsl_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_RSL,
-					  trx, TEI_RSL+1, SAPI_RSL);
-		/* create back-links from trx */
-		trx->rsl_link = rsl_link;
-
-		/* enable subchannel demuxer on TS2 */
-		subch_demux_activate(&line->ts[base_ts+4-1].trau.demux, 0);
-		subch_demux_activate(&line->ts[base_ts+4-1].trau.demux, 1);
-		subch_demux_activate(&line->ts[base_ts+4-1].trau.demux, 2);
-		subch_demux_activate(&line->ts[base_ts+4-1].trau.demux, 3);
-
-		/* enable subchannel demuxer on TS3 */
-		subch_demux_activate(&line->ts[base_ts+5-1].trau.demux, 0);
-		subch_demux_activate(&line->ts[base_ts+5-1].trau.demux, 1);
-		subch_demux_activate(&line->ts[base_ts+5-1].trau.demux, 2);
-		subch_demux_activate(&line->ts[base_ts+5-1].trau.demux, 3);
-	}
-
-	return mi_setup(cardnr, line, release_l2);
-}
-#endif
diff --git a/src/libbsc/gsm_04_08_utils.c b/src/libbsc/gsm_04_08_utils.c
deleted file mode 100644
index 7c5e0e9..0000000
--- a/src/libbsc/gsm_04_08_utils.c
+++ /dev/null
@@ -1,632 +0,0 @@
-/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
- * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0
- * utility functions
- */
-
-/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2008, 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/>.
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <netinet/in.h>
-
-#include <osmocom/core/msgb.h>
-#include <osmocom/gsm/gsm48.h>
-
-#include <openbsc/abis_rsl.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/transaction.h>
-#include <openbsc/paging.h>
-#include <openbsc/signal.h>
-#include <openbsc/bsc_api.h>
-
-/* should ip.access BTS use direct RTP streams between each other (1),
- * or should OpenBSC always act as RTP relay/proxy in between (0) ? */
-int ipacc_rtp_direct = 1;
-
-static int gsm48_sendmsg(struct msgb *msg)
-{
-	if (msg->lchan)
-		msg->dst = msg->lchan->ts->trx->rsl_link;
-
-	msg->l3h = msg->data;
-	return rsl_data_request(msg, 0);
-}
-
-/* Section 9.1.8 / Table 9.9 */
-struct chreq {
-	uint8_t val;
-	uint8_t mask;
-	enum chreq_type type;
-};
-
-/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
-static const struct chreq chreq_type_neci1[] = {
-	{ 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
-	{ 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
-	{ 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
-	{ 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
-	{ 0xe0, 0xe0, CHREQ_T_TCH_F },
-	{ 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
-	{ 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
-	{ 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
-	{ 0x10, 0xf0, CHREQ_T_SDCCH },
-	{ 0x80, 0xe0, CHREQ_T_PAG_R_ANY_NECI1 },
-	{ 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
-	{ 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
-	{ 0x67, 0xff, CHREQ_T_LMU },
-	{ 0x60, 0xf9, CHREQ_T_RESERVED_SDCCH },
-	{ 0x61, 0xfb, CHREQ_T_RESERVED_SDCCH },
-	{ 0x63, 0xff, CHREQ_T_RESERVED_SDCCH },
-	{ 0x70, 0xf8, CHREQ_T_PDCH_TWO_PHASE },
-	{ 0x78, 0xfc, CHREQ_T_PDCH_ONE_PHASE },
-	{ 0x78, 0xfa, CHREQ_T_PDCH_ONE_PHASE },
-	{ 0x78, 0xf9, CHREQ_T_PDCH_ONE_PHASE },
-	{ 0x7f, 0xff, CHREQ_T_RESERVED_IGNORE },
-};
-
-/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
-static const struct chreq chreq_type_neci0[] = {
-	{ 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
-	{ 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
-	{ 0xe0, 0xe0, CHREQ_T_TCH_F },
-	{ 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
-	{ 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
-	{ 0x80, 0xe0, CHREQ_T_PAG_R_ANY_NECI0 },
-	{ 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
-	{ 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
-	{ 0x67, 0xff, CHREQ_T_LMU },
-	{ 0x60, 0xf9, CHREQ_T_RESERVED_SDCCH },
-	{ 0x61, 0xfb, CHREQ_T_RESERVED_SDCCH },
-	{ 0x63, 0xff, CHREQ_T_RESERVED_SDCCH },
-	{ 0x70, 0xf8, CHREQ_T_PDCH_TWO_PHASE },
-	{ 0x78, 0xfc, CHREQ_T_PDCH_ONE_PHASE },
-	{ 0x78, 0xfa, CHREQ_T_PDCH_ONE_PHASE },
-	{ 0x78, 0xf9, CHREQ_T_PDCH_ONE_PHASE },
-	{ 0x7f, 0xff, CHREQ_T_RESERVED_IGNORE },
-};
-
-static const enum gsm_chan_t ctype_by_chreq[] = {
-	[CHREQ_T_EMERG_CALL]		= GSM_LCHAN_TCH_F,
-	[CHREQ_T_CALL_REEST_TCH_F]	= GSM_LCHAN_TCH_F,
-	[CHREQ_T_CALL_REEST_TCH_H]	= GSM_LCHAN_TCH_H,
-	[CHREQ_T_CALL_REEST_TCH_H_DBL]	= GSM_LCHAN_TCH_H,
-	[CHREQ_T_SDCCH]			= GSM_LCHAN_SDCCH,
-	[CHREQ_T_TCH_F]			= GSM_LCHAN_TCH_F,
-	[CHREQ_T_VOICE_CALL_TCH_H]	= GSM_LCHAN_TCH_H,
-	[CHREQ_T_DATA_CALL_TCH_H]	= GSM_LCHAN_TCH_H,
-	[CHREQ_T_LOCATION_UPD]		= GSM_LCHAN_SDCCH,
-	[CHREQ_T_PAG_R_ANY_NECI1]	= GSM_LCHAN_SDCCH,
-	[CHREQ_T_PAG_R_ANY_NECI0]	= GSM_LCHAN_SDCCH,
-	[CHREQ_T_PAG_R_TCH_F]		= GSM_LCHAN_TCH_F,
-	[CHREQ_T_PAG_R_TCH_FH]		= GSM_LCHAN_TCH_F,
-	[CHREQ_T_LMU]			= GSM_LCHAN_SDCCH,
-	[CHREQ_T_RESERVED_SDCCH]	= GSM_LCHAN_SDCCH,
-	[CHREQ_T_PDCH_ONE_PHASE]	= GSM_LCHAN_PDTCH,
-	[CHREQ_T_PDCH_TWO_PHASE]	= GSM_LCHAN_PDTCH,
-	[CHREQ_T_RESERVED_IGNORE]	= GSM_LCHAN_UNKNOWN,
-};
-
-static const enum gsm_chreq_reason_t reason_by_chreq[] = {
-	[CHREQ_T_EMERG_CALL]		= GSM_CHREQ_REASON_EMERG,
-	[CHREQ_T_CALL_REEST_TCH_F]	= GSM_CHREQ_REASON_CALL,
-	[CHREQ_T_CALL_REEST_TCH_H]	= GSM_CHREQ_REASON_CALL,
-	[CHREQ_T_CALL_REEST_TCH_H_DBL]	= GSM_CHREQ_REASON_CALL,
-	[CHREQ_T_SDCCH]			= GSM_CHREQ_REASON_OTHER,
-	[CHREQ_T_TCH_F]			= GSM_CHREQ_REASON_OTHER,
-	[CHREQ_T_VOICE_CALL_TCH_H]	= GSM_CHREQ_REASON_CALL,
-	[CHREQ_T_DATA_CALL_TCH_H]	= GSM_CHREQ_REASON_OTHER,
-	[CHREQ_T_LOCATION_UPD]		= GSM_CHREQ_REASON_LOCATION_UPD,
-	[CHREQ_T_PAG_R_ANY_NECI1]	= GSM_CHREQ_REASON_PAG,
-	[CHREQ_T_PAG_R_ANY_NECI0]	= GSM_CHREQ_REASON_PAG,
-	[CHREQ_T_PAG_R_TCH_F]		= GSM_CHREQ_REASON_PAG,
-	[CHREQ_T_PAG_R_TCH_FH]		= GSM_CHREQ_REASON_PAG,
-	[CHREQ_T_LMU]			= GSM_CHREQ_REASON_OTHER,
-	[CHREQ_T_PDCH_ONE_PHASE]	= GSM_CHREQ_REASON_PDCH,
-	[CHREQ_T_PDCH_TWO_PHASE]	= GSM_CHREQ_REASON_PDCH,
-	[CHREQ_T_RESERVED_SDCCH]	= GSM_CHREQ_REASON_OTHER,
-	[CHREQ_T_RESERVED_IGNORE]	= GSM_CHREQ_REASON_OTHER,
-};
-
-/* verify that the two tables match */
-osmo_static_assert(sizeof(ctype_by_chreq) ==
-	      sizeof(((struct gsm_network *) NULL)->ctype_by_chreq), assert_size);
-
-/*
- * Update channel types for request based on policy. E.g. in the
- * case of a TCH/H network/bsc use TCH/H for the emergency calls,
- * for early assignment assign a SDCCH and some other options.
- */
-void gsm_net_update_ctype(struct gsm_network *network)
-{
-	/* copy over the data */
-	memcpy(network->ctype_by_chreq, ctype_by_chreq, sizeof(ctype_by_chreq));
-
-	/*
-	 * Use TCH/H for emergency calls when this cell allows TCH/H. Maybe it
-	 * is better to iterate over the BTS/TRX and check if no TCH/F is available
-	 * and then set it to TCH/H.
-	 */
-	if (network->neci)
-		network->ctype_by_chreq[CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_H;
-
-	if (network->pag_any_tch) {
-		if (network->neci) {
-			network->ctype_by_chreq[CHREQ_T_PAG_R_ANY_NECI0] = GSM_LCHAN_TCH_H;
-			network->ctype_by_chreq[CHREQ_T_PAG_R_ANY_NECI1] = GSM_LCHAN_TCH_H;
-		} else {
-			network->ctype_by_chreq[CHREQ_T_PAG_R_ANY_NECI0] = GSM_LCHAN_TCH_F;
-			network->ctype_by_chreq[CHREQ_T_PAG_R_ANY_NECI1] = GSM_LCHAN_TCH_F;
-		}
-	}
-}
-
-enum gsm_chan_t get_ctype_by_chreq(struct gsm_network *network, uint8_t ra)
-{
-	int i;
-	int length;
-	const struct chreq *chreq;
-
-	if (network->neci) {
-		chreq = chreq_type_neci1;
-		length = ARRAY_SIZE(chreq_type_neci1);
-	} else {
-		chreq = chreq_type_neci0;
-		length = ARRAY_SIZE(chreq_type_neci0);
-	}
-
-
-	for (i = 0; i < length; i++) {
-		const struct chreq *chr = &chreq[i];
-		if ((ra & chr->mask) == chr->val)
-			return network->ctype_by_chreq[chr->type];
-	}
-	LOGP(DRR, LOGL_ERROR, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
-	return GSM_LCHAN_SDCCH;
-}
-
-int get_reason_by_chreq(uint8_t ra, int neci)
-{
-	int i;
-	int length;
-	const struct chreq *chreq;
-
-	if (neci) {
-		chreq = chreq_type_neci1;
-		length = ARRAY_SIZE(chreq_type_neci1);
-	} else {
-		chreq = chreq_type_neci0;
-		length = ARRAY_SIZE(chreq_type_neci0);
-	}
-
-	for (i = 0; i < length; i++) {
-		const struct chreq *chr = &chreq[i];
-		if ((ra & chr->mask) == chr->val)
-			return reason_by_chreq[chr->type];
-	}
-	LOGP(DRR, LOGL_ERROR, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
-	return GSM_CHREQ_REASON_OTHER;
-}
-
-static void mr_config_for_ms(struct gsm_lchan *lchan, struct msgb *msg)
-{
-	if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
-		msgb_tlv_put(msg, GSM48_IE_MUL_RATE_CFG, lchan->mr_ms_lv[0],
-			lchan->mr_ms_lv + 1);
-}
-
-/* 7.1.7 and 9.1.7: RR CHANnel RELease */
-int gsm48_send_rr_release(struct gsm_lchan *lchan)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 RR REL");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	uint8_t *cause;
-
-	msg->lchan = lchan;
-	gh->proto_discr = GSM48_PDISC_RR;
-	gh->msg_type = GSM48_MT_RR_CHAN_REL;
-
-	cause = msgb_put(msg, 1);
-	cause[0] = GSM48_RR_CAUSE_NORMAL;
-
-	DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
-		lchan->nr, lchan->type);
-
-	/* Send actual release request to MS */
-	return gsm48_sendmsg(msg);
-}
-
-int send_siemens_mrpci(struct gsm_lchan *lchan,
-		       uint8_t *classmark2_lv)
-{
-	struct rsl_mrpci mrpci;
-
-	if (classmark2_lv[0] < 2)
-		return -EINVAL;
-
-	mrpci.power_class = classmark2_lv[1] & 0x7;
-	mrpci.vgcs_capable = classmark2_lv[2] & (1 << 1);
-	mrpci.vbs_capable = classmark2_lv[2] & (1 <<2);
-	mrpci.gsm_phase = (classmark2_lv[1]) >> 5 & 0x3;
-
-	return rsl_siemens_mrpci(lchan, &mrpci);
-}
-
-/* Chapter 9.1.9: Ciphering Mode Command */
-int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CIPH");
-	struct gsm48_hdr *gh;
-	uint8_t ciph_mod_set;
-
-	msg->lchan = lchan;
-
-	DEBUGP(DRR, "TX CIPHERING MODE CMD\n");
-
-	if (lchan->encr.alg_id <= RSL_ENC_ALG_A5(0))
-		ciph_mod_set = 0;
-	else
-		ciph_mod_set = (lchan->encr.alg_id-2)<<1 | 1;
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
-	gh->proto_discr = GSM48_PDISC_RR;
-	gh->msg_type = GSM48_MT_RR_CIPH_M_CMD;
-	gh->data[0] = (want_imeisv & 0x1) << 4 | (ciph_mod_set & 0xf);
-
-	return rsl_encryption_cmd(msg);
-}
-
-static void gsm48_cell_desc(struct gsm48_cell_desc *cd,
-			    const struct gsm_bts *bts)
-{
-	cd->ncc = (bts->bsic >> 3 & 0x7);
-	cd->bcc = (bts->bsic & 0x7);
-	cd->arfcn_hi = bts->c0->arfcn >> 8;
-	cd->arfcn_lo = bts->c0->arfcn & 0xff;
-}
-
-void gsm48_lchan2chan_desc(struct gsm48_chan_desc *cd,
-			   const struct gsm_lchan *lchan)
-{
-	uint16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
-
-	cd->chan_nr = gsm_lchan2chan_nr(lchan);
-	if (!lchan->ts->hopping.enabled) {
-		cd->h0.tsc = gsm_ts_tsc(lchan->ts);
-		cd->h0.h = 0;
-		cd->h0.arfcn_high = arfcn >> 8;
-		cd->h0.arfcn_low = arfcn & 0xff;
-	} else {
-		cd->h1.tsc = gsm_ts_tsc(lchan->ts);
-		cd->h1.h = 1;
-		cd->h1.maio_high = lchan->ts->hopping.maio >> 2;
-		cd->h1.maio_low = lchan->ts->hopping.maio & 0x03;
-		cd->h1.hsn = lchan->ts->hopping.hsn;
-	}
-}
-
-/*! \brief Encode a TS 04.08 multirate config LV according to 10.5.2.21aa
- *  \param[out] lv caller-allocated buffer of 7 bytes. First octet is IS length
- *  \param[in] mr multi-rate configuration to encode
- *  \param[in] modes array describing the AMR modes
- *  \returns 0 on success */
-int gsm48_multirate_config(uint8_t *lv, const struct amr_multirate_conf *mr, const struct amr_mode *modes)
-{
-	int num = 0, i;
-
-	for (i = 0; i < 8; i++) {
-		if (((mr->gsm48_ie[1] >> i) & 1))
-			num++;
-	}
-	if (num > 4) {
-		LOGP(DRR, LOGL_ERROR, "BUG: Using multirate codec with too "
-				"many modes in config.\n");
-		num = 4;
-	}
-	if (num < 1) {
-		LOGP(DRR, LOGL_ERROR, "BUG: Using multirate codec with no "
-				"mode in config.\n");
-		num = 1;
-	}
-
-	lv[0] = (num == 1) ? 2 : (num + 2);
-	memcpy(lv + 1, mr->gsm48_ie, 2);
-	if (num == 1)
-		return 0;
-
-	lv[3] = modes[0].threshold & 0x3f;
-	lv[4] = modes[0].hysteresis << 4;
-	if (num == 2)
-		return 0;
-	lv[4] |= (modes[1].threshold & 0x3f) >> 2;
-	lv[5] = modes[1].threshold << 6;
-	lv[5] |= (modes[1].hysteresis & 0x0f) << 2;
-	if (num == 3)
-		return 0;
-	lv[5] |= (modes[2].threshold & 0x3f) >> 4;
-	lv[6] = modes[2].threshold << 4;
-	lv[6] |= modes[2].hysteresis & 0x0f;
-
-	return 0;
-}
-
-#define GSM48_HOCMD_CCHDESC_LEN	16
-
-/* Chapter 9.1.15: Handover Command */
-int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan,
-		      uint8_t power_command, uint8_t ho_ref)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 HO CMD");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	struct gsm48_ho_cmd *ho =
-		(struct gsm48_ho_cmd *) msgb_put(msg, sizeof(*ho));
-
-	msg->lchan = old_lchan;
-	gh->proto_discr = GSM48_PDISC_RR;
-	gh->msg_type = GSM48_MT_RR_HANDO_CMD;
-
-	/* mandatory bits */
-	gsm48_cell_desc(&ho->cell_desc, new_lchan->ts->trx->bts);
-	gsm48_lchan2chan_desc(&ho->chan_desc, new_lchan);
-	ho->ho_ref = ho_ref;
-	ho->power_command = power_command;
-
-	if (new_lchan->ts->hopping.enabled) {
-		struct gsm_bts *bts = new_lchan->ts->trx->bts;
-		struct gsm48_system_information_type_1 *si1;
-		uint8_t *cur;
-
-		si1 = GSM_BTS_SI(bts, SYSINFO_TYPE_1);
-		/* Copy the Cell Chan Desc (ARFCNS in this cell) */
-		msgb_put_u8(msg, GSM48_IE_CELL_CH_DESC);
-		cur = msgb_put(msg, GSM48_HOCMD_CCHDESC_LEN);
-		memcpy(cur, si1->cell_channel_description,
-			GSM48_HOCMD_CCHDESC_LEN);
-		/* Copy the Mobile Allocation */
-		msgb_tlv_put(msg, GSM48_IE_MA_BEFORE,
-			     new_lchan->ts->hopping.ma_len,
-			     new_lchan->ts->hopping.ma_data);
-	}
-	/* FIXME: optional bits for type of synchronization? */
-
-	return gsm48_sendmsg(msg);
-}
-
-/* Chapter 9.1.2: Assignment Command */
-int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, uint8_t power_command)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ASS CMD");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	struct gsm48_ass_cmd *ass =
-		(struct gsm48_ass_cmd *) msgb_put(msg, sizeof(*ass));
-
-	DEBUGP(DRR, "-> ASSIGNMENT COMMAND tch_mode=0x%02x\n", lchan->tch_mode);
-
-	msg->lchan = dest_lchan;
-	gh->proto_discr = GSM48_PDISC_RR;
-	gh->msg_type = GSM48_MT_RR_ASS_CMD;
-
-	/*
-	 * fill the channel information element, this code
-	 * should probably be shared with rsl_rx_chan_rqd(),
-	 * gsm48_lchan_modify(). But beware that 10.5.2.5
-	 * 10.5.2.5.a have slightly different semantic for
-	 * the chan_desc. But as long as multi-slot configurations
-	 * are not used we seem to be fine.
-	 */
-	gsm48_lchan2chan_desc(&ass->chan_desc, lchan);
-	ass->power_command = power_command;
-
-	/* optional: cell channel description */
-
-	msgb_tv_put(msg, GSM48_IE_CHANMODE_1, lchan->tch_mode);
-
-	/* mobile allocation in case of hopping */
-	if (lchan->ts->hopping.enabled) {
-		msgb_tlv_put(msg, GSM48_IE_MA_BEFORE, lchan->ts->hopping.ma_len,
-			     lchan->ts->hopping.ma_data);
-	}
-
-	/* in case of multi rate we need to attach a config */
-	mr_config_for_ms(lchan, msg);
-
-	return gsm48_sendmsg(msg);
-}
-
-/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
-int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t mode)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CHN MOD");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	struct gsm48_chan_mode_modify *cmm =
-		(struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
-
-	DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
-
-	lchan->tch_mode = mode;
-	msg->lchan = lchan;
-	gh->proto_discr = GSM48_PDISC_RR;
-	gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
-
-	/* fill the channel information element, this code
-	 * should probably be shared with rsl_rx_chan_rqd() */
-	gsm48_lchan2chan_desc(&cmm->chan_desc, lchan);
-	cmm->mode = mode;
-
-	/* in case of multi rate we need to attach a config */
-	mr_config_for_ms(lchan, msg);
-
-	return gsm48_sendmsg(msg);
-}
-
-int gsm48_rx_rr_modif_ack(struct msgb *msg)
-{
-	int rc;
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	struct gsm48_chan_mode_modify *mod =
-				(struct gsm48_chan_mode_modify *) gh->data;
-
-	DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
-
-	if (mod->mode != msg->lchan->tch_mode) {
-		LOGP(DRR, LOGL_ERROR, "CHANNEL MODE change failed. Wanted: %d Got: %d\n",
-			msg->lchan->tch_mode, mod->mode);
-		return -1;
-	}
-
-	/* update the channel type */
-	switch (mod->mode) {
-	case GSM48_CMODE_SIGN:
-		msg->lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
-		break;
-	case GSM48_CMODE_SPEECH_V1:
-	case GSM48_CMODE_SPEECH_EFR:
-	case GSM48_CMODE_SPEECH_AMR:
-		msg->lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
-		break;
-	case GSM48_CMODE_DATA_14k5:
-	case GSM48_CMODE_DATA_12k0:
-	case GSM48_CMODE_DATA_6k0:
-	case GSM48_CMODE_DATA_3k6:
-		msg->lchan->rsl_cmode = RSL_CMOD_SPD_DATA;
-		break;
-	}
-
-	/* We've successfully modified the MS side of the channel,
-	 * now go on to modify the BTS side of the channel */
-	rc = rsl_chan_mode_modify_req(msg->lchan);
-
-	/* FIXME: we not only need to do this after mode modify, but
-	 * also after channel activation */
-	if (is_ipaccess_bts(msg->lchan->ts->trx->bts) && mod->mode != GSM48_CMODE_SIGN)
-		rsl_ipacc_crcx(msg->lchan);
-	return rc;
-}
-
-int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	uint8_t *data = gh->data;
-	struct gsm_bts *bts = msg->lchan->ts->trx->bts;
-	struct bitvec *nbv = &bts->si_common.neigh_list;
-	struct gsm_meas_rep_cell *mrc;
-
-	if (gh->msg_type != GSM48_MT_RR_MEAS_REP)
-		return -EINVAL;
-
-	if (data[0] & 0x80)
-		rep->flags |= MEAS_REP_F_BA1;
-	if (data[0] & 0x40)
-		rep->flags |= MEAS_REP_F_UL_DTX;
-	if ((data[1] & 0x40) == 0x00)
-		rep->flags |= MEAS_REP_F_DL_VALID;
-
-	rep->dl.full.rx_lev = data[0] & 0x3f;
-	rep->dl.sub.rx_lev = data[1] & 0x3f;
-	rep->dl.full.rx_qual = (data[2] >> 4) & 0x7;
-	rep->dl.sub.rx_qual = (data[2] >> 1) & 0x7;
-
-	rep->num_cell = ((data[3] >> 6) & 0x3) | ((data[2] & 0x01) << 2);
-	if (rep->num_cell < 1 || rep->num_cell > 6)
-		return 0;
-
-	/* an encoding nightmare in perfection */
-	mrc = &rep->cell[0];
-	mrc->rxlev = data[3] & 0x3f;
-	mrc->neigh_idx = data[4] >> 3;
-	mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
-	mrc->bsic = ((data[4] & 0x07) << 3) | (data[5] >> 5);
-	if (rep->num_cell < 2)
-		return 0;
-
-	mrc = &rep->cell[1];
-	mrc->rxlev = ((data[5] & 0x1f) << 1) | (data[6] >> 7);
-	mrc->neigh_idx = (data[6] >> 2) & 0x1f;
-	mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
-	mrc->bsic = ((data[6] & 0x03) << 4) | (data[7] >> 4);
-	if (rep->num_cell < 3)
-		return 0;
-
-	mrc = &rep->cell[2];
-	mrc->rxlev = ((data[7] & 0x0f) << 2) | (data[8] >> 6);
-	mrc->neigh_idx = (data[8] >> 1) & 0x1f;
-	mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
-	mrc->bsic = ((data[8] & 0x01) << 5) | (data[9] >> 3);
-	if (rep->num_cell < 4)
-		return 0;
-
-	mrc = &rep->cell[3];
-	mrc->rxlev = ((data[9] & 0x07) << 3) | (data[10] >> 5);
-	mrc->neigh_idx = data[10] & 0x1f;
-	mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
-	mrc->bsic = data[11] >> 2;
-	if (rep->num_cell < 5)
-		return 0;
-
-	mrc = &rep->cell[4];
-	mrc->rxlev = ((data[11] & 0x03) << 4) | (data[12] >> 4);
-	mrc->neigh_idx = ((data[12] & 0xf) << 1) | (data[13] >> 7);
-	mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
-	mrc->bsic = (data[13] >> 1) & 0x3f;
-	if (rep->num_cell < 6)
-		return 0;
-
-	mrc = &rep->cell[5];
-	mrc->rxlev = ((data[13] & 0x01) << 5) | (data[14] >> 3);
-	mrc->neigh_idx = ((data[14] & 0x07) << 2) | (data[15] >> 6);
-	mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
-	mrc->bsic = data[15] & 0x3f;
-
-	return 0;
-}
-
-/* 9.2.5 CM service accept */
-int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SERV ACK");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	msg->lchan = conn->lchan;
-
-	gh->proto_discr = GSM48_PDISC_MM;
-	gh->msg_type = GSM48_MT_MM_CM_SERV_ACC;
-
-	DEBUGP(DMM, "-> CM SERVICE ACK\n");
-
-	return gsm0808_submit_dtap(conn, msg, 0, 0);
-}
-
-/* 9.2.6 CM service reject */
-int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
-				enum gsm48_reject_value value)
-{
-	struct msgb *msg;
-
-	msg = gsm48_create_mm_serv_rej(value);
-	if (!msg) {
-		LOGP(DMM, LOGL_ERROR, "Failed to allocate CM Service Reject.\n");
-		return -1;
-	}
-
-	DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
-
-	return gsm0808_submit_dtap(conn, msg, 0, 0);
-}
diff --git a/src/libbsc/gsm_04_80_utils.c b/src/libbsc/gsm_04_80_utils.c
deleted file mode 100644
index e0db81e..0000000
--- a/src/libbsc/gsm_04_80_utils.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/* OpenBSC utility functions for 3GPP TS 04.80 */
-
-/* (C) 2016 by sysmocom s.m.f.c. GmbH <info@sysmocom.de>
- *
- * 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/>.
- *
- */
-
-#include <osmocom/gsm/gsm0480.h>
-#include <openbsc/bsc_api.h>
-
-int bsc_send_ussd_notify(struct gsm_subscriber_connection *conn, int level,
-			 const char *text)
-{
-	struct msgb *msg = gsm0480_create_ussd_notify(level, text);
-	if (!msg)
-		return -1;
-	return gsm0808_submit_dtap(conn, msg, 0, 0);
-}
-
-int bsc_send_ussd_release_complete(struct gsm_subscriber_connection *conn)
-{
-	struct msgb *msg = gsm0480_create_ussd_release_complete();
-	if (!msg)
-		return -1;
-	return gsm0808_submit_dtap(conn, msg, 0, 0);
-}
diff --git a/src/libbsc/handover_decision.c b/src/libbsc/handover_decision.c
deleted file mode 100644
index 8d7e047..0000000
--- a/src/libbsc/handover_decision.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/* Handover Decision making for Inter-BTS (Intra-BSC) Handover.  This
- * only implements the handover algorithm/decision, but not execution
- * of it */
-
-/* (C) 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/>.
- *
- */
-
-#include <stdlib.h>
-#include <errno.h>
-
-#include <osmocom/core/msgb.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/meas_rep.h>
-#include <openbsc/signal.h>
-#include <osmocom/core/talloc.h>
-#include <openbsc/handover.h>
-#include <osmocom/gsm/gsm_utils.h>
-
-/* Get reference to a neighbor cell on a given BCCH ARFCN */
-static struct gsm_bts *gsm_bts_neighbor(const struct gsm_bts *bts,
-					uint16_t arfcn, uint8_t bsic)
-{
-	struct gsm_bts *neigh;
-	/* FIXME: use some better heuristics here to determine which cell
-	 * using this ARFCN really is closest to the target cell.  For
-	 * now we simply assume that each ARFCN will only be used by one
-	 * cell */
-
-	llist_for_each_entry(neigh, &bts->network->bts_list, list) {
-		/* FIXME: this is probably returning the same bts again!? */
-		if (neigh->c0->arfcn == arfcn &&
-		    neigh->bsic == bsic)
-			return neigh;
-	}
-
-	return NULL;
-}
-
-
-/* issue handover to a cell identified by ARFCN and BSIC */
-static int handover_to_arfcn_bsic(struct gsm_lchan *lchan,
-				  uint16_t arfcn, uint8_t bsic)
-{
-	struct gsm_bts *new_bts;
-
-	/* resolve the gsm_bts structure for the best neighbor */
-	new_bts = gsm_bts_neighbor(lchan->ts->trx->bts, arfcn, bsic);
-	if (!new_bts) {
-		LOGP(DHO, LOGL_NOTICE, "unable to determine neighbor BTS "
-		     "for ARFCN %u BSIC %u ?!?\n", arfcn, bsic);
-		return -EINVAL;
-	}
-
-	/* and actually try to handover to that cell */
-	return bsc_handover_start(lchan, new_bts);
-}
-
-/* did we get a RXLEV for a given cell in the given report? */
-static int rxlev_for_cell_in_rep(struct gsm_meas_rep *mr,
-				 uint16_t arfcn, uint8_t bsic)
-{
-	int i;
-
-	for (i = 0; i < mr->num_cell; i++) {
-		struct gsm_meas_rep_cell *mrc = &mr->cell[i];
-
-		/* search for matching report */
-		if (!(mrc->arfcn == arfcn && mrc->bsic == bsic))
-			continue;
-
-		mrc->flags |= MRC_F_PROCESSED;
-		return mrc->rxlev;
-	}
-	return -ENODEV;
-}
-
-/* obtain averaged rxlev for given neighbor */
-static int neigh_meas_avg(struct neigh_meas_proc *nmp, int window)
-{
-	unsigned int i, idx;
-	int avg = 0;
-
-	idx = calc_initial_idx(ARRAY_SIZE(nmp->rxlev),
-				nmp->rxlev_cnt % ARRAY_SIZE(nmp->rxlev),
-				window);
-
-	for (i = 0; i < window; i++) {
-		int j = (idx+i) % ARRAY_SIZE(nmp->rxlev);
-
-		avg += nmp->rxlev[j];
-	}
-
-	return avg / window;
-}
-
-/* find empty or evict bad neighbor */
-static struct neigh_meas_proc *find_evict_neigh(struct gsm_lchan *lchan)
-{
-	int j, worst = 999999;
-	struct neigh_meas_proc *nmp_worst = NULL;
-
-	/* first try to find an empty/unused slot */
-	for (j = 0; j < ARRAY_SIZE(lchan->neigh_meas); j++) {
-		struct neigh_meas_proc *nmp = &lchan->neigh_meas[j];
-		if (!nmp->arfcn)
-			return nmp;
-	}
-
-	/* no empty slot found. evict worst neighbor from list */
-	for (j = 0; j < ARRAY_SIZE(lchan->neigh_meas); j++) {
-		struct neigh_meas_proc *nmp = &lchan->neigh_meas[j];
-		int avg = neigh_meas_avg(nmp, MAX_WIN_NEIGH_AVG);
-		if (!nmp_worst || avg < worst) {
-			worst = avg;
-			nmp_worst = nmp;
-		}
-	}
-
-	return nmp_worst;
-}
-
-/* process neighbor cell measurement reports */
-static void process_meas_neigh(struct gsm_meas_rep *mr)
-{
-	int i, j, idx;
-
-	/* for each reported cell, try to update global state */
-	for (j = 0; j < ARRAY_SIZE(mr->lchan->neigh_meas); j++) {
-		struct neigh_meas_proc *nmp = &mr->lchan->neigh_meas[j];
-		unsigned int idx;
-		int rxlev;
-
-		/* skip unused entries */
-		if (!nmp->arfcn)
-			continue;
-
-		rxlev = rxlev_for_cell_in_rep(mr, nmp->arfcn, nmp->bsic);
-		idx = nmp->rxlev_cnt % ARRAY_SIZE(nmp->rxlev);
-		if (rxlev >= 0) {
-			nmp->rxlev[idx] = rxlev;
-			nmp->last_seen_nr = mr->nr;
-		} else
-			nmp->rxlev[idx] = 0;
-		nmp->rxlev_cnt++;
-	}
-
-	/* iterate over list of reported cells, check if we did not
-	 * process all of them */
-	for (i = 0; i < mr->num_cell; i++) {
-		struct gsm_meas_rep_cell *mrc = &mr->cell[i];
-		struct neigh_meas_proc *nmp;
-
-		if (mrc->flags & MRC_F_PROCESSED)
-			continue;
-
-		nmp = find_evict_neigh(mr->lchan);
-
-		nmp->arfcn = mrc->arfcn;
-		nmp->bsic = mrc->bsic;
-
-		idx = nmp->rxlev_cnt % ARRAY_SIZE(nmp->rxlev);
-		nmp->rxlev[idx] = mrc->rxlev;
-		nmp->rxlev_cnt++;
-		nmp->last_seen_nr = mr->nr;
-
-		mrc->flags |= MRC_F_PROCESSED;
-	}
-}
-
-/* attempt to do a handover */
-static int attempt_handover(struct gsm_meas_rep *mr)
-{
-	struct gsm_network *net = mr->lchan->ts->trx->bts->network;
-	struct neigh_meas_proc *best_cell = NULL;
-	unsigned int best_better_db = 0;
-	int i, rc;
-
-	/* find the best cell in this report that is at least RXLEV_HYST
-	 * better than the current serving cell */
-
-	for (i = 0; i < ARRAY_SIZE(mr->lchan->neigh_meas); i++) {
-		struct neigh_meas_proc *nmp = &mr->lchan->neigh_meas[i];
-		int avg, better;
-
-		/* skip empty slots */
-		if (nmp->arfcn == 0)
-			continue;
-
-		/* caculate average rxlev for this cell over the window */
-		avg = neigh_meas_avg(nmp, net->handover.win_rxlev_avg_neigh);
-
-		/* check if hysteresis is fulfilled */
-		if (avg < mr->dl.full.rx_lev + net->handover.pwr_hysteresis)
-			continue;
-
-		better = avg - mr->dl.full.rx_lev;
-		if (better > best_better_db) {
-			best_cell = nmp;
-			best_better_db = better;
-		}
-	}
-
-	if (!best_cell)
-		return 0;
-
-	LOGP(DHO, LOGL_INFO, "%s: Cell on ARFCN %u is better: ",
-		gsm_ts_name(mr->lchan->ts), best_cell->arfcn);
-	if (!net->handover.active) {
-		LOGPC(DHO, LOGL_INFO, "Skipping, Handover disabled\n");
-		return 0;
-	}
-
-	rc = handover_to_arfcn_bsic(mr->lchan, best_cell->arfcn, best_cell->bsic);
-	switch (rc) {
-	case 0:
-		LOGPC(DHO, LOGL_INFO, "Starting handover\n");
-		break;
-	case -ENOSPC:
-		LOGPC(DHO, LOGL_INFO, "No channel available\n");
-		break;
-	case -EBUSY:
-		LOGPC(DHO, LOGL_INFO, "Handover already active\n");
-		break;
-	default:
-		LOGPC(DHO, LOGL_ERROR, "Unknown error\n");
-	}
-	return rc;
-}
-
-/* process an already parsed measurement report and decide if we want to
- * attempt a handover */
-static int process_meas_rep(struct gsm_meas_rep *mr)
-{
-	struct gsm_network *net = mr->lchan->ts->trx->bts->network;
-	enum meas_rep_field dlev, dqual;
-	int av_rxlev;
-
-	/* we currently only do handover for TCH channels */
-	switch (mr->lchan->type) {
-	case GSM_LCHAN_TCH_F:
-	case GSM_LCHAN_TCH_H:
-		break;
-	default:
-		return 0;
-	}
-
-	if (mr->flags & MEAS_REP_F_DL_DTX) {
-		dlev = MEAS_REP_DL_RXLEV_SUB;
-		dqual = MEAS_REP_DL_RXQUAL_SUB;
-	} else {
-		dlev = MEAS_REP_DL_RXLEV_FULL;
-		dqual = MEAS_REP_DL_RXQUAL_FULL;
-	}
-
-	/* parse actual neighbor cell info */
-	if (mr->num_cell > 0 && mr->num_cell < 7)
-		process_meas_neigh(mr);
-
-	av_rxlev = get_meas_rep_avg(mr->lchan, dlev,
-				    net->handover.win_rxlev_avg);
-
-	/* Interference HO */
-	if (rxlev2dbm(av_rxlev) > -85 &&
-	    meas_rep_n_out_of_m_be(mr->lchan, dqual, 3, 4, 5))
-		return attempt_handover(mr);
-
-	/* Bad Quality */
-	if (meas_rep_n_out_of_m_be(mr->lchan, dqual, 3, 4, 5))
-		return attempt_handover(mr);
-
-	/* Low Level */
-	if (rxlev2dbm(av_rxlev) <= -110)
-		return attempt_handover(mr);
-
-	/* Distance */
-	if (mr->ms_l1.ta > net->handover.max_distance)
-		return attempt_handover(mr);
-
-	/* Power Budget AKA Better Cell */
-	if ((mr->nr % net->handover.pwr_interval) == 0)
-		return attempt_handover(mr);
-
-	return 0;
-
-}
-
-static int ho_dec_sig_cb(unsigned int subsys, unsigned int signal,
-			   void *handler_data, void *signal_data)
-{
-	struct lchan_signal_data *lchan_data;
-
-	if (subsys != SS_LCHAN)
-		return 0;
-
-	lchan_data = signal_data;
-	switch (signal) {
-	case S_LCHAN_MEAS_REP:
-		process_meas_rep(lchan_data->mr);
-		break;
-	}
-
-	return 0;
-}
-
-void on_dso_load_ho_dec(void)
-{
-	osmo_signal_register_handler(SS_LCHAN, ho_dec_sig_cb, NULL);
-}
diff --git a/src/libbsc/handover_logic.c b/src/libbsc/handover_logic.c
deleted file mode 100644
index 14566cf..0000000
--- a/src/libbsc/handover_logic.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/* Handover Logic for Inter-BTS (Intra-BSC) Handover.  This does not
- * actually implement the handover algorithm/decision, but executes a
- * handover decision */
-
-/* (C) 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/>.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-#include <netinet/in.h>
-
-#include <osmocom/core/msgb.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/chan_alloc.h>
-#include <openbsc/signal.h>
-#include <osmocom/core/talloc.h>
-#include <openbsc/transaction.h>
-#include <openbsc/trau_mux.h>
-#include <openbsc/vlr.h>
-
-struct bsc_handover {
-	struct llist_head list;
-
-	struct gsm_lchan *old_lchan;
-	struct gsm_lchan *new_lchan;
-
-	struct osmo_timer_list T3103;
-
-	uint8_t ho_ref;
-};
-
-static LLIST_HEAD(bsc_handovers);
-
-static void handover_free(struct bsc_handover *ho)
-{
-	osmo_timer_del(&ho->T3103);
-	llist_del(&ho->list);
-	talloc_free(ho);
-}
-
-static struct bsc_handover *bsc_ho_by_new_lchan(struct gsm_lchan *new_lchan)
-{
-	struct bsc_handover *ho;
-
-	llist_for_each_entry(ho, &bsc_handovers, list) {
-		if (ho->new_lchan == new_lchan)
-			return ho;
-	}
-
-	return NULL;
-}
-
-static struct bsc_handover *bsc_ho_by_old_lchan(struct gsm_lchan *old_lchan)
-{
-	struct bsc_handover *ho;
-
-	llist_for_each_entry(ho, &bsc_handovers, list) {
-		if (ho->old_lchan == old_lchan)
-			return ho;
-	}
-
-	return NULL;
-}
-
-/*! \brief Hand over the specified logical channel to the specified new BTS.
- * This is the main entry point for the actual handover algorithm, after the
- * decision whether to initiate HO to a specific BTS. */
-int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts)
-{
-	struct gsm_lchan *new_lchan;
-	struct bsc_handover *ho;
-	static uint8_t ho_ref;
-	int rc;
-
-	/* don't attempt multiple handovers for the same lchan at
-	 * the same time */
-	if (bsc_ho_by_old_lchan(old_lchan))
-		return -EBUSY;
-
-	DEBUGP(DHO, "Beginning with handover operation"
-	       "(old_lchan on BTS %u, new BTS %u) ...\n",
-		old_lchan->ts->trx->bts->nr, bts->nr);
-
-	rate_ctr_inc(&bts->network->bsc_ctrs->ctr[BSC_CTR_HANDOVER_ATTEMPTED]);
-
-	if (!old_lchan->conn) {
-		LOGP(DHO, LOGL_ERROR, "Old lchan lacks connection data.\n");
-		return -ENOSPC;
-	}
-
-	new_lchan = lchan_alloc(bts, old_lchan->type, 0);
-	if (!new_lchan) {
-		LOGP(DHO, LOGL_NOTICE, "No free channel\n");
-		rate_ctr_inc(&bts->network->bsc_ctrs->ctr[BSC_CTR_HANDOVER_NO_CHANNEL]);
-		return -ENOSPC;
-	}
-
-	ho = talloc_zero(tall_bsc_ctx, struct bsc_handover);
-	if (!ho) {
-		LOGP(DHO, LOGL_FATAL, "Out of Memory\n");
-		lchan_free(new_lchan);
-		return -ENOMEM;
-	}
-	ho->old_lchan = old_lchan;
-	ho->new_lchan = new_lchan;
-	ho->ho_ref = ho_ref++;
-
-	/* copy some parameters from old lchan */
-	memcpy(&new_lchan->encr, &old_lchan->encr, sizeof(new_lchan->encr));
-	new_lchan->ms_power = old_lchan->ms_power;
-	new_lchan->bs_power = old_lchan->bs_power;
-	new_lchan->rsl_cmode = old_lchan->rsl_cmode;
-	new_lchan->tch_mode = old_lchan->tch_mode;
-	memcpy(&new_lchan->mr_ms_lv, &old_lchan->mr_ms_lv, ARRAY_SIZE(new_lchan->mr_ms_lv));
-	memcpy(&new_lchan->mr_bts_lv, &old_lchan->mr_bts_lv, ARRAY_SIZE(new_lchan->mr_bts_lv));
-
-	new_lchan->conn = old_lchan->conn;
-	new_lchan->conn->ho_lchan = new_lchan;
-
-	/* FIXME: do we have a better idea of the timing advance? */
-	rc = rsl_chan_activate_lchan(new_lchan, RSL_ACT_INTER_ASYNC, ho->ho_ref);
-	if (rc < 0) {
-		LOGP(DHO, LOGL_ERROR, "could not activate channel\n");
-		new_lchan->conn->ho_lchan = NULL;
-		new_lchan->conn = NULL;
-		talloc_free(ho);
-		lchan_free(new_lchan);
-		return rc;
-	}
-
-	rsl_lchan_set_state(new_lchan, LCHAN_S_ACT_REQ);
-	llist_add(&ho->list, &bsc_handovers);
-	/* we continue in the SS_LCHAN handler / ho_chan_activ_ack */
-
-	return 0;
-}
-
-void bsc_clear_handover(struct gsm_subscriber_connection *conn, int free_lchan)
-{
-	struct bsc_handover *ho;
-
-	ho = bsc_ho_by_new_lchan(conn->ho_lchan);
-
-
-	if (!ho && conn->ho_lchan)
-		LOGP(DHO, LOGL_ERROR, "BUG: We lost some state.\n");
-
-	if (!ho) {
-		LOGP(DHO, LOGL_ERROR, "unable to find HO record\n");
-		return;
-	}
-
-	conn->ho_lchan->conn = NULL;
-	conn->ho_lchan = NULL;
-
-	if (free_lchan)
-		lchan_release(ho->new_lchan, 0, RSL_REL_LOCAL_END);
-
-	handover_free(ho);
-}
-
-/* T3103 expired: Handover has failed without HO COMPLETE or HO FAIL */
-static void ho_T3103_cb(void *_ho)
-{
-	struct bsc_handover *ho = _ho;
-	struct gsm_network *net = ho->new_lchan->ts->trx->bts->network;
-
-	DEBUGP(DHO, "HO T3103 expired\n");
-	rate_ctr_inc(&net->bsc_ctrs->ctr[BSC_CTR_HANDOVER_TIMEOUT]);
-
-	ho->new_lchan->conn->ho_lchan = NULL;
-	ho->new_lchan->conn = NULL;
-	lchan_release(ho->new_lchan, 0, RSL_REL_LOCAL_END);
-	handover_free(ho);
-}
-
-/* RSL has acknowledged activation of the new lchan */
-static int ho_chan_activ_ack(struct gsm_lchan *new_lchan)
-{
-	struct bsc_handover *ho;
-
-	/* we need to check if this channel activation is related to
-	 * a handover at all (and if, which particular handover) */
-	ho = bsc_ho_by_new_lchan(new_lchan);
-	if (!ho)
-		return -ENODEV;
-
-	DEBUGP(DHO, "handover activate ack, send HO Command\n");
-
-	/* we can now send the 04.08 HANDOVER COMMAND to the MS
-	 * using the old lchan */
-
-	gsm48_send_ho_cmd(ho->old_lchan, new_lchan, 0, ho->ho_ref);
-
-	/* start T3103.  We can continue either with T3103 expiration,
-	 * 04.08 HANDOVER COMPLETE or 04.08 HANDOVER FAIL */
-	osmo_timer_setup(&ho->T3103, ho_T3103_cb, ho);
-	osmo_timer_schedule(&ho->T3103, 10, 0);
-
-	/* create a RTP connection */
-	if (is_ipaccess_bts(new_lchan->ts->trx->bts))
-		rsl_ipacc_crcx(new_lchan);
-
-	return 0;
-}
-
-/* RSL has not acknowledged activation of the new lchan */
-static int ho_chan_activ_nack(struct gsm_lchan *new_lchan)
-{
-	struct bsc_handover *ho;
-
-	ho = bsc_ho_by_new_lchan(new_lchan);
-	if (!ho) {
-		LOGP(DHO, LOGL_INFO, "ACT NACK: unable to find HO record\n");
-		return -ENODEV;
-	}
-
-	new_lchan->conn->ho_lchan = NULL;
-	new_lchan->conn = NULL;
-	handover_free(ho);
-
-	/* FIXME: maybe we should try to allocate a new LCHAN here? */
-
-	return 0;
-}
-
-/* GSM 04.08 HANDOVER COMPLETE has been received on new channel */
-static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan)
-{
-	struct gsm_network *net;
-	struct bsc_handover *ho;
-
-	ho = bsc_ho_by_new_lchan(new_lchan);
-	if (!ho) {
-		LOGP(DHO, LOGL_ERROR, "unable to find HO record\n");
-		return -ENODEV;
-	}
-
-	net = new_lchan->ts->trx->bts->network;
-	LOGP(DHO, LOGL_INFO, "Subscriber %s HO from BTS %u->%u on ARFCN "
-	     "%u->%u\n", vlr_subscr_name(ho->old_lchan->conn->vsub),
-	     ho->old_lchan->ts->trx->bts->nr, new_lchan->ts->trx->bts->nr,
-	     ho->old_lchan->ts->trx->arfcn, new_lchan->ts->trx->arfcn);
-
-	rate_ctr_inc(&net->bsc_ctrs->ctr[BSC_CTR_HANDOVER_COMPLETED]);
-
-	osmo_timer_del(&ho->T3103);
-
-	/* switch TRAU muxer for E1 based BTS from one channel to another */
-	if (is_e1_bts(new_lchan->conn->bts))
-		switch_trau_mux(ho->old_lchan, new_lchan);
-
-	/* Replace the ho lchan with the primary one */
-	if (ho->old_lchan != new_lchan->conn->lchan)
-		LOGP(DHO, LOGL_ERROR, "Primary lchan changed during handover.\n");
-
-	if (new_lchan != new_lchan->conn->ho_lchan)
-		LOGP(DHO, LOGL_ERROR, "Handover channel changed during this handover.\n");
-
-	new_lchan->conn->ho_lchan = NULL;
-	new_lchan->conn->lchan = new_lchan;
-	new_lchan->conn->bts = new_lchan->ts->trx->bts;
-	ho->old_lchan->conn = NULL;
-
-	lchan_release(ho->old_lchan, 0, RSL_REL_LOCAL_END);
-
-	handover_free(ho);
-	return 0;
-}
-
-/* GSM 04.08 HANDOVER FAIL has been received */
-static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan)
-{
-	struct gsm_network *net = old_lchan->ts->trx->bts->network;
-	struct bsc_handover *ho;
-	struct gsm_lchan *new_lchan;
-
-	ho = bsc_ho_by_old_lchan(old_lchan);
-	if (!ho) {
-		LOGP(DHO, LOGL_ERROR, "unable to find HO record\n");
-		return -ENODEV;
-	}
-
-	rate_ctr_inc(&net->bsc_ctrs->ctr[BSC_CTR_HANDOVER_FAILED]);
-
-	new_lchan = ho->new_lchan;
-
-	/* release the channel and forget about it */
-	ho->new_lchan->conn->ho_lchan = NULL;
-	ho->new_lchan->conn = NULL;
-	handover_free(ho);
-
-	lchan_release(new_lchan, 0, RSL_REL_LOCAL_END);
-
-
-	return 0;
-}
-
-/* GSM 08.58 HANDOVER DETECT has been received */
-static int ho_rsl_detect(struct gsm_lchan *new_lchan)
-{
-	struct bsc_handover *ho;
-
-	ho = bsc_ho_by_new_lchan(new_lchan);
-	if (!ho) {
-		LOGP(DHO, LOGL_ERROR, "unable to find HO record\n");
-		return -ENODEV;
-	}
-
-	/* FIXME: do we actually want to do something here ? */
-
-	return 0;
-}
-
-static int ho_logic_sig_cb(unsigned int subsys, unsigned int signal,
-			   void *handler_data, void *signal_data)
-{
-	struct lchan_signal_data *lchan_data;
-	struct gsm_lchan *lchan;
-
-	lchan_data = signal_data;
-	switch (subsys) {
-	case SS_LCHAN:
-		lchan = lchan_data->lchan;
-		switch (signal) {
-		case S_LCHAN_ACTIVATE_ACK:
-			return ho_chan_activ_ack(lchan);
-		case S_LCHAN_ACTIVATE_NACK:
-			return ho_chan_activ_nack(lchan);
-		case S_LCHAN_HANDOVER_DETECT:
-			return ho_rsl_detect(lchan);
-		case S_LCHAN_HANDOVER_COMPL:
-			return ho_gsm48_ho_compl(lchan);
-		case S_LCHAN_HANDOVER_FAIL:
-			return ho_gsm48_ho_fail(lchan);
-		}
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-struct gsm_lchan *bsc_handover_pending(struct gsm_lchan *new_lchan)
-{
-	struct bsc_handover *ho;
-	ho = bsc_ho_by_new_lchan(new_lchan);
-	if (!ho)
-		return NULL;
-	return ho->old_lchan;
-}
-
-static __attribute__((constructor)) void on_dso_load_ho_logic(void)
-{
-	osmo_signal_register_handler(SS_LCHAN, ho_logic_sig_cb, NULL);
-}
diff --git a/src/libbsc/meas_proc.c b/src/libbsc/meas_proc.c
deleted file mode 100644
index 5b97e74..0000000
--- a/src/libbsc/meas_proc.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* Measurement Processing */
-
-/* (C) 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/>.
- *
- */
-
-#include <stdlib.h>
-#include <errno.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/msgb.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/meas_rep.h>
-#include <openbsc/signal.h>
-
-/* process an already parsed measurement report */
-static int process_meas_rep(struct gsm_meas_rep *mr)
-{
-	struct gsm_meas_rep_cell *mr_cell = NULL;
-	unsigned int best_better_db;
-	int i;
-
-	/* FIXME: implement actual averaging over multiple measurement
-	 * reports */
-
-	/* find the best cell in this report that is at least RXLEV_HYST
-	 * better than the current serving cell */
-	for (i = 0; i < mr->num_cell; i++) {
-		unsigned int better;
-		if (mr->cell[i].rxlev < mr->dl.full.rx_lev + RXLEV_HYST)
-			continue;
-
-		better = mr->cell[i].rxlev - mr->dl.full.rx_lev;
-		if (better > best_better_db) {
-			mr_cell = &mr->cell[i];
-			best_better_db = better;
-		}
-	}
-
-	if (mr_cell)
-		return handover_to_arfcn_bsic(mr->lchan, mr_cell->arfcn,
-						mr_cell->bsic);
-	return 0;
-}
-
-static int meas_proc_sig_cb(unsigned int subsys, unsigned int signal,
-			   void *handler_data, void *signal_data)
-{
-	struct gsm_lchan *lchan;
-	struct gsm_meas_rep *mr;
-
-	if (subsys != SS_LCHAN)
-		return 0;
-
-	switch (signal) {
-	case S_LCHAN_MEAS_REP:
-		mr = signal_data;
-		process_meas_rep(mr);
-		break;
-	}
-
-	return 0;
-}
-
-static __attribute__((constructor)) void on_dso_load_meas(void)
-{
-	osmo_signal_register_handler(SS_LCHAN, meas_proc_sig_cb, NULL);
-}
diff --git a/src/libbsc/meas_rep.c b/src/libbsc/meas_rep.c
deleted file mode 100644
index 808103d..0000000
--- a/src/libbsc/meas_rep.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Measurement Report Processing */
-
-/* (C) 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/>.
- *
- */
-
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/meas_rep.h>
-
-static int get_field(const struct gsm_meas_rep *rep,
-		     enum meas_rep_field field)
-{
-	switch (field) {
-	case MEAS_REP_DL_RXLEV_FULL:
-		return rep->dl.full.rx_lev;
-	case MEAS_REP_DL_RXLEV_SUB:
-		return rep->dl.sub.rx_lev;
-	case MEAS_REP_DL_RXQUAL_FULL:
-		return rep->dl.full.rx_qual;
-	case MEAS_REP_DL_RXQUAL_SUB:
-		return rep->dl.sub.rx_qual;
-	case MEAS_REP_UL_RXLEV_FULL:
-		return rep->ul.full.rx_lev;
-	case MEAS_REP_UL_RXLEV_SUB:
-		return rep->ul.sub.rx_lev;
-	case MEAS_REP_UL_RXQUAL_FULL:
-		return rep->ul.full.rx_qual;
-	case MEAS_REP_UL_RXQUAL_SUB:
-		return rep->ul.sub.rx_qual;
-	}
-
-	return 0;
-}
-
-
-unsigned int calc_initial_idx(unsigned int array_size,
-			      unsigned int meas_rep_idx,
-			      unsigned int num_values)
-{
-	int offs, idx;
-
-	/* from which element do we need to start if we're interested
-	 * in an average of 'num' elements */
-	offs = meas_rep_idx - num_values;
-
-	if (offs < 0)
-		idx = array_size + offs;
-	else
-		idx = offs;
-
-	return idx;
-}
-
-/* obtain an average over the last 'num' fields in the meas reps */
-int get_meas_rep_avg(const struct gsm_lchan *lchan,
-		     enum meas_rep_field field, unsigned int num)
-{
-	unsigned int i, idx;
-	int avg = 0;
-
-	if (num < 1)
-		return 0;
-
-	idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep),
-				lchan->meas_rep_idx, num);
-
-	for (i = 0; i < num; i++) {
-		int j = (idx+i) % ARRAY_SIZE(lchan->meas_rep);
-
-		avg += get_field(&lchan->meas_rep[j], field);
-	}
-
-	return avg / num;
-}
-
-/* Check if N out of M last values for FIELD are >= bd */
-int meas_rep_n_out_of_m_be(const struct gsm_lchan *lchan,
-			enum meas_rep_field field,
-			unsigned int n, unsigned int m, int be)
-{
-	unsigned int i, idx;
-	int count = 0;
-
-	idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep),
-				lchan->meas_rep_idx, m);
-
-	for (i = 0; i < m; i++) {
-		int j = (idx + i) % ARRAY_SIZE(lchan->meas_rep);
-		int val = get_field(&lchan->meas_rep[j], field);
-
-		if (val >= be)
-			count++;
-
-		if (count >= n)
-			return 1;
-	}
-
-	return 0;
-}
diff --git a/src/libbsc/net_init.c b/src/libbsc/net_init.c
deleted file mode 100644
index 9d54319..0000000
--- a/src/libbsc/net_init.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/* (C) 2008-2010 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/>.
- *
- */
-
-#include <openbsc/common_cs.h>
-#include <openbsc/osmo_bsc.h>
-#include <openbsc/bsc_msc_data.h>
-
-struct gsm_network *bsc_network_init(void *ctx,
-				     uint16_t country_code,
-				     uint16_t network_code,
-				     mncc_recv_cb_t mncc_recv)
-{
-	struct gsm_network *net;
-
-	net = gsm_network_init(ctx, country_code, network_code, mncc_recv);
-
-	net->bsc_data = talloc_zero(net, struct osmo_bsc_data);
-	if (!net->bsc_data) {
-		talloc_free(net);
-		return NULL;
-	}
-
-	/* Init back pointer */
-	net->bsc_data->auto_off_timeout = -1;
-	net->bsc_data->network = net;
-	INIT_LLIST_HEAD(&net->bsc_data->mscs);
-
-	net->num_bts = 0;
-	net->reject_cause = GSM48_REJECT_ROAMING_NOT_ALLOWED;
-	net->T3101 = GSM_T3101_DEFAULT;
-	net->T3103 = GSM_T3103_DEFAULT;
-	net->T3105 = GSM_T3105_DEFAULT;
-	net->T3107 = GSM_T3107_DEFAULT;
-	net->T3109 = GSM_T3109_DEFAULT;
-	net->T3111 = GSM_T3111_DEFAULT;
-	net->T3113 = GSM_T3113_DEFAULT;
-	net->T3115 = GSM_T3115_DEFAULT;
-	net->T3117 = GSM_T3117_DEFAULT;
-	net->T3119 = GSM_T3119_DEFAULT;
-	net->T3122 = GSM_T3122_DEFAULT;
-	net->T3141 = GSM_T3141_DEFAULT;
-
-	/* default set of handover parameters */
-	net->handover.win_rxlev_avg = 10;
-	net->handover.win_rxqual_avg = 1;
-	net->handover.win_rxlev_avg_neigh = 10;
-	net->handover.pwr_interval = 6;
-	net->handover.pwr_hysteresis = 3;
-	net->handover.max_distance = 9999;
-
-	INIT_LLIST_HEAD(&net->bts_list);
-
-	/* init statistics */
-	net->bsc_ctrs = rate_ctr_group_alloc(net, &bsc_ctrg_desc, 0);
-	if (!net->bsc_ctrs) {
-		talloc_free(net);
-		return NULL;
-	}
-
-	gsm_net_update_ctype(net);
-
-	return net;
-}
-
diff --git a/src/libbsc/paging.c b/src/libbsc/paging.c
deleted file mode 100644
index e19c2d1..0000000
--- a/src/libbsc/paging.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/* Paging helper and manager.... */
-/* (C) 2009,2013 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/>.
- *
- */
-
-/*
- * Relevant specs:
- *     12.21:
- *       - 9.4.12 for CCCH Local Threshold
- *
- *     05.58:
- *       - 8.5.2 CCCH Load indication
- *       - 9.3.15 Paging Load
- *
- * Approach:
- *       - Send paging command to subscriber
- *       - On Channel Request we will remember the reason
- *       - After the ACK we will request the identity
- *	 - Then we will send assign the gsm_subscriber and
- *	 - and call a callback
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/gsm/gsm48.h>
-#include <osmocom/gsm/gsm0502.h>
-
-#include <openbsc/bsc_subscriber.h>
-#include <openbsc/paging.h>
-#include <openbsc/debug.h>
-#include <openbsc/signal.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/chan_alloc.h>
-#include <openbsc/bsc_api.h>
-#include <openbsc/vlr.h>
-
-void *tall_paging_ctx;
-
-#define PAGING_TIMER 0, 500000
-
-/*
- * TODO MSCSPLIT: the paging in libbsc is closely tied to MSC land in that the
- * MSC realm callback functions used to be invoked from the BSC/BTS level. So
- * this entire file needs to be rewired for use with an A interface.
- */
-
-/*
- * Kill one paging request update the internal list...
- */
-static void paging_remove_request(struct gsm_bts_paging_state *paging_bts,
-				  struct gsm_paging_request *to_be_deleted)
-{
-	osmo_timer_del(&to_be_deleted->T3113);
-	llist_del(&to_be_deleted->entry);
-	bsc_subscr_put(to_be_deleted->bsub);
-	talloc_free(to_be_deleted);
-}
-
-static void page_ms(struct gsm_paging_request *request)
-{
-	uint8_t mi[128];
-	unsigned int mi_len;
-	unsigned int page_group;
-	struct gsm_bts *bts = request->bts;
-
-	/* the bts is down.. we will just wait for the paging to expire */
-	if (!bts->oml_link)
-		return;
-
-	log_set_context(LOG_CTX_BSC_SUBSCR, request->bsub);
-
-	LOGP(DPAG, LOGL_INFO, "Going to send paging commands: imsi: %s tmsi: "
-	     "0x%08x for ch. type %d (attempt %d)\n", request->bsub->imsi,
-	     request->bsub->tmsi, request->chan_type, request->attempts);
-
-	if (request->bsub->tmsi == GSM_RESERVED_TMSI)
-		mi_len = gsm48_generate_mid_from_imsi(mi, request->bsub->imsi);
-	else
-		mi_len = gsm48_generate_mid_from_tmsi(mi, request->bsub->tmsi);
-
-	page_group = gsm0502_calc_paging_group(&bts->si_common.chan_desc,
-					       str_to_imsi(request->bsub->imsi));
-	gsm0808_page(bts, page_group, mi_len, mi, request->chan_type);
-	log_set_context(LOG_CTX_BSC_SUBSCR, NULL);
-}
-
-static void paging_schedule_if_needed(struct gsm_bts_paging_state *paging_bts)
-{
-	if (llist_empty(&paging_bts->pending_requests))
-		return;
-
-	if (!osmo_timer_pending(&paging_bts->work_timer))
-		osmo_timer_schedule(&paging_bts->work_timer, PAGING_TIMER);
-}
-
-
-static void paging_handle_pending_requests(struct gsm_bts_paging_state *paging_bts);
-static void paging_give_credit(void *data)
-{
-	struct gsm_bts_paging_state *paging_bts = data;
-
-	LOGP(DPAG, LOGL_NOTICE, "No slots available on bts nr %d\n", paging_bts->bts->nr);
-	paging_bts->available_slots = 20;
-	paging_handle_pending_requests(paging_bts);
-}
-
-static int can_send_pag_req(struct gsm_bts *bts, int rsl_type)
-{
-	struct pchan_load pl;
-	int count;
-
-	memset(&pl, 0, sizeof(pl));
-	bts_chan_load(&pl, bts);
-
-	switch (rsl_type) {
-	case RSL_CHANNEED_TCH_F:
-	case RSL_CHANNEED_TCH_ForH:
-		goto count_tch;
-		break;
-	case RSL_CHANNEED_SDCCH:
-		goto count_sdcch;
-		break;
-	case RSL_CHANNEED_ANY:
-	default:
-		if (bts->network->pag_any_tch)
-			goto count_tch;
-		else
-			goto count_sdcch;
-		break;
-	}
-
-	return 0;
-
-	/* could available SDCCH */
-count_sdcch:
-	count = 0;
-	count += pl.pchan[GSM_PCHAN_SDCCH8_SACCH8C].total
-			- pl.pchan[GSM_PCHAN_SDCCH8_SACCH8C].used;
-	count += pl.pchan[GSM_PCHAN_CCCH_SDCCH4].total
-			- pl.pchan[GSM_PCHAN_CCCH_SDCCH4].used;
-	return bts->paging.free_chans_need > count;
-
-count_tch:
-	count = 0;
-	count += pl.pchan[GSM_PCHAN_TCH_F].total
-			- pl.pchan[GSM_PCHAN_TCH_F].used;
-	if (bts->network->neci)
-		count += pl.pchan[GSM_PCHAN_TCH_H].total
-				- pl.pchan[GSM_PCHAN_TCH_H].used;
-	return bts->paging.free_chans_need > count;
-}
-
-/*
- * This is kicked by the periodic PAGING LOAD Indicator
- * coming from abis_rsl.c
- *
- * We attempt to iterate once over the list of items but
- * only upto available_slots.
- */
-static void paging_handle_pending_requests(struct gsm_bts_paging_state *paging_bts)
-{
-	struct gsm_paging_request *request = NULL;
-
-	/*
-	 * Determine if the pending_requests list is empty and
-	 * return then.
-	 */
-	if (llist_empty(&paging_bts->pending_requests)) {
-		/* since the list is empty, no need to reschedule the timer */
-		return;
-	}
-
-	/*
-	 * In case the BTS does not provide us with load indication and we
-	 * ran out of slots, call an autofill routine. It might be that the
-	 * BTS did not like our paging messages and then we have counted down
-	 * to zero and we do not get any messages.
-	 */
-	if (paging_bts->available_slots == 0) {
-		osmo_timer_setup(&paging_bts->credit_timer, paging_give_credit,
-				 paging_bts);
-		osmo_timer_schedule(&paging_bts->credit_timer, 5, 0);
-		return;
-	}
-
-	request = llist_entry(paging_bts->pending_requests.next,
-			      struct gsm_paging_request, entry);
-
-	/* we need to determine the number of free channels */
-	if (paging_bts->free_chans_need != -1) {
-		if (can_send_pag_req(request->bts, request->chan_type) != 0)
-			goto skip_paging;
-	}
-
-	/* handle the paging request now */
-	page_ms(request);
-	paging_bts->available_slots--;
-	request->attempts++;
-
-	/* take the current and add it to the back */
-	llist_del(&request->entry);
-	llist_add_tail(&request->entry, &paging_bts->pending_requests);
-
-skip_paging:
-	osmo_timer_schedule(&paging_bts->work_timer, PAGING_TIMER);
-}
-
-static void paging_worker(void *data)
-{
-	struct gsm_bts_paging_state *paging_bts = data;
-
-	paging_handle_pending_requests(paging_bts);
-}
-
-static void paging_init_if_needed(struct gsm_bts *bts)
-{
-	if (bts->paging.bts)
-		return;
-
-	bts->paging.bts = bts;
-	INIT_LLIST_HEAD(&bts->paging.pending_requests);
-	osmo_timer_setup(&bts->paging.work_timer, paging_worker,
-			 &bts->paging);
-
-	/* Large number, until we get a proper message */
-	bts->paging.available_slots = 20;
-}
-
-static int paging_pending_request(struct gsm_bts_paging_state *bts,
-				  struct bsc_subscr *bsub)
-{
-	struct gsm_paging_request *req;
-
-	llist_for_each_entry(req, &bts->pending_requests, entry) {
-		if (bsub == req->bsub)
-			return 1;
-	}
-
-	return 0;	
-}
-
-static void paging_T3113_expired(void *data)
-{
-	struct gsm_paging_request *req = (struct gsm_paging_request *)data;
-	void *cbfn_param;
-	gsm_cbfn *cbfn;
-	int msg;
-
-	log_set_context(LOG_CTX_BSC_SUBSCR, req->bsub);
-
-	LOGP(DPAG, LOGL_INFO, "T3113 expired for request %p (%s)\n",
-	     req, bsc_subscr_name(req->bsub));
-
-	/* must be destroyed before calling cbfn, to prevent double free */
-	rate_ctr_inc(&req->bts->network->bsc_ctrs->ctr[BSC_CTR_PAGING_EXPIRED]);
-	cbfn_param = req->cbfn_param;
-	cbfn = req->cbfn;
-
-	/* did we ever manage to page the subscriber */
-	msg = req->attempts > 0 ? GSM_PAGING_EXPIRED : GSM_PAGING_BUSY;
-
-	/* destroy it now. Do not access req afterwards */
-	paging_remove_request(&req->bts->paging, req);
-
-	if (cbfn)
-		cbfn(GSM_HOOK_RR_PAGING, msg, NULL, NULL,
-			  cbfn_param);
-
-}
-
-static int _paging_request(struct gsm_bts *bts, struct bsc_subscr *bsub,
-			   int type, gsm_cbfn *cbfn, void *data)
-{
-	struct gsm_bts_paging_state *bts_entry = &bts->paging;
-	struct gsm_paging_request *req;
-
-	if (paging_pending_request(bts_entry, bsub)) {
-		LOGP(DPAG, LOGL_INFO, "Paging request already pending for %s\n",
-		     bsc_subscr_name(bsub));
-		return -EEXIST;
-	}
-
-	LOGP(DPAG, LOGL_DEBUG, "Start paging of subscriber %s on bts %d.\n",
-	     bsc_subscr_name(bsub), bts->nr);
-	req = talloc_zero(tall_paging_ctx, struct gsm_paging_request);
-	req->bsub = bsc_subscr_get(bsub);
-	req->bts = bts;
-	req->chan_type = type;
-	req->cbfn = cbfn;
-	req->cbfn_param = data;
-	osmo_timer_setup(&req->T3113, paging_T3113_expired, req);
-	osmo_timer_schedule(&req->T3113, bts->network->T3113, 0);
-	llist_add_tail(&req->entry, &bts_entry->pending_requests);
-	paging_schedule_if_needed(bts_entry);
-
-	return 0;
-}
-
-int paging_request_bts(struct gsm_bts *bts, struct bsc_subscr *bsub,
-		       int type, gsm_cbfn *cbfn, void *data)
-{
-	int rc;
-
-	/* skip all currently inactive TRX */
-	if (!trx_is_usable(bts->c0))
-		return 0;
-
-	/* maybe it is the first time we use it */
-	paging_init_if_needed(bts);
-
-	/* Trigger paging, pass any error to the caller */
-	rc = _paging_request(bts, bsub, type, cbfn, data);
-	if (rc < 0)
-		return rc;
-	return 1;
-}
-
-int paging_request(struct gsm_network *network, struct bsc_subscr *bsub,
-		   int type, gsm_cbfn *cbfn, void *data)
-{
-	struct gsm_bts *bts = NULL;
-	int num_pages = 0;
-
-	rate_ctr_inc(&network->bsc_ctrs->ctr[BSC_CTR_PAGING_ATTEMPTED]);
-
-	/* start paging subscriber on all BTS within Location Area */
-	do {
-		int rc;
-
-		bts = gsm_bts_by_lac(network, bsub->lac, bts);
-		if (!bts)
-			break;
-
-		rc = paging_request_bts(bts, bsub, type, cbfn, data);
-		if (rc < 0) {
-			paging_request_stop(&network->bts_list, NULL, bsub,
-					    NULL, NULL);
-			return rc;
-		}
-		num_pages += rc;
-	} while (1);
-
-	if (num_pages == 0)
-		rate_ctr_inc(&network->bsc_ctrs->ctr[BSC_CTR_PAGING_DETACHED]);
-
-	return num_pages;
-}
-
-
-/* we consciously ignore the type of the request here */
-static void _paging_request_stop(struct gsm_bts *bts, struct bsc_subscr *bsub,
-				 struct gsm_subscriber_connection *conn,
-				 struct msgb *msg)
-{
-	struct gsm_bts_paging_state *bts_entry = &bts->paging;
-	struct gsm_paging_request *req, *req2;
-
-	paging_init_if_needed(bts);
-
-	llist_for_each_entry_safe(req, req2, &bts_entry->pending_requests,
-				  entry) {
-		if (req->bsub == bsub) {
-			gsm_cbfn *cbfn = req->cbfn;
-			void *param = req->cbfn_param;
-
-			/* now give up the data structure */
-			paging_remove_request(&bts->paging, req);
-			req = NULL;
-
-			if (conn && cbfn) {
-				LOGP(DPAG, LOGL_DEBUG, "Stop paging %s on bts %d, calling cbfn.\n", bsub->imsi, bts->nr);
-				cbfn(GSM_HOOK_RR_PAGING, GSM_PAGING_SUCCEEDED,
-				     msg, conn, param);
-			} else
-				LOGP(DPAG, LOGL_DEBUG, "Stop paging %s on bts %d silently.\n", bsub->imsi, bts->nr);
-			break;
-		}
-	}
-}
-
-/* Stop paging on all other bts' */
-void paging_request_stop(struct llist_head *bts_list,
-			 struct gsm_bts *_bts, struct bsc_subscr *bsub,
-			 struct gsm_subscriber_connection *conn,
-			 struct msgb *msg)
-{
-	struct gsm_bts *bts;
-
-	log_set_context(LOG_CTX_BSC_SUBSCR, bsub);
-
-	/* Stop this first and dispatch the request */
-	if (_bts)
-		_paging_request_stop(_bts, bsub, conn, msg);
-
-	/* Make sure to cancel this everywhere else */
-	llist_for_each_entry(bts, bts_list, list) {
-		/* Sort of an optimization. */
-		if (bts == _bts)
-			continue;
-		_paging_request_stop(bts, bsub, NULL, NULL);
-	}
-}
-
-void paging_update_buffer_space(struct gsm_bts *bts, uint16_t free_slots)
-{
-	paging_init_if_needed(bts);
-
-	osmo_timer_del(&bts->paging.credit_timer);
-	bts->paging.available_slots = free_slots;
-	paging_schedule_if_needed(&bts->paging);
-}
-
-unsigned int paging_pending_requests_nr(struct gsm_bts *bts)
-{
-	unsigned int requests = 0;
-	struct gsm_paging_request *req;
-
-	paging_init_if_needed(bts);
-
-	llist_for_each_entry(req, &bts->paging.pending_requests, entry)
-		++requests;
-
-	return requests;
-}
-
-/**
- * Find any paging data for the given subscriber at the given BTS.
- */
-void *paging_get_data(struct gsm_bts *bts, struct bsc_subscr *bsub)
-{
-	struct gsm_paging_request *req;
-
-	llist_for_each_entry(req, &bts->paging.pending_requests, entry)
-		if (req->bsub == bsub)
-			return req->cbfn_param;
-
-	return NULL;
-}
diff --git a/src/libbsc/pcu_sock.c b/src/libbsc/pcu_sock.c
deleted file mode 100644
index 98e12fa..0000000
--- a/src/libbsc/pcu_sock.c
+++ /dev/null
@@ -1,742 +0,0 @@
-/* pcu_sock.c: Connect from PCU via unix domain socket */
-
-/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009-2012 by Andreas Eversberg <jolly@eversberg.eu>
- * (C) 2012 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 General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * 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.
- *
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/socket.h>
-#include <osmocom/core/logging.h>
-#include <osmocom/gsm/l1sap.h>
-#include <osmocom/gsm/gsm0502.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/pcu_if.h>
-#include <openbsc/pcuif_proto.h>
-#include <openbsc/signal.h>
-#include <openbsc/debug.h>
-#include <openbsc/abis_rsl.h>
-
-static int pcu_sock_send(struct gsm_bts *bts, struct msgb *msg);
-uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx);
-int pcu_direct = 1;
-
-static const char *sapi_string[] = {
-	[PCU_IF_SAPI_RACH] =	"RACH",
-	[PCU_IF_SAPI_AGCH] =	"AGCH",
-	[PCU_IF_SAPI_PCH] =	"PCH",
-	[PCU_IF_SAPI_BCCH] =	"BCCH",
-	[PCU_IF_SAPI_PDTCH] =	"PDTCH",
-	[PCU_IF_SAPI_PRACH] =	"PRACH",
-	[PCU_IF_SAPI_PTCCH] = 	"PTCCH",
-	[PCU_IF_SAPI_AGCH_DT] = 	"AGCH_DT",
-};
-
-/* Check if BTS has a PCU connection */
-static bool pcu_connected(struct gsm_bts *bts)
-{
-	struct pcu_sock_state *state = bts->pcu_state;
-
-	if (!state)
-		return false;
-	if (state->conn_bfd.fd <= 0)
-		return false;
-	return true;
-}
-
-/*
- * PCU messages
- */
-
-/* Set up an message buffer to package an pcu interface message */
-struct msgb *pcu_msgb_alloc(uint8_t msg_type, uint8_t bts_nr)
-{
-	struct msgb *msg;
-	struct gsm_pcu_if *pcu_prim;
-
-	msg = msgb_alloc(sizeof(struct gsm_pcu_if), "pcu_sock_tx");
-	if (!msg)
-		return NULL;
-
-	msgb_put(msg, sizeof(struct gsm_pcu_if));
-	pcu_prim = (struct gsm_pcu_if *) msg->data;
-	pcu_prim->msg_type = msg_type;
-	pcu_prim->bts_nr = bts_nr;
-
-	return msg;
-}
-
-/* Helper function exclusivly used by pcu_if_signal_cb() */
-static bool ts_should_be_pdch(struct gsm_bts_trx_ts *ts) {
-	if (ts->pchan == GSM_PCHAN_PDCH)
-		return true;
-	if (ts->pchan == GSM_PCHAN_TCH_F_PDCH) {
-		/* When we're busy deactivating the PDCH, we first set
-		 * DEACT_PENDING, tell the PCU about it and wait for a
-		 * response. So DEACT_PENDING means "no PDCH" to the PCU.
-		 * Similarly, when we're activating PDCH, we set the
-		 * ACT_PENDING and wait for an activation response from the
-		 * PCU, so ACT_PENDING means "is PDCH". */
-		if (ts->flags & TS_F_PDCH_ACTIVE)
-			return !(ts->flags & TS_F_PDCH_DEACT_PENDING);
-		else
-			return (ts->flags & TS_F_PDCH_ACT_PENDING);
-	}
-	if (ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH) {
-		/*
-		 * When we're busy de-/activating the PDCH, we first set
-		 * ts->dyn.pchan_want, tell the PCU about it and wait for a
-		 * response. So only care about dyn.pchan_want here.
-		 */
-		return ts->dyn.pchan_want == GSM_PCHAN_PDCH;
-	}
-	return false;
-}
-
-/* Send BTS properties to the PCU */
-static int pcu_tx_info_ind(struct gsm_bts *bts)
-{
-	struct msgb *msg;
-	struct gsm_pcu_if *pcu_prim;
-	struct gsm_pcu_if_info_ind *info_ind;
-	struct gprs_rlc_cfg *rlcc;
-	struct gsm_bts_gprs_nsvc *nsvc;
-	struct gsm_bts_trx *trx;
-	struct gsm_bts_trx_ts *ts;
-	int i, j;
-
-	OSMO_ASSERT(bts);
-	OSMO_ASSERT(bts->network);
-
-	LOGP(DPCU, LOGL_INFO, "Sending info for BTS %d\n",bts->nr);
-
-	rlcc = &bts->gprs.cell.rlc_cfg;
-
-	msg = pcu_msgb_alloc(PCU_IF_MSG_INFO_IND, bts->nr);
-	if (!msg)
-		return -ENOMEM;
-
-	pcu_prim = (struct gsm_pcu_if *) msg->data;
-	info_ind = &pcu_prim->u.info_ind;
-	info_ind->version = PCU_IF_VERSION;
-	info_ind->flags |= PCU_IF_FLAG_ACTIVE;
-
-	if (pcu_direct)
-		info_ind->flags |= PCU_IF_FLAG_SYSMO;
-
-	/* RAI */
-	info_ind->mcc = bts->network->country_code;
-	info_ind->mnc = bts->network->network_code;
-	info_ind->lac = bts->location_area_code;
-	info_ind->rac = bts->gprs.rac;
-
-	/* NSE */
-	info_ind->nsei = bts->gprs.nse.nsei;
-	memcpy(info_ind->nse_timer, bts->gprs.nse.timer, 7);
-	memcpy(info_ind->cell_timer, bts->gprs.cell.timer, 11);
-
-	/* cell attributes */
-	info_ind->cell_id = bts->cell_identity;
-	info_ind->repeat_time = rlcc->paging.repeat_time;
-	info_ind->repeat_count = rlcc->paging.repeat_count;
-	info_ind->bvci = bts->gprs.cell.bvci;
-	info_ind->t3142 = rlcc->parameter[RLC_T3142];
-	info_ind->t3169 = rlcc->parameter[RLC_T3169];
-	info_ind->t3191 = rlcc->parameter[RLC_T3191];
-	info_ind->t3193_10ms = rlcc->parameter[RLC_T3193];
-	info_ind->t3195 = rlcc->parameter[RLC_T3195];
-	info_ind->n3101 = rlcc->parameter[RLC_N3101];
-	info_ind->n3103 = rlcc->parameter[RLC_N3103];
-	info_ind->n3105 = rlcc->parameter[RLC_N3105];
-	info_ind->cv_countdown = rlcc->parameter[CV_COUNTDOWN];
-	if (rlcc->cs_mask & (1 << GPRS_CS1))
-		info_ind->flags |= PCU_IF_FLAG_CS1;
-	if (rlcc->cs_mask & (1 << GPRS_CS2))
-		info_ind->flags |= PCU_IF_FLAG_CS2;
-	if (rlcc->cs_mask & (1 << GPRS_CS3))
-		info_ind->flags |= PCU_IF_FLAG_CS3;
-	if (rlcc->cs_mask & (1 << GPRS_CS4))
-		info_ind->flags |= PCU_IF_FLAG_CS4;
-	if (bts->gprs.mode == BTS_GPRS_EGPRS) {
-		if (rlcc->cs_mask & (1 << GPRS_MCS1))
-			info_ind->flags |= PCU_IF_FLAG_MCS1;
-		if (rlcc->cs_mask & (1 << GPRS_MCS2))
-			info_ind->flags |= PCU_IF_FLAG_MCS2;
-		if (rlcc->cs_mask & (1 << GPRS_MCS3))
-			info_ind->flags |= PCU_IF_FLAG_MCS3;
-		if (rlcc->cs_mask & (1 << GPRS_MCS4))
-			info_ind->flags |= PCU_IF_FLAG_MCS4;
-		if (rlcc->cs_mask & (1 << GPRS_MCS5))
-			info_ind->flags |= PCU_IF_FLAG_MCS5;
-		if (rlcc->cs_mask & (1 << GPRS_MCS6))
-			info_ind->flags |= PCU_IF_FLAG_MCS6;
-		if (rlcc->cs_mask & (1 << GPRS_MCS7))
-			info_ind->flags |= PCU_IF_FLAG_MCS7;
-		if (rlcc->cs_mask & (1 << GPRS_MCS8))
-			info_ind->flags |= PCU_IF_FLAG_MCS8;
-		if (rlcc->cs_mask & (1 << GPRS_MCS9))
-			info_ind->flags |= PCU_IF_FLAG_MCS9;
-	}
-#warning	"isn't dl_tbf_ext wrong?: * 10 and no ntohs"
-	info_ind->dl_tbf_ext = rlcc->parameter[T_DL_TBF_EXT];
-#warning	"isn't ul_tbf_ext wrong?: * 10 and no ntohs"
-	info_ind->ul_tbf_ext = rlcc->parameter[T_UL_TBF_EXT];
-	info_ind->initial_cs = rlcc->initial_cs;
-	info_ind->initial_mcs = rlcc->initial_mcs;
-
-	/* NSVC */
-	for (i = 0; i < ARRAY_SIZE(info_ind->nsvci); i++) {
-		nsvc = &bts->gprs.nsvc[i];
-		info_ind->nsvci[i] = nsvc->nsvci;
-		info_ind->local_port[i] = nsvc->local_port;
-		info_ind->remote_port[i] = nsvc->remote_port;
-		info_ind->remote_ip[i] = nsvc->remote_ip;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(info_ind->trx); i++) {
-		trx = gsm_bts_trx_num(bts, i);
-		if (!trx)
-			continue;
-		info_ind->trx[i].hlayer1 = 0x2342;
-		info_ind->trx[i].pdch_mask = 0;
-		info_ind->trx[i].arfcn = trx->arfcn;
-		for (j = 0; j < ARRAY_SIZE(trx->ts); j++) {
-			ts = &trx->ts[j];
-			if (ts->mo.nm_state.operational == NM_OPSTATE_ENABLED
-			    && ts_should_be_pdch(ts)) {
-				info_ind->trx[i].pdch_mask |= (1 << j);
-				info_ind->trx[i].tsc[j] =
-					(ts->tsc >= 0) ? ts->tsc : bts->bsic & 7;
-				LOGP(DPCU, LOGL_INFO, "trx=%d ts=%d: "
-					"available (tsc=%d arfcn=%d)\n",
-					trx->nr, ts->nr,
-					info_ind->trx[i].tsc[j],
-					info_ind->trx[i].arfcn);
-			}
-		}
-	}
-
-	return pcu_sock_send(bts, msg);
-}
-
-void pcu_info_update(struct gsm_bts *bts)
-{
-	if (pcu_connected(bts))
-		pcu_tx_info_ind(bts);
-}
-
-/* Forward rach indication to PCU */
-int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint16_t ra, uint32_t fn,
-	uint8_t is_11bit, enum ph_burst_type burst_type)
-{
-	struct msgb *msg;
-	struct gsm_pcu_if *pcu_prim;
-	struct gsm_pcu_if_rach_ind *rach_ind;
-
-	/* Bail if no PCU is connected */
-	if (!pcu_connected(bts)) {
-		LOGP(DRSL, LOGL_ERROR, "BTS %d CHAN RQD(GPRS) but PCU not "
-			"connected!\n", bts->nr);
-		return -ENODEV;
-	}
-
-	LOGP(DPCU, LOGL_INFO, "Sending RACH indication: qta=%d, ra=%d, "
-		"fn=%d\n", qta, ra, fn);
-
-	msg = pcu_msgb_alloc(PCU_IF_MSG_RACH_IND, bts->nr);
-	if (!msg)
-		return -ENOMEM;
-	pcu_prim = (struct gsm_pcu_if *) msg->data;
-	rach_ind = &pcu_prim->u.rach_ind;
-
-	rach_ind->sapi = PCU_IF_SAPI_RACH;
-	rach_ind->ra = ra;
-	rach_ind->qta = qta;
-	rach_ind->fn = fn;
-	rach_ind->is_11bit = is_11bit;
-	rach_ind->burst_type = burst_type;
-
-	return pcu_sock_send(bts, msg);
-}
-
-/* Confirm the sending of an immediate assignment to the pcu */
-int pcu_tx_imm_ass_sent(struct gsm_bts *bts, uint32_t tlli)
-{
-	struct msgb *msg;
-	struct gsm_pcu_if *pcu_prim;
-	struct gsm_pcu_if_data_cnf_dt *data_cnf_dt;
-
-	LOGP(DPCU, LOGL_INFO, "Sending PCH confirm with direct TLLI\n");
-
-	msg = pcu_msgb_alloc(PCU_IF_MSG_DATA_CNF_DT, bts->nr);
-	if (!msg)
-		return -ENOMEM;
-	pcu_prim = (struct gsm_pcu_if *) msg->data;
-	data_cnf_dt = &pcu_prim->u.data_cnf_dt;
-
-	data_cnf_dt->sapi = PCU_IF_SAPI_PCH;
-	data_cnf_dt->tlli = tlli;
-
-	return pcu_sock_send(bts, msg);
-}
-
-/* we need to decode the raw RR paging messsage (see PCU code
- * Encoding::write_paging_request) and extract the mobile identity
- * (P-TMSI) from it */
-static int pcu_rx_rr_paging(struct gsm_bts *bts, uint8_t paging_group,
-			    const uint8_t *raw_rr_msg)
-{
-	struct gsm48_paging1 *p1 = (struct gsm48_paging1 *) raw_rr_msg;
-	uint8_t chan_needed;
-	unsigned int mi_len;
-	uint8_t *mi;
-	int rc;
-
-	switch (p1->msg_type) {
-	case GSM48_MT_RR_PAG_REQ_1:
-		chan_needed = (p1->cneed2 << 2) | p1->cneed1;
-		mi_len = p1->data[0];
-		mi = p1->data+1;
-		LOGP(DPCU, LOGL_ERROR, "PCU Sends paging "
-		     "request type %02x (chan_needed=%02x, mi_len=%u, mi=%s)\n",
-		     p1->msg_type, chan_needed, mi_len,
-		     osmo_hexdump_nospc(mi,mi_len));
-		/* NOTE: We will have to add 2 to mi_len and subtract 2 from
-		 * the mi pointer because rsl_paging_cmd() will perform the
-		 * reverse operations. This is because rsl_paging_cmd() is
-		 * normally expected to chop off the element identifier (0xC0)
-		 * and the length field. In our parameter, we do not have
-		 * those fields included. */
-		rc = rsl_paging_cmd(bts, paging_group, mi_len+2, mi-2,
-				    chan_needed, true);
-		break;
-	case GSM48_MT_RR_PAG_REQ_2:
-	case GSM48_MT_RR_PAG_REQ_3:
-		LOGP(DPCU, LOGL_ERROR, "PCU Sends unsupported paging "
-			"request type %02x\n", p1->msg_type);
-		rc = -EINVAL;
-		break;
-	default:
-		LOGP(DPCU, LOGL_ERROR, "PCU Sends unknown paging "
-			"request type %02x\n", p1->msg_type);
-		rc = -EINVAL;
-		break;
-	}
-
-	return rc;
-}
-
-static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type,
-	struct gsm_pcu_if_data *data_req)
-{
-	uint8_t is_ptcch;
-	struct gsm_bts_trx *trx;
-	struct gsm_bts_trx_ts *ts;
-	struct msgb *msg;
-	char imsi_digit_buf[4];
-	uint32_t tlli = -1;
-	uint8_t pag_grp;
-	int rc = 0;
-
-	LOGP(DPCU, LOGL_DEBUG, "Data request received: sapi=%s arfcn=%d "
-		"block=%d data=%s\n", sapi_string[data_req->sapi],
-		data_req->arfcn, data_req->block_nr,
-		osmo_hexdump(data_req->data, data_req->len));
-
-	switch (data_req->sapi) {
-	case PCU_IF_SAPI_PCH:
-		/* the first three bytes are the last three digits of
-		 * the IMSI, which we need to compute the paging group */
-		imsi_digit_buf[0] = data_req->data[0];
-		imsi_digit_buf[1] = data_req->data[1];
-		imsi_digit_buf[2] = data_req->data[2];
-		imsi_digit_buf[3] = '\0';
-		LOGP(DPCU, LOGL_DEBUG, "SAPI PCH imsi %s\n", imsi_digit_buf);
-		pag_grp = gsm0502_calc_paging_group(&bts->si_common.chan_desc,
-						str_to_imsi(imsi_digit_buf));
-		pcu_rx_rr_paging(bts, pag_grp, data_req->data+3);
-		break;
-	case PCU_IF_SAPI_AGCH:
-		msg = msgb_alloc(data_req->len, "pcu_agch");
-		if (!msg) {
-			rc = -ENOMEM;
-			break;
-		}
-		msg->l3h = msgb_put(msg, data_req->len);
-		memcpy(msg->l3h, data_req->data, data_req->len);
-
-		if (rsl_imm_assign_cmd(bts, msg->len, msg->data)) {
-			msgb_free(msg);
-			rc = -EIO;
-		}
-		break;
-	case PCU_IF_SAPI_AGCH_DT:
-		/* DT = direct tlli. A tlli is prefixed */
-
-		if (data_req->len < 5) {
-			LOGP(DPCU, LOGL_ERROR, "Received PCU data request with "
-					"invalid/small length %d\n", data_req->len);
-			break;
-		}
-		tlli = *((uint32_t *)data_req->data);
-
-		msg = msgb_alloc(data_req->len - 4, "pcu_agch");
-		if (!msg) {
-			rc = -ENOMEM;
-			break;
-		}
-		msg->l3h = msgb_put(msg, data_req->len - 4);
-		memcpy(msg->l3h, data_req->data + 4, data_req->len - 4);
-
-		if (bts->type == GSM_BTS_TYPE_RBS2000)
-			rc = rsl_ericsson_imm_assign_cmd(bts, tlli, msg->len, msg->data);
-		else
-			rc = rsl_imm_assign_cmd(bts, msg->len, msg->data);
-
-		if (rc) {
-			msgb_free(msg);
-			rc = -EIO;
-		}
-		break;
-	default:
-		LOGP(DPCU, LOGL_ERROR, "Received PCU data request with "
-			"unsupported sapi %d\n", data_req->sapi);
-		rc = -EINVAL;
-	}
-
-	return rc;
-}
-
-static int pcu_rx(struct gsm_network *net, uint8_t msg_type,
-	struct gsm_pcu_if *pcu_prim)
-{
-	int rc = 0;
-	struct gsm_bts *bts;
-
-	/* FIXME: allow multiple BTS */
-	bts = llist_entry(net->bts_list.next, struct gsm_bts, list);
-
-	switch (msg_type) {
-	case PCU_IF_MSG_DATA_REQ:
-	case PCU_IF_MSG_PAG_REQ:
-		rc = pcu_rx_data_req(bts, msg_type, &pcu_prim->u.data_req);
-		break;
-	default:
-		LOGP(DPCU, LOGL_ERROR, "Received unknwon PCU msg type %d\n",
-			msg_type);
-		rc = -EINVAL;
-	}
-
-	return rc;
-}
-
-/*
- * PCU socket interface
- */
-
-static int pcu_sock_send(struct gsm_bts *bts, struct msgb *msg)
-{
-	struct pcu_sock_state *state = bts->pcu_state;
-	struct osmo_fd *conn_bfd;
-	struct gsm_pcu_if *pcu_prim = (struct gsm_pcu_if *) msg->data;
-
-	if (!state) {
-		if (pcu_prim->msg_type != PCU_IF_MSG_TIME_IND)
-			LOGP(DPCU, LOGL_INFO, "PCU socket not created, "
-				"dropping message\n");
-		msgb_free(msg);
-		return -EINVAL;
-	}
-	conn_bfd = &state->conn_bfd;
-	if (conn_bfd->fd <= 0) {
-		if (pcu_prim->msg_type != PCU_IF_MSG_TIME_IND)
-			LOGP(DPCU, LOGL_NOTICE, "PCU socket not connected, "
-				"dropping message\n");
-		msgb_free(msg);
-		return -EIO;
-	}
-	msgb_enqueue(&state->upqueue, msg);
-	conn_bfd->when |= BSC_FD_WRITE;
-
-	return 0;
-}
-
-static void pcu_sock_close(struct pcu_sock_state *state)
-{
-	struct osmo_fd *bfd = &state->conn_bfd;
-	struct gsm_bts *bts;
-	struct gsm_bts_trx *trx;
-	struct gsm_bts_trx_ts *ts;
-	int i, j;
-
-	/* FIXME: allow multiple BTS */
-	bts = llist_entry(state->net->bts_list.next, struct gsm_bts, list);
-
-	LOGP(DPCU, LOGL_NOTICE, "PCU socket has LOST connection\n");
-
-	close(bfd->fd);
-	bfd->fd = -1;
-	osmo_fd_unregister(bfd);
-
-	/* re-enable the generation of ACCEPT for new connections */
-	state->listen_bfd.when |= BSC_FD_READ;
-
-#if 0
-	/* remove si13, ... */
-	bts->si_valid &= ~(1 << SYSINFO_TYPE_13);
-	osmo_signal_dispatch(SS_GLOBAL, S_NEW_SYSINFO, bts);
-#endif
-
-	/* release PDCH */
-	for (i = 0; i < 8; i++) {
-		trx = gsm_bts_trx_num(bts, i);
-		if (!trx)
-			break;
-		for (j = 0; j < 8; j++) {
-			ts = &trx->ts[j];
-			if (ts->mo.nm_state.operational == NM_OPSTATE_ENABLED
-			 && ts->pchan == GSM_PCHAN_PDCH) {
-				printf("l1sap_chan_rel(trx,gsm_lchan2chan_nr(ts->lchan));\n");
-			}
-		}
-	}
-
-	/* flush the queue */
-	while (!llist_empty(&state->upqueue)) {
-		struct msgb *msg = msgb_dequeue(&state->upqueue);
-		msgb_free(msg);
-	}
-}
-
-static int pcu_sock_read(struct osmo_fd *bfd)
-{
-	struct pcu_sock_state *state = (struct pcu_sock_state *)bfd->data;
-	struct gsm_pcu_if *pcu_prim;
-	struct msgb *msg;
-	int rc;
-
-	msg = msgb_alloc(sizeof(*pcu_prim), "pcu_sock_rx");
-	if (!msg)
-		return -ENOMEM;
-
-	pcu_prim = (struct gsm_pcu_if *) msg->tail;
-
-	rc = recv(bfd->fd, msg->tail, msgb_tailroom(msg), 0);
-	if (rc == 0)
-		goto close;
-
-	if (rc < 0) {
-		if (errno == EAGAIN)
-			return 0;
-		goto close;
-	}
-
-	rc = pcu_rx(state->net, pcu_prim->msg_type, pcu_prim);
-
-	/* as we always synchronously process the message in pcu_rx() and
-	 * its callbacks, we can free the message here. */
-	msgb_free(msg);
-
-	return rc;
-
-close:
-	msgb_free(msg);
-	pcu_sock_close(state);
-	return -1;
-}
-
-static int pcu_sock_write(struct osmo_fd *bfd)
-{
-	struct pcu_sock_state *state = bfd->data;
-	int rc;
-
-	while (!llist_empty(&state->upqueue)) {
-		struct msgb *msg, *msg2;
-		struct gsm_pcu_if *pcu_prim;
-
-		/* peek at the beginning of the queue */
-		msg = llist_entry(state->upqueue.next, struct msgb, list);
-		pcu_prim = (struct gsm_pcu_if *)msg->data;
-
-		bfd->when &= ~BSC_FD_WRITE;
-
-		/* bug hunter 8-): maybe someone forgot msgb_put(...) ? */
-		if (!msgb_length(msg)) {
-			LOGP(DPCU, LOGL_ERROR, "message type (%d) with ZERO "
-				"bytes!\n", pcu_prim->msg_type);
-			goto dontsend;
-		}
-
-		/* try to send it over the socket */
-		rc = write(bfd->fd, msgb_data(msg), msgb_length(msg));
-		if (rc == 0)
-			goto close;
-		if (rc < 0) {
-			if (errno == EAGAIN) {
-				bfd->when |= BSC_FD_WRITE;
-				break;
-			}
-			goto close;
-		}
-
-dontsend:
-		/* _after_ we send it, we can deueue */
-		msg2 = msgb_dequeue(&state->upqueue);
-		assert(msg == msg2);
-		msgb_free(msg);
-	}
-	return 0;
-
-close:
-	pcu_sock_close(state);
-
-	return -1;
-}
-
-static int pcu_sock_cb(struct osmo_fd *bfd, unsigned int flags)
-{
-	int rc = 0;
-
-	if (flags & BSC_FD_READ)
-		rc = pcu_sock_read(bfd);
-	if (rc < 0)
-		return rc;
-
-	if (flags & BSC_FD_WRITE)
-		rc = pcu_sock_write(bfd);
-
-	return rc;
-}
-
-/* accept connection comming from PCU */
-static int pcu_sock_accept(struct osmo_fd *bfd, unsigned int flags)
-{
-	struct pcu_sock_state *state = (struct pcu_sock_state *)bfd->data;
-	struct osmo_fd *conn_bfd = &state->conn_bfd;
-	struct sockaddr_un un_addr;
-	socklen_t len;
-	int rc;
-
-	len = sizeof(un_addr);
-	rc = accept(bfd->fd, (struct sockaddr *) &un_addr, &len);
-	if (rc < 0) {
-		LOGP(DPCU, LOGL_ERROR, "Failed to accept a new connection\n");
-		return -1;
-	}
-
-	if (conn_bfd->fd >= 0) {
-		LOGP(DPCU, LOGL_NOTICE, "PCU connects but we already have "
-			"another active connection ?!?\n");
-		/* We already have one PCU connected, this is all we support */
-		state->listen_bfd.when &= ~BSC_FD_READ;
-		close(rc);
-		return 0;
-	}
-
-	conn_bfd->fd = rc;
-	conn_bfd->when = BSC_FD_READ;
-	conn_bfd->cb = pcu_sock_cb;
-	conn_bfd->data = state;
-
-	if (osmo_fd_register(conn_bfd) != 0) {
-		LOGP(DPCU, LOGL_ERROR, "Failed to register new connection "
-			"fd\n");
-		close(conn_bfd->fd);
-		conn_bfd->fd = -1;
-		return -1;
-	}
-
-	LOGP(DPCU, LOGL_NOTICE, "PCU socket connected to external PCU\n");
-
-	return 0;
-}
-
-/* Open connection to PCU */
-int pcu_sock_init(const char *path, struct gsm_bts *bts)
-{
-	struct pcu_sock_state *state;
-	struct osmo_fd *bfd;
-	int rc;
-
-	state = talloc_zero(NULL, struct pcu_sock_state);
-	if (!state)
-		return -ENOMEM;
-
-	INIT_LLIST_HEAD(&state->upqueue);
-	state->net = bts->network;
-	state->conn_bfd.fd = -1;
-
-	bfd = &state->listen_bfd;
-
-	bfd->fd = osmo_sock_unix_init(SOCK_SEQPACKET, 0, path,
-		OSMO_SOCK_F_BIND);
-	if (bfd->fd < 0) {
-		LOGP(DPCU, LOGL_ERROR, "Could not create unix socket: %s\n",
-			strerror(errno));
-		talloc_free(state);
-		return -1;
-	}
-
-	bfd->when = BSC_FD_READ;
-	bfd->cb = pcu_sock_accept;
-	bfd->data = state;
-
-	rc = osmo_fd_register(bfd);
-	if (rc < 0) {
-		LOGP(DPCU, LOGL_ERROR, "Could not register listen fd: %d\n",
-			rc);
-		close(bfd->fd);
-		talloc_free(state);
-		return rc;
-	}
-
-	bts->pcu_state = state;
-	return 0;
-}
-
-/* Close connection to PCU */
-void pcu_sock_exit(struct gsm_bts *bts)
-{
-	struct pcu_sock_state *state = bts->pcu_state;
-	struct osmo_fd *bfd, *conn_bfd;
-
-	if (!state)
-		return;
-
-	conn_bfd = &state->conn_bfd;
-	if (conn_bfd->fd > 0)
-		pcu_sock_close(state);
-	bfd = &state->listen_bfd;
-	close(bfd->fd);
-	osmo_fd_unregister(bfd);
-	talloc_free(state);
-	bts->pcu_state = NULL;
-}
-
diff --git a/src/libbsc/rest_octets.c b/src/libbsc/rest_octets.c
deleted file mode 100644
index fdab70a..0000000
--- a/src/libbsc/rest_octets.c
+++ /dev/null
@@ -1,860 +0,0 @@
-/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface,
- * rest octet handling according to
- * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
-
-/* (C) 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/>.
- *
- */
-
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <stdbool.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <osmocom/core/bitvec.h>
-#include <osmocom/gsm/bitvec_gsm.h>
-#include <openbsc/rest_octets.h>
-#include <openbsc/arfcn_range_encode.h>
-#include <openbsc/system_information.h>
-
-/* generate SI1 rest octets */
-int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net)
-{
-	struct bitvec bv;
-
-	memset(&bv, 0, sizeof(bv));
-	bv.data = data;
-	bv.data_len = 1;
-
-	if (nch_pos) {
-		bitvec_set_bit(&bv, H);
-		bitvec_set_uint(&bv, *nch_pos, 5);
-	} else
-		bitvec_set_bit(&bv, L);
-
-	if (is1800_net)
-		bitvec_set_bit(&bv, L);
-	else
-		bitvec_set_bit(&bv, H);
-
-	bitvec_spare_padding(&bv, 6);
-	return bv.data_len;
-}
-
-/* Append Repeated E-UTRAN Neighbour Cell to bitvec: see 3GPP TS 44.018 Table 10.5.2.33b.1 */
-static inline void append_eutran_neib_cell(struct bitvec *bv, struct gsm_bts *bts, uint8_t budget)
-{
-	const struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list;
-	unsigned i, skip = 0;
-	size_t offset = bts->e_offset;
-	uint8_t rem = budget - 6, earfcn_budget; /* account for mandatory stop bit and THRESH_E-UTRAN_high */
-
-	if (budget <= 6)
-		return;
-
-	OSMO_ASSERT(budget <= SI2Q_MAX_LEN);
-
-	/* first we have to properly adjust budget requirements */
-	if (e->prio_valid) /* E-UTRAN_PRIORITY: 3GPP TS 45.008*/
-		rem -= 4;
-	else
-		rem--;
-
-	if (e->thresh_lo_valid) /* THRESH_E-UTRAN_low: */
-		rem -= 6;
-	else
-		rem--;
-
-	if (e->qrxlm_valid) /* E-UTRAN_QRXLEVMIN: */
-		rem -= 6;
-	else
-		rem--;
-
-	/* now we can proceed with actually adding EARFCNs within adjusted budget limit */
-	for (i = 0; i < e->length; i++) {
-		if (e->arfcn[i] != OSMO_EARFCN_INVALID) {
-			if (skip < offset) {
-				skip++; /* ignore EARFCNs added on previous calls */
-			} else {
-				earfcn_budget = 17; /* compute budget per-EARFCN */
-				if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i])
-					earfcn_budget++;
-				else
-					earfcn_budget += 4;
-
-				if (rem - earfcn_budget < 0)
-					break;
-				else {
-					bts->e_offset++;
-					rem -= earfcn_budget;
-					bitvec_set_bit(bv, 1); /* EARFCN: */
-					bitvec_set_uint(bv, e->arfcn[i], 16);
-
-					if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i])
-						bitvec_set_bit(bv, 0);
-					else { /* Measurement Bandwidth: 9.1.54 */
-						bitvec_set_bit(bv, 1);
-						bitvec_set_uint(bv, e->meas_bw[i], 3);
-					}
-				}
-			}
-		}
-	}
-
-	/* stop bit - end of EARFCN + Measurement Bandwidth sequence */
-	bitvec_set_bit(bv, 0);
-
-	/* Note: we don't support different EARFCN arrays each with different priority, threshold etc. */
-
-	if (e->prio_valid) {
-		/* E-UTRAN_PRIORITY: 3GPP TS 45.008*/
-		bitvec_set_bit(bv, 1);
-		bitvec_set_uint(bv, e->prio, 3);
-	} else
-		bitvec_set_bit(bv, 0);
-
-	/* THRESH_E-UTRAN_high */
-	bitvec_set_uint(bv, e->thresh_hi, 5);
-
-	if (e->thresh_lo_valid) {
-		/* THRESH_E-UTRAN_low: */
-		bitvec_set_bit(bv, 1);
-		bitvec_set_uint(bv, e->thresh_lo, 5);
-	} else
-		bitvec_set_bit(bv, 0);
-
-	if (e->qrxlm_valid) {
-		/* E-UTRAN_QRXLEVMIN: */
-		bitvec_set_bit(bv, 1);
-		bitvec_set_uint(bv, e->qrxlm, 5);
-	} else
-		bitvec_set_bit(bv, 0);
-}
-
-static inline void append_earfcn(struct bitvec *bv, struct gsm_bts *bts, uint8_t budget)
-{
-	int rem = budget - 25;
-	if (rem <= 0)
-		return;
-
-	OSMO_ASSERT(budget <= SI2Q_MAX_LEN);
-
-	/* Additions in Rel-5: */
-	bitvec_set_bit(bv, H);
-	/* No 3G Additional Measurement Param. Descr. */
-	bitvec_set_bit(bv, 0);
-	/* No 3G ADDITIONAL MEASUREMENT Param. Descr. 2 */
-	bitvec_set_bit(bv, 0);
-	/* Additions in Rel-6: */
-	bitvec_set_bit(bv, H);
-	/* 3G_CCN_ACTIVE */
-	bitvec_set_bit(bv, 0);
-	/* Additions in Rel-7: */
-	bitvec_set_bit(bv, H);
-	/* No 700_REPORTING_OFFSET */
-	bitvec_set_bit(bv, 0);
-	/* No 810_REPORTING_OFFSET */
-	bitvec_set_bit(bv, 0);
-	/* Additions in Rel-8: */
-	bitvec_set_bit(bv, H);
-
-	/* Priority and E-UTRAN Parameters Description */
-	bitvec_set_bit(bv, 1);
-
-	/* No Serving Cell Priority Parameters Descr. */
-	bitvec_set_bit(bv, 0);
-	/* No 3G Priority Parameters Description */
-	bitvec_set_bit(bv, 0);
-	/* E-UTRAN Parameters Description */
-	bitvec_set_bit(bv, 1);
-
-	/* E-UTRAN_CCN_ACTIVE */
-	bitvec_set_bit(bv, 0);
-	/* E-UTRAN_Start: 9.1.54 */
-	bitvec_set_bit(bv, 1);
-	/* E-UTRAN_Stop: 9.1.54 */
-	bitvec_set_bit(bv, 1);
-
-	/* No E-UTRAN Measurement Parameters Descr. */
-	bitvec_set_bit(bv, 0);
-	/* No GPRS E-UTRAN Measurement Param. Descr. */
-	bitvec_set_bit(bv, 0);
-
-	/* Note: each of next 3 "repeated" structures might be repeated any
-	   (0, 1, 2...) times - we only support 1 and 0 */
-
-	/* Repeated E-UTRAN Neighbour Cells */
-	bitvec_set_bit(bv, 1);
-
-	/* N. B: 25 bits are set in append_earfcn() - keep it in sync with budget adjustment below: */
-	append_eutran_neib_cell(bv, bts, rem);
-
-	/* stop bit - end of Repeated E-UTRAN Neighbour Cells sequence: */
-	bitvec_set_bit(bv, 0);
-
-	/* Note: following 2 repeated structs are not supported ATM */
-	/* stop bit - end of Repeated E-UTRAN Not Allowed Cells sequence: */
-	bitvec_set_bit(bv, 0);
-	/* stop bit - end of Repeated E-UTRAN PCID to TA mapping sequence: */
-	bitvec_set_bit(bv, 0);
-
-	/* Priority and E-UTRAN Parameters Description ends here */
-	/* No 3G CSG Description */
-	bitvec_set_bit(bv, 0);
-	/* No E-UTRAN CSG Description */
-	bitvec_set_bit(bv, 0);
-	/* No Additions in Rel-9: */
-	bitvec_set_bit(bv, L);
-}
-
-static inline int f0_helper(int *sc, size_t length, uint8_t *chan_list)
-{
-	int w[RANGE_ENC_MAX_ARFCNS] = { 0 };
-
-	return range_encode(ARFCN_RANGE_1024, sc, length, w, 0, chan_list);
-}
-
-/* Estimate how many bits it'll take to append single FDD UARFCN */
-static inline int append_utran_fdd_length(uint16_t u, int *sc, size_t sc_len, size_t length)
-{
-	uint8_t chan_list[16] = { 0 };
-	int tmp[sc_len], f0;
-
-	memcpy(tmp, sc, sizeof(tmp));
-
-	f0 = f0_helper(tmp, length, chan_list);
-	if (f0 < 0)
-		return f0;
-
-	return 21 + range1024_p(length);
-}
-
-/* Append single FDD UARFCN */
-static inline int append_utran_fdd(struct bitvec *bv, uint16_t u, int *sc, size_t length)
-{
-	uint8_t chan_list[16] = { 0 };
-	int f0 = f0_helper(sc, length, chan_list);
-
-	if (f0 < 0)
-		return f0;
-
-	/* Repeated UTRAN FDD Neighbour Cells */
-	bitvec_set_bit(bv, 1);
-
-	/* FDD-ARFCN */
-	bitvec_set_bit(bv, 0);
-	bitvec_set_uint(bv, u, 14);
-
-	/* FDD_Indic0: parameter value '0000000000' is a member of the set? */
-	bitvec_set_bit(bv, f0);
-	/* NR_OF_FDD_CELLS */
-	bitvec_set_uint(bv, length, 5);
-
-	f0 = bv->cur_bit;
-	bitvec_add_range1024(bv, (struct gsm48_range_1024 *)chan_list);
-	bv->cur_bit = f0 + range1024_p(length);
-
-	return 21 + range1024_p(length);
-}
-
-/* Append multiple FDD UARFCNs */
-static inline int append_uarfcns(struct bitvec *bv, struct gsm_bts *bts, uint8_t budget)
-{
-	const uint16_t *u = bts->si_common.data.uarfcn_list, *sc = bts->si_common.data.scramble_list;
-	int i, j, k, rc, st = 0, a[bts->si_common.uarfcn_length];
-	uint16_t cu = u[bts->u_offset]; /* caller ensures that length is positive */
-	uint8_t rem = budget - 7, offset_diff; /* account for constant bits right away */
-
-	OSMO_ASSERT(budget <= SI2Q_MAX_LEN);
-
-	if (budget <= 7)
-		return -ENOMEM;
-
-	/* 3G Neighbour Cell Description */
-	bitvec_set_bit(bv, 1);
-	/* No Index_Start_3G */
-	bitvec_set_bit(bv, 0);
-	/* No Absolute_Index_Start_EMR */
-	bitvec_set_bit(bv, 0);
-
-	/* UTRAN FDD Description */
-	bitvec_set_bit(bv, 1);
-	/* No Bandwidth_FDD */
-	bitvec_set_bit(bv, 0);
-
-	for (i = bts->u_offset; i < bts->si_common.uarfcn_length; i++) {
-		offset_diff = 0;
-		for (j = st, k = 0; j < i; j++) {
-			a[k++] = sc[j]; /* copy corresponding SCs */
-			offset_diff++; /* compute proper offset step */
-		}
-		if (u[i] != cu) { /* we've reached new UARFCN */
-			rc = append_utran_fdd_length(cu, a, bts->si_common.uarfcn_length, k);
-			if (rc < 0) { /* estimate bit length requirements */
-				return rc;
-			}
-
-			if (rem - rc <= 0)
-				break; /* we have ran out of budget in current SI2q */
-			else {
-				rem -= append_utran_fdd(bv, cu, a, k);
-				bts->u_offset += offset_diff;
-			}
-			cu = u[i];
-			st = i; /* update start position */
-		}
-	}
-
-	if (rem > 22) {	/* add last UARFCN not covered by previous cycle if it could possibly fit into budget */
-		offset_diff = 0;
-		for (i = st, k = 0; i < bts->si_common.uarfcn_length; i++) {
-			a[k++] = sc[i];
-			offset_diff++;
-		}
-		rc = append_utran_fdd_length(cu, a, bts->si_common.uarfcn_length, k);
-		if (rc < 0) {
-			return rc;
-		}
-
-		if (rem - rc >= 0) {
-			rem -= append_utran_fdd(bv, cu, a, k);
-			bts->u_offset += offset_diff;
-		}
-	}
-
-	/* stop bit - end of Repeated UTRAN FDD Neighbour Cells */
-	bitvec_set_bit(bv, 0);
-
-	/* UTRAN TDD Description */
-	bitvec_set_bit(bv, 0);
-
-	return 0;
-}
-
-/* generate SI2quater rest octets: 3GPP TS 44.018 § 10.5.2.33b */
-int rest_octets_si2quater(uint8_t *data, struct gsm_bts *bts)
-{
-	int rc;
-	struct bitvec bv;
-
-	if (bts->si2q_count < bts->si2q_index)
-		return -EINVAL;
-
-	bv.data = data;
-	bv.data_len = 20;
-	bitvec_zero(&bv);
-
-	/* BA_IND */
-	bitvec_set_bit(&bv, 1);
-	/* 3G_BA_IND */
-	bitvec_set_bit(&bv, 1);
-	/* MP_CHANGE_MARK */
-	bitvec_set_bit(&bv, 0);
-
-	/* SI2quater_INDEX */
-	bitvec_set_uint(&bv, bts->si2q_index, 4);
-	/* SI2quater_COUNT */
-	bitvec_set_uint(&bv, bts->si2q_count, 4);
-
-	/* No Measurement_Parameters Description */
-	bitvec_set_bit(&bv, 0);
-	/* No GPRS_Real Time Difference Description */
-	bitvec_set_bit(&bv, 0);
-	/* No GPRS_BSIC Description */
-	bitvec_set_bit(&bv, 0);
-	/* No GPRS_REPORT PRIORITY Description */
-	bitvec_set_bit(&bv, 0);
-	/* No GPRS_MEASUREMENT_Parameters Description */
-	bitvec_set_bit(&bv, 0);
-	/* No NC Measurement Parameters */
-	bitvec_set_bit(&bv, 0);
-	/* No extension (length) */
-	bitvec_set_bit(&bv, 0);
-
-	rc = SI2Q_MAX_LEN - (bv.cur_bit + 3);
-	if (rc > 0 && bts->si_common.uarfcn_length - bts->u_offset > 0) {
-		rc = append_uarfcns(&bv, bts, rc);
-		if (rc < 0) {
-			LOGP(DRR, LOGL_ERROR, "SI2quater [%u/%u]: failed to append %zu UARFCNs due to range encoding "
-			     "failure: %s\n",
-			     bts->si2q_index, bts->si2q_count, bts->si_common.uarfcn_length, strerror(-rc));
-			return rc;
-		}
-	} else /* No 3G Neighbour Cell Description */
-		bitvec_set_bit(&bv, 0);
-
-	/* No 3G Measurement Parameters Description */
-	bitvec_set_bit(&bv, 0);
-	/* No GPRS_3G_MEASUREMENT Parameters Descr. */
-	bitvec_set_bit(&bv, 0);
-
-	rc = SI2Q_MAX_LEN - bv.cur_bit;
-	if (rc > 0 && si2q_earfcn_count(&bts->si_common.si2quater_neigh_list) - bts->e_offset > 0)
-		append_earfcn(&bv, bts, rc);
-	else /* No Additions in Rel-5: */
-		bitvec_set_bit(&bv, L);
-
-	bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);
-	return bv.data_len;
-}
-
-/* Append selection parameters to bitvec */
-static void append_selection_params(struct bitvec *bv,
-				    const struct gsm48_si_selection_params *sp)
-{
-	if (sp->present) {
-		bitvec_set_bit(bv, H);
-		bitvec_set_bit(bv, sp->cbq);
-		bitvec_set_uint(bv, sp->cell_resel_off, 6);
-		bitvec_set_uint(bv, sp->temp_offs, 3);
-		bitvec_set_uint(bv, sp->penalty_time, 5);
-	} else
-		bitvec_set_bit(bv, L);
-}
-
-/* Append power offset to bitvec */
-static void append_power_offset(struct bitvec *bv,
-				const struct gsm48_si_power_offset *po)
-{
-	if (po->present) {
-		bitvec_set_bit(bv, H);
-		bitvec_set_uint(bv, po->power_offset, 2);
-	} else
-		bitvec_set_bit(bv, L);
-}
-
-/* Append GPRS indicator to bitvec */
-static void append_gprs_ind(struct bitvec *bv,
-			    const struct gsm48_si3_gprs_ind *gi)
-{
-	if (gi->present) {
-		bitvec_set_bit(bv, H);
-		bitvec_set_uint(bv, gi->ra_colour, 3);
-		/* 0 == SI13 in BCCH Norm, 1 == SI13 sent on BCCH Ext */
-		bitvec_set_bit(bv, gi->si13_position);
-	} else
-		bitvec_set_bit(bv, L);
-}
-
-
-/* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */
-int rest_octets_si3(uint8_t *data, const struct gsm48_si_ro_info *si3)
-{
-	struct bitvec bv;
-
-	memset(&bv, 0, sizeof(bv));
-	bv.data = data;
-	bv.data_len = 4;
-
-	/* Optional Selection Parameters */
-	append_selection_params(&bv, &si3->selection_params);
-
-	/* Optional Power Offset */
-	append_power_offset(&bv, &si3->power_offset);
-
-	/* Do we have a SI2ter on the BCCH? */
-	if (si3->si2ter_indicator)
-		bitvec_set_bit(&bv, H);
-	else
-		bitvec_set_bit(&bv, L);
-
-	/* Early Classmark Sending Control */
-	if (si3->early_cm_ctrl)
-		bitvec_set_bit(&bv, H);
-	else
-		bitvec_set_bit(&bv, L);
-
-	/* Do we have a SI Type 9 on the BCCH? */
-	if (si3->scheduling.present) {
-		bitvec_set_bit(&bv, H);
-		bitvec_set_uint(&bv, si3->scheduling.where, 3);
-	} else
-		bitvec_set_bit(&bv, L);
-
-	/* GPRS Indicator */
-	append_gprs_ind(&bv, &si3->gprs_ind);
-
-	/* 3G Early Classmark Sending Restriction controlled by
-	 * early_cm_ctrl above */
-	bitvec_set_bit(&bv, H);
-
-	if (si3->si2quater_indicator) {
-		bitvec_set_bit(&bv, H); /* indicator struct present */
-		bitvec_set_uint(&bv, 0, 1); /* message is sent on BCCH Norm */
-	}
-
-	bitvec_spare_padding(&bv, (bv.data_len*8)-1);
-	return bv.data_len;
-}
-
-static int append_lsa_params(struct bitvec *bv,
-			     const struct gsm48_lsa_params *lsa_params)
-{
-	/* FIXME */
-	return -1;
-}
-
-/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
-int rest_octets_si4(uint8_t *data, const struct gsm48_si_ro_info *si4, int len)
-{
-	struct bitvec bv;
-
-	memset(&bv, 0, sizeof(bv));
-	bv.data = data;
-	bv.data_len = len;
-
-	/* SI4 Rest Octets O */
-	append_selection_params(&bv, &si4->selection_params);
-	append_power_offset(&bv, &si4->power_offset);
-	append_gprs_ind(&bv, &si4->gprs_ind);
-
-	if (0 /* FIXME */) {
-		/* H and SI4 Rest Octets S */
-		bitvec_set_bit(&bv, H);
-
-		/* LSA Parameters */
-		if (si4->lsa_params.present) {
-			bitvec_set_bit(&bv, H);
-			append_lsa_params(&bv, &si4->lsa_params);
-		} else
-			bitvec_set_bit(&bv, L);
-
-		/* Cell Identity */
-		if (1) {
-			bitvec_set_bit(&bv, H);
-			bitvec_set_uint(&bv, si4->cell_id, 16);
-		} else
-			bitvec_set_bit(&bv, L);
-
-		/* LSA ID Information */
-		if (0) {
-			bitvec_set_bit(&bv, H);
-			/* FIXME */
-		} else
-			bitvec_set_bit(&bv, L);
-	} else {
-		/* L and break indicator */
-		bitvec_set_bit(&bv, L);
-		bitvec_set_bit(&bv, si4->break_ind ? H : L);
-	}
-
-	return bv.data_len;
-}
-
-
-/* GSM 04.18 ETSI TS 101 503 V8.27.0 (2006-05)
-
-<SI6 rest octets> ::=
-{L | H <PCH and NCH info>}
-{L | H <VBS/VGCS options : bit(2)>}
-{ < DTM_support : bit == L > I < DTM_support : bit == H >
-< RAC : bit (8) >
-< MAX_LAPDm : bit (3) > }
-< Band indicator >
-{ L | H < GPRS_MS_TXPWR_MAX_CCH : bit (5) > }
-<implicit spare >;
-*/
-int rest_octets_si6(uint8_t *data, bool is1800_net)
-{
-	struct bitvec bv;
-
-	memset(&bv, 0, sizeof(bv));
-	bv.data = data;
-	bv.data_len = 1;
-
-	/* no PCH/NCH info */
-	bitvec_set_bit(&bv, L);
-	/* no VBS/VGCS options */
-	bitvec_set_bit(&bv, L);
-	/* no DTM_support */
-	bitvec_set_bit(&bv, L);
-	/* band indicator */
-	if (is1800_net)
-		bitvec_set_bit(&bv, L);
-	else
-		bitvec_set_bit(&bv, H);
-	/* no GPRS_MS_TXPWR_MAX_CCH */
-	bitvec_set_bit(&bv, L);
-
-	bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);
-	return bv.data_len;
-}
-
-/* GPRS Mobile Allocation as per TS 04.60 Chapter 12.10a:
-   < GPRS Mobile Allocation IE > ::=
-     < HSN : bit (6) >
-     { 0 | 1 < RFL number list : < RFL number list struct > > }
-     { 0 < MA_LENGTH : bit (6) >
-         < MA_BITMAP: bit (val(MA_LENGTH) + 1) >
-     | 1 { 0 | 1 <ARFCN index list : < ARFCN index list struct > > } } ;
-
-     < RFL number list struct > :: =
-       < RFL_NUMBER : bit (4) >
-       { 0 | 1 < RFL number list struct > } ;
-     < ARFCN index list struct > ::=
-       < ARFCN_INDEX : bit(6) >
-       { 0 | 1 < ARFCN index list struct > } ;
- */
-static int append_gprs_mobile_alloc(struct bitvec *bv)
-{
-	/* Hopping Sequence Number */
-	bitvec_set_uint(bv, 0, 6);
-
-	if (0) {
-		/* We want to use a RFL number list */
-		bitvec_set_bit(bv, 1);
-		/* FIXME: RFL number list */
-	} else
-		bitvec_set_bit(bv, 0);
-
-	if (0) {
-		/* We want to use a MA_BITMAP */
-		bitvec_set_bit(bv, 0);
-		/* FIXME: MA_LENGTH, MA_BITMAP, ... */
-	} else {
-		bitvec_set_bit(bv, 1);
-		if (0) {
-			/* We want to provide an ARFCN index list */
-			bitvec_set_bit(bv, 1);
-			/* FIXME */
-		} else
-			bitvec_set_bit(bv, 0);
-	}
-	return 0;
-}
-
-static int encode_t3192(unsigned int t3192)
-{
-	/* See also 3GPP TS 44.060
-	   Table 12.24.2: GPRS Cell Options information element details */
-	if (t3192 == 0)
-		return 3;
-	else if (t3192 <= 80)
-		return 4;
-	else if (t3192 <= 120)
-		return 5;
-	else if (t3192 <= 160)
-		return 6;
-	else if (t3192 <= 200)
-		return 7;
-	else if (t3192 <= 500)
-		return 0;
-	else if (t3192 <= 1000)
-		return 1;
-	else if (t3192 <= 1500)
-		return 2;
-	else
-		return -EINVAL;
-}
-
-static int encode_drx_timer(unsigned int drx)
-{
-	if (drx == 0)
-		return 0;
-	else if (drx == 1)
-		return 1;
-	else if (drx == 2)
-		return 2;
-	else if (drx <= 4)
-		return 3;
-	else if (drx <= 8)
-		return 4;
-	else if (drx <= 16)
-		return 5;
-	else if (drx <= 32)
-		return 6;
-	else if (drx <= 64)
-		return 7;
-	else
-		return -EINVAL;
-}
-
-/* GPRS Cell Options as per TS 04.60 Chapter 12.24
-	< GPRS Cell Options IE > ::=
-		< NMO : bit(2) >
-		< T3168 : bit(3) >
-		< T3192 : bit(3) >
-		< DRX_TIMER_MAX: bit(3) >
-		< ACCESS_BURST_TYPE: bit >
-		< CONTROL_ACK_TYPE : bit >
-		< BS_CV_MAX: bit(4) >
-		{ 0 | 1 < PAN_DEC : bit(3) >
-			< PAN_INC : bit(3) >
-			< PAN_MAX : bit(3) >
-		{ 0 | 1 < Extension Length : bit(6) >
-			< bit (val(Extension Length) + 1
-			& { < Extension Information > ! { bit ** = <no string> } } ;
-	< Extension Information > ::=
-		{ 0 | 1 < EGPRS_PACKET_CHANNEL_REQUEST : bit >
-			< BEP_PERIOD : bit(4) > }
-		< PFC_FEATURE_MODE : bit >
-		< DTM_SUPPORT : bit >
-		<BSS_PAGING_COORDINATION: bit >
-		<spare bit > ** ;
- */
-static int append_gprs_cell_opt(struct bitvec *bv,
-				const struct gprs_cell_options *gco)
-{
-	int t3192, drx_timer_max;
-
-	t3192 = encode_t3192(gco->t3192);
-	if (t3192 < 0)
-		return t3192;
-
-	drx_timer_max = encode_drx_timer(gco->drx_timer_max);
-	if (drx_timer_max < 0)
-		return drx_timer_max;
-
-	bitvec_set_uint(bv, gco->nmo, 2);
-
-	/* See also 3GPP TS 44.060
-	   Table 12.24.2: GPRS Cell Options information element details */
-	bitvec_set_uint(bv, gco->t3168 / 500 - 1, 3);
-
-	bitvec_set_uint(bv, t3192, 3);
-	bitvec_set_uint(bv, drx_timer_max, 3);
-	/* ACCESS_BURST_TYPE: Hard-code 8bit */
-	bitvec_set_bit(bv, 0);
-	/* CONTROL_ACK_TYPE: */
-	bitvec_set_bit(bv, gco->ctrl_ack_type_use_block);
-	bitvec_set_uint(bv, gco->bs_cv_max, 4);
-
-	if (0) {
-		/* hard-code no PAN_{DEC,INC,MAX} */
-		bitvec_set_bit(bv, 0);
-	} else {
-		/* copied from ip.access BSC protocol trace */
-		bitvec_set_bit(bv, 1);
-		bitvec_set_uint(bv, 1, 3);	/* DEC */
-		bitvec_set_uint(bv, 1, 3);	/* INC */
-		bitvec_set_uint(bv, 15, 3);	/* MAX */
-	}
-
-	if (!gco->ext_info_present) {
-		/* no extension information */
-		bitvec_set_bit(bv, 0);
-	} else {
-		/* extension information */
-		bitvec_set_bit(bv, 1);
-		if (!gco->ext_info.egprs_supported) {
-			/* 6bit length of extension */
-			bitvec_set_uint(bv, (1 + 3)-1, 6);
-			/* EGPRS supported in the cell */
-			bitvec_set_bit(bv, 0);
-		} else {
-			/* 6bit length of extension */
-			bitvec_set_uint(bv, (1 + 5 + 3)-1, 6);
-			/* EGPRS supported in the cell */
-			bitvec_set_bit(bv, 1);
-
-			/* 1bit EGPRS PACKET CHANNEL REQUEST */
-			if (gco->supports_egprs_11bit_rach == 0) {
-				bitvec_set_bit(bv,
-					gco->ext_info.use_egprs_p_ch_req);
-			} else {
-				bitvec_set_bit(bv, 0);
-			}
-
-			/* 4bit BEP PERIOD */
-			bitvec_set_uint(bv, gco->ext_info.bep_period, 4);
-		}
-		bitvec_set_bit(bv, gco->ext_info.pfc_supported);
-		bitvec_set_bit(bv, gco->ext_info.dtm_supported);
-		bitvec_set_bit(bv, gco->ext_info.bss_paging_coordination);
-	}
-
-	return 0;
-}
-
-static void append_gprs_pwr_ctrl_pars(struct bitvec *bv,
-				      const struct gprs_power_ctrl_pars *pcp)
-{
-	bitvec_set_uint(bv, pcp->alpha, 4);
-	bitvec_set_uint(bv, pcp->t_avg_w, 5);
-	bitvec_set_uint(bv, pcp->t_avg_t, 5);
-	bitvec_set_uint(bv, pcp->pc_meas_chan, 1);
-	bitvec_set_uint(bv, pcp->n_avg_i, 4);
-}
-
-/* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */
-int rest_octets_si13(uint8_t *data, const struct gsm48_si13_info *si13)
-{
-	struct bitvec bv;
-
-	memset(&bv, 0, sizeof(bv));
-	bv.data = data;
-	bv.data_len = 20;
-
-	if (0) {
-		/* No rest octets */
-		bitvec_set_bit(&bv, L);
-	} else {
-		bitvec_set_bit(&bv, H);
-		bitvec_set_uint(&bv, si13->bcch_change_mark, 3);
-		bitvec_set_uint(&bv, si13->si_change_field, 4);
-		if (1) {
-			bitvec_set_bit(&bv, 0);
-		} else {
-			bitvec_set_bit(&bv, 1);
-			bitvec_set_uint(&bv, si13->bcch_change_mark, 2);
-			append_gprs_mobile_alloc(&bv);
-		}
-		if (!si13->pbcch_present) {
-			/* PBCCH not present in cell */
-			bitvec_set_bit(&bv, 0);
-			bitvec_set_uint(&bv, si13->no_pbcch.rac, 8);
-			bitvec_set_bit(&bv, si13->no_pbcch.spgc_ccch_sup);
-			bitvec_set_uint(&bv, si13->no_pbcch.prio_acc_thr, 3);
-			bitvec_set_uint(&bv, si13->no_pbcch.net_ctrl_ord, 2);
-			append_gprs_cell_opt(&bv, &si13->cell_opts);
-			append_gprs_pwr_ctrl_pars(&bv, &si13->pwr_ctrl_pars);
-		} else {
-			/* PBCCH present in cell */
-			bitvec_set_bit(&bv, 1);
-			bitvec_set_uint(&bv, si13->pbcch.psi1_rep_per, 4);
-			/* PBCCH Descripiton */
-			bitvec_set_uint(&bv, si13->pbcch.pb, 4);
-			bitvec_set_uint(&bv, si13->pbcch.tsc, 3);
-			bitvec_set_uint(&bv, si13->pbcch.tn, 3);
-			switch (si13->pbcch.carrier_type) {
-			case PBCCH_BCCH:
-				bitvec_set_bit(&bv, 0);
-				bitvec_set_bit(&bv, 0);
-				break;
-			case PBCCH_ARFCN:
-				bitvec_set_bit(&bv, 0);
-				bitvec_set_bit(&bv, 1);
-				bitvec_set_uint(&bv, si13->pbcch.arfcn, 10);
-				break;
-			case PBCCH_MAIO:
-				bitvec_set_bit(&bv, 1);
-				bitvec_set_uint(&bv, si13->pbcch.maio, 6);
-				break;
-			}
-		}
-		/* 3GPP TS 44.018 Release 6 / 10.5.2.37b */
-		bitvec_set_bit(&bv, H);	/* added Release 99 */
-		/* claim our SGSN is compatible with Release 99, as EDGE and EGPRS
-		 * was only added in this Release */
-		bitvec_set_bit(&bv, 1);
-	}
-	bitvec_spare_padding(&bv, (bv.data_len*8)-1);
-	return bv.data_len;
-}
diff --git a/src/libbsc/system_information.c b/src/libbsc/system_information.c
deleted file mode 100644
index dcabbbd..0000000
--- a/src/libbsc/system_information.c
+++ /dev/null
@@ -1,1169 +0,0 @@
-/* GSM 04.08 System Information (SI) encoding and decoding
- * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
-
-/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2012 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/>.
- *
- */
-
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <netinet/in.h>
-#include <stdbool.h>
-
-#include <osmocom/core/bitvec.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/gsm/sysinfo.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/rest_octets.h>
-#include <openbsc/arfcn_range_encode.h>
-
-/*
- * DCS1800 and PCS1900 have overlapping ARFCNs. We would need to set the
- * ARFCN_PCS flag on the 1900 ARFCNs but this would increase cell_alloc
- * and other arrays to make sure (ARFCN_PCS + 1024)/8 ARFCNs fit into the
- * array. DCS1800 and PCS1900 can not be used at the same time so conserve
- * memory and do the below.
- */
-static int band_compatible(const struct gsm_bts *bts, int arfcn)
-{
-	enum gsm_band band = gsm_arfcn2band(arfcn);
-
-	/* normal case */
-	if (band == bts->band)
-		return 1;
-	/* deal with ARFCN_PCS not set */
-	if (band == GSM_BAND_1800 && bts->band == GSM_BAND_1900)
-		return 1;
-
-	return 0;
-}
-
-static int is_dcs_net(const struct gsm_bts *bts)
-{
-	if (bts->band == GSM_BAND_850)
-		return 0;
-	if (bts->band == GSM_BAND_1900)
-		return 0;
-	return 1;
-}
-
-/* Return p(n) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */
-unsigned range1024_p(unsigned n)
-{
-	switch (n) {
-	case 0: return 0;
-	case 1: return 10;
-	case 2: return 19;
-	case 3: return 28;
-	case 4: return 36;
-	case 5: return 44;
-	case 6: return 52;
-	case 7: return 60;
-	case 8: return 67;
-	case 9: return 74;
-	case 10: return 81;
-	case 11: return 88;
-	case 12: return 95;
-	case 13: return 102;
-	case 14: return 109;
-	case 15: return 116;
-	case 16: return 122;
-	default: return 0;
-	}
-}
-
-/* Return q(m) for given NR_OF_TDD_CELLS - see Table 9.1.54.1b, 3GPP TS 44.018 */
-unsigned range512_q(unsigned m)
-{
-	switch (m) {
-	case 0: return 0;
-	case 1: return 9;
-	case 2: return 17;
-	case 3: return 25;
-	case 4: return 32;
-	case 5: return 39;
-	case 6: return 46;
-	case 7: return 53;
-	case 8: return 59;
-	case 9: return 65;
-	case 10: return 71;
-	case 11: return 77;
-	case 12: return 83;
-	case 13: return 89;
-	case 14: return 95;
-	case 15: return 101;
-	case 16: return 106;
-	case 17: return 111;
-	case 18: return 116;
-	case 19: return 121;
-	case 20: return 126;
-	default: return 0;
-	}
-}
-
-size_t si2q_earfcn_count(const struct osmo_earfcn_si2q *e)
-{
-	unsigned i, ret = 0;
-
-	if (!e)
-		return 0;
-
-	for (i = 0; i < e->length; i++)
-		if (e->arfcn[i] != OSMO_EARFCN_INVALID)
-			ret++;
-
-	return ret;
-}
-
-/* generate SI2quater messages, return rest octets length of last generated message or negative error code */
-static int make_si2quaters(struct gsm_bts *bts, bool counting)
-{
-	int rc;
-	bool memory_exceeded = true;
-	struct gsm48_system_information_type_2quater *si2q;
-
-	for (bts->si2q_index = 0; bts->si2q_index < SI2Q_MAX_NUM; bts->si2q_index++) {
-		si2q = GSM_BTS_SI2Q(bts, bts->si2q_index);
-		if (counting) { /* that's legitimate if we're called for counting purpose: */
-			if (bts->si2q_count < bts->si2q_index)
-				bts->si2q_count = bts->si2q_index;
-		} else {
-			memset(si2q, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
-
-			si2q->header.l2_plen = GSM48_LEN2PLEN(22);
-			si2q->header.rr_protocol_discriminator = GSM48_PDISC_RR;
-			si2q->header.skip_indicator = 0;
-			si2q->header.system_information = GSM48_MT_RR_SYSINFO_2quater;
-		}
-
-		rc = rest_octets_si2quater(si2q->rest_octets, bts);
-		if (rc < 0)
-			return rc;
-
-		if (bts->u_offset >= bts->si_common.uarfcn_length &&
-		    bts->e_offset >= si2q_earfcn_count(&bts->si_common.si2quater_neigh_list)) {
-			memory_exceeded = false;
-			break;
-		}
-	}
-
-	if (memory_exceeded)
-		return -ENOMEM;
-
-	return rc;
-}
-
-/* we generate SI2q rest octets twice to get proper estimation but it's one time cost anyway */
-uint8_t si2q_num(struct gsm_bts *bts)
-{
-	int rc = make_si2quaters(bts, true);
-	uint8_t num = bts->si2q_index + 1; /* number of SI2quater messages */
-
-	/* N. B: si2q_num() should NEVER be called during actualSI2q rest octets generation
-	   we're not re-entrant because of the following code: */
-	bts->u_offset = 0;
-	bts->e_offset = 0;
-
-	if (rc < 0)
-		return 0xFF; /* return impossible index as an indicator of error in generating SI2quater */
-
-	return num;
-}
-
-/* 3GPP TS 44.018, Table 9.1.54.1 - prepend diversity bit to scrambling code */
-static inline uint16_t encode_fdd(uint16_t scramble, bool diversity)
-{
-	if (diversity)
-		return scramble | (1 << 9);
-	return scramble;
-}
-
-int bts_earfcn_add(struct gsm_bts *bts, uint16_t earfcn, uint8_t thresh_hi, uint8_t thresh_lo, uint8_t prio,
-		   uint8_t qrx, uint8_t meas_bw)
-{
-	struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list;
-	int r = osmo_earfcn_add(e, earfcn, (meas_bw < EARFCN_MEAS_BW_INVALID) ? meas_bw : OSMO_EARFCN_MEAS_INVALID);
-
-	if (r < 0)
-		return r;
-
-	if (e->thresh_hi && thresh_hi != e->thresh_hi)
-		r = 1;
-
-	e->thresh_hi = thresh_hi;
-
-	if (thresh_lo != EARFCN_THRESH_LOW_INVALID) {
-		if (e->thresh_lo_valid && e->thresh_lo != thresh_lo)
-			r = EARFCN_THRESH_LOW_INVALID;
-		e->thresh_lo = thresh_lo;
-		e->thresh_lo_valid = true;
-	}
-
-	if (qrx != EARFCN_QRXLV_INVALID) {
-		if (e->qrxlm_valid && e->qrxlm != qrx)
-			r = EARFCN_QRXLV_INVALID + 1;
-		e->qrxlm = qrx;
-		e->qrxlm_valid = true;
-	}
-
-	if (prio != EARFCN_PRIO_INVALID) {
-		if (e->prio_valid && e->prio != prio)
-			r = EARFCN_PRIO_INVALID;
-		e->prio = prio;
-		e->prio_valid = true;
-	}
-
-	return r;
-}
-
-int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble)
-{
-	uint16_t sc0 = encode_fdd(scramble, false), sc1 = encode_fdd(scramble, true),
-		*ual = bts->si_common.data.uarfcn_list,
-		*scl = bts->si_common.data.scramble_list;
-	size_t len = bts->si_common.uarfcn_length, i;
-	for (i = 0; i < len; i++) {
-		if (arfcn == ual[i] && (sc0 == scl[i] || sc1 == scl[i])) {
-			/* we rely on the assumption that (uarfcn, scramble)
-			   tuple is unique in the lists */
-			if (i != len - 1) { /* move the tail if necessary */
-				memmove(ual + i, ual + i + 1, 2 * (len - i + 1));
-				memmove(scl + i, scl + i + 1, 2 * (len - i + 1));
-			}
-			break;
-		}
-	}
-
-	if (i == len)
-		return -EINVAL;
-
-	bts->si_common.uarfcn_length--;
-	return 0;
-}
-
-int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, bool diversity)
-{
-	size_t len = bts->si_common.uarfcn_length, i, k = 0;
-	uint16_t scr, chk,
-		*ual = bts->si_common.data.uarfcn_list,
-		*scl = bts->si_common.data.scramble_list,
-		scramble1 = encode_fdd(scramble, true),
-		scramble0 = encode_fdd(scramble, false);
-
-	scr = diversity ? scramble1 : scramble0;
-	chk = diversity ? scramble0 : scramble1;
-
-	if (len == MAX_EARFCN_LIST)
-		return -ENOMEM;
-
-	for (i = 0; i < len; i++) /* find the position of arfcn if any */
-		if (arfcn == ual[i])
-			break;
-
-	for (k = 0; i < len; i++) {
-		if (arfcn == ual[i] && (scr == scl[i] || chk == scl[i]))
-			return -EADDRINUSE;
-		if (scr > scl[i])
-			k = i + 1;
-	}
-	/* we keep lists sorted by scramble code:
-	   insert into appropriate position and move the tail */
-	if (len - k) {
-		memmove(ual + k + 1, ual + k, (len - k) * 2);
-		memmove(scl + k + 1, scl + k, (len - k) * 2);
-	}
-
-	ual[k] = arfcn;
-	scl[k] = scr;
-	bts->si_common.uarfcn_length++;
-
-	if (si2q_num(bts) <= SI2Q_MAX_NUM) {
-		bts->si2q_count = si2q_num(bts) - 1;
-		return 0;
-	}
-
-	bts_uarfcn_del(bts, arfcn, scramble);
-	return -ENOSPC;
-}
-
-static inline int use_arfcn(const struct gsm_bts *bts, const bool bis, const bool ter,
-			const bool pgsm, const int arfcn)
-{
-	if (bts->force_combined_si)
-		return !bis && !ter;
-	if (!bis && !ter && band_compatible(bts, arfcn))
-		return 1;
-	/* Correct but somehow broken with either the nanoBTS or the iPhone5 */
-	if (bis && pgsm && band_compatible(bts, arfcn) && (arfcn < 1 || arfcn > 124))
-		return 1;
-	if (ter && !band_compatible(bts, arfcn))
-		return 1;
-	return 0;
-}
-
-/* Frequency Lists as per TS 04.08 10.5.2.13 */
-
-/* 10.5.2.13.2: Bit map 0 format */
-static int freq_list_bm0_set_arfcn(uint8_t *chan_list, unsigned int arfcn)
-{
-	unsigned int byte, bit;
-
-	if (arfcn > 124 || arfcn < 1) {
-		LOGP(DRR, LOGL_ERROR, "Bitmap 0 only supports ARFCN 1...124\n");
-		return -EINVAL;
-	}
-
-	/* the bitmask is from 1..124, not from 0..123 */
-	arfcn--;
-
-	byte = arfcn / 8;
-	bit = arfcn % 8;
-
-	chan_list[GSM48_CELL_CHAN_DESC_SIZE-1-byte] |= (1 << bit);
-
-	return 0;
-}
-
-/* 10.5.2.13.7: Variable bit map format */
-static int freq_list_bmrel_set_arfcn(uint8_t *chan_list, unsigned int arfcn)
-{
-	unsigned int byte, bit;
-	unsigned int min_arfcn;
-	unsigned int bitno;
-
-	min_arfcn = (chan_list[0] & 1) << 9;
-	min_arfcn |= chan_list[1] << 1;
-	min_arfcn |= (chan_list[2] >> 7) & 1;
-
-	/* The lower end of our bitmaks is always implicitly included */
-	if (arfcn == min_arfcn)
-		return 0;
-
-	if (((arfcn - min_arfcn) & 1023) > 111) {
-		LOGP(DRR, LOGL_ERROR, "arfcn(%u) > min(%u) + 111\n", arfcn, min_arfcn);
-		return -EINVAL;
-	}
-
-	bitno = (arfcn - min_arfcn) & 1023;
-	byte = bitno / 8;
-	bit = bitno % 8;
-
-	chan_list[2 + byte] |= 1 << (7 - bit);
-
-	return 0;
-}
-
-/* generate a variable bitmap */
-static inline int enc_freq_lst_var_bitmap(uint8_t *chan_list,
-				struct bitvec *bv, const struct gsm_bts *bts,
-				bool bis, bool ter, int min, bool pgsm)
-{
-	int i;
-
-	/* set it to 'Variable bitmap format' */
-	chan_list[0] = 0x8e;
-
-	chan_list[0] |= (min >> 9) & 1;
-	chan_list[1] = (min >> 1);
-	chan_list[2] = (min & 1) << 7;
-
-	for (i = 0; i < bv->data_len*8; i++) {
-		/* see notes in bitvec2freq_list */
-		if (bitvec_get_bit_pos(bv, i)
-		 && ((!bis && !ter && band_compatible(bts,i))
-		  || (bis && pgsm && band_compatible(bts,i) && (i < 1 || i > 124))
-		  || (ter && !band_compatible(bts, i)))) {
-			int rc = freq_list_bmrel_set_arfcn(chan_list, i);
-			if (rc < 0)
-				return rc;
-		}
-	}
-
-	return 0;
-}
-
-int range_encode(enum gsm48_range r, int *arfcns, int arfcns_used, int *w,
-		 int f0, uint8_t *chan_list)
-{
-	/*
-	 * Manipulate the ARFCN list according to the rules in J4 depending
-	 * on the selected range.
-	 */
-	int rc, f0_included;
-
-	range_enc_filter_arfcns(arfcns, arfcns_used, f0, &f0_included);
-
-	rc = range_enc_arfcns(r, arfcns, arfcns_used, w, 0);
-	if (rc < 0)
-		return rc;
-
-	/* Select the range and the amount of bits needed */
-	switch (r) {
-	case ARFCN_RANGE_128:
-		return range_enc_range128(chan_list, f0, w);
-	case ARFCN_RANGE_256:
-		return range_enc_range256(chan_list, f0, w);
-	case ARFCN_RANGE_512:
-		return range_enc_range512(chan_list, f0, w);
-	case ARFCN_RANGE_1024:
-		return range_enc_range1024(chan_list, f0, f0_included, w);
-	default:
-		return -ERANGE;
-	};
-
-	return f0_included;
-}
-
-/* generate a frequency list with the range 512 format */
-static inline int enc_freq_lst_range(uint8_t *chan_list,
-				struct bitvec *bv, const struct gsm_bts *bts,
-				bool bis, bool ter, bool pgsm)
-{
-	int arfcns[RANGE_ENC_MAX_ARFCNS];
-	int w[RANGE_ENC_MAX_ARFCNS];
-	int arfcns_used = 0;
-	int i, range, f0;
-
-	/*
-	 * Select ARFCNs according to the rules in bitvec2freq_list
-	 */
-	for (i = 0; i < bv->data_len * 8; ++i) {
-		/* More ARFCNs than the maximum */
-		if (arfcns_used > ARRAY_SIZE(arfcns))
-			return -1;
-		/* Check if we can select it? */
-		if (bitvec_get_bit_pos(bv, i) && use_arfcn(bts, bis, ter, pgsm, i))
-			arfcns[arfcns_used++] = i;
-	}
-
-	/*
-	 * Check if the given list of ARFCNs can be encoded.
-	 */
-	range = range_enc_determine_range(arfcns, arfcns_used, &f0);
-	if (range == ARFCN_RANGE_INVALID)
-		return -2;
-
-	memset(w, 0, sizeof(w));
-	return range_encode(range, arfcns, arfcns_used, w, f0, chan_list);
-}
-
-/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
-static int bitvec2freq_list(uint8_t *chan_list, struct bitvec *bv,
-			    const struct gsm_bts *bts, bool bis, bool ter)
-{
-	int i, rc, min = -1, max = -1, arfcns = 0;
-	bool pgsm = false;
-	memset(chan_list, 0, 16);
-
-	if (bts->band == GSM_BAND_900
-	 && bts->c0->arfcn >= 1 && bts->c0->arfcn <= 124)
-		pgsm = true;
-	/* P-GSM-only handsets only support 'bit map 0 format' */
-	if (!bis && !ter && pgsm) {
-		chan_list[0] = 0;
-
-		for (i = 0; i < bv->data_len*8; i++) {
-			if (i >= 1 && i <= 124
-			 && bitvec_get_bit_pos(bv, i)) {
-				rc = freq_list_bm0_set_arfcn(chan_list, i);
-				if (rc < 0)
-					return rc;
-			}
-		}
-		return 0;
-	}
-
-	for (i = 0; i < bv->data_len*8; i++) {
-		/* in case of SI2 or SI5 allow all neighbours in same band
-		 * in case of SI*bis, allow neighbours in same band ouside pgsm
-		 * in case of SI*ter, allow neighbours in different bands
-		 */
-		if (!bitvec_get_bit_pos(bv, i))
-			continue;
-		if (!use_arfcn(bts, bis, ter, pgsm, i))
-			continue;
-		/* count the arfcns we want to carry */
-		arfcns += 1;
-
-		/* 955..1023 < 0..885 */
-		if (min < 0)
-			min = i;
-		if (i >= 955 && min < 955)
-			min = i;
-		if (i >= 955 && min >= 955 && i < min)
-			min = i;
-		if (i < 955 && min < 955 && i < min)
-			min = i;
-		if (max < 0)
-			max = i;
-		if (i < 955 && max >= 955)
-			max = i;
-		if (i >= 955 && max >= 955 && i > max)
-			max = i;
-		if (i < 955 && max < 955 && i > max)
-			max = i;
-	}
-
-	if (max == -1) {
-		/* Empty set, use 'bit map 0 format' */
-		chan_list[0] = 0;
-		return 0;
-	}
-
-	/* Now find the best encoding */
-	if (((max - min) & 1023) <= 111)
-		return enc_freq_lst_var_bitmap(chan_list, bv, bts, bis,
-				ter, min, pgsm);
-
-	/* Attempt to do the range encoding */
-	rc = enc_freq_lst_range(chan_list, bv, bts, bis, ter, pgsm);
-	if (rc >= 0)
-		return 0;
-
-	LOGP(DRR, LOGL_ERROR, "min_arfcn=%u, max_arfcn=%u, arfcns=%d "
-		"can not generate ARFCN list", min, max, arfcns);
-	return -EINVAL;
-}
-
-/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
-/* static*/ int generate_cell_chan_list(uint8_t *chan_list, struct gsm_bts *bts)
-{
-	struct gsm_bts_trx *trx;
-	struct bitvec *bv = &bts->si_common.cell_alloc;
-
-	/* Zero-initialize the bit-vector */
-	memset(bv->data, 0, bv->data_len);
-
-	/* first we generate a bitvec of all TRX ARFCN's in our BTS */
-	llist_for_each_entry(trx, &bts->trx_list, list) {
-		unsigned int i, j;
-		/* Always add the TRX's ARFCN */
-		bitvec_set_bit_pos(bv, trx->arfcn, 1);
-		for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
-			struct gsm_bts_trx_ts *ts = &trx->ts[i];
-			/* Add any ARFCNs present in hopping channels */
-			for (j = 0; j < 1024; j++) {
-				if (bitvec_get_bit_pos(&ts->hopping.arfcns, j))
-					bitvec_set_bit_pos(bv, j, 1);
-			}
-		}
-	}
-
-	/* then we generate a GSM 04.08 frequency list from the bitvec */
-	return bitvec2freq_list(chan_list, bv, bts, false, false);
-}
-
-/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
-static int generate_bcch_chan_list(uint8_t *chan_list, struct gsm_bts *bts,
-	bool si5, bool bis, bool ter)
-{
-	struct gsm_bts *cur_bts;
-	struct bitvec *bv;
-
-	if (si5 && bts->neigh_list_manual_mode == NL_MODE_MANUAL_SI5SEP)
-		bv = &bts->si_common.si5_neigh_list;
-	else
-		bv = &bts->si_common.neigh_list;
-
-	/* Generate list of neighbor cells if we are in automatic mode */
-	if (bts->neigh_list_manual_mode == NL_MODE_AUTOMATIC) {
-		/* Zero-initialize the bit-vector */
-		memset(bv->data, 0, bv->data_len);
-
-		/* first we generate a bitvec of the BCCH ARFCN's in our BSC */
-		llist_for_each_entry(cur_bts, &bts->network->bts_list, list) {
-			if (cur_bts == bts)
-				continue;
-			bitvec_set_bit_pos(bv, cur_bts->c0->arfcn, 1);
-		}
-	}
-
-	/* then we generate a GSM 04.08 frequency list from the bitvec */
-	return bitvec2freq_list(chan_list, bv, bts, bis, ter);
-}
-
-static int list_arfcn(uint8_t *chan_list, uint8_t mask, char *text)
-{
-	int n = 0, i;
-	struct gsm_sysinfo_freq freq[1024];
-
-	memset(freq, 0, sizeof(freq));
-	gsm48_decode_freq_list(freq, chan_list, 16, 0xce, 1);
-	for (i = 0; i < 1024; i++) {
-		if (freq[i].mask) {
-			if (!n)
-				LOGP(DRR, LOGL_INFO, "%s", text);
-			LOGPC(DRR, LOGL_INFO, " %d", i);
-			n++;
-		}
-	}
-	if (n)
-		LOGPC(DRR, LOGL_INFO, "\n");
-
-	return n;
-}
-
-static int generate_si1(enum osmo_sysinfo_type t, struct gsm_bts *bts)
-{
-	int rc;
-	struct gsm48_system_information_type_1 *si1 = (struct gsm48_system_information_type_1 *) GSM_BTS_SI(bts, t);
-
-	memset(si1, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
-
-	si1->header.l2_plen = GSM48_LEN2PLEN(21);
-	si1->header.rr_protocol_discriminator = GSM48_PDISC_RR;
-	si1->header.skip_indicator = 0;
-	si1->header.system_information = GSM48_MT_RR_SYSINFO_1;
-
-	rc = generate_cell_chan_list(si1->cell_channel_description, bts);
-	if (rc < 0)
-		return rc;
-	list_arfcn(si1->cell_channel_description, 0xce, "Serving cell:");
-
-	si1->rach_control = bts->si_common.rach_control;
-
-	/*
-	 * SI1 Rest Octets (10.5.2.32), contains NCH position and band
-	 * indicator but that is not in the 04.08.
-	 */
-	rc = rest_octets_si1(si1->rest_octets, NULL, is_dcs_net(bts));
-
-	return sizeof(*si1) + rc;
-}
-
-static int generate_si2(enum osmo_sysinfo_type t, struct gsm_bts *bts)
-{
-	int rc;
-	struct gsm48_system_information_type_2 *si2 = (struct gsm48_system_information_type_2 *) GSM_BTS_SI(bts, t);
-
-	memset(si2, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
-
-	si2->header.l2_plen = GSM48_LEN2PLEN(22);
-	si2->header.rr_protocol_discriminator = GSM48_PDISC_RR;
-	si2->header.skip_indicator = 0;
-	si2->header.system_information = GSM48_MT_RR_SYSINFO_2;
-
-	rc = generate_bcch_chan_list(si2->bcch_frequency_list, bts, false, false, false);
-	if (rc < 0)
-		return rc;
-	list_arfcn(si2->bcch_frequency_list, 0xce,
-		"SI2 Neighbour cells in same band:");
-
-	si2->ncc_permitted = bts->si_common.ncc_permitted;
-	si2->rach_control = bts->si_common.rach_control;
-
-	return sizeof(*si2);
-}
-
-static int generate_si2bis(enum osmo_sysinfo_type t, struct gsm_bts *bts)
-{
-	int rc;
-	struct gsm48_system_information_type_2bis *si2b =
-		(struct gsm48_system_information_type_2bis *) GSM_BTS_SI(bts, t);
-	int n;
-
-	memset(si2b, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
-
-	si2b->header.l2_plen = GSM48_LEN2PLEN(22);
-	si2b->header.rr_protocol_discriminator = GSM48_PDISC_RR;
-	si2b->header.skip_indicator = 0;
-	si2b->header.system_information = GSM48_MT_RR_SYSINFO_2bis;
-
-	rc = generate_bcch_chan_list(si2b->bcch_frequency_list, bts, false, true, false);
-	if (rc < 0)
-		return rc;
-	n = list_arfcn(si2b->bcch_frequency_list, 0xce,
-		"Neighbour cells in same band, but outside P-GSM:");
-	if (n) {
-		/* indicate in SI2 and SI2bis: there is an extension */
-		struct gsm48_system_information_type_2 *si2 =
-			(struct gsm48_system_information_type_2 *) GSM_BTS_SI(bts, SYSINFO_TYPE_2);
-		si2->bcch_frequency_list[0] |= 0x20;
-		si2b->bcch_frequency_list[0] |= 0x20;
-	} else
-		bts->si_valid &= ~(1 << SYSINFO_TYPE_2bis);
-
-	si2b->rach_control = bts->si_common.rach_control;
-
-	return sizeof(*si2b);
-}
-
-static int generate_si2ter(enum osmo_sysinfo_type t, struct gsm_bts *bts)
-{
-	int rc;
-	struct gsm48_system_information_type_2ter *si2t =
-		(struct gsm48_system_information_type_2ter *) GSM_BTS_SI(bts, t);
-	int n;
-
-	memset(si2t, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
-
-	si2t->header.l2_plen = GSM48_LEN2PLEN(22);
-	si2t->header.rr_protocol_discriminator = GSM48_PDISC_RR;
-	si2t->header.skip_indicator = 0;
-	si2t->header.system_information = GSM48_MT_RR_SYSINFO_2ter;
-
-	rc = generate_bcch_chan_list(si2t->ext_bcch_frequency_list, bts, false, false, true);
-	if (rc < 0)
-		return rc;
-	n = list_arfcn(si2t->ext_bcch_frequency_list, 0x8e,
-		"Neighbour cells in different band:");
-	if (!n)
-		bts->si_valid &= ~(1 << SYSINFO_TYPE_2ter);
-
-	return sizeof(*si2t);
-}
-
-/* SI2quater messages are optional - we only generate them when neighbor UARFCNs or EARFCNs are configured */
-static inline bool si2quater_not_needed(struct gsm_bts *bts)
-{
-	unsigned i = MAX_EARFCN_LIST;
-
-	if (bts->si_common.si2quater_neigh_list.arfcn)
-		for (i = 0; i < MAX_EARFCN_LIST; i++)
-			if (bts->si_common.si2quater_neigh_list.arfcn[i] != OSMO_EARFCN_INVALID)
-				break;
-
-	if (!bts->si_common.uarfcn_length && i == MAX_EARFCN_LIST) {
-		bts->si_valid &= ~(1 << SYSINFO_TYPE_2quater); /* mark SI2q as invalid if no (E|U)ARFCNs are present */
-		return true;
-	}
-
-	return false;
-}
-
-static int generate_si2quater(enum osmo_sysinfo_type t, struct gsm_bts *bts)
-{
-	int rc;
-	struct gsm48_system_information_type_2quater *si2q;
-
-	if (si2quater_not_needed(bts)) /* generate rest_octets for SI2q only when necessary */
-		return GSM_MACBLOCK_LEN;
-
-	bts->u_offset = 0;
-	bts->e_offset = 0;
-	bts->si2q_index = 0;
-	bts->si2q_count = si2q_num(bts) - 1;
-
-	rc = make_si2quaters(bts, false);
-	if (rc < 0)
-		return rc;
-
-	OSMO_ASSERT(bts->si2q_count == bts->si2q_index);
-	OSMO_ASSERT(bts->si2q_count <= SI2Q_MAX_NUM);
-
-	return sizeof(*si2q) + rc;
-}
-
-static struct gsm48_si_ro_info si_info = {
-	.selection_params = {
-		.present = 0,
-	},
-	.power_offset = {
-		.present = 0,
-	},
-	.si2ter_indicator = 0,
-	.early_cm_ctrl = 1,
-	.scheduling = {
-		.present = 0,
-	},
-	.gprs_ind = {
-		.si13_position = 0,
-		.ra_colour = 0,
-		.present = 1,
-	},
-	.si2quater_indicator = 0,
-	.lsa_params = {
-		.present = 0,
-	},
-	.cell_id = 0,	/* FIXME: doesn't the bts have this? */
-	.break_ind = 0,
-};
-
-static int generate_si3(enum osmo_sysinfo_type t, struct gsm_bts *bts)
-{
-	int rc;
-	struct gsm48_system_information_type_3 *si3 = (struct gsm48_system_information_type_3 *) GSM_BTS_SI(bts, t);
-
-	memset(si3, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
-
-	si3->header.l2_plen = GSM48_LEN2PLEN(18);
-	si3->header.rr_protocol_discriminator = GSM48_PDISC_RR;
-	si3->header.skip_indicator = 0;
-	si3->header.system_information = GSM48_MT_RR_SYSINFO_3;
-
-	si3->cell_identity = htons(bts->cell_identity);
-	gsm48_generate_lai(&si3->lai, bts->network->country_code,
-			   bts->network->network_code,
-			   bts->location_area_code);
-	si3->control_channel_desc = bts->si_common.chan_desc;
-	si3->cell_options = bts->si_common.cell_options;
-	si3->cell_sel_par = bts->si_common.cell_sel_par;
-	si3->rach_control = bts->si_common.rach_control;
-
-	/* allow/disallow DTXu */
-	gsm48_set_dtx(&si3->cell_options, bts->dtxu, bts->dtxu, true);
-
-	if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2ter)) {
-		LOGP(DRR, LOGL_INFO, "SI 2ter is included.\n");
-		si_info.si2ter_indicator = 1;
-	} else {
-		si_info.si2ter_indicator = 0;
-	}
-	if (GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2quater)) {
-		LOGP(DRR, LOGL_INFO, "SI 2quater is included, based on %zu EARFCNs and %zu UARFCNs.\n",
-		     si2q_earfcn_count(&bts->si_common.si2quater_neigh_list), bts->si_common.uarfcn_length);
-		si_info.si2quater_indicator = 1;
-	} else {
-		si_info.si2quater_indicator = 0;
-	}
-	si_info.early_cm_ctrl = bts->early_classmark_allowed;
-
-	/* SI3 Rest Octets (10.5.2.34), containing
-		CBQ, CELL_RESELECT_OFFSET, TEMPORARY_OFFSET, PENALTY_TIME
-		Power Offset, 2ter Indicator, Early Classmark Sending,
-		Scheduling if and WHERE, GPRS Indicator, SI13 position */
-	rc = rest_octets_si3(si3->rest_octets, &si_info);
-
-	return sizeof(*si3) + rc;
-}
-
-static int generate_si4(enum osmo_sysinfo_type t, struct gsm_bts *bts)
-{
-	int rc;
-	struct gsm48_system_information_type_4 *si4 = (struct gsm48_system_information_type_4 *) GSM_BTS_SI(bts, t);
-	struct gsm_lchan *cbch_lchan;
-	uint8_t *restoct = si4->data;
-
-	/* length of all IEs present except SI4 rest octets and l2_plen */
-	int l2_plen = sizeof(*si4) - 1;
-
-	memset(si4, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
-
-	si4->header.rr_protocol_discriminator = GSM48_PDISC_RR;
-	si4->header.skip_indicator = 0;
-	si4->header.system_information = GSM48_MT_RR_SYSINFO_4;
-
-	gsm48_generate_lai(&si4->lai, bts->network->country_code,
-			   bts->network->network_code,
-			   bts->location_area_code);
-	si4->cell_sel_par = bts->si_common.cell_sel_par;
-	si4->rach_control = bts->si_common.rach_control;
-
-	/* Optional: CBCH Channel Description + CBCH Mobile Allocation */
-	cbch_lchan = gsm_bts_get_cbch(bts);
-	if (cbch_lchan) {
-		struct gsm48_chan_desc cd;
-		gsm48_lchan2chan_desc(&cd, cbch_lchan);
-		tv_fixed_put(si4->data, GSM48_IE_CBCH_CHAN_DESC, 3,
-			     (uint8_t *) &cd);
-		l2_plen += 3 + 1;
-		restoct += 3 + 1;
-		/* we don't use hopping and thus don't need a CBCH MA */
-	}
-
-	si4->header.l2_plen = GSM48_LEN2PLEN(l2_plen);
-
-	/* SI4 Rest Octets (10.5.2.35), containing
-		Optional Power offset, GPRS Indicator,
-		Cell Identity, LSA ID, Selection Parameter */
-	rc = rest_octets_si4(restoct, &si_info, (uint8_t *)GSM_BTS_SI(bts, t) + GSM_MACBLOCK_LEN - restoct);
-
-	return l2_plen + 1 + rc;
-}
-
-static int generate_si5(enum osmo_sysinfo_type t, struct gsm_bts *bts)
-{
-	struct gsm48_system_information_type_5 *si5;
-	uint8_t *output = GSM_BTS_SI(bts, t);
-	int rc, l2_plen = 18;
-
-	memset(output, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
-
-	/* ip.access nanoBTS needs l2_plen!! */
-	switch (bts->type) {
-	case GSM_BTS_TYPE_NANOBTS:
-	case GSM_BTS_TYPE_OSMOBTS:
-		*output++ = GSM48_LEN2PLEN(l2_plen);
-		l2_plen++;
-		break;
-	default:
-		break;
-	}
-
-	si5 = (struct gsm48_system_information_type_5 *) GSM_BTS_SI(bts, t);
-
-	/* l2 pseudo length, not part of msg: 18 */
-	si5->rr_protocol_discriminator = GSM48_PDISC_RR;
-	si5->skip_indicator = 0;
-	si5->system_information = GSM48_MT_RR_SYSINFO_5;
-	rc = generate_bcch_chan_list(si5->bcch_frequency_list, bts, true, false, false);
-	if (rc < 0)
-		return rc;
-	list_arfcn(si5->bcch_frequency_list, 0xce,
-		"SI5 Neighbour cells in same band:");
-
-	/* 04.08 9.1.37: L2 Pseudo Length of 18 */
-	return l2_plen;
-}
-
-static int generate_si5bis(enum osmo_sysinfo_type t, struct gsm_bts *bts)
-{
-	struct gsm48_system_information_type_5bis *si5b;
-	uint8_t *output = GSM_BTS_SI(bts, t);
-	int rc, l2_plen = 18;
-	int n;
-
-	memset(output, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
-
-	/* ip.access nanoBTS needs l2_plen!! */
-	switch (bts->type) {
-	case GSM_BTS_TYPE_NANOBTS:
-	case GSM_BTS_TYPE_OSMOBTS:
-		*output++ = GSM48_LEN2PLEN(l2_plen);
-		l2_plen++;
-		break;
-	default:
-		break;
-	}
-
-	si5b = (struct gsm48_system_information_type_5bis *) GSM_BTS_SI(bts, t);
-
-	/* l2 pseudo length, not part of msg: 18 */
-	si5b->rr_protocol_discriminator = GSM48_PDISC_RR;
-	si5b->skip_indicator = 0;
-	si5b->system_information = GSM48_MT_RR_SYSINFO_5bis;
-	rc = generate_bcch_chan_list(si5b->bcch_frequency_list, bts, true, true, false);
-	if (rc < 0)
-		return rc;
-	n = list_arfcn(si5b->bcch_frequency_list, 0xce,
-		"Neighbour cells in same band, but outside P-GSM:");
-	if (n) {
-		/* indicate in SI5 and SI5bis: there is an extension */
-		struct gsm48_system_information_type_5 *si5 =
-			(struct gsm48_system_information_type_5 *) GSM_BTS_SI(bts, SYSINFO_TYPE_5);
-		si5->bcch_frequency_list[0] |= 0x20;
-		si5b->bcch_frequency_list[0] |= 0x20;
-	} else
-		bts->si_valid &= ~(1 << SYSINFO_TYPE_5bis);
-
-	/* 04.08 9.1.37: L2 Pseudo Length of 18 */
-	return l2_plen;
-}
-
-static int generate_si5ter(enum osmo_sysinfo_type t, struct gsm_bts *bts)
-{
-	struct gsm48_system_information_type_5ter *si5t;
-	uint8_t *output = GSM_BTS_SI(bts, t);
-	int rc, l2_plen = 18;
-	int n;
-
-	memset(output, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
-
-	/* ip.access nanoBTS needs l2_plen!! */
-	switch (bts->type) {
-	case GSM_BTS_TYPE_NANOBTS:
-	case GSM_BTS_TYPE_OSMOBTS:
-		*output++ = GSM48_LEN2PLEN(l2_plen);
-		l2_plen++;
-		break;
-	default:
-		break;
-	}
-
-	si5t = (struct gsm48_system_information_type_5ter *) GSM_BTS_SI(bts, t);
-
-	/* l2 pseudo length, not part of msg: 18 */
-	si5t->rr_protocol_discriminator = GSM48_PDISC_RR;
-	si5t->skip_indicator = 0;
-	si5t->system_information = GSM48_MT_RR_SYSINFO_5ter;
-	rc = generate_bcch_chan_list(si5t->bcch_frequency_list, bts, true, false, true);
-	if (rc < 0)
-		return rc;
-	n = list_arfcn(si5t->bcch_frequency_list, 0x8e,
-		"Neighbour cells in different band:");
-	if (!n)
-		bts->si_valid &= ~(1 << SYSINFO_TYPE_5ter);
-
-	/* 04.08 9.1.37: L2 Pseudo Length of 18 */
-	return l2_plen;
-}
-
-static int generate_si6(enum osmo_sysinfo_type t, struct gsm_bts *bts)
-{
-	struct gsm48_system_information_type_6 *si6;
-	uint8_t *output = GSM_BTS_SI(bts, t);
-	int l2_plen = 11;
-	int rc;
-
-	memset(output, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
-
-	/* ip.access nanoBTS needs l2_plen!! */
-	switch (bts->type) {
-	case GSM_BTS_TYPE_NANOBTS:
-	case GSM_BTS_TYPE_OSMOBTS:
-		*output++ = GSM48_LEN2PLEN(l2_plen);
-		l2_plen++;
-		break;
-	default:
-		break;
-	}
-
-	si6 = (struct gsm48_system_information_type_6 *) GSM_BTS_SI(bts, t);
-
-	/* l2 pseudo length, not part of msg: 11 */
-	si6->rr_protocol_discriminator = GSM48_PDISC_RR;
-	si6->skip_indicator = 0;
-	si6->system_information = GSM48_MT_RR_SYSINFO_6;
-	si6->cell_identity = htons(bts->cell_identity);
-	gsm48_generate_lai(&si6->lai, bts->network->country_code,
-			   bts->network->network_code,
-			   bts->location_area_code);
-	si6->cell_options = bts->si_common.cell_options;
-	si6->ncc_permitted = bts->si_common.ncc_permitted;
-	/* allow/disallow DTXu */
-	gsm48_set_dtx(&si6->cell_options, bts->dtxu, bts->dtxu, false);
-
-	/* SI6 Rest Octets: 10.5.2.35a: PCH / NCH info, VBS/VGCS options */
-	rc = rest_octets_si6(si6->rest_octets, is_dcs_net(bts));
-
-	return l2_plen + rc;
-}
-
-static struct gsm48_si13_info si13_default = {
-	.cell_opts = {
-		.nmo 		= GPRS_NMO_II,
-		.t3168		= 2000,
-		.t3192		= 1500,
-		.drx_timer_max	= 3,
-		.bs_cv_max	= 15,
-		.ctrl_ack_type_use_block = true,
-		.ext_info_present = 0,
-		.supports_egprs_11bit_rach = 0,
-		.ext_info = {
-			/* The values below are just guesses ! */
-			.egprs_supported = 0,
-			.use_egprs_p_ch_req = 1,
-			.bep_period = 5,
-			.pfc_supported = 0,
-			.dtm_supported = 0,
-			.bss_paging_coordination = 0,
-		},
-	},
-	.pwr_ctrl_pars = {
-		.alpha		= 0,	/* a = 0.0 */
-		.t_avg_w	= 16,
-		.t_avg_t	= 16,
-		.pc_meas_chan	= 0, 	/* downling measured on CCCH */
-		.n_avg_i	= 8,
-	},
-	.bcch_change_mark	= 1,
-	.si_change_field	= 0,
-	.pbcch_present		= 0,
-	{
-		.no_pbcch = {
-			.rac		= 0,	/* needs to be patched */
-			.spgc_ccch_sup 	= 0,
-			.net_ctrl_ord	= 0,
-			.prio_acc_thr	= 6,
-		},
-	},
-};
-
-static int generate_si13(enum osmo_sysinfo_type t, struct gsm_bts *bts)
-{
-	struct gsm48_system_information_type_13 *si13 =
-		(struct gsm48_system_information_type_13 *) GSM_BTS_SI(bts, t);
-	int ret;
-
-	memset(si13, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
-
-	si13->header.rr_protocol_discriminator = GSM48_PDISC_RR;
-	si13->header.skip_indicator = 0;
-	si13->header.system_information = GSM48_MT_RR_SYSINFO_13;
-
-	si13_default.no_pbcch.rac = bts->gprs.rac;
-	si13_default.no_pbcch.net_ctrl_ord = bts->gprs.net_ctrl_ord;
-
-	si13_default.cell_opts.ctrl_ack_type_use_block =
-		bts->gprs.ctrl_ack_type_use_block;
-
-	/* Information about the other SIs */
-	si13_default.bcch_change_mark = bts->bcch_change_mark;
-	si13_default.cell_opts.supports_egprs_11bit_rach =
-					bts->gprs.supports_egprs_11bit_rach;
-
-	ret = rest_octets_si13(si13->rest_octets, &si13_default);
-	if (ret < 0)
-		return ret;
-
-	/* length is coded in bit 2 an up */
-	si13->header.l2_plen = 0x01;
-
-	return sizeof (*si13) + ret;
-}
-
-typedef int (*gen_si_fn_t)(enum osmo_sysinfo_type t, struct gsm_bts *bts);
-
-static const gen_si_fn_t gen_si_fn[_MAX_SYSINFO_TYPE] = {
-	[SYSINFO_TYPE_1] = &generate_si1,
-	[SYSINFO_TYPE_2] = &generate_si2,
-	[SYSINFO_TYPE_2bis] = &generate_si2bis,
-	[SYSINFO_TYPE_2ter] = &generate_si2ter,
-	[SYSINFO_TYPE_2quater] = &generate_si2quater,
-	[SYSINFO_TYPE_3] = &generate_si3,
-	[SYSINFO_TYPE_4] = &generate_si4,
-	[SYSINFO_TYPE_5] = &generate_si5,
-	[SYSINFO_TYPE_5bis] = &generate_si5bis,
-	[SYSINFO_TYPE_5ter] = &generate_si5ter,
-	[SYSINFO_TYPE_6] = &generate_si6,
-	[SYSINFO_TYPE_13] = &generate_si13,
-};
-
-int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type si_type)
-{
-	gen_si_fn_t gen_si;
-
-	switch (bts->gprs.mode) {
-	case BTS_GPRS_EGPRS:
-		si13_default.cell_opts.ext_info_present = 1;
-		si13_default.cell_opts.ext_info.egprs_supported = 1;
-		/* fallthrough */
-	case BTS_GPRS_GPRS:
-		si_info.gprs_ind.present = 1;
-		break;
-	case BTS_GPRS_NONE:
-		si_info.gprs_ind.present = 0;
-		break;
-	}
-
-	memcpy(&si_info.selection_params,
-	       &bts->si_common.cell_ro_sel_par,
-	       sizeof(struct gsm48_si_selection_params));
-
-	gen_si = gen_si_fn[si_type];
-	if (!gen_si)
-		return -EINVAL;
-
-	return gen_si(si_type, bts);
-}
diff --git a/src/libcommon-cs/Makefile.am b/src/libcommon-cs/Makefile.am
deleted file mode 100644
index 21c2745..0000000
--- a/src/libcommon-cs/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	-I$(top_builddir) \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOVTY_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(NULL)
-
-noinst_LIBRARIES = libcommon-cs.a
-
-libcommon_cs_a_SOURCES = \
-	a_reset.c \
-	common_cs.c \
-	common_cs_vty.c
diff --git a/src/libcommon-cs/a_reset.c b/src/libcommon-cs/a_reset.c
deleted file mode 100644
index c0294c7..0000000
--- a/src/libcommon-cs/a_reset.c
+++ /dev/null
@@ -1,224 +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/>.
- *
- */
-
-#include <osmocom/core/logging.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/timer.h>
-#include <osmocom/core/fsm.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <openbsc/debug.h>
-#include <openbsc/bsc_msc_data.h>
-#include <openbsc/osmo_bsc_sigtran.h>
-
-#define RESET_RESEND_INTERVAL 2	/* sec */
-#define RESET_RESEND_TIMER_NO 1234	/* FIXME: dig out the real timer number */
-#define BAD_CONNECTION_THRESOLD 3	/* connection failures */
-
-enum fsm_states {
-	ST_DISC,		/* Disconnected from remote end */
-	ST_CONN,		/* We have a confirmed connection */
-};
-
-static const struct value_string fsm_state_names[] = {
-	{ST_DISC, "ST_DISC (disconnected)"},
-	{ST_CONN, "ST_CONN (connected)"},
-	{0, NULL},
-};
-
-enum fsm_evt {
-	EV_RESET_ACK,		/* got reset acknowlegement from remote end */
-	EV_N_DISCONNECT,	/* lost a connection */
-	EV_N_CONNECT,		/* made a successful connection */
-};
-
-static const struct value_string fsm_evt_names[] = {
-	{EV_RESET_ACK, "EV_RESET_ACK"},
-	{EV_N_DISCONNECT, "EV_N_DISCONNECT"},
-	{EV_N_CONNECT, "EV_N_CONNECT"},
-	{0, NULL},
-};
-
-/* Disconnected state */
-static void fsm_disc_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct a_reset_ctx *reset = (struct a_reset_ctx *)data;
-	OSMO_ASSERT(reset);
-
-	LOGP(DMSC, LOGL_NOTICE, "(%s) fsm-state (msc-reset): %s, fsm-event: %s\n", reset->name,
-	     get_value_string(fsm_state_names, ST_CONN), get_value_string(fsm_evt_names, event));
-
-	reset->conn_loss_counter = 0;
-	osmo_fsm_inst_state_chg(fi, ST_CONN, 0, 0);
-}
-
-/* Connected state */
-static void fsm_conn_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct a_reset_ctx *reset = (struct a_reset_ctx *)data;
-	OSMO_ASSERT(reset);
-
-	LOGP(DMSC, LOGL_NOTICE, "(%s) fsm-state (msc-reset): %s, fsm-event: %s\n", reset->name,
-	     get_value_string(fsm_state_names, ST_CONN), get_value_string(fsm_evt_names, event));
-
-	switch (event) {
-	case EV_N_DISCONNECT:
-		if (reset->conn_loss_counter >= BAD_CONNECTION_THRESOLD) {
-			LOGP(DMSC, LOGL_NOTICE, "(%s) SIGTRAN connection down, reconnecting...\n", reset->name);
-			osmo_fsm_inst_state_chg(fi, ST_DISC, RESET_RESEND_INTERVAL, RESET_RESEND_TIMER_NO);
-		} else
-			reset->conn_loss_counter++;
-		break;
-	case EV_N_CONNECT:
-		reset->conn_loss_counter = 0;
-		break;
-	}
-}
-
-/* Timer callback to retransmit the reset signal */
-static int fsm_reset_ack_timeout_cb(struct osmo_fsm_inst *fi)
-{
-	struct a_reset_ctx *reset = (struct a_reset_ctx *)fi->priv;
-
-	LOGP(DMSC, LOGL_NOTICE, "(%s) reset-ack timeout (T%i) in state %s, resending...\n", reset->name, fi->T,
-	     get_value_string(fsm_state_names, fi->state));
-
-	reset->cb(reset->priv);
-
-	osmo_fsm_inst_state_chg(fi, ST_DISC, RESET_RESEND_INTERVAL, RESET_RESEND_TIMER_NO);
-	return 0;
-}
-
-static struct osmo_fsm_state fsm_states[] = {
-	[ST_DISC] = {
-		     .in_event_mask = (1 << EV_RESET_ACK),
-		     .out_state_mask = (1 << ST_DISC) | (1 << ST_CONN),
-		     .name = "DISC",
-		     .action = fsm_disc_cb,
-		     },
-	[ST_CONN] = {
-		     .in_event_mask = (1 << EV_N_DISCONNECT) | (1 << EV_N_CONNECT),
-		     .out_state_mask = (1 << ST_DISC) | (1 << ST_CONN),
-		     .name = "CONN",
-		     .action = fsm_conn_cb,
-		     },
-};
-
-/* State machine definition */
-static struct osmo_fsm fsm = {
-	.name = "FSM RESET",
-	.states = fsm_states,
-	.num_states = ARRAY_SIZE(fsm_states),
-	.log_subsys = DMSC,
-	.timer_cb = fsm_reset_ack_timeout_cb,
-};
-
-/* 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)
-{
-	OSMO_ASSERT(name);
-
-	struct a_reset_ctx *reset;
-
-	/* Register the fsm description (if not already done) */
-	if (osmo_fsm_find_by_name(fsm.name) != &fsm)
-		osmo_fsm_register(&fsm);
-
-	/* Allocate and configure a new fsm instance */
-	reset = talloc_zero(ctx, struct a_reset_ctx);
-	OSMO_ASSERT(reset);
-	reset->priv = priv;
-	reset->cb = cb;
-	strncpy(reset->name, name, sizeof(reset->name));
-	reset->conn_loss_counter = 0;
-	reset->fsm = osmo_fsm_inst_alloc(&fsm, NULL, NULL, LOGL_DEBUG, "FSM RESET INST");
-	OSMO_ASSERT(reset->fsm);
-	reset->fsm->priv = reset;
-	LOGP(DMSC, LOGL_NOTICE, "(%s) reset handler fsm created.\n", reset->name);
-
-	/* kick off reset-ack sending mechanism */
-	osmo_fsm_inst_state_chg(reset->fsm, ST_DISC, RESET_RESEND_INTERVAL, RESET_RESEND_TIMER_NO);
-
-	return reset;
-}
-
-/* Tear down state machine */
-void a_reset_free(struct a_reset_ctx *reset)
-{
-	OSMO_ASSERT(reset);
-	OSMO_ASSERT(reset->fsm);
-
-	osmo_fsm_inst_free(reset->fsm);
-	reset->fsm = NULL;
-
-	memset(reset, 0, sizeof(*reset));
-	talloc_free(reset);
-
-	LOGP(DMSC, LOGL_NOTICE, "(%s) reset handler fsm destroyed.\n", reset->name);
-}
-
-/* Confirm that we sucessfully received a reset acknowlege message */
-void a_reset_ack_confirm(struct a_reset_ctx *reset)
-{
-	OSMO_ASSERT(reset);
-	OSMO_ASSERT(reset->fsm);
-
-	osmo_fsm_inst_dispatch(reset->fsm, EV_RESET_ACK, reset);
-}
-
-/* Report a failed connection */
-void a_reset_conn_fail(struct a_reset_ctx *reset)
-{
-	/* If no reset context is supplied, just drop the info */
-	if (!reset)
-		return;
-
-	OSMO_ASSERT(reset->fsm);
-
-	osmo_fsm_inst_dispatch(reset->fsm, EV_N_DISCONNECT, reset);
-}
-
-/* Report a successful connection */
-void a_reset_conn_success(struct a_reset_ctx *reset)
-{
-	/* If no reset context is supplied, just drop the info */
-	if (!reset)
-		return;
-
-	OSMO_ASSERT(reset->fsm);
-
-	osmo_fsm_inst_dispatch(reset->fsm, EV_N_CONNECT, reset);
-}
-
-/* Check if we have a connection to a specified msc */
-bool a_reset_conn_ready(struct a_reset_ctx *reset)
-{
-	/* If no reset context is supplied, we assume that
-	 * the connection can't be ready! */
-	if (!reset)
-		return false;
-
-	OSMO_ASSERT(reset->fsm);
-	if (reset->fsm->state == ST_CONN)
-		return true;
-
-	return false;
-}
diff --git a/src/libcommon-cs/common_cs.c b/src/libcommon-cs/common_cs.c
deleted file mode 100644
index d6dff95..0000000
--- a/src/libcommon-cs/common_cs.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/* Code used by both libbsc and libmsc (common_cs means "BSC or MSC").
- *
- * (C) 2016 by sysmocom s.m.f.c. <info@sysmocom.de>
- * (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2014 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/>.
- *
- */
-
-#include <stdbool.h>
-
-#include <osmocom/gsm/gsm0480.h>
-
-#include <openbsc/common_cs.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_04_11.h>
-
-/* Warning: if bsc_network_init() is not called, some of the members of
- * gsm_network are not initialized properly and must not be used! (In
- * particular the llist heads and stats counters.)
- * The long term aim should be to have entirely separate structs for libbsc and
- * libmsc with some common general items.
- */
-struct gsm_network *gsm_network_init(void *ctx,
-				     uint16_t country_code,
-				     uint16_t network_code,
-				     mncc_recv_cb_t mncc_recv)
-{
-	struct gsm_network *net;
-
-	const char *default_regexp = ".*";
-
-	net = talloc_zero(ctx, struct gsm_network);
-	if (!net)
-		return NULL;
-
-	if (gsm_parse_reg(net, &net->authorized_regexp, &net->authorized_reg_str, 1,
-			  &default_regexp) != 0)
-		return NULL;
-
-	net->country_code = country_code;
-	net->network_code = network_code;
-
-	/* Use 30 min periodic update interval as sane default */
-	net->t3212 = 5;
-
-	INIT_LLIST_HEAD(&net->trans_list);
-	INIT_LLIST_HEAD(&net->upqueue);
-	INIT_LLIST_HEAD(&net->subscr_conns);
-
-	net->bsc_subscribers = talloc_zero(net, struct llist_head);
-	INIT_LLIST_HEAD(net->bsc_subscribers);
-
-	/* init statistics */
-	net->msc_ctrs = rate_ctr_group_alloc(net, &msc_ctrg_desc, 0);
-	if (!net->msc_ctrs) {
-		talloc_free(net);
-		return NULL;
-	}
-	net->active_calls = osmo_counter_alloc("msc.active_calls");
-
-	net->mncc_recv = mncc_recv;
-
-	net->dyn_ts_allow_tch_f = true;
-
-	INIT_LLIST_HEAD(&net->a.bscs);
-
-	return net;
-}
-
-struct msgb *gsm48_create_mm_serv_rej(enum gsm48_reject_value value)
-{
-	struct msgb *msg;
-	struct gsm48_hdr *gh;
-
-	msg = gsm48_msgb_alloc_name("GSM 04.08 SERV REJ");
-	if (!msg)
-		return NULL;
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
-	gh->proto_discr = GSM48_PDISC_MM;
-	gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
-	gh->data[0] = value;
-
-	return msg;
-}
-
-struct msgb *gsm48_create_loc_upd_rej(uint8_t cause)
-{
-	struct gsm48_hdr *gh;
-	struct msgb *msg;
-
-	msg = gsm48_msgb_alloc_name("GSM 04.08 LOC UPD REJ");
-	if (!msg)
-		return NULL;
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
-	gh->proto_discr = GSM48_PDISC_MM;
-	gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
-	gh->data[0] = cause;
-	return msg;
-}
-
-int gsm48_extract_mi(uint8_t *classmark2_lv, int length, char *mi_string, uint8_t *mi_type)
-{
-	/* Check the size for the classmark */
-	if (length < 1 + *classmark2_lv)
-		return -1;
-
-	uint8_t *mi_lv = classmark2_lv + *classmark2_lv + 1;
-	if (length < 2 + *classmark2_lv + mi_lv[0])
-		return -2;
-
-	*mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
-	return gsm48_mi_to_string(mi_string, GSM48_MI_SIZE, mi_lv+1, *mi_lv);
-}
-
-int gsm48_paging_extract_mi(struct gsm48_pag_resp *resp, int length,
-			    char *mi_string, uint8_t *mi_type)
-{
-	static const uint32_t classmark_offset =
-		offsetof(struct gsm48_pag_resp, classmark2);
-	uint8_t *classmark2_lv = (uint8_t *) &resp->classmark2;
-	return gsm48_extract_mi(classmark2_lv, length - classmark_offset,
-				mi_string, mi_type);
-}
-
-uint8_t sms_next_rp_msg_ref(uint8_t *next_rp_ref)
-{
-	const uint8_t rp_msg_ref = *next_rp_ref;
-	/*
-	 * This should wrap as the valid range is 0 to 255. We only
-	 * transfer one SMS at a time so we don't need to check if
-	 * the id has been already assigned.
-	 */
-	*next_rp_ref += 1;
-
-	return rp_msg_ref;
-}
diff --git a/src/libcommon-cs/common_cs_vty.c b/src/libcommon-cs/common_cs_vty.c
deleted file mode 100644
index 1791687..0000000
--- a/src/libcommon-cs/common_cs_vty.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/* Code used by both libbsc and libmsc (common_cs means "BSC or MSC").
- *
- * (C) 2016 by sysmocom s.m.f.c. <info@sysmocom.de>
- * (C) 2008-2010 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/>.
- *
- */
-
-#include <osmocom/core/utils.h>
-
-#include <osmocom/vty/command.h>
-#include <osmocom/vty/logging.h>
-#include <osmocom/vty/stats.h>
-
-#include <openbsc/vty.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_subscriber.h>
-
-struct cmd_node net_node = {
-	GSMNET_NODE,
-	"%s(config-net)# ",
-	1,
-};
-
-#define NETWORK_STR "Configure the GSM network\n"
-#define CODE_CMD_STR "Code commands\n"
-#define NAME_CMD_STR "Name Commands\n"
-#define NAME_STR "Name to use\n"
-
-DEFUN(cfg_net,
-      cfg_net_cmd,
-      "network", NETWORK_STR)
-{
-	vty->index = gsmnet_from_vty(vty);
-	vty->node = GSMNET_NODE;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_ncc,
-      cfg_net_ncc_cmd,
-      "network country code <1-999>",
-      "Set the GSM network country code\n"
-      "Country commands\n"
-      CODE_CMD_STR
-      "Network Country Code to use\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-
-	gsmnet->country_code = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_mnc,
-      cfg_net_mnc_cmd,
-      "mobile network code <0-999>",
-      "Set the GSM mobile network code\n"
-      "Network Commands\n"
-      CODE_CMD_STR
-      "Mobile Network Code to use\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-
-	gsmnet->network_code = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_name_short,
-      cfg_net_name_short_cmd,
-      "short name NAME",
-      "Set the short GSM network name\n" NAME_CMD_STR NAME_STR)
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-
-	osmo_talloc_replace_string(gsmnet, &gsmnet->name_short, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_name_long,
-      cfg_net_name_long_cmd,
-      "long name NAME",
-      "Set the long GSM network name\n" NAME_CMD_STR NAME_STR)
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-
-	osmo_talloc_replace_string(gsmnet, &gsmnet->name_long, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_auth_policy,
-      cfg_net_auth_policy_cmd,
-      "auth policy (closed|accept-all|regexp|token)",
-	"Authentication (not cryptographic)\n"
-	"Set the GSM network authentication policy\n"
-	"Require the MS to be activated in HLR\n"
-	"Accept all MS, whether in HLR or not\n"
-	"Use regular expression for IMSI authorization decision\n"
-	"Use SMS-token based authentication\n")
-{
-	enum gsm_auth_policy policy = gsm_auth_policy_parse(argv[0]);
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-
-	gsmnet->auth_policy = policy;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_authorize_regexp, cfg_net_authorize_regexp_cmd,
-      "authorized-regexp REGEXP",
-      "Set regexp for IMSI which will be used for authorization decision\n"
-      "Regular expression, IMSIs matching it are allowed to use the network\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	if (gsm_parse_reg(gsmnet, &gsmnet->authorized_regexp,
-			  &gsmnet->authorized_reg_str, argc, argv) != 0) {
-		vty_out(vty, "%%Failed to parse the authorized-regexp: '%s'%s",
-			argv[0], VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_reject_cause,
-      cfg_net_reject_cause_cmd,
-      "location updating reject cause <2-111>",
-      "Set the reject cause of location updating reject\n"
-      "Set the reject cause of location updating reject\n"
-      "Set the reject cause of location updating reject\n"
-      "Set the reject cause of location updating reject\n"
-      "Cause Value as Per GSM TS 04.08\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-
-	gsmnet->reject_cause = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_encryption,
-      cfg_net_encryption_cmd,
-      "encryption a5 (0|1|2|3)",
-	"Encryption options\n"
-	"A5 encryption\n" "A5/0: No encryption\n"
-	"A5/1: Encryption\n" "A5/2: Export-grade Encryption\n"
-	"A5/3: 'New' Secure Encryption\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-
-	gsmnet->a5_encryption = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_authentication,
-      cfg_net_authentication_cmd,
-      "authentication (optional|required)",
-	"Whether to enforce MS authentication in 2G\n"
-	"Allow MS to attach via 2G BSC without authentication\n"
-	"Always do authentication\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-
-	gsmnet->authentication_required = (argv[0][0] == 'r') ? true : false;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_rrlp_mode, cfg_net_rrlp_mode_cmd,
-      "rrlp mode (none|ms-based|ms-preferred|ass-preferred)",
-	"Radio Resource Location Protocol\n"
-	"Set the Radio Resource Location Protocol Mode\n"
-	"Don't send RRLP request\n"
-	"Request MS-based location\n"
-	"Request any location, prefer MS-based\n"
-	"Request any location, prefer MS-assisted\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-
-	gsmnet->rrlp.mode = rrlp_mode_parse(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_mm_info, cfg_net_mm_info_cmd,
-      "mm info (0|1)",
-	"Mobility Management\n"
-	"Send MM INFO after LOC UPD ACCEPT\n"
-	"Disable\n" "Enable\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-
-	gsmnet->send_mm_info = atoi(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_dyn_ts_allow_tch_f,
-      cfg_net_dyn_ts_allow_tch_f_cmd,
-      "dyn_ts_allow_tch_f (0|1)",
-      "Allow or disallow allocating TCH/F on TCH_F_TCH_H_PDCH timeslots\n"
-      "Disallow TCH/F on TCH_F_TCH_H_PDCH (default)\n"
-      "Allow TCH/F on TCH_F_TCH_H_PDCH\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	gsmnet->dyn_ts_allow_tch_f = atoi(argv[0]) ? true : false;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_timezone,
-      cfg_net_timezone_cmd,
-      "timezone <-19-19> (0|15|30|45)",
-      "Set the Timezone Offset of the network\n"
-      "Timezone offset (hours)\n"
-      "Timezone offset (00 minutes)\n"
-      "Timezone offset (15 minutes)\n"
-      "Timezone offset (30 minutes)\n"
-      "Timezone offset (45 minutes)\n"
-      )
-{
-	struct gsm_network *net = vty->index;
-	int tzhr = atoi(argv[0]);
-	int tzmn = atoi(argv[1]);
-
-	net->tz.hr = tzhr;
-	net->tz.mn = tzmn;
-	net->tz.dst = 0;
-	net->tz.override = 1;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_timezone_dst,
-      cfg_net_timezone_dst_cmd,
-      "timezone <-19-19> (0|15|30|45) <0-2>",
-      "Set the Timezone Offset of the network\n"
-      "Timezone offset (hours)\n"
-      "Timezone offset (00 minutes)\n"
-      "Timezone offset (15 minutes)\n"
-      "Timezone offset (30 minutes)\n"
-      "Timezone offset (45 minutes)\n"
-      "DST offset (hours)\n"
-      )
-{
-	struct gsm_network *net = vty->index;
-	int tzhr = atoi(argv[0]);
-	int tzmn = atoi(argv[1]);
-	int tzdst = atoi(argv[2]);
-
-	net->tz.hr = tzhr;
-	net->tz.mn = tzmn;
-	net->tz.dst = tzdst;
-	net->tz.override = 1;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_no_timezone,
-      cfg_net_no_timezone_cmd,
-      "no timezone",
-      NO_STR
-      "Disable network timezone override, use system tz\n")
-{
-	struct gsm_network *net = vty->index;
-
-	net->tz.override = 0;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
-      "periodic location update <6-1530>",
-      "Periodic Location Updating Interval\n"
-      "Periodic Location Updating Interval\n"
-      "Periodic Location Updating Interval\n"
-      "Periodic Location Updating Interval in Minutes\n")
-{
-	struct gsm_network *net = vty->index;
-
-	net->t3212 = atoi(argv[0]) / 6;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
-      "no periodic location update",
-      NO_STR
-      "Periodic Location Updating Interval\n"
-      "Periodic Location Updating Interval\n"
-      "Periodic Location Updating Interval\n")
-{
-	struct gsm_network *net = vty->index;
-
-	net->t3212 = 0;
-
-	return CMD_SUCCESS;
-}
-
-static struct gsm_network *vty_global_gsm_network = NULL;
-
-/* initialize VTY elements used in both BSC and MSC */
-int common_cs_vty_init(struct gsm_network *network,
-                 int (* config_write_net )(struct vty *))
-{
-	OSMO_ASSERT(vty_global_gsm_network == NULL);
-	vty_global_gsm_network = network;
-
-	osmo_stats_vty_add_cmds();
-
-	install_element(CONFIG_NODE, &cfg_net_cmd);
-	install_node(&net_node, config_write_net);
-	vty_install_default(GSMNET_NODE);
-	install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
-	install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
-	install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
-	install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
-	install_element(GSMNET_NODE, &cfg_net_auth_policy_cmd);
-	install_element(GSMNET_NODE, &cfg_net_authorize_regexp_cmd);
-	install_element(GSMNET_NODE, &cfg_net_reject_cause_cmd);
-	install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
-	install_element(GSMNET_NODE, &cfg_net_authentication_cmd);
-	install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd);
-	install_element(GSMNET_NODE, &cfg_net_mm_info_cmd);
-	install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
-	install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
-	install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
-	install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
-	install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
-	install_element(GSMNET_NODE, &cfg_net_dyn_ts_allow_tch_f_cmd);
-
-	return CMD_SUCCESS;
-}
-
-struct gsm_network *gsmnet_from_vty(struct vty *v)
-{
-	/* It can't hurt to force callers to continue to pass the vty instance
-	 * to this function, in case we'd like to retrieve the global
-	 * gsm_network instance from the vty at some point in the future. But
-	 * until then, just return the global pointer, which should have been
-	 * initialized by common_cs_vty_init().
-	 */
-	OSMO_ASSERT(vty_global_gsm_network);
-	return vty_global_gsm_network;
-}
diff --git a/src/libcommon/Makefile.am b/src/libcommon/Makefile.am
deleted file mode 100644
index 0b258c0..0000000
--- a/src/libcommon/Makefile.am
+++ /dev/null
@@ -1,47 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	-I$(top_builddir) \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOVTY_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(NULL)
-
-noinst_LIBRARIES = \
-	libcommon.a \
-	$(NULL)
-
-libcommon_a_SOURCES = \
-	bsc_version.c \
-	common_vty.c \
-	debug.c \
-	gsm_data.c \
-	gsm_data_shared.c \
-	gsup_client.c \
-	oap_client.c \
-	socket.c \
-	talloc_ctx.c \
-	gsm_subscriber_base.c \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	gsup_test_client \
-	$(NULL)
-
-gsup_test_client_SOURCES = \
-	gsup_test_client.c \
-	$(NULL)
-gsup_test_client_LDADD = \
-	libcommon.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOVTY_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	-lrt \
-	$(NULL)
diff --git a/src/libcommon/bsc_version.c b/src/libcommon/bsc_version.c
deleted file mode 100644
index f0369bf..0000000
--- a/src/libcommon/bsc_version.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Hold the copyright and version string */
-/* (C) 2010-2016 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/>.
- *
- */
-
-#include "../../bscconfig.h"
-
-const char *openbsc_copyright =
-	"Copyright (C) 2008-2016 Harald Welte, Holger Freyther\r\n"
-	"Contributions by Daniel Willmann, Jan Lübbe, Stefan Schmidt\r\n"
-	"Dieter Spaar, Andreas Eversberg, Sylvain Munaut, Neels Hofmeyr\r\n\r\n"
-	"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
-	"This is free software: you are free to change and redistribute it.\r\n"
-	"There is NO WARRANTY, to the extent permitted by law.\r\n";
-
-
diff --git a/src/libcommon/common_vty.c b/src/libcommon/common_vty.c
deleted file mode 100644
index 1443791..0000000
--- a/src/libcommon/common_vty.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/* OpenBSC VTY common helpers */
-/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009-2010 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/>.
- *
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <osmocom/core/talloc.h>
-
-#include <openbsc/vty.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/bsc_nat.h>
-#include <openbsc/abis_om2000.h>
-
-#include <osmocom/vty/telnet_interface.h>
-#include <osmocom/vty/command.h>
-#include <osmocom/vty/buffer.h>
-#include <osmocom/vty/vty.h>
-#include <osmocom/sigtran/osmo_ss7.h>
-
-
-int bsc_vty_go_parent(struct vty *vty)
-{
-	switch (vty->node) {
-	case GSMNET_NODE:
-		vty->node = CONFIG_NODE;
-		vty->index = NULL;
-		break;
-	case BTS_NODE:
-		vty->node = GSMNET_NODE;
-		{
-			/* set vty->index correctly ! */
-			struct gsm_bts *bts = vty->index;
-			vty->index = bts->network;
-			vty->index_sub = NULL;
-		}
-		break;
-	case TRX_NODE:
-		vty->node = BTS_NODE;
-		{
-			/* set vty->index correctly ! */
-			struct gsm_bts_trx *trx = vty->index;
-			vty->index = trx->bts;
-			vty->index_sub = &trx->bts->description;
-		}
-		break;
-	case TS_NODE:
-		vty->node = TRX_NODE;
-		{
-			/* set vty->index correctly ! */
-			struct gsm_bts_trx_ts *ts = vty->index;
-			vty->index = ts->trx;
-			vty->index_sub = &ts->trx->description;
-		}
-		break;
-	case OML_NODE:
-	case OM2K_NODE:
-		vty->node = ENABLE_NODE;
-		/* NOTE: this only works because it's not part of the config
-		 * tree, where outer commands are searched via vty_go_parent()
-		 * and only (!) executed when a matching one is found.
-		 */
-		talloc_free(vty->index);
-		vty->index = NULL;
-		break;
-	case OM2K_CON_GROUP_NODE:
-		vty->node = BTS_NODE;
-		{
-			struct con_group *cg = vty->index;
-			struct gsm_bts *bts = cg->bts;
-			vty->index = bts;
-			vty->index_sub = &bts->description;
-		}
-		break;
-	case NAT_BSC_NODE:
-		vty->node = NAT_NODE;
-		{
-			struct bsc_config *bsc_config = vty->index;
-			vty->index = bsc_config->nat;
-		}
-		break;
-	case PGROUP_NODE:
-		vty->node = NAT_NODE;
-		vty->index = NULL;
-		break;
-	case TRUNK_NODE:
-		vty->node = MGCP_NODE;
-		vty->index = NULL;
-		break;
-	case SMPP_ESME_NODE:
-		vty->node = SMPP_NODE;
-		vty->index = NULL;
-		break;
-	case SMPP_NODE:
-	case MGCP_NODE:
-	case GBPROXY_NODE:
-	case SGSN_NODE:
-	case NAT_NODE:
-	case BSC_NODE:
-	case MSC_NODE:
-	case MNCC_INT_NODE:
-	case NITB_NODE:
-		vty->node = CONFIG_NODE;
-		vty->index = NULL;
-		break;
-	case SUBSCR_NODE:
-		vty->node = ENABLE_NODE;
-		vty->index = NULL;
-		break;
-	default:
-		osmo_ss7_vty_go_parent(vty);
-	}
-
-	return vty->node;
-}
-
-int bsc_vty_is_config_node(struct vty *vty, int node)
-{
-	/* Check if libosmo-sccp declares the node in
-	 * question as config node */
-	if (osmo_ss7_is_config_node(vty, node))
-		return 1;
-
-	switch (node) {
-	/* add items that are not config */
-	case OML_NODE:
-	case OM2K_NODE:
-	case SUBSCR_NODE:
-	case CONFIG_NODE:
-		return 0;
-
-	default:
-		return 1;
-	}
-}
diff --git a/src/libcommon/debug.c b/src/libcommon/debug.c
deleted file mode 100644
index 7236413..0000000
--- a/src/libcommon/debug.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/* OpenBSC Debugging/Logging support code */
-
-/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2008 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/>.
- *
- */
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include <time.h>
-#include <errno.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/logging.h>
-#include <osmocom/gprs/gprs_msgb.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/debug.h>
-
-/* default categories */
-static const struct log_info_cat default_categories[] = {
-	[DRLL] = {
-		.name = "DRLL",
-		.description = "A-bis Radio Link Layer (RLL)",
-		.color = "\033[1;31m",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DCC] = {
-		.name = "DCC",
-		.description = "Layer3 Call Control (CC)",
-		.color = "\033[1;32m",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DMM] = {
-		.name = "DMM",
-		.description = "Layer3 Mobility Management (MM)",
-		.color = "\033[1;33m",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DRR] = {
-		.name = "DRR",
-		.description = "Layer3 Radio Resource (RR)",
-		.color = "\033[1;34m",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DRSL] = {
-		.name = "DRSL",
-		.description = "A-bis Radio Siganlling Link (RSL)",
-		.color = "\033[1;35m",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DNM] =	{
-		.name = "DNM",
-		.description = "A-bis Network Management / O&M (NM/OML)",
-		.color = "\033[1;36m",
-		.enabled = 1, .loglevel = LOGL_INFO,
-	},
-	[DMNCC] = {
-		.name = "DMNCC",
-		.description = "MNCC API for Call Control application",
-		.color = "\033[1;39m",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DPAG]	= {
-		.name = "DPAG",
-		.description = "Paging Subsystem",
-		.color = "\033[1;38m",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DMEAS] = {
-		.name = "DMEAS",
-		.description = "Radio Measurement Processing",
-		.enabled = 0, .loglevel = LOGL_NOTICE,
-	},
-	[DSCCP] = {
-		.name = "DSCCP",
-		.description = "SCCP Protocol",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DMSC] = {
-		.name = "DMSC",
-		.description = "Mobile Switching Center",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DMGCP] = {
-		.name = "DMGCP",
-		.description = "Media Gateway Control Protocol",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DHO] = {
-		.name = "DHO",
-		.description = "Hand-Over",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DDB] = {
-		.name = "DDB",
-		.description = "Database Layer",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DREF] = {
-		.name = "DREF",
-		.description = "Reference Counting",
-		.enabled = 0, .loglevel = LOGL_NOTICE,
-	},
-	[DGPRS] = {
-		.name = "DGPRS",
-		.description = "GPRS Packet Service",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DNS] = {
-		.name = "DNS",
-		.description = "GPRS Network Service (NS)",
-		.enabled = 1, .loglevel = LOGL_INFO,
-	},
-	[DBSSGP] = {
-		.name = "DBSSGP",
-		.description = "GPRS BSS Gateway Protocol (BSSGP)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DLLC] = {
-		.name = "DLLC",
-		.description = "GPRS Logical Link Control Protocol (LLC)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DSNDCP] = {
-		.name = "DSNDCP",
-		.description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DNAT] = {
-		.name = "DNAT",
-		.description = "GSM 08.08 NAT/Multiplexer",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DCTRL] = {
-		.name = "DCTRL",
-		.description = "Control interface",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DSMPP] = {
-		.name = "DSMPP",
-		.description = "SMPP interface for external SMS apps",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DFILTER] = {
-		.name = "DFILTER",
-		.description = "BSC/NAT IMSI based filtering",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DRANAP] = {
-		.name = "DRANAP",
-		.description = "Radio Access Network Application Part Protocol",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DSUA] = {
-		.name = "DSUA",
-		.description = "SCCP User Adaptation Protocol",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DPCU] = {
-		.name = "DPCU",
-		.description = "PCU Interface",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DVLR] = {
-		.name = "DVLR",
-		.description = "Visitor Location Register",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DIUCS] = {
-		.name = "DIUCS",
-		.description = "Iu-CS Protocol",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DSIGTRAN] = {
-		.name = "DSIGTRAN",
-		.description = "SIGTRAN Signalling Transport",
-		.color = "\033[1;29m",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-};
-
-static int filter_fn(const struct log_context *ctx, struct log_target *tar)
-{
-	const struct vlr_subscr *vsub = ctx->ctx[LOG_CTX_VLR_SUBSCR];
-	const struct bsc_subscr *bsub = ctx->ctx[LOG_CTX_BSC_SUBSCR];
-	const struct gprs_nsvc *nsvc = ctx->ctx[LOG_CTX_GB_NSVC];
-	const struct gprs_nsvc *bvc = ctx->ctx[LOG_CTX_GB_BVC];
-
-	if ((tar->filter_map & (1 << LOG_FLT_VLR_SUBSCR)) != 0
-	    && vsub && vsub == tar->filter_data[LOG_FLT_VLR_SUBSCR])
-		return 1;
-
-	if ((tar->filter_map & (1 << LOG_FLT_BSC_SUBSCR)) != 0
-	    && bsub && bsub == tar->filter_data[LOG_FLT_BSC_SUBSCR])
-		return 1;
-
-	/* Filter on the NS Virtual Connection */
-	if ((tar->filter_map & (1 << LOG_FLT_GB_NSVC)) != 0
-	    && nsvc && (nsvc == tar->filter_data[LOG_FLT_GB_NSVC]))
-		return 1;
-
-	/* Filter on the NS Virtual Connection */
-	if ((tar->filter_map & (1 << LOG_FLT_GB_BVC)) != 0
-	    && bvc && (bvc == tar->filter_data[LOG_FLT_GB_BVC]))
-		return 1;
-
-	return 0;
-}
-
-const struct log_info log_info = {
-	.filter_fn = filter_fn,
-	.cat = default_categories,
-	.num_cat = ARRAY_SIZE(default_categories),
-};
diff --git a/src/libcommon/gsm_data.c b/src/libcommon/gsm_data.c
deleted file mode 100644
index 7be2240..0000000
--- a/src/libcommon/gsm_data.c
+++ /dev/null
@@ -1,459 +0,0 @@
-/* (C) 2008-2010 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/>.
- *
- */
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <stdbool.h>
-#include <netinet/in.h>
-
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/gsm/abis_nm.h>
-#include <osmocom/core/statistics.h>
-#include <osmocom/gsm/protocol/gsm_04_08.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/bsc_msc_data.h>
-#include <openbsc/abis_nm.h>
-
-void *tall_bsc_ctx;
-
-static LLIST_HEAD(bts_models);
-
-void set_ts_e1link(struct gsm_bts_trx_ts *ts, uint8_t e1_nr,
-		   uint8_t e1_ts, uint8_t e1_ts_ss)
-{
-	ts->e1_link.e1_nr = e1_nr;
-	ts->e1_link.e1_ts = e1_ts;
-	ts->e1_link.e1_ts_ss = e1_ts_ss;
-}
-
-static struct gsm_bts_model *bts_model_find(enum gsm_bts_type type)
-{
-	struct gsm_bts_model *model;
-
-	llist_for_each_entry(model, &bts_models, list) {
-		if (model->type == type)
-			return model;
-	}
-
-	return NULL;
-}
-
-int gsm_bts_model_register(struct gsm_bts_model *model)
-{
-	if (bts_model_find(model->type))
-		return -EEXIST;
-
-	tlv_def_patch(&model->nm_att_tlvdef, &abis_nm_att_tlvdef);
-	llist_add_tail(&model->list, &bts_models);
-	return 0;
-}
-
-const struct value_string bts_type_descs[_NUM_GSM_BTS_TYPE+1] = {
-	{ GSM_BTS_TYPE_UNKNOWN,		"Unknown BTS Type" },
-	{ GSM_BTS_TYPE_BS11,		"Siemens BTS (BS-11 or compatible)" },
-	{ GSM_BTS_TYPE_NANOBTS,		"ip.access nanoBTS or compatible" },
-	{ GSM_BTS_TYPE_RBS2000,		"Ericsson RBS2000 Series" },
-	{ GSM_BTS_TYPE_NOKIA_SITE,	"Nokia {Metro,Ultra,In}Site" },
-	{ GSM_BTS_TYPE_OSMOBTS,		"sysmocom sysmoBTS" },
-	{ 0,				NULL }
-};
-
-struct gsm_bts_trx *gsm_bts_trx_by_nr(struct gsm_bts *bts, int nr)
-{
-	struct gsm_bts_trx *trx;
-
-	llist_for_each_entry(trx, &bts->trx_list, list) {
-		if (trx->nr == nr)
-			return trx;
-	}
-	return NULL;
-}
-
-/* Search for a BTS in the given Location Area; optionally start searching
- * with start_bts (for continuing to search after the first result) */
-struct gsm_bts *gsm_bts_by_lac(struct gsm_network *net, unsigned int lac,
-				struct gsm_bts *start_bts)
-{
-	int i;
-	struct gsm_bts *bts;
-	int skip = 0;
-
-	if (start_bts)
-		skip = 1;
-
-	for (i = 0; i < net->num_bts; i++) {
-		bts = gsm_bts_num(net, i);
-
-		if (skip) {
-			if (start_bts == bts)
-				skip = 0;
-			continue;
-		}
-
-		if (lac == GSM_LAC_RESERVED_ALL_BTS || bts->location_area_code == lac)
-			return bts;
-	}
-	return NULL;
-}
-
-static const struct value_string auth_policy_names[] = {
-	{ GSM_AUTH_POLICY_CLOSED,	"closed" },
-	{ GSM_AUTH_POLICY_ACCEPT_ALL,	"accept-all" },
-	{ GSM_AUTH_POLICY_TOKEN,	"token" },
-	{ GSM_AUTH_POLICY_REGEXP,	"regexp" },
-	{ 0,				NULL }
-};
-
-enum gsm_auth_policy gsm_auth_policy_parse(const char *arg)
-{
-	return get_string_value(auth_policy_names, arg);
-}
-
-const char *gsm_auth_policy_name(enum gsm_auth_policy policy)
-{
-	return get_value_string(auth_policy_names, policy);
-}
-
-static const struct value_string rrlp_mode_names[] = {
-	{ RRLP_MODE_NONE,	"none" },
-	{ RRLP_MODE_MS_BASED,	"ms-based" },
-	{ RRLP_MODE_MS_PREF,	"ms-preferred" },
-	{ RRLP_MODE_ASS_PREF,	"ass-preferred" },
-	{ 0,			NULL }
-};
-
-enum rrlp_mode rrlp_mode_parse(const char *arg)
-{
-	return get_string_value(rrlp_mode_names, arg);
-}
-
-const char *rrlp_mode_name(enum rrlp_mode mode)
-{
-	return get_value_string(rrlp_mode_names, mode);
-}
-
-static const struct value_string bts_gprs_mode_names[] = {
-	{ BTS_GPRS_NONE,	"none" },
-	{ BTS_GPRS_GPRS,	"gprs" },
-	{ BTS_GPRS_EGPRS,	"egprs" },
-	{ 0,			NULL }
-};
-
-enum bts_gprs_mode bts_gprs_mode_parse(const char *arg, int *valid)
-{
-	int rc;
-
-	rc = get_string_value(bts_gprs_mode_names, arg);
-	if (valid)
-		*valid = rc != -EINVAL;
-	return rc;
-}
-
-const char *bts_gprs_mode_name(enum bts_gprs_mode mode)
-{
-	return get_value_string(bts_gprs_mode_names, mode);
-}
-
-int bts_gprs_mode_is_compat(struct gsm_bts *bts, enum bts_gprs_mode mode)
-{
-	if (mode != BTS_GPRS_NONE &&
-	    !gsm_btsmodel_has_feature(bts->model, BTS_FEAT_GPRS)) {
-		return 0;
-	}
-	if (mode == BTS_GPRS_EGPRS &&
-	    !gsm_btsmodel_has_feature(bts->model, BTS_FEAT_EGPRS)) {
-		return 0;
-	}
-
-	return 1;
-}
-
-int gsm_btsmodel_set_feature(struct gsm_bts_model *model, enum gsm_bts_features feat)
-{
-	OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES);
-	return bitvec_set_bit_pos(&model->features, feat, 1);
-}
-
-bool gsm_btsmodel_has_feature(struct gsm_bts_model *model, enum gsm_bts_features feat)
-{
-	OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES);
-	return bitvec_get_bit_pos(&model->features, feat);
-}
-
-int gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type)
-{
-	struct gsm_bts_model *model;
-
-	model = bts_model_find(type);
-	if (!model)
-		return -EINVAL;
-
-	bts->type = type;
-	bts->model = model;
-
-	if (model->start && !model->started) {
-		int ret = model->start(bts->network);
-		if (ret < 0)
-			return ret;
-
-		model->started = true;
-	}
-
-	switch (bts->type) {
-	case GSM_BTS_TYPE_NANOBTS:
-	case GSM_BTS_TYPE_OSMOBTS:
-		/* Set the default OML Stream ID to 0xff */
-		bts->oml_tei = 0xff;
-		bts->c0->nominal_power = 23;
-		break;
-	case GSM_BTS_TYPE_RBS2000:
-		INIT_LLIST_HEAD(&bts->rbs2000.is.conn_groups);
-		INIT_LLIST_HEAD(&bts->rbs2000.con.conn_groups);
-		break;
-	case GSM_BTS_TYPE_BS11:
-	case GSM_BTS_TYPE_UNKNOWN:
-	case GSM_BTS_TYPE_NOKIA_SITE:
-		/* Set default BTS reset timer */
-		bts->nokia.bts_reset_timer_cnf = 15;
-	case _NUM_GSM_BTS_TYPE:
-		break;
-	}
-
-	return 0;
-}
-
-struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net, enum gsm_bts_type type,
-					uint8_t bsic)
-{
-	struct gsm_bts_model *model = bts_model_find(type);
-	struct gsm_bts *bts;
-
-	if (!model && type != GSM_BTS_TYPE_UNKNOWN)
-		return NULL;
-
-	bts = gsm_bts_alloc(net, net->num_bts);
-	if (!bts)
-		return NULL;
-
-	net->num_bts++;
-
-	bts->network = net;
-	bts->type = type;
-	bts->model = model;
-	bts->bsic = bsic;
-	bts->dtxu = GSM48_DTX_SHALL_NOT_BE_USED;
-	bts->dtxd = false;
-	bts->gprs.ctrl_ack_type_use_block = true; /* use RLC/MAC control block */
-	bts->neigh_list_manual_mode = 0;
-	bts->si_common.cell_sel_par.cell_resel_hyst = 2; /* 4 dB */
-	bts->si_common.cell_sel_par.rxlev_acc_min = 0;
-	bts->si_common.si2quater_neigh_list.arfcn = bts->si_common.data.earfcn_list;
-	bts->si_common.si2quater_neigh_list.meas_bw = bts->si_common.data.meas_bw_list;
-	bts->si_common.si2quater_neigh_list.length = MAX_EARFCN_LIST;
-	bts->si_common.si2quater_neigh_list.thresh_hi = 0;
-	osmo_earfcn_init(&bts->si_common.si2quater_neigh_list);
-	bts->si_common.neigh_list.data = bts->si_common.data.neigh_list;
-	bts->si_common.neigh_list.data_len =
-				sizeof(bts->si_common.data.neigh_list);
-	bts->si_common.si5_neigh_list.data = bts->si_common.data.si5_neigh_list;
-	bts->si_common.si5_neigh_list.data_len =
-				sizeof(bts->si_common.data.si5_neigh_list);
-	bts->si_common.cell_alloc.data = bts->si_common.data.cell_alloc;
-	bts->si_common.cell_alloc.data_len =
-				sizeof(bts->si_common.data.cell_alloc);
-	bts->si_common.rach_control.re = 1; /* no re-establishment */
-	bts->si_common.rach_control.tx_integer = 9;  /* 12 slots spread - 217/115 slots delay */
-	bts->si_common.rach_control.max_trans = 3; /* 7 retransmissions */
-	bts->si_common.rach_control.t2 = 4; /* no emergency calls */
-	bts->si_common.chan_desc.att = 1; /* attachment required */
-	bts->si_common.chan_desc.bs_pa_mfrms = RSL_BS_PA_MFRMS_5; /* paging frames */
-	bts->si_common.chan_desc.bs_ag_blks_res = 1; /* reserved AGCH blocks */
-	bts->si_common.chan_desc.t3212 = net->t3212; /* Use network's current value */
-	gsm_bts_set_radio_link_timeout(bts, 32); /* Use RADIO LINK TIMEOUT of 32 */
-
-	llist_add_tail(&bts->list, &net->bts_list);
-
-	INIT_LLIST_HEAD(&bts->abis_queue);
-
-	INIT_LLIST_HEAD(&bts->loc_list);
-
-	return bts;
-}
-
-void gprs_ra_id_by_bts(struct gprs_ra_id *raid, struct gsm_bts *bts)
-{
-	raid->mcc = bts->network->country_code;
-	raid->mnc = bts->network->network_code;
-	raid->lac = bts->location_area_code;
-	raid->rac = bts->gprs.rac;
-}
-
-int gsm48_ra_id_by_bts(uint8_t *buf, struct gsm_bts *bts)
-{
-	struct gprs_ra_id raid;
-
-	gprs_ra_id_by_bts(&raid, bts);
-
-	return gsm48_construct_ra(buf, &raid);
-}
-
-int gsm_parse_reg(void *ctx, regex_t *reg, char **str, int argc, const char **argv)
-{
-	int ret;
-
-	ret = 0;
-	if (*str) {
-		talloc_free(*str);
-		*str = NULL;
-	}
-	regfree(reg);
-
-	if (argc > 0) {
-		*str = talloc_strdup(ctx, argv[0]);
-		ret = regcomp(reg, argv[0], 0);
-
-		/* handle compilation failures */
-		if (ret != 0) {
-			talloc_free(*str);
-			*str = NULL;
-		}
-	}
-
-	return ret;
-}
-
-/* Assume there are only 256 possible bts */
-osmo_static_assert(sizeof(((struct gsm_bts *) 0)->nr) == 1, _bts_nr_is_256);
-static void depends_calc_index_bit(int bts_nr, int *idx, int *bit)
-{
-	*idx = bts_nr / (8 * 4);
-	*bit = bts_nr % (8 * 4);
-}
-
-void bts_depend_mark(struct gsm_bts *bts, int dep)
-{
-	int idx, bit;
-	depends_calc_index_bit(dep, &idx, &bit);
-
-	bts->depends_on[idx] |= 1 << bit;
-}
-
-void bts_depend_clear(struct gsm_bts *bts, int dep)
-{
-	int idx, bit;
-	depends_calc_index_bit(dep, &idx, &bit);
-
-	bts->depends_on[idx] &= ~(1 << bit);
-}
-
-int bts_depend_is_depedency(struct gsm_bts *base, struct gsm_bts *other)
-{
-	int idx, bit;
-	depends_calc_index_bit(other->nr, &idx, &bit);
-
-	/* Check if there is a depends bit */
-	return (base->depends_on[idx] & (1 << bit)) > 0;
-}
-
-static int bts_is_online(struct gsm_bts *bts)
-{
-	/* TODO: support E1 BTS too */
-	if (!is_ipaccess_bts(bts))
-		return 1;
-
-	if (!bts->oml_link)
-		return 0;
-
-	return bts->mo.nm_state.operational == NM_OPSTATE_ENABLED;
-}
-
-int bts_depend_check(struct gsm_bts *bts)
-{
-	struct gsm_bts *other_bts;
-
-	llist_for_each_entry(other_bts, &bts->network->bts_list, list) {
-		if (!bts_depend_is_depedency(bts, other_bts))
-			continue;
-		if (bts_is_online(other_bts))
-			continue;
-		return 0;
-	}
-	return 1;
-}
-
-/* get the radio link timeout (based on SACCH decode errors, according
- * to algorithm specified in TS 05.08 section 5.2.  A value of -1
- * indicates we should use an infinitely long timeout, which only works
- * with OsmoBTS as the BTS implementation */
-int gsm_bts_get_radio_link_timeout(const struct gsm_bts *bts)
-{
-	const struct gsm48_cell_options *cell_options = &bts->si_common.cell_options;
-
-	if (bts->infinite_radio_link_timeout)
-		return -1;
-	else {
-		/* Encoding as per Table 10.5.21 of TS 04.08 */
-		return (cell_options->radio_link_timeout + 1) << 2;
-	}
-}
-
-/* set the radio link timeout (based on SACCH decode errors, according
- * to algorithm specified in TS 05.08 Section 5.2.  A value of -1
- * indicates we should use an infinitely long timeout, which only works
- * with OsmoBTS as the BTS implementation */
-void gsm_bts_set_radio_link_timeout(struct gsm_bts *bts, int value)
-{
-	struct gsm48_cell_options *cell_options = &bts->si_common.cell_options;
-
-	if (value < 0)
-		bts->infinite_radio_link_timeout = true;
-	else {
-		bts->infinite_radio_link_timeout = false;
-		/* Encoding as per Table 10.5.21 of TS 04.08 */
-		if (value < 4)
-			value = 4;
-		if (value > 64)
-			value = 64;
-		cell_options->radio_link_timeout = (value >> 2) - 1;
-	}
-}
-
-bool classmark_is_r99(struct gsm_classmark *cm)
-{
-	int rev_lev = 0;
-	if (cm->classmark1_set)
-		rev_lev = cm->classmark1.rev_lev;
-	else if (cm->classmark2_len > 0)
-		rev_lev = (cm->classmark2[0] >> 5) & 0x3;
-	return rev_lev >= 2;
-}
-
-const struct value_string ran_type_names[] = {
-	OSMO_VALUE_STRING(RAN_UNKNOWN),
-	OSMO_VALUE_STRING(RAN_GERAN_A),
-	OSMO_VALUE_STRING(RAN_UTRAN_IU),
-	{ 0, NULL }
-};
diff --git a/src/libcommon/gsm_data_shared.c b/src/libcommon/gsm_data_shared.c
deleted file mode 100644
index 2696273..0000000
--- a/src/libcommon/gsm_data_shared.c
+++ /dev/null
@@ -1,853 +0,0 @@
-/* (C) 2008-2010 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/>.
- *
- */
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-
-#include <netinet/in.h>
-
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/gsm/abis_nm.h>
-#include <osmocom/core/statistics.h>
-
-#include <openbsc/gsm_data.h>
-
-void gsm_abis_mo_reset(struct gsm_abis_mo *mo)
-{
-	mo->nm_state.operational = NM_OPSTATE_NULL;
-	mo->nm_state.availability = NM_AVSTATE_POWER_OFF;
-}
-
-static void gsm_mo_init(struct gsm_abis_mo *mo, struct gsm_bts *bts,
-			uint8_t obj_class, uint8_t p1, uint8_t p2, uint8_t p3)
-{
-	mo->bts = bts;
-	mo->obj_class = obj_class;
-	mo->obj_inst.bts_nr = p1;
-	mo->obj_inst.trx_nr = p2;
-	mo->obj_inst.ts_nr = p3;
-	gsm_abis_mo_reset(mo);
-}
-
-const struct value_string bts_attribute_names[] = {
-	OSMO_VALUE_STRING(BTS_TYPE_VARIANT),
-	OSMO_VALUE_STRING(BTS_SUB_MODEL),
-	OSMO_VALUE_STRING(TRX_PHY_VERSION),
-	{ 0, NULL }
-};
-
-enum bts_attribute str2btsattr(const char *s)
-{
-	return get_string_value(bts_attribute_names, s);
-}
-
-const char *btsatttr2str(enum bts_attribute v)
-{
-	return get_value_string(bts_attribute_names, v);
-}
-
-const struct value_string osmo_bts_variant_names[_NUM_BTS_VARIANT + 1] = {
-	{ BTS_UNKNOWN,		"unknown" },
-	{ BTS_OSMO_LITECELL15,	"osmo-bts-lc15" },
-	{ BTS_OSMO_OCTPHY,	"osmo-bts-octphy" },
-	{ BTS_OSMO_SYSMO,	"osmo-bts-sysmo" },
-	{ BTS_OSMO_TRX,		"omso-bts-trx" },
-	{ 0, NULL }
-};
-
-enum gsm_bts_type_variant str2btsvariant(const char *arg)
-{
-	return get_string_value(osmo_bts_variant_names, arg);
-}
-
-const char *btsvariant2str(enum gsm_bts_type_variant v)
-{
-	return get_value_string(osmo_bts_variant_names, v);
-}
-
-const struct value_string bts_type_names[_NUM_GSM_BTS_TYPE + 1] = {
-	{ GSM_BTS_TYPE_UNKNOWN,		"unknown" },
-	{ GSM_BTS_TYPE_BS11,		"bs11" },
-	{ GSM_BTS_TYPE_NANOBTS,		"nanobts" },
-	{ GSM_BTS_TYPE_RBS2000,		"rbs2000" },
-	{ GSM_BTS_TYPE_NOKIA_SITE,	"nokia_site" },
-	{ GSM_BTS_TYPE_OSMOBTS,		"sysmobts" },
-	{ 0, NULL }
-};
-
-enum gsm_bts_type str2btstype(const char *arg)
-{
-	return get_string_value(bts_type_names, arg);
-}
-
-const char *btstype2str(enum gsm_bts_type type)
-{
-	return get_value_string(bts_type_names, type);
-}
-
-const struct value_string gsm_bts_features_descs[] = {
-	{ BTS_FEAT_HSCSD,		"HSCSD" },
-	{ BTS_FEAT_GPRS,		"GPRS" },
-	{ BTS_FEAT_EGPRS,		"EGPRS" },
-	{ BTS_FEAT_ECSD,		"ECSD" },
-	{ BTS_FEAT_HOPPING,		"Frequency Hopping" },
-	{ BTS_FEAT_MULTI_TSC,		"Multi-TSC" },
-	{ BTS_FEAT_OML_ALERTS,		"OML Alerts" },
-	{ BTS_FEAT_AGCH_PCH_PROP,	"AGCH/PCH proportional allocation" },
-	{ BTS_FEAT_CBCH,		"CBCH" },
-	{ 0, NULL }
-};
-
-const struct value_string gsm_chreq_descs[] = {
-	{ GSM_CHREQ_REASON_EMERG,	"emergency call" },
-	{ GSM_CHREQ_REASON_PAG,		"answer to paging" },
-	{ GSM_CHREQ_REASON_CALL,	"call re-establishment" },
-	{ GSM_CHREQ_REASON_LOCATION_UPD,"Location updating" },
-	{ GSM_CHREQ_REASON_PDCH,	"one phase packet access" },
-	{ GSM_CHREQ_REASON_OTHER,	"other" },
-	{ 0,				NULL }
-};
-
-const struct value_string gsm_pchant_names[13] = {
-	{ GSM_PCHAN_NONE,	"NONE" },
-	{ GSM_PCHAN_CCCH,	"CCCH" },
-	{ GSM_PCHAN_CCCH_SDCCH4,"CCCH+SDCCH4" },
-	{ GSM_PCHAN_TCH_F,	"TCH/F" },
-	{ GSM_PCHAN_TCH_H,	"TCH/H" },
-	{ GSM_PCHAN_SDCCH8_SACCH8C, "SDCCH8" },
-	{ GSM_PCHAN_PDCH,	"PDCH" },
-	{ GSM_PCHAN_TCH_F_PDCH,	"TCH/F_PDCH" },
-	{ GSM_PCHAN_UNKNOWN,	"UNKNOWN" },
-	{ GSM_PCHAN_CCCH_SDCCH4_CBCH, "CCCH+SDCCH4+CBCH" },
-	{ GSM_PCHAN_SDCCH8_SACCH8C_CBCH, "SDCCH8+CBCH" },
-	{ GSM_PCHAN_TCH_F_TCH_H_PDCH, "TCH/F_TCH/H_PDCH" },
-	{ 0,			NULL }
-};
-
-const struct value_string gsm_pchant_descs[13] = {
-	{ GSM_PCHAN_NONE,	"Physical Channel not configured" },
-	{ GSM_PCHAN_CCCH,	"FCCH + SCH + BCCH + CCCH (Comb. IV)" },
-	{ GSM_PCHAN_CCCH_SDCCH4,
-		"FCCH + SCH + BCCH + CCCH + 4 SDCCH + 2 SACCH (Comb. V)" },
-	{ GSM_PCHAN_TCH_F,	"TCH/F + FACCH/F + SACCH (Comb. I)" },
-	{ GSM_PCHAN_TCH_H,	"2 TCH/H + 2 FACCH/H + 2 SACCH (Comb. II)" },
-	{ GSM_PCHAN_SDCCH8_SACCH8C, "8 SDCCH + 4 SACCH (Comb. VII)" },
-	{ GSM_PCHAN_PDCH,	"Packet Data Channel for GPRS/EDGE" },
-	{ GSM_PCHAN_TCH_F_PDCH,	"Dynamic TCH/F or GPRS PDCH" },
-	{ GSM_PCHAN_UNKNOWN,	"Unknown / Unsupported channel combination" },
-	{ GSM_PCHAN_CCCH_SDCCH4_CBCH, "FCCH + SCH + BCCH + CCCH + CBCH + 3 SDCCH + 2 SACCH (Comb. V)" },
-	{ GSM_PCHAN_SDCCH8_SACCH8C_CBCH, "7 SDCCH + 4 SACCH + CBCH (Comb. VII)" },
-	{ GSM_PCHAN_TCH_F_TCH_H_PDCH, "Dynamic TCH/F or TCH/H or GPRS PDCH" },
-	{ 0,			NULL }
-};
-
-const char *gsm_pchan_name(enum gsm_phys_chan_config c)
-{
-	return get_value_string(gsm_pchant_names, c);
-}
-
-enum gsm_phys_chan_config gsm_pchan_parse(const char *name)
-{
-	return get_string_value(gsm_pchant_names, name);
-}
-
-/* TODO: move to libosmocore, next to gsm_chan_t_names? */
-const char *gsm_lchant_name(enum gsm_chan_t c)
-{
-	return get_value_string(gsm_chan_t_names, c);
-}
-
-static const struct value_string lchan_s_names[] = {
-	{ LCHAN_S_NONE,		"NONE" },
-	{ LCHAN_S_ACT_REQ,	"ACTIVATION REQUESTED" },
-	{ LCHAN_S_ACTIVE,	"ACTIVE" },
-	{ LCHAN_S_INACTIVE,	"INACTIVE" },
-	{ LCHAN_S_REL_REQ,	"RELEASE REQUESTED" },
-	{ LCHAN_S_REL_ERR,	"RELEASE DUE ERROR" },
-	{ LCHAN_S_BROKEN,	"BROKEN UNUSABLE" },
-	{ 0,			NULL }
-};
-
-const char *gsm_lchans_name(enum gsm_lchan_state s)
-{
-	return get_value_string(lchan_s_names, s);
-}
-
-static const struct value_string chreq_names[] = {
-	{ GSM_CHREQ_REASON_EMERG,	"EMERGENCY" },
-	{ GSM_CHREQ_REASON_PAG,		"PAGING" },
-	{ GSM_CHREQ_REASON_CALL,	"CALL" },
-	{ GSM_CHREQ_REASON_LOCATION_UPD,"LOCATION_UPDATE" },
-	{ GSM_CHREQ_REASON_OTHER,	"OTHER" },
-	{ 0,				NULL }
-};
-
-const char *gsm_chreq_name(enum gsm_chreq_reason_t c)
-{
-	return get_value_string(chreq_names, c);
-}
-
-struct gsm_bts *gsm_bts_num(struct gsm_network *net, int num)
-{
-	struct gsm_bts *bts;
-
-	if (num >= net->num_bts)
-		return NULL;
-
-	llist_for_each_entry(bts, &net->bts_list, list) {
-		if (bts->nr == num)
-			return bts;
-	}
-
-	return NULL;
-}
-
-struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
-{
-	struct gsm_bts_trx *trx = talloc_zero(bts, struct gsm_bts_trx);
-	int k;
-
-	if (!trx)
-		return NULL;
-
-	trx->bts = bts;
-	trx->nr = bts->num_trx++;
-	trx->mo.nm_state.administrative = NM_STATE_UNLOCKED;
-
-	gsm_mo_init(&trx->mo, bts, NM_OC_RADIO_CARRIER,
-		    bts->nr, trx->nr, 0xff);
-	gsm_mo_init(&trx->bb_transc.mo, bts, NM_OC_BASEB_TRANSC,
-		    bts->nr, trx->nr, 0xff);
-
-	for (k = 0; k < TRX_NR_TS; k++) {
-		struct gsm_bts_trx_ts *ts = &trx->ts[k];
-		int l;
-
-		ts->trx = trx;
-		ts->nr = k;
-		ts->pchan = GSM_PCHAN_NONE;
-		ts->dyn.pchan_is = GSM_PCHAN_NONE;
-		ts->dyn.pchan_want = GSM_PCHAN_NONE;
-		ts->tsc = -1;
-
-		gsm_mo_init(&ts->mo, bts, NM_OC_CHANNEL,
-			    bts->nr, trx->nr, ts->nr);
-
-		ts->hopping.arfcns.data_len = sizeof(ts->hopping.arfcns_data);
-		ts->hopping.arfcns.data = ts->hopping.arfcns_data;
-		ts->hopping.ma.data_len = sizeof(ts->hopping.ma_data);
-		ts->hopping.ma.data = ts->hopping.ma_data;
-
-		for (l = 0; l < TS_MAX_LCHAN; l++) {
-			struct gsm_lchan *lchan;
-			char *name;
-			lchan = &ts->lchan[l];
-
-			lchan->ts = ts;
-			lchan->nr = l;
-			lchan->type = GSM_LCHAN_NONE;
-
-			name = gsm_lchan_name_compute(lchan);
-			lchan->name = talloc_strdup(trx, name);
-#ifndef ROLE_BSC
-			INIT_LLIST_HEAD(&lchan->sapi_cmds);
-#endif
-		}
-	}
-
-	if (trx->nr != 0)
-		trx->nominal_power = bts->c0->nominal_power;
-
-	llist_add_tail(&trx->list, &bts->trx_list);
-
-	return trx;
-}
-
-
-static const uint8_t bts_nse_timer_default[] = { 3, 3, 3, 3, 30, 3, 10 };
-static const uint8_t bts_cell_timer_default[] =
-				{ 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 };
-static const struct gprs_rlc_cfg rlc_cfg_default = {
-	.parameter = {
-		[RLC_T3142] = 20,
-		[RLC_T3169] = 5,
-		[RLC_T3191] = 5,
-		[RLC_T3193] = 160, /* 10ms */
-		[RLC_T3195] = 5,
-		[RLC_N3101] = 10,
-		[RLC_N3103] = 4,
-		[RLC_N3105] = 8,
-		[CV_COUNTDOWN] = 15,
-		[T_DL_TBF_EXT] = 250 * 10, /* ms */
-		[T_UL_TBF_EXT] = 250 * 10, /* ms */
-	},
-	.paging = {
-		.repeat_time = 5 * 50, /* ms */
-		.repeat_count = 3,
-	},
-	.cs_mask = 0x1fff,
-	.initial_cs = 2,
-	.initial_mcs = 6,
-};
-
-struct gsm_bts *gsm_bts_alloc(void *ctx, uint8_t bts_num)
-{
-	struct gsm_bts *bts = talloc_zero(ctx, struct gsm_bts);
-	int i;
-
-	if (!bts)
-		return NULL;
-
-	bts->nr = bts_num;
-	bts->num_trx = 0;
-	INIT_LLIST_HEAD(&bts->trx_list);
-	bts->ms_max_power = 15;	/* dBm */
-
-	gsm_mo_init(&bts->mo, bts, NM_OC_BTS,
-			bts->nr, 0xff, 0xff);
-	gsm_mo_init(&bts->site_mgr.mo, bts, NM_OC_SITE_MANAGER,
-			0xff, 0xff, 0xff);
-
-	for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) {
-		bts->gprs.nsvc[i].bts = bts;
-		bts->gprs.nsvc[i].id = i;
-		gsm_mo_init(&bts->gprs.nsvc[i].mo, bts, NM_OC_GPRS_NSVC,
-				bts->nr, i, 0xff);
-	}
-	memcpy(&bts->gprs.nse.timer, bts_nse_timer_default,
-		sizeof(bts->gprs.nse.timer));
-	gsm_mo_init(&bts->gprs.nse.mo, bts, NM_OC_GPRS_NSE,
-			bts->nr, 0xff, 0xff);
-	memcpy(&bts->gprs.cell.timer, bts_cell_timer_default,
-		sizeof(bts->gprs.cell.timer));
-	gsm_mo_init(&bts->gprs.cell.mo, bts, NM_OC_GPRS_CELL,
-			bts->nr, 0xff, 0xff);
-	memcpy(&bts->gprs.cell.rlc_cfg, &rlc_cfg_default,
-		sizeof(bts->gprs.cell.rlc_cfg));
-
-	/* create our primary TRX */
-	bts->c0 = gsm_bts_trx_alloc(bts);
-	if (!bts->c0) {
-		talloc_free(bts);
-		return NULL;
-	}
-	bts->c0->ts[0].pchan = GSM_PCHAN_CCCH_SDCCH4;
-
-	bts->rach_b_thresh = -1;
-	bts->rach_ldavg_slots = -1;
-	bts->paging.free_chans_need = -1;
-	bts->features.data = &bts->_features_data[0];
-	bts->features.data_len = sizeof(bts->_features_data);
-
-	/* si handling */
-	bts->bcch_change_mark = 1;
-
-	return bts;
-}
-
-/* reset the state of all MO in the BTS */
-void gsm_bts_mo_reset(struct gsm_bts *bts)
-{
-	struct gsm_bts_trx *trx;
-	unsigned int i;
-
-	gsm_abis_mo_reset(&bts->mo);
-	gsm_abis_mo_reset(&bts->site_mgr.mo);
-	for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++)
-		gsm_abis_mo_reset(&bts->gprs.nsvc[i].mo);
-	gsm_abis_mo_reset(&bts->gprs.nse.mo);
-	gsm_abis_mo_reset(&bts->gprs.cell.mo);
-
-	llist_for_each_entry(trx, &bts->trx_list, list) {
-		gsm_abis_mo_reset(&trx->mo);
-		gsm_abis_mo_reset(&trx->bb_transc.mo);
-
-		for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
-			struct gsm_bts_trx_ts *ts = &trx->ts[i];
-			gsm_abis_mo_reset(&ts->mo);
-		}
-	}
-}
-
-struct gsm_bts_trx *gsm_bts_trx_num(const struct gsm_bts *bts, int num)
-{
-	struct gsm_bts_trx *trx;
-
-	if (num >= bts->num_trx)
-		return NULL;
-
-	llist_for_each_entry(trx, &bts->trx_list, list) {
-		if (trx->nr == num)
-			return trx;
-	}
-
-	return NULL;
-}
-
-static char ts2str[255];
-
-char *gsm_trx_name(const struct gsm_bts_trx *trx)
-{
-	if (!trx)
-		snprintf(ts2str, sizeof(ts2str), "(trx=NULL)");
-	else
-		snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d)",
-			 trx->bts->nr, trx->nr);
-
-	return ts2str;
-}
-
-
-char *gsm_ts_name(const struct gsm_bts_trx_ts *ts)
-{
-	snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d)",
-		 ts->trx->bts->nr, ts->trx->nr, ts->nr);
-
-	return ts2str;
-}
-
-/*! Log timeslot number with full pchan information */
-char *gsm_ts_and_pchan_name(const struct gsm_bts_trx_ts *ts)
-{
-	switch (ts->pchan) {
-	case GSM_PCHAN_TCH_F_TCH_H_PDCH:
-		if (ts->dyn.pchan_is == ts->dyn.pchan_want)
-			snprintf(ts2str, sizeof(ts2str),
-				 "(bts=%d,trx=%d,ts=%d,pchan=%s as %s)",
-				 ts->trx->bts->nr, ts->trx->nr, ts->nr,
-				 gsm_pchan_name(ts->pchan),
-				 gsm_pchan_name(ts->dyn.pchan_is));
-		else
-			snprintf(ts2str, sizeof(ts2str),
-				 "(bts=%d,trx=%d,ts=%d,pchan=%s"
-				 " switching %s -> %s)",
-				 ts->trx->bts->nr, ts->trx->nr, ts->nr,
-				 gsm_pchan_name(ts->pchan),
-				 gsm_pchan_name(ts->dyn.pchan_is),
-				 gsm_pchan_name(ts->dyn.pchan_want));
-		break;
-	case GSM_PCHAN_TCH_F_PDCH:
-		if ((ts->flags & TS_F_PDCH_PENDING_MASK) == 0)
-			snprintf(ts2str, sizeof(ts2str),
-				 "(bts=%d,trx=%d,ts=%d,pchan=%s as %s)",
-				 ts->trx->bts->nr, ts->trx->nr, ts->nr,
-				 gsm_pchan_name(ts->pchan),
-				 (ts->flags & TS_F_PDCH_ACTIVE)? "PDCH"
-							       : "TCH/F");
-		else
-			snprintf(ts2str, sizeof(ts2str),
-				 "(bts=%d,trx=%d,ts=%d,pchan=%s"
-				 " switching %s -> %s)",
-				 ts->trx->bts->nr, ts->trx->nr, ts->nr,
-				 gsm_pchan_name(ts->pchan),
-				 (ts->flags & TS_F_PDCH_ACTIVE)? "PDCH"
-							       : "TCH/F",
-				 (ts->flags & TS_F_PDCH_ACT_PENDING)? "PDCH"
-								    : "TCH/F");
-		break;
-	default:
-		snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d,pchan=%s)",
-			 ts->trx->bts->nr, ts->trx->nr, ts->nr,
-			 gsm_pchan_name(ts->pchan));
-		break;
-	}
-
-	return ts2str;
-}
-
-char *gsm_lchan_name_compute(const struct gsm_lchan *lchan)
-{
-	struct gsm_bts_trx_ts *ts = lchan->ts;
-
-	snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d,ss=%d)",
-		 ts->trx->bts->nr, ts->trx->nr, ts->nr, lchan->nr);
-
-	return ts2str;
-}
-
-/* obtain the MO structure for a given object instance */
-struct gsm_abis_mo *
-gsm_objclass2mo(struct gsm_bts *bts, uint8_t obj_class,
-	    const struct abis_om_obj_inst *obj_inst)
-{
-	struct gsm_bts_trx *trx;
-	struct gsm_abis_mo *mo = NULL;
-
-	switch (obj_class) {
-	case NM_OC_BTS:
-		mo = &bts->mo;
-		break;
-	case NM_OC_RADIO_CARRIER:
-		if (obj_inst->trx_nr >= bts->num_trx) {
-			return NULL;
-		}
-		trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
-		mo = &trx->mo;
-		break;
-	case NM_OC_BASEB_TRANSC:
-		if (obj_inst->trx_nr >= bts->num_trx) {
-			return NULL;
-		}
-		trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
-		mo = &trx->bb_transc.mo;
-		break;
-	case NM_OC_CHANNEL:
-		if (obj_inst->trx_nr >= bts->num_trx) {
-			return NULL;
-		}
-		trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
-		if (obj_inst->ts_nr >= TRX_NR_TS)
-			return NULL;
-		mo = &trx->ts[obj_inst->ts_nr].mo;
-		break;
-	case NM_OC_SITE_MANAGER:
-		mo = &bts->site_mgr.mo;
-		break;
-	case NM_OC_BS11:
-		switch (obj_inst->bts_nr) {
-		case BS11_OBJ_CCLK:
-			mo = &bts->bs11.cclk.mo;
-			break;
-		case BS11_OBJ_BBSIG:
-			if (obj_inst->ts_nr > bts->num_trx)
-				return NULL;
-			trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
-			mo = &trx->bs11.bbsig.mo;
-			break;
-		case BS11_OBJ_PA:
-			if (obj_inst->ts_nr > bts->num_trx)
-				return NULL;
-			trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
-			mo = &trx->bs11.pa.mo;
-			break;
-		default:
-			return NULL;
-		}
-		break;
-	case NM_OC_BS11_RACK:
-		mo = &bts->bs11.rack.mo;
-		break;
-	case NM_OC_BS11_ENVABTSE:
-		if (obj_inst->trx_nr >= ARRAY_SIZE(bts->bs11.envabtse))
-			return NULL;
-		mo = &bts->bs11.envabtse[obj_inst->trx_nr].mo;
-		break;
-	case NM_OC_GPRS_NSE:
-		mo = &bts->gprs.nse.mo;
-		break;
-	case NM_OC_GPRS_CELL:
-		mo = &bts->gprs.cell.mo;
-		break;
-	case NM_OC_GPRS_NSVC:
-		if (obj_inst->trx_nr >= ARRAY_SIZE(bts->gprs.nsvc))
-			return NULL;
-		mo = &bts->gprs.nsvc[obj_inst->trx_nr].mo;
-		break;
-	}
-	return mo;
-}
-
-/* obtain the gsm_nm_state data structure for a given object instance */
-struct gsm_nm_state *
-gsm_objclass2nmstate(struct gsm_bts *bts, uint8_t obj_class,
-		 const struct abis_om_obj_inst *obj_inst)
-{
-	struct gsm_abis_mo *mo;
-
-	mo = gsm_objclass2mo(bts, obj_class, obj_inst);
-	if (!mo)
-		return NULL;
-
-	return &mo->nm_state;
-}
-
-/* obtain the in-memory data structure of a given object instance */
-void *
-gsm_objclass2obj(struct gsm_bts *bts, uint8_t obj_class,
-	     const struct abis_om_obj_inst *obj_inst)
-{
-	struct gsm_bts_trx *trx;
-	void *obj = NULL;
-
-	switch (obj_class) {
-	case NM_OC_BTS:
-		obj = bts;
-		break;
-	case NM_OC_RADIO_CARRIER:
-		if (obj_inst->trx_nr >= bts->num_trx) {
-			return NULL;
-		}
-		trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
-		obj = trx;
-		break;
-	case NM_OC_BASEB_TRANSC:
-		if (obj_inst->trx_nr >= bts->num_trx) {
-			return NULL;
-		}
-		trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
-		obj = &trx->bb_transc;
-		break;
-	case NM_OC_CHANNEL:
-		if (obj_inst->trx_nr >= bts->num_trx) {
-			return NULL;
-		}
-		trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
-		if (obj_inst->ts_nr >= TRX_NR_TS)
-			return NULL;
-		obj = &trx->ts[obj_inst->ts_nr];
-		break;
-	case NM_OC_SITE_MANAGER:
-		obj = &bts->site_mgr;
-		break;
-	case NM_OC_GPRS_NSE:
-		obj = &bts->gprs.nse;
-		break;
-	case NM_OC_GPRS_CELL:
-		obj = &bts->gprs.cell;
-		break;
-	case NM_OC_GPRS_NSVC:
-		if (obj_inst->trx_nr >= ARRAY_SIZE(bts->gprs.nsvc))
-			return NULL;
-		obj = &bts->gprs.nsvc[obj_inst->trx_nr];
-		break;
-	}
-	return obj;
-}
-
-/* See Table 10.5.25 of GSM04.08 */
-uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan,
-			  uint8_t ts_nr, uint8_t lchan_nr)
-{
-	uint8_t cbits, chan_nr;
-
-	switch (pchan) {
-	case GSM_PCHAN_TCH_F:
-	case GSM_PCHAN_TCH_F_PDCH:
-		OSMO_ASSERT(lchan_nr == 0);
-		cbits = 0x01;
-		break;
-	case GSM_PCHAN_PDCH:
-		OSMO_ASSERT(lchan_nr == 0);
-		cbits = RSL_CHAN_OSMO_PDCH >> 3;
-		break;
-	case GSM_PCHAN_TCH_H:
-		OSMO_ASSERT(lchan_nr < 2);
-		cbits = 0x02;
-		cbits += lchan_nr;
-		break;
-	case GSM_PCHAN_CCCH_SDCCH4:
-	case GSM_PCHAN_CCCH_SDCCH4_CBCH:
-		/*
-		 * As a special hack for BCCH, lchan_nr == 4 may be passed
-		 * here. This should never be sent in an RSL message.
-		 * See osmo-bts-xxx/oml.c:opstart_compl().
-		 */
-		if (lchan_nr == CCCH_LCHAN)
-			chan_nr = 0;
-		else
-			OSMO_ASSERT(lchan_nr < 4);
-		cbits = 0x04;
-		cbits += lchan_nr;
-		break;
-	case GSM_PCHAN_SDCCH8_SACCH8C:
-	case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:
-		OSMO_ASSERT(lchan_nr < 8);
-		cbits = 0x08;
-		cbits += lchan_nr;
-		break;
-	default:
-	case GSM_PCHAN_CCCH:
-#ifdef ROLE_BSC
-		OSMO_ASSERT(lchan_nr == 0);
-#else
-		/*
-		 * FIXME: On octphy and litecell, we hit above assertion (see
-		 * Max's comment at https://gerrit.osmocom.org/589 ); disabled
-		 * for BTS until this is clarified; remove the #ifdef when it
-		 * is fixed.
-		 */
-#warning "fix caller that passes lchan_nr != 0"
-#endif
-		cbits = 0x10;
-		break;
-	}
-
-	chan_nr = (cbits << 3) | (ts_nr & 0x7);
-
-	return chan_nr;
-}
-
-uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan)
-{
-	enum gsm_phys_chan_config pchan = lchan->ts->pchan;
-	if (pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH)
-		return gsm_lchan_as_pchan2chan_nr(lchan,
-						  lchan->ts->dyn.pchan_is);
-	return gsm_pchan2chan_nr(lchan->ts->pchan, lchan->ts->nr, lchan->nr);
-}
-
-uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan,
-				   enum gsm_phys_chan_config as_pchan)
-{
-	if (lchan->ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH
-	    && as_pchan == GSM_PCHAN_PDCH)
-		return RSL_CHAN_OSMO_PDCH | (lchan->ts->nr & ~RSL_CHAN_NR_MASK);
-	return gsm_pchan2chan_nr(as_pchan, lchan->ts->nr, lchan->nr);
-}
-
-/* return the gsm_lchan for the CBCH (if it exists at all) */
-struct gsm_lchan *gsm_bts_get_cbch(struct gsm_bts *bts)
-{
-	struct gsm_lchan *lchan = NULL;
-	struct gsm_bts_trx *trx = bts->c0;
-
-	if (trx->ts[0].pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH)
-		lchan = &trx->ts[0].lchan[2];
-	else {
-		int i;
-		for (i = 0; i < 8; i++) {
-			if (trx->ts[i].pchan == GSM_PCHAN_SDCCH8_SACCH8C_CBCH) {
-				lchan = &trx->ts[i].lchan[2];
-				break;
-			}
-		}
-	}
-
-	return lchan;
-}
-
-/* determine logical channel based on TRX and channel number IE */
-struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,
-				   int *rc)
-{
-	uint8_t ts_nr = chan_nr & 0x07;
-	uint8_t cbits = chan_nr >> 3;
-	uint8_t lch_idx;
-	struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
-	bool ok = true;
-
-	if (rc)
-		*rc = -EINVAL;
-
-	if (cbits == 0x01) {
-		lch_idx = 0;	/* TCH/F */	
-		if (ts->pchan != GSM_PCHAN_TCH_F &&
-		    ts->pchan != GSM_PCHAN_PDCH &&
-		    ts->pchan != GSM_PCHAN_TCH_F_PDCH
-		    && !(ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH
-			 && (ts->dyn.pchan_is == GSM_PCHAN_TCH_F
-			     || ts->dyn.pchan_want == GSM_PCHAN_TCH_F)))
-			ok = false;
-	} else if ((cbits & 0x1e) == 0x02) {
-		lch_idx = cbits & 0x1;	/* TCH/H */
-		if (ts->pchan != GSM_PCHAN_TCH_H
-		    && !(ts->pchan == GSM_PCHAN_TCH_F_TCH_H_PDCH
-			 && (ts->dyn.pchan_is == GSM_PCHAN_TCH_H
-			     || ts->dyn.pchan_want == GSM_PCHAN_TCH_H)))
-			ok = false;
-	} else if ((cbits & 0x1c) == 0x04) {
-		lch_idx = cbits & 0x3;	/* SDCCH/4 */
-		if (ts->pchan != GSM_PCHAN_CCCH_SDCCH4 &&
-		    ts->pchan != GSM_PCHAN_CCCH_SDCCH4_CBCH)
-			ok = false;
-	} else if ((cbits & 0x18) == 0x08) {
-		lch_idx = cbits & 0x7;	/* SDCCH/8 */
-		if (ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C &&
-		    ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C_CBCH)
-			ok = false;
-	} else if (cbits == 0x10 || cbits == 0x11 || cbits == 0x12) {
-		lch_idx = 0;
-		if (ts->pchan != GSM_PCHAN_CCCH &&
-		    ts->pchan != GSM_PCHAN_CCCH_SDCCH4 &&
-		    ts->pchan != GSM_PCHAN_CCCH_SDCCH4_CBCH)
-			ok = false;
-		/* FIXME: we should not return first sdcch4 !!! */
-	} else if ((chan_nr & RSL_CHAN_NR_MASK) == RSL_CHAN_OSMO_PDCH) {
-		lch_idx = 0;
-		if (ts->pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH)
-			ok = false;
-	} else
-		return NULL;
-
-	if (rc && ok)
-		*rc = 0;
-
-	return &ts->lchan[lch_idx];
-}
-
-static const uint8_t subslots_per_pchan[] = {
-	[GSM_PCHAN_NONE] = 0,
-	[GSM_PCHAN_CCCH] = 0,
-	[GSM_PCHAN_PDCH] = 0,
-	[GSM_PCHAN_CCCH_SDCCH4] = 4,
-	[GSM_PCHAN_TCH_F] = 1,
-	[GSM_PCHAN_TCH_H] = 2,
-	[GSM_PCHAN_SDCCH8_SACCH8C] = 8,
-	[GSM_PCHAN_CCCH_SDCCH4_CBCH] = 4,
-	[GSM_PCHAN_SDCCH8_SACCH8C_CBCH] = 8,
-	/*
-	 * GSM_PCHAN_TCH_F_PDCH and GSM_PCHAN_TCH_F_TCH_H_PDCH should not be
-	 * part of this, those TS are handled according to their dynamic state.
-	 */
-};
-
-/*! Return the actual pchan type, also heeding dynamic TS. */
-enum gsm_phys_chan_config ts_pchan(struct gsm_bts_trx_ts *ts)
-{
-	switch (ts->pchan) {
-	case GSM_PCHAN_TCH_F_TCH_H_PDCH:
-		return ts->dyn.pchan_is;
-	case GSM_PCHAN_TCH_F_PDCH:
-		if (ts->flags & TS_F_PDCH_ACTIVE)
-			return GSM_PCHAN_PDCH;
-		else
-			return GSM_PCHAN_TCH_F;
-	default:
-		return ts->pchan;
-	}
-}
-
-/*! According to ts->pchan and possibly ts->dyn_pchan, return the number of
- * logical channels available in the timeslot. */
-uint8_t ts_subslots(struct gsm_bts_trx_ts *ts)
-{
-	return subslots_per_pchan[ts_pchan(ts)];
-}
-
-static bool pchan_is_tch(enum gsm_phys_chan_config pchan)
-{
-	switch (pchan) {
-	case GSM_PCHAN_TCH_F:
-	case GSM_PCHAN_TCH_H:
-		return true;
-	default:
-		return false;
-	}
-}
-
-bool ts_is_tch(struct gsm_bts_trx_ts *ts)
-{
-	return pchan_is_tch(ts_pchan(ts));
-}
diff --git a/src/libcommon/gsm_subscriber_base.c b/src/libcommon/gsm_subscriber_base.c
deleted file mode 100644
index 018ed21..0000000
--- a/src/libcommon/gsm_subscriber_base.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/* The concept of a subscriber as seen by the BSC */
-
-/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009-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/>.
- *
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/debug.h>
-#include <openbsc/vlr.h>
-
-LLIST_HEAD(active_subscribers);
-void *tall_subscr_ctx;
-
-/* return static buffer with printable name of VLR subscriber */
-const char *vlr_subscr_name(struct vlr_subscr *vsub)
-{
-	static char buf[32];
-	if (!vsub)
-		return "unknown";
-	if (vsub->msisdn[0])
-		snprintf(buf, sizeof(buf), "MSISDN:%s", vsub->msisdn);
-	else if (vsub->imsi[0])
-		snprintf(buf, sizeof(buf), "IMSI:%s", vsub->imsi);
-	else if (vsub->tmsi != GSM_RESERVED_TMSI)
-		snprintf(buf, sizeof(buf), "TMSI:0x%08x", vsub->tmsi);
-	else if (vsub->tmsi_new != GSM_RESERVED_TMSI)
-		snprintf(buf, sizeof(buf), "TMSI(new):0x%08x", vsub->tmsi_new);
-	else
-		return "unknown";
-	buf[sizeof(buf)-1] = '\0';
-	return buf;
-}
-
-const char *vlr_subscr_msisdn_or_name(struct vlr_subscr *vsub)
-{
-	if (!vsub || !vsub->msisdn[0])
-		return vlr_subscr_name(vsub);
-	return vsub->msisdn;
-}
diff --git a/src/libcommon/gsup_client.c b/src/libcommon/gsup_client.c
deleted file mode 100644
index 258f230..0000000
--- a/src/libcommon/gsup_client.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/* Generic Subscriber Update Protocol client */
-
-/* (C) 2014-2016 by Sysmocom s.f.m.c. GmbH
- * All Rights Reserved
- *
- * Author: Jacob Erlbeck
- * 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/>.
- *
- */
-
-#include <openbsc/gsup_client.h>
-
-#include <osmocom/abis/ipa.h>
-#include <osmocom/gsm/protocol/ipaccess.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/logging.h>
-
-#include <openbsc/debug.h>
-
-#include <errno.h>
-#include <string.h>
-
-extern void *tall_bsc_ctx;
-
-static void start_test_procedure(struct gsup_client *gsupc);
-
-static void gsup_client_send_ping(struct gsup_client *gsupc)
-{
-	struct msgb *msg = gsup_client_msgb_alloc();
-
-	msg->l2h = msgb_put(msg, 1);
-	msg->l2h[0] = IPAC_MSGT_PING;
-	ipa_msg_push_header(msg, IPAC_PROTO_IPACCESS);
-	ipa_client_conn_send(gsupc->link, msg);
-}
-
-static int gsup_client_connect(struct gsup_client *gsupc)
-{
-	int rc;
-
-	if (gsupc->is_connected)
-		return 0;
-
-	if (osmo_timer_pending(&gsupc->connect_timer)) {
-		LOGP(DLGSUP, LOGL_DEBUG,
-		     "GSUP connect: connect timer already running\n");
-		osmo_timer_del(&gsupc->connect_timer);
-	}
-
-	if (osmo_timer_pending(&gsupc->ping_timer)) {
-		LOGP(DLGSUP, LOGL_DEBUG,
-		     "GSUP connect: ping timer already running\n");
-		osmo_timer_del(&gsupc->ping_timer);
-	}
-
-	if (ipa_client_conn_clear_queue(gsupc->link) > 0)
-		LOGP(DLGSUP, LOGL_DEBUG, "GSUP connect: discarded stored messages\n");
-
-	rc = ipa_client_conn_open(gsupc->link);
-
-	if (rc >= 0) {
-		LOGP(DLGSUP, LOGL_NOTICE, "GSUP connecting to %s:%d\n",
-		     gsupc->link->addr, gsupc->link->port);
-		return 0;
-	}
-
-	LOGP(DLGSUP, LOGL_ERROR, "GSUP failed to connect to %s:%d: %s\n",
-	     gsupc->link->addr, gsupc->link->port, strerror(-rc));
-
-	if (rc == -EBADF || rc == -ENOTSOCK || rc == -EAFNOSUPPORT ||
-	    rc == -EINVAL)
-		return rc;
-
-	osmo_timer_schedule(&gsupc->connect_timer,
-			    GSUP_CLIENT_RECONNECT_INTERVAL, 0);
-
-	LOGP(DLGSUP, LOGL_INFO, "Scheduled timer to retry GSUP connect to %s:%d\n",
-	     gsupc->link->addr, gsupc->link->port);
-
-	return 0;
-}
-
-static void connect_timer_cb(void *gsupc_)
-{
-	struct gsup_client *gsupc = gsupc_;
-
-	if (gsupc->is_connected)
-		return;
-
-	gsup_client_connect(gsupc);
-}
-
-static void client_send(struct gsup_client *gsupc, int proto_ext,
-			struct msgb *msg_tx)
-{
-	ipa_prepend_header_ext(msg_tx, proto_ext);
-	ipa_msg_push_header(msg_tx, IPAC_PROTO_OSMO);
-	ipa_client_conn_send(gsupc->link, msg_tx);
-	/* msg_tx is now queued and will be freed. */
-}
-
-static void gsup_client_oap_register(struct gsup_client *gsupc)
-{
-	struct msgb *msg_tx;
-	int rc;
-	rc = oap_client_register(&gsupc->oap_state, &msg_tx);
-
-	if ((rc < 0) || (!msg_tx)) {
-		LOGP(DLGSUP, LOGL_ERROR, "GSUP OAP set up, but cannot register.\n");
-		return;
-	}
-
-	client_send(gsupc, IPAC_PROTO_EXT_OAP, msg_tx);
-}
-
-static void gsup_client_updown_cb(struct ipa_client_conn *link, int up)
-{
-	struct gsup_client *gsupc = link->data;
-
-	LOGP(DLGSUP, LOGL_INFO, "GSUP link to %s:%d %s\n",
-		     link->addr, link->port, up ? "UP" : "DOWN");
-
-	gsupc->is_connected = up;
-
-	if (up) {
-		start_test_procedure(gsupc);
-
-		if (gsupc->oap_state.state == OAP_INITIALIZED)
-			gsup_client_oap_register(gsupc);
-
-		osmo_timer_del(&gsupc->connect_timer);
-	} else {
-		osmo_timer_del(&gsupc->ping_timer);
-
-		osmo_timer_schedule(&gsupc->connect_timer,
-				    GSUP_CLIENT_RECONNECT_INTERVAL, 0);
-	}
-}
-
-static int gsup_client_oap_handle(struct gsup_client *gsupc, struct msgb *msg_rx)
-{
-	int rc;
-	struct msgb *msg_tx;
-
-	/* If the oap_state is disabled, this will reject the messages. */
-	rc = oap_client_handle(&gsupc->oap_state, msg_rx, &msg_tx);
-	msgb_free(msg_rx);
-	if (rc < 0)
-		return rc;
-
-	if (msg_tx)
-		client_send(gsupc, IPAC_PROTO_EXT_OAP, msg_tx);
-
-	return 0;
-}
-
-static int gsup_client_read_cb(struct ipa_client_conn *link, struct msgb *msg)
-{
-	struct ipaccess_head *hh = (struct ipaccess_head *) msg->data;
-	struct ipaccess_head_ext *he = (struct ipaccess_head_ext *) msgb_l2(msg);
-	struct gsup_client *gsupc = (struct gsup_client *)link->data;
-	int rc;
-	struct ipaccess_unit ipa_dev = {
-		/* see gsup_client_create() on const vs non-const */
-		.unit_name = (char*)gsupc->unit_name,
-	};
-
-	OSMO_ASSERT(ipa_dev.unit_name);
-
-	msg->l2h = &hh->data[0];
-
-	rc = ipaccess_bts_handle_ccm(link, &ipa_dev, msg);
-
-	if (rc < 0) {
-		LOGP(DLGSUP, LOGL_NOTICE,
-		     "GSUP received an invalid IPA/CCM message from %s:%d\n",
-		     link->addr, link->port);
-		/* Link has been closed */
-		gsupc->is_connected = 0;
-		msgb_free(msg);
-		return -1;
-	}
-
-	if (rc == 1) {
-		uint8_t msg_type = *(msg->l2h);
-		/* CCM message */
-		if (msg_type == IPAC_MSGT_PONG) {
-			LOGP(DLGSUP, LOGL_DEBUG, "GSUP receiving PONG\n");
-			gsupc->got_ipa_pong = 1;
-		}
-
-		msgb_free(msg);
-		return 0;
-	}
-
-	if (hh->proto != IPAC_PROTO_OSMO)
-		goto invalid;
-
-	if (!he || msgb_l2len(msg) < sizeof(*he))
-		goto invalid;
-
-	msg->l2h = &he->data[0];
-
-	if (he->proto == IPAC_PROTO_EXT_GSUP) {
-		OSMO_ASSERT(gsupc->read_cb != NULL);
-		gsupc->read_cb(gsupc, msg);
-		/* expecting read_cb() to free msg */
-	} else if (he->proto == IPAC_PROTO_EXT_OAP) {
-		return gsup_client_oap_handle(gsupc, msg);
-		/* gsup_client_oap_handle frees msg */
-	} else
-		goto invalid;
-
-	return 0;
-
-invalid:
-	LOGP(DLGSUP, LOGL_NOTICE,
-	     "GSUP received an invalid IPA message from %s:%d, size = %d\n",
-	     link->addr, link->port, msgb_length(msg));
-
-	msgb_free(msg);
-	return -1;
-}
-
-static void ping_timer_cb(void *gsupc_)
-{
-	struct gsup_client *gsupc = gsupc_;
-
-	LOGP(DLGSUP, LOGL_INFO, "GSUP ping callback (%s, %s PONG)\n",
-	     gsupc->is_connected ? "connected" : "not connected",
-	     gsupc->got_ipa_pong ? "got" : "didn't get");
-
-	if (gsupc->got_ipa_pong) {
-		start_test_procedure(gsupc);
-		return;
-	}
-
-	LOGP(DLGSUP, LOGL_NOTICE, "GSUP ping timed out, reconnecting\n");
-	ipa_client_conn_close(gsupc->link);
-	gsupc->is_connected = 0;
-
-	gsup_client_connect(gsupc);
-}
-
-static void start_test_procedure(struct gsup_client *gsupc)
-{
-	osmo_timer_setup(&gsupc->ping_timer, ping_timer_cb, gsupc);
-
-	gsupc->got_ipa_pong = 0;
-	osmo_timer_schedule(&gsupc->ping_timer, GSUP_CLIENT_PING_INTERVAL, 0);
-	LOGP(DLGSUP, LOGL_DEBUG, "GSUP sending PING\n");
-	gsup_client_send_ping(gsupc);
-}
-
-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)
-{
-	struct gsup_client *gsupc;
-	int rc;
-
-	gsupc = talloc_zero(tall_bsc_ctx, struct gsup_client);
-	OSMO_ASSERT(gsupc);
-
-	/* struct ipaccess_unit has a non-const unit_name, so let's copy to be
-	 * able to have a non-const unit_name here as well. To not taint the
-	 * public gsup_client API, let's store it in a const char* anyway. */
-	gsupc->unit_name = talloc_strdup(gsupc, unit_name);
-	OSMO_ASSERT(gsupc->unit_name);
-
-	/* a NULL oapc_config will mark oap_state disabled. */
-	rc = oap_client_init(oapc_config, &gsupc->oap_state);
-	if (rc != 0)
-		goto failed;
-
-	gsupc->link = ipa_client_conn_create(gsupc,
-					     /* no e1inp */ NULL,
-					     0,
-					     ip_addr, tcp_port,
-					     gsup_client_updown_cb,
-					     gsup_client_read_cb,
-					     /* default write_cb */ NULL,
-					     gsupc);
-	if (!gsupc->link)
-		goto failed;
-
-	osmo_timer_setup(&gsupc->connect_timer, connect_timer_cb, gsupc);
-
-	rc = gsup_client_connect(gsupc);
-
-	if (rc < 0)
-		goto failed;
-
-	gsupc->read_cb = read_cb;
-
-	return gsupc;
-
-failed:
-	gsup_client_destroy(gsupc);
-	return NULL;
-}
-
-void gsup_client_destroy(struct gsup_client *gsupc)
-{
-	osmo_timer_del(&gsupc->connect_timer);
-	osmo_timer_del(&gsupc->ping_timer);
-
-	if (gsupc->link) {
-		ipa_client_conn_close(gsupc->link);
-		ipa_client_conn_destroy(gsupc->link);
-		gsupc->link = NULL;
-	}
-	talloc_free(gsupc);
-}
-
-int gsup_client_send(struct gsup_client *gsupc, struct msgb *msg)
-{
-	if (!gsupc) {
-		LOGP(DGPRS, LOGL_NOTICE, "No GSUP client, unable to "
-			"send %s\n", msgb_hexdump(msg));
-		msgb_free(msg);
-		return -ENOTCONN;
-	}
-
-	if (!gsupc->is_connected) {
-		LOGP(DGPRS, LOGL_NOTICE, "GSUP not connected, unable to "
-			"send %s\n", msgb_hexdump(msg));
-		msgb_free(msg);
-		return -EAGAIN;
-	}
-
-	client_send(gsupc, IPAC_PROTO_EXT_GSUP, msg);
-
-	return 0;
-}
-
-struct msgb *gsup_client_msgb_alloc(void)
-{
-	return msgb_alloc_headroom(4000, 64, __func__);
-}
diff --git a/src/libcommon/gsup_test_client.c b/src/libcommon/gsup_test_client.c
deleted file mode 100644
index b6a8d6b..0000000
--- a/src/libcommon/gsup_test_client.c
+++ /dev/null
@@ -1,298 +0,0 @@
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <signal.h>
-
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/application.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/gsm/gsup.h>
-
-#include <openbsc/gsup_client.h>
-#include <openbsc/debug.h>
-
-static struct gsup_client *g_gc;
-
-
-/***********************************************************************
- * IMSI Operation
- ***********************************************************************/
-static LLIST_HEAD(g_imsi_ops);
-
-struct imsi_op_stats {
-	uint32_t num_alloc;
-	uint32_t num_released;
-	uint32_t num_rx_success;
-	uint32_t num_rx_error;
-	uint32_t num_timeout;
-};
-
-enum imsi_op_type {
-	IMSI_OP_SAI,
-	IMSI_OP_LU,
-	IMSI_OP_ISD,
-	_NUM_IMSI_OP
-};
-
-static const struct value_string imsi_op_names[] = {
-	{ IMSI_OP_SAI, "SAI" },
-	{ IMSI_OP_LU, "LU" },
-	{ IMSI_OP_ISD, "ISD" },
-	{ 0, NULL }
-};
-
-static struct imsi_op_stats imsi_op_stats[_NUM_IMSI_OP];
-
-struct imsi_op {
-	struct llist_head list;
-	char imsi[17];
-	enum imsi_op_type type;
-	struct osmo_timer_list timer;
-};
-
-static struct imsi_op *imsi_op_find(const char *imsi,
-			     enum imsi_op_type type)
-{
-	struct imsi_op *io;
-
-	llist_for_each_entry(io, &g_imsi_ops, list) {
-		if (!strcmp(io->imsi, imsi) && io->type == type)
-			return io;
-	}
-	return NULL;
-}
-
-static void imsi_op_timer_cb(void *data);
-
-static struct imsi_op *imsi_op_alloc(void *ctx, const char *imsi,
-				enum imsi_op_type type)
-{
-	struct imsi_op *io;
-
-	if (imsi_op_find(imsi, type))
-		return NULL;
-
-	io = talloc_zero(ctx, struct imsi_op);
-	osmo_strlcpy(io->imsi, imsi, sizeof(io->imsi));
-	io->type = type;
-	osmo_timer_setup(&io->timer, imsi_op_timer_cb, io);
-	llist_add(&io->list, &g_imsi_ops);
-	imsi_op_stats[type].num_alloc++;
-
-	return io;
-}
-
-static void imsi_op_release(struct imsi_op *io)
-{
-	osmo_timer_del(&io->timer);
-	llist_del(&io->list);
-	imsi_op_stats[io->type].num_released++;
-	talloc_free(io);
-}
-
-static void imsi_op_timer_cb(void *data)
-{
-	struct imsi_op *io = data;
-	printf("%s: Timer expiration\n", io->imsi);
-	imsi_op_stats[io->type].num_timeout++;
-	imsi_op_release(io);
-}
-
-/* allocate + generate + send Send-Auth-Info */
-int req_auth_info(const char *imsi)
-{
-	struct imsi_op *io = imsi_op_alloc(g_gc, imsi, IMSI_OP_SAI);
-	struct osmo_gsup_message gsup = {0};
-	struct msgb *msg = msgb_alloc_headroom(1200, 200, __func__);
-
-	osmo_strlcpy(gsup.imsi, io->imsi, sizeof(gsup.imsi));
-	gsup.message_type = OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST;
-
-	osmo_gsup_encode(msg, &gsup);
-
-	return gsup_client_send(g_gc, msg);
-}
-
-/* allocate + generate + send Send-Auth-Info */
-int req_loc_upd(const char *imsi)
-{
-	struct imsi_op *io = imsi_op_alloc(g_gc, imsi, IMSI_OP_LU);
-	struct osmo_gsup_message gsup = {0};
-	struct msgb *msg = msgb_alloc_headroom(1200, 200, __func__);
-
-	osmo_strlcpy(gsup.imsi, io->imsi, sizeof(gsup.imsi));
-	gsup.message_type = OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST;
-
-	osmo_gsup_encode(msg, &gsup);
-
-	return gsup_client_send(g_gc, msg);
-}
-
-int resp_isd(struct imsi_op *io)
-{
-	struct osmo_gsup_message gsup = {0};
-	struct msgb *msg = msgb_alloc_headroom(1200, 200, __func__);
-
-	osmo_strlcpy(gsup.imsi, io->imsi, sizeof(gsup.imsi));
-	gsup.message_type = OSMO_GSUP_MSGT_INSERT_DATA_RESULT;
-
-	osmo_gsup_encode(msg, &gsup);
-
-	imsi_op_release(io);
-
-	return gsup_client_send(g_gc, msg);
-}
-
-/* receive an incoming GSUP message */
-static void imsi_op_rx_gsup(struct imsi_op *io, const struct osmo_gsup_message *gsup)
-{
-	int is_error = 0;
-
-	if (OSMO_GSUP_IS_MSGT_ERROR(gsup->message_type)) {
-		imsi_op_stats[io->type].num_rx_error++;
-		is_error = 1;
-	} else
-		imsi_op_stats[io->type].num_rx_success++;
-
-	switch (io->type) {
-	case IMSI_OP_SAI:
-		printf("%s; SAI Response%s\n", io->imsi, is_error ? ": ERROR" : "");
-		/* now that we have auth tuples, request LU */
-		req_loc_upd(io->imsi);
-		imsi_op_release(io);
-		break;
-	case IMSI_OP_LU:
-		printf("%s; LU Response%s\n", io->imsi, is_error ? ": ERROR" : "");
-		imsi_op_release(io);
-		break;
-	case IMSI_OP_ISD:
-		printf("%s; ISD Request%s\n", io->imsi, is_error ? ": ERROR" : "");
-		resp_isd(io);
-		break;
-	default:
-		printf("%s: Unknown\n", io->imsi);
-		imsi_op_release(io);
-		break;
-	}
-}
-
-static int op_type_by_gsup_msgt(enum osmo_gsup_message_type msg_type)
-{
-	switch (msg_type) {
-	case OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT:
-	case OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR:
-		return IMSI_OP_SAI;
-	case OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT:
-	case OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR:
-		return IMSI_OP_LU;
-	case OSMO_GSUP_MSGT_INSERT_DATA_REQUEST:
-		return IMSI_OP_ISD;
-	default:
-		printf("Unknown GSUP msg_type %u\n", msg_type);
-		return -1;
-	}
-}
-
-static int gsupc_read_cb(struct gsup_client *gsupc, struct msgb *msg)
-{
-	struct osmo_gsup_message gsup_msg = {0};
-	struct imsi_op *io;
-	int rc;
-
-	DEBUGP(DGPRS, "Rx GSUP %s\n", osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
-
-	rc = osmo_gsup_decode(msgb_l2(msg), msgb_l2len(msg), &gsup_msg);
-	if (rc < 0)
-		return rc;
-
-	if (!gsup_msg.imsi[0])
-		return -1;
-
-	rc = op_type_by_gsup_msgt(gsup_msg.message_type);
-	if (rc < 0)
-		return rc;
-
-	switch (rc) {
-	case IMSI_OP_SAI:
-	case IMSI_OP_LU:
-		io = imsi_op_find(gsup_msg.imsi, rc);
-		if (!io)
-			return -1;
-		break;
-	case IMSI_OP_ISD:
-		/* ISD is an inbound transaction */
-		io = imsi_op_alloc(g_gc, gsup_msg.imsi, IMSI_OP_ISD);
-		break;
-	}
-
-	imsi_op_rx_gsup(io, &gsup_msg);
-	msgb_free(msg);
-
-	return 0;
-}
-
-static void print_report(void)
-{
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(imsi_op_stats); i++) {
-		struct imsi_op_stats *st = &imsi_op_stats[i];
-		const char *name = get_value_string(imsi_op_names, i);
-		printf("%s: %u alloc, %u released, %u success, %u error , %u tout\n",
-			name, st->num_alloc, st->num_released, st->num_rx_success,
-			st->num_rx_error, st->num_timeout);
-	}
-}
-
-static void sig_cb(int sig)
-{
-	switch (sig) {
-	case SIGINT:
-		print_report();
-		exit(0);
-		break;
-	}
-}
-
-void *tall_bsc_ctx = NULL;
-
-/* default categories */
-static struct log_info_cat default_categories[] = {
-};
-
-static const struct log_info gsup_test_client_log_info = {
-	.cat = default_categories,
-	.num_cat = ARRAY_SIZE(default_categories),
-};
-
-int main(int argc, char **argv)
-{
-	unsigned long long i;
-	char *server_host = "127.0.0.1";
-	uint16_t server_port = OSMO_GSUP_PORT;
-
-	osmo_init_logging(&gsup_test_client_log_info);
-
-	g_gc = gsup_client_create("GSUPTEST", server_host, server_port,
-				  gsupc_read_cb, NULL);
-
-
-	signal(SIGINT, sig_cb);
-
-	for (i = 0; i < 10000; i++) {
-		unsigned long long imsi = 901790000000000 + i;
-		char imsi_buf[17];
-		snprintf(imsi_buf, sizeof(imsi_buf), "%015llu", imsi);
-		req_auth_info(imsi_buf);
-		osmo_select_main(0);
-	}
-
-	while (1) {
-		osmo_select_main(0);
-	}
-
-	print_report();
-	exit(0);
-}
diff --git a/src/libcommon/oap_client.c b/src/libcommon/oap_client.c
deleted file mode 100644
index 5128ac1..0000000
--- a/src/libcommon/oap_client.c
+++ /dev/null
@@ -1,280 +0,0 @@
-/* Osmocom Authentication Protocol API */
-
-/* (C) 2015 by Sysmocom s.f.m.c. GmbH
- * 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/>.
- *
- */
-
-#include <string.h>
-#include <errno.h>
-
-#include <osmocom/core/utils.h>
-#include <osmocom/crypt/auth.h>
-#include <osmocom/gsm/oap.h>
-
-#include <openbsc/oap_client.h>
-#include <openbsc/debug.h>
-
-int oap_client_init(struct oap_client_config *config,
-		    struct oap_client_state *state)
-{
-	OSMO_ASSERT(state->state == OAP_UNINITIALIZED);
-
-	if (!config)
-		goto disable;
-
-	if (config->client_id == 0)
-		goto disable;
-
-	if (config->secret_k_present == 0) {
-		LOGP(DLOAP, LOGL_NOTICE, "OAP: client ID set, but secret K missing.\n");
-		goto disable;
-	}
-
-	if (config->secret_opc_present == 0) {
-		LOGP(DLOAP, LOGL_NOTICE, "OAP: client ID set, but secret OPC missing.\n");
-		goto disable;
-	}
-
-	state->client_id = config->client_id;
-	memcpy(state->secret_k, config->secret_k, sizeof(state->secret_k));
-	memcpy(state->secret_opc, config->secret_opc, sizeof(state->secret_opc));
-	state->state = OAP_INITIALIZED;
-	return 0;
-
-disable:
-	state->state = OAP_DISABLED;
-	return 0;
-}
-
-/* From the given state and received RAND and AUTN octets, validate the
- * server's authenticity and formulate the matching milenage reply octets in
- * *tx_xres. The state is not modified.
- * On success, and if tx_res is not NULL, exactly 8 octets will be written to
- * *tx_res. If not NULL, tx_res must point at allocated memory of at least 8
- * octets. The caller will want to send XRES back to the server in a challenge
- * response message and update the state.
- * Return 0 on success; -1 if OAP is disabled; -2 if rx_random and rx_autn fail
- * the authentication check; -3 for any other errors. */
-static int oap_evaluate_challenge(const struct oap_client_state *state,
-				  const uint8_t *rx_random,
-				  const uint8_t *rx_autn,
-				  uint8_t *tx_xres)
-{
-	struct osmo_auth_vector vec;
-
-	struct osmo_sub_auth_data auth = {
-		.type		= OSMO_AUTH_TYPE_UMTS,
-		.algo		= OSMO_AUTH_ALG_MILENAGE,
-	};
-
-	osmo_static_assert(sizeof(((struct osmo_sub_auth_data*)0)->u.umts.k)
-			   == sizeof(state->secret_k), _secret_k_size_match);
-	osmo_static_assert(sizeof(((struct osmo_sub_auth_data*)0)->u.umts.opc)
-			   == sizeof(state->secret_opc), _secret_opc_size_match);
-
-	switch (state->state) {
-	case OAP_UNINITIALIZED:
-	case OAP_DISABLED:
-		return -1;
-	default:
-		break;
-	}
-
-	memcpy(auth.u.umts.k, state->secret_k, sizeof(auth.u.umts.k));
-	memcpy(auth.u.umts.opc, state->secret_opc, sizeof(auth.u.umts.opc));
-	memset(auth.u.umts.amf, '\0', sizeof(auth.u.umts.amf));
-	auth.u.umts.sqn = 41; /* TODO use incrementing sequence nr */
-
-	memset(&vec, 0, sizeof(vec));
-	osmo_auth_gen_vec(&vec, &auth, rx_random);
-
-	if (vec.res_len != 8) {
-		LOGP(DLOAP, LOGL_ERROR, "OAP: Expected XRES to be 8 octets, got %d\n",
-		     vec.res_len);
-		return -3;
-	}
-
-	if (osmo_constant_time_cmp(vec.autn, rx_autn, sizeof(vec.autn)) != 0) {
-		LOGP(DLOAP, LOGL_ERROR, "OAP: AUTN mismatch!\n");
-		LOGP(DLOAP, LOGL_INFO, "OAP: AUTN from server: %s\n",
-		     osmo_hexdump_nospc(rx_autn, sizeof(vec.autn)));
-		LOGP(DLOAP, LOGL_INFO, "OAP: AUTN expected:    %s\n",
-		     osmo_hexdump_nospc(vec.autn, sizeof(vec.autn)));
-		return -2;
-	}
-
-	if (tx_xres != NULL)
-		memcpy(tx_xres, vec.res, 8);
-	return 0;
-}
-
-struct msgb *oap_client_encoded(const struct osmo_oap_message *oap_msg)
-{
-	struct msgb *msg = msgb_alloc_headroom(1000, 64, __func__);
-	OSMO_ASSERT(msg);
-	osmo_oap_encode(msg, oap_msg);
-	return msg;
-}
-
-/* Create a new msgb containing an OAP registration message.
- * On error, return NULL. */
-static struct msgb* oap_msg_register(uint16_t client_id)
-{
-	struct osmo_oap_message oap_msg = {0};
-
-	if (client_id < 1) {
-		LOGP(DLOAP, LOGL_ERROR, "OAP: Invalid client ID: %d\n", client_id);
-		return NULL;
-	}
-
-	oap_msg.message_type = OAP_MSGT_REGISTER_REQUEST;
-	oap_msg.client_id = client_id;
-	return oap_client_encoded(&oap_msg);
-}
-
-int oap_client_register(struct oap_client_state *state, struct msgb **msg_tx)
-{
-	*msg_tx = oap_msg_register(state->client_id);
-	if (!(*msg_tx))
-		return -1;
-
-	state->state = OAP_REQUESTED_CHALLENGE;
-	return 0;
-}
-
-/* Create a new msgb containing an OAP challenge response message.
- * xres must point at 8 octets to return as challenge response.
- * On error, return NULL. */
-static struct msgb* oap_msg_challenge_response(uint8_t *xres)
-{
-	struct osmo_oap_message oap_reply = {0};
-
-	oap_reply.message_type = OAP_MSGT_CHALLENGE_RESULT;
-	memcpy(oap_reply.xres, xres, sizeof(oap_reply.xres));
-	oap_reply.xres_present = 1;
-	return oap_client_encoded(&oap_reply);
-}
-
-static int handle_challenge(struct oap_client_state *state,
-			    struct osmo_oap_message *oap_rx,
-			    struct msgb **msg_tx)
-{
-	int rc;
-	uint8_t xres[8];
-
-	if (!(oap_rx->rand_present && oap_rx->autn_present)) {
-		LOGP(DLOAP, LOGL_ERROR,
-		     "OAP challenge incomplete (rand_present: %d, autn_present: %d)\n",
-		     oap_rx->rand_present, oap_rx->autn_present);
-		rc = -2;
-		goto failure;
-	}
-
-	rc = oap_evaluate_challenge(state,
-				    oap_rx->rand,
-				    oap_rx->autn,
-				    xres);
-	if (rc < 0)
-		goto failure;
-
-	*msg_tx = oap_msg_challenge_response(xres);
-	if ((*msg_tx) == NULL) {
-		rc = -1;
-		goto failure;
-	}
-
-	state->state = OAP_SENT_CHALLENGE_RESULT;
-	return 0;
-
-failure:
-	OSMO_ASSERT(rc < 0);
-	state->state = OAP_INITIALIZED;
-	return rc;
-}
-
-int oap_client_handle(struct oap_client_state *state,
-		      const struct msgb *msg_rx, struct msgb **msg_tx)
-{
-	uint8_t *data = msgb_l2(msg_rx);
-	size_t data_len = msgb_l2len(msg_rx);
-	struct osmo_oap_message oap_msg = {0};
-	int rc = 0;
-
-	*msg_tx = NULL;
-
-	OSMO_ASSERT(data);
-
-	rc = osmo_oap_decode(&oap_msg, data, data_len);
-	if (rc < 0) {
-		LOGP(DLOAP, LOGL_ERROR,
-		     "Decoding OAP message failed with error '%s' (%d)\n",
-		     get_value_string(gsm48_gmm_cause_names, -rc), -rc);
-		return -10;
-	}
-
-	switch (state->state) {
-	case OAP_UNINITIALIZED:
-		LOGP(DLOAP, LOGL_ERROR,
-		     "Received OAP message %d, but the OAP client is"
-		     " not initialized\n", oap_msg.message_type);
-		return -ENOTCONN;
-	case OAP_DISABLED:
-		LOGP(DLOAP, LOGL_ERROR,
-		     "Received OAP message %d, but the OAP client is"
-		     " disabled\n", oap_msg.message_type);
-		return -ENOTCONN;
-	default:
-		break;
-	}
-
-	switch (oap_msg.message_type) {
-	case OAP_MSGT_CHALLENGE_REQUEST:
-		return handle_challenge(state, &oap_msg, msg_tx);
-
-	case OAP_MSGT_REGISTER_RESULT:
-		/* successfully registered */
-		state->state = OAP_REGISTERED;
-		break;
-
-	case OAP_MSGT_REGISTER_ERROR:
-		LOGP(DLOAP, LOGL_ERROR,
-		     "OAP registration failed\n");
-		state->state = OAP_INITIALIZED;
-		if (state->registration_failures < 3) {
-			state->registration_failures ++;
-			return oap_client_register(state, msg_tx);
-		}
-		return -11;
-
-	case OAP_MSGT_REGISTER_REQUEST:
-	case OAP_MSGT_CHALLENGE_RESULT:
-		LOGP(DLOAP, LOGL_ERROR,
-		     "Received invalid OAP message type for OAP client side: %d\n",
-		     (int)oap_msg.message_type);
-		return -12;
-
-	default:
-		LOGP(DLOAP, LOGL_ERROR,
-		     "Unknown OAP message type: %d\n",
-		     (int)oap_msg.message_type);
-		return -13;
-	}
-
-	return 0;
-}
diff --git a/src/libcommon/socket.c b/src/libcommon/socket.c
deleted file mode 100644
index 2a64767..0000000
--- a/src/libcommon/socket.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/* OpenBSC sokcet code, taken from Abis input driver for ip.access */
-
-/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2010 by Holger Hans Peter Freyther
- * (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/>.
- *
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <time.h>
-#include <sys/fcntl.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <arpa/inet.h>
-
-#include <osmocom/core/select.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/core/msgb.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <osmocom/core/talloc.h>
-
-int make_sock(struct osmo_fd *bfd, int proto,
-	      uint32_t ip, uint16_t port, int priv_nr,
-	      int (*cb)(struct osmo_fd *fd, unsigned int what), void *data)
-{
-	struct sockaddr_in addr;
-	int ret, on = 1;
-	int type = SOCK_STREAM;
-
-	switch (proto) {
-	case IPPROTO_TCP:
-		type = SOCK_STREAM;
-		break;
-	case IPPROTO_UDP:
-		type = SOCK_DGRAM;
-		break;
-#ifdef IPPROTO_GRE
-	case IPPROTO_GRE:
-		type = SOCK_RAW;
-		break;
-#endif
-	default:
-		return -EINVAL;
-	}
-
-	bfd->fd = socket(AF_INET, type, proto);
-	bfd->cb = cb;
-	bfd->when = BSC_FD_READ;
-	bfd->data = data;
-	bfd->priv_nr = priv_nr;
-
-	if (bfd->fd < 0) {
-		LOGP(DLINP, LOGL_ERROR, "could not create socket.\n");
-		return -EIO;
-	}
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sin_family = AF_INET;
-	addr.sin_port = htons(port);
-	if (ip != INADDR_ANY)
-		addr.sin_addr.s_addr = htonl(ip);
-	else
-		addr.sin_addr.s_addr = INADDR_ANY;
-
-	setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-
-	ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
-	if (ret < 0) {
-		LOGP(DLINP, LOGL_ERROR, "could not bind socket %s\n",
-			strerror(errno));
-		close(bfd->fd);
-		return -EIO;
-	}
-
-	if (proto == IPPROTO_TCP) {
-		ret = listen(bfd->fd, 1);
-		if (ret < 0) {
-			perror("listen");
-			close(bfd->fd);
-			return ret;
-		}
-	}
-
-	ret = osmo_fd_register(bfd);
-	if (ret < 0) {
-		perror("register_listen_fd");
-		close(bfd->fd);
-		return ret;
-	}
-	return 0;
-}
diff --git a/src/libcommon/talloc_ctx.c b/src/libcommon/talloc_ctx.c
deleted file mode 100644
index c8e9cd3..0000000
--- a/src/libcommon/talloc_ctx.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* OpenBSC allocation contexts initialization code */
-/* (C) 2011-2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- * 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/>.
- *
- */
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/msgb.h>
-
-extern void *tall_bsc_ctx;
-extern void *tall_fle_ctx;
-extern void *tall_locop_ctx;
-extern void *tall_authciphop_ctx;
-extern void *tall_gsms_ctx;
-extern void *tall_subscr_ctx;
-extern void *tall_sub_req_ctx;
-extern void *tall_call_ctx;
-extern void *tall_paging_ctx;
-extern void *tall_sigh_ctx;
-extern void *tall_tqe_ctx;
-extern void *tall_trans_ctx;
-extern void *tall_map_ctx;
-extern void *tall_upq_ctx;
-extern void *tall_ctr_ctx;
-
-void talloc_ctx_init(void *ctx_root)
-{
-	msgb_talloc_ctx_init(ctx_root, 0);
-	tall_fle_ctx = talloc_named_const(ctx_root, 0, "bs11_file_list_entry");
-	tall_locop_ctx = talloc_named_const(ctx_root, 0, "loc_updating_oper");
-	tall_authciphop_ctx = talloc_named_const(ctx_root, 0, "auth_ciph_oper");
-	tall_gsms_ctx = talloc_named_const(ctx_root, 0, "sms");
-	tall_subscr_ctx = talloc_named_const(ctx_root, 0, "subscriber");
-	tall_call_ctx = talloc_named_const(ctx_root, 0, "gsm_call");
-	tall_paging_ctx = talloc_named_const(ctx_root, 0, "paging_request");
-	tall_sigh_ctx = talloc_named_const(ctx_root, 0, "signal_handler");
-	tall_tqe_ctx = talloc_named_const(ctx_root, 0, "subch_txq_entry");
-	tall_trans_ctx = talloc_named_const(ctx_root, 0, "transaction");
-	tall_map_ctx = talloc_named_const(ctx_root, 0, "trau_map_entry");
-	tall_upq_ctx = talloc_named_const(ctx_root, 0, "trau_upq_entry");
-	tall_ctr_ctx = talloc_named_const(ctx_root, 0, "counter");
-}
diff --git a/src/libfilter/Makefile.am b/src/libfilter/Makefile.am
deleted file mode 100644
index 6d3db0b..0000000
--- a/src/libfilter/Makefile.am
+++ /dev/null
@@ -1,26 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	-I$(top_builddir) \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOVTY_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(LIBOSMOSCCP_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(NULL)
-
-noinst_LIBRARIES = \
-	libfilter.a \
-	$(NULL)
-
-libfilter_a_SOURCES = \
-	bsc_msg_filter.c \
-	bsc_msg_acc.c \
-	bsc_msg_vty.c \
-	$(NULL)
-
diff --git a/src/libfilter/bsc_msg_acc.c b/src/libfilter/bsc_msg_acc.c
deleted file mode 100644
index bfc5bdd..0000000
--- a/src/libfilter/bsc_msg_acc.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * (C) 2010-2015 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2011 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/>.
- *
- */
-
-#include <openbsc/bsc_msg_filter.h>
-#include <openbsc/bsc_nat.h>
-
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/core/stats.h>
-
-#include <string.h>
-
-static const struct rate_ctr_desc acc_list_ctr_description[] = {
-	[ACC_LIST_LOCAL_FILTER]	= { "access-list.local-filter", "Rejected by rule for local"},
-	[ACC_LIST_GLOBAL_FILTER]= { "access-list.global-filter", "Rejected by rule for global"},
-};
-
-static const struct rate_ctr_group_desc bsc_cfg_acc_list_desc = {
-	.group_name_prefix = "nat.filter",
-	.group_description = "NAT Access-List Statistics",
-	.num_ctr = ARRAY_SIZE(acc_list_ctr_description),
-	.ctr_desc = acc_list_ctr_description,
-	.class_id = OSMO_STATS_CLASS_GLOBAL,
-};
-
-
-int bsc_msg_acc_lst_check_allow(struct bsc_msg_acc_lst *lst, const char *mi_string)
-{
-	struct bsc_msg_acc_lst_entry *entry;
-
-	llist_for_each_entry(entry, &lst->fltr_list, list) {
-		if (!entry->imsi_allow)
-			continue;
-		if (regexec(&entry->imsi_allow_re, mi_string, 0, NULL, 0) == 0)
-			return 0;
-	}
-
-	return 1;
-}
-
-struct bsc_msg_acc_lst *bsc_msg_acc_lst_find(struct llist_head *head, const char *name)
-{
-	struct bsc_msg_acc_lst *lst;
-
-	if (!name)
-		return NULL;
-
-	llist_for_each_entry(lst, head, list)
-		if (strcmp(lst->name, name) == 0)
-			return lst;
-
-	return NULL;
-}
-
-struct bsc_msg_acc_lst *bsc_msg_acc_lst_get(void *ctx, struct llist_head *head, const char *name)
-{
-	struct bsc_msg_acc_lst *lst;
-
-	lst = bsc_msg_acc_lst_find(head, name);
-	if (lst)
-		return lst;
-
-	lst = talloc_zero(ctx, struct bsc_msg_acc_lst);
-	if (!lst) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to allocate access list");
-		return NULL;
-	}
-
-	/* TODO: get the index right */
-	lst->stats = rate_ctr_group_alloc(lst, &bsc_cfg_acc_list_desc, 0);
-	if (!lst->stats) {
-		talloc_free(lst);
-		return NULL;
-	}
-
-	INIT_LLIST_HEAD(&lst->fltr_list);
-	lst->name = talloc_strdup(lst, name);
-	llist_add_tail(&lst->list, head);
-	return lst;
-}
-
-void bsc_msg_acc_lst_delete(struct bsc_msg_acc_lst *lst)
-{
-	llist_del(&lst->list);
-	rate_ctr_group_free(lst->stats);
-	talloc_free(lst);
-}
-
-struct bsc_msg_acc_lst_entry *bsc_msg_acc_lst_entry_create(struct bsc_msg_acc_lst *lst)
-{
-	struct bsc_msg_acc_lst_entry *entry;
-
-	entry = talloc_zero(lst, struct bsc_msg_acc_lst_entry);
-	if (!entry)
-		return NULL;
-
-	entry->cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
-	entry->lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
-	llist_add_tail(&entry->list, &lst->fltr_list);
-	return entry;
-}
-
diff --git a/src/libfilter/bsc_msg_filter.c b/src/libfilter/bsc_msg_filter.c
deleted file mode 100644
index 115d376..0000000
--- a/src/libfilter/bsc_msg_filter.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * Access filtering
- */
-/*
- * (C) 2010-2015 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/>.
- *
- */
-
-#include <openbsc/bsc_msg_filter.h>
-
-#include <openbsc/bsc_nat.h>
-#include <openbsc/bsc_msc.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/debug.h>
-#include <openbsc/ipaccess.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/gsm/gsm0808.h>
-
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-#include <osmocom/gsm/protocol/gsm_04_11.h>
-
-int bsc_filter_barr_find(struct rb_root *root, const char *imsi, int *cm, int *lu)
-{
-	struct bsc_filter_barr_entry *n;
-	n = rb_entry(root->rb_node, struct bsc_filter_barr_entry, node);
-
-	while (n) {
-		int rc = strcmp(imsi, n->imsi);
-		if (rc == 0) {
-			*cm = n->cm_reject_cause;
-			*lu = n->lu_reject_cause;
-			return 1;
-		}
-
-		n = rb_entry(
-			(rc < 0) ? n->node.rb_left : n->node.rb_right,
-			struct bsc_filter_barr_entry, node);
-	};
-
-	return 0;
-}
-
-static int insert_barr_node(struct bsc_filter_barr_entry *entry, struct rb_root *root)
-{
-	struct rb_node **new = &root->rb_node, *parent = NULL;
-
-	while (*new) {
-		int rc;
-		struct bsc_filter_barr_entry *this;
-		this = rb_entry(*new, struct bsc_filter_barr_entry, node);
-		parent = *new;
-
-		rc = strcmp(entry->imsi, this->imsi);
-		if (rc < 0)
-			new = &((*new)->rb_left);
-		else if (rc > 0)
-			new = &((*new)->rb_right);
-		else {
-			LOGP(DFILTER, LOGL_ERROR,
-				"Duplicate entry for IMSI(%s)\n", entry->imsi);
-			talloc_free(entry);
-			return -1;
-		}
-	}
-
-	rb_link_node(&entry->node, parent, new);
-	rb_insert_color(&entry->node, root);
-	return 0;
-}
-
-int bsc_filter_barr_adapt(void *ctx, struct rb_root *root,
-			const struct osmo_config_list *list)
-{
-	struct osmo_config_entry *cfg_entry;
-	int err = 0;
-
-	/* free the old data */
-	while (!RB_EMPTY_ROOT(root)) {
-		struct rb_node *node = rb_first(root);
-		rb_erase(node, root);
-		talloc_free(node);
-	}
-
-	if (!list)
-		return 0;
-
-	/* now adapt the new list */
-	llist_for_each_entry(cfg_entry, &list->entry, list) {
-		struct bsc_filter_barr_entry *entry;
-		entry = talloc_zero(ctx, struct bsc_filter_barr_entry);
-		if (!entry) {
-			LOGP(DFILTER, LOGL_ERROR,
-				"Allocation of the barr entry failed.\n");
-			continue;
-		}
-
-		entry->imsi = talloc_strdup(entry, cfg_entry->mcc);
-		entry->cm_reject_cause = atoi(cfg_entry->mnc);
-		entry->lu_reject_cause = atoi(cfg_entry->option);
-		err |= insert_barr_node(entry, root);
-	}
-
-	return err;
-}
-
-
-static int lst_check_deny(struct bsc_msg_acc_lst *lst, const char *mi_string,
-			int *cm_cause, int *lu_cause)
-{
-	struct bsc_msg_acc_lst_entry *entry;
-
-	llist_for_each_entry(entry, &lst->fltr_list, list) {
-		if (!entry->imsi_deny)
-			continue;
-		if (regexec(&entry->imsi_deny_re, mi_string, 0, NULL, 0) == 0) {
-			*cm_cause = entry->cm_reject_cause;
-			*lu_cause = entry->lu_reject_cause;
-			return 0;
-		}
-	}
-
-	return 1;
-}
-
-/* apply white/black list */
-static int auth_imsi(struct bsc_filter_request *req,
-		const char *imsi,
-		struct bsc_filter_reject_cause *cause)
-{
-	/*
-	 * Now apply blacklist/whitelist of the BSC and the NAT.
-	 * 1.) Check the global IMSI barr list
-	 * 2.) Allow directly if the IMSI is allowed at the BSC
-	 * 3.) Reject if the IMSI is not allowed at the BSC
-	 * 4.) Reject if the IMSI not allowed at the global level.
-	 * 5.) Allow directly if the IMSI is allowed at the global level
-	 */
-	int cm, lu;
-	struct bsc_msg_acc_lst *nat_lst = NULL;
-	struct bsc_msg_acc_lst *bsc_lst = NULL;
-
-	/* 1. global check for barred imsis */
-	if (req->black_list && bsc_filter_barr_find(req->black_list, imsi, &cm, &lu)) {
-		cause->cm_reject_cause = cm;
-		cause->lu_reject_cause = lu;
-		LOGP(DFILTER, LOGL_DEBUG,
-			"Blocking subscriber IMSI %s with CM: %d LU: %d\n",
-			imsi, cm, lu);
-		return -4;
-	}
-
-
-	bsc_lst = bsc_msg_acc_lst_find(req->access_lists, req->local_lst_name);
-	nat_lst = bsc_msg_acc_lst_find(req->access_lists, req->global_lst_name);
-
-
-	if (bsc_lst) {
-		/* 2. BSC allow */
-		if (bsc_msg_acc_lst_check_allow(bsc_lst, imsi) == 0)
-			return 1;
-
-		/* 3. BSC deny */
-		if (lst_check_deny(bsc_lst, imsi, &cm, &lu) == 0) {
-			LOGP(DFILTER, LOGL_ERROR,
-			     "Filtering %s by imsi_deny on config nr: %d.\n", imsi, req->bsc_nr);
-			rate_ctr_inc(&bsc_lst->stats->ctr[ACC_LIST_LOCAL_FILTER]);
-			cause->cm_reject_cause = cm;
-			cause->lu_reject_cause = lu;
-			return -2;
-		}
-
-	}
-
-	/* 4. NAT deny */
-	if (nat_lst) {
-		if (lst_check_deny(nat_lst, imsi, &cm, &lu) == 0) {
-			LOGP(DFILTER, LOGL_ERROR,
-			     "Filtering %s global imsi_deny on bsc nr: %d.\n", imsi, req->bsc_nr);
-			rate_ctr_inc(&nat_lst->stats->ctr[ACC_LIST_GLOBAL_FILTER]);
-			cause->cm_reject_cause = cm;
-			cause->lu_reject_cause = lu;
-			return -3;
-		}
-	}
-
-	return 1;
-}
-
-static int _cr_check_loc_upd(void *ctx,
-			     uint8_t *data, unsigned int length,
-			     char **imsi)
-{
-	uint8_t mi_type;
-	struct gsm48_loc_upd_req *lu;
-	char mi_string[GSM48_MI_SIZE];
-
-	if (length < sizeof(*lu)) {
-		LOGP(DFILTER, LOGL_ERROR,
-		     "LU does not fit. Length is %d \n", length);
-		return -1;
-	}
-
-	lu = (struct gsm48_loc_upd_req *) data;
-	mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
-
-	/*
-	 * We can only deal with the IMSI. This will fail for a phone that
-	 * will send the TMSI of a previous network to us.
-	 */
-	if (mi_type != GSM_MI_TYPE_IMSI)
-		return 0;
-
-	gsm48_mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
-	*imsi = talloc_strdup(ctx, mi_string);
-	return 1;
-}
-
-static int _cr_check_cm_serv_req(void *ctx,
-				 uint8_t *data, unsigned int length,
-				 int *con_type, char **imsi)
-{
-	static const uint32_t classmark_offset =
-				offsetof(struct gsm48_service_request, classmark);
-
-	char mi_string[GSM48_MI_SIZE];
-	uint8_t mi_type;
-	int rc;
-	struct gsm48_service_request *req;
-
-	/* unfortunately in Phase1 the classmark2 length is variable */
-
-	if (length < sizeof(*req)) {
-		LOGP(DFILTER, LOGL_ERROR,
-		     "CM Serv Req does not fit. Length is %d\n", length);
-		return -1;
-	}
-
-	req = (struct gsm48_service_request *) data;
-	if (req->cm_service_type == 0x8)
-		*con_type = FLT_CON_TYPE_SSA;
-	rc = gsm48_extract_mi((uint8_t *) &req->classmark,
-			      length - classmark_offset, mi_string, &mi_type);
-	if (rc < 0) {
-		LOGP(DFILTER, LOGL_ERROR, "Failed to parse the classmark2/mi. error: %d\n", rc);
-		return -1;
-	}
-
-	/* we have to let the TMSI or such pass */
-	if (mi_type != GSM_MI_TYPE_IMSI)
-		return 0;
-
-	*imsi = talloc_strdup(ctx, mi_string);
-	return 1;
-}
-
-static int _cr_check_pag_resp(void *ctx,
-			      uint8_t *data, unsigned int length, char **imsi)
-{
-	struct gsm48_pag_resp *resp;
-	char mi_string[GSM48_MI_SIZE];
-	uint8_t mi_type;
-
-	if (length < sizeof(*resp)) {
-		LOGP(DFILTER, LOGL_ERROR, "PAG RESP does not fit. Length was %d.\n", length);
-		return -1;
-	}
-
-	resp = (struct gsm48_pag_resp *) data;
-	if (gsm48_paging_extract_mi(resp, length, mi_string, &mi_type) < 0) {
-		LOGP(DFILTER, LOGL_ERROR, "Failed to extract the MI.\n");
-		return -1;
-	}
-
-	/* we need to let it pass for now */
-	if (mi_type != GSM_MI_TYPE_IMSI)
-		return 0;
-
-	*imsi = talloc_strdup(ctx, mi_string);
-	return 1;
-}
-
-static int _dt_check_id_resp(struct bsc_filter_request *req,
-			     uint8_t *data, unsigned int length,
-			     struct bsc_filter_state *state,
-			     struct bsc_filter_reject_cause *cause)
-{
-	char mi_string[GSM48_MI_SIZE];
-	uint8_t mi_type;
-
-	if (length < 2) {
-		LOGP(DFILTER, LOGL_ERROR, "mi does not fit.\n");
-		return -1;
-	}
-
-	if (data[0] < length - 1) {
-		LOGP(DFILTER, LOGL_ERROR, "mi length too big.\n");
-		return -2;
-	}
-
-	mi_type = data[1] & GSM_MI_TYPE_MASK;
-	gsm48_mi_to_string(mi_string, sizeof(mi_string), &data[1], data[0]);
-
-	if (mi_type != GSM_MI_TYPE_IMSI)
-		return 0;
-
-	state->imsi_checked = 1;
-	state->imsi = talloc_strdup(req->ctx, mi_string);
-	return auth_imsi(req, mi_string, cause);
-}
-
-
-/* Filter out CR data... */
-int bsc_msg_filter_initial(struct gsm48_hdr *hdr48, size_t hdr48_len,
-			struct bsc_filter_request *req,
-			int *con_type,
-			char **imsi, struct bsc_filter_reject_cause *cause)
-{
-	int ret = 0;
-	uint8_t msg_type, proto;
-
-	*con_type = FLT_CON_TYPE_NONE;
-	cause->cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
-	cause->lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
-	*imsi = NULL;
-
-	proto = gsm48_hdr_pdisc(hdr48);
-	msg_type = gsm48_hdr_msg_type(hdr48);
-	if (proto == GSM48_PDISC_MM &&
-	    msg_type == GSM48_MT_MM_LOC_UPD_REQUEST) {
-		*con_type = FLT_CON_TYPE_LU;
-		ret = _cr_check_loc_upd(req->ctx, &hdr48->data[0],
-					hdr48_len - sizeof(*hdr48), imsi);
-	} else if (proto == GSM48_PDISC_MM &&
-		   msg_type == GSM48_MT_MM_CM_SERV_REQ) {
-		*con_type = FLT_CON_TYPE_CM_SERV_REQ;
-		ret = _cr_check_cm_serv_req(req->ctx, &hdr48->data[0],
-					     hdr48_len - sizeof(*hdr48),
-					     con_type, imsi);
-	} else if (proto == GSM48_PDISC_RR &&
-		   msg_type == GSM48_MT_RR_PAG_RESP) {
-		*con_type = FLT_CON_TYPE_PAG_RESP;
-		ret = _cr_check_pag_resp(req->ctx, &hdr48->data[0],
-					hdr48_len - sizeof(*hdr48), imsi);
-	} else {
-		/* We only want to filter the above, let other things pass */
-		*con_type = FLT_CON_TYPE_OTHER;
-		return 0;
-	}
-
-	/* check if we are done */
-	if (ret != 1)
-		return ret;
-
-	/* the memory allocation failed */
-	if (!*imsi)
-		return -1;
-
-	/* now check the imsi */
-	return auth_imsi(req, *imsi, cause);
-}
-
-int bsc_msg_filter_data(struct gsm48_hdr *hdr48, size_t len,
-		struct bsc_filter_request *req,
-		struct bsc_filter_state *state,
-		struct bsc_filter_reject_cause *cause)
-{
-	uint8_t msg_type, proto;
-
-	cause->cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
-	cause->lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
-
-	if (state->imsi_checked)
-		return 0;
-
-	proto = gsm48_hdr_pdisc(hdr48);
-	msg_type = gsm48_hdr_msg_type(hdr48);
-	if (proto != GSM48_PDISC_MM || msg_type != GSM48_MT_MM_ID_RESP)
-		return 0;
-
-	return _dt_check_id_resp(req, &hdr48->data[0],
-					len - sizeof(*hdr48), state, cause);
-}
diff --git a/src/libfilter/bsc_msg_vty.c b/src/libfilter/bsc_msg_vty.c
deleted file mode 100644
index c342fdc..0000000
--- a/src/libfilter/bsc_msg_vty.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/* (C) 2010-2015 by Holger Hans Peter Freyther
- * (C) 2010-2013 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/>.
- *
- */
-
-#include <openbsc/bsc_msg_filter.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/vty.h>
-
-#include <osmocom/vty/misc.h>
-
-static struct llist_head *_acc_lst;
-static void *_ctx;
-
-DEFUN(cfg_lst_no,
-      cfg_lst_no_cmd,
-      "no access-list NAME",
-      NO_STR "Remove an access-list by name\n"
-      "The access-list to remove\n")
-{
-	struct bsc_msg_acc_lst *acc;
-	acc = bsc_msg_acc_lst_find(_acc_lst, argv[0]);
-	if (!acc)
-		return CMD_WARNING;
-
-	bsc_msg_acc_lst_delete(acc);
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_acc_lst,
-      show_acc_lst_cmd,
-      "show access-list NAME",
-      SHOW_STR "IMSI access list\n" "Name of the access list\n")
-{
-	struct bsc_msg_acc_lst *acc;
-	acc = bsc_msg_acc_lst_find(_acc_lst, argv[0]);
-	if (!acc)
-		return CMD_WARNING;
-
-	vty_out(vty, "access-list %s%s", acc->name, VTY_NEWLINE);
-	vty_out_rate_ctr_group(vty, " ", acc->stats);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_lst_imsi_allow,
-      cfg_lst_imsi_allow_cmd,
-      "access-list NAME imsi-allow [REGEXP]",
-      "Access list commands\n"
-      "Name of the access list\n"
-      "Add allowed IMSI to the list\n"
-      "Regexp for IMSIs\n")
-{
-	struct bsc_msg_acc_lst *acc;
-	struct bsc_msg_acc_lst_entry *entry;
-
-	acc = bsc_msg_acc_lst_get(_ctx, _acc_lst, argv[0]);
-	if (!acc)
-		return CMD_WARNING;
-
-	entry = bsc_msg_acc_lst_entry_create(acc);
-	if (!entry)
-		return CMD_WARNING;
-
-	if (gsm_parse_reg(acc, &entry->imsi_allow_re, &entry->imsi_allow, argc - 1, &argv[1]) != 0)
-		return CMD_WARNING;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_lst_imsi_deny,
-      cfg_lst_imsi_deny_cmd,
-      "access-list NAME imsi-deny [REGEXP] (<0-256>) (<0-256>)",
-      "Access list commands\n"
-      "Name of the access list\n"
-      "Add denied IMSI to the list\n"
-      "Regexp for IMSIs\n"
-      "CM Service Reject reason\n"
-      "LU Reject reason\n")
-{
-	struct bsc_msg_acc_lst *acc;
-	struct bsc_msg_acc_lst_entry *entry;
-
-	acc = bsc_msg_acc_lst_get(_ctx, _acc_lst, argv[0]);
-	if (!acc)
-		return CMD_WARNING;
-
-	entry = bsc_msg_acc_lst_entry_create(acc);
-	if (!entry)
-		return CMD_WARNING;
-
-	if (gsm_parse_reg(acc, &entry->imsi_deny_re, &entry->imsi_deny, argc - 1, &argv[1]) != 0)
-		return CMD_WARNING;
-	if (argc >= 3)
-		entry->cm_reject_cause = atoi(argv[2]);
-	if (argc >= 4)
-		entry->lu_reject_cause = atoi(argv[3]);
-	return CMD_SUCCESS;
-}
-
-void bsc_msg_acc_lst_write(struct vty *vty, struct bsc_msg_acc_lst *lst)
-{
-	struct bsc_msg_acc_lst_entry *entry;
-
-	llist_for_each_entry(entry, &lst->fltr_list, list) {
-		if (entry->imsi_allow)
-			vty_out(vty, " access-list %s imsi-allow %s%s",
-				lst->name, entry->imsi_allow, VTY_NEWLINE);
-		if (entry->imsi_deny)
-			vty_out(vty, " access-list %s imsi-deny %s %d %d%s",
-				lst->name, entry->imsi_deny,
-				entry->cm_reject_cause, entry->lu_reject_cause,
-				VTY_NEWLINE);
-	}
-}
-
-void bsc_msg_lst_vty_init(void *ctx, struct llist_head *lst, int node)
-{
-	_ctx = ctx;
-	_acc_lst = lst;
-	install_element_ve(&show_acc_lst_cmd);
-
-	/* access-list */
-	install_element(node, &cfg_lst_imsi_allow_cmd);
-	install_element(node, &cfg_lst_imsi_deny_cmd);
-	install_element(node, &cfg_lst_no_cmd);
-}
diff --git a/src/libmgcp/Makefile.am b/src/libmgcp/Makefile.am
deleted file mode 100644
index 5d7844d..0000000
--- a/src/libmgcp/Makefile.am
+++ /dev/null
@@ -1,46 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	-I$(top_builddir) \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOVTY_CFLAGS) \
-	$(LIBOSMONETIF_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(LIBBCG729_CFLAGS) \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMONETIF_LIBS) \
-	$(COVERAGE_LDFLAGS) \
-	$(LIBBCG729_LIBS) \
-	$(NULL)
-
-noinst_LIBRARIES = \
-	libmgcp.a \
-	$(NULL)
-
-noinst_HEADERS = \
-	g711common.h \
-	$(NULL)
-
-libmgcp_a_SOURCES = \
-	mgcp_common.c \
-	mgcp_protocol.c \
-	mgcp_network.c \
-	mgcp_vty.c \
-	mgcp_osmux.c \
-	mgcp_sdp.c \
-	mgcpgw_client.c \
-	mgcpgw_client_vty.c \
-	$(NULL)
-if BUILD_MGCP_TRANSCODING
-libmgcp_a_SOURCES += \
-	mgcp_transcode.c \
-	$(NULL)
-endif
diff --git a/src/libmgcp/mgcp_common.c b/src/libmgcp/mgcp_common.c
deleted file mode 100644
index 43c8667..0000000
--- a/src/libmgcp/mgcp_common.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Media Gateway Control Protocol Media Gateway: RFC 3435 */
-/* Implementations useful both for the MGCP GW as well as MGCP GW clients */
-
-/*
- * (C) 2016 by sysmocom s.m.f.c. GmbH <info@sysmocom.de>
- * 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/>.
- *
- */
-
-#include <errno.h>
-
-#include <osmocom/core/utils.h>
-#include <openbsc/mgcp.h>
-
-const struct value_string mgcp_connection_mode_strs[] = {
-	{ MGCP_CONN_NONE, "none" },
-	{ MGCP_CONN_RECV_SEND, "sendrecv" },
-	{ MGCP_CONN_SEND_ONLY, "sendonly" },
-	{ MGCP_CONN_RECV_ONLY, "recvonly" },
-	{ MGCP_CONN_LOOPBACK, "loopback" },
-	{ 0, NULL }
-};
-
-/* Ensure that the msg->l2h is NUL terminated. */
-int mgcp_msg_terminate_nul(struct msgb *msg)
-{
-	unsigned char *tail = msg->l2h + msgb_l2len(msg); /* char after l2 data */
-	if (tail[-1] == '\0')
-		/* nothing to do */;
-	else if (msgb_tailroom(msg) > 0)
-		tail[0] = '\0';
-	else if (tail[-1] == '\r' || tail[-1] == '\n')
-		tail[-1] = '\0';
-	else {
-		LOGP(DMGCP, LOGL_ERROR, "Cannot NUL terminate MGCP message: "
-		     "Length: %d, Buffer size: %d\n",
-		     msgb_l2len(msg), msg->data_len);
-		return -ENOTSUP;
-	}
-	return 0;
-}
diff --git a/src/libmgcp/mgcp_network.c b/src/libmgcp/mgcp_network.c
deleted file mode 100644
index 399dc8f..0000000
--- a/src/libmgcp/mgcp_network.c
+++ /dev/null
@@ -1,1166 +0,0 @@
-/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
-/* The protocol implementation */
-
-/*
- * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-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/>.
- *
- */
-
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <time.h>
-#include <limits.h>
-
-#include <sys/socket.h>
-#include <arpa/inet.h>
-
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/select.h>
-
-#include <osmocom/netif/rtp.h>
-
-#include <openbsc/mgcp.h>
-#include <openbsc/mgcp_internal.h>
-
-#include <openbsc/osmux.h>
-
-#warning "Make use of the rtp proxy code"
-
-
-#define RTP_SEQ_MOD		(1 << 16)
-#define RTP_MAX_DROPOUT		3000
-#define RTP_MAX_MISORDER	100
-#define RTP_BUF_SIZE		4096
-
-enum {
-	MGCP_PROTO_RTP,
-	MGCP_PROTO_RTCP,
-};
-
-/**
- * This does not need to be a precision timestamp and
- * is allowed to wrap quite fast. The returned value is
- * 1/unit seconds.
- */
-static uint32_t get_current_ts(unsigned unit)
-{
-	struct timespec tp;
-	uint64_t ret;
-
-	if (!unit)
-		return 0;
-
-	memset(&tp, 0, sizeof(tp));
-	if (clock_gettime(CLOCK_MONOTONIC, &tp) != 0)
-		LOGP(DMGCP, LOGL_NOTICE,
-			"Getting the clock failed.\n");
-
-	/* convert it to 1/unit seconds */
-	ret = tp.tv_sec;
-	ret *= unit;
-	ret += (int64_t)tp.tv_nsec * unit / 1000 / 1000 / 1000;
-
-	return ret;
-}
-
-int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len)
-{
-	struct sockaddr_in out;
-	out.sin_family = AF_INET;
-	out.sin_port = port;
-	memcpy(&out.sin_addr, addr, sizeof(*addr));
-
-	return sendto(fd, buf, len, 0, (struct sockaddr *)&out, sizeof(out));
-}
-
-int mgcp_send_dummy(struct mgcp_endpoint *endp)
-{
-	static char buf[] = { MGCP_DUMMY_LOAD };
-	int rc;
-	int was_rtcp = 0;
-
-	rc = mgcp_udp_send(endp->net_end.rtp.fd, &endp->net_end.addr,
-			   endp->net_end.rtp_port, buf, 1);
-
-	if (rc == -1)
-		goto failed;
-
-	if (endp->tcfg->omit_rtcp)
-		return rc;
-
-	was_rtcp = 1;
-	rc = mgcp_udp_send(endp->net_end.rtcp.fd, &endp->net_end.addr,
-			   endp->net_end.rtcp_port, buf, 1);
-
-	if (rc >= 0)
-		return rc;
-
-failed:
-	LOGP(DMGCP, LOGL_ERROR,
-		"Failed to send dummy %s packet: %s on: 0x%x to %s:%d\n",
-		was_rtcp ? "RTCP" : "RTP",
-		strerror(errno), ENDPOINT_NUMBER(endp), inet_ntoa(endp->net_end.addr),
-		was_rtcp ? endp->net_end.rtcp_port : endp->net_end.rtp_port);
-
-	return -1;
-}
-
-static int32_t compute_timestamp_aligment_error(struct mgcp_rtp_stream_state *sstate,
-						int ptime, uint32_t timestamp)
-{
-	int32_t timestamp_delta;
-
-	if (ptime == 0)
-		return 0;
-
-	/* Align according to: T - Tlast = k * Tptime */
-	timestamp_delta = timestamp - sstate->last_timestamp;
-
-	return timestamp_delta % ptime;
-}
-
-static int check_rtp_timestamp(struct mgcp_endpoint *endp,
-			       struct mgcp_rtp_state *state,
-			       struct mgcp_rtp_stream_state *sstate,
-			       struct mgcp_rtp_end *rtp_end,
-			       struct sockaddr_in *addr,
-			       uint16_t seq, uint32_t timestamp,
-			       const char *text, int32_t *tsdelta_out)
-{
-	int32_t tsdelta;
-	int32_t timestamp_error;
-
-	/* Not fully intialized, skip */
-	if (sstate->last_tsdelta == 0 && timestamp == sstate->last_timestamp)
-		return 0;
-
-	if (seq == sstate->last_seq) {
-		if (timestamp != sstate->last_timestamp) {
-			sstate->err_ts_counter += 1;
-			LOGP(DMGCP, LOGL_ERROR,
-			     "The %s timestamp delta is != 0 but the sequence "
-			     "number %d is the same, "
-			     "TS offset: %d, SeqNo offset: %d "
-			     "on 0x%x SSRC: %u timestamp: %u "
-			     "from %s:%d in %d\n",
-			     text, seq,
-			     state->timestamp_offset, state->seq_offset,
-			     ENDPOINT_NUMBER(endp), sstate->ssrc, timestamp,
-			     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
-			     endp->conn_mode);
-		}
-		return 0;
-	}
-
-	tsdelta =
-		(int32_t)(timestamp - sstate->last_timestamp) /
-		(int16_t)(seq - sstate->last_seq);
-
-	if (tsdelta == 0) {
-		/* Don't update *tsdelta_out */
-		LOGP(DMGCP, LOGL_NOTICE,
-		     "The %s timestamp delta is %d "
-		     "on 0x%x SSRC: %u timestamp: %u "
-		     "from %s:%d in %d\n",
-		     text, tsdelta,
-		     ENDPOINT_NUMBER(endp), sstate->ssrc, timestamp,
-		     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
-		     endp->conn_mode);
-
-		return 0;
-	}
-
-	if (sstate->last_tsdelta != tsdelta) {
-		if (sstate->last_tsdelta) {
-			LOGP(DMGCP, LOGL_INFO,
-			     "The %s timestamp delta changes from %d to %d "
-			     "on 0x%x SSRC: %u timestamp: %u from %s:%d in %d\n",
-			     text, sstate->last_tsdelta, tsdelta,
-			     ENDPOINT_NUMBER(endp), sstate->ssrc, timestamp,
-			     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
-			     endp->conn_mode);
-		}
-	}
-
-	if (tsdelta_out)
-		*tsdelta_out = tsdelta;
-
-	timestamp_error =
-		compute_timestamp_aligment_error(sstate, state->packet_duration,
-						 timestamp);
-
-	if (timestamp_error) {
-		sstate->err_ts_counter += 1;
-		LOGP(DMGCP, LOGL_NOTICE,
-		     "The %s timestamp has an alignment error of %d "
-		     "on 0x%x SSRC: %u "
-		     "SeqNo delta: %d, TS delta: %d, dTS/dSeq: %d "
-		     "from %s:%d in mode %d. ptime: %d\n",
-		     text, timestamp_error,
-		     ENDPOINT_NUMBER(endp), sstate->ssrc,
-		     (int16_t)(seq - sstate->last_seq),
-		     (int32_t)(timestamp - sstate->last_timestamp),
-		     tsdelta,
-		     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
-		     endp->conn_mode, state->packet_duration);
-	}
-	return 1;
-}
-
-/* Set the timestamp offset according to the packet duration. */
-static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
-				       struct mgcp_rtp_state *state,
-				       struct mgcp_rtp_end *rtp_end,
-				       struct sockaddr_in *addr,
-				       int16_t delta_seq, uint32_t in_timestamp)
-{
-	int32_t tsdelta = state->packet_duration;
-	int timestamp_offset;
-	uint32_t out_timestamp;
-
-	if (tsdelta == 0) {
-		tsdelta = state->out_stream.last_tsdelta;
-		if (tsdelta != 0) {
-			LOGP(DMGCP, LOGL_NOTICE,
-			     "A fixed packet duration is not available on 0x%x, "
-			     "using last output timestamp delta instead: %d "
-			     "from %s:%d in %d\n",
-			     ENDPOINT_NUMBER(endp), tsdelta,
-			     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
-			     endp->conn_mode);
-		} else {
-			tsdelta = rtp_end->codec.rate * 20 / 1000;
-			LOGP(DMGCP, LOGL_NOTICE,
-			     "Fixed packet duration and last timestamp delta "
-			     "are not available on 0x%x, "
-			     "using fixed 20ms instead: %d "
-			     "from %s:%d in %d\n",
-			     ENDPOINT_NUMBER(endp), tsdelta,
-			     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
-			     endp->conn_mode);
-		}
-	}
-
-	out_timestamp = state->out_stream.last_timestamp + delta_seq * tsdelta;
-	timestamp_offset = out_timestamp - in_timestamp;
-
-	if (state->timestamp_offset != timestamp_offset) {
-		state->timestamp_offset = timestamp_offset;
-
-		LOGP(DMGCP, LOGL_NOTICE,
-		     "Timestamp offset change on 0x%x SSRC: %u "
-		     "SeqNo delta: %d, TS offset: %d, "
-		     "from %s:%d in %d\n",
-		     ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
-		     delta_seq, state->timestamp_offset,
-		     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
-		     endp->conn_mode);
-	}
-
-	return timestamp_offset;
-}
-
-/* Set the timestamp offset according to the packet duration. */
-static int align_rtp_timestamp_offset(struct mgcp_endpoint *endp,
-				      struct mgcp_rtp_state *state,
-				      struct mgcp_rtp_end *rtp_end,
-				      struct sockaddr_in *addr,
-				      uint32_t timestamp)
-{
-	int timestamp_error = 0;
-	int ptime = state->packet_duration;
-
-	/* Align according to: T + Toffs - Tlast = k * Tptime */
-
-	timestamp_error = compute_timestamp_aligment_error(
-		&state->out_stream, ptime,
-		timestamp + state->timestamp_offset);
-
-	if (timestamp_error) {
-		state->timestamp_offset += ptime - timestamp_error;
-
-		LOGP(DMGCP, LOGL_NOTICE,
-		     "Corrected timestamp alignment error of %d on 0x%x SSRC: %u "
-		     "new TS offset: %d, "
-		     "from %s:%d in %d\n",
-		     timestamp_error,
-		     ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
-		     state->timestamp_offset, inet_ntoa(addr->sin_addr),
-		     ntohs(addr->sin_port), endp->conn_mode);
-	}
-
-	OSMO_ASSERT(compute_timestamp_aligment_error(&state->out_stream, ptime,
-						     timestamp + state->timestamp_offset) == 0);
-
-	return timestamp_error;
-}
-
-int mgcp_rtp_processing_default(struct mgcp_endpoint *endp, struct mgcp_rtp_end *dst_end,
-				char *data, int *len, int buf_size)
-{
-	return 0;
-}
-
-int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
-				      struct mgcp_rtp_end *dst_end,
-				      struct mgcp_rtp_end *src_end)
-{
-	return 0;
-}
-
-void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
-					  int *payload_type,
-					  const char**audio_name,
-					  const char**fmtp_extra)
-{
-	/* Use the BTS side parameters when passing the SDP data (for
-	 * downlink) to the net peer.
-	 */
-	*payload_type = endp->bts_end.codec.payload_type;
-	*audio_name = endp->bts_end.codec.audio_name;
-	*fmtp_extra = endp->bts_end.fmtp_extra;
-}
-
-
-void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
-			const uint16_t seq, const int32_t transit,
-			const uint32_t ssrc)
-{
-	int32_t d;
-
-	/* initialize or re-initialize */
-	if (!state->stats_initialized || state->stats_ssrc != ssrc) {
-		state->stats_initialized = 1;
-		state->stats_base_seq = seq;
-		state->stats_max_seq = seq - 1;
-		state->stats_ssrc = ssrc;
-		state->stats_jitter = 0;
-		state->stats_transit = transit;
-		state->stats_cycles = 0;
-	} else {
-		uint16_t udelta;
-
-		/*
-		 * The below takes the shape of the validation of
-		 * Appendix A. Check if there is something weird with
-		 * the sequence number, otherwise check for a wrap
-		 * around in the sequence number.
-		 * It can't wrap during the initialization so let's
-		 * skip it here. The Appendix A probably doesn't have
-		 * this issue because of the probation.
-		 */
-		udelta = seq - state->stats_max_seq;
-		if (udelta < RTP_MAX_DROPOUT) {
-			if (seq < state->stats_max_seq)
-				state->stats_cycles += RTP_SEQ_MOD;
-		} else if (udelta <= RTP_SEQ_MOD - RTP_MAX_MISORDER) {
-			LOGP(DMGCP, LOGL_NOTICE,
-				"RTP seqno made a very large jump on 0x%x delta: %u\n",
-				ENDPOINT_NUMBER(endp), udelta);
-		}
-	}
-
-	/*
-	 * Calculate the jitter between the two packages. The TS should be
-	 * taken closer to the read function. This was taken from the
-	 * Appendix A of RFC 3550. Timestamp and arrival_time have a 1/rate
-	 * resolution.
-	 */
-	d = transit - state->stats_transit;
-	state->stats_transit = transit;
-	if (d < 0)
-		d = -d;
-	state->stats_jitter += d - ((state->stats_jitter + 8) >> 4);
-	state->stats_max_seq = seq;
-}
-
-
-
-/**
- * The RFC 3550 Appendix A assumes there are multiple sources but
- * some of the supported endpoints (e.g. the nanoBTS) can only handle
- * one source and this code will patch RTP header to appear as if there
- * is only one source.
- * There is also no probation period for new sources. Every RTP header
- * we receive will be seen as a switch in streams.
- */
-void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
-			  struct mgcp_rtp_end *rtp_end, struct sockaddr_in *addr,
-			  char *data, int len)
-{
-	uint32_t arrival_time;
-	int32_t transit;
-	uint16_t seq;
-	uint32_t timestamp, ssrc;
-	struct rtp_hdr *rtp_hdr;
-	int payload = rtp_end->codec.payload_type;
-
-	if (len < sizeof(*rtp_hdr))
-		return;
-
-	rtp_hdr = (struct rtp_hdr *) data;
-	seq = ntohs(rtp_hdr->sequence);
-	timestamp = ntohl(rtp_hdr->timestamp);
-	arrival_time = get_current_ts(rtp_end->codec.rate);
-	ssrc = ntohl(rtp_hdr->ssrc);
-	transit = arrival_time - timestamp;
-
-	mgcp_rtp_annex_count(endp, state, seq, transit, ssrc);
-
-	if (!state->initialized) {
-		state->initialized = 1;
-		state->in_stream.last_seq = seq - 1;
-		state->in_stream.ssrc = state->orig_ssrc = ssrc;
-		state->in_stream.last_tsdelta = 0;
-		state->packet_duration = mgcp_rtp_packet_duration(endp, rtp_end);
-		state->out_stream = state->in_stream;
-		state->out_stream.last_timestamp = timestamp;
-		state->out_stream.ssrc = ssrc - 1; /* force output SSRC change */
-		LOGP(DMGCP, LOGL_INFO,
-			"Initializing stream on 0x%x SSRC: %u timestamp: %u "
-			"pkt-duration: %d, from %s:%d in %d\n",
-			ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
-			state->seq_offset, state->packet_duration,
-			inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
-			endp->conn_mode);
-		if (state->packet_duration == 0) {
-			state->packet_duration = rtp_end->codec.rate * 20 / 1000;
-			LOGP(DMGCP, LOGL_NOTICE,
-			     "Fixed packet duration is not available on 0x%x, "
-			     "using fixed 20ms instead: %d from %s:%d in %d\n",
-			     ENDPOINT_NUMBER(endp), state->packet_duration,
-			     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
-			     endp->conn_mode);
-		}
-	} else if (state->in_stream.ssrc != ssrc) {
-		LOGP(DMGCP, LOGL_NOTICE,
-			"The SSRC changed on 0x%x: %u -> %u  "
-			"from %s:%d in %d\n",
-			ENDPOINT_NUMBER(endp),
-			state->in_stream.ssrc, rtp_hdr->ssrc,
-			inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
-			endp->conn_mode);
-
-		state->in_stream.ssrc = ssrc;
-		if (rtp_end->force_constant_ssrc) {
-			int16_t delta_seq;
-
-			/* Always increment seqno by 1 */
-			state->seq_offset =
-				(state->out_stream.last_seq + 1) - seq;
-
-			/* Estimate number of packets that would have been sent */
-			delta_seq =
-				(arrival_time - state->in_stream.last_arrival_time
-				 + state->packet_duration/2) /
-				state->packet_duration;
-
-			adjust_rtp_timestamp_offset(endp, state, rtp_end, addr,
-						    delta_seq, timestamp);
-
-			state->patch_ssrc = 1;
-			ssrc = state->orig_ssrc;
-			if (rtp_end->force_constant_ssrc != -1)
-				rtp_end->force_constant_ssrc -= 1;
-
-			LOGP(DMGCP, LOGL_NOTICE,
-			     "SSRC patching enabled on 0x%x SSRC: %u "
-			     "SeqNo offset: %d, TS offset: %d "
-			     "from %s:%d in %d\n",
-			     ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
-			     state->seq_offset, state->timestamp_offset,
-			     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
-			     endp->conn_mode);
-		}
-
-		state->in_stream.last_tsdelta = 0;
-	} else {
-		/* Compute current per-packet timestamp delta */
-		check_rtp_timestamp(endp, state, &state->in_stream, rtp_end, addr,
-				    seq, timestamp, "input",
-				    &state->in_stream.last_tsdelta);
-
-		if (state->patch_ssrc)
-			ssrc = state->orig_ssrc;
-	}
-
-	/* Save before patching */
-	state->in_stream.last_timestamp = timestamp;
-	state->in_stream.last_seq = seq;
-	state->in_stream.last_arrival_time = arrival_time;
-
-	if (rtp_end->force_aligned_timing &&
-	    state->out_stream.ssrc == ssrc && state->packet_duration)
-		/* Align the timestamp offset */
-		align_rtp_timestamp_offset(endp, state, rtp_end, addr, timestamp);
-
-	/* Store the updated SSRC back to the packet */
-	if (state->patch_ssrc)
-		rtp_hdr->ssrc = htonl(ssrc);
-
-	/* Apply the offset and store it back to the packet.
-	 * This won't change anything if the offset is 0, so the conditional is
-	 * omitted. */
-	seq += state->seq_offset;
-	rtp_hdr->sequence = htons(seq);
-	timestamp += state->timestamp_offset;
-	rtp_hdr->timestamp = htonl(timestamp);
-
-	/* Check again, whether the timestamps are still valid */
-	if (state->out_stream.ssrc == ssrc)
-		check_rtp_timestamp(endp, state, &state->out_stream, rtp_end,
-				    addr, seq, timestamp, "output",
-				    &state->out_stream.last_tsdelta);
-
-	/* Save output values */
-	state->out_stream.last_seq = seq;
-	state->out_stream.last_timestamp = timestamp;
-	state->out_stream.ssrc = ssrc;
-
-	if (payload < 0)
-		return;
-
-#if 0
-	DEBUGP(DMGCP, "Payload hdr payload %u -> endp payload %u\n",
-	       rtp_hdr->payload_type, payload);
-	rtp_hdr->payload_type = payload;
-#endif
-}
-
-/*
- * The below code is for dispatching. We have a dedicated port for
- * the data coming from the net and one to discover the BTS.
- */
-static int forward_data(int fd, struct mgcp_rtp_tap *tap, const char *buf, int len)
-{
-	if (!tap->enabled)
-		return 0;
-
-	return sendto(fd, buf, len, 0,
-		      (struct sockaddr *)&tap->forward, sizeof(tap->forward));
-}
-
-static int mgcp_send_transcoder(struct mgcp_rtp_end *end,
-				struct mgcp_config *cfg, int is_rtp,
-				const char *buf, int len)
-{
-	int rc;
-	int port;
-	struct sockaddr_in addr;
-
-	port = is_rtp ? end->rtp_port : end->rtcp_port;
-
-	addr.sin_family = AF_INET;
-	addr.sin_addr = cfg->transcoder_in;
-	addr.sin_port = port;
-
-	rc = sendto(is_rtp ?
-		end->rtp.fd :
-		end->rtcp.fd, buf, len, 0,
-		(struct sockaddr *) &addr, sizeof(addr));
-
-	if (rc != len)
-		LOGP(DMGCP, LOGL_ERROR,
-			"Failed to send data to the transcoder: %s\n",
-			strerror(errno));
-
-	return rc;
-}
-
-int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp,
-	      struct sockaddr_in *addr, char *buf, int rc)
-{
-	struct mgcp_trunk_config *tcfg = endp->tcfg;
-	struct mgcp_rtp_end *rtp_end;
-	struct mgcp_rtp_state *rtp_state;
-	int tap_idx;
-
-	LOGP(DMGCP, LOGL_DEBUG,
-	     "endpoint %x dest %s tcfg->audio_loop %d endp->conn_mode %d (== loopback: %d)\n",
-	     ENDPOINT_NUMBER(endp),
-	     dest == MGCP_DEST_NET? "net" : "bts",
-	     tcfg->audio_loop,
-	     endp->conn_mode,
-	     endp->conn_mode == MGCP_CONN_LOOPBACK);
-
-	/* For loop toggle the destination and then dispatch. */
-	if (tcfg->audio_loop)
-		dest = !dest;
-
-	/* Loop based on the conn_mode, maybe undoing the above */
-	if (endp->conn_mode == MGCP_CONN_LOOPBACK)
-		dest = !dest;
-
-	if (dest == MGCP_DEST_NET) {
-		rtp_end = &endp->net_end;
-		rtp_state = &endp->bts_state;
-		tap_idx = MGCP_TAP_NET_OUT;
-	} else {
-		rtp_end = &endp->bts_end;
-		rtp_state = &endp->net_state;
-		tap_idx = MGCP_TAP_BTS_OUT;
-	}
-	LOGP(DMGCP, LOGL_DEBUG,
-	     "endpoint %x dest %s net_end %s %d %d bts_end %s %d %d rtp_end %s %d %d\n",
-	     ENDPOINT_NUMBER(endp),
-	     dest == MGCP_DEST_NET? "net" : "bts",
-
-	     inet_ntoa(endp->net_end.addr),
-	     ntohs(endp->net_end.rtp_port),
-	     ntohs(endp->net_end.rtcp_port),
-
-	     inet_ntoa(endp->bts_end.addr),
-	     ntohs(endp->bts_end.rtp_port),
-	     ntohs(endp->bts_end.rtcp_port),
-
-	     inet_ntoa(rtp_end->addr),
-	     ntohs(rtp_end->rtp_port),
-	     ntohs(rtp_end->rtcp_port)
-	    );
-
-	if (!rtp_end->output_enabled) {
-		rtp_end->dropped_packets += 1;
-		LOGP(DMGCP, LOGL_DEBUG,
-		     "endpoint %x output disabled, drop to %s %s %d %d\n",
-		     ENDPOINT_NUMBER(endp),
-		     dest == MGCP_DEST_NET? "net" : "bts",
-		     inet_ntoa(rtp_end->addr),
-		     ntohs(rtp_end->rtp_port),
-		     ntohs(rtp_end->rtcp_port)
-		    );
-	} else if (is_rtp) {
-		int cont;
-		int nbytes = 0;
-		int len = rc;
-		do {
-			cont = endp->cfg->rtp_processing_cb(endp, rtp_end,
-							buf, &len, RTP_BUF_SIZE);
-			if (cont < 0)
-				break;
-
-			mgcp_patch_and_count(endp, rtp_state, rtp_end, addr, buf, len);
-		LOGP(DMGCP, LOGL_DEBUG,
-		     "endpoint %x process/send to %s %s %d %d\n",
-		     ENDPOINT_NUMBER(endp),
-		     (dest == MGCP_DEST_NET)? "net" : "bts",
-		     inet_ntoa(rtp_end->addr),
-		     ntohs(rtp_end->rtp_port),
-		     ntohs(rtp_end->rtcp_port)
-		    );
-			forward_data(rtp_end->rtp.fd, &endp->taps[tap_idx],
-				     buf, len);
-
-			/* FIXME: HACK HACK HACK. See OS#2459.
-			 * The ip.access nano3G needs the first RTP payload's first two bytes to read hex
-			 * 'e400', or it will reject the RAB assignment. It seems to not harm other femto
-			 * cells (as long as we patch only the first RTP payload in each stream).
-			 */
-			if (tap_idx == MGCP_TAP_BTS_OUT
-			    && !rtp_state->patched_first_rtp_payload) {
-				uint8_t *data = (uint8_t*)&buf[12];
-				data[0] = 0xe4;
-				data[1] = 0x00;
-				rtp_state->patched_first_rtp_payload = true;
-			}
-
-			rc = mgcp_udp_send(rtp_end->rtp.fd,
-					   &rtp_end->addr,
-					   rtp_end->rtp_port, buf, len);
-
-			if (rc <= 0)
-				return rc;
-			nbytes += rc;
-			len = cont;
-		} while (len > 0);
-		return nbytes;
-	} else if (!tcfg->omit_rtcp) {
-		LOGP(DMGCP, LOGL_DEBUG,
-		     "endpoint %x send to %s %s %d %d\n",
-		     ENDPOINT_NUMBER(endp),
-		     dest == MGCP_DEST_NET? "net" : "bts",
-		     inet_ntoa(rtp_end->addr),
-		     ntohs(rtp_end->rtp_port),
-		     ntohs(rtp_end->rtcp_port)
-		    );
-
-		return mgcp_udp_send(rtp_end->rtcp.fd,
-				     &rtp_end->addr,
-				     rtp_end->rtcp_port, buf, rc);
-	}
-
-	return 0;
-}
-
-static int receive_from(struct mgcp_endpoint *endp, int fd, struct sockaddr_in *addr,
-			char *buf, int bufsize)
-{
-	int rc;
-	socklen_t slen = sizeof(*addr);
-
-	rc = recvfrom(fd, buf, bufsize, 0,
-			    (struct sockaddr *) addr, &slen);
-	if (rc < 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to receive message on: 0x%x errno: %d/%s\n",
-			ENDPOINT_NUMBER(endp), errno, strerror(errno));
-		return -1;
-	}
-
-	/* do not forward aynthing... maybe there is a packet from the bts */
-	if (!endp->allocated)
-		return -1;
-
-	#warning "Slight spec violation. With connection mode recvonly we should attempt to forward."
-
-	return rc;
-}
-
-static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
-{
-	char buf[RTP_BUF_SIZE];
-	struct sockaddr_in addr;
-	struct mgcp_endpoint *endp;
-	int rc, proto;
-
-	endp = (struct mgcp_endpoint *) fd->data;
-
-	rc = receive_from(endp, fd->fd, &addr, buf, sizeof(buf));
-	if (rc <= 0)
-		return -1;
-
-	LOGP(DMGCP, LOGL_DEBUG,
-	     "endpoint %x",
-	     ENDPOINT_NUMBER(endp));
-	LOGPC(DMGCP, LOGL_DEBUG,
-	      " from net %s %d",
-	      inet_ntoa(addr.sin_addr),
-	      ntohs(addr.sin_port));
-	LOGPC(DMGCP, LOGL_DEBUG,
-	      " net_end %s %d %d",
-	      inet_ntoa(endp->net_end.addr),
-	      ntohs(endp->net_end.rtp_port),
-	      ntohs(endp->net_end.rtcp_port));
-	LOGPC(DMGCP, LOGL_DEBUG,
-	      " bts_end %s %d %d\n",
-	      inet_ntoa(endp->bts_end.addr),
-	      ntohs(endp->bts_end.rtp_port),
-	      ntohs(endp->bts_end.rtcp_port)
-	     );
-
-	if (memcmp(&addr.sin_addr, &endp->net_end.addr, sizeof(addr.sin_addr)) != 0) {
-		LOGP(DMGCP, LOGL_ERROR,
-			"rtp_data_net: Endpoint 0x%x data from wrong address %s vs. ",
-			ENDPOINT_NUMBER(endp), inet_ntoa(addr.sin_addr));
-		LOGPC(DMGCP, LOGL_ERROR,
-			"%s\n", inet_ntoa(endp->net_end.addr));
-		return -1;
-	}
-
-	switch(endp->type) {
-	case MGCP_RTP_DEFAULT:
-	case MGCP_RTP_TRANSCODED:
-		if (endp->net_end.rtp_port != addr.sin_port &&
-		    endp->net_end.rtcp_port != addr.sin_port) {
-			LOGP(DMGCP, LOGL_ERROR,
-				"rtp_data_net: Data from wrong source port %d on 0x%x\n",
-				ntohs(addr.sin_port), ENDPOINT_NUMBER(endp));
-			return -1;
-		}
-		break;
-	case MGCP_OSMUX_BSC:
-	case MGCP_OSMUX_BSC_NAT:
-		break;
-	}
-
-	LOGP(DMGCP, LOGL_DEBUG,
-	     "rtp_data_net: Endpoint %x data from %s %d\n",
-	     ENDPOINT_NUMBER(endp),
-	     inet_ntoa(addr.sin_addr),
-	     ntohs(addr.sin_port));
-
-	/* throw away the dummy message */
-	if (rc == 1 && buf[0] == MGCP_DUMMY_LOAD) {
-		LOGP(DMGCP, LOGL_NOTICE, "Filtered dummy from network on 0x%x\n",
-			ENDPOINT_NUMBER(endp));
-		return 0;
-	}
-
-	proto = fd == &endp->net_end.rtp ? MGCP_PROTO_RTP : MGCP_PROTO_RTCP;
-	endp->net_end.packets += 1;
-	endp->net_end.octets += rc;
-
-	forward_data(fd->fd, &endp->taps[MGCP_TAP_NET_IN], buf, rc);
-
-	switch (endp->type) {
-	case MGCP_RTP_DEFAULT:
-		return mgcp_send(endp, MGCP_DEST_BTS, proto == MGCP_PROTO_RTP,
-				 &addr, buf, rc);
-	case MGCP_RTP_TRANSCODED:
-		return mgcp_send_transcoder(&endp->trans_net, endp->cfg,
-					    proto == MGCP_PROTO_RTP, buf, rc);
-	case MGCP_OSMUX_BSC_NAT:
-		return osmux_xfrm_to_osmux(MGCP_DEST_BTS, buf, rc, endp);
-	case MGCP_OSMUX_BSC:	/* Should not happen */
-		break;
-	}
-
-	LOGP(DMGCP, LOGL_ERROR, "Bad MGCP type %u on endpoint %u\n",
-	     endp->type, ENDPOINT_NUMBER(endp));
-	return 0;
-}
-
-static void discover_bts(struct mgcp_endpoint *endp, int proto, struct sockaddr_in *addr)
-{
-	struct mgcp_config *cfg = endp->cfg;
-
-	if (proto == MGCP_PROTO_RTP && endp->bts_end.rtp_port == 0) {
-		if (!cfg->bts_ip ||
-		    memcmp(&addr->sin_addr,
-			   &cfg->bts_in, sizeof(cfg->bts_in)) == 0 ||
-		    memcmp(&addr->sin_addr,
-			   &endp->bts_end.addr, sizeof(endp->bts_end.addr)) == 0) {
-
-			endp->bts_end.rtp_port = addr->sin_port;
-			endp->bts_end.addr = addr->sin_addr;
-
-			LOGP(DMGCP, LOGL_NOTICE,
-				"Found BTS for endpoint: 0x%x on port: %d/%d of %s\n",
-				ENDPOINT_NUMBER(endp), ntohs(endp->bts_end.rtp_port),
-				ntohs(endp->bts_end.rtcp_port), inet_ntoa(addr->sin_addr));
-		}
-	} else if (proto == MGCP_PROTO_RTCP && endp->bts_end.rtcp_port == 0) {
-		if (memcmp(&endp->bts_end.addr, &addr->sin_addr,
-				sizeof(endp->bts_end.addr)) == 0) {
-			endp->bts_end.rtcp_port = addr->sin_port;
-		}
-	}
-}
-
-static int rtp_data_bts(struct osmo_fd *fd, unsigned int what)
-{
-	char buf[RTP_BUF_SIZE];
-	struct sockaddr_in addr;
-	struct mgcp_endpoint *endp;
-	int rc, proto;
-
-	endp = (struct mgcp_endpoint *) fd->data;
-
-	rc = receive_from(endp, fd->fd, &addr, buf, sizeof(buf));
-	if (rc <= 0)
-		return -1;
-
-	proto = fd == &endp->bts_end.rtp ? MGCP_PROTO_RTP : MGCP_PROTO_RTCP;
-
-	/* We have no idea who called us, maybe it is the BTS. */
-	/* it was the BTS... */
-	discover_bts(endp, proto, &addr);
-
-	if (memcmp(&endp->bts_end.addr, &addr.sin_addr, sizeof(addr.sin_addr)) != 0) {
-		LOGP(DMGCP, LOGL_ERROR,
-			"rtp_data_bts: Data from wrong bts %s on 0x%x\n",
-			inet_ntoa(addr.sin_addr), ENDPOINT_NUMBER(endp));
-		return -1;
-	}
-
-	if (endp->bts_end.rtp_port != addr.sin_port &&
-	    endp->bts_end.rtcp_port != addr.sin_port) {
-		LOGP(DMGCP, LOGL_ERROR,
-			"rtp_data_bts: ata from wrong bts source port %d on 0x%x\n",
-			ntohs(addr.sin_port), ENDPOINT_NUMBER(endp));
-		return -1;
-	}
-
-	LOGP(DMGCP, LOGL_DEBUG,
-	     "rtp_data_bts: Endpoint %x data from %s %d\n",
-	     ENDPOINT_NUMBER(endp),
-	     inet_ntoa(addr.sin_addr),
-	     ntohs(addr.sin_port));
-
-	/* throw away the dummy message */
-	if (rc == 1 && buf[0] == MGCP_DUMMY_LOAD) {
-		LOGP(DMGCP, LOGL_NOTICE, "Filtered dummy from bts on 0x%x\n",
-			ENDPOINT_NUMBER(endp));
-		return 0;
-	}
-
-	/* do this before the loop handling */
-	endp->bts_end.packets += 1;
-	endp->bts_end.octets += rc;
-
-	forward_data(fd->fd, &endp->taps[MGCP_TAP_BTS_IN], buf, rc);
-
-	switch (endp->type) {
-	case MGCP_RTP_DEFAULT:
-		LOGP(DMGCP, LOGL_DEBUG,
-		     "rtp_data_bts: Endpoint %x MGCP_RTP_DEFAULT\n",
-		     ENDPOINT_NUMBER(endp));
-		return mgcp_send(endp, MGCP_DEST_NET, proto == MGCP_PROTO_RTP,
-				 &addr, buf, rc);
-	case MGCP_RTP_TRANSCODED:
-		return mgcp_send_transcoder(&endp->trans_bts, endp->cfg,
-					    proto == MGCP_PROTO_RTP, buf, rc);
-	case MGCP_OSMUX_BSC:
-		/* OSMUX translation: BTS -> BSC */
-		return osmux_xfrm_to_osmux(MGCP_DEST_NET, buf, rc, endp);
-	case MGCP_OSMUX_BSC_NAT:
-		break;	/* Should not happen */
-	}
-
-	LOGP(DMGCP, LOGL_ERROR, "Bad MGCP type %u on endpoint %u\n",
-	     endp->type, ENDPOINT_NUMBER(endp));
-	return 0;
-}
-
-static int rtp_data_transcoder(struct mgcp_rtp_end *end, struct mgcp_endpoint *_endp,
-			      int dest, struct osmo_fd *fd)
-{
-	char buf[RTP_BUF_SIZE];
-	struct sockaddr_in addr;
-	struct mgcp_config *cfg;
-	int rc, proto;
-
-	cfg = _endp->cfg;
-	rc = receive_from(_endp, fd->fd, &addr, buf, sizeof(buf));
-	if (rc <= 0)
-		return -1;
-
-	proto = fd == &end->rtp ? MGCP_PROTO_RTP : MGCP_PROTO_RTCP;
-
-	if (memcmp(&addr.sin_addr, &cfg->transcoder_in, sizeof(addr.sin_addr)) != 0) {
-		LOGP(DMGCP, LOGL_ERROR,
-			"Data not coming from transcoder dest: %d %s on 0x%x\n",
-			dest, inet_ntoa(addr.sin_addr), ENDPOINT_NUMBER(_endp));
-		return -1;
-	}
-
-	if (end->rtp_port != addr.sin_port &&
-	    end->rtcp_port != addr.sin_port) {
-		LOGP(DMGCP, LOGL_ERROR,
-			"Data from wrong transcoder dest %d source port %d on 0x%x\n",
-			dest, ntohs(addr.sin_port), ENDPOINT_NUMBER(_endp));
-		return -1;
-	}
-
-	/* throw away the dummy message */
-	if (rc == 1 && buf[0] == MGCP_DUMMY_LOAD) {
-		LOGP(DMGCP, LOGL_NOTICE, "Filtered dummy from transcoder dest %d on 0x%x\n",
-			dest, ENDPOINT_NUMBER(_endp));
-		return 0;
-	}
-
-	end->packets += 1;
-	return mgcp_send(_endp, dest, proto == MGCP_PROTO_RTP, &addr, buf, rc);
-}
-
-static int rtp_data_trans_net(struct osmo_fd *fd, unsigned int what)
-{
-	struct mgcp_endpoint *endp;
-	endp = (struct mgcp_endpoint *) fd->data;
-
-	return rtp_data_transcoder(&endp->trans_net, endp, MGCP_DEST_NET, fd);
-}
-
-static int rtp_data_trans_bts(struct osmo_fd *fd, unsigned int what)
-{
-	struct mgcp_endpoint *endp;
-	endp = (struct mgcp_endpoint *) fd->data;
-
-	return rtp_data_transcoder(&endp->trans_bts, endp, MGCP_DEST_BTS, fd);
-}
-
-int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port)
-{
-	struct sockaddr_in addr;
-	int on = 1;
-
-	fd->fd = socket(AF_INET, SOCK_DGRAM, 0);
-	if (fd->fd < 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to create UDP port.\n");
-		return -1;
-	}
-
-	setsockopt(fd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-	memset(&addr, 0, sizeof(addr));
-	addr.sin_family = AF_INET;
-	addr.sin_port = htons(port);
-	inet_aton(source_addr, &addr.sin_addr);
-
-	if (bind(fd->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		close(fd->fd);
-		fd->fd = -1;
-		return -1;
-	}
-
-	return 0;
-}
-
-int mgcp_set_ip_tos(int fd, int tos)
-{
-	int ret;
-	ret = setsockopt(fd, IPPROTO_IP, IP_TOS,
-			 &tos, sizeof(tos));
-	return ret != 0;
-}
-
-static int bind_rtp(struct mgcp_config *cfg, const char *source_addr,
-			struct mgcp_rtp_end *rtp_end, int endpno)
-{
-	if (mgcp_create_bind(source_addr, &rtp_end->rtp,
-			     rtp_end->local_port) != 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to create RTP port: %s:%d on 0x%x\n",
-		       source_addr, rtp_end->local_port, endpno);
-		goto cleanup0;
-	}
-
-	if (mgcp_create_bind(source_addr, &rtp_end->rtcp,
-			     rtp_end->local_port + 1) != 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to create RTCP port: %s:%d on 0x%x\n",
-		       source_addr, rtp_end->local_port + 1, endpno);
-		goto cleanup1;
-	}
-
-	mgcp_set_ip_tos(rtp_end->rtp.fd, cfg->endp_dscp);
-	mgcp_set_ip_tos(rtp_end->rtcp.fd, cfg->endp_dscp);
-
-	rtp_end->rtp.when = BSC_FD_READ;
-	if (osmo_fd_register(&rtp_end->rtp) != 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to register RTP port %d on 0x%x\n",
-			rtp_end->local_port, endpno);
-		goto cleanup2;
-	}
-
-	rtp_end->rtcp.when = BSC_FD_READ;
-	if (osmo_fd_register(&rtp_end->rtcp) != 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to register RTCP port %d on 0x%x\n",
-			rtp_end->local_port + 1, endpno);
-		goto cleanup3;
-	}
-
-	return 0;
-
-cleanup3:
-	osmo_fd_unregister(&rtp_end->rtp);
-cleanup2:
-	close(rtp_end->rtcp.fd);
-	rtp_end->rtcp.fd = -1;
-cleanup1:
-	close(rtp_end->rtp.fd);
-	rtp_end->rtp.fd = -1;
-cleanup0:
-	return -1;
-}
-
-static int int_bind(const char *port,
-		    struct mgcp_rtp_end *end, int (*cb)(struct osmo_fd *, unsigned),
-		    struct mgcp_endpoint *_endp,
-		    const char *source_addr, int rtp_port)
-{
-	if (end->rtp.fd != -1 || end->rtcp.fd != -1) {
-		LOGP(DMGCP, LOGL_ERROR, "Previous %s was still bound on %d\n",
-			port, ENDPOINT_NUMBER(_endp));
-		mgcp_free_rtp_port(end);
-	}
-
-	end->local_port = rtp_port;
-	end->rtp.cb = cb;
-	end->rtp.data = _endp;
-	end->rtcp.data = _endp;
-	end->rtcp.cb = cb;
-	return bind_rtp(_endp->cfg, source_addr, end, ENDPOINT_NUMBER(_endp));
-}
-
-int mgcp_bind_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port)
-{
-	return int_bind("bts-port", &endp->bts_end,
-			rtp_data_bts, endp,
-			mgcp_bts_src_addr(endp), rtp_port);
-}
-
-int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port)
-{
-	return int_bind("net-port", &endp->net_end,
-			rtp_data_net, endp,
-			mgcp_net_src_addr(endp), rtp_port);
-}
-
-int mgcp_bind_trans_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port)
-{
-	return int_bind("trans-net", &endp->trans_net,
-			rtp_data_trans_net, endp,
-			endp->cfg->source_addr, rtp_port);
-}
-
-int mgcp_bind_trans_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port)
-{
-	return int_bind("trans-bts", &endp->trans_bts,
-			rtp_data_trans_bts, endp,
-			endp->cfg->source_addr, rtp_port);
-}
-
-int mgcp_free_rtp_port(struct mgcp_rtp_end *end)
-{
-	if (end->rtp.fd != -1) {
-		close(end->rtp.fd);
-		end->rtp.fd = -1;
-		osmo_fd_unregister(&end->rtp);
-	}
-
-	if (end->rtcp.fd != -1) {
-		close(end->rtcp.fd);
-		end->rtcp.fd = -1;
-		osmo_fd_unregister(&end->rtcp);
-	}
-
-	return 0;
-}
-
-
-void mgcp_state_calc_loss(struct mgcp_rtp_state *state,
-			struct mgcp_rtp_end *end, uint32_t *expected,
-			int *loss)
-{
-	*expected = state->stats_cycles + state->stats_max_seq;
-	*expected = *expected - state->stats_base_seq + 1;
-
-	if (!state->stats_initialized) {
-		*expected = 0;
-		*loss = 0;
-		return;
-	}
-
-	/*
-	 * Make sure the sign is correct and use the biggest
-	 * positive/negative number that fits.
-	 */
-	*loss = *expected - end->packets;
-	if (*expected < end->packets) {
-		if (*loss > 0)
-			*loss = INT_MIN;
-	} else {
-		if (*loss < 0)
-			*loss = INT_MAX;
-	}
-}
-
-uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *state)
-{
-	if (!state->stats_initialized)
-		return 0;
-	return state->stats_jitter >> 4;
-}
diff --git a/src/libmgcp/mgcp_osmux.c b/src/libmgcp/mgcp_osmux.c
deleted file mode 100644
index c52984b..0000000
--- a/src/libmgcp/mgcp_osmux.c
+++ /dev/null
@@ -1,583 +0,0 @@
-/*
- * (C) 2012-2013 by Pablo Neira Ayuso <pablo@gnumonks.org>
- * (C) 2012-2013 by On Waves ehf <http://www.on-waves.com>
- * All rights not specifically granted under this license are 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.
- */
-
-#include <stdio.h> /* for printf */
-#include <string.h> /* for memcpy */
-#include <stdlib.h> /* for abs */
-#include <inttypes.h> /* for PRIu64 */
-#include <netinet/in.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/talloc.h>
-
-#include <osmocom/netif/osmux.h>
-#include <osmocom/netif/rtp.h>
-
-#include <openbsc/mgcp.h>
-#include <openbsc/mgcp_internal.h>
-#include <openbsc/osmux.h>
-
-static struct osmo_fd osmux_fd;
-
-static LLIST_HEAD(osmux_handle_list);
-
-struct osmux_handle {
-	struct llist_head head;
-	struct osmux_in_handle *in;
-	struct in_addr rem_addr;
-	int rem_port;
-	int refcnt;
-};
-
-static void *osmux;
-
-static void osmux_deliver(struct msgb *batch_msg, void *data)
-{
-	struct osmux_handle *handle = data;
-	struct sockaddr_in out = {
-		.sin_family = AF_INET,
-		.sin_port = handle->rem_port,
-	};
-
-	memcpy(&out.sin_addr, &handle->rem_addr, sizeof(handle->rem_addr));
-	sendto(osmux_fd.fd, batch_msg->data, batch_msg->len, 0,
-		(struct sockaddr *)&out, sizeof(out));
-	msgb_free(batch_msg);
-}
-
-static struct osmux_handle *
-osmux_handle_find_get(struct in_addr *addr, int rem_port)
-{
-	struct osmux_handle *h;
-
-	/* Lookup for existing OSMUX handle for this destination address. */
-	llist_for_each_entry(h, &osmux_handle_list, head) {
-		if (memcmp(&h->rem_addr, addr, sizeof(struct in_addr)) == 0 &&
-		    h->rem_port == rem_port) {
-			LOGP(DMGCP, LOGL_DEBUG, "using existing OSMUX handle "
-						"for addr=%s:%d\n",
-				inet_ntoa(*addr), ntohs(rem_port));
-			h->refcnt++;
-			return h;
-		}
-	}
-
-	return NULL;
-}
-
-static void osmux_handle_put(struct osmux_in_handle *in)
-{
-	struct osmux_handle *h;
-
-	/* Lookup for existing OSMUX handle for this destination address. */
-	llist_for_each_entry(h, &osmux_handle_list, head) {
-		if (h->in == in) {
-			if (--h->refcnt == 0) {
-				LOGP(DMGCP, LOGL_INFO,
-				     "Releasing unused osmux handle for %s:%d\n",
-				     inet_ntoa(h->rem_addr),
-				     ntohs(h->rem_port));
-				LOGP(DMGCP, LOGL_INFO, "Stats: "
-				     "input RTP msgs: %u bytes: %"PRIu64" "
-				     "output osmux msgs: %u bytes: %"PRIu64"\n",
-				     in->stats.input_rtp_msgs,
-				     in->stats.input_rtp_bytes,
-				     in->stats.output_osmux_msgs,
-				     in->stats.output_osmux_bytes);
-				llist_del(&h->head);
-				osmux_xfrm_input_fini(h->in);
-				talloc_free(h);
-			}
-			return;
-		}
-	}
-	LOGP(DMGCP, LOGL_ERROR, "cannot find Osmux input handle %p\n", in);
-}
-
-static struct osmux_handle *
-osmux_handle_alloc(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
-{
-	struct osmux_handle *h;
-
-	h = talloc_zero(osmux, struct osmux_handle);
-	if (!h)
-		return NULL;
-	h->rem_addr = *addr;
-	h->rem_port = rem_port;
-	h->refcnt++;
-
-	h->in = talloc_zero(h, struct osmux_in_handle);
-	if (!h->in) {
-		talloc_free(h);
-		return NULL;
-	}
-
-	h->in->osmux_seq = 0; /* sequence number to start OSmux message from */
-	h->in->batch_factor = cfg->osmux_batch;
-	/* If batch size is zero, the library defaults to 1470 bytes. */
-	h->in->batch_size = cfg->osmux_batch_size;
-	h->in->deliver = osmux_deliver;
-	osmux_xfrm_input_init(h->in);
-	h->in->data = h;
-
-	llist_add(&h->head, &osmux_handle_list);
-
-	LOGP(DMGCP, LOGL_DEBUG, "created new OSMUX handle for addr=%s:%d\n",
-		inet_ntoa(*addr), ntohs(rem_port));
-
-	return h;
-}
-
-static struct osmux_in_handle *
-osmux_handle_lookup(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
-{
-	struct osmux_handle *h;
-
-	h = osmux_handle_find_get(addr, rem_port);
-	if (h != NULL)
-		return h->in;
-
-	h = osmux_handle_alloc(cfg, addr, rem_port);
-	if (h == NULL)
-		return NULL;
-
-	return h->in;
-}
-
-int osmux_xfrm_to_osmux(int type, char *buf, int rc, struct mgcp_endpoint *endp)
-{
-	int ret;
-	struct msgb *msg;
-
-	msg = msgb_alloc(4096, "RTP");
-	if (!msg)
-		return 0;
-
-	memcpy(msg->data, buf, rc);
-	msgb_put(msg, rc);
-
-	while ((ret = osmux_xfrm_input(endp->osmux.in, msg, endp->osmux.cid)) > 0) {
-		/* batch full, build and deliver it */
-		osmux_xfrm_input_deliver(endp->osmux.in);
-	}
-	return 0;
-}
-
-static struct mgcp_endpoint *
-endpoint_lookup(struct mgcp_config *cfg, int cid,
-		struct in_addr *from_addr, int type)
-{
-	struct mgcp_endpoint *tmp = NULL;
-	int i;
-
-	/* Lookup for the endpoint that corresponds to this port */
-	for (i=0; i<cfg->trunk.number_endpoints; i++) {
-		struct in_addr *this;
-
-		tmp = &cfg->trunk.endpoints[i];
-
-		if (!tmp->allocated)
-			continue;
-
-		switch(type) {
-		case MGCP_DEST_NET:
-			this = &tmp->net_end.addr;
-			break;
-		case MGCP_DEST_BTS:
-			this = &tmp->bts_end.addr;
-			break;
-		default:
-			/* Should not ever happen */
-			LOGP(DMGCP, LOGL_ERROR, "Bad type %d. Fix your code.\n", type);
-			return NULL;
-		}
-
-		if (tmp->osmux.cid == cid && this->s_addr == from_addr->s_addr)
-			return tmp;
-	}
-
-	LOGP(DMGCP, LOGL_ERROR, "Cannot find endpoint with cid=%d\n", cid);
-
-	return NULL;
-}
-
-static void scheduled_tx_net_cb(struct msgb *msg, void *data)
-{
-	struct mgcp_endpoint *endp = data;
-	struct sockaddr_in addr = {
-		.sin_addr = endp->net_end.addr,
-		.sin_port = endp->net_end.rtp_port,
-	};
-
-	endp->bts_end.octets += msg->len;
-	endp->bts_end.packets++;
-
-	mgcp_send(endp, MGCP_DEST_NET, 1, &addr, (char *)msg->data, msg->len);
-	msgb_free(msg);
-}
-
-static void scheduled_tx_bts_cb(struct msgb *msg, void *data)
-{
-	struct mgcp_endpoint *endp = data;
-	struct sockaddr_in addr = {
-		.sin_addr = endp->bts_end.addr,
-		.sin_port = endp->bts_end.rtp_port,
-	};
-
-	endp->net_end.octets += msg->len;
-	endp->net_end.packets++;
-
-	mgcp_send(endp, MGCP_DEST_BTS, 1, &addr, (char *)msg->data, msg->len);
-	msgb_free(msg);
-}
-
-static struct msgb *osmux_recv(struct osmo_fd *ofd, struct sockaddr_in *addr)
-{
-	struct msgb *msg;
-	socklen_t slen = sizeof(*addr);
-	int ret;
-
-	msg = msgb_alloc(4096, "OSMUX");
-	if (!msg) {
-		LOGP(DMGCP, LOGL_ERROR, "cannot allocate message\n");
-		return NULL;
-	}
-	ret = recvfrom(ofd->fd, msg->data, msg->data_len, 0,
-			(struct sockaddr *)addr, &slen);
-	if (ret <= 0) {
-		msgb_free(msg);
-		LOGP(DMGCP, LOGL_ERROR, "cannot receive message\n");
-		return NULL;
-	}
-	msgb_put(msg, ret);
-
-	return msg;
-}
-
-#define osmux_chunk_length(msg, rem) (rem - msg->len);
-
-int osmux_read_from_bsc_nat_cb(struct osmo_fd *ofd, unsigned int what)
-{
-	struct msgb *msg;
-	struct osmux_hdr *osmuxh;
-	struct llist_head list;
-	struct sockaddr_in addr;
-	struct mgcp_config *cfg = ofd->data;
-	uint32_t rem;
-
-	msg = osmux_recv(ofd, &addr);
-	if (!msg)
-		return -1;
-
-	/* not any further processing dummy messages */
-	if (msg->data[0] == MGCP_DUMMY_LOAD)
-		goto out;
-
-	rem = msg->len;
-	while((osmuxh = osmux_xfrm_output_pull(msg)) != NULL) {
-		struct mgcp_endpoint *endp;
-
-		/* Yes, we use MGCP_DEST_NET to locate the origin */
-		endp = endpoint_lookup(cfg, osmuxh->circuit_id,
-				       &addr.sin_addr, MGCP_DEST_NET);
-		if (!endp) {
-			LOGP(DMGCP, LOGL_ERROR,
-			     "Cannot find an endpoint for circuit_id=%d\n",
-			     osmuxh->circuit_id);
-			goto out;
-		}
-		endp->osmux.stats.octets += osmux_chunk_length(msg, rem);
-		endp->osmux.stats.chunks++;
-		rem = msg->len;
-
-		osmux_xfrm_output(osmuxh, &endp->osmux.out, &list);
-		osmux_tx_sched(&list, scheduled_tx_bts_cb, endp);
-	}
-out:
-	msgb_free(msg);
-	return 0;
-}
-
-/* This is called from the bsc-nat */
-static int osmux_handle_dummy(struct mgcp_config *cfg, struct sockaddr_in *addr,
-			      struct msgb *msg)
-{
-	struct mgcp_endpoint *endp;
-	uint8_t osmux_cid;
-
-	if (msg->len < 1 + sizeof(osmux_cid)) {
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Discarding truncated Osmux dummy load\n");
-		goto out;
-	}
-
-	LOGP(DMGCP, LOGL_DEBUG, "Received Osmux dummy load from %s\n",
-	     inet_ntoa(addr->sin_addr));
-
-	if (!cfg->osmux) {
-		LOGP(DMGCP, LOGL_ERROR,
-		     "bsc wants to use Osmux but bsc-nat did not request it\n");
-		goto out;
-	}
-
-	/* extract the osmux CID from the dummy message */
-	memcpy(&osmux_cid, &msg->data[1], sizeof(osmux_cid));
-
-	endp = endpoint_lookup(cfg, osmux_cid, &addr->sin_addr, MGCP_DEST_BTS);
-	if (!endp) {
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Cannot find endpoint for Osmux CID %d\n", osmux_cid);
-		goto out;
-	}
-
-	if (endp->osmux.state == OSMUX_STATE_ENABLED)
-		goto out;
-
-	if (osmux_enable_endpoint(endp, &addr->sin_addr, addr->sin_port) < 0 ) {
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Could not enable osmux in endpoint %d\n",
-		     ENDPOINT_NUMBER(endp));
-		goto out;
-	}
-
-	LOGP(DMGCP, LOGL_INFO, "Enabling osmux in endpoint %d for %s:%u\n",
-	     ENDPOINT_NUMBER(endp), inet_ntoa(addr->sin_addr),
-	     ntohs(addr->sin_port));
-out:
-	msgb_free(msg);
-	return 0;
-}
-
-int osmux_read_from_bsc_cb(struct osmo_fd *ofd, unsigned int what)
-{
-	struct msgb *msg;
-	struct osmux_hdr *osmuxh;
-	struct llist_head list;
-	struct sockaddr_in addr;
-	struct mgcp_config *cfg = ofd->data;
-	uint32_t rem;
-
-	msg = osmux_recv(ofd, &addr);
-	if (!msg)
-		return -1;
-
-	/* not any further processing dummy messages */
-	if (msg->data[0] == MGCP_DUMMY_LOAD)
-		return osmux_handle_dummy(cfg, &addr, msg);
-
-	rem = msg->len;
-	while((osmuxh = osmux_xfrm_output_pull(msg)) != NULL) {
-		struct mgcp_endpoint *endp;
-
-		/* Yes, we use MGCP_DEST_BTS to locate the origin */
-		endp = endpoint_lookup(cfg, osmuxh->circuit_id,
-				       &addr.sin_addr, MGCP_DEST_BTS);
-		if (!endp) {
-			LOGP(DMGCP, LOGL_ERROR,
-			     "Cannot find an endpoint for circuit_id=%d\n",
-			     osmuxh->circuit_id);
-			goto out;
-		}
-		endp->osmux.stats.octets += osmux_chunk_length(msg, rem);
-		endp->osmux.stats.chunks++;
-		rem = msg->len;
-
-		osmux_xfrm_output(osmuxh, &endp->osmux.out, &list);
-		osmux_tx_sched(&list, scheduled_tx_net_cb, endp);
-	}
-out:
-	msgb_free(msg);
-	return 0;
-}
-
-int osmux_init(int role, struct mgcp_config *cfg)
-{
-	int ret;
-
-	switch(role) {
-	case OSMUX_ROLE_BSC:
-		osmux_fd.cb = osmux_read_from_bsc_nat_cb;
-		break;
-	case OSMUX_ROLE_BSC_NAT:
-		osmux_fd.cb = osmux_read_from_bsc_cb;
-		break;
-	default:
-		LOGP(DMGCP, LOGL_ERROR, "wrong role for OSMUX\n");
-		return -1;
-	}
-	osmux_fd.data = cfg;
-
-	ret = mgcp_create_bind(cfg->osmux_addr, &osmux_fd, cfg->osmux_port);
-	if (ret < 0) {
-		LOGP(DMGCP, LOGL_ERROR, "cannot bind OSMUX socket\n");
-		return ret;
-	}
-	mgcp_set_ip_tos(osmux_fd.fd, cfg->endp_dscp);
-	osmux_fd.when |= BSC_FD_READ;
-
-	ret = osmo_fd_register(&osmux_fd);
-	if (ret < 0) {
-		LOGP(DMGCP, LOGL_ERROR, "cannot register OSMUX socket\n");
-		return ret;
-	}
-	cfg->osmux_init = 1;
-
-	return 0;
-}
-
-int osmux_enable_endpoint(struct mgcp_endpoint *endp, struct in_addr *addr, uint16_t port)
-{
-	/* If osmux is enabled, initialize the output handler. This handler is
-	 * used to reconstruct the RTP flow from osmux. The RTP SSRC is
-	 * allocated based on the circuit ID (endp->osmux.cid), which is unique
-	 * in the local scope to the BSC/BSC-NAT. We use it to divide the RTP
-	 * SSRC space (2^32) by the 256 possible circuit IDs, then randomly
-	 * select one value from that window. Thus, we have no chance to have
-	 * overlapping RTP SSRC traveling to the BTSes behind the BSC,
-	 * similarly, for flows traveling to the MSC.
-	 */
-	static const uint32_t rtp_ssrc_winlen = UINT32_MAX / 256;
-
-	if (endp->osmux.state == OSMUX_STATE_DISABLED) {
-		LOGP(DMGCP, LOGL_ERROR, "Endpoint %u didn't request Osmux\n",
-		     ENDPOINT_NUMBER(endp));
-		return -1;
-	}
-
-	osmux_xfrm_output_init(&endp->osmux.out,
-			       (endp->osmux.cid * rtp_ssrc_winlen) +
-			       (random() % rtp_ssrc_winlen));
-
-	endp->osmux.in = osmux_handle_lookup(endp->cfg, addr, port);
-	if (!endp->osmux.in) {
-		LOGP(DMGCP, LOGL_ERROR, "Cannot allocate input osmux handle\n");
-		return -1;
-	}
-	if (!osmux_xfrm_input_open_circuit(endp->osmux.in, endp->osmux.cid,
-					   endp->cfg->osmux_dummy)) {
-		LOGP(DMGCP, LOGL_ERROR, "Cannot open osmux circuit %u\n",
-		     endp->osmux.cid);
-		return -1;
-	}
-
-	switch (endp->cfg->role) {
-		case MGCP_BSC_NAT:
-			endp->type = MGCP_OSMUX_BSC_NAT;
-			break;
-		case MGCP_BSC:
-			endp->type = MGCP_OSMUX_BSC;
-			break;
-	}
-	endp->osmux.state = OSMUX_STATE_ENABLED;
-
-	return 0;
-}
-
-void osmux_disable_endpoint(struct mgcp_endpoint *endp)
-{
-	LOGP(DMGCP, LOGL_INFO, "Releasing endpoint %u using Osmux CID %u\n",
-	     ENDPOINT_NUMBER(endp), endp->osmux.cid);
-	osmux_xfrm_input_close_circuit(endp->osmux.in, endp->osmux.cid);
-	endp->osmux.state = OSMUX_STATE_DISABLED;
-	endp->osmux.cid = -1;
-	osmux_handle_put(endp->osmux.in);
-}
-
-void osmux_release_cid(struct mgcp_endpoint *endp)
-{
-	if (endp->osmux.allocated_cid >= 0)
-		osmux_put_cid(endp->osmux.allocated_cid);
-	endp->osmux.allocated_cid = -1;
-}
-
-void osmux_allocate_cid(struct mgcp_endpoint *endp)
-{
-	osmux_release_cid(endp);
-	endp->osmux.allocated_cid = osmux_get_cid();
-}
-
-/* We don't need to send the dummy load for osmux so often as another endpoint
- * may have already punched the hole in the firewall. This approach is simple
- * though.
- */
-int osmux_send_dummy(struct mgcp_endpoint *endp)
-{
-	char buf[1 + sizeof(uint8_t)];
-	struct in_addr addr_unset = {};
-
-	buf[0] = MGCP_DUMMY_LOAD;
-	memcpy(&buf[1], &endp->osmux.cid, sizeof(endp->osmux.cid));
-
-	/* Wait until we have the connection information from MDCX */
-	if (memcmp(&endp->net_end.addr, &addr_unset, sizeof(addr_unset)) == 0)
-		return 0;
-
-	if (endp->osmux.state == OSMUX_STATE_ACTIVATING) {
-		if (osmux_enable_endpoint(endp, &endp->net_end.addr,
-					  htons(endp->cfg->osmux_port)) < 0) {
-			LOGP(DMGCP, LOGL_ERROR,
-			     "Could not activate osmux in endpoint %d\n",
-			     ENDPOINT_NUMBER(endp));
-		}
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Osmux CID %u for %s:%u is now enabled\n",
-		     endp->osmux.cid, inet_ntoa(endp->net_end.addr),
-		     endp->cfg->osmux_port);
-	}
-	LOGP(DMGCP, LOGL_DEBUG,
-	     "sending OSMUX dummy load to %s CID %u\n",
-	     inet_ntoa(endp->net_end.addr), endp->osmux.cid);
-
-	return mgcp_udp_send(osmux_fd.fd, &endp->net_end.addr,
-			     htons(endp->cfg->osmux_port), buf, sizeof(buf));
-}
-
-/* bsc-nat allocates/releases the Osmux circuit ID */
-static uint8_t osmux_cid_bitmap[(OSMUX_CID_MAX + 1) / 8];
-
-int osmux_used_cid(void)
-{
-	int i, j, used = 0;
-
-	for (i = 0; i < sizeof(osmux_cid_bitmap); i++) {
-		for (j = 0; j < 8; j++) {
-			if (osmux_cid_bitmap[i] & (1 << j))
-				used += 1;
-		}
-	}
-
-	return used;
-}
-
-int osmux_get_cid(void)
-{
-	int i, j;
-
-	for (i = 0; i < sizeof(osmux_cid_bitmap); i++) {
-		for (j = 0; j < 8; j++) {
-			if (osmux_cid_bitmap[i] & (1 << j))
-				continue;
-
-			osmux_cid_bitmap[i] |= (1 << j);
-			LOGP(DMGCP, LOGL_DEBUG,
-			     "Allocating Osmux CID %u from pool\n", (i * 8) + j);
-			return (i * 8) + j;
-		}
-	}
-
-	LOGP(DMGCP, LOGL_ERROR, "All Osmux circuits are in use!\n");
-	return -1;
-}
-
-void osmux_put_cid(uint8_t osmux_cid)
-{
-	LOGP(DMGCP, LOGL_DEBUG, "Osmux CID %u is back to the pool\n", osmux_cid);
-	osmux_cid_bitmap[osmux_cid / 8] &= ~(1 << (osmux_cid % 8));
-}
diff --git a/src/libmgcp/mgcp_protocol.c b/src/libmgcp/mgcp_protocol.c
deleted file mode 100644
index c8b6e86..0000000
--- a/src/libmgcp/mgcp_protocol.c
+++ /dev/null
@@ -1,1639 +0,0 @@
-/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
-/* The protocol implementation */
-
-/*
- * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-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/>.
- *
- */
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <limits.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/select.h>
-
-#include <openbsc/mgcp.h>
-#include <openbsc/mgcp_internal.h>
-
-#define for_each_non_empty_line(line, save)			\
-	for (line = strtok_r(NULL, "\r\n", &save); line;\
-	     line = strtok_r(NULL, "\r\n", &save))
-
-
-static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end);
-
-struct mgcp_request {
-	char *name;
-	struct msgb *(*handle_request) (struct mgcp_parse_data *data);
-	char *debug_name;
-};
-
-#define MGCP_REQUEST(NAME, REQ, DEBUG_NAME) \
-	{ .name = NAME, .handle_request = REQ, .debug_name = DEBUG_NAME },
-
-static struct msgb *handle_audit_endpoint(struct mgcp_parse_data *data);
-static struct msgb *handle_create_con(struct mgcp_parse_data *data);
-static struct msgb *handle_delete_con(struct mgcp_parse_data *data);
-static struct msgb *handle_modify_con(struct mgcp_parse_data *data);
-static struct msgb *handle_rsip(struct mgcp_parse_data *data);
-static struct msgb *handle_noti_req(struct mgcp_parse_data *data);
-
-static void create_transcoder(struct mgcp_endpoint *endp);
-static void delete_transcoder(struct mgcp_endpoint *endp);
-
-static int setup_rtp_processing(struct mgcp_endpoint *endp);
-
-static int mgcp_analyze_header(struct mgcp_parse_data *parse, char *data);
-
-/* Display an mgcp message on the log output */
-void display_mgcp_message(unsigned char *message, unsigned int len,
-			  char *preamble)
-{
-	unsigned char line[80];
-	unsigned char *ptr;
-	unsigned int consumed = 0;
-	unsigned int consumed_line = 0;
-	unsigned int line_count = 0;
-
-	if (!log_check_level(DMGCP, LOGL_DEBUG))
-		return;
-
-	while (1) {
-		memset(line, 0, sizeof(line));
-		ptr = line;
-		consumed_line = 0;
-		do {
-			if (*message != '\n' && *message != '\r') {
-				*ptr = *message;
-				ptr++;
-			}
-			message++;
-			consumed++;
-			consumed_line++;
-		} while (*message != '\n' && consumed < len
-			 && consumed_line < sizeof(line));
-
-		if (strlen((const char *)line)) {
-			LOGP(DMGCP, LOGL_DEBUG, "%s: line #%02u: %s\n",
-			     preamble, line_count, line);
-			line_count++;
-		}
-
-		if (consumed >= len)
-			return;
-	}
-}
-
-static int mgcp_check_param(const struct mgcp_endpoint *endp, const char *line)
-{
-	const size_t line_len = strlen(line);
-	if (line[0] != '\0' && line_len < 2) {
-		LOGP(DMGCP, LOGL_ERROR,
-			"Wrong MGCP option format: '%s' on 0x%x\n",
-			line, ENDPOINT_NUMBER(endp));
-		return 0;
-	}
-
-	return 1;
-}
-
-static uint32_t generate_call_id(struct mgcp_config *cfg)
-{
-	int i;
-
-	/* use the call id */
-	++cfg->last_call_id;
-
-	/* handle wrap around */
-	if (cfg->last_call_id == CI_UNUSED)
-		++cfg->last_call_id;
-
-	/* callstack can only be of size number_of_endpoints */
-	/* verify that the call id is free, e.g. in case of overrun */
-	for (i = 1; i < cfg->trunk.number_endpoints; ++i)
-		if (cfg->trunk.endpoints[i].ci == cfg->last_call_id)
-			return generate_call_id(cfg);
-
-	return cfg->last_call_id;
-}
-
-/*
- * array of function pointers for handling various
- * messages. In the future this might be binary sorted
- * for performance reasons.
- */
-static const struct mgcp_request mgcp_requests [] = {
-	MGCP_REQUEST("AUEP", handle_audit_endpoint, "AuditEndpoint")
-	MGCP_REQUEST("CRCX", handle_create_con, "CreateConnection")
-	MGCP_REQUEST("DLCX", handle_delete_con, "DeleteConnection")
-	MGCP_REQUEST("MDCX", handle_modify_con, "ModifiyConnection")
-	MGCP_REQUEST("RQNT", handle_noti_req, "NotificationRequest")
-
-	/* SPEC extension */
-	MGCP_REQUEST("RSIP", handle_rsip, "ReSetInProgress")
-};
-
-static struct msgb *mgcp_msgb_alloc(void)
-{
-	struct msgb *msg;
-	msg = msgb_alloc_headroom(4096, 128, "MGCP msg");
-	if (!msg)
-	    LOGP(DMGCP, LOGL_ERROR, "Failed to msgb for MGCP data.\n");
-
-	return msg;
-}
-
-static struct msgb *do_retransmission(const struct mgcp_endpoint *endp)
-{
-	struct msgb *msg = mgcp_msgb_alloc();
-	if (!msg)
-		return NULL;
-
-	msg->l2h = msgb_put(msg, strlen(endp->last_response));
-	memcpy(msg->l2h, endp->last_response, msgb_l2len(msg));
-	return msg;
-}
-
-static struct msgb *create_resp(struct mgcp_endpoint *endp, int code,
-				const char *txt, const char *msg,
-				const char *trans, const char *param,
-				const char *sdp)
-{
-	int len;
-	struct msgb *res;
-
-	res = mgcp_msgb_alloc();
-	if (!res)
-		return NULL;
-
-	len = snprintf((char *) res->data, 2048, "%d %s%s%s\r\n%s",
-			code, trans, txt, param ? param : "", sdp ? sdp : "");
-	if (len < 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to sprintf MGCP response.\n");
-		msgb_free(res);
-		return NULL;
-	}
-
-	res->l2h = msgb_put(res, len);
-	LOGP(DMGCP, LOGL_DEBUG, "Generated response: code=%d\n", code);
-	display_mgcp_message(res->l2h, msgb_l2len(res), "Generated response");
-
-	/*
-	 * Remember the last transmission per endpoint.
-	 */
-	if (endp) {
-		struct mgcp_trunk_config *tcfg = endp->tcfg;
-		talloc_free(endp->last_response);
-		talloc_free(endp->last_trans);
-		endp->last_trans = talloc_strdup(tcfg->endpoints, trans);
-		endp->last_response = talloc_strndup(tcfg->endpoints,
-						(const char *) res->l2h,
-						msgb_l2len(res));
-	}
-
-	return res;
-}
-
-static struct msgb *create_ok_resp_with_param(struct mgcp_endpoint *endp,
-					int code, const char *msg,
-					const char *trans, const char *param)
-{
-	return create_resp(endp, code, " OK", msg, trans, param, NULL);
-}
-
-static struct msgb *create_ok_response(struct mgcp_endpoint *endp,
-					int code, const char *msg, const char *trans)
-{
-	return create_ok_resp_with_param(endp, code, msg, trans, NULL);
-}
-
-static struct msgb *create_err_response(struct mgcp_endpoint *endp,
-					int code, const char *msg, const char *trans)
-{
-	return create_resp(endp, code, " FAIL", msg, trans, NULL, NULL);
-}
-
-static int write_response_sdp(struct mgcp_endpoint *endp,
-			      char *sdp_record, size_t size, const char *addr)
-{
-	const char *fmtp_extra;
-	const char *audio_name;
-	int payload_type;
-	int len;
-	int nchars;
-
-	endp->cfg->get_net_downlink_format_cb(endp, &payload_type,
-					      &audio_name, &fmtp_extra);
-
-	len = snprintf(sdp_record, size,
-			"v=0\r\n"
-			"o=- %u 23 IN IP4 %s\r\n"
-			"s=-\r\n"
-			"c=IN IP4 %s\r\n"
-			"t=0 0\r\n",
-			endp->ci, addr, addr);
-
-	if (len < 0 || len >= size)
-		goto buffer_too_small;
-
-	if (payload_type >= 0) {
-		nchars = snprintf(sdp_record + len, size - len,
-				  "m=audio %d RTP/AVP %d\r\n",
-				  endp->net_end.local_port, payload_type);
-		if (nchars < 0 || nchars >= size - len)
-			goto buffer_too_small;
-
-		len += nchars;
-
-		if (audio_name && endp->tcfg->audio_send_name) {
-			nchars = snprintf(sdp_record + len, size - len,
-					  "a=rtpmap:%d %s\r\n",
-					  payload_type, audio_name);
-
-			if (nchars < 0 || nchars >= size - len)
-				goto buffer_too_small;
-
-			len += nchars;
-		}
-
-		if (fmtp_extra) {
-			nchars = snprintf(sdp_record + len, size - len,
-					  "%s\r\n", fmtp_extra);
-
-			if (nchars < 0 || nchars >= size - len)
-				goto buffer_too_small;
-
-			len += nchars;
-		}
-	}
-	if (endp->bts_end.packet_duration_ms > 0 && endp->tcfg->audio_send_ptime) {
-		nchars = snprintf(sdp_record + len, size - len,
-				  "a=ptime:%d\r\n",
-				  endp->bts_end.packet_duration_ms);
-		if (nchars < 0 || nchars >= size - len)
-			goto buffer_too_small;
-
-		len += nchars;
-	}
-
-	return len;
-
-buffer_too_small:
-	LOGP(DMGCP, LOGL_ERROR, "SDP buffer too small: %zu (needed %d)\n",
-	     size, len);
-	return -1;
-}
-
-static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
-					     const char *msg, const char *trans_id)
-{
-	const char *addr = endp->cfg->local_ip;
-	char sdp_record[4096];
-	int len;
-	int nchars;
-	char osmux_extension[strlen("\nX-Osmux: 255") + 1];
-
-	if (!addr)
-		addr = mgcp_net_src_addr(endp);
-
-	if (endp->osmux.state == OSMUX_STATE_NEGOTIATING) {
-		sprintf(osmux_extension, "\nX-Osmux: %u", endp->osmux.cid);
-		endp->osmux.state = OSMUX_STATE_ACTIVATING;
-	} else {
-		osmux_extension[0] = '\0';
-	}
-
-	len = snprintf(sdp_record, sizeof(sdp_record),
-		       "I: %u%s\n\n", endp->ci, osmux_extension);
-	if (len < 0)
-		return NULL;
-
-	nchars = write_response_sdp(endp, sdp_record + len,
-				    sizeof(sdp_record) - len - 1, addr);
-	if (nchars < 0)
-		return NULL;
-
-	len += nchars;
-
-	sdp_record[sizeof(sdp_record) - 1] = '\0';
-
-	return create_resp(endp, 200, " OK", msg, trans_id, NULL, sdp_record);
-}
-
-static void send_dummy(struct mgcp_endpoint *endp)
-{
-	if (endp->osmux.state != OSMUX_STATE_DISABLED)
-		osmux_send_dummy(endp);
-	else
-		mgcp_send_dummy(endp);
-}
-
-/*
- * handle incoming messages:
- *   - this can be a command (four letters, space, transaction id)
- *   - or a response (three numbers, space, transaction id)
- */
-struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg)
-{
-	struct mgcp_parse_data pdata;
-	int i, code, handled = 0;
-	struct msgb *resp = NULL;
-	char *data;
-
-	if (msgb_l2len(msg) < 4) {
-		LOGP(DMGCP, LOGL_ERROR, "msg too short: %d\n", msg->len);
-		return NULL;
-	}
-
-	if (mgcp_msg_terminate_nul(msg))
-		return NULL;
-
-	display_mgcp_message(msg->l2h, msgb_l2len(msg), "Received message");
-
-        /* attempt to treat it as a response */
-        if (sscanf((const char *)&msg->l2h[0], "%3d %*s", &code) == 1) {
-		LOGP(DMGCP, LOGL_DEBUG, "Response: Code: %d\n", code);
-		return NULL;
-	}
-
-	msg->l3h = &msg->l2h[4];
-
-
-	/*
-	 * Check for a duplicate message and respond.
-	 */
-	memset(&pdata, 0, sizeof(pdata));
-	pdata.cfg = cfg;
-	data = strline_r((char *) msg->l3h, &pdata.save);
-	pdata.found = mgcp_analyze_header(&pdata, data);
-	if (pdata.endp && pdata.trans
-			&& pdata.endp->last_trans
-			&& strcmp(pdata.endp->last_trans, pdata.trans) == 0) {
-		return do_retransmission(pdata.endp);
-	}
-
-	for (i = 0; i < ARRAY_SIZE(mgcp_requests); ++i) {
-		if (strncmp(mgcp_requests[i].name, (const char *) &msg->l2h[0], 4) == 0) {
-			handled = 1;
-			resp = mgcp_requests[i].handle_request(&pdata);
-			break;
-		}
-	}
-
-	if (!handled)
-		LOGP(DMGCP, LOGL_NOTICE, "MSG with type: '%.4s' not handled\n", &msg->l2h[0]);
-
-	return resp;
-}
-
-/**
- * We have a null terminated string with the endpoint name here. We only
- * support two kinds. Simple ones as seen on the BSC level and the ones
- * seen on the trunk side.
- */
-static struct mgcp_endpoint *find_e1_endpoint(struct mgcp_config *cfg,
-					     const char *mgcp)
-{
-	char *rest = NULL;
-	struct mgcp_trunk_config *tcfg;
-	int trunk, endp;
-
-	trunk = strtoul(mgcp + 6, &rest, 10);
-	if (rest == NULL || rest[0] != '/' || trunk < 1) {
-		LOGP(DMGCP, LOGL_ERROR, "Wrong trunk name '%s'\n", mgcp);
-		return NULL;
-	}
-
-	endp = strtoul(rest + 1, &rest, 10);
-	if (rest == NULL || rest[0] != '@') {
-		LOGP(DMGCP, LOGL_ERROR, "Wrong endpoint name '%s'\n", mgcp);
-		return NULL;
-	}
-
-	/* signalling is on timeslot 1 */
-	if (endp == 1)
-		return NULL;
-
-	tcfg = mgcp_trunk_num(cfg, trunk);
-	if (!tcfg) {
-		LOGP(DMGCP, LOGL_ERROR, "The trunk %d is not declared.\n", trunk);
-		return NULL;
-	}
-
-	if (!tcfg->endpoints) {
-		LOGP(DMGCP, LOGL_ERROR, "Endpoints of trunk %d not allocated.\n", trunk);
-		return NULL;
-	}
-
-	if (endp < 1 || endp >= tcfg->number_endpoints) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to find endpoint '%s'\n", mgcp);
-		return NULL;
-	}
-
-	return &tcfg->endpoints[endp];
-}
-
-static struct mgcp_endpoint *find_endpoint(struct mgcp_config *cfg, const char *mgcp)
-{
-	char *endptr = NULL;
-	unsigned int gw = INT_MAX;
-
-	if (strncmp(mgcp, "ds/e1", 5) == 0)
-		return find_e1_endpoint(cfg, mgcp);
-
-	gw = strtoul(mgcp, &endptr, 16);
-	if (gw > 0 && gw < cfg->trunk.number_endpoints && endptr[0] == '@')
-		return &cfg->trunk.endpoints[gw];
-
-	LOGP(DMGCP, LOGL_ERROR, "Not able to find the endpoint: '%s'\n", mgcp);
-	return NULL;
-}
-
-/**
- * @returns 0 when the status line was complete and transaction_id and
- * endp out parameters are set.
- */
-static int mgcp_analyze_header(struct mgcp_parse_data *pdata, char *data)
-{
-	int i = 0;
-	char *elem, *save = NULL;
-
-	OSMO_ASSERT(data);
-	pdata->trans = "000000";
-
-	for (elem = strtok_r(data, " ", &save); elem;
-	     elem = strtok_r(NULL, " ", &save)) {
-		switch (i) {
-		case 0:
-			pdata->trans = elem;
-			break;
-		case 1:
-			pdata->endp = find_endpoint(pdata->cfg, elem);
-			if (!pdata->endp) {
-				LOGP(DMGCP, LOGL_ERROR,
-				     "Unable to find Endpoint `%s'\n", elem);
-				return -1;
-			}
-			break;
-		case 2:
-			if (strcmp("MGCP", elem)) {
-				LOGP(DMGCP, LOGL_ERROR,
-				     "MGCP header parsing error\n");
-				return -1;
-			}
-			break;
-		case 3:
-			if (strcmp("1.0", elem)) {
-				LOGP(DMGCP, LOGL_ERROR, "MGCP version `%s' "
-					"not supported\n", elem);
-				return -1;
-			}
-			break;
-		}
-		i++;
-	}
-
-	if (i != 4) {
-		LOGP(DMGCP, LOGL_ERROR, "MGCP status line too short.\n");
-		pdata->trans = "000000";
-		pdata->endp = NULL;
-		return -1;
-	}
-
-	return 0;
-}
-
-static int verify_call_id(const struct mgcp_endpoint *endp,
-			  const char *callid)
-{
-	if (strcmp(endp->callid, callid) != 0) {
-		LOGP(DMGCP, LOGL_ERROR, "CallIDs does not match on 0x%x. '%s' != '%s'\n",
-			ENDPOINT_NUMBER(endp), endp->callid, callid);
-		return -1;
-	}
-
-	return 0;
-}
-
-static int verify_ci(const struct mgcp_endpoint *endp,
-		     const char *_ci)
-{
-	uint32_t ci = strtoul(_ci, NULL, 10);
-
-	if (ci != endp->ci) {
-		LOGP(DMGCP, LOGL_ERROR, "ConnectionIdentifiers do not match on 0x%x. %u != %s\n",
-			ENDPOINT_NUMBER(endp), endp->ci, _ci);
-		return -1;
-	}
-
-	return 0;
-}
-
-static struct msgb *handle_audit_endpoint(struct mgcp_parse_data *p)
-{
-	if (p->found != 0)
-		return create_err_response(NULL, 500, "AUEP", p->trans);
-	else
-		return create_ok_response(p->endp, 200, "AUEP", p->trans);
-}
-
-static int parse_conn_mode(const char *msg, struct mgcp_endpoint *endp)
-{
-	int ret = 0;
-	if (strcmp(msg, "recvonly") == 0)
-		endp->conn_mode = MGCP_CONN_RECV_ONLY;
-	else if (strcmp(msg, "sendrecv") == 0)
-		endp->conn_mode = MGCP_CONN_RECV_SEND;
-	else if (strcmp(msg, "sendonly") == 0)
-		endp->conn_mode = MGCP_CONN_SEND_ONLY;
-	else if (strcmp(msg, "loopback") == 0)
-		endp->conn_mode = MGCP_CONN_LOOPBACK;
-	else {
-		LOGP(DMGCP, LOGL_ERROR, "Unknown connection mode: '%s'\n", msg);
-		ret = -1;
-	}
-
-	endp->net_end.output_enabled =
-		endp->conn_mode & MGCP_CONN_SEND_ONLY ? 1 : 0;
-	endp->bts_end.output_enabled =
-		endp->conn_mode & MGCP_CONN_RECV_ONLY ? 1 : 0;
-
-	LOGP(DMGCP, LOGL_DEBUG, "endpoint %x connection mode '%s' %d output_enabled net %d bts %d\n",
-	     ENDPOINT_NUMBER(endp),
-	     msg, endp->conn_mode, endp->net_end.output_enabled,
-	     endp->bts_end.output_enabled);
-
-	return ret;
-}
-
-static int allocate_port(struct mgcp_endpoint *endp, struct mgcp_rtp_end *end,
-			 struct mgcp_port_range *range,
-			 int (*alloc)(struct mgcp_endpoint *endp, int port))
-{
-	int i;
-
-	if (range->mode == PORT_ALLOC_STATIC) {
-		end->local_alloc = PORT_ALLOC_STATIC;
-		return 0;
-	}
-
-	/* attempt to find a port */
-	for (i = 0; i < 200; ++i) {
-		int rc;
-
-		if (range->last_port >= range->range_end)
-			range->last_port = range->range_start;
-
-		rc = alloc(endp, range->last_port);
-
-		range->last_port += 2;
-		if (rc == 0) {
-			end->local_alloc = PORT_ALLOC_DYNAMIC;
-			return 0;
-		}
-
-	}
-
-	LOGP(DMGCP, LOGL_ERROR, "Allocating a RTP/RTCP port failed 200 times 0x%x.\n",
-	     ENDPOINT_NUMBER(endp));
-	return -1;
-}
-
-static int allocate_ports(struct mgcp_endpoint *endp)
-{
-	if (allocate_port(endp, &endp->net_end, &endp->cfg->net_ports,
-			  mgcp_bind_net_rtp_port) != 0)
-		return -1;
-
-	if (allocate_port(endp, &endp->bts_end, &endp->cfg->bts_ports,
-			  mgcp_bind_bts_rtp_port) != 0) {
-		mgcp_rtp_end_reset(&endp->net_end);
-		return -1;
-	}
-
-	if (endp->cfg->transcoder_ip && endp->tcfg->trunk_type == MGCP_TRUNK_VIRTUAL) {
-		if (allocate_port(endp, &endp->trans_net,
-				  &endp->cfg->transcoder_ports,
-				  mgcp_bind_trans_net_rtp_port) != 0) {
-			mgcp_rtp_end_reset(&endp->net_end);
-			mgcp_rtp_end_reset(&endp->bts_end);
-			return -1;
-		}
-
-		if (allocate_port(endp, &endp->trans_bts,
-				  &endp->cfg->transcoder_ports,
-				  mgcp_bind_trans_bts_rtp_port) != 0) {
-			mgcp_rtp_end_reset(&endp->net_end);
-			mgcp_rtp_end_reset(&endp->bts_end);
-			mgcp_rtp_end_reset(&endp->trans_net);
-			return -1;
-		}
-
-		/* remember that we have set up transcoding */
-		endp->type = MGCP_RTP_TRANSCODED;
-	}
-
-	return 0;
-}
-
-/* Set the LCO from a string (see RFC 3435).
- * The string is stored in the 'string' field. A NULL string is handled excatly
- * like an empty string, the 'string' field is never NULL after this function
- * has been called. */
-static void set_local_cx_options(void *ctx, struct mgcp_lco *lco,
-				 const char *options)
-{
-	char *p_opt, *a_opt;
-	char codec[9];
-
-	talloc_free(lco->string);
-	talloc_free(lco->codec);
-	lco->codec = NULL;
-	lco->pkt_period_min = lco->pkt_period_max = 0;
-	lco->string = talloc_strdup(ctx, options ? options : "");
-
-	p_opt = strstr(lco->string, "p:");
-	if (p_opt && sscanf(p_opt, "p:%d-%d",
-			    &lco->pkt_period_min, &lco->pkt_period_max) == 1)
-		lco->pkt_period_max = lco->pkt_period_min;
-
-	a_opt = strstr(lco->string, "a:");
-	if (a_opt && sscanf(a_opt, "a:%8[^,]", codec) == 1)
-		lco->codec = talloc_strdup(ctx, codec);
-}
-
-void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
-			 struct mgcp_rtp_end *rtp)
-{
-	struct mgcp_trunk_config *tcfg = endp->tcfg;
-
-	int patch_ssrc = expect_ssrc_change && tcfg->force_constant_ssrc;
-
-	rtp->force_aligned_timing = tcfg->force_aligned_timing;
-	rtp->force_constant_ssrc = patch_ssrc ? 1 : 0;
-
-	LOGP(DMGCP, LOGL_DEBUG,
-	     "Configuring RTP endpoint: local port %d%s%s\n",
-	     ntohs(rtp->rtp_port),
-	     rtp->force_aligned_timing ? ", force constant timing" : "",
-	     rtp->force_constant_ssrc ? ", force constant ssrc" : "");
-}
-
-uint32_t mgcp_rtp_packet_duration(struct mgcp_endpoint *endp,
-				  struct mgcp_rtp_end *rtp)
-{
-	int f = 0;
-
-	/* Get the number of frames per channel and packet */
-	if (rtp->frames_per_packet)
-		f = rtp->frames_per_packet;
-	else if (rtp->packet_duration_ms && rtp->codec.frame_duration_num) {
-		int den = 1000 * rtp->codec.frame_duration_num;
-		f = (rtp->packet_duration_ms * rtp->codec.frame_duration_den + den/2)
-			/ den;
-	}
-
-	return rtp->codec.rate * f * rtp->codec.frame_duration_num / rtp->codec.frame_duration_den;
-}
-
-static int mgcp_parse_osmux_cid(const char *line)
-{
-	int osmux_cid;
-
-	if (sscanf(line + 2, "Osmux: %u", &osmux_cid) != 1)
-		return -1;
-
-	if (osmux_cid > OSMUX_CID_MAX) {
-		LOGP(DMGCP, LOGL_ERROR, "Osmux ID too large: %u > %u\n",
-		     osmux_cid, OSMUX_CID_MAX);
-		return -1;
-	}
-	LOGP(DMGCP, LOGL_DEBUG, "bsc-nat offered Osmux CID %u\n", osmux_cid);
-
-	return osmux_cid;
-}
-
-static int mgcp_osmux_setup(struct mgcp_endpoint *endp, const char *line)
-{
-	if (!endp->cfg->osmux_init) {
-		if (osmux_init(OSMUX_ROLE_BSC, endp->cfg) < 0) {
-			LOGP(DMGCP, LOGL_ERROR, "Cannot init OSMUX\n");
-			return -1;
-		}
-		LOGP(DMGCP, LOGL_NOTICE, "OSMUX socket has been set up\n");
-	}
-
-	return mgcp_parse_osmux_cid(line);
-}
-
-static struct msgb *handle_create_con(struct mgcp_parse_data *p)
-{
-	struct mgcp_trunk_config *tcfg;
-	struct mgcp_endpoint *endp = p->endp;
-	int error_code = 400;
-
-	const char *local_options = NULL;
-	const char *callid = NULL;
-	const char *mode = NULL;
-	char *line;
-	int have_sdp = 0, osmux_cid = -1;
-
-	if (p->found != 0)
-		return create_err_response(NULL, 510, "CRCX", p->trans);
-
-	/* parse CallID C: and LocalParameters L: */
-	for_each_line(line, p->save) {
-		if (!mgcp_check_param(endp, line))
-			continue;
-
-		switch (line[0]) {
-		case 'L':
-			local_options = (const char *) line + 3;
-			break;
-		case 'C':
-			callid = (const char *) line + 3;
-			break;
-		case 'M':
-			mode = (const char *) line + 3;
-			break;
-		case 'X':
-			/* Osmux is not enabled in this bsc, ignore it so the
-			 * bsc-nat knows that we don't want to use Osmux.
-			 */
-			if (!p->endp->cfg->osmux)
-				break;
-
-			if (strncmp("Osmux: ", line + 2, strlen("Osmux: ")) == 0)
-				osmux_cid = mgcp_osmux_setup(endp, line);
-			break;
-		case '\0':
-			have_sdp = 1;
-			goto mgcp_header_done;
-		default:
-			LOGP(DMGCP, LOGL_NOTICE, "Unhandled option: '%c'/%d on 0x%x\n",
-				*line, *line, ENDPOINT_NUMBER(endp));
-			break;
-		}
-	}
-
-mgcp_header_done:
-	tcfg = p->endp->tcfg;
-
-	/* Check required data */
-	if (!callid || !mode) {
-		LOGP(DMGCP, LOGL_ERROR, "Missing callid and mode in CRCX on 0x%x\n",
-		     ENDPOINT_NUMBER(endp));
-		return create_err_response(endp, 400, "CRCX", p->trans);
-	}
-
-	if (endp->allocated) {
-		if (tcfg->force_realloc) {
-			LOGP(DMGCP, LOGL_NOTICE, "Endpoint 0x%x already allocated. Forcing realloc.\n",
-			    ENDPOINT_NUMBER(endp));
-			mgcp_release_endp(endp);
-			if (p->cfg->realloc_cb)
-				p->cfg->realloc_cb(tcfg, ENDPOINT_NUMBER(endp));
-		} else {
-			LOGP(DMGCP, LOGL_ERROR, "Endpoint is already used. 0x%x\n",
-			     ENDPOINT_NUMBER(endp));
-			return create_err_response(endp, 400, "CRCX", p->trans);
-		}
-	}
-
-	/* copy some parameters */
-	endp->callid = talloc_strdup(tcfg->endpoints, callid);
-
-	set_local_cx_options(endp->tcfg->endpoints, &endp->local_options,
-			     local_options);
-
-	if (parse_conn_mode(mode, endp) != 0) {
-		    error_code = 517;
-		    goto error2;
-	}
-
-	/* initialize */
-	endp->net_end.rtp_port = endp->net_end.rtcp_port = endp->bts_end.rtp_port = endp->bts_end.rtcp_port = 0;
-	mgcp_rtp_end_config(endp, 0, &endp->net_end);
-	mgcp_rtp_end_config(endp, 0, &endp->bts_end);
-
-	/* set to zero until we get the info */
-	memset(&endp->net_end.addr, 0, sizeof(endp->net_end.addr));
-
-	/* bind to the port now */
-	if (allocate_ports(endp) != 0)
-		goto error2;
-
-	/* assign a local call identifier or fail */
-	endp->ci = generate_call_id(p->cfg);
-	if (endp->ci == CI_UNUSED)
-		goto error2;
-
-	/* Annotate Osmux circuit ID and set it to negotiating state until this
-	 * is fully set up from the dummy load.
-	 */
-	endp->osmux.state = OSMUX_STATE_DISABLED;
-	if (osmux_cid >= 0) {
-		endp->osmux.cid = osmux_cid;
-		endp->osmux.state = OSMUX_STATE_NEGOTIATING;
-	} else if (endp->cfg->osmux == OSMUX_USAGE_ONLY) {
-		LOGP(DMGCP, LOGL_ERROR,
-			"Osmux only and no osmux offered on 0x%x\n", ENDPOINT_NUMBER(endp));
-		goto error2;
-	}
-
-	endp->allocated = 1;
-
-	/* set up RTP media parameters */
-	mgcp_set_audio_info(p->cfg, &endp->bts_end.codec, tcfg->audio_payload, tcfg->audio_name);
-	endp->bts_end.fmtp_extra = talloc_strdup(tcfg->endpoints,
-						tcfg->audio_fmtp_extra);
-	if (have_sdp)
-		mgcp_parse_sdp_data(endp, &endp->net_end, p);
-	else if (endp->local_options.codec)
-		mgcp_set_audio_info(p->cfg, &endp->net_end.codec,
-			       PTYPE_UNDEFINED, endp->local_options.codec);
-
-	if (p->cfg->bts_force_ptime) {
-		endp->bts_end.packet_duration_ms = p->cfg->bts_force_ptime;
-		endp->bts_end.force_output_ptime = 1;
-	}
-
-	if (setup_rtp_processing(endp) != 0)
-		goto error2;
-
-	/* policy CB */
-	if (p->cfg->policy_cb) {
-		int rc;
-		rc = p->cfg->policy_cb(tcfg, ENDPOINT_NUMBER(endp),
-				MGCP_ENDP_CRCX, p->trans);
-		switch (rc) {
-		case MGCP_POLICY_REJECT:
-			LOGP(DMGCP, LOGL_NOTICE, "CRCX rejected by policy on 0x%x\n",
-			     ENDPOINT_NUMBER(endp));
-			mgcp_release_endp(endp);
-			return create_err_response(endp, 400, "CRCX", p->trans);
-			break;
-		case MGCP_POLICY_DEFER:
-			/* stop processing */
-			create_transcoder(endp);
-			return NULL;
-			break;
-		case MGCP_POLICY_CONT:
-			/* just continue */
-			break;
-		}
-	}
-
-	LOGP(DMGCP, LOGL_DEBUG, "Creating endpoint on: 0x%x CI: %u port: %u/%u\n",
-		ENDPOINT_NUMBER(endp), endp->ci,
-		endp->net_end.local_port, endp->bts_end.local_port);
-	if (p->cfg->change_cb)
-		p->cfg->change_cb(tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_CRCX);
-
-	if (endp->conn_mode & MGCP_CONN_RECV_ONLY && tcfg->keepalive_interval != 0) {
-		send_dummy(endp);
-	}
-
-	create_transcoder(endp);
-	return create_response_with_sdp(endp, "CRCX", p->trans);
-error2:
-	mgcp_release_endp(endp);
-	LOGP(DMGCP, LOGL_NOTICE, "Resource error on 0x%x\n", ENDPOINT_NUMBER(endp));
-	return create_err_response(endp, error_code, "CRCX", p->trans);
-}
-
-static struct msgb *handle_modify_con(struct mgcp_parse_data *p)
-{
-	struct mgcp_endpoint *endp = p->endp;
-	int error_code = 500;
-	int silent = 0;
-	int have_sdp = 0;
-	char *line;
-	const char *local_options = NULL;
-
-	if (p->found != 0)
-		return create_err_response(NULL, 510, "MDCX", p->trans);
-
-	if (endp->ci == CI_UNUSED) {
-		LOGP(DMGCP, LOGL_ERROR, "Endpoint is not "
-			"holding a connection. 0x%x\n", ENDPOINT_NUMBER(endp));
-		return create_err_response(endp, 400, "MDCX", p->trans);
-	}
-
-	for_each_line(line, p->save) {
-		if (!mgcp_check_param(endp, line))
-			continue;
-
-		switch (line[0]) {
-		case 'C': {
-			if (verify_call_id(endp, line + 3) != 0)
-				goto error3;
-			break;
-		}
-		case 'I': {
-			if (verify_ci(endp, line + 3) != 0)
-				goto error3;
-			break;
-		}
-		case 'L':
-			local_options = (const char *) line + 3;
-			break;
-		case 'M':
-			if (parse_conn_mode(line + 3, endp) != 0) {
-			    error_code = 517;
-			    goto error3;
-			}
-			endp->orig_mode = endp->conn_mode;
-			break;
-		case 'Z':
-			silent = strcmp("noanswer", line + 3) == 0;
-			break;
-		case '\0':
-			/* SDP file begins */
-			have_sdp = 1;
-			mgcp_parse_sdp_data(endp, &endp->net_end, p);
-			/* This will exhaust p->save, so the loop will
-			 * terminate next time.
-			 */
-			break;
-		default:
-			LOGP(DMGCP, LOGL_NOTICE, "Unhandled MGCP option: '%c'/%d on 0x%x\n",
-				line[0], line[0], ENDPOINT_NUMBER(endp));
-			break;
-		}
-	}
-
-	set_local_cx_options(endp->tcfg->endpoints, &endp->local_options,
-			     local_options);
-
-	if (!have_sdp && endp->local_options.codec)
-		mgcp_set_audio_info(p->cfg, &endp->net_end.codec,
-			       PTYPE_UNDEFINED, endp->local_options.codec);
-
-	if (setup_rtp_processing(endp) != 0)
-		goto error3;
-
-	/* policy CB */
-	if (p->cfg->policy_cb) {
-		int rc;
-		rc = p->cfg->policy_cb(endp->tcfg, ENDPOINT_NUMBER(endp),
-						MGCP_ENDP_MDCX, p->trans);
-		switch (rc) {
-		case MGCP_POLICY_REJECT:
-			LOGP(DMGCP, LOGL_NOTICE, "MDCX rejected by policy on 0x%x\n",
-			     ENDPOINT_NUMBER(endp));
-			if (silent)
-				goto out_silent;
-			return create_err_response(endp, 400, "MDCX", p->trans);
-			break;
-		case MGCP_POLICY_DEFER:
-			/* stop processing */
-			LOGP(DMGCP, LOGL_DEBUG, "endp %x MDCX defer\n",
-			     ENDPOINT_NUMBER(endp));
-			return NULL;
-			break;
-		case MGCP_POLICY_CONT:
-			/* just continue */
-			break;
-		}
-	}
-
-	mgcp_rtp_end_config(endp, 1, &endp->net_end);
-	mgcp_rtp_end_config(endp, 1, &endp->bts_end);
-
-	/* modify */
-	LOGP(DMGCP, LOGL_DEBUG, "Modified endpoint on: 0x%x Server: %s:%u\n",
-		ENDPOINT_NUMBER(endp), inet_ntoa(endp->net_end.addr), ntohs(endp->net_end.rtp_port));
-	if (p->cfg->change_cb)
-		p->cfg->change_cb(endp->tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_MDCX);
-
-	if (endp->conn_mode & MGCP_CONN_RECV_ONLY &&
-	    endp->tcfg->keepalive_interval != 0)
-		send_dummy(endp);
-
-	if (silent)
-		goto out_silent;
-
-	return create_response_with_sdp(endp, "MDCX", p->trans);
-
-error3:
-	return create_err_response(endp, error_code, "MDCX", p->trans);
-
-
-out_silent:
-	LOGP(DMGCP, LOGL_DEBUG, "endp %x Modify endpoint: silent exit\n",
-	     ENDPOINT_NUMBER(endp));
-	return NULL;
-}
-
-static struct msgb *handle_delete_con(struct mgcp_parse_data *p)
-{
-	struct mgcp_endpoint *endp = p->endp;
-	int error_code = 400;
-	int silent = 0;
-	char *line;
-	char stats[1048];
-
-	if (p->found != 0)
-		return create_err_response(NULL, error_code, "DLCX", p->trans);
-
-	if (!p->endp->allocated) {
-		LOGP(DMGCP, LOGL_ERROR, "Endpoint is not used. 0x%x\n",
-			ENDPOINT_NUMBER(endp));
-		return create_err_response(endp, 400, "DLCX", p->trans);
-	}
-
-	for_each_line(line, p->save) {
-		if (!mgcp_check_param(endp, line))
-			continue;
-
-		switch (line[0]) {
-		case 'C':
-			if (verify_call_id(endp, line + 3) != 0)
-				goto error3;
-			break;
-		case 'I':
-			if (verify_ci(endp, line + 3) != 0)
-				goto error3;
-			break;
-		case 'Z':
-			silent = strcmp("noanswer", line + 3) == 0;
-			break;
-		default:
-			LOGP(DMGCP, LOGL_NOTICE, "Unhandled option: '%c'/%d on 0x%x\n",
-				line[0], line[0], ENDPOINT_NUMBER(endp));
-			break;
-		}
-	}
-
-	/* policy CB */
-	if (p->cfg->policy_cb) {
-		int rc;
-		rc = p->cfg->policy_cb(endp->tcfg, ENDPOINT_NUMBER(endp),
-						MGCP_ENDP_DLCX, p->trans);
-		switch (rc) {
-		case MGCP_POLICY_REJECT:
-			LOGP(DMGCP, LOGL_NOTICE, "DLCX rejected by policy on 0x%x\n",
-			     ENDPOINT_NUMBER(endp));
-			if (silent)
-				goto out_silent;
-			return create_err_response(endp, 400, "DLCX", p->trans);
-			break;
-		case MGCP_POLICY_DEFER:
-			/* stop processing */
-			delete_transcoder(endp);
-			return NULL;
-			break;
-		case MGCP_POLICY_CONT:
-			/* just continue */
-			break;
-		}
-	}
-
-	/* free the connection */
-	LOGP(DMGCP, LOGL_DEBUG, "Deleted endpoint on: 0x%x Server: %s:%u\n",
-		ENDPOINT_NUMBER(endp), inet_ntoa(endp->net_end.addr), ntohs(endp->net_end.rtp_port));
-
-	/* save the statistics of the current call */
-	mgcp_format_stats(endp, stats, sizeof(stats));
-
-	delete_transcoder(endp);
-	mgcp_release_endp(endp);
-	if (p->cfg->change_cb)
-		p->cfg->change_cb(endp->tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_DLCX);
-
-	if (silent)
-		goto out_silent;
-	return create_ok_resp_with_param(endp, 250, "DLCX", p->trans, stats);
-
-error3:
-	return create_err_response(endp, error_code, "DLCX", p->trans);
-
-out_silent:
-	return NULL;
-}
-
-static struct msgb *handle_rsip(struct mgcp_parse_data *p)
-{
-	if (p->found != 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to find the endpoint.\n");
-		return NULL;
-	}
-
-	if (p->cfg->reset_cb)
-		p->cfg->reset_cb(p->endp->tcfg);
-	return NULL;
-}
-
-static char extract_tone(const char *line)
-{
-	const char *str = strstr(line, "D/");
-	if (!str)
-		return CHAR_MAX;
-
-	return str[2];
-}
-
-/*
- * This can request like DTMF detection and forward, fax detection... it
- * can also request when the notification should be send and such. We don't
- * do this right now.
- */
-static struct msgb *handle_noti_req(struct mgcp_parse_data *p)
-{
-	int res = 0;
-	char *line;
-	char tone = CHAR_MAX;
-
-	if (p->found != 0)
-		return create_err_response(NULL, 400, "RQNT", p->trans);
-
-	for_each_line(line, p->save) {
-		switch (line[0]) {
-		case 'S':
-			tone = extract_tone(line);
-			break;
-		}
-	}
-
-	/* we didn't see a signal request with a tone */
-	if (tone == CHAR_MAX)
-		return create_ok_response(p->endp, 200, "RQNT", p->trans);
-
-	if (p->cfg->rqnt_cb)
-		res = p->cfg->rqnt_cb(p->endp, tone);
-
-	return res == 0 ?
-		create_ok_response(p->endp, 200, "RQNT", p->trans) :
-		create_err_response(p->endp, res, "RQNT", p->trans);
-}
-
-static void mgcp_keepalive_timer_cb(void *_tcfg)
-{
-	struct mgcp_trunk_config *tcfg = _tcfg;
-	int i;
-	LOGP(DMGCP, LOGL_DEBUG, "Triggered trunk %d keepalive timer.\n",
-	     tcfg->trunk_nr);
-
-	if (tcfg->keepalive_interval <= 0)
-		return;
-
-	for (i = 1; i < tcfg->number_endpoints; ++i) {
-		struct mgcp_endpoint *endp = &tcfg->endpoints[i];
-		if (endp->conn_mode == MGCP_CONN_RECV_ONLY)
-			send_dummy(endp);
-	}
-
-	LOGP(DMGCP, LOGL_DEBUG, "Rescheduling trunk %d keepalive timer.\n",
-	     tcfg->trunk_nr);
-	osmo_timer_schedule(&tcfg->keepalive_timer, tcfg->keepalive_interval, 0);
-}
-
-void mgcp_trunk_set_keepalive(struct mgcp_trunk_config *tcfg, int interval)
-{
-	tcfg->keepalive_interval = interval;
-	osmo_timer_setup(&tcfg->keepalive_timer, mgcp_keepalive_timer_cb, tcfg);
-
-	if (interval <= 0)
-		osmo_timer_del(&tcfg->keepalive_timer);
-	else
-		osmo_timer_schedule(&tcfg->keepalive_timer,
-				    tcfg->keepalive_interval, 0);
-}
-
-struct mgcp_config *mgcp_config_alloc(void)
-{
-	struct mgcp_config *cfg;
-
-	cfg = talloc_zero(NULL, struct mgcp_config);
-	if (!cfg) {
-		LOGP(DMGCP, LOGL_FATAL, "Failed to allocate config.\n");
-		return NULL;
-	}
-
-	cfg->source_port = 2427;
-	cfg->source_addr = talloc_strdup(cfg, "0.0.0.0");
-	cfg->osmux_addr = talloc_strdup(cfg, "0.0.0.0");
-
-	cfg->transcoder_remote_base = 4000;
-
-	cfg->bts_ports.base_port = RTP_PORT_DEFAULT;
-	cfg->net_ports.base_port = RTP_PORT_NET_DEFAULT;
-
-	cfg->rtp_processing_cb = &mgcp_rtp_processing_default;
-	cfg->setup_rtp_processing_cb = &mgcp_setup_rtp_processing_default;
-
-	cfg->get_net_downlink_format_cb = &mgcp_get_net_downlink_format_default;
-
-	/* default trunk handling */
-	cfg->trunk.cfg = cfg;
-	cfg->trunk.trunk_nr = 0;
-	cfg->trunk.trunk_type = MGCP_TRUNK_VIRTUAL;
-	cfg->trunk.audio_name = talloc_strdup(cfg, "AMR/8000");
-	cfg->trunk.audio_payload = 126;
-	cfg->trunk.audio_send_ptime = 1;
-	cfg->trunk.audio_send_name = 1;
-	cfg->trunk.omit_rtcp = 0;
-	mgcp_trunk_set_keepalive(&cfg->trunk, MGCP_KEEPALIVE_ONCE);
-
-	INIT_LLIST_HEAD(&cfg->trunks);
-
-	return cfg;
-}
-
-struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int nr)
-{
-	struct mgcp_trunk_config *trunk;
-
-	trunk = talloc_zero(cfg, struct mgcp_trunk_config);
-	if (!trunk) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to allocate.\n");
-		return NULL;
-	}
-
-	trunk->cfg = cfg;
-	trunk->trunk_type = MGCP_TRUNK_E1;
-	trunk->trunk_nr = nr;
-	trunk->audio_name = talloc_strdup(cfg, "AMR/8000");
-	trunk->audio_payload = 126;
-	trunk->audio_send_ptime = 1;
-	trunk->audio_send_name = 1;
-	trunk->number_endpoints = 33;
-	trunk->omit_rtcp = 0;
-	mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
-	llist_add_tail(&trunk->entry, &cfg->trunks);
-	return trunk;
-}
-
-struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index)
-{
-	struct mgcp_trunk_config *trunk;
-
-	llist_for_each_entry(trunk, &cfg->trunks, entry)
-		if (trunk->trunk_nr == index)
-			return trunk;
-
-	return NULL;
-}
-
-static void mgcp_rtp_codec_reset(struct mgcp_rtp_codec *codec)
-{
-	codec->payload_type = -1;
-	talloc_free(codec->subtype_name);
-	codec->subtype_name = NULL;
-	talloc_free(codec->audio_name);
-	codec->audio_name = NULL;
-	codec->frame_duration_num = DEFAULT_RTP_AUDIO_FRAME_DUR_NUM;
-	codec->frame_duration_den = DEFAULT_RTP_AUDIO_FRAME_DUR_DEN;
-	codec->rate               = DEFAULT_RTP_AUDIO_DEFAULT_RATE;
-	codec->channels           = DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS;
-}
-
-static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end)
-{
-	if (end->local_alloc == PORT_ALLOC_DYNAMIC) {
-		mgcp_free_rtp_port(end);
-		end->local_port = 0;
-	}
-
-	end->packets = 0;
-	end->octets = 0;
-	end->dropped_packets = 0;
-	memset(&end->addr, 0, sizeof(end->addr));
-	end->rtp_port = end->rtcp_port = 0;
-	end->local_alloc = -1;
-	talloc_free(end->fmtp_extra);
-	end->fmtp_extra = NULL;
-	talloc_free(end->rtp_process_data);
-	end->rtp_process_data = NULL;
-
-	/* Set default values */
-	end->frames_per_packet  = 0; /* unknown */
-	end->packet_duration_ms = DEFAULT_RTP_AUDIO_PACKET_DURATION_MS;
-	end->output_enabled	= 0;
-
-	mgcp_rtp_codec_reset(&end->codec);
-	mgcp_rtp_codec_reset(&end->alt_codec);
-}
-
-static void mgcp_rtp_end_init(struct mgcp_rtp_end *end)
-{
-	mgcp_rtp_end_reset(end);
-	end->rtp.fd = -1;
-	end->rtcp.fd = -1;
-}
-
-int mgcp_endpoints_allocate(struct mgcp_trunk_config *tcfg)
-{
-	int i;
-
-	/* Initialize all endpoints */
-	tcfg->endpoints = _talloc_zero_array(tcfg->cfg,
-				       sizeof(struct mgcp_endpoint),
-				       tcfg->number_endpoints, "endpoints");
-	if (!tcfg->endpoints)
-		return -1;
-
-	for (i = 0; i < tcfg->number_endpoints; ++i) {
-		tcfg->endpoints[i].osmux.allocated_cid = -1;
-		tcfg->endpoints[i].ci = CI_UNUSED;
-		tcfg->endpoints[i].cfg = tcfg->cfg;
-		tcfg->endpoints[i].tcfg = tcfg;
-		mgcp_rtp_end_init(&tcfg->endpoints[i].net_end);
-		mgcp_rtp_end_init(&tcfg->endpoints[i].bts_end);
-		mgcp_rtp_end_init(&tcfg->endpoints[i].trans_net);
-		mgcp_rtp_end_init(&tcfg->endpoints[i].trans_bts);
-	}
-
-	return 0;
-}
-
-void mgcp_release_endp(struct mgcp_endpoint *endp)
-{
-	LOGP(DMGCP, LOGL_DEBUG, "Releasing endpoint on: 0x%x\n", ENDPOINT_NUMBER(endp));
-	endp->ci = CI_UNUSED;
-	endp->allocated = 0;
-
-	talloc_free(endp->callid);
-	endp->callid = NULL;
-
-	talloc_free(endp->local_options.string);
-	endp->local_options.string = NULL;
-	talloc_free(endp->local_options.codec);
-	endp->local_options.codec = NULL;
-
-	mgcp_rtp_end_reset(&endp->bts_end);
-	mgcp_rtp_end_reset(&endp->net_end);
-	mgcp_rtp_end_reset(&endp->trans_net);
-	mgcp_rtp_end_reset(&endp->trans_bts);
-	endp->type = MGCP_RTP_DEFAULT;
-
-	memset(&endp->net_state, 0, sizeof(endp->net_state));
-	memset(&endp->bts_state, 0, sizeof(endp->bts_state));
-
-	endp->conn_mode = endp->orig_mode = MGCP_CONN_NONE;
-
-	if (endp->osmux.state == OSMUX_STATE_ENABLED)
-		osmux_disable_endpoint(endp);
-
-	/* release the circuit ID if it had been allocated */
-	osmux_release_cid(endp);
-
-	memset(&endp->taps, 0, sizeof(endp->taps));
-}
-
-void mgcp_initialize_endp(struct mgcp_endpoint *endp)
-{
-	return mgcp_release_endp(endp);
-}
-
-static int send_trans(struct mgcp_config *cfg, const char *buf, int len)
-{
-	struct sockaddr_in addr;
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sin_family = AF_INET;
-	addr.sin_addr = cfg->transcoder_in;
-	addr.sin_port = htons(2427);
-	return sendto(cfg->gw_fd.bfd.fd, buf, len, 0,
-		      (struct sockaddr *) &addr, sizeof(addr));
-}
-
-static void send_msg(struct mgcp_endpoint *endp, int endpoint, int port,
-		     const char *msg, const char *mode)
-{
-	char buf[2096];
-	int len;
-	int nchars;
-
-	/* hardcoded to AMR right now, we do not know the real type at this point */
-	len = snprintf(buf, sizeof(buf),
-			"%s 42 %x@mgw MGCP 1.0\r\n"
-			"C: 4256\r\n"
-			"M: %s\r\n"
-			"\r\n",
-			msg, endpoint, mode);
-
-	if (len < 0)
-		return;
-
-	nchars = write_response_sdp(endp, buf + len, sizeof(buf) + len - 1, NULL);
-	if (nchars < 0)
-		return;
-
-	len += nchars;
-
-	buf[sizeof(buf) - 1] = '\0';
-
-	send_trans(endp->cfg, buf, len);
-}
-
-static void send_dlcx(struct mgcp_endpoint *endp, int endpoint)
-{
-	char buf[2096];
-	int len;
-
-	len = snprintf(buf, sizeof(buf),
-			"DLCX 43 %x@mgw MGCP 1.0\r\n"
-			"C: 4256\r\n"
-			, endpoint);
-
-	if (len < 0)
-		return;
-
-	buf[sizeof(buf) - 1] = '\0';
-
-	send_trans(endp->cfg, buf, len);
-}
-
-static int send_agent(struct mgcp_config *cfg, const char *buf, int len)
-{
-	return write(cfg->gw_fd.bfd.fd, buf, len);
-}
-
-int mgcp_send_reset_all(struct mgcp_config *cfg)
-{
-	static const char mgcp_reset[] = {
-	    "RSIP 1 *@mgw MGCP 1.0\r\n"
-	};
-
-	return send_agent(cfg, mgcp_reset, sizeof mgcp_reset -1);
-}
-
-int mgcp_send_reset_ep(struct mgcp_endpoint *endp, int endpoint)
-{
-	char buf[128];
-	int len;
-
-	len = snprintf(buf, sizeof(buf),
-			"RSIP 39 %x@mgw MGCP 1.0\r\n"
-			, endpoint);
-	if (len < 0)
-		return len;
-
-	buf[sizeof(buf) - 1] = '\0';
-
-	return send_agent(endp->cfg, buf, len);
-}
-
-static int setup_rtp_processing(struct mgcp_endpoint *endp)
-{
-	int rc = 0;
-	struct mgcp_config *cfg = endp->cfg;
-
-	if (endp->type != MGCP_RTP_DEFAULT)
-		return 0;
-
-	if (endp->conn_mode == MGCP_CONN_LOOPBACK)
-		return 0;
-
-	if (endp->conn_mode & MGCP_CONN_SEND_ONLY)
-		rc |= cfg->setup_rtp_processing_cb(endp, &endp->net_end, &endp->bts_end);
-	else
-		rc |= cfg->setup_rtp_processing_cb(endp, &endp->net_end, NULL);
-
-	if (endp->conn_mode & MGCP_CONN_RECV_ONLY)
-		rc |= cfg->setup_rtp_processing_cb(endp, &endp->bts_end, &endp->net_end);
-	else
-		rc |= cfg->setup_rtp_processing_cb(endp, &endp->bts_end, NULL);
-	return rc;
-}
-
-static void create_transcoder(struct mgcp_endpoint *endp)
-{
-	int port;
-	int in_endp = ENDPOINT_NUMBER(endp);
-	int out_endp = endp_back_channel(in_endp);
-
-	if (endp->type != MGCP_RTP_TRANSCODED)
-		return;
-
-	send_msg(endp, in_endp, endp->trans_bts.local_port, "CRCX", "sendrecv");
-	send_msg(endp, in_endp, endp->trans_bts.local_port, "MDCX", "sendrecv");
-	send_msg(endp, out_endp, endp->trans_net.local_port, "CRCX", "sendrecv");
-	send_msg(endp, out_endp, endp->trans_net.local_port, "MDCX", "sendrecv");
-
-	port = rtp_calculate_port(in_endp, endp->cfg->transcoder_remote_base);
-	endp->trans_bts.rtp_port = htons(port);
-	endp->trans_bts.rtcp_port = htons(port + 1);
-
-	port = rtp_calculate_port(out_endp, endp->cfg->transcoder_remote_base);
-	endp->trans_net.rtp_port = htons(port);
-	endp->trans_net.rtcp_port = htons(port + 1);
-}
-
-static void delete_transcoder(struct mgcp_endpoint *endp)
-{
-	int in_endp = ENDPOINT_NUMBER(endp);
-	int out_endp = endp_back_channel(in_endp);
-
-	if (endp->type != MGCP_RTP_TRANSCODED)
-		return;
-
-	send_dlcx(endp, in_endp);
-	send_dlcx(endp, out_endp);
-}
-
-int mgcp_reset_transcoder(struct mgcp_config *cfg)
-{
-	if (!cfg->transcoder_ip)
-		return 0;
-
-	static const char mgcp_reset[] = {
-	    "RSIP 1 13@mgw MGCP 1.0\r\n"
-	};
-
-	return send_trans(cfg, mgcp_reset, sizeof mgcp_reset -1);
-}
-
-void mgcp_format_stats(struct mgcp_endpoint *endp, char *msg, size_t size)
-{
-	uint32_t expected, jitter;
-	int ploss;
-	int nchars;
-	mgcp_state_calc_loss(&endp->net_state, &endp->net_end,
-				&expected, &ploss);
-	jitter = mgcp_state_calc_jitter(&endp->net_state);
-
-	nchars = snprintf(msg, size,
-			  "\r\nP: PS=%u, OS=%u, PR=%u, OR=%u, PL=%d, JI=%u",
-			  endp->bts_end.packets, endp->bts_end.octets,
-			  endp->net_end.packets, endp->net_end.octets,
-			  ploss, jitter);
-	if (nchars < 0 || nchars >= size)
-		goto truncate;
-
-	msg += nchars;
-	size -= nchars;
-
-	/* Error Counter */
-	nchars = snprintf(msg, size,
-			  "\r\nX-Osmo-CP: EC TIS=%u, TOS=%u, TIR=%u, TOR=%u",
-			  endp->net_state.in_stream.err_ts_counter,
-			  endp->net_state.out_stream.err_ts_counter,
-			  endp->bts_state.in_stream.err_ts_counter,
-			  endp->bts_state.out_stream.err_ts_counter);
-	if (nchars < 0 || nchars >= size)
-		goto truncate;
-
-	msg += nchars;
-	size -= nchars;
-
-	if (endp->osmux.state == OSMUX_STATE_ENABLED) {
-		snprintf(msg, size,
-			 "\r\nX-Osmux-ST: CR=%u, BR=%u",
-			 endp->osmux.stats.chunks,
-			 endp->osmux.stats.octets);
-	}
-truncate:
-	msg[size - 1] = '\0';
-}
-
-int mgcp_parse_stats(struct msgb *msg, uint32_t *ps, uint32_t *os,
-		uint32_t *pr, uint32_t *_or, int *loss, uint32_t *jitter)
-{
-	char *line, *save;
-	int rc;
-
-	/* initialize with bad values */
-	*ps = *os = *pr = *_or = *jitter = UINT_MAX;
-	*loss = INT_MAX;
-
-
-	line = strtok_r((char *) msg->l2h, "\r\n", &save);
-	if (!line)
-		return -1;
-
-	/* this can only parse the message that is created above... */
-	for_each_non_empty_line(line, save) {
-		switch (line[0]) {
-		case 'P':
-			rc = sscanf(line, "P: PS=%u, OS=%u, PR=%u, OR=%u, PL=%d, JI=%u",
-					ps, os, pr, _or, loss, jitter);
-			return rc == 6 ? 0 : -1;
-		}
-	}
-
-	return -1;
-}
diff --git a/src/libmgcp/mgcp_sdp.c b/src/libmgcp/mgcp_sdp.c
deleted file mode 100644
index b648944..0000000
--- a/src/libmgcp/mgcp_sdp.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Some SDP file parsing...
- *
- * (C) 2009-2015 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2014 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/>.
- *
- */
-
-#include <openbsc/mgcp.h>
-#include <openbsc/mgcp_internal.h>
-
-#include <errno.h>
-
-struct sdp_rtp_map {
-	/* the type */
-	int payload_type;
-	/* null, static or later dynamic codec name */
-	char *codec_name;
-	/* A pointer to the original line for later parsing */
-	char *map_line;
-
-	int rate;
-	int channels;
-};
-
-int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
-			int payload_type, const char *audio_name)
-{
-	int rate = codec->rate;
-	int channels = codec->channels;
-	char audio_codec[64];
-
-	talloc_free(codec->subtype_name);
-	codec->subtype_name = NULL;
-	talloc_free(codec->audio_name);
-	codec->audio_name = NULL;
-
-	if (payload_type != PTYPE_UNDEFINED)
-		codec->payload_type = payload_type;
-
-	if (!audio_name) {
-		switch (payload_type) {
-		case 0: audio_name = "PCMU/8000/1"; break;
-		case 3: audio_name = "GSM/8000/1"; break;
-		case 8: audio_name = "PCMA/8000/1"; break;
-		case 18: audio_name = "G729/8000/1"; break;
-		default:
-			 /* Payload type is unknown, don't change rate and
-			  * channels. */
-			 /* TODO: return value? */
-			 return 0;
-		}
-	}
-
-	if (sscanf(audio_name, "%63[^/]/%d/%d",
-		   audio_codec, &rate, &channels) < 1)
-		return -EINVAL;
-
-	codec->rate = rate;
-	codec->channels = channels;
-	codec->subtype_name = talloc_strdup(ctx, audio_codec);
-	codec->audio_name = talloc_strdup(ctx, audio_name);
-
-	if (!strcmp(audio_codec, "G729")) {
-		codec->frame_duration_num = 10;
-		codec->frame_duration_den = 1000;
-	} else {
-		codec->frame_duration_num = DEFAULT_RTP_AUDIO_FRAME_DUR_NUM;
-		codec->frame_duration_den = DEFAULT_RTP_AUDIO_FRAME_DUR_DEN;
-	}
-
-	if (payload_type < 0) {
-		payload_type = 96;
-		if (rate == 8000 && channels == 1) {
-			if (!strcmp(audio_codec, "GSM"))
-				payload_type = 3;
-			else if (!strcmp(audio_codec, "PCMA"))
-				payload_type = 8;
-			else if (!strcmp(audio_codec, "PCMU"))
-				payload_type = 0;
-			else if (!strcmp(audio_codec, "G729"))
-				payload_type = 18;
-		}
-
-		codec->payload_type = payload_type;
-	}
-
-	if (channels != 1)
-		LOGP(DMGCP, LOGL_NOTICE,
-		     "Channels != 1 in SDP: '%s'\n", audio_name);
-
-	return 0;
-}
-
-void codecs_initialize(void *ctx, struct sdp_rtp_map *codecs, int used)
-{
-	int i;
-
-	for (i = 0; i < used; ++i) {
-		switch (codecs[i].payload_type) {
-		case 0:
-			codecs[i].codec_name = "PCMU";
-			codecs[i].rate = 8000;
-			codecs[i].channels = 1;
-			break;
-		case 3:
-			codecs[i].codec_name = "GSM";
-			codecs[i].rate = 8000;
-			codecs[i].channels = 1;
-			break;
-		case 8:
-			codecs[i].codec_name = "PCMA";
-			codecs[i].rate = 8000;
-			codecs[i].channels = 1;
-			break;
-		case 18:
-			codecs[i].codec_name = "G729";
-			codecs[i].rate = 8000;
-			codecs[i].channels = 1;
-			break;
-		}
-	}
-}
-
-void codecs_update(void *ctx, struct sdp_rtp_map *codecs, int used, int payload, char *audio_name)
-{
-	int i;
-
-	for (i = 0; i < used; ++i) {
-		char audio_codec[64];
-		int rate = -1;
-		int channels = -1;
-		if (codecs[i].payload_type != payload)
-			continue;
-		if (sscanf(audio_name, "%63[^/]/%d/%d",
-				audio_codec, &rate, &channels) < 1) {
-			LOGP(DMGCP, LOGL_ERROR, "Failed to parse '%s'\n", audio_name);
-			continue;
-		}
-
-		codecs[i].map_line = talloc_strdup(ctx, audio_name);
-		codecs[i].codec_name = talloc_strdup(ctx, audio_codec);
-		codecs[i].rate = rate;
-		codecs[i].channels = channels;
-		return;
-	}
-
-	LOGP(DMGCP, LOGL_ERROR, "Unconfigured PT(%d) with %s\n", payload, audio_name);
-}
-
-int is_codec_compatible(struct mgcp_endpoint *endp, struct sdp_rtp_map *codec)
-{
-	char *bts_codec;
-	char audio_codec[64];
-
-	if (!codec->codec_name)
-		return 0;
-
-	/*
-	 * GSM, GSM/8000 and GSM/8000/1 should all be compatible.. let's go
-	 * by name first.
-	 */
-	bts_codec = endp->tcfg->audio_name;
-	if (sscanf(bts_codec, "%63[^/]/%*d/%*d", audio_codec) < 1)
-		return 0;
-
-	return strcasecmp(audio_codec, codec->codec_name) == 0;
-}
-
-int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p)
-{
-	struct sdp_rtp_map codecs[10];
-	int codecs_used = 0;
-	char *line;
-	int maxptime = -1;
-	int i;
-	int codecs_assigned = 0;
-	void *tmp_ctx = talloc_new(NULL);
-
-	memset(&codecs, 0, sizeof(codecs));
-
-	for_each_line(line, p->save) {
-		switch (line[0]) {
-		case 'o':
-		case 's':
-		case 't':
-		case 'v':
-			/* skip these SDP attributes */
-			break;
-		case 'a': {
-			int payload;
-			int ptime, ptime2 = 0;
-			char audio_name[64];
-
-
-			if (sscanf(line, "a=rtpmap:%d %63s",
-				   &payload, audio_name) == 2) {
-				codecs_update(tmp_ctx, codecs, codecs_used, payload, audio_name);
-			} else if (sscanf(line, "a=ptime:%d-%d",
-					  &ptime, &ptime2) >= 1) {
-				if (ptime2 > 0 && ptime2 != ptime)
-					rtp->packet_duration_ms = 0;
-				else
-					rtp->packet_duration_ms = ptime;
-			} else if (sscanf(line, "a=maxptime:%d", &ptime2) == 1) {
-				maxptime = ptime2;
-			}
-			break;
-		}
-		case 'm': {
-			int port, rc;
-
-			rc = sscanf(line, "m=audio %d RTP/AVP %d %d %d %d %d %d %d %d %d %d",
-					&port,
-					&codecs[0].payload_type,
-					&codecs[1].payload_type,
-					&codecs[2].payload_type,
-					&codecs[3].payload_type,
-					&codecs[4].payload_type,
-					&codecs[5].payload_type,
-					&codecs[6].payload_type,
-					&codecs[7].payload_type,
-					&codecs[8].payload_type,
-					&codecs[9].payload_type);
-			if (rc >= 2) {
-				rtp->rtp_port = htons(port);
-				rtp->rtcp_port = htons(port + 1);
-				codecs_used = rc - 1;
-				codecs_initialize(tmp_ctx, codecs, codecs_used);
-			}
-			break;
-		}
-		case 'c': {
-			char ipv4[16];
-
-			if (sscanf(line, "c=IN IP4 %15s", ipv4) == 1) {
-				inet_aton(ipv4, &rtp->addr);
-			}
-			break;
-		}
-		default:
-			if (p->endp)
-				LOGP(DMGCP, LOGL_NOTICE,
-				     "Unhandled SDP option: '%c'/%d on 0x%x\n",
-				     line[0], line[0], ENDPOINT_NUMBER(p->endp));
-			else
-				LOGP(DMGCP, LOGL_NOTICE,
-				     "Unhandled SDP option: '%c'/%d\n",
-				     line[0], line[0]);
-			break;
-		}
-	}
-
-	/* Now select the primary and alt_codec */
-	for (i = 0; i < codecs_used && codecs_assigned < 2; ++i) {
-		struct mgcp_rtp_codec *codec = codecs_assigned == 0 ?
-					&rtp->codec : &rtp->alt_codec;
-
-		if (endp->tcfg->no_audio_transcoding &&
-			!is_codec_compatible(endp, &codecs[i])) {
-			LOGP(DMGCP, LOGL_NOTICE, "Skipping codec %s\n",
-				codecs[i].codec_name);
-			continue;
-		}
-
-		mgcp_set_audio_info(p->cfg, codec,
-					codecs[i].payload_type,
-					codecs[i].map_line);
-		codecs_assigned += 1;
-	}
-
-	if (codecs_assigned > 0) {
-		/* TODO/XXX: Store this per codec and derive it on use */
-		if (maxptime >= 0 && maxptime * rtp->codec.frame_duration_den >
-				rtp->codec.frame_duration_num * 1500) {
-			/* more than 1 frame */
-			rtp->packet_duration_ms = 0;
-		}
-
-		LOGP(DMGCP, LOGL_NOTICE,
-		     "Got media info via SDP: port %d, payload %d (%s), "
-		     "duration %d, addr %s\n",
-		     ntohs(rtp->rtp_port), rtp->codec.payload_type,
-		     rtp->codec.subtype_name ? rtp->codec.subtype_name : "unknown",
-		     rtp->packet_duration_ms, inet_ntoa(rtp->addr));
-	}
-
-	talloc_free(tmp_ctx);
-	return codecs_assigned > 0;
-}
-
diff --git a/src/libmgcp/mgcp_transcode.c b/src/libmgcp/mgcp_transcode.c
deleted file mode 100644
index f31e7ae..0000000
--- a/src/libmgcp/mgcp_transcode.c
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- * (C) 2014 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/>.
- *
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-
-#include "g711common.h"
-
-#include <openbsc/debug.h>
-#include <openbsc/mgcp.h>
-#include <openbsc/mgcp_internal.h>
-#include <openbsc/mgcp_transcode.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/netif/rtp.h>
-
-int mgcp_transcoding_get_frame_size(void *state_, int nsamples, int dst)
-{
-	struct mgcp_process_rtp_state *state = state_;
-	if (dst)
-		return (nsamples >= 0 ?
-			nsamples / state->dst_samples_per_frame :
-			1) * state->dst_frame_size;
-	else
-		return (nsamples >= 0 ?
-			nsamples / state->src_samples_per_frame :
-			1) * state->src_frame_size;
-}
-
-static enum audio_format get_audio_format(const struct mgcp_rtp_codec *codec)
-{
-	if (codec->subtype_name) {
-		if (!strcasecmp("GSM", codec->subtype_name))
-			return AF_GSM;
-		if (!strcasecmp("PCMA", codec->subtype_name))
-			return AF_PCMA;
-		if (!strcasecmp("PCMU", codec->subtype_name))
-			return AF_PCMU;
-#ifdef HAVE_BCG729
-		if (!strcasecmp("G729", codec->subtype_name))
-			return AF_G729;
-#endif
-		if (!strcasecmp("L16", codec->subtype_name))
-			return AF_L16;
-	}
-
-	switch (codec->payload_type) {
-	case 0 /* PCMU */:
-		return AF_PCMU;
-	case 3 /* GSM */:
-		return AF_GSM;
-	case 8 /* PCMA */:
-		return AF_PCMA;
-#ifdef HAVE_BCG729
-	case 18 /* G.729 */:
-		return AF_G729;
-#endif
-	case 11 /* L16 */:
-		return AF_L16;
-	default:
-		return AF_INVALID;
-	}
-}
-
-static void l16_encode(short *sample, unsigned char *buf, size_t n)
-{
-	for (; n > 0; --n, ++sample, buf += 2) {
-		buf[0] = sample[0] >> 8;
-		buf[1] = sample[0] & 0xff;
-	}
-}
-
-static void l16_decode(unsigned char *buf, short *sample, size_t n)
-{
-	for (; n > 0; --n, ++sample, buf += 2)
-		sample[0] = ((short)buf[0] << 8) | buf[1];
-}
-
-static void alaw_encode(short *sample, unsigned char *buf, size_t n)
-{
-	for (; n > 0; --n)
-		*(buf++) = s16_to_alaw(*(sample++));
-}
-
-static void alaw_decode(unsigned char *buf, short *sample, size_t n)
-{
-	for (; n > 0; --n)
-		*(sample++) = alaw_to_s16(*(buf++));
-}
-
-static void ulaw_encode(short *sample, unsigned char *buf, size_t n)
-{
-	for (; n > 0; --n)
-		*(buf++) = s16_to_ulaw(*(sample++));
-}
-
-static void ulaw_decode(unsigned char *buf, short *sample, size_t n)
-{
-	for (; n > 0; --n)
-		*(sample++) = ulaw_to_s16(*(buf++));
-}
-
-static int processing_state_destructor(struct mgcp_process_rtp_state *state)
-{
-	switch (state->src_fmt) {
-	case AF_GSM:
-		if (state->src.gsm_handle)
-			gsm_destroy(state->src.gsm_handle);
-		break;
-#ifdef HAVE_BCG729
-	case AF_G729:
-		if (state->src.g729_dec)
-			closeBcg729DecoderChannel(state->src.g729_dec);
-		break;
-#endif
-	default:
-		break;
-	}
-	switch (state->dst_fmt) {
-	case AF_GSM:
-		if (state->dst.gsm_handle)
-			gsm_destroy(state->dst.gsm_handle);
-		break;
-#ifdef HAVE_BCG729
-	case AF_G729:
-		if (state->dst.g729_enc)
-			closeBcg729EncoderChannel(state->dst.g729_enc);
-		break;
-#endif
-	default:
-		break;
-	}
-	return 0;
-}
-
-int mgcp_transcoding_setup(struct mgcp_endpoint *endp,
-			   struct mgcp_rtp_end *dst_end,
-			   struct mgcp_rtp_end *src_end)
-{
-	struct mgcp_process_rtp_state *state;
-	enum audio_format src_fmt, dst_fmt;
-	const struct mgcp_rtp_codec *dst_codec = &dst_end->codec;
-
-	/* cleanup first */
-	if (dst_end->rtp_process_data) {
-		talloc_free(dst_end->rtp_process_data);
-		dst_end->rtp_process_data = NULL;
-	}
-
-	if (!src_end)
-		return 0;
-
-	const struct mgcp_rtp_codec *src_codec = &src_end->codec;
-
-	if (endp->tcfg->no_audio_transcoding) {
-		LOGP(DMGCP, LOGL_NOTICE,
-			"Transcoding disabled on endpoint 0x%x\n",
-			ENDPOINT_NUMBER(endp));
-		return 0;
-	}
-
-	src_fmt = get_audio_format(src_codec);
-	dst_fmt = get_audio_format(dst_codec);
-
-	LOGP(DMGCP, LOGL_ERROR,
-	     "Checking transcoding: %s (%d) -> %s (%d)\n",
-	     src_codec->subtype_name, src_codec->payload_type,
-	     dst_codec->subtype_name, dst_codec->payload_type);
-
-	if (src_fmt == AF_INVALID || dst_fmt == AF_INVALID) {
-		if (!src_codec->subtype_name || !dst_codec->subtype_name)
-			/* Not enough info, do nothing */
-			return 0;
-
-		if (strcasecmp(src_codec->subtype_name, dst_codec->subtype_name) == 0)
-			/* Nothing to do */
-			return 0;
-
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Cannot transcode: %s codec not supported (%s -> %s).\n",
-		     src_fmt != AF_INVALID ? "destination" : "source",
-		     src_codec->audio_name, dst_codec->audio_name);
-		return -EINVAL;
-	}
-
-	if (src_codec->rate && dst_codec->rate && src_codec->rate != dst_codec->rate) {
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Cannot transcode: rate conversion (%d -> %d) not supported.\n",
-		     src_codec->rate, dst_codec->rate);
-		return -EINVAL;
-	}
-
-	state = talloc_zero(endp->tcfg->cfg, struct mgcp_process_rtp_state);
-	talloc_set_destructor(state, processing_state_destructor);
-	dst_end->rtp_process_data = state;
-
-	state->src_fmt = src_fmt;
-
-	switch (state->src_fmt) {
-	case AF_L16:
-	case AF_S16:
-		state->src_frame_size = 80 * sizeof(short);
-		state->src_samples_per_frame = 80;
-		break;
-	case AF_GSM:
-		state->src_frame_size = sizeof(gsm_frame);
-		state->src_samples_per_frame = 160;
-		state->src.gsm_handle = gsm_create();
-		if (!state->src.gsm_handle) {
-			LOGP(DMGCP, LOGL_ERROR,
-			     "Failed to initialize GSM decoder.\n");
-			return -EINVAL;
-		}
-		break;
-#ifdef HAVE_BCG729
-	case AF_G729:
-		state->src_frame_size = 10;
-		state->src_samples_per_frame = 80;
-		state->src.g729_dec = initBcg729DecoderChannel();
-		if (!state->src.g729_dec) {
-			LOGP(DMGCP, LOGL_ERROR,
-			     "Failed to initialize G.729 decoder.\n");
-			return -EINVAL;
-		}
-		break;
-#endif
-	case AF_PCMU:
-	case AF_PCMA:
-		state->src_frame_size = 80;
-		state->src_samples_per_frame = 80;
-		break;
-	default:
-		break;
-	}
-
-	state->dst_fmt = dst_fmt;
-
-	switch (state->dst_fmt) {
-	case AF_L16:
-	case AF_S16:
-		state->dst_frame_size = 80*sizeof(short);
-		state->dst_samples_per_frame = 80;
-		break;
-	case AF_GSM:
-		state->dst_frame_size = sizeof(gsm_frame);
-		state->dst_samples_per_frame = 160;
-		state->dst.gsm_handle = gsm_create();
-		if (!state->dst.gsm_handle) {
-			LOGP(DMGCP, LOGL_ERROR,
-			     "Failed to initialize GSM encoder.\n");
-			return -EINVAL;
-		}
-		break;
-#ifdef HAVE_BCG729
-	case AF_G729:
-		state->dst_frame_size = 10;
-		state->dst_samples_per_frame = 80;
-		state->dst.g729_enc = initBcg729EncoderChannel();
-		if (!state->dst.g729_enc) {
-			LOGP(DMGCP, LOGL_ERROR,
-			     "Failed to initialize G.729 decoder.\n");
-			return -EINVAL;
-		}
-		break;
-#endif
-	case AF_PCMU:
-	case AF_PCMA:
-		state->dst_frame_size = 80;
-		state->dst_samples_per_frame = 80;
-		break;
-	default:
-		break;
-	}
-
-	if (dst_end->force_output_ptime)
-		state->dst_packet_duration = mgcp_rtp_packet_duration(endp, dst_end);
-
-	LOGP(DMGCP, LOGL_INFO,
-	     "Initialized RTP processing on: 0x%x "
-	     "conv: %d (%d, %d, %s) -> %d (%d, %d, %s)\n",
-	     ENDPOINT_NUMBER(endp),
-	     src_fmt, src_codec->payload_type, src_codec->rate, src_end->fmtp_extra,
-	     dst_fmt, dst_codec->payload_type, dst_codec->rate, dst_end->fmtp_extra);
-
-	return 0;
-}
-
-void mgcp_transcoding_net_downlink_format(struct mgcp_endpoint *endp,
-					  int *payload_type,
-					  const char**audio_name,
-					  const char**fmtp_extra)
-{
-	struct mgcp_process_rtp_state *state = endp->net_end.rtp_process_data;
-	struct mgcp_rtp_codec *net_codec = &endp->net_end.codec;
-	struct mgcp_rtp_codec *bts_codec = &endp->bts_end.codec;
-
-	if (!state || net_codec->payload_type < 0) {
-		*payload_type = bts_codec->payload_type;
-		*audio_name = bts_codec->audio_name;
-		*fmtp_extra = endp->bts_end.fmtp_extra;
-		return;
-	}
-
-	*payload_type = net_codec->payload_type;
-	*audio_name = net_codec->audio_name;
-	*fmtp_extra = endp->net_end.fmtp_extra;
-}
-
-static int decode_audio(struct mgcp_process_rtp_state *state,
-			uint8_t **src, size_t *nbytes)
-{
-	while (*nbytes >= state->src_frame_size) {
-		if (state->sample_cnt + state->src_samples_per_frame > ARRAY_SIZE(state->samples)) {
-			LOGP(DMGCP, LOGL_ERROR,
-			     "Sample buffer too small: %zu > %zu.\n",
-			     state->sample_cnt + state->src_samples_per_frame,
-			     ARRAY_SIZE(state->samples));
-			return -ENOSPC;
-		}
-		switch (state->src_fmt) {
-		case AF_GSM:
-			if (gsm_decode(state->src.gsm_handle,
-				       (gsm_byte *)*src, state->samples + state->sample_cnt) < 0) {
-				LOGP(DMGCP, LOGL_ERROR,
-				     "Failed to decode GSM.\n");
-				return -EINVAL;
-			}
-			break;
-#ifdef HAVE_BCG729
-		case AF_G729:
-			bcg729Decoder(state->src.g729_dec, *src, 0, state->samples + state->sample_cnt);
-			break;
-#endif
-		case AF_PCMU:
-			ulaw_decode(*src, state->samples + state->sample_cnt,
-				    state->src_samples_per_frame);
-			break;
-		case AF_PCMA:
-			alaw_decode(*src, state->samples + state->sample_cnt,
-				    state->src_samples_per_frame);
-			break;
-		case AF_S16:
-			memmove(state->samples + state->sample_cnt, *src,
-				state->src_frame_size);
-			break;
-		case AF_L16:
-			l16_decode(*src, state->samples + state->sample_cnt,
-				   state->src_samples_per_frame);
-			break;
-		default:
-			break;
-		}
-		*src        += state->src_frame_size;
-		*nbytes     -= state->src_frame_size;
-		state->sample_cnt += state->src_samples_per_frame;
-	}
-	return 0;
-}
-
-static int encode_audio(struct mgcp_process_rtp_state *state,
-			uint8_t *dst, size_t buf_size, size_t max_samples)
-{
-	int nbytes = 0;
-	size_t nsamples = 0;
-	/* Encode samples into dst */
-	while (nsamples + state->dst_samples_per_frame <= max_samples) {
-		if (nbytes + state->dst_frame_size > buf_size) {
-			if (nbytes > 0)
-				break;
-
-			/* Not even one frame fits into the buffer */
-			LOGP(DMGCP, LOGL_INFO,
-			     "Encoding (RTP) buffer too small: %zu > %zu.\n",
-			     nbytes + state->dst_frame_size, buf_size);
-			return -ENOSPC;
-		}
-		switch (state->dst_fmt) {
-		case AF_GSM:
-			gsm_encode(state->dst.gsm_handle,
-				   state->samples + state->sample_offs, dst);
-			break;
-#ifdef HAVE_BCG729
-		case AF_G729:
-			bcg729Encoder(state->dst.g729_enc,
-				      state->samples + state->sample_offs, dst);
-			break;
-#endif
-		case AF_PCMU:
-			ulaw_encode(state->samples + state->sample_offs, dst,
-				    state->src_samples_per_frame);
-			break;
-		case AF_PCMA:
-			alaw_encode(state->samples + state->sample_offs, dst,
-				    state->src_samples_per_frame);
-			break;
-		case AF_S16:
-			memmove(dst, state->samples + state->sample_offs,
-				state->dst_frame_size);
-			break;
-		case AF_L16:
-			l16_encode(state->samples + state->sample_offs, dst,
-				   state->src_samples_per_frame);
-			break;
-		default:
-			break;
-		}
-		dst        += state->dst_frame_size;
-		nbytes     += state->dst_frame_size;
-		state->sample_offs += state->dst_samples_per_frame;
-		nsamples   += state->dst_samples_per_frame;
-	}
-	state->sample_cnt -= nsamples;
-	return nbytes;
-}
-
-static struct mgcp_rtp_end *source_for_dest(struct mgcp_endpoint *endp,
-					struct mgcp_rtp_end *dst_end)
-{
-	if (&endp->bts_end == dst_end)
-		return &endp->net_end;
-	else if (&endp->net_end == dst_end)
-		return &endp->bts_end;
-	OSMO_ASSERT(0);
-}
-
-/*
- * With some modems we get offered multiple codecs
- * and we have selected one of them. It might not
- * be the right one and we need to detect this with
- * the first audio packets. One difficulty is that
- * we patch the rtp payload type in place, so we
- * need to discuss this.
- */
-struct mgcp_process_rtp_state *check_transcode_state(
-				struct mgcp_endpoint *endp,
-				struct mgcp_rtp_end *dst_end,
-				struct rtp_hdr *rtp_hdr)
-{
-	struct mgcp_rtp_end *src_end;
-
-	/* Only deal with messages from net to bts */
-	if (&endp->bts_end != dst_end)
-		goto done;
-
-	src_end = source_for_dest(endp, dst_end);
-
-	/* Already patched */
-	if (rtp_hdr->payload_type == dst_end->codec.payload_type)
-		goto done;
-	/* The payload we expect */
-	if (rtp_hdr->payload_type == src_end->codec.payload_type)
-		goto done;
-	/* The matching alternate payload type? Then switch */
-	if (rtp_hdr->payload_type == src_end->alt_codec.payload_type) {
-		struct mgcp_config *cfg = endp->cfg;
-		struct mgcp_rtp_codec tmp_codec = src_end->alt_codec;
-		src_end->alt_codec = src_end->codec;
-		src_end->codec = tmp_codec;
-		cfg->setup_rtp_processing_cb(endp, &endp->net_end, &endp->bts_end);
-		cfg->setup_rtp_processing_cb(endp, &endp->bts_end, &endp->net_end);
-	}
-
-done:
-	return dst_end->rtp_process_data;
-}
-
-int mgcp_transcoding_process_rtp(struct mgcp_endpoint *endp,
-				struct mgcp_rtp_end *dst_end,
-			     char *data, int *len, int buf_size)
-{
-	struct mgcp_process_rtp_state *state;
-	const size_t rtp_hdr_size = sizeof(struct rtp_hdr);
-	struct rtp_hdr *rtp_hdr = (struct rtp_hdr *) data;
-	char *payload_data = (char *) &rtp_hdr->data[0];
-	int payload_len = *len - rtp_hdr_size;
-	uint8_t *src = (uint8_t *)payload_data;
-	uint8_t *dst = (uint8_t *)payload_data;
-	size_t nbytes = payload_len;
-	size_t nsamples;
-	size_t max_samples;
-	uint32_t ts_no;
-	int rc;
-
-	state = check_transcode_state(endp, dst_end, rtp_hdr);
-	if (!state)
-		return 0;
-
-	if (state->src_fmt == state->dst_fmt) {
-		if (!state->dst_packet_duration)
-			return 0;
-
-		/* TODO: repackage without transcoding */
-	}
-
-	/* If the remaining samples do not fit into a fixed ptime,
-	 * a) discard them, if the next packet is much later
-	 * b) add silence and * send it, if the current packet is not
-	 *    yet too late
-	 * c) append the sample data, if the timestamp matches exactly
-	 */
-
-	/* TODO: check payload type (-> G.711 comfort noise) */
-
-	if (payload_len > 0) {
-		ts_no = ntohl(rtp_hdr->timestamp);
-		if (!state->is_running) {
-			state->next_seq = ntohs(rtp_hdr->sequence);
-			state->next_time = ts_no;
-			state->is_running = 1;
-		}
-
-
-		if (state->sample_cnt > 0) {
-			int32_t delta = ts_no - state->next_time;
-			/* TODO: check sequence? reordering? packet loss? */
-
-			if (delta > state->sample_cnt) {
-				/* There is a time gap between the last packet
-				 * and the current one. Just discard the
-				 * partial data that is left in the buffer.
-				 * TODO: This can be improved by adding silence
-				 * instead if the delta is small enough.
-				 */
-				LOGP(DMGCP, LOGL_NOTICE,
-					"0x%x dropping sample buffer due delta=%d sample_cnt=%zu\n",
-					ENDPOINT_NUMBER(endp), delta, state->sample_cnt);
-				state->sample_cnt = 0;
-				state->next_time = ts_no;
-			} else if (delta < 0) {
-				LOGP(DMGCP, LOGL_NOTICE,
-				     "RTP time jumps backwards, delta = %d, "
-				     "discarding buffered samples\n",
-				     delta);
-				state->sample_cnt = 0;
-				state->sample_offs = 0;
-				return -EAGAIN;
-			}
-
-			/* Make sure the samples start without offset */
-			if (state->sample_offs && state->sample_cnt)
-				memmove(&state->samples[0],
-					&state->samples[state->sample_offs],
-					state->sample_cnt *
-					sizeof(state->samples[0]));
-		}
-
-		state->sample_offs = 0;
-
-		/* Append decoded audio to samples */
-		decode_audio(state, &src, &nbytes);
-
-		if (nbytes > 0)
-			LOGP(DMGCP, LOGL_NOTICE,
-			     "Skipped audio frame in RTP packet: %zu octets\n",
-			     nbytes);
-	} else
-		ts_no = state->next_time;
-
-	if (state->sample_cnt < state->dst_packet_duration)
-		return -EAGAIN;
-
-	max_samples =
-		state->dst_packet_duration ?
-		state->dst_packet_duration : state->sample_cnt;
-
-	nsamples = state->sample_cnt;
-
-	rc = encode_audio(state, dst, buf_size, max_samples);
-	/*
-	 * There were no samples to encode?
-	 * TODO: how does this work for comfort noise?
-	 */
-	if (rc == 0)
-		return -ENOMSG;
-	/* Any other error during the encoding */
-	if (rc < 0)
-		return rc;
-
-	nsamples -= state->sample_cnt;
-
-	*len = rtp_hdr_size + rc;
-	rtp_hdr->sequence = htons(state->next_seq);
-	rtp_hdr->timestamp = htonl(ts_no);
-
-	state->next_seq += 1;
-	state->next_time = ts_no + nsamples;
-
-	/*
-	 * XXX: At this point we should always have consumed
-	 * samples. So doing OSMO_ASSERT(nsamples > 0) and returning
-	 * rtp_hdr_size should be fine.
-	 */
-	return nsamples ? rtp_hdr_size : 0;
-}
diff --git a/src/libmgcp/mgcp_vty.c b/src/libmgcp/mgcp_vty.c
deleted file mode 100644
index 51889d9..0000000
--- a/src/libmgcp/mgcp_vty.c
+++ /dev/null
@@ -1,1555 +0,0 @@
-/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
-/* The protocol implementation */
-
-/*
- * (C) 2009-2014 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2011 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/>.
- *
- */
-
-
-#include <osmocom/core/talloc.h>
-
-#include <openbsc/mgcp.h>
-#include <openbsc/mgcp_internal.h>
-#include <openbsc/vty.h>
-
-#include <string.h>
-
-#define RTCP_OMIT_STR "Drop RTCP packets in both directions\n"
-#define RTP_PATCH_STR "Modify RTP packet header in both directions\n"
-#define RTP_KEEPALIVE_STR "Send dummy UDP packet to net RTP destination\n"
-
-static struct mgcp_config *g_cfg = NULL;
-
-static struct mgcp_trunk_config *find_trunk(struct mgcp_config *cfg, int nr)
-{
-	struct mgcp_trunk_config *trunk;
-
-	if (nr == 0)
-		trunk = &cfg->trunk;
-	else
-		trunk = mgcp_trunk_num(cfg, nr);
-
-	return trunk;
-}
-
-/*
- * vty code for mgcp below
- */
-struct cmd_node mgcp_node = {
-	MGCP_NODE,
-	"%s(config-mgcp)# ",
-	1,
-};
-
-struct cmd_node trunk_node = {
-	TRUNK_NODE,
-	"%s(config-mgcp-trunk)# ",
-	1,
-};
-
-static int config_write_mgcp(struct vty *vty)
-{
-	vty_out(vty, "mgcp%s", VTY_NEWLINE);
-	if (g_cfg->local_ip)
-		vty_out(vty, "  local ip %s%s", g_cfg->local_ip, VTY_NEWLINE);
-	if (g_cfg->bts_ip && strlen(g_cfg->bts_ip) != 0)
-		vty_out(vty, "  bts ip %s%s", g_cfg->bts_ip, VTY_NEWLINE);
-	vty_out(vty, "  bind ip %s%s", g_cfg->source_addr, VTY_NEWLINE);
-	vty_out(vty, "  bind port %u%s", g_cfg->source_port, VTY_NEWLINE);
-
-	if (g_cfg->bts_ports.mode == PORT_ALLOC_STATIC)
-		vty_out(vty, "  rtp bts-base %u%s", g_cfg->bts_ports.base_port, VTY_NEWLINE);
-	else
-		vty_out(vty, "  rtp bts-range %u %u%s",
-			g_cfg->bts_ports.range_start, g_cfg->bts_ports.range_end, VTY_NEWLINE);
-	if (g_cfg->bts_ports.bind_addr)
-		vty_out(vty, "  rtp bts-bind-ip %s%s", g_cfg->bts_ports.bind_addr, VTY_NEWLINE);
-
-	if (g_cfg->net_ports.mode == PORT_ALLOC_STATIC)
-		vty_out(vty, "  rtp net-base %u%s", g_cfg->net_ports.base_port, VTY_NEWLINE);
-	else
-		vty_out(vty, "  rtp net-range %u %u%s",
-			g_cfg->net_ports.range_start, g_cfg->net_ports.range_end, VTY_NEWLINE);
-	if (g_cfg->net_ports.bind_addr)
-		vty_out(vty, "  rtp net-bind-ip %s%s", g_cfg->net_ports.bind_addr, VTY_NEWLINE);
-
-	vty_out(vty, "  rtp ip-dscp %d%s", g_cfg->endp_dscp, VTY_NEWLINE);
-	if (g_cfg->trunk.keepalive_interval == MGCP_KEEPALIVE_ONCE)
-		vty_out(vty, "  rtp keep-alive once%s", VTY_NEWLINE);
-	else if (g_cfg->trunk.keepalive_interval)
-		vty_out(vty, "  rtp keep-alive %d%s",
-			g_cfg->trunk.keepalive_interval, VTY_NEWLINE);
-	else
-		vty_out(vty, "  no rtp keep-alive%s", VTY_NEWLINE);
-
-	if (g_cfg->trunk.omit_rtcp)
-		vty_out(vty, "  rtcp-omit%s", VTY_NEWLINE);
-	else
-		vty_out(vty, "  no rtcp-omit%s", VTY_NEWLINE);
-	if (g_cfg->trunk.force_constant_ssrc || g_cfg->trunk.force_aligned_timing) {
-		vty_out(vty, "  %srtp-patch ssrc%s",
-			g_cfg->trunk.force_constant_ssrc ? "" : "no ", VTY_NEWLINE);
-		vty_out(vty, "  %srtp-patch timestamp%s",
-			g_cfg->trunk.force_aligned_timing ? "" : "no ", VTY_NEWLINE);
-	} else
-		vty_out(vty, "  no rtp-patch%s", VTY_NEWLINE);
-	if (g_cfg->trunk.audio_payload != -1)
-		vty_out(vty, "  sdp audio-payload number %d%s",
-			g_cfg->trunk.audio_payload, VTY_NEWLINE);
-	if (g_cfg->trunk.audio_name)
-		vty_out(vty, "  sdp audio-payload name %s%s",
-			g_cfg->trunk.audio_name, VTY_NEWLINE);
-	if (g_cfg->trunk.audio_fmtp_extra)
-		vty_out(vty, "  sdp audio fmtp-extra %s%s",
-			g_cfg->trunk.audio_fmtp_extra, VTY_NEWLINE);
-	vty_out(vty, "  %ssdp audio-payload send-ptime%s",
-		g_cfg->trunk.audio_send_ptime ? "" : "no ", VTY_NEWLINE);
-	vty_out(vty, "  %ssdp audio-payload send-name%s",
-		g_cfg->trunk.audio_send_name ? "" : "no ", VTY_NEWLINE);
-	vty_out(vty, "  loop %u%s", !!g_cfg->trunk.audio_loop, VTY_NEWLINE);
-	vty_out(vty, "  number endpoints %u%s", g_cfg->trunk.number_endpoints - 1, VTY_NEWLINE);
-	vty_out(vty, "  %sallow-transcoding%s",
-		g_cfg->trunk.no_audio_transcoding ? "no " : "", VTY_NEWLINE);
-	if (g_cfg->call_agent_addr)
-		vty_out(vty, "  call-agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE);
-	if (g_cfg->transcoder_ip)
-		vty_out(vty, "  transcoder-mgw %s%s", g_cfg->transcoder_ip, VTY_NEWLINE);
-
-	if (g_cfg->transcoder_ports.mode == PORT_ALLOC_STATIC)
-		vty_out(vty, "  rtp transcoder-base %u%s", g_cfg->transcoder_ports.base_port, VTY_NEWLINE);
-	else
-		vty_out(vty, "  rtp transcoder-range %u %u%s",
-			g_cfg->transcoder_ports.range_start, g_cfg->transcoder_ports.range_end, VTY_NEWLINE);
-	if (g_cfg->bts_force_ptime > 0)
-		vty_out(vty, "  rtp force-ptime %d%s", g_cfg->bts_force_ptime, VTY_NEWLINE);
-	vty_out(vty, "  transcoder-remote-base %u%s", g_cfg->transcoder_remote_base, VTY_NEWLINE);
-
-	switch (g_cfg->osmux) {
-	case OSMUX_USAGE_ON:
-		vty_out(vty, "  osmux on%s", VTY_NEWLINE);
-		break;
-	case OSMUX_USAGE_ONLY:
-		vty_out(vty, "  osmux only%s", VTY_NEWLINE);
-		break;
-	case OSMUX_USAGE_OFF:
-	default:
-		vty_out(vty, "  osmux off%s", VTY_NEWLINE);
-		break;
-	}
-	if (g_cfg->osmux) {
-		vty_out(vty, "  osmux bind-ip %s%s",
-			g_cfg->osmux_addr, VTY_NEWLINE);
-		vty_out(vty, "  osmux batch-factor %d%s",
-			g_cfg->osmux_batch, VTY_NEWLINE);
-		vty_out(vty, "  osmux batch-size %u%s",
-			g_cfg->osmux_batch_size, VTY_NEWLINE);
-		vty_out(vty, "  osmux port %u%s",
-			g_cfg->osmux_port, VTY_NEWLINE);
-		vty_out(vty, "  osmux dummy %s%s",
-			g_cfg->osmux_dummy ? "on" : "off", VTY_NEWLINE);
-	}
-	return CMD_SUCCESS;
-}
-
-static void dump_rtp_end(const char *end_name, struct vty *vty,
-			struct mgcp_rtp_state *state, struct mgcp_rtp_end *end)
-{
-	struct mgcp_rtp_codec *codec = &end->codec;
-
-	vty_out(vty,
-		"  %s%s"
-		"   Timestamp Errs: %d->%d%s"
-		"   Dropped Packets: %d%s"
-		"   Payload Type: %d Rate: %u Channels: %d %s"
-		"   Frame Duration: %u Frame Denominator: %u%s"
-		"   FPP: %d Packet Duration: %u%s"
-		"   FMTP-Extra: %s Audio-Name: %s Sub-Type: %s%s"
-		"   Output-Enabled: %d Force-PTIME: %d%s",
-		end_name, VTY_NEWLINE,
-		state->in_stream.err_ts_counter,
-		state->out_stream.err_ts_counter, VTY_NEWLINE,
-		end->dropped_packets, VTY_NEWLINE,
-		codec->payload_type, codec->rate, codec->channels, VTY_NEWLINE,
-		codec->frame_duration_num, codec->frame_duration_den, VTY_NEWLINE,
-		end->frames_per_packet, end->packet_duration_ms, VTY_NEWLINE,
-		end->fmtp_extra, codec->audio_name, codec->subtype_name, VTY_NEWLINE,
-		end->output_enabled, end->force_output_ptime, VTY_NEWLINE);
-}
-
-static void dump_trunk(struct vty *vty, struct mgcp_trunk_config *cfg, int verbose)
-{
-	int i;
-
-	vty_out(vty, "%s trunk nr %d with %d endpoints:%s",
-		cfg->trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1",
-		cfg->trunk_nr, cfg->number_endpoints - 1, VTY_NEWLINE);
-
-	if (!cfg->endpoints) {
-		vty_out(vty, "No endpoints allocated yet.%s", VTY_NEWLINE);
-		return;
-	}
-
-	for (i = 1; i < cfg->number_endpoints; ++i) {
-		struct mgcp_endpoint *endp = &cfg->endpoints[i];
-		vty_out(vty,
-			" Endpoint 0x%.2x: CI: %d net: %u/%u bts: %u/%u on %s "
-			"traffic received bts: %u  remote: %u transcoder: %u/%u%s",
-			i, endp->ci,
-			ntohs(endp->net_end.rtp_port), ntohs(endp->net_end.rtcp_port),
-			ntohs(endp->bts_end.rtp_port), ntohs(endp->bts_end.rtcp_port),
-			inet_ntoa(endp->bts_end.addr),
-			endp->bts_end.packets, endp->net_end.packets,
-			endp->trans_net.packets, endp->trans_bts.packets,
-			VTY_NEWLINE);
-
-		if (verbose && endp->allocated) {
-			dump_rtp_end("Net->BTS", vty, &endp->bts_state, &endp->bts_end);
-			dump_rtp_end("BTS->Net", vty, &endp->net_state, &endp->net_end);
-		}
-	}
-}
-
-DEFUN(show_mcgp, show_mgcp_cmd,
-      "show mgcp [stats]",
-      SHOW_STR
-      "Display information about the MGCP Media Gateway\n"
-      "Include Statistics\n")
-{
-	struct mgcp_trunk_config *trunk;
-	int show_stats = argc >= 1;
-
-	dump_trunk(vty, &g_cfg->trunk, show_stats);
-
-	llist_for_each_entry(trunk, &g_cfg->trunks, entry)
-		dump_trunk(vty, trunk, show_stats);
-
-	if (g_cfg->osmux)
-		vty_out(vty, "Osmux used CID: %d%s", osmux_used_cid(), VTY_NEWLINE);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp,
-      cfg_mgcp_cmd,
-      "mgcp",
-      "Configure the MGCP")
-{
-	vty->node = MGCP_NODE;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_local_ip,
-      cfg_mgcp_local_ip_cmd,
-      "local ip A.B.C.D",
-      "Local options for the SDP record\n"
-      IP_STR
-      "IPv4 Address to use in SDP record\n")
-{
-	osmo_talloc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_bts_ip,
-      cfg_mgcp_bts_ip_cmd,
-      "bts ip A.B.C.D",
-      "BTS Audio source/destination options\n"
-      IP_STR
-      "IPv4 Address of the BTS\n")
-{
-	osmo_talloc_replace_string(g_cfg, &g_cfg->bts_ip, argv[0]);
-	inet_aton(g_cfg->bts_ip, &g_cfg->bts_in);
-	return CMD_SUCCESS;
-}
-
-#define BIND_STR "Listen/Bind related socket option\n"
-DEFUN(cfg_mgcp_bind_ip,
-      cfg_mgcp_bind_ip_cmd,
-      "bind ip A.B.C.D",
-      BIND_STR
-      IP_STR
-      "IPv4 Address to bind to\n")
-{
-	osmo_talloc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_bind_port,
-      cfg_mgcp_bind_port_cmd,
-      "bind port <0-65534>",
-      BIND_STR
-      "Port information\n"
-      "UDP port to listen for MGCP messages\n")
-{
-	unsigned int port = atoi(argv[0]);
-	g_cfg->source_port = port;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_bind_early,
-      cfg_mgcp_bind_early_cmd,
-      "bind early (0|1)",
-      BIND_STR
-      "Bind local ports on start up\n"
-      "Bind on demand\n" "Bind on startup\n")
-{
-	vty_out(vty, "bind early is deprecated, remove it from the config.\n");
-	return CMD_WARNING;
-}
-
-static void parse_base(struct mgcp_port_range *range, const char **argv)
-{
-	unsigned int port = atoi(argv[0]);
-	range->mode = PORT_ALLOC_STATIC;
-	range->base_port = port;
-}
-
-static void parse_range(struct mgcp_port_range *range, const char **argv)
-{
-	range->mode = PORT_ALLOC_DYNAMIC;
-	range->range_start = atoi(argv[0]);
-	range->range_end = atoi(argv[1]);
-	range->last_port = g_cfg->bts_ports.range_start;
-}
-
-
-#define RTP_STR "RTP configuration\n"
-#define BTS_START_STR "First UDP port allocated for the BTS side\n"
-#define NET_START_STR "First UDP port allocated for the NET side\n"
-#define UDP_PORT_STR "UDP Port number\n"
-DEFUN(cfg_mgcp_rtp_bts_base_port,
-      cfg_mgcp_rtp_bts_base_port_cmd,
-      "rtp bts-base <0-65534>",
-      RTP_STR
-      BTS_START_STR
-      UDP_PORT_STR)
-{
-	parse_base(&g_cfg->bts_ports, argv);
-	return CMD_SUCCESS;
-}
-
-#define RANGE_START_STR "Start of the range of ports\n"
-#define RANGE_END_STR "End of the range of ports\n"
-DEFUN(cfg_mgcp_rtp_bts_range,
-      cfg_mgcp_rtp_bts_range_cmd,
-      "rtp bts-range <0-65534> <0-65534>",
-      RTP_STR "Range of ports to use for the BTS side\n"
-      RANGE_START_STR RANGE_END_STR)
-{
-	parse_range(&g_cfg->bts_ports, argv);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_rtp_net_range,
-      cfg_mgcp_rtp_net_range_cmd,
-      "rtp net-range <0-65534> <0-65534>",
-      RTP_STR "Range of ports to use for the NET side\n"
-      RANGE_START_STR RANGE_END_STR)
-{
-	parse_range(&g_cfg->net_ports, argv);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_rtp_net_base_port,
-      cfg_mgcp_rtp_net_base_port_cmd,
-      "rtp net-base <0-65534>",
-      RTP_STR NET_START_STR UDP_PORT_STR)
-{
-	parse_base(&g_cfg->net_ports, argv);
-	return CMD_SUCCESS;
-}
-
-ALIAS_DEPRECATED(cfg_mgcp_rtp_bts_base_port, cfg_mgcp_rtp_base_port_cmd,
-      "rtp base <0-65534>",
-      RTP_STR BTS_START_STR UDP_PORT_STR)
-
-DEFUN(cfg_mgcp_rtp_transcoder_range,
-      cfg_mgcp_rtp_transcoder_range_cmd,
-      "rtp transcoder-range <0-65534> <0-65534>",
-      RTP_STR "Range of ports to use for the Transcoder\n"
-      RANGE_START_STR RANGE_END_STR)
-{
-	parse_range(&g_cfg->transcoder_ports, argv);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_rtp_transcoder_base,
-      cfg_mgcp_rtp_transcoder_base_cmd,
-      "rtp transcoder-base <0-65534>",
-      RTP_STR "First UDP port allocated for the Transcoder side\n"
-      UDP_PORT_STR)
-{
-	parse_base(&g_cfg->transcoder_ports, argv);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_rtp_bts_bind_ip,
-      cfg_mgcp_rtp_bts_bind_ip_cmd,
-      "rtp bts-bind-ip A.B.C.D",
-      RTP_STR "Bind endpoints facing the BTS\n" "Address to bind to\n")
-{
-	osmo_talloc_replace_string(g_cfg, &g_cfg->bts_ports.bind_addr, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_rtp_no_bts_bind_ip,
-      cfg_mgcp_rtp_no_bts_bind_ip_cmd,
-      "no rtp bts-bind-ip",
-      NO_STR RTP_STR "Bind endpoints facing the BTS\n" "Address to bind to\n")
-{
-	talloc_free(g_cfg->bts_ports.bind_addr);
-	g_cfg->bts_ports.bind_addr = NULL;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_rtp_net_bind_ip,
-      cfg_mgcp_rtp_net_bind_ip_cmd,
-      "rtp net-bind-ip A.B.C.D",
-      RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
-{
-	osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_rtp_no_net_bind_ip,
-      cfg_mgcp_rtp_no_net_bind_ip_cmd,
-      "no rtp net-bind-ip",
-      NO_STR RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
-{
-	talloc_free(g_cfg->net_ports.bind_addr);
-	g_cfg->net_ports.bind_addr = NULL;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_rtp_ip_dscp,
-      cfg_mgcp_rtp_ip_dscp_cmd,
-      "rtp ip-dscp <0-255>",
-      RTP_STR
-      "Apply IP_TOS to the audio stream (including Osmux)\n" "The DSCP value\n")
-{
-	int dscp = atoi(argv[0]);
-	g_cfg->endp_dscp = dscp;
-	return CMD_SUCCESS;
-}
-
-ALIAS_DEPRECATED(cfg_mgcp_rtp_ip_dscp, cfg_mgcp_rtp_ip_tos_cmd,
-      "rtp ip-tos <0-255>",
-      RTP_STR
-      "Apply IP_TOS to the audio stream\n" "The DSCP value\n")
-
-#define FORCE_PTIME_STR "Force a fixed ptime for packets sent to the BTS"
-DEFUN(cfg_mgcp_rtp_force_ptime,
-      cfg_mgcp_rtp_force_ptime_cmd,
-      "rtp force-ptime (10|20|40)",
-      RTP_STR FORCE_PTIME_STR
-      "The required ptime (packet duration) in ms\n"
-      "10 ms\n20 ms\n40 ms\n")
-{
-	g_cfg->bts_force_ptime = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_no_rtp_force_ptime,
-      cfg_mgcp_no_rtp_force_ptime_cmd,
-      "no rtp force-ptime",
-      NO_STR RTP_STR FORCE_PTIME_STR)
-{
-	g_cfg->bts_force_ptime = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_sdp_fmtp_extra,
-      cfg_mgcp_sdp_fmtp_extra_cmd,
-      "sdp audio fmtp-extra .NAME",
-      "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
-      "Extra Information\n")
-{
-	char *txt = argv_concat(argv, argc, 0);
-	if (!txt)
-		return CMD_WARNING;
-
-	osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_fmtp_extra, txt);
-	talloc_free(txt);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_allow_transcoding,
-      cfg_mgcp_allow_transcoding_cmd,
-      "allow-transcoding",
-      "Allow transcoding\n")
-{
-	g_cfg->trunk.no_audio_transcoding = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_no_allow_transcoding,
-      cfg_mgcp_no_allow_transcoding_cmd,
-      "no allow-transcoding",
-      NO_STR "Allow transcoding\n")
-{
-	g_cfg->trunk.no_audio_transcoding = 1;
-	return CMD_SUCCESS;
-}
-
-#define SDP_STR "SDP File related options\n"
-#define AUDIO_STR "Audio payload options\n"
-DEFUN(cfg_mgcp_sdp_payload_number,
-      cfg_mgcp_sdp_payload_number_cmd,
-      "sdp audio-payload number <0-255>",
-      SDP_STR AUDIO_STR
-      "Number\n" "Payload number\n")
-{
-	unsigned int payload = atoi(argv[0]);
-	g_cfg->trunk.audio_payload = payload;
-	return CMD_SUCCESS;
-}
-
-ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_number, cfg_mgcp_sdp_payload_number_cmd_old,
-      "sdp audio payload number <0-255>",
-      SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload number\n")
-      
-
-DEFUN(cfg_mgcp_sdp_payload_name,
-      cfg_mgcp_sdp_payload_name_cmd,
-      "sdp audio-payload name NAME",
-      SDP_STR AUDIO_STR "Name\n" "Payload name\n")
-{
-	osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_name, argv[0]);
-	return CMD_SUCCESS;
-}
-
-ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_name, cfg_mgcp_sdp_payload_name_cmd_old,
-      "sdp audio payload name NAME",
-      SDP_STR AUDIO_STR AUDIO_STR "Name\n" "Payload name\n")
-
-DEFUN(cfg_mgcp_sdp_payload_send_ptime,
-      cfg_mgcp_sdp_payload_send_ptime_cmd,
-      "sdp audio-payload send-ptime",
-      SDP_STR AUDIO_STR
-      "Send SDP ptime (packet duration) attribute\n")
-{
-	g_cfg->trunk.audio_send_ptime = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_no_sdp_payload_send_ptime,
-      cfg_mgcp_no_sdp_payload_send_ptime_cmd,
-      "no sdp audio-payload send-ptime",
-      NO_STR SDP_STR AUDIO_STR
-      "Send SDP ptime (packet duration) attribute\n")
-{
-	g_cfg->trunk.audio_send_ptime = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_sdp_payload_send_name,
-      cfg_mgcp_sdp_payload_send_name_cmd,
-      "sdp audio-payload send-name",
-      SDP_STR AUDIO_STR
-      "Send SDP rtpmap with the audio name\n")
-{
-	g_cfg->trunk.audio_send_name = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_no_sdp_payload_send_name,
-      cfg_mgcp_no_sdp_payload_send_name_cmd,
-      "no sdp audio-payload send-name",
-      NO_STR SDP_STR AUDIO_STR
-      "Send SDP rtpmap with the audio name\n")
-{
-	g_cfg->trunk.audio_send_name = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_loop,
-      cfg_mgcp_loop_cmd,
-      "loop (0|1)",
-      "Loop audio for all endpoints on main trunk\n"
-      "Don't Loop\n" "Loop\n")
-{
-	if (g_cfg->osmux) {
-		vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-	g_cfg->trunk.audio_loop = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_force_realloc,
-      cfg_mgcp_force_realloc_cmd,
-      "force-realloc (0|1)",
-      "Force endpoint reallocation when the endpoint is still seized\n"
-      "Don't force reallocation\n" "force reallocation\n")
-{
-	g_cfg->trunk.force_realloc = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_number_endp,
-      cfg_mgcp_number_endp_cmd,
-      "number endpoints <0-65534>",
-      "Number options\n" "Endpoints available\n" "Number endpoints\n")
-{
-	/* + 1 as we start counting at one */
-	g_cfg->trunk.number_endpoints = atoi(argv[0]) + 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_omit_rtcp,
-      cfg_mgcp_omit_rtcp_cmd,
-      "rtcp-omit",
-      RTCP_OMIT_STR)
-{
-	g_cfg->trunk.omit_rtcp = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_no_omit_rtcp,
-      cfg_mgcp_no_omit_rtcp_cmd,
-      "no rtcp-omit",
-      NO_STR RTCP_OMIT_STR)
-{
-	g_cfg->trunk.omit_rtcp = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_patch_rtp_ssrc,
-      cfg_mgcp_patch_rtp_ssrc_cmd,
-      "rtp-patch ssrc",
-      RTP_PATCH_STR
-      "Force a fixed SSRC\n"
-      )
-{
-	g_cfg->trunk.force_constant_ssrc = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_no_patch_rtp_ssrc,
-      cfg_mgcp_no_patch_rtp_ssrc_cmd,
-      "no rtp-patch ssrc",
-      NO_STR RTP_PATCH_STR
-      "Force a fixed SSRC\n"
-      )
-{
-	g_cfg->trunk.force_constant_ssrc = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_patch_rtp_ts,
-      cfg_mgcp_patch_rtp_ts_cmd,
-      "rtp-patch timestamp",
-      RTP_PATCH_STR
-      "Adjust RTP timestamp\n"
-      )
-{
-	g_cfg->trunk.force_aligned_timing = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_no_patch_rtp_ts,
-      cfg_mgcp_no_patch_rtp_ts_cmd,
-      "no rtp-patch timestamp",
-      NO_STR RTP_PATCH_STR
-      "Adjust RTP timestamp\n"
-      )
-{
-	g_cfg->trunk.force_aligned_timing = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_no_patch_rtp,
-      cfg_mgcp_no_patch_rtp_cmd,
-      "no rtp-patch",
-      NO_STR RTP_PATCH_STR)
-{
-	g_cfg->trunk.force_constant_ssrc = 0;
-	g_cfg->trunk.force_aligned_timing = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_rtp_keepalive,
-      cfg_mgcp_rtp_keepalive_cmd,
-      "rtp keep-alive <1-120>",
-      RTP_STR RTP_KEEPALIVE_STR
-      "Keep alive interval in secs\n"
-      )
-{
-	mgcp_trunk_set_keepalive(&g_cfg->trunk, atoi(argv[0]));
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_rtp_keepalive_once,
-      cfg_mgcp_rtp_keepalive_once_cmd,
-      "rtp keep-alive once",
-      RTP_STR RTP_KEEPALIVE_STR
-      "Send dummy packet only once after CRCX/MDCX\n"
-      )
-{
-	mgcp_trunk_set_keepalive(&g_cfg->trunk, MGCP_KEEPALIVE_ONCE);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_no_rtp_keepalive,
-      cfg_mgcp_no_rtp_keepalive_cmd,
-      "no rtp keep-alive",
-      NO_STR RTP_STR RTP_KEEPALIVE_STR
-      )
-{
-	mgcp_trunk_set_keepalive(&g_cfg->trunk, 0);
-	return CMD_SUCCESS;
-}
-
-
-
-#define CALL_AGENT_STR "Callagent information\n"
-DEFUN(cfg_mgcp_agent_addr,
-      cfg_mgcp_agent_addr_cmd,
-      "call-agent ip A.B.C.D",
-      CALL_AGENT_STR IP_STR
-      "IPv4 Address of the callagent\n")
-{
-	osmo_talloc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
-	return CMD_SUCCESS;
-}
-
-ALIAS_DEPRECATED(cfg_mgcp_agent_addr, cfg_mgcp_agent_addr_cmd_old,
-      "call agent ip A.B.C.D",
-      CALL_AGENT_STR CALL_AGENT_STR IP_STR
-      "IPv4 Address of the callagent\n")
-      
-
-DEFUN(cfg_mgcp_transcoder,
-      cfg_mgcp_transcoder_cmd,
-      "transcoder-mgw A.B.C.D",
-      "Use a MGW to detranscoder RTP\n"
-      "The IP address of the MGW")
-{
-	osmo_talloc_replace_string(g_cfg, &g_cfg->transcoder_ip, argv[0]);
-	inet_aton(g_cfg->transcoder_ip, &g_cfg->transcoder_in);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_no_transcoder,
-      cfg_mgcp_no_transcoder_cmd,
-      "no transcoder-mgw",
-      NO_STR "Disable the transcoding\n")
-{
-	if (g_cfg->transcoder_ip) {
-		LOGP(DMGCP, LOGL_NOTICE, "Disabling transcoding on future calls.\n");
-		talloc_free(g_cfg->transcoder_ip);
-		g_cfg->transcoder_ip = NULL;
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_transcoder_remote_base,
-      cfg_mgcp_transcoder_remote_base_cmd,
-      "transcoder-remote-base <0-65534>",
-      "Set the base port for the transcoder\n" "The RTP base port on the transcoder")
-{
-	g_cfg->transcoder_remote_base = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd,
-      "trunk <1-64>",
-      "Configure a SS7 trunk\n" "Trunk Nr\n")
-{
-	struct mgcp_trunk_config *trunk;
-	int index = atoi(argv[0]);
-
-	trunk = mgcp_trunk_num(g_cfg, index);
-	if (!trunk)
-		trunk = mgcp_trunk_alloc(g_cfg, index);
-
-	if (!trunk) {
-		vty_out(vty, "%%Unable to allocate trunk %u.%s",
-			index, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	vty->node = TRUNK_NODE;
-	vty->index = trunk;
-	return CMD_SUCCESS;
-}
-
-static int config_write_trunk(struct vty *vty)
-{
-	struct mgcp_trunk_config *trunk;
-
-	llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
-		vty_out(vty, " trunk %d%s", trunk->trunk_nr, VTY_NEWLINE);
-		vty_out(vty, "  sdp audio-payload number %d%s",
-			trunk->audio_payload, VTY_NEWLINE);
-		vty_out(vty, "  sdp audio-payload name %s%s",
-			trunk->audio_name, VTY_NEWLINE);
-		vty_out(vty, "  %ssdp audio-payload send-ptime%s",
-			trunk->audio_send_ptime ? "" : "no ", VTY_NEWLINE);
-		vty_out(vty, "  %ssdp audio-payload send-name%s",
-			trunk->audio_send_name ? "" : "no ", VTY_NEWLINE);
-
-		if (trunk->keepalive_interval == MGCP_KEEPALIVE_ONCE)
-			vty_out(vty, "  rtp keep-alive once%s", VTY_NEWLINE);
-		else if (trunk->keepalive_interval)
-			vty_out(vty, "  rtp keep-alive %d%s",
-				trunk->keepalive_interval, VTY_NEWLINE);
-		else
-			vty_out(vty, "  no rtp keep-alive%s", VTY_NEWLINE);
-		vty_out(vty, "  loop %d%s",
-			trunk->audio_loop, VTY_NEWLINE);
-		vty_out(vty, "  force-realloc %d%s",
-			trunk->force_realloc, VTY_NEWLINE);
-		if (trunk->omit_rtcp)
-			vty_out(vty, "  rtcp-omit%s", VTY_NEWLINE);
-		else
-			vty_out(vty, "  no rtcp-omit%s", VTY_NEWLINE);
-		if (trunk->force_constant_ssrc || trunk->force_aligned_timing) {
-			vty_out(vty, "  %srtp-patch ssrc%s",
-				trunk->force_constant_ssrc ? "" : "no ", VTY_NEWLINE);
-			vty_out(vty, "  %srtp-patch timestamp%s",
-				trunk->force_aligned_timing ? "" : "no ", VTY_NEWLINE);
-		} else
-			vty_out(vty, "  no rtp-patch%s", VTY_NEWLINE);
-		if (trunk->audio_fmtp_extra)
-			vty_out(vty, "   sdp audio fmtp-extra %s%s",
-				trunk->audio_fmtp_extra, VTY_NEWLINE);
-		vty_out(vty, "  %sallow-transcoding%s",
-			trunk->no_audio_transcoding ? "no " : "", VTY_NEWLINE);
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_sdp_fmtp_extra,
-      cfg_trunk_sdp_fmtp_extra_cmd,
-      "sdp audio fmtp-extra .NAME",
-      "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
-      "Extra Information\n")
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	char *txt = argv_concat(argv, argc, 0);
-	if (!txt)
-		return CMD_WARNING;
-
-	osmo_talloc_replace_string(g_cfg, &trunk->audio_fmtp_extra, txt);
-	talloc_free(txt);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_payload_number,
-      cfg_trunk_payload_number_cmd,
-      "sdp audio-payload number <0-255>",
-      SDP_STR AUDIO_STR "Number\n" "Payload Number\n")
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	unsigned int payload = atoi(argv[0]);
-
-	trunk->audio_payload = payload;
-	return CMD_SUCCESS;
-}
-
-ALIAS_DEPRECATED(cfg_trunk_payload_number, cfg_trunk_payload_number_cmd_old,
-      "sdp audio payload number <0-255>",
-      SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload Number\n")
-
-DEFUN(cfg_trunk_payload_name,
-      cfg_trunk_payload_name_cmd,
-      "sdp audio-payload name NAME",
-       SDP_STR AUDIO_STR "Payload\n" "Payload Name\n")
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-
-	osmo_talloc_replace_string(g_cfg, &trunk->audio_name, argv[0]);
-	return CMD_SUCCESS;
-}
-
-ALIAS_DEPRECATED(cfg_trunk_payload_name, cfg_trunk_payload_name_cmd_old,
-      "sdp audio payload name NAME",
-       SDP_STR AUDIO_STR AUDIO_STR "Payload\n" "Payload Name\n")
-
-
-DEFUN(cfg_trunk_loop,
-      cfg_trunk_loop_cmd,
-      "loop (0|1)",
-      "Loop audio for all endpoints on this trunk\n"
-      "Don't Loop\n" "Loop\n")
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-
-	if (g_cfg->osmux) {
-		vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-	trunk->audio_loop = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_sdp_payload_send_ptime,
-      cfg_trunk_sdp_payload_send_ptime_cmd,
-      "sdp audio-payload send-ptime",
-      SDP_STR AUDIO_STR
-      "Send SDP ptime (packet duration) attribute\n")
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	trunk->audio_send_ptime = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_no_sdp_payload_send_ptime,
-      cfg_trunk_no_sdp_payload_send_ptime_cmd,
-      "no sdp audio-payload send-ptime",
-      NO_STR SDP_STR AUDIO_STR
-      "Send SDP ptime (packet duration) attribute\n")
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	trunk->audio_send_ptime = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_sdp_payload_send_name,
-      cfg_trunk_sdp_payload_send_name_cmd,
-      "sdp audio-payload send-name",
-      SDP_STR AUDIO_STR
-      "Send SDP rtpmap with the audio name\n")
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	trunk->audio_send_name = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_no_sdp_payload_send_name,
-      cfg_trunk_no_sdp_payload_send_name_cmd,
-      "no sdp audio-payload send-name",
-      NO_STR SDP_STR AUDIO_STR
-      "Send SDP rtpmap with the audio name\n")
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	trunk->audio_send_name = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_omit_rtcp,
-      cfg_trunk_omit_rtcp_cmd,
-      "rtcp-omit",
-      RTCP_OMIT_STR)
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	trunk->omit_rtcp = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_no_omit_rtcp,
-      cfg_trunk_no_omit_rtcp_cmd,
-      "no rtcp-omit",
-      NO_STR RTCP_OMIT_STR)
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	trunk->omit_rtcp = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_patch_rtp_ssrc,
-      cfg_trunk_patch_rtp_ssrc_cmd,
-      "rtp-patch ssrc",
-      RTP_PATCH_STR
-      "Force a fixed SSRC\n"
-      )
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	trunk->force_constant_ssrc = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_no_patch_rtp_ssrc,
-      cfg_trunk_no_patch_rtp_ssrc_cmd,
-      "no rtp-patch ssrc",
-      NO_STR RTP_PATCH_STR
-      "Force a fixed SSRC\n"
-      )
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	trunk->force_constant_ssrc = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_patch_rtp_ts,
-      cfg_trunk_patch_rtp_ts_cmd,
-      "rtp-patch timestamp",
-      RTP_PATCH_STR
-      "Adjust RTP timestamp\n"
-      )
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	trunk->force_aligned_timing = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_no_patch_rtp_ts,
-      cfg_trunk_no_patch_rtp_ts_cmd,
-      "no rtp-patch timestamp",
-      NO_STR RTP_PATCH_STR
-      "Adjust RTP timestamp\n"
-      )
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	trunk->force_aligned_timing = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_no_patch_rtp,
-      cfg_trunk_no_patch_rtp_cmd,
-      "no rtp-patch",
-      NO_STR RTP_PATCH_STR)
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	trunk->force_constant_ssrc = 0;
-	trunk->force_aligned_timing = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_rtp_keepalive,
-      cfg_trunk_rtp_keepalive_cmd,
-      "rtp keep-alive <1-120>",
-      RTP_STR RTP_KEEPALIVE_STR
-      "Keep-alive interval in secs\n"
-      )
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	mgcp_trunk_set_keepalive(trunk, atoi(argv[0]));
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_rtp_keepalive_once,
-      cfg_trunk_rtp_keepalive_once_cmd,
-      "rtp keep-alive once",
-      RTP_STR RTP_KEEPALIVE_STR
-      "Send dummy packet only once after CRCX/MDCX\n"
-      )
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_no_rtp_keepalive,
-      cfg_trunk_no_rtp_keepalive_cmd,
-      "no rtp keep-alive",
-      NO_STR RTP_STR RTP_KEEPALIVE_STR
-      )
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	mgcp_trunk_set_keepalive(trunk, 0);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_allow_transcoding,
-      cfg_trunk_allow_transcoding_cmd,
-      "allow-transcoding",
-      "Allow transcoding\n")
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	trunk->no_audio_transcoding = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trunk_no_allow_transcoding,
-      cfg_trunk_no_allow_transcoding_cmd,
-      "no allow-transcoding",
-      NO_STR "Allow transcoding\n")
-{
-	struct mgcp_trunk_config *trunk = vty->index;
-	trunk->no_audio_transcoding = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(loop_endp,
-      loop_endp_cmd,
-      "loop-endpoint <0-64> NAME (0|1)",
-      "Loop a given endpoint\n" "Trunk number\n"
-      "The name in hex of the endpoint\n" "Disable the loop\n" "Enable the loop\n")
-{
-	struct mgcp_trunk_config *trunk;
-	struct mgcp_endpoint *endp;
-
-	trunk = find_trunk(g_cfg, atoi(argv[0]));
-	if (!trunk) {
-		vty_out(vty, "%%Trunk %d not found in the config.%s",
-			atoi(argv[0]), VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (!trunk->endpoints) {
-		vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
-			trunk->trunk_nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	int endp_no = strtoul(argv[1], NULL, 16);
-	if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
-		vty_out(vty, "Loopback number %s/%d is invalid.%s",
-		argv[1], endp_no, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-
-	endp = &trunk->endpoints[endp_no];
-	int loop = atoi(argv[2]);
-
-	if (loop)
-		endp->conn_mode = MGCP_CONN_LOOPBACK;
-	else
-		endp->conn_mode = endp->orig_mode;
-
-	/* Handle it like a MDCX, switch on SSRC patching if enabled */
-	mgcp_rtp_end_config(endp, 1, &endp->bts_end);
-	mgcp_rtp_end_config(endp, 1, &endp->net_end);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(tap_call,
-      tap_call_cmd,
-      "tap-call <0-64> ENDPOINT (bts-in|bts-out|net-in|net-out) A.B.C.D <0-65534>",
-      "Forward data on endpoint to a different system\n" "Trunk number\n"
-      "The endpoint in hex\n"
-      "Forward the data coming from the bts\n"
-      "Forward the data coming from the bts leaving to the network\n"
-      "Forward the data coming from the net\n"
-      "Forward the data coming from the net leaving to the bts\n"
-      "destination IP of the data\n" "destination port\n")
-{
-	struct mgcp_rtp_tap *tap;
-	struct mgcp_trunk_config *trunk;
-	struct mgcp_endpoint *endp;
-	int port = 0;
-
-	trunk = find_trunk(g_cfg, atoi(argv[0]));
-	if (!trunk) {
-		vty_out(vty, "%%Trunk %d not found in the config.%s",
-			atoi(argv[0]), VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (!trunk->endpoints) {
-		vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
-			trunk->trunk_nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	int endp_no = strtoul(argv[1], NULL, 16);
-	if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
-		vty_out(vty, "Endpoint number %s/%d is invalid.%s",
-		argv[1], endp_no, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	endp = &trunk->endpoints[endp_no];
-
-	if (strcmp(argv[2], "bts-in") == 0) {
-		port = MGCP_TAP_BTS_IN;
-	} else if (strcmp(argv[2], "bts-out") == 0) {
-		port = MGCP_TAP_BTS_OUT;
-	} else if (strcmp(argv[2], "net-in") == 0) {
-		port = MGCP_TAP_NET_IN;
-	} else if (strcmp(argv[2], "net-out") == 0) {
-		port = MGCP_TAP_NET_OUT;
-	} else {
-		vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	tap = &endp->taps[port];
-	memset(&tap->forward, 0, sizeof(tap->forward));
-	inet_aton(argv[3], &tap->forward.sin_addr);
-	tap->forward.sin_port = htons(atoi(argv[4]));
-	tap->enabled = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(free_endp, free_endp_cmd,
-      "free-endpoint <0-64> NUMBER",
-      "Free the given endpoint\n" "Trunk number\n"
-      "Endpoint number in hex.\n")
-{
-	struct mgcp_trunk_config *trunk;
-	struct mgcp_endpoint *endp;
-
-	trunk = find_trunk(g_cfg, atoi(argv[0]));
-	if (!trunk) {
-		vty_out(vty, "%%Trunk %d not found in the config.%s",
-			atoi(argv[0]), VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (!trunk->endpoints) {
-		vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
-			trunk->trunk_nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	int endp_no = strtoul(argv[1], NULL, 16);
-	if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
-		vty_out(vty, "Endpoint number %s/%d is invalid.%s",
-		argv[1], endp_no, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	endp = &trunk->endpoints[endp_no];
-	mgcp_release_endp(endp);
-	return CMD_SUCCESS;
-}
-
-DEFUN(reset_endp, reset_endp_cmd,
-      "reset-endpoint <0-64> NUMBER",
-      "Reset the given endpoint\n" "Trunk number\n"
-      "Endpoint number in hex.\n")
-{
-	struct mgcp_trunk_config *trunk;
-	struct mgcp_endpoint *endp;
-	int endp_no, rc;
-
-	trunk = find_trunk(g_cfg, atoi(argv[0]));
-	if (!trunk) {
-		vty_out(vty, "%%Trunk %d not found in the config.%s",
-			atoi(argv[0]), VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (!trunk->endpoints) {
-		vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
-			trunk->trunk_nr, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	endp_no = strtoul(argv[1], NULL, 16);
-	if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
-		vty_out(vty, "Endpoint number %s/%d is invalid.%s",
-		argv[1], endp_no, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	endp = &trunk->endpoints[endp_no];
-	rc = mgcp_send_reset_ep(endp, ENDPOINT_NUMBER(endp));
-	if (rc < 0) {
-		vty_out(vty, "Error %d sending reset.%s", rc, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-	return CMD_SUCCESS;
-}
-
-DEFUN(reset_all_endp, reset_all_endp_cmd,
-      "reset-all-endpoints",
-      "Reset all endpoints\n")
-{
-	int rc;
-
-	rc = mgcp_send_reset_all(g_cfg);
-	if (rc < 0) {
-		vty_out(vty, "Error %d during endpoint reset.%s",
-			rc, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-	return CMD_SUCCESS;
-}
-
-#define OSMUX_STR "RTP multiplexing\n"
-DEFUN(cfg_mgcp_osmux,
-      cfg_mgcp_osmux_cmd,
-      "osmux (on|off|only)",
-       OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
-{
-	if (strcmp(argv[0], "off") == 0) {
-		g_cfg->osmux = OSMUX_USAGE_OFF;
-		return CMD_SUCCESS;
-	}
-
-	if (strcmp(argv[0], "on") == 0)
-		g_cfg->osmux = OSMUX_USAGE_ON;
-	else if (strcmp(argv[0], "only") == 0)
-		g_cfg->osmux = OSMUX_USAGE_ONLY;
-
-	if (g_cfg->trunk.audio_loop) {
-		vty_out(vty, "Cannot use `loop' with `osmux'.%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_osmux_ip,
-      cfg_mgcp_osmux_ip_cmd,
-      "osmux bind-ip A.B.C.D",
-      OSMUX_STR IP_STR "IPv4 Address to bind to\n")
-{
-	osmo_talloc_replace_string(g_cfg, &g_cfg->osmux_addr, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_osmux_batch_factor,
-      cfg_mgcp_osmux_batch_factor_cmd,
-      "osmux batch-factor <1-8>",
-      OSMUX_STR "Batching factor\n" "Number of messages in the batch\n")
-{
-	g_cfg->osmux_batch = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_osmux_batch_size,
-      cfg_mgcp_osmux_batch_size_cmd,
-      "osmux batch-size <1-65535>",
-      OSMUX_STR "batch size\n" "Batch size in bytes\n")
-{
-	g_cfg->osmux_batch_size = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_osmux_port,
-      cfg_mgcp_osmux_port_cmd,
-      "osmux port <1-65535>",
-      OSMUX_STR "port\n" "UDP port\n")
-{
-	g_cfg->osmux_port = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcp_osmux_dummy,
-      cfg_mgcp_osmux_dummy_cmd,
-      "osmux dummy (on|off)",
-      OSMUX_STR "Dummy padding\n" "Enable dummy padding\n" "Disable dummy padding\n")
-{
-	if (strcmp(argv[0], "on") == 0)
-		g_cfg->osmux_dummy = 1;
-	else if (strcmp(argv[0], "off") == 0)
-		g_cfg->osmux_dummy = 0;
-
-	return CMD_SUCCESS;
-}
-
-int mgcp_vty_init(void)
-{
-	install_element_ve(&show_mgcp_cmd);
-	install_element(ENABLE_NODE, &loop_endp_cmd);
-	install_element(ENABLE_NODE, &tap_call_cmd);
-	install_element(ENABLE_NODE, &free_endp_cmd);
-	install_element(ENABLE_NODE, &reset_endp_cmd);
-	install_element(ENABLE_NODE, &reset_all_endp_cmd);
-
-	install_element(CONFIG_NODE, &cfg_mgcp_cmd);
-	install_node(&mgcp_node, config_write_mgcp);
-
-	vty_install_default(MGCP_NODE);
-	install_element(MGCP_NODE, &cfg_mgcp_local_ip_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_bts_ip_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_bind_ip_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_bind_port_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_bind_early_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_rtp_base_port_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_base_port_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_rtp_net_base_port_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_range_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_bind_ip_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_rtp_no_bts_bind_ip_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_rtp_net_range_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_rtp_transcoder_range_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_rtp_transcoder_base_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_tos_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_rtp_force_ptime_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_no_rtp_force_ptime_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_once_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_no_rtp_keepalive_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd_old);
-	install_element(MGCP_NODE, &cfg_mgcp_transcoder_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_no_transcoder_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_transcoder_remote_base_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd_old);
-	install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd_old);
-	install_element(MGCP_NODE, &cfg_mgcp_loop_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_force_realloc_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_omit_rtcp_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_no_omit_rtcp_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ssrc_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ssrc_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ts_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ts_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_sdp_fmtp_extra_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_ptime_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_ptime_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_name_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_name_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_osmux_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_osmux_ip_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_factor_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_size_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_osmux_port_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_osmux_dummy_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_allow_transcoding_cmd);
-	install_element(MGCP_NODE, &cfg_mgcp_no_allow_transcoding_cmd);
-
-
-	install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd);
-	install_node(&trunk_node, config_write_trunk);
-	vty_install_default(TRUNK_NODE);
-	install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_once_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_no_rtp_keepalive_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd_old);
-	install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd_old);
-	install_element(TRUNK_NODE, &cfg_trunk_loop_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_omit_rtcp_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_no_omit_rtcp_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ssrc_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ssrc_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ts_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ts_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_sdp_fmtp_extra_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_ptime_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_ptime_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_name_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_name_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_allow_transcoding_cmd);
-	install_element(TRUNK_NODE, &cfg_trunk_no_allow_transcoding_cmd);
-
-	return 0;
-}
-
-static int allocate_trunk(struct mgcp_trunk_config *trunk)
-{
-	int i;
-	struct mgcp_config *cfg = trunk->cfg;
-
-	if (mgcp_endpoints_allocate(trunk) != 0) {
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Failed to allocate %d endpoints on trunk %d.\n",
-		     trunk->number_endpoints, trunk->trunk_nr);
-		return -1;
-	}
-
-	/* early bind */
-	for (i = 1; i < trunk->number_endpoints; ++i) {
-		struct mgcp_endpoint *endp = &trunk->endpoints[i];
-
-		if (cfg->bts_ports.mode == PORT_ALLOC_STATIC) {
-			cfg->last_bts_port += 2;
-			if (mgcp_bind_bts_rtp_port(endp, cfg->last_bts_port) != 0) {
-				LOGP(DMGCP, LOGL_FATAL,
-				     "Failed to bind: %d\n", cfg->last_bts_port);
-				return -1;
-			}
-			endp->bts_end.local_alloc = PORT_ALLOC_STATIC;
-		}
-
-		if (cfg->net_ports.mode == PORT_ALLOC_STATIC) {
-			cfg->last_net_port += 2;
-			if (mgcp_bind_net_rtp_port(endp, cfg->last_net_port) != 0) {
-				LOGP(DMGCP, LOGL_FATAL,
-				     "Failed to bind: %d\n", cfg->last_net_port);
-				return -1;
-			}
-			endp->net_end.local_alloc = PORT_ALLOC_STATIC;
-		}
-
-		if (trunk->trunk_type == MGCP_TRUNK_VIRTUAL &&
-		    cfg->transcoder_ip && cfg->transcoder_ports.mode == PORT_ALLOC_STATIC) {
-			int rtp_port;
-
-			/* network side */
-			rtp_port = rtp_calculate_port(ENDPOINT_NUMBER(endp),
-						      cfg->transcoder_ports.base_port);
-			if (mgcp_bind_trans_net_rtp_port(endp, rtp_port) != 0) {
-				LOGP(DMGCP, LOGL_FATAL, "Failed to bind: %d\n", rtp_port);
-				return -1;
-			}
-			endp->trans_net.local_alloc = PORT_ALLOC_STATIC;
-
-			/* bts side */
-			rtp_port = rtp_calculate_port(endp_back_channel(ENDPOINT_NUMBER(endp)),
-						      cfg->transcoder_ports.base_port);
-			if (mgcp_bind_trans_bts_rtp_port(endp, rtp_port) != 0) {
-				LOGP(DMGCP, LOGL_FATAL, "Failed to bind: %d\n", rtp_port);
-				return -1;
-			}
-			endp->trans_bts.local_alloc = PORT_ALLOC_STATIC;
-		}
-	}
-
-	return 0;
-}
-
-int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
-		      enum mgcp_role role)
-{
-	int rc;
-	struct mgcp_trunk_config *trunk;
-
-	cfg->osmux_port = OSMUX_PORT;
-	cfg->osmux_batch = 4;
-	cfg->osmux_batch_size = OSMUX_BATCH_DEFAULT_MAX;
-
-	g_cfg = cfg;
-	rc = vty_read_config_file(config_file, NULL);
-	if (rc < 0) {
-		fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
-		return rc;
-	}
-
-
-	if (!g_cfg->bts_ip)
-		fprintf(stderr, "No BTS ip address specified. This will allow everyone to connect.\n");
-
-	if (!g_cfg->source_addr) {
-		fprintf(stderr, "You need to specify a bind address.\n");
-		return -1;
-	}
-
-	/* initialize the last ports */
-	g_cfg->last_bts_port = rtp_calculate_port(0, g_cfg->bts_ports.base_port);
-	g_cfg->last_net_port = rtp_calculate_port(0, g_cfg->net_ports.base_port);
-
-	if (allocate_trunk(&g_cfg->trunk) != 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to initialize the virtual trunk.\n");
-		return -1;
-	}
-
-	llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
-		if (allocate_trunk(trunk) != 0) {
-			LOGP(DMGCP, LOGL_ERROR,
-			     "Failed to initialize E1 trunk %d.\n", trunk->trunk_nr);
-			return -1;
-		}
-	}
-	cfg->role = role;
-
-	return 0;
-}
-
diff --git a/src/libmgcp/mgcpgw_client.c b/src/libmgcp/mgcpgw_client.c
deleted file mode 100644
index 1910a9f..0000000
--- a/src/libmgcp/mgcpgw_client.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/* mgcp_utils - common functions to setup an MGCP connection
- */
-/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- * 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/>.
- *
- */
-
-#include <osmocom/core/select.h>
-#include <osmocom/core/write_queue.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/logging.h>
-
-#include <openbsc/mgcpgw_client.h>
-#include <openbsc/mgcp.h>
-#include <openbsc/mgcp_internal.h>
-#include <openbsc/debug.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-
-void mgcpgw_client_conf_init(struct mgcpgw_client_conf *conf)
-{
-	/* NULL and -1 default to MGCPGW_CLIENT_*_DEFAULT values */
-	*conf = (struct mgcpgw_client_conf){
-		.local_addr = NULL,
-		.local_port = -1,
-		.remote_addr = NULL,
-		.remote_port = -1,
-		.first_endpoint = 0,
-		.last_endpoint = 0,
-		.bts_base = 0,
-	};
-}
-
-/* Test if a given endpoint id is currently in use */
-static bool endpoint_in_use(uint16_t id, struct mgcpgw_client *client)
-{
-	struct mgcp_inuse_endpoint *endpoint;
-	llist_for_each_entry(endpoint, &client->inuse_endpoints, entry) {
-		if (endpoint->id == id)
-			return true;
-	}
-
-	return false;
-}
-
-/* Find and seize an unsused endpoint id */
-int mgcpgw_client_next_endpoint(struct mgcpgw_client *client)
-{
-	int i;
-	uint16_t first_endpoint = client->actual.first_endpoint;
-	uint16_t last_endpoint = client->actual.last_endpoint;
-	struct mgcp_inuse_endpoint *endpoint;
-
-	/* Use the maximum permitted range if the VTY
-	 * configuration does not specify a range */
-	if (client->actual.last_endpoint == 0) {
-		first_endpoint = 1;
-		last_endpoint = 65534;
-	}
-
-	/* Test the permitted endpoint range for an endpoint
-	 * number that is not in use. When a suitable endpoint
-	 * number can be found, seize it by adding it to the
-	 * inuse list. */
-	for (i=first_endpoint;i<last_endpoint;i++)
-	{
-		if (endpoint_in_use(i,client) == false) {
-			endpoint = talloc_zero(client, struct mgcp_inuse_endpoint);
-			endpoint->id = i;
-			llist_add_tail(&endpoint->entry, &client->inuse_endpoints);
-			return endpoint->id;
-		}
-	}
-
-	/* All endpoints are busy! */
-	return -EINVAL;
-}
-
-/* Release a seized endpoint id to make it available again for other calls */
-void mgcpgw_client_release_endpoint(uint16_t id, struct mgcpgw_client *client)
-{
-	struct mgcp_inuse_endpoint *endpoint;
-	struct mgcp_inuse_endpoint *endpoint_tmp;
-	llist_for_each_entry_safe(endpoint, endpoint_tmp, &client->inuse_endpoints, entry) {
-		if (endpoint->id == id) {
-			llist_del(&endpoint->entry);
-			talloc_free(endpoint);
-		}
-	}
-}
-
-static void mgcpgw_client_handle_response(struct mgcpgw_client *mgcp,
-					  struct mgcp_response_pending *pending,
-					  struct mgcp_response *response)
-{
-	if (!pending) {
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Cannot handle NULL response\n");
-		return;
-	}
-	if (pending->response_cb)
-		pending->response_cb(response, pending->priv);
-	else
-		LOGP(DMGCP, LOGL_INFO, "MGCP response ignored (NULL cb)\n");
-	talloc_free(pending);
-}
-
-static int mgcp_response_parse_head(struct mgcp_response *r, struct msgb *msg)
-{
-	int comment_pos;
-	char *end;
-
-	if (mgcp_msg_terminate_nul(msg))
-		goto response_parse_failure;
-
-	r->body = (char *)msg->data;
-
-        if (sscanf(r->body, "%3d %u %n",
-		   &r->head.response_code, &r->head.trans_id,
-		   &comment_pos) != 2)
-		goto response_parse_failure;
-
-	r->head.comment = r->body + comment_pos;
-	end = strchr(r->head.comment, '\r');
-	if (!end)
-		goto response_parse_failure;
-	/* Mark the end of the comment */
-	*end = '\0';
-	r->body = end + 1;
-	if (r->body[0] == '\n')
-		r->body ++;
-	return 0;
-
-response_parse_failure:
-	LOGP(DMGCP, LOGL_ERROR,
-	     "Failed to parse MGCP response header\n");
-	return -EINVAL;
-}
-
-/* TODO undup against mgcp_protocol.c:mgcp_check_param() */
-static bool mgcp_line_is_valid(const char *line)
-{
-	const size_t line_len = strlen(line);
-	if (line[0] == '\0')
-		return true;
-
-	if (line_len < 2
-	    || line[1] != '=') {
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Wrong MGCP option format: '%s'\n",
-		     line);
-		return false;
-	}
-
-	return true;
-}
-
-/* Parse a line like "m=audio 16002 RTP/AVP 98" */
-static int mgcp_parse_audio(struct mgcp_response *r, const char *line)
-{
-        if (sscanf(line, "m=audio %hu",
-		   &r->audio_port) != 1)
-		goto response_parse_failure;
-
-	return 0;
-
-response_parse_failure:
-	LOGP(DMGCP, LOGL_ERROR,
-	     "Failed to parse MGCP response header\n");
-	return -EINVAL;
-}
-
-int mgcp_response_parse_params(struct mgcp_response *r)
-{
-	char *line;
-	int rc;
-	OSMO_ASSERT(r->body);
-	char *data = strstr(r->body, "\n\n");
-
-	if (!data) {
-		LOGP(DMGCP, LOGL_ERROR,
-		     "MGCP response: cannot find start of parameters\n");
-		return -EINVAL;
-	}
-
-	/* Advance to after the \n\n, replace the second \n with \0. That's
-	 * where the parameters start. */
-	data ++;
-	*data = '\0';
-	data ++;
-
-	for_each_line(line, data) {
-		if (!mgcp_line_is_valid(line))
-			return -EINVAL;
-
-		switch (line[0]) {
-		case 'm':
-			rc = mgcp_parse_audio(r, line);
-			if (rc)
-				return rc;
-			break;
-		default:
-			/* skip unhandled parameters */
-			break;
-		}
-	}
-	return 0;
-}
-
-static struct mgcp_response_pending *mgcpgw_client_response_pending_get(
-					 struct mgcpgw_client *mgcp,
-					 struct mgcp_response *r)
-{
-	struct mgcp_response_pending *pending;
-	if (!r)
-		return NULL;
-	llist_for_each_entry(pending, &mgcp->responses_pending, entry) {
-		if (pending->trans_id == r->head.trans_id) {
-			llist_del(&pending->entry);
-			return pending;
-		}
-	}
-	return NULL;
-}
-
-/* Feed an MGCP message into the receive processing.
- * Parse the head and call any callback registered for the transaction id found
- * in the MGCP message. This is normally called directly from the internal
- * mgcp_do_read that reads from the socket connected to the MGCP gateway. This
- * function is published mainly to be able to feed data from the test suite.
- */
-int mgcpgw_client_rx(struct mgcpgw_client *mgcp, struct msgb *msg)
-{
-	struct mgcp_response r = { 0 };
-	struct mgcp_response_pending *pending;
-	int rc;
-
-	rc = mgcp_response_parse_head(&r, msg);
-	if (rc) {
-		LOGP(DMGCP, LOGL_ERROR, "Cannot parse MGCP response\n");
-		return -1;
-	}
-
-	pending = mgcpgw_client_response_pending_get(mgcp, &r);
-	if (!pending) {
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Cannot find matching MGCP transaction for trans_id %d\n",
-		     r.head.trans_id);
-		return -1;
-	}
-
-	mgcpgw_client_handle_response(mgcp, pending, &r);
-	return 0;
-}
-
-static int mgcp_do_read(struct osmo_fd *fd)
-{
-	struct mgcpgw_client *mgcp = fd->data;
-	struct msgb *msg;
-	int ret;
-
-	msg = msgb_alloc_headroom(4096, 128, "mgcp_from_gw");
-	if (!msg) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to allocate MGCP message.\n");
-		return -1;
-	}
-
-	ret = read(fd->fd, msg->data, 4096 - 128);
-	if (ret <= 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to read: %d/%s\n", errno, strerror(errno));
-		msgb_free(msg);
-		return -1;
-	} else if (ret > 4096 - 128) {
-		LOGP(DMGCP, LOGL_ERROR, "Too much data: %d\n", ret);
-		msgb_free(msg);
-		return -1;
-        }
-
-	msg->l2h = msgb_put(msg, ret);
-	ret = mgcpgw_client_rx(mgcp, msg);
-	talloc_free(msg);
-	return ret;
-}
-
-static int mgcp_do_write(struct osmo_fd *fd, struct msgb *msg)
-{
-	int ret;
-	static char strbuf[4096];
-	unsigned int l = msg->len < sizeof(strbuf) ? msg->len : sizeof(strbuf);
-	unsigned int i;
-
-	strncpy(strbuf, (const char*)msg->data, l);
-	for (i = 0; i < sizeof(strbuf); i++) {
-		if (strbuf[i] == '\n' || strbuf[i] == '\r') {
-			strbuf[i] = '\0';
-			break;
-		}
-	}
-	DEBUGP(DMGCP, "Tx MGCP msg to MGCP GW: '%s'\n", strbuf);
-
-	LOGP(DMGCP, LOGL_DEBUG, "Sending msg to MGCP GW size: %u\n", msg->len);
-
-	ret = write(fd->fd, msg->data, msg->len);
-	if (ret != msg->len)
-		LOGP(DMGCP, LOGL_ERROR, "Failed to forward message to MGCP"
-		     " GW: %s\n", strerror(errno));
-
-	return ret;
-}
-
-struct mgcpgw_client *mgcpgw_client_init(void *ctx,
-					 struct mgcpgw_client_conf *conf)
-{
-	struct mgcpgw_client *mgcp;
-
-	mgcp = talloc_zero(ctx, struct mgcpgw_client);
-
-	INIT_LLIST_HEAD(&mgcp->responses_pending);
-	INIT_LLIST_HEAD(&mgcp->inuse_endpoints);
-
-	mgcp->next_trans_id = 1;
-
-	mgcp->actual.local_addr = conf->local_addr ? conf->local_addr :
-		MGCPGW_CLIENT_LOCAL_ADDR_DEFAULT;
-	mgcp->actual.local_port = conf->local_port >= 0 ? (uint16_t)conf->local_port :
-		MGCPGW_CLIENT_LOCAL_PORT_DEFAULT;
-
-	mgcp->actual.remote_addr = conf->remote_addr ? conf->remote_addr :
-		MGCPGW_CLIENT_REMOTE_ADDR_DEFAULT;
-	mgcp->actual.remote_port = conf->remote_port >= 0 ? (uint16_t)conf->remote_port :
-		MGCPGW_CLIENT_REMOTE_PORT_DEFAULT;
-
-	mgcp->actual.first_endpoint = conf->first_endpoint > 0 ? (uint16_t)conf->first_endpoint : 0;
-	mgcp->actual.last_endpoint = conf->last_endpoint > 0 ? (uint16_t)conf->last_endpoint : 0;
-	mgcp->actual.bts_base = conf->bts_base > 0 ? (uint16_t)conf->bts_base : 4000;
-
-	return mgcp;
-}
-
-int mgcpgw_client_connect(struct mgcpgw_client *mgcp)
-{
-	int on;
-	struct sockaddr_in addr;
-	struct osmo_wqueue *wq;
-	int rc;
-
-	if (!mgcp) {
-		LOGP(DMGCP, LOGL_FATAL, "MGCPGW client not initialized properly\n");
-		return -EINVAL;
-	}
-
-	wq = &mgcp->wq;
-
-	wq->bfd.fd = socket(AF_INET, SOCK_DGRAM, 0);
-	if (wq->bfd.fd < 0) {
-		LOGP(DMGCP, LOGL_FATAL, "Failed to create UDP socket errno: %d\n", errno);
-		return -errno;
-	}
-
-	on = 1;
-	if (setsockopt(wq->bfd.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
-		LOGP(DMGCP, LOGL_FATAL,
-		     "Failed to initialize socket for MGCP GW: %s\n",
-		     strerror(errno));
-		rc = -errno;
-		goto error_close_fd;
-	}
-
-	/* bind socket */
-	memset(&addr, 0, sizeof(addr));
-	addr.sin_family = AF_INET;
-	inet_aton(mgcp->actual.local_addr, &addr.sin_addr);
-	addr.sin_port = htons(mgcp->actual.local_port);
-	if (bind(wq->bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		LOGP(DMGCP, LOGL_FATAL,
-		     "Failed to bind for MGCP GW to %s %u\n",
-		     mgcp->actual.local_addr, mgcp->actual.local_port);
-		rc = -errno;
-		goto error_close_fd;
-	}
-
-	/* connect to the remote */
-	inet_aton(mgcp->actual.remote_addr, &addr.sin_addr);
-	addr.sin_port = htons(mgcp->actual.remote_port);
-	if (connect(wq->bfd.fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-		LOGP(DMGCP, LOGL_FATAL,
-		     "Failed to connect to MGCP GW at %s %u: %s\n",
-		     mgcp->actual.remote_addr, mgcp->actual.remote_port,
-		     strerror(errno));
-		rc = -errno;
-		goto error_close_fd;
-	}
-
-	mgcp->remote_addr = htonl(addr.sin_addr.s_addr);
-
-	osmo_wqueue_init(wq, 10);
-	wq->bfd.when = BSC_FD_READ;
-	wq->bfd.data = mgcp;
-	wq->read_cb = mgcp_do_read;
-	wq->write_cb = mgcp_do_write;
-
-	if (osmo_fd_register(&wq->bfd) != 0) {
-		LOGP(DMGCP, LOGL_FATAL, "Failed to register BFD\n");
-		rc = -EIO;
-		goto error_close_fd;
-	}
-	LOGP(DMGCP, LOGL_INFO, "MGCP GW connection: %s:%u -> %s:%u\n",
-	     mgcp->actual.local_addr, mgcp->actual.local_port,
-	     mgcp->actual.remote_addr, mgcp->actual.remote_port);
-
-	return 0;
-error_close_fd:
-	close(wq->bfd.fd);
-	wq->bfd.fd = -1;
-	return rc;
-}
-
-const char *mgcpgw_client_remote_addr_str(struct mgcpgw_client *mgcp)
-{
-	return mgcp->actual.remote_addr;
-}
-
-uint16_t mgcpgw_client_remote_port(struct mgcpgw_client *mgcp)
-{
-	return mgcp->actual.remote_port;
-}
-
-/* Return the MGCP GW binary IPv4 address in network byte order. */
-uint32_t mgcpgw_client_remote_addr_n(struct mgcpgw_client *mgcp)
-{
-	return mgcp->remote_addr;
-}
-
-struct mgcp_response_pending * mgcpgw_client_pending_add(
-					struct mgcpgw_client *mgcp,
-					mgcp_trans_id_t trans_id,
-					mgcp_response_cb_t response_cb,
-					void *priv)
-{
-	struct mgcp_response_pending *pending;
-
-	pending = talloc_zero(mgcp, struct mgcp_response_pending);
-	pending->trans_id = trans_id;
-	pending->response_cb = response_cb;
-	pending->priv = priv;
-	llist_add_tail(&pending->entry, &mgcp->responses_pending);
-
-	return pending;
-}
-
-/* Send the MGCP message in msg to the MGCP GW and handle a response with
- * response_cb. NOTE: the response_cb still needs to call
- * mgcp_response_parse_params(response) to get the parsed parameters -- to
- * potentially save some CPU cycles, only the head line has been parsed when
- * the response_cb is invoked. */
-int mgcpgw_client_tx(struct mgcpgw_client *mgcp, struct msgb *msg,
-		     mgcp_response_cb_t response_cb, void *priv)
-{
-	struct mgcp_response_pending *pending;
-	mgcp_trans_id_t trans_id;
-	int rc;
-
-	trans_id = msg->cb[MSGB_CB_MGCP_TRANS_ID];
-	if (!trans_id) {
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Unset transaction id in mgcp send request\n");
-		talloc_free(msg);
-		return -EINVAL;
-	}
-
-	pending = mgcpgw_client_pending_add(mgcp, trans_id, response_cb, priv);
-
-	if (msgb_l2len(msg) > 4096) {
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Cannot send, MGCP message too large: %u\n",
-		     msgb_l2len(msg));
-		msgb_free(msg);
-		rc = -EINVAL;
-		goto mgcp_tx_error;
-	}
-
-	rc = osmo_wqueue_enqueue(&mgcp->wq, msg);
-	if (rc) {
-		LOGP(DMGCP, LOGL_FATAL, "Could not queue message to MGCP GW\n");
-		msgb_free(msg);
-		goto mgcp_tx_error;
-	} else
-		LOGP(DMGCP, LOGL_INFO, "Queued %u bytes for MGCP GW\n",
-		     msgb_l2len(msg));
-	return 0;
-
-mgcp_tx_error:
-	/* Pass NULL to response cb to indicate an error */
-	mgcpgw_client_handle_response(mgcp, pending, NULL);
-	return -1;
-}
-
-static struct msgb *mgcp_msg_from_buf(mgcp_trans_id_t trans_id,
-				      const char *buf, int len)
-{
-	struct msgb *msg;
-
-	if (len > (4096 - 128)) {
-		LOGP(DMGCP, LOGL_ERROR, "Cannot send to MGCP GW:"
-		     " message too large: %d\n", len);
-		return NULL;
-	}
-
-	msg = msgb_alloc_headroom(4096, 128, "MGCP tx");
-	OSMO_ASSERT(msg);
-
-	char *dst = (char*)msgb_put(msg, len);
-	memcpy(dst, buf, len);
-	msg->l2h = msg->data;
-	msg->cb[MSGB_CB_MGCP_TRANS_ID] = trans_id;
-
-	return msg;
-}
-
-static struct msgb *mgcp_msg_from_str(mgcp_trans_id_t trans_id,
-				      const char *fmt, ...)
-{
-	static char compose[4096 - 128];
-	va_list ap;
-	int len;
-	OSMO_ASSERT(fmt);
-
-	va_start(ap, fmt);
-	len = vsnprintf(compose, sizeof(compose), fmt, ap);
-	va_end(ap);
-	if (len >= sizeof(compose)) {
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Message too large: trans_id=%u len=%d\n",
-		     trans_id, len);
-		return NULL;
-	}
-	if (len < 1) {
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Failed to compose message: trans_id=%u len=%d\n",
-		     trans_id, len);
-		return NULL;
-	}
-	return mgcp_msg_from_buf(trans_id, compose, len);
-}
-
-static mgcp_trans_id_t mgcpgw_client_next_trans_id(struct mgcpgw_client *mgcp)
-{
-	/* avoid zero trans_id to distinguish from unset trans_id */
-	if (!mgcp->next_trans_id)
-		mgcp->next_trans_id ++;
-	return mgcp->next_trans_id ++;
-}
-
-struct msgb *mgcp_msg_crcx(struct mgcpgw_client *mgcp,
-			   uint16_t rtp_endpoint, unsigned int call_id,
-			   enum mgcp_connection_mode mode)
-{
-	mgcp_trans_id_t trans_id = mgcpgw_client_next_trans_id(mgcp);
-	return mgcp_msg_from_str(trans_id,
-		 "CRCX %u %x@mgw MGCP 1.0\r\n"
-		 "C: %x\r\n"
-		 "L: p:20, a:AMR, nt:IN\r\n"
-		 "M: %s\r\n"
-		 ,
-		 trans_id,
-		 rtp_endpoint,
-		 call_id,
-		 mgcp_cmode_name(mode));
-}
-
-struct msgb *mgcp_msg_mdcx(struct mgcpgw_client *mgcp,
-			   uint16_t rtp_endpoint, const char *rtp_conn_addr,
-			   uint16_t rtp_port, enum mgcp_connection_mode mode)
-
-{
-	mgcp_trans_id_t trans_id = mgcpgw_client_next_trans_id(mgcp);
-	return mgcp_msg_from_str(trans_id,
-		 "MDCX %u %x@mgw MGCP 1.0\r\n"
-		 "M: %s\r\n"
-		 "\r\n"
-		 "c=IN IP4 %s\r\n"
-		 "m=audio %u RTP/AVP 255\r\n"
-		 ,
-		 trans_id,
-		 rtp_endpoint,
-		 mgcp_cmode_name(mode),
-		 rtp_conn_addr,
-		 rtp_port);
-}
-
-struct msgb *mgcp_msg_dlcx(struct mgcpgw_client *mgcp, uint16_t rtp_endpoint,
-			   unsigned int call_id)
-{
-	mgcp_trans_id_t trans_id = mgcpgw_client_next_trans_id(mgcp);
-	return mgcp_msg_from_str(trans_id,
-				 "DLCX %u %x@mgw MGCP 1.0\r\n"
-				 "C: %x\r\n", trans_id, rtp_endpoint, call_id);
-}
diff --git a/src/libmgcp/mgcpgw_client_vty.c b/src/libmgcp/mgcpgw_client_vty.c
deleted file mode 100644
index 8068000..0000000
--- a/src/libmgcp/mgcpgw_client_vty.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/* MGCPGW client interface to quagga VTY */
-/* (C) 2016 by sysmocom s.m.f.c. GmbH <info@sysmocom.de>
- * Based on OpenBSC interface to quagga VTY (libmsc/vty_interface_layer3.c)
- * (C) 2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009-2011 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/>.
- *
- */
-
-#include <inttypes.h>
-#include <stdlib.h>
-#include <talloc.h>
-
-#include <osmocom/vty/command.h>
-
-#include <openbsc/vty.h>
-#include <openbsc/mgcpgw_client.h>
-
-#define MGCPGW_STR "MGCP gateway configuration for RTP streams\n"
-
-struct mgcpgw_client_conf *global_mgcpgw_client_conf = NULL;
-
-DEFUN(cfg_mgcpgw_local_ip, cfg_mgcpgw_local_ip_cmd,
-      "mgcpgw local-ip A.B.C.D",
-      MGCPGW_STR "local bind to connect to MGCP gateway with\n"
-      "local bind IP address\n")
-{
-	if (!global_mgcpgw_client_conf)
-		return CMD_ERR_NOTHING_TODO;
-	global_mgcpgw_client_conf->local_addr =
-		talloc_strdup(gsmnet_from_vty(vty), argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcpgw_local_port, cfg_mgcpgw_local_port_cmd,
-      "mgcpgw local-port <0-65535>",
-      MGCPGW_STR "local bind to connect to MGCP gateway with\n"
-      "local bind port\n")
-{
-	if (!global_mgcpgw_client_conf)
-		return CMD_ERR_NOTHING_TODO;
-	global_mgcpgw_client_conf->local_port = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcpgw_remote_ip, cfg_mgcpgw_remote_ip_cmd,
-      "mgcpgw remote-ip A.B.C.D",
-      MGCPGW_STR "remote bind to connect to MGCP gateway with\n"
-      "remote bind IP address\n")
-{
-	if (!global_mgcpgw_client_conf)
-		return CMD_ERR_NOTHING_TODO;
-	global_mgcpgw_client_conf->remote_addr =
-		talloc_strdup(gsmnet_from_vty(vty), argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcpgw_remote_port, cfg_mgcpgw_remote_port_cmd,
-      "mgcpgw remote-port <0-65535>",
-      MGCPGW_STR "remote bind to connect to MGCP gateway with\n"
-      "remote bind port\n")
-{
-	if (!global_mgcpgw_client_conf)
-		return CMD_ERR_NOTHING_TODO;
-	global_mgcpgw_client_conf->remote_port = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_mgcpgw_endpoint_range, cfg_mgcpgw_endpoint_range_cmd,
-      "mgcpgw endpoint-range <1-65534> <1-65534>",
-      MGCPGW_STR "usable range of endpoint identifiers\n"
-      "set first useable endpoint identifier\n"
-      "set the last useable endpoint identifier\n")
-{
-	uint16_t first_endpoint = atoi(argv[0]);
-	uint16_t last_endpoint = atoi(argv[1]);
-
-	if (last_endpoint < first_endpoint) {
-		vty_out(vty, "last endpoint must be greater than first endpoint!%s",
-			VTY_NEWLINE);
-		return CMD_SUCCESS;
-	}
-
-	global_mgcpgw_client_conf->first_endpoint = first_endpoint;
-	global_mgcpgw_client_conf->last_endpoint = last_endpoint;
-	return CMD_SUCCESS;
-}
-
-#define BTS_START_STR "First UDP port allocated for the BTS side\n"
-#define UDP_PORT_STR "UDP Port number\n"
-DEFUN(cfg_mgcp_rtp_bts_base_port,
-      cfg_mgcp_rtp_bts_base_port_cmd,
-      "mgcpgw bts-base <0-65534>",
-      MGCPGW_STR
-      BTS_START_STR
-      UDP_PORT_STR)
-{
-	global_mgcpgw_client_conf->bts_base = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-int mgcpgw_client_config_write(struct vty *vty, const char *indent)
-{
-	const char *addr;
-	int port;
-	uint16_t first_endpoint;
-	uint16_t last_endpoint;
-	uint16_t bts_base;
-
-	addr = global_mgcpgw_client_conf->local_addr;
-	if (addr)
-		vty_out(vty, "%smgcpgw local-ip %s%s", indent, addr,
-			VTY_NEWLINE);
-	port = global_mgcpgw_client_conf->local_port;
-	if (port >= 0)
-		vty_out(vty, "%smgcpgw local-port %u%s", indent,
-			(uint16_t)port, VTY_NEWLINE);
-
-	addr = global_mgcpgw_client_conf->remote_addr;
-	if (addr)
-		vty_out(vty, "%smgcpgw remote-ip %s%s", indent, addr,
-			VTY_NEWLINE);
-	port = global_mgcpgw_client_conf->remote_port;
-	if (port >= 0)
-		vty_out(vty, "%smgcpgw remote-port %u%s", indent,
-			(uint16_t)port, VTY_NEWLINE);
-
-	first_endpoint = global_mgcpgw_client_conf->first_endpoint;
-	last_endpoint = global_mgcpgw_client_conf->last_endpoint;
-	if (last_endpoint != 0) {
-		vty_out(vty, "%smgcpgw endpoint-range %u %u%s", indent,
-			first_endpoint, last_endpoint, VTY_NEWLINE);
-	}
-
-	bts_base = global_mgcpgw_client_conf->bts_base;
-	if (bts_base) {
-		vty_out(vty, "%smgcpgw bts-base %u%s", indent,
-			bts_base, VTY_NEWLINE);
-	}
-
-	return CMD_SUCCESS;
-}
-
-void mgcpgw_client_vty_init(int node, struct mgcpgw_client_conf *conf)
-{
-	global_mgcpgw_client_conf = conf;
-
-	install_element(node, &cfg_mgcpgw_local_ip_cmd);
-	install_element(node, &cfg_mgcpgw_local_port_cmd);
-	install_element(node, &cfg_mgcpgw_remote_ip_cmd);
-	install_element(node, &cfg_mgcpgw_remote_port_cmd);
-	install_element(node, &cfg_mgcpgw_endpoint_range_cmd);
-	install_element(node, &cfg_mgcp_rtp_bts_base_port_cmd);
-}
diff --git a/src/libmsc/Makefile.am b/src/libmsc/Makefile.am
deleted file mode 100644
index c9b8bb4..0000000
--- a/src/libmsc/Makefile.am
+++ /dev/null
@@ -1,75 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	-I$(top_builddir) \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOVTY_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(LIBCRYPTO_CFLAGS) \
-	$(LIBSMPP34_CFLAGS) \
-	$(LIBASN1C_CFLAGS) \
-	$(LIBOSMOSIGTRAN_CFLAGS) \
-	$(NULL)
-
-noinst_HEADERS = \
-	meas_feed.h \
-	$(NULL)
-
-noinst_LIBRARIES = \
-	libmsc.a \
-	$(NULL)
-
-libmsc_a_SOURCES = \
-	a_iface.c \
-	a_iface_bssap.c \
-	auth.c \
-	msc_vty.c \
-	db.c \
-	gsm_04_08.c \
-	gsm_04_11.c \
-	gsm_04_14.c \
-	gsm_04_80.c \
-	gsm_subscriber.c \
-	mncc.c \
-	mncc_builtin.c \
-	mncc_sock.c \
-	msc_ifaces.c \
-	rrlp.c \
-	silent_call.c \
-	sms_queue.c \
-	ussd.c \
-	vty_interface_layer3.c \
-	transaction.c \
-	osmo_msc.c \
-	ctrl_commands.c \
-	meas_feed.c \
-	subscr_conn.c \
-	$(NULL)
-if BUILD_IU
-libmsc_a_SOURCES += \
-	iucs.c \
-	iucs_ranap.c \
-	$(NULL)
-else
-libmsc_a_SOURCES += \
-	iu_dummy.c \
-	$(NULL)
-endif
-
-if BUILD_SMPP
-noinst_HEADERS += \
-	smpp_smsc.h \
-	$(NULL)
-
-libmsc_a_SOURCES += \
-	smpp_smsc.c \
-	smpp_openbsc.c \
-	smpp_vty.c \
-	smpp_utils.c \
-	$(NULL)
-endif
diff --git a/src/libmsc/a_iface.c b/src/libmsc/a_iface.c
deleted file mode 100644
index 93e8ab5..0000000
--- a/src/libmsc/a_iface.c
+++ /dev/null
@@ -1,591 +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/>.
- *
- */
-
-#include <osmocom/core/utils.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/logging.h>
-#include <osmocom/sigtran/sccp_helpers.h>
-#include <osmocom/sigtran/sccp_sap.h>
-#include <osmocom/sigtran/osmo_ss7.h>
-#include <osmocom/sigtran/protocol/m3ua.h>
-#include <osmocom/gsm/gsm0808.h>
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-#include <osmocom/gsm/protocol/gsm_04_08.h>
-#include <osmocom/gsm/gsm0808_utils.h>
-#include <openbsc/debug.h>
-#include <openbsc/msc_ifaces.h>
-#include <openbsc/a_iface.h>
-#include <openbsc/a_iface_bssap.h>
-#include <openbsc/transaction.h>
-#include <openbsc/mgcpgw_client.h>
-#include <osmocom/core/byteswap.h>
-#include <osmocom/sccp/sccp_types.h>
-#include <openbsc/a_reset.h>
-#include <openbsc/osmo_msc.h>
-
-/* A pointer to the GSM network we work with. By the current paradigm,
- * there can only be one gsm_network per MSC. The pointer is set once
- * when calling a_init() */
-static struct gsm_network *gsm_network = NULL;
-
-/* A struct to track currently active connections. We need that information
- * to handle failure sitautions. In case of a problem, we must know which
- * connections are currently open and which BSC is responsible. We also need
- * the data to perform our connection checks (a_reset). All other logic will
- * look at the connection ids and addresses that are supplied by the
- * primitives */
-struct bsc_conn {
-	struct llist_head list;
-	uint32_t conn_id;			/* Connection identifier */
-};
-
-/* Internal list with connections we currently maintain. This
- * list is of type struct bsc_conn (see above) */
-static LLIST_HEAD(active_connections);
-
-/* Record info of a new active connection in the active connection list */
-static void record_bsc_con(const void *ctx, uint32_t conn_id)
-{
-	struct bsc_conn *conn;
-
-	conn = talloc_zero(ctx, struct bsc_conn);
-	OSMO_ASSERT(conn);
-
-	conn->conn_id = conn_id;
-
-	llist_add_tail(&conn->list, &active_connections);
-}
-
-/* Delete info of a closed connection from the active connection list */
-void a_delete_bsc_con(uint32_t conn_id)
-{
-	struct bsc_conn *conn;
-	struct bsc_conn *conn_temp;
-
-	LOGP(DMSC, LOGL_DEBUG,
-	     "Removing connection from active sccp-connection list (conn_id=%i)\n",
-	     conn_id);
-
-	llist_for_each_entry_safe(conn, conn_temp, &active_connections, list) {
-		if (conn->conn_id == conn_id) {
-			llist_del(&conn->list);
-			talloc_free(conn);
-		}
-	}
-}
-
-/* Check if a specified connection id has an active SCCP connection */
-static bool check_connection_active(uint32_t conn_id)
-{
-	struct bsc_conn *conn;
-
-	/* Find the address for the current connection id */
-	llist_for_each_entry(conn, &active_connections, list) {
-		if (conn->conn_id == conn_id) {
-			return true;
-		}
-	}
-
-	return false;
-}
-
-/* Get the reset context for a specifiec calling (BSC) address */
-static struct a_reset_ctx *get_reset_ctx_by_sccp_addr(const struct osmo_sccp_addr *addr)
-{
-	struct bsc_context *bsc_ctx;
-	struct osmo_ss7_instance *ss7;
-
-	if (!addr)
-		return NULL;
-
-	llist_for_each_entry(bsc_ctx, &gsm_network->a.bscs, list) {
-		if (memcmp(&bsc_ctx->bsc_addr, addr, sizeof(*addr)) == 0)
-			return bsc_ctx->reset;
-	}
-
-	ss7 = osmo_ss7_instance_find(gsm_network->a.cs7_instance);
-	OSMO_ASSERT(ss7);
-	LOGP(DMSC, LOGL_ERROR, "The calling BSC (%s) is unknown to this MSC ...\n",
-	     osmo_sccp_addr_name(ss7, addr));
-	return NULL;
-}
-
-/* Send DTAP message via A-interface */
-int a_iface_tx_dtap(struct msgb *msg)
-{
-	struct gsm_subscriber_connection *conn;
-	struct msgb *msg_resp;
-
-	/* FIXME: Set this to some meaninful value! */
-	uint8_t link_id = 0x00;
-	OSMO_ASSERT(msg);
-	conn = (struct gsm_subscriber_connection *)msg->dst;
-	OSMO_ASSERT(conn);
-	OSMO_ASSERT(conn->a.scu);
-
-	LOGP(DMSC, LOGL_DEBUG, "Passing DTAP message from MSC to BSC (conn_id=%i)\n", conn->a.conn_id);
-
-	msg->l3h = msg->data;
-	msg_resp = gsm0808_create_dtap(msg, link_id);
-	if (!msg_resp) {
-		LOGP(DMSC, LOGL_ERROR, "Unable to generate BSSMAP DTAP message!\n");
-		return -EINVAL;
-	} else
-		LOGP(DMSC, LOGL_DEBUG, "Massage will be sent as BSSMAP DTAP message!\n");
-
-	LOGP(DMSC, LOGL_DEBUG, "N-DATA.req(%u, %s)\n", conn->a.conn_id, osmo_hexdump(msg_resp->data, msg_resp->len));
-	return osmo_sccp_tx_data_msg(conn->a.scu, conn->a.conn_id, msg_resp);
-}
-
-/* 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)
-{
-	/* TODO generalize for A- and Iu interfaces, don't name after 08.08 */
-	struct msgb *msg_resp;
-	struct gsm0808_encrypt_info ei;
-
-	OSMO_ASSERT(conn);
-
-	LOGP(DMSC, LOGL_DEBUG, "Passing Cipher mode command message from MSC to BSC (conn_id=%i)\n", conn->a.conn_id);
-	uint8_t crm = 0x01;
-	uint8_t *crm_ptr = NULL;
-
-	/* Setup encryption information */
-	if (len > ENCRY_INFO_KEY_MAXLEN || !key) {
-		LOGP(DMSC, LOGL_ERROR,
-		     "Cipher mode command message could not be generated due to invalid key! (conn_id=%i)\n",
-		     conn->a.conn_id);
-		return -EINVAL;
-	} else {
-		memcpy(&ei.key, key, len);
-		ei.key_len = len;
-	}
-
-	if (include_imeisv)
-		crm_ptr = &crm;
-
-	ei.perm_algo[0] = (uint8_t) (1 << cipher);
-	ei.perm_algo_len = 1;
-
-	msg_resp = gsm0808_create_cipher(&ei, crm_ptr);
-	LOGP(DMSC, LOGL_DEBUG, "N-DATA.req(%u, %s)\n", conn->a.conn_id, osmo_hexdump(msg_resp->data, msg_resp->len));
-
-	return osmo_sccp_tx_data_msg(conn->a.scu, conn->a.conn_id, msg_resp);
-}
-
-/* Page a subscriber via A-interface */
-int a_iface_tx_paging(const char *imsi, uint32_t tmsi, uint16_t lac)
-{
-	struct bsc_context *bsc_ctx;
-	struct gsm0808_cell_id_list cil;
-	struct msgb *msg;
-	int page_count = 0;
-	struct osmo_ss7_instance *ss7;
-
-	OSMO_ASSERT(imsi);
-
-	cil.id_discr = CELL_IDENT_LAC;
-	cil.id_list_lac[0] = lac;
-	cil.id_list_len = 1;
-
-	ss7 = osmo_ss7_instance_find(gsm_network->a.cs7_instance);
-	OSMO_ASSERT(ss7);
-
-	/* Deliver paging request to all known BSCs */
-	llist_for_each_entry(bsc_ctx, &gsm_network->a.bscs, list) {
-		if (a_reset_conn_ready(bsc_ctx->reset)) {
-			LOGP(DMSC, LOGL_DEBUG,
-			     "Passing paging message from MSC %s to BSC %s (imsi=%s, tmsi=0x%08x, lac=%u)\n",
-			     osmo_sccp_addr_name(ss7, &bsc_ctx->msc_addr),
-			     osmo_sccp_addr_name(ss7, &bsc_ctx->bsc_addr), imsi, tmsi, lac);
-			msg = gsm0808_create_paging(imsi, &tmsi, &cil, NULL);
-			osmo_sccp_tx_unitdata_msg(bsc_ctx->sccp_user,
-						  &bsc_ctx->msc_addr, &bsc_ctx->bsc_addr, msg);
-			page_count++;
-		} else {
-			LOGP(DMSC, LOGL_DEBUG,
-			     "Connection down, dropping paging from MSC %s to BSC %s (imsi=%s, tmsi=0x%08x, lac=%u)\n",
-			     osmo_sccp_addr_name(ss7, &bsc_ctx->msc_addr),
-			     osmo_sccp_addr_name(ss7, &bsc_ctx->bsc_addr), imsi, tmsi, lac);
-		}
-	}
-
-	if (page_count <= 0)
-		LOGP(DMSC, LOGL_ERROR, "Could not deliver paging because none of the associated BSCs is available!\n");
-
-	return page_count;
-}
-
-/* Convert speech version field */
-static uint8_t convert_Abis_sv_to_A_sv(int speech_ver)
-{
-	/* The speech versions that are transmitted in the Bearer capability
-	 * information element, that is transmitted on the Abis interfece
-	 * use a different encoding than the permitted speech version
-	 * identifier, that is signalled in the channel type element on the A
-	 * interface. (See also 3GPP TS 48.008, 3.2.2.1 and 3GPP TS 24.008,
-	 * 10.5.103 */
-
-	switch (speech_ver) {
-	case GSM48_BCAP_SV_FR:
-		return GSM0808_PERM_FR1;
-		break;
-	case GSM48_BCAP_SV_HR:
-		return GSM0808_PERM_HR1;
-		break;
-	case GSM48_BCAP_SV_EFR:
-		return GSM0808_PERM_FR2;
-		break;
-	case GSM48_BCAP_SV_AMR_F:
-		return GSM0808_PERM_FR3;
-		break;
-	case GSM48_BCAP_SV_AMR_H:
-		return GSM0808_PERM_HR3;
-		break;
-	case GSM48_BCAP_SV_AMR_OFW:
-		return GSM0808_PERM_FR4;
-		break;
-	case GSM48_BCAP_SV_AMR_OHW:
-		return GSM0808_PERM_HR4;
-		break;
-	case GSM48_BCAP_SV_AMR_FW:
-		return GSM0808_PERM_FR5;
-		break;
-	case GSM48_BCAP_SV_AMR_OH:
-		return GSM0808_PERM_HR6;
-		break;
-	}
-
-	/* If nothing matches, tag the result as invalid */
-	LOGP(DMSC, LOGL_ERROR, "Invalid permitted speech version / rate detected, discarding.\n");
-	return 0xFF;
-}
-
-/* Convert speech preference field */
-static uint8_t convert_Abis_prev_to_A_pref(int radio)
-{
-	/* The Radio channel requirement field that is transmitted in the
-	 * Bearer capability information element, that is transmitted on the
-	 * Abis interfece uses a different encoding than the Channel rate and
-	 * type field that is signalled in the channel type element on the A
-	 * interface. (See also 3GPP TS 48.008, 3.2.2.1 and 3GPP TS 24.008,
-	 * 10.5.102 */
-
-	switch (radio) {
-	case GSM48_BCAP_RRQ_FR_ONLY:
-		return GSM0808_SPEECH_FULL_BM;
-	case GSM48_BCAP_RRQ_DUAL_FR:
-		return GSM0808_SPEECH_FULL_PREF;
-	case GSM48_BCAP_RRQ_DUAL_HR:
-		return GSM0808_SPEECH_HALF_PREF;
-	}
-
-	LOGP(DMSC, LOGL_ERROR, "Invalid speech version / rate combination preference, defaulting to full rate.\n");
-	return GSM0808_SPEECH_FULL_BM;
-}
-
-/* Assemble the channel type field */
-static int enc_channel_type(struct gsm0808_channel_type *ct, const struct gsm_mncc_bearer_cap *bc)
-{
-	unsigned int i;
-	uint8_t sv;
-	unsigned int count = 0;
-	bool only_gsm_hr = true;
-
-	OSMO_ASSERT(ct);
-	OSMO_ASSERT(bc);
-
-	ct->ch_indctr = GSM0808_CHAN_SPEECH;
-
-	for (i = 0; i < ARRAY_SIZE(bc->speech_ver); i++) {
-		if (bc->speech_ver[i] == -1)
-			break;
-		sv = convert_Abis_sv_to_A_sv(bc->speech_ver[i]);
-		if (sv != 0xFF) {
-			/* Detect if something else than
-			 * GSM HR V1 is supported */
-			if (sv == GSM0808_PERM_HR2 ||
-			    sv == GSM0808_PERM_HR3 || sv == GSM0808_PERM_HR4 || sv == GSM0808_PERM_HR6)
-				only_gsm_hr = false;
-
-			ct->perm_spch[count] = sv;
-			count++;
-		}
-	}
-	ct->perm_spch_len = count;
-
-	if (only_gsm_hr)
-		/* Note: We must avoid the usage of GSM HR1 as this
-		 * codec only offers very poor audio quality. If the
-		 * MS only supports GSM HR1 (and full rate), and has
-		 * a preference for half rate. Then we will ignore the
-		 * preference and assume a preference for full rate. */
-		ct->ch_rate_type = GSM0808_SPEECH_FULL_BM;
-	else
-		ct->ch_rate_type = convert_Abis_prev_to_A_pref(bc->radio);
-
-	if (count)
-		return 0;
-	else
-		return -EINVAL;
-}
-
-/* Assemble the speech codec field */
-static int enc_speech_codec_list(struct gsm0808_speech_codec_list *scl, const struct gsm0808_channel_type *ct)
-{
-	unsigned int i;
-	int rc;
-
-	memset(scl, 0, sizeof(*scl));
-	for (i = 0; i < ct->perm_spch_len; i++) {
-		rc = gsm0808_speech_codec_from_chan_type(&scl->codec[i], ct->perm_spch[i]);
-		if (rc != 0)
-			return -EINVAL;
-	}
-	scl->len = i;
-
-	return 0;
-}
-
-/* Send assignment request via A-interface */
-int a_iface_tx_assignment(const struct gsm_trans *trans)
-{
-	struct gsm_subscriber_connection *conn;
-	struct gsm0808_channel_type ct;
-	struct gsm0808_speech_codec_list scl;
-	uint32_t *ci_ptr = NULL;
-	struct msgb *msg;
-	struct sockaddr_storage rtp_addr;
-	struct sockaddr_in rtp_addr_in;
-	int rc;
-
-	OSMO_ASSERT(trans);
-	conn = trans->conn;
-	OSMO_ASSERT(conn);
-
-	LOGP(DMSC, LOGL_ERROR, "Sending assignment command to BSC (conn_id %u)\n", conn->a.conn_id);
-
-	/* Channel type */
-	rc = enc_channel_type(&ct, &trans->bearer_cap);
-	if (rc < 0) {
-		LOGP(DMSC, LOGL_ERROR, "Faild to generate channel type -- assignment not sent!\n");
-		return -EINVAL;
-	}
-
-	/* Speech codec list */
-	rc = enc_speech_codec_list(&scl, &ct);
-	if (rc < 0) {
-		LOGP(DMSC, LOGL_ERROR, "Faild to generate Speech codec list -- assignment not sent!\n");
-		return -EINVAL;
-	}
-
-	/* Package RTP-Address data */
-	memset(&rtp_addr_in, 0, sizeof(rtp_addr_in));
-	rtp_addr_in.sin_family = AF_INET;
-	rtp_addr_in.sin_port = osmo_htons(conn->rtp.port_subscr);
-	rtp_addr_in.sin_addr.s_addr = osmo_htonl(mgcpgw_client_remote_addr_n(gsm_network->mgcpgw.client));
-
-	memset(&rtp_addr, 0, sizeof(rtp_addr));
-	memcpy(&rtp_addr, &rtp_addr_in, sizeof(rtp_addr_in));
-
-	msg = gsm0808_create_ass(&ct, NULL, &rtp_addr, &scl, ci_ptr);
-
-	LOGP(DMSC, LOGL_DEBUG, "N-DATA.req(%u, %s)\n", conn->a.conn_id, osmo_hexdump(msg->data, msg->len));
-	return osmo_sccp_tx_data_msg(conn->a.scu, conn->a.conn_id, msg);
-}
-
-/* Send clear command via A-interface */
-int a_iface_tx_clear_cmd(struct gsm_subscriber_connection *conn)
-{
-	struct msgb *msg;
-
-	LOGP(DMSC, LOGL_NOTICE, "Sending clear command to BSC (conn_id=%u)\n", conn->a.conn_id);
-
-	msg = gsm0808_create_clear_command(GSM0808_CAUSE_CALL_CONTROL);
-	return osmo_sccp_tx_data_msg(conn->a.scu, conn->a.conn_id, msg);
-}
-
-/* Callback function: Close all open connections */
-static void a_reset_cb(const void *priv)
-{
-	struct msgb *msg;
-	struct bsc_context *bsc_ctx = (struct bsc_context*) priv;
-	struct osmo_ss7_instance *ss7;
-
-	/* Skip if the A interface is not properly initalized yet */
-	if (!gsm_network)
-		return;
-
-	/* Clear all now orphaned subscriber connections */
-	a_clear_all(bsc_ctx->sccp_user, &bsc_ctx->bsc_addr);
-
-	/* Send reset to the remote BSC */
-	ss7 = osmo_ss7_instance_find(gsm_network->a.cs7_instance);
-	OSMO_ASSERT(ss7);
-	LOGP(DMSC, LOGL_NOTICE, "Sending RESET to BSC %s\n", osmo_sccp_addr_name(ss7, &bsc_ctx->bsc_addr));
-	msg = gsm0808_create_reset();
-	osmo_sccp_tx_unitdata_msg(bsc_ctx->sccp_user, &bsc_ctx->msc_addr,
-				  &bsc_ctx->bsc_addr, msg);
-}
-
-/* Add a new BSC connection to our internal list with known BSCs */
-static void add_bsc(const struct osmo_sccp_addr *msc_addr, const struct osmo_sccp_addr *bsc_addr,
-		    struct osmo_sccp_user *scu)
-{
-	struct bsc_context *bsc_ctx;
-	struct osmo_ss7_instance *ss7;
-
-	OSMO_ASSERT(bsc_addr);
-	OSMO_ASSERT(msc_addr);
-	OSMO_ASSERT(scu);
-
-	/* Check if we already know this BSC, if yes, skip adding it. */
-	if (get_reset_ctx_by_sccp_addr(bsc_addr))
-		return;
-
-	ss7 = osmo_ss7_instance_find(gsm_network->a.cs7_instance);
-	OSMO_ASSERT(ss7);
-	LOGP(DMSC, LOGL_NOTICE, "Adding new BSC connection for BSC %s...\n", osmo_sccp_addr_name(ss7, bsc_addr));
-
-	/* Generate and fill up a new bsc context */
-	bsc_ctx = talloc_zero(gsm_network, struct bsc_context);
-	OSMO_ASSERT(bsc_ctx);
-	memcpy(&bsc_ctx->bsc_addr, bsc_addr, sizeof(*bsc_addr));
-	memcpy(&bsc_ctx->msc_addr, msc_addr, sizeof(*msc_addr));
-	bsc_ctx->sccp_user = scu;
-	llist_add_tail(&bsc_ctx->list, &gsm_network->a.bscs);
-
-	/* Start reset procedure to make the new connection active */
-	bsc_ctx->reset = a_reset_alloc(bsc_ctx, osmo_sccp_addr_name(ss7, bsc_addr), a_reset_cb, bsc_ctx);
-}
-
-/* Callback function, called by the SSCP stack when data arrives */
-static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
-{
-	struct osmo_sccp_user *scu = _scu;
-	struct osmo_scu_prim *scu_prim = (struct osmo_scu_prim *)oph;
-	int rc = 0;
-	struct a_conn_info a_conn_info;
-	memset(&a_conn_info, 0, sizeof(a_conn_info));
-	a_conn_info.network = gsm_network;
-	a_conn_info.reset = NULL;
-
-	switch (OSMO_PRIM_HDR(&scu_prim->oph)) {
-	case OSMO_PRIM(OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_INDICATION):
-		/* Handle inbound connection indication */
-		add_bsc(&scu_prim->u.connect.called_addr, &scu_prim->u.connect.calling_addr, scu);
-		a_conn_info.conn_id = scu_prim->u.connect.conn_id;
-		a_conn_info.msc_addr = &scu_prim->u.connect.called_addr;
-		a_conn_info.bsc_addr = &scu_prim->u.connect.calling_addr;
-		a_conn_info.reset = get_reset_ctx_by_sccp_addr(&scu_prim->u.unitdata.calling_addr);
-
-		if (a_reset_conn_ready(a_conn_info.reset) == false) {
-			rc = osmo_sccp_tx_disconn(scu, a_conn_info.conn_id, a_conn_info.msc_addr,
-						  SCCP_RETURN_CAUSE_UNQUALIFIED);
-			break;
-		}
-
-		osmo_sccp_tx_conn_resp(scu, scu_prim->u.connect.conn_id, &scu_prim->u.connect.called_addr, NULL, 0);
-		if (msgb_l2len(oph->msg) > 0) {
-			LOGP(DMSC, LOGL_DEBUG, "N-CONNECT.ind(%u, %s)\n",
-			     scu_prim->u.connect.conn_id, osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)));
-			rc = sccp_rx_dt(scu, &a_conn_info, oph->msg);
-		} else
-			LOGP(DMSC, LOGL_DEBUG, "N-CONNECT.ind(%u)\n", scu_prim->u.connect.conn_id);
-
-		record_bsc_con(scu, scu_prim->u.connect.conn_id);
-		break;
-
-	case OSMO_PRIM(OSMO_SCU_PRIM_N_DATA, PRIM_OP_INDICATION):
-		/* Handle incoming connection oriented data */
-		a_conn_info.conn_id = scu_prim->u.data.conn_id;
-		LOGP(DMSC, LOGL_DEBUG, "N-DATA.ind(%u, %s)\n",
-		     scu_prim->u.data.conn_id, osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)));
-		sccp_rx_dt(scu, &a_conn_info, oph->msg);
-		break;
-
-	case OSMO_PRIM(OSMO_SCU_PRIM_N_UNITDATA, PRIM_OP_INDICATION):
-		/* Handle inbound UNITDATA */
-		add_bsc(&scu_prim->u.unitdata.called_addr, &scu_prim->u.unitdata.calling_addr, scu);
-		a_conn_info.msc_addr = &scu_prim->u.unitdata.called_addr;
-		a_conn_info.bsc_addr = &scu_prim->u.unitdata.calling_addr;
-		a_conn_info.reset = get_reset_ctx_by_sccp_addr(&scu_prim->u.unitdata.calling_addr);
-		DEBUGP(DMSC, "N-UNITDATA.ind(%s)\n", osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)));
-		sccp_rx_udt(scu, &a_conn_info, oph->msg);
-		break;
-
-	default:
-		LOGP(DMSC, LOGL_ERROR, "Unhandled SIGTRAN primitive: %u:%u\n", oph->primitive, oph->operation);
-		break;
-	}
-
-	return rc;
-}
-
-/* Clear all subscriber connections on a specified BSC */
-void a_clear_all(struct osmo_sccp_user *scu, const struct osmo_sccp_addr *bsc_addr)
-{
-	struct gsm_subscriber_connection *conn;
-	struct gsm_subscriber_connection *conn_temp;
-	struct gsm_network *network = gsm_network;
-
-	OSMO_ASSERT(scu);
-	OSMO_ASSERT(bsc_addr);
-
-	llist_for_each_entry_safe(conn, conn_temp, &network->subscr_conns, entry) {
-		/* Clear only A connections and connections that actually
-		 * belong to the specified BSC */
-		if (conn->via_ran == RAN_GERAN_A && memcmp(bsc_addr, &conn->a.bsc_addr, sizeof(conn->a.bsc_addr)) == 0) {
-			LOGP(DMSC, LOGL_NOTICE, "Dropping orphaned subscriber connection (conn_id %i)\n",
-			     conn->a.conn_id);
-			msc_clear_request(conn, GSM48_CC_CAUSE_SWITCH_CONG);
-
-			/* If there is still an SCCP connection active, remove it now */
-			if (check_connection_active(conn->a.conn_id)) {
-				osmo_sccp_tx_disconn(scu, conn->a.conn_id, bsc_addr,
-						     SCCP_RELEASE_CAUSE_END_USER_ORIGINATED);
-				a_delete_bsc_con(conn->a.conn_id);
-			}
-		}
-	}
-}
-
-/* Initalize A interface connection between to MSC and BSC */
-int a_init(struct osmo_sccp_instance *sccp, struct gsm_network *network)
-{
-	OSMO_ASSERT(sccp);
-	OSMO_ASSERT(network);
-
-	/* FIXME: Remove hardcoded parameters, use parameters in parameter list */
-	LOGP(DMSC, LOGL_NOTICE, "Initalizing SCCP connection to stp...\n");
-
-	/* Set GSM network variable, there can only be
-	 * one network by design */
-	if (gsm_network != NULL) {
-		OSMO_ASSERT(gsm_network == network);
-	} else
-		gsm_network = network;
-
-	/* SCCP Protocol stack */
-	osmo_sccp_user_bind(sccp, "OsmoMSC-A", sccp_sap_up, SCCP_SSN_BSSAP);
-
-	return 0;
-}
diff --git a/src/libmsc/a_iface_bssap.c b/src/libmsc/a_iface_bssap.c
deleted file mode 100644
index e8a2293..0000000
--- a/src/libmsc/a_iface_bssap.c
+++ /dev/null
@@ -1,716 +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/>.
- *
- */
-
-#include <osmocom/core/utils.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/logging.h>
-#include <osmocom/sigtran/sccp_helpers.h>
-#include <osmocom/sccp/sccp_types.h>
-#include <osmocom/gsm/gsm0808.h>
-#include <osmocom/gsm/gsm0808_utils.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/a_iface_bssap.h>
-#include <openbsc/a_iface.h>
-#include <openbsc/osmo_msc.h>
-#include <osmocom/core/byteswap.h>
-#include <openbsc/a_reset.h>
-
-#define IP_V4_ADDR_LEN 4
-
-/*
- * Helper functions to lookup and allocate subscribers
- */
-
-/* Allocate a new subscriber connection */
-static struct gsm_subscriber_connection *subscr_conn_allocate_a(const struct a_conn_info *a_conn_info,
-								struct gsm_network *network,
-								uint16_t lac, struct osmo_sccp_user *scu, int conn_id)
-{
-	struct gsm_subscriber_connection *conn;
-
-	LOGP(DMSC, LOGL_NOTICE, "Allocating A-Interface subscriber conn: lac %i, conn_id %i\n", lac, conn_id);
-
-	conn = talloc_zero(network, struct gsm_subscriber_connection);
-	if (!conn)
-		return NULL;
-
-	conn->network = network;
-	conn->via_ran = RAN_GERAN_A;
-	conn->lac = lac;
-
-	conn->a.conn_id = conn_id;
-	conn->a.scu = scu;
-
-	/* Also backup the calling address of the BSC, this allows us to
-	 * identify later which BSC is responsible for this subscriber connection */
-	memcpy(&conn->a.bsc_addr, a_conn_info->bsc_addr, sizeof(conn->a.bsc_addr));
-
-	llist_add_tail(&conn->entry, &network->subscr_conns);
-	LOGP(DMSC, LOGL_NOTICE, "A-Interface subscriber connection successfully allocated!\n");
-	return conn;
-}
-
-/* Return an existing A subscriber connection record for the given
- * connection IDs, or return NULL if not found. */
-static struct gsm_subscriber_connection *subscr_conn_lookup_a(const struct gsm_network *network, int conn_id)
-{
-	struct gsm_subscriber_connection *conn;
-
-	OSMO_ASSERT(network);
-
-	DEBUGP(DMSC, "Looking for A subscriber: conn_id %i\n", conn_id);
-
-	/* FIXME: log_subscribers() is defined in iucs.c as static inline, if
-	 * maybe this function should be public to reach it from here? */
-	/* log_subscribers(network); */
-
-	llist_for_each_entry(conn, &network->subscr_conns, entry) {
-		if (conn->via_ran == RAN_GERAN_A && conn->a.conn_id == conn_id) {
-			DEBUGP(DIUCS, "Found A subscriber for conn_id %i\n", conn_id);
-			return conn;
-		}
-	}
-	DEBUGP(DMSC, "No A subscriber found for conn_id %i\n", conn_id);
-	return NULL;
-}
-
-/*
- * BSSMAP handling for UNITDATA
- */
-
-/* Endpoint to handle BSSMAP reset */
-static void bssmap_rx_reset(struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg)
-{
-	struct gsm_network *network = a_conn_info->network;
-	struct osmo_ss7_instance *ss7;
-
-	ss7 = osmo_ss7_instance_find(network->a.cs7_instance);
-	OSMO_ASSERT(ss7);
-
-	LOGP(DMSC, LOGL_NOTICE, "Rx RESET from BSC %s, sending RESET ACK\n",
-	     osmo_sccp_addr_name(ss7, a_conn_info->bsc_addr));
-	osmo_sccp_tx_unitdata_msg(scu, a_conn_info->msc_addr, a_conn_info->bsc_addr, gsm0808_create_reset_ack());
-
-	/* Make sure all orphand subscriber connections will be cleard */
-	a_clear_all(scu, a_conn_info->bsc_addr);
-
-	msgb_free(msg);
-}
-
-/* Endpoint to handle BSSMAP reset acknowlegement */
-static void bssmap_rx_reset_ack(const struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info,
-				struct msgb *msg)
-{
-
-	struct gsm_network *network = a_conn_info->network;
-	struct osmo_ss7_instance *ss7;
-
-	ss7 = osmo_ss7_instance_find(network->a.cs7_instance);
-	OSMO_ASSERT(ss7);
-
-	if (a_conn_info->reset == NULL) {
-		LOGP(DMSC, LOGL_ERROR, "Received RESET ACK from an unknown BSC %s, ignoring...\n",
-		     osmo_sccp_addr_name(ss7, a_conn_info->bsc_addr));
-		goto fail;
-	}
-
-	LOGP(DMSC, LOGL_NOTICE, "Received RESET ACK from BSC %s\n", osmo_sccp_addr_name(ss7, a_conn_info->bsc_addr));
-
-	/* Confirm that we managed to get the reset ack message
-	 * towards the connection reset logic */
-	a_reset_ack_confirm(a_conn_info->reset);
-
-fail:
-	msgb_free(msg);
-}
-
-/* Handle UNITDATA BSSMAP messages */
-static void bssmap_rcvmsg_udt(struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg)
-{
-	/* Note: When in the MSC role, RESET ACK is the only valid message that
-	 * can be received via UNITDATA */
-
-	if (msgb_l3len(msg) < 1) {
-		LOGP(DMSC, LOGL_NOTICE, "Error: No data received -- discarding message!\n");
-		return;
-	}
-
-	LOGP(DMSC, LOGL_NOTICE, "Rx BSC UDT BSSMAP %s\n", gsm0808_bssmap_name(msg->l3h[0]));
-
-	switch (msg->l3h[0]) {
-	case BSS_MAP_MSG_RESET:
-		bssmap_rx_reset(scu, a_conn_info, msg);
-		break;
-	case BSS_MAP_MSG_RESET_ACKNOWLEDGE:
-		bssmap_rx_reset_ack(scu, a_conn_info, msg);
-		break;
-	default:
-		LOGP(DMSC, LOGL_NOTICE, "Unimplemented message format: %s -- message discarded!\n",
-		     gsm0808_bssmap_name(msg->l3h[0]));
-		msgb_free(msg);
-	}
-}
-
-/* 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)
-{
-	/* Note: The only valid message type that can be received
-	 * via UNITDATA are BSS Management messages */
-	struct bssmap_header *bs;
-
-	OSMO_ASSERT(scu);
-	OSMO_ASSERT(a_conn_info);
-	OSMO_ASSERT(msg);
-
-	LOGP(DMSC, LOGL_NOTICE, "Rx BSC UDT: %s\n", osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
-
-	if (msgb_l2len(msg) < sizeof(*bs)) {
-		LOGP(DMSC, LOGL_ERROR, "Error: Header is too short -- discarding message!\n");
-		msgb_free(msg);
-		return;
-	}
-
-	bs = (struct bssmap_header *)msgb_l2(msg);
-	if (bs->length < msgb_l2len(msg) - sizeof(*bs)) {
-		LOGP(DMSC, LOGL_ERROR, "Error: Message is too short -- discarding message!\n");
-		msgb_free(msg);
-		return;
-	}
-
-	switch (bs->type) {
-	case BSSAP_MSG_BSS_MANAGEMENT:
-		msg->l3h = &msg->l2h[sizeof(struct bssmap_header)];
-		bssmap_rcvmsg_udt(scu, a_conn_info, msg);
-		break;
-	default:
-		LOGP(DMSC, LOGL_ERROR,
-		     "Error: Unimplemented message type: %s -- message discarded!\n", gsm0808_bssmap_name(bs->type));
-		msgb_free(msg);
-	}
-}
-
-/*
- * BSSMAP handling for connection oriented data
- */
-
-/* Endpoint to handle BSSMAP clear request */
-static int bssmap_rx_clear_rqst(struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg)
-{
-	struct gsm_network *network = a_conn_info->network;
-	struct tlv_parsed tp;
-	int rc;
-	struct msgb *msg_resp;
-	uint8_t cause;
-	struct gsm_subscriber_connection *conn;
-
-	LOGP(DMSC, LOGL_NOTICE, "BSC requested to clear connection (conn_id=%i)\n", a_conn_info->conn_id);
-
-	tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, msgb_l3len(msg) - 1, 0, 0);
-	if (!TLVP_PRESENT(&tp, GSM0808_IE_CAUSE)) {
-		LOGP(DMSC, LOGL_ERROR, "Cause code is missing -- discarding message!\n");
-		goto fail;
-	}
-	cause = TLVP_VAL(&tp, GSM0808_IE_CAUSE)[0];
-
-	/* Respond with clear command */
-	msg_resp = gsm0808_create_clear_command(GSM0808_CAUSE_CALL_CONTROL);
-	rc = osmo_sccp_tx_data_msg(scu, a_conn_info->conn_id, msg_resp);
-
-	/* If possible, inform the MSC about the clear request */
-	conn = subscr_conn_lookup_a(network, a_conn_info->conn_id);
-	if (!conn)
-		goto fail;
-	msc_clear_request(conn, cause);
-
-	msgb_free(msg);
-	return rc;
-
-fail:
-	msgb_free(msg);
-	return -EINVAL;
-}
-
-/* Endpoint to handle BSSMAP clear complete */
-static int bssmap_rx_clear_complete(struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg)
-{
-	int rc;
-
-	LOGP(DMSC, LOGL_NOTICE, "Releasing connection (conn_id=%i)\n", a_conn_info->conn_id);
-	rc = osmo_sccp_tx_disconn(scu, a_conn_info->conn_id,
-				  a_conn_info->msc_addr, SCCP_RELEASE_CAUSE_END_USER_ORIGINATED);
-
-	/* Remove the record from the list with active connections. */
-	a_delete_bsc_con(a_conn_info->conn_id);
-
-	msgb_free(msg);
-	return rc;
-}
-
-/* Endpoint to handle layer 3 complete messages */
-static int bssmap_rx_l3_compl(struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg)
-{
-	struct tlv_parsed tp;
-	struct {
-		uint8_t ident;
-		struct gsm48_loc_area_id lai;
-		uint16_t ci;
-	} __attribute__ ((packed)) lai_ci;
-	uint16_t mcc;
-	uint16_t mnc;
-	uint16_t lac;
-	uint8_t data_length;
-	const uint8_t *data;
-	int rc;
-
-	struct gsm_network *network = a_conn_info->network;
-	struct gsm_subscriber_connection *conn;
-
-	LOGP(DMSC, LOGL_NOTICE, "BSC has completed layer 3 connection (conn_id=%i)\n", a_conn_info->conn_id);
-
-	tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, msgb_l3len(msg) - 1, 0, 0);
-	if (!TLVP_PRESENT(&tp, GSM0808_IE_CELL_IDENTIFIER)) {
-		LOGP(DMSC, LOGL_ERROR, "Mandatory CELL IDENTIFIER not present -- discarding message!\n");
-		goto fail;
-	}
-	if (!TLVP_PRESENT(&tp, GSM0808_IE_LAYER_3_INFORMATION)) {
-		LOGP(DMSC, LOGL_ERROR, "Mandatory LAYER 3 INFORMATION not present -- discarding message!\n");
-		goto fail;
-	}
-
-	/* Parse Cell ID element */
-	/* FIXME: Encapsulate this in a parser/generator function inside
-	 * libosmocore, add support for all specified cell identification
-	 * discriminators (see 3GPP ts 3.2.2.17 Cell Identifier) */
-	data_length = TLVP_LEN(&tp, GSM0808_IE_CELL_IDENTIFIER);
-	data = TLVP_VAL(&tp, GSM0808_IE_CELL_IDENTIFIER);
-	if (sizeof(lai_ci) != data_length) {
-		LOGP(DMSC, LOGL_ERROR,
-		     "Unable to parse element CELL IDENTIFIER (wrong field length) -- discarding message!\n");
-		goto fail;
-	}
-	memcpy(&lai_ci, data, sizeof(lai_ci));
-	if (lai_ci.ident != CELL_IDENT_WHOLE_GLOBAL) {
-		LOGP(DMSC, LOGL_ERROR,
-		     "Unable to parse element CELL IDENTIFIER (wrong cell identification discriminator) -- discarding message!\n");
-		goto fail;
-	}
-	if (gsm48_decode_lai(&lai_ci.lai, &mcc, &mnc, &lac) != 0) {
-		LOGP(DMSC, LOGL_ERROR,
-		     "Unable to parse element CELL IDENTIFIER (lai decoding failed) -- discarding message!\n");
-		goto fail;
-	}
-
-	/* Parse Layer 3 Information element */
-	/* FIXME: This is probably to hackish, compiler also complains "assignment discards ‘const’ qualifier..." */
-	msg->l3h = TLVP_VAL(&tp, GSM0808_IE_LAYER_3_INFORMATION);
-	msg->tail = msg->l3h + TLVP_LEN(&tp, GSM0808_IE_LAYER_3_INFORMATION);
-
-	/* Create new subscriber context */
-	conn = subscr_conn_allocate_a(a_conn_info, network, lac, scu, a_conn_info->conn_id);
-
-	/* Handover location update to the MSC code */
-	/* msc_compl_l3() takes ownership of dtap_msg
-	 * message buffer */
-	rc = msc_compl_l3(conn, msg, 0);
-	if (rc == MSC_CONN_ACCEPT) {
-		LOGP(DMSC, LOGL_NOTICE, "User has been accepted by MSC.\n");
-		return 0;
-	} else if (rc == MSC_CONN_REJECT)
-		LOGP(DMSC, LOGL_NOTICE, "User has been rejected by MSC.\n");
-	else
-		LOGP(DMSC, LOGL_NOTICE, "User has been rejected by MSC (unknown error)\n");
-
-	return -EINVAL;
-
-fail:
-	msgb_free(msg);
-	return -EINVAL;
-}
-
-/* Endpoint to handle BSSMAP classmark update */
-static int bssmap_rx_classmark_upd(struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg)
-{
-	struct gsm_network *network = a_conn_info->network;
-	struct gsm_subscriber_connection *conn;
-	struct tlv_parsed tp;
-	const uint8_t *cm2 = NULL;
-	const uint8_t *cm3 = NULL;
-	uint8_t cm2_len = 0;
-	uint8_t cm3_len = 0;
-
-	conn = subscr_conn_lookup_a(network, a_conn_info->conn_id);
-	if (!conn)
-		goto fail;
-
-	LOGP(DMSC, LOGL_NOTICE, "BSC sends clasmark update (conn_id=%i)\n", conn->a.conn_id);
-
-	tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, msgb_l3len(msg) - 1, 0, 0);
-	if (!TLVP_PRESENT(&tp, GSM0808_IE_CLASSMARK_INFORMATION_T2)) {
-		LOGP(DMSC, LOGL_ERROR, "Mandatory Classmark Information Type 2 not present -- discarding message!\n");
-		goto fail;
-	}
-
-	cm2 = TLVP_VAL(&tp, GSM0808_IE_CLASSMARK_INFORMATION_T2);
-	cm2_len = TLVP_LEN(&tp, GSM0808_IE_CLASSMARK_INFORMATION_T2);
-
-	if (TLVP_PRESENT(&tp, GSM0808_IE_CLASSMARK_INFORMATION_T3)) {
-		cm3 = TLVP_VAL(&tp, GSM0808_IE_CLASSMARK_INFORMATION_T3);
-		cm3_len = TLVP_LEN(&tp, GSM0808_IE_CLASSMARK_INFORMATION_T3);
-	}
-
-	/* Inform MSC about the classmark change */
-	msc_classmark_chg(conn, cm2, cm2_len, cm3, cm3_len);
-
-	msgb_free(msg);
-	return 0;
-
-fail:
-	msgb_free(msg);
-	return -EINVAL;
-}
-
-/* Endpoint to handle BSSMAP cipher mode complete */
-static int bssmap_rx_ciph_compl(const struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info,
-				struct msgb *msg)
-{
-	/* FIXME: The field GSM0808_IE_LAYER_3_MESSAGE_CONTENTS is optional by
-	 * means of the specification. So there can be messages without L3 info.
-	 * In this case, the code will crash becrause msc_cipher_mode_compl()
-	 * is not able to deal with msg = NULL and apperently
-	 * msc_cipher_mode_compl() was never meant to be used without L3 data.
-	 * This needs to be discussed further! */
-
-	struct gsm_network *network = a_conn_info->network;
-	struct gsm_subscriber_connection *conn;
-	struct tlv_parsed tp;
-	uint8_t alg_id = 1;
-
-	conn = subscr_conn_lookup_a(network, a_conn_info->conn_id);
-	if (!conn)
-		goto fail;
-
-	LOGP(DMSC, LOGL_NOTICE, "BSC sends cipher mode complete (conn_id=%i)\n", conn->a.conn_id);
-
-	tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, msgb_l3len(msg) - 1, 0, 0);
-
-	if (TLVP_PRESENT(&tp, GSM0808_IE_CHOSEN_ENCR_ALG)) {
-		alg_id = TLVP_VAL(&tp, GSM0808_IE_CHOSEN_ENCR_ALG)[0] - 1;
-	}
-
-	if (TLVP_PRESENT(&tp, GSM0808_IE_LAYER_3_MESSAGE_CONTENTS)) {
-		msg->l3h = TLVP_VAL(&tp, GSM0808_IE_LAYER_3_MESSAGE_CONTENTS);
-		msg->tail = msg->l3h + TLVP_LEN(&tp, GSM0808_IE_LAYER_3_MESSAGE_CONTENTS);
-	} else {
-		msgb_free(msg);
-		msg = NULL;
-	}
-
-	/* Hand over cipher mode complete message to the MSC,
-	 * msc_cipher_mode_compl() takes ownership for msg */
-	msc_cipher_mode_compl(conn, msg, alg_id);
-
-	return 0;
-fail:
-	msgb_free(msg);
-	return -EINVAL;
-}
-
-/* Endpoint to handle BSSMAP cipher mode reject */
-static int bssmap_rx_ciph_rej(const struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg)
-{
-	struct gsm_network *network = a_conn_info->network;
-	struct gsm_subscriber_connection *conn;
-	struct tlv_parsed tp;
-	uint8_t cause;
-
-	conn = subscr_conn_lookup_a(network, a_conn_info->conn_id);
-	if (!conn)
-		goto fail;
-
-	LOGP(DMSC, LOGL_NOTICE, "BSC sends cipher mode reject (conn_id=%i)\n", conn->a.conn_id);
-
-	tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, msgb_l3len(msg) - 1, 0, 0);
-	if (!TLVP_PRESENT(&tp, BSS_MAP_MSG_CIPHER_MODE_REJECT)) {
-		LOGP(DMSC, LOGL_ERROR, "Cause code is missing -- discarding message!\n");
-		goto fail;
-	}
-
-	cause = TLVP_VAL(&tp, BSS_MAP_MSG_CIPHER_MODE_REJECT)[0];
-	LOGP(DMSC, LOGL_NOTICE, "Cipher mode rejection cause: %i\n", cause);
-
-	/* FIXME: Can we do something meaningful here? e.g. report to the
-	 * msc code somehow that the cipher mode command has failed. */
-
-	msgb_free(msg);
-	return 0;
-fail:
-	msgb_free(msg);
-	return -EINVAL;
-}
-
-/* Endpoint to handle BSSMAP assignment failure */
-static int bssmap_rx_ass_fail(const struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg)
-{
-	struct gsm_network *network = a_conn_info->network;
-	struct gsm_subscriber_connection *conn;
-	struct tlv_parsed tp;
-	uint8_t cause;
-	uint8_t *rr_cause_ptr = NULL;
-	uint8_t rr_cause;
-
-	conn = subscr_conn_lookup_a(network, a_conn_info->conn_id);
-	if (!conn)
-		goto fail;
-
-	LOGP(DMSC, LOGL_NOTICE, "BSC sends assignment failure message (conn_id=%i)\n", conn->a.conn_id);
-
-	tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, msgb_l3len(msg) - 1, 0, 0);
-	if (!TLVP_PRESENT(&tp, GSM0808_IE_CAUSE)) {
-		LOGP(DMSC, LOGL_ERROR, "Cause code is missing -- discarding message!\n");
-		goto fail;
-	}
-	cause = TLVP_VAL(&tp, GSM0808_IE_CAUSE)[0];
-
-	if (TLVP_PRESENT(&tp, GSM0808_IE_RR_CAUSE)) {
-		rr_cause = TLVP_VAL(&tp, GSM0808_IE_RR_CAUSE)[0];
-		rr_cause_ptr = &rr_cause;
-	}
-
-	/* FIXME: In AoIP, the Assignment failure will carry also an optional
-	 * Codec List (BSS Supported) element. It has to be discussed if we
-	 * can ignore this element. If not, The msc_assign_fail() function
-	 * call has to change. However msc_assign_fail() does nothing in the
-	 * end. So probably we can just leave it as it is. Even for AoIP */
-
-	/* Inform the MSC about the assignment failure event */
-	msc_assign_fail(conn, cause, rr_cause_ptr);
-
-	msgb_free(msg);
-	return 0;
-fail:
-	msgb_free(msg);
-	return -EINVAL;
-}
-
-/* Endpoint to handle sapi "n" reject */
-static int bssmap_rx_sapi_n_rej(const struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info,
-				struct msgb *msg)
-{
-	struct gsm_network *network = a_conn_info->network;
-	struct gsm_subscriber_connection *conn;
-	struct tlv_parsed tp;
-	uint8_t dlci;
-
-	conn = subscr_conn_lookup_a(network, a_conn_info->conn_id);
-	if (!conn)
-		goto fail;
-
-	LOGP(DMSC, LOGL_NOTICE, "BSC sends sapi \"n\" reject message (conn_id=%i)\n", conn->a.conn_id);
-
-	/* Note: The MSC code seems not to care about the cause code, but by
-	 * the specification it is mandatory, so we check its presence. See
-	 * also 3GPP TS 48.008 3.2.1.34 SAPI "n" REJECT */
-	tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, msgb_l3len(msg) - 1, 0, 0);
-	if (!TLVP_PRESENT(&tp, GSM0808_IE_CAUSE)) {
-		LOGP(DMSC, LOGL_ERROR, "Cause code is missing -- discarding message!\n");
-		goto fail;
-	}
-
-	tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, msgb_l3len(msg) - 1, 0, 0);
-	if (!TLVP_PRESENT(&tp, GSM0808_IE_DLCI)) {
-		LOGP(DMSC, LOGL_ERROR, "DLCI is missing -- discarding message!\n");
-		goto fail;
-	}
-	dlci = TLVP_VAL(&tp, GSM0808_IE_DLCI)[0];
-
-	/* Inform the MSC about the sapi "n" reject event */
-	msc_sapi_n_reject(conn, dlci);
-
-	msgb_free(msg);
-	return 0;
-fail:
-	msgb_free(msg);
-	return -EINVAL;
-}
-
-/* Endpoint to handle assignment complete */
-static int bssmap_rx_ass_compl(const struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info,
-			       struct msgb *msg)
-{
-	struct gsm_network *network = a_conn_info->network;
-	struct gsm_subscriber_connection *conn;
-	struct mgcpgw_client *mgcp;
-	struct tlv_parsed tp;
-	struct sockaddr_storage rtp_addr;
-	struct sockaddr_in *rtp_addr_in;
-	int rc;
-
-	conn = subscr_conn_lookup_a(network, a_conn_info->conn_id);
-	if (!conn)
-		goto fail;
-
-	mgcp = conn->network->mgcpgw.client;
-	OSMO_ASSERT(mgcp);
-
-	LOGP(DMSC, LOGL_NOTICE, "BSC sends assignment complete message (conn_id=%i)\n", conn->a.conn_id);
-
-	tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, msgb_l3len(msg) - 1, 0, 0);
-
-	if (!TLVP_PRESENT(&tp, GSM0808_IE_AOIP_TRASP_ADDR)) {
-		LOGP(DMSC, LOGL_ERROR, "AoIP transport identifier missing -- discarding message!\n");
-		goto fail;
-	}
-
-	/* Decode AoIP transport address element */
-	rc = gsm0808_dec_aoip_trasp_addr(&rtp_addr, TLVP_VAL(&tp, GSM0808_IE_AOIP_TRASP_ADDR),
-					 TLVP_LEN(&tp, GSM0808_IE_AOIP_TRASP_ADDR));
-	if (rc < 0) {
-		LOGP(DMSC, LOGL_ERROR, "Unable to decode aoip transport address.\n");
-		goto fail;
-	}
-
-	/* use address / port supplied with the AoIP
-	 * transport address element */
-	if (rtp_addr.ss_family == AF_INET) {
-		rtp_addr_in = (struct sockaddr_in *)&rtp_addr;
-		conn->rtp.port_subscr = osmo_ntohs(rtp_addr_in->sin_port);
-		/* FIXME: We also get the IP-Address of the remote (e.g. BTS)
-		 * end with the response. Currently we just ignore that address.
-		 * Instead we expect that our local MGCP gateway and the code
-		 * controlling it, magically knows the IP of the remote end. */
-	} else {
-		LOGP(DMSC, LOGL_ERROR, "Unsopported addressing scheme. (supports only IPV4)\n");
-		goto fail;
-	}
-
-	/* FIXME: Seems to be related to authentication or,
-	   encryption. Is this really in the right place? */
-	msc_rx_sec_mode_compl(conn);
-
-	msgb_free(msg);
-	return 0;
-fail:
-	msgb_free(msg);
-	return -EINVAL;
-}
-
-/* Handle incoming connection oriented BSSMAP messages */
-static int rx_bssmap(struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg)
-{
-	if (msgb_l3len(msg) < 1) {
-		LOGP(DMSC, LOGL_NOTICE, "Error: No data received -- discarding message!\n");
-		msgb_free(msg);
-		return -1;
-	}
-
-	LOGP(DMSC, LOGL_NOTICE, "Rx MSC DT1 BSSMAP %s\n", gsm0808_bssmap_name(msg->l3h[0]));
-
-	switch (msg->l3h[0]) {
-	case BSS_MAP_MSG_CLEAR_RQST:
-		return bssmap_rx_clear_rqst(scu, a_conn_info, msg);
-		break;
-	case BSS_MAP_MSG_CLEAR_COMPLETE:
-		return bssmap_rx_clear_complete(scu, a_conn_info, msg);
-		break;
-	case BSS_MAP_MSG_COMPLETE_LAYER_3:
-		return bssmap_rx_l3_compl(scu, a_conn_info, msg);
-		break;
-	case BSS_MAP_MSG_CLASSMARK_UPDATE:
-		return bssmap_rx_classmark_upd(scu, a_conn_info, msg);
-		break;
-	case BSS_MAP_MSG_CIPHER_MODE_COMPLETE:
-		return bssmap_rx_ciph_compl(scu, a_conn_info, msg);
-		break;
-	case BSS_MAP_MSG_CIPHER_MODE_REJECT:
-		return bssmap_rx_ciph_rej(scu, a_conn_info, msg);
-		break;
-	case BSS_MAP_MSG_ASSIGMENT_FAILURE:
-		return bssmap_rx_ass_fail(scu, a_conn_info, msg);
-		break;
-	case BSS_MAP_MSG_SAPI_N_REJECT:
-		return bssmap_rx_sapi_n_rej(scu, a_conn_info, msg);
-		break;
-	case BSS_MAP_MSG_ASSIGMENT_COMPLETE:
-		return bssmap_rx_ass_compl(scu, a_conn_info, msg);
-		break;
-	default:
-		LOGP(DMSC, LOGL_ERROR, "Unimplemented msg type: %s\n", gsm0808_bssmap_name(msg->l3h[0]));
-		msgb_free(msg);
-		return -EINVAL;
-	}
-
-	return -EINVAL;
-}
-
-/* Endpoint to handle regular BSSAP DTAP messages */
-static int rx_dtap(const struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg)
-{
-	struct gsm_network *network = a_conn_info->network;
-	struct gsm_subscriber_connection *conn;
-
-	conn = subscr_conn_lookup_a(network, a_conn_info->conn_id);
-	if (!conn) {
-		msgb_free(msg);
-		return -EINVAL;
-	}
-
-	LOGP(DMSC, LOGL_NOTICE, "BSC sends layer 3 dtap (conn_id=%i)\n", conn->a.conn_id);
-
-	/* msc_dtap expects the dtap payload in l3h */
-	msg->l3h = msg->l2h + 3;
-
-	/* Forward dtap payload into the msc,
-	 * msc_dtap() takes ownership for msg */
-	msc_dtap(conn, conn->a.conn_id, msg);
-
-	return 0;
-}
-
-/* Handle incoming connection oriented messages */
-int sccp_rx_dt(struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg)
-{
-	OSMO_ASSERT(scu);
-	OSMO_ASSERT(a_conn_info);
-	OSMO_ASSERT(msg);
-
-	LOGP(DMSC, LOGL_NOTICE, "Rx BSC DT: %s\n", osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
-
-	if (msgb_l2len(msg) < sizeof(struct bssmap_header)) {
-		LOGP(DMSC, LOGL_NOTICE, "The header is too short -- discarding message!\n");
-		msgb_free(msg);
-	}
-
-	switch (msg->l2h[0]) {
-	case BSSAP_MSG_BSS_MANAGEMENT:
-		msg->l3h = &msg->l2h[sizeof(struct bssmap_header)];
-		return rx_bssmap(scu, a_conn_info, msg);
-		break;
-	case BSSAP_MSG_DTAP:
-		return rx_dtap(scu, a_conn_info, msg);
-		break;
-	default:
-		LOGP(DMSC, LOGL_ERROR, "Unimplemented BSSAP msg type: %s\n", gsm0808_bssap_name(msg->l2h[0]));
-		msgb_free(msg);
-		return -EINVAL;
-	}
-
-	return -EINVAL;
-}
diff --git a/src/libmsc/auth.c b/src/libmsc/auth.c
deleted file mode 100644
index 9064ce6..0000000
--- a/src/libmsc/auth.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Authentication related functions */
-
-/*
- * (C) 2010 by Sylvain Munaut <tnt@246tNt.com>
- *
- * 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/>.
- *
- */
-
-#include <openbsc/db.h>
-#include <openbsc/debug.h>
-#include <openbsc/auth.h>
-#include <openbsc/gsm_data.h>
-
-#include <osmocom/gsm/comp128.h>
-#include <osmocom/core/utils.h>
-
-#include <openssl/rand.h>
-
-#include <stdlib.h>
-
-const struct value_string auth_action_names[] = {
-	OSMO_VALUE_STRING(AUTH_ERROR),
-	OSMO_VALUE_STRING(AUTH_NOT_AVAIL),
-	OSMO_VALUE_STRING(AUTH_DO_AUTH_THEN_CIPH),
-	OSMO_VALUE_STRING(AUTH_DO_CIPH),
-	OSMO_VALUE_STRING(AUTH_DO_AUTH),
-	{ 0, NULL }
-};
diff --git a/src/libmsc/ctrl_commands.c b/src/libmsc/ctrl_commands.c
deleted file mode 100644
index 9d1f0d4..0000000
--- a/src/libmsc/ctrl_commands.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * (C) 2014 by Holger Hans Peter Freyther
- * (C) 2014 by 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 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/>.
- *
- */
-
-#include <osmocom/ctrl/control_cmd.h>
-#include <osmocom/core/utils.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/db.h>
-#include <openbsc/debug.h>
-#include <openbsc/vlr.h>
-
-#include <stdbool.h>
-
-static struct gsm_network *msc_ctrl_net = NULL;
-
-static int verify_subscriber_modify(struct ctrl_cmd *cmd, const char *value, void *d)
-{
-	return 0;
-}
-
-static int set_subscriber_modify(struct ctrl_cmd *cmd, void *data)
-{
-	cmd->reply = "Command moved to osmo-hlr, no longer available here";
-	return CTRL_CMD_ERROR;
-}
-
-CTRL_CMD_DEFINE_WO(subscriber_modify, "subscriber-modify-v1");
-
-static int set_subscriber_delete(struct ctrl_cmd *cmd, void *data)
-{
-	cmd->reply = "Command moved to osmo-hlr, no longer available here";
-	return CTRL_CMD_ERROR;
-}
-CTRL_CMD_DEFINE_WO_NOVRF(subscriber_delete, "subscriber-delete-v1");
-
-static int get_subscriber_list(struct ctrl_cmd *cmd, void *d)
-{
-	struct vlr_subscr *vsub;
-
-	if (!msc_ctrl_net) {
-		cmd->reply = "MSC CTRL commands not initialized";
-		return CTRL_CMD_ERROR;
-	}
-
-	if (!msc_ctrl_net->vlr) {
-		cmd->reply = "VLR not initialized";
-		return CTRL_CMD_ERROR;
-	}
-
-	cmd->reply = talloc_strdup(cmd, "");
-
-	llist_for_each_entry(vsub, &msc_ctrl_net->vlr->subscribers, list) {
-		cmd->reply = talloc_asprintf_append(cmd->reply, "%s,%s\n",
-						    vsub->imsi, vsub->msisdn);
-	}
-	printf("%s\n", cmd->reply); /* <-- what? */
-	return CTRL_CMD_REPLY;
-}
-CTRL_CMD_DEFINE_RO(subscriber_list, "subscriber-list-active-v1");
-
-int msc_ctrl_cmds_install(struct gsm_network *net)
-{
-	int rc = 0;
-	msc_ctrl_net = net;
-
-	rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_subscriber_modify);
-	rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_subscriber_delete);
-	rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_subscriber_list);
-	return rc;
-}
diff --git a/src/libmsc/db.c b/src/libmsc/db.c
deleted file mode 100644
index ae7e287..0000000
--- a/src/libmsc/db.c
+++ /dev/null
@@ -1,1007 +0,0 @@
-/* Simple HLR/VLR database backend using dbi */
-/* (C) 2008 by Jan Luebbe <jluebbe@debian.org>
- * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 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/>.
- *
- */
-
-#include <stdint.h>
-#include <inttypes.h>
-#include <libgen.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <dbi/dbi.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/gsm_04_11.h>
-#include <openbsc/db.h>
-#include <openbsc/debug.h>
-#include <openbsc/vlr.h>
-
-#include <osmocom/gsm/protocol/gsm_23_003.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/statistics.h>
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/core/utils.h>
-
-#include <openssl/rand.h>
-
-static char *db_basename = NULL;
-static char *db_dirname = NULL;
-static dbi_conn conn;
-
-#define SCHEMA_REVISION "5"
-
-enum {
-	SCHEMA_META,
-	INSERT_META,
-	SCHEMA_SUBSCRIBER,
-	SCHEMA_AUTH,
-	SCHEMA_EQUIPMENT,
-	SCHEMA_EQUIPMENT_WATCH,
-	SCHEMA_SMS,
-	SCHEMA_VLR,
-	SCHEMA_APDU,
-	SCHEMA_COUNTERS,
-	SCHEMA_RATE,
-	SCHEMA_AUTHKEY,
-	SCHEMA_AUTHLAST,
-};
-
-static const char *create_stmts[] = {
-	[SCHEMA_META] = "CREATE TABLE IF NOT EXISTS Meta ("
-		"id INTEGER PRIMARY KEY AUTOINCREMENT, "
-		"key TEXT UNIQUE NOT NULL, "
-		"value TEXT NOT NULL"
-		")",
-	[INSERT_META] = "INSERT OR IGNORE INTO Meta "
-		"(key, value) "
-		"VALUES "
-		"('revision', " SCHEMA_REVISION ")",
-	[SCHEMA_SUBSCRIBER] = "CREATE TABLE IF NOT EXISTS 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, "
-		"expire_lu TIMESTAMP DEFAULT NULL"
-		")",
-	[SCHEMA_AUTH] = "CREATE TABLE IF NOT EXISTS AuthToken ("
-		"id INTEGER PRIMARY KEY AUTOINCREMENT, "
-		"subscriber_id INTEGER UNIQUE NOT NULL, "
-		"created TIMESTAMP NOT NULL, "
-		"token TEXT UNIQUE NOT NULL"
-		")",
-	[SCHEMA_EQUIPMENT] = "CREATE TABLE IF NOT EXISTS Equipment ("
-		"id INTEGER PRIMARY KEY AUTOINCREMENT, "
-		"created TIMESTAMP NOT NULL, "
-		"updated TIMESTAMP NOT NULL, "
-		"name TEXT, "
-		"classmark1 NUMERIC, "
-		"classmark2 BLOB, "
-		"classmark3 BLOB, "
-		"imei NUMERIC UNIQUE NOT NULL"
-		")",
-	[SCHEMA_EQUIPMENT_WATCH] = "CREATE TABLE IF NOT EXISTS EquipmentWatch ("
-		"id INTEGER PRIMARY KEY AUTOINCREMENT, "
-		"created TIMESTAMP NOT NULL, "
-		"updated TIMESTAMP NOT NULL, "
-		"subscriber_id NUMERIC NOT NULL, "
-		"equipment_id NUMERIC NOT NULL, "
-		"UNIQUE (subscriber_id, equipment_id) "
-		")",
-	[SCHEMA_SMS] = "CREATE TABLE IF NOT EXISTS SMS ("
-		/* metadata, not part of sms */
-		"id INTEGER PRIMARY KEY AUTOINCREMENT, "
-		"created TIMESTAMP NOT NULL, "
-		"sent TIMESTAMP, "
-		"deliver_attempts INTEGER NOT NULL DEFAULT 0, "
-		/* data directly copied/derived from SMS */
-		"valid_until TIMESTAMP, "
-		"reply_path_req INTEGER NOT NULL, "
-		"status_rep_req INTEGER NOT NULL, "
-		"is_report INTEGER NOT NULL, "
-		"msg_ref INTEGER NOT NULL, "
-		"protocol_id INTEGER NOT NULL, "
-		"data_coding_scheme INTEGER NOT NULL, "
-		"ud_hdr_ind INTEGER NOT NULL, "
-		"src_addr TEXT NOT NULL, "
-		"src_ton INTEGER NOT NULL, "
-		"src_npi INTEGER NOT NULL, "
-		"dest_addr TEXT NOT NULL, "
-		"dest_ton INTEGER NOT NULL, "
-		"dest_npi INTEGER NOT NULL, "
-		"user_data BLOB, "	/* TP-UD */
-		/* additional data, interpreted from SMS */
-		"header BLOB, "		/* UD Header */
-		"text TEXT "		/* decoded UD after UDH */
-		")",
-	[SCHEMA_VLR] = "CREATE TABLE IF NOT EXISTS VLR ("
-		"id INTEGER PRIMARY KEY AUTOINCREMENT, "
-		"created TIMESTAMP NOT NULL, "
-		"updated TIMESTAMP NOT NULL, "
-		"subscriber_id NUMERIC UNIQUE NOT NULL, "
-		"last_bts NUMERIC NOT NULL "
-		")",
-	[SCHEMA_APDU] = "CREATE TABLE IF NOT EXISTS ApduBlobs ("
-		"id INTEGER PRIMARY KEY AUTOINCREMENT, "
-		"created TIMESTAMP NOT NULL, "
-		"apdu_id_flags INTEGER NOT NULL, "
-		"subscriber_id INTEGER NOT NULL, "
-		"apdu BLOB "
-		")",
-	[SCHEMA_COUNTERS] = "CREATE TABLE IF NOT EXISTS Counters ("
-		"id INTEGER PRIMARY KEY AUTOINCREMENT, "
-		"timestamp TIMESTAMP NOT NULL, "
-		"value INTEGER NOT NULL, "
-		"name TEXT NOT NULL "
-		")",
-	[SCHEMA_RATE] = "CREATE TABLE IF NOT EXISTS RateCounters ("
-		"id INTEGER PRIMARY KEY AUTOINCREMENT, "
-		"timestamp TIMESTAMP NOT NULL, "
-		"value INTEGER NOT NULL, "
-		"name TEXT NOT NULL, "
-		"idx INTEGER NOT NULL "
-		")",
-	[SCHEMA_AUTHKEY] = "CREATE TABLE IF NOT EXISTS AuthKeys ("
-		"subscriber_id INTEGER PRIMARY KEY, "
-		"algorithm_id INTEGER NOT NULL, "
-		"a3a8_ki BLOB "
-		")",
-	[SCHEMA_AUTHLAST] = "CREATE TABLE IF NOT EXISTS AuthLastTuples ("
-		"subscriber_id INTEGER PRIMARY KEY, "
-		"issued TIMESTAMP NOT NULL, "
-		"use_count INTEGER NOT NULL DEFAULT 0, "
-		"key_seq INTEGER NOT NULL, "
-		"rand BLOB NOT NULL, "
-		"sres BLOB NOT NULL, "
-		"kc BLOB NOT NULL "
-		")",
-};
-
-void db_error_func(dbi_conn conn, void *data)
-{
-	const char *msg;
-	dbi_conn_error(conn, &msg);
-	LOGP(DDB, LOGL_ERROR, "DBI: %s\n", msg);
-	osmo_log_backtrace(DDB, LOGL_ERROR);
-}
-
-static int update_db_revision_2(void)
-{
-	dbi_result result;
-
-	result = dbi_conn_query(conn,
-				"ALTER TABLE Subscriber "
-				"ADD COLUMN expire_lu "
-				"TIMESTAMP DEFAULT NULL");
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-		     "Failed to alter table Subscriber (upgrade from rev 2).\n");
-		return -EINVAL;
-	}
-	dbi_result_free(result);
-
-	result = dbi_conn_query(conn,
-				"UPDATE Meta "
-				"SET value = '3' "
-				"WHERE key = 'revision'");
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-		     "Failed to update DB schema revision  (upgrade from rev 2).\n");
-		return -EINVAL;
-	}
-	dbi_result_free(result);
-
-	return 0;
-}
-
-/**
- * Copied from the normal sms_from_result_v3 to avoid having
- * to make sure that the real routine will remain backward
- * compatible.
- */
-static struct gsm_sms *sms_from_result_v3(dbi_result result)
-{
-	struct gsm_sms *sms = sms_alloc();
-	long long unsigned int sender_id;
-	const char *text, *daddr;
-	const unsigned char *user_data;
-	char buf[32];
-	char *quoted;
-	dbi_result result2;
-	const char *extension;
-
-	if (!sms)
-		return NULL;
-
-	sms->id = dbi_result_get_ulonglong(result, "id");
-
-	/* find extension by id, assuming that the subscriber still exists in
-	 * the db */
-	sender_id = dbi_result_get_ulonglong(result, "sender_id");
-	snprintf(buf, sizeof(buf), "%llu", sender_id);
-
-	dbi_conn_quote_string_copy(conn, buf, &quoted);
-	result2 = dbi_conn_queryf(conn,
-				  "SELECT extension FROM Subscriber "
-				  "WHERE id = %s ", quoted);
-	free(quoted);
-	extension = dbi_result_get_string(result2, "extension");
-	if (extension)
-		osmo_strlcpy(sms->src.addr, extension, sizeof(sms->src.addr));
-	dbi_result_free(result2);
-	/* got the extension */
-
-	sms->reply_path_req = dbi_result_get_ulonglong(result, "reply_path_req");
-	sms->status_rep_req = dbi_result_get_ulonglong(result, "status_rep_req");
-	sms->ud_hdr_ind = dbi_result_get_ulonglong(result, "ud_hdr_ind");
-	sms->protocol_id = dbi_result_get_ulonglong(result, "protocol_id");
-	sms->data_coding_scheme = dbi_result_get_ulonglong(result,
-						  "data_coding_scheme");
-
-	daddr = dbi_result_get_string(result, "dest_addr");
-	if (daddr)
-		osmo_strlcpy(sms->dst.addr, daddr, sizeof(sms->dst.addr));
-
-	sms->user_data_len = dbi_result_get_field_length(result, "user_data");
-	user_data = dbi_result_get_binary(result, "user_data");
-	if (sms->user_data_len > sizeof(sms->user_data))
-		sms->user_data_len = (uint8_t) sizeof(sms->user_data);
-	memcpy(sms->user_data, user_data, sms->user_data_len);
-
-	text = dbi_result_get_string(result, "text");
-	if (text)
-		osmo_strlcpy(sms->text, text, sizeof(sms->text));
-	return sms;
-}
-
-static int update_db_revision_3(void)
-{
-	dbi_result result;
-	struct gsm_sms *sms;
-
-	LOGP(DDB, LOGL_NOTICE, "Going to migrate from revision 3\n");
-
-	result = dbi_conn_query(conn, "BEGIN EXCLUSIVE TRANSACTION");
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-			"Failed to begin transaction (upgrade from rev 3)\n");
-		return -EINVAL;
-	}
-	dbi_result_free(result);
-
-	/* Rename old SMS table to be able create a new one */
-	result = dbi_conn_query(conn, "ALTER TABLE SMS RENAME TO SMS_3");
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-		     "Failed to rename the old SMS table (upgrade from rev 3).\n");
-		goto rollback;
-	}
-	dbi_result_free(result);
-
-	/* Create new SMS table with all the bells and whistles! */
-	result = dbi_conn_query(conn, create_stmts[SCHEMA_SMS]);
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-		     "Failed to create a new SMS table (upgrade from rev 3).\n");
-		goto rollback;
-	}
-	dbi_result_free(result);
-
-	/* Cycle through old messages and convert them to the new format */
-	result = dbi_conn_query(conn, "SELECT * FROM SMS_3");
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-		     "Failed fetch messages from the old SMS table (upgrade from rev 3).\n");
-		goto rollback;
-	}
-	while (dbi_result_next_row(result)) {
-		sms = sms_from_result_v3(result);
-		if (db_sms_store(sms) != 0) {
-			LOGP(DDB, LOGL_ERROR, "Failed to store message to the new SMS table(upgrade from rev 3).\n");
-			sms_free(sms);
-			dbi_result_free(result);
-			goto rollback;
-		}
-		sms_free(sms);
-	}
-	dbi_result_free(result);
-
-	/* Remove the temporary table */
-	result = dbi_conn_query(conn, "DROP TABLE SMS_3");
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-		     "Failed to drop the old SMS table (upgrade from rev 3).\n");
-		goto rollback;
-	}
-	dbi_result_free(result);
-
-	/* We're done. Bump DB Meta revision to 4 */
-	result = dbi_conn_query(conn,
-				"UPDATE Meta "
-				"SET value = '4' "
-				"WHERE key = 'revision'");
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-		     "Failed to update DB schema revision (upgrade from rev 3).\n");
-		goto rollback;
-	}
-	dbi_result_free(result);
-
-	result = dbi_conn_query(conn, "COMMIT TRANSACTION");
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-			"Failed to commit the transaction (upgrade from rev 3)\n");
-		return -EINVAL;
-	} else {
-		dbi_result_free(result);
-	}
-
-	/* Shrink DB file size by actually wiping out SMS_3 table data */
-	result = dbi_conn_query(conn, "VACUUM");
-	if (!result)
-		LOGP(DDB, LOGL_ERROR,
-			"VACUUM failed. Ignoring it (upgrade from rev 3).\n");
-	else
-		dbi_result_free(result);
-
-	return 0;
-
-rollback:
-	result = dbi_conn_query(conn, "ROLLBACK TRANSACTION");
-	if (!result)
-		LOGP(DDB, LOGL_ERROR,
-			"Rollback failed (upgrade from rev 3).\n");
-	else
-		dbi_result_free(result);
-	return -EINVAL;
-}
-
-/* Just like v3, but there is a new message reference field for status reports,
- * that is set to zero for existing entries since there is no way we can infer
- * this.
- */
-static struct gsm_sms *sms_from_result_v4(dbi_result result)
-{
-	struct gsm_sms *sms = sms_alloc();
-	const unsigned char *user_data;
-	const char *text, *addr;
-
-	if (!sms)
-		return NULL;
-
-	sms->id = dbi_result_get_ulonglong(result, "id");
-
-	sms->reply_path_req = dbi_result_get_ulonglong(result, "reply_path_req");
-	sms->status_rep_req = dbi_result_get_ulonglong(result, "status_rep_req");
-	sms->ud_hdr_ind = dbi_result_get_ulonglong(result, "ud_hdr_ind");
-	sms->protocol_id = dbi_result_get_ulonglong(result, "protocol_id");
-	sms->data_coding_scheme = dbi_result_get_ulonglong(result,
-						  "data_coding_scheme");
-
-	addr = dbi_result_get_string(result, "src_addr");
-	osmo_strlcpy(sms->src.addr, addr, sizeof(sms->src.addr));
-	sms->src.ton = dbi_result_get_ulonglong(result, "src_ton");
-	sms->src.npi = dbi_result_get_ulonglong(result, "src_npi");
-
-	addr = dbi_result_get_string(result, "dest_addr");
-	osmo_strlcpy(sms->dst.addr, addr, sizeof(sms->dst.addr));
-	sms->dst.ton = dbi_result_get_ulonglong(result, "dest_ton");
-	sms->dst.npi = dbi_result_get_ulonglong(result, "dest_npi");
-
-	sms->user_data_len = dbi_result_get_field_length(result, "user_data");
-	user_data = dbi_result_get_binary(result, "user_data");
-	if (sms->user_data_len > sizeof(sms->user_data))
-		sms->user_data_len = (uint8_t) sizeof(sms->user_data);
-	memcpy(sms->user_data, user_data, sms->user_data_len);
-
-	text = dbi_result_get_string(result, "text");
-	if (text)
-		osmo_strlcpy(sms->text, text, sizeof(sms->text));
-	return sms;
-}
-
-static int update_db_revision_4(void)
-{
-	dbi_result result;
-	struct gsm_sms *sms;
-
-	LOGP(DDB, LOGL_NOTICE, "Going to migrate from revision 4\n");
-
-	result = dbi_conn_query(conn, "BEGIN EXCLUSIVE TRANSACTION");
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-			"Failed to begin transaction (upgrade from rev 4)\n");
-		return -EINVAL;
-	}
-	dbi_result_free(result);
-
-	/* Rename old SMS table to be able create a new one */
-	result = dbi_conn_query(conn, "ALTER TABLE SMS RENAME TO SMS_4");
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-		     "Failed to rename the old SMS table (upgrade from rev 4).\n");
-		goto rollback;
-	}
-	dbi_result_free(result);
-
-	/* Create new SMS table with all the bells and whistles! */
-	result = dbi_conn_query(conn, create_stmts[SCHEMA_SMS]);
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-		     "Failed to create a new SMS table (upgrade from rev 4).\n");
-		goto rollback;
-	}
-	dbi_result_free(result);
-
-	/* Cycle through old messages and convert them to the new format */
-	result = dbi_conn_query(conn, "SELECT * FROM SMS_4");
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-		     "Failed fetch messages from the old SMS table (upgrade from rev 4).\n");
-		goto rollback;
-	}
-	while (dbi_result_next_row(result)) {
-		sms = sms_from_result_v4(result);
-		if (db_sms_store(sms) != 0) {
-			LOGP(DDB, LOGL_ERROR, "Failed to store message to the new SMS table(upgrade from rev 4).\n");
-			sms_free(sms);
-			dbi_result_free(result);
-			goto rollback;
-		}
-		sms_free(sms);
-	}
-	dbi_result_free(result);
-
-	/* Remove the temporary table */
-	result = dbi_conn_query(conn, "DROP TABLE SMS_4");
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-		     "Failed to drop the old SMS table (upgrade from rev 4).\n");
-		goto rollback;
-	}
-	dbi_result_free(result);
-
-	/* We're done. Bump DB Meta revision to 4 */
-	result = dbi_conn_query(conn,
-				"UPDATE Meta "
-				"SET value = '5' "
-				"WHERE key = 'revision'");
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-		     "Failed to update DB schema revision (upgrade from rev 4).\n");
-		goto rollback;
-	}
-	dbi_result_free(result);
-
-	result = dbi_conn_query(conn, "COMMIT TRANSACTION");
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-			"Failed to commit the transaction (upgrade from rev 4)\n");
-		return -EINVAL;
-	} else {
-		dbi_result_free(result);
-	}
-
-	/* Shrink DB file size by actually wiping out SMS_4 table data */
-	result = dbi_conn_query(conn, "VACUUM");
-	if (!result)
-		LOGP(DDB, LOGL_ERROR,
-			"VACUUM failed. Ignoring it (upgrade from rev 4).\n");
-	else
-		dbi_result_free(result);
-
-	return 0;
-
-rollback:
-	result = dbi_conn_query(conn, "ROLLBACK TRANSACTION");
-	if (!result)
-		LOGP(DDB, LOGL_ERROR,
-			"Rollback failed (upgrade from rev 4).\n");
-	else
-		dbi_result_free(result);
-	return -EINVAL;
-}
-
-static int check_db_revision(void)
-{
-	dbi_result result;
-	const char *rev_s;
-	int db_rev = 0;
-
-	/* Make a query */
-	result = dbi_conn_query(conn,
-		"SELECT value FROM Meta "
-		"WHERE key = 'revision'");
-
-	if (!result)
-		return -EINVAL;
-
-	if (!dbi_result_next_row(result)) {
-		dbi_result_free(result);
-		return -EINVAL;
-	}
-
-	/* Fetch the DB schema revision */
-	rev_s = dbi_result_get_string(result, "value");
-	if (!rev_s) {
-		dbi_result_free(result);
-		return -EINVAL;
-	}
-
-	if (!strcmp(rev_s, SCHEMA_REVISION)) {
-		/* Everything is fine */
-		dbi_result_free(result);
-		return 0;
-	}
-
-	db_rev = atoi(rev_s);
-	dbi_result_free(result);
-
-	/* Incremental migration waterfall */
-	switch (db_rev) {
-	case 2:
-		if (update_db_revision_2())
-			goto error;
-	case 3:
-		if (update_db_revision_3())
-			goto error;
-	case 4:
-		if (update_db_revision_4())
-			goto error;
-
-	/* The end of waterfall */
-	break;
-	default:
-		LOGP(DDB, LOGL_FATAL,
-			"Invalid database schema revision '%d'.\n", db_rev);
-		return -EINVAL;
-	}
-
-	return 0;
-
-error:
-	LOGP(DDB, LOGL_FATAL, "Failed to update database "
-		"from schema revision '%d'.\n", db_rev);
-	return -EINVAL;
-}
-
-static int db_configure(void)
-{
-	dbi_result result;
-
-	result = dbi_conn_query(conn,
-				"PRAGMA synchronous = FULL");
-	if (!result)
-		return -EINVAL;
-
-	dbi_result_free(result);
-	return 0;
-}
-
-int db_init(const char *name)
-{
-	dbi_initialize(NULL);
-
-	conn = dbi_conn_new("sqlite3");
-	if (conn == NULL) {
-		LOGP(DDB, LOGL_FATAL, "Failed to create connection.\n");
-		return 1;
-	}
-
-	dbi_conn_error_handler( conn, db_error_func, NULL );
-
-	/* MySQL
-	dbi_conn_set_option(conn, "host", "localhost");
-	dbi_conn_set_option(conn, "username", "your_name");
-	dbi_conn_set_option(conn, "password", "your_password");
-	dbi_conn_set_option(conn, "dbname", "your_dbname");
-	dbi_conn_set_option(conn, "encoding", "UTF-8");
-	*/
-
-	/* SqLite 3 */
-	db_basename = strdup(name);
-	db_dirname = strdup(name);
-	dbi_conn_set_option(conn, "sqlite3_dbdir", dirname(db_dirname));
-	dbi_conn_set_option(conn, "dbname", basename(db_basename));
-
-	if (dbi_conn_connect(conn) < 0)
-		goto out_err;
-
-	return 0;
-
-out_err:
-	free(db_dirname);
-	free(db_basename);
-	db_dirname = db_basename = NULL;
-	return -1;
-}
-
-
-int db_prepare(void)
-{
-	dbi_result result;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(create_stmts); i++) {
-		result = dbi_conn_query(conn, create_stmts[i]);
-		if (!result) {
-			LOGP(DDB, LOGL_ERROR,
-			     "Failed to create some table.\n");
-			return 1;
-		}
-		dbi_result_free(result);
-	}
-
-	if (check_db_revision() < 0) {
-		LOGP(DDB, LOGL_FATAL, "Database schema revision invalid, "
-			"please update your database schema\n");
-                return -1;
-	}
-
-	db_configure();
-
-	return 0;
-}
-
-int db_fini(void)
-{
-	dbi_conn_close(conn);
-	dbi_shutdown();
-
-	free(db_dirname);
-	free(db_basename);
-	return 0;
-}
-
-/* store an [unsent] SMS to the database */
-int db_sms_store(struct gsm_sms *sms)
-{
-	dbi_result result;
-	char *q_text, *q_daddr, *q_saddr;
-	unsigned char *q_udata;
-	char *validity_timestamp = "2222-2-2";
-
-	/* FIXME: generate validity timestamp based on validity_minutes */
-
-	dbi_conn_quote_string_copy(conn, (char *)sms->text, &q_text);
-	dbi_conn_quote_string_copy(conn, (char *)sms->dst.addr, &q_daddr);
-	dbi_conn_quote_string_copy(conn, (char *)sms->src.addr, &q_saddr);
-	dbi_conn_quote_binary_copy(conn, sms->user_data, sms->user_data_len,
-				   &q_udata);
-
-	/* FIXME: correct validity period */
-	result = dbi_conn_queryf(conn,
-		"INSERT INTO SMS "
-		"(created, valid_until, "
-		 "reply_path_req, status_rep_req, is_report, "
-		 "msg_ref, protocol_id, data_coding_scheme, "
-		 "ud_hdr_ind, "
-		 "user_data, text, "
-		 "dest_addr, dest_ton, dest_npi, "
-		 "src_addr, src_ton, src_npi) VALUES "
-		"(datetime('now'), %u, "
-		"%u, %u, %u, "
-		"%u, %u, %u, "
-		"%u, "
-		"%s, %s, "
-		"%s, %u, %u, "
-		"%s, %u, %u)",
-		validity_timestamp,
-		sms->reply_path_req, sms->status_rep_req, sms->is_report,
-		sms->msg_ref, sms->protocol_id, sms->data_coding_scheme,
-		sms->ud_hdr_ind,
-		q_udata, q_text,
-		q_daddr, sms->dst.ton, sms->dst.npi,
-		q_saddr, sms->src.ton, sms->src.npi);
-	free(q_text);
-	free(q_udata);
-	free(q_daddr);
-	free(q_saddr);
-
-	if (!result)
-		return -EIO;
-
-	dbi_result_free(result);
-	return 0;
-}
-
-static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result result)
-{
-	struct gsm_sms *sms = sms_alloc();
-	const char *text, *daddr, *saddr;
-	const unsigned char *user_data;
-
-	if (!sms)
-		return NULL;
-
-	sms->id = dbi_result_get_ulonglong(result, "id");
-
-	/* FIXME: validity */
-	/* FIXME: those should all be get_uchar, but sqlite3 is braindead */
-	sms->created = dbi_result_get_datetime(result, "created");
-	sms->reply_path_req = dbi_result_get_ulonglong(result, "reply_path_req");
-	sms->status_rep_req = dbi_result_get_ulonglong(result, "status_rep_req");
-	sms->is_report = dbi_result_get_ulonglong(result, "is_report");
-	sms->msg_ref = dbi_result_get_ulonglong(result, "msg_ref");
-	sms->ud_hdr_ind = dbi_result_get_ulonglong(result, "ud_hdr_ind");
-	sms->protocol_id = dbi_result_get_ulonglong(result, "protocol_id");
-	sms->data_coding_scheme = dbi_result_get_ulonglong(result,
-						  "data_coding_scheme");
-
-	sms->dst.npi = dbi_result_get_ulonglong(result, "dest_npi");
-	sms->dst.ton = dbi_result_get_ulonglong(result, "dest_ton");
-	daddr = dbi_result_get_string(result, "dest_addr");
-	if (daddr)
-		osmo_strlcpy(sms->dst.addr, daddr, sizeof(sms->dst.addr));
-	sms->receiver = vlr_subscr_find_by_msisdn(net->vlr, sms->dst.addr);
-
-	sms->src.npi = dbi_result_get_ulonglong(result, "src_npi");
-	sms->src.ton = dbi_result_get_ulonglong(result, "src_ton");
-	saddr = dbi_result_get_string(result, "src_addr");
-	if (saddr)
-		osmo_strlcpy(sms->src.addr, saddr, sizeof(sms->src.addr));
-
-	sms->user_data_len = dbi_result_get_field_length(result, "user_data");
-	user_data = dbi_result_get_binary(result, "user_data");
-	if (sms->user_data_len > sizeof(sms->user_data))
-		sms->user_data_len = (uint8_t) sizeof(sms->user_data);
-	memcpy(sms->user_data, user_data, sms->user_data_len);
-
-	text = dbi_result_get_string(result, "text");
-	if (text)
-		osmo_strlcpy(sms->text, text, sizeof(sms->text));
-	return sms;
-}
-
-struct gsm_sms *db_sms_get(struct gsm_network *net, unsigned long long id)
-{
-	dbi_result result;
-	struct gsm_sms *sms;
-
-	result = dbi_conn_queryf(conn,
-		"SELECT * FROM SMS WHERE SMS.id = %llu", id);
-	if (!result)
-		return NULL;
-
-	if (!dbi_result_next_row(result)) {
-		dbi_result_free(result);
-		return NULL;
-	}
-
-	sms = sms_from_result(net, result);
-
-	dbi_result_free(result);
-
-	return sms;
-}
-
-struct gsm_sms *db_sms_get_next_unsent(struct gsm_network *net,
-				       unsigned long long min_sms_id,
-				       unsigned int max_failed)
-{
-	dbi_result result;
-	struct gsm_sms *sms;
-
-	result = dbi_conn_queryf(conn,
-		"SELECT * FROM SMS"
-		" WHERE sent IS NULL"
-		" AND id >= %llu"
-		" AND deliver_attempts <= %u"
-		" ORDER BY id LIMIT 1",
-		min_sms_id, max_failed);
-
-	if (!result)
-		return NULL;
-
-	if (!dbi_result_next_row(result)) {
-		dbi_result_free(result);
-		return NULL;
-	}
-
-	sms = sms_from_result(net, result);
-
-	dbi_result_free(result);
-
-	return sms;
-}
-
-/* retrieve the next unsent SMS for a given subscriber */
-struct gsm_sms *db_sms_get_unsent_for_subscr(struct vlr_subscr *vsub,
-					     unsigned int max_failed)
-{
-	struct gsm_network *net = vsub->vlr->user_ctx;
-	dbi_result result;
-	struct gsm_sms *sms;
-
-	if (!vsub->lu_complete)
-		return NULL;
-
-	result = dbi_conn_queryf(conn,
-		"SELECT * FROM SMS"
-		" WHERE sent IS NULL"
-		" AND dest_addr=%s"
-		" AND deliver_attempts <= %u"
-		" ORDER BY id LIMIT 1",
-		vsub->msisdn, max_failed);
-	if (!result)
-		return NULL;
-
-	if (!dbi_result_next_row(result)) {
-		dbi_result_free(result);
-		return NULL;
-	}
-
-	sms = sms_from_result(net, result);
-
-	dbi_result_free(result);
-
-	return sms;
-}
-
-struct gsm_sms *db_sms_get_next_unsent_rr_msisdn(struct gsm_network *net,
-						 const char *last_msisdn,
-						 unsigned int max_failed)
-{
-	dbi_result result;
-	struct gsm_sms *sms;
-
-	result = dbi_conn_queryf(conn,
-		"SELECT * FROM SMS"
-		" WHERE sent IS NULL"
-		" AND dest_addr > '%s'"
-		" AND deliver_attempts <= %u"
-		" ORDER BY dest_addr, id LIMIT 1",
-		last_msisdn, max_failed);
-	if (!result)
-		return NULL;
-
-	if (!dbi_result_next_row(result)) {
-		dbi_result_free(result);
-		return NULL;
-	}
-
-	sms = sms_from_result(net, result);
-
-	dbi_result_free(result);
-
-	return sms;
-}
-
-/* mark a given SMS as delivered */
-int db_sms_mark_delivered(struct gsm_sms *sms)
-{
-	dbi_result result;
-
-	result = dbi_conn_queryf(conn,
-		"UPDATE SMS "
-		"SET sent = datetime('now') "
-		"WHERE id = %llu", sms->id);
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR, "Failed to mark SMS %llu as sent.\n", sms->id);
-		return 1;
-	}
-
-	dbi_result_free(result);
-	return 0;
-}
-
-/* increase the number of attempted deliveries */
-int db_sms_inc_deliver_attempts(struct gsm_sms *sms)
-{
-	dbi_result result;
-
-	result = dbi_conn_queryf(conn,
-		"UPDATE SMS "
-		"SET deliver_attempts = deliver_attempts + 1 "
-		"WHERE id = %llu", sms->id);
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR, "Failed to inc deliver attempts for "
-			"SMS %llu.\n", sms->id);
-		return 1;
-	}
-
-	dbi_result_free(result);
-	return 0;
-}
-
-/* Drop all pending SMS to or from the given extension */
-int db_sms_delete_by_msisdn(const char *msisdn)
-{
-	dbi_result result;
-	if (!msisdn || !*msisdn)
-		return 0;
-	result = dbi_conn_queryf(conn,
-		    "DELETE FROM SMS WHERE src_addr=%s OR dest_addr=%s",
-		    msisdn, msisdn);
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-		     "Failed to delete SMS for %s\n", msisdn);
-		return -1;
-	}
-	dbi_result_free(result);
-	return 0;
-}
-
-int db_store_counter(struct osmo_counter *ctr)
-{
-	dbi_result result;
-	char *q_name;
-
-	dbi_conn_quote_string_copy(conn, ctr->name, &q_name);
-
-	result = dbi_conn_queryf(conn,
-		"INSERT INTO Counters "
-		"(timestamp,name,value) VALUES "
-		"(datetime('now'),%s,%lu)", q_name, ctr->value);
-
-	free(q_name);
-
-	if (!result)
-		return -EIO;
-
-	dbi_result_free(result);
-	return 0;
-}
-
-static int db_store_rate_ctr(struct rate_ctr_group *ctrg, unsigned int num,
-			     char *q_prefix)
-{
-	dbi_result result;
-	char *q_name;
-
-	dbi_conn_quote_string_copy(conn, ctrg->desc->ctr_desc[num].name,
-				   &q_name);
-
-	result = dbi_conn_queryf(conn,
-		"Insert INTO RateCounters "
-		"(timestamp,name,idx,value) VALUES "
-		"(datetime('now'),%s.%s,%u,%"PRIu64")",
-		q_prefix, q_name, ctrg->idx, ctrg->ctr[num].current);
-
-	free(q_name);
-
-	if (!result)
-		return -EIO;
-
-	dbi_result_free(result);
-	return 0;
-}
-
-int db_store_rate_ctr_group(struct rate_ctr_group *ctrg)
-{
-	unsigned int i;
-	char *q_prefix;
-
-	dbi_conn_quote_string_copy(conn, ctrg->desc->group_name_prefix, &q_prefix);
-
-	for (i = 0; i < ctrg->desc->num_ctr; i++)
-		db_store_rate_ctr(ctrg, i, q_prefix);
-
-	free(q_prefix);
-
-	return 0;
-}
diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c
deleted file mode 100644
index 21bc2b8..0000000
--- a/src/libmsc/gsm_04_08.c
+++ /dev/null
@@ -1,3493 +0,0 @@
-/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
- * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
-
-/* (C) 2008-2016 by Harald Welte <laforge@gnumonks.org>
- * (C) 2008-2012 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/>.
- *
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdbool.h>
-#include <errno.h>
-#include <time.h>
-#include <netinet/in.h>
-#include <regex.h>
-#include <sys/types.h>
-#include <openssl/rand.h>
-
-#include "bscconfig.h"
-
-#include <openbsc/auth.h>
-#include <openbsc/db.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/gsm_04_11.h>
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/gsm_04_80.h>
-#include <openbsc/gsm_04_14.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/chan_alloc.h>
-#include <openbsc/paging.h>
-#include <openbsc/signal.h>
-#include <osmocom/abis/trau_frame.h>
-#include <openbsc/trau_mux.h>
-#include <openbsc/rtp_proxy.h>
-#include <openbsc/transaction.h>
-#include <openbsc/ussd.h>
-#include <openbsc/silent_call.h>
-#include <openbsc/bsc_api.h>
-#include <openbsc/osmo_msc.h>
-#include <openbsc/handover.h>
-#include <openbsc/mncc_int.h>
-#include <osmocom/abis/e1_input.h>
-#include <osmocom/core/bitvec.h>
-#include <openbsc/vlr.h>
-#include <openbsc/msc_ifaces.h>
-
-#include <osmocom/gsm/gsm48.h>
-#include <osmocom/gsm/gsm0480.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/gsm/protocol/gsm_04_08.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/crypt/auth.h>
-#ifdef BUILD_IU
-#include <osmocom/ranap/iu_client.h>
-#endif
-
-#include <openbsc/msc_ifaces.h>
-#include <openbsc/a_iface.h>
-
-#include <assert.h>
-
-
-void *tall_locop_ctx;
-void *tall_authciphop_ctx;
-
-static int gsm0408_loc_upd_acc(struct gsm_subscriber_connection *conn,
-			       uint32_t send_tmsi);
-static int gsm48_tx_simple(struct gsm_subscriber_connection *conn,
-			   uint8_t pdisc, uint8_t msg_type);
-
-struct gsm_lai {
-	uint16_t mcc;
-	uint16_t mnc;
-	uint16_t lac;
-};
-
-static uint32_t new_callref = 0x80000001;
-
-void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg)
-{
-	net->mncc_recv(net, msg);
-}
-
-static int gsm48_conn_sendmsg(struct msgb *msg, struct gsm_subscriber_connection *conn,
-			      struct gsm_trans *trans)
-{
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
-
-	/* if we get passed a transaction reference, do some common
-	 * work that the caller no longer has to do */
-	if (trans) {
-		gh->proto_discr = trans->protocol | (trans->transaction_id << 4);
-	}
-
-	return msc_tx_dtap(conn, msg);
-}
-
-int gsm48_cc_tx_notify_ss(struct gsm_trans *trans, const char *message)
-{
-	struct gsm48_hdr *gh;
-	struct msgb *ss_notify;
-
-	ss_notify = gsm0480_create_notifySS(message);
-	if (!ss_notify)
-		return -1;
-
-	gsm0480_wrap_invoke(ss_notify, GSM0480_OP_CODE_NOTIFY_SS, 0);
-	uint8_t *data = msgb_push(ss_notify, 1);
-	data[0] = ss_notify->len - 1;
-	gh = (struct gsm48_hdr *) msgb_push(ss_notify, sizeof(*gh));
-	gh->msg_type = GSM48_MT_CC_FACILITY;
-	return gsm48_conn_sendmsg(ss_notify, trans->conn, trans);
-}
-
-/* clear all transactions globally; used in case of MNCC socket disconnect */
-void gsm0408_clear_all_trans(struct gsm_network *net, int protocol)
-{
-	struct gsm_trans *trans, *temp;
-
-	LOGP(DCC, LOGL_NOTICE, "Clearing all currently active transactions!!!\n");
-
-	llist_for_each_entry_safe(trans, temp, &net->trans_list, entry) {
-		if (trans->protocol == protocol) {
-			trans->callref = 0;
-			trans_free(trans);
-		}
-	}
-}
-
-/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
-static int gsm0408_loc_upd_rej(struct gsm_subscriber_connection *conn, uint8_t cause)
-{
-	struct msgb *msg;
-
-	msg = gsm48_create_loc_upd_rej(cause);
-	if (!msg) {
-		LOGP(DMM, LOGL_ERROR, "Failed to create msg for LOCATION UPDATING REJECT.\n");
-		return -1;
-	}
-
-	LOGP(DMM, LOGL_INFO, "Subscriber %s: LOCATION UPDATING REJECT\n",
-	     vlr_subscr_name(conn->vsub));
-
-	return gsm48_conn_sendmsg(msg, conn, NULL);
-}
-
-/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
-static int gsm0408_loc_upd_acc(struct gsm_subscriber_connection *conn,
-			       uint32_t send_tmsi)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 LOC UPD ACC");
-	struct gsm48_hdr *gh;
-	struct gsm48_loc_area_id *lai;
-	uint8_t *mid;
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	gh->proto_discr = GSM48_PDISC_MM;
-	gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
-
-	lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
-	gsm48_generate_lai(lai, conn->network->country_code,
-			   conn->network->network_code,
-			   conn->lac);
-
-	if (send_tmsi == GSM_RESERVED_TMSI) {
-		/* we did not allocate a TMSI to the MS, so we need to
-		 * include the IMSI in order for the MS to delete any
-		 * old TMSI that might still be allocated */
-		uint8_t mi[10];
-		int len;
-		len = gsm48_generate_mid_from_imsi(mi, conn->vsub->imsi);
-		mid = msgb_put(msg, len);
-		memcpy(mid, mi, len);
-		DEBUGP(DMM, "-> %s LOCATION UPDATE ACCEPT\n",
-		       vlr_subscr_name(conn->vsub));
-	} else {
-		/* Include the TMSI, which means that the MS will send a
-		 * TMSI REALLOCATION COMPLETE, and we should wait for
-		 * that until T3250 expiration */
-		mid = msgb_put(msg, GSM48_MID_TMSI_LEN);
-		gsm48_generate_mid_from_tmsi(mid, send_tmsi);
-		DEBUGP(DMM, "-> %s LOCATION UPDATE ACCEPT (TMSI = 0x%08x)\n",
-		       vlr_subscr_name(conn->vsub),
-		       send_tmsi);
-	}
-	/* TODO: Follow-on proceed */
-	/* TODO: CTS permission */
-	/* TODO: Equivalent PLMNs */
-	/* TODO: Emergency Number List */
-	/* TODO: Per-MS T3312 */
-
-
-	return gsm48_conn_sendmsg(msg, conn, NULL);
-}
-
-/* Transmit Chapter 9.2.10 Identity Request */
-static int mm_tx_identity_req(struct gsm_subscriber_connection *conn, uint8_t id_type)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ID REQ");
-	struct gsm48_hdr *gh;
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
-	gh->proto_discr = GSM48_PDISC_MM;
-	gh->msg_type = GSM48_MT_MM_ID_REQ;
-	gh->data[0] = id_type;
-
-	return gsm48_conn_sendmsg(msg, conn, NULL);
-}
-
-/* Parse Chapter 9.2.11 Identity Response */
-static int mm_rx_id_resp(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	uint8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
-	char mi_string[GSM48_MI_SIZE];
-
-	if (!conn->vsub) {
-		LOGP(DMM, LOGL_ERROR,
-		     "Rx MM Identity Response: invalid: no subscriber\n");
-		return -EINVAL;
-	}
-
-	gsm48_mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
-	DEBUGP(DMM, "IDENTITY RESPONSE: MI(%s)=%s\n",
-		gsm48_mi_type_name(mi_type), mi_string);
-
-	osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_IDENTITY, gh->data);
-
-	return vlr_subscr_rx_id_resp(conn->vsub, gh->data+1, gh->data[0]);
-}
-
-/* FIXME: to libosmogsm */
-static const struct value_string lupd_names[] = {
-	{ GSM48_LUPD_NORMAL, "NORMAL" },
-	{ GSM48_LUPD_PERIODIC, "PERIODIC" },
-	{ GSM48_LUPD_IMSI_ATT, "IMSI ATTACH" },
-	{ 0, NULL }
-};
-
-/* Chapter 9.2.15: Receive Location Updating Request.
- * Keep this function non-static for direct invocation by unit tests. */
-int mm_rx_loc_upd_req(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	static const enum subscr_conn_from conn_from_lu = SUBSCR_CONN_FROM_LU;
-	struct gsm_network *net = conn->network;
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	struct gsm48_loc_upd_req *lu;
-	uint8_t mi_type;
-	char mi_string[GSM48_MI_SIZE];
-	enum vlr_lu_type vlr_lu_type = VLR_LU_TYPE_REGULAR;
-	uint32_t tmsi;
-	char *imsi;
-	struct osmo_location_area_id old_lai, new_lai;
-	struct osmo_fsm_inst *lu_fsm;
-	bool is_utran;
-	int rc;
-
- 	lu = (struct gsm48_loc_upd_req *) gh->data;
-
-	mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
-
-	gsm48_mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
-
-	rc = msc_create_conn_fsm(conn, mi_string);
-	if (rc)
-		/* logging already happened in msc_create_conn_fsm() */
-		return rc;
-
-	conn->classmark.classmark1 = lu->classmark1;
-	conn->classmark.classmark1_set = true;
-
-	DEBUGP(DMM, "LOCATION UPDATING REQUEST: MI(%s)=%s type=%s\n",
-	       gsm48_mi_type_name(mi_type), mi_string,
-	       get_value_string(lupd_names, lu->type));
-
-	osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_IDENTITY, &lu->mi_len);
-
-	switch (lu->type) {
-	case GSM48_LUPD_NORMAL:
-		rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL]);
-		vlr_lu_type = VLR_LU_TYPE_REGULAR;
-		break;
-	case GSM48_LUPD_IMSI_ATT:
-		rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH]);
-		vlr_lu_type = VLR_LU_TYPE_IMSI_ATTACH;
-		break;
-	case GSM48_LUPD_PERIODIC:
-		rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC]);
-		vlr_lu_type = VLR_LU_TYPE_PERIODIC;
-		break;
-	}
-
-	/* TODO: 10.5.1.6 MS Classmark for UMTS / Classmark 2 */
-	/* TODO: 10.5.3.14 Aditional update parameters (CS fallback calls) */
-	/* TODO: 10.5.7.8 Device properties */
-	/* TODO: 10.5.1.15 MS network feature support */
-
-	switch (mi_type) {
-	case GSM_MI_TYPE_IMSI:
-		tmsi = GSM_RESERVED_TMSI;
-		imsi = mi_string;
-		break;
-	case GSM_MI_TYPE_TMSI:
-		tmsi = tmsi_from_string(mi_string);
-		imsi = NULL;
-		break;
-	default:
-		DEBUGPC(DMM, "unknown mobile identity type\n");
-		tmsi = GSM_RESERVED_TMSI;
-		imsi = NULL;
-		break;
-	}
-
-	gsm48_decode_lai(&lu->lai, &old_lai.plmn.mcc,
-			 &old_lai.plmn.mnc, &old_lai.lac);
-	new_lai.plmn.mcc = conn->network->country_code;
-	new_lai.plmn.mnc = conn->network->network_code;
-	new_lai.lac = conn->lac;
-	DEBUGP(DMM, "LU/new-LAC: %u/%u\n", old_lai.lac, new_lai.lac);
-
-	is_utran = (conn->via_ran == RAN_UTRAN_IU);
-	lu_fsm = vlr_loc_update(conn->conn_fsm,
-				SUBSCR_CONN_E_ACCEPTED,
-				SUBSCR_CONN_E_CN_CLOSE,
-				(void*)&conn_from_lu,
-				net->vlr, conn, vlr_lu_type, tmsi, imsi,
-				&old_lai, &new_lai,
-				is_utran || conn->network->authentication_required,
-				is_utran? VLR_CIPH_A5_3
-					: conn->network->a5_encryption,
-				classmark_is_r99(&conn->classmark),
-				is_utran,
-				net->vlr->cfg.assign_tmsi);
-	if (!lu_fsm) {
-		DEBUGP(DRR, "%s: Can't start LU FSM\n", mi_string);
-		return 0;
-	}
-
-	/* From vlr_loc_update() we expect an implicit dispatch of
-	 * VLR_ULA_E_UPDATE_LA, and thus we expect msc_vlr_subscr_assoc() to
-	 * already have been called and completed. Has an error occured? */
-
-	if (!conn->vsub || conn->vsub->lu_fsm != lu_fsm) {
-		LOGP(DRR, LOGL_ERROR,
-		     "%s: internal error during Location Updating attempt\n",
-		     mi_string);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-/* Turn int into semi-octet representation: 98 => 0x89 */
-/* FIXME: libosmocore/libosmogsm */
-static uint8_t bcdify(uint8_t value)
-{
-        uint8_t ret;
-
-        ret = value / 10;
-        ret |= (value % 10) << 4;
-
-        return ret;
-}
-
-
-/* Section 9.2.15a */
-int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 MM INF");
-	struct gsm48_hdr *gh;
-	struct gsm_network *net = conn->network;
-	uint8_t *ptr8;
-	int name_len, name_pad;
-
-	time_t cur_t;
-	struct tm* gmt_time;
-	struct tm* local_time;
-	int tzunits;
-	int dst = 0;
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	gh->proto_discr = GSM48_PDISC_MM;
-	gh->msg_type = GSM48_MT_MM_INFO;
-
-	if (net->name_long) {
-#if 0
-		name_len = strlen(net->name_long);
-		/* 10.5.3.5a */
-		ptr8 = msgb_put(msg, 3);
-		ptr8[0] = GSM48_IE_NAME_LONG;
-		ptr8[1] = name_len*2 +1;
-		ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
-
-		ptr16 = (uint16_t *) msgb_put(msg, name_len*2);
-		for (i = 0; i < name_len; i++)
-			ptr16[i] = htons(net->name_long[i]);
-
-		/* FIXME: Use Cell Broadcast, not UCS-2, since
-		 * UCS-2 is only supported by later revisions of the spec */
-#endif
-		name_len = (strlen(net->name_long)*7)/8;
-		name_pad = (8 - strlen(net->name_long)*7)%8;
-		if (name_pad > 0)
-			name_len++;
-		/* 10.5.3.5a */
-		ptr8 = msgb_put(msg, 3);
-		ptr8[0] = GSM48_IE_NAME_LONG;
-		ptr8[1] = name_len +1;
-		ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */
-
-		ptr8 = msgb_put(msg, name_len);
-		gsm_7bit_encode_n(ptr8, name_len, net->name_long, NULL);
-
-	}
-
-	if (net->name_short) {
-#if 0
-		name_len = strlen(net->name_short);
-		/* 10.5.3.5a */
-		ptr8 = (uint8_t *) msgb_put(msg, 3);
-		ptr8[0] = GSM48_IE_NAME_SHORT;
-		ptr8[1] = name_len*2 + 1;
-		ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
-
-		ptr16 = (uint16_t *) msgb_put(msg, name_len*2);
-		for (i = 0; i < name_len; i++)
-			ptr16[i] = htons(net->name_short[i]);
-#endif
-		name_len = (strlen(net->name_short)*7)/8;
-		name_pad = (8 - strlen(net->name_short)*7)%8;
-		if (name_pad > 0)
-			name_len++;
-		/* 10.5.3.5a */
-		ptr8 = (uint8_t *) msgb_put(msg, 3);
-		ptr8[0] = GSM48_IE_NAME_SHORT;
-		ptr8[1] = name_len +1;
-		ptr8[2] = 0x80 | name_pad; /* Cell Broadcast DCS, no CI */
-
-		ptr8 = msgb_put(msg, name_len);
-		gsm_7bit_encode_n(ptr8, name_len, net->name_short, NULL);
-
-	}
-
-	/* Section 10.5.3.9 */
-	cur_t = time(NULL);
-	gmt_time = gmtime(&cur_t);
-
-	ptr8 = msgb_put(msg, 8);
-	ptr8[0] = GSM48_IE_NET_TIME_TZ;
-	ptr8[1] = bcdify(gmt_time->tm_year % 100);
-	ptr8[2] = bcdify(gmt_time->tm_mon + 1);
-	ptr8[3] = bcdify(gmt_time->tm_mday);
-	ptr8[4] = bcdify(gmt_time->tm_hour);
-	ptr8[5] = bcdify(gmt_time->tm_min);
-	ptr8[6] = bcdify(gmt_time->tm_sec);
-
-	if (net->tz.override) {
-		/* Convert tz.hr and tz.mn to units */
-		if (net->tz.hr < 0) {
-			tzunits = ((net->tz.hr/-1)*4);
-			tzunits = tzunits + (net->tz.mn/15);
-			ptr8[7] = bcdify(tzunits);
-			/* Set negative time */
-			ptr8[7] |= 0x08;
-		}
-		else {
-			tzunits = net->tz.hr*4;
-			tzunits = tzunits + (net->tz.mn/15);
-			ptr8[7] = bcdify(tzunits);
-		}
-		/* Convert DST value */
-		if (net->tz.dst >= 0 && net->tz.dst <= 2)
-			dst = net->tz.dst;
-	}
-	else {
-		/* Need to get GSM offset and convert into 15 min units */
-		/* This probably breaks if gmtoff returns a value not evenly divisible by 15? */
-#ifdef HAVE_TM_GMTOFF_IN_TM
-		local_time = localtime(&cur_t);
-		tzunits = (local_time->tm_gmtoff/60)/15;
-#else
-		/* find timezone offset */
-		time_t utc;
-		double offsetFromUTC;
-		utc = mktime(gmt_time);
-		local_time = localtime(&cur_t);
-		offsetFromUTC = difftime(cur_t, utc);
-		if (local_time->tm_isdst)
-			offsetFromUTC += 3600.0;
-		tzunits = ((int)offsetFromUTC) / 60 / 15;
-#endif
-		if (tzunits < 0) {
-			tzunits = tzunits/-1;
-			ptr8[7] = bcdify(tzunits);
-			/* Flip it to negative */
-			ptr8[7] |= 0x08;
-		}
-		else
-			ptr8[7] = bcdify(tzunits);
-
-		/* Does not support DST +2 */
-		if (local_time->tm_isdst)
-			dst = 1;
-	}
-
-	if (dst) {
-		ptr8 = msgb_put(msg, 3);
-		ptr8[0] = GSM48_IE_NET_DST;
-		ptr8[1] = 1;
-		ptr8[2] = dst;
-	}
-
-	DEBUGP(DMM, "-> MM INFO\n");
-
-	return gsm48_conn_sendmsg(msg, conn, NULL);
-}
-
-/*! Send an Authentication Request to MS on the given subscriber connection
- * according to 3GPP/ETSI TS 24.008, Section 9.2.2.
- * \param[in] conn  Subscriber connection to send on.
- * \param[in] rand  Random challenge token to send, must be 16 bytes long.
- * \param[in] autn  r99: In case of UMTS mutual authentication, AUTN token to
- * 	send; must be 16 bytes long, or pass NULL for plain GSM auth.
- * \param[in] key_seq  auth tuple's sequence number.
- */
-int gsm48_tx_mm_auth_req(struct gsm_subscriber_connection *conn, uint8_t *rand,
-			 uint8_t *autn, int key_seq)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 AUTH REQ");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	struct gsm48_auth_req *ar = (struct gsm48_auth_req *) msgb_put(msg, sizeof(*ar));
-
-	DEBUGP(DMM, "-> AUTH REQ (rand = %s)\n", osmo_hexdump_nospc(rand, 16));
-	if (autn)
-		DEBUGP(DMM, "   AUTH REQ (autn = %s)\n", osmo_hexdump_nospc(autn, 16));
-
-	gh->proto_discr = GSM48_PDISC_MM;
-	gh->msg_type = GSM48_MT_MM_AUTH_REQ;
-
-	ar->key_seq = key_seq;
-
-	/* 16 bytes RAND parameters */
-	osmo_static_assert(sizeof(ar->rand) == 16, sizeof_auth_req_r99_rand);
-	if (rand)
-		memcpy(ar->rand, rand, 16);
-
-
-	/* 16 bytes AUTN */
-	if (autn)
-		msgb_tlv_put(msg, GSM48_IE_AUTN, 16, autn);
-
-	return gsm48_conn_sendmsg(msg, conn, NULL);
-}
-
-/* Section 9.2.1 */
-int gsm48_tx_mm_auth_rej(struct gsm_subscriber_connection *conn)
-{
-	DEBUGP(DMM, "-> AUTH REJECT\n");
-	return gsm48_tx_simple(conn, GSM48_PDISC_MM, GSM48_MT_MM_AUTH_REJ);
-}
-
-static int msc_vlr_tx_cm_serv_acc(void *msc_conn_ref);
-static int msc_vlr_tx_cm_serv_rej(void *msc_conn_ref, enum vlr_proc_arq_result result);
-
-static int cm_serv_reuse_conn(struct gsm_subscriber_connection *conn, const uint8_t *mi_lv)
-{
-	uint8_t mi_type;
-	char mi_string[GSM48_MI_SIZE];
-	uint32_t tmsi;
-
-	gsm48_mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, mi_lv[0]);
-	mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
-
-	switch (mi_type) {
-	case GSM_MI_TYPE_IMSI:
-		if (vlr_subscr_matches_imsi(conn->vsub, mi_string))
-			goto accept_reuse;
-		break;
-	case GSM_MI_TYPE_TMSI:
-		tmsi = osmo_load32be(mi_lv+2);
-		if (vlr_subscr_matches_tmsi(conn->vsub, tmsi))
-			goto accept_reuse;
-		break;
-	case GSM_MI_TYPE_IMEI:
-		if (vlr_subscr_matches_imei(conn->vsub, mi_string))
-			goto accept_reuse;
-		break;
-	default:
-		break;
-	}
-
-	LOGP(DMM, LOGL_ERROR, "%s: CM Service Request with mismatching mobile identity: %s %s\n",
-	     vlr_subscr_name(conn->vsub), gsm48_mi_type_name(mi_type), mi_string);
-	msc_vlr_tx_cm_serv_rej(conn, VLR_PR_ARQ_RES_ILLEGAL_SUBSCR);
-	return -EINVAL;
-
-accept_reuse:
-	DEBUGP(DMM, "%s: re-using already accepted connection\n",
-	       vlr_subscr_name(conn->vsub));
-	conn->received_cm_service_request = true;
-	return conn->network->vlr->ops.tx_cm_serv_acc(conn);
-}
-
-/*
- * Handle CM Service Requests
- * a) Verify that the packet is long enough to contain the information
- *    we require otherwsie reject with INCORRECT_MESSAGE
- * b) Try to parse the TMSI. If we do not have one reject
- * c) Check that we know the subscriber with the TMSI otherwise reject
- *    with a HLR cause
- * d) Set the subscriber on the conn and accept
- *
- * Keep this function non-static for direct invocation by unit tests.
- */
-int gsm48_rx_mm_serv_req(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	static const enum subscr_conn_from conn_from_cm_service_req =
-		SUBSCR_CONN_FROM_CM_SERVICE_REQ;
-	struct gsm_network *net = conn->network;
-	uint8_t mi_type;
-	char mi_string[GSM48_MI_SIZE];
-
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	struct gsm48_service_request *req =
-			(struct gsm48_service_request *)gh->data;
-	/* unfortunately in Phase1 the classmark2 length is variable */
-	uint8_t classmark2_len = gh->data[1];
-	uint8_t *classmark2 = gh->data+2;
-	uint8_t mi_len = *(classmark2 + classmark2_len);
-	uint8_t *mi = (classmark2 + classmark2_len + 1);
-	struct osmo_location_area_id lai;
-	bool is_utran;
-	int rc;
-
-	lai.plmn.mcc = conn->network->country_code;
-	lai.plmn.mnc = conn->network->network_code;
-	lai.lac = conn->lac;
-
-	DEBUGP(DMM, "<- CM SERVICE REQUEST ");
-	if (msg->data_len < sizeof(struct gsm48_service_request*)) {
-		DEBUGPC(DMM, "wrong sized message\n");
-		return msc_gsm48_tx_mm_serv_rej(conn,
-						GSM48_REJECT_INCORRECT_MESSAGE);
-	}
-
-	if (msg->data_len < req->mi_len + 6) {
-		DEBUGPC(DMM, "does not fit in packet\n");
-		return msc_gsm48_tx_mm_serv_rej(conn,
-						GSM48_REJECT_INCORRECT_MESSAGE);
-	}
-
-	gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
-	mi_type = mi[0] & GSM_MI_TYPE_MASK;
-
-	if (mi_type == GSM_MI_TYPE_IMSI) {
-		DEBUGPC(DMM, "serv_type=0x%02x MI(%s)=%s\n",
-			req->cm_service_type, gsm48_mi_type_name(mi_type),
-			mi_string);
-	} else if (mi_type == GSM_MI_TYPE_TMSI) {
-		DEBUGPC(DMM, "serv_type=0x%02x MI(%s)=%s\n",
-			req->cm_service_type, gsm48_mi_type_name(mi_type),
-			mi_string);
-	} else {
-		DEBUGPC(DMM, "mi_type is not expected: %d\n", mi_type);
-		return msc_gsm48_tx_mm_serv_rej(conn,
-						GSM48_REJECT_INCORRECT_MESSAGE);
-	}
-
-	osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_IDENTITY, (classmark2 + classmark2_len));
-	memcpy(conn->classmark.classmark2, classmark2, classmark2_len);
-	conn->classmark.classmark2_len = classmark2_len;
-
-	if (conn->conn_fsm) {
-		if (msc_subscr_conn_is_accepted(conn))
-			return cm_serv_reuse_conn(conn, mi-1);
-		LOGP(DMM, LOGL_ERROR, "%s: connection already in use\n",
-		     vlr_subscr_name(conn->vsub));
-		msc_vlr_tx_cm_serv_rej(conn, VLR_PR_ARQ_RES_UNKNOWN_ERROR);
-		return -EINVAL;
-	}
-
-	rc = msc_create_conn_fsm(conn, mi_string);
-	if (rc) {
-		msc_vlr_tx_cm_serv_rej(conn, VLR_PR_ARQ_RES_UNKNOWN_ERROR);
-		/* logging already happened in msc_create_conn_fsm() */
-		return rc;
-	}
-
-	is_utran = (conn->via_ran == RAN_UTRAN_IU);
-	vlr_proc_acc_req(conn->conn_fsm,
-			 SUBSCR_CONN_E_ACCEPTED,
-			 SUBSCR_CONN_E_CN_CLOSE,
-			 (void*)&conn_from_cm_service_req,
-			 net->vlr, conn,
-			 VLR_PR_ARQ_T_CM_SERV_REQ, mi-1, &lai,
-			 is_utran || conn->network->authentication_required,
-			 is_utran? VLR_CIPH_A5_3
-				 : conn->network->a5_encryption,
-			 classmark_is_r99(&conn->classmark),
-			 is_utran);
-
-	return 0;
-}
-
-static int gsm48_rx_mm_imsi_detach_ind(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	struct gsm_network *network = conn->network;
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	struct gsm48_imsi_detach_ind *idi =
-				(struct gsm48_imsi_detach_ind *) gh->data;
-	uint8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
-	char mi_string[GSM48_MI_SIZE];
-	struct vlr_subscr *vsub = NULL;
-
-	gsm48_mi_to_string(mi_string, sizeof(mi_string), idi->mi, idi->mi_len);
-	DEBUGP(DMM, "IMSI DETACH INDICATION: MI(%s)=%s\n",
-	       gsm48_mi_type_name(mi_type), mi_string);
-
-	rate_ctr_inc(&network->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH]);
-
-	switch (mi_type) {
-	case GSM_MI_TYPE_TMSI:
-		vsub = vlr_subscr_find_by_tmsi(network->vlr,
-					       tmsi_from_string(mi_string));
-		break;
-	case GSM_MI_TYPE_IMSI:
-		vsub = vlr_subscr_find_by_imsi(network->vlr, mi_string);
-		break;
-	case GSM_MI_TYPE_IMEI:
-	case GSM_MI_TYPE_IMEISV:
-		/* no sim card... FIXME: what to do ? */
-		LOGP(DMM, LOGL_ERROR, "MI(%s)=%s: unimplemented mobile identity type\n",
-		     gsm48_mi_type_name(mi_type), mi_string);
-		break;
-	default:
-		LOGP(DMM, LOGL_ERROR, "MI(%s)=%s: unknown mobile identity type\n",
-		     gsm48_mi_type_name(mi_type), mi_string);
-		break;
-	}
-
-	/* TODO? We used to remember the subscriber's classmark1 here and
-	 * stored it in the old sqlite db, but now we store it in a conn that
-	 * will be discarded anyway: */
-	conn->classmark.classmark1 = idi->classmark1;
-
-	if (!vsub) {
-		LOGP(DMM, LOGL_ERROR, "IMSI DETACH for unknown subscriber MI(%s)=%s\n",
-		     gsm48_mi_type_name(mi_type), mi_string);
-	} else {
-		LOGP(DMM, LOGL_INFO, "IMSI DETACH for %s\n", vlr_subscr_name(vsub));
-		vlr_subscr_rx_imsi_detach(vsub);
-		osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_DETACHED, vsub);
-		vlr_subscr_put(vsub);
-	}
-
-	msc_subscr_conn_close(conn, 0);
-	return 0;
-}
-
-static int gsm48_rx_mm_status(struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-
-	DEBUGP(DMM, "MM STATUS (reject cause 0x%02x)\n", gh->data[0]);
-
-	return 0;
-}
-
-static int parse_gsm_auth_resp(uint8_t *res, uint8_t *res_len,
-			       struct gsm_subscriber_connection *conn,
-			       struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	struct gsm48_auth_resp *ar = (struct gsm48_auth_resp*) gh->data;
-
-	if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*ar)) {
-		LOGP(DMM, LOGL_ERROR,
-		     "%s: MM AUTHENTICATION RESPONSE:"
-		     " l3 length invalid: %u\n",
-		     vlr_subscr_name(conn->vsub), msgb_l3len(msg));
-		return -EINVAL;
-	}
-
-	*res_len = sizeof(ar->sres);
-	memcpy(res, ar->sres, sizeof(ar->sres));
-	return 0;
-}
-
-static int parse_umts_auth_resp(uint8_t *res, uint8_t *res_len,
-				struct gsm_subscriber_connection *conn,
-				struct msgb *msg)
-{
-	struct gsm48_hdr *gh;
-	uint8_t *data;
-	uint8_t iei;
-	uint8_t ie_len;
-	unsigned int data_len;
-
-	/* First parse the GSM part */
-	if (parse_gsm_auth_resp(res, res_len, conn, msg))
-		return -EINVAL;
-	OSMO_ASSERT(*res_len == 4);
-
-	/* Then add the extended res part */
-	gh = msgb_l3(msg);
-	data = gh->data + sizeof(struct gsm48_auth_resp);
-	data_len = msgb_l3len(msg) - (data - (uint8_t*)msgb_l3(msg));
-
-	if (data_len < 3) {
-		LOGP(DMM, LOGL_ERROR,
-		     "%s: MM AUTHENTICATION RESPONSE:"
-		     " l3 length invalid: %u\n",
-		     vlr_subscr_name(conn->vsub), msgb_l3len(msg));
-		return -EINVAL;
-	}
-
-	iei = data[0];
-	ie_len = data[1];
-	if (iei != GSM48_IE_AUTH_RES_EXT) {
-		LOGP(DMM, LOGL_ERROR,
-		     "%s: MM R99 AUTHENTICATION RESPONSE:"
-		     " expected IEI 0x%02x, got 0x%02x\n",
-		     vlr_subscr_name(conn->vsub),
-		     GSM48_IE_AUTH_RES_EXT, iei);
-		return -EINVAL;
-	}
-
-	if (ie_len > 12) {
-		LOGP(DMM, LOGL_ERROR,
-		     "%s: MM R99 AUTHENTICATION RESPONSE:"
-		     " extended Auth Resp IE 0x%02x is too large: %u bytes\n",
-		     vlr_subscr_name(conn->vsub), GSM48_IE_AUTH_RES_EXT, ie_len);
-		return -EINVAL;
-	}
-
-	*res_len += ie_len;
-	memcpy(res + 4, &data[2], ie_len);
-	return 0;
-}
-
-/* Chapter 9.2.3: Authentication Response */
-static int gsm48_rx_mm_auth_resp(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	uint8_t res[16];
-	uint8_t res_len;
-	int rc;
-	bool is_r99;
-
-	if (!conn->vsub) {
-		LOGP(DMM, LOGL_ERROR,
-		     "MM AUTHENTICATION RESPONSE: invalid: no subscriber\n");
-		msc_subscr_conn_close(conn, GSM_CAUSE_AUTH_FAILED);
-		return -EINVAL;
-	}
-
-	if (msgb_l3len(msg) >
-	    sizeof(struct gsm48_hdr) + sizeof(struct gsm48_auth_resp)) {
-		rc = parse_umts_auth_resp(res, &res_len, conn, msg);
-		is_r99 = true;
-	} else {
-		rc = parse_gsm_auth_resp(res, &res_len, conn, msg);
-		is_r99 = false;
-	}
-
-	if (rc) {
-		msc_subscr_conn_close(conn, GSM_CAUSE_AUTH_FAILED);
-		return -EINVAL;
-	}
-
-	DEBUGP(DMM, "%s: MM %s AUTHENTICATION RESPONSE (%s = %s)\n",
-	       vlr_subscr_name(conn->vsub),
-	       is_r99 ? "R99" : "GSM", is_r99 ? "res" : "sres",
-	       osmo_hexdump_nospc(res, res_len));
-
-	return vlr_subscr_rx_auth_resp(conn->vsub, is_r99,
-				       conn->via_ran == RAN_UTRAN_IU,
-				       res, res_len);
-}
-
-static int gsm48_rx_mm_auth_fail(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	uint8_t cause;
-	uint8_t auts_tag;
-	uint8_t auts_len;
-	uint8_t *auts;
-
-	if (!conn->vsub) {
-		LOGP(DMM, LOGL_ERROR,
-		     "MM R99 AUTHENTICATION FAILURE: invalid: no subscriber\n");
-		msc_subscr_conn_close(conn, GSM_CAUSE_AUTH_FAILED);
-		return -EINVAL;
-	}
-
-	if (msgb_l3len(msg) < sizeof(*gh) + 1) {
-		LOGP(DMM, LOGL_ERROR,
-		     "%s: MM R99 AUTHENTICATION FAILURE:"
-		     " l3 length invalid: %u\n",
-		     vlr_subscr_name(conn->vsub), msgb_l3len(msg));
-		msc_subscr_conn_close(conn, GSM_CAUSE_AUTH_FAILED);
-		return -EINVAL;
-	}
-
-	cause = gh->data[0];
-
-	if (cause != GSM48_REJECT_SYNCH_FAILURE) {
-		LOGP(DMM, LOGL_INFO,
-		     "%s: MM R99 AUTHENTICATION FAILURE: cause 0x%0x\n",
-		     vlr_subscr_name(conn->vsub), cause);
-		vlr_subscr_rx_auth_fail(conn->vsub, NULL);
-		return 0;
-	}
-
-	/* This is a Synch Failure procedure, which should pass an AUTS to
-	 * resynchronize the sequence nr with the HLR. Expecting exactly one
-	 * TLV with 14 bytes of AUTS. */
-
-	if (msgb_l3len(msg) < sizeof(*gh) + 1 + 2) {
-		LOGP(DMM, LOGL_INFO,
-		     "%s: MM R99 AUTHENTICATION FAILURE:"
-		     " invalid Synch Failure: missing AUTS IE\n",
-		     vlr_subscr_name(conn->vsub));
-		msc_subscr_conn_close(conn, GSM_CAUSE_AUTH_FAILED);
-		return -EINVAL;
-	}
-
-	auts_tag = gh->data[1];
-	auts_len = gh->data[2];
-	auts = &gh->data[3];
-
-	if (auts_tag != GSM48_IE_AUTS
-	    || auts_len != 14) {
-		LOGP(DMM, LOGL_INFO,
-		     "%s: MM R99 AUTHENTICATION FAILURE:"
-		     " invalid Synch Failure:"
-		     " expected AUTS IE 0x%02x of 14 bytes,"
-		     " got IE 0x%02x of %u bytes\n",
-		     vlr_subscr_name(conn->vsub),
-		     GSM48_IE_AUTS, auts_tag, auts_len);
-		msc_subscr_conn_close(conn, GSM_CAUSE_AUTH_FAILED);
-		return -EINVAL;
-	}
-
-	if (msgb_l3len(msg) < sizeof(*gh) + 1 + 2 + auts_len) {
-		LOGP(DMM, LOGL_INFO,
-		     "%s: MM R99 AUTHENTICATION FAILURE:"
-		     " invalid Synch Failure msg: message truncated (%u)\n",
-		     vlr_subscr_name(conn->vsub), msgb_l3len(msg));
-		msc_subscr_conn_close(conn, GSM_CAUSE_AUTH_FAILED);
-		return -EINVAL;
-	}
-
-	/* We have an AUTS IE with exactly 14 bytes of AUTS and the msgb is
-	 * large enough. */
-
-	DEBUGP(DMM, "%s: MM R99 AUTHENTICATION SYNCH (AUTS = %s)\n",
-	       vlr_subscr_name(conn->vsub), osmo_hexdump_nospc(auts, 14));
-
-	return vlr_subscr_rx_auth_fail(conn->vsub, auts);
-}
-
-static int gsm48_rx_mm_tmsi_reall_compl(struct gsm_subscriber_connection *conn)
-{
-	DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
-	       vlr_subscr_name(conn->vsub));
-	if (!conn->vsub) {
-		LOGP(DMM, LOGL_ERROR,
-		     "Rx MM TMSI Reallocation Complete: invalid: no subscriber\n");
-		return -EINVAL;
-	}
-	return vlr_subscr_rx_tmsi_reall_compl(conn->vsub);
-}
-
-/* Receive a GSM 04.08 Mobility Management (MM) message */
-static int gsm0408_rcv_mm(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	int rc = 0;
-
-	switch (gsm48_hdr_msg_type(gh)) {
-	case GSM48_MT_MM_LOC_UPD_REQUEST:
-		rc = mm_rx_loc_upd_req(conn, msg);
-		break;
-	case GSM48_MT_MM_ID_RESP:
-		rc = mm_rx_id_resp(conn, msg);
-		break;
-	case GSM48_MT_MM_CM_SERV_REQ:
-		rc = gsm48_rx_mm_serv_req(conn, msg);
-		break;
-	case GSM48_MT_MM_STATUS:
-		rc = gsm48_rx_mm_status(msg);
-		break;
-	case GSM48_MT_MM_TMSI_REALL_COMPL:
-		rc = gsm48_rx_mm_tmsi_reall_compl(conn);
-		break;
-	case GSM48_MT_MM_IMSI_DETACH_IND:
-		rc = gsm48_rx_mm_imsi_detach_ind(conn, msg);
-		break;
-	case GSM48_MT_MM_CM_REEST_REQ:
-		DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
-		break;
-	case GSM48_MT_MM_AUTH_RESP:
-		rc = gsm48_rx_mm_auth_resp(conn, msg);
-		break;
-	case GSM48_MT_MM_AUTH_FAIL:
-		rc = gsm48_rx_mm_auth_fail(conn, msg);
-		break;
-	default:
-		LOGP(DMM, LOGL_NOTICE, "Unknown GSM 04.08 MM msg type 0x%02x\n",
-			gh->msg_type);
-		break;
-	}
-
-	return rc;
-}
-
-static uint8_t *gsm48_cm2_get_mi(uint8_t *classmark2_lv, unsigned int tot_len)
-{
-	/* Check the size for the classmark */
-	if (tot_len < 1 + *classmark2_lv)
-		return NULL;
-
-	uint8_t *mi_lv = classmark2_lv + *classmark2_lv + 1;
-	if (tot_len < 2 + *classmark2_lv + mi_lv[0])
-		return NULL;
-
-	return mi_lv;
-}
-
-/* Receive a PAGING RESPONSE message from the MS */
-static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	static const enum subscr_conn_from conn_from_paging_resp =
-		SUBSCR_CONN_FROM_PAGING_RESP;
-	struct gsm_network *net = conn->network;
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	struct gsm48_pag_resp *resp;
-	uint8_t *classmark2_lv = gh->data + 1;
-	uint8_t *mi_lv;
-	uint8_t mi_type;
-	char mi_string[GSM48_MI_SIZE];
-	int rc = 0;
-	struct osmo_location_area_id lai;
-	bool is_utran;
-
-	lai.plmn.mcc = conn->network->country_code;
-	lai.plmn.mnc = conn->network->network_code;
-	lai.lac = conn->lac;
-
-	resp = (struct gsm48_pag_resp *) &gh->data[0];
-	gsm48_paging_extract_mi(resp, msgb_l3len(msg) - sizeof(*gh),
-				mi_string, &mi_type);
-	DEBUGP(DRR, "PAGING RESPONSE: MI(%s)=%s\n",
-		gsm48_mi_type_name(mi_type), mi_string);
-
-	mi_lv = gsm48_cm2_get_mi(classmark2_lv, msgb_l3len(msg) - sizeof(*gh));
-	if (!mi_lv) {
-		/* FIXME */
-		return -1;
-	}
-
-	rc = msc_create_conn_fsm(conn, mi_string);
-	if (rc)
-		/* logging already happened in msc_create_conn_fsm() */
-		return rc;
-
-	memcpy(conn->classmark.classmark2, classmark2_lv+1, *classmark2_lv);
-	conn->classmark.classmark2_len = *classmark2_lv;
-
-	is_utran = (conn->via_ran == RAN_UTRAN_IU);
-	vlr_proc_acc_req(conn->conn_fsm,
-			 SUBSCR_CONN_E_ACCEPTED,
-			 SUBSCR_CONN_E_CN_CLOSE,
-			 (void*)&conn_from_paging_resp,
-			 net->vlr, conn,
-			 VLR_PR_ARQ_T_PAGING_RESP, mi_lv, &lai,
-			 is_utran || conn->network->authentication_required,
-			 is_utran? VLR_CIPH_A5_3
-				 : conn->network->a5_encryption,
-			 classmark_is_r99(&conn->classmark),
-			 is_utran);
-
-	return 0;
-}
-
-static int gsm48_rx_rr_app_info(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	uint8_t apdu_id_flags;
-	uint8_t apdu_len;
-	uint8_t *apdu_data;
-
-	apdu_id_flags = gh->data[0];
-	apdu_len = gh->data[1];
-	apdu_data = gh->data+2;
-
-	DEBUGP(DRR, "RX APPLICATION INFO id/flags=0x%02x apdu_len=%u apdu=%s\n",
-		apdu_id_flags, apdu_len, osmo_hexdump(apdu_data, apdu_len));
-
-	/* we're not using the app info blob anywhere, so ignore. */
-#if 0
-	return db_apdu_blob_store(conn->subscr, apdu_id_flags, apdu_len, apdu_data);
-#else
-	return 0;
-#endif
-}
-
-/* Receive a GSM 04.08 Radio Resource (RR) message */
-static int gsm0408_rcv_rr(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	int rc = 0;
-
-	switch (gh->msg_type) {
-	case GSM48_MT_RR_PAG_RESP:
-		rc = gsm48_rx_rr_pag_resp(conn, msg);
-		break;
-	case GSM48_MT_RR_APP_INFO:
-		rc = gsm48_rx_rr_app_info(conn, msg);
-		break;
-	default:
-		LOGP(DRR, LOGL_NOTICE, "MSC: Unimplemented %s GSM 04.08 RR "
-		     "message\n", gsm48_rr_msg_name(gh->msg_type));
-		break;
-	}
-
-	return rc;
-}
-
-int gsm48_send_rr_app_info(struct gsm_subscriber_connection *conn, uint8_t apdu_id,
-			   uint8_t apdu_len, const uint8_t *apdu)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 APP INF");
-	struct gsm48_hdr *gh;
-
-	DEBUGP(DRR, "TX APPLICATION INFO id=0x%02x, len=%u\n",
-		apdu_id, apdu_len);
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 2 + apdu_len);
-	gh->proto_discr = GSM48_PDISC_RR;
-	gh->msg_type = GSM48_MT_RR_APP_INFO;
-	gh->data[0] = apdu_id;
-	gh->data[1] = apdu_len;
-	memcpy(gh->data+2, apdu, apdu_len);
-
-	return gsm48_conn_sendmsg(msg, conn, NULL);
-}
-
-/* FIXME: this count_statistics is a state machine behaviour. we should convert
- * the complete call control into a state machine. Afterwards we can move this
- * code into state transitions.
- */
-static void count_statistics(struct gsm_trans *trans, int new_state)
-{
-	int old_state = trans->cc.state;
-	struct rate_ctr_group *msc = trans->net->msc_ctrs;
-
-	if (old_state == new_state)
-		return;
-
-	/* state incoming */
-	switch (new_state) {
-	case GSM_CSTATE_ACTIVE:
-		osmo_counter_inc(trans->net->active_calls);
-		rate_ctr_inc(&msc->ctr[MSC_CTR_CALL_ACTIVE]);
-		break;
-	}
-
-	/* state outgoing */
-	switch (old_state) {
-	case GSM_CSTATE_ACTIVE:
-		osmo_counter_dec(trans->net->active_calls);
-		if (new_state == GSM_CSTATE_DISCONNECT_REQ ||
-				new_state == GSM_CSTATE_DISCONNECT_IND)
-			rate_ctr_inc(&msc->ctr[MSC_CTR_CALL_COMPLETE]);
-		else
-			rate_ctr_inc(&msc->ctr[MSC_CTR_CALL_INCOMPLETE]);
-		break;
-	}
-}
-
-/* Call Control */
-
-/* The entire call control code is written in accordance with Figure 7.10c
- * for 'very early assignment', i.e. we allocate a TCH/F during IMMEDIATE
- * ASSIGN, then first use that TCH/F for signalling and later MODE MODIFY
- * it for voice */
-
-static void new_cc_state(struct gsm_trans *trans, int state)
-{
-	if (state > 31 || state < 0)
-		return;
-
-	DEBUGP(DCC, "new state %s -> %s\n",
-		gsm48_cc_state_name(trans->cc.state),
-		gsm48_cc_state_name(state));
-
-	count_statistics(trans, state);
-	trans->cc.state = state;
-}
-
-static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC STATUS");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	uint8_t *cause, *call_state;
-
-	gh->msg_type = GSM48_MT_CC_STATUS;
-
-	cause = msgb_put(msg, 3);
-	cause[0] = 2;
-	cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
-	cause[2] = 0x80 | 30;	/* response to status inquiry */
-
-	call_state = msgb_put(msg, 1);
-	call_state[0] = 0xc0 | 0x00;
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_tx_simple(struct gsm_subscriber_connection *conn,
-			   uint8_t pdisc, uint8_t msg_type)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 TX SIMPLE");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->proto_discr = pdisc;
-	gh->msg_type = msg_type;
-
-	return gsm48_conn_sendmsg(msg, conn, NULL);
-}
-
-static void gsm48_stop_cc_timer(struct gsm_trans *trans)
-{
-	if (osmo_timer_pending(&trans->cc.timer)) {
-		DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
-		osmo_timer_del(&trans->cc.timer);
-		trans->cc.Tcurrent = 0;
-	}
-}
-
-static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
-			int msg_type, struct gsm_mncc *mncc)
-{
-	struct msgb *msg;
-	unsigned char *data;
-
-	DEBUGP(DMNCC, "transmit message %s\n", get_mncc_name(msg_type));
-
-#if BEFORE_MSCSPLIT
-	/* Re-enable this log output once we can obtain this information via
-	 * A-interface, see OS#2391. */
-	if (trans)
-		if (trans->conn && trans->conn->lchan)
-			DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
-				"Sending '%s' to MNCC.\n",
-				trans->conn->lchan->ts->trx->bts->nr,
-				trans->conn->lchan->ts->trx->nr,
-				trans->conn->lchan->ts->nr, trans->transaction_id,
-				vlr_subscr_msisdn_or_name(trans->vsub),
-				get_mncc_name(msg_type));
-		else
-			DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
-				"Sending '%s' to MNCC.\n",
-				vlr_subscr_msisdn_or_name(trans->vsub),
-				get_mncc_name(msg_type));
-	else
-		DEBUGP(DCC, "(bts - trx - ts - ti -- sub -) "
-			"Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
-#else
-	DEBUGP(DCC, "Sending '%s' to MNCC.\n", get_mncc_name(msg_type));
-#endif
-
-	mncc->msg_type = msg_type;
-
-	msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
-	if (!msg)
-		return -ENOMEM;
-
-	data = msgb_put(msg, sizeof(struct gsm_mncc));
-	memcpy(data, mncc, sizeof(struct gsm_mncc));
-
-	cc_tx_to_mncc(net, msg);
-
-	return 0;
-}
-
-int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
-		     uint32_t callref, int location, int value)
-{
-	struct gsm_mncc rel;
-
-	memset(&rel, 0, sizeof(rel));
-	rel.callref = callref;
-	mncc_set_cause(&rel, location, value);
-	if (trans && trans->cc.state == GSM_CSTATE_RELEASE_REQ)
-		return mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
-	return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
-}
-
-/* Call Control Specific transaction release.
- * gets called by trans_free, DO NOT CALL YOURSELF! */
-void _gsm48_cc_trans_free(struct gsm_trans *trans)
-{
-	gsm48_stop_cc_timer(trans);
-
-	/* Make sure call also gets released on the mgcp side */
-	msc_call_release(trans);
-
-	/* send release to L4, if callref still exists */
-	if (trans->callref) {
-		/* Ressource unavailable */
-		mncc_release_ind(trans->net, trans, trans->callref,
-				 GSM48_CAUSE_LOC_PRN_S_LU,
-				 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
-	}
-	if (trans->cc.state != GSM_CSTATE_NULL)
-		new_cc_state(trans, GSM_CSTATE_NULL);
-}
-
-static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
-
-/* call-back from paging the B-end of the connection */
-static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
-			      struct msgb *msg, void *_conn, void *_transt)
-{
-	struct gsm_subscriber_connection *conn = _conn;
-	struct gsm_trans *transt = _transt;
-
-	OSMO_ASSERT(!transt->conn);
-
-	switch (event) {
-	case GSM_PAGING_SUCCEEDED:
-		DEBUGP(DCC, "Paging subscr %s succeeded!\n",
-		       vlr_subscr_msisdn_or_name(transt->vsub));
-		OSMO_ASSERT(conn);
-		/* Assign conn */
-		transt->conn = conn;
-		/* send SETUP request to called party */
-		gsm48_cc_tx_setup(transt, &transt->cc.msg);
-		break;
-	case GSM_PAGING_EXPIRED:
-	case GSM_PAGING_BUSY:
-		DEBUGP(DCC, "Paging subscr %s expired!\n",
-		       vlr_subscr_msisdn_or_name(transt->vsub));
-		/* Temporarily out of order */
-		mncc_release_ind(transt->net, transt,
-				 transt->callref,
-				 GSM48_CAUSE_LOC_PRN_S_LU,
-				 GSM48_CC_CAUSE_DEST_OOO);
-		transt->callref = 0;
-		transt->paging_request = NULL;
-		trans_free(transt);
-		break;
-	default:
-		LOGP(DCC, LOGL_ERROR, "Unknown paging event %d\n", event);
-		break;
-	}
-
-	transt->paging_request = NULL;
-	return 0;
-}
-
-/* bridge channels of two transactions */
-static int tch_bridge(struct gsm_network *net, struct gsm_mncc_bridge *bridge)
-{
-	struct gsm_trans *trans1 = trans_find_by_callref(net, bridge->callref[0]);
-	struct gsm_trans *trans2 = trans_find_by_callref(net, bridge->callref[1]);
-
-	if (!trans1 || !trans2)
-		return -EIO;
-
-	if (!trans1->conn || !trans2->conn)
-		return -EIO;
-
-	/* Which subscriber do we want to track trans1 or trans2? */
-	log_set_context(LOG_CTX_VLR_SUBSCR, trans1->vsub);
-
-	return msc_call_bridge(trans1, trans2);
-}
-
-static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg)
-{
-	DEBUGP(DCC, "-> STATUS ENQ\n");
-	return gsm48_cc_tx_status(trans, msg);
-}
-
-static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg);
-static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg);
-
-static void gsm48_cc_timeout(void *arg)
-{
-	struct gsm_trans *trans = arg;
-	int disconnect = 0, release = 0;
-	int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
-	int mo_location = GSM48_CAUSE_LOC_USER;
-	int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
-	int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
-	struct gsm_mncc mo_rel, l4_rel;
-
-	memset(&mo_rel, 0, sizeof(struct gsm_mncc));
-	mo_rel.callref = trans->callref;
-	memset(&l4_rel, 0, sizeof(struct gsm_mncc));
-	l4_rel.callref = trans->callref;
-
-	switch(trans->cc.Tcurrent) {
-	case 0x303:
-		release = 1;
-		l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
-		break;
-	case 0x310:
-		disconnect = 1;
-		l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
-		break;
-	case 0x313:
-		disconnect = 1;
-		/* unknown, did not find it in the specs */
-		break;
-	case 0x301:
-		disconnect = 1;
-		l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
-		break;
-	case 0x308:
-		if (!trans->cc.T308_second) {
-			/* restart T308 a second time */
-			gsm48_cc_tx_release(trans, &trans->cc.msg);
-			trans->cc.T308_second = 1;
-			break; /* stay in release state */
-		}
-		trans_free(trans);
-		return;
-//		release = 1;
-//		l4_cause = 14;
-//		break;
-	case 0x306:
-		release = 1;
-		mo_cause = trans->cc.msg.cause.value;
-		mo_location = trans->cc.msg.cause.location;
-		break;
-	case 0x323:
-		disconnect = 1;
-		break;
-	default:
-		release = 1;
-	}
-
-	if (release && trans->callref) {
-		/* process release towards layer 4 */
-		mncc_release_ind(trans->net, trans, trans->callref,
-				 l4_location, l4_cause);
-		trans->callref = 0;
-	}
-
-	if (disconnect && trans->callref) {
-		/* process disconnect towards layer 4 */
-		mncc_set_cause(&l4_rel, l4_location, l4_cause);
-		mncc_recvmsg(trans->net, trans, MNCC_DISC_IND, &l4_rel);
-	}
-
-	/* process disconnect towards mobile station */
-	if (disconnect || release) {
-		mncc_set_cause(&mo_rel, mo_location, mo_cause);
-		mo_rel.cause.diag[0] = ((trans->cc.Tcurrent & 0xf00) >> 8) + '0';
-		mo_rel.cause.diag[1] = ((trans->cc.Tcurrent & 0x0f0) >> 4) + '0';
-		mo_rel.cause.diag[2] = (trans->cc.Tcurrent & 0x00f) + '0';
-		mo_rel.cause.diag_len = 3;
-
-		if (disconnect)
-			gsm48_cc_tx_disconnect(trans, &mo_rel);
-		if (release)
-			gsm48_cc_tx_release(trans, &mo_rel);
-	}
-
-}
-
-/* disconnect both calls from the bridge */
-static inline void disconnect_bridge(struct gsm_network *net,
-				     struct gsm_mncc_bridge *bridge, int err)
-{
-	struct gsm_trans *trans0 = trans_find_by_callref(net, bridge->callref[0]);
-	struct gsm_trans *trans1 = trans_find_by_callref(net, bridge->callref[1]);
-	struct gsm_mncc mx_rel;
-	if (!trans0 || !trans1)
-		return;
-
-	DEBUGP(DCC, "Failed to bridge TCH for calls %x <-> %x :: %s \n",
-	       trans0->callref, trans1->callref, strerror(err));
-
-	memset(&mx_rel, 0, sizeof(struct gsm_mncc));
-	mncc_set_cause(&mx_rel, GSM48_CAUSE_LOC_INN_NET,
-		       GSM48_CC_CAUSE_CHAN_UNACCEPT);
-
-	mx_rel.callref = trans0->callref;
-	gsm48_cc_tx_disconnect(trans0, &mx_rel);
-
-	mx_rel.callref = trans1->callref;
-	gsm48_cc_tx_disconnect(trans1, &mx_rel);
-}
-
-static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
-				 int sec, int micro)
-{
-	DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
-	osmo_timer_setup(&trans->cc.timer, gsm48_cc_timeout, trans);
-	osmo_timer_schedule(&trans->cc.timer, sec, micro);
-	trans->cc.Tcurrent = current;
-}
-
-static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	uint8_t msg_type = gsm48_hdr_msg_type(gh);
-	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
-	struct tlv_parsed tp;
-	struct gsm_mncc setup;
-
-	memset(&setup, 0, sizeof(struct gsm_mncc));
-	setup.callref = trans->callref;
-
-	tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
-	/* emergency setup is identified by msg_type */
-	if (msg_type == GSM48_MT_CC_EMERG_SETUP)
-		setup.emergency = 1;
-
-	/* use subscriber as calling party number */
-	setup.fields |= MNCC_F_CALLING;
-	osmo_strlcpy(setup.calling.number, trans->vsub->msisdn, sizeof(setup.calling.number));
-	osmo_strlcpy(setup.imsi, trans->vsub->imsi, sizeof(setup.imsi));
-
-	/* bearer capability */
-	if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
-		setup.fields |= MNCC_F_BEARER_CAP;
-		gsm48_decode_bearer_cap(&setup.bearer_cap,
-				  TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
-
-		/* Create a copy of the bearer capability
-		 * in the transaction struct, so we can use
-		 * this information later */
-		memcpy(&trans->bearer_cap,&setup.bearer_cap,
-		       sizeof(trans->bearer_cap));
-	}
-	/* facility */
-	if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
-		setup.fields |= MNCC_F_FACILITY;
-		gsm48_decode_facility(&setup.facility,
-				TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
-	}
-	/* called party bcd number */
-	if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
-		setup.fields |= MNCC_F_CALLED;
-		gsm48_decode_called(&setup.called,
-			      TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1);
-	}
-	/* user-user */
-	if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
-		setup.fields |= MNCC_F_USERUSER;
-		gsm48_decode_useruser(&setup.useruser,
-				TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
-	}
-	/* ss-version */
-	if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
-		setup.fields |= MNCC_F_SSVERSION;
-		gsm48_decode_ssversion(&setup.ssversion,
-				 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
-	}
-	/* CLIR suppression */
-	if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP))
-		setup.clir.sup = 1;
-	/* CLIR invocation */
-	if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC))
-		setup.clir.inv = 1;
-	/* cc cap */
-	if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
-		setup.fields |= MNCC_F_CCCAP;
-		gsm48_decode_cccap(&setup.cccap,
-			     TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
-	}
-
-	new_cc_state(trans, GSM_CSTATE_INITIATED);
-
-	LOGP(DCC, LOGL_INFO, "Subscriber %s (%s) sends SETUP to %s\n",
-	     vlr_subscr_name(trans->vsub), trans->vsub->msisdn,
-	     setup.called.number);
-
-	rate_ctr_inc(&trans->net->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP]);
-
-	/* indicate setup to MNCC */
-	mncc_recvmsg(trans->net, trans, MNCC_SETUP_IND, &setup);
-
-	/* MNCC code will modify the channel asynchronously, we should
-	 * ipaccess-bind only after the modification has been made to the
-	 * lchan->tch_mode */
-	return 0;
-}
-
-static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC STUP");
-	struct gsm48_hdr *gh;
-	struct gsm_mncc *setup = arg;
-	int rc, trans_id;
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	/* transaction id must not be assigned */
-	if (trans->transaction_id != 0xff) { /* unasssigned */
-		DEBUGP(DCC, "TX Setup with assigned transaction. "
-			"This is not allowed!\n");
-		/* Temporarily out of order */
-		rc = mncc_release_ind(trans->net, trans, trans->callref,
-				      GSM48_CAUSE_LOC_PRN_S_LU,
-				      GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
-		trans->callref = 0;
-		trans_free(trans);
-		return rc;
-	}
-
-	/* Get free transaction_id */
-	trans_id = trans_assign_trans_id(trans->net, trans->vsub,
-					 GSM48_PDISC_CC, 0);
-	if (trans_id < 0) {
-		/* no free transaction ID */
-		rc = mncc_release_ind(trans->net, trans, trans->callref,
-				      GSM48_CAUSE_LOC_PRN_S_LU,
-				      GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
-		trans->callref = 0;
-		trans_free(trans);
-		return rc;
-	}
-	trans->transaction_id = trans_id;
-
-	gh->msg_type = GSM48_MT_CC_SETUP;
-
-	gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
-
-	/* bearer capability */
-	if (setup->fields & MNCC_F_BEARER_CAP)
-		gsm48_encode_bearer_cap(msg, 0, &setup->bearer_cap);
-	/* facility */
-	if (setup->fields & MNCC_F_FACILITY)
-		gsm48_encode_facility(msg, 0, &setup->facility);
-	/* progress */
-	if (setup->fields & MNCC_F_PROGRESS)
-		gsm48_encode_progress(msg, 0, &setup->progress);
-	/* calling party BCD number */
-	if (setup->fields & MNCC_F_CALLING)
-		gsm48_encode_calling(msg, &setup->calling);
-	/* called party BCD number */
-	if (setup->fields & MNCC_F_CALLED)
-		gsm48_encode_called(msg, &setup->called);
-	/* user-user */
-	if (setup->fields & MNCC_F_USERUSER)
-		gsm48_encode_useruser(msg, 0, &setup->useruser);
-	/* redirecting party BCD number */
-	if (setup->fields & MNCC_F_REDIRECTING)
-		gsm48_encode_redirecting(msg, &setup->redirecting);
-	/* signal */
-	if (setup->fields & MNCC_F_SIGNAL)
-		gsm48_encode_signal(msg, setup->signal);
-
-	new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
-
-	rate_ctr_inc(&trans->net->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP]);
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
-	struct tlv_parsed tp;
-	struct gsm_mncc call_conf;
-	int rc;
-
-	gsm48_stop_cc_timer(trans);
-	gsm48_start_cc_timer(trans, 0x310, GSM48_T310);
-
-	memset(&call_conf, 0, sizeof(struct gsm_mncc));
-	call_conf.callref = trans->callref;
-
-	tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
-#if 0
-	/* repeat */
-	if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_CIR))
-		call_conf.repeat = 1;
-	if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ))
-		call_conf.repeat = 2;
-#endif
-	/* bearer capability */
-	if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
-		call_conf.fields |= MNCC_F_BEARER_CAP;
-		gsm48_decode_bearer_cap(&call_conf.bearer_cap,
-				  TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
-
-		/* Create a copy of the bearer capability
-		 * in the transaction struct, so we can use
-		 * this information later */
-		memcpy(&trans->bearer_cap,&call_conf.bearer_cap,
-		       sizeof(trans->bearer_cap));
-	}
-	/* cause */
-	if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
-		call_conf.fields |= MNCC_F_CAUSE;
-		gsm48_decode_cause(&call_conf.cause,
-			     TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
-	}
-	/* cc cap */
-	if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) {
-		call_conf.fields |= MNCC_F_CCCAP;
-		gsm48_decode_cccap(&call_conf.cccap,
-			     TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1);
-	}
-
-	/* IMSI of called subscriber */
-	osmo_strlcpy(call_conf.imsi, trans->vsub->imsi, sizeof(call_conf.imsi));
-
-	new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
-
-	/* Assign call (if not done yet) */
-	if (trans->assignment_done == false) {
-		rc = msc_call_assignment(trans);
-		trans->assignment_done = true;
-	}
-	else
-		rc = 0;
-
-	/* don't continue, if there were problems with
-	 * the call assignment. */
-	if (rc)
-		return rc;
-
-	return mncc_recvmsg(trans->net, trans, MNCC_CALL_CONF_IND,
-			    &call_conf);
-}
-
-static int gsm48_cc_tx_call_proc_and_assign(struct gsm_trans *trans, void *arg)
-{
-	struct gsm_mncc *proceeding = arg;
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC PROC");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	int rc;
-
-	gh->msg_type = GSM48_MT_CC_CALL_PROC;
-
-	new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
-
-	/* bearer capability */
-	if (proceeding->fields & MNCC_F_BEARER_CAP)
-		gsm48_encode_bearer_cap(msg, 0, &proceeding->bearer_cap);
-	/* facility */
-	if (proceeding->fields & MNCC_F_FACILITY)
-		gsm48_encode_facility(msg, 0, &proceeding->facility);
-	/* progress */
-	if (proceeding->fields & MNCC_F_PROGRESS)
-		gsm48_encode_progress(msg, 0, &proceeding->progress);
-
-	rc = gsm48_conn_sendmsg(msg, trans->conn, trans);
-	if (rc)
-		return rc;
-
-	/* Assign call (if not done yet) */
-	if (trans->assignment_done == false) {
-		rc = msc_call_assignment(trans);
-		trans->assignment_done = true;
-	}
-	else
-		rc = 0;
-
-	return rc;
-}
-
-static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
-	struct tlv_parsed tp;
-	struct gsm_mncc alerting;
-
-	gsm48_stop_cc_timer(trans);
-	gsm48_start_cc_timer(trans, 0x301, GSM48_T301);
-
-	memset(&alerting, 0, sizeof(struct gsm_mncc));
-	alerting.callref = trans->callref;
-	tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
-	/* facility */
-	if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
-		alerting.fields |= MNCC_F_FACILITY;
-		gsm48_decode_facility(&alerting.facility,
-				TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
-	}
-
-	/* progress */
-	if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
-		alerting.fields |= MNCC_F_PROGRESS;
-		gsm48_decode_progress(&alerting.progress,
-				TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
-	}
-	/* ss-version */
-	if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
-		alerting.fields |= MNCC_F_SSVERSION;
-		gsm48_decode_ssversion(&alerting.ssversion,
-				 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
-	}
-
-	new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
-
-	return mncc_recvmsg(trans->net, trans, MNCC_ALERT_IND,
-			    &alerting);
-}
-
-static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
-{
-	struct gsm_mncc *alerting = arg;
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC ALERT");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_ALERTING;
-
-	/* facility */
-	if (alerting->fields & MNCC_F_FACILITY)
-		gsm48_encode_facility(msg, 0, &alerting->facility);
-	/* progress */
-	if (alerting->fields & MNCC_F_PROGRESS)
-		gsm48_encode_progress(msg, 0, &alerting->progress);
-	/* user-user */
-	if (alerting->fields & MNCC_F_USERUSER)
-		gsm48_encode_useruser(msg, 0, &alerting->useruser);
-
-	new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
-{
-	struct gsm_mncc *progress = arg;
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC PROGRESS");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_PROGRESS;
-
-	/* progress */
-	gsm48_encode_progress(msg, 1, &progress->progress);
-	/* user-user */
-	if (progress->fields & MNCC_F_USERUSER)
-		gsm48_encode_useruser(msg, 0, &progress->useruser);
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
-{
-	struct gsm_mncc *connect = arg;
-	struct msgb *msg = gsm48_msgb_alloc_name("GSN 04.08 CC CON");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_CONNECT;
-
-	gsm48_stop_cc_timer(trans);
-	gsm48_start_cc_timer(trans, 0x313, GSM48_T313);
-
-	/* facility */
-	if (connect->fields & MNCC_F_FACILITY)
-		gsm48_encode_facility(msg, 0, &connect->facility);
-	/* progress */
-	if (connect->fields & MNCC_F_PROGRESS)
-		gsm48_encode_progress(msg, 0, &connect->progress);
-	/* connected number */
-	if (connect->fields & MNCC_F_CONNECTED)
-		gsm48_encode_connected(msg, &connect->connected);
-	/* user-user */
-	if (connect->fields & MNCC_F_USERUSER)
-		gsm48_encode_useruser(msg, 0, &connect->useruser);
-
-	new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
-	struct tlv_parsed tp;
-	struct gsm_mncc connect;
-
-	gsm48_stop_cc_timer(trans);
-
-	memset(&connect, 0, sizeof(struct gsm_mncc));
-	connect.callref = trans->callref;
-	tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
-	/* use subscriber as connected party number */
-	connect.fields |= MNCC_F_CONNECTED;
-	osmo_strlcpy(connect.connected.number, trans->vsub->msisdn, sizeof(connect.connected.number));
-	osmo_strlcpy(connect.imsi, trans->vsub->imsi, sizeof(connect.imsi));
-
-	/* facility */
-	if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
-		connect.fields |= MNCC_F_FACILITY;
-		gsm48_decode_facility(&connect.facility,
-				TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
-	}
-	/* user-user */
-	if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
-		connect.fields |= MNCC_F_USERUSER;
-		gsm48_decode_useruser(&connect.useruser,
-				TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
-	}
-	/* ss-version */
-	if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
-		connect.fields |= MNCC_F_SSVERSION;
-		gsm48_decode_ssversion(&connect.ssversion,
-				 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
-	}
-
-	new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
-	rate_ctr_inc(&trans->net->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT]);
-
-	return mncc_recvmsg(trans->net, trans, MNCC_SETUP_CNF, &connect);
-}
-
-
-static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm_mncc connect_ack;
-
-	gsm48_stop_cc_timer(trans);
-
-	new_cc_state(trans, GSM_CSTATE_ACTIVE);
-	rate_ctr_inc(&trans->net->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK]);
-
-	memset(&connect_ack, 0, sizeof(struct gsm_mncc));
-	connect_ack.callref = trans->callref;
-
-	return mncc_recvmsg(trans->net, trans, MNCC_SETUP_COMPL_IND,
-			    &connect_ack);
-}
-
-static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC CON ACK");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
-
-	new_cc_state(trans, GSM_CSTATE_ACTIVE);
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
-	struct tlv_parsed tp;
-	struct gsm_mncc disc;
-
-	gsm48_stop_cc_timer(trans);
-
-	new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
-
-	memset(&disc, 0, sizeof(struct gsm_mncc));
-	disc.callref = trans->callref;
-	tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0);
-	/* cause */
-	if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
-		disc.fields |= MNCC_F_CAUSE;
-		gsm48_decode_cause(&disc.cause,
-			     TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
-	}
-	/* facility */
-	if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
-		disc.fields |= MNCC_F_FACILITY;
-		gsm48_decode_facility(&disc.facility,
-				TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
-	}
-	/* user-user */
-	if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
-		disc.fields |= MNCC_F_USERUSER;
-		gsm48_decode_useruser(&disc.useruser,
-				TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
-	}
-	/* ss-version */
-	if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
-		disc.fields |= MNCC_F_SSVERSION;
-		gsm48_decode_ssversion(&disc.ssversion,
-				 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
-	}
-
-	return mncc_recvmsg(trans->net, trans, MNCC_DISC_IND, &disc);
-
-}
-
-static struct gsm_mncc_cause default_cause = {
-	.location	= GSM48_CAUSE_LOC_PRN_S_LU,
-	.coding		= 0,
-	.rec		= 0,
-	.rec_val	= 0,
-	.value		= GSM48_CC_CAUSE_NORMAL_UNSPEC,
-	.diag_len	= 0,
-	.diag		= { 0 },
-};
-
-static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
-{
-	struct gsm_mncc *disc = arg;
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC DISC");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_DISCONNECT;
-
-	gsm48_stop_cc_timer(trans);
-	gsm48_start_cc_timer(trans, 0x306, GSM48_T306);
-
-	/* cause */
-	if (disc->fields & MNCC_F_CAUSE)
-		gsm48_encode_cause(msg, 1, &disc->cause);
-	else
-		gsm48_encode_cause(msg, 1, &default_cause);
-
-	/* facility */
-	if (disc->fields & MNCC_F_FACILITY)
-		gsm48_encode_facility(msg, 0, &disc->facility);
-	/* progress */
-	if (disc->fields & MNCC_F_PROGRESS)
-		gsm48_encode_progress(msg, 0, &disc->progress);
-	/* user-user */
-	if (disc->fields & MNCC_F_USERUSER)
-		gsm48_encode_useruser(msg, 0, &disc->useruser);
-
-	/* store disconnect cause for T306 expiry */
-	memcpy(&trans->cc.msg, disc, sizeof(struct gsm_mncc));
-
-	new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
-	struct tlv_parsed tp;
-	struct gsm_mncc rel;
-	int rc;
-
-	gsm48_stop_cc_timer(trans);
-
-	memset(&rel, 0, sizeof(struct gsm_mncc));
-	rel.callref = trans->callref;
-	tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
-	/* cause */
-	if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
-		rel.fields |= MNCC_F_CAUSE;
-		gsm48_decode_cause(&rel.cause,
-			     TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
-	}
-	/* facility */
-	if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
-		rel.fields |= MNCC_F_FACILITY;
-		gsm48_decode_facility(&rel.facility,
-				TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
-	}
-	/* user-user */
-	if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
-		rel.fields |= MNCC_F_USERUSER;
-		gsm48_decode_useruser(&rel.useruser,
-				TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
-	}
-	/* ss-version */
-	if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
-		rel.fields |= MNCC_F_SSVERSION;
-		gsm48_decode_ssversion(&rel.ssversion,
-				 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
-	}
-
-	if (trans->cc.state == GSM_CSTATE_RELEASE_REQ) {
-		/* release collision 5.4.5 */
-		rc = mncc_recvmsg(trans->net, trans, MNCC_REL_CNF, &rel);
-	} else {
-		rc = gsm48_tx_simple(trans->conn,
-				     GSM48_PDISC_CC | (trans->transaction_id << 4),
-				     GSM48_MT_CC_RELEASE_COMPL);
-		rc = mncc_recvmsg(trans->net, trans, MNCC_REL_IND, &rel);
-	}
-
-	new_cc_state(trans, GSM_CSTATE_NULL);
-
-	trans->callref = 0;
-	trans_free(trans);
-
-	return rc;
-}
-
-static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
-{
-	struct gsm_mncc *rel = arg;
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC REL");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_RELEASE;
-
-	gsm48_stop_cc_timer(trans);
-	gsm48_start_cc_timer(trans, 0x308, GSM48_T308);
-
-	/* cause */
-	if (rel->fields & MNCC_F_CAUSE)
-		gsm48_encode_cause(msg, 0, &rel->cause);
-	/* facility */
-	if (rel->fields & MNCC_F_FACILITY)
-		gsm48_encode_facility(msg, 0, &rel->facility);
-	/* user-user */
-	if (rel->fields & MNCC_F_USERUSER)
-		gsm48_encode_useruser(msg, 0, &rel->useruser);
-
-	trans->cc.T308_second = 0;
-	memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
-
-	if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
-		new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
-	struct tlv_parsed tp;
-	struct gsm_mncc rel;
-	int rc = 0;
-
-	gsm48_stop_cc_timer(trans);
-
-	memset(&rel, 0, sizeof(struct gsm_mncc));
-	rel.callref = trans->callref;
-	tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
-	/* cause */
-	if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
-		rel.fields |= MNCC_F_CAUSE;
-		gsm48_decode_cause(&rel.cause,
-			     TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
-	}
-	/* facility */
-	if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
-		rel.fields |= MNCC_F_FACILITY;
-		gsm48_decode_facility(&rel.facility,
-				TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
-	}
-	/* user-user */
-	if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
-		rel.fields |= MNCC_F_USERUSER;
-		gsm48_decode_useruser(&rel.useruser,
-				TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
-	}
-	/* ss-version */
-	if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
-		rel.fields |= MNCC_F_SSVERSION;
-		gsm48_decode_ssversion(&rel.ssversion,
-				 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
-	}
-
-	if (trans->callref) {
-		switch (trans->cc.state) {
-		case GSM_CSTATE_CALL_PRESENT:
-			rc = mncc_recvmsg(trans->net, trans,
-					  MNCC_REJ_IND, &rel);
-			break;
-		case GSM_CSTATE_RELEASE_REQ:
-			rc = mncc_recvmsg(trans->net, trans,
-					  MNCC_REL_CNF, &rel);
-			break;
-		default:
-			rc = mncc_recvmsg(trans->net, trans,
-					  MNCC_REL_IND, &rel);
-		}
-	}
-
-	trans->callref = 0;
-	trans_free(trans);
-
-	return rc;
-}
-
-static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
-{
-	struct gsm_mncc *rel = arg;
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC REL COMPL");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	int ret;
-
-	gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
-
-	trans->callref = 0;
-
-	gsm48_stop_cc_timer(trans);
-
-	/* cause */
-	if (rel->fields & MNCC_F_CAUSE)
-		gsm48_encode_cause(msg, 0, &rel->cause);
-	/* facility */
-	if (rel->fields & MNCC_F_FACILITY)
-		gsm48_encode_facility(msg, 0, &rel->facility);
-	/* user-user */
-	if (rel->fields & MNCC_F_USERUSER)
-		gsm48_encode_useruser(msg, 0, &rel->useruser);
-
-	ret =  gsm48_conn_sendmsg(msg, trans->conn, trans);
-
-	trans_free(trans);
-
-	return ret;
-}
-
-static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
-	struct tlv_parsed tp;
-	struct gsm_mncc fac;
-
-	memset(&fac, 0, sizeof(struct gsm_mncc));
-	fac.callref = trans->callref;
-	tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0);
-	/* facility */
-	if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) {
-		fac.fields |= MNCC_F_FACILITY;
-		gsm48_decode_facility(&fac.facility,
-				TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
-	}
-	/* ss-version */
-	if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) {
-		fac.fields |= MNCC_F_SSVERSION;
-		gsm48_decode_ssversion(&fac.ssversion,
-				 TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
-	}
-
-	return mncc_recvmsg(trans->net, trans, MNCC_FACILITY_IND, &fac);
-}
-
-static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
-{
-	struct gsm_mncc *fac = arg;
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC FAC");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_FACILITY;
-
-	/* facility */
-	gsm48_encode_facility(msg, 1, &fac->facility);
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm_mncc hold;
-
-	memset(&hold, 0, sizeof(struct gsm_mncc));
-	hold.callref = trans->callref;
-	return mncc_recvmsg(trans->net, trans, MNCC_HOLD_IND, &hold);
-}
-
-static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC HLD ACK");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_HOLD_ACK;
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
-{
-	struct gsm_mncc *hold_rej = arg;
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC HLD REJ");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_HOLD_REJ;
-
-	/* cause */
-	if (hold_rej->fields & MNCC_F_CAUSE)
-		gsm48_encode_cause(msg, 1, &hold_rej->cause);
-	else
-		gsm48_encode_cause(msg, 1, &default_cause);
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm_mncc retrieve;
-
-	memset(&retrieve, 0, sizeof(struct gsm_mncc));
-	retrieve.callref = trans->callref;
-	return mncc_recvmsg(trans->net, trans, MNCC_RETRIEVE_IND,
-			    &retrieve);
-}
-
-static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC RETR ACK");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_RETR_ACK;
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
-{
-	struct gsm_mncc *retrieve_rej = arg;
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC RETR REJ");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_RETR_REJ;
-
-	/* cause */
-	if (retrieve_rej->fields & MNCC_F_CAUSE)
-		gsm48_encode_cause(msg, 1, &retrieve_rej->cause);
-	else
-		gsm48_encode_cause(msg, 1, &default_cause);
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
-	struct tlv_parsed tp;
-	struct gsm_mncc dtmf;
-
-	memset(&dtmf, 0, sizeof(struct gsm_mncc));
-	dtmf.callref = trans->callref;
-	tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
-	/* keypad facility */
-	if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) {
-		dtmf.fields |= MNCC_F_KEYPAD;
-		gsm48_decode_keypad(&dtmf.keypad,
-			      TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
-	}
-
-	return mncc_recvmsg(trans->net, trans, MNCC_START_DTMF_IND, &dtmf);
-}
-
-static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
-{
-	struct gsm_mncc *dtmf = arg;
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 DTMF ACK");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
-
-	/* keypad */
-	if (dtmf->fields & MNCC_F_KEYPAD)
-		gsm48_encode_keypad(msg, dtmf->keypad);
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
-{
-	struct gsm_mncc *dtmf = arg;
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 DTMF REJ");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
-
-	/* cause */
-	if (dtmf->fields & MNCC_F_CAUSE)
-		gsm48_encode_cause(msg, 1, &dtmf->cause);
-	else
-		gsm48_encode_cause(msg, 1, &default_cause);
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 DTMF STP ACK");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm_mncc dtmf;
-
-	memset(&dtmf, 0, sizeof(struct gsm_mncc));
-	dtmf.callref = trans->callref;
-
-	return mncc_recvmsg(trans->net, trans, MNCC_STOP_DTMF_IND, &dtmf);
-}
-
-static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
-	struct tlv_parsed tp;
-	struct gsm_mncc modify;
-
-	memset(&modify, 0, sizeof(struct gsm_mncc));
-	modify.callref = trans->callref;
-	tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
-	/* bearer capability */
-	if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
-		modify.fields |= MNCC_F_BEARER_CAP;
-		gsm48_decode_bearer_cap(&modify.bearer_cap,
-				  TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
-
-		/* Create a copy of the bearer capability
-		 * in the transaction struct, so we can use
-		 * this information later */
-		memcpy(&trans->bearer_cap,&modify.bearer_cap,
-		       sizeof(trans->bearer_cap));
-	}
-
-	new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
-
-	return mncc_recvmsg(trans->net, trans, MNCC_MODIFY_IND, &modify);
-}
-
-static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
-{
-	struct gsm_mncc *modify = arg;
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC MOD");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_MODIFY;
-
-	gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
-
-	/* bearer capability */
-	gsm48_encode_bearer_cap(msg, 1, &modify->bearer_cap);
-
-	new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
-	struct tlv_parsed tp;
-	struct gsm_mncc modify;
-
-	gsm48_stop_cc_timer(trans);
-
-	memset(&modify, 0, sizeof(struct gsm_mncc));
-	modify.callref = trans->callref;
-	tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0);
-	/* bearer capability */
-	if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
-		modify.fields |= MNCC_F_BEARER_CAP;
-		gsm48_decode_bearer_cap(&modify.bearer_cap,
-				  TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
-
-		/* Create a copy of the bearer capability
-		 * in the transaction struct, so we can use
-		 * this information later */
-		memcpy(&trans->bearer_cap,&modify.bearer_cap,
-		       sizeof(trans->bearer_cap));
-	}
-
-	new_cc_state(trans, GSM_CSTATE_ACTIVE);
-
-	return mncc_recvmsg(trans->net, trans, MNCC_MODIFY_CNF, &modify);
-}
-
-static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
-{
-	struct gsm_mncc *modify = arg;
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC MOD COMPL");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
-
-	/* bearer capability */
-	gsm48_encode_bearer_cap(msg, 1, &modify->bearer_cap);
-
-	new_cc_state(trans, GSM_CSTATE_ACTIVE);
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
-	struct tlv_parsed tp;
-	struct gsm_mncc modify;
-
-	gsm48_stop_cc_timer(trans);
-
-	memset(&modify, 0, sizeof(struct gsm_mncc));
-	modify.callref = trans->callref;
-	tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE);
-	/* bearer capability */
-	if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) {
-		modify.fields |= GSM48_IE_BEARER_CAP;
-		gsm48_decode_bearer_cap(&modify.bearer_cap,
-				  TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1);
-
-		/* Create a copy of the bearer capability
-		 * in the transaction struct, so we can use
-		 * this information later */
-		memcpy(&trans->bearer_cap,&modify.bearer_cap,
-		       sizeof(trans->bearer_cap));
-	}
-	/* cause */
-	if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) {
-		modify.fields |= MNCC_F_CAUSE;
-		gsm48_decode_cause(&modify.cause,
-			     TLVP_VAL(&tp, GSM48_IE_CAUSE)-1);
-	}
-
-	new_cc_state(trans, GSM_CSTATE_ACTIVE);
-
-	return mncc_recvmsg(trans->net, trans, MNCC_MODIFY_REJ, &modify);
-}
-
-static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
-{
-	struct gsm_mncc *modify = arg;
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC MOD REJ");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
-
-	/* bearer capability */
-	gsm48_encode_bearer_cap(msg, 1, &modify->bearer_cap);
-	/* cause */
-	gsm48_encode_cause(msg, 1, &modify->cause);
-
-	new_cc_state(trans, GSM_CSTATE_ACTIVE);
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
-{
-	struct gsm_mncc *notify = arg;
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC NOT");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_NOTIFY;
-
-	/* notify */
-	gsm48_encode_notify(msg, notify->notify);
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
-//	struct tlv_parsed tp;
-	struct gsm_mncc notify;
-
-	memset(&notify, 0, sizeof(struct gsm_mncc));
-	notify.callref = trans->callref;
-//	tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len);
-	if (payload_len >= 1)
-		gsm48_decode_notify(&notify.notify, gh->data);
-
-	return mncc_recvmsg(trans->net, trans, MNCC_NOTIFY_IND, &notify);
-}
-
-static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
-{
-	struct gsm_mncc *user = arg;
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 USR INFO");
-	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-	gh->msg_type = GSM48_MT_CC_USER_INFO;
-
-	/* user-user */
-	if (user->fields & MNCC_F_USERUSER)
-		gsm48_encode_useruser(msg, 1, &user->useruser);
-	/* more data */
-	if (user->more)
-		gsm48_encode_more(msg);
-
-	return gsm48_conn_sendmsg(msg, trans->conn, trans);
-}
-
-static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
-	struct tlv_parsed tp;
-	struct gsm_mncc user;
-
-	memset(&user, 0, sizeof(struct gsm_mncc));
-	user.callref = trans->callref;
-	tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0);
-	/* user-user */
-	if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
-		user.fields |= MNCC_F_USERUSER;
-		gsm48_decode_useruser(&user.useruser,
-				TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
-	}
-	/* more data */
-	if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
-		user.more = 1;
-
-	return mncc_recvmsg(trans->net, trans, MNCC_USERINFO_IND, &user);
-}
-
-static void mncc_recv_rtp(struct gsm_network *net, uint32_t callref,
-		int cmd, uint32_t addr, uint16_t port, uint32_t payload_type,
-		uint32_t payload_msg_type)
-{
-	uint8_t data[sizeof(struct gsm_mncc)];
-	struct gsm_mncc_rtp *rtp;
-
-	memset(&data, 0, sizeof(data));
-	rtp = (struct gsm_mncc_rtp *) &data[0];
-
-	rtp->callref = callref;
-	rtp->msg_type = cmd;
-	rtp->ip = addr;
-	rtp->port = port;
-	rtp->payload_type = payload_type;
-	rtp->payload_msg_type = payload_msg_type;
-	mncc_recvmsg(net, NULL, cmd, (struct gsm_mncc *)data);
-}
-
-static void mncc_recv_rtp_sock(struct gsm_network *net, struct gsm_trans *trans, int cmd)
-{
-	int msg_type;
-
-	/* FIXME This has to be set to some meaningful value.
-	 * Possible options are:
-	 * GSM_TCHF_FRAME, GSM_TCHF_FRAME_EFR,
-	 * GSM_TCHH_FRAME, GSM_TCH_FRAME_AMR
-	 * (0 if unknown) */
-	msg_type = GSM_TCHF_FRAME;
-
-	uint32_t addr = mgcpgw_client_remote_addr_n(net->mgcpgw.client);
-	uint16_t port = trans->conn->rtp.port_cn;
-
-	/* FIXME: This has to be set to some meaningful value,
-	 * before the MSC-Split, this value was pulled from
-	 * lchan->abis_ip.rtp_payload */
-	uint32_t payload_type = 0;
-
-	return mncc_recv_rtp(net, trans->callref, cmd,
-			addr,
-			port,
-		        payload_type,
-			msg_type);
-}
-
-static void mncc_recv_rtp_err(struct gsm_network *net, uint32_t callref, int cmd)
-{
-	return mncc_recv_rtp(net, callref, cmd, 0, 0, 0, 0);
-}
-
-static int tch_rtp_create(struct gsm_network *net, uint32_t callref)
-{
-	struct gsm_trans *trans;
-	int rc;
-
-	/* Find callref */
-	trans = trans_find_by_callref(net, callref);
-	if (!trans) {
-		LOGP(DMNCC, LOGL_ERROR, "RTP create for non-existing trans\n");
-		mncc_recv_rtp_err(net, callref, MNCC_RTP_CREATE);
-		return -EIO;
-	}
-	log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub);
-	if (!trans->conn) {
-		LOGP(DMNCC, LOGL_NOTICE, "RTP create for trans without conn\n");
-		mncc_recv_rtp_err(net, callref, MNCC_RTP_CREATE);
-		return 0;
-	}
-
-	trans->conn->mncc_rtp_bridge = 1;
-
-	/* When we call msc_call_assignment() we will trigger, depending
-	 * on the RAN type the call assignment on the A or Iu interface.
-	 * msc_call_assignment() also takes care about sending the CRCX
-	 * command to the MGCP-GW. The CRCX will return the port number,
-	 * where the PBX (e.g. Asterisk) will send its RTP stream to. We
-	 * have to return this port number back to the MNCC by sending
-	 * it back with the TCH_RTP_CREATE message. To make sure that
-	 * this message is sent AFTER the response to CRCX from the
-	 * MGCP-GW has arrived, we need will instruct msc_call_assignment()
-	 * to take care of this by setting trans->tch_rtp_create to true.
-	 * This will make sure that gsm48_tch_rtp_create() (below) is
-	 * called as soon as the local port number has become known. */
-	trans->tch_rtp_create = true;
-
-	/* Assign call (if not done yet) */
-	if (trans->assignment_done == false) {
-		rc = msc_call_assignment(trans);
-		trans->assignment_done = true;
-	}
-	else
-		rc = 0;
-
-	return rc;
-}
-
-/* Trigger TCH_RTP_CREATE acknowledgement */
-int gsm48_tch_rtp_create(struct gsm_trans *trans)
-{
-	/* This function is called as soon as the port, on which the
-	 * mgcp-gw expects the incoming RTP stream from the remote
-	 * end (e.g. Asterisk) is known. */
-
-	struct gsm_subscriber_connection *conn = trans->conn;
-	struct gsm_network *network = conn->network;
-
-	mncc_recv_rtp_sock(network, trans, MNCC_RTP_CREATE);
-	return 0;
-}
-
-static int tch_rtp_connect(struct gsm_network *net, void *arg)
-{
-	struct gsm_trans *trans;
-	struct gsm_mncc_rtp *rtp = arg;
-
-	/* Find callref */
-	trans = trans_find_by_callref(net, rtp->callref);
-	if (!trans) {
-		LOGP(DMNCC, LOGL_ERROR, "RTP connect for non-existing trans\n");
-		mncc_recv_rtp_err(net, rtp->callref, MNCC_RTP_CONNECT);
-		return -EIO;
-	}
-	log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub);
-	if (!trans->conn) {
-		LOGP(DMNCC, LOGL_ERROR, "RTP connect for trans without conn\n");
-		mncc_recv_rtp_err(net, rtp->callref, MNCC_RTP_CONNECT);
-		return 0;
-	}
-
-	msc_call_connect(trans,rtp->port,rtp->ip);
-	return 0;
-}
-
-static struct downstate {
-	uint32_t	states;
-	int		type;
-	int		(*rout) (struct gsm_trans *trans, void *arg);
-} downstatelist[] = {
-	/* mobile originating call establishment */
-	{SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.2 */
-	 MNCC_CALL_PROC_REQ, gsm48_cc_tx_call_proc_and_assign},
-	{SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.2 | 5.2.1.5 */
-	 MNCC_ALERT_REQ, gsm48_cc_tx_alerting},
-	{SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC) | SBIT(GSM_CSTATE_CALL_DELIVERED), /* 5.2.1.2 | 5.2.1.6 | 5.2.1.6 */
-	 MNCC_SETUP_RSP, gsm48_cc_tx_connect},
-	{SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.4.2 */
-	 MNCC_PROGRESS_REQ, gsm48_cc_tx_progress},
-	/* mobile terminating call establishment */
-	{SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */
-	 MNCC_SETUP_REQ, gsm48_cc_tx_setup},
-	{SBIT(GSM_CSTATE_CONNECT_REQUEST),
-	 MNCC_SETUP_COMPL_REQ, gsm48_cc_tx_connect_ack},
-	 /* signalling during call */
-	{SBIT(GSM_CSTATE_ACTIVE),
-	 MNCC_NOTIFY_REQ, gsm48_cc_tx_notify},
-	{ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ),
-	 MNCC_FACILITY_REQ, gsm48_cc_tx_facility},
-	{ALL_STATES,
-	 MNCC_START_DTMF_RSP, gsm48_cc_tx_start_dtmf_ack},
-	{ALL_STATES,
-	 MNCC_START_DTMF_REJ, gsm48_cc_tx_start_dtmf_rej},
-	{ALL_STATES,
-	 MNCC_STOP_DTMF_RSP, gsm48_cc_tx_stop_dtmf_ack},
-	{SBIT(GSM_CSTATE_ACTIVE),
-	 MNCC_HOLD_CNF, gsm48_cc_tx_hold_ack},
-	{SBIT(GSM_CSTATE_ACTIVE),
-	 MNCC_HOLD_REJ, gsm48_cc_tx_hold_rej},
-	{SBIT(GSM_CSTATE_ACTIVE),
-	 MNCC_RETRIEVE_CNF, gsm48_cc_tx_retrieve_ack},
-	{SBIT(GSM_CSTATE_ACTIVE),
-	 MNCC_RETRIEVE_REJ, gsm48_cc_tx_retrieve_rej},
-	{SBIT(GSM_CSTATE_ACTIVE),
-	 MNCC_MODIFY_REQ, gsm48_cc_tx_modify},
-	{SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
-	 MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete},
-	{SBIT(GSM_CSTATE_MO_ORIG_MODIFY),
-	 MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject},
-	{SBIT(GSM_CSTATE_ACTIVE),
-	 MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo},
-	/* clearing */
-	{SBIT(GSM_CSTATE_INITIATED),
-	 MNCC_REJ_REQ, gsm48_cc_tx_release_compl},
-	{ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.4 */
-	 MNCC_DISC_REQ, gsm48_cc_tx_disconnect},
-	{ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
-	 MNCC_REL_REQ, gsm48_cc_tx_release},
-};
-
-#define DOWNSLLEN \
-	(sizeof(downstatelist) / sizeof(struct downstate))
-
-
-int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg)
-{
-	int i, rc = 0;
-	struct gsm_trans *trans = NULL, *transt;
-	struct gsm_subscriber_connection *conn = NULL;
-	struct gsm_mncc *data = arg, rel;
-
-	DEBUGP(DMNCC, "receive message %s\n", get_mncc_name(msg_type));
-
-	/* handle special messages */
-	switch(msg_type) {
-	case MNCC_BRIDGE:
-		rc = tch_bridge(net, arg);
-		if (rc < 0)
-			disconnect_bridge(net, arg, -rc);
-		return rc;
-	case MNCC_RTP_CREATE:
-		return tch_rtp_create(net, data->callref);
-	case MNCC_RTP_CONNECT:
-		return tch_rtp_connect(net, arg);
-	case MNCC_RTP_FREE:
-		/* unused right now */
-		return -EIO;
-
-	case MNCC_FRAME_DROP:
-	case MNCC_FRAME_RECV:
-	case GSM_TCHF_FRAME:
-	case GSM_TCHF_FRAME_EFR:
-	case GSM_TCHH_FRAME:
-	case GSM_TCH_FRAME_AMR:
-		LOGP(DMNCC, LOGL_ERROR, "RTP streams must be handled externally; %s not supported.\n",
-		     get_mncc_name(msg_type));
-		return -ENOTSUP;
-	}
-
-	memset(&rel, 0, sizeof(struct gsm_mncc));
-	rel.callref = data->callref;
-
-	/* Find callref */
-	trans = trans_find_by_callref(net, data->callref);
-
-	/* Callref unknown */
-	if (!trans) {
-		struct vlr_subscr *vsub;
-
-		if (msg_type != MNCC_SETUP_REQ) {
-			DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
-				"Received '%s' from MNCC with "
-				"unknown callref %d\n", data->called.number,
-				get_mncc_name(msg_type), data->callref);
-			/* Invalid call reference */
-			return mncc_release_ind(net, NULL, data->callref,
-						GSM48_CAUSE_LOC_PRN_S_LU,
-						GSM48_CC_CAUSE_INVAL_TRANS_ID);
-		}
-		if (!data->called.number[0] && !data->imsi[0]) {
-			DEBUGP(DCC, "(bts - trx - ts - ti) "
-				"Received '%s' from MNCC with "
-				"no number or IMSI\n", get_mncc_name(msg_type));
-			/* Invalid number */
-			return mncc_release_ind(net, NULL, data->callref,
-						GSM48_CAUSE_LOC_PRN_S_LU,
-						GSM48_CC_CAUSE_INV_NR_FORMAT);
-		}
-		/* New transaction due to setup, find subscriber */
-		if (data->called.number[0])
-			vsub = vlr_subscr_find_by_msisdn(net->vlr,
-							 data->called.number);
-		else
-			vsub = vlr_subscr_find_by_imsi(net->vlr, data->imsi);
-
-		/* update the subscriber we deal with */
-		log_set_context(LOG_CTX_VLR_SUBSCR, vsub);
-
-		/* If subscriber is not found */
-		if (!vsub) {
-			DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
-				"Received '%s' from MNCC with "
-				"unknown subscriber %s\n", data->called.number,
-				get_mncc_name(msg_type), data->called.number);
-			/* Unknown subscriber */
-			return mncc_release_ind(net, NULL, data->callref,
-						GSM48_CAUSE_LOC_PRN_S_LU,
-						GSM48_CC_CAUSE_UNASSIGNED_NR);
-		}
-		/* If subscriber is not "attached" */
-		if (!vsub->lac) {
-			DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
-				"Received '%s' from MNCC with "
-				"detached subscriber %s\n", data->called.number,
-				get_mncc_name(msg_type), data->called.number);
-			vlr_subscr_put(vsub);
-			/* Temporarily out of order */
-			return mncc_release_ind(net, NULL, data->callref,
-						GSM48_CAUSE_LOC_PRN_S_LU,
-						GSM48_CC_CAUSE_DEST_OOO);
-		}
-		/* Create transaction */
-		trans = trans_alloc(net, vsub, GSM48_PDISC_CC, 0xff, data->callref);
-		if (!trans) {
-			DEBUGP(DCC, "No memory for trans.\n");
-			vlr_subscr_put(vsub);
-			/* Ressource unavailable */
-			mncc_release_ind(net, NULL, data->callref,
-					 GSM48_CAUSE_LOC_PRN_S_LU,
-					 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
-			return -ENOMEM;
-		}
-
-		/* Find conn */
-		conn = connection_for_subscr(vsub);
-
-		/* If subscriber has no conn */
-		if (!conn) {
-			/* find transaction with this subscriber already paging */
-			llist_for_each_entry(transt, &net->trans_list, entry) {
-				/* Transaction of our conn? */
-				if (transt == trans ||
-				    transt->vsub != vsub)
-					continue;
-				DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
-					"Received '%s' from MNCC with "
-					"unallocated channel, paging already "
-					"started for lac %d.\n",
-					data->called.number,
-					get_mncc_name(msg_type), vsub->lac);
-				vlr_subscr_put(vsub);
-				trans_free(trans);
-				return 0;
-			}
-			/* store setup information until paging succeeds */
-			memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
-
-			/* Request a channel */
-			trans->paging_request = subscr_request_conn(
-							vsub,
-							setup_trig_pag_evt,
-							trans,
-							"MNCC: establish call");
-			if (!trans->paging_request) {
-				LOGP(DCC, LOGL_ERROR, "Failed to allocate paging token.\n");
-				vlr_subscr_put(vsub);
-				trans_free(trans);
-				return 0;
-			}
-			vlr_subscr_put(vsub);
-			return 0;
-		}
-
-		/* Assign conn */
-		trans->conn = msc_subscr_conn_get(conn);
-		vlr_subscr_put(vsub);
-	} else {
-		/* update the subscriber we deal with */
-		log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub);
-	}
-
-	if (trans->conn)
-		conn = trans->conn;
-
-	/* if paging did not respond yet */
-	if (!conn) {
-		DEBUGP(DCC, "(sub %s) "
-			"Received '%s' from MNCC in paging state\n",
-			vlr_subscr_msisdn_or_name(trans->vsub),
-			get_mncc_name(msg_type));
-		mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
-				GSM48_CC_CAUSE_NORM_CALL_CLEAR);
-		if (msg_type == MNCC_REL_REQ)
-			rc = mncc_recvmsg(net, trans, MNCC_REL_CNF, &rel);
-		else
-			rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
-		trans->callref = 0;
-		trans_free(trans);
-		return rc;
-	}
-
-	DEBUGP(DCC, "(ti %02x sub %s) "
-		"Received '%s' from MNCC in state %d (%s)\n",
-		trans->transaction_id,
-		vlr_subscr_msisdn_or_name(trans->conn->vsub),
-		get_mncc_name(msg_type), trans->cc.state,
-		gsm48_cc_state_name(trans->cc.state));
-
-	/* Find function for current state and message */
-	for (i = 0; i < DOWNSLLEN; i++)
-		if ((msg_type == downstatelist[i].type)
-		 && ((1 << trans->cc.state) & downstatelist[i].states))
-			break;
-	if (i == DOWNSLLEN) {
-		DEBUGP(DCC, "Message unhandled at this state.\n");
-		return 0;
-	}
-
-	rc = downstatelist[i].rout(trans, arg);
-
-	return rc;
-}
-
-
-static struct datastate {
-	uint32_t	states;
-	int		type;
-	int		(*rout) (struct gsm_trans *trans, struct msgb *msg);
-} datastatelist[] = {
-	/* mobile originating call establishment */
-	{SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
-	 GSM48_MT_CC_SETUP, gsm48_cc_rx_setup},
-	{SBIT(GSM_CSTATE_NULL), /* 5.2.1.2 */
-	 GSM48_MT_CC_EMERG_SETUP, gsm48_cc_rx_setup},
-	{SBIT(GSM_CSTATE_CONNECT_IND), /* 5.2.1.2 */
-	 GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack},
-	/* mobile terminating call establishment */
-	{SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.2 */
-	 GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf},
-	{SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */
-	 GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting},
-	{SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF) | SBIT(GSM_CSTATE_CALL_RECEIVED), /* (5.2.2.6) | 5.2.2.6 | 5.2.2.6 */
-	 GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect},
-	 /* signalling during call */
-	{ALL_STATES - SBIT(GSM_CSTATE_NULL),
-	 GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility},
-	{SBIT(GSM_CSTATE_ACTIVE),
-	 GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify},
-	{ALL_STATES,
-	 GSM48_MT_CC_START_DTMF, gsm48_cc_rx_start_dtmf},
-	{ALL_STATES,
-	 GSM48_MT_CC_STOP_DTMF, gsm48_cc_rx_stop_dtmf},
-	{ALL_STATES,
-	 GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq},
-	{SBIT(GSM_CSTATE_ACTIVE),
-	 GSM48_MT_CC_HOLD, gsm48_cc_rx_hold},
-	{SBIT(GSM_CSTATE_ACTIVE),
-	 GSM48_MT_CC_RETR, gsm48_cc_rx_retrieve},
-	{SBIT(GSM_CSTATE_ACTIVE),
-	 GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
-	{SBIT(GSM_CSTATE_MO_TERM_MODIFY),
-	 GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete},
-	{SBIT(GSM_CSTATE_MO_TERM_MODIFY),
-	 GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject},
-	{SBIT(GSM_CSTATE_ACTIVE),
-	 GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo},
-	/* clearing */
-	{ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* 5.4.3.2 */
-	 GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect},
-	{ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.4.1.2.2 */
-	 GSM48_MT_CC_RELEASE, gsm48_cc_rx_release},
-	{ALL_STATES, /* 5.4.3.4 */
-	 GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl},
-};
-
-#define DATASLLEN \
-	(sizeof(datastatelist) / sizeof(struct datastate))
-
-static int gsm0408_rcv_cc(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	uint8_t msg_type = gsm48_hdr_msg_type(gh);
-	uint8_t transaction_id = gsm48_hdr_trans_id_flip_ti(gh);
-	struct gsm_trans *trans = NULL;
-	int i, rc = 0;
-
-	if (msg_type & 0x80) {
-		DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type);
-		return -EINVAL;
-	}
-
-	if (!conn->vsub) {
-		LOGP(DCC, LOGL_ERROR, "Invalid conn: no subscriber\n");
-		return -EINVAL;
-	}
-
-	/* Find transaction */
-	trans = trans_find_by_id(conn, GSM48_PDISC_CC, transaction_id);
-
-#if BEFORE_MSCSPLIT
-	/* Re-enable this log output once we can obtain this information via
-	 * A-interface, see OS#2391. */
-	DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
-		"Received '%s' from MS in state %d (%s)\n",
-		conn->bts->nr, conn->lchan->ts->trx->nr, conn->lchan->ts->nr,
-		transaction_id, vlr_subscr_msisdn_or_name(conn->vsub),
-		gsm48_cc_msg_name(msg_type), trans?(trans->cc.state):0,
-		gsm48_cc_state_name(trans?(trans->cc.state):0));
-#endif
-
-	/* Create transaction */
-	if (!trans) {
-		DEBUGP(DCC, "Unknown transaction ID %x, "
-			"creating new trans.\n", transaction_id);
-		/* Create transaction */
-		trans = trans_alloc(conn->network, conn->vsub,
-				    GSM48_PDISC_CC,
-				    transaction_id, new_callref++);
-		if (!trans) {
-			DEBUGP(DCC, "No memory for trans.\n");
-			rc = gsm48_tx_simple(conn,
-					     GSM48_PDISC_CC | (transaction_id << 4),
-					     GSM48_MT_CC_RELEASE_COMPL);
-			return -ENOMEM;
-		}
-		/* Assign transaction */
-		trans->conn = msc_subscr_conn_get(conn);
-		cm_service_request_concludes(conn, msg);
-	}
-
-	/* find function for current state and message */
-	for (i = 0; i < DATASLLEN; i++)
-		if ((msg_type == datastatelist[i].type)
-		 && ((1 << trans->cc.state) & datastatelist[i].states))
-			break;
-	if (i == DATASLLEN) {
-		DEBUGP(DCC, "Message unhandled at this state.\n");
-		return 0;
-	}
-
-	assert(trans->vsub);
-
-	rc = datastatelist[i].rout(trans, msg);
-
-	msc_subscr_conn_communicating(conn);
-	return rc;
-}
-
-static bool msg_is_initially_permitted(const struct gsm48_hdr *hdr)
-{
-	uint8_t pdisc = gsm48_hdr_pdisc(hdr);
-	uint8_t msg_type = gsm48_hdr_msg_type(hdr);
-
-	switch (pdisc) {
-	case GSM48_PDISC_MM:
-		switch (msg_type) {
-		case GSM48_MT_MM_LOC_UPD_REQUEST:
-		case GSM48_MT_MM_CM_SERV_REQ:
-		case GSM48_MT_MM_AUTH_RESP:
-		case GSM48_MT_MM_AUTH_FAIL:
-		case GSM48_MT_MM_ID_RESP:
-		case GSM48_MT_MM_TMSI_REALL_COMPL:
-		case GSM48_MT_MM_IMSI_DETACH_IND:
-			return true;
-		default:
-			break;
-		}
-		break;
-	case GSM48_PDISC_RR:
-		switch (msg_type) {
-		case GSM48_MT_RR_CIPH_M_COMPL:
-		case GSM48_MT_RR_PAG_RESP:
-			return true;
-		default:
-			break;
-		}
-		break;
-	default:
-		break;
-	}
-
-	return false;
-}
-
-void cm_service_request_concludes(struct gsm_subscriber_connection *conn,
-				  struct msgb *msg)
-{
-
-	/* If a CM Service Request was received before, this is the request the
-	 * conn was opened for. No need to wait for further messages. */
-
-	if (!conn->received_cm_service_request)
-		return;
-
-	if (log_check_level(DMM, LOGL_DEBUG)) {
-		struct gsm48_hdr *gh = msgb_l3(msg);
-		uint8_t pdisc = gsm48_hdr_pdisc(gh);
-		uint8_t msg_type = gsm48_hdr_msg_type(gh);
-
-		DEBUGP(DMM, "%s: rx msg %s:"
-		       " received_cm_service_request changes to false\n",
-		       vlr_subscr_name(conn->vsub),
-		       gsm48_pdisc_msgtype_name(pdisc, msg_type));
-	}
-	conn->received_cm_service_request = false;
-}
-
-
-/* Main entry point for GSM 04.08/44.008 Layer 3 data (e.g. from the BSC). */
-int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	uint8_t pdisc = gsm48_hdr_pdisc(gh);
-	int rc = 0;
-
-	OSMO_ASSERT(conn);
-	OSMO_ASSERT(msg);
-
-	LOGP(DRLL, LOGL_DEBUG, "Dispatching 04.08 message %s (0x%x:0x%x)\n",
-	     gsm48_pdisc_msgtype_name(pdisc, gsm48_hdr_msg_type(gh)),
-	     pdisc, gsm48_hdr_msg_type(gh));
-
-	if (!msc_subscr_conn_is_accepted(conn)
-	    && !msg_is_initially_permitted(gh)) {
-		LOGP(DRLL, LOGL_ERROR,
-		     "subscr %s: Message not permitted for initial conn: %s\n",
-		     vlr_subscr_name(conn->vsub),
-		     gsm48_pdisc_msgtype_name(pdisc, gsm48_hdr_msg_type(gh)));
-		return -EACCES;
-	}
-
-	if (conn->vsub && conn->vsub->cs.attached_via_ran != conn->via_ran) {
-		LOGP(DMM, LOGL_ERROR,
-		     "%s: Illegal situation: RAN type mismatch:"
-		     " attached via %s, received message via %s\n",
-		     vlr_subscr_name(conn->vsub),
-		     ran_type_name(conn->vsub->cs.attached_via_ran),
-		     ran_type_name(conn->via_ran));
-		return -EACCES;
-	}
-
-#if 0
-	if (silent_call_reroute(conn, msg))
-		return silent_call_rx(conn, msg);
-#endif
-
-	switch (pdisc) {
-	case GSM48_PDISC_CC:
-		rc = gsm0408_rcv_cc(conn, msg);
-		break;
-	case GSM48_PDISC_MM:
-		rc = gsm0408_rcv_mm(conn, msg);
-		break;
-	case GSM48_PDISC_RR:
-		rc = gsm0408_rcv_rr(conn, msg);
-		break;
-	case GSM48_PDISC_SMS:
-		rc = gsm0411_rcv_sms(conn, msg);
-		break;
-	case GSM48_PDISC_MM_GPRS:
-	case GSM48_PDISC_SM_GPRS:
-		LOGP(DRLL, LOGL_NOTICE, "Unimplemented "
-			"GSM 04.08 discriminator 0x%02x\n", pdisc);
-		rc = -ENOTSUP;
-		break;
-	case GSM48_PDISC_NC_SS:
-		rc = handle_rcv_ussd(conn, msg);
-		break;
-	case GSM48_PDISC_TEST:
-		rc = gsm0414_rcv_test(conn, msg);
-		break;
-	default:
-		LOGP(DRLL, LOGL_NOTICE, "Unknown "
-			"GSM 04.08 discriminator 0x%02x\n", pdisc);
-		rc = -EINVAL;
-		break;
-	}
-
-	return rc;
-}
-
-/***********************************************************************
- * VLR integration
- ***********************************************************************/
-
-/* VLR asks us to send an authentication request */
-static int msc_vlr_tx_auth_req(void *msc_conn_ref, struct gsm_auth_tuple *at,
-			       bool send_autn)
-{
-	struct gsm_subscriber_connection *conn = msc_conn_ref;
-	return gsm48_tx_mm_auth_req(conn, at->vec.rand,
-				    send_autn? at->vec.autn : NULL,
-				    at->key_seq);
-}
-
-/* VLR asks us to send an authentication reject */
-static int msc_vlr_tx_auth_rej(void *msc_conn_ref)
-{
-	struct gsm_subscriber_connection *conn = msc_conn_ref;
-	return gsm48_tx_mm_auth_rej(conn);
-}
-
-/* VLR asks us to transmit an Identity Request of given type */
-static int msc_vlr_tx_id_req(void *msc_conn_ref, uint8_t mi_type)
-{
-	struct gsm_subscriber_connection *conn = msc_conn_ref;
-	return mm_tx_identity_req(conn, mi_type);
-}
-
-/* VLR asks us to transmit a Location Update Accept */
-static int msc_vlr_tx_lu_acc(void *msc_conn_ref, uint32_t send_tmsi)
-{
-	struct gsm_subscriber_connection *conn = msc_conn_ref;
-	return gsm0408_loc_upd_acc(conn, send_tmsi);
-}
-
-/* VLR asks us to transmit a Location Update Reject */
-static int msc_vlr_tx_lu_rej(void *msc_conn_ref, uint8_t cause)
-{
-	struct gsm_subscriber_connection *conn = msc_conn_ref;
-	return gsm0408_loc_upd_rej(conn, cause);
-}
-
-/* VLR asks us to transmit a CM Service Accept */
-static int msc_vlr_tx_cm_serv_acc(void *msc_conn_ref)
-{
-	struct gsm_subscriber_connection *conn = msc_conn_ref;
-	return msc_gsm48_tx_mm_serv_ack(conn);
-}
-
-static int msc_vlr_tx_common_id(void *msc_conn_ref)
-{
-	struct gsm_subscriber_connection *conn = msc_conn_ref;
-	return msc_tx_common_id(conn);
-}
-
-/* VLR asks us to transmit a CM Service Reject */
-static int msc_vlr_tx_cm_serv_rej(void *msc_conn_ref, enum vlr_proc_arq_result result)
-{
-	uint8_t cause;
-	struct gsm_subscriber_connection *conn = msc_conn_ref;
-	conn->received_cm_service_request = false;
-
-	switch (result) {
-	default:
-	case VLR_PR_ARQ_RES_NONE:
-	case VLR_PR_ARQ_RES_SYSTEM_FAILURE:
-	case VLR_PR_ARQ_RES_UNKNOWN_ERROR:
-		cause = GSM48_REJECT_NETWORK_FAILURE;
-		break;
-	case VLR_PR_ARQ_RES_ILLEGAL_SUBSCR:
-		cause = GSM48_REJECT_LOC_NOT_ALLOWED;
-		break;
-	case VLR_PR_ARQ_RES_UNIDENT_SUBSCR:
-		cause = GSM48_REJECT_INVALID_MANDANTORY_INF;
-		break;
-	case VLR_PR_ARQ_RES_ROAMING_NOTALLOWED:
-		cause = GSM48_REJECT_ROAMING_NOT_ALLOWED;
-		break;
-	case VLR_PR_ARQ_RES_ILLEGAL_EQUIP:
-		cause = GSM48_REJECT_ILLEGAL_MS;
-		break;
-	case VLR_PR_ARQ_RES_TIMEOUT:
-		cause = GSM48_REJECT_CONGESTION;
-		break;
-	};
-
-	return msc_gsm48_tx_mm_serv_rej(conn, cause);
-}
-
-/* VLR asks us to start using ciphering */
-static int msc_vlr_set_ciph_mode(void *msc_conn_ref,
-				 enum vlr_ciph ciph,
-				 bool retrieve_imeisv)
-{
-	struct gsm_subscriber_connection *conn = msc_conn_ref;
-	struct vlr_subscr *vsub;
-	struct gsm_auth_tuple *tuple;
-
-	if (!conn || !conn->vsub) {
-		LOGP(DMM, LOGL_ERROR, "Cannot send Ciphering Mode Command to"
-		     " NULL conn/subscriber");
-		return -EINVAL;
-	}
-
-	vsub = conn->vsub;
-	tuple = vsub->last_tuple;
-
-	if (!tuple) {
-		LOGP(DMM, LOGL_ERROR, "subscr %s: Cannot send Ciphering Mode"
-		     " Command: no auth tuple available\n",
-		     vlr_subscr_name(vsub));
-		return -EINVAL;
-	}
-
-	switch (conn->via_ran) {
-	case RAN_GERAN_A:
-		DEBUGP(DMM, "-> CIPHER MODE COMMAND %s\n",
-		       vlr_subscr_name(conn->vsub));
-		return a_iface_tx_cipher_mode(conn, ciph, tuple->vec.kc, 8,
-					      retrieve_imeisv);
-	case RAN_UTRAN_IU:
-#ifdef BUILD_IU
-		DEBUGP(DMM, "-> SECURITY MODE CONTROL %s\n",
-		       vlr_subscr_name(conn->vsub));
-		return ranap_iu_tx_sec_mode_cmd(conn->iu.ue_ctx, &tuple->vec, 0, 1);
-#else
-		LOGP(DMM, LOGL_ERROR, "Cannot send Security Mode Control over RAN_UTRAN_IU,"
-		     " built without Iu support\n");
-		return -ENOTSUP;
-#endif
-
-	default:
-		break;
-	}
-	LOGP(DMM, LOGL_ERROR,
-	     "%s: cannot start ciphering, unknown RAN type %d\n",
-	     vlr_subscr_name(conn->vsub), conn->via_ran);
-	return -ENOTSUP;
-}
-
-void msc_rx_sec_mode_compl(struct gsm_subscriber_connection *conn)
-{
-	struct vlr_ciph_result vlr_res = {};
-
-	if (!conn || !conn->vsub) {
-		LOGP(DMM, LOGL_ERROR,
-		     "Rx Security Mode Complete for invalid conn\n");
-		return;
-	}
-
-	DEBUGP(DMM, "<- SECURITY MODE COMPLETE %s\n",
-	       vlr_subscr_name(conn->vsub));
-
-	vlr_res.cause = VLR_CIPH_COMPL;
-	vlr_subscr_rx_ciph_res(conn->vsub, &vlr_res);
-}
-
-/* VLR informs us that the subscriber data has somehow been modified */
-static void msc_vlr_subscr_update(struct vlr_subscr *subscr)
-{
-	/* FIXME */
-}
-
-/* VLR informs us that the subscriber has been associated with a conn */
-static void msc_vlr_subscr_assoc(void *msc_conn_ref,
-				 struct vlr_subscr *vsub)
-{
-	struct gsm_subscriber_connection *conn = msc_conn_ref;
-	OSMO_ASSERT(!conn->vsub);
-	conn->vsub = vlr_subscr_get(vsub);
-	conn->vsub->cs.attached_via_ran = conn->via_ran;
-}
-
-/* operations that we need to implement for libvlr */
-static const struct vlr_ops msc_vlr_ops = {
-	.tx_auth_req = msc_vlr_tx_auth_req,
-	.tx_auth_rej = msc_vlr_tx_auth_rej,
-	.tx_id_req = msc_vlr_tx_id_req,
-	.tx_lu_acc = msc_vlr_tx_lu_acc,
-	.tx_lu_rej = msc_vlr_tx_lu_rej,
-	.tx_cm_serv_acc = msc_vlr_tx_cm_serv_acc,
-	.tx_cm_serv_rej = msc_vlr_tx_cm_serv_rej,
-	.set_ciph_mode = msc_vlr_set_ciph_mode,
-	.tx_common_id = msc_vlr_tx_common_id,
-	.subscr_update = msc_vlr_subscr_update,
-	.subscr_assoc = msc_vlr_subscr_assoc,
-};
-
-/* Allocate net->vlr so that the VTY may configure the VLR's data structures */
-int msc_vlr_alloc(struct gsm_network *net)
-{
-	net->vlr = vlr_alloc(net, &msc_vlr_ops);
-	if (!net->vlr)
-		return -ENOMEM;
-	net->vlr->user_ctx = net;
-	return 0;
-}
-
-/* Launch the VLR, i.e. its GSUP connection */
-int msc_vlr_start(struct gsm_network *net)
-{
-	OSMO_ASSERT(net->vlr);
-	return vlr_start("MSC", net->vlr, net->gsup_server_addr_str,
-			 net->gsup_server_port);
-}
diff --git a/src/libmsc/gsm_04_11.c b/src/libmsc/gsm_04_11.c
deleted file mode 100644
index c5bcce7..0000000
--- a/src/libmsc/gsm_04_11.c
+++ /dev/null
@@ -1,1187 +0,0 @@
-/* Point-to-Point (PP) Short Message Service (SMS)
- * Support on Mobile Radio Interface
- * 3GPP TS 04.11 version 7.1.0 Release 1998 / ETSI TS 100 942 V7.1.0 */
-
-/* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
- * (C) 2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010 by On-Waves
- * (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
- *
- * 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/>.
- *
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-#include <netinet/in.h>
-
-#include "bscconfig.h"
-
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/gsm/gsm0411_utils.h>
-#include <osmocom/gsm/protocol/gsm_04_11.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/db.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/signal.h>
-#include <openbsc/db.h>
-#include <openbsc/transaction.h>
-#include <openbsc/paging.h>
-#include <openbsc/bsc_rll.h>
-#include <openbsc/chan_alloc.h>
-#include <openbsc/msc_ifaces.h>
-#include <openbsc/osmo_msc.h>
-#include <openbsc/vlr.h>
-
-#ifdef BUILD_SMPP
-#include "smpp_smsc.h"
-#endif
-
-void *tall_gsms_ctx;
-static uint32_t new_callref = 0x40000001;
-
-
-struct gsm_sms *sms_alloc(void)
-{
-	return talloc_zero(tall_gsms_ctx, struct gsm_sms);
-}
-
-void sms_free(struct gsm_sms *sms)
-{
-	/* drop references to subscriber structure */
-	if (sms->receiver)
-		vlr_subscr_put(sms->receiver);
-#ifdef BUILD_SMPP
-	if (sms->smpp.esme)
-		smpp_esme_put(sms->smpp.esme);
-#endif
-
-	talloc_free(sms);
-}
-
-struct gsm_sms *sms_from_text(struct vlr_subscr *receiver,
-			      struct vlr_subscr *sender,
-                              int dcs, const char *text)
-{
-	struct gsm_sms *sms = sms_alloc();
-
-	if (!sms)
-		return NULL;
-
-	sms->receiver = vlr_subscr_get(receiver);
-	osmo_strlcpy(sms->text, text, sizeof(sms->text));
-
-	osmo_strlcpy(sms->src.addr, sender->msisdn, sizeof(sms->src.addr));
-	sms->reply_path_req = 0;
-	sms->status_rep_req = 0;
-	sms->ud_hdr_ind = 0;
-	sms->protocol_id = 0; /* implicit */
-	sms->data_coding_scheme = dcs;
-	osmo_strlcpy(sms->dst.addr, receiver->msisdn, sizeof(sms->dst.addr));
-	/* Generate user_data */
-	sms->user_data_len = gsm_7bit_encode_n(sms->user_data, sizeof(sms->user_data),
-						sms->text, NULL);
-
-	return sms;
-}
-
-
-static void send_signal(int sig_no,
-			struct gsm_trans *trans,
-			struct gsm_sms *sms,
-			int paging_result)
-{
-	struct sms_signal_data sig;
-	sig.trans = trans;
-	sig.sms = sms;
-	sig.paging_result = paging_result;
-	osmo_signal_dispatch(SS_SMS, sig_no, &sig);
-}
-
-static int gsm411_sendmsg(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	DEBUGP(DLSMS, "GSM4.11 TX %s\n", osmo_hexdump(msg->data, msg->len));
-	msg->l3h = msg->data;
-	return msc_tx_dtap(conn, msg);
-}
-
-/* Prefix msg with a 04.08/04.11 CP header */
-static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
-			     uint8_t msg_type)
-{
-	struct gsm48_hdr *gh;
-
-	gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
-	/* Outgoing needs the highest bit set */
-	gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
-	gh->msg_type = msg_type;
-
-	DEBUGP(DLSMS, "sending CP message (trans=%x)\n", trans->transaction_id);
-
-	return gsm411_sendmsg(trans->conn, msg);
-}
-
-/* mm_send: receive MMCCSMS sap message from SMC */
-static int gsm411_mm_send(struct gsm411_smc_inst *inst, int msg_type,
-			struct msgb *msg, int cp_msg_type)
-{
-	struct gsm_trans *trans =
-		container_of(inst, struct gsm_trans, sms.smc_inst);
-	int rc = 0;
-
-	switch (msg_type) {
-	case GSM411_MMSMS_EST_REQ:
-		/* recycle msg */
-		rc = gsm411_smc_recv(inst, GSM411_MMSMS_EST_CNF, msg, 0);
-		msgb_free(msg); /* upper layer does not free msg */
-		break;
-	case GSM411_MMSMS_DATA_REQ:
-		rc = gsm411_cp_sendmsg(msg, trans, cp_msg_type);
-		break;
-	case GSM411_MMSMS_REL_REQ:
-		DEBUGP(DLSMS, "Got MMSMS_REL_REQ, destroying transaction.\n");
-		msgb_free(msg);
-		trans_free(trans);
-		break;
-	default:
-		LOGP(DLSMS, LOGL_NOTICE, "Unhandled MMCCSMS msg 0x%x\n", msg_type);
-		msgb_free(msg);
-		rc = -EINVAL;
-	}
-
-	return rc;
-}
-
-/* mm_send: receive MNCCSMS sap message from SMR */
-int gsm411_mn_send(struct gsm411_smr_inst *inst, int msg_type,
-			struct msgb *msg)
-{
-	struct gsm_trans *trans =
-		container_of(inst, struct gsm_trans, sms.smr_inst);
-
-	/* forward to SMC */
-	return gsm411_smc_send(&trans->sms.smc_inst, msg_type, msg);
-}
-
-static int gsm340_rx_sms_submit(struct gsm_sms *gsms)
-{
-	if (db_sms_store(gsms) != 0) {
-		LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
-		return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
-	}
-	/* dispatch a signal to tell higher level about it */
-	send_signal(S_SMS_SUBMITTED, NULL, gsms, 0);
-
-	return 0;
-}
-
-/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
-static int gsm340_gen_oa_sub(uint8_t *oa, unsigned int oa_len,
-			 const struct gsm_sms_addr *src)
-{
-	/* network specific, private numbering plan */
-	return gsm340_gen_oa(oa, oa_len, src->ton, src->npi, src->addr);
-}
-
-/* generate a msgb containing an 03.40 9.2.2.1 SMS-DELIVER TPDU derived from
- * struct gsm_sms, returns total size of TPDU */
-static int gsm340_gen_sms_deliver_tpdu(struct msgb *msg, struct gsm_sms *sms)
-{
-	uint8_t *smsp;
-	uint8_t oa[12];	/* max len per 03.40 */
-	uint8_t octet_len;
-	unsigned int old_msg_len = msg->len;
-	int oa_len;
-
-	/* generate first octet with masked bits */
-	smsp = msgb_put(msg, 1);
-	/* TP-MTI (message type indicator) */
-	*smsp = GSM340_SMS_DELIVER_SC2MS;
-	/* TP-MMS (more messages to send) */
-	if (0 /* FIXME */)
-		*smsp |= 0x04;
-	/* TP-SRI(deliver)/SRR(submit) */
-	if (sms->status_rep_req)
-		*smsp |= 0x20;
-	/* TP-UDHI (indicating TP-UD contains a header) */
-	if (sms->ud_hdr_ind)
-		*smsp |= 0x40;
-
-	/* generate originator address */
-	oa_len = gsm340_gen_oa_sub(oa, sizeof(oa), &sms->src);
-	if (oa_len < 0)
-		return -ENOSPC;
-
-	smsp = msgb_put(msg, oa_len);
-	memcpy(smsp, oa, oa_len);
-
-	/* generate TP-PID */
-	smsp = msgb_put(msg, 1);
-	*smsp = sms->protocol_id;
-
-	/* generate TP-DCS */
-	smsp = msgb_put(msg, 1);
-	*smsp = sms->data_coding_scheme;
-
-	/* generate TP-SCTS */
-	smsp = msgb_put(msg, 7);
-	gsm340_gen_scts(smsp, time(NULL));
-
-	/* generate TP-UDL */
-	smsp = msgb_put(msg, 1);
-	*smsp = sms->user_data_len;
-
-	/* generate TP-UD */
-	switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
-	case DCS_7BIT_DEFAULT:
-		octet_len = sms->user_data_len*7/8;
-		if (sms->user_data_len*7%8 != 0)
-			octet_len++;
-		/* Warning, user_data_len indicates the amount of septets
-		 * (characters), we need amount of octets occupied */
-		smsp = msgb_put(msg, octet_len);
-		memcpy(smsp, sms->user_data, octet_len);
-		break;
-	case DCS_UCS2:
-	case DCS_8BIT_DATA:
-		smsp = msgb_put(msg, sms->user_data_len);
-		memcpy(smsp, sms->user_data, sms->user_data_len);
-		break;
-	default:
-		LOGP(DLSMS, LOGL_NOTICE, "Unhandled Data Coding Scheme: 0x%02X\n",
-		     sms->data_coding_scheme);
-		break;
-	}
-
-	return msg->len - old_msg_len;
-}
-
-/* As defined by GSM 03.40, Section 9.2.2.3. */
-static int gsm340_gen_sms_status_report_tpdu(struct msgb *msg,
-					     struct gsm_sms *sms)
-{
-	unsigned int old_msg_len = msg->len;
-	uint8_t oa[12];	/* max len per 03.40 */
-	uint8_t *smsp;
-	int oa_len;
-
-	/* generate first octet with masked bits */
-	smsp = msgb_put(msg, 1);
-	/* TP-MTI (message type indicator) */
-	*smsp = GSM340_SMS_STATUS_REP_SC2MS;
-	/* TP-MMS (more messages to send) */
-	if (0 /* FIXME */)
-		*smsp |= 0x04;
-	/* TP-MR (message reference) */
-	smsp = msgb_put(msg, 1);
-	*smsp = sms->msg_ref;
-
-	/* generate recipient address */
-	oa_len = gsm340_gen_oa_sub(oa, sizeof(oa), &sms->src);
-	if (oa_len < 0)
-		return -ENOSPC;
-
-	smsp = msgb_put(msg, oa_len);
-	memcpy(smsp, oa, oa_len);
-
-	/* generate TP-SCTS (Service centre timestamp) */
-	smsp = msgb_put(msg, 7);
-	gsm340_gen_scts(smsp, sms->created);
-
-	/* generate TP-DT (Discharge time, in TP-SCTS format). */
-	smsp = msgb_put(msg, 7);
-	gsm340_gen_scts(smsp, sms->created);
-
-	/* TP-ST (status) */
-	smsp = msgb_put(msg, 1);
-	/* From GSM 03.40, Section 9.2.3.15, 0x00 means OK. */
-	*smsp = 0x00;
-
-	LOGP(DLSMS, LOGL_INFO, "sending status report for SMS reference %x\n",
-	     sms->msg_ref);
-
-	return msg->len - old_msg_len;
-}
-
-static int sms_route_mt_sms(struct gsm_subscriber_connection *conn,
-			    struct gsm_sms *gsms)
-{
-	int rc;
-
-#ifdef BUILD_SMPP
-	int smpp_first = smpp_route_smpp_first(gsms, conn);
-
-	/*
-	 * Route through SMPP first before going to the local database. In case
-	 * of a unroutable message and no local subscriber, SMPP will be tried
-	 * twice. In case of an unknown subscriber continue with the normal
-	 * delivery of the SMS.
-	 */
-	if (smpp_first) {
-		rc = smpp_try_deliver(gsms, conn);
-		if (rc == GSM411_RP_CAUSE_MO_NUM_UNASSIGNED)
-			/* unknown subscriber, try local */
-			goto try_local;
-		if (rc < 0) {
-	 		LOGP(DLSMS, LOGL_ERROR, "%s: SMS delivery error: %d.",
-			     vlr_subscr_name(conn->vsub), rc);
-	 		rc = GSM411_RP_CAUSE_MO_TEMP_FAIL;
-			/* rc will be logged by gsm411_send_rp_error() */
-	 		rate_ctr_inc(&conn->bts->network->msc_ctrs->ctr[
-					MSC_CTR_SMS_DELIVER_UNKNOWN_ERROR]);
-		}
-		return rc;
-	}
-
-try_local:
-#endif
-
-	/* determine gsms->receiver based on dialled number */
-	gsms->receiver = vlr_subscr_find_by_msisdn(conn->network->vlr,
-						   gsms->dst.addr);
-	if (!gsms->receiver) {
-#ifdef BUILD_SMPP
-		/* Avoid a second look-up */
-		if (smpp_first) {
-			rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER]);
-			return GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
-		}
-
-		rc = smpp_try_deliver(gsms, conn);
-		if (rc == GSM411_RP_CAUSE_MO_NUM_UNASSIGNED) {
-			rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER]);
-		} else if (rc < 0) {
-	 		LOGP(DLSMS, LOGL_ERROR, "%s: SMS delivery error: %d.",
-			     vlr_subscr_name(conn->vsub), rc);
-	 		rc = GSM411_RP_CAUSE_MO_TEMP_FAIL;
-			/* rc will be logged by gsm411_send_rp_error() */
-	 		rate_ctr_inc(&conn->bts->network->msc_ctrs->ctr[
-					MSC_CTR_SMS_DELIVER_UNKNOWN_ERROR]);
-		}
-#else
-		rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
-		rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER]);
-#endif
-	}
-
-	return rc;
-}
-
-
-/* process an incoming TPDU (called from RP-DATA)
- * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
-static int gsm340_rx_tpdu(struct gsm_trans *trans, struct msgb *msg,
-			  uint32_t gsm411_msg_ref)
-{
-	struct gsm_subscriber_connection *conn = trans->conn;
-	uint8_t *smsp = msgb_sms(msg);
-	struct gsm_sms *gsms;
-	unsigned int sms_alphabet;
-	uint8_t sms_mti, sms_vpf;
-	uint8_t *sms_vp;
-	uint8_t da_len_bytes;
-	uint8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
-	int rc = 0;
-
-	rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED]);
-
-	gsms = sms_alloc();
-	if (!gsms)
-		return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
-
-	/* invert those fields where 0 means active/present */
-	sms_mti = *smsp & 0x03;
-	sms_vpf = (*smsp & 0x18) >> 3;
-	gsms->status_rep_req = (*smsp & 0x20) >> 5;
-	gsms->ud_hdr_ind = (*smsp & 0x40);
-	/*
-	 * Not evaluating MMS (More Messages to Send) because the
-	 * lchan stays open anyway.
-	 * Not evaluating RP (Reply Path) because we're not aware of its
-	 * benefits.
-	 */
-
-	smsp++;
-	gsms->msg_ref = *smsp++;
-
-	gsms->gsm411.transaction_id = trans->transaction_id;
-	gsms->gsm411.msg_ref = gsm411_msg_ref;
-
-	/* length in bytes of the destination address */
-	da_len_bytes = 2 + *smsp/2 + *smsp%2;
-	if (da_len_bytes > 12) {
-		LOGP(DLSMS, LOGL_ERROR, "Destination Address > 12 bytes ?!?\n");
-		rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
-		goto out;
-	} else if (da_len_bytes < 4) {
-		LOGP(DLSMS, LOGL_ERROR, "Destination Address < 4 bytes ?!?\n");
-		rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
-		goto out;
-	}
-	memset(address_lv, 0, sizeof(address_lv));
-	memcpy(address_lv, smsp, da_len_bytes);
-	/* mangle first byte to reflect length in bytes, not digits */
-	address_lv[0] = da_len_bytes - 1;
-
-	gsms->dst.ton = (address_lv[1] >> 4) & 7;
-	gsms->dst.npi = address_lv[1] & 0xF;
-	/* convert to real number */
-	gsm48_decode_bcd_number(gsms->dst.addr,
-				sizeof(gsms->dst.addr), address_lv, 1);
-	smsp += da_len_bytes;
-
-	gsms->protocol_id = *smsp++;
-	gsms->data_coding_scheme = *smsp++;
-
-	sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
-	if (sms_alphabet == 0xffffffff) {
-		rc = GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
-		goto out;
-	}
-
-	switch (sms_vpf) {
-	case GSM340_TP_VPF_RELATIVE:
-		sms_vp = smsp++;
-		break;
-	case GSM340_TP_VPF_ABSOLUTE:
-	case GSM340_TP_VPF_ENHANCED:
-		sms_vp = smsp;
-		/* the additional functionality indicator... */
-		if (sms_vpf == GSM340_TP_VPF_ENHANCED && *smsp & (1<<7))
-			smsp++;
-		smsp += 7;
-		break;
-	case GSM340_TP_VPF_NONE:
-		sms_vp = 0;
-		break;
-	default:
-		LOGP(DLSMS, LOGL_NOTICE,
-		     "SMS Validity period not implemented: 0x%02x\n", sms_vpf);
-		rc = GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
-		goto out;
-	}
-	gsms->user_data_len = *smsp++;
-	if (gsms->user_data_len) {
-		memcpy(gsms->user_data, smsp, gsms->user_data_len);
-
-		switch (sms_alphabet) {
-		case DCS_7BIT_DEFAULT:
-			gsm_7bit_decode_n(gsms->text, sizeof(gsms->text), smsp,
-					  gsms->user_data_len);
-			break;
-		case DCS_8BIT_DATA:
-		case DCS_UCS2:
-		case DCS_NONE:
-			break;
-		}
-	}
-
-	osmo_strlcpy(gsms->src.addr, conn->vsub->msisdn, sizeof(gsms->src.addr));
-
-	LOGP(DLSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, "
-	     "MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, "
-	     "UserDataLength: 0x%02x, UserData: \"%s\"\n",
-	     vlr_subscr_name(conn->vsub), sms_mti, sms_vpf, gsms->msg_ref,
-	     gsms->protocol_id, gsms->data_coding_scheme, gsms->dst.addr,
-	     gsms->user_data_len,
-			sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
-				osmo_hexdump(gsms->user_data, gsms->user_data_len));
-
-	gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
-
-	/* FIXME: This looks very wrong */
-	send_signal(0, NULL, gsms, 0);
-
-	rc = sms_route_mt_sms(conn, gsms);
-
-	/* This SMS got routed through SMPP or no receiver exists. */
-	if (!gsms->receiver)
-		return rc;
-
-	switch (sms_mti) {
-	case GSM340_SMS_SUBMIT_MS2SC:
-		/* MS is submitting a SMS */
-		rc = gsm340_rx_sms_submit(gsms);
-		break;
-	case GSM340_SMS_COMMAND_MS2SC:
-	case GSM340_SMS_DELIVER_REP_MS2SC:
-		LOGP(DLSMS, LOGL_NOTICE, "Unimplemented MTI 0x%02x\n", sms_mti);
-		rc = GSM411_RP_CAUSE_IE_NOTEXIST;
-		break;
-	default:
-		LOGP(DLSMS, LOGL_NOTICE, "Undefined MTI 0x%02x\n", sms_mti);
-		rc = GSM411_RP_CAUSE_IE_NOTEXIST;
-		break;
-	}
-out:
-	sms_free(gsms);
-
-	return rc;
-}
-
-/* Prefix msg with a RP-DATA header and send as SMR DATA */
-static int gsm411_rp_sendmsg(struct gsm411_smr_inst *inst, struct msgb *msg,
-			     uint8_t rp_msg_type, uint8_t rp_msg_ref,
-			     int rl_msg_type)
-{
-	struct gsm411_rp_hdr *rp;
-	uint8_t len = msg->len;
-
-	/* GSM 04.11 RP-DATA header */
-	rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
-	rp->len = len + 2;
-	rp->msg_type = rp_msg_type;
-	rp->msg_ref = rp_msg_ref;
-
-	return gsm411_smr_send(inst, rl_msg_type, msg);
-}
-
-int gsm411_send_rp_ack(struct gsm_trans *trans, uint8_t msg_ref)
-{
-	struct msgb *msg = gsm411_msgb_alloc();
-
-	DEBUGP(DLSMS, "TX: SMS RP ACK\n");
-
-	return gsm411_rp_sendmsg(&trans->sms.smr_inst, msg, GSM411_MT_RP_ACK_MT,
-		msg_ref, GSM411_SM_RL_REPORT_REQ);
-}
-
-int gsm411_send_rp_error(struct gsm_trans *trans, uint8_t msg_ref,
-			 uint8_t cause)
-{
-	struct msgb *msg = gsm411_msgb_alloc();
-
-	msgb_tv_put(msg, 1, cause);
-
-	LOGP(DLSMS, LOGL_NOTICE, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
-		get_value_string(gsm411_rp_cause_strs, cause));
-
-	return gsm411_rp_sendmsg(&trans->sms.smr_inst, msg,
-		GSM411_MT_RP_ERROR_MT, msg_ref, GSM411_SM_RL_REPORT_REQ);
-}
-
-/* Receive a 04.11 TPDU inside RP-DATA / user data */
-static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
-			  struct gsm411_rp_hdr *rph,
-			  uint8_t src_len, uint8_t *src,
-			  uint8_t dst_len, uint8_t *dst,
-			  uint8_t tpdu_len, uint8_t *tpdu)
-{
-	int rc = 0;
-
-	if (src_len && src)
-		LOGP(DLSMS, LOGL_ERROR, "RP-DATA (MO) with SRC ?!?\n");
-
-	if (!dst_len || !dst || !tpdu_len || !tpdu) {
-		LOGP(DLSMS, LOGL_ERROR,
-			"RP-DATA (MO) without DST or TPDU ?!?\n");
-		gsm411_send_rp_error(trans, rph->msg_ref,
-				     GSM411_RP_CAUSE_INV_MAND_INF);
-		return -EIO;
-	}
-	msg->l4h = tpdu;
-
-	DEBUGP(DLSMS, "DST(%u,%s)\n", dst_len, osmo_hexdump(dst, dst_len));
-
-	rc = gsm340_rx_tpdu(trans, msg, rph->msg_ref);
-	if (rc == 0)
-		return gsm411_send_rp_ack(trans, rph->msg_ref);
-	else if (rc > 0)
-		return gsm411_send_rp_error(trans, rph->msg_ref, rc);
-	else
-		return rc;
-}
-
-/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
-static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
-			     struct gsm411_rp_hdr *rph)
-{
-	uint8_t src_len, dst_len, rpud_len;
-	uint8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
-
-	/* in the MO case, this should always be zero length */
-	src_len = rph->data[0];
-	if (src_len)
-		src = &rph->data[1];
-
-	dst_len = rph->data[1+src_len];
-	if (dst_len)
-		dst = &rph->data[1+src_len+1];
-
-	rpud_len = rph->data[1+src_len+1+dst_len];
-	if (rpud_len)
-		rp_ud = &rph->data[1+src_len+1+dst_len+1];
-
-	DEBUGP(DLSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
-		src_len, dst_len, rpud_len);
-	return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
-				rpud_len, rp_ud);
-}
-
-static struct gsm_sms *sms_report_alloc(struct gsm_sms *sms)
-{
-	struct gsm_sms *sms_report;
-	int len;
-
-	sms_report = sms_alloc();
-	OSMO_ASSERT(sms_report);
-
-	sms_report->msg_ref = sms->msg_ref;
-	sms_report->protocol_id = sms->protocol_id;
-	sms_report->data_coding_scheme = GSM338_DCS_1111_8BIT_DATA;
-
-	/* Invert address to send status report back to origin. */
-	sms_report->src = sms->dst;
-	sms_report->dst = sms->src;
-
-	/* As specified by Appendix B. Delivery Receipt Format.
-	 * TODO: Many fields in this string are just set with dummy values,
-	 * 	 revisit this.
-	 */
-	len = snprintf((char *)sms_report->user_data,
-		       sizeof(sms_report->user_data),
-		       "id:%.08llu sub:000 dlvrd:000 submit date:YYMMDDhhmm done date:YYMMDDhhmm stat:DELIVRD err:000 text:%.20s",
-		       sms->id, sms->text);
-	sms_report->user_data_len = len;
-	LOGP(DLSMS, LOGL_NOTICE, "%s\n", sms_report->user_data);
-
-	/* This represents a sms report. */
-	sms_report->is_report = true;
-
-	return sms_report;
-}
-
-static void sms_status_report(struct gsm_sms *gsms,
-			      struct gsm_subscriber_connection *conn)
-{
-	struct gsm_sms *sms_report;
-	int rc;
-
-	sms_report = sms_report_alloc(gsms);
-
-	rc = sms_route_mt_sms(conn, sms_report);
-	if (rc < 0) {
-		LOGP(DLSMS, LOGL_ERROR,
-		     "Failed to send status report! err=%d\n", rc);
-	}
-
-	/* No route via SMPP, send the GSM 03.40 status-report now. */
-	if (gsms->receiver)
-		gsm340_rx_sms_submit(sms_report);
-
-	LOGP(DLSMS, LOGL_NOTICE, "Status report has been sent\n");
-
-	sms_free(sms_report);
-}
-
-/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
-static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
-			    struct gsm411_rp_hdr *rph)
-{
-	struct gsm_sms *sms = trans->sms.sms;
-
-	/* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
-	 * successfully received a SMS.  We can now safely mark it as
-	 * transmitted */
-
-	if (!sms) {
-		LOGP(DLSMS, LOGL_ERROR, "RX RP-ACK but no sms in transaction?!?\n");
-		return gsm411_send_rp_error(trans, rph->msg_ref,
-					    GSM411_RP_CAUSE_PROTOCOL_ERR);
-	}
-
-	/* mark this SMS as sent in database */
-	db_sms_mark_delivered(sms);
-
-	send_signal(S_SMS_DELIVERED, trans, sms, 0);
-
-	if (sms->status_rep_req)
-		sms_status_report(sms, trans->conn);
-
-	sms_free(sms);
-	trans->sms.sms = NULL;
-
-	return 0;
-}
-
-static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
-			      struct gsm411_rp_hdr *rph)
-{
-	struct gsm_network *net = trans->conn->network;
-	struct gsm_sms *sms = trans->sms.sms;
-	uint8_t cause_len = rph->data[0];
-	uint8_t cause = rph->data[1];
-
-	/* Error in response to MT RP_DATA, i.e. the MS did not
-	 * successfully receive the SMS.  We need to investigate
-	 * the cause and take action depending on it */
-
-	LOGP(DLSMS, LOGL_NOTICE, "%s: RX SMS RP-ERROR, cause %d:%d (%s)\n",
-	     vlr_subscr_name(trans->conn->vsub), cause_len, cause,
-	     get_value_string(gsm411_rp_cause_strs, cause));
-
-	if (!sms) {
-		LOGP(DLSMS, LOGL_ERROR,
-			"RX RP-ERR, but no sms in transaction?!?\n");
-		return -EINVAL;
-#if 0
-		return gsm411_send_rp_error(trans, rph->msg_ref,
-					    GSM411_RP_CAUSE_PROTOCOL_ERR);
-#endif
-	}
-
-	if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
-		/* MS has not enough memory to store the message.  We need
-		 * to store this in our database and wait for a SMMA message */
-		/* FIXME */
-		send_signal(S_SMS_MEM_EXCEEDED, trans, sms, 0);
-		rate_ctr_inc(&net->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM]);
-	} else {
-		send_signal(S_SMS_UNKNOWN_ERROR, trans, sms, 0);
-		rate_ctr_inc(&net->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER]);
-	}
-
-	sms_free(sms);
-	trans->sms.sms = NULL;
-
-	return 0;
-}
-
-static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
-			     struct gsm411_rp_hdr *rph)
-{
-	int rc;
-
-	rc = gsm411_send_rp_ack(trans, rph->msg_ref);
-
-	/* MS tells us that it has memory for more SMS, we need
-	 * to check if we have any pending messages for it and then
-	 * transfer those */
-	send_signal(S_SMS_SMMA, trans, NULL, 0);
-
-	return rc;
-}
-
-/* receive RL DATA */
-static int gsm411_rx_rl_data(struct msgb *msg, struct gsm48_hdr *gh,
-			     struct gsm_trans *trans)
-{
-	struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
-	uint8_t msg_type =  rp_data->msg_type & 0x07;
-	int rc = 0;
-
-	switch (msg_type) {
-	case GSM411_MT_RP_DATA_MO:
-		DEBUGP(DLSMS, "RX SMS RP-DATA (MO)\n");
-		rc = gsm411_rx_rp_data(msg, trans, rp_data);
-		break;
-	case GSM411_MT_RP_SMMA_MO:
-		DEBUGP(DLSMS, "RX SMS RP-SMMA\n");
-		rc = gsm411_rx_rp_smma(msg, trans, rp_data);
-		break;
-	default:
-		LOGP(DLSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
-		rc = -EINVAL;
-		break;
-	}
-
-	return rc;
-}
-
-/* receive RL REPORT */
-static int gsm411_rx_rl_report(struct msgb *msg, struct gsm48_hdr *gh,
-			     struct gsm_trans *trans)
-{
-	struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
-	uint8_t msg_type =  rp_data->msg_type & 0x07;
-	int rc = 0;
-
-	switch (msg_type) {
-	case GSM411_MT_RP_ACK_MO:
-		DEBUGP(DLSMS, "RX SMS RP-ACK (MO)\n");
-		rc = gsm411_rx_rp_ack(msg, trans, rp_data);
-		break;
-	case GSM411_MT_RP_ERROR_MO:
-		DEBUGP(DLSMS, "RX SMS RP-ERROR (MO)\n");
-		rc = gsm411_rx_rp_error(msg, trans, rp_data);
-		break;
-	default:
-		LOGP(DLSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
-		rc = -EINVAL;
-		break;
-	}
-
-	return rc;
-}
-
-/* receive SM-RL sap message from SMR
- * NOTE: Message is freed by sender
- */
-int gsm411_rl_recv(struct gsm411_smr_inst *inst, int msg_type,
-                        struct msgb *msg)
-{
-	struct gsm_trans *trans =
-		container_of(inst, struct gsm_trans, sms.smr_inst);
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	int rc = 0;
-
-	switch (msg_type) {
-	case GSM411_SM_RL_DATA_IND:
-		rc = gsm411_rx_rl_data(msg, gh, trans);
-		break;
-	case GSM411_SM_RL_REPORT_IND:
-		if (gh)
-			rc = gsm411_rx_rl_report(msg, gh, trans);
-		break;
-	default:
-		LOGP(DLSMS, LOGL_NOTICE, "Unhandled SM-RL message 0x%x\n", msg_type);
-		rc = -EINVAL;
-	}
-
-	return rc;
-}
-
-/* receive MNCCSMS sap message from SMC
- * NOTE: Message is freed by sender
- */
-static int gsm411_mn_recv(struct gsm411_smc_inst *inst, int msg_type,
-			struct msgb *msg)
-{
-	struct gsm_trans *trans =
-		container_of(inst, struct gsm_trans, sms.smc_inst);
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	int rc = 0;
-
-	switch (msg_type) {
-	case GSM411_MNSMS_EST_IND:
-	case GSM411_MNSMS_DATA_IND:
-		DEBUGP(DLSMS, "MNSMS-DATA/EST-IND\n");
-		rc = gsm411_smr_recv(&trans->sms.smr_inst, msg_type, msg);
-		break;
-	case GSM411_MNSMS_ERROR_IND:
-		if (gh)
-			DEBUGP(DLSMS, "MNSMS-ERROR-IND, cause %d (%s)\n",
-				gh->data[0],
-				get_value_string(gsm411_cp_cause_strs,
-				gh->data[0]));
-		else
-			DEBUGP(DLSMS, "MNSMS-ERROR-IND, no cause\n");
-		rc = gsm411_smr_recv(&trans->sms.smr_inst, msg_type, msg);
-		break;
-	default:
-		LOGP(DLSMS, LOGL_NOTICE, "Unhandled MNCCSMS msg 0x%x\n", msg_type);
-		rc = -EINVAL;
-	}
-
-	return rc;
-}
-
-/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
-int gsm0411_rcv_sms(struct gsm_subscriber_connection *conn,
-		    struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	uint8_t msg_type = gh->msg_type;
-	uint8_t transaction_id = gsm48_hdr_trans_id_flip_ti(gh);
-	struct gsm_trans *trans;
-	int new_trans = 0;
-	int rc = 0;
-
-	if (!conn->vsub)
-		return -EIO;
-		/* FIXME: send some error message */
-
-	DEBUGP(DLSMS, "receiving data (trans_id=%x)\n", transaction_id);
-	trans = trans_find_by_id(conn, GSM48_PDISC_SMS, transaction_id);
-
-	/*
-	 * A transaction we created but don't know about?
-	 */
-	if (!trans && (transaction_id & 0x8) == 0) {
-		LOGP(DLSMS, LOGL_ERROR, "trans_id=%x allocated by us but known "
-			"to us anymore. We are ignoring it, maybe a CP-ERROR "
-			"from a MS?\n",
-			transaction_id);
-		return -EINVAL;
-	}
-
-	if (!trans) {
-		DEBUGP(DLSMS, " -> (new transaction)\n");
-		trans = trans_alloc(conn->network, conn->vsub,
-				    GSM48_PDISC_SMS,
-				    transaction_id, new_callref++);
-		if (!trans) {
-			DEBUGP(DLSMS, " -> No memory for trans\n");
-			/* FIXME: send some error message */
-			return -ENOMEM;
-		}
-		gsm411_smc_init(&trans->sms.smc_inst, 0, 1,
-			gsm411_mn_recv, gsm411_mm_send);
-		gsm411_smr_init(&trans->sms.smr_inst, 0, 1,
-			gsm411_rl_recv, gsm411_mn_send);
-
-		trans->conn = msc_subscr_conn_get(conn);
-
-		new_trans = 1;
-		cm_service_request_concludes(conn, msg);
-	}
-
-	/* 5.4: For MO, if a CP-DATA is received for a new
-	 * transaction, equals reception of an implicit
-	 * last CP-ACK for previous transaction */
-	if (trans->sms.smc_inst.cp_state == GSM411_CPS_IDLE
-	 && msg_type == GSM411_MT_CP_DATA) {
-		int i;
-		struct gsm_trans *ptrans;
-
-		/* Scan through all remote initiated transactions */
-		for (i=8; i<15; i++) {
-			if (i == transaction_id)
-				continue;
-
-			ptrans = trans_find_by_id(conn, GSM48_PDISC_SMS, i);
-			if (!ptrans)
-				continue;
-
-			DEBUGP(DLSMS, "Implicit CP-ACK for trans_id=%x\n", i);
-
-			/* Finish it for good */
-			trans_free(ptrans);
-		}
-	}
-
-	msc_subscr_conn_communicating(conn);
-
-	gsm411_smc_recv(&trans->sms.smc_inst,
-		(new_trans) ? GSM411_MMSMS_EST_IND : GSM411_MMSMS_DATA_IND,
-		msg, msg_type);
-
-	return rc;
-}
-
-/* Take a SMS in gsm_sms structure and send it through an already
- * existing conn. We also assume that the caller ensured this conn already
- * has a SAPI3 RLL connection! */
-int gsm411_send_sms(struct gsm_subscriber_connection *conn, struct gsm_sms *sms)
-{
-	struct msgb *msg = gsm411_msgb_alloc();
-	struct gsm_trans *trans;
-	uint8_t *data, *rp_ud_len;
-	uint8_t msg_ref = sms_next_rp_msg_ref(&conn->next_rp_ref);
-	int transaction_id;
-	int rc;
-
-	transaction_id =
-		trans_assign_trans_id(conn->network, conn->vsub,
-				      GSM48_PDISC_SMS, 0);
-	if (transaction_id == -1) {
-		LOGP(DLSMS, LOGL_ERROR, "No available transaction ids\n");
-		send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, 0);
-		sms_free(sms);
-		msgb_free(msg);
-		return -EBUSY;
-	}
-
-	DEBUGP(DLSMS, "%s()\n", __func__);
-
-	/* FIXME: allocate transaction with message reference */
-	trans = trans_alloc(conn->network, conn->vsub,
-			    GSM48_PDISC_SMS,
-			    transaction_id, new_callref++);
-	if (!trans) {
-		LOGP(DLSMS, LOGL_ERROR, "No memory for trans\n");
-		send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, 0);
-		sms_free(sms);
-		msgb_free(msg);
-		/* FIXME: send some error message */
-		return -ENOMEM;
-	}
-	gsm411_smc_init(&trans->sms.smc_inst, sms->id, 1,
-		gsm411_mn_recv, gsm411_mm_send);
-	gsm411_smr_init(&trans->sms.smr_inst, sms->id, 1,
-		gsm411_rl_recv, gsm411_mn_send);
-	trans->sms.sms = sms;
-
-	trans->conn = msc_subscr_conn_get(conn);
-
-	/* Hardcode SMSC Originating Address for now */
-	data = (uint8_t *)msgb_put(msg, 8);
-	data[0] = 0x07;	/* originator length == 7 */
-	data[1] = 0x91; /* type of number: international, ISDN */
-	data[2] = 0x44; /* 447785016005 */
-	data[3] = 0x77;
-	data[4] = 0x58;
-	data[5] = 0x10;
-	data[6] = 0x06;
-	data[7] = 0x50;
-
-	/* Hardcoded Destination Address */
-	data = (uint8_t *)msgb_put(msg, 1);
-	data[0] = 0;	/* destination length == 0 */
-
-	/* obtain a pointer for the rp_ud_len, so we can fill it later */
-	rp_ud_len = (uint8_t *)msgb_put(msg, 1);
-
-	if (sms->is_report) {
-		/* generate the 03.40 SMS-STATUS-REPORT TPDU */
-		rc = gsm340_gen_sms_status_report_tpdu(msg, sms);
-	} else {
-		/* generate the 03.40 SMS-DELIVER TPDU */
-		rc = gsm340_gen_sms_deliver_tpdu(msg, sms);
-	}
-	if (rc < 0) {
-		send_signal(S_SMS_UNKNOWN_ERROR, trans, sms, 0);
-		sms_free(sms);
-		trans->sms.sms = NULL;
-		trans_free(trans);
-		msgb_free(msg);
-		return rc;
-	}
-
-	*rp_ud_len = rc;
-
-	DEBUGP(DLSMS, "TX: SMS DELIVER\n");
-
-	rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED]);
-	db_sms_inc_deliver_attempts(trans->sms.sms);
-
-	return gsm411_rp_sendmsg(&trans->sms.smr_inst, msg,
-		GSM411_MT_RP_DATA_MT, msg_ref, GSM411_SM_RL_DATA_REQ);
-}
-
-/* paging callback. Here we get called if paging a subscriber has
- * succeeded or failed. */
-static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
-			      struct msgb *msg, void *_conn, void *_sms)
-{
-	struct gsm_subscriber_connection *conn = _conn;
-	struct gsm_sms *sms = _sms;
-	int rc = 0;
-
-	DEBUGP(DLSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
-		"conn=%p, sms=%p/id: %llu)\n", hooknum, event, msg, conn, sms, sms->id);
-
-	if (hooknum != GSM_HOOK_RR_PAGING)
-		return -EINVAL;
-
-	switch (event) {
-	case GSM_PAGING_SUCCEEDED:
-		gsm411_send_sms(conn, sms);
-		break;
-	case GSM_PAGING_EXPIRED:
-	case GSM_PAGING_OOM:
-	case GSM_PAGING_BUSY:
-		send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, event);
-		sms_free(sms);
-		rc = -ETIMEDOUT;
-		break;
-	default:
-		LOGP(DLSMS, LOGL_ERROR, "Unhandled paging event: %d\n", event);
-	}
-
-	return rc;
-}
-
-/* high-level function to send a SMS to a given subscriber. The function
- * will take care of paging the subscriber, establishing the RLL SAPI3
- * connection, etc. */
-int gsm411_send_sms_subscr(struct vlr_subscr *vsub,
-			   struct gsm_sms *sms)
-{
-	struct gsm_subscriber_connection *conn;
-	void *res;
-
-	/* check if we already have an open conn to the subscriber.
-	 * if yes, send the SMS this way */
-	conn = connection_for_subscr(vsub);
-	if (conn) {
-		LOGP(DLSMS, LOGL_DEBUG, "Sending SMS via already open connection %p to %s\n",
-		     conn, vlr_subscr_name(vsub));
-		return gsm411_send_sms(conn, sms);
-	}
-
-	/* if not, we have to start paging */
-	LOGP(DLSMS, LOGL_DEBUG, "Sending SMS: no connection open, start paging %s\n",
-	     vlr_subscr_name(vsub));
-	res = subscr_request_conn(vsub, paging_cb_send_sms, sms, "send SMS");
-	if (!res) {
-		send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, GSM_PAGING_BUSY);
-		sms_free(sms);
-	}
-	return 0;
-}
-
-void _gsm411_sms_trans_free(struct gsm_trans *trans)
-{
-	/* cleanup SMS instance */
-	gsm411_smr_clear(&trans->sms.smr_inst);
-	trans->sms.smr_inst.rl_recv = NULL;
-	trans->sms.smr_inst.mn_send = NULL;
-
-	gsm411_smc_clear(&trans->sms.smc_inst);
-	trans->sms.smc_inst.mn_recv = NULL;
-	trans->sms.smc_inst.mm_send = NULL;
-
-	if (trans->sms.sms) {
-		LOGP(DLSMS, LOGL_ERROR, "Transaction contains SMS.\n");
-		send_signal(S_SMS_UNKNOWN_ERROR, trans, trans->sms.sms, 0);
-		sms_free(trans->sms.sms);
-		trans->sms.sms = NULL;
-	}
-}
-
-/* Process incoming SAPI N-REJECT from BSC */
-void gsm411_sapi_n_reject(struct gsm_subscriber_connection *conn)
-{
-	struct gsm_network *net;
-	struct gsm_trans *trans, *tmp;
-
-	net = conn->network;
-
-	llist_for_each_entry_safe(trans, tmp, &net->trans_list, entry) {
-		struct gsm_sms *sms;
-
-		if (trans->conn != conn)
-			continue;
-		if (trans->protocol != GSM48_PDISC_SMS)
-			continue;
-
-		sms = trans->sms.sms;
-		if (!sms) {
-			LOGP(DLSMS, LOGL_ERROR, "SAPI Reject but no SMS.\n");
-			continue;
-		}
-
-		send_signal(S_SMS_UNKNOWN_ERROR, trans, sms, 0);
-		sms_free(sms);
-		trans->sms.sms = NULL;
-		trans_free(trans);
-	}
-}
-
diff --git a/src/libmsc/gsm_04_80.c b/src/libmsc/gsm_04_80.c
deleted file mode 100644
index bec1d26..0000000
--- a/src/libmsc/gsm_04_80.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
- * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
-
-/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2008, 2009, 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009 by Mike Haben <michael.haben@btinternet.com>
- *
- * 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/>.
- *
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/gsm_04_80.h>
-#include <openbsc/msc_ifaces.h>
-
-#include <osmocom/gsm/gsm0480.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/gsm/tlv.h>
-
-static inline unsigned char *msgb_wrap_with_TL(struct msgb *msgb, uint8_t tag)
-{
-	uint8_t *data = msgb_push(msgb, 2);
-
-	data[0] = tag;
-	data[1] = msgb->len - 2;
-	return data;
-}
-
-static inline unsigned char *msgb_push_TLV1(struct msgb *msgb, uint8_t tag,
-					    uint8_t value)
-{
-	uint8_t *data = msgb_push(msgb, 3);
-
-	data[0] = tag;
-	data[1] = 1;
-	data[2] = value;
-	return data;
-}
-
-
-/* Send response to a mobile-originated ProcessUnstructuredSS-Request */
-int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn,
-			       const struct msgb *in_msg, const char *response_text,
-			       const struct ss_request *req)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 USSD RSP");
-	struct gsm48_hdr *gh;
-	uint8_t *ptr8;
-	int response_len;
-
-	/* First put the payload text into the message */
-	ptr8 = msgb_put(msg, 0);
-	gsm_7bit_encode_n_ussd(ptr8, msgb_tailroom(msg), response_text, &response_len);
-	msgb_put(msg, response_len);
-
-	/* Then wrap it as an Octet String */
-	msgb_wrap_with_TL(msg, ASN1_OCTET_STRING_TAG);
-
-	/* Pre-pend the DCS octet string */
-	msgb_push_TLV1(msg, ASN1_OCTET_STRING_TAG, 0x0F);
-
-	/* Then wrap these as a Sequence */
-	msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG);
-
-	/* Pre-pend the operation code */
-	msgb_push_TLV1(msg, GSM0480_OPERATION_CODE,
-			GSM0480_OP_CODE_PROCESS_USS_REQ);
-
-	/* Wrap the operation code and IA5 string as a sequence */
-	msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG);
-
-	/* Pre-pend the invoke ID */
-	msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id);
-
-	/* Wrap this up as a Return Result component */
-	msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_RESULT);
-
-	/* Wrap the component in a Facility message */
-	msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY);
-
-	/* And finally pre-pend the L3 header */
-	gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
-	gh->proto_discr = GSM48_PDISC_NC_SS | req->transaction_id
-					| (1<<7);  /* TI direction = 1 */
-	gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE;
-
-	return msc_tx_dtap(conn, msg);
-}
-
-int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn,
-			     const struct msgb *in_msg,
-			     const struct ss_request *req)
-{
-	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 USSD REJ");
-	struct gsm48_hdr *gh;
-
-	/* First insert the problem code */
-	msgb_push_TLV1(msg, GSM_0480_PROBLEM_CODE_TAG_GENERAL,
-			GSM_0480_GEN_PROB_CODE_UNRECOGNISED);
-
-	/* Before it insert the invoke ID */
-	msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id);
-
-	/* Wrap this up as a Reject component */
-	msgb_wrap_with_TL(msg, GSM0480_CTYPE_REJECT);
-
-	/* Wrap the component in a Facility message */
-	msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY);
-
-	/* And finally pre-pend the L3 header */
-	gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
-	gh->proto_discr = GSM48_PDISC_NC_SS;
-	gh->proto_discr |= req->transaction_id | (1<<7);  /* TI direction = 1 */
-	gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE;
-
-	return msc_tx_dtap(conn, msg);
-}
-
-int msc_send_ussd_notify(struct gsm_subscriber_connection *conn, int level, const char *text)
-{
-	struct msgb *msg = gsm0480_create_ussd_notify(level, text);
-	if (!msg)
-		return -1;
-	return msc_tx_dtap(conn, msg);
-}
-
-int msc_send_ussd_release_complete(struct gsm_subscriber_connection *conn)
-{
-	struct msgb *msg = gsm0480_create_ussd_release_complete();
-	if (!msg)
-		return -1;
-	return msc_tx_dtap(conn, msg);
-}
diff --git a/src/libmsc/gsm_subscriber.c b/src/libmsc/gsm_subscriber.c
deleted file mode 100644
index 09540c1..0000000
--- a/src/libmsc/gsm_subscriber.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/* The concept of a subscriber for the MSC, roughly HLR/VLR functionality */
-
-/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009,2013 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/>.
- *
- */
-
-#include "../../bscconfig.h"
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <time.h>
-#include <stdbool.h>
-
-#include <osmocom/core/talloc.h>
-
-#include <osmocom/vty/vty.h>
-
-#ifdef BUILD_IU
-#include <osmocom/ranap/iu_client.h>
-#else
-#include <openbsc/iu_dummy.h>
-#endif
-
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/debug.h>
-#include <openbsc/paging.h>
-#include <openbsc/signal.h>
-#include <openbsc/db.h>
-#include <openbsc/chan_alloc.h>
-#include <openbsc/vlr.h>
-#include <openbsc/osmo_msc.h>
-#include <openbsc/msc_ifaces.h>
-#include <openbsc/a_iface.h>
-
-int subscr_paging_dispatch(unsigned int hooknum, unsigned int event,
-			   struct msgb *msg, void *data, void *param)
-{
-	struct subscr_request *request, *tmp;
-	struct gsm_subscriber_connection *conn = data;
-	struct vlr_subscr *vsub = param;
-	struct paging_signal_data sig_data;
-
-	OSMO_ASSERT(vsub);
-	OSMO_ASSERT(hooknum == GSM_HOOK_RR_PAGING);
-	OSMO_ASSERT(!(conn && (conn->vsub != vsub)));
-	OSMO_ASSERT(!((event == GSM_PAGING_SUCCEEDED) && !conn));
-
-	LOGP(DPAG, LOGL_DEBUG, "Paging %s for %s (event=%d)\n",
-	     event == GSM_PAGING_SUCCEEDED ? "success" : "failure",
-	     vlr_subscr_name(vsub), event);
-
-	if (!vsub->cs.is_paging) {
-		LOGP(DPAG, LOGL_ERROR,
-		     "Paging Response received for subscriber"
-		     " that is not paging.\n");
-		return -EINVAL;
-	}
-
-	if (event == GSM_PAGING_SUCCEEDED)
-		msc_stop_paging(vsub);
-
-	/* Inform parts of the system we don't know */
-	sig_data.vsub = vsub;
-	sig_data.conn = conn;
-	sig_data.paging_result = event;
-	osmo_signal_dispatch(SS_PAGING,
-			     event == GSM_PAGING_SUCCEEDED ?
-				S_PAGING_SUCCEEDED : S_PAGING_EXPIRED,
-			     &sig_data);
-
-	llist_for_each_entry_safe(request, tmp, &vsub->cs.requests, entry) {
-		llist_del(&request->entry);
-		if (request->cbfn) {
-			LOGP(DPAG, LOGL_DEBUG, "Calling paging cbfn.\n");
-			request->cbfn(hooknum, event, msg, data, request->param);
-		} else
-			LOGP(DPAG, LOGL_DEBUG, "Paging without action.\n");
-		talloc_free(request);
-	}
-
-	/* balanced with the moment we start paging */
-	vsub->cs.is_paging = false;
-	vlr_subscr_put(vsub);
-	return 0;
-}
-
-int msc_paging_request(struct vlr_subscr *vsub)
-{
-	/* The subscriber was last seen in subscr->lac. Find out which
-	 * BSCs/RNCs are responsible and send them a paging request via open
-	 * SCCP connections (if any). */
-	/* TODO Implementing only RNC paging, since this is code on the iu branch.
-	 * Need to add BSC paging at some point. */
-	switch (vsub->cs.attached_via_ran) {
-	case RAN_GERAN_A:
-		return a_iface_tx_paging(vsub->imsi, vsub->tmsi, vsub->lac);
-	case RAN_UTRAN_IU:
-		return ranap_iu_page_cs(vsub->imsi,
-					vsub->tmsi == GSM_RESERVED_TMSI?
-					NULL : &vsub->tmsi,
-					vsub->lac);
-	default:
-		break;
-	}
-
-	LOGP(DPAG, LOGL_ERROR, "%s: Cannot page, subscriber not attached\n",
-	     vlr_subscr_name(vsub));
-	return -EINVAL;
-}
-
-/*! \brief Start a paging request for vsub, call cbfn(param) when done.
- * \param vsub  subscriber to page.
- * \param cbfn  function to call when the conn is established.
- * \param param  caller defined param to pass to cbfn().
- * \param label  human readable label of the request kind used for logging.
- */
-struct subscr_request *subscr_request_conn(struct vlr_subscr *vsub,
-					   gsm_cbfn *cbfn, void *param,
-					   const char *label)
-{
-	int rc;
-	struct subscr_request *request;
-
-	/* Start paging.. we know it is async so we can do it before */
-	if (!vsub->cs.is_paging) {
-		LOGP(DMM, LOGL_DEBUG, "Subscriber %s not paged yet, start paging.\n",
-		     vlr_subscr_name(vsub));
-		rc = msc_paging_request(vsub);
-		if (rc <= 0) {
-			LOGP(DMM, LOGL_ERROR, "Subscriber %s paging failed: %d\n",
-			     vlr_subscr_name(vsub), rc);
-			return NULL;
-		}
-		/* reduced on the first paging callback */
-		vlr_subscr_get(vsub);
-		vsub->cs.is_paging = true;
-	} else {
-		LOGP(DMM, LOGL_DEBUG, "Subscriber %s already paged.\n",
-			vlr_subscr_name(vsub));
-	}
-
-	/* TODO: Stop paging in case of memory allocation failure */
-	request = talloc_zero(vsub, struct subscr_request);
-	if (!request)
-		return NULL;
-
-	request->cbfn = cbfn;
-	request->param = param;
-	llist_add_tail(&request->entry, &vsub->cs.requests);
-	return request;
-}
-
-void subscr_remove_request(struct subscr_request *request)
-{
-	llist_del(&request->entry);
-	talloc_free(request);
-}
-
-struct gsm_subscriber_connection *connection_for_subscr(struct vlr_subscr *vsub)
-{
-	struct gsm_network *net = vsub->vlr->user_ctx;
-	struct gsm_subscriber_connection *conn;
-
-	llist_for_each_entry(conn, &net->subscr_conns, entry) {
-		if (conn->vsub == vsub)
-			return conn;
-	}
-
-	return NULL;
-}
diff --git a/src/libmsc/iu_dummy.c b/src/libmsc/iu_dummy.c
deleted file mode 100644
index e9d335e..0000000
--- a/src/libmsc/iu_dummy.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/* Trivial switch-off of external Iu dependencies,
- * allowing to run full unit tests even when built without Iu support. */
-
-/*
- * (C) 2016,2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- *
- * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
- *
- * 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/>.
- *
- */
-
-#include "../../bscconfig.h"
-#ifndef BUILD_IU
-
-#include <openbsc/iu_dummy.h>
-
-#include <osmocom/core/logging.h>
-#include <osmocom/vty/logging.h>
-#include <osmocom/core/msgb.h>
-
-struct msgb;
-struct ranap_ue_conn_ctx;
-struct gsm_auth_tuple;
-struct RANAP_Cause;
-struct osmo_auth_vector;
-
-int ranap_iu_tx(struct msgb *msg, uint8_t sapi)
-{
-	LOGP(DLGLOBAL, LOGL_INFO, "iu_tx() dummy called, NOT transmitting %d bytes: %s\n",
-	     msg->len, osmo_hexdump(msg->data, msg->len));
-	return 0;
-}
-
-int ranap_iu_tx_sec_mode_cmd(struct ranap_ue_conn_ctx *uectx, struct osmo_auth_vector *vec,
-			     int send_ck)
-{
-	LOGP(DLGLOBAL, LOGL_INFO, "iu_tx_sec_mode_cmd() dummy called, NOT transmitting Security Mode Command\n");
-	return 0;
-}
-
-int ranap_iu_page_cs(const char *imsi, const uint32_t *tmsi, uint16_t lac)
-{
-	LOGP(DLGLOBAL, LOGL_INFO, "iu_page_cs() dummy called, NOT paging\n");
-	return 23;
-}
-
-int ranap_iu_page_ps(const char *imsi, const uint32_t *ptmsi, uint16_t lac, uint8_t rac)
-{
-	LOGP(DLGLOBAL, LOGL_INFO, "iu_page_ps() dummy called, NOT paging\n");
-	return 0;
-}
-
-struct msgb *ranap_new_msg_rab_assign_voice(uint8_t rab_id, uint32_t rtp_ip,
-					    uint16_t rtp_port,
-					    bool use_x213_nsap)
-{
-	LOGP(DLGLOBAL, LOGL_INFO, "ranap_new_msg_rab_assign_voice() dummy called, NOT composing RAB Assignment\n");
-	return NULL;
-}
-
-int ranap_iu_rab_act(struct ranap_ue_conn_ctx *ue_ctx, struct msgb *msg)
-{
-	LOGP(DLGLOBAL, LOGL_INFO, "iu_rab_act() dummy called, NOT activating RAB\n");
-	return 0;
-}
-
-int ranap_iu_tx_common_id(struct ranap_ue_conn_ctx *uectx, const char *imsi)
-{
-	LOGP(DLGLOBAL, LOGL_INFO, "iu_tx_common_id() dummy called, NOT sending CommonID\n");
-	return 0;
-}
-
-int ranap_iu_tx_release(struct ranap_ue_conn_ctx *ctx, const struct RANAP_Cause *cause)
-{
-	LOGP(DLGLOBAL, LOGL_INFO, "iu_tx_release() dummy called, NOT sending Release\n");
-	return 0;
-}
-
-#endif
diff --git a/src/libmsc/iucs.c b/src/libmsc/iucs.c
deleted file mode 100644
index 04b9ece..0000000
--- a/src/libmsc/iucs.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/* Code to manage MSC subscriber connections over IuCS interface */
-
-/*
- * (C) 2016,2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- *
- * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
- *
- * 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/>.
- *
- */
-
-#include <inttypes.h>
-
-#include <osmocom/core/logging.h>
-#include <osmocom/ranap/iu_client.h>
-#include <openbsc/debug.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/osmo_msc.h>
-#include <openbsc/vlr.h>
-
-/* For A-interface see libbsc/bsc_api.c subscr_con_allocate() */
-static struct gsm_subscriber_connection *subscr_conn_allocate_iu(struct gsm_network *network,
-								 struct ranap_ue_conn_ctx *ue,
-								 uint16_t lac)
-{
-	struct gsm_subscriber_connection *conn;
-
-	DEBUGP(DIUCS, "Allocating IuCS subscriber conn: lac %d, conn_id %" PRIx32 "\n",
-	       lac, ue->conn_id);
-
-	conn = talloc_zero(network, struct gsm_subscriber_connection);
-	if (!conn)
-		return NULL;
-
-	conn->network = network;
-	conn->via_ran = RAN_UTRAN_IU;
-	conn->iu.ue_ctx = ue;
-	conn->iu.ue_ctx->rab_assign_addr_enc = network->iu.rab_assign_addr_enc;
-	conn->lac = lac;
-
-	llist_add_tail(&conn->entry, &network->subscr_conns);
-	return conn;
-}
-
-static int same_ue_conn(struct ranap_ue_conn_ctx *a, struct ranap_ue_conn_ctx *b)
-{
-	if (a == b)
-		return 1;
-	return (a->conn_id == b->conn_id);
-}
-
-static inline void log_subscribers(struct gsm_network *network)
-{
-	if (!log_check_level(DIUCS, LOGL_DEBUG))
-		return;
-
-	struct gsm_subscriber_connection *conn;
-	int i = 0;
-	llist_for_each_entry(conn, &network->subscr_conns, entry) {
-		DEBUGP(DIUCS, "%3d: %s", i, vlr_subscr_name(conn->vsub));
-		switch (conn->via_ran) {
-		case RAN_UTRAN_IU:
-			DEBUGPC(DIUCS, " Iu");
-			if (conn->iu.ue_ctx) {
-				DEBUGPC(DIUCS, " conn_id %d",
-					conn->iu.ue_ctx->conn_id
-				       );
-			}
-			break;
-		case RAN_GERAN_A:
-			DEBUGPC(DIUCS, " A");
-			/* TODO log A-interface connection details */
-			break;
-		case RAN_UNKNOWN:
-			DEBUGPC(DIUCS, " ?");
-			break;
-		default:
-			DEBUGPC(DIUCS, " invalid");
-			break;
-		}
-		DEBUGPC(DIUCS, "\n");
-		i++;
-	}
-	DEBUGP(DIUCS, "subscribers registered: %d\n", i);
-}
-
-/* Return an existing IuCS subscriber connection record for the given
- * connection IDs, or return NULL if not found. */
-struct gsm_subscriber_connection *subscr_conn_lookup_iu(
-						struct gsm_network *network,
-						struct ranap_ue_conn_ctx *ue)
-{
-	struct gsm_subscriber_connection *conn;
-
-	DEBUGP(DIUCS, "Looking for IuCS subscriber: conn_id %" PRIx32 "\n",
-	       ue->conn_id);
-	log_subscribers(network);
-
-	llist_for_each_entry(conn, &network->subscr_conns, entry) {
-		if (conn->via_ran != RAN_UTRAN_IU)
-			continue;
-		if (!same_ue_conn(conn->iu.ue_ctx, ue))
-			continue;
-		DEBUGP(DIUCS, "Found IuCS subscriber for conn_id %" PRIx32 "\n",
-		       ue->conn_id);
-		return conn;
-	}
-	DEBUGP(DIUCS, "No IuCS subscriber found for conn_id %" PRIx32 "\n",
-	       ue->conn_id);
-	return NULL;
-}
-
-/* Receive MM/CC/... message from IuCS (SCCP user SAP).
- * msg->dst must reference a struct ranap_ue_conn_ctx, which identifies the peer that
- * sent the msg.
- *
- * For A-interface see libbsc/bsc_api.c gsm0408_rcvmsg(). */
-int gsm0408_rcvmsg_iucs(struct gsm_network *network, struct msgb *msg,
-			uint16_t *lac)
-{
-	int rc;
-	struct ranap_ue_conn_ctx *ue_ctx;
-	struct gsm_subscriber_connection *conn;
-
-	ue_ctx = (struct ranap_ue_conn_ctx*)msg->dst;
-
-	/* TODO: are there message types that could allow us to skip this
-	 * search? */
-	conn = subscr_conn_lookup_iu(network, ue_ctx);
-
-	if (conn && lac && (conn->lac != *lac)) {
-		LOGP(DIUCS, LOGL_ERROR, "IuCS subscriber has changed LAC"
-		     " within the same connection, discarding connection:"
-		     " %s from LAC %d to %d\n",
-		     vlr_subscr_name(conn->vsub), conn->lac, *lac);
-		/* Deallocate conn with previous LAC */
-		msc_subscr_conn_close(conn, GSM_CAUSE_INV_MAND_INFO);
-		/* At this point we could be tolerant and allocate a new
-		 * connection, but changing the LAC within the same connection
-		 * is shifty. Rather cancel everything. */
-		return -1;
-	}
-
-	if (conn) {
-		/* Make sure we don't receive RR over IuCS; otherwise all
-		 * messages handled by gsm0408_dispatch() are of interest (CC,
-		 * MM, SMS, NS_SS, maybe even MM_GPRS and SM_GPRS). */
-		struct gsm48_hdr *gh = msgb_l3(msg);
-		uint8_t pdisc = gh->proto_discr & 0x0f;
-		OSMO_ASSERT(pdisc != GSM48_PDISC_RR);
-
-		msc_dtap(conn, ue_ctx->conn_id, msg);
-		rc = 0;
-	} else {
-		/* allocate a new connection */
-
-		if (!lac) {
-			LOGP(DIUCS, LOGL_ERROR, "New IuCS subscriber"
-			     " but no LAC available. Expecting an InitialUE"
-			     " message containing a LAI IE."
-			     " Dropping connection.\n");
-			return -1;
-		}
-
-		conn = subscr_conn_allocate_iu(network, ue_ctx, *lac);
-		if (!conn)
-			abort();
-
-		/* ownership of conn hereby goes to the MSC: */
-		rc = msc_compl_l3(conn, msg, 0);
-	}
-
-	return rc;
-}
diff --git a/src/libmsc/iucs_ranap.c b/src/libmsc/iucs_ranap.c
deleted file mode 100644
index 45de1ca..0000000
--- a/src/libmsc/iucs_ranap.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* Implementation of RANAP messages to/from an MSC via an Iu-CS interface.
- * This keeps direct RANAP dependencies out of libmsc. */
-
-/* (C) 2016 by sysmocom s.m.f.c. GmbH <info@sysmocom.de>
- *
- * 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/>.
- *
- */
-
-#include "../../bscconfig.h"
-
-#ifdef BUILD_IU
-
-#include <osmocom/core/logging.h>
-
-#include <osmocom/ranap/ranap_ies_defs.h>
-#include <osmocom/ranap/iu_client.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/iucs.h>
-#include <openbsc/vlr.h>
-#include <openbsc/iucs_ranap.h>
-#include <openbsc/osmo_msc.h>
-
-/* To continue authorization after a Security Mode Complete */
-int gsm0408_authorize(struct gsm_subscriber_connection *conn);
-
-static int iucs_rx_rab_assign(struct gsm_subscriber_connection *conn,
-			      RANAP_RAB_SetupOrModifiedItemIEs_t *setup_ies)
-{
-	uint8_t rab_id;
-	RANAP_RAB_SetupOrModifiedItem_t *item = &setup_ies->raB_SetupOrModifiedItem;
-
-	rab_id = item->rAB_ID.buf[0];
-
-	LOGP(DIUCS, LOGL_NOTICE,
-	     "Received RAB assignment event for %s rab_id=%hhd\n",
-	     vlr_subscr_name(conn->vsub), rab_id);
-
-	return 0;
-}
-
-int iucs_rx_sec_mode_compl(struct gsm_subscriber_connection *conn,
-			   RANAP_SecurityModeCompleteIEs_t *ies)
-{
-	OSMO_ASSERT(conn->via_ran == RAN_UTRAN_IU);
-
-	/* TODO evalute ies */
-
-	msc_rx_sec_mode_compl(conn);
-	return 0;
-}
-
-int iucs_rx_ranap_event(struct gsm_network *network,
-			struct ranap_ue_conn_ctx *ue_ctx, int type, void *data)
-{
-	struct gsm_subscriber_connection *conn;
-
-	conn = subscr_conn_lookup_iu(network, ue_ctx);
-
-	if (!conn) {
-		LOGP(DRANAP, LOGL_ERROR, "Cannot find subscriber for IU event %u\n", type);
-		return -1;
-	}
-
-	switch (type) {
-	case RANAP_IU_EVENT_IU_RELEASE:
-	case RANAP_IU_EVENT_LINK_INVALIDATED:
-		LOGP(DIUCS, LOGL_INFO, "IuCS release for %s\n",
-		     vlr_subscr_name(conn->vsub));
-		msc_subscr_conn_close(conn, 0);
-		return 0;
-
-	case RANAP_IU_EVENT_SECURITY_MODE_COMPLETE:
-		LOGP(DIUCS, LOGL_INFO, "IuCS security mode complete for %s\n",
-		     vlr_subscr_name(conn->vsub));
-		return iucs_rx_sec_mode_compl(conn,
-					      (RANAP_SecurityModeCompleteIEs_t*)data);
-	case RANAP_IU_EVENT_RAB_ASSIGN:
-		return iucs_rx_rab_assign(conn,
-				(RANAP_RAB_SetupOrModifiedItemIEs_t*)data);
-	default:
-		LOGP(DIUCS, LOGL_NOTICE, "Unknown message received:"
-		     " RANAP event: %i\n", type);
-		return -1;
-	}
-}
-
-#endif /* BUILD_IU */
diff --git a/src/libmsc/meas_feed.c b/src/libmsc/meas_feed.c
deleted file mode 100644
index 1e7b4cd..0000000
--- a/src/libmsc/meas_feed.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/* UDP-Feed of measurement reports */
-
-#include <unistd.h>
-
-#include <sys/socket.h>
-
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/socket.h>
-#include <osmocom/core/write_queue.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-
-#include <osmocom/vty/command.h>
-#include <osmocom/vty/vty.h>
-
-#include <openbsc/meas_rep.h>
-#include <openbsc/signal.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/meas_feed.h>
-#include <openbsc/vty.h>
-#include <openbsc/vlr.h>
-
-#include "meas_feed.h"
-
-struct meas_feed_state {
-	struct osmo_wqueue wqueue;
-	char scenario[31+1];
-	char *dst_host;
-	uint16_t dst_port;
-};
-
-
-static struct meas_feed_state g_mfs;
-
-static int process_meas_rep(struct gsm_meas_rep *mr)
-{
-	struct msgb *msg;
-	struct meas_feed_meas *mfm;
-	struct vlr_subscr *vsub;
-
-	/* ignore measurements as long as we don't know who it is */
-	if (!mr->lchan || !mr->lchan->conn || !mr->lchan->conn->vsub)
-		return 0;
-
-	vsub = mr->lchan->conn->vsub;
-
-	msg = msgb_alloc(sizeof(struct meas_feed_meas), "Meas. Feed");
-	if (!msg)
-		return 0;
-
-	/* fill in the header */
-	mfm = (struct meas_feed_meas *) msgb_put(msg, sizeof(*mfm));
-	mfm->hdr.msg_type = MEAS_FEED_MEAS;
-	mfm->hdr.version = MEAS_FEED_VERSION;
-
-	/* fill in MEAS_FEED_MEAS specific header */
-	osmo_strlcpy(mfm->imsi, vsub->imsi, sizeof(mfm->imsi));
-	osmo_strlcpy(mfm->name, vsub->name, sizeof(mfm->name));
-	osmo_strlcpy(mfm->scenario, g_mfs.scenario, sizeof(mfm->scenario));
-
-	/* copy the entire measurement report */
-	memcpy(&mfm->mr, mr, sizeof(mfm->mr));
-
-	/* copy channel information */
-	/* we assume that the measurement report always belong to some timeslot */
-	mfm->lchan_type = (uint8_t)mr->lchan->type;
-	mfm->pchan_type = (uint8_t)mr->lchan->ts->pchan;
-	mfm->bts_nr = mr->lchan->ts->trx->bts->nr;
-	mfm->trx_nr = mr->lchan->ts->trx->nr;
-	mfm->ts_nr = mr->lchan->ts->nr;
-	mfm->ss_nr = mr->lchan->nr;
-
-	/* and send it to the socket */
-	if (osmo_wqueue_enqueue(&g_mfs.wqueue, msg) != 0)
-		msgb_free(msg);
-
-	return 0;
-}
-
-static int meas_feed_sig_cb(unsigned int subsys, unsigned int signal,
-			    void *handler_data, void *signal_data)
-{
-	struct lchan_signal_data *sdata = signal_data;
-
-	if (subsys != SS_LCHAN)
-		return 0;
-
-	if (signal == S_LCHAN_MEAS_REP)
-		process_meas_rep(sdata->mr);
-
-	return 0;
-}
-
-static int feed_write_cb(struct osmo_fd *ofd, struct msgb *msg)
-{
-	return write(ofd->fd, msgb_data(msg), msgb_length(msg));
-}
-
-static int feed_read_cb(struct osmo_fd *ofd)
-{
-	int rc;
-	char buf[256];
-
-	rc = read(ofd->fd, buf, sizeof(buf));
-	ofd->fd &= ~BSC_FD_READ;
-
-	return rc;
-}
-
-int meas_feed_cfg_set(const char *dst_host, uint16_t dst_port)
-{
-	int rc;
-	int already_initialized = 0;
-
-	if (g_mfs.wqueue.bfd.fd)
-		already_initialized = 1;
-
-
-	if (already_initialized &&
-	    !strcmp(dst_host, g_mfs.dst_host) &&
-	    dst_port == g_mfs.dst_port)
-		return 0;
-
-	if (!already_initialized) {
-		osmo_wqueue_init(&g_mfs.wqueue, 10);
-		g_mfs.wqueue.write_cb = feed_write_cb;
-		g_mfs.wqueue.read_cb = feed_read_cb;
-		osmo_signal_register_handler(SS_LCHAN, meas_feed_sig_cb, NULL);
-	}
-
-	if (already_initialized) {
-		osmo_wqueue_clear(&g_mfs.wqueue);
-		osmo_fd_unregister(&g_mfs.wqueue.bfd);
-		close(g_mfs.wqueue.bfd.fd);
-		/* don't set to zero, as that would mean 'not yet initialized' */
-		g_mfs.wqueue.bfd.fd = -1;
-	}
-	rc = osmo_sock_init_ofd(&g_mfs.wqueue.bfd, AF_UNSPEC, SOCK_DGRAM,
-				IPPROTO_UDP, dst_host, dst_port,
-				OSMO_SOCK_F_CONNECT);
-	if (rc < 0)
-		return rc;
-
-	g_mfs.wqueue.bfd.when &= ~BSC_FD_READ;
-
-	if (g_mfs.dst_host)
-		talloc_free(g_mfs.dst_host);
-	g_mfs.dst_host = talloc_strdup(NULL, dst_host);
-	g_mfs.dst_port = dst_port;
-
-	return 0;
-}
-
-void meas_feed_cfg_get(char **host, uint16_t *port)
-{
-	*port = g_mfs.dst_port;
-	*host = g_mfs.dst_host;
-}
-
-void meas_feed_scenario_set(const char *name)
-{
-	osmo_strlcpy(g_mfs.scenario, name, sizeof(g_mfs.scenario));
-}
-
-const char *meas_feed_scenario_get(void)
-{
-	return g_mfs.scenario;
-}
diff --git a/src/libmsc/meas_feed.h b/src/libmsc/meas_feed.h
deleted file mode 100644
index 782a961..0000000
--- a/src/libmsc/meas_feed.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _INT_MEAS_FEED_H
-#define _INT_MEAS_FEED_H
-
-#include <stdint.h>
-
-int meas_feed_cfg_set(const char *dst_host, uint16_t dst_port);
-void meas_feed_cfg_get(char **host, uint16_t *port);
-
-void meas_feed_scenario_set(const char *name);
-const char *meas_feed_scenario_get(void);
-
-#endif  /* _INT_MEAS_FEED_H */
diff --git a/src/libmsc/mncc.c b/src/libmsc/mncc.c
deleted file mode 100644
index 8110ead..0000000
--- a/src/libmsc/mncc.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/* mncc.c - utility routines for the MNCC API between the 04.08
- *	    message parsing and the actual Call Control logic */
-
-/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009 by Andreas Eversberg <Andreas.Eversberg@versatel.de>
- * 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/>.
- *
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/debug.h>
-#include <openbsc/mncc.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/transaction.h>
-#include <openbsc/rtp_proxy.h>
-
-
-static const struct value_string mncc_names[] = {
-	{ MNCC_SETUP_REQ, "MNCC_SETUP_REQ" },
-	{ MNCC_SETUP_IND, "MNCC_SETUP_IND" },
-	{ MNCC_SETUP_RSP, "MNCC_SETUP_RSP" },
-	{ MNCC_SETUP_CNF, "MNCC_SETUP_CNF" },
-	{ MNCC_SETUP_COMPL_REQ, "MNCC_SETUP_COMPL_REQ" },
-	{ MNCC_SETUP_COMPL_IND, "MNCC_SETUP_COMPL_IND" },
-	{ MNCC_CALL_CONF_IND, "MNCC_CALL_CONF_IND" },
-	{ MNCC_CALL_PROC_REQ, "MNCC_CALL_PROC_REQ" },
-	{ MNCC_PROGRESS_REQ, "MNCC_PROGRESS_REQ" },
-	{ MNCC_ALERT_REQ, "MNCC_ALERT_REQ" },
-	{ MNCC_ALERT_IND, "MNCC_ALERT_IND" },
-	{ MNCC_NOTIFY_REQ, "MNCC_NOTIFY_REQ" },
-	{ MNCC_NOTIFY_IND, "MNCC_NOTIFY_IND" },
-	{ MNCC_DISC_REQ, "MNCC_DISC_REQ" },
-	{ MNCC_DISC_IND, "MNCC_DISC_IND" },
-	{ MNCC_REL_REQ, "MNCC_REL_REQ" },
-	{ MNCC_REL_IND, "MNCC_REL_IND" },
-	{ MNCC_REL_CNF, "MNCC_REL_CNF" },
-	{ MNCC_FACILITY_REQ, "MNCC_FACILITY_REQ" },
-	{ MNCC_FACILITY_IND, "MNCC_FACILITY_IND" },
-	{ MNCC_START_DTMF_IND, "MNCC_START_DTMF_IND" },
-	{ MNCC_START_DTMF_RSP, "MNCC_START_DTMF_RSP" },
-	{ MNCC_START_DTMF_REJ, "MNCC_START_DTMF_REJ" },
-	{ MNCC_STOP_DTMF_IND, "MNCC_STOP_DTMF_IND" },
-	{ MNCC_STOP_DTMF_RSP, "MNCC_STOP_DTMF_RSP" },
-	{ MNCC_MODIFY_REQ, "MNCC_MODIFY_REQ" },
-	{ MNCC_MODIFY_IND, "MNCC_MODIFY_IND" },
-	{ MNCC_MODIFY_RSP, "MNCC_MODIFY_RSP" },
-	{ MNCC_MODIFY_CNF, "MNCC_MODIFY_CNF" },
-	{ MNCC_MODIFY_REJ, "MNCC_MODIFY_REJ" },
-	{ MNCC_HOLD_IND, "MNCC_HOLD_IND" },
-	{ MNCC_HOLD_CNF, "MNCC_HOLD_CNF" },
-	{ MNCC_HOLD_REJ, "MNCC_HOLD_REJ" },
-	{ MNCC_RETRIEVE_IND, "MNCC_RETRIEVE_IND" },
-	{ MNCC_RETRIEVE_CNF, "MNCC_RETRIEVE_CNF" },
-	{ MNCC_RETRIEVE_REJ, "MNCC_RETRIEVE_REJ" },
-	{ MNCC_USERINFO_REQ, "MNCC_USERINFO_REQ" },
-	{ MNCC_USERINFO_IND, "MNCC_USERINFO_IND" },
-	{ MNCC_REJ_REQ, "MNCC_REJ_REQ" },
-	{ MNCC_REJ_IND, "MNCC_REJ_IND" },
-	{ MNCC_BRIDGE, "MNCC_BRIDGE" },
-	{ MNCC_FRAME_RECV, "MNCC_FRAME_RECV" },
-	{ MNCC_FRAME_DROP, "MNCC_FRAME_DROP" },
-	{ MNCC_LCHAN_MODIFY, "MNCC_LCHAN_MODIFY" },
-	{ MNCC_RTP_CREATE, "MNCC_RTP_CREATE" },
-	{ MNCC_RTP_CONNECT, "MNCC_RTP_CONNECT" },
-	{ MNCC_RTP_FREE, "MNCC_RTP_FREE" },
-	{ GSM_TCHF_FRAME, "GSM_TCHF_FRAME" },
-	{ GSM_TCHF_FRAME_EFR, "GSM_TCHF_FRAME_EFR" },
-	{ GSM_TCHH_FRAME, "GSM_TCHH_FRAME" },
-	{ GSM_TCH_FRAME_AMR, "GSM_TCH_FRAME_AMR" },
-	{ GSM_BAD_FRAME, "GSM_BAD_FRAME" },
-	{ 0, NULL },
-};
-
-const char *get_mncc_name(int value)
-{
-	return get_value_string(mncc_names, value);
-}
-
-void mncc_set_cause(struct gsm_mncc *data, int loc, int val)
-{
-	data->fields |= MNCC_F_CAUSE;
-	data->cause.location = loc;
-	data->cause.value = val;
-}
-
diff --git a/src/libmsc/mncc_builtin.c b/src/libmsc/mncc_builtin.c
deleted file mode 100644
index ac6e734..0000000
--- a/src/libmsc/mncc_builtin.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/* mncc_builtin.c - default, minimal built-in MNCC Application for
- *		    standalone bsc_hack (network-in-the-box mode) */
-
-/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009 by Andreas Eversberg <Andreas.Eversberg@versatel.de>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * 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.
- *
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/debug.h>
-#include <openbsc/mncc.h>
-#include <openbsc/mncc_int.h>
-#include <osmocom/core/talloc.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/transaction.h>
-#include <openbsc/rtp_proxy.h>
-
-void *tall_call_ctx;
-
-static LLIST_HEAD(call_list);
-
-static uint32_t new_callref = 0x00000001;
-
-struct mncc_int mncc_int = {
-	.def_codec = { GSM48_CMODE_SPEECH_V1, GSM48_CMODE_SPEECH_V1 },
-};
-
-static void free_call(struct gsm_call *call)
-{
-	llist_del(&call->entry);
-	DEBUGP(DMNCC, "(call %x) Call removed.\n", call->callref);
-	talloc_free(call);
-}
-
-
-static struct gsm_call *get_call_ref(uint32_t callref)
-{
-	struct gsm_call *callt;
-
-	llist_for_each_entry(callt, &call_list, entry) {
-		if (callt->callref == callref)
-			return callt;
-	}
-	return NULL;
-}
-
-/* on incoming call, look up database and send setup to remote subscr. */
-static int mncc_setup_ind(struct gsm_call *call, int msg_type,
-			  struct gsm_mncc *setup)
-{
-	struct gsm_mncc mncc;
-	struct gsm_call *remote;
-
-	memset(&mncc, 0, sizeof(struct gsm_mncc));
-	mncc.callref = call->callref;
-
-	/* already have remote call */
-	if (call->remote_ref)
-		return 0;
-	
-	/* transfer mode 1 would be packet mode, which was never specified */
-	if (setup->bearer_cap.mode != 0) {
-		LOGP(DMNCC, LOGL_NOTICE, "(call %x) We don't support "
-			"packet mode\n", call->callref);
-		mncc_set_cause(&mncc, GSM48_CAUSE_LOC_PRN_S_LU,
-				GSM48_CC_CAUSE_BEARER_CA_UNAVAIL);
-		goto out_reject;
-	}
-
-	/* we currently only do speech */
-	if (setup->bearer_cap.transfer != GSM_MNCC_BCAP_SPEECH) {
-		LOGP(DMNCC, LOGL_NOTICE, "(call %x) We only support "
-			"voice calls\n", call->callref);
-		mncc_set_cause(&mncc, GSM48_CAUSE_LOC_PRN_S_LU,
-				GSM48_CC_CAUSE_BEARER_CA_UNAVAIL);
-		goto out_reject;
-	}
-
-	/* create remote call */
-	if (!(remote = talloc_zero(tall_call_ctx, struct gsm_call))) {
-		mncc_set_cause(&mncc, GSM48_CAUSE_LOC_PRN_S_LU,
-				GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
-		goto out_reject;
-	}
-	llist_add_tail(&remote->entry, &call_list);
-	remote->net = call->net;
-	remote->callref = new_callref++;
-	DEBUGP(DMNCC, "(call %x) Creating new remote instance %x.\n",
-		call->callref, remote->callref);
-
-	/* link remote call */
-	call->remote_ref = remote->callref;
-	remote->remote_ref = call->callref;
-
-	/* send call proceeding */
-	memset(&mncc, 0, sizeof(struct gsm_mncc));
-	mncc.callref = call->callref;
-	DEBUGP(DMNCC, "(call %x) Accepting call.\n", call->callref);
-	mncc_tx_to_cc(call->net, MNCC_CALL_PROC_REQ, &mncc);
-
-	/* modify mode */
-	memset(&mncc, 0, sizeof(struct gsm_mncc));
-	mncc.callref = call->callref;
-	DEBUGP(DMNCC, "(call %x) Modify channel mode\n", call->callref);
-	mncc_tx_to_cc(call->net, MNCC_LCHAN_MODIFY, &mncc);
-
-	/* send setup to remote */
-//	setup->fields |= MNCC_F_SIGNAL;
-//	setup->signal = GSM48_SIGNAL_DIALTONE;
-	setup->callref = remote->callref;
-	DEBUGP(DMNCC, "(call %x) Forwarding SETUP to remote.\n", call->callref);
-	return mncc_tx_to_cc(remote->net, MNCC_SETUP_REQ, setup);
-
-out_reject:
-	mncc_tx_to_cc(call->net, MNCC_REJ_REQ, &mncc);
-	free_call(call);
-	return 0;
-}
-
-static int mncc_alert_ind(struct gsm_call *call, int msg_type,
-			  struct gsm_mncc *alert)
-{
-	struct gsm_call *remote;
-
-	/* send alerting to remote */
-	if (!(remote = get_call_ref(call->remote_ref)))
-		return 0;
-	alert->callref = remote->callref;
-	DEBUGP(DMNCC, "(call %x) Forwarding ALERT to remote.\n", call->callref);
-	return mncc_tx_to_cc(remote->net, MNCC_ALERT_REQ, alert);
-}
-
-static int mncc_notify_ind(struct gsm_call *call, int msg_type,
-			   struct gsm_mncc *notify)
-{
-	struct gsm_call *remote;
-
-	/* send notify to remote */
-	if (!(remote = get_call_ref(call->remote_ref)))
-		return 0;
-	notify->callref = remote->callref;
-	DEBUGP(DMNCC, "(call %x) Forwarding NOTIF to remote.\n", call->callref);
-	return mncc_tx_to_cc(remote->net, MNCC_NOTIFY_REQ, notify);
-}
-
-static int mncc_setup_cnf(struct gsm_call *call, int msg_type,
-			  struct gsm_mncc *connect)
-{
-	struct gsm_mncc connect_ack, frame_recv;
-	struct gsm_network *net = call->net;
-	struct gsm_call *remote;
-	struct gsm_mncc_bridge bridge = { .msg_type = MNCC_BRIDGE };
-
-	/* acknowledge connect */
-	memset(&connect_ack, 0, sizeof(struct gsm_mncc));
-	connect_ack.callref = call->callref;
-	DEBUGP(DMNCC, "(call %x) Acknowledge SETUP.\n", call->callref);
-	mncc_tx_to_cc(call->net, MNCC_SETUP_COMPL_REQ, &connect_ack);
-
-	/* send connect message to remote */
-	if (!(remote = get_call_ref(call->remote_ref)))
-		return 0;
-	connect->callref = remote->callref;
-	DEBUGP(DMNCC, "(call %x) Sending CONNECT to remote.\n", call->callref);
-	mncc_tx_to_cc(remote->net, MNCC_SETUP_RSP, connect);
-
-	/* bridge tch */
-	bridge.callref[0] = call->callref;
-	bridge.callref[1] = call->remote_ref;
-	DEBUGP(DMNCC, "(call %x) Bridging with remote.\n", call->callref);
-
-	/* proxy mode */
-	if (!net->handover.active) {
-		/* in the no-handover case, we can bridge, i.e. use
-		 * the old RTP proxy code */
-		return mncc_tx_to_cc(call->net, MNCC_BRIDGE, &bridge);
-	} else {
-		/* in case of handover, we need to re-write the RTP
-		 * SSRC, sequence and timestamp values and thus
-		 * need to enable RTP receive for both directions */
-		memset(&frame_recv, 0, sizeof(struct gsm_mncc));
-		frame_recv.callref = call->callref;
-		mncc_tx_to_cc(call->net, MNCC_FRAME_RECV, &frame_recv);
-		frame_recv.callref = call->remote_ref;
-		return mncc_tx_to_cc(call->net, MNCC_FRAME_RECV, &frame_recv);
-	}
-}
-
-static int mncc_disc_ind(struct gsm_call *call, int msg_type,
-			 struct gsm_mncc *disc)
-{
-	struct gsm_call *remote;
-
-	/* send release */
-	DEBUGP(DMNCC, "(call %x) Releasing call with cause %d\n",
-		call->callref, disc->cause.value);
-	mncc_tx_to_cc(call->net, MNCC_REL_REQ, disc);
-
-	/* send disc to remote */
-	if (!(remote = get_call_ref(call->remote_ref))) {
-		return 0;
-	}
-	disc->callref = remote->callref;
-	DEBUGP(DMNCC, "(call %x) Disconnecting remote with cause %d\n",
-		remote->callref, disc->cause.value);
-	return mncc_tx_to_cc(remote->net, MNCC_DISC_REQ, disc);
-}
-
-static int mncc_rel_ind(struct gsm_call *call, int msg_type, struct gsm_mncc *rel)
-{
-	struct gsm_call *remote;
-
-	/* send release to remote */
-	if (!(remote = get_call_ref(call->remote_ref))) {
-		free_call(call);
-		return 0;
-	}
-
-	rel->callref = remote->callref;
-	DEBUGP(DMNCC, "(call %x) Releasing remote with cause %d\n",
-		call->callref, rel->cause.value);
-
-	/*
-	 * Release this side of the call right now. Otherwise we end up
-	 * in this method for the other call and will also try to release
-	 * it and then we will end up with a double free and a crash
-	 */
-	free_call(call);
-	mncc_tx_to_cc(remote->net, MNCC_REL_REQ, rel);
-
-	return 0;
-}
-
-static int mncc_rel_cnf(struct gsm_call *call, int msg_type, struct gsm_mncc *rel)
-{
-	free_call(call);
-	return 0;
-}
-
-/* Internal MNCC handler input function (from CC -> MNCC -> here) */
-int int_mncc_recv(struct gsm_network *net, struct msgb *msg)
-{
-	void *arg = msgb_data(msg);
-	struct gsm_mncc *data = arg;
-	int msg_type = data->msg_type;
-	int callref;
-	struct gsm_call *call = NULL, *callt;
-	int rc = 0;
-
-	/* Special messages */
-	switch(msg_type) {
-	}
-	
-	/* find callref */
-	callref = data->callref;
-	llist_for_each_entry(callt, &call_list, entry) {
-		if (callt->callref == callref) {
-			call = callt;
-			break;
-		}
-	}
-
-	/* create callref, if setup is received */
-	if (!call) {
-		if (msg_type != MNCC_SETUP_IND)
-			goto out_free; /* drop */
-		/* create call */
-		if (!(call = talloc_zero(tall_call_ctx, struct gsm_call))) {
-			struct gsm_mncc rel;
-			
-			memset(&rel, 0, sizeof(struct gsm_mncc));
-			rel.callref = callref;
-			mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
-				       GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
-			mncc_tx_to_cc(net, MNCC_REL_REQ, &rel);
-			goto out_free;
-		}
-		llist_add_tail(&call->entry, &call_list);
-		call->net = net;
-		call->callref = callref;
-		DEBUGP(DMNCC, "(call %x) Call created.\n", call->callref);
-	}
-
-	if (mncc_is_data_frame(msg_type)) {
-		LOGP(DMNCC, LOGL_ERROR, "(call %x) Received data frame, which is not supported.\n",
-		     call->callref);
-		goto out_free;
-	}
-
-	DEBUGP(DMNCC, "(call %x) Received message %s\n", call->callref,
-		get_mncc_name(msg_type));
-
-	switch(msg_type) {
-	case MNCC_SETUP_IND:
-		rc = mncc_setup_ind(call, msg_type, arg);
-		break;
-	case MNCC_SETUP_CNF:
-		rc = mncc_setup_cnf(call, msg_type, arg);
-		break;
-	case MNCC_SETUP_COMPL_IND:
-		break;
-	case MNCC_CALL_CONF_IND:
-		/* we now need to MODIFY the channel */
-		mncc_tx_to_cc(call->net, MNCC_LCHAN_MODIFY, data);
-		break;
-	case MNCC_ALERT_IND:
-		rc = mncc_alert_ind(call, msg_type, arg);
-		break;
-	case MNCC_NOTIFY_IND:
-		rc = mncc_notify_ind(call, msg_type, arg);
-		break;
-	case MNCC_DISC_IND:
-		rc = mncc_disc_ind(call, msg_type, arg);
-		break;
-	case MNCC_REL_IND:
-	case MNCC_REJ_IND:
-		rc = mncc_rel_ind(call, msg_type, arg);
-		break;
-	case MNCC_REL_CNF:
-		rc = mncc_rel_cnf(call, msg_type, arg);
-		break;
-	case MNCC_FACILITY_IND:
-		break;
-	case MNCC_START_DTMF_IND:
-		rc = mncc_tx_to_cc(net, MNCC_START_DTMF_REJ, data);
-		break;
-	case MNCC_STOP_DTMF_IND:
-		rc = mncc_tx_to_cc(net, MNCC_STOP_DTMF_RSP, data);
-		break;
-	case MNCC_MODIFY_IND:
-		mncc_set_cause(data, GSM48_CAUSE_LOC_PRN_S_LU,
-				GSM48_CC_CAUSE_SERV_OPT_UNIMPL);
-		DEBUGP(DMNCC, "(call %x) Rejecting MODIFY with cause %d\n",
-			call->callref, data->cause.value);
-		rc = mncc_tx_to_cc(net, MNCC_MODIFY_REJ, data);
-		break;
-	case MNCC_MODIFY_CNF:
-		break;
-	case MNCC_HOLD_IND:
-		mncc_set_cause(data, GSM48_CAUSE_LOC_PRN_S_LU,
-				GSM48_CC_CAUSE_SERV_OPT_UNIMPL);
-		DEBUGP(DMNCC, "(call %x) Rejecting HOLD with cause %d\n",
-			call->callref, data->cause.value);
-		rc = mncc_tx_to_cc(net, MNCC_HOLD_REJ, data);
-		break;
-	case MNCC_RETRIEVE_IND:
-		mncc_set_cause(data, GSM48_CAUSE_LOC_PRN_S_LU,
-				GSM48_CC_CAUSE_SERV_OPT_UNIMPL);
-		DEBUGP(DMNCC, "(call %x) Rejecting RETRIEVE with cause %d\n",
-			call->callref, data->cause.value);
-		rc = mncc_tx_to_cc(net, MNCC_RETRIEVE_REJ, data);
-		break;
-	default:
-		LOGP(DMNCC, LOGL_NOTICE, "(call %x) Message unhandled\n", callref);
-		break;
-	}
-
-out_free:
-	msgb_free(msg);
-
-	return rc;
-}
diff --git a/src/libmsc/mncc_sock.c b/src/libmsc/mncc_sock.c
deleted file mode 100644
index 0c696f2..0000000
--- a/src/libmsc/mncc_sock.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/* mncc_sock.c: Tie the MNCC interface to a unix domain socket */
-
-/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009 by Andreas Eversberg <Andreas.Eversberg@versatel.de>
- * (C) 2012 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 General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * 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.
- *
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/socket.h>
-#include <osmocom/gsm/protocol/gsm_04_08.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/mncc.h>
-#include <openbsc/gsm_data.h>
-
-struct mncc_sock_state {
-	struct gsm_network *net;
-	struct osmo_fd listen_bfd;	/* fd for listen socket */
-	struct osmo_fd conn_bfd;		/* fd for connection to lcr */
-};
-
-/* input from CC code into mncc_sock */
-int mncc_sock_from_cc(struct gsm_network *net, struct msgb *msg)
-{
-	struct gsm_mncc *mncc_in = (struct gsm_mncc *) msgb_data(msg);
-	int msg_type = mncc_in->msg_type;
-
-	/* Check if we currently have a MNCC handler connected */
-	if (net->mncc_state->conn_bfd.fd < 0) {
-		LOGP(DMNCC, LOGL_ERROR, "mncc_sock receives %s for external CC app "
-			"but socket is gone\n", get_mncc_name(msg_type));
-		if (!mncc_is_data_frame(msg_type)) {
-			/* release the request */
-			struct gsm_mncc mncc_out;
-			memset(&mncc_out, 0, sizeof(mncc_out));
-			mncc_out.callref = mncc_in->callref;
-			mncc_set_cause(&mncc_out, GSM48_CAUSE_LOC_PRN_S_LU,
-					GSM48_CC_CAUSE_TEMP_FAILURE);
-			mncc_tx_to_cc(net, MNCC_REL_REQ, &mncc_out);
-		}
-		/* free the original message */
-		msgb_free(msg);
-		return -1;
-	}
-
-	/* FIXME: check for some maximum queue depth? */
-
-	/* Actually enqueue the message and mark socket write need */
-	msgb_enqueue(&net->upqueue, msg);
-	net->mncc_state->conn_bfd.when |= BSC_FD_WRITE;
-	return 0;
-}
-
-static void mncc_sock_close(struct mncc_sock_state *state)
-{
-	struct osmo_fd *bfd = &state->conn_bfd;
-
-	LOGP(DMNCC, LOGL_NOTICE, "MNCC Socket has LOST connection\n");
-
-	close(bfd->fd);
-	bfd->fd = -1;
-	osmo_fd_unregister(bfd);
-
-	/* re-enable the generation of ACCEPT for new connections */
-	state->listen_bfd.when |= BSC_FD_READ;
-
-	/* release all exisitng calls */
-	gsm0408_clear_all_trans(state->net, GSM48_PDISC_CC);
-
-	/* flush the queue */
-	while (!llist_empty(&state->net->upqueue)) {
-		struct msgb *msg = msgb_dequeue(&state->net->upqueue);
-		msgb_free(msg);
-	}
-}
-
-static int mncc_sock_read(struct osmo_fd *bfd)
-{
-	struct mncc_sock_state *state = (struct mncc_sock_state *)bfd->data;
-	struct gsm_mncc *mncc_prim;
-	struct msgb *msg;
-	int rc;
-
-	msg = msgb_alloc(sizeof(*mncc_prim)+256, "mncc_sock_rx");
-	if (!msg)
-		return -ENOMEM;
-
-	mncc_prim = (struct gsm_mncc *) msg->tail;
-
-	rc = recv(bfd->fd, msg->tail, msgb_tailroom(msg), 0);
-	if (rc == 0)
-		goto close;
-
-	if (rc < 0) {
-		if (errno == EAGAIN)
-			return 0;
-		goto close;
-	}
-
-	rc = mncc_tx_to_cc(state->net, mncc_prim->msg_type, mncc_prim);
-
-	/* as we always synchronously process the message in mncc_send() and
-	 * its callbacks, we can free the message here. */
-	msgb_free(msg);
-
-	return rc;
-
-close:
-	msgb_free(msg);
-	mncc_sock_close(state);
-	return -1;
-}
-
-static int mncc_sock_write(struct osmo_fd *bfd)
-{
-	struct mncc_sock_state *state = bfd->data;
-	struct gsm_network *net = state->net;
-	int rc;
-
-	while (!llist_empty(&net->upqueue)) {
-		struct msgb *msg, *msg2;
-		struct gsm_mncc *mncc_prim;
-
-		/* peek at the beginning of the queue */
-		msg = llist_entry(net->upqueue.next, struct msgb, list);
-		mncc_prim = (struct gsm_mncc *)msg->data;
-
-		bfd->when &= ~BSC_FD_WRITE;
-
-		/* bug hunter 8-): maybe someone forgot msgb_put(...) ? */
-		if (!msgb_length(msg)) {
-			LOGP(DMNCC, LOGL_ERROR, "message type (%d) with ZERO "
-				"bytes!\n", mncc_prim->msg_type);
-			goto dontsend;
-		}
-
-		/* try to send it over the socket */
-		rc = write(bfd->fd, msgb_data(msg), msgb_length(msg));
-		if (rc == 0)
-			goto close;
-		if (rc < 0) {
-			if (errno == EAGAIN) {
-				bfd->when |= BSC_FD_WRITE;
-				break;
-			}
-			goto close;
-		}
-
-dontsend:
-		/* _after_ we send it, we can deueue */
-		msg2 = msgb_dequeue(&net->upqueue);
-		assert(msg == msg2);
-		msgb_free(msg);
-	}
-	return 0;
-
-close:
-	mncc_sock_close(state);
-
-	return -1;
-}
-
-static int mncc_sock_cb(struct osmo_fd *bfd, unsigned int flags)
-{
-	int rc = 0;
-
-	if (flags & BSC_FD_READ)
-		rc = mncc_sock_read(bfd);
-	if (rc < 0)
-		return rc;
-
-	if (flags & BSC_FD_WRITE)
-		rc = mncc_sock_write(bfd);
-
-	return rc;
-}
-
-/**
- * Send a version indication to the remote.
- */
-static void queue_hello(struct mncc_sock_state *mncc)
-{
-	struct gsm_mncc_hello *hello;
-	struct msgb *msg;
-
-	msg = msgb_alloc(512, "mncc hello");
-	if (!msg) {
-		LOGP(DMNCC, LOGL_ERROR, "Failed to allocate hello.\n");
-		mncc_sock_close(mncc);
-		return;
-	}
-
-	hello = (struct gsm_mncc_hello *) msgb_put(msg, sizeof(*hello));
-	hello->msg_type = MNCC_SOCKET_HELLO;
-	hello->version = MNCC_SOCK_VERSION;
-	hello->mncc_size = sizeof(struct gsm_mncc);
-	hello->data_frame_size = sizeof(struct gsm_data_frame);
-	hello->called_offset = offsetof(struct gsm_mncc, called);
-	hello->signal_offset = offsetof(struct gsm_mncc, signal);
-	hello->emergency_offset = offsetof(struct gsm_mncc, emergency);
-
-	msgb_enqueue(&mncc->net->upqueue, msg);
-	mncc->conn_bfd.when |= BSC_FD_WRITE;
-}
-
-/* accept a new connection */
-static int mncc_sock_accept(struct osmo_fd *bfd, unsigned int flags)
-{
-	struct mncc_sock_state *state = (struct mncc_sock_state *)bfd->data;
-	struct osmo_fd *conn_bfd = &state->conn_bfd;
-	struct sockaddr_un un_addr;
-	socklen_t len;
-	int rc;
-
-	len = sizeof(un_addr);
-	rc = accept(bfd->fd, (struct sockaddr *) &un_addr, &len);
-	if (rc < 0) {
-		LOGP(DMNCC, LOGL_ERROR, "Failed to accept a new connection\n");
-		return -1;
-	}
-
-	if (conn_bfd->fd >= 0) {
-		LOGP(DMNCC, LOGL_NOTICE, "MNCC app connects but we already have "
-			"another active connection ?!?\n");
-		/* We already have one MNCC app connected, this is all we support */
-		state->listen_bfd.when &= ~BSC_FD_READ;
-		close(rc);
-		return 0;
-	}
-
-	conn_bfd->fd = rc;
-	conn_bfd->when = BSC_FD_READ;
-	conn_bfd->cb = mncc_sock_cb;
-	conn_bfd->data = state;
-
-	if (osmo_fd_register(conn_bfd) != 0) {
-		LOGP(DMNCC, LOGL_ERROR, "Failed to register new connection fd\n");
-		close(conn_bfd->fd);
-		conn_bfd->fd = -1;
-		return -1;
-	}
-
-	LOGP(DMNCC, LOGL_NOTICE, "MNCC Socket has connection with external "
-		"call control application\n");
-
-	queue_hello(state);
-	return 0;
-}
-
-
-int mncc_sock_init(struct gsm_network *net, const char *sock_path)
-{
-	struct mncc_sock_state *state;
-	struct osmo_fd *bfd;
-	int rc;
-
-	state = talloc_zero(tall_bsc_ctx, struct mncc_sock_state);
-	if (!state)
-		return -ENOMEM;
-
-	state->net = net;
-	state->conn_bfd.fd = -1;
-
-	bfd = &state->listen_bfd;
-
-	bfd->fd = osmo_sock_unix_init(SOCK_SEQPACKET, 0, sock_path,
-		OSMO_SOCK_F_BIND);
-	if (bfd->fd < 0) {
-		LOGP(DMNCC, LOGL_ERROR, "Could not create unix socket: %s: %s\n",
-		     sock_path, strerror(errno));
-		talloc_free(state);
-		return -1;
-	}
-
-	bfd->when = BSC_FD_READ;
-	bfd->cb = mncc_sock_accept;
-	bfd->data = state;
-
-	rc = osmo_fd_register(bfd);
-	if (rc < 0) {
-		LOGP(DMNCC, LOGL_ERROR, "Could not register listen fd: %d\n", rc);
-		close(bfd->fd);
-		talloc_free(state);
-		return rc;
-	}
-
-	net->mncc_state = state;
-
-	LOGP(DMNCC, LOGL_NOTICE, "MNCC socket at %s\n", sock_path);
-	return 0;
-}
diff --git a/src/libmsc/msc_ifaces.c b/src/libmsc/msc_ifaces.c
deleted file mode 100644
index 262bf98..0000000
--- a/src/libmsc/msc_ifaces.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/* Implementation for MSC decisions which interface to send messages out on. */
-
-/* (C) 2016 by sysmocom s.m.f.c GmbH <info@sysmocom.de>
- *
- * 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/>.
- */
-
-#include <osmocom/core/logging.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/msc_ifaces.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/transaction.h>
-#include <openbsc/mgcp.h>
-#include <openbsc/mgcpgw_client.h>
-#include <openbsc/vlr.h>
-#include <openbsc/a_iface.h>
-
-#include "../../bscconfig.h"
-
-#ifdef BUILD_IU
-#include <osmocom/ranap/iu_client.h>
-extern struct msgb *ranap_new_msg_rab_assign_voice(uint8_t rab_id,
-						   uint32_t rtp_ip,
-						   uint16_t rtp_port,
-						   bool use_x213_nsap);
-#else
-#include <openbsc/iu_dummy.h>
-#endif /* BUILD_IU */
-
-static int msc_tx(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	if (!conn)
-		return -EINVAL;
-	if (!msg)
-		return -EINVAL;
-
-	DEBUGP(DMSC, "msc_tx %u bytes to %s via %s\n",
-	       msg->len, vlr_subscr_name(conn->vsub),
-	       ran_type_name(conn->via_ran));
-	switch (conn->via_ran) {
-	case RAN_GERAN_A:
-		msg->dst = conn;
-		return a_iface_tx_dtap(msg);
-
-	case RAN_UTRAN_IU:
-		msg->dst = conn->iu.ue_ctx;
-		return ranap_iu_tx(msg, 0);
-
-	default:
-		LOGP(DMSC, LOGL_ERROR,
-		     "msc_tx(): conn->via_ran invalid (%d)\n",
-		     conn->via_ran);
-		return -1;
-	}
-}
-
-
-int msc_tx_dtap(struct gsm_subscriber_connection *conn,
-		struct msgb *msg)
-{
-	return msc_tx(conn, msg);
-}
-
-
-/* 9.2.5 CM service accept */
-int msc_gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn)
-{
-	struct msgb *msg;
-	struct gsm48_hdr *gh;
-
-	if (!conn)
-		return -EINVAL;
-
-	msg = gsm48_msgb_alloc_name("GSM 04.08 SERV ACC");
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	gh->proto_discr = GSM48_PDISC_MM;
-	gh->msg_type = GSM48_MT_MM_CM_SERV_ACC;
-
-	DEBUGP(DMM, "-> CM SERVICE ACCEPT %s\n",
-	       vlr_subscr_name(conn->vsub));
-
-	return msc_tx_dtap(conn, msg);
-}
-
-/* 9.2.6 CM service reject */
-int msc_gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
-			     enum gsm48_reject_value value)
-{
-	struct msgb *msg;
-
-	if (!conn)
-		return -EINVAL;
-
-	conn->received_cm_service_request = false;
-
-	msg = gsm48_create_mm_serv_rej(value);
-	if (!msg) {
-		LOGP(DMM, LOGL_ERROR, "Failed to allocate CM Service Reject.\n");
-		return -1;
-	}
-
-	DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
-
-	return msc_tx_dtap(conn, msg);
-}
-
-int msc_tx_common_id(struct gsm_subscriber_connection *conn)
-{
-	if (!conn)
-		return -EINVAL;
-
-	/* Common ID is only sent over IuCS */
-	if (conn->via_ran != RAN_UTRAN_IU) {
-		LOGP(DMM, LOGL_INFO,
-		     "%s: Asked to transmit Common ID, but skipping"
-		     " because this is not on UTRAN\n",
-		     vlr_subscr_name(conn->vsub));
-		return 0;
-	}
-
-	DEBUGP(DIUCS, "%s: tx CommonID %s\n",
-	       vlr_subscr_name(conn->vsub), conn->vsub->imsi);
-	return ranap_iu_tx_common_id(conn->iu.ue_ctx, conn->vsub->imsi);
-}
-
-static int iu_rab_act_cs(struct ranap_ue_conn_ctx *uectx, uint8_t rab_id,
-			 uint32_t rtp_ip, uint16_t rtp_port)
-{
-#ifdef BUILD_IU
-	struct msgb *msg;
-	bool use_x213_nsap;
-	uint32_t conn_id = uectx->conn_id;
-
-	use_x213_nsap = (uectx->rab_assign_addr_enc == RANAP_NSAP_ADDR_ENC_X213);
-
-	LOGP(DIUCS, LOGL_DEBUG, "Assigning RAB: conn_id=%u, rab_id=%d,"
-	     " rtp=%x:%u, use_x213_nsap=%d\n", conn_id, rab_id, rtp_ip,
-	     rtp_port, use_x213_nsap);
-
-	msg = ranap_new_msg_rab_assign_voice(rab_id, rtp_ip, rtp_port,
-					     use_x213_nsap);
-	msg->l2h = msg->data;
-
-	if (ranap_iu_rab_act(uectx, msg))
-		LOGP(DIUCS, LOGL_ERROR, "Failed to send RAB Assignment:"
-		     " conn_id=%d rab_id=%d rtp=%x:%u\n",
-		     conn_id, rab_id, rtp_ip, rtp_port);
-	return 0;
-#else
-	LOGP(DMSC, LOGL_ERROR, "Cannot send Iu RAB Assignment: built without Iu support\n");
-	return -ENOTSUP;
-#endif
-}
-
-static void mgcp_response_rab_act_cs_crcx(struct mgcp_response *r, void *priv)
-{
-	struct gsm_trans *trans = priv;
-	struct gsm_subscriber_connection *conn = trans->conn;
-	uint32_t rtp_ip;
-	int rc;
-
-	if (r->head.response_code != 200) {
-		LOGP(DMGCP, LOGL_ERROR,
-		     "MGCPGW response yields error: %d %s\n",
-		     r->head.response_code, r->head.comment);
-		goto rab_act_cs_error;
-	}
-
-	rc = mgcp_response_parse_params(r);
-	if (rc) {
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Cannot parse MGCP response, for %s\n",
-		     vlr_subscr_name(trans->vsub));
-		goto rab_act_cs_error;
-	}
-
-	conn->rtp.port_cn = r->audio_port;
-
-	rtp_ip = mgcpgw_client_remote_addr_n(conn->network->mgcpgw.client);
-
-	if (trans->conn->via_ran == RAN_UTRAN_IU) {
-		/* Assign a voice channel via RANAP on 3G */
-		if (iu_rab_act_cs(conn->iu.ue_ctx, conn->iu.rab_id, rtp_ip, conn->rtp.port_subscr))
-			goto rab_act_cs_error;
-	} else if (trans->conn->via_ran == RAN_GERAN_A) {
-		/* Assign a voice channel via A on 2G */
-		if (a_iface_tx_assignment(trans))
-			goto rab_act_cs_error;
-	} else
-		goto rab_act_cs_error;
-
-	/* Respond back to MNCC (if requested) */
-	if (trans->tch_rtp_create) {
-		if (gsm48_tch_rtp_create(trans))
-			goto rab_act_cs_error;
-	}
-	return;
-
-rab_act_cs_error:
-	/* FIXME abort call, invalidate conn, ... */
-	LOGP(DMSC, LOGL_ERROR, "%s: failure during assignment\n",
-	     vlr_subscr_name(trans->vsub));
-	return;
-}
-
-int msc_call_assignment(struct gsm_trans *trans)
-{
-	struct gsm_subscriber_connection *conn;
-	struct mgcpgw_client *mgcp;
-	struct msgb *msg;
-	uint16_t bts_base;
-
-	if (!trans)
-		return -EINVAL;
-	if (!trans->conn)
-		return -EINVAL;
-
-	conn = trans->conn;
-	mgcp = conn->network->mgcpgw.client;
-
-#ifdef BUILD_IU
-	/* FIXME: HACK. where to scope the RAB Id? At the conn / subscriber / ranap_ue_conn_ctx? */
-	static uint8_t next_iu_rab_id = 1;
-	if (conn->via_ran == RAN_UTRAN_IU)
-		conn->iu.rab_id = next_iu_rab_id ++;
-#endif
-
-	conn->rtp.mgcp_rtp_endpoint =
-		mgcpgw_client_next_endpoint(conn->network->mgcpgw.client);
-
-	/* This will calculate the port we assign to the BTS via AoIP
-	 * assignment command (or rab-assignment on 3G) The BTS will send
-	 * its RTP traffic to that port on the MGCPGW side. The MGCPGW only
-	 * gets the endpoint ID via the CRCX. It will do the same calculation
-	 * on his side too to get knowledge of the rtp port. */
-	bts_base = mgcp->actual.bts_base;
-	conn->rtp.port_subscr = bts_base + 2 * conn->rtp.mgcp_rtp_endpoint;
-
-	/* Establish the RTP stream first as looping back to the originator.
-	 * The MDCX will patch through to the counterpart. TODO: play a ring
-	 * tone instead. */
-	msg = mgcp_msg_crcx(mgcp, conn->rtp.mgcp_rtp_endpoint,
-			    conn->rtp.mgcp_rtp_endpoint, MGCP_CONN_LOOPBACK);
-	return mgcpgw_client_tx(mgcp, msg, mgcp_response_rab_act_cs_crcx, trans);
-}
-
-static void mgcp_response_bridge_mdcx(struct mgcp_response *r, void *priv);
-
-static void mgcp_bridge(struct gsm_trans *from, struct gsm_trans *to,
-			enum bridge_state state,
-			enum mgcp_connection_mode mode)
-{
-	struct gsm_subscriber_connection *conn1 = from->conn;
-	struct gsm_subscriber_connection *conn2 = to->conn;
-	struct mgcpgw_client *mgcp = conn1->network->mgcpgw.client;
-	const char *ip;
-	struct msgb *msg;
-
-	OSMO_ASSERT(mgcp);
-
-	from->bridge.peer = to;
-	from->bridge.state = state;
-
-	/* Loop back to the same MGCP GW */
-	ip = mgcpgw_client_remote_addr_str(mgcp);
-
-	msg = mgcp_msg_mdcx(mgcp,
-			    conn1->rtp.mgcp_rtp_endpoint,
-			    ip, conn2->rtp.port_cn,
-			    mode);
-	if (mgcpgw_client_tx(mgcp, msg, mgcp_response_bridge_mdcx, from))
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Failed to send MDCX message for %s\n",
-		     vlr_subscr_name(from->vsub));
-}
-
-static void mgcp_response_bridge_mdcx(struct mgcp_response *r, void *priv)
-{
-	struct gsm_trans *trans = priv;
-	struct gsm_trans *peer = trans->bridge.peer;
-
-	switch (trans->bridge.state) {
-	case BRIDGE_STATE_LOOPBACK_PENDING:
-		trans->bridge.state = BRIDGE_STATE_LOOPBACK_ESTABLISHED;
-
-		switch (peer->bridge.state) {
-		case BRIDGE_STATE_LOOPBACK_PENDING:
-			/* Wait until the other is done as well. */
-			return;
-		case BRIDGE_STATE_LOOPBACK_ESTABLISHED:
-			/* Now that both are in loopback, switch both to
-			 * forwarding. */
-			mgcp_bridge(trans, peer, BRIDGE_STATE_BRIDGE_PENDING,
-				    MGCP_CONN_RECV_SEND);
-			mgcp_bridge(peer, trans, BRIDGE_STATE_BRIDGE_PENDING,
-				    MGCP_CONN_RECV_SEND);
-			break;
-		default:
-			LOGP(DMGCP, LOGL_ERROR,
-			     "Unexpected bridge state: %d for %s\n",
-			     trans->bridge.state, vlr_subscr_name(trans->vsub));
-			break;
-		}
-		break;
-
-	case BRIDGE_STATE_BRIDGE_PENDING:
-		trans->bridge.state = BRIDGE_STATE_BRIDGE_ESTABLISHED;
-		break;
-
-	default:
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Unexpected bridge state: %d for %s\n",
-		     trans->bridge.state, vlr_subscr_name(trans->vsub));
-		break;
-	}
-}
-
-int msc_call_connect(struct gsm_trans *trans, uint16_t port, uint32_t ip)
-{
-	/* With this function we inform the MGCP-GW  where (ip/port) it
-	 * has to send its outgoing voic traffic. The receiving end will
-	 * usually be a PBX (e.g. Asterisk). The IP-Address we tell, will
-	 * not only be used to direct the traffic, it will also be used
-	 * as a filter to make sure only RTP packets from the right
-	 * remote end will reach the BSS. This is also the reason why
-	 * inbound audio will not work until this step is performed */
-
-	/* NOTE: This function is used when msc_call_bridge(), is not
-	 * applicable. This is usually the case when an external MNCC
-	 * is in use */
-
-	struct gsm_subscriber_connection *conn;
-	struct mgcpgw_client *mgcp;
-	struct msgb *msg;
-
-	if (!trans)
-		return -EINVAL;
-	if (!trans->conn)
-		return -EINVAL;
-	if (!trans->conn->network)
-		return -EINVAL;
-	if (!trans->conn->network->mgcpgw.client)
-		return -EINVAL;
-
-	mgcp = trans->conn->network->mgcpgw.client;
-
-	struct in_addr ip_addr;
-	ip_addr.s_addr = ntohl(ip);
-
-	conn = trans->conn;
-
-	msg = mgcp_msg_mdcx(mgcp,
-			    conn->rtp.mgcp_rtp_endpoint,
-			    inet_ntoa(ip_addr), port, MGCP_CONN_RECV_SEND);
-	if (mgcpgw_client_tx(mgcp, msg, NULL, trans))
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Failed to send MDCX message for %s\n",
-		     vlr_subscr_name(trans->vsub));
-
-	return 0;
-}
-
-int msc_call_bridge(struct gsm_trans *trans1, struct gsm_trans *trans2)
-{
-	if (!trans1)
-		return -EINVAL;
-	if (!trans2)
-		return -EINVAL;
-
-	/* First setup as loopback and configure the counterparts' endpoints,
-	 * so that when transmission starts the originating addresses are
-	 * already known to be valid. The mgcp callback will continue. */
-	mgcp_bridge(trans1, trans2, BRIDGE_STATE_LOOPBACK_PENDING,
-		    MGCP_CONN_LOOPBACK);
-	mgcp_bridge(trans2, trans1, BRIDGE_STATE_LOOPBACK_PENDING,
-		    MGCP_CONN_LOOPBACK);
-
-	return 0;
-}
-
-void msc_call_release(struct gsm_trans *trans)
-{
-	struct msgb *msg;
-	struct gsm_subscriber_connection *conn;
-	struct mgcpgw_client *mgcp;
-
-	if (!trans)
-		return;
-	if (!trans->conn)
-		return;
-	if (!trans->conn->network)
-		return;
-
-	conn = trans->conn;
-	mgcp = conn->network->mgcpgw.client;
-
-	/* Send DLCX */
-	msg = mgcp_msg_dlcx(mgcp, conn->rtp.mgcp_rtp_endpoint,
-			    conn->rtp.mgcp_rtp_endpoint);
-	if (mgcpgw_client_tx(mgcp, msg, NULL, NULL))
-		LOGP(DMGCP, LOGL_ERROR,
-		     "Failed to send DLCX message for %s\n",
-		     vlr_subscr_name(trans->vsub));
-
-	/* Release endpoint id */
-	mgcpgw_client_release_endpoint(conn->rtp.mgcp_rtp_endpoint, mgcp);
-}
diff --git a/src/libmsc/msc_vty.c b/src/libmsc/msc_vty.c
deleted file mode 100644
index 6ae4529..0000000
--- a/src/libmsc/msc_vty.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/* MSC interface to quagga VTY */
-/* (C) 2016 by sysmocom s.m.f.c. GmbH <info@sysmocom.de>
- * Based on OpenBSC interface to quagga VTY (libmsc/vty_interface_layer3.c)
- * (C) 2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009-2011 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/>.
- *
- */
-
-/* NOTE: I would have liked to call this the MSC_NODE instead of the MSC_NODE,
- * but MSC_NODE already exists to configure a remote MSC for osmo-bsc. */
-
-#include "../../bscconfig.h"
-
-#include <inttypes.h>
-
-#include <osmocom/vty/command.h>
-#ifdef BUILD_IU
-#include <osmocom/ranap/iu_client.h>
-#endif
-
-#include <openbsc/vty.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/vlr.h>
-
-static struct cmd_node msc_node = {
-	MSC_NODE,
-	"%s(config-msc)# ",
-	1,
-};
-
-DEFUN(cfg_msc, cfg_msc_cmd,
-      "msc", "Configure MSC options")
-{
-	vty->node = MSC_NODE;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd,
-      "assign-tmsi",
-      "Assign TMSI during Location Updating.\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	gsmnet->vlr->cfg.assign_tmsi = true;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_msc_no_assign_tmsi, cfg_msc_no_assign_tmsi_cmd,
-      "no assign-tmsi",
-      NO_STR "Assign TMSI during Location Updating.\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	gsmnet->vlr->cfg.assign_tmsi = false;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_msc_cs7_instance_a,
-      cfg_msc_cs7_instance_a_cmd,
-      "cs7-instance-a <0-15>",
-      "Set SS7 to be used by the A-Interface.\n" "SS7 instance reference number\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	gsmnet->a.cs7_instance = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_msc_cs7_instance_iu,
-      cfg_msc_cs7_instance_iu_cmd,
-      "cs7-instance-iu <0-15>",
-      "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	gsmnet->iu.cs7_instance = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-static int config_write_msc(struct vty *vty)
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-
-	vty_out(vty, "msc%s", VTY_NEWLINE);
-	vty_out(vty, " %sassign-tmsi%s",
-		gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE);
-
-	vty_out(vty, " cs7-instance-a %u%s", gsmnet->a.cs7_instance,
-		VTY_NEWLINE);
-	vty_out(vty, " cs7-instance-iu %u%s", gsmnet->iu.cs7_instance,
-		VTY_NEWLINE);
-
-	mgcpgw_client_config_write(vty, " ");
-#ifdef BUILD_IU
-	ranap_iu_vty_config_write(vty, " ");
-#endif
-
-	return CMD_SUCCESS;
-}
-
-static int config_write_net(struct vty *vty)
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-
-	vty_out(vty, "network%s", VTY_NEWLINE);
-	vty_out(vty, " network country code %u%s", gsmnet->country_code, VTY_NEWLINE);
-	vty_out(vty, " mobile network code %u%s", gsmnet->network_code, VTY_NEWLINE);
-	vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
-	vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
-	vty_out(vty, " auth policy %s%s", gsm_auth_policy_name(gsmnet->auth_policy), VTY_NEWLINE);
-	vty_out(vty, " location updating reject cause %u%s",
-		gsmnet->reject_cause, VTY_NEWLINE);
-	vty_out(vty, " encryption a5 %u%s", gsmnet->a5_encryption, VTY_NEWLINE);
-	vty_out(vty, " rrlp mode %s%s", rrlp_mode_name(gsmnet->rrlp.mode),
-		VTY_NEWLINE);
-	vty_out(vty, " mm info %u%s", gsmnet->send_mm_info, VTY_NEWLINE);
-	if (gsmnet->tz.override != 0) {
-		if (gsmnet->tz.dst)
-			vty_out(vty, " timezone %d %d %d%s",
-				gsmnet->tz.hr, gsmnet->tz.mn, gsmnet->tz.dst,
-				VTY_NEWLINE);
-		else
-			vty_out(vty, " timezone %d %d%s",
-				gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
-	}
-	if (gsmnet->t3212 == 0)
-		vty_out(vty, " no periodic location update%s", VTY_NEWLINE);
-	else
-		vty_out(vty, " periodic location update %u%s",
-			gsmnet->t3212 * 6, VTY_NEWLINE);
-
-	return CMD_SUCCESS;
-}
-
-void msc_vty_init(struct gsm_network *msc_network)
-{
-	common_cs_vty_init(msc_network, config_write_net);
-
-	install_element(CONFIG_NODE, &cfg_msc_cmd);
-	install_node(&msc_node, config_write_msc);
-	vty_install_default(MSC_NODE);
-	install_element(MSC_NODE, &cfg_msc_assign_tmsi_cmd);
-	install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd);
-	install_element(MSC_NODE, &cfg_msc_cs7_instance_a_cmd);
-	install_element(MSC_NODE, &cfg_msc_cs7_instance_iu_cmd);
-
-	mgcpgw_client_vty_init(MSC_NODE, &msc_network->mgcpgw.conf);
-#ifdef BUILD_IU
-	ranap_iu_vty_init(MSC_NODE, &msc_network->iu.rab_assign_addr_enc);
-#endif
-}
diff --git a/src/libmsc/osmo_msc.c b/src/libmsc/osmo_msc.c
deleted file mode 100644
index 4d24f22..0000000
--- a/src/libmsc/osmo_msc.c
+++ /dev/null
@@ -1,387 +0,0 @@
-/* main MSC management code... */
-
-/*
- * (C) 2010,2013 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/>.
- *
- */
-
-#include <openbsc/osmo_msc.h>
-#include <openbsc/bsc_api.h>
-#include <openbsc/debug.h>
-#include <openbsc/transaction.h>
-#include <openbsc/db.h>
-#include <openbsc/vlr.h>
-#include <openbsc/osmo_msc.h>
-#include <openbsc/a_iface.h>
-
-#include <openbsc/gsm_04_11.h>
-
-#include "../../bscconfig.h"
-#ifdef BUILD_IU
-#include <osmocom/ranap/iu_client.h>
-#else
-#include <openbsc/iu_dummy.h>
-#endif
-
-/* Receive a SAPI-N-REJECT from BSC */
-void msc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci)
-{
-	int sapi = dlci & 0x7;
-
-	if (sapi == UM_SAPI_SMS)
-		gsm411_sapi_n_reject(conn);
-}
-
-static void subscr_conn_bump(struct gsm_subscriber_connection *conn)
-{
-	if (!conn)
-		return;
-	if (!conn->conn_fsm)
-		return;
-	if (!(conn->conn_fsm->state == SUBSCR_CONN_S_ACCEPTED
-	      || conn->conn_fsm->state == SUBSCR_CONN_S_COMMUNICATING)) {
-		DEBUGP(DMM, "%s: bump: conn still being established (%s)\n",
-		       vlr_subscr_name(conn->vsub),
-		       osmo_fsm_inst_state_name(conn->conn_fsm));
-		return;
-	}
-	osmo_fsm_inst_dispatch(conn->conn_fsm, SUBSCR_CONN_E_BUMP, NULL);
-}
-
-/* receive a Level 3 Complete message and return MSC_CONN_ACCEPT or
- * MSC_CONN_REJECT */
-int msc_compl_l3(struct gsm_subscriber_connection *conn,
-		 struct msgb *msg, uint16_t chosen_channel)
-{
-	msc_subscr_conn_get(conn);
-	gsm0408_dispatch(conn, msg);
-
-	/* Bump whether the conn wants to be closed */
-	subscr_conn_bump(conn);
-
-	/* If this should be kept, the conn->conn_fsm has placed a use_count */
-	msc_subscr_conn_put(conn);
-
-	/* Always return acceptance, because even if the conn was not accepted,
-	 * we assumed ownership of it and the caller shall not interfere with
-	 * that. We may even already have discarded the conn. */
-	return MSC_CONN_ACCEPT;
-
-#if 0
-	/*
-	 * If this is a silent call we want the channel to remain open as long as
-	 * possible and this is why we accept this connection regardless of any
-	 * pending transaction or ongoing operation.
-	 */
-	if (conn->silent_call)
-		return MSC_CONN_ACCEPT;
-	if (conn->loc_operation || conn->sec_operation || conn->anch_operation)
-		return MSC_CONN_ACCEPT;
-	if (trans_has_conn(conn))
-		return MSC_CONN_ACCEPT;
-
-	LOGP(DRR, LOGL_INFO, "MSC Complete L3: Rejecting connection.\n");
-	return MSC_CONN_REJECT;
-#endif
-}
-
-/* Receive a DTAP message from BSC */
-void msc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg)
-{
-	msc_subscr_conn_get(conn);
-	gsm0408_dispatch(conn, msg);
-
-	/* Bump whether the conn wants to be closed */
-	subscr_conn_bump(conn);
-	msc_subscr_conn_put(conn);
-}
-
-/* Receive an ASSIGNMENT COMPLETE from BSC */
-void msc_assign_compl(struct gsm_subscriber_connection *conn,
-		      uint8_t rr_cause, uint8_t chosen_channel,
-		      uint8_t encr_alg_id, uint8_t speec)
-{
-	LOGP(DRR, LOGL_DEBUG, "MSC assign complete (do nothing).\n");
-}
-
-/* Receive an ASSIGNMENT FAILURE from BSC */
-void msc_assign_fail(struct gsm_subscriber_connection *conn,
-		     uint8_t cause, uint8_t *rr_cause)
-{
-	LOGP(DRR, LOGL_DEBUG, "MSC assign failure (do nothing).\n");
-}
-
-/* Receive a CLASSMARK CHANGE from BSC */
-void msc_classmark_chg(struct gsm_subscriber_connection *conn,
-		       const uint8_t *cm2, uint8_t cm2_len,
-		       const uint8_t *cm3, uint8_t cm3_len)
-{
-	if (cm2 && cm2_len) {
-		if (cm2_len > sizeof(conn->classmark.classmark2)) {
-			LOGP(DRR, LOGL_NOTICE, "%s: classmark2 is %u bytes, truncating at %zu bytes\n",
-			     vlr_subscr_name(conn->vsub), cm2_len, sizeof(conn->classmark.classmark2));
-			cm2_len = sizeof(conn->classmark.classmark2);
-		}
-		conn->classmark.classmark2_len = cm2_len;
-		memcpy(conn->classmark.classmark2, cm2, cm2_len);
-	}
-	if (cm3 && cm3_len) {
-		if (cm3_len > sizeof(conn->classmark.classmark3)) {
-			LOGP(DRR, LOGL_NOTICE, "%s: classmark3 is %u bytes, truncating at %zu bytes\n",
-			     vlr_subscr_name(conn->vsub), cm3_len, sizeof(conn->classmark.classmark3));
-			cm3_len = sizeof(conn->classmark.classmark3);
-		}
-		conn->classmark.classmark3_len = cm3_len;
-		memcpy(conn->classmark.classmark3, cm3, cm3_len);
-	}
-}
-
-/* Receive a CIPHERING MODE COMPLETE from BSC */
-void msc_cipher_mode_compl(struct gsm_subscriber_connection *conn,
-			   struct msgb *msg, uint8_t alg_id)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
-	struct tlv_parsed tp;
-	uint8_t mi_type;
-	char imeisv[GSM48_MI_SIZE] = "";
-	struct vlr_ciph_result ciph_res = { .cause = VLR_CIPH_REJECT };
-
-	if (!gh) {
-		LOGP(DRR, LOGL_ERROR, "invalid: msgb without l3 header\n");
-		return;
-	}
-
-	if (!conn) {
-		LOGP(DRR, LOGL_ERROR,
-		     "invalid: rx Ciphering Mode Complete on NULL conn\n");
-		return;
-	}
-	if (!conn->vsub) {
-		LOGP(DRR, LOGL_ERROR,
-		     "invalid: rx Ciphering Mode Complete for NULL subscr\n");
-		return;
-	}
-
-	DEBUGP(DRR, "%s: CIPHERING MODE COMPLETE\n",
-	       vlr_subscr_name(conn->vsub));
-
-	tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
-
-	/* bearer capability */
-	if (TLVP_PRESENT(&tp, GSM48_IE_MOBILE_ID)) {
-		mi_type = TLVP_VAL(&tp, GSM48_IE_MOBILE_ID)[0] & GSM_MI_TYPE_MASK;
-		if (mi_type == GSM_MI_TYPE_IMEISV
-		    && TLVP_LEN(&tp, GSM48_IE_MOBILE_ID) > 0) {
-			gsm48_mi_to_string(imeisv, sizeof(imeisv),
-					   TLVP_VAL(&tp, GSM48_IE_MOBILE_ID),
-					   TLVP_LEN(&tp, GSM48_IE_MOBILE_ID));
-			ciph_res.imeisv = imeisv;
-		}
-	}
-
-	ciph_res.cause = VLR_CIPH_COMPL;
-	vlr_subscr_rx_ciph_res(conn->vsub, &ciph_res);
-}
-
-struct gsm_subscriber_connection *msc_subscr_con_allocate(struct gsm_network *network)
-{
-	struct gsm_subscriber_connection *conn;
-
-	conn = talloc_zero(network, struct gsm_subscriber_connection);
-	if (!conn)
-		return NULL;
-
-	conn->network = network;
-	llist_add_tail(&conn->entry, &network->subscr_conns);
-	return conn;
-}
-
-void msc_subscr_cleanup(struct vlr_subscr *vsub)
-{
-	if (!vsub)
-		return;
-	vsub->lu_fsm = NULL;
-}
-
-void msc_subscr_con_cleanup(struct gsm_subscriber_connection *conn)
-{
-	if (!conn)
-		return;
-
-	if (conn->vsub) {
-		DEBUGP(DRLL, "subscr %s: Freeing subscriber connection\n",
-		       vlr_subscr_name(conn->vsub));
-		msc_subscr_cleanup(conn->vsub);
-		vlr_subscr_put(conn->vsub);
-		conn->vsub = NULL;
-	} else
-		DEBUGP(DRLL, "Freeing subscriber connection"
-		       " with NULL subscriber\n");
-
-	if (!conn->conn_fsm)
-		return;
-
-	osmo_fsm_inst_term(conn->conn_fsm,
-			   (conn->conn_fsm->state == SUBSCR_CONN_S_RELEASED)
-				? OSMO_FSM_TERM_REGULAR
-				: OSMO_FSM_TERM_ERROR,
-			   NULL);
-}
-
-void msc_subscr_con_free(struct gsm_subscriber_connection *conn)
-{
-	if (!conn)
-		return;
-
-	msc_subscr_con_cleanup(conn);
-
-	llist_del(&conn->entry);
-	talloc_free(conn);
-}
-
-/* Receive a CLEAR REQUEST from BSC */
-int msc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
-{
-	msc_subscr_conn_close(conn, cause);
-	return 1;
-}
-
-/* MSC-level operations to be called by libbsc in NITB */
-static struct bsc_api msc_handler = {
-	.sapi_n_reject = msc_sapi_n_reject,
-	.compl_l3 = msc_compl_l3,
-	.dtap = msc_dtap,
-	.clear_request = msc_clear_request,
-	.assign_compl = msc_assign_compl,
-	.assign_fail = msc_assign_fail,
-	.classmark_chg = msc_classmark_chg,
-	.cipher_mode_compl = msc_cipher_mode_compl,
-	.conn_cleanup = msc_subscr_con_cleanup,
-};
-
-struct bsc_api *msc_bsc_api() {
-	return &msc_handler;
-}
-
-static void msc_subscr_conn_release_all(struct gsm_subscriber_connection *conn, uint32_t cause)
-{
-	if (conn->in_release)
-		return;
-	conn->in_release = true;
-
-	/* If we're closing in a middle of a trans, we need to clean up */
-	trans_conn_closed(conn);
-
-	switch (conn->via_ran) {
-	case RAN_UTRAN_IU:
-		ranap_iu_tx_release(conn->iu.ue_ctx, NULL);
-		/* FIXME: keep the conn until the Iu Release Outcome is
-		 * received from the UE, or a timeout expires. For now, the log
-		 * says "unknown UE" for each release outcome. */
-		break;
-	case RAN_GERAN_A:
-		a_iface_tx_clear_cmd(conn);
-		break;
-	default:
-		LOGP(DMM, LOGL_ERROR, "%s: Unknown RAN type, cannot tx release/clear\n",
-		     vlr_subscr_name(conn->vsub));
-		break;
-	}
-}
-
-/* If the conn->conn_fsm is still present, dispatch SUBSCR_CONN_E_CN_CLOSE
- * event to gracefully terminate the connection. If the conn_fsm is already
- * cleared, call msc_subscr_conn_release_all() to take release actions.
- * \param cause  a GSM_CAUSE_* constant, e.g. GSM_CAUSE_AUTH_FAILED.
- */
-void msc_subscr_conn_close(struct gsm_subscriber_connection *conn,
-			   uint32_t cause)
-{
-	if (!conn)
-		return;
-	if (conn->in_release) {
-		DEBUGP(DMM, "msc_subscr_conn_close(vsub=%s, cause=%u):"
-		       " already dispatching release, ignore.\n",
-		       vlr_subscr_name(conn->vsub), cause);
-		return;
-	}
-	if (!conn->conn_fsm) {
-		DEBUGP(DMM, "msc_subscr_conn_close(vsub=%s, cause=%u): no conn fsm,"
-		       " releasing directly without release event.\n",
-		       vlr_subscr_name(conn->vsub), cause);
-		/* In case of an IMSI Detach, we don't have conn_fsm. Release
-		 * anyway to ensure a timely Iu Release / BSSMAP Clear. */
-		msc_subscr_conn_release_all(conn, cause);
-		return;
-	}
-	if (conn->conn_fsm->state == SUBSCR_CONN_S_RELEASED) {
-		DEBUGP(DMM, "msc_subscr_conn_close(vsub=%s, cause=%u):"
-		       " conn fsm already releasing, ignore.\n",
-		       vlr_subscr_name(conn->vsub), cause);
-		return;
-	}
-	osmo_fsm_inst_dispatch(conn->conn_fsm, SUBSCR_CONN_E_CN_CLOSE, &cause);
-}
-
-/* increment the ref-count. Needs to be called by every user */
-struct gsm_subscriber_connection *
-_msc_subscr_conn_get(struct gsm_subscriber_connection *conn,
-		     const char *file, int line)
-{
-	OSMO_ASSERT(conn);
-
-	if (conn->in_release)
-		return NULL;
-
-	conn->use_count++;
-	LOGPSRC(DREF, LOGL_DEBUG, file, line,
-		"%s: MSC conn use + 1 == %u\n",
-		vlr_subscr_name(conn->vsub), conn->use_count);
-
-	return conn;
-}
-
-/* decrement the ref-count. Once it reaches zero, we release */
-void _msc_subscr_conn_put(struct gsm_subscriber_connection *conn,
-			  const char *file, int line)
-{
-	OSMO_ASSERT(conn);
-
-	if (conn->use_count == 0) {
-		LOGPSRC(DREF, LOGL_ERROR, file, line,
-			"%s: MSC conn use - 1 failed: is already 0\n",
-			vlr_subscr_name(conn->vsub));
-		return;
-	}
-
-	conn->use_count--;
-	LOGPSRC(DREF, LOGL_DEBUG, file, line,
-		"%s: MSC conn use - 1 == %u\n",
-		vlr_subscr_name(conn->vsub), conn->use_count);
-
-	if (conn->use_count == 0)
-		msc_subscr_con_free(conn);
-}
-
-void msc_stop_paging(struct vlr_subscr *vsub)
-{
-	DEBUGP(DPAG, "Paging can stop for %s\n", vlr_subscr_name(vsub));
-	/* tell BSCs and RNCs to stop paging? How? */
-}
diff --git a/src/libmsc/rrlp.c b/src/libmsc/rrlp.c
deleted file mode 100644
index cd3da06..0000000
--- a/src/libmsc/rrlp.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* Radio Resource LCS (Location) Protocol, GMS TS 04.31 */
-
-/* (C) 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/>.
- *
- */
-
-
-
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/signal.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/chan_alloc.h>
-
-/* RRLP msPositionReq, nsBased,
- *	Accuracy=60, Method=gps, ResponseTime=2, oneSet */
-static const uint8_t ms_based_pos_req[] = { 0x40, 0x01, 0x78, 0xa8 };
-
-/* RRLP msPositionReq, msBasedPref,
-	Accuracy=60, Method=gpsOrEOTD, ResponseTime=5, multipleSets */
-static const uint8_t ms_pref_pos_req[]  = { 0x40, 0x02, 0x79, 0x50 };
-
-/* RRLP msPositionReq, msAssistedPref,
-	Accuracy=60, Method=gpsOrEOTD, ResponseTime=5, multipleSets */
-static const uint8_t ass_pref_pos_req[] = { 0x40, 0x03, 0x79, 0x50 };
-
-static int send_rrlp_req(struct gsm_subscriber_connection *conn)
-{
-	struct gsm_network *net = conn->network;
-	const uint8_t *req;
-
-	switch (net->rrlp.mode) {
-	case RRLP_MODE_MS_BASED:
-		req = ms_based_pos_req;
-		break;
-	case RRLP_MODE_MS_PREF:
-		req = ms_pref_pos_req;
-		break;
-	case RRLP_MODE_ASS_PREF:
-		req = ass_pref_pos_req;
-		break;
-	case RRLP_MODE_NONE:
-	default:
-		return 0;
-	}
-
-	return gsm48_send_rr_app_info(conn, 0x00,
-				      sizeof(ms_based_pos_req), req);
-}
-
-static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
-			 void *handler_data, void *signal_data)
-{
-	struct vlr_subscr *vsub;
-	struct gsm_subscriber_connection *conn;
-
-	switch (signal) {
-	case S_SUBSCR_ATTACHED:
-		/* A subscriber has attached. */
-		vsub = signal_data;
-		conn = connection_for_subscr(vsub);
-		if (!conn)
-			break;
-		send_rrlp_req(conn);
-		break;
-	}
-	return 0;
-}
-
-static int paging_sig_cb(unsigned int subsys, unsigned int signal,
-			 void *handler_data, void *signal_data)
-{
-	struct paging_signal_data *psig_data = signal_data;
-
-	switch (signal) {
-	case S_PAGING_SUCCEEDED:
-		/* A subscriber has attached. */
-		send_rrlp_req(psig_data->conn);
-		break;
-	case S_PAGING_EXPIRED:
-		break;
-	}
-	return 0;
-}
-
-void on_dso_load_rrlp(void)
-{
-	osmo_signal_register_handler(SS_SUBSCR, subscr_sig_cb, NULL);
-	osmo_signal_register_handler(SS_PAGING, paging_sig_cb, NULL);
-}
diff --git a/src/libmsc/silent_call.c b/src/libmsc/silent_call.c
deleted file mode 100644
index 7af7a80..0000000
--- a/src/libmsc/silent_call.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/* GSM silent call feature */
-
-/*
- * (C) 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/>.
- *
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <osmocom/core/msgb.h>
-#include <openbsc/signal.h>
-#include <openbsc/debug.h>
-#include <openbsc/paging.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/chan_alloc.h>
-#include <openbsc/osmo_msc.h>
-
-/* paging of the requested subscriber has completed */
-static int paging_cb_silent(unsigned int hooknum, unsigned int event,
-			    struct msgb *msg, void *_conn, void *_data)
-{
-	struct gsm_subscriber_connection *conn = _conn;
-	struct scall_signal_data sigdata;
-	int rc = 0;
-
-	if (hooknum != GSM_HOOK_RR_PAGING)
-		return -EINVAL;
-
-	DEBUGP(DLSMS, "paging_cb_silent: ");
-
-	sigdata.conn = conn;
-	sigdata.data = _data;
-
-	switch (event) {
-	case GSM_PAGING_SUCCEEDED:
-#if BEFORE_MSCSPLIT
-		/* Re-enable this log output once we can obtain this information via
-		 * A-interface, see OS#2391. */
-		DEBUGPC(DLSMS, "success, using Timeslot %u on ARFCN %u\n",
-			conn->lchan->ts->nr, conn->lchan->ts->trx->arfcn);
-#endif
-		conn->silent_call = 1;
-		msc_subscr_conn_get(conn);
-		/* increment lchan reference count */
-		osmo_signal_dispatch(SS_SCALL, S_SCALL_SUCCESS, &sigdata);
-		break;
-	case GSM_PAGING_EXPIRED:
-	case GSM_PAGING_BUSY:
-	case GSM_PAGING_OOM:
-		DEBUGP(DLSMS, "expired\n");
-		osmo_signal_dispatch(SS_SCALL, S_SCALL_EXPIRED, &sigdata);
-		break;
-	default:
-		rc = -EINVAL;
-		break;
-	}
-
-	return rc;
-}
-
-#if 0
-/* receive a layer 3 message from a silent call */
-int silent_call_rx(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	/* FIXME: do something like sending it through a UDP port */
-	LOGP(DLSMS, LOGL_NOTICE, "Discarding L3 message from a silent call.\n");
-	return 0;
-}
-#endif
-
-struct msg_match {
-	uint8_t pdisc;
-	uint8_t msg_type;
-};
-
-/* list of messages that are handled inside OpenBSC, even in a silent call */
-static const struct msg_match silent_call_accept[] = {
-	{ GSM48_PDISC_MM, GSM48_MT_MM_LOC_UPD_REQUEST },
-	{ GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_REQ },
-};
-
-#if 0
-/* decide if we need to reroute a message as part of a silent call */
-int silent_call_reroute(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	uint8_t pdisc = gsm48_hdr_pdisc(gh);
-	uint8_t msg_type = gsm48_hdr_msg_type(gh);
-	int i;
-
-	/* if we're not part of a silent call, never reroute */
-	if (!conn->silent_call)
-		return 0;
-
-	/* check if we are a special message that is handled in openbsc */
-	for (i = 0; i < ARRAY_SIZE(silent_call_accept); i++) {
-		if (silent_call_accept[i].pdisc == pdisc &&
-		    silent_call_accept[i].msg_type == msg_type)
-			return 0;
-	}
-
-	/* otherwise, reroute */
-	LOGP(DLSMS, LOGL_INFO, "Rerouting L3 message from a silent call.\n");
-	return 1;
-}
-#endif
-
-
-/* initiate a silent call with a given subscriber */
-int gsm_silent_call_start(struct vlr_subscr *vsub, void *data, int type)
-{
-	struct subscr_request *req;
-
-	/* FIXME the VTY command allows selecting a silent call channel type.
-	 * This doesn't apply to the situation after MSCSPLIT with an
-	 * A-interface. */
-	req = subscr_request_conn(vsub, paging_cb_silent, data,
-				  "establish silent call");
-	return req != NULL;
-}
-
-/* end a silent call with a given subscriber */
-int gsm_silent_call_stop(struct vlr_subscr *vsub)
-{
-	struct gsm_subscriber_connection *conn;
-
-	conn = connection_for_subscr(vsub);
-	if (!conn)
-		return -EINVAL;
-
-	/* did we actually establish a silent call for this guy? */
-	if (!conn->silent_call)
-		return -EINVAL;
-
-#if BEFORE_MSCSPLIT
-	/* Re-enable this log output once we can obtain this information via
-	 * A-interface, see OS#2391. */
-	DEBUGPC(DLSMS, "Stopping silent call using Timeslot %u on ARFCN %u\n",
-		conn->lchan->ts->nr, conn->lchan->ts->trx->arfcn);
-#endif
-
-	conn->silent_call = 0;
-	msc_subscr_conn_put(conn);
-
-	return 0;
-}
diff --git a/src/libmsc/smpp_openbsc.c b/src/libmsc/smpp_openbsc.c
deleted file mode 100644
index 431cb4d..0000000
--- a/src/libmsc/smpp_openbsc.c
+++ /dev/null
@@ -1,794 +0,0 @@
-/* OpenBSC SMPP 3.4 interface, SMSC-side implementation */
-
-/* (C) 2012-2013 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/>.
- */
-
-
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdint.h>
-#include <errno.h>
-
-#include <smpp34.h>
-#include <smpp34_structs.h>
-#include <smpp34_params.h>
-
-#include <osmocom/core/utils.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/logging.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/gsm/protocol/gsm_04_11.h>
-#include <osmocom/gsm/protocol/smpp34_osmocom.h>
-
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/debug.h>
-#include <openbsc/db.h>
-#include <openbsc/gsm_04_11.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/signal.h>
-#include <openbsc/transaction.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/chan_alloc.h>
-#include <openbsc/vlr.h>
-
-#include "smpp_smsc.h"
-
-/*! \brief find vlr_subscr for a given SMPP NPI/TON/Address */
-static struct vlr_subscr *subscr_by_dst(struct gsm_network *net,
-					    uint8_t npi, uint8_t ton,
-					    const char *addr)
-{
-	struct vlr_subscr *vsub = NULL;
-
-	switch (npi) {
-	case NPI_Land_Mobile_E212:
-		vsub = vlr_subscr_find_by_imsi(net->vlr, addr);
-		break;
-	case NPI_ISDN_E163_E164:
-	case NPI_Private:
-		vsub = vlr_subscr_find_by_msisdn(net->vlr, addr);
-		break;
-	default:
-		LOGP(DSMPP, LOGL_NOTICE, "Unsupported NPI: %u\n", npi);
-		break;
-	}
-
-	log_set_context(LOG_CTX_VLR_SUBSCR, vsub);
-	return vsub;
-}
-
-static int smpp34_submit_tlv_msg_payload(const struct tlv_t *t,
-					 const struct submit_sm_t *submit,
-					 const uint8_t **sms_msg,
-					 unsigned int *sms_msg_len)
-{
-	if (submit->sm_length) {
-		LOGP(DLSMS, LOGL_ERROR,
-		     "SMPP cannot have payload in TLV _and_ in the header\n");
-		return -1;
-	}
-	*sms_msg = t->value.octet;
-	*sms_msg_len = t->length;
-
-	return 0;
-}
-
-/*! \brief convert from submit_sm_t to gsm_sms */
-static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net,
-			 const struct submit_sm_t *submit)
-{
-	const uint8_t *sms_msg = NULL;
-	unsigned int sms_msg_len = 0;
-	struct vlr_subscr *dest;
-	uint16_t msg_ref = 0;
-	struct gsm_sms *sms;
-	struct tlv_t *t;
-	int mode;
-
-	dest = subscr_by_dst(net, submit->dest_addr_npi,
-			     submit->dest_addr_ton,
-			     (const char *)submit->destination_addr);
-	if (!dest) {
-		LOGP(DLSMS, LOGL_NOTICE, "SMPP SUBMIT-SM for unknown subscriber: "
-		     "%s (NPI=%u)\n", submit->destination_addr,
-		     submit->dest_addr_npi);
-		return ESME_RINVDSTADR;
-	}
-
-	smpp34_tlv_for_each(t, submit->tlv) {
-		switch (t->tag) {
-		case TLVID_message_payload:
-			if (smpp34_submit_tlv_msg_payload(t, submit, &sms_msg,
-							  &sms_msg_len) < 0) {
-				vlr_subscr_put(dest);
-				return ESME_ROPTPARNOTALLWD;
-			}
-			break;
-		case TLVID_user_message_reference:
-			msg_ref = t->value.val16;
-			break;
-		default:
-			break;
-		}
-	}
-
-	if (!sms_msg) {
-		if (submit->sm_length > 0 && submit->sm_length < 255) {
-			sms_msg = submit->short_message;
-			sms_msg_len = submit->sm_length;
-		} else {
-			LOGP(DLSMS, LOGL_ERROR,
-			     "SMPP neither message payload nor valid sm_length.\n");
-			vlr_subscr_put(dest);
-			return ESME_RINVPARLEN;
-		}
-	}
-
-	sms = sms_alloc();
-	sms->source = SMS_SOURCE_SMPP;
-	sms->smpp.sequence_nr = submit->sequence_number;
-	sms->status_rep_req = submit->registered_delivery;
-	sms->msg_ref = msg_ref;
-
-	/* fill in the destination address */
-	sms->receiver = dest;
-	sms->dst.ton = submit->dest_addr_ton;
-	sms->dst.npi = submit->dest_addr_npi;
-	osmo_strlcpy(sms->dst.addr, dest->msisdn, sizeof(sms->dst.addr));
-
-	/* fill in the source address */
-	sms->src.ton = submit->source_addr_ton;
-	sms->src.npi = submit->source_addr_npi;
-	osmo_strlcpy(sms->src.addr, (char *)submit->source_addr,
-		     sizeof(sms->src.addr));
-
-	if (submit->esm_class == SMPP34_DELIVERY_ACK)
-		sms->is_report = true;
-
-	if (submit->esm_class & SMPP34_UDHI_IND)
-		sms->ud_hdr_ind = 1;
-
-	if (submit->esm_class & SMPP34_REPLY_PATH) {
-		sms->reply_path_req = 1;
-#warning Implement reply path
-	}
-
-	if (submit->data_coding == 0x00 ||	/* SMSC default */
-	    submit->data_coding == 0x01) {	/* GSM default alphabet */
-		sms->data_coding_scheme = GSM338_DCS_1111_7BIT;
-		mode = MODE_7BIT;
-	} else if ((submit->data_coding & 0xFC) == 0xF0) { /* 03.38 DCS default */
-		/* pass DCS 1:1 through from SMPP to GSM */
-		sms->data_coding_scheme = submit->data_coding;
-		mode = MODE_7BIT;
-	} else if (submit->data_coding == 0x02 ||
-		   submit->data_coding == 0x04) {
-		/* 8-bit binary */
-		sms->data_coding_scheme = GSM338_DCS_1111_8BIT_DATA;
-		mode = MODE_8BIT;
-	} else if ((submit->data_coding & 0xFC) == 0xF4) { /* 03.38 DCS 8bit */
-		/* pass DCS 1:1 through from SMPP to GSM */
-		sms->data_coding_scheme = submit->data_coding;
-		mode = MODE_8BIT;
-	} else if (submit->data_coding == 0x08) {
-		/* UCS-2 */
-		sms->data_coding_scheme = (2 << 2);
-		mode = MODE_8BIT;
-	} else {
-		sms_free(sms);
-		LOGP(DLSMS, LOGL_ERROR, "SMPP Unknown Data Coding 0x%02x\n",
-			submit->data_coding);
-		return ESME_RUNKNOWNERR;
-	}
-
-	if (mode == MODE_7BIT) {
-		uint8_t ud_len = 0, padbits = 0;
-		sms->data_coding_scheme = GSM338_DCS_1111_7BIT;
-		if (sms->ud_hdr_ind) {
-			ud_len = *sms_msg + 1;
-			printf("copying %u bytes user data...\n", ud_len);
-			memcpy(sms->user_data, sms_msg,
-				OSMO_MIN(ud_len, sizeof(sms->user_data)));
-			sms_msg += ud_len;
-			sms_msg_len -= ud_len;
-			padbits = 7 - (ud_len % 7);
-		}
-		gsm_septets2octets(sms->user_data+ud_len, sms_msg,
-				   sms_msg_len, padbits);
-		sms->user_data_len = (ud_len*8 + padbits)/7 + sms_msg_len;/* SEPTETS */
-		/* FIXME: sms->text */
-	} else {
-		memcpy(sms->user_data, sms_msg, sms_msg_len);
-		sms->user_data_len = sms_msg_len;
-	}
-
-	*psms = sms;
-	return ESME_ROK;
-}
-
-/*! \brief handle incoming libsmpp34 ssubmit_sm_t from remote ESME */
-int handle_smpp_submit(struct osmo_esme *esme, struct submit_sm_t *submit,
-		       struct submit_sm_resp_t *submit_r)
-{
-	struct gsm_sms *sms;
-	struct gsm_network *net = esme->smsc->priv;
-	struct sms_signal_data sig;
-	int rc = -1;
-
-	rc = submit_to_sms(&sms, net, submit);
-	if (rc != ESME_ROK) {
-		submit_r->command_status = rc;
-		return 0;
-	}
-	smpp_esme_get(esme);
-	sms->smpp.esme = esme;
-	sms->protocol_id = submit->protocol_id;
-
-	switch (submit->esm_class & SMPP34_MSG_MODE_MASK) {
-	case 0: /* default */
-	case 1: /* datagram */
-	case 3: /* store-and-forward */
-		rc = db_sms_store(sms);
-		sms_free(sms);
-		sms = NULL;
-		if (rc < 0) {
-			LOGP(DLSMS, LOGL_ERROR, "SMPP SUBMIT-SM: Unable to "
-				"store SMS in database\n");
-			submit_r->command_status = ESME_RSYSERR;
-			return 0;
-		}
-		strcpy((char *)submit_r->message_id, "msg_id_not_implemented");
-		LOGP(DLSMS, LOGL_INFO, "SMPP SUBMIT-SM: Stored in DB\n");
-
-		memset(&sig, 0, sizeof(sig));
-		osmo_signal_dispatch(SS_SMS, S_SMS_SUBMITTED, &sig);
-		rc = 0;
-		break;
-	case 2: /* forward (i.e. transaction) mode */
-		LOGP(DLSMS, LOGL_DEBUG, "SMPP SUBMIT-SM: Forwarding in "
-			"real time (Transaction/Forward mode)\n");
-		sms->smpp.transaction_mode = 1;
-		gsm411_send_sms_subscr(sms->receiver, sms);
-		rc = 1; /* don't send any response yet */
-		break;
-	}
-	return rc;
-}
-
-static void alert_all_esme(struct smsc *smsc, struct vlr_subscr *vsub,
-			   uint8_t smpp_avail_status)
-{
-	struct osmo_esme *esme;
-
-	llist_for_each_entry(esme, &smsc->esme_list, list) {
-		/* we currently send an alert notification to each ESME that is
-		 * connected, and do not require a (non-existant) delivery
-		 * pending flag to be set before,  FIXME: make this VTY
-		 * configurable */
-		if (esme->acl && esme->acl->deliver_src_imsi) {
-			smpp_tx_alert(esme, TON_Subscriber_Number,
-				      NPI_Land_Mobile_E212,
-				      vsub->imsi, smpp_avail_status);
-		} else {
-			smpp_tx_alert(esme, TON_Network_Specific,
-				      NPI_ISDN_E163_E164,
-				      vsub->msisdn, smpp_avail_status);
-		}
-	}
-}
-
-
-/*! \brief signal handler for status of attempted SMS deliveries */
-static int smpp_sms_cb(unsigned int subsys, unsigned int signal,
-			void *handler_data, void *signal_data)
-{
-	struct sms_signal_data *sig_sms = signal_data;
-	struct gsm_sms *sms = sig_sms->sms;
-	struct smsc *smsc = handler_data;
-	int rc = 0;
-
-	if (!sms)
-		return 0;
-
-	if (sms->source != SMS_SOURCE_SMPP)
-		return 0;
-
-	switch (signal) {
-	case S_SMS_MEM_EXCEEDED:
-		/* fall-through: There is no ESME_Rxxx result code to
-		 * indicate a MEMORY EXCEEDED in transaction mode back
-		 * to the ESME */
-	case S_SMS_UNKNOWN_ERROR:
-		if (sms->smpp.transaction_mode) {
-			/* Send back the SUBMIT-SM response with apropriate error */
-			LOGP(DLSMS, LOGL_INFO, "SMPP SUBMIT-SM: Error\n");
-			rc = smpp_tx_submit_r(sms->smpp.esme,
-					      sms->smpp.sequence_nr,
-					      ESME_RDELIVERYFAILURE,
-					      sms->smpp.msg_id);
-		}
-		break;
-	case S_SMS_DELIVERED:
-		/* SMS layer tells us the delivery has been completed */
-		if (sms->smpp.transaction_mode) {
-			/* Send back the SUBMIT-SM response */
-			LOGP(DLSMS, LOGL_INFO, "SMPP SUBMIT-SM: Success\n");
-			rc = smpp_tx_submit_r(sms->smpp.esme,
-					      sms->smpp.sequence_nr,
-					      ESME_ROK, sms->smpp.msg_id);
-		}
-		break;
-	case S_SMS_SMMA:
-		if (!sig_sms->trans || !sig_sms->trans->vsub) {
-			/* SMMA without a subscriber? strange... */
-			LOGP(DLSMS, LOGL_NOTICE, "SMMA without subscriber?\n");
-			break;
-		}
-
-		/* There's no real 1:1 match for SMMA in SMPP.  However,
-		 * an ALERT NOTIFICATION seems to be the most logical
-		 * choice */
-		alert_all_esme(smsc, sig_sms->trans->vsub, 0);
-		break;
-	}
-
-	return rc;
-}
-
-/*! \brief signal handler for subscriber related signals */
-static int smpp_subscr_cb(unsigned int subsys, unsigned int signal,
-			  void *handler_data, void *signal_data)
-{
-	struct vlr_subscr *vsub = signal_data;
-	struct smsc *smsc = handler_data;
-	uint8_t smpp_avail_status;
-
-	/* determine the smpp_avail_status depending on attach/detach */
-	switch (signal) {
-	case S_SUBSCR_ATTACHED:
-		smpp_avail_status = 0;
-		break;
-	case S_SUBSCR_DETACHED:
-		smpp_avail_status = 2;
-		break;
-	default:
-		return 0;
-	}
-
-	alert_all_esme(smsc, vsub, smpp_avail_status);
-
-	return 0;
-}
-
-/* GSM 03.38 6.2.1 Character expanding (no decode!) */
-static int gsm_7bit_expand(char *text, const uint8_t *user_data, uint8_t septet_l, uint8_t ud_hdr_ind)
-{
-	int i = 0;
-	int shift = 0;
-	uint8_t c;
-
-	/* skip the user data header */
-	if (ud_hdr_ind) {
-		/* get user data header length + 1 (for the 'user data header length'-field) */
-		shift = ((user_data[0] + 1) * 8) / 7;
-		if ((((user_data[0] + 1) * 8) % 7) != 0)
-			shift++;
-		septet_l = septet_l - shift;
-	}
-
-	for (i = 0; i < septet_l; i++) {
-		c =
-			((user_data[((i + shift) * 7 + 7) >> 3] <<
-			  (7 - (((i + shift) * 7 + 7) & 7))) |
-			 (user_data[((i + shift) * 7) >> 3] >>
-			  (((i + shift) * 7) & 7))) & 0x7f;
-
-		*(text++) = c;
-	}
-
-	*text = '\0';
-
-	return i;
-}
-
-
-/* FIXME: libsmpp34 helpers, they should  be part of libsmpp34! */
-void append_tlv(tlv_t **req_tlv, uint16_t tag,
-	        const uint8_t *data, uint16_t len)
-{
-	tlv_t tlv;
-
-	memset(&tlv, 0, sizeof(tlv));
-	tlv.tag = tag;
-	tlv.length = len;
-	memcpy(tlv.value.octet, data, tlv.length);
-	build_tlv(req_tlv, &tlv);
-}
-void append_tlv_u8(tlv_t **req_tlv, uint16_t tag, uint8_t val)
-{
-	tlv_t tlv;
-
-	memset(&tlv, 0, sizeof(tlv));
-	tlv.tag = tag;
-	tlv.length = 1;
-	tlv.value.val08 = val;
-	build_tlv(req_tlv, &tlv);
-}
-void append_tlv_u16(tlv_t **req_tlv, uint16_t tag, uint16_t val)
-{
-	tlv_t tlv;
-
-	memset(&tlv, 0, sizeof(tlv));
-	tlv.tag = tag;
-	tlv.length = 2;
-	tlv.value.val16 = val;
-	build_tlv(req_tlv, &tlv);
-}
-
-#if BEFORE_MSCSPLIT
-/* We currently have no lchan information. Re-add after A-interface, see OS#2390. */
-/* Append the Osmocom vendor-specific additional TLVs to a SMPP msg */
-static void append_osmo_tlvs(tlv_t **req_tlv, const struct gsm_lchan *lchan)
-{
-	int idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep),
-				   lchan->meas_rep_idx, 1);
-	const struct gsm_meas_rep *mr = &lchan->meas_rep[idx];
-	const struct gsm_meas_rep_unidir *ul_meas = &mr->ul;
-	const struct gsm_meas_rep_unidir *dl_meas = &mr->dl;
-
-	/* Osmocom vendor-specific SMPP34 extensions */
-	append_tlv_u16(req_tlv, TLVID_osmo_arfcn, lchan->ts->trx->arfcn);
-	if (mr->flags & MEAS_REP_F_MS_L1) {
-		uint8_t ms_dbm;
-		append_tlv_u8(req_tlv, TLVID_osmo_ta, mr->ms_l1.ta);
-		ms_dbm = ms_pwr_dbm(lchan->ts->trx->bts->band, mr->ms_l1.pwr);
-		append_tlv_u8(req_tlv, TLVID_osmo_ms_l1_txpwr, ms_dbm);
-	} else if (mr->flags & MEAS_REP_F_MS_TO) /* Save Timing Offset field = MS Timing Offset + 63 */
-		append_tlv_u8(req_tlv, TLVID_osmo_ta, mr->ms_timing_offset + 63);
-
-	append_tlv_u16(req_tlv, TLVID_osmo_rxlev_ul,
-		       rxlev2dbm(ul_meas->full.rx_lev));
-	append_tlv_u8(req_tlv, TLVID_osmo_rxqual_ul, ul_meas->full.rx_qual);
-
-	if (mr->flags & MEAS_REP_F_DL_VALID) {
-		append_tlv_u16(req_tlv, TLVID_osmo_rxlev_dl,
-			       rxlev2dbm(dl_meas->full.rx_lev));
-		append_tlv_u8(req_tlv, TLVID_osmo_rxqual_dl,
-			      dl_meas->full.rx_qual);
-	}
-
-	if (lchan->conn && lchan->conn->vsub) {
-		struct vlr_subscr *vsub = lchan->conn->vsub;
-		size_t imei_len = strlen(vsub->imei);
-		if (imei_len)
-			append_tlv(req_tlv, TLVID_osmo_imei,
-				   (uint8_t *)vsub->imei, imei_len+1);
-	}
-}
-#endif
-
-struct {
-	uint32_t smpp_status_code;
-	uint8_t gsm411_cause;
-} smpp_to_gsm411_err_array[] = {
-
-	/* Seems like most phones don't care about the failure cause,
-	 * although some will display a different notification for
-	 * GSM411_RP_CAUSE_MO_NUM_UNASSIGNED
-	 * Some provoke a display of "Try again later"
-	 * while others a more definitive "Message sending failed"
-	 */
-
-	{ ESME_RSYSERR, 	GSM411_RP_CAUSE_MO_DEST_OUT_OF_ORDER	},
-	{ ESME_RINVDSTADR,	GSM411_RP_CAUSE_MO_NUM_UNASSIGNED	},
-	{ ESME_RMSGQFUL,	GSM411_RP_CAUSE_MO_CONGESTION		},
-	{ ESME_RINVSRCADR,	GSM411_RP_CAUSE_MO_SMS_REJECTED		},
-	{ ESME_RINVMSGID,	GSM411_RP_CAUSE_INV_TRANS_REF		}
-};
-
-static int smpp_to_gsm411_err(uint32_t smpp_status_code, int *gsm411_cause)
-{
-	int i;
-	for (i = 0; i < ARRAY_SIZE(smpp_to_gsm411_err_array); i++) {
-		if (smpp_to_gsm411_err_array[i].smpp_status_code != smpp_status_code)
-			continue;
-		*gsm411_cause = smpp_to_gsm411_err_array[i].gsm411_cause;
-		return 0;
-	}
-	return -1;
-}
-
-static void smpp_cmd_free(struct osmo_smpp_cmd *cmd)
-{
-	osmo_timer_del(&cmd->response_timer);
-	llist_del(&cmd->list);
-	vlr_subscr_put(cmd->vsub);
-	talloc_free(cmd);
-}
-
-void smpp_cmd_flush_pending(struct osmo_esme *esme)
-{
-	struct osmo_smpp_cmd *cmd, *next;
-
-	llist_for_each_entry_safe(cmd, next, &esme->smpp_cmd_list, list)
-		smpp_cmd_free(cmd);
-}
-
-void smpp_cmd_ack(struct osmo_smpp_cmd *cmd)
-{
-	struct gsm_subscriber_connection *conn;
-	struct gsm_trans *trans;
-
-	if (cmd->is_report)
-		goto out;
-
-	conn = connection_for_subscr(cmd->vsub);
-	if (!conn) {
-		LOGP(DSMPP, LOGL_ERROR, "No connection to subscriber anymore\n");
-		goto out;
-	}
-
-	trans = trans_find_by_id(conn, GSM48_PDISC_SMS, cmd->gsm411_trans_id);
-	if (!trans) {
-		LOGP(DSMPP, LOGL_ERROR, "GSM transaction %u is gone\n",
-		     cmd->gsm411_trans_id);
-		goto out;
-	}
-
-	gsm411_send_rp_ack(trans, cmd->gsm411_msg_ref);
-out:
-	smpp_cmd_free(cmd);
-}
-
-void smpp_cmd_err(struct osmo_smpp_cmd *cmd, uint32_t status)
-{
-	struct gsm_subscriber_connection *conn;
-	struct gsm_trans *trans;
-	int gsm411_cause;
-
-	if (cmd->is_report)
-		goto out;
-
-	conn = connection_for_subscr(cmd->vsub);
-	if (!conn) {
-		LOGP(DSMPP, LOGL_ERROR, "No connection to subscriber anymore\n");
-		goto out;
-	}
-
-	trans = trans_find_by_id(conn, GSM48_PDISC_SMS, cmd->gsm411_trans_id);
-	if (!trans) {
-		LOGP(DSMPP, LOGL_ERROR, "GSM transaction %u is gone\n",
-		     cmd->gsm411_trans_id);
-		goto out;
-	}
-
-	if (smpp_to_gsm411_err(status, &gsm411_cause) < 0)
-		gsm411_cause = GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
-
-	gsm411_send_rp_error(trans, cmd->gsm411_msg_ref, gsm411_cause);
-out:
-	smpp_cmd_free(cmd);
-}
-
-static void smpp_deliver_sm_cb(void *data)
-{
-	smpp_cmd_err(data, ESME_RSYSERR);
-}
-
-static int smpp_cmd_enqueue(struct osmo_esme *esme,
-			    struct vlr_subscr *vsub, struct gsm_sms *sms,
-			    uint32_t sequence_number)
-{
-	struct osmo_smpp_cmd *cmd;
-
-	cmd = talloc_zero(esme, struct osmo_smpp_cmd);
-	if (!cmd)
-		return -1;
-
-	cmd->sequence_nr	= sequence_number;
-	cmd->is_report		= sms->is_report;
-	cmd->gsm411_msg_ref	= sms->gsm411.msg_ref;
-	cmd->gsm411_trans_id	= sms->gsm411.transaction_id;
-	cmd->vsub		= vlr_subscr_get(vsub);
-
-	/* FIXME: No predefined value for this response_timer as specified by
-	 * SMPP 3.4 specs, section 7.2. Make this configurable? Don't forget
-	 * lchan keeps busy until we get a reply to this SMPP command. Too high
-	 * value may exhaust resources.
-	 */
-	osmo_timer_setup(&cmd->response_timer, smpp_deliver_sm_cb, cmd);
-	osmo_timer_schedule(&cmd->response_timer, 5, 0);
-	llist_add_tail(&cmd->list, &esme->smpp_cmd_list);
-
-	return 0;
-}
-
-struct osmo_smpp_cmd *smpp_cmd_find_by_seqnum(struct osmo_esme *esme,
-					      uint32_t sequence_nr)
-{
-	struct osmo_smpp_cmd *cmd;
-
-	llist_for_each_entry(cmd, &esme->smpp_cmd_list, list) {
-		if (cmd->sequence_nr == sequence_nr)
-			return cmd;
-	}
-	return NULL;
-}
-
-static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms,
-			   struct gsm_subscriber_connection *conn)
-{
-	struct deliver_sm_t deliver;
-	int mode, ret;
-	uint8_t dcs;
-
-	memset(&deliver, 0, sizeof(deliver));
-	deliver.command_length	= 0;
-	deliver.command_id	= DELIVER_SM;
-	deliver.command_status	= ESME_ROK;
-
-	strcpy((char *)deliver.service_type, "CMT");
-	if (esme->acl && esme->acl->deliver_src_imsi) {
-		deliver.source_addr_ton	= TON_Subscriber_Number;
-		deliver.source_addr_npi = NPI_Land_Mobile_E212;
-		snprintf((char *)deliver.source_addr,
-			sizeof(deliver.source_addr), "%s",
-			conn->vsub->imsi);
-	} else {
-		deliver.source_addr_ton = TON_Network_Specific;
-		deliver.source_addr_npi = NPI_ISDN_E163_E164;
-		snprintf((char *)deliver.source_addr,
-			 sizeof(deliver.source_addr), "%s",
-			 conn->vsub->msisdn);
-	}
-
-	deliver.dest_addr_ton	= sms->dst.ton;
-	deliver.dest_addr_npi	= sms->dst.npi;
-	memcpy(deliver.destination_addr, sms->dst.addr,
-		sizeof(deliver.destination_addr));
-
-	if (sms->is_report)
-		deliver.esm_class = SMPP34_DELIVERY_RECEIPT;
-	else
-		deliver.esm_class = SMPP34_DATAGRAM_MODE;
-
-	if (sms->ud_hdr_ind)
-		deliver.esm_class |= SMPP34_UDHI_IND;
-	if (sms->reply_path_req)
-		deliver.esm_class |= SMPP34_REPLY_PATH;
-
-	deliver.protocol_id 	= sms->protocol_id;
-	deliver.priority_flag	= 0;
-	if (sms->status_rep_req)
-		deliver.registered_delivery = SMPP34_DELIVERY_RECEIPT_ON;
-
-	/* Figure out SMPP DCS from TP-DCS */
-	dcs = sms->data_coding_scheme;
-	if (smpp_determine_scheme(dcs, &deliver.data_coding, &mode) == -1)
-		return -1;
-
-	/* Transparently pass on DCS via SMPP if requested */
-	if (esme->acl && esme->acl->dcs_transparent)
-		deliver.data_coding = dcs;
-
-	if (mode == MODE_7BIT) {
-		uint8_t *dst = deliver.short_message;
-
-		/* SMPP has this strange notion of putting 7bit SMS in
-		 * an octet-aligned mode */
-		if (sms->ud_hdr_ind) {
-			/* length (bytes) of UDH inside UD */
-			uint8_t udh_len = sms->user_data[0] + 1;
-
-			/* copy over the UDH */
-			memcpy(dst, sms->user_data, udh_len);
-			dst += udh_len;
-			deliver.sm_length = udh_len;
-		}
-		/* add decoded text */
-		deliver.sm_length += gsm_7bit_expand((char *)dst, sms->user_data, sms->user_data_len, sms->ud_hdr_ind);
-	} else {
-		deliver.sm_length = sms->user_data_len;
-		memcpy(deliver.short_message, sms->user_data, deliver.sm_length);
-	}
-
-#if BEFORE_MSCSPLIT
-	/* We currently have no lchan information. Re-add after A-interface, see OS#2390. */
-	if (esme->acl && esme->acl->osmocom_ext && conn->lchan)
-		append_osmo_tlvs(&deliver.tlv, conn->lchan);
-#endif
-
-	append_tlv_u16(&deliver.tlv, TLVID_user_message_reference,
-		       sms->msg_ref);
-
-	ret = smpp_tx_deliver(esme, &deliver);
-	if (ret < 0)
-		return ret;
-
-	return smpp_cmd_enqueue(esme, conn->vsub, sms,
-				deliver.sequence_number);
-}
-
-static struct smsc *g_smsc;
-
-int smpp_route_smpp_first(struct gsm_sms *sms, struct gsm_subscriber_connection *conn)
-{
-	return g_smsc->smpp_first;
-}
-
-int smpp_try_deliver(struct gsm_sms *sms,
-		     struct gsm_subscriber_connection *conn)
-{
-	struct osmo_esme *esme;
-	struct osmo_smpp_addr dst;
-	int rc;
-
-	memset(&dst, 0, sizeof(dst));
-	dst.ton = sms->dst.ton;
-	dst.npi = sms->dst.npi;
-	memcpy(dst.addr, sms->dst.addr, sizeof(dst.addr));
-
-	rc = smpp_route(g_smsc, &dst, &esme);
-	if (!rc)
-		rc = deliver_to_esme(esme, sms, conn);
-
-	return rc;
-}
-
-struct smsc *smsc_from_vty(struct vty *v)
-{
-	/* FIXME: this is ugly */
-	return g_smsc;
-}
-
-/*! \brief Allocate the OpenBSC SMPP interface struct and init VTY. */
-int smpp_openbsc_alloc_init(void *ctx)
-{
-	g_smsc = smpp_smsc_alloc_init(ctx);
-	if (!g_smsc) {
-		LOGP(DSMPP, LOGL_FATAL, "Cannot allocate smsc struct\n");
-		return -1;
-	}
-	return smpp_vty_init();
-}
-
-/*! \brief Launch the OpenBSC SMPP interface with the parameters set from VTY.
- */
-int smpp_openbsc_start(struct gsm_network *net)
-{
-	int rc;
-	g_smsc->priv = net;
-
-	/* If a VTY configuration has taken place, the values have been stored
-	 * in the smsc struct. Otherwise, use the defaults (NULL -> any, 0 ->
-	 * default SMPP port, see smpp_smsc_bind()). */
-	rc = smpp_smsc_start(g_smsc, g_smsc->bind_addr, g_smsc->listen_port);
-	if (rc < 0)
-		return rc;
-
-	rc = osmo_signal_register_handler(SS_SMS, smpp_sms_cb, g_smsc);
-	if (rc < 0)
-		return rc;
-	rc = osmo_signal_register_handler(SS_SUBSCR, smpp_subscr_cb, g_smsc);
-	if (rc < 0)
-		return rc;
-
-	return 0;
-}
-
diff --git a/src/libmsc/smpp_smsc.c b/src/libmsc/smpp_smsc.c
deleted file mode 100644
index 04afc49..0000000
--- a/src/libmsc/smpp_smsc.c
+++ /dev/null
@@ -1,1037 +0,0 @@
-/* SMPP 3.4 interface, SMSC-side implementation */
-/* (C) 2012 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/>.
- */
-
-
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdint.h>
-#include <errno.h>
-#include <limits.h>
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#include <smpp34.h>
-#include <smpp34_structs.h>
-#include <smpp34_params.h>
-
-#include <osmocom/core/utils.h>
-#include <osmocom/core/socket.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/logging.h>
-#include <osmocom/core/write_queue.h>
-#include <osmocom/core/talloc.h>
-
-#include "smpp_smsc.h"
-
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-
-/*! \brief Ugly wrapper. libsmpp34 should do this itself! */
-#define SMPP34_UNPACK(rc, type, str, data, len)		\
-	memset(str, 0, sizeof(*str));			\
-	rc = smpp34_unpack(type, str, data, len)
-
-enum emse_bind {
-	ESME_BIND_RX = 0x01,
-	ESME_BIND_TX = 0x02,
-};
-
-const struct value_string smpp_status_strs[] = {
-	{ ESME_ROK,		"No Error" },
-	{ ESME_RINVMSGLEN,	"Message Length is invalid" },
-	{ ESME_RINVCMDLEN,	"Command Length is invalid" },
-	{ ESME_RINVCMDID,	"Invalid Command ID" },
-	{ ESME_RINVBNDSTS,	"Incorrect BIND Status for given command" },
-	{ ESME_RALYBND,		"ESME Already in Bound State" },
-	{ ESME_RINVPRTFLG,	"Invalid Priority Flag" },
-	{ ESME_RINVREGDLVFLG,	"Invalid Registered Delivery Flag" },
-	{ ESME_RSYSERR,		"System Error" },
-	{ ESME_RINVSRCADR,	"Invalid Source Address" },
-	{ ESME_RINVDSTADR,	"Invalid Destination Address" },
-	{ ESME_RINVMSGID,	"Message ID is invalid" },
-	{ ESME_RBINDFAIL,	"Bind failed" },
-	{ ESME_RINVPASWD,	"Invalid Password" },
-	{ ESME_RINVSYSID,	"Invalid System ID" },
-	{ ESME_RCANCELFAIL,	"Cancel SM Failed" },
-	{ ESME_RREPLACEFAIL,	"Replace SM Failed" },
-	{ ESME_RMSGQFUL,	"Message Queue Full" },
-	{ ESME_RINVSERTYP,	"Invalid Service Type" },
-	{ ESME_RINVNUMDESTS,	"Invalid number of destinations" },
-	{ ESME_RINVDLNAME,	"Invalid Distribution List name" },
-	{ ESME_RINVDESTFLAG,	"Destination flag is invalid" },
-	{ ESME_RINVSUBREP,	"Invalid submit with replace request" },
-	{ ESME_RINVESMCLASS,	"Invalid esm_class field data" },
-	{ ESME_RCNTSUBDL,	"Cannot Submit to Distribution List" },
-	{ ESME_RSUBMITFAIL,	"submit_sm or submit_multi failed" },
-	{ ESME_RINVSRCTON,	"Invalid Source address TON" },
-	{ ESME_RINVSRCNPI,	"Invalid Sourec address NPI" },
-	{ ESME_RINVDSTTON,	"Invalid Destination address TON" },
-	{ ESME_RINVDSTNPI,	"Invalid Desetination address NPI" },
-	{ ESME_RINVSYSTYP,	"Invalid system_type field" },
-	{ ESME_RINVREPFLAG,	"Invalid replace_if_present field" },
-	{ ESME_RINVNUMMSGS,	"Invalid number of messages" },
-	{ ESME_RTHROTTLED,	"Throttling error (ESME has exceeded message limits)" },
-	{ ESME_RINVSCHED,	"Invalid Scheduled Delivery Time" },
-	{ ESME_RINVEXPIRY,	"Invalid message validity period (Expiry time)" },
-	{ ESME_RINVDFTMSGID,	"Predefined Message Invalid or Not Found" },
-	{ ESME_RX_T_APPN,	"ESME Receiver Temporary App Error Code" },
-	{ ESME_RX_P_APPN,	"ESME Receiver Permanent App Error Code" },
-	{ ESME_RX_R_APPN,	"ESME Receiver Reject Message Error Code" },
-	{ ESME_RQUERYFAIL,	"query_sm request failed" },
-	{ ESME_RINVOPTPARSTREAM,"Error in the optional part of the PDU Body" },
-	{ ESME_ROPTPARNOTALLWD,	"Optional Parameter not allowed" },
-	{ ESME_RINVPARLEN,	"Invalid Parameter Length" },
-	{ ESME_RMISSINGOPTPARAM,"Expected Optional Parameter missing" },
-	{ ESME_RINVOPTPARAMVAL,	"Invalid Optional Parameter Value" },
-	{ ESME_RDELIVERYFAILURE,"Delivery Failure (used for data_sm_resp)" },
-	{ ESME_RUNKNOWNERR,	"Unknown Error" },
-	{ 0, NULL }
-};
-
-/*! \brief compare if two SMPP addresses are equal */
-int smpp_addr_eq(const struct osmo_smpp_addr *a,
-		 const struct osmo_smpp_addr *b)
-{
-	if (a->ton == b->ton &&
-	    a->npi == b->npi &&
-	    !strcmp(a->addr, b->addr))
-		return 1;
-
-	return 0;
-}
-
-
-struct osmo_smpp_acl *smpp_acl_by_system_id(struct smsc *smsc,
-					    const char *sys_id)
-{
-	struct osmo_smpp_acl *acl;
-
-	llist_for_each_entry(acl, &smsc->acl_list, list) {
-		if (!strcmp(acl->system_id, sys_id))
-			return acl;
-	}
-
-	return NULL;
-}
-
-struct osmo_smpp_acl *smpp_acl_alloc(struct smsc *smsc, const char *sys_id)
-{
-	struct osmo_smpp_acl *acl;
-
-	if (strlen(sys_id) > SMPP_SYS_ID_LEN)
-		return NULL;
-
-	if (smpp_acl_by_system_id(smsc, sys_id))
-		return NULL;
-
-	acl = talloc_zero(smsc, struct osmo_smpp_acl);
-	if (!acl)
-		return NULL;
-
-	acl->smsc = smsc;
-	strcpy(acl->system_id, sys_id);
-	INIT_LLIST_HEAD(&acl->route_list);
-
-	llist_add_tail(&acl->list, &smsc->acl_list);
-
-	return acl;
-}
-
-void smpp_acl_delete(struct osmo_smpp_acl *acl)
-{
-	struct osmo_smpp_route *r, *r2;
-
-	llist_del(&acl->list);
-
-	/* kill any active ESMEs */
-	if (acl->esme) {
-		struct osmo_esme *esme = acl->esme;
-		osmo_fd_unregister(&esme->wqueue.bfd);
-		close(esme->wqueue.bfd.fd);
-		esme->wqueue.bfd.fd = -1;
-		esme->acl = NULL;
-		smpp_esme_put(esme);
-	}
-
-	/* delete all routes for this ACL */
-	llist_for_each_entry_safe(r, r2, &acl->route_list, list) {
-		llist_del(&r->list);
-		llist_del(&r->global_list);
-		talloc_free(r);
-	}
-
-	talloc_free(acl);
-}
-
-static struct osmo_smpp_route *route_alloc(struct osmo_smpp_acl *acl)
-{
-	struct osmo_smpp_route *r;
-
-	r = talloc_zero(acl, struct osmo_smpp_route);
-	if (!r)
-		return NULL;
-
-	llist_add_tail(&r->list, &acl->route_list);
-	llist_add_tail(&r->global_list, &acl->smsc->route_list);
-
-	return r;
-}
-
-int smpp_route_pfx_add(struct osmo_smpp_acl *acl,
-			const struct osmo_smpp_addr *pfx)
-{
-	struct osmo_smpp_route *r;
-
-	llist_for_each_entry(r, &acl->route_list, list) {
-		if (r->type == SMPP_ROUTE_PREFIX &&
-		    smpp_addr_eq(&r->u.prefix, pfx))
-			return -EEXIST;
-	}
-
-	r = route_alloc(acl);
-	if (!r)
-		return -ENOMEM;
-	r->type = SMPP_ROUTE_PREFIX;
-	r->acl = acl;
-	memcpy(&r->u.prefix, pfx, sizeof(r->u.prefix));
-
-	return 0;
-}
-
-int smpp_route_pfx_del(struct osmo_smpp_acl *acl,
-		       const struct osmo_smpp_addr *pfx)
-{
-	struct osmo_smpp_route *r, *r2;
-
-	llist_for_each_entry_safe(r, r2, &acl->route_list, list) {
-		if (r->type == SMPP_ROUTE_PREFIX &&
-		    smpp_addr_eq(&r->u.prefix, pfx)) {
-			llist_del(&r->list);
-			talloc_free(r);
-			return 0;
-		}
-	}
-
-	return -ENODEV;
-}
-
-
-/*! \brief increaes the use/reference count */
-void smpp_esme_get(struct osmo_esme *esme)
-{
-	esme->use++;
-}
-
-static void esme_destroy(struct osmo_esme *esme)
-{
-	osmo_wqueue_clear(&esme->wqueue);
-	if (esme->wqueue.bfd.fd >= 0) {
-		osmo_fd_unregister(&esme->wqueue.bfd);
-		close(esme->wqueue.bfd.fd);
-	}
-	smpp_cmd_flush_pending(esme);
-	llist_del(&esme->list);
-	talloc_free(esme);
-}
-
-static uint32_t esme_inc_seq_nr(struct osmo_esme *esme)
-{
-	esme->own_seq_nr++;
-	if (esme->own_seq_nr > 0x7fffffff)
-		esme->own_seq_nr = 1;
-
-	return esme->own_seq_nr;
-}
-
-/*! \brief decrease the use/reference count, free if it is 0 */
-void smpp_esme_put(struct osmo_esme *esme)
-{
-	esme->use--;
-	if (esme->use <= 0)
-		esme_destroy(esme);
-}
-
-/*! \brief try to find a SMPP route (ESME) for given destination */
-int smpp_route(const struct smsc *smsc, const struct osmo_smpp_addr *dest, struct osmo_esme **pesme)
-{
-	struct osmo_smpp_route *r;
-	struct osmo_smpp_acl *acl = NULL;
-
-	DEBUGP(DSMPP, "Looking up route for (%u/%u/%s)\n",
-		dest->ton, dest->npi, dest->addr);
-
-	/* search for a specific route */
-	llist_for_each_entry(r, &smsc->route_list, global_list) {
-		switch (r->type) {
-		case SMPP_ROUTE_PREFIX:
-			DEBUGP(DSMPP, "Checking prefix route (%u/%u/%s)->%s\n",
-				r->u.prefix.ton, r->u.prefix.npi, r->u.prefix.addr,
-				r->acl->system_id);
-			if (r->u.prefix.ton == dest->ton &&
-			    r->u.prefix.npi == dest->npi &&
-			    !strncmp(r->u.prefix.addr, dest->addr,
-				     strlen(r->u.prefix.addr))) {
-				DEBUGP(DSMPP, "Found prefix route ACL\n");
-				acl = r->acl;
-			}
-			break;
-		default:
-			break;
-		}
-
-		if (acl)
-			break;
-	}
-
-	if (!acl) {
-		/* check for default route */
-		if (smsc->def_route) {
-			DEBUGP(DSMPP, "Using existing default route\n");
-			acl = smsc->def_route;
-		}
-	}
-
-	if (acl && acl->esme) {
-		struct osmo_esme *esme;
-		DEBUGP(DSMPP, "ACL even has ESME, we can route to it!\n");
-		esme = acl->esme;
-		if (esme->bind_flags & ESME_BIND_RX) {
-			*pesme = esme;
-			return 0;
-		} else
-			LOGP(DSMPP, LOGL_NOTICE, "[%s] is matching route, "
-			     "but not bound for Rx, discarding MO SMS\n",
-				     esme->system_id);
-	}
-
-	*pesme = NULL;
-	if (acl)
-		return GSM48_CC_CAUSE_NETWORK_OOO;
-	else
-		return GSM48_CC_CAUSE_UNASSIGNED_NR;
-}
-
-
-/*! \brief initialize the libsmpp34 data structure for a response */
-#define INIT_RESP(type, resp, req) 		{ \
-	memset((resp), 0, sizeof(*(resp)));	  \
-	(resp)->command_length	= 0;		  \
-	(resp)->command_id	= type;		  \
-	(resp)->command_status	= ESME_ROK;	  \
-	(resp)->sequence_number	= (req)->sequence_number;	\
-}
-
-/*! \brief pack a libsmpp34 data strcutrure and send it to the ESME */
-#define PACK_AND_SEND(esme, ptr)	pack_and_send(esme, (ptr)->command_id, ptr)
-static int pack_and_send(struct osmo_esme *esme, uint32_t type, void *ptr)
-{
-	struct msgb *msg = msgb_alloc(4096, "SMPP_Tx");
-	int rc, rlen;
-	if (!msg)
-		return -ENOMEM;
-
-	rc = smpp34_pack(type, msg->tail, msgb_tailroom(msg), &rlen, ptr);
-	if (rc != 0) {
-		LOGP(DSMPP, LOGL_ERROR, "[%s] Error during smpp34_pack(): %s\n",
-		     esme->system_id, smpp34_strerror);
-		msgb_free(msg);
-		return -EINVAL;
-	}
-	msgb_put(msg, rlen);
-
-	if (osmo_wqueue_enqueue(&esme->wqueue, msg) != 0) {
-		LOGP(DSMPP, LOGL_ERROR, "[%s] Write queue full. Dropping message\n",
-		     esme->system_id);
-		msgb_free(msg);
-		return -EAGAIN;
-	}
-	return 0;
-}
-
-/*! \brief transmit a generic NACK to a remote ESME */
-static int smpp_tx_gen_nack(struct osmo_esme *esme, uint32_t seq, uint32_t status)
-{
-	struct generic_nack_t nack;
-	char buf[SMALL_BUFF];
-
-	nack.command_length = 0;
-	nack.command_id = GENERIC_NACK;
-	nack.sequence_number = seq;
-	nack.command_status = status;
-
-	LOGP(DSMPP, LOGL_ERROR, "[%s] Tx GENERIC NACK: %s\n",
-	     esme->system_id, str_command_status(status, buf));
-
-	return PACK_AND_SEND(esme, &nack);
-}
-
-/*! \brief retrieve SMPP command ID from a msgb */
-static inline uint32_t smpp_msgb_cmdid(struct msgb *msg)
-{
-	uint8_t *tmp = msgb_data(msg) + 4;
-	return ntohl(*(uint32_t *)tmp);
-}
-
-/*! \brief retrieve SMPP sequence number from a msgb */
-static inline uint32_t smpp_msgb_seq(struct msgb *msg)
-{
-	uint8_t *tmp = msgb_data(msg);
-	return ntohl(*(uint32_t *)tmp);
-}
-
-/*! \brief handle an incoming SMPP generic NACK */
-static int smpp_handle_gen_nack(struct osmo_esme *esme, struct msgb *msg)
-{
-	struct generic_nack_t nack;
-	char buf[SMALL_BUFF];
-	int rc;
-
-	SMPP34_UNPACK(rc, GENERIC_NACK, &nack, msgb_data(msg),
-			 msgb_length(msg));
-	if (rc < 0) {
-		LOGP(DSMPP, LOGL_ERROR, "[%s] Error in smpp34_unpack():%s\n",
-			esme->system_id, smpp34_strerror);
-		return rc;
-	}
-
-	LOGP(DSMPP, LOGL_ERROR, "[%s] Rx GENERIC NACK: %s\n",
-	     esme->system_id, str_command_status(nack.command_status, buf));
-
-	return 0;
-}
-
-static int _process_bind(struct osmo_esme *esme, uint8_t if_version,
-			 uint32_t bind_flags, const char *sys_id,
-			 const char *passwd)
-{
-	struct osmo_smpp_acl *acl;
-
-	if (if_version != SMPP_VERSION)
-		return ESME_RSYSERR;
-
-	if (esme->bind_flags)
-		return ESME_RALYBND;
-
-	esme->smpp_version = if_version;
-	snprintf(esme->system_id, sizeof(esme->system_id), "%s", sys_id);
-
-	acl = smpp_acl_by_system_id(esme->smsc, esme->system_id);
-	if (!esme->smsc->accept_all) {
-		if (!acl) {
-			/* This system is unknown */
-			return ESME_RINVSYSID;
-		} else {
-			if (strlen(acl->passwd) &&
-			    strcmp(acl->passwd, passwd)) {
-				return ESME_RINVPASWD;
-			}
-		}
-	}
-	if (acl) {
-		esme->acl = acl;
-		acl->esme = esme;
-	}
-
-	esme->bind_flags = bind_flags;
-
-	return ESME_ROK;
-}
-
-
-/*! \brief handle an incoming SMPP BIND RECEIVER */
-static int smpp_handle_bind_rx(struct osmo_esme *esme, struct msgb *msg)
-{
-	struct bind_receiver_t bind;
-	struct bind_receiver_resp_t bind_r;
-	int rc;
-
-	SMPP34_UNPACK(rc, BIND_RECEIVER, &bind, msgb_data(msg),
-			   msgb_length(msg));
-	if (rc < 0) {
-		LOGP(DSMPP, LOGL_ERROR, "[%s] Error in smpp34_unpack():%s\n",
-			esme->system_id, smpp34_strerror);
-		return rc;
-	}
-
-	INIT_RESP(BIND_TRANSMITTER_RESP, &bind_r, &bind);
-
-	LOGP(DSMPP, LOGL_INFO, "[%s] Rx BIND Rx from (Version %02x)\n",
-		bind.system_id, bind.interface_version);
-
-	rc = _process_bind(esme, bind.interface_version, ESME_BIND_RX,
-			   (const char *)bind.system_id, (const char *)bind.password);
-	bind_r.command_status = rc;
-
-	return PACK_AND_SEND(esme, &bind_r);
-}
-
-/*! \brief handle an incoming SMPP BIND TRANSMITTER */
-static int smpp_handle_bind_tx(struct osmo_esme *esme, struct msgb *msg)
-{
-	struct bind_transmitter_t bind;
-	struct bind_transmitter_resp_t bind_r;
-	struct tlv_t tlv;
-	int rc;
-
-	SMPP34_UNPACK(rc, BIND_TRANSMITTER, &bind, msgb_data(msg),
-			   msgb_length(msg));
-	if (rc < 0) {
-		LOGP(DSMPP, LOGL_ERROR, "[%s] Error in smpp34_unpack():%s\n",
-			esme->system_id, smpp34_strerror);
-		return rc;
-	}
-
-	INIT_RESP(BIND_TRANSMITTER_RESP, &bind_r, &bind);
-
-	LOGP(DSMPP, LOGL_INFO, "[%s] Rx BIND Tx (Version %02x)\n",
-		bind.system_id, bind.interface_version);
-
-	rc = _process_bind(esme, bind.interface_version, ESME_BIND_TX,
-			   (const char *)bind.system_id, (const char *)bind.password);
-	bind_r.command_status = rc;
-
-	/* build response */
-	snprintf((char *)bind_r.system_id, sizeof(bind_r.system_id), "%s",
-		 esme->smsc->system_id);
-
-	/* add interface version TLV */
-	tlv.tag = TLVID_sc_interface_version;
-	tlv.length = sizeof(uint8_t);
-	tlv.value.val16 = esme->smpp_version;
-	build_tlv(&bind_r.tlv, &tlv);
-
-	return PACK_AND_SEND(esme, &bind_r);
-}
-
-/*! \brief handle an incoming SMPP BIND TRANSCEIVER */
-static int smpp_handle_bind_trx(struct osmo_esme *esme, struct msgb *msg)
-{
-	struct bind_transceiver_t bind;
-	struct bind_transceiver_resp_t bind_r;
-	int rc;
-
-	SMPP34_UNPACK(rc, BIND_TRANSCEIVER, &bind, msgb_data(msg),
-			   msgb_length(msg));
-	if (rc < 0) {
-		LOGP(DSMPP, LOGL_ERROR, "[%s] Error in smpp34_unpack():%s\n",
-			esme->system_id, smpp34_strerror);
-		return rc;
-	}
-
-	INIT_RESP(BIND_TRANSCEIVER_RESP, &bind_r, &bind);
-
-	LOGP(DSMPP, LOGL_INFO, "[%s] Rx BIND Trx (Version %02x)\n",
-		bind.system_id, bind.interface_version);
-
-	rc = _process_bind(esme, bind.interface_version, ESME_BIND_RX|ESME_BIND_TX,
-			   (const char *)bind.system_id, (const char *)bind.password);
-	bind_r.command_status = rc;
-
-	return PACK_AND_SEND(esme, &bind_r);
-}
-
-/*! \brief handle an incoming SMPP UNBIND */
-static int smpp_handle_unbind(struct osmo_esme *esme, struct msgb *msg)
-{
-	struct unbind_t unbind;
-	struct unbind_resp_t unbind_r;
-	int rc;
-
-	SMPP34_UNPACK(rc, UNBIND, &unbind, msgb_data(msg),
-			   msgb_length(msg));
-	if (rc < 0) {
-		LOGP(DSMPP, LOGL_ERROR, "[%s] Error in smpp34_unpack():%s\n",
-			esme->system_id, smpp34_strerror);
-		return rc;
-	}
-
-	INIT_RESP(UNBIND_RESP, &unbind_r, &unbind);
-
-	LOGP(DSMPP, LOGL_INFO, "[%s] Rx UNBIND\n", esme->system_id);
-
-	if (esme->bind_flags == 0) {
-		unbind_r.command_status = ESME_RINVBNDSTS;
-		goto err;
-	}
-
-	esme->bind_flags = 0;
-err:
-	return PACK_AND_SEND(esme, &unbind_r);
-}
-
-/*! \brief handle an incoming SMPP ENQUIRE LINK */
-static int smpp_handle_enq_link(struct osmo_esme *esme, struct msgb *msg)
-{
-	struct enquire_link_t enq;
-	struct enquire_link_resp_t enq_r;
-	int rc;
-
-	SMPP34_UNPACK(rc, ENQUIRE_LINK, &enq, msgb_data(msg),
-			   msgb_length(msg));
-	if (rc < 0) {
-		LOGP(DSMPP, LOGL_ERROR, "[%s] Error in smpp34_unpack():%s\n",
-			esme->system_id, smpp34_strerror);
-		return rc;
-	}
-
-	LOGP(DSMPP, LOGL_DEBUG, "[%s] Rx Enquire Link\n", esme->system_id);
-
-	INIT_RESP(ENQUIRE_LINK_RESP, &enq_r, &enq);
-
-	LOGP(DSMPP, LOGL_DEBUG, "[%s] Tx Enquire Link Response\n", esme->system_id);
-
-	return PACK_AND_SEND(esme, &enq_r);
-}
-
-/*! \brief send a SUBMIT-SM RESPONSE to a remote ESME */
-int smpp_tx_submit_r(struct osmo_esme *esme, uint32_t sequence_nr,
-		     uint32_t command_status, char *msg_id)
-{
-	struct submit_sm_resp_t submit_r;
-
-	memset(&submit_r, 0, sizeof(submit_r));
-	submit_r.command_length	= 0;
-	submit_r.command_id	= SUBMIT_SM_RESP;
-	submit_r.command_status	= command_status;
-	submit_r.sequence_number= sequence_nr;
-	snprintf((char *) submit_r.message_id, sizeof(submit_r.message_id), "%s", msg_id);
-
-	return PACK_AND_SEND(esme, &submit_r);
-}
-
-static const struct value_string smpp_avail_strs[] = {
-	{ 0,	"Available" },
-	{ 1,	"Denied" },
-	{ 2,	"Unavailable" },
-	{ 0,	NULL }
-};
-
-/*! \brief send an ALERT_NOTIFICATION to a remote ESME */
-int smpp_tx_alert(struct osmo_esme *esme, uint8_t ton, uint8_t npi,
-		  const char *addr, uint8_t avail_status)
-{
-	struct alert_notification_t alert;
-	struct tlv_t tlv;
-
-	memset(&alert, 0, sizeof(alert));
-	alert.command_length	= 0;
-	alert.command_id	= ALERT_NOTIFICATION;
-	alert.command_status	= ESME_ROK;
-	alert.sequence_number	= esme_inc_seq_nr(esme);
-	alert.source_addr_ton 	= ton;
-	alert.source_addr_npi	= npi;
-	snprintf((char *)alert.source_addr, sizeof(alert.source_addr), "%s", addr);
-
-	tlv.tag = TLVID_ms_availability_status;
-	tlv.length = sizeof(uint8_t);
-	tlv.value.val08 = avail_status;
-	build_tlv(&alert.tlv, &tlv);
-
-	LOGP(DSMPP, LOGL_DEBUG, "[%s] Tx ALERT_NOTIFICATION (%s/%u/%u): %s\n",
-		esme->system_id, alert.source_addr, alert.source_addr_ton,
-		alert.source_addr_npi,
-		get_value_string(smpp_avail_strs, avail_status));
-
-	return PACK_AND_SEND(esme, &alert);
-}
-
-/* \brief send a DELIVER-SM message to given ESME */
-int smpp_tx_deliver(struct osmo_esme *esme, struct deliver_sm_t *deliver)
-{
-	deliver->sequence_number = esme_inc_seq_nr(esme);
-
-	LOGP(DSMPP, LOGL_DEBUG, "[%s] Tx DELIVER-SM (from %s)\n",
-		esme->system_id, deliver->source_addr);
-
-	return PACK_AND_SEND(esme, deliver);
-}
-
-/*! \brief handle an incoming SMPP DELIVER-SM RESPONSE */
-static int smpp_handle_deliver_resp(struct osmo_esme *esme, struct msgb *msg)
-{
-	struct deliver_sm_resp_t deliver_r;
-	struct osmo_smpp_cmd *cmd;
-	int rc;
-
-	memset(&deliver_r, 0, sizeof(deliver_r));
-	SMPP34_UNPACK(rc, DELIVER_SM_RESP, &deliver_r, msgb_data(msg),
-			   msgb_length(msg));
-	if (rc < 0) {
-		LOGP(DSMPP, LOGL_ERROR, "[%s] Error in smpp34_unpack():%s\n",
-			esme->system_id, smpp34_strerror);
-		return rc;
-	}
-
-	cmd = smpp_cmd_find_by_seqnum(esme, deliver_r.sequence_number);
-	if (!cmd) {
-		LOGP(DSMPP, LOGL_ERROR, "[%s] Rx DELIVER-SM RESP !? (%s)\n",
-			esme->system_id, get_value_string(smpp_status_strs,
-						  deliver_r.command_status));
-		return -1;
-	}
-
-	if (deliver_r.command_status == ESME_ROK)
-		smpp_cmd_ack(cmd);
-	else
-		smpp_cmd_err(cmd, deliver_r.command_status);
-
-	LOGP(DSMPP, LOGL_INFO, "[%s] Rx DELIVER-SM RESP (%s)\n",
-		esme->system_id, get_value_string(smpp_status_strs,
-						  deliver_r.command_status));
-
-	return 0;
-}
-
-/*! \brief handle an incoming SMPP SUBMIT-SM */
-static int smpp_handle_submit(struct osmo_esme *esme, struct msgb *msg)
-{
-	struct submit_sm_t submit;
-	struct submit_sm_resp_t submit_r;
-	int rc;
-
-	memset(&submit, 0, sizeof(submit));
-	SMPP34_UNPACK(rc, SUBMIT_SM, &submit, msgb_data(msg),
-			   msgb_length(msg));
-	if (rc < 0) {
-		LOGP(DSMPP, LOGL_ERROR, "[%s] Error in smpp34_unpack():%s\n",
-			esme->system_id, smpp34_strerror);
-		return rc;
-	}
-
-	INIT_RESP(SUBMIT_SM_RESP, &submit_r, &submit);
-
-	if (!(esme->bind_flags & ESME_BIND_TX)) {
-		submit_r.command_status = ESME_RINVBNDSTS;
-		return PACK_AND_SEND(esme, &submit_r);
-	}
-
-	LOGP(DSMPP, LOGL_INFO, "[%s] Rx SUBMIT-SM (%s/%u/%u)\n",
-		esme->system_id, submit.destination_addr,
-		submit.dest_addr_ton, submit.dest_addr_npi);
-
-	INIT_RESP(SUBMIT_SM_RESP, &submit_r, &submit);
-
-	rc = handle_smpp_submit(esme, &submit, &submit_r);
-	if (rc == 0)
-		return PACK_AND_SEND(esme, &submit_r);
-
-	return rc;
-}
-
-/*! \brief one complete SMPP PDU from the ESME has been received */
-static int smpp_pdu_rx(struct osmo_esme *esme, struct msgb *msg __uses)
-{
-	uint32_t cmd_id = smpp_msgb_cmdid(msg);
-	int rc = 0;
-
-	LOGP(DSMPP, LOGL_DEBUG, "[%s] smpp_pdu_rx(%s)\n", esme->system_id,
-	     osmo_hexdump(msgb_data(msg), msgb_length(msg)));
-
-	switch (cmd_id) {
-	case GENERIC_NACK:
-		rc = smpp_handle_gen_nack(esme, msg);
-		break;
-	case BIND_RECEIVER:
-		rc = smpp_handle_bind_rx(esme, msg);
-		break;
-	case BIND_TRANSMITTER:
-		rc = smpp_handle_bind_tx(esme, msg);
-		break;
-	case BIND_TRANSCEIVER:
-		rc = smpp_handle_bind_trx(esme, msg);
-		break;
-	case UNBIND:
-		rc = smpp_handle_unbind(esme, msg);
-		break;
-	case ENQUIRE_LINK:
-		rc = smpp_handle_enq_link(esme, msg);
-		break;
-	case SUBMIT_SM:
-		rc = smpp_handle_submit(esme, msg);
-		break;
-	case DELIVER_SM_RESP:
-		rc = smpp_handle_deliver_resp(esme, msg);
-		break;
-	case DELIVER_SM:
-		break;
-	case DATA_SM:
-		break;
-	case CANCEL_SM:
-	case QUERY_SM:
-	case REPLACE_SM:
-	case SUBMIT_MULTI:
-		LOGP(DSMPP, LOGL_NOTICE, "[%s] Unimplemented PDU Command "
-		     "0x%08x\n", esme->system_id, cmd_id);
-		break;
-	default:
-		LOGP(DSMPP, LOGL_ERROR, "[%s] Unknown PDU Command 0x%08x\n",
-		     esme->system_id, cmd_id);
-		rc = smpp_tx_gen_nack(esme, smpp_msgb_seq(msg), ESME_RINVCMDID);
-		break;
-	}
-
-	return rc;
-}
-
-/* This macro should be called after a call to read() in the read_cb of an
- * osmo_fd to properly check for errors.
- * rc is the return value of read, err_label is the label to jump to in case of
- * an error. The code there should handle closing the connection.
- * FIXME: This code should go in libosmocore utils.h so it can be used by other
- * projects as well.
- * */
-#define OSMO_FD_CHECK_READ(rc, err_label) \
-	if (rc < 0) { \
-		/* EINTR is a non-fatal error, just try again */ \
-		if (errno == EINTR) \
-			return 0; \
-		goto err_label; \
-	} else if (rc == 0) { \
-		goto err_label; \
-	}
-
-/* !\brief call-back when per-ESME TCP socket has some data to be read */
-static int esme_link_read_cb(struct osmo_fd *ofd)
-{
-	struct osmo_esme *esme = ofd->data;
-	uint32_t len;
-	uint8_t *lenptr = (uint8_t *) &len;
-	uint8_t *cur;
-	struct msgb *msg;
-	ssize_t rdlen, rc;
-
-	switch (esme->read_state) {
-	case READ_ST_IN_LEN:
-		rdlen = sizeof(uint32_t) - esme->read_idx;
-		rc = read(ofd->fd, lenptr + esme->read_idx, rdlen);
-		if (rc < 0)
-			LOGP(DSMPP, LOGL_ERROR, "[%s] read returned %zd (%s)\n",
-					esme->system_id, rc, strerror(errno));
-		OSMO_FD_CHECK_READ(rc, dead_socket);
-
-		esme->read_idx += rc;
-
-		if (esme->read_idx >= sizeof(uint32_t)) {
-			esme->read_len = ntohl(len);
-			if (esme->read_len < 8 || esme->read_len > UINT16_MAX) {
-				LOGP(DSMPP, LOGL_ERROR, "[%s] length invalid %u\n",
-						esme->system_id, esme->read_len);
-				goto dead_socket;
-			}
-
-			msg = msgb_alloc(esme->read_len, "SMPP Rx");
-			if (!msg)
-				return -ENOMEM;
-			esme->read_msg = msg;
-			cur = msgb_put(msg, sizeof(uint32_t));
-			memcpy(cur, lenptr, sizeof(uint32_t));
-			esme->read_state = READ_ST_IN_MSG;
-			esme->read_idx = sizeof(uint32_t);
-		}
-		break;
-	case READ_ST_IN_MSG:
-		msg = esme->read_msg;
-		rdlen = esme->read_len - esme->read_idx;
-		rc = read(ofd->fd, msg->tail, OSMO_MIN(rdlen, msgb_tailroom(msg)));
-		if (rc < 0)
-			LOGP(DSMPP, LOGL_ERROR, "[%s] read returned %zd (%s)\n",
-					esme->system_id, rc, strerror(errno));
-		OSMO_FD_CHECK_READ(rc, dead_socket);
-
-		esme->read_idx += rc;
-		msgb_put(msg, rc);
-
-		if (esme->read_idx >= esme->read_len) {
-			rc = smpp_pdu_rx(esme, esme->read_msg);
-			msgb_free(esme->read_msg);
-			esme->read_msg = NULL;
-			esme->read_idx = 0;
-			esme->read_len = 0;
-			esme->read_state = READ_ST_IN_LEN;
-		}
-		break;
-	}
-
-	return 0;
-dead_socket:
-	msgb_free(esme->read_msg);
-	osmo_fd_unregister(&esme->wqueue.bfd);
-	close(esme->wqueue.bfd.fd);
-	esme->wqueue.bfd.fd = -1;
-	smpp_esme_put(esme);
-
-	return 0;
-}
-
-/* call-back of write queue once it wishes to write a message to the socket */
-static int esme_link_write_cb(struct osmo_fd *ofd, struct msgb *msg)
-{
-	struct osmo_esme *esme = ofd->data;
-	int rc;
-
-	rc = write(ofd->fd, msgb_data(msg), msgb_length(msg));
-	if (rc == 0) {
-		osmo_fd_unregister(&esme->wqueue.bfd);
-		close(esme->wqueue.bfd.fd);
-		esme->wqueue.bfd.fd = -1;
-		smpp_esme_put(esme);
-	} else if (rc < msgb_length(msg)) {
-		LOGP(DSMPP, LOGL_ERROR, "[%s] Short write\n", esme->system_id);
-		return -1;
-	}
-
-	return 0;
-}
-
-/* callback for already-accepted new TCP socket */
-static int link_accept_cb(struct smsc *smsc, int fd,
-			  struct sockaddr_storage *s, socklen_t s_len)
-{
-	struct osmo_esme *esme = talloc_zero(smsc, struct osmo_esme);
-	if (!esme) {
-		close(fd);
-		return -ENOMEM;
-	}
-
-	INIT_LLIST_HEAD(&esme->smpp_cmd_list);
-	smpp_esme_get(esme);
-	esme->own_seq_nr = rand();
-	esme_inc_seq_nr(esme);
-	esme->smsc = smsc;
-	osmo_wqueue_init(&esme->wqueue, 10);
-	esme->wqueue.bfd.fd = fd;
-	esme->wqueue.bfd.data = esme;
-	esme->wqueue.bfd.when = BSC_FD_READ;
-
-	if (osmo_fd_register(&esme->wqueue.bfd) != 0) {
-		close(fd);
-		talloc_free(esme);
-		return -EIO;
-	}
-
-	esme->wqueue.read_cb = esme_link_read_cb;
-	esme->wqueue.write_cb = esme_link_write_cb;
-
-	esme->sa_len = OSMO_MIN(sizeof(esme->sa), s_len);
-	memcpy(&esme->sa, s, esme->sa_len);
-
-	llist_add_tail(&esme->list, &smsc->esme_list);
-
-	return 0;
-}
-
-/* callback of listening TCP socket */
-static int smsc_fd_cb(struct osmo_fd *ofd, unsigned int what)
-{
-	int rc;
-	struct sockaddr_storage sa;
-	socklen_t sa_len = sizeof(sa);
-
-	rc = accept(ofd->fd, (struct sockaddr *)&sa, &sa_len);
-	if (rc < 0) {
-		LOGP(DSMPP, LOGL_ERROR, "Accept returns %d (%s)\n",
-		     rc, strerror(errno));
-		return rc;
-	}
-	return link_accept_cb(ofd->data, rc, &sa, sa_len);
-}
-
-/*! \brief allocate and initialize an smsc struct from talloc context ctx. */
-struct smsc *smpp_smsc_alloc_init(void *ctx)
-{
-	struct smsc *smsc = talloc_zero(ctx, struct smsc);
-
-	INIT_LLIST_HEAD(&smsc->esme_list);
-	INIT_LLIST_HEAD(&smsc->acl_list);
-	INIT_LLIST_HEAD(&smsc->route_list);
-
-	smsc->listen_ofd.data = smsc;
-	smsc->listen_ofd.cb = smsc_fd_cb;
-
-	return smsc;
-}
-
-/*! \brief Set the SMPP address and port without binding. */
-int smpp_smsc_conf(struct smsc *smsc, const char *bind_addr, uint16_t port)
-{
-	talloc_free((void*)smsc->bind_addr);
-	smsc->bind_addr = NULL;
-	if (bind_addr) {
-		smsc->bind_addr = talloc_strdup(smsc, bind_addr);
-		if (!smsc->bind_addr)
-			return -ENOMEM;
-	}
-	smsc->listen_port = port;
-	return 0;
-}
-
-/*! \brief Bind to given address and port and accept connections.
- * \param[in] bind_addr Local IP address, may be NULL for any.
- * \param[in] port TCP port number, may be 0 for default SMPP (2775).
- */
-int smpp_smsc_start(struct smsc *smsc, const char *bind_addr, uint16_t port)
-{
-	int rc;
-
-	/* default port for SMPP */
-	if (!port)
-		port = 2775;
-
-	smpp_smsc_stop(smsc);
-
-	LOGP(DSMPP, LOGL_NOTICE, "SMPP at %s %d\n",
-	     bind_addr? bind_addr : "0.0.0.0", port);
-
-	rc = osmo_sock_init_ofd(&smsc->listen_ofd, AF_UNSPEC, SOCK_STREAM,
-				IPPROTO_TCP, bind_addr, port,
-				OSMO_SOCK_F_BIND);
-	if (rc < 0)
-		return rc;
-
-	/* store new address and port */
-	rc = smpp_smsc_conf(smsc, bind_addr, port);
-	if (rc)
-		smpp_smsc_stop(smsc);
-	return rc;
-}
-
-/*! \brief Change a running connection to a different address/port, and upon
- * error switch back to the running configuration. */
-int smpp_smsc_restart(struct smsc *smsc, const char *bind_addr, uint16_t port)
-{
-	int rc;
-
-	rc = smpp_smsc_start(smsc, bind_addr, port);
-	if (rc)
-		/* if there is an error, try to re-bind to the old port */
-		return smpp_smsc_start(smsc, smsc->bind_addr, smsc->listen_port);
-	return 0;
-}
-
-/*! /brief Close SMPP connection. */
-void smpp_smsc_stop(struct smsc *smsc)
-{
-	if (smsc->listen_ofd.fd > 0) {
-		close(smsc->listen_ofd.fd);
-		smsc->listen_ofd.fd = 0;
-		osmo_fd_unregister(&smsc->listen_ofd);
-	}
-}
diff --git a/src/libmsc/smpp_smsc.h b/src/libmsc/smpp_smsc.h
deleted file mode 100644
index 755e685..0000000
--- a/src/libmsc/smpp_smsc.h
+++ /dev/null
@@ -1,167 +0,0 @@
-#ifndef _SMPP_SMSC_H
-#define _SMPP_SMSC_H
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#include <osmocom/core/utils.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/write_queue.h>
-#include <osmocom/core/timer.h>
-
-#include <smpp34.h>
-#include <smpp34_structs.h>
-#include <smpp34_params.h>
-
-#define SMPP_SYS_ID_LEN	16
-#define SMPP_PASSWD_LEN	16
-
-#define MODE_7BIT	7
-#define MODE_8BIT	8
-
-enum esme_read_state {
-	READ_ST_IN_LEN = 0,
-	READ_ST_IN_MSG = 1,
-};
-
-struct osmo_smpp_acl;
-
-struct osmo_smpp_addr {
-	uint8_t ton;
-	uint8_t npi;
-	char addr[21+1];
-};
-
-struct osmo_esme {
-	struct llist_head list;
-	struct smsc *smsc;
-	struct osmo_smpp_acl *acl;
-	int use;
-
-	struct llist_head smpp_cmd_list;
-
-	uint32_t own_seq_nr;
-
-	struct osmo_wqueue wqueue;
-	struct sockaddr_storage sa;
-	socklen_t sa_len;
-
-	enum esme_read_state read_state;
-	uint32_t read_len;
-	uint32_t read_idx;
-	struct msgb *read_msg;
-
-	uint8_t smpp_version;
-	char system_id[SMPP_SYS_ID_LEN+1];
-
-	uint8_t bind_flags;
-};
-
-struct osmo_smpp_acl {
-	struct llist_head list;
-	struct smsc *smsc;
-	struct osmo_esme *esme;
-	char *description;
-	char system_id[SMPP_SYS_ID_LEN+1];
-	char passwd[SMPP_PASSWD_LEN+1];
-	int default_route;
-	int deliver_src_imsi;
-	int osmocom_ext;
-	int dcs_transparent;
-	struct llist_head route_list;
-};
-
-enum osmo_smpp_rtype {
-	SMPP_ROUTE_NONE,
-	SMPP_ROUTE_PREFIX,
-};
-
-struct osmo_smpp_route {
-	struct llist_head list;	/*!< in acl.route_list */
-	struct llist_head global_list; /*!< in smsc->route_list */
-	struct osmo_smpp_acl *acl;
-	enum osmo_smpp_rtype type;
-	union {
-		struct osmo_smpp_addr prefix;
-	} u;
-};
-
-struct osmo_smpp_cmd {
-	struct llist_head	list;
-	struct vlr_subscr	*vsub;
-	uint32_t		sequence_nr;
-	uint32_t		gsm411_msg_ref;
-	uint8_t			gsm411_trans_id;
-	bool			is_report;
-	struct osmo_timer_list	response_timer;
-};
-
-struct osmo_smpp_cmd *smpp_cmd_find_by_seqnum(struct osmo_esme *esme,
-					      uint32_t sequence_number);
-void smpp_cmd_ack(struct osmo_smpp_cmd *cmd);
-void smpp_cmd_err(struct osmo_smpp_cmd *cmd, uint32_t status);
-void smpp_cmd_flush_pending(struct osmo_esme *esme);
-
-struct smsc {
-	struct osmo_fd listen_ofd;
-	struct llist_head esme_list;
-	struct llist_head acl_list;
-	struct llist_head route_list;
-	const char *bind_addr;
-	uint16_t listen_port;
-	char system_id[SMPP_SYS_ID_LEN+1];
-	int accept_all;
-	int smpp_first;
-	struct osmo_smpp_acl *def_route;
-	void *priv;
-};
-
-int smpp_addr_eq(const struct osmo_smpp_addr *a,
-		 const struct osmo_smpp_addr *b);
-
-struct smsc *smpp_smsc_alloc_init(void *ctx);
-int smpp_smsc_conf(struct smsc *smsc, const char *bind_addr, uint16_t port);
-int smpp_smsc_start(struct smsc *smsc, const char *bind_addr, uint16_t port);
-int smpp_smsc_restart(struct smsc *smsc, const char *bind_addr, uint16_t port);
-void smpp_smsc_stop(struct smsc *smsc);
-
-void smpp_esme_get(struct osmo_esme *esme);
-void smpp_esme_put(struct osmo_esme *esme);
-
-int smpp_route(const struct smsc *smsc, const struct osmo_smpp_addr *dest, struct osmo_esme **emse);
-
-struct osmo_smpp_acl *smpp_acl_alloc(struct smsc *smsc, const char *sys_id);
-struct osmo_smpp_acl *smpp_acl_by_system_id(struct smsc *smsc,
-					    const char *sys_id);
-void smpp_acl_delete(struct osmo_smpp_acl *acl);
-
-int smpp_tx_submit_r(struct osmo_esme *esme, uint32_t sequence_nr,
-		     uint32_t command_status, char *msg_id);
-
-int smpp_tx_alert(struct osmo_esme *esme, uint8_t ton, uint8_t npi,
-		  const char *addr, uint8_t avail_status);
-
-int smpp_tx_deliver(struct osmo_esme *esme, struct deliver_sm_t *deliver);
-
-int handle_smpp_submit(struct osmo_esme *esme, struct submit_sm_t *submit,
-			struct submit_sm_resp_t *submit_r);
-
-int smpp_route_pfx_add(struct osmo_smpp_acl *acl,
-		       const struct osmo_smpp_addr *pfx);
-int smpp_route_pfx_del(struct osmo_smpp_acl *acl,
-		       const struct osmo_smpp_addr *pfx);
-
-int smpp_vty_init(void);
-
-int smpp_determine_scheme(uint8_t dcs, uint8_t *data_coding, int *mode);
-
-
-
-struct gsm_sms;
-struct gsm_subscriber_connection;
-
-int smpp_route_smpp_first(struct gsm_sms *sms,
-			    struct gsm_subscriber_connection *conn);
-int smpp_try_deliver(struct gsm_sms *sms,
-		     struct gsm_subscriber_connection *conn);
-#endif
diff --git a/src/libmsc/smpp_utils.c b/src/libmsc/smpp_utils.c
deleted file mode 100644
index d0850d8..0000000
--- a/src/libmsc/smpp_utils.c
+++ /dev/null
@@ -1,62 +0,0 @@
-
-/* (C) 2012-2013 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/>.
- */
-
-
-#include "smpp_smsc.h"
-#include <openbsc/debug.h>
-
-
-int smpp_determine_scheme(uint8_t dcs, uint8_t *data_coding, int *mode)
-{
-	if ((dcs & 0xF0) == 0xF0) {
-		if (dcs & 0x04) {
-			/* bit 2 == 1: 8bit data */
-			*data_coding = 0x02;
-			*mode = MODE_8BIT;
-		} else {
-			/* bit 2 == 0: default alphabet */
-			*data_coding = 0x01;
-			*mode = MODE_7BIT;
-		}
-	} else if ((dcs & 0xE0) == 0) {
-		switch (dcs & 0xC) {
-		case 0:
-			*data_coding = 0x01;
-			*mode = MODE_7BIT;
-			break;
-		case 4:
-			*data_coding = 0x02;
-			*mode = MODE_8BIT;
-			break;
-		case 8:
-			*data_coding = 0x08;     /* UCS-2 */
-			*mode = MODE_8BIT;
-			break;
-		default:
-			goto unknown_mo;
-		}
-	} else {
-unknown_mo:
-		LOGP(DLSMS, LOGL_ERROR, "SMPP MO Unknown Data Coding 0x%02x\n", dcs);
-		return -1;
-	}
-
-	return 0;
-
-}
diff --git a/src/libmsc/smpp_vty.c b/src/libmsc/smpp_vty.c
deleted file mode 100644
index 13467f1..0000000
--- a/src/libmsc/smpp_vty.c
+++ /dev/null
@@ -1,612 +0,0 @@
-/* SMPP vty interface */
-
-/* (C) 2012 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/>.
- *
- */
-
-#include <ctype.h>
-#include <string.h>
-#include <errno.h>
-#include <netdb.h>
-#include <sys/socket.h>
-
-#include <osmocom/vty/command.h>
-#include <osmocom/vty/buffer.h>
-#include <osmocom/vty/vty.h>
-
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/talloc.h>
-
-#include <openbsc/vty.h>
-
-#include "smpp_smsc.h"
-
-struct smsc *smsc_from_vty(struct vty *v);
-
-static struct cmd_node smpp_node = {
-	SMPP_NODE,
-	"%s(config-smpp)# ",
-	1,
-};
-
-static struct cmd_node esme_node = {
-	SMPP_ESME_NODE,
-	"%s(config-smpp-esme)# ",
-	1,
-};
-
-DEFUN(cfg_smpp, cfg_smpp_cmd,
-	"smpp", "Configure SMPP SMS Interface")
-{
-	vty->node = SMPP_NODE;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_smpp_first, cfg_smpp_first_cmd,
-	"smpp-first",
-	"Try SMPP routes before the subscriber DB\n")
-{
-	struct smsc *smsc = smsc_from_vty(vty);
-	smsc->smpp_first = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_no_smpp_first, cfg_no_smpp_first_cmd,
-	"no smpp-first",
-	NO_STR "Try SMPP before routes before the subscriber DB\n")
-{
-	struct smsc *smsc = smsc_from_vty(vty);
-	smsc->smpp_first = 0;
-	return CMD_SUCCESS;
-}
-
-static int smpp_local_tcp(struct vty *vty,
-			  const char *bind_addr, uint16_t port)
-{
-	struct smsc *smsc = smsc_from_vty(vty);
-	int is_running = smsc->listen_ofd.fd > 0;
-	int same_bind_addr;
-	int rc;
-
-	/* If it is not up yet, don't rebind, just set values. */
-	if (!is_running) {
-		rc = smpp_smsc_conf(smsc, bind_addr, port);
-		if (rc < 0) {
-			vty_out(vty, "%% Cannot configure new address:port%s",
-				VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-		return CMD_SUCCESS;
-	}
-
-	rc = smpp_smsc_restart(smsc, bind_addr, port);
-	if (rc < 0) {
-		vty_out(vty, "%% Cannot bind to new port %s:%u nor to"
-			" old port %s:%u%s",
-			bind_addr? bind_addr : "0.0.0.0",
-			port,
-			smsc->bind_addr? smsc->bind_addr : "0.0.0.0",
-			smsc->listen_port,
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	same_bind_addr = (bind_addr == smsc->bind_addr)
-		|| (bind_addr && smsc->bind_addr
-		    && (strcmp(bind_addr, smsc->bind_addr) == 0));
-
-	if (!same_bind_addr || port != smsc->listen_port) {
-		vty_out(vty, "%% Cannot bind to new port %s:%u, staying on"
-			" old port %s:%u%s",
-			bind_addr? bind_addr : "0.0.0.0",
-			port,
-			smsc->bind_addr? smsc->bind_addr : "0.0.0.0",
-			smsc->listen_port,
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_smpp_port, cfg_smpp_port_cmd,
-	"local-tcp-port <1-65535>",
-	"Set the local TCP port on which we listen for SMPP\n"
-	"TCP port number")
-{
-	struct smsc *smsc = smsc_from_vty(vty);
-	uint16_t port = atoi(argv[0]);
-	return smpp_local_tcp(vty, smsc->bind_addr, port);
-}
-
-DEFUN(cfg_smpp_addr_port, cfg_smpp_addr_port_cmd,
-	"local-tcp-ip A.B.C.D <1-65535>",
-	"Set the local IP address and TCP port on which we listen for SMPP\n"
-	"Local IP address\n"
-	"TCP port number")
-{
-	const char *bind_addr = argv[0];
-	uint16_t port = atoi(argv[1]);
-	return smpp_local_tcp(vty, bind_addr, port);
-}
-
-DEFUN(cfg_smpp_sys_id, cfg_smpp_sys_id_cmd,
-	"system-id ID",
-	"Set the System ID of this SMSC\n"
-	"Alphanumeric SMSC System ID\n")
-{
-	struct smsc *smsc = smsc_from_vty(vty);
-
-	if (strlen(argv[0])+1 > sizeof(smsc->system_id))
-		return CMD_WARNING;
-
-	strcpy(smsc->system_id, argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_smpp_policy, cfg_smpp_policy_cmd,
-	"policy (accept-all|closed)",
-	"Set the authentication policy of this SMSC\n"
-	"Accept all SMPP connections independeint of system ID / passwd\n"
-	"Accept only SMPP connections from ESMEs explicitly configured")
-{
-	struct smsc *smsc = smsc_from_vty(vty);
-
-	if (!strcmp(argv[0], "accept-all"))
-		smsc->accept_all = 1;
-	else
-		smsc->accept_all = 0;
-
-	return CMD_SUCCESS;
-}
-
-
-static int config_write_smpp(struct vty *vty)
-{
-	struct smsc *smsc = smsc_from_vty(vty);
-
-	vty_out(vty, "smpp%s", VTY_NEWLINE);
-	if (smsc->bind_addr)
-		vty_out(vty, " local-tcp-ip %s %u%s", smsc->bind_addr,
-			smsc->listen_port, VTY_NEWLINE);
-	else
-		vty_out(vty, " local-tcp-port %u%s", smsc->listen_port,
-			VTY_NEWLINE);
-	if (strlen(smsc->system_id) > 0)
-		vty_out(vty, " system-id %s%s", smsc->system_id, VTY_NEWLINE);
-	vty_out(vty, " policy %s%s",
-		smsc->accept_all ? "accept-all" : "closed", VTY_NEWLINE);
-	vty_out(vty, " %ssmpp-first%s",
-		smsc->smpp_first ? "" : "no ", VTY_NEWLINE);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_esme, cfg_esme_cmd,
-	"esme NAME",
-	"Configure a particular ESME\n"
-	"Alphanumeric System ID of the ESME to be configured\n")
-{
-	struct smsc *smsc = smsc_from_vty(vty);
-	struct osmo_smpp_acl *acl;
-	const char *id = argv[0];
-
-	if (strlen(id) > 16) {
-		vty_out(vty, "%% System ID cannot be more than 16 "
-			"characters long%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-	acl = smpp_acl_by_system_id(smsc, id);
-	if (!acl) {
-		acl = smpp_acl_alloc(smsc, id);
-		if (!acl)
-			return CMD_WARNING;
-	}
-
-	vty->index = acl;
-	vty->index_sub = &acl->description;
-	vty->node = SMPP_ESME_NODE;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_no_esme, cfg_no_esme_cmd,
-	"no esme NAME",
-	NO_STR "Remove ESME configuration\n"
-	"Alphanumeric System ID of the ESME to be removed\n")
-{
-	struct smsc *smsc = smsc_from_vty(vty);
-	struct osmo_smpp_acl *acl;
-	const char *id = argv[0];
-
-	acl = smpp_acl_by_system_id(smsc, id);
-	if (!acl) {
-		vty_out(vty, "%% ESME with system id '%s' unknown%s",
-			id, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	/* FIXME: close the connection, free data structure, etc. */
-
-	smpp_acl_delete(acl);
-
-	return CMD_SUCCESS;
-}
-
-
-DEFUN(cfg_esme_passwd, cfg_esme_passwd_cmd,
-	"password PASSWORD",
-	"Set the password for this ESME\n"
-	"Alphanumeric password string\n")
-{
-	struct osmo_smpp_acl *acl = vty->index;
-
-	if (strlen(argv[0])+1 > sizeof(acl->passwd))
-		return CMD_WARNING;
-
-	strcpy(acl->passwd, argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_esme_no_passwd, cfg_esme_no_passwd_cmd,
-	"no password",
-	NO_STR "Remove the password for this ESME\n")
-{
-	struct osmo_smpp_acl *acl = vty->index;
-
-	memset(acl->passwd, 0, sizeof(acl->passwd));
-
-	return CMD_SUCCESS;
-}
-
-static int osmo_is_digits(const char *str)
-{
-	int i;
-	for (i = 0; i < strlen(str); i++) {
-		if (!isdigit(str[i]))
-			return 0;
-	}
-	return 1;
-}
-
-static const struct value_string route_errstr[] = {
-	{ -EEXIST,	"Route already exists" },
-	{ -ENODEV,	"Route does not exist" },
-	{ -ENOMEM,	"No memory" },
-	{ -EINVAL,	"Invalid" },
-	{ 0, NULL }
-};
-
-static const struct value_string smpp_ton_str_short[] = {
-	{ TON_Unknown,		"unknown" },
-	{ TON_International,	"international" },
-	{ TON_National,		"national" },
-	{ TON_Network_Specific,	"network" },
-	{ TON_Subscriber_Number,"subscriber" },
-	{ TON_Alphanumeric,	"alpha" },
-	{ TON_Abbreviated,	"abbrev" },
-	{ 0, NULL }
-};
-
-static const struct value_string smpp_npi_str_short[] = {
-	{ NPI_Unknown,		"unknown" },
-	{ NPI_ISDN_E163_E164,	"isdn" },
-	{ NPI_Data_X121,	"x121" },
-	{ NPI_Telex_F69,	"f69" },
-	{ NPI_Land_Mobile_E212,	"e212" },
-	{ NPI_National,		"national" },
-	{ NPI_Private,		"private" },
-	{ NPI_ERMES,		"ermes" },
-	{ NPI_Internet_IP,	"ip" },
-	{ NPI_WAP_Client_Id,	"wap" },
-	{ 0, NULL }
-};
-
-
-#define SMPP_ROUTE_STR "Configure a route for MO-SMS to be sent to this ESME\n"
-#define SMPP_ROUTE_P_STR SMPP_ROUTE_STR "Prefix-match route\n"
-#define SMPP_PREFIX_STR "Destination number prefix\n"
-
-#define TON_CMD "(unknown|international|national|network|subscriber|alpha|abbrev)"
-#define NPI_CMD "(unknown|isdn|x121|f69|e212|national|private|ermes|ip|wap)"
-#define TON_STR "Unknown type-of-number\n"		\
-		"International type-of-number\n"	\
-		"National type-of-number\n"		\
-		"Network specific type-of-number\n"	\
-		"Subscriber type-of-number\n"		\
-		"Alphanumeric type-of-number\n"		\
-		"Abbreviated type-of-number\n"
-#define NPI_STR "Unknown numbering plan\n"		\
-		"ISDN (E.164) numbering plan\n"		\
-		"X.121 numbering plan\n"		\
-		"F.69 numbering plan\n"			\
-		"E.212 numbering plan\n"		\
-		"National numbering plan\n"		\
-		"Private numbering plan\n"		\
-		"ERMES numbering plan\n"		\
-		"IP numbering plan\n"			\
-		"WAP numbeing plan\n"
-
-DEFUN(cfg_esme_route_pfx, cfg_esme_route_pfx_cmd,
-	"route prefix " TON_CMD " " NPI_CMD " PREFIX",
-	SMPP_ROUTE_P_STR TON_STR NPI_STR SMPP_PREFIX_STR)
-{
-	struct osmo_smpp_acl *acl = vty->index;
-	struct osmo_smpp_addr pfx;
-	int rc;
-
-	/* check if DESTINATION is all-digits */
-	if (!osmo_is_digits(argv[2])) {
-		vty_out(vty, "%% PREFIX has to be numeric%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	pfx.ton = get_string_value(smpp_ton_str_short, argv[0]);
-	pfx.npi = get_string_value(smpp_npi_str_short, argv[1]);
-	snprintf(pfx.addr, sizeof(pfx.addr), "%s", argv[2]);
-
-	rc = smpp_route_pfx_add(acl, &pfx);
-	if (rc < 0) {
-		vty_out(vty, "%% error adding prefix route: %s%s",
-			get_value_string(route_errstr, rc), VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_esme_no_route_pfx, cfg_esme_no_route_pfx_cmd,
-	"no route prefix " TON_CMD " " NPI_CMD " PREFIX",
-	NO_STR SMPP_ROUTE_P_STR TON_STR NPI_STR SMPP_PREFIX_STR)
-{
-	struct osmo_smpp_acl *acl = vty->index;
-	struct osmo_smpp_addr pfx;
-	int rc;
-
-	/* check if DESTINATION is all-digits */
-	if (!osmo_is_digits(argv[2])) {
-		vty_out(vty, "%% PREFIX has to be numeric%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	pfx.ton = get_string_value(smpp_ton_str_short, argv[0]);
-	pfx.npi = get_string_value(smpp_npi_str_short, argv[1]);
-	snprintf(pfx.addr, sizeof(pfx.addr), "%s", argv[2]);
-
-	rc = smpp_route_pfx_del(acl, &pfx);
-	if (rc < 0) {
-		vty_out(vty, "%% error removing prefix route: %s%s",
-			get_value_string(route_errstr, rc), VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	return CMD_SUCCESS;
-
-}
-
-
-DEFUN(cfg_esme_defaultroute, cfg_esme_defaultroute_cmd,
-	"default-route",
-	"Set this ESME as default-route for all SMS to unknown destinations")
-{
-	struct osmo_smpp_acl *acl = vty->index;
-
-	acl->default_route = 1;
-
-	if (!acl->smsc->def_route)
-		acl->smsc->def_route = acl;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_no_esme_defaultroute, cfg_esme_no_defaultroute_cmd,
-	"no default-route", NO_STR
-	"Remove this ESME as default-route for all SMS to unknown destinations")
-{
-	struct osmo_smpp_acl *acl = vty->index;
-
-	acl->default_route = 0;
-
-	/* remove currently active default route, if it was created by
-	 * this ACL */
-	if (acl->smsc->def_route && acl->smsc->def_route == acl)
-		acl->smsc->def_route = NULL;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_esme_del_src_imsi, cfg_esme_del_src_imsi_cmd,
-	"deliver-src-imsi",
-	"Enable the use of IMSI as source address in DELIVER")
-{
-	struct osmo_smpp_acl *acl = vty->index;
-
-	acl->deliver_src_imsi = 1;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_esme_no_del_src_imsi, cfg_esme_no_del_src_imsi_cmd,
-	"no deliver-src-imsi", NO_STR
-	"Disable the use of IMSI as source address in DELIVER")
-{
-	struct osmo_smpp_acl *acl = vty->index;
-
-	acl->deliver_src_imsi = 0;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_esme_osmo_ext, cfg_esme_osmo_ext_cmd,
-	"osmocom-extensions",
-	"Enable the use of Osmocom SMPP Extensions for this ESME")
-{
-	struct osmo_smpp_acl *acl = vty->index;
-
-	acl->osmocom_ext = 1;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_esme_no_osmo_ext, cfg_esme_no_osmo_ext_cmd,
-	"no osmocom-extensions", NO_STR
-	"Disable the use of Osmocom SMPP Extensions for this ESME")
-{
-	struct osmo_smpp_acl *acl = vty->index;
-
-	acl->osmocom_ext = 0;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_esme_dcs_transp, cfg_esme_dcs_transp_cmd,
-	"dcs-transparent",
-	"Enable the transparent pass-through of TP-DCS to SMPP DataCoding")
-{
-	struct osmo_smpp_acl *acl = vty->index;
-
-	acl->dcs_transparent = 1;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_esme_no_dcs_transp, cfg_esme_no_dcs_transp_cmd,
-	"no dcs-transparent", NO_STR
-	"Disable the transparent pass-through of TP-DCS to SMPP DataCoding")
-{
-	struct osmo_smpp_acl *acl = vty->index;
-
-	acl->dcs_transparent = 0;
-
-	return CMD_SUCCESS;
-}
-
-
-static void dump_one_esme(struct vty *vty, struct osmo_esme *esme)
-{
-	char host[128], serv[128];
-
-	host[0] = 0;
-	serv[0] = 0;
-	getnameinfo((const struct sockaddr *) &esme->sa, esme->sa_len,
-		    host, sizeof(host), serv, sizeof(serv), NI_NUMERICSERV);
-
-	vty_out(vty, "ESME System ID: %s, Password: %s, SMPP Version %02x%s",
-		esme->system_id, esme->acl ? esme->acl->passwd : "",
-		esme->smpp_version, VTY_NEWLINE);
-	vty_out(vty, "  Connected from: %s:%s%s", host, serv, VTY_NEWLINE);
-	if (esme->smsc->def_route == esme->acl)
-		vty_out(vty, "  Is current default route%s", VTY_NEWLINE);
-}
-
-DEFUN(show_esme, show_esme_cmd,
-	"show smpp esme",
-	SHOW_STR "SMPP Interface\n" "SMPP Extrenal SMS Entity\n")
-{
-	struct smsc *smsc = smsc_from_vty(vty);
-	struct osmo_esme *esme;
-
-	llist_for_each_entry(esme, &smsc->esme_list, list)
-		dump_one_esme(vty, esme);
-
-	return CMD_SUCCESS;
-}
-
-static void write_esme_route_single(struct vty *vty, struct osmo_smpp_route *r)
-{
-	switch (r->type) {
-	case SMPP_ROUTE_PREFIX:
-		vty_out(vty, "   route prefix %s ",
-			get_value_string(smpp_ton_str_short, r->u.prefix.ton));
-		vty_out(vty, "%s %s%s",
-			get_value_string(smpp_npi_str_short, r->u.prefix.npi),
-			r->u.prefix.addr, VTY_NEWLINE);
-		break;
-	case SMPP_ROUTE_NONE:
-		break;
-	}
-}
-
-static void config_write_esme_single(struct vty *vty, struct osmo_smpp_acl *acl)
-{
-	struct osmo_smpp_route *r;
-
-	vty_out(vty, " esme %s%s", acl->system_id, VTY_NEWLINE);
-	if (strlen(acl->passwd))
-		vty_out(vty, "  password %s%s", acl->passwd, VTY_NEWLINE);
-	if (acl->default_route)
-		vty_out(vty, "  default-route%s", VTY_NEWLINE);
-	if (acl->deliver_src_imsi)
-		vty_out(vty, "  deliver-src-imsi%s", VTY_NEWLINE);
-	if (acl->osmocom_ext)
-		vty_out(vty, "  osmocom-extensions%s", VTY_NEWLINE);
-	if (acl->dcs_transparent)
-		vty_out(vty, "  dcs-transparent%s", VTY_NEWLINE);
-
-	llist_for_each_entry(r, &acl->route_list, list)
-		write_esme_route_single(vty, r);
-}
-
-static int config_write_esme(struct vty *v)
-{
-	struct smsc *smsc = smsc_from_vty(v);
-	struct osmo_smpp_acl *acl;
-
-	llist_for_each_entry(acl, &smsc->acl_list, list)
-		config_write_esme_single(v, acl);
-
-	return CMD_SUCCESS;
-}
-
-int smpp_vty_init(void)
-{
-	install_node(&smpp_node, config_write_smpp);
-	vty_install_default(SMPP_NODE);
-	install_element(CONFIG_NODE, &cfg_smpp_cmd);
-
-	install_element(SMPP_NODE, &cfg_smpp_first_cmd);
-	install_element(SMPP_NODE, &cfg_no_smpp_first_cmd);
-	install_element(SMPP_NODE, &cfg_smpp_port_cmd);
-	install_element(SMPP_NODE, &cfg_smpp_addr_port_cmd);
-	install_element(SMPP_NODE, &cfg_smpp_sys_id_cmd);
-	install_element(SMPP_NODE, &cfg_smpp_policy_cmd);
-	install_element(SMPP_NODE, &cfg_esme_cmd);
-	install_element(SMPP_NODE, &cfg_no_esme_cmd);
-
-	install_node(&esme_node, config_write_esme);
-	vty_install_default(SMPP_ESME_NODE);
-	install_element(SMPP_ESME_NODE, &cfg_esme_passwd_cmd);
-	install_element(SMPP_ESME_NODE, &cfg_esme_no_passwd_cmd);
-	install_element(SMPP_ESME_NODE, &cfg_esme_route_pfx_cmd);
-	install_element(SMPP_ESME_NODE, &cfg_esme_no_route_pfx_cmd);
-	install_element(SMPP_ESME_NODE, &cfg_esme_defaultroute_cmd);
-	install_element(SMPP_ESME_NODE, &cfg_esme_no_defaultroute_cmd);
-	install_element(SMPP_ESME_NODE, &cfg_esme_del_src_imsi_cmd);
-	install_element(SMPP_ESME_NODE, &cfg_esme_no_del_src_imsi_cmd);
-	install_element(SMPP_ESME_NODE, &cfg_esme_osmo_ext_cmd);
-	install_element(SMPP_ESME_NODE, &cfg_esme_no_osmo_ext_cmd);
-	install_element(SMPP_ESME_NODE, &cfg_esme_dcs_transp_cmd);
-	install_element(SMPP_ESME_NODE, &cfg_esme_no_dcs_transp_cmd);
-
-	install_element_ve(&show_esme_cmd);
-
-	return 0;
-}
diff --git a/src/libmsc/sms_queue.c b/src/libmsc/sms_queue.c
deleted file mode 100644
index fe7a608..0000000
--- a/src/libmsc/sms_queue.c
+++ /dev/null
@@ -1,578 +0,0 @@
-/* SMS queue to continously attempt to deliver SMS */
-/*
- * (C) 2010 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/>.
- *
- */
-
-/**
- * The difficulty of such a queue is to send a lot of SMS without
- * overloading the paging subsystem and the database and other users
- * of the MSC. To make the best use we would need to know the number
- * of pending paging requests, then throttle the number of SMS we
- * want to send and such.
- * We will start with a very simple SMS Queue and then try to speed
- * things up by collecting data from other parts of the system.
- */
-
-#include <limits.h>
-
-#include <openbsc/sms_queue.h>
-#include <openbsc/chan_alloc.h>
-#include <openbsc/db.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_04_11.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/signal.h>
-#include <openbsc/vlr.h>
-
-#include <osmocom/core/talloc.h>
-
-#include <osmocom/vty/vty.h>
-
-/*
- * One pending SMS that we wait for.
- */
-struct gsm_sms_pending {
-	struct llist_head entry;
-
-	struct vlr_subscr *vsub;
-	unsigned long long sms_id;
-	int failed_attempts;
-	int resend;
-};
-
-struct gsm_sms_queue {
-	struct osmo_timer_list resend_pending;
-	struct osmo_timer_list push_queue;
-	struct gsm_network *network;
-	int max_fail;
-	int max_pending;
-	int pending;
-
-	struct llist_head pending_sms;
-
-	char last_msisdn[GSM_EXTENSION_LENGTH+1];
-};
-
-static int sms_subscr_cb(unsigned int, unsigned int, void *, void *);
-static int sms_sms_cb(unsigned int, unsigned int, void *, void *);
-
-static struct gsm_sms_pending *sms_find_pending(struct gsm_sms_queue *smsq,
-						struct gsm_sms *sms)
-{
-	struct gsm_sms_pending *pending;
-
-	llist_for_each_entry(pending, &smsq->pending_sms, entry) {
-		if (pending->sms_id == sms->id)
-			return pending;
-	}
-
-	return NULL;
-}
-
-static int sms_is_in_pending(struct gsm_sms_queue *smsq, struct gsm_sms *sms)
-{
-	return sms_find_pending(smsq, sms) != NULL;
-}
-
-static struct gsm_sms_pending *sms_subscriber_find_pending(
-					struct gsm_sms_queue *smsq,
-					struct vlr_subscr *vsub)
-{
-	struct gsm_sms_pending *pending;
-
-	llist_for_each_entry(pending, &smsq->pending_sms, entry) {
-		if (pending->vsub == vsub)
-			return pending;
-	}
-
-	return NULL;
-}
-
-static int sms_subscriber_is_pending(struct gsm_sms_queue *smsq,
-				     struct vlr_subscr *vsub)
-{
-	return sms_subscriber_find_pending(smsq, vsub) != NULL;
-}
-
-static struct gsm_sms_pending *sms_pending_from(struct gsm_sms_queue *smsq,
-						struct gsm_sms *sms)
-{
-	struct gsm_sms_pending *pending;
-
-	pending = talloc_zero(smsq, struct gsm_sms_pending);
-	if (!pending)
-		return NULL;
-
-	pending->vsub = vlr_subscr_get(sms->receiver);
-	pending->sms_id = sms->id;
-	return pending;
-}
-
-static void sms_pending_free(struct gsm_sms_pending *pending)
-{
-	vlr_subscr_put(pending->vsub);
-	llist_del(&pending->entry);
-	talloc_free(pending);
-}
-
-static void sms_pending_resend(struct gsm_sms_pending *pending)
-{
-	struct gsm_network *net = pending->vsub->vlr->user_ctx;
-	struct gsm_sms_queue *smsq;
-	LOGP(DLSMS, LOGL_DEBUG,
-	     "Scheduling resend of SMS %llu.\n", pending->sms_id);
-
-	pending->resend = 1;
-
-	smsq = net->sms_queue;
-	if (osmo_timer_pending(&smsq->resend_pending))
-		return;
-
-	osmo_timer_schedule(&smsq->resend_pending, 1, 0);
-}
-
-static void sms_pending_failed(struct gsm_sms_pending *pending, int paging_error)
-{
-	struct gsm_network *net = pending->vsub->vlr->user_ctx;
-	struct gsm_sms_queue *smsq;
-
-	LOGP(DLSMS, LOGL_NOTICE, "Sending SMS %llu failed %d times.\n",
-	     pending->sms_id, pending->failed_attempts);
-
-	smsq = net->sms_queue;
-	if (++pending->failed_attempts < smsq->max_fail)
-		return sms_pending_resend(pending);
-
-	sms_pending_free(pending);
-	smsq->pending -= 1;
-	sms_queue_trigger(smsq);
-}
-
-/*
- * Resend all SMS that are scheduled for a resend. This is done to
- * avoid an immediate failure.
- */
-static void sms_resend_pending(void *_data)
-{
-	struct gsm_sms_pending *pending, *tmp;
-	struct gsm_sms_queue *smsq = _data;
-
-	llist_for_each_entry_safe(pending, tmp, &smsq->pending_sms, entry) {
-		struct gsm_sms *sms;
-		if (!pending->resend)
-			continue;
-
-		sms = db_sms_get(smsq->network, pending->sms_id);
-
-		/* the sms is gone? Move to the next */
-		if (!sms) {
-			sms_pending_free(pending);
-			smsq->pending -= 1;
-			sms_queue_trigger(smsq);
-		} else {
-			pending->resend = 0;
-			gsm411_send_sms_subscr(sms->receiver, sms);
-		}
-	}
-}
-
-/* Find the next pending SMS by cycling through the recipients. We could also
- * cycle through the pending SMS, but that might cause us to keep trying to
- * send SMS to the same few subscribers repeatedly while not servicing other
- * subscribers for a long time. By walking the list of recipient MSISDNs, we
- * ensure that all subscribers get their fair time to receive SMS. */
-struct gsm_sms *smsq_take_next_sms(struct gsm_network *net,
-				   char *last_msisdn,
-				   size_t last_msisdn_buflen)
-{
-	struct gsm_sms *sms;
-	int wrapped = 0;
-	int sanity = 100;
-	char started_with_msisdn[last_msisdn_buflen];
-
-	osmo_strlcpy(started_with_msisdn, last_msisdn,
-		     sizeof(started_with_msisdn));
-
-	while (wrapped < 2 && (--sanity)) {
-		/* If we wrapped around and passed the first msisdn, we're
-		 * through the entire SMS DB; end it. */
-		if (wrapped && strcmp(last_msisdn, started_with_msisdn) >= 0)
-			break;
-
-		sms = db_sms_get_next_unsent_rr_msisdn(net, last_msisdn, 9);
-		if (!sms) {
-			last_msisdn[0] = '\0';
-			wrapped ++;
-			continue;
-		}
-
-		/* Whatever happens, next time around service another recipient
-		 */
-		osmo_strlcpy(last_msisdn, sms->dst.addr, last_msisdn_buflen);
-
-		/* Is the subscriber attached? If not, go to next SMS */
-		if (!sms->receiver || !sms->receiver->lu_complete)
-			continue;
-
-		return sms;
-	}
-
-	DEBUGP(DLSMS, "SMS queue: no SMS to be sent\n");
-	return NULL;
-}
-
-/**
- * I will submit up to max_pending - pending SMS to the
- * subsystem.
- */
-static void sms_submit_pending(void *_data)
-{
-	struct gsm_sms_queue *smsq = _data;
-	int attempts = smsq->max_pending - smsq->pending;
-	int initialized = 0;
-	unsigned long long first_sub = 0;
-	int attempted = 0, rounds = 0;
-
-	LOGP(DLSMS, LOGL_DEBUG, "Attempting to send %d SMS\n", attempts);
-
-	do {
-		struct gsm_sms_pending *pending;
-		struct gsm_sms *sms;
-
-
-		sms = smsq_take_next_sms(smsq->network, smsq->last_msisdn,
-					 sizeof(smsq->last_msisdn));
-		if (!sms) {
-			LOGP(DLSMS, LOGL_DEBUG, "Sending SMS done (%d attempted)\n",
-			     attempted);
-			break;
-		}
-
-		rounds += 1;
-		LOGP(DLSMS, LOGL_DEBUG, "Sending SMS round %d\n", rounds);
-
-		/*
-		 * This code needs to detect a loop. It assumes that no SMS
-		 * will vanish during the time this is executed. We will remember
-		 * the id of the first GSM subscriber we see and then will
-		 * compare this. The Database code should make sure that we will
-		 * see all other subscribers first before seeing this one again.
-		 *
-		 * It is always scary to have an infinite loop like this.
-		 */
-		if (!initialized) {
-			first_sub = sms->receiver->id;
-			initialized = 1;
-		} else if (first_sub == sms->receiver->id) {
-			LOGP(DLSMS, LOGL_DEBUG, "Sending SMS done (loop) (%d attempted)\n",
-			     attempted);
-			sms_free(sms);
-			break;
-		}
-
-		/* no need to send a pending sms */
-		if (sms_is_in_pending(smsq, sms)) {
-			LOGP(DLSMS, LOGL_DEBUG,
-			     "SMSqueue with pending sms: %llu. Skipping\n", sms->id);
-			sms_free(sms);
-			continue;
-		}
-
-		/* no need to send a SMS with the same receiver */
-		if (sms_subscriber_is_pending(smsq, sms->receiver)) {
-			LOGP(DLSMS, LOGL_DEBUG,
-			     "SMSqueue with pending sub: %llu. Skipping\n", sms->receiver->id);
-			sms_free(sms);
-			continue;
-		}
-
-		pending = sms_pending_from(smsq, sms);
-		if (!pending) {
-			LOGP(DLSMS, LOGL_ERROR,
-			     "Failed to create pending SMS entry.\n");
-			sms_free(sms);
-			continue;
-		}
-
-		attempted += 1;
-		smsq->pending += 1;
-		llist_add_tail(&pending->entry, &smsq->pending_sms);
-		gsm411_send_sms_subscr(sms->receiver, sms);
-	} while (attempted < attempts && rounds < 1000);
-
-	LOGP(DLSMS, LOGL_DEBUG, "SMSqueue added %d messages in %d rounds\n", attempted, rounds);
-}
-
-/**
- * Send the next SMS or trigger the queue
- */
-static void sms_send_next(struct vlr_subscr *vsub)
-{
-	struct gsm_network *net = vsub->vlr->user_ctx;
-	struct gsm_sms_queue *smsq = net->sms_queue;
-	struct gsm_sms_pending *pending;
-	struct gsm_sms *sms;
-
-	/* the subscriber should not be in the queue */
-	OSMO_ASSERT(!sms_subscriber_is_pending(smsq, vsub));
-
-	/* check for more messages for this subscriber */
-	sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
-	if (!sms)
-		goto no_pending_sms;
-
-	/* The sms should not be scheduled right now */
-	OSMO_ASSERT(!sms_is_in_pending(smsq, sms));
-
-	/* Remember that we deliver this SMS and send it */
-	pending = sms_pending_from(smsq, sms);
-	if (!pending) {
-		LOGP(DLSMS, LOGL_ERROR,
-			"Failed to create pending SMS entry.\n");
-		sms_free(sms);
-		goto no_pending_sms;
-	}
-
-	smsq->pending += 1;
-	llist_add_tail(&pending->entry, &smsq->pending_sms);
-	gsm411_send_sms_subscr(sms->receiver, sms);
-	return;
-
-no_pending_sms:
-	/* Try to send the SMS to avoid the queue being stuck */
-	sms_submit_pending(net->sms_queue);
-}
-
-/*
- * Kick off the queue again.
- */
-int sms_queue_trigger(struct gsm_sms_queue *smsq)
-{
-	LOGP(DLSMS, LOGL_DEBUG, "Triggering SMS queue\n");
-	if (osmo_timer_pending(&smsq->push_queue))
-		return 0;
-
-	osmo_timer_schedule(&smsq->push_queue, 1, 0);
-	return 0;
-}
-
-int sms_queue_start(struct gsm_network *network, int max_pending)
-{
-	struct gsm_sms_queue *sms = talloc_zero(network, struct gsm_sms_queue);
-	if (!sms) {
-		LOGP(DMSC, LOGL_ERROR, "Failed to create the SMS queue.\n");
-		return -1;
-	}
-
-	osmo_signal_register_handler(SS_SUBSCR, sms_subscr_cb, network);
-	osmo_signal_register_handler(SS_SMS, sms_sms_cb, network);
-
-	network->sms_queue = sms;
-	INIT_LLIST_HEAD(&sms->pending_sms);
-	sms->max_fail = 1;
-	sms->network = network;
-	sms->max_pending = max_pending;
-	osmo_timer_setup(&sms->push_queue, sms_submit_pending, sms);
-	osmo_timer_setup(&sms->resend_pending, sms_resend_pending, sms);
-
-	sms_submit_pending(sms);
-
-	return 0;
-}
-
-static int sub_ready_for_sm(struct gsm_network *net, struct vlr_subscr *vsub)
-{
-	struct gsm_sms *sms;
-	struct gsm_sms_pending *pending;
-	struct gsm_subscriber_connection *conn;
-
-	/*
-	 * The code used to be very clever and tried to submit
-	 * a SMS during the Location Updating Request. This has
-	 * two issues:
-	 *   1.) The Phone might not be ready yet, e.g. the C155
-	 *       will not respond to the Submit when it is booting.
-	 *   2.) The queue is already trying to submit SMS to the
-	 *	 user and by not responding to the paging request
-	 *	 we will set the LAC back to 0. We would have to
-	 *	 stop the paging and move things over.
-	 *
-	 * We need to be careful in what we try here.
-	 */
-
-	/* check if we have pending requests */
-	pending = sms_subscriber_find_pending(net->sms_queue, vsub);
-	if (pending) {
-		LOGP(DMSC, LOGL_NOTICE,
-		     "Pending paging while subscriber %llu attached.\n",
-		      vsub->id);
-		return 0;
-	}
-
-	conn = connection_for_subscr(vsub);
-	if (!conn)
-		return -1;
-
-	/* Now try to deliver any pending SMS to this sub */
-	sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
-	if (!sms)
-		return -1;
-	gsm411_send_sms(conn, sms);
-	return 0;
-}
-
-static int sms_subscr_cb(unsigned int subsys, unsigned int signal,
-			 void *handler_data, void *signal_data)
-{
-	struct vlr_subscr *vsub = signal_data;
-
-	if (signal != S_SUBSCR_ATTACHED)
-		return 0;
-
-	/* this is readyForSM */
-	return sub_ready_for_sm(handler_data, vsub);
-}
-
-static int sms_sms_cb(unsigned int subsys, unsigned int signal,
-		      void *handler_data, void *signal_data)
-{
-	struct gsm_network *network = handler_data;
-	struct sms_signal_data *sig_sms = signal_data;
-	struct gsm_sms_pending *pending;
-	struct vlr_subscr *vsub;
-
-	/* We got a new SMS and maybe should launch the queue again. */
-	if (signal == S_SMS_SUBMITTED || signal == S_SMS_SMMA) {
-		/* TODO: For SMMA we might want to re-use the radio connection. */
-		sms_queue_trigger(network->sms_queue);
-		return 0;
-	}
-
-	if (!sig_sms->sms)
-		return -1;
-
-
-	/*
-	 * Find the entry of our queue. The SMS subsystem will submit
-	 * sms that are not in our control as we just have a channel
-	 * open anyway.
-	 */
-	pending = sms_find_pending(network->sms_queue, sig_sms->sms);
-	if (!pending)
-		return 0;
-
-	switch (signal) {
-	case S_SMS_DELIVERED:
-		/* Remember the subscriber and clear the pending entry */
-		network->sms_queue->pending -= 1;
-		vsub = vlr_subscr_get(pending->vsub);
-		sms_pending_free(pending);
-		/* Attempt to send another SMS to this subscriber */
-		sms_send_next(vsub);
-		vlr_subscr_put(vsub);
-		break;
-	case S_SMS_MEM_EXCEEDED:
-		network->sms_queue->pending -= 1;
-		sms_pending_free(pending);
-		sms_queue_trigger(network->sms_queue);
-		break;
-	case S_SMS_UNKNOWN_ERROR:
-		/*
-		 * There can be many reasons for this failure. E.g. the paging
-		 * timed out, the subscriber was not paged at all, or there was
-		 * a protocol error. The current strategy is to try sending the
-		 * next SMS for busy/oom and to retransmit when we have paged.
-		 *
-		 * When the paging expires three times we will disable the
-		 * subscriber. If we have some kind of other transmit error we
-		 * should flag the SMS as bad.
-		 */
-		switch (sig_sms->paging_result) {
-		case 0:
-			/* BAD SMS? */
-			db_sms_inc_deliver_attempts(sig_sms->sms);
-			sms_pending_failed(pending, 0);
-			break;
-		case GSM_PAGING_EXPIRED:
-			sms_pending_failed(pending, 1);
-			break;
-
-		case GSM_PAGING_OOM:
-		case GSM_PAGING_BUSY:
-			network->sms_queue->pending -= 1;
-			sms_pending_free(pending);
-			sms_queue_trigger(network->sms_queue);
-			break;
-		default:
-			LOGP(DLSMS, LOGL_ERROR, "Unhandled result: %d\n",
-			     sig_sms->paging_result);
-		}
-		break;
-	default:
-		LOGP(DLSMS, LOGL_ERROR, "Unhandled result: %d\n",
-		     sig_sms->paging_result);
-	}
-
-	return 0;
-}
-
-/* VTY helper functions */
-int sms_queue_stats(struct gsm_sms_queue *smsq, struct vty *vty)
-{
-	struct gsm_sms_pending *pending;
-
-	vty_out(vty, "SMSqueue with max_pending: %d pending: %d%s",
-		smsq->max_pending, smsq->pending, VTY_NEWLINE);
-
-	llist_for_each_entry(pending, &smsq->pending_sms, entry)
-		vty_out(vty, " SMS Pending for Subscriber: %llu SMS: %llu Failed: %d.%s",
-			pending->vsub->id, pending->sms_id,
-			pending->failed_attempts, VTY_NEWLINE);
-	return 0;
-}
-
-int sms_queue_set_max_pending(struct gsm_sms_queue *smsq, int max_pending)
-{
-	LOGP(DLSMS, LOGL_NOTICE, "SMSqueue old max: %d new: %d\n",
-	     smsq->max_pending, max_pending);
-	smsq->max_pending = max_pending;
-	return 0;
-}
-
-int sms_queue_set_max_failure(struct gsm_sms_queue *smsq, int max_fail)
-{
-	LOGP(DLSMS, LOGL_NOTICE, "SMSqueue max failure old: %d new: %d\n",
-	     smsq->max_fail, max_fail);
-	smsq->max_fail = max_fail;
-	return 0;
-}
-
-int sms_queue_clear(struct gsm_sms_queue *smsq)
-{
-	struct gsm_sms_pending *pending, *tmp;
-
-	llist_for_each_entry_safe(pending, tmp, &smsq->pending_sms, entry) {
-		LOGP(DLSMS, LOGL_NOTICE,
-		     "SMSqueue clearing for sub %llu\n", pending->vsub->id);
-		sms_pending_free(pending);
-	}
-
-	smsq->pending = 0;
-	return 0;
-}
diff --git a/src/libmsc/subscr_conn.c b/src/libmsc/subscr_conn.c
deleted file mode 100644
index bcab8e4..0000000
--- a/src/libmsc/subscr_conn.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/* MSC subscriber connection implementation */
-
-/*
- * (C) 2016 by sysmocom s.m.f.c. <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/>.
- *
- */
-
-#include <osmocom/core/logging.h>
-#include <osmocom/core/fsm.h>
-#include <osmocom/core/signal.h>
-
-#include <openbsc/osmo_msc.h>
-#include <openbsc/vlr.h>
-#include <openbsc/debug.h>
-#include <openbsc/transaction.h>
-#include <openbsc/signal.h>
-#include <openbsc/a_iface.h>
-
-#define SUBSCR_CONN_TIMEOUT 5 /* seconds */
-
-static const struct value_string subscr_conn_fsm_event_names[] = {
-	OSMO_VALUE_STRING(SUBSCR_CONN_E_INVALID),
-	OSMO_VALUE_STRING(SUBSCR_CONN_E_START),
-	OSMO_VALUE_STRING(SUBSCR_CONN_E_ACCEPTED),
-	OSMO_VALUE_STRING(SUBSCR_CONN_E_COMMUNICATING),
-	OSMO_VALUE_STRING(SUBSCR_CONN_E_BUMP),
-	OSMO_VALUE_STRING(SUBSCR_CONN_E_MO_CLOSE),
-	OSMO_VALUE_STRING(SUBSCR_CONN_E_CN_CLOSE),
-	{ 0, NULL }
-};
-
-const struct value_string subscr_conn_from_names[] = {
-	OSMO_VALUE_STRING(SUBSCR_CONN_FROM_INVALID),
-	OSMO_VALUE_STRING(SUBSCR_CONN_FROM_LU),
-	OSMO_VALUE_STRING(SUBSCR_CONN_FROM_CM_SERVICE_REQ),
-	OSMO_VALUE_STRING(SUBSCR_CONN_FROM_PAGING_RESP),
-	{ 0, NULL }
-};
-
-static void paging_event(struct gsm_subscriber_connection *conn,
-			 enum gsm_paging_event pe)
-{
-	subscr_paging_dispatch(GSM_HOOK_RR_PAGING, pe, NULL, conn, conn->vsub);
-}
-
-void subscr_conn_fsm_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	OSMO_ASSERT(event == SUBSCR_CONN_E_START);
-	osmo_fsm_inst_state_chg(fi, SUBSCR_CONN_S_NEW,
-				SUBSCR_CONN_TIMEOUT, 0);
-}
-
-void subscr_conn_fsm_new(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct gsm_subscriber_connection *conn = fi->priv;
-	enum subscr_conn_from from = SUBSCR_CONN_FROM_INVALID;
-	bool success;
-
-	if (data) {
-		from = *(enum subscr_conn_from*)data;
-		LOGPFSM(fi, "%s\n", subscr_conn_from_name(from));
-	}
-
-	/* If accepted, transition the state, all other cases mean failure. */
-	switch (event) {
-	case SUBSCR_CONN_E_ACCEPTED:
-		osmo_fsm_inst_state_chg(fi, SUBSCR_CONN_S_ACCEPTED,
-					SUBSCR_CONN_TIMEOUT, 0);
-		break;
-
-	case SUBSCR_CONN_E_MO_CLOSE:
-	case SUBSCR_CONN_E_CN_CLOSE:
-		if (data)
-			LOGPFSM(fi, "Close event, cause %u\n",
-				*(uint32_t*)data);
-		/* will release further below, see
-		 * 'if (fi->state != SUBSCR_CONN_S_ACCEPTED)' */
-		break;
-
-	default:
-		LOGPFSML(fi, LOGL_ERROR,
-			 "Unexpected event: %d %s\n", event,
-			 osmo_fsm_event_name(fi->fsm, event));
-		break;
-	}
-
-	success = (fi->state == SUBSCR_CONN_S_ACCEPTED);
-
-	if (from == SUBSCR_CONN_FROM_LU)
-		rate_ctr_inc(&conn->network->msc_ctrs->ctr[
-		             	success ? MSC_CTR_LOC_UPDATE_COMPLETED
-					: MSC_CTR_LOC_UPDATE_FAILED]);
-
-	/* signal paging success or failure in case this was a paging */
-	if (from == SUBSCR_CONN_FROM_PAGING_RESP)
-		paging_event(conn,
-			     success ? GSM_PAGING_SUCCEEDED
-			     	     : GSM_PAGING_EXPIRED);
-
-	/* FIXME rate counters */
-	/*rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED]);*/
-
-	/* On failure, discard the conn */
-	if (!success) {
-		/* TODO: on MO_CLOSE or CN_CLOSE, first go to RELEASING and
-		 * await BSC/RNC confirmation? */
-		osmo_fsm_inst_state_chg(fi, SUBSCR_CONN_S_RELEASED, 0, 0);
-		return;
-	}
-
-	if (from == SUBSCR_CONN_FROM_CM_SERVICE_REQ) {
-		conn->received_cm_service_request = true;
-		LOGPFSML(fi, LOGL_DEBUG, "received_cm_service_request = true\n");
-	}
-
-	osmo_fsm_inst_dispatch(fi, SUBSCR_CONN_E_BUMP, data);
-}
-
-static void subscr_conn_fsm_bump(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct gsm_subscriber_connection *conn = fi->priv;
-	struct gsm_trans *trans;
-
-	if (conn->silent_call) {
-		LOGPFSML(fi, LOGL_DEBUG, "bump: silent call still active\n");
-		return;
-	}
-
-	if (conn->received_cm_service_request) {
-		LOGPFSML(fi, LOGL_DEBUG, "bump: still awaiting first request after a CM Service Request\n");
-		return;
-	}
-
-	if (conn->vsub && !llist_empty(&conn->vsub->cs.requests)) {
-		struct subscr_request *sr;
-		if (!log_check_level(fi->fsm->log_subsys, LOGL_DEBUG)) {
-			llist_for_each_entry(sr, &conn->vsub->cs.requests, entry) {
-				LOGPFSML(fi, LOGL_DEBUG, "bump: still active: %s\n",
-					 sr->label);
-			}
-		}
-		return;
-	}
-
-	if ((trans = trans_has_conn(conn))) {
-		LOGPFSML(fi, LOGL_DEBUG,
-			 "bump: connection still has active transaction: %s\n",
-			 gsm48_pdisc_name(trans->protocol));
-		return;
-	}
-
-	LOGPFSML(fi, LOGL_DEBUG, "bump: releasing conn\n");
-	osmo_fsm_inst_state_chg(fi, SUBSCR_CONN_S_RELEASED, 0, 0);
-}
-
-static void subscr_conn_fsm_accepted_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
-{
-	struct gsm_subscriber_connection *conn = fi->priv;
-	osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_ATTACHED, conn->vsub);
-}
-
-static void subscr_conn_fsm_accepted(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	switch (event) {
-	case SUBSCR_CONN_E_COMMUNICATING:
-		osmo_fsm_inst_state_chg(fi, SUBSCR_CONN_S_COMMUNICATING, 0, 0);
-		return;
-
-	case SUBSCR_CONN_E_BUMP:
-		subscr_conn_fsm_bump(fi, event, data);
-		return;
-
-	default:
-		break;
-	}
-	/* Whatever unexpected happens in the accepted state, it means release.
-	 * Even if an unexpected event is passed, the safest thing to do is
-	 * discard the conn. We don't expect another SUBSCR_CONN_E_ACCEPTED. */
-	osmo_fsm_inst_state_chg(fi, SUBSCR_CONN_S_RELEASED, 0, 0);
-}
-
-static void subscr_conn_fsm_communicating(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	switch (event) {
-	case SUBSCR_CONN_E_COMMUNICATING:
-		/* no-op */
-		return;
-
-	case SUBSCR_CONN_E_BUMP:
-		subscr_conn_fsm_bump(fi, event, data);
-		return;
-
-	default:
-		break;
-	}
-	/* Whatever unexpected happens in the accepted state, it means release.
-	 * Even if an unexpected event is passed, the safest thing to do is
-	 * discard the conn. We don't expect another SUBSCR_CONN_E_ACCEPTED. */
-	osmo_fsm_inst_state_chg(fi, SUBSCR_CONN_S_RELEASED, 0, 0);
-}
-
-static void subscr_conn_fsm_cleanup(struct osmo_fsm_inst *fi,
-				    enum osmo_fsm_term_cause cause)
-{
-	struct gsm_subscriber_connection *conn = fi->priv;
-	fi->priv = NULL;
-
-	if (!conn)
-		return;
-	conn->conn_fsm = NULL;
- 	msc_subscr_conn_close(conn, cause);
-	msc_subscr_conn_put(conn);
-}
-
-int subscr_conn_fsm_timeout(struct osmo_fsm_inst *fi)
-{
-	struct gsm_subscriber_connection *conn = fi->priv;
-	if (conn)
-		vlr_subscr_conn_timeout(conn->vsub);
-	osmo_fsm_inst_dispatch(fi, SUBSCR_CONN_E_CN_CLOSE, NULL);
-	return 0;
-}
-
-static void subscr_conn_fsm_release(struct osmo_fsm_inst *fi, uint32_t prev_state)
-{
-	osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
-}
-
-#define S(x)	(1 << (x))
-
-static const struct osmo_fsm_state subscr_conn_fsm_states[] = {
-	[SUBSCR_CONN_S_INIT] = {
-		.name = OSMO_STRINGIFY(SUBSCR_CONN_S_INIT),
-		.in_event_mask = S(SUBSCR_CONN_E_START),
-		.out_state_mask = S(SUBSCR_CONN_S_NEW),
-		.action = subscr_conn_fsm_init,
-	},
-	[SUBSCR_CONN_S_NEW] = {
-		.name = OSMO_STRINGIFY(SUBSCR_CONN_S_NEW),
-		.in_event_mask = S(SUBSCR_CONN_E_ACCEPTED) |
-				 S(SUBSCR_CONN_E_MO_CLOSE) |
-				 S(SUBSCR_CONN_E_CN_CLOSE),
-		.out_state_mask = S(SUBSCR_CONN_S_ACCEPTED) |
-				  S(SUBSCR_CONN_S_RELEASED),
-		.action = subscr_conn_fsm_new,
-	},
-	[SUBSCR_CONN_S_ACCEPTED] = {
-		.name = OSMO_STRINGIFY(SUBSCR_CONN_S_ACCEPTED),
-		/* allow everything to release for any odd behavior */
-		.in_event_mask = S(SUBSCR_CONN_E_COMMUNICATING) |
-		                 S(SUBSCR_CONN_E_BUMP) |
-				 S(SUBSCR_CONN_E_ACCEPTED) |
-				 S(SUBSCR_CONN_E_MO_CLOSE) |
-				 S(SUBSCR_CONN_E_CN_CLOSE),
-		.out_state_mask = S(SUBSCR_CONN_S_RELEASED) |
-				  S(SUBSCR_CONN_S_COMMUNICATING),
-		.onenter = subscr_conn_fsm_accepted_enter,
-		.action = subscr_conn_fsm_accepted,
-	},
-	[SUBSCR_CONN_S_COMMUNICATING] = {
-		.name = OSMO_STRINGIFY(SUBSCR_CONN_S_COMMUNICATING),
-		/* allow everything to release for any odd behavior */
-		.in_event_mask = S(SUBSCR_CONN_E_BUMP) |
-				 S(SUBSCR_CONN_E_ACCEPTED) |
-				 S(SUBSCR_CONN_E_COMMUNICATING) |
-				 S(SUBSCR_CONN_E_MO_CLOSE) |
-				 S(SUBSCR_CONN_E_CN_CLOSE),
-		.out_state_mask = S(SUBSCR_CONN_S_RELEASED),
-		.action = subscr_conn_fsm_communicating,
-	},
-	[SUBSCR_CONN_S_RELEASED] = {
-		.name = OSMO_STRINGIFY(SUBSCR_CONN_S_RELEASED),
-		.onenter = subscr_conn_fsm_release,
-	},
-};
-
-static struct osmo_fsm subscr_conn_fsm = {
-	.name = "Subscr_Conn",
-	.states = subscr_conn_fsm_states,
-	.num_states = ARRAY_SIZE(subscr_conn_fsm_states),
-	.allstate_event_mask = 0,
-	.allstate_action = NULL,
-	.log_subsys = DMM,
-	.event_names = subscr_conn_fsm_event_names,
-	.cleanup = subscr_conn_fsm_cleanup,
-	.timer_cb = subscr_conn_fsm_timeout,
-};
-
-int msc_create_conn_fsm(struct gsm_subscriber_connection *conn, const char *id)
-{
-	struct osmo_fsm_inst *fi;
-	OSMO_ASSERT(conn);
-
-	if (conn->conn_fsm) {
-		LOGP(DMM, LOGL_ERROR,
-		     "%s: Error: connection already in use\n", id);
-		return -EINVAL;
-	}
-
-	/* Allocate the FSM not with the subscr_conn. Semantically it would
-	 * make sense, but in subscr_conn_fsm_cleanup(), we want to discard the
-	 * subscriber connection. If the FSM is freed along with the subscriber
-	 * connection, then in _osmo_fsm_inst_term() the osmo_fsm_inst_free()
-	 * that follows the cleanup() call would run into a double free. */
-	fi = osmo_fsm_inst_alloc(&subscr_conn_fsm, conn->network,
-				 msc_subscr_conn_get(conn),
-				 LOGL_DEBUG, id);
-
-	if (!fi) {
-		LOGP(DMM, LOGL_ERROR,
-		     "%s: Failed to allocate subscr conn master FSM\n", id);
-		return -ENOMEM;
-	}
-	conn->conn_fsm = fi;
-	osmo_fsm_inst_dispatch(conn->conn_fsm, SUBSCR_CONN_E_START, NULL);
-	return 0;
-}
-
-bool msc_subscr_conn_is_accepted(struct gsm_subscriber_connection *conn)
-{
-	if (!conn)
-		return false;
-	if (!conn->vsub)
-		return false;
-	if (!conn->conn_fsm)
-		return false;
-	if (!(conn->conn_fsm->state == SUBSCR_CONN_S_ACCEPTED
-	      || conn->conn_fsm->state == SUBSCR_CONN_S_COMMUNICATING))
-		return false;
-	return true;
-}
-
-void msc_subscr_conn_communicating(struct gsm_subscriber_connection *conn)
-{
-	OSMO_ASSERT(conn);
-	osmo_fsm_inst_dispatch(conn->conn_fsm, SUBSCR_CONN_E_COMMUNICATING,
-			       NULL);
-}
-
-void msc_subscr_conn_init(void)
-{
-	osmo_fsm_register(&subscr_conn_fsm);
-}
diff --git a/src/libmsc/transaction.c b/src/libmsc/transaction.c
deleted file mode 100644
index 28e0914..0000000
--- a/src/libmsc/transaction.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/* GSM 04.07 Transaction handling */
-
-/* (C) 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/>.
- *
- */
-
-#include <openbsc/transaction.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/mncc.h>
-#include <openbsc/debug.h>
-#include <osmocom/core/talloc.h>
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/mncc.h>
-#include <openbsc/paging.h>
-#include <openbsc/osmo_msc.h>
-#include <openbsc/vlr.h>
-
-void *tall_trans_ctx;
-
-void _gsm48_cc_trans_free(struct gsm_trans *trans);
-
-/*! Find a transaction in connection for given protocol + transaction ID
- * \param[in] conn Connection in whihc we want to find transaction
- * \param[in] proto Protocol of transaction
- * \param[in] trans_id Transaction ID of transaction
- * \returns Matching transaction, if any
- */
-struct gsm_trans *trans_find_by_id(struct gsm_subscriber_connection *conn,
-				   uint8_t proto, uint8_t trans_id)
-{
-	struct gsm_trans *trans;
-	struct gsm_network *net = conn->network;
-	struct vlr_subscr *vsub = conn->vsub;
-
-	llist_for_each_entry(trans, &net->trans_list, entry) {
-		if (trans->vsub == vsub &&
-		    trans->protocol == proto &&
-		    trans->transaction_id == trans_id)
-			return trans;
-	}
-	return NULL;
-}
-
-/*! Find a transaction by call reference
- * \param[in] net Network in which we should search
- * \param[in] callref Call Reference of transaction
- * \returns Matching transaction, if any
- */
-struct gsm_trans *trans_find_by_callref(struct gsm_network *net,
-					uint32_t callref)
-{
-	struct gsm_trans *trans;
-
-	llist_for_each_entry(trans, &net->trans_list, entry) {
-		if (trans->callref == callref)
-			return trans;
-	}
-	return NULL;
-}
-
-/*! Allocate a new transaction and add it to network list
- *  \param[in] net Netwokr in which we allocate transaction
- *  \param[in] subscr Subscriber for which we allocate transaction
- *  \param[in] protocol Protocol (CC/SMS/...)
- *  \param[in] callref Call Reference
- *  \returns Transaction
- */
-struct gsm_trans *trans_alloc(struct gsm_network *net,
-			      struct vlr_subscr *vsub,
-			      uint8_t protocol, uint8_t trans_id,
-			      uint32_t callref)
-{
-	struct gsm_trans *trans;
-
-	DEBUGP(DCC, "subscr=%p, net=%p\n", vsub, net);
-
-	/* a valid subscriber is indispensable */
-	if (vsub == NULL) {
-		LOGP(DCC, LOGL_NOTICE,
-		     "unable to alloc transaction, invalid subscriber (NULL)\n");
-		return NULL;
-	}
-
-	trans = talloc_zero(tall_trans_ctx, struct gsm_trans);
-	if (!trans)
-		return NULL;
-
-	trans->vsub = vlr_subscr_get(vsub);
-
-	trans->protocol = protocol;
-	trans->transaction_id = trans_id;
-	trans->callref = callref;
-
-	trans->net = net;
-	llist_add_tail(&trans->entry, &net->trans_list);
-
-	return trans;
-}
-
-/*! Release a transaction
- * \param[in] trans Transaction to be released
- */
-void trans_free(struct gsm_trans *trans)
-{
-	switch (trans->protocol) {
-	case GSM48_PDISC_CC:
-		_gsm48_cc_trans_free(trans);
-		break;
-	case GSM48_PDISC_SMS:
-		_gsm411_sms_trans_free(trans);
-		break;
-	}
-
-	if (trans->paging_request) {
-		subscr_remove_request(trans->paging_request);
-		trans->paging_request = NULL;
-	}
-
-	if (trans->vsub) {
-		vlr_subscr_put(trans->vsub);
-		trans->vsub = NULL;
-	}
-
-	llist_del(&trans->entry);
-
-	if (trans->conn)
-		msc_subscr_conn_put(trans->conn);
-
-	trans->conn = NULL;
-	talloc_free(trans);
-}
-
-/*! allocate an unused transaction ID for the given subscriber
- * in the given protocol using the ti_flag specified
- * \param[in] net GSM network
- * \param[in] subscr Subscriber for which to find ID
- * \param[in] protocol Protocol for whihc to find ID
- * \param[in] ti_flag FIXME
- */
-int trans_assign_trans_id(struct gsm_network *net, struct vlr_subscr *vsub,
-			  uint8_t protocol, uint8_t ti_flag)
-{
-	struct gsm_trans *trans;
-	unsigned int used_tid_bitmask = 0;
-	int i, j, h;
-
-	if (ti_flag)
-		ti_flag = 0x8;
-
-	/* generate bitmask of already-used TIDs for this (subscr,proto) */
-	llist_for_each_entry(trans, &net->trans_list, entry) {
-		if (trans->vsub != vsub ||
-		    trans->protocol != protocol ||
-		    trans->transaction_id == 0xff)
-			continue;
-		used_tid_bitmask |= (1 << trans->transaction_id);
-	}
-
-	/* find a new one, trying to go in a 'circular' pattern */
-	for (h = 6; h > 0; h--)
-		if (used_tid_bitmask & (1 << (h | ti_flag)))
-			break;
-	for (i = 0; i < 7; i++) {
-		j = ((h + i) % 7) | ti_flag;
-		if ((used_tid_bitmask & (1 << j)) == 0)
-			return j;
-	}
-
-	return -1;
-}
-
-/*! Check if we have any transaction for given connection
- * \param[in] conn Connection to check
- * \returns 1 in case there is a transaction, 0 otherwise
- */
-struct gsm_trans *trans_has_conn(const struct gsm_subscriber_connection *conn)
-{
-	struct gsm_trans *trans;
-
-	llist_for_each_entry(trans, &conn->network->trans_list, entry)
-		if (trans->conn == conn)
-			return trans;
-
-	return NULL;
-}
-
-/*! Free all transactions associated with a connection, presumably when the
- * conn is being closed. The transaction code will inform the CC or SMS
- * facilities, which will then send the necessary release indications.
- * \param[in] conn Connection that is going to be closed.
- */
-void trans_conn_closed(struct gsm_subscriber_connection *conn)
-{
-	struct gsm_trans *trans;
-
-	/* As part of the CC REL_IND the remote leg might be released and this
-	 * will trigger another call to trans_free. This is something the llist
-	 * macro can not handle and we need to re-iterate the list every time.
-	 */
-restart:
-	llist_for_each_entry(trans, &conn->network->trans_list, entry) {
-		if (trans->conn == conn) {
-			trans_free(trans);
-			goto restart;
-		}
-	}
-}
diff --git a/src/libmsc/ussd.c b/src/libmsc/ussd.c
deleted file mode 100644
index 81a3566..0000000
--- a/src/libmsc/ussd.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/* Network-specific handling of mobile-originated USSDs. */
-
-/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009 by Mike Haben <michael.haben@btinternet.com>
- *
- * 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/>.
- *
- */
-
-/* This module defines the network-specific handling of mobile-originated
-   USSD messages. */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <openbsc/gsm_04_80.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/debug.h>
-#include <openbsc/osmo_msc.h>
-#include <openbsc/vlr.h>
-
-/* Declarations of USSD strings to be recognised */
-const char USSD_TEXT_OWN_NUMBER[] = "*#100#";
-
-/* Forward declarations of network-specific handler functions */
-static int send_own_number(struct gsm_subscriber_connection *conn, const struct msgb *msg, const struct ss_request *req);
-
-
-/* Entrypoint - handler function common to all mobile-originated USSDs */
-int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	int rc;
-	struct ss_request req;
-	struct gsm48_hdr *gh;
-
-	/* TODO: Use subscriber_connection ref-counting if we ever want
-	 * to keep the connection alive due ot ongoing USSD exchange.
-	 * As we answer everytying synchronously so far, there's no need
-	 * yet */
-
-	cm_service_request_concludes(conn, msg);
-
-	memset(&req, 0, sizeof(req));
-	gh = msgb_l3(msg);
-	rc = gsm0480_decode_ss_request(gh, msgb_l3len(msg), &req);
-	if (!rc) {
-		DEBUGP(DMM, "Unhandled SS\n");
-		rc = gsm0480_send_ussd_reject(conn, msg, &req);
-		return rc;
-	}
-
-	/* Interrogation or releaseComplete? */
-	if (req.ussd_text[0] == '\0' || req.ussd_text[0] == 0xFF) {
-		if (req.ss_code > 0) {
-			/* Assume interrogateSS or modification of it and reject */
-			rc = gsm0480_send_ussd_reject(conn, msg, &req);
-			return rc;
-		}
-		/* Still assuming a Release-Complete and returning */
-		return 0;
-	}
-
-	msc_subscr_conn_communicating(conn);
-	if (!strcmp(USSD_TEXT_OWN_NUMBER, (const char *)req.ussd_text)) {
-		DEBUGP(DMM, "USSD: Own number requested\n");
-		rc = send_own_number(conn, msg, &req);
-	} else {
-		DEBUGP(DMM, "Unhandled USSD %s\n", req.ussd_text);
-		rc = gsm0480_send_ussd_reject(conn, msg, &req);
-	}
-
-	return rc;
-}
-
-/* A network-specific handler function */
-static int send_own_number(struct gsm_subscriber_connection *conn, const struct msgb *msg, const struct ss_request *req)
-{
-	char *own_number = conn->vsub->msisdn;
-	char response_string[GSM_EXTENSION_LENGTH + 20];
-
-	DEBUGP(DMM, "%s: MSISDN = %s\n", vlr_subscr_name(conn->vsub),
-	       own_number);
-
-	/* Need trailing CR as EOT character */
-	snprintf(response_string, sizeof(response_string), "Your extension is %s\r", own_number);
-	return gsm0480_send_ussd_response(conn, msg, response_string, req);
-}
diff --git a/src/libmsc/vty_interface_layer3.c b/src/libmsc/vty_interface_layer3.c
deleted file mode 100644
index 864597d..0000000
--- a/src/libmsc/vty_interface_layer3.c
+++ /dev/null
@@ -1,979 +0,0 @@
-/* OpenBSC interface to quagga VTY */
-/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009-2011 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/>.
- *
- */
-
-#include <stdlib.h>
-#include <limits.h>
-#include <unistd.h>
-#include <time.h>
-#include <inttypes.h>
-
-#include <osmocom/vty/command.h>
-#include <osmocom/vty/buffer.h>
-#include <osmocom/vty/vty.h>
-
-#include <arpa/inet.h>
-
-#include <osmocom/core/linuxlist.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/bsc_subscriber.h>
-#include <openbsc/silent_call.h>
-#include <openbsc/gsm_04_11.h>
-#include <osmocom/abis/e1_input.h>
-#include <openbsc/abis_nm.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/core/utils.h>
-#include <openbsc/db.h>
-#include <osmocom/core/talloc.h>
-#include <openbsc/signal.h>
-#include <openbsc/debug.h>
-#include <openbsc/vty.h>
-#include <openbsc/gsm_04_80.h>
-#include <openbsc/gsm_04_14.h>
-#include <openbsc/chan_alloc.h>
-#include <openbsc/sms_queue.h>
-#include <openbsc/mncc_int.h>
-#include <openbsc/handover.h>
-#include <openbsc/vlr.h>
-
-#include <osmocom/vty/logging.h>
-
-#include <openbsc/osmo_msc.h>
-
-#include "meas_feed.h"
-
-extern struct gsm_network *gsmnet_from_vty(struct vty *v);
-
-static void subscr_dump_full_vty(struct vty *vty, struct vlr_subscr *vsub)
-{
-	int reqs;
-	struct llist_head *entry;
-	char expire_time[200];
-
-	if (strlen(vsub->name))
-		vty_out(vty, "    Name: '%s'%s", vsub->name, VTY_NEWLINE);
-	if (strlen(vsub->msisdn))
-		vty_out(vty, "    Extension: %s%s", vsub->msisdn,
-			VTY_NEWLINE);
-	vty_out(vty, "    LAC: %d/0x%x%s",
-		vsub->lac, vsub->lac, VTY_NEWLINE);
-	vty_out(vty, "    IMSI: %s%s", vsub->imsi, VTY_NEWLINE);
-	if (vsub->tmsi != GSM_RESERVED_TMSI)
-		vty_out(vty, "    TMSI: %08X%s", vsub->tmsi,
-			VTY_NEWLINE);
-	if (vsub->tmsi_new != GSM_RESERVED_TMSI)
-		vty_out(vty, "    new TMSI: %08X%s", vsub->tmsi_new,
-			VTY_NEWLINE);
-
-#if 0
-	/* TODO: add this to vlr_subscr? */
-	if (vsub->auth_info.auth_algo != AUTH_ALGO_NONE) {
-		struct gsm_auth_info *i = &vsub->auth_info;
-		vty_out(vty, "    A3A8 algorithm id: %d%s",
-			i->auth_algo, VTY_NEWLINE);
-		vty_out(vty, "    A3A8 Ki: %s%s",
-			osmo_hexdump(i->a3a8_ki, i->a3a8_ki_len),
-			VTY_NEWLINE);
-	}
-#endif
-
-	if (vsub->last_tuple) {
-		struct gsm_auth_tuple *t = vsub->last_tuple;
-		vty_out(vty, "    A3A8 last tuple (used %d times):%s",
-			t->use_count, VTY_NEWLINE);
-		vty_out(vty, "     seq # : %d%s",
-			t->key_seq, VTY_NEWLINE);
-		vty_out(vty, "     RAND  : %s%s",
-			osmo_hexdump(t->vec.rand, sizeof(t->vec.rand)),
-			VTY_NEWLINE);
-		vty_out(vty, "     SRES  : %s%s",
-			osmo_hexdump(t->vec.sres, sizeof(t->vec.sres)),
-			VTY_NEWLINE);
-		vty_out(vty, "     Kc    : %s%s",
-			osmo_hexdump(t->vec.kc, sizeof(t->vec.kc)),
-			VTY_NEWLINE);
-	}
-
-	/* print the expiration time of a subscriber */
-	strftime(expire_time, sizeof(expire_time),
-			"%a, %d %b %Y %T %z", localtime(&vsub->expire_lu));
-	expire_time[sizeof(expire_time) - 1] = '\0';
-	vty_out(vty, "    Expiration Time: %s%s", expire_time, VTY_NEWLINE);
-
-	reqs = 0;
-	llist_for_each(entry, &vsub->cs.requests)
-		reqs += 1;
-	vty_out(vty, "    Paging: %s paging for %d requests%s",
-		vsub->cs.is_paging ? "is" : "not", reqs, VTY_NEWLINE);
-	vty_out(vty, "    Use count: %u%s", vsub->use_count, VTY_NEWLINE);
-}
-
-
-/* Subscriber */
-DEFUN(show_subscr_cache,
-      show_subscr_cache_cmd,
-      "show subscriber cache",
-	SHOW_STR "Show information about subscribers\n"
-	"Display contents of subscriber cache\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	struct vlr_subscr *vsub;
-	int count = 0;
-
-	llist_for_each_entry(vsub, &gsmnet->vlr->subscribers, list) {
-		if (++count > 100) {
-			vty_out(vty, "%% More than %d subscribers in cache,"
-				" stopping here.%s", count-1, VTY_NEWLINE);
-			break;
-		}
-		vty_out(vty, "  Subscriber:%s", VTY_NEWLINE);
-		subscr_dump_full_vty(vty, vsub);
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(sms_send_pend,
-      sms_send_pend_cmd,
-      "sms send pending",
-      "SMS related commands\n" "SMS Sending related commands\n"
-      "Send all pending SMS")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	struct gsm_sms *sms;
-	unsigned long long sms_id = 0;
-
-	while (1) {
-		sms = db_sms_get_next_unsent(gsmnet, sms_id, UINT_MAX);
-		if (!sms)
-			break;
-
-		if (sms->receiver)
-			gsm411_send_sms_subscr(sms->receiver, sms);
-
-		sms_id = sms->id + 1;
-	}
-
-	return CMD_SUCCESS;
-}
-
-static int _send_sms_str(struct vlr_subscr *receiver,
-			 struct vlr_subscr *sender,
-			 char *str, uint8_t tp_pid)
-{
-	struct gsm_network *net = receiver->vlr->user_ctx;
-	struct gsm_sms *sms;
-
-	sms = sms_from_text(receiver, sender, 0, str);
-	sms->protocol_id = tp_pid;
-
-	/* store in database for the queue */
-	if (db_sms_store(sms) != 0) {
-		LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
-		sms_free(sms);
-		return CMD_WARNING;
-	}
-	LOGP(DLSMS, LOGL_DEBUG, "SMS stored in DB\n");
-
-	sms_free(sms);
-	sms_queue_trigger(net->sms_queue);
-	return CMD_SUCCESS;
-}
-
-static struct vlr_subscr *get_vsub_by_argv(struct gsm_network *gsmnet,
-					       const char *type,
-					       const char *id)
-{
-	if (!strcmp(type, "extension") || !strcmp(type, "msisdn"))
-		return vlr_subscr_find_by_msisdn(gsmnet->vlr, id);
-	else if (!strcmp(type, "imsi") || !strcmp(type, "id"))
-		return vlr_subscr_find_by_imsi(gsmnet->vlr, id);
-	else if (!strcmp(type, "tmsi"))
-		return vlr_subscr_find_by_tmsi(gsmnet->vlr, atoi(id));
-
-	return NULL;
-}
-#define SUBSCR_TYPES "(extension|imsi|tmsi|id)"
-#define SUBSCR_HELP "Operations on a Subscriber\n"			\
-	"Identify subscriber by extension (phone number)\n"		\
-	"Identify subscriber by IMSI\n"					\
-	"Identify subscriber by TMSI\n"					\
-	"Identify subscriber by database ID\n"				\
-	"Identifier for the subscriber\n"
-
-DEFUN(show_subscr,
-      show_subscr_cmd,
-      "show subscriber " SUBSCR_TYPES " ID",
-	SHOW_STR SUBSCR_HELP)
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
-						       argv[1]);
-
-	if (!vsub) {
-		vty_out(vty, "%% No subscriber found for %s %s%s",
-			argv[0], argv[1], VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	subscr_dump_full_vty(vty, vsub);
-
-	vlr_subscr_put(vsub);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(subscriber_create,
-      subscriber_create_cmd,
-      "subscriber create imsi ID",
-	"Operations on a Subscriber\n" \
-	"Create new subscriber\n" \
-	"Identify the subscriber by his IMSI\n" \
-	"Identifier for the subscriber\n")
-{
-	vty_out(vty, "%% 'subscriber create' now needs to be done at osmo-hlr%s",
-		VTY_NEWLINE);
-	return CMD_WARNING;
-}
-
-DEFUN(subscriber_send_pending_sms,
-      subscriber_send_pending_sms_cmd,
-      "subscriber " SUBSCR_TYPES " ID sms pending-send",
-	SUBSCR_HELP "SMS Operations\n" "Send pending SMS\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	struct vlr_subscr *vsub;
-	struct gsm_sms *sms;
-
-	vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
-	if (!vsub) {
-		vty_out(vty, "%% No subscriber found for %s %s%s",
-			argv[0], argv[1], VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX);
-	if (sms)
-		gsm411_send_sms_subscr(sms->receiver, sms);
-
-	vlr_subscr_put(vsub);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(subscriber_send_sms,
-      subscriber_send_sms_cmd,
-      "subscriber " SUBSCR_TYPES " ID sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
-	SUBSCR_HELP "SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
-	struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
-	char *str;
-	int rc;
-
-	if (!vsub) {
-		vty_out(vty, "%% No subscriber found for %s %s%s",
-			argv[0], argv[1], VTY_NEWLINE);
-		rc = CMD_WARNING;
-		goto err;
-	}
-
-	if (!sender) {
-		vty_out(vty, "%% No sender found for %s %s%s",
-			argv[2], argv[3], VTY_NEWLINE);
-		rc = CMD_WARNING;
-		goto err;
-	}
-
-	str = argv_concat(argv, argc, 4);
-	rc = _send_sms_str(vsub, sender, str, 0);
-	talloc_free(str);
-
-err:
-	if (sender)
-		vlr_subscr_put(sender);
-
-	if (vsub)
-		vlr_subscr_put(vsub);
-
-	return rc;
-}
-
-DEFUN(subscriber_silent_sms,
-      subscriber_silent_sms_cmd,
-
-      "subscriber " SUBSCR_TYPES " ID silent-sms sender " SUBSCR_TYPES " SENDER_ID send .LINE",
-	SUBSCR_HELP "Silent SMS Operations\n" SUBSCR_HELP "Send SMS\n" "Actual SMS Text\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
-	struct vlr_subscr *sender = get_vsub_by_argv(gsmnet, argv[2], argv[3]);
-	char *str;
-	int rc;
-
-	if (!vsub) {
-		vty_out(vty, "%% No subscriber found for %s %s%s",
-			argv[0], argv[1], VTY_NEWLINE);
-		rc = CMD_WARNING;
-		goto err;
-	}
-
-	if (!sender) {
-		vty_out(vty, "%% No sender found for %s %s%s",
-			argv[2], argv[3], VTY_NEWLINE);
-		rc = CMD_WARNING;
-		goto err;
-	}
-
-	str = argv_concat(argv, argc, 4);
-	rc = _send_sms_str(vsub, sender, str, 64);
-	talloc_free(str);
-
-err:
-	if (sender)
-		vlr_subscr_put(sender);
-
-	if (vsub)
-		vlr_subscr_put(vsub);
-
-	return rc;
-}
-
-#define CHAN_TYPES "(any|tch/f|tch/any|sdcch)"
-#define CHAN_TYPE_HELP 			\
-		"Any channel\n"		\
-		"TCH/F channel\n"	\
-		"Any TCH channel\n"	\
-		"SDCCH channel\n"
-
-DEFUN(subscriber_silent_call_start,
-      subscriber_silent_call_start_cmd,
-      "subscriber " SUBSCR_TYPES " ID silent-call start (any|tch/f|tch/any|sdcch)",
-	SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
-	CHAN_TYPE_HELP)
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
-	int rc, type;
-
-	if (!vsub) {
-		vty_out(vty, "%% No subscriber found for %s %s%s",
-			argv[0], argv[1], VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (!strcmp(argv[2], "tch/f"))
-		type = RSL_CHANNEED_TCH_F;
-	else if (!strcmp(argv[2], "tch/any"))
-		type = RSL_CHANNEED_TCH_ForH;
-	else if (!strcmp(argv[2], "sdcch"))
-		type = RSL_CHANNEED_SDCCH;
-	else
-		type = RSL_CHANNEED_ANY;	/* Defaults to ANY */
-
-	rc = gsm_silent_call_start(vsub, vty, type);
-	if (rc <= 0) {
-		vty_out(vty, "%% Subscriber not attached%s",
-			VTY_NEWLINE);
-		vlr_subscr_put(vsub);
-		return CMD_WARNING;
-	}
-
-	vlr_subscr_put(vsub);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(subscriber_silent_call_stop,
-      subscriber_silent_call_stop_cmd,
-      "subscriber " SUBSCR_TYPES " ID silent-call stop",
-	SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
-	CHAN_TYPE_HELP)
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
-	int rc;
-
-	if (!vsub) {
-		vty_out(vty, "%% No subscriber found for %s %s%s",
-			argv[0], argv[1], VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	rc = gsm_silent_call_stop(vsub);
-	if (rc < 0) {
-		vlr_subscr_put(vsub);
-		return CMD_WARNING;
-	}
-
-	vlr_subscr_put(vsub);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(subscriber_ussd_notify,
-      subscriber_ussd_notify_cmd,
-      "subscriber " SUBSCR_TYPES " ID ussd-notify (0|1|2) .TEXT",
-      SUBSCR_HELP "Send a USSD notify to the subscriber\n"
-      "Alerting Level 0\n"
-      "Alerting Level 1\n"
-      "Alerting Level 2\n"
-      "Text of USSD message to send\n")
-{
-	char *text;
-	struct gsm_subscriber_connection *conn;
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
-	int level;
-
-	if (!vsub) {
-		vty_out(vty, "%% No subscriber found for %s %s%s",
-			argv[0], argv[1], VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	level = atoi(argv[2]);
-	text = argv_concat(argv, argc, 3);
-	if (!text) {
-		vlr_subscr_put(vsub);
-		return CMD_WARNING;
-	}
-
-	conn = connection_for_subscr(vsub);
-	if (!conn) {
-		vty_out(vty, "%% An active connection is required for %s %s%s",
-			argv[0], argv[1], VTY_NEWLINE);
-		vlr_subscr_put(vsub);
-		talloc_free(text);
-		return CMD_WARNING;
-	}
-
-	msc_send_ussd_notify(conn, level, text);
-	msc_send_ussd_release_complete(conn);
-
-	vlr_subscr_put(vsub);
-	talloc_free(text);
-	return CMD_SUCCESS;
-}
-
-static int loop_by_char(uint8_t ch)
-{
-	switch (ch) {
-	case 'a':
-		return GSM414_LOOP_A;
-	case 'b':
-		return GSM414_LOOP_B;
-	case 'c':
-		return GSM414_LOOP_C;
-	case 'd':
-		return GSM414_LOOP_D;
-	case 'e':
-		return GSM414_LOOP_E;
-	case 'f':
-		return GSM414_LOOP_F;
-	case 'i':
-		return GSM414_LOOP_I;
-	}
-	return -1;
-}
-
-DEFUN(subscriber_mstest_close,
-      subscriber_mstest_close_cmd,
-      "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
-      SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
-      "Close a TCH Loop inside the MS\n"
-      "Loop Type A\n"
-      "Loop Type B\n"
-      "Loop Type C\n"
-      "Loop Type D\n"
-      "Loop Type E\n"
-      "Loop Type F\n"
-      "Loop Type I\n")
-{
-	struct gsm_subscriber_connection *conn;
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
-	const char *loop_str;
-	int loop_mode;
-
-	if (!vsub) {
-		vty_out(vty, "%% No subscriber found for %s %s%s",
-			argv[0], argv[1], VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	loop_str = argv[2];
-	loop_mode = loop_by_char(loop_str[0]);
-
-	conn = connection_for_subscr(vsub);
-	if (!conn) {
-		vty_out(vty, "%% An active connection is required for %s %s%s",
-			argv[0], argv[1], VTY_NEWLINE);
-		vlr_subscr_put(vsub);
-		return CMD_WARNING;
-	}
-
-	gsm0414_tx_close_tch_loop_cmd(conn, loop_mode);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(subscriber_mstest_open,
-      subscriber_mstest_open_cmd,
-      "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
-      SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
-      "Open a TCH Loop inside the MS\n")
-{
-	struct gsm_subscriber_connection *conn;
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
-
-	if (!vsub) {
-		vty_out(vty, "%% No subscriber found for %s %s%s",
-			argv[0], argv[1], VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	conn = connection_for_subscr(vsub);
-	if (!conn) {
-		vty_out(vty, "%% An active connection is required for %s %s%s",
-			argv[0], argv[1], VTY_NEWLINE);
-		vlr_subscr_put(vsub);
-		return CMD_WARNING;
-	}
-
-	gsm0414_tx_open_loop_cmd(conn);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(ena_subscr_expire,
-      ena_subscr_expire_cmd,
-      "subscriber " SUBSCR_TYPES " ID expire",
-	SUBSCR_HELP "Expire the subscriber Now\n")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0],
-						       argv[1]);
-
-	if (!vsub) {
-		vty_out(vty, "%% No subscriber found for %s %s%s",
-			argv[0], argv[1], VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	if (vsub->lu_complete) {
-		vsub->lu_complete = false;
-		vlr_subscr_put(vsub);
-		vty_out(vty, "%% VLR released subscriber %s%s",
-			vlr_subscr_name(vsub), VTY_NEWLINE);
-	}
-
-	if (vsub->use_count > 1)
-		vty_out(vty, "%% Subscriber %s is still in use,"
-			" should be released soon%s",
-			vlr_subscr_name(vsub), VTY_NEWLINE);
-
-	vlr_subscr_put(vsub);
-	return CMD_SUCCESS;
-}
-
-#define A3A8_ALG_TYPES "(none|xor|comp128v1)"
-#define A3A8_ALG_HELP 			\
-	"Use No A3A8 algorithm\n"	\
-	"Use XOR algorithm\n"		\
-	"Use COMP128v1 algorithm\n"
-
-DEFUN(ena_subscr_a3a8,
-      ena_subscr_a3a8_cmd,
-      "subscriber " SUBSCR_TYPES " ID a3a8 " A3A8_ALG_TYPES " [KI]",
-      SUBSCR_HELP "Set a3a8 parameters for the subscriber\n"
-      A3A8_ALG_HELP "Encryption Key Ki\n")
-{
-	vty_out(vty, "%% 'subscriber a3a8' is no longer supported.%s"
-		"%% This is now up to osmo-hlr.%s",
-		VTY_NEWLINE, VTY_NEWLINE);
-	return CMD_WARNING;
-}
-
-DEFUN(subscriber_update,
-      subscriber_update_cmd,
-      "subscriber " SUBSCR_TYPES " ID update",
-      SUBSCR_HELP "Update the subscriber data from the dabase.\n")
-{
-	vty_out(vty, "%% 'subscriber update' is no longer supported.%s",
-		VTY_NEWLINE);
-	return CMD_WARNING;
-}
-
-static int scall_cbfn(unsigned int subsys, unsigned int signal,
-			void *handler_data, void *signal_data)
-{
-	struct scall_signal_data *sigdata = signal_data;
-	struct vty *vty = sigdata->data;
-
-	switch (signal) {
-	case S_SCALL_SUCCESS:
-		vty_out(vty, "%% silent call success%s", VTY_NEWLINE);
-		break;
-	case S_SCALL_EXPIRED:
-		vty_out(vty, "%% silent call expired paging%s", VTY_NEWLINE);
-		break;
-	}
-	return 0;
-}
-
-DEFUN(show_stats,
-      show_stats_cmd,
-      "show statistics",
-	SHOW_STR "Display network statistics\n")
-{
-	struct gsm_network *net = gsmnet_from_vty(vty);
-
-	vty_out(vty, "Location Update         : %lu attach, %lu normal, %lu periodic%s",
-		net->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
-		net->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
-		net->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC].current,
-		VTY_NEWLINE);
-	vty_out(vty, "IMSI Detach Indications : %lu%s",
-		net->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_DETACH].current,
-		VTY_NEWLINE);
-	vty_out(vty, "Location Updating Results: %lu completed, %lu failed%s",
-		net->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_COMPLETED].current,
-		net->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_FAILED].current,
-		VTY_NEWLINE);
-	vty_out(vty, "Handover                : %lu attempted, %lu no_channel, %lu timeout, "
-		"%lu completed, %lu failed%s",
-		net->bsc_ctrs->ctr[BSC_CTR_HANDOVER_ATTEMPTED].current,
-		net->bsc_ctrs->ctr[BSC_CTR_HANDOVER_NO_CHANNEL].current,
-		net->bsc_ctrs->ctr[BSC_CTR_HANDOVER_TIMEOUT].current,
-		net->bsc_ctrs->ctr[BSC_CTR_HANDOVER_COMPLETED].current,
-		net->bsc_ctrs->ctr[BSC_CTR_HANDOVER_FAILED].current,
-		VTY_NEWLINE);
-	vty_out(vty, "SMS MO                  : %lu submitted, %lu no receiver%s",
-		net->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
-		net->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER].current,
-		VTY_NEWLINE);
-	vty_out(vty, "SMS MT                  : %lu delivered, %lu no memory, %lu other error%s",
-		net->msc_ctrs->ctr[MSC_CTR_SMS_DELIVERED].current,
-		net->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_MEM].current,
-		net->msc_ctrs->ctr[MSC_CTR_SMS_RP_ERR_OTHER].current,
-		VTY_NEWLINE);
-	vty_out(vty, "MO Calls                : %lu setup, %lu connect ack%s",
-		net->msc_ctrs->ctr[MSC_CTR_CALL_MO_SETUP].current,
-		net->msc_ctrs->ctr[MSC_CTR_CALL_MO_CONNECT_ACK].current,
-		VTY_NEWLINE);
-	vty_out(vty, "MT Calls                : %lu setup, %lu connect%s",
-		net->msc_ctrs->ctr[MSC_CTR_CALL_MT_SETUP].current,
-		net->msc_ctrs->ctr[MSC_CTR_CALL_MT_CONNECT].current,
-		VTY_NEWLINE);
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_smsqueue,
-      show_smsqueue_cmd,
-      "show sms-queue",
-      SHOW_STR "Display SMSqueue statistics\n")
-{
-	struct gsm_network *net = gsmnet_from_vty(vty);
-
-	sms_queue_stats(net->sms_queue, vty);
-	return CMD_SUCCESS;
-}
-
-DEFUN(smsqueue_trigger,
-      smsqueue_trigger_cmd,
-      "sms-queue trigger",
-      "SMS Queue\n" "Trigger sending messages\n")
-{
-	struct gsm_network *net = gsmnet_from_vty(vty);
-
-	sms_queue_trigger(net->sms_queue);
-	return CMD_SUCCESS;
-}
-
-DEFUN(smsqueue_max,
-      smsqueue_max_cmd,
-      "sms-queue max-pending <1-500>",
-      "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n")
-{
-	struct gsm_network *net = gsmnet_from_vty(vty);
-
-	sms_queue_set_max_pending(net->sms_queue, atoi(argv[0]));
-	return CMD_SUCCESS;
-}
-
-DEFUN(smsqueue_clear,
-      smsqueue_clear_cmd,
-      "sms-queue clear",
-      "SMS Queue\n" "Clear the queue of pending SMS\n")
-{
-	struct gsm_network *net = gsmnet_from_vty(vty);
-
-	sms_queue_clear(net->sms_queue);
-	return CMD_SUCCESS;
-}
-
-DEFUN(smsqueue_fail,
-      smsqueue_fail_cmd,
-      "sms-queue max-failure <1-500>",
-      "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n")
-{
-	struct gsm_network *net = gsmnet_from_vty(vty);
-
-	sms_queue_set_max_failure(net->sms_queue, atoi(argv[0]));
-	return CMD_SUCCESS;
-}
-
-
-DEFUN(cfg_mncc_int, cfg_mncc_int_cmd,
-      "mncc-int", "Configure internal MNCC handler")
-{
-	vty->node = MNCC_INT_NODE;
-
-	return CMD_SUCCESS;
-}
-
-static struct cmd_node mncc_int_node = {
-	MNCC_INT_NODE,
-	"%s(config-mncc-int)# ",
-	1,
-};
-
-static const struct value_string tchf_codec_names[] = {
-	{ GSM48_CMODE_SPEECH_V1,	"fr" },
-	{ GSM48_CMODE_SPEECH_EFR,	"efr" },
-	{ GSM48_CMODE_SPEECH_AMR,	"amr" },
-	{ 0, NULL }
-};
-
-static const struct value_string tchh_codec_names[] = {
-	{ GSM48_CMODE_SPEECH_V1,	"hr" },
-	{ GSM48_CMODE_SPEECH_AMR,	"amr" },
-	{ 0, NULL }
-};
-
-static int config_write_mncc_int(struct vty *vty)
-{
-	uint16_t meas_port;
-	char *meas_host;
-	const char *meas_scenario;
-
-	meas_feed_cfg_get(&meas_host, &meas_port);
-	meas_scenario = meas_feed_scenario_get();
-
-	vty_out(vty, "mncc-int%s", VTY_NEWLINE);
-	vty_out(vty, " default-codec tch-f %s%s",
-		get_value_string(tchf_codec_names, mncc_int.def_codec[0]),
-		VTY_NEWLINE);
-	vty_out(vty, " default-codec tch-h %s%s",
-		get_value_string(tchh_codec_names, mncc_int.def_codec[1]),
-		VTY_NEWLINE);
-	if (meas_port)
-		vty_out(vty, " meas-feed destination %s %u%s",
-			meas_host, meas_port, VTY_NEWLINE);
-	if (strlen(meas_scenario) > 0)
-		vty_out(vty, " meas-feed scenario %s%s",
-			meas_scenario, VTY_NEWLINE);
-
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(mnccint_def_codec_f,
-      mnccint_def_codec_f_cmd,
-      "default-codec tch-f (fr|efr|amr)",
-      "Set default codec\n" "Codec for TCH/F\n"
-      "Full-Rate\n" "Enhanced Full-Rate\n" "Adaptive Multi-Rate\n")
-{
-	mncc_int.def_codec[0] = get_string_value(tchf_codec_names, argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(mnccint_def_codec_h,
-      mnccint_def_codec_h_cmd,
-      "default-codec tch-h (hr|amr)",
-      "Set default codec\n" "Codec for TCH/H\n"
-      "Half-Rate\n" "Adaptive Multi-Rate\n")
-{
-	mncc_int.def_codec[1] = get_string_value(tchh_codec_names, argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-#define OBSOLETE_MSG "Obsolete\n"
-/* this is just for backwards compatibility as the sms code moved into
- * libosmocore and old config files no longer parse... */
-DEFUN_DEPRECATED(log_level_sms, log_level_sms_cmd,
-	"logging level sms (everything|debug|info|notice|error|fatal)",
-	".HIDDEN\n" OBSOLETE_MSG OBSOLETE_MSG OBSOLETE_MSG OBSOLETE_MSG
-	OBSOLETE_MSG OBSOLETE_MSG OBSOLETE_MSG OBSOLETE_MSG)
-{
-	vty_out(vty, "%% 'logging level sms' is now called 'logging level "
-		"lsms', please update your config %s", VTY_NEWLINE);
-
-	return CMD_SUCCESS;
-}
-
-#define MEAS_STR "Measurement export related\n"
-DEFUN(mnccint_meas_feed, mnccint_meas_feed_cmd,
-	"meas-feed destination ADDR <0-65535>",
-	MEAS_STR "destination\n" "address or hostname\n" "port number\n")
-{
-	int rc;
-
-	rc = meas_feed_cfg_set(argv[0], atoi(argv[1]));
-	if (rc < 0)
-		return CMD_WARNING;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(meas_feed_scenario, meas_feed_scenario_cmd,
-	"meas-feed scenario NAME",
-	MEAS_STR "scenario\n" "Name up to 31 characters included in report\n")
-{
-	meas_feed_scenario_set(argv[0]);
-
-	return CMD_SUCCESS;
-}
-
-
-DEFUN(logging_fltr_imsi,
-      logging_fltr_imsi_cmd,
-      "logging filter imsi IMSI",
-	LOGGING_STR FILTER_STR
-      "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
-{
-	struct vlr_subscr *vlr_subscr;
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	struct log_target *tgt = osmo_log_vty2tgt(vty);
-	const char *imsi = argv[0];
-
-	if (!tgt)
-		return CMD_WARNING;
-
-	vlr_subscr = vlr_subscr_find_by_imsi(gsmnet->vlr, imsi);
-
-	if (!vlr_subscr) {
-		vty_out(vty, "%%no subscriber with IMSI(%s)%s",
-			argv[0], VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	log_set_filter_vlr_subscr(tgt, vlr_subscr);
-	return CMD_SUCCESS;
-}
-
-static struct cmd_node hlr_node = {
-	HLR_NODE,
-	"%s(config-hlr)# ",
-	1,
-};
-
-DEFUN(cfg_hlr, cfg_hlr_cmd,
-      "hlr", "Configure connection to the HLR")
-{
-	vty->node = HLR_NODE;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_hlr_remote_ip, cfg_hlr_remote_ip_cmd, "remote-ip A.B.C.D",
-      "Remote GSUP address of the HLR\n"
-      "Remote GSUP address (default: " MSC_HLR_REMOTE_IP_DEFAULT ")")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	talloc_free((void*)gsmnet->gsup_server_addr_str);
-	gsmnet->gsup_server_addr_str = talloc_strdup(gsmnet, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_hlr_remote_port, cfg_hlr_remote_port_cmd, "remote-port <1-65535>",
-      "Remote GSUP port of the HLR\n"
-      "Remote GSUP port (default: " OSMO_STRINGIFY(MSC_HLR_REMOTE_PORT_DEFAULT) ")")
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	gsmnet->gsup_server_port = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-static int config_write_hlr(struct vty *vty)
-{
-	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-
-	vty_out(vty, "hlr%s", VTY_NEWLINE);
-	vty_out(vty, " remote-ip %s%s",
-		gsmnet->gsup_server_addr_str, VTY_NEWLINE);
-	vty_out(vty, " remote-port %u%s",
-		gsmnet->gsup_server_port, VTY_NEWLINE);
-	return CMD_SUCCESS;
-}
-
-int bsc_vty_init_extra(void)
-{
-	osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
-
-	install_element_ve(&show_subscr_cmd);
-	install_element_ve(&show_subscr_cache_cmd);
-
-	install_element_ve(&sms_send_pend_cmd);
-
-	install_element_ve(&subscriber_create_cmd);
-	install_element_ve(&subscriber_send_sms_cmd);
-	install_element_ve(&subscriber_silent_sms_cmd);
-	install_element_ve(&subscriber_silent_call_start_cmd);
-	install_element_ve(&subscriber_silent_call_stop_cmd);
-	install_element_ve(&subscriber_ussd_notify_cmd);
-	install_element_ve(&subscriber_mstest_close_cmd);
-	install_element_ve(&subscriber_mstest_open_cmd);
-	install_element_ve(&subscriber_update_cmd);
-	install_element_ve(&show_stats_cmd);
-	install_element_ve(&show_smsqueue_cmd);
-	install_element_ve(&logging_fltr_imsi_cmd);
-
-	install_element(ENABLE_NODE, &ena_subscr_expire_cmd);
-	install_element(ENABLE_NODE, &ena_subscr_a3a8_cmd);
-	install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
-	install_element(ENABLE_NODE, &smsqueue_max_cmd);
-	install_element(ENABLE_NODE, &smsqueue_clear_cmd);
-	install_element(ENABLE_NODE, &smsqueue_fail_cmd);
-	install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd);
-	install_element(ENABLE_NODE, &meas_feed_scenario_cmd);
-
-	install_element(CONFIG_NODE, &cfg_mncc_int_cmd);
-	install_node(&mncc_int_node, config_write_mncc_int);
-	vty_install_default(MNCC_INT_NODE);
-	install_element(MNCC_INT_NODE, &mnccint_def_codec_f_cmd);
-	install_element(MNCC_INT_NODE, &mnccint_def_codec_h_cmd);
-	install_element(MNCC_INT_NODE, &mnccint_meas_feed_cmd);
-	install_element(MNCC_INT_NODE, &meas_feed_scenario_cmd);
-
-	install_element(CFG_LOG_NODE, &log_level_sms_cmd);
-	install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
-
-	install_element(CONFIG_NODE, &cfg_hlr_cmd);
-	install_node(&hlr_node, config_write_hlr);
-	install_element(HLR_NODE, &cfg_hlr_remote_ip_cmd);
-	install_element(HLR_NODE, &cfg_hlr_remote_port_cmd);
-
-	return 0;
-}
diff --git a/src/libosmo-legacy-mgcp/Makefile.am b/src/libosmo-legacy-mgcp/Makefile.am
new file mode 100644
index 0000000..42f25c0
--- /dev/null
+++ b/src/libosmo-legacy-mgcp/Makefile.am
@@ -0,0 +1,53 @@
+AM_CPPFLAGS = \
+	$(all_includes) \
+	-I$(top_srcdir)/include \
+	-I$(top_builddir) \
+	$(NULL)
+
+AM_CFLAGS = \
+	-Wall \
+	$(LIBOSMOCORE_CFLAGS) \
+	$(LIBOSMOVTY_CFLAGS) \
+	$(LIBOSMONETIF_CFLAGS) \
+	$(COVERAGE_CFLAGS) \
+	$(LIBBCG729_CFLAGS) \
+	$(NULL)
+
+AM_LDFLAGS = \
+	$(LIBOSMOCORE_LIBS) \
+	$(LIBOSMOGSM_LIBS) \
+	$(LIBOSMONETIF_LIBS) \
+	$(COVERAGE_LDFLAGS) \
+	$(LIBBCG729_LIBS) \
+	$(NULL)
+
+# This is _NOT_ the library release version, it's an API version.
+# Please read Chapter 6 "Library interface versions" of the libtool
+# documentation before making any modification
+LEGACY_MGCP_LIBVERSION=0:0:0
+
+lib_LTLIBRARIES = \
+	libosmo-legacy-mgcp.la \
+	$(NULL)
+
+noinst_HEADERS = \
+	g711common.h \
+	$(NULL)
+
+libosmo_legacy_mgcp_la_SOURCES = \
+	mgcp_common.c \
+	mgcp_protocol.c \
+	mgcp_network.c \
+	mgcp_vty.c \
+	mgcp_osmux.c \
+	mgcp_sdp.c \
+	mgcpgw_client.c \
+	mgcpgw_client_vty.c \
+	$(NULL)
+if BUILD_MGCP_TRANSCODING
+libosmo_legacy_mgcp_la_SOURCES += \
+	mgcp_transcode.c \
+	$(NULL)
+endif
+
+libosmo_legacy_mgcp_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LEGACY_MGCP_LIBVERSION)
diff --git a/src/libmgcp/g711common.h b/src/libosmo-legacy-mgcp/g711common.h
similarity index 100%
rename from src/libmgcp/g711common.h
rename to src/libosmo-legacy-mgcp/g711common.h
diff --git a/src/libosmo-legacy-mgcp/mgcp_common.c b/src/libosmo-legacy-mgcp/mgcp_common.c
new file mode 100644
index 0000000..444a060
--- /dev/null
+++ b/src/libosmo-legacy-mgcp/mgcp_common.c
@@ -0,0 +1,54 @@
+/* Media Gateway Control Protocol Media Gateway: RFC 3435 */
+/* Implementations useful both for the MGCP GW as well as MGCP GW clients */
+
+/*
+ * (C) 2016 by sysmocom s.m.f.c. GmbH <info@sysmocom.de>
+ * 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/>.
+ *
+ */
+
+#include <errno.h>
+
+#include <osmocom/core/utils.h>
+#include <osmocom/legacy_mgcp/mgcp.h>
+
+const struct value_string mgcp_connection_mode_strs[] = {
+	{ MGCP_CONN_NONE, "none" },
+	{ MGCP_CONN_RECV_SEND, "sendrecv" },
+	{ MGCP_CONN_SEND_ONLY, "sendonly" },
+	{ MGCP_CONN_RECV_ONLY, "recvonly" },
+	{ MGCP_CONN_LOOPBACK, "loopback" },
+	{ 0, NULL }
+};
+
+/* Ensure that the msg->l2h is NUL terminated. */
+int mgcp_msg_terminate_nul(struct msgb *msg)
+{
+	unsigned char *tail = msg->l2h + msgb_l2len(msg); /* char after l2 data */
+	if (tail[-1] == '\0')
+		/* nothing to do */;
+	else if (msgb_tailroom(msg) > 0)
+		tail[0] = '\0';
+	else if (tail[-1] == '\r' || tail[-1] == '\n')
+		tail[-1] = '\0';
+	else {
+		LOGP(DLMGCP, LOGL_ERROR, "Cannot NUL terminate MGCP message: "
+		     "Length: %d, Buffer size: %d\n",
+		     msgb_l2len(msg), msg->data_len);
+		return -ENOTSUP;
+	}
+	return 0;
+}
diff --git a/src/libosmo-legacy-mgcp/mgcp_network.c b/src/libosmo-legacy-mgcp/mgcp_network.c
new file mode 100644
index 0000000..8ccfb42
--- /dev/null
+++ b/src/libosmo-legacy-mgcp/mgcp_network.c
@@ -0,0 +1,1166 @@
+/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
+/* The protocol implementation */
+
+/*
+ * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-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/>.
+ *
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+#include <limits.h>
+
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/select.h>
+
+#include <osmocom/netif/rtp.h>
+
+#include <osmocom/legacy_mgcp/mgcp.h>
+#include <osmocom/legacy_mgcp/mgcp_internal.h>
+
+#include <osmocom/legacy_mgcp/osmux.h>
+
+#warning "Make use of the rtp proxy code"
+
+
+#define RTP_SEQ_MOD		(1 << 16)
+#define RTP_MAX_DROPOUT		3000
+#define RTP_MAX_MISORDER	100
+#define RTP_BUF_SIZE		4096
+
+enum {
+	MGCP_PROTO_RTP,
+	MGCP_PROTO_RTCP,
+};
+
+/**
+ * This does not need to be a precision timestamp and
+ * is allowed to wrap quite fast. The returned value is
+ * 1/unit seconds.
+ */
+static uint32_t get_current_ts(unsigned unit)
+{
+	struct timespec tp;
+	uint64_t ret;
+
+	if (!unit)
+		return 0;
+
+	memset(&tp, 0, sizeof(tp));
+	if (clock_gettime(CLOCK_MONOTONIC, &tp) != 0)
+		LOGP(DLMGCP, LOGL_NOTICE,
+			"Getting the clock failed.\n");
+
+	/* convert it to 1/unit seconds */
+	ret = tp.tv_sec;
+	ret *= unit;
+	ret += (int64_t)tp.tv_nsec * unit / 1000 / 1000 / 1000;
+
+	return ret;
+}
+
+int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len)
+{
+	struct sockaddr_in out;
+	out.sin_family = AF_INET;
+	out.sin_port = port;
+	memcpy(&out.sin_addr, addr, sizeof(*addr));
+
+	return sendto(fd, buf, len, 0, (struct sockaddr *)&out, sizeof(out));
+}
+
+int mgcp_send_dummy(struct mgcp_endpoint *endp)
+{
+	static char buf[] = { MGCP_DUMMY_LOAD };
+	int rc;
+	int was_rtcp = 0;
+
+	rc = mgcp_udp_send(endp->net_end.rtp.fd, &endp->net_end.addr,
+			   endp->net_end.rtp_port, buf, 1);
+
+	if (rc == -1)
+		goto failed;
+
+	if (endp->tcfg->omit_rtcp)
+		return rc;
+
+	was_rtcp = 1;
+	rc = mgcp_udp_send(endp->net_end.rtcp.fd, &endp->net_end.addr,
+			   endp->net_end.rtcp_port, buf, 1);
+
+	if (rc >= 0)
+		return rc;
+
+failed:
+	LOGP(DLMGCP, LOGL_ERROR,
+		"Failed to send dummy %s packet: %s on: 0x%x to %s:%d\n",
+		was_rtcp ? "RTCP" : "RTP",
+		strerror(errno), ENDPOINT_NUMBER(endp), inet_ntoa(endp->net_end.addr),
+		was_rtcp ? endp->net_end.rtcp_port : endp->net_end.rtp_port);
+
+	return -1;
+}
+
+static int32_t compute_timestamp_aligment_error(struct mgcp_rtp_stream_state *sstate,
+						int ptime, uint32_t timestamp)
+{
+	int32_t timestamp_delta;
+
+	if (ptime == 0)
+		return 0;
+
+	/* Align according to: T - Tlast = k * Tptime */
+	timestamp_delta = timestamp - sstate->last_timestamp;
+
+	return timestamp_delta % ptime;
+}
+
+static int check_rtp_timestamp(struct mgcp_endpoint *endp,
+			       struct mgcp_rtp_state *state,
+			       struct mgcp_rtp_stream_state *sstate,
+			       struct mgcp_rtp_end *rtp_end,
+			       struct sockaddr_in *addr,
+			       uint16_t seq, uint32_t timestamp,
+			       const char *text, int32_t *tsdelta_out)
+{
+	int32_t tsdelta;
+	int32_t timestamp_error;
+
+	/* Not fully intialized, skip */
+	if (sstate->last_tsdelta == 0 && timestamp == sstate->last_timestamp)
+		return 0;
+
+	if (seq == sstate->last_seq) {
+		if (timestamp != sstate->last_timestamp) {
+			sstate->err_ts_counter += 1;
+			LOGP(DLMGCP, LOGL_ERROR,
+			     "The %s timestamp delta is != 0 but the sequence "
+			     "number %d is the same, "
+			     "TS offset: %d, SeqNo offset: %d "
+			     "on 0x%x SSRC: %u timestamp: %u "
+			     "from %s:%d in %d\n",
+			     text, seq,
+			     state->timestamp_offset, state->seq_offset,
+			     ENDPOINT_NUMBER(endp), sstate->ssrc, timestamp,
+			     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
+			     endp->conn_mode);
+		}
+		return 0;
+	}
+
+	tsdelta =
+		(int32_t)(timestamp - sstate->last_timestamp) /
+		(int16_t)(seq - sstate->last_seq);
+
+	if (tsdelta == 0) {
+		/* Don't update *tsdelta_out */
+		LOGP(DLMGCP, LOGL_NOTICE,
+		     "The %s timestamp delta is %d "
+		     "on 0x%x SSRC: %u timestamp: %u "
+		     "from %s:%d in %d\n",
+		     text, tsdelta,
+		     ENDPOINT_NUMBER(endp), sstate->ssrc, timestamp,
+		     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
+		     endp->conn_mode);
+
+		return 0;
+	}
+
+	if (sstate->last_tsdelta != tsdelta) {
+		if (sstate->last_tsdelta) {
+			LOGP(DLMGCP, LOGL_INFO,
+			     "The %s timestamp delta changes from %d to %d "
+			     "on 0x%x SSRC: %u timestamp: %u from %s:%d in %d\n",
+			     text, sstate->last_tsdelta, tsdelta,
+			     ENDPOINT_NUMBER(endp), sstate->ssrc, timestamp,
+			     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
+			     endp->conn_mode);
+		}
+	}
+
+	if (tsdelta_out)
+		*tsdelta_out = tsdelta;
+
+	timestamp_error =
+		compute_timestamp_aligment_error(sstate, state->packet_duration,
+						 timestamp);
+
+	if (timestamp_error) {
+		sstate->err_ts_counter += 1;
+		LOGP(DLMGCP, LOGL_NOTICE,
+		     "The %s timestamp has an alignment error of %d "
+		     "on 0x%x SSRC: %u "
+		     "SeqNo delta: %d, TS delta: %d, dTS/dSeq: %d "
+		     "from %s:%d in mode %d. ptime: %d\n",
+		     text, timestamp_error,
+		     ENDPOINT_NUMBER(endp), sstate->ssrc,
+		     (int16_t)(seq - sstate->last_seq),
+		     (int32_t)(timestamp - sstate->last_timestamp),
+		     tsdelta,
+		     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
+		     endp->conn_mode, state->packet_duration);
+	}
+	return 1;
+}
+
+/* Set the timestamp offset according to the packet duration. */
+static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
+				       struct mgcp_rtp_state *state,
+				       struct mgcp_rtp_end *rtp_end,
+				       struct sockaddr_in *addr,
+				       int16_t delta_seq, uint32_t in_timestamp)
+{
+	int32_t tsdelta = state->packet_duration;
+	int timestamp_offset;
+	uint32_t out_timestamp;
+
+	if (tsdelta == 0) {
+		tsdelta = state->out_stream.last_tsdelta;
+		if (tsdelta != 0) {
+			LOGP(DLMGCP, LOGL_NOTICE,
+			     "A fixed packet duration is not available on 0x%x, "
+			     "using last output timestamp delta instead: %d "
+			     "from %s:%d in %d\n",
+			     ENDPOINT_NUMBER(endp), tsdelta,
+			     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
+			     endp->conn_mode);
+		} else {
+			tsdelta = rtp_end->codec.rate * 20 / 1000;
+			LOGP(DLMGCP, LOGL_NOTICE,
+			     "Fixed packet duration and last timestamp delta "
+			     "are not available on 0x%x, "
+			     "using fixed 20ms instead: %d "
+			     "from %s:%d in %d\n",
+			     ENDPOINT_NUMBER(endp), tsdelta,
+			     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
+			     endp->conn_mode);
+		}
+	}
+
+	out_timestamp = state->out_stream.last_timestamp + delta_seq * tsdelta;
+	timestamp_offset = out_timestamp - in_timestamp;
+
+	if (state->timestamp_offset != timestamp_offset) {
+		state->timestamp_offset = timestamp_offset;
+
+		LOGP(DLMGCP, LOGL_NOTICE,
+		     "Timestamp offset change on 0x%x SSRC: %u "
+		     "SeqNo delta: %d, TS offset: %d, "
+		     "from %s:%d in %d\n",
+		     ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
+		     delta_seq, state->timestamp_offset,
+		     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
+		     endp->conn_mode);
+	}
+
+	return timestamp_offset;
+}
+
+/* Set the timestamp offset according to the packet duration. */
+static int align_rtp_timestamp_offset(struct mgcp_endpoint *endp,
+				      struct mgcp_rtp_state *state,
+				      struct mgcp_rtp_end *rtp_end,
+				      struct sockaddr_in *addr,
+				      uint32_t timestamp)
+{
+	int timestamp_error = 0;
+	int ptime = state->packet_duration;
+
+	/* Align according to: T + Toffs - Tlast = k * Tptime */
+
+	timestamp_error = compute_timestamp_aligment_error(
+		&state->out_stream, ptime,
+		timestamp + state->timestamp_offset);
+
+	if (timestamp_error) {
+		state->timestamp_offset += ptime - timestamp_error;
+
+		LOGP(DLMGCP, LOGL_NOTICE,
+		     "Corrected timestamp alignment error of %d on 0x%x SSRC: %u "
+		     "new TS offset: %d, "
+		     "from %s:%d in %d\n",
+		     timestamp_error,
+		     ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
+		     state->timestamp_offset, inet_ntoa(addr->sin_addr),
+		     ntohs(addr->sin_port), endp->conn_mode);
+	}
+
+	OSMO_ASSERT(compute_timestamp_aligment_error(&state->out_stream, ptime,
+						     timestamp + state->timestamp_offset) == 0);
+
+	return timestamp_error;
+}
+
+int mgcp_rtp_processing_default(struct mgcp_endpoint *endp, struct mgcp_rtp_end *dst_end,
+				char *data, int *len, int buf_size)
+{
+	return 0;
+}
+
+int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
+				      struct mgcp_rtp_end *dst_end,
+				      struct mgcp_rtp_end *src_end)
+{
+	return 0;
+}
+
+void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
+					  int *payload_type,
+					  const char**audio_name,
+					  const char**fmtp_extra)
+{
+	/* Use the BTS side parameters when passing the SDP data (for
+	 * downlink) to the net peer.
+	 */
+	*payload_type = endp->bts_end.codec.payload_type;
+	*audio_name = endp->bts_end.codec.audio_name;
+	*fmtp_extra = endp->bts_end.fmtp_extra;
+}
+
+
+void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
+			const uint16_t seq, const int32_t transit,
+			const uint32_t ssrc)
+{
+	int32_t d;
+
+	/* initialize or re-initialize */
+	if (!state->stats_initialized || state->stats_ssrc != ssrc) {
+		state->stats_initialized = 1;
+		state->stats_base_seq = seq;
+		state->stats_max_seq = seq - 1;
+		state->stats_ssrc = ssrc;
+		state->stats_jitter = 0;
+		state->stats_transit = transit;
+		state->stats_cycles = 0;
+	} else {
+		uint16_t udelta;
+
+		/*
+		 * The below takes the shape of the validation of
+		 * Appendix A. Check if there is something weird with
+		 * the sequence number, otherwise check for a wrap
+		 * around in the sequence number.
+		 * It can't wrap during the initialization so let's
+		 * skip it here. The Appendix A probably doesn't have
+		 * this issue because of the probation.
+		 */
+		udelta = seq - state->stats_max_seq;
+		if (udelta < RTP_MAX_DROPOUT) {
+			if (seq < state->stats_max_seq)
+				state->stats_cycles += RTP_SEQ_MOD;
+		} else if (udelta <= RTP_SEQ_MOD - RTP_MAX_MISORDER) {
+			LOGP(DLMGCP, LOGL_NOTICE,
+				"RTP seqno made a very large jump on 0x%x delta: %u\n",
+				ENDPOINT_NUMBER(endp), udelta);
+		}
+	}
+
+	/*
+	 * Calculate the jitter between the two packages. The TS should be
+	 * taken closer to the read function. This was taken from the
+	 * Appendix A of RFC 3550. Timestamp and arrival_time have a 1/rate
+	 * resolution.
+	 */
+	d = transit - state->stats_transit;
+	state->stats_transit = transit;
+	if (d < 0)
+		d = -d;
+	state->stats_jitter += d - ((state->stats_jitter + 8) >> 4);
+	state->stats_max_seq = seq;
+}
+
+
+
+/**
+ * The RFC 3550 Appendix A assumes there are multiple sources but
+ * some of the supported endpoints (e.g. the nanoBTS) can only handle
+ * one source and this code will patch RTP header to appear as if there
+ * is only one source.
+ * There is also no probation period for new sources. Every RTP header
+ * we receive will be seen as a switch in streams.
+ */
+void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
+			  struct mgcp_rtp_end *rtp_end, struct sockaddr_in *addr,
+			  char *data, int len)
+{
+	uint32_t arrival_time;
+	int32_t transit;
+	uint16_t seq;
+	uint32_t timestamp, ssrc;
+	struct rtp_hdr *rtp_hdr;
+	int payload = rtp_end->codec.payload_type;
+
+	if (len < sizeof(*rtp_hdr))
+		return;
+
+	rtp_hdr = (struct rtp_hdr *) data;
+	seq = ntohs(rtp_hdr->sequence);
+	timestamp = ntohl(rtp_hdr->timestamp);
+	arrival_time = get_current_ts(rtp_end->codec.rate);
+	ssrc = ntohl(rtp_hdr->ssrc);
+	transit = arrival_time - timestamp;
+
+	mgcp_rtp_annex_count(endp, state, seq, transit, ssrc);
+
+	if (!state->initialized) {
+		state->initialized = 1;
+		state->in_stream.last_seq = seq - 1;
+		state->in_stream.ssrc = state->orig_ssrc = ssrc;
+		state->in_stream.last_tsdelta = 0;
+		state->packet_duration = mgcp_rtp_packet_duration(endp, rtp_end);
+		state->out_stream = state->in_stream;
+		state->out_stream.last_timestamp = timestamp;
+		state->out_stream.ssrc = ssrc - 1; /* force output SSRC change */
+		LOGP(DLMGCP, LOGL_INFO,
+			"Initializing stream on 0x%x SSRC: %u timestamp: %u "
+			"pkt-duration: %d, from %s:%d in %d\n",
+			ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
+			state->seq_offset, state->packet_duration,
+			inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
+			endp->conn_mode);
+		if (state->packet_duration == 0) {
+			state->packet_duration = rtp_end->codec.rate * 20 / 1000;
+			LOGP(DLMGCP, LOGL_NOTICE,
+			     "Fixed packet duration is not available on 0x%x, "
+			     "using fixed 20ms instead: %d from %s:%d in %d\n",
+			     ENDPOINT_NUMBER(endp), state->packet_duration,
+			     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
+			     endp->conn_mode);
+		}
+	} else if (state->in_stream.ssrc != ssrc) {
+		LOGP(DLMGCP, LOGL_NOTICE,
+			"The SSRC changed on 0x%x: %u -> %u  "
+			"from %s:%d in %d\n",
+			ENDPOINT_NUMBER(endp),
+			state->in_stream.ssrc, rtp_hdr->ssrc,
+			inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
+			endp->conn_mode);
+
+		state->in_stream.ssrc = ssrc;
+		if (rtp_end->force_constant_ssrc) {
+			int16_t delta_seq;
+
+			/* Always increment seqno by 1 */
+			state->seq_offset =
+				(state->out_stream.last_seq + 1) - seq;
+
+			/* Estimate number of packets that would have been sent */
+			delta_seq =
+				(arrival_time - state->in_stream.last_arrival_time
+				 + state->packet_duration/2) /
+				state->packet_duration;
+
+			adjust_rtp_timestamp_offset(endp, state, rtp_end, addr,
+						    delta_seq, timestamp);
+
+			state->patch_ssrc = 1;
+			ssrc = state->orig_ssrc;
+			if (rtp_end->force_constant_ssrc != -1)
+				rtp_end->force_constant_ssrc -= 1;
+
+			LOGP(DLMGCP, LOGL_NOTICE,
+			     "SSRC patching enabled on 0x%x SSRC: %u "
+			     "SeqNo offset: %d, TS offset: %d "
+			     "from %s:%d in %d\n",
+			     ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
+			     state->seq_offset, state->timestamp_offset,
+			     inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
+			     endp->conn_mode);
+		}
+
+		state->in_stream.last_tsdelta = 0;
+	} else {
+		/* Compute current per-packet timestamp delta */
+		check_rtp_timestamp(endp, state, &state->in_stream, rtp_end, addr,
+				    seq, timestamp, "input",
+				    &state->in_stream.last_tsdelta);
+
+		if (state->patch_ssrc)
+			ssrc = state->orig_ssrc;
+	}
+
+	/* Save before patching */
+	state->in_stream.last_timestamp = timestamp;
+	state->in_stream.last_seq = seq;
+	state->in_stream.last_arrival_time = arrival_time;
+
+	if (rtp_end->force_aligned_timing &&
+	    state->out_stream.ssrc == ssrc && state->packet_duration)
+		/* Align the timestamp offset */
+		align_rtp_timestamp_offset(endp, state, rtp_end, addr, timestamp);
+
+	/* Store the updated SSRC back to the packet */
+	if (state->patch_ssrc)
+		rtp_hdr->ssrc = htonl(ssrc);
+
+	/* Apply the offset and store it back to the packet.
+	 * This won't change anything if the offset is 0, so the conditional is
+	 * omitted. */
+	seq += state->seq_offset;
+	rtp_hdr->sequence = htons(seq);
+	timestamp += state->timestamp_offset;
+	rtp_hdr->timestamp = htonl(timestamp);
+
+	/* Check again, whether the timestamps are still valid */
+	if (state->out_stream.ssrc == ssrc)
+		check_rtp_timestamp(endp, state, &state->out_stream, rtp_end,
+				    addr, seq, timestamp, "output",
+				    &state->out_stream.last_tsdelta);
+
+	/* Save output values */
+	state->out_stream.last_seq = seq;
+	state->out_stream.last_timestamp = timestamp;
+	state->out_stream.ssrc = ssrc;
+
+	if (payload < 0)
+		return;
+
+#if 0
+	DEBUGP(DLMGCP, "Payload hdr payload %u -> endp payload %u\n",
+	       rtp_hdr->payload_type, payload);
+	rtp_hdr->payload_type = payload;
+#endif
+}
+
+/*
+ * The below code is for dispatching. We have a dedicated port for
+ * the data coming from the net and one to discover the BTS.
+ */
+static int forward_data(int fd, struct mgcp_rtp_tap *tap, const char *buf, int len)
+{
+	if (!tap->enabled)
+		return 0;
+
+	return sendto(fd, buf, len, 0,
+		      (struct sockaddr *)&tap->forward, sizeof(tap->forward));
+}
+
+static int mgcp_send_transcoder(struct mgcp_rtp_end *end,
+				struct mgcp_config *cfg, int is_rtp,
+				const char *buf, int len)
+{
+	int rc;
+	int port;
+	struct sockaddr_in addr;
+
+	port = is_rtp ? end->rtp_port : end->rtcp_port;
+
+	addr.sin_family = AF_INET;
+	addr.sin_addr = cfg->transcoder_in;
+	addr.sin_port = port;
+
+	rc = sendto(is_rtp ?
+		end->rtp.fd :
+		end->rtcp.fd, buf, len, 0,
+		(struct sockaddr *) &addr, sizeof(addr));
+
+	if (rc != len)
+		LOGP(DLMGCP, LOGL_ERROR,
+			"Failed to send data to the transcoder: %s\n",
+			strerror(errno));
+
+	return rc;
+}
+
+int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp,
+	      struct sockaddr_in *addr, char *buf, int rc)
+{
+	struct mgcp_trunk_config *tcfg = endp->tcfg;
+	struct mgcp_rtp_end *rtp_end;
+	struct mgcp_rtp_state *rtp_state;
+	int tap_idx;
+
+	LOGP(DLMGCP, LOGL_DEBUG,
+	     "endpoint %x dest %s tcfg->audio_loop %d endp->conn_mode %d (== loopback: %d)\n",
+	     ENDPOINT_NUMBER(endp),
+	     dest == MGCP_DEST_NET? "net" : "bts",
+	     tcfg->audio_loop,
+	     endp->conn_mode,
+	     endp->conn_mode == MGCP_CONN_LOOPBACK);
+
+	/* For loop toggle the destination and then dispatch. */
+	if (tcfg->audio_loop)
+		dest = !dest;
+
+	/* Loop based on the conn_mode, maybe undoing the above */
+	if (endp->conn_mode == MGCP_CONN_LOOPBACK)
+		dest = !dest;
+
+	if (dest == MGCP_DEST_NET) {
+		rtp_end = &endp->net_end;
+		rtp_state = &endp->bts_state;
+		tap_idx = MGCP_TAP_NET_OUT;
+	} else {
+		rtp_end = &endp->bts_end;
+		rtp_state = &endp->net_state;
+		tap_idx = MGCP_TAP_BTS_OUT;
+	}
+	LOGP(DLMGCP, LOGL_DEBUG,
+	     "endpoint %x dest %s net_end %s %d %d bts_end %s %d %d rtp_end %s %d %d\n",
+	     ENDPOINT_NUMBER(endp),
+	     dest == MGCP_DEST_NET? "net" : "bts",
+
+	     inet_ntoa(endp->net_end.addr),
+	     ntohs(endp->net_end.rtp_port),
+	     ntohs(endp->net_end.rtcp_port),
+
+	     inet_ntoa(endp->bts_end.addr),
+	     ntohs(endp->bts_end.rtp_port),
+	     ntohs(endp->bts_end.rtcp_port),
+
+	     inet_ntoa(rtp_end->addr),
+	     ntohs(rtp_end->rtp_port),
+	     ntohs(rtp_end->rtcp_port)
+	    );
+
+	if (!rtp_end->output_enabled) {
+		rtp_end->dropped_packets += 1;
+		LOGP(DLMGCP, LOGL_DEBUG,
+		     "endpoint %x output disabled, drop to %s %s %d %d\n",
+		     ENDPOINT_NUMBER(endp),
+		     dest == MGCP_DEST_NET? "net" : "bts",
+		     inet_ntoa(rtp_end->addr),
+		     ntohs(rtp_end->rtp_port),
+		     ntohs(rtp_end->rtcp_port)
+		    );
+	} else if (is_rtp) {
+		int cont;
+		int nbytes = 0;
+		int len = rc;
+		do {
+			cont = endp->cfg->rtp_processing_cb(endp, rtp_end,
+							buf, &len, RTP_BUF_SIZE);
+			if (cont < 0)
+				break;
+
+			mgcp_patch_and_count(endp, rtp_state, rtp_end, addr, buf, len);
+		LOGP(DLMGCP, LOGL_DEBUG,
+		     "endpoint %x process/send to %s %s %d %d\n",
+		     ENDPOINT_NUMBER(endp),
+		     (dest == MGCP_DEST_NET)? "net" : "bts",
+		     inet_ntoa(rtp_end->addr),
+		     ntohs(rtp_end->rtp_port),
+		     ntohs(rtp_end->rtcp_port)
+		    );
+			forward_data(rtp_end->rtp.fd, &endp->taps[tap_idx],
+				     buf, len);
+
+			/* FIXME: HACK HACK HACK. See OS#2459.
+			 * The ip.access nano3G needs the first RTP payload's first two bytes to read hex
+			 * 'e400', or it will reject the RAB assignment. It seems to not harm other femto
+			 * cells (as long as we patch only the first RTP payload in each stream).
+			 */
+			if (tap_idx == MGCP_TAP_BTS_OUT
+			    && !rtp_state->patched_first_rtp_payload) {
+				uint8_t *data = (uint8_t*)&buf[12];
+				data[0] = 0xe4;
+				data[1] = 0x00;
+				rtp_state->patched_first_rtp_payload = true;
+			}
+
+			rc = mgcp_udp_send(rtp_end->rtp.fd,
+					   &rtp_end->addr,
+					   rtp_end->rtp_port, buf, len);
+
+			if (rc <= 0)
+				return rc;
+			nbytes += rc;
+			len = cont;
+		} while (len > 0);
+		return nbytes;
+	} else if (!tcfg->omit_rtcp) {
+		LOGP(DLMGCP, LOGL_DEBUG,
+		     "endpoint %x send to %s %s %d %d\n",
+		     ENDPOINT_NUMBER(endp),
+		     dest == MGCP_DEST_NET? "net" : "bts",
+		     inet_ntoa(rtp_end->addr),
+		     ntohs(rtp_end->rtp_port),
+		     ntohs(rtp_end->rtcp_port)
+		    );
+
+		return mgcp_udp_send(rtp_end->rtcp.fd,
+				     &rtp_end->addr,
+				     rtp_end->rtcp_port, buf, rc);
+	}
+
+	return 0;
+}
+
+static int receive_from(struct mgcp_endpoint *endp, int fd, struct sockaddr_in *addr,
+			char *buf, int bufsize)
+{
+	int rc;
+	socklen_t slen = sizeof(*addr);
+
+	rc = recvfrom(fd, buf, bufsize, 0,
+			    (struct sockaddr *) addr, &slen);
+	if (rc < 0) {
+		LOGP(DLMGCP, LOGL_ERROR, "Failed to receive message on: 0x%x errno: %d/%s\n",
+			ENDPOINT_NUMBER(endp), errno, strerror(errno));
+		return -1;
+	}
+
+	/* do not forward aynthing... maybe there is a packet from the bts */
+	if (!endp->allocated)
+		return -1;
+
+	#warning "Slight spec violation. With connection mode recvonly we should attempt to forward."
+
+	return rc;
+}
+
+static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
+{
+	char buf[RTP_BUF_SIZE];
+	struct sockaddr_in addr;
+	struct mgcp_endpoint *endp;
+	int rc, proto;
+
+	endp = (struct mgcp_endpoint *) fd->data;
+
+	rc = receive_from(endp, fd->fd, &addr, buf, sizeof(buf));
+	if (rc <= 0)
+		return -1;
+
+	LOGP(DLMGCP, LOGL_DEBUG,
+	     "endpoint %x",
+	     ENDPOINT_NUMBER(endp));
+	LOGPC(DLMGCP, LOGL_DEBUG,
+	      " from net %s %d",
+	      inet_ntoa(addr.sin_addr),
+	      ntohs(addr.sin_port));
+	LOGPC(DLMGCP, LOGL_DEBUG,
+	      " net_end %s %d %d",
+	      inet_ntoa(endp->net_end.addr),
+	      ntohs(endp->net_end.rtp_port),
+	      ntohs(endp->net_end.rtcp_port));
+	LOGPC(DLMGCP, LOGL_DEBUG,
+	      " bts_end %s %d %d\n",
+	      inet_ntoa(endp->bts_end.addr),
+	      ntohs(endp->bts_end.rtp_port),
+	      ntohs(endp->bts_end.rtcp_port)
+	     );
+
+	if (memcmp(&addr.sin_addr, &endp->net_end.addr, sizeof(addr.sin_addr)) != 0) {
+		LOGP(DLMGCP, LOGL_ERROR,
+			"rtp_data_net: Endpoint 0x%x data from wrong address %s vs. ",
+			ENDPOINT_NUMBER(endp), inet_ntoa(addr.sin_addr));
+		LOGPC(DLMGCP, LOGL_ERROR,
+			"%s\n", inet_ntoa(endp->net_end.addr));
+		return -1;
+	}
+
+	switch(endp->type) {
+	case MGCP_RTP_DEFAULT:
+	case MGCP_RTP_TRANSCODED:
+		if (endp->net_end.rtp_port != addr.sin_port &&
+		    endp->net_end.rtcp_port != addr.sin_port) {
+			LOGP(DLMGCP, LOGL_ERROR,
+				"rtp_data_net: Data from wrong source port %d on 0x%x\n",
+				ntohs(addr.sin_port), ENDPOINT_NUMBER(endp));
+			return -1;
+		}
+		break;
+	case MGCP_OSMUX_BSC:
+	case MGCP_OSMUX_BSC_NAT:
+		break;
+	}
+
+	LOGP(DLMGCP, LOGL_DEBUG,
+	     "rtp_data_net: Endpoint %x data from %s %d\n",
+	     ENDPOINT_NUMBER(endp),
+	     inet_ntoa(addr.sin_addr),
+	     ntohs(addr.sin_port));
+
+	/* throw away the dummy message */
+	if (rc == 1 && buf[0] == MGCP_DUMMY_LOAD) {
+		LOGP(DLMGCP, LOGL_NOTICE, "Filtered dummy from network on 0x%x\n",
+			ENDPOINT_NUMBER(endp));
+		return 0;
+	}
+
+	proto = fd == &endp->net_end.rtp ? MGCP_PROTO_RTP : MGCP_PROTO_RTCP;
+	endp->net_end.packets += 1;
+	endp->net_end.octets += rc;
+
+	forward_data(fd->fd, &endp->taps[MGCP_TAP_NET_IN], buf, rc);
+
+	switch (endp->type) {
+	case MGCP_RTP_DEFAULT:
+		return mgcp_send(endp, MGCP_DEST_BTS, proto == MGCP_PROTO_RTP,
+				 &addr, buf, rc);
+	case MGCP_RTP_TRANSCODED:
+		return mgcp_send_transcoder(&endp->trans_net, endp->cfg,
+					    proto == MGCP_PROTO_RTP, buf, rc);
+	case MGCP_OSMUX_BSC_NAT:
+		return osmux_xfrm_to_osmux(MGCP_DEST_BTS, buf, rc, endp);
+	case MGCP_OSMUX_BSC:	/* Should not happen */
+		break;
+	}
+
+	LOGP(DLMGCP, LOGL_ERROR, "Bad MGCP type %u on endpoint %u\n",
+	     endp->type, ENDPOINT_NUMBER(endp));
+	return 0;
+}
+
+static void discover_bts(struct mgcp_endpoint *endp, int proto, struct sockaddr_in *addr)
+{
+	struct mgcp_config *cfg = endp->cfg;
+
+	if (proto == MGCP_PROTO_RTP && endp->bts_end.rtp_port == 0) {
+		if (!cfg->bts_ip ||
+		    memcmp(&addr->sin_addr,
+			   &cfg->bts_in, sizeof(cfg->bts_in)) == 0 ||
+		    memcmp(&addr->sin_addr,
+			   &endp->bts_end.addr, sizeof(endp->bts_end.addr)) == 0) {
+
+			endp->bts_end.rtp_port = addr->sin_port;
+			endp->bts_end.addr = addr->sin_addr;
+
+			LOGP(DLMGCP, LOGL_NOTICE,
+				"Found BTS for endpoint: 0x%x on port: %d/%d of %s\n",
+				ENDPOINT_NUMBER(endp), ntohs(endp->bts_end.rtp_port),
+				ntohs(endp->bts_end.rtcp_port), inet_ntoa(addr->sin_addr));
+		}
+	} else if (proto == MGCP_PROTO_RTCP && endp->bts_end.rtcp_port == 0) {
+		if (memcmp(&endp->bts_end.addr, &addr->sin_addr,
+				sizeof(endp->bts_end.addr)) == 0) {
+			endp->bts_end.rtcp_port = addr->sin_port;
+		}
+	}
+}
+
+static int rtp_data_bts(struct osmo_fd *fd, unsigned int what)
+{
+	char buf[RTP_BUF_SIZE];
+	struct sockaddr_in addr;
+	struct mgcp_endpoint *endp;
+	int rc, proto;
+
+	endp = (struct mgcp_endpoint *) fd->data;
+
+	rc = receive_from(endp, fd->fd, &addr, buf, sizeof(buf));
+	if (rc <= 0)
+		return -1;
+
+	proto = fd == &endp->bts_end.rtp ? MGCP_PROTO_RTP : MGCP_PROTO_RTCP;
+
+	/* We have no idea who called us, maybe it is the BTS. */
+	/* it was the BTS... */
+	discover_bts(endp, proto, &addr);
+
+	if (memcmp(&endp->bts_end.addr, &addr.sin_addr, sizeof(addr.sin_addr)) != 0) {
+		LOGP(DLMGCP, LOGL_ERROR,
+			"rtp_data_bts: Data from wrong bts %s on 0x%x\n",
+			inet_ntoa(addr.sin_addr), ENDPOINT_NUMBER(endp));
+		return -1;
+	}
+
+	if (endp->bts_end.rtp_port != addr.sin_port &&
+	    endp->bts_end.rtcp_port != addr.sin_port) {
+		LOGP(DLMGCP, LOGL_ERROR,
+			"rtp_data_bts: ata from wrong bts source port %d on 0x%x\n",
+			ntohs(addr.sin_port), ENDPOINT_NUMBER(endp));
+		return -1;
+	}
+
+	LOGP(DLMGCP, LOGL_DEBUG,
+	     "rtp_data_bts: Endpoint %x data from %s %d\n",
+	     ENDPOINT_NUMBER(endp),
+	     inet_ntoa(addr.sin_addr),
+	     ntohs(addr.sin_port));
+
+	/* throw away the dummy message */
+	if (rc == 1 && buf[0] == MGCP_DUMMY_LOAD) {
+		LOGP(DLMGCP, LOGL_NOTICE, "Filtered dummy from bts on 0x%x\n",
+			ENDPOINT_NUMBER(endp));
+		return 0;
+	}
+
+	/* do this before the loop handling */
+	endp->bts_end.packets += 1;
+	endp->bts_end.octets += rc;
+
+	forward_data(fd->fd, &endp->taps[MGCP_TAP_BTS_IN], buf, rc);
+
+	switch (endp->type) {
+	case MGCP_RTP_DEFAULT:
+		LOGP(DLMGCP, LOGL_DEBUG,
+		     "rtp_data_bts: Endpoint %x MGCP_RTP_DEFAULT\n",
+		     ENDPOINT_NUMBER(endp));
+		return mgcp_send(endp, MGCP_DEST_NET, proto == MGCP_PROTO_RTP,
+				 &addr, buf, rc);
+	case MGCP_RTP_TRANSCODED:
+		return mgcp_send_transcoder(&endp->trans_bts, endp->cfg,
+					    proto == MGCP_PROTO_RTP, buf, rc);
+	case MGCP_OSMUX_BSC:
+		/* OSMUX translation: BTS -> BSC */
+		return osmux_xfrm_to_osmux(MGCP_DEST_NET, buf, rc, endp);
+	case MGCP_OSMUX_BSC_NAT:
+		break;	/* Should not happen */
+	}
+
+	LOGP(DLMGCP, LOGL_ERROR, "Bad MGCP type %u on endpoint %u\n",
+	     endp->type, ENDPOINT_NUMBER(endp));
+	return 0;
+}
+
+static int rtp_data_transcoder(struct mgcp_rtp_end *end, struct mgcp_endpoint *_endp,
+			      int dest, struct osmo_fd *fd)
+{
+	char buf[RTP_BUF_SIZE];
+	struct sockaddr_in addr;
+	struct mgcp_config *cfg;
+	int rc, proto;
+
+	cfg = _endp->cfg;
+	rc = receive_from(_endp, fd->fd, &addr, buf, sizeof(buf));
+	if (rc <= 0)
+		return -1;
+
+	proto = fd == &end->rtp ? MGCP_PROTO_RTP : MGCP_PROTO_RTCP;
+
+	if (memcmp(&addr.sin_addr, &cfg->transcoder_in, sizeof(addr.sin_addr)) != 0) {
+		LOGP(DLMGCP, LOGL_ERROR,
+			"Data not coming from transcoder dest: %d %s on 0x%x\n",
+			dest, inet_ntoa(addr.sin_addr), ENDPOINT_NUMBER(_endp));
+		return -1;
+	}
+
+	if (end->rtp_port != addr.sin_port &&
+	    end->rtcp_port != addr.sin_port) {
+		LOGP(DLMGCP, LOGL_ERROR,
+			"Data from wrong transcoder dest %d source port %d on 0x%x\n",
+			dest, ntohs(addr.sin_port), ENDPOINT_NUMBER(_endp));
+		return -1;
+	}
+
+	/* throw away the dummy message */
+	if (rc == 1 && buf[0] == MGCP_DUMMY_LOAD) {
+		LOGP(DLMGCP, LOGL_NOTICE, "Filtered dummy from transcoder dest %d on 0x%x\n",
+			dest, ENDPOINT_NUMBER(_endp));
+		return 0;
+	}
+
+	end->packets += 1;
+	return mgcp_send(_endp, dest, proto == MGCP_PROTO_RTP, &addr, buf, rc);
+}
+
+static int rtp_data_trans_net(struct osmo_fd *fd, unsigned int what)
+{
+	struct mgcp_endpoint *endp;
+	endp = (struct mgcp_endpoint *) fd->data;
+
+	return rtp_data_transcoder(&endp->trans_net, endp, MGCP_DEST_NET, fd);
+}
+
+static int rtp_data_trans_bts(struct osmo_fd *fd, unsigned int what)
+{
+	struct mgcp_endpoint *endp;
+	endp = (struct mgcp_endpoint *) fd->data;
+
+	return rtp_data_transcoder(&endp->trans_bts, endp, MGCP_DEST_BTS, fd);
+}
+
+int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port)
+{
+	struct sockaddr_in addr;
+	int on = 1;
+
+	fd->fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (fd->fd < 0) {
+		LOGP(DLMGCP, LOGL_ERROR, "Failed to create UDP port.\n");
+		return -1;
+	}
+
+	setsockopt(fd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+	memset(&addr, 0, sizeof(addr));
+	addr.sin_family = AF_INET;
+	addr.sin_port = htons(port);
+	inet_aton(source_addr, &addr.sin_addr);
+
+	if (bind(fd->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		close(fd->fd);
+		fd->fd = -1;
+		return -1;
+	}
+
+	return 0;
+}
+
+int mgcp_set_ip_tos(int fd, int tos)
+{
+	int ret;
+	ret = setsockopt(fd, IPPROTO_IP, IP_TOS,
+			 &tos, sizeof(tos));
+	return ret != 0;
+}
+
+static int bind_rtp(struct mgcp_config *cfg, const char *source_addr,
+			struct mgcp_rtp_end *rtp_end, int endpno)
+{
+	if (mgcp_create_bind(source_addr, &rtp_end->rtp,
+			     rtp_end->local_port) != 0) {
+		LOGP(DLMGCP, LOGL_ERROR, "Failed to create RTP port: %s:%d on 0x%x\n",
+		       source_addr, rtp_end->local_port, endpno);
+		goto cleanup0;
+	}
+
+	if (mgcp_create_bind(source_addr, &rtp_end->rtcp,
+			     rtp_end->local_port + 1) != 0) {
+		LOGP(DLMGCP, LOGL_ERROR, "Failed to create RTCP port: %s:%d on 0x%x\n",
+		       source_addr, rtp_end->local_port + 1, endpno);
+		goto cleanup1;
+	}
+
+	mgcp_set_ip_tos(rtp_end->rtp.fd, cfg->endp_dscp);
+	mgcp_set_ip_tos(rtp_end->rtcp.fd, cfg->endp_dscp);
+
+	rtp_end->rtp.when = BSC_FD_READ;
+	if (osmo_fd_register(&rtp_end->rtp) != 0) {
+		LOGP(DLMGCP, LOGL_ERROR, "Failed to register RTP port %d on 0x%x\n",
+			rtp_end->local_port, endpno);
+		goto cleanup2;
+	}
+
+	rtp_end->rtcp.when = BSC_FD_READ;
+	if (osmo_fd_register(&rtp_end->rtcp) != 0) {
+		LOGP(DLMGCP, LOGL_ERROR, "Failed to register RTCP port %d on 0x%x\n",
+			rtp_end->local_port + 1, endpno);
+		goto cleanup3;
+	}
+
+	return 0;
+
+cleanup3:
+	osmo_fd_unregister(&rtp_end->rtp);
+cleanup2:
+	close(rtp_end->rtcp.fd);
+	rtp_end->rtcp.fd = -1;
+cleanup1:
+	close(rtp_end->rtp.fd);
+	rtp_end->rtp.fd = -1;
+cleanup0:
+	return -1;
+}
+
+static int int_bind(const char *port,
+		    struct mgcp_rtp_end *end, int (*cb)(struct osmo_fd *, unsigned),
+		    struct mgcp_endpoint *_endp,
+		    const char *source_addr, int rtp_port)
+{
+	if (end->rtp.fd != -1 || end->rtcp.fd != -1) {
+		LOGP(DLMGCP, LOGL_ERROR, "Previous %s was still bound on %d\n",
+			port, ENDPOINT_NUMBER(_endp));
+		mgcp_free_rtp_port(end);
+	}
+
+	end->local_port = rtp_port;
+	end->rtp.cb = cb;
+	end->rtp.data = _endp;
+	end->rtcp.data = _endp;
+	end->rtcp.cb = cb;
+	return bind_rtp(_endp->cfg, source_addr, end, ENDPOINT_NUMBER(_endp));
+}
+
+int mgcp_bind_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port)
+{
+	return int_bind("bts-port", &endp->bts_end,
+			rtp_data_bts, endp,
+			mgcp_bts_src_addr(endp), rtp_port);
+}
+
+int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port)
+{
+	return int_bind("net-port", &endp->net_end,
+			rtp_data_net, endp,
+			mgcp_net_src_addr(endp), rtp_port);
+}
+
+int mgcp_bind_trans_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port)
+{
+	return int_bind("trans-net", &endp->trans_net,
+			rtp_data_trans_net, endp,
+			endp->cfg->source_addr, rtp_port);
+}
+
+int mgcp_bind_trans_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port)
+{
+	return int_bind("trans-bts", &endp->trans_bts,
+			rtp_data_trans_bts, endp,
+			endp->cfg->source_addr, rtp_port);
+}
+
+int mgcp_free_rtp_port(struct mgcp_rtp_end *end)
+{
+	if (end->rtp.fd != -1) {
+		close(end->rtp.fd);
+		end->rtp.fd = -1;
+		osmo_fd_unregister(&end->rtp);
+	}
+
+	if (end->rtcp.fd != -1) {
+		close(end->rtcp.fd);
+		end->rtcp.fd = -1;
+		osmo_fd_unregister(&end->rtcp);
+	}
+
+	return 0;
+}
+
+
+void mgcp_state_calc_loss(struct mgcp_rtp_state *state,
+			struct mgcp_rtp_end *end, uint32_t *expected,
+			int *loss)
+{
+	*expected = state->stats_cycles + state->stats_max_seq;
+	*expected = *expected - state->stats_base_seq + 1;
+
+	if (!state->stats_initialized) {
+		*expected = 0;
+		*loss = 0;
+		return;
+	}
+
+	/*
+	 * Make sure the sign is correct and use the biggest
+	 * positive/negative number that fits.
+	 */
+	*loss = *expected - end->packets;
+	if (*expected < end->packets) {
+		if (*loss > 0)
+			*loss = INT_MIN;
+	} else {
+		if (*loss < 0)
+			*loss = INT_MAX;
+	}
+}
+
+uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *state)
+{
+	if (!state->stats_initialized)
+		return 0;
+	return state->stats_jitter >> 4;
+}
diff --git a/src/libosmo-legacy-mgcp/mgcp_osmux.c b/src/libosmo-legacy-mgcp/mgcp_osmux.c
new file mode 100644
index 0000000..743d3f9
--- /dev/null
+++ b/src/libosmo-legacy-mgcp/mgcp_osmux.c
@@ -0,0 +1,583 @@
+/*
+ * (C) 2012-2013 by Pablo Neira Ayuso <pablo@gnumonks.org>
+ * (C) 2012-2013 by On Waves ehf <http://www.on-waves.com>
+ * All rights not specifically granted under this license are 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.
+ */
+
+#include <stdio.h> /* for printf */
+#include <string.h> /* for memcpy */
+#include <stdlib.h> /* for abs */
+#include <inttypes.h> /* for PRIu64 */
+#include <netinet/in.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/talloc.h>
+
+#include <osmocom/netif/osmux.h>
+#include <osmocom/netif/rtp.h>
+
+#include <osmocom/legacy_mgcp/mgcp.h>
+#include <osmocom/legacy_mgcp/mgcp_internal.h>
+#include <osmocom/legacy_mgcp/osmux.h>
+
+static struct osmo_fd osmux_fd;
+
+static LLIST_HEAD(osmux_handle_list);
+
+struct osmux_handle {
+	struct llist_head head;
+	struct osmux_in_handle *in;
+	struct in_addr rem_addr;
+	int rem_port;
+	int refcnt;
+};
+
+static void *osmux;
+
+static void osmux_deliver(struct msgb *batch_msg, void *data)
+{
+	struct osmux_handle *handle = data;
+	struct sockaddr_in out = {
+		.sin_family = AF_INET,
+		.sin_port = handle->rem_port,
+	};
+
+	memcpy(&out.sin_addr, &handle->rem_addr, sizeof(handle->rem_addr));
+	sendto(osmux_fd.fd, batch_msg->data, batch_msg->len, 0,
+		(struct sockaddr *)&out, sizeof(out));
+	msgb_free(batch_msg);
+}
+
+static struct osmux_handle *
+osmux_handle_find_get(struct in_addr *addr, int rem_port)
+{
+	struct osmux_handle *h;
+
+	/* Lookup for existing OSMUX handle for this destination address. */
+	llist_for_each_entry(h, &osmux_handle_list, head) {
+		if (memcmp(&h->rem_addr, addr, sizeof(struct in_addr)) == 0 &&
+		    h->rem_port == rem_port) {
+			LOGP(DLMGCP, LOGL_DEBUG, "using existing OSMUX handle "
+						"for addr=%s:%d\n",
+				inet_ntoa(*addr), ntohs(rem_port));
+			h->refcnt++;
+			return h;
+		}
+	}
+
+	return NULL;
+}
+
+static void osmux_handle_put(struct osmux_in_handle *in)
+{
+	struct osmux_handle *h;
+
+	/* Lookup for existing OSMUX handle for this destination address. */
+	llist_for_each_entry(h, &osmux_handle_list, head) {
+		if (h->in == in) {
+			if (--h->refcnt == 0) {
+				LOGP(DLMGCP, LOGL_INFO,
+				     "Releasing unused osmux handle for %s:%d\n",
+				     inet_ntoa(h->rem_addr),
+				     ntohs(h->rem_port));
+				LOGP(DLMGCP, LOGL_INFO, "Stats: "
+				     "input RTP msgs: %u bytes: %"PRIu64" "
+				     "output osmux msgs: %u bytes: %"PRIu64"\n",
+				     in->stats.input_rtp_msgs,
+				     in->stats.input_rtp_bytes,
+				     in->stats.output_osmux_msgs,
+				     in->stats.output_osmux_bytes);
+				llist_del(&h->head);
+				osmux_xfrm_input_fini(h->in);
+				talloc_free(h);
+			}
+			return;
+		}
+	}
+	LOGP(DLMGCP, LOGL_ERROR, "cannot find Osmux input handle %p\n", in);
+}
+
+static struct osmux_handle *
+osmux_handle_alloc(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
+{
+	struct osmux_handle *h;
+
+	h = talloc_zero(osmux, struct osmux_handle);
+	if (!h)
+		return NULL;
+	h->rem_addr = *addr;
+	h->rem_port = rem_port;
+	h->refcnt++;
+
+	h->in = talloc_zero(h, struct osmux_in_handle);
+	if (!h->in) {
+		talloc_free(h);
+		return NULL;
+	}
+
+	h->in->osmux_seq = 0; /* sequence number to start OSmux message from */
+	h->in->batch_factor = cfg->osmux_batch;
+	/* If batch size is zero, the library defaults to 1470 bytes. */
+	h->in->batch_size = cfg->osmux_batch_size;
+	h->in->deliver = osmux_deliver;
+	osmux_xfrm_input_init(h->in);
+	h->in->data = h;
+
+	llist_add(&h->head, &osmux_handle_list);
+
+	LOGP(DLMGCP, LOGL_DEBUG, "created new OSMUX handle for addr=%s:%d\n",
+		inet_ntoa(*addr), ntohs(rem_port));
+
+	return h;
+}
+
+static struct osmux_in_handle *
+osmux_handle_lookup(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
+{
+	struct osmux_handle *h;
+
+	h = osmux_handle_find_get(addr, rem_port);
+	if (h != NULL)
+		return h->in;
+
+	h = osmux_handle_alloc(cfg, addr, rem_port);
+	if (h == NULL)
+		return NULL;
+
+	return h->in;
+}
+
+int osmux_xfrm_to_osmux(int type, char *buf, int rc, struct mgcp_endpoint *endp)
+{
+	int ret;
+	struct msgb *msg;
+
+	msg = msgb_alloc(4096, "RTP");
+	if (!msg)
+		return 0;
+
+	memcpy(msg->data, buf, rc);
+	msgb_put(msg, rc);
+
+	while ((ret = osmux_xfrm_input(endp->osmux.in, msg, endp->osmux.cid)) > 0) {
+		/* batch full, build and deliver it */
+		osmux_xfrm_input_deliver(endp->osmux.in);
+	}
+	return 0;
+}
+
+static struct mgcp_endpoint *
+endpoint_lookup(struct mgcp_config *cfg, int cid,
+		struct in_addr *from_addr, int type)
+{
+	struct mgcp_endpoint *tmp = NULL;
+	int i;
+
+	/* Lookup for the endpoint that corresponds to this port */
+	for (i=0; i<cfg->trunk.number_endpoints; i++) {
+		struct in_addr *this;
+
+		tmp = &cfg->trunk.endpoints[i];
+
+		if (!tmp->allocated)
+			continue;
+
+		switch(type) {
+		case MGCP_DEST_NET:
+			this = &tmp->net_end.addr;
+			break;
+		case MGCP_DEST_BTS:
+			this = &tmp->bts_end.addr;
+			break;
+		default:
+			/* Should not ever happen */
+			LOGP(DLMGCP, LOGL_ERROR, "Bad type %d. Fix your code.\n", type);
+			return NULL;
+		}
+
+		if (tmp->osmux.cid == cid && this->s_addr == from_addr->s_addr)
+			return tmp;
+	}
+
+	LOGP(DLMGCP, LOGL_ERROR, "Cannot find endpoint with cid=%d\n", cid);
+
+	return NULL;
+}
+
+static void scheduled_tx_net_cb(struct msgb *msg, void *data)
+{
+	struct mgcp_endpoint *endp = data;
+	struct sockaddr_in addr = {
+		.sin_addr = endp->net_end.addr,
+		.sin_port = endp->net_end.rtp_port,
+	};
+
+	endp->bts_end.octets += msg->len;
+	endp->bts_end.packets++;
+
+	mgcp_send(endp, MGCP_DEST_NET, 1, &addr, (char *)msg->data, msg->len);
+	msgb_free(msg);
+}
+
+static void scheduled_tx_bts_cb(struct msgb *msg, void *data)
+{
+	struct mgcp_endpoint *endp = data;
+	struct sockaddr_in addr = {
+		.sin_addr = endp->bts_end.addr,
+		.sin_port = endp->bts_end.rtp_port,
+	};
+
+	endp->net_end.octets += msg->len;
+	endp->net_end.packets++;
+
+	mgcp_send(endp, MGCP_DEST_BTS, 1, &addr, (char *)msg->data, msg->len);
+	msgb_free(msg);
+}
+
+static struct msgb *osmux_recv(struct osmo_fd *ofd, struct sockaddr_in *addr)
+{
+	struct msgb *msg;
+	socklen_t slen = sizeof(*addr);
+	int ret;
+
+	msg = msgb_alloc(4096, "OSMUX");
+	if (!msg) {
+		LOGP(DLMGCP, LOGL_ERROR, "cannot allocate message\n");
+		return NULL;
+	}
+	ret = recvfrom(ofd->fd, msg->data, msg->data_len, 0,
+			(struct sockaddr *)addr, &slen);
+	if (ret <= 0) {
+		msgb_free(msg);
+		LOGP(DLMGCP, LOGL_ERROR, "cannot receive message\n");
+		return NULL;
+	}
+	msgb_put(msg, ret);
+
+	return msg;
+}
+
+#define osmux_chunk_length(msg, rem) (rem - msg->len);
+
+int osmux_read_from_bsc_nat_cb(struct osmo_fd *ofd, unsigned int what)
+{
+	struct msgb *msg;
+	struct osmux_hdr *osmuxh;
+	struct llist_head list;
+	struct sockaddr_in addr;
+	struct mgcp_config *cfg = ofd->data;
+	uint32_t rem;
+
+	msg = osmux_recv(ofd, &addr);
+	if (!msg)
+		return -1;
+
+	/* not any further processing dummy messages */
+	if (msg->data[0] == MGCP_DUMMY_LOAD)
+		goto out;
+
+	rem = msg->len;
+	while((osmuxh = osmux_xfrm_output_pull(msg)) != NULL) {
+		struct mgcp_endpoint *endp;
+
+		/* Yes, we use MGCP_DEST_NET to locate the origin */
+		endp = endpoint_lookup(cfg, osmuxh->circuit_id,
+				       &addr.sin_addr, MGCP_DEST_NET);
+		if (!endp) {
+			LOGP(DLMGCP, LOGL_ERROR,
+			     "Cannot find an endpoint for circuit_id=%d\n",
+			     osmuxh->circuit_id);
+			goto out;
+		}
+		endp->osmux.stats.octets += osmux_chunk_length(msg, rem);
+		endp->osmux.stats.chunks++;
+		rem = msg->len;
+
+		osmux_xfrm_output(osmuxh, &endp->osmux.out, &list);
+		osmux_tx_sched(&list, scheduled_tx_bts_cb, endp);
+	}
+out:
+	msgb_free(msg);
+	return 0;
+}
+
+/* This is called from the bsc-nat */
+static int osmux_handle_dummy(struct mgcp_config *cfg, struct sockaddr_in *addr,
+			      struct msgb *msg)
+{
+	struct mgcp_endpoint *endp;
+	uint8_t osmux_cid;
+
+	if (msg->len < 1 + sizeof(osmux_cid)) {
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "Discarding truncated Osmux dummy load\n");
+		goto out;
+	}
+
+	LOGP(DLMGCP, LOGL_DEBUG, "Received Osmux dummy load from %s\n",
+	     inet_ntoa(addr->sin_addr));
+
+	if (!cfg->osmux) {
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "bsc wants to use Osmux but bsc-nat did not request it\n");
+		goto out;
+	}
+
+	/* extract the osmux CID from the dummy message */
+	memcpy(&osmux_cid, &msg->data[1], sizeof(osmux_cid));
+
+	endp = endpoint_lookup(cfg, osmux_cid, &addr->sin_addr, MGCP_DEST_BTS);
+	if (!endp) {
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "Cannot find endpoint for Osmux CID %d\n", osmux_cid);
+		goto out;
+	}
+
+	if (endp->osmux.state == OSMUX_STATE_ENABLED)
+		goto out;
+
+	if (osmux_enable_endpoint(endp, &addr->sin_addr, addr->sin_port) < 0 ) {
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "Could not enable osmux in endpoint %d\n",
+		     ENDPOINT_NUMBER(endp));
+		goto out;
+	}
+
+	LOGP(DLMGCP, LOGL_INFO, "Enabling osmux in endpoint %d for %s:%u\n",
+	     ENDPOINT_NUMBER(endp), inet_ntoa(addr->sin_addr),
+	     ntohs(addr->sin_port));
+out:
+	msgb_free(msg);
+	return 0;
+}
+
+int osmux_read_from_bsc_cb(struct osmo_fd *ofd, unsigned int what)
+{
+	struct msgb *msg;
+	struct osmux_hdr *osmuxh;
+	struct llist_head list;
+	struct sockaddr_in addr;
+	struct mgcp_config *cfg = ofd->data;
+	uint32_t rem;
+
+	msg = osmux_recv(ofd, &addr);
+	if (!msg)
+		return -1;
+
+	/* not any further processing dummy messages */
+	if (msg->data[0] == MGCP_DUMMY_LOAD)
+		return osmux_handle_dummy(cfg, &addr, msg);
+
+	rem = msg->len;
+	while((osmuxh = osmux_xfrm_output_pull(msg)) != NULL) {
+		struct mgcp_endpoint *endp;
+
+		/* Yes, we use MGCP_DEST_BTS to locate the origin */
+		endp = endpoint_lookup(cfg, osmuxh->circuit_id,
+				       &addr.sin_addr, MGCP_DEST_BTS);
+		if (!endp) {
+			LOGP(DLMGCP, LOGL_ERROR,
+			     "Cannot find an endpoint for circuit_id=%d\n",
+			     osmuxh->circuit_id);
+			goto out;
+		}
+		endp->osmux.stats.octets += osmux_chunk_length(msg, rem);
+		endp->osmux.stats.chunks++;
+		rem = msg->len;
+
+		osmux_xfrm_output(osmuxh, &endp->osmux.out, &list);
+		osmux_tx_sched(&list, scheduled_tx_net_cb, endp);
+	}
+out:
+	msgb_free(msg);
+	return 0;
+}
+
+int osmux_init(int role, struct mgcp_config *cfg)
+{
+	int ret;
+
+	switch(role) {
+	case OSMUX_ROLE_BSC:
+		osmux_fd.cb = osmux_read_from_bsc_nat_cb;
+		break;
+	case OSMUX_ROLE_BSC_NAT:
+		osmux_fd.cb = osmux_read_from_bsc_cb;
+		break;
+	default:
+		LOGP(DLMGCP, LOGL_ERROR, "wrong role for OSMUX\n");
+		return -1;
+	}
+	osmux_fd.data = cfg;
+
+	ret = mgcp_create_bind(cfg->osmux_addr, &osmux_fd, cfg->osmux_port);
+	if (ret < 0) {
+		LOGP(DLMGCP, LOGL_ERROR, "cannot bind OSMUX socket\n");
+		return ret;
+	}
+	mgcp_set_ip_tos(osmux_fd.fd, cfg->endp_dscp);
+	osmux_fd.when |= BSC_FD_READ;
+
+	ret = osmo_fd_register(&osmux_fd);
+	if (ret < 0) {
+		LOGP(DLMGCP, LOGL_ERROR, "cannot register OSMUX socket\n");
+		return ret;
+	}
+	cfg->osmux_init = 1;
+
+	return 0;
+}
+
+int osmux_enable_endpoint(struct mgcp_endpoint *endp, struct in_addr *addr, uint16_t port)
+{
+	/* If osmux is enabled, initialize the output handler. This handler is
+	 * used to reconstruct the RTP flow from osmux. The RTP SSRC is
+	 * allocated based on the circuit ID (endp->osmux.cid), which is unique
+	 * in the local scope to the BSC/BSC-NAT. We use it to divide the RTP
+	 * SSRC space (2^32) by the 256 possible circuit IDs, then randomly
+	 * select one value from that window. Thus, we have no chance to have
+	 * overlapping RTP SSRC traveling to the BTSes behind the BSC,
+	 * similarly, for flows traveling to the MSC.
+	 */
+	static const uint32_t rtp_ssrc_winlen = UINT32_MAX / 256;
+
+	if (endp->osmux.state == OSMUX_STATE_DISABLED) {
+		LOGP(DLMGCP, LOGL_ERROR, "Endpoint %u didn't request Osmux\n",
+		     ENDPOINT_NUMBER(endp));
+		return -1;
+	}
+
+	osmux_xfrm_output_init(&endp->osmux.out,
+			       (endp->osmux.cid * rtp_ssrc_winlen) +
+			       (random() % rtp_ssrc_winlen));
+
+	endp->osmux.in = osmux_handle_lookup(endp->cfg, addr, port);
+	if (!endp->osmux.in) {
+		LOGP(DLMGCP, LOGL_ERROR, "Cannot allocate input osmux handle\n");
+		return -1;
+	}
+	if (!osmux_xfrm_input_open_circuit(endp->osmux.in, endp->osmux.cid,
+					   endp->cfg->osmux_dummy)) {
+		LOGP(DLMGCP, LOGL_ERROR, "Cannot open osmux circuit %u\n",
+		     endp->osmux.cid);
+		return -1;
+	}
+
+	switch (endp->cfg->role) {
+		case MGCP_BSC_NAT:
+			endp->type = MGCP_OSMUX_BSC_NAT;
+			break;
+		case MGCP_BSC:
+			endp->type = MGCP_OSMUX_BSC;
+			break;
+	}
+	endp->osmux.state = OSMUX_STATE_ENABLED;
+
+	return 0;
+}
+
+void osmux_disable_endpoint(struct mgcp_endpoint *endp)
+{
+	LOGP(DLMGCP, LOGL_INFO, "Releasing endpoint %u using Osmux CID %u\n",
+	     ENDPOINT_NUMBER(endp), endp->osmux.cid);
+	osmux_xfrm_input_close_circuit(endp->osmux.in, endp->osmux.cid);
+	endp->osmux.state = OSMUX_STATE_DISABLED;
+	endp->osmux.cid = -1;
+	osmux_handle_put(endp->osmux.in);
+}
+
+void osmux_release_cid(struct mgcp_endpoint *endp)
+{
+	if (endp->osmux.allocated_cid >= 0)
+		osmux_put_cid(endp->osmux.allocated_cid);
+	endp->osmux.allocated_cid = -1;
+}
+
+void osmux_allocate_cid(struct mgcp_endpoint *endp)
+{
+	osmux_release_cid(endp);
+	endp->osmux.allocated_cid = osmux_get_cid();
+}
+
+/* We don't need to send the dummy load for osmux so often as another endpoint
+ * may have already punched the hole in the firewall. This approach is simple
+ * though.
+ */
+int osmux_send_dummy(struct mgcp_endpoint *endp)
+{
+	char buf[1 + sizeof(uint8_t)];
+	struct in_addr addr_unset = {};
+
+	buf[0] = MGCP_DUMMY_LOAD;
+	memcpy(&buf[1], &endp->osmux.cid, sizeof(endp->osmux.cid));
+
+	/* Wait until we have the connection information from MDCX */
+	if (memcmp(&endp->net_end.addr, &addr_unset, sizeof(addr_unset)) == 0)
+		return 0;
+
+	if (endp->osmux.state == OSMUX_STATE_ACTIVATING) {
+		if (osmux_enable_endpoint(endp, &endp->net_end.addr,
+					  htons(endp->cfg->osmux_port)) < 0) {
+			LOGP(DLMGCP, LOGL_ERROR,
+			     "Could not activate osmux in endpoint %d\n",
+			     ENDPOINT_NUMBER(endp));
+		}
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "Osmux CID %u for %s:%u is now enabled\n",
+		     endp->osmux.cid, inet_ntoa(endp->net_end.addr),
+		     endp->cfg->osmux_port);
+	}
+	LOGP(DLMGCP, LOGL_DEBUG,
+	     "sending OSMUX dummy load to %s CID %u\n",
+	     inet_ntoa(endp->net_end.addr), endp->osmux.cid);
+
+	return mgcp_udp_send(osmux_fd.fd, &endp->net_end.addr,
+			     htons(endp->cfg->osmux_port), buf, sizeof(buf));
+}
+
+/* bsc-nat allocates/releases the Osmux circuit ID */
+static uint8_t osmux_cid_bitmap[(OSMUX_CID_MAX + 1) / 8];
+
+int osmux_used_cid(void)
+{
+	int i, j, used = 0;
+
+	for (i = 0; i < sizeof(osmux_cid_bitmap); i++) {
+		for (j = 0; j < 8; j++) {
+			if (osmux_cid_bitmap[i] & (1 << j))
+				used += 1;
+		}
+	}
+
+	return used;
+}
+
+int osmux_get_cid(void)
+{
+	int i, j;
+
+	for (i = 0; i < sizeof(osmux_cid_bitmap); i++) {
+		for (j = 0; j < 8; j++) {
+			if (osmux_cid_bitmap[i] & (1 << j))
+				continue;
+
+			osmux_cid_bitmap[i] |= (1 << j);
+			LOGP(DLMGCP, LOGL_DEBUG,
+			     "Allocating Osmux CID %u from pool\n", (i * 8) + j);
+			return (i * 8) + j;
+		}
+	}
+
+	LOGP(DLMGCP, LOGL_ERROR, "All Osmux circuits are in use!\n");
+	return -1;
+}
+
+void osmux_put_cid(uint8_t osmux_cid)
+{
+	LOGP(DLMGCP, LOGL_DEBUG, "Osmux CID %u is back to the pool\n", osmux_cid);
+	osmux_cid_bitmap[osmux_cid / 8] &= ~(1 << (osmux_cid % 8));
+}
diff --git a/src/libosmo-legacy-mgcp/mgcp_protocol.c b/src/libosmo-legacy-mgcp/mgcp_protocol.c
new file mode 100644
index 0000000..332aa91
--- /dev/null
+++ b/src/libosmo-legacy-mgcp/mgcp_protocol.c
@@ -0,0 +1,1639 @@
+/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
+/* The protocol implementation */
+
+/*
+ * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-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/>.
+ *
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <limits.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/select.h>
+
+#include <osmocom/legacy_mgcp/mgcp.h>
+#include <osmocom/legacy_mgcp/mgcp_internal.h>
+
+#define for_each_non_empty_line(line, save)			\
+	for (line = strtok_r(NULL, "\r\n", &save); line;\
+	     line = strtok_r(NULL, "\r\n", &save))
+
+
+static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end);
+
+struct mgcp_request {
+	char *name;
+	struct msgb *(*handle_request) (struct mgcp_parse_data *data);
+	char *debug_name;
+};
+
+#define MGCP_REQUEST(NAME, REQ, DEBUG_NAME) \
+	{ .name = NAME, .handle_request = REQ, .debug_name = DEBUG_NAME },
+
+static struct msgb *handle_audit_endpoint(struct mgcp_parse_data *data);
+static struct msgb *handle_create_con(struct mgcp_parse_data *data);
+static struct msgb *handle_delete_con(struct mgcp_parse_data *data);
+static struct msgb *handle_modify_con(struct mgcp_parse_data *data);
+static struct msgb *handle_rsip(struct mgcp_parse_data *data);
+static struct msgb *handle_noti_req(struct mgcp_parse_data *data);
+
+static void create_transcoder(struct mgcp_endpoint *endp);
+static void delete_transcoder(struct mgcp_endpoint *endp);
+
+static int setup_rtp_processing(struct mgcp_endpoint *endp);
+
+static int mgcp_analyze_header(struct mgcp_parse_data *parse, char *data);
+
+/* Display an mgcp message on the log output */
+void display_mgcp_message(unsigned char *message, unsigned int len,
+			  char *preamble)
+{
+	unsigned char line[80];
+	unsigned char *ptr;
+	unsigned int consumed = 0;
+	unsigned int consumed_line = 0;
+	unsigned int line_count = 0;
+
+	if (!log_check_level(DLMGCP, LOGL_DEBUG))
+		return;
+
+	while (1) {
+		memset(line, 0, sizeof(line));
+		ptr = line;
+		consumed_line = 0;
+		do {
+			if (*message != '\n' && *message != '\r') {
+				*ptr = *message;
+				ptr++;
+			}
+			message++;
+			consumed++;
+			consumed_line++;
+		} while (*message != '\n' && consumed < len
+			 && consumed_line < sizeof(line));
+
+		if (strlen((const char *)line)) {
+			LOGP(DLMGCP, LOGL_DEBUG, "%s: line #%02u: %s\n",
+			     preamble, line_count, line);
+			line_count++;
+		}
+
+		if (consumed >= len)
+			return;
+	}
+}
+
+static int mgcp_check_param(const struct mgcp_endpoint *endp, const char *line)
+{
+	const size_t line_len = strlen(line);
+	if (line[0] != '\0' && line_len < 2) {
+		LOGP(DLMGCP, LOGL_ERROR,
+			"Wrong MGCP option format: '%s' on 0x%x\n",
+			line, ENDPOINT_NUMBER(endp));
+		return 0;
+	}
+
+	return 1;
+}
+
+static uint32_t generate_call_id(struct mgcp_config *cfg)
+{
+	int i;
+
+	/* use the call id */
+	++cfg->last_call_id;
+
+	/* handle wrap around */
+	if (cfg->last_call_id == CI_UNUSED)
+		++cfg->last_call_id;
+
+	/* callstack can only be of size number_of_endpoints */
+	/* verify that the call id is free, e.g. in case of overrun */
+	for (i = 1; i < cfg->trunk.number_endpoints; ++i)
+		if (cfg->trunk.endpoints[i].ci == cfg->last_call_id)
+			return generate_call_id(cfg);
+
+	return cfg->last_call_id;
+}
+
+/*
+ * array of function pointers for handling various
+ * messages. In the future this might be binary sorted
+ * for performance reasons.
+ */
+static const struct mgcp_request mgcp_requests [] = {
+	MGCP_REQUEST("AUEP", handle_audit_endpoint, "AuditEndpoint")
+	MGCP_REQUEST("CRCX", handle_create_con, "CreateConnection")
+	MGCP_REQUEST("DLCX", handle_delete_con, "DeleteConnection")
+	MGCP_REQUEST("MDCX", handle_modify_con, "ModifiyConnection")
+	MGCP_REQUEST("RQNT", handle_noti_req, "NotificationRequest")
+
+	/* SPEC extension */
+	MGCP_REQUEST("RSIP", handle_rsip, "ReSetInProgress")
+};
+
+static struct msgb *mgcp_msgb_alloc(void)
+{
+	struct msgb *msg;
+	msg = msgb_alloc_headroom(4096, 128, "MGCP msg");
+	if (!msg)
+	    LOGP(DLMGCP, LOGL_ERROR, "Failed to msgb for MGCP data.\n");
+
+	return msg;
+}
+
+static struct msgb *do_retransmission(const struct mgcp_endpoint *endp)
+{
+	struct msgb *msg = mgcp_msgb_alloc();
+	if (!msg)
+		return NULL;
+
+	msg->l2h = msgb_put(msg, strlen(endp->last_response));
+	memcpy(msg->l2h, endp->last_response, msgb_l2len(msg));
+	return msg;
+}
+
+static struct msgb *create_resp(struct mgcp_endpoint *endp, int code,
+				const char *txt, const char *msg,
+				const char *trans, const char *param,
+				const char *sdp)
+{
+	int len;
+	struct msgb *res;
+
+	res = mgcp_msgb_alloc();
+	if (!res)
+		return NULL;
+
+	len = snprintf((char *) res->data, 2048, "%d %s%s%s\r\n%s",
+			code, trans, txt, param ? param : "", sdp ? sdp : "");
+	if (len < 0) {
+		LOGP(DLMGCP, LOGL_ERROR, "Failed to sprintf MGCP response.\n");
+		msgb_free(res);
+		return NULL;
+	}
+
+	res->l2h = msgb_put(res, len);
+	LOGP(DLMGCP, LOGL_DEBUG, "Generated response: code=%d\n", code);
+	display_mgcp_message(res->l2h, msgb_l2len(res), "Generated response");
+
+	/*
+	 * Remember the last transmission per endpoint.
+	 */
+	if (endp) {
+		struct mgcp_trunk_config *tcfg = endp->tcfg;
+		talloc_free(endp->last_response);
+		talloc_free(endp->last_trans);
+		endp->last_trans = talloc_strdup(tcfg->endpoints, trans);
+		endp->last_response = talloc_strndup(tcfg->endpoints,
+						(const char *) res->l2h,
+						msgb_l2len(res));
+	}
+
+	return res;
+}
+
+static struct msgb *create_ok_resp_with_param(struct mgcp_endpoint *endp,
+					int code, const char *msg,
+					const char *trans, const char *param)
+{
+	return create_resp(endp, code, " OK", msg, trans, param, NULL);
+}
+
+static struct msgb *create_ok_response(struct mgcp_endpoint *endp,
+					int code, const char *msg, const char *trans)
+{
+	return create_ok_resp_with_param(endp, code, msg, trans, NULL);
+}
+
+static struct msgb *create_err_response(struct mgcp_endpoint *endp,
+					int code, const char *msg, const char *trans)
+{
+	return create_resp(endp, code, " FAIL", msg, trans, NULL, NULL);
+}
+
+static int write_response_sdp(struct mgcp_endpoint *endp,
+			      char *sdp_record, size_t size, const char *addr)
+{
+	const char *fmtp_extra;
+	const char *audio_name;
+	int payload_type;
+	int len;
+	int nchars;
+
+	endp->cfg->get_net_downlink_format_cb(endp, &payload_type,
+					      &audio_name, &fmtp_extra);
+
+	len = snprintf(sdp_record, size,
+			"v=0\r\n"
+			"o=- %u 23 IN IP4 %s\r\n"
+			"s=-\r\n"
+			"c=IN IP4 %s\r\n"
+			"t=0 0\r\n",
+			endp->ci, addr, addr);
+
+	if (len < 0 || len >= size)
+		goto buffer_too_small;
+
+	if (payload_type >= 0) {
+		nchars = snprintf(sdp_record + len, size - len,
+				  "m=audio %d RTP/AVP %d\r\n",
+				  endp->net_end.local_port, payload_type);
+		if (nchars < 0 || nchars >= size - len)
+			goto buffer_too_small;
+
+		len += nchars;
+
+		if (audio_name && endp->tcfg->audio_send_name) {
+			nchars = snprintf(sdp_record + len, size - len,
+					  "a=rtpmap:%d %s\r\n",
+					  payload_type, audio_name);
+
+			if (nchars < 0 || nchars >= size - len)
+				goto buffer_too_small;
+
+			len += nchars;
+		}
+
+		if (fmtp_extra) {
+			nchars = snprintf(sdp_record + len, size - len,
+					  "%s\r\n", fmtp_extra);
+
+			if (nchars < 0 || nchars >= size - len)
+				goto buffer_too_small;
+
+			len += nchars;
+		}
+	}
+	if (endp->bts_end.packet_duration_ms > 0 && endp->tcfg->audio_send_ptime) {
+		nchars = snprintf(sdp_record + len, size - len,
+				  "a=ptime:%d\r\n",
+				  endp->bts_end.packet_duration_ms);
+		if (nchars < 0 || nchars >= size - len)
+			goto buffer_too_small;
+
+		len += nchars;
+	}
+
+	return len;
+
+buffer_too_small:
+	LOGP(DLMGCP, LOGL_ERROR, "SDP buffer too small: %zu (needed %d)\n",
+	     size, len);
+	return -1;
+}
+
+static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
+					     const char *msg, const char *trans_id)
+{
+	const char *addr = endp->cfg->local_ip;
+	char sdp_record[4096];
+	int len;
+	int nchars;
+	char osmux_extension[strlen("\nX-Osmux: 255") + 1];
+
+	if (!addr)
+		addr = mgcp_net_src_addr(endp);
+
+	if (endp->osmux.state == OSMUX_STATE_NEGOTIATING) {
+		sprintf(osmux_extension, "\nX-Osmux: %u", endp->osmux.cid);
+		endp->osmux.state = OSMUX_STATE_ACTIVATING;
+	} else {
+		osmux_extension[0] = '\0';
+	}
+
+	len = snprintf(sdp_record, sizeof(sdp_record),
+		       "I: %u%s\n\n", endp->ci, osmux_extension);
+	if (len < 0)
+		return NULL;
+
+	nchars = write_response_sdp(endp, sdp_record + len,
+				    sizeof(sdp_record) - len - 1, addr);
+	if (nchars < 0)
+		return NULL;
+
+	len += nchars;
+
+	sdp_record[sizeof(sdp_record) - 1] = '\0';
+
+	return create_resp(endp, 200, " OK", msg, trans_id, NULL, sdp_record);
+}
+
+static void send_dummy(struct mgcp_endpoint *endp)
+{
+	if (endp->osmux.state != OSMUX_STATE_DISABLED)
+		osmux_send_dummy(endp);
+	else
+		mgcp_send_dummy(endp);
+}
+
+/*
+ * handle incoming messages:
+ *   - this can be a command (four letters, space, transaction id)
+ *   - or a response (three numbers, space, transaction id)
+ */
+struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg)
+{
+	struct mgcp_parse_data pdata;
+	int i, code, handled = 0;
+	struct msgb *resp = NULL;
+	char *data;
+
+	if (msgb_l2len(msg) < 4) {
+		LOGP(DLMGCP, LOGL_ERROR, "msg too short: %d\n", msg->len);
+		return NULL;
+	}
+
+	if (mgcp_msg_terminate_nul(msg))
+		return NULL;
+
+	display_mgcp_message(msg->l2h, msgb_l2len(msg), "Received message");
+
+        /* attempt to treat it as a response */
+        if (sscanf((const char *)&msg->l2h[0], "%3d %*s", &code) == 1) {
+		LOGP(DLMGCP, LOGL_DEBUG, "Response: Code: %d\n", code);
+		return NULL;
+	}
+
+	msg->l3h = &msg->l2h[4];
+
+
+	/*
+	 * Check for a duplicate message and respond.
+	 */
+	memset(&pdata, 0, sizeof(pdata));
+	pdata.cfg = cfg;
+	data = strline_r((char *) msg->l3h, &pdata.save);
+	pdata.found = mgcp_analyze_header(&pdata, data);
+	if (pdata.endp && pdata.trans
+			&& pdata.endp->last_trans
+			&& strcmp(pdata.endp->last_trans, pdata.trans) == 0) {
+		return do_retransmission(pdata.endp);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(mgcp_requests); ++i) {
+		if (strncmp(mgcp_requests[i].name, (const char *) &msg->l2h[0], 4) == 0) {
+			handled = 1;
+			resp = mgcp_requests[i].handle_request(&pdata);
+			break;
+		}
+	}
+
+	if (!handled)
+		LOGP(DLMGCP, LOGL_NOTICE, "MSG with type: '%.4s' not handled\n", &msg->l2h[0]);
+
+	return resp;
+}
+
+/**
+ * We have a null terminated string with the endpoint name here. We only
+ * support two kinds. Simple ones as seen on the BSC level and the ones
+ * seen on the trunk side.
+ */
+static struct mgcp_endpoint *find_e1_endpoint(struct mgcp_config *cfg,
+					     const char *mgcp)
+{
+	char *rest = NULL;
+	struct mgcp_trunk_config *tcfg;
+	int trunk, endp;
+
+	trunk = strtoul(mgcp + 6, &rest, 10);
+	if (rest == NULL || rest[0] != '/' || trunk < 1) {
+		LOGP(DLMGCP, LOGL_ERROR, "Wrong trunk name '%s'\n", mgcp);
+		return NULL;
+	}
+
+	endp = strtoul(rest + 1, &rest, 10);
+	if (rest == NULL || rest[0] != '@') {
+		LOGP(DLMGCP, LOGL_ERROR, "Wrong endpoint name '%s'\n", mgcp);
+		return NULL;
+	}
+
+	/* signalling is on timeslot 1 */
+	if (endp == 1)
+		return NULL;
+
+	tcfg = mgcp_trunk_num(cfg, trunk);
+	if (!tcfg) {
+		LOGP(DLMGCP, LOGL_ERROR, "The trunk %d is not declared.\n", trunk);
+		return NULL;
+	}
+
+	if (!tcfg->endpoints) {
+		LOGP(DLMGCP, LOGL_ERROR, "Endpoints of trunk %d not allocated.\n", trunk);
+		return NULL;
+	}
+
+	if (endp < 1 || endp >= tcfg->number_endpoints) {
+		LOGP(DLMGCP, LOGL_ERROR, "Failed to find endpoint '%s'\n", mgcp);
+		return NULL;
+	}
+
+	return &tcfg->endpoints[endp];
+}
+
+static struct mgcp_endpoint *find_endpoint(struct mgcp_config *cfg, const char *mgcp)
+{
+	char *endptr = NULL;
+	unsigned int gw = INT_MAX;
+
+	if (strncmp(mgcp, "ds/e1", 5) == 0)
+		return find_e1_endpoint(cfg, mgcp);
+
+	gw = strtoul(mgcp, &endptr, 16);
+	if (gw > 0 && gw < cfg->trunk.number_endpoints && endptr[0] == '@')
+		return &cfg->trunk.endpoints[gw];
+
+	LOGP(DLMGCP, LOGL_ERROR, "Not able to find the endpoint: '%s'\n", mgcp);
+	return NULL;
+}
+
+/**
+ * @returns 0 when the status line was complete and transaction_id and
+ * endp out parameters are set.
+ */
+static int mgcp_analyze_header(struct mgcp_parse_data *pdata, char *data)
+{
+	int i = 0;
+	char *elem, *save = NULL;
+
+	OSMO_ASSERT(data);
+	pdata->trans = "000000";
+
+	for (elem = strtok_r(data, " ", &save); elem;
+	     elem = strtok_r(NULL, " ", &save)) {
+		switch (i) {
+		case 0:
+			pdata->trans = elem;
+			break;
+		case 1:
+			pdata->endp = find_endpoint(pdata->cfg, elem);
+			if (!pdata->endp) {
+				LOGP(DLMGCP, LOGL_ERROR,
+				     "Unable to find Endpoint `%s'\n", elem);
+				return -1;
+			}
+			break;
+		case 2:
+			if (strcmp("MGCP", elem)) {
+				LOGP(DLMGCP, LOGL_ERROR,
+				     "MGCP header parsing error\n");
+				return -1;
+			}
+			break;
+		case 3:
+			if (strcmp("1.0", elem)) {
+				LOGP(DLMGCP, LOGL_ERROR, "MGCP version `%s' "
+					"not supported\n", elem);
+				return -1;
+			}
+			break;
+		}
+		i++;
+	}
+
+	if (i != 4) {
+		LOGP(DLMGCP, LOGL_ERROR, "MGCP status line too short.\n");
+		pdata->trans = "000000";
+		pdata->endp = NULL;
+		return -1;
+	}
+
+	return 0;
+}
+
+static int verify_call_id(const struct mgcp_endpoint *endp,
+			  const char *callid)
+{
+	if (strcmp(endp->callid, callid) != 0) {
+		LOGP(DLMGCP, LOGL_ERROR, "CallIDs does not match on 0x%x. '%s' != '%s'\n",
+			ENDPOINT_NUMBER(endp), endp->callid, callid);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int verify_ci(const struct mgcp_endpoint *endp,
+		     const char *_ci)
+{
+	uint32_t ci = strtoul(_ci, NULL, 10);
+
+	if (ci != endp->ci) {
+		LOGP(DLMGCP, LOGL_ERROR, "ConnectionIdentifiers do not match on 0x%x. %u != %s\n",
+			ENDPOINT_NUMBER(endp), endp->ci, _ci);
+		return -1;
+	}
+
+	return 0;
+}
+
+static struct msgb *handle_audit_endpoint(struct mgcp_parse_data *p)
+{
+	if (p->found != 0)
+		return create_err_response(NULL, 500, "AUEP", p->trans);
+	else
+		return create_ok_response(p->endp, 200, "AUEP", p->trans);
+}
+
+static int parse_conn_mode(const char *msg, struct mgcp_endpoint *endp)
+{
+	int ret = 0;
+	if (strcmp(msg, "recvonly") == 0)
+		endp->conn_mode = MGCP_CONN_RECV_ONLY;
+	else if (strcmp(msg, "sendrecv") == 0)
+		endp->conn_mode = MGCP_CONN_RECV_SEND;
+	else if (strcmp(msg, "sendonly") == 0)
+		endp->conn_mode = MGCP_CONN_SEND_ONLY;
+	else if (strcmp(msg, "loopback") == 0)
+		endp->conn_mode = MGCP_CONN_LOOPBACK;
+	else {
+		LOGP(DLMGCP, LOGL_ERROR, "Unknown connection mode: '%s'\n", msg);
+		ret = -1;
+	}
+
+	endp->net_end.output_enabled =
+		endp->conn_mode & MGCP_CONN_SEND_ONLY ? 1 : 0;
+	endp->bts_end.output_enabled =
+		endp->conn_mode & MGCP_CONN_RECV_ONLY ? 1 : 0;
+
+	LOGP(DLMGCP, LOGL_DEBUG, "endpoint %x connection mode '%s' %d output_enabled net %d bts %d\n",
+	     ENDPOINT_NUMBER(endp),
+	     msg, endp->conn_mode, endp->net_end.output_enabled,
+	     endp->bts_end.output_enabled);
+
+	return ret;
+}
+
+static int allocate_port(struct mgcp_endpoint *endp, struct mgcp_rtp_end *end,
+			 struct mgcp_port_range *range,
+			 int (*alloc)(struct mgcp_endpoint *endp, int port))
+{
+	int i;
+
+	if (range->mode == PORT_ALLOC_STATIC) {
+		end->local_alloc = PORT_ALLOC_STATIC;
+		return 0;
+	}
+
+	/* attempt to find a port */
+	for (i = 0; i < 200; ++i) {
+		int rc;
+
+		if (range->last_port >= range->range_end)
+			range->last_port = range->range_start;
+
+		rc = alloc(endp, range->last_port);
+
+		range->last_port += 2;
+		if (rc == 0) {
+			end->local_alloc = PORT_ALLOC_DYNAMIC;
+			return 0;
+		}
+
+	}
+
+	LOGP(DLMGCP, LOGL_ERROR, "Allocating a RTP/RTCP port failed 200 times 0x%x.\n",
+	     ENDPOINT_NUMBER(endp));
+	return -1;
+}
+
+static int allocate_ports(struct mgcp_endpoint *endp)
+{
+	if (allocate_port(endp, &endp->net_end, &endp->cfg->net_ports,
+			  mgcp_bind_net_rtp_port) != 0)
+		return -1;
+
+	if (allocate_port(endp, &endp->bts_end, &endp->cfg->bts_ports,
+			  mgcp_bind_bts_rtp_port) != 0) {
+		mgcp_rtp_end_reset(&endp->net_end);
+		return -1;
+	}
+
+	if (endp->cfg->transcoder_ip && endp->tcfg->trunk_type == MGCP_TRUNK_VIRTUAL) {
+		if (allocate_port(endp, &endp->trans_net,
+				  &endp->cfg->transcoder_ports,
+				  mgcp_bind_trans_net_rtp_port) != 0) {
+			mgcp_rtp_end_reset(&endp->net_end);
+			mgcp_rtp_end_reset(&endp->bts_end);
+			return -1;
+		}
+
+		if (allocate_port(endp, &endp->trans_bts,
+				  &endp->cfg->transcoder_ports,
+				  mgcp_bind_trans_bts_rtp_port) != 0) {
+			mgcp_rtp_end_reset(&endp->net_end);
+			mgcp_rtp_end_reset(&endp->bts_end);
+			mgcp_rtp_end_reset(&endp->trans_net);
+			return -1;
+		}
+
+		/* remember that we have set up transcoding */
+		endp->type = MGCP_RTP_TRANSCODED;
+	}
+
+	return 0;
+}
+
+/* Set the LCO from a string (see RFC 3435).
+ * The string is stored in the 'string' field. A NULL string is handled excatly
+ * like an empty string, the 'string' field is never NULL after this function
+ * has been called. */
+static void set_local_cx_options(void *ctx, struct mgcp_lco *lco,
+				 const char *options)
+{
+	char *p_opt, *a_opt;
+	char codec[9];
+
+	talloc_free(lco->string);
+	talloc_free(lco->codec);
+	lco->codec = NULL;
+	lco->pkt_period_min = lco->pkt_period_max = 0;
+	lco->string = talloc_strdup(ctx, options ? options : "");
+
+	p_opt = strstr(lco->string, "p:");
+	if (p_opt && sscanf(p_opt, "p:%d-%d",
+			    &lco->pkt_period_min, &lco->pkt_period_max) == 1)
+		lco->pkt_period_max = lco->pkt_period_min;
+
+	a_opt = strstr(lco->string, "a:");
+	if (a_opt && sscanf(a_opt, "a:%8[^,]", codec) == 1)
+		lco->codec = talloc_strdup(ctx, codec);
+}
+
+void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
+			 struct mgcp_rtp_end *rtp)
+{
+	struct mgcp_trunk_config *tcfg = endp->tcfg;
+
+	int patch_ssrc = expect_ssrc_change && tcfg->force_constant_ssrc;
+
+	rtp->force_aligned_timing = tcfg->force_aligned_timing;
+	rtp->force_constant_ssrc = patch_ssrc ? 1 : 0;
+
+	LOGP(DLMGCP, LOGL_DEBUG,
+	     "Configuring RTP endpoint: local port %d%s%s\n",
+	     ntohs(rtp->rtp_port),
+	     rtp->force_aligned_timing ? ", force constant timing" : "",
+	     rtp->force_constant_ssrc ? ", force constant ssrc" : "");
+}
+
+uint32_t mgcp_rtp_packet_duration(struct mgcp_endpoint *endp,
+				  struct mgcp_rtp_end *rtp)
+{
+	int f = 0;
+
+	/* Get the number of frames per channel and packet */
+	if (rtp->frames_per_packet)
+		f = rtp->frames_per_packet;
+	else if (rtp->packet_duration_ms && rtp->codec.frame_duration_num) {
+		int den = 1000 * rtp->codec.frame_duration_num;
+		f = (rtp->packet_duration_ms * rtp->codec.frame_duration_den + den/2)
+			/ den;
+	}
+
+	return rtp->codec.rate * f * rtp->codec.frame_duration_num / rtp->codec.frame_duration_den;
+}
+
+static int mgcp_parse_osmux_cid(const char *line)
+{
+	int osmux_cid;
+
+	if (sscanf(line + 2, "Osmux: %u", &osmux_cid) != 1)
+		return -1;
+
+	if (osmux_cid > OSMUX_CID_MAX) {
+		LOGP(DLMGCP, LOGL_ERROR, "Osmux ID too large: %u > %u\n",
+		     osmux_cid, OSMUX_CID_MAX);
+		return -1;
+	}
+	LOGP(DLMGCP, LOGL_DEBUG, "bsc-nat offered Osmux CID %u\n", osmux_cid);
+
+	return osmux_cid;
+}
+
+static int mgcp_osmux_setup(struct mgcp_endpoint *endp, const char *line)
+{
+	if (!endp->cfg->osmux_init) {
+		if (osmux_init(OSMUX_ROLE_BSC, endp->cfg) < 0) {
+			LOGP(DLMGCP, LOGL_ERROR, "Cannot init OSMUX\n");
+			return -1;
+		}
+		LOGP(DLMGCP, LOGL_NOTICE, "OSMUX socket has been set up\n");
+	}
+
+	return mgcp_parse_osmux_cid(line);
+}
+
+static struct msgb *handle_create_con(struct mgcp_parse_data *p)
+{
+	struct mgcp_trunk_config *tcfg;
+	struct mgcp_endpoint *endp = p->endp;
+	int error_code = 400;
+
+	const char *local_options = NULL;
+	const char *callid = NULL;
+	const char *mode = NULL;
+	char *line;
+	int have_sdp = 0, osmux_cid = -1;
+
+	if (p->found != 0)
+		return create_err_response(NULL, 510, "CRCX", p->trans);
+
+	/* parse CallID C: and LocalParameters L: */
+	for_each_line(line, p->save) {
+		if (!mgcp_check_param(endp, line))
+			continue;
+
+		switch (line[0]) {
+		case 'L':
+			local_options = (const char *) line + 3;
+			break;
+		case 'C':
+			callid = (const char *) line + 3;
+			break;
+		case 'M':
+			mode = (const char *) line + 3;
+			break;
+		case 'X':
+			/* Osmux is not enabled in this bsc, ignore it so the
+			 * bsc-nat knows that we don't want to use Osmux.
+			 */
+			if (!p->endp->cfg->osmux)
+				break;
+
+			if (strncmp("Osmux: ", line + 2, strlen("Osmux: ")) == 0)
+				osmux_cid = mgcp_osmux_setup(endp, line);
+			break;
+		case '\0':
+			have_sdp = 1;
+			goto mgcp_header_done;
+		default:
+			LOGP(DLMGCP, LOGL_NOTICE, "Unhandled option: '%c'/%d on 0x%x\n",
+				*line, *line, ENDPOINT_NUMBER(endp));
+			break;
+		}
+	}
+
+mgcp_header_done:
+	tcfg = p->endp->tcfg;
+
+	/* Check required data */
+	if (!callid || !mode) {
+		LOGP(DLMGCP, LOGL_ERROR, "Missing callid and mode in CRCX on 0x%x\n",
+		     ENDPOINT_NUMBER(endp));
+		return create_err_response(endp, 400, "CRCX", p->trans);
+	}
+
+	if (endp->allocated) {
+		if (tcfg->force_realloc) {
+			LOGP(DLMGCP, LOGL_NOTICE, "Endpoint 0x%x already allocated. Forcing realloc.\n",
+			    ENDPOINT_NUMBER(endp));
+			mgcp_release_endp(endp);
+			if (p->cfg->realloc_cb)
+				p->cfg->realloc_cb(tcfg, ENDPOINT_NUMBER(endp));
+		} else {
+			LOGP(DLMGCP, LOGL_ERROR, "Endpoint is already used. 0x%x\n",
+			     ENDPOINT_NUMBER(endp));
+			return create_err_response(endp, 400, "CRCX", p->trans);
+		}
+	}
+
+	/* copy some parameters */
+	endp->callid = talloc_strdup(tcfg->endpoints, callid);
+
+	set_local_cx_options(endp->tcfg->endpoints, &endp->local_options,
+			     local_options);
+
+	if (parse_conn_mode(mode, endp) != 0) {
+		    error_code = 517;
+		    goto error2;
+	}
+
+	/* initialize */
+	endp->net_end.rtp_port = endp->net_end.rtcp_port = endp->bts_end.rtp_port = endp->bts_end.rtcp_port = 0;
+	mgcp_rtp_end_config(endp, 0, &endp->net_end);
+	mgcp_rtp_end_config(endp, 0, &endp->bts_end);
+
+	/* set to zero until we get the info */
+	memset(&endp->net_end.addr, 0, sizeof(endp->net_end.addr));
+
+	/* bind to the port now */
+	if (allocate_ports(endp) != 0)
+		goto error2;
+
+	/* assign a local call identifier or fail */
+	endp->ci = generate_call_id(p->cfg);
+	if (endp->ci == CI_UNUSED)
+		goto error2;
+
+	/* Annotate Osmux circuit ID and set it to negotiating state until this
+	 * is fully set up from the dummy load.
+	 */
+	endp->osmux.state = OSMUX_STATE_DISABLED;
+	if (osmux_cid >= 0) {
+		endp->osmux.cid = osmux_cid;
+		endp->osmux.state = OSMUX_STATE_NEGOTIATING;
+	} else if (endp->cfg->osmux == OSMUX_USAGE_ONLY) {
+		LOGP(DLMGCP, LOGL_ERROR,
+			"Osmux only and no osmux offered on 0x%x\n", ENDPOINT_NUMBER(endp));
+		goto error2;
+	}
+
+	endp->allocated = 1;
+
+	/* set up RTP media parameters */
+	mgcp_set_audio_info(p->cfg, &endp->bts_end.codec, tcfg->audio_payload, tcfg->audio_name);
+	endp->bts_end.fmtp_extra = talloc_strdup(tcfg->endpoints,
+						tcfg->audio_fmtp_extra);
+	if (have_sdp)
+		mgcp_parse_sdp_data(endp, &endp->net_end, p);
+	else if (endp->local_options.codec)
+		mgcp_set_audio_info(p->cfg, &endp->net_end.codec,
+			       PTYPE_UNDEFINED, endp->local_options.codec);
+
+	if (p->cfg->bts_force_ptime) {
+		endp->bts_end.packet_duration_ms = p->cfg->bts_force_ptime;
+		endp->bts_end.force_output_ptime = 1;
+	}
+
+	if (setup_rtp_processing(endp) != 0)
+		goto error2;
+
+	/* policy CB */
+	if (p->cfg->policy_cb) {
+		int rc;
+		rc = p->cfg->policy_cb(tcfg, ENDPOINT_NUMBER(endp),
+				MGCP_ENDP_CRCX, p->trans);
+		switch (rc) {
+		case MGCP_POLICY_REJECT:
+			LOGP(DLMGCP, LOGL_NOTICE, "CRCX rejected by policy on 0x%x\n",
+			     ENDPOINT_NUMBER(endp));
+			mgcp_release_endp(endp);
+			return create_err_response(endp, 400, "CRCX", p->trans);
+			break;
+		case MGCP_POLICY_DEFER:
+			/* stop processing */
+			create_transcoder(endp);
+			return NULL;
+			break;
+		case MGCP_POLICY_CONT:
+			/* just continue */
+			break;
+		}
+	}
+
+	LOGP(DLMGCP, LOGL_DEBUG, "Creating endpoint on: 0x%x CI: %u port: %u/%u\n",
+		ENDPOINT_NUMBER(endp), endp->ci,
+		endp->net_end.local_port, endp->bts_end.local_port);
+	if (p->cfg->change_cb)
+		p->cfg->change_cb(tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_CRCX);
+
+	if (endp->conn_mode & MGCP_CONN_RECV_ONLY && tcfg->keepalive_interval != 0) {
+		send_dummy(endp);
+	}
+
+	create_transcoder(endp);
+	return create_response_with_sdp(endp, "CRCX", p->trans);
+error2:
+	mgcp_release_endp(endp);
+	LOGP(DLMGCP, LOGL_NOTICE, "Resource error on 0x%x\n", ENDPOINT_NUMBER(endp));
+	return create_err_response(endp, error_code, "CRCX", p->trans);
+}
+
+static struct msgb *handle_modify_con(struct mgcp_parse_data *p)
+{
+	struct mgcp_endpoint *endp = p->endp;
+	int error_code = 500;
+	int silent = 0;
+	int have_sdp = 0;
+	char *line;
+	const char *local_options = NULL;
+
+	if (p->found != 0)
+		return create_err_response(NULL, 510, "MDCX", p->trans);
+
+	if (endp->ci == CI_UNUSED) {
+		LOGP(DLMGCP, LOGL_ERROR, "Endpoint is not "
+			"holding a connection. 0x%x\n", ENDPOINT_NUMBER(endp));
+		return create_err_response(endp, 400, "MDCX", p->trans);
+	}
+
+	for_each_line(line, p->save) {
+		if (!mgcp_check_param(endp, line))
+			continue;
+
+		switch (line[0]) {
+		case 'C': {
+			if (verify_call_id(endp, line + 3) != 0)
+				goto error3;
+			break;
+		}
+		case 'I': {
+			if (verify_ci(endp, line + 3) != 0)
+				goto error3;
+			break;
+		}
+		case 'L':
+			local_options = (const char *) line + 3;
+			break;
+		case 'M':
+			if (parse_conn_mode(line + 3, endp) != 0) {
+			    error_code = 517;
+			    goto error3;
+			}
+			endp->orig_mode = endp->conn_mode;
+			break;
+		case 'Z':
+			silent = strcmp("noanswer", line + 3) == 0;
+			break;
+		case '\0':
+			/* SDP file begins */
+			have_sdp = 1;
+			mgcp_parse_sdp_data(endp, &endp->net_end, p);
+			/* This will exhaust p->save, so the loop will
+			 * terminate next time.
+			 */
+			break;
+		default:
+			LOGP(DLMGCP, LOGL_NOTICE, "Unhandled MGCP option: '%c'/%d on 0x%x\n",
+				line[0], line[0], ENDPOINT_NUMBER(endp));
+			break;
+		}
+	}
+
+	set_local_cx_options(endp->tcfg->endpoints, &endp->local_options,
+			     local_options);
+
+	if (!have_sdp && endp->local_options.codec)
+		mgcp_set_audio_info(p->cfg, &endp->net_end.codec,
+			       PTYPE_UNDEFINED, endp->local_options.codec);
+
+	if (setup_rtp_processing(endp) != 0)
+		goto error3;
+
+	/* policy CB */
+	if (p->cfg->policy_cb) {
+		int rc;
+		rc = p->cfg->policy_cb(endp->tcfg, ENDPOINT_NUMBER(endp),
+						MGCP_ENDP_MDCX, p->trans);
+		switch (rc) {
+		case MGCP_POLICY_REJECT:
+			LOGP(DLMGCP, LOGL_NOTICE, "MDCX rejected by policy on 0x%x\n",
+			     ENDPOINT_NUMBER(endp));
+			if (silent)
+				goto out_silent;
+			return create_err_response(endp, 400, "MDCX", p->trans);
+			break;
+		case MGCP_POLICY_DEFER:
+			/* stop processing */
+			LOGP(DLMGCP, LOGL_DEBUG, "endp %x MDCX defer\n",
+			     ENDPOINT_NUMBER(endp));
+			return NULL;
+			break;
+		case MGCP_POLICY_CONT:
+			/* just continue */
+			break;
+		}
+	}
+
+	mgcp_rtp_end_config(endp, 1, &endp->net_end);
+	mgcp_rtp_end_config(endp, 1, &endp->bts_end);
+
+	/* modify */
+	LOGP(DLMGCP, LOGL_DEBUG, "Modified endpoint on: 0x%x Server: %s:%u\n",
+		ENDPOINT_NUMBER(endp), inet_ntoa(endp->net_end.addr), ntohs(endp->net_end.rtp_port));
+	if (p->cfg->change_cb)
+		p->cfg->change_cb(endp->tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_MDCX);
+
+	if (endp->conn_mode & MGCP_CONN_RECV_ONLY &&
+	    endp->tcfg->keepalive_interval != 0)
+		send_dummy(endp);
+
+	if (silent)
+		goto out_silent;
+
+	return create_response_with_sdp(endp, "MDCX", p->trans);
+
+error3:
+	return create_err_response(endp, error_code, "MDCX", p->trans);
+
+
+out_silent:
+	LOGP(DLMGCP, LOGL_DEBUG, "endp %x Modify endpoint: silent exit\n",
+	     ENDPOINT_NUMBER(endp));
+	return NULL;
+}
+
+static struct msgb *handle_delete_con(struct mgcp_parse_data *p)
+{
+	struct mgcp_endpoint *endp = p->endp;
+	int error_code = 400;
+	int silent = 0;
+	char *line;
+	char stats[1048];
+
+	if (p->found != 0)
+		return create_err_response(NULL, error_code, "DLCX", p->trans);
+
+	if (!p->endp->allocated) {
+		LOGP(DLMGCP, LOGL_ERROR, "Endpoint is not used. 0x%x\n",
+			ENDPOINT_NUMBER(endp));
+		return create_err_response(endp, 400, "DLCX", p->trans);
+	}
+
+	for_each_line(line, p->save) {
+		if (!mgcp_check_param(endp, line))
+			continue;
+
+		switch (line[0]) {
+		case 'C':
+			if (verify_call_id(endp, line + 3) != 0)
+				goto error3;
+			break;
+		case 'I':
+			if (verify_ci(endp, line + 3) != 0)
+				goto error3;
+			break;
+		case 'Z':
+			silent = strcmp("noanswer", line + 3) == 0;
+			break;
+		default:
+			LOGP(DLMGCP, LOGL_NOTICE, "Unhandled option: '%c'/%d on 0x%x\n",
+				line[0], line[0], ENDPOINT_NUMBER(endp));
+			break;
+		}
+	}
+
+	/* policy CB */
+	if (p->cfg->policy_cb) {
+		int rc;
+		rc = p->cfg->policy_cb(endp->tcfg, ENDPOINT_NUMBER(endp),
+						MGCP_ENDP_DLCX, p->trans);
+		switch (rc) {
+		case MGCP_POLICY_REJECT:
+			LOGP(DLMGCP, LOGL_NOTICE, "DLCX rejected by policy on 0x%x\n",
+			     ENDPOINT_NUMBER(endp));
+			if (silent)
+				goto out_silent;
+			return create_err_response(endp, 400, "DLCX", p->trans);
+			break;
+		case MGCP_POLICY_DEFER:
+			/* stop processing */
+			delete_transcoder(endp);
+			return NULL;
+			break;
+		case MGCP_POLICY_CONT:
+			/* just continue */
+			break;
+		}
+	}
+
+	/* free the connection */
+	LOGP(DLMGCP, LOGL_DEBUG, "Deleted endpoint on: 0x%x Server: %s:%u\n",
+		ENDPOINT_NUMBER(endp), inet_ntoa(endp->net_end.addr), ntohs(endp->net_end.rtp_port));
+
+	/* save the statistics of the current call */
+	mgcp_format_stats(endp, stats, sizeof(stats));
+
+	delete_transcoder(endp);
+	mgcp_release_endp(endp);
+	if (p->cfg->change_cb)
+		p->cfg->change_cb(endp->tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_DLCX);
+
+	if (silent)
+		goto out_silent;
+	return create_ok_resp_with_param(endp, 250, "DLCX", p->trans, stats);
+
+error3:
+	return create_err_response(endp, error_code, "DLCX", p->trans);
+
+out_silent:
+	return NULL;
+}
+
+static struct msgb *handle_rsip(struct mgcp_parse_data *p)
+{
+	if (p->found != 0) {
+		LOGP(DLMGCP, LOGL_ERROR, "Failed to find the endpoint.\n");
+		return NULL;
+	}
+
+	if (p->cfg->reset_cb)
+		p->cfg->reset_cb(p->endp->tcfg);
+	return NULL;
+}
+
+static char extract_tone(const char *line)
+{
+	const char *str = strstr(line, "D/");
+	if (!str)
+		return CHAR_MAX;
+
+	return str[2];
+}
+
+/*
+ * This can request like DTMF detection and forward, fax detection... it
+ * can also request when the notification should be send and such. We don't
+ * do this right now.
+ */
+static struct msgb *handle_noti_req(struct mgcp_parse_data *p)
+{
+	int res = 0;
+	char *line;
+	char tone = CHAR_MAX;
+
+	if (p->found != 0)
+		return create_err_response(NULL, 400, "RQNT", p->trans);
+
+	for_each_line(line, p->save) {
+		switch (line[0]) {
+		case 'S':
+			tone = extract_tone(line);
+			break;
+		}
+	}
+
+	/* we didn't see a signal request with a tone */
+	if (tone == CHAR_MAX)
+		return create_ok_response(p->endp, 200, "RQNT", p->trans);
+
+	if (p->cfg->rqnt_cb)
+		res = p->cfg->rqnt_cb(p->endp, tone);
+
+	return res == 0 ?
+		create_ok_response(p->endp, 200, "RQNT", p->trans) :
+		create_err_response(p->endp, res, "RQNT", p->trans);
+}
+
+static void mgcp_keepalive_timer_cb(void *_tcfg)
+{
+	struct mgcp_trunk_config *tcfg = _tcfg;
+	int i;
+	LOGP(DLMGCP, LOGL_DEBUG, "Triggered trunk %d keepalive timer.\n",
+	     tcfg->trunk_nr);
+
+	if (tcfg->keepalive_interval <= 0)
+		return;
+
+	for (i = 1; i < tcfg->number_endpoints; ++i) {
+		struct mgcp_endpoint *endp = &tcfg->endpoints[i];
+		if (endp->conn_mode == MGCP_CONN_RECV_ONLY)
+			send_dummy(endp);
+	}
+
+	LOGP(DLMGCP, LOGL_DEBUG, "Rescheduling trunk %d keepalive timer.\n",
+	     tcfg->trunk_nr);
+	osmo_timer_schedule(&tcfg->keepalive_timer, tcfg->keepalive_interval, 0);
+}
+
+void mgcp_trunk_set_keepalive(struct mgcp_trunk_config *tcfg, int interval)
+{
+	tcfg->keepalive_interval = interval;
+	osmo_timer_setup(&tcfg->keepalive_timer, mgcp_keepalive_timer_cb, tcfg);
+
+	if (interval <= 0)
+		osmo_timer_del(&tcfg->keepalive_timer);
+	else
+		osmo_timer_schedule(&tcfg->keepalive_timer,
+				    tcfg->keepalive_interval, 0);
+}
+
+struct mgcp_config *mgcp_config_alloc(void)
+{
+	struct mgcp_config *cfg;
+
+	cfg = talloc_zero(NULL, struct mgcp_config);
+	if (!cfg) {
+		LOGP(DLMGCP, LOGL_FATAL, "Failed to allocate config.\n");
+		return NULL;
+	}
+
+	cfg->source_port = 2427;
+	cfg->source_addr = talloc_strdup(cfg, "0.0.0.0");
+	cfg->osmux_addr = talloc_strdup(cfg, "0.0.0.0");
+
+	cfg->transcoder_remote_base = 4000;
+
+	cfg->bts_ports.base_port = RTP_PORT_DEFAULT;
+	cfg->net_ports.base_port = RTP_PORT_NET_DEFAULT;
+
+	cfg->rtp_processing_cb = &mgcp_rtp_processing_default;
+	cfg->setup_rtp_processing_cb = &mgcp_setup_rtp_processing_default;
+
+	cfg->get_net_downlink_format_cb = &mgcp_get_net_downlink_format_default;
+
+	/* default trunk handling */
+	cfg->trunk.cfg = cfg;
+	cfg->trunk.trunk_nr = 0;
+	cfg->trunk.trunk_type = MGCP_TRUNK_VIRTUAL;
+	cfg->trunk.audio_name = talloc_strdup(cfg, "AMR/8000");
+	cfg->trunk.audio_payload = 126;
+	cfg->trunk.audio_send_ptime = 1;
+	cfg->trunk.audio_send_name = 1;
+	cfg->trunk.omit_rtcp = 0;
+	mgcp_trunk_set_keepalive(&cfg->trunk, MGCP_KEEPALIVE_ONCE);
+
+	INIT_LLIST_HEAD(&cfg->trunks);
+
+	return cfg;
+}
+
+struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int nr)
+{
+	struct mgcp_trunk_config *trunk;
+
+	trunk = talloc_zero(cfg, struct mgcp_trunk_config);
+	if (!trunk) {
+		LOGP(DLMGCP, LOGL_ERROR, "Failed to allocate.\n");
+		return NULL;
+	}
+
+	trunk->cfg = cfg;
+	trunk->trunk_type = MGCP_TRUNK_E1;
+	trunk->trunk_nr = nr;
+	trunk->audio_name = talloc_strdup(cfg, "AMR/8000");
+	trunk->audio_payload = 126;
+	trunk->audio_send_ptime = 1;
+	trunk->audio_send_name = 1;
+	trunk->number_endpoints = 33;
+	trunk->omit_rtcp = 0;
+	mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
+	llist_add_tail(&trunk->entry, &cfg->trunks);
+	return trunk;
+}
+
+struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index)
+{
+	struct mgcp_trunk_config *trunk;
+
+	llist_for_each_entry(trunk, &cfg->trunks, entry)
+		if (trunk->trunk_nr == index)
+			return trunk;
+
+	return NULL;
+}
+
+static void mgcp_rtp_codec_reset(struct mgcp_rtp_codec *codec)
+{
+	codec->payload_type = -1;
+	talloc_free(codec->subtype_name);
+	codec->subtype_name = NULL;
+	talloc_free(codec->audio_name);
+	codec->audio_name = NULL;
+	codec->frame_duration_num = DEFAULT_RTP_AUDIO_FRAME_DUR_NUM;
+	codec->frame_duration_den = DEFAULT_RTP_AUDIO_FRAME_DUR_DEN;
+	codec->rate               = DEFAULT_RTP_AUDIO_DEFAULT_RATE;
+	codec->channels           = DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS;
+}
+
+static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end)
+{
+	if (end->local_alloc == PORT_ALLOC_DYNAMIC) {
+		mgcp_free_rtp_port(end);
+		end->local_port = 0;
+	}
+
+	end->packets = 0;
+	end->octets = 0;
+	end->dropped_packets = 0;
+	memset(&end->addr, 0, sizeof(end->addr));
+	end->rtp_port = end->rtcp_port = 0;
+	end->local_alloc = -1;
+	talloc_free(end->fmtp_extra);
+	end->fmtp_extra = NULL;
+	talloc_free(end->rtp_process_data);
+	end->rtp_process_data = NULL;
+
+	/* Set default values */
+	end->frames_per_packet  = 0; /* unknown */
+	end->packet_duration_ms = DEFAULT_RTP_AUDIO_PACKET_DURATION_MS;
+	end->output_enabled	= 0;
+
+	mgcp_rtp_codec_reset(&end->codec);
+	mgcp_rtp_codec_reset(&end->alt_codec);
+}
+
+static void mgcp_rtp_end_init(struct mgcp_rtp_end *end)
+{
+	mgcp_rtp_end_reset(end);
+	end->rtp.fd = -1;
+	end->rtcp.fd = -1;
+}
+
+int mgcp_endpoints_allocate(struct mgcp_trunk_config *tcfg)
+{
+	int i;
+
+	/* Initialize all endpoints */
+	tcfg->endpoints = _talloc_zero_array(tcfg->cfg,
+				       sizeof(struct mgcp_endpoint),
+				       tcfg->number_endpoints, "endpoints");
+	if (!tcfg->endpoints)
+		return -1;
+
+	for (i = 0; i < tcfg->number_endpoints; ++i) {
+		tcfg->endpoints[i].osmux.allocated_cid = -1;
+		tcfg->endpoints[i].ci = CI_UNUSED;
+		tcfg->endpoints[i].cfg = tcfg->cfg;
+		tcfg->endpoints[i].tcfg = tcfg;
+		mgcp_rtp_end_init(&tcfg->endpoints[i].net_end);
+		mgcp_rtp_end_init(&tcfg->endpoints[i].bts_end);
+		mgcp_rtp_end_init(&tcfg->endpoints[i].trans_net);
+		mgcp_rtp_end_init(&tcfg->endpoints[i].trans_bts);
+	}
+
+	return 0;
+}
+
+void mgcp_release_endp(struct mgcp_endpoint *endp)
+{
+	LOGP(DLMGCP, LOGL_DEBUG, "Releasing endpoint on: 0x%x\n", ENDPOINT_NUMBER(endp));
+	endp->ci = CI_UNUSED;
+	endp->allocated = 0;
+
+	talloc_free(endp->callid);
+	endp->callid = NULL;
+
+	talloc_free(endp->local_options.string);
+	endp->local_options.string = NULL;
+	talloc_free(endp->local_options.codec);
+	endp->local_options.codec = NULL;
+
+	mgcp_rtp_end_reset(&endp->bts_end);
+	mgcp_rtp_end_reset(&endp->net_end);
+	mgcp_rtp_end_reset(&endp->trans_net);
+	mgcp_rtp_end_reset(&endp->trans_bts);
+	endp->type = MGCP_RTP_DEFAULT;
+
+	memset(&endp->net_state, 0, sizeof(endp->net_state));
+	memset(&endp->bts_state, 0, sizeof(endp->bts_state));
+
+	endp->conn_mode = endp->orig_mode = MGCP_CONN_NONE;
+
+	if (endp->osmux.state == OSMUX_STATE_ENABLED)
+		osmux_disable_endpoint(endp);
+
+	/* release the circuit ID if it had been allocated */
+	osmux_release_cid(endp);
+
+	memset(&endp->taps, 0, sizeof(endp->taps));
+}
+
+void mgcp_initialize_endp(struct mgcp_endpoint *endp)
+{
+	return mgcp_release_endp(endp);
+}
+
+static int send_trans(struct mgcp_config *cfg, const char *buf, int len)
+{
+	struct sockaddr_in addr;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sin_family = AF_INET;
+	addr.sin_addr = cfg->transcoder_in;
+	addr.sin_port = htons(2427);
+	return sendto(cfg->gw_fd.bfd.fd, buf, len, 0,
+		      (struct sockaddr *) &addr, sizeof(addr));
+}
+
+static void send_msg(struct mgcp_endpoint *endp, int endpoint, int port,
+		     const char *msg, const char *mode)
+{
+	char buf[2096];
+	int len;
+	int nchars;
+
+	/* hardcoded to AMR right now, we do not know the real type at this point */
+	len = snprintf(buf, sizeof(buf),
+			"%s 42 %x@mgw MGCP 1.0\r\n"
+			"C: 4256\r\n"
+			"M: %s\r\n"
+			"\r\n",
+			msg, endpoint, mode);
+
+	if (len < 0)
+		return;
+
+	nchars = write_response_sdp(endp, buf + len, sizeof(buf) + len - 1, NULL);
+	if (nchars < 0)
+		return;
+
+	len += nchars;
+
+	buf[sizeof(buf) - 1] = '\0';
+
+	send_trans(endp->cfg, buf, len);
+}
+
+static void send_dlcx(struct mgcp_endpoint *endp, int endpoint)
+{
+	char buf[2096];
+	int len;
+
+	len = snprintf(buf, sizeof(buf),
+			"DLCX 43 %x@mgw MGCP 1.0\r\n"
+			"C: 4256\r\n"
+			, endpoint);
+
+	if (len < 0)
+		return;
+
+	buf[sizeof(buf) - 1] = '\0';
+
+	send_trans(endp->cfg, buf, len);
+}
+
+static int send_agent(struct mgcp_config *cfg, const char *buf, int len)
+{
+	return write(cfg->gw_fd.bfd.fd, buf, len);
+}
+
+int mgcp_send_reset_all(struct mgcp_config *cfg)
+{
+	static const char mgcp_reset[] = {
+	    "RSIP 1 *@mgw MGCP 1.0\r\n"
+	};
+
+	return send_agent(cfg, mgcp_reset, sizeof mgcp_reset -1);
+}
+
+int mgcp_send_reset_ep(struct mgcp_endpoint *endp, int endpoint)
+{
+	char buf[128];
+	int len;
+
+	len = snprintf(buf, sizeof(buf),
+			"RSIP 39 %x@mgw MGCP 1.0\r\n"
+			, endpoint);
+	if (len < 0)
+		return len;
+
+	buf[sizeof(buf) - 1] = '\0';
+
+	return send_agent(endp->cfg, buf, len);
+}
+
+static int setup_rtp_processing(struct mgcp_endpoint *endp)
+{
+	int rc = 0;
+	struct mgcp_config *cfg = endp->cfg;
+
+	if (endp->type != MGCP_RTP_DEFAULT)
+		return 0;
+
+	if (endp->conn_mode == MGCP_CONN_LOOPBACK)
+		return 0;
+
+	if (endp->conn_mode & MGCP_CONN_SEND_ONLY)
+		rc |= cfg->setup_rtp_processing_cb(endp, &endp->net_end, &endp->bts_end);
+	else
+		rc |= cfg->setup_rtp_processing_cb(endp, &endp->net_end, NULL);
+
+	if (endp->conn_mode & MGCP_CONN_RECV_ONLY)
+		rc |= cfg->setup_rtp_processing_cb(endp, &endp->bts_end, &endp->net_end);
+	else
+		rc |= cfg->setup_rtp_processing_cb(endp, &endp->bts_end, NULL);
+	return rc;
+}
+
+static void create_transcoder(struct mgcp_endpoint *endp)
+{
+	int port;
+	int in_endp = ENDPOINT_NUMBER(endp);
+	int out_endp = endp_back_channel(in_endp);
+
+	if (endp->type != MGCP_RTP_TRANSCODED)
+		return;
+
+	send_msg(endp, in_endp, endp->trans_bts.local_port, "CRCX", "sendrecv");
+	send_msg(endp, in_endp, endp->trans_bts.local_port, "MDCX", "sendrecv");
+	send_msg(endp, out_endp, endp->trans_net.local_port, "CRCX", "sendrecv");
+	send_msg(endp, out_endp, endp->trans_net.local_port, "MDCX", "sendrecv");
+
+	port = rtp_calculate_port(in_endp, endp->cfg->transcoder_remote_base);
+	endp->trans_bts.rtp_port = htons(port);
+	endp->trans_bts.rtcp_port = htons(port + 1);
+
+	port = rtp_calculate_port(out_endp, endp->cfg->transcoder_remote_base);
+	endp->trans_net.rtp_port = htons(port);
+	endp->trans_net.rtcp_port = htons(port + 1);
+}
+
+static void delete_transcoder(struct mgcp_endpoint *endp)
+{
+	int in_endp = ENDPOINT_NUMBER(endp);
+	int out_endp = endp_back_channel(in_endp);
+
+	if (endp->type != MGCP_RTP_TRANSCODED)
+		return;
+
+	send_dlcx(endp, in_endp);
+	send_dlcx(endp, out_endp);
+}
+
+int mgcp_reset_transcoder(struct mgcp_config *cfg)
+{
+	if (!cfg->transcoder_ip)
+		return 0;
+
+	static const char mgcp_reset[] = {
+	    "RSIP 1 13@mgw MGCP 1.0\r\n"
+	};
+
+	return send_trans(cfg, mgcp_reset, sizeof mgcp_reset -1);
+}
+
+void mgcp_format_stats(struct mgcp_endpoint *endp, char *msg, size_t size)
+{
+	uint32_t expected, jitter;
+	int ploss;
+	int nchars;
+	mgcp_state_calc_loss(&endp->net_state, &endp->net_end,
+				&expected, &ploss);
+	jitter = mgcp_state_calc_jitter(&endp->net_state);
+
+	nchars = snprintf(msg, size,
+			  "\r\nP: PS=%u, OS=%u, PR=%u, OR=%u, PL=%d, JI=%u",
+			  endp->bts_end.packets, endp->bts_end.octets,
+			  endp->net_end.packets, endp->net_end.octets,
+			  ploss, jitter);
+	if (nchars < 0 || nchars >= size)
+		goto truncate;
+
+	msg += nchars;
+	size -= nchars;
+
+	/* Error Counter */
+	nchars = snprintf(msg, size,
+			  "\r\nX-Osmo-CP: EC TIS=%u, TOS=%u, TIR=%u, TOR=%u",
+			  endp->net_state.in_stream.err_ts_counter,
+			  endp->net_state.out_stream.err_ts_counter,
+			  endp->bts_state.in_stream.err_ts_counter,
+			  endp->bts_state.out_stream.err_ts_counter);
+	if (nchars < 0 || nchars >= size)
+		goto truncate;
+
+	msg += nchars;
+	size -= nchars;
+
+	if (endp->osmux.state == OSMUX_STATE_ENABLED) {
+		snprintf(msg, size,
+			 "\r\nX-Osmux-ST: CR=%u, BR=%u",
+			 endp->osmux.stats.chunks,
+			 endp->osmux.stats.octets);
+	}
+truncate:
+	msg[size - 1] = '\0';
+}
+
+int mgcp_parse_stats(struct msgb *msg, uint32_t *ps, uint32_t *os,
+		uint32_t *pr, uint32_t *_or, int *loss, uint32_t *jitter)
+{
+	char *line, *save;
+	int rc;
+
+	/* initialize with bad values */
+	*ps = *os = *pr = *_or = *jitter = UINT_MAX;
+	*loss = INT_MAX;
+
+
+	line = strtok_r((char *) msg->l2h, "\r\n", &save);
+	if (!line)
+		return -1;
+
+	/* this can only parse the message that is created above... */
+	for_each_non_empty_line(line, save) {
+		switch (line[0]) {
+		case 'P':
+			rc = sscanf(line, "P: PS=%u, OS=%u, PR=%u, OR=%u, PL=%d, JI=%u",
+					ps, os, pr, _or, loss, jitter);
+			return rc == 6 ? 0 : -1;
+		}
+	}
+
+	return -1;
+}
diff --git a/src/libosmo-legacy-mgcp/mgcp_sdp.c b/src/libosmo-legacy-mgcp/mgcp_sdp.c
new file mode 100644
index 0000000..055e1af
--- /dev/null
+++ b/src/libosmo-legacy-mgcp/mgcp_sdp.c
@@ -0,0 +1,305 @@
+/*
+ * Some SDP file parsing...
+ *
+ * (C) 2009-2015 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2014 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/>.
+ *
+ */
+
+#include <osmocom/legacy_mgcp/mgcp.h>
+#include <osmocom/legacy_mgcp/mgcp_internal.h>
+
+#include <errno.h>
+
+struct sdp_rtp_map {
+	/* the type */
+	int payload_type;
+	/* null, static or later dynamic codec name */
+	char *codec_name;
+	/* A pointer to the original line for later parsing */
+	char *map_line;
+
+	int rate;
+	int channels;
+};
+
+int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
+			int payload_type, const char *audio_name)
+{
+	int rate = codec->rate;
+	int channels = codec->channels;
+	char audio_codec[64];
+
+	talloc_free(codec->subtype_name);
+	codec->subtype_name = NULL;
+	talloc_free(codec->audio_name);
+	codec->audio_name = NULL;
+
+	if (payload_type != PTYPE_UNDEFINED)
+		codec->payload_type = payload_type;
+
+	if (!audio_name) {
+		switch (payload_type) {
+		case 0: audio_name = "PCMU/8000/1"; break;
+		case 3: audio_name = "GSM/8000/1"; break;
+		case 8: audio_name = "PCMA/8000/1"; break;
+		case 18: audio_name = "G729/8000/1"; break;
+		default:
+			 /* Payload type is unknown, don't change rate and
+			  * channels. */
+			 /* TODO: return value? */
+			 return 0;
+		}
+	}
+
+	if (sscanf(audio_name, "%63[^/]/%d/%d",
+		   audio_codec, &rate, &channels) < 1)
+		return -EINVAL;
+
+	codec->rate = rate;
+	codec->channels = channels;
+	codec->subtype_name = talloc_strdup(ctx, audio_codec);
+	codec->audio_name = talloc_strdup(ctx, audio_name);
+
+	if (!strcmp(audio_codec, "G729")) {
+		codec->frame_duration_num = 10;
+		codec->frame_duration_den = 1000;
+	} else {
+		codec->frame_duration_num = DEFAULT_RTP_AUDIO_FRAME_DUR_NUM;
+		codec->frame_duration_den = DEFAULT_RTP_AUDIO_FRAME_DUR_DEN;
+	}
+
+	if (payload_type < 0) {
+		payload_type = 96;
+		if (rate == 8000 && channels == 1) {
+			if (!strcmp(audio_codec, "GSM"))
+				payload_type = 3;
+			else if (!strcmp(audio_codec, "PCMA"))
+				payload_type = 8;
+			else if (!strcmp(audio_codec, "PCMU"))
+				payload_type = 0;
+			else if (!strcmp(audio_codec, "G729"))
+				payload_type = 18;
+		}
+
+		codec->payload_type = payload_type;
+	}
+
+	if (channels != 1)
+		LOGP(DLMGCP, LOGL_NOTICE,
+		     "Channels != 1 in SDP: '%s'\n", audio_name);
+
+	return 0;
+}
+
+void codecs_initialize(void *ctx, struct sdp_rtp_map *codecs, int used)
+{
+	int i;
+
+	for (i = 0; i < used; ++i) {
+		switch (codecs[i].payload_type) {
+		case 0:
+			codecs[i].codec_name = "PCMU";
+			codecs[i].rate = 8000;
+			codecs[i].channels = 1;
+			break;
+		case 3:
+			codecs[i].codec_name = "GSM";
+			codecs[i].rate = 8000;
+			codecs[i].channels = 1;
+			break;
+		case 8:
+			codecs[i].codec_name = "PCMA";
+			codecs[i].rate = 8000;
+			codecs[i].channels = 1;
+			break;
+		case 18:
+			codecs[i].codec_name = "G729";
+			codecs[i].rate = 8000;
+			codecs[i].channels = 1;
+			break;
+		}
+	}
+}
+
+void codecs_update(void *ctx, struct sdp_rtp_map *codecs, int used, int payload, char *audio_name)
+{
+	int i;
+
+	for (i = 0; i < used; ++i) {
+		char audio_codec[64];
+		int rate = -1;
+		int channels = -1;
+		if (codecs[i].payload_type != payload)
+			continue;
+		if (sscanf(audio_name, "%63[^/]/%d/%d",
+				audio_codec, &rate, &channels) < 1) {
+			LOGP(DLMGCP, LOGL_ERROR, "Failed to parse '%s'\n", audio_name);
+			continue;
+		}
+
+		codecs[i].map_line = talloc_strdup(ctx, audio_name);
+		codecs[i].codec_name = talloc_strdup(ctx, audio_codec);
+		codecs[i].rate = rate;
+		codecs[i].channels = channels;
+		return;
+	}
+
+	LOGP(DLMGCP, LOGL_ERROR, "Unconfigured PT(%d) with %s\n", payload, audio_name);
+}
+
+int is_codec_compatible(struct mgcp_endpoint *endp, struct sdp_rtp_map *codec)
+{
+	char *bts_codec;
+	char audio_codec[64];
+
+	if (!codec->codec_name)
+		return 0;
+
+	/*
+	 * GSM, GSM/8000 and GSM/8000/1 should all be compatible.. let's go
+	 * by name first.
+	 */
+	bts_codec = endp->tcfg->audio_name;
+	if (sscanf(bts_codec, "%63[^/]/%*d/%*d", audio_codec) < 1)
+		return 0;
+
+	return strcasecmp(audio_codec, codec->codec_name) == 0;
+}
+
+int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p)
+{
+	struct sdp_rtp_map codecs[10];
+	int codecs_used = 0;
+	char *line;
+	int maxptime = -1;
+	int i;
+	int codecs_assigned = 0;
+	void *tmp_ctx = talloc_new(NULL);
+
+	memset(&codecs, 0, sizeof(codecs));
+
+	for_each_line(line, p->save) {
+		switch (line[0]) {
+		case 'o':
+		case 's':
+		case 't':
+		case 'v':
+			/* skip these SDP attributes */
+			break;
+		case 'a': {
+			int payload;
+			int ptime, ptime2 = 0;
+			char audio_name[64];
+
+
+			if (sscanf(line, "a=rtpmap:%d %63s",
+				   &payload, audio_name) == 2) {
+				codecs_update(tmp_ctx, codecs, codecs_used, payload, audio_name);
+			} else if (sscanf(line, "a=ptime:%d-%d",
+					  &ptime, &ptime2) >= 1) {
+				if (ptime2 > 0 && ptime2 != ptime)
+					rtp->packet_duration_ms = 0;
+				else
+					rtp->packet_duration_ms = ptime;
+			} else if (sscanf(line, "a=maxptime:%d", &ptime2) == 1) {
+				maxptime = ptime2;
+			}
+			break;
+		}
+		case 'm': {
+			int port, rc;
+
+			rc = sscanf(line, "m=audio %d RTP/AVP %d %d %d %d %d %d %d %d %d %d",
+					&port,
+					&codecs[0].payload_type,
+					&codecs[1].payload_type,
+					&codecs[2].payload_type,
+					&codecs[3].payload_type,
+					&codecs[4].payload_type,
+					&codecs[5].payload_type,
+					&codecs[6].payload_type,
+					&codecs[7].payload_type,
+					&codecs[8].payload_type,
+					&codecs[9].payload_type);
+			if (rc >= 2) {
+				rtp->rtp_port = htons(port);
+				rtp->rtcp_port = htons(port + 1);
+				codecs_used = rc - 1;
+				codecs_initialize(tmp_ctx, codecs, codecs_used);
+			}
+			break;
+		}
+		case 'c': {
+			char ipv4[16];
+
+			if (sscanf(line, "c=IN IP4 %15s", ipv4) == 1) {
+				inet_aton(ipv4, &rtp->addr);
+			}
+			break;
+		}
+		default:
+			if (p->endp)
+				LOGP(DLMGCP, LOGL_NOTICE,
+				     "Unhandled SDP option: '%c'/%d on 0x%x\n",
+				     line[0], line[0], ENDPOINT_NUMBER(p->endp));
+			else
+				LOGP(DLMGCP, LOGL_NOTICE,
+				     "Unhandled SDP option: '%c'/%d\n",
+				     line[0], line[0]);
+			break;
+		}
+	}
+
+	/* Now select the primary and alt_codec */
+	for (i = 0; i < codecs_used && codecs_assigned < 2; ++i) {
+		struct mgcp_rtp_codec *codec = codecs_assigned == 0 ?
+					&rtp->codec : &rtp->alt_codec;
+
+		if (endp->tcfg->no_audio_transcoding &&
+			!is_codec_compatible(endp, &codecs[i])) {
+			LOGP(DLMGCP, LOGL_NOTICE, "Skipping codec %s\n",
+				codecs[i].codec_name);
+			continue;
+		}
+
+		mgcp_set_audio_info(p->cfg, codec,
+					codecs[i].payload_type,
+					codecs[i].map_line);
+		codecs_assigned += 1;
+	}
+
+	if (codecs_assigned > 0) {
+		/* TODO/XXX: Store this per codec and derive it on use */
+		if (maxptime >= 0 && maxptime * rtp->codec.frame_duration_den >
+				rtp->codec.frame_duration_num * 1500) {
+			/* more than 1 frame */
+			rtp->packet_duration_ms = 0;
+		}
+
+		LOGP(DLMGCP, LOGL_NOTICE,
+		     "Got media info via SDP: port %d, payload %d (%s), "
+		     "duration %d, addr %s\n",
+		     ntohs(rtp->rtp_port), rtp->codec.payload_type,
+		     rtp->codec.subtype_name ? rtp->codec.subtype_name : "unknown",
+		     rtp->packet_duration_ms, inet_ntoa(rtp->addr));
+	}
+
+	talloc_free(tmp_ctx);
+	return codecs_assigned > 0;
+}
+
diff --git a/src/libosmo-legacy-mgcp/mgcp_transcode.c b/src/libosmo-legacy-mgcp/mgcp_transcode.c
new file mode 100644
index 0000000..cbabdd1
--- /dev/null
+++ b/src/libosmo-legacy-mgcp/mgcp_transcode.c
@@ -0,0 +1,611 @@
+/*
+ * (C) 2014 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/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+
+#include "g711common.h"
+
+#include <osmocom/legacy_mgcp/mgcp.h>
+#include <osmocom/legacy_mgcp/mgcp_internal.h>
+#include <osmocom/legacy_mgcp/mgcp_transcode.h>
+
+#include <osmocom/core/talloc.h>
+#include <osmocom/netif/rtp.h>
+
+int mgcp_transcoding_get_frame_size(void *state_, int nsamples, int dst)
+{
+	struct mgcp_process_rtp_state *state = state_;
+	if (dst)
+		return (nsamples >= 0 ?
+			nsamples / state->dst_samples_per_frame :
+			1) * state->dst_frame_size;
+	else
+		return (nsamples >= 0 ?
+			nsamples / state->src_samples_per_frame :
+			1) * state->src_frame_size;
+}
+
+static enum audio_format get_audio_format(const struct mgcp_rtp_codec *codec)
+{
+	if (codec->subtype_name) {
+		if (!strcasecmp("GSM", codec->subtype_name))
+			return AF_GSM;
+		if (!strcasecmp("PCMA", codec->subtype_name))
+			return AF_PCMA;
+		if (!strcasecmp("PCMU", codec->subtype_name))
+			return AF_PCMU;
+#ifdef HAVE_BCG729
+		if (!strcasecmp("G729", codec->subtype_name))
+			return AF_G729;
+#endif
+		if (!strcasecmp("L16", codec->subtype_name))
+			return AF_L16;
+	}
+
+	switch (codec->payload_type) {
+	case 0 /* PCMU */:
+		return AF_PCMU;
+	case 3 /* GSM */:
+		return AF_GSM;
+	case 8 /* PCMA */:
+		return AF_PCMA;
+#ifdef HAVE_BCG729
+	case 18 /* G.729 */:
+		return AF_G729;
+#endif
+	case 11 /* L16 */:
+		return AF_L16;
+	default:
+		return AF_INVALID;
+	}
+}
+
+static void l16_encode(short *sample, unsigned char *buf, size_t n)
+{
+	for (; n > 0; --n, ++sample, buf += 2) {
+		buf[0] = sample[0] >> 8;
+		buf[1] = sample[0] & 0xff;
+	}
+}
+
+static void l16_decode(unsigned char *buf, short *sample, size_t n)
+{
+	for (; n > 0; --n, ++sample, buf += 2)
+		sample[0] = ((short)buf[0] << 8) | buf[1];
+}
+
+static void alaw_encode(short *sample, unsigned char *buf, size_t n)
+{
+	for (; n > 0; --n)
+		*(buf++) = s16_to_alaw(*(sample++));
+}
+
+static void alaw_decode(unsigned char *buf, short *sample, size_t n)
+{
+	for (; n > 0; --n)
+		*(sample++) = alaw_to_s16(*(buf++));
+}
+
+static void ulaw_encode(short *sample, unsigned char *buf, size_t n)
+{
+	for (; n > 0; --n)
+		*(buf++) = s16_to_ulaw(*(sample++));
+}
+
+static void ulaw_decode(unsigned char *buf, short *sample, size_t n)
+{
+	for (; n > 0; --n)
+		*(sample++) = ulaw_to_s16(*(buf++));
+}
+
+static int processing_state_destructor(struct mgcp_process_rtp_state *state)
+{
+	switch (state->src_fmt) {
+	case AF_GSM:
+		if (state->src.gsm_handle)
+			gsm_destroy(state->src.gsm_handle);
+		break;
+#ifdef HAVE_BCG729
+	case AF_G729:
+		if (state->src.g729_dec)
+			closeBcg729DecoderChannel(state->src.g729_dec);
+		break;
+#endif
+	default:
+		break;
+	}
+	switch (state->dst_fmt) {
+	case AF_GSM:
+		if (state->dst.gsm_handle)
+			gsm_destroy(state->dst.gsm_handle);
+		break;
+#ifdef HAVE_BCG729
+	case AF_G729:
+		if (state->dst.g729_enc)
+			closeBcg729EncoderChannel(state->dst.g729_enc);
+		break;
+#endif
+	default:
+		break;
+	}
+	return 0;
+}
+
+int mgcp_transcoding_setup(struct mgcp_endpoint *endp,
+			   struct mgcp_rtp_end *dst_end,
+			   struct mgcp_rtp_end *src_end)
+{
+	struct mgcp_process_rtp_state *state;
+	enum audio_format src_fmt, dst_fmt;
+	const struct mgcp_rtp_codec *dst_codec = &dst_end->codec;
+
+	/* cleanup first */
+	if (dst_end->rtp_process_data) {
+		talloc_free(dst_end->rtp_process_data);
+		dst_end->rtp_process_data = NULL;
+	}
+
+	if (!src_end)
+		return 0;
+
+	const struct mgcp_rtp_codec *src_codec = &src_end->codec;
+
+	if (endp->tcfg->no_audio_transcoding) {
+		LOGP(DLMGCP, LOGL_NOTICE,
+			"Transcoding disabled on endpoint 0x%x\n",
+			ENDPOINT_NUMBER(endp));
+		return 0;
+	}
+
+	src_fmt = get_audio_format(src_codec);
+	dst_fmt = get_audio_format(dst_codec);
+
+	LOGP(DLMGCP, LOGL_ERROR,
+	     "Checking transcoding: %s (%d) -> %s (%d)\n",
+	     src_codec->subtype_name, src_codec->payload_type,
+	     dst_codec->subtype_name, dst_codec->payload_type);
+
+	if (src_fmt == AF_INVALID || dst_fmt == AF_INVALID) {
+		if (!src_codec->subtype_name || !dst_codec->subtype_name)
+			/* Not enough info, do nothing */
+			return 0;
+
+		if (strcasecmp(src_codec->subtype_name, dst_codec->subtype_name) == 0)
+			/* Nothing to do */
+			return 0;
+
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "Cannot transcode: %s codec not supported (%s -> %s).\n",
+		     src_fmt != AF_INVALID ? "destination" : "source",
+		     src_codec->audio_name, dst_codec->audio_name);
+		return -EINVAL;
+	}
+
+	if (src_codec->rate && dst_codec->rate && src_codec->rate != dst_codec->rate) {
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "Cannot transcode: rate conversion (%d -> %d) not supported.\n",
+		     src_codec->rate, dst_codec->rate);
+		return -EINVAL;
+	}
+
+	state = talloc_zero(endp->tcfg->cfg, struct mgcp_process_rtp_state);
+	talloc_set_destructor(state, processing_state_destructor);
+	dst_end->rtp_process_data = state;
+
+	state->src_fmt = src_fmt;
+
+	switch (state->src_fmt) {
+	case AF_L16:
+	case AF_S16:
+		state->src_frame_size = 80 * sizeof(short);
+		state->src_samples_per_frame = 80;
+		break;
+	case AF_GSM:
+		state->src_frame_size = sizeof(gsm_frame);
+		state->src_samples_per_frame = 160;
+		state->src.gsm_handle = gsm_create();
+		if (!state->src.gsm_handle) {
+			LOGP(DLMGCP, LOGL_ERROR,
+			     "Failed to initialize GSM decoder.\n");
+			return -EINVAL;
+		}
+		break;
+#ifdef HAVE_BCG729
+	case AF_G729:
+		state->src_frame_size = 10;
+		state->src_samples_per_frame = 80;
+		state->src.g729_dec = initBcg729DecoderChannel();
+		if (!state->src.g729_dec) {
+			LOGP(DLMGCP, LOGL_ERROR,
+			     "Failed to initialize G.729 decoder.\n");
+			return -EINVAL;
+		}
+		break;
+#endif
+	case AF_PCMU:
+	case AF_PCMA:
+		state->src_frame_size = 80;
+		state->src_samples_per_frame = 80;
+		break;
+	default:
+		break;
+	}
+
+	state->dst_fmt = dst_fmt;
+
+	switch (state->dst_fmt) {
+	case AF_L16:
+	case AF_S16:
+		state->dst_frame_size = 80*sizeof(short);
+		state->dst_samples_per_frame = 80;
+		break;
+	case AF_GSM:
+		state->dst_frame_size = sizeof(gsm_frame);
+		state->dst_samples_per_frame = 160;
+		state->dst.gsm_handle = gsm_create();
+		if (!state->dst.gsm_handle) {
+			LOGP(DLMGCP, LOGL_ERROR,
+			     "Failed to initialize GSM encoder.\n");
+			return -EINVAL;
+		}
+		break;
+#ifdef HAVE_BCG729
+	case AF_G729:
+		state->dst_frame_size = 10;
+		state->dst_samples_per_frame = 80;
+		state->dst.g729_enc = initBcg729EncoderChannel();
+		if (!state->dst.g729_enc) {
+			LOGP(DLMGCP, LOGL_ERROR,
+			     "Failed to initialize G.729 decoder.\n");
+			return -EINVAL;
+		}
+		break;
+#endif
+	case AF_PCMU:
+	case AF_PCMA:
+		state->dst_frame_size = 80;
+		state->dst_samples_per_frame = 80;
+		break;
+	default:
+		break;
+	}
+
+	if (dst_end->force_output_ptime)
+		state->dst_packet_duration = mgcp_rtp_packet_duration(endp, dst_end);
+
+	LOGP(DLMGCP, LOGL_INFO,
+	     "Initialized RTP processing on: 0x%x "
+	     "conv: %d (%d, %d, %s) -> %d (%d, %d, %s)\n",
+	     ENDPOINT_NUMBER(endp),
+	     src_fmt, src_codec->payload_type, src_codec->rate, src_end->fmtp_extra,
+	     dst_fmt, dst_codec->payload_type, dst_codec->rate, dst_end->fmtp_extra);
+
+	return 0;
+}
+
+void mgcp_transcoding_net_downlink_format(struct mgcp_endpoint *endp,
+					  int *payload_type,
+					  const char**audio_name,
+					  const char**fmtp_extra)
+{
+	struct mgcp_process_rtp_state *state = endp->net_end.rtp_process_data;
+	struct mgcp_rtp_codec *net_codec = &endp->net_end.codec;
+	struct mgcp_rtp_codec *bts_codec = &endp->bts_end.codec;
+
+	if (!state || net_codec->payload_type < 0) {
+		*payload_type = bts_codec->payload_type;
+		*audio_name = bts_codec->audio_name;
+		*fmtp_extra = endp->bts_end.fmtp_extra;
+		return;
+	}
+
+	*payload_type = net_codec->payload_type;
+	*audio_name = net_codec->audio_name;
+	*fmtp_extra = endp->net_end.fmtp_extra;
+}
+
+static int decode_audio(struct mgcp_process_rtp_state *state,
+			uint8_t **src, size_t *nbytes)
+{
+	while (*nbytes >= state->src_frame_size) {
+		if (state->sample_cnt + state->src_samples_per_frame > ARRAY_SIZE(state->samples)) {
+			LOGP(DLMGCP, LOGL_ERROR,
+			     "Sample buffer too small: %zu > %zu.\n",
+			     state->sample_cnt + state->src_samples_per_frame,
+			     ARRAY_SIZE(state->samples));
+			return -ENOSPC;
+		}
+		switch (state->src_fmt) {
+		case AF_GSM:
+			if (gsm_decode(state->src.gsm_handle,
+				       (gsm_byte *)*src, state->samples + state->sample_cnt) < 0) {
+				LOGP(DLMGCP, LOGL_ERROR,
+				     "Failed to decode GSM.\n");
+				return -EINVAL;
+			}
+			break;
+#ifdef HAVE_BCG729
+		case AF_G729:
+			bcg729Decoder(state->src.g729_dec, *src, 0, state->samples + state->sample_cnt);
+			break;
+#endif
+		case AF_PCMU:
+			ulaw_decode(*src, state->samples + state->sample_cnt,
+				    state->src_samples_per_frame);
+			break;
+		case AF_PCMA:
+			alaw_decode(*src, state->samples + state->sample_cnt,
+				    state->src_samples_per_frame);
+			break;
+		case AF_S16:
+			memmove(state->samples + state->sample_cnt, *src,
+				state->src_frame_size);
+			break;
+		case AF_L16:
+			l16_decode(*src, state->samples + state->sample_cnt,
+				   state->src_samples_per_frame);
+			break;
+		default:
+			break;
+		}
+		*src        += state->src_frame_size;
+		*nbytes     -= state->src_frame_size;
+		state->sample_cnt += state->src_samples_per_frame;
+	}
+	return 0;
+}
+
+static int encode_audio(struct mgcp_process_rtp_state *state,
+			uint8_t *dst, size_t buf_size, size_t max_samples)
+{
+	int nbytes = 0;
+	size_t nsamples = 0;
+	/* Encode samples into dst */
+	while (nsamples + state->dst_samples_per_frame <= max_samples) {
+		if (nbytes + state->dst_frame_size > buf_size) {
+			if (nbytes > 0)
+				break;
+
+			/* Not even one frame fits into the buffer */
+			LOGP(DLMGCP, LOGL_INFO,
+			     "Encoding (RTP) buffer too small: %zu > %zu.\n",
+			     nbytes + state->dst_frame_size, buf_size);
+			return -ENOSPC;
+		}
+		switch (state->dst_fmt) {
+		case AF_GSM:
+			gsm_encode(state->dst.gsm_handle,
+				   state->samples + state->sample_offs, dst);
+			break;
+#ifdef HAVE_BCG729
+		case AF_G729:
+			bcg729Encoder(state->dst.g729_enc,
+				      state->samples + state->sample_offs, dst);
+			break;
+#endif
+		case AF_PCMU:
+			ulaw_encode(state->samples + state->sample_offs, dst,
+				    state->src_samples_per_frame);
+			break;
+		case AF_PCMA:
+			alaw_encode(state->samples + state->sample_offs, dst,
+				    state->src_samples_per_frame);
+			break;
+		case AF_S16:
+			memmove(dst, state->samples + state->sample_offs,
+				state->dst_frame_size);
+			break;
+		case AF_L16:
+			l16_encode(state->samples + state->sample_offs, dst,
+				   state->src_samples_per_frame);
+			break;
+		default:
+			break;
+		}
+		dst        += state->dst_frame_size;
+		nbytes     += state->dst_frame_size;
+		state->sample_offs += state->dst_samples_per_frame;
+		nsamples   += state->dst_samples_per_frame;
+	}
+	state->sample_cnt -= nsamples;
+	return nbytes;
+}
+
+static struct mgcp_rtp_end *source_for_dest(struct mgcp_endpoint *endp,
+					struct mgcp_rtp_end *dst_end)
+{
+	if (&endp->bts_end == dst_end)
+		return &endp->net_end;
+	else if (&endp->net_end == dst_end)
+		return &endp->bts_end;
+	OSMO_ASSERT(0);
+}
+
+/*
+ * With some modems we get offered multiple codecs
+ * and we have selected one of them. It might not
+ * be the right one and we need to detect this with
+ * the first audio packets. One difficulty is that
+ * we patch the rtp payload type in place, so we
+ * need to discuss this.
+ */
+struct mgcp_process_rtp_state *check_transcode_state(
+				struct mgcp_endpoint *endp,
+				struct mgcp_rtp_end *dst_end,
+				struct rtp_hdr *rtp_hdr)
+{
+	struct mgcp_rtp_end *src_end;
+
+	/* Only deal with messages from net to bts */
+	if (&endp->bts_end != dst_end)
+		goto done;
+
+	src_end = source_for_dest(endp, dst_end);
+
+	/* Already patched */
+	if (rtp_hdr->payload_type == dst_end->codec.payload_type)
+		goto done;
+	/* The payload we expect */
+	if (rtp_hdr->payload_type == src_end->codec.payload_type)
+		goto done;
+	/* The matching alternate payload type? Then switch */
+	if (rtp_hdr->payload_type == src_end->alt_codec.payload_type) {
+		struct mgcp_config *cfg = endp->cfg;
+		struct mgcp_rtp_codec tmp_codec = src_end->alt_codec;
+		src_end->alt_codec = src_end->codec;
+		src_end->codec = tmp_codec;
+		cfg->setup_rtp_processing_cb(endp, &endp->net_end, &endp->bts_end);
+		cfg->setup_rtp_processing_cb(endp, &endp->bts_end, &endp->net_end);
+	}
+
+done:
+	return dst_end->rtp_process_data;
+}
+
+int mgcp_transcoding_process_rtp(struct mgcp_endpoint *endp,
+				struct mgcp_rtp_end *dst_end,
+			     char *data, int *len, int buf_size)
+{
+	struct mgcp_process_rtp_state *state;
+	const size_t rtp_hdr_size = sizeof(struct rtp_hdr);
+	struct rtp_hdr *rtp_hdr = (struct rtp_hdr *) data;
+	char *payload_data = (char *) &rtp_hdr->data[0];
+	int payload_len = *len - rtp_hdr_size;
+	uint8_t *src = (uint8_t *)payload_data;
+	uint8_t *dst = (uint8_t *)payload_data;
+	size_t nbytes = payload_len;
+	size_t nsamples;
+	size_t max_samples;
+	uint32_t ts_no;
+	int rc;
+
+	state = check_transcode_state(endp, dst_end, rtp_hdr);
+	if (!state)
+		return 0;
+
+	if (state->src_fmt == state->dst_fmt) {
+		if (!state->dst_packet_duration)
+			return 0;
+
+		/* TODO: repackage without transcoding */
+	}
+
+	/* If the remaining samples do not fit into a fixed ptime,
+	 * a) discard them, if the next packet is much later
+	 * b) add silence and * send it, if the current packet is not
+	 *    yet too late
+	 * c) append the sample data, if the timestamp matches exactly
+	 */
+
+	/* TODO: check payload type (-> G.711 comfort noise) */
+
+	if (payload_len > 0) {
+		ts_no = ntohl(rtp_hdr->timestamp);
+		if (!state->is_running) {
+			state->next_seq = ntohs(rtp_hdr->sequence);
+			state->next_time = ts_no;
+			state->is_running = 1;
+		}
+
+
+		if (state->sample_cnt > 0) {
+			int32_t delta = ts_no - state->next_time;
+			/* TODO: check sequence? reordering? packet loss? */
+
+			if (delta > state->sample_cnt) {
+				/* There is a time gap between the last packet
+				 * and the current one. Just discard the
+				 * partial data that is left in the buffer.
+				 * TODO: This can be improved by adding silence
+				 * instead if the delta is small enough.
+				 */
+				LOGP(DLMGCP, LOGL_NOTICE,
+					"0x%x dropping sample buffer due delta=%d sample_cnt=%zu\n",
+					ENDPOINT_NUMBER(endp), delta, state->sample_cnt);
+				state->sample_cnt = 0;
+				state->next_time = ts_no;
+			} else if (delta < 0) {
+				LOGP(DLMGCP, LOGL_NOTICE,
+				     "RTP time jumps backwards, delta = %d, "
+				     "discarding buffered samples\n",
+				     delta);
+				state->sample_cnt = 0;
+				state->sample_offs = 0;
+				return -EAGAIN;
+			}
+
+			/* Make sure the samples start without offset */
+			if (state->sample_offs && state->sample_cnt)
+				memmove(&state->samples[0],
+					&state->samples[state->sample_offs],
+					state->sample_cnt *
+					sizeof(state->samples[0]));
+		}
+
+		state->sample_offs = 0;
+
+		/* Append decoded audio to samples */
+		decode_audio(state, &src, &nbytes);
+
+		if (nbytes > 0)
+			LOGP(DLMGCP, LOGL_NOTICE,
+			     "Skipped audio frame in RTP packet: %zu octets\n",
+			     nbytes);
+	} else
+		ts_no = state->next_time;
+
+	if (state->sample_cnt < state->dst_packet_duration)
+		return -EAGAIN;
+
+	max_samples =
+		state->dst_packet_duration ?
+		state->dst_packet_duration : state->sample_cnt;
+
+	nsamples = state->sample_cnt;
+
+	rc = encode_audio(state, dst, buf_size, max_samples);
+	/*
+	 * There were no samples to encode?
+	 * TODO: how does this work for comfort noise?
+	 */
+	if (rc == 0)
+		return -ENOMSG;
+	/* Any other error during the encoding */
+	if (rc < 0)
+		return rc;
+
+	nsamples -= state->sample_cnt;
+
+	*len = rtp_hdr_size + rc;
+	rtp_hdr->sequence = htons(state->next_seq);
+	rtp_hdr->timestamp = htonl(ts_no);
+
+	state->next_seq += 1;
+	state->next_time = ts_no + nsamples;
+
+	/*
+	 * XXX: At this point we should always have consumed
+	 * samples. So doing OSMO_ASSERT(nsamples > 0) and returning
+	 * rtp_hdr_size should be fine.
+	 */
+	return nsamples ? rtp_hdr_size : 0;
+}
diff --git a/src/libosmo-legacy-mgcp/mgcp_vty.c b/src/libosmo-legacy-mgcp/mgcp_vty.c
new file mode 100644
index 0000000..a48e205
--- /dev/null
+++ b/src/libosmo-legacy-mgcp/mgcp_vty.c
@@ -0,0 +1,1555 @@
+/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
+/* The protocol implementation */
+
+/*
+ * (C) 2009-2014 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2011 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/>.
+ *
+ */
+
+
+#include <osmocom/core/talloc.h>
+
+#include <osmocom/legacy_mgcp/mgcp.h>
+#include <osmocom/legacy_mgcp/mgcp_internal.h>
+#include <osmocom/legacy_mgcp/vty.h>
+
+#include <string.h>
+
+#define RTCP_OMIT_STR "Drop RTCP packets in both directions\n"
+#define RTP_PATCH_STR "Modify RTP packet header in both directions\n"
+#define RTP_KEEPALIVE_STR "Send dummy UDP packet to net RTP destination\n"
+
+static struct mgcp_config *g_cfg = NULL;
+
+static struct mgcp_trunk_config *find_trunk(struct mgcp_config *cfg, int nr)
+{
+	struct mgcp_trunk_config *trunk;
+
+	if (nr == 0)
+		trunk = &cfg->trunk;
+	else
+		trunk = mgcp_trunk_num(cfg, nr);
+
+	return trunk;
+}
+
+/*
+ * vty code for mgcp below
+ */
+struct cmd_node mgcp_node = {
+	MGCP_NODE,
+	"%s(config-mgcp)# ",
+	1,
+};
+
+struct cmd_node trunk_node = {
+	TRUNK_NODE,
+	"%s(config-mgcp-trunk)# ",
+	1,
+};
+
+static int config_write_mgcp(struct vty *vty)
+{
+	vty_out(vty, "mgcp%s", VTY_NEWLINE);
+	if (g_cfg->local_ip)
+		vty_out(vty, "  local ip %s%s", g_cfg->local_ip, VTY_NEWLINE);
+	if (g_cfg->bts_ip && strlen(g_cfg->bts_ip) != 0)
+		vty_out(vty, "  bts ip %s%s", g_cfg->bts_ip, VTY_NEWLINE);
+	vty_out(vty, "  bind ip %s%s", g_cfg->source_addr, VTY_NEWLINE);
+	vty_out(vty, "  bind port %u%s", g_cfg->source_port, VTY_NEWLINE);
+
+	if (g_cfg->bts_ports.mode == PORT_ALLOC_STATIC)
+		vty_out(vty, "  rtp bts-base %u%s", g_cfg->bts_ports.base_port, VTY_NEWLINE);
+	else
+		vty_out(vty, "  rtp bts-range %u %u%s",
+			g_cfg->bts_ports.range_start, g_cfg->bts_ports.range_end, VTY_NEWLINE);
+	if (g_cfg->bts_ports.bind_addr)
+		vty_out(vty, "  rtp bts-bind-ip %s%s", g_cfg->bts_ports.bind_addr, VTY_NEWLINE);
+
+	if (g_cfg->net_ports.mode == PORT_ALLOC_STATIC)
+		vty_out(vty, "  rtp net-base %u%s", g_cfg->net_ports.base_port, VTY_NEWLINE);
+	else
+		vty_out(vty, "  rtp net-range %u %u%s",
+			g_cfg->net_ports.range_start, g_cfg->net_ports.range_end, VTY_NEWLINE);
+	if (g_cfg->net_ports.bind_addr)
+		vty_out(vty, "  rtp net-bind-ip %s%s", g_cfg->net_ports.bind_addr, VTY_NEWLINE);
+
+	vty_out(vty, "  rtp ip-dscp %d%s", g_cfg->endp_dscp, VTY_NEWLINE);
+	if (g_cfg->trunk.keepalive_interval == MGCP_KEEPALIVE_ONCE)
+		vty_out(vty, "  rtp keep-alive once%s", VTY_NEWLINE);
+	else if (g_cfg->trunk.keepalive_interval)
+		vty_out(vty, "  rtp keep-alive %d%s",
+			g_cfg->trunk.keepalive_interval, VTY_NEWLINE);
+	else
+		vty_out(vty, "  no rtp keep-alive%s", VTY_NEWLINE);
+
+	if (g_cfg->trunk.omit_rtcp)
+		vty_out(vty, "  rtcp-omit%s", VTY_NEWLINE);
+	else
+		vty_out(vty, "  no rtcp-omit%s", VTY_NEWLINE);
+	if (g_cfg->trunk.force_constant_ssrc || g_cfg->trunk.force_aligned_timing) {
+		vty_out(vty, "  %srtp-patch ssrc%s",
+			g_cfg->trunk.force_constant_ssrc ? "" : "no ", VTY_NEWLINE);
+		vty_out(vty, "  %srtp-patch timestamp%s",
+			g_cfg->trunk.force_aligned_timing ? "" : "no ", VTY_NEWLINE);
+	} else
+		vty_out(vty, "  no rtp-patch%s", VTY_NEWLINE);
+	if (g_cfg->trunk.audio_payload != -1)
+		vty_out(vty, "  sdp audio-payload number %d%s",
+			g_cfg->trunk.audio_payload, VTY_NEWLINE);
+	if (g_cfg->trunk.audio_name)
+		vty_out(vty, "  sdp audio-payload name %s%s",
+			g_cfg->trunk.audio_name, VTY_NEWLINE);
+	if (g_cfg->trunk.audio_fmtp_extra)
+		vty_out(vty, "  sdp audio fmtp-extra %s%s",
+			g_cfg->trunk.audio_fmtp_extra, VTY_NEWLINE);
+	vty_out(vty, "  %ssdp audio-payload send-ptime%s",
+		g_cfg->trunk.audio_send_ptime ? "" : "no ", VTY_NEWLINE);
+	vty_out(vty, "  %ssdp audio-payload send-name%s",
+		g_cfg->trunk.audio_send_name ? "" : "no ", VTY_NEWLINE);
+	vty_out(vty, "  loop %u%s", !!g_cfg->trunk.audio_loop, VTY_NEWLINE);
+	vty_out(vty, "  number endpoints %u%s", g_cfg->trunk.number_endpoints - 1, VTY_NEWLINE);
+	vty_out(vty, "  %sallow-transcoding%s",
+		g_cfg->trunk.no_audio_transcoding ? "no " : "", VTY_NEWLINE);
+	if (g_cfg->call_agent_addr)
+		vty_out(vty, "  call-agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE);
+	if (g_cfg->transcoder_ip)
+		vty_out(vty, "  transcoder-mgw %s%s", g_cfg->transcoder_ip, VTY_NEWLINE);
+
+	if (g_cfg->transcoder_ports.mode == PORT_ALLOC_STATIC)
+		vty_out(vty, "  rtp transcoder-base %u%s", g_cfg->transcoder_ports.base_port, VTY_NEWLINE);
+	else
+		vty_out(vty, "  rtp transcoder-range %u %u%s",
+			g_cfg->transcoder_ports.range_start, g_cfg->transcoder_ports.range_end, VTY_NEWLINE);
+	if (g_cfg->bts_force_ptime > 0)
+		vty_out(vty, "  rtp force-ptime %d%s", g_cfg->bts_force_ptime, VTY_NEWLINE);
+	vty_out(vty, "  transcoder-remote-base %u%s", g_cfg->transcoder_remote_base, VTY_NEWLINE);
+
+	switch (g_cfg->osmux) {
+	case OSMUX_USAGE_ON:
+		vty_out(vty, "  osmux on%s", VTY_NEWLINE);
+		break;
+	case OSMUX_USAGE_ONLY:
+		vty_out(vty, "  osmux only%s", VTY_NEWLINE);
+		break;
+	case OSMUX_USAGE_OFF:
+	default:
+		vty_out(vty, "  osmux off%s", VTY_NEWLINE);
+		break;
+	}
+	if (g_cfg->osmux) {
+		vty_out(vty, "  osmux bind-ip %s%s",
+			g_cfg->osmux_addr, VTY_NEWLINE);
+		vty_out(vty, "  osmux batch-factor %d%s",
+			g_cfg->osmux_batch, VTY_NEWLINE);
+		vty_out(vty, "  osmux batch-size %u%s",
+			g_cfg->osmux_batch_size, VTY_NEWLINE);
+		vty_out(vty, "  osmux port %u%s",
+			g_cfg->osmux_port, VTY_NEWLINE);
+		vty_out(vty, "  osmux dummy %s%s",
+			g_cfg->osmux_dummy ? "on" : "off", VTY_NEWLINE);
+	}
+	return CMD_SUCCESS;
+}
+
+static void dump_rtp_end(const char *end_name, struct vty *vty,
+			struct mgcp_rtp_state *state, struct mgcp_rtp_end *end)
+{
+	struct mgcp_rtp_codec *codec = &end->codec;
+
+	vty_out(vty,
+		"  %s%s"
+		"   Timestamp Errs: %d->%d%s"
+		"   Dropped Packets: %d%s"
+		"   Payload Type: %d Rate: %u Channels: %d %s"
+		"   Frame Duration: %u Frame Denominator: %u%s"
+		"   FPP: %d Packet Duration: %u%s"
+		"   FMTP-Extra: %s Audio-Name: %s Sub-Type: %s%s"
+		"   Output-Enabled: %d Force-PTIME: %d%s",
+		end_name, VTY_NEWLINE,
+		state->in_stream.err_ts_counter,
+		state->out_stream.err_ts_counter, VTY_NEWLINE,
+		end->dropped_packets, VTY_NEWLINE,
+		codec->payload_type, codec->rate, codec->channels, VTY_NEWLINE,
+		codec->frame_duration_num, codec->frame_duration_den, VTY_NEWLINE,
+		end->frames_per_packet, end->packet_duration_ms, VTY_NEWLINE,
+		end->fmtp_extra, codec->audio_name, codec->subtype_name, VTY_NEWLINE,
+		end->output_enabled, end->force_output_ptime, VTY_NEWLINE);
+}
+
+static void dump_trunk(struct vty *vty, struct mgcp_trunk_config *cfg, int verbose)
+{
+	int i;
+
+	vty_out(vty, "%s trunk nr %d with %d endpoints:%s",
+		cfg->trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1",
+		cfg->trunk_nr, cfg->number_endpoints - 1, VTY_NEWLINE);
+
+	if (!cfg->endpoints) {
+		vty_out(vty, "No endpoints allocated yet.%s", VTY_NEWLINE);
+		return;
+	}
+
+	for (i = 1; i < cfg->number_endpoints; ++i) {
+		struct mgcp_endpoint *endp = &cfg->endpoints[i];
+		vty_out(vty,
+			" Endpoint 0x%.2x: CI: %d net: %u/%u bts: %u/%u on %s "
+			"traffic received bts: %u  remote: %u transcoder: %u/%u%s",
+			i, endp->ci,
+			ntohs(endp->net_end.rtp_port), ntohs(endp->net_end.rtcp_port),
+			ntohs(endp->bts_end.rtp_port), ntohs(endp->bts_end.rtcp_port),
+			inet_ntoa(endp->bts_end.addr),
+			endp->bts_end.packets, endp->net_end.packets,
+			endp->trans_net.packets, endp->trans_bts.packets,
+			VTY_NEWLINE);
+
+		if (verbose && endp->allocated) {
+			dump_rtp_end("Net->BTS", vty, &endp->bts_state, &endp->bts_end);
+			dump_rtp_end("BTS->Net", vty, &endp->net_state, &endp->net_end);
+		}
+	}
+}
+
+DEFUN(show_mcgp, show_mgcp_cmd,
+      "show mgcp [stats]",
+      SHOW_STR
+      "Display information about the MGCP Media Gateway\n"
+      "Include Statistics\n")
+{
+	struct mgcp_trunk_config *trunk;
+	int show_stats = argc >= 1;
+
+	dump_trunk(vty, &g_cfg->trunk, show_stats);
+
+	llist_for_each_entry(trunk, &g_cfg->trunks, entry)
+		dump_trunk(vty, trunk, show_stats);
+
+	if (g_cfg->osmux)
+		vty_out(vty, "Osmux used CID: %d%s", osmux_used_cid(), VTY_NEWLINE);
+
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp,
+      cfg_mgcp_cmd,
+      "mgcp",
+      "Configure the MGCP")
+{
+	vty->node = MGCP_NODE;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_local_ip,
+      cfg_mgcp_local_ip_cmd,
+      "local ip A.B.C.D",
+      "Local options for the SDP record\n"
+      IP_STR
+      "IPv4 Address to use in SDP record\n")
+{
+	osmo_talloc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_bts_ip,
+      cfg_mgcp_bts_ip_cmd,
+      "bts ip A.B.C.D",
+      "BTS Audio source/destination options\n"
+      IP_STR
+      "IPv4 Address of the BTS\n")
+{
+	osmo_talloc_replace_string(g_cfg, &g_cfg->bts_ip, argv[0]);
+	inet_aton(g_cfg->bts_ip, &g_cfg->bts_in);
+	return CMD_SUCCESS;
+}
+
+#define BIND_STR "Listen/Bind related socket option\n"
+DEFUN(cfg_mgcp_bind_ip,
+      cfg_mgcp_bind_ip_cmd,
+      "bind ip A.B.C.D",
+      BIND_STR
+      IP_STR
+      "IPv4 Address to bind to\n")
+{
+	osmo_talloc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_bind_port,
+      cfg_mgcp_bind_port_cmd,
+      "bind port <0-65534>",
+      BIND_STR
+      "Port information\n"
+      "UDP port to listen for MGCP messages\n")
+{
+	unsigned int port = atoi(argv[0]);
+	g_cfg->source_port = port;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_bind_early,
+      cfg_mgcp_bind_early_cmd,
+      "bind early (0|1)",
+      BIND_STR
+      "Bind local ports on start up\n"
+      "Bind on demand\n" "Bind on startup\n")
+{
+	vty_out(vty, "bind early is deprecated, remove it from the config.\n");
+	return CMD_WARNING;
+}
+
+static void parse_base(struct mgcp_port_range *range, const char **argv)
+{
+	unsigned int port = atoi(argv[0]);
+	range->mode = PORT_ALLOC_STATIC;
+	range->base_port = port;
+}
+
+static void parse_range(struct mgcp_port_range *range, const char **argv)
+{
+	range->mode = PORT_ALLOC_DYNAMIC;
+	range->range_start = atoi(argv[0]);
+	range->range_end = atoi(argv[1]);
+	range->last_port = g_cfg->bts_ports.range_start;
+}
+
+
+#define RTP_STR "RTP configuration\n"
+#define BTS_START_STR "First UDP port allocated for the BTS side\n"
+#define NET_START_STR "First UDP port allocated for the NET side\n"
+#define UDP_PORT_STR "UDP Port number\n"
+DEFUN(cfg_mgcp_rtp_bts_base_port,
+      cfg_mgcp_rtp_bts_base_port_cmd,
+      "rtp bts-base <0-65534>",
+      RTP_STR
+      BTS_START_STR
+      UDP_PORT_STR)
+{
+	parse_base(&g_cfg->bts_ports, argv);
+	return CMD_SUCCESS;
+}
+
+#define RANGE_START_STR "Start of the range of ports\n"
+#define RANGE_END_STR "End of the range of ports\n"
+DEFUN(cfg_mgcp_rtp_bts_range,
+      cfg_mgcp_rtp_bts_range_cmd,
+      "rtp bts-range <0-65534> <0-65534>",
+      RTP_STR "Range of ports to use for the BTS side\n"
+      RANGE_START_STR RANGE_END_STR)
+{
+	parse_range(&g_cfg->bts_ports, argv);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_rtp_net_range,
+      cfg_mgcp_rtp_net_range_cmd,
+      "rtp net-range <0-65534> <0-65534>",
+      RTP_STR "Range of ports to use for the NET side\n"
+      RANGE_START_STR RANGE_END_STR)
+{
+	parse_range(&g_cfg->net_ports, argv);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_rtp_net_base_port,
+      cfg_mgcp_rtp_net_base_port_cmd,
+      "rtp net-base <0-65534>",
+      RTP_STR NET_START_STR UDP_PORT_STR)
+{
+	parse_base(&g_cfg->net_ports, argv);
+	return CMD_SUCCESS;
+}
+
+ALIAS_DEPRECATED(cfg_mgcp_rtp_bts_base_port, cfg_mgcp_rtp_base_port_cmd,
+      "rtp base <0-65534>",
+      RTP_STR BTS_START_STR UDP_PORT_STR)
+
+DEFUN(cfg_mgcp_rtp_transcoder_range,
+      cfg_mgcp_rtp_transcoder_range_cmd,
+      "rtp transcoder-range <0-65534> <0-65534>",
+      RTP_STR "Range of ports to use for the Transcoder\n"
+      RANGE_START_STR RANGE_END_STR)
+{
+	parse_range(&g_cfg->transcoder_ports, argv);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_rtp_transcoder_base,
+      cfg_mgcp_rtp_transcoder_base_cmd,
+      "rtp transcoder-base <0-65534>",
+      RTP_STR "First UDP port allocated for the Transcoder side\n"
+      UDP_PORT_STR)
+{
+	parse_base(&g_cfg->transcoder_ports, argv);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_rtp_bts_bind_ip,
+      cfg_mgcp_rtp_bts_bind_ip_cmd,
+      "rtp bts-bind-ip A.B.C.D",
+      RTP_STR "Bind endpoints facing the BTS\n" "Address to bind to\n")
+{
+	osmo_talloc_replace_string(g_cfg, &g_cfg->bts_ports.bind_addr, argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_rtp_no_bts_bind_ip,
+      cfg_mgcp_rtp_no_bts_bind_ip_cmd,
+      "no rtp bts-bind-ip",
+      NO_STR RTP_STR "Bind endpoints facing the BTS\n" "Address to bind to\n")
+{
+	talloc_free(g_cfg->bts_ports.bind_addr);
+	g_cfg->bts_ports.bind_addr = NULL;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_rtp_net_bind_ip,
+      cfg_mgcp_rtp_net_bind_ip_cmd,
+      "rtp net-bind-ip A.B.C.D",
+      RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
+{
+	osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr, argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_rtp_no_net_bind_ip,
+      cfg_mgcp_rtp_no_net_bind_ip_cmd,
+      "no rtp net-bind-ip",
+      NO_STR RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
+{
+	talloc_free(g_cfg->net_ports.bind_addr);
+	g_cfg->net_ports.bind_addr = NULL;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_rtp_ip_dscp,
+      cfg_mgcp_rtp_ip_dscp_cmd,
+      "rtp ip-dscp <0-255>",
+      RTP_STR
+      "Apply IP_TOS to the audio stream (including Osmux)\n" "The DSCP value\n")
+{
+	int dscp = atoi(argv[0]);
+	g_cfg->endp_dscp = dscp;
+	return CMD_SUCCESS;
+}
+
+ALIAS_DEPRECATED(cfg_mgcp_rtp_ip_dscp, cfg_mgcp_rtp_ip_tos_cmd,
+      "rtp ip-tos <0-255>",
+      RTP_STR
+      "Apply IP_TOS to the audio stream\n" "The DSCP value\n")
+
+#define FORCE_PTIME_STR "Force a fixed ptime for packets sent to the BTS"
+DEFUN(cfg_mgcp_rtp_force_ptime,
+      cfg_mgcp_rtp_force_ptime_cmd,
+      "rtp force-ptime (10|20|40)",
+      RTP_STR FORCE_PTIME_STR
+      "The required ptime (packet duration) in ms\n"
+      "10 ms\n20 ms\n40 ms\n")
+{
+	g_cfg->bts_force_ptime = atoi(argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_no_rtp_force_ptime,
+      cfg_mgcp_no_rtp_force_ptime_cmd,
+      "no rtp force-ptime",
+      NO_STR RTP_STR FORCE_PTIME_STR)
+{
+	g_cfg->bts_force_ptime = 0;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_sdp_fmtp_extra,
+      cfg_mgcp_sdp_fmtp_extra_cmd,
+      "sdp audio fmtp-extra .NAME",
+      "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
+      "Extra Information\n")
+{
+	char *txt = argv_concat(argv, argc, 0);
+	if (!txt)
+		return CMD_WARNING;
+
+	osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_fmtp_extra, txt);
+	talloc_free(txt);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_allow_transcoding,
+      cfg_mgcp_allow_transcoding_cmd,
+      "allow-transcoding",
+      "Allow transcoding\n")
+{
+	g_cfg->trunk.no_audio_transcoding = 0;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_no_allow_transcoding,
+      cfg_mgcp_no_allow_transcoding_cmd,
+      "no allow-transcoding",
+      NO_STR "Allow transcoding\n")
+{
+	g_cfg->trunk.no_audio_transcoding = 1;
+	return CMD_SUCCESS;
+}
+
+#define SDP_STR "SDP File related options\n"
+#define AUDIO_STR "Audio payload options\n"
+DEFUN(cfg_mgcp_sdp_payload_number,
+      cfg_mgcp_sdp_payload_number_cmd,
+      "sdp audio-payload number <0-255>",
+      SDP_STR AUDIO_STR
+      "Number\n" "Payload number\n")
+{
+	unsigned int payload = atoi(argv[0]);
+	g_cfg->trunk.audio_payload = payload;
+	return CMD_SUCCESS;
+}
+
+ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_number, cfg_mgcp_sdp_payload_number_cmd_old,
+      "sdp audio payload number <0-255>",
+      SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload number\n")
+      
+
+DEFUN(cfg_mgcp_sdp_payload_name,
+      cfg_mgcp_sdp_payload_name_cmd,
+      "sdp audio-payload name NAME",
+      SDP_STR AUDIO_STR "Name\n" "Payload name\n")
+{
+	osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_name, argv[0]);
+	return CMD_SUCCESS;
+}
+
+ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_name, cfg_mgcp_sdp_payload_name_cmd_old,
+      "sdp audio payload name NAME",
+      SDP_STR AUDIO_STR AUDIO_STR "Name\n" "Payload name\n")
+
+DEFUN(cfg_mgcp_sdp_payload_send_ptime,
+      cfg_mgcp_sdp_payload_send_ptime_cmd,
+      "sdp audio-payload send-ptime",
+      SDP_STR AUDIO_STR
+      "Send SDP ptime (packet duration) attribute\n")
+{
+	g_cfg->trunk.audio_send_ptime = 1;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_no_sdp_payload_send_ptime,
+      cfg_mgcp_no_sdp_payload_send_ptime_cmd,
+      "no sdp audio-payload send-ptime",
+      NO_STR SDP_STR AUDIO_STR
+      "Send SDP ptime (packet duration) attribute\n")
+{
+	g_cfg->trunk.audio_send_ptime = 0;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_sdp_payload_send_name,
+      cfg_mgcp_sdp_payload_send_name_cmd,
+      "sdp audio-payload send-name",
+      SDP_STR AUDIO_STR
+      "Send SDP rtpmap with the audio name\n")
+{
+	g_cfg->trunk.audio_send_name = 1;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_no_sdp_payload_send_name,
+      cfg_mgcp_no_sdp_payload_send_name_cmd,
+      "no sdp audio-payload send-name",
+      NO_STR SDP_STR AUDIO_STR
+      "Send SDP rtpmap with the audio name\n")
+{
+	g_cfg->trunk.audio_send_name = 0;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_loop,
+      cfg_mgcp_loop_cmd,
+      "loop (0|1)",
+      "Loop audio for all endpoints on main trunk\n"
+      "Don't Loop\n" "Loop\n")
+{
+	if (g_cfg->osmux) {
+		vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	g_cfg->trunk.audio_loop = atoi(argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_force_realloc,
+      cfg_mgcp_force_realloc_cmd,
+      "force-realloc (0|1)",
+      "Force endpoint reallocation when the endpoint is still seized\n"
+      "Don't force reallocation\n" "force reallocation\n")
+{
+	g_cfg->trunk.force_realloc = atoi(argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_number_endp,
+      cfg_mgcp_number_endp_cmd,
+      "number endpoints <0-65534>",
+      "Number options\n" "Endpoints available\n" "Number endpoints\n")
+{
+	/* + 1 as we start counting at one */
+	g_cfg->trunk.number_endpoints = atoi(argv[0]) + 1;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_omit_rtcp,
+      cfg_mgcp_omit_rtcp_cmd,
+      "rtcp-omit",
+      RTCP_OMIT_STR)
+{
+	g_cfg->trunk.omit_rtcp = 1;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_no_omit_rtcp,
+      cfg_mgcp_no_omit_rtcp_cmd,
+      "no rtcp-omit",
+      NO_STR RTCP_OMIT_STR)
+{
+	g_cfg->trunk.omit_rtcp = 0;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_patch_rtp_ssrc,
+      cfg_mgcp_patch_rtp_ssrc_cmd,
+      "rtp-patch ssrc",
+      RTP_PATCH_STR
+      "Force a fixed SSRC\n"
+      )
+{
+	g_cfg->trunk.force_constant_ssrc = 1;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_no_patch_rtp_ssrc,
+      cfg_mgcp_no_patch_rtp_ssrc_cmd,
+      "no rtp-patch ssrc",
+      NO_STR RTP_PATCH_STR
+      "Force a fixed SSRC\n"
+      )
+{
+	g_cfg->trunk.force_constant_ssrc = 0;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_patch_rtp_ts,
+      cfg_mgcp_patch_rtp_ts_cmd,
+      "rtp-patch timestamp",
+      RTP_PATCH_STR
+      "Adjust RTP timestamp\n"
+      )
+{
+	g_cfg->trunk.force_aligned_timing = 1;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_no_patch_rtp_ts,
+      cfg_mgcp_no_patch_rtp_ts_cmd,
+      "no rtp-patch timestamp",
+      NO_STR RTP_PATCH_STR
+      "Adjust RTP timestamp\n"
+      )
+{
+	g_cfg->trunk.force_aligned_timing = 0;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_no_patch_rtp,
+      cfg_mgcp_no_patch_rtp_cmd,
+      "no rtp-patch",
+      NO_STR RTP_PATCH_STR)
+{
+	g_cfg->trunk.force_constant_ssrc = 0;
+	g_cfg->trunk.force_aligned_timing = 0;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_rtp_keepalive,
+      cfg_mgcp_rtp_keepalive_cmd,
+      "rtp keep-alive <1-120>",
+      RTP_STR RTP_KEEPALIVE_STR
+      "Keep alive interval in secs\n"
+      )
+{
+	mgcp_trunk_set_keepalive(&g_cfg->trunk, atoi(argv[0]));
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_rtp_keepalive_once,
+      cfg_mgcp_rtp_keepalive_once_cmd,
+      "rtp keep-alive once",
+      RTP_STR RTP_KEEPALIVE_STR
+      "Send dummy packet only once after CRCX/MDCX\n"
+      )
+{
+	mgcp_trunk_set_keepalive(&g_cfg->trunk, MGCP_KEEPALIVE_ONCE);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_no_rtp_keepalive,
+      cfg_mgcp_no_rtp_keepalive_cmd,
+      "no rtp keep-alive",
+      NO_STR RTP_STR RTP_KEEPALIVE_STR
+      )
+{
+	mgcp_trunk_set_keepalive(&g_cfg->trunk, 0);
+	return CMD_SUCCESS;
+}
+
+
+
+#define CALL_AGENT_STR "Callagent information\n"
+DEFUN(cfg_mgcp_agent_addr,
+      cfg_mgcp_agent_addr_cmd,
+      "call-agent ip A.B.C.D",
+      CALL_AGENT_STR IP_STR
+      "IPv4 Address of the callagent\n")
+{
+	osmo_talloc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
+	return CMD_SUCCESS;
+}
+
+ALIAS_DEPRECATED(cfg_mgcp_agent_addr, cfg_mgcp_agent_addr_cmd_old,
+      "call agent ip A.B.C.D",
+      CALL_AGENT_STR CALL_AGENT_STR IP_STR
+      "IPv4 Address of the callagent\n")
+      
+
+DEFUN(cfg_mgcp_transcoder,
+      cfg_mgcp_transcoder_cmd,
+      "transcoder-mgw A.B.C.D",
+      "Use a MGW to detranscoder RTP\n"
+      "The IP address of the MGW")
+{
+	osmo_talloc_replace_string(g_cfg, &g_cfg->transcoder_ip, argv[0]);
+	inet_aton(g_cfg->transcoder_ip, &g_cfg->transcoder_in);
+
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_no_transcoder,
+      cfg_mgcp_no_transcoder_cmd,
+      "no transcoder-mgw",
+      NO_STR "Disable the transcoding\n")
+{
+	if (g_cfg->transcoder_ip) {
+		LOGP(DLMGCP, LOGL_NOTICE, "Disabling transcoding on future calls.\n");
+		talloc_free(g_cfg->transcoder_ip);
+		g_cfg->transcoder_ip = NULL;
+	}
+
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_transcoder_remote_base,
+      cfg_mgcp_transcoder_remote_base_cmd,
+      "transcoder-remote-base <0-65534>",
+      "Set the base port for the transcoder\n" "The RTP base port on the transcoder")
+{
+	g_cfg->transcoder_remote_base = atoi(argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd,
+      "trunk <1-64>",
+      "Configure a SS7 trunk\n" "Trunk Nr\n")
+{
+	struct mgcp_trunk_config *trunk;
+	int index = atoi(argv[0]);
+
+	trunk = mgcp_trunk_num(g_cfg, index);
+	if (!trunk)
+		trunk = mgcp_trunk_alloc(g_cfg, index);
+
+	if (!trunk) {
+		vty_out(vty, "%%Unable to allocate trunk %u.%s",
+			index, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	vty->node = TRUNK_NODE;
+	vty->index = trunk;
+	return CMD_SUCCESS;
+}
+
+static int config_write_trunk(struct vty *vty)
+{
+	struct mgcp_trunk_config *trunk;
+
+	llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
+		vty_out(vty, " trunk %d%s", trunk->trunk_nr, VTY_NEWLINE);
+		vty_out(vty, "  sdp audio-payload number %d%s",
+			trunk->audio_payload, VTY_NEWLINE);
+		vty_out(vty, "  sdp audio-payload name %s%s",
+			trunk->audio_name, VTY_NEWLINE);
+		vty_out(vty, "  %ssdp audio-payload send-ptime%s",
+			trunk->audio_send_ptime ? "" : "no ", VTY_NEWLINE);
+		vty_out(vty, "  %ssdp audio-payload send-name%s",
+			trunk->audio_send_name ? "" : "no ", VTY_NEWLINE);
+
+		if (trunk->keepalive_interval == MGCP_KEEPALIVE_ONCE)
+			vty_out(vty, "  rtp keep-alive once%s", VTY_NEWLINE);
+		else if (trunk->keepalive_interval)
+			vty_out(vty, "  rtp keep-alive %d%s",
+				trunk->keepalive_interval, VTY_NEWLINE);
+		else
+			vty_out(vty, "  no rtp keep-alive%s", VTY_NEWLINE);
+		vty_out(vty, "  loop %d%s",
+			trunk->audio_loop, VTY_NEWLINE);
+		vty_out(vty, "  force-realloc %d%s",
+			trunk->force_realloc, VTY_NEWLINE);
+		if (trunk->omit_rtcp)
+			vty_out(vty, "  rtcp-omit%s", VTY_NEWLINE);
+		else
+			vty_out(vty, "  no rtcp-omit%s", VTY_NEWLINE);
+		if (trunk->force_constant_ssrc || trunk->force_aligned_timing) {
+			vty_out(vty, "  %srtp-patch ssrc%s",
+				trunk->force_constant_ssrc ? "" : "no ", VTY_NEWLINE);
+			vty_out(vty, "  %srtp-patch timestamp%s",
+				trunk->force_aligned_timing ? "" : "no ", VTY_NEWLINE);
+		} else
+			vty_out(vty, "  no rtp-patch%s", VTY_NEWLINE);
+		if (trunk->audio_fmtp_extra)
+			vty_out(vty, "   sdp audio fmtp-extra %s%s",
+				trunk->audio_fmtp_extra, VTY_NEWLINE);
+		vty_out(vty, "  %sallow-transcoding%s",
+			trunk->no_audio_transcoding ? "no " : "", VTY_NEWLINE);
+	}
+
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_sdp_fmtp_extra,
+      cfg_trunk_sdp_fmtp_extra_cmd,
+      "sdp audio fmtp-extra .NAME",
+      "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
+      "Extra Information\n")
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	char *txt = argv_concat(argv, argc, 0);
+	if (!txt)
+		return CMD_WARNING;
+
+	osmo_talloc_replace_string(g_cfg, &trunk->audio_fmtp_extra, txt);
+	talloc_free(txt);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_payload_number,
+      cfg_trunk_payload_number_cmd,
+      "sdp audio-payload number <0-255>",
+      SDP_STR AUDIO_STR "Number\n" "Payload Number\n")
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	unsigned int payload = atoi(argv[0]);
+
+	trunk->audio_payload = payload;
+	return CMD_SUCCESS;
+}
+
+ALIAS_DEPRECATED(cfg_trunk_payload_number, cfg_trunk_payload_number_cmd_old,
+      "sdp audio payload number <0-255>",
+      SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload Number\n")
+
+DEFUN(cfg_trunk_payload_name,
+      cfg_trunk_payload_name_cmd,
+      "sdp audio-payload name NAME",
+       SDP_STR AUDIO_STR "Payload\n" "Payload Name\n")
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+
+	osmo_talloc_replace_string(g_cfg, &trunk->audio_name, argv[0]);
+	return CMD_SUCCESS;
+}
+
+ALIAS_DEPRECATED(cfg_trunk_payload_name, cfg_trunk_payload_name_cmd_old,
+      "sdp audio payload name NAME",
+       SDP_STR AUDIO_STR AUDIO_STR "Payload\n" "Payload Name\n")
+
+
+DEFUN(cfg_trunk_loop,
+      cfg_trunk_loop_cmd,
+      "loop (0|1)",
+      "Loop audio for all endpoints on this trunk\n"
+      "Don't Loop\n" "Loop\n")
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+
+	if (g_cfg->osmux) {
+		vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	trunk->audio_loop = atoi(argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_sdp_payload_send_ptime,
+      cfg_trunk_sdp_payload_send_ptime_cmd,
+      "sdp audio-payload send-ptime",
+      SDP_STR AUDIO_STR
+      "Send SDP ptime (packet duration) attribute\n")
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	trunk->audio_send_ptime = 1;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_no_sdp_payload_send_ptime,
+      cfg_trunk_no_sdp_payload_send_ptime_cmd,
+      "no sdp audio-payload send-ptime",
+      NO_STR SDP_STR AUDIO_STR
+      "Send SDP ptime (packet duration) attribute\n")
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	trunk->audio_send_ptime = 0;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_sdp_payload_send_name,
+      cfg_trunk_sdp_payload_send_name_cmd,
+      "sdp audio-payload send-name",
+      SDP_STR AUDIO_STR
+      "Send SDP rtpmap with the audio name\n")
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	trunk->audio_send_name = 1;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_no_sdp_payload_send_name,
+      cfg_trunk_no_sdp_payload_send_name_cmd,
+      "no sdp audio-payload send-name",
+      NO_STR SDP_STR AUDIO_STR
+      "Send SDP rtpmap with the audio name\n")
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	trunk->audio_send_name = 0;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_omit_rtcp,
+      cfg_trunk_omit_rtcp_cmd,
+      "rtcp-omit",
+      RTCP_OMIT_STR)
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	trunk->omit_rtcp = 1;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_no_omit_rtcp,
+      cfg_trunk_no_omit_rtcp_cmd,
+      "no rtcp-omit",
+      NO_STR RTCP_OMIT_STR)
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	trunk->omit_rtcp = 0;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_patch_rtp_ssrc,
+      cfg_trunk_patch_rtp_ssrc_cmd,
+      "rtp-patch ssrc",
+      RTP_PATCH_STR
+      "Force a fixed SSRC\n"
+      )
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	trunk->force_constant_ssrc = 1;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_no_patch_rtp_ssrc,
+      cfg_trunk_no_patch_rtp_ssrc_cmd,
+      "no rtp-patch ssrc",
+      NO_STR RTP_PATCH_STR
+      "Force a fixed SSRC\n"
+      )
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	trunk->force_constant_ssrc = 0;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_patch_rtp_ts,
+      cfg_trunk_patch_rtp_ts_cmd,
+      "rtp-patch timestamp",
+      RTP_PATCH_STR
+      "Adjust RTP timestamp\n"
+      )
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	trunk->force_aligned_timing = 1;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_no_patch_rtp_ts,
+      cfg_trunk_no_patch_rtp_ts_cmd,
+      "no rtp-patch timestamp",
+      NO_STR RTP_PATCH_STR
+      "Adjust RTP timestamp\n"
+      )
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	trunk->force_aligned_timing = 0;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_no_patch_rtp,
+      cfg_trunk_no_patch_rtp_cmd,
+      "no rtp-patch",
+      NO_STR RTP_PATCH_STR)
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	trunk->force_constant_ssrc = 0;
+	trunk->force_aligned_timing = 0;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_rtp_keepalive,
+      cfg_trunk_rtp_keepalive_cmd,
+      "rtp keep-alive <1-120>",
+      RTP_STR RTP_KEEPALIVE_STR
+      "Keep-alive interval in secs\n"
+      )
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	mgcp_trunk_set_keepalive(trunk, atoi(argv[0]));
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_rtp_keepalive_once,
+      cfg_trunk_rtp_keepalive_once_cmd,
+      "rtp keep-alive once",
+      RTP_STR RTP_KEEPALIVE_STR
+      "Send dummy packet only once after CRCX/MDCX\n"
+      )
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_no_rtp_keepalive,
+      cfg_trunk_no_rtp_keepalive_cmd,
+      "no rtp keep-alive",
+      NO_STR RTP_STR RTP_KEEPALIVE_STR
+      )
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	mgcp_trunk_set_keepalive(trunk, 0);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_allow_transcoding,
+      cfg_trunk_allow_transcoding_cmd,
+      "allow-transcoding",
+      "Allow transcoding\n")
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	trunk->no_audio_transcoding = 0;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_no_allow_transcoding,
+      cfg_trunk_no_allow_transcoding_cmd,
+      "no allow-transcoding",
+      NO_STR "Allow transcoding\n")
+{
+	struct mgcp_trunk_config *trunk = vty->index;
+	trunk->no_audio_transcoding = 1;
+	return CMD_SUCCESS;
+}
+
+DEFUN(loop_endp,
+      loop_endp_cmd,
+      "loop-endpoint <0-64> NAME (0|1)",
+      "Loop a given endpoint\n" "Trunk number\n"
+      "The name in hex of the endpoint\n" "Disable the loop\n" "Enable the loop\n")
+{
+	struct mgcp_trunk_config *trunk;
+	struct mgcp_endpoint *endp;
+
+	trunk = find_trunk(g_cfg, atoi(argv[0]));
+	if (!trunk) {
+		vty_out(vty, "%%Trunk %d not found in the config.%s",
+			atoi(argv[0]), VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	if (!trunk->endpoints) {
+		vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
+			trunk->trunk_nr, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	int endp_no = strtoul(argv[1], NULL, 16);
+	if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
+		vty_out(vty, "Loopback number %s/%d is invalid.%s",
+		argv[1], endp_no, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+
+	endp = &trunk->endpoints[endp_no];
+	int loop = atoi(argv[2]);
+
+	if (loop)
+		endp->conn_mode = MGCP_CONN_LOOPBACK;
+	else
+		endp->conn_mode = endp->orig_mode;
+
+	/* Handle it like a MDCX, switch on SSRC patching if enabled */
+	mgcp_rtp_end_config(endp, 1, &endp->bts_end);
+	mgcp_rtp_end_config(endp, 1, &endp->net_end);
+
+	return CMD_SUCCESS;
+}
+
+DEFUN(tap_call,
+      tap_call_cmd,
+      "tap-call <0-64> ENDPOINT (bts-in|bts-out|net-in|net-out) A.B.C.D <0-65534>",
+      "Forward data on endpoint to a different system\n" "Trunk number\n"
+      "The endpoint in hex\n"
+      "Forward the data coming from the bts\n"
+      "Forward the data coming from the bts leaving to the network\n"
+      "Forward the data coming from the net\n"
+      "Forward the data coming from the net leaving to the bts\n"
+      "destination IP of the data\n" "destination port\n")
+{
+	struct mgcp_rtp_tap *tap;
+	struct mgcp_trunk_config *trunk;
+	struct mgcp_endpoint *endp;
+	int port = 0;
+
+	trunk = find_trunk(g_cfg, atoi(argv[0]));
+	if (!trunk) {
+		vty_out(vty, "%%Trunk %d not found in the config.%s",
+			atoi(argv[0]), VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	if (!trunk->endpoints) {
+		vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
+			trunk->trunk_nr, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	int endp_no = strtoul(argv[1], NULL, 16);
+	if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
+		vty_out(vty, "Endpoint number %s/%d is invalid.%s",
+		argv[1], endp_no, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	endp = &trunk->endpoints[endp_no];
+
+	if (strcmp(argv[2], "bts-in") == 0) {
+		port = MGCP_TAP_BTS_IN;
+	} else if (strcmp(argv[2], "bts-out") == 0) {
+		port = MGCP_TAP_BTS_OUT;
+	} else if (strcmp(argv[2], "net-in") == 0) {
+		port = MGCP_TAP_NET_IN;
+	} else if (strcmp(argv[2], "net-out") == 0) {
+		port = MGCP_TAP_NET_OUT;
+	} else {
+		vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	tap = &endp->taps[port];
+	memset(&tap->forward, 0, sizeof(tap->forward));
+	inet_aton(argv[3], &tap->forward.sin_addr);
+	tap->forward.sin_port = htons(atoi(argv[4]));
+	tap->enabled = 1;
+	return CMD_SUCCESS;
+}
+
+DEFUN(free_endp, free_endp_cmd,
+      "free-endpoint <0-64> NUMBER",
+      "Free the given endpoint\n" "Trunk number\n"
+      "Endpoint number in hex.\n")
+{
+	struct mgcp_trunk_config *trunk;
+	struct mgcp_endpoint *endp;
+
+	trunk = find_trunk(g_cfg, atoi(argv[0]));
+	if (!trunk) {
+		vty_out(vty, "%%Trunk %d not found in the config.%s",
+			atoi(argv[0]), VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	if (!trunk->endpoints) {
+		vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
+			trunk->trunk_nr, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	int endp_no = strtoul(argv[1], NULL, 16);
+	if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
+		vty_out(vty, "Endpoint number %s/%d is invalid.%s",
+		argv[1], endp_no, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	endp = &trunk->endpoints[endp_no];
+	mgcp_release_endp(endp);
+	return CMD_SUCCESS;
+}
+
+DEFUN(reset_endp, reset_endp_cmd,
+      "reset-endpoint <0-64> NUMBER",
+      "Reset the given endpoint\n" "Trunk number\n"
+      "Endpoint number in hex.\n")
+{
+	struct mgcp_trunk_config *trunk;
+	struct mgcp_endpoint *endp;
+	int endp_no, rc;
+
+	trunk = find_trunk(g_cfg, atoi(argv[0]));
+	if (!trunk) {
+		vty_out(vty, "%%Trunk %d not found in the config.%s",
+			atoi(argv[0]), VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	if (!trunk->endpoints) {
+		vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
+			trunk->trunk_nr, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	endp_no = strtoul(argv[1], NULL, 16);
+	if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
+		vty_out(vty, "Endpoint number %s/%d is invalid.%s",
+		argv[1], endp_no, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	endp = &trunk->endpoints[endp_no];
+	rc = mgcp_send_reset_ep(endp, ENDPOINT_NUMBER(endp));
+	if (rc < 0) {
+		vty_out(vty, "Error %d sending reset.%s", rc, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	return CMD_SUCCESS;
+}
+
+DEFUN(reset_all_endp, reset_all_endp_cmd,
+      "reset-all-endpoints",
+      "Reset all endpoints\n")
+{
+	int rc;
+
+	rc = mgcp_send_reset_all(g_cfg);
+	if (rc < 0) {
+		vty_out(vty, "Error %d during endpoint reset.%s",
+			rc, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	return CMD_SUCCESS;
+}
+
+#define OSMUX_STR "RTP multiplexing\n"
+DEFUN(cfg_mgcp_osmux,
+      cfg_mgcp_osmux_cmd,
+      "osmux (on|off|only)",
+       OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
+{
+	if (strcmp(argv[0], "off") == 0) {
+		g_cfg->osmux = OSMUX_USAGE_OFF;
+		return CMD_SUCCESS;
+	}
+
+	if (strcmp(argv[0], "on") == 0)
+		g_cfg->osmux = OSMUX_USAGE_ON;
+	else if (strcmp(argv[0], "only") == 0)
+		g_cfg->osmux = OSMUX_USAGE_ONLY;
+
+	if (g_cfg->trunk.audio_loop) {
+		vty_out(vty, "Cannot use `loop' with `osmux'.%s",
+			VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_osmux_ip,
+      cfg_mgcp_osmux_ip_cmd,
+      "osmux bind-ip A.B.C.D",
+      OSMUX_STR IP_STR "IPv4 Address to bind to\n")
+{
+	osmo_talloc_replace_string(g_cfg, &g_cfg->osmux_addr, argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_osmux_batch_factor,
+      cfg_mgcp_osmux_batch_factor_cmd,
+      "osmux batch-factor <1-8>",
+      OSMUX_STR "Batching factor\n" "Number of messages in the batch\n")
+{
+	g_cfg->osmux_batch = atoi(argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_osmux_batch_size,
+      cfg_mgcp_osmux_batch_size_cmd,
+      "osmux batch-size <1-65535>",
+      OSMUX_STR "batch size\n" "Batch size in bytes\n")
+{
+	g_cfg->osmux_batch_size = atoi(argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_osmux_port,
+      cfg_mgcp_osmux_port_cmd,
+      "osmux port <1-65535>",
+      OSMUX_STR "port\n" "UDP port\n")
+{
+	g_cfg->osmux_port = atoi(argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_osmux_dummy,
+      cfg_mgcp_osmux_dummy_cmd,
+      "osmux dummy (on|off)",
+      OSMUX_STR "Dummy padding\n" "Enable dummy padding\n" "Disable dummy padding\n")
+{
+	if (strcmp(argv[0], "on") == 0)
+		g_cfg->osmux_dummy = 1;
+	else if (strcmp(argv[0], "off") == 0)
+		g_cfg->osmux_dummy = 0;
+
+	return CMD_SUCCESS;
+}
+
+int mgcp_vty_init(void)
+{
+	install_element_ve(&show_mgcp_cmd);
+	install_element(ENABLE_NODE, &loop_endp_cmd);
+	install_element(ENABLE_NODE, &tap_call_cmd);
+	install_element(ENABLE_NODE, &free_endp_cmd);
+	install_element(ENABLE_NODE, &reset_endp_cmd);
+	install_element(ENABLE_NODE, &reset_all_endp_cmd);
+
+	install_element(CONFIG_NODE, &cfg_mgcp_cmd);
+	install_node(&mgcp_node, config_write_mgcp);
+
+	vty_install_default(MGCP_NODE);
+	install_element(MGCP_NODE, &cfg_mgcp_local_ip_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_bts_ip_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_bind_ip_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_bind_port_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_bind_early_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_base_port_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_base_port_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_net_base_port_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_range_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_bind_ip_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_no_bts_bind_ip_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_net_range_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_transcoder_range_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_transcoder_base_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_tos_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_force_ptime_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_no_rtp_force_ptime_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_once_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_no_rtp_keepalive_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd_old);
+	install_element(MGCP_NODE, &cfg_mgcp_transcoder_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_no_transcoder_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_transcoder_remote_base_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd_old);
+	install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd_old);
+	install_element(MGCP_NODE, &cfg_mgcp_loop_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_force_realloc_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_omit_rtcp_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_no_omit_rtcp_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ssrc_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ssrc_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ts_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ts_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_sdp_fmtp_extra_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_ptime_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_ptime_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_name_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_name_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_osmux_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_osmux_ip_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_factor_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_size_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_osmux_port_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_osmux_dummy_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_allow_transcoding_cmd);
+	install_element(MGCP_NODE, &cfg_mgcp_no_allow_transcoding_cmd);
+
+
+	install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd);
+	install_node(&trunk_node, config_write_trunk);
+	vty_install_default(TRUNK_NODE);
+	install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_once_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_no_rtp_keepalive_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd_old);
+	install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd_old);
+	install_element(TRUNK_NODE, &cfg_trunk_loop_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_omit_rtcp_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_no_omit_rtcp_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ssrc_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ssrc_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ts_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ts_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_sdp_fmtp_extra_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_ptime_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_ptime_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_name_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_name_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_allow_transcoding_cmd);
+	install_element(TRUNK_NODE, &cfg_trunk_no_allow_transcoding_cmd);
+
+	return 0;
+}
+
+static int allocate_trunk(struct mgcp_trunk_config *trunk)
+{
+	int i;
+	struct mgcp_config *cfg = trunk->cfg;
+
+	if (mgcp_endpoints_allocate(trunk) != 0) {
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "Failed to allocate %d endpoints on trunk %d.\n",
+		     trunk->number_endpoints, trunk->trunk_nr);
+		return -1;
+	}
+
+	/* early bind */
+	for (i = 1; i < trunk->number_endpoints; ++i) {
+		struct mgcp_endpoint *endp = &trunk->endpoints[i];
+
+		if (cfg->bts_ports.mode == PORT_ALLOC_STATIC) {
+			cfg->last_bts_port += 2;
+			if (mgcp_bind_bts_rtp_port(endp, cfg->last_bts_port) != 0) {
+				LOGP(DLMGCP, LOGL_FATAL,
+				     "Failed to bind: %d\n", cfg->last_bts_port);
+				return -1;
+			}
+			endp->bts_end.local_alloc = PORT_ALLOC_STATIC;
+		}
+
+		if (cfg->net_ports.mode == PORT_ALLOC_STATIC) {
+			cfg->last_net_port += 2;
+			if (mgcp_bind_net_rtp_port(endp, cfg->last_net_port) != 0) {
+				LOGP(DLMGCP, LOGL_FATAL,
+				     "Failed to bind: %d\n", cfg->last_net_port);
+				return -1;
+			}
+			endp->net_end.local_alloc = PORT_ALLOC_STATIC;
+		}
+
+		if (trunk->trunk_type == MGCP_TRUNK_VIRTUAL &&
+		    cfg->transcoder_ip && cfg->transcoder_ports.mode == PORT_ALLOC_STATIC) {
+			int rtp_port;
+
+			/* network side */
+			rtp_port = rtp_calculate_port(ENDPOINT_NUMBER(endp),
+						      cfg->transcoder_ports.base_port);
+			if (mgcp_bind_trans_net_rtp_port(endp, rtp_port) != 0) {
+				LOGP(DLMGCP, LOGL_FATAL, "Failed to bind: %d\n", rtp_port);
+				return -1;
+			}
+			endp->trans_net.local_alloc = PORT_ALLOC_STATIC;
+
+			/* bts side */
+			rtp_port = rtp_calculate_port(endp_back_channel(ENDPOINT_NUMBER(endp)),
+						      cfg->transcoder_ports.base_port);
+			if (mgcp_bind_trans_bts_rtp_port(endp, rtp_port) != 0) {
+				LOGP(DLMGCP, LOGL_FATAL, "Failed to bind: %d\n", rtp_port);
+				return -1;
+			}
+			endp->trans_bts.local_alloc = PORT_ALLOC_STATIC;
+		}
+	}
+
+	return 0;
+}
+
+int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
+		      enum mgcp_role role)
+{
+	int rc;
+	struct mgcp_trunk_config *trunk;
+
+	cfg->osmux_port = OSMUX_PORT;
+	cfg->osmux_batch = 4;
+	cfg->osmux_batch_size = OSMUX_BATCH_DEFAULT_MAX;
+
+	g_cfg = cfg;
+	rc = vty_read_config_file(config_file, NULL);
+	if (rc < 0) {
+		fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
+		return rc;
+	}
+
+
+	if (!g_cfg->bts_ip)
+		fprintf(stderr, "No BTS ip address specified. This will allow everyone to connect.\n");
+
+	if (!g_cfg->source_addr) {
+		fprintf(stderr, "You need to specify a bind address.\n");
+		return -1;
+	}
+
+	/* initialize the last ports */
+	g_cfg->last_bts_port = rtp_calculate_port(0, g_cfg->bts_ports.base_port);
+	g_cfg->last_net_port = rtp_calculate_port(0, g_cfg->net_ports.base_port);
+
+	if (allocate_trunk(&g_cfg->trunk) != 0) {
+		LOGP(DLMGCP, LOGL_ERROR, "Failed to initialize the virtual trunk.\n");
+		return -1;
+	}
+
+	llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
+		if (allocate_trunk(trunk) != 0) {
+			LOGP(DLMGCP, LOGL_ERROR,
+			     "Failed to initialize E1 trunk %d.\n", trunk->trunk_nr);
+			return -1;
+		}
+	}
+	cfg->role = role;
+
+	return 0;
+}
+
diff --git a/src/libosmo-legacy-mgcp/mgcpgw_client.c b/src/libosmo-legacy-mgcp/mgcpgw_client.c
new file mode 100644
index 0000000..810ba16
--- /dev/null
+++ b/src/libosmo-legacy-mgcp/mgcpgw_client.c
@@ -0,0 +1,622 @@
+/* mgcp_utils - common functions to setup an MGCP connection
+ */
+/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * 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/>.
+ *
+ */
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/write_queue.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/logging.h>
+
+#include <osmocom/legacy_mgcp/mgcpgw_client.h>
+#include <osmocom/legacy_mgcp/mgcp.h>
+#include <osmocom/legacy_mgcp/mgcp_internal.h>
+#include <osmocom/legacy_mgcp/mgcpgw_client_internal.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+void mgcpgw_client_conf_init(struct mgcpgw_client_conf *conf)
+{
+	/* NULL and -1 default to MGCPGW_CLIENT_*_DEFAULT values */
+	*conf = (struct mgcpgw_client_conf){
+		.local_addr = NULL,
+		.local_port = -1,
+		.remote_addr = NULL,
+		.remote_port = -1,
+		.first_endpoint = 0,
+		.last_endpoint = 0,
+		.bts_base = 0,
+	};
+}
+
+/* Test if a given endpoint id is currently in use */
+static bool endpoint_in_use(uint16_t id, struct mgcpgw_client *client)
+{
+	struct mgcp_inuse_endpoint *endpoint;
+	llist_for_each_entry(endpoint, &client->inuse_endpoints, entry) {
+		if (endpoint->id == id)
+			return true;
+	}
+
+	return false;
+}
+
+/* Find and seize an unsused endpoint id */
+int mgcpgw_client_next_endpoint(struct mgcpgw_client *client)
+{
+	int i;
+	uint16_t first_endpoint = client->actual.first_endpoint;
+	uint16_t last_endpoint = client->actual.last_endpoint;
+	struct mgcp_inuse_endpoint *endpoint;
+
+	/* Use the maximum permitted range if the VTY
+	 * configuration does not specify a range */
+	if (client->actual.last_endpoint == 0) {
+		first_endpoint = 1;
+		last_endpoint = 65534;
+	}
+
+	/* Test the permitted endpoint range for an endpoint
+	 * number that is not in use. When a suitable endpoint
+	 * number can be found, seize it by adding it to the
+	 * inuse list. */
+	for (i=first_endpoint;i<last_endpoint;i++)
+	{
+		if (endpoint_in_use(i,client) == false) {
+			endpoint = talloc_zero(client, struct mgcp_inuse_endpoint);
+			endpoint->id = i;
+			llist_add_tail(&endpoint->entry, &client->inuse_endpoints);
+			return endpoint->id;
+		}
+	}
+
+	/* All endpoints are busy! */
+	return -EINVAL;
+}
+
+/* Release a seized endpoint id to make it available again for other calls */
+void mgcpgw_client_release_endpoint(uint16_t id, struct mgcpgw_client *client)
+{
+	struct mgcp_inuse_endpoint *endpoint;
+	struct mgcp_inuse_endpoint *endpoint_tmp;
+	llist_for_each_entry_safe(endpoint, endpoint_tmp, &client->inuse_endpoints, entry) {
+		if (endpoint->id == id) {
+			llist_del(&endpoint->entry);
+			talloc_free(endpoint);
+		}
+	}
+}
+
+static void mgcpgw_client_handle_response(struct mgcpgw_client *mgcp,
+					  struct mgcp_response_pending *pending,
+					  struct mgcp_response *response)
+{
+	if (!pending) {
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "Cannot handle NULL response\n");
+		return;
+	}
+	if (pending->response_cb)
+		pending->response_cb(response, pending->priv);
+	else
+		LOGP(DLMGCP, LOGL_INFO, "MGCP response ignored (NULL cb)\n");
+	talloc_free(pending);
+}
+
+static int mgcp_response_parse_head(struct mgcp_response *r, struct msgb *msg)
+{
+	int comment_pos;
+	char *end;
+
+	if (mgcp_msg_terminate_nul(msg))
+		goto response_parse_failure;
+
+	r->body = (char *)msg->data;
+
+        if (sscanf(r->body, "%3d %u %n",
+		   &r->head.response_code, &r->head.trans_id,
+		   &comment_pos) != 2)
+		goto response_parse_failure;
+
+	r->head.comment = r->body + comment_pos;
+	end = strchr(r->head.comment, '\r');
+	if (!end)
+		goto response_parse_failure;
+	/* Mark the end of the comment */
+	*end = '\0';
+	r->body = end + 1;
+	if (r->body[0] == '\n')
+		r->body ++;
+	return 0;
+
+response_parse_failure:
+	LOGP(DLMGCP, LOGL_ERROR,
+	     "Failed to parse MGCP response header\n");
+	return -EINVAL;
+}
+
+/* TODO undup against mgcp_protocol.c:mgcp_check_param() */
+static bool mgcp_line_is_valid(const char *line)
+{
+	const size_t line_len = strlen(line);
+	if (line[0] == '\0')
+		return true;
+
+	if (line_len < 2
+	    || line[1] != '=') {
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "Wrong MGCP option format: '%s'\n",
+		     line);
+		return false;
+	}
+
+	return true;
+}
+
+/* Parse a line like "m=audio 16002 RTP/AVP 98" */
+static int mgcp_parse_audio(struct mgcp_response *r, const char *line)
+{
+        if (sscanf(line, "m=audio %hu",
+		   &r->audio_port) != 1)
+		goto response_parse_failure;
+
+	return 0;
+
+response_parse_failure:
+	LOGP(DLMGCP, LOGL_ERROR,
+	     "Failed to parse MGCP response header\n");
+	return -EINVAL;
+}
+
+int mgcp_response_parse_params(struct mgcp_response *r)
+{
+	char *line;
+	int rc;
+	OSMO_ASSERT(r->body);
+	char *data = strstr(r->body, "\n\n");
+
+	if (!data) {
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "MGCP response: cannot find start of parameters\n");
+		return -EINVAL;
+	}
+
+	/* Advance to after the \n\n, replace the second \n with \0. That's
+	 * where the parameters start. */
+	data ++;
+	*data = '\0';
+	data ++;
+
+	for_each_line(line, data) {
+		if (!mgcp_line_is_valid(line))
+			return -EINVAL;
+
+		switch (line[0]) {
+		case 'm':
+			rc = mgcp_parse_audio(r, line);
+			if (rc)
+				return rc;
+			break;
+		default:
+			/* skip unhandled parameters */
+			break;
+		}
+	}
+	return 0;
+}
+
+static struct mgcp_response_pending *mgcpgw_client_response_pending_get(
+					 struct mgcpgw_client *mgcp,
+					 struct mgcp_response *r)
+{
+	struct mgcp_response_pending *pending;
+	if (!r)
+		return NULL;
+	llist_for_each_entry(pending, &mgcp->responses_pending, entry) {
+		if (pending->trans_id == r->head.trans_id) {
+			llist_del(&pending->entry);
+			return pending;
+		}
+	}
+	return NULL;
+}
+
+/* Feed an MGCP message into the receive processing.
+ * Parse the head and call any callback registered for the transaction id found
+ * in the MGCP message. This is normally called directly from the internal
+ * mgcp_do_read that reads from the socket connected to the MGCP gateway. This
+ * function is published mainly to be able to feed data from the test suite.
+ */
+int mgcpgw_client_rx(struct mgcpgw_client *mgcp, struct msgb *msg)
+{
+	struct mgcp_response r = { 0 };
+	struct mgcp_response_pending *pending;
+	int rc;
+
+	rc = mgcp_response_parse_head(&r, msg);
+	if (rc) {
+		LOGP(DLMGCP, LOGL_ERROR, "Cannot parse MGCP response\n");
+		return -1;
+	}
+
+	pending = mgcpgw_client_response_pending_get(mgcp, &r);
+	if (!pending) {
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "Cannot find matching MGCP transaction for trans_id %d\n",
+		     r.head.trans_id);
+		return -1;
+	}
+
+	mgcpgw_client_handle_response(mgcp, pending, &r);
+	return 0;
+}
+
+static int mgcp_do_read(struct osmo_fd *fd)
+{
+	struct mgcpgw_client *mgcp = fd->data;
+	struct msgb *msg;
+	int ret;
+
+	msg = msgb_alloc_headroom(4096, 128, "mgcp_from_gw");
+	if (!msg) {
+		LOGP(DLMGCP, LOGL_ERROR, "Failed to allocate MGCP message.\n");
+		return -1;
+	}
+
+	ret = read(fd->fd, msg->data, 4096 - 128);
+	if (ret <= 0) {
+		LOGP(DLMGCP, LOGL_ERROR, "Failed to read: %d/%s\n", errno, strerror(errno));
+		msgb_free(msg);
+		return -1;
+	} else if (ret > 4096 - 128) {
+		LOGP(DLMGCP, LOGL_ERROR, "Too much data: %d\n", ret);
+		msgb_free(msg);
+		return -1;
+        }
+
+	msg->l2h = msgb_put(msg, ret);
+	ret = mgcpgw_client_rx(mgcp, msg);
+	talloc_free(msg);
+	return ret;
+}
+
+static int mgcp_do_write(struct osmo_fd *fd, struct msgb *msg)
+{
+	int ret;
+	static char strbuf[4096];
+	unsigned int l = msg->len < sizeof(strbuf) ? msg->len : sizeof(strbuf);
+	unsigned int i;
+
+	strncpy(strbuf, (const char*)msg->data, l);
+	for (i = 0; i < sizeof(strbuf); i++) {
+		if (strbuf[i] == '\n' || strbuf[i] == '\r') {
+			strbuf[i] = '\0';
+			break;
+		}
+	}
+	DEBUGP(DLMGCP, "Tx MGCP msg to MGCP GW: '%s'\n", strbuf);
+
+	LOGP(DLMGCP, LOGL_DEBUG, "Sending msg to MGCP GW size: %u\n", msg->len);
+
+	ret = write(fd->fd, msg->data, msg->len);
+	if (ret != msg->len)
+		LOGP(DLMGCP, LOGL_ERROR, "Failed to forward message to MGCP"
+		     " GW: %s\n", strerror(errno));
+
+	return ret;
+}
+
+struct mgcpgw_client *mgcpgw_client_init(void *ctx,
+					 struct mgcpgw_client_conf *conf)
+{
+	struct mgcpgw_client *mgcp;
+
+	mgcp = talloc_zero(ctx, struct mgcpgw_client);
+
+	INIT_LLIST_HEAD(&mgcp->responses_pending);
+	INIT_LLIST_HEAD(&mgcp->inuse_endpoints);
+
+	mgcp->next_trans_id = 1;
+
+	mgcp->actual.local_addr = conf->local_addr ? conf->local_addr :
+		MGCPGW_CLIENT_LOCAL_ADDR_DEFAULT;
+	mgcp->actual.local_port = conf->local_port >= 0 ? (uint16_t)conf->local_port :
+		MGCPGW_CLIENT_LOCAL_PORT_DEFAULT;
+
+	mgcp->actual.remote_addr = conf->remote_addr ? conf->remote_addr :
+		MGCPGW_CLIENT_REMOTE_ADDR_DEFAULT;
+	mgcp->actual.remote_port = conf->remote_port >= 0 ? (uint16_t)conf->remote_port :
+		MGCPGW_CLIENT_REMOTE_PORT_DEFAULT;
+
+	mgcp->actual.first_endpoint = conf->first_endpoint > 0 ? (uint16_t)conf->first_endpoint : 0;
+	mgcp->actual.last_endpoint = conf->last_endpoint > 0 ? (uint16_t)conf->last_endpoint : 0;
+	mgcp->actual.bts_base = conf->bts_base > 0 ? (uint16_t)conf->bts_base : 4000;
+
+	return mgcp;
+}
+
+int mgcpgw_client_connect(struct mgcpgw_client *mgcp)
+{
+	int on;
+	struct sockaddr_in addr;
+	struct osmo_wqueue *wq;
+	int rc;
+
+	if (!mgcp) {
+		LOGP(DLMGCP, LOGL_FATAL, "MGCPGW client not initialized properly\n");
+		return -EINVAL;
+	}
+
+	wq = &mgcp->wq;
+
+	wq->bfd.fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (wq->bfd.fd < 0) {
+		LOGP(DLMGCP, LOGL_FATAL, "Failed to create UDP socket errno: %d\n", errno);
+		return -errno;
+	}
+
+	on = 1;
+	if (setsockopt(wq->bfd.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
+		LOGP(DLMGCP, LOGL_FATAL,
+		     "Failed to initialize socket for MGCP GW: %s\n",
+		     strerror(errno));
+		rc = -errno;
+		goto error_close_fd;
+	}
+
+	/* bind socket */
+	memset(&addr, 0, sizeof(addr));
+	addr.sin_family = AF_INET;
+	inet_aton(mgcp->actual.local_addr, &addr.sin_addr);
+	addr.sin_port = htons(mgcp->actual.local_port);
+	if (bind(wq->bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		LOGP(DLMGCP, LOGL_FATAL,
+		     "Failed to bind for MGCP GW to %s %u\n",
+		     mgcp->actual.local_addr, mgcp->actual.local_port);
+		rc = -errno;
+		goto error_close_fd;
+	}
+
+	/* connect to the remote */
+	inet_aton(mgcp->actual.remote_addr, &addr.sin_addr);
+	addr.sin_port = htons(mgcp->actual.remote_port);
+	if (connect(wq->bfd.fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+		LOGP(DLMGCP, LOGL_FATAL,
+		     "Failed to connect to MGCP GW at %s %u: %s\n",
+		     mgcp->actual.remote_addr, mgcp->actual.remote_port,
+		     strerror(errno));
+		rc = -errno;
+		goto error_close_fd;
+	}
+
+	mgcp->remote_addr = htonl(addr.sin_addr.s_addr);
+
+	osmo_wqueue_init(wq, 10);
+	wq->bfd.when = BSC_FD_READ;
+	wq->bfd.data = mgcp;
+	wq->read_cb = mgcp_do_read;
+	wq->write_cb = mgcp_do_write;
+
+	if (osmo_fd_register(&wq->bfd) != 0) {
+		LOGP(DLMGCP, LOGL_FATAL, "Failed to register BFD\n");
+		rc = -EIO;
+		goto error_close_fd;
+	}
+	LOGP(DLMGCP, LOGL_INFO, "MGCP GW connection: %s:%u -> %s:%u\n",
+	     mgcp->actual.local_addr, mgcp->actual.local_port,
+	     mgcp->actual.remote_addr, mgcp->actual.remote_port);
+
+	return 0;
+error_close_fd:
+	close(wq->bfd.fd);
+	wq->bfd.fd = -1;
+	return rc;
+}
+
+const char *mgcpgw_client_remote_addr_str(struct mgcpgw_client *mgcp)
+{
+	return mgcp->actual.remote_addr;
+}
+
+uint16_t mgcpgw_client_remote_port(struct mgcpgw_client *mgcp)
+{
+	return mgcp->actual.remote_port;
+}
+
+/* Return the MGCP GW binary IPv4 address in network byte order. */
+uint32_t mgcpgw_client_remote_addr_n(struct mgcpgw_client *mgcp)
+{
+	return mgcp->remote_addr;
+}
+
+struct mgcp_response_pending * mgcpgw_client_pending_add(
+					struct mgcpgw_client *mgcp,
+					mgcp_trans_id_t trans_id,
+					mgcp_response_cb_t response_cb,
+					void *priv)
+{
+	struct mgcp_response_pending *pending;
+
+	pending = talloc_zero(mgcp, struct mgcp_response_pending);
+	pending->trans_id = trans_id;
+	pending->response_cb = response_cb;
+	pending->priv = priv;
+	llist_add_tail(&pending->entry, &mgcp->responses_pending);
+
+	return pending;
+}
+
+/* Send the MGCP message in msg to the MGCP GW and handle a response with
+ * response_cb. NOTE: the response_cb still needs to call
+ * mgcp_response_parse_params(response) to get the parsed parameters -- to
+ * potentially save some CPU cycles, only the head line has been parsed when
+ * the response_cb is invoked. */
+int mgcpgw_client_tx(struct mgcpgw_client *mgcp, struct msgb *msg,
+		     mgcp_response_cb_t response_cb, void *priv)
+{
+	struct mgcp_response_pending *pending;
+	mgcp_trans_id_t trans_id;
+	int rc;
+
+	trans_id = msg->cb[MSGB_CB_MGCP_TRANS_ID];
+	if (!trans_id) {
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "Unset transaction id in mgcp send request\n");
+		talloc_free(msg);
+		return -EINVAL;
+	}
+
+	pending = mgcpgw_client_pending_add(mgcp, trans_id, response_cb, priv);
+
+	if (msgb_l2len(msg) > 4096) {
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "Cannot send, MGCP message too large: %u\n",
+		     msgb_l2len(msg));
+		msgb_free(msg);
+		rc = -EINVAL;
+		goto mgcp_tx_error;
+	}
+
+	rc = osmo_wqueue_enqueue(&mgcp->wq, msg);
+	if (rc) {
+		LOGP(DLMGCP, LOGL_FATAL, "Could not queue message to MGCP GW\n");
+		msgb_free(msg);
+		goto mgcp_tx_error;
+	} else
+		LOGP(DLMGCP, LOGL_INFO, "Queued %u bytes for MGCP GW\n",
+		     msgb_l2len(msg));
+	return 0;
+
+mgcp_tx_error:
+	/* Pass NULL to response cb to indicate an error */
+	mgcpgw_client_handle_response(mgcp, pending, NULL);
+	return -1;
+}
+
+static struct msgb *mgcp_msg_from_buf(mgcp_trans_id_t trans_id,
+				      const char *buf, int len)
+{
+	struct msgb *msg;
+
+	if (len > (4096 - 128)) {
+		LOGP(DLMGCP, LOGL_ERROR, "Cannot send to MGCP GW:"
+		     " message too large: %d\n", len);
+		return NULL;
+	}
+
+	msg = msgb_alloc_headroom(4096, 128, "MGCP tx");
+	OSMO_ASSERT(msg);
+
+	char *dst = (char*)msgb_put(msg, len);
+	memcpy(dst, buf, len);
+	msg->l2h = msg->data;
+	msg->cb[MSGB_CB_MGCP_TRANS_ID] = trans_id;
+
+	return msg;
+}
+
+static struct msgb *mgcp_msg_from_str(mgcp_trans_id_t trans_id,
+				      const char *fmt, ...)
+{
+	static char compose[4096 - 128];
+	va_list ap;
+	int len;
+	OSMO_ASSERT(fmt);
+
+	va_start(ap, fmt);
+	len = vsnprintf(compose, sizeof(compose), fmt, ap);
+	va_end(ap);
+	if (len >= sizeof(compose)) {
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "Message too large: trans_id=%u len=%d\n",
+		     trans_id, len);
+		return NULL;
+	}
+	if (len < 1) {
+		LOGP(DLMGCP, LOGL_ERROR,
+		     "Failed to compose message: trans_id=%u len=%d\n",
+		     trans_id, len);
+		return NULL;
+	}
+	return mgcp_msg_from_buf(trans_id, compose, len);
+}
+
+static mgcp_trans_id_t mgcpgw_client_next_trans_id(struct mgcpgw_client *mgcp)
+{
+	/* avoid zero trans_id to distinguish from unset trans_id */
+	if (!mgcp->next_trans_id)
+		mgcp->next_trans_id ++;
+	return mgcp->next_trans_id ++;
+}
+
+struct msgb *mgcp_msg_crcx(struct mgcpgw_client *mgcp,
+			   uint16_t rtp_endpoint, unsigned int call_id,
+			   enum mgcp_connection_mode mode)
+{
+	mgcp_trans_id_t trans_id = mgcpgw_client_next_trans_id(mgcp);
+	return mgcp_msg_from_str(trans_id,
+		 "CRCX %u %x@mgw MGCP 1.0\r\n"
+		 "C: %x\r\n"
+		 "L: p:20, a:AMR, nt:IN\r\n"
+		 "M: %s\r\n"
+		 ,
+		 trans_id,
+		 rtp_endpoint,
+		 call_id,
+		 mgcp_cmode_name(mode));
+}
+
+struct msgb *mgcp_msg_mdcx(struct mgcpgw_client *mgcp,
+			   uint16_t rtp_endpoint, const char *rtp_conn_addr,
+			   uint16_t rtp_port, enum mgcp_connection_mode mode)
+
+{
+	mgcp_trans_id_t trans_id = mgcpgw_client_next_trans_id(mgcp);
+	return mgcp_msg_from_str(trans_id,
+		 "MDCX %u %x@mgw MGCP 1.0\r\n"
+		 "M: %s\r\n"
+		 "\r\n"
+		 "c=IN IP4 %s\r\n"
+		 "m=audio %u RTP/AVP 255\r\n"
+		 ,
+		 trans_id,
+		 rtp_endpoint,
+		 mgcp_cmode_name(mode),
+		 rtp_conn_addr,
+		 rtp_port);
+}
+
+struct msgb *mgcp_msg_dlcx(struct mgcpgw_client *mgcp, uint16_t rtp_endpoint,
+			   unsigned int call_id)
+{
+	mgcp_trans_id_t trans_id = mgcpgw_client_next_trans_id(mgcp);
+	return mgcp_msg_from_str(trans_id,
+				 "DLCX %u %x@mgw MGCP 1.0\r\n"
+				 "C: %x\r\n", trans_id, rtp_endpoint, call_id);
+}
+
+struct mgcpgw_client_conf *mgcpgw_client_conf_actual(struct mgcpgw_client *mgcp)
+{
+	return &mgcp->actual;
+}
diff --git a/src/libosmo-legacy-mgcp/mgcpgw_client_vty.c b/src/libosmo-legacy-mgcp/mgcpgw_client_vty.c
new file mode 100644
index 0000000..d101ded
--- /dev/null
+++ b/src/libosmo-legacy-mgcp/mgcpgw_client_vty.c
@@ -0,0 +1,172 @@
+/* MGCPGW client interface to quagga VTY */
+/* (C) 2016 by sysmocom s.m.f.c. GmbH <info@sysmocom.de>
+ * Based on OpenBSC interface to quagga VTY (libmsc/vty_interface_layer3.c)
+ * (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2009-2011 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/>.
+ *
+ */
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <talloc.h>
+
+#include <osmocom/vty/command.h>
+#include <osmocom/core/utils.h>
+
+#include <osmocom/legacy_mgcp/vty.h>
+#include <osmocom/legacy_mgcp/mgcpgw_client.h>
+
+#define MGCPGW_STR "MGCP gateway configuration for RTP streams\n"
+
+void *global_mgcpgw_client_ctx = NULL;
+struct mgcpgw_client_conf *global_mgcpgw_client_conf = NULL;
+
+DEFUN(cfg_mgcpgw_local_ip, cfg_mgcpgw_local_ip_cmd,
+      "mgcpgw local-ip A.B.C.D",
+      MGCPGW_STR "local bind to connect to MGCP gateway with\n"
+      "local bind IP address\n")
+{
+	if (!global_mgcpgw_client_conf)
+		return CMD_ERR_NOTHING_TODO;
+	OSMO_ASSERT(global_mgcpgw_client_ctx);
+	global_mgcpgw_client_conf->local_addr =
+		talloc_strdup(global_mgcpgw_client_ctx, argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcpgw_local_port, cfg_mgcpgw_local_port_cmd,
+      "mgcpgw local-port <0-65535>",
+      MGCPGW_STR "local bind to connect to MGCP gateway with\n"
+      "local bind port\n")
+{
+	if (!global_mgcpgw_client_conf)
+		return CMD_ERR_NOTHING_TODO;
+	global_mgcpgw_client_conf->local_port = atoi(argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcpgw_remote_ip, cfg_mgcpgw_remote_ip_cmd,
+      "mgcpgw remote-ip A.B.C.D",
+      MGCPGW_STR "remote bind to connect to MGCP gateway with\n"
+      "remote bind IP address\n")
+{
+	if (!global_mgcpgw_client_conf)
+		return CMD_ERR_NOTHING_TODO;
+	OSMO_ASSERT(global_mgcpgw_client_ctx);
+	global_mgcpgw_client_conf->remote_addr =
+		talloc_strdup(global_mgcpgw_client_ctx, argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcpgw_remote_port, cfg_mgcpgw_remote_port_cmd,
+      "mgcpgw remote-port <0-65535>",
+      MGCPGW_STR "remote bind to connect to MGCP gateway with\n"
+      "remote bind port\n")
+{
+	if (!global_mgcpgw_client_conf)
+		return CMD_ERR_NOTHING_TODO;
+	global_mgcpgw_client_conf->remote_port = atoi(argv[0]);
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcpgw_endpoint_range, cfg_mgcpgw_endpoint_range_cmd,
+      "mgcpgw endpoint-range <1-65534> <1-65534>",
+      MGCPGW_STR "usable range of endpoint identifiers\n"
+      "set first useable endpoint identifier\n"
+      "set the last useable endpoint identifier\n")
+{
+	uint16_t first_endpoint = atoi(argv[0]);
+	uint16_t last_endpoint = atoi(argv[1]);
+
+	if (last_endpoint < first_endpoint) {
+		vty_out(vty, "last endpoint must be greater than first endpoint!%s",
+			VTY_NEWLINE);
+		return CMD_SUCCESS;
+	}
+
+	global_mgcpgw_client_conf->first_endpoint = first_endpoint;
+	global_mgcpgw_client_conf->last_endpoint = last_endpoint;
+	return CMD_SUCCESS;
+}
+
+#define BTS_START_STR "First UDP port allocated for the BTS side\n"
+#define UDP_PORT_STR "UDP Port number\n"
+DEFUN(cfg_mgcp_rtp_bts_base_port,
+      cfg_mgcp_rtp_bts_base_port_cmd,
+      "mgcpgw bts-base <0-65534>",
+      MGCPGW_STR
+      BTS_START_STR
+      UDP_PORT_STR)
+{
+	global_mgcpgw_client_conf->bts_base = atoi(argv[0]);
+	return CMD_SUCCESS;
+}
+
+int mgcpgw_client_config_write(struct vty *vty, const char *indent)
+{
+	const char *addr;
+	int port;
+	uint16_t first_endpoint;
+	uint16_t last_endpoint;
+	uint16_t bts_base;
+
+	addr = global_mgcpgw_client_conf->local_addr;
+	if (addr)
+		vty_out(vty, "%smgcpgw local-ip %s%s", indent, addr,
+			VTY_NEWLINE);
+	port = global_mgcpgw_client_conf->local_port;
+	if (port >= 0)
+		vty_out(vty, "%smgcpgw local-port %u%s", indent,
+			(uint16_t)port, VTY_NEWLINE);
+
+	addr = global_mgcpgw_client_conf->remote_addr;
+	if (addr)
+		vty_out(vty, "%smgcpgw remote-ip %s%s", indent, addr,
+			VTY_NEWLINE);
+	port = global_mgcpgw_client_conf->remote_port;
+	if (port >= 0)
+		vty_out(vty, "%smgcpgw remote-port %u%s", indent,
+			(uint16_t)port, VTY_NEWLINE);
+
+	first_endpoint = global_mgcpgw_client_conf->first_endpoint;
+	last_endpoint = global_mgcpgw_client_conf->last_endpoint;
+	if (last_endpoint != 0) {
+		vty_out(vty, "%smgcpgw endpoint-range %u %u%s", indent,
+			first_endpoint, last_endpoint, VTY_NEWLINE);
+	}
+
+	bts_base = global_mgcpgw_client_conf->bts_base;
+	if (bts_base) {
+		vty_out(vty, "%smgcpgw bts-base %u%s", indent,
+			bts_base, VTY_NEWLINE);
+	}
+
+	return CMD_SUCCESS;
+}
+
+void mgcpgw_client_vty_init(void *talloc_ctx, int node, struct mgcpgw_client_conf *conf)
+{
+	global_mgcpgw_client_ctx = talloc_ctx;
+	global_mgcpgw_client_conf = conf;
+
+	install_element(node, &cfg_mgcpgw_local_ip_cmd);
+	install_element(node, &cfg_mgcpgw_local_port_cmd);
+	install_element(node, &cfg_mgcpgw_remote_ip_cmd);
+	install_element(node, &cfg_mgcpgw_remote_port_cmd);
+	install_element(node, &cfg_mgcpgw_endpoint_range_cmd);
+	install_element(node, &cfg_mgcp_rtp_bts_base_port_cmd);
+}
diff --git a/src/libtrau/Makefile.am b/src/libtrau/Makefile.am
deleted file mode 100644
index 46becd6..0000000
--- a/src/libtrau/Makefile.am
+++ /dev/null
@@ -1,31 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	-I$(top_builddir) \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOVTY_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(LIBOSMONETIF_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	$(COVERAGE_LDFLAGS) \
-	$(NULL)
-
-noinst_LIBRARIES = \
-	libtrau.a \
-	$(NULL)
-
-libtrau_a_SOURCES = \
-	rtp_proxy.c \
-	trau_mux.c \
-	trau_upqueue.c \
-	$(NULL)
diff --git a/src/libtrau/rtp_proxy.c b/src/libtrau/rtp_proxy.c
deleted file mode 100644
index 6b38ee5..0000000
--- a/src/libtrau/rtp_proxy.c
+++ /dev/null
@@ -1,764 +0,0 @@
-/* RTP proxy handling for ip.access nanoBTS */
-
-/* (C) 2009-2013 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/>.
- *
- */
-
-#include <errno.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/time.h>    /* gettimeofday() */
-#include <unistd.h>      /* get..() */
-#include <time.h>        /* clock() */
-#include <sys/utsname.h> /* uname() */
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-#include <openbsc/gsm_data.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/select.h>
-#include <openbsc/debug.h>
-#include <openbsc/rtp_proxy.h>
-#include <openbsc/mncc.h>
-#include <openbsc/trau_upqueue.h>
-
-#include <osmocom/netif/rtp.h>
-
-/* attempt to determine byte order */
-#include <sys/param.h>
-#include <limits.h>
-
-static LLIST_HEAD(rtp_sockets);
-
-/* should we mangle the CNAME inside SDES of RTCP packets? We disable
- * this by default, as it seems to be not needed */
-static int mangle_rtcp_cname = 0;
-
-enum rtp_bfd_priv {
-	RTP_PRIV_NONE,
-	RTP_PRIV_RTP,
-	RTP_PRIV_RTCP
-};
-
-#define RTP_ALLOC_SIZE	1500
-
-#define RTCP_TYPE_SDES	202
-	
-#define RTCP_IE_CNAME	1
-
-
-#define RTP_VERSION	2
-
-/* 33 for FR, all other codecs have smaller size */
-#define MAX_RTP_PAYLOAD_LEN	33
-
-/* decode an rtp frame and create a new buffer with payload */
-static int rtp_decode(struct msgb *msg, uint32_t callref, struct msgb **data)
-{
-	struct msgb *new_msg;
-	struct gsm_data_frame *frame;
-	struct rtp_hdr *rtph = (struct rtp_hdr *)msg->data;
-	struct rtp_x_hdr *rtpxh;
-	uint8_t *payload, *payload_out;
-	int payload_len;
-	int msg_type;
-	int x_len;
-
-	if (msg->len < 12) {
-		DEBUGPC(DLMUX, "received RTP frame too short (len = %d)\n",
-			msg->len);
-		return -EINVAL;
-	}
-	if (rtph->version != RTP_VERSION) {
-		DEBUGPC(DLMUX, "received RTP version %d not supported.\n",
-			rtph->version);
-		return -EINVAL;
-	}
-	payload = msg->data + sizeof(struct rtp_hdr) + (rtph->csrc_count << 2);
-	payload_len = msg->len - sizeof(struct rtp_hdr) - (rtph->csrc_count << 2);
-	if (payload_len < 0) {
-		DEBUGPC(DLMUX, "received RTP frame too short (len = %d, "
-			"csrc count = %d)\n", msg->len, rtph->csrc_count);
-		return -EINVAL;
-	}
-	if (rtph->extension) {
-		if (payload_len < sizeof(struct rtp_x_hdr)) {
-			DEBUGPC(DLMUX, "received RTP frame too short for "
-				"extension header\n");
-			return -EINVAL;
-		}
-		rtpxh = (struct rtp_x_hdr *)payload;
-		x_len = ntohs(rtpxh->length) * 4 + sizeof(struct rtp_x_hdr);
-		payload += x_len;
-		payload_len -= x_len;
-		if (payload_len < 0) {
-			DEBUGPC(DLMUX, "received RTP frame too short, "
-				"extension header exceeds frame length\n");
-			return -EINVAL;
-		}
-	}
-	if (rtph->padding) {
-		if (payload_len < 1) {
-			DEBUGPC(DLMUX, "received RTP frame too short for "
-				"padding length\n");
-			return -EINVAL;
-		}
-		payload_len -= payload[payload_len - 1];
-		if (payload_len < 0) {
-			DEBUGPC(DLMUX, "received RTP frame with padding "
-				"greater than payload\n");
-			return -EINVAL;
-		}
-	}
-
-	switch (rtph->payload_type) {
-	case RTP_PT_GSM_FULL:
-		msg_type = GSM_TCHF_FRAME;
-		if (payload_len != RTP_LEN_GSM_FULL) {
-			DEBUGPC(DLMUX, "received RTP full rate frame with "
-				"payload length != %d (len = %d)\n",
-				RTP_LEN_GSM_FULL, payload_len);
-			return -EINVAL;
-		}
-		break;
-	case RTP_PT_GSM_EFR:
-		msg_type = GSM_TCHF_FRAME_EFR;
-		if (payload_len != RTP_LEN_GSM_EFR) {
-			DEBUGPC(DLMUX, "received RTP extended full rate frame "
-				"with payload length != %d (len = %d)\n",
-				RTP_LEN_GSM_EFR, payload_len);
-			return -EINVAL;
-		}
-		break;
-	case RTP_PT_GSM_HALF:
-		msg_type = GSM_TCHH_FRAME;
-		if (payload_len != RTP_LEN_GSM_HALF) {
-			DEBUGPC(DLMUX, "received RTP half rate frame with "
-				"payload length != %d (len = %d)\n",
-				RTP_LEN_GSM_HALF, payload_len);
-			return -EINVAL;
-		}
-		break;
-	case RTP_PT_AMR:
-		msg_type = GSM_TCH_FRAME_AMR;
-		break;
-	default:
-		DEBUGPC(DLMUX, "received RTP frame with unknown payload "
-			"type %d\n", rtph->payload_type);
-		return -EINVAL;
-	}
-
-	if (payload_len > MAX_RTP_PAYLOAD_LEN ||
-	    (rtph->payload_type == RTP_PT_AMR &&
-	     payload_len > MAX_RTP_PAYLOAD_LEN - 1)) {
-		DEBUGPC(DLMUX, "RTP payload too large (%d octets)\n",
-			payload_len);
-		return -EINVAL;
-	}
-
-	/* always allocate for the maximum possible size to avoid
-	 * fragmentation */
-	new_msg = msgb_alloc(sizeof(struct gsm_data_frame) +
-			     MAX_RTP_PAYLOAD_LEN+1, "GSM-DATA (TCH)");
-
-	if (!new_msg)
-		return -ENOMEM;
-	frame = (struct gsm_data_frame *) msgb_put(new_msg, sizeof(struct gsm_data_frame));
-	frame->msg_type = msg_type;
-	frame->callref = callref;
-	if (rtph->payload_type == RTP_PT_AMR) {
-		/* for FR/HR/EFR the length is implicit.  In AMR, we
-		 * need to make it explicit by using the first byte of
-		 * the data[] buffer as length byte */
-		uint8_t *data0 = msgb_put(new_msg, 1);
-		*data0 = payload_len;
-	}
-	payload_out = msgb_put(new_msg, payload_len);
-	memcpy(payload_out, payload, payload_len);
-
-	*data = new_msg;
-	return 0;
-}
-
-/*! \brief encode and send a rtp frame
- *  \param[in] rs RTP socket through which we shall send
- *  \param[in] frame GSM RTP frame to be sent
- */
-int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
-{
-	struct rtp_sub_socket *rss = &rs->rtp;
-	struct msgb *msg;
-	struct rtp_hdr *rtph;
-	uint8_t *payload;
-	int payload_type;
-	int payload_len;
-	int duration; /* in samples */
-	int is_bfi = 0;
-
-	if (rs->tx_action != RTP_SEND_DOWNSTREAM) {
-		/* initialize sequences */
-		rs->tx_action = RTP_SEND_DOWNSTREAM;
-		rs->transmit.ssrc = rand();
-		rs->transmit.sequence = random();
-		rs->transmit.timestamp = random();
-	}
-
-	switch (frame->msg_type) {
-	case GSM_TCHF_FRAME:
-		payload_type = RTP_PT_GSM_FULL;
-		payload_len = RTP_LEN_GSM_FULL;
-		duration = RTP_GSM_DURATION;
-		break;
-	case GSM_TCHF_FRAME_EFR:
-		payload_type = RTP_PT_GSM_EFR;
-		payload_len = RTP_LEN_GSM_EFR;
-		duration = RTP_GSM_DURATION;
-		break;
-	case GSM_TCHH_FRAME:
-		payload_type = RTP_PT_GSM_HALF;
-		payload_len = RTP_LEN_GSM_HALF;
-		duration = RTP_GSM_DURATION;
-		break;
-	case GSM_TCH_FRAME_AMR:
-		payload_type = RTP_PT_AMR;
-		payload_len = frame->data[0];
-		duration = RTP_GSM_DURATION;
-		break;
-	case GSM_BAD_FRAME:
-		payload_type = 0;
-		payload_len = 0;
-		duration = RTP_GSM_DURATION;
-		is_bfi = 1;
-		break;
-	default:
-		DEBUGPC(DLMUX, "unsupported message type %d\n",
-			frame->msg_type);
-		return -EINVAL;
-	}
-
-	if (payload_len > MAX_RTP_PAYLOAD_LEN) {
-		DEBUGPC(DLMUX, "RTP payload too large (%d octets)\n",
-			payload_len);
-		return -EINVAL;
-	}
-
-	if (is_bfi) {
-		/* In case of a bad frame, just count and drop packet. */
-		rs->transmit.timestamp += duration;
-		rs->transmit.sequence++;
-		return 0;
-	}
-
-	msg = msgb_alloc(sizeof(struct rtp_hdr) + payload_len, "RTP-GSM");
-	if (!msg)
-		return -ENOMEM;
-	rtph = (struct rtp_hdr *) msgb_put(msg, sizeof(struct rtp_hdr));
-	rtph->version = RTP_VERSION;
-	rtph->padding = 0;
-	rtph->extension = 0;
-	rtph->csrc_count = 0;
-	rtph->marker = 0;
-	rtph->payload_type = payload_type;
-	rtph->sequence = htons(rs->transmit.sequence++);
-	rtph->timestamp = htonl(rs->transmit.timestamp);
-	rs->transmit.timestamp += duration;
-	rtph->ssrc = htonl(rs->transmit.ssrc);
-
-	payload = msgb_put(msg, payload_len);
-	if (frame->msg_type == GSM_TCH_FRAME_AMR)
-		memcpy(payload, frame->data + 1, payload_len);
-	else
-		memcpy(payload, frame->data, payload_len);
-	msgb_enqueue(&rss->tx_queue, msg);
-	rss->bfd.when |= BSC_FD_WRITE;
-
-	return 0;
-}
-
-/* iterate over all chunks in one RTCP message, look for CNAME IEs and
- * replace all of those with 'new_cname' */
-static int rtcp_sdes_cname_mangle(struct msgb *msg, struct rtcp_hdr *rh,
-				  uint16_t *rtcp_len, const char *new_cname)
-{
-	uint8_t *rtcp_end;
-	uint8_t *cur = (uint8_t *) rh;
-	uint8_t tag, len = 0;
-
-	rtcp_end = cur + *rtcp_len;
-	/* move cur to end of RTP header */
-	cur += sizeof(*rh);
-
-	/* iterate over Chunks */
-	while (cur+4 < rtcp_end) {
-		/* skip four bytes SSRC/CSRC */
-		cur += 4;
-	
-		/* iterate over IE's inside the chunk */
-		while (cur+1 < rtcp_end) {
-			tag = *cur++;
-			if (tag == 0) {
-				/* end of chunk, skip additional zero */
-				while ((*cur++ == 0) && (cur < rtcp_end)) { }
-				break;
-			}
-			len = *cur++;
-	
-			if (tag == RTCP_IE_CNAME) {
-				/* we've found the CNAME, lets mangle it */
-				if (len < strlen(new_cname)) {
-					/* we need to make more space */
-					int increase = strlen(new_cname) - len;
-
-					msgb_push(msg, increase);
-					memmove(cur+len+increase, cur+len,
-						rtcp_end - (cur+len));
-					/* FIXME: we have to respect RTCP
-					 * padding/alignment rules! */
-					len += increase;
-					*(cur-1) += increase;
-					rtcp_end += increase;
-					*rtcp_len += increase;
-				}
-				/* copy new CNAME into message */
-				memcpy(cur, new_cname, strlen(new_cname));
-				/* FIXME: zero the padding in case new CNAME
-				 * is smaller than old one !!! */
-			}
-			cur += len;
-		}
-	}
-
-	return 0;
-}
-
-static int rtcp_mangle(struct msgb *msg, struct rtp_socket *rs)
-{
-	struct rtp_sub_socket *rss = &rs->rtcp;
-	struct rtcp_hdr *rtph;
-	uint16_t old_len;
-	int rc;
-
-	if (!mangle_rtcp_cname)
-		return 0;
-
-	printf("RTCP\n");
-	/* iterate over list of RTCP messages */
-	rtph = (struct rtcp_hdr *)msg->data;
-	while ((void *)rtph + sizeof(*rtph) <= (void *)msg->data + msg->len) {
-		old_len = (ntohs(rtph->length) + 1) * 4;
-		if ((void *)rtph + old_len > (void *)msg->data + msg->len) {
-			DEBUGPC(DLMUX, "received RTCP packet too short for "
-				"length element\n");
-			return -EINVAL;
-		}
-		if (rtph->type == RTCP_TYPE_SDES) {
-			char new_cname[255];
-			osmo_strlcpy(new_cname,
-				     inet_ntoa(rss->sin_local.sin_addr),
-				     sizeof(new_cname));
-			rc = rtcp_sdes_cname_mangle(msg, rtph, &old_len,
-						    new_cname);
-			if (rc < 0)
-				return rc;
-		}
-		rtph = (void *)rtph + old_len;
-	}
-
-	return 0;
-}
-
-/* read from incoming RTP/RTCP socket */
-static int rtp_socket_read(struct rtp_socket *rs, struct rtp_sub_socket *rss)
-{
-	int rc;
-	struct msgb *msg = msgb_alloc(RTP_ALLOC_SIZE, "RTP/RTCP");
-	struct msgb *new_msg;
-	struct rtp_sub_socket *other_rss;
-
-	if (!msg)
-		return -ENOMEM;
-
-	rc = read(rss->bfd.fd, msg->data, RTP_ALLOC_SIZE);
-	if (rc == 0) {
-		rss->bfd.when &= ~BSC_FD_READ;
-		goto out_free;
-	} else if (rc < 0) {
-		/* Ignore "connection refused". this happens, If we open the
-		 * socket faster than the remote side. */
-		if (errno == ECONNREFUSED)
-			goto out_free;
-		DEBUGPC(DLMUX, "Read of RTP socket (%p) failed (errno %d, "
-			"%s)\n", rs, errno, strerror(errno));
-		rss->bfd.when &= ~BSC_FD_READ;
-		goto out_free;
-	}
-
-	msgb_put(msg, rc);
-
-	switch (rs->rx_action) {
-	case RTP_PROXY:
-		if (!rs->proxy.other_sock) {
-			rc = -EIO;
-			goto out_free;
-		}
-		if (rss->bfd.priv_nr == RTP_PRIV_RTP)
-			other_rss = &rs->proxy.other_sock->rtp;
-		else if (rss->bfd.priv_nr == RTP_PRIV_RTCP) {
-			other_rss = &rs->proxy.other_sock->rtcp;
-			/* modify RTCP SDES CNAME */
-			rc = rtcp_mangle(msg, rs);
-			if (rc < 0)
-				goto out_free;
-		} else {
-			rc = -EINVAL;
-			goto out_free;
-		}
-		msgb_enqueue(&other_rss->tx_queue, msg);
-		other_rss->bfd.when |= BSC_FD_WRITE;
-		break;
-
-	case RTP_RECV_UPSTREAM:
-		if (!rs->receive.callref || !rs->receive.net) {
-			rc = -EIO;
-			goto out_free;
-		}
-		if (rss->bfd.priv_nr == RTP_PRIV_RTCP) {
-			if (!mangle_rtcp_cname) {
-				msgb_free(msg);
-				break;
-			}
-			/* modify RTCP SDES CNAME */
-			rc = rtcp_mangle(msg, rs);
-			if (rc < 0)
-				goto out_free;
-			msgb_enqueue(&rss->tx_queue, msg);
-			rss->bfd.when |= BSC_FD_WRITE;
-			break;
-		}
-		if (rss->bfd.priv_nr != RTP_PRIV_RTP) {
-			rc = -EINVAL;
-			goto out_free;
-		}
-		rc = rtp_decode(msg, rs->receive.callref, &new_msg);
-		if (rc < 0)
-			goto out_free;
-		msgb_free(msg);
-		trau_tx_to_mncc(rs->receive.net, new_msg);
-		break;
-
-	case RTP_NONE: /* if socket exists, but disabled by app */
-		msgb_free(msg);
-		break;
-	}
-
-	return 0;
-
-out_free:
-	msgb_free(msg);
-	return rc;
-}
-
-/* \brief write from tx_queue to RTP/RTCP socket */
-static int rtp_socket_write(struct rtp_socket *rs, struct rtp_sub_socket *rss)
-{
-	struct msgb *msg;
-	int written;
-
-	msg = msgb_dequeue(&rss->tx_queue);
-	if (!msg) {
-		rss->bfd.when &= ~BSC_FD_WRITE;
-		return 0;
-	}
-
-	written = write(rss->bfd.fd, msg->data, msg->len);
-	if (written < msg->len) {
-		LOGP(DLMIB, LOGL_ERROR, "short write");
-		msgb_free(msg);
-		return -EIO;
-	}
-
-	msgb_free(msg);
-
-	return 0;
-}
-
-
-/*! \brief callback for the select.c:bfd_* layer */
-static int rtp_bfd_cb(struct osmo_fd *bfd, unsigned int flags)
-{
-	struct rtp_socket *rs = bfd->data;
-	struct rtp_sub_socket *rss;
-
-	switch (bfd->priv_nr) {
-	case RTP_PRIV_RTP:
-		rss = &rs->rtp;
-		break;
-	case RTP_PRIV_RTCP:
-		rss = &rs->rtcp;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (flags & BSC_FD_READ)
-		rtp_socket_read(rs, rss);
-
-	if (flags & BSC_FD_WRITE)
-		rtp_socket_write(rs, rss);
-
-	return 0;
-}
-
-/*! \brief initialize one rtp sub-socket */
-static void init_rss(struct rtp_sub_socket *rss,
-		     struct rtp_socket *rs, int fd, int priv_nr)
-{
-	/* initialize bfd */
-	rss->bfd.fd = fd;
-	rss->bfd.data = rs;
-	rss->bfd.priv_nr = priv_nr;
-	rss->bfd.cb = rtp_bfd_cb;
-}
-
-/*! \brief create a new RTP/RTCP socket and bind it */
-struct rtp_socket *rtp_socket_create(void)
-{
-	int rc;
-	struct rtp_socket *rs;
-
-	DEBUGP(DLMUX, "rtp_socket_create(): ");
-
-	rs = talloc_zero(tall_bsc_ctx, struct rtp_socket);
-	if (!rs)
-		return NULL;
-
-	INIT_LLIST_HEAD(&rs->rtp.tx_queue);
-	INIT_LLIST_HEAD(&rs->rtcp.tx_queue);
-
-	rc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-	if (rc < 0)
-		goto out_free;
-
-	init_rss(&rs->rtp, rs, rc, RTP_PRIV_RTP);
-	rc = osmo_fd_register(&rs->rtp.bfd);
-	if (rc < 0)
-		goto out_rtp_socket;
-
-	rc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-	if (rc < 0)
-		goto out_rtp_bfd;
-
-	init_rss(&rs->rtcp, rs, rc, RTP_PRIV_RTCP);
-	rc = osmo_fd_register(&rs->rtcp.bfd);
-	if (rc < 0)
-		goto out_rtcp_socket;
-
-	DEBUGPC(DLMUX, "success\n");
-
-	rc = rtp_socket_bind(rs, INADDR_ANY);
-	if (rc < 0)
-		goto out_rtcp_bfd;
-
-	return rs;
-
-out_rtcp_bfd:
-	osmo_fd_unregister(&rs->rtcp.bfd);
-out_rtcp_socket:
-	close(rs->rtcp.bfd.fd);
-out_rtp_bfd:
-	osmo_fd_unregister(&rs->rtp.bfd);
-out_rtp_socket:
-	close(rs->rtp.bfd.fd);
-out_free:
-	talloc_free(rs);
-	DEBUGPC(DLMUX, "failed\n");
-	return NULL;
-}
-
-static int rtp_sub_socket_bind(struct rtp_sub_socket *rss, uint32_t ip,
-				uint16_t port)
-{
-	int rc;
-	socklen_t alen = sizeof(rss->sin_local);
-
-	rss->sin_local.sin_family = AF_INET;
-	rss->sin_local.sin_addr.s_addr = htonl(ip);
-	rss->sin_local.sin_port = htons(port);
-	rss->bfd.when |= BSC_FD_READ;
-
-	rc = bind(rss->bfd.fd, (struct sockaddr *)&rss->sin_local,
-		  sizeof(rss->sin_local));
-	if (rc < 0)
-		return rc;
-
-	/* retrieve the address we actually bound to, in case we
-	 * passed INADDR_ANY as IP address */
-	return getsockname(rss->bfd.fd, (struct sockaddr *)&rss->sin_local,
-			   &alen);
-}
-
-#define RTP_PORT_BASE	30000
-static unsigned int next_udp_port = RTP_PORT_BASE;
-
-/*! \brief bind a RTP socket to a specific local address
- *  \param[in] rs RTP socket to be bound
- *  \param[in] ip local IP address to which socket is to be bound
- */
-int rtp_socket_bind(struct rtp_socket *rs, uint32_t ip)
-{
-	int rc = -EIO;
-	struct in_addr ia;
-
-	ia.s_addr = htonl(ip);
-	DEBUGP(DLMUX, "rtp_socket_bind(rs=%p, IP=%s): ", rs,
-		inet_ntoa(ia));
-
-	/* try to bind to a consecutive pair of ports */
-	for (next_udp_port = next_udp_port % 0xffff;
-	     next_udp_port < 0xffff; next_udp_port += 2) {
-		rc = rtp_sub_socket_bind(&rs->rtp, ip, next_udp_port);
-		if (rc != 0)
-			continue;
-
-		rc = rtp_sub_socket_bind(&rs->rtcp, ip, next_udp_port+1);
-		if (rc == 0)
-			break;
-	}
-	if (rc < 0) {
-		DEBUGPC(DLMUX, "failed\n");
-		return rc;
-	}
-
-	ia.s_addr = rs->rtp.sin_local.sin_addr.s_addr;
-	DEBUGPC(DLMUX, "BOUND_IP=%s, BOUND_PORT=%u\n",
-		inet_ntoa(ia), ntohs(rs->rtp.sin_local.sin_port));
-	return ntohs(rs->rtp.sin_local.sin_port);
-}
-
-static int rtp_sub_socket_connect(struct rtp_sub_socket *rss,
-				  uint32_t ip, uint16_t port)
-{
-	int rc;
-	socklen_t alen = sizeof(rss->sin_local);
-
-	rss->sin_remote.sin_family = AF_INET;
-	rss->sin_remote.sin_addr.s_addr = htonl(ip);
-	rss->sin_remote.sin_port = htons(port);
-
-	rc = connect(rss->bfd.fd, (struct sockaddr *) &rss->sin_remote,
-		     sizeof(rss->sin_remote));
-	if (rc < 0)
-		return rc;
-
-	return getsockname(rss->bfd.fd, (struct sockaddr *)&rss->sin_local,
-			   &alen);
-}
-
-/*! \brief 'connect' a RTP socket to a remote peer
- *  \param[in] rs RTP socket to be connected
- *  \param[in] ip remote IP address to which to connect
- *  \param[in] port remote UDP port number to which to connect
- */
-int rtp_socket_connect(struct rtp_socket *rs, uint32_t ip, uint16_t port)
-{
-	int rc;
-	struct in_addr ia;
-
-	ia.s_addr = htonl(ip);
-	DEBUGP(DLMUX, "rtp_socket_connect(rs=%p, ip=%s, port=%u)\n",
-		rs, inet_ntoa(ia), port);
-
-	rc = rtp_sub_socket_connect(&rs->rtp, ip, port);
-	if (rc < 0)
-		return rc;
-
-	return rtp_sub_socket_connect(&rs->rtcp, ip, port+1);
-}
-
-/*! \brief bind two RTP/RTCP sockets together in the proxy
- *  \param[in] this First RTP socket
- *  \param[in] other Second RTP socket
- */
-int rtp_socket_proxy(struct rtp_socket *this, struct rtp_socket *other)
-{
-	DEBUGP(DLMUX, "rtp_socket_proxy(this=%p, other=%p)\n",
-		this, other);
-
-	this->rx_action = RTP_PROXY;
-	this->proxy.other_sock = other;
-
-	other->rx_action = RTP_PROXY;
-	other->proxy.other_sock = this;
-
-	return 0;
-}
-
-/*! \brief bind RTP/RTCP socket to application, disabling proxy
- *  \param[in] this RTP socket
- *  \param[in] net gsm_network argument to trau_tx_to_mncc()
- *  \param[in] callref callref argument to trau_tx_to_mncc()
- */
-int rtp_socket_upstream(struct rtp_socket *this, struct gsm_network *net,
-			uint32_t callref)
-{
-	DEBUGP(DLMUX, "rtp_socket_proxy(this=%p, callref=%u)\n",
-		this, callref);
-
-	if (callref) {
-		this->rx_action = RTP_RECV_UPSTREAM;
-		this->receive.net = net;
-		this->receive.callref = callref;
-	} else
-		this->rx_action = RTP_NONE;
-
-	return 0;
-}
-
-static void free_tx_queue(struct rtp_sub_socket *rss)
-{
-	struct msgb *msg;
-	
-	while ((msg = msgb_dequeue(&rss->tx_queue)))
-		msgb_free(msg);
-}
-
-/*! \brief Free/release a previously allocated RTP socket
- *  \param[in[] rs RTP/RTCP socket to be released
- */
-int rtp_socket_free(struct rtp_socket *rs)
-{
-	DEBUGP(DLMUX, "rtp_socket_free(rs=%p)\n", rs);
-
-	/* make sure we don't leave references dangling to us */
-	if (rs->rx_action == RTP_PROXY &&
-	    rs->proxy.other_sock)
-		rs->proxy.other_sock->proxy.other_sock = NULL;
-
-	osmo_fd_unregister(&rs->rtp.bfd);
-	close(rs->rtp.bfd.fd);
-	free_tx_queue(&rs->rtp);
-
-	osmo_fd_unregister(&rs->rtcp.bfd);
-	close(rs->rtcp.bfd.fd);
-	free_tx_queue(&rs->rtcp);
-
-	talloc_free(rs);
-
-	return 0;
-}
diff --git a/src/libtrau/trau_mux.c b/src/libtrau/trau_mux.c
deleted file mode 100644
index b37c765..0000000
--- a/src/libtrau/trau_mux.c
+++ /dev/null
@@ -1,547 +0,0 @@
-/* Simple TRAU frame reflector to route voice calls */
-
-/* (C) 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/>.
- *
- */
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <openbsc/gsm_data.h>
-#include <osmocom/abis/trau_frame.h>
-#include <openbsc/trau_mux.h>
-#include <osmocom/abis/subchan_demux.h>
-#include <osmocom/abis/e1_input.h>
-#include <openbsc/debug.h>
-#include <osmocom/core/talloc.h>
-#include <openbsc/trau_upqueue.h>
-#include <osmocom/core/crcgen.h>
-#include <openbsc/transaction.h>
-
-/* this corresponds to the bit-lengths of the individual codec
- * parameters as indicated in Table 1.1 of TS 06.10 */
-static const uint8_t gsm_fr_map[] = {
-	6, 6, 5, 5, 4, 4, 3, 3,
-	7, 2, 2, 6, 3, 3, 3, 3,
-	3, 3, 3, 3, 3, 3, 3, 3,
-	3, 7, 2, 2, 6, 3, 3, 3,
-	3, 3, 3, 3, 3, 3, 3, 3,
-	3, 3, 7, 2, 2, 6, 3, 3,
-	3, 3, 3, 3, 3, 3, 3, 3,
-	3, 3, 3, 7, 2, 2, 6, 3,
-	3, 3, 3, 3, 3, 3, 3, 3,
-	3, 3, 3, 3
-};
-
-
-/*
- * EFR TRAU parity
- *
- * g(x) = x^3 + x^1 + 1
- */
-static const struct osmo_crc8gen_code gsm0860_efr_crc3 = {
-	.bits = 3,
-	.poly = 0x3,
-	.init = 0x0,
-	.remainder = 0x7,
-};
-
-/* EFR parity bits */
-static inline void efr_parity_bits_1(ubit_t *check_bits, const ubit_t *d_bits)
-{
-	memcpy(check_bits + 0 , d_bits + 0, 22);
-	memcpy(check_bits + 22 , d_bits + 24, 3);
-	check_bits[25] = d_bits[28];
-}
-
-static inline void efr_parity_bits_2(ubit_t *check_bits, const ubit_t *d_bits)
-{
-	memcpy(check_bits + 0 , d_bits + 42, 10);
-	memcpy(check_bits + 10 , d_bits + 90, 2);
-}
-
-static inline void efr_parity_bits_3(ubit_t *check_bits, const ubit_t *d_bits)
-{
-	memcpy(check_bits + 0 , d_bits + 98, 5);
-	check_bits[5] = d_bits[104];
-	memcpy(check_bits + 6 , d_bits + 143, 2);
-}
-
-static inline void efr_parity_bits_4(ubit_t *check_bits, const ubit_t *d_bits)
-{
-	memcpy(check_bits + 0 , d_bits + 151, 10);
-	memcpy(check_bits + 10 , d_bits + 199, 2);
-}
-
-static inline void efr_parity_bits_5(ubit_t *check_bits, const ubit_t *d_bits)
-{
-	memcpy(check_bits + 0 , d_bits + 207, 5);
-	check_bits[5] = d_bits[213];
-	memcpy(check_bits + 6 , d_bits + 252, 2);
-}
-
-struct map_entry {
-	struct llist_head list;
-	struct gsm_e1_subslot src, dst;
-};
-
-struct upqueue_entry {
-	struct llist_head list;
-	struct gsm_network *net;
-	struct gsm_e1_subslot src;
-	uint32_t callref;
-};
-
-static LLIST_HEAD(ss_map);
-static LLIST_HEAD(ss_upqueue);
-
-void *tall_map_ctx, *tall_upq_ctx;
-
-/* map one particular subslot to another subslot */
-int trau_mux_map(const struct gsm_e1_subslot *src,
-		 const struct gsm_e1_subslot *dst)
-{
-	struct map_entry *me;
-
-	me = talloc(tall_map_ctx, struct map_entry);
-	if (!me) {
-		LOGP(DLMIB, LOGL_FATAL, "Out of memory\n");
-		return -ENOMEM;
-	}
-
-	DEBUGP(DCC, "Setting up TRAU mux map between (e1=%u,ts=%u,ss=%u) "
-		"and (e1=%u,ts=%u,ss=%u)\n",
-		src->e1_nr, src->e1_ts, src->e1_ts_ss,
-		dst->e1_nr, dst->e1_ts, dst->e1_ts_ss);
-
-	/* make sure to get rid of any stale old mappings */
-	trau_mux_unmap(src, 0);
-	trau_mux_unmap(dst, 0);
-
-	memcpy(&me->src, src, sizeof(me->src));
-	memcpy(&me->dst, dst, sizeof(me->dst));
-	llist_add(&me->list, &ss_map);
-
-	return 0;
-}
-
-int trau_mux_map_lchan(const struct gsm_lchan *src,	
-			const struct gsm_lchan *dst)
-{
-	struct gsm_e1_subslot *src_ss, *dst_ss;
-
-	src_ss = &src->ts->e1_link;
-	dst_ss = &dst->ts->e1_link;
-
-	return trau_mux_map(src_ss, dst_ss);
-}
-
-
-/* unmap one particular subslot from another subslot */
-int trau_mux_unmap(const struct gsm_e1_subslot *ss, uint32_t callref)
-{
-	struct map_entry *me, *me2;
-	struct upqueue_entry *ue, *ue2;
-
-	if (ss)
-		llist_for_each_entry_safe(me, me2, &ss_map, list) {
-			if (!memcmp(&me->src, ss, sizeof(*ss)) ||
-			    !memcmp(&me->dst, ss, sizeof(*ss))) {
-				llist_del(&me->list);
-				return 0;
-			}
-		}
-	llist_for_each_entry_safe(ue, ue2, &ss_upqueue, list) {
-		if (ue->callref == callref) {
-			llist_del(&ue->list);
-			return 0;
-		}
-		if (ss && !memcmp(&ue->src, ss, sizeof(*ss))) {
-			llist_del(&ue->list);
-			return 0;
-		}
-	}
-	return -ENOENT;
-}
-
-/* look-up an enty in the TRAU mux map */
-static struct gsm_e1_subslot *
-lookup_trau_mux_map(const struct gsm_e1_subslot *src)
-{
-	struct map_entry *me;
-
-	llist_for_each_entry(me, &ss_map, list) {
-		if (!memcmp(&me->src, src, sizeof(*src)))
-			return &me->dst;
-		if (!memcmp(&me->dst, src, sizeof(*src)))
-			return &me->src;
-	}
-	return NULL;
-}
-
-/* look-up an enty in the TRAU upqueue */
-struct upqueue_entry *
-lookup_trau_upqueue(const struct gsm_e1_subslot *src)
-{
-	struct upqueue_entry *ue;
-
-	llist_for_each_entry(ue, &ss_upqueue, list) {
-		if (!memcmp(&ue->src, src, sizeof(*src)))
-			return ue;
-	}
-	return NULL;
-}
-
-static const uint8_t c_bits_check_fr[] = { 0, 0, 0, 1, 0 };
-static const uint8_t c_bits_check_efr[] = { 1, 1, 0, 1, 0 };
-
-struct msgb *trau_decode_fr(uint32_t callref,
-	const struct decoded_trau_frame *tf)
-{
-	struct msgb *msg;
-	struct gsm_data_frame *frame;
-	unsigned char *data;
-	int i, j, k, l, o;
-
-	msg = msgb_alloc(sizeof(struct gsm_data_frame) + 33,
-				 "GSM-DATA");
-	if (!msg)
-		return NULL;
-
-	frame = (struct gsm_data_frame *)msg->data;
-	memset(frame, 0, sizeof(struct gsm_data_frame));
-	data = frame->data;
-	data[0] = 0xd << 4;
-	/* reassemble d-bits */
-	i = 0; /* counts bits */
-	j = 4; /* counts output bits */
-	k = gsm_fr_map[0]-1; /* current number bit in element */
-	l = 0; /* counts element bits */
-	o = 0; /* offset input bits */
-	while (i < 260) {
-		data[j/8] |= (tf->d_bits[k+o] << (7-(j%8)));
-		/* to avoid out-of-bounds access in gsm_fr_map[++l] */
-		if (i == 259)
-			break;
-		if (--k < 0) {
-			o += gsm_fr_map[l];
-			k = gsm_fr_map[++l]-1;
-		}
-		i++;
-		j++;
-	}
-	if (tf->c_bits[11]) /* BFI */
-		frame->msg_type = GSM_BAD_FRAME;
-	else
-		frame->msg_type = GSM_TCHF_FRAME;
-	frame->callref = callref;
-	msgb_put(msg, sizeof(struct gsm_data_frame) + 33);
-
-	return msg;
-}
-
-struct msgb *trau_decode_efr(uint32_t callref,
-	const struct decoded_trau_frame *tf)
-{
-	struct msgb *msg;
-	struct gsm_data_frame *frame;
-	unsigned char *data;
-	int i, j, rc;
-	ubit_t check_bits[26];
-
-	msg = msgb_alloc(sizeof(struct gsm_data_frame) + 31,
-				 "GSM-DATA");
-	if (!msg)
-		return NULL;
-
-	frame = (struct gsm_data_frame *)msg->data;
-	memset(frame, 0, sizeof(struct gsm_data_frame));
-	frame->msg_type = GSM_TCHF_FRAME_EFR;
-	frame->callref = callref;
-	msgb_put(msg, sizeof(struct gsm_data_frame) + 31);
-
-	if (tf->c_bits[11]) /* BFI */
-		goto bad_frame;
-
-	data = frame->data;
-	data[0] = 0xc << 4;
-	/* reassemble d-bits */
-	for (i = 1, j = 4; i < 39; i++, j++)
-		data[j/8] |= (tf->d_bits[i] << (7-(j%8)));
-	efr_parity_bits_1(check_bits, tf->d_bits);
-	rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 26,
-			tf->d_bits + 39);
-	if (rc)
-		goto bad_frame;
-	for (i = 42, j = 42; i < 95; i++, j++)
-		data[j/8] |= (tf->d_bits[i] << (7-(j%8)));
-	efr_parity_bits_2(check_bits, tf->d_bits);
-	rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 12,
-			tf->d_bits + 95);
-	if (rc)
-		goto bad_frame;
-	for (i = 98, j = 95; i < 148; i++, j++)
-		data[j/8] |= (tf->d_bits[i] << (7-(j%8)));
-	efr_parity_bits_3(check_bits, tf->d_bits);
-	rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 8,
-			tf->d_bits + 148);
-	if (rc)
-		goto bad_frame;
-	for (i = 151, j = 145; i < 204; i++, j++)
-		data[j/8] |= (tf->d_bits[i] << (7-(j%8)));
-	efr_parity_bits_4(check_bits, tf->d_bits);
-	rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 12,
-			tf->d_bits + 204);
-	if (rc)
-		goto bad_frame;
-	for (i = 207, j = 198; i < 257; i++, j++)
-		data[j/8] |= (tf->d_bits[i] << (7-(j%8)));
-	efr_parity_bits_5(check_bits, tf->d_bits);
-	rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 8,
-			tf->d_bits + 257);
-	if (rc)
-		goto bad_frame;
-
-	return msg;
-
-bad_frame:
-	frame->msg_type = GSM_BAD_FRAME;
-
-	return msg;
-}
-
-/* we get called by subchan_demux */
-int trau_mux_input(struct gsm_e1_subslot *src_e1_ss,
-		   const uint8_t *trau_bits, int num_bits)
-{
-	struct decoded_trau_frame tf;
-	uint8_t trau_bits_out[TRAU_FRAME_BITS];
-	struct gsm_e1_subslot *dst_e1_ss = lookup_trau_mux_map(src_e1_ss);
-	struct subch_mux *mx;
-	struct upqueue_entry *ue;
-	int rc;
-
-	/* decode TRAU, change it to downlink, re-encode */
-	rc = decode_trau_frame(&tf, trau_bits);
-	if (rc)
-		return rc;
-
-	if (!dst_e1_ss) {
-		struct msgb *msg = NULL;
-		/* frame shall be sent to upqueue */
-		if (!(ue = lookup_trau_upqueue(src_e1_ss)))
-			return -EINVAL;
-		if (!ue->callref)
-			return -EINVAL;
-		if (!memcmp(tf.c_bits, c_bits_check_fr, 5))
-			msg = trau_decode_fr(ue->callref, &tf);
-		else if (!memcmp(tf.c_bits, c_bits_check_efr, 5))
-			msg = trau_decode_efr(ue->callref, &tf);
-		else {
-			DEBUGPC(DLMUX, "illegal trau (C1-C5) %s\n",
-				osmo_hexdump(tf.c_bits, 5));
-			DEBUGPC(DLMUX, "test trau (C1-C5) %s\n",
-				osmo_hexdump(c_bits_check_efr, 5));
-			return -EINVAL;
-		}
-		if (!msg)
-			return -ENOMEM;
-		trau_tx_to_mncc(ue->net, msg);
-
-		return 0;
-	}
-
-	mx = e1inp_get_mux(dst_e1_ss->e1_nr, dst_e1_ss->e1_ts);
-	if (!mx)
-		return -EINVAL;
-
-	trau_frame_up2down(&tf);
-	encode_trau_frame(trau_bits_out, &tf);
-
-	/* and send it to the muxer */
-	return subchan_mux_enqueue(mx, dst_e1_ss->e1_ts_ss, trau_bits_out,
-				   TRAU_FRAME_BITS);
-}
-
-/* callback when a TRAU frame was received */
-int subch_cb(struct subch_demux *dmx, int ch, uint8_t *data, int len,
-	     void *_priv)
-{
-	struct e1inp_ts *e1i_ts = _priv;
-	struct gsm_e1_subslot src_ss;
-
-	src_ss.e1_nr = e1i_ts->line->num;
-	src_ss.e1_ts = e1i_ts->num;
-	src_ss.e1_ts_ss = ch;
-
-	return trau_mux_input(&src_ss, data, len);
-}
-
-/* add receiver instance for lchan and callref */
-int trau_recv_lchan(struct gsm_lchan *lchan, uint32_t callref)
-{
-	struct gsm_e1_subslot *src_ss;
-	struct upqueue_entry *ue;
-
-	ue = talloc(tall_upq_ctx, struct upqueue_entry);
-	if (!ue)
-		return -ENOMEM;
-
-	src_ss = &lchan->ts->e1_link;
-
-	DEBUGP(DCC, "Setting up TRAU receiver (e1=%u,ts=%u,ss=%u) "
-		"and (callref 0x%x)\n",
-		src_ss->e1_nr, src_ss->e1_ts, src_ss->e1_ts_ss,
-		callref);
-
-	/* make sure to get rid of any stale old mappings */
-	trau_mux_unmap(src_ss, callref);
-
-	memcpy(&ue->src, src_ss, sizeof(ue->src));
-	ue->net = lchan->ts->trx->bts->network;
-	ue->callref = callref;
-	llist_add(&ue->list, &ss_upqueue);
-
-	return 0;
-}
-
-void trau_encode_fr(struct decoded_trau_frame *tf,
-	const unsigned char *data)
-{
-	int i, j, k, l, o;
-
-	/* set c-bits and t-bits */
-	tf->c_bits[0] = 1;
-	tf->c_bits[1] = 1;
-	tf->c_bits[2] = 1;
-	tf->c_bits[3] = 0;
-	tf->c_bits[4] = 0;
-	memset(&tf->c_bits[5], 0, 6);
-	memset(&tf->c_bits[11], 1, 10);
-	memset(&tf->t_bits[0], 1, 4);
-	/* reassemble d-bits */
-	i = 0; /* counts bits */
-	j = 4; /* counts input bits */
-	k = gsm_fr_map[0]-1; /* current number bit in element */
-	l = 0; /* counts element bits */
-	o = 0; /* offset output bits */
-	while (i < 260) {
-		tf->d_bits[k+o] = (data[j/8] >> (7-(j%8))) & 1;
-		/* to avoid out-of-bounds access in gsm_fr_map[++l] */
-		if (i == 259)
-			break;
-		if (--k < 0) {
-			o += gsm_fr_map[l];
-			k = gsm_fr_map[++l]-1;
-		}
-		i++;
-		j++;
-	}
-}
-
-void trau_encode_efr(struct decoded_trau_frame *tf,
-	const unsigned char *data)
-{
-	int i, j;
-	ubit_t check_bits[26];
-
-	/* set c-bits and t-bits */
-	tf->c_bits[0] = 1;
-	tf->c_bits[1] = 1;
-	tf->c_bits[2] = 0;
-	tf->c_bits[3] = 1;
-	tf->c_bits[4] = 0;
-	memset(&tf->c_bits[5], 0, 6);
-	memset(&tf->c_bits[11], 1, 10);
-	memset(&tf->t_bits[0], 1, 4);
-	/* reassemble d-bits */
-	tf->d_bits[0] = 1;
-	for (i = 1, j = 4; i < 39; i++, j++)
-		tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
-	efr_parity_bits_1(check_bits, tf->d_bits);
-	osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 26,
-			tf->d_bits + 39);
-	for (i = 42, j = 42; i < 95; i++, j++)
-		tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
-	efr_parity_bits_2(check_bits, tf->d_bits);
-	osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 12,
-			tf->d_bits + 95);
-	for (i = 98, j = 95; i < 148; i++, j++)
-		tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
-	efr_parity_bits_3(check_bits, tf->d_bits);
-	osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 8,
-			tf->d_bits + 148);
-	for (i = 151, j = 145; i < 204; i++, j++)
-		tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
-	efr_parity_bits_4(check_bits, tf->d_bits);
-	osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 12,
-			tf->d_bits + 204);
-	for (i = 207, j = 198; i < 257; i++, j++)
-		tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
-	efr_parity_bits_5(check_bits, tf->d_bits);
-	osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 8,
-			tf->d_bits + 257);
-}
-
-int trau_send_frame(struct gsm_lchan *lchan, struct gsm_data_frame *frame)
-{
-	uint8_t trau_bits_out[TRAU_FRAME_BITS];
-	struct gsm_e1_subslot *dst_e1_ss = &lchan->ts->e1_link;
-	struct subch_mux *mx;
-	struct decoded_trau_frame tf;
-
-	mx = e1inp_get_mux(dst_e1_ss->e1_nr, dst_e1_ss->e1_ts);
-	if (!mx)
-		return -EINVAL;
-
-	switch (frame->msg_type) {
-	case GSM_TCHF_FRAME:
-		trau_encode_fr(&tf, frame->data);
-		break;
-	case GSM_TCHF_FRAME_EFR:
-		trau_encode_efr(&tf, frame->data);
-		break;
-	default:
-		DEBUGPC(DLMUX, "unsupported message type %d\n",
-			frame->msg_type);
-		return -EINVAL;
-	}
-
-	encode_trau_frame(trau_bits_out, &tf);
-
-	/* and send it to the muxer */
-	return subchan_mux_enqueue(mx, dst_e1_ss->e1_ts_ss, trau_bits_out,
-				   TRAU_FRAME_BITS);
-}
-
-/* switch trau muxer to new lchan */
-int switch_trau_mux(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan)
-{
-	struct gsm_network *net = old_lchan->ts->trx->bts->network;
-	struct gsm_trans *trans;
-
-	/* look up transaction with TCH frame receive enabled */
-	llist_for_each_entry(trans, &net->trans_list, entry) {
-		if (trans->conn && trans->conn->lchan == old_lchan && trans->tch_recv) {
-			/* switch */
-			trau_recv_lchan(new_lchan, trans->callref);
-		}
-	}
-
-	return 0;
-}
diff --git a/src/libtrau/trau_upqueue.c b/src/libtrau/trau_upqueue.c
deleted file mode 100644
index f8edaf0..0000000
--- a/src/libtrau/trau_upqueue.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* trau_upqueue.c - Pass msgb's up the chain */
-
-/* (C) 2010 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/>.
- *
- */
-
-#include <openbsc/mncc.h>
-#include <openbsc/gsm_data.h>
-
-void trau_tx_to_mncc(struct gsm_network *net, struct msgb *msg)
-{
-	net->mncc_recv(net, msg);
-}
diff --git a/src/libvlr/Makefile.am b/src/libvlr/Makefile.am
deleted file mode 100644
index 17ad411..0000000
--- a/src/libvlr/Makefile.am
+++ /dev/null
@@ -1,19 +0,0 @@
-AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) \
-	$(COVERAGE_CFLAGS) $(LIBCRYPTO_CFLAGS)
-
-noinst_HEADERS = \
-	vlr_access_req_fsm.h \
-	vlr_auth_fsm.h \
-	vlr_core.h \
-	vlr_lu_fsm.h \
-	$(NULL)
-
-noinst_LIBRARIES = libvlr.a
-
-libvlr_a_SOURCES = \
-	vlr.c \
-	vlr_access_req_fsm.c \
-	vlr_auth_fsm.c \
-	vlr_lu_fsm.c \
-	$(NULL)
diff --git a/src/libvlr/vlr.c b/src/libvlr/vlr.c
deleted file mode 100644
index d95d1b7..0000000
--- a/src/libvlr/vlr.c
+++ /dev/null
@@ -1,1112 +0,0 @@
-/* Osmocom Visitor Location Register (VLR) code base */
-
-/* (C) 2016 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/>.
- *
- */
-
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/fsm.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
-#include <osmocom/gsm/gsup.h>
-#include <osmocom/gsm/apn.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/gsup_client.h>
-#include <openbsc/vlr.h>
-#include <openbsc/gprs_sgsn.h>
-#include <openbsc/gprs_utils.h>
-#include <openbsc/debug.h>
-
-#include <openssl/rand.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <limits.h>
-
-#include "vlr_core.h"
-#include "vlr_auth_fsm.h"
-#include "vlr_lu_fsm.h"
-#include "vlr_access_req_fsm.h"
-
-#define SGSN_SUBSCR_MAX_RETRIES 3
-#define SGSN_SUBSCR_RETRY_INTERVAL 10
-
-/***********************************************************************
- * Convenience functions
- ***********************************************************************/
-
-const struct value_string vlr_ciph_names[] = {
-	OSMO_VALUE_STRING(VLR_CIPH_NONE),
-	OSMO_VALUE_STRING(VLR_CIPH_A5_1),
-	OSMO_VALUE_STRING(VLR_CIPH_A5_2),
-	OSMO_VALUE_STRING(VLR_CIPH_A5_3),
-	{ 0, NULL }
-};
-
-uint32_t vlr_timer(struct vlr_instance *vlr, uint32_t timer)
-{
-	uint32_t tidx = 0xffffffff;
-
-	switch (timer) {
-	case 3270:
-		tidx = VLR_T_3270;
-		break;
-	case 3260:
-		tidx = VLR_T_3260;
-		break;
-	case 3250:
-		tidx = VLR_T_3250;
-		break;
-	}
-
-	OSMO_ASSERT(tidx < sizeof(vlr->cfg.timer));
-	return vlr->cfg.timer[tidx];
-}
-
-struct vlr_subscr *_vlr_subscr_find_by_imsi(struct vlr_instance *vlr,
-					    const char *imsi,
-					    const char *file, int line)
-{
-	struct vlr_subscr *vsub;
-
-	if (!imsi || !*imsi)
-		return NULL;
-
-	llist_for_each_entry(vsub, &vlr->subscribers, list) {
-		if (vlr_subscr_matches_imsi(vsub, imsi))
-			return _vlr_subscr_get(vsub, file, line);
-	}
-	return NULL;
-}
-
-struct vlr_subscr *_vlr_subscr_find_by_tmsi(struct vlr_instance *vlr,
-					    uint32_t tmsi,
-					    const char *file, int line)
-{
-	struct vlr_subscr *vsub;
-
-	if (tmsi == GSM_RESERVED_TMSI)
-		return NULL;
-
-	llist_for_each_entry(vsub, &vlr->subscribers, list) {
-		if (vlr_subscr_matches_tmsi(vsub, tmsi))
-			return _vlr_subscr_get(vsub, file, line);
-	}
-	return NULL;
-}
-
-struct vlr_subscr *_vlr_subscr_find_by_msisdn(struct vlr_instance *vlr,
-					      const char *msisdn,
-					      const char *file, int line)
-{
-	struct vlr_subscr *vsub;
-
-	if (!msisdn || !*msisdn)
-		return NULL;
-
-	llist_for_each_entry(vsub, &vlr->subscribers, list) {
-		if (vlr_subscr_matches_msisdn(vsub, msisdn))
-			return _vlr_subscr_get(vsub, file, line);
-	}
-	return NULL;
-}
-
-/* Transmit GSUP message to HLR */
-static int vlr_tx_gsup_message(struct vlr_instance *vlr,
-			       struct osmo_gsup_message *gsup_msg)
-{
-	struct msgb *msg = gsup_client_msgb_alloc();
-
-	osmo_gsup_encode(msg, gsup_msg);
-
-	if (!vlr->gsup_client) {
-		LOGP(DVLR, LOGL_NOTICE, "GSUP link is down, cannot "
-			"send GSUP: %s\n", msgb_hexdump(msg));
-		msgb_free(msg);
-		return -ENOTSUP;
-	}
-
-	LOGP(DVLR, LOGL_DEBUG, "GSUP tx: %s\n",
-	     osmo_hexdump_nospc(msg->data, msg->len));
-
-	return gsup_client_send(vlr->gsup_client, msg);
-}
-
-/* Transmit GSUP message for subscriber to HLR, using IMSI from subscriber */
-static int vlr_subscr_tx_gsup_message(struct vlr_subscr *vsub,
-				      struct osmo_gsup_message *gsup_msg)
-{
-	struct vlr_instance *vlr = vsub->vlr;
-
-	if (strlen(gsup_msg->imsi) == 0)
-		osmo_strlcpy(gsup_msg->imsi, vsub->imsi, sizeof(gsup_msg->imsi));
-
-	return vlr_tx_gsup_message(vlr, gsup_msg);
-}
-
-/* Transmit GSUP error in response to original message */
-static int vlr_tx_gsup_error_reply(struct vlr_instance *vlr,
-				   struct osmo_gsup_message *gsup_orig,
-				   enum gsm48_gmm_cause cause)
-{
-	struct osmo_gsup_message gsup_reply = {0};
-
-	osmo_strlcpy(gsup_reply.imsi, gsup_orig->imsi, sizeof(gsup_reply.imsi));
-	gsup_reply.cause = cause;
-	gsup_reply.message_type =
-		OSMO_GSUP_TO_MSGT_ERROR(gsup_orig->message_type);
-
-	return vlr_tx_gsup_message(vlr, &gsup_reply);
-}
-
-struct vlr_subscr *_vlr_subscr_get(struct vlr_subscr *sub, const char *file, int line)
-{
-	if (!sub)
-		return NULL;
-	OSMO_ASSERT(sub->use_count < INT_MAX);
-	sub->use_count++;
-	LOGPSRC(DREF, LOGL_DEBUG, file, line,
-		"VLR subscr %s usage increases to: %d\n",
-		vlr_subscr_name(sub), sub->use_count);
-	return sub;
-}
-
-struct vlr_subscr *_vlr_subscr_put(struct vlr_subscr *sub, const char *file, int line)
-{
-	if (!sub)
-		return NULL;
-	sub->use_count--;
-	LOGPSRC(DREF, sub->use_count >= 0? LOGL_DEBUG : LOGL_ERROR,
-		file, line,
-		"VLR subscr %s usage decreases to: %d\n",
-		vlr_subscr_name(sub), sub->use_count);
-	if (sub->use_count <= 0)
-		vlr_subscr_free(sub);
-	return NULL;
-}
-
-/* Allocate a new subscriber and insert it into list */
-static struct vlr_subscr *_vlr_subscr_alloc(struct vlr_instance *vlr)
-{
-	struct vlr_subscr *vsub;
-	int i;
-
-	vsub = talloc_zero(vlr, struct vlr_subscr);
-	vsub->vlr = vlr;
-	vsub->tmsi = GSM_RESERVED_TMSI;
-	vsub->tmsi_new = GSM_RESERVED_TMSI;
-
-	for (i = 0; i < ARRAY_SIZE(vsub->auth_tuples); i++)
-		vsub->auth_tuples[i].key_seq = GSM_KEY_SEQ_INVAL;
-
-	INIT_LLIST_HEAD(&vsub->cs.requests);
-	INIT_LLIST_HEAD(&vsub->ps.pdp_list);
-
-	llist_add_tail(&vsub->list, &vlr->subscribers);
-	return vsub;
-}
-
-struct vlr_subscr *vlr_subscr_alloc(struct vlr_instance *vlr)
-{
-	return vlr_subscr_get(_vlr_subscr_alloc(vlr));
-}
-
-/* Send a GSUP Purge MS request.
- * TODO: this should be sent to the *previous* VLR when this VLR is "taking"
- * this subscriber, not to the HLR? */
-int vlr_subscr_purge(struct vlr_subscr *vsub)
-{
-	struct osmo_gsup_message gsup_msg = {0};
-
-	gsup_msg.message_type = OSMO_GSUP_MSGT_PURGE_MS_REQUEST;
-
-	/* provide HLR number in case we know it */
-	gsup_msg.hlr_enc_len = vsub->hlr.len;
-	gsup_msg.hlr_enc = vsub->hlr.buf;
-
-	return vlr_subscr_tx_gsup_message(vsub, &gsup_msg);
-}
-
-void vlr_subscr_cancel(struct vlr_subscr *vsub, enum gsm48_gmm_cause cause)
-{
-	if (!vsub)
-		return;
-
-	if (vsub->lu_fsm) {
-		if (vsub->lu_fsm->state == VLR_ULA_S_WAIT_HLR_UPD)
-			osmo_fsm_inst_dispatch(vsub->lu_fsm,
-					       VLR_ULA_E_HLR_LU_RES,
-					       (void*)&cause);
-		else
-			osmo_fsm_inst_term(vsub->lu_fsm, OSMO_FSM_TERM_ERROR,
-					   0);
-	}
-
-	if (vsub->proc_arq_fsm)
-		osmo_fsm_inst_term(vsub->proc_arq_fsm, OSMO_FSM_TERM_ERROR, 0);
-}
-
-/* Call vlr_subscr_cancel(), then completely drop the entry from the VLR */
-void vlr_subscr_free(struct vlr_subscr *vsub)
-{
-	llist_del(&vsub->list);
-	DEBUGP(DREF, "freeing VLR subscr %s\n", vlr_subscr_name(vsub));
-	talloc_free(vsub);
-}
-
-/* Generate a new TMSI and store in vsub->tmsi_new.
- * Search all known subscribers to ensure that the TMSI is unique. */
-int vlr_subscr_alloc_tmsi(struct vlr_subscr *vsub)
-{
-	struct vlr_instance *vlr = vsub->vlr;
-	uint32_t tmsi;
-	int tried;
-
-	for (tried = 0; tried < 100; tried++) {
-		if (RAND_bytes((uint8_t *) &tmsi, sizeof(tmsi)) != 1) {
-			LOGP(DVLR, LOGL_ERROR, "RAND_bytes failed\n");
-			return -1;
-		}
-		/* throw the dice again, if the TSMI doesn't fit */
-		if (tmsi == GSM_RESERVED_TMSI)
-			continue;
-
-		/* Section 2.4 of 23.003: MSC has two MSB 00/01/10, SGSN 11 */
-		if (vlr->cfg.is_ps) {
-			/* SGSN */
-			tmsi |= 0xC000000;
-		} else {
-			/* MSC */
-			if ((tmsi & 0xC0000000) == 0xC0000000)
-				tmsi &= ~0xC0000000;
-		}
-
-		/* If this TMSI is already in use, try another one. */
-		if (vlr_subscr_find_by_tmsi(vlr, tmsi))
-			continue;
-
-		vsub->tmsi_new = tmsi;
-		return 0;
-	}
-
-	LOGP(DVLR, LOGL_ERROR, "subscr %s: unable to generate valid TMSI"
-	     " after %d tries\n", vlr_subscr_name(vsub), tried);
-	return -1;
-}
-
-/* Find subscriber by IMSI, or create new subscriber if not found.
- * \param[in] vlr  VLR instace.
- * \param[in] imsi  IMSI string.
- * \param[out] created  if non-NULL, returns whether a new entry was created. */
-struct vlr_subscr *_vlr_subscr_find_or_create_by_imsi(struct vlr_instance *vlr,
-						      const char *imsi,
-						      bool *created,
-						      const char *file,
-						      int line)
-{
-	struct vlr_subscr *vsub;
-	vsub = _vlr_subscr_find_by_imsi(vlr, imsi, file, line);
-	if (vsub) {
-		if (created)
-			*created = false;
-		return vsub;
-	}
-
-	vsub = _vlr_subscr_get(_vlr_subscr_alloc(vlr), file, line);
-	if (!vsub)
-		return NULL;
-	vlr_subscr_set_imsi(vsub, imsi);
-	LOGP(DVLR, LOGL_INFO, "New subscr, IMSI: %s\n", vsub->imsi);
-	if (created)
-		*created = true;
-	return vsub;
-}
-
-/* Find subscriber by TMSI, or create new subscriber if not found.
- * \param[in] vlr  VLR instace.
- * \param[in] tmsi  TMSI.
- * \param[out] created  if non-NULL, returns whether a new entry was created. */
-struct vlr_subscr *_vlr_subscr_find_or_create_by_tmsi(struct vlr_instance *vlr,
-						      uint32_t tmsi,
-						      bool *created,
-						      const char *file,
-						      int line)
-{
-	struct vlr_subscr *vsub;
-	vsub = _vlr_subscr_find_by_tmsi(vlr, tmsi, file, line);
-	if (vsub) {
-		if (created)
-			*created = false;
-		return vsub;
-	}
-
-	vsub = _vlr_subscr_get(_vlr_subscr_alloc(vlr), file, line);
-	if (!vsub)
-		return NULL;
-	vsub->tmsi = tmsi;
-	LOGP(DVLR, LOGL_INFO, "New subscr, TMSI: 0x%08x\n", vsub->tmsi);
-	if (created)
-		*created = true;
-	return vsub;
-}
-
-void vlr_subscr_set_imsi(struct vlr_subscr *vsub, const char *imsi)
-{
-	if (!vsub)
-		return;
-	osmo_strlcpy(vsub->imsi, imsi, sizeof(vsub->imsi));
-	vsub->id = atoll(vsub->imsi);
-	DEBUGP(DVLR, "set IMSI on subscriber; IMSI=%s id=%llu\n",
-	       vsub->imsi, vsub->id);
-}
-
-void vlr_subscr_set_imei(struct vlr_subscr *vsub, const char *imei)
-{
-	if (!vsub)
-		return;
-	osmo_strlcpy(vsub->imei, imei, sizeof(vsub->imei));
-	DEBUGP(DVLR, "set IMEI on subscriber; IMSI=%s IMEI=%s\n",
-	       vsub->imsi, vsub->imei);
-}
-
-void vlr_subscr_set_imeisv(struct vlr_subscr *vsub, const char *imeisv)
-{
-	if (!vsub)
-		return;
-	osmo_strlcpy(vsub->imeisv, imeisv, sizeof(vsub->imeisv));
-	DEBUGP(DVLR, "set IMEISV on subscriber; IMSI=%s IMEISV=%s\n",
-	       vsub->imsi, vsub->imeisv);
-}
-
-/* Safely copy the given MSISDN string to vsub->msisdn */
-void vlr_subscr_set_msisdn(struct vlr_subscr *vsub, const char *msisdn)
-{
-	if (!vsub)
-		return;
-	osmo_strlcpy(vsub->msisdn, msisdn, sizeof(vsub->msisdn));
-	DEBUGP(DVLR, "set MSISDN on subscriber; IMSI=%s MSISDN=%s\n",
-	       vsub->imsi, vsub->msisdn);
-}
-
-bool vlr_subscr_matches_imsi(struct vlr_subscr *vsub, const char *imsi)
-{
-	return vsub && imsi && vsub->imsi[0] && !strcmp(vsub->imsi, imsi);
-}
-
-bool vlr_subscr_matches_tmsi(struct vlr_subscr *vsub, uint32_t tmsi)
-{
-	return vsub && tmsi != GSM_RESERVED_TMSI
-		&& (vsub->tmsi == tmsi || vsub->tmsi_new == tmsi);
-}
-
-bool vlr_subscr_matches_msisdn(struct vlr_subscr *vsub, const char *msisdn)
-{
-	return vsub && msisdn && vsub->msisdn[0]
-		&& !strcmp(vsub->msisdn, msisdn);
-}
-
-bool vlr_subscr_matches_imei(struct vlr_subscr *vsub, const char *imei)
-{
-	return vsub && imei && vsub->imei[0]
-		&& !strcmp(vsub->imei, imei);
-}
-
-/* Send updated subscriber information to HLR */
-int vlr_subscr_changed(struct vlr_subscr *vsub)
-{
-	/* FIXME */
-	LOGP(DVLR, LOGL_ERROR, "Not implemented: %s\n", __func__);
-	return 0;
-}
-
-/***********************************************************************
- * PDP context data
- ***********************************************************************/
-
-struct sgsn_subscriber_pdp_data *
-vlr_subscr_pdp_data_alloc(struct vlr_subscr *vsub)
-{
-	struct sgsn_subscriber_pdp_data* pdata;
-
-	pdata = talloc_zero(vsub, struct sgsn_subscriber_pdp_data);
-
-	llist_add_tail(&pdata->list, &vsub->ps.pdp_list);
-
-	return pdata;
-}
-
-static int vlr_subscr_pdp_data_clear(struct vlr_subscr *vsub)
-{
-	struct sgsn_subscriber_pdp_data *pdp, *pdp2;
-	int count = 0;
-
-	llist_for_each_entry_safe(pdp, pdp2, &vsub->ps.pdp_list, list) {
-		llist_del(&pdp->list);
-		talloc_free(pdp);
-		count += 1;
-	}
-
-	return count;
-}
-
-static struct sgsn_subscriber_pdp_data *
-vlr_subscr_pdp_data_get_by_id(struct vlr_subscr *vsub, unsigned context_id)
-{
-	struct sgsn_subscriber_pdp_data *pdp;
-
-	llist_for_each_entry(pdp, &vsub->ps.pdp_list, list) {
-		if (pdp->context_id == context_id)
-			return pdp;
-	}
-
-	return NULL;
-}
-
-/***********************************************************************
- * Actual Implementation
- ***********************************************************************/
-
-static int vlr_rx_gsup_unknown_imsi(struct vlr_instance *vlr,
-				   struct osmo_gsup_message *gsup_msg)
-{
-	if (OSMO_GSUP_IS_MSGT_REQUEST(gsup_msg->message_type)) {
-		vlr_tx_gsup_error_reply(vlr, gsup_msg,
-					GMM_CAUSE_IMSI_UNKNOWN);
-		LOGP(DVLR, LOGL_NOTICE,
-		     "Unknown IMSI %s, discarding GSUP request "
-		     "of type 0x%02x\n",
-		     gsup_msg->imsi, gsup_msg->message_type);
-	} else if (OSMO_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) {
-		LOGP(DVLR, LOGL_NOTICE,
-		     "Unknown IMSI %s, discarding GSUP error "
-		     "of type 0x%02x, cause '%s' (%d)\n",
-		     gsup_msg->imsi, gsup_msg->message_type,
-		     get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
-		     gsup_msg->cause);
-	} else {
-		LOGP(DVLR, LOGL_NOTICE,
-		     "Unknown IMSI %s, discarding GSUP response "
-		     "of type 0x%02x\n",
-		     gsup_msg->imsi, gsup_msg->message_type);
-	}
-
-	return -GMM_CAUSE_IMSI_UNKNOWN;
-}
-
-static int vlr_rx_gsup_purge_no_subscr(struct vlr_instance *vlr,
-				struct osmo_gsup_message *gsup_msg)
-{
-	if (OSMO_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) {
-		LOGGSUPP(LOGL_NOTICE, gsup_msg,
-			 "Purge MS has failed with cause '%s' (%d)\n",
-			 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
-			 gsup_msg->cause);
-		return -gsup_msg->cause;
-	}
-	LOGGSUPP(LOGL_INFO, gsup_msg, "Completing purge MS\n");
-	return 0;
-}
-
-/* VLR internal call to request UpdateLocation from HLR */
-int vlr_subscr_req_lu(struct vlr_subscr *vsub, bool is_ps)
-{
-	struct osmo_gsup_message gsup_msg = {0};
-	int rc;
-
-	gsup_msg.message_type = OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST;
-	rc = vlr_subscr_tx_gsup_message(vsub, &gsup_msg);
-
-	return rc;
-}
-
-/* VLR internal call to request tuples from HLR */
-int vlr_subscr_req_sai(struct vlr_subscr *vsub,
-		       const uint8_t *auts, const uint8_t *auts_rand)
-{
-	struct osmo_gsup_message gsup_msg = {0};
-
-	gsup_msg.message_type = OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST;
-	gsup_msg.auts = auts;
-	gsup_msg.rand = auts_rand;
-
-	return vlr_subscr_tx_gsup_message(vsub, &gsup_msg);
-}
-
-/* Tell HLR that authentication failure occurred */
-int vlr_subscr_tx_auth_fail_rep(struct vlr_subscr *vsub)
-{
-	struct osmo_gsup_message gsup_msg = {0};
-
-	gsup_msg.message_type = OSMO_GSUP_MSGT_AUTH_FAIL_REPORT;
-	osmo_strlcpy(gsup_msg.imsi, vsub->imsi, sizeof(gsup_msg.imsi));
-	return vlr_tx_gsup_message(vsub->vlr, &gsup_msg);
-}
-
-/* Update the subscriber with GSUP-received auth tuples */
-void vlr_subscr_update_tuples(struct vlr_subscr *vsub,
-			      const struct osmo_gsup_message *gsup)
-{
-	unsigned int i;
-	unsigned int got_tuples;
-
-	if (gsup->num_auth_vectors) {
-		memset(&vsub->auth_tuples, 0, sizeof(vsub->auth_tuples));
-		for (i = 0; i < ARRAY_SIZE(vsub->auth_tuples); i++)
-			vsub->auth_tuples[i].key_seq = GSM_KEY_SEQ_INVAL;
-	}
-
-	got_tuples = 0;
-	for (i = 0; i < gsup->num_auth_vectors; i++) {
-		size_t key_seq = i;
-
-		if (key_seq >= ARRAY_SIZE(vsub->auth_tuples)) {
-			LOGVSUBP(LOGL_NOTICE, vsub,
-				"Skipping auth tuple wih invalid cksn %zu\n",
-				key_seq);
-			continue;
-		}
-		vsub->auth_tuples[i].vec = gsup->auth_vectors[i];
-		vsub->auth_tuples[i].key_seq = key_seq;
-		got_tuples ++;
-	}
-
-	LOGVSUBP(LOGL_DEBUG, vsub, "Received %u auth tuples\n", got_tuples);
-
-	if (!got_tuples) {
-		/* FIXME what now? */
-		// vlr_subscr_cancel(vsub, GMM_CAUSE_GSM_AUTH_UNACCEPT); ?
-	}
-
-	/* New tuples means last_tuple becomes invalid */
-	vsub->last_tuple = NULL;
-}
-
-/* Handle SendAuthInfo Result/Error from HLR */
-static int vlr_subscr_handle_sai_res(struct vlr_subscr *vsub,
-				     const struct osmo_gsup_message *gsup)
-{
-	struct osmo_fsm_inst *auth_fi = vsub->auth_fsm;
-	void *data = (void *) gsup;
-
-	switch (gsup->message_type) {
-	case OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT:
-		osmo_fsm_inst_dispatch(auth_fi, VLR_AUTH_E_HLR_SAI_ACK, data);
-		break;
-	case OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR:
-		osmo_fsm_inst_dispatch(auth_fi, VLR_AUTH_E_HLR_SAI_NACK, data);
-		break;
-	default:
-		return -1;
-	}
-
-	return 0;
-}
-
-static int decode_bcd_number_safe(char *output, int output_len,
-				  const uint8_t *bcd_lv, int input_len,
-				  int h_len)
-{
-	uint8_t len;
-	OSMO_ASSERT(output_len >= 1);
-	*output = '\0';
-	if (input_len < 1)
-		return -EIO;
-	len = bcd_lv[0];
-	if (input_len < len)
-		return -EIO;
-	return gsm48_decode_bcd_number(output, output_len, bcd_lv, h_len);
-}
-
-static void vlr_subscr_gsup_insert_data(struct vlr_subscr *vsub,
-					const struct osmo_gsup_message *gsup_msg)
-{
-	unsigned idx;
-	int rc;
-
-	if (gsup_msg->msisdn_enc) {
-		decode_bcd_number_safe(vsub->msisdn, sizeof(vsub->msisdn),
-				       gsup_msg->msisdn_enc,
-				       gsup_msg->msisdn_enc_len, 0);
-		LOGP(DVLR, LOGL_DEBUG, "IMSI:%s has MSISDN:%s\n",
-		     vsub->imsi, vsub->msisdn);
-	}
-
-	if (gsup_msg->hlr_enc) {
-		if (gsup_msg->hlr_enc_len > sizeof(vsub->hlr.buf)) {
-			LOGP(DVLR, LOGL_ERROR, "HLR-Number too long (%zu)\n",
-				gsup_msg->hlr_enc_len);
-			vsub->hlr.len = 0;
-		} else {
-			memcpy(vsub->hlr.buf, gsup_msg->hlr_enc,
-				gsup_msg->hlr_enc_len);
-			vsub->hlr.len = gsup_msg->hlr_enc_len;
-		}
-	}
-
-	if (gsup_msg->pdp_info_compl) {
-		rc = vlr_subscr_pdp_data_clear(vsub);
-		if (rc > 0)
-			LOGP(DVLR, LOGL_INFO, "Cleared existing PDP info\n");
-	}
-
-	for (idx = 0; idx < gsup_msg->num_pdp_infos; idx++) {
-		const struct osmo_gsup_pdp_info *pdp_info = &gsup_msg->pdp_infos[idx];
-		size_t ctx_id = pdp_info->context_id;
-		struct sgsn_subscriber_pdp_data *pdp_data;
-
-		if (pdp_info->apn_enc_len >= sizeof(pdp_data->apn_str)-1) {
-			LOGVSUBP(LOGL_ERROR, vsub,
-			     "APN too long, context id = %zu, APN = %s\n",
-			     ctx_id, osmo_hexdump(pdp_info->apn_enc,
-						  pdp_info->apn_enc_len));
-			continue;
-		}
-
-		if (pdp_info->qos_enc_len > sizeof(pdp_data->qos_subscribed)) {
-			LOGVSUBP(LOGL_ERROR, vsub,
-				"QoS info too long (%zu)\n",
-				pdp_info->qos_enc_len);
-			continue;
-		}
-
-		LOGVSUBP(LOGL_INFO, vsub,
-		     "Will set PDP info, context id = %zu, APN = %s\n",
-		     ctx_id, osmo_hexdump(pdp_info->apn_enc, pdp_info->apn_enc_len));
-
-		/* Set PDP info [ctx_id] */
-		pdp_data = vlr_subscr_pdp_data_get_by_id(vsub, ctx_id);
-		if (!pdp_data) {
-			pdp_data = vlr_subscr_pdp_data_alloc(vsub);
-			pdp_data->context_id = ctx_id;
-		}
-
-		OSMO_ASSERT(pdp_data != NULL);
-		pdp_data->pdp_type = pdp_info->pdp_type;
-		osmo_apn_to_str(pdp_data->apn_str,
-				pdp_info->apn_enc, pdp_info->apn_enc_len);
-		memcpy(pdp_data->qos_subscribed, pdp_info->qos_enc, pdp_info->qos_enc_len);
-		pdp_data->qos_subscribed_len = pdp_info->qos_enc_len;
-	}
-}
-
-
-/* Handle InsertSubscrData Result from HLR */
-static int vlr_subscr_handle_isd_req(struct vlr_subscr *vsub,
-				     const struct osmo_gsup_message *gsup)
-{
-	struct osmo_gsup_message gsup_reply = {0};
-
-	vlr_subscr_gsup_insert_data(vsub, gsup);
-	vsub->vlr->ops.subscr_update(vsub);
-
-	gsup_reply.message_type = OSMO_GSUP_MSGT_INSERT_DATA_RESULT;
-	return vlr_subscr_tx_gsup_message(vsub, &gsup_reply);
-}
-
-/* Handle UpdateLocation Result from HLR */
-static int vlr_subscr_handle_lu_res(struct vlr_subscr *vsub,
-				    const struct osmo_gsup_message *gsup)
-{
-	if (!vsub->lu_fsm) {
-		LOGVSUBP(LOGL_ERROR, vsub, "Rx GSUP LU Result "
-			 "without LU in progress\n");
-		return -ENODEV;
-	}
-
-	/* contrary to MAP, we allow piggy-backing subscriber data onto the
-	 * UPDATE LOCATION RESULT, and don't mandate the use of a separate
-	 * nested INSERT SUBSCRIBER DATA transaction */
-	vlr_subscr_gsup_insert_data(vsub, gsup);
-
-	osmo_fsm_inst_dispatch(vsub->lu_fsm, VLR_ULA_E_HLR_LU_RES, NULL);
-
-	return 0;
-}
-
-/* Handle UpdateLocation Result from HLR */
-static int vlr_subscr_handle_lu_err(struct vlr_subscr *vsub,
-				    const struct osmo_gsup_message *gsup)
-{
-	if (!vsub->lu_fsm) {
-		LOGVSUBP(LOGL_ERROR, vsub, "Rx GSUP LU Error "
-			 "without LU in progress\n");
-		return -ENODEV;
-	}
-
-	LOGVSUBP(LOGL_DEBUG, vsub, "UpdateLocation failed; gmm_cause: %s\n",
-		 get_value_string(gsm48_gmm_cause_names, gsup->cause));
-
-	osmo_fsm_inst_dispatch(vsub->lu_fsm, VLR_ULA_E_HLR_LU_RES,
-				(void *)&gsup->cause);
-
-	return 0;
-}
-
-/* Handle LOCATION CANCEL request from HLR */
-static int vlr_subscr_handle_cancel_req(struct vlr_subscr *vsub,
-					struct osmo_gsup_message *gsup_msg)
-{
-	struct osmo_gsup_message gsup_reply = {0};
-	int is_update_procedure = !gsup_msg->cancel_type ||
-		gsup_msg->cancel_type == OSMO_GSUP_CANCEL_TYPE_UPDATE;
-
-	LOGVSUBP(LOGL_INFO, vsub, "Cancelling MS subscriber (%s)\n",
-		 is_update_procedure ?
-		 "update procedure" : "subscription withdraw");
-
-	gsup_reply.message_type = OSMO_GSUP_MSGT_LOCATION_CANCEL_RESULT;
-	vlr_subscr_tx_gsup_message(vsub, &gsup_reply);
-
-	vlr_subscr_cancel(vsub, gsup_msg->cause);
-
-	return 0;
-}
-
-/* Incoming handler for GSUP from HLR.
- * Keep this function non-static for direct invocation by unit tests. */
-int vlr_gsupc_read_cb(struct gsup_client *gsupc, struct msgb *msg)
-{
-	struct vlr_instance *vlr = (struct vlr_instance *) gsupc->data;
-	struct vlr_subscr *vsub;
-	struct osmo_gsup_message gsup;
-	int rc;
-
-	DEBUGP(DVLR, "GSUP rx %u: %s\n", msgb_l2len(msg),
-	       osmo_hexdump_nospc(msgb_l2(msg), msgb_l2len(msg)));
-
-	rc = osmo_gsup_decode(msgb_l2(msg), msgb_l2len(msg), &gsup);
-	if (rc < 0) {
-		LOGP(DVLR, LOGL_ERROR,
-			"decoding GSUP message fails with error '%s' (%d)\n",
-			get_value_string(gsm48_gmm_cause_names, -rc), -rc);
-		return rc;
-	}
-
-	if (!gsup.imsi[0]) {
-		LOGP(DVLR, LOGL_ERROR, "Missing IMSI in GSUP message\n");
-		if (OSMO_GSUP_IS_MSGT_REQUEST(gsup.message_type))
-			vlr_tx_gsup_error_reply(vlr, &gsup,
-						GMM_CAUSE_INV_MAND_INFO);
-		return -GMM_CAUSE_INV_MAND_INFO;
-	}
-
-	vsub = vlr_subscr_find_by_imsi(vlr, gsup.imsi);
-	if (!vsub) {
-		switch (gsup.message_type) {
-		case OSMO_GSUP_MSGT_PURGE_MS_RESULT:
-		case OSMO_GSUP_MSGT_PURGE_MS_ERROR:
-			return vlr_rx_gsup_purge_no_subscr(vlr, &gsup);
-		default:
-			return vlr_rx_gsup_unknown_imsi(vlr, &gsup);
-		}
-	}
-
-	switch (gsup.message_type) {
-	case OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT:
-	case OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR:
-		rc = vlr_subscr_handle_sai_res(vsub, &gsup);
-		break;
-	case OSMO_GSUP_MSGT_INSERT_DATA_REQUEST:
-		rc = vlr_subscr_handle_isd_req(vsub, &gsup);
-		break;
-	case OSMO_GSUP_MSGT_LOCATION_CANCEL_REQUEST:
-		rc = vlr_subscr_handle_cancel_req(vsub, &gsup);
-		break;
-	case OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT:
-		rc = vlr_subscr_handle_lu_res(vsub, &gsup);
-		break;
-	case OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR:
-		rc = vlr_subscr_handle_lu_err(vsub, &gsup);
-		break;
-	case OSMO_GSUP_MSGT_PURGE_MS_ERROR:
-	case OSMO_GSUP_MSGT_PURGE_MS_RESULT:
-	case OSMO_GSUP_MSGT_DELETE_DATA_REQUEST:
-		LOGVSUBP(LOGL_ERROR, vsub,
-			"Rx GSUP msg_type=%d not yet implemented\n",
-			gsup.message_type);
-		rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
-		break;
-	default:
-		LOGVSUBP(LOGL_ERROR, vsub,
-			"Rx GSUP msg_type=%d not valid at VLR/SGSN side\n",
-			gsup.message_type);
-		rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
-		break;
-	}
-
-	vlr_subscr_put(vsub);
-	return rc;
-}
-
-/* MSC->VLR: Subscriber has provided IDENTITY RESPONSE */
-int vlr_subscr_rx_id_resp(struct vlr_subscr *vsub,
-			  const uint8_t *mi, size_t mi_len)
-{
-	char mi_string[GSM48_MI_SIZE];
-	uint8_t mi_type = mi[0] & GSM_MI_TYPE_MASK;
-
-	gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
-
-	/* update the vlr_subscr with the given identity */
-	switch (mi_type) {
-	case GSM_MI_TYPE_IMSI:
-		if (vsub->imsi[0]
-		    && !vlr_subscr_matches_imsi(vsub, mi_string)) {
-			LOGVSUBP(LOGL_ERROR, vsub, "IMSI in ID RESP differs:"
-				 " %s\n", mi_string);
-		} else
-			vlr_subscr_set_imsi(vsub, mi_string);
-		break;
-	case GSM_MI_TYPE_IMEI:
-		vlr_subscr_set_imei(vsub, mi_string);
-		break;
-	case GSM_MI_TYPE_IMEISV:
-		vlr_subscr_set_imeisv(vsub, mi_string);
-		break;
-	}
-
-	if (vsub->auth_fsm) {
-		switch (mi_type) {
-		case GSM_MI_TYPE_IMSI:
-			osmo_fsm_inst_dispatch(vsub->auth_fsm,
-					VLR_AUTH_E_MS_ID_IMSI, mi_string);
-			break;
-		}
-	}
-
-	if (vsub->lu_fsm) {
-		uint32_t event = 0;
-		switch (mi_type) {
-		case GSM_MI_TYPE_IMSI:
-			event = VLR_ULA_E_ID_IMSI;
-			break;
-		case GSM_MI_TYPE_IMEI:
-			event = VLR_ULA_E_ID_IMEI;
-			break;
-		case GSM_MI_TYPE_IMEISV:
-			event = VLR_ULA_E_ID_IMEISV;
-			break;
-		default:
-			OSMO_ASSERT(0);
-			break;
-		}
-		osmo_fsm_inst_dispatch(vsub->lu_fsm, event, mi_string);
-	} else {
-		LOGVSUBP(LOGL_NOTICE,  vsub, "gratuitous ID RESPONSE?!?\n");
-	}
-
-	return 0;
-}
-
-/* MSC->VLR: Subscriber has provided IDENTITY RESPONSE */
-int vlr_subscr_rx_tmsi_reall_compl(struct vlr_subscr *vsub)
-{
-	if (vsub->lu_fsm) {
-		return osmo_fsm_inst_dispatch(vsub->lu_fsm,
-					      VLR_ULA_E_NEW_TMSI_ACK, NULL);
-	} else if (vsub->proc_arq_fsm) {
-		return osmo_fsm_inst_dispatch(vsub->proc_arq_fsm,
-					      PR_ARQ_E_TMSI_ACK, NULL);
-	} else {
-		LOGVSUBP(LOGL_NOTICE, vsub,
-			 "gratuitous TMSI REALLOC COMPL");
-		return -EINVAL;
-	}
-}
-
-int vlr_subscr_rx_imsi_detach(struct vlr_subscr *vsub)
-{
-	/* paranoia: should any LU or PARQ FSMs still be running, stop them. */
-	vlr_subscr_cancel(vsub, GMM_CAUSE_IMPL_DETACHED);
-
-	vsub->imsi_detached_flag = true;
-	if (vsub->lu_complete) {
-		vsub->lu_complete = false;
-		/* balancing the get from vlr_lu_compl_fsm_success() */
-		vlr_subscr_put(vsub);
-	}
-	return 0;
-}
-
-/* Tear down any running FSMs due to MSC connection timeout.
- * Visit all vsub->*_fsm pointers and give them a queue to send a final reject
- * message before the entire connection is torn down.
- * \param[in] vsub  subscriber to tear down
- */
-void vlr_subscr_conn_timeout(struct vlr_subscr *vsub)
-{
-	if (!vsub)
-		return;
-
-	vlr_loc_update_conn_timeout(vsub->lu_fsm);
-	vlr_parq_conn_timeout(vsub->proc_arq_fsm);
-}
-
-struct vlr_instance *vlr_alloc(void *ctx, const struct vlr_ops *ops)
-{
-	struct vlr_instance *vlr = talloc_zero(ctx, struct vlr_instance);
-	OSMO_ASSERT(vlr);
-
-	/* Some of these are needed only on UTRAN, but in case the caller wants
-	 * only GERAN, she should just provide dummy callbacks. */
-	OSMO_ASSERT(ops->tx_auth_req);
-	OSMO_ASSERT(ops->tx_auth_rej);
-	OSMO_ASSERT(ops->tx_id_req);
-	OSMO_ASSERT(ops->tx_lu_acc);
-	OSMO_ASSERT(ops->tx_lu_rej);
-	OSMO_ASSERT(ops->tx_cm_serv_acc);
-	OSMO_ASSERT(ops->tx_cm_serv_rej);
-	OSMO_ASSERT(ops->set_ciph_mode);
-	OSMO_ASSERT(ops->tx_common_id);
-	OSMO_ASSERT(ops->subscr_update);
-	OSMO_ASSERT(ops->subscr_assoc);
-
-	INIT_LLIST_HEAD(&vlr->subscribers);
-	INIT_LLIST_HEAD(&vlr->operations);
-	memcpy(&vlr->ops, ops, sizeof(vlr->ops));
-
-	/* osmo_auth_fsm.c */
-	osmo_fsm_register(&vlr_auth_fsm);
-	/* osmo_lu_fsm.c */
-	vlr_lu_fsm_init();
-	/* vlr_access_request_fsm.c */
-	vlr_parq_fsm_init();
-
-	return vlr;
-}
-
-int vlr_start(const char *gsup_unit_name, struct vlr_instance *vlr,
-	      const char *gsup_server_addr_str, uint16_t gsup_server_port)
-{
-	OSMO_ASSERT(vlr);
-
-	vlr->gsup_client = gsup_client_create(gsup_unit_name,
-					      gsup_server_addr_str,
-					      gsup_server_port,
-					      &vlr_gsupc_read_cb, NULL);
-	if (!vlr->gsup_client)
-		return -ENOMEM;
-	vlr->gsup_client->data = vlr;
-
-	return 0;
-}
-
-/* MSC->VLR: Subscribre has disconnected */
-int vlr_subscr_disconnected(struct vlr_subscr *vsub)
-{
-	/* This corresponds to a MAP-ABORT from MSC->VLR on a classic B
-	 * interface */
-	osmo_fsm_inst_term(vsub->lu_fsm, OSMO_FSM_TERM_REQUEST, NULL);
-	osmo_fsm_inst_term(vsub->auth_fsm, OSMO_FSM_TERM_REQUEST, NULL);
-	vsub->msc_conn_ref = NULL;
-
-	return 0;
-}
-
-/* MSC->VLR: Receive Authentication Failure from Subscriber */
-int vlr_subscr_rx_auth_fail(struct vlr_subscr *vsub, const uint8_t *auts)
-{
-	struct vlr_auth_resp_par par = {0};
-	par.auts = auts;
-
-	osmo_fsm_inst_dispatch(vsub->auth_fsm, VLR_AUTH_E_MS_AUTH_FAIL, &par);
-	return 0;
-}
-
-/* MSC->VLR: Receive Authentication Response from MS
- * \returns 1 in case of success, 0 in case of delay, -1 on auth error */
-int vlr_subscr_rx_auth_resp(struct vlr_subscr *vsub, bool is_r99,
-			 bool is_utran, const uint8_t *res, uint8_t res_len)
-{
-	struct osmo_fsm_inst *auth_fi = vsub->auth_fsm;
-	struct vlr_auth_resp_par par;
-
-	par.is_r99 = is_r99;
-	par.is_utran = is_utran;
-	par.res = res;
-	par.res_len = res_len;
-	osmo_fsm_inst_dispatch(auth_fi, VLR_AUTH_E_MS_AUTH_RESP, (void *) &par);
-
-	return 0;
-}
-
-/* MSC->VLR: Receive result of Ciphering Mode Command from MS */
-void vlr_subscr_rx_ciph_res(struct vlr_subscr *vsub, struct vlr_ciph_result *res)
-{
-	if (vsub->lu_fsm && vsub->lu_fsm->state == VLR_ULA_S_WAIT_CIPH)
-		osmo_fsm_inst_dispatch(vsub->lu_fsm, VLR_ULA_E_CIPH_RES, res);
-	if (vsub->proc_arq_fsm
-	    && vsub->proc_arq_fsm->state == PR_ARQ_S_WAIT_CIPH)
-		osmo_fsm_inst_dispatch(vsub->proc_arq_fsm, PR_ARQ_E_CIPH_RES,
-				       res);
-}
-
-/* Internal evaluation of requested ciphering mode.
- * Send set_ciph_mode() to MSC depending on the ciph_mode argument.
- * \param[in] vlr  VLR instance.
- * \param[in] fi  Calling FSM instance, for logging.
- * \param[in] msc_conn_ref  MSC conn to send to.
- * \param[in] ciph_mode  Ciphering config, to decide whether to do ciphering.
- * \returns 0 if no ciphering is needed or message was sent successfully,
- *          or a negative value if ciph_mode is invalid or sending failed.
- */
-int vlr_set_ciph_mode(struct vlr_instance *vlr,
-		      struct osmo_fsm_inst *fi,
-		      void *msc_conn_ref,
-		      enum vlr_ciph ciph_mode,
-		      bool retrieve_imeisv)
-{
-	switch (ciph_mode) {
-	case VLR_CIPH_NONE:
-		return 0;
-
-	case VLR_CIPH_A5_1:
-	case VLR_CIPH_A5_3:
-		return vlr->ops.set_ciph_mode(msc_conn_ref,
-					      ciph_mode,
-					      retrieve_imeisv);
-
-	case VLR_CIPH_A5_2:
-		/* TODO policy by user config? */
-		LOGPFSML(fi, LOGL_ERROR, "A5/2 ciphering is not allowed\n");
-		return -EINVAL;
-
-	default:
-		LOGPFSML(fi, LOGL_ERROR, "unknown ciphering value: %d\n",
-			 ciph_mode);
-		return -EINVAL;
-	}
-}
-
-void log_set_filter_vlr_subscr(struct log_target *target,
-			       struct vlr_subscr *vlr_subscr)
-{
-	struct vlr_subscr **fsub = (void*)&target->filter_data[LOG_FLT_VLR_SUBSCR];
-
-	/* free the old data */
-	if (*fsub) {
-		vlr_subscr_put(*fsub);
-		*fsub = NULL;
-	}
-
-	if (vlr_subscr) {
-		target->filter_map |= (1 << LOG_FLT_VLR_SUBSCR);
-		*fsub = vlr_subscr_get(vlr_subscr);
-	} else
-		target->filter_map &= ~(1 << LOG_FLT_VLR_SUBSCR);
-}
diff --git a/src/libvlr/vlr_access_req_fsm.c b/src/libvlr/vlr_access_req_fsm.c
deleted file mode 100644
index f9ed0b5..0000000
--- a/src/libvlr/vlr_access_req_fsm.c
+++ /dev/null
@@ -1,795 +0,0 @@
-/* Osmocom Visitor Location Register (VLR): Access Request FSMs */
-
-/* (C) 2016 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/>.
- *
- */
-
-#include <osmocom/core/fsm.h>
-#include <osmocom/gsm/gsup.h>
-#include <openbsc/vlr.h>
-#include <openbsc/debug.h>
-
-#include "vlr_core.h"
-#include "vlr_auth_fsm.h"
-#include "vlr_lu_fsm.h"
-#include "vlr_access_req_fsm.h"
-
-#define S(x)	(1 << (x))
-
-/***********************************************************************
- * Process_Access_Request_VLR, TS 29.002 Chapter 25.4.2
- ***********************************************************************/
-
-const struct value_string vlr_proc_arq_result_names[] = {
-	OSMO_VALUE_STRING(VLR_PR_ARQ_RES_NONE),
-	OSMO_VALUE_STRING(VLR_PR_ARQ_RES_SYSTEM_FAILURE),
-	OSMO_VALUE_STRING(VLR_PR_ARQ_RES_ILLEGAL_SUBSCR),
-	OSMO_VALUE_STRING(VLR_PR_ARQ_RES_UNIDENT_SUBSCR),
-	OSMO_VALUE_STRING(VLR_PR_ARQ_RES_ROAMING_NOTALLOWED),
-	OSMO_VALUE_STRING(VLR_PR_ARQ_RES_ILLEGAL_EQUIP),
-	OSMO_VALUE_STRING(VLR_PR_ARQ_RES_UNKNOWN_ERROR),
-	OSMO_VALUE_STRING(VLR_PR_ARQ_RES_TIMEOUT),
-	OSMO_VALUE_STRING(VLR_PR_ARQ_RES_PASSED),
-	{ 0, NULL }
-};
-
-static const struct value_string proc_arq_vlr_event_names[] = {
-	OSMO_VALUE_STRING(PR_ARQ_E_START),
-	OSMO_VALUE_STRING(PR_ARQ_E_ID_IMSI),
-	OSMO_VALUE_STRING(PR_ARQ_E_AUTH_RES),
-	OSMO_VALUE_STRING(PR_ARQ_E_CIPH_RES),
-	OSMO_VALUE_STRING(PR_ARQ_E_UPD_LOC_RES),
-	OSMO_VALUE_STRING(PR_ARQ_E_TRACE_RES),
-	OSMO_VALUE_STRING(PR_ARQ_E_IMEI_RES),
-	OSMO_VALUE_STRING(PR_ARQ_E_PRES_RES),
-	OSMO_VALUE_STRING(PR_ARQ_E_TMSI_ACK),
-	{ 0, NULL }
-};
-
-struct proc_arq_priv {
-	struct vlr_instance *vlr;
-	struct vlr_subscr *vsub;
-	void *msc_conn_ref;
-	struct osmo_fsm_inst *ul_child_fsm;
-	struct osmo_fsm_inst *sub_pres_vlr_fsm;
-	uint32_t parent_event_success;
-	uint32_t parent_event_failure;
-	void *parent_event_data;
-
-	enum vlr_parq_type type;
-	enum vlr_proc_arq_result result;
-	bool by_tmsi;
-	char imsi[16];
-	uint32_t tmsi;
-	struct osmo_location_area_id lai;
-	bool authentication_required;
-	enum vlr_ciph ciphering_required;
-	bool is_r99;
-	bool is_utran;
-	bool implicitly_accepted_parq_by_ciphering_cmd;
-};
-
-static void assoc_par_with_subscr(struct osmo_fsm_inst *fi, struct vlr_subscr *vsub)
-{
-	struct proc_arq_priv *par = fi->priv;
-	struct vlr_instance *vlr = par->vlr;
-
-	vsub->msc_conn_ref = par->msc_conn_ref;
-	par->vsub = vsub;
-	/* Tell MSC to associate this subscriber with the given
-	 * connection */
-	vlr->ops.subscr_assoc(par->msc_conn_ref, par->vsub);
-}
-
-#define proc_arq_fsm_done(fi, res) _proc_arq_fsm_done(fi, res, __FILE__, __LINE__)
-static void _proc_arq_fsm_done(struct osmo_fsm_inst *fi,
-			       enum vlr_proc_arq_result res,
-			       const char *file, int line)
-{
-	struct proc_arq_priv *par = fi->priv;
-	LOGPFSMSRC(fi, file, line, "proc_arq_fsm_done(%s)\n",
-		   vlr_proc_arq_result_name(res));
-	par->result = res;
-	osmo_fsm_inst_state_chg(fi, PR_ARQ_S_DONE, 0, 0);
-}
-
-static void proc_arq_vlr_dispatch_result(struct osmo_fsm_inst *fi,
-					 uint32_t prev_state)
-{
-	struct proc_arq_priv *par = fi->priv;
-	bool success;
-	int rc;
-	LOGPFSM(fi, "Process Access Request result: %s\n",
-		vlr_proc_arq_result_name(par->result));
-
-	success = (par->result == VLR_PR_ARQ_RES_PASSED);
-
-	/* It would be logical to first dispatch the success event to the
-	 * parent FSM, but that could start actions that send messages to the
-	 * MS. Rather send the CM Service Accept message first and then signal
-	 * success. Since messages are handled synchronously, the success event
-	 * will be processed before we handle new incoming data from the MS. */
-
-	if (par->type == VLR_PR_ARQ_T_CM_SERV_REQ) {
-		if (success
-		    && !par->implicitly_accepted_parq_by_ciphering_cmd) {
-			rc = par->vlr->ops.tx_cm_serv_acc(par->msc_conn_ref);
-			if (rc) {
-				LOGPFSML(fi, LOGL_ERROR,
-					 "Failed to send CM Service Accept\n");
-				success = false;
-			}
-		}
-		if (!success) {
-			rc = par->vlr->ops.tx_cm_serv_rej(par->msc_conn_ref,
-							  par->result);
-			if (rc)
-				LOGPFSML(fi, LOGL_ERROR,
-					 "Failed to send CM Service Reject\n");
-		}
-	}
-
-	/* For VLR_PR_ARQ_T_PAGING_RESP, there is nothing to send. The conn_fsm
-	 * will start handling pending paging transactions. */
-
-	if (!fi->proc.parent) {
-		LOGPFSML(fi, LOGL_ERROR, "No parent FSM");
-		return;
-	}
-	osmo_fsm_inst_dispatch(fi->proc.parent,
-			       success ? par->parent_event_success
-				       : par->parent_event_failure,
-			       par->parent_event_data);
-}
-
-void proc_arq_vlr_cleanup(struct osmo_fsm_inst *fi,
-			  enum osmo_fsm_term_cause cause)
-{
-	struct proc_arq_priv *par = fi->priv;
-	if (par->vsub && par->vsub->proc_arq_fsm == fi)
-		par->vsub->proc_arq_fsm = NULL;
-}
-
-static void _proc_arq_vlr_post_imei(struct osmo_fsm_inst *fi)
-{
-	struct proc_arq_priv *par = fi->priv;
-	struct vlr_subscr *vsub = par->vsub;
-
-	LOGPFSM(fi, "%s()\n", __func__);
-
-	/* See 3GPP TS 29.002 Proc_Acc_Req_VLR3. */
-	/* TODO: Identity := IMSI */
-	if (0 /* TODO: TMSI reallocation at access: vlr->cfg.alloc_tmsi_arq */) {
-		vlr_subscr_alloc_tmsi(vsub);
-		/* TODO: forward TMSI to MS, wait for TMSI
-		 * REALLOC COMPLETE */
-		/* TODO: Freeze old TMSI */
-		osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_TMSI_ACK, 0, 0);
-		return;
-	}
-
-	proc_arq_fsm_done(fi, VLR_PR_ARQ_RES_PASSED);
-}
-
-static void _proc_arq_vlr_post_trace(struct osmo_fsm_inst *fi)
-{
-	struct proc_arq_priv *par = fi->priv;
-	struct vlr_subscr *vsub = par->vsub;
-	struct vlr_instance *vlr = vsub->vlr;
-
-	LOGPFSM(fi, "%s()\n", __func__);
-
-	/* Node 3 */
-	/* See 3GPP TS 29.002 Proc_Acc_Req_VLR3. */
-	if (0 /* IMEI check required */) {
-		/* Chck_IMEI_VLR */
-		vlr->ops.tx_id_req(par->msc_conn_ref, GSM_MI_TYPE_IMEI);
-		osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_CHECK_IMEI,
-					vlr_timer(vlr, 3270), 3270);
-	} else
-		_proc_arq_vlr_post_imei(fi);
-}
-
-/* After Subscriber_Present_VLR */
-static void _proc_arq_vlr_post_pres(struct osmo_fsm_inst *fi)
-{
-	LOGPFSM(fi, "%s()\n", __func__);
-	/* See 3GPP TS 29.002 Proc_Acc_Req_VLR3. */
-	if (0 /* TODO: tracing required */) {
-		/* TODO: Trace_Subscriber_Activity_VLR */
-		osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_TRACE_SUB, 0, 0);
-	}
-	_proc_arq_vlr_post_trace(fi);
-}
-
-/* After Update_Location_Child_VLR */
-static void _proc_arq_vlr_node2_post_vlr(struct osmo_fsm_inst *fi)
-{
-	struct proc_arq_priv *par = fi->priv;
-	struct vlr_subscr *vsub = par->vsub;
-
-	LOGPFSM(fi, "%s()\n", __func__);
-
-	if (!vsub->sub_dataconf_by_hlr_ind) {
-		/* Set User Error: Unidentified Subscriber */
-		proc_arq_fsm_done(fi, VLR_PR_ARQ_RES_UNIDENT_SUBSCR);
-		return;
-	}
-	/* We don't feature location area specific blocking (yet). */
-	if (0 /* roaming not allowed in LA */) {
-		/* Set User Error: Roaming not allowed in this LA */
-		proc_arq_fsm_done(fi, VLR_PR_ARQ_RES_ROAMING_NOTALLOWED);
-		return;
-	}
-	vsub->imsi_detached_flag = false;
-	if (vsub->ms_not_reachable_flag) {
-		/* Start Subscriber_Present_VLR */
-		osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_SUB_PRES, 0, 0);
-		par->sub_pres_vlr_fsm = sub_pres_vlr_fsm_start(fi, vsub,
-							PR_ARQ_E_PRES_RES);
-		return;
-	}
-	_proc_arq_vlr_post_pres(fi);
-}
-
-static void _proc_arq_vlr_node2_post_ciph(struct osmo_fsm_inst *fi)
-{
-	struct proc_arq_priv *par = fi->priv;
-	struct vlr_subscr *vsub = par->vsub;
-
-	LOGPFSM(fi, "%s()\n", __func__);
-
-	if (par->is_utran) {
-		int rc;
-		rc = par->vlr->ops.tx_common_id(par->msc_conn_ref);
-		if (rc)
-			LOGPFSML(fi, LOGL_ERROR,
-				 "Error while sending Common ID (%d)\n", rc);
-	}
-
-	vsub->conf_by_radio_contact_ind = true;
-	if (vsub->loc_conf_in_hlr_ind == false) {
-		/* start Update_Location_Child_VLR.  WE use
-		 * Update_HLR_VLR instead, the differences appear
-		 * insignificant for now. */
-		par->ul_child_fsm = upd_hlr_vlr_proc_start(fi, vsub,
-							PR_ARQ_E_UPD_LOC_RES);
-		osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_UPD_LOC_CHILD, 0, 0);
-		return;
-	}
-	_proc_arq_vlr_node2_post_vlr(fi);
-}
-
-static bool is_ciph_required(struct proc_arq_priv *par)
-{
-	return par->ciphering_required != VLR_CIPH_NONE;
-}
-
-static void _proc_arq_vlr_node2(struct osmo_fsm_inst *fi)
-{
-	struct proc_arq_priv *par = fi->priv;
-	struct vlr_subscr *vsub = par->vsub;
-
-	LOGPFSM(fi, "%s()\n", __func__);
-
-	if (!is_ciph_required(par)) {
-		_proc_arq_vlr_node2_post_ciph(fi);
-		return;
-	}
-
-	if (vlr_set_ciph_mode(vsub->vlr, fi, par->msc_conn_ref,
-			      par->ciphering_required,
-			      vsub->vlr->cfg.retrieve_imeisv_ciphered)) {
-		LOGPFSML(fi, LOGL_ERROR,
-			 "Failed to send Ciphering Mode Command\n");
-		proc_arq_fsm_done(fi, VLR_PR_ARQ_RES_SYSTEM_FAILURE);
-		return;
-	}
-
-	par->implicitly_accepted_parq_by_ciphering_cmd = true;
-	osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_CIPH, 0, 0);
-}
-
-static bool is_auth_required(struct proc_arq_priv *par)
-{
-	/* The cases where the authentication procedure should be used
-	 * are defined in 3GPP TS 33.102 */
-	/* For now we use a default value passed in to vlr_lu_fsm(). */
-	return par->authentication_required
-	       || (par->ciphering_required != VLR_CIPH_NONE);
-}
-
-/* after the IMSI is known */
-static void proc_arq_vlr_fn_post_imsi(struct osmo_fsm_inst *fi)
-{
-	struct proc_arq_priv *par = fi->priv;
-	struct vlr_subscr *vsub = par->vsub;
-
-	LOGPFSM(fi, "%s()\n", __func__);
-
-	OSMO_ASSERT(vsub);
-
-	/* TODO: Identity IMEI -> System Failure */
-	if (is_auth_required(par)) {
-		osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_AUTH,
-					0, 0);
-		vsub->auth_fsm = auth_fsm_start(vsub, fi->log_level, fi,
-						PR_ARQ_E_AUTH_RES,
-						par->is_r99,
-						par->is_utran);
-	} else {
-		_proc_arq_vlr_node2(fi);
-	}
-}
-
-static void proc_arq_vlr_fn_init(struct osmo_fsm_inst *fi,
-				 uint32_t event, void *data)
-{
-	struct proc_arq_priv *par = fi->priv;
-	struct vlr_instance *vlr = par->vlr;
-	struct vlr_subscr *vsub = NULL;
-
-	OSMO_ASSERT(event == PR_ARQ_E_START);
-
-	/* Obtain_Identity_VLR */
-	if (!par->by_tmsi) {
-		/* IMSI was included */
-		vsub = vlr_subscr_find_by_imsi(par->vlr, par->imsi);
-	} else {
-		/* TMSI was included */
-		vsub = vlr_subscr_find_by_tmsi(par->vlr, par->tmsi);
-	}
-	if (vsub) {
-		log_set_context(LOG_CTX_VLR_SUBSCR, vsub);
-		if (vsub->proc_arq_fsm && fi != vsub->proc_arq_fsm) {
-			LOGPFSML(fi, LOGL_ERROR,
-				 "Another proc_arq_fsm is already"
-				 " associated with subscr %s,"
-				 " terminating the other FSM.\n",
-				 vlr_subscr_name(vsub));
-			proc_arq_fsm_done(vsub->proc_arq_fsm,
-					  VLR_PR_ARQ_RES_SYSTEM_FAILURE);
-		}
-		vsub->proc_arq_fsm = fi;
-		assoc_par_with_subscr(fi, vsub);
-		proc_arq_vlr_fn_post_imsi(fi);
-		vlr_subscr_put(vsub);
-		return;
-	}
-	/* No VSUB could be resolved. What now? */
-
-	if (!par->by_tmsi) {
-		/* We couldn't find a subscriber even by IMSI,
-		 * Set User Error: Unidentified Subscriber */
-		proc_arq_fsm_done(fi, VLR_PR_ARQ_RES_UNIDENT_SUBSCR);
-		return;
-	} else {
-		/* TMSI was included, are we permitted to use it? */
-		if (vlr->cfg.parq_retrieve_imsi) {
-			/* Obtain_IMSI_VLR */
-			osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_OBTAIN_IMSI,
-						vlr_timer(vlr, 3270), 3270);
-			return;
-		} else {
-			/* Set User Error: Unidentified Subscriber */
-			proc_arq_fsm_done(fi, VLR_PR_ARQ_RES_UNIDENT_SUBSCR);
-			return;
-		}
-	}
-}
-
-/* ID REQ(IMSI) has returned */
-static void proc_arq_vlr_fn_w_obt_imsi(struct osmo_fsm_inst *fi,
-					uint32_t event, void *data)
-{
-	struct proc_arq_priv *par = fi->priv;
-	struct vlr_instance *vlr = par->vlr;
-	struct vlr_subscr *vsub;
-
-	OSMO_ASSERT(event == PR_ARQ_E_ID_IMSI);
-
-	vsub = vlr_subscr_find_by_imsi(vlr, par->imsi);
-	if (!vsub) {
-		/* Set User Error: Unidentified Subscriber */
-		proc_arq_fsm_done(fi, VLR_PR_ARQ_RES_UNIDENT_SUBSCR);
-		return;
-	}
-	assoc_par_with_subscr(fi, vsub);
-	proc_arq_vlr_fn_post_imsi(fi);
-	vlr_subscr_put(vsub);
-}
-
-/* Authenticate_VLR has completed */
-static void proc_arq_vlr_fn_w_auth(struct osmo_fsm_inst *fi,
-				   uint32_t event, void *data)
-{
-	enum vlr_auth_fsm_result res;
-	enum vlr_proc_arq_result ret;
-
-	OSMO_ASSERT(event == PR_ARQ_E_AUTH_RES);
-
-	res = data ? *(enum vlr_auth_fsm_result*)data : -1;
-	LOGPFSM(fi, "got %s\n", vlr_auth_fsm_result_name(res));
-
-	switch (res) {
-	case VLR_AUTH_RES_PASSED:
-		/* Node 2 */
-		_proc_arq_vlr_node2(fi);
-		return;
-	case VLR_AUTH_RES_ABORTED:
-		/* Error */
-		ret = VLR_PR_ARQ_RES_UNKNOWN_ERROR;
-		break;
-	case VLR_AUTH_RES_UNKNOWN_SUBSCR:
-		/* Set User Error: Unidentified Subscriber */
-		ret = VLR_PR_ARQ_RES_UNIDENT_SUBSCR;
-		break;
-	case VLR_AUTH_RES_AUTH_FAILED:
-		/* Set User Error: Illegal Subscriber */
-		ret = VLR_PR_ARQ_RES_ILLEGAL_SUBSCR;
-		break;
-	case VLR_AUTH_RES_PROC_ERR:
-		/* Set User Error: System failure */
-		ret = VLR_PR_ARQ_RES_SYSTEM_FAILURE;
-		break;
-	default:
-		LOGPFSML(fi, LOGL_ERROR, "Unexpected vlr_auth_fsm_result value: %d (data=%p)\n", res, data);
-		ret = VLR_PR_ARQ_RES_UNKNOWN_ERROR;
-		break;
-	}
-
-	/* send process_access_req response to caller, enter error state */
-	proc_arq_fsm_done(fi, ret);
-}
-
-static void proc_arq_vlr_fn_w_ciph(struct osmo_fsm_inst *fi,
-				   uint32_t event, void *data)
-{
-	struct proc_arq_priv *par = fi->priv;
-	struct vlr_subscr *vsub = par->vsub;
-	struct vlr_ciph_result res = { .cause = VLR_CIPH_REJECT };
-
-	OSMO_ASSERT(event == PR_ARQ_E_CIPH_RES);
-
-	if (!data)
-		LOGPFSML(fi, LOGL_ERROR, "invalid ciphering result: NULL\n");
-	else
-		res = *(struct vlr_ciph_result*)data;
-
-	switch (res.cause) {
-	case VLR_CIPH_COMPL:
-		break;
-	case VLR_CIPH_REJECT:
-		LOGPFSM(fi, "ciphering rejected\n");
-		proc_arq_fsm_done(fi, VLR_PR_ARQ_RES_ILLEGAL_SUBSCR);
-		return;
-	default:
-		LOGPFSML(fi, LOGL_ERROR, "invalid ciphering result: %d\n",
-			 res.cause);
-		proc_arq_fsm_done(fi, VLR_PR_ARQ_RES_ILLEGAL_SUBSCR);
-		return;
-	}
-
-
-	if (res.imeisv) {
-		LOGPFSM(fi, "got IMEISV: %s\n", res.imeisv);
-		vlr_subscr_set_imeisv(vsub, res.imeisv);
-	}
-	_proc_arq_vlr_node2_post_ciph(fi);
-}
-
-/* Update_Location_Child_VLR has completed */
-static void proc_arq_vlr_fn_w_upd_loc(struct osmo_fsm_inst *fi,
-					uint32_t event, void *data)
-{
-	OSMO_ASSERT(event == PR_ARQ_E_UPD_LOC_RES);
-
-	_proc_arq_vlr_node2_post_vlr(fi);
-}
-
-/* Subscriber_Present_VLR has completed */
-static void proc_arq_vlr_fn_w_pres(struct osmo_fsm_inst *fi,
-					uint32_t event, void *data)
-{
-	OSMO_ASSERT(event == PR_ARQ_E_PRES_RES);
-
-	_proc_arq_vlr_post_pres(fi);
-}
-
-static void proc_arq_vlr_fn_w_trace(struct osmo_fsm_inst *fi,
-					uint32_t event, void *data)
-{
-	OSMO_ASSERT(event == PR_ARQ_E_TRACE_RES);
-
-	_proc_arq_vlr_post_trace(fi);
-}
-
-/* we have received the ID RESPONSE (IMEI) */
-static void proc_arq_vlr_fn_w_imei(struct osmo_fsm_inst *fi,
-				uint32_t event, void *data)
-{
-	OSMO_ASSERT(event == PR_ARQ_E_IMEI_RES);
-
-	_proc_arq_vlr_post_imei(fi);
-}
-
-/* MSC tells us that MS has acknowleded TMSI re-allocation */
-static void proc_arq_vlr_fn_w_tmsi(struct osmo_fsm_inst *fi,
-				uint32_t event, void *data)
-{
-	OSMO_ASSERT(event == PR_ARQ_E_TMSI_ACK);
-
-	/* FIXME: check confirmation? unfreeze? */
-	proc_arq_fsm_done(fi, VLR_PR_ARQ_RES_PASSED);
-}
-
-static const struct osmo_fsm_state proc_arq_vlr_states[] = {
-	[PR_ARQ_S_INIT] = {
-		.name = OSMO_STRINGIFY(PR_ARQ_S_INIT),
-		.in_event_mask = S(PR_ARQ_E_START),
-		.out_state_mask = S(PR_ARQ_S_DONE) |
-				  S(PR_ARQ_S_WAIT_OBTAIN_IMSI) |
-				  S(PR_ARQ_S_WAIT_AUTH) |
-				  S(PR_ARQ_S_WAIT_UPD_LOC_CHILD) |
-				  S(PR_ARQ_S_WAIT_SUB_PRES) |
-				  S(PR_ARQ_S_WAIT_TRACE_SUB) |
-				  S(PR_ARQ_S_WAIT_CHECK_IMEI) |
-				  S(PR_ARQ_S_WAIT_TMSI_ACK),
-		.action = proc_arq_vlr_fn_init,
-	},
-	[PR_ARQ_S_WAIT_OBTAIN_IMSI] = {
-		.name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_OBTAIN_IMSI),
-		.in_event_mask = S(PR_ARQ_E_ID_IMSI),
-		.out_state_mask = S(PR_ARQ_S_DONE) |
-				  S(PR_ARQ_S_WAIT_AUTH) |
-				  S(PR_ARQ_S_WAIT_UPD_LOC_CHILD) |
-				  S(PR_ARQ_S_WAIT_SUB_PRES) |
-				  S(PR_ARQ_S_WAIT_TRACE_SUB) |
-				  S(PR_ARQ_S_WAIT_CHECK_IMEI) |
-				  S(PR_ARQ_S_WAIT_TMSI_ACK),
-		.action = proc_arq_vlr_fn_w_obt_imsi,
-	},
-	[PR_ARQ_S_WAIT_AUTH] = {
-		.name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_AUTH),
-		.in_event_mask = S(PR_ARQ_E_AUTH_RES),
-		.out_state_mask = S(PR_ARQ_S_DONE) |
-				  S(PR_ARQ_S_WAIT_CIPH) |
-				  S(PR_ARQ_S_WAIT_UPD_LOC_CHILD) |
-				  S(PR_ARQ_S_WAIT_SUB_PRES) |
-				  S(PR_ARQ_S_WAIT_TRACE_SUB) |
-				  S(PR_ARQ_S_WAIT_CHECK_IMEI) |
-				  S(PR_ARQ_S_WAIT_TMSI_ACK),
-		.action = proc_arq_vlr_fn_w_auth,
-	},
-	[PR_ARQ_S_WAIT_CIPH] = {
-		.name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_CIPH),
-		.in_event_mask = S(PR_ARQ_E_CIPH_RES),
-		.out_state_mask = S(PR_ARQ_S_DONE) |
-				  S(PR_ARQ_S_WAIT_UPD_LOC_CHILD) |
-				  S(PR_ARQ_S_WAIT_SUB_PRES) |
-				  S(PR_ARQ_S_WAIT_TRACE_SUB) |
-				  S(PR_ARQ_S_WAIT_CHECK_IMEI) |
-				  S(PR_ARQ_S_WAIT_TMSI_ACK),
-		.action = proc_arq_vlr_fn_w_ciph,
-	},
-	[PR_ARQ_S_WAIT_UPD_LOC_CHILD] = {
-		.name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_UPD_LOC_CHILD),
-		.in_event_mask = S(PR_ARQ_E_UPD_LOC_RES),
-		.out_state_mask = S(PR_ARQ_S_DONE) |
-				  S(PR_ARQ_S_WAIT_SUB_PRES) |
-				  S(PR_ARQ_S_WAIT_TRACE_SUB) |
-				  S(PR_ARQ_S_WAIT_CHECK_IMEI) |
-				  S(PR_ARQ_S_WAIT_TMSI_ACK),
-		.action = proc_arq_vlr_fn_w_upd_loc,
-	},
-	[PR_ARQ_S_WAIT_SUB_PRES] = {
-		.name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_SUB_PRES),
-		.in_event_mask = S(PR_ARQ_E_PRES_RES),
-		.out_state_mask = S(PR_ARQ_S_DONE) |
-				  S(PR_ARQ_S_WAIT_TRACE_SUB) |
-				  S(PR_ARQ_S_WAIT_CHECK_IMEI) |
-				  S(PR_ARQ_S_WAIT_TMSI_ACK),
-		.action = proc_arq_vlr_fn_w_pres,
-	},
-	[PR_ARQ_S_WAIT_TRACE_SUB] = {
-		.name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_TRACE_SUB),
-		.in_event_mask = S(PR_ARQ_E_TRACE_RES),
-		.out_state_mask = S(PR_ARQ_S_DONE) |
-				  S(PR_ARQ_S_WAIT_CHECK_IMEI) |
-				  S(PR_ARQ_S_WAIT_TMSI_ACK),
-		.action = proc_arq_vlr_fn_w_trace,
-	},
-	[PR_ARQ_S_WAIT_CHECK_IMEI] = {
-		.name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_CHECK_IMEI),
-		.in_event_mask = S(PR_ARQ_E_IMEI_RES),
-		.out_state_mask = S(PR_ARQ_S_DONE) |
-				  S(PR_ARQ_S_WAIT_TMSI_ACK),
-		.action = proc_arq_vlr_fn_w_imei,
-	},
-	[PR_ARQ_S_WAIT_TMSI_ACK] = {
-		.name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_TMSI_ACK),
-		.in_event_mask = S(PR_ARQ_E_TMSI_ACK),
-		.out_state_mask = S(PR_ARQ_S_DONE),
-		.action = proc_arq_vlr_fn_w_tmsi,
-	},
-	[PR_ARQ_S_DONE] = {
-		.name = OSMO_STRINGIFY(PR_ARQ_S_DONE),
-		.onenter = proc_arq_vlr_dispatch_result,
-	},
-};
-
-static struct osmo_fsm proc_arq_vlr_fsm = {
-	.name = "Process_Access_Request_VLR",
-	.states = proc_arq_vlr_states,
-	.num_states = ARRAY_SIZE(proc_arq_vlr_states),
-	.allstate_event_mask = 0,
-	.allstate_action = NULL,
-	.log_subsys = DVLR,
-	.event_names = proc_arq_vlr_event_names,
-	.cleanup = proc_arq_vlr_cleanup,
-};
-
-void
-vlr_proc_acc_req(struct osmo_fsm_inst *parent,
-		 uint32_t parent_event_success,
-		 uint32_t parent_event_failure,
-		 void *parent_event_data,
-		 struct vlr_instance *vlr, void *msc_conn_ref,
-		 enum vlr_parq_type type, const uint8_t *mi_lv,
-		 const struct osmo_location_area_id *lai,
-		 bool authentication_required,
-		 enum vlr_ciph ciphering_required,
-		 bool is_r99, bool is_utran)
-{
-	struct osmo_fsm_inst *fi;
-	struct proc_arq_priv *par;
-	char mi_string[GSM48_MI_SIZE];
-	uint8_t mi_type;
-
-	fi = osmo_fsm_inst_alloc_child(&proc_arq_vlr_fsm, parent,
-				       parent_event_failure);
-	if (!fi)
-		return;
-
-	par = talloc_zero(fi, struct proc_arq_priv);
-	fi->priv = par;
-	par->vlr = vlr;
-	par->msc_conn_ref = msc_conn_ref;
-	par->type = type;
-	par->lai = *lai;
-	par->parent_event_success = parent_event_success;
-	par->parent_event_failure = parent_event_failure;
-	par->parent_event_data = parent_event_data;
-	par->authentication_required = authentication_required;
-	par->ciphering_required = ciphering_required;
-	par->is_r99 = is_r99;
-	par->is_utran = is_utran;
-
-	LOGPFSM(fi, "rev=%s net=%s%s%s\n",
-		is_r99 ? "R99" : "GSM",
-		is_utran ? "UTRAN" : "GERAN",
-		(authentication_required || ciphering_required)?
-		" Auth" : " (no Auth)",
-		(authentication_required || ciphering_required)?
-			(ciphering_required? "+Ciph" : " (no Ciph)")
-			: "");
-
-	if (is_utran && !authentication_required)
-		LOGPFSML(fi, LOGL_ERROR,
-			 "Authentication off on UTRAN network. Good luck.\n");
-
-	gsm48_mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, mi_lv[0]);
-	mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
-	switch (mi_type) {
-	case GSM_MI_TYPE_IMSI:
-		strncpy(par->imsi, mi_string, sizeof(par->imsi)-1);
-		par->imsi[sizeof(par->imsi)-1] = '\0';
-		par->by_tmsi = false;
-		break;
-	case GSM_MI_TYPE_TMSI:
-		par->by_tmsi = true;
-		par->tmsi = osmo_load32be(mi_lv+2);
-		break;
-	case GSM_MI_TYPE_IMEI:
-		/* TODO: IMEI (emergency call) */
-	default:
-		/* FIXME: directly send reject? */
-		proc_arq_fsm_done(fi, VLR_PR_ARQ_RES_UNIDENT_SUBSCR);
-		return;
-	}
-
-	osmo_fsm_inst_dispatch(fi, PR_ARQ_E_START, NULL);
-}
-
-/* Gracefully terminate an FSM created by vlr_proc_acc_req() in case of
- * external timeout (i.e. from MSC). */
-void vlr_parq_conn_timeout(struct osmo_fsm_inst *fi)
-{
-	if (!fi || fi->state == PR_ARQ_S_DONE)
-		return;
-	LOGPFSM(fi, "Connection timed out\n");
-	proc_arq_fsm_done(fi, VLR_PR_ARQ_RES_TIMEOUT);
-}
-
-
-#if 0
-/***********************************************************************
- * Update_Location_Child_VLR, TS 29.002 Chapter 25.4.4
- ***********************************************************************/
-
-enum upd_loc_child_vlr_state {
-	ULC_S_IDLE,
-	ULC_S_WAIT_HLR_RESP,
-	ULC_S_DONE,
-};
-
-enum upd_loc_child_vlr_event {
-	ULC_E_START,
-};
-
-static const struct value_string upd_loc_child_vlr_event_names[] = {
-	{ ULC_E_START, "START" },
-	{ 0, NULL }
-};
-
-static void upd_loc_child_f_idle(struct osmo_fsm_inst *fi, uint32_t event,
-				 void *data)
-{
-	OSMO_ASSERT(event == ULC_E_START);
-
-	/* send update location */
-}
-
-static void upd_loc_child_f_w_hlr(struct osmo_fsm_inst *fi, uint32_t event,
-				  void *data)
-{
-}
-
-static const struct osmo_fsm_state upd_loc_child_vlr_states[] = {
-	[ULC_S_IDLE] = {
-		.in_event_mask = ,
-		.out_state_mask = S(ULC_S_WAIT_HLR_RESP) |
-				  S(ULC_S_DONE),
-		.name = "IDLE",
-		.action = upd_loc_child_f_idle,
-	},
-	[ULC_S_WAIT_HLR_RESP] = {
-		.in_event_mask = ,
-		.out_state_mask = S(ULC_S_DONE),
-		.name = "WAIT-HLR-RESP",
-		.action = upd_loc_child_f_w_hlr,
-	},
-	[ULC_S_DONE] = {
-		.name = "DONE",
-	},
-};
-
-static struct osmo_fsm upd_loc_child_vlr_fsm = {
-	.name = "Update_Location_Child_VLR",
-	.states = upd_loc_child_vlr_states,
-	.num_states = ARRAY_SIZE(upd_loc_child_vlr_states),
-	.log_subsys = DVLR,
-	.event_names = upd_loc_child_vlr_event_names,
-};
-#endif
-
-void vlr_parq_fsm_init(void)
-{
-	//osmo_fsm_register(&upd_loc_child_vlr_fsm);
-	osmo_fsm_register(&proc_arq_vlr_fsm);
-}
diff --git a/src/libvlr/vlr_access_req_fsm.h b/src/libvlr/vlr_access_req_fsm.h
deleted file mode 100644
index 8386da6..0000000
--- a/src/libvlr/vlr_access_req_fsm.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-
-enum proc_arq_vlr_state {
-	PR_ARQ_S_INIT,
-	/* Waiting for Obtain_Identity_VLR (IMSI) result */
-	PR_ARQ_S_WAIT_OBTAIN_IMSI,
-	/* Waiting for Authenticate_VLR result */
-	PR_ARQ_S_WAIT_AUTH,
-	PR_ARQ_S_WAIT_CIPH,
-	PR_ARQ_S_WAIT_UPD_LOC_CHILD,
-	PR_ARQ_S_WAIT_SUB_PRES,
-	PR_ARQ_S_WAIT_TRACE_SUB,
-	PR_ARQ_S_WAIT_CHECK_IMEI,
-	PR_ARQ_S_WAIT_TMSI_ACK,
-	PR_ARQ_S_WAIT_CECK_CONF,
-	PR_ARQ_S_DONE,
-};
diff --git a/src/libvlr/vlr_auth_fsm.c b/src/libvlr/vlr_auth_fsm.c
deleted file mode 100644
index 0eb86e7..0000000
--- a/src/libvlr/vlr_auth_fsm.c
+++ /dev/null
@@ -1,605 +0,0 @@
-/* Osmocom Visitor Location Register (VLR) Autentication FSM */
-
-/* (C) 2016 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/>.
- *
- */
-
-
-#include <osmocom/core/fsm.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/gsm/gsup.h>
-#include <openbsc/vlr.h>
-#include <openbsc/debug.h>
-
-#include "vlr_core.h"
-#include "vlr_auth_fsm.h"
-
-#define S(x)	(1 << (x))
-
-static const struct value_string fsm_auth_event_names[] = {
-	OSMO_VALUE_STRING(VLR_AUTH_E_START),
-	OSMO_VALUE_STRING(VLR_AUTH_E_HLR_SAI_ACK),
-	OSMO_VALUE_STRING(VLR_AUTH_E_HLR_SAI_NACK),
-	OSMO_VALUE_STRING(VLR_AUTH_E_HLR_SAI_ABORT),
-	OSMO_VALUE_STRING(VLR_AUTH_E_MS_AUTH_RESP),
-	OSMO_VALUE_STRING(VLR_AUTH_E_MS_AUTH_FAIL),
-	OSMO_VALUE_STRING(VLR_AUTH_E_MS_ID_IMSI),
-	{ 0, NULL }
-};
-
-const struct value_string vlr_auth_fsm_result_names[] = {
-	OSMO_VALUE_STRING(VLR_AUTH_RES_ABORTED),
-	OSMO_VALUE_STRING(VLR_AUTH_RES_UNKNOWN_SUBSCR),
-	OSMO_VALUE_STRING(VLR_AUTH_RES_PROC_ERR),
-	OSMO_VALUE_STRING(VLR_AUTH_RES_AUTH_FAILED),
-	OSMO_VALUE_STRING(VLR_AUTH_RES_PASSED),
-	{0, NULL}
-};
-
-/* private state of the auth_fsm_instance */
-struct auth_fsm_priv {
-	struct vlr_subscr *vsub;
-	bool by_imsi;
-	bool is_r99;
-	bool is_utran;
-	bool auth_requested;
-
-	int auth_tuple_max_use_count; /* see vlr->cfg instead */
-};
-
-/***********************************************************************
- * Utility functions
- ***********************************************************************/
-
-/* Always use either vlr_subscr_get_auth_tuple() or vlr_subscr_has_auth_tuple()
- * instead, to ensure proper use count.
- * Return an auth tuple with the lowest use_count among the auth tuples. If
- * max_use_count >= 0, return NULL if all available auth tuples have a use
- * count > max_use_count. If max_use_count is negative, return a currently
- * least used auth tuple without enforcing a maximum use count.  If there are
- * no auth tuples, return NULL.
- */
-static struct gsm_auth_tuple *
-_vlr_subscr_next_auth_tuple(struct vlr_subscr *vsub, int max_use_count)
-{
-	unsigned int count;
-	unsigned int idx;
-	struct gsm_auth_tuple *at = NULL;
-	unsigned int key_seq = GSM_KEY_SEQ_INVAL;
-
-	if (!vsub)
-		return NULL;
-
-	if (vsub->last_tuple)
-		key_seq = vsub->last_tuple->key_seq;
-
-	if (key_seq == GSM_KEY_SEQ_INVAL)
-		/* Start with 0 after increment modulo array size */
-		idx = ARRAY_SIZE(vsub->auth_tuples) - 1;
-	else
-		idx = key_seq;
-
-	for (count = ARRAY_SIZE(vsub->auth_tuples); count > 0; count--) {
-		idx = (idx + 1) % ARRAY_SIZE(vsub->auth_tuples);
-
-		if (vsub->auth_tuples[idx].key_seq == GSM_KEY_SEQ_INVAL)
-			continue;
-
-		if (!at || vsub->auth_tuples[idx].use_count < at->use_count)
-			at = &vsub->auth_tuples[idx];
-	}
-
-	if (!at || (max_use_count >= 0 && at->use_count > max_use_count))
-		return NULL;
-
-	return at;
-}
-
-/* Return an auth tuple and increment its use count. */
-static struct gsm_auth_tuple *
-vlr_subscr_get_auth_tuple(struct vlr_subscr *vsub, int max_use_count)
-{
-	struct gsm_auth_tuple *at = _vlr_subscr_next_auth_tuple(vsub,
-							       max_use_count);
-	if (!at)
-		return NULL;
-	at->use_count++;
-	return at;
-}
-
-/* Return whether an auth tuple with the given max_use_count is available. */
-static bool vlr_subscr_has_auth_tuple(struct vlr_subscr *vsub,
-				      int max_use_count)
-{
-	return _vlr_subscr_next_auth_tuple(vsub, max_use_count) != NULL;
-}
-
-static bool check_auth_resp(struct vlr_subscr *vsub, bool is_r99,
-			    bool is_utran, const uint8_t *res,
-			    uint8_t res_len)
-{
-	struct gsm_auth_tuple *at = vsub->last_tuple;
-	struct osmo_auth_vector *vec = &at->vec;
-	bool check_umts;
-	OSMO_ASSERT(at);
-
-	LOGVSUBP(LOGL_DEBUG, vsub, "received res: %s\n",
-		 osmo_hexdump(res, res_len));
-
-	/* RES must be present and at least 32bit */
-	if (!res || res_len < sizeof(vec->sres)) {
-		LOGVSUBP(LOGL_NOTICE, vsub, "AUTH RES missing or too short "
-			 "(%u)\n", res_len);
-		goto out_false;
-	}
-
-	check_umts = false;
-	if (is_r99 && (vec->auth_types & OSMO_AUTH_TYPE_UMTS)) {
-		check_umts = true;
-		/* We have a R99 capable UE and have a UMTS AKA capable USIM.
-		 * However, the ME may still choose to only perform GSM AKA, as
-		 * long as the bearer is GERAN */
-		if (res_len != vec->res_len) {
-			if (is_utran) {
-				LOGVSUBP(LOGL_NOTICE, vsub,
-					 "AUTH via UTRAN but "
-					 "res_len(%u) != vec->res_len(%u)\n",
-					 res_len, vec->res_len);
-				goto out_false;
-			}
-			check_umts = false;
-		}
-	}
-
-	if (check_umts) {
-		if (res_len != vec->res_len
-		    || memcmp(res, vec->res, res_len)) {
-			LOGVSUBP(LOGL_INFO, vsub, "UMTS AUTH failure:"
-				 " mismatching res (expected res=%s)\n",
-				 osmo_hexdump(vec->res, vec->res_len));
-			goto out_false;
-		}
-
-		LOGVSUBP(LOGL_INFO, vsub, "AUTH established UMTS security"
-			 " context\n");
-		vsub->sec_ctx = VLR_SEC_CTX_UMTS;
-		return true;
-	} else {
-		if (res_len != sizeof(vec->sres)
-		    || memcmp(res, vec->sres, sizeof(vec->sres))) {
-			LOGVSUBP(LOGL_INFO, vsub, "GSM AUTH failure:"
-				 " mismatching sres (expected sres=%s)\n",
-				 osmo_hexdump(vec->sres, sizeof(vec->sres)));
-			goto out_false;
-		}
-
-		LOGVSUBP(LOGL_INFO, vsub, "AUTH established GSM security"
-			 " context\n");
-		vsub->sec_ctx = VLR_SEC_CTX_GSM;
-		return true;
-	}
-
-out_false:
-	vsub->sec_ctx = VLR_SEC_CTX_NONE;
-	return false;
-}
-
-static void auth_fsm_onenter_failed(struct osmo_fsm_inst *fi, uint32_t prev_state)
-{
-	struct auth_fsm_priv *afp = fi->priv;
-	struct vlr_subscr *vsub = afp->vsub;
-
-	/* If authentication hasn't even started, e.g. the HLR sent no auth
-	 * info, then we also don't need to tell the HLR about an auth failure.
-	 */
-	if (afp->auth_requested)
-		vlr_subscr_tx_auth_fail_rep(vsub);
-}
-
-static bool is_umts_auth(struct auth_fsm_priv *afp,
-			 uint32_t auth_types)
-{
-	if (!afp->is_r99)
-		return false;
-	if (!(auth_types & OSMO_AUTH_TYPE_UMTS))
-		return false;
-	return true;
-}
-
-/* Terminate the Auth FSM Instance and notify parent */
-static void auth_fsm_term(struct osmo_fsm_inst *fi, enum vlr_auth_fsm_result res)
-{
-	struct auth_fsm_priv *afp = fi->priv;
-	struct vlr_subscr *vsub = afp->vsub;
-
-	LOGPFSM(fi, "Authentication terminating with result %s\n",
-		vlr_auth_fsm_result_name(res));
-
-	/* Do one final state transition (mostly for logging purpose) */
-	if (res == VLR_AUTH_RES_PASSED)
-		osmo_fsm_inst_state_chg(fi, VLR_SUB_AS_AUTHENTICATED, 0, 0);
-	else
-		osmo_fsm_inst_state_chg(fi, VLR_SUB_AS_AUTH_FAILED, 0, 0);
-
-	/* return the result to the parent FSM */
-	osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, &res);
-	vsub->auth_fsm = NULL;
-}
-
-/* back-end function transmitting authentication. Caller ensures we have valid
- * tuple */
-static int _vlr_subscr_authenticate(struct osmo_fsm_inst *fi)
-{
-	struct auth_fsm_priv *afp = fi->priv;
-	struct vlr_subscr *vsub = afp->vsub;
-	struct gsm_auth_tuple *at;
-
-	/* Caller ensures we have vectors available */
-	at = vlr_subscr_get_auth_tuple(vsub, afp->auth_tuple_max_use_count);
-	if (!at) {
-		LOGPFSML(fi, LOGL_ERROR, "A previous check ensured that an"
-			 " auth tuple was available, but now there is in fact"
-			 " none.\n");
-		auth_fsm_term(fi, VLR_AUTH_RES_PROC_ERR);
-		return -1;
-	}
-
-	LOGPFSM(fi, "got auth tuple: use_count=%d key_seq=%d\n",
-		at->use_count, at->key_seq);
-
-	OSMO_ASSERT(at);
-
-	/* Transmit auth req to subscriber */
-	afp->auth_requested = true;
-	vsub->last_tuple = at;
-	vsub->vlr->ops.tx_auth_req(vsub->msc_conn_ref, at,
-				   is_umts_auth(afp, at->vec.auth_types));
-	return 0;
-}
-
-/***********************************************************************
- * FSM State Action functions
- ***********************************************************************/
-
-/* Initial State of TS 23.018 AUT_VLR */
-static void auth_fsm_needs_auth(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct auth_fsm_priv *afp = fi->priv;
-	struct vlr_subscr *vsub = afp->vsub;
-
-	OSMO_ASSERT(event == VLR_AUTH_E_START);
-
-	/* Start off with the default max_use_count, possibly change that if we
-	 * need to re-use an old tuple. */
-	afp->auth_tuple_max_use_count = vsub->vlr->cfg.auth_tuple_max_use_count;
-
-	/* Check if we have vectors available */
-	if (!vlr_subscr_has_auth_tuple(vsub, afp->auth_tuple_max_use_count)) {
-		/* Obtain_Authentication_Sets_VLR */
-		vlr_subscr_req_sai(vsub, NULL, NULL);
-		osmo_fsm_inst_state_chg(fi, VLR_SUB_AS_NEEDS_AUTH_WAIT_AI,
-					GSM_29002_TIMER_M, 0);
-	} else {
-		/* go straight ahead with sending auth request */
-		osmo_fsm_inst_state_chg(fi, VLR_SUB_AS_WAIT_RESP,
-					vlr_timer(vsub->vlr, 3260), 3260);
-		_vlr_subscr_authenticate(fi);
-	}
-}
-
-/* Waiting for Authentication Info from HLR */
-static void auth_fsm_wait_ai(struct osmo_fsm_inst *fi, uint32_t event,
-			     void *data)
-{
-	struct auth_fsm_priv *afp = fi->priv;
-	struct vlr_subscr *vsub = afp->vsub;
-	struct osmo_gsup_message *gsup = data;
-
-	if (event == VLR_AUTH_E_HLR_SAI_NACK)
-		LOGPFSM(fi, "GSUP: rx Auth Info Error cause: %d: %s\n",
-			gsup->cause,
-			get_value_string(gsm48_gmm_cause_names, gsup->cause));
-
-	/* We are in what corresponds to the
-	 * Wait_For_Authentication_Sets state of TS 23.018 OAS_VLR */
-	if ((event == VLR_AUTH_E_HLR_SAI_ACK && !gsup->num_auth_vectors)
-	    || (event == VLR_AUTH_E_HLR_SAI_NACK &&
-		gsup->cause != GMM_CAUSE_IMSI_UNKNOWN)
-	    || (event == VLR_AUTH_E_HLR_SAI_ABORT)) {
-		if (vsub->vlr->cfg.auth_reuse_old_sets_on_error
-		    && vlr_subscr_has_auth_tuple(vsub, -1)) {
-			/* To re-use an old tuple, disable the max_use_count
-			 * constraint. */
-			afp->auth_tuple_max_use_count = -1;
-			goto pass;
-		}
-		/* result = procedure error */
-		auth_fsm_term(fi, VLR_AUTH_RES_PROC_ERR);
-		return;
-	}
-
-	switch (event) {
-	case VLR_AUTH_E_HLR_SAI_ACK:
-		vlr_subscr_update_tuples(vsub, gsup);
-		goto pass;
-		break;
-	case VLR_AUTH_E_HLR_SAI_NACK:
-		auth_fsm_term(fi,
-			      gsup->cause == GMM_CAUSE_IMSI_UNKNOWN?
-				      VLR_AUTH_RES_UNKNOWN_SUBSCR
-				      : VLR_AUTH_RES_PROC_ERR);
-		break;
-	}
-
-	return;
-pass:
-	osmo_fsm_inst_state_chg(fi, VLR_SUB_AS_WAIT_RESP,
-				vlr_timer(vsub->vlr, 3260), 3260);
-	_vlr_subscr_authenticate(fi);
-}
-
-/* Waiting for Authentication Response from MS */
-static void auth_fsm_wait_auth_resp(struct osmo_fsm_inst *fi, uint32_t event,
-				    void *data)
-{
-	struct auth_fsm_priv *afp = fi->priv;
-	struct vlr_subscr *vsub = afp->vsub;
-	struct vlr_instance *vlr = vsub->vlr;
-	struct vlr_auth_resp_par *par = data;
-	int rc;
-
-	switch (event) {
-	case VLR_AUTH_E_MS_AUTH_RESP:
-		rc = check_auth_resp(vsub, par->is_r99, par->is_utran,
-				     par->res, par->res_len);
-		if (rc == false) {
-			if (!afp->by_imsi) {
-				vlr->ops.tx_id_req(vsub->msc_conn_ref,
-						   GSM_MI_TYPE_IMSI);
-				osmo_fsm_inst_state_chg(fi,
-						VLR_SUB_AS_WAIT_ID_IMSI,
-						vlr_timer(vlr, 3270), 3270);
-			} else {
-				auth_fsm_term(fi, VLR_AUTH_RES_AUTH_FAILED);
-			}
-		} else {
-			auth_fsm_term(fi, VLR_AUTH_RES_PASSED);
-		}
-		break;
-	case VLR_AUTH_E_MS_AUTH_FAIL:
-		if (par->auts) {
-			/* First failure, start re-sync attempt */
-			vlr_subscr_req_sai(vsub, par->auts,
-					   vsub->last_tuple->vec.rand);
-			osmo_fsm_inst_state_chg(fi,
-					VLR_SUB_AS_NEEDS_AUTH_WAIT_SAI_RESYNC,
-					GSM_29002_TIMER_M, 0);
-		} else
-			auth_fsm_term(fi, VLR_AUTH_RES_AUTH_FAILED);
-		break;
-	}
-}
-
-/* Waiting for Authentication Info from HLR (resync case) */
-static void auth_fsm_wait_ai_resync(struct osmo_fsm_inst *fi,
-				    uint32_t event, void *data)
-{
-	struct auth_fsm_priv *afp = fi->priv;
-	struct vlr_subscr *vsub = afp->vsub;
-	struct osmo_gsup_message *gsup = data;
-
-	/* We are in what corresponds to the
-	 * Wait_For_Authentication_Sets state of TS 23.018 OAS_VLR */
-	if ((event == VLR_AUTH_E_HLR_SAI_ACK && !gsup->num_auth_vectors) ||
-	    (event == VLR_AUTH_E_HLR_SAI_NACK &&
-	     gsup->cause != GMM_CAUSE_IMSI_UNKNOWN) ||
-	    (event == VLR_AUTH_E_HLR_SAI_ABORT)) {
-		/* result = procedure error */
-		auth_fsm_term(fi, VLR_AUTH_RES_PROC_ERR);
-	}
-	switch (event) {
-	case VLR_AUTH_E_HLR_SAI_ACK:
-		vlr_subscr_update_tuples(vsub, gsup);
-		goto pass;
-		break;
-	case VLR_AUTH_E_HLR_SAI_NACK:
-		auth_fsm_term(fi,
-			      gsup->cause == GMM_CAUSE_IMSI_UNKNOWN?
-				      VLR_AUTH_RES_UNKNOWN_SUBSCR
-				      : VLR_AUTH_RES_PROC_ERR);
-		break;
-	}
-
-	return;
-pass:
-	osmo_fsm_inst_state_chg(fi, VLR_SUB_AS_WAIT_RESP_RESYNC,
-				vlr_timer(vsub->vlr, 3260), 3260);
-	_vlr_subscr_authenticate(fi);
-}
-
-/* Waiting for AUTH RESP from MS (re-sync case) */
-static void auth_fsm_wait_auth_resp_resync(struct osmo_fsm_inst *fi,
-					   uint32_t event, void *data)
-{
-	struct auth_fsm_priv *afp = fi->priv;
-	struct vlr_subscr *vsub = afp->vsub;
-	struct vlr_auth_resp_par *par = data;
-	struct vlr_instance *vlr = vsub->vlr;
-	int rc;
-
-	switch (event) {
-	case VLR_AUTH_E_MS_AUTH_RESP:
-		rc = check_auth_resp(vsub, par->is_r99, par->is_utran,
-				     par->res, par->res_len);
-		if (rc == false) {
-			if (!afp->by_imsi) {
-				vlr->ops.tx_id_req(vsub->msc_conn_ref,
-						   GSM_MI_TYPE_IMSI);
-				osmo_fsm_inst_state_chg(fi,
-						VLR_SUB_AS_WAIT_ID_IMSI,
-						vlr_timer(vlr, 3270), 3270);
-			} else {
-				/* Result = Aborted */
-				auth_fsm_term(fi, VLR_AUTH_RES_ABORTED);
-			}
-		} else {
-			/* Result = Pass */
-			auth_fsm_term(fi, VLR_AUTH_RES_PASSED);
-		}
-		break;
-	case VLR_AUTH_E_MS_AUTH_FAIL:
-		/* Second failure: Result = Fail */
-		auth_fsm_term(fi, VLR_AUTH_RES_AUTH_FAILED);
-		break;
-	}
-}
-
-/* AUT_VLR waiting for Obtain_IMSI_VLR result */
-static void auth_fsm_wait_imsi(struct osmo_fsm_inst *fi, uint32_t event,
-				void *data)
-{
-	struct auth_fsm_priv *afp = fi->priv;
-	struct vlr_subscr *vsub = afp->vsub;
-	const char *mi_string = data;
-
-	switch (event) {
-	case VLR_AUTH_E_MS_ID_IMSI:
-		if (vsub->imsi[0]
-		    && !vlr_subscr_matches_imsi(vsub, mi_string)) {
-			LOGVSUBP(LOGL_ERROR, vsub, "IMSI in ID RESP differs:"
-				 " %s\n", mi_string);
-		} else {
-			strncpy(vsub->imsi, mi_string, sizeof(vsub->imsi));
-			vsub->imsi[sizeof(vsub->imsi)-1] = '\0';
-		}
-		/* retry with identity=IMSI */
-		afp->by_imsi = true;
-		osmo_fsm_inst_state_chg(fi, VLR_SUB_AS_NEEDS_AUTH, 0, 0);
-		osmo_fsm_inst_dispatch(fi, VLR_AUTH_E_START, NULL);
-		break;
-	}
-}
-
-static const struct osmo_fsm_state auth_fsm_states[] = {
-	[VLR_SUB_AS_NEEDS_AUTH] = {
-		.name = OSMO_STRINGIFY(VLR_SUB_AS_NEEDS_AUTH),
-		.in_event_mask = S(VLR_AUTH_E_START),
-		.out_state_mask = S(VLR_SUB_AS_NEEDS_AUTH_WAIT_AI) |
-				  S(VLR_SUB_AS_WAIT_RESP),
-		.action = auth_fsm_needs_auth,
-	},
-	[VLR_SUB_AS_NEEDS_AUTH_WAIT_AI] = {
-		.name = OSMO_STRINGIFY(VLR_SUB_AS_NEEDS_AUTH_WAIT_AI),
-		.in_event_mask = S(VLR_AUTH_E_HLR_SAI_ACK) |
-				 S(VLR_AUTH_E_HLR_SAI_NACK),
-		.out_state_mask = S(VLR_SUB_AS_AUTH_FAILED) |
-				  S(VLR_SUB_AS_WAIT_RESP),
-		.action = auth_fsm_wait_ai,
-	},
-	[VLR_SUB_AS_WAIT_RESP] = {
-		.name = OSMO_STRINGIFY(VLR_SUB_AS_WAIT_RESP),
-		.in_event_mask = S(VLR_AUTH_E_MS_AUTH_RESP) |
-				 S(VLR_AUTH_E_MS_AUTH_FAIL),
-		.out_state_mask = S(VLR_SUB_AS_WAIT_ID_IMSI) |
-				  S(VLR_SUB_AS_AUTH_FAILED) |
-				  S(VLR_SUB_AS_AUTHENTICATED) |
-				  S(VLR_SUB_AS_NEEDS_AUTH_WAIT_SAI_RESYNC),
-		.action = auth_fsm_wait_auth_resp,
-	},
-	[VLR_SUB_AS_NEEDS_AUTH_WAIT_SAI_RESYNC] = {
-		.name = OSMO_STRINGIFY(VLR_SUB_AS_NEEDS_AUTH_WAIT_SAI_RESYNC),
-		.in_event_mask = S(VLR_AUTH_E_HLR_SAI_ACK) |
-				 S(VLR_AUTH_E_HLR_SAI_NACK),
-		.out_state_mask = S(VLR_SUB_AS_AUTH_FAILED) |
-				  S(VLR_SUB_AS_WAIT_RESP_RESYNC),
-		.action = auth_fsm_wait_ai_resync,
-	},
-	[VLR_SUB_AS_WAIT_RESP_RESYNC] = {
-		.name = OSMO_STRINGIFY(VLR_SUB_AS_WAIT_RESP_RESYNC),
-		.in_event_mask = S(VLR_AUTH_E_MS_AUTH_RESP) |
-				 S(VLR_AUTH_E_MS_AUTH_FAIL),
-		.out_state_mask = S(VLR_SUB_AS_AUTH_FAILED) |
-				  S(VLR_SUB_AS_AUTHENTICATED),
-		.action = auth_fsm_wait_auth_resp_resync,
-	},
-	[VLR_SUB_AS_WAIT_ID_IMSI] = {
-		.name = OSMO_STRINGIFY(VLR_SUB_AS_WAIT_ID_IMSI),
-		.in_event_mask = S(VLR_AUTH_E_MS_ID_IMSI),
-		.out_state_mask = S(VLR_SUB_AS_NEEDS_AUTH),
-		.action = auth_fsm_wait_imsi,
-	},
-	[VLR_SUB_AS_AUTHENTICATED] = {
-		.name = OSMO_STRINGIFY(VLR_SUB_AS_AUTHENTICATED),
-		.in_event_mask = 0,
-		.out_state_mask = 0,
-	},
-	[VLR_SUB_AS_AUTH_FAILED] = {
-		.name = OSMO_STRINGIFY(VLR_SUB_AS_AUTH_FAILED),
-		.in_event_mask = 0,
-		.out_state_mask = 0,
-		.onenter = auth_fsm_onenter_failed,
-	},
-};
-
-struct osmo_fsm vlr_auth_fsm = {
-	.name = "VLR_Authenticate",
-	.states = auth_fsm_states,
-	.num_states = ARRAY_SIZE(auth_fsm_states),
-	.allstate_event_mask = 0,
-	.allstate_action = NULL,
-	.log_subsys = DVLR,
-	.event_names = fsm_auth_event_names,
-};
-
-/***********************************************************************
- * User API (for SGSN/MSC code)
- ***********************************************************************/
-
-/* MSC->VLR: Start Procedure Authenticate_VLR (TS 23.012 Ch. 4.1.2.2) */
-struct osmo_fsm_inst *auth_fsm_start(struct vlr_subscr *vsub,
-				     uint32_t log_level,
-				     struct osmo_fsm_inst *parent,
-				     uint32_t parent_term_event,
-				     bool is_r99,
-				     bool is_utran)
-{
-	struct osmo_fsm_inst *fi;
-	struct auth_fsm_priv *afp;
-
-	fi = osmo_fsm_inst_alloc_child(&vlr_auth_fsm, parent,
-					parent_term_event);
-
-
-	afp = talloc_zero(fi, struct auth_fsm_priv);
-	if (!afp) {
-		osmo_fsm_inst_dispatch(parent, parent_term_event, 0);
-		return NULL;
-	}
-
-	afp->vsub = vsub;
-	if (vsub->imsi[0])
-		afp->by_imsi = true;
-	afp->is_r99 = is_r99;
-	afp->is_utran = is_utran;
-	fi->priv = afp;
-	vsub->auth_fsm = fi;
-
-	osmo_fsm_inst_dispatch(fi, VLR_AUTH_E_START, NULL);
-
-	return fi;
-}
diff --git a/src/libvlr/vlr_auth_fsm.h b/src/libvlr/vlr_auth_fsm.h
deleted file mode 100644
index 226435f..0000000
--- a/src/libvlr/vlr_auth_fsm.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#pragma once
-
-#include <osmocom/core/utils.h>
-
-/* Parameters to VLR_AUTH_E_MS_AUTH_RESP */
-struct vlr_auth_resp_par {
-	bool is_r99;
-	bool is_utran;
-	const uint8_t *res;
-	unsigned int res_len;
-	const uint8_t *auts;
-};
-
-/* Result communicated back to parent FMS */
-enum vlr_auth_fsm_result {
-	VLR_AUTH_RES_ABORTED,
-	VLR_AUTH_RES_UNKNOWN_SUBSCR,
-	VLR_AUTH_RES_PROC_ERR,
-	VLR_AUTH_RES_AUTH_FAILED,
-	VLR_AUTH_RES_PASSED,
-};
-
-extern const struct value_string vlr_auth_fsm_result_names[];
-static inline const char *vlr_auth_fsm_result_name(enum vlr_auth_fsm_result val)
-{
-	return get_value_string(vlr_auth_fsm_result_names, val);
-}
-
-enum vlr_fsm_auth_event {
-	VLR_AUTH_E_START,
-	/* TS 23.018 OAS_VLR1(2): SendAuthInfo ACK from HLR */
-	VLR_AUTH_E_HLR_SAI_ACK,
-	/* TS 23.018 OAS_VLR1(2): SendAuthInfo NACK from HLR */
-	VLR_AUTH_E_HLR_SAI_NACK,
-	/* FIXME: merge with NACK? */
-	VLR_AUTH_E_HLR_SAI_ABORT,
-	/* Authentication Response from MS */
-	VLR_AUTH_E_MS_AUTH_RESP,
-	/* Authentication Failure from MS */
-	VLR_AUTH_E_MS_AUTH_FAIL,
-	/* Identity Response (IMSI) from MS */
-	VLR_AUTH_E_MS_ID_IMSI,
-};
-
-struct osmo_fsm vlr_auth_fsm;
-
-struct osmo_fsm_inst *auth_fsm_start(struct vlr_subscr *vsub,
-				     uint32_t log_level,
-				     struct osmo_fsm_inst *parent,
-				     uint32_t parent_term_event,
-				     bool is_r99,
-				     bool is_utran);
diff --git a/src/libvlr/vlr_core.h b/src/libvlr/vlr_core.h
deleted file mode 100644
index 0e63c7e..0000000
--- a/src/libvlr/vlr_core.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-
-#include <openbsc/vlr.h>
-
-#define LOGGSUPP(level, gsup, fmt, args...) \
-	LOGP(DVLR, level, "GSUP(%s) " fmt, \
-	     (gsup)->imsi, \
-	     ## args)
-
-#define LOGVSUBP(level, vsub, fmt, args...) \
-	LOGP(DVLR, level, "SUBSCR(%s) " fmt, \
-		vlr_subscr_name(vsub), ## args)
-
-
-const char *vlr_subscr_name(struct vlr_subscr *vsub);
-int vlr_subscr_req_lu(struct vlr_subscr *vsub, bool is_ps);
-int vlr_subscr_req_sai(struct vlr_subscr *vsub, const uint8_t *auts,
-		       const uint8_t *auts_rand);
-struct vlr_subscr *vlr_subscr_alloc(struct vlr_instance *vlr);
-void vlr_subscr_update_tuples(struct vlr_subscr *vsub,
-			      const struct osmo_gsup_message *gsup);
diff --git a/src/libvlr/vlr_lu_fsm.c b/src/libvlr/vlr_lu_fsm.c
deleted file mode 100644
index 94bea56..0000000
--- a/src/libvlr/vlr_lu_fsm.c
+++ /dev/null
@@ -1,1449 +0,0 @@
-/* Osmocom Visitor Location Register (VLR): Location Update FSMs */
-
-/* (C) 2016 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/>.
- *
- */
-
-#include <osmocom/core/fsm.h>
-#include <osmocom/gsm/gsup.h>
-#include <openbsc/vlr.h>
-#include <openbsc/debug.h>
-
-#include "vlr_core.h"
-#include "vlr_auth_fsm.h"
-#include "vlr_lu_fsm.h"
-
-#define S(x)	(1 << (x))
-
-#define LU_TIMEOUT_LONG		30
-
-enum vlr_fsm_result {
-	VLR_FSM_RESULT_NONE,
-	VLR_FSM_RESULT_SUCCESS,
-	VLR_FSM_RESULT_FAILURE,
-};
-
-
-/***********************************************************************
- * Update_HLR_VLR, TS 23.012 Chapter 4.1.2.4
- ***********************************************************************/
-
-enum upd_hlr_vlr_state {
-	UPD_HLR_VLR_S_INIT,
-	UPD_HLR_VLR_S_WAIT_FOR_DATA,
-	UPD_HLR_VLR_S_DONE,
-};
-
-enum upd_hlr_vlr_evt {
-	UPD_HLR_VLR_E_START,
-	UPD_HLR_VLR_E_INS_SUB_DATA,
-	UPD_HLR_VLR_E_ACT_TRACE_MODE,
-	UPD_HLR_VLR_E_FW_CHECK_SS_IND,
-	UPD_HLR_VLR_E_UPD_LOC_ACK,
-	UPD_HLR_VLR_E_UPD_LOC_NACK,
-};
-
-static const struct value_string upd_hlr_vlr_event_names[] = {
-	OSMO_VALUE_STRING(UPD_HLR_VLR_E_START),
-	OSMO_VALUE_STRING(UPD_HLR_VLR_E_INS_SUB_DATA),
-	OSMO_VALUE_STRING(UPD_HLR_VLR_E_ACT_TRACE_MODE),
-	OSMO_VALUE_STRING(UPD_HLR_VLR_E_FW_CHECK_SS_IND),
-	OSMO_VALUE_STRING(UPD_HLR_VLR_E_UPD_LOC_ACK),
-	OSMO_VALUE_STRING(UPD_HLR_VLR_E_UPD_LOC_NACK),
-	{ 0, NULL }
-};
-
-static void upd_hlr_vlr_fsm_init(struct osmo_fsm_inst *fi, uint32_t event,
-				 void *data)
-{
-	struct vlr_subscr *vsub = fi->priv;
-
-	OSMO_ASSERT(event == UPD_HLR_VLR_E_START);
-
-	/* Send UpdateLocation to HLR */
-	vlr_subscr_req_lu(vsub, vsub->vlr->cfg.is_ps);
-	osmo_fsm_inst_state_chg(fi, UPD_HLR_VLR_S_WAIT_FOR_DATA,
-				LU_TIMEOUT_LONG, 0);
-}
-
-static void upd_hlr_vlr_fsm_wait_data(struct osmo_fsm_inst *fi, uint32_t event,
-				      void *data)
-{
-	struct vlr_subscr *vsub = fi->priv;
-
-	switch (event) {
-	case UPD_HLR_VLR_E_INS_SUB_DATA:
-		/* FIXME: Insert_Subscr_Data_VLR */
-		break;
-	case UPD_HLR_VLR_E_ACT_TRACE_MODE:
-		/* TODO: Activate_Tracing_VLR */
-		break;
-	case UPD_HLR_VLR_E_FW_CHECK_SS_IND:
-		/* TODO: Forward Check SS Ind to MSC */
-		break;
-	case UPD_HLR_VLR_E_UPD_LOC_ACK:
-		/* Inside Update_HLR_VLR after UpdateLocationAck */
-		vsub->sub_dataconf_by_hlr_ind = true;
-		vsub->loc_conf_in_hlr_ind = true;
-		osmo_fsm_inst_state_chg(fi, UPD_HLR_VLR_S_DONE, 0, 0);
-		osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
-		break;
-	case UPD_HLR_VLR_E_UPD_LOC_NACK:
-		/* Inside Update_HLR_VLR after UpdateLocationNack */
-		/* TODO: Check_User_Error_In_Serving_Network_Entity */
-		vsub->sub_dataconf_by_hlr_ind = false;
-		vsub->loc_conf_in_hlr_ind = false;
-		osmo_fsm_inst_state_chg(fi, UPD_HLR_VLR_S_DONE, 0, 0);
-		/* Data is a pointer to a gsm48_gmm_cause which we
-		 * simply pass through */
-		osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, data);
-		break;
-	}
-}
-
-static const struct osmo_fsm_state upd_hlr_vlr_states[] = {
-	[UPD_HLR_VLR_S_INIT] = {
-		.in_event_mask = S(UPD_HLR_VLR_E_START),
-		.out_state_mask = S(UPD_HLR_VLR_S_WAIT_FOR_DATA),
-		.name = OSMO_STRINGIFY(UPD_HLR_VLR_S_INIT),
-		.action = upd_hlr_vlr_fsm_init,
-	},
-	[UPD_HLR_VLR_S_WAIT_FOR_DATA] = {
-		.in_event_mask = S(UPD_HLR_VLR_E_INS_SUB_DATA) |
-				 S(UPD_HLR_VLR_E_ACT_TRACE_MODE) |
-				 S(UPD_HLR_VLR_E_FW_CHECK_SS_IND) |
-				 S(UPD_HLR_VLR_E_UPD_LOC_ACK) |
-				 S(UPD_HLR_VLR_E_UPD_LOC_NACK),
-		.out_state_mask = S(UPD_HLR_VLR_S_DONE),
-		.name = OSMO_STRINGIFY(UPD_HLR_VLR_S_WAIT_FOR_DATA),
-		.action = upd_hlr_vlr_fsm_wait_data,
-	},
-	[UPD_HLR_VLR_S_DONE] = {
-		.name = OSMO_STRINGIFY(UPD_HLR_VLR_S_DONE),
-	},
-};
-
-static struct osmo_fsm upd_hlr_vlr_fsm = {
-	.name = "upd_hlr_vlr_fsm",
-	.states = upd_hlr_vlr_states,
-	.num_states = ARRAY_SIZE(upd_hlr_vlr_states),
-	.allstate_event_mask = 0,
-	.allstate_action = NULL,
-	.log_subsys = DVLR,
-	.event_names = upd_hlr_vlr_event_names,
-};
-
-struct osmo_fsm_inst *
-upd_hlr_vlr_proc_start(struct osmo_fsm_inst *parent,
-		       struct vlr_subscr *vsub,
-		       uint32_t parent_event)
-{
-	struct osmo_fsm_inst *fi;
-
-	fi = osmo_fsm_inst_alloc_child(&upd_hlr_vlr_fsm, parent,
-					parent_event);
-	if (!fi)
-		return NULL;
-
-	fi->priv = vsub;
-	osmo_fsm_inst_dispatch(fi, UPD_HLR_VLR_E_START, NULL);
-
-	return fi;
-}
-
-
-/***********************************************************************
- * Subscriber_Present_VLR, TS 29.002 Chapter 25.10.1
- ***********************************************************************/
-
-enum sub_pres_vlr_state {
-	SUB_PRES_VLR_S_INIT,
-	SUB_PRES_VLR_S_WAIT_FOR_HLR,
-	SUB_PRES_VLR_S_DONE,
-};
-
-enum sub_pres_vlr_event {
-	SUB_PRES_VLR_E_START,
-	SUB_PRES_VLR_E_READY_SM_CNF,
-	SUB_PRES_VLR_E_READY_SM_ERR,
-};
-
-static const struct value_string sub_pres_vlr_event_names[] = {
-	OSMO_VALUE_STRING(SUB_PRES_VLR_E_START),
-	OSMO_VALUE_STRING(SUB_PRES_VLR_E_READY_SM_CNF),
-	OSMO_VALUE_STRING(SUB_PRES_VLR_E_READY_SM_ERR),
-	{ 0, NULL }
-};
-
-static void sub_pres_vlr_fsm_init(struct osmo_fsm_inst *fi, uint32_t event,
-				  void *data)
-{
-	struct vlr_subscr *vsub = fi->priv;
-	OSMO_ASSERT(event == SUB_PRES_VLR_E_START);
-
-	if (!vsub->ms_not_reachable_flag) {
-		osmo_fsm_inst_state_chg(fi, SUB_PRES_VLR_S_DONE, 0, 0);
-		osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
-		return;
-	}
-	/* FIXME: Send READY_FOR_SM via GSUP */
-	osmo_fsm_inst_state_chg(fi, SUB_PRES_VLR_S_WAIT_FOR_HLR,
-				LU_TIMEOUT_LONG, 0);
-}
-
-static void sub_pres_vlr_fsm_wait_hlr(struct osmo_fsm_inst *fi, uint32_t event,
-				      void *data)
-{
-	struct vlr_subscr *vsub = fi->priv;
-
-	switch (event) {
-	case SUB_PRES_VLR_E_READY_SM_CNF:
-		vsub->ms_not_reachable_flag = false;
-		break;
-	case SUB_PRES_VLR_E_READY_SM_ERR:
-		break;
-	}
-	osmo_fsm_inst_state_chg(fi, SUB_PRES_VLR_S_DONE, 0, 0);
-	osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL);
-}
-
-static const struct osmo_fsm_state sub_pres_vlr_states[] = {
-	[SUB_PRES_VLR_S_INIT] = {
-		.in_event_mask = S(SUB_PRES_VLR_E_START),
-		.out_state_mask = S(SUB_PRES_VLR_S_WAIT_FOR_HLR) |
-				  S(SUB_PRES_VLR_S_DONE),
-		.name = OSMO_STRINGIFY(SUB_PRES_VLR_S_INIT),
-		.action = sub_pres_vlr_fsm_init,
-	},
-	[SUB_PRES_VLR_S_WAIT_FOR_HLR] = {
-		.in_event_mask = S(SUB_PRES_VLR_E_READY_SM_CNF) |
-				 S(SUB_PRES_VLR_E_READY_SM_ERR),
-		.out_state_mask = S(SUB_PRES_VLR_S_DONE),
-		.name = OSMO_STRINGIFY(SUB_PRES_VLR_S_WAIT_FOR_HLR),
-		.action = sub_pres_vlr_fsm_wait_hlr,
-	},
-	[SUB_PRES_VLR_S_DONE] = {
-		.name = OSMO_STRINGIFY(SUB_PRES_VLR_S_DONE),
-	},
-};
-
-static struct osmo_fsm sub_pres_vlr_fsm = {
-	.name = "sub_pres_vlr_fsm",
-	.states = sub_pres_vlr_states,
-	.num_states = ARRAY_SIZE(sub_pres_vlr_states),
-	.allstate_event_mask = 0,
-	.allstate_action = NULL,
-	.log_subsys = DVLR,
-	.event_names = sub_pres_vlr_event_names,
-};
-
-struct osmo_fsm_inst *sub_pres_vlr_fsm_start(struct osmo_fsm_inst *parent,
-					     struct vlr_subscr *vsub,
-					     uint32_t term_event)
-{
-	struct osmo_fsm_inst *fi;
-
-	fi = osmo_fsm_inst_alloc_child(&sub_pres_vlr_fsm, parent,
-					term_event);
-	if (!fi)
-		return NULL;
-
-	fi->priv = vsub;
-	osmo_fsm_inst_dispatch(fi, SUB_PRES_VLR_E_START, NULL);
-
-	return fi;
-}
-
-/***********************************************************************
- * Location_Update_Completion_VLR, TS 23.012 Chapter 4.1.2.3
- ***********************************************************************/
-
-enum lu_compl_vlr_state {
-	LU_COMPL_VLR_S_INIT,
-	LU_COMPL_VLR_S_WAIT_SUB_PRES,
-	LU_COMPL_VLR_S_WAIT_IMEI,
-	LU_COMPL_VLR_S_WAIT_IMEI_TMSI,
-	LU_COMPL_VLR_S_WAIT_TMSI_CNF,
-	LU_COMPL_VLR_S_DONE,
-};
-
-enum lu_compl_vlr_event {
-	LU_COMPL_VLR_E_START,
-	LU_COMPL_VLR_E_SUB_PRES_COMPL,
-	LU_COMPL_VLR_E_IMEI_CHECK_ACK,
-	LU_COMPL_VLR_E_IMEI_CHECK_NACK,
-	LU_COMPL_VLR_E_NEW_TMSI_ACK,
-};
-
-static const struct value_string lu_compl_vlr_event_names[] = {
-	OSMO_VALUE_STRING(LU_COMPL_VLR_E_START),
-	OSMO_VALUE_STRING(LU_COMPL_VLR_E_SUB_PRES_COMPL),
-	OSMO_VALUE_STRING(LU_COMPL_VLR_E_IMEI_CHECK_ACK),
-	OSMO_VALUE_STRING(LU_COMPL_VLR_E_IMEI_CHECK_NACK),
-	OSMO_VALUE_STRING(LU_COMPL_VLR_E_NEW_TMSI_ACK),
-	{ 0, NULL }
-};
-
-struct lu_compl_vlr_priv {
-	struct vlr_subscr *vsub;
-	void *msc_conn_ref;
-	struct osmo_fsm_inst *sub_pres_vlr_fsm;
-	uint32_t parent_event_success;
-	uint32_t parent_event_failure;
-	void *parent_event_data;
-	enum vlr_fsm_result result;
-	uint8_t cause;
-	bool assign_tmsi;
-};
-
-static void _vlr_lu_compl_fsm_done(struct osmo_fsm_inst *fi,
-				   enum vlr_fsm_result result,
-				   uint8_t cause)
-{
-	struct lu_compl_vlr_priv *lcvp = fi->priv;
-	lcvp->result = result;
-	lcvp->cause = cause;
-	osmo_fsm_inst_state_chg(fi, LU_COMPL_VLR_S_DONE, 0, 0);
-}
-
-static void vlr_lu_compl_fsm_success(struct osmo_fsm_inst *fi)
-{
-	struct lu_compl_vlr_priv *lcvp = fi->priv;
-	struct vlr_subscr *vsub = lcvp->vsub;
-	if (!vsub->lu_complete) {
-		vsub->lu_complete = true;
-		/* Balanced by vlr_subscr_rx_imsi_detach() */
-		vlr_subscr_get(vsub);
-	}
-	_vlr_lu_compl_fsm_done(fi, VLR_FSM_RESULT_SUCCESS, 0);
-}
-
-static void vlr_lu_compl_fsm_failure(struct osmo_fsm_inst *fi, uint8_t cause)
-{
-	struct lu_compl_vlr_priv *lcvp = fi->priv;
-	lcvp->vsub->vlr->ops.tx_lu_rej(lcvp->msc_conn_ref, cause);
-	_vlr_lu_compl_fsm_done(fi, VLR_FSM_RESULT_FAILURE, cause);
-}
-
-static void vlr_lu_compl_fsm_dispatch_result(struct osmo_fsm_inst *fi,
-					     uint32_t prev_state)
-{
-	struct lu_compl_vlr_priv *lcvp = fi->priv;
-	if (!fi->proc.parent) {
-		LOGPFSML(fi, LOGL_ERROR, "No parent FSM\n");
-		return;
-	}
-	osmo_fsm_inst_dispatch(fi->proc.parent,
-			       (lcvp->result == VLR_FSM_RESULT_SUCCESS)
-			       ? lcvp->parent_event_success
-			       : lcvp->parent_event_failure,
-			       &lcvp->cause);
-}
-
-static void lu_compl_vlr_init(struct osmo_fsm_inst *fi, uint32_t event,
-			      void *data)
-{
-	struct lu_compl_vlr_priv *lcvp = fi->priv;
-	struct vlr_subscr *vsub = lcvp->vsub;
-	struct vlr_instance *vlr;
-	OSMO_ASSERT(vsub);
-	vlr = vsub->vlr;
-	OSMO_ASSERT(vlr);
-
-	OSMO_ASSERT(event == LU_COMPL_VLR_E_START);
-
-	/* TODO: National Roaming restrictions? */
-	/* TODO: Roaming restriction due to unsupported feature in subscriber
-	 * data? */
-	/* TODO: Regional subscription restriction? */
-	/* TODO: Administrative restriction of subscribres' access feature? */
-	/* TODO: AccessRestrictuionData parameter available? */
-	/* TODO: AccessRestrictionData permits RAT? */
-	/* Node 1 */
-	/* TODO: Autonomous CSG supported in VPLMN and allowed by HPLMN? */
-	/* TODO: Hybrid Cel / CSG Cell */
-	/* Node 2 */
-	vsub->la_allowed = true;
-	vsub->imsi_detached_flag = false;
-	/* Start Subscriber_Present_VLR Procedure */
-	osmo_fsm_inst_state_chg(fi, LU_COMPL_VLR_S_WAIT_SUB_PRES,
-				LU_TIMEOUT_LONG, 0);
-
-	lcvp->sub_pres_vlr_fsm = sub_pres_vlr_fsm_start(fi, vsub,
-						LU_COMPL_VLR_E_SUB_PRES_COMPL);
-
-}
-
-static void lu_compl_vlr_new_tmsi(struct osmo_fsm_inst *fi)
-{
-	struct lu_compl_vlr_priv *lcvp = fi->priv;
-	struct vlr_subscr *vsub = lcvp->vsub;
-	struct vlr_instance *vlr = vsub->vlr;
-
-	LOGPFSM(fi, "%s()\n", __func__);
-
-	if (vlr_subscr_alloc_tmsi(vsub)) {
-		vlr_lu_compl_fsm_failure(fi,
-					 GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER);
-		return;
-	}
-
-	osmo_fsm_inst_state_chg(fi, LU_COMPL_VLR_S_WAIT_TMSI_CNF,
-				vlr_timer(vlr, 3250), 3250);
-
-	vlr->ops.tx_lu_acc(lcvp->msc_conn_ref, vsub->tmsi_new);
-}
-
-/* After completion of Subscriber_Present_VLR */
-static void lu_compl_vlr_wait_subscr_pres(struct osmo_fsm_inst *fi,
-					  uint32_t event,
-					  void *data)
-{
-	struct lu_compl_vlr_priv *lcvp = fi->priv;
-	struct vlr_subscr *vsub = lcvp->vsub;
-	struct vlr_instance *vlr = vsub->vlr;
-
-	OSMO_ASSERT(event == LU_COMPL_VLR_E_SUB_PRES_COMPL);
-
-	lcvp->sub_pres_vlr_fsm = NULL;
-
-	/* TODO: Trace_Subscriber_Activity_VLR */
-
-	if (vlr->cfg.check_imei_rqd) {
-		/* Check IMEI VLR */
-		osmo_fsm_inst_state_chg(fi,
-					lcvp->assign_tmsi ?
-					  LU_COMPL_VLR_S_WAIT_IMEI_TMSI
-					: LU_COMPL_VLR_S_WAIT_IMEI,
-					vlr_timer(vlr, 3270), 3270);
-		vlr->ops.tx_id_req(lcvp->msc_conn_ref, GSM_MI_TYPE_IMEI);
-		return;
-	}
-
-	/* Do we need to allocate a TMSI? */
-	if (lcvp->assign_tmsi) {
-		lu_compl_vlr_new_tmsi(fi);
-		return;
-	}
-
-	/* Location Updating Accept */
-	vlr->ops.tx_lu_acc(lcvp->msc_conn_ref, GSM_RESERVED_TMSI);
-	vlr_lu_compl_fsm_success(fi);
-}
-
-/* Waiting for completion of CHECK_IMEI_VLR */
-static void lu_compl_vlr_wait_imei(struct osmo_fsm_inst *fi, uint32_t event,
-				   void *data)
-{
-	struct lu_compl_vlr_priv *lcvp = fi->priv;
-	struct vlr_subscr *vsub = lcvp->vsub;
-	struct vlr_instance *vlr = vsub->vlr;
-
-	switch (event) {
-	case LU_COMPL_VLR_E_IMEI_CHECK_ACK:
-		if (!vsub->imei[0]) {
-			/* Abort: Do nothing */
-			vlr_lu_compl_fsm_failure(fi,
-						 GSM48_REJECT_PROTOCOL_ERROR);
-			return;
-		}
-		/* Pass */
-		break;
-
-	case LU_COMPL_VLR_E_IMEI_CHECK_NACK:
-		vlr_lu_compl_fsm_failure(fi, GSM48_REJECT_ILLEGAL_ME);
-		/* FIXME: IMEI Check Fail to VLR Application (Detach IMSI VLR) */
-		return;
-	}
-
-	/* IMEI is available. Allocate TMSI if needed. */
-	if (lcvp->assign_tmsi) {
-		if (fi->state != LU_COMPL_VLR_S_WAIT_IMEI_TMSI)
-			LOGPFSML(fi, LOGL_ERROR,
-				 "TMSI required, expected to be in state"
-				 " LU_COMPL_VLR_S_WAIT_IMEI_TMSI,"
-				 " am in %s instead\n",
-				 osmo_fsm_state_name(fi->fsm, fi->state));
-			/* Logged an error, continue anyway. */
-
-		lu_compl_vlr_new_tmsi(fi);
-
-		/* Wait for TMSI ack */
-		return;
-	}
-
-	/* No TMSI needed, accept now. */
-	vlr->ops.tx_lu_acc(lcvp->msc_conn_ref, GSM_RESERVED_TMSI);
-	vlr_lu_compl_fsm_success(fi);
-}
-
-/* Waiting for TMSI confirmation */
-static void lu_compl_vlr_wait_tmsi(struct osmo_fsm_inst *fi, uint32_t event,
-				   void *data)
-{
-	struct lu_compl_vlr_priv *lcvp = fi->priv;
-	struct vlr_subscr *vsub = lcvp->vsub;
-
-	OSMO_ASSERT(event == LU_COMPL_VLR_E_NEW_TMSI_ACK);
-
-	if (!vsub || vsub->tmsi_new == GSM_RESERVED_TMSI) {
-		LOGPFSML(fi, LOGL_ERROR, "TMSI Realloc Compl implies that"
-			 " the subscriber has a new TMSI allocated, but"
-			 " the new TMSI is unset.\n");
-		vlr_lu_compl_fsm_failure(fi, GSM48_REJECT_NETWORK_FAILURE);
-		return;
-	}
-
-	vsub->tmsi = vsub->tmsi_new;
-	vsub->tmsi_new = GSM_RESERVED_TMSI;
-
-	vlr_lu_compl_fsm_success(fi);
-}
-
-static const struct osmo_fsm_state lu_compl_vlr_states[] = {
-	[LU_COMPL_VLR_S_INIT] = {
-		.in_event_mask = S(LU_COMPL_VLR_E_START),
-		.out_state_mask = S(LU_COMPL_VLR_S_DONE) |
-				  S(LU_COMPL_VLR_S_WAIT_SUB_PRES) |
-				  S(LU_COMPL_VLR_S_WAIT_IMEI),
-		.name = OSMO_STRINGIFY(LU_COMPL_VLR_S_INIT),
-		.action = lu_compl_vlr_init,
-	},
-	[LU_COMPL_VLR_S_WAIT_SUB_PRES] = {
-		.in_event_mask = S(LU_COMPL_VLR_E_SUB_PRES_COMPL),
-		.out_state_mask = S(LU_COMPL_VLR_S_WAIT_IMEI) |
-				  S(LU_COMPL_VLR_S_WAIT_IMEI_TMSI) |
-				  S(LU_COMPL_VLR_S_WAIT_TMSI_CNF) |
-				  S(LU_COMPL_VLR_S_DONE),
-		.name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_SUB_PRES),
-		.action = lu_compl_vlr_wait_subscr_pres,
-	},
-	[LU_COMPL_VLR_S_WAIT_IMEI] = {
-		.in_event_mask = S(LU_COMPL_VLR_E_IMEI_CHECK_ACK) |
-				 S(LU_COMPL_VLR_E_IMEI_CHECK_NACK),
-		.out_state_mask = S(LU_COMPL_VLR_S_DONE),
-		.name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_IMEI),
-		.action = lu_compl_vlr_wait_imei,
-	},
-	[LU_COMPL_VLR_S_WAIT_IMEI_TMSI] = {
-		.in_event_mask = S(LU_COMPL_VLR_E_IMEI_CHECK_ACK) |
-				 S(LU_COMPL_VLR_E_IMEI_CHECK_NACK),
-		.out_state_mask = S(LU_COMPL_VLR_S_DONE) |
-				  S(LU_COMPL_VLR_S_WAIT_TMSI_CNF),
-		.name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_IMEI_TMSI),
-		.action = lu_compl_vlr_wait_imei,
-	},
-	[LU_COMPL_VLR_S_WAIT_TMSI_CNF] = {
-		.in_event_mask = S(LU_COMPL_VLR_E_NEW_TMSI_ACK),
-		.out_state_mask = S(LU_COMPL_VLR_S_DONE),
-		.name = OSMO_STRINGIFY(LU_COMPL_VLR_S_WAIT_TMSI_CNF),
-		.action = lu_compl_vlr_wait_tmsi,
-	},
-	[LU_COMPL_VLR_S_DONE] = {
-		.name = OSMO_STRINGIFY(LU_COMPL_VLR_S_DONE),
-		.onenter = vlr_lu_compl_fsm_dispatch_result,
-	},
-};
-
-static struct osmo_fsm lu_compl_vlr_fsm = {
-	.name = "lu_compl_vlr_fsm",
-	.states = lu_compl_vlr_states,
-	.num_states = ARRAY_SIZE(lu_compl_vlr_states),
-	.allstate_event_mask = 0,
-	.allstate_action = NULL,
-	.log_subsys = DVLR,
-	.event_names = lu_compl_vlr_event_names,
-};
-
-struct osmo_fsm_inst *
-lu_compl_vlr_proc_alloc(struct osmo_fsm_inst *parent,
-			struct vlr_subscr *vsub,
-			void *msc_conn_ref,
-			uint32_t parent_event_success,
-			uint32_t parent_event_failure,
-			bool assign_tmsi)
-{
-	struct osmo_fsm_inst *fi;
-	struct lu_compl_vlr_priv *lcvp;
-
-	fi = osmo_fsm_inst_alloc_child(&lu_compl_vlr_fsm, parent,
-				       parent_event_failure);
-	if (!fi)
-		return NULL;
-
-	lcvp = talloc_zero(fi, struct lu_compl_vlr_priv);
-	lcvp->vsub = vsub;
-	lcvp->msc_conn_ref = msc_conn_ref;
-	lcvp->parent_event_success = parent_event_success;
-	lcvp->parent_event_failure = parent_event_failure;
-	lcvp->assign_tmsi = assign_tmsi;
-	fi->priv = lcvp;
-
-	return fi;
-}
-
-
-/***********************************************************************
- * Update_Location_Area_VLR, TS 23.012 Chapter 4.1.2.1
- ***********************************************************************/
-
-static const struct value_string fsm_lu_event_names[] = {
-	OSMO_VALUE_STRING(VLR_ULA_E_UPDATE_LA),
-	OSMO_VALUE_STRING(VLR_ULA_E_SEND_ID_ACK),
-	OSMO_VALUE_STRING(VLR_ULA_E_SEND_ID_NACK),
-	OSMO_VALUE_STRING(VLR_ULA_E_AUTH_RES),
-	OSMO_VALUE_STRING(VLR_ULA_E_CIPH_RES),
-	OSMO_VALUE_STRING(VLR_ULA_E_ID_IMSI),
-	OSMO_VALUE_STRING(VLR_ULA_E_ID_IMEI),
-	OSMO_VALUE_STRING(VLR_ULA_E_ID_IMEISV),
-	OSMO_VALUE_STRING(VLR_ULA_E_HLR_LU_RES),
-	OSMO_VALUE_STRING(VLR_ULA_E_UPD_HLR_COMPL),
-	OSMO_VALUE_STRING(VLR_ULA_E_LU_COMPL_SUCCESS),
-	OSMO_VALUE_STRING(VLR_ULA_E_LU_COMPL_FAILURE),
-	OSMO_VALUE_STRING(VLR_ULA_E_NEW_TMSI_ACK),
-	{ 0, NULL }
-};
-
-struct lu_fsm_priv {
-	struct vlr_instance *vlr;
-	struct vlr_subscr *vsub;
-	void *msc_conn_ref;
-	struct osmo_fsm_inst *upd_hlr_vlr_fsm;
-	struct osmo_fsm_inst *lu_compl_vlr_fsm;
-	uint32_t parent_event_success;
-	uint32_t parent_event_failure;
-	void *parent_event_data;
-	enum vlr_fsm_result result;
-	uint8_t rej_cause;
-
-	enum vlr_lu_type type;
-	bool lu_by_tmsi;
-	char imsi[16];
-	uint32_t tmsi;
-	struct osmo_location_area_id old_lai;
-	struct osmo_location_area_id new_lai;
-	bool authentication_required;
-	enum vlr_ciph ciphering_required;
-	bool is_r99;
-	bool is_utran;
-	bool assign_tmsi;
-};
-
-
-/* Determine if given location area is served by this VLR */
-static bool lai_in_this_vlr(struct vlr_instance *vlr,
-			    const struct osmo_location_area_id *lai)
-{
-	/* TODO: VLR needs to keep a locally configued list of LAIs */
-	return true;
-}
-
-/* Determine if authentication is required */
-static bool is_auth_required(struct lu_fsm_priv *lfp)
-{
-	/* The cases where the authentication procedure should be used
-	 * are defined in 3GPP TS 33.102 */
-	/* For now we use a default value passed in to vlr_lu_fsm(). */
-	return lfp->authentication_required
-	       || (lfp->ciphering_required != VLR_CIPH_NONE);
-}
-
-/* Determine if ciphering is required */
-static bool is_ciph_required(struct lu_fsm_priv *lfp)
-{
-	return lfp->ciphering_required != VLR_CIPH_NONE;
-}
-
-/* Determine if a HLR Update is required */
-static bool hlr_update_needed(struct vlr_subscr *vsub)
-{
-	/* TODO: properly decide this, rather than always assuming we
-	 * need to update the HLR. */
-	return true;
-}
-
-static void lu_fsm_dispatch_result(struct osmo_fsm_inst *fi,
-				   uint32_t prev_state)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	if (!fi->proc.parent) {
-		LOGPFSML(fi, LOGL_ERROR, "No parent FSM\n");
-		return;
-	}
-	osmo_fsm_inst_dispatch(fi->proc.parent,
-			       (lfp->result == VLR_FSM_RESULT_SUCCESS)
-			       ? lfp->parent_event_success
-			       : lfp->parent_event_failure,
-			       lfp->parent_event_data);
-}
-
-static void _lu_fsm_done(struct osmo_fsm_inst *fi,
-			 enum vlr_fsm_result result)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	lfp->result = result;
-	osmo_fsm_inst_state_chg(fi, VLR_ULA_S_DONE, 0, 0);
-}
-
-static void lu_fsm_success(struct osmo_fsm_inst *fi)
-{
-	_lu_fsm_done(fi, VLR_FSM_RESULT_SUCCESS);
-}
-
-static void lu_fsm_failure(struct osmo_fsm_inst *fi, uint8_t rej_cause)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	if (rej_cause)
-		lfp->vlr->ops.tx_lu_rej(lfp->msc_conn_ref, rej_cause);
-	_lu_fsm_done(fi, VLR_FSM_RESULT_FAILURE);
-}
-
-static void vlr_loc_upd_start_lu_compl_fsm(struct osmo_fsm_inst *fi)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	lfp->lu_compl_vlr_fsm =
-		lu_compl_vlr_proc_alloc(fi, lfp->vsub, lfp->msc_conn_ref,
-					VLR_ULA_E_LU_COMPL_SUCCESS,
-					VLR_ULA_E_LU_COMPL_FAILURE,
-					lfp->assign_tmsi);
-
-	osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm, LU_COMPL_VLR_E_START, NULL);
-}
-
-static void lu_fsm_discard_lu_compl_fsm(struct osmo_fsm_inst *fi)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	if (!lfp->lu_compl_vlr_fsm)
-		return;
-	osmo_fsm_inst_term(lfp->lu_compl_vlr_fsm, OSMO_FSM_TERM_PARENT, NULL);
-}
-
-/* 4.1.2.1 Node 4 */
-static void vlr_loc_upd_node_4(struct osmo_fsm_inst *fi)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	struct vlr_subscr *vsub = lfp->vsub;
-	bool hlr_unknown = false;
-
-	LOGPFSM(fi, "%s()\n", __func__);
-
-	if (hlr_unknown) {
-		/* FIXME: Delete subscriber record */
-		/* LU REJ: Roaming not allowed */
-		lu_fsm_failure(fi, GSM48_REJECT_ROAMING_NOT_ALLOWED);
-	} else {
-		/* Update_HLR_VLR */
-		osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_HLR_UPD,
-					LU_TIMEOUT_LONG, 0);
-		lfp->upd_hlr_vlr_fsm =
-			upd_hlr_vlr_proc_start(fi, vsub, VLR_ULA_E_UPD_HLR_COMPL);
-	}
-}
-
-/* 4.1.2.1 Node B */
-static void vlr_loc_upd_node_b(struct osmo_fsm_inst *fi)
-{
-	LOGPFSM(fi, "%s()\n", __func__);
-
-	/* OsmoHLR does not support PgA, neither stores the IMEISV, so we have no need to update the HLR
-	 * with either. TODO: depend on actual HLR configuration. See 3GPP TS 23.012 Release 14, process
-	 * Update_Location_Area_VLR (ULA_VLR2). */
-	if (0) { /* IMEISV or PgA to send */
-		vlr_loc_upd_node_4(fi);
-	} else {
-		/* Location_Update_Completion */
-		osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_LU_COMPL,
-					LU_TIMEOUT_LONG, 0);
-		vlr_loc_upd_start_lu_compl_fsm(fi);
-	}
-}
-
-/* Non-standard: after Ciphering Mode Complete (or no ciph required) */
-static void vlr_loc_upd_post_ciph(struct osmo_fsm_inst *fi)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	struct vlr_subscr *vsub = lfp->vsub;
-
-	LOGPFSM(fi, "%s()\n", __func__);
-
-	OSMO_ASSERT(vsub);
-
-	if (lfp->is_utran) {
-		int rc;
-		rc = lfp->vlr->ops.tx_common_id(lfp->msc_conn_ref);
-		if (rc)
-			LOGPFSML(fi, LOGL_ERROR,
-				 "Error while sending Common ID (%d)\n", rc);
-	}
-
-	vsub->conf_by_radio_contact_ind = true;
-	/* Update LAI */
-	vsub->cgi.lai = lfp->new_lai;
-	vsub->dormant_ind = false;
-	vsub->cancel_loc_rx = false;
-	if (hlr_update_needed(vsub)) {
-		vlr_loc_upd_node_4(fi);
-	} else {
-		/* TODO: ADD Support */
-		/* TODO: Node A: PgA Support */
-		vlr_loc_upd_node_b(fi);
-	}
-}
-
-/* 4.1.2.1 after Authentication successful (or no auth rqd) */
-static void vlr_loc_upd_post_auth(struct osmo_fsm_inst *fi)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	struct vlr_subscr *vsub = lfp->vsub;
-
-	LOGPFSM(fi, "%s()\n", __func__);
-
-	OSMO_ASSERT(vsub);
-
-	if (!is_ciph_required(lfp)) {
-		vlr_loc_upd_post_ciph(fi);
-		return;
-	}
-
-	if (vlr_set_ciph_mode(vsub->vlr, fi, lfp->msc_conn_ref,
-			      lfp->ciphering_required,
-			      vsub->vlr->cfg.retrieve_imeisv_ciphered)) {
-		LOGPFSML(fi, LOGL_ERROR,
-			 "Failed to send Ciphering Mode Command\n");
-		vlr_lu_compl_fsm_failure(fi, GSM48_REJECT_NETWORK_FAILURE);
-		return;
-	}
-
-	osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_CIPH, LU_TIMEOUT_LONG, 0);
-}
-
-static void vlr_loc_upd_node1(struct osmo_fsm_inst *fi)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	struct vlr_subscr *vsub = lfp->vsub;
-
-	LOGPFSM(fi, "%s()\n", __func__);
-
-	OSMO_ASSERT(vsub);
-
-	if (is_auth_required(lfp)) {
-		/* Authenticate_VLR */
-		osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_AUTH,
-					LU_TIMEOUT_LONG, 0);
-		vsub->auth_fsm = auth_fsm_start(lfp->vsub, fi->log_level,
-						fi, VLR_ULA_E_AUTH_RES,
-						lfp->is_r99,
-						lfp->is_utran);
-	} else {
-		/* no need for authentication */
-		vlr_loc_upd_post_auth(fi);
-	}
-}
-
-static void vlr_loc_upd_want_imsi(struct osmo_fsm_inst *fi)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	struct vlr_instance *vlr = lfp->vlr;
-
-	LOGPFSM(fi, "%s()\n", __func__);
-
-	OSMO_ASSERT(lfp->vsub);
-
-	/* Obtain_IMSI_VLR */
-	osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_IMSI,
-				vlr_timer(vlr, 3270), 3270);
-	vlr->ops.tx_id_req(lfp->msc_conn_ref, GSM_MI_TYPE_IMSI);
-	/* will continue at vlr_loc_upd_node1() once IMSI arrives */
-}
-
-static int assoc_lfp_with_sub(struct osmo_fsm_inst *fi, struct vlr_subscr *vsub)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	struct vlr_instance *vlr = lfp->vlr;
-
-	if (vsub->lu_fsm) {
-		LOGPFSML(fi, LOGL_ERROR,
-			 "A Location Updating process is already pending for"
-			 " this subscriber. Aborting.\n");
-		/* Also get rid of the other pending LU attempt? */
-		/*lu_fsm_failure(vsub->lu_fsm, GSM48_REJECT_CONGESTION);*/
-		lu_fsm_failure(fi, GSM48_REJECT_CONGESTION);
-		return -EINVAL;
-	}
-	vsub->lu_fsm = fi;
-	vsub->msc_conn_ref = lfp->msc_conn_ref;
-	/* FIXME: send new LAC to HLR? */
-	vsub->lac = lfp->new_lai.lac;
-	lfp->vsub = vsub;
-	/* Tell MSC to associate this subscriber with the given
-	 * connection */
-	vlr->ops.subscr_assoc(lfp->msc_conn_ref, lfp->vsub);
-	return 0;
-}
-
-static const char *lai_name(struct osmo_location_area_id *lai)
-{
-	static char buf[64];
-	snprintf(buf, sizeof(buf),"MCC:%u, MNC:%u, LAC:%u",
-		 lai->plmn.mcc, lai->plmn.mnc, lai->lac);
-	return buf;
-}
-
-static int _lu_fsm_associate_vsub(struct osmo_fsm_inst *fi)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	struct vlr_instance *vlr = lfp->vlr;
-	struct vlr_subscr *vsub = NULL;
-
-	if (!lfp->imsi[0]) {
-		/* TMSI was used */
-		lfp->lu_by_tmsi = true;
-		/* TMSI clash: if a different subscriber already has this TMSI,
-		 * we will find that other subscriber in the VLR. So the IMSIs
-		 * would mismatch, but we don't know about it. Theoretically,
-		 * an authentication process would thwart any attempt to use
-		 * someone else's TMSI.
-		 * TODO: Otherwise we can ask for the IMSI and verify that it
-		 * matches the IMSI on record. */
-		vsub = vlr_subscr_find_or_create_by_tmsi(vlr, lfp->tmsi, NULL);
-
-		if (!vsub) {
-			LOGPFSML(fi, LOGL_ERROR, "VLR subscriber allocation failed\n");
-			lu_fsm_failure(fi, GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER);
-			return -1;
-		}
-
-		vsub->sub_dataconf_by_hlr_ind = false;
-		if (assoc_lfp_with_sub(fi, vsub)) {
-			vlr_subscr_put(vsub);
-			return -1; /* error, fsm failure invoked in assoc_lfp_with_sub() */
-		}
-		vlr_subscr_put(vsub);
-	} else {
-		/* IMSI was used */
-		vsub = vlr_subscr_find_or_create_by_imsi(vlr, lfp->imsi, NULL);
-
-		if (!vsub) {
-			LOGPFSML(fi, LOGL_ERROR, "VLR subscriber allocation failed\n");
-			lu_fsm_failure(fi, GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER);
-			vlr_subscr_put(vsub);
-			return -1;
-		}
-
-		vsub->sub_dataconf_by_hlr_ind = false;
-		if (assoc_lfp_with_sub(fi, vsub)) {
-			vlr_subscr_put(vsub);
-			return -1; /* error, fsm failure invoked in assoc_lfp_with_sub() */
-		}
-		vlr_subscr_put(vsub);
-	}
-	return 0;
-}
-
-/* 4.1.2.1: Subscriber (via MSC/SGSN) requests location update */
-static void _start_lu_main(struct osmo_fsm_inst *fi)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	struct vlr_instance *vlr = lfp->vlr;
-
-	/* TODO: PUESBINE related handling */
-
-	/* Is previous LAI in this VLR? */
-	if (!lai_in_this_vlr(vlr, &lfp->old_lai)) {
-#if 0
-		/* FIXME: check previous VLR, (3) */
-		osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_PVLR,
-					LU_TIMEOUT_LONG, 0);
-		return;
-#endif
-		LOGPFSML(fi, LOGL_NOTICE, "LAI change from %s,"
-			 " but checking previous VLR not implemented\n",
-			 lai_name(&lfp->old_lai));
-	}
-
-	/* If this is a TMSI based LU, we may not have the IMSI. Make sure that
-	 * we know the IMSI, either on record, or request it. */
-	if (!lfp->vsub->imsi[0])
-		vlr_loc_upd_want_imsi(fi);
-	else
-		vlr_loc_upd_node1(fi);
-}
-
-static void lu_fsm_idle(struct osmo_fsm_inst *fi, uint32_t event,
-			void *data)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	struct vlr_instance *vlr = lfp->vlr;
-
-	OSMO_ASSERT(event == VLR_ULA_E_UPDATE_LA);
-
-	if (_lu_fsm_associate_vsub(fi))
-		return; /* error. FSM already terminated. */
-
-	OSMO_ASSERT(lfp->vsub);
-
-	/* See 3GPP TS 23.012, procedure Retrieve_IMEISV_If_Required */
-	if ((!vlr->cfg.retrieve_imeisv_early)
-	    || (lfp->type == VLR_LU_TYPE_PERIODIC && lfp->vsub->imeisv[0])) {
-		/* R_IMEISV_IR1 passed */
-		_start_lu_main(fi);
-	} else {
-		vlr->ops.tx_id_req(lfp->msc_conn_ref, GSM_MI_TYPE_IMEISV);
-		osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_IMEISV,
-					vlr_timer(vlr, 3270), 3270);
-	}
-}
-
-static void lu_fsm_wait_imeisv(struct osmo_fsm_inst *fi, uint32_t event,
-			       void *data)
-{
-	switch (event) {
-	case VLR_ULA_E_ID_IMEISV:
-		/* IMEISV was copied in vlr_subscr_rx_id_resp(), and that's
-		 * where we received this event from. */
-		_start_lu_main(fi);
-		break;
-	default:
-		LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
-			 osmo_fsm_event_name(fi->fsm, event));
-		break;
-	}
-}
-
-/* Wait for response from Send_Identification to PVLR */
-static void lu_fsm_wait_pvlr(struct osmo_fsm_inst *fi, uint32_t event,
-			     void *data)
-{
-	switch (event) {
-	case VLR_ULA_E_SEND_ID_ACK:
-		vlr_loc_upd_node1(fi);
-		break;
-	case VLR_ULA_E_SEND_ID_NACK:
-		vlr_loc_upd_want_imsi(fi);
-		break;
-	default:
-		LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
-			 osmo_fsm_event_name(fi->fsm, event));
-		break;
-	}
-}
-
-/* Wait for result of Authenticate_VLR procedure */
-static void lu_fsm_wait_auth(struct osmo_fsm_inst *fi, uint32_t event,
-			     void *data)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	enum vlr_auth_fsm_result *res = data;
-	uint8_t rej_cause = 0;
-
-	OSMO_ASSERT(event == VLR_ULA_E_AUTH_RES);
-
-	lfp->upd_hlr_vlr_fsm = NULL;
-
-	if (res) {
-		switch (*res) {
-		case VLR_AUTH_RES_PASSED:
-			/* Result == Pass */
-			vlr_loc_upd_post_auth(fi);
-			return;
-		case VLR_AUTH_RES_ABORTED:
-			/* go to Idle with no response */
-			rej_cause = 0;
-			break;
-		case VLR_AUTH_RES_UNKNOWN_SUBSCR:
-			/* FIXME: delete subscribe record */
-			rej_cause = GSM48_REJECT_IMSI_UNKNOWN_IN_HLR;
-			break;
-		case VLR_AUTH_RES_AUTH_FAILED:
-			/* cause = illegal subscriber */
-			rej_cause = GSM48_REJECT_ILLEGAL_MS;
-			break;
-		case VLR_AUTH_RES_PROC_ERR:
-			/* cause = system failure */
-			rej_cause = GSM48_REJECT_NETWORK_FAILURE;
-			break;
-		default:
-			LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
-				 osmo_fsm_event_name(fi->fsm, event));
-			break;
-		}
-	} else
-		rej_cause = GSM48_REJECT_NETWORK_FAILURE;
-
-	lu_fsm_failure(fi, rej_cause);
-}
-
-static void lu_fsm_wait_ciph(struct osmo_fsm_inst *fi, uint32_t event,
-			     void *data)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	struct vlr_subscr *vsub = lfp->vsub;
-	struct vlr_ciph_result res = { .cause = VLR_CIPH_REJECT };
-
-	OSMO_ASSERT(event == VLR_ULA_E_CIPH_RES);
-
-	if (!data)
-		LOGPFSML(fi, LOGL_ERROR, "invalid ciphering result: NULL\n");
-	else
-		res = *(struct vlr_ciph_result*)data;
-
-	switch (res.cause) {
-	case VLR_CIPH_COMPL:
-		break;
-	case VLR_CIPH_REJECT:
-		LOGPFSM(fi, "ciphering rejected\n");
-		lu_fsm_failure(fi, GSM48_REJECT_INVALID_MANDANTORY_INF);
-		return;
-	default:
-		LOGPFSML(fi, LOGL_ERROR, "invalid ciphering result: %d\n",
-			 res.cause);
-		lu_fsm_failure(fi, GSM48_REJECT_INVALID_MANDANTORY_INF);
-		return;
-	}
-
-	if (res.imeisv) {
-		LOGPFSM(fi, "got IMEISV: %s\n", res.imeisv);
-		vlr_subscr_set_imeisv(vsub, res.imeisv);
-	}
-	vlr_loc_upd_post_ciph(fi);
-}
-
-static void lu_fsm_wait_imsi(struct osmo_fsm_inst *fi, uint32_t event,
-			     void *data)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	struct vlr_subscr *vsub = lfp->vsub;
-	char *mi_string = data;
-
-	switch (event) {
-	case VLR_ULA_E_ID_IMSI:
-		vlr_subscr_set_imsi(vsub, mi_string);
-		vlr_loc_upd_node1(fi);
-		break;
-	default:
-		LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
-			 osmo_fsm_event_name(fi->fsm, event));
-		break;
-	}
-}
-
-/* At the end of Update_HLR_VLR */
-static void lu_fsm_wait_hlr_ul_res(struct osmo_fsm_inst *fi, uint32_t event,
-				   void *data)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-
-	switch (event) {
-	case VLR_ULA_E_HLR_LU_RES:
-		/* pass-through this event to Update_HLR_VLR */
-		if (data == NULL)
-			osmo_fsm_inst_dispatch(lfp->upd_hlr_vlr_fsm, UPD_HLR_VLR_E_UPD_LOC_ACK, NULL);
-		else
-			osmo_fsm_inst_dispatch(lfp->upd_hlr_vlr_fsm, UPD_HLR_VLR_E_UPD_LOC_NACK, data);
-		break;
-	case VLR_ULA_E_UPD_HLR_COMPL:
-		if (data == NULL) {
-			/* successful case */
-			osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_LU_COMPL,
-						LU_TIMEOUT_LONG, 0);
-			vlr_loc_upd_start_lu_compl_fsm(fi);
-			/* continue in MSC ?!? */
-		} else {
-			/* unsuccessful case */
-			enum gsm48_gmm_cause cause =
-				*(enum gsm48_gmm_cause *)data;
-			/* Ignoring standalone mode for now. */
-			if (0 /* procedure_error && vlr->cfg.standalone_mode */) {
-				osmo_fsm_inst_state_chg(fi,
-						VLR_ULA_S_WAIT_LU_COMPL_STANDALONE,
-						LU_TIMEOUT_LONG, 0);
-				vlr_loc_upd_start_lu_compl_fsm(fi);
-			} else {
-				lu_fsm_failure(fi, cause);
-			}
-		}
-		break;
-	default:
-		LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
-			 osmo_fsm_event_name(fi->fsm, event));
-		break;
-	}
-}
-
-/* Wait for end of Location_Update_Completion_VLR */
-static void lu_fsm_wait_lu_compl(struct osmo_fsm_inst *fi, uint32_t event,
-				 void *data)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	uint8_t cause;
-
-	switch (event) {
-	case VLR_ULA_E_NEW_TMSI_ACK:
-		osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm,
-				       LU_COMPL_VLR_E_NEW_TMSI_ACK, NULL);
-		break;
-	case VLR_ULA_E_ID_IMEI:
-		osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm,
-				       LU_COMPL_VLR_E_IMEI_CHECK_ACK, NULL);
-		break;
-	case VLR_ULA_E_LU_COMPL_SUCCESS:
-		lu_fsm_discard_lu_compl_fsm(fi);
-
-		/* Update Register */
-		/* TODO: Set_Notification_Type 23.078 */
-		/* TODO: Notify_gsmSCF 23.078 */
-		/* TODO: Authenticated Radio Contact Established -> ARC */
-		lu_fsm_success(fi);
-		break;
-	case VLR_ULA_E_LU_COMPL_FAILURE:
-		cause = GSM48_REJECT_NETWORK_FAILURE;
-		if (data)
-			cause = *(uint8_t*)data;
-		lu_fsm_discard_lu_compl_fsm(fi);
-		lu_fsm_failure(fi, cause);
-		break;
-	default:
-		LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
-			 osmo_fsm_event_name(fi->fsm, event));
-		break;
-	}
-}
-
-/* Wait for end of Location_Update_Completion_VLR (standalone case) */
-static void lu_fsm_wait_lu_compl_standalone(struct osmo_fsm_inst *fi,
-					uint32_t event, void *data)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	struct vlr_subscr *vsub = lfp->vsub;
-	uint8_t cause;
-
-	switch (event) {
-	case VLR_ULA_E_NEW_TMSI_ACK:
-		osmo_fsm_inst_dispatch(lfp->lu_compl_vlr_fsm,
-				       LU_COMPL_VLR_E_NEW_TMSI_ACK, NULL);
-		break;
-	case VLR_ULA_E_LU_COMPL_SUCCESS:
-		lu_fsm_discard_lu_compl_fsm(fi);
-		vsub->sub_dataconf_by_hlr_ind = false;
-		lu_fsm_success(fi);
-		break;
-	case VLR_ULA_E_LU_COMPL_FAILURE:
-		vsub->sub_dataconf_by_hlr_ind = false;
-		cause = GSM48_REJECT_NETWORK_FAILURE;
-		if (data)
-			cause = *(uint8_t*)data;
-		lu_fsm_discard_lu_compl_fsm(fi);
-		lu_fsm_failure(fi, cause);
-		break;
-	default:
-		LOGPFSML(fi, LOGL_ERROR, "event without effect: %s\n",
-			 osmo_fsm_event_name(fi->fsm, event));
-		break;
-	}
-}
-
-static const struct osmo_fsm_state vlr_lu_fsm_states[] = {
-	[VLR_ULA_S_IDLE] = {
-		.in_event_mask = S(VLR_ULA_E_UPDATE_LA),
-		.out_state_mask = S(VLR_ULA_S_WAIT_IMEISV) |
-				  S(VLR_ULA_S_WAIT_PVLR) |
-				  S(VLR_ULA_S_WAIT_IMSI) |
-				  S(VLR_ULA_S_WAIT_AUTH) |
-				  S(VLR_ULA_S_WAIT_HLR_UPD) |
-				  S(VLR_ULA_S_DONE),
-		.name = OSMO_STRINGIFY(VLR_ULA_S_IDLE),
-		.action = lu_fsm_idle,
-	},
-	[VLR_ULA_S_WAIT_IMEISV] = {
-		.in_event_mask = S(VLR_ULA_E_ID_IMEISV),
-		.out_state_mask = S(VLR_ULA_S_WAIT_PVLR) |
-				  S(VLR_ULA_S_WAIT_IMSI) |
-				  S(VLR_ULA_S_WAIT_AUTH) |
-				  S(VLR_ULA_S_WAIT_HLR_UPD) |
-				  S(VLR_ULA_S_DONE),
-		.name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_IMEISV),
-		.action = lu_fsm_wait_imeisv,
-	},
-	[VLR_ULA_S_WAIT_PVLR] = {
-		.in_event_mask = S(VLR_ULA_E_SEND_ID_ACK) |
-				 S(VLR_ULA_E_SEND_ID_NACK),
-		.out_state_mask = S(VLR_ULA_S_WAIT_IMSI) |
-				  S(VLR_ULA_S_WAIT_AUTH) |
-				  S(VLR_ULA_S_DONE),
-		.name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_PVLR),
-		.action = lu_fsm_wait_pvlr,
-	},
-	[VLR_ULA_S_WAIT_AUTH] = {
-		.in_event_mask = S(VLR_ULA_E_AUTH_RES),
-		.out_state_mask = S(VLR_ULA_S_WAIT_CIPH) |
-				  S(VLR_ULA_S_WAIT_LU_COMPL) |
-				  S(VLR_ULA_S_WAIT_HLR_UPD) |
-				  S(VLR_ULA_S_DONE),
-		.name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_AUTH),
-		.action = lu_fsm_wait_auth,
-	},
-	[VLR_ULA_S_WAIT_CIPH] = {
-		.name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_CIPH),
-		.in_event_mask = S(VLR_ULA_E_CIPH_RES),
-		.out_state_mask = S(VLR_ULA_S_WAIT_LU_COMPL) |
-				  S(VLR_ULA_S_WAIT_HLR_UPD) |
-				  S(VLR_ULA_S_DONE),
-		.action = lu_fsm_wait_ciph,
-	},
-	[VLR_ULA_S_WAIT_IMSI] = {
-		.in_event_mask = S(VLR_ULA_E_ID_IMSI),
-		.out_state_mask = S(VLR_ULA_S_WAIT_AUTH) |
-				  S(VLR_ULA_S_WAIT_HLR_UPD) |
-				  S(VLR_ULA_S_DONE),
-		.name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_IMSI),
-		.action = lu_fsm_wait_imsi,
-	},
-	[VLR_ULA_S_WAIT_HLR_UPD] = {
-		.in_event_mask = S(VLR_ULA_E_HLR_LU_RES) |
-				 S(VLR_ULA_E_UPD_HLR_COMPL),
-		.out_state_mask = S(VLR_ULA_S_WAIT_LU_COMPL) |
-				  S(VLR_ULA_S_WAIT_LU_COMPL_STANDALONE) |
-				  S(VLR_ULA_S_DONE),
-		.name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_HLR_UPD),
-		.action = lu_fsm_wait_hlr_ul_res,
-	},
-	[VLR_ULA_S_WAIT_LU_COMPL] = {
-		.in_event_mask = S(VLR_ULA_E_LU_COMPL_SUCCESS) |
-				 S(VLR_ULA_E_LU_COMPL_FAILURE) |
-				 S(VLR_ULA_E_NEW_TMSI_ACK) |
-				 S(VLR_ULA_E_ID_IMEI) |
-				 S(VLR_ULA_E_ID_IMEISV),
-		.out_state_mask = S(VLR_ULA_S_DONE),
-		.name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_LU_COMPL),
-		.action = lu_fsm_wait_lu_compl,
-	},
-	[VLR_ULA_S_WAIT_LU_COMPL_STANDALONE] = {
-		.in_event_mask = S(VLR_ULA_E_LU_COMPL_SUCCESS) |
-				 S(VLR_ULA_E_LU_COMPL_FAILURE) |
-				 S(VLR_ULA_E_NEW_TMSI_ACK),
-		.out_state_mask = S(VLR_ULA_S_DONE),
-		.name = OSMO_STRINGIFY(VLR_ULA_S_WAIT_LU_COMPL_STANDALONE),
-		.action = lu_fsm_wait_lu_compl_standalone,
-	},
-	[VLR_ULA_S_DONE] = {
-		.name = OSMO_STRINGIFY(VLR_ULA_S_DONE),
-		.onenter = lu_fsm_dispatch_result,
-	},
-};
-
-static void fsm_lu_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
-{
-	struct lu_fsm_priv *lfp = fi->priv;
-	struct vlr_subscr *vsub = lfp->vsub;
-
-	LOGPFSM(fi, "fsm_lu_cleanup called with cause %s\n",
-		osmo_fsm_term_cause_name(cause));
-	if (vsub && vsub->lu_fsm == fi)
-		vsub->lu_fsm = NULL;
-}
-
-static struct osmo_fsm vlr_lu_fsm = {
-	.name = "vlr_lu_fsm",
-	.states = vlr_lu_fsm_states,
-	.num_states = ARRAY_SIZE(vlr_lu_fsm_states),
-	.allstate_event_mask = 0,
-	.allstate_action = NULL,
-	.log_subsys = DVLR,
-	.event_names = fsm_lu_event_names,
-	.cleanup = fsm_lu_cleanup,
-};
-
-struct osmo_fsm_inst *
-vlr_loc_update(struct osmo_fsm_inst *parent,
-	       uint32_t parent_event_success,
-	       uint32_t parent_event_failure,
-	       void *parent_event_data,
-	       struct vlr_instance *vlr, void *msc_conn_ref,
-	       enum vlr_lu_type type, uint32_t tmsi, const char *imsi,
-	       const struct osmo_location_area_id *old_lai,
-	       const struct osmo_location_area_id *new_lai,
-	       bool authentication_required,
-	       enum vlr_ciph ciphering_required,
-	       bool is_r99, bool is_utran,
-	       bool assign_tmsi)
-{
-	struct osmo_fsm_inst *fi;
-	struct lu_fsm_priv *lfp;
-
-	fi = osmo_fsm_inst_alloc_child(&vlr_lu_fsm, parent, parent_event_failure);
-	if (!fi)
-		return NULL;
-
-	lfp = talloc_zero(fi, struct lu_fsm_priv);
-	lfp->vlr = vlr;
-	lfp->msc_conn_ref = msc_conn_ref;
-	lfp->tmsi = tmsi;
-	lfp->type = type;
-	lfp->old_lai = *old_lai;
-	lfp->new_lai = *new_lai;
-	lfp->lu_by_tmsi = true;
-	lfp->parent_event_success = parent_event_success;
-	lfp->parent_event_failure = parent_event_failure;
-	lfp->parent_event_data = parent_event_data;
-	lfp->authentication_required = authentication_required;
-	lfp->ciphering_required = ciphering_required;
-	lfp->is_r99 = is_r99;
-	lfp->is_utran = is_utran;
-	lfp->assign_tmsi = assign_tmsi;
-	if (imsi) {
-		strncpy(lfp->imsi, imsi, sizeof(lfp->imsi)-1);
-		lfp->imsi[sizeof(lfp->imsi)-1] = '\0';
-		lfp->lu_by_tmsi = false;
-	}
-	fi->priv = lfp;
-
-	LOGPFSM(fi, "rev=%s net=%s%s%s\n",
-		is_r99 ? "R99" : "GSM",
-		is_utran ? "UTRAN" : "GERAN",
-		(authentication_required || ciphering_required)?
-		" Auth" : " (no Auth)",
-		(authentication_required || ciphering_required)?
-			(ciphering_required? "+Ciph" : " (no Ciph)")
-			: "");
-
-	if (is_utran && !authentication_required)
-		LOGPFSML(fi, LOGL_ERROR,
-			 "Authentication off on UTRAN network. Good luck.\n");
-
-	osmo_fsm_inst_dispatch(fi, VLR_ULA_E_UPDATE_LA, NULL);
-
-	return fi;
-}
-
-/* Gracefully terminate an FSM created by vlr_loc_update() in case of external
- * timeout (i.e. from MSC). */
-void vlr_loc_update_conn_timeout(struct osmo_fsm_inst *fi)
-{
-	if (!fi || fi->state == VLR_ULA_S_DONE)
-		return;
-	LOGPFSM(fi, "Connection timed out\n");
-	lu_fsm_failure(fi, GSM48_REJECT_CONGESTION);
-}
-
-void vlr_lu_fsm_init(void)
-{
-	osmo_fsm_register(&vlr_lu_fsm);
-	osmo_fsm_register(&upd_hlr_vlr_fsm);
-	osmo_fsm_register(&sub_pres_vlr_fsm);
-	osmo_fsm_register(&lu_compl_vlr_fsm);
-}
diff --git a/src/libvlr/vlr_lu_fsm.h b/src/libvlr/vlr_lu_fsm.h
deleted file mode 100644
index 5cf13c7..0000000
--- a/src/libvlr/vlr_lu_fsm.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma once
-
-#include <osmocom/core/fsm.h>
-
-enum vlr_lu_state {
-	VLR_ULA_S_IDLE,
-	VLR_ULA_S_WAIT_IMEISV,
-	VLR_ULA_S_WAIT_PVLR,	/* Waiting for ID from PVLR */
-	VLR_ULA_S_WAIT_AUTH,	/* Waiting for Authentication */
-	VLR_ULA_S_WAIT_CIPH,	/* Waiting for Ciphering Complete */
-	VLR_ULA_S_WAIT_IMSI,	/* Waiting for IMSI from MS */
-	VLR_ULA_S_WAIT_HLR_UPD,	/* Waiting for end of HLR update */
-	VLR_ULA_S_WAIT_LU_COMPL,/* Waiting for LU complete */
-	VLR_ULA_S_WAIT_LU_COMPL_STANDALONE, /* Standalone VLR */
-	VLR_ULA_S_DONE
-};
-
-void vlr_lu_fsm_init(void);
diff --git a/src/osmo-bsc/Makefile.am b/src/osmo-bsc/Makefile.am
deleted file mode 100644
index 5642fb2..0000000
--- a/src/osmo-bsc/Makefile.am
+++ /dev/null
@@ -1,57 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	-I$(top_builddir) \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOVTY_CFLAGS) \
-	$(LIBOSMOCTRL_CFLAGS) \
-	$(LIBOSMONETIF_CFLAGS) \
-	$(LIBOSMOSCCP_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(LIBOSMOSIGTRAN_CFLAGS) \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(COVERAGE_LDFLAGS) \
-	$(NULL)
-
-bin_PROGRAMS = \
-	osmo-bsc \
-	$(NULL)
-
-osmo_bsc_SOURCES = \
-	osmo_bsc_main.c \
-	osmo_bsc_vty.c \
-	osmo_bsc_api.c \
-	osmo_bsc_grace.c \
-	osmo_bsc_msc.c \
-	osmo_bsc_sigtran.c \
-	osmo_bsc_filter.c \
-	osmo_bsc_bssap.c \
-	osmo_bsc_audio.c \
-	osmo_bsc_ctrl.c \
-	$(NULL)
-
-# once again since TRAU uses CC symbol :(
-osmo_bsc_LDADD = \
-	$(top_builddir)/src/libfilter/libfilter.a \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
-	$(top_builddir)/src/libmsc/libmsc.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOSCCP_LIBS) \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOVTY_LIBS) \
-	$(LIBOSMOCTRL_LIBS) \
-	$(COVERAGE_LDFLAGS) \
-	$(LIBOSMOABIS_LIBS) \
-	$(LIBOSMOSIGTRAN_LIBS) \
-	$(NULL)
diff --git a/src/osmo-bsc/osmo_bsc_api.c b/src/osmo-bsc/osmo_bsc_api.c
deleted file mode 100644
index f7343f7..0000000
--- a/src/osmo-bsc/osmo_bsc_api.c
+++ /dev/null
@@ -1,569 +0,0 @@
-/* (C) 2009-2015 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2011 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/>.
- *
- */
-
-#include <openbsc/osmo_bsc.h>
-#include <openbsc/bsc_msc_data.h>
-#include <openbsc/debug.h>
-
-#include <openbsc/gsm_04_80.h>
-
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-#include <osmocom/gsm/gsm0808.h>
-
-#include <osmocom/sccp/sccp.h>
-#include <openbsc/osmo_bsc_sigtran.h>
-
-#define return_when_not_connected(conn) \
-	if (!conn->sccp_con) {\
-		LOGP(DMSC, LOGL_ERROR, "MSC Connection not present.\n"); \
-		return; \
-	}
-
-#define return_when_not_connected_val(conn, ret) \
-	if (!conn->sccp_con) {\
-		LOGP(DMSC, LOGL_ERROR, "MSC Connection not present.\n"); \
-		return ret; \
-	}
-
-#define queue_msg_or_return(resp) \
-	if (!resp) { \
-		LOGP(DMSC, LOGL_ERROR, "Failed to allocate response.\n"); \
-		return; \
-	} \
-	osmo_bsc_sigtran_send(conn->sccp_con, resp);
-
-static int bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause);
-static int complete_layer3(struct gsm_subscriber_connection *conn,
-			   struct msgb *msg, struct bsc_msc_data *msc);
-
-static uint16_t get_network_code_for_msc(struct bsc_msc_data *msc)
-{
-	if (msc->core_mnc != -1)
-		return msc->core_mnc;
-	return msc->network->network_code;
-}
-
-static uint16_t get_country_code_for_msc(struct bsc_msc_data *msc)
-{
-	if (msc->core_mcc != -1)
-		return msc->core_mcc;
-	return msc->network->country_code;
-}
-
-static uint16_t get_lac_for_msc(struct bsc_msc_data *msc, struct gsm_bts *bts)
-{
-	if (msc->core_lac != -1)
-		return msc->core_lac;
-	return bts->location_area_code;
-}
-
-static uint16_t get_ci_for_msc(struct bsc_msc_data *msc, struct gsm_bts *bts)
-{
-	if (msc->core_ci != -1)
-		return msc->core_ci;
-	return bts->cell_identity;
-}
-
-static void bsc_maybe_lu_reject(struct gsm_subscriber_connection *conn, int con_type, int cause)
-{
-	struct msgb *msg;
-
-	/* ignore cm service request or such */
-	if (con_type != FLT_CON_TYPE_LU)
-		return;
-
-	msg = gsm48_create_loc_upd_rej(cause);
-	if (!msg) {
-		LOGP(DMM, LOGL_ERROR, "Failed to create msg for LOCATION UPDATING REJECT.\n");
-		return;
-	}
-
-	msg->lchan = conn->lchan;
-	gsm0808_submit_dtap(conn, msg, 0, 0);
-}
-
-static int bsc_filter_initial(struct osmo_bsc_data *bsc,
-				struct bsc_msc_data *msc,
-				struct gsm_subscriber_connection *conn,
-				struct msgb *msg, char **imsi, int *con_type,
-				int *lu_cause)
-{
-	struct bsc_filter_request req;
-	struct bsc_filter_reject_cause cause;
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	int rc;
-
-	req.ctx = conn;
-	req.black_list = NULL;
-	req.access_lists = bsc_access_lists();
-	req.local_lst_name = msc->acc_lst_name;
-	req.global_lst_name = conn->bts->network->bsc_data->acc_lst_name;
-	req.bsc_nr = 0;
-
-	rc = bsc_msg_filter_initial(gh, msgb_l3len(msg), &req,
-				con_type, imsi, &cause);
-	*lu_cause = cause.lu_reject_cause;
-	return rc;
-}
-
-static int bsc_filter_data(struct gsm_subscriber_connection *conn,
-				struct msgb *msg, int *lu_cause)
-{
-	struct bsc_filter_request req;
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	struct bsc_filter_reject_cause cause;
-	int rc;
-
-	req.ctx = conn;
-	req.black_list = NULL;
-	req.access_lists = bsc_access_lists();
-	req.local_lst_name = conn->sccp_con->msc->acc_lst_name;
-	req.global_lst_name = conn->bts->network->bsc_data->acc_lst_name;
-	req.bsc_nr = 0;
-
-	rc = bsc_msg_filter_data(gh, msgb_l3len(msg), &req,
-				&conn->sccp_con->filter_state,
-				&cause);
-	*lu_cause = cause.lu_reject_cause;
-	return rc;
-}
-
-static void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci)
-{
-	struct msgb *resp;
-	return_when_not_connected(conn);
-
-	LOGP(DMSC, LOGL_NOTICE, "Tx MSC SAPI N REJECT DLCI=0x%02x\n", dlci);
-
-	resp = gsm0808_create_sapi_reject(dlci);
-	queue_msg_or_return(resp);
-}
-
-static void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn,
-				  struct msgb *msg, uint8_t chosen_encr)
-{
-	struct msgb *resp;
-	return_when_not_connected(conn);
-
-	LOGP(DMSC, LOGL_DEBUG, "CIPHER MODE COMPLETE from MS, forwarding to MSC\n");
-	resp = gsm0808_create_cipher_complete(msg, chosen_encr);
-	queue_msg_or_return(resp);
-}
-
-static void bsc_send_ussd_no_srv(struct gsm_subscriber_connection *conn,
-				 struct msgb *msg, const char *text)
-{
-	struct gsm48_hdr *gh;
-	int8_t pdisc;
-	uint8_t mtype;
-	int drop_message = 1;
-
-	if (!text)
-		return;
-
-	if (!msg || msgb_l3len(msg) < sizeof(*gh))
-		return;
-
-	gh = msgb_l3(msg);
-	pdisc = gsm48_hdr_pdisc(gh);
-	mtype = gsm48_hdr_msg_type(gh);
-
-	/* Is CM service request? */
-	if (pdisc == GSM48_PDISC_MM && mtype == GSM48_MT_MM_CM_SERV_REQ) {
-		struct gsm48_service_request *cm;
-
-		cm = (struct gsm48_service_request *) &gh->data[0];
-
-		/* Is type SMS or call? */
-		if (cm->cm_service_type == GSM48_CMSERV_SMS)
-			drop_message = 0;
-		else if (cm->cm_service_type == GSM48_CMSERV_MO_CALL_PACKET)
-			drop_message = 0;
-	}
-
-	if (drop_message) {
-		LOGP(DMSC, LOGL_DEBUG, "Skipping (not sending) USSD message: '%s'\n", text);
-		return;
-	}
-
-	LOGP(DMSC, LOGL_INFO, "Sending CM Service Accept\n");
-	gsm48_tx_mm_serv_ack(conn);
-
-	LOGP(DMSC, LOGL_INFO, "Sending USSD message: '%s'\n", text);
-	bsc_send_ussd_notify(conn, 1, text);
-	bsc_send_ussd_release_complete(conn);
-}
-
-/*
- * Instruct to reserve data for a new connectiom, create the complete
- * layer three message, send it to open the connection.
- */
-static int bsc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg,
-			uint16_t chosen_channel)
-{
-	struct bsc_msc_data *msc;
-
-	LOGP(DMSC, LOGL_INFO, "Tx MSC COMPL L3\n");
-
-	/* find the MSC link we want to use */
-	msc = bsc_find_msc(conn, msg);
-	if (!msc) {
-		LOGP(DMSC, LOGL_ERROR, "Failed to find a MSC for a connection.\n");
-		bsc_send_ussd_no_srv(conn, msg,
-				     conn->bts->network->bsc_data->ussd_no_msc_txt);
-		return -1;
-	}
-
-	return complete_layer3(conn, msg, msc);
-}
-
-static int complete_layer3(struct gsm_subscriber_connection *conn,
-			   struct msgb *msg, struct bsc_msc_data *msc)
-{
-	int con_type, rc, lu_cause;
-	char *imsi = NULL;
-	struct timeval tv;
-	struct msgb *resp;
-	uint16_t network_code;
-	uint16_t country_code;
-	uint16_t lac;
-	uint16_t ci;
-	enum bsc_con ret;
-	int send_ping = msc->advanced_ping;
-
-	/* Advanced ping/pong handling */
-	if (osmo_timer_pending(&msc->pong_timer))
-		send_ping = 0;
-	if (msc->ping_timeout <= 0)
-		send_ping = 0;
-	if (send_ping && osmo_timer_remaining(&msc->ping_timer, NULL, &tv) == -1)
-		send_ping = 0;
-
-	/* Check the filter */
-	rc = bsc_filter_initial(msc->network->bsc_data, msc, conn, msg,
-				&imsi, &con_type, &lu_cause);
-	if (rc < 0) {
-		bsc_maybe_lu_reject(conn, con_type, lu_cause);
-		return BSC_API_CONN_POL_REJECT;
-	}
-
-	/* allocate resource for a new connection */
-	//ret = bsc_create_new_connection(conn, msc, send_ping);
-	ret = osmo_bsc_sigtran_new_conn(conn, msc);
-
-	if (ret != BSC_CON_SUCCESS) {
-		/* allocation has failed */
-		if (ret == BSC_CON_REJECT_NO_LINK)
-			bsc_send_ussd_no_srv(conn, msg, msc->ussd_msc_lost_txt);
-		else if (ret == BSC_CON_REJECT_RF_GRACE)
-			bsc_send_ussd_no_srv(conn, msg, msc->ussd_grace_txt);
-
-		return BSC_API_CONN_POL_REJECT;
-	}
-
-	if (imsi)
-		conn->sccp_con->filter_state.imsi = talloc_steal(conn, imsi);
-	conn->sccp_con->filter_state.con_type = con_type;
-
-	/* check return value, if failed check msg for and send USSD */
-
-	network_code = get_network_code_for_msc(conn->sccp_con->msc);
-	country_code = get_country_code_for_msc(conn->sccp_con->msc);
-	lac = get_lac_for_msc(conn->sccp_con->msc, conn->bts);
-	ci = get_ci_for_msc(conn->sccp_con->msc, conn->bts);
-
-	bsc_scan_bts_msg(conn, msg);
-
-	resp = gsm0808_create_layer3(msg, network_code, country_code, lac, ci);
-	if (!resp) {
-		LOGP(DMSC, LOGL_DEBUG, "Failed to create layer3 message.\n");
-		sccp_connection_free(conn->sccp_con->sccp);
-		osmo_bsc_sigtran_del_conn(conn->sccp_con);
-		return BSC_API_CONN_POL_REJECT;
-	}
-
-	if (osmo_bsc_sigtran_open_conn(conn->sccp_con, resp) != 0) {
-		sccp_connection_free(conn->sccp_con->sccp);
-		osmo_bsc_sigtran_del_conn(conn->sccp_con);
-		msgb_free(resp);
-		return BSC_API_CONN_POL_REJECT;
-	}
-
-	return BSC_API_CONN_POL_ACCEPT;
-}
-
-/*
- * Plastic surgery... we want to give up the current connection
- */
-static int move_to_msc(struct gsm_subscriber_connection *_conn,
-		       struct msgb *msg, struct bsc_msc_data *msc)
-{
-	struct osmo_bsc_sccp_con *old_con = _conn->sccp_con;
-
-	/*
-	 * 1. Give up the old connection.
-	 * This happens by sending a clear request to the MSC,
-	 * it should end with the MSC releasing the connection.
-	 */
-	old_con->conn = NULL;
-	bsc_clear_request(_conn, 0);
-
-	/*
-	 * 2. Attempt to create a new connection to the local
-	 * MSC. If it fails the caller will need to handle this
-	 * properly.
-	 */
-	_conn->sccp_con = NULL;
-	if (complete_layer3(_conn, msg, msc) != BSC_API_CONN_POL_ACCEPT) {
-		gsm0808_clear(_conn);
-		bsc_subscr_con_free(_conn);
-		return 1;
-	}
-
-	return 2;
-}
-
-static int handle_cc_setup(struct gsm_subscriber_connection *conn,
-			   struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	uint8_t pdisc = gsm48_hdr_pdisc(gh);
-	uint8_t mtype = gsm48_hdr_msg_type(gh);
-
-	struct bsc_msc_data *msc;
-	struct gsm_mncc_number called;
-	struct tlv_parsed tp;
-	unsigned payload_len;
-
-	char _dest_nr[35];
-
-	/*
-	 * Do we have a setup message here? if not return fast.
-	 */
-	if (pdisc != GSM48_PDISC_CC || mtype != GSM48_MT_CC_SETUP)
-		return 0;
-
-	payload_len = msgb_l3len(msg) - sizeof(*gh);
-
-	tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0);
-	if (!TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) {
-		LOGP(DMSC, LOGL_ERROR, "Called BCD not present in setup.\n");
-		return -1;
-	}
-
-	memset(&called, 0, sizeof(called));
-	gsm48_decode_called(&called,
-			    TLVP_VAL(&tp, GSM48_IE_CALLED_BCD) - 1);
-
-	if (called.plan != 1 && called.plan != 0)
-		return 0;
-
-	if (called.plan == 1 && called.type == 1) {
-		_dest_nr[0] = _dest_nr[1] = '0';
-		memcpy(_dest_nr + 2, called.number, sizeof(called.number));
-	} else
-		memcpy(_dest_nr, called.number, sizeof(called.number));
-
-	/*
-	 * Check if the connection should be moved...
-	 */
-	llist_for_each_entry(msc, &conn->bts->network->bsc_data->mscs, entry) {
-		if (msc->type != MSC_CON_TYPE_LOCAL)
-			continue;
-		if (!msc->local_pref)
-			continue;
-		if (regexec(&msc->local_pref_reg, _dest_nr, 0, NULL, 0) != 0)
-			continue;
-
-		return move_to_msc(conn, msg, msc);
-	}
-
-	return 0;
-}
-
-
-static void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg)
-{
-	int lu_cause;
-	struct msgb *resp;
-	return_when_not_connected(conn);
-
-	LOGP(DMSC, LOGL_INFO, "Tx MSC DTAP LINK_ID=0x%02x\n", link_id);
-
-	/*
-	 * We might want to move this connection to a new MSC. Ask someone
-	 * to handle it. If it was handled we will return.
-	 */
-	if (handle_cc_setup(conn, msg) >= 1)
-		return;
-
-	/* Check the filter */
-	if (bsc_filter_data(conn, msg, &lu_cause) < 0) {
-		bsc_maybe_lu_reject(conn,
-					conn->sccp_con->filter_state.con_type,
-					lu_cause);
-		bsc_clear_request(conn, 0);
-		return;
-	}
-
-	bsc_scan_bts_msg(conn, msg);
-
-	resp = gsm0808_create_dtap(msg, link_id);
-	queue_msg_or_return(resp);
-}
-
-static void bsc_assign_compl(struct gsm_subscriber_connection *conn, uint8_t rr_cause,
-			     uint8_t chosen_channel, uint8_t encr_alg_id,
-			     uint8_t speech_model)
-{
-	struct msgb *resp;
-	return_when_not_connected(conn);
-
-	if (is_ipaccess_bts(conn->bts) && conn->sccp_con->rtp_ip) {
-		/* NOTE: In a network that makes use of an IPA base station
-		 * and AoIP, we have to wait until the BTS reports its RTP
-		 * IP/Port combination back to BSC via RSL. Unfortunately, the
-		 * IPA protocol sends its Abis assignment complete message
-		 * before it sends its RTP IP/Port via IPACC. So we will now
-		 * postpone the AoIP assignment completed message until we
-		 * know the RTP IP/Port combination. */
-		LOGP(DMSC, LOGL_INFO, "POSTPONE MSC ASSIGN COMPL\n");
-		conn->lchan->abis_ip.ass_compl.rr_cause = rr_cause;
-		conn->lchan->abis_ip.ass_compl.chosen_channel = chosen_channel;
-		conn->lchan->abis_ip.ass_compl.encr_alg_id = encr_alg_id;
-		conn->lchan->abis_ip.ass_compl.speech_mode = speech_model;
-		conn->lchan->abis_ip.ass_compl.valid = true;
-
-	} else {
-		/* NOTE: Send the A assignment complete message immediately. */
-		LOGP(DMSC, LOGL_INFO, "Tx MSC ASSIGN COMPL\n");
-		resp = gsm0808_create_assignment_completed(rr_cause, chosen_channel,
-							   encr_alg_id, speech_model);
-		queue_msg_or_return(resp);
-	}
-}
-
-static void bsc_assign_fail(struct gsm_subscriber_connection *conn,
-			    uint8_t cause, uint8_t *rr_cause)
-{
-	struct msgb *resp;
-	return_when_not_connected(conn);
-
-	LOGP(DMSC, LOGL_INFO, "Tx MSC ASSIGN FAIL\n");
-
-	resp = gsm0808_create_assignment_failure(cause, rr_cause);
-	queue_msg_or_return(resp);
-}
-
-static int bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
-{
-	struct osmo_bsc_sccp_con *sccp;
-	struct msgb *resp;
-	return_when_not_connected_val(conn, 1);
-
-	LOGP(DMSC, LOGL_INFO, "Tx MSC CLEAR REQUEST\n");
-
-	/*
-	 * Remove the connection from BSC<->SCCP part, the SCCP part
-	 * will either be cleared by channel release or MSC disconnect
-	 */
-	sccp = conn->sccp_con;
-	sccp->conn = NULL;
-	conn->sccp_con = NULL;
-
-	resp = gsm0808_create_clear_rqst(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE);
-	if (!resp) {
-		LOGP(DMSC, LOGL_ERROR, "Failed to allocate response.\n");
-		return 1;
-	}
-
-	osmo_bsc_sigtran_send(sccp, resp);
-	return 1;
-}
-
-static void bsc_cm_update(struct gsm_subscriber_connection *conn,
-			  const uint8_t *cm2, uint8_t cm2_len,
-			  const uint8_t *cm3, uint8_t cm3_len)
-{
-	struct msgb *resp;
-	return_when_not_connected(conn);
-
-	resp = gsm0808_create_classmark_update(cm2, cm2_len, cm3, cm3_len);
-
-	queue_msg_or_return(resp);
-}
-
-static void bsc_mr_config(struct gsm_subscriber_connection *conn,
-				struct gsm_lchan *lchan, int full_rate)
-{
-	struct bsc_msc_data *msc;
-	struct gsm48_multi_rate_conf *ms_conf, *bts_conf;
-
-	if (!conn->sccp_con) {
-		LOGP(DMSC, LOGL_ERROR,
-		     "No msc data available on conn %p. Audio will be broken.\n",
-		     conn);
-		return;
-	}
-
-	msc = conn->sccp_con->msc;
-
-	/* initialize the data structure */
-	lchan->mr_ms_lv[0] = sizeof(*ms_conf);
-	lchan->mr_bts_lv[0] = sizeof(*bts_conf);
-	ms_conf = (struct gsm48_multi_rate_conf *) &lchan->mr_ms_lv[1];
-	bts_conf = (struct gsm48_multi_rate_conf *) &lchan->mr_bts_lv[1];
-	memset(ms_conf, 0, sizeof(*ms_conf));
-	memset(bts_conf, 0, sizeof(*bts_conf));
-
-	bts_conf->ver = ms_conf->ver = 1;
-	bts_conf->icmi = ms_conf->icmi = 1;
-
-	/* maybe gcc see's it is copy of _one_ byte */
-	bts_conf->m4_75 = ms_conf->m4_75 = msc->amr_conf.m4_75;
-	bts_conf->m5_15 = ms_conf->m5_15 = msc->amr_conf.m5_15;
-	bts_conf->m5_90 = ms_conf->m5_90 = msc->amr_conf.m5_90;
-	bts_conf->m6_70 = ms_conf->m6_70 = msc->amr_conf.m6_70;
-	bts_conf->m7_40 = ms_conf->m7_40 = msc->amr_conf.m7_40;
-	bts_conf->m7_95 = ms_conf->m7_95 = msc->amr_conf.m7_95;
-	if (full_rate) {
-		bts_conf->m10_2 = ms_conf->m10_2 = msc->amr_conf.m10_2;
-		bts_conf->m12_2 = ms_conf->m12_2 = msc->amr_conf.m12_2;
-	}
-
-	/* now copy this into the bts structure */
-	memcpy(lchan->mr_bts_lv, lchan->mr_ms_lv, sizeof(lchan->mr_ms_lv));
-}
-
-static struct bsc_api bsc_handler = {
-	.sapi_n_reject = bsc_sapi_n_reject,
-	.cipher_mode_compl = bsc_cipher_mode_compl,
-	.compl_l3 = bsc_compl_l3,
-	.dtap = bsc_dtap,
-	.assign_compl = bsc_assign_compl,
-	.assign_fail = bsc_assign_fail,
-	.clear_request = bsc_clear_request,
-	.classmark_chg = bsc_cm_update,
-	.mr_config = bsc_mr_config,
-};
-
-struct bsc_api *osmo_bsc_api()
-{
-	return &bsc_handler;
-}
diff --git a/src/osmo-bsc/osmo_bsc_audio.c b/src/osmo-bsc/osmo_bsc_audio.c
deleted file mode 100644
index b4ffa88..0000000
--- a/src/osmo-bsc/osmo_bsc_audio.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * ipaccess audio handling
- *
- * (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-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/>.
- *
- */
-
-#include <openbsc/bsc_msc_data.h>
-#include <openbsc/osmo_bsc.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/debug.h>
-#include <openbsc/signal.h>
-#include <osmocom/gsm/gsm0808.h>
-#include <osmocom/gsm/gsm0808_utils.h>
-#include <openbsc/osmo_bsc_sigtran.h>
-
-#include <arpa/inet.h>
-
-/* Generate and send assignment complete message */
-static int send_aoip_ass_compl(struct gsm_subscriber_connection *conn, struct gsm_lchan *lchan)
-{
-	struct msgb *resp;
-	struct sockaddr_storage rtp_addr;
-	struct sockaddr_in rtp_addr_in;
-	struct gsm0808_speech_codec sc;
-
-	OSMO_ASSERT(lchan->abis_ip.ass_compl.valid == true);
-
-	/* Package RTP-Address data */
-	memset(&rtp_addr_in, 0, sizeof(rtp_addr_in));
-	rtp_addr_in.sin_family = AF_INET;
-	rtp_addr_in.sin_port = htons(lchan->abis_ip.bound_port);
-	rtp_addr_in.sin_addr.s_addr = htonl(lchan->abis_ip.bound_ip);
-	memset(&rtp_addr, 0, sizeof(rtp_addr));
-	memcpy(&rtp_addr, &rtp_addr_in, sizeof(rtp_addr_in));
-
-	/* Extrapolate speech codec from speech mode */
-	gsm0808_speech_codec_from_chan_type(&sc, lchan->abis_ip.ass_compl.speech_mode);
-
-	/* Generate message */
-	resp = gsm0808_create_ass_compl(lchan->abis_ip.ass_compl.rr_cause,
-					lchan->abis_ip.ass_compl.chosen_channel,
-					lchan->abis_ip.ass_compl.encr_alg_id,
-					lchan->abis_ip.ass_compl.speech_mode,
-					&rtp_addr,
-					&sc,
-					NULL);
-
-	if (!resp) {
-		LOGP(DMSC, LOGL_ERROR, "Failed to generate assignment completed message!\n"); \
-		return -EINVAL;
-	}
-
-	return osmo_bsc_sigtran_send(conn->sccp_con, resp);
-}
-
-static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
-				 void *handler_data, void *signal_data)
-{
-	struct gsm_subscriber_connection *con;
-	struct gsm_lchan *lchan = signal_data;
-	int rc;
-	uint32_t rtp_ip;
-
-	if (subsys != SS_ABISIP)
-		return 0;
-
-	con = lchan->conn;
-	if (!con || !con->sccp_con)
-		return 0;
-
-	switch (signal) {
-	case S_ABISIP_CRCX_ACK:
-		/*
-		 * TODO: handle handover here... then the audio should go to
-		 * the old mgcp port..
-		 */
-
-		/* we can ask it to connect now */
-		LOGP(DMSC, LOGL_DEBUG, "Connecting BTS to port: %d conn: %d\n",
-		     con->sccp_con->rtp_port, lchan->abis_ip.conn_id);
-
-		/* If AoIP is in use, the rtp_ip, which has been communicated
-		 * via the A interface as connect_ip */
-		if(con->sccp_con->rtp_ip)
-			rtp_ip = con->sccp_con->rtp_ip;
-		else
-			rtp_ip = ntohl(INADDR_ANY);
-
-		rc = rsl_ipacc_mdcx(lchan, rtp_ip,
-				    con->sccp_con->rtp_port,
-				    lchan->abis_ip.rtp_payload2);
-		if (rc < 0) {
-			LOGP(DMSC, LOGL_ERROR, "Failed to send MDCX: %d\n", rc);
-			return rc;
-		}
-		break;
-
-	case S_ABISIP_MDCX_ACK:
-		if (con->ho_lchan) {
-			/* NOTE: When an ho_lchan exists, the MDCX is part of an
-			 * handover operation (intra-bsc). This means we will not
-			 * inform the MSC about the event, which means that no
-			 * assignment complete message is transmitted */
-			LOGP(DMSC, LOGL_INFO," RTP connection handover complete\n");
-		} else if (is_ipaccess_bts(con->bts) && con->sccp_con->rtp_ip) {
-			/* NOTE: This is only relevant on AoIP networks with
-			 * IPA based base stations. See also osmo_bsc_api.c,
-			 * function bsc_assign_compl() */
-			LOGP(DMSC, LOGL_INFO, "Tx MSC ASSIGN COMPL (POSTPONED)\n");
-			if (send_aoip_ass_compl(con, lchan) != 0)
-				return -EINVAL;
-		}
-		break;
-	break;
-	}
-
-	return 0;
-}
-
-int osmo_bsc_audio_init(struct gsm_network *net)
-{
-	osmo_signal_register_handler(SS_ABISIP, handle_abisip_signal, net);
-	return 0;
-}
diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c
deleted file mode 100644
index 4353b9a..0000000
--- a/src/osmo-bsc/osmo_bsc_bssap.c
+++ /dev/null
@@ -1,721 +0,0 @@
-/* GSM 08.08 BSSMAP handling						*/
-/* (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-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/>.
- *
- */
-
-#include <openbsc/osmo_bsc.h>
-#include <openbsc/osmo_bsc_grace.h>
-#include <openbsc/osmo_bsc_rf.h>
-#include <openbsc/bsc_msc_data.h>
-#include <openbsc/debug.h>
-#include <openbsc/bsc_subscriber.h>
-#include <openbsc/mgcp.h>
-#include <openbsc/paging.h>
-
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-#include <osmocom/gsm/gsm0808.h>
-#include <osmocom/gsm/gsm0808_utils.h>
-#include <openbsc/osmo_bsc_sigtran.h>
-#include <openbsc/a_reset.h>
-#include <osmocom/core/byteswap.h>
-
-#define IP_V4_ADDR_LEN 4
-
-/*
- * helpers for the assignment command
- */
-
-/* Helper function for match_codec_pref(), looks up a matching permitted speech
- * value for a given msc audio codec pref */
-enum gsm0808_permitted_speech audio_support_to_gsm88(struct gsm_audio_support
-						     *audio)
-{
-	if (audio->hr) {
-		switch (audio->ver) {
-		case 1:
-			return GSM0808_PERM_HR1;
-			break;
-		case 2:
-			return GSM0808_PERM_HR2;
-			break;
-		case 3:
-			return GSM0808_PERM_HR3;
-			break;
-		default:
-			LOGP(DMSC, LOGL_ERROR, "Wrong speech mode: %d\n",
-			     audio->ver);
-			return GSM0808_PERM_FR1;
-		}
-	} else {
-		switch (audio->ver) {
-		case 1:
-			return GSM0808_PERM_FR1;
-			break;
-		case 2:
-			return GSM0808_PERM_FR2;
-			break;
-		case 3:
-			return GSM0808_PERM_FR3;
-			break;
-		default:
-			LOGP(DMSC, LOGL_ERROR, "Wrong speech mode: %d\n",
-			     audio->ver);
-			return GSM0808_PERM_HR1;
-		}
-	}
-}
-
-/* Helper function for match_codec_pref(), looks up a matching chan mode for
- * a given permitted speech value */
-enum gsm48_chan_mode gsm88_to_chan_mode(enum gsm0808_permitted_speech speech)
-{
-	switch (speech) {
-	case GSM0808_PERM_HR1:
-	case GSM0808_PERM_FR1:
-		return GSM48_CMODE_SPEECH_V1;
-		break;
-	case GSM0808_PERM_HR2:
-	case GSM0808_PERM_FR2:
-		return GSM48_CMODE_SPEECH_EFR;
-		break;
-	case GSM0808_PERM_HR3:
-	case GSM0808_PERM_FR3:
-		return GSM48_CMODE_SPEECH_AMR;
-		break;
-	default:
-		LOGP(DMSC, LOGL_FATAL,
-		     "Unsupported permitted speech selected, assuming AMR as channel mode...\n");
-		return GSM48_CMODE_SPEECH_AMR;
-	}
-}
-
-/* Helper function for match_codec_pref(), tests if a given audio support
- * matches one of the permitted speech settings of the channel type element.
- * The matched permitted speech value is then also compared against the
- * speech codec list. (optional, only relevant for AoIP) */
-static bool test_codec_pref(const struct gsm0808_channel_type *ct,
-			    const struct gsm0808_speech_codec_list *scl,
-			    uint8_t perm_spch)
-{
-	unsigned int i;
-	bool match = false;
-	struct gsm0808_speech_codec sc;
-	int rc;
-
-	/* Try to finde the given permitted speech value in the
-	 * codec list of the channel type element */
-	for (i = 0; i < ct->perm_spch_len; i++) {
-		if (ct->perm_spch[i] == perm_spch) {
-			match = true;
-			break;
-		}
-	}
-
-	/* If we do not have a speech codec list to test against,
-	 * we just exit early (will be always the case in non-AoIP networks) */
-	if (!scl)
-		return match;
-
-	/* If we failed to match until here, there is no
-	 * point in testing further */
-	if (match == false)
-		return false;
-
-	/* Extrapolate speech codec data */
-	rc = gsm0808_speech_codec_from_chan_type(&sc, perm_spch);
-	if (rc < 0)
-		return false;
-
-	/* Try to find extrapolated speech codec data in
-	 * the speech codec list */
-	for (i = 0; i < scl->len; i++) {
-		if (memcmp(&sc, &scl->codec[i], sizeof(sc)) == 0)
-			return true;
-	}
-
-	return false;
-}
-
-/* Helper function for bssmap_handle_assignm_req(), matches the codec
- * preferences from the MSC with the codec preferences */
-static int match_codec_pref(int *full_rate, enum gsm48_chan_mode *chan_mode,
-			    const struct gsm0808_channel_type *ct,
-			    const struct gsm0808_speech_codec_list *scl,
-			    const struct bsc_msc_data *msc)
-{
-	unsigned int i;
-	uint8_t perm_spch;
-	bool match = false;
-
-	for (i = 0; i < msc->audio_length; i++) {
-		perm_spch = audio_support_to_gsm88(msc->audio_support[i]);
-		if (test_codec_pref(ct, scl, perm_spch)) {
-			match = true;
-			break;
-		}
-	}
-
-	/* Exit without result, in case no match can be deteched */
-	if (!match) {
-		*full_rate = -1;
-		*chan_mode = GSM48_CMODE_SIGN;
-		return -1;
-	}
-
-	/* Check if the result is a half or full rate codec */
-	if (perm_spch == GSM0808_PERM_HR1 || perm_spch == GSM0808_PERM_HR2
-	    || perm_spch == GSM0808_PERM_HR3 || perm_spch == GSM0808_PERM_HR4
-	    || perm_spch == GSM0808_PERM_HR6)
-		*full_rate = 0;
-	else
-		*full_rate = 1;
-
-	/* Lookup a channel mode for the selected codec */
-	*chan_mode = gsm88_to_chan_mode(perm_spch);
-
-	return 0;
-}
-
-static int bssmap_handle_reset_ack(struct bsc_msc_data *msc,
-				   struct msgb *msg, unsigned int length)
-{
-	LOGP(DMSC, LOGL_NOTICE, "RESET ACK from MSC: %s\n",
-	     osmo_sccp_addr_name(osmo_ss7_instance_find(msc->a.cs7_instance),
-				 &msc->a.msc_addr));
-
-	/* Inform the FSM that controls the RESET/RESET-ACK procedure
-	 * that we have successfully received the reset-ack message */
-	a_reset_ack_confirm(msc->a.reset);
-
-	return 0;
-}
-
-/* Handle MSC sided reset */
-static int bssmap_handle_reset(struct bsc_msc_data *msc,
-			       struct msgb *msg, unsigned int length)
-{
-	LOGP(DMSC, LOGL_NOTICE, "RESET from MSC: %s\n",
-	     osmo_sccp_addr_name(osmo_ss7_instance_find(msc->a.cs7_instance),
-				 &msc->a.msc_addr));
-
-	/* Instruct the bsc to close all open sigtran connections and to
-	 * close all active channels on the BTS side as well */
-	osmo_bsc_sigtran_reset(msc);
-
-	/* Inform the MSC that we have received the reset request and
-	 * that we acted accordingly */
-	osmo_bsc_sigtran_tx_reset_ack(msc);
-
-	return 0;
-}
-
-/* GSM 08.08 § 3.2.1.19 */
-static int bssmap_handle_paging(struct bsc_msc_data *msc,
-				struct msgb *msg, unsigned int payload_length)
-{
-	struct bsc_subscr *subscr;
-	struct tlv_parsed tp;
-	char mi_string[GSM48_MI_SIZE];
-	uint32_t tmsi = GSM_RESERVED_TMSI;
-	unsigned int lac = GSM_LAC_RESERVED_ALL_BTS;
-	uint8_t data_length;
-	const uint8_t *data;
-	uint8_t chan_needed = RSL_CHANNEED_ANY;
-
-	tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, payload_length - 1, 0, 0);
-
-	if (!TLVP_PRESENT(&tp, GSM0808_IE_IMSI)) {
-		LOGP(DMSC, LOGL_ERROR, "Mandatory IMSI not present.\n");
-		return -1;
-	} else if ((TLVP_VAL(&tp, GSM0808_IE_IMSI)[0] & GSM_MI_TYPE_MASK) != GSM_MI_TYPE_IMSI) {
-		LOGP(DMSC, LOGL_ERROR, "Wrong content in the IMSI\n");
-		return -1;
-	}
-
-	if (!TLVP_PRESENT(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST)) {
-		LOGP(DMSC, LOGL_ERROR, "Mandatory CELL IDENTIFIER LIST not present.\n");
-		return -1;
-	}
-
-	if (TLVP_PRESENT(&tp, GSM0808_IE_TMSI) &&
-	    TLVP_LEN(&tp, GSM0808_IE_TMSI) == 4) {
-		tmsi = ntohl(tlvp_val32_unal(&tp, GSM0808_IE_TMSI));
-	}
-
-	/*
-	 * parse the IMSI
-	 */
-	gsm48_mi_to_string(mi_string, sizeof(mi_string),
-			   TLVP_VAL(&tp, GSM0808_IE_IMSI), TLVP_LEN(&tp, GSM0808_IE_IMSI));
-
-	/*
-	 * parse the cell identifier list
-	 */
-	data_length = TLVP_LEN(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
-	data = TLVP_VAL(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
-
-	/*
-	 * Support paging to all network or one BTS at one LAC
-	 */
-	if (data_length == 3 && data[0] == CELL_IDENT_LAC) {
-		lac = osmo_load16be(&data[1]);
-	} else if (data_length > 1 || (data[0] & 0x0f) != CELL_IDENT_BSS) {
-		LOGP(DMSC, LOGL_ERROR, "Unsupported Cell Identifier List: %s\n", osmo_hexdump(data, data_length));
-		return -1;
-	}
-
-	if (TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_NEEDED) && TLVP_LEN(&tp, GSM0808_IE_CHANNEL_NEEDED) == 1)
-		chan_needed = TLVP_VAL(&tp, GSM0808_IE_CHANNEL_NEEDED)[0] & 0x03;
-
-	if (TLVP_PRESENT(&tp, GSM0808_IE_EMLPP_PRIORITY)) {
-		LOGP(DMSC, LOGL_ERROR, "eMLPP is not handled\n");
-	}
-
-	subscr = bsc_subscr_find_or_create_by_imsi(msc->network->bsc_subscribers,
-						   mi_string);
-	if (!subscr) {
-		LOGP(DMSC, LOGL_ERROR, "Failed to allocate a subscriber for %s\n", mi_string);
-		return -1;
-	}
-
-	subscr->lac = lac;
-	subscr->tmsi = tmsi;
-
-	LOGP(DMSC, LOGL_INFO, "Paging request from MSC IMSI: '%s' TMSI: '0x%x/%u' LAC: 0x%x\n", mi_string, tmsi, tmsi, lac);
-	bsc_grace_paging_request(msc->network->bsc_data->rf_ctrl->policy,
-				 subscr, chan_needed, msc);
-	return 0;
-}
-
-/*
- * GSM 08.08 § 3.1.9.1 and 3.2.1.21...
- * release our gsm_subscriber_connection and send message
- */
-static int bssmap_handle_clear_command(struct osmo_bsc_sccp_con *conn,
-				       struct msgb *msg, unsigned int payload_length)
-{
-	struct msgb *resp;
-
-	/* TODO: handle the cause of this package */
-
-	if (conn->conn) {
-		LOGP(DMSC, LOGL_INFO, "Releasing all transactions on %p\n", conn);
-		gsm0808_clear(conn->conn);
-		bsc_subscr_con_free(conn->conn);
-		conn->conn = NULL;
-	}
-
-	/* send the clear complete message */
-	resp = gsm0808_create_clear_complete();
-	if (!resp) {
-		LOGP(DMSC, LOGL_ERROR, "Sending clear complete failed.\n");
-		return -1;
-	}
-
-	osmo_bsc_sigtran_send(conn, resp);
-	return 0;
-}
-
-/*
- * GSM 08.08 § 3.4.7 cipher mode handling. We will have to pick
- * the cipher to be used for this. In case we are already using
- * a cipher we will have to send cipher mode reject to the MSC,
- * otherwise we will have to pick something that we and the MS
- * is supporting. Currently we are doing it in a rather static
- * way by picking one ecnryption or no encrytpion.
- */
-static int bssmap_handle_cipher_mode(struct osmo_bsc_sccp_con *conn,
-				     struct msgb *msg, unsigned int payload_length)
-{
-	uint16_t len;
-	struct gsm_network *network = NULL;
-	const uint8_t *data;
-	struct tlv_parsed tp;
-	struct msgb *resp;
-	int reject_cause = -1;
-	int include_imeisv = 1;
-
-	if (!conn->conn) {
-		LOGP(DMSC, LOGL_ERROR, "No lchan/msc_data in cipher mode command.\n");
-		goto reject;
-	}
-
-	if (conn->ciphering_handled) {
-		LOGP(DMSC, LOGL_ERROR, "Already seen ciphering command. Protocol Error.\n");
-		goto reject;
-	}
-
-	conn->ciphering_handled = 1;
-
-	tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, payload_length - 1, 0, 0);
-	if (!TLVP_PRESENT(&tp, GSM0808_IE_ENCRYPTION_INFORMATION)) {
-		LOGP(DMSC, LOGL_ERROR, "IE Encryption Information missing.\n");
-		goto reject;
-	}
-
-	/*
-	 * check if our global setting is allowed
-	 *  - Currently we check for A5/0 and A5/1
-	 *  - Copy the key if that is necessary
-	 *  - Otherwise reject
-	 */
-	len = TLVP_LEN(&tp, GSM0808_IE_ENCRYPTION_INFORMATION);
-	if (len < 1) {
-		LOGP(DMSC, LOGL_ERROR, "IE Encryption Information is too short.\n");
-		goto reject;
-	}
-
-	network = conn->conn->bts->network;
-	data = TLVP_VAL(&tp, GSM0808_IE_ENCRYPTION_INFORMATION);
-
-	if (TLVP_PRESENT(&tp, GSM0808_IE_CIPHER_RESPONSE_MODE))
-		include_imeisv = TLVP_VAL(&tp, GSM0808_IE_CIPHER_RESPONSE_MODE)[0] & 0x1;
-
-	if (network->a5_encryption == 0 && (data[0] & 0x1) == 0x1) {
-		gsm0808_cipher_mode(conn->conn, 0, NULL, 0, include_imeisv);
-	} else if (network->a5_encryption != 0 && (data[0] & 0x2) == 0x2) {
-		gsm0808_cipher_mode(conn->conn, 1, &data[1], len - 1, include_imeisv);
-	} else {
-		LOGP(DMSC, LOGL_ERROR, "Can not select encryption...\n");
-		goto reject;
-	}
-
-	return 0;
-
-reject:
-	resp = gsm0808_create_cipher_reject(reject_cause);
-	if (!resp) {
-		LOGP(DMSC, LOGL_ERROR, "Sending the cipher reject failed.\n");
-		return -1;
-	}
-
-	osmo_bsc_sigtran_send(conn, resp);
-	return -1;
-}
-
-/*
- * Handle the assignment request message.
- *
- * See §3.2.1.1 for the message type
- */
-static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn,
-				     struct msgb *msg, unsigned int length)
-{
-	struct msgb *resp;
-	struct bsc_msc_data *msc;
-	struct tlv_parsed tp;
-	uint8_t timeslot = 0;
-	uint8_t multiplex = 0;
-	enum gsm48_chan_mode chan_mode = GSM48_CMODE_SIGN;
-	int port, full_rate = -1;
-	bool aoip = false;
-	struct sockaddr_storage rtp_addr;
-	struct sockaddr_in *rtp_addr_in;
-	struct gsm0808_channel_type ct;
-	struct gsm0808_speech_codec_list scl;
-	struct gsm0808_speech_codec_list *scl_ptr = NULL;
-	int rc;
-	const uint8_t *data;
-	char len;
-
-	if (!conn->conn) {
-		LOGP(DMSC, LOGL_ERROR,
-		     "No lchan/msc_data in cipher mode command.\n");
-		return -1;
-	}
-
-	msc = conn->msc;
-
-	tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, length - 1, 0, 0);
-
-	/* Check for channel type element, if its missing, immediately reject */
-	if (!TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_TYPE)) {
-		LOGP(DMSC, LOGL_ERROR, "Mandatory channel type not present.\n");
-		goto reject;
-	}
-
-	/* Detect if a CIC code is present, if so, we use the classic ip.access
-	 * method to calculate the RTP port */
-	if (TLVP_PRESENT(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE)) {
-		conn->cic =
-		    osmo_load16be(TLVP_VAL
-				  (&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE));
-		timeslot = conn->cic & 0x1f;
-		multiplex = (conn->cic & ~0x1f) >> 5;
-	} else if (TLVP_PRESENT(&tp, GSM0808_IE_AOIP_TRASP_ADDR)) {
-		/* Decode AoIP transport address element */
-		data = TLVP_VAL(&tp, GSM0808_IE_AOIP_TRASP_ADDR);
-		len = TLVP_LEN(&tp, GSM0808_IE_AOIP_TRASP_ADDR);
-		rc = gsm0808_dec_aoip_trasp_addr(&rtp_addr, data, len);
-		if (rc < 0) {
-			LOGP(DMSC, LOGL_ERROR,
-			     "Unable to decode aoip transport address.\n");
-			goto reject;
-		}
-		aoip = true;
-	} else {
-		LOGP(DMSC, LOGL_ERROR,
-		     "transport address missing. Audio routing will not work.\n");
-		goto reject;
-	}
-
-	/* Decode speech codec list (AoIP) */
-	if (aoip) {
-		/* Check for speech codec list element */
-		if (!TLVP_PRESENT(&tp, GSM0808_IE_SPEECH_CODEC_LIST)) {
-			LOGP(DMSC, LOGL_ERROR,
-			     "Mandatory speech codec list not present.\n");
-			goto reject;
-		}
-
-		/* Decode Speech Codec list */
-		data = TLVP_VAL(&tp, GSM0808_IE_SPEECH_CODEC_LIST);
-		len = TLVP_LEN(&tp, GSM0808_IE_SPEECH_CODEC_LIST);
-		rc = gsm0808_dec_speech_codec_list(&scl, data, len);
-		if (rc < 0) {
-			LOGP(DMSC, LOGL_ERROR,
-			     "Unable to decode speech codec list\n");
-			goto reject;
-		}
-		scl_ptr = &scl;
-	}
-
-	/* Decode Channel Type element */
-	data = TLVP_VAL(&tp, GSM0808_IE_CHANNEL_TYPE);
-	len = TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE);
-	rc = gsm0808_dec_channel_type(&ct, data, len);
-	if (rc < 0) {
-		LOGP(DMSC, LOGL_ERROR, "unable to decode channel type.\n");
-		goto reject;
-	}
-
-	/* Currently we only support a limited subset of all
-	 * possible channel types. The limitation ends by not using
-	 * multi-slot, limiting the channel coding to speech */
-	if (ct.ch_indctr != GSM0808_CHAN_SPEECH) {
-		LOGP(DMSC, LOGL_ERROR,
-		     "Unsupported channel type, currently only speech is supported!\n");
-		goto reject;
-	}
-
-	/* Match codec information from the assignment command against the
-	 * local preferences of the BSC */
-	rc = match_codec_pref(&full_rate, &chan_mode, &ct, scl_ptr, msc);
-	if (rc < 0) {
-		LOGP(DMSC, LOGL_ERROR, "No supported audio type found.\n");
-		goto reject;
-	}
-
-	if (aoip == false) {
-		/* map it to a MGCP Endpoint and a RTP port */
-		port = mgcp_timeslot_to_endpoint(multiplex, timeslot);
-		conn->rtp_port = rtp_calculate_port(port, msc->rtp_base);
-		conn->rtp_ip = 0;
-	} else {
-		/* use address / port supplied with the AoIP
-		 * transport address element */
-		if (rtp_addr.ss_family == AF_INET) {
-			rtp_addr_in = (struct sockaddr_in *)&rtp_addr;
-			conn->rtp_port = osmo_ntohs(rtp_addr_in->sin_port);
-			memcpy(&conn->rtp_ip, &rtp_addr_in->sin_addr.s_addr,
-			       IP_V4_ADDR_LEN);
-			conn->rtp_ip = osmo_ntohl(conn->rtp_ip);
-		} else {
-			LOGP(DMSC, LOGL_ERROR,
-			     "Unsopported addressing scheme. (supports only IPV4)\n");
-			goto reject;
-		}
-	}
-
-	return gsm0808_assign_req(conn->conn, chan_mode, full_rate);
-
-reject:
-	resp =
-	    gsm0808_create_assignment_failure
-	    (GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL);
-	if (!resp) {
-		LOGP(DMSC, LOGL_ERROR, "Channel allocation failure.\n");
-		return -1;
-	}
-
-	osmo_bsc_sigtran_send(conn, resp);
-	return -1;
-}
-
-static int bssmap_rcvmsg_udt(struct bsc_msc_data *msc,
-			     struct msgb *msg, unsigned int length)
-{
-	int ret = 0;
-
-	if (length < 1) {
-		LOGP(DMSC, LOGL_ERROR, "Not enough room: %d\n", length);
-		return -1;
-	}
-
-	LOGP(DMSC, LOGL_INFO, "Rx MSC UDT BSSMAP %s\n",
-		gsm0808_bssmap_name(msg->l4h[0]));
-
-	switch (msg->l4h[0]) {
-	case BSS_MAP_MSG_RESET_ACKNOWLEDGE:
-		ret = bssmap_handle_reset_ack(msc, msg, length);
-		break;
-	case BSS_MAP_MSG_RESET:
-		ret = bssmap_handle_reset(msc, msg, length);
-		break;
-	case BSS_MAP_MSG_PAGING:
-		ret = bssmap_handle_paging(msc, msg, length);
-		break;
-	}
-
-	return ret;
-}
-
-static int bssmap_rcvmsg_dt1(struct osmo_bsc_sccp_con *conn,
-			     struct msgb *msg, unsigned int length)
-{
-	int ret = 0;
-
-	if (length < 1) {
-		LOGP(DMSC, LOGL_ERROR, "Not enough room: %d\n", length);
-		return -1;
-	}
-
-	LOGP(DMSC, LOGL_INFO, "Rx MSC DT1 BSSMAP %s\n",
-		gsm0808_bssmap_name(msg->l4h[0]));
-
-	switch (msg->l4h[0]) {
-	case BSS_MAP_MSG_CLEAR_CMD:
-		ret = bssmap_handle_clear_command(conn, msg, length);
-		break;
-	case BSS_MAP_MSG_CIPHER_MODE_CMD:
-		ret = bssmap_handle_cipher_mode(conn, msg, length);
-		break;
-	case BSS_MAP_MSG_ASSIGMENT_RQST:
-		ret = bssmap_handle_assignm_req(conn, msg, length);
-		break;
-	default:
-		LOGP(DMSC, LOGL_NOTICE, "Unimplemented msg type: %s\n",
-			gsm0808_bssmap_name(msg->l4h[0]));
-		break;
-	}
-
-	return ret;
-}
-
-static int dtap_rcvmsg(struct osmo_bsc_sccp_con *conn,
-		       struct msgb *msg, unsigned int length)
-{
-	struct dtap_header *header;
-	struct msgb *gsm48;
-	uint8_t *data;
-	int rc, dtap_rc;
-
-	LOGP(DMSC, LOGL_DEBUG, "Rx MSC DTAP: %s\n",
-		osmo_hexdump(msg->l3h, length));
-
-	if (!conn->conn) {
-		LOGP(DMSC, LOGL_ERROR, "No subscriber connection available\n");
-		return -1;
-	}
-
-	header = (struct dtap_header *) msg->l3h;
-	if (sizeof(*header) >= length) {
-		LOGP(DMSC, LOGL_ERROR, "The DTAP header does not fit. Wanted: %zu got: %u\n", sizeof(*header), length);
-                LOGP(DMSC, LOGL_ERROR, "hex: %s\n", osmo_hexdump(msg->l3h, length));
-                return -1;
-	}
-
-	if (header->length > length - sizeof(*header)) {
-		LOGP(DMSC, LOGL_ERROR, "The DTAP l4 information does not fit: header: %u length: %u\n", header->length, length);
-                LOGP(DMSC, LOGL_ERROR, "hex: %s\n", osmo_hexdump(msg->l3h, length));
-		return -1;
-	}
-
-	LOGP(DMSC, LOGL_INFO, "Rx MSC DTAP, SAPI: %u CHAN: %u\n", header->link_id & 0x07, header->link_id & 0xC0);
-
-	/* forward the data */
-	gsm48 = gsm48_msgb_alloc_name("GSM 04.08 DTAP RCV");
-	if (!gsm48) {
-		LOGP(DMSC, LOGL_ERROR, "Allocation of the message failed.\n");
-		return -1;
-	}
-
-	gsm48->l3h = gsm48->data;
-	data = msgb_put(gsm48, length - sizeof(*header));
-	memcpy(data, msg->l3h + sizeof(*header), length - sizeof(*header));
-
-	/* pass it to the filter for extra actions */
-	rc = bsc_scan_msc_msg(conn->conn, gsm48);
-	dtap_rc = gsm0808_submit_dtap(conn->conn, gsm48, header->link_id, 1);
-	if (rc == BSS_SEND_USSD)
-		bsc_send_welcome_ussd(conn->conn);
-	return dtap_rc;
-}
-
-int bsc_handle_udt(struct bsc_msc_data *msc,
-		   struct msgb *msgb, unsigned int length)
-{
-	struct bssmap_header *bs;
-
-	LOGP(DMSC, LOGL_DEBUG, "Rx MSC UDT: %s\n",
-		osmo_hexdump(msgb->l3h, length));
-
-	if (length < sizeof(*bs)) {
-		LOGP(DMSC, LOGL_ERROR, "The header is too short.\n");
-		return -1;
-	}
-
-	bs = (struct bssmap_header *) msgb->l3h;
-	if (bs->length < length - sizeof(*bs))
-		return -1;
-
-	switch (bs->type) {
-	case BSSAP_MSG_BSS_MANAGEMENT:
-		msgb->l4h = &msgb->l3h[sizeof(*bs)];
-		bssmap_rcvmsg_udt(msc, msgb, length - sizeof(*bs));
-		break;
-	default:
-		LOGP(DMSC, LOGL_NOTICE, "Unimplemented msg type: %s\n",
-			gsm0808_bssmap_name(bs->type));
-	}
-
-	return 0;
-}
-
-int bsc_handle_dt(struct osmo_bsc_sccp_con *conn,
-		  struct msgb *msg, unsigned int len)
-{
-	if (len < sizeof(struct bssmap_header)) {
-		LOGP(DMSC, LOGL_ERROR, "The header is too short.\n");
-	}
-
-	switch (msg->l3h[0]) {
-	case BSSAP_MSG_BSS_MANAGEMENT:
-		msg->l4h = &msg->l3h[sizeof(struct bssmap_header)];
-		bssmap_rcvmsg_dt1(conn, msg, len - sizeof(struct bssmap_header));
-		break;
-	case BSSAP_MSG_DTAP:
-		dtap_rcvmsg(conn, msg, len);
-		break;
-	default:
-		LOGP(DMSC, LOGL_NOTICE, "Unimplemented BSSAP msg type: %s\n",
-			gsm0808_bssap_name(msg->l3h[0]));
-	}
-
-	return -1;
-}
diff --git a/src/osmo-bsc/osmo_bsc_ctrl.c b/src/osmo-bsc/osmo_bsc_ctrl.c
deleted file mode 100644
index c23ed21..0000000
--- a/src/osmo-bsc/osmo_bsc_ctrl.c
+++ /dev/null
@@ -1,680 +0,0 @@
-/* (C) 2011 by Daniel Willmann <daniel@totalueberwachung.de>
- * (C) 2011 by Holger Hans Peter Freyther
- * (C) 2011 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/>.
- *
- */
-
-#include <osmocom/ctrl/control_cmd.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/osmo_bsc.h>
-#include <openbsc/osmo_bsc_rf.h>
-#include <openbsc/bsc_msc_data.h>
-#include <openbsc/signal.h>
-#include <openbsc/gsm_04_80.h>
-
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/signal.h>
-#include <osmocom/core/talloc.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <unistd.h>
-
-void osmo_bsc_send_trap(struct ctrl_cmd *cmd, struct bsc_msc_connection *msc_con)
-{
-	struct ctrl_cmd *trap;
-	struct ctrl_handle *ctrl;
-	struct bsc_msc_data *msc_data;
-
-	msc_data = (struct bsc_msc_data *) msc_con->write_queue.bfd.data;
-	ctrl = msc_data->network->ctrl;
-
-	trap = ctrl_cmd_trap(cmd);
-	if (!trap) {
-		LOGP(DCTRL, LOGL_ERROR, "Failed to create trap.\n");
-		return;
-	}
-
-	ctrl_cmd_send_to_all(ctrl, trap);
-	ctrl_cmd_send(&msc_con->write_queue, trap);
-
-	talloc_free(trap);
-}
-
-CTRL_CMD_DEFINE_RO(msc_connection_status, "msc_connection_status");
-static int msc_connection_status = 0;
-
-static int get_msc_connection_status(struct ctrl_cmd *cmd, void *data)
-{
-	if (msc_connection_status)
-		cmd->reply = "connected";
-	else
-		cmd->reply = "disconnected";
-	return CTRL_CMD_REPLY;
-}
-
-static int msc_connection_status_trap_cb(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data)
-{
-	struct ctrl_cmd *cmd;
-	struct gsm_network *gsmnet = (struct gsm_network *)handler_data;
-
-	if (signal == S_MSC_LOST && msc_connection_status == 1) {
-		LOGP(DCTRL, LOGL_DEBUG, "MSC connection lost, sending TRAP.\n");
-		msc_connection_status = 0;
-	} else if (signal == S_MSC_CONNECTED && msc_connection_status == 0) {
-		LOGP(DCTRL, LOGL_DEBUG, "MSC connection (re)established, sending TRAP.\n");
-		msc_connection_status = 1;
-	} else {
-		return 0;
-	}
-
-	cmd = ctrl_cmd_create(tall_bsc_ctx, CTRL_TYPE_TRAP);
-	if (!cmd) {
-		LOGP(DCTRL, LOGL_ERROR, "Trap creation failed.\n");
-		return 0;
-	}
-
-	cmd->id = "0";
-	cmd->variable = "msc_connection_status";
-
-	get_msc_connection_status(cmd, NULL);
-
-	ctrl_cmd_send_to_all(gsmnet->ctrl, cmd);
-
-	talloc_free(cmd);
-
-	return 0;
-}
-
-CTRL_CMD_DEFINE_RO(bts_connection_status, "bts_connection_status");
-static int bts_connection_status = 0;
-
-static int get_bts_connection_status(struct ctrl_cmd *cmd, void *data)
-{
-	if (bts_connection_status)
-		cmd->reply = "connected";
-	else
-		cmd->reply = "disconnected";
-	return CTRL_CMD_REPLY;
-}
-
-static int bts_connection_status_trap_cb(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data)
-{
-	struct ctrl_cmd *cmd;
-	struct gsm_network *gsmnet = (struct gsm_network *)handler_data;
-	struct gsm_bts *bts;
-	int bts_current_status;
-
-	if (signal != S_L_INP_TEI_DN && signal != S_L_INP_TEI_UP) {
-		return 0;
-	}
-
-	bts_current_status = 0;
-	/* Check if OML on at least one BTS is up */
-	llist_for_each_entry(bts, &gsmnet->bts_list, list) {
-		if (bts->oml_link) {
-			bts_current_status = 1;
-			break;
-		}
-	}
-	if (bts_connection_status == 0 && bts_current_status == 1) {
-		LOGP(DCTRL, LOGL_DEBUG, "BTS connection (re)established, sending TRAP.\n");
-	} else if (bts_connection_status == 1 && bts_current_status == 0) {
-		LOGP(DCTRL, LOGL_DEBUG, "No more BTS connected, sending TRAP.\n");
-	} else {
-		return 0;
-	}
-
-	cmd = ctrl_cmd_create(tall_bsc_ctx, CTRL_TYPE_TRAP);
-	if (!cmd) {
-		LOGP(DCTRL, LOGL_ERROR, "Trap creation failed.\n");
-		return 0;
-	}
-
-	bts_connection_status = bts_current_status;
-
-	cmd->id = "0";
-	cmd->variable = "bts_connection_status";
-
-	get_bts_connection_status(cmd, NULL);
-
-	ctrl_cmd_send_to_all(gsmnet->ctrl, cmd);
-
-	talloc_free(cmd);
-
-	return 0;
-}
-
-static int get_bts_loc(struct ctrl_cmd *cmd, void *data);
-
-static void generate_location_state_trap(struct gsm_bts *bts, struct bsc_msc_connection *msc_con)
-{
-	struct ctrl_cmd *cmd;
-	const char *oper, *admin, *policy;
-
-	cmd = ctrl_cmd_create(msc_con, CTRL_TYPE_TRAP);
-	if (!cmd) {
-		LOGP(DCTRL, LOGL_ERROR, "Failed to create TRAP command.\n");
-		return;
-	}
-
-	cmd->id = "0";
-	cmd->variable = talloc_asprintf(cmd, "bts.%i.location-state", bts->nr);
-
-	/* Prepare the location reply */
-	cmd->node = bts;
-	get_bts_loc(cmd, NULL);
-
-	oper = osmo_bsc_rf_get_opstate_name(osmo_bsc_rf_get_opstate_by_bts(bts));
-	admin = osmo_bsc_rf_get_adminstate_name(osmo_bsc_rf_get_adminstate_by_bts(bts));
-	policy = osmo_bsc_rf_get_policy_name(osmo_bsc_rf_get_policy_by_bts(bts));
-
-	cmd->reply = talloc_asprintf_append(cmd->reply,
-				",%s,%s,%s,%d,%d",
-				oper, admin, policy,
-				bts->network->country_code,
-				bts->network->network_code);
-
-	osmo_bsc_send_trap(cmd, msc_con);
-	talloc_free(cmd);
-}
-
-void bsc_gen_location_state_trap(struct gsm_bts *bts)
-{
-	struct bsc_msc_data *msc;
-
-	llist_for_each_entry(msc, &bts->network->bsc_data->mscs, entry)
-		generate_location_state_trap(bts, msc->msc_con);
-}
-
-static int location_equal(struct bts_location *a, struct bts_location *b)
-{
-	return ((a->tstamp == b->tstamp) && (a->valid == b->valid) && (a->lat == b->lat) &&
-		(a->lon == b->lon) && (a->height == b->height));
-}
-
-static void cleanup_locations(struct llist_head *locations)
-{
-	struct bts_location *myloc, *tmp;
-	int invalpos = 0, i = 0;
-
-	LOGP(DCTRL, LOGL_DEBUG, "Checking position list.\n");
-	llist_for_each_entry_safe(myloc, tmp, locations, list) {
-		i++;
-		if (i > 3) {
-			LOGP(DCTRL, LOGL_DEBUG, "Deleting old position.\n");
-			llist_del(&myloc->list);
-			talloc_free(myloc);
-		} else if (myloc->valid == BTS_LOC_FIX_INVALID) {
-			/* Only capture the newest of subsequent invalid positions */
-			invalpos++;
-			if (invalpos > 1) {
-				LOGP(DCTRL, LOGL_DEBUG, "Deleting subsequent invalid position.\n");
-				invalpos--;
-				i--;
-				llist_del(&myloc->list);
-				talloc_free(myloc);
-			}
-		} else {
-			invalpos = 0;
-		}
-	}
-	LOGP(DCTRL, LOGL_DEBUG, "Found %i positions.\n", i);
-}
-
-CTRL_CMD_DEFINE(bts_loc, "location");
-static int get_bts_loc(struct ctrl_cmd *cmd, void *data)
-{
-	struct bts_location *curloc;
-	struct gsm_bts *bts = (struct gsm_bts *) cmd->node;
-	if (!bts) {
-		cmd->reply = "bts not found.";
-		return CTRL_CMD_ERROR;
-	}
-
-	if (llist_empty(&bts->loc_list)) {
-		cmd->reply = talloc_asprintf(cmd, "0,invalid,0,0,0");
-		return CTRL_CMD_REPLY;
-	} else {
-		curloc = llist_entry(bts->loc_list.next, struct bts_location, list);
-	}
-
-	cmd->reply = talloc_asprintf(cmd, "%lu,%s,%f,%f,%f", curloc->tstamp,
-			get_value_string(bts_loc_fix_names, curloc->valid), curloc->lat, curloc->lon, curloc->height);
-	if (!cmd->reply) {
-		cmd->reply = "OOM";
-		return CTRL_CMD_ERROR;
-	}
-
-	return CTRL_CMD_REPLY;
-}
-
-static int set_bts_loc(struct ctrl_cmd *cmd, void *data)
-{
-	char *saveptr, *lat, *lon, *height, *tstamp, *valid, *tmp;
-	struct bts_location *curloc, *lastloc;
-	int ret;
-	struct gsm_bts *bts = (struct gsm_bts *) cmd->node;
-	if (!bts) {
-		cmd->reply = "bts not found.";
-		return CTRL_CMD_ERROR;
-	}
-
-	tmp = talloc_strdup(cmd, cmd->value);
-	if (!tmp)
-		goto oom;
-
-	curloc = talloc_zero(tall_bsc_ctx, struct bts_location);
-	if (!curloc) {
-		talloc_free(tmp);
-		goto oom;
-	}
-	INIT_LLIST_HEAD(&curloc->list);
-
-
-	tstamp = strtok_r(tmp, ",", &saveptr);
-	valid = strtok_r(NULL, ",", &saveptr);
-	lat = strtok_r(NULL, ",", &saveptr);
-	lon = strtok_r(NULL, ",", &saveptr);
-	height = strtok_r(NULL, "\0", &saveptr);
-
-	curloc->tstamp = atol(tstamp);
-	curloc->valid = get_string_value(bts_loc_fix_names, valid);
-	curloc->lat = atof(lat);
-	curloc->lon = atof(lon);
-	curloc->height = atof(height);
-	talloc_free(tmp);
-
-	lastloc = llist_entry(bts->loc_list.next, struct bts_location, list);
-
-	/* Add location to the end of the list */
-	llist_add(&curloc->list, &bts->loc_list);
-
-	ret = get_bts_loc(cmd, data);
-
-	if (!location_equal(curloc, lastloc))
-		bsc_gen_location_state_trap(bts);
-
-	cleanup_locations(&bts->loc_list);
-
-	return ret;
-
-oom:
-	cmd->reply = "OOM";
-	return CTRL_CMD_ERROR;
-}
-
-static int verify_bts_loc(struct ctrl_cmd *cmd, const char *value, void *data)
-{
-	char *saveptr, *latstr, *lonstr, *heightstr, *tstampstr, *validstr, *tmp;
-	time_t tstamp;
-	int valid;
-	double lat, lon, height __attribute__((unused));
-
-	tmp = talloc_strdup(cmd, value);
-	if (!tmp)
-		return 1;
-
-	tstampstr = strtok_r(tmp, ",", &saveptr);
-	validstr = strtok_r(NULL, ",", &saveptr);
-	latstr = strtok_r(NULL, ",", &saveptr);
-	lonstr = strtok_r(NULL, ",", &saveptr);
-	heightstr = strtok_r(NULL, "\0", &saveptr);
-
-	if ((tstampstr == NULL) || (validstr == NULL) || (latstr == NULL) ||
-			(lonstr == NULL) || (heightstr == NULL))
-		goto err;
-
-	tstamp = atol(tstampstr);
-	valid = get_string_value(bts_loc_fix_names, validstr);
-	lat = atof(latstr);
-	lon = atof(lonstr);
-	height = atof(heightstr);
-	talloc_free(tmp);
-	tmp = NULL;
-
-	if (((tstamp == 0) && (valid != BTS_LOC_FIX_INVALID)) || (lat < -90) || (lat > 90) ||
-			(lon < -180) || (lon > 180) || (valid < 0)) {
-		goto err;
-	}
-
-	return 0;
-
-err:
-	talloc_free(tmp);
-	cmd->reply = talloc_strdup(cmd, "The format is <unixtime>,(invalid|fix2d|fix3d),<lat>,<lon>,<height>");
-	return 1;
-}
-
-CTRL_CMD_DEFINE(net_timezone, "timezone");
-static int get_net_timezone(struct ctrl_cmd *cmd, void *data)
-{
-	struct gsm_network *net = (struct gsm_network*)cmd->node;
-
-	struct gsm_tz *tz = &net->tz;
-	if (tz->override)
-		cmd->reply = talloc_asprintf(cmd, "%d,%d,%d",
-			       tz->hr, tz->mn, tz->dst);
-	else
-		cmd->reply = talloc_asprintf(cmd, "off");
-
-	if (!cmd->reply) {
-		cmd->reply = "OOM";
-		return CTRL_CMD_ERROR;
-	}
-
-	return CTRL_CMD_REPLY;
-}
-
-static int set_net_timezone(struct ctrl_cmd *cmd, void *data)
-{
-	char *saveptr, *hourstr, *minstr, *dststr, *tmp = 0;
-	int override;
-	struct gsm_network *net = (struct gsm_network*)cmd->node;
-
-	tmp = talloc_strdup(cmd, cmd->value);
-	if (!tmp)
-		goto oom;
-
-	hourstr = strtok_r(tmp, ",", &saveptr);
-	minstr = strtok_r(NULL, ",", &saveptr);
-	dststr = strtok_r(NULL, ",", &saveptr);
-
-	override = 0;
-
-	if (hourstr != NULL)
-		override = strcasecmp(hourstr, "off") != 0;
-
-	struct gsm_tz *tz = &net->tz;
-	tz->override = override;
-
-	if (override) {
-		tz->hr  = hourstr ? atol(hourstr) : 0;
-		tz->mn  = minstr ? atol(minstr) : 0;
-		tz->dst = dststr ? atol(dststr) : 0;
-	}
-
-	talloc_free(tmp);
-	tmp = NULL;
-
-	return get_net_timezone(cmd, data);
-
-oom:
-	cmd->reply = "OOM";
-	return CTRL_CMD_ERROR;
-}
-
-static int verify_net_timezone(struct ctrl_cmd *cmd, const char *value, void *data)
-{
-	char *saveptr, *hourstr, *minstr, *dststr, *tmp;
-	int override, tz_hours, tz_mins, tz_dst;
-
-	tmp = talloc_strdup(cmd, value);
-	if (!tmp)
-		return 1;
-
-	hourstr = strtok_r(tmp, ",", &saveptr);
-	minstr = strtok_r(NULL, ",", &saveptr);
-	dststr = strtok_r(NULL, ",", &saveptr);
-
-	if (hourstr == NULL)
-		goto err;
-
-	override = strcasecmp(hourstr, "off") != 0;
-
-	if (!override) {
-		talloc_free(tmp);
-		return 0;
-	}
-
-	if (minstr == NULL || dststr == NULL)
-		goto err;
-
-	tz_hours = atol(hourstr);
-	tz_mins = atol(minstr);
-	tz_dst = atol(dststr);
-
-	talloc_free(tmp);
-	tmp = NULL;
-
-	if ((tz_hours < -19) || (tz_hours > 19) ||
-	       (tz_mins < 0) || (tz_mins >= 60) || (tz_mins % 15 != 0) ||
-	       (tz_dst < 0) || (tz_dst > 2))
-		goto err;
-
-	return 0;
-
-err:
-	talloc_free(tmp);
-	cmd->reply = talloc_strdup(cmd, "The format is <hours>,<mins>,<dst> or 'off' where -19 <= hours <= 19, mins in {0, 15, 30, 45}, and 0 <= dst <= 2");
-	return 1;
-}
-
-CTRL_CMD_DEFINE(net_notification, "notification");
-static int get_net_notification(struct ctrl_cmd *cmd, void *data)
-{
-	cmd->reply = "There is nothing to read";
-	return CTRL_CMD_ERROR;
-}
-
-static int set_net_notification(struct ctrl_cmd *cmd, void *data)
-{
-	struct ctrl_cmd *trap;
-	struct gsm_network *net;
-
-	net = cmd->node;
-
-	trap = ctrl_cmd_create(tall_bsc_ctx, CTRL_TYPE_TRAP);
-	if (!trap) {
-		LOGP(DCTRL, LOGL_ERROR, "Trap creation failed\n");
-		goto handled;
-	}
-
-	trap->id = "0";
-	trap->variable = "notification";
-	trap->reply = talloc_strdup(trap, cmd->value);
-
-	/*
-	 * This should only be sent to local systems. In the future
-	 * we might even ask for systems to register to receive
-	 * the notifications.
-	 */
-	ctrl_cmd_send_to_all(net->ctrl, trap);
-	talloc_free(trap);
-
-handled:
-	return CTRL_CMD_HANDLED;
-}
-
-static int verify_net_notification(struct ctrl_cmd *cmd, const char *value, void *data)
-{
-	return 0;
-}
-
-CTRL_CMD_DEFINE(net_inform_msc, "inform-msc-v1");
-static int get_net_inform_msc(struct ctrl_cmd *cmd, void *data)
-{
-	cmd->reply = "There is nothing to read";
-	return CTRL_CMD_ERROR;
-}
-
-static int set_net_inform_msc(struct ctrl_cmd *cmd, void *data)
-{
-	struct gsm_network *net;
-	struct bsc_msc_data *msc;
-
-	net = cmd->node;
-	llist_for_each_entry(msc, &net->bsc_data->mscs, entry) {
-		struct ctrl_cmd *trap;
-
-		trap = ctrl_cmd_create(tall_bsc_ctx, CTRL_TYPE_TRAP);
-		if (!trap) {
-			LOGP(DCTRL, LOGL_ERROR, "Trap creation failed\n");
-			continue;
-		}
-
-		trap->id = "0";
-		trap->variable = "inform-msc-v1";
-		trap->reply = talloc_strdup(trap, cmd->value);
-		ctrl_cmd_send(&msc->msc_con->write_queue, trap);
-		talloc_free(trap);
-	}
-
-
-	return CTRL_CMD_HANDLED;
-}
-
-static int verify_net_inform_msc(struct ctrl_cmd *cmd, const char *value, void *data)
-{
-	return 0;
-}
-
-CTRL_CMD_DEFINE(net_ussd_notify, "ussd-notify-v1");
-static int get_net_ussd_notify(struct ctrl_cmd *cmd, void *data)
-{
-	cmd->reply = "There is nothing to read";
-	return CTRL_CMD_ERROR;
-}
-
-static int set_net_ussd_notify(struct ctrl_cmd *cmd, void *data)
-{
-	struct gsm_subscriber_connection *conn;
-	struct gsm_network *net;
-	char *saveptr = NULL;
-	char *cic_str, *alert_str, *text_str;
-	int cic, alert;
-
-	/* Verify has done the test for us */
-	cic_str = strtok_r(cmd->value, ",", &saveptr);
-	alert_str = strtok_r(NULL, ",", &saveptr);
-	text_str = strtok_r(NULL, ",", &saveptr);
-
-	if (!cic_str || !alert_str || !text_str) {
-		cmd->reply = "Programming issue. How did this pass verify?";
-		return CTRL_CMD_ERROR;
-	}
-
-	cmd->reply = "No connection found";
-
-	cic = atoi(cic_str);
-	alert = atoi(alert_str);
-
-	net = cmd->node;
-	llist_for_each_entry(conn, &net->subscr_conns, entry) {
-		if (!conn->sccp_con)
-			continue;
-
-		if (conn->sccp_con->cic != cic)
-			continue;
-
-		/*
-		 * This is a hack. My E71 does not like to immediately
-		 * receive a release complete on a TCH. So schedule a
-		 * release complete to clear any previous attempt. The
-		 * right thing would be to track invokeId and only send
-		 * the release complete when we get a returnResultLast
-		 * for this invoke id.
-		 */
-		bsc_send_ussd_release_complete(conn);
-		bsc_send_ussd_notify(conn, alert, text_str);
-		cmd->reply = "Found a connection";
-		break;
-	}
-
-	return CTRL_CMD_REPLY;
-}
-
-static int verify_net_ussd_notify(struct ctrl_cmd *cmd, const char *value, void *data)
-{
-	char *saveptr = NULL;
-	char *inp, *cic, *alert, *text;
-
-	OSMO_ASSERT(cmd);
-	inp = talloc_strdup(cmd, value);
-
-	cic = strtok_r(inp, ",", &saveptr);
-	alert = strtok_r(NULL, ",", &saveptr);
-	text = strtok_r(NULL, ",", &saveptr);
-
-	talloc_free(inp);
-	if (!cic || !alert || !text)
-		return 1;
-	return 0;
-}
-
-static int msc_signal_handler(unsigned int subsys, unsigned int signal,
-			void *handler_data, void *signal_data)
-{
-	struct msc_signal_data *msc;
-	struct gsm_network *net;
-	struct gsm_bts *bts;
-
-	if (subsys != SS_MSC)
-		return 0;
-	if (signal != S_MSC_AUTHENTICATED)
-		return 0;
-
-	msc = signal_data;
-
-	net = msc->data->network;
-	llist_for_each_entry(bts, &net->bts_list, list)
-		generate_location_state_trap(bts, msc->data->msc_con);	
-
-	return 0;
-}
-
-int bsc_ctrl_cmds_install(struct gsm_network *net)
-{
-	int rc;
-
-	rc = bsc_base_ctrl_cmds_install();
-	if (rc)
-		goto end;
-	rc = ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_loc);
-	if (rc)
-		goto end;
-	rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_timezone);
-	if (rc)
-		goto end;
-	rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_msc_connection_status);
-	if (rc)
-		goto end;
-	rc = osmo_signal_register_handler(SS_MSC, &msc_connection_status_trap_cb, net);
-	if (rc)
-		goto end;
-	rc = osmo_signal_register_handler(SS_MSC, msc_signal_handler, NULL);
-	if (rc)
-		goto end;
-	rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_bts_connection_status);
-	if (rc)
-		goto end;
-	rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_notification);
-	if (rc)
-		goto end;
-	rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_inform_msc);
-	if (rc)
-		goto end;
-	rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_ussd_notify);
-	if (rc)
-		goto end;
-	rc = osmo_signal_register_handler(SS_L_INPUT, &bts_connection_status_trap_cb, net);
-
-end:
-	return rc;
-}
diff --git a/src/osmo-bsc/osmo_bsc_filter.c b/src/osmo-bsc/osmo_bsc_filter.c
deleted file mode 100644
index 2c84b16..0000000
--- a/src/osmo-bsc/osmo_bsc_filter.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/* (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2011 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/>.
- *
- */
-
-#include <openbsc/osmo_bsc.h>
-#include <openbsc/bsc_msc_data.h>
-#include <openbsc/gsm_04_80.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/bsc_subscriber.h>
-#include <openbsc/debug.h>
-#include <openbsc/paging.h>
-
-#include <stdlib.h>
-
-static void handle_lu_request(struct gsm_subscriber_connection *conn,
-			      struct msgb *msg)
-{
-	struct gsm48_hdr *gh;
-	struct gsm48_loc_upd_req *lu;
-	struct gsm48_loc_area_id lai;
-	struct gsm_network *net;
-
-	if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*lu)) {
-		LOGP(DMSC, LOGL_ERROR, "LU too small to look at: %u\n", msgb_l3len(msg));
-		return;
-	}
-
-	net = conn->bts->network;
-
-	gh = msgb_l3(msg);
-	lu = (struct gsm48_loc_upd_req *) gh->data;
-
-	gsm48_generate_lai(&lai, net->country_code, net->network_code,
-			   conn->bts->location_area_code);
-
-	if (memcmp(&lai, &lu->lai, sizeof(lai)) != 0) {
-		LOGP(DMSC, LOGL_DEBUG, "Marking con for welcome USSD.\n");
-		conn->sccp_con->new_subscriber = 1;
-	}
-}
-
-/* extract a subscriber from the paging response */
-static struct bsc_subscr *extract_sub(struct gsm_subscriber_connection *conn,
-				   struct msgb *msg)
-{
-	uint8_t mi_type;
-	char mi_string[GSM48_MI_SIZE];
-	struct gsm48_hdr *gh;
-	struct gsm48_pag_resp *resp;
-	struct bsc_subscr *subscr;
-
-	if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*resp)) {
-		LOGP(DMSC, LOGL_ERROR, "PagingResponse too small: %u\n", msgb_l3len(msg));
-		return NULL;
-	}
-
-	gh = msgb_l3(msg);
-	resp = (struct gsm48_pag_resp *) &gh->data[0];
-
-	gsm48_paging_extract_mi(resp, msgb_l3len(msg) - sizeof(*gh),
-				mi_string, &mi_type);
-	DEBUGP(DRR, "PAGING RESPONSE: MI(%s)=%s\n",
-		gsm48_mi_type_name(mi_type), mi_string);
-
-	switch (mi_type) {
-	case GSM_MI_TYPE_TMSI:
-		subscr = bsc_subscr_find_by_tmsi(conn->network->bsc_subscribers,
-					      tmsi_from_string(mi_string));
-		break;
-	case GSM_MI_TYPE_IMSI:
-		subscr = bsc_subscr_find_by_imsi(conn->network->bsc_subscribers,
-					      mi_string);
-		break;
-	default:
-		subscr = NULL;
-		break;
-	}
-
-	return subscr;
-}
-
-/* we will need to stop the paging request */
-static int handle_page_resp(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	struct bsc_subscr *subscr = extract_sub(conn, msg);
-
-	if (!subscr) {
-		LOGP(DMSC, LOGL_ERROR, "Non active subscriber got paged.\n");
-		return -1;
-	}
-
-	paging_request_stop(&conn->network->bts_list, conn->bts, subscr, conn,
-			    msg);
-	bsc_subscr_put(subscr);
-	return 0;
-}
-
-static int is_cm_service_for_emerg(struct msgb *msg)
-{
-	struct gsm48_service_request *cm;
-	struct gsm48_hdr *gh = msgb_l3(msg);
-
-	if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*cm)) {
-		LOGP(DMSC, LOGL_ERROR, "CM ServiceRequest does not fit.\n");
-		return 0;
-	}
-
-	cm = (struct gsm48_service_request *) &gh->data[0];
-	return cm->cm_service_type == GSM48_CMSERV_EMERGENCY;
-}
-
-struct bsc_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn,
-				   struct msgb *msg)
-{
-	struct gsm48_hdr *gh;
-	int8_t pdisc;
-	uint8_t mtype;
-	struct osmo_bsc_data *bsc;
-	struct bsc_msc_data *msc, *pag_msc;
-	struct bsc_subscr *subscr;
-	int is_emerg = 0;
-
-	bsc = conn->bts->network->bsc_data;
-
-	if (msgb_l3len(msg) < sizeof(*gh)) {
-		LOGP(DMSC, LOGL_ERROR, "There is no GSM48 header here.\n");
-		return NULL;
-	}
-
-	gh = msgb_l3(msg);
-	pdisc = gsm48_hdr_pdisc(gh);
-	mtype = gsm48_hdr_msg_type(gh);
-
-	/*
-	 * We are asked to select a MSC here but they are not equal. We
-	 * want to respond to a paging request on the MSC where we got the
-	 * request from. This is where we need to decide where this connection
-	 * will go.
-	 */
-	if (pdisc == GSM48_PDISC_RR && mtype == GSM48_MT_RR_PAG_RESP)
-		goto paging;
-	else if (pdisc == GSM48_PDISC_MM && mtype == GSM48_MT_MM_CM_SERV_REQ) {
-		is_emerg = is_cm_service_for_emerg(msg);
-		goto round_robin;
-	} else
-		goto round_robin;
-
-round_robin:
-	llist_for_each_entry(msc, &bsc->mscs, entry) {
-		if (!msc->msc_con->is_authenticated)
-			continue;
-		if (!is_emerg && msc->type != MSC_CON_TYPE_NORMAL)
-			continue;
-		if (is_emerg && !msc->allow_emerg)
-			continue;
-
-		/* force round robin by moving it to the end */
-		llist_move_tail(&msc->entry, &bsc->mscs);
-		return msc;
-	}
-
-	return NULL;
-
-paging:
-	subscr = extract_sub(conn, msg);
-
-	if (!subscr) {
-		LOGP(DMSC, LOGL_ERROR, "Got paged but no subscriber found.\n");
-		return NULL;
-	}
-
-	pag_msc = paging_get_data(conn->bts, subscr);
-	bsc_subscr_put(subscr);
-
-	llist_for_each_entry(msc, &bsc->mscs, entry) {
-		if (msc != pag_msc)
-			continue;
-
-		/*
-		 * We don't check if the MSC is connected. In case it
-		 * is not the connection will be dropped.
-		 */
-
-		/* force round robin by moving it to the end */
-		llist_move_tail(&msc->entry, &bsc->mscs);
-		return msc;
-	}
-
-	LOGP(DMSC, LOGL_ERROR, "Got paged but no request found.\n");
-	return NULL;
-}
-
-
-/**
- * This is used to scan a message for extra functionality of the BSC. This
- * includes scanning for location updating requests/acceptd and then send
- * a welcome USSD message to the subscriber.
- */
-int bsc_scan_bts_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	struct gsm48_hdr *gh = msgb_l3(msg);
-	uint8_t pdisc = gsm48_hdr_pdisc(gh);
-	uint8_t mtype = gsm48_hdr_msg_type(gh);
-
-	if (pdisc == GSM48_PDISC_MM) {
-		if (mtype == GSM48_MT_MM_LOC_UPD_REQUEST)
-			handle_lu_request(conn, msg);
-	} else if (pdisc == GSM48_PDISC_RR) {
-		if (mtype == GSM48_MT_RR_PAG_RESP)
-			handle_page_resp(conn, msg);
-	}
-
-	return 0;
-}
-
-static int send_welcome_ussd(struct gsm_subscriber_connection *conn)
-{
-	struct osmo_bsc_sccp_con *bsc_con;
-
-	bsc_con = conn->sccp_con;
-	if (!bsc_con) {
-		LOGP(DMSC, LOGL_DEBUG, "No SCCP connection associated.\n");
-		return 0;
-	}
-
-	if (!bsc_con->msc->ussd_welcome_txt) {
-		LOGP(DMSC, LOGL_DEBUG, "No USSD Welcome text defined.\n");
-		return 0;
-	}
-
-	return BSS_SEND_USSD;
-}
-
-int bsc_send_welcome_ussd(struct gsm_subscriber_connection *conn)
-{
-	bsc_send_ussd_notify(conn, 1, conn->sccp_con->msc->ussd_welcome_txt);
-	bsc_send_ussd_release_complete(conn);
-
-	return 0;
-}
-
-static int bsc_patch_mm_info(struct gsm_subscriber_connection *conn,
-		uint8_t *data, unsigned int length)
-{
-	struct tlv_parsed tp;
-	int parse_res;
-	struct gsm_bts *bts = conn->bts;
-	int tzunits;
-	uint8_t tzbsd = 0;
-	uint8_t dst = 0;
-
-	parse_res = tlv_parse(&tp, &gsm48_mm_att_tlvdef, data, length, 0, 0);
-	if (parse_res <= 0 && parse_res != -3)
-		/* FIXME: -3 means unknown IE error, so this accepts messages
-		 * with unknown IEs. But parsing has aborted with the unknown
-		 * IE and the message is broken or parsed incompletely. */
-		return 0;
-
-	/* Is TZ patching enabled? */
-	struct gsm_tz *tz = &bts->network->tz;
-	if (!tz->override)
-		return 0;
-
-	/* Convert tz.hr and tz.mn to units */
-	if (tz->hr < 0) {
-		tzunits = -tz->hr*4;
-		tzbsd |= 0x08;
-	} else
-		tzunits = tz->hr*4;
-
-	tzunits = tzunits + (tz->mn/15);
-
-	tzbsd |= (tzunits % 10)*0x10 + (tzunits / 10);
-
-	/* Convert DST value */
-	if (tz->dst >= 0 && tz->dst <= 2)
-		dst = tz->dst;
-
-	if (TLVP_PRESENT(&tp, GSM48_IE_UTC)) {
-		LOGP(DMSC, LOGL_DEBUG,
-			"Changing 'Local time zone' from 0x%02x to 0x%02x.\n",
-			TLVP_VAL(&tp, GSM48_IE_UTC)[6], tzbsd);
-		((uint8_t *)(TLVP_VAL(&tp, GSM48_IE_UTC)))[0] = tzbsd;
-	}
-	if (TLVP_PRESENT(&tp, GSM48_IE_NET_TIME_TZ)) {
-		LOGP(DMSC, LOGL_DEBUG,
-			"Changing 'Universal time and local time zone' TZ from "
-			"0x%02x to 0x%02x.\n",
-			TLVP_VAL(&tp, GSM48_IE_NET_TIME_TZ)[6], tzbsd);
-		((uint8_t *)(TLVP_VAL(&tp, GSM48_IE_NET_TIME_TZ)))[6] = tzbsd;
-	}
-#ifdef GSM48_IE_NET_DST
-	if (TLVP_PRESENT(&tp, GSM48_IE_NET_DST)) {
-		LOGP(DMSC, LOGL_DEBUG,
-			"Changing 'Network daylight saving time' from "
-			"0x%02x to 0x%02x.\n",
-			TLVP_VAL(&tp, GSM48_IE_NET_DST)[0], dst);
-		((uint8_t *)(TLVP_VAL(&tp, GSM48_IE_NET_DST)))[0] = dst;
-	}
-#endif
-
-	return 0;
-}
-
-static int has_core_identity(struct bsc_msc_data *msc)
-{
-	if (msc->core_mnc != -1)
-		return 1;
-	if (msc->core_mcc != -1)
-		return 1;
-	if (msc->core_lac != -1)
-		return 1;
-	if (msc->core_ci != -1)
-		return 1;
-	return 0;
-}
-
-/**
- * Messages coming back from the MSC.
- */
-int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
-{
-	struct bsc_msc_data *msc;
-	struct gsm_network *net;
-	struct gsm48_loc_area_id *lai;
-	struct gsm48_hdr *gh;
-	uint8_t pdisc;
-	uint8_t mtype;
-	int length = msgb_l3len(msg);
-
-	if (length < sizeof(*gh)) {
-		LOGP(DMSC, LOGL_ERROR, "GSM48 header does not fit.\n");
-		return -1;
-	}
-
-	gh = (struct gsm48_hdr *) msgb_l3(msg);
-	length -= (const char *)&gh->data[0] - (const char *)gh;
-
-	pdisc = gsm48_hdr_pdisc(gh);
-	if (pdisc != GSM48_PDISC_MM)
-		return 0;
-
-	mtype = gsm48_hdr_msg_type(gh);
-	net = conn->bts->network;
-	msc = conn->sccp_con->msc;
-
-	if (mtype == GSM48_MT_MM_LOC_UPD_ACCEPT) {
-		if (has_core_identity(msc)) {
-			if (msgb_l3len(msg) >= sizeof(*gh) + sizeof(*lai)) {
-				/* overwrite LAI in the message */
-				lai = (struct gsm48_loc_area_id *) &gh->data[0];
-				gsm48_generate_lai(lai, net->country_code,
-						   net->network_code,
-						   conn->bts->location_area_code);
-			}
-		}
-
-		if (conn->sccp_con->new_subscriber)
-			return send_welcome_ussd(conn);
-		return 0;
-	} else if (mtype == GSM48_MT_MM_INFO) {
-		bsc_patch_mm_info(conn, &gh->data[0], length);
-	}
-
-	return 0;
-}
diff --git a/src/osmo-bsc/osmo_bsc_grace.c b/src/osmo-bsc/osmo_bsc_grace.c
deleted file mode 100644
index 63afa20..0000000
--- a/src/osmo-bsc/osmo_bsc_grace.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * (C) 2010-2013 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2013 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/>.
- *
- */
-
-#include <openbsc/osmo_bsc_grace.h>
-#include <openbsc/osmo_bsc_rf.h>
-#include <openbsc/bsc_msc_data.h>
-#include <openbsc/gsm_04_80.h>
-#include <openbsc/bsc_subscriber.h>
-#include <openbsc/paging.h>
-#include <openbsc/signal.h>
-
-int bsc_grace_allow_new_connection(struct gsm_network *network, struct gsm_bts *bts)
-{
-	if (bts->excl_from_rf_lock)
-		return 1;
-	return network->bsc_data->rf_ctrl->policy == S_RF_ON;
-}
-
-
-static int normal_paging(struct bsc_subscr *subscr, int chan_needed,
-			 struct bsc_msc_data *msc)
-{
-	/* we can't page by lac.. we need to page everything */
-	if (msc->core_lac != -1) {
-		struct gsm_bts *bts;
-
-		llist_for_each_entry(bts, &msc->network->bts_list, list)
-			paging_request_bts(bts, subscr, chan_needed, NULL, msc);
-
-		return 0;
-	}
-
-	return paging_request(msc->network, subscr, chan_needed, NULL, msc);
-}
-
-static int locked_paging(struct bsc_subscr *subscr, int chan_needed,
-			 struct bsc_msc_data *msc)
-{
-	struct gsm_bts *bts = NULL;
-
-	/*
-	 * Check if there is any BTS that is on for the given lac. Start
-	 * with NULL and iterate through all bts.
-	 */
-	llist_for_each_entry(bts, &msc->network->bts_list, list) {
-		/*
-		 * continue if the BTS is not excluded from the lock
-		 */
-		if (!bts->excl_from_rf_lock)
-			continue;
-
-		/* in case of no lac patching is in place, check the BTS */
-		if (msc->core_lac == -1 && subscr->lac != bts->location_area_code)
-			continue;
-
-		/*
-		 * now page on this bts
-		 */
-		paging_request_bts(bts, subscr, chan_needed, NULL, msc);
-	};
-
-	/* All bts are either off or in the grace period */
-	return 0;
-}
-
-/**
- * Try to not page if everything the cell is not on.
- */
-int bsc_grace_paging_request(enum signal_rf rf_policy,
-			     struct bsc_subscr *subscr,
-			     int chan_needed,
-			     struct bsc_msc_data *msc)
-{
-	if (rf_policy == S_RF_ON)
-		return normal_paging(subscr, chan_needed, msc);
-	return locked_paging(subscr, chan_needed, msc);
-}
-
-static int handle_sub(struct gsm_lchan *lchan, const char *text)
-{
-	struct gsm_subscriber_connection *conn;
-
-	/* only send it to TCH */
-	if (lchan->type != GSM_LCHAN_TCH_H && lchan->type != GSM_LCHAN_TCH_F)
-		return -1;
-
-	/* only send on the primary channel */
-	conn = lchan->conn;
-	if (!conn)
-		return -1;
-
-	if (conn->lchan != lchan)
-		return -1;
-
-	/* only when active */
-	if (lchan->state != LCHAN_S_ACTIVE)
-		return -1;
-
-	bsc_send_ussd_notify(conn, 0, text);
-	bsc_send_ussd_release_complete(conn);
-
-	return 0;
-}
-
-/*
- * The place to handle the grace mode. Right now we will send
- * USSD messages to the subscriber, in the future we might start
- * a timer to have different modes for the grace period.
- */
-static int handle_grace(struct gsm_network *network)
-{
-	int ts_nr, lchan_nr;
-	struct gsm_bts *bts;
-	struct gsm_bts_trx *trx;
-
-	if (!network->bsc_data->mid_call_txt)
-		return 0;
-
-	llist_for_each_entry(bts, &network->bts_list, list) {
-		llist_for_each_entry(trx, &bts->trx_list, list) {
-			for (ts_nr = 0; ts_nr < TRX_NR_TS; ++ts_nr) {
-				struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
-				for (lchan_nr = 0; lchan_nr < TS_MAX_LCHAN; ++lchan_nr) {
-					handle_sub(&ts->lchan[lchan_nr],
-						   network->bsc_data->mid_call_txt);
-				}
-			}
-		}
-	}
-	return 0;
-}
-
-static int handle_rf_signal(unsigned int subsys, unsigned int signal,
-			    void *handler_data, void *signal_data)
-{
-	struct rf_signal_data *sig;
-
-	if (subsys != SS_RF)
-		return -1;
-
-	sig = signal_data;
-
-	if (signal == S_RF_GRACE)
-		handle_grace(sig->net);
-
-	return 0;
-}
-
-static __attribute__((constructor)) void on_dso_load_grace(void)
-{
-	osmo_signal_register_handler(SS_RF, handle_rf_signal, NULL);
-}
diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c
deleted file mode 100644
index cf188a9..0000000
--- a/src/osmo-bsc/osmo_bsc_main.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2011 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/>.
- *
- */
-
-#include <openbsc/bss.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/osmo_bsc.h>
-#include <openbsc/osmo_bsc_rf.h>
-#include <openbsc/bsc_msc_data.h>
-#include <openbsc/signal.h>
-#include <openbsc/vty.h>
-#include <openbsc/ipaccess.h>
-#include <openbsc/ctrl.h>
-#include <openbsc/osmo_bsc_sigtran.h>
-
-#include <osmocom/ctrl/control_cmd.h>
-#include <osmocom/ctrl/control_if.h>
-#include <osmocom/ctrl/ports.h>
-#include <osmocom/ctrl/control_vty.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/stats.h>
-#include <osmocom/gsm/protocol/gsm_12_21.h>
-
-#include <osmocom/abis/abis.h>
-
-#include <osmocom/sccp/sccp.h>
-
-#define _GNU_SOURCE
-#include <getopt.h>
-
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <unistd.h>
-
-
-#include "../../bscconfig.h"
-
-struct gsm_network *bsc_gsmnet = 0;
-static const char *config_file = "openbsc.cfg";
-static const char *rf_ctrl = NULL;
-extern const char *openbsc_copyright;
-static int daemonize = 0;
-static struct llist_head access_lists;
-
-struct llist_head *bsc_access_lists(void)
-{
-	return &access_lists;
-}
-
-static void print_usage()
-{
-	printf("Usage: osmo-bsc\n");
-}
-
-static void print_help()
-{
-	printf("  Some useful help...\n");
-	printf("  -h --help this text\n");
-	printf("  -D --daemonize Fork the process into a background daemon\n");
-	printf("  -d option --debug=DRLL:DCC:DMM:DRR:DRSL:DNM enable debugging\n");
-	printf("  -s --disable-color\n");
-	printf("  -T --timestamp. Print a timestamp in the debug output.\n");
-	printf("  -c --config-file filename The config file to use.\n");
-	printf("  -l --local=IP. The local address of the MGCP.\n");
-	printf("  -e --log-level number. Set a global loglevel.\n");
-	printf("  -r --rf-ctl NAME. A unix domain socket to listen for cmds.\n");
-	printf("  -t --testmode. A special mode to provoke failures at the MSC.\n");
-}
-
-static void handle_options(int argc, char **argv)
-{
-	while (1) {
-		int option_index = 0, c;
-		static struct option long_options[] = {
-			{"help", 0, 0, 'h'},
-			{"debug", 1, 0, 'd'},
-			{"daemonize", 0, 0, 'D'},
-			{"config-file", 1, 0, 'c'},
-			{"disable-color", 0, 0, 's'},
-			{"timestamp", 0, 0, 'T'},
-			{"local", 1, 0, 'l'},
-			{"log-level", 1, 0, 'e'},
-			{"rf-ctl", 1, 0, 'r'},
-			{"testmode", 0, 0, 't'},
-			{0, 0, 0, 0}
-		};
-
-		c = getopt_long(argc, argv, "hd:DsTc:e:r:t",
-				long_options, &option_index);
-		if (c == -1)
-			break;
-
-		switch (c) {
-		case 'h':
-			print_usage();
-			print_help();
-			exit(0);
-		case 's':
-			log_set_use_color(osmo_stderr_target, 0);
-			break;
-		case 'd':
-			log_parse_category_mask(osmo_stderr_target, optarg);
-			break;
-		case 'D':
-			daemonize = 1;
-			break;
-		case 'c':
-			config_file = optarg;
-			break;
-		case 'T':
-			log_set_print_timestamp(osmo_stderr_target, 1);
-			break;
-		case 'e':
-			log_set_log_level(osmo_stderr_target, atoi(optarg));
-			break;
-		case 'r':
-			rf_ctrl = optarg;
-			break;
-		default:
-			/* ignore */
-			break;
-		}
-	}
-}
-
-extern int bsc_vty_go_parent(struct vty *vty);
-
-static struct vty_app_info vty_info = {
-	.name 		= "OsmoBSC",
-	.version	= PACKAGE_VERSION,
-	.go_parent_cb	= bsc_vty_go_parent,
-	.is_config_node	= bsc_vty_is_config_node,
-};
-
-extern int bsc_shutdown_net(struct gsm_network *net);
-static void signal_handler(int signal)
-{
-	struct bsc_msc_data *msc;
-
-	fprintf(stdout, "signal %u received\n", signal);
-
-	switch (signal) {
-	case SIGINT:
-	case SIGTERM:
-		bsc_shutdown_net(bsc_gsmnet);
-		osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL);
-		sleep(3);
-		exit(0);
-		break;
-	case SIGABRT:
-		/* in case of abort, we want to obtain a talloc report
-		 * and then return to the caller, who will abort the process */
-	case SIGUSR1:
-		talloc_report(tall_vty_ctx, stderr);
-		talloc_report_full(tall_bsc_ctx, stderr);
-		break;
-	case SIGUSR2:
-		if (!bsc_gsmnet->bsc_data)
-			return;
-		llist_for_each_entry(msc, &bsc_gsmnet->bsc_data->mscs, entry)
-			bsc_msc_lost(msc->msc_con);
-		break;
-	default:
-		break;
-	}
-}
-
-int main(int argc, char **argv)
-{
-	struct bsc_msc_data *msc;
-	struct osmo_bsc_data *data;
-	int rc;
-
-	tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
-	msgb_talloc_ctx_init(tall_bsc_ctx, 0);
-
-	/* Allocate global gsm_network struct */
-	rc = bsc_network_alloc(NULL);
-	if (rc) {
-		fprintf(stderr, "Allocation failed. exiting.\n");
-		exit(1);
-	}
-
-	osmo_init_logging(&log_info);
-	osmo_stats_init(tall_bsc_ctx);
-
-	bts_init();
-	libosmo_abis_init(tall_bsc_ctx);
-
-	/* enable filters */
-
-	/* This needs to precede handle_options() */
-	vty_info.copyright = openbsc_copyright;
-	vty_init(&vty_info);
-	bsc_vty_init(bsc_gsmnet);
-	bsc_msg_lst_vty_init(tall_bsc_ctx, &access_lists, BSC_NODE);
-	ctrl_vty_init(tall_bsc_ctx);
-
-	/* Initalize SS7 */
-	osmo_ss7_init();
-	osmo_ss7_vty_init_asp(tall_bsc_ctx);
-
-	INIT_LLIST_HEAD(&access_lists);
-
-	/* parse options */
-	handle_options(argc, argv);
-
-	/* seed the PRNG */
-	srand(time(NULL));
-
-	/* initialize SCCP */
-	sccp_set_log_area(DSCCP);
-
-	/* Read the config */
-	rc = bsc_network_configure(config_file);
-	if (rc < 0) {
-		fprintf(stderr, "Bootstrapping the network failed. exiting.\n");
-		exit(1);
-	}
-	bsc_api_init(bsc_gsmnet, osmo_bsc_api());
-
-	/* start control interface after reading config for
-	 * ctrl_vty_get_bind_addr() */
-	bsc_gsmnet->ctrl = bsc_controlif_setup(bsc_gsmnet,
-					       ctrl_vty_get_bind_addr(),
-					       OSMO_CTRL_PORT_NITB_BSC);
-	if (!bsc_gsmnet->ctrl) {
-		fprintf(stderr, "Failed to init the control interface. Exiting.\n");
-		exit(1);
-	}
-
-	rc = bsc_ctrl_cmds_install(bsc_gsmnet);
-	if (rc < 0) {
-		fprintf(stderr, "Failed to install control commands. Exiting.\n");
-		exit(1);
-	}
-
-	data = bsc_gsmnet->bsc_data;
-	if (rf_ctrl)
-		osmo_talloc_replace_string(data, &data->rf_ctrl_name, rf_ctrl);
-
-	data->rf_ctrl = osmo_bsc_rf_create(data->rf_ctrl_name, bsc_gsmnet);
-	if (!data->rf_ctrl) {
-		fprintf(stderr, "Failed to create the RF service.\n");
-		exit(1);
-	}
-
-	llist_for_each_entry(msc, &bsc_gsmnet->bsc_data->mscs, entry) {
-		if (osmo_bsc_msc_init(msc) != 0) {
-			LOGP(DNAT, LOGL_ERROR, "Failed to start up. Exiting.\n");
-			exit(1);
-		}
-	}
-
-	if (osmo_bsc_sigtran_init(&bsc_gsmnet->bsc_data->mscs) != 0) {
-		LOGP(DNM, LOGL_ERROR, "Failed to initalize sigtran backhaul.\n");
-		exit(1);
-	}
-
-	if (osmo_bsc_audio_init(bsc_gsmnet) != 0) {
-		LOGP(DMSC, LOGL_ERROR, "Failed to register audio support.\n");
-		exit(1);
-	}
-
-	signal(SIGINT, &signal_handler);
-	signal(SIGTERM, &signal_handler);
-	signal(SIGABRT, &signal_handler);
-	signal(SIGUSR1, &signal_handler);
-	signal(SIGUSR2, &signal_handler);
-	osmo_init_ignore_signals();
-
-	if (daemonize) {
-		rc = osmo_daemonize();
-		if (rc < 0) {
-			perror("Error during daemonize");
-			exit(1);
-		}
-	}
-
-	while (1) {
-		osmo_select_main(0);
-	}
-
-	return 0;
-}
diff --git a/src/osmo-bsc/osmo_bsc_msc.c b/src/osmo-bsc/osmo_bsc_msc.c
deleted file mode 100644
index 351fd2c..0000000
--- a/src/osmo-bsc/osmo_bsc_msc.c
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * Handle the connection to the MSC. This include ping/timeout/reconnect
- * (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009-2015 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-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/>.
- *
- */
-
-#include <openbsc/bsc_nat.h>
-#include <osmocom/ctrl/control_cmd.h>
-#include <osmocom/ctrl/control_if.h>
-#include <osmocom/crypt/auth.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/ipaccess.h>
-#include <openbsc/bsc_msc_data.h>
-#include <openbsc/signal.h>
-
-#include <osmocom/core/talloc.h>
-
-#include <osmocom/gsm/gsm0808.h>
-
-#include <osmocom/sccp/sccp.h>
-
-#include <osmocom/abis/ipa.h>
-
-#include <sys/socket.h>
-#include <netinet/tcp.h>
-#include <unistd.h>
-
-#if 0
-static void initialize_if_needed(struct bsc_msc_connection *conn);
-static void send_lacs(struct gsm_network *net, struct bsc_msc_connection *conn);
-static void send_id_get_response(struct bsc_msc_data *data, int fd, struct msgb *inp);
-static void send_ping(struct bsc_msc_data *data);
-static void schedule_ping_pong(struct bsc_msc_data *data);
-
-/*
- * MGCP forwarding code
- */
-
-#endif
-static int mgcp_do_read(struct osmo_fd *fd)
-{
-	struct bsc_msc_data *data = (struct bsc_msc_data *) fd->data;
-	struct msgb *mgcp;
-	int ret;
-
-	mgcp = msgb_alloc_headroom(4096, 128, "mgcp_from_gw");
-	if (!mgcp) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to allocate MGCP message.\n");
-		return -1;
-	}
-
-	ret = read(fd->fd, mgcp->data, 4096 - 128);
-	if (ret <= 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to read: %d/%s\n", errno, strerror(errno));
-		msgb_free(mgcp);
-		return -1;
-	} else if (ret > 4096 - 128) {
-		LOGP(DMGCP, LOGL_ERROR, "Too much data: %d\n", ret);
-		msgb_free(mgcp);
-		return -1;
-        }
-
-	mgcp->l2h = msgb_put(mgcp, ret);
-	msc_queue_write(data->msc_con, mgcp, IPAC_PROTO_MGCP_OLD);
-	return 0;
-}
-
-static int mgcp_do_write(struct osmo_fd *fd, struct msgb *msg)
-{
-	int ret;
-
-	LOGP(DMGCP, LOGL_DEBUG, "Sending msg to MGCP GW size: %u\n", msg->len);
-
-	ret = write(fd->fd, msg->data, msg->len);
-	if (ret != msg->len)
-		LOGP(DMGCP, LOGL_ERROR, "Failed to forward message to MGCP GW (%s).\n", strerror(errno));
-
-	return ret;
-}
-
-#if 0
-static void mgcp_forward(struct bsc_msc_data *data, struct msgb *msg)
-{
-	struct msgb *mgcp;
-
-	if (msgb_l2len(msg) > 4096) {
-		LOGP(DMGCP, LOGL_ERROR, "Can not forward too big message.\n");
-		return;
-	}
-
-	mgcp = msgb_alloc(4096, "mgcp_to_gw");
-	if (!mgcp) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to send message.\n");
-		return;
-	}
-
-	msgb_put(mgcp, msgb_l2len(msg));
-	memcpy(mgcp->data, msg->l2h, mgcp->len);
-	if (osmo_wqueue_enqueue(&data->mgcp_agent, mgcp) != 0) {
-		LOGP(DMGCP, LOGL_FATAL, "Could not queue message to MGCP GW.\n");
-		msgb_free(mgcp);
-	}
-}
-#endif
-
-static int mgcp_create_port(struct bsc_msc_data *data)
-{
-	int on;
-	struct sockaddr_in addr;
-
-	data->mgcp_agent.bfd.fd = socket(AF_INET, SOCK_DGRAM, 0);
-	if (data->mgcp_agent.bfd.fd < 0) {
-		LOGP(DMGCP, LOGL_FATAL, "Failed to create UDP socket errno: %d\n", errno);
-		return -1;
-	}
-
-	on = 1;
-	setsockopt(data->mgcp_agent.bfd.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-
-	/* try to bind the socket */
-	memset(&addr, 0, sizeof(addr));
-	addr.sin_family = AF_INET;
-	addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-	addr.sin_port = 0;
-
-	if (bind(data->mgcp_agent.bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		LOGP(DMGCP, LOGL_FATAL, "Failed to bind to any port.\n");
-		close(data->mgcp_agent.bfd.fd);
-		data->mgcp_agent.bfd.fd = -1;
-		return -1;
-	}
-
-	/* connect to the remote */
-	addr.sin_port = htons(2427);
-	if (connect(data->mgcp_agent.bfd.fd, (struct sockaddr *) & addr, sizeof(addr)) < 0) {
-		LOGP(DMGCP, LOGL_FATAL, "Failed to connect to local MGCP GW. %s\n", strerror(errno));
-		close(data->mgcp_agent.bfd.fd);
-		data->mgcp_agent.bfd.fd = -1;
-		return -1;
-	}
-
-	osmo_wqueue_init(&data->mgcp_agent, 10);
-	data->mgcp_agent.bfd.when = BSC_FD_READ;
-	data->mgcp_agent.bfd.data = data;
-	data->mgcp_agent.read_cb = mgcp_do_read;
-	data->mgcp_agent.write_cb = mgcp_do_write;
-
-	if (osmo_fd_register(&data->mgcp_agent.bfd) != 0) {
-		LOGP(DMGCP, LOGL_FATAL, "Failed to register BFD\n");
-		close(data->mgcp_agent.bfd.fd);
-		data->mgcp_agent.bfd.fd = -1;
-		return -1;
-	}
-
-	return 0;
-}
-
-
-/*
- * Send data to the network
- */
-int msc_queue_write(struct bsc_msc_connection *conn, struct msgb *msg, int proto)
-{
-	ipa_prepend_header(msg, proto);
-	if (osmo_wqueue_enqueue(&conn->write_queue, msg) != 0) {
-		LOGP(DMSC, LOGL_FATAL, "Failed to queue IPA/%d\n", proto);
-		msgb_free(msg);
-		return -1;
-	}
-
-	return 0;
-}
-
-#if 0
-int msc_queue_write_with_ping(struct bsc_msc_connection *conn,
-			struct msgb *msg, int proto)
-{
-	struct bsc_msc_data *data;
-	uint8_t val;
-
-	/* prepend the header */
-	ipa_prepend_header(msg, proto);
-	if (osmo_wqueue_enqueue(&conn->write_queue, msg) != 0) {
-		LOGP(DMSC, LOGL_FATAL, "Failed to queue IPA/%d\n", proto);
-		msgb_free(msg);
-		return -1;
-	}
-
-	/* add the ping as the other message */
-	val = IPAC_MSGT_PING;
-	msgb_l16tv_put(msg, 1, IPAC_PROTO_IPACCESS, &val);
-
-	data = (struct bsc_msc_data *) conn->write_queue.bfd.data;
-	schedule_ping_pong(data);
-	return 0;
-}
-
-static int msc_alink_do_write(struct osmo_fd *fd, struct msgb *msg)
-{
-	int ret;
-
-	LOGP(DMSC, LOGL_DEBUG, "Sending SCCP to MSC: %u\n", msgb_l2len(msg));
-	LOGP(DLMI, LOGL_DEBUG, "MSC TX %s\n", osmo_hexdump(msg->data, msg->len));
-
-	ret = write(fd->fd, msg->data, msg->len);
-	if (ret < msg->len)
-		perror("MSC: Failed to send SCCP");
-
-	return ret;
-}
-
-static void handle_ctrl(struct bsc_msc_data *msc, struct msgb *msg)
-{
-	int ret;
-	struct ctrl_cmd *cmd;
-
-	cmd = ctrl_cmd_parse(msc->msc_con, msg);
-	if (!cmd) {
-		LOGP(DMSC, LOGL_ERROR, "Failed to parse control message.\n");
-		cmd = talloc_zero(msc->msc_con, struct ctrl_cmd);
-		if (!cmd) {
-			LOGP(DMSC, LOGL_ERROR, "OOM!\n");
-			return;
-		}
-		cmd->type = CTRL_TYPE_ERROR;
-		cmd->id = "err";
-		cmd->reply = "Failed to parse control message.";
-
-		ctrl_cmd_send(&msc->msc_con->write_queue, cmd);
-		talloc_free(cmd);
-
-		return;
-	}
-
-	ret = ctrl_cmd_handle(msc->network->ctrl, cmd, msc->network);
-	if (ret != CTRL_CMD_HANDLED)
-		ctrl_cmd_send(&msc->msc_con->write_queue, cmd);
-	talloc_free(cmd);
-}
-
-static void osmo_ext_handle(struct bsc_msc_data *msc, struct msgb *msg)
-{
-	struct ipaccess_head *hh;
-	struct ipaccess_head_ext *hh_ext;
-
-	hh = (struct ipaccess_head *) msg->data;
-	hh_ext = (struct ipaccess_head_ext *) hh->data;
-	if (msg->len < sizeof(*hh) + sizeof(*hh_ext)) {
-		LOGP(DMSC, LOGL_ERROR, "Packet too short for extended header.\n");
-		return;
-	}
-
-	msg->l2h = hh_ext->data;
-	if (hh_ext->proto == IPAC_PROTO_EXT_MGCP)
-		mgcp_forward(msc, msg);
-	else if (hh_ext->proto == IPAC_PROTO_EXT_LAC)
-		send_lacs(msc->network, msc->msc_con);
-	else if (hh_ext->proto == IPAC_PROTO_EXT_CTRL)
-		handle_ctrl(msc, msg);
-}
-
-static int ipaccess_a_fd_cb(struct osmo_fd *bfd)
-{
-	struct msgb *msg = NULL;
-	struct ipaccess_head *hh;
-	struct bsc_msc_data *data = (struct bsc_msc_data *) bfd->data;
-	int ret;
-
-	ret = ipa_msg_recv_buffered(bfd->fd, &msg, &data->msc_con->pending_msg);
-	if (ret <= 0) {
-		if (ret == -EAGAIN)
-			return 0;
-		if (ret == 0) {
-			LOGP(DMSC, LOGL_ERROR, "The connection to the MSC was lost.\n");
-			bsc_msc_lost(data->msc_con);
-			return -1;
-		}
-
-		LOGP(DMSC, LOGL_ERROR, "Failed to parse ip access message: %d\n", ret);
-		return -1;
-	}
-
-	LOGP(DLMI, LOGL_DEBUG, "From MSC: %s proto: %d\n", osmo_hexdump(msg->data, msg->len), msg->l2h[0]);
-
-	/* handle base message handling */
-	hh = (struct ipaccess_head *) msg->data;
-
-	/* initialize the networking. This includes sending a GSM08.08 message */
-	msg->cb[0] = (unsigned long) data;
-	if (hh->proto == IPAC_PROTO_IPACCESS) {
-		ipa_ccm_rcvmsg_base(msg, bfd);
-		if (msg->l2h[0] == IPAC_MSGT_ID_ACK)
-			initialize_if_needed(data->msc_con);
-		else if (msg->l2h[0] == IPAC_MSGT_ID_GET) {
-			send_id_get_response(data, bfd->fd, msg);
-		} else if (msg->l2h[0] == IPAC_MSGT_PONG) {
-			osmo_timer_del(&data->pong_timer);
-		}
-	} else if (hh->proto == IPAC_PROTO_SCCP) {
-		sccp_system_incoming_ctx(msg, data->msc_con);
-	} else if (hh->proto == IPAC_PROTO_MGCP_OLD) {
-		mgcp_forward(data, msg);
-	} else if (hh->proto == IPAC_PROTO_OSMO) {
-		osmo_ext_handle(data, msg);
-	}
-
-	msgb_free(msg);
-	return 0;
-}
-
-static void send_ping(struct bsc_msc_data *data)
-{
-	struct msgb *msg;
-
-	msg = msgb_alloc_headroom(4096, 128, "ping");
-	if (!msg) {
-		LOGP(DMSC, LOGL_ERROR, "Failed to create PING.\n");
-		return;
-	}
-
-	msg->l2h = msgb_put(msg, 1);
-	msg->l2h[0] = IPAC_MSGT_PING;
-
-	msc_queue_write(data->msc_con, msg, IPAC_PROTO_IPACCESS);
-}
-
-static void schedule_ping_pong(struct bsc_msc_data *data)
-{
-	/* send another ping in 20 seconds */
-	osmo_timer_schedule(&data->ping_timer, data->ping_timeout, 0);
-
-	/* also start a pong timer */
-	osmo_timer_schedule(&data->pong_timer, data->pong_timeout, 0);
-}
-
-static void msc_ping_timeout_cb(void *_data)
-{
-	struct bsc_msc_data *data = (struct bsc_msc_data *) _data;
-	if (data->ping_timeout <= 0)
-		return;
-
-	send_ping(data);
-	schedule_ping_pong(data);
-}
-
-static void msc_pong_timeout_cb(void *_data)
-{
-//	struct bsc_msc_data *data = (struct bsc_msc_data *) _data;
-
-	LOGP(DMSC, LOGL_ERROR, "MSC didn't answer PING. Closing connection.\n");
-//	bsc_msc_lost(data->msc_con);
-}
-
-static void msc_connection_connected(struct bsc_msc_connection *con)
-{
-	struct msc_signal_data sig;
-	struct bsc_msc_data *data;
-	int ret, on;
-	on = 1;
-//	ret = setsockopt(con->write_queue.bfd.fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
-//	if (ret != 0)
-//                LOGP(DMSC, LOGL_ERROR, "Failed to set TCP_NODELAY: %s\n", strerror(errno));
-
-//	data = (struct bsc_msc_data *) con->write_queue.bfd.data;
-//	msc_ping_timeout_cb(data);
-
-	sig.data = data;
-	osmo_signal_dispatch(SS_MSC, S_MSC_CONNECTED, &sig);
-}
-
-/*
- * The connection to the MSC was lost and we will need to free all
- * resources and then attempt to reconnect.
- */
-static void msc_connection_was_lost(struct bsc_msc_connection *msc)
-{
-//	struct msc_signal_data sig;
-//	struct bsc_msc_data *data;
-
-	LOGP(DMSC, LOGL_ERROR, "Lost MSC connection. Freing stuff.\n");
-
-//	data = (struct bsc_msc_data *) msc->write_queue.bfd.data;
-//	osmo_timer_del(&data->ping_timer);
-//	osmo_timer_del(&data->pong_timer);
-//
-//	sig.data = data;
-//	osmo_signal_dispatch(SS_MSC, S_MSC_LOST, &sig);
-
-	msc->is_authenticated = 0;
-//	bsc_msc_schedule_connect(msc);
-}
-
-static void send_lacs(struct gsm_network *net, struct bsc_msc_connection *conn)
-{
-	struct ipac_ext_lac_cmd *lac;
-	struct gsm_bts *bts;
-	struct msgb *msg;
-	int lacs = 0;
-
-	if (llist_empty(&net->bts_list)) {
-		LOGP(DMSC, LOGL_ERROR, "No BTSs configured. Not sending LACs.\n");
-		return;
-	}
-
-	msg = msgb_alloc_headroom(4096, 128, "LAC Command");
-	if (!msg) {
-		LOGP(DMSC, LOGL_ERROR, "Failed to create the LAC command.\n");
-		return;
-	}
-
-	lac = (struct ipac_ext_lac_cmd *) msgb_put(msg, sizeof(*lac));
-	lac->add_remove = 1;
-
-	llist_for_each_entry(bts, &net->bts_list, list) {
-		if (lacs++ == 0)
-			lac->lac = htons(bts->location_area_code);
-		else
-			msgb_put_u16(msg, htons(bts->location_area_code));
-	}
-
-	lac->nr_extra_lacs = lacs - 1;
-	ipa_prepend_header_ext(msg, IPAC_PROTO_EXT_LAC);
-	msc_queue_write(conn, msg, IPAC_PROTO_OSMO);
-}
-
-static void initialize_if_needed(struct bsc_msc_connection *conn)
-{
-	struct msgb *msg;
-
-	if (!conn->is_authenticated) {
-		/* send a gsm 08.08 reset message from here */
-		msg = gsm0808_create_reset();
-		if (!msg) {
-			LOGP(DMSC, LOGL_ERROR, "Failed to create the reset message.\n");
-			return;
-		}
-
-		sccp_write(msg, &sccp_ssn_bssap, &sccp_ssn_bssap, 0, conn);
-		msgb_free(msg);
-		conn->is_authenticated = 1;
-	}
-}
-
-static int answer_challenge(struct bsc_msc_data *data, struct msgb *inp, struct osmo_auth_vector *vec)
-{
-	int ret;
-	struct tlv_parsed tvp;
-	const uint8_t *mrand;
-	uint8_t mrand_len;
-	struct osmo_sub_auth_data auth = {
-		.type		= OSMO_AUTH_TYPE_GSM,
-		.algo		= OSMO_AUTH_ALG_MILENAGE,
-	};
-
-	ret = ipa_ccm_idtag_parse_off(&tvp,
-				inp->l2h + 1,
-				msgb_l2len(inp) - 1, 1);
-	if (ret < 0) {
-		LOGP(DMSC, LOGL_ERROR, "ignoring IPA response "
-			"message with malformed TLVs: %s\n", osmo_hexdump(inp->l2h + 1,
-			msgb_l2len(inp) - 1));
-		return 0;
-	}
-
-	mrand = TLVP_VAL(&tvp, 0x23);
-	mrand_len = TLVP_LEN(&tvp, 0x23);
-	if (mrand_len != 16) {
-		LOGP(DMSC, LOGL_ERROR,
-			"RAND is not 16 bytes. Was %d\n",
-			mrand_len);
-		return 0;
-	}
-
-	/* copy the key */
-	memcpy(auth.u.umts.opc, data->bsc_key, 16);
-	memcpy(auth.u.umts.k, data->bsc_key, 16);
-	memset(auth.u.umts.amf, 0, 2);
-	auth.u.umts.sqn = 0;
-
-	/* generate the result */
-	memset(vec, 0, sizeof(*vec));
-	osmo_auth_gen_vec(vec, &auth, mrand);
-	return 1;
-}
-
-
-static void send_id_get_response(struct bsc_msc_data *data, int fd, struct msgb *inp)
-{
-	struct msc_signal_data sig;
-	struct msgb *msg;
-	struct osmo_auth_vector vec;
-	int valid = 0;
-
-	if (data->bsc_key_present)
-		valid = answer_challenge(data, inp, &vec);
-
-	msg = bsc_msc_id_get_resp(valid, data->bsc_token,
-			vec.res, valid ? vec.res_len : 0);
-	if (!msg)
-		return;
-	msc_queue_write(data->msc_con, msg, IPAC_PROTO_IPACCESS);
-
-	sig.data = data;
-	osmo_signal_dispatch(SS_MSC, S_MSC_AUTHENTICATED, &sig);
-}
-
-#endif 
-
-int osmo_bsc_msc_init(struct bsc_msc_data *data)
-{
-	if (mgcp_create_port(data) != 0)
-		return -1;
-
-	data->msc_con = bsc_msc_create(data, &data->dests);
-	if (!data->msc_con) {
-		LOGP(DMSC, LOGL_ERROR, "Creating the MSC network connection failed.\n");
-		return -1;
-	}
-
-//	osmo_timer_setup(&data->ping_timer, msc_ping_timeout_cb, data);
-//	osmo_timer_setup(&data->pong_timer, msc_pong_timeout_cb, data);
-
-	data->msc_con->write_queue.bfd.data = data;
-//	data->msc_con->connection_loss = msc_connection_was_lost;
-//	data->msc_con->connected = msc_connection_connected;
-//	data->msc_con->write_queue.read_cb = ipaccess_a_fd_cb;
-//	data->msc_con->write_queue.write_cb = msc_alink_do_write;
-//	bsc_msc_connect(data->msc_con);
-
-	data->msc_con->is_connected = 1;
-	data->msc_con->is_authenticated = 1;
-
-
-	return 0;
-}
-
-
-struct bsc_msc_data *osmo_msc_data_find(struct gsm_network *net, int nr)
-{
-	struct bsc_msc_data *msc_data;
-
-	llist_for_each_entry(msc_data, &net->bsc_data->mscs, entry)
-		if (msc_data->nr == nr)
-			return msc_data;
-	return NULL;
-}
-
-struct bsc_msc_data *osmo_msc_data_alloc(struct gsm_network *net, int nr)
-{
-	struct bsc_msc_data *msc_data;
-
-	/* check if there is already one */
-	msc_data = osmo_msc_data_find(net, nr);
-	if (msc_data)
-		return msc_data;
-
-	msc_data = talloc_zero(net, struct bsc_msc_data);
-	if (!msc_data)
-		return NULL;
-
-	llist_add_tail(&msc_data->entry, &net->bsc_data->mscs);
-
-	/* Init back pointer */
-	msc_data->network = net;
-
-	INIT_LLIST_HEAD(&msc_data->dests);
-	msc_data->ping_timeout = 20;
-	msc_data->pong_timeout = 5;
-	msc_data->core_mnc = -1;
-	msc_data->core_mcc = -1;
-	msc_data->core_ci = -1;
-	msc_data->core_lac = -1;
-	msc_data->rtp_base = 4000;
-
-	msc_data->nr = nr;
-	msc_data->allow_emerg = 1;
-
-	/* Defaults for the audio setup */
-	msc_data->amr_conf.m5_90 = 1;
-
-	return msc_data;
-}
-
diff --git a/src/osmo-bsc/osmo_bsc_reset.c b/src/osmo-bsc/osmo_bsc_reset.c
deleted file mode 100644
index 0baf080..0000000
--- a/src/osmo-bsc/osmo_bsc_reset.c
+++ /dev/null
@@ -1,190 +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/>.
- *
- */
-
-#include <osmocom/core/logging.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/timer.h>
-#include <osmocom/core/fsm.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <openbsc/debug.h>
-#include <openbsc/bsc_msc_data.h>
-#include <openbsc/osmo_bsc_sigtran.h>
-
-#define RESET_RESEND_INTERVAL 2	/* sec */
-#define RESET_RESEND_TIMER_NO 1234	/* FIXME: dig out the real timer number */
-#define BAD_CONNECTION_THRESOLD 3	/* connection failures */
-
-enum fsm_states {
-	ST_DISC,		/* Disconnected from MSC */
-	ST_CONN,		/* We have a confirmed connection to the MSC */
-};
-
-static const struct value_string fsm_state_names[] = {
-	{ST_DISC, "ST_DISC (disconnected)"},
-	{ST_CONN, "ST_CONN (connected)"},
-	{0, NULL},
-};
-
-enum fsm_evt {
-	EV_RESET_ACK,		/* got reset acknowlegement from the MSC */
-	EV_N_DISCONNECT,	/* lost a connection */
-	EV_N_CONNECT,		/* made a successful connection */
-};
-
-static const struct value_string fsm_evt_names[] = {
-	{EV_RESET_ACK, "EV_RESET_ACK"},
-	{EV_N_DISCONNECT, "EV_N_DISCONNECT"},
-	{EV_N_CONNECT, "EV_N_CONNECT"},
-	{0, NULL},
-};
-
-/* Disconnected state */
-static void fsm_disc_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct bsc_msc_data *msc = (struct bsc_msc_data *)data;
-
-	LOGP(DMSC, LOGL_NOTICE, "fsm-state (msc-reset): %s, fsm-event: %s, MSC No.: %i\n",
-	     get_value_string(fsm_state_names, ST_DISC), get_value_string(fsm_evt_names, event), msc->nr);
-	msc->msc_con->msc_conn_loss_count = 0;
-	osmo_fsm_inst_state_chg(fi, ST_CONN, 0, 0);
-}
-
-/* Connected state */
-static void fsm_conn_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
-	struct bsc_msc_data *msc = (struct bsc_msc_data *)data;
-
-	LOGP(DMSC, LOGL_NOTICE, "fsm-state (msc-reset): %s, fsm-event: %s, MSC No.: %i\n",
-	     get_value_string(fsm_state_names, ST_CONN), get_value_string(fsm_evt_names, event), msc->nr);
-
-	OSMO_ASSERT(msc);
-
-	switch (event) {
-	case EV_N_DISCONNECT:
-		if (msc->msc_con->msc_conn_loss_count >= BAD_CONNECTION_THRESOLD) {
-			LOGP(DMSC, LOGL_NOTICE, "SIGTRAN connection to MSC No.: %i down, reconnecting...\n", msc->nr);
-			osmo_fsm_inst_state_chg(fi, ST_DISC, RESET_RESEND_INTERVAL, RESET_RESEND_TIMER_NO);
-		} else
-			msc->msc_con->msc_conn_loss_count++;
-		break;
-	case EV_N_CONNECT:
-		msc->msc_con->msc_conn_loss_count = 0;
-		break;
-	}
-}
-
-/* Timer callback to retransmit the reset signal */
-static int fsm_reset_ack_timeout_cb(struct osmo_fsm_inst *fi)
-{
-	struct bsc_msc_data *msc = (struct bsc_msc_data *)fi->priv;
-
-	LOGP(DMSC, LOGL_NOTICE, "reset-ack timeout (T%i) in state %s, MSC No.: %i, resending...\n", fi->T,
-	     get_value_string(fsm_state_names, fi->state), msc->nr);
-
-	osmo_bsc_sigtran_reset(msc);
-	osmo_bsc_sigtran_tx_reset(msc);
-
-	osmo_fsm_inst_state_chg(fi, ST_DISC, RESET_RESEND_INTERVAL, RESET_RESEND_TIMER_NO);
-	return 0;
-}
-
-static struct osmo_fsm_state fsm_states[] = {
-	[ST_DISC] = {
-		     .in_event_mask = (1 << EV_RESET_ACK),
-		     .out_state_mask = (1 << ST_DISC) | (1 << ST_CONN),
-		     .name = "DISC",
-		     .action = fsm_disc_cb,
-		     },
-	[ST_CONN] = {
-		     .in_event_mask = (1 << EV_N_DISCONNECT) | (1 << EV_N_CONNECT),
-		     .out_state_mask = (1 << ST_DISC) | (1 << ST_CONN),
-		     .name = "CONN",
-		     .action = fsm_conn_cb,
-		     },
-};
-
-/* State machine definition */
-static struct osmo_fsm fsm = {
-	.name = "FSM RESET",
-	.states = fsm_states,
-	.num_states = ARRAY_SIZE(fsm_states),
-	.log_subsys = DMSC,
-	.timer_cb = fsm_reset_ack_timeout_cb,
-};
-
-/* Create and start state machine which handles the reset/reset-ack procedure */
-void start_reset_fsm(struct bsc_msc_data *msc)
-{
-	OSMO_ASSERT(msc);
-	OSMO_ASSERT(msc->msc_con);
-
-	osmo_fsm_register(&fsm);
-	msc->msc_con->fsm_reset = osmo_fsm_inst_alloc(&fsm, NULL, NULL, LOGL_DEBUG, "FSM RESET INST");
-	OSMO_ASSERT(msc->msc_con->fsm_reset);
-
-	msc->msc_con->fsm_reset->priv = msc;
-
-	/* kick off reset-ack sending mechanism */
-	osmo_fsm_inst_state_chg(msc->msc_con->fsm_reset, ST_DISC, RESET_RESEND_INTERVAL, RESET_RESEND_TIMER_NO);
-}
-
-/* Confirm that we sucessfully received a reset acknowlege message */
-void reset_ack_confirm(struct bsc_msc_data *msc)
-{
-	OSMO_ASSERT(msc);
-	OSMO_ASSERT(msc->msc_con);
-	OSMO_ASSERT(msc->msc_con->fsm_reset);
-
-	osmo_fsm_inst_dispatch(msc->msc_con->fsm_reset, EV_RESET_ACK, msc);
-}
-
-/* Report a failed connection */
-void report_conn_fail(struct bsc_msc_data *msc)
-{
-	OSMO_ASSERT(msc);
-	OSMO_ASSERT(msc->msc_con);
-	OSMO_ASSERT(msc->msc_con->fsm_reset);
-
-	osmo_fsm_inst_dispatch(msc->msc_con->fsm_reset, EV_N_DISCONNECT, msc);
-}
-
-/* Report a successful connection */
-void report_conn_success(struct bsc_msc_data *msc)
-{
-	OSMO_ASSERT(msc);
-	OSMO_ASSERT(msc->msc_con);
-	OSMO_ASSERT(msc->msc_con->fsm_reset);
-
-	osmo_fsm_inst_dispatch(msc->msc_con->fsm_reset, EV_N_CONNECT, msc);
-}
-
-/* Check if we have a connection to a specified msc */
-bool sccp_conn_ready(struct bsc_msc_data *msc)
-{
-	OSMO_ASSERT(msc);
-	OSMO_ASSERT(msc->msc_con);
-	OSMO_ASSERT(msc->msc_con->fsm_reset);
-	if (msc->msc_con->fsm_reset->state == ST_CONN)
-		return true;
-
-	return false;
-}
diff --git a/src/osmo-bsc/osmo_bsc_sigtran.c b/src/osmo-bsc/osmo_bsc_sigtran.c
deleted file mode 100644
index 0f6ca33..0000000
--- a/src/osmo-bsc/osmo_bsc_sigtran.c
+++ /dev/null
@@ -1,561 +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/>.
- *
- */
-
-#include <osmocom/core/utils.h>
-#include <osmocom/core/logging.h>
-#include <osmocom/sigtran/osmo_ss7.h>
-#include <osmocom/sigtran/sccp_sap.h>
-#include <osmocom/sccp/sccp_types.h>
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/gsm/gsm0808.h>
-#include <osmocom/core/msgb.h>
-#include <openbsc/bsc_msc_data.h>
-#include <openbsc/debug.h>
-#include <openbsc/osmo_bsc.h>
-#include <openbsc/osmo_bsc_grace.h>
-#include <openbsc/osmo_bsc_sigtran.h>
-#include <openbsc/a_reset.h>
-#include <openbsc/gsm_04_80.h>
-
-/* A pointer to a list with all involved MSCs
- * (a copy of the pointer location submitted with osmo_bsc_sigtran_init() */
-static struct llist_head *msc_list;
-
-#define RESET_INTERVAL 1	/* sek */
-#define SCCP_MSG_MAXSIZE 1024
-#define CS7_POINTCODE_DEFAULT_OFFSET 2
-
-/* Internal list with connections we currently maintain. This
- * list is of type struct osmo_bsc_sccp_con */
-static LLIST_HEAD(active_connections);
-
-/* The SCCP stack will not assign connection IDs to us automatically, we
- * will do this ourselves using a counter variable, that counts one up
- * for every new connection */
-static uint32_t conn_id_counter;
-
-/* Helper function to Check if the given connection id is already assigned */
-static struct osmo_bsc_sccp_con *get_bsc_conn_by_conn_id(int conn_id)
-{
-	conn_id &= 0xFFFFFF;
-	struct osmo_bsc_sccp_con *bsc_con;
-
-	llist_for_each_entry(bsc_con, &active_connections, entry) {
-		if (bsc_con->conn_id == conn_id)
-			return bsc_con;
-	}
-
-	return NULL;
-}
-
-/* Pick a free connection id */
-static int pick_free_conn_id(const struct bsc_msc_data *msc)
-{
-	int conn_id = conn_id_counter;
-	int i;
-
-	for (i = 0; i < 0xFFFFFF; i++) {
-		conn_id++;
-		conn_id &= 0xFFFFFF;
-		if (get_bsc_conn_by_conn_id(conn_id) == false) {
-			conn_id_counter = conn_id;
-			return conn_id;
-		}
-	}
-
-	return -1;
-}
-
-/* Send reset to MSC */
-static void osmo_bsc_sigtran_tx_reset(const struct bsc_msc_data *msc)
-{
-	struct osmo_ss7_instance *ss7;
-	struct msgb *msg;
-
-	ss7 = osmo_ss7_instance_find(msc->a.cs7_instance);
-	OSMO_ASSERT(ss7);
-	LOGP(DMSC, LOGL_NOTICE, "Sending RESET to MSC: %s\n", osmo_sccp_addr_name(ss7, &msc->a.msc_addr));
-	msg = gsm0808_create_reset();
-	osmo_sccp_tx_unitdata_msg(msc->a.sccp_user, &msc->a.bsc_addr,
-				  &msc->a.msc_addr, msg);
-}
-
-/* Send reset-ack to MSC */
-void osmo_bsc_sigtran_tx_reset_ack(const struct bsc_msc_data *msc)
-{
-	struct osmo_ss7_instance *ss7;
-	struct msgb *msg;
-	OSMO_ASSERT(msc);
-
-	ss7 = osmo_ss7_instance_find(msc->a.cs7_instance);
-	OSMO_ASSERT(ss7);
-	LOGP(DMSC, LOGL_NOTICE, "Sending RESET ACK to MSC: %s\n", osmo_sccp_addr_name(ss7, &msc->a.msc_addr));
-	msg = gsm0808_create_reset_ack();
-	osmo_sccp_tx_unitdata_msg(msc->a.sccp_user, &msc->a.bsc_addr,
-				  &msc->a.msc_addr, msg);
-}
-
-/* Find an MSC by its sigtran point code */
-static struct bsc_msc_data *get_msc_by_addr(const struct osmo_sccp_addr *msc_addr)
-{
-	struct osmo_ss7_instance *ss7;
-	struct bsc_msc_data *msc;
-	llist_for_each_entry(msc, msc_list, entry) {
-		if (memcmp(msc_addr, &msc->a.msc_addr, sizeof(*msc_addr)) == 0)
-			return msc;
-	}
-
-	ss7 = osmo_ss7_instance_find(msc->a.cs7_instance);
-	OSMO_ASSERT(ss7);
-	LOGP(DMSC, LOGL_ERROR, "Unable to find MSC data under address: %s\n", osmo_sccp_addr_name(ss7, msc_addr));
-	return NULL;
-}
-
-/* Send data to MSC, use the connection id which MSC it is */
-static int handle_data_from_msc(int conn_id, struct msgb *msg)
-{
-	struct osmo_bsc_sccp_con *bsc_con = get_bsc_conn_by_conn_id(conn_id);
-	int rc = -EINVAL;
-
-	if (bsc_con) {
-		msg->l3h = msgb_l2(msg);
-		rc = bsc_handle_dt(bsc_con, msg, msgb_l2len(msg));
-	} else
-		LOGP(DMSC, LOGL_NOTICE, "incoming data from unknown connection id: %i\n", conn_id);
-
-	return rc;
-}
-
-/* Sent unitdata to MSC, use the point code to determine which MSC it is */
-static int handle_unitdata_from_msc(const struct osmo_sccp_addr *msc_addr, struct msgb *msg,
-				    const struct osmo_sccp_user *scu)
-{
-	struct osmo_ss7_instance *ss7;
-	struct bsc_msc_data *msc = get_msc_by_addr(msc_addr);
-	int rc = -EINVAL;
-
-	if (msc) {
-		msg->l3h = msgb_l2(msg);
-		rc = bsc_handle_udt(msc, msg, msgb_l2len(msg));
-	} else {
-		ss7 = osmo_sccp_get_ss7(osmo_sccp_get_sccp(scu));
-		OSMO_ASSERT(ss7);
-		LOGP(DMSC, LOGL_NOTICE, "incoming unitdata data from unknown remote address: %s\n",
-		     osmo_sccp_addr_name(ss7, msc_addr));
-	}
-	return rc;
-}
-
-/* Callback function, called by the SSCP stack when data arrives */
-static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
-{
-	struct osmo_scu_prim *scu_prim = (struct osmo_scu_prim *)oph;
-	struct osmo_sccp_user *scu = _scu;
-	struct osmo_bsc_sccp_con *bsc_con;
-	int rc = 0;
-
-	switch (OSMO_PRIM_HDR(&scu_prim->oph)) {
-	case OSMO_PRIM(OSMO_SCU_PRIM_N_UNITDATA, PRIM_OP_INDICATION):
-		/* Handle inbound UNITDATA */
-		DEBUGP(DMSC, "N-UNITDATA.ind(%s)\n", osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)));
-		rc = handle_unitdata_from_msc(&scu_prim->u.unitdata.calling_addr, oph->msg, scu);
-		break;
-
-	case OSMO_PRIM(OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_INDICATION):
-		/* Handle (Reject) inbound connections */
-		DEBUGP(DMSC, "N-CONNECT.ind(X->%u)\n", scu_prim->u.connect.conn_id);
-		LOGP(DMSC, LOGL_DEBUG, "Rejecting inbound SCCP connection...\n");
-		rc = osmo_sccp_tx_disconn(scu, scu_prim->u.connect.conn_id, &scu_prim->u.connect.called_addr, 0);
-		break;
-
-	case OSMO_PRIM(OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_CONFIRM):
-		/* Handle outbound connection confirmation */
-		if (msgb_l2len(oph->msg) > 0) {
-			DEBUGP(DMSC, "N-CONNECT.cnf(%u, %s)\n", scu_prim->u.connect.conn_id,
-			       osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)));
-			rc = handle_data_from_msc(scu_prim->u.connect.conn_id, oph->msg);
-		} else
-			DEBUGP(DRANAP, "N-CONNECT.cnf(%u)\n", scu_prim->u.connect.conn_id);
-		break;
-
-	case OSMO_PRIM(OSMO_SCU_PRIM_N_DATA, PRIM_OP_INDICATION):
-		/* Handle incoming connection oriented data */
-		DEBUGP(DMSC, "N-DATA.ind(%u, %s)\n", scu_prim->u.data.conn_id,
-		       osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)));
-
-		/* Incoming data is a sign of a vital connection */
-		bsc_con = get_bsc_conn_by_conn_id(scu_prim->u.disconnect.conn_id);
-		if (bsc_con)
-			a_reset_conn_success(bsc_con->msc->a.reset);
-
-		rc = handle_data_from_msc(scu_prim->u.data.conn_id, oph->msg);
-		break;
-
-	case OSMO_PRIM(OSMO_SCU_PRIM_N_DISCONNECT, PRIM_OP_INDICATION):
-		/* indication of disconnect */
-		if (msgb_l2len(oph->msg) > 0) {
-			DEBUGP(DMSC, "N-DISCONNECT.ind(%u, %s, cause=%i)\n", scu_prim->u.disconnect.conn_id,
-			       osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)), scu_prim->u.disconnect.cause);
-			handle_data_from_msc(scu_prim->u.disconnect.conn_id, oph->msg);
-		} else
-			DEBUGP(DRANAP, "N-DISCONNECT.ind(%u, cause=%i)\n", scu_prim->u.disconnect.conn_id,
-			       scu_prim->u.disconnect.cause);
-
-		bsc_con = get_bsc_conn_by_conn_id(scu_prim->u.disconnect.conn_id);
-		if (bsc_con) {
-			/* We might have a connectivity problem. Maybe we need to go
-			 * through the reset procedure again? */
-			if (scu_prim->u.disconnect.cause == 0)
-				a_reset_conn_fail(bsc_con->msc->a.reset);
-
-			rc = osmo_bsc_sigtran_del_conn(bsc_con);
-		}
-		break;
-
-	default:
-		LOGP(DMSC, LOGL_ERROR, "Unhandled SIGTRAN primitive: %u:%u\n", oph->primitive, oph->operation);
-		break;
-	}
-
-	msgb_free(oph->msg);
-	return rc;
-}
-
-/* Allocate resources to make a new connection oriented sigtran connection
- * (not the connection ittself!) */
-enum bsc_con osmo_bsc_sigtran_new_conn(struct gsm_subscriber_connection *conn, struct bsc_msc_data *msc)
-{
-	struct osmo_ss7_instance *ss7;
-	struct osmo_bsc_sccp_con *bsc_con;
-	int conn_id;
-
-	OSMO_ASSERT(conn);
-	OSMO_ASSERT(msc);
-
-	ss7 = osmo_ss7_instance_find(msc->a.cs7_instance);
-	OSMO_ASSERT(ss7);
-	LOGP(DMSC, LOGL_NOTICE, "Initializing resources for new SIGTRAN connection to MSC: %s...\n",
-	     osmo_sccp_addr_name(ss7, &msc->a.msc_addr));
-
-	if (a_reset_conn_ready(msc->a.reset) == false) {
-		LOGP(DMSC, LOGL_ERROR, "MSC is not connected. Dropping.\n");
-		return BSC_CON_REJECT_NO_LINK;
-	}
-
-	if (!bsc_grace_allow_new_connection(conn->bts->network, conn->bts)) {
-		LOGP(DMSC, LOGL_NOTICE, "BSC in grace period. No new connections.\n");
-		return BSC_CON_REJECT_RF_GRACE;
-	}
-
-	bsc_con = talloc_zero(conn->bts, struct osmo_bsc_sccp_con);
-	if (!bsc_con) {
-		LOGP(DMSC, LOGL_ERROR, "Failed to allocate new SIGTRAN connection.\n");
-		return BSC_CON_NO_MEM;
-	}
-
-	bsc_con->msc = msc;
-	bsc_con->conn = conn;
-	llist_add_tail(&bsc_con->entry, &active_connections);
-	conn->sccp_con = bsc_con;
-
-	/* Pick a free connection id */
-	conn_id = pick_free_conn_id(msc);
-	if (conn_id < 0)
-		return BSC_CON_REJECT_NO_LINK;
-	bsc_con->conn_id = conn_id;
-
-	LOGP(DMSC, LOGL_NOTICE, "Allocated new connection id: %i\n", conn_id);
-
-	return BSC_CON_SUCCESS;
-}
-
-/* Open a new connection oriented sigtran connection */
-int osmo_bsc_sigtran_open_conn(const struct osmo_bsc_sccp_con *conn, struct msgb *msg)
-{
-	struct osmo_ss7_instance *ss7;
-	struct bsc_msc_data *msc;
-	int conn_id;
-	int rc;
-
-	OSMO_ASSERT(conn);
-	OSMO_ASSERT(msg);
-	OSMO_ASSERT(conn->msc);
-
-	msc = conn->msc;
-
-	if (a_reset_conn_ready(msc->a.reset) == false) {
-		LOGP(DMSC, LOGL_ERROR, "MSC is not connected. Dropping.\n");
-		return -EINVAL;
-	}
-
-	conn_id = conn->conn_id;
-	ss7 = osmo_ss7_instance_find(msc->a.cs7_instance);
-	OSMO_ASSERT(ss7);
-	LOGP(DMSC, LOGL_NOTICE, "Opening new SIGTRAN connection (id=%i) to MSC: %s\n", conn_id,
-	     osmo_sccp_addr_name(ss7, &msc->a.msc_addr));
-
-	rc = osmo_sccp_tx_conn_req_msg(msc->a.sccp_user, conn_id, &msc->a.bsc_addr,
-				       &msc->a.msc_addr, msg);
-
-	return rc;
-}
-
-/* Send data to MSC */
-int osmo_bsc_sigtran_send(const struct osmo_bsc_sccp_con *conn, struct msgb *msg)
-{
-	struct osmo_ss7_instance *ss7;
-	int conn_id;
-	int rc;
-	struct bsc_msc_data *msc;
-
-	OSMO_ASSERT(conn);
-	OSMO_ASSERT(msg);
-	OSMO_ASSERT(conn->msc);
-
-	msc = conn->msc;
-
-	if (a_reset_conn_ready(msc->a.reset) == false) {
-		LOGP(DMSC, LOGL_ERROR, "MSC is not connected. Dropping.\n");
-		return -EINVAL;
-	}
-
-	conn_id = conn->conn_id;
-
-	ss7 = osmo_ss7_instance_find(msc->a.cs7_instance);
-	OSMO_ASSERT(ss7);
-	LOGP(DMSC, LOGL_DEBUG, "Sending connection (id=%i) oriented data to MSC: %si\n",
-	     conn_id, osmo_sccp_addr_name(ss7, &msc->a.msc_addr));
-
-	rc = osmo_sccp_tx_data_msg(msc->a.sccp_user, conn_id, msg);
-
-	return rc;
-}
-
-/* Delete a connection from the list with open connections
- * (called by osmo_bsc_api.c on failing open connections and
- * locally, when a connection is closed by the MSC */
-int osmo_bsc_sigtran_del_conn(struct osmo_bsc_sccp_con *conn)
-{
-	if (!conn)
-		return 0;
-
-	if (conn->conn) {
-		LOGP(DMSC, LOGL_ERROR,
-		     "sccp connection (id=%i) not cleared (gsm subscriber connection still active) -- forcefully clearing it now!\n",
-		     conn->conn_id);
-		bsc_subscr_con_free(conn->conn);
-		conn->conn = NULL;
-
-		/* This bahaviour might be caused by a bad connection. Maybe we
-		 * will have to go through the reset procedure again */
-		a_reset_conn_fail(conn->msc->a.reset);
-	}
-
-	llist_del(&conn->entry);
-	talloc_free(conn);
-
-	return 0;
-}
-
-/* Send an USSD notification in case we loose the connection to the MSC */
-static void bsc_notify_msc_lost(const struct osmo_bsc_sccp_con *conn)
-{
-	struct gsm_subscriber_connection *subscr_conn;
-
-	/* Check if sccp conn is still present */
-	if (!conn)
-		return;
-	subscr_conn = conn->conn;
-
-	/* send USSD notification if string configured and conn->data is set */
-	if (!subscr_conn)
-		return;
-
-	/* check for config string */
-	if (!conn->msc->ussd_msc_lost_txt)
-		return;
-	if (conn->msc->ussd_msc_lost_txt[0] == '\0')
-		return;
-
-	/* send USSD notification */
-	bsc_send_ussd_notify(subscr_conn, 1, subscr_conn->sccp_con->msc->ussd_msc_lost_txt);
-	bsc_send_ussd_release_complete(subscr_conn);
-}
-
-/* Close all open sigtran connections and channels */
-void osmo_bsc_sigtran_reset(const struct bsc_msc_data *msc)
-{
-	struct osmo_bsc_sccp_con *conn;
-	struct osmo_bsc_sccp_con *conn_temp;
-	OSMO_ASSERT(msc);
-
-	/* Close all open connections */
-	llist_for_each_entry_safe(conn, conn_temp, &active_connections, entry) {
-
-		/* We only may close connections which actually belong to this
-		 * MSC. All other open connections are left untouched */
-		if (conn->msc == msc) {
-			/* Notify active connection users via USSD that the MSC is down */
-			bsc_notify_msc_lost(conn);
-
-			/* Take down all occopied RF channels */
-			if (conn->conn)
-				gsm0808_clear(conn->conn);
-
-			/* Disconnect all Sigtran connections */
-			osmo_sccp_tx_disconn(msc->a.sccp_user, conn->conn_id, &msc->a.bsc_addr, 0);
-
-			/* Delete subscriber connection */
-			osmo_bsc_sigtran_del_conn(conn);
-		}
-	}
-}
-
-/* Callback function: Close all open connections */
-static void osmo_bsc_sigtran_reset_cb(const void *priv)
-{
-	struct bsc_msc_data *msc = (struct bsc_msc_data*) priv;
-
-	/* Shut down all ongoing traffic */
-	osmo_bsc_sigtran_reset(msc);
-
-	/* Send reset to MSC */
-	osmo_bsc_sigtran_tx_reset(msc);
-}
-
-/* Default point-code to be used as local address (BSC) */
-#define BSC_DEFAULT_PC "0.23.3"
-
-/* Default point-code to be used as remote address (MSC) */
-#define MSC_DEFAULT_PC "0.23.1"
-
-/* Initalize osmo sigtran backhaul */
-int osmo_bsc_sigtran_init(struct llist_head *mscs)
-{
-	bool free_attempt_used = false;
-	bool fail_on_next_invalid_cfg = false;
-
-	struct bsc_msc_data *msc;
-	char msc_name[32];
-	uint32_t default_pc;
-
-	OSMO_ASSERT(mscs);
-	msc_list = mscs;
-
-	llist_for_each_entry(msc, msc_list, entry) {
-		snprintf(msc_name, sizeof(msc_name), "msc-%u", msc->nr);
-		LOGP(DMSC, LOGL_NOTICE, "Initializing SCCP connection to MSC %s\n", msc_name);
-
-		/* Check if the VTY could determine a valid CS7 instance,
-		 * use safe default in case none is set */
-		if (msc->a.cs7_instance_valid == false) {
-			msc->a.cs7_instance = 0;
-			if (fail_on_next_invalid_cfg)
-				goto fail_auto_cofiguration;
-			free_attempt_used = true;
-		}
-		LOGP(DMSC, LOGL_NOTICE, "CS7 Instance identifier, A-Interface: %u\n", msc->a.cs7_instance);
-
-		/* Pre-Check if there is an ss7 instance present */
-		if (osmo_ss7_instance_find(msc->a.cs7_instance) == NULL) {
-			if (fail_on_next_invalid_cfg)
-				goto fail_auto_cofiguration;
-			free_attempt_used = true;
-		}
-
-		/* SS7 Protocol stack */
-		default_pc = osmo_ss7_pointcode_parse(NULL, BSC_DEFAULT_PC);
-		msc->a.sccp =
-		    osmo_sccp_simple_client_on_ss7_id(msc, msc->a.cs7_instance, msc_name, default_pc,
-						      OSMO_SS7_ASP_PROT_M3UA, 0, NULL, 0, NULL);
-		if (!msc->a.sccp)
-			return -EINVAL;
-
-		/* Check if the sccp-address fullfills minimum requirements (SSN+PC is present,
-		 * automatically recover addresses if the addresses are not set up properly) */
-		if (!osmo_sccp_check_addr(&msc->a.bsc_addr, OSMO_SCCP_ADDR_T_SSN | OSMO_SCCP_ADDR_T_PC)) {
-			if (fail_on_next_invalid_cfg)
-				goto fail_auto_cofiguration;
-			free_attempt_used = true;
-
-			LOGP(DMSC, LOGL_NOTICE,
-			     "A-interface: invalid or missing local (BSC) SCCP address (a.bsc_addr=%s)\n",
-			     osmo_sccp_addr_name(osmo_ss7_instance_find(msc->a.cs7_instance), &msc->a.bsc_addr));
-			osmo_sccp_local_addr_by_instance(&msc->a.bsc_addr, msc->a.sccp, SCCP_SSN_BSSAP);
-			LOGP(DMSC, LOGL_NOTICE,
-			     "A-interface: using automatically generated local (BSC) SCCP address (a.bsc_addr=%s)\n",
-			     osmo_sccp_addr_name(osmo_ss7_instance_find(msc->a.cs7_instance), &msc->a.bsc_addr));
-		} else {
-			LOGP(DMSC, LOGL_NOTICE,
-			     "A-interface: using local (BSC) automatically SCCP address (a.msc_addr=%s)\n",
-			     osmo_sccp_addr_name(osmo_ss7_instance_find(msc->a.cs7_instance), &msc->a.bsc_addr));
-		}
-
-		if (!osmo_sccp_check_addr(&msc->a.msc_addr, OSMO_SCCP_ADDR_T_SSN | OSMO_SCCP_ADDR_T_PC)) {
-			if (fail_on_next_invalid_cfg)
-				goto fail_auto_cofiguration;
-			free_attempt_used = true;
-
-			LOGP(DMSC, LOGL_NOTICE,
-			     "A-interface: invalid or missing remote (MSC) SCCP address for the MSC (a.msc_addr=%s)\n",
-			     osmo_sccp_addr_name(osmo_ss7_instance_find(msc->a.cs7_instance), &msc->a.msc_addr));
-			osmo_sccp_local_addr_by_instance(&msc->a.msc_addr, msc->a.sccp, SCCP_SSN_BSSAP);
-			msc->a.msc_addr.pc = osmo_ss7_pointcode_parse(NULL, MSC_DEFAULT_PC);
-			LOGP(DMSC, LOGL_NOTICE,
-			     "A-interface: using automatically generated remote (MSC) SCCP address (a.msc_addr=%s)\n",
-			     osmo_sccp_addr_name(osmo_ss7_instance_find(msc->a.cs7_instance), &msc->a.msc_addr));
-			free_attempt_used = true;
-		} else {
-			LOGP(DMSC, LOGL_NOTICE,
-			     "A-interface: using remote (MSC) automatically SCCP address (a.msc_addr=%s)\n",
-			     osmo_sccp_addr_name(osmo_ss7_instance_find(msc->a.cs7_instance), &msc->a.msc_addr));
-		}
-
-		/* Bind SCCP user */
-		msc->a.sccp_user = osmo_sccp_user_bind(msc->a.sccp, msc_name, sccp_sap_up, msc->a.bsc_addr.ssn);
-		if (!msc->a.sccp_user)
-			return -EINVAL;
-
-		/* Start MSC-Reset procedure */
-		msc->a.reset = a_reset_alloc(msc, msc_name, osmo_bsc_sigtran_reset_cb, msc);
-		if (!msc->a.reset)
-			return -EINVAL;
-
-		/* If we have detected that the SS7 configuration of the MSC we have just initalized
-		 * was incomplete or completely missing, we can not tolerate another incomplete
-		 * configuration. The reson for this is that we do only specify exactly one default
-		 * pointcode pair. We also specify localhost as default IP-Address. If we have wanted
-		 * to support multiple MSCs with automatic configuration we would be forced to invent
-		 * a complex ruleset how to allocate the pointcodes and respective IP-Addresses.
-		 * Furthermore, the situation where a single BSC is connected to multiple MSCs
-		 * is a very rare situation anyway. In this case we expect the user to experienced
-		 * enough to create a valid SS7/CS7 VTY configuration that does not lack any
-		 * components */
-		if (free_attempt_used)
-			fail_on_next_invalid_cfg = true;
-	}
-
-	return 0;
-
-fail_auto_cofiguration:
-	LOGP(DMSC, LOGL_ERROR,
-	     "A-interface: More than one invalid/inclomplete configuration detected, unable to revover - check config file!\n");
-	return -EINVAL;
-}
diff --git a/src/osmo-bsc/osmo_bsc_vty.c b/src/osmo-bsc/osmo_bsc_vty.c
deleted file mode 100644
index 8edcbf3..0000000
--- a/src/osmo-bsc/osmo_bsc_vty.c
+++ /dev/null
@@ -1,1039 +0,0 @@
-/* Osmo BSC VTY Configuration */
-/* (C) 2009-2015 by Holger Hans Peter Freyther
- * (C) 2009-2014 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/>.
- *
- */
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/osmo_bsc.h>
-#include <openbsc/bsc_msc_data.h>
-#include <openbsc/vty.h>
-#include <openbsc/bsc_subscriber.h>
-#include <openbsc/debug.h>
-#include <openbsc/bsc_msg_filter.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/vty/logging.h>
-#include <osmocom/sccp/sccp_types.h>
-
-#include <time.h>
-
-
-#define IPA_STR "IP.ACCESS specific\n"
-
-extern struct gsm_network *bsc_gsmnet;
-
-static struct osmo_bsc_data *osmo_bsc_data(struct vty *vty)
-{
-	return bsc_gsmnet->bsc_data;
-}
-
-static struct bsc_msc_data *bsc_msc_data(struct vty *vty)
-{
-	return vty->index;
-}
-
-static struct cmd_node bsc_node = {
-	BSC_NODE,
-	"%s(config-bsc)# ",
-	1,
-};
-
-static struct cmd_node msc_node = {
-	MSC_NODE,
-	"%s(config-msc)# ",
-	1,
-};
-
-DEFUN(cfg_net_msc, cfg_net_msc_cmd,
-      "msc [<0-1000>]", "Configure MSC details\n" "MSC connection to configure\n")
-{
-	int index = argc == 1 ? atoi(argv[0]) : 0;
-	struct bsc_msc_data *msc;
-
-	msc = osmo_msc_data_alloc(bsc_gsmnet, index);
-	if (!msc) {
-		vty_out(vty, "%%Failed to allocate MSC data.%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	vty->index = msc;
-	vty->node = MSC_NODE;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_bsc, cfg_net_bsc_cmd,
-      "bsc", "Configure BSC\n")
-{
-	vty->node = BSC_NODE;
-	return CMD_SUCCESS;
-}
-
-static void write_msc_amr_options(struct vty *vty, struct bsc_msc_data *msc)
-{
-#define WRITE_AMR(vty, msc, name, var) \
-	vty_out(vty, " amr-config %s %s%s", \
-		name, msc->amr_conf.var ? "allowed" : "forbidden", \
-		VTY_NEWLINE);
-
-	WRITE_AMR(vty, msc, "12_2k", m12_2);
-	WRITE_AMR(vty, msc, "10_2k", m10_2);
-	WRITE_AMR(vty, msc, "7_95k", m7_95);
-	WRITE_AMR(vty, msc, "7_40k", m7_40);
-	WRITE_AMR(vty, msc, "6_70k", m6_70);
-	WRITE_AMR(vty, msc, "5_90k", m5_90);
-	WRITE_AMR(vty, msc, "5_15k", m5_15);
-	WRITE_AMR(vty, msc, "4_75k", m4_75);
-#undef WRITE_AMR
-}
-
-static void write_msc(struct vty *vty, struct bsc_msc_data *msc)
-{
-	struct bsc_msc_dest *dest;
-
-	vty_out(vty, "msc %d%s", msc->nr, VTY_NEWLINE);
-	if (msc->bsc_token)
-		vty_out(vty, " token %s%s", msc->bsc_token, VTY_NEWLINE);
-	if (msc->bsc_key_present)
-		vty_out(vty, " auth-key %s%s",
-			osmo_hexdump(msc->bsc_key, sizeof(msc->bsc_key)), VTY_NEWLINE);
-	if (msc->core_mnc != -1)
-		vty_out(vty, " core-mobile-network-code %d%s",
-			msc->core_mnc, VTY_NEWLINE);
-	if (msc->core_mcc != -1)
-		vty_out(vty, " core-mobile-country-code %d%s",
-			msc->core_mcc, VTY_NEWLINE);
-	if (msc->core_lac != -1)
-		vty_out(vty, " core-location-area-code %d%s",
-			msc->core_lac, VTY_NEWLINE);
-	if (msc->core_ci != -1)
-		vty_out(vty, " core-cell-identity %d%s",
-			msc->core_ci, VTY_NEWLINE);
-	vty_out(vty, " ip.access rtp-base %d%s", msc->rtp_base, VTY_NEWLINE);
-
-	if (msc->ping_timeout == -1)
-		vty_out(vty, " no timeout-ping%s", VTY_NEWLINE);
-	else {
-		vty_out(vty, " timeout-ping %d%s", msc->ping_timeout, VTY_NEWLINE);
-		vty_out(vty, " timeout-pong %d%s", msc->pong_timeout, VTY_NEWLINE);
-		if (msc->advanced_ping)
-			vty_out(vty, " timeout-ping advanced%s", VTY_NEWLINE);
-		else
-			vty_out(vty, " no timeout-ping advanced%s", VTY_NEWLINE);
-	}
-
-	if (msc->ussd_welcome_txt)
-		vty_out(vty, " bsc-welcome-text %s%s", msc->ussd_welcome_txt, VTY_NEWLINE);
-	else
-		vty_out(vty, " no bsc-welcome-text%s", VTY_NEWLINE);
-
-	if (msc->ussd_msc_lost_txt && msc->ussd_msc_lost_txt[0])
-		vty_out(vty, " bsc-msc-lost-text %s%s", msc->ussd_msc_lost_txt, VTY_NEWLINE);
-	else
-		vty_out(vty, " no bsc-msc-lost-text%s", VTY_NEWLINE);
-
-	if (msc->ussd_grace_txt && msc->ussd_grace_txt[0])
-		vty_out(vty, " bsc-grace-text %s%s", msc->ussd_grace_txt, VTY_NEWLINE);
-	else
-		vty_out(vty, " no bsc-grace-text%s", VTY_NEWLINE);
-
-	if (msc->audio_length != 0) {
-		int i;
-
-		vty_out(vty, " codec-list ");
-		for (i = 0; i < msc->audio_length; ++i) {
-			if (i != 0)
-				vty_out(vty, " ");
-
-			if (msc->audio_support[i]->hr)
-				vty_out(vty, "hr%.1u", msc->audio_support[i]->ver);
-			else
-				vty_out(vty, "fr%.1u", msc->audio_support[i]->ver);
-		}
-		vty_out(vty, "%s", VTY_NEWLINE);
-
-	}
-
-	llist_for_each_entry(dest, &msc->dests, list)
-		vty_out(vty, " dest %s %d %d%s", dest->ip, dest->port,
-			dest->dscp, VTY_NEWLINE);
-
-	vty_out(vty, " type %s%s", msc->type == MSC_CON_TYPE_NORMAL ?
-					"normal" : "local", VTY_NEWLINE);
-	vty_out(vty, " allow-emergency %s%s", msc->allow_emerg ?
-					"allow" : "deny", VTY_NEWLINE);
-
-	if (msc->local_pref)
-		vty_out(vty, " local-prefix %s%s", msc->local_pref, VTY_NEWLINE);
-
-	if (msc->acc_lst_name)
-		vty_out(vty, " access-list-name %s%s", msc->acc_lst_name, VTY_NEWLINE);
-
-	/* write amr options */
-	write_msc_amr_options(vty, msc);
-
-	/* write sccp connection configuration */
-	if (msc->a.bsc_addr_name) {
-		vty_out(vty, " bsc-addr %s%s",
-			msc->a.bsc_addr_name, VTY_NEWLINE);
-	}
-	if (msc->a.msc_addr_name) {
-		vty_out(vty, " msc-addr %s%s",
-			msc->a.msc_addr_name, VTY_NEWLINE);
-	}
-}
-
-static int config_write_msc(struct vty *vty)
-{
-	struct bsc_msc_data *msc;
-	struct osmo_bsc_data *bsc = osmo_bsc_data(vty);
-
-	llist_for_each_entry(msc, &bsc->mscs, entry)
-		write_msc(vty, msc);
-
-	return CMD_SUCCESS;
-}
-
-static int config_write_bsc(struct vty *vty)
-{
-	struct osmo_bsc_data *bsc = osmo_bsc_data(vty);
-
-	vty_out(vty, "bsc%s", VTY_NEWLINE);
-	if (bsc->mid_call_txt)
-		vty_out(vty, " mid-call-text %s%s", bsc->mid_call_txt, VTY_NEWLINE);
-	vty_out(vty, " mid-call-timeout %d%s", bsc->mid_call_timeout, VTY_NEWLINE);
-	if (bsc->rf_ctrl_name)
-		vty_out(vty, " bsc-rf-socket %s%s",
-			bsc->rf_ctrl_name, VTY_NEWLINE);
-
-	if (bsc->auto_off_timeout != -1)
-		vty_out(vty, " bsc-auto-rf-off %d%s",
-			bsc->auto_off_timeout, VTY_NEWLINE);
-
-	if (bsc->ussd_no_msc_txt && bsc->ussd_no_msc_txt[0])
-		vty_out(vty, " missing-msc-text %s%s", bsc->ussd_no_msc_txt, VTY_NEWLINE);
-	else
-		vty_out(vty, " no missing-msc-text%s", VTY_NEWLINE);
-	if (bsc->acc_lst_name)
-		vty_out(vty, " access-list-name %s%s", bsc->acc_lst_name, VTY_NEWLINE);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_bsc_token,
-      cfg_net_bsc_token_cmd,
-      "token TOKEN",
-      "A token for the BSC to be sent to the MSC\n" "A token\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-
-	osmo_talloc_replace_string(osmo_bsc_data(vty), &data->bsc_token, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_bsc_key,
-      cfg_net_bsc_key_cmd,
-      "auth-key KEY",
-      "Authentication (secret) key configuration\n"
-      "Security key\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-
-	osmo_hexparse(argv[0], data->bsc_key, sizeof(data->bsc_key));
-	data->bsc_key_present = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_no_bsc_key, cfg_net_bsc_no_key_cmd,
-      "no auth-key",
-      NO_STR "Authentication (secret) key configuration\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-
-	memset(data->bsc_key, 0, sizeof(data->bsc_key));
-	data->bsc_key_present = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_bsc_ncc,
-      cfg_net_bsc_ncc_cmd,
-      "core-mobile-network-code <1-999>",
-      "Use this network code for the core network\n" "MNC value\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-	data->core_mnc = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_bsc_mcc,
-      cfg_net_bsc_mcc_cmd,
-      "core-mobile-country-code <1-999>",
-      "Use this country code for the core network\n" "MCC value\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-	data->core_mcc = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_bsc_lac,
-      cfg_net_bsc_lac_cmd,
-      "core-location-area-code <0-65535>",
-      "Use this location area code for the core network\n" "LAC value\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-	data->core_lac = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_bsc_ci,
-      cfg_net_bsc_ci_cmd,
-      "core-cell-identity <0-65535>",
-      "Use this cell identity for the core network\n" "CI value\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-	data->core_ci = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_bsc_rtp_base,
-      cfg_net_bsc_rtp_base_cmd,
-      "ip.access rtp-base <1-65000>",
-      IPA_STR
-      "Set the rtp-base port for the RTP stream\n"
-      "Port number\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-	data->rtp_base = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_bsc_codec_list,
-      cfg_net_bsc_codec_list_cmd,
-      "codec-list .LIST",
-      "Set the allowed audio codecs\n"
-      "List of audio codecs, e.g. fr3 fr1 hr3\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-	int saw_fr, saw_hr;
-	int i;
-
-	saw_fr = saw_hr = 0;
-
-	/* free the old list... if it exists */
-	if (data->audio_support) {
-		talloc_free(data->audio_support);
-		data->audio_support = NULL;
-		data->audio_length = 0;
-	}
-
-	/* create a new array */
-	data->audio_support =
-		talloc_zero_array(osmo_bsc_data(vty), struct gsm_audio_support *, argc);
-	data->audio_length = argc;
-
-	for (i = 0; i < argc; ++i) {
-		/* check for hrX or frX */
-		if (strlen(argv[i]) != 3
-				|| argv[i][1] != 'r'
-				|| (argv[i][0] != 'h' && argv[i][0] != 'f')
-				|| argv[i][2] < 0x30
-				|| argv[i][2] > 0x39)
-			goto error;
-
-		data->audio_support[i] = talloc_zero(data->audio_support,
-				struct gsm_audio_support);
-		data->audio_support[i]->ver = atoi(argv[i] + 2);
-
-		if (strncmp("hr", argv[i], 2) == 0) {
-			data->audio_support[i]->hr = 1;
-			saw_hr = 1;
-		} else if (strncmp("fr", argv[i], 2) == 0) {
-			data->audio_support[i]->hr = 0;
-			saw_fr = 1;
-		}
-
-		if (saw_hr && saw_fr) {
-			vty_out(vty, "Can not have full-rate and half-rate codec.%s",
-					VTY_NEWLINE);
-			return CMD_ERR_INCOMPLETE;
-		}
-	}
-
-	return CMD_SUCCESS;
-
-error:
-	vty_out(vty, "Codec name must be hrX or frX. Was '%s'%s",
-			argv[i], VTY_NEWLINE);
-	return CMD_ERR_INCOMPLETE;
-}
-
-DEFUN(cfg_net_msc_dest,
-      cfg_net_msc_dest_cmd,
-      "dest A.B.C.D <1-65000> <0-255>",
-      "Add a destination to a MUX/MSC\n"
-      "IP Address\n" "Port\n" "DSCP\n")
-{
-	struct bsc_msc_dest *dest;
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-
-	dest = talloc_zero(osmo_bsc_data(vty), struct bsc_msc_dest);
-	if (!dest) {
-		vty_out(vty, "%%Failed to create structure.%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	dest->ip = talloc_strdup(dest, argv[0]);
-	if (!dest->ip) {
-		vty_out(vty, "%%Failed to copy dest ip.%s", VTY_NEWLINE);
-		talloc_free(dest);
-		return CMD_WARNING;
-	}
-
-	dest->port = atoi(argv[1]);
-	dest->dscp = atoi(argv[2]);
-	llist_add_tail(&dest->list, &data->dests);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_msc_no_dest,
-      cfg_net_msc_no_dest_cmd,
-      "no dest A.B.C.D <1-65000> <0-255>",
-      NO_STR "Remove a destination to a MUX/MSC\n"
-      "IP Address\n" "Port\n" "DSCP\n")
-{
-	struct bsc_msc_dest *dest, *tmp;
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-
-	int port = atoi(argv[1]);
-	int dscp = atoi(argv[2]);
-
-	llist_for_each_entry_safe(dest, tmp, &data->dests, list) {
-		if (port != dest->port || dscp != dest->dscp
-		    || strcmp(dest->ip, argv[0]) != 0)
-			continue;
-
-		llist_del(&dest->list);
-		talloc_free(dest);
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_msc_no_ping_time,
-      cfg_net_msc_no_ping_time_cmd,
-      "no timeout-ping",
-      NO_STR "Disable the ping/pong handling on A-link\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-	data->ping_timeout = -1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_msc_ping_time,
-      cfg_net_msc_ping_time_cmd,
-      "timeout-ping <1-2147483647>",
-      "Set the PING interval, negative for not sending PING\n"
-      "Timeout in seconds\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-	data->ping_timeout = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_msc_pong_time,
-      cfg_net_msc_pong_time_cmd,
-      "timeout-pong <1-2147483647>",
-      "Set the time to wait for a PONG\n" "Timeout in seconds\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-	data->pong_timeout = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_msc_advanced_ping,
-      cfg_net_msc_advanced_ping_cmd,
-      "timeout-ping advanced",
-      "Ping timeout handling\nEnable advanced mode during SCCP\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-
-	if (data->ping_timeout == -1) {
-		vty_out(vty, "%%ping handling is disabled. Enable it first.%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	data->advanced_ping = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_no_net_msc_advanced_ping,
-      cfg_no_net_msc_advanced_ping_cmd,
-      "no timeout-ping advanced",
-      NO_STR "Ping timeout handling\nEnable advanced mode during SCCP\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-	data->advanced_ping = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_msc_welcome_ussd,
-      cfg_net_msc_welcome_ussd_cmd,
-      "bsc-welcome-text .TEXT",
-      "Set the USSD notification to be sent\n" "Text to be sent\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-	char *str = argv_concat(argv, argc, 0);
-	if (!str)
-		return CMD_WARNING;
-
-	osmo_talloc_replace_string(osmo_bsc_data(vty), &data->ussd_welcome_txt, str);
-	talloc_free(str);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_msc_no_welcome_ussd,
-      cfg_net_msc_no_welcome_ussd_cmd,
-      "no bsc-welcome-text",
-      NO_STR "Clear the USSD notification to be sent\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-
-	talloc_free(data->ussd_welcome_txt);
-	data->ussd_welcome_txt = NULL;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_msc_lost_ussd,
-      cfg_net_msc_lost_ussd_cmd,
-      "bsc-msc-lost-text .TEXT",
-      "Set the USSD notification to be sent on MSC connection loss\n" "Text to be sent\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-	char *str = argv_concat(argv, argc, 0);
-	if (!str)
-		return CMD_WARNING;
-
-	osmo_talloc_replace_string(osmo_bsc_data(vty), &data->ussd_msc_lost_txt, str);
-	talloc_free(str);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_msc_no_lost_ussd,
-      cfg_net_msc_no_lost_ussd_cmd,
-      "no bsc-msc-lost-text",
-      NO_STR "Clear the USSD notification to be sent on MSC connection loss\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-
-	talloc_free(data->ussd_msc_lost_txt);
-	data->ussd_msc_lost_txt = 0;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_msc_grace_ussd,
-      cfg_net_msc_grace_ussd_cmd,
-      "bsc-grace-text .TEXT",
-      "Set the USSD notification to be sent when the MSC has entered the grace period\n" "Text to be sent\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-	char *str = argv_concat(argv, argc, 0);
-	if (!str)
-		return CMD_WARNING;
-
-	osmo_talloc_replace_string(osmo_bsc_data(vty), &data->ussd_grace_txt, str);
-	talloc_free(str);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_msc_no_grace_ussd,
-      cfg_net_msc_no_grace_ussd_cmd,
-      "no bsc-grace-text",
-      NO_STR "Clear the USSD notification to be sent when the MSC has entered the grace period\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-
-	talloc_free(data->ussd_grace_txt);
-	data->ussd_grace_txt = NULL;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_bsc_missing_msc_ussd,
-      cfg_net_bsc_missing_msc_ussd_cmd,
-      "missing-msc-text .TEXT",
-      "Set the USSD notification to be send when a MSC has not been found.\n" "Text to be sent\n")
-{
-	struct osmo_bsc_data *data = osmo_bsc_data(vty);
-	char *txt = argv_concat(argv, argc, 0);
-	if (!txt)
-		return CMD_WARNING;
-
-	osmo_talloc_replace_string(data, &data->ussd_no_msc_txt, txt);
-	talloc_free(txt);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_bsc_no_missing_msc_text,
-      cfg_net_bsc_no_missing_msc_text_cmd,
-      "no missing-msc-text",
-      NO_STR "Clear the USSD notification to be send when a MSC has not been found.\n")
-{
-	struct osmo_bsc_data *data = osmo_bsc_data(vty);
-
-	talloc_free(data->ussd_no_msc_txt);
-	data->ussd_no_msc_txt = 0;
-
-	return CMD_SUCCESS;
-}
-
-
-DEFUN(cfg_net_msc_type,
-      cfg_net_msc_type_cmd,
-      "type (normal|local)",
-      "Select the MSC type\n"
-      "Plain GSM MSC\n" "Special MSC for local call routing\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-
-	if (strcmp(argv[0], "normal") == 0)
-		data->type = MSC_CON_TYPE_NORMAL;
-	else if (strcmp(argv[0], "local") == 0)
-		data->type = MSC_CON_TYPE_LOCAL;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_msc_emerg,
-      cfg_net_msc_emerg_cmd,
-      "allow-emergency (allow|deny)",
-      "Allow CM ServiceRequests with type emergency\n"
-      "Allow\n" "Deny\n")
-{
-	struct bsc_msc_data *data = bsc_msc_data(vty);
-	data->allow_emerg = strcmp("allow", argv[0]) == 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_msc_local_prefix,
-      cfg_net_msc_local_prefix_cmd,
-      "local-prefix REGEXP",
-      "Prefix for local numbers\n" "REGEXP used\n")
-{
-	struct bsc_msc_data *msc = bsc_msc_data(vty);
-
-	if (gsm_parse_reg(msc, &msc->local_pref_reg, &msc->local_pref, argc, argv) != 0) {
-		vty_out(vty, "%%Failed to parse the regexp: '%s'%s",
-			argv[0], VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	return CMD_SUCCESS;
-}
-
-#define AMR_CONF_STR "AMR Multirate Configuration\n"
-#define AMR_COMMAND(name) \
-	DEFUN(cfg_net_msc_amr_##name,					\
-	  cfg_net_msc_amr_##name##_cmd,					\
-	  "amr-config " #name "k (allowed|forbidden)",			\
-	  AMR_CONF_STR "Bitrate\n" "Allowed\n" "Forbidden\n")		\
-{									\
-	struct bsc_msc_data *msc = bsc_msc_data(vty);			\
-									\
-	msc->amr_conf.m##name = strcmp(argv[0], "allowed") == 0; 	\
-	return CMD_SUCCESS;						\
-}
-
-AMR_COMMAND(12_2)
-AMR_COMMAND(10_2)
-AMR_COMMAND(7_95)
-AMR_COMMAND(7_40)
-AMR_COMMAND(6_70)
-AMR_COMMAND(5_90)
-AMR_COMMAND(5_15)
-AMR_COMMAND(4_75)
-
-DEFUN(cfg_msc_acc_lst_name,
-      cfg_msc_acc_lst_name_cmd,
-      "access-list-name NAME",
-      "Set the name of the access list to use.\n"
-      "The name of the to be used access list.")
-{
-	struct bsc_msc_data *msc = bsc_msc_data(vty);
-
-	osmo_talloc_replace_string(msc, &msc->acc_lst_name, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_msc_no_acc_lst_name,
-      cfg_msc_no_acc_lst_name_cmd,
-      "no access-list-name",
-      NO_STR "Remove the access list from the NAT.\n")
-{
-	struct bsc_msc_data *msc = bsc_msc_data(vty);
-
-	if (msc->acc_lst_name) {
-		talloc_free(msc->acc_lst_name);
-		msc->acc_lst_name = NULL;
-	}
-
-	return CMD_SUCCESS;
-}
-
-/* Make sure only standard SSN numbers are used. If no ssn number is
- * configured, silently apply the default SSN */
-static void enforce_standard_ssn(struct vty *vty, struct osmo_sccp_addr *addr)
-{
-	if (addr->presence & OSMO_SCCP_ADDR_T_SSN) {
-		if (addr->ssn != SCCP_SSN_BSSAP)
-			vty_out(vty,
-				"setting an SSN (%u) different from the standard (%u) is not allowd, will use standard SSN for address: %s%s",
-				addr->ssn, SCCP_SSN_BSSAP, osmo_sccp_addr_dump(addr), VTY_NEWLINE);
-	}
-
-	addr->presence |= OSMO_SCCP_ADDR_T_SSN;
-	addr->ssn = SCCP_SSN_BSSAP;
-}
-
-DEFUN(cfg_msc_cs7_bsc_addr,
-      cfg_msc_cs7_bsc_addr_cmd,
-      "bsc-addr NAME",
-      "Calling Address (local address of this BSC)\n" "SCCP address name\n")
-{
-	struct bsc_msc_data *msc = bsc_msc_data(vty);
-	const char *bsc_addr_name = argv[0];
-	struct osmo_ss7_instance *ss7;
-
-	ss7 = osmo_sccp_addr_by_name(&msc->a.bsc_addr, bsc_addr_name);
-	if (!ss7) {
-		vty_out(vty, "No sccp address %s found%s", bsc_addr_name,
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	/* Prevent mixing addresses from different CS7/SS7 instances */
-	if (msc->a.cs7_instance_valid) {
-		if (msc->a.cs7_instance != ss7->cfg.id) {
-			vty_out(vty,
-				"SCCP address %s from different CS7 instance%s",
-				bsc_addr_name, VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-	}
-
-	msc->a.cs7_instance = ss7->cfg.id;
-	msc->a.cs7_instance_valid = true;
-	enforce_standard_ssn(vty, &msc->a.bsc_addr);
-	msc->a.bsc_addr_name = talloc_strdup(msc, bsc_addr_name);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_msc_cs7_msc_addr,
-      cfg_msc_cs7_msc_addr_cmd,
-      "msc-addr NAME",
-      "Called Address (remote address of the MSC)\n" "SCCP address name\n")
-{
-	struct bsc_msc_data *msc = bsc_msc_data(vty);
-	const char *msc_addr_name = argv[0];
-	struct osmo_ss7_instance *ss7;
-
-	ss7 = osmo_sccp_addr_by_name(&msc->a.msc_addr, msc_addr_name);
-	if (!ss7) {
-		vty_out(vty, "No sccp address %s found%s", msc_addr_name,
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	/* Prevent mixing addresses from different CS7/SS7 instances */
-	if (msc->a.cs7_instance_valid) {
-		if (msc->a.cs7_instance != ss7->cfg.id) {
-			vty_out(vty,
-				"SCCP address %s from different CS7 instance%s",
-				msc_addr_name, VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-	}
-
-	msc->a.cs7_instance = ss7->cfg.id;
-	msc->a.cs7_instance_valid = true;
-	enforce_standard_ssn(vty, &msc->a.msc_addr);
-	msc->a.msc_addr_name = talloc_strdup(msc, msc_addr_name);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_bsc_mid_call_text,
-      cfg_net_bsc_mid_call_text_cmd,
-      "mid-call-text .TEXT",
-      "Set the USSD notification to be send.\n" "Text to be sent\n")
-{
-	struct osmo_bsc_data *data = osmo_bsc_data(vty);
-	char *txt = argv_concat(argv, argc, 0);
-	if (!txt)
-		return CMD_WARNING;
-
-	osmo_talloc_replace_string(data, &data->mid_call_txt, txt);
-	talloc_free(txt);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_bsc_mid_call_timeout,
-      cfg_net_bsc_mid_call_timeout_cmd,
-      "mid-call-timeout NR",
-      "Switch from Grace to Off in NR seconds.\n" "Timeout in seconds\n")
-{
-	struct osmo_bsc_data *data = osmo_bsc_data(vty);
-	data->mid_call_timeout = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_rf_socket,
-      cfg_net_rf_socket_cmd,
-      "bsc-rf-socket PATH",
-      "Set the filename for the RF control interface.\n" "RF Control path\n")
-{
-	struct osmo_bsc_data *data = osmo_bsc_data(vty);
-
-	osmo_talloc_replace_string(data, &data->rf_ctrl_name, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_rf_off_time,
-      cfg_net_rf_off_time_cmd,
-      "bsc-auto-rf-off <1-65000>",
-      "Disable RF on MSC Connection\n" "Timeout\n")
-{
-	struct osmo_bsc_data *data = osmo_bsc_data(vty);
-	data->auto_off_timeout = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_net_no_rf_off_time,
-      cfg_net_no_rf_off_time_cmd,
-      "no bsc-auto-rf-off",
-      NO_STR "Disable RF on MSC Connection\n")
-{
-	struct osmo_bsc_data *data = osmo_bsc_data(vty);
-	data->auto_off_timeout = -1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_acc_lst_name,
-      cfg_bsc_acc_lst_name_cmd,
-      "access-list-name NAME",
-      "Set the name of the access list to use.\n"
-      "The name of the to be used access list.")
-{
-	struct osmo_bsc_data *bsc = osmo_bsc_data(vty);
-
-	osmo_talloc_replace_string(bsc, &bsc->acc_lst_name, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_no_acc_lst_name,
-      cfg_bsc_no_acc_lst_name_cmd,
-      "no access-list-name",
-      NO_STR "Remove the access list from the BSC\n")
-{
-	struct osmo_bsc_data *bsc = osmo_bsc_data(vty);
-
-	if (bsc->acc_lst_name) {
-		talloc_free(bsc->acc_lst_name);
-		bsc->acc_lst_name = NULL;
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_statistics,
-      show_statistics_cmd,
-      "show statistics",
-      SHOW_STR "Statistics about the BSC\n")
-{
-	openbsc_vty_print_statistics(vty, bsc_gsmnet);
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_mscs,
-      show_mscs_cmd,
-      "show mscs",
-      SHOW_STR "MSC Connections and State\n")
-{
-	struct bsc_msc_data *msc;
-	llist_for_each_entry(msc, &bsc_gsmnet->bsc_data->mscs, entry) {
-		vty_out(vty, "MSC Nr: %d is connected: %d auth: %d.%s",
-			msc->nr,
-			msc->msc_con ? msc->msc_con->is_connected : -1,
-			msc->msc_con ? msc->msc_con->is_authenticated : -1,
-			VTY_NEWLINE);
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_pos,
-      show_pos_cmd,
-      "show position",
-      SHOW_STR "Position information of the BTS\n")
-{
-	struct gsm_bts *bts;
-	struct bts_location *curloc;
-	struct tm time;
-	char timestr[50];
-
-	llist_for_each_entry(bts, &bsc_gsmnet->bts_list, list) {
-		if (llist_empty(&bts->loc_list)) {
-			vty_out(vty, "BTS Nr: %d position invalid%s", bts->nr,
-				VTY_NEWLINE);
-			continue;
-		}
-		curloc = llist_entry(bts->loc_list.next, struct bts_location, list);
-		if (gmtime_r(&curloc->tstamp, &time) == NULL) {
-			vty_out(vty, "Time conversion failed for BTS %d%s", bts->nr,
-				VTY_NEWLINE);
-			continue;
-		}
-		if (asctime_r(&time, timestr) == NULL) {
-			vty_out(vty, "Time conversion failed for BTS %d%s", bts->nr,
-				VTY_NEWLINE);
-			continue;
-		}
-		/* Last character in asctime is \n */
-		timestr[strlen(timestr)-1] = 0;
-
-		vty_out(vty, "BTS Nr: %d position: %s time: %s%s", bts->nr,
-			get_value_string(bts_loc_fix_names, curloc->valid), timestr,
-			VTY_NEWLINE);
-		vty_out(vty, " lat: %f lon: %f height: %f%s", curloc->lat, curloc->lon,
-			curloc->height, VTY_NEWLINE);
-	}
-	return CMD_SUCCESS;
-}
-
-DEFUN(gen_position_trap,
-      gen_position_trap_cmd,
-      "generate-location-state-trap <0-255>",
-      "Generate location state report\n"
-      "BTS to report\n")
-{
-	int bts_nr;
-	struct gsm_bts *bts;
-	struct gsm_network *net = bsc_gsmnet;
-
-	bts_nr = atoi(argv[0]);
-	if (bts_nr >= net->num_bts) {
-		vty_out(vty, "%% can't find BTS '%s'%s", argv[0],
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bts = gsm_bts_num(net, bts_nr);
-	bsc_gen_location_state_trap(bts);
-	return CMD_SUCCESS;
-}
-
-DEFUN(logging_fltr_imsi,
-      logging_fltr_imsi_cmd,
-      "logging filter imsi IMSI",
-	LOGGING_STR FILTER_STR
-      "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
-{
-	struct bsc_subscr *bsc_subscr;
-	struct log_target *tgt = osmo_log_vty2tgt(vty);
-	const char *imsi = argv[0];
-
-	bsc_subscr = bsc_subscr_find_by_imsi(bsc_gsmnet->bsc_subscribers, imsi);
-
-	if (!bsc_subscr) {
-		vty_out(vty, "%%no subscriber with IMSI(%s)%s",
-			imsi, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	log_set_filter_bsc_subscr(tgt, bsc_subscr);
-	return CMD_SUCCESS;
-}
-
-int bsc_vty_init_extra(void)
-{
-	install_element(CONFIG_NODE, &cfg_net_msc_cmd);
-	install_element(CONFIG_NODE, &cfg_net_bsc_cmd);
-
-	install_node(&bsc_node, config_write_bsc);
-	vty_install_default(BSC_NODE);
-	install_element(BSC_NODE, &cfg_net_bsc_mid_call_text_cmd);
-	install_element(BSC_NODE, &cfg_net_bsc_mid_call_timeout_cmd);
-	install_element(BSC_NODE, &cfg_net_rf_socket_cmd);
-	install_element(BSC_NODE, &cfg_net_rf_off_time_cmd);
-	install_element(BSC_NODE, &cfg_net_no_rf_off_time_cmd);
-	install_element(BSC_NODE, &cfg_net_bsc_missing_msc_ussd_cmd);
-	install_element(BSC_NODE, &cfg_net_bsc_no_missing_msc_text_cmd);
-	install_element(BSC_NODE, &cfg_bsc_acc_lst_name_cmd);
-	install_element(BSC_NODE, &cfg_bsc_no_acc_lst_name_cmd);
-
-	install_node(&msc_node, config_write_msc);
-	vty_install_default(MSC_NODE);
-	install_element(MSC_NODE, &cfg_net_bsc_token_cmd);
-	install_element(MSC_NODE, &cfg_net_bsc_key_cmd);
-	install_element(MSC_NODE, &cfg_net_bsc_no_key_cmd);
-	install_element(MSC_NODE, &cfg_net_bsc_ncc_cmd);
-	install_element(MSC_NODE, &cfg_net_bsc_mcc_cmd);
-	install_element(MSC_NODE, &cfg_net_bsc_lac_cmd);
-	install_element(MSC_NODE, &cfg_net_bsc_ci_cmd);
-	install_element(MSC_NODE, &cfg_net_bsc_rtp_base_cmd);
-	install_element(MSC_NODE, &cfg_net_bsc_codec_list_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_dest_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_no_dest_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_no_ping_time_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_ping_time_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_pong_time_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_advanced_ping_cmd);
-	install_element(MSC_NODE, &cfg_no_net_msc_advanced_ping_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_welcome_ussd_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_no_welcome_ussd_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_lost_ussd_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_no_lost_ussd_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_grace_ussd_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_no_grace_ussd_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_type_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_emerg_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_local_prefix_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_amr_12_2_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_amr_10_2_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_amr_7_95_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_amr_7_40_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_amr_6_70_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_amr_5_90_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_amr_5_15_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_amr_4_75_cmd);
-	install_element(MSC_NODE, &cfg_msc_acc_lst_name_cmd);
-	install_element(MSC_NODE, &cfg_msc_no_acc_lst_name_cmd);
-	install_element(MSC_NODE, &cfg_msc_cs7_bsc_addr_cmd);
-	install_element(MSC_NODE, &cfg_msc_cs7_msc_addr_cmd);
-
-	install_element_ve(&show_statistics_cmd);
-	install_element_ve(&show_mscs_cmd);
-	install_element_ve(&show_pos_cmd);
-	install_element_ve(&logging_fltr_imsi_cmd);
-
-	install_element(ENABLE_NODE, &gen_position_trap_cmd);
-
-	install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
-
-	return 0;
-}
diff --git a/src/osmo-bsc_mgcp/Makefile.am b/src/osmo-bsc_mgcp/Makefile.am
index b4e0d85..3e3511d 100644
--- a/src/osmo-bsc_mgcp/Makefile.am
+++ b/src/osmo-bsc_mgcp/Makefile.am
@@ -7,10 +7,9 @@
 AM_CFLAGS = \
 	-Wall \
 	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
 	$(LIBOSMOVTY_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
 	$(LIBOSMONETIF_CFLAGS) \
+	$(LIBBCG729_CFLAGS) \
 	$(COVERAGE_CFLAGS) \
 	$(NULL)
 
@@ -23,14 +22,10 @@
 	$(NULL)
 
 osmo_bsc_mgcp_LDADD = \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(top_builddir)/src/libmgcp/libmgcp.a \
-	$(LIBOSMOVTY_LIBS) \
+	$(top_builddir)/src/libosmo-legacy-mgcp/libosmo-legacy-mgcp.la \
 	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
 	$(LIBOSMONETIF_LIBS) \
+	$(LIBOSMOVTY_LIBS) \
 	$(LIBBCG729_LIBS) \
 	$(LIBRARY_GSM) \
-	$(LIBOSMOSIGTRAN_LIBS) \
-	-lrt \
 	$(NULL)
diff --git a/src/osmo-bsc_mgcp/mgcp_main.c b/src/osmo-bsc_mgcp/mgcp_main.c
index 6cf9ab7..48241a6 100644
--- a/src/osmo-bsc_mgcp/mgcp_main.c
+++ b/src/osmo-bsc_mgcp/mgcp_main.c
@@ -28,14 +28,13 @@
 #include <time.h>
 #include <limits.h>
 #include <unistd.h>
+#include <errno.h>
 
 #include <sys/socket.h>
 
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/mgcp.h>
-#include <openbsc/mgcp_internal.h>
-#include <openbsc/vty.h>
+#include <osmocom/legacy_mgcp/mgcp.h>
+#include <osmocom/legacy_mgcp/mgcp_internal.h>
+#include <osmocom/legacy_mgcp/vty.h>
 
 #include <osmocom/core/application.h>
 #include <osmocom/core/msgb.h>
@@ -43,6 +42,7 @@
 #include <osmocom/core/select.h>
 #include <osmocom/core/stats.h>
 #include <osmocom/core/rate_ctr.h>
+#include <osmocom/core/logging.h>
 
 #include <osmocom/vty/telnet_interface.h>
 #include <osmocom/vty/logging.h>
@@ -53,7 +53,7 @@
 #include "../../bscconfig.h"
 
 #ifdef BUILD_MGCP_TRANSCODING
-#include "openbsc/mgcp_transcode.h"
+#include <osmocom/legacy_mgcp/mgcp_transcode.h>
 #endif
 
 #define _GNU_SOURCE
@@ -174,7 +174,7 @@
 	}
 
 	if (reset_endpoints) {
-		LOGP(DMGCP, LOGL_NOTICE,
+		LOGP(DLMGCP, LOGL_NOTICE,
 		     "Asked to reset endpoints: %d/%d\n",
 		     reset_trunk->trunk_nr, reset_trunk->trunk_type);
 		reset_endpoints = 0;
@@ -187,18 +187,56 @@
 	return 0;
 }
 
-extern int bsc_vty_go_parent(struct vty *vty);
+int mgcp_vty_is_config_node(struct vty *vty, int node)
+{
+        switch (node) {
+        case CONFIG_NODE:
+                return 0;
+
+        default:
+                return 1;
+        }
+}
+
+int mgcp_vty_go_parent(struct vty *vty)
+{
+        switch (vty->node) {
+        case TRUNK_NODE:
+                vty->node = MGCP_NODE;
+                vty->index = NULL;
+                break;
+        case MGCP_NODE:
+        default:
+                if (mgcp_vty_is_config_node(vty, vty->node))
+                        vty->node = CONFIG_NODE;
+                else
+                        vty->node = ENABLE_NODE;
+
+                vty->index = NULL;
+        }
+
+        return vty->node;
+}
+
 
 static struct vty_app_info vty_info = {
 	.name 		= "OpenBSC MGCP",
 	.version	= PACKAGE_VERSION,
-	.go_parent_cb	= bsc_vty_go_parent,
-	.is_config_node	= bsc_vty_is_config_node,
+	.go_parent_cb	= mgcp_vty_go_parent,
+	.is_config_node	= mgcp_vty_is_config_node,
+};
+
+static const struct log_info_cat log_categories[] = {
+	/* DLMGCP is provided by the MGCP library */
+};
+
+const struct log_info log_info = {
+        .cat = log_categories,
+        .num_cat = ARRAY_SIZE(log_categories),
 };
 
 int main(int argc, char **argv)
 {
-	struct gsm_network dummy_network;
 	struct sockaddr_in addr;
 	int on = 1, rc;
 
@@ -236,7 +274,7 @@
 		return rc;
 
 	/* start telnet after reading config for vty_get_bind_addr() */
-	rc = telnet_init_dynif(tall_bsc_ctx, &dummy_network,
+	rc = telnet_init_dynif(tall_bsc_ctx, NULL,
 			       vty_get_bind_addr(), OSMO_VTY_PORT_BSC_MGCP);
 	if (rc < 0)
 		return rc;
@@ -276,7 +314,7 @@
 			addr.sin_port = htons(2727);
 			inet_aton(cfg->call_agent_addr, &addr.sin_addr);
 			if (connect(cfg->gw_fd.bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-				LOGP(DMGCP, LOGL_ERROR, "Failed to connect to: '%s'. errno: %d\n",
+				LOGP(DLMGCP, LOGL_ERROR, "Failed to connect to: '%s'. errno: %d\n",
 				     cfg->call_agent_addr, errno);
 				close(cfg->gw_fd.bfd.fd);
 				cfg->gw_fd.bfd.fd = -1;
@@ -285,11 +323,11 @@
 		}
 
 		if (osmo_fd_register(&cfg->gw_fd.bfd) != 0) {
-			LOGP(DMGCP, LOGL_FATAL, "Failed to register the fd\n");
+			LOGP(DLMGCP, LOGL_FATAL, "Failed to register the fd\n");
 			return -1;
 		}
 
-		LOGP(DMGCP, LOGL_NOTICE, "Configured for MGCP.\n");
+		LOGP(DLMGCP, LOGL_NOTICE, "Configured for MGCP.\n");
 	}
 
 	/* initialisation */
diff --git a/src/osmo-bsc_nat/Makefile.am b/src/osmo-bsc_nat/Makefile.am
deleted file mode 100644
index b7c13ad..0000000
--- a/src/osmo-bsc_nat/Makefile.am
+++ /dev/null
@@ -1,59 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	-I$(top_builddir) \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOVTY_CFLAGS) \
-	$(LIBOSMOCTRL_CFLAGS) \
-	$(LIBOSMOSCCP_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(LIBOSMONETIF_CFLAGS) \
-	$(LIBCRYPTO_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(COVERAGE_LDFLAGS) \
-	$(NULL)
-
-bin_PROGRAMS = \
-	osmo-bsc_nat \
-	$(NULL)
-
-osmo_bsc_nat_SOURCES = \
-	bsc_filter.c \
-	bsc_mgcp_utils.c \
-	bsc_nat.c \
-	bsc_nat_utils.c \
-	bsc_nat_vty.c \
-	bsc_sccp.c \
-	bsc_ussd.c \
-	bsc_nat_ctrl.c \
-	bsc_nat_rewrite.c \
-	bsc_nat_rewrite_trie.c \
-	bsc_nat_filter.c \
-	$(NULL)
-
-osmo_bsc_nat_LDADD = \
-	$(top_builddir)/src/libmgcp/libmgcp.a \
-	$(top_builddir)/src/libfilter/libfilter.a \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOSCCP_LIBS) \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOVTY_LIBS) \
-	$(LIBOSMOCTRL_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	$(LIBOSMONETIF_LIBS) \
-	$(LIBOSMOSIGTRAN_LIBS) \
-	$(LIBCRYPTO_LIBS) \
-	-lrt \
-	$(NULL)
diff --git a/src/osmo-bsc_nat/bsc_filter.c b/src/osmo-bsc_nat/bsc_filter.c
deleted file mode 100644
index 6a9e99f..0000000
--- a/src/osmo-bsc_nat/bsc_filter.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/* BSC Multiplexer/NAT */
-
-/*
- * (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/>.
- *
- */
-
-#include <openbsc/bsc_nat.h>
-#include <openbsc/bsc_nat_sccp.h>
-#include <openbsc/ipaccess.h>
-#include <openbsc/debug.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-
-#include <osmocom/sccp/sccp.h>
-
-/*
- * The idea is to have a simple struct describing a IPA packet with
- * SCCP SSN and the GSM 08.08 payload and decide. We will both have
- * a white and a blacklist of packets we want to handle.
- *
- * TODO: Implement a "NOT" in the filter language.
- */
-
-#define ALLOW_ANY -1
-
-#define FILTER_TO_BSC	1
-#define FILTER_TO_MSC	2
-#define FILTER_TO_BOTH	3
-
-
-struct bsc_pkt_filter {
-	int ipa_proto;
-	int dest_ssn;
-	int bssap;
-	int gsm;
-	int filter_dir;
-};
-
-static struct bsc_pkt_filter black_list[] = {
-	/* filter reset messages to the MSC */
-	{ IPAC_PROTO_SCCP, SCCP_SSN_BSSAP, 0, BSS_MAP_MSG_RESET, FILTER_TO_MSC },
-
-	/* filter reset ack messages to the BSC */
-	{ IPAC_PROTO_SCCP, SCCP_SSN_BSSAP, 0, BSS_MAP_MSG_RESET_ACKNOWLEDGE, FILTER_TO_BSC },
-
-	/* filter ip access */
-	{ IPAC_PROTO_IPACCESS, ALLOW_ANY, ALLOW_ANY, ALLOW_ANY, FILTER_TO_MSC },
-};
-
-static struct bsc_pkt_filter white_list[] = {
-	/* allow IPAC_PROTO_SCCP messages to both sides */
-	{ IPAC_PROTO_SCCP, ALLOW_ANY, ALLOW_ANY, ALLOW_ANY, FILTER_TO_BOTH },
-
-	/* allow MGCP messages to both sides */
-	{ IPAC_PROTO_MGCP_OLD, ALLOW_ANY, ALLOW_ANY, ALLOW_ANY, FILTER_TO_BOTH },
-};
-
-struct bsc_nat_parsed *bsc_nat_parse(struct msgb *msg)
-{
-	struct sccp_parse_result result;
-	struct bsc_nat_parsed *parsed;
-	struct ipaccess_head *hh;
-
-	/* quick fail */
-	if (msg->len < 4)
-		return NULL;
-
-	parsed = talloc_zero(msg, struct bsc_nat_parsed);
-	if (!parsed)
-		return NULL;
-
-	/* more init */
-	parsed->ipa_proto = parsed->called_ssn = parsed->calling_ssn = -1;
-	parsed->sccp_type = parsed->bssap = parsed->gsm_type = -1;
-
-	/* start parsing */
-	hh = (struct ipaccess_head *) msg->data;
-	parsed->ipa_proto = hh->proto;
-
-	msg->l2h = &hh->data[0];
-
-	/* do a size check on the input */
-	if (ntohs(hh->len) != msgb_l2len(msg)) {
-		LOGP(DLINP, LOGL_ERROR, "Wrong input length?\n");
-		talloc_free(parsed);
-		return NULL;
-	}
-
-	/* analyze sccp down here */
-	if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
-		memset(&result, 0, sizeof(result));
-		if (sccp_parse_header(msg, &result) != 0) {
-			talloc_free(parsed);
-			return 0;
-		}
-
-		if (msg->l3h && msgb_l3len(msg) < 3) {
-			LOGP(DNAT, LOGL_ERROR, "Not enough space or GSM payload\n");
-			talloc_free(parsed);
-			return 0;
-		}
-
-		parsed->sccp_type = sccp_determine_msg_type(msg);
-		parsed->src_local_ref = result.source_local_reference;
-		parsed->dest_local_ref = result.destination_local_reference;
-		if (parsed->dest_local_ref)
-			parsed->original_dest_ref = *parsed->dest_local_ref;
-		parsed->called_ssn = result.called.ssn;
-		parsed->calling_ssn = result.calling.ssn;
-
-		/* in case of connection confirm we have no payload */
-		if (msg->l3h) {
-			parsed->bssap = msg->l3h[0];
-			parsed->gsm_type = msg->l3h[2];
-		}
-	}
-
-	return parsed;
-}
-
-int bsc_nat_filter_ipa(int dir, struct msgb *msg, struct bsc_nat_parsed *parsed)
-{
-	int i;
-
-	/* go through the blacklist now */
-	for (i = 0; i < ARRAY_SIZE(black_list); ++i) {
-		/* ignore the rule? */
-		if (black_list[i].filter_dir != FILTER_TO_BOTH
-		    && black_list[i].filter_dir != dir)
-			continue;
-
-		/* the proto is not blacklisted */
-		if (black_list[i].ipa_proto != ALLOW_ANY
-		    && black_list[i].ipa_proto != parsed->ipa_proto)
-			continue;
-
-		if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
-			/* the SSN is not blacklisted */
-			if (black_list[i].dest_ssn != ALLOW_ANY
-			    && black_list[i].dest_ssn != parsed->called_ssn)
-				continue;
-
-			/* bssap */
-			if (black_list[i].bssap != ALLOW_ANY
-			    && black_list[i].bssap != parsed->bssap)
-				continue;
-
-			/* gsm */
-			if (black_list[i].gsm != ALLOW_ANY
-			    && black_list[i].gsm != parsed->gsm_type)
-				continue;
-
-			/* blacklisted */
-			LOGP(DNAT, LOGL_INFO, "Blacklisted with rule %d\n", i);
-			return 1;
-		} else {
-			/* blacklisted, we have no content sniffing yet */
-			LOGP(DNAT, LOGL_INFO, "Blacklisted with rule %d\n", i);
-			return 1;
-		}
-	}
-
-	/* go through the whitelust now */
-	for (i = 0; i < ARRAY_SIZE(white_list); ++i) {
-		/* ignore the rule? */
-		if (white_list[i].filter_dir != FILTER_TO_BOTH
-		    && white_list[i].filter_dir != dir)
-			continue;
-
-		/* the proto is not whitelisted */
-		if (white_list[i].ipa_proto != ALLOW_ANY
-		    && white_list[i].ipa_proto != parsed->ipa_proto)
-			continue;
-
-		if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
-			/* the SSN is not whitelisted */
-			if (white_list[i].dest_ssn != ALLOW_ANY
-			    && white_list[i].dest_ssn != parsed->called_ssn)
-				continue;
-
-			/* bssap */
-			if (white_list[i].bssap != ALLOW_ANY
-			    && white_list[i].bssap != parsed->bssap)
-				continue;
-
-			/* gsm */
-			if (white_list[i].gsm != ALLOW_ANY
-			    && white_list[i].gsm != parsed->gsm_type)
-				continue;
-
-			/* whitelisted */
-			LOGP(DNAT, LOGL_INFO, "Whitelisted with rule %d\n", i);
-			return 0;
-		} else {
-			/* whitelisted */
-			return 0;
-		}
-	}
-
-	return 1;
-}
diff --git a/src/osmo-bsc_nat/bsc_mgcp_utils.c b/src/osmo-bsc_nat/bsc_mgcp_utils.c
deleted file mode 100644
index 7df362f..0000000
--- a/src/osmo-bsc_nat/bsc_mgcp_utils.c
+++ /dev/null
@@ -1,1151 +0,0 @@
-/**
- * This file contains helper routines for MGCP Gateway handling.
- *
- * The first thing to remember is that each BSC has its own namespace/range
- * of endpoints. Whenever a BSSMAP ASSIGNMENT REQUEST is received this code
- * will be called to select an endpoint on the BSC. The mapping from original
- * multiplex/timeslot to BSC multiplex'/timeslot' will be stored.
- *
- * The second part is to take messages on the public MGCP GW interface
- * and forward them to the right BSC. This requires the MSC to first
- * assign the timeslot. This assumption has been true so far. We are using
- * the policy_cb of the MGCP protocol code to decide if the request should
- * be immediately answered or delayed. An extension "Z: noanswer" is used
- * to request the BSC to not respond. This is saving some bytes of bandwidth
- * and as we are using TCP to forward the message we know it will arrive.
- * The mgcp_do_read method reads these messages and hands them to the protocol
- * parsing code which will call the mentioned policy_cb. The bsc_mgcp_forward
- * method is used on the way back from the BSC to the network.
- *
- * The third part is to patch messages forwarded to the BSC. This includes
- * the endpoint number, the ports to be used inside the SDP file and maybe
- * some other bits.
- *
- */
-/*
- * (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/>.
- *
- */
-
-#include <openbsc/bsc_nat.h>
-#include <openbsc/bsc_nat_callstats.h>
-#include <openbsc/bsc_nat_sccp.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/debug.h>
-#include <openbsc/ipaccess.h>
-#include <openbsc/mgcp.h>
-#include <openbsc/mgcp_internal.h>
-#include <openbsc/osmux.h>
-
-#include <osmocom/ctrl/control_cmd.h>
-
-#include <osmocom/sccp/sccp.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/gsm/gsm0808.h>
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <errno.h>
-#include <unistd.h>
-
-static void send_direct(struct bsc_nat *nat, struct msgb *output)
-{
-	if (osmo_wqueue_enqueue(&nat->mgcp_cfg->gw_fd, output) != 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to queue MGCP msg.\n");
-		msgb_free(output);
-	}
-}
-
-static void mgcp_queue_for_call_agent(struct bsc_nat *nat, struct msgb *output)
-{
-	if (nat->mgcp_ipa)
-		bsc_nat_send_mgcp_to_msc(nat, output);
-	else
-		send_direct(nat, output);
-}
-
-int bsc_mgcp_nr_multiplexes(int max_endpoints)
-{
-	int div = max_endpoints / 32;
-
-	if ((max_endpoints % 32) != 0)
-		div += 1;
-
-	return div;
-}
-
-static int bsc_init_endps_if_needed(struct bsc_connection *con)
-{
-	int multiplexes;
-
-	/* we have done that */
-	if (con->_endpoint_status)
-		return 0;
-
-	/* we have no config... */
-	if (!con->cfg)
-		return -1;
-
-	multiplexes = bsc_mgcp_nr_multiplexes(con->cfg->max_endpoints);
-	con->number_multiplexes = multiplexes;
-	con->max_endpoints = con->cfg->max_endpoints;
-	con->_endpoint_status = talloc_zero_array(con, char, 32 * multiplexes + 1);
-	return con->_endpoint_status == NULL;
-}
-
-static int bsc_assign_endpoint(struct bsc_connection *bsc, struct nat_sccp_connection *con)
-{
-	int multiplex;
-	int timeslot;
-	const int number_endpoints = bsc->max_endpoints;
-	int i;
-
-	mgcp_endpoint_to_timeslot(bsc->last_endpoint, &multiplex, &timeslot);
-	timeslot += 1;
-
-	for (i = 0; i < number_endpoints; ++i) {
-		int endpoint;
-
-		/* Wrap around timeslots */
-		if (timeslot == 0)
-			timeslot = 1;
-
-		if (timeslot == 0x1f) {
-			timeslot = 1;
-			multiplex += 1;
-		}
-
-		/* Wrap around the multiplex */
-		if (multiplex >= bsc->number_multiplexes)
-			multiplex = 0;
-
-		endpoint = mgcp_timeslot_to_endpoint(multiplex, timeslot);
-
-		/* Now check if we are allowed to assign this one */
-		if (endpoint >= bsc->max_endpoints) {
-			multiplex = 0;
-			timeslot = 1;
-			endpoint = mgcp_timeslot_to_endpoint(multiplex, timeslot);
-		}
-
-
-		if (bsc->_endpoint_status[endpoint] == 0) {
-			bsc->_endpoint_status[endpoint] = 1;
-			con->bsc_endp = endpoint;
-			bsc->last_endpoint = endpoint;
-			return 0;
-		}
-
-		timeslot += 1;
-	}
-
-	return -1;
-}
-
-static uint16_t create_cic(int endpoint)
-{
-	int timeslot, multiplex;
-
-	mgcp_endpoint_to_timeslot(endpoint, &multiplex, &timeslot);
-	return (multiplex << 5) | (timeslot & 0x1f);
-}
-
-int bsc_mgcp_assign_patch(struct nat_sccp_connection *con, struct msgb *msg)
-{
-	struct nat_sccp_connection *mcon;
-	struct tlv_parsed tp;
-	uint16_t cic;
-	uint8_t timeslot;
-	uint8_t multiplex;
-	unsigned int endp;
-
-	if (!msg->l3h) {
-		LOGP(DNAT, LOGL_ERROR, "Assignment message should have l3h pointer.\n");
-		return -1;
-	}
-
-	if (msgb_l3len(msg) < 3) {
-		LOGP(DNAT, LOGL_ERROR, "Assignment message has not enough space for GSM0808.\n");
-		return -1;
-	}
-
-	tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 3, msgb_l3len(msg) - 3, 0, 0);
-	if (!TLVP_PRESENT(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE)) {
-		LOGP(DNAT, LOGL_ERROR, "Circuit identity code not found in assignment message.\n");
-		return -1;
-	}
-
-	cic = ntohs(tlvp_val16_unal(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE));
-	timeslot = cic & 0x1f;
-	multiplex = (cic & ~0x1f) >> 5;
-
-
-	endp = mgcp_timeslot_to_endpoint(multiplex, timeslot);
-
-	if (endp >= con->bsc->nat->mgcp_cfg->trunk.number_endpoints) {
-		LOGP(DNAT, LOGL_ERROR,
-			"MSC attempted to assign bad endpoint 0x%x\n",
-			endp);
-		return -1;
-	}
-
-	/* find stale connections using that endpoint */
-	llist_for_each_entry(mcon, &con->bsc->nat->sccp_connections, list_entry) {
-		if (mcon->msc_endp == endp) {
-			LOGP(DNAT, LOGL_ERROR,
-			     "Endpoint %d was assigned to 0x%x and now 0x%x\n",
-			     endp,
-			     sccp_src_ref_to_int(&mcon->patched_ref),
-			     sccp_src_ref_to_int(&con->patched_ref));
-			bsc_mgcp_dlcx(mcon);
-		}
-	}
-
-	con->msc_endp = endp;
-	if (bsc_init_endps_if_needed(con->bsc) != 0)
-		return -1;
-	if (bsc_assign_endpoint(con->bsc, con) != 0)
-		return -1;
-
-	/*
-	 * now patch the message for the new CIC...
-	 * still assumed to be one multiplex only
-	 */
-	cic = htons(create_cic(con->bsc_endp));
-	memcpy((uint8_t *) TLVP_VAL(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE),
-		&cic, sizeof(cic));
-
-	return 0;
-}
-
-static void bsc_mgcp_free_endpoint(struct bsc_nat *nat, int i)
-{
-	if (nat->bsc_endpoints[i].transaction_id) {
-		talloc_free(nat->bsc_endpoints[i].transaction_id);
-		nat->bsc_endpoints[i].transaction_id = NULL;
-	}
-
-	nat->bsc_endpoints[i].transaction_state = 0;
-	nat->bsc_endpoints[i].bsc = NULL;
-}
-
-void bsc_mgcp_free_endpoints(struct bsc_nat *nat)
-{
-	int i;
-
-	for (i = 1; i < nat->mgcp_cfg->trunk.number_endpoints; ++i){
-		bsc_mgcp_free_endpoint(nat, i);
-		mgcp_release_endp(&nat->mgcp_cfg->trunk.endpoints[i]);
-	}
-}
-
-/* send a MDCX where we do not want a response */
-static void bsc_mgcp_send_mdcx(struct bsc_connection *bsc, int port, struct mgcp_endpoint *endp)
-{
-	char buf[2096];
-	int len;
-
-	len = snprintf(buf, sizeof(buf),
-		       "MDCX 23 %x@mgw MGCP 1.0\r\n"
-		       "Z: noanswer\r\n"
-		       "\r\n"
-		       "c=IN IP4 %s\r\n"
-		       "m=audio %d RTP/AVP 255\r\n",
-		       port, mgcp_bts_src_addr(endp),
-		       endp->bts_end.local_port);
-	if (len < 0) {
-		LOGP(DMGCP, LOGL_ERROR, "snprintf for MDCX failed.\n");
-		return;
-	}
-
-	bsc_write_mgcp(bsc, (uint8_t *) buf, len);
-}
-
-static void bsc_mgcp_send_dlcx(struct bsc_connection *bsc, int endpoint, int trans)
-{
-	char buf[2096];
-	int len;
-
-	/*
-	 * The following is a bit of a spec violation. According to the
-	 * MGCP grammar the transaction id is are upto 9 digits but we
-	 * prefix it with an alpha numeric value so we can easily recognize
-	 * it as a response.
-	 */
-	len = snprintf(buf, sizeof(buf),
-		       "DLCX nat-%u %x@mgw MGCP 1.0\r\n",
-			trans, endpoint);
-	if (len < 0) {
-		LOGP(DMGCP, LOGL_ERROR, "snprintf for DLCX failed.\n");
-		return;
-	}
-
-	bsc_write_mgcp(bsc, (uint8_t *) buf, len);
-}
-
-void bsc_mgcp_init(struct nat_sccp_connection *con)
-{
-	con->msc_endp = -1;
-	con->bsc_endp = -1;
-}
-
-/**
- * This code will remember the network side of the audio statistics and
- * once the internal DLCX response arrives this can be combined with the
- * the BSC side and forwarded as a trap.
- */
-static void remember_pending_dlcx(struct nat_sccp_connection *con, uint32_t transaction)
-{
-	struct bsc_nat_call_stats *stats;
-	struct bsc_connection *bsc = con->bsc;
-	struct mgcp_endpoint *endp;
-
-	stats = talloc_zero(bsc, struct bsc_nat_call_stats);
-	if (!stats) {
-		LOGP(DNAT, LOGL_NOTICE,
-			"Failed to allocate statistics for endpoint 0x%x\n",
-			con->msc_endp);
-		return;
-	}
-
-	/* take the endpoint here */
-	endp = &bsc->nat->mgcp_cfg->trunk.endpoints[con->msc_endp];
-
-	stats->remote_ref = con->remote_ref;
-	stats->src_ref = con->patched_ref;
-
-	stats->ci = endp->ci;
-	stats->bts_rtp_port = endp->bts_end.rtp_port;
-	stats->bts_addr = endp->bts_end.addr;
-	stats->net_rtp_port = endp->net_end.rtp_port;
-	stats->net_addr = endp->net_end.addr;
-
-	stats->net_ps = endp->net_end.packets;
-	stats->net_os = endp->net_end.octets;
-	stats->bts_pr = endp->bts_end.packets;
-	stats->bts_or = endp->bts_end.octets;
-	mgcp_state_calc_loss(&endp->bts_state, &endp->bts_end,
-				&stats->bts_expected, &stats->bts_loss);
-	stats->bts_jitter = mgcp_state_calc_jitter(&endp->bts_state);
-
-	stats->trans_id = transaction;
-	stats->msc_endpoint = con->msc_endp;
-
-	/*
-	 * Too many pending requests.. let's remove the first two items.
-	 */
-	if (!llist_empty(&bsc->pending_dlcx) &&
-			bsc->pending_dlcx_count >= bsc->cfg->max_endpoints * 3) {
-		struct bsc_nat_call_stats *tmp;
-		LOGP(DNAT, LOGL_ERROR,
-			"Too many(%d) pending DLCX responses on BSC: %d\n",
-			bsc->pending_dlcx_count, bsc->cfg->nr);
-		bsc->pending_dlcx_count -= 1;
-		tmp = (struct bsc_nat_call_stats *) bsc->pending_dlcx.next;
-		llist_del(&tmp->entry);
-		talloc_free(tmp);
-	}
-
-	bsc->pending_dlcx_count += 1;
-	llist_add_tail(&stats->entry, &bsc->pending_dlcx);
-}
-
-void bsc_mgcp_dlcx(struct nat_sccp_connection *con)
-{
-	/* send a DLCX down the stream */
-	if (con->bsc_endp != -1 && con->bsc->_endpoint_status) {
-		LOGP(DNAT, LOGL_NOTICE,
-			"Endpoint 0x%x was allocated for bsc: %d. Freeing it.\n",
-			con->bsc_endp, con->bsc->cfg->nr);
-		if (con->bsc->_endpoint_status[con->bsc_endp] != 1)
-			LOGP(DNAT, LOGL_ERROR, "Endpoint 0x%x was not in use\n", con->bsc_endp);
-		remember_pending_dlcx(con, con->bsc->next_transaction);
-		con->bsc->_endpoint_status[con->bsc_endp] = 0;
-		bsc_mgcp_send_dlcx(con->bsc, con->bsc_endp, con->bsc->next_transaction++);
-		bsc_mgcp_free_endpoint(con->bsc->nat, con->msc_endp);
-	}
-
-	bsc_mgcp_init(con);
-
-}
-
-/*
- * Search for the pending request
- */
-static void handle_dlcx_response(struct bsc_connection *bsc, struct msgb *msg,
-			int code, const char *transaction)
-{
-	uint32_t trans_id = UINT32_MAX;
-	uint32_t b_ps, b_os, n_pr, n_or, jitter;
-	int loss;
-	struct bsc_nat_call_stats *tmp, *stat = NULL;
-	struct ctrl_cmd *cmd;
-
-	/* parse the transaction identifier */
-	int rc = sscanf(transaction, "nat-%u", &trans_id);
-	if (rc != 1) {
-		LOGP(DNAT, LOGL_ERROR, "Can not parse transaction id: '%s'\n",
-			transaction);
-		return;
-	}
-
-	/* find the answer for the request we made */
-	llist_for_each_entry(tmp, &bsc->pending_dlcx, entry) {
-		if (trans_id != tmp->trans_id)
-			continue;
-
-		stat = tmp;
-		break;
-	}
-
-	if (!stat) {
-		LOGP(DNAT, LOGL_ERROR,
-			"Can not find transaction for: %u\n", trans_id);
-		return;
-	}
-
-	/* attempt to parse the data now */
-	rc = mgcp_parse_stats(msg, &b_ps, &b_os, &n_pr, &n_or, &loss, &jitter);
-	if (rc != 0)
-		LOGP(DNAT, LOGL_ERROR,
-			"Can not parse connection statistics: %d\n", rc);
-
-	/* send a trap now */
-	cmd = ctrl_cmd_create(bsc, CTRL_TYPE_TRAP);
-	if (!cmd) {
-		LOGP(DNAT, LOGL_ERROR,
-			"Creating a ctrl cmd failed.\n");
-		goto free_stat;
-	}
-
-	cmd->id = "0";
-	cmd->variable = talloc_asprintf(cmd, "net.0.bsc.%d.call_stats.v2",
-				bsc->cfg->nr);
-	cmd->reply = talloc_asprintf(cmd,
-			"mg_ip_addr=%s,mg_port=%d,",
-			inet_ntoa(stat->net_addr),
-			stat->net_rtp_port);
-	cmd->reply = talloc_asprintf_append(cmd->reply,
-			"endpoint_ip_addr=%s,endpoint_port=%d,",
-			inet_ntoa(stat->bts_addr),
-			stat->bts_rtp_port);
-	cmd->reply = talloc_asprintf_append(cmd->reply,
-			"nat_pkt_in=%u,nat_pkt_out=%u,"
-			"nat_bytes_in=%u,nat_bytes_out=%u,"
-			"nat_jitter=%u,nat_pkt_lost=%d,",
-			stat->bts_pr, stat->net_ps,
-			stat->bts_or, stat->net_os,
-			stat->bts_jitter, stat->bts_loss);
-	cmd->reply = talloc_asprintf_append(cmd->reply,
-			"bsc_pkt_in=%u,bsc_pkt_out=%u,"
-			"bsc_bytes_in=%u,bsc_bytes_out=%u,"
-			"bsc_jitter=%u,bsc_pkt_lost=%d,",
-			n_pr, b_ps,
-			n_or, b_os,
-			jitter, loss);
-	cmd->reply = talloc_asprintf_append(cmd->reply,
-			"sccp_src_ref=%u,sccp_dst_ref=%u",
-			sccp_src_ref_to_int(&stat->src_ref),
-			sccp_src_ref_to_int(&stat->remote_ref));
-
-	/* send it and be done */
-	ctrl_cmd_send_to_all(bsc->nat->ctrl, cmd);
-	talloc_free(cmd);
-
-free_stat:
-	bsc->pending_dlcx_count -= 1;
-	llist_del(&stat->entry);
-	talloc_free(stat);
-}
-
-
-struct nat_sccp_connection *bsc_mgcp_find_con(struct bsc_nat *nat, int endpoint)
-{
-	struct nat_sccp_connection *con = NULL;
-	struct nat_sccp_connection *sccp;
-
-	llist_for_each_entry(sccp, &nat->sccp_connections, list_entry) {
-		if (sccp->msc_endp == -1)
-			continue;
-		if (sccp->msc_endp != endpoint)
-			continue;
-
-		con = sccp;
-	}
-
-	if (con)
-		return con;
-
-	LOGP(DMGCP, LOGL_ERROR,
-		"Failed to find the connection for endpoint: 0x%x\n", endpoint);
-	return NULL;
-}
-
-static int nat_osmux_only(struct mgcp_config *mgcp_cfg, struct bsc_config *bsc_cfg)
-{
-	if (mgcp_cfg->osmux == OSMUX_USAGE_ONLY)
-		return 1;
-	if (bsc_cfg->osmux == OSMUX_USAGE_ONLY)
-		return 1;
-	return 0;
-}
-
-static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int state, const char *transaction_id)
-{
-	struct bsc_nat *nat;
-	struct bsc_endpoint *bsc_endp;
-	struct nat_sccp_connection *sccp;
-	struct mgcp_endpoint *mgcp_endp;
-	struct msgb *bsc_msg;
-
-	nat = tcfg->cfg->data;
-	bsc_endp = &nat->bsc_endpoints[endpoint];
-	mgcp_endp = &nat->mgcp_cfg->trunk.endpoints[endpoint];
-
-	if (bsc_endp->transaction_id) {
-		LOGP(DMGCP, LOGL_ERROR, "Endpoint 0x%x had pending transaction: '%s'\n",
-		     endpoint, bsc_endp->transaction_id);
-		talloc_free(bsc_endp->transaction_id);
-		bsc_endp->transaction_id = NULL;
-		bsc_endp->transaction_state = 0;
-	}
-	bsc_endp->bsc = NULL;
-
-	sccp = bsc_mgcp_find_con(nat, endpoint);
-
-	if (!sccp) {
-		LOGP(DMGCP, LOGL_ERROR, "Did not find BSC for change on endpoint: 0x%x state: %d\n", endpoint, state);
-
-		switch (state) {
-		case MGCP_ENDP_CRCX:
-			return MGCP_POLICY_REJECT;
-			break;
-		case MGCP_ENDP_DLCX:
-			return MGCP_POLICY_CONT;
-			break;
-		case MGCP_ENDP_MDCX:
-			return MGCP_POLICY_CONT;
-			break;
-		default:
-			LOGP(DMGCP, LOGL_FATAL, "Unhandled state: %d\n", state);
-			return MGCP_POLICY_CONT;
-			break;
-		}
-	}
-
-	/* Allocate a Osmux circuit ID */
-	if (state == MGCP_ENDP_CRCX) {
-		if (nat->mgcp_cfg->osmux && sccp->bsc->cfg->osmux) {
-			osmux_allocate_cid(mgcp_endp);
-			if (mgcp_endp->osmux.allocated_cid < 0 &&
-				nat_osmux_only(nat->mgcp_cfg, sccp->bsc->cfg)) {
-				LOGP(DMGCP, LOGL_ERROR,
-					"Rejecting usage of endpoint\n");
-				return MGCP_POLICY_REJECT;
-			}
-		}
-	}
-
-	/* we need to generate a new and patched message */
-	bsc_msg = bsc_mgcp_rewrite((char *) nat->mgcp_msg, nat->mgcp_length,
-				   sccp->bsc_endp, mgcp_bts_src_addr(mgcp_endp),
-				   mgcp_endp->bts_end.local_port,
-				   mgcp_endp->osmux.allocated_cid,
-				   &mgcp_endp->net_end.codec.payload_type,
-				   nat->sdp_ensure_amr_mode_set);
-	if (!bsc_msg) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to patch the msg.\n");
-		return MGCP_POLICY_CONT;
-	}
-
-
-	bsc_endp->transaction_id = talloc_strdup(nat, transaction_id);
-	bsc_endp->transaction_state = state;
-	bsc_endp->bsc = sccp->bsc;
-
-	/* we need to update some bits */
-	if (state == MGCP_ENDP_CRCX) {
-		struct sockaddr_in sock;
-
-		/* Annotate the allocated Osmux CID until the bsc confirms that
-		 * it agrees to use Osmux for this voice flow.
-		 */
-		if (mgcp_endp->osmux.allocated_cid >= 0 &&
-		    mgcp_endp->osmux.state != OSMUX_STATE_ENABLED) {
-			mgcp_endp->osmux.state = OSMUX_STATE_NEGOTIATING;
-			mgcp_endp->osmux.cid = mgcp_endp->osmux.allocated_cid;
-		}
-
-		socklen_t len = sizeof(sock);
-		if (getpeername(sccp->bsc->write_queue.bfd.fd, (struct sockaddr *) &sock, &len) != 0) {
-			LOGP(DMGCP, LOGL_ERROR, "Can not get the peername...%d/%s\n",
-			      errno, strerror(errno));
-		} else {
-			mgcp_endp->bts_end.addr = sock.sin_addr;
-		}
-
-		/* send the message and a fake MDCX to force sending of a dummy packet */
-		bsc_write(sccp->bsc, bsc_msg, IPAC_PROTO_MGCP_OLD);
-		bsc_mgcp_send_mdcx(sccp->bsc, sccp->bsc_endp, mgcp_endp);
-		return MGCP_POLICY_DEFER;
-	} else if (state == MGCP_ENDP_DLCX) {
-		/* we will free the endpoint now and send a DLCX to the BSC */
-		msgb_free(bsc_msg);
-		bsc_mgcp_dlcx(sccp);
-
-		/* libmgcp clears the MGCP endpoint for us */
-		if (mgcp_endp->osmux.state == OSMUX_STATE_ENABLED)
-			osmux_release_cid(mgcp_endp);
-
-		return MGCP_POLICY_CONT;
-	} else {
-		bsc_write(sccp->bsc, bsc_msg, IPAC_PROTO_MGCP_OLD);
-		return MGCP_POLICY_DEFER;
-	}
-}
-
-/*
- * We do have a failure, free data downstream..
- */
-static void free_chan_downstream(struct mgcp_endpoint *endp, struct bsc_endpoint *bsc_endp,
-				 struct bsc_connection *bsc)
-{
-	LOGP(DMGCP, LOGL_ERROR, "No CI, freeing endpoint 0x%x in state %d\n",
-		ENDPOINT_NUMBER(endp), bsc_endp->transaction_state);
-
-	/* if a CRCX failed... send a DLCX down the stream */
-	if (bsc_endp->transaction_state == MGCP_ENDP_CRCX) {
-		struct nat_sccp_connection *con;
-		con = bsc_mgcp_find_con(bsc->nat, ENDPOINT_NUMBER(endp));
-		if (!con) {
-			LOGP(DMGCP, LOGL_ERROR,
-				"No SCCP connection for endp 0x%x\n",
-				ENDPOINT_NUMBER(endp));
-		} else {
-			if (con->bsc == bsc) {
-				bsc_mgcp_send_dlcx(bsc, con->bsc_endp, con->bsc->next_transaction++);
-			} else {
-				LOGP(DMGCP, LOGL_ERROR,
-					"Endpoint belongs to a different BSC\n");
-			}
-		}
-	}
-
-	bsc_mgcp_free_endpoint(bsc->nat, ENDPOINT_NUMBER(endp));
-	mgcp_release_endp(endp);
-}
-
-static void bsc_mgcp_osmux_confirm(struct mgcp_endpoint *endp, const char *str)
-{
-	unsigned int osmux_cid;
-	char *res;
-
-	res = strstr(str, "X-Osmux: ");
-	if (!res) {
-		LOGP(DMGCP, LOGL_INFO,
-		     "BSC doesn't want to use Osmux, failing back to RTP\n");
-		goto err;
-	}
-
-	if (sscanf(res, "X-Osmux: %u", &osmux_cid) != 1) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to parse Osmux CID '%s'\n",
-		     str);
-		goto err;
-	}
-
-	if (endp->osmux.cid != osmux_cid) {
-		LOGP(DMGCP, LOGL_ERROR,
-		     "BSC sent us wrong CID %u, we expected %u",
-		     osmux_cid, endp->osmux.cid);
-		goto err;
-	}
-
-	LOGP(DMGCP, LOGL_NOTICE, "bsc accepted to use Osmux (cid=%u)\n",
-	     osmux_cid);
-	endp->osmux.state = OSMUX_STATE_ACTIVATING;
-	return;
-err:
-	osmux_release_cid(endp);
-	endp->osmux.state = OSMUX_STATE_DISABLED;
-}
-
-/*
- * We have received a msg from the BSC. We will see if we know
- * this transaction and if it belongs to the BSC. Then we will
- * need to patch the content to point to the local network and we
- * need to update the I: that was assigned by the BSS.
- *
- * Only responses to CRCX and DLCX should arrive here. The DLCX
- * needs to be handled specially to combine the two statistics.
- */
-void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg)
-{
-	struct msgb *output;
-	struct bsc_endpoint *bsc_endp = NULL;
-	struct mgcp_endpoint *endp = NULL;
-	int i, code;
-	char transaction_id[60];
-
-	/* Some assumption that our buffer is big enough.. and null terminate */
-	if (msgb_l2len(msg) > 2000) {
-		LOGP(DMGCP, LOGL_ERROR, "MGCP message too long.\n");
-		return;
-	}
-
-	msg->l2h[msgb_l2len(msg)] = '\0';
-
-	if (bsc_mgcp_parse_response((const char *) msg->l2h, &code, transaction_id) != 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to parse response code.\n");
-		return;
-	}
-
-	for (i = 1; i < bsc->nat->mgcp_cfg->trunk.number_endpoints; ++i) {
-		if (bsc->nat->bsc_endpoints[i].bsc != bsc)
-			continue;
-		/* no one listening? a bug? */
-		if (!bsc->nat->bsc_endpoints[i].transaction_id)
-			continue;
-		if (strcmp(transaction_id, bsc->nat->bsc_endpoints[i].transaction_id) != 0)
-			continue;
-
-		endp = &bsc->nat->mgcp_cfg->trunk.endpoints[i];
-		bsc_endp = &bsc->nat->bsc_endpoints[i];
-		break;
-	}
-
-	if (!bsc_endp && strncmp("nat-", transaction_id, 4) == 0) {
-		handle_dlcx_response(bsc, msg, code, transaction_id);
-		return;
-	}
-
-	if (!bsc_endp) {
-		LOGP(DMGCP, LOGL_ERROR, "Could not find active endpoint: %s for msg: '%s'\n",
-		     transaction_id, (const char *) msg->l2h);
-		return;
-	}
-
-	endp->ci = bsc_mgcp_extract_ci((const char *) msg->l2h);
-	if (endp->ci == CI_UNUSED) {
-		free_chan_downstream(endp, bsc_endp, bsc);
-		return;
-	}
-
-	if (endp->osmux.state == OSMUX_STATE_NEGOTIATING)
-		bsc_mgcp_osmux_confirm(endp, (const char *) msg->l2h);
-
-	/* If we require osmux and it is disabled.. fail */
-	if (nat_osmux_only(bsc->nat->mgcp_cfg, bsc->cfg) &&
-		endp->osmux.state == OSMUX_STATE_DISABLED) {
-		LOGP(DMGCP, LOGL_ERROR,
-			"Failed to activate osmux endpoint 0x%x\n",
-			ENDPOINT_NUMBER(endp));
-		free_chan_downstream(endp, bsc_endp, bsc);
-		return;
-	}
-
-	/* free some stuff */
-	talloc_free(bsc_endp->transaction_id);
-	bsc_endp->transaction_id = NULL;
-	bsc_endp->transaction_state = 0;
-
-	/*
-	 * rewrite the information. In case the endpoint was deleted
-	 * there should be nothing for us to rewrite so putting endp->rtp_port
-	 * with the value of 0 should be no problem.
-	 */
-	output = bsc_mgcp_rewrite((char * ) msg->l2h, msgb_l2len(msg), -1,
-				  mgcp_net_src_addr(endp),
-				  endp->net_end.local_port, -1,
-				  &endp->bts_end.codec.payload_type,
-				  bsc->nat->sdp_ensure_amr_mode_set);
-	if (!output) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to rewrite MGCP msg.\n");
-		return;
-	}
-
-	mgcp_queue_for_call_agent(bsc->nat, output);
-}
-
-int bsc_mgcp_parse_response(const char *str, int *code, char transaction[60])
-{
-	int rc;
-	/* we want to parse two strings */
-	rc = sscanf(str, "%3d %59s\n", code, transaction) != 2;
-	transaction[59] = '\0';
-	return rc;
-}
-
-uint32_t bsc_mgcp_extract_ci(const char *str)
-{
-	unsigned int ci;
-	char *res = strstr(str, "I: ");
-	if (!res) {
-		LOGP(DMGCP, LOGL_ERROR, "No CI in msg '%s'\n", str);
-		return CI_UNUSED;
-	}
-
-	if (sscanf(res, "I: %u", &ci) != 1) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to parse CI in msg '%s'\n", str);
-		return CI_UNUSED;
-	}
-
-	return ci;
-}
-
-/**
- * Create a new MGCPCommand based on the input and endpoint from a message
- */
-static void patch_mgcp(struct msgb *output, const char *op, const char *tok,
-		       int endp, int len, int cr, int osmux_cid)
-{
-	int slen;
-	int ret;
-	char buf[40];
-	char osmux_extension[strlen("\nX-Osmux: 255") + 1];
-
-	buf[0] = buf[39] = '\0';
-	ret = sscanf(tok, "%*s %s", buf);
-	if (ret != 1) {
-		LOGP(DMGCP, LOGL_ERROR,
-			"Failed to find Endpoint in: %s\n", tok);
-		return;
-	}
-
-	if (osmux_cid >= 0)
-		sprintf(osmux_extension, "\nX-Osmux: %u", osmux_cid & 0xff);
-	else
-		osmux_extension[0] = '\0';
-
-	slen = sprintf((char *) output->l3h, "%s %s %x@mgw MGCP 1.0%s%s",
-			op, buf, endp, osmux_extension, cr ? "\r\n" : "\n");
-	output->l3h = msgb_put(output, slen);
-}
-
-/* we need to replace some strings... */
-struct msgb *bsc_mgcp_rewrite(char *input, int length, int endpoint,
-			      const char *ip, int port, int osmux_cid,
-			      int *first_payload_type, int ensure_mode_set)
-{
-	static const char crcx_str[] = "CRCX ";
-	static const char dlcx_str[] = "DLCX ";
-	static const char mdcx_str[] = "MDCX ";
-
-	static const char ip_str[] = "c=IN IP4 ";
-	static const char aud_str[] = "m=audio ";
-	static const char fmt_str[] = "a=fmtp:";
-
-	char buf[128];
-	char *running, *token;
-	struct msgb *output;
-
-	/* keep state to add the a=fmtp line */
-	int found_fmtp = 0;
-	int payload = -1;
-	int cr = 1;
-
-	if (length > 4096 - 256) {
-		LOGP(DMGCP, LOGL_ERROR, "Input is too long.\n");
-		return NULL;
-	}
-
-	output = msgb_alloc_headroom(4096, 128, "MGCP rewritten");
-	if (!output) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to allocate new MGCP msg.\n");
-		return NULL;
-	}
-
-	running = input;
-	output->l2h = output->data;
-	output->l3h = output->l2h;
-	for (token = strsep(&running, "\n"); running; token = strsep(&running, "\n")) {
-		int len = strlen(token);
-		cr = len > 0 && token[len - 1] == '\r';
-
-		if (strncmp(crcx_str, token, (sizeof crcx_str) - 1) == 0) {
-			patch_mgcp(output, "CRCX", token, endpoint, len, cr, osmux_cid);
-		} else if (strncmp(dlcx_str, token, (sizeof dlcx_str) - 1) == 0) {
-			patch_mgcp(output, "DLCX", token, endpoint, len, cr, -1);
-		} else if (strncmp(mdcx_str, token, (sizeof mdcx_str) - 1) == 0) {
-			patch_mgcp(output, "MDCX", token, endpoint, len, cr, -1);
-		} else if (strncmp(ip_str, token, (sizeof ip_str) - 1) == 0) {
-			output->l3h = msgb_put(output, strlen(ip_str));
-			memcpy(output->l3h, ip_str, strlen(ip_str));
-			output->l3h = msgb_put(output, strlen(ip));
-			memcpy(output->l3h, ip, strlen(ip));
-
-			if (cr) {
-				output->l3h = msgb_put(output, 2);
-				output->l3h[0] = '\r';
-				output->l3h[1] = '\n';
-			} else {
-				output->l3h = msgb_put(output, 1);
-				output->l3h[0] = '\n';
-			}
-		} else if (strncmp(aud_str, token, (sizeof aud_str) - 1) == 0) {
-			int offset;
-			if (sscanf(token, "m=audio %*d RTP/AVP %n%d", &offset, &payload) != 1) {
-				LOGP(DMGCP, LOGL_ERROR, "Could not parsed audio line.\n");
-				msgb_free(output);
-				return NULL;
-			}
-
-			snprintf(buf, sizeof(buf)-1, "m=audio %d RTP/AVP %s\n",
-				 port, &token[offset]);
-			buf[sizeof(buf)-1] = '\0';
-
-			output->l3h = msgb_put(output, strlen(buf));
-			memcpy(output->l3h, buf, strlen(buf));
-		} else if (strncmp(fmt_str, token, (sizeof fmt_str) - 1) == 0) {
-			found_fmtp = 1;
-			goto copy;
-		} else {
-copy:
-			output->l3h = msgb_put(output, len + 1);
-			memcpy(output->l3h, token, len);
-			output->l3h[len] = '\n';
-		}
-	}
-
-	/*
-	 * the above code made sure that we have 128 bytes lefts. So we can
-	 * safely append another line.
-	 */
-	if (ensure_mode_set && !found_fmtp && payload != -1) {
-		snprintf(buf, sizeof(buf) - 1, "a=fmtp:%d mode-set=2%s",
-			payload, cr ? "\r\n" : "\n");
-		buf[sizeof(buf) - 1] = '\0';
-		output->l3h = msgb_put(output, strlen(buf));
-		memcpy(output->l3h, buf, strlen(buf));
-	}
-
-	if (payload != -1 && first_payload_type)
-		*first_payload_type = payload;
-
-	return output;
-}
-
-/*
- * This comes from the MSC and we will now parse it. The caller needs
- * to free the msgb.
- */
-void bsc_nat_handle_mgcp(struct bsc_nat *nat, struct msgb *msg)
-{
-	struct msgb *resp;
-
-	if (!nat->mgcp_ipa) {
-		LOGP(DMGCP, LOGL_ERROR, "MGCP message not allowed on IPA.\n");
-		return;
-	}
-
-	if (msgb_l2len(msg) > sizeof(nat->mgcp_msg) - 1) {
-		LOGP(DMGCP, LOGL_ERROR, "MGCP msg too big for handling.\n");
-		return;
-	}
-
-	memcpy(nat->mgcp_msg, msg->l2h, msgb_l2len(msg));
-	nat->mgcp_length = msgb_l2len(msg);
-	nat->mgcp_msg[nat->mgcp_length] = '\0';
-
-	/* now handle the message */
-	resp = mgcp_handle_message(nat->mgcp_cfg, msg);
-
-	/* we do have a direct answer... e.g. AUEP */
-	if (resp)
-		mgcp_queue_for_call_agent(nat, resp);
-
-	return;
-}
-
-static int mgcp_do_read(struct osmo_fd *fd)
-{
-	struct bsc_nat *nat;
-	struct msgb *msg, *resp;
-	int rc;
-
-	nat = fd->data;
-
-	rc = read(fd->fd, nat->mgcp_msg, sizeof(nat->mgcp_msg) - 1);
-	if (rc <= 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to read errno: %d\n", errno);
-		return -1;
-	}
-
-	nat->mgcp_msg[rc] = '\0';
-	nat->mgcp_length = rc;
-
-	msg = msgb_alloc(sizeof(nat->mgcp_msg), "MGCP GW Read");
-	if (!msg) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to create buffer.\n");
-		return -1;
-	}
-
-	msg->l2h = msgb_put(msg, rc);
-	memcpy(msg->l2h, nat->mgcp_msg, msgb_l2len(msg));
-	resp = mgcp_handle_message(nat->mgcp_cfg, msg);
-	msgb_free(msg);
-
-	/* we do have a direct answer... e.g. AUEP */
-	if (resp)
-		mgcp_queue_for_call_agent(nat, resp);
-
-	return 0;
-}
-
-static int mgcp_do_write(struct osmo_fd *bfd, struct msgb *msg)
-{
-	int rc;
-
-	rc = write(bfd->fd, msg->data, msg->len);
-
-	if (rc != msg->len) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to write msg to MGCP CallAgent.\n");
-		return -1;
-	}
-
-	return rc;
-}
-
-static int init_mgcp_socket(struct bsc_nat *nat, struct mgcp_config *cfg)
-{
-	struct sockaddr_in addr;
-	int on;
-
-	cfg->gw_fd.bfd.fd = socket(AF_INET, SOCK_DGRAM, 0);
-	if (cfg->gw_fd.bfd.fd < 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to create MGCP socket. errno: %d\n", errno);
-		return -1;
-	}
-
-	on = 1;
-	setsockopt(cfg->gw_fd.bfd.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sin_family = AF_INET;
-	addr.sin_port = htons(cfg->source_port);
-	inet_aton(cfg->source_addr, &addr.sin_addr);
-
-	if (bind(cfg->gw_fd.bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to bind on %s:%d errno: %d\n",
-		     cfg->source_addr, cfg->source_port, errno);
-		close(cfg->gw_fd.bfd.fd);
-		cfg->gw_fd.bfd.fd = -1;
-		return -1;
-	}
-
-	addr.sin_port = htons(2727);
-	inet_aton(cfg->call_agent_addr, &addr.sin_addr);
-	if (connect(cfg->gw_fd.bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to connect to: '%s'. errno: %d\n",
-		     cfg->call_agent_addr, errno);
-		close(cfg->gw_fd.bfd.fd);
-		cfg->gw_fd.bfd.fd = -1;
-		return -1;
-	}
-
-	osmo_wqueue_init(&cfg->gw_fd, 10);
-	cfg->gw_fd.bfd.when = BSC_FD_READ;
-	cfg->gw_fd.bfd.data = nat;
-	cfg->gw_fd.read_cb = mgcp_do_read;
-	cfg->gw_fd.write_cb = mgcp_do_write;
-
-	if (osmo_fd_register(&cfg->gw_fd.bfd) != 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to register MGCP fd.\n");
-		close(cfg->gw_fd.bfd.fd);
-		cfg->gw_fd.bfd.fd = -1;
-		return -1;
-	}
-
-	return 0;
-}
-
-int bsc_mgcp_nat_init(struct bsc_nat *nat)
-{
-	struct mgcp_config *cfg = nat->mgcp_cfg;
-
-	if (!cfg->call_agent_addr) {
-		LOGP(DMGCP, LOGL_ERROR, "The BSC nat requires the call agent ip to be set.\n");
-		return -1;
-	}
-
-	if (cfg->bts_ip) {
-		LOGP(DMGCP, LOGL_ERROR, "Do not set the BTS ip for the nat.\n");
-		return -1;
-	}
-
-	/* initialize the MGCP socket */
-	if (!nat->mgcp_ipa) {
-		int rc =  init_mgcp_socket(nat, cfg);
-		if (rc != 0)
-			return rc;
-	}
-
-
-	/* some more MGCP config handling */
-	cfg->data = nat;
-	cfg->policy_cb = bsc_mgcp_policy_cb;
-
-	if (cfg->bts_ip)
-		talloc_free(cfg->bts_ip);
-	cfg->bts_ip = "";
-
-	nat->bsc_endpoints = talloc_zero_array(nat,
-					       struct bsc_endpoint,
-					       cfg->trunk.number_endpoints + 1);
-	if (!nat->bsc_endpoints) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to allocate nat endpoints\n");
-		close(cfg->gw_fd.bfd.fd);
-		cfg->gw_fd.bfd.fd = -1;
-		return -1;
-	}
-
-	if (mgcp_reset_transcoder(cfg) < 0) {
-		LOGP(DMGCP, LOGL_ERROR, "Failed to send packet to the transcoder.\n");
-		talloc_free(nat->bsc_endpoints);
-		nat->bsc_endpoints = NULL;
-		close(cfg->gw_fd.bfd.fd);
-		cfg->gw_fd.bfd.fd = -1;
-		return -1;
-	}
-
-	return 0;
-}
-
-void bsc_mgcp_clear_endpoints_for(struct bsc_connection *bsc)
-{
-	struct rate_ctr *ctr = NULL;
-	int i;
-
-	if (bsc->cfg)
-		ctr = &bsc->cfg->stats.ctrg->ctr[BCFG_CTR_DROPPED_CALLS];
-
-	for (i = 1; i < bsc->nat->mgcp_cfg->trunk.number_endpoints; ++i) {
-		struct bsc_endpoint *bsc_endp = &bsc->nat->bsc_endpoints[i];
-
-		if (bsc_endp->bsc != bsc)
-			continue;
-
-		if (ctr)
-			rate_ctr_inc(ctr);
-
-		bsc_mgcp_free_endpoint(bsc->nat, i);
-		mgcp_release_endp(&bsc->nat->mgcp_cfg->trunk.endpoints[i]);
-	}
-}
diff --git a/src/osmo-bsc_nat/bsc_nat.c b/src/osmo-bsc_nat/bsc_nat.c
deleted file mode 100644
index 401288d..0000000
--- a/src/osmo-bsc_nat/bsc_nat.c
+++ /dev/null
@@ -1,1739 +0,0 @@
-/* BSC Multiplexer/NAT */
-
-/*
- * (C) 2010-2013 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2013 by On-Waves
- * (C) 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/>.
- *
- */
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <libgen.h>
-
-#define _GNU_SOURCE
-#include <getopt.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/bsc_msc.h>
-#include <openbsc/bsc_nat.h>
-#include <openbsc/bsc_nat_sccp.h>
-#include <openbsc/bsc_msg_filter.h>
-#include <openbsc/ipaccess.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/socket.h>
-#include <openbsc/vty.h>
-
-#include <osmocom/ctrl/control_cmd.h>
-#include <osmocom/ctrl/control_if.h>
-#include <osmocom/ctrl/ports.h>
-#include <osmocom/ctrl/control_vty.h>
-
-#include <osmocom/crypt/auth.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/stats.h>
-
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/gsm/gsm0808.h>
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-
-#include <osmocom/vty/telnet_interface.h>
-#include <osmocom/vty/vty.h>
-#include <osmocom/vty/logging.h>
-#include <osmocom/vty/stats.h>
-#include <osmocom/vty/ports.h>
-
-#include <osmocom/sccp/sccp.h>
-
-#include <osmocom/abis/ipa.h>
-
-#include <openssl/rand.h>
-
-#include "../../bscconfig.h"
-
-#define SCCP_CLOSE_TIME 20
-#define SCCP_CLOSE_TIME_TIMEOUT 19
-
-static const char *config_file = "bsc-nat.cfg";
-static struct in_addr local_addr;
-static struct osmo_fd bsc_listen;
-static const char *msc_ip = NULL;
-static struct osmo_timer_list sccp_close;
-static int daemonize = 0;
-
-const char *openbsc_copyright =
-	"Copyright (C) 2010 Holger Hans Peter Freyther and On-Waves\r\n"
-	"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
-	"This is free software: you are free to change and redistribute it.\r\n"
-	"There is NO WARRANTY, to the extent permitted by law.\r\n";
-
-static struct bsc_nat *nat;
-static void bsc_send_data(struct bsc_connection *bsc, const uint8_t *data, unsigned int length, int);
-static void msc_send_reset(struct bsc_msc_connection *con);
-static void bsc_stat_reject(int filter, struct bsc_connection *bsc, int normal);
-
-struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num)
-{
-	struct bsc_config *conf;
-
-	llist_for_each_entry(conf, &nat->bsc_configs, entry)
-		if (conf->nr == num)
-			return conf;
-
-	return NULL;
-}
-
-static void queue_for_msc(struct bsc_msc_connection *con, struct msgb *msg)
-{
-	if (!con) {
-		LOGP(DLINP, LOGL_ERROR, "No MSC Connection assigned. Check your code.\n");
-		msgb_free(msg);
-		return;
-	}
-
-
-	if (osmo_wqueue_enqueue(&con->write_queue, msg) != 0) {
-		LOGP(DLINP, LOGL_ERROR, "Failed to enqueue the write.\n");
-		msgb_free(msg);
-	}
-}
-
-static void send_reset_ack(struct bsc_connection *bsc)
-{
-	static const uint8_t gsm_reset_ack[] = {
-		0x09, 0x00, 0x03, 0x07, 0x0b, 0x04, 0x43, 0x01,
-		0x00, 0xfe, 0x04, 0x43, 0x5c, 0x00, 0xfe, 0x03,
-		0x00, 0x01, 0x31,
-	};
-
-	bsc_send_data(bsc, gsm_reset_ack, sizeof(gsm_reset_ack), IPAC_PROTO_SCCP);
-}
-
-static void send_ping(struct bsc_connection *bsc)
-{
-	static const uint8_t id_ping[] = {
-		IPAC_MSGT_PING,
-	};
-
-	bsc_send_data(bsc, id_ping, sizeof(id_ping), IPAC_PROTO_IPACCESS);
-}
-
-static void send_pong(struct bsc_connection *bsc)
-{
-	static const uint8_t id_pong[] = {
-		IPAC_MSGT_PONG,
-	};
-
-	bsc_send_data(bsc, id_pong, sizeof(id_pong), IPAC_PROTO_IPACCESS);
-}
-
-static void bsc_pong_timeout(void *_bsc)
-{
-	struct bsc_connection *bsc = _bsc;
-
-	LOGP(DNAT, LOGL_ERROR, "BSC Nr: %d PONG timeout.\n", bsc->cfg->nr);
-	bsc_close_connection(bsc);
-}
-
-static void bsc_ping_timeout(void *_bsc)
-{
-	struct bsc_connection *bsc = _bsc;
-
-	if (bsc->nat->ping_timeout < 0)
-		return;
-
-	send_ping(bsc);
-
-	/* send another ping in 20 seconds */
-	osmo_timer_schedule(&bsc->ping_timeout, bsc->nat->ping_timeout, 0);
-
-	/* also start a pong timer */
-	osmo_timer_schedule(&bsc->pong_timeout, bsc->nat->pong_timeout, 0);
-}
-
-static void start_ping_pong(struct bsc_connection *bsc)
-{
-	osmo_timer_setup(&bsc->pong_timeout, bsc_pong_timeout, bsc);
-	osmo_timer_setup(&bsc->ping_timeout, bsc_ping_timeout, bsc);
-
-	bsc_ping_timeout(bsc);
-}
-
-static void send_id_ack(struct bsc_connection *bsc)
-{
-	static const uint8_t id_ack[] = {
-		IPAC_MSGT_ID_ACK
-	};
-
-	bsc_send_data(bsc, id_ack, sizeof(id_ack), IPAC_PROTO_IPACCESS);
-}
-
-static void send_id_req(struct bsc_nat *nat, struct bsc_connection *bsc)
-{
-	static const uint8_t s_id_req[] = {
-		IPAC_MSGT_ID_GET,
-		0x01, IPAC_IDTAG_UNIT,
-		0x01, IPAC_IDTAG_MACADDR,
-		0x01, IPAC_IDTAG_LOCATION1,
-		0x01, IPAC_IDTAG_LOCATION2,
-		0x01, IPAC_IDTAG_EQUIPVERS,
-		0x01, IPAC_IDTAG_SWVERSION,
-		0x01, IPAC_IDTAG_UNITNAME,
-		0x01, IPAC_IDTAG_SERNR,
-	};
-
-	uint8_t *mrand;
-	uint8_t id_req[sizeof(s_id_req) + (2+16)];
-	uint8_t *buf = &id_req[sizeof(s_id_req)];
-
-	/* copy the static data */
-	memcpy(id_req, s_id_req, sizeof(s_id_req));
-
-	/* put the RAND with length, tag, value */
-	buf = v_put(buf, 0x11);
-	buf = v_put(buf, 0x23);
-	mrand = bsc->last_rand;
-
-	if (RAND_bytes(mrand, 16) != 1)
-		goto failed_random;
-
-	memcpy(buf, mrand, 16);
-	buf += 16;
-
-	bsc_send_data(bsc, id_req, sizeof(id_req), IPAC_PROTO_IPACCESS);
-	return;
-
-failed_random:
-	/* the timeout will trigger and close this connection */
-	LOGP(DNAT, LOGL_ERROR, "Failed to read from urandom.\n");
-	return;
-}
-
-static struct msgb *nat_create_rlsd(struct nat_sccp_connection *conn)
-{
-	struct sccp_connection_released *rel;
-	struct msgb *msg;
-
-	msg = msgb_alloc_headroom(4096, 128, "rlsd");
-	if (!msg) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to allocate released.\n");
-		return NULL;
-	}
-
-	msg->l2h = msgb_put(msg, sizeof(*rel));
-	rel = (struct sccp_connection_released *) msg->l2h;
-	rel->type = SCCP_MSG_TYPE_RLSD;
-	rel->release_cause = SCCP_RELEASE_CAUSE_SCCP_FAILURE;
-	rel->destination_local_reference = conn->remote_ref;
-	rel->source_local_reference = conn->patched_ref;
-
-	return msg;
-}
-
-static void nat_send_rlsd_ussd(struct bsc_nat *nat, struct nat_sccp_connection *conn)
-{
-	struct msgb *msg;
-
-	if (!nat->ussd_con)
-		return;
-
-	msg = nat_create_rlsd(conn);
-	if (!msg)
-		return;
-
-	bsc_do_write(&nat->ussd_con->queue, msg, IPAC_PROTO_SCCP);
-}
-
-static void nat_send_rlsd_msc(struct nat_sccp_connection *conn)
-{
-	struct msgb *msg;
-
-	msg = nat_create_rlsd(conn);
-	if (!msg)
-		return;
-
-	ipa_prepend_header(msg, IPAC_PROTO_SCCP);
-	queue_for_msc(conn->msc_con, msg);
-}
-
-static void nat_send_rlsd_bsc(struct nat_sccp_connection *conn)
-{
-	struct msgb *msg;
-	struct sccp_connection_released *rel;
-
-	msg = msgb_alloc_headroom(4096, 128, "rlsd");
-	if (!msg) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to allocate clear command.\n");
-		return;
-	}
-
-	msg->l2h = msgb_put(msg, sizeof(*rel));
-	rel = (struct sccp_connection_released *) msg->l2h;
-	rel->type = SCCP_MSG_TYPE_RLSD;
-	rel->release_cause = SCCP_RELEASE_CAUSE_SCCP_FAILURE;
-	rel->destination_local_reference = conn->real_ref;
-	rel->source_local_reference = conn->remote_ref;
-
-	bsc_write(conn->bsc, msg, IPAC_PROTO_SCCP);
-}
-
-static struct msgb *nat_creat_clrc(struct nat_sccp_connection *conn, uint8_t cause)
-{
-	struct msgb *msg;
-	struct msgb *sccp;
-
-	msg = gsm0808_create_clear_command(cause);
-	if (!msg) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to allocate clear command.\n");
-		return NULL;
-	}
-
-	sccp = sccp_create_dt1(&conn->real_ref, msg->data, msg->len);
-	if (!sccp) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to allocate SCCP msg.\n");
-		msgb_free(msg);
-		return NULL;
-	}
-
-	msgb_free(msg);
-	return sccp;
-}
-
-static int nat_send_clrc_bsc(struct nat_sccp_connection *conn)
-{
-	struct msgb *sccp;
-
-	sccp = nat_creat_clrc(conn, 0x20);
-	if (!sccp)
-		return -1;
-	return bsc_write(conn->bsc, sccp, IPAC_PROTO_SCCP);
-}
-
-static void nat_send_rlc(struct bsc_msc_connection *msc_con,
-			 struct sccp_source_reference *src,
-			 struct sccp_source_reference *dst)
-{
-	struct sccp_connection_release_complete *rlc;
-	struct msgb *msg;
-
-	msg = msgb_alloc_headroom(4096, 128, "rlc");
-	if (!msg) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to sccp rlc.\n");
-		return;
-	}
-
-	msg->l2h = msgb_put(msg, sizeof(*rlc));
-	rlc = (struct sccp_connection_release_complete *) msg->l2h;
-	rlc->type = SCCP_MSG_TYPE_RLC;
-	rlc->destination_local_reference = *dst;
-	rlc->source_local_reference = *src;
-
-	ipa_prepend_header(msg, IPAC_PROTO_SCCP);
-
-	queue_for_msc(msc_con, msg);
-}
-
-static void send_mgcp_reset(struct bsc_connection *bsc)
-{
-	static const uint8_t mgcp_reset[] = {
-	    "RSIP 1 13@mgw MGCP 1.0\r\n"
-	};
-
-	bsc_write_mgcp(bsc, mgcp_reset, sizeof mgcp_reset - 1);
-}
-
-void bsc_nat_send_mgcp_to_msc(struct bsc_nat *nat, struct msgb *msg)
-{
-	ipa_prepend_header(msg, IPAC_PROTO_MGCP_OLD);
-	queue_for_msc(nat->msc_con, msg);
-}
-
-/*
- * Below is the handling of messages coming
- * from the MSC and need to be forwarded to
- * a real BSC.
- */
-static void initialize_msc_if_needed(struct bsc_msc_connection *msc_con)
-{
-	if (msc_con->first_contact)
-		return;
-
-	msc_con->first_contact = 1;
-	msc_send_reset(msc_con);
-}
-
-static void send_id_get_response(struct bsc_msc_connection *msc_con)
-{
-	struct msgb *msg = bsc_msc_id_get_resp(0, nat->token, NULL, 0);
-	if (!msg)
-		return;
-
-	ipa_prepend_header(msg, IPAC_PROTO_IPACCESS);
-	queue_for_msc(msc_con, msg);
-}
-
-/*
- * Currently we are lacking refcounting so we need to copy each message.
- */
-static void bsc_send_data(struct bsc_connection *bsc, const uint8_t *data, unsigned int length, int proto)
-{
-	struct msgb *msg;
-
-	if (length > 4096 - 128) {
-		LOGP(DLINP, LOGL_ERROR, "Can not send message of that size.\n");
-		return;
-	}
-
-	msg = msgb_alloc_headroom(4096, 128, "to-bsc");
-	if (!msg) {
-		LOGP(DLINP, LOGL_ERROR, "Failed to allocate memory for BSC msg.\n");
-		return;
-	}
-
-	msg->l2h = msgb_put(msg, length);
-	memcpy(msg->data, data, length);
-
-	bsc_write(bsc, msg, proto);
-}
-
-/*
- * Update the release statistics
- */
-static void bsc_stat_reject(int filter, struct bsc_connection *bsc, int normal)
-{
-	if (!bsc->cfg) {
-		LOGP(DNAT, LOGL_ERROR, "BSC is not authenticated.");
-		return;
-	}
-
-	if (filter >= 0) {
-		LOGP(DNAT, LOGL_ERROR, "Connection was not rejected");
-		return;
-	}
-
-	if (filter == -1)
-		rate_ctr_inc(&bsc->cfg->stats.ctrg->ctr[BCFG_CTR_ILL_PACKET]);
-	else if (normal)
-		rate_ctr_inc(&bsc->cfg->stats.ctrg->ctr[BCFG_CTR_REJECTED_MSG]);
-	else
-		rate_ctr_inc(&bsc->cfg->stats.ctrg->ctr[BCFG_CTR_REJECTED_CR]);
-}
-
-/*
- * Release an established connection. We will have to release it to the BSC
- * and to the network and we do it the following way.
- * 1.) Give up on the MSC side
- *  1.1) Send a RLSD message, it is a bit non standard but should work, we
- *       ignore the RLC... we might complain about it. Other options would
- *       be to send a Release Request, handle the Release Complete..
- *  1.2) Mark the data structure to be con_local and wait for 2nd
- *
- * 2.) Give up on the BSC side
- *  2.1) Depending on the con type reject the service, or just close it
- */
-static void bsc_send_con_release(struct bsc_connection *bsc,
-		struct nat_sccp_connection *con,
-		struct bsc_filter_reject_cause *cause)
-{
-	struct msgb *rlsd;
-	/* 1. release the network */
-	rlsd = sccp_create_rlsd(&con->patched_ref, &con->remote_ref,
-				SCCP_RELEASE_CAUSE_END_USER_ORIGINATED);
-	if (!rlsd)
-		LOGP(DNAT, LOGL_ERROR, "Failed to create RLSD message.\n");
-	else {
-		ipa_prepend_header(rlsd, IPAC_PROTO_SCCP);
-		queue_for_msc(con->msc_con, rlsd);
-	}
-	con->con_local = NAT_CON_END_LOCAL;
-	con->msc_con = NULL;
-
-	/* 2. release the BSC side */
-	if (con->filter_state.con_type == FLT_CON_TYPE_LU) {
-		struct msgb *payload, *udt;
-		payload = gsm48_create_loc_upd_rej(cause->lu_reject_cause);
-
-		if (payload) {
-			gsm0808_prepend_dtap_header(payload, 0);
-			udt = sccp_create_dt1(&con->real_ref, payload->data, payload->len);
-			if (udt)
-				bsc_write(bsc, udt, IPAC_PROTO_SCCP);
-			else
-				LOGP(DNAT, LOGL_ERROR, "Failed to create DT1\n");
-
-			msgb_free(payload);
-		} else {
-			LOGP(DNAT, LOGL_ERROR, "Failed to allocate LU Reject.\n");
-		}
-	}
-
-	nat_send_clrc_bsc(con);
-
-	rlsd = sccp_create_rlsd(&con->remote_ref, &con->real_ref,
-				SCCP_RELEASE_CAUSE_END_USER_ORIGINATED);
-	if (!rlsd) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to allocate RLSD for the BSC.\n");
-		sccp_connection_destroy(con);
-		return;
-	}
-
-	con->filter_state.con_type = FLT_CON_TYPE_LOCAL_REJECT;
-	bsc_write(bsc, rlsd, IPAC_PROTO_SCCP);
-}
-
-static void bsc_send_con_refuse(struct bsc_connection *bsc,
-			struct bsc_nat_parsed *parsed, int con_type,
-			struct bsc_filter_reject_cause *cause)
-{
-	struct msgb *payload;
-	struct msgb *refuse;
-
-	if (con_type == FLT_CON_TYPE_LU)
-		payload = gsm48_create_loc_upd_rej(cause->lu_reject_cause);
-	else if (con_type == FLT_CON_TYPE_CM_SERV_REQ || con_type == FLT_CON_TYPE_SSA)
-		payload = gsm48_create_mm_serv_rej(cause->cm_reject_cause);
-	else {
-		LOGP(DNAT, LOGL_ERROR, "Unknown connection type: %d\n", con_type);
-		payload = NULL;
-	}
-
-	/*
-	 * Some BSCs do not handle the payload inside a SCCP CREF msg
-	 * so we will need to:
-	 * 1.) Allocate a local connection and mark it as local..
-	 * 2.) queue data for downstream.. and the RLC should delete everything
-	 */
-	if (payload) {
-		struct msgb *cc, *udt, *clear, *rlsd;
-		struct nat_sccp_connection *con;
-		con = create_sccp_src_ref(bsc, parsed);
-		if (!con)
-			goto send_refuse;
-
-		/* declare it local and assign a unique remote_ref */
-		con->filter_state.con_type = FLT_CON_TYPE_LOCAL_REJECT;
-		con->con_local = NAT_CON_END_LOCAL;
-		con->has_remote_ref = 1;
-		con->remote_ref = con->patched_ref;
-
-		/* 1. create a confirmation */
-		cc = sccp_create_cc(&con->remote_ref, &con->real_ref);
-		if (!cc)
-			goto send_refuse;
-
-		/* 2. create the DT1 */
-		gsm0808_prepend_dtap_header(payload, 0);
-		udt = sccp_create_dt1(&con->real_ref, payload->data, payload->len);
-		if (!udt) {
-			msgb_free(cc);
-			goto send_refuse;
-		}
-
-		/* 3. send a Clear Command */
-		clear = nat_creat_clrc(con, 0x20);
-		if (!clear) {
-			msgb_free(cc);
-			msgb_free(udt);
-			goto send_refuse;
-		}
-
-		/* 4. send a RLSD */
-		rlsd = sccp_create_rlsd(&con->remote_ref, &con->real_ref,
-					SCCP_RELEASE_CAUSE_END_USER_ORIGINATED);
-		if (!rlsd) {
-			msgb_free(cc);
-			msgb_free(udt);
-			msgb_free(clear);
-			goto send_refuse;
-		}
-
-		bsc_write(bsc, cc, IPAC_PROTO_SCCP);
-		bsc_write(bsc, udt, IPAC_PROTO_SCCP);
-		bsc_write(bsc, clear, IPAC_PROTO_SCCP);
-		bsc_write(bsc, rlsd, IPAC_PROTO_SCCP);
-		msgb_free(payload);
-		return;
-	}
-
-
-send_refuse:
-	if (payload)
-		msgb_free(payload);
-
-	refuse = sccp_create_refuse(parsed->src_local_ref,
-				    SCCP_REFUSAL_SCCP_FAILURE, NULL, 0);
-	if (!refuse) {
-		LOGP(DNAT, LOGL_ERROR,
-		     "Creating refuse msg failed for SCCP 0x%x on BSC Nr: %d.\n",
-		      sccp_src_ref_to_int(parsed->src_local_ref), bsc->cfg->nr);
-		return;
-	}
-
-	bsc_write(bsc, refuse, IPAC_PROTO_SCCP);
-}
-
-static void bsc_nat_send_paging(struct bsc_connection *bsc, struct msgb *msg)
-{
-	if (bsc->cfg->forbid_paging) {
-		LOGP(DNAT, LOGL_DEBUG, "Paging forbidden for BTS: %d\n", bsc->cfg->nr);
-		return;
-	}
-
-	bsc_send_data(bsc, msg->l2h, msgb_l2len(msg), IPAC_PROTO_SCCP);
-}
-
-static void bsc_nat_handle_paging(struct bsc_nat *nat, struct msgb *msg)
-{
-	struct bsc_connection *bsc;
-	const uint8_t *paging_start;
-	int paging_length, i, ret;
-
-	ret = bsc_nat_find_paging(msg, &paging_start, &paging_length);
-	if (ret != 0) {
-		LOGP(DNAT, LOGL_ERROR, "Could not parse paging message: %d\n", ret);
-		return;
-	}
-
-	/* This is quite expensive now */
-	for (i = 0; i < paging_length; i += 2) {
-		unsigned int _lac = ntohs(*(unsigned int *) &paging_start[i]);
-		unsigned int paged = 0;
-		llist_for_each_entry(bsc, &nat->bsc_connections, list_entry) {
-			if (!bsc->cfg)
-				continue;
-			if (!bsc->authenticated)
-				continue;
-			if (!bsc_config_handles_lac(bsc->cfg, _lac))
-				continue;
-			bsc_nat_send_paging(bsc, msg);
-			paged += 1;
-		}
-
-		/* highlight a possible config issue */
-		if (paged == 0)
-			LOGP(DNAT, LOGL_ERROR, "No BSC for LAC %d/0x%d\n", _lac, _lac);
-
-	}
-}
-
-
-/*
- * Update the auth status. This can be either a CIPHER MODE COMMAND or
- * a CM Serivce Accept. Maybe also LU Accept or such in the future.
- */
-static void update_con_authorize(struct nat_sccp_connection *con,
-				 struct bsc_nat_parsed *parsed,
-				 struct msgb *msg)
-{
-	if (!con)
-		return;
-	if (con->authorized)
-		return;
-
-	if (parsed->bssap == BSSAP_MSG_BSS_MANAGEMENT &&
-	    parsed->gsm_type == BSS_MAP_MSG_CIPHER_MODE_CMD) {
-		con->authorized = 1;
-	} else if (parsed->bssap == BSSAP_MSG_DTAP) {
-		uint8_t msg_type, proto;
-		uint32_t len;
-		struct gsm48_hdr *hdr48;
-		hdr48 = bsc_unpack_dtap(parsed, msg, &len);
-		if (!hdr48)
-			return;
-
-		proto = gsm48_hdr_pdisc(hdr48);
-		msg_type = gsm48_hdr_msg_type(hdr48);
-		if (proto == GSM48_PDISC_MM &&
-		    msg_type == GSM48_MT_MM_CM_SERV_ACC)
-			con->authorized = 1;
-	}
-}
-
-static int forward_sccp_to_bts(struct bsc_msc_connection *msc_con, struct msgb *msg)
-{
-	struct nat_sccp_connection *con = NULL;
-	struct bsc_connection *bsc;
-	struct bsc_nat_parsed *parsed;
-	int proto;
-
-	/* filter, drop, patch the message? */
-	parsed = bsc_nat_parse(msg);
-	if (!parsed) {
-		LOGP(DNAT, LOGL_ERROR, "Can not parse msg from BSC.\n");
-		return -1;
-	}
-
-	if (bsc_nat_filter_ipa(DIR_BSC, msg, parsed))
-		goto exit;
-
-	proto = parsed->ipa_proto;
-
-	/* Route and modify the SCCP packet */
-	if (proto == IPAC_PROTO_SCCP) {
-		switch (parsed->sccp_type) {
-		case SCCP_MSG_TYPE_UDT:
-			/* forward UDT messages to every BSC */
-			goto send_to_all;
-			break;
-		case SCCP_MSG_TYPE_RLSD:
-		case SCCP_MSG_TYPE_CREF:
-		case SCCP_MSG_TYPE_DT1:
-		case SCCP_MSG_TYPE_IT:
-			con = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
-			if (parsed->gsm_type == BSS_MAP_MSG_ASSIGMENT_RQST) {
-				osmo_counter_inc(nat->stats.sccp.calls);
-
-				if (con) {
-					struct rate_ctr_group *ctrg;
-					ctrg = con->bsc->cfg->stats.ctrg;
-					rate_ctr_inc(&ctrg->ctr[BCFG_CTR_SCCP_CALLS]);
-					if (bsc_mgcp_assign_patch(con, msg) != 0)
-						LOGP(DNAT, LOGL_ERROR, "Failed to assign...\n");
-				} else
-					LOGP(DNAT, LOGL_ERROR, "Assignment command but no BSC.\n");
-			} else if (con && con->con_local == NAT_CON_END_USSD &&
-				   parsed->gsm_type == BSS_MAP_MSG_CLEAR_CMD) {
-				LOGP(DNAT, LOGL_NOTICE, "Clear Command for USSD Connection. Ignoring.\n");
-				con = NULL;
-			}
-			break;
-		case SCCP_MSG_TYPE_CC:
-			con = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
-			if (!con || update_sccp_src_ref(con, parsed) != 0)
-				goto exit;
-			break;
-		case SCCP_MSG_TYPE_RLC:
-			LOGP(DNAT, LOGL_ERROR, "Unexpected release complete from MSC.\n");
-			goto exit;
-			break;
-		case SCCP_MSG_TYPE_CR:
-			/* MSC never opens a SCCP connection, fall through */
-		default:
-			goto exit;
-		}
-
-		if (!con && parsed->sccp_type == SCCP_MSG_TYPE_RLSD) {
-			LOGP(DNAT, LOGL_NOTICE, "Sending fake RLC on RLSD message to network.\n");
-			/* Exchange src/dest for the reply */
-			nat_send_rlc(msc_con, &parsed->original_dest_ref,
-					parsed->src_local_ref);
-		} else if (!con)
-			LOGP(DNAT, LOGL_ERROR, "Unknown connection for msg type: 0x%x from the MSC.\n", parsed->sccp_type);
-	}
-
-	if (!con) {
-		talloc_free(parsed);
-		return -1;
-	}
-	if (!con->bsc->authenticated) {
-		talloc_free(parsed);
-		LOGP(DNAT, LOGL_ERROR, "Selected BSC not authenticated.\n");
-		return -1;
-	}
-
-	update_con_authorize(con, parsed, msg);
-	talloc_free(parsed);
-
-	bsc_send_data(con->bsc, msg->l2h, msgb_l2len(msg), proto);
-	return 0;
-
-send_to_all:
-	/*
-	 * Filter Paging from the network. We do not want to send a PAGING
-	 * Command to every BSC in our network. We will analys the PAGING
-	 * message and then send it to the authenticated messages...
-	 */
-	if (parsed->ipa_proto == IPAC_PROTO_SCCP && parsed->gsm_type == BSS_MAP_MSG_PAGING) {
-		bsc_nat_handle_paging(nat, msg);
-		goto exit;
-	}
-	/* currently send this to every BSC connected */
-	llist_for_each_entry(bsc, &nat->bsc_connections, list_entry) {
-		if (!bsc->authenticated)
-			continue;
-
-		bsc_send_data(bsc, msg->l2h, msgb_l2len(msg), parsed->ipa_proto);
-	}
-
-exit:
-	talloc_free(parsed);
-	return 0;
-}
-
-static void msc_connection_was_lost(struct bsc_msc_connection *con)
-{
-	struct bsc_connection *bsc, *tmp;
-
-	LOGP(DMSC, LOGL_ERROR, "Closing all connections downstream.\n");
-	llist_for_each_entry_safe(bsc, tmp, &nat->bsc_connections, list_entry)
-		bsc_close_connection(bsc);
-
-	bsc_mgcp_free_endpoints(nat);
-	bsc_msc_schedule_connect(con);
-}
-
-static void msc_connection_connected(struct bsc_msc_connection *con)
-{
-	osmo_counter_inc(nat->stats.msc.reconn);
-}
-
-static void msc_send_reset(struct bsc_msc_connection *msc_con)
-{
-	static const uint8_t reset[] = {
-		0x00, 0x12, 0xfd,
-		0x09, 0x00, 0x03, 0x05, 0x07, 0x02, 0x42, 0xfe,
-		0x02, 0x42, 0xfe, 0x06, 0x00, 0x04, 0x30, 0x04,
-		0x01, 0x20
-	};
-
-	struct msgb *msg;
-
-	msg = msgb_alloc_headroom(4096, 128, "08.08 reset");
-	if (!msg) {
-		LOGP(DMSC, LOGL_ERROR, "Failed to allocate reset msg.\n");
-		return;
-	}
-
-	msg->l2h = msgb_put(msg, sizeof(reset));
-	memcpy(msg->l2h, reset, msgb_l2len(msg));
-
-	queue_for_msc(msc_con, msg);
-
-	LOGP(DMSC, LOGL_NOTICE, "Scheduled GSM0808 reset msg for the MSC.\n");
-}
-
-static int ipaccess_msc_read_cb(struct osmo_fd *bfd)
-{
-	struct bsc_msc_connection *msc_con;
-	struct msgb *msg = NULL;
-	struct ipaccess_head *hh;
-	int ret;
-
-	msc_con = (struct bsc_msc_connection *) bfd->data;
-
-	ret = ipa_msg_recv_buffered(bfd->fd, &msg, &msc_con->pending_msg);
-	if (ret <= 0) {
-		if (ret == -EAGAIN)
-			return 0;
-		if (ret == 0)
-			LOGP(DNAT, LOGL_FATAL,
-				"The connection the MSC(%s) was lost, exiting\n",
-				msc_con->name);
-		else
-			LOGP(DNAT, LOGL_ERROR,
-				"Failed to parse ip access message on %s: %d\n",
-				msc_con->name, ret);
-
-		bsc_msc_lost(msc_con);
-		return -1;
-	}
-
-	LOGP(DNAT, LOGL_DEBUG,
-		"MSG from MSC(%s): %s proto: %d\n", msc_con->name,
-		osmo_hexdump(msg->data, msg->len), msg->l2h[0]);
-
-	/* handle base message handling */
-	hh = (struct ipaccess_head *) msg->data;
-
-	/* initialize the networking. This includes sending a GSM08.08 message */
-	if (hh->proto == IPAC_PROTO_IPACCESS) {
-		ipa_ccm_rcvmsg_base(msg, bfd);
-		if (msg->l2h[0] == IPAC_MSGT_ID_ACK)
-			initialize_msc_if_needed(msc_con);
-		else if (msg->l2h[0] == IPAC_MSGT_ID_GET)
-			send_id_get_response(msc_con);
-	} else if (hh->proto == IPAC_PROTO_SCCP) {
-		forward_sccp_to_bts(msc_con, msg);
-	} else if (hh->proto == IPAC_PROTO_MGCP_OLD) {
-		bsc_nat_handle_mgcp(nat, msg);
-	}
-
-	msgb_free(msg);
-	return 0;
-}
-
-static int ipaccess_msc_write_cb(struct osmo_fd *bfd, struct msgb *msg)
-{
-	int rc;
-	rc = write(bfd->fd, msg->data, msg->len);
-
-	if (rc != msg->len) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to write MSG to MSC.\n");
-		return -1;
-	}
-
-	return rc;
-}
-
-/*
- * Below is the handling of messages coming
- * from the BSC and need to be forwarded to
- * a real BSC.
- */
-
-/*
- * Remove the connection from the connections list,
- * remove it from the patching of SCCP header lists
- * as well. Maybe in the future even close connection..
- */
-void bsc_close_connection(struct bsc_connection *connection)
-{
-	struct nat_sccp_connection *sccp_patch, *tmp;
-	struct bsc_cmd_list *cmd_entry, *cmd_tmp;
-	struct rate_ctr *ctr = NULL;
-
-	/* stop the timeout timer */
-	osmo_timer_del(&connection->id_timeout);
-	osmo_timer_del(&connection->ping_timeout);
-	osmo_timer_del(&connection->pong_timeout);
-
-	if (connection->cfg)
-		ctr = &connection->cfg->stats.ctrg->ctr[BCFG_CTR_DROPPED_SCCP];
-
-	/* remove all SCCP connections */
-	llist_for_each_entry_safe(sccp_patch, tmp, &nat->sccp_connections, list_entry) {
-		if (sccp_patch->bsc != connection)
-			continue;
-
-		if (ctr)
-			rate_ctr_inc(ctr);
-		if (sccp_patch->has_remote_ref) {
-			if (sccp_patch->con_local == NAT_CON_END_MSC)
-				nat_send_rlsd_msc(sccp_patch);
-			else if (sccp_patch->con_local == NAT_CON_END_USSD)
-				nat_send_rlsd_ussd(nat, sccp_patch);
-		}
-
-		sccp_connection_destroy(sccp_patch);
-	}
-
-	/* Reply to all outstanding commands */
-	llist_for_each_entry_safe(cmd_entry, cmd_tmp, &connection->cmd_pending, list_entry) {
-		cmd_entry->cmd->type = CTRL_TYPE_ERROR;
-		cmd_entry->cmd->reply = "BSC closed the connection";
-		ctrl_cmd_send(&cmd_entry->ccon->write_queue, cmd_entry->cmd);
-		bsc_nat_ctrl_del_pending(cmd_entry);
-	}
-
-	/* close endpoints allocated by this BSC */
-	bsc_mgcp_clear_endpoints_for(connection);
-
-	osmo_fd_unregister(&connection->write_queue.bfd);
-	close(connection->write_queue.bfd.fd);
-	osmo_wqueue_clear(&connection->write_queue);
-	llist_del(&connection->list_entry);
-
-	if (connection->pending_msg) {
-		LOGP(DNAT, LOGL_ERROR, "Dropping partial message on connection %d.\n",
-		     connection->cfg ? connection->cfg->nr : -1);
-		msgb_free(connection->pending_msg);
-		connection->pending_msg = NULL;
-	}
-
-	talloc_free(connection);
-}
-
-static void bsc_maybe_close(struct bsc_connection *bsc)
-{
-	struct nat_sccp_connection *sccp;
-	if (!bsc->nat->blocked)
-		return;
-
-	/* are there any connections left */
-	llist_for_each_entry(sccp, &bsc->nat->sccp_connections, list_entry)
-		if (sccp->bsc == bsc)
-			return;
-
-	/* nothing left, close the BSC */
-	LOGP(DNAT, LOGL_NOTICE, "Cleaning up BSC %d in blocking mode.\n",
-	     bsc->cfg ? bsc->cfg->nr : -1);
-	bsc_close_connection(bsc);
-}
-
-static void ipaccess_close_bsc(void *data)
-{
-	struct sockaddr_in sock;
-	socklen_t len = sizeof(sock);
-	struct bsc_connection *conn = data;
-
-
-	getpeername(conn->write_queue.bfd.fd, (struct sockaddr *) &sock, &len);
-	LOGP(DNAT, LOGL_ERROR, "BSC on %s didn't respond to identity request. Closing.\n",
-	     inet_ntoa(sock.sin_addr));
-	bsc_close_connection(conn);
-}
-
-static int verify_key(struct bsc_connection *conn, struct bsc_config *conf, const uint8_t *key, const int keylen)
-{
-	struct osmo_auth_vector vec;
-
-	struct osmo_sub_auth_data auth = {
-		.type		= OSMO_AUTH_TYPE_GSM,
-		.algo		= OSMO_AUTH_ALG_MILENAGE,
-	};
-
-	/* expect a specific keylen */
-	if (keylen != 8) {
-		LOGP(DNAT, LOGL_ERROR, "Key length is wrong: %d for bsc nr %d\n",
-			keylen, conf->nr);
-		return 0;
-	}
-
-	memcpy(auth.u.umts.opc, conf->key, 16);
-	memcpy(auth.u.umts.k, conf->key, 16);
-	memset(auth.u.umts.amf, 0, 2);
-	auth.u.umts.sqn = 0;
-
-	memset(&vec, 0, sizeof(vec));
-	osmo_auth_gen_vec(&vec, &auth, conn->last_rand);
-
-	if (vec.res_len != 8) {
-		LOGP(DNAT, LOGL_ERROR, "Res length is wrong: %d for bsc nr %d\n",
-			vec.res_len, conf->nr);
-		return 0;
-	}
-
-	return osmo_constant_time_cmp(vec.res, key, 8) == 0;
-}
-
-static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc)
-{
-	struct bsc_config *conf;
-	const char *token = (const char *) TLVP_VAL(tvp, IPAC_IDTAG_UNITNAME);
-	int len = TLVP_LEN(tvp, IPAC_IDTAG_UNITNAME);
-	const uint8_t *xres = TLVP_VAL(tvp, 0x24);
-	const int xlen = TLVP_LEN(tvp, 0x24);
-
-	if (bsc->cfg) {
-		LOGP(DNAT, LOGL_ERROR, "Reauth on fd %d bsc nr %d\n",
-		     bsc->write_queue.bfd.fd, bsc->cfg->nr);
-		return;
-	}
-
-	if (len <= 0) {
-		LOGP(DNAT, LOGL_ERROR, "Token with length zero on fd: %d\n",
-			bsc->write_queue.bfd.fd);
-		return;
-	}
-
-	if (token[len - 1] != '\0') {
-		LOGP(DNAT, LOGL_ERROR, "Token not null terminated on fd: %d\n",
-			bsc->write_queue.bfd.fd);
-		return;
-	}
-
-	/*
-	 * New systems have fixed the structure of the message but
-	 * we need to support old ones too.
-	 */
-	if (len >= 2 && token[len - 2] == '\0')
-		len -= 1;
-
-	conf = bsc_config_by_token(bsc->nat, token, len);
-	if (!conf) {
-		LOGP(DNAT, LOGL_ERROR,
-			"No bsc found for token '%s' len %d on fd: %d.\n", token,
-			bsc->write_queue.bfd.fd, len);
-		bsc_close_connection(bsc);
-		return;
-	}
-
-	/* We have set a key and expect it to be present */
-	if (conf->key_present && !verify_key(bsc, conf, xres, xlen - 1)) {
-		LOGP(DNAT, LOGL_ERROR,
-			"Wrong key for bsc nr %d fd: %d.\n", conf->nr,
-			bsc->write_queue.bfd.fd);
-		bsc_close_connection(bsc);
-		return;
-	}
-
-	rate_ctr_inc(&conf->stats.ctrg->ctr[BCFG_CTR_NET_RECONN]);
-	bsc->authenticated = 1;
-	bsc->cfg = conf;
-	osmo_timer_del(&bsc->id_timeout);
-	LOGP(DNAT, LOGL_NOTICE, "Authenticated bsc nr: %d on fd %d\n",
-		conf->nr, bsc->write_queue.bfd.fd);
-	start_ping_pong(bsc);
-}
-
-static void handle_con_stats(struct nat_sccp_connection *con)
-{
-	struct rate_ctr_group *ctrg;
-	int id = bsc_conn_type_to_ctr(con);
-
-	if (id == -1)
-		return;
-
-	if (!con->bsc || !con->bsc->cfg)
-		return;
-
-	ctrg = con->bsc->cfg->stats.ctrg;
-	rate_ctr_inc(&ctrg->ctr[id]);
-}
-
-static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
-{
-	int con_filter = 0;
-	char *imsi = NULL;
-	struct bsc_msc_connection *con_msc = NULL;
-	struct bsc_connection *con_bsc = NULL;
-	int con_type;
-	struct bsc_nat_parsed *parsed;
-	struct bsc_filter_reject_cause cause;
-
-	/* Parse and filter messages */
-	parsed = bsc_nat_parse(msg);
-	if (!parsed) {
-		LOGP(DNAT, LOGL_ERROR, "Can not parse msg from BSC.\n");
-		msgb_free(msg);
-		return -1;
-	}
-
-	if (bsc_nat_filter_ipa(DIR_MSC, msg, parsed))
-		goto exit;
-
-	/*
-	 * check authentication after filtering to not reject auth
-	 * responses coming from the BSC. We have to make sure that
-	 * nothing from the exit path will forward things to the MSC
-	 */
-	if (!bsc->authenticated) {
-		LOGP(DNAT, LOGL_ERROR, "BSC is not authenticated.\n");
-		msgb_free(msg);
-		return -1;
-	}
-
-
-	/* modify the SCCP entries */
-	if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
-		int filter;
-		struct nat_sccp_connection *con;
-		switch (parsed->sccp_type) {
-		case SCCP_MSG_TYPE_CR:
-			memset(&cause, 0, sizeof(cause));
-			filter = bsc_nat_filter_sccp_cr(bsc, msg, parsed,
-						&con_type, &imsi, &cause);
-			if (filter < 0) {
-				if (imsi)
-					bsc_nat_inform_reject(bsc, imsi);
-				bsc_stat_reject(filter, bsc, 0);
-				goto exit3;
-			}
-
-			if (!create_sccp_src_ref(bsc, parsed))
-				goto exit2;
-			con = patch_sccp_src_ref_to_msc(msg, parsed, bsc);
-			OSMO_ASSERT(con);
-			con->msc_con = bsc->nat->msc_con;
-			con_msc = con->msc_con;
-			con->filter_state.con_type = con_type;
-			con->filter_state.imsi_checked = filter;
-			bsc_nat_extract_lac(bsc, con, parsed, msg);
-			if (imsi)
-				con->filter_state.imsi = talloc_steal(con, imsi);
-			imsi = NULL;
-			con_bsc = con->bsc;
-			handle_con_stats(con);
-			break;
-		case SCCP_MSG_TYPE_RLSD:
-		case SCCP_MSG_TYPE_CREF:
-		case SCCP_MSG_TYPE_DT1:
-		case SCCP_MSG_TYPE_CC:
-		case SCCP_MSG_TYPE_IT:
-			con = patch_sccp_src_ref_to_msc(msg, parsed, bsc);
-			if (con) {
-				/* only filter non local connections */
-				if (!con->con_local) {
-					memset(&cause, 0, sizeof(cause));
-					filter = bsc_nat_filter_dt(bsc, msg,
-							con, parsed, &cause);
-					if (filter < 0) {
-						if (con->filter_state.imsi)
-							bsc_nat_inform_reject(bsc,
-								con->filter_state.imsi);
-						bsc_stat_reject(filter, bsc, 1);
-						bsc_send_con_release(bsc, con, &cause);
-						con = NULL;
-						goto exit2;
-					}
-
-					/* hand data to a side channel */
-					if (bsc_ussd_check(con, parsed, msg) == 1) 
-						con->con_local = NAT_CON_END_USSD;
-
-					/*
-					 * Optionally rewrite setup message. This can
-					 * replace the msg and the parsed structure becomes
-					 * invalid.
-					 */
-					msg = bsc_nat_rewrite_msg(bsc->nat, msg, parsed,
-									con->filter_state.imsi);
-					talloc_free(parsed);
-					parsed = NULL;
-				} else if (con->con_local == NAT_CON_END_USSD) {
-					bsc_ussd_check(con, parsed, msg);
-				}
-
-				con_bsc = con->bsc;
-				con_msc = con->msc_con;
-				con_filter = con->con_local;
-			}
-
-			break;
-		case SCCP_MSG_TYPE_RLC:
-			con = patch_sccp_src_ref_to_msc(msg, parsed, bsc);
-			if (con) {
-				con_bsc = con->bsc;
-				con_msc = con->msc_con;
-				con_filter = con->con_local;
-			}
-			remove_sccp_src_ref(bsc, msg, parsed);
-			bsc_maybe_close(bsc);
-			break;
-		case SCCP_MSG_TYPE_UDT:
-			/* simply forward everything */
-			con = NULL;
-			break;
-		default:
-			LOGP(DNAT, LOGL_ERROR, "Not forwarding to msc sccp type: 0x%x\n", parsed->sccp_type);
-			con = NULL;
-			goto exit2;
-			break;
-		}
-        } else if (parsed->ipa_proto == IPAC_PROTO_MGCP_OLD) {
-                bsc_mgcp_forward(bsc, msg);
-                goto exit2;
-	} else {
-		LOGP(DNAT, LOGL_ERROR, "Not forwarding unknown stream id: 0x%x\n", parsed->ipa_proto);
-		goto exit2;
-	}
-
-	if (con_msc && con_bsc != bsc) {
-		LOGP(DNAT, LOGL_ERROR, "The connection belongs to a different BTS: input: %d con: %d\n",
-		     bsc->cfg->nr, con_bsc->cfg->nr);
-		goto exit2;
-	}
-
-	/* do not forward messages to the MSC */
-	if (con_filter)
-		goto exit2;
-
-	if (!con_msc) {
-		LOGP(DNAT, LOGL_ERROR, "Not forwarding data bsc_nr: %d ipa: %d type: 0x%x\n",
-			bsc->cfg->nr,
-			parsed ? parsed->ipa_proto : -1,
-			parsed ? parsed->sccp_type : -1);
-		goto exit2;
-	}
-
-	/* send the non-filtered but maybe modified msg */
-	queue_for_msc(con_msc, msg);
-	if (parsed)
-		talloc_free(parsed);
-	return 0;
-
-exit:
-	/* if we filter out the reset send an ack to the BSC */
-	if (parsed->bssap == 0 && parsed->gsm_type == BSS_MAP_MSG_RESET) {
-		send_reset_ack(bsc);
-		send_reset_ack(bsc);
-	} else if (parsed->ipa_proto == IPAC_PROTO_IPACCESS) {
-		/* do we know who is handling this? */
-		if (msg->l2h[0] == IPAC_MSGT_ID_RESP && msgb_l2len(msg) > 2) {
-			struct tlv_parsed tvp;
-			int ret;
-			ret = ipa_ccm_idtag_parse_off(&tvp,
-					     (unsigned char *) msg->l2h + 2,
-					     msgb_l2len(msg) - 2, 0);
-			if (ret < 0) {
-				LOGP(DNAT, LOGL_ERROR, "ignoring IPA response "
-					"message with malformed TLVs\n");
-				return ret;
-			}
-			if (TLVP_PRESENT(&tvp, IPAC_IDTAG_UNITNAME))
-				ipaccess_auth_bsc(&tvp, bsc);
-		}
-
-		goto exit2;
-	}
-
-exit2:
-	if (imsi)
-		talloc_free(imsi);
-	talloc_free(parsed);
-	msgb_free(msg);
-	return -1;
-
-exit3:
-	/* send a SCCP Connection Refused */
-	if (imsi)
-		talloc_free(imsi);
-	bsc_send_con_refuse(bsc, parsed, con_type, &cause);
-	talloc_free(parsed);
-	msgb_free(msg);
-	return -1;
-}
-
-static int ipaccess_bsc_read_cb(struct osmo_fd *bfd)
-{
-	struct bsc_connection *bsc = bfd->data;
-	struct msgb *msg = NULL;
-	struct ipaccess_head *hh;
-	struct ipaccess_head_ext *hh_ext;
-	int ret;
-
-	ret = ipa_msg_recv_buffered(bfd->fd, &msg, &bsc->pending_msg);
-	if (ret <= 0) {
-		if (ret == -EAGAIN)
-			return 0;
-		if (ret == 0)
-			LOGP(DNAT, LOGL_ERROR,
-			     "The connection to the BSC Nr: %d was lost. Cleaning it\n",
-			     bsc->cfg ? bsc->cfg->nr : -1);
-		else
-			LOGP(DNAT, LOGL_ERROR,
-			     "Stream error on BSC Nr: %d. Failed to parse ip access message: %d (%s)\n",
-			     bsc->cfg ? bsc->cfg->nr : -1, ret, strerror(-ret));
-
-		bsc_close_connection(bsc);
-		return -1;
-	}
-
-
-	LOGP(DNAT, LOGL_DEBUG, "MSG from BSC: %s proto: %d\n", osmo_hexdump(msg->data, msg->len), msg->l2h[0]);
-
-	/* Handle messages from the BSC */
-	hh = (struct ipaccess_head *) msg->data;
-
-	/* stop the pong timeout */
-	if (hh->proto == IPAC_PROTO_IPACCESS) {
-		if (msg->l2h[0] == IPAC_MSGT_PONG) {
-			osmo_timer_del(&bsc->pong_timeout);
-			msgb_free(msg);
-			return 0;
-		} else if (msg->l2h[0] == IPAC_MSGT_PING) {
-			send_pong(bsc);
-			msgb_free(msg);
-			return 0;
-		}
-	/* Message contains the ipaccess_head_ext header, investigate further */
-	} else if (hh->proto == IPAC_PROTO_OSMO &&
-		   msg->len > sizeof(*hh) + sizeof(*hh_ext)) {
-
-		hh_ext = (struct ipaccess_head_ext *) hh->data;
-		/* l2h is where the actual command data is expected */
-		msg->l2h = hh_ext->data;
-
-		if (hh_ext->proto == IPAC_PROTO_EXT_CTRL)
-			return bsc_nat_handle_ctrlif_msg(bsc, msg);
-	}
-
-	/* FIXME: Currently no PONG is sent to the BSC */
-	/* FIXME: Currently no ID ACK is sent to the BSC */
-	forward_sccp_to_msc(bsc, msg);
-
-	return 0;
-}
-
-static int ipaccess_listen_bsc_cb(struct osmo_fd *bfd, unsigned int what)
-{
-	struct bsc_connection *bsc;
-	int fd, rc, on;
-	struct sockaddr_in sa;
-	socklen_t sa_len = sizeof(sa);
-
-	if (!(what & BSC_FD_READ))
-		return 0;
-
-	fd = accept(bfd->fd, (struct sockaddr *) &sa, &sa_len);
-	if (fd < 0) {
-		perror("accept");
-		return fd;
-	}
-
-	/* count the reconnect */
-	osmo_counter_inc(nat->stats.bsc.reconn);
-
-	/*
-	 * if we are not connected to a msc... just close the socket
-	 */
-	if (!bsc_nat_msc_is_connected(nat)) {
-		LOGP(DNAT, LOGL_NOTICE, "Disconnecting BSC due lack of MSC connection.\n");
-		close(fd);
-		return 0;
-	}
-
-	if (nat->blocked) {
-		LOGP(DNAT, LOGL_NOTICE, "Disconnecting BSC due NAT being blocked.\n");
-		close(fd);
-		return 0;
-	}
-
-	on = 1;
-	rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
-	if (rc != 0)
-                LOGP(DNAT, LOGL_ERROR, "Failed to set TCP_NODELAY: %s\n", strerror(errno));
-
-	rc = setsockopt(fd, IPPROTO_IP, IP_TOS,
-			&nat->bsc_ip_dscp, sizeof(nat->bsc_ip_dscp));
-	if (rc != 0)
-		LOGP(DNAT, LOGL_ERROR, "Failed to set IP_TOS: %s\n", strerror(errno));
-
-	/* todo... do something with the connection */
-	/* todo... use GNUtls to see if we want to trust this as a BTS */
-
-	/*
-	 *
-	 */
-	bsc = bsc_connection_alloc(nat);
-	if (!bsc) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to allocate BSC struct.\n");
-		close(fd);
-		return -1;
-	}
-
-	bsc->write_queue.bfd.data = bsc;
-	bsc->write_queue.bfd.fd = fd;
-	bsc->write_queue.read_cb = ipaccess_bsc_read_cb;
-	bsc->write_queue.write_cb = bsc_write_cb;
-	bsc->write_queue.bfd.when = BSC_FD_READ;
-	if (osmo_fd_register(&bsc->write_queue.bfd) < 0) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to register BSC fd.\n");
-		close(fd);
-		talloc_free(bsc);
-		return -2;
-	}
-
-	LOGP(DNAT, LOGL_NOTICE, "BSC connection on %d with IP: %s\n",
-		fd, inet_ntoa(sa.sin_addr));
-
-	llist_add(&bsc->list_entry, &nat->bsc_connections);
-	bsc->last_id = 0;
-
-	send_id_ack(bsc);
-	send_id_req(nat, bsc);
-	send_mgcp_reset(bsc);
-
-	/*
-	 * start the hangup timer
-	 */
-	osmo_timer_setup(&bsc->id_timeout, ipaccess_close_bsc, bsc);
-	osmo_timer_schedule(&bsc->id_timeout, nat->auth_timeout, 0);
-	return 0;
-}
-
-static void print_usage()
-{
-	printf("Usage: bsc_nat\n");
-}
-
-static void print_help()
-{
-	printf("  Some useful help...\n");
-	printf("  -h --help this text\n");
-	printf("  -d option --debug=DRLL:DCC:DMM:DRR:DRSL:DNM enable debugging\n");
-	printf("  -D --daemonize Fork the process into a background daemon\n");
-	printf("  -s --disable-color\n");
-	printf("  -c --config-file filename The config file to use.\n");
-	printf("  -m --msc=IP. The address of the MSC.\n");
-	printf("  -l --local=IP. The local address of this BSC.\n");
-}
-
-static void handle_options(int argc, char **argv)
-{
-	while (1) {
-		int option_index = 0, c;
-		static struct option long_options[] = {
-			{"help", 0, 0, 'h'},
-			{"debug", 1, 0, 'd'},
-			{"daemonize", 0, 0, 'D'},
-			{"config-file", 1, 0, 'c'},
-			{"disable-color", 0, 0, 's'},
-			{"timestamp", 0, 0, 'T'},
-			{"msc", 1, 0, 'm'},
-			{"local", 1, 0, 'l'},
-			{0, 0, 0, 0}
-		};
-
-		c = getopt_long(argc, argv, "hd:sTPc:m:l:D",
-				long_options, &option_index);
-		if (c == -1)
-			break;
-
-		switch (c) {
-		case 'h':
-			print_usage();
-			print_help();
-			exit(0);
-		case 's':
-			log_set_use_color(osmo_stderr_target, 0);
-			break;
-		case 'd':
-			log_parse_category_mask(osmo_stderr_target, optarg);
-			break;
-		case 'D':
-			daemonize = 1;
-			break;
-		case 'c':
-			config_file = optarg;
-			break;
-		case 'T':
-			log_set_print_timestamp(osmo_stderr_target, 1);
-			break;
-		case 'm':
-			msc_ip = optarg;
-			break;
-		case 'l':
-			inet_aton(optarg, &local_addr);
-			break;
-		default:
-			/* ignore */
-			break;
-		}
-	}
-}
-
-static void signal_handler(int signal)
-{
-	switch (signal) {
-	case SIGABRT:
-		/* in case of abort, we want to obtain a talloc report
-		 * and then return to the caller, who will abort the process */
-	case SIGUSR1:
-		talloc_report_full(tall_bsc_ctx, stderr);
-		break;
-	default:
-		break;
-	}
-}
-
-static void sccp_close_unconfirmed(void *_data)
-{
-	int destroyed = 0;
-	struct bsc_connection *bsc, *bsc_tmp;
-	struct nat_sccp_connection *conn, *tmp1;
-	struct timespec now;
-	clock_gettime(CLOCK_MONOTONIC, &now);
-
-	llist_for_each_entry_safe(conn, tmp1, &nat->sccp_connections, list_entry) {
-		if (conn->has_remote_ref)
-			continue;
-
-		int diff = (now.tv_sec - conn->creation_time.tv_sec) / 60;
-		if (diff < SCCP_CLOSE_TIME_TIMEOUT)
-			continue;
-
-		LOGP(DNAT, LOGL_ERROR,
-			"SCCP connection 0x%x/0x%x was never confirmed on bsc nr. %d\n",
-			sccp_src_ref_to_int(&conn->real_ref),
-			sccp_src_ref_to_int(&conn->patched_ref),
-			conn->bsc->cfg->nr);
-		sccp_connection_destroy(conn);
-		destroyed = 1;
-	}
-
-	if (!destroyed)
-		goto out;
-
-	/* now close out any BSC */
-	llist_for_each_entry_safe(bsc, bsc_tmp, &nat->bsc_connections, list_entry)
-		bsc_maybe_close(bsc);
-
-out:
-	osmo_timer_schedule(&sccp_close, SCCP_CLOSE_TIME, 0);
-}
-
-extern void *tall_ctr_ctx;
-static void talloc_init_ctx()
-{
-	tall_bsc_ctx = talloc_named_const(NULL, 0, "nat");
-	msgb_talloc_ctx_init(tall_bsc_ctx, 0);
-	tall_ctr_ctx = talloc_named_const(tall_bsc_ctx, 0, "counter");
-}
-
-extern int bsc_vty_go_parent(struct vty *vty);
-
-static struct vty_app_info vty_info = {
-	.name 		= "OsmoBSCNAT",
-	.version	= PACKAGE_VERSION,
-	.go_parent_cb	= bsc_vty_go_parent,
-	.is_config_node	= bsc_vty_is_config_node,
-};
-
-
-int main(int argc, char **argv)
-{
-	int rc;
-
-	talloc_init_ctx();
-
-	osmo_init_logging(&log_info);
-
-	nat = bsc_nat_alloc();
-	if (!nat) {
-		fprintf(stderr, "Failed to allocate the BSC nat.\n");
-		return -4;
-	}
-
-	nat->mgcp_cfg = mgcp_config_alloc();
-	if (!nat->mgcp_cfg) {
-		fprintf(stderr, "Failed to allocate MGCP cfg.\n");
-		return -5;
-	}
-
-	/* We need to add mode-set for amr codecs */
-	nat->sdp_ensure_amr_mode_set = 1;
-
-	vty_info.copyright = openbsc_copyright;
-	vty_init(&vty_info);
-	logging_vty_add_cmds(NULL);
-	osmo_stats_vty_add_cmds(&log_info);
-	bsc_nat_vty_init(nat);
-	ctrl_vty_init(tall_bsc_ctx);
-
-
-	/* parse options */
-	local_addr.s_addr = INADDR_ANY;
-	handle_options(argc, argv);
-
-	nat->include_base = dirname(talloc_strdup(tall_bsc_ctx, config_file));
-
-	rate_ctr_init(tall_bsc_ctx);
-	osmo_stats_init(tall_bsc_ctx);
-
-	/* Ensure that forced enpoint allocation is turned on by default */
-	nat->mgcp_cfg->trunk.force_realloc = 1;
-
-	/* init vty and parse */
-	if (mgcp_parse_config(config_file, nat->mgcp_cfg, MGCP_BSC_NAT) < 0) {
-		fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
-		return -3;
-	}
-
-	/* start telnet after reading config for vty_get_bind_addr() */
-	if (telnet_init_dynif(tall_bsc_ctx, NULL, vty_get_bind_addr(),
-			      OSMO_VTY_PORT_BSC_NAT)) {
-		fprintf(stderr, "Creating VTY telnet line failed\n");
-		return -5;
-	}
-
-	/* over rule the VTY config for MSC IP */
-	if (msc_ip)
-		bsc_nat_set_msc_ip(nat, msc_ip);
-
-	/* seed the PRNG */
-	srand(time(NULL));
-
-	LOGP(DNAT, LOGL_NOTICE, "BSCs configured from %s\n", nat->resolved_path);
-
-	/*
-	 * Setup the MGCP code..
-	 */
-	if (bsc_mgcp_nat_init(nat) != 0)
-		return -4;
-
-	/* connect to the MSC */
-	nat->msc_con = bsc_msc_create(nat, &nat->dests);
-	if (!nat->msc_con) {
-		fprintf(stderr, "Creating a bsc_msc_connection failed.\n");
-		exit(1);
-	}
-
-	/* start control interface after reading config for
-	 * ctrl_vty_get_bind_addr() */
-	nat->ctrl = bsc_nat_controlif_setup(nat, ctrl_vty_get_bind_addr(),
-					    OSMO_CTRL_PORT_BSC_NAT);
-	if (!nat->ctrl) {
-		fprintf(stderr, "Creating the control interface failed.\n");
-		exit(1);
-	}
-
-	nat->msc_con->name = "main MSC";
-	nat->msc_con->connection_loss = msc_connection_was_lost;
-	nat->msc_con->connected = msc_connection_connected;
-	nat->msc_con->write_queue.read_cb = ipaccess_msc_read_cb;
-	nat->msc_con->write_queue.write_cb = ipaccess_msc_write_cb;;
-	nat->msc_con->write_queue.bfd.data = nat->msc_con;
-	bsc_msc_connect(nat->msc_con);
-
-	/* wait for the BSC */
-	rc = make_sock(&bsc_listen, IPPROTO_TCP, ntohl(local_addr.s_addr),
-		       5000, 0, ipaccess_listen_bsc_cb, nat);
-	if (rc != 0) {
-		fprintf(stderr, "Failed to listen for BSC.\n");
-		exit(1);
-	}
-
-	rc = bsc_ussd_init(nat);
-	if (rc != 0) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to bind the USSD socket.\n");
-		exit(1);
-	}
-
-	signal(SIGABRT, &signal_handler);
-	signal(SIGUSR1, &signal_handler);
-	osmo_init_ignore_signals();
-
-	if (daemonize) {
-		rc = osmo_daemonize();
-		if (rc < 0) {
-			perror("Error during daemonize");
-			exit(1);
-		}
-	}
-
-	/* recycle timer */
-	sccp_set_log_area(DSCCP);
-	osmo_timer_setup(&sccp_close, sccp_close_unconfirmed, NULL);
-	osmo_timer_schedule(&sccp_close, SCCP_CLOSE_TIME, 0);
-
-	while (1) {
-		osmo_select_main(0);
-	}
-
-	return 0;
-}
-
-/* Close all connections handed out to the USSD module */
-int bsc_ussd_close_connections(struct bsc_nat *nat)
-{
-	struct nat_sccp_connection *con;
-	llist_for_each_entry(con, &nat->sccp_connections, list_entry) {
-		if (con->con_local != NAT_CON_END_USSD)
-			continue;
-		if (!con->bsc)
-			continue;
-
-		nat_send_clrc_bsc(con);
-		nat_send_rlsd_bsc(con);
-	}
-
-	return 0;
-}
diff --git a/src/osmo-bsc_nat/bsc_nat_ctrl.c b/src/osmo-bsc_nat/bsc_nat_ctrl.c
deleted file mode 100644
index 128ea65..0000000
--- a/src/osmo-bsc_nat/bsc_nat_ctrl.c
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * (C) 2011-2012 by Holger Hans Peter Freyther
- * (C) 2011-2012 by On-Waves
- * (C) 2011 by Daniel Willmann
- * 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/>.
- *
- */
-
-#include <osmocom/core/talloc.h>
-
-#include <osmocom/ctrl/control_cmd.h>
-#include <osmocom/ctrl/control_if.h>
-#include <osmocom/ctrl/ports.h>
-
-#include <osmocom/vty/misc.h>
-
-#include <openbsc/ctrl.h>
-#include <openbsc/bsc_nat.h>
-#include <openbsc/bsc_msg_filter.h>
-#include <openbsc/vty.h>
-#include <openbsc/gsm_data.h>
-
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-
-#define NAT_MAX_CTRL_ID 65535
-
-static struct bsc_nat *g_nat;
-
-static int bsc_id_unused(int id, struct bsc_connection *bsc)
-{
-	struct bsc_cmd_list *pending;
-
-	llist_for_each_entry(pending, &bsc->cmd_pending, list_entry) {
-		if (pending->nat_id == id)
-			return 0;
-	}
-	return 1;
-}
-
-static int get_next_free_bsc_id(struct bsc_connection *bsc)
-{
-	int new_id, overflow = 0;
-
-	new_id = bsc->last_id;
-
-	do {
-		new_id++;
-		if (new_id == NAT_MAX_CTRL_ID) {
-			new_id = 1;
-			overflow++;
-		}
-
-		if (bsc_id_unused(new_id, bsc)) {
-			bsc->last_id = new_id;
-			return new_id;
-		}
-	} while (overflow != 2);
-
-	return -1;
-}
-
-void bsc_nat_ctrl_del_pending(struct bsc_cmd_list *pending)
-{
-	llist_del(&pending->list_entry);
-	osmo_timer_del(&pending->timeout);
-	talloc_free(pending->cmd);
-	talloc_free(pending);
-}
-
-static struct bsc_cmd_list *bsc_get_pending(struct bsc_connection *bsc, char *id_str)
-{
-	struct bsc_cmd_list *cmd_entry;
-	int id = atoi(id_str);
-	if (id == 0)
-		return NULL;
-
-	llist_for_each_entry(cmd_entry, &bsc->cmd_pending, list_entry) {
-		if (cmd_entry->nat_id == id) {
-			return cmd_entry;
-		}
-	}
-	return NULL;
-}
-
-int bsc_nat_handle_ctrlif_msg(struct bsc_connection *bsc, struct msgb *msg)
-{
-	struct ctrl_cmd *cmd;
-	struct bsc_cmd_list *pending;
-	char *var, *id;
-
-	cmd = ctrl_cmd_parse(bsc, msg);
-	msgb_free(msg);
-
-	if (!cmd) {
-		cmd = talloc_zero(bsc, struct ctrl_cmd);
-		if (!cmd) {
-			LOGP(DNAT, LOGL_ERROR, "OOM!\n");
-			return -ENOMEM;
-		}
-		cmd->type = CTRL_TYPE_ERROR;
-		cmd->id = "err";
-		cmd->reply = "Failed to parse command.";
-		goto err;
-	}
-
-	if (bsc->cfg && !llist_empty(&bsc->cfg->lac_list)) {
-		if (cmd->variable) {
-			var = talloc_asprintf(cmd, "net.0.bsc.%i.%s", bsc->cfg->nr,
-					   cmd->variable);
-			if (!var) {
-				cmd->type = CTRL_TYPE_ERROR;
-				cmd->reply = "OOM";
-				goto err;
-			}
-			talloc_free(cmd->variable);
-			cmd->variable = var;
-		}
-
-		/* We have to handle TRAPs before matching pending */
-		if (cmd->type == CTRL_TYPE_TRAP) {
-			ctrl_cmd_send_to_all(bsc->nat->ctrl, cmd);
-			talloc_free(cmd);
-			return 0;
-		}
-
-		/* Find the pending command */
-		pending = bsc_get_pending(bsc, cmd->id);
-		if (pending) {
-			id = talloc_strdup(cmd, pending->cmd->id);
-			if (!id) {
-				cmd->type = CTRL_TYPE_ERROR;
-				cmd->reply = "OOM";
-				goto err;
-			}
-			cmd->id = id;
-			ctrl_cmd_send(&pending->ccon->write_queue, cmd);
-			bsc_nat_ctrl_del_pending(pending);
-		} else {
-			/* We need to handle TRAPS here */
-			if ((cmd->type != CTRL_TYPE_ERROR) &&
-			    (cmd->type != CTRL_TYPE_TRAP)) {
-				LOGP(DNAT, LOGL_NOTICE, "Got control message "
-					"from BSC without pending entry\n");
-				cmd->type = CTRL_TYPE_ERROR;
-				cmd->reply = "No request outstanding";
-				goto err;
-			}
-		}
-	}
-	talloc_free(cmd);
-	return 0;
-err:
-	ctrl_cmd_send(&bsc->write_queue, cmd);
-	talloc_free(cmd);
-	return 0;
-}
-
-static void pending_timeout_cb(void *data)
-{
-	struct bsc_cmd_list *pending = data;
-	LOGP(DNAT, LOGL_ERROR, "Command timed out\n");
-	pending->cmd->type = CTRL_TYPE_ERROR;
-	pending->cmd->reply = "Command timed out";
-	ctrl_cmd_send(&pending->ccon->write_queue, pending->cmd);
-
-	bsc_nat_ctrl_del_pending(pending);
-}
-
-static void ctrl_conn_closed_cb(struct ctrl_connection *connection)
-{
-	struct bsc_connection *bsc;
-	struct bsc_cmd_list *pending, *tmp;
-
-	llist_for_each_entry(bsc, &g_nat->bsc_connections, list_entry) {
-		llist_for_each_entry_safe(pending, tmp, &bsc->cmd_pending, list_entry) {
-			if (pending->ccon == connection)
-				bsc_nat_ctrl_del_pending(pending);
-		}
-	}
-}
-
-static int extract_bsc_nr_variable(char *variable, unsigned int *nr, char **bsc_variable)
-{
-	char *nr_str, *tmp, *saveptr = NULL;
-
-	tmp = strtok_r(variable, ".", &saveptr);
-	tmp = strtok_r(NULL, ".", &saveptr);
-	tmp = strtok_r(NULL, ".", &saveptr);
-	nr_str = strtok_r(NULL, ".", &saveptr);
-	if (!nr_str)
-		return 0;
-	*nr = atoi(nr_str);
-
-	tmp = strtok_r(NULL, "\0", &saveptr);
-	if (!tmp)
-		return 0;
-
-	*bsc_variable = tmp;
-	return 1;
-}
-
-static int forward_to_bsc(struct ctrl_cmd *cmd)
-{
-	int ret = CTRL_CMD_HANDLED;
-	struct ctrl_cmd *bsc_cmd = NULL;
-	struct bsc_connection *bsc;
-	struct bsc_cmd_list *pending;
-	unsigned int nr;
-	char *bsc_variable;
-
-	/* Skip over the beginning (bsc.) */
-	if (!extract_bsc_nr_variable(cmd->variable, &nr, &bsc_variable)) {
-		cmd->reply = "command incomplete";
-		goto err;
-	}
-
-
-	llist_for_each_entry(bsc, &g_nat->bsc_connections, list_entry) {
-		if (!bsc->cfg)
-			continue;
-		if (!bsc->authenticated)
-			continue;
-		if (bsc->cfg->nr == nr) {
-			/* Add pending command to list */
-			pending = talloc_zero(bsc, struct bsc_cmd_list);
-			if (!pending) {
-				cmd->reply = "OOM";
-				goto err;
-			}
-
-			pending->nat_id = get_next_free_bsc_id(bsc);
-			if (pending->nat_id < 0) {
-				cmd->reply = "No free ID found";
-				goto err;
-			}
-
-			bsc_cmd = ctrl_cmd_cpy(bsc, cmd);
-			if (!bsc_cmd) {
-				cmd->reply = "Could not forward command";
-				goto err;
-			}
-
-			talloc_free(bsc_cmd->id);
-			bsc_cmd->id = talloc_asprintf(bsc_cmd, "%i", pending->nat_id);
-			if (!bsc_cmd->id) {
-				cmd->reply = "OOM";
-				goto err;
-			}
-
-			talloc_free(bsc_cmd->variable);
-			bsc_cmd->variable = talloc_strdup(bsc_cmd, bsc_variable);
-			if (!bsc_cmd->variable) {
-				cmd->reply = "OOM";
-				goto err;
-			}
-
-			if (ctrl_cmd_send(&bsc->write_queue, bsc_cmd)) {
-				cmd->reply = "Sending failed";
-				goto err;
-			}
-			pending->ccon = cmd->ccon;
-			pending->ccon->closed_cb = ctrl_conn_closed_cb;
-			pending->cmd = cmd;
-
-			/* Setup the timeout */
-			osmo_timer_setup(&pending->timeout, pending_timeout_cb,
-					 pending);
-			/* TODO: Make timeout configurable */
-			osmo_timer_schedule(&pending->timeout, 10, 0);
-			llist_add_tail(&pending->list_entry, &bsc->cmd_pending);
-
-			goto done;
-		}
-	}
-	/* We end up here if there's no bsc to handle our LAC */
-	cmd->reply = "no BSC with this nr";
-err:
-	ret = CTRL_CMD_ERROR;
-done:
-	talloc_free(bsc_cmd);
-	return ret;
-
-}
-
-
-CTRL_CMD_DEFINE(fwd_cmd, "net 0 bsc *");
-static int get_fwd_cmd(struct ctrl_cmd *cmd, void *data)
-{
-	return forward_to_bsc(cmd);
-}
-
-static int set_fwd_cmd(struct ctrl_cmd *cmd, void *data)
-{
-	return forward_to_bsc(cmd);
-}
-
-static int verify_fwd_cmd(struct ctrl_cmd *cmd, const char *value, void *data)
-{
-	return 0;
-}
-
-static int extract_bsc_cfg_variable(struct ctrl_cmd *cmd, struct bsc_config **cfg,
-				char **bsc_variable)
-{
-	unsigned int nr;
-
-	if (!extract_bsc_nr_variable(cmd->variable, &nr, bsc_variable)) {
-		cmd->reply = "command incomplete";
-		return 0;
-	}
-
-	*cfg = bsc_config_num(g_nat, nr);
-	if (!*cfg) {
-		cmd->reply = "Unknown BSC";
-		return 0;
-	}
-
-	return 1;
-}
-
-CTRL_CMD_DEFINE(net_cfg_cmd, "net 0 bsc_cfg *");
-static int get_net_cfg_cmd(struct ctrl_cmd *cmd, void *data)
-{
-	char *bsc_variable;
-	struct bsc_config *bsc_cfg;
-
-	if (!extract_bsc_cfg_variable(cmd, &bsc_cfg, &bsc_variable))
-		return CTRL_CMD_ERROR;
-
-	if (strcmp(bsc_variable, "access-list-name") == 0) {
-		cmd->reply = talloc_asprintf(cmd, "%s",
-				bsc_cfg->acc_lst_name ? bsc_cfg->acc_lst_name : "");
-		return CTRL_CMD_REPLY;
-	}
-
-	cmd->reply = "unknown command";
-	return CTRL_CMD_ERROR;
-}
-
-static int set_net_cfg_cmd(struct ctrl_cmd *cmd, void *data)
-{
-	char *bsc_variable;
-	struct bsc_config *bsc_cfg;
-
-	if (!extract_bsc_cfg_variable(cmd, &bsc_cfg, &bsc_variable))
-		return CTRL_CMD_ERROR;
-
-	if (strcmp(bsc_variable, "access-list-name") == 0) {
-		osmo_talloc_replace_string(bsc_cfg, &bsc_cfg->acc_lst_name, cmd->value);
-		cmd->reply = talloc_asprintf(cmd, "%s",
-				bsc_cfg->acc_lst_name ? bsc_cfg->acc_lst_name : "");
-		return CTRL_CMD_REPLY;
-	} else if (strcmp(bsc_variable, "no-access-list-name") == 0) {
-		talloc_free(bsc_cfg->acc_lst_name);
-		bsc_cfg->acc_lst_name = NULL;
-		cmd->reply = "";
-		return CTRL_CMD_REPLY;
-	}
-
-	cmd->reply = "unknown command";
-	return CTRL_CMD_ERROR;
-}
-
-static int verify_net_cfg_cmd(struct ctrl_cmd *cmd, const char *value, void *data)
-{
-	return 0;
-}
-
-CTRL_CMD_DEFINE(net_cfg_acc_cmd, "net 0 add allow access-list *");
-static const char *extract_acc_name(const char *var)
-{
-	char *str;
-
-	str = strstr(var, "net.0.add.allow.access-list.");
-	if (!str)
-		return NULL;
-	str += strlen("net.0.add.allow.access-list.");
-	if (strlen(str) == 0)
-		return NULL;
-	return str;
-}
-
-static int get_net_cfg_acc_cmd(struct ctrl_cmd *cmd, void *data)
-{
-	cmd->reply = "Append only";
-	return CTRL_CMD_ERROR;
-}
-
-static int set_net_cfg_acc_cmd(struct ctrl_cmd *cmd, void *data)
-{
-	const char *access_name = extract_acc_name(cmd->variable);
-	struct bsc_msg_acc_lst *acc;
-	struct bsc_msg_acc_lst_entry *entry;
-	const char *value = cmd->value;
-	int rc;
-
-	/* Should have been caught by verify_net_cfg_acc_cmd */
-	acc = bsc_msg_acc_lst_find(&g_nat->access_lists, access_name);
-	if (!acc) {
-		cmd->reply = "Access list not found";
-		return CTRL_CMD_ERROR;
-	}
-
-	entry = bsc_msg_acc_lst_entry_create(acc);
-	if (!entry) {
-		cmd->reply = "OOM";
-		return CTRL_CMD_ERROR;
-	}
-
-	rc = gsm_parse_reg(acc, &entry->imsi_allow_re, &entry->imsi_allow, 1, &value);
-	if (rc !=  0) {
-		cmd->reply = "Failed to compile expression";
-		return CTRL_CMD_ERROR;
-	}
-
-	cmd->reply = "IMSI allow added to access list";
-	return CTRL_CMD_REPLY;
-}
-
-static int verify_net_cfg_acc_cmd(struct ctrl_cmd *cmd, const char *value, void *data)
-{
-	const char *access_name = extract_acc_name(cmd->variable);
-	struct bsc_msg_acc_lst *acc = bsc_msg_acc_lst_find(&g_nat->access_lists, access_name);
-
-	if (!acc) {
-		cmd->reply = "Access list not known";
-		return -1;
-	}
-
-	return 0;
-}
-
-CTRL_CMD_DEFINE_WO_NOVRF(net_save_cmd, "net 0 save-configuration");
-
-static int set_net_save_cmd(struct ctrl_cmd *cmd, void *data)
-{
-	int rc = osmo_vty_save_config_file();
-	cmd->reply = talloc_asprintf(cmd, "%d", rc);
-	if (!cmd->reply) {
-		cmd->reply = "OOM";
-		return CTRL_CMD_ERROR;
-	}
-
-	return CTRL_CMD_REPLY;
-}
-
-struct ctrl_handle *bsc_nat_controlif_setup(struct bsc_nat *nat,
-					    const char *bind_addr, int port)
-{
-	struct ctrl_handle *ctrl;
-	int rc;
-
-
-	ctrl = bsc_controlif_setup(NULL, bind_addr, OSMO_CTRL_PORT_BSC_NAT);
-	if (!ctrl) {
-		fprintf(stderr, "Failed to initialize the control interface. Exiting.\n");
-		return NULL;
-	}
-
-	rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_fwd_cmd);
-	if (rc) {
-		fprintf(stderr, "Failed to install the control command. Exiting.\n");
-		goto error;
-	}
-	rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_cfg_cmd);
-	if (rc) {
-		fprintf(stderr, "Failed to install the net cfg command. Exiting.\n");
-		goto error;
-	}
-	rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_cfg_acc_cmd);
-	if (rc) {
-		fprintf(stderr, "Failed to install the net acc command. Exiting.\n");
-		goto error;
-	}
-	rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_save_cmd);
-	if (rc) {
-		fprintf(stderr, "Failed to install the net save command. Exiting.\n");
-		goto error;
-	}
-
-	g_nat = nat;
-	return ctrl;
-
-error:
-	osmo_fd_unregister(&ctrl->listen_fd);
-	close(ctrl->listen_fd.fd);
-	talloc_free(ctrl);
-	return NULL;
-}
-
-void bsc_nat_inform_reject(struct bsc_connection *conn, const char *imsi)
-{
-	struct ctrl_cmd *cmd;
-
-	cmd = ctrl_cmd_create(conn, CTRL_TYPE_TRAP);
-	if (!cmd) {
-		LOGP(DCTRL, LOGL_ERROR, "Failed to create TRAP command.\n");
-		return;
-	}
-
-	cmd->id = "0";
-	cmd->variable = talloc_asprintf(cmd, "net.0.bsc.%d.notification-rejection-v1",
-					conn->cfg->nr);
-	cmd->reply = talloc_asprintf(cmd, "imsi=%s", imsi);
-
-	ctrl_cmd_send_to_all(conn->cfg->nat->ctrl, cmd);
-	talloc_free(cmd);
-}
diff --git a/src/osmo-bsc_nat/bsc_nat_filter.c b/src/osmo-bsc_nat/bsc_nat_filter.c
deleted file mode 100644
index e735290..0000000
--- a/src/osmo-bsc_nat/bsc_nat_filter.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * (C) 2010-2015 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/>.
- *
- */
-
-#include <openbsc/bsc_nat.h>
-#include <openbsc/bsc_nat_sccp.h>
-#include <openbsc/bsc_msg_filter.h>
-#include <openbsc/debug.h>
-
-#include <osmocom/gsm/gsm0808.h>
-
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-#include <osmocom/gsm/protocol/gsm_04_11.h>
-
-#include <osmocom/sccp/sccp.h>
-
-/* Filter out CR data... */
-int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg,
-			struct bsc_nat_parsed *parsed, int *con_type,
-			char **imsi, struct bsc_filter_reject_cause *cause)
-{
-	struct bsc_filter_request req;
-	struct tlv_parsed tp;
-	struct gsm48_hdr *hdr48;
-	int hdr48_len;
-	int len;
-
-	*con_type = FLT_CON_TYPE_NONE;
-	cause->cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
-	cause->lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
-	*imsi = NULL;
-
-	if (parsed->gsm_type != BSS_MAP_MSG_COMPLETE_LAYER_3) {
-		LOGP(DNAT, LOGL_ERROR,
-		     "Rejecting CR message due wrong GSM Type %d\n", parsed->gsm_type);
-		return -1;
-	}
-
-	/* the parsed has had some basic l3 length check */
-	len = msg->l3h[1];
-	if (msgb_l3len(msg) - 3 < len) {
-		LOGP(DNAT, LOGL_ERROR,
-		     "The CR Data has not enough space...\n");
-		return -1;
-	}
-
-	msg->l4h = &msg->l3h[3];
-	len -= 1;
-
-	tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h, len, 0, 0);
-
-	if (!TLVP_PRESENT(&tp, GSM0808_IE_LAYER_3_INFORMATION)) {
-		LOGP(DNAT, LOGL_ERROR, "CR Data does not contain layer3 information.\n");
-		return -1;
-	}
-
-	hdr48_len = TLVP_LEN(&tp, GSM0808_IE_LAYER_3_INFORMATION);
-
-	if (hdr48_len < sizeof(*hdr48)) {
-		LOGP(DNAT, LOGL_ERROR, "GSM48 header does not fit.\n");
-		return -1;
-	}
-
-	hdr48 = (struct gsm48_hdr *) TLVP_VAL(&tp, GSM0808_IE_LAYER_3_INFORMATION);
-	req.ctx = bsc;
-	req.black_list = &bsc->nat->imsi_black_list;
-	req.access_lists = &bsc->nat->access_lists;
-	req.local_lst_name = bsc->cfg->acc_lst_name;
-	req.global_lst_name = bsc->nat->acc_lst_name;
-	req.bsc_nr = bsc->cfg->nr;
-	return bsc_msg_filter_initial(hdr48, hdr48_len, &req, con_type, imsi, 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)
-{
-	uint32_t len;
-	struct gsm48_hdr *hdr48;
-	struct bsc_filter_request req;
-
-	cause->cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
-	cause->lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
-
-	if (con->filter_state.imsi_checked)
-		return 0;
-
-	/* only care about DTAP messages */
-	if (parsed->bssap != BSSAP_MSG_DTAP)
-		return 0;
-
-	hdr48 = bsc_unpack_dtap(parsed, msg, &len);
-	if (!hdr48)
-		return -1;
-
-	req.ctx = con;
-	req.black_list = &bsc->nat->imsi_black_list;
-	req.access_lists = &bsc->nat->access_lists;
-	req.local_lst_name = bsc->cfg->acc_lst_name;
-	req.global_lst_name = bsc->nat->acc_lst_name;
-	req.bsc_nr = bsc->cfg->nr;
-	return bsc_msg_filter_data(hdr48, len, &req, &con->filter_state, cause);
-}
diff --git a/src/osmo-bsc_nat/bsc_nat_rewrite.c b/src/osmo-bsc_nat/bsc_nat_rewrite.c
deleted file mode 100644
index e7c387c..0000000
--- a/src/osmo-bsc_nat/bsc_nat_rewrite.c
+++ /dev/null
@@ -1,714 +0,0 @@
-/*
- * Message rewriting functionality
- */
-/*
- * (C) 2010-2013 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2013 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/>.
- *
- */
-
-#include <openbsc/bsc_nat.h>
-#include <openbsc/bsc_nat_sccp.h>
-#include <openbsc/bsc_msc.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/debug.h>
-#include <openbsc/ipaccess.h>
-#include <openbsc/nat_rewrite_trie.h>
-
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/gsm/gsm0808.h>
-#include <osmocom/gsm/ipa.h>
-
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-#include <osmocom/gsm/protocol/gsm_04_11.h>
-
-#include <osmocom/sccp/sccp.h>
-
-static char *trie_lookup(struct nat_rewrite *trie, const char *number,
-			regoff_t off, void *ctx)
-{
-	struct nat_rewrite_rule *rule;
-
-	if (!trie) {
-		LOGP(DCC, LOGL_ERROR,
-			"Asked to do a table lookup but no table.\n");
-		return NULL;
-	}
-
-	rule = nat_rewrite_lookup(trie, number);
-	if (!rule) {
-		LOGP(DCC, LOGL_DEBUG,
-			"Couldn't find a prefix rule for %s\n", number);
-		return NULL;
-	}
-
-	return talloc_asprintf(ctx, "%s%s", rule->rewrite, &number[off]);
-}
-
-static char *match_and_rewrite_number(void *ctx, const char *number,
-				const char *imsi, struct llist_head *list,
-				struct nat_rewrite *trie)
-{
-	struct bsc_nat_num_rewr_entry *entry;
-	char *new_number = NULL;
-
-	/* need to find a replacement and then fix it */
-	llist_for_each_entry(entry, list, list) {
-		regmatch_t matches[2];
-
-		/* check the IMSI match */
-		if (regexec(&entry->msisdn_reg, imsi, 0, NULL, 0) != 0)
-			continue;
-
-		/* this regexp matches... */
-		if (regexec(&entry->num_reg, number, 2, matches, 0) == 0
-			&& matches[1].rm_eo != -1) {
-			if (entry->is_prefix_lookup)
-				new_number = trie_lookup(trie, number,
-						matches[1].rm_so, ctx);
-			else
-				new_number = talloc_asprintf(ctx, "%s%s",
-					entry->replace,
-					&number[matches[1].rm_so]);
-		}
-
-		if (new_number)
-			break;
-	}
-
-	return new_number;
-}
-
-static char *rewrite_isdn_number(struct bsc_nat *nat, struct llist_head *rewr_list,
-				void *ctx, const char *imsi,
-				struct gsm_mncc_number *called)
-{
-	char int_number[sizeof(called->number) + 2];
-	char *number = called->number;
-
-	if (llist_empty(&nat->num_rewr)) {
-		LOGP(DCC, LOGL_DEBUG, "Rewrite rules empty.\n");
-		return NULL;
-	}
-
-	/* only ISDN plan */
-	if (called->plan != 1) {
-		LOGP(DCC, LOGL_DEBUG, "Called plan is not 1 it was %d\n",
-			called->plan);
-		return NULL;
-	}
-
-	/* international, prepend */
-	if (called->type == 1) {
-		int_number[0] = '+';
-		memcpy(&int_number[1], number, strlen(number) + 1);
-		number = int_number;
-	}
-
-	return match_and_rewrite_number(ctx, number,
-					imsi, rewr_list, nat->num_rewr_trie);
-}
-
-static void update_called_number(struct gsm_mncc_number *called,
-				const char *chosen_number)
-{
-	if (strncmp(chosen_number, "00", 2) == 0) {
-		called->type = 1;
-		osmo_strlcpy(called->number, chosen_number + 2,
-			     sizeof(called->number));
-	} else {
-		/* rewrite international to unknown */
-		if (called->type == 1)
-			called->type = 0;
-		osmo_strlcpy(called->number, chosen_number,
-			     sizeof(called->number));
-	}
-}
-
-/**
- * Rewrite non global numbers... according to rules based on the IMSI
- */
-static struct msgb *rewrite_setup(struct bsc_nat *nat, struct msgb *msg,
-				  struct bsc_nat_parsed *parsed, const char *imsi,
-				  struct gsm48_hdr *hdr48, const uint32_t len)
-{
-	struct tlv_parsed tp;
-	unsigned int payload_len;
-	struct gsm_mncc_number called;
-	struct msgb *out;
-	char *new_number_pre = NULL, *new_number_post = NULL, *chosen_number;
-	uint8_t *outptr;
-	const uint8_t *msgptr;
-	int sec_len;
-
-	/* decode and rewrite the message */
-	payload_len = len - sizeof(*hdr48);
-	tlv_parse(&tp, &gsm48_att_tlvdef, hdr48->data, payload_len, 0, 0);
-
-	/* no number, well let us ignore it */
-	if (!TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD))
-		return NULL;
-
-	memset(&called, 0, sizeof(called));
-	gsm48_decode_called(&called,
-			    TLVP_VAL(&tp, GSM48_IE_CALLED_BCD) - 1);
-
-	/* check if it looks international and stop */
-	LOGP(DCC, LOGL_DEBUG,
-		"Pre-Rewrite for IMSI(%s) Plan(%d) Type(%d) Number(%s)\n",
-		imsi, called.plan, called.type, called.number);
-	new_number_pre = rewrite_isdn_number(nat, &nat->num_rewr, msg, imsi, &called);
-
-	if (!new_number_pre) {
-		LOGP(DCC, LOGL_DEBUG, "No IMSI(%s) match found, returning message.\n",
-			imsi);
-		return NULL;
-	}
-
-	if (strlen(new_number_pre) > sizeof(called.number)) {
-		LOGP(DCC, LOGL_ERROR, "Number %s is too long for structure.\n",
-				new_number_pre);
-		talloc_free(new_number_pre);
-		return NULL;
-	}
-	update_called_number(&called, new_number_pre);
-
-	/* another run through the re-write engine with other rules */
-	LOGP(DCC, LOGL_DEBUG,
-		"Post-Rewrite for IMSI(%s) Plan(%d) Type(%d) Number(%s)\n",
-		imsi, called.plan, called.type, called.number);
-	new_number_post = rewrite_isdn_number(nat, &nat->num_rewr_post, msg,
-					imsi, &called);
-	chosen_number = new_number_post ? new_number_post : new_number_pre;
-
-
-	if (strlen(chosen_number) > sizeof(called.number)) {
-		LOGP(DCC, LOGL_ERROR, "Number %s is too long for structure.\n",
-			chosen_number);
-		talloc_free(new_number_pre);
-		talloc_free(new_number_post);
-		return NULL;
-	}
-
-	/*
-	 * Need to create a new message now based on the old onew
-	 * with a new number. We can sadly not patch this in place
-	 * so we will need to regenerate it.
-	 */
-
-	out = msgb_alloc_headroom(4096, 128, "changed-setup");
-	if (!out) {
-		LOGP(DCC, LOGL_ERROR, "Failed to allocate.\n");
-		talloc_free(new_number_pre);
-		talloc_free(new_number_post);
-		return NULL;
-	}
-
-	/* copy the header */
-	outptr = msgb_put(out, sizeof(*hdr48));
-	memcpy(outptr, hdr48, sizeof(*hdr48));
-
-	/* copy everything up to the number */
-	sec_len = TLVP_VAL(&tp, GSM48_IE_CALLED_BCD) - 2 - &hdr48->data[0];
-	outptr = msgb_put(out, sec_len);
-	memcpy(outptr, &hdr48->data[0], sec_len);
-
-	/* create the new number */
-	update_called_number(&called, chosen_number);
-	LOGP(DCC, LOGL_DEBUG,
-		"Chosen number for IMSI(%s) is Plan(%d) Type(%d) Number(%s)\n",
-		imsi, called.plan, called.type, called.number);
-	gsm48_encode_called(out, &called);
-
-	/* copy thre rest */
-	msgptr = TLVP_VAL(&tp, GSM48_IE_CALLED_BCD) +
-		 TLVP_LEN(&tp, GSM48_IE_CALLED_BCD);
-	sec_len = payload_len - (msgptr - &hdr48->data[0]);
-	outptr = msgb_put(out, sec_len);
-	memcpy(outptr, msgptr, sec_len);
-
-	talloc_free(new_number_pre);
-	talloc_free(new_number_post);
-	return out;
-}
-
-/**
- * Find a new SMSC address, returns an allocated string that needs to be
- * freed or is NULL.
- */
-static char *find_new_smsc(struct bsc_nat *nat, void *ctx, const char *imsi,
-			   const char *smsc_addr, const char *dest_nr)
-{
-	struct bsc_nat_num_rewr_entry *entry;
-	char *new_number = NULL;
-	uint8_t dest_match = llist_empty(&nat->tpdest_match);
-
-	/* We will find a new number now */
-	llist_for_each_entry(entry, &nat->smsc_rewr, list) {
-		regmatch_t matches[2];
-
-		/* check the IMSI match */
-		if (regexec(&entry->msisdn_reg, imsi, 0, NULL, 0) != 0)
-			continue;
-
-		/* this regexp matches... */
-		if (regexec(&entry->num_reg, smsc_addr, 2, matches, 0) == 0 &&
-		    matches[1].rm_eo != -1)
-			new_number = talloc_asprintf(ctx, "%s%s",
-					entry->replace,
-					&smsc_addr[matches[1].rm_so]);
-		if (new_number)
-			break;
-	}
-
-	if (!new_number)
-		return NULL;
-
-	/*
-	 * now match the number against another list
-	 */
-	llist_for_each_entry(entry, &nat->tpdest_match, list) {
-		/* check the IMSI match */
-		if (regexec(&entry->msisdn_reg, imsi, 0, NULL, 0) != 0)
-			continue;
-
-		if (regexec(&entry->num_reg, dest_nr, 0, NULL, 0) == 0) {
-			dest_match = 1;
-			break;
-		}
-	}
-
-	if (!dest_match) {
-		talloc_free(new_number);
-		return NULL;
-	}
-
-	return new_number;
-}
-
-/**
- * Clear the TP-SRR from the TPDU header
- */
-static uint8_t sms_new_tpdu_hdr(struct bsc_nat *nat, const char *imsi,
-				const char *dest_nr, uint8_t hdr)
-{
-	struct bsc_nat_num_rewr_entry *entry;
-
-	/* We will find a new number now */
-	llist_for_each_entry(entry, &nat->sms_clear_tp_srr, list) {
-		/* check the IMSI match */
-		if (regexec(&entry->msisdn_reg, imsi, 0, NULL, 0) != 0)
-			continue;
-		if (regexec(&entry->num_reg, dest_nr, 0, NULL, 0) != 0)
-			continue;
-
-		/* matched phone number and imsi */
-		return hdr & ~0x20;
-	}
-
-	return hdr;
-}
-
-/**
- * Check if we need to rewrite the number. For this SMS.
- */
-static char *sms_new_dest_nr(struct bsc_nat *nat, void *ctx,
-			     const char *imsi, const char *dest_nr)
-{
-	return match_and_rewrite_number(ctx, dest_nr, imsi,
-					&nat->sms_num_rewr, NULL);
-}
-
-/**
- * This is a helper for GSM 04.11 8.2.5.2 Destination address element
- */
-void sms_encode_addr_element(struct msgb *out, const char *new_number,
-			     int format, int tp_data)
-{
-	uint8_t new_addr_len;
-	uint8_t new_addr[26];
-
-	/*
-	 * Copy the new number. We let libosmocore encode it, then set
-	 * the extension followed after the length. Depending on if
-	 * we want to write RP we will let the TLV code add the
-	 * length for us or we need to use strlen... This is not very clear
-	 * as of 03.40 and 04.11.
-	 */
-	new_addr_len = gsm48_encode_bcd_number(new_addr, ARRAY_SIZE(new_addr),
-					       1, new_number);
-	new_addr[1] = format;
-	if (tp_data) {
-		uint8_t *data = msgb_put(out, new_addr_len);
-		memcpy(data, new_addr, new_addr_len);
-		data[0] = strlen(new_number);
-	} else {
-		msgb_lv_put(out, new_addr_len - 1, new_addr + 1);
-	}
-}
-
-static struct msgb *sms_create_new(uint8_t type, uint8_t ref,
-				   struct gsm48_hdr *old_hdr48,
-				   const uint8_t *orig_addr_ptr,
-				   int orig_addr_len, const char *new_number,
-				   const uint8_t *data_ptr, int data_len,
-				   uint8_t tpdu_first_byte,
-				   const int old_dest_len, const char *new_dest_nr)
-{
-	struct gsm48_hdr *new_hdr48;
-	struct msgb *out;
-
-	/*
-	 * We need to re-create the patched structure. This is why we have
-	 * saved the above pointers.
-	 */
-	out = msgb_alloc_headroom(4096, 128, "changed-smsc");
-	if (!out) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to allocate.\n");
-		return NULL;
-	}
-
-	out->l2h = out->data;
-	msgb_v_put(out, GSM411_MT_RP_DATA_MO);
-	msgb_v_put(out, ref);
-	msgb_lv_put(out, orig_addr_len, orig_addr_ptr);
-
-	sms_encode_addr_element(out, new_number, 0x91, 0);
-
-
-	/* Patch the TPDU from here on */
-
-	/**
-	 * Do we need to put a new TP-Destination-Address (TP-DA) here or
-	 * can we copy the old thing? For the TP-DA we need to find out the
-	 * new size.
-	 */
-	if (new_dest_nr) {
-		uint8_t *data, *new_size;
-
-		/* reserve the size and write the header */
-		new_size = msgb_put(out, 1);
-		out->l3h = new_size + 1;
-		msgb_v_put(out, tpdu_first_byte);
-		msgb_v_put(out, data_ptr[1]);
-
-		/* encode the new number and put it */
-		if (strncmp(new_dest_nr, "00", 2) == 0)
-			sms_encode_addr_element(out, new_dest_nr + 2, 0x91, 1);
-		else
-			sms_encode_addr_element(out, new_dest_nr, 0x81, 1);
-
-		/* Copy the rest after the TP-DS */
-		data = msgb_put(out, data_len - 2 - 1 - old_dest_len);
-		memcpy(data, &data_ptr[2 + 1 + old_dest_len], data_len - 2 - 1 - old_dest_len);
-
-		/* fill in the new size */
-		new_size[0] = msgb_l3len(out);
-	} else {
-		msgb_v_put(out, data_len);
-		msgb_tv_fixed_put(out, tpdu_first_byte, data_len - 1, &data_ptr[1]);
-	}
-
-	/* prepend GSM 04.08 header */
-	new_hdr48 = (struct gsm48_hdr *) msgb_push(out, sizeof(*new_hdr48) + 1);
-	memcpy(new_hdr48, old_hdr48, sizeof(*old_hdr48));
-	new_hdr48->data[0] = msgb_l2len(out);
-
-	return out;
-}
-
-/**
- * Parse the SMS and check if it needs to be rewritten
- */
-static struct msgb *rewrite_sms(struct bsc_nat *nat, struct msgb *msg,
-				struct bsc_nat_parsed *parsed, const char *imsi,
-				struct gsm48_hdr *hdr48, const uint32_t len)
-{
-	unsigned int payload_len;
-	unsigned int cp_len;
-
-	uint8_t ref;
-	uint8_t orig_addr_len, *orig_addr_ptr;
-	uint8_t dest_addr_len, *dest_addr_ptr;
-	uint8_t data_len, *data_ptr;
-	char smsc_addr[30];
-
-
-	uint8_t dest_len, orig_dest_len;
-	char _dest_nr[30];
-	char *dest_nr;
-	char *new_dest_nr;
-
-	char *new_number = NULL;
-	uint8_t tpdu_hdr;
-	struct msgb *out;
-
-	payload_len = len - sizeof(*hdr48);
-	if (payload_len < 1) {
-		LOGP(DNAT, LOGL_ERROR, "SMS too short for things. %d\n", payload_len);
-		return NULL;
-	}
-
-	cp_len = hdr48->data[0];
-	if (payload_len + 1 < cp_len) {
-		LOGP(DNAT, LOGL_ERROR, "SMS RPDU can not fit in: %d %d\n", cp_len, payload_len);
-		return NULL;
-	}
-
-	if (hdr48->data[1] != GSM411_MT_RP_DATA_MO)
-		return NULL;
-
-	if (cp_len < 5) {
-		LOGP(DNAT, LOGL_ERROR, "RD-DATA can not fit in the CP len: %d\n", cp_len);
-		return NULL;
-	}
-
-	/* RP */
-	ref = hdr48->data[2];
-	orig_addr_len = hdr48->data[3];
-	orig_addr_ptr = &hdr48->data[4];
-
-	/* the +1 is for checking if the following element has some space */
-	if (cp_len < 3 + orig_addr_len + 1) {
-		LOGP(DNAT, LOGL_ERROR, "RP-Originator addr does not fit: %d\n", orig_addr_len);
-		return NULL;
-	}
-
-	dest_addr_len = hdr48->data[3 + orig_addr_len + 1];
-	dest_addr_ptr = &hdr48->data[3 + orig_addr_len + 2];
-
-	if (cp_len < 3 + orig_addr_len + 1 + dest_addr_len + 1) {
-		LOGP(DNAT, LOGL_ERROR, "RP-Destination addr does not fit: %d\n", dest_addr_len);
-		return NULL;
-	}
-	gsm48_decode_bcd_number(smsc_addr, ARRAY_SIZE(smsc_addr), dest_addr_ptr - 1, 1);
-
-	data_len = hdr48->data[3 + orig_addr_len + 1 + dest_addr_len + 1];
-	data_ptr = &hdr48->data[3 + orig_addr_len + 1 + dest_addr_len + 2];
-
-	if (cp_len < 3 + orig_addr_len + 1 + dest_addr_len + 1 + data_len) {
-		LOGP(DNAT, LOGL_ERROR, "RP-Data does not fit: %d\n", data_len);
-		return NULL;
-	}
-
-	if (data_len < 3) {
-		LOGP(DNAT, LOGL_ERROR, "SMS-SUBMIT is too short.\n");
-		return NULL;
-	}
-
-	/* TP-PDU starts here */
-	if ((data_ptr[0] & 0x03) != GSM340_SMS_SUBMIT_MS2SC)
-		return NULL;
-
-	/*
-	 * look into the phone number. The length is in semi-octets, we will
-	 * need to add the byte for the number type as well.
-	 */
-	orig_dest_len = data_ptr[2];
-	dest_len = ((orig_dest_len + 1) / 2) + 1;
-	if (data_len < dest_len + 3 || dest_len < 2) {
-		LOGP(DNAT, LOGL_ERROR, "SMS-SUBMIT can not have TP-DestAddr.\n");
-		return NULL;
-	}
-
-	if ((data_ptr[3] & 0x80) == 0) {
-		LOGP(DNAT, LOGL_ERROR, "TP-DestAddr has extension. Not handled.\n");
-		return NULL;
-	}
-
-	if ((data_ptr[3] & 0x0F) == 0) {
-		LOGP(DNAT, LOGL_ERROR, "TP-DestAddr is of unknown type.\n");
-		return NULL;
-	}
-
-	/**
-	 * Besides of what I think I read in GSM 03.40 and 04.11 the TP-DA
-	 * contains the semi-octets as length (strlen), change it to the
-	 * the number of bytes, but then change it back.
-	 */
-	data_ptr[2] = dest_len;
-	gsm48_decode_bcd_number(_dest_nr + 2, ARRAY_SIZE(_dest_nr) - 2,
-				&data_ptr[2], 1);
-	data_ptr[2] = orig_dest_len;
-	if ((data_ptr[3] & 0x70) == 0x10) {
-		_dest_nr[0] = _dest_nr[1] = '0';
-		dest_nr = &_dest_nr[0];
-	} else {
-		dest_nr = &_dest_nr[2];
-	}
-
-	/**
-	 * Call functions to rewrite the data
-	 */
-	tpdu_hdr = sms_new_tpdu_hdr(nat, imsi, dest_nr, data_ptr[0]);
-	new_number = find_new_smsc(nat, msg, imsi, smsc_addr, dest_nr);
-	new_dest_nr = sms_new_dest_nr(nat, msg, imsi, dest_nr);
-
-	if (tpdu_hdr == data_ptr[0] && !new_number && !new_dest_nr)
-		return NULL;
-
-	out = sms_create_new(GSM411_MT_RP_DATA_MO, ref, hdr48,
-			orig_addr_ptr, orig_addr_len,
-			new_number ? new_number : smsc_addr,
-			data_ptr, data_len, tpdu_hdr,
-			dest_len, new_dest_nr);
-	talloc_free(new_number);
-	talloc_free(new_dest_nr);
-	return out;
-}
-
-struct msgb *bsc_nat_rewrite_msg(struct bsc_nat *nat, struct msgb *msg, struct bsc_nat_parsed *parsed, const char *imsi)
-{
-	struct gsm48_hdr *hdr48;
-	uint32_t len;
-	uint8_t msg_type, proto;
-	struct msgb *new_msg = NULL, *sccp;
-	uint8_t link_id;
-
-	if (!imsi || strlen(imsi) < 5)
-		return msg;
-
-	/* only care about DTAP messages */
-	if (parsed->bssap != BSSAP_MSG_DTAP)
-		return msg;
-	if (!parsed->dest_local_ref)
-		return msg;
-
-	hdr48 = bsc_unpack_dtap(parsed, msg, &len);
-	if (!hdr48)
-		return msg;
-
-	link_id = msg->l3h[1];
-	proto = gsm48_hdr_pdisc(hdr48);
-	msg_type = gsm48_hdr_msg_type(hdr48);
-
-	if (proto == GSM48_PDISC_CC && msg_type == GSM48_MT_CC_SETUP)
-		new_msg = rewrite_setup(nat, msg, parsed, imsi, hdr48, len);
-	else if (proto == GSM48_PDISC_SMS && msg_type == GSM411_MT_CP_DATA)
-		new_msg = rewrite_sms(nat, msg, parsed, imsi, hdr48, len);
-
-	if (!new_msg)
-		return msg;
-
-	/* wrap with DTAP, SCCP, then IPA. TODO: Stop copying */
-	gsm0808_prepend_dtap_header(new_msg, link_id);
-	sccp = sccp_create_dt1(parsed->dest_local_ref, new_msg->data, new_msg->len);
-	talloc_free(new_msg);
-
-	if (!sccp) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to allocate.\n");
-		return msg;
-	}
-
-	ipa_prepend_header(sccp, IPAC_PROTO_SCCP);
-
-	/* the parsed hangs off from msg but it needs to survive */
-	talloc_steal(sccp, parsed);
-	msgb_free(msg);
-	return sccp;
-}
-
-static void num_rewr_free_data(struct bsc_nat_num_rewr_entry *entry)
-{
-	regfree(&entry->msisdn_reg);
-	regfree(&entry->num_reg);
-	talloc_free(entry->replace);
-}
-
-void bsc_nat_num_rewr_entry_adapt(void *ctx, struct llist_head *head,
-				  const struct osmo_config_list *list)
-{
-	struct bsc_nat_num_rewr_entry *entry, *tmp;
-	struct osmo_config_entry *cfg_entry;
-
-	/* free the old data */
-	llist_for_each_entry_safe(entry, tmp, head, list) {
-		num_rewr_free_data(entry);
-		llist_del(&entry->list);
-		talloc_free(entry);
-	}
-
-
-	if (!list)
-		return;
-
-	llist_for_each_entry(cfg_entry, &list->entry, list) {
-		char *regexp;
-		if (cfg_entry->text[0] == '+') {
-			LOGP(DNAT, LOGL_ERROR,
-				"Plus is not allowed in the number\n");
-			continue;
-		}
-
-		entry = talloc_zero(ctx, struct bsc_nat_num_rewr_entry);
-		if (!entry) {
-			LOGP(DNAT, LOGL_ERROR,
-				"Allocation of the num_rewr entry failed.\n");
-			continue;
-		}
-
-		entry->replace = talloc_strdup(entry, cfg_entry->text);
-		if (!entry->replace) {
-			LOGP(DNAT, LOGL_ERROR,
-				"Failed to copy the replacement text.\n");
-			talloc_free(entry);
-			continue;
-		}
-
-		if (strcmp("prefix_lookup", entry->replace) == 0)
-			entry->is_prefix_lookup = 1;
-
-		/* we will now build a regexp string */
-		if (cfg_entry->mcc[0] == '^') {
-			regexp = talloc_strdup(entry, cfg_entry->mcc);
-		} else {
-			regexp = talloc_asprintf(entry, "^%s%s",
-					cfg_entry->mcc[0] == '*' ?
-						"[0-9][0-9][0-9]" : cfg_entry->mcc,
-					cfg_entry->mnc[0] == '*' ?
-						"[0-9][0-9]" : cfg_entry->mnc);
-		}
-
-		if (!regexp) {
-			LOGP(DNAT, LOGL_ERROR, "Failed to create a regexp string.\n");
-			talloc_free(entry);
-			continue;
-		}
-
-		if (regcomp(&entry->msisdn_reg, regexp, 0) != 0) {
-			LOGP(DNAT, LOGL_ERROR,
-				"Failed to compile regexp '%s'\n", regexp);
-			talloc_free(regexp);
-			talloc_free(entry);
-			continue;
-		}
-
-		talloc_free(regexp);
-		if (regcomp(&entry->num_reg, cfg_entry->option, REG_EXTENDED) != 0) {
-			LOGP(DNAT, LOGL_ERROR,
-				"Failed to compile regexp '%s'\n", cfg_entry->option);
-			regfree(&entry->msisdn_reg);
-			talloc_free(entry);
-			continue;
-		}
-
-		/* we have copied the number */
-		llist_add_tail(&entry->list, head);
-	}
-}
diff --git a/src/osmo-bsc_nat/bsc_nat_rewrite_trie.c b/src/osmo-bsc_nat/bsc_nat_rewrite_trie.c
deleted file mode 100644
index 633fa87..0000000
--- a/src/osmo-bsc_nat/bsc_nat_rewrite_trie.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/* Handling for loading a re-write file/database */
-/*
- * (C) 2013 by On-Waves
- * (C) 2013 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/>.
- *
- */
-
-#include <openbsc/nat_rewrite_trie.h>
-#include <openbsc/debug.h>
-#include <openbsc/vty.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-
-#define CHECK_IS_DIGIT_OR_FAIL(prefix, pos)						\
-	if (!isdigit(prefix[pos]) && prefix[pos] != '+') {				\
-			LOGP(DNAT, LOGL_ERROR,						\
-				"Prefix(%s) contains non ascii text at(%d=%c)\n",	\
-				prefix, pos, prefix[pos]);				\
-			goto fail;							\
-	}
-#define TO_INT(c) \
-	((c) == '+' ? 10 : ((c - '0') % 10))
-
-static void insert_rewrite_node(struct nat_rewrite_rule *rule, struct nat_rewrite *root)
-{
-	struct nat_rewrite_rule *new = &root->rule;
-
-	const int len = strlen(rule->prefix);
-	int i;
-
-	if (len <= 0) {
-		LOGP(DNAT, LOGL_ERROR, "An empty prefix does not make sense.\n");
-		goto fail;
-	}
-
-	for (i = 0; i < len - 1; ++i) {
-		int pos;
-
-		/* check if the input is valid */
-		CHECK_IS_DIGIT_OR_FAIL(rule->prefix, i);
-
-		/* check if the next node is already valid */
-		pos = TO_INT(rule->prefix[i]);
-		if (!new->rules[pos]) {
-			new->rules[pos] = talloc_zero(root, struct nat_rewrite_rule);
-			if (!new->rules[pos]) {
-				LOGP(DNAT, LOGL_ERROR,
-					"Failed to allocate memory.\n");
-				goto fail;
-			}
-
-			new->rules[pos]->empty = 1;
-		}
-
-		/* we continue here */
-		new = new->rules[pos];
-	}
-
-	/* new now points to the place where we want to add it */
-	int pos;
-
-	/* check if the input is valid */
-	CHECK_IS_DIGIT_OR_FAIL(rule->prefix, (len - 1));
-
-	/* check if the next node is already valid */
-	pos = TO_INT(rule->prefix[len - 1]);
-	if (!new->rules[pos])
-		new->rules[pos] = rule;
-	else if (new->rules[pos]->empty) {
-		/* copy over entries */
-		new->rules[pos]->empty = 0;
-		memcpy(new->rules[pos]->prefix, rule->prefix, sizeof(rule->prefix));
-		memcpy(new->rules[pos]->rewrite, rule->rewrite, sizeof(rule->rewrite));
-		talloc_free(rule);
-	} else {
-		LOGP(DNAT, LOGL_ERROR,
-			"Prefix(%s) is already installed\n", rule->prefix);
-		goto fail;
-	}
-
-	root->prefixes += 1;
-	return;
-
-fail:
-	talloc_free(rule);
-	return;
-}
-
-static void handle_line(struct nat_rewrite *rewrite, char *line)
-{
-	char *split;
-	struct nat_rewrite_rule *rule;
-	size_t size_prefix, size_end, len;
-
-
-	/* Find the ',' in the line */
-	len = strlen(line);
-	split = strstr(line, ",");
-	if (!split) {
-		LOGP(DNAT, LOGL_ERROR, "Line doesn't contain ','\n");
-		return;
-	}
-
-	/* Check if there is space for the rewrite rule */
-	size_prefix = split - line;
-	if (len - size_prefix <= 2) {
-		LOGP(DNAT, LOGL_ERROR, "No rewrite available.\n");
-		return;
-	}
-
-	/* Continue after the ',' to the end */
-	split = &line[size_prefix + 1];
-	size_end = strlen(split) - 1;
-
-	/* Check if both strings can fit into the static array */
-	if (size_prefix > sizeof(rule->prefix) - 1) {
-		LOGP(DNAT, LOGL_ERROR,
-			"Prefix is too long with %zu\n", size_prefix);
-		return;
-	}
-
-	if (size_end > sizeof(rule->rewrite) - 1) {
-		LOGP(DNAT, LOGL_ERROR,
-			"Rewrite is too long with %zu on %s\n",
-			size_end, &line[size_prefix + 1]);
-		return;
-	}
-
-	/* Now create the entry and insert it into the trie */
-	rule = talloc_zero(rewrite, struct nat_rewrite_rule);
-	if (!rule) {
-		LOGP(DNAT, LOGL_ERROR, "Can not allocate memory\n");
-		return;
-	}
-
-	memcpy(rule->prefix, line, size_prefix);
-	assert(size_prefix < sizeof(rule->prefix));
-	rule->prefix[size_prefix] = '\0';
-
-	memcpy(rule->rewrite, split, size_end);
-	assert(size_end < sizeof(rule->rewrite));
-	rule->rewrite[size_end] = '\0';
-
-	/* now insert and balance the tree */
-	insert_rewrite_node(rule, rewrite);
-}
-
-struct nat_rewrite *nat_rewrite_parse(void *ctx, const char *filename)
-{
-	FILE *file;
-	char *line = NULL;
-	size_t n = 0;
-	struct nat_rewrite *res;
-
-	file = fopen(filename, "r");
-	if (!file)
-		return NULL;
-
-	res = talloc_zero(ctx, struct nat_rewrite);
-	if (!res) {
-		fclose(file);
-		return NULL;
-	}
-
-	/* mark the root as empty */
-	res->rule.empty = 1;
-
-	while (getline(&line, &n, file) != -1) {
-		handle_line(res, line);
-	}
-
-	free(line);
-	fclose(file);
-	return res;
-}
-
-/**
- * Simple find that tries to do a longest match...
- */
-struct nat_rewrite_rule *nat_rewrite_lookup(struct nat_rewrite *rewrite,
-					const char *prefix)
-{
-	struct nat_rewrite_rule *rule = &rewrite->rule;
-	struct nat_rewrite_rule *last = NULL;
-	const int len = OSMO_MIN(strlen(prefix), (sizeof(rule->prefix) - 1));
-	int i;
-
-	for (i = 0; rule && i < len; ++i) {
-		int pos;
-
-		CHECK_IS_DIGIT_OR_FAIL(prefix, i);
-		pos = TO_INT(prefix[i]);
-
-		rule = rule->rules[pos];
-		if (rule && !rule->empty)
-			last = rule;
-	}
-
-	return last;
-
-fail:
-	return NULL;
-}
-
-static void nat_rewrite_dump_rec(struct nat_rewrite_rule *rule)
-{
-	int i;
-	if (!rule->empty)
-		printf("%s,%s\n", rule->prefix, rule->rewrite);
-
-	for (i = 0; i < ARRAY_SIZE(rule->rules); ++i) {
-		if (!rule->rules[i])
-			continue;
-		nat_rewrite_dump_rec(rule->rules[i]);
-	}
-}
-
-void nat_rewrite_dump(struct nat_rewrite *rewrite)
-{
-	nat_rewrite_dump_rec(&rewrite->rule);
-}
-
-static void nat_rewrite_dump_rec_vty(struct vty *vty, struct nat_rewrite_rule *rule)
-{
-	int i;
-	if (!rule->empty)
-		vty_out(vty, "%s,%s%s", rule->prefix, rule->rewrite, VTY_NEWLINE);
-
-	for (i = 0; i < ARRAY_SIZE(rule->rules); ++i) {
-		if (!rule->rules[i])
-			continue;
-		nat_rewrite_dump_rec_vty(vty, rule->rules[i]);
-	}
-}
-
-void nat_rewrite_dump_vty(struct vty *vty, struct nat_rewrite *rewrite)
-{
-	nat_rewrite_dump_rec_vty(vty, &rewrite->rule);
-}
diff --git a/src/osmo-bsc_nat/bsc_nat_utils.c b/src/osmo-bsc_nat/bsc_nat_utils.c
deleted file mode 100644
index c12b29f..0000000
--- a/src/osmo-bsc_nat/bsc_nat_utils.c
+++ /dev/null
@@ -1,535 +0,0 @@
-
-/* BSC Multiplexer/NAT Utilities */
-
-/*
- * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2011 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/>.
- *
- */
-
-#include <openbsc/bsc_nat.h>
-#include <openbsc/bsc_nat_sccp.h>
-#include <openbsc/bsc_msg_filter.h>
-#include <openbsc/bsc_msc.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/debug.h>
-#include <openbsc/ipaccess.h>
-#include <openbsc/vty.h>
-
-#include <osmocom/core/linuxlist.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/stats.h>
-#include <osmocom/gsm/gsm0808.h>
-#include <osmocom/gsm/ipa.h>
-
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-#include <osmocom/gsm/protocol/gsm_04_11.h>
-
-#include <osmocom/sccp/sccp.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-
-static const struct rate_ctr_desc bsc_cfg_ctr_description[] = {
-	[BCFG_CTR_SCCP_CONN]     = { "sccp.conn",      "SCCP Connections         "},
-	[BCFG_CTR_SCCP_CALLS]    = { "sccp.calls",     "SCCP Assignment Commands "},
-	[BCFG_CTR_NET_RECONN]    = { "net.reconnects", "Network reconnects       "},
-	[BCFG_CTR_DROPPED_SCCP]  = { "dropped.sccp",   "Dropped SCCP connections."},
-	[BCFG_CTR_DROPPED_CALLS] = { "dropped.calls",  "Dropped active calls.    "},
-	[BCFG_CTR_REJECTED_CR]   = { "rejected.cr",    "Rejected CR due filter   "},
-	[BCFG_CTR_REJECTED_MSG]  = { "rejected.msg",   "Rejected MSG due filter  "},
-	[BCFG_CTR_ILL_PACKET]    = { "rejected.ill",   "Rejected due parse error "},
-	[BCFG_CTR_CON_TYPE_LU]   = { "conn.lu",        "Conn Location Update     "},
-	[BCFG_CTR_CON_CMSERV_RQ] = { "conn.rq",        "Conn CM Service Req      "},
-	[BCFG_CTR_CON_PAG_RESP]  = { "conn.pag",       "Conn Paging Response     "},
-	[BCFG_CTR_CON_SSA]       = { "conn.ssa",       "Conn USSD                "},
-	[BCFG_CTR_CON_OTHER]     = { "conn.other",     "Conn Other               "},
-};
-
-static const struct rate_ctr_group_desc bsc_cfg_ctrg_desc = {
-	.group_name_prefix = "nat.bsc",
-	.group_description = "NAT BSC Statistics",
-	.num_ctr = ARRAY_SIZE(bsc_cfg_ctr_description),
-	.ctr_desc = bsc_cfg_ctr_description,
-	.class_id = OSMO_STATS_CLASS_PEER,
-};
-
-struct bsc_nat *bsc_nat_alloc(void)
-{
-	struct bsc_nat *nat = talloc_zero(tall_bsc_ctx, struct bsc_nat);
-	if (!nat)
-		return NULL;
-
-	nat->main_dest = talloc_zero(nat, struct bsc_msc_dest);
-	if (!nat->main_dest) {
-		talloc_free(nat);
-		return NULL;
-	}
-
-	INIT_LLIST_HEAD(&nat->sccp_connections);
-	INIT_LLIST_HEAD(&nat->bsc_connections);
-	INIT_LLIST_HEAD(&nat->paging_groups);
-	INIT_LLIST_HEAD(&nat->bsc_configs);
-	INIT_LLIST_HEAD(&nat->access_lists);
-	INIT_LLIST_HEAD(&nat->dests);
-	INIT_LLIST_HEAD(&nat->num_rewr);
-	INIT_LLIST_HEAD(&nat->num_rewr_post);
-	INIT_LLIST_HEAD(&nat->smsc_rewr);
-	INIT_LLIST_HEAD(&nat->tpdest_match);
-	INIT_LLIST_HEAD(&nat->sms_clear_tp_srr);
-	INIT_LLIST_HEAD(&nat->sms_num_rewr);
-
-	nat->stats.sccp.conn = osmo_counter_alloc("nat.sccp.conn");
-	nat->stats.sccp.calls = osmo_counter_alloc("nat.sccp.calls");
-	nat->stats.bsc.reconn = osmo_counter_alloc("nat.bsc.conn");
-	nat->stats.bsc.auth_fail = osmo_counter_alloc("nat.bsc.auth_fail");
-	nat->stats.msc.reconn = osmo_counter_alloc("nat.msc.conn");
-	nat->stats.ussd.reconn = osmo_counter_alloc("nat.ussd.conn");
-	nat->auth_timeout = 2;
-	nat->ping_timeout = 20;
-	nat->pong_timeout = 5;
-
-	llist_add(&nat->main_dest->list, &nat->dests);
-	nat->main_dest->ip = talloc_strdup(nat, "127.0.0.1");
-	nat->main_dest->port = 5000;
-
-	return nat;
-}
-
-void bsc_nat_free(struct bsc_nat *nat)
-{
-	struct bsc_config *cfg, *tmp;
-	struct bsc_msg_acc_lst *lst, *tmp_lst;
-
-	llist_for_each_entry_safe(cfg, tmp, &nat->bsc_configs, entry)
-		bsc_config_free(cfg);
-	llist_for_each_entry_safe(lst, tmp_lst, &nat->access_lists, list)
-		bsc_msg_acc_lst_delete(lst);
-
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, NULL);
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr_post, NULL);
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->sms_clear_tp_srr, NULL);
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->sms_num_rewr, NULL);
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->tpdest_match, NULL);
-
-	osmo_counter_free(nat->stats.sccp.conn);
-	osmo_counter_free(nat->stats.sccp.calls);
-	osmo_counter_free(nat->stats.bsc.reconn);
-	osmo_counter_free(nat->stats.bsc.auth_fail);
-	osmo_counter_free(nat->stats.msc.reconn);
-	osmo_counter_free(nat->stats.ussd.reconn);
-	talloc_free(nat->mgcp_cfg);
-	talloc_free(nat);
-}
-
-void bsc_nat_set_msc_ip(struct bsc_nat *nat, const char *ip)
-{
-	osmo_talloc_replace_string(nat, &nat->main_dest->ip, ip);
-}
-
-struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat)
-{
-	struct bsc_connection *con = talloc_zero(nat, struct bsc_connection);
-	if (!con)
-		return NULL;
-
-	con->nat = nat;
-	osmo_wqueue_init(&con->write_queue, 100);
-	INIT_LLIST_HEAD(&con->cmd_pending);
-	INIT_LLIST_HEAD(&con->pending_dlcx);
-	return con;
-}
-
-struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token,
-				    unsigned int number)
-{
-	struct bsc_config *conf = talloc_zero(nat, struct bsc_config);
-	if (!conf)
-		return NULL;
-
-	conf->token = talloc_strdup(conf, token);
-	conf->nr = number;
-	conf->nat = nat;
-	conf->max_endpoints = 32;
-	conf->paging_group = PAGIN_GROUP_UNASSIGNED;
-
-	INIT_LLIST_HEAD(&conf->lac_list);
-
-	llist_add_tail(&conf->entry, &nat->bsc_configs);
-	++nat->num_bsc;
-
-	conf->stats.ctrg = rate_ctr_group_alloc(conf, &bsc_cfg_ctrg_desc, conf->nr);
-	if (!conf->stats.ctrg) {
-		llist_del(&conf->entry);
-		talloc_free(conf);
-		return NULL;
-	}
-
-	return conf;
-}
-
-struct bsc_config *bsc_config_by_token(struct bsc_nat *nat, const char *token, int len)
-{
-	struct bsc_config *conf;
-
-	llist_for_each_entry(conf, &nat->bsc_configs, entry) {
-		/*
-		 * Add the '\0' of the token for the memcmp, the IPA messages
-		 * for some reason added null termination.
-		 */
-		const int token_len = strlen(conf->token) + 1;
-
-		if (token_len == len && memcmp(conf->token, token, token_len) == 0)
-			return conf;
-	}
-
-	return NULL;
-}
-
-void bsc_config_free(struct bsc_config *cfg)
-{
-	llist_del(&cfg->entry);
-	rate_ctr_group_free(cfg->stats.ctrg);
-	cfg->nat->num_bsc--;
-	OSMO_ASSERT(cfg->nat->num_bsc >= 0)
-	talloc_free(cfg);
-}
-
-static void _add_lac(void *ctx, struct llist_head *list, int _lac)
-{
-	struct bsc_lac_entry *lac;
-
-	llist_for_each_entry(lac, list, entry)
-		if (lac->lac == _lac)
-			return;
-
-	lac = talloc_zero(ctx, struct bsc_lac_entry);
-	if (!lac) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to allocate.\n");
-		return;
-	}
-
-	lac->lac = _lac;
-	llist_add_tail(&lac->entry, list);
-}
-
-static void _del_lac(struct llist_head *list, int _lac)
-{
-	struct bsc_lac_entry *lac;
-
-	llist_for_each_entry(lac, list, entry)
-		if (lac->lac == _lac) {
-			llist_del(&lac->entry);
-			talloc_free(lac);
-			return;
-		}
-}
-
-void bsc_config_add_lac(struct bsc_config *cfg, int _lac)
-{
-	_add_lac(cfg, &cfg->lac_list, _lac);
-}
-
-void bsc_config_del_lac(struct bsc_config *cfg, int _lac)
-{
-	_del_lac(&cfg->lac_list, _lac);
-}
-
-struct bsc_nat_paging_group *bsc_nat_paging_group_create(struct bsc_nat *nat, int group)
-{
-	struct bsc_nat_paging_group *pgroup;
-
-	pgroup = talloc_zero(nat, struct bsc_nat_paging_group);
-	if (!pgroup) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to allocate a paging group.\n");
-		return NULL;
-	}
-
-	pgroup->nr = group;
-	INIT_LLIST_HEAD(&pgroup->lists);
-	llist_add_tail(&pgroup->entry, &nat->paging_groups);
-	return pgroup;
-}
-
-void bsc_nat_paging_group_delete(struct bsc_nat_paging_group *pgroup)
-{
-	llist_del(&pgroup->entry);
-	talloc_free(pgroup);
-}
-
-struct bsc_nat_paging_group *bsc_nat_paging_group_num(struct bsc_nat *nat, int group)
-{
-	struct bsc_nat_paging_group *pgroup;
-
-	llist_for_each_entry(pgroup, &nat->paging_groups, entry)
-		if (pgroup->nr == group)
-			return pgroup;
-
-	return NULL;
-}
-
-void bsc_nat_paging_group_add_lac(struct bsc_nat_paging_group *pgroup, int lac)
-{
-	_add_lac(pgroup, &pgroup->lists, lac);
-}
-
-void bsc_nat_paging_group_del_lac(struct bsc_nat_paging_group *pgroup, int lac)
-{
-	_del_lac(&pgroup->lists, lac);
-}
-
-int bsc_config_handles_lac(struct bsc_config *cfg, int lac_nr)
-{
-	struct bsc_nat_paging_group *pgroup;
-	struct bsc_lac_entry *entry;
-
-	llist_for_each_entry(entry, &cfg->lac_list, entry)
-		if (entry->lac == lac_nr)
-			return 1;
-
-	/* now lookup the paging group */
-	pgroup = bsc_nat_paging_group_num(cfg->nat, cfg->paging_group);
-	if (!pgroup)
-		return 0;
-
-	llist_for_each_entry(entry, &pgroup->lists, entry)
-		if (entry->lac == lac_nr)
-			return 1;
-
-	return 0;
-}
-
-void sccp_connection_destroy(struct nat_sccp_connection *conn)
-{
-	LOGP(DNAT, LOGL_DEBUG, "Destroy 0x%x <-> 0x%x mapping for con %p\n",
-	     sccp_src_ref_to_int(&conn->real_ref),
-	     sccp_src_ref_to_int(&conn->patched_ref), conn->bsc);
-	bsc_mgcp_dlcx(conn);
-	llist_del(&conn->list_entry);
-	talloc_free(conn);
-}
-
-
-int bsc_nat_find_paging(struct msgb *msg,
-			const uint8_t **out_data, int *out_leng)
-{
-	int data_length;
-	const uint8_t *data;
-	struct tlv_parsed tp;
-
-	if (!msg->l3h || msgb_l3len(msg) < 3) {
-		LOGP(DNAT, LOGL_ERROR, "Paging message is too short.\n");
-		return -1;
-	}
-
-	tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 3, msgb_l3len(msg) - 3, 0, 0);
-	if (!TLVP_PRESENT(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST)) {
-		LOGP(DNAT, LOGL_ERROR, "No CellIdentifier List inside paging msg.\n");
-		return -2;
-	}
-
-	data_length = TLVP_LEN(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
-	data = TLVP_VAL(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
-
-	/* No need to try a different BSS */
-	if (data[0] == CELL_IDENT_BSS) {
-		return -3;
-	} else if (data[0] != CELL_IDENT_LAC) {
-		LOGP(DNAT, LOGL_ERROR, "Unhandled cell ident discrminator: %d\n", data[0]);
-		return -4;
-	}
-
-	*out_data = &data[1];
-	*out_leng = data_length - 1;
-	return 0;
-}
-
-int bsc_write_mgcp(struct bsc_connection *bsc, const uint8_t *data, unsigned int length)
-{
-	struct msgb *msg;
-
-	if (length > 4096 - 128) {
-		LOGP(DLINP, LOGL_ERROR, "Can not send message of that size.\n");
-		return -1;
-	}
-
-	msg = msgb_alloc_headroom(4096, 128, "to-bsc");
-	if (!msg) {
-		LOGP(DLINP, LOGL_ERROR, "Failed to allocate memory for BSC msg.\n");
-		return -1;
-	}
-
-	/* copy the data */
-	msg->l3h = msgb_put(msg, length);
-	memcpy(msg->l3h, data, length);
-
-        return bsc_write(bsc, msg, IPAC_PROTO_MGCP_OLD);
-}
-
-int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int proto)
-{
-	return bsc_do_write(&bsc->write_queue, msg, proto);
-}
-
-int bsc_do_write(struct osmo_wqueue *queue, struct msgb *msg, int proto)
-{
-	/* prepend the header */
-	ipa_prepend_header(msg, proto);
-	return bsc_write_msg(queue, msg);
-}
-
-int bsc_write_msg(struct osmo_wqueue *queue, struct msgb *msg)
-{
-	if (osmo_wqueue_enqueue(queue, msg) != 0) {
-		LOGP(DLINP, LOGL_ERROR, "Failed to enqueue the write.\n");
-		msgb_free(msg);
-		return -1;
-	}
-
-	return 0;
-}
-
-struct gsm48_hdr *bsc_unpack_dtap(struct bsc_nat_parsed *parsed,
-				  struct msgb *msg, uint32_t *len)
-{
-	/* gsm_type is actually the size of the dtap */
-	*len = parsed->gsm_type;
-	if (*len < msgb_l3len(msg) - 3) {
-		LOGP(DNAT, LOGL_ERROR, "Not enough space for DTAP.\n");
-		return NULL;
-	}
-
-	if (msgb_l3len(msg) - 3 < msg->l3h[2]) {
-		LOGP(DNAT, LOGL_ERROR,
-		     "GSM48 payload does not fit: %d %d\n",
-		     msg->l3h[2], msgb_l3len(msg) - 3);
-		return NULL;
-	}
-
-	msg->l4h = &msg->l3h[3];
-	return (struct gsm48_hdr *) msg->l4h;
-}
-
-static const char *con_types [] = {
-	[FLT_CON_TYPE_NONE] = "n/a",
-	[FLT_CON_TYPE_LU] = "Location Update",
-	[FLT_CON_TYPE_CM_SERV_REQ] = "CM Serv Req",
-	[FLT_CON_TYPE_PAG_RESP] = "Paging Response",
-	[FLT_CON_TYPE_SSA] = "Supplementar Service Activation",
-	[FLT_CON_TYPE_LOCAL_REJECT] = "Local Reject",
-	[FLT_CON_TYPE_OTHER] = "Other",
-};
-
-const char *bsc_con_type_to_string(int type)
-{
-	return con_types[type];
-}
-
-int bsc_nat_msc_is_connected(struct bsc_nat *nat)
-{
-	return nat->msc_con->is_connected;
-}
-
-static const int con_to_ctr[] = {
-	[FLT_CON_TYPE_NONE]		= -1,
-	[FLT_CON_TYPE_LU]		= BCFG_CTR_CON_TYPE_LU,
-	[FLT_CON_TYPE_CM_SERV_REQ]	= BCFG_CTR_CON_CMSERV_RQ,
-	[FLT_CON_TYPE_PAG_RESP]		= BCFG_CTR_CON_PAG_RESP,
-	[FLT_CON_TYPE_SSA]		= BCFG_CTR_CON_SSA,
-	[FLT_CON_TYPE_LOCAL_REJECT]	= -1,
-	[FLT_CON_TYPE_OTHER]		= BCFG_CTR_CON_OTHER,
-};
-
-int bsc_conn_type_to_ctr(struct nat_sccp_connection *conn)
-{
-	return con_to_ctr[conn->filter_state.con_type];
-}
-
-int bsc_write_cb(struct osmo_fd *bfd, struct msgb *msg)
-{
-	int rc;
-
-	rc = write(bfd->fd, msg->data, msg->len);
-	if (rc != msg->len)
-		LOGP(DNAT, LOGL_ERROR, "Failed to write message to the BSC.\n");
-
-	return rc;
-}
-
-static void extract_lac(const uint8_t *data, uint16_t *lac, uint16_t *ci)
-{
-	memcpy(lac, &data[0], sizeof(*lac));
-	memcpy(ci, &data[2], sizeof(*ci));
-
-	*lac = ntohs(*lac);
-	*ci = ntohs(*ci);
-}
-
-int bsc_nat_extract_lac(struct bsc_connection *bsc,
-			struct nat_sccp_connection *con,
-			struct bsc_nat_parsed *parsed, struct msgb *msg)
-{
-	int data_length;
-	const uint8_t *data;
-	struct tlv_parsed tp;
-	uint16_t lac, ci;
-
-	if (parsed->gsm_type != BSS_MAP_MSG_COMPLETE_LAYER_3) {
-		LOGP(DNAT, LOGL_ERROR, "Can only extract LAC from Complete Layer3\n");
-		return -1;
-	}
-
-	if (!msg->l3h || msgb_l3len(msg) < 3) {
-		LOGP(DNAT, LOGL_ERROR, "Complete Layer3 mssage is too short.\n");
-		return -1;
-	}
-
-	tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 3, msgb_l3len(msg) - 3, 0, 0);
-	if (!TLVP_PRESENT(&tp, GSM0808_IE_CELL_IDENTIFIER)) {
-		LOGP(DNAT, LOGL_ERROR, "No CellIdentifier List inside paging msg.\n");
-		return -2;
-	}
-
-	data_length = TLVP_LEN(&tp, GSM0808_IE_CELL_IDENTIFIER);
-	data = TLVP_VAL(&tp, GSM0808_IE_CELL_IDENTIFIER);
-
-	/* Attemt to get the LAC/CI from it */
-	if (data[0] == CELL_IDENT_WHOLE_GLOBAL) {
-		if (data_length != 8) {
-			LOGP(DNAT, LOGL_ERROR,
-				"Ident too short: %d\n", data_length);
-			return -3;
-		}
-		extract_lac(&data[1 + 3], &lac, &ci);
-	} else if (data[0] == CELL_IDENT_LAC_AND_CI) {
-		if (data_length != 5) {
-			LOGP(DNAT, LOGL_ERROR,
-				"Ident too short: %d\n", data_length);
-			return -3;
-		}
-		extract_lac(&data[1], &lac, &ci);
-	} else {
-		LOGP(DNAT, LOGL_ERROR,
-			"Unhandled cell identifier: %d\n", data[0]);
-		return -1;
-	}
-
-	con->lac = lac;
-	con->ci = ci;
-	return 0;
-}
diff --git a/src/osmo-bsc_nat/bsc_nat_vty.c b/src/osmo-bsc_nat/bsc_nat_vty.c
deleted file mode 100644
index a11ae15..0000000
--- a/src/osmo-bsc_nat/bsc_nat_vty.c
+++ /dev/null
@@ -1,1336 +0,0 @@
-/* OpenBSC NAT interface to quagga VTY */
-/* (C) 2010-2015 by Holger Hans Peter Freyther
- * (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/>.
- *
- */
-
-#include <openbsc/vty.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/bsc_nat.h>
-#include <openbsc/bsc_nat_sccp.h>
-#include <openbsc/bsc_msg_filter.h>
-#include <openbsc/bsc_msc.h>
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/mgcp.h>
-#include <openbsc/vty.h>
-#include <openbsc/nat_rewrite_trie.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/vty/logging.h>
-#include <osmocom/vty/misc.h>
-#include <openbsc/osmux.h>
-
-#include <osmocom/sccp/sccp.h>
-
-#include <stdlib.h>
-#include <stdbool.h>
-
-static struct bsc_nat *_nat;
-
-
-#define BSC_STR "Information about BSCs\n"
-#define MGCP_STR "MGCP related status\n"
-#define PAGING_STR "Paging\n"
-#define SMSC_REWRITE "SMSC Rewriting\n"
-
-static struct cmd_node nat_node = {
-	NAT_NODE,
-	"%s(config-nat)# ",
-	1,
-};
-
-static struct cmd_node bsc_node = {
-	NAT_BSC_NODE,
-	"%s(config-nat-bsc)# ",
-	1,
-};
-
-static struct cmd_node pgroup_node = {
-	PGROUP_NODE,
-	"%s(config-nat-paging-group)# ",
-	1,
-};
-
-static int config_write_pgroup(struct vty *vty)
-{
-	return CMD_SUCCESS;
-}
-
-static void dump_lac(struct vty *vty, struct llist_head *head)
-{
-	struct bsc_lac_entry *lac;
-	llist_for_each_entry(lac, head, entry)
-		vty_out(vty, "  location_area_code %u%s", lac->lac, VTY_NEWLINE);
-}
-
-
-static void write_pgroup_lst(struct vty *vty, struct bsc_nat_paging_group *pgroup)
-{
-	vty_out(vty, " paging-group %d%s", pgroup->nr, VTY_NEWLINE);
-	dump_lac(vty, &pgroup->lists);
-}
-
-static int config_write_nat(struct vty *vty)
-{
-	struct bsc_msg_acc_lst *lst;
-	struct bsc_nat_paging_group *pgroup;
-
-	vty_out(vty, "nat%s", VTY_NEWLINE);
-	vty_out(vty, " msc ip %s%s", _nat->main_dest->ip, VTY_NEWLINE);
-	vty_out(vty, " msc port %d%s", _nat->main_dest->port, VTY_NEWLINE);
-	vty_out(vty, " timeout auth %d%s", _nat->auth_timeout, VTY_NEWLINE);
-	vty_out(vty, " timeout ping %d%s", _nat->ping_timeout, VTY_NEWLINE);
-	vty_out(vty, " timeout pong %d%s", _nat->pong_timeout, VTY_NEWLINE);
-	if (_nat->include_file)
-		vty_out(vty, " bscs-config-file %s%s", _nat->include_file, VTY_NEWLINE);
-	if (_nat->token)
-		vty_out(vty, " token %s%s", _nat->token, VTY_NEWLINE);
-	vty_out(vty, " ip-dscp %d%s", _nat->bsc_ip_dscp, VTY_NEWLINE);
-	if (_nat->acc_lst_name)
-		vty_out(vty, " access-list-name %s%s", _nat->acc_lst_name, VTY_NEWLINE);
-	if (_nat->imsi_black_list_fn)
-		vty_out(vty, " imsi-black-list-file-name %s%s",
-			_nat->imsi_black_list_fn, VTY_NEWLINE);
-	if (_nat->ussd_lst_name)
-		vty_out(vty, " ussd-list-name %s%s", _nat->ussd_lst_name, VTY_NEWLINE);
-	if (_nat->ussd_query)
-		vty_out(vty, " ussd-query %s%s", _nat->ussd_query, VTY_NEWLINE);
-	if (_nat->ussd_token)
-		vty_out(vty, " ussd-token %s%s", _nat->ussd_token, VTY_NEWLINE);
-	if (_nat->ussd_local)
-		vty_out(vty, " ussd-local-ip %s%s", _nat->ussd_local, VTY_NEWLINE);
-
-	if (_nat->num_rewr_name)
-		vty_out(vty, " number-rewrite %s%s", _nat->num_rewr_name, VTY_NEWLINE);
-	if (_nat->num_rewr_post_name)
-		vty_out(vty, " number-rewrite-post %s%s",
-			_nat->num_rewr_post_name, VTY_NEWLINE);
-
-	if (_nat->smsc_rewr_name)
-		vty_out(vty, " rewrite-smsc addr %s%s",
-			_nat->smsc_rewr_name, VTY_NEWLINE);
-	if (_nat->tpdest_match_name)
-		vty_out(vty, " rewrite-smsc tp-dest-match %s%s",
-			_nat->tpdest_match_name, VTY_NEWLINE);
-	if (_nat->sms_clear_tp_srr_name)
-		vty_out(vty, " sms-clear-tp-srr %s%s",
-			_nat->sms_clear_tp_srr_name, VTY_NEWLINE);
-	if (_nat->sms_num_rewr_name)
-		vty_out(vty, " sms-number-rewrite %s%s",
-			_nat->sms_num_rewr_name, VTY_NEWLINE);
-	if (_nat->num_rewr_trie_name)
-		vty_out(vty, " prefix-tree %s%s",
-			_nat->num_rewr_trie_name, VTY_NEWLINE);
-
-	llist_for_each_entry(lst, &_nat->access_lists, list)
-		bsc_msg_acc_lst_write(vty, lst);
-	llist_for_each_entry(pgroup, &_nat->paging_groups, entry)
-		write_pgroup_lst(vty, pgroup);
-	if (_nat->mgcp_ipa)
-		vty_out(vty, " use-msc-ipa-for-mgcp%s", VTY_NEWLINE);
-	vty_out(vty, " %ssdp-ensure-amr-mode-set%s",
-		_nat->sdp_ensure_amr_mode_set ? "" : "no ", VTY_NEWLINE);
-
-	return CMD_SUCCESS;
-}
-
-static void config_write_bsc_single(struct vty *vty, struct bsc_config *bsc)
-{
-	vty_out(vty, " bsc %u%s", bsc->nr, VTY_NEWLINE);
-	vty_out(vty, "  token %s%s", bsc->token, VTY_NEWLINE);
-	if (bsc->key_present)
-		vty_out(vty, "  auth-key %s%s", osmo_hexdump(bsc->key, 16), VTY_NEWLINE);
-	dump_lac(vty, &bsc->lac_list);
-	if (bsc->description)
-		vty_out(vty, "  description %s%s", bsc->description, VTY_NEWLINE);
-	if (bsc->acc_lst_name)
-		vty_out(vty, "  access-list-name %s%s", bsc->acc_lst_name, VTY_NEWLINE);
-	vty_out(vty, "  max-endpoints %d%s", bsc->max_endpoints, VTY_NEWLINE);
-	if (bsc->paging_group != -1)
-		vty_out(vty, "  paging group %d%s", bsc->paging_group, VTY_NEWLINE);
-	vty_out(vty, "  paging forbidden %d%s", bsc->forbid_paging, VTY_NEWLINE);
-	switch (bsc->osmux) {
-	case OSMUX_USAGE_ON:
-		vty_out(vty, "  osmux on%s", VTY_NEWLINE);
-		break;
-	case OSMUX_USAGE_ONLY:
-		vty_out(vty, "  osmux only%s", VTY_NEWLINE);
-		break;
-	}
-}
-
-static int config_write_bsc(struct vty *vty)
-{
-	struct bsc_config *bsc;
-
-	llist_for_each_entry(bsc, &_nat->bsc_configs, entry)
-		config_write_bsc_single(vty, bsc);
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_bscs, show_bscs_cmd, "show bscs-config",
-      SHOW_STR "Show configured BSCs\n"
-      "Both from included file and vty\n")
-{
-	vty_out(vty, "BSCs configuration loaded from %s:%s", _nat->resolved_path,
-		VTY_NEWLINE);
-	return config_write_bsc(vty);
-}
-
-DEFUN(show_sccp, show_sccp_cmd, "show sccp connections",
-      SHOW_STR "Display information about SCCP\n"
-      "All active connections\n")
-{
-	struct nat_sccp_connection *con;
-	vty_out(vty, "Listing all open SCCP connections%s", VTY_NEWLINE);
-
-	llist_for_each_entry(con, &_nat->sccp_connections, list_entry) {
-		vty_out(vty, "For BSC Nr: %d BSC ref: 0x%x; MUX ref: 0x%x; Network has ref: %d ref: 0x%x MSC/BSC mux: 0x%x/0x%x type: %s%s",
-			con->bsc->cfg ? con->bsc->cfg->nr : -1,
-			sccp_src_ref_to_int(&con->real_ref),
-			sccp_src_ref_to_int(&con->patched_ref),
-			con->has_remote_ref,
-			sccp_src_ref_to_int(&con->remote_ref),
-			con->msc_endp, con->bsc_endp,
-			bsc_con_type_to_string(con->filter_state.con_type),
-			VTY_NEWLINE);
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_nat_bsc, show_nat_bsc_cmd, "show nat num-bscs-configured",
-      SHOW_STR "Display NAT configuration details\n"
-      "BSCs-related\n")
-{
-	vty_out(vty, "%d BSCs configured%s", _nat->num_bsc, VTY_NEWLINE);
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_bsc, show_bsc_cmd, "show bsc connections",
-      SHOW_STR BSC_STR
-      "All active connections\n")
-{
-	struct bsc_connection *con;
-	struct sockaddr_in sock;
-	socklen_t len = sizeof(sock);
-
-	llist_for_each_entry(con, &_nat->bsc_connections, list_entry) {
-		getpeername(con->write_queue.bfd.fd, (struct sockaddr *) &sock, &len);
-		vty_out(vty, "BSC nr: %d auth: %d fd: %d peername: %s pending-stats: %u%s",
-			con->cfg ? con->cfg->nr : -1,
-			con->authenticated, con->write_queue.bfd.fd,
-			inet_ntoa(sock.sin_addr), con->pending_dlcx_count,
-			VTY_NEWLINE);
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_bsc_mgcp, show_bsc_mgcp_cmd, "show bsc mgcp NR",
-      SHOW_STR BSC_STR MGCP_STR "Identifier of the BSC\n")
-{
-	struct bsc_connection *con;
-	int nr = atoi(argv[0]);
-	int i, j, endp;
-
-	llist_for_each_entry(con, &_nat->bsc_connections, list_entry) {
-		int max;
-		if (!con->cfg)
-			continue;
-		if (con->cfg->nr != nr)
-			continue;
-
-		/* this bsc has no audio endpoints yet */
-		if (!con->_endpoint_status)
-			continue;
-
-		vty_out(vty, "MGCP Status for %d%s", con->cfg->nr, VTY_NEWLINE);
-		max = bsc_mgcp_nr_multiplexes(con->max_endpoints);
-		for (i = 0; i < max; ++i) {
-			for (j = 1; j < 32; ++j) {
-				endp = mgcp_timeslot_to_endpoint(i, j);
-				vty_out(vty, " Endpoint 0x%x %s%s", endp,
-					con->_endpoint_status[endp] == 0 
-						? "free" : "allocated",
-				VTY_NEWLINE);
-			}
-		}
-		break;
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_bsc_cfg, show_bsc_cfg_cmd, "show bsc config",
-      SHOW_STR BSC_STR "Configuration of BSCs\n")
-{
-	struct bsc_config *conf;
-	llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
-		vty_out(vty, "BSC token: '%s' nr: %u%s",
-			conf->token, conf->nr, VTY_NEWLINE);
-		if (conf->acc_lst_name)
-			vty_out(vty, " access-list: %s%s",
-				conf->acc_lst_name, VTY_NEWLINE);
-		vty_out(vty, " paging forbidden: %d%s",
-			conf->forbid_paging, VTY_NEWLINE);
-		if (conf->description)
-			vty_out(vty, " description: %s%s", conf->description, VTY_NEWLINE);
-		else
-			vty_out(vty, " No description.%s", VTY_NEWLINE);
-
-	}
-
-	return CMD_SUCCESS;
-}
-
-static void dump_stat_total(struct vty *vty, struct bsc_nat *nat)
-{
-	vty_out(vty, "NAT statistics%s", VTY_NEWLINE);
-	vty_out(vty, " SCCP Connections %lu total, %lu calls%s",
-		osmo_counter_get(nat->stats.sccp.conn),
-		osmo_counter_get(nat->stats.sccp.calls), VTY_NEWLINE);
-	vty_out(vty, " MSC Connections %lu%s",
-		osmo_counter_get(nat->stats.msc.reconn), VTY_NEWLINE);
-	vty_out(vty, " MSC Connected: %d%s",
-		bsc_nat_msc_is_connected(nat), VTY_NEWLINE);
-	vty_out(vty, " BSC Connections %lu total, %lu auth failed.%s",
-		osmo_counter_get(nat->stats.bsc.reconn),
-		osmo_counter_get(nat->stats.bsc.auth_fail), VTY_NEWLINE);
-}
-
-static void dump_stat_bsc(struct vty *vty, struct bsc_config *conf)
-{
-	int connected = 0;
-	struct bsc_connection *con;
-
-	vty_out(vty, " BSC nr: %d%s",
-		conf->nr, VTY_NEWLINE);
-	vty_out_rate_ctr_group(vty, " ", conf->stats.ctrg);
-
-	llist_for_each_entry(con, &conf->nat->bsc_connections, list_entry) {
-		if (con->cfg != conf)
-			continue;
-		connected = 1;
-		break;
-	}
-
-	vty_out(vty, "  Connected: %d%s", connected, VTY_NEWLINE);
-}
-
-DEFUN(show_stats,
-      show_stats_cmd,
-      "show statistics [NR]",
-      SHOW_STR "Display network statistics\n"
-      "Number of the BSC\n")
-{
-	struct bsc_config *conf;
-
-	int nr = -1;
-
-	if (argc == 1)
-		nr = atoi(argv[0]);
-
-	dump_stat_total(vty, _nat);
-	llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
-		if (argc == 1 && nr != conf->nr)
-			continue;
-		dump_stat_bsc(vty, conf);
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_stats_lac,
-      show_stats_lac_cmd,
-      "show statistics-by-lac <0-65535>",
-      SHOW_STR "Display network statistics by lac\n"
-      "The lac of the BSC\n")
-{
-	int lac;
-	struct bsc_config *conf;
-
-	lac = atoi(argv[0]);
-
-	dump_stat_total(vty, _nat);
-	llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
-		if (!bsc_config_handles_lac(conf, lac))
-			continue;
-		dump_stat_bsc(vty, conf);
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_msc,
-      show_msc_cmd,
-      "show msc connection",
-      SHOW_STR "MSC related information\n"
-      "Status of the A-link connection\n")
-{
-	if (!_nat->msc_con) {
-		vty_out(vty, "The MSC is not yet configured.%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	vty_out(vty, "MSC is connected: %d%s",
-		bsc_nat_msc_is_connected(_nat), VTY_NEWLINE);
-	return CMD_SUCCESS;
-}
-
-DEFUN(close_bsc,
-      close_bsc_cmd,
-      "close bsc connection BSC_NR",
-      "Close\n" "A-link\n" "Connection\n" "Identifier of the BSC\n")
-{
-	struct bsc_connection *bsc;
-	int bsc_nr = atoi(argv[0]);
-
-	llist_for_each_entry(bsc, &_nat->bsc_connections, list_entry) {
-		if (!bsc->cfg || bsc->cfg->nr != bsc_nr)
-			continue;
-		bsc_close_connection(bsc);
-		break;
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat, cfg_nat_cmd, "nat", "Configure the NAT")
-{
-	vty->index = _nat;
-	vty->node = NAT_NODE;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_msc_ip,
-      cfg_nat_msc_ip_cmd,
-      "msc ip A.B.C.D",
-      "MSC related configuration\n"
-      "Configure the IP address\n" IP_STR)
-{
-	bsc_nat_set_msc_ip(_nat, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_msc_port,
-      cfg_nat_msc_port_cmd,
-      "msc port <1-65500>",
-      "MSC related configuration\n"
-      "Configure the port\n"
-      "Port number\n")
-{
-	_nat->main_dest->port = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_auth_time,
-      cfg_nat_auth_time_cmd,
-      "timeout auth <1-256>",
-      "Timeout configuration\n"
-      "Authentication timeout\n"
-      "Timeout in seconds\n")
-{
-	_nat->auth_timeout = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_ping_time,
-      cfg_nat_ping_time_cmd,
-      "timeout ping NR",
-      "Timeout configuration\n"
-      "Time between two pings\n"
-      "Timeout in seconds\n")
-{
-	_nat->ping_timeout = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_pong_time,
-      cfg_nat_pong_time_cmd,
-      "timeout pong NR",
-      "Timeout configuration\n"
-      "Waiting for pong timeout\n"
-      "Timeout in seconds\n")
-{
-	_nat->pong_timeout = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_token, cfg_nat_token_cmd,
-      "token TOKEN",
-      "Authentication token configuration\n"
-      "Token of the BSC, currently transferred in cleartext\n")
-{
-	osmo_talloc_replace_string(_nat, &_nat->token, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_bsc_ip_dscp, cfg_nat_bsc_ip_dscp_cmd,
-      "ip-dscp <0-255>",
-      "Set the IP DSCP for the BSCs to use\n" "Set the IP_TOS attribute")
-{
-	_nat->bsc_ip_dscp = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-ALIAS_DEPRECATED(cfg_nat_bsc_ip_dscp, cfg_nat_bsc_ip_tos_cmd,
-      "ip-tos <0-255>",
-      "Use ip-dscp in the future.\n" "Set the DSCP\n")
-
-
-DEFUN(cfg_nat_acc_lst_name,
-      cfg_nat_acc_lst_name_cmd,
-      "access-list-name NAME",
-      "Set the name of the access list to use.\n"
-      "The name of the to be used access list.")
-{
-	osmo_talloc_replace_string(_nat, &_nat->acc_lst_name, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_include,
-      cfg_nat_include_cmd,
-      "bscs-config-file NAME",
-      "Set the filename of the BSC configuration to include.\n"
-      "The filename to be included.")
-{
-	char *path;
-	int rc;
-	struct bsc_config *cf1, *cf2;
-	struct bsc_connection *con1, *con2;
-
-	if ('/' == argv[0][0])
-		osmo_talloc_replace_string(_nat, &_nat->resolved_path, argv[0]);
-	else {
-		path = talloc_asprintf(_nat, "%s/%s", _nat->include_base,
-				       argv[0]);
-		osmo_talloc_replace_string(_nat, &_nat->resolved_path, path);
-		talloc_free(path);
-	}
-
-	llist_for_each_entry_safe(cf1, cf2, &_nat->bsc_configs, entry) {
-		cf1->remove = true;
-		cf1->token_updated = false;
-	}
-
-	rc = vty_read_config_file(_nat->resolved_path, NULL);
-	if (rc < 0) {
-		vty_out(vty, "Failed to parse the config file %s: %s%s",
-			_nat->resolved_path, strerror(-rc), VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	osmo_talloc_replace_string(_nat, &_nat->include_file, argv[0]);
-
-	llist_for_each_entry_safe(con1, con2, &_nat->bsc_connections,
-				  list_entry) {
-		if (con1->cfg)
-			if (con1->cfg->token_updated || con1->cfg->remove)
-				bsc_close_connection(con1);
-	}
-
-	llist_for_each_entry_safe(cf1, cf2, &_nat->bsc_configs, entry) {
-		if (cf1->remove)
-			bsc_config_free(cf1);
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_no_acc_lst_name,
-      cfg_nat_no_acc_lst_name_cmd,
-      "no access-list-name",
-      NO_STR "Remove the access list from the NAT.\n")
-{
-	if (_nat->acc_lst_name) {
-		talloc_free(_nat->acc_lst_name);
-		_nat->acc_lst_name = NULL;
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_imsi_black_list_fn,
-      cfg_nat_imsi_black_list_fn_cmd,
-      "imsi-black-list-file-name NAME",
-      "IMSI black listing\n" "Filename IMSI and reject-cause\n")
-{
-
-	osmo_talloc_replace_string(_nat, &_nat->imsi_black_list_fn, argv[0]);
-	if (_nat->imsi_black_list_fn) {
-		int rc;
-		struct osmo_config_list *rewr = NULL;
-		rewr = osmo_config_list_parse(_nat, _nat->imsi_black_list_fn);
-		rc = bsc_filter_barr_adapt(_nat, &_nat->imsi_black_list, rewr);
-		if (rc != 0) {
-			vty_out(vty, "%%There was an error parsing the list."
-				" Please see the error log.%s", VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-
-		return CMD_SUCCESS;
-	}
-
-	bsc_filter_barr_adapt(_nat, &_nat->imsi_black_list, NULL);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_no_imsi_black_list_fn,
-      cfg_nat_no_imsi_black_list_fn_cmd,
-      "no imsi-black-list-file-name",
-      NO_STR "Remove the imsi-black-list\n")
-{
-	talloc_free(_nat->imsi_black_list_fn);
-	_nat->imsi_black_list_fn = NULL;
-	bsc_filter_barr_adapt(_nat, &_nat->imsi_black_list, NULL);
-	return CMD_SUCCESS;
-}
-
-static int replace_rules(struct bsc_nat *nat, char **name,
-			 struct llist_head *head, const char *file)
-{
-	struct osmo_config_list *rewr = NULL;
-
-	osmo_talloc_replace_string(nat, name, file);
-	if (*name) {
-		rewr = osmo_config_list_parse(nat, *name);
-		bsc_nat_num_rewr_entry_adapt(nat, head, rewr);
-		talloc_free(rewr);
-		return CMD_SUCCESS;
-	} else {
-		bsc_nat_num_rewr_entry_adapt(nat, head, NULL);
-		return CMD_SUCCESS;
-	}
-}
-
-DEFUN(cfg_nat_number_rewrite,
-      cfg_nat_number_rewrite_cmd,
-      "number-rewrite FILENAME",
-      "Set the file with rewriting rules.\n" "Filename")
-{
-	return replace_rules(_nat, &_nat->num_rewr_name,
-			     &_nat->num_rewr, argv[0]);
-}
-
-DEFUN(cfg_nat_no_number_rewrite,
-      cfg_nat_no_number_rewrite_cmd,
-      "no number-rewrite",
-      NO_STR "Set the file with rewriting rules.\n")
-{
-	talloc_free(_nat->num_rewr_name);
-	_nat->num_rewr_name = NULL;
-
-	bsc_nat_num_rewr_entry_adapt(NULL, &_nat->num_rewr, NULL);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_number_rewrite_post,
-      cfg_nat_number_rewrite_post_cmd,
-      "number-rewrite-post FILENAME",
-      "Set the file with post-routing rewriting rules.\n" "Filename")
-{
-	return replace_rules(_nat, &_nat->num_rewr_post_name,
-			     &_nat->num_rewr_post, argv[0]);
-}
-
-DEFUN(cfg_nat_no_number_rewrite_post,
-      cfg_nat_no_number_rewrite_post_cmd,
-      "no number-rewrite-post",
-      NO_STR "Set the file with post-routing rewriting rules.\n")
-{
-	talloc_free(_nat->num_rewr_post_name);
-	_nat->num_rewr_post_name = NULL;
-
-	bsc_nat_num_rewr_entry_adapt(NULL, &_nat->num_rewr_post, NULL);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_smsc_addr,
-      cfg_nat_smsc_addr_cmd,
-      "rewrite-smsc addr FILENAME",
-      SMSC_REWRITE
-      "The SMSC Address to match and replace in RP-DATA\n"
-      "File with rules for the SMSC Address replacing\n")
-{
-	return replace_rules(_nat, &_nat->smsc_rewr_name,
-			     &_nat->smsc_rewr, argv[0]);
-}
-
-DEFUN(cfg_nat_smsc_tpdest,
-      cfg_nat_smsc_tpdest_cmd,
-      "rewrite-smsc tp-dest-match FILENAME",
-      SMSC_REWRITE
-      "Match TP-Destination of a SMS.\n"
-      "File with rules for matching MSISDN and TP-DEST\n")
-{
-	return replace_rules(_nat, &_nat->tpdest_match_name,
-			     &_nat->tpdest_match, argv[0]);
-}
-
-DEFUN(cfg_nat_sms_clear_tpsrr,
-      cfg_nat_sms_clear_tpsrr_cmd,
-      "sms-clear-tp-srr FILENAME",
-      "SMS TPDU Sender Report Request clearing\n"
-      "Files with rules for matching MSISDN\n")
-{
-	return replace_rules(_nat, &_nat->sms_clear_tp_srr_name,
-			     &_nat->sms_clear_tp_srr, argv[0]);
-}
-
-DEFUN(cfg_nat_no_sms_clear_tpsrr,
-      cfg_nat_no_sms_clear_tpsrr_cmd,
-      "no sms-clear-tp-srr",
-      NO_STR
-      "SMS TPDU Sender Report Request clearing\n")
-{
-	talloc_free(_nat->sms_clear_tp_srr_name);
-	_nat->sms_clear_tp_srr_name = NULL;
-
-	bsc_nat_num_rewr_entry_adapt(NULL, &_nat->sms_clear_tp_srr, NULL);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_sms_number_rewrite,
-      cfg_nat_sms_number_rewrite_cmd,
-      "sms-number-rewrite FILENAME",
-      "SMS TP-DA Number rewriting\n"
-      "Files with rules for matching MSISDN\n")
-{
-	return replace_rules(_nat, &_nat->sms_num_rewr_name,
-			     &_nat->sms_num_rewr, argv[0]);
-}
-
-DEFUN(cfg_nat_no_sms_number_rewrite,
-      cfg_nat_no_sms_number_rewrite_cmd,
-      "no sms-number-rewrite",
-      NO_STR "Disable SMS TP-DA rewriting\n")
-{
-	talloc_free(_nat->sms_num_rewr_name);
-	_nat->sms_num_rewr_name = NULL;
-
-	bsc_nat_num_rewr_entry_adapt(NULL, &_nat->sms_num_rewr, NULL);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_prefix_trie,
-      cfg_nat_prefix_trie_cmd,
-      "prefix-tree FILENAME",
-      "Prefix tree for number rewriting\n" "File to load\n")
-{
-	/* give up the old data */
-	talloc_free(_nat->num_rewr_trie);
-	_nat->num_rewr_trie = NULL;
-
-	/* replace the file name */
-	osmo_talloc_replace_string(_nat, &_nat->num_rewr_trie_name, argv[0]);
-	if (!_nat->num_rewr_trie_name) {
-		vty_out(vty, "%% prefix-tree no filename is present.%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	_nat->num_rewr_trie = nat_rewrite_parse(_nat, _nat->num_rewr_trie_name);
-	if (!_nat->num_rewr_trie) {
-		vty_out(vty, "%% prefix-tree parsing has failed.%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	vty_out(vty, "%% prefix-tree loaded %zu rules.%s",
-		_nat->num_rewr_trie->prefixes, VTY_NEWLINE);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_no_prefix_trie, cfg_nat_no_prefix_trie_cmd,
-      "no prefix-tree",
-      NO_STR "Prefix tree for number rewriting\n")
-{
-	talloc_free(_nat->num_rewr_trie);
-	_nat->num_rewr_trie = NULL;
-	talloc_free(_nat->num_rewr_trie_name);
-	_nat->num_rewr_trie_name = NULL;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_prefix_tree, show_prefix_tree_cmd,
-      "show prefix-tree",
-      SHOW_STR "Prefix tree for number rewriting\n")
-{
-	if (!_nat->num_rewr_trie) {
-		vty_out(vty, "%% there is now prefix tree loaded.%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	nat_rewrite_dump_vty(vty, _nat->num_rewr_trie);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_ussd_lst_name,
-      cfg_nat_ussd_lst_name_cmd,
-      "ussd-list-name NAME",
-      "Set the name of the access list to check for IMSIs for USSD message\n"
-      "The name of the access list for HLR USSD handling")
-{
-	osmo_talloc_replace_string(_nat, &_nat->ussd_lst_name, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_ussd_query,
-      cfg_nat_ussd_query_cmd,
-      "ussd-query REGEXP",
-      "Set the USSD query to match with the ussd-list-name\n"
-      "The query to match")
-{
-	if (gsm_parse_reg(_nat, &_nat->ussd_query_re, &_nat->ussd_query, argc, argv) != 0)
-		return CMD_WARNING;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_ussd_token,
-      cfg_nat_ussd_token_cmd,
-      "ussd-token TOKEN",
-      "Set the token used to identify the USSD module\n" "Secret key\n")
-{
-	osmo_talloc_replace_string(_nat, &_nat->ussd_token, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_ussd_local,
-      cfg_nat_ussd_local_cmd,
-      "ussd-local-ip A.B.C.D",
-      "Set the IP to listen for the USSD Provider\n" "IP Address\n")
-{
-	osmo_talloc_replace_string(_nat, &_nat->ussd_local, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_use_ipa_for_mgcp,
-      cfg_nat_use_ipa_for_mgcp_cmd,
-      "use-msc-ipa-for-mgcp",
-      "This needs to be set at start. Handle MGCP messages through "
-      "the IPA protocol and not through the UDP socket.\n")
-{
-	if (_nat->mgcp_cfg->data)
-		vty_out(vty,
-			"%%the setting will not be applied right now.%s",
-			VTY_NEWLINE);
-	_nat->mgcp_ipa = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_sdp_amr_mode_set,
-      cfg_nat_sdp_amr_mode_set_cmd,
-      "sdp-ensure-amr-mode-set",
-      "Ensure that SDP records include a mode-set\n")
-{
-	_nat->sdp_ensure_amr_mode_set = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_no_sdp_amr_mode_set,
-      cfg_nat_no_sdp_amr_mode_set_cmd,
-      "no sdp-ensure-amr-mode-set",
-      NO_STR "Ensure that SDP records include a mode-set\n")
-{
-	_nat->sdp_ensure_amr_mode_set = 0;
-	return CMD_SUCCESS;
-}
-
-/* per BSC configuration */
-DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR",
-      "BSC configuration\n" "Identifier of the BSC\n")
-{
-	int bsc_nr = atoi(argv[0]);
-	struct bsc_config *bsc = bsc_config_num(_nat, bsc_nr);
-
-	/* allocate a new one */
-	if (!bsc)
-		bsc = bsc_config_alloc(_nat, "unknown", bsc_nr);
-
-	if (!bsc)
-		return CMD_WARNING;
-
-	bsc->remove = false;
-	vty->index = bsc;
-	vty->node = NAT_BSC_NODE;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_token, cfg_bsc_token_cmd, "token TOKEN",
-      "Authentication token configuration\n"
-      "Token of the BSC, currently transferred in cleartext\n")
-{
-	struct bsc_config *conf = vty->index;
-
-	if (strncmp(conf->token, argv[0], 128) != 0)
-		conf->token_updated = true;
-
-	osmo_talloc_replace_string(conf, &conf->token, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_auth_key, cfg_bsc_auth_key_cmd,
-      "auth-key KEY",
-      "Authentication (secret) key configuration\n"
-      "Non null security key\n")
-{
-	struct bsc_config *conf = vty->index;
-
-	memset(conf->key, 0, sizeof(conf->key));
-	osmo_hexparse(argv[0], conf->key, sizeof(conf->key));
-	conf->key_present = 1;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_no_auth_key, cfg_bsc_no_auth_key_cmd,
-      "no auth-key",
-      NO_STR "Authentication (secret) key configuration\n")
-{
-	struct bsc_config *conf = vty->index;
-
-	memset(conf->key, 0, sizeof(conf->key));
-	conf->key_present = 0;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>",
-      "Add the Location Area Code (LAC) of this BSC\n" "LAC\n")
-{
-	struct bsc_config *tmp;
-	struct bsc_config *conf = vty->index;
-
-	int lac = atoi(argv[0]);
-
-	if (lac == GSM_LAC_RESERVED_DETACHED || lac == GSM_LAC_RESERVED_ALL_BTS) {
-		vty_out(vty, "%% LAC %d is reserved by GSM 04.08%s",
-			lac, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	/* verify that the LACs are unique */
-	llist_for_each_entry(tmp, &_nat->bsc_configs, entry) {
-		if (bsc_config_handles_lac(tmp, lac)) {
-			if (tmp->nr != conf->nr) {
-				vty_out(vty, "%% LAC %d is already used.%s", lac,
-					VTY_NEWLINE);
-				return CMD_ERR_INCOMPLETE;
-			}
-		}
-	}
-
-	bsc_config_add_lac(conf, lac);
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_no_lac, cfg_bsc_no_lac_cmd,
-      "no location_area_code <0-65535>",
-      NO_STR "Remove the Location Area Code (LAC) of this BSC\n" "LAC\n")
-{
-	int lac = atoi(argv[0]);
-	struct bsc_config *conf = vty->index;
-
-	bsc_config_del_lac(conf, lac);
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_bar_lst,
-      show_bar_lst_cmd,
-      "show imsi-black-list",
-      SHOW_STR "IMSIs barred from the network\n")
-{
-	struct rb_node *node;
-
-	vty_out(vty, "IMSIs barred from the network:%s", VTY_NEWLINE);
-
-	for (node = rb_first(&_nat->imsi_black_list); node; node = rb_next(node)) {
-		struct bsc_filter_barr_entry *entry;
-		entry = rb_entry(node, struct bsc_filter_barr_entry, node);
-
-		vty_out(vty, " IMSI(%s) CM-Reject-Cause(%d) LU-Reject-Cause(%d)%s",
-			entry->imsi, entry->cm_reject_cause, entry->lu_reject_cause,
-			VTY_NEWLINE);
-	}
-
-	return CMD_SUCCESS;
-}
-
-
-DEFUN(cfg_bsc_acc_lst_name,
-      cfg_bsc_acc_lst_name_cmd,
-      "access-list-name NAME",
-      "Set the name of the access list to use.\n"
-      "The name of the to be used access list.")
-{
-	struct bsc_config *conf = vty->index;
-
-	osmo_talloc_replace_string(conf, &conf->acc_lst_name, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_no_acc_lst_name,
-      cfg_bsc_no_acc_lst_name_cmd,
-      "no access-list-name",
-      NO_STR "Do not use an access-list for the BSC.\n")
-{
-	struct bsc_config *conf = vty->index;
-
-	if (conf->acc_lst_name) {
-		talloc_free(conf->acc_lst_name);
-		conf->acc_lst_name = NULL;
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_max_endps, cfg_bsc_max_endps_cmd,
-      "max-endpoints <1-1024>",
-      "Highest endpoint to use (exclusively)\n" "Number of ports\n")
-{
-	struct bsc_config *conf = vty->index;
-
-	conf->max_endpoints = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_paging,
-      cfg_bsc_paging_cmd,
-      "paging forbidden (0|1)",
-      PAGING_STR "Forbid sending PAGING REQUESTS to the BSC.\n"
-      "Do not forbid\n" "Forbid\n")
-{
-	struct bsc_config *conf = vty->index;
-
-	if (strcmp("1", argv[0]) == 0)
-		conf->forbid_paging = 1;
-	else
-		conf->forbid_paging = 0;
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_desc,
-      cfg_bsc_desc_cmd,
-      "description DESC",
-      "Provide a description for the given BSC.\n" "Description\n")
-{
-	struct bsc_config *conf = vty->index;
-
-	osmo_talloc_replace_string(conf, &conf->description, argv[0]);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bsc_paging_grp,
-      cfg_bsc_paging_grp_cmd,
-      "paging group <0-1000>",
-      PAGING_STR "Use a paging group\n" "Paging Group to use\n")
-{
-	struct bsc_config *conf = vty->index;
-	conf->paging_group = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
-
-ALIAS_DEPRECATED(cfg_bsc_paging_grp, cfg_bsc_old_grp_cmd,
-		 "paging-group <0-1000>",
-		 "Use a paging group\n" "Paging Group to use\n")
-
-DEFUN(cfg_bsc_no_paging_grp,
-      cfg_bsc_no_paging_grp_cmd,
-      "no paging group",
-      NO_STR PAGING_STR "Disable the usage of a paging group.\n")
-{
-	struct bsc_config *conf = vty->index;
-	conf->paging_group = PAGIN_GROUP_UNASSIGNED;
-	return CMD_SUCCESS;
-}
-
-DEFUN(test_regex, test_regex_cmd,
-      "test regex PATTERN STRING",
-      "Test utilities\n"
-      "Regexp testing\n" "The regexp pattern\n"
-      "The string to match\n")
-{
-	regex_t reg;
-	char *str = NULL;
-
-	memset(&reg, 0, sizeof(reg));
-	if (gsm_parse_reg(_nat, &reg, &str, 1, argv) != 0)
-		return CMD_WARNING;
-
-	vty_out(vty, "String matches allow pattern: %d%s",
-		regexec(&reg, argv[1], 0, NULL, 0) == 0, VTY_NEWLINE);
-
-	talloc_free(str);
-	regfree(&reg);
-	return CMD_SUCCESS;
-}
-
-DEFUN(set_last_endp, set_last_endp_cmd,
-      "set bsc last-used-endpoint <0-9999999999> <0-1024>",
-      "Set a value\n" "Operate on a BSC\n"
-      "Last used endpoint for an assignment\n" "BSC configuration number\n"
-      "Endpoint number used\n")
-{
-	struct bsc_connection *con;
-	int nr = atoi(argv[0]);
-	int endp = atoi(argv[1]);
-
-
-	llist_for_each_entry(con, &_nat->bsc_connections, list_entry) {
-		if (!con->cfg)
-			continue;
-		if (con->cfg->nr != nr)
-			continue;
-
-		con->last_endpoint = endp;
-		vty_out(vty, "Updated the last endpoint for %d to %d.%s",
-			con->cfg->nr, con->last_endpoint, VTY_NEWLINE);
-	}
-
-	return CMD_SUCCESS;
-}
-
-DEFUN(block_new_conn, block_new_conn_cmd,
-      "nat-block (block|unblock)",
-      "Block the NAT for new connections\n"
-      "Block\n" "Unblock\n")
-{
-	_nat->blocked = argv[0][0] == 'b';
-	vty_out(vty, "%%Going to %s the NAT.%s",
-		_nat->blocked ? "block" : "unblock", VTY_NEWLINE);
-	return CMD_SUCCESS;
-}
-
-/* paging group */
-DEFUN(cfg_nat_pgroup, cfg_nat_pgroup_cmd,
-      "paging-group <0-1000>",
-      "Create a Paging Group\n" "Number of the Group\n")
-{
-	int group = atoi(argv[0]);
-	struct bsc_nat_paging_group *pgroup;
-	pgroup = bsc_nat_paging_group_num(_nat, group);
-	if (!pgroup)
-		pgroup = bsc_nat_paging_group_create(_nat, group);
-	if (!pgroup) {
-		vty_out(vty, "Failed to create the group.%s", VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	vty->index = pgroup;
-	vty->node = PGROUP_NODE;
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nat_no_pgroup, cfg_nat_no_pgroup_cmd,
-      "no paging-group <0-1000>",
-      NO_STR "Delete paging-group\n" "Paging-group number\n")
-{
-	int group = atoi(argv[0]);
-	struct bsc_nat_paging_group *pgroup;
-	pgroup = bsc_nat_paging_group_num(_nat, group);
-	if (!pgroup) {
-		vty_out(vty, "No such paging group %d.%s", group, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bsc_nat_paging_group_delete(pgroup);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_pgroup_lac, cfg_pgroup_lac_cmd,
-      "location_area_code <0-65535>",
-       "Add the Location Area Code (LAC)\n" "LAC\n")
-{
-	struct bsc_nat_paging_group *pgroup = vty->index;
-
-	int lac = atoi(argv[0]);
-	if (lac == GSM_LAC_RESERVED_DETACHED || lac == GSM_LAC_RESERVED_ALL_BTS) {
-		vty_out(vty, "%% LAC %d is reserved by GSM 04.08%s",
-			lac, VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	bsc_nat_paging_group_add_lac(pgroup, lac);
-	return CMD_SUCCESS;
-}
-
-DEFUN(cfg_pgroup_no_lac, cfg_pgroup_no_lac_cmd,
-      "no location_area_code <0-65535>",
-      NO_STR "Remove the Location Area Code (LAC)\n" "LAC\n")
-{
-	int lac = atoi(argv[0]);
-	struct bsc_nat_paging_group *pgroup = vty->index;
-
-	bsc_nat_paging_group_del_lac(pgroup, lac);
-	return CMD_SUCCESS;
-}
-
-DEFUN(show_ussd_connection,
-      show_ussd_connection_cmd,
-      "show ussd-connection",
-      SHOW_STR "USSD connection related information\n")
-{
-	vty_out(vty, "The USSD side channel provider is %sconnected and %sauthorized.%s",
-		_nat->ussd_con ? "" : "not ",
-		_nat->ussd_con && _nat->ussd_con->authorized? "" : "not ",
-		VTY_NEWLINE);
-	return CMD_SUCCESS;
-}
-
-#define OSMUX_STR "RTP multiplexing\n"
-DEFUN(cfg_bsc_osmux,
-      cfg_bsc_osmux_cmd,
-      "osmux (on|off|only)",
-       OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only OSMUX\n")
-{
-	struct bsc_config *conf = vty->index;
-	int old = conf->osmux;
-
-	if (strcmp(argv[0], "on") == 0)
-		conf->osmux = OSMUX_USAGE_ON;
-	else if (strcmp(argv[0], "off") == 0)
-		conf->osmux = OSMUX_USAGE_OFF;
-	else if (strcmp(argv[0], "only") == 0)
-		conf->osmux = OSMUX_USAGE_ONLY;
-
-	if (old == 0 && conf->osmux > 0 && !conf->nat->mgcp_cfg->osmux_init) {
-		LOGP(DMGCP, LOGL_NOTICE, "Setting up OSMUX socket\n");
-		if (osmux_init(OSMUX_ROLE_BSC_NAT, conf->nat->mgcp_cfg) < 0) {
-			LOGP(DMGCP, LOGL_ERROR, "Cannot init OSMUX\n");
-			vty_out(vty, "%% failed to create Osmux socket%s",
-				VTY_NEWLINE);
-			return CMD_WARNING;
-		}
-	} else if (old > 0 && conf->osmux == 0) {
-		LOGP(DMGCP, LOGL_NOTICE, "Disabling OSMUX socket\n");
-		/* Don't stop the socket, we may already have ongoing voice
-		 * flows already using Osmux. This just switch indicates that
-		 * new upcoming flows should use RTP.
-		 */
-	}
-
-	return CMD_SUCCESS;
-}
-
-int bsc_nat_vty_init(struct bsc_nat *nat)
-{
-	_nat = nat;
-
-	/* show commands */
-	install_element_ve(&show_sccp_cmd);
-	install_element_ve(&show_bsc_cmd);
-	install_element_ve(&show_nat_bsc_cmd);
-	install_element_ve(&show_bsc_cfg_cmd);
-	install_element_ve(&show_stats_cmd);
-	install_element_ve(&show_stats_lac_cmd);
-	install_element_ve(&close_bsc_cmd);
-	install_element_ve(&show_msc_cmd);
-	install_element_ve(&test_regex_cmd);
-	install_element_ve(&show_bsc_mgcp_cmd);
-	install_element_ve(&show_bscs_cmd);
-	install_element_ve(&show_bar_lst_cmd);
-	install_element_ve(&show_prefix_tree_cmd);
-	install_element_ve(&show_ussd_connection_cmd);
-
-	install_element(ENABLE_NODE, &set_last_endp_cmd);
-	install_element(ENABLE_NODE, &block_new_conn_cmd);
-
-	/* nat group */
-	install_element(CONFIG_NODE, &cfg_nat_cmd);
-	install_node(&nat_node, config_write_nat);
-	vty_install_default(NAT_NODE);
-	install_element(NAT_NODE, &cfg_nat_msc_ip_cmd);
-	install_element(NAT_NODE, &cfg_nat_msc_port_cmd);
-	install_element(NAT_NODE, &cfg_nat_auth_time_cmd);
-	install_element(NAT_NODE, &cfg_nat_ping_time_cmd);
-	install_element(NAT_NODE, &cfg_nat_pong_time_cmd);
-	install_element(NAT_NODE, &cfg_nat_token_cmd);
-	install_element(NAT_NODE, &cfg_nat_bsc_ip_dscp_cmd);
-	install_element(NAT_NODE, &cfg_nat_bsc_ip_tos_cmd);
-	install_element(NAT_NODE, &cfg_nat_acc_lst_name_cmd);
-	install_element(NAT_NODE, &cfg_nat_no_acc_lst_name_cmd);
-	install_element(NAT_NODE, &cfg_nat_include_cmd);
-	install_element(NAT_NODE, &cfg_nat_imsi_black_list_fn_cmd);
-	install_element(NAT_NODE, &cfg_nat_no_imsi_black_list_fn_cmd);
-	install_element(NAT_NODE, &cfg_nat_ussd_lst_name_cmd);
-	install_element(NAT_NODE, &cfg_nat_ussd_query_cmd);
-	install_element(NAT_NODE, &cfg_nat_ussd_token_cmd);
-	install_element(NAT_NODE, &cfg_nat_ussd_local_cmd);
-	install_element(NAT_NODE, &cfg_nat_use_ipa_for_mgcp_cmd);
-
-	bsc_msg_lst_vty_init(nat, &nat->access_lists, NAT_NODE);
-
-	/* number rewriting */
-	install_element(NAT_NODE, &cfg_nat_number_rewrite_cmd);
-	install_element(NAT_NODE, &cfg_nat_no_number_rewrite_cmd);
-	install_element(NAT_NODE, &cfg_nat_number_rewrite_post_cmd);
-	install_element(NAT_NODE, &cfg_nat_no_number_rewrite_post_cmd);
-	install_element(NAT_NODE, &cfg_nat_smsc_addr_cmd);
-	install_element(NAT_NODE, &cfg_nat_smsc_tpdest_cmd);
-	install_element(NAT_NODE, &cfg_nat_sms_clear_tpsrr_cmd);
-	install_element(NAT_NODE, &cfg_nat_no_sms_clear_tpsrr_cmd);
-	install_element(NAT_NODE, &cfg_nat_sms_number_rewrite_cmd);
-	install_element(NAT_NODE, &cfg_nat_no_sms_number_rewrite_cmd);
-	install_element(NAT_NODE, &cfg_nat_prefix_trie_cmd);
-	install_element(NAT_NODE, &cfg_nat_no_prefix_trie_cmd);
-
-	install_element(NAT_NODE, &cfg_nat_sdp_amr_mode_set_cmd);
-	install_element(NAT_NODE, &cfg_nat_no_sdp_amr_mode_set_cmd);
-
-	install_element(NAT_NODE, &cfg_nat_pgroup_cmd);
-	install_element(NAT_NODE, &cfg_nat_no_pgroup_cmd);
-	install_node(&pgroup_node, config_write_pgroup);
-	vty_install_default(PGROUP_NODE);
-	install_element(PGROUP_NODE, &cfg_pgroup_lac_cmd);
-	install_element(PGROUP_NODE, &cfg_pgroup_no_lac_cmd);
-
-	/* BSC subgroups */
-	install_element(NAT_NODE, &cfg_bsc_cmd);
-	install_node(&bsc_node, NULL);
-	vty_install_default(NAT_BSC_NODE);
-	install_element(NAT_BSC_NODE, &cfg_bsc_token_cmd);
-	install_element(NAT_BSC_NODE, &cfg_bsc_auth_key_cmd);
-	install_element(NAT_BSC_NODE, &cfg_bsc_no_auth_key_cmd);
-	install_element(NAT_BSC_NODE, &cfg_bsc_lac_cmd);
-	install_element(NAT_BSC_NODE, &cfg_bsc_no_lac_cmd);
-	install_element(NAT_BSC_NODE, &cfg_bsc_paging_cmd);
-	install_element(NAT_BSC_NODE, &cfg_bsc_desc_cmd);
-	install_element(NAT_BSC_NODE, &cfg_bsc_acc_lst_name_cmd);
-	install_element(NAT_BSC_NODE, &cfg_bsc_no_acc_lst_name_cmd);
-	install_element(NAT_BSC_NODE, &cfg_bsc_max_endps_cmd);
-	install_element(NAT_BSC_NODE, &cfg_bsc_old_grp_cmd);
-	install_element(NAT_BSC_NODE, &cfg_bsc_paging_grp_cmd);
-	install_element(NAT_BSC_NODE, &cfg_bsc_no_paging_grp_cmd);
-	install_element(NAT_BSC_NODE, &cfg_bsc_osmux_cmd);
-
-	mgcp_vty_init();
-
-	return 0;
-}
-
-
-/* called by the telnet interface... we have our own init above */
-int bsc_vty_init(struct gsm_network *network)
-{
-	logging_vty_add_cmds(NULL);
-	return 0;
-}
diff --git a/src/osmo-bsc_nat/bsc_sccp.c b/src/osmo-bsc_nat/bsc_sccp.c
deleted file mode 100644
index c6c265f..0000000
--- a/src/osmo-bsc_nat/bsc_sccp.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/* SCCP patching and handling routines */
-/*
- * (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/>.
- *
- */
-
-#include <openbsc/debug.h>
-#include <openbsc/bsc_nat.h>
-#include <openbsc/bsc_nat_sccp.h>
-
-#include <osmocom/sccp/sccp.h>
-
-#include <osmocom/core/talloc.h>
-
-#include <string.h>
-#include <time.h>
-
-static int equal(struct sccp_source_reference *ref1, struct sccp_source_reference *ref2)
-{
-	return memcmp(ref1, ref2, sizeof(*ref1)) == 0;
-}
-
-/*
- * SCCP patching below
- */
-
-/* check if we are using this ref for patched already */
-static int sccp_ref_is_free(struct sccp_source_reference *ref, struct bsc_nat *nat)
-{
-	struct nat_sccp_connection *conn;
-
-	llist_for_each_entry(conn, &nat->sccp_connections, list_entry) {
-		if (equal(ref, &conn->patched_ref))
-			return -1;
-	}
-
-	return 0;
-}
-
-/* copied from sccp.c */
-static int assign_src_local_reference(struct sccp_source_reference *ref, struct bsc_nat *nat)
-{
-	static uint32_t last_ref = 0x50000;
-	int wrapped = 0;
-
-	do {
-		struct sccp_source_reference reference;
-		reference.octet1 = (last_ref >>  0) & 0xff;
-		reference.octet2 = (last_ref >>  8) & 0xff;
-		reference.octet3 = (last_ref >> 16) & 0xff;
-
-		++last_ref;
-		/* do not use the reversed word and wrap around */
-		if ((last_ref & 0x00FFFFFF) == 0x00FFFFFF) {
-			LOGP(DNAT, LOGL_NOTICE, "Wrapped searching for a free code\n");
-			last_ref = 0;
-			++wrapped;
-		}
-
-		if (sccp_ref_is_free(&reference, nat) == 0) {
-			*ref = reference;
-			return 0;
-		}
-	} while (wrapped != 2);
-
-	LOGP(DNAT, LOGL_ERROR, "Finding a free reference failed\n");
-	return -1;
-}
-
-struct nat_sccp_connection *create_sccp_src_ref(struct bsc_connection *bsc,
-					     struct bsc_nat_parsed *parsed)
-{
-	struct nat_sccp_connection *conn;
-
-	/* Some commercial BSCs like to reassign there SRC ref */
-	llist_for_each_entry(conn, &bsc->nat->sccp_connections, list_entry) {
-		if (conn->bsc != bsc)
-			continue;
-		if (!equal(parsed->src_local_ref, &conn->real_ref))
-			continue;
-
-		/* the BSC has reassigned the SRC ref and we failed to keep track */
-		memset(&conn->remote_ref, 0, sizeof(conn->remote_ref));
-		if (assign_src_local_reference(&conn->patched_ref, bsc->nat) != 0) {
-			LOGP(DNAT, LOGL_ERROR, "BSC %d reused src ref: %d and we failed to generate a new id.\n",
-			     bsc->cfg->nr, sccp_src_ref_to_int(parsed->src_local_ref));
-			bsc_mgcp_dlcx(conn);
-			llist_del(&conn->list_entry);
-			talloc_free(conn);
-			return NULL;
-		} else {
-			clock_gettime(CLOCK_MONOTONIC, &conn->creation_time);
-			bsc_mgcp_dlcx(conn);
-			return conn;
-		}
-	}
-
-
-	conn = talloc_zero(bsc->nat, struct nat_sccp_connection);
-	if (!conn) {
-		LOGP(DNAT, LOGL_ERROR, "Memory allocation failure.\n");
-		return NULL;
-	}
-
-	conn->bsc = bsc;
-	clock_gettime(CLOCK_MONOTONIC, &conn->creation_time);
-	conn->real_ref = *parsed->src_local_ref;
-	if (assign_src_local_reference(&conn->patched_ref, bsc->nat) != 0) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to assign a ref.\n");
-		talloc_free(conn);
-		return NULL;
-	}
-
-	bsc_mgcp_init(conn);
-	llist_add_tail(&conn->list_entry, &bsc->nat->sccp_connections);
-	rate_ctr_inc(&bsc->cfg->stats.ctrg->ctr[BCFG_CTR_SCCP_CONN]);
-	osmo_counter_inc(bsc->cfg->nat->stats.sccp.conn);
-
-	LOGP(DNAT, LOGL_DEBUG, "Created 0x%x <-> 0x%x mapping for con %p\n",
-	     sccp_src_ref_to_int(&conn->real_ref),
-	     sccp_src_ref_to_int(&conn->patched_ref), bsc);
-
-	return conn;
-}
-
-int update_sccp_src_ref(struct nat_sccp_connection *sccp, struct bsc_nat_parsed *parsed)
-{
-	if (!parsed->dest_local_ref || !parsed->src_local_ref) {
-		LOGP(DNAT, LOGL_ERROR, "CC MSG should contain both local and dest address.\n");
-		return -1;
-	}
-
-	sccp->remote_ref = *parsed->src_local_ref;
-	sccp->has_remote_ref = 1;
-	LOGP(DNAT, LOGL_DEBUG, "Updating 0x%x to remote 0x%x on %p\n",
-	     sccp_src_ref_to_int(&sccp->patched_ref),
-	     sccp_src_ref_to_int(&sccp->remote_ref), sccp->bsc);
-
-	return 0;
-}
-
-void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed)
-{
-	struct nat_sccp_connection *conn;
-
-	llist_for_each_entry(conn, &bsc->nat->sccp_connections, list_entry) {
-		if (equal(parsed->src_local_ref, &conn->patched_ref)) {
-			sccp_connection_destroy(conn);
-			return;
-		}
-	}
-
-	LOGP(DNAT, LOGL_ERROR, "Can not remove connection: 0x%x\n",
-	     sccp_src_ref_to_int(parsed->src_local_ref));
-}
-
-/*
- * We have a message from the MSC to the BSC. The MSC is using
- * an address that was assigned by the MUX, we need to update the
- * dest reference to the real network.
- */
-struct nat_sccp_connection *patch_sccp_src_ref_to_bsc(struct msgb *msg,
-						   struct bsc_nat_parsed *parsed,
-						   struct bsc_nat *nat)
-{
-	struct nat_sccp_connection *conn;
-
-	if (!parsed->dest_local_ref) {
-		LOGP(DNAT, LOGL_ERROR, "MSG should contain dest_local_ref.\n");
-		return NULL;
-	}
-
-
-	llist_for_each_entry(conn, &nat->sccp_connections, list_entry) {
-		if (!equal(parsed->dest_local_ref, &conn->patched_ref))
-			continue;
-
-		/* Change the dest address to the real one */
-		*parsed->dest_local_ref = conn->real_ref;
-		return conn;
-	}
-
-	return NULL;
-}
-
-/*
- * These are message to the MSC. We will need to find the BSC
- * Connection by either the SRC or the DST local reference.
- *
- * In case of a CR we need to work by the SRC local reference
- * in all other cases we need to work by the destination local
- * reference..
- */
-struct nat_sccp_connection *patch_sccp_src_ref_to_msc(struct msgb *msg,
-						   struct bsc_nat_parsed *parsed,
-						   struct bsc_connection *bsc)
-{
-	struct nat_sccp_connection *conn;
-
-	llist_for_each_entry(conn, &bsc->nat->sccp_connections, list_entry) {
-		if (conn->bsc != bsc)
-			continue;
-
-		if (parsed->src_local_ref) {
-			if (equal(parsed->src_local_ref, &conn->real_ref)) {
-				*parsed->src_local_ref = conn->patched_ref;
-				return conn;
-			}
-		} else if (parsed->dest_local_ref) {
-			if (equal(parsed->dest_local_ref, &conn->remote_ref))
-				return conn;
-		} else {
-			LOGP(DNAT, LOGL_ERROR, "Header has neither loc/dst ref.\n");
-			return NULL;
-		}
-	}
-
-	return NULL;
-}
-
-struct nat_sccp_connection *bsc_nat_find_con_by_bsc(struct bsc_nat *nat,
-						 struct sccp_source_reference *ref)
-{
-	struct nat_sccp_connection *conn;
-
-	llist_for_each_entry(conn, &nat->sccp_connections, list_entry) {
-		if (equal(ref, &conn->real_ref))
-			return conn;
-	}
-
-	return NULL;
-}
diff --git a/src/osmo-bsc_nat/bsc_ussd.c b/src/osmo-bsc_nat/bsc_ussd.c
deleted file mode 100644
index 0ba6327..0000000
--- a/src/osmo-bsc_nat/bsc_ussd.c
+++ /dev/null
@@ -1,453 +0,0 @@
-/* USSD Filter Code */
-
-/*
- * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2011 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/>.
- *
- */
-
-#include <openbsc/bsc_nat.h>
-#include <openbsc/bsc_nat_sccp.h>
-#include <openbsc/bsc_msg_filter.h>
-#include <openbsc/ipaccess.h>
-#include <openbsc/socket.h>
-
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-#include <osmocom/gsm/gsm0480.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/gsm/ipa.h>
-
-#include <osmocom/sccp/sccp.h>
-
-#include <osmocom/abis/ipa.h>
-
-#include <sys/socket.h>
-#include <string.h>
-#include <unistd.h>
-
-#define USSD_LAC_IE	0
-#define USSD_CI_IE	1
-
-static void ussd_auth_con(struct tlv_parsed *, struct bsc_nat_ussd_con *);
-
-static struct bsc_nat_ussd_con *bsc_nat_ussd_alloc(struct bsc_nat *nat)
-{
-	struct bsc_nat_ussd_con *con;
-
-	con = talloc_zero(nat, struct bsc_nat_ussd_con);
-	if (!con)
-		return NULL;
-
-	con->nat = nat;
-	return con;
-}
-
-static void bsc_nat_ussd_destroy(struct bsc_nat_ussd_con *con)
-{
-	if (con->nat->ussd_con == con) {
-		bsc_ussd_close_connections(con->nat);
-		con->nat->ussd_con = NULL;
-	}
-
-	close(con->queue.bfd.fd);
-	osmo_fd_unregister(&con->queue.bfd);
-	osmo_timer_del(&con->auth_timeout);
-	osmo_wqueue_clear(&con->queue);
-
-	msgb_free(con->pending_msg);
-	talloc_free(con);
-}
-
-static void ussd_pong(struct bsc_nat_ussd_con *conn)
-{
-	struct msgb *msg;
-
-	msg = msgb_alloc_headroom(4096, 128, "pong message");
-	if (!msg) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to allocate pong msg\n");
-		return;
-	}
-
-	msgb_v_put(msg, IPAC_MSGT_PONG);
-	bsc_do_write(&conn->queue, msg, IPAC_PROTO_IPACCESS);
-}
-
-static int forward_sccp(struct bsc_nat *nat, struct msgb *msg)
-{
-	struct nat_sccp_connection *con;
-	struct bsc_nat_parsed *parsed;
-
-
-	parsed = bsc_nat_parse(msg);
-	if (!parsed) {
-		LOGP(DNAT, LOGL_ERROR, "Can not parse msg from USSD.\n");
-		msgb_free(msg);
-		return -1;
-	}
-
-	if (!parsed->dest_local_ref) {
-		LOGP(DNAT, LOGL_ERROR, "No destination local reference.\n");
-		msgb_free(msg);
-		return -1;
-	}
-
-	con = bsc_nat_find_con_by_bsc(nat, parsed->dest_local_ref);
-	if (!con || !con->bsc) {
-		LOGP(DNAT, LOGL_ERROR, "No active connection found.\n");
-		msgb_free(msg);
-		return -1;
-	}
-
-	talloc_free(parsed);
-	bsc_write_msg(&con->bsc->write_queue, msg);
-	return 0;
-}
-
-static int ussd_read_cb(struct osmo_fd *bfd)
-{
-	struct bsc_nat_ussd_con *conn = bfd->data;
-	struct msgb *msg = NULL;
-	struct ipaccess_head *hh;
-	int ret;
-
-	ret = ipa_msg_recv_buffered(bfd->fd, &msg, &conn->pending_msg);
-	if (ret <= 0) {
-		if (ret == -EAGAIN)
-			return 0;
-		LOGP(DNAT, LOGL_ERROR, "USSD Connection was lost.\n");
-		bsc_nat_ussd_destroy(conn);
-		return -1;
-	}
-
-	LOGP(DNAT, LOGL_NOTICE, "MSG from USSD: %s proto: %d\n",
-		osmo_hexdump(msg->data, msg->len), msg->l2h[0]);
-	hh = (struct ipaccess_head *) msg->data;
-
-	if (hh->proto == IPAC_PROTO_IPACCESS) {
-		if (msg->l2h[0] == IPAC_MSGT_ID_RESP) {
-			struct tlv_parsed tvp;
-			int ret;
-			ret = ipa_ccm_idtag_parse(&tvp,
-					     (unsigned char *) msg->l2h + 2,
-					     msgb_l2len(msg) - 2);
-			if (ret < 0) {
-				LOGP(DNAT, LOGL_ERROR, "ignoring IPA response "
-					"message with malformed TLVs\n");
-				msgb_free(msg);
-				return ret;
-			}
-			if (TLVP_PRESENT(&tvp, IPAC_IDTAG_UNITNAME))
-				ussd_auth_con(&tvp, conn);
-		} else if (msg->l2h[0] == IPAC_MSGT_PING) {
-			LOGP(DNAT, LOGL_DEBUG, "Got USSD ping request.\n");
-			ussd_pong(conn);
-		} else {
-			LOGP(DNAT, LOGL_NOTICE, "Got unknown IPACCESS message 0x%02x.\n", msg->l2h[0]);
-		}
-
-		msgb_free(msg);
-	} else if (hh->proto == IPAC_PROTO_SCCP) {
-		forward_sccp(conn->nat, msg);
-	} else {
-		msgb_free(msg);
-	}
-
-	return 0;
-}
-
-static void ussd_auth_cb(void *_data)
-{
-	LOGP(DNAT, LOGL_ERROR, "USSD module didn't authenticate\n");
-	bsc_nat_ussd_destroy((struct bsc_nat_ussd_con *) _data);
-}
-
-static void ussd_auth_con(struct tlv_parsed *tvp, struct bsc_nat_ussd_con *conn)
-{
-	const char *token;
-	int len;
-	if (!conn->nat->ussd_token) {
-		LOGP(DNAT, LOGL_ERROR, "No USSD token set. Closing\n");
-		bsc_nat_ussd_destroy(conn);
-		return;
-	}
-
-	token = (const char *) TLVP_VAL(tvp, IPAC_IDTAG_UNITNAME);
- 	len = TLVP_LEN(tvp, IPAC_IDTAG_UNITNAME);
-
-	/* last byte should be a NULL */
-	if (strlen(conn->nat->ussd_token) != len - 1)
-		goto disconnect;
-	/* compare everything including the null byte */
-	if (memcmp(conn->nat->ussd_token, token, len) != 0)
-		goto disconnect;
-
-	/* it is authenticated now */
-	if (conn->nat->ussd_con && conn->nat->ussd_con != conn)
-		bsc_nat_ussd_destroy(conn->nat->ussd_con);
-
-	LOGP(DNAT, LOGL_ERROR, "USSD token specified. USSD provider is connected.\n");
-	osmo_timer_del(&conn->auth_timeout);
-	conn->authorized = 1;
-	conn->nat->ussd_con = conn;
-	return;
-
-disconnect:
-	LOGP(DNAT, LOGL_ERROR, "Wrong USSD token by client: %d\n",
-		conn->queue.bfd.fd);
-	bsc_nat_ussd_destroy(conn);
-}
-
-static void ussd_start_auth(struct bsc_nat_ussd_con *conn)
-{
-	struct msgb *msg;
-
-	osmo_timer_setup(&conn->auth_timeout, ussd_auth_cb, conn);
-	osmo_timer_schedule(&conn->auth_timeout, conn->nat->auth_timeout, 0);
-
-	msg = msgb_alloc_headroom(4096, 128, "auth message");
-	if (!msg) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to allocate auth msg\n");
-		return;
-	}
-
-	msgb_v_put(msg, IPAC_MSGT_ID_GET);
-	bsc_do_write(&conn->queue, msg, IPAC_PROTO_IPACCESS);
-}
-
-static int ussd_listen_cb(struct osmo_fd *bfd, unsigned int what)
-{
-	struct bsc_nat_ussd_con *conn;
-	struct bsc_nat *nat;
-	struct sockaddr_in sa;
-	socklen_t sa_len = sizeof(sa);
-	int fd;
-
-	if (!(what & BSC_FD_READ))
-		return 0;
-
-	fd = accept(bfd->fd, (struct sockaddr *) &sa, &sa_len);
-	if (fd < 0) {
-		perror("accept");
-		return fd;
-	}
-
-	nat = (struct bsc_nat *) bfd->data;
-	osmo_counter_inc(nat->stats.ussd.reconn);
-
-	conn = bsc_nat_ussd_alloc(nat);
-	if (!conn) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to allocate USSD con struct.\n");
-		close(fd);
-		return -1;
-	}
-
-	osmo_wqueue_init(&conn->queue, 10);
-	conn->queue.bfd.data = conn;
-	conn->queue.bfd.fd = fd;
-	conn->queue.bfd.when = BSC_FD_READ;
-	conn->queue.read_cb = ussd_read_cb;
-	conn->queue.write_cb = bsc_write_cb;
-
-	if (osmo_fd_register(&conn->queue.bfd) < 0) {
-		LOGP(DNAT, LOGL_ERROR, "Failed to register USSD fd.\n");
-		bsc_nat_ussd_destroy(conn);
-		return -1;
-	}
-
-	LOGP(DNAT, LOGL_NOTICE, "USSD Connection on %d with IP: %s\n",
-	     fd, inet_ntoa(sa.sin_addr));
-
-	/* do authentication */
-	ussd_start_auth(conn);
-	return 0;
-}
-
-int bsc_ussd_init(struct bsc_nat *nat)
-{
-	struct in_addr addr;
-
-	addr.s_addr = INADDR_ANY;
-	if (nat->ussd_local)
-		inet_aton(nat->ussd_local, &addr);
-
-	nat->ussd_listen.data = nat;
-	return make_sock(&nat->ussd_listen, IPPROTO_TCP,
-			 ntohl(addr.s_addr), 5001, 0, ussd_listen_cb, nat);
-}
-
-static int forward_ussd_simple(struct nat_sccp_connection *con, struct msgb *input)
-{
-	struct msgb *copy;
-	struct bsc_nat_ussd_con *ussd;
-
-	if (!con->bsc->nat->ussd_con)
-		return -1;
-
-	copy = msgb_alloc_headroom(4096, 128, "forward bts");
-	if (!copy) {
-		LOGP(DNAT, LOGL_ERROR, "Allocation failed, not forwarding.\n");
-		return -1;
-	}
-
-	/* copy the data into the copy */
-	copy->l2h = msgb_put(copy, msgb_l2len(input));
-	memcpy(copy->l2h, input->l2h, msgb_l2len(input));
-
-	/* send it out */
-	ussd = con->bsc->nat->ussd_con;
-	bsc_do_write(&ussd->queue, copy, IPAC_PROTO_SCCP);
-	return 0;
-}
-
-static int forward_ussd(struct nat_sccp_connection *con, const struct ussd_request *req,
-			struct msgb *input)
-{
-	struct msgb *msg, *copy;
-	struct ipac_msgt_sccp_state *state;
-	struct bsc_nat_ussd_con *ussd;
-	uint16_t lac, ci;
-
-	if (!con->bsc->nat->ussd_con)
-		return -1;
-
-	msg = msgb_alloc_headroom(4096, 128, "forward ussd");
-	if (!msg) {
-		LOGP(DNAT, LOGL_ERROR, "Allocation failed, not forwarding.\n");
-		return -1;
-	}
-
-	copy = msgb_alloc_headroom(4096, 128, "forward bts");
-	if (!copy) {
-		LOGP(DNAT, LOGL_ERROR, "Allocation failed, not forwarding.\n");
-		msgb_free(msg);
-		return -1;
-	}
-
-	copy->l2h = msgb_put(copy, msgb_l2len(input));
-	memcpy(copy->l2h, input->l2h, msgb_l2len(input));
-
-	msg->l2h = msgb_put(msg, 1);
-	msg->l2h[0] = IPAC_MSGT_SCCP_OLD;
-
-	/* fill out the data */
-	state = (struct ipac_msgt_sccp_state *) msgb_put(msg, sizeof(*state));
-	state->trans_id = req->transaction_id;
-	state->invoke_id = req->invoke_id;
-	memcpy(&state->src_ref, &con->remote_ref, sizeof(con->remote_ref));
-	memcpy(&state->dst_ref, &con->real_ref, sizeof(con->real_ref));
-	memcpy(state->imsi, con->filter_state.imsi, strlen(con->filter_state.imsi));
-
-	/* add additional tag/values */
-	lac = htons(con->lac);
-	ci = htons(con->ci);
-	msgb_tv_fixed_put(msg, USSD_LAC_IE, sizeof(lac), (const uint8_t *) &lac);
-	msgb_tv_fixed_put(msg, USSD_CI_IE, sizeof(ci), (const uint8_t *) &ci);
-
-	ussd = con->bsc->nat->ussd_con;
-	bsc_do_write(&ussd->queue, msg, IPAC_PROTO_IPACCESS);
-	bsc_do_write(&ussd->queue, copy, IPAC_PROTO_SCCP);
-
-	return 0;
-}
-
-int bsc_ussd_check(struct nat_sccp_connection *con, struct bsc_nat_parsed *parsed,
-		   struct msgb *msg)
-{
-	uint32_t len;
-	uint8_t msg_type;
-	uint8_t proto;
-	uint8_t ti;
-	struct gsm48_hdr *hdr48;
-	struct bsc_msg_acc_lst *lst;
-	struct ussd_request req;
-
-	/*
-	 * various checks to avoid the decoding work. Right now we only want to
-	 * decode if the connection was created for USSD, we do have a USSD access
-	 * list, a query, a IMSI and such...
-	 */
-	if (con->filter_state.con_type != FLT_CON_TYPE_SSA)
-		return 0;
-
-	if (!con->filter_state.imsi)
-		return 0;
-
-	/* We have not verified the IMSI yet */
-	if (!con->authorized)
-		return 0;
-
-	if (!con->bsc->nat->ussd_lst_name)
-		return 0;
-	if (!con->bsc->nat->ussd_query)
-		return 0;
-
-	if (parsed->bssap != BSSAP_MSG_DTAP)
-		return 0;
-
-	if (strlen(con->filter_state.imsi) > GSM23003_IMSI_MAX_DIGITS)
-		return 0;
-
-	hdr48 = bsc_unpack_dtap(parsed, msg, &len);
-	if (!hdr48)
-		return 0;
-
-	proto = gsm48_hdr_pdisc(hdr48);
-	msg_type = gsm48_hdr_msg_type(hdr48);
-	ti = gsm48_hdr_trans_id_no_ti(hdr48);
-	if (proto != GSM48_PDISC_NC_SS)
-		return 0;
-
-	if (msg_type == GSM0480_MTYPE_REGISTER) {
-
-		/* now check if it is a IMSI we care about */
-		lst = bsc_msg_acc_lst_find(&con->bsc->nat->access_lists,
-					   con->bsc->nat->ussd_lst_name);
-		if (!lst)
-			return 0;
-
-		if (bsc_msg_acc_lst_check_allow(lst, con->filter_state.imsi) != 0)
-			return 0;
-
-		/* now decode the message and see if we really want to handle it */
-		memset(&req, 0, sizeof(req));
-		if (gsm0480_decode_ussd_request(hdr48, len, &req) != 1)
-			return 0;
-		if (req.text[0] == 0xff)
-			return 0;
-
-		if (regexec(&con->bsc->nat->ussd_query_re,
-			    req.text, 0, NULL, 0) == REG_NOMATCH)
-			return 0;
-
-		/* found a USSD query for our subscriber */
-		LOGP(DNAT, LOGL_NOTICE, "Found USSD query for %s\n",
-			con->filter_state.imsi);
-		con->ussd_ti[ti] = 1;
-		if (forward_ussd(con, &req, msg) != 0)
-			return 0;
-		return 1;
-	} else if (msg_type == GSM0480_MTYPE_FACILITY && con->ussd_ti[ti]) {
-		LOGP(DNAT, LOGL_NOTICE, "Forwarding message part of TI: %d %s\n",
-		     ti, con->filter_state.imsi);
-		if (forward_ussd_simple(con, msg) != 0)
-			return 0;
-		return 1;
-	}
-
-	return 0;
-}
diff --git a/src/osmo-msc/Makefile.am b/src/osmo-msc/Makefile.am
deleted file mode 100644
index 87b6133..0000000
--- a/src/osmo-msc/Makefile.am
+++ /dev/null
@@ -1,56 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	-I$(top_builddir) \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	$(COVERAGE_CFLAGS) \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOVTY_CFLAGS) \
-	$(LIBOSMOCTRL_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(LIBSMPP34_CFLAGS) \
-	$(LIBCRYPTO_CFLAGS) \
-	$(LIBOSMORANAP_CFLAGS) \
-	$(LIBASN1C_CFLAGS) \
-	$(LIBOSMOSIGTRAN_CFLAGS) \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(COVERAGE_LDFLAGS) \
-	$(NULL)
-
-bin_PROGRAMS = \
-	osmo-msc \
-	$(NULL)
-
-osmo_msc_SOURCES = \
-	msc_main.c \
-	$(NULL)
-
-osmo_msc_LDADD = \
-	$(top_builddir)/src/libmsc/libmsc.a \
-	$(top_builddir)/src/libvlr/libvlr.a \
-	$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(top_builddir)/src/libmgcp/libmgcp.a \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOVTY_LIBS) \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOCTRL_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	$(LIBSMPP34_LIBS) \
-	$(LIBCRYPTO_LIBS) \
-	$(LIBOSMOSIGTRAN_LIBS) \
-	-ldbi \
-	$(NULL)
-if BUILD_IU
-osmo_msc_LDADD += \
-	$(LIBOSMORANAP_LIBS) \
-	$(LIBASN1C_LIBS) \
-	$(NULL)
-endif
diff --git a/src/osmo-msc/msc_main.c b/src/osmo-msc/msc_main.c
deleted file mode 100644
index de6af5d..0000000
--- a/src/osmo-msc/msc_main.c
+++ /dev/null
@@ -1,589 +0,0 @@
-/* OsmoMSC - Circuit-Switched Core Network (MSC+VLR+HLR+SMSC) implementation
- */
-
-/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- * All Rights Reserved
- *
- * Based on OsmoNITB:
- * (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009-2012 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/>.
- *
- */
-
-#include <unistd.h>
-#include <time.h>
-#include <errno.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-#define _GNU_SOURCE
-#include <getopt.h>
-
-/* build switches from the configure script */
-#include "../../bscconfig.h"
-
-#include <openbsc/db.h>
-#include <osmocom/core/application.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/stats.h>
-#include <openbsc/debug.h>
-#include <osmocom/abis/abis.h>
-#include <osmocom/abis/e1_input.h>
-#include <osmocom/core/talloc.h>
-#include <openbsc/signal.h>
-#include <openbsc/osmo_msc.h>
-#include <openbsc/bsc_msc_data.h>
-#include <openbsc/sms_queue.h>
-#include <osmocom/vty/telnet_interface.h>
-#include <osmocom/vty/ports.h>
-#include <osmocom/vty/logging.h>
-#include <openbsc/vty.h>
-#include <openbsc/bss.h>
-#include <openbsc/mncc.h>
-#include <openbsc/handover_decision.h>
-#include <openbsc/rrlp.h>
-#include <osmocom/ctrl/control_if.h>
-#include <osmocom/ctrl/control_vty.h>
-#include <osmocom/ctrl/ports.h>
-#include <openbsc/ctrl.h>
-#include <openbsc/osmo_bsc_rf.h>
-#include <openbsc/smpp.h>
-#include <osmocom/sigtran/osmo_ss7.h>
-#include <openbsc/mgcpgw_client.h>
-
-#ifdef BUILD_IU
-#include <osmocom/ranap/iu_client.h>
-#endif
-
-#include <openbsc/msc_ifaces.h>
-#include <openbsc/iucs.h>
-#include <openbsc/iucs_ranap.h>
-#include <openbsc/a_iface.h>
-
-static const char * const osmomsc_copyright =
-	"OsmoMSC - Osmocom Circuit-Switched Core Network implementation\r\n"
-	"Copyright (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>\r\n"
-	"Based on OsmoNITB:\r\n"
-	"  (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>\r\n"
-	"  (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>\r\n"
-	"Contributions by Daniel Willmann, Jan Lübbe, Stefan Schmidt\r\n"
-	"Dieter Spaar, Andreas Eversberg, Sylvain Munaut, Neels Hofmeyr\r\n\r\n"
-	"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
-	"This is free software: you are free to change and redistribute it.\r\n"
-	"There is NO WARRANTY, to the extent permitted by law.\r\n";
-
-void *tall_msc_ctx = NULL;
-
-/* satisfy deps from libbsc legacy.
-   TODO double check these */
-void *tall_fle_ctx = NULL;
-void *tall_paging_ctx = NULL;
-void *tall_map_ctx = NULL;
-void *tall_upq_ctx = NULL;
-/* end deps from libbsc legacy. */
-
-static struct {
-	const char *database_name;
-	const char *config_file;
-	int daemonize;
-	const char *mncc_sock_path;
-	int use_db_counter;
-} msc_cmdline_config = {
-	"sms.db",
-	"osmo-msc.cfg",
-	0,
-	0,
-	1
-};
-
-/* timer to store statistics */
-#define DB_SYNC_INTERVAL	60, 0
-#define EXPIRE_INTERVAL		10, 0
-
-static struct osmo_timer_list db_sync_timer;
-
-static void create_pcap_file(char *file)
-{
-	mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
-	int fd = open(file, O_WRONLY|O_TRUNC|O_CREAT, mode);
-
-	if (fd < 0) {
-		perror("Failed to open file for pcap");
-		return;
-	}
-
-	e1_set_pcap_fd(fd);
-}
-
-static void print_usage()
-{
-	printf("Usage: osmo-nitb\n");
-}
-
-static void print_help()
-{
-	printf("  Some useful help...\n");
-	printf("  -h --help                  This text.\n");
-	printf("  -d option --debug=DRLL:DCC:DMM:DRR:DRSL:DNM  Enable debugging.\n");
-	printf("  -D --daemonize             Fork the process into a background daemon.\n");
-	printf("  -c --config-file filename  The config file to use.\n");
-	printf("  -s --disable-color\n");
-	printf("  -l --database db-name      The database to use.\n");
-	printf("  -T --timestamp             Prefix every log line with a timestamp.\n");
-	printf("  -V --version               Print the version of OpenBSC.\n");
-	printf("  -P --rtp-proxy             Enable the RTP Proxy code inside OpenBSC.\n");
-	printf("  -e --log-level number      Set a global loglevel.\n");
-	printf("  -M --mncc-sock-path PATH   Disable built-in MNCC handler and offer socket.\n");
-	printf("  -m --mncc-sock             Same as `-M /tmp/bsc_mncc' (deprecated).\n");
-	printf("  -C --no-dbcounter          Disable regular syncing of counters to database.\n");
-	printf("  -r --rf-ctl PATH           A unix domain socket to listen for cmds.\n");
-	printf("  -p --pcap PATH             Write abis communication to pcap trace file.\n");
-}
-
-static void handle_options(int argc, char **argv)
-{
-	while (1) {
-		int option_index = 0, c;
-		static struct option long_options[] = {
-			{"help", 0, 0, 'h'},
-			{"debug", 1, 0, 'd'},
-			{"daemonize", 0, 0, 'D'},
-			{"config-file", 1, 0, 'c'},
-			{"disable-color", 0, 0, 's'},
-			{"database", 1, 0, 'l'},
-			{"pcap", 1, 0, 'p'},
-			{"timestamp", 0, 0, 'T'},
-			{"version", 0, 0, 'V' },
-			{"rtp-proxy", 0, 0, 'P'},
-			{"log-level", 1, 0, 'e'},
-			{"mncc-sock", 0, 0, 'm'},
-			{"mncc-sock-path", 1, 0, 'M'},
-			{"no-dbcounter", 0, 0, 'C'},
-			{0, 0, 0, 0}
-		};
-
-		c = getopt_long(argc, argv, "hd:Dsl:ap:TPVc:e:mCM:",
-				long_options, &option_index);
-		if (c == -1)
-			break;
-
-		switch (c) {
-		case 'h':
-			print_usage();
-			print_help();
-			exit(0);
-		case 's':
-			log_set_use_color(osmo_stderr_target, 0);
-			break;
-		case 'd':
-			log_parse_category_mask(osmo_stderr_target, optarg);
-			break;
-		case 'D':
-			msc_cmdline_config.daemonize = 1;
-			break;
-		case 'l':
-			msc_cmdline_config.database_name = optarg;
-			break;
-		case 'c':
-			msc_cmdline_config.config_file = optarg;
-			break;
-		case 'p':
-			create_pcap_file(optarg);
-			break;
-		case 'T':
-			log_set_print_timestamp(osmo_stderr_target, 1);
-			break;
-#if BEFORE_MSCSPLIT
-		case 'P':
-			ipacc_rtp_direct = 0;
-			break;
-#endif
-		case 'e':
-			log_set_log_level(osmo_stderr_target, atoi(optarg));
-			break;
-		case 'M':
-			msc_cmdline_config.mncc_sock_path = optarg;
-			break;
-		case 'm':
-			msc_cmdline_config.mncc_sock_path = "/tmp/bsc_mncc";
-			break;
-		case 'C':
-			msc_cmdline_config.use_db_counter = 0;
-			break;
-		case 'V':
-			print_version(1);
-			exit(0);
-			break;
-		default:
-			/* catch unknown options *as well as* missing arguments. */
-			fprintf(stderr, "Error in command line options. Exiting.\n");
-			exit(-1);
-		}
-	}
-}
-
-struct gsm_network *msc_network_alloc(void *ctx,
-				      mncc_recv_cb_t mncc_recv)
-{
-	struct gsm_network *net = gsm_network_init(ctx, 1, 1, mncc_recv);
-	if (!net)
-		return NULL;
-
-	net->name_long = talloc_strdup(net, "OsmoMSC");
-	net->name_short = talloc_strdup(net, "OsmoMSC");
-
-	net->gsup_server_addr_str = talloc_strdup(net,
-						  MSC_HLR_REMOTE_IP_DEFAULT);
-	net->gsup_server_port = MSC_HLR_REMOTE_PORT_DEFAULT;
-
-	mgcpgw_client_conf_init(&net->mgcpgw.conf);
-
-	return net;
-}
-
-void msc_network_shutdown(struct gsm_network *net)
-{
-	/* nothing here yet */
-}
-
-static struct gsm_network *msc_network = NULL;
-
-extern void *tall_vty_ctx;
-static void signal_handler(int signal)
-{
-	fprintf(stdout, "signal %u received\n", signal);
-
-	switch (signal) {
-	case SIGINT:
-	case SIGTERM:
-		msc_network_shutdown(msc_network);
-		osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL);
-		sleep(3);
-		exit(0);
-		break;
-	case SIGABRT:
-		osmo_generate_backtrace();
-		/* in case of abort, we want to obtain a talloc report
-		 * and then return to the caller, who will abort the process */
-	case SIGUSR1:
-		talloc_report(tall_vty_ctx, stderr);
-		talloc_report_full(tall_msc_ctx, stderr);
-		break;
-	case SIGUSR2:
-		talloc_report_full(tall_vty_ctx, stderr);
-		break;
-	default:
-		break;
-	}
-}
-
-/* timer handling */
-static int _db_store_counter(struct osmo_counter *counter, void *data)
-{
-	return db_store_counter(counter);
-}
-
-static void db_sync_timer_cb(void *data)
-{
-	/* store counters to database and re-schedule */
-	osmo_counters_for_each(_db_store_counter, NULL);
-	osmo_timer_schedule(&db_sync_timer, DB_SYNC_INTERVAL);
-}
-
-extern int bsc_vty_go_parent(struct vty *vty);
-
-static struct vty_app_info msc_vty_info = {
-	.name		= "OsmoMSC",
-	.version	= PACKAGE_VERSION,
-	.go_parent_cb	= bsc_vty_go_parent,
-	.is_config_node	= bsc_vty_is_config_node,
-};
-
-#ifdef BUILD_IU
-static int rcvmsg_iu_cs(struct msgb *msg, struct gprs_ra_id *ra_id, uint16_t *sai)
-{
-	DEBUGP(DIUCS, "got IuCS message"
-	       " %d bytes: %s\n",
-	       msg->len, osmo_hexdump(msg->data, msg->len));
-	if (ra_id) {
-		DEBUGP(DIUCS, "got IuCS message on"
-		       " MNC %d MCC %d LAC %d RAC %d\n",
-		       ra_id->mnc, ra_id->mcc, ra_id->lac, ra_id->rac);
-	}
-
-	return gsm0408_rcvmsg_iucs(msc_network, msg, ra_id? &ra_id->lac : NULL);
-}
-
-static int rx_iu_event(struct ranap_ue_conn_ctx *ctx, enum ranap_iu_event_type type,
-		       void *data)
-{
-	DEBUGP(DIUCS, "got IuCS event %u: %s\n", type,
-	       ranap_iu_event_type_str(type));
-
-	return iucs_rx_ranap_event(msc_network, ctx, type, data);
-}
-#endif
-
-#define DEFAULT_M3UA_REMOTE_IP "127.0.0.1"
-#define DEFAULT_PC_A "0.23.1"
-#define DEFAULT_PC_IU "0.23.2"
-#define DEFAULT_PC_A_IU DEFAULT_PC_A
-
-static struct osmo_sccp_instance *sccp_setup(void *ctx, uint32_t cs7_instance,
-					     const char *label, const char *default_pc_str)
-{
-	int default_pc = osmo_ss7_pointcode_parse(NULL, default_pc_str);
-	if (default_pc < 0)
-		return NULL;
-
-	return osmo_sccp_simple_client_on_ss7_id(ctx, cs7_instance, label, default_pc,
-						 OSMO_SS7_ASP_PROT_M3UA,
-						 0, NULL, /* local: use arbitrary port and 0.0.0.0. */
-						 0, /* remote: use protocol default port */
-						 DEFAULT_M3UA_REMOTE_IP);
-	/* Note: If a differing remote IP is to be used, it was already entered in the vty config at
-	 * 'cs7' / 'asp' / 'remote-ip', and this default remote IP has no effect.
-	 * Similarly, 'cs7' / 'listen' can specify the local IP address. */
-}
-
-static int ss7_setup(void *ctx)
-{
-	uint32_t cs7_instance_a = msc_network->a.cs7_instance;
-#if BUILD_IU
-	uint32_t cs7_instance_iu = msc_network->iu.cs7_instance;
-
-	if (cs7_instance_a == cs7_instance_iu) {
-		/* Create one single SCCP instance which will be used for both,
-		 * Iu and A at the same time, under the same point-code */
-		LOGP(DMSC, LOGL_NOTICE, "CS7 Instance identifiers: A = Iu = %u\n", cs7_instance_a);
-
-		msc_network->a.sccp = sccp_setup(ctx, cs7_instance_a, "OsmoMSC-A-Iu", DEFAULT_PC_A_IU);
-		if (!msc_network->a.sccp)
-			return -EINVAL;
-
-		msc_network->iu.sccp = msc_network->a.sccp;
-	} else {
-		/* Create two separate SCCP instances to run A and Iu independently on different
-		 * pointcodes */
-		LOGP(DMSC, LOGL_NOTICE, "CS7 Instance identifiers: A = %u, Iu = %u\n",
-		     cs7_instance_a, cs7_instance_iu);
-
-		msc_network->a.sccp = sccp_setup(ctx, cs7_instance_a, "OsmoMSC-A", DEFAULT_PC_A);
-		if (!msc_network->a.sccp)
-			return -EINVAL;
-
-		msc_network->iu.sccp = sccp_setup(ctx, cs7_instance_iu, "OsmoMSC-Iu", DEFAULT_PC_IU);
-		if (!msc_network->iu.sccp)
-			return -EINVAL;
-	}
-#else
-	/* No Iu support, just open up an A instance */
-	msc_network->a.sccp = sccp_setup(ctx, cs7_instance_a, "OsmoMSC-A", DEFAULT_PC_A);
-	if (!msc_network->a.sccp)
-		return -EINVAL;
-#endif
-
-	return 0;
-}
-
-int main(int argc, char **argv)
-{
-	int rc;
-
-	msc_vty_info.copyright	= osmomsc_copyright;
-
-	tall_msc_ctx = talloc_named_const(NULL, 1, "osmo_msc");
-	talloc_ctx_init(tall_msc_ctx);
-
-	osmo_init_logging(&log_info);
-	osmo_stats_init(tall_msc_ctx);
-
-	/* For --version, vty_init() must be called before handling options */
-	vty_init(&msc_vty_info);
-
-	osmo_ss7_init();
-	osmo_ss7_vty_init_asp(tall_msc_ctx);
-
-	/* Parse options */
-	handle_options(argc, argv);
-
-	/* Allocate global gsm_network struct; choose socket/internal MNCC */
-	msc_network = msc_network_alloc(tall_msc_ctx,
-				        msc_cmdline_config.mncc_sock_path?
-						mncc_sock_from_cc
-						: int_mncc_recv);
-	if (!msc_network)
-		return -ENOMEM;
-
-	if (msc_vlr_alloc(msc_network)) {
-		fprintf(stderr, "Failed to allocate VLR\n");
-		exit(1);
-	}
-
-	ctrl_vty_init(tall_msc_ctx);
-	logging_vty_add_cmds(&log_info);
-	msc_vty_init(msc_network);
-	bsc_vty_init_extra();
-
-#ifdef BUILD_SMPP
-	if (smpp_openbsc_alloc_init(tall_msc_ctx) < 0)
-		return -1;
-#endif
-
-	/*
-	 * For osmo-nitb, skip TCH/F for now, because otherwise dyn TS
-	 * always imply the possibility to have a mix of TCH/F and
-	 * TCH/H channels; if two phones request a TCH/F and a TCH/H,
-	 * respectively, they cannot call each other. If we deny TCH/F,
-	 * they will both fall back to TCH/H, and dynamic channels are
-	 * usable. See OS#1778.
-	 *
-	 * A third-party MSC may well be able to handle a TCH/H TCH/F
-	 * mismatch. Moreover, this option may be overwritten in the
-	 * config file or in VTY.
-	 */
-	msc_network->dyn_ts_allow_tch_f = false;
-
-	rc = vty_read_config_file(msc_cmdline_config.config_file, NULL);
-	if (rc < 0) {
-		LOGP(DNM, LOGL_FATAL, "Failed to parse the config file: '%s'\n",
-		     msc_cmdline_config.config_file);
-		return 1;
-	}
-
-	/* Initialize MNCC socket if appropriate */
-	if (msc_cmdline_config.mncc_sock_path) {
-		rc = mncc_sock_init(msc_network,
-				    msc_cmdline_config.mncc_sock_path);
-		if (rc) {
-			fprintf(stderr, "MNCC socket initialization failed. exiting.\n");
-			exit(1);
-		}
-	} else
-		DEBUGP(DMNCC, "Using internal MNCC handler.\n");
-
-	/* start telnet after reading config for vty_get_bind_addr() */
-	rc = telnet_init_dynif(tall_msc_ctx, &msc_network,
-			       vty_get_bind_addr(), OSMO_VTY_PORT_MSC);
-	if (rc < 0)
-		return 2;
-
-	/* BSC stuff is to be split behind an A-interface to be used with
-	 * OsmoBSC, but there is no need to remove it yet. Most of the
-	 * following code until iu_init() is legacy. */
-
-#ifdef BUILD_SMPP
-	smpp_openbsc_start(msc_network);
-#endif
-
-	/* start control interface after reading config for
-	 * ctrl_vty_get_bind_addr() */
-	msc_network->ctrl = ctrl_interface_setup_dynip(msc_network, ctrl_vty_get_bind_addr(),
-						       OSMO_CTRL_PORT_MSC, NULL);
-	if (!msc_network->ctrl) {
-		printf("Failed to initialize control interface. Exiting.\n");
-		return -1;
-	}
-
-#if 0
-TODO: we probably want some of the _net_ ctrl commands from bsc_base_ctrl_cmds_install().
-	if (bsc_base_ctrl_cmds_install() != 0) {
-		printf("Failed to initialize the BSC control commands.\n");
-		return -1;
-	}
-#endif
-
-	if (msc_ctrl_cmds_install(msc_network) != 0) {
-		printf("Failed to initialize the MSC control commands.\n");
-		return -1;
-	}
-
-	/* seed the PRNG */
-	srand(time(NULL));
-	/* TODO: is this used for crypto?? Improve randomness, at least we
-	 * should try to use the nanoseconds part of the current time. */
-
-	if (db_init(msc_cmdline_config.database_name)) {
-		printf("DB: Failed to init database: %s\n",
-		       msc_cmdline_config.database_name);
-		return 4;
-	}
-
-	osmo_fsm_log_addr(true);
-	if (msc_vlr_start(msc_network)) {
-		fprintf(stderr, "Failed to start VLR\n");
-		exit(1);
-	}
-
-	msc_subscr_conn_init();
-
-	if (db_prepare()) {
-		printf("DB: Failed to prepare database.\n");
-		return 5;
-	}
-
-	/* setup the timer */
-	osmo_timer_setup(&db_sync_timer, db_sync_timer_cb, NULL);
-	if (msc_cmdline_config.use_db_counter)
-		osmo_timer_schedule(&db_sync_timer, DB_SYNC_INTERVAL);
-
-	signal(SIGINT, &signal_handler);
-	signal(SIGTERM, &signal_handler);
-	signal(SIGABRT, &signal_handler);
-	signal(SIGUSR1, &signal_handler);
-	signal(SIGUSR2, &signal_handler);
-	osmo_init_ignore_signals();
-
-	/* start the SMS queue */
-	if (sms_queue_start(msc_network, 20) != 0)
-		return -1;
-
-	msc_network->mgcpgw.client = mgcpgw_client_init(
-			msc_network, &msc_network->mgcpgw.conf);
-
-	if (mgcpgw_client_connect(msc_network->mgcpgw.client)) {
-		printf("MGCPGW connect failed\n");
-		return 7;
-	}
-
-	if (ss7_setup(tall_msc_ctx)) {
-		printf("Setting up SCCP client failed.\n");
-		return 8;
-	}
-
-#ifdef BUILD_IU
-	/* Set up IuCS */
-	ranap_iu_init(tall_msc_ctx, DRANAP, "OsmoMSC-IuCS", msc_network->iu.sccp, rcvmsg_iu_cs, rx_iu_event);
-#endif
-
-	/* Set up A interface */
-	a_init(msc_network->a.sccp, msc_network);
-
-	if (msc_cmdline_config.daemonize) {
-		rc = osmo_daemonize();
-		if (rc < 0) {
-			perror("Error during daemonize");
-			return 6;
-		}
-	}
-
-	while (1) {
-		log_reset_context();
-		osmo_select_main(0);
-	}
-}
diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am
deleted file mode 100644
index 26494e1..0000000
--- a/src/utils/Makefile.am
+++ /dev/null
@@ -1,147 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	-I$(top_builddir) \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(SQLITE3_CFLAGS) \
-	$(LIBSMPP34_CFLAGS) \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(COVERAGE_LDFLAGS) \
-	$(NULL)
-
-noinst_HEADERS = \
-	meas_db.h \
-	$(NULL)
-
-bin_PROGRAMS = \
-	bs11_config \
-	isdnsync \
-	meas_json \
-	$(NULL)
-if HAVE_SQLITE3
-bin_PROGRAMS += \
-	osmo-meas-udp2db \
-	$(NULL)
-if HAVE_PCAP
-bin_PROGRAMS += \
-	osmo-meas-pcap2db \
-	$(NULL)
-endif
-endif
-if HAVE_LIBCDK
-bin_PROGRAMS += \
-	meas_vis \
-	$(NULL)
-endif
-
-if BUILD_SMPP
-noinst_PROGRAMS = \
-	smpp_mirror \
-	$(NULL)
-endif
-
-bs11_config_SOURCES = \
-	bs11_config.c \
-	$(NULL)
-
-bs11_config_LDADD = \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	$(NULL)
-
-isdnsync_SOURCES = \
-	isdnsync.c \
-	$(NULL)
-
-smpp_mirror_SOURCES = \
-	smpp_mirror.c \
-	$(NULL)
-
-smpp_mirror_LDADD = \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBSMPP34_LIBS) \
-	$(NULL)
-
-meas_vis_SOURCES = \
-	meas_vis.c \
-	$(NULL)
-
-meas_vis_LDADD = \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	-lcdk \
-	-lncurses \
-	$(NULL)
-
-meas_vis_CFLAGS = \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(NULL)
-
-osmo_meas_pcap2db_SOURCES = \
-	meas_pcap2db.c \
-	meas_db.c \
-	$(NULL)
-
-osmo_meas_pcap2db_LDADD = \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(SQLITE3_LIBS) \
-	-lpcap \
-	$(NULL)
-
-osmo_meas_pcap2db_CFLAGS = \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(NULL)
-
-osmo_meas_udp2db_SOURCES = \
-	meas_udp2db.c \
-	meas_db.c \
-	$(NULL)
-
-osmo_meas_udp2db_LDADD = \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(SQLITE3_LIBS) \
-	$(NULL)
-
-osmo_meas_udp2db_CFLAGS = \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(NULL)
-
-meas_json_SOURCES = \
-	meas_json.c \
-	$(NULL)
-
-meas_json_LDADD = \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(NULL)
-
-meas_json_CFLAGS = \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(NULL)
-
diff --git a/src/utils/bs11_config.c b/src/utils/bs11_config.c
deleted file mode 100644
index a0f3cb7..0000000
--- a/src/utils/bs11_config.c
+++ /dev/null
@@ -1,953 +0,0 @@
-/* Siemens BS-11 microBTS configuration tool */
-
-/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
- * All Rights Reserved
- *
- * This software is based on ideas (but not code) of BS11Config
- * (C) 2009 by Dieter Spaar <spaar@mirider.augusta.de>
- *
- * 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/>.
- *
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <getopt.h>
-#include <fcntl.h>
-#include <signal.h>
-
-#include <sys/stat.h>
-
-#include <openbsc/common_bsc.h>
-#include <openbsc/abis_nm.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/gsm/tlv.h>
-#include <openbsc/debug.h>
-#include <osmocom/core/select.h>
-#include <openbsc/rs232.h>
-#include <osmocom/core/application.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/abis/abis.h>
-#include <osmocom/abis/e1_input.h>
-
-static void *tall_bs11cfg_ctx;
-static struct e1inp_sign_link *oml_link;
-
-/* state of our bs11_config application */
-enum bs11cfg_state {
-	STATE_NONE,
-	STATE_LOGON_WAIT,
-	STATE_LOGON_ACK,
-	STATE_SWLOAD,
-	STATE_QUERY,
-};
-static enum bs11cfg_state bs11cfg_state = STATE_NONE;
-static char *command, *value;
-struct osmo_timer_list status_timer;
-
-static const uint8_t obj_li_attr[] = {
-	NM_ATT_BS11_BIT_ERR_THESH, 0x09, 0x00,
-	NM_ATT_BS11_L1_PROT_TYPE, 0x00,
-	NM_ATT_BS11_LINE_CFG, 0x00,
-};
-static const uint8_t obj_bbsig0_attr[] = {
-	NM_ATT_BS11_RSSI_OFFS, 0x02, 0x00, 0x00,
-	NM_ATT_BS11_DIVERSITY, 0x01, 0x00,
-};
-static const uint8_t obj_pa0_attr[] = {
-	NM_ATT_BS11_TXPWR, 0x01, BS11_TRX_POWER_GSM_30mW,
-};
-static const char *trx1_password = "1111111111";
-#define TEI_OML	25
-
-/* dummy function to keep gsm_data.c happy */
-struct osmo_counter *osmo_counter_alloc(const char *name)
-{
-	return NULL;
-}
-
-int handle_serial_msg(struct msgb *rx_msg);
-
-/* create all objects for an initial configuration */
-static int create_objects(struct gsm_bts *bts)
-{
-	fprintf(stdout, "Crating Objects for minimal config\n");
-	abis_nm_bs11_create_object(bts, BS11_OBJ_LI, 0, sizeof(obj_li_attr),
-				   obj_li_attr);
-	abis_nm_bs11_create_object(bts, BS11_OBJ_GPSU, 0, 0, NULL);
-	abis_nm_bs11_create_object(bts, BS11_OBJ_ALCO, 0, 0, NULL);
-	abis_nm_bs11_create_object(bts, BS11_OBJ_CCLK, 0, 0, NULL);
-	abis_nm_bs11_create_object(bts, BS11_OBJ_BBSIG, 0,
-				   sizeof(obj_bbsig0_attr), obj_bbsig0_attr);
-	abis_nm_bs11_create_object(bts, BS11_OBJ_PA, 0,
-				   sizeof(obj_pa0_attr), obj_pa0_attr);
-	abis_nm_bs11_create_envaBTSE(bts, 0);
-	abis_nm_bs11_create_envaBTSE(bts, 1);
-	abis_nm_bs11_create_envaBTSE(bts, 2);
-	abis_nm_bs11_create_envaBTSE(bts, 3);
-
-	abis_nm_bs11_conn_oml_tei(bts, 0, 1, 0xff, TEI_OML);
-
-	abis_nm_bs11_set_trx_power(bts->c0, BS11_TRX_POWER_GSM_30mW);
-	
-	sleep(1);
-
-	abis_nm_bs11_set_trx1_pw(bts, trx1_password);
-
-	sleep(1);
-
-	return 0;
-}
-
-static int create_trx1(struct gsm_bts *bts)
-{
-	uint8_t bbsig1_attr[sizeof(obj_bbsig0_attr)+12];
-	uint8_t *cur = bbsig1_attr;
-	struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, 1);
-
-	if (!trx)
-		trx = gsm_bts_trx_alloc(bts);
-
-	fprintf(stdout, "Crating Objects for TRX1\n");
-
-	abis_nm_bs11_set_trx1_pw(bts, trx1_password);
-
-	sleep(1);
-
-	cur = tlv_put(cur, NM_ATT_BS11_PASSWORD, 10,
-		      (uint8_t *)trx1_password);
-	memcpy(cur, obj_bbsig0_attr, sizeof(obj_bbsig0_attr));
-	abis_nm_bs11_create_object(bts, BS11_OBJ_BBSIG, 1,
-				   sizeof(bbsig1_attr), bbsig1_attr);
-	abis_nm_bs11_create_object(bts, BS11_OBJ_PA, 1,
-				   sizeof(obj_pa0_attr), obj_pa0_attr);
-	abis_nm_bs11_set_trx_power(trx, BS11_TRX_POWER_GSM_30mW);
-	
-	return 0;
-}
-
-static char *serial_port = "/dev/ttyUSB0";
-static char *fname_safety = "BTSBMC76.SWI";
-static char *fname_software = "HS011106.SWL";
-static int delay_ms = 0;
-static int win_size = 8;
-static int param_disconnect = 0;
-static int param_restart = 0;
-static int param_forced = 0;
-static struct gsm_bts *g_bts;
-
-static int file_is_readable(const char *fname)
-{
-	int rc;
-	struct stat st;
-
-	rc = stat(fname, &st);
-	if (rc < 0)
-		return 0;
-
-	if (S_ISREG(st.st_mode) && (st.st_mode & S_IRUSR))
-		return 1;
-
-	return 0;
-}
-
-static int percent;
-static int percent_old;
-
-/* callback function passed to the ABIS OML code */
-static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *msg,
-		       void *data, void *param)
-{
-	if (hook != GSM_HOOK_NM_SWLOAD)
-		return 0;
-
-	switch (event) {
-	case NM_MT_LOAD_INIT_ACK:
-		fprintf(stdout, "Software Load Initiate ACK\n");
-		break;
-	case NM_MT_LOAD_INIT_NACK:
-		fprintf(stderr, "ERROR: Software Load Initiate NACK\n");
-		exit(5);
-		break;
-	case NM_MT_LOAD_END_ACK:
-		if (data) {
-			/* we did a safety load and must activate it */
-			abis_nm_software_activate(g_bts, fname_safety,
-						  swload_cbfn, g_bts);
-			sleep(5);
-		}
-		break;
-	case NM_MT_LOAD_END_NACK:
-		fprintf(stderr, "ERROR: Software Load End NACK\n");
-		exit(3);
-		break;
-	case NM_MT_ACTIVATE_SW_NACK:
-		fprintf(stderr, "ERROR: Activate Software NACK\n");
-		exit(4);
-		break;
-	case NM_MT_ACTIVATE_SW_ACK:
-		bs11cfg_state = STATE_NONE;
-		
-		break;
-	case NM_MT_LOAD_SEG_ACK:
-		percent = abis_nm_software_load_status(g_bts);
-		if (percent > percent_old)
-			printf("Software Download Progress: %d%%\n", percent);
-		percent_old = percent;
-		break;
-	}
-	return 0;
-}
-
-static const struct value_string bs11_linkst_names[] = {
-	{ 0,	"Down" },
-	{ 1,	"Up" },
-	{ 2,	"Restoring" },
-	{ 0,	NULL }
-};
-
-static const char *linkstate_name(uint8_t linkstate)
-{
-	return get_value_string(bs11_linkst_names, linkstate);
-}
-
-static const struct value_string mbccu_load_names[] = {
-	{ 0,	"No Load" },
-	{ 1,	"Load BTSCAC" },
-	{ 2,	"Load BTSDRX" },
-	{ 3,	"Load BTSBBX" },
-	{ 4,	"Load BTSARC" },
-	{ 5,	"Load" },
-	{ 0,	NULL }
-};
-
-static const char *mbccu_load_name(uint8_t linkstate)
-{
-	return get_value_string(mbccu_load_names, linkstate);
-}
-
-static const char *bts_phase_name(uint8_t phase)
-{
-	switch (phase) {
-	case BS11_STATE_WARM_UP:
-	case BS11_STATE_WARM_UP_2:
-		return "Warm Up";
-		break;
-	case BS11_STATE_LOAD_SMU_SAFETY:
-		return "Load SMU Safety";
-		break;
-	case BS11_STATE_LOAD_SMU_INTENDED:
-		return "Load SMU Intended";
-		break;
-	case BS11_STATE_LOAD_MBCCU:
-		return "Load MBCCU";
-		break;
-	case BS11_STATE_SOFTWARE_RQD:
-		return "Software required";
-		break;
-	case BS11_STATE_WAIT_MIN_CFG:
-	case BS11_STATE_WAIT_MIN_CFG_2:
-		return "Wait minimal config";
-		break;
-	case BS11_STATE_MAINTENANCE:
-		return "Maintenance";
-		break;
-	case BS11_STATE_NORMAL:
-		return "Normal";
-		break;
-	case BS11_STATE_ABIS_LOAD:
-		return "Abis load";
-		break;
-	default:
-		return "Unknown";
-		break;
-	}
-}
-
-static const char *trx_power_name(uint8_t pwr)
-{
-	switch (pwr) {
-	case BS11_TRX_POWER_GSM_2W:	
-		return "2W (GSM)";
-	case BS11_TRX_POWER_GSM_250mW:
-		return "250mW (GSM)";
-	case BS11_TRX_POWER_GSM_80mW:
-		return "80mW (GSM)";
-	case BS11_TRX_POWER_GSM_30mW:
-		return "30mW (GSM)";
-	case BS11_TRX_POWER_DCS_3W:
-		return "3W (DCS)";
-	case BS11_TRX_POWER_DCS_1W6:
-		return "1.6W (DCS)";
-	case BS11_TRX_POWER_DCS_500mW:
-		return "500mW (DCS)";
-	case BS11_TRX_POWER_DCS_160mW:
-		return "160mW (DCS)";
-	default:
-		return "unknown value";
-	}
-}
-
-static const char *pll_mode_name(uint8_t mode)
-{
-	switch (mode) {
-	case BS11_LI_PLL_LOCKED:
-		return "E1 Locked";
-	case BS11_LI_PLL_STANDALONE:
-		return "Standalone";
-	default:
-		return "unknown";
-	}
-}
-
-static const char *cclk_acc_name(uint8_t acc)
-{
-	switch (acc) {
-	case 0:
-		/* Out of the demanded +/- 0.05ppm */
-		return "Medium";
-	case 1:
-		/* Synchronized with Abis, within demanded tolerance +/- 0.05ppm */
-		return "High";
-	default:
-		return "unknown";
-	}
-}
-
-static const char *bport_lcfg_name(uint8_t lcfg)
-{
-	switch (lcfg) {
-	case BS11_LINE_CFG_STAR:
-		return "Star";
-	case BS11_LINE_CFG_MULTIDROP:
-		return "Multi-Drop";
-	default:
-		return "unknown";
-	}
-}
-
-static const char *obj_name(struct abis_om_fom_hdr *foh)
-{
-	static char retbuf[256];
-
-	retbuf[0] = 0;
-
-	switch (foh->obj_class) {
-	case NM_OC_BS11:
-		strcat(retbuf, "BS11 ");
-		switch (foh->obj_inst.bts_nr) {
-		case BS11_OBJ_PA:
-			sprintf(retbuf+strlen(retbuf), "Power Amplifier %d ",
-				foh->obj_inst.ts_nr);
-			break;
-		case BS11_OBJ_LI:
-			sprintf(retbuf+strlen(retbuf), "Line Interface ");
-			break;
-		case BS11_OBJ_CCLK:
-			sprintf(retbuf+strlen(retbuf), "CCLK ");
-			break;
-		}
-		break;
-	case NM_OC_SITE_MANAGER:
-		strcat(retbuf, "SITE MANAGER ");
-		break;
-	case NM_OC_BS11_BPORT:
-		sprintf(retbuf+strlen(retbuf), "BPORT%u ",
-			foh->obj_inst.bts_nr);
-		break;
-	}
-	return retbuf;
-}
-
-static void print_state(struct tlv_parsed *tp)
-{
-	if (TLVP_PRESENT(tp, NM_ATT_BS11_BTS_STATE)) {
-		uint8_t phase, mbccu;
-		if (TLVP_LEN(tp, NM_ATT_BS11_BTS_STATE) >= 1) {
-			phase = *TLVP_VAL(tp, NM_ATT_BS11_BTS_STATE);
-			printf("PHASE: %u %-20s ", phase & 0xf,
-				bts_phase_name(phase));
-		}
-		if (TLVP_LEN(tp, NM_ATT_BS11_BTS_STATE) >= 2) {
-			mbccu = *(TLVP_VAL(tp, NM_ATT_BS11_BTS_STATE)+1);
-			printf("MBCCU0: %-11s MBCCU1: %-11s ",
-				mbccu_load_name(mbccu & 0xf), mbccu_load_name(mbccu >> 4));
-		}
-	}
-	if (TLVP_PRESENT(tp, NM_ATT_BS11_E1_STATE) &&
-	    TLVP_LEN(tp, NM_ATT_BS11_E1_STATE) >= 1) {
-		uint8_t e1_state = *TLVP_VAL(tp, NM_ATT_BS11_E1_STATE);
-		printf("Abis-link: %-9s ", linkstate_name(e1_state & 0xf));
-	}
-	printf("\n");
-}
-
-static int print_attr(struct tlv_parsed *tp)
-{
-	if (TLVP_PRESENT(tp, NM_ATT_BS11_ESN_PCB_SERIAL)) {
-		printf("\tBS-11 ESN PCB Serial Number: %s\n",
-			TLVP_VAL(tp, NM_ATT_BS11_ESN_PCB_SERIAL));
-	}
-	if (TLVP_PRESENT(tp, NM_ATT_BS11_ESN_HW_CODE_NO)) {
-		printf("\tBS-11 ESN Hardware Code Number: %s\n",
-			TLVP_VAL(tp, NM_ATT_BS11_ESN_HW_CODE_NO)+6);
-	}
-	if (TLVP_PRESENT(tp, NM_ATT_BS11_ESN_FW_CODE_NO)) {
-		printf("\tBS-11 ESN Firmware Code Number: %s\n",
-			TLVP_VAL(tp, NM_ATT_BS11_ESN_FW_CODE_NO)+6);
-	}
-#if 0
-	if (TLVP_PRESENT(tp, NM_ATT_BS11_BOOT_SW_VERS)) {
-		printf("BS-11 Boot Software Version: %s\n",
-			TLVP_VAL(tp, NM_ATT_BS11_BOOT_SW_VERS)+6);
-	}
-#endif
-	if (TLVP_PRESENT(tp, NM_ATT_ABIS_CHANNEL) &&
-	    TLVP_LEN(tp, NM_ATT_ABIS_CHANNEL) >= 3) {
-		const uint8_t *chan = TLVP_VAL(tp, NM_ATT_ABIS_CHANNEL);
-		printf("\tE1 Channel: Port=%u Timeslot=%u ",
-			chan[0], chan[1]);
-		if (chan[2] == 0xff)
-			printf("(Full Slot)\n");
-		else
-			printf("Subslot=%u\n", chan[2]);
-	}
-	if (TLVP_PRESENT(tp, NM_ATT_TEI))
-		printf("\tTEI: %d\n", *TLVP_VAL(tp, NM_ATT_TEI));
-	if (TLVP_PRESENT(tp, NM_ATT_BS11_TXPWR) &&
-	    TLVP_LEN(tp, NM_ATT_BS11_TXPWR) >= 1) {
-		printf("\tTRX Power: %s\n",
-			trx_power_name(*TLVP_VAL(tp, NM_ATT_BS11_TXPWR)));
-	}
-	if (TLVP_PRESENT(tp, NM_ATT_BS11_PLL_MODE) &&
-	    TLVP_LEN(tp, NM_ATT_BS11_PLL_MODE) >= 1) {
-		printf("\tPLL Mode: %s\n",
-			pll_mode_name(*TLVP_VAL(tp, NM_ATT_BS11_PLL_MODE)));
-	}
-	if (TLVP_PRESENT(tp, NM_ATT_BS11_PLL) &&
-	    TLVP_LEN(tp, NM_ATT_BS11_PLL) >= 4) {
-		const uint8_t *vp = TLVP_VAL(tp, NM_ATT_BS11_PLL);
-		printf("\tPLL Set Value=%d, Work Value=%d\n",
-			vp[0] << 8 | vp[1], vp[2] << 8 | vp[3]);
-	}
-	if (TLVP_PRESENT(tp, NM_ATT_BS11_CCLK_ACCURACY) &&
-	    TLVP_LEN(tp, NM_ATT_BS11_CCLK_ACCURACY) >= 1) {
-		const uint8_t *acc = TLVP_VAL(tp, NM_ATT_BS11_CCLK_ACCURACY);
-		printf("\tCCLK Accuracy: %s (%d)\n", cclk_acc_name(*acc), *acc);
-	}
-	if (TLVP_PRESENT(tp, NM_ATT_BS11_CCLK_TYPE) &&
-	    TLVP_LEN(tp, NM_ATT_BS11_CCLK_TYPE) >= 1) {
-		const uint8_t *acc = TLVP_VAL(tp, NM_ATT_BS11_CCLK_TYPE);
-		printf("\tCCLK Type=%d\n", *acc);
-	}
-	if (TLVP_PRESENT(tp, NM_ATT_BS11_LINE_CFG) &&
-	    TLVP_LEN(tp, NM_ATT_BS11_LINE_CFG) >= 1) {
-		const uint8_t *lcfg = TLVP_VAL(tp, NM_ATT_BS11_LINE_CFG);
-		printf("\tLine Configuration: %s (%d)\n",
-			bport_lcfg_name(*lcfg), *lcfg);
-	}
-
-
-
-	return 0;
-}
-
-static void cmd_query(void)
-{
-	struct gsm_bts_trx *trx = g_bts->c0;
-
-	bs11cfg_state = STATE_QUERY;
-	abis_nm_bs11_get_serno(g_bts);
-	abis_nm_bs11_get_oml_tei_ts(g_bts);
-	abis_nm_bs11_get_pll_mode(g_bts);
-	abis_nm_bs11_get_cclk(g_bts);
-	abis_nm_bs11_get_trx_power(trx);
-	trx = gsm_bts_trx_num(g_bts, 1);
-	if (trx)
-		abis_nm_bs11_get_trx_power(trx);
-	abis_nm_bs11_get_bport_line_cfg(g_bts, 0);
-	abis_nm_bs11_get_bport_line_cfg(g_bts, 1);
-	sleep(1);
-	abis_nm_bs11_factory_logon(g_bts, 0);
-	command = NULL;
-}
-
-/* handle a response from the BTS to a GET STATE command */
-static int handle_state_resp(enum abis_bs11_phase state)
-{
-	int rc = 0;
-
-	switch (state) {
-	case BS11_STATE_WARM_UP:
-	case BS11_STATE_LOAD_SMU_SAFETY:
-	case BS11_STATE_LOAD_SMU_INTENDED:
-	case BS11_STATE_LOAD_MBCCU:
-		break;
-	case BS11_STATE_SOFTWARE_RQD:
-		bs11cfg_state = STATE_SWLOAD;
-		/* send safety load. Use g_bts as private 'param'
-		 * argument, so our swload_cbfn can distinguish
-		 * a safety load from a regular software */
-		if (file_is_readable(fname_safety))
-			rc = abis_nm_software_load(g_bts, 0xff, fname_safety,
-						   win_size, param_forced,
-						   swload_cbfn, g_bts);
-		else
-			fprintf(stderr, "No valid Safety Load file \"%s\"\n",
-				fname_safety);
-		break;
-	case BS11_STATE_WAIT_MIN_CFG:
-	case BS11_STATE_WAIT_MIN_CFG_2:
-		bs11cfg_state = STATE_SWLOAD;
-		rc = create_objects(g_bts);
-		break;
-	case BS11_STATE_MAINTENANCE:
-		if (command) {
-			if (!strcmp(command, "disconnect"))
-				abis_nm_bs11_factory_logon(g_bts, 0);
-			else if (!strcmp(command, "reconnect"))
-				rc = abis_nm_bs11_bsc_disconnect(g_bts, 1);
-			else if (!strcmp(command, "software")
-			    && bs11cfg_state != STATE_SWLOAD) {
-				bs11cfg_state = STATE_SWLOAD;
-				/* send software (FIXME: over A-bis?) */
-				if (file_is_readable(fname_software))
-					rc = abis_nm_bs11_load_swl(g_bts, fname_software,
-								   win_size, param_forced,
-								   swload_cbfn);
-				else
-					fprintf(stderr, "No valid Software file \"%s\"\n",
-						fname_software);
-			} else if (!strcmp(command, "delete-trx1")) {
-				printf("Locing BBSIG and PA objects of TRX1\n");
-				abis_nm_chg_adm_state(g_bts, NM_OC_BS11,
-						      BS11_OBJ_BBSIG, 0, 1,
-						      NM_STATE_LOCKED);
-				abis_nm_chg_adm_state(g_bts, NM_OC_BS11,
-						      BS11_OBJ_PA, 0, 1,
-						      NM_STATE_LOCKED);
-				sleep(1);
-				printf("Deleting BBSIG and PA objects of TRX1\n");
-				abis_nm_bs11_delete_object(g_bts, BS11_OBJ_BBSIG, 1);
-				abis_nm_bs11_delete_object(g_bts, BS11_OBJ_PA, 1);
-				sleep(1);
-				abis_nm_bs11_factory_logon(g_bts, 0);
-				command = NULL;
-			} else if (!strcmp(command, "create-trx1")) {
-				create_trx1(g_bts);
-				sleep(1);
-				abis_nm_bs11_factory_logon(g_bts, 0);
-				command = NULL;
-			} else if (!strcmp(command, "pll-e1-locked")) {
-				abis_nm_bs11_set_pll_locked(g_bts, 1);
-				sleep(1);
-				abis_nm_bs11_factory_logon(g_bts, 0);
-				command = NULL;
-			} else if (!strcmp(command, "pll-standalone")) {
-				abis_nm_bs11_set_pll_locked(g_bts, 0);
-				sleep(1);
-				abis_nm_bs11_factory_logon(g_bts, 0);
-				command = NULL;
-			} else if (!strcmp(command, "pll-setvalue")) {
-				abis_nm_bs11_set_pll(g_bts, atoi(value));
-				sleep(1);
-				abis_nm_bs11_factory_logon(g_bts, 0);
-				command = NULL;
-			} else if (!strcmp(command, "pll-workvalue")) {
-				/* To set the work value we need to login as FIELD */
-				abis_nm_bs11_factory_logon(g_bts, 0);
-				sleep(1);
-				abis_nm_bs11_infield_logon(g_bts, 1);
-				sleep(1);
-				abis_nm_bs11_set_pll(g_bts, atoi(value));
-				sleep(1);
-				abis_nm_bs11_infield_logon(g_bts, 0);
-				command = NULL;
-			} else if (!strcmp(command, "oml-tei")) {
-				abis_nm_bs11_conn_oml_tei(g_bts, 0, 1, 0xff, TEI_OML);
-				command = NULL;
-			} else if (!strcmp(command, "restart")) {
-				abis_nm_bs11_restart(g_bts);
-				command = NULL;
-			} else if (!strcmp(command, "query")) {
-				cmd_query();
-			} else if (!strcmp(command, "create-bport1")) {
-				abis_nm_bs11_create_bport(g_bts, 1);
-				sleep(1);
-				abis_nm_bs11_factory_logon(g_bts, 0);
-				command = NULL;
-			} else if (!strcmp(command, "delete-bport1")) {
-				abis_nm_chg_adm_state(g_bts, NM_OC_BS11_BPORT, 1, 0xff, 0xff, NM_STATE_LOCKED);
-				sleep(1);
-				abis_nm_bs11_delete_bport(g_bts, 1);
-				sleep(1);
-				abis_nm_bs11_factory_logon(g_bts, 0);
-				command = NULL;
-			} else if (!strcmp(command, "bport0-star")) {
-				abis_nm_bs11_set_bport_line_cfg(g_bts, 0, BS11_LINE_CFG_STAR);
-				sleep(1);
-				abis_nm_bs11_factory_logon(g_bts, 0);
-				command = NULL;
-			} else if (!strcmp(command, "bport0-multidrop")) {
-				abis_nm_bs11_set_bport_line_cfg(g_bts, 0, BS11_LINE_CFG_MULTIDROP);
-				sleep(1);
-				abis_nm_bs11_factory_logon(g_bts, 0);
-				command = NULL;
-			} else if (!strcmp(command, "bport1-multidrop")) {
-				abis_nm_bs11_set_bport_line_cfg(g_bts, 1, BS11_LINE_CFG_MULTIDROP);
-				sleep(1);
-				abis_nm_bs11_factory_logon(g_bts, 0);
-				command = NULL;
-			}
-
-		}
-		break;
-	case BS11_STATE_NORMAL:
-		if (command) {
-			if (!strcmp(command, "reconnect"))
-				abis_nm_bs11_factory_logon(g_bts, 0);
-			else if (!strcmp(command, "disconnect"))
-				abis_nm_bs11_bsc_disconnect(g_bts, 0);
-			else if (!strcmp(command, "query")) {
-				cmd_query();
-			}
-		} else if (param_disconnect) {
-			param_disconnect = 0;
-			abis_nm_bs11_bsc_disconnect(g_bts, 0);
-			if (param_restart) {
-				param_restart = 0;
-				abis_nm_bs11_restart(g_bts);
-			}
-		}
-		break;
-	default:
-		break;
-	}
-	return rc;
-}
-
-/* handle a fully-received message/packet from the RS232 port */
-static int abis_nm_bs11cfg_rcvmsg(struct msgb *rx_msg)
-{
-	struct e1inp_sign_link *link = rx_msg->dst;
-	struct abis_om_hdr *oh;
-	struct abis_om_fom_hdr *foh;
-	struct tlv_parsed tp;
-	int rc = -1;
-
-#if 0
-	const uint8_t too_fast[] = { 0x12, 0x80, 0x00, 0x00, 0x02, 0x02 };
-
-	if (rx_msg->len < LAPD_HDR_LEN
-			  + sizeof(struct abis_om_fom_hdr)
-			  + sizeof(struct abis_om_hdr)) {
-		if (!memcmp(rx_msg->data + 2, too_fast,
-			    sizeof(too_fast))) {
-			fprintf(stderr, "BS11 tells us we're too "
-				"fast, try --delay bigger than %u\n",
-				delay_ms);
-			return -E2BIG;
-		} else
-			fprintf(stderr, "unknown BS11 message\n");
-	}
-#endif
-
-	oh = (struct abis_om_hdr *) msgb_l2(rx_msg);
-	foh = (struct abis_om_fom_hdr *) oh->data;
-	switch (foh->msg_type) {
-	case NM_MT_BS11_LMT_LOGON_ACK:
-		printf("LMT LOGON: ACK\n\n");
-		if (bs11cfg_state == STATE_NONE)
-			bs11cfg_state = STATE_LOGON_ACK;
-		rc = abis_nm_bs11_get_state(g_bts);
-		break;
-	case NM_MT_BS11_LMT_LOGOFF_ACK:
-		printf("LMT LOGOFF: ACK\n");
-		exit(0);
-		break;
-	case NM_MT_BS11_GET_STATE_ACK:
-		rc = abis_nm_tlv_parse(&tp, g_bts, foh->data, oh->length-sizeof(*foh));
-		print_state(&tp);
-		if (TLVP_PRESENT(&tp, NM_ATT_BS11_BTS_STATE) &&
-		    TLVP_LEN(&tp, NM_ATT_BS11_BTS_STATE) >= 1)
-			rc = handle_state_resp(*TLVP_VAL(&tp, NM_ATT_BS11_BTS_STATE));
-		break;
-	case NM_MT_GET_ATTR_RESP:
-		printf("\n%sATTRIBUTES:\n", obj_name(foh));
-		abis_nm_tlv_parse(&tp, g_bts, foh->data, oh->length-sizeof(*foh));
-		rc = print_attr(&tp);
-		//osmo_hexdump(foh->data, oh->length-sizeof(*foh));
-		break;
-	case NM_MT_BS11_SET_ATTR_ACK:
-		printf("SET ATTRIBUTE ObjClass=0x%02x ObjInst=(%d,%d,%d) ACK\n",
-			foh->obj_class, foh->obj_inst.bts_nr,
-			foh->obj_inst.trx_nr, foh->obj_inst.ts_nr);
-		rc = 0;
-		break;
-	case NM_MT_BS11_SET_ATTR_NACK:
-		printf("SET ATTRIBUTE ObjClass=0x%02x ObjInst=(%d,%d,%d) NACK\n",
-			foh->obj_class, foh->obj_inst.bts_nr,
-			foh->obj_inst.trx_nr, foh->obj_inst.ts_nr);
-		break;
-	case NM_MT_GET_ATTR_NACK:
-		printf("\n%sGET ATTR NACK\n", obj_name(foh));
-		break;
-	case NM_MT_BS11_CREATE_OBJ_ACK:
-		printf("\n%sCREATE OBJECT ACK\n", obj_name(foh));
-		break;
-	case NM_MT_BS11_CREATE_OBJ_NACK:
-		printf("\n%sCREATE OBJECT NACK\n", obj_name(foh));
-		break;
-	case NM_MT_BS11_DELETE_OBJ_ACK:
-		printf("\n%sDELETE OBJECT ACK\n", obj_name(foh));
-		break;
-	case NM_MT_BS11_DELETE_OBJ_NACK:
-		printf("\n%sDELETE OBJECT NACK\n", obj_name(foh));
-		break;
-	default:
-		rc = abis_nm_rcvmsg(rx_msg);
-	}
-	if (rc < 0) {
-		perror("ERROR in main loop");
-		//break;
-	}
-	/* flush the queue of pending messages to be sent. */
-	abis_nm_queue_send_next(link->trx->bts);
-	if (rc == 1)
-		return rc;
-
-	switch (bs11cfg_state) {
-	case STATE_NONE:
-		abis_nm_bs11_factory_logon(g_bts, 1);
-		break;
-	case STATE_LOGON_ACK:
-		osmo_timer_schedule(&status_timer, 5, 0);
-		break;
-	default:
-		break;
-	}
-
-	return rc;
-}
-
-void status_timer_cb(void *data)
-{
-	abis_nm_bs11_get_state(g_bts);
-}
-
-static void print_banner(void)
-{
-	printf("bs11_config (C) 2009-2010 by Harald Welte and Dieter Spaar\n");
-	printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
-}
-
-static void print_help(void)
-{
-	printf("bs11_config [options] [command]\n");
-	printf("\nSupported options:\n");
-	printf("\t-h --help\t\t\tPrint this help text\n");
-	printf("\t-p --port </dev/ttyXXX>\t\tSpecify serial port\n");
-	printf("\t-s --software <file>\t\tSpecify Software file\n");
-	printf("\t-S --safety <file>\t\tSpecify Safety Load file\n");
-	printf("\t-d --delay <ms>\t\t\tSpecify delay in milliseconds\n");
-	printf("\t-D --disconnect\t\t\tDisconnect BTS from BSC\n");
-	printf("\t-w --win-size <num>\t\tSpecify Window Size\n");
-	printf("\t-f --forced\t\t\tForce Software Load\n");
-	printf("\nSupported commands:\n");
-	printf("\tquery\t\t\tQuery the BS-11 about serial number and configuration\n");
-	printf("\tdisconnect\t\tDisconnect A-bis link (go into administrative state)\n");
-	printf("\tresconnect\t\tReconnect A-bis link (go into normal state)\n");
-	printf("\trestart\t\t\tRestart the BTS\n");
-	printf("\tsoftware\t\tDownload Software (only in administrative state)\n");
-	printf("\tcreate-trx1\t\tCreate objects for TRX1 (Danger: Your BS-11 might overheat)\n");
-	printf("\tdelete-trx1\t\tDelete objects for TRX1\n");
-	printf("\tpll-e1-locked\t\tSet the PLL to be locked to E1 clock\n");
-	printf("\tpll-standalone\t\tSet the PLL to be in standalone mode\n");
-	printf("\tpll-setvalue <value>\tSet the PLL set value\n");
-	printf("\tpll-workvalue <value>\tSet the PLL work value\n");
-	printf("\toml-tei\t\t\tSet OML E1 TS and TEI\n");
-	printf("\tbport0-star\t\tSet BPORT0 line config to star\n");
-	printf("\tbport0-multidrop\tSet BPORT0 line config to multidrop\n");
-	printf("\tbport1-multidrop\tSet BPORT1 line config to multidrop\n");
-	printf("\tcreate-bport1\t\tCreate BPORT1 object\n");
-	printf("\tdelete-bport1\t\tDelete BPORT1 object\n");
-}
-
-static void handle_options(int argc, char **argv)
-{
-	int option_index = 0;
-	print_banner();
-
-	while (1) {
-		int c;
-		static struct option long_options[] = {
-			{ "help", 0, 0, 'h' },
-			{ "port", 1, 0, 'p' },
-			{ "software", 1, 0, 's' },
-			{ "safety", 1, 0, 'S' },
-			{ "delay", 1, 0, 'd' },
-			{ "disconnect", 0, 0, 'D' },
-			{ "win-size", 1, 0, 'w' },
-			{ "forced", 0, 0, 'f' },
-			{ "restart", 0, 0, 'r' },
-			{ "debug", 1, 0, 'b'},
-		};
-
-		c = getopt_long(argc, argv, "hp:s:S:td:Dw:fra:",
-				long_options, &option_index);
-
-		if (c == -1)
-			break;
-
-		switch (c) {
-		case 'h':
-			print_help();
-			exit(0);
-		case 'p':
-			serial_port = optarg;
-			break;
-		case 'b':
-			log_parse_category_mask(osmo_stderr_target, optarg);
-			break;
-		case 's':
-			fname_software = optarg;
-			break;
-		case 'S':
-			fname_safety = optarg;
-			break;
-		case 'd':
-			delay_ms = atoi(optarg);
-			break;
-		case 'w':
-			win_size = atoi(optarg);
-			break;
-		case 'D':
-			param_disconnect = 1;
-			break;
-		case 'f':
-			param_forced = 1;
-			break;
-		case 'r':
-			param_disconnect = 1;
-			param_restart = 1;
-			break;
-		default:
-			break;
-		}
-	}
-	if (optind < argc) {
-		command = argv[optind];
-	        if (optind+1 < argc)
-			value = argv[optind+1];
-	}
-
-}
-
-static int num_sigint;
-
-static void signal_handler(int signal)
-{
-	fprintf(stdout, "\nsignal %u received\n", signal);
-
-	switch (signal) {
-	case SIGINT:
-		num_sigint++;
-		abis_nm_bs11_factory_logon(g_bts, 0);
-		if (num_sigint >= 3)
-			exit(0);
-		break;
-	}
-}
-
-static int bs11cfg_sign_link(struct msgb *msg)
-{
-	msg->dst = oml_link;
-	return abis_nm_bs11cfg_rcvmsg(msg);
-}
-
-struct e1inp_line_ops bs11cfg_e1inp_line_ops = {
-	.sign_link	= bs11cfg_sign_link,
-};
-
-extern int bts_model_bs11_init(void);
-int main(int argc, char **argv)
-{
-	struct gsm_network *gsmnet;
-	struct e1inp_line *line;
-
-	tall_bs11cfg_ctx = talloc_named_const(NULL, 0, "bs11-config");
-	msgb_talloc_ctx_init(tall_bs11cfg_ctx, 0);
-
-	osmo_init_logging(&log_info);
-	handle_options(argc, argv);
-	bts_model_bs11_init();
-
-	gsmnet = bsc_network_init(tall_bs11cfg_ctx, 1, 1, NULL);
-	if (!gsmnet) {
-		fprintf(stderr, "Unable to allocate gsm network\n");
-		exit(1);
-	}
-	g_bts = gsm_bts_alloc_register(gsmnet, GSM_BTS_TYPE_BS11,
-					HARDCODED_BSIC);
-
-	/* Override existing OML callback handler to set our own. */
-	g_bts->model->oml_rcvmsg = abis_nm_bs11cfg_rcvmsg;
-
-	libosmo_abis_init(tall_bs11cfg_ctx);
-
-	/* Initialize virtual E1 line over rs232. */
-	line = talloc_zero(tall_bs11cfg_ctx, struct e1inp_line);
-	if (!line) {
-		fprintf(stderr, "Unable to allocate memory for virtual E1 line\n");
-		exit(1);
-	}
-	/* set the serial port. */
-	bs11cfg_e1inp_line_ops.cfg.rs232.port = serial_port;
-	bs11cfg_e1inp_line_ops.cfg.rs232.delay = delay_ms;
-
-	line->driver = e1inp_driver_find("rs232");
-	if (!line->driver) {
-		fprintf(stderr, "cannot find `rs232' driver, giving up.\n");
-		exit(1);
-	}
-	e1inp_line_bind_ops(line, &bs11cfg_e1inp_line_ops);
-
-	/* configure and create signalling link for OML. */
-	e1inp_ts_config_sign(&line->ts[0], line);
-	g_bts->oml_link = oml_link =
-		e1inp_sign_link_create(&line->ts[0], E1INP_SIGN_OML,
-					g_bts->c0, TEI_OML, 0);
-
-	e1inp_line_update(line);
-
-	signal(SIGINT, &signal_handler);
-
-	abis_nm_bs11_factory_logon(g_bts, 1);
-	//abis_nm_bs11_get_serno(g_bts);
-
-	osmo_timer_setup(&status_timer, status_timer_cb, NULL);
-
-	while (1) {
-		if (osmo_select_main(0) < 0)
-			break;
-	}
-
-	abis_nm_bs11_factory_logon(g_bts, 0);
-
-	exit(0);
-}
diff --git a/src/utils/isdnsync.c b/src/utils/isdnsync.c
deleted file mode 100644
index cc8ff67..0000000
--- a/src/utils/isdnsync.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/* isdnsync.c
- *
- * Author       Andreas Eversberg <jolly@eversberg.eu>
- *
- * 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/>.
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include "mISDNif.h"
-#define MISDN_OLD_AF_COMPATIBILITY
-#define AF_COMPATIBILITY_FUNC
-#include "compat_af_isdn.h"
-
-int card = 0;
-int sock = -1;
-
-int mISDN_open(void)
-{
-	int			fd, ret;
-	struct mISDN_devinfo	devinfo;
-	struct sockaddr_mISDN	l2addr;
-
-	fd = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
-	if (fd < 0) {
-		fprintf(stderr, "could not open socket (%s)\n", strerror(errno));
-		return fd;
-	}
-	devinfo.id = card;
-	ret = ioctl(fd, IMGETDEVINFO, &devinfo);
-	if (ret < 0) {
-		fprintf(stderr,"could not send IOCTL IMGETCOUNT (%s)\n", strerror(errno));
-		close(fd);
-		return ret;
-	}
-	close(fd);
-	if (!(devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
-	 && !(devinfo.Dprotocols & (1 << ISDN_P_TE_E1))) {
-		fprintf(stderr,"Interface does not support TE mode (%s)\n", strerror(errno));
-		return ret;
-	}
-	fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_LAPD_TE);
-	if (fd < 0) {
-		fprintf(stderr,"could not open ISDN_P_LAPD_TE socket (%s)\n", strerror(errno));
-		return fd;
-	}
-	l2addr.family = AF_ISDN;
-	l2addr.dev = card;
-	l2addr.channel = 0;
-	l2addr.sapi = 0;
-	l2addr.tei = 0;
-	ret = bind(fd, (struct sockaddr *)&l2addr, sizeof(l2addr));
-	if (ret < 0) {
-		fprintf(stderr,"could not bind socket for card %d (%s)\n", card, strerror(errno));
-		close(fd);
-		return ret;
-	}
-	sock = fd;
-
-	return sock;
-}
-
-
-void mISDN_handle(void)
-{
-	int ret;
-	fd_set rfd;
-	struct timeval tv;
-	struct sockaddr_mISDN addr;
-	socklen_t alen;
-	unsigned char buffer[2048];
-	struct mISDNhead *hh = (struct mISDNhead *)buffer;
-	int l1 = 0, l2 = 0, tei = 0;
-
-	while(1) {
-again:
-		FD_ZERO(&rfd);
-		FD_SET(sock, &rfd);
-		tv.tv_sec = 2;
-		tv.tv_usec = 0;
-		ret = select(sock+1, &rfd, NULL, NULL, &tv);
-		if (ret < 0) {
-			if (errno == EINTR)
-				continue;
-			fprintf(stderr, "%s aborted: %s\n", __FUNCTION__, strerror(errno));
-			break;
-		}
-		if (FD_ISSET(sock, &rfd)) {
-			alen = sizeof(addr);
-			ret = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *) &addr, &alen);
-			if (ret < 0) {
-				fprintf(stderr, "%s read socket error %s\n", __FUNCTION__, strerror(errno));
-			} else if (ret < MISDN_HEADER_LEN) {
-					fprintf(stderr, "%s read socket shor frame\n", __FUNCTION__);
-			} else {
-				switch(hh->prim) {
-					case MPH_ACTIVATE_IND:
-					case PH_ACTIVATE_IND:
-						if (!l1) {
-							printf("PH_ACTIVATE\n");
-							printf("*** Sync available from interface :-)\n");
-							l1 = 1;
-						}
-						goto again;
-					break;
-					case MPH_DEACTIVATE_IND:
-					case PH_DEACTIVATE_IND:
-						if (l1) {
-							printf("PH_DEACTIVATE\n");
-							printf("*** Lost sync on interface        :-(\n");
-							l1 = 0;
-						}
-						goto again;
-					break;
-					case DL_ESTABLISH_IND:
-					case DL_ESTABLISH_CNF:
-						printf("DL_ESTABLISH\n");
-						l2 = 1;
-						goto again;
-					break;
-					case DL_RELEASE_IND:
-					case DL_RELEASE_CNF:
-						printf("DL_RELEASE\n");
-						l2 = 0;
-						goto again;
-					break;
-					case DL_INFORMATION_IND:
-						printf("DL_INFORMATION (tei %d sapi %d)\n", addr.tei, addr.sapi);
-						tei = 1;
-					break;
-					default:
-//						printf("prim %x\n", hh->prim);
-						goto again;
-				}
-			}
-		}
-		if (tei && !l2) {
-			hh->prim = DL_ESTABLISH_REQ;
-			printf("-> activating layer 2\n");
-			sendto(sock, buffer, MISDN_HEADER_LEN, 0, (struct sockaddr *) &addr, alen);
-		}
-	}
-}
-
-int main(int argc, char *argv[])
-{
-	int ret;
-
-	if (argc <= 1)
-	{
-		printf("Usage: %s <card>\n\n", argv[0]);
-		printf("Opens given card number in TE-mode PTP and tries to keep layer 2 established.\n");
-		printf("This keeps layer 1 activated to retrieve a steady sync signal from network.\n");
-		return(0);
-	}
-
-	card = atoi(argv[1]);
-
-	init_af_isdn();
-
-	if ((ret = mISDN_open() < 0))
-		return(ret);
-
-	mISDN_handle();
-
-	close(sock);
-
-	return 0;
-}
diff --git a/src/utils/meas_db.c b/src/utils/meas_db.c
deleted file mode 100644
index d81efca..0000000
--- a/src/utils/meas_db.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/* Routines for storing measurement reports in SQLite3 database */
-
-/* (C) 2012 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/>.
- *
- */
-
-#include <stdint.h>
-#include <errno.h>
-#include <string.h>
-
-#include <sqlite3.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <openbsc/meas_rep.h>
-
-#include "meas_db.h"
-
-#define INS_MR "INSERT INTO meas_rep (time, imsi, name, scenario, nr, bs_power, ms_timing_offset, fpc, ms_l1_pwr, ms_l1_ta) VALUES (?,?,?,?,?,?,?,?,?,?)"
-#define INS_UD "INSERT INTO meas_rep_unidir (meas_id, rx_lev_full, rx_lev_sub, rx_qual_full, rx_qual_sub, dtx, uplink) VALUES (?,?,?,?,?,?,?)"
-#define UPD_MR "UPDATE meas_rep SET ul_unidir=?, dl_unidir=? WHERE id=?"
-
-struct meas_db_state {
-	sqlite3 *db;
-	sqlite3_stmt *stmt_ins_ud;
-	sqlite3_stmt *stmt_ins_mr;
-	sqlite3_stmt *stmt_upd_mr;
-};
-
-/* macros to check for SQLite3 result codes */
-#define _SCK_OK(db, call, exp)				\
-	do {						\
-		int rc = call;				\
-		if (rc != exp) {			\
-			fprintf(stderr,"SQL Error in line %u: %s\n",	\
-				__LINE__, sqlite3_errmsg(db));		\
-			goto err_io;					\
-		}							\
-	} while (0)
-#define SCK_OK(db, call)	_SCK_OK(db, call, SQLITE_OK)
-#define SCK_DONE(db, call)	_SCK_OK(db, call, SQLITE_DONE)
-
-static int _insert_ud(struct meas_db_state *st, unsigned long meas_id, int dtx,
-		      int uplink, const struct gsm_meas_rep_unidir *ud)
-{
-	unsigned long rowid;
-
-	SCK_OK(st->db, sqlite3_bind_int(st->stmt_ins_ud, 1, meas_id));
-	SCK_OK(st->db, sqlite3_bind_int(st->stmt_ins_ud, 2,
-					rxlev2dbm(ud->full.rx_lev)));
-	SCK_OK(st->db, sqlite3_bind_int(st->stmt_ins_ud, 3,
-					rxlev2dbm(ud->sub.rx_lev)));
-	SCK_OK(st->db, sqlite3_bind_int(st->stmt_ins_ud, 4, ud->full.rx_qual));
-	SCK_OK(st->db, sqlite3_bind_int(st->stmt_ins_ud, 5, ud->sub.rx_qual));
-	SCK_OK(st->db, sqlite3_bind_int(st->stmt_ins_ud, 6, dtx));
-	SCK_OK(st->db, sqlite3_bind_int(st->stmt_ins_ud, 7, uplink));
-
-	SCK_DONE(st->db, sqlite3_step(st->stmt_ins_ud));
-
-	SCK_OK(st->db, sqlite3_reset(st->stmt_ins_ud));
-
-	return sqlite3_last_insert_rowid(st->db);
-err_io:
-	exit(1);
-}
-
-/* insert a measurement report into the database */
-int meas_db_insert(struct meas_db_state *st, const char *imsi,
-		   const char *name, unsigned long timestamp,
-		   const char *scenario,
-		   const struct gsm_meas_rep *mr)
-{
-	int rc;
-	sqlite3_int64 rowid, ul_rowid, dl_rowid;
-
-	SCK_OK(st->db, sqlite3_bind_int(st->stmt_ins_mr, 1, timestamp));
-
-	if (imsi)
-		SCK_OK(st->db, sqlite3_bind_text(st->stmt_ins_mr, 2,
-						 imsi, -1, SQLITE_STATIC));
-	else
-		SCK_OK(st->db, sqlite3_bind_null(st->stmt_ins_mr, 2));
-
-	if (name)
-		SCK_OK(st->db, sqlite3_bind_text(st->stmt_ins_mr, 3,
-						 name, -1, SQLITE_STATIC));
-	else
-		SCK_OK(st->db, sqlite3_bind_null(st->stmt_ins_mr, 3));
-
-	if (scenario)
-		SCK_OK(st->db, sqlite3_bind_text(st->stmt_ins_mr, 4,
-						 scenario, -1, SQLITE_STATIC));
-	else
-		SCK_OK(st->db, sqlite3_bind_null(st->stmt_ins_mr, 4));
-
-
-	SCK_OK(st->db, sqlite3_bind_int(st->stmt_ins_mr, 5, mr->nr));
-	SCK_OK(st->db, sqlite3_bind_int(st->stmt_ins_mr, 6, mr->bs_power));
-
-	if (mr->flags & MEAS_REP_F_MS_TO)
-		SCK_OK(st->db, sqlite3_bind_int(st->stmt_ins_mr, 7, mr->ms_timing_offset));
-	else
-		SCK_OK(st->db, sqlite3_bind_null(st->stmt_ins_mr, 7));
-
-	if (mr->flags & MEAS_REP_F_FPC)
-		SCK_OK(st->db, sqlite3_bind_int(st->stmt_ins_mr, 8, 1));
-	else
-		SCK_OK(st->db, sqlite3_bind_int(st->stmt_ins_mr, 8, 0));
-
-	if (mr->flags & MEAS_REP_F_MS_L1) {
-		SCK_OK(st->db, sqlite3_bind_int(st->stmt_ins_mr, 9,
-						mr->ms_l1.pwr));
-		SCK_OK(st->db, sqlite3_bind_int(st->stmt_ins_mr, 10,
-						mr->ms_l1.ta));
-	}
-
-	SCK_DONE(st->db, sqlite3_step(st->stmt_ins_mr));
-	SCK_OK(st->db, sqlite3_reset(st->stmt_ins_mr));
-
-	rowid = sqlite3_last_insert_rowid(st->db);
-
-	/* insert uplink measurement */
-	ul_rowid = _insert_ud(st, rowid, mr->flags & MEAS_REP_F_UL_DTX,
-				1, &mr->ul);
-	SCK_OK(st->db, sqlite3_bind_int(st->stmt_upd_mr, 1, ul_rowid));
-
-	/* insert downlink measurement, if present */
-	if (mr->flags & MEAS_REP_F_DL_VALID) {
-		dl_rowid = _insert_ud(st, rowid, mr->flags & MEAS_REP_F_DL_DTX,
-			       	      0, &mr->dl);
-		SCK_OK(st->db, sqlite3_bind_int(st->stmt_upd_mr, 2, dl_rowid));
-	} else
-		SCK_OK(st->db, sqlite3_bind_null(st->stmt_upd_mr, 2));
-
-	/* update meas_rep with the id's of the unidirectional
-	 * measurements */
-	SCK_OK(st->db, sqlite3_bind_int(st->stmt_upd_mr, 3, rowid));
-	SCK_DONE(st->db, sqlite3_step(st->stmt_upd_mr));
-	SCK_OK(st->db, sqlite3_reset(st->stmt_upd_mr));
-
-	return 0;
-
-err_io:
-	return -EIO;
-}
-
-int meas_db_begin(struct meas_db_state *st)
-{
-	SCK_OK(st->db, sqlite3_exec(st->db, "BEGIN", NULL, NULL, NULL));
-
-	return 0;
-
-err_io:
-	return -EIO;
-}
-
-int meas_db_commit(struct meas_db_state *st)
-{
-	SCK_OK(st->db, sqlite3_exec(st->db, "COMMIT", NULL, NULL, NULL));
-
-	return 0;
-
-err_io:
-	return -EIO;
-}
-
-static const char *create_stmts[] = {
-	"CREATE TABLE IF NOT EXISTS meas_rep ("
-		"id INTEGER PRIMARY KEY AUTOINCREMENT,"
-		"time TIMESTAMP,"
-		"imsi TEXT,"
-		"name TEXT,"
-		"scenario TEXT,"
-		"nr INTEGER,"
-		"bs_power INTEGER NOT NULL,"
-		"ms_timing_offset INTEGER,"
-		"fpc INTEGER NOT NULL DEFAULT 0,"
-		"ul_unidir INTEGER REFERENCES meas_rep_unidir(id),"
-		"dl_unidir INTEGER REFERENCES meas_rep_unidir(id),"
-		"ms_l1_pwr INTEGER,"
-		"ms_l1_ta INTEGER"
-	")",
-	"CREATE TABLE IF NOT EXISTS meas_rep_unidir ("
-		"id INTEGER PRIMARY KEY AUTOINCREMENT,"
-		"meas_id INTEGER NOT NULL REFERENCES meas_rep(id),"
-		"rx_lev_full INTEGER NOT NULL,"
-		"rx_lev_sub INTEGER NOT NULL,"
-		"rx_qual_full INTEGER NOT NULL,"
-		"rx_qual_sub INTEGER NOT NULL,"
-		"dtx BOOLEAN NOT NULL DEFAULT 0,"
-	       	"uplink BOOLEAN NOT NULL"
-	")",
-	"CREATE VIEW IF NOT EXISTS path_loss AS "
-		"SELECT "
-			"meas_rep.id, "
-			"datetime(time,'unixepoch') AS timestamp, "
-			"imsi, "
-			"name, "
-			"scenario, "
-			"ms_timing_offset, "
-			"ms_l1_ta, "
-			"fpc, "
-			"ms_l1_pwr, "
-			"ud_ul.rx_lev_full AS ul_rx_lev_full, "
-			"ms_l1_pwr-ud_ul.rx_lev_full AS ul_path_loss_full, "
-			"ud_ul.rx_lev_sub ul_rx_lev_sub, "
-			"ms_l1_pwr-ud_ul.rx_lev_sub AS ul_path_loss_sub, "
-			"ud_ul.rx_qual_full AS ul_rx_qual_full, "
-			"ud_ul.rx_qual_sub AS ul_rx_qual_sub, "
-			"bs_power, "
-			"ud_dl.rx_lev_full AS dl_rx_lev_full, "
-			"bs_power-ud_dl.rx_lev_full AS dl_path_loss_full, "
-			"ud_dl.rx_lev_sub AS dl_rx_lev_sub, "
-			"bs_power-ud_dl.rx_lev_sub AS dl_path_loss_sub, "
-			"ud_dl.rx_qual_full AS dl_rx_qual_full, "
-			"ud_dl.rx_qual_sub AS dl_rx_qual_sub "
-		"FROM "
-			"meas_rep, "
-			"meas_rep_unidir AS ud_dl, "
-			"meas_rep_unidir AS ud_ul "
-		"WHERE "
-			"ud_ul.id = meas_rep.ul_unidir AND "
-			"ud_dl.id = meas_rep.dl_unidir",
-	"CREATE VIEW IF NOT EXISTS overview AS "
-		"SELECT "
-			"id,"
-			"timestamp,"
-			"imsi,"
-			"name,"
-			"scenario,"
-			"ms_l1_pwr,"
-			"ul_rx_lev_full,"
-			"ul_path_loss_full,"
-			"ul_rx_qual_full,"
-			"bs_power,"
-			"dl_rx_lev_full,"
-			"dl_path_loss_full,"
-			"dl_rx_qual_full "
-		"FROM path_loss",
-};
-
-static int check_create_tbl(struct meas_db_state *st)
-{
-	int i, rc;
-
-	for (i = 0; i < ARRAY_SIZE(create_stmts); i++) {
-		SCK_OK(st->db, sqlite3_exec(st->db, create_stmts[i],
-					    NULL, NULL, NULL));
-	}
-
-	return 0;
-err_io:
-	return -EIO;
-}
-
-
-#define PREP_CHK(db, stmt, ptr)						\
-	do {								\
-		int rc;							\
-		rc = sqlite3_prepare_v2(db, stmt, strlen(stmt)+1,	\
-					ptr, NULL); 			\
-		if (rc != SQLITE_OK) {					\
-			fprintf(stderr, "Error during prepare of '%s': %s\n", \
-				stmt, sqlite3_errmsg(db)); 		\
-			goto err_io;					\
-		}							\
-	} while (0)
-
-struct meas_db_state *meas_db_open(void *ctx, const char *fname)
-{
-	int rc;
-	struct meas_db_state *st = talloc_zero(ctx, struct meas_db_state);
-
-	if (!st)
-		return NULL;
-
-	rc = sqlite3_open_v2(fname, &st->db,
-			     SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE,
-			     NULL);
-	if (rc != SQLITE_OK) {
-		fprintf(stderr, "Unable to open DB: %s\n",
-			sqlite3_errmsg(st->db));
-		goto err_io;
-	}
-
-	rc = check_create_tbl(st);
-
-	PREP_CHK(st->db, INS_MR, &st->stmt_ins_mr);
-	PREP_CHK(st->db, INS_UD, &st->stmt_ins_ud);
-	PREP_CHK(st->db, UPD_MR, &st->stmt_upd_mr);
-
-	return st;
-err_io:
-	talloc_free(st);
-	return NULL;
-}
-
-void meas_db_close(struct meas_db_state *st)
-{
-	if (sqlite3_finalize(st->stmt_ins_mr) != SQLITE_OK)
-		fprintf(stderr, "DB insert measurement report finalize error: %s\n",
-			sqlite3_errmsg(st->db));
-	if (sqlite3_finalize(st->stmt_ins_ud) != SQLITE_OK)
-		fprintf(stderr, "DB insert unidir finalize error: %s\n",
-			sqlite3_errmsg(st->db));
-	if (sqlite3_finalize(st->stmt_upd_mr) != SQLITE_OK)
-		fprintf(stderr, "DB update measurement report finalize error: %s\n",
-			sqlite3_errmsg(st->db));
-	if (sqlite3_close(st->db) != SQLITE_OK)
-		fprintf(stderr, "Unable to close DB, abandoning.\n");
-
-	talloc_free(st);
-
-}
diff --git a/src/utils/meas_db.h b/src/utils/meas_db.h
deleted file mode 100644
index 889e902..0000000
--- a/src/utils/meas_db.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef OPENBSC_MEAS_DB_H
-#define OPENBSC_MEAS_DB_H
-
-struct meas_db_state;
-
-struct meas_db_state *meas_db_open(void *ctx, const char *fname);
-void meas_db_close(struct meas_db_state *st);
-
-int meas_db_begin(struct meas_db_state *st);
-int meas_db_commit(struct meas_db_state *st);
-
-int meas_db_insert(struct meas_db_state *st, const char *imsi,
-		   const char *name, unsigned long timestamp,
-		   const char *scenario,
-		   const struct gsm_meas_rep *mr);
-
-#endif
diff --git a/src/utils/meas_json.c b/src/utils/meas_json.c
deleted file mode 100644
index 51eb6c7..0000000
--- a/src/utils/meas_json.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/* Convert measurement report feed into JSON feed printed to stdout.
- * Each measurement report is printed as a separae JSON root entry.
- * All measurement reports are separated by a new line.
- */
-
-/* (C) 2015 by Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
- * With parts of code adopted from different places in OpenBSC.
- *
- * 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/>.
- *
- */
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-
-#include <netinet/in.h>
-
-#include <osmocom/core/socket.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/select.h>
-
-#include <osmocom/gsm/gsm_utils.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_data_shared.h>
-#include <openbsc/meas_feed.h>
-
-static void print_meas_rep_uni_json(struct gsm_meas_rep_unidir *mru)
-{
-	printf("\"RXL-FULL\":%d, \"RXL-SUB\":%d, ",
-		rxlev2dbm(mru->full.rx_lev),
-		rxlev2dbm(mru->sub.rx_lev));
-	printf("\"RXQ-FULL\":%d, \"RXQ-SUB\":%d",
-		mru->full.rx_qual, mru->sub.rx_qual);
-}
-
-static void print_meas_rep_json(struct gsm_meas_rep *mr)
-{
-	int i;
-
-	printf("\"NR\":%d", mr->nr);
-
-	if (mr->flags & MEAS_REP_F_DL_DTX)
-		printf(", \"DTXd\":true");
-
-	printf(", \"UL_MEAS\":{");
-	print_meas_rep_uni_json(&mr->ul);
-	printf("}");
-	printf(", \"BS_POWER\":%d", mr->bs_power);
-	if (mr->flags & MEAS_REP_F_MS_TO)
-		printf(", \"MS_TO\":%d", mr->ms_timing_offset);
-
-	if (mr->flags & MEAS_REP_F_MS_L1) {
-		printf(", \"L1_MS_PWR\":%d", mr->ms_l1.pwr);
-		printf(", \"L1_FPC\":%s",
-			mr->flags & MEAS_REP_F_FPC ? "true" : "false");
-		printf(", \"L1_TA\":%u", mr->ms_l1.ta);
-	}
-
-	if (mr->flags & MEAS_REP_F_UL_DTX)
-		printf(", \"DTXu\":true");
-	if (mr->flags & MEAS_REP_F_BA1)
-		printf(", \"BA1\":true");
-	if (mr->flags & MEAS_REP_F_DL_VALID) {
-		printf(", \"DL_MEAS\":{");
-		print_meas_rep_uni_json(&mr->dl);
-		printf("}");
-	}
-
-	if (mr->num_cell == 7)
-		return;
-	printf(", \"NUM_NEIGH\":%u, \"NEIGH\":[", mr->num_cell);
-	for (i = 0; i < mr->num_cell; i++) {
-		struct gsm_meas_rep_cell *mrc = &mr->cell[i];
-		if (i!=0) printf(", ");
-		printf("{\"IDX\":%u, \"ARFCN\":%u, \"BSIC\":%u, \"POWER\":%d}",
-			mrc->neigh_idx, mrc->arfcn, mrc->bsic, rxlev2dbm(mrc->rxlev));
-	}
-	printf("]");
-}
-
-static void print_chan_info_json(struct meas_feed_meas *mfm)
-{
-	printf("\"lchan_type\":\"%s\", \"pchan_type\":\"%s\", "
-		   "\"bts_nr\":%d, \"trx_nr\":%d, \"ts_nr\":%d, \"ss_nr\":%d",
-	gsm_lchant_name(mfm->lchan_type), gsm_pchan_name(mfm->pchan_type),
-	mfm->bts_nr, mfm->trx_nr, mfm->ts_nr, mfm->ss_nr);
-}
-
-static void print_meas_feed_json(struct meas_feed_meas *mfm)
-{
-	time_t now = time(NULL);
-
-	printf("{");
-	printf("\"time\":%ld, \"imsi\":\"%s\", \"name\":\"%s\", \"scenario\":\"%s\", ",
-		now, mfm->imsi, mfm->name, mfm->scenario);
-
-	switch (mfm->hdr.version) {
-	case 1:
-		printf("\"chan_info\":{");
-		print_chan_info_json(mfm);
-		printf("}, ");
-		/* no break, fall to version 0 */
-	case 0:
-		printf("\"meas_rep\":{");
-		print_meas_rep_json(&mfm->mr);
-		printf("}");
-		break;
-	}
-
-	printf("}\n");
-
-}
-
-static int handle_meas(struct msgb *msg)
-{
-	struct meas_feed_meas *mfm = (struct meas_feed_meas *) msgb_data(msg);
-
-	print_meas_feed_json(mfm);
-
-	return 0;
-}
-
-static int handle_msg(struct msgb *msg)
-{
-	struct meas_feed_hdr *mfh = (struct meas_feed_hdr *) msgb_data(msg);
-
-	if (mfh->version != MEAS_FEED_VERSION)
-		return -EINVAL;
-
-	switch (mfh->msg_type) {
-	case MEAS_FEED_MEAS:
-		handle_meas(msg);
-		break;
-	default:
-		break;
-	}
-	return 0;
-}
-
-static int udp_fd_cb(struct osmo_fd *ofd, unsigned int what)
-{
-	int rc;
-
-	if (what & BSC_FD_READ) {
-		struct msgb *msg = msgb_alloc(1024, "UDP Rx");
-
-		rc = read(ofd->fd, msgb_data(msg), msgb_tailroom(msg));
-		if (rc < 0)
-			return rc;
-		msgb_put(msg, rc);
-		handle_msg(msg);
-		msgb_free(msg);
-	}
-
-	return 0;
-}
-
-int main(int argc, char **argv)
-{
-	int rc;
-	struct osmo_fd udp_ofd;
-
-	udp_ofd.cb = udp_fd_cb;
-	rc =  osmo_sock_init_ofd(&udp_ofd, AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 8888, OSMO_SOCK_F_BIND);
-	if (rc < 0)
-		exit(1);
-
-	while (1) {
-		osmo_select_main(0);
-	};
-
-	exit(0);
-}
diff --git a/src/utils/meas_pcap2db.c b/src/utils/meas_pcap2db.c
deleted file mode 100644
index b874ac4..0000000
--- a/src/utils/meas_pcap2db.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/* read PCAP file with meas_feed data and write it to sqlite3 database */
-
-/* (C) 2012 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/>.
- *
- */
-
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/udp.h>
-
-#include <osmocom/core/socket.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/talloc.h>
-
-#include <osmocom/gsm/gsm_utils.h>
-
-#include <openbsc/meas_feed.h>
-
-#include <pcap/pcap.h>
-
-#include "meas_db.h"
-
-static struct meas_db_state *db;
-
-static void handle_mfm(const struct pcap_pkthdr *h,
-		       const struct meas_feed_meas *mfm)
-{
-	const char *scenario;
-
-	if (strlen(mfm->scenario))
-		scenario = mfm->scenario;
-	else
-		scenario = NULL;
-
-	meas_db_insert(db, mfm->imsi, mfm->name, h->ts.tv_sec,
-			scenario, &mfm->mr);
-}
-
-static void pcap_cb(u_char *user, const struct pcap_pkthdr *h,
-		   const u_char *bytes)
-{
-	const char *cur = bytes;
-	const struct iphdr *ip;
-	const struct udphdr *udp;
-	const struct meas_feed_meas *mfm;
-	uint16_t udplen;
-
-	if (h->caplen < 14+20+8)
-		return;
-
-	/* Check if there is IPv4 in the Ethernet */
-	if (cur[12] != 0x08 || cur[13] != 0x00)
-		return;
-
-	cur += 14;	/* ethernet header */
-	ip = (struct iphdr *) cur;
-
-	if (ip->version != 4)
-		return;
-	cur += ip->ihl * 4;
-
-	if (ip->protocol != IPPROTO_UDP)
-		return;
-
-	udp = (struct udphdr *) cur;
-
-	if (udp->dest != htons(8888))
-		return;
-
-	udplen = ntohs(udp->len);
-	if (udplen != sizeof(*udp) + sizeof(*mfm))
-		return;
-	cur += sizeof(*udp);
-
-	mfm = (const struct meas_feed_meas *) cur;
-
-	handle_mfm(h, mfm);
-}
-
-int main(int argc, char **argv)
-{
-	char errbuf[PCAP_ERRBUF_SIZE+1];
-	char *pcap_fname, *db_fname;
-	pcap_t *pc;
-	int rc;
-
-	if (argc < 3) {
-		fprintf(stderr, "You need to specify PCAP and database file\n");
-		exit(2);
-	}
-
-	pcap_fname = argv[1];
-	db_fname = argv[2];
-
-	pc = pcap_open_offline(pcap_fname, errbuf);
-	if (!pc) {
-		fprintf(stderr, "Cannot open %s: %s\n", pcap_fname, errbuf);
-		exit(1);
-	}
-
-	db = meas_db_open(NULL, db_fname);
-	if (!db)
-		exit(0);
-
-	rc = meas_db_begin(db);
-	if (rc < 0) {
-		fprintf(stderr, "Error during BEGIN\n");
-		exit(1);
-	}
-
-	pcap_loop(pc, 0 , pcap_cb, NULL);
-
-	meas_db_commit(db);
-
-	exit(0);
-}
diff --git a/src/utils/meas_udp2db.c b/src/utils/meas_udp2db.c
deleted file mode 100644
index 5032d0c..0000000
--- a/src/utils/meas_udp2db.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/* liesten to meas_feed on UDP and write it to sqlite3 database */
-
-/* (C) 2012 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/>.
- *
- */
-
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-
-#include <netinet/in.h>
-
-#include <osmocom/core/socket.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/talloc.h>
-
-#include <osmocom/gsm/gsm_utils.h>
-
-#include <openbsc/meas_feed.h>
-
-#include "meas_db.h"
-
-static struct osmo_fd udp_ofd;
-static struct meas_db_state *db;
-
-static int handle_msg(struct msgb *msg)
-{
-	struct meas_feed_hdr *mfh = (struct meas_feed_hdr *) msgb_data(msg);
-	struct meas_feed_meas *mfm = (struct meas_feed_meas *) msgb_data(msg);
-	const char *scenario;
-	time_t now = time(NULL);
-
-	if (mfh->version != MEAS_FEED_VERSION)
-		return -EINVAL;
-
-	if (mfh->msg_type != MEAS_FEED_MEAS)
-		return -EINVAL;
-
-	if (strlen(mfm->scenario))
-		scenario = mfm->scenario;
-	else
-		scenario = NULL;
-
-	meas_db_insert(db, mfm->imsi, mfm->name, now,
-			scenario, &mfm->mr);
-
-	return 0;
-}
-
-static int udp_fd_cb(struct osmo_fd *ofd, unsigned int what)
-{
-	int rc;
-
-	if (what & BSC_FD_READ) {
-		struct msgb *msg = msgb_alloc(1024, "UDP Rx");
-
-		rc = read(ofd->fd, msgb_data(msg), msgb_tailroom(msg));
-		if (rc < 0)
-			return rc;
-		msgb_put(msg, rc);
-		handle_msg(msg);
-		msgb_free(msg);
-	}
-
-	return 0;
-}
-
-int main(int argc, char **argv)
-{
-	char *db_fname;
-	int rc;
-
-	msgb_talloc_ctx_init(NULL, 0);
-
-	if (argc < 2) {
-		fprintf(stderr, "You have to specify the database file name\n");
-		exit(2);
-	}
-
-	db_fname = argv[1];
-
-	udp_ofd.cb = udp_fd_cb;
-	rc =  osmo_sock_init_ofd(&udp_ofd, AF_INET, SOCK_DGRAM,
-			 	 IPPROTO_UDP, NULL, 8888, OSMO_SOCK_F_BIND);
-	if (rc < 0) {
-		fprintf(stderr, "Unable to create UDP listen socket\n");
-		exit(1);
-	}
-
-	db = meas_db_open(NULL, db_fname);
-	if (!db) {
-		fprintf(stderr, "Unable to open database\n");
-		exit(1);
-	}
-
-	/* FIXME: timer-based BEGIN/COMMIT */
-
-	while (1) {
-		osmo_select_main(0);
-	};
-
-	meas_db_close(db);
-
-	exit(0);
-}
-
diff --git a/src/utils/meas_vis.c b/src/utils/meas_vis.c
deleted file mode 100644
index 77194de..0000000
--- a/src/utils/meas_vis.c
+++ /dev/null
@@ -1,310 +0,0 @@
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <netinet/in.h>
-
-#include <cdk/cdk.h>
-
-#include <osmocom/core/socket.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/talloc.h>
-
-#include <osmocom/gsm/gsm_utils.h>
-
-#include <openbsc/meas_feed.h>
-
-struct ms_state_uni {
-	CDKSLIDER *cdk;
-	CDKLABEL *cdk_label;
-
-	time_t last_update;
-	char label[32];
-	char *_lbl[1];
-};
-
-
-struct ms_state {
-	struct llist_head list;
-
-	char name[31+1];
-	char imsi[15+1];
-	struct gsm_meas_rep mr;
-
-	struct ms_state_uni ul;
-	struct ms_state_uni dl;
-};
-
-struct state {
-	struct osmo_fd udp_ofd;
-	struct llist_head ms_list;
-
-	CDKSCREEN *cdkscreen;
-	WINDOW *curses_win;
-
-	CDKLABEL *cdk_title;
-	char *title;
-
-	CDKLABEL *cdk_header;
-	char header[256];
-};
-
-static struct state g_st;
-
-struct ms_state *find_ms(const char *imsi)
-{
-	struct ms_state *ms;
-
-	llist_for_each_entry(ms, &g_st.ms_list, list) {
-		if (!strcmp(ms->imsi, imsi))
-			return ms;
-	}
-	return NULL;
-}
-
-static struct ms_state *find_alloc_ms(const char *imsi)
-{
-	struct ms_state *ms;
-
-	ms = find_ms(imsi);
-	if (!ms) {
-		ms = talloc_zero(NULL, struct ms_state);
-		osmo_strlcpy(ms->imsi, imsi, sizeof(ms->imsi));
-		ms->ul._lbl[0] = ms->ul.label;
-		ms->dl._lbl[0] = ms->dl.label;
-		llist_add_tail(&ms->list, &g_st.ms_list);
-	}
-
-	return ms;
-}
-
-static int handle_meas(struct msgb *msg)
-{
-	struct meas_feed_meas *mfm = (struct meas_feed_meas *) msgb_data(msg);
-	struct ms_state *ms = find_alloc_ms(mfm->imsi);
-	time_t now = time(NULL);
-
-	osmo_strlcpy(ms->name, mfm->name, sizeof(ms->name));
-	memcpy(&ms->mr, &mfm->mr, sizeof(ms->mr));
-	ms->ul.last_update = now;
-	if (ms->mr.flags & MEAS_REP_F_DL_VALID)
-		ms->dl.last_update = now;
-
-	/* move to head of list */
-	llist_del(&ms->list);
-	llist_add(&ms->list, &g_st.ms_list);
-
-	return 0;
-}
-
-static int handle_msg(struct msgb *msg)
-{
-	struct meas_feed_hdr *mfh = (struct meas_feed_hdr *) msgb_data(msg);
-
-	if (mfh->version != MEAS_FEED_VERSION)
-		return -EINVAL;
-
-	switch (mfh->msg_type) {
-	case MEAS_FEED_MEAS:
-		handle_meas(msg);
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int udp_fd_cb(struct osmo_fd *ofd, unsigned int what)
-{
-	int rc;
-
-	if (what & BSC_FD_READ) {
-		struct msgb *msg = msgb_alloc(1024, "UDP Rx");
-
-		rc = read(ofd->fd, msgb_data(msg), msgb_tailroom(msg));
-		if (rc < 0)
-			return rc;
-		msgb_put(msg, rc);
-		handle_msg(msg);
-		msgb_free(msg);
-	}
-
-	return 0;
-}
-
-
-static void destroy_dir(struct ms_state_uni *uni)
-{
-	if (uni->cdk) {
-		destroyCDKSlider(uni->cdk);
-		uni->cdk = NULL;
-	}
-	if (uni->cdk_label) {
-		destroyCDKLabel(uni->cdk_label);
-		uni->cdk_label = NULL;
-	}
-}
-
-#define DIR_UL	0
-#define DIR_DL	1
-static const char *dir_str[2] = {
-	[DIR_UL]	= "UL",
-	[DIR_DL]	= "DL",
-};
-
-static int colpair_by_qual(uint8_t rx_qual)
-{
-	if (rx_qual == 0)
-		return 24;
-	else if (rx_qual <= 4)
-		return 32;
-	else
-		return 16;
-}
-
-static int colpair_by_lev(int rx_lev)
-{
-	if (rx_lev < -95)
-		return 16;
-	else if (rx_lev < -80)
-		return 32;
-	else
-		return 24;
-}
-
-
-void write_uni(struct ms_state *ms, struct ms_state_uni *msu,
-		struct gsm_rx_lev_qual *lq, int dir, int row)
-{
-
-	char label[128];
-	time_t now = time(NULL);
-	int qual_col = colpair_by_qual(lq->rx_qual);
-	int lev_col = colpair_by_lev(rxlev2dbm(lq->rx_lev));
-	int color, pwr;
-
-	if (dir == DIR_UL) {
-		pwr = ms->mr.ms_l1.pwr;
-	} else {
-		pwr = ms->mr.bs_power;
-	}
-
-	color = A_REVERSE | COLOR_PAIR(lev_col) | ' ';
-	snprintf(label, sizeof(label), "%s %s ", ms->imsi, dir_str[dir]);
-	msu->cdk = newCDKSlider(g_st.cdkscreen, 0, row, NULL, label, color,
-				  COLS-40, rxlev2dbm(lq->rx_lev), -110, -47,
-				  1, 2, FALSE, FALSE);
-	//IsVisibleObj(ms->ul.cdk) = FALSE;
-	snprintf(msu->label, sizeof(msu->label), "</%d>%1d<!%d> %3d %2u %2d %4u",
-		 qual_col, lq->rx_qual, qual_col, pwr,
-		 ms->mr.ms_l1.ta, ms->mr.ms_timing_offset,
-		 now - msu->last_update);
-	msu->cdk_label = newCDKLabel(g_st.cdkscreen, RIGHT, row,
-					msu->_lbl, 1, FALSE, FALSE);
-}
-
-static void update_sliders(void)
-{
-	int num_vis_sliders = 0;
-	struct ms_state *ms;
-#define HEADER_LINES 2
-
-	/* remove all sliders */
-	llist_for_each_entry(ms, &g_st.ms_list, list) {
-		destroy_dir(&ms->ul);
-		destroy_dir(&ms->dl);
-
-	}
-
-	llist_for_each_entry(ms, &g_st.ms_list, list) {
-		struct gsm_rx_lev_qual *lq;
-		unsigned int row = HEADER_LINES + num_vis_sliders*3;
-
-		if (ms->mr.flags & MEAS_REP_F_UL_DTX)
-			lq = &ms->mr.ul.sub;
-		else
-			lq = &ms->mr.ul.full;
-		write_uni(ms, &ms->ul, lq, DIR_UL, row);
-
-		if (ms->mr.flags & MEAS_REP_F_DL_DTX)
-			lq = &ms->mr.dl.sub;
-		else
-			lq = &ms->mr.dl.full;
-		write_uni(ms, &ms->dl, lq, DIR_DL, row+1);
-
-		num_vis_sliders++;
-		if (num_vis_sliders >= LINES/3)
-			break;
-	}
-
-	refreshCDKScreen(g_st.cdkscreen);
-
-}
-
-const struct value_string col_strs[] = {
-	{ COLOR_WHITE,	"white" },
-	{ COLOR_RED,	"red" },
-	{ COLOR_GREEN,	"green" },
-	{ COLOR_YELLOW,	"yellow" },
-	{ COLOR_BLUE,	"blue" },
-	{ COLOR_MAGENTA,"magenta" },
-	{ COLOR_CYAN,	"cyan" },
-	{ COLOR_BLACK, 	"black" },
-	{ 0, NULL }
-};
-
-int main(int argc, char **argv)
-{
-	int rc;
-	char *header[1];
-	char *title[1];
-
-	msgb_talloc_ctx_init(NULL, 0);
-
-	printf("sizeof(gsm_meas_rep)=%u\n", sizeof(struct gsm_meas_rep));
-	printf("sizeof(meas_feed_meas)=%u\n", sizeof(struct meas_feed_meas));
-
-	INIT_LLIST_HEAD(&g_st.ms_list);
-	g_st.curses_win = initscr();
-	g_st.cdkscreen = initCDKScreen(g_st.curses_win);
-	initCDKColor();
-
-	g_st.title = "OpenBSC link quality monitor";
-	title[0] = g_st.title;
-	g_st.cdk_title = newCDKLabel(g_st.cdkscreen, CENTER, 0, title, 1, FALSE, FALSE);
-
-	snprintf(g_st.header, sizeof(g_st.header), "Q Pwr TA TO Time");
-	header[0] = g_st.header;
-	g_st.cdk_header = newCDKLabel(g_st.cdkscreen, RIGHT, 1, header, 1, FALSE, FALSE);
-
-#if 0
-	int i;
-	for (i = 0; i < 64; i++) {
-		short f, b;
-		pair_content(i, &f, &b);
-		attron(COLOR_PAIR(i));
-		printw("%u: %u (%s) ", i, f, get_value_string(col_strs, f));
-		printw("%u (%s)\n\r", b, get_value_string(col_strs, b));
-	}
-	refresh();
-	getch();
-	exit(0);
-#endif
-
-	g_st.udp_ofd.cb = udp_fd_cb;
-	rc =  osmo_sock_init_ofd(&g_st.udp_ofd, AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 8888, OSMO_SOCK_F_BIND);
-	if (rc < 0)
-		exit(1);
-
-	while (1) {
-		osmo_select_main(0);
-		update_sliders();
-	};
-
-	exit(0);
-}
diff --git a/src/utils/smpp_mirror.c b/src/utils/smpp_mirror.c
deleted file mode 100644
index c570505..0000000
--- a/src/utils/smpp_mirror.c
+++ /dev/null
@@ -1,359 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <string.h>
-
-#include <netinet/in.h>
-
-#include <smpp34.h>
-#include <smpp34_structs.h>
-#include <smpp34_params.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/socket.h>
-#include <osmocom/core/write_queue.h>
-
-#include <openbsc/debug.h>
-
-/* FIXME: merge with smpp_smsc.c */
-#define SMPP_SYS_ID_LEN	16
-enum esme_read_state {
-	READ_ST_IN_LEN = 0,
-	READ_ST_IN_MSG = 1,
-};
-/* FIXME: merge with smpp_smsc.c */
-
-struct esme {
-	struct osmo_fd ofd;
-
-	uint32_t own_seq_nr;
-
-	struct osmo_wqueue wqueue;
-	enum esme_read_state read_state;
-	uint32_t read_len;
-	uint32_t read_idx;
-	struct msgb *read_msg;
-
-	uint8_t smpp_version;
-	char system_id[SMPP_SYS_ID_LEN+1];
-	char password[SMPP_SYS_ID_LEN+1];
-};
-
-/* FIXME: merge with smpp_smsc.c */
-#define SMPP34_UNPACK(rc, type, str, data, len)		\
-	memset(str, 0, sizeof(*str));			\
-	rc = smpp34_unpack(type, str, data, len)
-#define INIT_RESP(type, resp, req) 		{ \
-	memset((resp), 0, sizeof(*(resp)));	  \
-	(resp)->command_length	= 0;		  \
-	(resp)->command_id	= type;		  \
-	(resp)->command_status	= ESME_ROK;	  \
-	(resp)->sequence_number	= (req)->sequence_number;	\
-}
-#define PACK_AND_SEND(esme, ptr)	pack_and_send(esme, (ptr)->command_id, ptr)
-static inline uint32_t smpp_msgb_cmdid(struct msgb *msg)
-{
-	uint8_t *tmp = msgb_data(msg) + 4;
-	return ntohl(*(uint32_t *)tmp);
-}
-static uint32_t esme_inc_seq_nr(struct esme *esme)
-{
-	esme->own_seq_nr++;
-	if (esme->own_seq_nr > 0x7fffffff)
-		esme->own_seq_nr = 1;
-
-	return esme->own_seq_nr;
-}
-static int pack_and_send(struct esme *esme, uint32_t type, void *ptr)
-{
-	struct msgb *msg = msgb_alloc(4096, "SMPP_Tx");
-	int rc, rlen;
-	if (!msg)
-		return -ENOMEM;
-
-	rc = smpp34_pack(type, msg->tail, msgb_tailroom(msg), &rlen, ptr);
-	if (rc != 0) {
-		LOGP(DSMPP, LOGL_ERROR, "[%s] Error during smpp34_pack(): %s\n",
-		     esme->system_id, smpp34_strerror);
-		msgb_free(msg);
-		return -EINVAL;
-	}
-	msgb_put(msg, rlen);
-
-	if (osmo_wqueue_enqueue(&esme->wqueue, msg) != 0) {
-		LOGP(DSMPP, LOGL_ERROR, "[%s] Write queue full. Dropping message\n",
-		     esme->system_id);
-		msgb_free(msg);
-		return -EAGAIN;
-	}
-	return 0;
-}
-/* FIXME: merge with smpp_smsc.c */
-
-static struct tlv_t *find_tlv(struct tlv_t *head, uint16_t tag)
-{
-	struct tlv_t *t;
-
-	for (t = head; t != NULL; t = t->next) {
-		if (t->tag == tag)
-			return t;
-	}
-	return NULL;
-}
-
-static int smpp_handle_deliver(struct esme *esme, struct msgb *msg)
-{
-	struct deliver_sm_t deliver;
-	struct deliver_sm_resp_t deliver_r;
-	struct submit_sm_t submit;
-	tlv_t *t;
-	int rc;
-
-	memset(&deliver, 0, sizeof(deliver));
-	SMPP34_UNPACK(rc, DELIVER_SM, &deliver, msgb_data(msg), msgb_length(msg));
-	if (rc < 0)
-		return rc;
-
-	INIT_RESP(DELIVER_SM_RESP, &deliver_r, &deliver);
-
-	PACK_AND_SEND(esme, &deliver_r);
-
-	memset(&submit, 0, sizeof(submit));
-	submit.command_id = SUBMIT_SM;
-	submit.command_status = ESME_ROK;
-	submit.sequence_number = esme_inc_seq_nr(esme);
-
-	submit.dest_addr_ton =  deliver.source_addr_ton;
-	submit.dest_addr_npi =  deliver.source_addr_npi;
-	memcpy(submit.destination_addr, deliver.source_addr,
-		OSMO_MIN(sizeof(submit.destination_addr),
-			 sizeof(deliver.source_addr)));
-
-	submit.source_addr_ton = deliver.dest_addr_ton;
-	submit.source_addr_npi = deliver.dest_addr_npi;
-	memcpy(submit.source_addr, deliver.destination_addr,
-		OSMO_MIN(sizeof(submit.source_addr),
-			 sizeof(deliver.destination_addr)));
-
-	/* Mirror delivery receipts as a delivery acknowledgements. */
-	if (deliver.esm_class == 0x04) {
-		LOGP(DSMPP, LOGL_DEBUG, "%s\n", deliver.short_message);
-		submit.esm_class = 0x08;
-	} else {
-		submit.esm_class = deliver.esm_class;
-	}
-
-	submit.registered_delivery = deliver.registered_delivery;
-	submit.protocol_id = deliver.protocol_id;
-	submit.priority_flag = deliver.priority_flag;
-	memcpy(submit.schedule_delivery_time, deliver.schedule_delivery_time,
-	       OSMO_MIN(sizeof(submit.schedule_delivery_time),
-		        sizeof(deliver.schedule_delivery_time)));
-	memcpy(submit.validity_period, deliver.validity_period,
-		OSMO_MIN(sizeof(submit.validity_period),
-			 sizeof(deliver.validity_period)));
-	submit.registered_delivery = deliver.registered_delivery;
-	submit.replace_if_present_flag = deliver.replace_if_present_flag;
-	submit.data_coding = deliver.data_coding;
-	submit.sm_default_msg_id = deliver.sm_default_msg_id;
-	submit.sm_length = deliver.sm_length;
-	memcpy(submit.short_message, deliver.short_message,
-		OSMO_MIN(sizeof(submit.short_message),
-			 sizeof(deliver.short_message)));
-
-	/* FIXME: More TLV? */
-	t = find_tlv(deliver.tlv, TLVID_user_message_reference);
-	if (t) {
-		tlv_t tlv;
-
-		memset(&tlv, 0, sizeof(tlv));
-		tlv.tag = TLVID_user_message_reference;
-		tlv.length = 2;
-		tlv.value.val16 = t->value.val16;
-		build_tlv(&submit.tlv, &tlv);
-	}
-
-	return PACK_AND_SEND(esme, &submit);
-}
-
-static int bind_transceiver(struct esme *esme)
-{
-	struct bind_transceiver_t bind;
-
-	memset(&bind, 0, sizeof(bind));
-	bind.command_id = BIND_TRANSCEIVER;
-	bind.sequence_number = esme_inc_seq_nr(esme);
-	snprintf((char *)bind.system_id, sizeof(bind.system_id), "%s", esme->system_id);
-	snprintf((char *)bind.password, sizeof(bind.password), "%s", esme->password);
-	snprintf((char *)bind.system_type, sizeof(bind.system_type), "mirror");
-	bind.interface_version = esme->smpp_version;
-
-	return PACK_AND_SEND(esme, &bind);
-}
-
-static int smpp_pdu_rx(struct esme *esme, struct msgb *msg)
-{
-	uint32_t cmd_id = smpp_msgb_cmdid(msg);
-	int rc;
-
-	switch (cmd_id) {
-	case DELIVER_SM:
-		rc = smpp_handle_deliver(esme, msg);
-		break;
-	default:
-		LOGP(DSMPP, LOGL_NOTICE, "unhandled case %d\n", cmd_id);
-		rc = 0;
-		break;
-	}
-
-	return rc;
-}
-
-/* FIXME: merge with smpp_smsc.c */
-static int esme_read_cb(struct osmo_fd *ofd)
-{
-	struct esme *esme = ofd->data;
-	uint32_t len;
-	uint8_t *lenptr = (uint8_t *) &len;
-	uint8_t *cur;
-	struct msgb *msg;
-	int rdlen;
-	int rc;
-
-	switch (esme->read_state) {
-	case READ_ST_IN_LEN:
-		rdlen = sizeof(uint32_t) - esme->read_idx;
-		rc = read(ofd->fd, lenptr + esme->read_idx, rdlen);
-		if (rc < 0) {
-			LOGP(DSMPP, LOGL_ERROR, "[%s] read returned %d\n",
-			     esme->system_id, rc);
-		} else if (rc == 0) {
-			goto dead_socket;
-		} else
-			esme->read_idx += rc;
-		if (esme->read_idx >= sizeof(uint32_t)) {
-			esme->read_len = ntohl(len);
-			msg = msgb_alloc(esme->read_len, "SMPP Rx");
-			if (!msg)
-				return -ENOMEM;
-			esme->read_msg = msg;
-			cur = msgb_put(msg, sizeof(uint32_t));
-			memcpy(cur, lenptr, sizeof(uint32_t));
-			esme->read_state = READ_ST_IN_MSG;
-			esme->read_idx = sizeof(uint32_t);
-		}
-		break;
-	case READ_ST_IN_MSG:
-		msg = esme->read_msg;
-		rdlen = esme->read_len - esme->read_idx;
-		rc = read(ofd->fd, msg->tail, OSMO_MIN(rdlen, msgb_tailroom(msg)));
-		if (rc < 0) {
-			LOGP(DSMPP, LOGL_ERROR, "[%s] read returned %d\n",
-				esme->system_id, rc);
-		} else if (rc == 0) {
-			goto dead_socket;
-		} else {
-			esme->read_idx += rc;
-			msgb_put(msg, rc);
-		}
-
-		if (esme->read_idx >= esme->read_len) {
-			rc = smpp_pdu_rx(esme, esme->read_msg);
-			esme->read_msg = NULL;
-			esme->read_idx = 0;
-			esme->read_len = 0;
-			esme->read_state = READ_ST_IN_LEN;
-		}
-		break;
-	}
-
-	return 0;
-dead_socket:
-	msgb_free(esme->read_msg);
-	osmo_fd_unregister(&esme->wqueue.bfd);
-	close(esme->wqueue.bfd.fd);
-	esme->wqueue.bfd.fd = -1;
-	exit(2342);
-
-	return 0;
-}
-
-static int esme_write_cb(struct osmo_fd *ofd, struct msgb *msg)
-{
-	struct esme *esme = ofd->data;
-	int rc;
-
-	rc = write(ofd->fd, msgb_data(msg), msgb_length(msg));
-	if (rc == 0) {
-		osmo_fd_unregister(&esme->wqueue.bfd);
-		close(esme->wqueue.bfd.fd);
-		esme->wqueue.bfd.fd = -1;
-		exit(99);
-	} else if (rc < msgb_length(msg)) {
-		LOGP(DSMPP, LOGL_ERROR, "[%s] Short write\n", esme->system_id);
-		return 0;
-	}
-
-	return 0;
-}
-
-static int smpp_esme_init(struct esme *esme, const char *host, uint16_t port)
-{
-	int rc;
-
-	if (port == 0)
-		port = 2775;
-
-	esme->own_seq_nr = rand();
-	esme_inc_seq_nr(esme);
-	osmo_wqueue_init(&esme->wqueue, 10);
-	esme->wqueue.bfd.data = esme;
-	esme->wqueue.read_cb = esme_read_cb;
-	esme->wqueue.write_cb = esme_write_cb;
-
-	rc = osmo_sock_init_ofd(&esme->wqueue.bfd, AF_UNSPEC, SOCK_STREAM,
-				IPPROTO_TCP, host, port, OSMO_SOCK_F_CONNECT);
-	if (rc < 0)
-		return rc;
-
-	return bind_transceiver(esme);
-}
-
-
-int main(int argc, char **argv)
-{
-	struct esme esme;
-	char *host = "localhost";
-	int port = 0;
-	int rc;
-
-	msgb_talloc_ctx_init(NULL, 0);
-
-	memset(&esme, 0, sizeof(esme));
-
-	osmo_init_logging(&log_info);
-
-	snprintf((char *) esme.system_id, sizeof(esme.system_id), "mirror");
-	snprintf((char *) esme.password, sizeof(esme.password), "mirror");
-	esme.smpp_version = 0x34;
-
-	if (argc >= 2)
-		host = argv[1];
-	if (argc >= 3)
-		port = atoi(argv[2]);
-
-	rc = smpp_esme_init(&esme, host, port);
-	if (rc < 0)
-		exit(1);
-
-	while (1) {
-		osmo_select_main(0);
-	}
-
-	exit(0);
-}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 38890a8..4a1f27a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,50 +1,7 @@
 SUBDIRS = \
-	gsm0408 \
-	channel \
-	mgcp \
-	gprs \
-	abis \
-	gbproxy \
-	trau \
-	subscr \
-	nanobts_omlattr \
-	sms_queue \
-	msc_vlr \
+	legacy_mgcp \
 	$(NULL)
 
-if BUILD_NAT
-SUBDIRS += \
-	bsc-nat \
-	bsc-nat-trie \
-	$(NULL)
-endif
-if BUILD_BSC
-SUBDIRS += \
-	bsc \
-	$(NULL)
-endif
-if BUILD_SMPP
-SUBDIRS += \
-	smpp \
-	$(NULL)
-endif
-if HAVE_LIBGTP
-SUBDIRS += \
-	gtphub \
-	$(NULL)
-
-if HAVE_LIBCARES
-SUBDIRS += \
-	sgsn \
-	oap \
-	xid \
-	sndcp_xid \
-	slhc \
-	v42bis \
-	$(NULL)
-endif
-endif
-
 # The `:;' works around a Bash 3.2 bug when the output is not writeable.
 $(srcdir)/package.m4: $(top_srcdir)/configure.ac
 	:;{ \
@@ -69,7 +26,6 @@
 	$(TESTSUITE) \
 	vty_test_runner.py \
 	ctrl_test_runner.py \
-	smpp_test_runner.py \
 	$(NULL)
 
 TESTSUITE = $(srcdir)/testsuite
@@ -84,10 +40,6 @@
 	osmotestconfig.py -p $(abs_top_srcdir) -w $(abs_top_builddir) -v
 	$(PYTHON) $(srcdir)/vty_test_runner.py -w $(abs_top_builddir) -v
 	$(PYTHON) $(srcdir)/ctrl_test_runner.py -w $(abs_top_builddir) -v
-if BUILD_SMPP
-	$(PYTHON) $(srcdir)/smpp_test_runner.py -w $(abs_top_builddir) -v
-endif
-	rm -f $(top_builddir)/sms.db $(top_builddir)/gsn_restart $(top_builddir)/gtphub_restart_count
 else
 python-tests: $(BUILT_SOURCES)
 	echo "Not running python-based tests (determined at configure-time)"
diff --git a/tests/abis/Makefile.am b/tests/abis/Makefile.am
deleted file mode 100644
index 1c5dede..0000000
--- a/tests/abis/Makefile.am
+++ /dev/null
@@ -1,34 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	-ggdb3 \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(NULL)
-
-EXTRA_DIST = \
-	abis_test.ok \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	abis_test \
-	$(NULL)
-
-abis_test_SOURCES = \
-	abis_test.c \
-	$(NULL)
-
-abis_test_LDADD = \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(NULL)
diff --git a/tests/abis/abis_test.c b/tests/abis/abis_test.c
deleted file mode 100644
index 591f835..0000000
--- a/tests/abis/abis_test.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * (C) 2012 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 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/>.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/gsm/protocol/gsm_12_21.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/debug.h>
-
-static const uint8_t load_config[] = {
-	0x42, 0x12, 0x00, 0x08, 0x31, 0x36, 0x38, 0x64,
-	0x34, 0x37, 0x32, 0x00, 0x13, 0x00, 0x0b, 0x76,
-	0x32, 0x30, 0x30, 0x62, 0x31, 0x34, 0x33, 0x64,
-	0x30, 0x00, 0x42, 0x12, 0x00, 0x08, 0x31, 0x36,
-	0x38, 0x64, 0x34, 0x37, 0x32, 0x00, 0x13, 0x00,
-	0x0b, 0x76, 0x32, 0x30, 0x30, 0x62, 0x31, 0x34,
-	0x33, 0x64, 0x31, 0x00
-};
-
-static void test_sw_selection(void)
-{
-	struct abis_nm_sw_desc descr[8], tmp;
-	uint16_t len0, len1;
-	int rc, pos;
-
-	rc = abis_nm_get_sw_conf(load_config, ARRAY_SIZE(load_config),
-				&descr[0], ARRAY_SIZE(descr));
-	if (rc != 2) {
-		printf("%s(): FAILED to parse the File Id/File version: %d\n",
-		       __func__, rc);
-		abort();
-	}
-
-	len0 = abis_nm_sw_desc_len(&descr[0], true);
-	printf("len: %u\n", len0);
-	printf("file_id:  %s\n", osmo_hexdump(descr[0].file_id, descr[0].file_id_len));
-	printf("file_ver: %s\n", osmo_hexdump(descr[0].file_version, descr[0].file_version_len));
-
-	len1 = abis_nm_sw_desc_len(&descr[1], true);
-	printf("len: %u\n", len1);
-	printf("file_id:  %s\n", osmo_hexdump(descr[1].file_id, descr[1].file_id_len));
-	printf("file_ver: %s\n", osmo_hexdump(descr[1].file_version, descr[1].file_version_len));
-
-	/* start */
-	pos = abis_nm_select_newest_sw(descr, rc);
-	if (pos != 1) {
-		printf("Selected the wrong version: %d\n", pos);
-		abort();
-	}
-	printf("SELECTED: %d\n", pos);
-
-	/* shuffle */
-	tmp = descr[0];
-	descr[0] = descr[1];
-	descr[1] = tmp;
-	pos = abis_nm_select_newest_sw(descr, rc);
-	if (pos != 0) {
-		printf("Selected the wrong version: %d\n", pos);
-		abort();
-	}
-	printf("SELECTED: %d\n", pos);
-	printf("%s(): OK\n", __func__);
-}
-
-int main(int argc, char **argv)
-{
-	osmo_init_logging(&log_info);
-
-	test_sw_selection();
-
-	return EXIT_SUCCESS;
-}
diff --git a/tests/abis/abis_test.ok b/tests/abis/abis_test.ok
deleted file mode 100644
index 8418cad..0000000
--- a/tests/abis/abis_test.ok
+++ /dev/null
@@ -1,9 +0,0 @@
-len: 26
-file_id:  31 36 38 64 34 37 32 00 
-file_ver: 76 32 30 30 62 31 34 33 64 30 00 
-len: 26
-file_id:  31 36 38 64 34 37 32 00 
-file_ver: 76 32 30 30 62 31 34 33 64 31 00 
-SELECTED: 1
-SELECTED: 0
-test_sw_selection(): OK
diff --git a/tests/bsc-nat-trie/Makefile.am b/tests/bsc-nat-trie/Makefile.am
deleted file mode 100644
index cf8ebaf..0000000
--- a/tests/bsc-nat-trie/Makefile.am
+++ /dev/null
@@ -1,17 +0,0 @@
-AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
-AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(COVERAGE_LDFLAGS)
-
-EXTRA_DIST = bsc_nat_trie_test.ok prefixes.csv
-
-noinst_PROGRAMS = bsc_nat_trie_test
-
-bsc_nat_trie_test_SOURCES = bsc_nat_trie_test.c \
-			$(top_srcdir)/src/osmo-bsc_nat/bsc_nat_rewrite_trie.c
-bsc_nat_trie_test_LDADD = $(top_builddir)/src/libbsc/libbsc.a \
-			$(top_builddir)/src/libmgcp/libmgcp.a \
-			$(top_builddir)/src/libtrau/libtrau.a \
-			$(top_builddir)/src/libcommon/libcommon.a \
-			$(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -lrt \
-			$(LIBOSMOSCCP_LIBS) $(LIBOSMOVTY_LIBS) \
-			$(LIBOSMOABIS_LIBS)
diff --git a/tests/bsc-nat-trie/bsc_nat_trie_test.c b/tests/bsc-nat-trie/bsc_nat_trie_test.c
deleted file mode 100644
index 4b4df2f..0000000
--- a/tests/bsc-nat-trie/bsc_nat_trie_test.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * (C) 2013 by On-Waves
- * (C) 2013 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/>.
- *
- */
-
-#include <openbsc/nat_rewrite_trie.h>
-#include <openbsc/debug.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/backtrace.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-
-#include <string.h>
-
-int main(int argc, char **argv)
-{
-	struct nat_rewrite *trie;
-
-	osmo_init_logging(&log_info);
-
-	printf("Testing the trie\n");
-
-	trie = nat_rewrite_parse(NULL, "prefixes.csv");
-	OSMO_ASSERT(trie);
-
-	/* verify that it has been parsed */
-	OSMO_ASSERT(trie->prefixes == 17);
-	printf("Dumping the internal trie\n");
-	nat_rewrite_dump(trie);
-
-	/* now do the matching... */
-	OSMO_ASSERT(!nat_rewrite_lookup(trie, ""));
-	OSMO_ASSERT(!nat_rewrite_lookup(trie, "2"));
-
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "1")->rewrite, "1") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "12")->rewrite, "2") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "123")->rewrite, "3") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "1234")->rewrite, "4") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "12345")->rewrite, "5") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "123456")->rewrite, "6") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "1234567")->rewrite, "7") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "12345678")->rewrite, "8") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "123456789")->rewrite, "9") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "1234567890")->rewrite, "10") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "13")->rewrite, "11") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "14")->rewrite, "12") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "15")->rewrite, "13") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "16")->rewrite, "14") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "823455")->rewrite, "15") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "82")->rewrite, "16") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "+49123445")->rewrite, "17") == 0);
-
-	/* match a prefix */
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "121")->rewrite, "2") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "1292323")->rewrite, "2") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "12345678901")->rewrite, "10") == 0);
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "160")->rewrite, "14") == 0);
-
-	OSMO_ASSERT(strcmp(nat_rewrite_lookup(trie, "12345678901123452123123")->rewrite, "10") == 0);
-
-	/* invalid input */
-	OSMO_ASSERT(!nat_rewrite_lookup(trie, "12abc"));
-
-	talloc_free(trie);
-
-	trie = nat_rewrite_parse(NULL, "does_not_exist.csv");
-	OSMO_ASSERT(!trie);
-
-	printf("Done with the tests.\n");
-	return 0;
-}
diff --git a/tests/bsc-nat-trie/bsc_nat_trie_test.ok b/tests/bsc-nat-trie/bsc_nat_trie_test.ok
deleted file mode 100644
index 4d4cc99..0000000
--- a/tests/bsc-nat-trie/bsc_nat_trie_test.ok
+++ /dev/null
@@ -1,20 +0,0 @@
-Testing the trie
-Dumping the internal trie
-1,1
-12,2
-123,3
-1234,4
-12345,5
-123456,6
-1234567,7
-12345678,8
-123456789,9
-1234567890,10
-13,11
-14,12
-15,13
-16,14
-82,16
-823455,15
-+49123,17
-Done with the tests.
diff --git a/tests/bsc-nat-trie/prefixes.csv b/tests/bsc-nat-trie/prefixes.csv
deleted file mode 100644
index 35485b1..0000000
--- a/tests/bsc-nat-trie/prefixes.csv
+++ /dev/null
@@ -1,25 +0,0 @@
-1,1
-12,2
-123,3
-1234,4
-12345,5
-123456,6
-1234567,7
-12345678,8
-123456789,9
-1234567890,10
-13,11
-14,12
-15,13
-16,14
-823455,15
-82,16
-+49123,17
-1ABC,18
-12345678901234567890,19
-,20
-14A,21
-124,324324324234
-1234567890,10
-no line
-99,
diff --git a/tests/bsc-nat/Makefile.am b/tests/bsc-nat/Makefile.am
deleted file mode 100644
index 40be3a3..0000000
--- a/tests/bsc-nat/Makefile.am
+++ /dev/null
@@ -1,59 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	-ggdb3 \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOCTRL_LIBS) \
-	$(LIBOSMOSCCP_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(LIBOSMONETIF_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(COVERAGE_LDFLAGS) \
-	$(NULL)
-
-EXTRA_DIST = \
-	bsc_nat_test.ok \
-	bsc_data.c \
-	barr.cfg \
-	barr_dup.cfg \
-	prefixes.csv \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	bsc_nat_test \
-	$(NULL)
-
-bsc_nat_test_SOURCES = \
-	bsc_nat_test.c \
-	$(top_srcdir)/src/osmo-bsc_nat/bsc_filter.c \
-	$(top_srcdir)/src/osmo-bsc_nat/bsc_sccp.c \
-	$(top_srcdir)/src/osmo-bsc_nat/bsc_nat_utils.c \
-	$(top_srcdir)/src/osmo-bsc_nat/bsc_nat_rewrite.c \
-	$(top_srcdir)/src/osmo-bsc_nat/bsc_nat_rewrite_trie.c \
-	$(top_srcdir)/src/osmo-bsc_nat/bsc_mgcp_utils.c \
-	$(top_srcdir)/src/osmo-bsc_nat/bsc_nat_filter.c
-
-bsc_nat_test_LDADD = \
-	$(top_builddir)/src/libfilter/libfilter.a \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
-	$(top_builddir)/src/libmgcp/libmgcp.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOSCCP_LIBS) \
-	$(LIBOSMOVTY_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	$(LIBOSMONETIF_LIBS) \
-	$(LIBOSMOCTRL_LIBS) \
-	-lrt \
-	$(NULL)
diff --git a/tests/bsc-nat/barr.cfg b/tests/bsc-nat/barr.cfg
deleted file mode 100644
index a9a4a2b..0000000
--- a/tests/bsc-nat/barr.cfg
+++ /dev/null
@@ -1,12 +0,0 @@
-12123124:3:2:
-12123123:3:1:
-12123128:3:6:
-12123125:3:3:
-12123127:3:5:
-12123126:3:4:
-12123120:3:4:
-12123119:3:4:
-12123118:3:4:
-12123117:3:4:
-12123116:3:4:
-12123115:3:4:
diff --git a/tests/bsc-nat/barr_dup.cfg b/tests/bsc-nat/barr_dup.cfg
deleted file mode 100644
index ea94631..0000000
--- a/tests/bsc-nat/barr_dup.cfg
+++ /dev/null
@@ -1,2 +0,0 @@
-12123124:3:2:
-12123124:3:2:
diff --git a/tests/bsc-nat/bsc_data.c b/tests/bsc-nat/bsc_data.c
deleted file mode 100644
index 3a9f1da..0000000
--- a/tests/bsc-nat/bsc_data.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/* test data */
-
-/* BSC -> MSC, CR */
-static const uint8_t bsc_cr[] = {
-0x00, 0x2e, 0xfd,
-0x01, 0x00, 0x00, 0x15, 0x02, 0x02, 0x04, 0x02,
-0x42, 0xfe, 0x0f, 0x21, 0x00, 0x1f, 0x57, 0x05,
-0x08, 0x00, 0x72, 0xf4, 0x80, 0x20, 0x1c, 0xc3,
-0x51, 0x17, 0x12, 0x05, 0x08, 0x20, 0x72, 0xf4,
-0x90, 0x20, 0x1d, 0x50, 0x08, 0x29, 0x47, 0x80,
-0x00, 0x00, 0x00, 0x00, 0x80, 0x00 };
-
-static const uint8_t bsc_cr_patched[] = {
-0x00, 0x2e, 0xfd,
-0x01, 0x00, 0x00, 0x05, 0x02, 0x02, 0x04, 0x02,
-0x42, 0xfe, 0x0f, 0x21, 0x00, 0x1f, 0x57, 0x05,
-0x08, 0x00, 0x72, 0xf4, 0x80, 0x20, 0x1c, 0xc3,
-0x51, 0x17, 0x12, 0x05, 0x08, 0x20, 0x72, 0xf4,
-0x90, 0x20, 0x1d, 0x50, 0x08, 0x29, 0x47, 0x80,
-0x00, 0x00, 0x00, 0x00, 0x80, 0x00 };
-
-/* CC, MSC -> BSC */
-static const uint8_t msc_cc[] = {
-0x00, 0x0a, 0xfd,
-0x02, 0x00, 0x00, 0x05, 0x01, 0x1f, 0xe4, 0x02,
-0x01, 0x00 };
-static const uint8_t msc_cc_patched[] = {
-0x00, 0x0a, 0xfd,
-0x02, 0x00, 0x00, 0x15, 0x01, 0x1f, 0xe4, 0x02,
-0x01, 0x00 };
-
-/* Classmark, BSC -> MSC */
-static const uint8_t bsc_dtap[] = {
-0x00, 0x17, 0xfd,
-0x06, 0x01, 0x1f, 0xe4, 0x00, 0x01, 0x10, 0x00,
-0x0e, 0x54, 0x12, 0x03, 0x50, 0x18, 0x93, 0x13,
-0x06, 0x60, 0x14, 0x45, 0x00, 0x81, 0x00 };
-
-static const uint8_t bsc_dtap_patched[] = {
-0x00, 0x17, 0xfd,
-0x06, 0x01, 0x1f, 0xe4, 0x00, 0x01, 0x10, 0x00,
-0x0e, 0x54, 0x12, 0x03, 0x50, 0x18, 0x93, 0x13,
-0x06, 0x60, 0x14, 0x45, 0x00, 0x81, 0x00 };
-
-/* Clear command, MSC -> BSC */
-static const uint8_t msc_dtap[] = {
-0x00, 0x0d, 0xfd,
-0x06, 0x00, 0x00, 0x05, 0x00, 0x01, 0x06, 0x00,
-0x04, 0x20, 0x04, 0x01, 0x09 };
-static const uint8_t msc_dtap_patched[] = {
-0x00, 0x0d, 0xfd,
-0x06, 0x00, 0x00, 0x15, 0x00, 0x01, 0x06, 0x00,
-0x04, 0x20, 0x04, 0x01, 0x09 };
-
-/*RLSD, MSC -> BSC */
-static const uint8_t msc_rlsd[] = {
-0x00, 0x0a, 0xfd,
-0x04, 0x00, 0x00, 0x05, 0x01, 0x1f, 0xe4, 0x00,
-0x01, 0x00 };
-static const uint8_t msc_rlsd_patched[] = {
-0x00, 0x0a, 0xfd,
-0x04, 0x00, 0x00, 0x15, 0x01, 0x1f, 0xe4, 0x00,
-0x01, 0x00 };
-
-/* RLC, BSC -> MSC */
-static const uint8_t bsc_rlc[] = {
-0x00, 0x07, 0xfd,
-0x05, 0x01, 0x1f, 0xe4, 0x00, 0x00, 0x15 };
-
-static const uint8_t bsc_rlc_patched[] = {
-0x00, 0x07, 0xfd,
-0x05, 0x01, 0x1f, 0xe4, 0x00, 0x00, 0x05 };
-
-
-/* a paging command */
-static const uint8_t paging_by_lac_cmd[] = {
-0x00, 0x22, 0xfd, 0x09,
-0x00, 0x03, 0x07, 0x0b, 0x04, 0x43, 0x02, 0x00,
-0xfe, 0x04, 0x43, 0x5c, 0x00, 0xfe, 0x12, 0x00,
-0x10, 0x52, 0x08, 0x08, 0x29, 0x47, 0x10, 0x02,
-0x01, 0x50, 0x02, 0x30, 0x1a, 0x03, 0x05, 0x20,
-0x15 };
-
-/* an assignment command */
-static const uint8_t ass_cmd[] = {
-0x00, 0x12, 0xfd, 0x06,
-0x00, 0x00, 0x49, 0x00, 0x01, 0x0b, 0x00, 0x09,
-0x01, 0x0b, 0x03, 0x01, 0x0a, 0x11, 0x01, 0x00,
-0x01 };
-
-/* identity response */
-static const uint8_t id_resp[] = {
-0x00, 0x15, 0xfd, 0x06, 0x01, 0x1c, 0xdc,
-0x00, 0x01, 0x0e, 0x01, 0x00, 0x0b, 0x05, 0x59,
-0x08, 0x29, 0x40, 0x21, 0x03, 0x07, 0x48, 0x66,
-0x31
-};
-
-/* sms code msg */
-static const uint8_t smsc_rewrite[] = {
-0x00, 0x30, 0xfd, 0x06, 0x01, 0x13, 0x1e, 0x00,
-0x01, 0x29, 0x01, 0x03, 0x26, 0x09, 0x01, 0x23,
-0x00, 0x0c, 0x00, 0x07, 0x91, 0x36, 0x19, 0x08,
-0x00, 0x10, 0x50, 0x17, 0x21, 0x0c, 0x0f, 0x81,
-0x00, 0x94, 0x51, 0x87, 0x86, 0x78, 0x46, 0xf5,
-0x00, 0x00, 0x09, 0xcc, 0xb7, 0xbd, 0x0c, 0xca,
-0xbf, 0xeb, 0x20
-};
-
-static const uint8_t smsc_rewrite_patched[] = {
-0x00, 0x31, 0xfd, 0x06, 0x01, 0x13, 0x1e, 0x00,
-0x01, 0x2a, 0x01, 0x03, 0x27, 0x09, 0x01, 0x24,
-0x00, 0x0c, 0x00, 0x08, 0x91, 0x66, 0x66, 0x66,
-0x66, 0x66, 0x66, 0xf7, 0x17, 0x01, 0x0c, 0x0f,
-0x81, 0x00, 0x94, 0x51, 0x87, 0x86, 0x78, 0x46,
-0xf5, 0x00, 0x00, 0x09, 0xcc, 0xb7, 0xbd, 0x0c,
-0xca, 0xbf, 0xeb, 0x20
-};
-
-static const uint8_t smsc_rewrite_patched_hdr[] = {
-0x00, 0x30, 0xfd, 0x06, 0x01, 0x13, 0x1e, 0x00,
-0x01, 0x29, 0x01, 0x03, 0x26, 0x09, 0x01, 0x23,
-0x00, 0x0c, 0x00, 0x07, 0x91, 0x36, 0x19, 0x08,
-0x00, 0x10, 0x50, 0x17, 0x01, 0x0c, 0x0f, 0x81,
-0x00, 0x94, 0x51, 0x87, 0x86, 0x78, 0x46, 0xf5,
-0x00, 0x00, 0x09, 0xcc, 0xb7, 0xbd, 0x0c, 0xca,
-0xbf, 0xeb, 0x20
-};
-
-static const uint8_t smsc_rewrite_num_patched[] = {
-0x00, 0x2f, 0xfd, 0x06, 0x01, 0x13, 0x1e, 0x00,
-0x01, 0x28, 0x01, 0x03, 0x25, 0x09, 0x01, 0x22,
-0x00, 0x0c, 0x00, 0x07, 0x91, 0x36, 0x19, 0x08,
-0x00, 0x10, 0x50, 0x16, 0x21, 0x0c, 0x0d, 0x91,
-      0x23, 0x51, 0x87, 0x86, 0x78, 0x46, 0xf5,
-0x00, 0x00, 0x09, 0xcc, 0xb7, 0xbd, 0x0c, 0xca,
-0xbf, 0xeb, 0x20
-};
-
-static const uint8_t smsc_rewrite_num_patched_tp_srr[] = {
-0x00, 0x2f, 0xfd, 0x06, 0x01, 0x13, 0x1e, 0x00,
-0x01, 0x28, 0x01, 0x03, 0x25, 0x09, 0x01, 0x22,
-0x00, 0x0c, 0x00, 0x07, 0x91, 0x36, 0x19, 0x08,
-0x00, 0x10, 0x50, 0x16, 0x01, 0x0c, 0x0d, 0x91,
-      0x23, 0x51, 0x87, 0x86, 0x78, 0x46, 0xf5,
-0x00, 0x00, 0x09, 0xcc, 0xb7, 0xbd, 0x0c, 0xca,
-0xbf, 0xeb, 0x20
-};
-
-/*
- * MGCP messages
- */
-
-/* nothing to patch */
-static const char crcx[] = "CRCX 23265295 8@mgw MGCP 1.0\r\nC: 394b0439fb\r\nL: p:20, a:AMR, nt:IN\r\nM: recvonly\r\n";
-static const char crcx_patched[] = "CRCX 23265295 1e@mgw MGCP 1.0\r\nC: 394b0439fb\r\nL: p:20, a:AMR, nt:IN\r\nM: recvonly\r\n";
-
-
-/* patch the ip and port */
-static const char crcx_resp[] = "200 23265295\r\nI: 1\r\n\r\nv=0\r\nc=IN IP4 172.16.18.2\r\nm=audio 4002 RTP/AVP 98 3\r\na=rtpmap:98 AMR/8000\r\n";
-static const char crcx_resp_patched[] = "200 23265295\r\nI: 1\r\n\r\nv=0\r\nc=IN IP4 10.0.0.1\r\nm=audio 999 RTP/AVP 98 3\r\na=rtpmap:98 AMR/8000\r\na=fmtp:98 mode-set=2\r\n";
-
-/* patch the ip and port */
-static const char mdcx[] = "MDCX 23330829 8@mgw MGCP 1.0\r\nC: 394b0439fb\r\nI: 1\r\nL: p:20, a:AMR, nt:IN\r\nM: recvonly\r\n\r\nv=0\r\no=- 1049380491 0 IN IP4 172.16.18.2\r\ns=-\r\nc=IN IP4 172.16.18.2\r\nt=0 0\r\nm=audio 4410 RTP/AVP 126\r\na=rtpmap:126 AMR/8000/1\r\na=fmtp:126 mode-set=2;start-mode=0\r\na=ptime:20\r\na=recvonly\r\nm=image 4412 udptl t38\r\na=T38FaxVersion:0\r\na=T38MaxBitRate:14400\r\n";
-static const char mdcx_patched[] = "MDCX 23330829 1e@mgw MGCP 1.0\r\nC: 394b0439fb\r\nI: 1\r\nL: p:20, a:AMR, nt:IN\r\nM: recvonly\r\n\r\nv=0\r\no=- 1049380491 0 IN IP4 172.16.18.2\r\ns=-\r\nc=IN IP4 10.0.0.23\r\nt=0 0\r\nm=audio 6666 RTP/AVP 126\r\na=rtpmap:126 AMR/8000/1\r\na=fmtp:126 mode-set=2;start-mode=0\r\na=ptime:20\r\na=recvonly\r\nm=image 4412 udptl t38\r\na=T38FaxVersion:0\r\na=T38MaxBitRate:14400\r\n";
-
-
-static const char mdcx_resp[] = "200 23330829\r\n\r\nv=0\r\nc=IN IP4 172.16.18.2\r\nm=audio 4002 RTP/AVP 98\r\na=rtpmap:98 AMR/8000\r\n";
-static const char mdcx_resp_patched[] = "200 23330829\r\n\r\nv=0\r\nc=IN IP4 10.0.0.23\r\nm=audio 5555 RTP/AVP 98\r\na=rtpmap:98 AMR/8000\r\na=fmtp:98 mode-set=2\r\n";
-
-/* different line ending */
-static const char mdcx_resp2[] = "200 33330829\n\nv=0\nc=IN IP4 172.16.18.2\nm=audio 4002 RTP/AVP 98\na=rtpmap:98 AMR/8000\n";
-static const char mdcx_resp_patched2[] = "200 33330829\n\nv=0\nc=IN IP4 10.0.0.23\nm=audio 5555 RTP/AVP 98\na=rtpmap:98 AMR/8000\na=fmtp:98 mode-set=2\n";
-static const char mdcx_resp_patched2_noamr[] = "200 33330829\n\nv=0\nc=IN IP4 10.0.0.23\nm=audio 5555 RTP/AVP 98\na=rtpmap:98 AMR/8000\n";
-
-struct mgcp_patch_test {
-	const char *orig;
-	const char *patch;
-	const char *ip;
-	const int port;
-	const int payload_type;
-	const int ensure_mode_set;
-};
-
-static const struct mgcp_patch_test mgcp_messages[] = {
-	{
-		.orig = crcx,
-		.patch = crcx_patched,
-		.ip = "0.0.0.0",
-		.port = 2323,
-		.ensure_mode_set = 1,
-	},
-	{
-		.orig = crcx_resp,
-		.patch = crcx_resp_patched,
-		.ip = "10.0.0.1",
-		.port = 999,
-		.payload_type = 98,
-		.ensure_mode_set = 1,
-	},
-	{
-		.orig = mdcx,
-		.patch = mdcx_patched,
-		.ip = "10.0.0.23",
-		.port = 6666,
-		.payload_type = 126,
-		.ensure_mode_set = 1,
-	},
-	{
-		.orig = mdcx_resp,
-		.patch = mdcx_resp_patched,
-		.ip = "10.0.0.23",
-		.port = 5555,
-		.payload_type = 98,
-		.ensure_mode_set = 1,
-	},
-	{
-		.orig = mdcx_resp2,
-		.patch = mdcx_resp_patched2,
-		.ip = "10.0.0.23",
-		.port = 5555,
-		.payload_type = 98,
-		.ensure_mode_set = 1,
-	},
-	{
-		.orig = mdcx_resp2,
-		.patch = mdcx_resp_patched2_noamr,
-		.ip = "10.0.0.23",
-		.port = 5555,
-		.payload_type = 98,
-		.ensure_mode_set = 0,
-	},
-};
-
-/* CC Setup messages */
-static const uint8_t cc_setup_national[] = {
-	0x00, 0x20, 0xfd, 0x06, 0x01, 0x12,
-	0x6d, 0x00, 0x01, 0x19, 0x01, 0x00, 0x16, 0x03,
-	0x05, 0x04, 0x06, 0x60, 0x04, 0x02, 0x00, 0x05,
-	0x81, 0x5e, 0x06, 0x81, 0x10, 0x27, 0x33, 0x63,
-	0x66, 0x15, 0x02, 0x11, 0x01
-};
-
-static const uint8_t cc_setup_national_patched[] = {
-	0x00, 0x21, 0xfd, 0x06, 0x01, 0x12,
-	0x6d, 0x00, 0x01, 0x1a, 0x01, 0x00, 0x17, 0x03,
-	0x05, 0x04, 0x06, 0x60, 0x04, 0x02, 0x00, 0x05,
-	0x81, 0x5e, 0x07, 0x91, 0x94, 0x71, 0x32, 0x33,
-	0x66, 0xf6, 0x15, 0x02, 0x11, 0x01
-};
-
-/* patch the phone number of cc_setup_national_patched */
-static const uint8_t cc_setup_national_patched_patched[] = {
-	0x00, 0x21, 0xfd, 0x06, 0x01, 0x12,
-	0x6d, 0x00, 0x01, 0x1a, 0x01, 0x00, 0x17, 0x03,
-	0x05, 0x04, 0x06, 0x60, 0x04, 0x02, 0x00, 0x05,
-	0x81, 0x5e, 0x07, 0x91, 0x63, 0x71, 0x32, 0x33,
-	0x66, 0xf6, 0x15, 0x02, 0x11, 0x01
-};
-
-static const uint8_t cc_setup_international[] = {
-	0x00, 0x22, 0xfd, 0x06, 0x01, 0x13,
-	0xe7, 0x00, 0x01, 0x1b, 0x01, 0x00, 0x18, 0x03,
-	0x45, 0x04, 0x06, 0x60, 0x04, 0x02, 0x00, 0x05,
-	0x81, 0x5e, 0x08, 0x81, 0x00, 0x94, 0x71, 0x33,
-	0x63, 0x66, 0x03, 0x15, 0x02, 0x11, 0x01
-};
-
-static const uint8_t cc_setup_national_again[] = {
-	0x00, 0x22, 0xfd, 0x06, 0x01, 0x12, 0x6d, 0x00,
-	0x01, 0x1b, 0x01, 0x00, 0x18, 0x03, 0x05, 0x04,
-	0x06, 0x60, 0x04, 0x02, 0x00, 0x05, 0x81, 0x5e,
-	0x08, 0x81, 0x63, 0x94, 0x71, 0x32, 0x33, 0x66,
-	0xf6, 0x15, 0x02, 0x11, 0x01
-};
diff --git a/tests/bsc-nat/bsc_nat_test.c b/tests/bsc-nat/bsc_nat_test.c
deleted file mode 100644
index 2914a01..0000000
--- a/tests/bsc-nat/bsc_nat_test.c
+++ /dev/null
@@ -1,1584 +0,0 @@
-/*
- * BSC NAT Message filtering
- *
- * (C) 2010-2013 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2013 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 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/>.
- *
- */
-
-
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/bsc_nat.h>
-#include <openbsc/bsc_nat_sccp.h>
-#include <openbsc/bsc_msg_filter.h>
-#include <openbsc/nat_rewrite_trie.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/backtrace.h>
-#include <osmocom/core/talloc.h>
-
-#include <osmocom/sccp/sccp.h>
-#include <osmocom/gsm/protocol/gsm_08_08.h>
-
-#include <stdio.h>
-
-/* test messages for ipa */
-static uint8_t ipa_id[] = {
-	0x00, 0x01, 0xfe, 0x06,
-};
-
-/* SCCP messages are below */
-static uint8_t gsm_reset[] = {
-	0x00, 0x12, 0xfd,
-	0x09, 0x00, 0x03, 0x05, 0x07, 0x02, 0x42, 0xfe,
-	0x02, 0x42, 0xfe, 0x06, 0x00, 0x04, 0x30, 0x04,
-	0x01, 0x20,
-};
-
-static const uint8_t gsm_reset_ack[] = {
-	0x00, 0x13, 0xfd,
-	0x09, 0x00, 0x03, 0x07, 0x0b, 0x04, 0x43, 0x01,
-	0x00, 0xfe, 0x04, 0x43, 0x5c, 0x00, 0xfe, 0x03,
-	0x00, 0x01, 0x31,
-};
-
-static const uint8_t gsm_paging[] = {
-	0x00, 0x20, 0xfd,
-	0x09, 0x00, 0x03, 0x07, 0x0b, 0x04, 0x43, 0x01,
-	0x00, 0xfe, 0x04, 0x43, 0x5c, 0x00, 0xfe, 0x10,
-	0x00, 0x0e, 0x52, 0x08, 0x08, 0x29, 0x47, 0x10,
-	0x02, 0x01, 0x31, 0x97, 0x61, 0x1a, 0x01, 0x06,
-};
-
-/* BSC -> MSC connection open */
-static const uint8_t bssmap_cr[] = {
-	0x00, 0x2c, 0xfd,
-	0x01, 0x01, 0x02, 0x03, 0x02, 0x02, 0x04, 0x02,
-	0x42, 0xfe, 0x0f, 0x1f, 0x00, 0x1d, 0x57, 0x05,
-	0x08, 0x00, 0x72, 0xf4, 0x80, 0x20, 0x12, 0xc3,
-	0x50, 0x17, 0x10, 0x05, 0x24, 0x11, 0x03, 0x33,
-	0x19, 0xa2, 0x08, 0x29, 0x47, 0x10, 0x02, 0x01,
-	0x31, 0x97, 0x61, 0x00
-};
-
-/* MSC -> BSC connection confirm */
-static const uint8_t bssmap_cc[] = {
-	0x00, 0x0a, 0xfd,
-	0x02, 0x01, 0x02, 0x03, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
-};
-
-/* MSC -> BSC released */
-static const uint8_t bssmap_released[] = {
-	0x00, 0x0e, 0xfd,
-	0x04, 0x00, 0x00, 0x03, 0x01, 0x02, 0x03, 0x00, 0x01, 0x0f,
-	0x02, 0x23, 0x42, 0x00,
-};
-
-/* BSC -> MSC released */
-static const uint8_t bssmap_release_complete[] = {
-	0x00, 0x07, 0xfd,
-	0x05, 0x01, 0x02, 0x03, 0x00, 0x00, 0x03
-};
-
-/* both directions IT timer */
-static const uint8_t connnection_it[] = {
-	0x00, 0x0b, 0xfd,
-	0x10, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03,
-	0x00, 0x00, 0x00, 0x00,
-};
-
-/* error in both directions */
-static const uint8_t proto_error[] = {
-	0x00, 0x05, 0xfd,
-	0x0f, 0x22, 0x33, 0x44, 0x00,
-};
-
-/* MGCP wrap... */
-static const uint8_t mgcp_msg[] = {
-	0x00, 0x03, 0xfc,
-	0x20, 0x20, 0x20,
-};
-
-/* location updating request */
-static const uint8_t bss_lu[] = {
-	0x00, 0x2e, 0xfd,
-	0x01, 0x91, 0x45, 0x14, 0x02, 0x02, 0x04, 0x02,
-	0x42, 0xfe, 0x0f, 0x21, 0x00, 0x1f, 0x57, 0x05,
-	0x08, 0x00, 0x72, 0xf4, 0x80, 0x20, 0x14, 0xc3,
-	0x50, 0x17, 0x12, 0x05, 0x08, 0x70, 0x72, 0xf4,
-	0x80, 0xff, 0xfe, 0x30, 0x08, 0x29, 0x44, 0x50,
-	0x12, 0x03, 0x24, 0x01, 0x95, 0x00
-};
-
-/* paging response */
-static const uint8_t pag_resp[] = {
-	0x00, 0x2c, 0xfd, 0x01, 0xe5, 0x68,
-	0x14, 0x02, 0x02, 0x04, 0x02, 0x42, 0xfe, 0x0f,
-	0x1f, 0x00, 0x1d, 0x57, 0x05, 0x08, 0x00, 0x72,
-	0xf4, 0x80, 0x20, 0x16, 0xc3, 0x50, 0x17, 0x10,
-	0x06, 0x27, 0x01, 0x03, 0x30, 0x18, 0x96, 0x08,
-	0x29, 0x26, 0x30, 0x32, 0x11, 0x42, 0x01, 0x19,
-	0x00
-};
-
-struct filter_result {
-	const uint8_t *data;
-	const uint16_t length;
-	const int dir;
-	const int result;
-};
-
-static const struct filter_result results[] = {
-	{
-		.data = ipa_id,
-		.length = ARRAY_SIZE(ipa_id),
-		.dir = DIR_MSC,
-		.result = 1,
-	},
-	{
-		.data = gsm_reset,
-		.length = ARRAY_SIZE(gsm_reset),
-		.dir = DIR_MSC,
-		.result = 1,
-	},
-	{
-		.data = gsm_reset_ack,
-		.length = ARRAY_SIZE(gsm_reset_ack),
-		.dir = DIR_BSC,
-		.result = 1,
-	},
-	{
-		.data = gsm_paging,
-		.length = ARRAY_SIZE(gsm_paging),
-		.dir = DIR_BSC,
-		.result = 0,
-	},
-	{
-		.data = bssmap_cr,
-		.length = ARRAY_SIZE(bssmap_cr),
-		.dir = DIR_MSC,
-		.result = 0,
-	},
-	{
-		.data = bssmap_cc,
-		.length = ARRAY_SIZE(bssmap_cc),
-		.dir = DIR_BSC,
-		.result = 0,
-	},
-	{
-		.data = bssmap_released,
-		.length = ARRAY_SIZE(bssmap_released),
-		.dir = DIR_MSC,
-		.result = 0,
-	},
-	{
-		.data = bssmap_release_complete,
-		.length = ARRAY_SIZE(bssmap_release_complete),
-		.dir = DIR_BSC,
-		.result = 0,
-	},
-	{
-		.data = mgcp_msg,
-		.length = ARRAY_SIZE(mgcp_msg),
-		.dir = DIR_MSC,
-		.result = 0,
-	},
-	{
-		.data = connnection_it,
-		.length = ARRAY_SIZE(connnection_it),
-		.dir = DIR_BSC,
-		.result = 0,
-	},
-	{
-		.data = connnection_it,
-		.length = ARRAY_SIZE(connnection_it),
-		.dir = DIR_MSC,
-		.result = 0,
-	},
-	{
-		.data = proto_error,
-		.length = ARRAY_SIZE(proto_error),
-		.dir = DIR_BSC,
-		.result = 0,
-	},
-	{
-		.data = proto_error,
-		.length = ARRAY_SIZE(proto_error),
-		.dir = DIR_MSC,
-		.result = 0,
-	},
-
-};
-
-static void test_filter(void)
-{
-	int i;
-
-
-	/* start testinh with proper messages */
-	printf("Testing BSS Filtering.\n");
-	for (i = 0; i < ARRAY_SIZE(results); ++i) {
-		int result;
-		struct bsc_nat_parsed *parsed;
-		struct msgb *msg = msgb_alloc(4096, "test-message");
-
-		printf("Going to test item: %d\n", i);
-		memcpy(msg->data, results[i].data, results[i].length);
-		msg->l2h = msgb_put(msg, results[i].length);
-
-		parsed = bsc_nat_parse(msg);
-		if (!parsed) {
-			printf("FAIL: Failed to parse the message\n");
-			continue;
-		}
-
-		result = bsc_nat_filter_ipa(results[i].dir, msg, parsed);
-		if (result != results[i].result) {
-			printf("FAIL: Not the expected result got: %d wanted: %d\n",
-				result, results[i].result);
-		}
-
-		msgb_free(msg);
-	}
-}
-
-#include "bsc_data.c"
-
-static void copy_to_msg(struct msgb *msg, const uint8_t *data, unsigned int length)
-{
-	msgb_reset(msg);
-	msg->l2h = msgb_put(msg, length);
-	memcpy(msg->l2h, data, msgb_l2len(msg));
-}
-
-static void verify_msg(struct msgb *out, const uint8_t *ref, int ref_len)
-{
-	if (out->len != ref_len) {
-		printf("FAIL: The size should match: %d vs. %d\n",
-			out->len, ref_len);
-		printf("%s\n", osmo_hexdump(out->data, out->len));
-		printf("Wanted\n");
-		printf("%s\n", osmo_hexdump(ref, ref_len));
-		abort();
-	}
-
-	if (memcmp(out->data, ref, out->len) != 0) {
-		printf("FAIL: the data should be changed.\n");
-		printf("%s\n", osmo_hexdump(out->data, out->len));
-		printf("Wanted\n");
-		printf("%s\n", osmo_hexdump(ref, ref_len));
-		abort();
-	}
-}
-
-
-#define VERIFY(con_found, con, msg, ver, str) \
-	if (!con_found) {						\
-		printf("Failed to find connection.\n");			\
-		abort();						\
-	}								\
-	if (con_found->bsc != con) {					\
-		printf("Got connection of the wrong BSC: %d\n",		\
-			con_found->bsc->cfg->nr);			\
-		abort();						\
-	}								\
-	if (memcmp(msg->data, ver, sizeof(ver)) != 0) { \
-		printf("Failed to patch the %s msg.\n", str); 		\
-		abort(); \
-	}
-
-/* test conn tracking once */
-static void test_contrack()
-{
-	struct bsc_nat *nat;
-	struct bsc_connection *con;
-	struct nat_sccp_connection *con_found;
-	struct nat_sccp_connection *rc_con;
-	struct bsc_nat_parsed *parsed;
-	struct msgb *msg;
-
-	printf("Testing connection tracking.\n");
-	nat = bsc_nat_alloc();
-	con = bsc_connection_alloc(nat);
-	con->cfg = bsc_config_alloc(nat, "foo", 0);
-	bsc_config_add_lac(con->cfg, 23);
-	bsc_config_add_lac(con->cfg, 49);
-	bsc_config_add_lac(con->cfg, 42);
-	bsc_config_del_lac(con->cfg, 49);
-	bsc_config_add_lac(con->cfg, 1111);
-	msg = msgb_alloc(4096, "test");
-
-	/* 1.) create a connection */
-	copy_to_msg(msg, bsc_cr, sizeof(bsc_cr));
-	parsed = bsc_nat_parse(msg);
-	con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
-	if (con_found != NULL) {
-		printf("Con should not exist realref(%u)\n",
-		       sccp_src_ref_to_int(&con_found->real_ref));
-		abort();
-	}
-	rc_con = create_sccp_src_ref(con, parsed);
-	if (!rc_con) {
-		printf("Failed to create a ref\n");
-		abort();
-	}
-	con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
-	if (!con_found) {
-		printf("Failed to find connection.\n");
-		abort();
-	}
-	if (con_found->bsc != con) {
-		printf("Got connection of the wrong BSC: %d\n",
-			con_found->bsc->cfg->nr);
-		abort();
-	}
-	if (con_found != rc_con) {
-		printf("Failed to find the right connection.\n");
-		abort();
-	}
-	if (memcmp(msg->data, bsc_cr_patched, sizeof(bsc_cr_patched)) != 0) {
-		printf("Failed to patch the BSC CR msg.\n");
-		abort();
-	}
-	talloc_free(parsed);
-
-	/* 2.) get the cc */
-	copy_to_msg(msg, msc_cc, sizeof(msc_cc));
-	parsed = bsc_nat_parse(msg);
-	con_found = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
-	VERIFY(con_found, con, msg, msc_cc_patched, "MSC CC");
-	if (update_sccp_src_ref(con_found, parsed) != 0) {
-		printf("Failed to update the SCCP con.\n");
-		abort();
-	}
-
-	/* 3.) send some data */
-	copy_to_msg(msg, bsc_dtap, sizeof(bsc_dtap));
-	parsed = bsc_nat_parse(msg);
-	con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
-	VERIFY(con_found, con, msg, bsc_dtap_patched, "BSC DTAP");
-
-	/* 4.) receive some data */
-	copy_to_msg(msg, msc_dtap, sizeof(msc_dtap));
-	parsed = bsc_nat_parse(msg);
-	con_found = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
-	VERIFY(con_found, con, msg, msc_dtap_patched, "MSC DTAP");
-
-	/* 5.) close the connection */
-	copy_to_msg(msg, msc_rlsd, sizeof(msc_rlsd));
-	parsed = bsc_nat_parse(msg);
-	con_found = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
-	VERIFY(con_found, con, msg, msc_rlsd_patched, "MSC RLSD");
-
-	/* 6.) confirm the connection close */
-	copy_to_msg(msg, bsc_rlc, sizeof(bsc_rlc));
-	parsed = bsc_nat_parse(msg);
-	con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
-	if (!con_found) {
-		printf("Failed to find connection.\n");
-		abort();
-	}
-	if (con_found->bsc != con) {
-		printf("Got connection of the wrong BSC: %d\n",
-			con_found->bsc->cfg->nr);
-		abort();
-	}
-	if (memcmp(msg->data, bsc_rlc_patched, sizeof(bsc_rlc_patched)) != 0) {
-		printf("Failed to patch the BSC CR msg.\n");
-		abort();
-	}
-	remove_sccp_src_ref(con, msg, parsed);
-	talloc_free(parsed);
-
-	copy_to_msg(msg, bsc_rlc, sizeof(bsc_rlc));
-	parsed = bsc_nat_parse(msg);
-	con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
-
-	/* verify that it is gone */
-	if (con_found != NULL) {
-		printf("Con should not exist real_ref(%u)\n",
-		       sccp_src_ref_to_int(&con_found->real_ref));
-		abort();
-	}
-	talloc_free(parsed);
-
-
-	bsc_config_free(con->cfg);
-	bsc_nat_free(nat);
-	msgb_free(msg);
-}
-
-static void test_paging(void)
-{
-	struct bsc_nat *nat;
-	struct bsc_connection *con;
-	struct bsc_config *cfg;
-
-	printf("Testing paging by lac.\n");
-
-	nat = bsc_nat_alloc();
-	con = bsc_connection_alloc(nat);
-	cfg = bsc_config_alloc(nat, "unknown", 0);
-	con->cfg = cfg;
-	bsc_config_add_lac(cfg, 23);
-	con->authenticated = 1;
-	llist_add(&con->list_entry, &nat->bsc_connections);
-
-	/* Test it by not finding it */
-	if (bsc_config_handles_lac(cfg, 8213) != 0) {
-		printf("Should not be handled.\n");
-		abort();
-	}
-
-	/* Test by finding it */
-	bsc_config_del_lac(cfg, 23);
-	bsc_config_add_lac(cfg, 8213);
-	if (bsc_config_handles_lac(cfg, 8213) == 0) {
-		printf("Should have found it.\n");
-		abort();
-	}
-
-	bsc_nat_free(nat);
-}
-
-static void test_mgcp_allocations(void)
-{
-#if 0
-	struct bsc_connection *bsc;
-	struct bsc_nat *nat;
-	struct nat_sccp_connection con;
-	int i, j, multiplex;
-
-	printf("Testing MGCP.\n");
-	memset(&con, 0, sizeof(con));
-
-	nat = bsc_nat_alloc();
-	nat->bsc_endpoints = talloc_zero_array(nat,
-					       struct bsc_endpoint,
-					       65);
-	nat->mgcp_cfg = mgcp_config_alloc();
-	nat->mgcp_cfg->trunk.number_endpoints = 64;
-
-	bsc = bsc_connection_alloc(nat);
-	bsc->cfg = bsc_config_alloc(nat, "foo", 0);
-	bsc->cfg->max_endpoints = 60;
-	bsc_config_add_lac(bsc->cfg, 2323);
-	bsc->last_endpoint = 0x22;
-	con.bsc = bsc;
-
-	bsc_init_endps_if_needed(bsc);
-
-	i  = 1;
-	do {
-		if (bsc_assign_endpoint(bsc, &con) != 0) {
-			printf("failed to allocate... on iteration %d\n", i);
-			break;
-		}
-		++i;
-	} while(1);
-
-	multiplex = bsc_mgcp_nr_multiplexes(bsc->cfg->max_endpoints);
-	for (i = 0; i < multiplex; ++i) {
-		for (j = 0; j < 32; ++j)
-			printf("%d", bsc->_endpoint_status[i*32 + j]);
-		printf(": %d of %d\n", i*32 + 32, 32 * 8);
-	}
-#endif
-}
-
-static void test_mgcp_ass_tracking(void)
-{
-	struct bsc_connection *bsc;
-	struct bsc_nat *nat;
-	struct nat_sccp_connection con;
-	struct bsc_nat_parsed *parsed;
-	struct msgb *msg;
-
-	printf("Testing MGCP.\n");
-	memset(&con, 0, sizeof(con));
-
-	nat = bsc_nat_alloc();
-	nat->bsc_endpoints = talloc_zero_array(nat,
-					       struct bsc_endpoint,
-					       33);
-	nat->mgcp_cfg = mgcp_config_alloc();
-	nat->mgcp_cfg->trunk.number_endpoints = 64;
-	mgcp_endpoints_allocate(&nat->mgcp_cfg->trunk);
-
-	bsc = bsc_connection_alloc(nat);
-	bsc->cfg = bsc_config_alloc(nat, "foo", 0);
-	bsc_config_add_lac(bsc->cfg, 2323);
-	bsc->last_endpoint = 0x1e;
-	con.bsc = bsc;
-
-	msg = msgb_alloc(4096, "foo");
-	copy_to_msg(msg, ass_cmd, sizeof(ass_cmd));
-	parsed = bsc_nat_parse(msg);
-
-	if (msg->l2h[16] != 0 ||
-	    msg->l2h[17] != 0x1) {
-		printf("Input is not as expected.. %s 0x%x\n",
-			osmo_hexdump(msg->l2h, msgb_l2len(msg)),
-			msg->l2h[17]);
-		abort();
-	}
-
-	if (bsc_mgcp_assign_patch(&con, msg) != 0) {
-		printf("Failed to handle assignment.\n");
-		abort();
-	}
-
-	if (con.msc_endp != 1) {
-		printf("Timeslot should be 1.\n");
-		abort();
-	}
-
-	if (con.bsc_endp != 0x1) {
-		printf("Assigned timeslot should have been 1.\n");
-		abort();
-	}
-	if (con.bsc->_endpoint_status[0x1] != 1) {
-		printf("The status on the BSC is wrong.\n");
-		abort();
-	}
-
-	int multiplex, timeslot;
-	mgcp_endpoint_to_timeslot(0x1, &multiplex, &timeslot);
-
-	uint16_t cic = htons(timeslot & 0x1f);
-	if (memcmp(&cic, &msg->l2h[16], sizeof(cic)) != 0) {
-		printf("Message was not patched properly\n");
-		printf("data cic: 0x%x %s\n", cic, osmo_hexdump(msg->l2h, msgb_l2len(msg)));
-		abort();
-	}
-
-	talloc_free(parsed);
-
-	bsc_mgcp_dlcx(&con);
-	if (con.bsc_endp != -1 || con.msc_endp != -1 ||
-	    con.bsc->_endpoint_status[1] != 0 || con.bsc->last_endpoint != 0x1) {
-		printf("Clearing should remove the mapping.\n");
-		abort();
-	}
-
-	bsc_config_free(bsc->cfg);
-	bsc_nat_free(nat);
-}
-
-/* test the code to find a given connection */
-static void test_mgcp_find(void)
-{
-	struct bsc_nat *nat;
-	struct bsc_connection *con;
-	struct nat_sccp_connection *sccp_con;
-
-	printf("Testing finding of a BSC Connection\n");
-
-	nat = bsc_nat_alloc();
-	con = bsc_connection_alloc(nat);
-	llist_add(&con->list_entry, &nat->bsc_connections);
-
-	sccp_con = talloc_zero(con, struct nat_sccp_connection);
-	sccp_con->msc_endp = 12;
-	sccp_con->bsc_endp = 12;
-	sccp_con->bsc = con;
-	llist_add(&sccp_con->list_entry, &nat->sccp_connections);
-
-	if (bsc_mgcp_find_con(nat, 11) != NULL) {
-		printf("Found the wrong connection.\n");
-		abort();
-	}
-
-	if (bsc_mgcp_find_con(nat, 12) != sccp_con) {
-		printf("Didn't find the connection\n");
-		abort();
-	}
-
-	/* free everything */
-	bsc_nat_free(nat);
-}
-
-static void test_mgcp_rewrite(void)
-{
-	int i;
-	struct msgb *output;
-	printf("Testing rewriting MGCP messages.\n");
-
-	for (i = 0; i < ARRAY_SIZE(mgcp_messages); ++i) {
-		const char *orig = mgcp_messages[i].orig;
-		const char *patc = mgcp_messages[i].patch;
-		const char *ip = mgcp_messages[i].ip;
-		const int port = mgcp_messages[i].port;
-		const int expected_payload_type = mgcp_messages[i].payload_type;
-		const int ensure_mode_set = mgcp_messages[i].ensure_mode_set;
-		int payload_type = -1;
-
-		char *input = strdup(orig);
-
-		output = bsc_mgcp_rewrite(input, strlen(input), 0x1e,
-					  ip, port, -1, &payload_type, ensure_mode_set);
-
-		if (payload_type != -1) {
-			fprintf(stderr, "Found media payload type %d in SDP data\n",
-				payload_type);
-			if (payload_type != expected_payload_type) {
-				printf("Wrong payload type %d (expected %d)\n",
-				       payload_type, expected_payload_type);
-				abort();
-			}
-		}
-
-		if (msgb_l2len(output) != strlen(patc)) {
-			printf("Wrong sizes for test: %d  %u != %zu != %zu\n", i, msgb_l2len(output), strlen(patc), strlen(orig));
-			printf("String '%s' vs '%s'\n", (const char *) output->l2h, patc);
-			abort();
-		}
-
-		if (memcmp(output->l2h, patc, msgb_l2len(output)) != 0) {
-			printf("Broken on %d msg: '%s'\n", i, (const char *) output->l2h);
-			abort();
-		}
-
-		msgb_free(output);
-		free(input);
-	}
-}
-
-static void test_mgcp_parse(void)
-{
-	int code, ci;
-	char transaction[60];
-
-	printf("Testing MGCP response parsing.\n");
-
-	if (bsc_mgcp_parse_response(crcx_resp, &code, transaction) != 0) {
-		printf("Failed to parse CRCX resp.\n");
-		abort();
-	}
-
-	if (code != 200) {
-		printf("Failed to parse the CODE properly. Got: %d\n", code);
-		abort();
-	}
-
-	if (strcmp(transaction, "23265295") != 0) {
-		printf("Failed to parse transaction id: '%s'\n", transaction);
-		abort();
-	}
-
-	ci = bsc_mgcp_extract_ci(crcx_resp);
-	if (ci != 1) {
-		printf("Failed to parse the CI. Got: %d\n", ci);
-		abort();
-	}
-}
-
-struct cr_filter {
-	const uint8_t *data;
-	int length;
-	int result;
-	int contype;
-
-	const char *bsc_imsi_allow;
-	const char *bsc_imsi_deny;
-	const char *nat_imsi_deny;
-	int nat_cm_reject_cause;
-	int nat_lu_reject_cause;
-	int bsc_cm_reject_cause;
-	int bsc_lu_reject_cause;
-	int want_cm_reject_cause;
-	int want_lu_reject_cause;
-};
-
-static struct cr_filter cr_filter[] = {
-	{
-		.data = bssmap_cr,
-		.length = sizeof(bssmap_cr),
-		.result = 1,
-		.contype = FLT_CON_TYPE_CM_SERV_REQ,
-		.nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-	},
-	{
-		.data = bss_lu,
-		.length = sizeof(bss_lu),
-		.result = 1,
-		.contype = FLT_CON_TYPE_LU,
-		.nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-	},
-	{
-		.data = pag_resp,
-		.length = sizeof(pag_resp),
-		.result = 1,
-		.contype = FLT_CON_TYPE_PAG_RESP,
-		.nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-	},
-	{
-		/* nat deny is before blank/null BSC */
-		.data = bss_lu,
-		.length = sizeof(bss_lu),
-		.result = -3,
-		.nat_imsi_deny = "[0-9]*",
-		.contype = FLT_CON_TYPE_LU,
-		.nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-	},
-	{
-		/* BSC allow is before NAT deny */
-		.data = bss_lu,
-		.length = sizeof(bss_lu),
-		.result = 1,
-		.nat_imsi_deny = "[0-9]*",
-		.bsc_imsi_allow = "2440[0-9]*",
-		.contype = FLT_CON_TYPE_LU,
-		.nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-	},
-	{
-		/* BSC allow is before NAT deny */
-		.data = bss_lu,
-		.length = sizeof(bss_lu),
-		.result = 1,
-		.bsc_imsi_allow = "[0-9]*",
-		.nat_imsi_deny = "[0-9]*",
-		.contype = FLT_CON_TYPE_LU,
-		.nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-	},
-	{
-		/* filter as deny is first */
-		.data = bss_lu,
-		.length = sizeof(bss_lu),
-		.result = 1,
-		.bsc_imsi_deny = "[0-9]*",
-		.bsc_imsi_allow = "[0-9]*",
-		.nat_imsi_deny = "[0-9]*",
-		.contype = FLT_CON_TYPE_LU,
-		.nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-	},
-	{
-		/* deny by nat rule */
-		.data = bss_lu,
-		.length = sizeof(bss_lu),
-		.result = -3,
-		.bsc_imsi_deny = "000[0-9]*",
-		.nat_imsi_deny = "[0-9]*",
-		.contype = FLT_CON_TYPE_LU,
-		.nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-	},
-	{
-		/* deny by nat rule */
-		.data = bss_lu,
-		.length = sizeof(bss_lu),
-		.result = -3,
-		.bsc_imsi_deny = "000[0-9]*",
-		.nat_imsi_deny = "[0-9]*",
-		.contype = FLT_CON_TYPE_LU,
-		.nat_cm_reject_cause = 0x23,
-		.nat_lu_reject_cause = 0x42,
-		.bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_lu_reject_cause = 0x42,
-		.want_cm_reject_cause = 0x23,
-	},
-	{
-		/* deny by bsc rule */
-		.data = bss_lu,
-		.length = sizeof(bss_lu),
-		.result = -2,
-		.bsc_imsi_deny = "[0-9]*",
-		.contype = FLT_CON_TYPE_LU,
-		.nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.want_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-	},
-	{
-		/* deny by bsc rule */
-		.data = bss_lu,
-		.length = sizeof(bss_lu),
-		.result = -2,
-		.bsc_imsi_deny = "[0-9]*",
-		.contype = FLT_CON_TYPE_LU,
-		.nat_cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.nat_lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED,
-		.bsc_cm_reject_cause = 0x42,
-		.bsc_lu_reject_cause = 0x23,
-		.want_lu_reject_cause = 0x23,
-		.want_cm_reject_cause = 0x42,
-	},
-};
-
-static void test_cr_filter()
-{
-	int i, res, contype;
-	struct msgb *msg = msgb_alloc(4096, "test_cr_filter");
-	struct bsc_nat_parsed *parsed;
-	struct bsc_msg_acc_lst *nat_lst, *bsc_lst;
-	struct bsc_msg_acc_lst_entry *nat_entry, *bsc_entry;
-	struct bsc_filter_reject_cause cause;
-
-	struct bsc_nat *nat = bsc_nat_alloc();
-	struct bsc_connection *bsc = bsc_connection_alloc(nat);
-	bsc->cfg = bsc_config_alloc(nat, "foo", 0);
-	bsc_config_add_lac(bsc->cfg, 1234);
-	bsc->cfg->acc_lst_name = "bsc";
-	nat->acc_lst_name = "nat";
-
-	nat_lst = bsc_msg_acc_lst_get(nat, &nat->access_lists, "nat");
-	bsc_lst = bsc_msg_acc_lst_get(nat, &nat->access_lists, "bsc");
-
-	bsc_entry = bsc_msg_acc_lst_entry_create(bsc_lst);
-	nat_entry = bsc_msg_acc_lst_entry_create(nat_lst);
-
-	/* test the default value as we are going to overwrite it */
-	OSMO_ASSERT(bsc_entry->cm_reject_cause == GSM48_REJECT_PLMN_NOT_ALLOWED);
-	OSMO_ASSERT(bsc_entry->lu_reject_cause == GSM48_REJECT_PLMN_NOT_ALLOWED);
-
-	for (i = 0; i < ARRAY_SIZE(cr_filter); ++i) {
-		char *imsi;
-		msgb_reset(msg);
-		copy_to_msg(msg, cr_filter[i].data, cr_filter[i].length);
-
-		bsc_entry->cm_reject_cause = cr_filter[i].bsc_cm_reject_cause;
-		bsc_entry->lu_reject_cause = cr_filter[i].bsc_lu_reject_cause;
-		nat_entry->cm_reject_cause = cr_filter[i].nat_cm_reject_cause;
-		nat_entry->lu_reject_cause = cr_filter[i].nat_lu_reject_cause;
-
-		if (gsm_parse_reg(nat_entry, &nat_entry->imsi_deny_re, &nat_entry->imsi_deny,
-			      cr_filter[i].nat_imsi_deny ? 1 : 0,
-			      &cr_filter[i].nat_imsi_deny) != 0)
-			abort();
-		if (gsm_parse_reg(bsc_entry, &bsc_entry->imsi_allow_re, &bsc_entry->imsi_allow,
-			      cr_filter[i].bsc_imsi_allow ? 1 : 0,
-			      &cr_filter[i].bsc_imsi_allow) != 0)
-			abort();
-		if (gsm_parse_reg(bsc_entry, &bsc_entry->imsi_deny_re, &bsc_entry->imsi_deny,
-			      cr_filter[i].bsc_imsi_deny ? 1 : 0,
-			      &cr_filter[i].bsc_imsi_deny) != 0)
-			abort();
-
-		parsed = bsc_nat_parse(msg);
-		if (!parsed) {
-			printf("FAIL: Failed to parse the message\n");
-			abort();
-		}
-
-		memset(&cause, 0, sizeof(cause));
-		res = bsc_nat_filter_sccp_cr(bsc, msg, parsed, &contype, &imsi, &cause);
-		if (res != cr_filter[i].result) {
-			printf("FAIL: Wrong result %d for test %d.\n", res, i);
-			abort();
-		}
-
-
-		OSMO_ASSERT(cause.cm_reject_cause == cr_filter[i].want_cm_reject_cause);
-		OSMO_ASSERT(cause.lu_reject_cause == cr_filter[i].want_lu_reject_cause);
-
-		if (contype != cr_filter[i].contype) {
-			printf("FAIL: Wrong contype %d for test %d.\n", res, contype);
-			abort();
-		}
-
-		talloc_steal(parsed, imsi);
-		talloc_free(parsed);
-	}
-
-	msgb_free(msg);
-	bsc_nat_free(nat);
-}
-
-static void test_dt_filter()
-{
-	int i;
-	struct msgb *msg = msgb_alloc(4096, "test_dt_filter");
-	struct bsc_nat_parsed *parsed;
-	struct bsc_filter_reject_cause cause;
-
-	struct bsc_nat *nat = bsc_nat_alloc();
-	struct bsc_connection *bsc = bsc_connection_alloc(nat);
-	struct nat_sccp_connection *con = talloc_zero(0, struct nat_sccp_connection);
-
-	bsc->cfg = bsc_config_alloc(nat, "foo", 0);
-	bsc_config_add_lac(bsc->cfg, 23);
-	con->bsc = bsc;
-
-	msgb_reset(msg);
-	copy_to_msg(msg, id_resp, ARRAY_SIZE(id_resp));
-
-	parsed = bsc_nat_parse(msg);
-	if (!parsed) {
-		printf("FAIL: Could not parse ID resp\n");
-		abort();
-	}
-
-	if (parsed->bssap != BSSAP_MSG_DTAP) {
-		printf("FAIL: It should be dtap\n");
-		abort();
-	}
-
-	/* gsm_type is actually the size of the dtap */
-	if (parsed->gsm_type < msgb_l3len(msg) - 3) {
-		printf("FAIL: Not enough space for the content\n");
-		abort();
-	}
-
-	memset(&cause, 0, sizeof(cause));
-	OSMO_ASSERT(!con->filter_state.imsi);
-	if (bsc_nat_filter_dt(bsc, msg, con, parsed, &cause) != 1) {
-		printf("FAIL: Should have passed..\n");
-		abort();
-	}
-	OSMO_ASSERT(con->filter_state.imsi);
-	OSMO_ASSERT(talloc_parent(con->filter_state.imsi) == con);
-
-	/* just some basic length checking... */
-	for (i = ARRAY_SIZE(id_resp); i >= 0; --i) {
-		msgb_reset(msg);
-		copy_to_msg(msg, id_resp, ARRAY_SIZE(id_resp));
-
-		parsed = bsc_nat_parse(msg);
-		if (!parsed)
-			continue;
-
-		con->filter_state.imsi_checked = 0;
-		memset(&cause, 0, sizeof(cause));
-		bsc_nat_filter_dt(bsc, msg, con, parsed, &cause);
-	}
-
-	msgb_free(msg);
-	bsc_nat_free(nat);
-}
-
-static void test_setup_rewrite()
-{
-	struct msgb *msg = msgb_alloc(4096, "test_dt_filter");
-	struct msgb *out;
-	struct bsc_nat_parsed *parsed;
-	const char *imsi = "27408000001234";
-
-	struct bsc_nat *nat = bsc_nat_alloc();
-
-	/* a fake list */
-	struct osmo_config_list entries;
-	struct osmo_config_entry entry;
-
-	INIT_LLIST_HEAD(&entries.entry);
-	entry.mcc = "274";
-	entry.mnc = "08";
-	entry.option = "^0([1-9])";
-	entry.text = "0049";
-	llist_add_tail(&entry.list, &entries.entry);
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, &entries);
-
-	/* verify that nothing changed */
-	msgb_reset(msg);
-	copy_to_msg(msg, cc_setup_international, ARRAY_SIZE(cc_setup_international));
-	parsed = bsc_nat_parse(msg);
-	if (!parsed) {
-		printf("FAIL: Could not parse ID resp\n");
-		abort();
-	}
-
-	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
-	if (msg != out) {
-		printf("FAIL: The message should not have been changed\n");
-		abort();
-	}
-
-	verify_msg(out, cc_setup_international, ARRAY_SIZE(cc_setup_international));
-	talloc_free(parsed);
-
-	/* verify that something in the message changes */
-	msgb_reset(msg);
-	copy_to_msg(msg, cc_setup_national, ARRAY_SIZE(cc_setup_national));
-	parsed = bsc_nat_parse(msg);
-	if (!parsed) {
-		printf("FAIL: Could not parse ID resp\n");
-		abort();
-	}
-
-	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
-	if (!out) {
-		printf("FAIL: A new message should be created.\n");
-		abort();
-	}
-
-	if (msg == out) {
-		printf("FAIL: The message should have changed\n");
-		abort();
-	}
-
-	verify_msg(out, cc_setup_national_patched, ARRAY_SIZE(cc_setup_national_patched));
-	msgb_free(out);
-
-	/* Make sure that a wildcard is matching */
-	entry.mnc = "*";
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, &entries);
-	msg = msgb_alloc(4096, "test_dt_filter");
-	copy_to_msg(msg, cc_setup_national, ARRAY_SIZE(cc_setup_national));
-	parsed = bsc_nat_parse(msg);
-	if (!parsed) {
-		printf("FAIL: Could not parse ID resp\n");
-		abort();
-	}
-
-	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
-	if (!out) {
-		printf("FAIL: A new message should be created.\n");
-		abort();
-	}
-
-	if (msg == out) {
-		printf("FAIL: The message should have changed\n");
-		abort();
-	}
-
-	verify_msg(out, cc_setup_national_patched, ARRAY_SIZE(cc_setup_national_patched));
-	msgb_free(out);
-
-	/* Make sure that a wildcard is matching */
-	entry.mnc = "09";
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, &entries);
-	msg = msgb_alloc(4096, "test_dt_filter");
-	copy_to_msg(msg, cc_setup_national, ARRAY_SIZE(cc_setup_national));
-	parsed = bsc_nat_parse(msg);
-	if (!parsed) {
-		printf("FAIL: Could not parse ID resp\n");
-		abort();
-	}
-
-	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
-	if (out != msg) {
-		printf("FAIL: The message should be unchanged.\n");
-		abort();
-	}
-
-	verify_msg(out, cc_setup_national, ARRAY_SIZE(cc_setup_national));
-	msgb_free(out);
-
-	/* Now see what happens to an international number */
-	entry.mnc = "*";
-	entry.option = "^\\+[0-9][0-9]([1-9])";
-	entry.text = "0036";
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, &entries);
-	msg = msgb_alloc(4096, "test_dt_filter");
-	copy_to_msg(msg, cc_setup_national_patched, ARRAY_SIZE(cc_setup_national_patched));
-	parsed = bsc_nat_parse(msg);
-	if (!parsed) {
-		printf("FAIL: Could not parse ID resp %d\n", __LINE__);
-		abort();
-	}
-
-	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
-	if (!out) {
-		printf("FAIL: A new message should be created %d.\n", __LINE__);
-		abort();
-	}
-
-	if (msg == out) {
-		printf("FAIL: The message should have changed %d\n", __LINE__);
-		abort();
-	}
-
-	verify_msg(out, cc_setup_national_patched_patched,
-			ARRAY_SIZE(cc_setup_national_patched_patched));
-	msgb_free(out);
-
-	/* go from international back to national */
-	entry.mnc = "*";
-	entry.option = "^\\+([0-9])";
-	entry.text = "36";
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, &entries);
-	msg = msgb_alloc(4096, "test_dt_filter");
-	copy_to_msg(msg, cc_setup_national_patched, ARRAY_SIZE(cc_setup_national_patched));
-	parsed = bsc_nat_parse(msg);
-	if (!parsed) {
-		printf("FAIL: Could not parse ID resp %d\n", __LINE__);
-		abort();
-	}
-
-	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
-	if (!out) {
-		printf("FAIL: A new message should be created %d.\n", __LINE__);
-		abort();
-	}
-
-	if (msg == out) {
-		printf("FAIL: The message should have changed %d\n", __LINE__);
-		abort();
-	}
-
-	verify_msg(out, cc_setup_national_again,
-			ARRAY_SIZE(cc_setup_national_again));
-	msgb_free(out);
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, NULL);
-	bsc_nat_free(nat);
-}
-
-static void test_setup_rewrite_prefix(void)
-{
-	struct msgb *msg = msgb_alloc(4096, "test_dt_filter");
-	struct msgb *out;
-	struct bsc_nat_parsed *parsed;
-	const char *imsi = "27408000001234";
-
-	struct bsc_nat *nat = bsc_nat_alloc();
-
-	/* a fake list */
-	struct osmo_config_list entries;
-	struct osmo_config_entry entry;
-
-	INIT_LLIST_HEAD(&entries.entry);
-	entry.mcc = "274";
-	entry.mnc = "08";
-	entry.option = "^0([1-9])";
-	entry.text = "prefix_lookup";
-	llist_add_tail(&entry.list, &entries.entry);
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, &entries);
-
-        nat->num_rewr_trie = nat_rewrite_parse(nat, "prefixes.csv");
-
-	msgb_reset(msg);
-	copy_to_msg(msg, cc_setup_national, ARRAY_SIZE(cc_setup_national));
-	parsed = bsc_nat_parse(msg);
-	if (!parsed) {
-		printf("FAIL: Could not parse ID resp\n");
-		abort();
-	}
-
-	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
-	if (!out) {
-		printf("FAIL: A new message should be created.\n");
-		abort();
-	}
-
-	if (msg == out) {
-		printf("FAIL: The message should have changed\n");
-		abort();
-	}
-
-	verify_msg(out, cc_setup_national_patched, ARRAY_SIZE(cc_setup_national_patched));
-	msgb_free(out);
-
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, NULL);
-	bsc_nat_free(nat);
-}
-
-static void test_setup_rewrite_post(void)
-{
-	struct msgb *msg = msgb_alloc(4096, "test_dt_filter");
-	struct msgb *out;
-	struct bsc_nat_parsed *parsed;
-	const char *imsi = "27408000001234";
-
-	struct bsc_nat *nat = bsc_nat_alloc();
-
-	/* a fake list */
-	struct osmo_config_list entries;
-	struct osmo_config_entry entry;
-	struct osmo_config_list entries_post;
-	struct osmo_config_entry entry_post;
-
-	INIT_LLIST_HEAD(&entries.entry);
-	entry.mcc = "274";
-	entry.mnc = "08";
-	entry.option = "^0([1-9])";
-	entry.text = "0049";
-	llist_add_tail(&entry.list, &entries.entry);
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, &entries);
-
-	/* attempt to undo the previous one */
-	INIT_LLIST_HEAD(&entries_post.entry);
-	entry_post.mcc = "274";
-	entry_post.mnc = "08";
-	entry_post.option = "^\\+49([1-9])";
-	entry_post.text = "prefix_lookup";
-	llist_add_tail(&entry_post.list, &entries_post.entry);
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr_post, &entries_post);
-
-        nat->num_rewr_trie = nat_rewrite_parse(nat, "prefixes.csv");
-
-	msgb_reset(msg);
-	copy_to_msg(msg, cc_setup_national, ARRAY_SIZE(cc_setup_national));
-	parsed = bsc_nat_parse(msg);
-	if (!parsed) {
-		printf("FAIL: Could not parse ID resp\n");
-		abort();
-	}
-
-	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
-	if (!out) {
-		printf("FAIL: A new message should be created.\n");
-		abort();
-	}
-
-	if (msg == out) {
-		printf("FAIL: The message should have changed\n");
-		abort();
-	}
-
-	verify_msg(out, cc_setup_national, ARRAY_SIZE(cc_setup_national));
-	msgb_free(out);
-
-	bsc_nat_free(nat);
-}
-
-static void test_sms_smsc_rewrite()
-{
-	struct msgb *msg = msgb_alloc(4096, "SMSC rewrite"), *out;
-	struct bsc_nat_parsed *parsed;
-	const char *imsi = "515039900406700";
-
-	struct bsc_nat *nat = bsc_nat_alloc();
-
-	/* a fake list */
-	struct osmo_config_list smsc_entries, dest_entries, clear_entries;
-	struct osmo_config_entry smsc_entry, dest_entry, clear_entry;
-
-	INIT_LLIST_HEAD(&smsc_entries.entry);
-	INIT_LLIST_HEAD(&dest_entries.entry);
-	INIT_LLIST_HEAD(&clear_entries.entry);
-	smsc_entry.mcc = "^515039";
-	smsc_entry.option = "639180000105()";
-	smsc_entry.text   = "6666666666667";
-	llist_add_tail(&smsc_entry.list, &smsc_entries.entry);
-	dest_entry.mcc = "515";
-	dest_entry.mnc = "03";
-	dest_entry.option = "^0049";
-	dest_entry.text   = "";
-	llist_add_tail(&dest_entry.list, &dest_entries.entry);
-	clear_entry.mcc = "^515039";
-	clear_entry.option = "^0049";
-	clear_entry.text   = "";
-	llist_add_tail(&clear_entry.list, &clear_entries.entry);
-
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->smsc_rewr, &smsc_entries);
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->tpdest_match, &dest_entries);
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->sms_clear_tp_srr, &clear_entries);
-
-	printf("Testing SMSC rewriting.\n");
-
-	/*
-	 * Check if the SMSC address is changed
-	 */
-	copy_to_msg(msg, smsc_rewrite, ARRAY_SIZE(smsc_rewrite));
-	parsed = bsc_nat_parse(msg);
-	if (!parsed) {
-		printf("FAIL: Could not parse SMS\n");
-		abort();
-	}
-
-	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
-	if (out == msg) {
-		printf("FAIL: This should have changed.\n");
-		abort();
-	}
-
-	verify_msg(out, smsc_rewrite_patched, ARRAY_SIZE(smsc_rewrite_patched));
-	msgb_free(out);
-
-	/* clear out the filter for SMSC */
-	printf("Attempting to only rewrite the HDR\n");
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->smsc_rewr, NULL);
-	msg = msgb_alloc(4096, "SMSC rewrite");
-	copy_to_msg(msg, smsc_rewrite, ARRAY_SIZE(smsc_rewrite));
-	parsed = bsc_nat_parse(msg);
-	if (!parsed) {
-		printf("FAIL: Could not parse SMS\n");
-		abort();
-	}
-
-	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
-	if (out == msg) {
-		printf("FAIL: This should have changed.\n");
-		abort();
-	}
-
-	verify_msg(out, smsc_rewrite_patched_hdr, ARRAY_SIZE(smsc_rewrite_patched_hdr));
-	msgb_free(out);
-
-	/* clear out the next filter */
-	printf("Attempting to change nothing.\n");
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->sms_clear_tp_srr, NULL);
-	msg = msgb_alloc(4096, "SMSC rewrite");
-	copy_to_msg(msg, smsc_rewrite, ARRAY_SIZE(smsc_rewrite));
-	parsed = bsc_nat_parse(msg);
-	if (!parsed) {
-		printf("FAIL: Could not parse SMS\n");
-		abort();
-	}
-
-	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
-	if (out != msg) {
-		printf("FAIL: This should not have changed.\n");
-		abort();
-	}
-
-	verify_msg(out, smsc_rewrite, ARRAY_SIZE(smsc_rewrite));
-	msgb_free(out);
-	bsc_nat_free(nat);
-}
-
-static void test_sms_number_rewrite(void)
-{
-	struct msgb *msg, *out;
-	struct bsc_nat_parsed *parsed;
-	const char *imsi = "515039900406700";
-
-	struct bsc_nat *nat = bsc_nat_alloc();
-
-	/* a fake list */
-	struct osmo_config_list num_entries, clear_entries;
-	struct osmo_config_entry num_entry, clear_entry;
-
-	INIT_LLIST_HEAD(&num_entries.entry);
-	num_entry.mcc = "^515039";
-	num_entry.option = "^0049()";
-	num_entry.text   = "0032";
-	llist_add_tail(&num_entry.list, &num_entries.entry);
-
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->sms_num_rewr, &num_entries);
-
-	printf("Testing SMS TP-DA rewriting.\n");
-
-	/*
-	 * Check if the SMSC address is changed
-	 */
- 	msg = msgb_alloc(4096, "SMSC rewrite");
-	copy_to_msg(msg, smsc_rewrite, ARRAY_SIZE(smsc_rewrite));
-	parsed = bsc_nat_parse(msg);
-	if (!parsed) {
-		printf("FAIL: Could not parse SMS\n");
-		abort();
-	}
-
-	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
-	if (out == msg) {
-		printf("FAIL: This should have changed.\n");
-		abort();
-	}
-
-	verify_msg(out, smsc_rewrite_num_patched,
-		   ARRAY_SIZE(smsc_rewrite_num_patched));
-	msgb_free(out);
-
-	/*
-	 * Now with TP-SRR rewriting enabled
-	 */
-	INIT_LLIST_HEAD(&clear_entries.entry);
-	clear_entry.mcc = "^515039";
-	clear_entry.option = "";
-	clear_entry.text   = "";
-	llist_add_tail(&clear_entry.list, &clear_entries.entry);
-	bsc_nat_num_rewr_entry_adapt(nat, &nat->sms_clear_tp_srr, &clear_entries);
-
- 	msg = msgb_alloc(4096, "SMSC rewrite");
-	copy_to_msg(msg, smsc_rewrite, ARRAY_SIZE(smsc_rewrite));
-	parsed = bsc_nat_parse(msg);
-	if (!parsed) {
-		printf("FAIL: Could not parse SMS\n");
-		abort();
-	}
-
-	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
-	if (out == msg) {
-		printf("FAIL: This should have changed.\n");
-		abort();
-	}
-
-	verify_msg(out, smsc_rewrite_num_patched_tp_srr,
-		   ARRAY_SIZE(smsc_rewrite_num_patched_tp_srr));
-	msgb_free(out);
-	bsc_nat_free(nat);
-}
-
-static void test_barr_list_parsing(void)
-{
-	int rc;
-	int cm, lu;
-	struct rb_node *node;
-	struct rb_root root = RB_ROOT;
-	struct osmo_config_list *lst = osmo_config_list_parse(NULL, "barr.cfg");
-	if (lst == NULL)
-		abort();
-
-	rc = bsc_filter_barr_adapt(NULL, &root, lst);
-	if (rc != 0)
-		abort();
-	talloc_free(lst);
-
-
-	for (node = rb_first(&root); node; node = rb_next(node)) {
-		struct bsc_filter_barr_entry *entry;
-		entry = rb_entry(node, struct bsc_filter_barr_entry, node);
-		printf("IMSI: %s CM: %d LU: %d\n", entry->imsi,
-			entry->cm_reject_cause, entry->lu_reject_cause);
-	}
-
-	/* do the look up now.. */
-	rc = bsc_filter_barr_find(&root, "12123119", &cm, &lu);
-	if (!rc) {
-		printf("Failed to find the IMSI.\n");
-		abort();
-	}
-
-	if (cm != 3 || lu != 4) {
-		printf("Found CM(%d) and LU(%d)\n", cm, lu);
-		abort();
-	}
-
-	/* empty and check that it is empty */
-	bsc_filter_barr_adapt(NULL, &root, NULL);
-	if (!RB_EMPTY_ROOT(&root)) {
-		printf("Failed to empty the list.\n");
-		abort();
-	}
-
-	/* check that dup results in an error */
-	lst = osmo_config_list_parse(NULL, "barr_dup.cfg");
-	if (lst == NULL) {
-		printf("Failed to parse list with dups\n");
-		abort();
-	}
-
-	rc = bsc_filter_barr_adapt(NULL, &root, lst);
-	if (rc != -1) {
-		printf("It should have failed due dup\n");
-		abort();
-	}
-	talloc_free(lst);
-
-	/* dump for reference */
-	for (node = rb_first(&root); node; node = rb_next(node)) {
-		struct bsc_filter_barr_entry *entry;
-		entry = rb_entry(node, struct bsc_filter_barr_entry, node);
-		printf("IMSI: %s CM: %d LU: %d\n", entry->imsi,
-			entry->cm_reject_cause, entry->lu_reject_cause);
-
-	}
-	rc = bsc_filter_barr_adapt(NULL, &root, NULL);
-}
-
-static void test_nat_extract_lac()
-{
-	int res;
-	struct bsc_connection *bsc;
-	struct bsc_nat *nat;
-	struct nat_sccp_connection con;
-	struct bsc_nat_parsed *parsed;
-	struct msgb *msg = msgb_alloc(4096, "test-message");
-
-	printf("Testing LAC extraction from SCCP CR\n");
-
-	/* initialize the testcase */
-	nat = bsc_nat_alloc();
-	bsc = bsc_connection_alloc(nat);
-	bsc->cfg = bsc_config_alloc(nat, "foo", 0);
-
-	memset(&con, 0, sizeof(con));
-	con.bsc = bsc;
-
-	/* create the SCCP CR */
-	msg->l2h = msgb_put(msg, ARRAY_SIZE(bssmap_cr));
-	memcpy(msg->l2h, bssmap_cr, ARRAY_SIZE(bssmap_cr));
-
-	/* parse it and pass it on */
-	parsed = bsc_nat_parse(msg);
-	res = bsc_nat_extract_lac(bsc, &con, parsed, msg);
-	OSMO_ASSERT(res == 0);
-
-	/* verify the LAC */
-	OSMO_ASSERT(con.lac == 8210);
-	OSMO_ASSERT(con.ci == 50000);
-
-	bsc_nat_free(nat);
-}
-
-int main(int argc, char **argv)
-{
-	msgb_talloc_ctx_init(NULL, 0);
-	sccp_set_log_area(DSCCP);
-	osmo_init_logging(&log_info);
-
-	test_filter();
-	test_contrack();
-	test_paging();
-	test_mgcp_ass_tracking();
-	test_mgcp_find();
-	test_mgcp_rewrite();
-	test_mgcp_parse();
-	test_cr_filter();
-	test_dt_filter();
-	test_setup_rewrite();
-	test_setup_rewrite_prefix();
-	test_setup_rewrite_post();
-	test_sms_smsc_rewrite();
-	test_sms_number_rewrite();
-	test_mgcp_allocations();
-	test_barr_list_parsing();
-	test_nat_extract_lac();
-
-	printf("Testing execution completed.\n");
-	return 0;
-}
-
-/* stub */
-void bsc_nat_send_mgcp_to_msc(struct bsc_nat *nat, struct msgb *msg)
-{
-	abort();
-}
diff --git a/tests/bsc-nat/bsc_nat_test.ok b/tests/bsc-nat/bsc_nat_test.ok
deleted file mode 100644
index ab04f42..0000000
--- a/tests/bsc-nat/bsc_nat_test.ok
+++ /dev/null
@@ -1,39 +0,0 @@
-Testing BSS Filtering.
-Going to test item: 0
-Going to test item: 1
-Going to test item: 2
-Going to test item: 3
-Going to test item: 4
-Going to test item: 5
-Going to test item: 6
-Going to test item: 7
-Going to test item: 8
-Going to test item: 9
-Going to test item: 10
-Going to test item: 11
-Going to test item: 12
-Testing connection tracking.
-Testing paging by lac.
-Testing MGCP.
-Testing finding of a BSC Connection
-Testing rewriting MGCP messages.
-Testing MGCP response parsing.
-Testing SMSC rewriting.
-Attempting to only rewrite the HDR
-Attempting to change nothing.
-Testing SMS TP-DA rewriting.
-IMSI: 12123115 CM: 3 LU: 4
-IMSI: 12123116 CM: 3 LU: 4
-IMSI: 12123117 CM: 3 LU: 4
-IMSI: 12123118 CM: 3 LU: 4
-IMSI: 12123119 CM: 3 LU: 4
-IMSI: 12123120 CM: 3 LU: 4
-IMSI: 12123123 CM: 3 LU: 1
-IMSI: 12123124 CM: 3 LU: 2
-IMSI: 12123125 CM: 3 LU: 3
-IMSI: 12123126 CM: 3 LU: 4
-IMSI: 12123127 CM: 3 LU: 5
-IMSI: 12123128 CM: 3 LU: 6
-IMSI: 12123124 CM: 3 LU: 2
-Testing LAC extraction from SCCP CR
-Testing execution completed.
diff --git a/tests/bsc-nat/prefixes.csv b/tests/bsc-nat/prefixes.csv
deleted file mode 100644
index 0c7660f..0000000
--- a/tests/bsc-nat/prefixes.csv
+++ /dev/null
@@ -1,2 +0,0 @@
-0172,0049
-+49,0
diff --git a/tests/bsc/Makefile.am b/tests/bsc/Makefile.am
deleted file mode 100644
index 904bdfc..0000000
--- a/tests/bsc/Makefile.am
+++ /dev/null
@@ -1,45 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	-ggdb3 \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOSCCP_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(COVERAGE_LDFLAGS) \
-	$(NULL)
-
-EXTRA_DIST = \
-	bsc_test.ok \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	bsc_test \
-	$(NULL)
-
-bsc_test_SOURCES = \
-	bsc_test.c \
-	$(top_srcdir)/src/osmo-bsc/osmo_bsc_filter.c \
-	$(NULL)
-
-bsc_test_LDADD = \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
-	$(top_builddir)/src/libmgcp/libmgcp.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOSCCP_LIBS) \
-	$(LIBOSMOVTY_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	-lrt \
-	$(NULL)
diff --git a/tests/bsc/bsc_test.c b/tests/bsc/bsc_test.c
deleted file mode 100644
index 20ed5b4..0000000
--- a/tests/bsc/bsc_test.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * BSC Message filtering
- *
- * (C) 2013 by sysmocom s.f.m.c. GmbH
- * Written by Jacob Erlbeck <jerlbeck@sysmocom.de>
- * (C) 2010-2013 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2013 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 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/>.
- *
- */
-
-
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-
-#include <openbsc/osmo_bsc.h>
-#include <openbsc/bsc_msc_data.h>
-#include <openbsc/gsm_04_80.h>
-#include <openbsc/gsm_subscriber.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/backtrace.h>
-#include <osmocom/core/talloc.h>
-
-#include <stdio.h>
-#include <search.h>
-
-enum test {
-	TEST_SCAN_TO_BTS,
-	TEST_SCAN_TO_MSC,
-};
-
-/* GSM 04.08 MM INFORMATION test message */
-static uint8_t gsm48_mm_info_nn_tzt[] = {
-	0x05, 0x32, 0x45, 0x08, 0x80, 0x4f, 0x77, 0xeb,
-	0x1a, 0xb6, 0x97, 0xe7, 0x47, 0x31, 0x90, 0x61,
-	0x11, 0x02, 0x73, 0x00,
-};
-
-static uint8_t gsm48_mm_info_nn_tzt_out[] = {
-	0x05, 0x32, 0x45, 0x08, 0x80, 0x4f, 0x77, 0xeb,
-	0x1a, 0xb6, 0x97, 0xe7, 0x47, 0x31, 0x90, 0x61,
-	0x11, 0x02, 0x73, 0x1a,
-};
-
-static uint8_t gsm48_mm_info_nn_tzt_dst[] = {
-	0x05, 0x32, 0x45, 0x08, 0x80, 0x4f, 0x77, 0xeb,
-	0x1a, 0xb6, 0x97, 0xe7, 0x47, 0x31, 0x90, 0x61,
-	0x11, 0x02, 0x73, 0x00, 0x49, 0x01, 0x00,
-};
-
-static uint8_t gsm48_mm_info_nn_tzt_dst_out[] = {
-	0x05, 0x32, 0x45, 0x08, 0x80, 0x4f, 0x77, 0xeb,
-	0x1a, 0xb6, 0x97, 0xe7, 0x47, 0x31, 0x90, 0x61,
-	0x11, 0x02, 0x73, 0x1a, 0x49, 0x01, 0x02,
-};
-
-struct test_definition {
-	const uint8_t *data;
-	const uint16_t length;
-	const int dir;
-	const int result;
-	const uint8_t *out_data;
-	const uint16_t out_length;
-	const char* params;
-	const int n_params;
-};
-
-static int get_int(const char *params, size_t nmemb, const char *key, int def, int *is_set)
-{
-	const char *kv = NULL;
-
-	kv = strstr(params, key);
-	if (kv) {
-		kv += strlen(key) + 1;
-		fprintf(stderr, "get_int(%s) -> %d\n", key, atoi(kv));
-		if (is_set)
-			*is_set = 1;
-	}
-
-	return kv ? atoi(kv) : def;
-}
-
-static const struct test_definition test_scan_defs[] = {
-	{
-		.data = gsm48_mm_info_nn_tzt_dst,
-		.length = ARRAY_SIZE(gsm48_mm_info_nn_tzt),
-		.dir = TEST_SCAN_TO_BTS,
-		.result = 0,
-		.out_data = gsm48_mm_info_nn_tzt_dst_out,
-		.out_length = ARRAY_SIZE(gsm48_mm_info_nn_tzt_out),
-		.params = "tz_hr=-5 tz_mn=15 tz_dst=2",
-		.n_params = 3,
-	},
-	{
-		.data = gsm48_mm_info_nn_tzt_dst,
-		.length = ARRAY_SIZE(gsm48_mm_info_nn_tzt_dst),
-		.dir = TEST_SCAN_TO_BTS,
-		.result = 0,
-		.out_data = gsm48_mm_info_nn_tzt_dst_out,
-		.out_length = ARRAY_SIZE(gsm48_mm_info_nn_tzt_dst_out),
-		.params = "tz_hr=-5 tz_mn=15 tz_dst=2",
-		.n_params = 3,
-	},
-};
-
-static void test_scan(void)
-{
-	int i;
-
-	struct gsm_network *net;
-	struct gsm_bts *bts;
-	struct osmo_bsc_sccp_con *sccp_con;
-	struct bsc_msc_data *msc;
-	struct gsm_subscriber_connection *conn;
-
-	net = talloc_zero(NULL, struct gsm_network);
-	bts = talloc_zero(net, struct gsm_bts);
-	sccp_con = talloc_zero(net, struct osmo_bsc_sccp_con);
-	msc = talloc_zero(net, struct bsc_msc_data);
-	conn = talloc_zero(net, struct gsm_subscriber_connection);
-
-	bts->network = net;
-	sccp_con->msc = msc;
-	conn->bts = bts;
-	conn->sccp_con = sccp_con;
-
-	/* start testing with proper messages */
-	printf("Testing BTS<->MSC message scan.\n");
-	for (i = 0; i < ARRAY_SIZE(test_scan_defs); ++i) {
-		const struct test_definition *test_def = &test_scan_defs[i];
-		int result;
-		struct msgb *msg = msgb_alloc(4096, "test-message");
-		int is_set = 0;
-
-		net->tz.hr = get_int(test_def->params, test_def->n_params, "tz_hr", 0, &is_set);
-		net->tz.mn = get_int(test_def->params, test_def->n_params, "tz_mn", 0, &is_set);
-		net->tz.dst = get_int(test_def->params, test_def->n_params, "tz_dst", 0, &is_set);
-		net->tz.override = 1;
-
-		printf("Going to test item: %d\n", i);
-		msg->l3h = msgb_put(msg, test_def->length);
-		memcpy(msg->l3h, test_def->data, test_def->length);
-
-		switch (test_def->dir) {
-		case TEST_SCAN_TO_BTS:
-			/* override timezone of msg coming from the MSC */
-			result = bsc_scan_msc_msg(conn, msg);
-			break;
-		case TEST_SCAN_TO_MSC:
-			/* override timezone of msg coming from the BSC */
-			/* FIXME: no test for this case is defined in
-			 * test_scan_defs[], so this is never used. */
-			result = bsc_scan_bts_msg(conn, msg);
-			break;
-		default:
-			abort();
-			break;
-		}
-
-		if (result != test_def->result) {
-			printf("FAIL: Not the expected result, got: %d wanted: %d\n",
-				result, test_def->result);
-			goto out;
-		}
-
-		if (msgb_l3len(msg) != test_def->out_length) {
-			printf("FAIL: Not the expected message size, got: %d wanted: %d\n",
-				msgb_l3len(msg), test_def->out_length);
-			goto out;
-		}
-
-		if (memcmp(msgb_l3(msg), test_def->out_data, test_def->out_length) != 0) {
-			printf("FAIL: Not the expected message\n");
-			goto out;
-		}
-
-out:
-		msgb_free(msg);
-	}
-
-	talloc_free(net);
-}
-
-
-int main(int argc, char **argv)
-{
-	msgb_talloc_ctx_init(NULL, 0);
-	osmo_init_logging(&log_info);
-
-	test_scan();
-
-	printf("Testing execution completed.\n");
-	return 0;
-}
diff --git a/tests/bsc/bsc_test.ok b/tests/bsc/bsc_test.ok
deleted file mode 100644
index 0564bf0..0000000
--- a/tests/bsc/bsc_test.ok
+++ /dev/null
@@ -1,4 +0,0 @@
-Testing BTS<->MSC message scan.
-Going to test item: 0
-Going to test item: 1
-Testing execution completed.
diff --git a/tests/channel/Makefile.am b/tests/channel/Makefile.am
deleted file mode 100644
index dd78bdc..0000000
--- a/tests/channel/Makefile.am
+++ /dev/null
@@ -1,35 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	-ggdb3 \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(NULL)
-
-EXTRA_DIST = \
-	channel_test.ok \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	channel_test \
-	$(NULL)
-
-channel_test_SOURCES = \
-	channel_test.c \
-	$(NULL)
-
-channel_test_LDADD = \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libvlr/libvlr.a \
-	$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBCRYPTO_LIBS) \
-	-ldbi \
-	$(NULL)
diff --git a/tests/channel/channel_test.c b/tests/channel/channel_test.c
deleted file mode 100644
index beae658..0000000
--- a/tests/channel/channel_test.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * (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 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/>.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <assert.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/select.h>
-
-#include <openbsc/common_bsc.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/vlr.h>
-
-void test_bts_debug_print(void)
-{
-	struct gsm_network *network;
-	struct gsm_bts *bts;
-	struct gsm_bts_trx *trx;
-
-	printf("Testing the lchan printing:");
-
-	/* Create a dummy network */
-	network = bsc_network_init(tall_bsc_ctx, 1, 1, NULL);
-	if (!network)
-		exit(1);
-	/* Add a BTS with some reasonanbly non-zero id */
-	bts = gsm_bts_alloc(network, 45);
-	/* Add a second TRX to test on multiple TRXs */
-	gsm_bts_trx_alloc(bts);
-
-	llist_for_each_entry(trx, &bts->trx_list, list) {
-		char *name = gsm_lchan_name(&trx->ts[3].lchan[4]);
-
-		if (name)
-			printf(" %s", name);
-		else
-			printf("NULL name");
-	}
-	printf("\n");
-}
-
-
-void test_dyn_ts_subslots(void)
-{
-	struct gsm_bts_trx_ts ts;
-
-	printf("Testing subslot numbers for pchan types\n");
-
-	ts.pchan = GSM_PCHAN_TCH_F;
-	OSMO_ASSERT(ts_subslots(&ts) == 1);
-
-	ts.pchan = GSM_PCHAN_TCH_H;
-	OSMO_ASSERT(ts_subslots(&ts) == 2);
-
-	ts.pchan = GSM_PCHAN_PDCH;
-	OSMO_ASSERT(ts_subslots(&ts) == 0);
-
-	ts.pchan = GSM_PCHAN_TCH_F_PDCH;
-	ts.flags = 0; /* TCH_F mode */
-	OSMO_ASSERT(ts_subslots(&ts) == 1);
-	ts.flags = TS_F_PDCH_ACTIVE;
-	OSMO_ASSERT(ts_subslots(&ts) == 0);
-
-	ts.pchan = GSM_PCHAN_TCH_F_TCH_H_PDCH;
-	ts.dyn.pchan_is = GSM_PCHAN_TCH_F;
-	OSMO_ASSERT(ts_subslots(&ts) == 1);
-	ts.dyn.pchan_is = GSM_PCHAN_TCH_H;
-	OSMO_ASSERT(ts_subslots(&ts) == 2);
-	ts.dyn.pchan_is = GSM_PCHAN_PDCH;
-	OSMO_ASSERT(ts_subslots(&ts) == 0);
-}
-
-int main(int argc, char **argv)
-{
-	osmo_init_logging(&log_info);
-
-	test_dyn_ts_subslots();
-	test_bts_debug_print();
-
-	return EXIT_SUCCESS;
-}
-
-void _abis_nm_sendmsg() {}
-void sms_alloc() {}
-void sms_free() {}
-void gsm_net_update_ctype(struct gsm_network *network) {}
-void gsm48_secure_channel() {}
-void paging_request_stop() {}
-void vty_out() {}
-
-void ipa_client_conn_clear_queue() {}
-void ipa_client_conn_close() {}
-void ipa_client_conn_create() {}
-void ipa_client_conn_destroy() {}
-void ipa_client_conn_open() {}
-void ipa_client_conn_send() {}
-void ipa_msg_push_header() {}
-void ipaccess_bts_handle_ccm() {}
-
-struct tlv_definition nm_att_tlvdef;
diff --git a/tests/channel/channel_test.ok b/tests/channel/channel_test.ok
deleted file mode 100644
index 81d6569..0000000
--- a/tests/channel/channel_test.ok
+++ /dev/null
@@ -1,2 +0,0 @@
-Testing subslot numbers for pchan types
-Testing the lchan printing: (bts=45,trx=0,ts=3,ss=4) (bts=45,trx=1,ts=3,ss=4)
diff --git a/tests/db/Makefile.am b/tests/db/Makefile.am
deleted file mode 100644
index bcb66ec..0000000
--- a/tests/db/Makefile.am
+++ /dev/null
@@ -1,47 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	-ggdb3 \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(LIBSMPP34_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(COVERAGE_LDFLAGS) \
-	$(NULL)
-
-EXTRA_DIST = \
-	db_test.ok \
-	db_test.err \
-	hlr.sqlite3 \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	db_test \
-	$(NULL)
-
-db_test_SOURCES = \
-	db_test.c \
-	$(NULL)
-
-db_test_LDADD = \
-	$(top_builddir)/src/libmsc/libmsc.a \
-	$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(top_builddir)/tests/libiudummy/libiudummy.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBSMPP34_LIBS) \
-	$(LIBOSMOVTY_LIBS) \
-	$(LIBCRYPTO_LIBS) \
-	-ldbi \
-	$(NULL)
diff --git a/tests/db/db_test.c b/tests/db/db_test.c
deleted file mode 100644
index a0c1e79..0000000
--- a/tests/db/db_test.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/* (C) 2008 by Jan Luebbe <jluebbe@debian.org>
- * (C) 2009-2016 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2014 by Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
- * 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 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/>.
- *
- */
-
-#include <openbsc/debug.h>
-#include <openbsc/db.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/gsm_04_11.h>
-#include <openbsc/mgcp.h>
-
-#include <osmocom/core/application.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <inttypes.h>
-
-static struct gsm_network dummy_net;
-static struct gsm_subscriber_group dummy_sgrp;
-
-#define SUBSCR_PUT(sub) \
-	sub->group = &dummy_sgrp;	\
-	subscr_put(sub);
-
-#define COMPARE(original, copy) \
-	if (original->id != copy->id) \
-		printf("Ids do not match in %s:%d %llu %llu\n", \
-			__FUNCTION__, __LINE__, original->id, copy->id); \
-	if (original->lac != copy->lac) \
-		printf("LAC do not match in %s:%d %d %d\n", \
-			__FUNCTION__, __LINE__, original->lac, copy->lac); \
-	if (original->authorized != copy->authorized) \
-		printf("Authorize do not match in %s:%d %d %d\n", \
-			__FUNCTION__, __LINE__, original->authorized, \
-			copy->authorized); \
-	if (strcmp(original->imsi, copy->imsi) != 0) \
-		printf("IMSIs do not match in %s:%d '%s' '%s'\n", \
-			__FUNCTION__, __LINE__, original->imsi, copy->imsi); \
-	if (original->tmsi != copy->tmsi) \
-		printf("TMSIs do not match in %s:%d '%u' '%u'\n", \
-			__FUNCTION__, __LINE__, original->tmsi, copy->tmsi); \
-	if (strcmp(original->name, copy->name) != 0) \
-		printf("names do not match in %s:%d '%s' '%s'\n", \
-			__FUNCTION__, __LINE__, original->name, copy->name); \
-	if (strcmp(original->extension, copy->extension) != 0) \
-		printf("Extensions do not match in %s:%d '%s' '%s'\n", \
-			__FUNCTION__, __LINE__, original->extension, copy->extension); \
-
-/*
- * Create/Store a SMS and then try to load it.
- */
-static void test_sms(void)
-{
-	int rc;
-	struct gsm_sms *sms;
-	struct gsm_subscriber *subscr;
-	subscr = db_get_subscriber(GSM_SUBSCRIBER_IMSI, "9993245423445");
-	OSMO_ASSERT(subscr);
-	subscr->group = &dummy_sgrp;
-
-	sms = sms_alloc();
-	sms->receiver = subscr_get(subscr);
-
-	sms->src.ton = 0x23;
-	sms->src.npi = 0x24;
-	memcpy(sms->src.addr, "1234", strlen("1234") + 1);
-
-	sms->dst.ton = 0x32;
-	sms->dst.npi = 0x42;
-	memcpy(sms->dst.addr, subscr->extension, sizeof(subscr->extension));
-
-	memcpy(sms->text, "Text123", strlen("Text123") + 1);
-	memcpy(sms->user_data, "UserData123", strlen("UserData123") + 1);
-	sms->user_data_len = strlen("UserData123");
-
-	/* random values */
-	sms->reply_path_req = 1;
-	sms->status_rep_req = 2;
-	sms->ud_hdr_ind = 3;
-	sms->protocol_id = 4;
-	sms->data_coding_scheme = 5;
-
-	rc = db_sms_store(sms);
-	sms_free(sms);
-	OSMO_ASSERT(rc == 0);
-
-	/* now query */
-	sms = db_sms_get_unsent_for_subscr(subscr);
-	OSMO_ASSERT(sms);
-	OSMO_ASSERT(sms->receiver == subscr);
-	OSMO_ASSERT(sms->reply_path_req == 1);
-	OSMO_ASSERT(sms->status_rep_req == 2);
-	OSMO_ASSERT(sms->ud_hdr_ind == 3);
-	OSMO_ASSERT(sms->protocol_id == 4);
-	OSMO_ASSERT(sms->data_coding_scheme == 5);
-	OSMO_ASSERT(sms->src.ton == 0x23);
-	OSMO_ASSERT(sms->src.npi == 0x24);
-	OSMO_ASSERT(sms->dst.ton == 0x32);
-	OSMO_ASSERT(sms->dst.npi == 0x42);
-	OSMO_ASSERT(strcmp((char *) sms->text, "Text123") == 0);
-	OSMO_ASSERT(sms->user_data_len == strlen("UserData123"));
-	OSMO_ASSERT(strcmp((char *) sms->user_data, "UserData123") == 0);
-
-	/* Mark the SMS as delivered */
-	db_sms_mark_delivered(sms);
-	sms_free(sms);
-
-	sms = db_sms_get_unsent_for_subscr(subscr);
-	OSMO_ASSERT(!sms);
-
-	subscr_put(subscr);
-}
-
-static void test_sms_migrate(void)
-{
-	struct gsm_subscriber *rcv_subscr;
-	struct gsm_sms *sms;
-	static const uint8_t user_data_1[] = {
-		0x41, 0xf1, 0xd8, 0x05, 0x22, 0x96, 0xcd, 0x2e,
-		0x90, 0xf1, 0xfd, 0x06, 0x00 };
-	static const uint8_t user_data_2[] = {
-		0x41, 0xf1, 0xd8, 0x05, 0x22, 0x96, 0xcd, 0x2e,
-		0xd0, 0xf1, 0xfd, 0x06, 0x00 };
-
-	rcv_subscr = db_get_subscriber(GSM_SUBSCRIBER_IMSI, "901010000001111");
-	rcv_subscr->group = &dummy_sgrp;
-
-	sms = db_sms_get(&dummy_net, 1);
-	OSMO_ASSERT(sms->id == 1);
-	OSMO_ASSERT(sms->receiver == rcv_subscr);
-	OSMO_ASSERT(strcmp(sms->text, "Abc. Def. Foo") == 0);
-	OSMO_ASSERT(sms->user_data_len == ARRAY_SIZE(user_data_1));
-	OSMO_ASSERT(memcmp(sms->user_data, user_data_1, ARRAY_SIZE(user_data_1)) == 0);
-	sms_free(sms);
-
-	sms = db_sms_get(&dummy_net, 2);
-	OSMO_ASSERT(sms->id == 2);
-	OSMO_ASSERT(sms->receiver == rcv_subscr);
-	OSMO_ASSERT(strcmp(sms->text, "Abc. Def. Goo") == 0);
-	OSMO_ASSERT(sms->user_data_len == ARRAY_SIZE(user_data_2));
-	OSMO_ASSERT(memcmp(sms->user_data, user_data_2, ARRAY_SIZE(user_data_2)) == 0);
-	sms_free(sms);
-
-	subscr_put(rcv_subscr);
-}
-
-static void test_subs(const char *imsi, char *imei1, char *imei2, bool make_ext)
-{
-	struct gsm_subscriber *alice = NULL, *alice_db;
-	char scratch_str[256];
-
-	alice = db_create_subscriber(imsi, GSM_MIN_EXTEN, GSM_MAX_EXTEN,
-				     make_ext);
-	db_subscriber_assoc_imei(alice, imei1);
-	if (imei2)
-		db_subscriber_assoc_imei(alice, imei2);
-	db_subscriber_alloc_tmsi(alice);
-	alice->lac=42;
-	db_sync_subscriber(alice);
-	/* Get by TMSI */
-	snprintf(scratch_str, sizeof(scratch_str), "%"PRIu32, alice->tmsi);
-	alice_db = db_get_subscriber(GSM_SUBSCRIBER_TMSI, scratch_str);
-	COMPARE(alice, alice_db);
-	SUBSCR_PUT(alice_db);
-	/* Get by IMSI */
-	alice_db = db_get_subscriber(GSM_SUBSCRIBER_IMSI, imsi);
-	COMPARE(alice, alice_db);
-	SUBSCR_PUT(alice_db);
-	/* Get by id */
-	snprintf(scratch_str, sizeof(scratch_str), "%llu", alice->id);
-	alice_db = db_get_subscriber(GSM_SUBSCRIBER_ID, scratch_str);
-	COMPARE(alice, alice_db);
-	SUBSCR_PUT(alice_db);
-	/* Get by extension */
-	alice_db = db_get_subscriber(GSM_SUBSCRIBER_EXTENSION, alice->extension);
-	if (alice_db) {
-		if (!make_ext)
-			printf("FAIL: bogus extension created for IMSI %s\n",
-			       imsi);
-		COMPARE(alice, alice_db);
-		SUBSCR_PUT(alice_db);
-	} else if (make_ext)
-		printf("FAIL: no subscriber extension for IMSI %s\n", imsi);
-	SUBSCR_PUT(alice);
-}
-
-int main()
-{
-	printf("Testing subscriber database code.\n");
-	osmo_init_logging(&log_info);
-	log_set_print_filename(osmo_stderr_target, 0);
-
-	dummy_net.subscr_group = &dummy_sgrp;
-	dummy_sgrp.net         = &dummy_net;
-
-	if (db_init("hlr.sqlite3")) {
-		printf("DB: Failed to init database. Please check the option settings.\n");
-		return 1;
-	}	 
-	printf("DB: Database initialized.\n");
-
-	if (db_prepare()) {
-		printf("DB: Failed to prepare database.\n");
-		return 1;
-	}
-	printf("DB: Database prepared.\n");
-
-	struct gsm_subscriber *alice = NULL;
-	struct gsm_subscriber *alice_db;
-
-	char *alice_imsi = "3243245432345";
-	alice = db_create_subscriber(alice_imsi, GSM_MIN_EXTEN, GSM_MAX_EXTEN,
-				     true);
-	db_sync_subscriber(alice);
-	alice_db = db_get_subscriber(GSM_SUBSCRIBER_IMSI, alice->imsi);
-	COMPARE(alice, alice_db);
-	SUBSCR_PUT(alice_db);
-	SUBSCR_PUT(alice);
-
-	test_subs("3693245423445", "1234567890", NULL, true);
-	test_subs("9993245423445", "1234567890", "6543560920", true);
-	test_subs("3123122223445", "1234567890", NULL, false);
-	test_subs("9123121223445", "1234567890", "6543560920", false);
-
-	/* create it again and see it fails */
-	alice = db_create_subscriber(alice_imsi, GSM_MIN_EXTEN, GSM_MAX_EXTEN,
-				     true);
-	OSMO_ASSERT(!alice);
-
-	test_sms();
-	test_sms_migrate();
-
-	db_fini();
-
-	printf("Done\n");
-	return 0;
-}
-
-/* stubs */
-void vty_out() {}
-void vlr_subscr_disconnected() {}
-void vlr_subscr_rx_tmsi_reall_compl() {}
-void vlr_subscr_rx_id_resp() {}
-void vlr_subscr_rx_auth_resp() {}
-void vlr_loc_update() {}
-void vlr_proc_acc_req() {}
-void vlr_init() {}
-unsigned int mgcpgw_client_next_endpoint(struct mgcpgw_client *client)
-{ return 0; }
-struct msgb *mgcp_msg_crcx(struct mgcpgw_client *mgcp,
-			   uint16_t rtp_endpoint, unsigned int call_id,
-			   enum mgcp_connection_mode mode)
-{ return NULL; }
-struct msgb *mgcp_msg_mdcx(struct mgcpgw_client *mgcp,
-			   uint16_t rtp_endpoint, const char *rtp_conn_addr,
-			   uint16_t rtp_port, enum mgcp_connection_mode mode)
-{ return NULL; }
-int mgcpgw_client_tx(struct mgcpgw_client *mgcp, struct msgb *msg,
-		     mgcp_response_cb_t response_cb, void *priv)
-{ return -EINVAL; }
-const char *mgcpgw_client_remote_addr_str(struct mgcpgw_client *mgcp)
-{ return "0.0.0.0"; }
-uint32_t mgcpgw_client_remote_addr_n(struct mgcpgw_client *mgcp)
-{ return 0; }
-int mgcp_response_parse_params(struct mgcp_response *r)
-{ return -EINVAL; }
-struct RANAP_Cause;
-int iu_tx_release(struct ue_conn_ctx *ctx, const struct RANAP_Cause *cause)
-{ return 0; }
diff --git a/tests/db/db_test.err b/tests/db/db_test.err
deleted file mode 100644
index 27e5703..0000000
--- a/tests/db/db_test.err
+++ /dev/null
@@ -1,3 +0,0 @@
-Going to migrate from revision 3
-Going to migrate from revision 4
-
\ No newline at end of file
diff --git a/tests/db/db_test.ok b/tests/db/db_test.ok
deleted file mode 100644
index 2632a8c..0000000
--- a/tests/db/db_test.ok
+++ /dev/null
@@ -1,4 +0,0 @@
-Testing subscriber database code.
-DB: Database initialized.
-DB: Database prepared.
-Done
diff --git a/tests/db/hlr.sqlite3 b/tests/db/hlr.sqlite3
deleted file mode 100644
index e59dcdc..0000000
--- a/tests/db/hlr.sqlite3
+++ /dev/null
Binary files differ
diff --git a/tests/gbproxy/Makefile.am b/tests/gbproxy/Makefile.am
deleted file mode 100644
index 2dd66df..0000000
--- a/tests/gbproxy/Makefile.am
+++ /dev/null
@@ -1,54 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	-ggdb3 \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(COVERAGE_LDFLAGS) \
-	$(NULL)
-
-EXTRA_DIST = \
-	gbproxy_test.ok \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	gbproxy_test \
-	$(NULL)
-
-gbproxy_test_SOURCES = \
-	gbproxy_test.c \
-	$(NULL)
-
-gbproxy_test_LDFLAGS = \
-	-Wl,--wrap=RAND_bytes \
-	$(NULL)
-
-gbproxy_test_LDADD = \
-	$(top_builddir)/src/gprs/gb_proxy.o \
-	$(top_builddir)/src/gprs/gb_proxy_patch.o \
-	$(top_builddir)/src/gprs/gb_proxy_peer.o \
-	$(top_builddir)/src/gprs/gb_proxy_tlli.o \
-	$(top_builddir)/src/gprs/gprs_gb_parse.o \
-	$(top_builddir)/src/gprs/gprs_llc_parse.o \
-	$(top_builddir)/src/gprs/crc24.o \
-	$(top_builddir)/src/gprs/gprs_utils.o \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGB_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOVTY_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	$(LIBRARY_DL) \
-	$(LIBCRYPTO_LIBS) \
-	-lrt \
-	$(NULL)
diff --git a/tests/gbproxy/gbproxy_test.c b/tests/gbproxy/gbproxy_test.c
deleted file mode 100644
index 577daa9..0000000
--- a/tests/gbproxy/gbproxy_test.c
+++ /dev/null
@@ -1,4971 +0,0 @@
-/* test routines for gbproxy
- * send NS messages to the gbproxy and dumps what happens
- * (C) 2013 by sysmocom s.f.m.c. GmbH
- * Author: Jacob Erlbeck <jerlbeck@sysmocom.de>
- */
-
-#undef _GNU_SOURCE
-#define _GNU_SOURCE
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <getopt.h>
-#include <dlfcn.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/application.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/logging.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/signal.h>
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
-#include <osmocom/gprs/gprs_msgb.h>
-#include <osmocom/gprs/gprs_ns.h>
-#include <osmocom/gprs/gprs_bssgp.h>
-
-#include <openbsc/gb_proxy.h>
-#include <openbsc/gprs_utils.h>
-#include <openbsc/gprs_llc.h>
-#include <openbsc/gprs_gb_parse.h>
-#include <openbsc/debug.h>
-
-#include <openssl/rand.h>
-
-#define REMOTE_BSS_ADDR 0x01020304
-#define REMOTE_SGSN_ADDR 0x05060708
-
-#define SGSN_NSEI 0x0100
-
-#define REMOTE_SGSN2_ADDR 0x15161718
-#define SGSN2_NSEI 0x0102
-
-#define MATCH_ANY (-1)
-
-struct gbproxy_config gbcfg = {0};
-
-struct llist_head *received_messages = NULL;
-
-/* override, requires '-Wl,--wrap=RAND_bytes' */
-int __real_RAND_bytes(unsigned char *buf, int num);
-int mock_RAND_bytes(unsigned char *buf, int num);
-int (*RAND_bytes_cb)(unsigned char *, int) =
-  &mock_RAND_bytes;
-
-int __wrap_RAND_bytes(unsigned char *buf, int num)
-{
-	return (*RAND_bytes_cb)(buf, num);
-}
-
-static int rand_seq_num = 0;
-int mock_RAND_bytes(unsigned char *buf, int num)
-{
-	uint32_t val;
-
-	OSMO_ASSERT(num == sizeof(val));
-	OSMO_ASSERT(__real_RAND_bytes(buf, num) == 1);
-
-	val = 0x00dead00 + rand_seq_num;
-
-	rand_seq_num++;
-
-	memcpy(buf, &val, num);
-
-	return 1;
-}
-
-static void cleanup_test()
-{
-	rand_seq_num = 0;
-}
-
-static int dump_global(FILE *stream, int indent)
-{
-	unsigned int i;
-	const struct rate_ctr_group_desc *desc;
-	int rc;
-
-	rc = fprintf(stream, "%*sGbproxy global:\n", indent, "");
-	if (rc < 0)
-		return rc;
-
-	desc = gbcfg.ctrg->desc;
-
-	for (i = 0; i < desc->num_ctr; i++) {
-		struct rate_ctr *ctr = &gbcfg.ctrg->ctr[i];
-		if (ctr->current) {
-			rc = fprintf(stream, "%*s    %s: %llu\n",
-				     indent, "",
-				     desc->ctr_desc[i].description,
-				     (long long)ctr->current);
-
-			if (rc < 0)
-				return rc;
-		}
-	}
-
-	return 0;
-}
-
-static int dump_peers(FILE *stream, int indent, time_t now,
-		      struct gbproxy_config *cfg)
-{
-	struct gbproxy_peer *peer;
-	struct gprs_ra_id raid;
-	unsigned int i;
-	const struct rate_ctr_group_desc *desc;
-	int rc;
-
-	rc = fprintf(stream, "%*sPeers:\n", indent, "");
-	if (rc < 0)
-		return rc;
-
-	llist_for_each_entry(peer, &cfg->bts_peers, list) {
-		struct gbproxy_link_info *link_info;
-		struct gbproxy_patch_state *state = &peer->patch_state;
-		gsm48_parse_ra(&raid, peer->ra);
-
-		rc = fprintf(stream, "%*s  NSEI %u, BVCI %u, %sblocked, "
-			     "RAI %u-%u-%u-%u\n",
-			     indent, "",
-			     peer->nsei, peer->bvci,
-			     peer->blocked ? "" : "not ",
-			     raid.mcc, raid.mnc, raid.lac, raid.rac);
-
-		if (rc < 0)
-			return rc;
-
-		desc = peer->ctrg->desc;
-
-		for (i = 0; i < desc->num_ctr; i++) {
-			struct rate_ctr *ctr = &peer->ctrg->ctr[i];
-			if (ctr->current) {
-				rc = fprintf(stream, "%*s    %s: %llu\n",
-					     indent, "",
-					     desc->ctr_desc[i].description,
-					     (long long)ctr->current);
-
-				if (rc < 0)
-					return rc;
-			}
-		}
-
-		fprintf(stream, "%*s    TLLI-Cache: %d\n",
-			indent, "", state->logical_link_count);
-		llist_for_each_entry(link_info, &state->logical_links, list) {
-			char mi_buf[200];
-			time_t age = now ? now - link_info->timestamp : 0;
-			int stored_msgs = 0;
-			struct llist_head *iter;
-			enum gbproxy_match_id match_id;
-			llist_for_each(iter, &link_info->stored_msgs)
-				stored_msgs++;
-
-			if (link_info->imsi_len > 0) {
-				snprintf(mi_buf, sizeof(mi_buf), "(invalid)");
-				gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
-						   link_info->imsi,
-						   link_info->imsi_len);
-			} else {
-				snprintf(mi_buf, sizeof(mi_buf), "(none)");
-			}
-			fprintf(stream, "%*s      TLLI %08x",
-				     indent, "", link_info->tlli.current);
-			if (link_info->tlli.assigned)
-				fprintf(stream, "/%08x", link_info->tlli.assigned);
-			if (link_info->sgsn_tlli.current) {
-				fprintf(stream, " -> %08x",
-					link_info->sgsn_tlli.current);
-				if (link_info->sgsn_tlli.assigned)
-					fprintf(stream, "/%08x",
-						link_info->sgsn_tlli.assigned);
-			}
-			fprintf(stream, ", IMSI %s, AGE %d",
-				mi_buf, (int)age);
-
-			if (stored_msgs)
-				fprintf(stream, ", STORED %d", stored_msgs);
-
-			for (match_id = 0; match_id < ARRAY_SIZE(cfg->matches);
-			     ++match_id) {
-				if (cfg->matches[match_id].enable &&
-				    link_info->is_matching[match_id]) {
-					fprintf(stream, ", IMSI matches");
-					break;
-				}
-			}
-
-			if (link_info->imsi_acq_pending)
-				fprintf(stream, ", IMSI acquisition in progress");
-
-			if (cfg->route_to_sgsn2)
-				fprintf(stream, ", SGSN NSEI %d",
-					link_info->sgsn_nsei);
-
-			if (link_info->is_deregistered)
-				fprintf(stream, ", DE-REGISTERED");
-
-			rc = fprintf(stream, "\n");
-			if (rc < 0)
-				return rc;
-		}
-	}
-
-	return 0;
-}
-
-const uint8_t *convert_ra(struct gprs_ra_id *raid)
-{
-	static uint8_t buf[6];
-	gsm48_construct_ra(buf, raid);
-	return buf;
-}
-
-/* DTAP - Attach Request */
-static const unsigned char dtap_attach_req[] = {
-	0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
-	0x05, 0xf4, 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22,
-	0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43,
-	0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a,
-	0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
-	0xc6, 0x62, 0x00, 0x60, 0x80, 0x00,
-};
-
-/* DTAP - Attach Request (invalid RAI) */
-static const unsigned char dtap_attach_req2[] = {
-	0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
-	0x05, 0xf4, 0xfb, 0x00, 0xbe, 0xef, 0x99, 0x99,
-	0x99, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43,
-	0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a,
-	0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
-	0xc6, 0x62, 0x00, 0x60, 0x80, 0x00,
-};
-
-/* DTAP - Attach Request (P-TMSI 0x3f32b700) */
-static const unsigned char dtap_attach_req3[] = {
-	0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
-	0x05, 0xf4, 0xef, 0xe2, 0xb7, 0x00, 0x11, 0x22,
-	0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43,
-	0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a,
-	0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
-	0xc6, 0x62, 0x00, 0x60, 0x80, 0x00,
-};
-
-/* DTAP - Attach Request (IMSI 12131415161718) */
-static const unsigned char dtap_attach_req4[] = {
-	0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
-	0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-	0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
-	0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
-	0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
-	0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
-	0x00,
-};
-
-/* DTAP - Identity Request */
-static const unsigned char dtap_identity_req[] = {
-	0x08, 0x15, 0x01
-};
-
-/* DTAP - Identity Response */
-static const unsigned char dtap_identity_resp[] = {
-	0x08, 0x16, 0x08, 0x11, 0x12, 0x13, 0x14, 0x15,
-	0x16, 0x17, 0x18
-};
-
-/* DTAP - Identity Response, IMSI 2 */
-static const unsigned char dtap_identity2_resp[] = {
-	0x08, 0x16, 0x08, 0x11, 0x12, 0x99, 0x99, 0x99,
-	0x16, 0x17, 0x18
-};
-
-/* DTAP - Identity Response, IMSI 3 */
-static const unsigned char dtap_identity3_resp[] = {
-	0x08, 0x16, 0x08, 0x11, 0x12, 0x99, 0x99, 0x99,
-	0x26, 0x27, 0x28
-};
-
-/* DTAP - Attach Accept */
-static const unsigned char dtap_attach_acc[] = {
-	0x08, 0x02, 0x01, 0x49, 0x04, 0x21, 0x63, 0x54,
-	0x40, 0x50, 0x60, 0x19, 0xcd, 0xd7, 0x08, 0x17,
-	0x16, 0x18, 0x05, 0xf4, 0xef, 0xe2, 0xb7, 0x00
-};
-
-/* DTAP - Attach Accept, P-TMSI 2 */
-static const unsigned char dtap_attach_acc2[] = {
-	0x08, 0x02, 0x01, 0x49, 0x04, 0x21, 0x63, 0x54,
-	0x40, 0x50, 0x60, 0x19, 0xcd, 0xd7, 0x08, 0x17,
-	0x16, 0x18, 0x05, 0xf4, 0xe0, 0x98, 0x76, 0x54
-};
-
-/* DTAP - Attach Complete */
-static const unsigned char dtap_attach_complete[] = {
-	0x08, 0x03
-};
-
-/* DTAP - Attach Reject (GPRS services not allowed) */
-static const unsigned char dtap_attach_rej7[] = {
-	0x08, 0x04, 0x07
-};
-
-/* DTAP - GMM Information */
-static const unsigned char dtap_gmm_information[] = {
-	0x08, 0x21
-};
-
-/* DTAP - Routing Area Update Request */
-static const unsigned char dtap_ra_upd_req[] = {
-	0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
-	0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
-	0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
-	0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
-	0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
-	0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
-	0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
-};
-
-/* DTAP - Routing Area Update Accept */
-static const unsigned char dtap_ra_upd_acc[] = {
-	0x08, 0x09, 0x00, 0x49, 0x21, 0x63, 0x54,
-	0x40, 0x50, 0x60, 0x19, 0x54, 0xab, 0xb3, 0x18,
-	0x05, 0xf4, 0xef, 0xe2, 0xb7, 0x00, 0x17, 0x16,
-};
-
-/* DTAP - Routing Area Update Accept, P-TMSI 2 */
-static const unsigned char dtap_ra_upd_acc2[] = {
-	0x08, 0x09, 0x00, 0x49, 0x21, 0x63, 0x54,
-	0x40, 0x50, 0x60, 0x19, 0x54, 0xab, 0xb3, 0x18,
-	0x05, 0xf4, 0xe0, 0x98, 0x76, 0x54, 0x17, 0x16,
-};
-
-/* DTAP - Routing Area Update Accept, P-TMSI 3 */
-static const unsigned char dtap_ra_upd_acc3[] = {
-	0x08, 0x09, 0x00, 0x49, 0x21, 0x63, 0x54,
-	0x40, 0x50, 0x60, 0x19, 0x54, 0xab, 0xb3, 0x18,
-	0x05, 0xf4, 0xe0, 0x54, 0x32, 0x10, 0x17, 0x16,
-};
-
-/* DTAP - Routing Area Update Complete */
-static const unsigned char dtap_ra_upd_complete[] = {
-	0x08, 0x0a
-};
-
-/* DTAP - Routing Area Update Reject */
-/* cause = 10 ("Implicitly detached"), force_standby = 0 */
-static const unsigned char dtap_ra_upd_rej[] = {
-	0x08, 0x0b, 0x0a, 0x00,
-};
-
-/* DTAP - Activate PDP Context Request */
-static const unsigned char dtap_act_pdp_ctx_req[] = {
-	0x0a, 0x41, 0x05, 0x03, 0x0c, 0x00,
-	0x00, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x02, 0x01, 0x21, 0x28, 0x03,
-	0x02, 0x61, 0x62, 0x27, 0x14, 0x80, 0x80, 0x21,
-	0x10, 0x01, 0x00, 0x00, 0x10, 0x81, 0x06, 0x00,
-	0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x00,
-	0x00
-};
-
-/* DTAP - Detach Request (MO) */
-/* normal detach, power_off = 1 */
-static const unsigned char dtap_detach_po_req[] = {
-	0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
-	0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
-};
-
-/* DTAP - Detach Request (MO) */
-/* normal detach, power_off = 0 */
-static const unsigned char dtap_detach_req[] = {
-	0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
-	0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
-};
-
-/* DTAP - Detach Accept (MO) */
-static const unsigned char dtap_detach_acc[] = {
-	0x08, 0x06, 0x00
-};
-
-/* DTAP - Detach Request (MT) */
-/* normal detach, reattach required, implicitly detached */
-static const unsigned char dtap_mt_detach_rea_req[] = {
-	0x08, 0x05, 0x01, 0x25, 0x0a
-};
-
-/* DTAP - Detach Request (MT) */
-/* normal detach, reattach not required, implicitly detached */
-static const unsigned char dtap_mt_detach_req[] = {
-	0x08, 0x05, 0x02, 0x25, 0x0a
-};
-
-/* DTAP - Detach Accept (MT) */
-static const unsigned char dtap_mt_detach_acc[] = {
-	0x08, 0x06
-};
-
-/* GPRS-LLC - SAPI: LLGMM, U, XID */
-static const unsigned char llc_u_xid_ul[] = {
-	0x41, 0xfb, 0x01, 0x00, 0x0e, 0x00, 0x64, 0x11,
-	0x05, 0x16, 0x01, 0x90, 0x66, 0xb3, 0x28
-};
-
-/* GPRS-LLC - SAPI: LLGMM, U, XID */
-static const unsigned char llc_u_xid_dl[] = {
-	0x41, 0xfb, 0x30, 0x84, 0x10, 0x61, 0xb6, 0x64,
-	0xe4, 0xa9, 0x1a, 0x9e
-};
-
-/* GPRS-LLC - SAPI: LL11, UI, NSAPI 5, DNS query */
-static const unsigned char llc_ui_ll11_dns_query_ul[] = {
-	0x0b, 0xc0, 0x01, 0x65, 0x00, 0x00, 0x00, 0x45,
-	0x00, 0x00, 0x38, 0x95, 0x72, 0x00, 0x00, 0x45,
-	0x11, 0x20, 0x85, 0x0a, 0xc0, 0x07, 0xe4, 0xac,
-	0x10, 0x01, 0x0a, 0xad, 0xab, 0x00, 0x35, 0x00,
-	0x24, 0x0e, 0x1c, 0x3b, 0xe0, 0x01, 0x00, 0x00,
-	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-	0x6d, 0x05, 0x68, 0x65, 0x69, 0x73, 0x65, 0x02,
-	0x64, 0x65, 0x00, 0x00, 0x01, 0x00, 0x01, 0x47,
-	0x8f, 0x07
-};
-
-/* GPRS-LLC - SAPI: LL11, UI, NSAPI 5, DNS query */
-static const unsigned char llc_ui_ll11_dns_resp_dl[] = {
-	0x4b, 0xc0, 0x01, 0x65, 0x00, 0x00, 0x00, 0x45,
-	0x00, 0x00, 0xc6, 0x00, 0x00, 0x40, 0x00, 0x3e,
-	0x11, 0x7c, 0x69, 0xac, 0x10, 0x01, 0x0a, 0x0a,
-	0xc0, 0x07, 0xe4, 0x00, 0x35, 0xad, 0xab, 0x00,
-	0xb2, 0x74, 0x4e, 0x3b, 0xe0, 0x81, 0x80, 0x00,
-	0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x01,
-	0x6d, 0x05, 0x68, 0x65, 0x69, 0x73, 0x65, 0x02,
-	0x64, 0x65, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0,
-	0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0e,
-	0x10, 0x00, 0x04, 0xc1, 0x63, 0x90, 0x58, 0xc0,
-	0x0e, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x0e,
-	0x10, 0x00, 0x16, 0x03, 0x6e, 0x73, 0x32, 0x0c,
-	0x70, 0x6f, 0x70, 0x2d, 0x68, 0x61, 0x6e, 0x6e,
-	0x6f, 0x76, 0x65, 0x72, 0x03, 0x6e, 0x65, 0x74,
-	0x00, 0xc0, 0x0e, 0x00, 0x02, 0x00, 0x01, 0x00,
-	0x00, 0x0e, 0x10, 0x00, 0x10, 0x02, 0x6e, 0x73,
-	0x01, 0x73, 0x08, 0x70, 0x6c, 0x75, 0x73, 0x6c,
-	0x69, 0x6e, 0x65, 0xc0, 0x14, 0xc0, 0x0e, 0x00,
-	0x02, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10, 0x00,
-	0x05, 0x02, 0x6e, 0x73, 0xc0, 0x0e, 0xc0, 0x0e,
-	0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10,
-	0x00, 0x05, 0x02, 0x6e, 0x73, 0xc0, 0x5f, 0xc0,
-	0x0e, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x0e,
-	0x10, 0x00, 0x12, 0x02, 0x6e, 0x73, 0x0c, 0x70,
-	0x6f, 0x70, 0x2d, 0x68, 0x61, 0x6e, 0x6e, 0x6f,
-	0x76, 0x65, 0x72, 0xc0, 0x14, 0xaa, 0xdf, 0x31
-};
-
-static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text,
-				struct sockaddr_in *peer, const unsigned char* data,
-				size_t data_len);
-
-static void send_ns_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
-			  enum ns_cause cause, uint16_t nsvci, uint16_t nsei)
-{
-	/* GPRS Network Service, PDU type: NS_RESET,
-	 */
-	unsigned char msg[12] = {
-		0x02, 0x00, 0x81, 0x01, 0x01, 0x82, 0x11, 0x22,
-		0x04, 0x82, 0x11, 0x22
-	};
-
-	msg[3] = cause;
-	msg[6] = nsvci / 256;
-	msg[7] = nsvci % 256;
-	msg[10] = nsei / 256;
-	msg[11] = nsei % 256;
-
-	gprs_process_message(nsi, "RESET", src_addr, msg, sizeof(msg));
-}
-
-static void send_ns_reset_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
-			      uint16_t nsvci, uint16_t nsei)
-{
-	/* GPRS Network Service, PDU type: NS_RESET_ACK,
-	 */
-	unsigned char msg[9] = {
-		0x03, 0x01, 0x82, 0x11, 0x22,
-		0x04, 0x82, 0x11, 0x22
-	};
-
-	msg[3] = nsvci / 256;
-	msg[4] = nsvci % 256;
-	msg[7] = nsei / 256;
-	msg[8] = nsei % 256;
-
-	gprs_process_message(nsi, "RESET_ACK", src_addr, msg, sizeof(msg));
-}
-
-static void send_ns_alive(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
-{
-	/* GPRS Network Service, PDU type: NS_ALIVE */
-	unsigned char msg[1] = {
-		0x0a
-	};
-
-	gprs_process_message(nsi, "ALIVE", src_addr, msg, sizeof(msg));
-}
-
-static void send_ns_alive_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
-{
-	/* GPRS Network Service, PDU type: NS_ALIVE_ACK */
-	unsigned char msg[1] = {
-		0x0b
-	};
-
-	gprs_process_message(nsi, "ALIVE_ACK", src_addr, msg, sizeof(msg));
-}
-
-static void send_ns_unblock(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
-{
-	/* GPRS Network Service, PDU type: NS_UNBLOCK */
-	unsigned char msg[1] = {
-		0x06
-	};
-
-	gprs_process_message(nsi, "UNBLOCK", src_addr, msg, sizeof(msg));
-}
-
-static void send_ns_unblock_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
-{
-	/* GPRS Network Service, PDU type: NS_UNBLOCK_ACK */
-	unsigned char msg[1] = {
-		0x07
-	};
-
-	gprs_process_message(nsi, "UNBLOCK_ACK", src_addr, msg, sizeof(msg));
-}
-
-static void send_ns_unitdata(struct gprs_ns_inst *nsi, const char *text,
-			     struct sockaddr_in *src_addr, uint16_t nsbvci,
-			     const unsigned char *bssgp_msg, size_t bssgp_msg_size)
-{
-	/* GPRS Network Service, PDU type: NS_UNITDATA */
-	unsigned char msg[4096] = {
-		0x00, 0x00, 0x00, 0x00
-	};
-
-	OSMO_ASSERT(bssgp_msg_size <= sizeof(msg) - 4);
-
-	msg[2] = nsbvci / 256;
-	msg[3] = nsbvci % 256;
-	memcpy(msg + 4, bssgp_msg, bssgp_msg_size);
-
-	gprs_process_message(nsi, text ? text : "UNITDATA", src_addr, msg, bssgp_msg_size + 4);
-}
-
-static void send_bssgp_ul_unitdata(
-	struct gprs_ns_inst *nsi, const char *text,
-	struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
-	struct gprs_ra_id *raid, uint16_t cell_id,
-	const uint8_t *llc_msg, size_t llc_msg_size)
-{
-	/* GPRS Network Service, PDU type: NS_UNITDATA */
-	/* Base Station Subsystem GPRS Protocol: UL_UNITDATA */
-	unsigned char msg[4096] = {
-		0x01, /* TLLI */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
-		0x08, 0x88, /* RAI */ 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
-		/* CELL ID */ 0x00, 0x00, 0x00, 0x80, 0x0e, /* LLC LEN */ 0x00, 0x00,
-	};
-
-	size_t bssgp_msg_size = 23 + llc_msg_size;
-
-	OSMO_ASSERT(bssgp_msg_size <= sizeof(msg));
-
-	gsm48_construct_ra(msg + 10, raid);
-	msg[1] = (uint8_t)(tlli >> 24);
-	msg[2] = (uint8_t)(tlli >> 16);
-	msg[3] = (uint8_t)(tlli >> 8);
-	msg[4] = (uint8_t)(tlli >> 0);
-	msg[16] = cell_id / 256;
-	msg[17] = cell_id % 256;
-	msg[21] = llc_msg_size / 256;
-	msg[22] = llc_msg_size % 256;
-	memcpy(msg + 23, llc_msg, llc_msg_size);
-
-	send_ns_unitdata(nsi, text ? text : "BSSGP UL UNITDATA",
-			 src_addr, nsbvci, msg, bssgp_msg_size);
-}
-
-static void send_bssgp_dl_unitdata(
-	struct gprs_ns_inst *nsi, const char *text,
-	struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
-	int with_racap_drx, const uint8_t *imsi, size_t imsi_size,
-	const uint8_t *llc_msg, size_t llc_msg_size)
-{
-	/* Base Station Subsystem GPRS Protocol: DL_UNITDATA */
-	unsigned char msg[4096] = {
-		0x00, /* TLLI */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x20,
-		0x16, 0x82, 0x02, 0x58,
-	};
-	unsigned char racap_drx[] = {
-		0x13, 0x99, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96,
-		0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62,
-		0x00, 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00,
-		0x60, 0x80, 0x00, 0x0a, 0x82, 0x08, 0x02
-	};
-
-	size_t bssgp_msg_size = 0;
-
-	OSMO_ASSERT(51 + imsi_size + llc_msg_size <= sizeof(msg));
-
-	msg[1] = (uint8_t)(tlli >> 24);
-	msg[2] = (uint8_t)(tlli >> 16);
-	msg[3] = (uint8_t)(tlli >> 8);
-	msg[4] = (uint8_t)(tlli >> 0);
-
-	bssgp_msg_size = 12;
-
-	if (with_racap_drx) {
-		memcpy(msg + bssgp_msg_size, racap_drx, sizeof(racap_drx));
-		bssgp_msg_size += sizeof(racap_drx);
-	}
-
-	if (imsi) {
-		OSMO_ASSERT(imsi_size <= 127);
-		msg[bssgp_msg_size] = BSSGP_IE_IMSI;
-		msg[bssgp_msg_size + 1] = 0x80 | imsi_size;
-		memcpy(msg + bssgp_msg_size + 2, imsi, imsi_size);
-		bssgp_msg_size += 2 + imsi_size;
-	}
-
-	if ((bssgp_msg_size % 4) != 0) {
-		size_t abytes = (4 - (bssgp_msg_size + 2) % 4) % 4;
-		msg[bssgp_msg_size] = BSSGP_IE_ALIGNMENT;
-		msg[bssgp_msg_size + 1] = 0x80 | abytes;
-		memset(msg + bssgp_msg_size + 2, 0, abytes);
-		bssgp_msg_size += 2 + abytes;
-	}
-
-	msg[bssgp_msg_size] = BSSGP_IE_LLC_PDU;
-	if (llc_msg_size < 128) {
-		msg[bssgp_msg_size + 1] = 0x80 | llc_msg_size;
-		bssgp_msg_size += 2;
-	} else {
-		msg[bssgp_msg_size + 1] = llc_msg_size / 256;
-		msg[bssgp_msg_size + 2] = llc_msg_size % 256;
-		bssgp_msg_size += 3;
-	}
-	memcpy(msg + bssgp_msg_size, llc_msg, llc_msg_size);
-	bssgp_msg_size += llc_msg_size;
-
-
-	send_ns_unitdata(nsi, text ? text : "BSSGP DL UNITDATA",
-			 src_addr, nsbvci, msg, bssgp_msg_size);
-}
-
-static void send_bssgp_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
-			     uint16_t bvci)
-{
-	/* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0
-	 * BSSGP RESET */
-	unsigned char msg[18] = {
-		0x22, 0x04, 0x82, 0x4a,
-		0x2e, 0x07, 0x81, 0x08, 0x08, 0x88, 0x11, 0x22,
-		0x33, 0x40, 0x50, 0x60, 0x10, 0x00
-	};
-
-	msg[3] = bvci / 256;
-	msg[4] = bvci % 256;
-
-	send_ns_unitdata(nsi, "BVC_RESET", src_addr, 0, msg, sizeof(msg));
-}
-
-static void send_bssgp_reset_ack(struct gprs_ns_inst *nsi,
-				 struct sockaddr_in *src_addr, uint16_t bvci)
-{
-	/* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0
-	 * BSSGP RESET_ACK */
-	static unsigned char msg[5] = {
-		0x23, 0x04, 0x82, 0x00,
-		0x00
-	};
-
-	msg[3] = bvci / 256;
-	msg[4] = bvci % 256;
-
-	send_ns_unitdata(nsi, "BVC_RESET_ACK", src_addr, 0, msg, sizeof(msg));
-}
-
-static void send_bssgp_suspend(struct gprs_ns_inst *nsi,
-			       struct sockaddr_in *src_addr,
-			       uint32_t tlli,
-			       struct gprs_ra_id *raid)
-{
-	/* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND */
-	unsigned char msg[15] = {
-		0x0b, 0x1f, 0x84, /* TLLI */ 0xff, 0xff, 0xff, 0xff, 0x1b,
-		0x86, /* RAI */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-	};
-
-	msg[3] = (uint8_t)(tlli >> 24);
-	msg[4] = (uint8_t)(tlli >> 16);
-	msg[5] = (uint8_t)(tlli >> 8);
-	msg[6] = (uint8_t)(tlli >> 0);
-
-	gsm48_construct_ra(msg + 9, raid);
-
-	send_ns_unitdata(nsi, "BVC_SUSPEND", src_addr, 0, msg, sizeof(msg));
-}
-
-static void send_bssgp_suspend_ack(struct gprs_ns_inst *nsi,
-				   struct sockaddr_in *src_addr,
-				   uint32_t tlli,
-				   struct gprs_ra_id *raid)
-{
-	/* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND ACK */
-	unsigned char msg[18] = {
-		0x0c, 0x1f, 0x84, /* TLLI */ 0xff, 0xff, 0xff, 0xff, 0x1b,
-		0x86, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1d,
-		0x81, 0x01
-	};
-
-	msg[3] = (uint8_t)(tlli >> 24);
-	msg[4] = (uint8_t)(tlli >> 16);
-	msg[5] = (uint8_t)(tlli >> 8);
-	msg[6] = (uint8_t)(tlli >> 0);
-
-	gsm48_construct_ra(msg + 9, raid);
-
-	send_ns_unitdata(nsi, "BVC_SUSPEND_ACK", src_addr, 0, msg, sizeof(msg));
-}
-
-static void send_bssgp_llc_discarded(struct gprs_ns_inst *nsi,
-				     struct sockaddr_in *src_addr,
-				     uint16_t bvci, uint32_t tlli,
-				     unsigned n_frames, unsigned n_octets)
-{
-	/* Base Station Subsystem GPRS Protocol: LLC-DISCARDED (0x2c) */
-	unsigned char msg[] = {
-		0x2c, 0x1f, 0x84, /* TLLI */ 0xff, 0xff, 0xff, 0xff, 0x0f,
-		0x81, /* n frames */ 0xff, 0x04, 0x82, /* BVCI */ 0xff, 0xff, 0x25, 0x83,
-		/* n octets */ 0xff, 0xff, 0xff
-	};
-
-	msg[3] = (uint8_t)(tlli >> 24);
-	msg[4] = (uint8_t)(tlli >> 16);
-	msg[5] = (uint8_t)(tlli >> 8);
-	msg[6] = (uint8_t)(tlli >> 0);
-	msg[9] = (uint8_t)(n_frames);
-	msg[12] = (uint8_t)(bvci >> 8);
-	msg[13] = (uint8_t)(bvci >> 0);
-	msg[16] = (uint8_t)(n_octets >> 16);
-	msg[17] = (uint8_t)(n_octets >> 8);
-	msg[18] = (uint8_t)(n_octets >> 0);
-
-	send_ns_unitdata(nsi, "LLC_DISCARDED", src_addr, 0, msg, sizeof(msg));
-}
-
-static void send_bssgp_paging(struct gprs_ns_inst *nsi,
-			      struct sockaddr_in *src_addr,
-			      const uint8_t *imsi, size_t imsi_size,
-			      struct gprs_ra_id *raid, uint32_t ptmsi)
-{
-	/* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND */
-	unsigned char msg[100] = {
-		0x06,
-	};
-
-	const unsigned char drx_ie[] = {0x0a, 0x82, 0x07, 0x04};
-	const unsigned char qos_ie[] = {0x18, 0x83, 0x00, 0x00, 0x00};
-
-	size_t bssgp_msg_size = 1;
-
-	if (imsi) {
-		OSMO_ASSERT(imsi_size <= 127);
-		msg[bssgp_msg_size] = BSSGP_IE_IMSI;
-		msg[bssgp_msg_size + 1] = 0x80 | imsi_size;
-		memcpy(msg + bssgp_msg_size + 2, imsi, imsi_size);
-		bssgp_msg_size += 2 + imsi_size;
-	}
-
-	memcpy(msg + bssgp_msg_size, drx_ie, sizeof(drx_ie));
-	bssgp_msg_size += sizeof(drx_ie);
-
-	if (raid) {
-		msg[bssgp_msg_size] = BSSGP_IE_ROUTEING_AREA;
-		msg[bssgp_msg_size+1] = 0x86;
-		gsm48_construct_ra(msg + bssgp_msg_size + 2, raid);
-		bssgp_msg_size += 8;
-	}
-
-	memcpy(msg + bssgp_msg_size, qos_ie, sizeof(qos_ie));
-	bssgp_msg_size += sizeof(qos_ie);
-
-	if (ptmsi != GSM_RESERVED_TMSI) {
-		const uint32_t ptmsi_be = htonl(ptmsi);
-		msg[bssgp_msg_size] = BSSGP_IE_TMSI;
-		msg[bssgp_msg_size+1] = 0x84;
-		memcpy(msg + bssgp_msg_size + 2, &ptmsi_be, 4);
-		bssgp_msg_size += 6;
-	}
-
-	send_ns_unitdata(nsi, "PAGING_PS", src_addr, 0, msg, bssgp_msg_size);
-}
-
-static void send_bssgp_flow_control_bvc(struct gprs_ns_inst *nsi,
-					struct sockaddr_in *src_addr,
-					uint16_t bvci, uint8_t tag)
-{
-	/* GPRS Network Service, PDU type: NS_UNITDATA,
-	 * BSSGP FLOW_CONTROL_BVC */
-	unsigned char msg[] = {
-		0x26, 0x1e, 0x81, /* Tag */ 0xff, 0x05, 0x82, 0x01, 0xdc,
-		0x03, 0x82, 0x02, 0x76, 0x01, 0x82, 0x00, 0x50,
-		0x1c, 0x82, 0x02, 0x58, 0x06, 0x82, 0x00, 0x03
-	};
-
-	msg[3] = tag;
-
-	send_ns_unitdata(nsi, "FLOW_CONTROL_BVC", src_addr, bvci,
-			 msg, sizeof(msg));
-}
-
-static void send_bssgp_flow_control_bvc_ack(struct gprs_ns_inst *nsi,
-					    struct sockaddr_in *src_addr,
-					    uint16_t bvci, uint8_t tag)
-{
-	/* GPRS Network Service, PDU type: NS_UNITDATA,
-	 * BSSGP FLOW_CONTROL_BVC_ACK */
-	unsigned char msg[] = {
-		0x27, 0x1e, 0x81, /* Tag */ 0xce
-	};
-
-	msg[3] = tag;
-
-	send_ns_unitdata(nsi, "FLOW_CONTROL_BVC_ACK", src_addr, bvci,
-			 msg, sizeof(msg));
-}
-
-static void send_llc_ul_ui(
-	struct gprs_ns_inst *nsi, const char *text,
-	struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
-	struct gprs_ra_id *raid, uint16_t cell_id,
-	unsigned sapi, unsigned nu,
-	const uint8_t *msg, size_t msg_size)
-{
-	unsigned char llc_msg[4096] = {
-		0x00, 0xc0, 0x01
-	};
-
-	size_t llc_msg_size = 3 + msg_size + 3;
-	uint8_t e_bit = 0;
-	uint8_t pm_bit = 1;
-	unsigned fcs;
-
-	nu &= 0x01ff;
-
-	OSMO_ASSERT(llc_msg_size <= sizeof(llc_msg));
-
-	llc_msg[0] = (sapi & 0x0f);
-	llc_msg[1] = 0xc0 | (nu >> 6); /* UI frame */
-	llc_msg[2] = (nu << 2) | ((e_bit & 1) << 1) | (pm_bit & 1);
-
-	memcpy(llc_msg + 3, msg, msg_size);
-
-	fcs = gprs_llc_fcs(llc_msg, msg_size + 3);
-	llc_msg[3 + msg_size + 0] = (uint8_t)(fcs >> 0);
-	llc_msg[3 + msg_size + 1] = (uint8_t)(fcs >> 8);
-	llc_msg[3 + msg_size + 2] = (uint8_t)(fcs >> 16);
-
-	send_bssgp_ul_unitdata(nsi, text ? text : "LLC UI",
-			       src_addr, nsbvci, tlli, raid, cell_id,
-			       llc_msg, llc_msg_size);
-}
-
-static void send_llc_dl_ui(
-	struct gprs_ns_inst *nsi, const char *text,
-	struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
-	int with_racap_drx, const uint8_t *imsi, size_t imsi_size,
-	unsigned sapi, unsigned nu,
-	const uint8_t *msg, size_t msg_size)
-{
-	/* GPRS Network Service, PDU type: NS_UNITDATA */
-	/* Base Station Subsystem GPRS Protocol: UL_UNITDATA */
-	unsigned char llc_msg[4096] = {
-		0x00, 0x00, 0x01
-	};
-
-	size_t llc_msg_size = 3 + msg_size + 3;
-	uint8_t e_bit = 0;
-	uint8_t pm_bit = 1;
-	unsigned fcs;
-
-	nu &= 0x01ff;
-
-	OSMO_ASSERT(llc_msg_size <= sizeof(llc_msg));
-
-	llc_msg[0] = 0x40 | (sapi & 0x0f);
-	llc_msg[1] = 0xc0 | (nu >> 6); /* UI frame */
-	llc_msg[2] = (nu << 2) | ((e_bit & 1) << 1) | (pm_bit & 1);
-
-	memcpy(llc_msg + 3, msg, msg_size);
-
-	fcs = gprs_llc_fcs(llc_msg, msg_size + 3);
-	llc_msg[3 + msg_size + 0] = (uint8_t)(fcs >> 0);
-	llc_msg[3 + msg_size + 1] = (uint8_t)(fcs >> 8);
-	llc_msg[3 + msg_size + 2] = (uint8_t)(fcs >> 16);
-
-	send_bssgp_dl_unitdata(nsi, text ? text : "LLC UI",
-			       src_addr, nsbvci, tlli,
-			       with_racap_drx, imsi, imsi_size,
-			       llc_msg, llc_msg_size);
-}
-
-
-static void setup_ns(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
-		     uint16_t nsvci, uint16_t nsei)
-{
-	printf("Setup NS-VC: remote 0x%08x:%d, "
-	       "NSVCI 0x%04x(%d), NSEI 0x%04x(%d)\n\n",
-	       ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
-	       nsvci, nsvci, nsei, nsei);
-
-	send_ns_reset(nsi, src_addr, NS_CAUSE_OM_INTERVENTION, nsvci, nsei);
-	send_ns_alive(nsi, src_addr);
-	send_ns_unblock(nsi, src_addr);
-	send_ns_alive_ack(nsi, src_addr);
-}
-
-static void setup_bssgp(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
-		     uint16_t bvci)
-{
-	printf("Setup BSSGP: remote 0x%08x:%d, "
-	       "BVCI 0x%04x(%d)\n\n",
-	       ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
-	       bvci, bvci);
-
-	send_bssgp_reset(nsi, src_addr, bvci);
-}
-
-static void connect_sgsn(struct gprs_ns_inst *nsi, struct sockaddr_in *sgsn_peer,
-			 uint32_t sgsn_nsei)
-{
-	gprs_ns_nsip_connect(nsi, sgsn_peer, sgsn_nsei, sgsn_nsei+1);
-	send_ns_reset_ack(nsi, sgsn_peer, sgsn_nsei+1, sgsn_nsei);
-	send_ns_alive_ack(nsi, sgsn_peer);
-	send_ns_unblock_ack(nsi, sgsn_peer);
-	send_ns_alive(nsi, sgsn_peer);
-}
-
-static void configure_sgsn_peer(struct sockaddr_in *sgsn_peer)
-{
-	sgsn_peer->sin_family = AF_INET;
-	sgsn_peer->sin_port = htons(32000);
-	sgsn_peer->sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR);
-}
-
-static void configure_sgsn2_peer(struct sockaddr_in *sgsn_peer)
-{
-	sgsn_peer->sin_family = AF_INET;
-	sgsn_peer->sin_port = htons(32001);
-	sgsn_peer->sin_addr.s_addr = htonl(REMOTE_SGSN2_ADDR);
-}
-
-static void configure_bss_peers(struct sockaddr_in *bss_peers, size_t size)
-{
-	size_t i;
-
-	for (i = 0; i < size; ++i) {
-		bss_peers[i].sin_family = AF_INET;
-		bss_peers[i].sin_port = htons((i + 1) * 1111);
-		bss_peers[i].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR);
-	}
-}
-
-int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
-		   struct sockaddr_in *saddr, enum gprs_ns_ll ll);
-
-/* override */
-int gprs_ns_callback(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
-			 struct msgb *msg, uint16_t bvci)
-{
-	printf("CALLBACK, event %d, msg length %zu, bvci 0x%04x\n%s\n\n",
-			event, msgb_bssgp_len(msg), bvci,
-			osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
-
-	switch (event) {
-	case GPRS_NS_EVT_UNIT_DATA:
-		return gbprox_rcvmsg(&gbcfg, msg, nsvc->nsei, bvci, nsvc->nsvci);
-	default:
-		break;
-	}
-	return 0;
-}
-
-/* override */
-ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
-		const struct sockaddr *dest_addr, socklen_t addrlen)
-{
-	typedef ssize_t (*sendto_t)(int, const void *, size_t, int,
-			const struct sockaddr *, socklen_t);
-	static sendto_t real_sendto = NULL;
-	uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr);
-	int      dest_port = htons(((struct sockaddr_in *)dest_addr)->sin_port);
-
-	if (!real_sendto)
-		real_sendto = dlsym(RTLD_NEXT, "sendto");
-
-	if (dest_host == REMOTE_BSS_ADDR)
-		printf("MESSAGE to BSS at 0x%08x:%d, msg length %zu\n%s\n\n",
-		       dest_host, dest_port,
-		       len, osmo_hexdump(buf, len));
-	else if (dest_host == REMOTE_SGSN_ADDR)
-		printf("MESSAGE to SGSN at 0x%08x:%d, msg length %zu\n%s\n\n",
-		       dest_host, dest_port,
-		       len, osmo_hexdump(buf, len));
-	else if (dest_host == REMOTE_SGSN2_ADDR)
-		printf("MESSAGE to SGSN 2 at 0x%08x:%d, msg length %zu\n%s\n\n",
-		       dest_host, dest_port,
-		       len, osmo_hexdump(buf, len));
-	else
-		return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
-
-	return len;
-}
-
-/* override */
-int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg)
-{
-	typedef int (*gprs_ns_sendmsg_t)(struct gprs_ns_inst *nsi, struct msgb *msg);
-	static gprs_ns_sendmsg_t real_gprs_ns_sendmsg = NULL;
-	uint16_t bvci = msgb_bvci(msg);
-	uint16_t nsei = msgb_nsei(msg);
-
-	size_t len = msgb_length(msg);
-
-	if (!real_gprs_ns_sendmsg)
-		real_gprs_ns_sendmsg = dlsym(RTLD_NEXT, "gprs_ns_sendmsg");
-
-	if (nsei == SGSN_NSEI)
-		printf("NS UNITDATA MESSAGE to SGSN, BVCI 0x%04x, "
-		       "msg length %zu (%s)\n",
-		       bvci, len, __func__);
-	else if (nsei == SGSN2_NSEI)
-		printf("NS UNITDATA MESSAGE to SGSN 2, BVCI 0x%04x, "
-		       "msg length %zu (%s)\n",
-		       bvci, len, __func__);
-	else
-		printf("NS UNITDATA MESSAGE to BSS, BVCI 0x%04x, "
-		       "msg length %zu (%s)\n",
-		       bvci, len, __func__);
-
-	if (received_messages) {
-		struct msgb *msg_copy;
-		msg_copy = gprs_msgb_copy(msg, "received_messages");
-		llist_add_tail(&msg_copy->list, received_messages);
-	}
-
-	return real_gprs_ns_sendmsg(nsi, msg);
-}
-
-/* Get the next message from the receive FIFO
- *
- * \returns a pointer to the message which will be invalidated at the next call
- *          to expect_msg. Returns NULL, if there is no message left.
- */
-static struct msgb *expect_msg(void)
-{
-	static struct msgb *msg = NULL;
-
-	msgb_free(msg);
-	msg = NULL;
-
-	if (!received_messages)
-		return NULL;
-
-	if (llist_empty(received_messages))
-		return NULL;
-
-	msg = llist_entry(received_messages->next, struct msgb, list);
-	llist_del(&msg->list);
-
-	return msg;
-}
-
-struct expect_result {
-	struct msgb *msg;
-	struct gprs_gb_parse_context parse_ctx;
-};
-
-static struct expect_result *expect_bssgp_msg(
-	int match_nsei, int match_bvci, int match_pdu_type)
-{
-	static struct expect_result result;
-	static const struct expect_result empty_result = {0,};
-	static struct msgb *msg;
-	uint16_t nsei;
-	int rc;
-
-	memcpy(&result, &empty_result, sizeof(result));
-
-	msg = expect_msg();
-	if (!msg)
-		return NULL;
-
-	nsei = msgb_nsei(msg);
-
-	if (match_nsei != MATCH_ANY && match_nsei != nsei) {
-		fprintf(stderr, "%s: NSEI mismatch (expected %u, got %u)\n",
-			__func__, match_nsei, nsei);
-		return NULL;
-	}
-
-	if (match_bvci != MATCH_ANY && match_bvci != msgb_bvci(msg)) {
-		fprintf(stderr, "%s: BVCI mismatch (expected %u, got %u)\n",
-			__func__, match_bvci, msgb_bvci(msg));
-		return NULL;
-	}
-
-	result.msg = msg;
-
-	result.parse_ctx.to_bss = nsei != SGSN_NSEI && nsei != SGSN2_NSEI;
-	result.parse_ctx.peer_nsei = nsei;
-
-	if (!msgb_bssgph(msg)) {
-		fprintf(stderr, "%s: Expected BSSGP\n", __func__);
-		return NULL;
-	}
-
-	rc = gprs_gb_parse_bssgp(msgb_bssgph(msg), msgb_bssgp_len(msg),
-				 &result.parse_ctx);
-
-	if (!rc) {
-		fprintf(stderr, "%s: Failed to parse message\n", __func__);
-		return NULL;
-	}
-
-	if (match_pdu_type != MATCH_ANY &&
-	    match_pdu_type != result.parse_ctx.pdu_type) {
-		fprintf(stderr, "%s: PDU type mismatch (expected %u, got %u)\n",
-			__func__, match_pdu_type, result.parse_ctx.pdu_type);
-		return NULL;
-	}
-
-	return &result;
-}
-
-static struct expect_result *expect_llc_msg(
-	int match_nsei, int match_bvci, int match_sapi, int match_type)
-{
-	static struct expect_result *result;
-
-	result = expect_bssgp_msg(match_nsei, match_bvci, MATCH_ANY);
-	if (!result)
-		return NULL;
-
-	if (!result->parse_ctx.llc) {
-		fprintf(stderr, "%s: Expected LLC message\n", __func__);
-		return NULL;
-	}
-
-	if (match_sapi != MATCH_ANY &&
-	    match_sapi != result->parse_ctx.llc_hdr_parsed.sapi) {
-		fprintf(stderr, "%s: LLC SAPI mismatch (expected %u, got %u)\n",
-			__func__, match_sapi, result->parse_ctx.llc_hdr_parsed.sapi);
-		return NULL;
-	}
-
-	if (match_type != MATCH_ANY &&
-	    match_type != result->parse_ctx.llc_hdr_parsed.cmd) {
-		fprintf(stderr,
-			"%s: LLC command/type mismatch (expected %u, got %u)\n",
-			__func__, match_type, result->parse_ctx.llc_hdr_parsed.cmd);
-		return NULL;
-	}
-
-	return result;
-}
-
-static struct expect_result *expect_gmm_msg(int match_nsei, int match_bvci,
-					    int match_type)
-{
-	static struct expect_result *result;
-
-	result = expect_llc_msg(match_nsei, match_bvci, GPRS_SAPI_GMM, GPRS_LLC_UI);
-	if (!result)
-		return NULL;
-
-	if (!result->parse_ctx.g48_hdr) {
-		fprintf(stderr, "%s: Expected GSM 04.08 message\n", __func__);
-		return NULL;
-	}
-
-	if (match_type != MATCH_ANY &&
-	    match_type != result->parse_ctx.g48_hdr->msg_type) {
-		fprintf(stderr,
-			"%s: GSM 04.08 message type mismatch (expected %u, got %u)\n",
-			__func__, match_type, result->parse_ctx.g48_hdr->msg_type);
-		return NULL;
-	}
-
-	return result;
-}
-
-static void dump_rate_ctr_group(FILE *stream, const char *prefix,
-			    struct rate_ctr_group *ctrg)
-{
-	unsigned int i;
-
-	for (i = 0; i < ctrg->desc->num_ctr; i++) {
-		struct rate_ctr *ctr = &ctrg->ctr[i];
-		if (ctr->current && !strchr(ctrg->desc->ctr_desc[i].name, '.'))
-			fprintf(stream, " %s%s: %llu%s",
-				prefix, ctrg->desc->ctr_desc[i].description,
-				(long long)ctr->current,
-				"\n");
-	};
-}
-
-/* Signal handler for signals from NS layer */
-static int test_signal(unsigned int subsys, unsigned int signal,
-		  void *handler_data, void *signal_data)
-{
-	struct ns_signal_data *nssd = signal_data;
-	int rc;
-
-	if (subsys != SS_L_NS)
-		return 0;
-
-	switch (signal) {
-	case S_NS_RESET:
-		printf("==> got signal NS_RESET, NS-VC 0x%04x/%s\n",
-		       nssd->nsvc->nsvci,
-		       gprs_ns_ll_str(nssd->nsvc));
-		break;
-
-	case S_NS_ALIVE_EXP:
-		printf("==> got signal NS_ALIVE_EXP, NS-VC 0x%04x/%s\n",
-		       nssd->nsvc->nsvci,
-		       gprs_ns_ll_str(nssd->nsvc));
-		break;
-
-	case S_NS_BLOCK:
-		printf("==> got signal NS_BLOCK, NS-VC 0x%04x/%s\n",
-		       nssd->nsvc->nsvci,
-		       gprs_ns_ll_str(nssd->nsvc));
-		break;
-
-	case S_NS_UNBLOCK:
-		printf("==> got signal NS_UNBLOCK, NS-VC 0x%04x/%s\n",
-		       nssd->nsvc->nsvci,
-		       gprs_ns_ll_str(nssd->nsvc));
-		break;
-
-	case S_NS_REPLACED:
-		printf("==> got signal NS_REPLACED: 0x%04x/%s",
-		       nssd->nsvc->nsvci,
-		       gprs_ns_ll_str(nssd->nsvc));
-		printf(" -> 0x%04x/%s\n",
-		       nssd->old_nsvc->nsvci,
-		       gprs_ns_ll_str(nssd->old_nsvc));
-		break;
-
-	default:
-		printf("==> got signal %d, NS-VC 0x%04x/%s\n", signal,
-		       nssd->nsvc->nsvci,
-		       gprs_ns_ll_str(nssd->nsvc));
-		break;
-	}
-	printf("\n");
-	rc = gbprox_signal(subsys, signal, handler_data, signal_data);
-	return rc;
-}
-
-static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, size_t data_len)
-{
-	struct msgb *msg;
-	int ret;
-	if (data_len > NS_ALLOC_SIZE - NS_ALLOC_HEADROOM) {
-		fprintf(stderr, "message too long: %zu\n", data_len);
-		return -1;
-	}
-
-	msg = gprs_ns_msgb_alloc();
-	OSMO_ASSERT(msg);
-	memmove(msg->data, data, data_len);
-	msg->l2h = msg->data;
-	msgb_put(msg, data_len);
-
-	printf("PROCESSING %s from 0x%08x:%d\n%s\n\n",
-	       text, ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
-	       osmo_hexdump(data, data_len));
-
-	ret = gprs_ns_rcvmsg(nsi, msg, peer, GPRS_NS_LL_UDP);
-
-	printf("result (%s) = %d\n\n", text, ret);
-
-	msgb_free(msg);
-
-	return ret;
-}
-
-static void gprs_dump_nsi(struct gprs_ns_inst *nsi)
-{
-	struct gprs_nsvc *nsvc;
-
-	printf("Current NS-VCIs:\n");
-	llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
-		struct sockaddr_in *peer = &(nsvc->ip.bts_addr);
-		printf("    VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d%s%s\n",
-		       nsvc->nsvci, nsvc->nsei,
-		       ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
-		       nsvc->state & NSE_S_BLOCKED ? ", blocked" : "",
-		       nsvc->state & NSE_S_ALIVE   ? "" : ", dead"
-		      );
-		dump_rate_ctr_group(stdout, "        ", nsvc->ctrg);
-	}
-	printf("\n");
-}
-
-static void test_gbproxy()
-{
-	struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
-	struct sockaddr_in bss_peer[4] = {{0},};
-	struct sockaddr_in sgsn_peer= {0};
-
-	bssgp_nsi = nsi;
-	gbcfg.nsi = bssgp_nsi;
-	gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
-
-	configure_sgsn_peer(&sgsn_peer);
-	configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
-
-	printf("=== %s ===\n", __func__);
-	printf("--- Initialise SGSN ---\n\n");
-
-	connect_sgsn(nsi, &sgsn_peer, SGSN_NSEI);
-	gprs_dump_nsi(nsi);
-
-	printf("--- Initialise BSS 1 ---\n\n");
-
-	setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
-	setup_bssgp(nsi, &bss_peer[0], 0x1002);
-	gprs_dump_nsi(nsi);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
-
-	printf("--- Initialise BSS 2 ---\n\n");
-
-	setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000);
-	setup_bssgp(nsi, &bss_peer[1], 0x2002);
-	gprs_dump_nsi(nsi);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_bssgp_reset_ack(nsi, &sgsn_peer, 0x2002);
-
-	printf("--- Move BSS 1 to new port ---\n\n");
-
-	setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000);
-	gprs_dump_nsi(nsi);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
-
-	setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
-	gprs_dump_nsi(nsi);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Move BSS 1 to current BSS 2 port ---\n\n");
-
-	setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
-	gprs_dump_nsi(nsi);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Move BSS 2 to new port ---\n\n");
-
-	setup_ns(nsi, &bss_peer[3], 0x2001, 0x2000);
-	gprs_dump_nsi(nsi);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
-
-	setup_ns(nsi, &bss_peer[2], 0x2001, 0x2000);
-	gprs_dump_nsi(nsi);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Move BSS 1 to original BSS 1 port ---\n\n");
-
-	setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
-	gprs_dump_nsi(nsi);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Reset BSS 1 with a new BVCI ---\n\n");
-
-	setup_bssgp(nsi, &bss_peer[0], 0x1012);
-	gprs_dump_nsi(nsi);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1012);
-
-	printf("--- Reset BSS 1 with the old BVCI ---\n\n");
-
-	setup_bssgp(nsi, &bss_peer[0], 0x1002);
-	gprs_dump_nsi(nsi);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
-
-	printf("--- Reset BSS 1 with the old BVCI again ---\n\n");
-
-	setup_bssgp(nsi, &bss_peer[0], 0x1002);
-	gprs_dump_nsi(nsi);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
-
-	printf("--- Send message from BSS 1 to SGSN, BVCI 0x1012 ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
-
-	printf("--- Send message from SGSN to BSS 1, BVCI 0x1012 ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
-
-	printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
-
-	printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
-
-	printf("--- Send message from BSS 2 to SGSN, BVCI 0x2002 ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x2002, (uint8_t *)"", 0);
-
-	printf("--- Send message from SGSN to BSS 2, BVCI 0x2002 ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x2002, (uint8_t *)"", 0);
-
-	printf("--- Reset BSS 1 with the old BVCI on BSS2's link ---\n\n");
-
-	setup_bssgp(nsi, &bss_peer[2], 0x1002);
-	gprs_dump_nsi(nsi);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	dump_global(stdout, 0);
-
-	send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
-
-	printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
-
-	printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
-
-	printf("--- Send message from SGSN to BSS 1, BVCI 0x10ff (invalid) ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x10ff, (uint8_t *)"", 0);
-
-	/* Find peer */
-	OSMO_ASSERT(gbproxy_peer_by_bvci(&gbcfg, 0xeeee) == NULL);
-	OSMO_ASSERT(gbproxy_peer_by_bvci(&gbcfg, 0x1000) == NULL);
-	OSMO_ASSERT(gbproxy_peer_by_bvci(&gbcfg, 0x1012) != NULL);
-	OSMO_ASSERT(gbproxy_peer_by_nsei(&gbcfg, 0xeeee) == NULL);
-	OSMO_ASSERT(gbproxy_peer_by_nsei(&gbcfg, 0x1012) == NULL);
-	OSMO_ASSERT(gbproxy_peer_by_nsei(&gbcfg, 0x1000) != NULL);
-
-
-	/* Cleanup */
-	OSMO_ASSERT(gbproxy_cleanup_peers(&gbcfg, 0, 0) == 0);
-	OSMO_ASSERT(gbproxy_cleanup_peers(&gbcfg, 0x1000, 0xeeee) == 0);
-	OSMO_ASSERT(gbproxy_cleanup_peers(&gbcfg, 0, 0x1002) == 0);
-	OSMO_ASSERT(gbproxy_cleanup_peers(&gbcfg, 0x1000, 0x1012) == 1);
-	OSMO_ASSERT(gbproxy_cleanup_peers(&gbcfg, 0x1000, 0x1012) == 0);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	dump_global(stdout, 0);
-
-	gbprox_reset(&gbcfg);
-	gprs_ns_destroy(nsi);
-	nsi = NULL;
-}
-
-static void test_gbproxy_ident_changes()
-{
-	struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
-	struct sockaddr_in bss_peer[1] = {{0},};
-	struct sockaddr_in sgsn_peer= {0};
-	uint16_t nsei[2] = {0x1000, 0x2000};
-	uint16_t nsvci[2] = {0x1001, 0x2001};
-	uint16_t bvci[4] = {0x1002, 0x2002, 0x3002, 0x4002};
-
-	bssgp_nsi = nsi;
-	gbcfg.nsi = bssgp_nsi;
-	gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
-
-	configure_sgsn_peer(&sgsn_peer);
-	configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
-
-	printf("=== %s ===\n", __func__);
-	printf("--- Initialise SGSN ---\n\n");
-
-	connect_sgsn(nsi, &sgsn_peer, SGSN_NSEI);
-	gprs_dump_nsi(nsi);
-
-	printf("--- Initialise BSS 1 ---\n\n");
-
-	setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[0]);
-	gprs_dump_nsi(nsi);
-
-	printf("--- Setup BVCI 1 ---\n\n");
-
-	setup_bssgp(nsi, &bss_peer[0], bvci[0]);
-	send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Setup BVCI 2 ---\n\n");
-
-	setup_bssgp(nsi, &bss_peer[0], bvci[1]);
-	send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[1]);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
-	send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
-
-	printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
-	send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
-
-	printf("--- Change NSEI ---\n\n");
-
-	setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[1]);
-	gprs_dump_nsi(nsi);
-
-	printf("--- Setup BVCI 1 ---\n\n");
-
-	setup_bssgp(nsi, &bss_peer[0], bvci[0]);
-	send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Setup BVCI 3 ---\n\n");
-
-	setup_bssgp(nsi, &bss_peer[0], bvci[2]);
-	send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[2]);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
-	send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
-
-	printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
-	       " (should fail) ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
-	dump_peers(stdout, 0, 0, &gbcfg);
-	send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
-	send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
-
-	printf("--- Change NSVCI ---\n\n");
-
-	setup_ns(nsi, &bss_peer[0], nsvci[1], nsei[1]);
-	gprs_dump_nsi(nsi);
-
-	printf("--- Setup BVCI 1 ---\n\n");
-
-	setup_bssgp(nsi, &bss_peer[0], bvci[0]);
-	send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Setup BVCI 4 ---\n\n");
-
-	setup_bssgp(nsi, &bss_peer[0], bvci[3]);
-	send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[3]);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
-	send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
-
-	printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
-	       " (should fail) ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
-	dump_peers(stdout, 0, 0, &gbcfg);
-	send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
-	send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
-
-	printf("--- Send message from BSS 1 to SGSN and back, BVCI 4 ---\n\n");
-
-	send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[3], (uint8_t *)"", 0);
-	send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[3], (uint8_t *)"", 0);
-
-	dump_global(stdout, 0);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	gbprox_reset(&gbcfg);
-	gprs_ns_destroy(nsi);
-	nsi = NULL;
-}
-
-static void test_gbproxy_ra_patching()
-{
-	struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
-	struct sockaddr_in bss_peer[1] = {{0},};
-	struct sockaddr_in sgsn_peer= {0};
-	struct  gprs_ra_id rai_bss =
-		{.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
-	struct  gprs_ra_id rai_sgsn =
-		{.mcc = 123, .mnc = 456, .lac = 16464, .rac = 96};
-	struct  gprs_ra_id rai_unknown =
-		{.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
-	uint16_t cell_id = 0x7530;
-	const char *err_msg = NULL;
-	const uint32_t ptmsi = 0xefe2b700;
-	const uint32_t local_tlli = 0xefe2b700;
-	const uint32_t foreign_tlli = 0xbbc54679;
-	const uint32_t foreign_tlli2 = 0xbb00beef;
-	const uint8_t imsi[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};
-	const char *patch_re = "^9898|^121314";
-	struct gbproxy_link_info *link_info;
-	struct gbproxy_peer *peer;
-	LLIST_HEAD(rcv_list);
-	struct expect_result *expect_res;
-
-	OSMO_ASSERT(local_tlli == gprs_tmsi2tlli(ptmsi, TLLI_LOCAL));
-
-	bssgp_nsi = nsi;
-	gbcfg.nsi = bssgp_nsi;
-	gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
-	gbcfg.core_mcc = 123;
-	gbcfg.core_mnc = 456;
-	gbcfg.core_apn = talloc_zero_size(NULL, 100);
-	gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
-	gbcfg.patch_ptmsi = 0;
-
-	configure_sgsn_peer(&sgsn_peer);
-	configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
-
-	if (gbproxy_set_patch_filter(&gbcfg.matches[GBPROX_MATCH_PATCHING],
-				     patch_re, &err_msg) != 0) {
-		fprintf(stderr, "Failed to compile RE '%s': %s\n",
-			patch_re, err_msg);
-		exit(1);
-	}
-
-
-	printf("=== %s ===\n", __func__);
-	printf("--- Initialise SGSN ---\n\n");
-
-	connect_sgsn(nsi, &sgsn_peer, SGSN_NSEI);
-	gprs_dump_nsi(nsi);
-
-	printf("--- Initialise BSS 1 ---\n\n");
-
-	setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
-
-	received_messages = &rcv_list;
-
-	setup_bssgp(nsi, &bss_peer[0], 0x1002);
-	gprs_dump_nsi(nsi);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	peer = gbproxy_peer_by_nsei(&gbcfg, 0x1000);
-	OSMO_ASSERT(peer != NULL);
-
-	OSMO_ASSERT(expect_bssgp_msg(SGSN_NSEI, 0, BSSGP_PDUT_BVC_RESET));
-
-	send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
-
-	OSMO_ASSERT(expect_bssgp_msg(0x1000, 0, BSSGP_PDUT_BVC_RESET_ACK));
-
-	send_bssgp_suspend(nsi, &bss_peer[0], 0xccd1758b, &rai_bss);
-
-	OSMO_ASSERT(expect_bssgp_msg(SGSN_NSEI, 0, BSSGP_PDUT_SUSPEND));
-
-	send_bssgp_suspend_ack(nsi, &sgsn_peer, 0xccd1758b, &rai_sgsn);
-
-	OSMO_ASSERT(expect_bssgp_msg(0x1000, 0, BSSGP_PDUT_SUSPEND_ACK));
-
-	dump_global(stdout, 0);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(2 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_BSS].current);
-	OSMO_ASSERT(1 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_SGSN].current);
-
-	printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, 0,
-		       dtap_attach_req, sizeof(dtap_attach_req));
-
-	OSMO_ASSERT(4 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_BSS].current);
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_REQ));
-
-	send_llc_dl_ui(nsi, "IDENT REQUEST", &sgsn_peer, 0x1002,
-		       foreign_tlli, 0, NULL, 0,
-		       GPRS_SAPI_GMM, 0,
-		       dtap_identity_req, sizeof(dtap_identity_req));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ID_REQ));
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, 3,
-		       dtap_identity_resp, sizeof(dtap_identity_resp));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ID_RESP));
-
-	OSMO_ASSERT(5 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_BSS].current);
-	OSMO_ASSERT(1 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_SGSN].current);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
-		       foreign_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, 1,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ATTACH_ACK));
-
-	OSMO_ASSERT(2 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_SGSN].current);
-
-	OSMO_ASSERT(gbproxy_peer_by_rai(&gbcfg, convert_ra(&rai_bss)) != NULL);
-	OSMO_ASSERT(gbproxy_peer_by_rai(&gbcfg, convert_ra(&rai_sgsn)) == NULL);
-	OSMO_ASSERT(gbproxy_peer_by_rai(&gbcfg, convert_ra(&rai_unknown)) == NULL);
-
-	OSMO_ASSERT(gbproxy_peer_by_lai(&gbcfg, convert_ra(&rai_bss)) != NULL);
-	OSMO_ASSERT(gbproxy_peer_by_lai(&gbcfg, convert_ra(&rai_sgsn)) == NULL);
-	OSMO_ASSERT(gbproxy_peer_by_lai(&gbcfg, convert_ra(&rai_unknown)) == NULL);
-
-	OSMO_ASSERT(gbproxy_peer_by_lac(&gbcfg, convert_ra(&rai_bss)) != NULL);
-	OSMO_ASSERT(gbproxy_peer_by_lac(&gbcfg, convert_ra(&rai_sgsn)) != NULL);
-	OSMO_ASSERT(gbproxy_peer_by_lac(&gbcfg, convert_ra(&rai_unknown)) == NULL);
-
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_tlli);
-	OSMO_ASSERT(link_info->tlli.current != local_tlli);
-	OSMO_ASSERT(!link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.current != local_tlli);
-	OSMO_ASSERT(!link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, 4,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_COMPL));
-
-	OSMO_ASSERT(6 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_BSS].current);
-
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_tlli);
-	OSMO_ASSERT(link_info->tlli.current != local_tlli);
-	OSMO_ASSERT(link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.current != local_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-
-	/* Replace APN (1) */
-	send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REPLACE APN)", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, 3,
-		       dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GSM_ACT_PDP_REQ));
-
-	OSMO_ASSERT(7 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_BSS].current);
-
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_tlli);
-	OSMO_ASSERT(link_info->tlli.current != local_tlli);
-	OSMO_ASSERT(link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.current != local_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-
-	send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
-		       local_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, 2,
-		       dtap_gmm_information, sizeof(dtap_gmm_information));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_INFO));
-
-	OSMO_ASSERT(2 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_SGSN].current);
-
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == 0);
-	OSMO_ASSERT(link_info->tlli.current == local_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == 0);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == local_tlli);
-
-	/* Replace APN (2) */
-	send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REPLACE APN)", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, 3,
-		       dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
-
-	expect_res = expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GSM_ACT_PDP_REQ);
-	OSMO_ASSERT(expect_res != NULL);
-	OSMO_ASSERT(expect_res->parse_ctx.apn_ie_len == gbcfg.core_apn_size + 2);
-
-	OSMO_ASSERT(8 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_BSS].current);
-
-	gbcfg.core_apn[0] = 0;
-	gbcfg.core_apn_size = 0;
-
-	/* Remove APN */
-	send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REMOVE APN)", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, 3,
-		       dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
-
-	expect_res = expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GSM_ACT_PDP_REQ);
-	OSMO_ASSERT(expect_res != NULL);
-	OSMO_ASSERT(expect_res->parse_ctx.apn_ie_len == 0);
-
-	OSMO_ASSERT(9 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_BSS].current);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Detach */
-	send_llc_ul_ui(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, 6,
-		       dtap_detach_req, sizeof(dtap_detach_req));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_DETACH_REQ));
-
-	OSMO_ASSERT(10 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_BSS].current);
-	OSMO_ASSERT(2 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_SGSN].current);
-
-	send_llc_dl_ui(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
-		       local_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, 5,
-		       dtap_detach_acc, sizeof(dtap_detach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_DETACH_ACK));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- RA update ---\n\n");
-
-	send_llc_ul_ui(nsi, "RA UPD REQ", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, 0x7080,
-		       GPRS_SAPI_GMM, 5,
-		       dtap_ra_upd_req, sizeof(dtap_ra_upd_req));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_RA_UPD_REQ));
-
-	OSMO_ASSERT(12 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_BSS].current);
-
-	send_llc_dl_ui(nsi, "RA UPD ACC", &sgsn_peer, 0x1002,
-		       foreign_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, 6,
-		       dtap_ra_upd_acc, sizeof(dtap_ra_upd_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_RA_UPD_ACK));
-
-	OSMO_ASSERT(3 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_SGSN].current);
-
-	/* Remove APN */
-	send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REMOVE APN)", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, 3,
-		       dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
-
-	expect_res = expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GSM_ACT_PDP_REQ);
-	OSMO_ASSERT(expect_res != NULL);
-	OSMO_ASSERT(expect_res->parse_ctx.apn_ie_len == 0);
-
-	OSMO_ASSERT(13 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_BSS].current);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Detach (power off -> no Detach Accept) */
-	send_llc_ul_ui(nsi, "DETACH REQ (PWR OFF)", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, 6,
-		       dtap_detach_po_req, sizeof(dtap_detach_po_req));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_DETACH_REQ));
-
-	OSMO_ASSERT(14 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_BSS].current);
-
-	dump_global(stdout, 0);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Bad cases ---\n\n");
-
-	/* The RAI in the Attach Request message differs from the RAI in the
-	 * BSSGP message, only patch the latter */
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST (foreign RAI)", &bss_peer[0], 0x1002,
-		       foreign_tlli2, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, 0,
-		       dtap_attach_req2, sizeof(dtap_attach_req2));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_REQ));
-
-	OSMO_ASSERT(15 == peer->ctrg->ctr[GBPROX_PEER_CTR_RAID_PATCHED_BSS].current);
-
-	printf("TLLI is already detached, shouldn't patch\n");
-	send_llc_ul_ui(nsi, "ACT PDP CTX REQ", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, 3,
-		       dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GSM_ACT_PDP_REQ));
-
-	printf("Invalid RAI, shouldn't patch\n");
-	send_bssgp_suspend_ack(nsi, &sgsn_peer, 0xccd1758b, &rai_unknown);
-
-	/* TODO: The following breaks with the current libosmocore, enable it
-	 * again (and remove the plain expect_msg), when the msgb_bssgph patch
-	 * is integrated */
-	/* OSMO_ASSERT(expect_bssgp_msg(SGSN_NSEI, 0, BSSGP_PDUT_STATUS)); */
-	OSMO_ASSERT(expect_msg());
-
-	dump_global(stdout, 0);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!expect_msg());
-	received_messages = NULL;
-
-	gbproxy_clear_patch_filter(&gbcfg.matches[GBPROX_MATCH_PATCHING]);
-	gbprox_reset(&gbcfg);
-	gprs_ns_destroy(nsi);
-	nsi = NULL;
-}
-
-static void test_gbproxy_ptmsi_assignment()
-{
-	struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
-	struct sockaddr_in bss_peer[1] = {{0},};
-	struct sockaddr_in sgsn_peer= {0};
-	struct  gprs_ra_id rai_bss =
-		{.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
-	struct  gprs_ra_id rai_unknown =
-		{.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
-	uint16_t cell_id = 0x1234;
-
-	const uint32_t ptmsi = 0xefe2b700;
-	const uint32_t local_tlli = 0xefe2b700;
-
-	const uint32_t foreign_tlli1 = 0x8000dead;
-	const uint32_t foreign_tlli2 = 0x8000beef;
-
-	const uint8_t imsi1[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};
-	const uint8_t imsi2[] = {0x11, 0x12, 0x99, 0x99, 0x99, 0x16, 0x17, 0x18};
-
-	struct gbproxy_link_info *link_info, *link_info2;
-	struct gbproxy_peer *peer;
-	unsigned bss_nu = 0;
-	unsigned sgsn_nu = 0;
-
-	OSMO_ASSERT(local_tlli == gprs_tmsi2tlli(ptmsi, TLLI_LOCAL));
-
-	bssgp_nsi = nsi;
-	gbcfg.nsi = bssgp_nsi;
-	gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
-	gbcfg.core_mcc = 0;
-	gbcfg.core_mnc = 0;
-	gbcfg.core_apn = talloc_zero_size(NULL, 100);
-	gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
-	gbcfg.patch_ptmsi = 0;
-
-	configure_sgsn_peer(&sgsn_peer);
-	configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
-
-	printf("=== %s ===\n", __func__);
-	printf("--- Initialise SGSN ---\n\n");
-
-	connect_sgsn(nsi, &sgsn_peer, SGSN_NSEI);
-
-	printf("--- Initialise BSS 1 ---\n\n");
-
-	setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
-	setup_bssgp(nsi, &bss_peer[0], 0x1002);
-
-	peer = gbproxy_peer_by_nsei(&gbcfg, 0x1000);
-	OSMO_ASSERT(peer != NULL);
-
-	send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
-
-	gprs_dump_nsi(nsi);
-	dump_global(stdout, 0);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Establish first LLC connection ---\n\n");
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_tlli1, &rai_unknown, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req, sizeof(dtap_attach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "IDENT REQUEST", &sgsn_peer, 0x1002,
-		       foreign_tlli1, 0, NULL, 0,
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_identity_req, sizeof(dtap_identity_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_tlli1, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity_resp, sizeof(dtap_identity_resp));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
-		       foreign_tlli1, 1, imsi1, sizeof(imsi1),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli1);
-	link_info2 = gbproxy_link_info_by_tlli(peer, local_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info == link_info2);
-	OSMO_ASSERT(link_info->tlli.assigned == local_tlli);
-	OSMO_ASSERT(link_info->tlli.current == foreign_tlli1);
-	OSMO_ASSERT(!link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->tlli.ptmsi == ptmsi);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, local_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_tlli);
-	OSMO_ASSERT(link_info->tlli.current == foreign_tlli1);
-	OSMO_ASSERT(link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->tlli.ptmsi == ptmsi);
-
-
-	send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
-		       local_tlli, 1, imsi1, sizeof(imsi1),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_gmm_information, sizeof(dtap_gmm_information));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_imsi(peer, imsi1, ARRAY_SIZE(imsi1));
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.ptmsi == ptmsi);
-	OSMO_ASSERT(!gbproxy_link_info_by_imsi(peer, imsi2, ARRAY_SIZE(imsi2)));
-
-	link_info2 = gbproxy_link_info_by_tlli(peer, local_tlli);
-	OSMO_ASSERT(link_info == link_info2);
-	OSMO_ASSERT(link_info->tlli.assigned == 0);
-	OSMO_ASSERT(link_info->tlli.current == local_tlli);
-	OSMO_ASSERT(link_info->tlli.ptmsi == ptmsi);
-
-	printf("--- Establish second LLC connection with the same P-TMSI ---\n\n");
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_tlli2, &rai_unknown, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req, sizeof(dtap_attach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "IDENT REQUEST", &sgsn_peer, 0x1002,
-		       foreign_tlli2, 0, NULL, 0,
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_identity_req, sizeof(dtap_identity_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_tlli2, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity2_resp, sizeof(dtap_identity2_resp));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
-		       foreign_tlli2, 1, imsi2, sizeof(imsi2),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli2);
-	link_info2 = gbproxy_link_info_by_tlli(peer, local_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info == link_info2);
-	OSMO_ASSERT(link_info->tlli.assigned == local_tlli);
-	OSMO_ASSERT(link_info->tlli.current == foreign_tlli2);
-	OSMO_ASSERT(!link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->tlli.ptmsi == ptmsi);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, local_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_tlli);
-	OSMO_ASSERT(link_info->tlli.current == foreign_tlli2);
-	OSMO_ASSERT(link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->tlli.ptmsi == ptmsi);
-
-	send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
-		       local_tlli, 1, imsi2, sizeof(imsi2),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_gmm_information, sizeof(dtap_gmm_information));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_imsi(peer, imsi2, ARRAY_SIZE(imsi2));
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.ptmsi == ptmsi);
-	OSMO_ASSERT(!gbproxy_link_info_by_imsi(peer, imsi1, ARRAY_SIZE(imsi1)));
-
-	link_info2 = gbproxy_link_info_by_tlli(peer, local_tlli);
-	OSMO_ASSERT(link_info == link_info2);
-	OSMO_ASSERT(link_info->tlli.assigned == 0);
-	OSMO_ASSERT(link_info->tlli.current == local_tlli);
-	OSMO_ASSERT(link_info->tlli.ptmsi == ptmsi);
-
-	dump_global(stdout, 0);
-
-	gbprox_reset(&gbcfg);
-	gprs_ns_destroy(nsi);
-	nsi = NULL;
-
-	cleanup_test();
-}
-
-static void test_gbproxy_ptmsi_patching()
-{
-	struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
-	struct sockaddr_in bss_peer[1] = {{0},};
-	struct sockaddr_in sgsn_peer= {0};
-	struct  gprs_ra_id rai_bss =
-		{.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
-	struct  gprs_ra_id rai_sgsn =
-		{.mcc = 123, .mnc = 456, .lac = 16464, .rac = 96};
-	struct  gprs_ra_id rai_wrong_mcc_sgsn =
-		{.mcc = 999, .mnc = 456, .lac = 16464, .rac = 96};
-	struct  gprs_ra_id rai_unknown =
-		{.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
-	uint16_t cell_id = 0x1234;
-
-	const uint32_t sgsn_ptmsi = 0xefe2b700;
-	const uint32_t sgsn_ptmsi2 = 0xe0987654;
-	const uint32_t sgsn_ptmsi3 = 0xe0543210;
-	const uint32_t local_sgsn_tlli = 0xefe2b700;
-	const uint32_t local_sgsn_tlli2 = 0xe0987654;
-	const uint32_t local_sgsn_tlli3 = 0xe0543210;
-	const uint32_t random_sgsn_tlli = 0x78dead00;
-	const uint32_t unknown_sgsn_tlli = 0xeebadbad;
-
-	const uint32_t bss_ptmsi = 0xc0dead01;
-	const uint32_t bss_ptmsi2 = 0xc0dead02;
-	const uint32_t bss_ptmsi3 = 0xc0dead03;
-	const uint32_t local_bss_tlli = 0xc0dead01;
-	const uint32_t local_bss_tlli2 = 0xc0dead02;
-	const uint32_t local_bss_tlli3 = 0xc0dead03;
-	const uint32_t foreign_bss_tlli = 0x8000dead;
-
-
-	const uint8_t imsi[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};
-	struct gbproxy_link_info *link_info;
-	struct gbproxy_peer *peer;
-	unsigned bss_nu = 0;
-	unsigned sgsn_nu = 0;
-	int old_ctr;
-
-	OSMO_ASSERT(local_sgsn_tlli == gprs_tmsi2tlli(sgsn_ptmsi, TLLI_LOCAL));
-	OSMO_ASSERT(local_sgsn_tlli2 == gprs_tmsi2tlli(sgsn_ptmsi2, TLLI_LOCAL));
-	OSMO_ASSERT(local_sgsn_tlli3 == gprs_tmsi2tlli(sgsn_ptmsi3, TLLI_LOCAL));
-	OSMO_ASSERT(local_bss_tlli == gprs_tmsi2tlli(bss_ptmsi, TLLI_LOCAL));
-	OSMO_ASSERT(local_bss_tlli2 == gprs_tmsi2tlli(bss_ptmsi2, TLLI_LOCAL));
-	OSMO_ASSERT(local_bss_tlli3 == gprs_tmsi2tlli(bss_ptmsi3, TLLI_LOCAL));
-
-	bssgp_nsi = nsi;
-	gbcfg.nsi = bssgp_nsi;
-	gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
-	gbcfg.core_mcc = 123;
-	gbcfg.core_mnc = 456;
-	gbcfg.core_apn = talloc_zero_size(NULL, 100);
-	gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
-	gbcfg.patch_ptmsi = 1;
-
-	configure_sgsn_peer(&sgsn_peer);
-	configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
-
-	printf("=== %s ===\n", __func__);
-	printf("--- Initialise SGSN ---\n\n");
-
-	connect_sgsn(nsi, &sgsn_peer, SGSN_NSEI);
-
-	printf("--- Initialise BSS 1 ---\n\n");
-
-	setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
-	setup_bssgp(nsi, &bss_peer[0], 0x1002);
-
-	peer = gbproxy_peer_by_nsei(&gbcfg, 0x1000);
-	OSMO_ASSERT(peer != NULL);
-
-	send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
-
-	gprs_dump_nsi(nsi);
-	dump_global(stdout, 0);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_unknown, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req, sizeof(dtap_attach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "IDENT REQUEST", &sgsn_peer, 0x1002,
-		       random_sgsn_tlli, 0, NULL, 0,
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_identity_req, sizeof(dtap_identity_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity_resp, sizeof(dtap_identity_resp));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
-		       random_sgsn_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, random_sgsn_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_bss_tlli);
-	OSMO_ASSERT(link_info->tlli.current == foreign_bss_tlli);
-	OSMO_ASSERT(!link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->tlli.ptmsi == bss_ptmsi);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == random_sgsn_tlli);
-	OSMO_ASSERT(!link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.ptmsi == sgsn_ptmsi);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_bss_tlli);
-	OSMO_ASSERT(link_info->tlli.current == foreign_bss_tlli);
-	OSMO_ASSERT(link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == random_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-
-	send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
-		       local_sgsn_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_gmm_information, sizeof(dtap_gmm_information));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.current == local_bss_tlli);
-	OSMO_ASSERT(link_info->tlli.assigned == 0);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == local_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == 0);
-
-	send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REPLACE APN)", &bss_peer[0], 0x1002,
-		       local_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Non-DTAP */
-	send_bssgp_ul_unitdata(nsi, "XID (UL)", &bss_peer[0], 0x1002,
-			       local_bss_tlli, &rai_bss, cell_id,
-			       llc_u_xid_ul, sizeof(llc_u_xid_ul));
-
-	send_bssgp_dl_unitdata(nsi, "XID (DL)", &sgsn_peer, 0x1002,
-			       local_sgsn_tlli, 1, imsi, sizeof(imsi),
-			       llc_u_xid_dl, sizeof(llc_u_xid_dl));
-
-	send_bssgp_ul_unitdata(nsi, "LL11 DNS QUERY (UL)", &bss_peer[0], 0x1002,
-			       local_bss_tlli, &rai_bss, cell_id,
-			       llc_ui_ll11_dns_query_ul,
-			       sizeof(llc_ui_ll11_dns_query_ul));
-
-	send_bssgp_dl_unitdata(nsi, "LL11 DNS RESP (DL)", &sgsn_peer, 0x1002,
-			       local_sgsn_tlli, 1, imsi, sizeof(imsi),
-			       llc_ui_ll11_dns_resp_dl,
-			       sizeof(llc_ui_ll11_dns_resp_dl));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Repeated RA Update Requests */
-	send_llc_ul_ui(nsi, "RA UPD REQ (P-TMSI 2)", &bss_peer[0], 0x1002,
-		       local_bss_tlli, &rai_bss, 0x7080,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_ra_upd_req, sizeof(dtap_ra_upd_req));
-
-	send_llc_dl_ui(nsi, "RA UDP ACC (P-TMSI 2)", &sgsn_peer, 0x1002,
-		       local_sgsn_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_ra_upd_acc2, sizeof(dtap_ra_upd_acc2));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli2, SGSN_NSEI) != NULL);
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_bss_tlli2);
-	OSMO_ASSERT(link_info->tlli.current == local_bss_tlli);
-	OSMO_ASSERT(!link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->tlli.ptmsi == bss_ptmsi2);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_sgsn_tlli2);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == local_sgsn_tlli);
-	OSMO_ASSERT(!link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.ptmsi == sgsn_ptmsi2);
-
-	send_llc_ul_ui(nsi, "RA UPD REQ (P-TMSI 3)", &bss_peer[0], 0x1002,
-		       local_bss_tlli2, &rai_bss, 0x7080,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_ra_upd_req, sizeof(dtap_ra_upd_req));
-
-	send_llc_dl_ui(nsi, "RA UDP ACC (P-TMSI 3)", &sgsn_peer, 0x1002,
-		       local_sgsn_tlli2, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_ra_upd_acc3, sizeof(dtap_ra_upd_acc3));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli2, SGSN_NSEI) == NULL);
-	OSMO_ASSERT(gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli3, SGSN_NSEI) != NULL);
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_bss_tlli3);
-	OSMO_ASSERT(link_info->tlli.current == local_bss_tlli);
-	OSMO_ASSERT(!link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->tlli.ptmsi == bss_ptmsi3);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_sgsn_tlli3);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == local_sgsn_tlli);
-	OSMO_ASSERT(!link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.ptmsi == sgsn_ptmsi3);
-
-	send_llc_ul_ui(nsi, "RA UPD COMPLETE", &bss_peer[0], 0x1002,
-		       local_bss_tlli3, &rai_bss, 0x7080,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_ra_upd_complete, sizeof(dtap_ra_upd_complete));
-
-	link_info = gbproxy_link_info_by_tlli(peer, local_bss_tlli3);
-
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-
-	send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
-		       local_sgsn_tlli3, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_gmm_information, sizeof(dtap_gmm_information));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli3, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.current == local_bss_tlli3);
-	OSMO_ASSERT(link_info->tlli.assigned == 0);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == local_sgsn_tlli3);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == 0);
-
-	/* Other messages */
-	send_bssgp_llc_discarded(nsi, &bss_peer[0], 0x1002,
-				 local_bss_tlli3, 1, 12);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_bssgp_suspend(nsi, &bss_peer[0], local_bss_tlli3, &rai_bss);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_bssgp_suspend_ack(nsi, &sgsn_peer, local_sgsn_tlli3, &rai_sgsn);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	old_ctr = peer->ctrg->ctr[GBPROX_PEER_CTR_PTMSI_PATCHED_SGSN].current;
-
-	send_bssgp_paging(nsi, &sgsn_peer, imsi, sizeof(imsi), &rai_bss, sgsn_ptmsi3);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(old_ctr + 1 ==
-		    peer->ctrg->ctr[GBPROX_PEER_CTR_PTMSI_PATCHED_SGSN].current);
-
-	/* Bad case: Invalid BVCI */
-	send_bssgp_llc_discarded(nsi, &bss_peer[0], 0xeee1,
-				 local_bss_tlli3, 1, 12);
-	dump_global(stdout, 0);
-
-	/* Bad case: Invalid RAI */
-	send_bssgp_suspend_ack(nsi, &sgsn_peer, local_sgsn_tlli3, &rai_unknown);
-
-	dump_global(stdout, 0);
-
-	/* Bad case: Invalid MCC (LAC ok) */
-	send_bssgp_suspend_ack(nsi, &sgsn_peer, local_sgsn_tlli3,
-			       &rai_wrong_mcc_sgsn);
-
-	dump_global(stdout, 0);
-
-	/* Bad case: Invalid TLLI from SGSN (IMSI unknown) */
-	send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
-		       unknown_sgsn_tlli, 1, NULL, 0,
-		       GPRS_SAPI_GMM, 2,
-		       dtap_gmm_information, sizeof(dtap_gmm_information));
-
-	/* Bad case: Invalid TLLI from SGSN (IMSI known) */
-	send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
-		       unknown_sgsn_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, 3,
-		       dtap_gmm_information, sizeof(dtap_gmm_information));
-
-	/* Detach */
-	send_llc_ul_ui(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
-		       local_bss_tlli3, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_detach_req, sizeof(dtap_detach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
-		       local_sgsn_tlli3, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_detach_acc, sizeof(dtap_detach_acc));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	dump_global(stdout, 0);
-
-	gbprox_reset(&gbcfg);
-	gprs_ns_destroy(nsi);
-	nsi = NULL;
-
-	cleanup_test();
-}
-
-static void test_gbproxy_ptmsi_patching_bad_cases()
-{
-	struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
-	struct sockaddr_in bss_peer[1] = {{0},};
-	struct sockaddr_in sgsn_peer= {0};
-	struct  gprs_ra_id rai_bss =
-		{.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
-	struct  gprs_ra_id rai_unknown =
-		{.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
-	uint16_t cell_id = 0x1234;
-
-	const uint32_t sgsn_ptmsi = 0xefe2b700;
-	const uint32_t local_sgsn_tlli = 0xefe2b700;
-	const uint32_t random_sgsn_tlli = 0x78dead00;
-
-	const uint32_t bss_ptmsi = 0xc0dead01;
-	const uint32_t local_bss_tlli = 0xc0dead01;
-	const uint32_t foreign_bss_tlli = 0x8000dead;
-
-
-	const uint8_t imsi[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};
-	struct gbproxy_link_info *link_info;
-	struct gbproxy_peer *peer;
-	unsigned bss_nu = 0;
-	unsigned sgsn_nu = 0;
-
-	OSMO_ASSERT(local_sgsn_tlli == gprs_tmsi2tlli(sgsn_ptmsi, TLLI_LOCAL));
-	OSMO_ASSERT(local_bss_tlli == gprs_tmsi2tlli(bss_ptmsi, TLLI_LOCAL));
-
-	bssgp_nsi = nsi;
-	gbcfg.nsi = bssgp_nsi;
-	gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
-	gbcfg.core_mcc = 123;
-	gbcfg.core_mnc = 456;
-	gbcfg.core_apn = talloc_zero_size(NULL, 100);
-	gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
-	gbcfg.patch_ptmsi = 1;
-
-	configure_sgsn_peer(&sgsn_peer);
-	configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
-
-	printf("=== %s ===\n", __func__);
-	printf("--- Initialise SGSN ---\n\n");
-
-	connect_sgsn(nsi, &sgsn_peer, SGSN_NSEI);
-
-	printf("--- Initialise BSS 1 ---\n\n");
-
-	setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
-	setup_bssgp(nsi, &bss_peer[0], 0x1002);
-
-	peer = gbproxy_peer_by_nsei(&gbcfg, 0x1000);
-	OSMO_ASSERT(peer != NULL);
-
-	send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
-
-	gprs_dump_nsi(nsi);
-	dump_global(stdout, 0);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_unknown, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req, sizeof(dtap_attach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "IDENT REQUEST", &sgsn_peer, 0x1002,
-		       random_sgsn_tlli, 0, NULL, 0,
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_identity_req, sizeof(dtap_identity_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity_resp, sizeof(dtap_identity_resp));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
-		       random_sgsn_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, random_sgsn_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_bss_tlli);
-	OSMO_ASSERT(link_info->tlli.current == foreign_bss_tlli);
-	OSMO_ASSERT(!link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->tlli.ptmsi == bss_ptmsi);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == random_sgsn_tlli);
-	OSMO_ASSERT(!link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.ptmsi == sgsn_ptmsi);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT (duplicated)", &sgsn_peer, 0x1002,
-		       random_sgsn_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, random_sgsn_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_bss_tlli);
-	OSMO_ASSERT(link_info->tlli.current == foreign_bss_tlli);
-	OSMO_ASSERT(!link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->tlli.ptmsi == bss_ptmsi);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == random_sgsn_tlli);
-	OSMO_ASSERT(!link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.ptmsi == sgsn_ptmsi);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_bss_tlli);
-	OSMO_ASSERT(link_info->tlli.current == foreign_bss_tlli);
-	OSMO_ASSERT(link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == random_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-
-	send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
-		       local_sgsn_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_gmm_information, sizeof(dtap_gmm_information));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.current == local_bss_tlli);
-	OSMO_ASSERT(link_info->tlli.assigned == 0);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == local_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == 0);
-
-	/* Detach */
-	send_llc_ul_ui(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
-		       local_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_detach_req, sizeof(dtap_detach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
-		       local_sgsn_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_detach_acc, sizeof(dtap_detach_acc));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	dump_global(stdout, 0);
-
-	gbprox_reset(&gbcfg);
-	gprs_ns_destroy(nsi);
-	nsi = NULL;
-
-	cleanup_test();
-}
-
-
-static void test_gbproxy_imsi_acquisition()
-{
-	struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
-	struct sockaddr_in bss_peer[1] = {{0},};
-	struct sockaddr_in sgsn_peer= {0};
-	struct  gprs_ra_id rai_bss =
-		{.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
-	struct  gprs_ra_id rai_sgsn =
-		{.mcc = 123, .mnc = 456, .lac = 16464, .rac = 96};
-	struct  gprs_ra_id rai_wrong_mcc_sgsn =
-		{.mcc = 999, .mnc = 456, .lac = 16464, .rac = 96};
-	struct  gprs_ra_id rai_unknown =
-		{.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
-	uint16_t cell_id = 0x1234;
-
-	const uint32_t sgsn_ptmsi = 0xefe2b700;
-	const uint32_t local_sgsn_tlli = 0xefe2b700;
-	const uint32_t random_sgsn_tlli = 0x78dead00;
-	const uint32_t random_sgsn_tlli2 = 0x78dead02;
-
-	const uint32_t bss_ptmsi = 0xc0dead01;
-	const uint32_t local_bss_tlli = 0xc0dead01;
-	const uint32_t foreign_bss_tlli = 0x8000dead;
-	const uint32_t other_bss_tlli = 0x8000beef;
-
-	const uint8_t imsi[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};
-	struct gbproxy_link_info *link_info;
-	struct gbproxy_peer *peer;
-	unsigned bss_nu = 0;
-	unsigned sgsn_nu = 0;
-
-	OSMO_ASSERT(local_sgsn_tlli == gprs_tmsi2tlli(sgsn_ptmsi, TLLI_LOCAL));
-
-	bssgp_nsi = nsi;
-	gbcfg.nsi = bssgp_nsi;
-	gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
-	gbcfg.core_mcc = 123;
-	gbcfg.core_mnc = 456;
-	gbcfg.core_apn = talloc_zero_size(NULL, 100);
-	gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
-	gbcfg.patch_ptmsi = 1;
-	gbcfg.acquire_imsi = 1;
-
-	configure_sgsn_peer(&sgsn_peer);
-	configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
-
-	printf("=== %s ===\n", __func__);
-	printf("--- Initialise SGSN ---\n\n");
-
-	connect_sgsn(nsi, &sgsn_peer, SGSN_NSEI);
-
-	printf("--- Initialise BSS 1 ---\n\n");
-
-	setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
-	setup_bssgp(nsi, &bss_peer[0], 0x1002);
-
-	peer = gbproxy_peer_by_nsei(&gbcfg, 0x1000);
-	OSMO_ASSERT(peer != NULL);
-
-	send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
-
-	gprs_dump_nsi(nsi);
-	dump_global(stdout, 0);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req, sizeof(dtap_attach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity_resp, sizeof(dtap_identity_resp));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "IDENT REQUEST", &sgsn_peer, 0x1002,
-		       random_sgsn_tlli, 0, NULL, 0,
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_identity_req, sizeof(dtap_identity_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity_resp, sizeof(dtap_identity_resp));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
-		       random_sgsn_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, random_sgsn_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_bss_tlli);
-	OSMO_ASSERT(link_info->tlli.current == foreign_bss_tlli);
-	OSMO_ASSERT(!link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->tlli.ptmsi == bss_ptmsi);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == random_sgsn_tlli);
-	OSMO_ASSERT(!link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.ptmsi == sgsn_ptmsi);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_bss_tlli);
-	OSMO_ASSERT(link_info->tlli.current == foreign_bss_tlli);
-	OSMO_ASSERT(link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == random_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-
-	send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
-		       local_sgsn_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_gmm_information, sizeof(dtap_gmm_information));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.current == local_bss_tlli);
-	OSMO_ASSERT(link_info->tlli.assigned == 0);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == local_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == 0);
-
-	/* Non-DTAP */
-	send_bssgp_ul_unitdata(nsi, "XID (UL)", &bss_peer[0], 0x1002,
-			       local_bss_tlli, &rai_bss, cell_id,
-			       llc_u_xid_ul, sizeof(llc_u_xid_ul));
-
-	send_bssgp_dl_unitdata(nsi, "XID (DL)", &sgsn_peer, 0x1002,
-			       local_sgsn_tlli, 1, imsi, sizeof(imsi),
-			       llc_u_xid_dl, sizeof(llc_u_xid_dl));
-
-	send_bssgp_ul_unitdata(nsi, "LL11 DNS QUERY (UL)", &bss_peer[0], 0x1002,
-			       local_bss_tlli, &rai_bss, cell_id,
-			       llc_ui_ll11_dns_query_ul,
-			       sizeof(llc_ui_ll11_dns_query_ul));
-
-	send_bssgp_dl_unitdata(nsi, "LL11 DNS RESP (DL)", &sgsn_peer, 0x1002,
-			       local_sgsn_tlli, 1, imsi, sizeof(imsi),
-			       llc_ui_ll11_dns_resp_dl,
-			       sizeof(llc_ui_ll11_dns_resp_dl));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Other messages */
-	send_bssgp_llc_discarded(nsi, &bss_peer[0], 0x1002,
-				 local_bss_tlli, 1, 12);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_bssgp_llc_discarded(nsi, &sgsn_peer, 0x1002,
-				 local_sgsn_tlli, 1, 12);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_bssgp_suspend(nsi, &bss_peer[0], local_bss_tlli, &rai_bss);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_bssgp_suspend_ack(nsi, &sgsn_peer, local_sgsn_tlli, &rai_sgsn);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Bad case: Invalid BVCI */
-	send_bssgp_llc_discarded(nsi, &bss_peer[0], 0xeee1,
-				 local_bss_tlli, 1, 12);
-	dump_global(stdout, 0);
-
-	/* Bad case: Invalid RAI */
-	send_bssgp_suspend_ack(nsi, &sgsn_peer, local_sgsn_tlli, &rai_unknown);
-
-	dump_global(stdout, 0);
-
-	/* Bad case: Invalid MCC (LAC ok) */
-	send_bssgp_suspend_ack(nsi, &sgsn_peer, local_sgsn_tlli,
-			       &rai_wrong_mcc_sgsn);
-
-	dump_global(stdout, 0);
-
-	/* Detach */
-	send_llc_ul_ui(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
-		       local_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_detach_req, sizeof(dtap_detach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
-		       local_sgsn_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_detach_acc, sizeof(dtap_detach_acc));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* RA Update request */
-
-	send_llc_ul_ui(nsi, "RA UPD REQ", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_unknown, 0x7080,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_ra_upd_req, sizeof(dtap_ra_upd_req));
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity_resp, sizeof(dtap_identity_resp));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "RA UDP ACC", &sgsn_peer, 0x1002,
-		       random_sgsn_tlli2, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_ra_upd_acc, sizeof(dtap_ra_upd_acc));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Detach */
-
-	send_llc_ul_ui(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
-		       local_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_detach_req, sizeof(dtap_detach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
-		       local_sgsn_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_detach_acc, sizeof(dtap_detach_acc));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Special case: Repeated Attach Requests */
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_unknown, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req, sizeof(dtap_attach_req));
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_unknown, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req, sizeof(dtap_attach_req));
-
-	send_llc_ul_ui(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_detach_req, sizeof(dtap_detach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Special case: Detach from an unknown TLLI */
-
-	send_llc_ul_ui(nsi, "DETACH REQ (unknown TLLI)", &bss_peer[0], 0x1002,
-		       other_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_detach_req, sizeof(dtap_detach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Special case: Repeated RA Update Requests */
-
-	send_llc_ul_ui(nsi, "RA UPD REQ", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_unknown, 0x7080,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_ra_upd_req, sizeof(dtap_ra_upd_req));
-
-	send_llc_ul_ui(nsi, "RA UPD REQ", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_unknown, 0x7080,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_ra_upd_req, sizeof(dtap_ra_upd_req));
-
-	send_llc_ul_ui(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_detach_req, sizeof(dtap_detach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	dump_global(stdout, 0);
-
-	gbprox_reset(&gbcfg);
-	gprs_ns_destroy(nsi);
-	nsi = NULL;
-
-	cleanup_test();
-}
-
-static void test_gbproxy_secondary_sgsn()
-{
-	struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
-	struct sockaddr_in bss_peer[1] = {{0},};
-	struct sockaddr_in sgsn_peer[2]= {{0},};
-	struct  gprs_ra_id rai_bss =
-		{.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
-	struct  gprs_ra_id rai_sgsn =
-		{.mcc = 123, .mnc = 456, .lac = 16464, .rac = 96};
-	struct  gprs_ra_id rai_unknown =
-		{.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
-	uint16_t cell_id = 0x1234;
-
-	const uint32_t sgsn_ptmsi = 0xefe2b700;
-	const uint32_t local_sgsn_tlli = 0xefe2b700;
-	const uint32_t random_sgsn_tlli = 0x78dead00;
-
-	const uint32_t bss_ptmsi = 0xc0dead01;
-	const uint32_t local_bss_tlli = 0xc0dead01;
-	const uint32_t foreign_bss_tlli = 0x8000dead;
-
-	const uint32_t sgsn_ptmsi2 = 0xe0987654;
-	const uint32_t local_sgsn_tlli2 = 0xe0987654;
-	const uint32_t random_sgsn_tlli2 = 0x78dead02;
-	const uint32_t bss_ptmsi2 = 0xc0dead03;
-	const uint32_t local_bss_tlli2 = 0xc0dead03;
-	const uint32_t foreign_bss_tlli2 = 0x8000beef;
-
-	const uint32_t random_sgsn_tlli3 = 0x78dead04;
-	const uint32_t bss_ptmsi3 = 0xc0dead05;
-	const uint32_t local_bss_tlli3 = 0xc0dead05;
-	const uint32_t foreign_bss_tlli3 = 0x8000feed;
-
-	const uint8_t imsi1[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};
-	const uint8_t imsi2[] = {0x11, 0x12, 0x99, 0x99, 0x99, 0x16, 0x17, 0x18};
-	const uint8_t imsi3[] = {0x11, 0x12, 0x99, 0x99, 0x99, 0x26, 0x27, 0x28};
-	struct gbproxy_link_info *link_info;
-	struct gbproxy_link_info *other_info;
-	struct gbproxy_peer *peer;
-	unsigned bss_nu = 0;
-	unsigned sgsn_nu = 0;
-
-	const char *err_msg = NULL;
-	const char *filter_re = "999999";
-
-	OSMO_ASSERT(local_sgsn_tlli == gprs_tmsi2tlli(sgsn_ptmsi, TLLI_LOCAL));
-	OSMO_ASSERT(local_sgsn_tlli2 == gprs_tmsi2tlli(sgsn_ptmsi2, TLLI_LOCAL));
-
-	bssgp_nsi = nsi;
-	gbcfg.nsi = bssgp_nsi;
-	gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
-	gbcfg.core_mcc = 123;
-	gbcfg.core_mnc = 456;
-	gbcfg.core_apn = talloc_zero_size(NULL, 100);
-	gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
-	gbcfg.patch_ptmsi = 1;
-	gbcfg.acquire_imsi = 1;
-
-	gbcfg.route_to_sgsn2 = 1;
-	gbcfg.nsip_sgsn2_nsei = SGSN2_NSEI;
-
-	if (gbproxy_set_patch_filter(&gbcfg.matches[GBPROX_MATCH_ROUTING],
-				     filter_re, &err_msg) != 0) {
-		fprintf(stderr, "gbprox_set_patch_filter: got error: %s\n",
-			err_msg);
-		OSMO_ASSERT(err_msg == NULL);
-	}
-
-	configure_sgsn_peer(&sgsn_peer[0]);
-	configure_sgsn2_peer(&sgsn_peer[1]);
-	configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
-
-	printf("=== %s ===\n", __func__);
-	printf("--- Initialise SGSN 1 ---\n\n");
-
-	connect_sgsn(nsi, &sgsn_peer[0], SGSN_NSEI);
-
-	printf("--- Initialise SGSN 2 ---\n\n");
-
-	connect_sgsn(nsi, &sgsn_peer[1], SGSN2_NSEI);
-
-	printf("--- Initialise BSS 1 ---\n\n");
-
-	setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
-	setup_bssgp(nsi, &bss_peer[0], 0x0);
-	send_bssgp_reset_ack(nsi, &sgsn_peer[0], 0x0);
-	setup_bssgp(nsi, &bss_peer[0], 0x1002);
-	send_bssgp_reset_ack(nsi, &sgsn_peer[0], 0x1002);
-	send_bssgp_reset_ack(nsi, &sgsn_peer[1], 0x1002);
-
-	peer = gbproxy_peer_by_nsei(&gbcfg, 0x1000);
-	OSMO_ASSERT(peer != NULL);
-
-	gprs_dump_nsi(nsi);
-	dump_global(stdout, 0);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Flow control ---\n\n");
-
-	send_bssgp_flow_control_bvc(nsi, &bss_peer[0], 0x1002, 1);
-	send_bssgp_flow_control_bvc_ack(nsi, &sgsn_peer[0], 0x1002, 1);
-	send_bssgp_flow_control_bvc_ack(nsi, &sgsn_peer[1], 0x1002, 1);
-
-	printf("--- Establish GPRS connection (SGSN 1) ---\n\n");
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_unknown, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req, sizeof(dtap_attach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity_resp, sizeof(dtap_identity_resp));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "IDENT REQUEST", &sgsn_peer[0], 0x1002,
-		       random_sgsn_tlli, 0, NULL, 0,
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_identity_req, sizeof(dtap_identity_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity_resp, sizeof(dtap_identity_resp));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer[0], 0x1002,
-		       random_sgsn_tlli, 1, imsi1, sizeof(imsi1),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli, SGSN2_NSEI));
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, random_sgsn_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_bss_tlli);
-	OSMO_ASSERT(link_info->tlli.current == foreign_bss_tlli);
-	OSMO_ASSERT(!link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->tlli.ptmsi == bss_ptmsi);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == random_sgsn_tlli);
-	OSMO_ASSERT(!link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.ptmsi == sgsn_ptmsi);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli, SGSN2_NSEI));
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_bss_tlli);
-	OSMO_ASSERT(link_info->tlli.current == foreign_bss_tlli);
-	OSMO_ASSERT(link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == random_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-
-	send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer[0], 0x1002,
-		       local_sgsn_tlli, 1, imsi1, sizeof(imsi1),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_gmm_information, sizeof(dtap_gmm_information));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli, SGSN2_NSEI));
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli, SGSN_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.current == local_bss_tlli);
-	OSMO_ASSERT(link_info->tlli.assigned == 0);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == local_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == 0);
-
-	/* Non-DTAP */
-	send_bssgp_ul_unitdata(nsi, "XID (UL)", &bss_peer[0], 0x1002,
-			       local_bss_tlli, &rai_bss, cell_id,
-			       llc_u_xid_ul, sizeof(llc_u_xid_ul));
-
-	send_bssgp_dl_unitdata(nsi, "XID (DL)", &sgsn_peer[0], 0x1002,
-			       local_sgsn_tlli, 1, imsi1, sizeof(imsi1),
-			       llc_u_xid_dl, sizeof(llc_u_xid_dl));
-
-	send_bssgp_ul_unitdata(nsi, "LL11 DNS QUERY (UL)", &bss_peer[0], 0x1002,
-			       local_bss_tlli, &rai_bss, cell_id,
-			       llc_ui_ll11_dns_query_ul,
-			       sizeof(llc_ui_ll11_dns_query_ul));
-
-	send_bssgp_dl_unitdata(nsi, "LL11 DNS RESP (DL)", &sgsn_peer[0], 0x1002,
-			       local_sgsn_tlli, 1, imsi1, sizeof(imsi1),
-			       llc_ui_ll11_dns_resp_dl,
-			       sizeof(llc_ui_ll11_dns_resp_dl));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Other messages */
-	send_bssgp_llc_discarded(nsi, &bss_peer[0], 0x1002,
-				 local_bss_tlli, 1, 12);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_bssgp_llc_discarded(nsi, &sgsn_peer[0], 0x1002,
-				 local_sgsn_tlli, 1, 12);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_bssgp_suspend(nsi, &bss_peer[0], local_bss_tlli, &rai_bss);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_bssgp_suspend_ack(nsi, &sgsn_peer[0], local_sgsn_tlli, &rai_sgsn);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Establish GPRS connection (SGSN 2) ---\n\n");
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli2, &rai_unknown, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req, sizeof(dtap_attach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli2, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity2_resp, sizeof(dtap_identity2_resp));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "IDENT REQUEST", &sgsn_peer[1], 0x1002,
-		       random_sgsn_tlli2, 0, NULL, 0,
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_identity_req, sizeof(dtap_identity_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli2, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity2_resp, sizeof(dtap_identity2_resp));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer[1], 0x1002,
-		       random_sgsn_tlli2, 1, imsi2, sizeof(imsi2),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc2, sizeof(dtap_attach_acc2));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_sgsn_tlli(peer, random_sgsn_tlli2, SGSN_NSEI));
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, random_sgsn_tlli2, SGSN2_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_bss_tlli2);
-	OSMO_ASSERT(link_info->tlli.current == foreign_bss_tlli2);
-	OSMO_ASSERT(!link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->tlli.ptmsi == bss_ptmsi2);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_sgsn_tlli2);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == random_sgsn_tlli2);
-	OSMO_ASSERT(!link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.ptmsi == sgsn_ptmsi2);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_bss_tlli2, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli2, SGSN_NSEI));
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli2, SGSN2_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_bss_tlli2);
-	OSMO_ASSERT(link_info->tlli.current == foreign_bss_tlli2);
-	OSMO_ASSERT(link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_sgsn_tlli2);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == random_sgsn_tlli2);
-	OSMO_ASSERT(link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-
-	send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer[1], 0x1002,
-		       local_sgsn_tlli2, 1, imsi2, sizeof(imsi2),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_gmm_information, sizeof(dtap_gmm_information));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli2, SGSN_NSEI));
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli2, SGSN2_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.current == local_bss_tlli2);
-	OSMO_ASSERT(link_info->tlli.assigned == 0);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == local_sgsn_tlli2);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == 0);
-
-	/* Non-DTAP */
-	send_bssgp_ul_unitdata(nsi, "XID (UL)", &bss_peer[0], 0x1002,
-			       local_bss_tlli2, &rai_bss, cell_id,
-			       llc_u_xid_ul, sizeof(llc_u_xid_ul));
-
-	send_bssgp_dl_unitdata(nsi, "XID (DL)", &sgsn_peer[1], 0x1002,
-			       local_sgsn_tlli2, 1, imsi2, sizeof(imsi2),
-			       llc_u_xid_dl, sizeof(llc_u_xid_dl));
-
-	send_bssgp_ul_unitdata(nsi, "LL11 DNS QUERY (UL)", &bss_peer[0], 0x1002,
-			       local_bss_tlli2, &rai_bss, cell_id,
-			       llc_ui_ll11_dns_query_ul,
-			       sizeof(llc_ui_ll11_dns_query_ul));
-
-	send_bssgp_dl_unitdata(nsi, "LL11 DNS RESP (DL)", &sgsn_peer[1], 0x1002,
-			       local_sgsn_tlli2, 1, imsi2, sizeof(imsi2),
-			       llc_ui_ll11_dns_resp_dl,
-			       sizeof(llc_ui_ll11_dns_resp_dl));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Other messages */
-	send_bssgp_llc_discarded(nsi, &bss_peer[0], 0x1002,
-				 local_bss_tlli2, 1, 12);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_bssgp_llc_discarded(nsi, &sgsn_peer[1], 0x1002,
-				 local_sgsn_tlli2, 1, 12);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_bssgp_suspend(nsi, &bss_peer[0], local_bss_tlli2, &rai_bss);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_bssgp_suspend_ack(nsi, &sgsn_peer[1], local_sgsn_tlli2, &rai_sgsn);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Establish GPRS connection (SGSN 2, P-TMSI collision) ---\n\n");
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli3, &rai_unknown, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req, sizeof(dtap_attach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli3, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity3_resp, sizeof(dtap_identity3_resp));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "IDENT REQUEST", &sgsn_peer[1], 0x1002,
-		       random_sgsn_tlli3, 0, NULL, 0,
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_identity_req, sizeof(dtap_identity_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_bss_tlli3, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity3_resp, sizeof(dtap_identity3_resp));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT (P-TMSI 1)", &sgsn_peer[1], 0x1002,
-		       random_sgsn_tlli3, 1, imsi3, sizeof(imsi3),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_sgsn_tlli(peer, random_sgsn_tlli3, SGSN_NSEI));
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, random_sgsn_tlli3, SGSN2_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_bss_tlli3);
-	OSMO_ASSERT(link_info->tlli.current == foreign_bss_tlli3);
-	OSMO_ASSERT(!link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->tlli.ptmsi == bss_ptmsi3);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == random_sgsn_tlli3);
-	OSMO_ASSERT(!link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.ptmsi == sgsn_ptmsi);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_bss_tlli3, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	other_info = gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli, SGSN_NSEI);
-	OSMO_ASSERT(other_info);
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli, SGSN2_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info != other_info);
-	OSMO_ASSERT(link_info->tlli.assigned == local_bss_tlli3);
-	OSMO_ASSERT(link_info->tlli.current == foreign_bss_tlli3);
-	OSMO_ASSERT(link_info->tlli.bss_validated);
-	OSMO_ASSERT(!link_info->tlli.net_validated);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == local_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == random_sgsn_tlli3);
-	OSMO_ASSERT(link_info->sgsn_tlli.bss_validated);
-	OSMO_ASSERT(!link_info->sgsn_tlli.net_validated);
-
-	send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer[1], 0x1002,
-		       local_sgsn_tlli, 1, imsi3, sizeof(imsi3),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_gmm_information, sizeof(dtap_gmm_information));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	other_info = gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli, SGSN_NSEI);
-	OSMO_ASSERT(other_info);
-	link_info = gbproxy_link_info_by_sgsn_tlli(peer, local_sgsn_tlli, SGSN2_NSEI);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info != other_info);
-	OSMO_ASSERT(link_info->tlli.current == local_bss_tlli3);
-	OSMO_ASSERT(link_info->tlli.assigned == 0);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == local_sgsn_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == 0);
-
-
-	printf("--- Shutdown GPRS connection (SGSN 1) ---\n\n");
-
-	/* Detach */
-	send_llc_ul_ui(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
-		       local_bss_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_detach_req, sizeof(dtap_detach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "DETACH ACC", &sgsn_peer[0], 0x1002,
-		       local_sgsn_tlli, 1, imsi1, sizeof(imsi1),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_detach_acc, sizeof(dtap_detach_acc));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Shutdown GPRS connection (SGSN 2) ---\n\n");
-
-	send_llc_ul_ui(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
-		       local_bss_tlli2, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_detach_req, sizeof(dtap_detach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "DETACH ACC", &sgsn_peer[1], 0x1002,
-		       local_sgsn_tlli2, 1, imsi2, sizeof(imsi2),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_detach_acc, sizeof(dtap_detach_acc));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Shutdown GPRS connection (SGSN 2, P-TMSI 1) ---\n\n");
-
-	send_llc_ul_ui(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
-		       local_bss_tlli3, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_detach_req, sizeof(dtap_detach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "DETACH ACC", &sgsn_peer[1], 0x1002,
-		       local_sgsn_tlli, 1, imsi3, sizeof(imsi3),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_detach_acc, sizeof(dtap_detach_acc));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	dump_global(stdout, 0);
-
-	gbproxy_clear_patch_filter(&gbcfg.matches[GBPROX_MATCH_ROUTING]);
-	gbprox_reset(&gbcfg);
-	gprs_ns_destroy(nsi);
-	nsi = NULL;
-
-	cleanup_test();
-}
-
-static void test_gbproxy_keep_info()
-{
-	struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
-	struct sockaddr_in bss_peer[1] = {{0},};
-	struct sockaddr_in sgsn_peer= {0};
-	struct  gprs_ra_id rai_bss =
-		{.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
-	uint16_t cell_id = 0x1234;
-
-	const uint32_t ptmsi = 0xefe2b700;
-	const uint32_t local_tlli = 0xefe2b700;
-	const uint32_t foreign_tlli = 0xafe2b700;
-
-	const uint8_t imsi[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};
-	struct gbproxy_link_info *link_info, *link_info2;
-	struct gbproxy_peer *peer;
-	unsigned bss_nu = 0;
-	unsigned sgsn_nu = 0;
-
-	LLIST_HEAD(rcv_list);
-
-	OSMO_ASSERT(local_tlli == gprs_tmsi2tlli(ptmsi, TLLI_LOCAL));
-
-	bssgp_nsi = nsi;
-	gbcfg.nsi = bssgp_nsi;
-	gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
-	gbcfg.patch_ptmsi = 0;
-	gbcfg.acquire_imsi = 1;
-	gbcfg.core_mcc = 0;
-	gbcfg.core_mnc = 0;
-	gbcfg.core_apn = NULL;
-	gbcfg.core_apn_size = 0;
-	gbcfg.route_to_sgsn2 = 0;
-	gbcfg.nsip_sgsn2_nsei = 0xffff;
-	gbcfg.keep_link_infos = GBPROX_KEEP_ALWAYS;
-
-	configure_sgsn_peer(&sgsn_peer);
-	configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
-
-	printf("=== %s ===\n", __func__);
-	printf("--- Initialise SGSN ---\n\n");
-
-	connect_sgsn(nsi, &sgsn_peer, SGSN_NSEI);
-
-	printf("--- Initialise BSS 1 ---\n\n");
-
-	setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
-	setup_bssgp(nsi, &bss_peer[0], 0x1002);
-
-	peer = gbproxy_peer_by_nsei(&gbcfg, 0x1000);
-	OSMO_ASSERT(peer != NULL);
-
-	send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
-
-	gprs_dump_nsi(nsi);
-	dump_global(stdout, 0);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
-
-	received_messages = &rcv_list;
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req, sizeof(dtap_attach_req));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ID_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->imsi_len == 0);
-	OSMO_ASSERT(!link_info->is_deregistered);
-	OSMO_ASSERT(link_info->imsi_acq_pending);
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity_resp, sizeof(dtap_identity_resp));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->imsi_len > 0);
-	OSMO_ASSERT(!link_info->imsi_acq_pending);
-	OSMO_ASSERT(gprs_tlli_type(link_info->sgsn_tlli.current) == TLLI_FOREIGN);
-
-	send_llc_dl_ui(nsi, "IDENT REQUEST", &sgsn_peer, 0x1002,
-		       foreign_tlli, 0, NULL, 0,
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_identity_req, sizeof(dtap_identity_req));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ID_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity_resp, sizeof(dtap_identity_resp));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ID_RESP));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->imsi_len > 0);
-	OSMO_ASSERT(gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi)));
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
-		       foreign_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ATTACH_ACK));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_COMPL));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
-		       local_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_gmm_information, sizeof(dtap_gmm_information));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_INFO));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, local_tlli);
-	OSMO_ASSERT(link_info);
-
-	/* Detach (MO) */
-	send_llc_ul_ui(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_detach_req, sizeof(dtap_detach_req));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_DETACH_REQ));
-
-	link_info = gbproxy_link_info_by_tlli(peer, local_tlli);
-	OSMO_ASSERT(link_info);
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
-		       local_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_detach_acc, sizeof(dtap_detach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_DETACH_ACK));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_tlli(peer, local_tlli));
-	link_info = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->is_deregistered);
-
-	OSMO_ASSERT(!expect_msg());
-
-	/* Re-Attach */
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req3, sizeof(dtap_attach_req3));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info2 = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info == link_info2);
-	OSMO_ASSERT(link_info->imsi_len != 0);
-	OSMO_ASSERT(!link_info->is_deregistered);
-	OSMO_ASSERT(!link_info->imsi_acq_pending);
-	OSMO_ASSERT(gprs_tlli_type(link_info->sgsn_tlli.current) == TLLI_FOREIGN);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
-		       foreign_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ATTACH_ACK));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_COMPL));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Detach (MT) */
-	send_llc_dl_ui(nsi, "DETACH REQ (re-attach)", &sgsn_peer, 0x1002,
-		       local_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_mt_detach_rea_req, sizeof(dtap_mt_detach_rea_req));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_DETACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, local_tlli);
-	OSMO_ASSERT(link_info);
-
-	send_llc_ul_ui(nsi, "DETACH ACC", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_mt_detach_acc, sizeof(dtap_mt_detach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_DETACH_ACK));
-	OSMO_ASSERT(!expect_msg());
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_tlli(peer, local_tlli));
-	link_info = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->is_deregistered);
-
-	/* Re-Attach */
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req3, sizeof(dtap_attach_req3));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info2 = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info == link_info2);
-	OSMO_ASSERT(link_info->imsi_len != 0);
-	OSMO_ASSERT(!link_info->is_deregistered);
-	OSMO_ASSERT(!link_info->imsi_acq_pending);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
-		       foreign_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ATTACH_ACK));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_COMPL));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Detach (MT) */
-	send_llc_dl_ui(nsi, "DETACH REQ", &sgsn_peer, 0x1002,
-		       local_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_mt_detach_req, sizeof(dtap_mt_detach_req));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_DETACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, local_tlli);
-	OSMO_ASSERT(link_info);
-
-	send_llc_ul_ui(nsi, "DETACH ACC", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_mt_detach_acc, sizeof(dtap_mt_detach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_DETACH_ACK));
-	OSMO_ASSERT(!expect_msg());
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_tlli(peer, local_tlli));
-	link_info = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->is_deregistered);
-
-	/* Re-Attach with IMSI */
-	send_llc_ul_ui(nsi, "ATTACH REQUEST (IMSI)", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req4, sizeof(dtap_attach_req4));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info2 = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info == link_info2);
-	OSMO_ASSERT(link_info->imsi_len != 0);
-	OSMO_ASSERT(!link_info->is_deregistered);
-	OSMO_ASSERT(!link_info->imsi_acq_pending);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == foreign_tlli);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
-		       foreign_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ATTACH_ACK));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_COMPL));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Detach (MT) */
-	send_llc_dl_ui(nsi, "DETACH REQ", &sgsn_peer, 0x1002,
-		       local_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_mt_detach_req, sizeof(dtap_mt_detach_req));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_DETACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, local_tlli);
-	OSMO_ASSERT(link_info);
-
-	send_llc_ul_ui(nsi, "DETACH ACC", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_mt_detach_acc, sizeof(dtap_mt_detach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_DETACH_ACK));
-	OSMO_ASSERT(!expect_msg());
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_tlli(peer, local_tlli));
-	link_info = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->is_deregistered);
-
-	/* Re-Attach */
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req3, sizeof(dtap_attach_req3));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info2 = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info == link_info2);
-	OSMO_ASSERT(link_info->imsi_len != 0);
-	OSMO_ASSERT(!link_info->is_deregistered);
-	OSMO_ASSERT(!link_info->imsi_acq_pending);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
-		       foreign_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ATTACH_ACK));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_COMPL));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* RA update procedure (reject -> Detach) */
-	send_llc_ul_ui(nsi, "RA UPD REQ", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, 0x7080,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_ra_upd_req, sizeof(dtap_ra_upd_req));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_RA_UPD_REQ));
-
-	send_llc_dl_ui(nsi, "RA UDP REJ", &sgsn_peer, 0x1002,
-		       local_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_ra_upd_rej, sizeof(dtap_ra_upd_rej));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_RA_UPD_REJ));
-	OSMO_ASSERT(!expect_msg());
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_tlli(peer, local_tlli));
-	link_info = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->is_deregistered);
-
-	/* Bad case: Re-Attach with wrong (initial) P-TMSI */
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req, sizeof(dtap_attach_req));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ID_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info2 = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info != link_info2);
-	OSMO_ASSERT(link_info->imsi_len == 0);
-	OSMO_ASSERT(!link_info->is_deregistered);
-	OSMO_ASSERT(link_info->imsi_acq_pending);
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity_resp, sizeof(dtap_identity_resp));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info2 = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info == link_info2);
-	OSMO_ASSERT(link_info->imsi_len != 0);
-	OSMO_ASSERT(!link_info->is_deregistered);
-	OSMO_ASSERT(!link_info->imsi_acq_pending);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
-		       foreign_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ATTACH_ACK));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info2 = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info == link_info2);
-	OSMO_ASSERT(link_info->imsi_len > 0);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_COMPL));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Detach (MT) */
-	send_llc_dl_ui(nsi, "DETACH REQ", &sgsn_peer, 0x1002,
-		       local_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_mt_detach_req, sizeof(dtap_mt_detach_req));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_DETACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, local_tlli);
-	OSMO_ASSERT(link_info);
-
-	send_llc_ul_ui(nsi, "DETACH ACC", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_mt_detach_acc, sizeof(dtap_mt_detach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_DETACH_ACK));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_tlli(peer, local_tlli));
-	link_info = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->is_deregistered);
-
-	OSMO_ASSERT(!expect_msg());
-
-	/* Bad case: Re-Attach with local TLLI */
-	send_llc_ul_ui(nsi, "ATTACH REQUEST (local TLLI)", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req3, sizeof(dtap_attach_req3));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info2 = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	link_info = gbproxy_link_info_by_tlli(peer, local_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info == link_info2);
-	OSMO_ASSERT(link_info->imsi_len != 0);
-	OSMO_ASSERT(!link_info->is_deregistered);
-	OSMO_ASSERT(!link_info->imsi_acq_pending);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == local_tlli);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
-		       local_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ATTACH_ACK));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_COMPL));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Detach (MT) */
-	send_llc_dl_ui(nsi, "DETACH REQ (re-attach)", &sgsn_peer, 0x1002,
-		       local_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_mt_detach_rea_req, sizeof(dtap_mt_detach_rea_req));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_DETACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, local_tlli);
-	OSMO_ASSERT(link_info);
-
-	send_llc_ul_ui(nsi, "DETACH ACC", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_mt_detach_acc, sizeof(dtap_mt_detach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_DETACH_ACK));
-	OSMO_ASSERT(!expect_msg());
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_tlli(peer, local_tlli));
-	link_info = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->is_deregistered);
-
-	/* Bad case: Unexpected Re-Attach with IMSI after completed attachment
-	 * procedure */
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req3, sizeof(dtap_attach_req3));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info2 = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info == link_info2);
-	OSMO_ASSERT(link_info->imsi_len != 0);
-	OSMO_ASSERT(!link_info->is_deregistered);
-	OSMO_ASSERT(!link_info->imsi_acq_pending);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
-		       foreign_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ATTACH_ACK));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_COMPL));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
-		       local_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_gmm_information, sizeof(dtap_gmm_information));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_INFO));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST (unexpected, IMSI)",
-		       &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req4, sizeof(dtap_attach_req4));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info2 = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info == link_info2);
-	OSMO_ASSERT(link_info->imsi_len != 0);
-	OSMO_ASSERT(!link_info->is_deregistered);
-	OSMO_ASSERT(!link_info->imsi_acq_pending);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == foreign_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == 0);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
-		       foreign_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ATTACH_ACK));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_COMPL));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Detach (MT) */
-	send_llc_dl_ui(nsi, "DETACH REQ", &sgsn_peer, 0x1002,
-		       local_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_mt_detach_req, sizeof(dtap_mt_detach_req));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_DETACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, local_tlli);
-	OSMO_ASSERT(link_info);
-
-	send_llc_ul_ui(nsi, "DETACH ACC", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_mt_detach_acc, sizeof(dtap_mt_detach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_DETACH_ACK));
-	OSMO_ASSERT(!expect_msg());
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_tlli(peer, local_tlli));
-	link_info = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->is_deregistered);
-
-	/* Bad case: Unexpected Re-Attach with P-TMSI after completed attachment
-	 * procedure */
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req3, sizeof(dtap_attach_req3));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info2 = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info == link_info2);
-	OSMO_ASSERT(link_info->imsi_len != 0);
-	OSMO_ASSERT(!link_info->is_deregistered);
-	OSMO_ASSERT(!link_info->imsi_acq_pending);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
-		       foreign_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ATTACH_ACK));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_COMPL));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
-		       local_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_gmm_information, sizeof(dtap_gmm_information));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_INFO));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST (unexpected)", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req3, sizeof(dtap_attach_req3));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info2 = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info == link_info2);
-	OSMO_ASSERT(link_info->imsi_len != 0);
-	OSMO_ASSERT(!link_info->is_deregistered);
-	OSMO_ASSERT(!link_info->imsi_acq_pending);
-	OSMO_ASSERT(link_info->sgsn_tlli.current == foreign_tlli);
-	OSMO_ASSERT(link_info->sgsn_tlli.assigned == 0);
-
-	send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
-		       foreign_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_acc, sizeof(dtap_attach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ATTACH_ACK));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_complete, sizeof(dtap_attach_complete));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_COMPL));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	/* Detach (MT) */
-	send_llc_dl_ui(nsi, "DETACH REQ", &sgsn_peer, 0x1002,
-		       local_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_mt_detach_req, sizeof(dtap_mt_detach_req));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_DETACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, local_tlli);
-	OSMO_ASSERT(link_info);
-
-	send_llc_ul_ui(nsi, "DETACH ACC", &bss_peer[0], 0x1002,
-		       local_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_mt_detach_acc, sizeof(dtap_mt_detach_acc));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_DETACH_ACK));
-	OSMO_ASSERT(!expect_msg());
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_tlli(peer, local_tlli));
-	link_info = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->is_deregistered);
-
-
-	/* Attach rejected */
-
-	gbproxy_delete_link_infos(peer);
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req, sizeof(dtap_attach_req));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ID_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->imsi_len == 0);
-	OSMO_ASSERT(!link_info->is_deregistered);
-	OSMO_ASSERT(link_info->imsi_acq_pending);
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity_resp, sizeof(dtap_identity_resp));
-
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info2 = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info == link_info2);
-	OSMO_ASSERT(link_info->imsi_len != 0);
-	OSMO_ASSERT(!link_info->is_deregistered);
-	OSMO_ASSERT(!link_info->imsi_acq_pending);
-
-	send_llc_dl_ui(nsi, "ATTACH REJECT", &sgsn_peer, 0x1002,
-		       foreign_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_attach_rej7, sizeof(dtap_attach_rej7));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ATTACH_REJ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_tlli(peer, foreign_tlli));
-
-	OSMO_ASSERT(!expect_msg());
-
-	/* Attach (incomplete) and Detach (MO) */
-
-	gbproxy_delete_link_infos(peer);
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req, sizeof(dtap_attach_req));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ID_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->imsi_len == 0);
-	OSMO_ASSERT(!link_info->is_deregistered);
-	OSMO_ASSERT(link_info->imsi_acq_pending);
-
-	send_llc_ul_ui(nsi, "DETACH REQ (MO)", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_detach_req, sizeof(dtap_detach_req));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_DETACH_ACK));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!expect_msg());
-
-	/* Attach (incomplete) and Detach (MT) */
-
-	gbproxy_delete_link_infos(peer);
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req, sizeof(dtap_attach_req));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_ID_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->imsi_len == 0);
-	OSMO_ASSERT(!link_info->is_deregistered);
-	OSMO_ASSERT(link_info->imsi_acq_pending);
-
-	send_llc_dl_ui(nsi, "DETACH REQ (MT)", &sgsn_peer, 0x1002,
-		       foreign_tlli, 1, imsi, sizeof(imsi),
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_mt_detach_req, sizeof(dtap_mt_detach_req));
-
-	OSMO_ASSERT(expect_gmm_msg(0x1000, 0x1002, GSM48_MT_GMM_DETACH_REQ));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	link_info = gbproxy_link_info_by_tlli(peer, foreign_tlli);
-	OSMO_ASSERT(link_info);
-
-	send_llc_ul_ui(nsi, "DETACH ACC", &bss_peer[0], 0x1002,
-		       foreign_tlli, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_mt_detach_acc, sizeof(dtap_mt_detach_acc));
-
-	/* TODO: The stored messaged should be cleaned when receiving a Detach
-	 * Ack. Remove the first OSMO_ASSERT when this is fixed. */
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_ATTACH_REQ));
-	OSMO_ASSERT(expect_gmm_msg(SGSN_NSEI, 0x1002, GSM48_MT_GMM_DETACH_ACK));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	OSMO_ASSERT(!gbproxy_link_info_by_tlli(peer, foreign_tlli));
-	link_info = gbproxy_link_info_by_imsi(peer, imsi, sizeof(imsi));
-	OSMO_ASSERT(link_info);
-	OSMO_ASSERT(link_info->is_deregistered);
-
-	OSMO_ASSERT(!expect_msg());
-	received_messages = NULL;
-
-	dump_global(stdout, 0);
-
-	gbprox_reset(&gbcfg);
-	gprs_ns_destroy(nsi);
-	nsi = NULL;
-
-	cleanup_test();
-}
-
-struct gbproxy_link_info *register_tlli(
-	struct gbproxy_peer *peer, uint32_t tlli,
-	const uint8_t *imsi, size_t imsi_len, time_t now)
-{
-	struct gbproxy_link_info *link_info;
-	int imsi_matches = -1;
-	int tlli_already_known = 0;
-	struct gbproxy_config *cfg = peer->cfg;
-
-	/* Check, whether the IMSI matches */
-	if (gprs_is_mi_imsi(imsi, imsi_len)) {
-		imsi_matches = gbproxy_check_imsi(
-			&cfg->matches[GBPROX_MATCH_PATCHING], imsi, imsi_len);
-		if (imsi_matches < 0)
-			return NULL;
-	}
-
-	link_info = gbproxy_link_info_by_tlli(peer, tlli);
-
-	if (!link_info) {
-		link_info = gbproxy_link_info_by_imsi(peer, imsi, imsi_len);
-
-		if (link_info) {
-			/* TLLI has changed somehow, adjust it */
-			LOGP(DGPRS, LOGL_INFO,
-			     "The TLLI has changed from %08x to %08x\n",
-			     link_info->tlli.current, tlli);
-			link_info->tlli.current = tlli;
-		}
-	}
-
-	if (!link_info) {
-		link_info = gbproxy_link_info_alloc(peer);
-		link_info->tlli.current = tlli;
-	} else {
-		gbproxy_detach_link_info(peer, link_info);
-		tlli_already_known = 1;
-	}
-
-	OSMO_ASSERT(link_info != NULL);
-
-	if (!tlli_already_known)
-		LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list\n", tlli);
-
-	gbproxy_attach_link_info(peer, now, link_info);
-	gbproxy_update_link_info(link_info, imsi, imsi_len);
-
-	if (imsi_matches >= 0)
-		link_info->is_matching[GBPROX_MATCH_PATCHING] = imsi_matches;
-
-	return link_info;
-}
-
-static void test_gbproxy_tlli_expire(void)
-{
-	struct gbproxy_config cfg = {0};
-	struct gbproxy_peer *peer;
-	const char *err_msg = NULL;
-	const uint8_t imsi1[] = { GSM_MI_TYPE_IMSI, 0x23, 0x24, 0x25, 0x26 };
-	const uint8_t imsi2[] = { GSM_MI_TYPE_IMSI, 0x26, 0x27, 0x28, 0x29 };
-	const uint8_t imsi3[] = { GSM_MI_TYPE_IMSI | 0x10, 0x32, 0x54, 0x76, 0xf8 };
-	const uint32_t tlli1 = 1234 | 0xc0000000;
-	const uint32_t tlli2 = 5678 | 0xc0000000;
-	const uint32_t tlli3 = 3456 | 0xc0000000;
-	const char *filter_re = ".*";
-	time_t now = 1407479214;
-
-	printf("Test TLLI info expiry\n\n");
-
-	gbproxy_init_config(&cfg);
-
-	if (gbproxy_set_patch_filter(&cfg.matches[GBPROX_MATCH_PATCHING],
-				     filter_re, &err_msg) != 0) {
-		fprintf(stderr, "gbprox_set_patch_filter: got error: %s\n",
-			err_msg);
-		OSMO_ASSERT(err_msg == NULL);
-	}
-
-	{
-		struct gbproxy_link_info *link_info;
-
-		printf("Test TLLI replacement:\n");
-
-		cfg.tlli_max_len = 0;
-		cfg.tlli_max_age = 0;
-		peer = gbproxy_peer_alloc(&cfg, 20);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 0);
-
-		printf("  Add TLLI 1, IMSI 1\n");
-		link_info = register_tlli(peer, tlli1,
-						  imsi1, ARRAY_SIZE(imsi1), now);
-		OSMO_ASSERT(link_info);
-		OSMO_ASSERT(link_info->tlli.current == tlli1);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 1);
-
-		/* replace the old entry */
-		printf("  Add TLLI 2, IMSI 1 (should replace TLLI 1)\n");
-		link_info = register_tlli(peer, tlli2,
-						  imsi1, ARRAY_SIZE(imsi1), now);
-		OSMO_ASSERT(link_info);
-		OSMO_ASSERT(link_info->tlli.current == tlli2);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 1);
-
-		dump_peers(stdout, 2, now, &cfg);
-
-		/* verify that 5678 has survived */
-		link_info = gbproxy_link_info_by_imsi(peer, imsi1, ARRAY_SIZE(imsi1));
-		OSMO_ASSERT(link_info);
-		OSMO_ASSERT(link_info->tlli.current == tlli2);
-		link_info = gbproxy_link_info_by_imsi(peer, imsi2, ARRAY_SIZE(imsi2));
-		OSMO_ASSERT(!link_info);
-
-		printf("\n");
-
-		gbproxy_peer_free(peer);
-	}
-
-	{
-		struct gbproxy_link_info *link_info;
-
-		printf("Test IMSI replacement:\n");
-
-		cfg.tlli_max_len = 0;
-		cfg.tlli_max_age = 0;
-		peer = gbproxy_peer_alloc(&cfg, 20);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 0);
-
-		printf("  Add TLLI 1, IMSI 1\n");
-		link_info = register_tlli(peer, tlli1,
-						  imsi1, ARRAY_SIZE(imsi1), now);
-		OSMO_ASSERT(link_info);
-		OSMO_ASSERT(link_info->tlli.current == tlli1);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 1);
-
-		/* try to replace the old entry */
-		printf("  Add TLLI 1, IMSI 2 (should replace IMSI 1)\n");
-		link_info = register_tlli(peer, tlli1,
-						  imsi2, ARRAY_SIZE(imsi2), now);
-		OSMO_ASSERT(link_info);
-		OSMO_ASSERT(link_info->tlli.current == tlli1);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 1);
-
-		dump_peers(stdout, 2, now, &cfg);
-
-		/* verify that 5678 has survived */
-		link_info = gbproxy_link_info_by_imsi(peer, imsi1, ARRAY_SIZE(imsi1));
-		OSMO_ASSERT(!link_info);
-		link_info = gbproxy_link_info_by_imsi(peer, imsi2, ARRAY_SIZE(imsi2));
-		OSMO_ASSERT(link_info);
-		OSMO_ASSERT(link_info->tlli.current == tlli1);
-
-		printf("\n");
-
-		gbproxy_peer_free(peer);
-	}
-
-	{
-		struct gbproxy_link_info *link_info;
-		int num_removed;
-
-		printf("Test TLLI expiry, max_len == 1:\n");
-
-		cfg.tlli_max_len = 1;
-		cfg.tlli_max_age = 0;
-		peer = gbproxy_peer_alloc(&cfg, 20);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 0);
-
-		printf("  Add TLLI 1, IMSI 1\n");
-		register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 1);
-
-		/* replace the old entry */
-		printf("  Add TLLI 2, IMSI 2 (should replace IMSI 1)\n");
-		register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2), now);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 2);
-
-		num_removed = gbproxy_remove_stale_link_infos(peer, now + 2);
-		OSMO_ASSERT(num_removed == 1);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 1);
-
-		dump_peers(stdout, 2, now, &cfg);
-
-		/* verify that 5678 has survived */
-		link_info = gbproxy_link_info_by_imsi(peer, imsi1, ARRAY_SIZE(imsi1));
-		OSMO_ASSERT(!link_info);
-		link_info = gbproxy_link_info_by_imsi(peer, imsi2, ARRAY_SIZE(imsi2));
-		OSMO_ASSERT(link_info);
-		OSMO_ASSERT(link_info->tlli.current == tlli2);
-
-		printf("\n");
-
-		gbproxy_peer_free(peer);
-	}
-
-	{
-		struct gbproxy_link_info *link_info;
-		int num_removed;
-
-		printf("Test TLLI expiry, max_age == 1:\n");
-
-		cfg.tlli_max_len = 0;
-		cfg.tlli_max_age = 1;
-		peer = gbproxy_peer_alloc(&cfg, 20);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 0);
-
-		printf("  Add TLLI 1, IMSI 1 (should expire after timeout)\n");
-		register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 1);
-
-		printf("  Add TLLI 2, IMSI 2 (should not expire after timeout)\n");
-		register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2),
-				     now + 1);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 2);
-
-		num_removed = gbproxy_remove_stale_link_infos(peer, now + 2);
-		OSMO_ASSERT(num_removed == 1);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 1);
-
-		dump_peers(stdout, 2, now + 2, &cfg);
-
-		/* verify that 5678 has survived */
-		link_info = gbproxy_link_info_by_imsi(peer, imsi1, ARRAY_SIZE(imsi1));
-		OSMO_ASSERT(!link_info);
-		link_info = gbproxy_link_info_by_imsi(peer, imsi2, ARRAY_SIZE(imsi2));
-		OSMO_ASSERT(link_info);
-		OSMO_ASSERT(link_info->tlli.current == tlli2);
-
-		printf("\n");
-
-		gbproxy_peer_free(peer);
-	}
-
-	{
-		struct gbproxy_link_info *link_info;
-		int num_removed;
-
-		printf("Test TLLI expiry, max_len == 2, max_age == 1:\n");
-
-		cfg.tlli_max_len = 0;
-		cfg.tlli_max_age = 1;
-		peer = gbproxy_peer_alloc(&cfg, 20);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 0);
-
-		printf("  Add TLLI 1, IMSI 1 (should expire)\n");
-		register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 1);
-
-		printf("  Add TLLI 2, IMSI 2 (should expire after timeout)\n");
-		register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2),
-				     now + 1);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 2);
-
-		printf("  Add TLLI 3, IMSI 3 (should not expire after timeout)\n");
-		register_tlli(peer, tlli3, imsi3, ARRAY_SIZE(imsi3),
-				      now + 2);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 3);
-
-		dump_peers(stdout, 2, now + 2, &cfg);
-
-		printf("  Remove stale TLLIs\n");
-		num_removed = gbproxy_remove_stale_link_infos(peer, now + 3);
-		OSMO_ASSERT(num_removed == 2);
-		OSMO_ASSERT(peer->patch_state.logical_link_count == 1);
-
-		dump_peers(stdout, 2, now + 2, &cfg);
-
-		/* verify that tlli3 has survived */
-		link_info = gbproxy_link_info_by_imsi(peer, imsi1, ARRAY_SIZE(imsi1));
-		OSMO_ASSERT(!link_info);
-		link_info = gbproxy_link_info_by_imsi(peer, imsi2, ARRAY_SIZE(imsi2));
-		OSMO_ASSERT(!link_info);
-		link_info = gbproxy_link_info_by_imsi(peer, imsi3, ARRAY_SIZE(imsi3));
-		OSMO_ASSERT(link_info);
-		OSMO_ASSERT(link_info->tlli.current == tlli3);
-
-		printf("\n");
-
-		gbproxy_peer_free(peer);
-	}
-	gbproxy_clear_patch_filter(&cfg.matches[GBPROX_MATCH_PATCHING]);
-	gbprox_reset(&cfg);
-
-	cleanup_test();
-}
-
-static void test_gbproxy_imsi_matching(void)
-{
-	const char *err_msg = NULL;
-	const uint8_t imsi1[] = { GSM_MI_TYPE_IMSI | 0x10, 0x32, 0x54, 0xf6 };
-	const uint8_t imsi2[] = { GSM_MI_TYPE_IMSI | GSM_MI_ODD | 0x10, 0x32, 0x54, 0x76 };
-	const uint8_t imsi3_bad[] = { GSM_MI_TYPE_IMSI | 0x10, 0xee, 0x54, 0xff };
-	const uint8_t tmsi1[] = { GSM_MI_TYPE_TMSI | 0xf0, 0x11, 0x22, 0x33, 0x44 };
-	const uint8_t tmsi2_bad[] = { GSM_MI_TYPE_TMSI | 0xf0, 0x11, 0x22 };
-	const uint8_t imei1[] = { GSM_MI_TYPE_IMEI | 0x10, 0x32, 0x54, 0xf6 };
-	const uint8_t imei2[] = { GSM_MI_TYPE_IMEI | GSM_MI_ODD | 0x10, 0x32, 0x54, 0x76 };
-	const char *filter_re1 = ".*";
-	const char *filter_re2 = "^1234";
-	const char *filter_re3 = "^4321";
-	const char *filter_re4_bad = "^12[";
-	struct gbproxy_match match = {0,};
-
-	printf("=== Test IMSI/TMSI matching ===\n\n");
-
-	OSMO_ASSERT(match.enable == 0);
-
-	OSMO_ASSERT(gbproxy_set_patch_filter(&match, filter_re1, &err_msg) == 0);
-	OSMO_ASSERT(match.enable == 1);
-
-	OSMO_ASSERT(gbproxy_set_patch_filter(&match, filter_re2, &err_msg) == 0);
-	OSMO_ASSERT(match.enable == 1);
-
-	err_msg = NULL;
-	OSMO_ASSERT(gbproxy_set_patch_filter(&match, filter_re4_bad, &err_msg) == -1);
-	OSMO_ASSERT(err_msg != NULL);
-	OSMO_ASSERT(match.enable == 0);
-
-	OSMO_ASSERT(gbproxy_set_patch_filter(&match, filter_re2, &err_msg) == 0);
-	OSMO_ASSERT(match.enable == 1);
-
-	OSMO_ASSERT(gbproxy_set_patch_filter(&match, NULL, &err_msg) == 0);
-	OSMO_ASSERT(match.enable == 0);
-
-	OSMO_ASSERT(gbproxy_set_patch_filter(&match, filter_re2, &err_msg) == 0);
-	OSMO_ASSERT(match.enable == 1);
-
-	gbproxy_clear_patch_filter(&match);
-	OSMO_ASSERT(match.enable == 0);
-
-	OSMO_ASSERT(gbproxy_set_patch_filter(&match, filter_re2, &err_msg) == 0);
-	OSMO_ASSERT(match.enable == 1);
-
-	OSMO_ASSERT(gbproxy_check_imsi(&match, imsi1, ARRAY_SIZE(imsi1)) == 1);
-	OSMO_ASSERT(gbproxy_check_imsi(&match, imsi2, ARRAY_SIZE(imsi2)) == 1);
-	/* imsi3_bad contains 0xE and 0xF digits, but the conversion function
-	 * doesn't complain, so gbproxy_check_imsi() doesn't return -1 in this
-	 * case. */
-	OSMO_ASSERT(gbproxy_check_imsi(&match, imsi3_bad, ARRAY_SIZE(imsi3_bad)) == 0);
-	OSMO_ASSERT(gbproxy_check_imsi(&match, tmsi1, ARRAY_SIZE(tmsi1)) == -1);
-	OSMO_ASSERT(gbproxy_check_imsi(&match, tmsi2_bad, ARRAY_SIZE(tmsi2_bad)) == -1);
-	OSMO_ASSERT(gbproxy_check_imsi(&match, imei1, ARRAY_SIZE(imei1)) == -1);
-	OSMO_ASSERT(gbproxy_check_imsi(&match, imei2, ARRAY_SIZE(imei2)) == -1);
-
-	OSMO_ASSERT(gbproxy_set_patch_filter(&match, filter_re3, &err_msg) == 0);
-	OSMO_ASSERT(match.enable == 1);
-
-	OSMO_ASSERT(gbproxy_check_imsi(&match, imsi1, ARRAY_SIZE(imsi1)) == 0);
-	OSMO_ASSERT(gbproxy_check_imsi(&match, imsi2, ARRAY_SIZE(imsi2)) == 0);
-	OSMO_ASSERT(gbproxy_check_imsi(&match, imsi3_bad, ARRAY_SIZE(imsi3_bad)) == 0);
-	OSMO_ASSERT(gbproxy_check_imsi(&match, tmsi1, ARRAY_SIZE(tmsi1)) == -1);
-	OSMO_ASSERT(gbproxy_check_imsi(&match, tmsi2_bad, ARRAY_SIZE(tmsi2_bad)) == -1);
-	OSMO_ASSERT(gbproxy_check_imsi(&match, imei1, ARRAY_SIZE(imei1)) == -1);
-	OSMO_ASSERT(gbproxy_check_imsi(&match, imei2, ARRAY_SIZE(imei2)) == -1);
-
-	/* TODO: Check correct length but wrong type with is_mi_tmsi */
-
-	gbproxy_clear_patch_filter(&match);
-	OSMO_ASSERT(match.enable == 0);
-
-	cleanup_test();
-}
-
-static void test_gbproxy_stored_messages()
-{
-	struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
-	struct sockaddr_in bss_peer[1] = {{0},};
-	struct sockaddr_in sgsn_peer= {0};
-	struct  gprs_ra_id rai_bss =
-		{.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
-	struct  gprs_ra_id rai_unknown =
-		{.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
-	uint16_t cell_id = 0x1234;
-
-	const uint32_t ptmsi = 0xefe2b700;
-	const uint32_t local_tlli = 0xefe2b700;
-
-	const uint32_t foreign_tlli1 = 0x8000dead;
-
-	struct gbproxy_peer *peer;
-	unsigned bss_nu = 0;
-	unsigned sgsn_nu = 0;
-
-	OSMO_ASSERT(local_tlli == gprs_tmsi2tlli(ptmsi, TLLI_LOCAL));
-
-	bssgp_nsi = nsi;
-	gbcfg.nsi = bssgp_nsi;
-	gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
-	gbcfg.core_mcc = 0;
-	gbcfg.core_mnc = 0;
-	gbcfg.core_apn = talloc_zero_size(NULL, 100);
-	gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
-	gbcfg.patch_ptmsi = 0;
-	gbcfg.acquire_imsi = 1;
-	gbcfg.keep_link_infos = 0;
-
-	configure_sgsn_peer(&sgsn_peer);
-	configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
-
-	printf("=== %s ===\n", __func__);
-	printf("--- Initialise SGSN ---\n\n");
-
-	connect_sgsn(nsi, &sgsn_peer, SGSN_NSEI);
-
-	printf("--- Initialise BSS 1 ---\n\n");
-
-	setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
-	setup_bssgp(nsi, &bss_peer[0], 0x1002);
-
-	peer = gbproxy_peer_by_nsei(&gbcfg, 0x1000);
-	OSMO_ASSERT(peer != NULL);
-
-	send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
-
-	gprs_dump_nsi(nsi);
-	dump_global(stdout, 0);
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	printf("--- Establish first LLC connection ---\n\n");
-
-	send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
-		       foreign_tlli1, &rai_unknown, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_attach_req, sizeof(dtap_attach_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_dl_ui(nsi, "IDENT REQUEST", &sgsn_peer, 0x1002,
-		       foreign_tlli1, 0, NULL, 0,
-		       GPRS_SAPI_GMM, sgsn_nu++,
-		       dtap_identity_req, sizeof(dtap_identity_req));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "DETACH ACCEPT", &bss_peer[0], 0x1002,
-		       foreign_tlli1, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_detach_acc, sizeof(dtap_detach_acc));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
-		       foreign_tlli1, &rai_bss, cell_id,
-		       GPRS_SAPI_GMM, bss_nu++,
-		       dtap_identity_resp, sizeof(dtap_identity_resp));
-
-	dump_peers(stdout, 0, 0, &gbcfg);
-
-	dump_global(stdout, 0);
-
-	gbprox_reset(&gbcfg);
-	gprs_ns_destroy(nsi);
-	nsi = NULL;
-
-	cleanup_test();
-}
-
-static struct log_info_cat gprs_categories[] = {
-	[DGPRS] = {
-		.name = "DGPRS",
-		.description = "GPRS Packet Service",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DNS] = {
-		.name = "DNS",
-		.description = "GPRS Network Service (NS)",
-		.enabled = 1, .loglevel = LOGL_INFO,
-	},
-	[DBSSGP] = {
-		.name = "DBSSGP",
-		.description = "GPRS BSS Gateway Protocol (BSSGP)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-};
-
-static struct log_info info = {
-	.cat = gprs_categories,
-	.num_cat = ARRAY_SIZE(gprs_categories),
-};
-
-int main(int argc, char **argv)
-{
-	msgb_talloc_ctx_init(NULL, 0);
-
-	osmo_init_logging(&info);
-	log_set_use_color(osmo_stderr_target, 0);
-	log_set_print_filename(osmo_stderr_target, 0);
-	osmo_signal_register_handler(SS_L_NS, &test_signal, &gbcfg);
-
-	log_set_print_filename(osmo_stderr_target, 0);
-	log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
-	log_set_all_filter(osmo_stderr_target, 1);
-
-	rate_ctr_init(NULL);
-
-	setlinebuf(stdout);
-
-	printf("===== GbProxy test START\n");
-	gbproxy_init_config(&gbcfg);
-	test_gbproxy();
-	test_gbproxy_ident_changes();
-	test_gbproxy_imsi_matching();
-	test_gbproxy_ptmsi_assignment();
-	test_gbproxy_ra_patching();
-	test_gbproxy_ptmsi_patching();
-	test_gbproxy_ptmsi_patching_bad_cases();
-	test_gbproxy_imsi_acquisition();
-	test_gbproxy_secondary_sgsn();
-	test_gbproxy_keep_info();
-	test_gbproxy_tlli_expire();
-	test_gbproxy_stored_messages();
-	printf("===== GbProxy test END\n\n");
-
-	exit(EXIT_SUCCESS);
-}
diff --git a/tests/gbproxy/gbproxy_test.ok b/tests/gbproxy/gbproxy_test.ok
deleted file mode 100644
index 737aec0..0000000
--- a/tests/gbproxy/gbproxy_test.ok
+++ /dev/null
@@ -1,7244 +0,0 @@
-===== GbProxy test START
-=== test_gbproxy ===
---- Initialise SGSN ---
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 12
-02 00 81 01 01 82 01 01 04 82 01 00 
-
-PROCESSING RESET_ACK from 0x05060708:32000
-03 01 82 01 01 04 82 01 00 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0a 
-
-result (RESET_ACK) = 1
-
-PROCESSING ALIVE_ACK from 0x05060708:32000
-0b 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-06 
-
-result (ALIVE_ACK) = 1
-
-PROCESSING UNBLOCK_ACK from 0x05060708:32000
-07 
-
-==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000
-
-result (UNBLOCK_ACK) = 0
-
-PROCESSING ALIVE from 0x05060708:32000
-0a 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-Current NS-VCIs:
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
---- Initialise BSS 1 ---
-
-Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096)
-
-PROCESSING RESET from 0x01020304:1111
-02 00 81 01 01 82 10 01 04 82 10 00 
-
-==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-03 01 82 10 01 04 82 10 00 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:1111
-0a 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:1111
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:1111
-0b 
-
-result (ALIVE_ACK) = 0
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-Current NS-VCIs:
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 10 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 10 02 
-
-result (BVC_RESET_ACK) = 9
-
---- Initialise BSS 2 ---
-
-Setup NS-VC: remote 0x01020304:2222, NSVCI 0x2001(8193), NSEI 0x2000(8192)
-
-PROCESSING RESET from 0x01020304:2222
-02 00 81 01 01 82 20 01 04 82 20 00 
-
-==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:2222
-
-MESSAGE to BSS at 0x01020304:2222, msg length 9
-03 01 82 20 01 04 82 20 00 
-
-MESSAGE to BSS at 0x01020304:2222, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:2222
-0a 
-
-MESSAGE to BSS at 0x01020304:2222, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:2222
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:2222
-
-MESSAGE to BSS at 0x01020304:2222, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:2222
-0b 
-
-result (ALIVE_ACK) = 0
-
-Setup BSSGP: remote 0x01020304:2222, BVCI 0x2002(8194)
-
-PROCESSING BVC_RESET from 0x01020304:2222
-00 00 00 00 22 04 82 20 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 20 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 20 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-Current NS-VCIs:
-    VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Peers:
-  NSEI 8192, BVCI 8194, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 20 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 20 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:2222, msg length 9
-00 00 00 00 23 04 82 20 02 
-
-result (BVC_RESET_ACK) = 9
-
---- Move BSS 1 to new port ---
-
-Setup NS-VC: remote 0x01020304:3333, NSVCI 0x1001(4097), NSEI 0x1000(4096)
-
-PROCESSING RESET from 0x01020304:3333
-02 00 81 01 01 82 10 01 04 82 10 00 
-
-==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:3333
-
-MESSAGE to BSS at 0x01020304:3333, msg length 9
-03 01 82 10 01 04 82 10 00 
-
-MESSAGE to BSS at 0x01020304:3333, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:3333
-0a 
-
-MESSAGE to BSS at 0x01020304:3333, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:3333
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:3333
-
-MESSAGE to BSS at 0x01020304:3333, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:3333
-0b 
-
-result (ALIVE_ACK) = 0
-
-Current NS-VCIs:
-    VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Peers:
-  NSEI 8192, BVCI 8194, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
---- Move BSS 2 to former BSS 1 port ---
-
-Setup NS-VC: remote 0x01020304:1111, NSVCI 0x2001(8193), NSEI 0x2000(8192)
-
-PROCESSING RESET from 0x01020304:1111
-02 00 81 01 01 82 20 01 04 82 20 00 
-
-==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-03 01 82 20 01 04 82 20 00 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:1111
-0a 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:1111
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:1111
-0b 
-
-result (ALIVE_ACK) = 0
-
-Current NS-VCIs:
-    VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Peers:
-  NSEI 8192, BVCI 8194, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
---- Move BSS 1 to current BSS 2 port ---
-
-Setup NS-VC: remote 0x01020304:1111, NSVCI 0x2001(8193), NSEI 0x2000(8192)
-
-PROCESSING RESET from 0x01020304:1111
-02 00 81 01 01 82 20 01 04 82 20 00 
-
-==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-03 01 82 20 01 04 82 20 00 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:1111
-0a 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:1111
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:1111
-0b 
-
-result (ALIVE_ACK) = 0
-
-Current NS-VCIs:
-    VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Peers:
-  NSEI 8192, BVCI 8194, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
---- Move BSS 2 to new port ---
-
-Setup NS-VC: remote 0x01020304:4444, NSVCI 0x2001(8193), NSEI 0x2000(8192)
-
-PROCESSING RESET from 0x01020304:4444
-02 00 81 01 01 82 20 01 04 82 20 00 
-
-==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:4444
-
-MESSAGE to BSS at 0x01020304:4444, msg length 9
-03 01 82 20 01 04 82 20 00 
-
-MESSAGE to BSS at 0x01020304:4444, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:4444
-0a 
-
-MESSAGE to BSS at 0x01020304:4444, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:4444
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:4444
-
-MESSAGE to BSS at 0x01020304:4444, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:4444
-0b 
-
-result (ALIVE_ACK) = 0
-
-Current NS-VCIs:
-    VCI 0x2001, NSEI 0x2000, peer 0x01020304:4444
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Peers:
-  NSEI 8192, BVCI 8194, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
---- Move BSS 2 to former BSS 1 port ---
-
-Setup NS-VC: remote 0x01020304:3333, NSVCI 0x2001(8193), NSEI 0x2000(8192)
-
-PROCESSING RESET from 0x01020304:3333
-02 00 81 01 01 82 20 01 04 82 20 00 
-
-==> got signal NS_REPLACED: 0x2001/1.2.3.4:4444 -> 0x1001/1.2.3.4:3333
-
-==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:3333
-
-MESSAGE to BSS at 0x01020304:3333, msg length 9
-03 01 82 20 01 04 82 20 00 
-
-MESSAGE to BSS at 0x01020304:3333, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:3333
-0a 
-
-MESSAGE to BSS at 0x01020304:3333, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:3333
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:3333
-
-MESSAGE to BSS at 0x01020304:3333, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:3333
-0b 
-
-result (ALIVE_ACK) = 0
-
-Current NS-VCIs:
-    VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333
-         NS-VC replaced other count: 1
-    VCI 0x1001, NSEI 0x1000, peer 0x00000000:0
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Peers:
-  NSEI 8192, BVCI 8194, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
---- Move BSS 1 to original BSS 1 port ---
-
-Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096)
-
-PROCESSING RESET from 0x01020304:1111
-02 00 81 01 01 82 10 01 04 82 10 00 
-
-==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-03 01 82 10 01 04 82 10 00 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:1111
-0a 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:1111
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:1111
-0b 
-
-result (ALIVE_ACK) = 0
-
-Current NS-VCIs:
-    VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333
-         NS-VC replaced other count: 1
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Peers:
-  NSEI 8192, BVCI 8194, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
---- Reset BSS 1 with a new BVCI ---
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x1012(4114)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 10 12 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 10 12 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 10 12 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-Current NS-VCIs:
-    VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333
-         NS-VC replaced other count: 1
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Peers:
-  NSEI 4096, BVCI 4114, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 8194, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 10 12 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 10 12 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 10 12 
-
-result (BVC_RESET_ACK) = 9
-
---- Reset BSS 1 with the old BVCI ---
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-Current NS-VCIs:
-    VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333
-         NS-VC replaced other count: 1
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Peers:
-  NSEI 4096, BVCI 4114, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 8194, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 10 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 10 02 
-
-result (BVC_RESET_ACK) = 9
-
---- Reset BSS 1 with the old BVCI again ---
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-Current NS-VCIs:
-    VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333
-         NS-VC replaced other count: 1
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Peers:
-  NSEI 4096, BVCI 4114, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 8194, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 10 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 10 02 
-
-result (BVC_RESET_ACK) = 9
-
---- Send message from BSS 1 to SGSN, BVCI 0x1012 ---
-
-PROCESSING UNITDATA from 0x01020304:1111
-00 00 10 12 
-
-CALLBACK, event 0, msg length 0, bvci 0x1012
-00 00 10 12 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1012, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 4
-00 00 10 12 
-
-result (UNITDATA) = 4
-
---- Send message from SGSN to BSS 1, BVCI 0x1012 ---
-
-PROCESSING UNITDATA from 0x05060708:32000
-00 00 10 12 
-
-CALLBACK, event 0, msg length 0, bvci 0x1012
-00 00 10 12 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1012, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 4
-00 00 10 12 
-
-result (UNITDATA) = 4
-
---- Send message from BSS 1 to SGSN, BVCI 0x1002 ---
-
-PROCESSING UNITDATA from 0x01020304:1111
-00 00 10 12 
-
-CALLBACK, event 0, msg length 0, bvci 0x1012
-00 00 10 12 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1012, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 4
-00 00 10 12 
-
-result (UNITDATA) = 4
-
---- Send message from SGSN to BSS 1, BVCI 0x1002 ---
-
-PROCESSING UNITDATA from 0x05060708:32000
-00 00 10 12 
-
-CALLBACK, event 0, msg length 0, bvci 0x1012
-00 00 10 12 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1012, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 4
-00 00 10 12 
-
-result (UNITDATA) = 4
-
---- Send message from BSS 2 to SGSN, BVCI 0x2002 ---
-
-PROCESSING UNITDATA from 0x01020304:1111
-00 00 20 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x2002
-00 00 20 02 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x2002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 4
-00 00 20 02 
-
-result (UNITDATA) = 4
-
---- Send message from SGSN to BSS 2, BVCI 0x2002 ---
-
-PROCESSING UNITDATA from 0x05060708:32000
-00 00 20 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x2002
-00 00 20 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x2002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:3333, msg length 4
-00 00 20 02 
-
-result (UNITDATA) = 4
-
---- Reset BSS 1 with the old BVCI on BSS2's link ---
-
-Setup BSSGP: remote 0x01020304:3333, BVCI 0x1002(4098)
-
-PROCESSING BVC_RESET from 0x01020304:3333
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-Current NS-VCIs:
-    VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333
-         NS-VC replaced other count: 1
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Peers:
-  NSEI 4096, BVCI 4114, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 8194, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 1
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 4098, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 1
-    TLLI-Cache: 0
-Gbproxy global:
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 10 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:3333, msg length 9
-00 00 00 00 23 04 82 10 02 
-
-result (BVC_RESET_ACK) = 9
-
---- Send message from BSS 1 to SGSN, BVCI 0x1002 ---
-
-PROCESSING UNITDATA from 0x01020304:1111
-00 00 10 12 
-
-CALLBACK, event 0, msg length 0, bvci 0x1012
-00 00 10 12 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1012, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 4
-00 00 10 12 
-
-result (UNITDATA) = 4
-
---- Send message from SGSN to BSS 1, BVCI 0x1002 ---
-
-PROCESSING UNITDATA from 0x05060708:32000
-00 00 10 12 
-
-CALLBACK, event 0, msg length 0, bvci 0x1012
-00 00 10 12 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1012, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 4
-00 00 10 12 
-
-result (UNITDATA) = 4
-
---- Send message from SGSN to BSS 1, BVCI 0x10ff (invalid) ---
-
-PROCESSING UNITDATA from 0x05060708:32000
-00 00 10 ff 
-
-CALLBACK, event 0, msg length 0, bvci 0x10ff
-00 00 10 ff 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 10 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 14
-00 00 00 00 41 07 81 05 04 82 10 ff 15 80 
-
-result (UNITDATA) = 14
-
-Peers:
-  NSEI 8192, BVCI 8194, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 1
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 4098, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 1
-    TLLI-Cache: 0
-Gbproxy global:
-    Invalid BVC Identifier          : 1
-=== test_gbproxy_ident_changes ===
---- Initialise SGSN ---
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 12
-02 00 81 01 01 82 01 01 04 82 01 00 
-
-PROCESSING RESET_ACK from 0x05060708:32000
-03 01 82 01 01 04 82 01 00 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0a 
-
-result (RESET_ACK) = 1
-
-PROCESSING ALIVE_ACK from 0x05060708:32000
-0b 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-06 
-
-result (ALIVE_ACK) = 1
-
-PROCESSING UNBLOCK_ACK from 0x05060708:32000
-07 
-
-==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000
-
-result (UNBLOCK_ACK) = 0
-
-PROCESSING ALIVE from 0x05060708:32000
-0a 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-Current NS-VCIs:
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
---- Initialise BSS 1 ---
-
-Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096)
-
-PROCESSING RESET from 0x01020304:1111
-02 00 81 01 01 82 10 01 04 82 10 00 
-
-==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-03 01 82 10 01 04 82 10 00 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:1111
-0a 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:1111
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:1111
-0b 
-
-result (ALIVE_ACK) = 0
-
-Current NS-VCIs:
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
---- Setup BVCI 1 ---
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 10 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 10 02 
-
-result (BVC_RESET_ACK) = 9
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
---- Setup BVCI 2 ---
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x2002(8194)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 20 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 20 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 20 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 20 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 20 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 20 02 
-
-result (BVC_RESET_ACK) = 9
-
-Peers:
-  NSEI 4096, BVCI 8194, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
---- Send message from BSS 1 to SGSN and back, BVCI 1 ---
-
-PROCESSING UNITDATA from 0x01020304:1111
-00 00 10 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x1002
-00 00 10 02 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 4
-00 00 10 02 
-
-result (UNITDATA) = 4
-
-PROCESSING UNITDATA from 0x05060708:32000
-00 00 10 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x1002
-00 00 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 4
-00 00 10 02 
-
-result (UNITDATA) = 4
-
---- Send message from BSS 1 to SGSN and back, BVCI 2 ---
-
-PROCESSING UNITDATA from 0x01020304:1111
-00 00 20 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x2002
-00 00 20 02 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x2002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 4
-00 00 20 02 
-
-result (UNITDATA) = 4
-
-PROCESSING UNITDATA from 0x05060708:32000
-00 00 20 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x2002
-00 00 20 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x2002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 4
-00 00 20 02 
-
-result (UNITDATA) = 4
-
---- Change NSEI ---
-
-Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x2000(8192)
-
-PROCESSING RESET from 0x01020304:1111
-02 00 81 01 01 82 10 01 04 82 20 00 
-
-==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-03 01 82 10 01 04 82 20 00 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:1111
-0a 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:1111
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:1111
-0b 
-
-result (ALIVE_ACK) = 0
-
-Current NS-VCIs:
-    VCI 0x1001, NSEI 0x2000, peer 0x01020304:1111
-         NS-VC changed NSEI count  : 1
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
---- Setup BVCI 1 ---
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 10 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 10 02 
-
-result (BVC_RESET_ACK) = 9
-
-Peers:
-  NSEI 4096, BVCI 8194, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 4098, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 1
-    TLLI-Cache: 0
---- Setup BVCI 3 ---
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x3002(12290)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 30 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 30 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 30 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 30 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 30 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 30 02 
-
-result (BVC_RESET_ACK) = 9
-
-Peers:
-  NSEI 8192, BVCI 12290, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 8194, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 4098, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 1
-    TLLI-Cache: 0
---- Send message from BSS 1 to SGSN and back, BVCI 1 ---
-
-PROCESSING UNITDATA from 0x01020304:1111
-00 00 10 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x1002
-00 00 10 02 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 4
-00 00 10 02 
-
-result (UNITDATA) = 4
-
-PROCESSING UNITDATA from 0x05060708:32000
-00 00 10 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x1002
-00 00 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 4
-00 00 10 02 
-
-result (UNITDATA) = 4
-
---- Send message from BSS 1 to SGSN and back, BVCI 2  (should fail) ---
-
-PROCESSING UNITDATA from 0x01020304:1111
-00 00 20 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x2002
-00 00 20 02 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x2002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 4
-00 00 20 02 
-
-result (UNITDATA) = 4
-
-Peers:
-  NSEI 8192, BVCI 12290, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 8194, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 1
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 4098, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 1
-    TLLI-Cache: 0
-PROCESSING UNITDATA from 0x05060708:32000
-00 00 20 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x2002
-00 00 20 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x2002, msg length 0 (gprs_ns_sendmsg)
-result (UNITDATA) = -22
-
-Peers:
-  NSEI 8192, BVCI 12290, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 8194, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 1
-    NS Transmission error           : 1
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 4098, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 1
-    TLLI-Cache: 0
---- Send message from BSS 1 to SGSN and back, BVCI 3 ---
-
-PROCESSING UNITDATA from 0x01020304:1111
-00 00 30 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x3002
-00 00 30 02 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x3002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 4
-00 00 30 02 
-
-result (UNITDATA) = 4
-
-PROCESSING UNITDATA from 0x05060708:32000
-00 00 30 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x3002
-00 00 30 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x3002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 4
-00 00 30 02 
-
-result (UNITDATA) = 4
-
---- Change NSVCI ---
-
-Setup NS-VC: remote 0x01020304:1111, NSVCI 0x2001(8193), NSEI 0x2000(8192)
-
-PROCESSING RESET from 0x01020304:1111
-02 00 81 01 01 82 20 01 04 82 20 00 
-
-==> got signal NS_REPLACED: 0x2001/0.0.0.0:0 -> 0x1001/1.2.3.4:1111
-
-==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-03 01 82 20 01 04 82 20 00 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:1111
-0a 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:1111
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:1111
-0b 
-
-result (ALIVE_ACK) = 0
-
-Current NS-VCIs:
-    VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111
-         NS-VC replaced other count: 1
-    VCI 0x1001, NSEI 0x2000, peer 0x00000000:0
-         NS-VC changed NSEI count  : 1
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
---- Setup BVCI 1 ---
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 10 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 10 02 
-
-result (BVC_RESET_ACK) = 9
-
-Peers:
-  NSEI 8192, BVCI 12290, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 8194, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 1
-    NS Transmission error           : 1
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 4098, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 1
-    TLLI-Cache: 0
---- Setup BVCI 4 ---
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x4002(16386)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 40 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 40 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 40 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 40 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 40 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 40 02 
-
-result (BVC_RESET_ACK) = 9
-
-Peers:
-  NSEI 8192, BVCI 16386, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 12290, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 8194, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 1
-    NS Transmission error           : 1
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 4098, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 1
-    TLLI-Cache: 0
---- Send message from BSS 1 to SGSN and back, BVCI 1 ---
-
-PROCESSING UNITDATA from 0x01020304:1111
-00 00 10 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x1002
-00 00 10 02 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 4
-00 00 10 02 
-
-result (UNITDATA) = 4
-
-PROCESSING UNITDATA from 0x05060708:32000
-00 00 10 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x1002
-00 00 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 4
-00 00 10 02 
-
-result (UNITDATA) = 4
-
---- Send message from BSS 1 to SGSN and back, BVCI 2  (should fail) ---
-
-PROCESSING UNITDATA from 0x01020304:1111
-00 00 20 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x2002
-00 00 20 02 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x2002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 4
-00 00 20 02 
-
-result (UNITDATA) = 4
-
-Peers:
-  NSEI 8192, BVCI 16386, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 12290, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 8194, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 2
-    NS Transmission error           : 1
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 4098, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 1
-    TLLI-Cache: 0
-PROCESSING UNITDATA from 0x05060708:32000
-00 00 20 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x2002
-00 00 20 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x2002, msg length 0 (gprs_ns_sendmsg)
-result (UNITDATA) = -22
-
-Peers:
-  NSEI 8192, BVCI 16386, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 12290, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 8194, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 2
-    NS Transmission error           : 2
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 4098, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 1
-    TLLI-Cache: 0
---- Send message from BSS 1 to SGSN and back, BVCI 3 ---
-
-PROCESSING UNITDATA from 0x01020304:1111
-00 00 30 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x3002
-00 00 30 02 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x3002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 4
-00 00 30 02 
-
-result (UNITDATA) = 4
-
-PROCESSING UNITDATA from 0x05060708:32000
-00 00 30 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x3002
-00 00 30 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x3002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 4
-00 00 30 02 
-
-result (UNITDATA) = 4
-
---- Send message from BSS 1 to SGSN and back, BVCI 4 ---
-
-PROCESSING UNITDATA from 0x01020304:1111
-00 00 40 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x4002
-00 00 40 02 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x4002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 4
-00 00 40 02 
-
-result (UNITDATA) = 4
-
-PROCESSING UNITDATA from 0x05060708:32000
-00 00 40 02 
-
-CALLBACK, event 0, msg length 0, bvci 0x4002
-00 00 40 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x4002, msg length 0 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 4
-00 00 40 02 
-
-result (UNITDATA) = 4
-
-Gbproxy global:
-Peers:
-  NSEI 8192, BVCI 16386, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 12290, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
-  NSEI 4096, BVCI 8194, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 2
-    NS Transmission error           : 2
-    TLLI-Cache: 0
-  NSEI 8192, BVCI 4098, not blocked, RAI 112-332-16464-96
-    NSEI mismatch                   : 1
-    TLLI-Cache: 0
-=== Test IMSI/TMSI matching ===
-
-=== test_gbproxy_ptmsi_assignment ===
---- Initialise SGSN ---
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 12
-02 00 81 01 01 82 01 01 04 82 01 00 
-
-PROCESSING RESET_ACK from 0x05060708:32000
-03 01 82 01 01 04 82 01 00 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0a 
-
-result (RESET_ACK) = 1
-
-PROCESSING ALIVE_ACK from 0x05060708:32000
-0b 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-06 
-
-result (ALIVE_ACK) = 1
-
-PROCESSING UNBLOCK_ACK from 0x05060708:32000
-07 
-
-==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000
-
-result (UNBLOCK_ACK) = 0
-
-PROCESSING ALIVE from 0x05060708:32000
-0a 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0b 
-
-result (ALIVE) = 1
-
---- Initialise BSS 1 ---
-
-Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096)
-
-PROCESSING RESET from 0x01020304:1111
-02 00 81 01 01 82 10 01 04 82 10 00 
-
-==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-03 01 82 10 01 04 82 10 00 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:1111
-0a 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:1111
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:1111
-0b 
-
-result (ALIVE_ACK) = 0
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 10 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 10 02 
-
-result (BVC_RESET_ACK) = 9
-
-Current NS-VCIs:
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Gbproxy global:
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
---- Establish first LLC connection ---
-
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-result (ATTACH REQUEST) = 79
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 8000dead, IMSI (none), AGE 0
-PROCESSING IDENT REQUEST from 0x05060708:32000
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-CALLBACK, event 0, msg length 23, bvci 0x1002
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 27
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-result (IDENT REQUEST) = 27
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 8000dead, IMSI (none), AGE 0
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 44
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 
-
-result (IDENT RESPONSE) = 44
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 8000dead, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead/efe2b700 -> 8000dead/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc 
-
-result (ATTACH COMPLETE) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead/efe2b700 -> 8000dead/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING GMM INFO from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-CALLBACK, event 0, msg length 66, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 70
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-result (GMM INFO) = 70
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
---- Establish second LLC connection with the same P-TMSI ---
-
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 80 00 be ef 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 0d 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 46 42 6e 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 80 00 be ef 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 0d 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 46 42 6e 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 80 00 be ef 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 0d 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 46 42 6e 
-
-result (ATTACH REQUEST) = 79
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 2
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI 8000beef -> 8000beef, IMSI (none), AGE 0
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING IDENT REQUEST from 0x05060708:32000
-00 00 10 02 00 80 00 be ef 00 50 20 16 82 02 58 0e 89 41 c0 0d 08 15 01 0c a6 18 
-
-CALLBACK, event 0, msg length 23, bvci 0x1002
-00 00 10 02 00 80 00 be ef 00 50 20 16 82 02 58 0e 89 41 c0 0d 08 15 01 0c a6 18 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 27
-00 00 10 02 00 80 00 be ef 00 50 20 16 82 02 58 0e 89 41 c0 0d 08 15 01 0c a6 18 
-
-result (IDENT REQUEST) = 27
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 2
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI 8000beef -> 8000beef, IMSI (none), AGE 0
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 80 00 be ef 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 11 08 16 08 11 12 99 99 99 16 17 18 bf d2 01 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 80 00 be ef 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 11 08 16 08 11 12 99 99 99 16 17 18 bf d2 01 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 44
-00 00 10 02 01 80 00 be ef 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 11 08 16 08 11 12 99 99 99 16 17 18 bf d2 01 
-
-result (IDENT RESPONSE) = 44
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 2
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI 8000beef -> 8000beef, IMSI 12199999961718, AGE 0
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 80 00 be ef 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 9e 41 c0 11 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 3a 6d d4 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 80 00 be ef 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 9e 41 c0 11 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 3a 6d d4 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 80 00 be ef 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 9e 41 c0 11 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 3a 6d d4 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 2
-    Attach Accept count             : 2
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000beef/efe2b700 -> 8000beef/efe2b700, IMSI 12199999961718, AGE 0
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 15 08 03 86 ac 47 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 15 08 03 86 ac 47 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 15 08 03 86 ac 47 
-
-result (ATTACH COMPLETE) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 2
-    Attach Accept count             : 2
-    Attach Completed count          : 2
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000beef/efe2b700 -> 8000beef/efe2b700, IMSI 12199999961718, AGE 0
-PROCESSING GMM INFO from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 88 41 c0 15 08 21 bb c1 c6 
-
-CALLBACK, event 0, msg length 66, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 88 41 c0 15 08 21 bb c1 c6 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 70
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 88 41 c0 15 08 21 bb c1 c6 
-
-result (GMM INFO) = 70
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 2
-    Attach Accept count             : 2
-    Attach Completed count          : 2
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI efe2b700 -> efe2b700, IMSI 12199999961718, AGE 0
-Gbproxy global:
-=== test_gbproxy_ra_patching ===
---- Initialise SGSN ---
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 12
-02 00 81 01 01 82 01 01 04 82 01 00 
-
-PROCESSING RESET_ACK from 0x05060708:32000
-03 01 82 01 01 04 82 01 00 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0a 
-
-result (RESET_ACK) = 1
-
-PROCESSING ALIVE_ACK from 0x05060708:32000
-0b 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-06 
-
-result (ALIVE_ACK) = 1
-
-PROCESSING UNBLOCK_ACK from 0x05060708:32000
-07 
-
-==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000
-
-result (UNBLOCK_ACK) = 0
-
-PROCESSING ALIVE from 0x05060708:32000
-0a 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-Current NS-VCIs:
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
---- Initialise BSS 1 ---
-
-Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096)
-
-PROCESSING RESET from 0x01020304:1111
-02 00 81 01 01 82 10 01 04 82 10 00 
-
-==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-03 01 82 10 01 04 82 10 00 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:1111
-0a 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:1111
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:1111
-0b 
-
-result (ALIVE_ACK) = 0
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 21 63 54 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-Current NS-VCIs:
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 1
-    TLLI-Cache: 0
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 10 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 10 02 
-
-result (BVC_RESET_ACK) = 9
-
-PROCESSING BVC_SUSPEND from 0x01020304:1111
-00 00 00 00 0b 1f 84 cc d1 75 8b 1b 86 11 22 33 40 50 60 
-
-CALLBACK, event 0, msg length 15, bvci 0x0000
-00 00 00 00 0b 1f 84 cc d1 75 8b 1b 86 11 22 33 40 50 60 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 15 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 19
-00 00 00 00 0b 1f 84 cc d1 75 8b 1b 86 21 63 54 40 50 60 
-
-result (BVC_SUSPEND) = 19
-
-PROCESSING BVC_SUSPEND_ACK from 0x05060708:32000
-00 00 00 00 0c 1f 84 cc d1 75 8b 1b 86 21 63 54 40 50 60 1d 81 01 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 0c 1f 84 cc d1 75 8b 1b 86 21 63 54 40 50 60 1d 81 01 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 22
-00 00 00 00 0c 1f 84 cc d1 75 8b 1b 86 11 22 33 40 50 60 1d 81 01 
-
-result (BVC_SUSPEND_ACK) = 22
-
-Gbproxy global:
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 2
-    RAID patched              (SGSN): 1
-    TLLI from SGSN unknown          : 1
-    TLLI-Cache: 0
---- Send message from BSS 1 to SGSN, BVCI 0x1002 ---
-
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 bb c5 46 79 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 21 63 54 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 8e cd 32 
-
-result (ATTACH REQUEST) = 79
-
-PROCESSING IDENT REQUEST from 0x05060708:32000
-00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-CALLBACK, event 0, msg length 23, bvci 0x1002
-00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 27
-00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-result (IDENT REQUEST) = 27
-
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 11 01 c0 0d 08 16 08 11 12 13 14 15 16 17 18 b7 1b 9a 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 11 01 c0 0d 08 16 08 11 12 13 14 15 16 17 18 b7 1b 9a 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 44
-00 00 10 02 01 bb c5 46 79 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 11 01 c0 0d 08 16 08 11 12 13 14 15 16 17 18 b7 1b 9a 
-
-result (IDENT RESPONSE) = 44
-
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 11 22 33 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 be 38 c0 
-
-result (ATTACH ACCEPT) = 92
-
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 08 01 c0 11 08 03 ea 67 11 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 08 01 c0 11 08 03 ea 67 11 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 08 01 c0 11 08 03 ea 67 11 
-
-result (ATTACH COMPLETE) = 35
-
-PROCESSING ACT PDP CTX REQ (REPLACE APN) from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 35 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 03 02 61 62 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 5a ff 02 
-
-CALLBACK, event 0, msg length 76, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 35 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 03 02 61 62 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 5a ff 02 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 81 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 85
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 3a 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 08 03 66 6f 6f 03 62 61 72 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 24 9d 75 
-
-result (ACT PDP CTX REQ (REPLACE APN)) = 85
-
-PROCESSING GMM INFO from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-CALLBACK, event 0, msg length 66, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 70
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-result (GMM INFO) = 70
-
-PROCESSING ACT PDP CTX REQ (REPLACE APN) from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 35 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 03 02 61 62 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 5a ff 02 
-
-CALLBACK, event 0, msg length 76, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 35 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 03 02 61 62 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 5a ff 02 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 81 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 85
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 3a 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 08 03 66 6f 6f 03 62 61 72 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 24 9d 75 
-
-result (ACT PDP CTX REQ (REPLACE APN)) = 85
-
-PROCESSING ACT PDP CTX REQ (REMOVE APN) from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 35 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 03 02 61 62 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 5a ff 02 
-
-CALLBACK, event 0, msg length 76, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 35 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 03 02 61 62 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 5a ff 02 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 71 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 75
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 30 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 85 fa 60 
-
-result (ACT PDP CTX REQ (REMOVE APN)) = 75
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 9
-    RAID patched              (SGSN): 2
-    APN patched                     : 3
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    PDP Activation Request count    : 3
-    TLLI from SGSN unknown          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0, IMSI matches
-PROCESSING DETACH REQ from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 15 01 c0 19 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 7e e1 41 
-
-CALLBACK, event 0, msg length 44, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 15 01 c0 19 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 7e e1 41 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 48
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 15 01 c0 19 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 7e e1 41 
-
-result (DETACH REQ) = 48
-
-PROCESSING DETACH ACC from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 15 08 06 00 f7 35 f0 
-
-CALLBACK, event 0, msg length 67, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 15 08 06 00 f7 35 f0 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 71
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 15 08 06 00 f7 35 f0 
-
-result (DETACH ACC) = 71
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 10
-    RAID patched              (SGSN): 2
-    APN patched                     : 3
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    PDP Activation Request count    : 3
-    TLLI from SGSN unknown          : 1
-    TLLI-Cache: 0
---- RA update ---
-
-PROCESSING RA UPD REQ from 0x01020304:1111
-00 00 10 02 01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 
-
-CALLBACK, event 0, msg length 85, bvci 0x1002
-00 00 10 02 01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 85 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 89
-00 00 10 02 01 bb c5 46 79 00 00 04 08 88 21 63 54 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 21 63 54 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 1d f0 41 
-
-result (RA UPD REQ) = 89
-
-PROCESSING RA UPD ACC from 0x05060708:32000
-00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 19 08 09 00 49 21 63 54 40 50 60 19 54 ab b3 18 05 f4 ef e2 b7 00 17 16 d7 59 65 
-
-CALLBACK, event 0, msg length 87, bvci 0x1002
-00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 19 08 09 00 49 21 63 54 40 50 60 19 54 ab b3 18 05 f4 ef e2 b7 00 17 16 d7 59 65 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 87 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 91
-00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 19 08 09 00 49 11 22 33 40 50 60 19 54 ab b3 18 05 f4 ef e2 b7 00 17 16 3a 03 54 
-
-result (RA UPD ACC) = 91
-
-PROCESSING ACT PDP CTX REQ (REMOVE APN) from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 35 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 03 02 61 62 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 5a ff 02 
-
-CALLBACK, event 0, msg length 76, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 35 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 03 02 61 62 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 5a ff 02 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 71 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 75
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 30 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 85 fa 60 
-
-result (ACT PDP CTX REQ (REMOVE APN)) = 75
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 13
-    RAID patched              (SGSN): 3
-    APN patched                     : 4
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 1
-    RoutingArea Update Accept count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    PDP Activation Request count    : 4
-    TLLI from SGSN unknown          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI bbc54679/efe2b700 -> bbc54679/efe2b700, IMSI 12131415161718, AGE 0, IMSI matches
-PROCESSING DETACH REQ (PWR OFF) from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 15 01 c0 19 08 05 09 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 84 0c eb 
-
-CALLBACK, event 0, msg length 44, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 15 01 c0 19 08 05 09 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 84 0c eb 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 48
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 15 01 c0 19 08 05 09 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 84 0c eb 
-
-result (DETACH REQ (PWR OFF)) = 48
-
-Gbproxy global:
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 14
-    RAID patched              (SGSN): 3
-    APN patched                     : 4
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 1
-    RoutingArea Update Accept count : 1
-    Detach Request count            : 2
-    Detach Accept count             : 1
-    PDP Activation Request count    : 4
-    TLLI from SGSN unknown          : 1
-    TLLI-Cache: 0
---- Bad cases ---
-
-PROCESSING ATTACH REQUEST (foreign RAI) from 0x01020304:1111
-00 00 10 02 01 bb 00 be ef 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb 00 be ef 99 99 99 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 2d c7 df 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 bb 00 be ef 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb 00 be ef 99 99 99 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 2d c7 df 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 bb 00 be ef 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb 00 be ef 99 99 99 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 2d c7 df 
-
-result (ATTACH REQUEST (foreign RAI)) = 79
-
-TLLI is already detached, shouldn't patch
-PROCESSING ACT PDP CTX REQ from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 35 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 03 02 61 62 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 5a ff 02 
-
-CALLBACK, event 0, msg length 76, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 35 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 03 02 61 62 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 5a ff 02 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 76 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 80
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 35 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 03 02 61 62 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 5a ff 02 
-
-result (ACT PDP CTX REQ) = 80
-
-Invalid RAI, shouldn't patch
-PROCESSING BVC_SUSPEND_ACK from 0x05060708:32000
-00 00 00 00 0c 1f 84 cc d1 75 8b 1b 86 00 f1 99 00 63 60 1d 81 01 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 0c 1f 84 cc d1 75 8b 1b 86 00 f1 99 00 63 60 1d 81 01 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 28
-00 00 00 00 41 07 81 21 15 92 0c 1f 84 cc d1 75 8b 1b 86 00 f1 99 00 63 60 1d 81 01 
-
-result (BVC_SUSPEND_ACK) = 28
-
-Gbproxy global:
-    Invalid Routing Area Identifier : 1
-    Patch error: no peer            : 1
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 16
-    RAID patched              (SGSN): 3
-    APN patched                     : 4
-    Attach Request count            : 2
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 1
-    RoutingArea Update Accept count : 1
-    Detach Request count            : 2
-    Detach Accept count             : 1
-    PDP Activation Request count    : 5
-    TLLI from SGSN unknown          : 1
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI efe2b700 -> efe2b700, IMSI (none), AGE 0
-      TLLI bb00beef -> bb00beef, IMSI (none), AGE 0
-=== test_gbproxy_ptmsi_patching ===
---- Initialise SGSN ---
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 12
-02 00 81 01 01 82 01 01 04 82 01 00 
-
-PROCESSING RESET_ACK from 0x05060708:32000
-03 01 82 01 01 04 82 01 00 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0a 
-
-result (RESET_ACK) = 1
-
-PROCESSING ALIVE_ACK from 0x05060708:32000
-0b 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-06 
-
-result (ALIVE_ACK) = 1
-
-PROCESSING UNBLOCK_ACK from 0x05060708:32000
-07 
-
-==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000
-
-result (UNBLOCK_ACK) = 0
-
-PROCESSING ALIVE from 0x05060708:32000
-0a 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0b 
-
-result (ALIVE) = 1
-
---- Initialise BSS 1 ---
-
-Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096)
-
-PROCESSING RESET from 0x01020304:1111
-02 00 81 01 01 82 10 01 04 82 10 00 
-
-==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-03 01 82 10 01 04 82 10 00 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:1111
-0a 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:1111
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:1111
-0b 
-
-result (ALIVE_ACK) = 0
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 21 63 54 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 10 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 10 02 
-
-result (BVC_RESET_ACK) = 9
-
-Current NS-VCIs:
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Gbproxy global:
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 1
-    TLLI-Cache: 0
---- Send message from BSS 1 to SGSN, BVCI 0x1002 ---
-
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 78 de ad 00 00 00 04 08 88 21 63 54 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-result (ATTACH REQUEST) = 79
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 2
-    TLLI patched              (BSS ): 1
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 78dead00, IMSI (none), AGE 0
-PROCESSING IDENT REQUEST from 0x05060708:32000
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-CALLBACK, event 0, msg length 23, bvci 0x1002
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 27
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-result (IDENT REQUEST) = 27
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 2
-    TLLI patched              (BSS ): 1
-    TLLI patched              (SGSN): 1
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 78dead00, IMSI (none), AGE 0
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 44
-00 00 10 02 01 78 de ad 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 
-
-result (IDENT RESPONSE) = 44
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 3
-    TLLI patched              (BSS ): 2
-    TLLI patched              (SGSN): 1
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 78dead00, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 11 22 33 40 50 60 19 cd d7 08 17 16 18 05 f4 c0 de ad 01 0c 0a 29 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 3
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 2
-    TLLI patched              (SGSN): 2
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc 
-
-result (ATTACH COMPLETE) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 4
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 3
-    TLLI patched              (SGSN): 2
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING GMM INFO from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-CALLBACK, event 0, msg length 66, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 70
-00 00 10 02 00 c0 de ad 01 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-result (GMM INFO) = 70
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 4
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 3
-    TLLI patched              (SGSN): 3
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ACT PDP CTX REQ (REPLACE APN) from 0x01020304:1111
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 35 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 03 02 61 62 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 5a ff 02 
-
-CALLBACK, event 0, msg length 76, bvci 0x1002
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 35 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 03 02 61 62 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 5a ff 02 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 81 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 85
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 3a 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 08 03 66 6f 6f 03 62 61 72 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 24 9d 75 
-
-result (ACT PDP CTX REQ (REPLACE APN)) = 85
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 5
-    RAID patched              (SGSN): 1
-    APN patched                     : 1
-    TLLI patched              (BSS ): 4
-    TLLI patched              (SGSN): 3
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    PDP Activation Request count    : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING XID (UL) from 0x01020304:1111
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 
-
-CALLBACK, event 0, msg length 38, bvci 0x1002
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 38 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 42
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 
-
-result (XID (UL)) = 42
-
-PROCESSING XID (DL) from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e 
-
-CALLBACK, event 0, msg length 70, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 70 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 74
-00 00 10 02 00 c0 de ad 01 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e 
-
-result (XID (DL)) = 74
-
-PROCESSING LL11 DNS QUERY (UL) from 0x01020304:1111
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 
-
-CALLBACK, event 0, msg length 89, bvci 0x1002
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 89 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 93
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 
-
-result (LL11 DNS QUERY (UL)) = 93
-
-PROCESSING LL11 DNS RESP (DL) from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 
-
-CALLBACK, event 0, msg length 267, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 267 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 271
-00 00 10 02 00 c0 de ad 01 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 
-
-result (LL11 DNS RESP (DL)) = 271
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 7
-    RAID patched              (SGSN): 1
-    APN patched                     : 1
-    TLLI patched              (BSS ): 6
-    TLLI patched              (SGSN): 5
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    PDP Activation Request count    : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING RA UPD REQ (P-TMSI 2) from 0x01020304:1111
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 11 08 08 10 11 22 33 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 e2 6d 78 
-
-CALLBACK, event 0, msg length 85, bvci 0x1002
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 11 08 08 10 11 22 33 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 e2 6d 78 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 85 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 89
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 70 80 00 80 0e 00 3e 01 c0 11 08 08 10 21 63 54 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 69 a3 ae 
-
-result (RA UPD REQ (P-TMSI 2)) = 89
-
-PROCESSING RA UDP ACC (P-TMSI 2) from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 0d 08 09 00 49 21 63 54 40 50 60 19 54 ab b3 18 05 f4 e0 98 76 54 17 16 9f e8 ea 
-
-CALLBACK, event 0, msg length 87, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 0d 08 09 00 49 21 63 54 40 50 60 19 54 ab b3 18 05 f4 e0 98 76 54 17 16 9f e8 ea 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 87 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 91
-00 00 10 02 00 c0 de ad 01 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 0d 08 09 00 49 11 22 33 40 50 60 19 54 ab b3 18 05 f4 c0 de ad 02 17 16 bb 4d a0 
-
-result (RA UDP ACC (P-TMSI 2)) = 91
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 9
-    RAID patched              (SGSN): 2
-    APN patched                     : 1
-    TLLI patched              (BSS ): 7
-    TLLI patched              (SGSN): 6
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 1
-    RoutingArea Update Accept count : 1
-    PDP Activation Request count    : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01/c0dead02 -> efe2b700/e0987654, IMSI 12131415161718, AGE 0
-PROCESSING RA UPD REQ (P-TMSI 3) from 0x01020304:1111
-00 00 10 02 01 c0 de ad 02 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 
-
-CALLBACK, event 0, msg length 85, bvci 0x1002
-00 00 10 02 01 c0 de ad 02 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 85 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 89
-00 00 10 02 01 e0 98 76 54 00 00 04 08 88 21 63 54 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 21 63 54 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 1d f0 41 
-
-result (RA UPD REQ (P-TMSI 3)) = 89
-
-PROCESSING RA UDP ACC (P-TMSI 3) from 0x05060708:32000
-00 00 10 02 00 e0 98 76 54 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 11 08 09 00 49 21 63 54 40 50 60 19 54 ab b3 18 05 f4 e0 54 32 10 17 16 1b a3 a8 
-
-CALLBACK, event 0, msg length 87, bvci 0x1002
-00 00 10 02 00 e0 98 76 54 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 11 08 09 00 49 21 63 54 40 50 60 19 54 ab b3 18 05 f4 e0 54 32 10 17 16 1b a3 a8 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 87 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 91
-00 00 10 02 00 c0 de ad 02 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 11 08 09 00 49 11 22 33 40 50 60 19 54 ab b3 18 05 f4 c0 de ad 03 17 16 6e 58 26 
-
-result (RA UDP ACC (P-TMSI 3)) = 91
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 11
-    RAID patched              (SGSN): 3
-    APN patched                     : 1
-    TLLI patched              (BSS ): 8
-    TLLI patched              (SGSN): 7
-    P-TMSI patched            (SGSN): 3
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 2
-    RoutingArea Update Accept count : 2
-    PDP Activation Request count    : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01/c0dead03 -> efe2b700/e0543210, IMSI 12131415161718, AGE 0
-PROCESSING RA UPD COMPLETE from 0x01020304:1111
-00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 08 01 c0 19 08 0a d5 5f 5e 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 08 01 c0 19 08 0a d5 5f 5e 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 e0 54 32 10 00 00 04 08 88 21 63 54 40 50 60 70 80 00 80 0e 00 08 01 c0 19 08 0a d5 5f 5e 
-
-result (RA UPD COMPLETE) = 35
-
-PROCESSING GMM INFO from 0x05060708:32000
-00 00 10 02 00 e0 54 32 10 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 15 08 21 bb c1 c6 
-
-CALLBACK, event 0, msg length 66, bvci 0x1002
-00 00 10 02 00 e0 54 32 10 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 15 08 21 bb c1 c6 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 70
-00 00 10 02 00 c0 de ad 03 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 15 08 21 bb c1 c6 
-
-result (GMM INFO) = 70
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 12
-    RAID patched              (SGSN): 3
-    APN patched                     : 1
-    TLLI patched              (BSS ): 9
-    TLLI patched              (SGSN): 8
-    P-TMSI patched            (SGSN): 3
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 2
-    RoutingArea Update Accept count : 2
-    RoutingArea Update Compltd count: 1
-    PDP Activation Request count    : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead03 -> e0543210, IMSI 12131415161718, AGE 0
-PROCESSING LLC_DISCARDED from 0x01020304:1111
-00 00 00 00 2c 1f 84 c0 de ad 03 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-CALLBACK, event 0, msg length 19, bvci 0x0000
-00 00 00 00 2c 1f 84 c0 de ad 03 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 19 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 23
-00 00 00 00 2c 1f 84 e0 54 32 10 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-result (LLC_DISCARDED) = 23
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 12
-    RAID patched              (SGSN): 3
-    APN patched                     : 1
-    TLLI patched              (BSS ): 10
-    TLLI patched              (SGSN): 8
-    P-TMSI patched            (SGSN): 3
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 2
-    RoutingArea Update Accept count : 2
-    RoutingArea Update Compltd count: 1
-    PDP Activation Request count    : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead03 -> e0543210, IMSI 12131415161718, AGE 0
-PROCESSING BVC_SUSPEND from 0x01020304:1111
-00 00 00 00 0b 1f 84 c0 de ad 03 1b 86 11 22 33 40 50 60 
-
-CALLBACK, event 0, msg length 15, bvci 0x0000
-00 00 00 00 0b 1f 84 c0 de ad 03 1b 86 11 22 33 40 50 60 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 15 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 19
-00 00 00 00 0b 1f 84 e0 54 32 10 1b 86 21 63 54 40 50 60 
-
-result (BVC_SUSPEND) = 19
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 13
-    RAID patched              (SGSN): 3
-    APN patched                     : 1
-    TLLI patched              (BSS ): 11
-    TLLI patched              (SGSN): 8
-    P-TMSI patched            (SGSN): 3
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 2
-    RoutingArea Update Accept count : 2
-    RoutingArea Update Compltd count: 1
-    PDP Activation Request count    : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead03 -> e0543210, IMSI 12131415161718, AGE 0
-PROCESSING BVC_SUSPEND_ACK from 0x05060708:32000
-00 00 00 00 0c 1f 84 e0 54 32 10 1b 86 21 63 54 40 50 60 1d 81 01 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 0c 1f 84 e0 54 32 10 1b 86 21 63 54 40 50 60 1d 81 01 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 22
-00 00 00 00 0c 1f 84 c0 de ad 03 1b 86 11 22 33 40 50 60 1d 81 01 
-
-result (BVC_SUSPEND_ACK) = 22
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 13
-    RAID patched              (SGSN): 4
-    APN patched                     : 1
-    TLLI patched              (BSS ): 11
-    TLLI patched              (SGSN): 9
-    P-TMSI patched            (SGSN): 3
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 2
-    RoutingArea Update Accept count : 2
-    RoutingArea Update Compltd count: 1
-    PDP Activation Request count    : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead03 -> e0543210, IMSI 12131415161718, AGE 0
-PROCESSING PAGING_PS from 0x05060708:32000
-00 00 00 00 06 0d 88 11 12 13 14 15 16 17 18 0a 82 07 04 1b 86 11 22 33 40 50 60 18 83 00 00 00 20 84 e0 54 32 10 
-
-CALLBACK, event 0, msg length 34, bvci 0x0000
-00 00 00 00 06 0d 88 11 12 13 14 15 16 17 18 0a 82 07 04 1b 86 11 22 33 40 50 60 18 83 00 00 00 20 84 e0 54 32 10 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 34 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 38
-00 00 00 00 06 0d 88 11 12 13 14 15 16 17 18 0a 82 07 04 1b 86 11 22 33 40 50 60 18 83 00 00 00 20 84 c0 de ad 03 
-
-result (PAGING_PS) = 38
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 13
-    RAID patched              (SGSN): 5
-    APN patched                     : 1
-    TLLI patched              (BSS ): 11
-    TLLI patched              (SGSN): 9
-    P-TMSI patched            (SGSN): 4
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 2
-    RoutingArea Update Accept count : 2
-    RoutingArea Update Compltd count: 1
-    PDP Activation Request count    : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead03 -> e0543210, IMSI 12131415161718, AGE 0
-PROCESSING LLC_DISCARDED from 0x01020304:1111
-00 00 00 00 2c 1f 84 c0 de ad 03 0f 81 01 04 82 ee e1 25 83 00 00 0c 
-
-CALLBACK, event 0, msg length 19, bvci 0x0000
-00 00 00 00 2c 1f 84 c0 de ad 03 0f 81 01 04 82 ee e1 25 83 00 00 0c 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 19 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 23
-00 00 00 00 2c 1f 84 e0 54 32 10 0f 81 01 04 82 ee e1 25 83 00 00 0c 
-
-result (LLC_DISCARDED) = 23
-
-Gbproxy global:
-PROCESSING BVC_SUSPEND_ACK from 0x05060708:32000
-00 00 00 00 0c 1f 84 e0 54 32 10 1b 86 00 f1 99 00 63 60 1d 81 01 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 0c 1f 84 e0 54 32 10 1b 86 00 f1 99 00 63 60 1d 81 01 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 28
-00 00 00 00 41 07 81 21 15 92 0c 1f 84 e0 54 32 10 1b 86 00 f1 99 00 63 60 1d 81 01 
-
-result (BVC_SUSPEND_ACK) = 28
-
-Gbproxy global:
-    Invalid Routing Area Identifier : 1
-    Patch error: no peer            : 1
-PROCESSING BVC_SUSPEND_ACK from 0x05060708:32000
-00 00 00 00 0c 1f 84 e0 54 32 10 1b 86 99 69 54 40 50 60 1d 81 01 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 0c 1f 84 e0 54 32 10 1b 86 99 69 54 40 50 60 1d 81 01 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 22
-00 00 00 00 0c 1f 84 c0 de ad 03 1b 86 11 22 33 40 50 60 1d 81 01 
-
-result (BVC_SUSPEND_ACK) = 22
-
-Gbproxy global:
-    Invalid Routing Area Identifier : 1
-    Patch error: no peer            : 1
-PROCESSING GMM INFO from 0x05060708:32000
-00 00 10 02 00 ee ba db ad 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 00 83 00 00 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-CALLBACK, event 0, msg length 58, bvci 0x1002
-00 00 10 02 00 ee ba db ad 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 00 83 00 00 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 58 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 62
-00 00 10 02 00 ee ba db ad 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 00 83 00 00 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-result (GMM INFO) = 62
-
-PROCESSING GMM INFO from 0x05060708:32000
-00 00 10 02 00 ee ba db ad 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 0d 08 21 68 71 6b 
-
-CALLBACK, event 0, msg length 66, bvci 0x1002
-00 00 10 02 00 ee ba db ad 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 0d 08 21 68 71 6b 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 70
-00 00 10 02 00 ee ba db ad 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 0d 08 21 68 71 6b 
-
-result (GMM INFO) = 70
-
-PROCESSING DETACH REQ from 0x01020304:1111
-00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 1d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb aa cc a3 
-
-CALLBACK, event 0, msg length 44, bvci 0x1002
-00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 1d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb aa cc a3 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 48
-00 00 10 02 01 e0 54 32 10 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 15 01 c0 1d 08 05 01 18 05 f4 e0 54 32 10 19 03 b9 97 cb ea 6d af 
-
-result (DETACH REQ) = 48
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 14
-    RAID patched              (SGSN): 6
-    APN patched                     : 1
-    TLLI patched              (BSS ): 13
-    TLLI patched              (SGSN): 10
-    P-TMSI patched            (BSS ): 1
-    P-TMSI patched            (SGSN): 4
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 2
-    RoutingArea Update Accept count : 2
-    RoutingArea Update Compltd count: 1
-    Detach Request count            : 1
-    PDP Activation Request count    : 1
-    TLLI from SGSN unknown          : 2
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead03 -> e0543210, IMSI 12131415161718, AGE 0
-PROCESSING DETACH ACC from 0x05060708:32000
-00 00 10 02 00 e0 54 32 10 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 19 08 06 00 04 ff 52 
-
-CALLBACK, event 0, msg length 67, bvci 0x1002
-00 00 10 02 00 e0 54 32 10 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 19 08 06 00 04 ff 52 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 71
-00 00 10 02 00 c0 de ad 03 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 19 08 06 00 04 ff 52 
-
-result (DETACH ACC) = 71
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 14
-    RAID patched              (SGSN): 6
-    APN patched                     : 1
-    TLLI patched              (BSS ): 13
-    TLLI patched              (SGSN): 11
-    P-TMSI patched            (BSS ): 1
-    P-TMSI patched            (SGSN): 4
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 2
-    RoutingArea Update Accept count : 2
-    RoutingArea Update Compltd count: 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    PDP Activation Request count    : 1
-    TLLI from SGSN unknown          : 2
-    TLLI-Cache: 0
-Gbproxy global:
-    Invalid Routing Area Identifier : 1
-    Patch error: no peer            : 1
-=== test_gbproxy_ptmsi_patching_bad_cases ===
---- Initialise SGSN ---
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 12
-02 00 81 01 01 82 01 01 04 82 01 00 
-
-PROCESSING RESET_ACK from 0x05060708:32000
-03 01 82 01 01 04 82 01 00 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0a 
-
-result (RESET_ACK) = 1
-
-PROCESSING ALIVE_ACK from 0x05060708:32000
-0b 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-06 
-
-result (ALIVE_ACK) = 1
-
-PROCESSING UNBLOCK_ACK from 0x05060708:32000
-07 
-
-==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000
-
-result (UNBLOCK_ACK) = 0
-
-PROCESSING ALIVE from 0x05060708:32000
-0a 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0b 
-
-result (ALIVE) = 1
-
---- Initialise BSS 1 ---
-
-Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096)
-
-PROCESSING RESET from 0x01020304:1111
-02 00 81 01 01 82 10 01 04 82 10 00 
-
-==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-03 01 82 10 01 04 82 10 00 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:1111
-0a 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:1111
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:1111
-0b 
-
-result (ALIVE_ACK) = 0
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 21 63 54 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 10 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 10 02 
-
-result (BVC_RESET_ACK) = 9
-
-Current NS-VCIs:
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Gbproxy global:
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 1
-    TLLI-Cache: 0
---- Send message from BSS 1 to SGSN, BVCI 0x1002 ---
-
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 78 de ad 00 00 00 04 08 88 21 63 54 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-result (ATTACH REQUEST) = 79
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 2
-    TLLI patched              (BSS ): 1
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 78dead00, IMSI (none), AGE 0
-PROCESSING IDENT REQUEST from 0x05060708:32000
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-CALLBACK, event 0, msg length 23, bvci 0x1002
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 27
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-result (IDENT REQUEST) = 27
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 2
-    TLLI patched              (BSS ): 1
-    TLLI patched              (SGSN): 1
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 78dead00, IMSI (none), AGE 0
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 44
-00 00 10 02 01 78 de ad 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 
-
-result (IDENT RESPONSE) = 44
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 3
-    TLLI patched              (BSS ): 2
-    TLLI patched              (SGSN): 1
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 78dead00, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 11 22 33 40 50 60 19 cd d7 08 17 16 18 05 f4 c0 de ad 01 0c 0a 29 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 3
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 2
-    TLLI patched              (SGSN): 2
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH ACCEPT (duplicated) from 0x05060708:32000
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 09 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 1d 9e 24 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 09 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 1d 9e 24 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 09 08 02 01 49 04 11 22 33 40 50 60 19 cd d7 08 17 16 18 05 f4 c0 de ad 01 42 f6 fc 
-
-result (ATTACH ACCEPT (duplicated)) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 3
-    RAID patched              (SGSN): 2
-    TLLI patched              (BSS ): 2
-    TLLI patched              (SGSN): 3
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 1
-    Attach Accept count             : 2
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc 
-
-result (ATTACH COMPLETE) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 4
-    RAID patched              (SGSN): 2
-    TLLI patched              (BSS ): 3
-    TLLI patched              (SGSN): 3
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 1
-    Attach Accept count             : 2
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING GMM INFO from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 0d 08 21 68 71 6b 
-
-CALLBACK, event 0, msg length 66, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 0d 08 21 68 71 6b 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 70
-00 00 10 02 00 c0 de ad 01 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 0d 08 21 68 71 6b 
-
-result (GMM INFO) = 70
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 4
-    RAID patched              (SGSN): 2
-    TLLI patched              (BSS ): 3
-    TLLI patched              (SGSN): 4
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 1
-    Attach Accept count             : 2
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH REQ from 0x01020304:1111
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 0d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 37 67 c6 
-
-CALLBACK, event 0, msg length 44, bvci 0x1002
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 0d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 37 67 c6 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 48
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 15 01 c0 0d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 37 67 c6 
-
-result (DETACH REQ) = 48
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 5
-    RAID patched              (SGSN): 2
-    TLLI patched              (BSS ): 4
-    TLLI patched              (SGSN): 4
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 1
-    Attach Accept count             : 2
-    Attach Completed count          : 1
-    Detach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH ACC from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 11 08 06 00 cf 8a 58 
-
-CALLBACK, event 0, msg length 67, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 11 08 06 00 cf 8a 58 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 71
-00 00 10 02 00 c0 de ad 01 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 11 08 06 00 cf 8a 58 
-
-result (DETACH ACC) = 71
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 5
-    RAID patched              (SGSN): 2
-    TLLI patched              (BSS ): 4
-    TLLI patched              (SGSN): 5
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 1
-    Attach Accept count             : 2
-    Attach Completed count          : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI-Cache: 0
-Gbproxy global:
-=== test_gbproxy_imsi_acquisition ===
---- Initialise SGSN ---
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 12
-02 00 81 01 01 82 01 01 04 82 01 00 
-
-PROCESSING RESET_ACK from 0x05060708:32000
-03 01 82 01 01 04 82 01 00 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0a 
-
-result (RESET_ACK) = 1
-
-PROCESSING ALIVE_ACK from 0x05060708:32000
-0b 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-06 
-
-result (ALIVE_ACK) = 1
-
-PROCESSING UNBLOCK_ACK from 0x05060708:32000
-07 
-
-==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000
-
-result (UNBLOCK_ACK) = 0
-
-PROCESSING ALIVE from 0x05060708:32000
-0a 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0b 
-
-result (ALIVE) = 1
-
---- Initialise BSS 1 ---
-
-Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096)
-
-PROCESSING RESET from 0x01020304:1111
-02 00 81 01 01 82 10 01 04 82 10 00 
-
-==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-03 01 82 10 01 04 82 10 00 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:1111
-0a 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:1111
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:1111
-0b 
-
-result (ALIVE_ACK) = 0
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 21 63 54 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 10 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 10 02 
-
-result (BVC_RESET_ACK) = 9
-
-Current NS-VCIs:
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Gbproxy global:
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 1
-    TLLI-Cache: 0
---- Send message from BSS 1 to SGSN, BVCI 0x1002 ---
-
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 15 01 b7 f8 36 
-
-result (ATTACH REQUEST) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 1
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 78dead00, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 78 de ad 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 21 63 54 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 8e cd 32 
-
-result (IDENT RESPONSE) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 3
-    TLLI patched              (BSS ): 1
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 78dead00, IMSI 12131415161718, AGE 0
-PROCESSING IDENT REQUEST from 0x05060708:32000
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-CALLBACK, event 0, msg length 23, bvci 0x1002
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 27
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-result (IDENT REQUEST) = 27
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 3
-    TLLI patched              (BSS ): 1
-    TLLI patched              (SGSN): 1
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 78dead00, IMSI 12131415161718, AGE 0
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 09 08 16 08 11 12 13 14 15 16 17 18 ba 14 c3 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 09 08 16 08 11 12 13 14 15 16 17 18 ba 14 c3 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 44
-00 00 10 02 01 78 de ad 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 09 08 16 08 11 12 13 14 15 16 17 18 ba 14 c3 
-
-result (IDENT RESPONSE) = 44
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 4
-    TLLI patched              (BSS ): 2
-    TLLI patched              (SGSN): 1
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 78dead00, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 11 22 33 40 50 60 19 cd d7 08 17 16 18 05 f4 c0 de ad 01 0c 0a 29 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 4
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 2
-    TLLI patched              (SGSN): 2
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 0d 08 03 55 1c ea 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 0d 08 03 55 1c ea 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 08 01 c0 0d 08 03 55 1c ea 
-
-result (ATTACH COMPLETE) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 5
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 3
-    TLLI patched              (SGSN): 2
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING GMM INFO from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-CALLBACK, event 0, msg length 66, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 70
-00 00 10 02 00 c0 de ad 01 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-result (GMM INFO) = 70
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 5
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 3
-    TLLI patched              (SGSN): 3
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING XID (UL) from 0x01020304:1111
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 
-
-CALLBACK, event 0, msg length 38, bvci 0x1002
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 38 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 42
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 
-
-result (XID (UL)) = 42
-
-PROCESSING XID (DL) from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e 
-
-CALLBACK, event 0, msg length 70, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 70 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 74
-00 00 10 02 00 c0 de ad 01 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e 
-
-result (XID (DL)) = 74
-
-PROCESSING LL11 DNS QUERY (UL) from 0x01020304:1111
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 
-
-CALLBACK, event 0, msg length 89, bvci 0x1002
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 89 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 93
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 
-
-result (LL11 DNS QUERY (UL)) = 93
-
-PROCESSING LL11 DNS RESP (DL) from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 
-
-CALLBACK, event 0, msg length 267, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 267 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 271
-00 00 10 02 00 c0 de ad 01 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 
-
-result (LL11 DNS RESP (DL)) = 271
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 7
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 5
-    TLLI patched              (SGSN): 5
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING LLC_DISCARDED from 0x01020304:1111
-00 00 00 00 2c 1f 84 c0 de ad 01 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-CALLBACK, event 0, msg length 19, bvci 0x0000
-00 00 00 00 2c 1f 84 c0 de ad 01 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 19 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 23
-00 00 00 00 2c 1f 84 ef e2 b7 00 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-result (LLC_DISCARDED) = 23
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 7
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 6
-    TLLI patched              (SGSN): 5
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING LLC_DISCARDED from 0x05060708:32000
-00 00 00 00 2c 1f 84 ef e2 b7 00 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-CALLBACK, event 0, msg length 19, bvci 0x0000
-00 00 00 00 2c 1f 84 ef e2 b7 00 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 25 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 29
-00 00 00 00 41 07 81 27 15 93 2c 1f 84 ef e2 b7 00 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-result (LLC_DISCARDED) = 29
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 7
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 6
-    TLLI patched              (SGSN): 6
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING BVC_SUSPEND from 0x01020304:1111
-00 00 00 00 0b 1f 84 c0 de ad 01 1b 86 11 22 33 40 50 60 
-
-CALLBACK, event 0, msg length 15, bvci 0x0000
-00 00 00 00 0b 1f 84 c0 de ad 01 1b 86 11 22 33 40 50 60 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 15 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 19
-00 00 00 00 0b 1f 84 ef e2 b7 00 1b 86 21 63 54 40 50 60 
-
-result (BVC_SUSPEND) = 19
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 8
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 7
-    TLLI patched              (SGSN): 6
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING BVC_SUSPEND_ACK from 0x05060708:32000
-00 00 00 00 0c 1f 84 ef e2 b7 00 1b 86 21 63 54 40 50 60 1d 81 01 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 0c 1f 84 ef e2 b7 00 1b 86 21 63 54 40 50 60 1d 81 01 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 22
-00 00 00 00 0c 1f 84 c0 de ad 01 1b 86 11 22 33 40 50 60 1d 81 01 
-
-result (BVC_SUSPEND_ACK) = 22
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 8
-    RAID patched              (SGSN): 2
-    TLLI patched              (BSS ): 7
-    TLLI patched              (SGSN): 7
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING LLC_DISCARDED from 0x01020304:1111
-00 00 00 00 2c 1f 84 c0 de ad 01 0f 81 01 04 82 ee e1 25 83 00 00 0c 
-
-CALLBACK, event 0, msg length 19, bvci 0x0000
-00 00 00 00 2c 1f 84 c0 de ad 01 0f 81 01 04 82 ee e1 25 83 00 00 0c 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 19 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 23
-00 00 00 00 2c 1f 84 ef e2 b7 00 0f 81 01 04 82 ee e1 25 83 00 00 0c 
-
-result (LLC_DISCARDED) = 23
-
-Gbproxy global:
-    BSSGP protocol error      (SGSN): 1
-PROCESSING BVC_SUSPEND_ACK from 0x05060708:32000
-00 00 00 00 0c 1f 84 ef e2 b7 00 1b 86 00 f1 99 00 63 60 1d 81 01 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 0c 1f 84 ef e2 b7 00 1b 86 00 f1 99 00 63 60 1d 81 01 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 28
-00 00 00 00 41 07 81 21 15 92 0c 1f 84 ef e2 b7 00 1b 86 00 f1 99 00 63 60 1d 81 01 
-
-result (BVC_SUSPEND_ACK) = 28
-
-Gbproxy global:
-    Invalid Routing Area Identifier : 1
-    BSSGP protocol error      (SGSN): 1
-    Patch error: no peer            : 1
-PROCESSING BVC_SUSPEND_ACK from 0x05060708:32000
-00 00 00 00 0c 1f 84 ef e2 b7 00 1b 86 99 69 54 40 50 60 1d 81 01 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 0c 1f 84 ef e2 b7 00 1b 86 99 69 54 40 50 60 1d 81 01 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 22
-00 00 00 00 0c 1f 84 c0 de ad 01 1b 86 11 22 33 40 50 60 1d 81 01 
-
-result (BVC_SUSPEND_ACK) = 22
-
-Gbproxy global:
-    Invalid Routing Area Identifier : 1
-    BSSGP protocol error      (SGSN): 1
-    Patch error: no peer            : 1
-PROCESSING DETACH REQ from 0x01020304:1111
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 11 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 6d b1 de 
-
-CALLBACK, event 0, msg length 44, bvci 0x1002
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 11 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 6d b1 de 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 48
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 15 01 c0 11 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 6d b1 de 
-
-result (DETACH REQ) = 48
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 9
-    RAID patched              (SGSN): 3
-    TLLI patched              (BSS ): 9
-    TLLI patched              (SGSN): 8
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    Detach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH ACC from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 0d 08 06 00 aa ab ee 
-
-CALLBACK, event 0, msg length 67, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 0d 08 06 00 aa ab ee 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 71
-00 00 10 02 00 c0 de ad 01 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 0d 08 06 00 aa ab ee 
-
-result (DETACH ACC) = 71
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 9
-    RAID patched              (SGSN): 3
-    TLLI patched              (BSS ): 9
-    TLLI patched              (SGSN): 9
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI-Cache: 0
-PROCESSING RA UPD REQ from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 
-
-CALLBACK, event 0, msg length 85, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 15 01 b7 f8 36 
-
-result (RA UPD REQ) = 0
-
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 19 08 16 08 11 12 13 14 15 16 17 18 35 23 fc 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 19 08 16 08 11 12 13 14 15 16 17 18 35 23 fc 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 85 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 89
-00 00 10 02 01 78 de ad 02 00 00 04 08 88 21 63 54 00 63 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 
-
-result (IDENT RESPONSE) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 10
-    RAID patched              (SGSN): 3
-    TLLI patched              (BSS ): 10
-    TLLI patched              (SGSN): 9
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 78dead02, IMSI 12131415161718, AGE 0
-PROCESSING RA UDP ACC from 0x05060708:32000
-00 00 10 02 00 78 de ad 02 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 11 08 09 00 49 21 63 54 40 50 60 19 54 ab b3 18 05 f4 ef e2 b7 00 17 16 36 98 77 
-
-CALLBACK, event 0, msg length 87, bvci 0x1002
-00 00 10 02 00 78 de ad 02 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 11 08 09 00 49 21 63 54 40 50 60 19 54 ab b3 18 05 f4 ef e2 b7 00 17 16 36 98 77 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 87 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 91
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 11 08 09 00 49 11 22 33 40 50 60 19 54 ab b3 18 05 f4 c0 de ad 03 17 16 6e 58 26 
-
-result (RA UDP ACC) = 91
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 10
-    RAID patched              (SGSN): 4
-    TLLI patched              (BSS ): 10
-    TLLI patched              (SGSN): 10
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 1
-    RoutingArea Update Accept count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead/c0dead03 -> 78dead02/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH REQ from 0x01020304:1111
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 1d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb aa cc a3 
-
-CALLBACK, event 0, msg length 44, bvci 0x1002
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 1d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb aa cc a3 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 c0 de ad 01 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 06 00 11 f5 c0 
-
-result (DETACH REQ) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 10
-    RAID patched              (SGSN): 4
-    TLLI patched              (BSS ): 10
-    TLLI patched              (SGSN): 10
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 1
-    RoutingArea Update Accept count : 1
-    Detach Request count            : 2
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead/c0dead03 -> 78dead02/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH ACC from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 15 08 06 00 f7 35 f0 
-
-CALLBACK, event 0, msg length 67, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 15 08 06 00 f7 35 f0 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 71
-00 00 10 02 00 c0 de ad 03 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 15 08 06 00 f7 35 f0 
-
-result (DETACH ACC) = 71
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 10
-    RAID patched              (SGSN): 4
-    TLLI patched              (BSS ): 10
-    TLLI patched              (SGSN): 11
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 1
-    RoutingArea Update Accept count : 1
-    Detach Request count            : 2
-    Detach Accept count             : 2
-    TLLI-Cache: 0
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 21 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 44 b6 bb 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 21 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 44 b6 bb 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 15 01 b7 f8 36 
-
-result (ATTACH REQUEST) = 0
-
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 25 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 1d aa 57 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 25 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 1d aa 57 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 00 09 41 c4 05 08 15 01 8f 47 9e 
-
-result (ATTACH REQUEST) = 0
-
-PROCESSING DETACH REQ from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 29 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb d9 1d ef 
-
-CALLBACK, event 0, msg length 44, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 29 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb d9 1d ef 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 00 09 41 c4 09 08 06 00 da 80 ca 
-
-result (DETACH REQ) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 10
-    RAID patched              (SGSN): 4
-    TLLI patched              (BSS ): 10
-    TLLI patched              (SGSN): 11
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 3
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 1
-    RoutingArea Update Accept count : 1
-    Detach Request count            : 3
-    Detach Accept count             : 2
-    TLLI-Cache: 0
-PROCESSING DETACH REQ (unknown TLLI) from 0x01020304:1111
-00 00 10 02 01 80 00 be ef 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 2d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 0d 30 0d 
-
-CALLBACK, event 0, msg length 44, bvci 0x1002
-00 00 10 02 01 80 00 be ef 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 2d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 0d 30 0d 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 80 00 be ef 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 06 00 11 f5 c0 
-
-result (DETACH REQ (unknown TLLI)) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 10
-    RAID patched              (SGSN): 4
-    TLLI patched              (BSS ): 10
-    TLLI patched              (SGSN): 11
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 3
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 1
-    RoutingArea Update Accept count : 1
-    Detach Request count            : 4
-    Detach Accept count             : 2
-    TLLI-Cache: 0
-PROCESSING RA UPD REQ from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 70 80 00 80 0e 00 3e 01 c0 31 08 08 10 11 22 33 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 d8 cf d8 
-
-CALLBACK, event 0, msg length 85, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 70 80 00 80 0e 00 3e 01 c0 31 08 08 10 11 22 33 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 d8 cf d8 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 15 01 b7 f8 36 
-
-result (RA UPD REQ) = 0
-
-PROCESSING RA UPD REQ from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 70 80 00 80 0e 00 3e 01 c0 35 08 08 10 11 22 33 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 ac 9c 37 
-
-CALLBACK, event 0, msg length 85, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 70 80 00 80 0e 00 3e 01 c0 35 08 08 10 11 22 33 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 ac 9c 37 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 00 09 41 c4 05 08 15 01 8f 47 9e 
-
-result (RA UPD REQ) = 0
-
-PROCESSING DETACH REQ from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 39 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 44 b6 8a 
-
-CALLBACK, event 0, msg length 44, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 39 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 44 b6 8a 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 00 09 41 c4 09 08 06 00 da 80 ca 
-
-result (DETACH REQ) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 10
-    RAID patched              (SGSN): 4
-    TLLI patched              (BSS ): 10
-    TLLI patched              (SGSN): 11
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 3
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    RoutingArea Update Request count: 3
-    RoutingArea Update Accept count : 1
-    Detach Request count            : 5
-    Detach Accept count             : 2
-    TLLI-Cache: 0
-Gbproxy global:
-    Invalid Routing Area Identifier : 1
-    BSSGP protocol error      (SGSN): 1
-    Patch error: no peer            : 1
-=== test_gbproxy_secondary_sgsn ===
---- Initialise SGSN 1 ---
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 12
-02 00 81 01 01 82 01 01 04 82 01 00 
-
-PROCESSING RESET_ACK from 0x05060708:32000
-03 01 82 01 01 04 82 01 00 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0a 
-
-result (RESET_ACK) = 1
-
-PROCESSING ALIVE_ACK from 0x05060708:32000
-0b 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-06 
-
-result (ALIVE_ACK) = 1
-
-PROCESSING UNBLOCK_ACK from 0x05060708:32000
-07 
-
-==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000
-
-result (UNBLOCK_ACK) = 0
-
-PROCESSING ALIVE from 0x05060708:32000
-0a 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0b 
-
-result (ALIVE) = 1
-
---- Initialise SGSN 2 ---
-
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 12
-02 00 81 01 01 82 01 03 04 82 01 02 
-
-PROCESSING RESET_ACK from 0x15161718:32001
-03 01 82 01 03 04 82 01 02 
-
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 1
-0a 
-
-result (RESET_ACK) = 1
-
-PROCESSING ALIVE_ACK from 0x15161718:32001
-0b 
-
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 1
-06 
-
-result (ALIVE_ACK) = 1
-
-PROCESSING UNBLOCK_ACK from 0x15161718:32001
-07 
-
-==> got signal NS_UNBLOCK, NS-VC 0x0103/21.22.23.24:32001
-
-result (UNBLOCK_ACK) = 0
-
-PROCESSING ALIVE from 0x15161718:32001
-0a 
-
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 1
-0b 
-
-result (ALIVE) = 1
-
---- Initialise BSS 1 ---
-
-Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096)
-
-PROCESSING RESET from 0x01020304:1111
-02 00 81 01 01 82 10 01 04 82 10 00 
-
-==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-03 01 82 10 01 04 82 10 00 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:1111
-0a 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:1111
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:1111
-0b 
-
-result (ALIVE_ACK) = 0
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x0000(0)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 00 00 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 00 00 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 00 00 
-
-result (BVC_RESET) = 9
-
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 00 00 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 00 00 
-
-result (BVC_RESET_ACK) = -2
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN 2, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 22
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 21 63 54 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 21 63 54 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 10 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 10 02 
-
-result (BVC_RESET_ACK) = 9
-
-PROCESSING BVC_RESET_ACK from 0x15161718:32001
-00 00 00 00 23 04 82 10 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 10 02 
-
-result (BVC_RESET_ACK) = 1
-
-Current NS-VCIs:
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111
-    VCI 0x0103, NSEI 0x0102, peer 0x15161718:32001
-         NS-VC Block count         : 1
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Gbproxy global:
-    Invalid BVC Identifier          : 1
-    Patch error: no peer            : 1
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 1
-    TLLI-Cache: 0
---- Flow control ---
-
-PROCESSING FLOW_CONTROL_BVC from 0x01020304:1111
-00 00 10 02 26 1e 81 01 05 82 01 dc 03 82 02 76 01 82 00 50 1c 82 02 58 06 82 00 03 
-
-CALLBACK, event 0, msg length 24, bvci 0x1002
-00 00 10 02 26 1e 81 01 05 82 01 dc 03 82 02 76 01 82 00 50 1c 82 02 58 06 82 00 03 
-
-NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 28
-00 00 10 02 26 1e 81 01 05 82 01 dc 03 82 02 76 01 82 00 50 1c 82 02 58 06 82 00 03 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 28
-00 00 10 02 26 1e 81 01 05 82 01 dc 03 82 02 76 01 82 00 50 1c 82 02 58 06 82 00 03 
-
-result (FLOW_CONTROL_BVC) = 28
-
-PROCESSING FLOW_CONTROL_BVC_ACK from 0x05060708:32000
-00 00 10 02 27 1e 81 01 
-
-CALLBACK, event 0, msg length 4, bvci 0x1002
-00 00 10 02 27 1e 81 01 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 4 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 8
-00 00 10 02 27 1e 81 01 
-
-result (FLOW_CONTROL_BVC_ACK) = 8
-
-PROCESSING FLOW_CONTROL_BVC_ACK from 0x15161718:32001
-00 00 10 02 27 1e 81 01 
-
-CALLBACK, event 0, msg length 4, bvci 0x1002
-00 00 10 02 27 1e 81 01 
-
-result (FLOW_CONTROL_BVC_ACK) = 0
-
---- Establish GPRS connection (SGSN 1) ---
-
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 15 01 b7 f8 36 
-
-result (ATTACH REQUEST) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 1
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 78dead00, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress, SGSN NSEI 65535
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 78 de ad 00 00 00 04 08 88 21 63 54 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-result (IDENT RESPONSE) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 2
-    TLLI patched              (BSS ): 1
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 78dead00, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING IDENT REQUEST from 0x05060708:32000
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-CALLBACK, event 0, msg length 23, bvci 0x1002
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 27
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-result (IDENT REQUEST) = 27
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 2
-    TLLI patched              (BSS ): 1
-    TLLI patched              (SGSN): 1
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 78dead00, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 09 08 16 08 11 12 13 14 15 16 17 18 ba 14 c3 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 09 08 16 08 11 12 13 14 15 16 17 18 ba 14 c3 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 44
-00 00 10 02 01 78 de ad 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 09 08 16 08 11 12 13 14 15 16 17 18 ba 14 c3 
-
-result (IDENT RESPONSE) = 44
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 3
-    TLLI patched              (BSS ): 2
-    TLLI patched              (SGSN): 1
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 78dead00, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 11 22 33 40 50 60 19 cd d7 08 17 16 18 05 f4 c0 de ad 01 0c 0a 29 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 3
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 2
-    TLLI patched              (SGSN): 2
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 0d 08 03 55 1c ea 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 0d 08 03 55 1c ea 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 08 01 c0 0d 08 03 55 1c ea 
-
-result (ATTACH COMPLETE) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 4
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 3
-    TLLI patched              (SGSN): 2
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING GMM INFO from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-CALLBACK, event 0, msg length 66, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 70
-00 00 10 02 00 c0 de ad 01 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-result (GMM INFO) = 70
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 4
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 3
-    TLLI patched              (SGSN): 3
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING XID (UL) from 0x01020304:1111
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 
-
-CALLBACK, event 0, msg length 38, bvci 0x1002
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 38 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 42
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 
-
-result (XID (UL)) = 42
-
-PROCESSING XID (DL) from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e 
-
-CALLBACK, event 0, msg length 70, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 70 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 74
-00 00 10 02 00 c0 de ad 01 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e 
-
-result (XID (DL)) = 74
-
-PROCESSING LL11 DNS QUERY (UL) from 0x01020304:1111
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 
-
-CALLBACK, event 0, msg length 89, bvci 0x1002
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 89 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 93
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 
-
-result (LL11 DNS QUERY (UL)) = 93
-
-PROCESSING LL11 DNS RESP (DL) from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 
-
-CALLBACK, event 0, msg length 267, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 267 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 271
-00 00 10 02 00 c0 de ad 01 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 
-
-result (LL11 DNS RESP (DL)) = 271
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 6
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 5
-    TLLI patched              (SGSN): 5
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING LLC_DISCARDED from 0x01020304:1111
-00 00 00 00 2c 1f 84 c0 de ad 01 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-CALLBACK, event 0, msg length 19, bvci 0x0000
-00 00 00 00 2c 1f 84 c0 de ad 01 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 19 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 23
-00 00 00 00 2c 1f 84 ef e2 b7 00 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-result (LLC_DISCARDED) = 23
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 6
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 6
-    TLLI patched              (SGSN): 5
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING LLC_DISCARDED from 0x05060708:32000
-00 00 00 00 2c 1f 84 ef e2 b7 00 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-CALLBACK, event 0, msg length 19, bvci 0x0000
-00 00 00 00 2c 1f 84 ef e2 b7 00 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 25 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 29
-00 00 00 00 41 07 81 27 15 93 2c 1f 84 ef e2 b7 00 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-result (LLC_DISCARDED) = 29
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 6
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 6
-    TLLI patched              (SGSN): 6
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING BVC_SUSPEND from 0x01020304:1111
-00 00 00 00 0b 1f 84 c0 de ad 01 1b 86 11 22 33 40 50 60 
-
-CALLBACK, event 0, msg length 15, bvci 0x0000
-00 00 00 00 0b 1f 84 c0 de ad 01 1b 86 11 22 33 40 50 60 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 15 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 19
-00 00 00 00 0b 1f 84 ef e2 b7 00 1b 86 21 63 54 40 50 60 
-
-result (BVC_SUSPEND) = 19
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 7
-    RAID patched              (SGSN): 1
-    TLLI patched              (BSS ): 7
-    TLLI patched              (SGSN): 6
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING BVC_SUSPEND_ACK from 0x05060708:32000
-00 00 00 00 0c 1f 84 ef e2 b7 00 1b 86 21 63 54 40 50 60 1d 81 01 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 0c 1f 84 ef e2 b7 00 1b 86 21 63 54 40 50 60 1d 81 01 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 22
-00 00 00 00 0c 1f 84 c0 de ad 01 1b 86 11 22 33 40 50 60 1d 81 01 
-
-result (BVC_SUSPEND_ACK) = 22
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 7
-    RAID patched              (SGSN): 2
-    TLLI patched              (BSS ): 7
-    TLLI patched              (SGSN): 7
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
---- Establish GPRS connection (SGSN 2) ---
-
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 80 00 be ef 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 11 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 bf 00 5c 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 80 00 be ef 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 11 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 bf 00 5c 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 80 00 be ef 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 15 01 b7 f8 36 
-
-result (ATTACH REQUEST) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 7
-    RAID patched              (SGSN): 2
-    TLLI patched              (BSS ): 7
-    TLLI patched              (SGSN): 7
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 2
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI 8000beef -> 78dead02, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress, SGSN NSEI 65535
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 80 00 be ef 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 15 08 16 08 11 12 99 99 99 16 17 18 b2 dd 58 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 80 00 be ef 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 15 08 16 08 11 12 99 99 99 16 17 18 b2 dd 58 
-
-NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 79
-00 00 10 02 01 78 de ad 02 00 00 04 08 88 21 63 54 00 63 60 12 34 00 80 0e 00 34 01 c0 11 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 bf 00 5c 
-
-result (IDENT RESPONSE) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 8
-    RAID patched              (SGSN): 2
-    TLLI patched              (BSS ): 8
-    TLLI patched              (SGSN): 7
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 2
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI 8000beef -> 78dead02, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING IDENT REQUEST from 0x15161718:32001
-00 00 10 02 00 78 de ad 02 00 50 20 16 82 02 58 0e 89 41 c0 0d 08 15 01 0c a6 18 
-
-CALLBACK, event 0, msg length 23, bvci 0x1002
-00 00 10 02 00 78 de ad 02 00 50 20 16 82 02 58 0e 89 41 c0 0d 08 15 01 0c a6 18 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 27
-00 00 10 02 00 80 00 be ef 00 50 20 16 82 02 58 0e 89 41 c0 0d 08 15 01 0c a6 18 
-
-result (IDENT REQUEST) = 27
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 8
-    RAID patched              (SGSN): 2
-    TLLI patched              (BSS ): 8
-    TLLI patched              (SGSN): 8
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 2
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI 8000beef -> 78dead02, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 80 00 be ef 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 19 08 16 08 11 12 99 99 99 16 17 18 a5 cc b3 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 80 00 be ef 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 19 08 16 08 11 12 99 99 99 16 17 18 a5 cc b3 
-
-NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg)
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 44
-00 00 10 02 01 78 de ad 02 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 19 08 16 08 11 12 99 99 99 16 17 18 a5 cc b3 
-
-result (IDENT RESPONSE) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 9
-    RAID patched              (SGSN): 2
-    TLLI patched              (BSS ): 9
-    TLLI patched              (SGSN): 8
-    P-TMSI patched            (SGSN): 1
-    Attach Request count            : 2
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI 8000beef -> 78dead02, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING ATTACH ACCEPT from 0x15161718:32001
-00 00 10 02 00 78 de ad 02 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 9e 41 c0 11 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 e0 98 76 54 cb 1c 5b 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 78 de ad 02 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 9e 41 c0 11 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 e0 98 76 54 cb 1c 5b 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 80 00 be ef 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 9e 41 c0 11 08 02 01 49 04 11 22 33 40 50 60 19 cd d7 08 17 16 18 05 f4 c0 de ad 03 32 40 fa 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 9
-    RAID patched              (SGSN): 3
-    TLLI patched              (BSS ): 9
-    TLLI patched              (SGSN): 9
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 2
-    Attach Accept count             : 2
-    Attach Completed count          : 1
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI 8000beef/c0dead03 -> 78dead02/e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 1d 08 03 5e 3a ea 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 1d 08 03 5e 3a ea 
-
-NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 35
-00 00 10 02 01 e0 98 76 54 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 08 01 c0 1d 08 03 5e 3a ea 
-
-result (ATTACH COMPLETE) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 10
-    RAID patched              (SGSN): 3
-    TLLI patched              (BSS ): 10
-    TLLI patched              (SGSN): 9
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 2
-    Attach Accept count             : 2
-    Attach Completed count          : 2
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI 8000beef/c0dead03 -> 78dead02/e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING GMM INFO from 0x15161718:32001
-00 00 10 02 00 e0 98 76 54 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 88 41 c0 15 08 21 bb c1 c6 
-
-CALLBACK, event 0, msg length 66, bvci 0x1002
-00 00 10 02 00 e0 98 76 54 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 88 41 c0 15 08 21 bb c1 c6 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 70
-00 00 10 02 00 c0 de ad 03 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 88 41 c0 15 08 21 bb c1 c6 
-
-result (GMM INFO) = 70
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 10
-    RAID patched              (SGSN): 3
-    TLLI patched              (BSS ): 10
-    TLLI patched              (SGSN): 10
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 2
-    Attach Accept count             : 2
-    Attach Completed count          : 2
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING XID (UL) from 0x01020304:1111
-00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 
-
-CALLBACK, event 0, msg length 38, bvci 0x1002
-00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 
-
-NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 38 (gprs_ns_sendmsg)
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 42
-00 00 10 02 01 e0 98 76 54 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 
-
-result (XID (UL)) = 0
-
-PROCESSING XID (DL) from 0x15161718:32001
-00 00 10 02 00 e0 98 76 54 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e 
-
-CALLBACK, event 0, msg length 70, bvci 0x1002
-00 00 10 02 00 e0 98 76 54 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 70 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 74
-00 00 10 02 00 c0 de ad 03 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e 
-
-result (XID (DL)) = 74
-
-PROCESSING LL11 DNS QUERY (UL) from 0x01020304:1111
-00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 
-
-CALLBACK, event 0, msg length 89, bvci 0x1002
-00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 
-
-NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 89 (gprs_ns_sendmsg)
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 93
-00 00 10 02 01 e0 98 76 54 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 
-
-result (LL11 DNS QUERY (UL)) = 0
-
-PROCESSING LL11 DNS RESP (DL) from 0x15161718:32001
-00 00 10 02 00 e0 98 76 54 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 
-
-CALLBACK, event 0, msg length 267, bvci 0x1002
-00 00 10 02 00 e0 98 76 54 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 267 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 271
-00 00 10 02 00 c0 de ad 03 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 
-
-result (LL11 DNS RESP (DL)) = 271
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 12
-    RAID patched              (SGSN): 3
-    TLLI patched              (BSS ): 12
-    TLLI patched              (SGSN): 12
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 2
-    Attach Accept count             : 2
-    Attach Completed count          : 2
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING LLC_DISCARDED from 0x01020304:1111
-00 00 00 00 2c 1f 84 c0 de ad 03 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-CALLBACK, event 0, msg length 19, bvci 0x0000
-00 00 00 00 2c 1f 84 c0 de ad 03 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-NS UNITDATA MESSAGE to SGSN 2, BVCI 0x0000, msg length 19 (gprs_ns_sendmsg)
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 23
-00 00 00 00 2c 1f 84 e0 98 76 54 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-result (LLC_DISCARDED) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 12
-    RAID patched              (SGSN): 3
-    TLLI patched              (BSS ): 13
-    TLLI patched              (SGSN): 12
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 2
-    Attach Accept count             : 2
-    Attach Completed count          : 2
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING LLC_DISCARDED from 0x15161718:32001
-00 00 00 00 2c 1f 84 e0 98 76 54 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-CALLBACK, event 0, msg length 19, bvci 0x0000
-00 00 00 00 2c 1f 84 e0 98 76 54 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-NS UNITDATA MESSAGE to SGSN 2, BVCI 0x0000, msg length 25 (gprs_ns_sendmsg)
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 29
-00 00 00 00 41 07 81 27 15 93 2c 1f 84 e0 98 76 54 0f 81 01 04 82 10 02 25 83 00 00 0c 
-
-result (LLC_DISCARDED) = 29
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 12
-    RAID patched              (SGSN): 3
-    TLLI patched              (BSS ): 13
-    TLLI patched              (SGSN): 13
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 2
-    Attach Accept count             : 2
-    Attach Completed count          : 2
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING BVC_SUSPEND from 0x01020304:1111
-00 00 00 00 0b 1f 84 c0 de ad 03 1b 86 11 22 33 40 50 60 
-
-CALLBACK, event 0, msg length 15, bvci 0x0000
-00 00 00 00 0b 1f 84 c0 de ad 03 1b 86 11 22 33 40 50 60 
-
-NS UNITDATA MESSAGE to SGSN 2, BVCI 0x0000, msg length 15 (gprs_ns_sendmsg)
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 19
-00 00 00 00 0b 1f 84 e0 98 76 54 1b 86 21 63 54 40 50 60 
-
-result (BVC_SUSPEND) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 13
-    RAID patched              (SGSN): 3
-    TLLI patched              (BSS ): 14
-    TLLI patched              (SGSN): 13
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 2
-    Attach Accept count             : 2
-    Attach Completed count          : 2
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING BVC_SUSPEND_ACK from 0x15161718:32001
-00 00 00 00 0c 1f 84 e0 98 76 54 1b 86 21 63 54 40 50 60 1d 81 01 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 0c 1f 84 e0 98 76 54 1b 86 21 63 54 40 50 60 1d 81 01 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 22
-00 00 00 00 0c 1f 84 c0 de ad 03 1b 86 11 22 33 40 50 60 1d 81 01 
-
-result (BVC_SUSPEND_ACK) = 22
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 13
-    RAID patched              (SGSN): 4
-    TLLI patched              (BSS ): 14
-    TLLI patched              (SGSN): 14
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 2
-    Attach Accept count             : 2
-    Attach Completed count          : 2
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
---- Establish GPRS connection (SGSN 2, P-TMSI collision) ---
-
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 80 00 fe ed 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 21 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 44 b6 bb 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 80 00 fe ed 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 21 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 44 b6 bb 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 80 00 fe ed 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 15 01 b7 f8 36 
-
-result (ATTACH REQUEST) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 13
-    RAID patched              (SGSN): 4
-    TLLI patched              (BSS ): 14
-    TLLI patched              (SGSN): 14
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 3
-    Attach Accept count             : 2
-    Attach Completed count          : 2
-    TLLI cache size                 : 3
-    TLLI-Cache: 3
-      TLLI 8000feed -> 78dead04, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress, SGSN NSEI 65535
-      TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 80 00 fe ed 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 25 08 16 08 11 12 99 99 99 26 27 28 58 c7 cb 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 80 00 fe ed 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 25 08 16 08 11 12 99 99 99 26 27 28 58 c7 cb 
-
-NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 79
-00 00 10 02 01 78 de ad 04 00 00 04 08 88 21 63 54 00 63 60 12 34 00 80 0e 00 34 01 c0 21 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 44 b6 bb 
-
-result (IDENT RESPONSE) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 14
-    RAID patched              (SGSN): 4
-    TLLI patched              (BSS ): 15
-    TLLI patched              (SGSN): 14
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 3
-    Attach Accept count             : 2
-    Attach Completed count          : 2
-    TLLI cache size                 : 3
-    TLLI-Cache: 3
-      TLLI 8000feed -> 78dead04, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING IDENT REQUEST from 0x15161718:32001
-00 00 10 02 00 78 de ad 04 00 50 20 16 82 02 58 0e 89 41 c0 19 08 15 01 a2 f2 a4 
-
-CALLBACK, event 0, msg length 23, bvci 0x1002
-00 00 10 02 00 78 de ad 04 00 50 20 16 82 02 58 0e 89 41 c0 19 08 15 01 a2 f2 a4 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 27
-00 00 10 02 00 80 00 fe ed 00 50 20 16 82 02 58 0e 89 41 c0 19 08 15 01 a2 f2 a4 
-
-result (IDENT REQUEST) = 27
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 14
-    RAID patched              (SGSN): 4
-    TLLI patched              (BSS ): 15
-    TLLI patched              (SGSN): 15
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 3
-    Attach Accept count             : 2
-    Attach Completed count          : 2
-    TLLI cache size                 : 3
-    TLLI-Cache: 3
-      TLLI 8000feed -> 78dead04, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 80 00 fe ed 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 29 08 16 08 11 12 99 99 99 26 27 28 4f d6 20 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 80 00 fe ed 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 29 08 16 08 11 12 99 99 99 26 27 28 4f d6 20 
-
-NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg)
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 44
-00 00 10 02 01 78 de ad 04 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 29 08 16 08 11 12 99 99 99 26 27 28 4f d6 20 
-
-result (IDENT RESPONSE) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 15
-    RAID patched              (SGSN): 4
-    TLLI patched              (BSS ): 16
-    TLLI patched              (SGSN): 15
-    P-TMSI patched            (SGSN): 2
-    Attach Request count            : 3
-    Attach Accept count             : 2
-    Attach Completed count          : 2
-    TLLI cache size                 : 3
-    TLLI-Cache: 3
-      TLLI 8000feed -> 78dead04, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING ATTACH ACCEPT (P-TMSI 1) from 0x15161718:32001
-00 00 10 02 00 78 de ad 04 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 26 27 28 00 81 00 0e 9e 41 c0 1d 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 74 91 01 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 78 de ad 04 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 26 27 28 00 81 00 0e 9e 41 c0 1d 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 74 91 01 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 80 00 fe ed 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 26 27 28 00 81 00 0e 9e 41 c0 1d 08 02 01 49 04 11 22 33 40 50 60 19 cd d7 08 17 16 18 05 f4 c0 de ad 05 3e 78 6e 
-
-result (ATTACH ACCEPT (P-TMSI 1)) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 15
-    RAID patched              (SGSN): 5
-    TLLI patched              (BSS ): 16
-    TLLI patched              (SGSN): 16
-    P-TMSI patched            (SGSN): 3
-    Attach Request count            : 3
-    Attach Accept count             : 3
-    Attach Completed count          : 2
-    TLLI cache size                 : 3
-    TLLI-Cache: 3
-      TLLI 8000feed/c0dead05 -> 78dead04/efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 c0 de ad 05 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 2d 08 03 43 50 ea 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 c0 de ad 05 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 2d 08 03 43 50 ea 
-
-NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 08 01 c0 2d 08 03 43 50 ea 
-
-result (ATTACH COMPLETE) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 16
-    RAID patched              (SGSN): 5
-    TLLI patched              (BSS ): 17
-    TLLI patched              (SGSN): 16
-    P-TMSI patched            (SGSN): 3
-    Attach Request count            : 3
-    Attach Accept count             : 3
-    Attach Completed count          : 3
-    TLLI cache size                 : 3
-    TLLI-Cache: 3
-      TLLI 8000feed/c0dead05 -> 78dead04/efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-PROCESSING GMM INFO from 0x15161718:32001
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 26 27 28 00 81 00 0e 88 41 c0 21 08 21 ca 60 90 
-
-CALLBACK, event 0, msg length 66, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 26 27 28 00 81 00 0e 88 41 c0 21 08 21 ca 60 90 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 70
-00 00 10 02 00 c0 de ad 05 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 26 27 28 00 81 00 0e 88 41 c0 21 08 21 ca 60 90 
-
-result (GMM INFO) = 70
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 16
-    RAID patched              (SGSN): 5
-    TLLI patched              (BSS ): 17
-    TLLI patched              (SGSN): 17
-    P-TMSI patched            (SGSN): 3
-    Attach Request count            : 3
-    Attach Accept count             : 3
-    Attach Completed count          : 3
-    TLLI cache size                 : 3
-    TLLI-Cache: 3
-      TLLI c0dead05 -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
---- Shutdown GPRS connection (SGSN 1) ---
-
-PROCESSING DETACH REQ from 0x01020304:1111
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 31 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 57 e6 15 
-
-CALLBACK, event 0, msg length 44, bvci 0x1002
-00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 31 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 57 e6 15 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 48
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 15 01 c0 31 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 57 e6 15 
-
-result (DETACH REQ) = 48
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 17
-    RAID patched              (SGSN): 5
-    TLLI patched              (BSS ): 18
-    TLLI patched              (SGSN): 17
-    P-TMSI patched            (SGSN): 3
-    Attach Request count            : 3
-    Attach Accept count             : 3
-    Attach Completed count          : 3
-    Detach Request count            : 1
-    TLLI cache size                 : 3
-    TLLI-Cache: 3
-      TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256
-      TLLI c0dead05 -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-PROCESSING DETACH ACC from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 25 08 06 00 4d 09 cd 
-
-CALLBACK, event 0, msg length 67, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 25 08 06 00 4d 09 cd 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 71
-00 00 10 02 00 c0 de ad 01 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 25 08 06 00 4d 09 cd 
-
-result (DETACH ACC) = 71
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 17
-    RAID patched              (SGSN): 5
-    TLLI patched              (BSS ): 18
-    TLLI patched              (SGSN): 18
-    P-TMSI patched            (SGSN): 3
-    Attach Request count            : 3
-    Attach Accept count             : 3
-    Attach Completed count          : 3
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI c0dead05 -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
---- Shutdown GPRS connection (SGSN 2) ---
-
-PROCESSING DETACH REQ from 0x01020304:1111
-00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 35 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 83 cb f7 
-
-CALLBACK, event 0, msg length 44, bvci 0x1002
-00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 35 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 83 cb f7 
-
-NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg)
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 48
-00 00 10 02 01 e0 98 76 54 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 15 01 c0 35 08 05 01 18 05 f4 e0 98 76 54 19 03 b9 97 cb b4 31 31 
-
-result (DETACH REQ) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 18
-    RAID patched              (SGSN): 5
-    TLLI patched              (BSS ): 19
-    TLLI patched              (SGSN): 18
-    P-TMSI patched            (BSS ): 1
-    P-TMSI patched            (SGSN): 3
-    Attach Request count            : 3
-    Attach Accept count             : 3
-    Attach Completed count          : 3
-    Detach Request count            : 2
-    Detach Accept count             : 1
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258
-      TLLI c0dead05 -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258
-PROCESSING DETACH ACC from 0x15161718:32001
-00 00 10 02 00 e0 98 76 54 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 89 41 c0 29 08 06 00 be c3 6f 
-
-CALLBACK, event 0, msg length 67, bvci 0x1002
-00 00 10 02 00 e0 98 76 54 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 89 41 c0 29 08 06 00 be c3 6f 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 71
-00 00 10 02 00 c0 de ad 03 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 16 17 18 00 81 00 0e 89 41 c0 29 08 06 00 be c3 6f 
-
-result (DETACH ACC) = 71
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 18
-    RAID patched              (SGSN): 5
-    TLLI patched              (BSS ): 19
-    TLLI patched              (SGSN): 19
-    P-TMSI patched            (BSS ): 1
-    P-TMSI patched            (SGSN): 3
-    Attach Request count            : 3
-    Attach Accept count             : 3
-    Attach Completed count          : 3
-    Detach Request count            : 2
-    Detach Accept count             : 2
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead05 -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258
---- Shutdown GPRS connection (SGSN 2, P-TMSI 1) ---
-
-PROCESSING DETACH REQ from 0x01020304:1111
-00 00 10 02 01 c0 de ad 05 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 39 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 44 b6 8a 
-
-CALLBACK, event 0, msg length 44, bvci 0x1002
-00 00 10 02 01 c0 de ad 05 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 39 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 44 b6 8a 
-
-NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg)
-MESSAGE to SGSN 2 at 0x15161718:32001, msg length 48
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 15 01 c0 39 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 44 b6 8a 
-
-result (DETACH REQ) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 19
-    RAID patched              (SGSN): 5
-    TLLI patched              (BSS ): 20
-    TLLI patched              (SGSN): 19
-    P-TMSI patched            (BSS ): 1
-    P-TMSI patched            (SGSN): 3
-    Attach Request count            : 3
-    Attach Accept count             : 3
-    Attach Completed count          : 3
-    Detach Request count            : 3
-    Detach Accept count             : 2
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI c0dead05 -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258
-PROCESSING DETACH ACC from 0x15161718:32001
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 26 27 28 00 81 00 0e 89 41 c0 2d 08 06 00 86 7c c7 
-
-CALLBACK, event 0, msg length 67, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 26 27 28 00 81 00 0e 89 41 c0 2d 08 06 00 86 7c c7 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 71
-00 00 10 02 00 c0 de ad 05 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 99 99 99 26 27 28 00 81 00 0e 89 41 c0 2d 08 06 00 86 7c c7 
-
-result (DETACH ACC) = 71
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    RAID patched              (BSS ): 19
-    RAID patched              (SGSN): 5
-    TLLI patched              (BSS ): 20
-    TLLI patched              (SGSN): 20
-    P-TMSI patched            (BSS ): 1
-    P-TMSI patched            (SGSN): 3
-    Attach Request count            : 3
-    Attach Accept count             : 3
-    Attach Completed count          : 3
-    Detach Request count            : 3
-    Detach Accept count             : 3
-    TLLI-Cache: 0
-Gbproxy global:
-    Invalid BVC Identifier          : 1
-    BSSGP protocol error      (SGSN): 2
-    Patch error: no peer            : 1
-=== test_gbproxy_keep_info ===
---- Initialise SGSN ---
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 12
-02 00 81 01 01 82 01 01 04 82 01 00 
-
-PROCESSING RESET_ACK from 0x05060708:32000
-03 01 82 01 01 04 82 01 00 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0a 
-
-result (RESET_ACK) = 1
-
-PROCESSING ALIVE_ACK from 0x05060708:32000
-0b 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-06 
-
-result (ALIVE_ACK) = 1
-
-PROCESSING UNBLOCK_ACK from 0x05060708:32000
-07 
-
-==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000
-
-result (UNBLOCK_ACK) = 0
-
-PROCESSING ALIVE from 0x05060708:32000
-0a 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0b 
-
-result (ALIVE) = 1
-
---- Initialise BSS 1 ---
-
-Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096)
-
-PROCESSING RESET from 0x01020304:1111
-02 00 81 01 01 82 10 01 04 82 10 00 
-
-==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-03 01 82 10 01 04 82 10 00 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:1111
-0a 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:1111
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:1111
-0b 
-
-result (ALIVE_ACK) = 0
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 10 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 10 02 
-
-result (BVC_RESET_ACK) = 9
-
-Current NS-VCIs:
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Gbproxy global:
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
---- Send message from BSS 1 to SGSN, BVCI 0x1002 ---
-
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 15 01 b7 f8 36 
-
-result (ATTACH REQUEST) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-result (IDENT RESPONSE) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI 12131415161718, AGE 0
-PROCESSING IDENT REQUEST from 0x05060708:32000
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-CALLBACK, event 0, msg length 23, bvci 0x1002
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 27
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-result (IDENT REQUEST) = 27
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI 12131415161718, AGE 0
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 09 08 16 08 11 12 13 14 15 16 17 18 ba 14 c3 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 09 08 16 08 11 12 13 14 15 16 17 18 ba 14 c3 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 44
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 09 08 16 08 11 12 13 14 15 16 17 18 ba 14 c3 
-
-result (IDENT RESPONSE) = 44
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 0d 08 03 55 1c ea 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 0d 08 03 55 1c ea 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 0d 08 03 55 1c ea 
-
-result (ATTACH COMPLETE) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING GMM INFO from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-CALLBACK, event 0, msg length 66, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 70
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d 
-
-result (GMM INFO) = 70
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH REQ from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 11 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 6d b1 de 
-
-CALLBACK, event 0, msg length 44, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 11 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 6d b1 de 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 48
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 11 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 6d b1 de 
-
-result (DETACH REQ) = 48
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    Detach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH ACC from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 0d 08 06 00 aa ab ee 
-
-CALLBACK, event 0, msg length 67, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 0d 08 06 00 aa ab ee 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 71
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 0d 08 06 00 aa ab ee 
-
-result (DETACH ACC) = 71
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 00000000, IMSI 12131415161718, AGE 0, DE-REGISTERED
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 15 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 e6 71 c7 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 15 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 e6 71 c7 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 15 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 e6 71 c7 
-
-result (ATTACH REQUEST) = 79
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 2
-    Attach Accept count             : 1
-    Attach Completed count          : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 11 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 3a 6d d4 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 11 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 3a 6d d4 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 11 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 3a 6d d4 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 2
-    Attach Accept count             : 2
-    Attach Completed count          : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 19 08 03 32 f1 bc 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 19 08 03 32 f1 bc 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 19 08 03 32 f1 bc 
-
-result (ATTACH COMPLETE) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 2
-    Attach Accept count             : 2
-    Attach Completed count          : 2
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH REQ (re-attach) from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 15 08 05 01 25 0a 67 0e 96 
-
-CALLBACK, event 0, msg length 69, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 15 08 05 01 25 0a 67 0e 96 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 69 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 73
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 15 08 05 01 25 0a 67 0e 96 
-
-result (DETACH REQ (re-attach)) = 73
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 2
-    Attach Accept count             : 2
-    Attach Completed count          : 2
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH ACC from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 1d 08 06 3d 1c 8b 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 1d 08 06 3d 1c 8b 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 1d 08 06 3d 1c 8b 
-
-result (DETACH ACC) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 2
-    Attach Accept count             : 2
-    Attach Completed count          : 2
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 00000000, IMSI 12131415161718, AGE 0, DE-REGISTERED
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 21 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 44 db cc 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 21 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 44 db cc 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 21 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 44 db cc 
-
-result (ATTACH REQUEST) = 79
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 3
-    Attach Accept count             : 2
-    Attach Completed count          : 2
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 19 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 27 3c 84 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 19 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 27 3c 84 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 19 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 27 3c 84 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 3
-    Attach Accept count             : 3
-    Attach Completed count          : 2
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 25 08 03 9b c6 47 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 25 08 03 9b c6 47 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 25 08 03 9b c6 47 
-
-result (ATTACH COMPLETE) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 3
-    Attach Accept count             : 3
-    Attach Completed count          : 3
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH REQ from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 1d 08 05 02 25 0a dd 56 6c 
-
-CALLBACK, event 0, msg length 69, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 1d 08 05 02 25 0a dd 56 6c 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 69 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 73
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 1d 08 05 02 25 0a dd 56 6c 
-
-result (DETACH REQ) = 73
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 3
-    Attach Accept count             : 3
-    Attach Completed count          : 3
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH ACC from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 29 08 06 4c bd dd 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 29 08 06 4c bd dd 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 29 08 06 4c bd dd 
-
-result (DETACH ACC) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 3
-    Attach Accept count             : 3
-    Attach Completed count          : 3
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 00000000, IMSI 12131415161718, AGE 0, DE-REGISTERED
-PROCESSING ATTACH REQUEST (IMSI) from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 37 01 c0 2d 08 01 02 f5 e0 21 08 02 08 11 12 13 14 15 16 17 18 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 a5 85 76 
-
-CALLBACK, event 0, msg length 78, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 37 01 c0 2d 08 01 02 f5 e0 21 08 02 08 11 12 13 14 15 16 17 18 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 a5 85 76 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 78 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 82
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 37 01 c0 2d 08 01 02 f5 e0 21 08 02 08 11 12 13 14 15 16 17 18 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 a5 85 76 
-
-result (ATTACH REQUEST (IMSI)) = 82
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 4
-    Attach Accept count             : 3
-    Attach Completed count          : 3
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 21 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 cf 80 6e 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 21 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 cf 80 6e 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 21 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 cf 80 6e 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 4
-    Attach Accept count             : 4
-    Attach Completed count          : 3
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 31 08 03 fc 2b 11 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 31 08 03 fc 2b 11 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 31 08 03 fc 2b 11 
-
-result (ATTACH COMPLETE) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 4
-    Attach Accept count             : 4
-    Attach Completed count          : 4
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH REQ from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 25 08 05 02 25 0a 8e ee 85 
-
-CALLBACK, event 0, msg length 69, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 25 08 05 02 25 0a 8e ee 85 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 69 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 73
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 25 08 05 02 25 0a 8e ee 85 
-
-result (DETACH REQ) = 73
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 4
-    Attach Accept count             : 4
-    Attach Completed count          : 4
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH ACC from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 35 08 06 f3 c6 26 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 35 08 06 f3 c6 26 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 35 08 06 f3 c6 26 
-
-result (DETACH ACC) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 4
-    Attach Accept count             : 4
-    Attach Completed count          : 4
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 00000000, IMSI 12131415161718, AGE 0, DE-REGISTERED
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 39 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 e4 85 12 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 39 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 e4 85 12 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 39 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 e4 85 12 
-
-result (ATTACH REQUEST) = 79
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 5
-    Attach Accept count             : 4
-    Attach Completed count          : 4
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 29 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 d2 d1 3e 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 29 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 d2 d1 3e 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 29 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 d2 d1 3e 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 5
-    Attach Accept count             : 5
-    Attach Completed count          : 4
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 3d 08 03 48 76 ea 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 3d 08 03 48 76 ea 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 3d 08 03 48 76 ea 
-
-result (ATTACH COMPLETE) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 5
-    Attach Accept count             : 5
-    Attach Completed count          : 5
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING RA UPD REQ from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 41 08 08 10 11 22 33 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 30 73 32 
-
-CALLBACK, event 0, msg length 85, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 41 08 08 10 11 22 33 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 30 73 32 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 85 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 89
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 41 08 08 10 11 22 33 40 50 60 1d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 30 73 32 
-
-result (RA UPD REQ) = 89
-
-PROCESSING RA UDP REJ from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8a 41 c0 2d 08 0b 0a 00 41 30 a7 
-
-CALLBACK, event 0, msg length 68, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8a 41 c0 2d 08 0b 0a 00 41 30 a7 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 68 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 72
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8a 41 c0 2d 08 0b 0a 00 41 30 a7 
-
-result (RA UDP REJ) = 72
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 5
-    Attach Accept count             : 5
-    Attach Completed count          : 5
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 00000000, IMSI 12131415161718, AGE 0, DE-REGISTERED
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 45 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 50 cc c3 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 45 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 50 cc c3 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 15 01 b7 f8 36 
-
-result (ATTACH REQUEST) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 6
-    Attach Accept count             : 5
-    Attach Completed count          : 5
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 2
-    TLLI-Cache: 2
-      TLLI afe2b700 -> afe2b700, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress
-      TLLI 00000000, IMSI 12131415161718, AGE 0, DE-REGISTERED
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 49 08 16 08 11 12 13 14 15 16 17 18 86 ca 3f 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 49 08 16 08 11 12 13 14 15 16 17 18 86 ca 3f 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 45 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 50 cc c3 
-
-result (IDENT RESPONSE) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 6
-    Attach Accept count             : 5
-    Attach Completed count          : 5
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 31 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 f5 22 ce 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 31 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 f5 22 ce 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 31 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 f5 22 ce 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 6
-    Attach Accept count             : 6
-    Attach Completed count          : 5
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 4d 08 03 79 84 ea 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 4d 08 03 79 84 ea 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 4d 08 03 79 84 ea 
-
-result (ATTACH COMPLETE) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 6
-    Attach Accept count             : 6
-    Attach Completed count          : 6
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH REQ from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 35 08 05 02 25 0a 9b fa 57 
-
-CALLBACK, event 0, msg length 69, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 35 08 05 02 25 0a 9b fa 57 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 69 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 73
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 35 08 05 02 25 0a 9b fa 57 
-
-result (DETACH REQ) = 73
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 6
-    Attach Accept count             : 6
-    Attach Completed count          : 6
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH ACC from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 51 08 06 a5 d9 70 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 51 08 06 a5 d9 70 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 51 08 06 a5 d9 70 
-
-result (DETACH ACC) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 6
-    Attach Accept count             : 6
-    Attach Completed count          : 6
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 00000000, IMSI 12131415161718, AGE 0, DE-REGISTERED
-PROCESSING ATTACH REQUEST (local TLLI) from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 55 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 f9 cc e9 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 55 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 f9 cc e9 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 55 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 f9 cc e9 
-
-result (ATTACH REQUEST (local TLLI)) = 79
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 7
-    Attach Accept count             : 6
-    Attach Completed count          : 6
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 39 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 e8 73 9e 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 39 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 e8 73 9e 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 39 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 e8 73 9e 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 7
-    Attach Accept count             : 7
-    Attach Completed count          : 6
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 59 08 03 1e 69 bc 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 59 08 03 1e 69 bc 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 59 08 03 1e 69 bc 
-
-result (ATTACH COMPLETE) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 7
-    Attach Accept count             : 7
-    Attach Completed count          : 7
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH REQ (re-attach) from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 3d 08 05 01 25 0a 21 a2 ad 
-
-CALLBACK, event 0, msg length 69, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 3d 08 05 01 25 0a 21 a2 ad 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 69 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 73
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 3d 08 05 01 25 0a 21 a2 ad 
-
-result (DETACH REQ (re-attach)) = 73
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 7
-    Attach Accept count             : 7
-    Attach Completed count          : 7
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH ACC from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 5d 08 06 11 84 8b 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 5d 08 06 11 84 8b 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 5d 08 06 11 84 8b 
-
-result (DETACH ACC) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 7
-    Attach Accept count             : 7
-    Attach Completed count          : 7
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 00000000, IMSI 12131415161718, AGE 0, DE-REGISTERED
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 61 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 5b 66 e2 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 61 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 5b 66 e2 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 61 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 5b 66 e2 
-
-result (ATTACH REQUEST) = 79
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 8
-    Attach Accept count             : 7
-    Attach Completed count          : 7
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 41 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 9e 50 40 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 41 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 9e 50 40 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 41 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 9e 50 40 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 8
-    Attach Accept count             : 8
-    Attach Completed count          : 7
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 65 08 03 b7 5e 47 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 65 08 03 b7 5e 47 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 65 08 03 b7 5e 47 
-
-result (ATTACH COMPLETE) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 8
-    Attach Accept count             : 8
-    Attach Completed count          : 8
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING GMM INFO from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 45 08 21 9c 7f c6 
-
-CALLBACK, event 0, msg length 66, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 45 08 21 9c 7f c6 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 70
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 45 08 21 9c 7f c6 
-
-result (GMM INFO) = 70
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 8
-    Attach Accept count             : 8
-    Attach Completed count          : 8
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH REQUEST (unexpected, IMSI) from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 37 01 c0 69 08 01 02 f5 e0 21 08 02 08 11 12 13 14 15 16 17 18 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 e1 11 8e 
-
-CALLBACK, event 0, msg length 78, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 37 01 c0 69 08 01 02 f5 e0 21 08 02 08 11 12 13 14 15 16 17 18 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 e1 11 8e 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 78 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 82
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 37 01 c0 69 08 01 02 f5 e0 21 08 02 08 11 12 13 14 15 16 17 18 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 e1 11 8e 
-
-result (ATTACH REQUEST (unexpected, IMSI)) = 82
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 9
-    Attach Accept count             : 8
-    Attach Completed count          : 8
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 49 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 83 01 10 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 49 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 83 01 10 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 49 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 83 01 10 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 9
-    Attach Accept count             : 9
-    Attach Completed count          : 8
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 6d 08 03 6f c8 ea 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 6d 08 03 6f c8 ea 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 6d 08 03 6f c8 ea 
-
-result (ATTACH COMPLETE) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 9
-    Attach Accept count             : 9
-    Attach Completed count          : 9
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH REQ from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 4d 08 05 02 25 0a 51 0e 1b 
-
-CALLBACK, event 0, msg length 69, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 4d 08 05 02 25 0a 51 0e 1b 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 69 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 73
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 4d 08 05 02 25 0a 51 0e 1b 
-
-result (DETACH REQ) = 73
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 9
-    Attach Accept count             : 9
-    Attach Completed count          : 9
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH ACC from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 71 08 06 b3 95 70 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 71 08 06 b3 95 70 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 71 08 06 b3 95 70 
-
-result (DETACH ACC) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 9
-    Attach Accept count             : 9
-    Attach Completed count          : 9
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 00000000, IMSI 12131415161718, AGE 0, DE-REGISTERED
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 75 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 ab 17 53 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 75 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 ab 17 53 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 75 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 ab 17 53 
-
-result (ATTACH REQUEST) = 79
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 10
-    Attach Accept count             : 9
-    Attach Completed count          : 9
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 51 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 a4 f2 e0 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 51 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 a4 f2 e0 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 51 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 a4 f2 e0 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 10
-    Attach Accept count             : 10
-    Attach Completed count          : 9
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 79 08 03 08 25 bc 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 79 08 03 08 25 bc 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 79 08 03 08 25 bc 
-
-result (ATTACH COMPLETE) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 10
-    Attach Accept count             : 10
-    Attach Completed count          : 10
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING GMM INFO from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 55 08 21 97 59 c6 
-
-CALLBACK, event 0, msg length 66, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 55 08 21 97 59 c6 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 70
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 55 08 21 97 59 c6 
-
-result (GMM INFO) = 70
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 10
-    Attach Accept count             : 10
-    Attach Completed count          : 10
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH REQUEST (unexpected) from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 7d 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 a2 24 d0 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 7d 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 a2 24 d0 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 7d 08 01 02 f5 e0 21 08 02 05 f4 ef e2 b7 00 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 a2 24 d0 
-
-result (ATTACH REQUEST (unexpected)) = 79
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 11
-    Attach Accept count             : 10
-    Attach Completed count          : 10
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH ACCEPT from 0x05060708:32000
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 59 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 b9 a3 b0 
-
-CALLBACK, event 0, msg length 88, bvci 0x1002
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 59 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 b9 a3 b0 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 92
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 59 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 b9 a3 b0 
-
-result (ATTACH ACCEPT) = 92
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 11
-    Attach Accept count             : 11
-    Attach Completed count          : 10
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH COMPLETE from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 81 08 03 b9 71 10 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 81 08 03 b9 71 10 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 81 08 03 b9 71 10 
-
-result (ATTACH COMPLETE) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 11
-    Attach Accept count             : 11
-    Attach Completed count          : 11
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700/efe2b700 -> afe2b700/efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH REQ from 0x05060708:32000
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 5d 08 05 02 25 0a 44 1a c9 
-
-CALLBACK, event 0, msg length 69, bvci 0x1002
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 5d 08 05 02 25 0a 44 1a c9 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 69 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 73
-00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 5d 08 05 02 25 0a 44 1a c9 
-
-result (DETACH REQ) = 73
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 11
-    Attach Accept count             : 11
-    Attach Completed count          : 11
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
-PROCESSING DETACH ACC from 0x01020304:1111
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 85 08 06 b6 9c 27 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 85 08 06 b6 9c 27 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 85 08 06 b6 9c 27 
-
-result (DETACH ACC) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 11
-    Attach Accept count             : 11
-    Attach Completed count          : 11
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 00000000, IMSI 12131415161718, AGE 0, DE-REGISTERED
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 89 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 21 24 df 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 89 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 21 24 df 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 15 01 b7 f8 36 
-
-result (ATTACH REQUEST) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 12
-    Attach Accept count             : 11
-    Attach Completed count          : 11
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 8d 08 16 08 11 12 13 14 15 16 17 18 74 ac 38 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 8d 08 16 08 11 12 13 14 15 16 17 18 74 ac 38 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 89 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 21 24 df 
-
-result (IDENT RESPONSE) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 12
-    Attach Accept count             : 11
-    Attach Completed count          : 11
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI 12131415161718, AGE 0
-PROCESSING ATTACH REJECT from 0x05060708:32000
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 61 08 04 07 79 ba a5 
-
-CALLBACK, event 0, msg length 67, bvci 0x1002
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 61 08 04 07 79 ba a5 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 71
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 61 08 04 07 79 ba a5 
-
-result (ATTACH REJECT) = 71
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 12
-    Attach Reject count             : 1
-    Attach Accept count             : 11
-    Attach Completed count          : 11
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 00000000, IMSI 12131415161718, AGE 0, DE-REGISTERED
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 91 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 81 7a 01 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 91 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 81 7a 01 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 15 01 b7 f8 36 
-
-result (ATTACH REQUEST) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 13
-    Attach Reject count             : 1
-    Attach Accept count             : 11
-    Attach Completed count          : 11
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 1
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress
-PROCESSING DETACH REQ (MO) from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 95 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 9c dc fc 
-
-CALLBACK, event 0, msg length 44, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 95 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 9c dc fc 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 0e 00 09 41 c4 05 08 06 00 29 4a 68 
-
-result (DETACH REQ (MO)) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 13
-    Attach Reject count             : 1
-    Attach Accept count             : 11
-    Attach Completed count          : 11
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 2
-    Detach Accept count             : 1
-    TLLI-Cache: 0
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 99 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 88 49 82 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 99 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 88 49 82 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 15 01 b7 f8 36 
-
-result (ATTACH REQUEST) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 14
-    Attach Reject count             : 1
-    Attach Accept count             : 11
-    Attach Completed count          : 11
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 2
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress
-PROCESSING DETACH REQ (MT) from 0x05060708:32000
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 65 08 05 02 25 0a 17 a2 20 
-
-CALLBACK, event 0, msg length 69, bvci 0x1002
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 65 08 05 02 25 0a 17 a2 20 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 69 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 73
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8b 41 c0 65 08 05 02 25 0a 17 a2 20 
-
-result (DETACH REQ (MT)) = 73
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 14
-    Attach Reject count             : 1
-    Attach Accept count             : 11
-    Attach Completed count          : 11
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 2
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI afe2b700 -> afe2b700, IMSI 12131415161718, AGE 0, STORED 1, IMSI acquisition in progress
-PROCESSING DETACH ACC from 0x01020304:1111
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 9d 08 06 65 2c 8a 
-
-CALLBACK, event 0, msg length 31, bvci 0x1002
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 9d 08 06 65 2c 8a 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 34 01 c0 99 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 88 49 82 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 35
-00 00 10 02 01 af e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 9d 08 06 65 2c 8a 
-
-result (DETACH ACC) = 35
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 14
-    Attach Reject count             : 1
-    Attach Accept count             : 11
-    Attach Completed count          : 11
-    RoutingArea Update Request count: 1
-    RoutingArea Update Reject count : 1
-    Detach Request count            : 2
-    Detach Accept count             : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 00000000, IMSI 12131415161718, AGE 0, DE-REGISTERED
-Gbproxy global:
-Test TLLI info expiry
-
-Test TLLI replacement:
-  Add TLLI 1, IMSI 1
-  Add TLLI 2, IMSI 1 (should replace TLLI 1)
-  Peers:
-    NSEI 0, BVCI 20, not blocked, RAI 0-0-0-0
-      TLLI cache size                 : 1
-      TLLI-Cache: 1
-        TLLI c000162e, IMSI 03242526, AGE 0, IMSI matches
-
-Test IMSI replacement:
-  Add TLLI 1, IMSI 1
-  Add TLLI 1, IMSI 2 (should replace IMSI 1)
-  Peers:
-    NSEI 0, BVCI 20, not blocked, RAI 0-0-0-0
-      TLLI cache size                 : 1
-      TLLI-Cache: 1
-        TLLI c00004d2, IMSI 06272829, AGE 0, IMSI matches
-
-Test TLLI expiry, max_len == 1:
-  Add TLLI 1, IMSI 1
-  Add TLLI 2, IMSI 2 (should replace IMSI 1)
-  Peers:
-    NSEI 0, BVCI 20, not blocked, RAI 0-0-0-0
-      TLLI cache size                 : 1
-      TLLI-Cache: 1
-        TLLI c000162e, IMSI 06272829, AGE 0, IMSI matches
-
-Test TLLI expiry, max_age == 1:
-  Add TLLI 1, IMSI 1 (should expire after timeout)
-  Add TLLI 2, IMSI 2 (should not expire after timeout)
-  Peers:
-    NSEI 0, BVCI 20, not blocked, RAI 0-0-0-0
-      TLLI cache size                 : 1
-      TLLI-Cache: 1
-        TLLI c000162e, IMSI 06272829, AGE 1, IMSI matches
-
-Test TLLI expiry, max_len == 2, max_age == 1:
-  Add TLLI 1, IMSI 1 (should expire)
-  Add TLLI 2, IMSI 2 (should expire after timeout)
-  Add TLLI 3, IMSI 3 (should not expire after timeout)
-  Peers:
-    NSEI 0, BVCI 20, not blocked, RAI 0-0-0-0
-      TLLI cache size                 : 3
-      TLLI-Cache: 3
-        TLLI c0000d80, IMSI 12345678, AGE 0, IMSI matches
-        TLLI c000162e, IMSI 06272829, AGE 1, IMSI matches
-        TLLI c00004d2, IMSI 03242526, AGE 2, IMSI matches
-  Remove stale TLLIs
-  Peers:
-    NSEI 0, BVCI 20, not blocked, RAI 0-0-0-0
-      TLLI cache size                 : 1
-      TLLI-Cache: 1
-        TLLI c0000d80, IMSI 12345678, AGE 0, IMSI matches
-
-=== test_gbproxy_stored_messages ===
---- Initialise SGSN ---
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 12
-02 00 81 01 01 82 01 01 04 82 01 00 
-
-PROCESSING RESET_ACK from 0x05060708:32000
-03 01 82 01 01 04 82 01 00 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0a 
-
-result (RESET_ACK) = 1
-
-PROCESSING ALIVE_ACK from 0x05060708:32000
-0b 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-06 
-
-result (ALIVE_ACK) = 1
-
-PROCESSING UNBLOCK_ACK from 0x05060708:32000
-07 
-
-==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000
-
-result (UNBLOCK_ACK) = 0
-
-PROCESSING ALIVE from 0x05060708:32000
-0a 
-
-MESSAGE to SGSN at 0x05060708:32000, msg length 1
-0b 
-
-result (ALIVE) = 1
-
---- Initialise BSS 1 ---
-
-Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096)
-
-PROCESSING RESET from 0x01020304:1111
-02 00 81 01 01 82 10 01 04 82 10 00 
-
-==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-03 01 82 10 01 04 82 10 00 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0a 
-
-result (RESET) = 9
-
-PROCESSING ALIVE from 0x01020304:1111
-0a 
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-0b 
-
-result (ALIVE) = 1
-
-PROCESSING UNBLOCK from 0x01020304:1111
-06 
-
-==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111
-
-MESSAGE to BSS at 0x01020304:1111, msg length 1
-07 
-
-result (UNBLOCK) = 1
-
-PROCESSING ALIVE_ACK from 0x01020304:1111
-0b 
-
-result (ALIVE_ACK) = 0
-
-Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098)
-
-PROCESSING BVC_RESET from 0x01020304:1111
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-CALLBACK, event 0, msg length 18, bvci 0x0000
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 22
-00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 
-
-result (BVC_RESET) = 22
-
-PROCESSING BVC_RESET_ACK from 0x05060708:32000
-00 00 00 00 23 04 82 10 02 
-
-CALLBACK, event 0, msg length 5, bvci 0x0000
-00 00 00 00 23 04 82 10 02 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 9
-00 00 00 00 23 04 82 10 02 
-
-result (BVC_RESET_ACK) = 9
-
-Current NS-VCIs:
-    VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111
-    VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
-         NS-VC Block count         : 1
-
-Gbproxy global:
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    TLLI-Cache: 0
---- Establish first LLC connection ---
-
-PROCESSING ATTACH REQUEST from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-CALLBACK, event 0, msg length 75, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 15 01 b7 f8 36 
-
-result (ATTACH REQUEST) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 8000dead, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress
-PROCESSING IDENT REQUEST from 0x05060708:32000
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-CALLBACK, event 0, msg length 23, bvci 0x1002
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg)
-MESSAGE to BSS at 0x01020304:1111, msg length 27
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba 
-
-result (IDENT REQUEST) = 27
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 8000dead, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress
-PROCESSING DETACH ACCEPT from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 09 01 c0 05 08 06 00 f8 92 41 
-
-CALLBACK, event 0, msg length 32, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 09 01 c0 05 08 06 00 f8 92 41 
-
-result (DETACH ACCEPT) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    TLLI cache size                 : 1
-    TLLI-Cache: 1
-      TLLI 8000dead -> 8000dead, IMSI (none), AGE 0, STORED 2, IMSI acquisition in progress
-PROCESSING IDENT RESPONSE from 0x01020304:1111
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 09 08 16 08 11 12 13 14 15 16 17 18 ba 14 c3 
-
-CALLBACK, event 0, msg length 40, bvci 0x1002
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 09 08 16 08 11 12 13 14 15 16 17 18 ba 14 c3 
-
-NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
-MESSAGE to SGSN at 0x05060708:32000, msg length 79
-00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01 
-
-result (IDENT RESPONSE) = 0
-
-Peers:
-  NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
-    Attach Request count            : 1
-    TLLI-Cache: 0
-Gbproxy global:
-===== GbProxy test END
-
diff --git a/tests/gprs/Makefile.am b/tests/gprs/Makefile.am
deleted file mode 100644
index 902313f..0000000
--- a/tests/gprs/Makefile.am
+++ /dev/null
@@ -1,10 +0,0 @@
-AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
-AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOABIS_CFLAGS)
-
-EXTRA_DIST = gprs_test.ok
-
-noinst_PROGRAMS = gprs_test
-
-gprs_test_SOURCES = gprs_test.c $(top_srcdir)/src/gprs/gprs_utils.c
-
-gprs_test_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS)
diff --git a/tests/gprs/gprs_test.c b/tests/gprs/gprs_test.c
deleted file mode 100644
index aac9bb8..0000000
--- a/tests/gprs/gprs_test.c
+++ /dev/null
@@ -1,140 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-
-#include <openbsc/gprs_llc.h>
-#include <openbsc/gprs_utils.h>
-
-#include <openbsc/debug.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/gsm/gsup.h>
-
-#define ASSERT_FALSE(x) if (x)  { printf("Should have returned false.\n"); abort(); }
-#define ASSERT_TRUE(x)  if (!x) { printf("Should have returned true.\n"); abort(); }
-
-/**
- * GSM 04.64 8.4.2 Receipt of unacknowledged information
- */
-static int nu_is_retransmission(uint16_t nu, uint16_t vur)
-{
-	int ret = gprs_llc_is_retransmit(nu, vur);
-	printf("N(U) = %d, V(UR) = %d => %s\n", nu, vur,
-	       ret == 1 ? "retransmit" : "new");
-	return ret;
-}
-
-static void test_8_4_2()
-{
-	printf("Testing gprs_llc_is_retransmit.\n");
-
-	ASSERT_FALSE(nu_is_retransmission(0, 0));
-	ASSERT_TRUE (nu_is_retransmission(0, 1));
-
-	/* expect 1... check for retransmissions */
-	ASSERT_TRUE (nu_is_retransmission(0, 1));
-	ASSERT_TRUE (nu_is_retransmission(511, 1));
-	ASSERT_TRUE (nu_is_retransmission(483, 1));
-	ASSERT_TRUE (nu_is_retransmission(482, 1));
-	ASSERT_FALSE(nu_is_retransmission(481, 1));
-
-	/* expect 511... check for retransmissions */
-	ASSERT_FALSE(nu_is_retransmission(0, 240)); // ahead
-	ASSERT_FALSE(nu_is_retransmission(0, 511)); // ahead
-	ASSERT_FALSE(nu_is_retransmission(1, 511)); // ahead
-	ASSERT_FALSE(nu_is_retransmission(511, 511)); // same
-	ASSERT_TRUE (nu_is_retransmission(510, 511)); // behind
-	ASSERT_TRUE (nu_is_retransmission(481, 511)); // behind
-	ASSERT_FALSE(nu_is_retransmission(479, 511)); // wrapped
-}
-
-static void test_gprs_timer_enc_dec(void)
-{
-	int i, u, secs, tmr;
-	const int upper_secs_test_limit = 12000;
-	int dec_secs, last_dec_secs = -1;
-
-	printf("Test GPRS timer decoding/encoding\n");
-
-	/* Check gprs_tmr_to_secs with all 256 encoded values */
-	for (u = 0; u <= GPRS_TMR_DEACTIVATED; u += 32) {
-		fprintf(stderr, "Testing decoding with timer value unit %u\n",
-			u / 32);
-		for (i = 0; i < 32; i++) {
-			switch (u) {
-			case GPRS_TMR_2SECONDS:
-				OSMO_ASSERT(gprs_tmr_to_secs(u + i) == 2 * i);
-				break;
-
-			default:
-			case GPRS_TMR_MINUTE:
-				OSMO_ASSERT(gprs_tmr_to_secs(u + i) == 60 * i);
-				break;
-
-			case GPRS_TMR_6MINUTE:
-				OSMO_ASSERT(gprs_tmr_to_secs(u + i) == 360 * i);
-				break;
-
-			case GPRS_TMR_DEACTIVATED:
-				OSMO_ASSERT(gprs_tmr_to_secs(u + i) == -1);
-				break;
-			}
-
-			OSMO_ASSERT(gprs_tmr_to_secs(u + i) < upper_secs_test_limit);
-		}
-	}
-
-	/* Check gprs_secs_to_tmr_floor for secs that can exactly be
-	 * represented as GPRS timer values */
-	for (i = 0; i < GPRS_TMR_DEACTIVATED; i++) {
-		int j;
-		secs = gprs_tmr_to_secs(i);
-		tmr = gprs_secs_to_tmr_floor(secs);
-		OSMO_ASSERT(secs == gprs_tmr_to_secs(tmr));
-
-		/* Check that the highest resolution is used */
-		for (j = 0; j < tmr; j++)
-			OSMO_ASSERT(secs != gprs_tmr_to_secs(j));
-	}
-	OSMO_ASSERT(GPRS_TMR_DEACTIVATED == gprs_secs_to_tmr_floor(-1));
-
-	/* Check properties of gprs_secs_to_tmr_floor */
-	for (secs = 0; secs <= upper_secs_test_limit; secs++) {
-		int tmr = gprs_secs_to_tmr_floor(secs);
-		int delta_secs = gprs_tmr_to_secs((tmr & ~0x1f) | 1);
-		dec_secs = gprs_tmr_to_secs(tmr);
-
-		/* Check floor */
-		OSMO_ASSERT(dec_secs <= secs);
-		/* Check monotonicity */
-		OSMO_ASSERT(dec_secs >= last_dec_secs);
-		/* Check max distance (<= resolution) */
-		OSMO_ASSERT(dec_secs - last_dec_secs <= delta_secs);
-
-		last_dec_secs = dec_secs;
-	}
-}
-
-const struct log_info_cat default_categories[] = {
-	[DGPRS] = {
-		.name = "DGPRS",
-		.description = "GPRS Packet Service",
-		.enabled = 0, .loglevel = LOGL_DEBUG,
-	},
-};
-
-static struct log_info info = {
-	.cat = default_categories,
-	.num_cat = ARRAY_SIZE(default_categories),
-};
-
-int main(int argc, char **argv)
-{
-	osmo_init_logging(&info);
-
-	test_8_4_2();
-	test_gprs_timer_enc_dec();
-
-	printf("Done.\n");
-	return EXIT_SUCCESS;
-}
diff --git a/tests/gprs/gprs_test.ok b/tests/gprs/gprs_test.ok
deleted file mode 100644
index da7888c..0000000
--- a/tests/gprs/gprs_test.ok
+++ /dev/null
@@ -1,17 +0,0 @@
-Testing gprs_llc_is_retransmit.
-N(U) = 0, V(UR) = 0 => new
-N(U) = 0, V(UR) = 1 => retransmit
-N(U) = 0, V(UR) = 1 => retransmit
-N(U) = 511, V(UR) = 1 => retransmit
-N(U) = 483, V(UR) = 1 => retransmit
-N(U) = 482, V(UR) = 1 => retransmit
-N(U) = 481, V(UR) = 1 => new
-N(U) = 0, V(UR) = 240 => new
-N(U) = 0, V(UR) = 511 => new
-N(U) = 1, V(UR) = 511 => new
-N(U) = 511, V(UR) = 511 => new
-N(U) = 510, V(UR) = 511 => retransmit
-N(U) = 481, V(UR) = 511 => retransmit
-N(U) = 479, V(UR) = 511 => new
-Test GPRS timer decoding/encoding
-Done.
diff --git a/tests/gsm0408/Makefile.am b/tests/gsm0408/Makefile.am
deleted file mode 100644
index ae81c2c..0000000
--- a/tests/gsm0408/Makefile.am
+++ /dev/null
@@ -1,34 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	gsm0408_test \
-	$(NULL)
-
-EXTRA_DIST = \
-	gsm0408_test.ok \
-	$(NULL)
-
-gsm0408_test_SOURCES = \
-	gsm0408_test.c \
-	$(NULL)
-
-gsm0408_test_LDADD = \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	-ldbi \
-	$(NULL)
diff --git a/tests/gsm0408/gsm0408_test.c b/tests/gsm0408/gsm0408_test.c
deleted file mode 100644
index fcdc8f8..0000000
--- a/tests/gsm0408/gsm0408_test.c
+++ /dev/null
@@ -1,697 +0,0 @@
-/* simple test for the gsm0408 formatting functions */
-/*
- * (C) 2008 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 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/>.
- *
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <arpa/inet.h>
-
-#include <openbsc/common_bsc.h>
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/gsm_04_11.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/gsm_data_shared.h>
-#include <openbsc/debug.h>
-#include <openbsc/arfcn_range_encode.h>
-#include <openbsc/system_information.h>
-#include <openbsc/abis_rsl.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/gsm/sysinfo.h>
-
-#define COMPARE(result, op, value) \
-    if (!((result) op (value))) {\
-	fprintf(stderr, "Compare failed. Was %x should be %x in %s:%d\n",result, value, __FILE__, __LINE__); \
-	exit(-1); \
-    }
-
-#define COMPARE_STR(result, value) \
-	if (strcmp(result, value) != 0) { \
-		fprintf(stderr, "Compare failed. Was %s should be %s in %s:%d\n",result, value, __FILE__, __LINE__); \
-		exit(-1); \
-	}
-
-#define DBG(...)
-
-#define VERIFY(res, cmp, wanted)					\
-	if (!(res cmp wanted)) {					\
-		printf("ASSERT failed: %s:%d Wanted: %d %s %d\n",	\
-			__FILE__, __LINE__, (int) res, # cmp, (int) wanted);	\
-	}
-
-
-
-/*
- * Test Location Area Identifier formatting. Table 10.5.3 of 04.08
- */
-static void test_location_area_identifier(void)
-{
-    struct gsm48_loc_area_id lai48;
-
-    printf("Testing test location area identifier\n");
-
-    /*
-     * Test the default/test setup. Coming from
-     * bsc_hack.c dumps
-     */
-    gsm48_generate_lai(&lai48, 1, 1, 1);
-    COMPARE(lai48.digits[0], ==, 0x00);
-    COMPARE(lai48.digits[1], ==, 0xF1);
-    COMPARE(lai48.digits[2], ==, 0x10);
-    COMPARE(lai48.lac, ==, htons(0x0001));
-
-    gsm48_generate_lai(&lai48, 602, 1, 15);
-    COMPARE(lai48.digits[0], ==, 0x06);
-    COMPARE(lai48.digits[1], ==, 0xF2);
-    COMPARE(lai48.digits[2], ==, 0x10);
-    COMPARE(lai48.lac, ==, htons(0x000f));
-}
-
-static inline void gen(struct gsm_bts *bts, const char *s)
-{
-	int r;
-
-	bts->si_valid = 0;
-	bts->si_valid |= (1 << SYSINFO_TYPE_2quater);
-
-	printf("generating SI2quater for %zu EARFCNs and %zu UARFCNs...\n",
-	       si2q_earfcn_count(&bts->si_common.si2quater_neigh_list), bts->si_common.uarfcn_length);
-
-	r = gsm_generate_si(bts, SYSINFO_TYPE_2quater);
-	if (r > 0)
-		for (bts->si2q_index = 0; bts->si2q_index < bts->si2q_count + 1; bts->si2q_index++)
-			printf("generated %s SI2quater [%02u/%02u]: [%d] %s\n",
-			       GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2quater) ? "valid" : "invalid",
-			       bts->si2q_index, bts->si2q_count, r,
-			       osmo_hexdump((void *)GSM_BTS_SI2Q(bts, bts->si2q_index), GSM_MACBLOCK_LEN));
-	else
-		printf("%s() failed to generate SI2quater: %s\n", s, strerror(-r));
-}
-
-static inline void del_earfcn_b(struct gsm_bts *bts, uint16_t earfcn)
-{
-	struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list;
-	int r = osmo_earfcn_del(e, earfcn);
-	if (r)
-		printf("failed to remove EARFCN %u: %s\n", earfcn, strerror(-r));
-	else
-		printf("removed EARFCN %u - ", earfcn);
-
-	gen(bts, __func__);
-}
-
-static inline void add_earfcn_b(struct gsm_bts *bts, uint16_t earfcn, uint8_t bw)
-{
-	struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list;
-	int r = osmo_earfcn_add(e, earfcn, bw);
-	if (r)
-		printf("failed to add EARFCN %u: %s\n", earfcn, strerror(-r));
-	else
-		printf("added EARFCN %u - ", earfcn);
-
-	gen(bts, __func__);
-}
-
-static inline void _bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, bool diversity)
-{
-	int r;
-
-	bts->u_offset = 0;
-
-	r = bts_uarfcn_add(bts, arfcn, scramble, diversity);
-	if (r < 0)
-		printf("failed to add UARFCN to SI2quater: %s\n", strerror(-r));
-	else {
-		bts->si2q_count = si2q_num(bts) - 1;
-		gen(bts, __func__);
-	}
-}
-
-static inline void test_si2q_segfault(void)
-{
-	struct gsm_bts *bts;
-	struct gsm_network *network = bsc_network_init(tall_bsc_ctx, 1, 1, NULL);
-	printf("Test SI2quater UARFCN (same scrambling code and diversity):\n");
-
-	if (!network)
-		exit(1);
-	bts = gsm_bts_alloc(network, 0);
-
-	_bts_uarfcn_add(bts, 10564, 319, 0);
-	_bts_uarfcn_add(bts, 10612, 319, 0);
-	gen(bts, __func__);
-}
-
-static inline void test_si2q_mu(void)
-{
-	struct gsm_bts *bts;
-	struct gsm_network *network = bsc_network_init(tall_bsc_ctx, 1, 1, NULL);
-	printf("Test SI2quater multiple UARFCNs:\n");
-
-	if (!network)
-		exit(1);
-	bts = gsm_bts_alloc(network, 0);
-
-	_bts_uarfcn_add(bts, 10564, 318, 0);
-	_bts_uarfcn_add(bts, 10612, 319, 0);
-	_bts_uarfcn_add(bts, 10612, 31, 0);
-	_bts_uarfcn_add(bts, 10612, 19, 0);
-	_bts_uarfcn_add(bts, 10613, 64, 0);
-	_bts_uarfcn_add(bts, 10613, 164, 0);
-	_bts_uarfcn_add(bts, 10613, 14, 0);
-}
-
-static inline void test_si2q_u(void)
-{
-	struct gsm_bts *bts;
-	struct gsm_network *network = bsc_network_init(NULL, 1, 1, NULL);
-	printf("Testing SYSINFO_TYPE_2quater UARFCN generation:\n");
-
-	if (!network)
-		exit(1);
-
-	bts = gsm_bts_alloc(network, 0);
-
-	/* first generate invalid SI as no UARFCN added */
-	gen(bts, __func__);
-
-	/* subsequent calls should produce valid SI if there's enough memory */
-	_bts_uarfcn_add(bts, 1982, 13, 1);
-	_bts_uarfcn_add(bts, 1982, 44, 0);
-	_bts_uarfcn_add(bts, 1982, 61, 1);
-	_bts_uarfcn_add(bts, 1982, 89, 1);
-	_bts_uarfcn_add(bts, 1982, 113, 0);
-	_bts_uarfcn_add(bts, 1982, 123, 0);
-	_bts_uarfcn_add(bts, 1982, 56, 1);
-	_bts_uarfcn_add(bts, 1982, 72, 1);
-	_bts_uarfcn_add(bts, 1982, 223, 1);
-	_bts_uarfcn_add(bts, 1982, 14, 0);
-	_bts_uarfcn_add(bts, 1982, 88, 0);
-}
-
-static inline void test_si2q_e(void)
-{
-	struct gsm_bts *bts;
-	struct gsm_network *network = bsc_network_init(NULL, 1, 1, NULL);
-	printf("Testing SYSINFO_TYPE_2quater EARFCN generation:\n");
-
-	if (!network)
-		exit(1);
-
-	bts = gsm_bts_alloc(network, 0);
-
-	bts->si_common.si2quater_neigh_list.arfcn = bts->si_common.data.earfcn_list;
-	bts->si_common.si2quater_neigh_list.meas_bw = bts->si_common.data.meas_bw_list;
-	bts->si_common.si2quater_neigh_list.length = MAX_EARFCN_LIST;
-	bts->si_common.si2quater_neigh_list.thresh_hi = 5;
-
-	osmo_earfcn_init(&bts->si_common.si2quater_neigh_list);
-
-	/* first generate invalid SI as no EARFCN added */
-	gen(bts, __func__);
-
-	/* subsequent calls should produce valid SI if there's enough memory and EARFCNs */
-	add_earfcn_b(bts, 1917, 5);
-	del_earfcn_b(bts, 1917);
-	add_earfcn_b(bts, 1917, 1);
-	add_earfcn_b(bts, 1932, OSMO_EARFCN_MEAS_INVALID);
-	add_earfcn_b(bts, 1937, 2);
-	add_earfcn_b(bts, 1945, OSMO_EARFCN_MEAS_INVALID);
-	add_earfcn_b(bts, 1965, OSMO_EARFCN_MEAS_INVALID);
-	add_earfcn_b(bts, 1967, 4);
-	add_earfcn_b(bts, 1982, 3);
-}
-
-static inline void test_si2q_long(void)
-{
-	struct gsm_bts *bts;
-	struct gsm_network *network = bsc_network_init(tall_bsc_ctx, 1, 1, NULL);
-	printf("Testing SYSINFO_TYPE_2quater combined EARFCN & UARFCN generation:\n");
-
-	if (!network)
-		exit(1);
-
-	bts = gsm_bts_alloc(network, 0);
-
-	bts->si_common.si2quater_neigh_list.arfcn = bts->si_common.data.earfcn_list;
-	bts->si_common.si2quater_neigh_list.meas_bw = bts->si_common.data.meas_bw_list;
-	bts->si_common.si2quater_neigh_list.length = MAX_EARFCN_LIST;
-	bts->si_common.si2quater_neigh_list.thresh_hi = 5;
-
-	osmo_earfcn_init(&bts->si_common.si2quater_neigh_list);
-
-	bts_earfcn_add(bts, 1922, 11, 22, 8,32, 8);
-	bts_earfcn_add(bts, 1922, 11, 22, 8, 32, 8);
-	bts_earfcn_add(bts, 1924, 11, 12, 6, 11, 5);
-	bts_earfcn_add(bts, 1923, 11, 12, 6, 11, 5);
-	bts_earfcn_add(bts, 1925, 11, 12, 6, 11, 5);
-	bts_earfcn_add(bts, 2111, 11, 12, 6, 11, 5);
-	bts_earfcn_add(bts, 2112, 11, 12, 6, 11, 4);
-	bts_earfcn_add(bts, 2113, 11, 12, 6, 11, 3);
-	bts_earfcn_add(bts, 2114, 11, 12, 6, 11, 2);
-	bts_earfcn_add(bts, 2131, 11, 12, 6, 11, 5);
-	bts_earfcn_add(bts, 2132, 11, 12, 6, 11, 4);
-	bts_earfcn_add(bts, 2133, 11, 12, 6, 11, 3);
-	bts_earfcn_add(bts, 2134, 11, 12, 6, 11, 2);
-	bts_earfcn_add(bts, 2121, 11, 12, 6, 11, 5);
-	bts_earfcn_add(bts, 2122, 11, 12, 6, 11, 4);
-	bts_earfcn_add(bts, 2123, 11, 12, 6, 11, 3);
-	bts_earfcn_add(bts, 2124, 11, 12, 6, 11, 2);
-	_bts_uarfcn_add(bts, 1976, 13, 1);
-	_bts_uarfcn_add(bts, 1976, 38, 1);
-	_bts_uarfcn_add(bts, 1976, 44, 1);
-	_bts_uarfcn_add(bts, 1976, 120, 1);
-	_bts_uarfcn_add(bts, 1976, 140, 1);
-	_bts_uarfcn_add(bts, 1976, 163, 1);
-	_bts_uarfcn_add(bts, 1976, 166, 1);
-	_bts_uarfcn_add(bts, 1976, 217, 1);
-	_bts_uarfcn_add(bts, 1976, 224, 1);
-	_bts_uarfcn_add(bts, 1976, 225, 1);
-	_bts_uarfcn_add(bts, 1976, 226, 1);
-}
-
-static void test_mi_functionality(void)
-{
-	const char *imsi_odd  = "987654321098763";
-	const char *imsi_even = "9876543210987654";
-	const uint32_t tmsi = 0xfabeacd0;
-	uint8_t mi[128];
-	unsigned int mi_len;
-	char mi_parsed[GSM48_MI_SIZE];
-
-	printf("Testing parsing and generating TMSI/IMSI\n");
-
-	/* tmsi code */
-	mi_len = gsm48_generate_mid_from_tmsi(mi, tmsi);
-	gsm48_mi_to_string(mi_parsed, sizeof(mi_parsed), mi + 2, mi_len - 2);
-	COMPARE((uint32_t)strtoul(mi_parsed, NULL, 10), ==, tmsi);
-
-	/* imsi code */
-	mi_len = gsm48_generate_mid_from_imsi(mi, imsi_odd);
-	gsm48_mi_to_string(mi_parsed, sizeof(mi_parsed), mi + 2, mi_len -2);
-	printf("hex: %s\n", osmo_hexdump(mi, mi_len));
-	COMPARE_STR(mi_parsed, imsi_odd);
-
-	mi_len = gsm48_generate_mid_from_imsi(mi, imsi_even);
-	gsm48_mi_to_string(mi_parsed, sizeof(mi_parsed), mi + 2, mi_len -2);
-	printf("hex: %s\n", osmo_hexdump(mi, mi_len));
-	COMPARE_STR(mi_parsed, imsi_even);
-}
-
-struct {
-	int range;
-	int arfcns_num;
-	int arfcns[RANGE_ENC_MAX_ARFCNS];
-} arfcn_test_ranges[] = {
-	{ARFCN_RANGE_512, 12,
-		{ 1, 12, 31, 51, 57, 91, 97, 98, 113, 117, 120, 125 }},
-	{ARFCN_RANGE_512, 17,
-		{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }},
-	{ARFCN_RANGE_512, 18,
-		{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 }},
-	{ARFCN_RANGE_512, 18,
-		{ 1, 17, 31, 45, 58, 79, 81, 97,
-		  113, 127, 213, 277, 287, 311, 331, 391,
-		  417, 511 }},
-	{ARFCN_RANGE_512, 6,
-		{ 1, 17, 31, 45, 58, 79 }},
-	{ARFCN_RANGE_512, 6,
-		{ 10, 17, 31, 45, 58, 79 }},
-	{ARFCN_RANGE_1024, 17,
-		{ 0, 17, 31, 45, 58, 79, 81, 97,
-		  113, 127, 213, 277, 287, 311, 331, 391,
-		  1023 }},
-	{ARFCN_RANGE_1024, 16,
-		{ 17, 31, 45, 58, 79, 81, 97, 113,
-		  127, 213, 277, 287, 311, 331, 391, 1023 }},
-	{-1}
-};
-
-static int test_single_range_encoding(int range, const int *orig_arfcns,
-				       int arfcns_num, int silent)
-{
-	int arfcns[RANGE_ENC_MAX_ARFCNS];
-	int w[RANGE_ENC_MAX_ARFCNS];
-	int f0_included = 0;
-	int rc, f0;
-	uint8_t chan_list[16] = {0};
-	struct gsm_sysinfo_freq dec_freq[1024] = {{0}};
-	int dec_arfcns[RANGE_ENC_MAX_ARFCNS] = {0};
-	int dec_arfcns_count = 0;
-	int arfcns_used = 0;
-	int i;
-
-	arfcns_used = arfcns_num;
-	memmove(arfcns, orig_arfcns, sizeof(arfcns));
-
-	f0 = range == ARFCN_RANGE_1024 ? 0 : arfcns[0];
-	/*
-	 * Manipulate the ARFCN list according to the rules in J4 depending
-	 * on the selected range.
-	 */
-	arfcns_used = range_enc_filter_arfcns(arfcns, arfcns_used,
-					      f0, &f0_included);
-
-	memset(w, 0, sizeof(w));
-	range_enc_arfcns(range, arfcns, arfcns_used, w, 0);
-
-	if (!silent)
-		fprintf(stderr, "range=%d, arfcns_used=%d, f0=%d, f0_included=%d\n",
-			range, arfcns_used, f0, f0_included);
-
-	/* Select the range and the amount of bits needed */
-	switch (range) {
-	case ARFCN_RANGE_128:
-		range_enc_range128(chan_list, f0, w);
-		break;
-	case ARFCN_RANGE_256:
-		range_enc_range256(chan_list, f0, w);
-		break;
-	case ARFCN_RANGE_512:
-		range_enc_range512(chan_list, f0, w);
-		break;
-	case ARFCN_RANGE_1024:
-		range_enc_range1024(chan_list, f0, f0_included, w);
-		break;
-	default:
-		return 1;
-	};
-
-	if (!silent)
-		printf("chan_list = %s\n",
-		       osmo_hexdump(chan_list, sizeof(chan_list)));
-
-	rc = gsm48_decode_freq_list(dec_freq, chan_list, sizeof(chan_list),
-				    0xfe, 1);
-	if (rc != 0) {
-		printf("Cannot decode freq list, rc = %d\n", rc);
-		return 1;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(dec_freq); i++) {
-		if (dec_freq[i].mask &&
-		    dec_arfcns_count < ARRAY_SIZE(dec_arfcns))
-			dec_arfcns[dec_arfcns_count++] = i;
-	}
-
-	if (!silent) {
-		printf("Decoded freqs %d (expected %d)\n",
-		       dec_arfcns_count, arfcns_num);
-		printf("Decoded: ");
-		for (i = 0; i < dec_arfcns_count; i++) {
-			printf("%d ", dec_arfcns[i]);
-			if (dec_arfcns[i] != orig_arfcns[i])
-				printf("(!= %d) ", orig_arfcns[i]);
-		}
-		printf("\n");
-	}
-
-	if (dec_arfcns_count != arfcns_num) {
-		printf("Wrong number of arfcns\n");
-		return 1;
-	}
-
-	if (memcmp(dec_arfcns, orig_arfcns, sizeof(dec_arfcns)) != 0) {
-		printf("Decoding error, got wrong freqs\n");
-		fprintf(stderr, " w = ");
-		for (i = 0; i < ARRAY_SIZE(w); i++)
-			fprintf(stderr, "%d ", w[i]);
-		fprintf(stderr, "\n");
-		return 1;
-	}
-
-	return 0;
-}
-
-static void test_random_range_encoding(int range, int max_arfcn_num)
-{
-	int arfcns_num = 0;
-	int test_idx;
-	int rc, max_count;
-	int num_tests = 1024;
-
-	printf("Random range test: range %d, max num ARFCNs %d\n",
-	       range, max_arfcn_num);
-
-	srandom(1);
-
-	for (max_count = 1; max_count < max_arfcn_num; max_count++) {
-		for (test_idx = 0; test_idx < num_tests; test_idx++) {
-			int count;
-			int i;
-			int min_freq = 0;
-
-			int rnd_arfcns[RANGE_ENC_MAX_ARFCNS] = {0};
-			char rnd_arfcns_set[1024] = {0};
-
-			if (range < ARFCN_RANGE_1024)
-				min_freq = random() % (1023 - range);
-
-			for (count = max_count; count; ) {
-				int arfcn = min_freq + random() % (range + 1);
-				OSMO_ASSERT(arfcn < ARRAY_SIZE(rnd_arfcns_set));
-
-				if (!rnd_arfcns_set[arfcn]) {
-					rnd_arfcns_set[arfcn] = 1;
-					count -= 1;
-				}
-			}
-
-			arfcns_num = 0;
-			for (i = 0; i < ARRAY_SIZE(rnd_arfcns_set); i++)
-				if (rnd_arfcns_set[i])
-					rnd_arfcns[arfcns_num++] = i;
-
-			rc = test_single_range_encoding(range, rnd_arfcns,
-							arfcns_num, 1);
-			if (rc != 0) {
-				printf("Failed on test %d, range %d, num ARFCNs %d\n",
-				       test_idx, range, max_count);
-				test_single_range_encoding(range, rnd_arfcns,
-							   arfcns_num, 0);
-				return;
-			}
-		}
-	}
-}
-
-static void test_range_encoding()
-{
-	int *arfcns;
-	int arfcns_num = 0;
-	int test_idx;
-	int range;
-
-	for (test_idx = 0; arfcn_test_ranges[test_idx].arfcns_num > 0; test_idx++)
-	{
-		arfcns_num = arfcn_test_ranges[test_idx].arfcns_num;
-		arfcns = &arfcn_test_ranges[test_idx].arfcns[0];
-		range = arfcn_test_ranges[test_idx].range;
-
-		printf("Range test %d: range %d, num ARFCNs %d\n",
-		       test_idx, range, arfcns_num);
-
-		test_single_range_encoding(range, arfcns, arfcns_num, 0);
-	}
-
-	test_random_range_encoding(ARFCN_RANGE_128, 29);
-	test_random_range_encoding(ARFCN_RANGE_256, 22);
-	test_random_range_encoding(ARFCN_RANGE_512, 18);
-	test_random_range_encoding(ARFCN_RANGE_1024, 16);
-}
-
-static int freqs1[] = {
-	12, 70, 121, 190, 250, 320, 401, 475, 520, 574, 634, 700, 764, 830, 905, 980
-};
-
-static int freqs2[] = {
-	402, 460, 1, 67, 131, 197, 272, 347,
-};
-
-static int freqs3[] = {
-	68, 128, 198, 279, 353, 398, 452,
-
-};
-
-static int w_out[] = {
-	122, 2, 69, 204, 75, 66, 60, 70, 83, 3, 24, 67, 54, 64, 70, 9,
-};
-
-static int range128[] = {
-	1, 1 + 127,
-};
-
-static int range256[] = {
-	1, 1 + 128,
-};
-
-static int range512[] = {
-	1, 1+ 511,
-};
-
-
-static void test_arfcn_filter()
-{
-	int arfcns[50], i, res, f0_included;
-	for (i = 0; i < ARRAY_SIZE(arfcns); ++i)
-		arfcns[i] = (i + 1) * 2;
-
-	/* check that the arfcn is taken out. f0_included is only set for Range1024 */
-	f0_included = 24;
-	res = range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns),
-			arfcns[0], &f0_included);
-	VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1);
-	VERIFY(f0_included, ==, 1);
-	for (i = 0; i < res; ++i)
-		VERIFY(arfcns[i], ==, ((i+2) * 2) - (2+1));
-
-	/* check with range1024, ARFCN 0 is included */
-	for (i = 0; i < ARRAY_SIZE(arfcns); ++i)
-		arfcns[i] = i * 2;
-	res = range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns),
-			0, &f0_included);
-	VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1);
-	VERIFY(f0_included, ==, 1);
-	for (i = 0; i < res; ++i)
-		VERIFY(arfcns[i], ==, (i + 1) * 2 - 1);
-
-	/* check with range1024, ARFCN 0 not included */
-	for (i = 0; i < ARRAY_SIZE(arfcns); ++i)
-		arfcns[i] = (i + 1) * 2;
-	res = range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns),
-			0, &f0_included);
-	VERIFY(res, ==, ARRAY_SIZE(arfcns));
-	VERIFY(f0_included, ==, 0);
-	for (i = 0; i < res; ++i)
-		VERIFY(arfcns[i], ==, ((i + 1) * 2) - 1);
-}
-
-static void test_print_encoding()
-{
-	int rc;
-	int w[17];
-	uint8_t chan_list[16];
-	memset(chan_list, 0x23, sizeof(chan_list));
-
-	for (rc = 0; rc < ARRAY_SIZE(w); ++rc)
-		switch (rc % 3) {
-		case 0:
-			w[rc] = 0xAAAA;
-			break;
-		case 1:
-			w[rc] = 0x5555;
-			break;
-		case 2:
-			w[rc] = 0x9696;
-			break;
-		}
-
-	range_enc_range512(chan_list, (1 << 9) | 0x96, w);
-
-	printf("Range512: %s\n", osmo_hexdump(chan_list, ARRAY_SIZE(chan_list)));
-}
-
-static void test_si_range_helpers()
-{
-	int ws[(sizeof(freqs1)/sizeof(freqs1[0]))];
-	int i, f0 = 0xFFFFFF;
-
-	memset(&ws[0], 0x23, sizeof(ws));
-
-	i = range_enc_find_index(1023, freqs1, ARRAY_SIZE(freqs1));
-	printf("Element is: %d => freqs[i] = %d\n", i, i >= 0 ? freqs1[i] : -1);
-	VERIFY(i, ==, 2);
-
-	i = range_enc_find_index(511, freqs2, ARRAY_SIZE(freqs2));
-	printf("Element is: %d => freqs[i] = %d\n", i,  i >= 0 ? freqs2[i] : -1);
-	VERIFY(i, ==, 2);
-
-	i = range_enc_find_index(511, freqs3, ARRAY_SIZE(freqs3));
-	printf("Element is: %d => freqs[i] = %d\n", i,  i >= 0 ? freqs3[i] : -1);
-	VERIFY(i, ==, 0);
-
-	range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0);
-
-	for (i = 0; i < sizeof(freqs1)/sizeof(freqs1[0]); ++i) {
-		printf("w[%d]=%d\n", i, ws[i]);
-		VERIFY(ws[i], ==, w_out[i]);
-	}
-
-	i = range_enc_determine_range(range128, ARRAY_SIZE(range128), &f0);
-	VERIFY(i, ==, ARFCN_RANGE_128);
-	VERIFY(f0, ==, 1);
-
-	i = range_enc_determine_range(range256, ARRAY_SIZE(range256), &f0);
-	VERIFY(i, ==, ARFCN_RANGE_256);
-	VERIFY(f0, ==, 1);
-
-	i = range_enc_determine_range(range512, ARRAY_SIZE(range512), &f0);
-	VERIFY(i, ==, ARFCN_RANGE_512);
-	VERIFY(f0, ==, 1);
-}
-
-static void test_gsm411_rp_ref_wrap(void)
-{
-	struct gsm_subscriber_connection conn;
-	int res;
-
-	printf("testing RP-Reference wrap\n");
-
-	memset(&conn, 0, sizeof(conn));
-	conn.next_rp_ref = 255;
-
-	res = sms_next_rp_msg_ref(&conn.next_rp_ref);
-	printf("Allocated reference: %d\n", res);
-	OSMO_ASSERT(res == 255);
-
-	res = sms_next_rp_msg_ref(&conn.next_rp_ref);
-	printf("Allocated reference: %d\n", res);
-	OSMO_ASSERT(res == 0);
-
-	res = sms_next_rp_msg_ref(&conn.next_rp_ref);
-	printf("Allocated reference: %d\n", res);
-	OSMO_ASSERT(res == 1);
-}
-
-int main(int argc, char **argv)
-{
-	osmo_init_logging(&log_info);
-	log_set_log_level(osmo_stderr_target, LOGL_INFO);
-
-	test_location_area_identifier();
-	test_mi_functionality();
-
-	test_si_range_helpers();
-	test_arfcn_filter();
-	test_print_encoding();
-	test_range_encoding();
-	test_gsm411_rp_ref_wrap();
-
-	test_si2q_segfault();
-	test_si2q_e();
-	test_si2q_u();
-	test_si2q_mu();
-	test_si2q_long();
-
-	printf("Done.\n");
-
-	return EXIT_SUCCESS;
-}
diff --git a/tests/gsm0408/gsm0408_test.ok b/tests/gsm0408/gsm0408_test.ok
deleted file mode 100644
index d30f421..0000000
--- a/tests/gsm0408/gsm0408_test.ok
+++ /dev/null
@@ -1,204 +0,0 @@
-Testing test location area identifier
-Testing parsing and generating TMSI/IMSI
-hex: 17 08 99 78 56 34 12 90 78 36 
-hex: 17 09 91 78 56 34 12 90 78 56 f4 
-Element is: 2 => freqs[i] = 121
-Element is: 2 => freqs[i] = 1
-Element is: 0 => freqs[i] = 68
-w[0]=122
-w[1]=2
-w[2]=69
-w[3]=204
-w[4]=75
-w[5]=66
-w[6]=60
-w[7]=70
-w[8]=83
-w[9]=3
-w[10]=24
-w[11]=67
-w[12]=54
-w[13]=64
-w[14]=70
-w[15]=9
-Range512: 89 4b 2a 95 65 95 55 2c a9 55 aa 55 6a 95 59 55 
-Range test 0: range 511, num ARFCNs 12
-chan_list = 88 00 98 34 85 36 7c 50 22 dc 5e ec 00 00 00 00 
-Decoded freqs 12 (expected 12)
-Decoded: 1 12 31 51 57 91 97 98 113 117 120 125 
-Range test 1: range 511, num ARFCNs 17
-chan_list = 88 00 82 7f 01 3f 7e 04 0b ff ff fc 10 41 07 e0 
-Decoded freqs 17 (expected 17)
-Decoded: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 
-Range test 2: range 511, num ARFCNs 18
-chan_list = 88 00 82 7f 01 7f 7e 04 0b ff ff fc 10 41 07 ff 
-Decoded freqs 18 (expected 18)
-Decoded: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 
-Range test 3: range 511, num ARFCNs 18
-chan_list = 88 00 94 3a 44 32 d7 2a 43 2a 13 94 e5 38 39 f6 
-Decoded freqs 18 (expected 18)
-Decoded: 1 17 31 45 58 79 81 97 113 127 213 277 287 311 331 391 417 511 
-Range test 4: range 511, num ARFCNs 6
-chan_list = 88 00 8b 3c 88 b9 6b 00 00 00 00 00 00 00 00 00 
-Decoded freqs 6 (expected 6)
-Decoded: 1 17 31 45 58 79 
-Range test 5: range 511, num ARFCNs 6
-chan_list = 88 05 08 fc 88 b9 6b 00 00 00 00 00 00 00 00 00 
-Decoded freqs 6 (expected 6)
-Decoded: 10 17 31 45 58 79 
-Range test 6: range 1023, num ARFCNs 17
-chan_list = 84 71 e4 ab b9 58 05 cb 39 17 fd b0 75 62 0f 2f 
-Decoded freqs 17 (expected 17)
-Decoded: 0 17 31 45 58 79 81 97 113 127 213 277 287 311 331 391 1023 
-Range test 7: range 1023, num ARFCNs 16
-chan_list = 80 71 e4 ab b9 58 05 cb 39 17 fd b0 75 62 0f 2f 
-Decoded freqs 16 (expected 16)
-Decoded: 17 31 45 58 79 81 97 113 127 213 277 287 311 331 391 1023 
-Random range test: range 127, max num ARFCNs 29
-Random range test: range 255, max num ARFCNs 22
-Random range test: range 511, max num ARFCNs 18
-Random range test: range 1023, max num ARFCNs 16
-testing RP-Reference wrap
-Allocated reference: 255
-Allocated reference: 0
-Allocated reference: 1
-Test SI2quater UARFCN (same scrambling code and diversity):
-generating SI2quater for 0 EARFCNs and 1 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 52 88 0a 7e 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 0 EARFCNs and 2 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 52 e8 0a 7f 52 88 0a 7e 0b 2b 2b 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 0 EARFCNs and 2 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 52 e8 0a 7f 52 88 0a 7e 0b 2b 2b 2b 2b 2b 2b 2b 2b 
-Testing SYSINFO_TYPE_2quater EARFCN generation:
-generating SI2quater for 0 EARFCNs and 0 UARFCNs...
-generated invalid SI2quater [00/00]: [23] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
-added EARFCN 1917 - generating SI2quater for 1 EARFCNs and 0 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 04 86 59 83 be e8 50 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 
-removed EARFCN 1917 - generating SI2quater for 0 EARFCNs and 0 UARFCNs...
-generated invalid SI2quater [00/00]: [23] 59 06 07 c0 00 04 86 59 83 be e8 50 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 
-added EARFCN 1917 - generating SI2quater for 1 EARFCNs and 0 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 04 86 59 83 be c8 50 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 
-added EARFCN 1932 - generating SI2quater for 2 EARFCNs and 0 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 30 14 03 2b 2b 2b 2b 2b 2b 2b 2b 
-added EARFCN 1937 - generating SI2quater for 3 EARFCNs and 0 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a0 a0 2b 2b 2b 2b 2b 2b 
-added EARFCN 1945 - generating SI2quater for 4 EARFCNs and 0 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a8 3c c8 28 0b 2b 2b 2b 
-added EARFCN 1965 - generating SI2quater for 5 EARFCNs and 0 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a8 3c ca 0f 5a 0a 03 2b 
-added EARFCN 1967 - generating SI2quater for 6 EARFCNs and 0 UARFCNs...
-generated valid SI2quater [00/01]: [23] 59 06 07 c0 20 04 86 59 83 be cc 1e 31 07 91 a8 3c ca 0f 5a 0a 03 2b 
-generated valid SI2quater [01/01]: [23] 59 06 07 c2 20 04 86 59 83 d7 e0 50 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 
-added EARFCN 1982 - generating SI2quater for 7 EARFCNs and 0 UARFCNs...
-generated valid SI2quater [00/01]: [23] 59 06 07 c0 20 04 86 59 83 be cc 1e 31 07 91 a8 3c ca 0f 5a 0a 03 2b 
-generated valid SI2quater [01/01]: [23] 59 06 07 c2 20 04 86 59 83 d7 e4 1e fa c2 80 2b 2b 2b 2b 2b 2b 2b 2b 
-Testing SYSINFO_TYPE_2quater UARFCN generation:
-generating SI2quater for 0 EARFCNs and 0 UARFCNs...
-generated invalid SI2quater [00/00]: [23] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
-generating SI2quater for 0 EARFCNs and 1 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 0f 7c 0c 1a 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 0 EARFCNs and 2 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 0f 7c 14 1a 1f 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 0 EARFCNs and 3 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 0f 7c 18 58 12 f0 83 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 0 EARFCNs and 4 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 0f 7c 20 58 2e f0 f2 03 2b 2b 2b 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 0 EARFCNs and 5 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 0f 7c 28 58 2e 22 f2 4e 83 2b 2b 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 0 EARFCNs and 6 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 0f 7c 34 1a 64 26 5d f2 05 03 2b 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 0 EARFCNs and 7 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 0f 7c 38 58 12 22 fd ce 8e 05 03 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 0 EARFCNs and 8 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 0f 7c 40 58 1d 22 fa ce 88 85 7b 0b 2b 2b 2b 2b 2b 
-generating SI2quater for 0 EARFCNs and 9 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 0f 7c 4c 7a 34 0e 64 77 85 43 55 c8 0b 2b 2b 2b 2b 
-generating SI2quater for 0 EARFCNs and 10 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 0f 7c 50 1c 3b 31 fa dd 88 85 7b c4 1c 2b 2b 2b 2b 
-generating SI2quater for 0 EARFCNs and 11 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 0f 7c 58 1c 3b 25 7a ea 08 91 fb c4 1f b0 2b 2b 2b 
-Test SI2quater multiple UARFCNs:
-generating SI2quater for 0 EARFCNs and 1 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 52 88 0a 7c 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 0 EARFCNs and 2 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 52 e8 0a 7f 52 88 0a 7c 0b 2b 2b 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 0 EARFCNs and 3 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 52 e8 12 7e e0 a9 44 05 3e 0b 2b 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 0 EARFCNs and 4 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 52 e8 18 3f f4 90 54 a2 02 9f 03 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 0 EARFCNs and 5 UARFCNs...
-generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 52 ea 08 81 52 e8 18 3f f4 90 54 a2 02 9f 03 2b 2b 
-generating SI2quater for 0 EARFCNs and 6 UARFCNs...
-generated valid SI2quater [00/01]: [23] 59 06 07 c0 20 25 52 ea 08 81 52 e8 10 3f f4 a9 75 04 a4 0b 2b 2b 2b 
-generated valid SI2quater [01/01]: [23] 59 06 07 c2 20 25 52 e8 28 81 df 7f fa 32 d4 a2 02 9f 03 2b 2b 2b 2b 
-generating SI2quater for 0 EARFCNs and 7 UARFCNs...
-generated valid SI2quater [00/01]: [23] 59 06 07 c0 20 25 52 ea 10 81 ce a9 74 08 1f fa 54 ba 82 52 03 2b 2b 
-generated valid SI2quater [01/01]: [23] 59 06 07 c2 20 25 52 e8 30 81 d3 7f fd b2 86 54 a2 02 9f 03 2b 2b 2b 
-Testing SYSINFO_TYPE_2quater combined EARFCN & UARFCN generation:
-generating SI2quater for 17 EARFCNs and 1 UARFCNs...
-generated valid SI2quater [00/04]: [23] 59 06 07 c0 80 25 0f 70 0c 1a 10 99 66 0f 04 83 c1 1c bb 2b 03 2b 2b 
-generated valid SI2quater [01/04]: [23] 59 06 07 c2 80 04 86 59 83 c2 6c 1e 0f 60 f0 bb 08 3f d7 2e ca c1 2b 
-generated valid SI2quater [02/04]: [23] 59 06 07 c4 80 04 86 59 84 20 64 21 06 e1 08 55 08 53 d7 2e ca c1 2b 
-generated valid SI2quater [03/04]: [23] 59 06 07 c6 80 04 86 59 84 2a 64 21 56 e1 0a d5 08 49 d7 2e ca c1 2b 
-generated valid SI2quater [04/04]: [23] 59 06 07 c8 80 04 86 59 84 25 64 21 2e e1 09 94 e5 d9 58 2b 2b 2b 2b 
-generating SI2quater for 17 EARFCNs and 2 UARFCNs...
-generated valid SI2quater [00/04]: [23] 59 06 07 c0 80 25 0f 70 14 4d e7 00 44 b3 07 82 41 e0 8e 5d 95 83 2b 
-generated valid SI2quater [01/04]: [23] 59 06 07 c2 80 04 86 59 83 c2 6c 1e 0f 60 f0 bb 08 3f d7 2e ca c1 2b 
-generated valid SI2quater [02/04]: [23] 59 06 07 c4 80 04 86 59 84 20 64 21 06 e1 08 55 08 53 d7 2e ca c1 2b 
-generated valid SI2quater [03/04]: [23] 59 06 07 c6 80 04 86 59 84 2a 64 21 56 e1 0a d5 08 49 d7 2e ca c1 2b 
-generated valid SI2quater [04/04]: [23] 59 06 07 c8 80 04 86 59 84 25 64 21 2e e1 09 94 e5 d9 58 2b 2b 2b 2b 
-generating SI2quater for 17 EARFCNs and 3 UARFCNs...
-generated valid SI2quater [00/04]: [23] 59 06 07 c0 80 25 0f 70 1c 4d e7 03 04 86 59 83 c1 20 f0 47 2e ca c1 
-generated valid SI2quater [01/04]: [23] 59 06 07 c2 80 04 86 59 83 c2 6c 1e 0f 60 f0 bb 08 3f d7 2e ca c1 2b 
-generated valid SI2quater [02/04]: [23] 59 06 07 c4 80 04 86 59 84 20 64 21 06 e1 08 55 08 53 d7 2e ca c1 2b 
-generated valid SI2quater [03/04]: [23] 59 06 07 c6 80 04 86 59 84 2a 64 21 56 e1 0a d5 08 49 d7 2e ca c1 2b 
-generated valid SI2quater [04/04]: [23] 59 06 07 c8 80 04 86 59 84 25 64 21 2e e1 09 94 e5 d9 58 2b 2b 2b 2b 
-generating SI2quater for 17 EARFCNs and 4 UARFCNs...
-generated valid SI2quater [00/04]: [23] 59 06 07 c0 80 25 0f 70 24 59 fa 26 73 84 86 59 83 c1 1c bb 2b 03 2b 
-generated valid SI2quater [01/04]: [23] 59 06 07 c2 80 04 86 59 83 c1 20 f0 9b 07 83 d8 3c 2e b9 76 56 0b 2b 
-generated valid SI2quater [02/04]: [23] 59 06 07 c4 80 04 86 59 84 1f ec 21 03 21 08 37 08 42 a7 2e ca c1 2b 
-generated valid SI2quater [03/04]: [23] 59 06 07 c6 80 04 86 59 84 29 ec 21 53 21 0a b7 08 56 a7 2e ca c1 2b 
-generated valid SI2quater [04/04]: [23] 59 06 07 c8 80 04 86 59 84 24 ec 21 2b 21 09 77 08 4c a7 2e ca c1 2b 
-generating SI2quater for 17 EARFCNs and 5 UARFCNs...
-generated valid SI2quater [00/04]: [23] 59 06 07 c0 80 25 0f 70 2c 59 fa 30 73 f6 04 86 59 83 c1 1c bb 2b 03 
-generated valid SI2quater [01/04]: [23] 59 06 07 c2 80 04 86 59 83 c1 20 f0 9b 07 83 d8 3c 2e b9 76 56 0b 2b 
-generated valid SI2quater [02/04]: [23] 59 06 07 c4 80 04 86 59 84 1f ec 21 03 21 08 37 08 42 a7 2e ca c1 2b 
-generated valid SI2quater [03/04]: [23] 59 06 07 c6 80 04 86 59 84 29 ec 21 53 21 0a b7 08 56 a7 2e ca c1 2b 
-generated valid SI2quater [04/04]: [23] 59 06 07 c8 80 04 86 59 84 24 ec 21 2b 21 09 77 08 4c a7 2e ca c1 2b 
-generating SI2quater for 17 EARFCNs and 6 UARFCNs...
-generated valid SI2quater [00/05]: [23] 59 06 07 c0 a0 25 0f 70 34 f1 ae 15 f3 f4 83 04 86 59 72 ec ac 0b 2b 
-generated valid SI2quater [01/05]: [23] 59 06 07 c2 a0 04 86 59 83 c1 20 f0 48 3c 26 c1 e0 f5 cb b2 b0 2b 2b 
-generated valid SI2quater [02/05]: [23] 59 06 07 c4 a0 04 86 59 83 c2 ec 20 ff 61 08 19 08 41 b7 2e ca c1 2b 
-generated valid SI2quater [03/05]: [23] 59 06 07 c6 a0 04 86 59 84 21 54 21 4f 61 0a 99 08 55 b7 2e ca c1 2b 
-generated valid SI2quater [04/05]: [23] 59 06 07 c8 a0 04 86 59 84 2b 54 21 27 61 09 59 08 4b b7 2e ca c1 2b 
-generated valid SI2quater [05/05]: [23] 59 06 07 ca a0 04 86 59 84 26 53 97 65 60 2b 2b 2b 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 17 EARFCNs and 7 UARFCNs...
-generated valid SI2quater [00/05]: [23] 59 06 07 c0 a0 25 0f 70 3c f1 ae 15 f3 f4 83 01 84 86 59 72 ec ac 0b 
-generated valid SI2quater [01/05]: [23] 59 06 07 c2 a0 04 86 59 83 c1 20 f0 48 3c 26 c1 e0 f5 cb b2 b0 2b 2b 
-generated valid SI2quater [02/05]: [23] 59 06 07 c4 a0 04 86 59 83 c2 ec 20 ff 61 08 19 08 41 b7 2e ca c1 2b 
-generated valid SI2quater [03/05]: [23] 59 06 07 c6 a0 04 86 59 84 21 54 21 4f 61 0a 99 08 55 b7 2e ca c1 2b 
-generated valid SI2quater [04/05]: [23] 59 06 07 c8 a0 04 86 59 84 2b 54 21 27 61 09 59 08 4b b7 2e ca c1 2b 
-generated valid SI2quater [05/05]: [23] 59 06 07 ca a0 04 86 59 84 26 53 97 65 60 2b 2b 2b 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 17 EARFCNs and 8 UARFCNs...
-generated valid SI2quater [00/02]: [23] 59 06 07 c0 40 25 0f 70 45 19 a0 0d 7d 7e a6 19 e7 00 44 b3 07 82 41 
-generated valid SI2quater [01/02]: [23] 59 06 07 c2 40 04 86 59 84 2b 54 21 27 61 09 59 08 4b b7 2e ca c1 2b 
-generated valid SI2quater [02/02]: [23] 59 06 07 c4 40 04 86 59 84 26 53 97 65 60 2b 2b 2b 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 17 EARFCNs and 9 UARFCNs...
-generated valid SI2quater [00/02]: [23] 59 06 07 c0 40 25 0f 70 4d 19 a0 26 fd 66 a6 03 e7 fa 10 99 66 0f 04 
-generated valid SI2quater [01/02]: [23] 59 06 07 c2 40 04 86 59 84 2b 54 21 27 61 09 59 08 4b b7 2e ca c1 2b 
-generated valid SI2quater [02/02]: [23] 59 06 07 c4 40 04 86 59 84 26 53 97 65 60 2b 2b 2b 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 17 EARFCNs and 10 UARFCNs...
-generated valid SI2quater [00/05]: [23] 59 06 07 c0 a0 25 0f 70 55 47 89 1e fd 7c b0 00 e7 9b b0 04 12 c8 2b 
-generated valid SI2quater [01/05]: [23] 59 06 07 c2 a0 04 86 59 83 c1 20 f0 48 3c 26 c1 e0 f5 cb b2 b0 2b 2b 
-generated valid SI2quater [02/05]: [23] 59 06 07 c4 a0 04 86 59 83 c2 ec 20 ff 61 08 19 08 41 b7 2e ca c1 2b 
-generated valid SI2quater [03/05]: [23] 59 06 07 c6 a0 04 86 59 84 21 54 21 4f 61 0a 99 08 55 b7 2e ca c1 2b 
-generated valid SI2quater [04/05]: [23] 59 06 07 c8 a0 04 86 59 84 2b 54 21 27 61 09 59 08 4b b7 2e ca c1 2b 
-generated valid SI2quater [05/05]: [23] 59 06 07 ca a0 04 86 59 84 26 53 97 65 60 2b 2b 2b 2b 2b 2b 2b 2b 2b 
-generating SI2quater for 17 EARFCNs and 11 UARFCNs...
-generated valid SI2quater [00/05]: [23] 59 06 07 c0 a0 25 0f 70 5d 47 89 1e fd 7c b0 01 67 9b b3 f8 2b 2b 2b 
-generated valid SI2quater [01/05]: [23] 59 06 07 c2 a0 04 86 59 83 c1 20 f0 48 3c 26 c1 e0 f5 cb b2 b0 2b 2b 
-generated valid SI2quater [02/05]: [23] 59 06 07 c4 a0 04 86 59 83 c2 ec 20 ff 61 08 19 08 41 b7 2e ca c1 2b 
-generated valid SI2quater [03/05]: [23] 59 06 07 c6 a0 04 86 59 84 21 54 21 4f 61 0a 99 08 55 b7 2e ca c1 2b 
-generated valid SI2quater [04/05]: [23] 59 06 07 c8 a0 04 86 59 84 2b 54 21 27 61 09 59 08 4b b7 2e ca c1 2b 
-generated valid SI2quater [05/05]: [23] 59 06 07 ca a0 04 86 59 84 26 53 97 65 60 2b 2b 2b 2b 2b 2b 2b 2b 2b 
-Done.
diff --git a/tests/gtphub/Makefile.am b/tests/gtphub/Makefile.am
deleted file mode 100644
index f2a6b88..0000000
--- a/tests/gtphub/Makefile.am
+++ /dev/null
@@ -1,44 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	-ggdb3 \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBGTP_CFLAGS) \
-	$(NULL)
-
-EXTRA_DIST = \
-	gtphub_test.ok \
-	$(NULL)
-
-if HAVE_LIBGTP
-if HAVE_LIBCARES
-noinst_PROGRAMS = \
-	gtphub_test \
-	$(NULL)
-endif
-endif
-
-gtphub_test_SOURCES = \
-	gtphub_test.c \
-	$(NULL)
-
-gtphub_test_LDFLAGS = \
-	-Wl,--wrap=gtphub_resolve_ggsn_addr \
-	-Wl,--wrap=gtphub_ares_init \
-	-Wl,--wrap=gtphub_write \
-	$(NULL)
-
-gtphub_test_LDADD = \
-	$(top_builddir)/src/gprs/gtphub.o \
-	$(top_builddir)/src/gprs/gprs_utils.o \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBGTP_LIBS) \
-	-lrt \
-	$(NULL)
diff --git a/tests/gtphub/gtphub_test.c b/tests/gtphub/gtphub_test.c
deleted file mode 100644
index e7c27d2..0000000
--- a/tests/gtphub/gtphub_test.c
+++ /dev/null
@@ -1,1786 +0,0 @@
-/* Test the GTP hub */
-
-/* (C) 2015 by sysmocom s.f.m.c. GmbH
- * All Rights Reserved
- *
- * Author: Neels Hofmeyr <nhofmeyr@sysmcom.de>
- *
- * 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/>.
- *
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <limits.h>
-#include <unistd.h>
-
-#include <osmocom/core/utils.h>
-#include <osmocom/core/application.h>
-
-#include <openbsc/debug.h>
-
-#include <openbsc/gtphub.h>
-#include <gtp.h>
-#include <gtpie.h>
-
-#define ZERO_STRUCT(struct_pointer) memset(struct_pointer, '\0', \
-					   sizeof(*(struct_pointer)))
-
-#define LVL2_ASSERT(exp) LVL2_ASSERT_R(exp, return 0)
-#define LVL2_ASSERT_R(exp, ret)    \
-	if (!(exp)) { \
-		fprintf(stderr, "LVL2 Assert failed %s %s:%d\n", #exp, \
-			__FILE__, __LINE__); \
-		osmo_generate_backtrace(); \
-		ret; \
-	}
-
-/* Convenience makro, note: only within this C file. */
-#define LOG(label) \
-	{ fprintf(stderr, "\n" label "\n"); \
-	  printf(label "\n"); }
-
-void gtphub_init(struct gtphub *hub);
-void gtphub_free(struct gtphub *hub);
-
-void *osmo_gtphub_ctx;
-
-static void nr_mapping_free(struct expiring_item *e)
-{
-	struct nr_mapping *m = container_of(e, struct nr_mapping,
-					    expiry_entry);
-	nr_mapping_del(m);
-	talloc_free(m);
-}
-
-static struct nr_mapping *nr_mapping_alloc(void)
-{
-	struct nr_mapping *m;
-	m = talloc(osmo_gtphub_ctx, struct nr_mapping);
-	nr_mapping_init(m);
-	m->expiry_entry.del_cb = nr_mapping_free;
-	return m;
-}
-
-static struct nr_mapping *nr_map_have(struct nr_map *map, void *origin,
-				      nr_t orig, time_t now)
-{
-	struct nr_mapping *mapping;
-
-	mapping = nr_map_get(map, origin, orig);
-	if (!mapping) {
-		mapping = nr_mapping_alloc();
-		mapping->origin = origin;
-		mapping->orig = orig;
-		nr_map_add(map, mapping, now);
-	}
-
-	return mapping;
-}
-
-static nr_t nr_map_verify(const struct nr_map *map, void *origin, nr_t orig,
-			  nr_t expect_repl)
-{
-	struct nr_mapping *m;
-	m = nr_map_get(map, origin, orig);
-
-	if (!m) {
-		printf("mapping not found for %p %d\n", origin, orig);
-		return 0;
-	}
-
-	if (m->repl != expect_repl) {
-		printf("mapping found, but nr mismatches: expect %d, got %d\n",
-		       (int)expect_repl, (int)m->repl);
-		return 0;
-	}
-
-	return 1;
-}
-
-static int nr_map_verify_inv(const struct nr_map *map, nr_t repl,
-			     void *expect_origin, nr_t expect_orig)
-{
-	struct nr_mapping *m;
-	m = nr_map_get_inv(map, repl);
-	if (!m) {
-		printf("mapping not found for %d\n", (int)repl);
-		return 0;
-	}
-
-	if (m->origin != expect_origin) {
-		printf("mapping found, but origin mismatches:"
-		       " expect %p, got %p\n",
-		       expect_origin, m->origin);
-		return 0;
-	}
-
-	if (m->orig != expect_orig) {
-		printf("mapping found, but nr mismatches: expect %d, got %d\n",
-		       (int)expect_orig, (int)m->orig);
-		return 0;
-	}
-
-	return 1;
-}
-
-
-static void test_nr_map_basic(void)
-{
-	struct nr_pool _pool;
-	struct nr_pool *pool = &_pool;
-	struct nr_map _map;
-	struct nr_map *map = &_map;
-
-	nr_pool_init(pool, 1, 1000);
-	nr_map_init(map, pool, NULL);
-
-	OSMO_ASSERT(llist_empty(&map->mappings));
-
-#define TEST_N_HALF 100
-#define TEST_N (2*TEST_N_HALF)
-#define TEST_I 123
-	uint32_t i, check_i;
-	uint32_t m[TEST_N];
-	struct nr_mapping *mapping;
-
-	/* create half of TEST_N mappings from one origin */
-	void *origin1 = (void*)0x1234;
-	for (i = 0; i < TEST_N_HALF; i++) {
-		nr_t orig = TEST_I + i;
-		mapping = nr_map_have(map, origin1, orig, 0);
-		m[i] = mapping->repl;
-		OSMO_ASSERT(m[i] != 0);
-		OSMO_ASSERT(llist_count(&map->mappings) == (i+1));
-		for (check_i = 0; check_i < i; check_i++)
-			OSMO_ASSERT(m[check_i] != m[i]);
-	}
-	OSMO_ASSERT(llist_count(&map->mappings) == TEST_N_HALF);
-
-	/* create another TEST_N mappings with the same original numbers, but
-	 * from a different origin */
-	void *origin2 = (void*)0x5678;
-	for (i = 0; i < TEST_N_HALF; i++) {
-		int i2 = TEST_N_HALF + i;
-		nr_t orig = TEST_I + i;
-		mapping = nr_map_have(map, origin2, orig, 0);
-		m[i2] = mapping->repl;
-		OSMO_ASSERT(m[i2] != 0);
-		OSMO_ASSERT(llist_count(&map->mappings) == (i2+1));
-		for (check_i = 0; check_i < i2; check_i++)
-			OSMO_ASSERT(m[check_i] != m[i2]);
-	}
-	OSMO_ASSERT(llist_count(&map->mappings) == TEST_N);
-
-	/* verify mappings */
-	for (i = 0; i < TEST_N_HALF; i++) {
-		nr_t orig = TEST_I + i;
-		{
-			OSMO_ASSERT(nr_map_verify(map, origin1, orig, m[i]));
-			OSMO_ASSERT(nr_map_verify_inv(map, m[i], origin1,
-						      orig));
-		}
-		{
-			int i2 = TEST_N_HALF + i;
-			OSMO_ASSERT(nr_map_verify(map, origin2, orig, m[i2]));
-			OSMO_ASSERT(nr_map_verify_inv(map, m[i2], origin2,
-						      orig));
-		}
-	}
-
-	/* remove all mappings */
-	for (i = 0; i < TEST_N_HALF; i++) {
-		OSMO_ASSERT(llist_count(&map->mappings) == (TEST_N - 2*i));
-
-		nr_t orig = TEST_I + i;
-		nr_mapping_del(nr_map_get(map, origin1, orig));
-		nr_mapping_del(nr_map_get(map, origin2, orig));
-	}
-	OSMO_ASSERT(llist_empty(&map->mappings));
-#undef TEST_N
-#undef TEST_I
-}
-
-static int nr_map_is(struct nr_map *map, const char *str)
-{
-	static char buf[4096];
-	char *pos = buf;
-	size_t len = sizeof(buf);
-	struct nr_mapping *m;
-	llist_for_each_entry(m, &map->mappings, entry) {
-		size_t wrote = snprintf(pos, len, "(%u->%u@%d), ",
-					m->orig,
-					m->repl,
-					(int)m->expiry_entry.expiry);
-		OSMO_ASSERT(wrote < len);
-		pos += wrote;
-		len -= wrote;
-	}
-	*pos = '\0';
-
-	if (strncmp(buf, str, sizeof(buf)) != 0) {
-		printf("FAILURE: nr_map_is() mismatches expected value:\n"
-		       "expected: \"%s\"\n"
-		       "is:       \"%s\"\n",
-		       str, buf);
-		return 0;
-	}
-	return 1;
-}
-
-static int test_nr_map_wrap_with(nr_t nr_min, nr_t nr_max, nr_t repl_last,
-				 nr_t orig_start, int orig_n,
-				 const char *expect)
-{
-	struct nr_pool _pool;
-	struct nr_pool *pool = &_pool;
-	struct nr_map _map;
-	struct nr_map *map = &_map;
-
-	nr_pool_init(pool, nr_min, nr_max);
-	nr_map_init(map, pool, NULL);
-
-	pool->last_nr = repl_last;
-
-	void *origin = (void*)0x1234;
-
-	int i;
-	for (i = 0; i < orig_n; i++)
-		LVL2_ASSERT(nr_map_have(map, origin, orig_start + i, 0));
-
-	LVL2_ASSERT(nr_map_is(map, expect));
-
-	nr_map_clear(map);
-	return 1;
-}
-
-static void test_nr_map_wrap(void)
-{
-	OSMO_ASSERT(test_nr_map_wrap_with(
-		0, UINT_MAX, UINT_MAX - 2,
-		1, 5,
-		"(1->4294967294@0), "
-		"(2->4294967295@0), "
-		"(3->0@0), "
-		"(4->1@0), "
-		"(5->2@0), "
-		));
-	OSMO_ASSERT(test_nr_map_wrap_with(
-		5, 10, 8,
-		1, 5,
-		"(1->9@0), (2->10@0), (3->5@0), (4->6@0), (5->7@0), "
-		));
-}
-
-static void test_expiry(void)
-{
-	struct expiry expiry;
-	struct nr_pool pool;
-	struct nr_map map;
-	int i;
-
-	expiry_init(&expiry, 30);
-	nr_pool_init(&pool, 1, 1000);
-	nr_map_init(&map, &pool, &expiry);
-	OSMO_ASSERT(nr_map_is(&map, ""));
-
-	/* tick on empty map */
-	OSMO_ASSERT(expiry_tick(&expiry, 10000) == 0);
-	OSMO_ASSERT(nr_map_is(&map, ""));
-
-#define MAP1 \
-	"(10->1@10040), " \
-	""
-
-#define MAP2 \
-	"(20->2@10050), " \
-	"(21->3@10051), " \
-	"(22->4@10052), " \
-	"(23->5@10053), " \
-	"(24->6@10054), " \
-	"(25->7@10055), " \
-	"(26->8@10056), " \
-	"(27->9@10057), " \
-	""
-
-#define MAP3 \
-	"(420->10@10072), " \
-	"(421->11@10072), " \
-	"(422->12@10072), " \
-	"(423->13@10072), " \
-	"(424->14@10072), " \
-	"(425->15@10072), " \
-	"(426->16@10072), " \
-	"(427->17@10072), " \
-	""
-
-	/* add mapping at time 10010. */
-	nr_map_have(&map, 0, 10, 10010);
-	OSMO_ASSERT(nr_map_is(&map, MAP1));
-
-	/* tick on unexpired item. */
-	OSMO_ASSERT(expiry_tick(&expiry, 10010) == 0);
-	OSMO_ASSERT(expiry_tick(&expiry, 10011) == 0);
-	OSMO_ASSERT(nr_map_is(&map, MAP1));
-
-	/* Spread mappings at 10020, 10021, ... 10027. */
-	for (i = 0; i < 8; i++)
-		nr_map_have(&map, 0, 20 + i, 10020 + i);
-	OSMO_ASSERT(nr_map_is(&map, MAP1 MAP2));
-
-	/* tick on unexpired items. */
-	OSMO_ASSERT(expiry_tick(&expiry, 10030) == 0);
-	OSMO_ASSERT(expiry_tick(&expiry, 10039) == 0);
-	OSMO_ASSERT(nr_map_is(&map, MAP1 MAP2));
-
-	/* expire the first item (from 10010). */
-	OSMO_ASSERT(expiry_tick(&expiry, 10010 + 30) == 1);
-	OSMO_ASSERT(nr_map_is(&map, MAP2));
-
-	/* again nothing to expire */
-	OSMO_ASSERT(expiry_tick(&expiry, 10041) == 0);
-	OSMO_ASSERT(nr_map_is(&map, MAP2));
-
-	/* Mappings all at the same time. */
-	for (i = 0; i < 8; i++)
-		nr_map_have(&map, 0, 420 + i, 10042);
-	OSMO_ASSERT(nr_map_is(&map, MAP2 MAP3));
-
-	/* Eight to expire, were added further above to be chronologically
-	 * correct, at 10020..10027. */
-	OSMO_ASSERT(expiry_tick(&expiry, 10027 + 30) == 8);
-	OSMO_ASSERT(nr_map_is(&map, MAP3));
-
-	/* again nothing to expire */
-	OSMO_ASSERT(expiry_tick(&expiry, 10027 + 30) == 0);
-	OSMO_ASSERT(nr_map_is(&map, MAP3));
-
-	/* Eight to expire, from 10042. Now at 10042 + 30: */
-	OSMO_ASSERT(expiry_tick(&expiry, 10042 + 30) == 8);
-	OSMO_ASSERT(nr_map_is(&map, ""));
-
-#undef MAP1
-#undef MAP2
-#undef MAP3
-}
-
-char resolve_ggsn_got_imsi[GSM23003_IMSI_MAX_DIGITS+1];
-char resolve_ggsn_got_ni[GSM_APN_LENGTH];
-
-struct osmo_sockaddr resolved_ggsn_addr;
-static int resolve_to_ggsn(const char *addr, uint16_t port)
-{
-	LVL2_ASSERT(osmo_sockaddr_init_udp(&resolved_ggsn_addr,
-					   addr, port)
-		    == 0);
-	return 1;
-}
-
-struct osmo_sockaddr resolved_sgsn_addr;
-static int resolve_to_sgsn(const char *addr, uint16_t port)
-{
-	LVL2_ASSERT(osmo_sockaddr_init_udp(&resolved_sgsn_addr,
-					   addr, port)
-		    == 0);
-	return 1;
-}
-
-struct osmo_sockaddr sgsn_sender;
-static int send_from_sgsn(const char *addr, uint16_t port)
-{
-	LVL2_ASSERT(osmo_sockaddr_init_udp(&sgsn_sender,
-					   addr, port)
-		    == 0);
-	return 1;
-}
-
-struct osmo_sockaddr ggsn_sender;
-static int send_from_ggsn(const char *addr, uint16_t port)
-{
-	LVL2_ASSERT(osmo_sockaddr_init_udp(&ggsn_sender,
-					   addr, port)
-		    == 0);
-	return 1;
-}
-
-
-/* override, requires '-Wl,--wrap=gtphub_resolve_ggsn_addr' */
-struct gtphub_peer_port *__real_gtphub_resolve_ggsn_addr(struct gtphub *hub,
-							 const char *imsi_str,
-							 const char *apn_ni_str);
-
-struct gtphub_peer_port *__wrap_gtphub_resolve_ggsn_addr(struct gtphub *hub,
-							 const char *imsi_str,
-							 const char *apn_ni_str)
-{
-	struct gsn_addr resolved_gsna;
-	uint16_t resolved_port;
-
-	OSMO_ASSERT(gsn_addr_from_sockaddr(&resolved_gsna, &resolved_port,
-					   &resolved_ggsn_addr) == 0);
-
-	struct gtphub_peer_port *pp;
-	pp = gtphub_port_have(hub, &hub->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL],
-			      &resolved_gsna, resolved_port);
-	printf("- __wrap_gtphub_resolve_ggsn_addr():\n"
-	       "  returning GGSN addr from imsi %s ni %s: %s\n",
-	       imsi_str, apn_ni_str, gtphub_port_str(pp));
-
-	if (!imsi_str)
-		imsi_str = "(null)";
-	osmo_strlcpy(resolve_ggsn_got_imsi, imsi_str,
-		     sizeof(resolve_ggsn_got_imsi));
-
-	if (!apn_ni_str)
-		apn_ni_str = "(null)";
-	osmo_strlcpy(resolve_ggsn_got_ni, apn_ni_str,
-		     sizeof(resolve_ggsn_got_ni));
-
-	return pp;
-}
-
-#define was_resolved_for(IMSI,NI) _was_resolved_for(IMSI, NI, __FILE__, __LINE__)
-static int _was_resolved_for(const char *imsi, const char *ni, const char
-			     *file, int line)
-{
-	int cmp0 = strncmp(imsi, resolve_ggsn_got_imsi,
-			   sizeof(resolve_ggsn_got_imsi));
-
-	if (cmp0 != 0) {
-		printf("\n%s:%d: was_resolved_for(): MISMATCH for IMSI\n"
-		       "  expecting: '%s'\n"
-		       "        got: '%s'\n\n",
-		       file,
-		       line,
-		       imsi, resolve_ggsn_got_imsi);
-	}
-
-	int cmp1 = strncmp(ni, resolve_ggsn_got_ni,
-			   sizeof(resolve_ggsn_got_ni));
-	if (cmp1 != 0) {
-		printf("\n%s:%d: was_resolved_for(): MISMATCH for NI\n"
-		       "  expecting: '%s'\n"
-		       "        got: '%s'\n\n",
-		       file,
-		       line,
-		       ni, resolve_ggsn_got_ni);
-	}
-
-	return (cmp0 == 0) && (cmp1 == 0);
-}
-
-/* override, requires '-Wl,--wrap=gtphub_ares_init' */
-int __real_gtphub_ares_init(struct gtphub *hub);
-
-int __wrap_gtphub_ares_init(struct gtphub *hub)
-{
-	/* Do nothing. */
-	return 0;
-}
-
-/* override, requires '-Wl,--wrap=gtphub_write' */
-int __real_gtphub_write(const struct osmo_fd *to,
-			const struct osmo_sockaddr *to_addr,
-			const uint8_t *buf, size_t buf_len);
-
-int __wrap_gtphub_write(const struct osmo_fd *to,
-			const struct osmo_sockaddr *to_addr,
-			const uint8_t *buf, size_t buf_len)
-{
-	printf("Out-of-band gtphub_write(%d):\n"
-	       "to %s\n"
-	       "%s\n",
-	       (int)buf_len,
-	       osmo_sockaddr_to_str(to_addr),
-	       osmo_hexdump(buf, buf_len));
-	return 0;
-}
-
-#define buf_len 1024
-static uint8_t buf[buf_len];
-static uint8_t *reply_buf;
-
-static unsigned int msg(const char *hex)
-{
-	unsigned int l = osmo_hexparse(hex, buf, buf_len);
-	OSMO_ASSERT(l > 0);
-	return l;
-}
-
-/* Compare static buf to given string constant. The amount of bytes is obtained
- * from parsing the GTP header in buf.  hex must match an osmo_hexdump() of the
- * desired message. Return 1 if size and content match. */
-#define reply_is(MSG) _reply_is(MSG, __FILE__, __LINE__)
-static int _reply_is(const char *hex, const char *file, int line)
-{
-	struct gtp1_header_long *h = (void*)reply_buf;
-	int len = ntoh16(h->length) + 8;
-	const char *dump = osmo_hexdump_nospc(reply_buf, len);
-	int cmp = strcmp(dump, hex);
-
-	if (cmp != 0) {
-		printf("\n%s:%d: reply_is(): MISMATCH\n"
-		       "  expecting:\n'%s'\n"
-		       "        got:\n'%s'\n\n",
-		       file,
-		       line,
-		       hex, dump);
-		int i;
-		int l = strlen(hex);
-		int m = strlen(dump);
-		if (m < l)
-			l = m;
-		for (i = 0; i < l; i++) {
-			if (hex[i] != dump[i]) {
-				printf("First mismatch at position %d:\n"
-				       "  %s\n  %s\n", i, hex + i, dump + i);
-				break;
-			}
-		}
-	}
-	return cmp == 0;
-}
-
-#define same_addr(GOT, EXPECTED) _same_addr((GOT),(EXPECTED), __FILE__, __LINE__)
-static int _same_addr(const struct osmo_sockaddr *got,
-		      const struct osmo_sockaddr *expected,
-		      const char *file, int line)
-{
-	int cmp = osmo_sockaddr_cmp(got, expected);
-	if (!cmp)
-		return 1;
-	char buf[256];
-	printf("\n%s:%d: addr_is(): MISMATCH\n"
-	       "  expecting: '%s'\n"
-	       "        got: '%s'\n\n",
-	       file, line,
-	       osmo_sockaddr_to_str(expected),
-	       osmo_sockaddr_to_strb(got, buf, sizeof(buf)));
-	return 0;
-}
-
-
-time_t now;
-static struct gtphub _hub;
-static struct gtphub *hub = &_hub;
-
-static int setup_test_hub()
-{
-	/* Not really needed, but to make 100% sure... */
-	ZERO_STRUCT(hub);
-
-	gtphub_init(hub);
-
-	/* Tell this mock gtphub its local address for this test. */
-	LVL2_ASSERT(gsn_addr_from_str(&hub->to_gsns[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].local_addr,
-				      "127.0.1.1") == 0);
-	LVL2_ASSERT(gsn_addr_from_str(&hub->to_gsns[GTPH_SIDE_SGSN][GTPH_PLANE_USER].local_addr,
-				      "127.0.1.2") == 0);
-	LVL2_ASSERT(gsn_addr_from_str(&hub->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].local_addr,
-				      "127.0.2.1") == 0);
-	LVL2_ASSERT(gsn_addr_from_str(&hub->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_USER].local_addr,
-				      "127.0.2.2") == 0);
-
-	hub->restart_counter = 0x23;
-	now = 345;
-	LVL2_ASSERT(send_from_sgsn("192.168.42.23", 423));
-	LVL2_ASSERT(resolve_to_ggsn("192.168.43.34", 2123));
-	LVL2_ASSERT(send_from_ggsn("192.168.43.34", 434));
-	LVL2_ASSERT(resolve_to_sgsn("192.168.42.23", 2123));
-
-#define GGSNS_CTRL_FD 1
-#define GGSNS_USER_FD 2
-#define SGSNS_CTRL_FD 3
-#define SGSNS_USER_FD 4
-	hub->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL].ofd.priv_nr = GGSNS_CTRL_FD;
-	hub->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_USER].ofd.priv_nr = GGSNS_USER_FD;
-	hub->to_gsns[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL].ofd.priv_nr = SGSNS_CTRL_FD;
-	hub->to_gsns[GTPH_SIDE_SGSN][GTPH_PLANE_USER].ofd.priv_nr = SGSNS_USER_FD;
-
-	return 1;
-}
-
-static int clear_test_hub()
-{
-	/* expire all */
-	gtphub_gc(hub, now + (60 * GTPH_EXPIRE_SLOWLY_MINUTES) + 1);
-
-	int plane_idx;
-	plane_idx = GTPH_PLANE_CTRL;
-	LVL2_ASSERT(llist_empty(&hub->to_gsns[GTPH_SIDE_GGSN][plane_idx].peers));
-	LVL2_ASSERT(llist_empty(&hub->to_gsns[GTPH_SIDE_SGSN][plane_idx].peers));
-	plane_idx = GTPH_PLANE_USER;
-	LVL2_ASSERT(llist_empty(&hub->to_gsns[GTPH_SIDE_GGSN][plane_idx].peers));
-	LVL2_ASSERT(llist_empty(&hub->to_gsns[GTPH_SIDE_SGSN][plane_idx].peers));
-
-	LVL2_ASSERT(llist_empty(&hub->tunnels));
-	LVL2_ASSERT(llist_empty(&hub->pending_deletes));
-	LVL2_ASSERT(llist_empty(&hub->ggsn_lookups));
-	LVL2_ASSERT(llist_empty(&hub->resolved_ggsns));
-
-	gtphub_free(hub);
-	return 1;
-}
-
-static int tunnels_are(const char *expect)
-{
-	static char buf[4096];
-	char *pos = buf;
-	size_t len = sizeof(buf);
-	struct gtphub_tunnel *t;
-	llist_for_each_entry(t, &hub->tunnels, entry) {
-		size_t wrote = snprintf(pos, len, "%s @%d\n",
-					gtphub_tunnel_str(t),
-					(int)t->expiry_entry.expiry);
-		LVL2_ASSERT(wrote < len);
-		pos += wrote;
-		len -= wrote;
-	}
-	*pos = '\0';
-
-	if (strncmp(buf, expect, sizeof(buf)) != 0) {
-		fprintf(stderr, "FAILURE: tunnels_are() mismatches expected value:\n"
-		       "EXPECTED:\n%s\n"
-		       "IS:\n%s\n",
-		       expect, buf);
-		LVL2_ASSERT("tunnels do not match expected listing.");
-		return 0;
-	}
-	return 1;
-}
-
-static void test_echo(void)
-{
-	LOG("test_echo");
-	OSMO_ASSERT(setup_test_hub());
-
-	now = 123;
-
-	struct osmo_fd *to_ofd;
-	struct osmo_sockaddr to_addr;
-	struct gtphub_peer_port *pp;
-	int send;
-
-	const char *gtp_ping_from_sgsn =
-		"32"	/* 0b001'1 0010: version 1, protocol GTP, with seq nr */
-		"01"	/* type 01: Echo request */
-		"0004"	/* length of 4 after header TEI */
-		"00000000" /* header TEI == 0 in Echo */
-		"abcd"	/* some 2 octet sequence nr */
-		"0000"	/* N-PDU 0, no extension header (why is this here?) */
-		;
-
-	const char *gtp_pong_to_sgsn =
-		"32"
-		"02"	/* type 02: Echo response */
-		"0006"	/* length of 6 after header TEI */
-		"00000000" /* header TEI == 0 in Echo */
-		"abcd"	/* same sequence nr */
-		"0000"
-		"0e23"	/* Recovery with restart counter */
-		;
-
-	to_ofd = NULL;
-	ZERO_STRUCT(&to_addr);
-	send = gtphub_handle_buf(hub, GTPH_SIDE_SGSN, GTPH_PLANE_CTRL,
-				 &sgsn_sender, buf, msg(gtp_ping_from_sgsn),
-				 now, &reply_buf, &to_ofd, &to_addr);
-	OSMO_ASSERT(send > 0);
-	OSMO_ASSERT(to_addr.l);
-	OSMO_ASSERT(same_addr(&to_addr, &sgsn_sender));
-	OSMO_ASSERT(to_ofd && (to_ofd->priv_nr == SGSNS_CTRL_FD));
-	OSMO_ASSERT(reply_is(gtp_pong_to_sgsn));
-
-	pp = gtphub_port_find_sa(&hub->to_gsns[GTPH_SIDE_SGSN][GTPH_PLANE_CTRL],
-				 &sgsn_sender);
-	/* We don't record Echo peers. */
-	OSMO_ASSERT(!pp);
-
-	const char *gtp_ping_from_ggsn =
-		"32"	/* 0b001'1 0010: version 1, protocol GTP, with seq nr */
-		"01"	/* type 01: Echo request */
-		"0004"	/* length of 4 after header TEI */
-		"00000000" /* header TEI == 0 in Echo */
-		"cdef"	/* some 2 octet sequence nr */
-		"0000"	/* N-PDU 0, no extension header (why is this here?) */
-		;
-
-	const char *gtp_pong_to_ggsn =
-		"32"
-		"02"	/* type 02: Echo response */
-		"0006"	/* length of 6 after header TEI */
-		"00000000" /* header TEI == 0 in Echo */
-		"cdef"	/* same sequence nr */
-		"0000"
-		"0e23"	/* Recovery with restart counter */
-		;
-
-	to_ofd = NULL;
-	ZERO_STRUCT(&to_addr);
-	send = gtphub_handle_buf(hub, GTPH_SIDE_GGSN, GTPH_PLANE_CTRL,
-				 &ggsn_sender, buf, msg(gtp_ping_from_ggsn),
-				 now, &reply_buf, &to_ofd, &to_addr);
-	OSMO_ASSERT(send > 0);
-	OSMO_ASSERT(same_addr(&to_addr, &ggsn_sender));
-	OSMO_ASSERT(to_ofd && (to_ofd->priv_nr == GGSNS_CTRL_FD));
-	OSMO_ASSERT(reply_is(gtp_pong_to_ggsn));
-
-	pp = gtphub_port_find_sa(&hub->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL],
-				 &sgsn_sender);
-	OSMO_ASSERT(!pp);
-
-
-	/* And all the same on the user plane. */
-
-	to_ofd = NULL;
-	ZERO_STRUCT(&to_addr);
-	send = gtphub_handle_buf(hub, GTPH_SIDE_SGSN, GTPH_PLANE_USER,
-				 &sgsn_sender, buf, msg(gtp_ping_from_sgsn),
-				 now, &reply_buf, &to_ofd, &to_addr);
-	OSMO_ASSERT(send > 0);
-	OSMO_ASSERT(to_addr.l);
-	OSMO_ASSERT(same_addr(&to_addr, &sgsn_sender));
-	OSMO_ASSERT(to_ofd && (to_ofd->priv_nr == SGSNS_USER_FD));
-	OSMO_ASSERT(reply_is(gtp_pong_to_sgsn));
-
-	pp = gtphub_port_find_sa(&hub->to_gsns[GTPH_SIDE_SGSN][GTPH_PLANE_USER],
-				 &sgsn_sender);
-	OSMO_ASSERT(!pp);
-
-	to_ofd = NULL;
-	ZERO_STRUCT(&to_addr);
-	send = gtphub_handle_buf(hub, GTPH_SIDE_GGSN, GTPH_PLANE_USER,
-				 &ggsn_sender, buf, msg(gtp_ping_from_ggsn),
-				 now, &reply_buf, &to_ofd, &to_addr);
-	OSMO_ASSERT(send > 0);
-	OSMO_ASSERT(same_addr(&to_addr, &ggsn_sender));
-	OSMO_ASSERT(to_ofd && (to_ofd->priv_nr == GGSNS_USER_FD));
-	OSMO_ASSERT(reply_is(gtp_pong_to_ggsn));
-
-	pp = gtphub_port_find_sa(&hub->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_USER],
-				 &sgsn_sender);
-	OSMO_ASSERT(!pp);
-
-
-	OSMO_ASSERT(clear_test_hub());
-}
-
-
-#define MSG_PDP_CTX_REQ(len, seq, restart, imsi, tei_u, tei_c, apn, gsn_c, gsn_u) \
-		"32" 	/* 0b001'1 0010: version 1, protocol GTP, with seq nr. */ \
-		"10" 	/* type 16: Create PDP Context Request */ \
-		len	/* msg length = 8 + len (2 octets) */ \
-		"00000000" /* No TEI yet */ \
-		seq	/* Sequence nr (2 octets) */ \
-		"00"	/* N-PDU 0 */ \
-		"00"	/* No extensions */ \
-		/* IEs */ \
-		"0e" restart /* 14: Recovery (restart counter: 1 octet) */ \
-		"02"	/* 2 = IMSI */ \
-		  imsi	/* (8 octets) */ \
-		"0f01"	/* 15: Selection mode = MS provided APN, subscription not verified*/ \
-		"10"	/* 16: TEI Data I */ \
-		  tei_u	/* (4 octets) */ \
-		"11"	/* 17: TEI Control Plane */ \
-		  tei_c	/* (4 octets) */ \
-		"1400"	/* 20: NSAPI = 0*/ \
-		"1a"	/* 26: Charging Characteristics */ \
-		  "0800" \
-		"80"	/* 128: End User Address */ \
-		  "0002" /* length = 2: empty PDP Address */ \
-		  "f121" /* spare 0xf0, PDP organization 1, PDP type number 0x21 = 33 */ \
-		"83"	/* 131: Access Point Name */ \
-                  apn	/* (2 octets length, N octets encoded APN-NI) */ \
-		"84"	/* 132: Protocol Configuration Options */ \
-		  "0015" /* length = 21 */ \
-		  "80c0231101010011036d69670868656d6d656c6967" \
-		"85"	/* 133: GSN Address */ \
-		  gsn_c /* (2 octets length, N octets addr) */ \
-		"85"	/* 133: GSN Address (second entry) */ \
-		  gsn_u /* (2 octets length, N octets addr) */ \
-		"86"	/* 134: MS International PSTN/ISDN Number (MSISDN) */ \
-		  "0007" /* length */ \
-		  "916407123254f6" /* 1946702123456(f) */ \
-		"87"	/* 135: Quality of Service (QoS) Profile */ \
-		  "0004" /* length */ \
-		  "00"	/* priority */ \
-		  "0b921f" /* QoS profile data */ 
-
-#define MSG_PDP_CTX_RSP(len, tei_h, seq, restart, tei_u, tei_c, gsn_c, gsn_u) \
-		"32" \
-		"11"	/* Create PDP Context Response */ \
-		len	/* msg length = 8 + len (2 octets) */ \
-		tei_h	/* destination TEI (sent in req above) */ \
-		seq	/* mapped seq */ \
-		"00" "00" \
-		/* IEs */ \
-		"01"	/* 1: Cause */ \
-		  "80"	/* value = 0b10000000 = response, no rejection. */ \
-		"08"	/* 8: Reordering Required */ \
-		  "00"	/* not required. */ \
-		"0e" restart /* 14: Recovery */ \
-		"10"	/* 16: TEI Data I */ \
-		  tei_u \
-		"11"	/* 17: TEI Control */ \
-		  tei_c \
-		"7f"	/* 127: Charging ID */ \
-		  "00000001" \
-		"80"	/* 128: End User Address */ \
-		  "0006" /* length = 6 */ \
-		  "f121" /* spare 0xf0, PDP organization 1, PDP type number 0x21 = 33 */ \
-		  "7f000002" \
-		"84"	/* 132: Protocol Configuration Options */ \
-		  "0014" /* len = 20 */ \
-		  "8080211002000010810608080808830600000000" \
-		"85"	/* 133: GSN Address (Ctrl) */ \
-		  gsn_c \
-		"85"	/* 133: GSN Address (User) */ \
-		  gsn_u \
-		"87"	/* 135: Quality of Service (QoS) Profile */ \
-		  "0004" /* length */ \
-		  "00"	/* priority */ \
-		  "0b921f" /* QoS profile data */
-
-#define msg_from_sgsn_c(A,B,C,D) msg_from_sgsn(GTPH_PLANE_CTRL, A,B,C,D)
-#define msg_from_sgsn_u(A,B,C,D) msg_from_sgsn(GTPH_PLANE_USER, A,B,C,D)
-static int msg_from_sgsn(int plane_idx,
-			 struct osmo_sockaddr *_sgsn_sender,
-			 struct osmo_sockaddr *ggsn_receiver,
-			 const char *hex_from_sgsn,
-			 const char *hex_to_ggsn)
-{
-	struct osmo_fd *ggsn_ofd = NULL;
-	struct osmo_sockaddr ggsn_addr;
-	int send;
-	send = gtphub_handle_buf(hub, GTPH_SIDE_SGSN, plane_idx, _sgsn_sender,
-				 buf, msg(hex_from_sgsn), now,
-				 &reply_buf, &ggsn_ofd, &ggsn_addr);
-	LVL2_ASSERT(send > 0);
-	LVL2_ASSERT(same_addr(&ggsn_addr, ggsn_receiver));
-	LVL2_ASSERT(reply_is(hex_to_ggsn));
-	return 1;
-}
-
-#define msg_from_ggsn_c(A,B,C,D) msg_from_ggsn(GTPH_PLANE_CTRL, A,B,C,D)
-#define msg_from_ggsn_u(A,B,C,D) msg_from_ggsn(GTPH_PLANE_USER, A,B,C,D)
-static int msg_from_ggsn(int plane_idx,
-			 struct osmo_sockaddr *ggsn_sender,
-			 struct osmo_sockaddr *sgsn_receiver,
-			 const char *msg_from_ggsn,
-			 const char *msg_to_sgsn)
-{
-	struct osmo_fd *sgsn_ofd;
-	struct osmo_sockaddr sgsn_addr;
-	int send;
-	send = gtphub_handle_buf(hub, GTPH_SIDE_GGSN, plane_idx, ggsn_sender,
-				 buf, msg(msg_from_ggsn), now,
-				 &reply_buf, &sgsn_ofd, &sgsn_addr);
-	if (*msg_to_sgsn) {
-		LVL2_ASSERT(send > 0);
-		LVL2_ASSERT(same_addr(&sgsn_addr, sgsn_receiver));
-		LVL2_ASSERT(reply_is(msg_to_sgsn));
-	}
-	else
-		LVL2_ASSERT(send == 0);
-	return 1;
-}
-
-static int create_pdp_ctx()
-{
-	const char *gtp_req_from_sgsn =
-		MSG_PDP_CTX_REQ("0068",
-				"abcd",
-				"60",
-				"42000121436587f9",
-				"00000123",
-				"00000321",
-				"0009""08696e7465726e6574", /* "(8)internet" */
-				"0004""c0a82a17", /* same as default sgsn_sender */
-				"0004""c0a82a17"
-			       );
-	const char *gtp_req_to_ggsn =
-		MSG_PDP_CTX_REQ("0068",
-				"6d31",	/* mapped seq ("abcd") */
-				"23",
-				"42000121436587f9",
-				"00000001", /* Data I: tunnel's TEI */
-				"00000001", /* Control: tunnel's TEI */
-				"0009""08696e7465726e6574",
-				"0004""7f000201", /* replaced with gtphub's ggsn ctrl */
-				"0004""7f000202" /* replaced with gtphub's ggsn user */
-			       );
-
-	LVL2_ASSERT(msg_from_sgsn_c(&sgsn_sender,
-				    &resolved_ggsn_addr,
-				    gtp_req_from_sgsn,
-				    gtp_req_to_ggsn));
-	LVL2_ASSERT(was_resolved_for("240010123456789", "internet"));
-
-	LVL2_ASSERT(tunnels_are(
-		"TEI=1:"
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34/(uninitialized) (TEI C=0 U=0)"
-		" @21945\n"));
-
-	const char *gtp_resp_from_ggsn =
-		MSG_PDP_CTX_RSP("004e",
-				"00000001", /* destination TEI (sent in req above) */
-				"6d31", /* mapped seq */
-				"01", /* restart */
-				"00000567", /* TEI U */
-				"00000765", /* TEI C */
-				"0004""c0a82b22", /* GSN addresses */
-				"0004""c0a82b22"  /* (== resolved_ggsn_addr) */
-			       );
-	const char *gtp_resp_to_sgsn =
-		MSG_PDP_CTX_RSP("004e",
-				"00000321", /* unmapped TEI ("001") */
-				"abcd", /* unmapped seq ("6d31") */
-				"23",
-				"00000001", /* mapped TEI from GGSN ("567") */
-				"00000001", /* mapped TEI from GGSN ("765") */
-				"0004""7f000101", /* gtphub's address towards SGSNs (Ctrl) */
-				"0004""7f000102" /* gtphub's address towards SGSNs (User) */
-			       );
-	/* The response should go back to whichever port the request came from
-	 * (unmapped by sequence nr) */
-	LVL2_ASSERT(msg_from_ggsn_c(&resolved_ggsn_addr,
-				    &sgsn_sender,
-				    gtp_resp_from_ggsn,
-				    gtp_resp_to_sgsn));
-
-	return 1;
-}
-
-#define MSG_DEL_PDP_CTX_REQ(tei, seq) \
-		"32" 	/* 0b001'1 0010: version 1, protocol GTP, with seq nr. */ \
-		"14" 	/* type 20: Delete PDP Context Request */ \
-		"0008"	/* msg length = 8 + len (2 octets) */ \
-		tei	/* TEI Ctrl */ \
-		seq	/* Sequence nr (2 octets) */ \
-		"00"	/* N-PDU 0 */ \
-		"00"	/* No extensions */ \
-		/* IEs */ \
-		"13fe"  /* 19: Teardown ind = 0 */ \
-		"1400"	/* 20: NSAPI = 0*/ \
-
-#define MSG_DEL_PDP_CTX_RSP(tei, seq) \
-		"32" 	/* 0b001'1 0010: version 1, protocol GTP, with seq nr. */ \
-		"15" 	/* type 21: Delete PDP Context Response */ \
-		"0006"	/* msg length = 8 + len (2 octets) */ \
-		tei	/* TEI Ctrl */ \
-		seq	/* Sequence nr (2 octets) */ \
-		"00"	/* N-PDU 0 */ \
-		"00"	/* No extensions */ \
-		/* IEs */ \
-		"01"	/* 1: Cause */ \
-		  "80"	/* value = 0b10000000 = response, no rejection. */ \
-
-static int delete_pdp_ctx_from_sgsn(void)
-{
-	now += GTPH_EXPIRE_QUICKLY_SECS + 1;
-	gtphub_gc(hub, now);
-
-	LVL2_ASSERT(tunnels_are(
-		"TEI=1:"
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34 (TEI C=765 U=567)"
-		" @21945\n"));
-
-	/* TEI Ctrl from above and next sequence after abcd. */
-	const char *gtp_req_from_sgsn = MSG_DEL_PDP_CTX_REQ("00000001", "abce");
-	const char *gtp_req_to_ggsn = MSG_DEL_PDP_CTX_REQ("00000765", "6d32");
-
-	LVL2_ASSERT(msg_from_sgsn_c(&sgsn_sender,
-				    &resolved_ggsn_addr,
-				    gtp_req_from_sgsn,
-				    gtp_req_to_ggsn));
-
-	/* 21945 + 31 = 21976 */
-	LVL2_ASSERT(tunnels_are(
-		"TEI=1:"
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34 (TEI C=765 U=567)"
-		" @21976\n"));
-
-	const char *gtp_resp_from_ggsn =
-		MSG_DEL_PDP_CTX_RSP("00000001", "6d32");
-	const char *gtp_resp_to_sgsn =
-		MSG_DEL_PDP_CTX_RSP("00000321", "abce");
-
-	/* The response should go back to whichever port the request came from
-	 * (unmapped by sequence nr) */
-	LVL2_ASSERT(msg_from_ggsn_c(&resolved_ggsn_addr,
-				    &sgsn_sender,
-				    gtp_resp_from_ggsn,
-				    gtp_resp_to_sgsn));
-
-	LVL2_ASSERT(tunnels_are(""));
-
-	return 1;
-}
-
-static int delete_pdp_ctx_from_ggsn(void)
-{
-	now += GTPH_EXPIRE_QUICKLY_SECS + 1;
-	gtphub_gc(hub, now);
-
-	LVL2_ASSERT(tunnels_are(
-		"TEI=1:"
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34 (TEI C=765 U=567)"
-		" @21945\n"));
-
-	/* TEI Ctrl from above and next sequence after abcd. */
-	const char *gtp_req_from_ggsn = MSG_DEL_PDP_CTX_REQ("00000001", "5432");
-	const char *gtp_req_to_sgsn = MSG_DEL_PDP_CTX_REQ("00000321", "6d31");
-
-	LVL2_ASSERT(msg_from_ggsn_c(&ggsn_sender,
-				    &resolved_sgsn_addr,
-				    gtp_req_from_ggsn,
-				    gtp_req_to_sgsn));
-
-	/* 21945 + 31 = 21976 */
-	LVL2_ASSERT(tunnels_are(
-		"TEI=1:"
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34 (TEI C=765 U=567)"
-		" @21976\n"));
-
-	const char *gtp_resp_from_sgsn =
-		MSG_DEL_PDP_CTX_RSP("00000001", "6d31");
-	const char *gtp_resp_to_ggsn =
-		MSG_DEL_PDP_CTX_RSP("00000765", "5432");
-
-	/* The response should go back to whichever port the request came from
-	 * (unmapped by sequence nr) */
-	LVL2_ASSERT(msg_from_sgsn_c(&resolved_sgsn_addr,
-				    &ggsn_sender,
-				    gtp_resp_from_sgsn,
-				    gtp_resp_to_ggsn));
-
-	LVL2_ASSERT(tunnels_are(""));
-
-	return 1;
-}
-
-static void test_one_pdp_ctx(int del_from_side)
-{
-	if (del_from_side == GTPH_SIDE_SGSN)
-		LOG("test_one_pdp_ctx (del from SGSN)")
-	else	LOG("test_one_pdp_ctx (del from GGSN)");
-	OSMO_ASSERT(setup_test_hub());
-
-	OSMO_ASSERT(create_pdp_ctx());
-
-	struct gtphub_peer_port *ggsn_port =
-		gtphub_port_find_sa(&hub->to_gsns[GTPH_SIDE_GGSN][GTPH_PLANE_CTRL],
-				    &resolved_ggsn_addr);
-	OSMO_ASSERT(ggsn_port);
-	struct gtphub_peer *ggsn = ggsn_port->peer_addr->peer;
-	/* now == 345; now + 30 == 375.
-	 * seq mapping from above:
-	 *   0xabcd == 43981 (sent in the packet)
-	 *   0x6d31 == 27953 (harcoded seq mapping start val) */
-	OSMO_ASSERT(nr_map_is(&ggsn->seq_map, "(43981->27953@375), "));
-
-	/* now == 345; now + (6 * 60 * 60) == 21600 + 345 == 21945.
-	 * 0x00000321 == 801 (TEI from SGSN Ctrl)
-	 * 0x00000123 == 291 (TEI from SGSN User)
-	 * 0x00000765 == 1893 (TEI from GGSN Ctrl)
-	 * 0x00000567 == 1383 (TEI from GGSN User)
-	 * Mapped TEIs should be 1 and 2. */
-	OSMO_ASSERT(tunnels_are(
-		"TEI=1:"
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34 (TEI C=765 U=567)"
-		" @21945\n"));
-
-	if (del_from_side == GTPH_SIDE_SGSN) {
-		OSMO_ASSERT(delete_pdp_ctx_from_sgsn());
-	} else {
-		OSMO_ASSERT(delete_pdp_ctx_from_ggsn());
-	}
-	OSMO_ASSERT(tunnels_are(""));
-
-	OSMO_ASSERT(clear_test_hub());
-}
-
-static void test_user_data(void)
-{
-	LOG("test_user_data");
-
-	OSMO_ASSERT(setup_test_hub());
-
-	OSMO_ASSERT(create_pdp_ctx());
-
-	/* now == 345; now + (6 * 60 * 60) == 21600 + 345 == 21945. */
-	OSMO_ASSERT(tunnels_are(
-		"TEI=1:"
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34 (TEI C=765 U=567)"
-		" @21945\n"));
-
-	LOG("- user data starts");
-	/* Now expect default port numbers for User plane. */
-	resolve_to_ggsn("192.168.43.34", 2152);
-	resolve_to_sgsn("192.168.42.23", 2152);
-
-	/* 10 minutes later */
-	now += 600;
-
-	const char *u_from_ggsn =
-		"32" 	/* 0b001'1 0010: version 1, protocol GTP, with seq nr */
-		"ff"	/* type 255: G-PDU */
-		"0058"	/* length: 88 + 8 octets == 96 */
-		"00000001" /* mapped TEI for SGSN from create_pdp_ctx() */
-		"0070"	/* seq */
-		"0000"	/* No extensions */
-		/* User data (ICMP packet), 96 - 12 = 84 octets  */
-		"45000054daee40004001f7890a172a010a172a02080060d23f590071e3f8"
-		"4156000000007241010000000000101112131415161718191a1b1c1d1e1f"
-		"202122232425262728292a2b2c2d2e2f3031323334353637"
-		;
-	const char *u_to_sgsn =
-		"32" 	/* 0b001'1 0010: version 1, protocol GTP, with seq nr */
-		"ff"	/* type 255: G-PDU */
-		"0058"	/* length: 88 + 8 octets == 96 */
-		"00000123" /* unmapped User TEI */
-		"6d31"	/* new mapped seq */
-		"0000"
-		"45000054daee40004001f7890a172a010a172a02080060d23f590071e3f8"
-		"4156000000007241010000000000101112131415161718191a1b1c1d1e1f"
-		"202122232425262728292a2b2c2d2e2f3031323334353637"
-		;
-
-	/* This depends on create_pdp_ctx() sending resolved_sgsn_addr as GSN
-	 * Address IEs in the GGSN's Create PDP Ctx Response. */
-	OSMO_ASSERT(msg_from_ggsn_u(&ggsn_sender,
-				    &resolved_sgsn_addr,
-				    u_from_ggsn,
-				    u_to_sgsn));
-
-	/* Make sure the user plane messages have refreshed the TEI mapping
-	 * timeouts: 21945 + 600 == 22545. */
-	OSMO_ASSERT(tunnels_are(
-		"TEI=1:"
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34 (TEI C=765 U=567)"
-		" @22545\n"));
-
-	const char *u_from_sgsn =
-		"32" 	/* 0b001'1 0010: version 1, protocol GTP, with seq nr */
-		"ff"	/* type 255: G-PDU */
-		"0058"	/* length: 88 + 8 octets == 96 */
-		"00000001" /* mapped User TEI for GGSN from create_pdp_ctx() */
-		"1234"	/* unknown seq */
-		"0000"	/* No extensions */
-		/* User data (ICMP packet), 96 - 12 = 84 octets  */
-		"45000054daee40004001f7890a172a010a172a02080060d23f590071e3f8"
-		"4156000000007241010000000000101112131415161718191a1b1c1d1e1f"
-		"202122232425262728292a2b2c2d2e2f3031323334353637"
-		;
-	const char *u_to_ggsn =
-		"32" 	/* 0b001'1 0010: version 1, protocol GTP, with seq nr */
-		"ff"	/* type 255: G-PDU */
-		"0058"	/* length: 88 + 8 octets == 96 */
-		"00000567" /* unmapped User TEI */
-		"6d31"	/* unmapped seq */
-		"0000"
-		"45000054daee40004001f7890a172a010a172a02080060d23f590071e3f8"
-		"4156000000007241010000000000101112131415161718191a1b1c1d1e1f"
-		"202122232425262728292a2b2c2d2e2f3031323334353637"
-		;
-
-	OSMO_ASSERT(msg_from_sgsn_u(&sgsn_sender,
-				    &resolved_ggsn_addr,
-				    u_from_sgsn,
-				    u_to_ggsn));
-
-	/* Make sure the user plane messages have refreshed the TEI mapping
-	 * timeouts: 21945 + 600 == 22545. Both timeouts refreshed: */
-	OSMO_ASSERT(tunnels_are(
-		"TEI=1:"
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34 (TEI C=765 U=567)"
-		" @22545\n"));
-
-	OSMO_ASSERT(clear_test_hub());
-}
-
-static void test_reused_tei(void)
-{
-	LOG("test_reused_tei");
-
-	OSMO_ASSERT(setup_test_hub());
-
-	OSMO_ASSERT(create_pdp_ctx());
-
-	const char *gtp_req_from_sgsn =
-		MSG_PDP_CTX_REQ("0068",
-				"abce", /* Next seq */
-				"60",
-				"42000121436587f9",
-				"00000123", /* Same TEIs as before */
-				"00000321",
-				"0009""08696e7465726e6574", /* "(8)internet" */
-				"0004""c0a82a17", /* same as default sgsn_sender */
-				"0004""c0a82a17"
-			       );
-	const char *gtp_req_to_ggsn =
-		MSG_PDP_CTX_REQ("0068",
-				"6d32",	/* mapped seq ("abce") */
-				"23",
-				"42000121436587f9",
-				"00000002", /* mapped TEI Data I ("123") */
-				"00000002", /* mapped TEI Control ("321") */
-				"0009""08696e7465726e6574",
-				"0004""7f000201", /* replaced with gtphub's ggsn ctrl */
-				"0004""7f000202" /* replaced with gtphub's ggsn user */
-			       );
-
-	OSMO_ASSERT(msg_from_sgsn_c(&sgsn_sender,
-				    &resolved_ggsn_addr,
-				    gtp_req_from_sgsn,
-				    gtp_req_to_ggsn));
-	OSMO_ASSERT(was_resolved_for("240010123456789", "internet"));
-
-	OSMO_ASSERT(tunnels_are(
-		"TEI=2:"
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34/(uninitialized) (TEI C=0 U=0)"
-		" @21945\n"));
-
-	const char *gtp_resp_from_ggsn =
-		MSG_PDP_CTX_RSP("004e",
-				"00000002", /* destination TEI (sent in req above) */
-				"6d32", /* mapped seq */
-				"01", /* restart */
-				"00000567", /* TEI U */
-				"00000765", /* TEI C */
-				"0004""c0a82b22", /* GSN addresses */
-				"0004""c0a82b22"  /* (== resolved_ggsn_addr) */
-			       );
-	const char *gtp_resp_to_sgsn =
-		MSG_PDP_CTX_RSP("004e",
-				"00000321", /* unmapped TEI ("001") */
-				"abce", /* unmapped seq ("6d32") */
-				"23",
-				"00000002", /* mapped TEI from GGSN ("567") */
-				"00000002", /* mapped TEI from GGSN ("765") */
-				"0004""7f000101", /* gtphub's address towards SGSNs (Ctrl) */
-				"0004""7f000102" /* gtphub's address towards SGSNs (User) */
-			       );
-	/* The response should go back to whichever port the request came from
-	 * (unmapped by sequence nr) */
-	OSMO_ASSERT(msg_from_ggsn_c(&resolved_ggsn_addr,
-				    &sgsn_sender,
-				    gtp_resp_from_ggsn,
-				    gtp_resp_to_sgsn));
-
-	OSMO_ASSERT(clear_test_hub());
-}
-
-static void test_peer_restarted(void)
-{
-	LOG("test_peer_restarted");
-
-	OSMO_ASSERT(setup_test_hub());
-
-	OSMO_ASSERT(create_pdp_ctx());
-
-	now += 10;
-
-	const char *gtp_req_from_sgsn =
-		MSG_PDP_CTX_REQ("0068",
-				"1234", /* brand new seq */
-				"61",	/* DIFFERING restart counter */
-				"42000121436587f9",
-				"00000abc",
-				"00000cba",
-				"0009""08696e7465726e6574", /* "(8)internet" */
-				"0004""c0a82a17", /* same as default sgsn_sender */
-				"0004""c0a82a17"
-			       );
-	const char *gtp_req_to_ggsn =
-		MSG_PDP_CTX_REQ("0068",
-				"6d33",	/* mapped seq ("1234") */
-				"23",
-				"42000121436587f9",
-				"00000002", /* mapped TEI Data I ("123") */
-				"00000002", /* mapped TEI Control ("321") */
-				"0009""08696e7465726e6574",
-				"0004""7f000201", /* replaced with gtphub's ggsn ctrl */
-				"0004""7f000202" /* replaced with gtphub's ggsn user */
-			       );
-
-	OSMO_ASSERT(msg_from_sgsn_c(&sgsn_sender,
-				    &resolved_ggsn_addr,
-				    gtp_req_from_sgsn,
-				    gtp_req_to_ggsn));
-	OSMO_ASSERT(was_resolved_for("240010123456789", "internet"));
-
-	OSMO_ASSERT(tunnels_are(
-		"TEI=2:"
-		" 192.168.42.23 (TEI C=cba U=abc)"
-		" <-> 192.168.43.34/(uninitialized) (TEI C=0 U=0)"
-		" @21955\n"
-		"TEI=1:"
-		" (uninitialized) (TEI C=321 U=123)"
-		" <-> 192.168.43.34 (TEI C=765 U=567)"
-		" @21945\n"
-		));
-
-	const char *gtp_resp_from_ggsn =
-		MSG_PDP_CTX_RSP("004e",
-				"00000002", /* destination TEI (sent in req above) */
-				"6d33", /* mapped seq */
-				"01", /* restart */
-				"00000def", /* TEI U */
-				"00000fde", /* TEI C */
-				"0004""c0a82b22", /* GSN addresses */
-				"0004""c0a82b22"  /* (== resolved_ggsn_addr) */
-			       );
-	const char *gtp_resp_to_sgsn =
-		MSG_PDP_CTX_RSP("004e",
-				"00000cba", /* unmapped TEI ("005") */
-				"1234", /* unmapped seq ("6d32") */
-				"23",
-				"00000002", /* mapped TEI from GGSN ("567") */
-				"00000002", /* mapped TEI from GGSN ("765") */
-				"0004""7f000101", /* gtphub's address towards SGSNs (Ctrl) */
-				"0004""7f000102" /* gtphub's address towards SGSNs (User) */
-			       );
-	/* The response should go back to whichever port the request came from
-	 * (unmapped by sequence nr) */
-	OSMO_ASSERT(msg_from_ggsn_c(&resolved_ggsn_addr,
-				    &sgsn_sender,
-				    gtp_resp_from_ggsn,
-				    gtp_resp_to_sgsn));
-
-	OSMO_ASSERT(clear_test_hub());
-}
-
-static void test_peer_restarted_reusing_tei(void)
-{
-	LOG("test_peer_restarted_reusing_tei");
-
-	OSMO_ASSERT(setup_test_hub());
-
-	OSMO_ASSERT(create_pdp_ctx());
-
-	now += 10;
-
-	const char *gtp_req_from_sgsn =
-		MSG_PDP_CTX_REQ("0068",
-				"1234", /* brand new seq */
-				"61",	/* DIFFERING restart counter */
-				"42000121436587f9",
-				"00000123", /* SAME TEI */
-				"00000321",
-				"0009""08696e7465726e6574", /* "(8)internet" */
-				"0004""c0a82a17", /* same as default sgsn_sender */
-				"0004""c0a82a17"
-			       );
-	const char *gtp_req_to_ggsn =
-		MSG_PDP_CTX_REQ("0068",
-				"6d33",	/* seq 6d31 + 2, after "out-of-band" Delete PDP Ctx
-					   due to differing restart counter. */
-				"23",
-				"42000121436587f9",
-				"00000002", /* mapped TEI Data I ("123") */
-				"00000002", /* mapped TEI Control ("321") */
-				"0009""08696e7465726e6574",
-				"0004""7f000201", /* replaced with gtphub's ggsn ctrl */
-				"0004""7f000202" /* replaced with gtphub's ggsn user */
-			       );
-
-	OSMO_ASSERT(msg_from_sgsn_c(&sgsn_sender,
-				    &resolved_ggsn_addr,
-				    gtp_req_from_sgsn,
-				    gtp_req_to_ggsn));
-	OSMO_ASSERT(was_resolved_for("240010123456789", "internet"));
-
-	OSMO_ASSERT(tunnels_are(
-		"TEI=2:" /* being established after restart */
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34/(uninitialized) (TEI C=0 U=0)"
-		" @21955\n"
-		"TEI=1:" /* invalidated due to restart */
-		" (uninitialized) (TEI C=321 U=123)"
-		" <-> 192.168.43.34 (TEI C=765 U=567)"
-		" @21945\n"
-		));
-
-	/* An "out-of-band" delete request should have been sent to the GGSN
-	 * (checked by expected log output in gtphub_test.ok), and the GGSN
-	 * will (usually) send a Delete Response like this: */
-	const char *gtp_del_resp_from_ggsn =
-		MSG_DEL_PDP_CTX_RSP("00000001", "6d32");
-
-	/* For this response (due to peer restart) we expect no forwarded
-	 * message. */
-	OSMO_ASSERT(msg_from_ggsn_c(&resolved_ggsn_addr,
-				    &sgsn_sender,
-				    gtp_del_resp_from_ggsn,
-				    ""));
-
-	OSMO_ASSERT(tunnels_are(
-		"TEI=2:" /* still being established after restart */
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34/(uninitialized) (TEI C=0 U=0)"
-		" @21955\n"
-		));
-
-	const char *gtp_resp_from_ggsn =
-		MSG_PDP_CTX_RSP("004e",
-				"00000002", /* destination TEI (sent in req above) */
-				"6d33", /* mapped seq */
-				"01", /* restart */
-				"00000def", /* TEI U */
-				"00000fde", /* TEI C */
-				"0004""c0a82b22", /* GSN addresses */
-				"0004""c0a82b22"  /* (== resolved_ggsn_addr) */
-			       );
-	const char *gtp_resp_to_sgsn =
-		MSG_PDP_CTX_RSP("004e",
-				"00000321", /* unmapped TEI ("005") */
-				"1234", /* unmapped seq ("6d33") */
-				"23",
-				"00000002", /* mapped TEI from GGSN ("567") */
-				"00000002", /* mapped TEI from GGSN ("765") */
-				"0004""7f000101", /* gtphub's address towards SGSNs (Ctrl) */
-				"0004""7f000102" /* gtphub's address towards SGSNs (User) */
-			       );
-	/* The response should go back to whichever port the request came from
-	 * (unmapped by sequence nr) */
-	OSMO_ASSERT(msg_from_ggsn_c(&resolved_ggsn_addr,
-				    &sgsn_sender,
-				    gtp_resp_from_ggsn,
-				    gtp_resp_to_sgsn));
-
-	OSMO_ASSERT(tunnels_are(
-		"TEI=2:" /* still being established after restart */
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34 (TEI C=fde U=def)"
-		" @21955\n"
-		));
-
-	OSMO_ASSERT(clear_test_hub());
-}
-
-static void test_sgsn_behind_nat(void)
-{
-	LOG("test_user_data");
-
-	OSMO_ASSERT(setup_test_hub());
-	hub->sgsn_use_sender = 1; /* <-- Main difference to test_user_data() */
-	resolve_to_sgsn("192.168.42.23", 423); /* Same as sender */
-
-	OSMO_ASSERT(create_pdp_ctx());
-
-	/* now == 345; now + (6 * 60 * 60) == 21600 + 345 == 21945. */
-	OSMO_ASSERT(tunnels_are(
-		"TEI=1:"
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34 (TEI C=765 U=567)"
-		" @21945\n"));
-
-	LOG("- user data starts");
-	/* Now expect default port numbers for User plane -- except SGSN. */
-	resolve_to_ggsn("192.168.43.34", 2152);
-
-	/* 10 minutes later */
-	now += 600;
-
-	const char *u_from_ggsn =
-		"32" 	/* 0b001'1 0010: version 1, protocol GTP, with seq nr */
-		"ff"	/* type 255: G-PDU */
-		"0058"	/* length: 88 + 8 octets == 96 */
-		"00000001" /* mapped User TEI for SGSN from create_pdp_ctx() */
-		"0070"	/* seq */
-		"0000"	/* No extensions */
-		/* User data (ICMP packet), 96 - 12 = 84 octets  */
-		"45000054daee40004001f7890a172a010a172a02080060d23f590071e3f8"
-		"4156000000007241010000000000101112131415161718191a1b1c1d1e1f"
-		"202122232425262728292a2b2c2d2e2f3031323334353637"
-		;
-	const char *u_to_sgsn =
-		"32" 	/* 0b001'1 0010: version 1, protocol GTP, with seq nr */
-		"ff"	/* type 255: G-PDU */
-		"0058"	/* length: 88 + 8 octets == 96 */
-		"00000123" /* unmapped User TEI */
-		"6d31"	/* new mapped seq */
-		"0000"
-		"45000054daee40004001f7890a172a010a172a02080060d23f590071e3f8"
-		"4156000000007241010000000000101112131415161718191a1b1c1d1e1f"
-		"202122232425262728292a2b2c2d2e2f3031323334353637"
-		;
-
-	/* This depends on create_pdp_ctx() sending resolved_sgsn_addr as GSN
-	 * Address IEs in the GGSN's Create PDP Ctx Response. */
-	OSMO_ASSERT(msg_from_ggsn_u(&ggsn_sender,
-				    &resolved_sgsn_addr,
-				    u_from_ggsn,
-				    u_to_sgsn));
-
-	/* Make sure the user plane messages have refreshed the TEI mapping
-	 * timeouts: 21945 + 600 == 22545. */
-	OSMO_ASSERT(tunnels_are(
-		"TEI=1:"
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34 (TEI C=765 U=567)"
-		" @22545\n"));
-
-	const char *u_from_sgsn =
-		"32" 	/* 0b001'1 0010: version 1, protocol GTP, with seq nr */
-		"ff"	/* type 255: G-PDU */
-		"0058"	/* length: 88 + 8 octets == 96 */
-		"00000001" /* mapped User TEI for GGSN from create_pdp_ctx() */
-		"1234"	/* unknown seq */
-		"0000"	/* No extensions */
-		/* User data (ICMP packet), 96 - 12 = 84 octets  */
-		"45000054daee40004001f7890a172a010a172a02080060d23f590071e3f8"
-		"4156000000007241010000000000101112131415161718191a1b1c1d1e1f"
-		"202122232425262728292a2b2c2d2e2f3031323334353637"
-		;
-	const char *u_to_ggsn =
-		"32" 	/* 0b001'1 0010: version 1, protocol GTP, with seq nr */
-		"ff"	/* type 255: G-PDU */
-		"0058"	/* length: 88 + 8 octets == 96 */
-		"00000567" /* unmapped User TEI */
-		"6d31"	/* unmapped seq */
-		"0000"
-		"45000054daee40004001f7890a172a010a172a02080060d23f590071e3f8"
-		"4156000000007241010000000000101112131415161718191a1b1c1d1e1f"
-		"202122232425262728292a2b2c2d2e2f3031323334353637"
-		;
-
-	OSMO_ASSERT(msg_from_sgsn_u(&sgsn_sender,
-				    &resolved_ggsn_addr,
-				    u_from_sgsn,
-				    u_to_ggsn));
-
-	/* Make sure the user plane messages have refreshed the TEI mapping
-	 * timeouts: 21945 + 600 == 22545. Both timeouts refreshed: */
-	OSMO_ASSERT(tunnels_are(
-		"TEI=1:"
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34 (TEI C=765 U=567)"
-		" @22545\n"));
-
-	OSMO_ASSERT(clear_test_hub());
-}
-
-void test_parallel_context_creation(void)
-{
-	LOG("test_parallel_context_creation");
-
-	OSMO_ASSERT(setup_test_hub());
-
-	const char *gtp_req_from_sgsn1 =
-		MSG_PDP_CTX_REQ("0068",
-				"abcd",
-				"60",
-				"42000121436587f9",
-				"00000123",
-				"00000321",
-				"0009""08696e7465726e6574", /* "(8)internet" */
-				"0004""c0a82a17", /* same as default sgsn_sender */
-				"0004""c0a82a17"
-			       );
-	const char *gtp_req_to_ggsn1 =
-		MSG_PDP_CTX_REQ("0068",
-				"6d31",	/* mapped seq ("abcd") */
-				"23",
-				"42000121436587f9",
-				"00000001", /* mapped TEI Data I ("123") */
-				"00000001", /* mapped TEI Control ("321") */
-				"0009""08696e7465726e6574",
-				"0004""7f000201", /* replaced with gtphub's ggsn ctrl */
-				"0004""7f000202" /* replaced with gtphub's ggsn user */
-			       );
-
-	OSMO_ASSERT(msg_from_sgsn_c(&sgsn_sender,
-				    &resolved_ggsn_addr,
-				    gtp_req_from_sgsn1,
-				    gtp_req_to_ggsn1));
-
-	OSMO_ASSERT(tunnels_are(
-		"TEI=1:"
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34/(uninitialized) (TEI C=0 U=0)"
-		" @21945\n"));
-
-	now ++;
-
-	const char *gtp_req_from_sgsn2 =
-		MSG_PDP_CTX_REQ("0068",
-				"abce",
-				"60",
-				"42000121436588f9",
-				"00000124",
-				"00000322",
-				"0009""08696e7465726e6574", /* "(8)internet" */
-				"0004""c0a82a17", /* same as default sgsn_sender */
-				"0004""c0a82a17"
-			       );
-	const char *gtp_req_to_ggsn2 =
-		MSG_PDP_CTX_REQ("0068",
-				"6d32",	/* mapped seq ("abce") */
-				"23",
-				"42000121436588f9",
-				"00000002", /* mapped TEI Data I ("124") */
-				"00000002", /* mapped TEI Control ("322") */
-				"0009""08696e7465726e6574",
-				"0004""7f000201", /* replaced with gtphub's ggsn ctrl */
-				"0004""7f000202" /* replaced with gtphub's ggsn user */
-			       );
-
-	OSMO_ASSERT(msg_from_sgsn_c(&sgsn_sender,
-				    &resolved_ggsn_addr,
-				    gtp_req_from_sgsn2,
-				    gtp_req_to_ggsn2));
-
-	OSMO_ASSERT(tunnels_are(
-		"TEI=2:"
-		" 192.168.42.23 (TEI C=322 U=124)"
-		" <-> 192.168.43.34/(uninitialized) (TEI C=0 U=0)"
-		" @21946\n"
-		"TEI=1:"
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34/(uninitialized) (TEI C=0 U=0)"
-		" @21945\n"
-		));
-
-	now ++;
-
-	const char *gtp_resp_from_ggsn1 =
-		MSG_PDP_CTX_RSP("004e",
-				"00000001", /* destination TEI (sent in req above) */
-				"6d31", /* mapped seq */
-				"01", /* restart */
-				"00000567", /* TEI U */
-				"00000765", /* TEI C */
-				"0004""c0a82b22", /* GSN addresses */
-				"0004""c0a82b22"  /* (== resolved_ggsn_addr) */
-			       );
-	const char *gtp_resp_to_sgsn1 =
-		MSG_PDP_CTX_RSP("004e",
-				"00000321", /* unmapped TEI ("001") */
-				"abcd", /* unmapped seq ("6d31") */
-				"23",
-				"00000001", /* mapped TEI from GGSN ("567") */
-				"00000001", /* mapped TEI from GGSN ("765") */
-				"0004""7f000101", /* gtphub's address towards SGSNs (Ctrl) */
-				"0004""7f000102" /* gtphub's address towards SGSNs (User) */
-			       );
-
-	OSMO_ASSERT(msg_from_ggsn_c(&resolved_ggsn_addr,
-				    &sgsn_sender,
-				    gtp_resp_from_ggsn1,
-				    gtp_resp_to_sgsn1));
-
-	OSMO_ASSERT(tunnels_are(
-		"TEI=2:"
-		" 192.168.42.23 (TEI C=322 U=124)"
-		" <-> 192.168.43.34/(uninitialized) (TEI C=0 U=0)"
-		" @21946\n"
-		"TEI=1:"
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34 (TEI C=765 U=567)"
-		" @21947\n"
-		));
-
-	now ++;
-
-	const char *gtp_resp_from_ggsn2 =
-		MSG_PDP_CTX_RSP("004e",
-				"00000002", /* destination TEI (sent in req above) */
-				"6d32", /* mapped seq */
-				"01", /* restart */
-				"00000568", /* TEI U */
-				"00000766", /* TEI C */
-				"0004""c0a82b22", /* GSN addresses */
-				"0004""c0a82b22"  /* (== resolved_ggsn_addr) */
-			       );
-	const char *gtp_resp_to_sgsn2 =
-		MSG_PDP_CTX_RSP("004e",
-				"00000322", /* unmapped TEI ("001") */
-				"abce", /* unmapped seq ("6d31") */
-				"23",
-				"00000002", /* mapped TEI from GGSN ("567") */
-				"00000002", /* mapped TEI from GGSN ("765") */
-				"0004""7f000101", /* gtphub's address towards SGSNs (Ctrl) */
-				"0004""7f000102" /* gtphub's address towards SGSNs (User) */
-			       );
-
-	OSMO_ASSERT(msg_from_ggsn_c(&resolved_ggsn_addr,
-				    &sgsn_sender,
-				    gtp_resp_from_ggsn2,
-				    gtp_resp_to_sgsn2));
-
-	OSMO_ASSERT(tunnels_are(
-		"TEI=2:"
-		" 192.168.42.23 (TEI C=322 U=124)"
-		" <-> 192.168.43.34 (TEI C=766 U=568)"
-		" @21948\n"
-		"TEI=1:"
-		" 192.168.42.23 (TEI C=321 U=123)"
-		" <-> 192.168.43.34 (TEI C=765 U=567)"
-		" @21947\n"
-		));
-
-	OSMO_ASSERT(clear_test_hub());
-}
-
-
-static struct log_info_cat gtphub_categories[] = {
-	[DGTPHUB] = {
-		.name = "DGTPHUB",
-		.description = "GTP Hub",
-		.color = "\033[1;33m",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-};
-
-static struct log_info info = {
-	.cat = gtphub_categories,
-	.num_cat = ARRAY_SIZE(gtphub_categories),
-};
-
-int main(int argc, char **argv)
-{
-	osmo_init_logging(&info);
-	osmo_gtphub_ctx = talloc_named_const(NULL, 0, "osmo_gtphub");
-
-	test_nr_map_basic();
-	test_nr_map_wrap();
-	test_expiry();
-	test_echo();
-	test_one_pdp_ctx(GTPH_SIDE_SGSN);
-	test_one_pdp_ctx(GTPH_SIDE_GGSN);
-	test_user_data();
-	test_reused_tei();
-	test_peer_restarted();
-	test_peer_restarted_reusing_tei();
-	test_sgsn_behind_nat();
-	test_parallel_context_creation();
-	printf("Done\n");
-
-	talloc_report_full(osmo_gtphub_ctx, stderr);
-	OSMO_ASSERT(talloc_total_blocks(osmo_gtphub_ctx) == 1);
-	return 0;
-}
-
diff --git a/tests/gtphub/gtphub_test.ok b/tests/gtphub/gtphub_test.ok
deleted file mode 100644
index e60d5f2..0000000
--- a/tests/gtphub/gtphub_test.ok
+++ /dev/null
@@ -1,42 +0,0 @@
-test_echo
-test_one_pdp_ctx (del from SGSN)
-- __wrap_gtphub_resolve_ggsn_addr():
-  returning GGSN addr from imsi 240010123456789 ni internet: 192.168.43.34 port 2123
-test_one_pdp_ctx (del from GGSN)
-- __wrap_gtphub_resolve_ggsn_addr():
-  returning GGSN addr from imsi 240010123456789 ni internet: 192.168.43.34 port 2123
-test_user_data
-- __wrap_gtphub_resolve_ggsn_addr():
-  returning GGSN addr from imsi 240010123456789 ni internet: 192.168.43.34 port 2123
-- user data starts
-test_reused_tei
-- __wrap_gtphub_resolve_ggsn_addr():
-  returning GGSN addr from imsi 240010123456789 ni internet: 192.168.43.34 port 2123
-- __wrap_gtphub_resolve_ggsn_addr():
-  returning GGSN addr from imsi 240010123456789 ni internet: 192.168.43.34 port 2123
-test_peer_restarted
-- __wrap_gtphub_resolve_ggsn_addr():
-  returning GGSN addr from imsi 240010123456789 ni internet: 192.168.43.34 port 2123
-Out-of-band gtphub_write(16):
-to 192.168.43.34 port 2123
-32 14 00 08 00 00 07 65 6d 32 00 00 13 ff 14 00 
-- __wrap_gtphub_resolve_ggsn_addr():
-  returning GGSN addr from imsi 240010123456789 ni internet: 192.168.43.34 port 2123
-test_peer_restarted_reusing_tei
-- __wrap_gtphub_resolve_ggsn_addr():
-  returning GGSN addr from imsi 240010123456789 ni internet: 192.168.43.34 port 2123
-Out-of-band gtphub_write(16):
-to 192.168.43.34 port 2123
-32 14 00 08 00 00 07 65 6d 32 00 00 13 ff 14 00 
-- __wrap_gtphub_resolve_ggsn_addr():
-  returning GGSN addr from imsi 240010123456789 ni internet: 192.168.43.34 port 2123
-test_user_data
-- __wrap_gtphub_resolve_ggsn_addr():
-  returning GGSN addr from imsi 240010123456789 ni internet: 192.168.43.34 port 2123
-- user data starts
-test_parallel_context_creation
-- __wrap_gtphub_resolve_ggsn_addr():
-  returning GGSN addr from imsi 240010123456789 ni internet: 192.168.43.34 port 2123
-- __wrap_gtphub_resolve_ggsn_addr():
-  returning GGSN addr from imsi 240010123456889 ni internet: 192.168.43.34 port 2123
-Done
diff --git a/tests/legacy_mgcp/Makefile.am b/tests/legacy_mgcp/Makefile.am
new file mode 100644
index 0000000..e5f6888
--- /dev/null
+++ b/tests/legacy_mgcp/Makefile.am
@@ -0,0 +1,77 @@
+AM_CPPFLAGS = \
+	$(all_includes) \
+	-I$(top_srcdir)/include \
+	-I$(top_srcdir) \
+	$(NULL)
+
+AM_CFLAGS = \
+	-Wall \
+	-ggdb3 \
+	$(LIBOSMOCORE_CFLAGS) \
+	$(LIBOSMONETIF_CFLAGS) \
+	$(LIBBCG729_CFLAGS) \
+	$(COVERAGE_CFLAGS) \
+	$(NULL)
+
+AM_LDFLAGS = \
+	$(COVERAGE_LDFLAGS) \
+	$(NULL)
+
+EXTRA_DIST = \
+	mgcp_test.ok \
+	mgcp_transcoding_test.ok \
+	mgcpgw_client_test.ok \
+	mgcpgw_client_test.err \
+	$(NULL)
+
+noinst_PROGRAMS = \
+	mgcp_test \
+	mgcpgw_client_test \
+	$(NULL)
+if BUILD_MGCP_TRANSCODING
+noinst_PROGRAMS += \
+	mgcp_transcoding_test \
+	$(NULL)
+endif
+
+mgcp_test_SOURCES = \
+	mgcp_test.c \
+	$(NULL)
+
+mgcp_test_LDADD = \
+	$(top_builddir)/src/libosmo-legacy-mgcp/libosmo-legacy-mgcp.la \
+	$(LIBOSMOCORE_LIBS) \
+	$(LIBOSMOVTY_LIBS) \
+	$(LIBRARY_DL) \
+	$(LIBOSMONETIF_LIBS) \
+	$(LIBRARY_GSM) \
+	-lm  \
+	$(NULL)
+
+mgcp_transcoding_test_SOURCES = \
+	mgcp_transcoding_test.c \
+	$(NULL)
+
+mgcp_transcoding_test_LDADD = \
+	$(top_builddir)/src/libosmo-legacy-mgcp/libosmo-legacy-mgcp.la \
+	$(LIBOSMOCORE_LIBS) \
+	$(LIBOSMOVTY_LIBS) \
+	$(LIBBCG729_LIBS) \
+	$(LIBRARY_DL) \
+	$(LIBOSMONETIF_LIBS) \
+	$(LIBRARY_GSM) \
+	-lm \
+	$(NULL)
+
+mgcpgw_client_test_SOURCES = \
+	mgcpgw_client_test.c \
+	$(NULL)
+
+mgcpgw_client_test_LDADD = \
+	$(top_builddir)/src/libosmo-legacy-mgcp/libosmo-legacy-mgcp.la \
+	$(LIBOSMOCORE_LIBS) \
+	$(LIBOSMOVTY_LIBS) \
+	$(LIBRARY_DL) \
+	$(LIBOSMONETIF_LIBS) \
+	$(LIBRARY_GSM) \
+	$(NULL)
diff --git a/tests/legacy_mgcp/mgcp_test.c b/tests/legacy_mgcp/mgcp_test.c
new file mode 100644
index 0000000..bbb0db2
--- /dev/null
+++ b/tests/legacy_mgcp/mgcp_test.c
@@ -0,0 +1,1235 @@
+/*
+ * (C) 2011-2012,2014 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2011-2012,2014 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/>.
+ */
+#undef _GNU_SOURCE
+#define _GNU_SOURCE
+
+#include <osmocom/legacy_mgcp/mgcp.h>
+#include <osmocom/legacy_mgcp/vty.h>
+#include <osmocom/legacy_mgcp/mgcp_internal.h>
+
+#include <osmocom/core/application.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/utils.h>
+#include <string.h>
+#include <limits.h>
+#include <dlfcn.h>
+#include <time.h>
+#include <math.h>
+
+char *strline_r(char *str, char **saveptr);
+
+const char *strline_test_data =
+    "one CR\r"
+    "two CR\r"
+    "\r"
+    "one CRLF\r\n"
+    "two CRLF\r\n"
+    "\r\n"
+    "one LF\n"
+    "two LF\n"
+    "\n"
+    "mixed (4 lines)\r\r\n\n\r\n";
+
+#define EXPECTED_NUMBER_OF_LINES 13
+
+static void test_strline(void)
+{
+	char *save = NULL;
+	char *line;
+	char buf[2048];
+	int counter = 0;
+
+	osmo_strlcpy(buf, strline_test_data, sizeof(buf));
+
+	for (line = strline_r(buf, &save); line;
+	     line = strline_r(NULL, &save)) {
+		printf("line: '%s'\n", line);
+		counter++;
+	}
+
+	OSMO_ASSERT(counter == EXPECTED_NUMBER_OF_LINES);
+}
+
+#define AUEP1	"AUEP 158663169 ds/e1-1/2@172.16.6.66 MGCP 1.0\r\n"
+#define AUEP1_RET "200 158663169 OK\r\n"
+#define AUEP2	"AUEP 18983213 ds/e1-2/1@172.16.6.66 MGCP 1.0\r\n"
+#define AUEP2_RET "500 18983213 FAIL\r\n"
+#define EMPTY	"\r\n"
+#define EMPTY_RET NULL
+#define SHORT	"CRCX \r\n"
+#define SHORT_RET "510 000000 FAIL\r\n"
+
+#define MDCX_WRONG_EP "MDCX 18983213 ds/e1-3/1@172.16.6.66 MGCP 1.0\r\n"
+#define MDCX_ERR_RET "510 18983213 FAIL\r\n"
+#define MDCX_UNALLOCATED "MDCX 18983214 ds/e1-1/2@172.16.6.66 MGCP 1.0\r\n"
+#define MDCX_RET "400 18983214 FAIL\r\n"
+#define MDCX3 "MDCX 18983215 1@mgw MGCP 1.0\r\n"
+#define MDCX3_RET "200 18983215 OK\r\n"		\
+		 "I: 1\n"			\
+		 "\n"				\
+		 "v=0\r\n"			\
+		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
+		 "s=-\r\n"			\
+		 "c=IN IP4 0.0.0.0\r\n"		\
+		 "t=0 0\r\n"			\
+		 "m=audio 0 RTP/AVP 126\r\n"	\
+		 "a=rtpmap:126 AMR/8000\r\n"	\
+		 "a=ptime:20\r\n"
+#define MDCX3_FMTP_RET "200 18983215 OK\r\n"		\
+		 "I: 3\n"			\
+		 "\n"				\
+		 "v=0\r\n"			\
+		 "o=- 3 23 IN IP4 0.0.0.0\r\n"	\
+		 "s=-\r\n"			\
+		 "c=IN IP4 0.0.0.0\r\n"		\
+		 "t=0 0\r\n"			\
+		 "m=audio 0 RTP/AVP 126\r\n"	\
+		 "a=rtpmap:126 AMR/8000\r\n"	\
+		 "a=fmtp:126 0/1/2\r\n"		\
+		 "a=ptime:20\r\n"
+#define MDCX4 "MDCX 18983216 1@mgw MGCP 1.0\r\n" \
+		 "M: sendrecv\r"		\
+		 "C: 2\r\n"          \
+		 "I: 1\r\n"                    \
+		 "L: p:20, a:AMR, nt:IN\r\n"    \
+		 "\n"				\
+		 "v=0\r\n"			\
+		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
+		 "c=IN IP4 0.0.0.0\r\n"		\
+		 "t=0 0\r\n"			\
+		 "m=audio 4441 RTP/AVP 99\r\n"	\
+		 "a=rtpmap:99 AMR/8000\r\n"	\
+		 "a=ptime:40\r\n"
+#define MDCX4_RET(Ident) "200 " Ident " OK\r\n"	\
+		 "I: 1\n"			\
+		 "\n"				\
+		 "v=0\r\n"			\
+		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
+		 "s=-\r\n"			\
+		 "c=IN IP4 0.0.0.0\r\n"		\
+		 "t=0 0\r\n"			\
+		 "m=audio 0 RTP/AVP 126\r\n"	\
+		 "a=rtpmap:126 AMR/8000\r\n"	\
+		 "a=ptime:20\r\n"
+
+#define MDCX4_PT1 "MDCX 18983217 1@mgw MGCP 1.0\r\n" \
+		 "M: sendrecv\r"		\
+		 "C: 2\r\n"          \
+		 "I: 1\r\n"                    \
+		 "L: p:20-40, a:AMR, nt:IN\r\n"    \
+		 "\n"				\
+		 "v=0\r\n"			\
+		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
+		 "c=IN IP4 0.0.0.0\r\n"		\
+		 "t=0 0\r\n"			\
+		 "m=audio 4441 RTP/AVP 99\r\n"	\
+		 "a=rtpmap:99 AMR/8000\r\n"	\
+		 "a=ptime:40\r\n"
+
+#define MDCX4_PT2 "MDCX 18983218 1@mgw MGCP 1.0\r\n" \
+		 "M: sendrecv\r"		\
+		 "C: 2\r\n"          \
+		 "I: 1\r\n"                    \
+		 "L: p:20-20, a:AMR, nt:IN\r\n"    \
+		 "\n"				\
+		 "v=0\r\n"			\
+		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
+		 "c=IN IP4 0.0.0.0\r\n"		\
+		 "t=0 0\r\n"			\
+		 "m=audio 4441 RTP/AVP 99\r\n"	\
+		 "a=rtpmap:99 AMR/8000\r\n"	\
+		 "a=ptime:40\r\n"
+
+#define MDCX4_PT3 "MDCX 18983219 1@mgw MGCP 1.0\r\n" \
+		 "M: sendrecv\r"		\
+		 "C: 2\r\n"          \
+		 "I: 1\r\n"                    \
+		 "L: a:AMR, nt:IN\r\n"    \
+		 "\n"				\
+		 "v=0\r\n"			\
+		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
+		 "c=IN IP4 0.0.0.0\r\n"		\
+		 "t=0 0\r\n"			\
+		 "m=audio 4441 RTP/AVP 99\r\n"	\
+		 "a=rtpmap:99 AMR/8000\r\n"	\
+		 "a=ptime:40\r\n"
+
+#define MDCX4_SO "MDCX 18983220 1@mgw MGCP 1.0\r\n" \
+		 "M: sendonly\r"		\
+		 "C: 2\r\n"          \
+		 "I: 1\r\n"                    \
+		 "L: p:20, a:AMR, nt:IN\r\n"    \
+		 "\n"				\
+		 "v=0\r\n"			\
+		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
+		 "c=IN IP4 0.0.0.0\r\n"		\
+		 "t=0 0\r\n"			\
+		 "m=audio 4441 RTP/AVP 99\r\n"	\
+		 "a=rtpmap:99 AMR/8000\r\n"	\
+		 "a=ptime:40\r\n"
+
+#define MDCX4_RO "MDCX 18983221 1@mgw MGCP 1.0\r\n" \
+		 "M: recvonly\r"		\
+		 "C: 2\r\n"          \
+		 "I: 1\r\n"                    \
+		 "L: p:20, a:AMR, nt:IN\r\n"
+
+#define SHORT2	"CRCX 1"
+#define SHORT2_RET "510 000000 FAIL\r\n"
+#define SHORT3	"CRCX 1 1@mgw"
+#define SHORT4	"CRCX 1 1@mgw MGCP"
+#define SHORT5	"CRCX 1 1@mgw MGCP 1.0"
+
+#define CRCX	 "CRCX 2 1@mgw MGCP 1.0\r\n"	\
+		 "M: recvonly\r\n"		\
+		 "C: 2\r\n"			\
+		 "X\r\n"			\
+		 "L: p:20\r\n"		\
+		 "\r\n"				\
+		 "v=0\r\n"			\
+		 "c=IN IP4 123.12.12.123\r\n"	\
+		 "m=audio 5904 RTP/AVP 97\r\n"	\
+		 "a=rtpmap:97 GSM-EFR/8000\r\n"	\
+		 "a=ptime:40\r\n"
+
+#define CRCX_RET "200 2 OK\r\n"			\
+		 "I: 1\n"			\
+		 "\n"				\
+		 "v=0\r\n"			\
+		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
+		 "s=-\r\n"			\
+		 "c=IN IP4 0.0.0.0\r\n"		\
+		 "t=0 0\r\n"			\
+		 "m=audio 0 RTP/AVP 126\r\n"	\
+		 "a=rtpmap:126 AMR/8000\r\n"	\
+		 "a=ptime:20\r\n"
+
+#define CRCX_RET_NO_RTPMAP "200 2 OK\r\n"	\
+		 "I: 1\n"			\
+		 "\n"				\
+		 "v=0\r\n"			\
+		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
+		 "s=-\r\n"			\
+		 "c=IN IP4 0.0.0.0\r\n"		\
+		 "t=0 0\r\n"			\
+		 "m=audio 0 RTP/AVP 126\r\n"	\
+		 "a=ptime:20\r\n"
+
+#define CRCX_FMTP_RET "200 2 OK\r\n"			\
+		 "I: 3\n"			\
+		 "\n"				\
+		 "v=0\r\n"			\
+		 "o=- 3 23 IN IP4 0.0.0.0\r\n"	\
+		 "s=-\r\n"			\
+		 "c=IN IP4 0.0.0.0\r\n"		\
+		 "t=0 0\r\n"			\
+		 "m=audio 0 RTP/AVP 126\r\n"	\
+		 "a=rtpmap:126 AMR/8000\r\n"	\
+		 "a=fmtp:126 0/1/2\r\n"		\
+		 "a=ptime:20\r\n"
+
+#define CRCX_ZYN "CRCX 2 1@mgw MGCP 1.0\r"	\
+		 "M: recvonly\r"		\
+		 "C: 2\r\r"			\
+		 "v=0\r"			\
+		 "c=IN IP4 123.12.12.123\r"	\
+		 "m=audio 5904 RTP/AVP 97\r"	\
+		 "a=rtpmap:97 GSM-EFR/8000\r"
+
+#define CRCX_ZYN_RET "200 2 OK\r\n"		\
+		 "I: 2\n"			\
+		 "\n"				\
+		 "v=0\r\n"			\
+		 "o=- 2 23 IN IP4 0.0.0.0\r\n"	\
+		 "s=-\r\n"			\
+		 "c=IN IP4 0.0.0.0\r\n"		\
+		 "t=0 0\r\n"			\
+		 "m=audio 0 RTP/AVP 126\r\n"	\
+		 "a=rtpmap:126 AMR/8000\r\n"	\
+		 "a=ptime:20\r\n"
+
+#define DLCX	 "DLCX 7 1@mgw MGCP 1.0\r\n"	\
+		 "C: 2\r\n"
+
+#define DLCX_RET "250 7 OK\r\n"			\
+		 "P: PS=0, OS=0, PR=0, OR=0, PL=0, JI=0\r\n" \
+		 "X-Osmo-CP: EC TIS=0, TOS=0, TIR=0, TOR=0\r\n"
+
+#define RQNT	 "RQNT 186908780 1@mgw MGCP 1.0\r\n"	\
+		 "X: B244F267488\r\n"			\
+		 "S: D/9\r\n"
+
+#define RQNT2	 "RQNT 186908781 1@mgw MGCP 1.0\r\n"	\
+		 "X: ADD4F26746F\r\n"			\
+		 "R: D/[0-9#*](N), G/ft, fxr/t38\r\n"
+
+#define RQNT1_RET "200 186908780 OK\r\n"
+#define RQNT2_RET "200 186908781 OK\r\n"
+
+#define PTYPE_IGNORE 0 /* == default initializer */
+#define PTYPE_NONE 128
+#define PTYPE_NYI  PTYPE_NONE
+
+#define CRCX_MULT_1 "CRCX 2 1@mgw MGCP 1.0\r\n"	\
+		 "M: recvonly\r\n"		\
+		 "C: 2\r\n"			\
+		 "X\r\n"			\
+		 "L: p:20\r\n"		\
+		 "\r\n"				\
+		 "v=0\r\n"			\
+		 "c=IN IP4 123.12.12.123\r\n"	\
+		 "m=audio 5904 RTP/AVP 18 97\r\n"\
+		 "a=rtpmap:18 G729/8000\r\n"	\
+		 "a=rtpmap:97 GSM-EFR/8000\r\n"	\
+		 "a=ptime:40\r\n"
+
+#define CRCX_MULT_2 "CRCX 2 2@mgw MGCP 1.0\r\n"	\
+		 "M: recvonly\r\n"		\
+		 "C: 2\r\n"			\
+		 "X\r\n"			\
+		 "L: p:20\r\n"		\
+		 "\r\n"				\
+		 "v=0\r\n"			\
+		 "c=IN IP4 123.12.12.123\r\n"	\
+		 "m=audio 5904 RTP/AVP 18 97 101\r\n"\
+		 "a=rtpmap:18 G729/8000\r\n"	\
+		 "a=rtpmap:97 GSM-EFR/8000\r\n"	\
+		 "a=rtpmap:101 FOO/8000\r\n"	\
+		 "a=ptime:40\r\n"
+
+#define CRCX_MULT_3 "CRCX 2 3@mgw MGCP 1.0\r\n"	\
+		 "M: recvonly\r\n"		\
+		 "C: 2\r\n"			\
+		 "X\r\n"			\
+		 "L: p:20\r\n"		\
+		 "\r\n"				\
+		 "v=0\r\n"			\
+		 "c=IN IP4 123.12.12.123\r\n"	\
+		 "m=audio 5904 RTP/AVP\r\n"	\
+		 "a=rtpmap:18 G729/8000\r\n"	\
+		 "a=rtpmap:97 GSM-EFR/8000\r\n"	\
+		 "a=rtpmap:101 FOO/8000\r\n"	\
+		 "a=ptime:40\r\n"
+
+#define CRCX_MULT_4 "CRCX 2 4@mgw MGCP 1.0\r\n"	\
+		 "M: recvonly\r\n"		\
+		 "C: 2\r\n"			\
+		 "X\r\n"			\
+		 "L: p:20\r\n"		\
+		 "\r\n"				\
+		 "v=0\r\n"			\
+		 "c=IN IP4 123.12.12.123\r\n"	\
+		 "m=audio 5904 RTP/AVP 18\r\n"	\
+		 "a=rtpmap:18 G729/8000\r\n"	\
+		 "a=rtpmap:97 GSM-EFR/8000\r\n"	\
+		 "a=rtpmap:101 FOO/8000\r\n"	\
+		 "a=ptime:40\r\n"
+
+#define CRCX_MULT_GSM_EXACT \
+		"CRCX 259260421 5@mgw MGCP 1.0\r\n"	\
+		"C: 1355c6041e\r\n"			\
+		"I: 3\r\n"				\
+		"L: p:20, a:GSM, nt:IN\r\n"		\
+		"M: recvonly\r\n"			\
+		"\r\n"					\
+		"v=0\r\n"				\
+		"o=- 1439038275 1439038275 IN IP4 192.168.181.247\r\n" \
+		"s=-\r\nc=IN IP4 192.168.181.247\r\n"	\
+		"t=0 0\r\nm=audio 29084 RTP/AVP 255 0 8 3 18 4 96 97 101\r\n" \
+		"a=rtpmap:0 PCMU/8000\r\n"		\
+		"a=rtpmap:8 PCMA/8000\r\n"		\
+		"a=rtpmap:3 gsm/8000\r\n"		\
+		"a=rtpmap:18 G729/8000\r\n"		\
+		"a=fmtp:18 annexb=no\r\n"		\
+		"a=rtpmap:4 G723/8000\r\n"		\
+		"a=rtpmap:96 iLBC/8000\r\n"		\
+		"a=fmtp:96 mode=20\r\n"			\
+		"a=rtpmap:97 iLBC/8000\r\n"		\
+		"a=fmtp:97 mode=30\r\n"			\
+		"a=rtpmap:101 telephone-event/8000\r\n"	\
+		"a=fmtp:101 0-15\r\n"			\
+		"a=recvonly\r\n"
+#define MDCX_NAT_DUMMY \
+		"MDCX 23 5@mgw MGCP 1.0\r\n"		\
+		"C: 1355c6041e\r\n"			\
+		"\r\n"					\
+		"c=IN IP4 8.8.8.8\r\n"		\
+		"m=audio 16434 RTP/AVP 255\r\n"
+
+
+struct mgcp_test {
+	const char *name;
+	const char *req;
+	const char *exp_resp;
+	int exp_net_ptype;
+	int exp_bts_ptype;
+
+	const char *extra_fmtp;
+};
+
+static const struct mgcp_test tests[] = {
+	{ "AUEP1", AUEP1, AUEP1_RET },
+	{ "AUEP2", AUEP2, AUEP2_RET },
+	{ "MDCX1", MDCX_WRONG_EP, MDCX_ERR_RET },
+	{ "MDCX2", MDCX_UNALLOCATED, MDCX_RET },
+	{ "CRCX", CRCX, CRCX_RET, 97, 126 },
+	{ "MDCX3", MDCX3, MDCX3_RET, PTYPE_NONE, 126 },
+	{ "MDCX4", MDCX4, MDCX4_RET("18983216"), 99, 126 },
+	{ "MDCX4_PT1", MDCX4_PT1, MDCX4_RET("18983217"), 99, 126 },
+	{ "MDCX4_PT2", MDCX4_PT2, MDCX4_RET("18983218"), 99, 126 },
+	{ "MDCX4_PT3", MDCX4_PT3, MDCX4_RET("18983219"), 99, 126 },
+	{ "MDCX4_SO", MDCX4_SO, MDCX4_RET("18983220"), 99, 126 },
+	{ "MDCX4_RO", MDCX4_RO, MDCX4_RET("18983221"), PTYPE_IGNORE, 126 },
+	{ "DLCX", DLCX, DLCX_RET, -1, -1 },
+	{ "CRCX_ZYN", CRCX_ZYN, CRCX_ZYN_RET, 97, 126 },
+	{ "EMPTY", EMPTY, EMPTY_RET },
+	{ "SHORT1", SHORT, SHORT_RET },
+	{ "SHORT2", SHORT2, SHORT2_RET },
+	{ "SHORT3", SHORT3, SHORT2_RET },
+	{ "SHORT4", SHORT4, SHORT2_RET },
+	{ "RQNT1", RQNT, RQNT1_RET },
+	{ "RQNT2", RQNT2, RQNT2_RET },
+	{ "DLCX", DLCX, DLCX_RET, -1, -1 },
+	{ "CRCX", CRCX, CRCX_FMTP_RET, 97, 126, .extra_fmtp = "a=fmtp:126 0/1/2" },
+	{ "MDCX3", MDCX3, MDCX3_FMTP_RET, PTYPE_NONE, 126 , .extra_fmtp = "a=fmtp:126 0/1/2" },
+	{ "DLCX", DLCX, DLCX_RET, -1, -1 , .extra_fmtp = "a=fmtp:126 0/1/2" },
+};
+
+static const struct mgcp_test retransmit[] = {
+	{ "CRCX", CRCX, CRCX_RET },
+	{ "RQNT1", RQNT, RQNT1_RET },
+	{ "RQNT2", RQNT2, RQNT2_RET },
+	{ "MDCX3", MDCX3, MDCX3_RET },
+	{ "DLCX", DLCX, DLCX_RET },
+};
+
+static struct msgb *create_msg(const char *str)
+{
+	struct msgb *msg;
+
+	msg = msgb_alloc_headroom(4096, 128, "MGCP msg");
+	int len = sprintf((char *)msg->data, "%s", str);
+	msg->l2h = msgb_put(msg, len);
+	return msg;
+}
+
+static int last_endpoint = -1;
+
+static int mgcp_test_policy_cb(struct mgcp_trunk_config *cfg, int endpoint,
+			       int state, const char *transactio_id)
+{
+	fprintf(stderr, "Policy CB got state %d on endpoint %d\n",
+		state, endpoint);
+	last_endpoint = endpoint;
+	return MGCP_POLICY_CONT;
+}
+
+#define MGCP_DUMMY_LOAD 0x23
+static int dummy_packets = 0;
+/* override and forward */
+ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
+		const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+	typedef ssize_t (*sendto_t)(int, const void *, size_t, int,
+			const struct sockaddr *, socklen_t);
+	static sendto_t real_sendto = NULL;
+	uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr);
+	int      dest_port = htons(((struct sockaddr_in *)dest_addr)->sin_port);
+
+	if (!real_sendto)
+		real_sendto = dlsym(RTLD_NEXT, "sendto");
+
+	if (len == 1 && ((const char *)buf)[0] == MGCP_DUMMY_LOAD ) {
+		fprintf(stderr, "Dummy packet to 0x%08x:%d, msg length %zu\n%s\n\n",
+		       dest_host, dest_port,
+		       len, osmo_hexdump(buf, len));
+		dummy_packets += 1;
+	}
+
+	return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
+}
+
+static int64_t force_monotonic_time_us = -1;
+/* override and forward */
+int clock_gettime(clockid_t clk_id, struct timespec *tp)
+{
+	typedef int (*clock_gettime_t)(clockid_t clk_id, struct timespec *tp);
+	static clock_gettime_t real_clock_gettime = NULL;
+
+	if (!real_clock_gettime)
+		real_clock_gettime = dlsym(RTLD_NEXT, "clock_gettime");
+
+	if (clk_id == CLOCK_MONOTONIC && force_monotonic_time_us >= 0) {
+		tp->tv_sec = force_monotonic_time_us / 1000000;
+		tp->tv_nsec = (force_monotonic_time_us % 1000000) * 1000;
+		return 0;
+	}
+
+	return real_clock_gettime(clk_id, tp);
+}
+
+#define CONN_UNMODIFIED (0x1000)
+
+static void test_values(void)
+{
+	/* Check that NONE disables all output */
+	OSMO_ASSERT((MGCP_CONN_NONE & MGCP_CONN_RECV_SEND) == 0)
+
+	/* Check that LOOPBACK enables all output */
+	OSMO_ASSERT((MGCP_CONN_LOOPBACK & MGCP_CONN_RECV_SEND) ==
+		    MGCP_CONN_RECV_SEND)
+}
+
+
+static void test_messages(void)
+{
+	struct mgcp_config *cfg;
+	struct mgcp_endpoint *endp;
+	int i;
+
+	cfg = mgcp_config_alloc();
+
+	cfg->trunk.number_endpoints = 64;
+	mgcp_endpoints_allocate(&cfg->trunk);
+
+	cfg->policy_cb = mgcp_test_policy_cb;
+
+	mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1));
+
+	/* reset endpoints */
+	for (i = 0; i < cfg->trunk.number_endpoints; i++) {
+		endp = &cfg->trunk.endpoints[i];
+		endp->net_end.codec.payload_type = PTYPE_NONE;
+		endp->net_end.packet_duration_ms = -1;
+
+		OSMO_ASSERT(endp->conn_mode == MGCP_CONN_NONE);
+		endp->conn_mode |= CONN_UNMODIFIED;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(tests); i++) {
+		const struct mgcp_test *t = &tests[i];
+		struct msgb *inp;
+		struct msgb *msg;
+
+		printf("Testing %s\n", t->name);
+
+		last_endpoint = -1;
+		dummy_packets = 0;
+
+		osmo_talloc_replace_string(cfg, &cfg->trunk.audio_fmtp_extra, t->extra_fmtp);
+
+		inp = create_msg(t->req);
+		msg = mgcp_handle_message(cfg, inp);
+		msgb_free(inp);
+		if (!t->exp_resp) {
+			if (msg)
+				printf("%s failed '%s'\n", t->name, (char *) msg->data);
+		} else if (strcmp((char *) msg->data, t->exp_resp) != 0)
+			printf("%s failed '%s'\n", t->name, (char *) msg->data);
+		msgb_free(msg);
+
+		if (dummy_packets)
+			printf("Dummy packets: %d\n", dummy_packets);
+
+		if (last_endpoint != -1) {
+			endp = &cfg->trunk.endpoints[last_endpoint];
+
+			if (endp->net_end.packet_duration_ms != -1)
+				printf("Detected packet duration: %d\n",
+				       endp->net_end.packet_duration_ms);
+			else
+				printf("Packet duration not set\n");
+			if (endp->local_options.pkt_period_min ||
+			    endp->local_options.pkt_period_max)
+				printf("Requested packetetization period: "
+				       "%d-%d\n",
+				       endp->local_options.pkt_period_min,
+				       endp->local_options.pkt_period_max);
+			else
+				printf("Requested packetization period not set\n");
+
+			if ((endp->conn_mode & CONN_UNMODIFIED) == 0) {
+				printf("Connection mode: %d:%s%s%s%s\n",
+				       endp->conn_mode,
+				       !endp->conn_mode ? " NONE" : "",
+				       endp->conn_mode & MGCP_CONN_SEND_ONLY ?
+				       " SEND" : "",
+				       endp->conn_mode & MGCP_CONN_RECV_ONLY ?
+				       " RECV" : "",
+				       endp->conn_mode & MGCP_CONN_LOOPBACK &
+				       ~MGCP_CONN_RECV_SEND ?
+				       " LOOP" : "");
+				fprintf(stderr,
+					"BTS output %sabled, NET output %sabled\n",
+					endp->bts_end.output_enabled ? "en" : "dis",
+					endp->net_end.output_enabled ? "en" : "dis");
+			} else
+				printf("Connection mode not set\n");
+
+			OSMO_ASSERT(endp->net_end.output_enabled ==
+				    (endp->conn_mode & MGCP_CONN_SEND_ONLY ? 1 : 0));
+			OSMO_ASSERT(endp->bts_end.output_enabled ==
+				    (endp->conn_mode & MGCP_CONN_RECV_ONLY ? 1 : 0));
+
+			endp->net_end.packet_duration_ms = -1;
+			endp->local_options.pkt_period_min = 0;
+			endp->local_options.pkt_period_max = 0;
+			endp->conn_mode |= CONN_UNMODIFIED;
+		}
+
+
+		/* Check detected payload type */
+		if (t->exp_net_ptype != PTYPE_IGNORE ||
+		    t->exp_bts_ptype != PTYPE_IGNORE) {
+			OSMO_ASSERT(last_endpoint != -1);
+			endp = &cfg->trunk.endpoints[last_endpoint];
+
+			fprintf(stderr, "endpoint %d: "
+				"payload type BTS %d (exp %d), NET %d (exp %d)\n",
+				last_endpoint,
+				endp->bts_end.codec.payload_type, t->exp_bts_ptype,
+				endp->net_end.codec.payload_type, t->exp_net_ptype);
+
+			if (t->exp_bts_ptype != PTYPE_IGNORE)
+				OSMO_ASSERT(endp->bts_end.codec.payload_type ==
+					    t->exp_bts_ptype);
+			if (t->exp_net_ptype != PTYPE_IGNORE)
+				OSMO_ASSERT(endp->net_end.codec.payload_type ==
+					    t->exp_net_ptype);
+
+			/* Reset them again for next test */
+			endp->net_end.codec.payload_type = PTYPE_NONE;
+		}
+	}
+
+	talloc_free(cfg);
+}
+
+static void test_retransmission(void)
+{
+	struct mgcp_config *cfg;
+	int i;
+
+	cfg = mgcp_config_alloc();
+
+	cfg->trunk.number_endpoints = 64;
+	mgcp_endpoints_allocate(&cfg->trunk);
+
+	mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1));
+
+	/* reset endpoints */
+	for (i = 0; i < cfg->trunk.number_endpoints; i++) {
+		struct mgcp_endpoint *endp;
+		endp = &cfg->trunk.endpoints[i];
+		endp->bts_end.packet_duration_ms = 20;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(retransmit); i++) {
+		const struct mgcp_test *t = &retransmit[i];
+		struct msgb *inp;
+		struct msgb *msg;
+
+		printf("Testing %s\n", t->name);
+
+		inp = create_msg(t->req);
+		msg = mgcp_handle_message(cfg, inp);
+		msgb_free(inp);
+		if (strcmp((char *) msg->data, t->exp_resp) != 0)
+			printf("%s failed '%s'\n", t->name, (char *) msg->data);
+		msgb_free(msg);
+
+		/* Retransmit... */
+		printf("Re-transmitting %s\n", t->name);
+		inp = create_msg(t->req);
+		msg = mgcp_handle_message(cfg, inp);
+		msgb_free(inp);
+		if (strcmp((char *) msg->data, t->exp_resp) != 0)
+			printf("%s failed '%s'\n", t->name, (char *) msg->data);
+		msgb_free(msg);
+	}
+
+	talloc_free(cfg);
+}
+
+static int rqnt_cb(struct mgcp_endpoint *endp, char _tone)
+{
+	ptrdiff_t tone = _tone;
+	endp->cfg->data = (void *) tone;
+	return 0;
+}
+
+static void test_rqnt_cb(void)
+{
+	struct mgcp_config *cfg;
+	struct msgb *inp, *msg;
+
+	cfg = mgcp_config_alloc();
+	cfg->rqnt_cb = rqnt_cb;
+
+	cfg->trunk.number_endpoints = 64;
+	mgcp_endpoints_allocate(&cfg->trunk);
+
+	mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1));
+
+	inp = create_msg(CRCX);
+	msgb_free(mgcp_handle_message(cfg, inp));
+	msgb_free(inp);
+
+	/* send the RQNT and check for the CB */
+	inp = create_msg(RQNT);
+	msg = mgcp_handle_message(cfg, inp);
+	if (strncmp((const char *) msg->l2h, "200", 3) != 0) {
+		printf("FAILED: message is not 200. '%s'\n", msg->l2h);
+		abort();
+	}
+
+	if (cfg->data != (void *) '9') {
+		printf("FAILED: callback not called: %p\n", cfg->data);
+		abort();
+	}
+
+	msgb_free(msg);
+	msgb_free(inp);
+
+	inp = create_msg(DLCX);
+	msgb_free(mgcp_handle_message(cfg, inp));
+	msgb_free(inp);
+	talloc_free(cfg);
+}
+
+struct pl_test {
+	int		cycles;
+	uint16_t	base_seq;
+	uint16_t	max_seq;
+	uint32_t	packets;
+
+	uint32_t	expected;
+	int		loss;
+};
+
+static const struct pl_test pl_test_dat[] = {
+	/* basic.. just one package */
+	{ .cycles = 0, .base_seq = 0, .max_seq = 0, .packets = 1, .expected = 1, .loss = 0},
+	/* some packages and a bit of loss */
+	{ .cycles = 0, .base_seq = 0, .max_seq = 100, .packets = 100, .expected = 101, .loss = 1},
+	/* wrap around */
+	{ .cycles = 1<<16, .base_seq = 0xffff, .max_seq = 2, .packets = 4, .expected = 4, .loss = 0},
+	/* min loss */
+	{ .cycles = 0, .base_seq = 0, .max_seq = 0, .packets = UINT_MAX, .expected = 1, .loss = INT_MIN },
+	/* max loss, with wrap around on expected max */
+	{ .cycles = INT_MAX, .base_seq = 0, .max_seq = UINT16_MAX, .packets = 0, .expected = ((uint32_t)(INT_MAX) + UINT16_MAX + 1), .loss = INT_MAX }, 
+};
+
+static void test_packet_loss_calc(void)
+{
+	int i;
+	printf("Testing packet loss calculation.\n");
+
+	for (i = 0; i < ARRAY_SIZE(pl_test_dat); ++i) {
+		uint32_t expected;
+		int loss;
+		struct mgcp_rtp_state state;
+		struct mgcp_rtp_end rtp;
+		memset(&state, 0, sizeof(state));
+		memset(&rtp, 0, sizeof(rtp));
+
+		state.stats_initialized = 1;
+		state.stats_base_seq = pl_test_dat[i].base_seq;
+		state.stats_max_seq = pl_test_dat[i].max_seq;
+		state.stats_cycles = pl_test_dat[i].cycles;
+
+		rtp.packets = pl_test_dat[i].packets;
+		mgcp_state_calc_loss(&state, &rtp, &expected, &loss);
+
+		if (loss != pl_test_dat[i].loss || expected != pl_test_dat[i].expected) {
+			printf("FAIL: Wrong exp/loss at idx(%d) Loss(%d vs. %d) Exp(%u vs. %u)\n",
+				i, loss, pl_test_dat[i].loss,
+				expected, pl_test_dat[i].expected);
+		}
+	}
+}
+
+static void test_mgcp_stats(void)
+{
+	printf("Testing stat parsing\n");
+
+	uint32_t bps, bos, pr, _or, jitter;
+	struct msgb *msg;
+	int loss;
+	int rc;
+
+	msg = create_msg(DLCX_RET);
+	rc = mgcp_parse_stats(msg, &bps, &bos, &pr, &_or, &loss, &jitter);
+	printf("Parsing result: %d\n", rc);
+	if (bps != 0 || bos != 0 || pr != 0 ||  _or != 0 || loss != 0 || jitter != 0)
+		printf("FAIL: Parsing failed1.\n");
+	msgb_free(msg);
+
+	msg = create_msg("250 7 OK\r\nP: PS=10, OS=20, PR=30, OR=40, PL=-3, JI=40\r\n");
+	rc = mgcp_parse_stats(msg, &bps, &bos, &pr, &_or, &loss, &jitter);
+	printf("Parsing result: %d\n", rc);
+	if (bps != 10 || bos != 20 || pr != 30 || _or != 40 || loss != -3 || jitter != 40)
+		printf("FAIL: Parsing failed2.\n");
+	msgb_free(msg);
+}
+
+struct rtp_packet_info {
+	float txtime;
+	int len;
+	char *data;
+};
+
+struct rtp_packet_info test_rtp_packets1[] = {
+	/* RTP: SeqNo=0, TS=0 */
+	{0.000000, 20, "\x80\x62\x00\x00\x00\x00\x00\x00\x11\x22\x33\x44"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=1, TS=160 */
+	{0.020000, 20, "\x80\x62\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=2, TS=320 */
+	{0.040000, 20, "\x80\x62\x00\x02\x00\x00\x01\x40\x11\x22\x33\x44"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* Repeat RTP timestamp: */
+	/* RTP: SeqNo=3, TS=320 */
+	{0.060000, 20, "\x80\x62\x00\x03\x00\x00\x01\x40\x11\x22\x33\x44"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=4, TS=480 */
+	{0.080000, 20, "\x80\x62\x00\x04\x00\x00\x01\xE0\x11\x22\x33\x44"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=5, TS=640 */
+	{0.100000, 20, "\x80\x62\x00\x05\x00\x00\x02\x80\x11\x22\x33\x44"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* Double skip RTP timestamp (delta = 2*160): */
+	/* RTP: SeqNo=6, TS=960 */
+	{0.120000, 20, "\x80\x62\x00\x06\x00\x00\x03\xC0\x11\x22\x33\x44"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=7, TS=1120 */
+	{0.140000, 20, "\x80\x62\x00\x07\x00\x00\x04\x60\x11\x22\x33\x44"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=8, TS=1280 */
+	{0.160000, 20, "\x80\x62\x00\x08\x00\x00\x05\x00\x11\x22\x33\x44"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* Non 20ms RTP timestamp (delta = 120): */
+	/* RTP: SeqNo=9, TS=1400 */
+	{0.180000, 20, "\x80\x62\x00\x09\x00\x00\x05\x78\x11\x22\x33\x44"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=10, TS=1560 */
+	{0.200000, 20, "\x80\x62\x00\x0A\x00\x00\x06\x18\x11\x22\x33\x44"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=11, TS=1720 */
+	{0.220000, 20, "\x80\x62\x00\x0B\x00\x00\x06\xB8\x11\x22\x33\x44"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* SSRC changed to 0x10203040, RTP timestamp jump */
+	/* RTP: SeqNo=12, TS=34688 */
+	{0.240000, 20, "\x80\x62\x00\x0C\x00\x00\x87\x80\x10\x20\x30\x40"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=13, TS=34848 */
+	{0.260000, 20, "\x80\x62\x00\x0D\x00\x00\x88\x20\x10\x20\x30\x40"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=14, TS=35008 */
+	{0.280000, 20, "\x80\x62\x00\x0E\x00\x00\x88\xC0\x10\x20\x30\x40"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* Non 20ms RTP timestamp (delta = 120): */
+	/* RTP: SeqNo=15, TS=35128 */
+	{0.300000, 20, "\x80\x62\x00\x0F\x00\x00\x89\x38\x10\x20\x30\x40"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=16, TS=35288 */
+	{0.320000, 20, "\x80\x62\x00\x10\x00\x00\x89\xD8\x10\x20\x30\x40"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=17, TS=35448 */
+	{0.340000, 20, "\x80\x62\x00\x11\x00\x00\x8A\x78\x10\x20\x30\x40"
+		       "\x01\x23\x45\x67\x8A\xAB\xCD\xEF"},
+	/* SeqNo increment by 2, RTP timestamp delta = 320: */
+	/* RTP: SeqNo=19, TS=35768 */
+	{0.360000, 20, "\x80\x62\x00\x13\x00\x00\x8B\xB8\x10\x20\x30\x40"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=20, TS=35928 */
+	{0.380000, 20, "\x80\x62\x00\x14\x00\x00\x8C\x58\x10\x20\x30\x40"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=21, TS=36088 */
+	{0.380000, 20, "\x80\x62\x00\x15\x00\x00\x8C\xF8\x10\x20\x30\x40"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* Repeat last packet */
+	/* RTP: SeqNo=21, TS=36088 */
+	{0.400000, 20, "\x80\x62\x00\x15\x00\x00\x8C\xF8\x10\x20\x30\x40"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=22, TS=36248 */
+	{0.420000, 20, "\x80\x62\x00\x16\x00\x00\x8D\x98\x10\x20\x30\x40"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=23, TS=36408 */
+	{0.440000, 20, "\x80\x62\x00\x17\x00\x00\x8E\x38\x10\x20\x30\x40"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* Don't increment SeqNo but increment timestamp by 160 */
+	/* RTP: SeqNo=23, TS=36568 */
+	{0.460000, 20, "\x80\x62\x00\x17\x00\x00\x8E\xD8\x10\x20\x30\x40"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=24, TS=36728 */
+	{0.480000, 20, "\x80\x62\x00\x18\x00\x00\x8F\x78\x10\x20\x30\x40"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=25, TS=36888 */
+	{0.500000, 20, "\x80\x62\x00\x19\x00\x00\x90\x18\x10\x20\x30\x40"
+		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* SSRC changed to 0x50607080, RTP timestamp jump, Delay of 1.5s,
+	 * SeqNo jump */
+	/* RTP: SeqNo=1000, TS=160000 */
+	{2.000000, 20, "\x80\x62\x03\xE8\x00\x02\x71\x00\x50\x60\x70\x80"
+			"\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=1001, TS=160160 */
+	{2.020000, 20, "\x80\x62\x03\xE9\x00\x02\x71\xA0\x50\x60\x70\x80"
+			"\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+	/* RTP: SeqNo=1002, TS=160320 */
+	{2.040000, 20, "\x80\x62\x03\xEA\x00\x02\x72\x40\x50\x60\x70\x80"
+			"\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+};
+
+void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
+			  struct mgcp_rtp_end *rtp_end, struct sockaddr_in *addr,
+			  char *data, int len);
+
+static void test_packet_error_detection(int patch_ssrc, int patch_ts)
+{
+	int i;
+
+	struct mgcp_trunk_config trunk;
+	struct mgcp_endpoint endp;
+	struct mgcp_rtp_state state;
+	struct mgcp_rtp_end *rtp = &endp.net_end;
+	struct sockaddr_in addr = {0};
+	char buffer[4096];
+	uint32_t last_ssrc = 0;
+	uint32_t last_timestamp = 0;
+	uint32_t last_seqno = 0;
+	int last_in_ts_err_cnt = 0;
+	int last_out_ts_err_cnt = 0;
+
+	printf("Testing packet error detection%s%s.\n",
+	       patch_ssrc ? ", patch SSRC" : "",
+	       patch_ts ? ", patch timestamps" : "");
+
+	memset(&trunk, 0, sizeof(trunk));
+	memset(&endp, 0, sizeof(endp));
+	memset(&state, 0, sizeof(state));
+
+	trunk.number_endpoints = 1;
+	trunk.endpoints = &endp;
+	trunk.force_constant_ssrc = patch_ssrc;
+	trunk.force_aligned_timing = patch_ts;
+
+	endp.tcfg = &trunk;
+
+	mgcp_initialize_endp(&endp);
+
+	rtp->codec.payload_type = 98;
+
+	for (i = 0; i < ARRAY_SIZE(test_rtp_packets1); ++i) {
+		struct rtp_packet_info *info = test_rtp_packets1 + i;
+
+		force_monotonic_time_us = round(1000000.0 * info->txtime);
+
+		OSMO_ASSERT(info->len <= sizeof(buffer));
+		OSMO_ASSERT(info->len >= 0);
+		memmove(buffer, info->data, info->len);
+
+		mgcp_rtp_end_config(&endp, 1, rtp);
+
+		mgcp_patch_and_count(&endp, &state, rtp, &addr,
+				     buffer, info->len);
+
+		if (state.out_stream.ssrc != last_ssrc) {
+			printf("Output SSRC changed to %08x\n",
+			       state.out_stream.ssrc);
+			last_ssrc = state.out_stream.ssrc;
+		}
+
+		printf("In TS: %d, dTS: %d, Seq: %d\n",
+		       state.in_stream.last_timestamp,
+		       state.in_stream.last_tsdelta,
+		       state.in_stream.last_seq);
+
+		printf("Out TS change: %d, dTS: %d, Seq change: %d, "
+		       "TS Err change: in %+d, out %+d\n",
+		       state.out_stream.last_timestamp - last_timestamp,
+		       state.out_stream.last_tsdelta,
+		       state.out_stream.last_seq - last_seqno,
+		       state.in_stream.err_ts_counter - last_in_ts_err_cnt,
+		       state.out_stream.err_ts_counter - last_out_ts_err_cnt);
+
+		printf("Stats: Jitter = %u, Transit = %d\n",
+		       mgcp_state_calc_jitter(&state), state.stats_transit);
+
+		last_in_ts_err_cnt = state.in_stream.err_ts_counter;
+		last_out_ts_err_cnt = state.out_stream.err_ts_counter;
+		last_timestamp = state.out_stream.last_timestamp;
+		last_seqno = state.out_stream.last_seq;
+	}
+
+	force_monotonic_time_us = -1;
+}
+
+static void test_multilple_codec(void)
+{
+	struct mgcp_config *cfg;
+	struct mgcp_endpoint *endp;
+	struct msgb *inp, *resp;
+	struct in_addr addr;
+
+	printf("Testing multiple payload types\n");
+
+	cfg = mgcp_config_alloc();
+	cfg->trunk.number_endpoints = 64;
+	mgcp_endpoints_allocate(&cfg->trunk);
+	cfg->policy_cb = mgcp_test_policy_cb;
+	mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1));
+
+	/* Allocate endpoint 1@mgw with two codecs */
+	last_endpoint = -1;
+	inp = create_msg(CRCX_MULT_1);
+	resp = mgcp_handle_message(cfg, inp);
+	msgb_free(inp);
+	msgb_free(resp);
+
+	OSMO_ASSERT(last_endpoint == 1);
+	endp = &cfg->trunk.endpoints[last_endpoint];
+	OSMO_ASSERT(endp->net_end.codec.payload_type == 18);
+	OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 97);
+
+	/* Allocate 2@mgw with three codecs, last one ignored */
+	last_endpoint = -1;
+	inp = create_msg(CRCX_MULT_2);
+	resp = mgcp_handle_message(cfg, inp);
+	msgb_free(inp);
+	msgb_free(resp);
+
+	OSMO_ASSERT(last_endpoint == 2);
+	endp = &cfg->trunk.endpoints[last_endpoint];
+	OSMO_ASSERT(endp->net_end.codec.payload_type == 18);
+	OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 97);
+
+	/* Allocate 3@mgw with no codecs, check for PT == -1 */
+	last_endpoint = -1;
+	inp = create_msg(CRCX_MULT_3);
+	resp = mgcp_handle_message(cfg, inp);
+	msgb_free(inp);
+	msgb_free(resp);
+
+	OSMO_ASSERT(last_endpoint == 3);
+	endp = &cfg->trunk.endpoints[last_endpoint];
+	OSMO_ASSERT(endp->net_end.codec.payload_type == -1);
+	OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1);
+
+	/* Allocate 4@mgw with a single codec */
+	last_endpoint = -1;
+	inp = create_msg(CRCX_MULT_4);
+	resp = mgcp_handle_message(cfg, inp);
+	msgb_free(inp);
+	msgb_free(resp);
+
+	OSMO_ASSERT(last_endpoint == 4);
+	endp = &cfg->trunk.endpoints[last_endpoint];
+	OSMO_ASSERT(endp->net_end.codec.payload_type == 18);
+	OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1);
+
+	/* Allocate 5@mgw at select GSM.. */
+	last_endpoint = -1;
+	inp = create_msg(CRCX_MULT_GSM_EXACT);
+	talloc_free(cfg->trunk.audio_name);
+	cfg->trunk.audio_name = "GSM/8000";
+	cfg->trunk.no_audio_transcoding = 1;
+	resp = mgcp_handle_message(cfg, inp);
+	msgb_free(inp);
+	msgb_free(resp);
+
+	OSMO_ASSERT(last_endpoint == 5);
+	endp = &cfg->trunk.endpoints[last_endpoint];
+	OSMO_ASSERT(endp->net_end.codec.payload_type == 3);
+	OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1);
+
+	inp = create_msg(MDCX_NAT_DUMMY);
+	last_endpoint = -1;
+	resp = mgcp_handle_message(cfg, inp);
+	msgb_free(inp);
+	msgb_free(resp);
+	OSMO_ASSERT(last_endpoint == 5);
+	endp = &cfg->trunk.endpoints[last_endpoint];
+	OSMO_ASSERT(endp->net_end.codec.payload_type == 3);
+	OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1);
+	OSMO_ASSERT(endp->net_end.rtp_port == htons(16434));
+	memset(&addr, 0, sizeof(addr));
+	inet_aton("8.8.8.8", &addr);
+	OSMO_ASSERT(endp->net_end.addr.s_addr == addr.s_addr);
+
+	/* Check what happens without that flag */
+
+	/* Free the previous endpoint and the data ... */
+	mgcp_release_endp(endp);
+	talloc_free(endp->last_response);
+	talloc_free(endp->last_trans);
+	endp->last_response = endp->last_trans = NULL;
+
+	last_endpoint = -1;
+	inp = create_msg(CRCX_MULT_GSM_EXACT);
+	cfg->trunk.no_audio_transcoding = 0;
+	resp = mgcp_handle_message(cfg, inp);
+	msgb_free(inp);
+	msgb_free(resp);
+
+	OSMO_ASSERT(last_endpoint == 5);
+	endp = &cfg->trunk.endpoints[last_endpoint];
+	OSMO_ASSERT(endp->net_end.codec.payload_type == 255);
+	OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 0);
+
+	talloc_free(cfg);
+}
+
+static void test_no_cycle(void)
+{
+	struct mgcp_config *cfg;
+	struct mgcp_endpoint *endp;
+
+	printf("Testing no sequence flow on initial packet\n");
+
+	cfg = mgcp_config_alloc();
+	cfg->trunk.number_endpoints = 64;
+	mgcp_endpoints_allocate(&cfg->trunk);
+
+	endp = &cfg->trunk.endpoints[1];
+	OSMO_ASSERT(endp->net_state.stats_initialized == 0);
+
+	mgcp_rtp_annex_count(endp, &endp->net_state, 0, 0, 2342);
+	OSMO_ASSERT(endp->net_state.stats_initialized == 1);
+	OSMO_ASSERT(endp->net_state.stats_cycles == 0);
+	OSMO_ASSERT(endp->net_state.stats_max_seq == 0);
+
+	mgcp_rtp_annex_count(endp, &endp->net_state, 1, 0, 2342);
+	OSMO_ASSERT(endp->net_state.stats_initialized == 1);
+	OSMO_ASSERT(endp->net_state.stats_cycles == 0);
+	OSMO_ASSERT(endp->net_state.stats_max_seq == 1);
+
+	/* now jump.. */
+	mgcp_rtp_annex_count(endp, &endp->net_state, UINT16_MAX, 0, 2342);
+	OSMO_ASSERT(endp->net_state.stats_initialized == 1);
+	OSMO_ASSERT(endp->net_state.stats_cycles == 0);
+	OSMO_ASSERT(endp->net_state.stats_max_seq == UINT16_MAX);
+
+	/* and wrap */
+	mgcp_rtp_annex_count(endp, &endp->net_state, 0, 0, 2342);
+	OSMO_ASSERT(endp->net_state.stats_initialized == 1);
+	OSMO_ASSERT(endp->net_state.stats_cycles == UINT16_MAX + 1);
+	OSMO_ASSERT(endp->net_state.stats_max_seq == 0);
+
+	talloc_free(cfg);
+}
+
+static void test_no_name(void)
+{
+	struct mgcp_config *cfg;
+	struct mgcp_endpoint *endp;
+	struct msgb *inp, *msg;
+	int i;
+
+	printf("Testing no rtpmap name\n");
+	cfg = mgcp_config_alloc();
+
+	cfg->trunk.number_endpoints = 64;
+	cfg->trunk.audio_send_name = 0;
+	mgcp_endpoints_allocate(&cfg->trunk);
+
+	cfg->policy_cb = mgcp_test_policy_cb;
+
+	mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1));
+
+	/* reset endpoints */
+	for (i = 0; i < cfg->trunk.number_endpoints; i++) {
+		endp = &cfg->trunk.endpoints[i];
+		endp->net_end.codec.payload_type = PTYPE_NONE;
+		endp->net_end.packet_duration_ms = -1;
+
+		OSMO_ASSERT(endp->conn_mode == MGCP_CONN_NONE);
+		endp->conn_mode |= CONN_UNMODIFIED;
+	}
+
+	inp = create_msg(CRCX);
+	msg = mgcp_handle_message(cfg, inp);
+	if (strcmp((char *) msg->data, CRCX_RET_NO_RTPMAP) != 0)
+		printf("FAILED: there should not be a RTPMAP: %s\n",
+			(char *) msg->data);
+	msgb_free(inp);
+	msgb_free(msg);
+
+	mgcp_release_endp(&cfg->trunk.endpoints[1]);
+	talloc_free(cfg);
+}
+
+static void test_osmux_cid(void)
+{
+	int id, i;
+
+	OSMO_ASSERT(osmux_used_cid() == 0);
+	id = osmux_get_cid();
+	OSMO_ASSERT(id == 0);
+	OSMO_ASSERT(osmux_used_cid() == 1);
+	osmux_put_cid(id);
+	OSMO_ASSERT(osmux_used_cid() == 0);
+
+	for (i = 0; i < 256; ++i) {
+		id = osmux_get_cid();
+		OSMO_ASSERT(id == i);
+		OSMO_ASSERT(osmux_used_cid() == i + 1);
+	}
+
+	id = osmux_get_cid();
+	OSMO_ASSERT(id == -1);
+
+	for (i = 0; i < 256; ++i)
+		osmux_put_cid(i);
+	OSMO_ASSERT(osmux_used_cid() == 0);
+}
+
+static const struct log_info_cat log_categories[] = {
+};
+
+const struct log_info log_info = {
+        .cat = log_categories,
+        .num_cat = ARRAY_SIZE(log_categories),
+};
+
+int main(int argc, char **argv)
+{
+	msgb_talloc_ctx_init(NULL, 0);
+	osmo_init_logging(&log_info);
+
+	test_strline();
+	test_values();
+	test_messages();
+	test_retransmission();
+	test_packet_loss_calc();
+	test_rqnt_cb();
+	test_mgcp_stats();
+	test_packet_error_detection(1, 0);
+	test_packet_error_detection(0, 0);
+	test_packet_error_detection(0, 1);
+	test_packet_error_detection(1, 1);
+	test_multilple_codec();
+	test_no_cycle();
+	test_no_name();
+	test_osmux_cid();
+
+	printf("Done\n");
+	return EXIT_SUCCESS;
+}
diff --git a/tests/mgcp/mgcp_test.ok b/tests/legacy_mgcp/mgcp_test.ok
similarity index 100%
rename from tests/mgcp/mgcp_test.ok
rename to tests/legacy_mgcp/mgcp_test.ok
diff --git a/tests/legacy_mgcp/mgcp_transcoding_test.c b/tests/legacy_mgcp/mgcp_transcoding_test.c
new file mode 100644
index 0000000..61de25f
--- /dev/null
+++ b/tests/legacy_mgcp/mgcp_transcoding_test.c
@@ -0,0 +1,661 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/application.h>
+
+#include <osmocom/netif/rtp.h>
+
+#include <osmocom/legacy_mgcp/mgcp.h>
+#include <osmocom/legacy_mgcp/mgcp_internal.h>
+
+#include "bscconfig.h"
+#ifndef BUILD_MGCP_TRANSCODING
+#error "Requires MGCP transcoding enabled (see --enable-mgcp-transcoding)"
+#endif
+
+#include <osmocom/legacy_mgcp/mgcp_transcode.h>
+
+uint8_t *audio_frame_l16[] = {
+};
+
+struct rtp_packets {
+	float t;
+	int len;
+	char *data;
+};
+
+struct rtp_packets audio_packets_l16[] = {
+	/* RTP: SeqNo=1, TS=160 */
+	{0.020000, 332,
+		"\x80\x0B\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
+	},
+};
+
+struct rtp_packets audio_packets_gsm[] = {
+	/* RTP: SeqNo=1, TS=160 */
+	{0.020000, 45,
+		"\x80\x03\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
+		"\xD4\x7C\xE3\xE9\x62\x50\x39\xF0\xF8\xB4\x68\xEA\x6C\x0E\x81\x1B"
+		"\x56\x2A\xD5\xBC\x69\x9C\xD1\xF0\x66\x7A\xEC\x49\x7A\x33\x3D\x0A"
+		"\xDE"
+	},
+};
+
+struct rtp_packets audio_packets_gsm_invalid_size[] = {
+	/* RTP: SeqNo=1, TS=160 */
+	{0.020000, 41,
+		"\x80\x03\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
+		"\xD4\x7C\xE3\xE9\x62\x50\x39\xF0\xF8\xB4\x68\xEA\x6C\x0E\x81\x1B"
+		"\x56\x2A\xD5\xBC\x69\x9C\xD1\xF0\x66\x7A\xEC\x49\x7A\x33\x3D\x0A"
+		"\xDE"
+	},
+};
+
+struct rtp_packets audio_packets_gsm_invalid_data[] = {
+	/* RTP: SeqNo=1, TS=160 */
+	{0.020000, 45,
+		"\x80\x03\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
+		"\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE"
+		"\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE"
+		"\xEE"
+	},
+};
+
+struct rtp_packets audio_packets_gsm_invalid_ptype[] = {
+	/* RTP: SeqNo=1, TS=160 */
+	{0.020000, 45,
+		"\x80\x08\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
+		"\xD4\x7C\xE3\xE9\x62\x50\x39\xF0\xF8\xB4\x68\xEA\x6C\x0E\x81\x1B"
+		"\x56\x2A\xD5\xBC\x69\x9C\xD1\xF0\x66\x7A\xEC\x49\x7A\x33\x3D\x0A"
+		"\xDE"
+	},
+};
+
+struct rtp_packets audio_packets_g729[] = {
+	/* RTP: SeqNo=1, TS=160 */
+	{0.020000, 32,
+		"\x80\x12\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
+		"\xAF\xC2\x81\x40\x00\xFA\xCE\xA4\x21\x7C\xC5\xC3\x4F\xA5\x98\xF5"
+		"\xB2\x95\xC4\xAD"
+	},
+};
+
+struct rtp_packets audio_packets_pcma[] = {
+	/* RTP: SeqNo=1, TS=160 */
+	{0.020000, 172,
+		"\x80\x08\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
+		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
+		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
+		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
+		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
+		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
+		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
+		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
+		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
+		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
+		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
+	},
+	/* RTP: SeqNo=26527, TS=232640 */
+	{0.020000, 92,
+		"\x80\x08\x67\x9f\x00\x03\x8c\xc0\x04\xaa\x67\x9f\xd5\xd5\xd5\xd5"
+		"\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5"
+		"\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5"
+		"\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5"
+		"\xd5\xd5\xd5\xd5\xd5\xd5\x55\x55\xd5\xd5\x55\x55\xd5\xd5\x55\x55"
+		"\xd5\xd5\xd5\x55\x55\xd5\xd5\xd5\x55\x55\xd5\xd5"
+	},
+	/* RTP: SeqNo=26528, TS=232720 */
+	{0.020000, 92,
+		"\x80\x08\x67\xa0\x00\x03\x8d\x10\x04\xaa\x67\x9f\x55\xd5\xd5\x55"
+		"\xd5\x55\xd5\xd5\xd5\x55\xd5\x55\xd5\xd5\x55\xd5\x55\xd5\x55\xd5"
+		"\x55\x55\xd5\x55\xd5\xd5\x55\x55\x55\x55\x55\xd5\xd5\x55\xd5\xd5"
+		"\xd5\x55\xd5\xd5\xd5\x55\x54\x55\xd5\xd5\x55\xd5\xd5\xd5\xd5\x55"
+		"\x54\x55\xd5\x55\xd5\x55\x55\x55\x55\x55\xd5\xd5\xd5\xd5\xd5\xd4"
+		"\xd5\x54\x55\xd5\xd4\xd5\x54\xd5\x55\xd5\xd5\xd5"
+	},
+};
+
+
+
+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);
+
+static int given_configured_endpoint(int in_samples, int out_samples,
+				const char *srcfmt, const char *dstfmt,
+				void **out_ctx, struct mgcp_endpoint **out_endp)
+{
+	int rc;
+	struct mgcp_rtp_end *dst_end;
+	struct mgcp_rtp_end *src_end;
+	struct mgcp_config *cfg;
+	struct mgcp_trunk_config *tcfg;
+	struct mgcp_endpoint *endp;
+
+	cfg = mgcp_config_alloc();
+	tcfg = talloc_zero(cfg, struct mgcp_trunk_config);
+	endp = talloc_zero(tcfg, struct mgcp_endpoint);
+
+	cfg->setup_rtp_processing_cb = mgcp_transcoding_setup;
+	cfg->rtp_processing_cb = mgcp_transcoding_process_rtp;
+	cfg->get_net_downlink_format_cb = mgcp_transcoding_net_downlink_format;
+
+	tcfg->endpoints = endp;
+	tcfg->number_endpoints = 1;
+	tcfg->cfg = cfg;
+	endp->tcfg = tcfg;
+	endp->cfg = cfg;
+	mgcp_initialize_endp(endp);
+
+	dst_end = &endp->bts_end;
+	dst_end->codec.payload_type = audio_name_to_type(dstfmt);
+
+	src_end = &endp->net_end;
+	src_end->codec.payload_type = audio_name_to_type(srcfmt);
+
+	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;
+		dst_end->force_output_ptime = 1;
+	}
+
+	rc = mgcp_transcoding_setup(endp, dst_end, src_end);
+	if (rc < 0) {
+		printf("setup failed: %s", strerror(-rc));
+		abort();
+	}
+
+	*out_ctx = cfg;
+	*out_endp = endp;
+	return 0;
+}
+
+
+static int transcode_test(const char *srcfmt, const char *dstfmt,
+			  uint8_t *src_pkts, size_t src_pkt_size)
+{
+	char buf[4096] = {0x80, 0};
+	void *ctx;
+
+	struct mgcp_rtp_end *dst_end;
+	struct mgcp_process_rtp_state *state;
+	struct mgcp_endpoint *endp;
+	int in_size;
+	const int in_samples = 160;
+	int len, cont;
+
+	printf("== Transcoding test ==\n");
+	printf("converting %s -> %s\n", srcfmt, dstfmt);
+
+	given_configured_endpoint(in_samples, 0, srcfmt, dstfmt, &ctx, &endp);
+
+	dst_end = &endp->bts_end;
+	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);
+
+	memcpy(buf, src_pkts, src_pkt_size);
+
+	len = src_pkt_size;
+
+	cont = mgcp_transcoding_process_rtp(endp, dst_end,
+					    buf, &len, sizeof(buf));
+	if (cont < 0) {
+		printf("Nothing encoded due: %s\n", strerror(-cont));
+		talloc_free(ctx);
+		return -1;
+	}
+
+	if (len < 24) {
+		printf("encoded: %s\n", osmo_hexdump((unsigned char *)buf, len));
+	} else {
+		const char *str = osmo_hexdump((unsigned char *)buf, len);
+		int i = 0;
+		const int prefix = 4;
+		const int cutlen = 48;
+		int nchars = 0;
+
+		printf("encoded:\n");
+		do {
+			nchars = printf("%*s%-.*s", prefix, "", cutlen, str + i);
+			i += nchars - prefix;
+			printf("\n");
+		} while (nchars - prefix >= cutlen);
+	}
+	printf("counted: %d\n", cont);
+	talloc_free(ctx);
+	return 0;
+}
+
+static void test_rtp_seq_state(void)
+{
+	char buf[4096];
+	int len;
+	int cont;
+	void *ctx;
+	struct mgcp_endpoint *endp;
+	struct mgcp_process_rtp_state *state;
+	struct rtp_hdr *hdr;
+	uint32_t ts_no;
+	uint16_t seq_no;
+
+	given_configured_endpoint(160, 0, "pcma", "l16", &ctx, &endp);
+	state = endp->bts_end.rtp_process_data;
+	OSMO_ASSERT(!state->is_running);
+	OSMO_ASSERT(state->next_seq == 0);
+	OSMO_ASSERT(state->next_time == 0);
+
+	/* initialize packet */
+	len = audio_packets_pcma[0].len;
+	memcpy(buf, audio_packets_pcma[0].data, len);
+	cont = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, len);
+	OSMO_ASSERT(cont >= 0);
+	OSMO_ASSERT(state->is_running);
+	OSMO_ASSERT(state->next_seq == 2);
+	OSMO_ASSERT(state->next_time == 240);
+
+	/* verify that the right timestamp was written */
+	OSMO_ASSERT(len == audio_packets_pcma[0].len);
+	hdr = (struct rtp_hdr *) &buf[0];
+
+	memcpy(&ts_no, &hdr->timestamp, sizeof(ts_no));
+	OSMO_ASSERT(htonl(ts_no) == 160);
+	memcpy(&seq_no, &hdr->sequence, sizeof(seq_no));
+	OSMO_ASSERT(htons(seq_no) == 1);
+	/* Check the right sequence number is written */
+	state->next_seq = 1234;
+	len = audio_packets_pcma[0].len;
+	memcpy(buf, audio_packets_pcma[0].data, len);
+	cont = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, len);
+	OSMO_ASSERT(cont >= 0);
+	OSMO_ASSERT(len == audio_packets_pcma[0].len);
+	hdr = (struct rtp_hdr *) &buf[0];
+
+	memcpy(&seq_no, &hdr->sequence, sizeof(seq_no));
+	OSMO_ASSERT(htons(seq_no) == 1234);
+
+	talloc_free(ctx);
+}
+
+static void test_transcode_result(void)
+{
+	char buf[4096];
+	int len, res;
+	void *ctx;
+	struct mgcp_endpoint *endp;
+	struct mgcp_process_rtp_state *state;
+
+	{
+		/* from GSM to PCMA and same ptime */
+		given_configured_endpoint(160, 0, "gsm", "pcma", &ctx, &endp);
+		state = endp->bts_end.rtp_process_data;
+
+		/* result */
+		len = audio_packets_gsm[0].len;
+		memcpy(buf, audio_packets_gsm[0].data, len);
+		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
+		OSMO_ASSERT(res == sizeof(struct rtp_hdr));
+		OSMO_ASSERT(state->sample_cnt == 0);
+
+		len = res;
+		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
+		OSMO_ASSERT(res == -ENOMSG);
+
+		talloc_free(ctx);
+	}
+
+	{
+		/* from GSM to PCMA and same ptime */
+		given_configured_endpoint(160, 160, "gsm", "pcma", &ctx, &endp);
+		state = endp->bts_end.rtp_process_data;
+
+		/* result */
+		len = audio_packets_gsm[0].len;
+		memcpy(buf, audio_packets_gsm[0].data, len);
+		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
+		OSMO_ASSERT(res == sizeof(struct rtp_hdr));
+		OSMO_ASSERT(state->sample_cnt == 0);
+
+		len = res;
+		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
+		OSMO_ASSERT(res == -EAGAIN);
+
+		talloc_free(ctx);
+	}
+
+	{
+		/* from PCMA to GSM and wrong different ptime */
+		given_configured_endpoint(80, 160, "pcma", "gsm", &ctx, &endp);
+		state = endp->bts_end.rtp_process_data;
+
+		/* Add the first sample */
+		len = audio_packets_pcma[1].len;
+		memcpy(buf, audio_packets_pcma[1].data, len);
+		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
+		OSMO_ASSERT(state->sample_cnt == 80);
+		OSMO_ASSERT(state->next_time == 232640);
+		OSMO_ASSERT(res < 0);
+
+		/* Add the second sample and it should be consumable */
+		len = audio_packets_pcma[2].len;
+		memcpy(buf, audio_packets_pcma[2].data, len);
+		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
+		OSMO_ASSERT(state->sample_cnt == 0);
+		OSMO_ASSERT(state->next_time == 232640 + 80 + 160);
+		OSMO_ASSERT(res == sizeof(struct rtp_hdr));
+
+		talloc_free(ctx);
+	}
+
+	{
+		/* from PCMA to GSM with a big time jump */
+		struct rtp_hdr *hdr;
+		uint32_t ts;
+
+		given_configured_endpoint(80, 160, "pcma", "gsm", &ctx, &endp);
+		state = endp->bts_end.rtp_process_data;
+
+		/* Add the first sample */
+		len = audio_packets_pcma[1].len;
+		memcpy(buf, audio_packets_pcma[1].data, len);
+		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
+		OSMO_ASSERT(state->sample_cnt == 80);
+		OSMO_ASSERT(state->next_time == 232640);
+		OSMO_ASSERT(state->next_seq == 26527);
+		OSMO_ASSERT(res < 0);
+
+		/* Add a skip to the packet to force a 'resync' */
+		len = audio_packets_pcma[2].len;
+		memcpy(buf, audio_packets_pcma[2].data, len);
+		hdr = (struct rtp_hdr *) &buf[0];
+		/* jump the time and add alignment error */
+		ts = ntohl(hdr->timestamp) + 123 * 80 + 2;
+		hdr->timestamp = htonl(ts);
+		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
+		OSMO_ASSERT(res < 0);
+		OSMO_ASSERT(state->sample_cnt == 80);
+		OSMO_ASSERT(state->next_time == ts);
+		OSMO_ASSERT(state->next_seq == 26527);
+		/* TODO: this can create alignment errors */
+
+
+		/* Now attempt to consume 160 samples */
+		len = audio_packets_pcma[2].len;
+		memcpy(buf, audio_packets_pcma[2].data, len);
+		hdr = (struct rtp_hdr *) &buf[0];
+		ts += 80;
+		hdr->timestamp = htonl(ts);
+		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
+		OSMO_ASSERT(res == 12);
+		OSMO_ASSERT(state->sample_cnt == 0);
+		OSMO_ASSERT(state->next_time == ts + 160);
+		OSMO_ASSERT(state->next_seq == 26528);
+
+		talloc_free(ctx);
+	}
+}
+
+static void test_transcode_change(void)
+{
+	char buf[4096] = {0x80, 0};
+	void *ctx;
+
+	struct mgcp_endpoint *endp;
+	struct mgcp_process_rtp_state *state;
+	struct rtp_hdr *hdr;
+
+	int len, res;
+
+	{
+		/* from GSM to PCMA and same ptime */
+		printf("Testing Initial L16->GSM, PCMA->GSM\n");
+		given_configured_endpoint(160, 0, "l16", "gsm", &ctx, &endp);
+		endp->net_end.alt_codec = endp->net_end.codec;
+		endp->net_end.alt_codec.payload_type = audio_name_to_type("pcma");
+		state = endp->bts_end.rtp_process_data;
+
+		/* initial transcoding work */
+		OSMO_ASSERT(state->src_fmt == AF_L16);
+		OSMO_ASSERT(state->dst_fmt == AF_GSM);
+		OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 8);
+		OSMO_ASSERT(endp->net_end.codec.payload_type == 11);
+
+		/* result */
+		len = audio_packets_pcma[0].len;
+		memcpy(buf, audio_packets_pcma[0].data, len);
+		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
+		state = endp->bts_end.rtp_process_data;
+		OSMO_ASSERT(res == sizeof(struct rtp_hdr));
+		OSMO_ASSERT(state->sample_cnt == 0);
+		OSMO_ASSERT(state->src_fmt == AF_PCMA);
+		OSMO_ASSERT(state->dst_fmt == AF_GSM);
+		OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 11);
+		OSMO_ASSERT(endp->net_end.codec.payload_type == 8);
+
+		len = res;
+		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
+		OSMO_ASSERT(res == -ENOMSG);
+		OSMO_ASSERT(state == endp->bts_end.rtp_process_data);
+
+
+		/* now check that comfort noise doesn't change anything */
+		len = audio_packets_pcma[1].len;
+		memcpy(buf, audio_packets_pcma[1].data, len);
+		hdr = (struct rtp_hdr *) buf;
+		hdr->payload_type = 12;
+		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
+		OSMO_ASSERT(state == endp->bts_end.rtp_process_data);
+		OSMO_ASSERT(state->sample_cnt == 80);
+		OSMO_ASSERT(state->src_fmt == AF_PCMA);
+		OSMO_ASSERT(state->dst_fmt == AF_GSM);
+		OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 11);
+		OSMO_ASSERT(endp->net_end.codec.payload_type == 8);
+
+		talloc_free(ctx);
+	}
+}
+
+static int test_repacking(int in_samples, int out_samples, int no_transcode)
+{
+	char buf[4096] = {0x80, 0};
+	int cc;
+	struct mgcp_endpoint *endp;
+	void *ctx;
+
+	struct mgcp_process_rtp_state *state;
+	int in_cnt;
+	int out_size;
+	int in_size;
+	uint32_t ts = 0;
+	uint16_t seq = 0;
+	const char *srcfmt = "pcma";
+	const char *dstfmt = no_transcode ? "pcma" : "l16";
+
+	printf("== Transcoding test ==\n");
+	printf("converting %s -> %s\n", srcfmt, dstfmt);
+
+	given_configured_endpoint(in_samples, out_samples, srcfmt, dstfmt, &ctx, &endp);
+
+	state = endp->bts_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);
+
+	out_size = mgcp_transcoding_get_frame_size(state, -1, 1);
+	OSMO_ASSERT(sizeof(buf) >= out_size + 12);
+
+	buf[1] = endp->net_end.codec.payload_type;
+	*(uint16_t*)(buf+2) = htons(1);
+	*(uint32_t*)(buf+4) = htonl(0);
+	*(uint32_t*)(buf+8) = htonl(0xaabbccdd);
+
+	for (in_cnt = 0; in_cnt < 16; in_cnt++) {
+		int cont;
+		int len;
+
+		/* fake PCMA data */
+		printf("generating %d %s input samples\n", in_samples, srcfmt);
+		for (cc = 0; cc < in_samples; cc++)
+			buf[12+cc] = cc;
+
+		*(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, &endp->bts_end,
+							    buf, &len, sizeof(buf));
+			if (cont == -EAGAIN) {
+				fprintf(stderr, "Got EAGAIN\n");
+				break;
+			}
+
+			if (cont < 0) {
+				printf("processing failed: %s", strerror(-cont));
+				abort();
+			}
+
+			len -= 12; /* ignore RTP header */
+
+			printf("got %d %s output frames (%d octets) count=%d\n",
+			       len / out_size, dstfmt, len, cont);
+
+			len = cont;
+		} while (len > 0);
+	}
+
+	talloc_free(ctx);
+	return 0;
+}
+
+static const struct log_info_cat log_categories[] = {
+};
+
+const struct log_info log_info = {
+        .cat = log_categories,
+        .num_cat = ARRAY_SIZE(log_categories),
+};
+
+int main(int argc, char **argv)
+{
+	int rc;
+	osmo_init_logging(&log_info);
+
+	printf("=== Transcoding Good Cases ===\n");
+
+	transcode_test("l16", "l16",
+		       (uint8_t *)audio_packets_l16[0].data,
+		       audio_packets_l16[0].len);
+	transcode_test("l16", "gsm",
+		       (uint8_t *)audio_packets_l16[0].data,
+		       audio_packets_l16[0].len);
+	transcode_test("l16", "pcma",
+		       (uint8_t *)audio_packets_l16[0].data,
+		       audio_packets_l16[0].len);
+	transcode_test("gsm", "l16",
+		       (uint8_t *)audio_packets_gsm[0].data,
+		       audio_packets_gsm[0].len);
+	transcode_test("gsm", "gsm",
+		       (uint8_t *)audio_packets_gsm[0].data,
+		       audio_packets_gsm[0].len);
+	transcode_test("gsm", "pcma",
+		       (uint8_t *)audio_packets_gsm[0].data,
+		       audio_packets_gsm[0].len);
+	transcode_test("pcma", "l16",
+		       (uint8_t *)audio_packets_pcma[0].data,
+		       audio_packets_pcma[0].len);
+	transcode_test("pcma", "gsm",
+		       (uint8_t *)audio_packets_pcma[0].data,
+		       audio_packets_pcma[0].len);
+	transcode_test("pcma", "pcma",
+		       (uint8_t *)audio_packets_pcma[0].data,
+		       audio_packets_pcma[0].len);
+
+	printf("=== Transcoding Bad Cases ===\n");
+
+	printf("Invalid size:\n");
+	rc = transcode_test("gsm", "pcma",
+		       (uint8_t *)audio_packets_gsm_invalid_size[0].data,
+		       audio_packets_gsm_invalid_size[0].len);
+	OSMO_ASSERT(rc < 0);
+
+	printf("Invalid data:\n");
+	rc = transcode_test("gsm", "pcma",
+		       (uint8_t *)audio_packets_gsm_invalid_data[0].data,
+		       audio_packets_gsm_invalid_data[0].len);
+	OSMO_ASSERT(rc < 0);
+
+	printf("Invalid payload type:\n");
+	rc = transcode_test("gsm", "pcma",
+		       (uint8_t *)audio_packets_gsm_invalid_ptype[0].data,
+		       audio_packets_gsm_invalid_ptype[0].len);
+	OSMO_ASSERT(rc == 0);
+
+	printf("=== Repacking ===\n");
+
+	test_repacking(160, 160, 0);
+	test_repacking(160, 160, 1);
+	test_repacking(160, 80, 0);
+	test_repacking(160, 80, 1);
+	test_repacking(160, 320, 0);
+	test_repacking(160, 320, 1);
+	test_repacking(160, 240, 0);
+	test_repacking(160, 240, 1);
+	test_repacking(160, 100, 0);
+	test_repacking(160, 100, 1);
+	test_rtp_seq_state();
+	test_transcode_result();
+	test_transcode_change();
+
+	return 0;
+}
+
diff --git a/tests/mgcp/mgcp_transcoding_test.ok b/tests/legacy_mgcp/mgcp_transcoding_test.ok
similarity index 100%
rename from tests/mgcp/mgcp_transcoding_test.ok
rename to tests/legacy_mgcp/mgcp_transcoding_test.ok
diff --git a/tests/legacy_mgcp/mgcpgw_client_test.c b/tests/legacy_mgcp/mgcpgw_client_test.c
new file mode 100644
index 0000000..51d5272
--- /dev/null
+++ b/tests/legacy_mgcp/mgcpgw_client_test.c
@@ -0,0 +1,175 @@
+/*
+ * (C) 2016 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/>.
+ */
+
+#include <string.h>
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/application.h>
+#include <osmocom/legacy_mgcp/mgcp.h>
+#include <osmocom/legacy_mgcp/mgcpgw_client.h>
+#include <osmocom/legacy_mgcp/mgcpgw_client_internal.h>
+
+void *ctx;
+
+#define buf_len 4096
+
+#if 0
+static struct msgb *from_hex(const char *hex)
+{
+	struct msgb *msg = msgb_alloc(buf_len, "mgcpgw_test_from_hex");
+	unsigned int l = osmo_hexparse(hex, msg->data, buf_len);
+	msg->l2h = msgb_put(msg, l);
+	return msg;
+}
+
+static struct msgb *mgcp_from_str(const char *head, const char *params)
+{
+	struct msgb *msg = msgb_alloc(buf_len, "mgcp_from_str");
+	unsigned int l;
+	char *data;
+	l = strlen(head);
+	msg->l2h = msgb_put(msg, l);
+	data = (char*)msgb_l2(msg);
+	strncpy(data, head, l);
+
+	data = (char*)msgb_put(msg, 1);
+	*data = '\n';
+
+	l = strlen(params);
+	data = (char*)msgb_put(msg, l);
+	strncpy(data, params, l);
+
+	return msg;
+}
+#endif
+
+static struct msgb *from_str(const char *str)
+{
+	struct msgb *msg = msgb_alloc(buf_len, "from_str");
+	unsigned int l = strlen(str);
+	char *data;
+	msg->l2h = msgb_put(msg, l);
+	data = (char*)msgb_l2(msg);
+	strncpy(data, str, l);
+	return msg;
+}
+
+static struct mgcpgw_client_conf conf;
+struct mgcpgw_client *mgcp = NULL;
+
+static void reply_to(mgcp_trans_id_t trans_id, int code, const char *comment,
+		     int conn_id, const char *params)
+{
+	static char compose[4096 - 128];
+	int len;
+
+	len = snprintf(compose, sizeof(compose),
+		       "%d %u %s\r\nI: %d\n\n%s",
+		       code, trans_id, comment, conn_id, params);
+	OSMO_ASSERT(len < sizeof(compose));
+	OSMO_ASSERT(len > 0);
+
+	printf("composed response:\n-----\n%s\n-----\n",
+	       compose);
+	mgcpgw_client_rx(mgcp, from_str(compose));
+}
+
+void test_response_cb(struct mgcp_response *response, void *priv)
+{
+	OSMO_ASSERT(priv == mgcp);
+	mgcp_response_parse_params(response);
+
+	printf("response cb received:\n"
+	       "  head.response_code = %d\n"
+	       "  head.trans_id = %u\n"
+	       "  head.comment = %s\n"
+	       "  audio_port = %u\n",
+	       response->head.response_code,
+	       response->head.trans_id,
+	       response->head.comment,
+	       response->audio_port
+	      );
+}
+
+mgcp_trans_id_t dummy_mgcp_send(struct msgb *msg)
+{
+	mgcp_trans_id_t trans_id;
+	trans_id = msg->cb[MSGB_CB_MGCP_TRANS_ID];
+	char *end;
+
+	OSMO_ASSERT(mgcpgw_client_pending_add(mgcp, trans_id, test_response_cb, mgcp));
+
+	end = (char*)msgb_put(msg, 1);
+	*end = '\0';
+	printf("composed:\n-----\n%s\n-----\n",
+	       (char*)msgb_l2(msg));
+
+	talloc_free(msg);
+	return trans_id;
+}
+
+void test_crcx(void)
+{
+	struct msgb *msg;
+	mgcp_trans_id_t trans_id;
+
+	printf("\n===== %s =====\n", __func__);
+
+	if (mgcp)
+		talloc_free(mgcp);
+	mgcp = mgcpgw_client_init(ctx, &conf);
+
+	msg = mgcp_msg_crcx(mgcp, 23, 42, MGCP_CONN_LOOPBACK);
+	trans_id = dummy_mgcp_send(msg);
+
+	reply_to(trans_id, 200, "OK", 1,
+		"v=0\r\n"
+		"o=- 1 23 IN IP4 10.9.1.120\r\n"
+		"s=-\r\n"
+		"c=IN IP4 10.9.1.120\r\n"
+		"t=0 0\r\n"
+		"m=audio 16002 RTP/AVP 98\r\n"
+		"a=rtpmap:98 AMR/8000\r\n"
+		"a=ptime:20\r\n");
+}
+
+static const struct log_info_cat log_categories[] = {
+};
+
+const struct log_info log_info = {
+        .cat = log_categories,
+        .num_cat = ARRAY_SIZE(log_categories),
+};
+
+
+int main(int argc, char **argv)
+{
+	ctx = talloc_named_const(NULL, 1, "mgcpgw_client_test");
+	msgb_talloc_ctx_init(ctx, 0);
+	osmo_init_logging(&log_info);
+
+	mgcpgw_client_conf_init(&conf);
+
+	test_crcx();
+
+	printf("Done\n");
+	fprintf(stderr, "Done\n");
+	return EXIT_SUCCESS;
+}
diff --git a/tests/mgcp/mgcpgw_client_test.err b/tests/legacy_mgcp/mgcpgw_client_test.err
similarity index 100%
rename from tests/mgcp/mgcpgw_client_test.err
rename to tests/legacy_mgcp/mgcpgw_client_test.err
diff --git a/tests/mgcp/mgcpgw_client_test.ok b/tests/legacy_mgcp/mgcpgw_client_test.ok
similarity index 100%
rename from tests/mgcp/mgcpgw_client_test.ok
rename to tests/legacy_mgcp/mgcpgw_client_test.ok
diff --git a/tests/mgcp/Makefile.am b/tests/mgcp/Makefile.am
deleted file mode 100644
index af9216f..0000000
--- a/tests/mgcp/Makefile.am
+++ /dev/null
@@ -1,93 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	-I$(top_srcdir) \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	-ggdb3 \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_FLAGS) \
-	$(LIBOSMONETIF_CFLAGS) \
-	$(LIBOSMOSCCP_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(LIBBCG729_CFLAGS) \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(COVERAGE_LDFLAGS) \
-	$(NULL)
-
-EXTRA_DIST = \
-	mgcp_test.ok \
-	mgcp_transcoding_test.ok \
-	mgcpgw_client_test.ok \
-	mgcpgw_client_test.err \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	mgcp_test \
-	mgcpgw_client_test \
-	$(NULL)
-if BUILD_MGCP_TRANSCODING
-noinst_PROGRAMS += \
-	mgcp_transcoding_test \
-	$(NULL)
-endif
-
-mgcp_test_SOURCES = \
-	mgcp_test.c \
-	$(NULL)
-
-mgcp_test_LDADD = \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libmgcp/libmgcp.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOSCCP_LIBS) \
-	$(LIBOSMOVTY_LIBS) \
-	$(LIBRARY_DL) \
-	$(LIBOSMONETIF_LIBS) \
-	-lrt \
-	-lm  \
-	$(NULL)
-
-mgcp_transcoding_test_SOURCES = \
-	mgcp_transcoding_test.c \
-	$(NULL)
-
-mgcp_transcoding_test_LDADD = \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libmgcp/libmgcp.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBBCG729_LIBS) \
-	$(LIBOSMOSCCP_LIBS) \
-	$(LIBOSMOVTY_LIBS) \
-	$(LIBRARY_DL) \
-	$(LIBOSMONETIF_LIBS) \
-	$(LIBRARY_GSM) \
-	-lrt \
-	-lm \
-	$(NULL)
-
-mgcpgw_client_test_SOURCES = \
-	mgcpgw_client_test.c \
-	$(NULL)
-
-mgcpgw_client_test_LDADD = \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libmgcp/libmgcp.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOSCCP_LIBS) \
-	$(LIBOSMOVTY_LIBS) \
-	$(LIBRARY_DL) \
-	$(LIBOSMONETIF_LIBS) \
-	-lrt \
-	-lm  \
-	$(NULL)
diff --git a/tests/mgcp/mgcp_test.c b/tests/mgcp/mgcp_test.c
deleted file mode 100644
index 43a453a..0000000
--- a/tests/mgcp/mgcp_test.c
+++ /dev/null
@@ -1,1227 +0,0 @@
-/*
- * (C) 2011-2012,2014 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2011-2012,2014 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/>.
- */
-#undef _GNU_SOURCE
-#define _GNU_SOURCE
-
-#include <openbsc/mgcp.h>
-#include <openbsc/vty.h>
-#include <openbsc/mgcp_internal.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-#include <string.h>
-#include <limits.h>
-#include <dlfcn.h>
-#include <time.h>
-#include <math.h>
-
-char *strline_r(char *str, char **saveptr);
-
-const char *strline_test_data =
-    "one CR\r"
-    "two CR\r"
-    "\r"
-    "one CRLF\r\n"
-    "two CRLF\r\n"
-    "\r\n"
-    "one LF\n"
-    "two LF\n"
-    "\n"
-    "mixed (4 lines)\r\r\n\n\r\n";
-
-#define EXPECTED_NUMBER_OF_LINES 13
-
-static void test_strline(void)
-{
-	char *save = NULL;
-	char *line;
-	char buf[2048];
-	int counter = 0;
-
-	osmo_strlcpy(buf, strline_test_data, sizeof(buf));
-
-	for (line = strline_r(buf, &save); line;
-	     line = strline_r(NULL, &save)) {
-		printf("line: '%s'\n", line);
-		counter++;
-	}
-
-	OSMO_ASSERT(counter == EXPECTED_NUMBER_OF_LINES);
-}
-
-#define AUEP1	"AUEP 158663169 ds/e1-1/2@172.16.6.66 MGCP 1.0\r\n"
-#define AUEP1_RET "200 158663169 OK\r\n"
-#define AUEP2	"AUEP 18983213 ds/e1-2/1@172.16.6.66 MGCP 1.0\r\n"
-#define AUEP2_RET "500 18983213 FAIL\r\n"
-#define EMPTY	"\r\n"
-#define EMPTY_RET NULL
-#define SHORT	"CRCX \r\n"
-#define SHORT_RET "510 000000 FAIL\r\n"
-
-#define MDCX_WRONG_EP "MDCX 18983213 ds/e1-3/1@172.16.6.66 MGCP 1.0\r\n"
-#define MDCX_ERR_RET "510 18983213 FAIL\r\n"
-#define MDCX_UNALLOCATED "MDCX 18983214 ds/e1-1/2@172.16.6.66 MGCP 1.0\r\n"
-#define MDCX_RET "400 18983214 FAIL\r\n"
-#define MDCX3 "MDCX 18983215 1@mgw MGCP 1.0\r\n"
-#define MDCX3_RET "200 18983215 OK\r\n"		\
-		 "I: 1\n"			\
-		 "\n"				\
-		 "v=0\r\n"			\
-		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
-		 "s=-\r\n"			\
-		 "c=IN IP4 0.0.0.0\r\n"		\
-		 "t=0 0\r\n"			\
-		 "m=audio 0 RTP/AVP 126\r\n"	\
-		 "a=rtpmap:126 AMR/8000\r\n"	\
-		 "a=ptime:20\r\n"
-#define MDCX3_FMTP_RET "200 18983215 OK\r\n"		\
-		 "I: 3\n"			\
-		 "\n"				\
-		 "v=0\r\n"			\
-		 "o=- 3 23 IN IP4 0.0.0.0\r\n"	\
-		 "s=-\r\n"			\
-		 "c=IN IP4 0.0.0.0\r\n"		\
-		 "t=0 0\r\n"			\
-		 "m=audio 0 RTP/AVP 126\r\n"	\
-		 "a=rtpmap:126 AMR/8000\r\n"	\
-		 "a=fmtp:126 0/1/2\r\n"		\
-		 "a=ptime:20\r\n"
-#define MDCX4 "MDCX 18983216 1@mgw MGCP 1.0\r\n" \
-		 "M: sendrecv\r"		\
-		 "C: 2\r\n"          \
-		 "I: 1\r\n"                    \
-		 "L: p:20, a:AMR, nt:IN\r\n"    \
-		 "\n"				\
-		 "v=0\r\n"			\
-		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
-		 "c=IN IP4 0.0.0.0\r\n"		\
-		 "t=0 0\r\n"			\
-		 "m=audio 4441 RTP/AVP 99\r\n"	\
-		 "a=rtpmap:99 AMR/8000\r\n"	\
-		 "a=ptime:40\r\n"
-#define MDCX4_RET(Ident) "200 " Ident " OK\r\n"	\
-		 "I: 1\n"			\
-		 "\n"				\
-		 "v=0\r\n"			\
-		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
-		 "s=-\r\n"			\
-		 "c=IN IP4 0.0.0.0\r\n"		\
-		 "t=0 0\r\n"			\
-		 "m=audio 0 RTP/AVP 126\r\n"	\
-		 "a=rtpmap:126 AMR/8000\r\n"	\
-		 "a=ptime:20\r\n"
-
-#define MDCX4_PT1 "MDCX 18983217 1@mgw MGCP 1.0\r\n" \
-		 "M: sendrecv\r"		\
-		 "C: 2\r\n"          \
-		 "I: 1\r\n"                    \
-		 "L: p:20-40, a:AMR, nt:IN\r\n"    \
-		 "\n"				\
-		 "v=0\r\n"			\
-		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
-		 "c=IN IP4 0.0.0.0\r\n"		\
-		 "t=0 0\r\n"			\
-		 "m=audio 4441 RTP/AVP 99\r\n"	\
-		 "a=rtpmap:99 AMR/8000\r\n"	\
-		 "a=ptime:40\r\n"
-
-#define MDCX4_PT2 "MDCX 18983218 1@mgw MGCP 1.0\r\n" \
-		 "M: sendrecv\r"		\
-		 "C: 2\r\n"          \
-		 "I: 1\r\n"                    \
-		 "L: p:20-20, a:AMR, nt:IN\r\n"    \
-		 "\n"				\
-		 "v=0\r\n"			\
-		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
-		 "c=IN IP4 0.0.0.0\r\n"		\
-		 "t=0 0\r\n"			\
-		 "m=audio 4441 RTP/AVP 99\r\n"	\
-		 "a=rtpmap:99 AMR/8000\r\n"	\
-		 "a=ptime:40\r\n"
-
-#define MDCX4_PT3 "MDCX 18983219 1@mgw MGCP 1.0\r\n" \
-		 "M: sendrecv\r"		\
-		 "C: 2\r\n"          \
-		 "I: 1\r\n"                    \
-		 "L: a:AMR, nt:IN\r\n"    \
-		 "\n"				\
-		 "v=0\r\n"			\
-		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
-		 "c=IN IP4 0.0.0.0\r\n"		\
-		 "t=0 0\r\n"			\
-		 "m=audio 4441 RTP/AVP 99\r\n"	\
-		 "a=rtpmap:99 AMR/8000\r\n"	\
-		 "a=ptime:40\r\n"
-
-#define MDCX4_SO "MDCX 18983220 1@mgw MGCP 1.0\r\n" \
-		 "M: sendonly\r"		\
-		 "C: 2\r\n"          \
-		 "I: 1\r\n"                    \
-		 "L: p:20, a:AMR, nt:IN\r\n"    \
-		 "\n"				\
-		 "v=0\r\n"			\
-		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
-		 "c=IN IP4 0.0.0.0\r\n"		\
-		 "t=0 0\r\n"			\
-		 "m=audio 4441 RTP/AVP 99\r\n"	\
-		 "a=rtpmap:99 AMR/8000\r\n"	\
-		 "a=ptime:40\r\n"
-
-#define MDCX4_RO "MDCX 18983221 1@mgw MGCP 1.0\r\n" \
-		 "M: recvonly\r"		\
-		 "C: 2\r\n"          \
-		 "I: 1\r\n"                    \
-		 "L: p:20, a:AMR, nt:IN\r\n"
-
-#define SHORT2	"CRCX 1"
-#define SHORT2_RET "510 000000 FAIL\r\n"
-#define SHORT3	"CRCX 1 1@mgw"
-#define SHORT4	"CRCX 1 1@mgw MGCP"
-#define SHORT5	"CRCX 1 1@mgw MGCP 1.0"
-
-#define CRCX	 "CRCX 2 1@mgw MGCP 1.0\r\n"	\
-		 "M: recvonly\r\n"		\
-		 "C: 2\r\n"			\
-		 "X\r\n"			\
-		 "L: p:20\r\n"		\
-		 "\r\n"				\
-		 "v=0\r\n"			\
-		 "c=IN IP4 123.12.12.123\r\n"	\
-		 "m=audio 5904 RTP/AVP 97\r\n"	\
-		 "a=rtpmap:97 GSM-EFR/8000\r\n"	\
-		 "a=ptime:40\r\n"
-
-#define CRCX_RET "200 2 OK\r\n"			\
-		 "I: 1\n"			\
-		 "\n"				\
-		 "v=0\r\n"			\
-		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
-		 "s=-\r\n"			\
-		 "c=IN IP4 0.0.0.0\r\n"		\
-		 "t=0 0\r\n"			\
-		 "m=audio 0 RTP/AVP 126\r\n"	\
-		 "a=rtpmap:126 AMR/8000\r\n"	\
-		 "a=ptime:20\r\n"
-
-#define CRCX_RET_NO_RTPMAP "200 2 OK\r\n"	\
-		 "I: 1\n"			\
-		 "\n"				\
-		 "v=0\r\n"			\
-		 "o=- 1 23 IN IP4 0.0.0.0\r\n"	\
-		 "s=-\r\n"			\
-		 "c=IN IP4 0.0.0.0\r\n"		\
-		 "t=0 0\r\n"			\
-		 "m=audio 0 RTP/AVP 126\r\n"	\
-		 "a=ptime:20\r\n"
-
-#define CRCX_FMTP_RET "200 2 OK\r\n"			\
-		 "I: 3\n"			\
-		 "\n"				\
-		 "v=0\r\n"			\
-		 "o=- 3 23 IN IP4 0.0.0.0\r\n"	\
-		 "s=-\r\n"			\
-		 "c=IN IP4 0.0.0.0\r\n"		\
-		 "t=0 0\r\n"			\
-		 "m=audio 0 RTP/AVP 126\r\n"	\
-		 "a=rtpmap:126 AMR/8000\r\n"	\
-		 "a=fmtp:126 0/1/2\r\n"		\
-		 "a=ptime:20\r\n"
-
-#define CRCX_ZYN "CRCX 2 1@mgw MGCP 1.0\r"	\
-		 "M: recvonly\r"		\
-		 "C: 2\r\r"			\
-		 "v=0\r"			\
-		 "c=IN IP4 123.12.12.123\r"	\
-		 "m=audio 5904 RTP/AVP 97\r"	\
-		 "a=rtpmap:97 GSM-EFR/8000\r"
-
-#define CRCX_ZYN_RET "200 2 OK\r\n"		\
-		 "I: 2\n"			\
-		 "\n"				\
-		 "v=0\r\n"			\
-		 "o=- 2 23 IN IP4 0.0.0.0\r\n"	\
-		 "s=-\r\n"			\
-		 "c=IN IP4 0.0.0.0\r\n"		\
-		 "t=0 0\r\n"			\
-		 "m=audio 0 RTP/AVP 126\r\n"	\
-		 "a=rtpmap:126 AMR/8000\r\n"	\
-		 "a=ptime:20\r\n"
-
-#define DLCX	 "DLCX 7 1@mgw MGCP 1.0\r\n"	\
-		 "C: 2\r\n"
-
-#define DLCX_RET "250 7 OK\r\n"			\
-		 "P: PS=0, OS=0, PR=0, OR=0, PL=0, JI=0\r\n" \
-		 "X-Osmo-CP: EC TIS=0, TOS=0, TIR=0, TOR=0\r\n"
-
-#define RQNT	 "RQNT 186908780 1@mgw MGCP 1.0\r\n"	\
-		 "X: B244F267488\r\n"			\
-		 "S: D/9\r\n"
-
-#define RQNT2	 "RQNT 186908781 1@mgw MGCP 1.0\r\n"	\
-		 "X: ADD4F26746F\r\n"			\
-		 "R: D/[0-9#*](N), G/ft, fxr/t38\r\n"
-
-#define RQNT1_RET "200 186908780 OK\r\n"
-#define RQNT2_RET "200 186908781 OK\r\n"
-
-#define PTYPE_IGNORE 0 /* == default initializer */
-#define PTYPE_NONE 128
-#define PTYPE_NYI  PTYPE_NONE
-
-#define CRCX_MULT_1 "CRCX 2 1@mgw MGCP 1.0\r\n"	\
-		 "M: recvonly\r\n"		\
-		 "C: 2\r\n"			\
-		 "X\r\n"			\
-		 "L: p:20\r\n"		\
-		 "\r\n"				\
-		 "v=0\r\n"			\
-		 "c=IN IP4 123.12.12.123\r\n"	\
-		 "m=audio 5904 RTP/AVP 18 97\r\n"\
-		 "a=rtpmap:18 G729/8000\r\n"	\
-		 "a=rtpmap:97 GSM-EFR/8000\r\n"	\
-		 "a=ptime:40\r\n"
-
-#define CRCX_MULT_2 "CRCX 2 2@mgw MGCP 1.0\r\n"	\
-		 "M: recvonly\r\n"		\
-		 "C: 2\r\n"			\
-		 "X\r\n"			\
-		 "L: p:20\r\n"		\
-		 "\r\n"				\
-		 "v=0\r\n"			\
-		 "c=IN IP4 123.12.12.123\r\n"	\
-		 "m=audio 5904 RTP/AVP 18 97 101\r\n"\
-		 "a=rtpmap:18 G729/8000\r\n"	\
-		 "a=rtpmap:97 GSM-EFR/8000\r\n"	\
-		 "a=rtpmap:101 FOO/8000\r\n"	\
-		 "a=ptime:40\r\n"
-
-#define CRCX_MULT_3 "CRCX 2 3@mgw MGCP 1.0\r\n"	\
-		 "M: recvonly\r\n"		\
-		 "C: 2\r\n"			\
-		 "X\r\n"			\
-		 "L: p:20\r\n"		\
-		 "\r\n"				\
-		 "v=0\r\n"			\
-		 "c=IN IP4 123.12.12.123\r\n"	\
-		 "m=audio 5904 RTP/AVP\r\n"	\
-		 "a=rtpmap:18 G729/8000\r\n"	\
-		 "a=rtpmap:97 GSM-EFR/8000\r\n"	\
-		 "a=rtpmap:101 FOO/8000\r\n"	\
-		 "a=ptime:40\r\n"
-
-#define CRCX_MULT_4 "CRCX 2 4@mgw MGCP 1.0\r\n"	\
-		 "M: recvonly\r\n"		\
-		 "C: 2\r\n"			\
-		 "X\r\n"			\
-		 "L: p:20\r\n"		\
-		 "\r\n"				\
-		 "v=0\r\n"			\
-		 "c=IN IP4 123.12.12.123\r\n"	\
-		 "m=audio 5904 RTP/AVP 18\r\n"	\
-		 "a=rtpmap:18 G729/8000\r\n"	\
-		 "a=rtpmap:97 GSM-EFR/8000\r\n"	\
-		 "a=rtpmap:101 FOO/8000\r\n"	\
-		 "a=ptime:40\r\n"
-
-#define CRCX_MULT_GSM_EXACT \
-		"CRCX 259260421 5@mgw MGCP 1.0\r\n"	\
-		"C: 1355c6041e\r\n"			\
-		"I: 3\r\n"				\
-		"L: p:20, a:GSM, nt:IN\r\n"		\
-		"M: recvonly\r\n"			\
-		"\r\n"					\
-		"v=0\r\n"				\
-		"o=- 1439038275 1439038275 IN IP4 192.168.181.247\r\n" \
-		"s=-\r\nc=IN IP4 192.168.181.247\r\n"	\
-		"t=0 0\r\nm=audio 29084 RTP/AVP 255 0 8 3 18 4 96 97 101\r\n" \
-		"a=rtpmap:0 PCMU/8000\r\n"		\
-		"a=rtpmap:8 PCMA/8000\r\n"		\
-		"a=rtpmap:3 gsm/8000\r\n"		\
-		"a=rtpmap:18 G729/8000\r\n"		\
-		"a=fmtp:18 annexb=no\r\n"		\
-		"a=rtpmap:4 G723/8000\r\n"		\
-		"a=rtpmap:96 iLBC/8000\r\n"		\
-		"a=fmtp:96 mode=20\r\n"			\
-		"a=rtpmap:97 iLBC/8000\r\n"		\
-		"a=fmtp:97 mode=30\r\n"			\
-		"a=rtpmap:101 telephone-event/8000\r\n"	\
-		"a=fmtp:101 0-15\r\n"			\
-		"a=recvonly\r\n"
-#define MDCX_NAT_DUMMY \
-		"MDCX 23 5@mgw MGCP 1.0\r\n"		\
-		"C: 1355c6041e\r\n"			\
-		"\r\n"					\
-		"c=IN IP4 8.8.8.8\r\n"		\
-		"m=audio 16434 RTP/AVP 255\r\n"
-
-
-struct mgcp_test {
-	const char *name;
-	const char *req;
-	const char *exp_resp;
-	int exp_net_ptype;
-	int exp_bts_ptype;
-
-	const char *extra_fmtp;
-};
-
-static const struct mgcp_test tests[] = {
-	{ "AUEP1", AUEP1, AUEP1_RET },
-	{ "AUEP2", AUEP2, AUEP2_RET },
-	{ "MDCX1", MDCX_WRONG_EP, MDCX_ERR_RET },
-	{ "MDCX2", MDCX_UNALLOCATED, MDCX_RET },
-	{ "CRCX", CRCX, CRCX_RET, 97, 126 },
-	{ "MDCX3", MDCX3, MDCX3_RET, PTYPE_NONE, 126 },
-	{ "MDCX4", MDCX4, MDCX4_RET("18983216"), 99, 126 },
-	{ "MDCX4_PT1", MDCX4_PT1, MDCX4_RET("18983217"), 99, 126 },
-	{ "MDCX4_PT2", MDCX4_PT2, MDCX4_RET("18983218"), 99, 126 },
-	{ "MDCX4_PT3", MDCX4_PT3, MDCX4_RET("18983219"), 99, 126 },
-	{ "MDCX4_SO", MDCX4_SO, MDCX4_RET("18983220"), 99, 126 },
-	{ "MDCX4_RO", MDCX4_RO, MDCX4_RET("18983221"), PTYPE_IGNORE, 126 },
-	{ "DLCX", DLCX, DLCX_RET, -1, -1 },
-	{ "CRCX_ZYN", CRCX_ZYN, CRCX_ZYN_RET, 97, 126 },
-	{ "EMPTY", EMPTY, EMPTY_RET },
-	{ "SHORT1", SHORT, SHORT_RET },
-	{ "SHORT2", SHORT2, SHORT2_RET },
-	{ "SHORT3", SHORT3, SHORT2_RET },
-	{ "SHORT4", SHORT4, SHORT2_RET },
-	{ "RQNT1", RQNT, RQNT1_RET },
-	{ "RQNT2", RQNT2, RQNT2_RET },
-	{ "DLCX", DLCX, DLCX_RET, -1, -1 },
-	{ "CRCX", CRCX, CRCX_FMTP_RET, 97, 126, .extra_fmtp = "a=fmtp:126 0/1/2" },
-	{ "MDCX3", MDCX3, MDCX3_FMTP_RET, PTYPE_NONE, 126 , .extra_fmtp = "a=fmtp:126 0/1/2" },
-	{ "DLCX", DLCX, DLCX_RET, -1, -1 , .extra_fmtp = "a=fmtp:126 0/1/2" },
-};
-
-static const struct mgcp_test retransmit[] = {
-	{ "CRCX", CRCX, CRCX_RET },
-	{ "RQNT1", RQNT, RQNT1_RET },
-	{ "RQNT2", RQNT2, RQNT2_RET },
-	{ "MDCX3", MDCX3, MDCX3_RET },
-	{ "DLCX", DLCX, DLCX_RET },
-};
-
-static struct msgb *create_msg(const char *str)
-{
-	struct msgb *msg;
-
-	msg = msgb_alloc_headroom(4096, 128, "MGCP msg");
-	int len = sprintf((char *)msg->data, "%s", str);
-	msg->l2h = msgb_put(msg, len);
-	return msg;
-}
-
-static int last_endpoint = -1;
-
-static int mgcp_test_policy_cb(struct mgcp_trunk_config *cfg, int endpoint,
-			       int state, const char *transactio_id)
-{
-	fprintf(stderr, "Policy CB got state %d on endpoint %d\n",
-		state, endpoint);
-	last_endpoint = endpoint;
-	return MGCP_POLICY_CONT;
-}
-
-#define MGCP_DUMMY_LOAD 0x23
-static int dummy_packets = 0;
-/* override and forward */
-ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
-		const struct sockaddr *dest_addr, socklen_t addrlen)
-{
-	typedef ssize_t (*sendto_t)(int, const void *, size_t, int,
-			const struct sockaddr *, socklen_t);
-	static sendto_t real_sendto = NULL;
-	uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr);
-	int      dest_port = htons(((struct sockaddr_in *)dest_addr)->sin_port);
-
-	if (!real_sendto)
-		real_sendto = dlsym(RTLD_NEXT, "sendto");
-
-	if (len == 1 && ((const char *)buf)[0] == MGCP_DUMMY_LOAD ) {
-		fprintf(stderr, "Dummy packet to 0x%08x:%d, msg length %zu\n%s\n\n",
-		       dest_host, dest_port,
-		       len, osmo_hexdump(buf, len));
-		dummy_packets += 1;
-	}
-
-	return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
-}
-
-static int64_t force_monotonic_time_us = -1;
-/* override and forward */
-int clock_gettime(clockid_t clk_id, struct timespec *tp)
-{
-	typedef int (*clock_gettime_t)(clockid_t clk_id, struct timespec *tp);
-	static clock_gettime_t real_clock_gettime = NULL;
-
-	if (!real_clock_gettime)
-		real_clock_gettime = dlsym(RTLD_NEXT, "clock_gettime");
-
-	if (clk_id == CLOCK_MONOTONIC && force_monotonic_time_us >= 0) {
-		tp->tv_sec = force_monotonic_time_us / 1000000;
-		tp->tv_nsec = (force_monotonic_time_us % 1000000) * 1000;
-		return 0;
-	}
-
-	return real_clock_gettime(clk_id, tp);
-}
-
-#define CONN_UNMODIFIED (0x1000)
-
-static void test_values(void)
-{
-	/* Check that NONE disables all output */
-	OSMO_ASSERT((MGCP_CONN_NONE & MGCP_CONN_RECV_SEND) == 0)
-
-	/* Check that LOOPBACK enables all output */
-	OSMO_ASSERT((MGCP_CONN_LOOPBACK & MGCP_CONN_RECV_SEND) ==
-		    MGCP_CONN_RECV_SEND)
-}
-
-
-static void test_messages(void)
-{
-	struct mgcp_config *cfg;
-	struct mgcp_endpoint *endp;
-	int i;
-
-	cfg = mgcp_config_alloc();
-
-	cfg->trunk.number_endpoints = 64;
-	mgcp_endpoints_allocate(&cfg->trunk);
-
-	cfg->policy_cb = mgcp_test_policy_cb;
-
-	mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1));
-
-	/* reset endpoints */
-	for (i = 0; i < cfg->trunk.number_endpoints; i++) {
-		endp = &cfg->trunk.endpoints[i];
-		endp->net_end.codec.payload_type = PTYPE_NONE;
-		endp->net_end.packet_duration_ms = -1;
-
-		OSMO_ASSERT(endp->conn_mode == MGCP_CONN_NONE);
-		endp->conn_mode |= CONN_UNMODIFIED;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(tests); i++) {
-		const struct mgcp_test *t = &tests[i];
-		struct msgb *inp;
-		struct msgb *msg;
-
-		printf("Testing %s\n", t->name);
-
-		last_endpoint = -1;
-		dummy_packets = 0;
-
-		osmo_talloc_replace_string(cfg, &cfg->trunk.audio_fmtp_extra, t->extra_fmtp);
-
-		inp = create_msg(t->req);
-		msg = mgcp_handle_message(cfg, inp);
-		msgb_free(inp);
-		if (!t->exp_resp) {
-			if (msg)
-				printf("%s failed '%s'\n", t->name, (char *) msg->data);
-		} else if (strcmp((char *) msg->data, t->exp_resp) != 0)
-			printf("%s failed '%s'\n", t->name, (char *) msg->data);
-		msgb_free(msg);
-
-		if (dummy_packets)
-			printf("Dummy packets: %d\n", dummy_packets);
-
-		if (last_endpoint != -1) {
-			endp = &cfg->trunk.endpoints[last_endpoint];
-
-			if (endp->net_end.packet_duration_ms != -1)
-				printf("Detected packet duration: %d\n",
-				       endp->net_end.packet_duration_ms);
-			else
-				printf("Packet duration not set\n");
-			if (endp->local_options.pkt_period_min ||
-			    endp->local_options.pkt_period_max)
-				printf("Requested packetetization period: "
-				       "%d-%d\n",
-				       endp->local_options.pkt_period_min,
-				       endp->local_options.pkt_period_max);
-			else
-				printf("Requested packetization period not set\n");
-
-			if ((endp->conn_mode & CONN_UNMODIFIED) == 0) {
-				printf("Connection mode: %d:%s%s%s%s\n",
-				       endp->conn_mode,
-				       !endp->conn_mode ? " NONE" : "",
-				       endp->conn_mode & MGCP_CONN_SEND_ONLY ?
-				       " SEND" : "",
-				       endp->conn_mode & MGCP_CONN_RECV_ONLY ?
-				       " RECV" : "",
-				       endp->conn_mode & MGCP_CONN_LOOPBACK &
-				       ~MGCP_CONN_RECV_SEND ?
-				       " LOOP" : "");
-				fprintf(stderr,
-					"BTS output %sabled, NET output %sabled\n",
-					endp->bts_end.output_enabled ? "en" : "dis",
-					endp->net_end.output_enabled ? "en" : "dis");
-			} else
-				printf("Connection mode not set\n");
-
-			OSMO_ASSERT(endp->net_end.output_enabled ==
-				    (endp->conn_mode & MGCP_CONN_SEND_ONLY ? 1 : 0));
-			OSMO_ASSERT(endp->bts_end.output_enabled ==
-				    (endp->conn_mode & MGCP_CONN_RECV_ONLY ? 1 : 0));
-
-			endp->net_end.packet_duration_ms = -1;
-			endp->local_options.pkt_period_min = 0;
-			endp->local_options.pkt_period_max = 0;
-			endp->conn_mode |= CONN_UNMODIFIED;
-		}
-
-
-		/* Check detected payload type */
-		if (t->exp_net_ptype != PTYPE_IGNORE ||
-		    t->exp_bts_ptype != PTYPE_IGNORE) {
-			OSMO_ASSERT(last_endpoint != -1);
-			endp = &cfg->trunk.endpoints[last_endpoint];
-
-			fprintf(stderr, "endpoint %d: "
-				"payload type BTS %d (exp %d), NET %d (exp %d)\n",
-				last_endpoint,
-				endp->bts_end.codec.payload_type, t->exp_bts_ptype,
-				endp->net_end.codec.payload_type, t->exp_net_ptype);
-
-			if (t->exp_bts_ptype != PTYPE_IGNORE)
-				OSMO_ASSERT(endp->bts_end.codec.payload_type ==
-					    t->exp_bts_ptype);
-			if (t->exp_net_ptype != PTYPE_IGNORE)
-				OSMO_ASSERT(endp->net_end.codec.payload_type ==
-					    t->exp_net_ptype);
-
-			/* Reset them again for next test */
-			endp->net_end.codec.payload_type = PTYPE_NONE;
-		}
-	}
-
-	talloc_free(cfg);
-}
-
-static void test_retransmission(void)
-{
-	struct mgcp_config *cfg;
-	int i;
-
-	cfg = mgcp_config_alloc();
-
-	cfg->trunk.number_endpoints = 64;
-	mgcp_endpoints_allocate(&cfg->trunk);
-
-	mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1));
-
-	/* reset endpoints */
-	for (i = 0; i < cfg->trunk.number_endpoints; i++) {
-		struct mgcp_endpoint *endp;
-		endp = &cfg->trunk.endpoints[i];
-		endp->bts_end.packet_duration_ms = 20;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(retransmit); i++) {
-		const struct mgcp_test *t = &retransmit[i];
-		struct msgb *inp;
-		struct msgb *msg;
-
-		printf("Testing %s\n", t->name);
-
-		inp = create_msg(t->req);
-		msg = mgcp_handle_message(cfg, inp);
-		msgb_free(inp);
-		if (strcmp((char *) msg->data, t->exp_resp) != 0)
-			printf("%s failed '%s'\n", t->name, (char *) msg->data);
-		msgb_free(msg);
-
-		/* Retransmit... */
-		printf("Re-transmitting %s\n", t->name);
-		inp = create_msg(t->req);
-		msg = mgcp_handle_message(cfg, inp);
-		msgb_free(inp);
-		if (strcmp((char *) msg->data, t->exp_resp) != 0)
-			printf("%s failed '%s'\n", t->name, (char *) msg->data);
-		msgb_free(msg);
-	}
-
-	talloc_free(cfg);
-}
-
-static int rqnt_cb(struct mgcp_endpoint *endp, char _tone)
-{
-	ptrdiff_t tone = _tone;
-	endp->cfg->data = (void *) tone;
-	return 0;
-}
-
-static void test_rqnt_cb(void)
-{
-	struct mgcp_config *cfg;
-	struct msgb *inp, *msg;
-
-	cfg = mgcp_config_alloc();
-	cfg->rqnt_cb = rqnt_cb;
-
-	cfg->trunk.number_endpoints = 64;
-	mgcp_endpoints_allocate(&cfg->trunk);
-
-	mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1));
-
-	inp = create_msg(CRCX);
-	msgb_free(mgcp_handle_message(cfg, inp));
-	msgb_free(inp);
-
-	/* send the RQNT and check for the CB */
-	inp = create_msg(RQNT);
-	msg = mgcp_handle_message(cfg, inp);
-	if (strncmp((const char *) msg->l2h, "200", 3) != 0) {
-		printf("FAILED: message is not 200. '%s'\n", msg->l2h);
-		abort();
-	}
-
-	if (cfg->data != (void *) '9') {
-		printf("FAILED: callback not called: %p\n", cfg->data);
-		abort();
-	}
-
-	msgb_free(msg);
-	msgb_free(inp);
-
-	inp = create_msg(DLCX);
-	msgb_free(mgcp_handle_message(cfg, inp));
-	msgb_free(inp);
-	talloc_free(cfg);
-}
-
-struct pl_test {
-	int		cycles;
-	uint16_t	base_seq;
-	uint16_t	max_seq;
-	uint32_t	packets;
-
-	uint32_t	expected;
-	int		loss;
-};
-
-static const struct pl_test pl_test_dat[] = {
-	/* basic.. just one package */
-	{ .cycles = 0, .base_seq = 0, .max_seq = 0, .packets = 1, .expected = 1, .loss = 0},
-	/* some packages and a bit of loss */
-	{ .cycles = 0, .base_seq = 0, .max_seq = 100, .packets = 100, .expected = 101, .loss = 1},
-	/* wrap around */
-	{ .cycles = 1<<16, .base_seq = 0xffff, .max_seq = 2, .packets = 4, .expected = 4, .loss = 0},
-	/* min loss */
-	{ .cycles = 0, .base_seq = 0, .max_seq = 0, .packets = UINT_MAX, .expected = 1, .loss = INT_MIN },
-	/* max loss, with wrap around on expected max */
-	{ .cycles = INT_MAX, .base_seq = 0, .max_seq = UINT16_MAX, .packets = 0, .expected = ((uint32_t)(INT_MAX) + UINT16_MAX + 1), .loss = INT_MAX }, 
-};
-
-static void test_packet_loss_calc(void)
-{
-	int i;
-	printf("Testing packet loss calculation.\n");
-
-	for (i = 0; i < ARRAY_SIZE(pl_test_dat); ++i) {
-		uint32_t expected;
-		int loss;
-		struct mgcp_rtp_state state;
-		struct mgcp_rtp_end rtp;
-		memset(&state, 0, sizeof(state));
-		memset(&rtp, 0, sizeof(rtp));
-
-		state.stats_initialized = 1;
-		state.stats_base_seq = pl_test_dat[i].base_seq;
-		state.stats_max_seq = pl_test_dat[i].max_seq;
-		state.stats_cycles = pl_test_dat[i].cycles;
-
-		rtp.packets = pl_test_dat[i].packets;
-		mgcp_state_calc_loss(&state, &rtp, &expected, &loss);
-
-		if (loss != pl_test_dat[i].loss || expected != pl_test_dat[i].expected) {
-			printf("FAIL: Wrong exp/loss at idx(%d) Loss(%d vs. %d) Exp(%u vs. %u)\n",
-				i, loss, pl_test_dat[i].loss,
-				expected, pl_test_dat[i].expected);
-		}
-	}
-}
-
-static void test_mgcp_stats(void)
-{
-	printf("Testing stat parsing\n");
-
-	uint32_t bps, bos, pr, _or, jitter;
-	struct msgb *msg;
-	int loss;
-	int rc;
-
-	msg = create_msg(DLCX_RET);
-	rc = mgcp_parse_stats(msg, &bps, &bos, &pr, &_or, &loss, &jitter);
-	printf("Parsing result: %d\n", rc);
-	if (bps != 0 || bos != 0 || pr != 0 ||  _or != 0 || loss != 0 || jitter != 0)
-		printf("FAIL: Parsing failed1.\n");
-	msgb_free(msg);
-
-	msg = create_msg("250 7 OK\r\nP: PS=10, OS=20, PR=30, OR=40, PL=-3, JI=40\r\n");
-	rc = mgcp_parse_stats(msg, &bps, &bos, &pr, &_or, &loss, &jitter);
-	printf("Parsing result: %d\n", rc);
-	if (bps != 10 || bos != 20 || pr != 30 || _or != 40 || loss != -3 || jitter != 40)
-		printf("FAIL: Parsing failed2.\n");
-	msgb_free(msg);
-}
-
-struct rtp_packet_info {
-	float txtime;
-	int len;
-	char *data;
-};
-
-struct rtp_packet_info test_rtp_packets1[] = {
-	/* RTP: SeqNo=0, TS=0 */
-	{0.000000, 20, "\x80\x62\x00\x00\x00\x00\x00\x00\x11\x22\x33\x44"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=1, TS=160 */
-	{0.020000, 20, "\x80\x62\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=2, TS=320 */
-	{0.040000, 20, "\x80\x62\x00\x02\x00\x00\x01\x40\x11\x22\x33\x44"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* Repeat RTP timestamp: */
-	/* RTP: SeqNo=3, TS=320 */
-	{0.060000, 20, "\x80\x62\x00\x03\x00\x00\x01\x40\x11\x22\x33\x44"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=4, TS=480 */
-	{0.080000, 20, "\x80\x62\x00\x04\x00\x00\x01\xE0\x11\x22\x33\x44"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=5, TS=640 */
-	{0.100000, 20, "\x80\x62\x00\x05\x00\x00\x02\x80\x11\x22\x33\x44"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* Double skip RTP timestamp (delta = 2*160): */
-	/* RTP: SeqNo=6, TS=960 */
-	{0.120000, 20, "\x80\x62\x00\x06\x00\x00\x03\xC0\x11\x22\x33\x44"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=7, TS=1120 */
-	{0.140000, 20, "\x80\x62\x00\x07\x00\x00\x04\x60\x11\x22\x33\x44"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=8, TS=1280 */
-	{0.160000, 20, "\x80\x62\x00\x08\x00\x00\x05\x00\x11\x22\x33\x44"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* Non 20ms RTP timestamp (delta = 120): */
-	/* RTP: SeqNo=9, TS=1400 */
-	{0.180000, 20, "\x80\x62\x00\x09\x00\x00\x05\x78\x11\x22\x33\x44"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=10, TS=1560 */
-	{0.200000, 20, "\x80\x62\x00\x0A\x00\x00\x06\x18\x11\x22\x33\x44"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=11, TS=1720 */
-	{0.220000, 20, "\x80\x62\x00\x0B\x00\x00\x06\xB8\x11\x22\x33\x44"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* SSRC changed to 0x10203040, RTP timestamp jump */
-	/* RTP: SeqNo=12, TS=34688 */
-	{0.240000, 20, "\x80\x62\x00\x0C\x00\x00\x87\x80\x10\x20\x30\x40"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=13, TS=34848 */
-	{0.260000, 20, "\x80\x62\x00\x0D\x00\x00\x88\x20\x10\x20\x30\x40"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=14, TS=35008 */
-	{0.280000, 20, "\x80\x62\x00\x0E\x00\x00\x88\xC0\x10\x20\x30\x40"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* Non 20ms RTP timestamp (delta = 120): */
-	/* RTP: SeqNo=15, TS=35128 */
-	{0.300000, 20, "\x80\x62\x00\x0F\x00\x00\x89\x38\x10\x20\x30\x40"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=16, TS=35288 */
-	{0.320000, 20, "\x80\x62\x00\x10\x00\x00\x89\xD8\x10\x20\x30\x40"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=17, TS=35448 */
-	{0.340000, 20, "\x80\x62\x00\x11\x00\x00\x8A\x78\x10\x20\x30\x40"
-		       "\x01\x23\x45\x67\x8A\xAB\xCD\xEF"},
-	/* SeqNo increment by 2, RTP timestamp delta = 320: */
-	/* RTP: SeqNo=19, TS=35768 */
-	{0.360000, 20, "\x80\x62\x00\x13\x00\x00\x8B\xB8\x10\x20\x30\x40"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=20, TS=35928 */
-	{0.380000, 20, "\x80\x62\x00\x14\x00\x00\x8C\x58\x10\x20\x30\x40"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=21, TS=36088 */
-	{0.380000, 20, "\x80\x62\x00\x15\x00\x00\x8C\xF8\x10\x20\x30\x40"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* Repeat last packet */
-	/* RTP: SeqNo=21, TS=36088 */
-	{0.400000, 20, "\x80\x62\x00\x15\x00\x00\x8C\xF8\x10\x20\x30\x40"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=22, TS=36248 */
-	{0.420000, 20, "\x80\x62\x00\x16\x00\x00\x8D\x98\x10\x20\x30\x40"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=23, TS=36408 */
-	{0.440000, 20, "\x80\x62\x00\x17\x00\x00\x8E\x38\x10\x20\x30\x40"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* Don't increment SeqNo but increment timestamp by 160 */
-	/* RTP: SeqNo=23, TS=36568 */
-	{0.460000, 20, "\x80\x62\x00\x17\x00\x00\x8E\xD8\x10\x20\x30\x40"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=24, TS=36728 */
-	{0.480000, 20, "\x80\x62\x00\x18\x00\x00\x8F\x78\x10\x20\x30\x40"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=25, TS=36888 */
-	{0.500000, 20, "\x80\x62\x00\x19\x00\x00\x90\x18\x10\x20\x30\x40"
-		       "\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* SSRC changed to 0x50607080, RTP timestamp jump, Delay of 1.5s,
-	 * SeqNo jump */
-	/* RTP: SeqNo=1000, TS=160000 */
-	{2.000000, 20, "\x80\x62\x03\xE8\x00\x02\x71\x00\x50\x60\x70\x80"
-			"\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=1001, TS=160160 */
-	{2.020000, 20, "\x80\x62\x03\xE9\x00\x02\x71\xA0\x50\x60\x70\x80"
-			"\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-	/* RTP: SeqNo=1002, TS=160320 */
-	{2.040000, 20, "\x80\x62\x03\xEA\x00\x02\x72\x40\x50\x60\x70\x80"
-			"\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
-};
-
-void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
-			  struct mgcp_rtp_end *rtp_end, struct sockaddr_in *addr,
-			  char *data, int len);
-
-static void test_packet_error_detection(int patch_ssrc, int patch_ts)
-{
-	int i;
-
-	struct mgcp_trunk_config trunk;
-	struct mgcp_endpoint endp;
-	struct mgcp_rtp_state state;
-	struct mgcp_rtp_end *rtp = &endp.net_end;
-	struct sockaddr_in addr = {0};
-	char buffer[4096];
-	uint32_t last_ssrc = 0;
-	uint32_t last_timestamp = 0;
-	uint32_t last_seqno = 0;
-	int last_in_ts_err_cnt = 0;
-	int last_out_ts_err_cnt = 0;
-
-	printf("Testing packet error detection%s%s.\n",
-	       patch_ssrc ? ", patch SSRC" : "",
-	       patch_ts ? ", patch timestamps" : "");
-
-	memset(&trunk, 0, sizeof(trunk));
-	memset(&endp, 0, sizeof(endp));
-	memset(&state, 0, sizeof(state));
-
-	trunk.number_endpoints = 1;
-	trunk.endpoints = &endp;
-	trunk.force_constant_ssrc = patch_ssrc;
-	trunk.force_aligned_timing = patch_ts;
-
-	endp.tcfg = &trunk;
-
-	mgcp_initialize_endp(&endp);
-
-	rtp->codec.payload_type = 98;
-
-	for (i = 0; i < ARRAY_SIZE(test_rtp_packets1); ++i) {
-		struct rtp_packet_info *info = test_rtp_packets1 + i;
-
-		force_monotonic_time_us = round(1000000.0 * info->txtime);
-
-		OSMO_ASSERT(info->len <= sizeof(buffer));
-		OSMO_ASSERT(info->len >= 0);
-		memmove(buffer, info->data, info->len);
-
-		mgcp_rtp_end_config(&endp, 1, rtp);
-
-		mgcp_patch_and_count(&endp, &state, rtp, &addr,
-				     buffer, info->len);
-
-		if (state.out_stream.ssrc != last_ssrc) {
-			printf("Output SSRC changed to %08x\n",
-			       state.out_stream.ssrc);
-			last_ssrc = state.out_stream.ssrc;
-		}
-
-		printf("In TS: %d, dTS: %d, Seq: %d\n",
-		       state.in_stream.last_timestamp,
-		       state.in_stream.last_tsdelta,
-		       state.in_stream.last_seq);
-
-		printf("Out TS change: %d, dTS: %d, Seq change: %d, "
-		       "TS Err change: in %+d, out %+d\n",
-		       state.out_stream.last_timestamp - last_timestamp,
-		       state.out_stream.last_tsdelta,
-		       state.out_stream.last_seq - last_seqno,
-		       state.in_stream.err_ts_counter - last_in_ts_err_cnt,
-		       state.out_stream.err_ts_counter - last_out_ts_err_cnt);
-
-		printf("Stats: Jitter = %u, Transit = %d\n",
-		       mgcp_state_calc_jitter(&state), state.stats_transit);
-
-		last_in_ts_err_cnt = state.in_stream.err_ts_counter;
-		last_out_ts_err_cnt = state.out_stream.err_ts_counter;
-		last_timestamp = state.out_stream.last_timestamp;
-		last_seqno = state.out_stream.last_seq;
-	}
-
-	force_monotonic_time_us = -1;
-}
-
-static void test_multilple_codec(void)
-{
-	struct mgcp_config *cfg;
-	struct mgcp_endpoint *endp;
-	struct msgb *inp, *resp;
-	struct in_addr addr;
-
-	printf("Testing multiple payload types\n");
-
-	cfg = mgcp_config_alloc();
-	cfg->trunk.number_endpoints = 64;
-	mgcp_endpoints_allocate(&cfg->trunk);
-	cfg->policy_cb = mgcp_test_policy_cb;
-	mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1));
-
-	/* Allocate endpoint 1@mgw with two codecs */
-	last_endpoint = -1;
-	inp = create_msg(CRCX_MULT_1);
-	resp = mgcp_handle_message(cfg, inp);
-	msgb_free(inp);
-	msgb_free(resp);
-
-	OSMO_ASSERT(last_endpoint == 1);
-	endp = &cfg->trunk.endpoints[last_endpoint];
-	OSMO_ASSERT(endp->net_end.codec.payload_type == 18);
-	OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 97);
-
-	/* Allocate 2@mgw with three codecs, last one ignored */
-	last_endpoint = -1;
-	inp = create_msg(CRCX_MULT_2);
-	resp = mgcp_handle_message(cfg, inp);
-	msgb_free(inp);
-	msgb_free(resp);
-
-	OSMO_ASSERT(last_endpoint == 2);
-	endp = &cfg->trunk.endpoints[last_endpoint];
-	OSMO_ASSERT(endp->net_end.codec.payload_type == 18);
-	OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 97);
-
-	/* Allocate 3@mgw with no codecs, check for PT == -1 */
-	last_endpoint = -1;
-	inp = create_msg(CRCX_MULT_3);
-	resp = mgcp_handle_message(cfg, inp);
-	msgb_free(inp);
-	msgb_free(resp);
-
-	OSMO_ASSERT(last_endpoint == 3);
-	endp = &cfg->trunk.endpoints[last_endpoint];
-	OSMO_ASSERT(endp->net_end.codec.payload_type == -1);
-	OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1);
-
-	/* Allocate 4@mgw with a single codec */
-	last_endpoint = -1;
-	inp = create_msg(CRCX_MULT_4);
-	resp = mgcp_handle_message(cfg, inp);
-	msgb_free(inp);
-	msgb_free(resp);
-
-	OSMO_ASSERT(last_endpoint == 4);
-	endp = &cfg->trunk.endpoints[last_endpoint];
-	OSMO_ASSERT(endp->net_end.codec.payload_type == 18);
-	OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1);
-
-	/* Allocate 5@mgw at select GSM.. */
-	last_endpoint = -1;
-	inp = create_msg(CRCX_MULT_GSM_EXACT);
-	talloc_free(cfg->trunk.audio_name);
-	cfg->trunk.audio_name = "GSM/8000";
-	cfg->trunk.no_audio_transcoding = 1;
-	resp = mgcp_handle_message(cfg, inp);
-	msgb_free(inp);
-	msgb_free(resp);
-
-	OSMO_ASSERT(last_endpoint == 5);
-	endp = &cfg->trunk.endpoints[last_endpoint];
-	OSMO_ASSERT(endp->net_end.codec.payload_type == 3);
-	OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1);
-
-	inp = create_msg(MDCX_NAT_DUMMY);
-	last_endpoint = -1;
-	resp = mgcp_handle_message(cfg, inp);
-	msgb_free(inp);
-	msgb_free(resp);
-	OSMO_ASSERT(last_endpoint == 5);
-	endp = &cfg->trunk.endpoints[last_endpoint];
-	OSMO_ASSERT(endp->net_end.codec.payload_type == 3);
-	OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1);
-	OSMO_ASSERT(endp->net_end.rtp_port == htons(16434));
-	memset(&addr, 0, sizeof(addr));
-	inet_aton("8.8.8.8", &addr);
-	OSMO_ASSERT(endp->net_end.addr.s_addr == addr.s_addr);
-
-	/* Check what happens without that flag */
-
-	/* Free the previous endpoint and the data ... */
-	mgcp_release_endp(endp);
-	talloc_free(endp->last_response);
-	talloc_free(endp->last_trans);
-	endp->last_response = endp->last_trans = NULL;
-
-	last_endpoint = -1;
-	inp = create_msg(CRCX_MULT_GSM_EXACT);
-	cfg->trunk.no_audio_transcoding = 0;
-	resp = mgcp_handle_message(cfg, inp);
-	msgb_free(inp);
-	msgb_free(resp);
-
-	OSMO_ASSERT(last_endpoint == 5);
-	endp = &cfg->trunk.endpoints[last_endpoint];
-	OSMO_ASSERT(endp->net_end.codec.payload_type == 255);
-	OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 0);
-
-	talloc_free(cfg);
-}
-
-static void test_no_cycle(void)
-{
-	struct mgcp_config *cfg;
-	struct mgcp_endpoint *endp;
-
-	printf("Testing no sequence flow on initial packet\n");
-
-	cfg = mgcp_config_alloc();
-	cfg->trunk.number_endpoints = 64;
-	mgcp_endpoints_allocate(&cfg->trunk);
-
-	endp = &cfg->trunk.endpoints[1];
-	OSMO_ASSERT(endp->net_state.stats_initialized == 0);
-
-	mgcp_rtp_annex_count(endp, &endp->net_state, 0, 0, 2342);
-	OSMO_ASSERT(endp->net_state.stats_initialized == 1);
-	OSMO_ASSERT(endp->net_state.stats_cycles == 0);
-	OSMO_ASSERT(endp->net_state.stats_max_seq == 0);
-
-	mgcp_rtp_annex_count(endp, &endp->net_state, 1, 0, 2342);
-	OSMO_ASSERT(endp->net_state.stats_initialized == 1);
-	OSMO_ASSERT(endp->net_state.stats_cycles == 0);
-	OSMO_ASSERT(endp->net_state.stats_max_seq == 1);
-
-	/* now jump.. */
-	mgcp_rtp_annex_count(endp, &endp->net_state, UINT16_MAX, 0, 2342);
-	OSMO_ASSERT(endp->net_state.stats_initialized == 1);
-	OSMO_ASSERT(endp->net_state.stats_cycles == 0);
-	OSMO_ASSERT(endp->net_state.stats_max_seq == UINT16_MAX);
-
-	/* and wrap */
-	mgcp_rtp_annex_count(endp, &endp->net_state, 0, 0, 2342);
-	OSMO_ASSERT(endp->net_state.stats_initialized == 1);
-	OSMO_ASSERT(endp->net_state.stats_cycles == UINT16_MAX + 1);
-	OSMO_ASSERT(endp->net_state.stats_max_seq == 0);
-
-	talloc_free(cfg);
-}
-
-static void test_no_name(void)
-{
-	struct mgcp_config *cfg;
-	struct mgcp_endpoint *endp;
-	struct msgb *inp, *msg;
-	int i;
-
-	printf("Testing no rtpmap name\n");
-	cfg = mgcp_config_alloc();
-
-	cfg->trunk.number_endpoints = 64;
-	cfg->trunk.audio_send_name = 0;
-	mgcp_endpoints_allocate(&cfg->trunk);
-
-	cfg->policy_cb = mgcp_test_policy_cb;
-
-	mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1));
-
-	/* reset endpoints */
-	for (i = 0; i < cfg->trunk.number_endpoints; i++) {
-		endp = &cfg->trunk.endpoints[i];
-		endp->net_end.codec.payload_type = PTYPE_NONE;
-		endp->net_end.packet_duration_ms = -1;
-
-		OSMO_ASSERT(endp->conn_mode == MGCP_CONN_NONE);
-		endp->conn_mode |= CONN_UNMODIFIED;
-	}
-
-	inp = create_msg(CRCX);
-	msg = mgcp_handle_message(cfg, inp);
-	if (strcmp((char *) msg->data, CRCX_RET_NO_RTPMAP) != 0)
-		printf("FAILED: there should not be a RTPMAP: %s\n",
-			(char *) msg->data);
-	msgb_free(inp);
-	msgb_free(msg);
-
-	mgcp_release_endp(&cfg->trunk.endpoints[1]);
-	talloc_free(cfg);
-}
-
-static void test_osmux_cid(void)
-{
-	int id, i;
-
-	OSMO_ASSERT(osmux_used_cid() == 0);
-	id = osmux_get_cid();
-	OSMO_ASSERT(id == 0);
-	OSMO_ASSERT(osmux_used_cid() == 1);
-	osmux_put_cid(id);
-	OSMO_ASSERT(osmux_used_cid() == 0);
-
-	for (i = 0; i < 256; ++i) {
-		id = osmux_get_cid();
-		OSMO_ASSERT(id == i);
-		OSMO_ASSERT(osmux_used_cid() == i + 1);
-	}
-
-	id = osmux_get_cid();
-	OSMO_ASSERT(id == -1);
-
-	for (i = 0; i < 256; ++i)
-		osmux_put_cid(i);
-	OSMO_ASSERT(osmux_used_cid() == 0);
-}
-
-int main(int argc, char **argv)
-{
-	msgb_talloc_ctx_init(NULL, 0);
-	osmo_init_logging(&log_info);
-
-	test_strline();
-	test_values();
-	test_messages();
-	test_retransmission();
-	test_packet_loss_calc();
-	test_rqnt_cb();
-	test_mgcp_stats();
-	test_packet_error_detection(1, 0);
-	test_packet_error_detection(0, 0);
-	test_packet_error_detection(0, 1);
-	test_packet_error_detection(1, 1);
-	test_multilple_codec();
-	test_no_cycle();
-	test_no_name();
-	test_osmux_cid();
-
-	printf("Done\n");
-	return EXIT_SUCCESS;
-}
diff --git a/tests/mgcp/mgcp_transcoding_test.c b/tests/mgcp/mgcp_transcoding_test.c
deleted file mode 100644
index c5c0a0b..0000000
--- a/tests/mgcp/mgcp_transcoding_test.c
+++ /dev/null
@@ -1,654 +0,0 @@
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <err.h>
-#include <stdint.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/application.h>
-
-#include <osmocom/netif/rtp.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"
-
-uint8_t *audio_frame_l16[] = {
-};
-
-struct rtp_packets {
-	float t;
-	int len;
-	char *data;
-};
-
-struct rtp_packets audio_packets_l16[] = {
-	/* RTP: SeqNo=1, TS=160 */
-	{0.020000, 332,
-		"\x80\x0B\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-		"\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
-	},
-};
-
-struct rtp_packets audio_packets_gsm[] = {
-	/* RTP: SeqNo=1, TS=160 */
-	{0.020000, 45,
-		"\x80\x03\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
-		"\xD4\x7C\xE3\xE9\x62\x50\x39\xF0\xF8\xB4\x68\xEA\x6C\x0E\x81\x1B"
-		"\x56\x2A\xD5\xBC\x69\x9C\xD1\xF0\x66\x7A\xEC\x49\x7A\x33\x3D\x0A"
-		"\xDE"
-	},
-};
-
-struct rtp_packets audio_packets_gsm_invalid_size[] = {
-	/* RTP: SeqNo=1, TS=160 */
-	{0.020000, 41,
-		"\x80\x03\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
-		"\xD4\x7C\xE3\xE9\x62\x50\x39\xF0\xF8\xB4\x68\xEA\x6C\x0E\x81\x1B"
-		"\x56\x2A\xD5\xBC\x69\x9C\xD1\xF0\x66\x7A\xEC\x49\x7A\x33\x3D\x0A"
-		"\xDE"
-	},
-};
-
-struct rtp_packets audio_packets_gsm_invalid_data[] = {
-	/* RTP: SeqNo=1, TS=160 */
-	{0.020000, 45,
-		"\x80\x03\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
-		"\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE"
-		"\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE"
-		"\xEE"
-	},
-};
-
-struct rtp_packets audio_packets_gsm_invalid_ptype[] = {
-	/* RTP: SeqNo=1, TS=160 */
-	{0.020000, 45,
-		"\x80\x08\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
-		"\xD4\x7C\xE3\xE9\x62\x50\x39\xF0\xF8\xB4\x68\xEA\x6C\x0E\x81\x1B"
-		"\x56\x2A\xD5\xBC\x69\x9C\xD1\xF0\x66\x7A\xEC\x49\x7A\x33\x3D\x0A"
-		"\xDE"
-	},
-};
-
-struct rtp_packets audio_packets_g729[] = {
-	/* RTP: SeqNo=1, TS=160 */
-	{0.020000, 32,
-		"\x80\x12\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
-		"\xAF\xC2\x81\x40\x00\xFA\xCE\xA4\x21\x7C\xC5\xC3\x4F\xA5\x98\xF5"
-		"\xB2\x95\xC4\xAD"
-	},
-};
-
-struct rtp_packets audio_packets_pcma[] = {
-	/* RTP: SeqNo=1, TS=160 */
-	{0.020000, 172,
-		"\x80\x08\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
-		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
-		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
-		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
-		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
-		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
-		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
-		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
-		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
-		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
-		"\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
-	},
-	/* RTP: SeqNo=26527, TS=232640 */
-	{0.020000, 92,
-		"\x80\x08\x67\x9f\x00\x03\x8c\xc0\x04\xaa\x67\x9f\xd5\xd5\xd5\xd5"
-		"\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5"
-		"\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5"
-		"\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5"
-		"\xd5\xd5\xd5\xd5\xd5\xd5\x55\x55\xd5\xd5\x55\x55\xd5\xd5\x55\x55"
-		"\xd5\xd5\xd5\x55\x55\xd5\xd5\xd5\x55\x55\xd5\xd5"
-	},
-	/* RTP: SeqNo=26528, TS=232720 */
-	{0.020000, 92,
-		"\x80\x08\x67\xa0\x00\x03\x8d\x10\x04\xaa\x67\x9f\x55\xd5\xd5\x55"
-		"\xd5\x55\xd5\xd5\xd5\x55\xd5\x55\xd5\xd5\x55\xd5\x55\xd5\x55\xd5"
-		"\x55\x55\xd5\x55\xd5\xd5\x55\x55\x55\x55\x55\xd5\xd5\x55\xd5\xd5"
-		"\xd5\x55\xd5\xd5\xd5\x55\x54\x55\xd5\xd5\x55\xd5\xd5\xd5\xd5\x55"
-		"\x54\x55\xd5\x55\xd5\x55\x55\x55\x55\x55\xd5\xd5\xd5\xd5\xd5\xd4"
-		"\xd5\x54\x55\xd5\xd4\xd5\x54\xd5\x55\xd5\xd5\xd5"
-	},
-};
-
-
-
-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);
-
-static int given_configured_endpoint(int in_samples, int out_samples,
-				const char *srcfmt, const char *dstfmt,
-				void **out_ctx, struct mgcp_endpoint **out_endp)
-{
-	int rc;
-	struct mgcp_rtp_end *dst_end;
-	struct mgcp_rtp_end *src_end;
-	struct mgcp_config *cfg;
-	struct mgcp_trunk_config *tcfg;
-	struct mgcp_endpoint *endp;
-
-	cfg = mgcp_config_alloc();
-	tcfg = talloc_zero(cfg, struct mgcp_trunk_config);
-	endp = talloc_zero(tcfg, struct mgcp_endpoint);
-
-	cfg->setup_rtp_processing_cb = mgcp_transcoding_setup;
-	cfg->rtp_processing_cb = mgcp_transcoding_process_rtp;
-	cfg->get_net_downlink_format_cb = mgcp_transcoding_net_downlink_format;
-
-	tcfg->endpoints = endp;
-	tcfg->number_endpoints = 1;
-	tcfg->cfg = cfg;
-	endp->tcfg = tcfg;
-	endp->cfg = cfg;
-	mgcp_initialize_endp(endp);
-
-	dst_end = &endp->bts_end;
-	dst_end->codec.payload_type = audio_name_to_type(dstfmt);
-
-	src_end = &endp->net_end;
-	src_end->codec.payload_type = audio_name_to_type(srcfmt);
-
-	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;
-		dst_end->force_output_ptime = 1;
-	}
-
-	rc = mgcp_transcoding_setup(endp, dst_end, src_end);
-	if (rc < 0) {
-		printf("setup failed: %s", strerror(-rc));
-		abort();
-	}
-
-	*out_ctx = cfg;
-	*out_endp = endp;
-	return 0;
-}
-
-
-static int transcode_test(const char *srcfmt, const char *dstfmt,
-			  uint8_t *src_pkts, size_t src_pkt_size)
-{
-	char buf[4096] = {0x80, 0};
-	void *ctx;
-
-	struct mgcp_rtp_end *dst_end;
-	struct mgcp_process_rtp_state *state;
-	struct mgcp_endpoint *endp;
-	int in_size;
-	const int in_samples = 160;
-	int len, cont;
-
-	printf("== Transcoding test ==\n");
-	printf("converting %s -> %s\n", srcfmt, dstfmt);
-
-	given_configured_endpoint(in_samples, 0, srcfmt, dstfmt, &ctx, &endp);
-
-	dst_end = &endp->bts_end;
-	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);
-
-	memcpy(buf, src_pkts, src_pkt_size);
-
-	len = src_pkt_size;
-
-	cont = mgcp_transcoding_process_rtp(endp, dst_end,
-					    buf, &len, sizeof(buf));
-	if (cont < 0) {
-		printf("Nothing encoded due: %s\n", strerror(-cont));
-		talloc_free(ctx);
-		return -1;
-	}
-
-	if (len < 24) {
-		printf("encoded: %s\n", osmo_hexdump((unsigned char *)buf, len));
-	} else {
-		const char *str = osmo_hexdump((unsigned char *)buf, len);
-		int i = 0;
-		const int prefix = 4;
-		const int cutlen = 48;
-		int nchars = 0;
-
-		printf("encoded:\n");
-		do {
-			nchars = printf("%*s%-.*s", prefix, "", cutlen, str + i);
-			i += nchars - prefix;
-			printf("\n");
-		} while (nchars - prefix >= cutlen);
-	}
-	printf("counted: %d\n", cont);
-	talloc_free(ctx);
-	return 0;
-}
-
-static void test_rtp_seq_state(void)
-{
-	char buf[4096];
-	int len;
-	int cont;
-	void *ctx;
-	struct mgcp_endpoint *endp;
-	struct mgcp_process_rtp_state *state;
-	struct rtp_hdr *hdr;
-	uint32_t ts_no;
-	uint16_t seq_no;
-
-	given_configured_endpoint(160, 0, "pcma", "l16", &ctx, &endp);
-	state = endp->bts_end.rtp_process_data;
-	OSMO_ASSERT(!state->is_running);
-	OSMO_ASSERT(state->next_seq == 0);
-	OSMO_ASSERT(state->next_time == 0);
-
-	/* initialize packet */
-	len = audio_packets_pcma[0].len;
-	memcpy(buf, audio_packets_pcma[0].data, len);
-	cont = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, len);
-	OSMO_ASSERT(cont >= 0);
-	OSMO_ASSERT(state->is_running);
-	OSMO_ASSERT(state->next_seq == 2);
-	OSMO_ASSERT(state->next_time == 240);
-
-	/* verify that the right timestamp was written */
-	OSMO_ASSERT(len == audio_packets_pcma[0].len);
-	hdr = (struct rtp_hdr *) &buf[0];
-
-	memcpy(&ts_no, &hdr->timestamp, sizeof(ts_no));
-	OSMO_ASSERT(htonl(ts_no) == 160);
-	memcpy(&seq_no, &hdr->sequence, sizeof(seq_no));
-	OSMO_ASSERT(htons(seq_no) == 1);
-	/* Check the right sequence number is written */
-	state->next_seq = 1234;
-	len = audio_packets_pcma[0].len;
-	memcpy(buf, audio_packets_pcma[0].data, len);
-	cont = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, len);
-	OSMO_ASSERT(cont >= 0);
-	OSMO_ASSERT(len == audio_packets_pcma[0].len);
-	hdr = (struct rtp_hdr *) &buf[0];
-
-	memcpy(&seq_no, &hdr->sequence, sizeof(seq_no));
-	OSMO_ASSERT(htons(seq_no) == 1234);
-
-	talloc_free(ctx);
-}
-
-static void test_transcode_result(void)
-{
-	char buf[4096];
-	int len, res;
-	void *ctx;
-	struct mgcp_endpoint *endp;
-	struct mgcp_process_rtp_state *state;
-
-	{
-		/* from GSM to PCMA and same ptime */
-		given_configured_endpoint(160, 0, "gsm", "pcma", &ctx, &endp);
-		state = endp->bts_end.rtp_process_data;
-
-		/* result */
-		len = audio_packets_gsm[0].len;
-		memcpy(buf, audio_packets_gsm[0].data, len);
-		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
-		OSMO_ASSERT(res == sizeof(struct rtp_hdr));
-		OSMO_ASSERT(state->sample_cnt == 0);
-
-		len = res;
-		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
-		OSMO_ASSERT(res == -ENOMSG);
-
-		talloc_free(ctx);
-	}
-
-	{
-		/* from GSM to PCMA and same ptime */
-		given_configured_endpoint(160, 160, "gsm", "pcma", &ctx, &endp);
-		state = endp->bts_end.rtp_process_data;
-
-		/* result */
-		len = audio_packets_gsm[0].len;
-		memcpy(buf, audio_packets_gsm[0].data, len);
-		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
-		OSMO_ASSERT(res == sizeof(struct rtp_hdr));
-		OSMO_ASSERT(state->sample_cnt == 0);
-
-		len = res;
-		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
-		OSMO_ASSERT(res == -EAGAIN);
-
-		talloc_free(ctx);
-	}
-
-	{
-		/* from PCMA to GSM and wrong different ptime */
-		given_configured_endpoint(80, 160, "pcma", "gsm", &ctx, &endp);
-		state = endp->bts_end.rtp_process_data;
-
-		/* Add the first sample */
-		len = audio_packets_pcma[1].len;
-		memcpy(buf, audio_packets_pcma[1].data, len);
-		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
-		OSMO_ASSERT(state->sample_cnt == 80);
-		OSMO_ASSERT(state->next_time == 232640);
-		OSMO_ASSERT(res < 0);
-
-		/* Add the second sample and it should be consumable */
-		len = audio_packets_pcma[2].len;
-		memcpy(buf, audio_packets_pcma[2].data, len);
-		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
-		OSMO_ASSERT(state->sample_cnt == 0);
-		OSMO_ASSERT(state->next_time == 232640 + 80 + 160);
-		OSMO_ASSERT(res == sizeof(struct rtp_hdr));
-
-		talloc_free(ctx);
-	}
-
-	{
-		/* from PCMA to GSM with a big time jump */
-		struct rtp_hdr *hdr;
-		uint32_t ts;
-
-		given_configured_endpoint(80, 160, "pcma", "gsm", &ctx, &endp);
-		state = endp->bts_end.rtp_process_data;
-
-		/* Add the first sample */
-		len = audio_packets_pcma[1].len;
-		memcpy(buf, audio_packets_pcma[1].data, len);
-		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
-		OSMO_ASSERT(state->sample_cnt == 80);
-		OSMO_ASSERT(state->next_time == 232640);
-		OSMO_ASSERT(state->next_seq == 26527);
-		OSMO_ASSERT(res < 0);
-
-		/* Add a skip to the packet to force a 'resync' */
-		len = audio_packets_pcma[2].len;
-		memcpy(buf, audio_packets_pcma[2].data, len);
-		hdr = (struct rtp_hdr *) &buf[0];
-		/* jump the time and add alignment error */
-		ts = ntohl(hdr->timestamp) + 123 * 80 + 2;
-		hdr->timestamp = htonl(ts);
-		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
-		OSMO_ASSERT(res < 0);
-		OSMO_ASSERT(state->sample_cnt == 80);
-		OSMO_ASSERT(state->next_time == ts);
-		OSMO_ASSERT(state->next_seq == 26527);
-		/* TODO: this can create alignment errors */
-
-
-		/* Now attempt to consume 160 samples */
-		len = audio_packets_pcma[2].len;
-		memcpy(buf, audio_packets_pcma[2].data, len);
-		hdr = (struct rtp_hdr *) &buf[0];
-		ts += 80;
-		hdr->timestamp = htonl(ts);
-		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
-		OSMO_ASSERT(res == 12);
-		OSMO_ASSERT(state->sample_cnt == 0);
-		OSMO_ASSERT(state->next_time == ts + 160);
-		OSMO_ASSERT(state->next_seq == 26528);
-
-		talloc_free(ctx);
-	}
-}
-
-static void test_transcode_change(void)
-{
-	char buf[4096] = {0x80, 0};
-	void *ctx;
-
-	struct mgcp_endpoint *endp;
-	struct mgcp_process_rtp_state *state;
-	struct rtp_hdr *hdr;
-
-	int len, res;
-
-	{
-		/* from GSM to PCMA and same ptime */
-		printf("Testing Initial L16->GSM, PCMA->GSM\n");
-		given_configured_endpoint(160, 0, "l16", "gsm", &ctx, &endp);
-		endp->net_end.alt_codec = endp->net_end.codec;
-		endp->net_end.alt_codec.payload_type = audio_name_to_type("pcma");
-		state = endp->bts_end.rtp_process_data;
-
-		/* initial transcoding work */
-		OSMO_ASSERT(state->src_fmt == AF_L16);
-		OSMO_ASSERT(state->dst_fmt == AF_GSM);
-		OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 8);
-		OSMO_ASSERT(endp->net_end.codec.payload_type == 11);
-
-		/* result */
-		len = audio_packets_pcma[0].len;
-		memcpy(buf, audio_packets_pcma[0].data, len);
-		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
-		state = endp->bts_end.rtp_process_data;
-		OSMO_ASSERT(res == sizeof(struct rtp_hdr));
-		OSMO_ASSERT(state->sample_cnt == 0);
-		OSMO_ASSERT(state->src_fmt == AF_PCMA);
-		OSMO_ASSERT(state->dst_fmt == AF_GSM);
-		OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 11);
-		OSMO_ASSERT(endp->net_end.codec.payload_type == 8);
-
-		len = res;
-		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
-		OSMO_ASSERT(res == -ENOMSG);
-		OSMO_ASSERT(state == endp->bts_end.rtp_process_data);
-
-
-		/* now check that comfort noise doesn't change anything */
-		len = audio_packets_pcma[1].len;
-		memcpy(buf, audio_packets_pcma[1].data, len);
-		hdr = (struct rtp_hdr *) buf;
-		hdr->payload_type = 12;
-		res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
-		OSMO_ASSERT(state == endp->bts_end.rtp_process_data);
-		OSMO_ASSERT(state->sample_cnt == 80);
-		OSMO_ASSERT(state->src_fmt == AF_PCMA);
-		OSMO_ASSERT(state->dst_fmt == AF_GSM);
-		OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 11);
-		OSMO_ASSERT(endp->net_end.codec.payload_type == 8);
-
-		talloc_free(ctx);
-	}
-}
-
-static int test_repacking(int in_samples, int out_samples, int no_transcode)
-{
-	char buf[4096] = {0x80, 0};
-	int cc;
-	struct mgcp_endpoint *endp;
-	void *ctx;
-
-	struct mgcp_process_rtp_state *state;
-	int in_cnt;
-	int out_size;
-	int in_size;
-	uint32_t ts = 0;
-	uint16_t seq = 0;
-	const char *srcfmt = "pcma";
-	const char *dstfmt = no_transcode ? "pcma" : "l16";
-
-	printf("== Transcoding test ==\n");
-	printf("converting %s -> %s\n", srcfmt, dstfmt);
-
-	given_configured_endpoint(in_samples, out_samples, srcfmt, dstfmt, &ctx, &endp);
-
-	state = endp->bts_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);
-
-	out_size = mgcp_transcoding_get_frame_size(state, -1, 1);
-	OSMO_ASSERT(sizeof(buf) >= out_size + 12);
-
-	buf[1] = endp->net_end.codec.payload_type;
-	*(uint16_t*)(buf+2) = htons(1);
-	*(uint32_t*)(buf+4) = htonl(0);
-	*(uint32_t*)(buf+8) = htonl(0xaabbccdd);
-
-	for (in_cnt = 0; in_cnt < 16; in_cnt++) {
-		int cont;
-		int len;
-
-		/* fake PCMA data */
-		printf("generating %d %s input samples\n", in_samples, srcfmt);
-		for (cc = 0; cc < in_samples; cc++)
-			buf[12+cc] = cc;
-
-		*(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, &endp->bts_end,
-							    buf, &len, sizeof(buf));
-			if (cont == -EAGAIN) {
-				fprintf(stderr, "Got EAGAIN\n");
-				break;
-			}
-
-			if (cont < 0) {
-				printf("processing failed: %s", strerror(-cont));
-				abort();
-			}
-
-			len -= 12; /* ignore RTP header */
-
-			printf("got %d %s output frames (%d octets) count=%d\n",
-			       len / out_size, dstfmt, len, cont);
-
-			len = cont;
-		} while (len > 0);
-	}
-
-	talloc_free(ctx);
-	return 0;
-}
-
-int main(int argc, char **argv)
-{
-	int rc;
-	osmo_init_logging(&log_info);
-
-	printf("=== Transcoding Good Cases ===\n");
-
-	transcode_test("l16", "l16",
-		       (uint8_t *)audio_packets_l16[0].data,
-		       audio_packets_l16[0].len);
-	transcode_test("l16", "gsm",
-		       (uint8_t *)audio_packets_l16[0].data,
-		       audio_packets_l16[0].len);
-	transcode_test("l16", "pcma",
-		       (uint8_t *)audio_packets_l16[0].data,
-		       audio_packets_l16[0].len);
-	transcode_test("gsm", "l16",
-		       (uint8_t *)audio_packets_gsm[0].data,
-		       audio_packets_gsm[0].len);
-	transcode_test("gsm", "gsm",
-		       (uint8_t *)audio_packets_gsm[0].data,
-		       audio_packets_gsm[0].len);
-	transcode_test("gsm", "pcma",
-		       (uint8_t *)audio_packets_gsm[0].data,
-		       audio_packets_gsm[0].len);
-	transcode_test("pcma", "l16",
-		       (uint8_t *)audio_packets_pcma[0].data,
-		       audio_packets_pcma[0].len);
-	transcode_test("pcma", "gsm",
-		       (uint8_t *)audio_packets_pcma[0].data,
-		       audio_packets_pcma[0].len);
-	transcode_test("pcma", "pcma",
-		       (uint8_t *)audio_packets_pcma[0].data,
-		       audio_packets_pcma[0].len);
-
-	printf("=== Transcoding Bad Cases ===\n");
-
-	printf("Invalid size:\n");
-	rc = transcode_test("gsm", "pcma",
-		       (uint8_t *)audio_packets_gsm_invalid_size[0].data,
-		       audio_packets_gsm_invalid_size[0].len);
-	OSMO_ASSERT(rc < 0);
-
-	printf("Invalid data:\n");
-	rc = transcode_test("gsm", "pcma",
-		       (uint8_t *)audio_packets_gsm_invalid_data[0].data,
-		       audio_packets_gsm_invalid_data[0].len);
-	OSMO_ASSERT(rc < 0);
-
-	printf("Invalid payload type:\n");
-	rc = transcode_test("gsm", "pcma",
-		       (uint8_t *)audio_packets_gsm_invalid_ptype[0].data,
-		       audio_packets_gsm_invalid_ptype[0].len);
-	OSMO_ASSERT(rc == 0);
-
-	printf("=== Repacking ===\n");
-
-	test_repacking(160, 160, 0);
-	test_repacking(160, 160, 1);
-	test_repacking(160, 80, 0);
-	test_repacking(160, 80, 1);
-	test_repacking(160, 320, 0);
-	test_repacking(160, 320, 1);
-	test_repacking(160, 240, 0);
-	test_repacking(160, 240, 1);
-	test_repacking(160, 100, 0);
-	test_repacking(160, 100, 1);
-	test_rtp_seq_state();
-	test_transcode_result();
-	test_transcode_change();
-
-	return 0;
-}
-
diff --git a/tests/mgcp/mgcpgw_client_test.c b/tests/mgcp/mgcpgw_client_test.c
deleted file mode 100644
index 20e9b78..0000000
--- a/tests/mgcp/mgcpgw_client_test.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * (C) 2016 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/>.
- */
-
-#include <string.h>
-
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/application.h>
-#include <openbsc/mgcp.h>
-#include <openbsc/mgcpgw_client.h>
-
-void *ctx;
-
-#define buf_len 4096
-
-#if 0
-static struct msgb *from_hex(const char *hex)
-{
-	struct msgb *msg = msgb_alloc(buf_len, "mgcpgw_test_from_hex");
-	unsigned int l = osmo_hexparse(hex, msg->data, buf_len);
-	msg->l2h = msgb_put(msg, l);
-	return msg;
-}
-
-static struct msgb *mgcp_from_str(const char *head, const char *params)
-{
-	struct msgb *msg = msgb_alloc(buf_len, "mgcp_from_str");
-	unsigned int l;
-	char *data;
-	l = strlen(head);
-	msg->l2h = msgb_put(msg, l);
-	data = (char*)msgb_l2(msg);
-	strncpy(data, head, l);
-
-	data = (char*)msgb_put(msg, 1);
-	*data = '\n';
-
-	l = strlen(params);
-	data = (char*)msgb_put(msg, l);
-	strncpy(data, params, l);
-
-	return msg;
-}
-#endif
-
-static struct msgb *from_str(const char *str)
-{
-	struct msgb *msg = msgb_alloc(buf_len, "from_str");
-	unsigned int l = strlen(str);
-	char *data;
-	msg->l2h = msgb_put(msg, l);
-	data = (char*)msgb_l2(msg);
-	strncpy(data, str, l);
-	return msg;
-}
-
-static struct mgcpgw_client_conf conf;
-struct mgcpgw_client *mgcp = NULL;
-
-static void reply_to(mgcp_trans_id_t trans_id, int code, const char *comment,
-		     int conn_id, const char *params)
-{
-	static char compose[4096 - 128];
-	int len;
-
-	len = snprintf(compose, sizeof(compose),
-		       "%d %u %s\r\nI: %d\n\n%s",
-		       code, trans_id, comment, conn_id, params);
-	OSMO_ASSERT(len < sizeof(compose));
-	OSMO_ASSERT(len > 0);
-
-	printf("composed response:\n-----\n%s\n-----\n",
-	       compose);
-	mgcpgw_client_rx(mgcp, from_str(compose));
-}
-
-void test_response_cb(struct mgcp_response *response, void *priv)
-{
-	OSMO_ASSERT(priv == mgcp);
-	mgcp_response_parse_params(response);
-
-	printf("response cb received:\n"
-	       "  head.response_code = %d\n"
-	       "  head.trans_id = %u\n"
-	       "  head.comment = %s\n"
-	       "  audio_port = %u\n",
-	       response->head.response_code,
-	       response->head.trans_id,
-	       response->head.comment,
-	       response->audio_port
-	      );
-}
-
-mgcp_trans_id_t dummy_mgcp_send(struct msgb *msg)
-{
-	mgcp_trans_id_t trans_id;
-	trans_id = msg->cb[MSGB_CB_MGCP_TRANS_ID];
-	char *end;
-
-	OSMO_ASSERT(mgcpgw_client_pending_add(mgcp, trans_id, test_response_cb, mgcp));
-
-	end = (char*)msgb_put(msg, 1);
-	*end = '\0';
-	printf("composed:\n-----\n%s\n-----\n",
-	       (char*)msgb_l2(msg));
-
-	talloc_free(msg);
-	return trans_id;
-}
-
-void test_crcx(void)
-{
-	struct msgb *msg;
-	mgcp_trans_id_t trans_id;
-
-	printf("\n===== %s =====\n", __func__);
-
-	if (mgcp)
-		talloc_free(mgcp);
-	mgcp = mgcpgw_client_init(ctx, &conf);
-
-	msg = mgcp_msg_crcx(mgcp, 23, 42, MGCP_CONN_LOOPBACK);
-	trans_id = dummy_mgcp_send(msg);
-
-	reply_to(trans_id, 200, "OK", 1,
-		"v=0\r\n"
-		"o=- 1 23 IN IP4 10.9.1.120\r\n"
-		"s=-\r\n"
-		"c=IN IP4 10.9.1.120\r\n"
-		"t=0 0\r\n"
-		"m=audio 16002 RTP/AVP 98\r\n"
-		"a=rtpmap:98 AMR/8000\r\n"
-		"a=ptime:20\r\n");
-}
-
-int main(int argc, char **argv)
-{
-	ctx = talloc_named_const(NULL, 1, "mgcpgw_client_test");
-	msgb_talloc_ctx_init(ctx, 0);
-	osmo_init_logging(&log_info);
-
-	mgcpgw_client_conf_init(&conf);
-
-	test_crcx();
-
-	printf("Done\n");
-	fprintf(stderr, "Done\n");
-	return EXIT_SUCCESS;
-}
diff --git a/tests/msc_vlr/Makefile.am b/tests/msc_vlr/Makefile.am
deleted file mode 100644
index 3ae0c84..0000000
--- a/tests/msc_vlr/Makefile.am
+++ /dev/null
@@ -1,166 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	-ggdb3 \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBSMPP34_CFLAGS) \
-	$(LIBCRYPTO_CFLAGS) \
-	$(LIBOSMOVTY_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(LIBOSMOSIGTRAN_CFLAGS) \
-	$(LIBOSMORANAP_CFLAGS) \
-	$(LIBASN1C_CFLAGS) \
-	$(NULL)
-
-noinst_HEADERS = \
-	msc_vlr_tests.h \
-	$(NULL)
-
-EXTRA_DIST = \
-	msc_vlr_test_no_authen.ok \
-	msc_vlr_test_no_authen.err \
-	msc_vlr_test_gsm_authen.ok \
-	msc_vlr_test_gsm_authen.err \
-	msc_vlr_test_gsm_ciph.ok \
-	msc_vlr_test_gsm_ciph.err \
-	msc_vlr_test_umts_authen.ok \
-	msc_vlr_test_umts_authen.err \
-	msc_vlr_test_hlr_reject.ok \
-	msc_vlr_test_hlr_reject.err \
-	msc_vlr_test_hlr_timeout.ok \
-	msc_vlr_test_hlr_timeout.err \
-	msc_vlr_test_ms_timeout.ok \
-	msc_vlr_test_ms_timeout.err \
-	msc_vlr_test_reject_concurrency.ok \
-	msc_vlr_test_reject_concurrency.err \
-	msc_vlr_test_rest.ok \
-	msc_vlr_test_rest.err \
-	$(NULL)
-
-COMMON_LDADD = \
-	$(top_builddir)/src/libmsc/libmsc.a \
-	$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
-	$(top_builddir)/src/libvlr/libvlr.a \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libmgcp/libmgcp.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBSMPP34_LIBS) \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBCRYPTO_LIBS) \
-	$(LIBOSMOVTY_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	$(LIBOSMOSIGTRAN_LIBS) \
-	$(LIBOSMORANAP_LIBS) \
-	$(LIBASN1C_LIBS) \
-	-ldbi \
-	-lrt \
-	$(NULL)
-
-COMMON_LDFLAGS = \
-	-Wl,--wrap=gsup_client_create \
-	-Wl,--wrap=gsup_client_send \
-	-Wl,--wrap=a_iface_tx_dtap \
-	-Wl,--wrap=a_iface_tx_clear_cmd \
-	-Wl,--wrap=a_iface_tx_paging \
-	-Wl,--wrap=ranap_iu_tx \
-	-Wl,--wrap=ranap_iu_tx_release \
-	-Wl,--wrap=ranap_iu_tx_common_id \
-	-Wl,--wrap=ranap_iu_page_cs \
-	-Wl,--wrap=msc_stop_paging \
-	-Wl,--wrap=gsm340_gen_scts \
-	-Wl,--wrap=RAND_bytes \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	msc_vlr_test_no_authen \
-	msc_vlr_test_gsm_authen \
-	msc_vlr_test_gsm_ciph \
-	msc_vlr_test_umts_authen \
-	msc_vlr_test_hlr_reject \
-	msc_vlr_test_hlr_timeout \
-	msc_vlr_test_ms_timeout \
-	msc_vlr_test_reject_concurrency \
-	msc_vlr_test_rest \
-	$(NULL)
-
-msc_vlr_test_no_authen_SOURCES = \
-	msc_vlr_test_no_authen.c \
-	msc_vlr_tests.c \
-	$(NULL)
-msc_vlr_test_no_authen_LDADD = $(COMMON_LDADD)
-msc_vlr_test_no_authen_LDFLAGS = $(COMMON_LDFLAGS)
-
-msc_vlr_test_gsm_authen_SOURCES = \
-	msc_vlr_test_gsm_authen.c \
-	msc_vlr_tests.c \
-	$(NULL)
-msc_vlr_test_gsm_authen_LDADD = $(COMMON_LDADD)
-msc_vlr_test_gsm_authen_LDFLAGS = $(COMMON_LDFLAGS)
-
-msc_vlr_test_gsm_ciph_SOURCES = \
-	msc_vlr_test_gsm_ciph.c \
-	msc_vlr_tests.c \
-	$(NULL)
-msc_vlr_test_gsm_ciph_LDADD = $(COMMON_LDADD)
-msc_vlr_test_gsm_ciph_LDFLAGS = $(COMMON_LDFLAGS)
-
-msc_vlr_test_umts_authen_SOURCES = \
-	msc_vlr_test_umts_authen.c \
-	msc_vlr_tests.c \
-	$(NULL)
-msc_vlr_test_umts_authen_LDADD = $(COMMON_LDADD)
-msc_vlr_test_umts_authen_LDFLAGS = $(COMMON_LDFLAGS)
-
-msc_vlr_test_hlr_reject_SOURCES = \
-	msc_vlr_test_hlr_reject.c \
-	msc_vlr_tests.c \
-	$(NULL)
-msc_vlr_test_hlr_reject_LDADD = $(COMMON_LDADD)
-msc_vlr_test_hlr_reject_LDFLAGS = $(COMMON_LDFLAGS)
-
-msc_vlr_test_hlr_timeout_SOURCES = \
-	msc_vlr_test_hlr_timeout.c \
-	msc_vlr_tests.c \
-	$(NULL)
-msc_vlr_test_hlr_timeout_LDADD = $(COMMON_LDADD)
-msc_vlr_test_hlr_timeout_LDFLAGS = $(COMMON_LDFLAGS)
-
-msc_vlr_test_ms_timeout_SOURCES = \
-	msc_vlr_test_ms_timeout.c \
-	msc_vlr_tests.c \
-	$(NULL)
-msc_vlr_test_ms_timeout_LDADD = $(COMMON_LDADD)
-msc_vlr_test_ms_timeout_LDFLAGS = $(COMMON_LDFLAGS)
-
-msc_vlr_test_reject_concurrency_SOURCES = \
-	msc_vlr_test_reject_concurrency.c \
-	msc_vlr_tests.c \
-	$(NULL)
-msc_vlr_test_reject_concurrency_LDADD = $(COMMON_LDADD)
-msc_vlr_test_reject_concurrency_LDFLAGS = $(COMMON_LDFLAGS)
-
-msc_vlr_test_rest_SOURCES = \
-	msc_vlr_test_rest.c \
-	msc_vlr_tests.c \
-	$(NULL)
-msc_vlr_test_rest_LDADD = $(COMMON_LDADD)
-msc_vlr_test_rest_LDFLAGS = $(COMMON_LDFLAGS)
-
-.PHONY: update_exp
-update_exp:
-	$(builddir)/msc_vlr_test_no_authen >$(srcdir)/msc_vlr_test_no_authen.ok 2>$(srcdir)/msc_vlr_test_no_authen.err
-	$(builddir)/msc_vlr_test_gsm_authen >$(srcdir)/msc_vlr_test_gsm_authen.ok 2>$(srcdir)/msc_vlr_test_gsm_authen.err
-	$(builddir)/msc_vlr_test_gsm_ciph >$(srcdir)/msc_vlr_test_gsm_ciph.ok 2>$(srcdir)/msc_vlr_test_gsm_ciph.err
-	$(builddir)/msc_vlr_test_umts_authen >$(srcdir)/msc_vlr_test_umts_authen.ok 2>$(srcdir)/msc_vlr_test_umts_authen.err
-	$(builddir)/msc_vlr_test_hlr_reject >$(srcdir)/msc_vlr_test_hlr_reject.ok 2>$(srcdir)/msc_vlr_test_hlr_reject.err
-	$(builddir)/msc_vlr_test_hlr_timeout >$(srcdir)/msc_vlr_test_hlr_timeout.ok 2>$(srcdir)/msc_vlr_test_hlr_timeout.err
-	$(builddir)/msc_vlr_test_ms_timeout >$(srcdir)/msc_vlr_test_ms_timeout.ok 2>$(srcdir)/msc_vlr_test_ms_timeout.err
-	$(builddir)/msc_vlr_test_reject_concurrency >$(srcdir)/msc_vlr_test_reject_concurrency.ok 2>$(srcdir)/msc_vlr_test_reject_concurrency.err
-	$(builddir)/msc_vlr_test_rest >$(srcdir)/msc_vlr_test_rest.ok 2>$(srcdir)/msc_vlr_test_rest.err
diff --git a/tests/msc_vlr/msc_vlr_test_gsm_authen.c b/tests/msc_vlr/msc_vlr_test_gsm_authen.c
deleted file mode 100644
index 44e4052..0000000
--- a/tests/msc_vlr/msc_vlr_test_gsm_authen.c
+++ /dev/null
@@ -1,924 +0,0 @@
-/* Osmocom MSC+VLR end-to-end tests */
-
-/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- *
- * All Rights Reserved
- *
- * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
- *
- * 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/>.
- *
- */
-
-#include "msc_vlr_tests.h"
-
-void test_gsm_authen()
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000004620";
-
-	comment_start();
-
-	net->authentication_required = true;
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS");
-	auth_request_sent = false;
-	auth_request_expect_rand = "585df1ae287f6e273dce07090d61320b";
-	auth_request_expect_autn = NULL;
-	/* Based on a Ki of 000102030405060708090a0b0c0d0e0f */
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000004026f0"
-		/* 5 auth vectors... */
-		/* TL    TL     rand */
-		"0322"  "2010" "585df1ae287f6e273dce07090d61320b"
-		/*       TL     sres       TL     kc */
-			"2104" "2d8b2c3e" "2208" "61855fb81fc2a800"
-		"0322"  "2010" "12aca96fb4ffdea5c985cbafa9b6e18b"
-			"2104" "20bde240" "2208" "07fa7502e07e1c00"
-		"0322"  "2010" "e7c03ba7cf0e2fde82b2dc4d63077d42"
-			"2104" "a29514ae" "2208" "e2b234f807886400"
-		"0322"  "2010" "fa8f20b781b5881329d4fea26b1a3c51"
-			"2104" "5afc8d72" "2208" "2392f14f709ae000"
-		"0322"  "2010" "0fd4cc8dbe8715d1f439e304edfd68dc"
-			"2104" "bc8d1c5b" "2208" "da7cdd6bfe2d7000",
-		NULL);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("If the HLR were to send a GSUP _UPDATE_LOCATION_RESULT we'd still reject");
-	gsup_rx("06010809710000004026f0", NULL);
-	EXPECT_ACCEPTED(false);
-
-	thwart_rx_non_initial_requests();
-
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR");
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("05542d8b2c3e");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	expect_bssap_clear();
-	gsup_rx("06010809710000004026f0", NULL);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("after a while, a new conn sends a CM Service Request. VLR responds with Auth Req, 2nd auth vector");
-	auth_request_sent = false;
-	auth_request_expect_rand = "12aca96fb4ffdea5c985cbafa9b6e18b";
-	cm_service_result_sent = RES_NONE;
-	ms_sends_msg("05247803305886089910070000006402");
-	OSMO_ASSERT(g_conn);
-	OSMO_ASSERT(g_conn->conn_fsm);
-	OSMO_ASSERT(g_conn->vsub);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-
-	btw("needs auth, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS sends Authen Response, VLR accepts with a CM Service Accept");
-	gsup_expect_tx(NULL);
-	ms_sends_msg("0554" "20bde240" /* 2nd vector's sres, s.a. */);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_ACCEPT, "%d");
-
-	btw("a USSD request is serviced");
-	dtap_expect_tx_ussd("Your extension is 46071\r");
-	expect_bssap_clear();
-	ms_sends_msg("0b3b1c15a11302010002013b300b04010f0406aa510c061b017f0100");
-	OSMO_ASSERT(dtap_tx_confirmed);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("all requests serviced, conn has been released");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("an SMS is sent, MS is paged");
-	paging_expect_imsi(imsi);
-	paging_sent = false;
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 0, "%d");
-
-	send_sms(vsub, vsub,
-		 "Privacy in residential applications is a desirable"
-		 " marketing option.");
-
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 1, "%d");
-	vlr_subscr_put(vsub);
-	vsub = NULL;
-	VERBOSE_ASSERT(paging_sent, == true, "%d");
-	VERBOSE_ASSERT(paging_stopped, == false, "%d");
-
-	btw("the subscriber and its pending request should remain");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 1, "%d");
-	vlr_subscr_put(vsub);
-
-	btw("MS replies with Paging Response, and VLR sends Auth Request with third key");
-	auth_request_sent = false;
-	auth_request_expect_rand = "e7c03ba7cf0e2fde82b2dc4d63077d42";
-	ms_sends_msg("06270703305882089910070000006402");
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-
-	btw("needs auth, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS sends Authen Response, VLR accepts and sends pending SMS");
-	dtap_expect_tx("09" /* SMS messages */
-		       "01" /* CP-DATA */
-		       "58" /* length */
-		       "01" /* Network to MS */
-		       "00" /* reference */
-		       /* originator (gsm411_send_sms() hardcodes this weird nr) */
-		       "0791" "447758100650" /* 447785016005 */
-		       "00" /* dest */
-		       /* SMS TPDU */
-		       "4c" /* len */
-		       "00" /* SMS deliver */
-		       "05806470f1" /* originating address 46071 */
-		       "00" /* TP-PID */
-		       "00" /* GSM default alphabet */
-		       "071010" /* Y-M-D (from wrapped gsm340_gen_scts())*/
-		       "000000" /* H-M-S */
-		       "00" /* GMT+0 */
-		       "44" /* data length */
-		       "5079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0e"
-		       "d3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb"
-		       "0c7ac3e9e9b7db05");
-	ms_sends_msg("0554" "a29514ae" /* 3rd vector's sres, s.a. */);
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	VERBOSE_ASSERT(paging_stopped, == true, "%d");
-
-	btw("SMS was delivered, no requests pending for subscr");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 0, "%d");
-	vlr_subscr_put(vsub);
-
-	btw("conn is still open to wait for SMS ack dance");
-	EXPECT_CONN_COUNT(1);
-
-	btw("MS replies with CP-ACK for received SMS");
-	ms_sends_msg("8904");
-	EXPECT_CONN_COUNT(1);
-
-	btw("MS also sends RP-ACK, MSC in turn sends CP-ACK for that");
-	dtap_expect_tx("0904");
-	expect_bssap_clear();
-	ms_sends_msg("890106020041020000");
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("SMS is done, conn is gone");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("subscriber detaches");
-	expect_bssap_clear();
-	ms_sends_msg("050130089910070000006402");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_gsm_authen_tmsi()
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000004620";
-
-	comment_start();
-
-	net->authentication_required = true;
-	net->vlr->cfg.assign_tmsi = true;
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS");
-	auth_request_sent = false;
-	auth_request_expect_rand = "585df1ae287f6e273dce07090d61320b";
-	auth_request_expect_autn = NULL;
-	/* Based on a Ki of 000102030405060708090a0b0c0d0e0f */
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000004026f0"
-		/* 5 auth vectors... */
-		/* TL    TL     rand */
-		"0322"  "2010" "585df1ae287f6e273dce07090d61320b"
-		/*       TL     sres       TL     kc */
-			"2104" "2d8b2c3e" "2208" "61855fb81fc2a800"
-		"0322"  "2010" "12aca96fb4ffdea5c985cbafa9b6e18b"
-			"2104" "20bde240" "2208" "07fa7502e07e1c00"
-		"0322"  "2010" "e7c03ba7cf0e2fde82b2dc4d63077d42"
-			"2104" "a29514ae" "2208" "e2b234f807886400"
-		"0322"  "2010" "fa8f20b781b5881329d4fea26b1a3c51"
-			"2104" "5afc8d72" "2208" "2392f14f709ae000"
-		"0322"  "2010" "0fd4cc8dbe8715d1f439e304edfd68dc"
-			"2104" "bc8d1c5b" "2208" "da7cdd6bfe2d7000",
-		NULL);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("If the HLR were to send a GSUP _UPDATE_LOCATION_RESULT we'd still reject");
-	gsup_rx("06010809710000004026f0", NULL);
-	EXPECT_ACCEPTED(false);
-
-	thwart_rx_non_initial_requests();
-
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR");
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("05542d8b2c3e");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	gsup_rx("06010809710000004026f0", NULL);
-
-	btw("a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl");
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("even though the TMSI is not acked, we can already find the subscr with it");
-	vsub = vlr_subscr_find_by_tmsi(net->vlr, 0x03020100);
-	VERBOSE_ASSERT(vsub != NULL, == true, "%d");
-	VERBOSE_ASSERT(strcmp(vsub->imsi, imsi), == 0, "%d");
-	VERBOSE_ASSERT(vsub->tmsi_new, == 0x03020100, "0x%08x");
-	VERBOSE_ASSERT(vsub->tmsi, == GSM_RESERVED_TMSI, "0x%08x");
-	vlr_subscr_put(vsub);
-
-	btw("MS sends TMSI Realloc Complete");
-	expect_bssap_clear();
-	ms_sends_msg("055b");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	EXPECT_CONN_COUNT(0);
-
-	btw("Subscriber has the new TMSI");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	VERBOSE_ASSERT(vsub != NULL, == true, "%d");
-	VERBOSE_ASSERT(strcmp(vsub->imsi, imsi), == 0, "%d");
-	VERBOSE_ASSERT(vsub->tmsi_new, == GSM_RESERVED_TMSI, "0x%08x");
-	VERBOSE_ASSERT(vsub->tmsi, == 0x03020100, "0x%08x");
-	vlr_subscr_put(vsub);
-
-	BTW("after a while, a new conn sends a CM Service Request using above TMSI. VLR responds with Auth Req, 2nd auth vector");
-	auth_request_sent = false;
-	auth_request_expect_rand = "12aca96fb4ffdea5c985cbafa9b6e18b";
-	cm_service_result_sent = RES_NONE;
-	ms_sends_msg("05247803305886" "05f4" "03020100");
-	OSMO_ASSERT(g_conn);
-	OSMO_ASSERT(g_conn->conn_fsm);
-	OSMO_ASSERT(g_conn->vsub);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-
-	btw("needs auth, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS sends Authen Response, VLR accepts with a CM Service Accept");
-	gsup_expect_tx(NULL);
-	ms_sends_msg("0554" "20bde240" /* 2nd vector's sres, s.a. */);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_ACCEPT, "%d");
-
-	btw("a USSD request is serviced");
-	dtap_expect_tx_ussd("Your extension is 46071\r");
-	expect_bssap_clear();
-	ms_sends_msg("0b3b1c15a11302010002013b300b04010f0406aa510c061b017f0100");
-	OSMO_ASSERT(dtap_tx_confirmed);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("all requests serviced, conn has been released");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("an SMS is sent, MS is paged");
-	paging_expect_tmsi(0x03020100);
-	paging_sent = false;
-	vsub = vlr_subscr_find_by_tmsi(net->vlr, 0x03020100);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 0, "%d");
-
-	send_sms(vsub, vsub,
-		 "Privacy in residential applications is a desirable"
-		 " marketing option.");
-
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 1, "%d");
-	vlr_subscr_put(vsub);
-	vsub = NULL;
-	VERBOSE_ASSERT(paging_sent, == true, "%d");
-	VERBOSE_ASSERT(paging_stopped, == false, "%d");
-
-	btw("the subscriber and its pending request should remain");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 1, "%d");
-	vlr_subscr_put(vsub);
-
-	btw("MS replies with Paging Response using TMSI, and VLR sends Auth Request with third key");
-	auth_request_sent = false;
-	auth_request_expect_rand = "e7c03ba7cf0e2fde82b2dc4d63077d42";
-	ms_sends_msg("06270703305882" "05f4" "03020100");
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-
-	btw("needs auth, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS sends Authen Response, VLR accepts and sends pending SMS");
-	dtap_expect_tx("09" /* SMS messages */
-		       "01" /* CP-DATA */
-		       "58" /* length */
-		       "01" /* Network to MS */
-		       "00" /* reference */
-		       /* originator (gsm411_send_sms() hardcodes this weird nr) */
-		       "0791" "447758100650" /* 447785016005 */
-		       "00" /* dest */
-		       /* SMS TPDU */
-		       "4c" /* len */
-		       "00" /* SMS deliver */
-		       "05806470f1" /* originating address 46071 */
-		       "00" /* TP-PID */
-		       "00" /* GSM default alphabet */
-		       "071010" /* Y-M-D (from wrapped gsm340_gen_scts())*/
-		       "000000" /* H-M-S */
-		       "00" /* GMT+0 */
-		       "44" /* data length */
-		       "5079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0e"
-		       "d3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb"
-		       "0c7ac3e9e9b7db05");
-	ms_sends_msg("0554" "a29514ae" /* 3rd vector's sres, s.a. */);
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	VERBOSE_ASSERT(paging_stopped, == true, "%d");
-
-	btw("SMS was delivered, no requests pending for subscr");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 0, "%d");
-	vlr_subscr_put(vsub);
-
-	btw("conn is still open to wait for SMS ack dance");
-	EXPECT_CONN_COUNT(1);
-
-	btw("MS replies with CP-ACK for received SMS");
-	ms_sends_msg("8904");
-	EXPECT_CONN_COUNT(1);
-
-	btw("MS also sends RP-ACK, MSC in turn sends CP-ACK for that");
-	dtap_expect_tx("0904");
-	expect_bssap_clear();
-	ms_sends_msg("890106020041020000");
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("SMS is done, conn is gone");
-	EXPECT_CONN_COUNT(0);
-
-	/* TODO: when the subscriber detaches, the vlr_subscr gets
-	 * deallocated and we no longer know the TMSI. This case is covered by
-	 * test_lu_unknown_tmsi(), so here I'd like to still have the TMSI.
-	BTW("subscriber detaches, using TMSI");
-	expect_bssap_clear();
-	ms_sends_msg("050130" "05f4" "03020100");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-	EXPECT_CONN_COUNT(0);
-	 */
-
-	BTW("subscriber sends LU Request, this time with the TMSI");
-	btw("Location Update request causes an Auth Req to MS");
-	lu_result_sent = RES_NONE;
-	auth_request_sent = false;
-	auth_request_expect_rand = "fa8f20b781b5881329d4fea26b1a3c51";
-	ms_sends_msg("050802008168000130" "05f4" "03020100");
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR");
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("05545afc8d72");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	gsup_rx("06010809710000004026f0", NULL);
-
-	btw("a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl");
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("even though the TMSI is not acked, we can already find the subscr with it");
-	vsub = vlr_subscr_find_by_tmsi(net->vlr, 0x07060504);
-	VERBOSE_ASSERT(vsub != NULL, == true, "%d");
-	VERBOSE_ASSERT(strcmp(vsub->imsi, imsi), == 0, "%d");
-	VERBOSE_ASSERT(vsub->tmsi_new, == 0x07060504, "0x%08x");
-	VERBOSE_ASSERT(vsub->tmsi, == 0x03020100, "0x%08x");
-	vlr_subscr_put(vsub);
-
-	btw("MS sends TMSI Realloc Complete");
-	expect_bssap_clear();
-	ms_sends_msg("055b");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	EXPECT_CONN_COUNT(0);
-
-	btw("subscriber has the new TMSI");
-	vsub = vlr_subscr_find_by_tmsi(net->vlr, 0x07060504);
-	VERBOSE_ASSERT(vsub != NULL, == true, "%d");
-	VERBOSE_ASSERT(strcmp(vsub->imsi, imsi), == 0, "%d");
-	VERBOSE_ASSERT(vsub->tmsi_new, == GSM_RESERVED_TMSI, "0x%08x");
-	VERBOSE_ASSERT(vsub->tmsi, == 0x07060504, "0x%08x");
-	vlr_subscr_put(vsub);
-
-	BTW("subscriber detaches, using new TMSI");
-	expect_bssap_clear();
-	ms_sends_msg("050130" "05f4" "07060504");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_gsm_authen_imei()
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000004620";
-
-	comment_start();
-
-	net->authentication_required = true;
-	net->vlr->cfg.check_imei_rqd = true;
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS");
-	auth_request_sent = false;
-	auth_request_expect_rand = "585df1ae287f6e273dce07090d61320b";
-	auth_request_expect_autn = NULL;
-	/* Based on a Ki of 000102030405060708090a0b0c0d0e0f */
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000004026f0"
-		/* 5 auth vectors... */
-		/* TL    TL     rand */
-		"0322"  "2010" "585df1ae287f6e273dce07090d61320b"
-		/*       TL     sres       TL     kc */
-			"2104" "2d8b2c3e" "2208" "61855fb81fc2a800"
-		"0322"  "2010" "12aca96fb4ffdea5c985cbafa9b6e18b"
-			"2104" "20bde240" "2208" "07fa7502e07e1c00"
-		"0322"  "2010" "e7c03ba7cf0e2fde82b2dc4d63077d42"
-			"2104" "a29514ae" "2208" "e2b234f807886400"
-		"0322"  "2010" "fa8f20b781b5881329d4fea26b1a3c51"
-			"2104" "5afc8d72" "2208" "2392f14f709ae000"
-		"0322"  "2010" "0fd4cc8dbe8715d1f439e304edfd68dc"
-			"2104" "bc8d1c5b" "2208" "da7cdd6bfe2d7000",
-		NULL);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("If the HLR were to send a GSUP _UPDATE_LOCATION_RESULT we'd still reject");
-	gsup_rx("06010809710000004026f0", NULL);
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR");
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("05542d8b2c3e");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT, and we send an ID Request for the IMEI to the MS");
-	dtap_expect_tx("051802");
-	gsup_rx("06010809710000004026f0", NULL);
-
-	btw("We will only do business when the IMEI is known");
-	EXPECT_CONN_COUNT(1);
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(vsub->imei[0], == 0, "%d");
-	vlr_subscr_put(vsub);
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS replies with an Identity Response");
-	expect_bssap_clear();
-	ms_sends_msg("0559084a32244332244332");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	btw("Subscriber has the IMEI");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(strcmp(vsub->imei, "423423423423423"), == 0, "%d");
-	vlr_subscr_put(vsub);
-
-	BTW("subscriber detaches");
-	expect_bssap_clear();
-	ms_sends_msg("050130089910070000006402");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_gsm_authen_tmsi_imei()
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000004620";
-
-	comment_start();
-
-	net->authentication_required = true;
-	net->vlr->cfg.assign_tmsi = true;
-	net->vlr->cfg.check_imei_rqd = true;
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS");
-	auth_request_sent = false;
-	auth_request_expect_rand = "585df1ae287f6e273dce07090d61320b";
-	auth_request_expect_autn = NULL;
-	/* Based on a Ki of 000102030405060708090a0b0c0d0e0f */
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000004026f0"
-		/* 5 auth vectors... */
-		/* TL    TL     rand */
-		"0322"  "2010" "585df1ae287f6e273dce07090d61320b"
-		/*       TL     sres       TL     kc */
-			"2104" "2d8b2c3e" "2208" "61855fb81fc2a800"
-		"0322"  "2010" "12aca96fb4ffdea5c985cbafa9b6e18b"
-			"2104" "20bde240" "2208" "07fa7502e07e1c00"
-		"0322"  "2010" "e7c03ba7cf0e2fde82b2dc4d63077d42"
-			"2104" "a29514ae" "2208" "e2b234f807886400"
-		"0322"  "2010" "fa8f20b781b5881329d4fea26b1a3c51"
-			"2104" "5afc8d72" "2208" "2392f14f709ae000"
-		"0322"  "2010" "0fd4cc8dbe8715d1f439e304edfd68dc"
-			"2104" "bc8d1c5b" "2208" "da7cdd6bfe2d7000",
-		NULL);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("If the HLR were to send a GSUP _UPDATE_LOCATION_RESULT we'd still reject");
-	gsup_rx("06010809710000004026f0", NULL);
-	EXPECT_ACCEPTED(false);
-
-	thwart_rx_non_initial_requests();
-
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR");
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("05542d8b2c3e");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT, and we send an ID Request for the IMEI to the MS");
-	dtap_expect_tx("051802");
-	gsup_rx("06010809710000004026f0", NULL);
-
-	btw("We will only do business when the IMEI is known");
-	EXPECT_CONN_COUNT(1);
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(vsub->imei[0], == 0, "%d");
-	vlr_subscr_put(vsub);
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS replies with an Identity Response");
-	ms_sends_msg("0559084a32244332244332");
-
-	btw("a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl");
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("even though the TMSI is not acked, we can already find the subscr with it");
-	vsub = vlr_subscr_find_by_tmsi(net->vlr, 0x03020100);
-	VERBOSE_ASSERT(vsub != NULL, == true, "%d");
-	VERBOSE_ASSERT(strcmp(vsub->imsi, imsi), == 0, "%d");
-	VERBOSE_ASSERT(vsub->tmsi_new, == 0x03020100, "0x%08x");
-	VERBOSE_ASSERT(vsub->tmsi, == GSM_RESERVED_TMSI, "0x%08x");
-	vlr_subscr_put(vsub);
-
-	btw("MS sends TMSI Realloc Complete");
-	expect_bssap_clear();
-	ms_sends_msg("055b");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	EXPECT_CONN_COUNT(0);
-
-	btw("Subscriber has the IMEI and TMSI");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(strcmp(vsub->imei, "423423423423423"), == 0, "%d");
-	VERBOSE_ASSERT(vsub->tmsi, == 0x03020100, "0x%08x");
-	vlr_subscr_put(vsub);
-
-	BTW("subscriber detaches, using TMSI");
-	expect_bssap_clear();
-	ms_sends_msg("050130" "05f4" "03020100");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_gsm_milenage_authen()
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000010650";
-
-	comment_start();
-
-	net->authentication_required = true;
-	rx_from_ran = RAN_GERAN_A;
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("080108" "09710000000156f0");
-	ms_sends_msg("0508" /* MM LU */
-		     "7" /* ciph key seq: no key available */
-		     "0" /* LU type: normal */
-		     "ffffff" "0000" /* LAI, LAC */
-		     "30" /* classmark 1: GSM phase 2 */
-		     "089910070000106005" /* IMSI */
-		     );
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS");
-	/* based on auc_3g:
-	 * K = 'EB215756028D60E3275E613320AEC880',
-	 * OPC = 'FB2A3D1B360F599ABAB99DB8669F8308'
-	 * SQN = 0
-	 */
-	auth_request_sent = false;
-	auth_request_expect_rand = "39fa2f4e3d523d8619a73b4f65c3e14d";
-	auth_request_expect_autn = NULL;
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000000156f0"
-		/* 5 auth vectors... */
-		/* TL    TL     rand */
-		"0362"  "2010" "39fa2f4e3d523d8619a73b4f65c3e14d"
-		/*       TL     sres       TL     kc */
-			"2104" "9b36efdf" "2208" "059a4f668f6fbe39"
-		/*       TL     3G IK */
-			"2310" "27497388b6cb044648f396aa155b95ef"
-		/*       TL     3G CK */
-			"2410" "f64735036e5871319c679f4742a75ea1"
-		/*       TL     AUTN */
-			"2510" "8704f5ba55f30000d2ee44b22c8ea919"
-		/*       TL     RES */
-			"2708" "e229c19e791f2e41"
-		"0362"  "2010" "c187a53a5e6b9d573cac7c74451fd46d"
-			"2104" "85aa3130" "2208" "d3d50a000bf04f6e"
-			"2310" "1159ec926a50e98c034a6b7d7c9f418d"
-			"2410" "df3a03d9ca5335641efc8e36d76cd20b"
-			"2510" "1843a645b98d00005b2d666af46c45d9"
-			"2708" "7db47cf7f81e4dc7"
-		"0362"  "2010" "efa9c29a9742148d5c9070348716e1bb"
-			"2104" "69d5f9fb" "2208" "3df176f0c29f1a3d"
-			"2310" "eb50e770ddcc3060101d2f43b6c2b884"
-			"2410" "76542abce5ff9345b0e8947f4c6e019c"
-			"2510" "f9375e6d41e1000096e7fe4ff1c27e39"
-			"2708" "706f996719ba609c"
-		,NULL);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR");
-	gsup_expect_tx("04010809710000000156f0");
-	ms_sends_msg("0554" "9b36efdf");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000000156f00804032443f2",
-		"12010809710000000156f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	expect_bssap_clear();
-	gsup_rx("06010809710000000156f0", NULL);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("after a while, a new conn sends a CM Service Request. VLR responds with Auth Req, 2nd auth vector");
-	auth_request_sent = false;
-	auth_request_expect_rand = "c187a53a5e6b9d573cac7c74451fd46d";
-	auth_request_expect_autn = NULL;
-	cm_service_result_sent = RES_NONE;
-	ms_sends_msg("052478"
-		     "03305886" /* classmark 2: GSM phase 2 */
-		     "089910070000106005" /* IMSI */);
-	OSMO_ASSERT(g_conn);
-	OSMO_ASSERT(g_conn->conn_fsm);
-	OSMO_ASSERT(g_conn->vsub);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-
-	btw("needs auth, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS sends Authen Response, VLR accepts with a CM Service Accept");
-	gsup_expect_tx(NULL);
-	ms_sends_msg("0554" "85aa3130"); /* 2nd vector's sres, s.a. */
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_ACCEPT, "%d");
-
-	btw("a USSD request is serviced");
-	dtap_expect_tx_ussd("Your extension is 42342\r");
-	expect_bssap_clear();
-	ms_sends_msg("0b3b1c15a11302010002013b300b04010f0406aa510c061b017f0100");
-	OSMO_ASSERT(dtap_tx_confirmed);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("all requests serviced, conn has been released");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("an SMS is sent, MS is paged");
-	paging_expect_imsi(imsi);
-	paging_sent = false;
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 0, "%d");
-
-	send_sms(vsub, vsub,
-		 "Privacy in residential applications is a desirable"
-		 " marketing option.");
-
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 1, "%d");
-	vlr_subscr_put(vsub);
-	vsub = NULL;
-	VERBOSE_ASSERT(paging_sent, == true, "%d");
-	VERBOSE_ASSERT(paging_stopped, == false, "%d");
-
-	btw("the subscriber and its pending request should remain");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 1, "%d");
-	vlr_subscr_put(vsub);
-
-	btw("MS replies with Paging Response, and VLR sends Auth Request with third key");
-	auth_request_sent = false;
-	auth_request_expect_rand = "efa9c29a9742148d5c9070348716e1bb";
-	auth_request_expect_autn = NULL;
-	ms_sends_msg("062707"
-		     "03305886" /* classmark 2 */
-		     "089910070000106005" /* IMSI */);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-
-	btw("needs auth, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS sends Authen Response, VLR accepts and sends pending SMS");
-	dtap_expect_tx("09" /* SMS messages */
-		       "01" /* CP-DATA */
-		       "58" /* length */
-		       "01" /* Network to MS */
-		       "00" /* reference */
-		       /* originator (gsm411_send_sms() hardcodes this weird nr) */
-		       "0791" "447758100650" /* 447785016005 */
-		       "00" /* dest */
-		       /* SMS TPDU */
-		       "4c" /* len */
-		       "00" /* SMS deliver */
-		       "05802443f2" /* originating address 42342 */
-		       "00" /* TP-PID */
-		       "00" /* GSM default alphabet */
-		       "071010" /* Y-M-D (from wrapped gsm340_gen_scts())*/
-		       "000000" /* H-M-S */
-		       "00" /* GMT+0 */
-		       "44" /* data length */
-		       "5079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0e"
-		       "d3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb"
-		       "0c7ac3e9e9b7db05");
-	ms_sends_msg("0554" "69d5f9fb"); /* 3nd vector's sres, s.a. */
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	VERBOSE_ASSERT(paging_stopped, == true, "%d");
-
-	btw("SMS was delivered, no requests pending for subscr");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 0, "%d");
-	vlr_subscr_put(vsub);
-
-	btw("conn is still open to wait for SMS ack dance");
-	EXPECT_CONN_COUNT(1);
-
-	btw("MS replies with CP-ACK for received SMS");
-	ms_sends_msg("8904");
-	EXPECT_CONN_COUNT(1);
-
-	btw("MS also sends RP-ACK, MSC in turn sends CP-ACK for that");
-	dtap_expect_tx("0904");
-	expect_bssap_clear();
-	ms_sends_msg("890106020041020000");
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("SMS is done, conn is gone");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("subscriber detaches");
-	expect_bssap_clear();
-	ms_sends_msg("050130"
-		     "089910070000106005" /* IMSI */);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-msc_vlr_test_func_t msc_vlr_tests[] = {
-	test_gsm_authen,
-	test_gsm_authen_tmsi,
-	test_gsm_authen_imei,
-	test_gsm_authen_tmsi_imei,
-	test_gsm_milenage_authen,
-	NULL
-};
diff --git a/tests/msc_vlr/msc_vlr_test_gsm_authen.err b/tests/msc_vlr/msc_vlr_test_gsm_authen.err
deleted file mode 100644
index bca64a4..0000000
--- a/tests/msc_vlr/msc_vlr_test_gsm_authen.err
+++ /dev/null
@@ -1,1997 +0,0 @@
-===== test_gsm_authen
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DVLR GSUP rx 191: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000004620) Received 5 auth tuples
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending GSM Auth Request for IMSI:901700000004620: tuple use_count=1 key_seq=0 auth_types=0x1 and...
-- ...rand=585df1ae287f6e273dce07090d61320b
-- ...expecting sres=2d8b2c3e
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- If the HLR were to send a GSUP _UPDATE_LOCATION_RESULT we'd still reject
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Event VLR_ULA_E_HLR_LU_RES not permitted
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000004620: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000004620: MM GSM AUTHENTICATION RESPONSE (sres = 2d8b2c3e)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000004620) received res: 2d 8b 2c 3e 
-DVLR SUBSCR(IMSI:901700000004620) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
----
-- after a while, a new conn sends a CM Service Request. VLR responds with Auth Req, 2nd auth vector
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_CM_SERV_REQ
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_CM_SERV_REQ (0x5:0x24)
-DMM <- CM SERVICE REQUEST serv_type=0x08 MI(IMSI)=901700000004620
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of Process_Access_Request_VLR(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=1
-- sending GSM Auth Request for MSISDN:46071: tuple use_count=1 key_seq=1 auth_types=0x1 and...
-- ...rand=12aca96fb4ffdea5c985cbafa9b6e18b
-- ...expecting sres=20bde240
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  cm_service_result_sent == 0
-  auth_request_sent == 1
-- needs auth, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Authen Response, VLR accepts with a CM Service Accept
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM MSISDN:46071: MM GSM AUTHENTICATION RESPONSE (sres = 20bde240)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(MSISDN:46071) received res: 20 bd e2 40 
-DVLR SUBSCR(MSISDN:46071) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent Process_Access_Request_VLR(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: Received Event PR_ARQ_E_AUTH_RES
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-- sending CM Service Accept for MSISDN:46071
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_CM_SERVICE_REQ
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: received_cm_service_request = true
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  cm_service_result_sent == 1
-- a USSD request is serviced
-  expecting USSD:
-  Your extension is 46071

-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_NC_SS:0x3b
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_PDISC_NC_SS:0x3b (0xb:0x3b)
-DMM MSISDN:46071: rx msg GSM48_PDISC_NC_SS:0x3b: received_cm_service_request changes to false
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM USSD: Own number requested
-DMM MSISDN:46071: MSISDN = 46071
-DMSC msc_tx 43 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_NC_SS:0x2a: 8b2a1c27a225020100302002013b301b04010f0416d9775d0e2ae3e965f73cfd7683d27310cd06bbc51a0d
-- DTAP matches expected message
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  bssap_clear_sent == 1
-- all requests serviced, conn has been released
-  llist_count(&net->subscr_conns) == 0
----
-- an SMS is sent, MS is paged
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DMM Subscriber MSISDN:46071 not paged yet, start paging.
-  RAN_GERAN_A sends out paging request to IMSI 901700000004620, TMSI 0xffffffff, LAC 0
-  strcmp(paging_expecting_imsi, imsi) == 0
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-  paging_sent == 1
-  paging_stopped == 0
-- the subscriber and its pending request should remain
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-- MS replies with Paging Response, and VLR sends Auth Request with third key
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_PAG_RESP
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_RR_PAG_RESP (0x6:0x27)
-DRR PAGING RESPONSE: MI(IMSI)=901700000004620
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of Process_Access_Request_VLR(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=2
-- sending GSM Auth Request for MSISDN:46071: tuple use_count=1 key_seq=2 auth_types=0x1 and...
-- ...rand=e7c03ba7cf0e2fde82b2dc4d63077d42
-- ...expecting sres=a29514ae
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  auth_request_sent == 1
-- needs auth, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Authen Response, VLR accepts and sends pending SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM MSISDN:46071: MM GSM AUTHENTICATION RESPONSE (sres = a29514ae)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(MSISDN:46071) received res: a2 95 14 ae 
-DVLR SUBSCR(MSISDN:46071) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent Process_Access_Request_VLR(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: Received Event PR_ARQ_E_AUTH_RES
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_PAGING_RESP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DPAG Paging success for MSISDN:46071 (event=0)
-DPAG Calling paging cbfn.
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DMSC msc_tx 91 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x01: 09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  dtap_tx_confirmed == 1
-  paging_stopped == 1
-- SMS was delivered, no requests pending for subscr
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-- conn is still open to wait for SMS ack dance
-  llist_count(&net->subscr_conns) == 1
-- MS replies with CP-ACK for received SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x04
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x04 (0x9:0x4)
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  llist_count(&net->subscr_conns) == 1
-- MS also sends RP-ACK, MSC in turn sends CP-ACK for that
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x01
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMSC msc_tx 2 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x04: 0904
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DREF MSISDN:46071: MSC conn use - 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  dtap_tx_confirmed == 1
-  bssap_clear_sent == 1
-- SMS is done, conn is gone
-  llist_count(&net->subscr_conns) == 0
----
-- subscriber detaches
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(IMSI)=901700000004620
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DMM IMSI DETACH for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-DMM msc_subscr_conn_close(vsub=unknown, cause=0): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_gsm_authen: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_gsm_authen_tmsi
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DVLR GSUP rx 191: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000004620) Received 5 auth tuples
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending GSM Auth Request for IMSI:901700000004620: tuple use_count=1 key_seq=0 auth_types=0x1 and...
-- ...rand=585df1ae287f6e273dce07090d61320b
-- ...expecting sres=2d8b2c3e
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- If the HLR were to send a GSUP _UPDATE_LOCATION_RESULT we'd still reject
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Event VLR_ULA_E_HLR_LU_RES not permitted
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000004620: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000004620: MM GSM AUTHENTICATION RESPONSE (sres = 2d8b2c3e)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000004620) received res: 2d 8b 2c 3e 
-DVLR SUBSCR(IMSI:901700000004620) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: lu_compl_vlr_new_tmsi()
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_WAIT_TMSI_CNF
-- sending LU Accept for MSISDN:46071, with TMSI 0x03020100
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-- a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- even though the TMSI is not acked, we can already find the subscr with it
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub != NULL == 1
-  strcmp(vsub->imsi, imsi) == 0
-  vsub->tmsi_new == 0x03020100
-  vsub->tmsi == 0xffffffff
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-- MS sends TMSI Realloc Complete
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_TMSI_REALL_COMPL
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_TMSI_REALL_COMPL (0x5:0x1b)
-DMM TMSI Reallocation Completed. Subscriber: MSISDN:46071
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_NEW_TMSI_ACK
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: Received Event LU_COMPL_VLR_E_NEW_TMSI_ACK
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  llist_count(&net->subscr_conns) == 0
-- Subscriber has the new TMSI
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub != NULL == 1
-  strcmp(vsub->imsi, imsi) == 0
-  vsub->tmsi_new == 0xffffffff
-  vsub->tmsi == 0x03020100
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
----
-- after a while, a new conn sends a CM Service Request using above TMSI. VLR responds with Auth Req, 2nd auth vector
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_CM_SERV_REQ
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_CM_SERV_REQ (0x5:0x24)
-DMM <- CM SERVICE REQUEST serv_type=0x08 MI(TMSI)=50462976
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: is child of Subscr_Conn(50462976)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_WAIT_AUTH
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: is child of Process_Access_Request_VLR(50462976)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=1
-- sending GSM Auth Request for MSISDN:46071: tuple use_count=1 key_seq=1 auth_types=0x1 and...
-- ...rand=12aca96fb4ffdea5c985cbafa9b6e18b
-- ...expecting sres=20bde240
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  cm_service_result_sent == 0
-  auth_request_sent == 1
-- needs auth, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Authen Response, VLR accepts with a CM Service Accept
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM MSISDN:46071: MM GSM AUTHENTICATION RESPONSE (sres = 20bde240)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(MSISDN:46071) received res: 20 bd e2 40 
-DVLR SUBSCR(MSISDN:46071) AUTH established GSM security context
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Removing from parent Process_Access_Request_VLR(50462976)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: Received Event PR_ARQ_E_AUTH_RES
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-- sending CM Service Accept for MSISDN:46071
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_CM_SERVICE_REQ
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: received_cm_service_request = true
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  cm_service_result_sent == 1
-- a USSD request is serviced
-  expecting USSD:
-  Your extension is 46071

-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_NC_SS:0x3b
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_PDISC_NC_SS:0x3b (0xb:0x3b)
-DMM MSISDN:46071: rx msg GSM48_PDISC_NC_SS:0x3b: received_cm_service_request changes to false
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM USSD: Own number requested
-DMM MSISDN:46071: MSISDN = 46071
-DMSC msc_tx 43 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_NC_SS:0x2a: 8b2a1c27a225020100302002013b301b04010f0416d9775d0e2ae3e965f73cfd7683d27310cd06bbc51a0d
-- DTAP matches expected message
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(50462976)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  bssap_clear_sent == 1
-- all requests serviced, conn has been released
-  llist_count(&net->subscr_conns) == 0
----
-- an SMS is sent, MS is paged
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DMM Subscriber MSISDN:46071 not paged yet, start paging.
-  RAN_GERAN_A sends out paging request to IMSI 901700000004620, TMSI 0x03020100, LAC 0
-  paging_expecting_tmsi == 0x03020100
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-  paging_sent == 1
-  paging_stopped == 0
-- the subscriber and its pending request should remain
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-- MS replies with Paging Response using TMSI, and VLR sends Auth Request with third key
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_PAG_RESP
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_RR_PAG_RESP (0x6:0x27)
-DRR PAGING RESPONSE: MI(TMSI)=50462976
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: is child of Subscr_Conn(50462976)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_WAIT_AUTH
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: is child of Process_Access_Request_VLR(50462976)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=2
-- sending GSM Auth Request for MSISDN:46071: tuple use_count=1 key_seq=2 auth_types=0x1 and...
-- ...rand=e7c03ba7cf0e2fde82b2dc4d63077d42
-- ...expecting sres=a29514ae
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  auth_request_sent == 1
-- needs auth, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Authen Response, VLR accepts and sends pending SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM MSISDN:46071: MM GSM AUTHENTICATION RESPONSE (sres = a29514ae)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(MSISDN:46071) received res: a2 95 14 ae 
-DVLR SUBSCR(MSISDN:46071) AUTH established GSM security context
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Removing from parent Process_Access_Request_VLR(50462976)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: Received Event PR_ARQ_E_AUTH_RES
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_PAGING_RESP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DPAG Paging success for MSISDN:46071 (event=0)
-DPAG Calling paging cbfn.
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DMSC msc_tx 91 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x01: 09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  dtap_tx_confirmed == 1
-  paging_stopped == 1
-- SMS was delivered, no requests pending for subscr
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-- conn is still open to wait for SMS ack dance
-  llist_count(&net->subscr_conns) == 1
-- MS replies with CP-ACK for received SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x04
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x04 (0x9:0x4)
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  llist_count(&net->subscr_conns) == 1
-- MS also sends RP-ACK, MSC in turn sends CP-ACK for that
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x01
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMSC msc_tx 2 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x04: 0904
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DREF MSISDN:46071: MSC conn use - 1 == 2
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(50462976)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  dtap_tx_confirmed == 1
-  bssap_clear_sent == 1
-- SMS is done, conn is gone
-  llist_count(&net->subscr_conns) == 0
----
-- subscriber sends LU Request, this time with the TMSI
-- Location Update request causes an Auth Req to MS
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(TMSI)=50462976 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_IDLE}: is child of Subscr_Conn(50462976)
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(50462976)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=3
-- sending GSM Auth Request for MSISDN:46071: tuple use_count=1 key_seq=3 auth_types=0x1 and...
-- ...rand=fa8f20b781b5881329d4fea26b1a3c51
-- ...expecting sres=5afc8d72
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  auth_request_sent == 1
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM MSISDN:46071: MM GSM AUTHENTICATION RESPONSE (sres = 5afc8d72)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(MSISDN:46071) received res: 5a fc 8d 72 
-DVLR SUBSCR(MSISDN:46071) AUTH established GSM security context
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(50462976)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(50462976)
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(50462976)
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(50462976)
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(50462976){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(50462976){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(50462976)
-DVLR sub_pres_vlr_fsm(50462976){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(50462976){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(50462976){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(50462976){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(50462976)
-DVLR sub_pres_vlr_fsm(50462976){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(50462976){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_WAIT_SUB_PRES}: lu_compl_vlr_new_tmsi()
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_WAIT_TMSI_CNF
-- sending LU Accept for MSISDN:46071, with TMSI 0x07060504
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-- a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- even though the TMSI is not acked, we can already find the subscr with it
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-  vsub != NULL == 1
-  strcmp(vsub->imsi, imsi) == 0
-  vsub->tmsi_new == 0x07060504
-  vsub->tmsi == 0x03020100
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-- MS sends TMSI Realloc Complete
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_TMSI_REALL_COMPL
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_TMSI_REALL_COMPL (0x5:0x1b)
-DMM TMSI Reallocation Completed. Subscriber: MSISDN:46071
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_NEW_TMSI_ACK
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: Received Event LU_COMPL_VLR_E_NEW_TMSI_ACK
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(50462976)
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(50462976)
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  llist_count(&net->subscr_conns) == 0
-- subscriber has the new TMSI
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub != NULL == 1
-  strcmp(vsub->imsi, imsi) == 0
-  vsub->tmsi_new == 0xffffffff
-  vsub->tmsi == 0x07060504
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
----
-- subscriber detaches, using new TMSI
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(TMSI)=117835012
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DMM IMSI DETACH for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-DMM msc_subscr_conn_close(vsub=unknown, cause=0): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_gsm_authen_tmsi: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_gsm_authen_imei
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DVLR GSUP rx 191: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000004620) Received 5 auth tuples
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending GSM Auth Request for IMSI:901700000004620: tuple use_count=1 key_seq=0 auth_types=0x1 and...
-- ...rand=585df1ae287f6e273dce07090d61320b
-- ...expecting sres=2d8b2c3e
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- If the HLR were to send a GSUP _UPDATE_LOCATION_RESULT we'd still reject
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Event VLR_ULA_E_HLR_LU_RES not permitted
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000004620: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000004620: MM GSM AUTHENTICATION RESPONSE (sres = 2d8b2c3e)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000004620) received res: 2d 8b 2c 3e 
-DVLR SUBSCR(IMSI:901700000004620) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT, and we send an ID Request for the IMEI to the MS
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_WAIT_IMEI
-DMSC msc_tx 3 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_MT_MM_ID_REQ: 051802
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-- We will only do business when the IMEI is known
-  llist_count(&net->subscr_conns) == 1
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub->imei[0] == 0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS replies with an Identity Response
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_ID_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_ID_RESP (0x5:0x19)
-DMM IDENTITY RESPONSE: MI(IMEI)=423423423423423
-DVLR set IMEI on subscriber; IMSI=901700000004620 IMEI=423423423423423
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_ID_IMEI
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_IMEI}: Received Event LU_COMPL_VLR_E_IMEI_CHECK_ACK
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_IMEI}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
-- Subscriber has the IMEI
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  strcmp(vsub->imei, "423423423423423") == 0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
----
-- subscriber detaches
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(IMSI)=901700000004620
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DMM IMSI DETACH for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-DMM msc_subscr_conn_close(vsub=unknown, cause=0): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_gsm_authen_imei: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_gsm_authen_tmsi_imei
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DVLR GSUP rx 191: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000004620) Received 5 auth tuples
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending GSM Auth Request for IMSI:901700000004620: tuple use_count=1 key_seq=0 auth_types=0x1 and...
-- ...rand=585df1ae287f6e273dce07090d61320b
-- ...expecting sres=2d8b2c3e
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- If the HLR were to send a GSUP _UPDATE_LOCATION_RESULT we'd still reject
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Event VLR_ULA_E_HLR_LU_RES not permitted
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000004620: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000004620: MM GSM AUTHENTICATION RESPONSE (sres = 2d8b2c3e)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000004620) received res: 2d 8b 2c 3e 
-DVLR SUBSCR(IMSI:901700000004620) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT, and we send an ID Request for the IMEI to the MS
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_WAIT_IMEI_TMSI
-DMSC msc_tx 3 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_MT_MM_ID_REQ: 051802
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-- We will only do business when the IMEI is known
-  llist_count(&net->subscr_conns) == 1
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub->imei[0] == 0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS replies with an Identity Response
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_ID_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_ID_RESP (0x5:0x19)
-DMM IDENTITY RESPONSE: MI(IMEI)=423423423423423
-DVLR set IMEI on subscriber; IMSI=901700000004620 IMEI=423423423423423
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_ID_IMEI
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_IMEI_TMSI}: Received Event LU_COMPL_VLR_E_IMEI_CHECK_ACK
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_IMEI_TMSI}: lu_compl_vlr_new_tmsi()
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_IMEI_TMSI}: state_chg to LU_COMPL_VLR_S_WAIT_TMSI_CNF
-- sending LU Accept for MSISDN:46071, with TMSI 0x03020100
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-- a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- even though the TMSI is not acked, we can already find the subscr with it
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub != NULL == 1
-  strcmp(vsub->imsi, imsi) == 0
-  vsub->tmsi_new == 0x03020100
-  vsub->tmsi == 0xffffffff
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-- MS sends TMSI Realloc Complete
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_TMSI_REALL_COMPL
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_TMSI_REALL_COMPL (0x5:0x1b)
-DMM TMSI Reallocation Completed. Subscriber: MSISDN:46071
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_NEW_TMSI_ACK
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: Received Event LU_COMPL_VLR_E_NEW_TMSI_ACK
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  llist_count(&net->subscr_conns) == 0
-- Subscriber has the IMEI and TMSI
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  strcmp(vsub->imei, "423423423423423") == 0
-  vsub->tmsi == 0x03020100
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
----
-- subscriber detaches, using TMSI
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(TMSI)=50462976
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DMM IMSI DETACH for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-DMM msc_subscr_conn_close(vsub=unknown, cause=0): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_gsm_authen_tmsi_imei: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_gsm_milenage_authen
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000010650 type=NORMAL
-DMM LU/new-LAC: 0/0
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000010650)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000010650 id=901700000010650
-DVLR New subscr, IMSI: 901700000010650
-DREF VLR subscr IMSI:901700000010650 usage increases to: 2
-DREF VLR subscr IMSI:901700000010650 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000000156f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000000156f0
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000010650: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000010650: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000000156f00362201039fa2f4e3d523d8619a73b4f65c3e14d21049b36efdf2208059a4f668f6fbe39231027497388b6cb044648f396aa155b95ef2410f64735036e5871319c679f4742a75ea125108704f5ba55f30000d2ee44b22c8ea9192708e229c19e791f2e4103622010c187a53a5e6b9d573cac7c74451fd46d210485aa31302208d3d50a000bf04f6e23101159ec926a50e98c034a6b7d7c9f418d2410df3a03d9ca5335641efc8e36d76cd20b25101843a645b98d00005b2d666af46c45d927087db47cf7f81e4dc703622010efa9c29a9742148d5c9070348716e1bb210469d5f9fb22083df176f0c29f1a3d2310eb50e770ddcc3060101d2f43b6c2b884241076542abce5ff9345b0e8947f4c6e019c2510f9375e6d41e1000096e7fe4ff1c27e392708706f996719ba609c
-DVLR GSUP rx 311: 0a010809710000000156f00362201039fa2f4e3d523d8619a73b4f65c3e14d21049b36efdf2208059a4f668f6fbe39231027497388b6cb044648f396aa155b95ef2410f64735036e5871319c679f4742a75ea125108704f5ba55f30000d2ee44b22c8ea9192708e229c19e791f2e4103622010c187a53a5e6b9d573cac7c74451fd46d210485aa31302208d3d50a000bf04f6e23101159ec926a50e98c034a6b7d7c9f418d2410df3a03d9ca5335641efc8e36d76cd20b25101843a645b98d00005b2d666af46c45d927087db47cf7f81e4dc703622010efa9c29a9742148d5c9070348716e1bb210469d5f9fb22083df176f0c29f1a3d2310eb50e770ddcc3060101d2f43b6c2b884241076542abce5ff9345b0e8947f4c6e019c2510f9375e6d41e1000096e7fe4ff1c27e392708706f996719ba609c
-DREF VLR subscr IMSI:901700000010650 usage increases to: 2
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000010650) Received 3 auth tuples
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending GSM Auth Request for IMSI:901700000010650: tuple use_count=1 key_seq=0 auth_types=0x3 and...
-- ...rand=39fa2f4e3d523d8619a73b4f65c3e14d
-- ...expecting sres=9b36efdf
-DREF VLR subscr IMSI:901700000010650 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000010650: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000010650: MM GSM AUTHENTICATION RESPONSE (sres = 9b36efdf)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000010650) received res: 9b 36 ef df 
-DVLR SUBSCR(IMSI:901700000010650) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000010650)
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000000156f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000000156f0
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000010650: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000010650: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000000156f00804032443f2
-DVLR GSUP rx 17: 10010809710000000156f00804032443f2
-DREF VLR subscr IMSI:901700000010650 usage increases to: 2
-DVLR IMSI:901700000010650 has MSISDN:42342
-DVLR GSUP tx: 12010809710000000156f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000000156f0
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000000156f0
-DVLR GSUP rx 11: 06010809710000000156f0
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000010650)
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000010650)
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000010650)
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000010650)
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:42342
-DREF VLR subscr MSISDN:42342 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000010650)
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000010650)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:42342, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:42342: MSC conn use - 1 == 0
-DRLL subscr MSISDN:42342: Freeing subscriber connection
-DREF VLR subscr MSISDN:42342 usage decreases to: 2
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
----
-- after a while, a new conn sends a CM Service Request. VLR responds with Auth Req, 2nd auth vector
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_CM_SERV_REQ
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_CM_SERV_REQ (0x5:0x24)
-DMM <- CM SERVICE REQUEST serv_type=0x08 MI(IMSI)=901700000010650
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000010650)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-DREF VLR subscr MSISDN:42342 usage increases to: 3
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: is child of Process_Access_Request_VLR(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=1
-- sending GSM Auth Request for MSISDN:42342: tuple use_count=1 key_seq=1 auth_types=0x3 and...
-- ...rand=c187a53a5e6b9d573cac7c74451fd46d
-- ...expecting sres=85aa3130
-DREF VLR subscr MSISDN:42342 usage decreases to: 2
-DMM MSISDN:42342: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:42342: MSC conn use - 1 == 1
-  cm_service_result_sent == 0
-  auth_request_sent == 1
-- needs auth, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Authen Response, VLR accepts with a CM Service Accept
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF MSISDN:42342: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM MSISDN:42342: MM GSM AUTHENTICATION RESPONSE (sres = 85aa3130)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(MSISDN:42342) received res: 85 aa 31 30 
-DVLR SUBSCR(MSISDN:42342) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Removing from parent Process_Access_Request_VLR(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: Received Event PR_ARQ_E_AUTH_RES
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-- sending CM Service Accept for MSISDN:42342
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_CM_SERVICE_REQ
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: received_cm_service_request = true
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF MSISDN:42342: MSC conn use - 1 == 1
-  cm_service_result_sent == 1
-- a USSD request is serviced
-  expecting USSD:
-  Your extension is 42342

-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_NC_SS:0x3b
-DREF MSISDN:42342: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_PDISC_NC_SS:0x3b (0xb:0x3b)
-DMM MSISDN:42342: rx msg GSM48_PDISC_NC_SS:0x3b: received_cm_service_request changes to false
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM USSD: Own number requested
-DMM MSISDN:42342: MSISDN = 42342
-DMSC msc_tx 43 bytes to MSISDN:42342 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_NC_SS:0x2a: 8b2a1c27a225020100302002013b301b04010f0416d9775d0e2ae3e965f73cfd7683d273104d36a3c91a0d
-- DTAP matches expected message
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000010650)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:42342, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:42342: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:42342: MSC conn use - 1 == 0
-DRLL subscr MSISDN:42342: Freeing subscriber connection
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-  bssap_clear_sent == 1
-- all requests serviced, conn has been released
-  llist_count(&net->subscr_conns) == 0
----
-- an SMS is sent, MS is paged
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:42342 usage increases to: 3
-DMM Subscriber MSISDN:42342 not paged yet, start paging.
-  RAN_GERAN_A sends out paging request to IMSI 901700000010650, TMSI 0xffffffff, LAC 0
-  strcmp(paging_expecting_imsi, imsi) == 0
-DREF VLR subscr MSISDN:42342 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:42342 usage decreases to: 3
-  paging_sent == 1
-  paging_stopped == 0
-- the subscriber and its pending request should remain
-DREF VLR subscr MSISDN:42342 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:42342 usage decreases to: 3
-- MS replies with Paging Response, and VLR sends Auth Request with third key
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_PAG_RESP
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_RR_PAG_RESP (0x6:0x27)
-DRR PAGING RESPONSE: MI(IMSI)=901700000010650
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000010650)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:42342 usage increases to: 4
-DREF VLR subscr MSISDN:42342 usage increases to: 5
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: is child of Process_Access_Request_VLR(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=2
-- sending GSM Auth Request for MSISDN:42342: tuple use_count=1 key_seq=2 auth_types=0x3 and...
-- ...rand=efa9c29a9742148d5c9070348716e1bb
-- ...expecting sres=69d5f9fb
-DREF VLR subscr MSISDN:42342 usage decreases to: 4
-DMM MSISDN:42342: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:42342: MSC conn use - 1 == 1
-  auth_request_sent == 1
-- needs auth, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Authen Response, VLR accepts and sends pending SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF MSISDN:42342: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM MSISDN:42342: MM GSM AUTHENTICATION RESPONSE (sres = 69d5f9fb)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(MSISDN:42342) received res: 69 d5 f9 fb 
-DVLR SUBSCR(MSISDN:42342) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Removing from parent Process_Access_Request_VLR(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: Received Event PR_ARQ_E_AUTH_RES
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_PAGING_RESP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DPAG Paging success for MSISDN:42342 (event=0)
-DPAG Calling paging cbfn.
-DREF VLR subscr MSISDN:42342 usage increases to: 5
-DREF MSISDN:42342: MSC conn use + 1 == 3
-DMSC msc_tx 91 bytes to MSISDN:42342 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x01: 09015801000791447758100650004c0005802443f2000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
-- DTAP matches expected message
-DREF VLR subscr MSISDN:42342 usage decreases to: 4
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:42342: MSC conn use - 1 == 2
-  dtap_tx_confirmed == 1
-  paging_stopped == 1
-- SMS was delivered, no requests pending for subscr
-DREF VLR subscr MSISDN:42342 usage increases to: 5
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:42342 usage decreases to: 4
-- conn is still open to wait for SMS ack dance
-  llist_count(&net->subscr_conns) == 1
-- MS replies with CP-ACK for received SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x04
-DREF MSISDN:42342: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x04 (0x9:0x4)
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:42342: MSC conn use - 1 == 2
-  llist_count(&net->subscr_conns) == 1
-- MS also sends RP-ACK, MSC in turn sends CP-ACK for that
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x01
-DREF MSISDN:42342: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMSC msc_tx 2 bytes to MSISDN:42342 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x04: 0904
-- DTAP matches expected message
-DREF VLR subscr MSISDN:42342 usage decreases to: 3
-DREF VLR subscr MSISDN:42342 usage decreases to: 2
-DREF MSISDN:42342: MSC conn use - 1 == 2
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000010650)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:42342, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:42342: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:42342: MSC conn use - 1 == 0
-DRLL subscr MSISDN:42342: Freeing subscriber connection
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-  dtap_tx_confirmed == 1
-  bssap_clear_sent == 1
-- SMS is done, conn is gone
-  llist_count(&net->subscr_conns) == 0
----
-- subscriber detaches
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(IMSI)=901700000010650
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-DMM IMSI DETACH for MSISDN:42342
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-DREF VLR subscr MSISDN:42342 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:42342
-DMM msc_subscr_conn_close(vsub=unknown, cause=0): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_gsm_milenage_authen: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
diff --git a/tests/msc_vlr/msc_vlr_test_gsm_authen.ok b/tests/msc_vlr/msc_vlr_test_gsm_authen.ok
deleted file mode 100644
index a965a70..0000000
--- a/tests/msc_vlr/msc_vlr_test_gsm_authen.ok
+++ /dev/null
@@ -1 +0,0 @@
-Done
diff --git a/tests/msc_vlr/msc_vlr_test_gsm_ciph.c b/tests/msc_vlr/msc_vlr_test_gsm_ciph.c
deleted file mode 100644
index 42e7c73..0000000
--- a/tests/msc_vlr/msc_vlr_test_gsm_ciph.c
+++ /dev/null
@@ -1,848 +0,0 @@
-/* Osmocom MSC+VLR end-to-end tests */
-
-/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- *
- * All Rights Reserved
- *
- * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
- *
- * 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/>.
- *
- */
-
-#include "msc_vlr_tests.h"
-
-void test_ciph()
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000004620";
-
-	comment_start();
-
-	/* implicit: net->authentication_required = true; */
-	net->a5_encryption = VLR_CIPH_A5_1;
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS");
-	/* Based on a Ki of 000102030405060708090a0b0c0d0e0f */
-	auth_request_sent = false;
-	auth_request_expect_rand = "585df1ae287f6e273dce07090d61320b";
-	auth_request_expect_autn = NULL;
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000004026f0"
-		/* 5 auth vectors... */
-		/* TL    TL     rand */
-		"0322"  "2010" "585df1ae287f6e273dce07090d61320b"
-		/*       TL     sres       TL     kc */
-			"2104" "2d8b2c3e" "2208" "61855fb81fc2a800"
-		"0322"  "2010" "12aca96fb4ffdea5c985cbafa9b6e18b"
-			"2104" "20bde240" "2208" "07fa7502e07e1c00"
-		"0322"  "2010" "e7c03ba7cf0e2fde82b2dc4d63077d42"
-			"2104" "a29514ae" "2208" "e2b234f807886400"
-		"0322"  "2010" "fa8f20b781b5881329d4fea26b1a3c51"
-			"2104" "5afc8d72" "2208" "2392f14f709ae000"
-		"0322"  "2010" "0fd4cc8dbe8715d1f439e304edfd68dc"
-			"2104" "bc8d1c5b" "2208" "da7cdd6bfe2d7000",
-		NULL);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-
-	btw("MS sends Authen Response, VLR accepts and sends Ciphering Mode Command to MS");
-	cipher_mode_cmd_sent = false;
-	ms_sends_msg("05542d8b2c3e");
-	OSMO_ASSERT(cipher_mode_cmd_sent);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("needs ciph, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Ciphering Mode Complete, VLR accepts and sends GSUP LU Req to HLR");
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("0632");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	expect_bssap_clear();
-	gsup_rx("06010809710000004026f0", NULL);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("after a while, a new conn sends a CM Service Request. VLR responds with Auth Req, 2nd auth vector");
-	cm_service_result_sent = RES_NONE;
-	auth_request_sent = false;
-	auth_request_expect_rand = "12aca96fb4ffdea5c985cbafa9b6e18b";
-	ms_sends_msg("05247803305886089910070000006402");
-	OSMO_ASSERT(g_conn);
-	OSMO_ASSERT(g_conn->conn_fsm);
-	OSMO_ASSERT(g_conn->vsub);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-
-	btw("needs auth, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS sends Authen Response, VLR accepts and requests Ciphering");
-	cipher_mode_cmd_sent = false;
-	ms_sends_msg("0554" "20bde240" /* 2nd vector's sres, s.a. */);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-	VERBOSE_ASSERT(cipher_mode_cmd_sent, == true, "%d");
-
-	btw("needs ciph, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS sends Ciphering Mode Complete, VLR accepts; above Ciphering is an implicit CM Service Accept");
-	ms_sends_msg("0632");
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-
-	btw("a USSD request is serviced");
-	dtap_expect_tx_ussd("Your extension is 46071\r");
-	expect_bssap_clear();
-	ms_sends_msg("0b3b1c15a11302010002013b300b04010f0406aa510c061b017f0100");
-	OSMO_ASSERT(dtap_tx_confirmed);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("all requests serviced, conn has been released");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("an SMS is sent, MS is paged");
-	paging_expect_imsi(imsi);
-	paging_sent = false;
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 0, "%d");
-
-	send_sms(vsub, vsub,
-		 "Privacy in residential applications is a desirable"
-		 " marketing option.");
-
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 1, "%d");
-	vlr_subscr_put(vsub);
-	vsub = NULL;
-	VERBOSE_ASSERT(paging_sent, == true, "%d");
-	VERBOSE_ASSERT(paging_stopped, == false, "%d");
-
-	btw("the subscriber and its pending request should remain");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 1, "%d");
-	vlr_subscr_put(vsub);
-
-	btw("MS replies with Paging Response, and VLR sends Auth Request with third key");
-	auth_request_sent = false;
-	auth_request_expect_rand = "e7c03ba7cf0e2fde82b2dc4d63077d42";
-	ms_sends_msg("06270703305882089910070000006402");
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-
-	btw("needs auth, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS sends Authen Response, VLR accepts and requests Ciphering");
-	cipher_mode_cmd_sent = false;
-	ms_sends_msg("0554" "a29514ae" /* 3rd vector's sres, s.a. */);
-	VERBOSE_ASSERT(cipher_mode_cmd_sent, == true, "%d");
-
-	btw("needs ciph, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS sends Ciphering Mode Complete, VLR accepts and sends pending SMS");
-	dtap_expect_tx("09" /* SMS messages */
-		       "01" /* CP-DATA */
-		       "58" /* length */
-		       "01" /* Network to MS */
-		       "00" /* reference */
-		       /* originator (gsm411_send_sms() hardcodes this weird nr) */
-		       "0791" "447758100650" /* 447785016005 */
-		       "00" /* dest */
-		       /* SMS TPDU */
-		       "4c" /* len */
-		       "00" /* SMS deliver */
-		       "05806470f1" /* originating address 46071 */
-		       "00" /* TP-PID */
-		       "00" /* GSM default alphabet */
-		       "071010" /* Y-M-D (from wrapped gsm340_gen_scts())*/
-		       "000000" /* H-M-S */
-		       "00" /* GMT+0 */
-		       "44" /* data length */
-		       "5079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0e"
-		       "d3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb"
-		       "0c7ac3e9e9b7db05");
-	ms_sends_msg("0632");
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	VERBOSE_ASSERT(paging_stopped, == true, "%d");
-
-	btw("SMS was delivered, no requests pending for subscr");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 0, "%d");
-	vlr_subscr_put(vsub);
-
-	btw("conn is still open to wait for SMS ack dance");
-	EXPECT_CONN_COUNT(1);
-
-	btw("MS replies with CP-ACK for received SMS");
-	ms_sends_msg("8904");
-	EXPECT_CONN_COUNT(1);
-
-	btw("MS also sends RP-ACK, MSC in turn sends CP-ACK for that");
-	dtap_expect_tx("0904");
-	expect_bssap_clear();
-	ms_sends_msg("890106020041020000");
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("SMS is done, conn is gone");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("subscriber detaches");
-	expect_bssap_clear();
-	ms_sends_msg("050130089910070000006402");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_ciph_tmsi()
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000004620";
-
-	comment_start();
-
-	/* implicit: net->authentication_required = true; */
-	net->a5_encryption = VLR_CIPH_A5_1;
-	net->vlr->cfg.assign_tmsi = true;
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS");
-	/* Based on a Ki of 000102030405060708090a0b0c0d0e0f */
-	auth_request_sent = false;
-	auth_request_expect_rand = "585df1ae287f6e273dce07090d61320b";
-	auth_request_expect_autn = NULL;
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000004026f0"
-		/* 5 auth vectors... */
-		/* TL    TL     rand */
-		"0322"  "2010" "585df1ae287f6e273dce07090d61320b"
-		/*       TL     sres       TL     kc */
-			"2104" "2d8b2c3e" "2208" "61855fb81fc2a800"
-		"0322"  "2010" "12aca96fb4ffdea5c985cbafa9b6e18b"
-			"2104" "20bde240" "2208" "07fa7502e07e1c00"
-		"0322"  "2010" "e7c03ba7cf0e2fde82b2dc4d63077d42"
-			"2104" "a29514ae" "2208" "e2b234f807886400"
-		"0322"  "2010" "fa8f20b781b5881329d4fea26b1a3c51"
-			"2104" "5afc8d72" "2208" "2392f14f709ae000"
-		"0322"  "2010" "0fd4cc8dbe8715d1f439e304edfd68dc"
-			"2104" "bc8d1c5b" "2208" "da7cdd6bfe2d7000",
-		NULL);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Authen Response, VLR accepts and sends Ciphering Mode Command to MS");
-	cipher_mode_cmd_sent = false;
-	ms_sends_msg("05542d8b2c3e");
-	OSMO_ASSERT(cipher_mode_cmd_sent);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-
-	btw("needs ciph, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Ciphering Mode Complete, VLR accepts and sends GSUP LU Req to HLR");
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("0632");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	gsup_rx("06010809710000004026f0", NULL);
-
-	btw("a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl");
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("even though the TMSI is not acked, we can already find the subscr with it");
-	vsub = vlr_subscr_find_by_tmsi(net->vlr, 0x03020100);
-	VERBOSE_ASSERT(vsub != NULL, == true, "%d");
-	VERBOSE_ASSERT(strcmp(vsub->imsi, imsi), == 0, "%d");
-	VERBOSE_ASSERT(vsub->tmsi_new, == 0x03020100, "0x%08x");
-	VERBOSE_ASSERT(vsub->tmsi, == GSM_RESERVED_TMSI, "0x%08x");
-	vlr_subscr_put(vsub);
-
-	btw("MS sends TMSI Realloc Complete");
-	expect_bssap_clear();
-	ms_sends_msg("055b");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	EXPECT_CONN_COUNT(0);
-
-	btw("Subscriber has the new TMSI");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	VERBOSE_ASSERT(vsub != NULL, == true, "%d");
-	VERBOSE_ASSERT(strcmp(vsub->imsi, imsi), == 0, "%d");
-	VERBOSE_ASSERT(vsub->tmsi_new, == GSM_RESERVED_TMSI, "0x%08x");
-	VERBOSE_ASSERT(vsub->tmsi, == 0x03020100, "0x%08x");
-	vlr_subscr_put(vsub);
-
-	BTW("after a while, a new conn sends a CM Service Request using above TMSI. VLR responds with Auth Req, 2nd auth vector");
-	cm_service_result_sent = RES_NONE;
-	auth_request_sent = false;
-	auth_request_expect_rand = "12aca96fb4ffdea5c985cbafa9b6e18b";
-	auth_request_expect_autn = NULL;
-	ms_sends_msg("05247803305886" "05f4" "03020100");
-	OSMO_ASSERT(g_conn);
-	OSMO_ASSERT(g_conn->conn_fsm);
-	OSMO_ASSERT(g_conn->vsub);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-
-	btw("needs auth, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS sends Authen Response, VLR accepts and requests Ciphering");
-	cipher_mode_cmd_sent = false;
-	ms_sends_msg("0554" "20bde240" /* 2nd vector's sres, s.a. */);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-	VERBOSE_ASSERT(cipher_mode_cmd_sent, == true, "%d");
-
-	btw("needs ciph, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS sends Ciphering Mode Complete, VLR accepts; above Ciphering is an implicit CM Service Accept");
-	ms_sends_msg("0632");
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-
-	btw("a USSD request is serviced");
-	dtap_expect_tx_ussd("Your extension is 46071\r");
-	expect_bssap_clear();
-	ms_sends_msg("0b3b1c15a11302010002013b300b04010f0406aa510c061b017f0100");
-	OSMO_ASSERT(dtap_tx_confirmed);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("all requests serviced, conn has been released");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("an SMS is sent, MS is paged");
-	paging_expect_tmsi(0x03020100);
-	paging_sent = false;
-	vsub = vlr_subscr_find_by_tmsi(net->vlr, 0x03020100);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 0, "%d");
-
-	send_sms(vsub, vsub,
-		 "Privacy in residential applications is a desirable"
-		 " marketing option.");
-
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 1, "%d");
-	vlr_subscr_put(vsub);
-	vsub = NULL;
-	VERBOSE_ASSERT(paging_sent, == true, "%d");
-	VERBOSE_ASSERT(paging_stopped, == false, "%d");
-
-	btw("the subscriber and its pending request should remain");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 1, "%d");
-	vlr_subscr_put(vsub);
-
-	btw("MS replies with Paging Response using TMSI, and VLR sends Auth Request with third key");
-	auth_request_sent = false;
-	auth_request_expect_rand = "e7c03ba7cf0e2fde82b2dc4d63077d42";
-	ms_sends_msg("06270703305882" "05f4" "03020100");
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-
-	btw("needs auth, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS sends Authen Response, VLR accepts and requests Ciphering");
-	cipher_mode_cmd_sent = false;
-	ms_sends_msg("0554" "a29514ae" /* 3rd vector's sres, s.a. */);
-	VERBOSE_ASSERT(cipher_mode_cmd_sent, == true, "%d");
-
-	btw("needs ciph, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS sends Ciphering Mode Complete, VLR accepts and sends pending SMS");
-	dtap_expect_tx("09" /* SMS messages */
-		       "01" /* CP-DATA */
-		       "58" /* length */
-		       "01" /* Network to MS */
-		       "00" /* reference */
-		       /* originator (gsm411_send_sms() hardcodes this weird nr) */
-		       "0791" "447758100650" /* 447785016005 */
-		       "00" /* dest */
-		       /* SMS TPDU */
-		       "4c" /* len */
-		       "00" /* SMS deliver */
-		       "05806470f1" /* originating address 46071 */
-		       "00" /* TP-PID */
-		       "00" /* GSM default alphabet */
-		       "071010" /* Y-M-D (from wrapped gsm340_gen_scts())*/
-		       "000000" /* H-M-S */
-		       "00" /* GMT+0 */
-		       "44" /* data length */
-		       "5079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0e"
-		       "d3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb"
-		       "0c7ac3e9e9b7db05");
-	ms_sends_msg("0632");
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	VERBOSE_ASSERT(paging_stopped, == true, "%d");
-
-	btw("SMS was delivered, no requests pending for subscr");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 0, "%d");
-	vlr_subscr_put(vsub);
-
-	btw("conn is still open to wait for SMS ack dance");
-	EXPECT_CONN_COUNT(1);
-
-	btw("MS replies with CP-ACK for received SMS");
-	ms_sends_msg("8904");
-	EXPECT_CONN_COUNT(1);
-
-	btw("MS also sends RP-ACK, MSC in turn sends CP-ACK for that");
-	dtap_expect_tx("0904");
-	expect_bssap_clear();
-	ms_sends_msg("890106020041020000");
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("SMS is done, conn is gone");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("subscriber detaches, using TMSI");
-	expect_bssap_clear();
-	ms_sends_msg("050130" "05f4" "03020100");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_ciph_imei()
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000004620";
-
-	comment_start();
-
-	/* implicit: net->authentication_required = true; */
-	net->a5_encryption = VLR_CIPH_A5_1;
-	net->vlr->cfg.check_imei_rqd = true;
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS");
-	/* Based on a Ki of 000102030405060708090a0b0c0d0e0f */
-	auth_request_sent = false;
-	auth_request_expect_rand = "585df1ae287f6e273dce07090d61320b";
-	auth_request_expect_autn = NULL;
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000004026f0"
-		/* 5 auth vectors... */
-		/* TL    TL     rand */
-		"0322"  "2010" "585df1ae287f6e273dce07090d61320b"
-		/*       TL     sres       TL     kc */
-			"2104" "2d8b2c3e" "2208" "61855fb81fc2a800"
-		"0322"  "2010" "12aca96fb4ffdea5c985cbafa9b6e18b"
-			"2104" "20bde240" "2208" "07fa7502e07e1c00"
-		"0322"  "2010" "e7c03ba7cf0e2fde82b2dc4d63077d42"
-			"2104" "a29514ae" "2208" "e2b234f807886400"
-		"0322"  "2010" "fa8f20b781b5881329d4fea26b1a3c51"
-			"2104" "5afc8d72" "2208" "2392f14f709ae000"
-		"0322"  "2010" "0fd4cc8dbe8715d1f439e304edfd68dc"
-			"2104" "bc8d1c5b" "2208" "da7cdd6bfe2d7000",
-		NULL);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Authen Response, VLR accepts and sends Ciphering Mode Command to MS");
-	cipher_mode_cmd_sent = false;
-	ms_sends_msg("05542d8b2c3e");
-	OSMO_ASSERT(cipher_mode_cmd_sent);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("needs ciph, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Ciphering Mode Complete, VLR accepts and sends GSUP LU Req to HLR");
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("0632");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT, and we send an ID Request for the IMEI to the MS");
-	dtap_expect_tx("051802");
-	gsup_rx("06010809710000004026f0", NULL);
-
-	btw("We will only do business when the IMEI is known");
-	EXPECT_CONN_COUNT(1);
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(vsub->imei[0], == 0, "%d");
-	vlr_subscr_put(vsub);
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS replies with an Identity Response");
-	expect_bssap_clear();
-	ms_sends_msg("0559084a32244332244332");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	btw("Subscriber has the IMEI");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(strcmp(vsub->imei, "423423423423423"), == 0, "%d");
-	vlr_subscr_put(vsub);
-
-	BTW("subscriber detaches");
-	expect_bssap_clear();
-	ms_sends_msg("050130089910070000006402");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_ciph_imeisv()
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000004620";
-
-	comment_start();
-
-	/* implicit: net->authentication_required = true; */
-	net->a5_encryption = VLR_CIPH_A5_1;
-	net->vlr->cfg.retrieve_imeisv_ciphered = true;
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS");
-	/* Based on a Ki of 000102030405060708090a0b0c0d0e0f */
-	auth_request_sent = false;
-	auth_request_expect_rand = "585df1ae287f6e273dce07090d61320b";
-	auth_request_expect_autn = NULL;
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000004026f0"
-		/* 5 auth vectors... */
-		/* TL    TL     rand */
-		"0322"  "2010" "585df1ae287f6e273dce07090d61320b"
-		/*       TL     sres       TL     kc */
-			"2104" "2d8b2c3e" "2208" "61855fb81fc2a800"
-		"0322"  "2010" "12aca96fb4ffdea5c985cbafa9b6e18b"
-			"2104" "20bde240" "2208" "07fa7502e07e1c00"
-		"0322"  "2010" "e7c03ba7cf0e2fde82b2dc4d63077d42"
-			"2104" "a29514ae" "2208" "e2b234f807886400"
-		"0322"  "2010" "fa8f20b781b5881329d4fea26b1a3c51"
-			"2104" "5afc8d72" "2208" "2392f14f709ae000"
-		"0322"  "2010" "0fd4cc8dbe8715d1f439e304edfd68dc"
-			"2104" "bc8d1c5b" "2208" "da7cdd6bfe2d7000",
-		NULL);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Authen Response, VLR accepts and sends Ciphering Mode Command to MS");
-	cipher_mode_cmd_sent = false;
-	ms_sends_msg("05542d8b2c3e");
-	VERBOSE_ASSERT(cipher_mode_cmd_sent, == true, "%d");
-	VERBOSE_ASSERT(cipher_mode_cmd_sent_with_imeisv, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("needs ciph, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(vsub->imeisv[0], == 0, "%d");
-	vlr_subscr_put(vsub);
-
-	btw("MS sends Ciphering Mode Complete with IMEISV, VLR accepts and sends GSUP LU Req to HLR");
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("063217094b32244332244332f5");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("Subscriber has the IMEISV");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(strcmp(vsub->imeisv, "4234234234234235"), == 0, "%d");
-	vlr_subscr_put(vsub);
-
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS replies with an Identity Response");
-	ms_sends_msg("0559084a32244332244332");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	expect_bssap_clear();
-	gsup_rx("06010809710000004026f0", NULL);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("subscriber detaches");
-	expect_bssap_clear();
-	ms_sends_msg("050130089910070000006402");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_ciph_tmsi_imei()
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000004620";
-
-	comment_start();
-
-	/* implicit: net->authentication_required = true; */
-	net->a5_encryption = VLR_CIPH_A5_1;
-	net->vlr->cfg.assign_tmsi = true;
-	net->vlr->cfg.check_imei_rqd = true;
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS");
-	/* Based on a Ki of 000102030405060708090a0b0c0d0e0f */
-	auth_request_sent = false;
-	auth_request_expect_rand = "585df1ae287f6e273dce07090d61320b";
-	auth_request_expect_autn = NULL;
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000004026f0"
-		/* 5 auth vectors... */
-		/* TL    TL     rand */
-		"0322"  "2010" "585df1ae287f6e273dce07090d61320b"
-		/*       TL     sres       TL     kc */
-			"2104" "2d8b2c3e" "2208" "61855fb81fc2a800"
-		"0322"  "2010" "12aca96fb4ffdea5c985cbafa9b6e18b"
-			"2104" "20bde240" "2208" "07fa7502e07e1c00"
-		"0322"  "2010" "e7c03ba7cf0e2fde82b2dc4d63077d42"
-			"2104" "a29514ae" "2208" "e2b234f807886400"
-		"0322"  "2010" "fa8f20b781b5881329d4fea26b1a3c51"
-			"2104" "5afc8d72" "2208" "2392f14f709ae000"
-		"0322"  "2010" "0fd4cc8dbe8715d1f439e304edfd68dc"
-			"2104" "bc8d1c5b" "2208" "da7cdd6bfe2d7000",
-		NULL);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Authen Response, VLR accepts and sends Ciphering Mode Command to MS");
-	cipher_mode_cmd_sent = false;
-	ms_sends_msg("05542d8b2c3e");
-	OSMO_ASSERT(cipher_mode_cmd_sent);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("needs ciph, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Ciphering Mode Complete, VLR accepts and sends GSUP LU Req to HLR");
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("0632");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT, and we send an ID Request for the IMEI to the MS");
-	dtap_expect_tx("051802");
-	gsup_rx("06010809710000004026f0", NULL);
-
-	btw("We will only do business when the IMEI is known");
-	EXPECT_CONN_COUNT(1);
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(vsub->imei[0], == 0, "%d");
-	vlr_subscr_put(vsub);
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS replies with an Identity Response");
-	ms_sends_msg("0559084a32244332244332");
-
-	btw("a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl");
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("even though the TMSI is not acked, we can already find the subscr with it");
-	vsub = vlr_subscr_find_by_tmsi(net->vlr, 0x03020100);
-	VERBOSE_ASSERT(vsub != NULL, == true, "%d");
-	VERBOSE_ASSERT(strcmp(vsub->imsi, imsi), == 0, "%d");
-	VERBOSE_ASSERT(vsub->tmsi_new, == 0x03020100, "0x%08x");
-	VERBOSE_ASSERT(vsub->tmsi, == GSM_RESERVED_TMSI, "0x%08x");
-	vlr_subscr_put(vsub);
-
-	btw("MS sends TMSI Realloc Complete");
-	expect_bssap_clear();
-	ms_sends_msg("055b");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	EXPECT_CONN_COUNT(0);
-
-	btw("Subscriber has the IMEI and TMSI");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(strcmp(vsub->imei, "423423423423423"), == 0, "%d");
-	VERBOSE_ASSERT(vsub->tmsi, == 0x03020100, "0x%08x");
-	vlr_subscr_put(vsub);
-
-	BTW("subscriber detaches, using TMSI");
-	expect_bssap_clear();
-	ms_sends_msg("050130" "05f4" "03020100");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_lu_unknown_tmsi()
-{
-	comment_start();
-
-	btw("Location Update request with unknown TMSI sends ID Request for IMSI");
-	lu_result_sent = RES_NONE;
-	dtap_expect_tx("051801");
-	ms_sends_msg("050802008168000130" "05f4" "23422342");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS tells us the IMSI, causes a GSUP LU request to HLR");
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("0559089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("having received subscriber data does not mean acceptance");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	expect_bssap_clear();
-	gsup_rx("06010809710000004026f0", NULL);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-msc_vlr_test_func_t msc_vlr_tests[] = {
-	test_ciph,
-	test_ciph_tmsi,
-	test_ciph_imei,
-	test_ciph_imeisv,
-	test_ciph_tmsi_imei,
-	NULL
-};
diff --git a/tests/msc_vlr/msc_vlr_test_gsm_ciph.err b/tests/msc_vlr/msc_vlr_test_gsm_ciph.err
deleted file mode 100644
index c219b49..0000000
--- a/tests/msc_vlr/msc_vlr_test_gsm_ciph.err
+++ /dev/null
@@ -1,1689 +0,0 @@
-===== test_ciph
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth+Ciph
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DVLR GSUP rx 191: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000004620) Received 5 auth tuples
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending GSM Auth Request for IMSI:901700000004620: tuple use_count=1 key_seq=0 auth_types=0x1 and...
-- ...rand=585df1ae287f6e273dce07090d61320b
-- ...expecting sres=2d8b2c3e
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-  auth_request_sent == 1
-- MS sends Authen Response, VLR accepts and sends Ciphering Mode Command to MS
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000004620: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000004620: MM GSM AUTHENTICATION RESPONSE (sres = 2d8b2c3e)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000004620) received res: 2d 8b 2c 3e 
-DVLR SUBSCR(IMSI:901700000004620) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-- sending Ciphering Mode Command for IMSI:901700000004620: cipher=VLR_CIPH_A5_1 kc=61855fb81fc2a800 retrieve_imeisv=0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_CIPH
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- needs ciph, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-  lu_result_sent == 0
-- MS sends Ciphering Mode Complete, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_CIPH_M_COMPL
-DRR IMSI:901700000004620: CIPHERING MODE COMPLETE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: Received Event VLR_ULA_E_CIPH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
----
-- after a while, a new conn sends a CM Service Request. VLR responds with Auth Req, 2nd auth vector
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_CM_SERV_REQ
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_CM_SERV_REQ (0x5:0x24)
-DMM <- CM SERVICE REQUEST serv_type=0x08 MI(IMSI)=901700000004620
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: rev=GSM net=GERAN Auth+Ciph
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of Process_Access_Request_VLR(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=1
-- sending GSM Auth Request for MSISDN:46071: tuple use_count=1 key_seq=1 auth_types=0x1 and...
-- ...rand=12aca96fb4ffdea5c985cbafa9b6e18b
-- ...expecting sres=20bde240
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  auth_request_sent == 1
-  cm_service_result_sent == 0
-- needs auth, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Authen Response, VLR accepts and requests Ciphering
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM MSISDN:46071: MM GSM AUTHENTICATION RESPONSE (sres = 20bde240)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(MSISDN:46071) received res: 20 bd e2 40 
-DVLR SUBSCR(MSISDN:46071) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent Process_Access_Request_VLR(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: Received Event PR_ARQ_E_AUTH_RES
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
-- sending Ciphering Mode Command for MSISDN:46071: cipher=VLR_CIPH_A5_1 kc=07fa7502e07e1c00 retrieve_imeisv=0
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_WAIT_CIPH
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  cm_service_result_sent == 0
-  cipher_mode_cmd_sent == 1
-- needs ciph, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Ciphering Mode Complete, VLR accepts; above Ciphering is an implicit CM Service Accept
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_CIPH_M_COMPL
-DRR MSISDN:46071: CIPHERING MODE COMPLETE
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_CIPH}: Received Event PR_ARQ_E_CIPH_RES
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_CIPH}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_CIPH}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_CM_SERVICE_REQ
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: received_cm_service_request = true
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-  cm_service_result_sent == 0
-- a USSD request is serviced
-  expecting USSD:
-  Your extension is 46071

-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_NC_SS:0x3b
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_PDISC_NC_SS:0x3b (0xb:0x3b)
-DMM MSISDN:46071: rx msg GSM48_PDISC_NC_SS:0x3b: received_cm_service_request changes to false
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM USSD: Own number requested
-DMM MSISDN:46071: MSISDN = 46071
-DMSC msc_tx 43 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_NC_SS:0x2a: 8b2a1c27a225020100302002013b301b04010f0416d9775d0e2ae3e965f73cfd7683d27310cd06bbc51a0d
-- DTAP matches expected message
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  bssap_clear_sent == 1
-- all requests serviced, conn has been released
-  llist_count(&net->subscr_conns) == 0
----
-- an SMS is sent, MS is paged
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DMM Subscriber MSISDN:46071 not paged yet, start paging.
-  RAN_GERAN_A sends out paging request to IMSI 901700000004620, TMSI 0xffffffff, LAC 0
-  strcmp(paging_expecting_imsi, imsi) == 0
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-  paging_sent == 1
-  paging_stopped == 0
-- the subscriber and its pending request should remain
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-- MS replies with Paging Response, and VLR sends Auth Request with third key
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_PAG_RESP
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_RR_PAG_RESP (0x6:0x27)
-DRR PAGING RESPONSE: MI(IMSI)=901700000004620
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: rev=GSM net=GERAN Auth+Ciph
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of Process_Access_Request_VLR(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=2
-- sending GSM Auth Request for MSISDN:46071: tuple use_count=1 key_seq=2 auth_types=0x1 and...
-- ...rand=e7c03ba7cf0e2fde82b2dc4d63077d42
-- ...expecting sres=a29514ae
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  auth_request_sent == 1
-- needs auth, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Authen Response, VLR accepts and requests Ciphering
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM MSISDN:46071: MM GSM AUTHENTICATION RESPONSE (sres = a29514ae)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(MSISDN:46071) received res: a2 95 14 ae 
-DVLR SUBSCR(MSISDN:46071) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent Process_Access_Request_VLR(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: Received Event PR_ARQ_E_AUTH_RES
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
-- sending Ciphering Mode Command for MSISDN:46071: cipher=VLR_CIPH_A5_1 kc=e2b234f807886400 retrieve_imeisv=0
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_WAIT_CIPH
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  cipher_mode_cmd_sent == 1
-- needs ciph, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Ciphering Mode Complete, VLR accepts and sends pending SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_CIPH_M_COMPL
-DRR MSISDN:46071: CIPHERING MODE COMPLETE
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_CIPH}: Received Event PR_ARQ_E_CIPH_RES
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_CIPH}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_CIPH}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_PAGING_RESP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DPAG Paging success for MSISDN:46071 (event=0)
-DPAG Calling paging cbfn.
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DMSC msc_tx 91 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x01: 09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-  dtap_tx_confirmed == 1
-  paging_stopped == 1
-- SMS was delivered, no requests pending for subscr
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-- conn is still open to wait for SMS ack dance
-  llist_count(&net->subscr_conns) == 1
-- MS replies with CP-ACK for received SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x04
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x04 (0x9:0x4)
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  llist_count(&net->subscr_conns) == 1
-- MS also sends RP-ACK, MSC in turn sends CP-ACK for that
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x01
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMSC msc_tx 2 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x04: 0904
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DREF MSISDN:46071: MSC conn use - 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  dtap_tx_confirmed == 1
-  bssap_clear_sent == 1
-- SMS is done, conn is gone
-  llist_count(&net->subscr_conns) == 0
----
-- subscriber detaches
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(IMSI)=901700000004620
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DMM IMSI DETACH for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-DMM msc_subscr_conn_close(vsub=unknown, cause=0): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_ciph: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_ciph_tmsi
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth+Ciph
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DVLR GSUP rx 191: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000004620) Received 5 auth tuples
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending GSM Auth Request for IMSI:901700000004620: tuple use_count=1 key_seq=0 auth_types=0x1 and...
-- ...rand=585df1ae287f6e273dce07090d61320b
-- ...expecting sres=2d8b2c3e
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends Ciphering Mode Command to MS
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000004620: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000004620: MM GSM AUTHENTICATION RESPONSE (sres = 2d8b2c3e)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000004620) received res: 2d 8b 2c 3e 
-DVLR SUBSCR(IMSI:901700000004620) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-- sending Ciphering Mode Command for IMSI:901700000004620: cipher=VLR_CIPH_A5_1 kc=61855fb81fc2a800 retrieve_imeisv=0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_CIPH
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-  auth_request_sent == 1
-- needs ciph, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-  lu_result_sent == 0
-- MS sends Ciphering Mode Complete, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_CIPH_M_COMPL
-DRR IMSI:901700000004620: CIPHERING MODE COMPLETE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: Received Event VLR_ULA_E_CIPH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: lu_compl_vlr_new_tmsi()
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_WAIT_TMSI_CNF
-- sending LU Accept for MSISDN:46071, with TMSI 0x03020100
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-- a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- even though the TMSI is not acked, we can already find the subscr with it
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub != NULL == 1
-  strcmp(vsub->imsi, imsi) == 0
-  vsub->tmsi_new == 0x03020100
-  vsub->tmsi == 0xffffffff
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-- MS sends TMSI Realloc Complete
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_TMSI_REALL_COMPL
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_TMSI_REALL_COMPL (0x5:0x1b)
-DMM TMSI Reallocation Completed. Subscriber: MSISDN:46071
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_NEW_TMSI_ACK
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: Received Event LU_COMPL_VLR_E_NEW_TMSI_ACK
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  llist_count(&net->subscr_conns) == 0
-- Subscriber has the new TMSI
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub != NULL == 1
-  strcmp(vsub->imsi, imsi) == 0
-  vsub->tmsi_new == 0xffffffff
-  vsub->tmsi == 0x03020100
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
----
-- after a while, a new conn sends a CM Service Request using above TMSI. VLR responds with Auth Req, 2nd auth vector
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_CM_SERV_REQ
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_CM_SERV_REQ (0x5:0x24)
-DMM <- CM SERVICE REQUEST serv_type=0x08 MI(TMSI)=50462976
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: is child of Subscr_Conn(50462976)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: rev=GSM net=GERAN Auth+Ciph
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_WAIT_AUTH
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: is child of Process_Access_Request_VLR(50462976)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=1
-- sending GSM Auth Request for MSISDN:46071: tuple use_count=1 key_seq=1 auth_types=0x1 and...
-- ...rand=12aca96fb4ffdea5c985cbafa9b6e18b
-- ...expecting sres=20bde240
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  auth_request_sent == 1
-  cm_service_result_sent == 0
-- needs auth, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Authen Response, VLR accepts and requests Ciphering
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM MSISDN:46071: MM GSM AUTHENTICATION RESPONSE (sres = 20bde240)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(MSISDN:46071) received res: 20 bd e2 40 
-DVLR SUBSCR(MSISDN:46071) AUTH established GSM security context
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Removing from parent Process_Access_Request_VLR(50462976)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: Received Event PR_ARQ_E_AUTH_RES
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
-- sending Ciphering Mode Command for MSISDN:46071: cipher=VLR_CIPH_A5_1 kc=07fa7502e07e1c00 retrieve_imeisv=0
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_WAIT_CIPH
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  cm_service_result_sent == 0
-  cipher_mode_cmd_sent == 1
-- needs ciph, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Ciphering Mode Complete, VLR accepts; above Ciphering is an implicit CM Service Accept
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_CIPH_M_COMPL
-DRR MSISDN:46071: CIPHERING MODE COMPLETE
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_CIPH}: Received Event PR_ARQ_E_CIPH_RES
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_CIPH}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_CIPH}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_CM_SERVICE_REQ
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: received_cm_service_request = true
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-  cm_service_result_sent == 0
-- a USSD request is serviced
-  expecting USSD:
-  Your extension is 46071

-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_NC_SS:0x3b
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_PDISC_NC_SS:0x3b (0xb:0x3b)
-DMM MSISDN:46071: rx msg GSM48_PDISC_NC_SS:0x3b: received_cm_service_request changes to false
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM USSD: Own number requested
-DMM MSISDN:46071: MSISDN = 46071
-DMSC msc_tx 43 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_NC_SS:0x2a: 8b2a1c27a225020100302002013b301b04010f0416d9775d0e2ae3e965f73cfd7683d27310cd06bbc51a0d
-- DTAP matches expected message
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(50462976)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  bssap_clear_sent == 1
-- all requests serviced, conn has been released
-  llist_count(&net->subscr_conns) == 0
----
-- an SMS is sent, MS is paged
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DMM Subscriber MSISDN:46071 not paged yet, start paging.
-  RAN_GERAN_A sends out paging request to IMSI 901700000004620, TMSI 0x03020100, LAC 0
-  paging_expecting_tmsi == 0x03020100
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-  paging_sent == 1
-  paging_stopped == 0
-- the subscriber and its pending request should remain
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-- MS replies with Paging Response using TMSI, and VLR sends Auth Request with third key
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_PAG_RESP
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_RR_PAG_RESP (0x6:0x27)
-DRR PAGING RESPONSE: MI(TMSI)=50462976
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: is child of Subscr_Conn(50462976)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: rev=GSM net=GERAN Auth+Ciph
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_WAIT_AUTH
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: is child of Process_Access_Request_VLR(50462976)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=2
-- sending GSM Auth Request for MSISDN:46071: tuple use_count=1 key_seq=2 auth_types=0x1 and...
-- ...rand=e7c03ba7cf0e2fde82b2dc4d63077d42
-- ...expecting sres=a29514ae
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  auth_request_sent == 1
-- needs auth, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Authen Response, VLR accepts and requests Ciphering
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM MSISDN:46071: MM GSM AUTHENTICATION RESPONSE (sres = a29514ae)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(MSISDN:46071) received res: a2 95 14 ae 
-DVLR SUBSCR(MSISDN:46071) AUTH established GSM security context
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Removing from parent Process_Access_Request_VLR(50462976)
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(50462976){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: Received Event PR_ARQ_E_AUTH_RES
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
-- sending Ciphering Mode Command for MSISDN:46071: cipher=VLR_CIPH_A5_1 kc=e2b234f807886400 retrieve_imeisv=0
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_WAIT_CIPH
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  cipher_mode_cmd_sent == 1
-- needs ciph, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Ciphering Mode Complete, VLR accepts and sends pending SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_CIPH_M_COMPL
-DRR MSISDN:46071: CIPHERING MODE COMPLETE
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_CIPH}: Received Event PR_ARQ_E_CIPH_RES
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_CIPH}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_CIPH}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_PAGING_RESP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DPAG Paging success for MSISDN:46071 (event=0)
-DPAG Calling paging cbfn.
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DMSC msc_tx 91 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x01: 09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-  dtap_tx_confirmed == 1
-  paging_stopped == 1
-- SMS was delivered, no requests pending for subscr
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-- conn is still open to wait for SMS ack dance
-  llist_count(&net->subscr_conns) == 1
-- MS replies with CP-ACK for received SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x04
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x04 (0x9:0x4)
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  llist_count(&net->subscr_conns) == 1
-- MS also sends RP-ACK, MSC in turn sends CP-ACK for that
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x01
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMSC msc_tx 2 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x04: 0904
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DREF MSISDN:46071: MSC conn use - 1 == 2
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(50462976)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  dtap_tx_confirmed == 1
-  bssap_clear_sent == 1
-- SMS is done, conn is gone
-  llist_count(&net->subscr_conns) == 0
----
-- subscriber detaches, using TMSI
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(TMSI)=50462976
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DMM IMSI DETACH for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-DMM msc_subscr_conn_close(vsub=unknown, cause=0): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_ciph_tmsi: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_ciph_imei
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth+Ciph
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DVLR GSUP rx 191: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000004620) Received 5 auth tuples
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending GSM Auth Request for IMSI:901700000004620: tuple use_count=1 key_seq=0 auth_types=0x1 and...
-- ...rand=585df1ae287f6e273dce07090d61320b
-- ...expecting sres=2d8b2c3e
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends Ciphering Mode Command to MS
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000004620: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000004620: MM GSM AUTHENTICATION RESPONSE (sres = 2d8b2c3e)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000004620) received res: 2d 8b 2c 3e 
-DVLR SUBSCR(IMSI:901700000004620) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-- sending Ciphering Mode Command for IMSI:901700000004620: cipher=VLR_CIPH_A5_1 kc=61855fb81fc2a800 retrieve_imeisv=0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_CIPH
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- needs ciph, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-  lu_result_sent == 0
-- MS sends Ciphering Mode Complete, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_CIPH_M_COMPL
-DRR IMSI:901700000004620: CIPHERING MODE COMPLETE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: Received Event VLR_ULA_E_CIPH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT, and we send an ID Request for the IMEI to the MS
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_WAIT_IMEI
-DMSC msc_tx 3 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_MT_MM_ID_REQ: 051802
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-- We will only do business when the IMEI is known
-  llist_count(&net->subscr_conns) == 1
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub->imei[0] == 0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS replies with an Identity Response
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_ID_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_ID_RESP (0x5:0x19)
-DMM IDENTITY RESPONSE: MI(IMEI)=423423423423423
-DVLR set IMEI on subscriber; IMSI=901700000004620 IMEI=423423423423423
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_ID_IMEI
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_IMEI}: Received Event LU_COMPL_VLR_E_IMEI_CHECK_ACK
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_IMEI}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
-- Subscriber has the IMEI
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  strcmp(vsub->imei, "423423423423423") == 0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
----
-- subscriber detaches
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(IMSI)=901700000004620
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DMM IMSI DETACH for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-DMM msc_subscr_conn_close(vsub=unknown, cause=0): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_ciph_imei: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_ciph_imeisv
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth+Ciph
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DVLR GSUP rx 191: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000004620) Received 5 auth tuples
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending GSM Auth Request for IMSI:901700000004620: tuple use_count=1 key_seq=0 auth_types=0x1 and...
-- ...rand=585df1ae287f6e273dce07090d61320b
-- ...expecting sres=2d8b2c3e
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends Ciphering Mode Command to MS
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000004620: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000004620: MM GSM AUTHENTICATION RESPONSE (sres = 2d8b2c3e)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000004620) received res: 2d 8b 2c 3e 
-DVLR SUBSCR(IMSI:901700000004620) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-- sending Ciphering Mode Command for IMSI:901700000004620: cipher=VLR_CIPH_A5_1 kc=61855fb81fc2a800 retrieve_imeisv=1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_CIPH
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  cipher_mode_cmd_sent == 1
-  cipher_mode_cmd_sent_with_imeisv == 1
-  lu_result_sent == 0
-- needs ciph, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-  lu_result_sent == 0
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-  vsub->imeisv[0] == 0
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-- MS sends Ciphering Mode Complete with IMEISV, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_CIPH_M_COMPL
-DRR IMSI:901700000004620: CIPHERING MODE COMPLETE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: Received Event VLR_ULA_E_CIPH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: got IMEISV: 4234234234234235F
-DVLR set IMEISV on subscriber; IMSI=901700000004620 IMEISV=4234234234234235
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-  lu_result_sent == 0
-- Subscriber has the IMEISV
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-  strcmp(vsub->imeisv, "4234234234234235") == 0
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS replies with an Identity Response
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_ID_RESP
-DREF IMSI:901700000004620: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_ID_RESP (0x5:0x19)
-DMM IDENTITY RESPONSE: MI(IMEI)=423423423423423
-DVLR set IMEI on subscriber; IMSI=901700000004620 IMEI=423423423423423
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_ID_IMEI
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Event VLR_ULA_E_ID_IMEI not permitted
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
----
-- subscriber detaches
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(IMSI)=901700000004620
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DMM IMSI DETACH for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-DMM msc_subscr_conn_close(vsub=unknown, cause=0): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_ciph_imeisv: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_ciph_tmsi_imei
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth+Ciph
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DVLR GSUP rx 191: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000004620) Received 5 auth tuples
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending GSM Auth Request for IMSI:901700000004620: tuple use_count=1 key_seq=0 auth_types=0x1 and...
-- ...rand=585df1ae287f6e273dce07090d61320b
-- ...expecting sres=2d8b2c3e
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends Ciphering Mode Command to MS
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000004620: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000004620: MM GSM AUTHENTICATION RESPONSE (sres = 2d8b2c3e)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000004620) received res: 2d 8b 2c 3e 
-DVLR SUBSCR(IMSI:901700000004620) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-- sending Ciphering Mode Command for IMSI:901700000004620: cipher=VLR_CIPH_A5_1 kc=61855fb81fc2a800 retrieve_imeisv=0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_CIPH
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- needs ciph, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr IMSI:901700000004620: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-  lu_result_sent == 0
-- MS sends Ciphering Mode Complete, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_CIPH_M_COMPL
-DRR IMSI:901700000004620: CIPHERING MODE COMPLETE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: Received Event VLR_ULA_E_CIPH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_CIPH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT, and we send an ID Request for the IMEI to the MS
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_WAIT_IMEI_TMSI
-DMSC msc_tx 3 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_MT_MM_ID_REQ: 051802
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-- We will only do business when the IMEI is known
-  llist_count(&net->subscr_conns) == 1
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub->imei[0] == 0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS replies with an Identity Response
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_ID_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_ID_RESP (0x5:0x19)
-DMM IDENTITY RESPONSE: MI(IMEI)=423423423423423
-DVLR set IMEI on subscriber; IMSI=901700000004620 IMEI=423423423423423
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_ID_IMEI
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_IMEI_TMSI}: Received Event LU_COMPL_VLR_E_IMEI_CHECK_ACK
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_IMEI_TMSI}: lu_compl_vlr_new_tmsi()
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_IMEI_TMSI}: state_chg to LU_COMPL_VLR_S_WAIT_TMSI_CNF
-- sending LU Accept for MSISDN:46071, with TMSI 0x03020100
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-- a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- even though the TMSI is not acked, we can already find the subscr with it
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub != NULL == 1
-  strcmp(vsub->imsi, imsi) == 0
-  vsub->tmsi_new == 0x03020100
-  vsub->tmsi == 0xffffffff
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-- MS sends TMSI Realloc Complete
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_TMSI_REALL_COMPL
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_TMSI_REALL_COMPL (0x5:0x1b)
-DMM TMSI Reallocation Completed. Subscriber: MSISDN:46071
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_NEW_TMSI_ACK
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: Received Event LU_COMPL_VLR_E_NEW_TMSI_ACK
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  llist_count(&net->subscr_conns) == 0
-- Subscriber has the IMEI and TMSI
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  strcmp(vsub->imei, "423423423423423") == 0
-  vsub->tmsi == 0x03020100
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
----
-- subscriber detaches, using TMSI
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(TMSI)=50462976
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DMM IMSI DETACH for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-DMM msc_subscr_conn_close(vsub=unknown, cause=0): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_ciph_tmsi_imei: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
diff --git a/tests/msc_vlr/msc_vlr_test_gsm_ciph.ok b/tests/msc_vlr/msc_vlr_test_gsm_ciph.ok
deleted file mode 100644
index a965a70..0000000
--- a/tests/msc_vlr/msc_vlr_test_gsm_ciph.ok
+++ /dev/null
@@ -1 +0,0 @@
-Done
diff --git a/tests/msc_vlr/msc_vlr_test_hlr_reject.c b/tests/msc_vlr/msc_vlr_test_hlr_reject.c
deleted file mode 100644
index 095da81..0000000
--- a/tests/msc_vlr/msc_vlr_test_hlr_reject.c
+++ /dev/null
@@ -1,447 +0,0 @@
-/* Osmocom MSC+VLR end-to-end tests */
-
-/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- *
- * All Rights Reserved
- *
- * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
- *
- * 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/>.
- *
- */
-
-#include "msc_vlr_tests.h"
-
-void test_hlr_rej_auth_info_unknown_imsi()
-{
-	comment_start();
-
-	net->authentication_required = true;
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _SEND_AUTH_INFO_ERROR = unknown IMSI");
-	auth_request_sent = false;
-	expect_bssap_clear();
-	gsup_rx("09" "010809710000004026f0" "020102", NULL);
-	VERBOSE_ASSERT(auth_request_sent, == false, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_REJECT, "%d");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_hlr_rej_auth_info_net_fail()
-{
-	comment_start();
-
-	net->authentication_required = true;
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _SEND_AUTH_INFO_ERROR = net fail");
-	auth_request_sent = false;
-	expect_bssap_clear();
-	gsup_rx("09" "010809710000004026f0" "020111", NULL);
-	VERBOSE_ASSERT(auth_request_sent, == false, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_REJECT, "%d");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_hlr_rej_auth_info_net_fail_no_reuse_tuples()
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000004620";
-
-	comment_start();
-
-	net->authentication_required = true;
-	net->vlr->cfg.auth_reuse_old_sets_on_error = false;
-	net->vlr->cfg.auth_tuple_max_use_count = 0;
-
-	BTW("Submit a used auth tuple in the VLR");
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS");
-	auth_request_sent = false;
-	auth_request_expect_rand = "585df1ae287f6e273dce07090d61320b";
-	auth_request_expect_autn = NULL;
-	/* Based on a Ki of 000102030405060708090a0b0c0d0e0f */
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000004026f0"
-		/* auth vectors... */
-		/* TL    TL     rand */
-		"0322"  "2010" "585df1ae287f6e273dce07090d61320b"
-		/*       TL     sres       TL     kc */
-			"2104" "2d8b2c3e" "2208" "61855fb81fc2a800"
-		,NULL);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR");
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("05542d8b2c3e");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	expect_bssap_clear();
-	gsup_rx("06010809710000004026f0", NULL);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-
-
-	BTW("Now one auth tuple is available, but used.");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	OSMO_ASSERT(vsub->last_tuple);
-	VERBOSE_ASSERT(vsub->last_tuple->use_count, == 1, "%d");
-	/* no need to look at all auth tuples, the ongoing test would take an
-	 * unexpected course if there were more. */
-	vlr_subscr_put(vsub);
-
-	BTW("Another LU wants to get new tuples; HLR sends Network Failure, we reject.");
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _SEND_AUTH_INFO_ERROR = net fail");
-	auth_request_sent = false;
-	expect_bssap_clear();
-	gsup_rx("09" "010809710000004026f0" "020111", NULL);
-	VERBOSE_ASSERT(auth_request_sent, == false, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_REJECT, "%d");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_hlr_rej_auth_info_unkown_imsi_no_reuse_tuples()
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000004620";
-
-	comment_start();
-
-	net->authentication_required = true;
-	net->vlr->cfg.auth_reuse_old_sets_on_error = true;
-	net->vlr->cfg.auth_tuple_max_use_count = 0;
-
-	BTW("Submit a used auth tuple in the VLR");
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS");
-	auth_request_sent = false;
-	auth_request_expect_rand = "585df1ae287f6e273dce07090d61320b";
-	auth_request_expect_autn = NULL;
-	/* Based on a Ki of 000102030405060708090a0b0c0d0e0f */
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000004026f0"
-		/* auth vectors... */
-		/* TL    TL     rand */
-		"0322"  "2010" "585df1ae287f6e273dce07090d61320b"
-		/*       TL     sres       TL     kc */
-			"2104" "2d8b2c3e" "2208" "61855fb81fc2a800"
-		,NULL);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR");
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("05542d8b2c3e");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	expect_bssap_clear();
-	gsup_rx("06010809710000004026f0", NULL);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-
-
-	BTW("Now one auth tuple is available, but used.");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	OSMO_ASSERT(vsub->last_tuple);
-	VERBOSE_ASSERT(vsub->last_tuple->use_count, == 1, "%d");
-	/* no need to look at all auth tuples, the ongoing test would take an
-	 * unexpected course if there were more. */
-	vlr_subscr_put(vsub);
-
-	BTW("Another LU wants to get new tuples; HLR sends IMSI Unknown. Even though we would re-use an old tuple, reject the unknown IMSI.");
-	VERBOSE_ASSERT(net->vlr->cfg.auth_reuse_old_sets_on_error, == true, "%d");
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _SEND_AUTH_INFO_ERROR = unknown IMSI");
-	auth_request_sent = false;
-	expect_bssap_clear();
-	gsup_rx("09" "010809710000004026f0" "020102", NULL);
-	VERBOSE_ASSERT(auth_request_sent, == false, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_REJECT, "%d");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_hlr_acc_but_no_auth_tuples()
-{
-	comment_start();
-
-	net->authentication_required = true;
-	net->vlr->cfg.auth_reuse_old_sets_on_error = true;
-	net->vlr->cfg.auth_tuple_max_use_count = 0;
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT but it lacks auth tuples");
-	auth_request_sent = false;
-	expect_bssap_clear();
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000004026f0"
-		/* NO auth vectors */
-		,NULL);
-	VERBOSE_ASSERT(auth_request_sent, == false, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_REJECT, "%d");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_hlr_rej_auth_info_net_fail_reuse_tuples()
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000004620";
-
-	comment_start();
-
-	net->authentication_required = true;
-	net->vlr->cfg.auth_reuse_old_sets_on_error = true;
-	net->vlr->cfg.auth_tuple_max_use_count = 0;
-
-	BTW("Submit a used auth tuple in the VLR");
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS");
-	auth_request_sent = false;
-	auth_request_expect_rand = "585df1ae287f6e273dce07090d61320b";
-	auth_request_expect_autn = NULL;
-	/* Based on a Ki of 000102030405060708090a0b0c0d0e0f */
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000004026f0"
-		/* auth vectors... */
-		/* TL    TL     rand */
-		"0322"  "2010" "585df1ae287f6e273dce07090d61320b"
-		/*       TL     sres       TL     kc */
-			"2104" "2d8b2c3e" "2208" "61855fb81fc2a800"
-		,NULL);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR");
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("05542d8b2c3e");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	expect_bssap_clear();
-	gsup_rx("06010809710000004026f0", NULL);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-
-
-	BTW("Now one auth tuple is available, but used.");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	OSMO_ASSERT(vsub->last_tuple);
-	VERBOSE_ASSERT(vsub->last_tuple->use_count, == 1, "%d");
-	/* no need to look at all auth tuples, the ongoing test would take an
-	 * unexpected course if there were more. */
-	vlr_subscr_put(vsub);
-
-	BTW("Another LU wants to get new tuples; even though HLR sends Network Failure, we are reusing the old tuples.");
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _SEND_AUTH_INFO_ERROR = net fail");
-	auth_request_sent = false;
-	gsup_rx("09" "010809710000004026f0" "020111", NULL);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR");
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("05542d8b2c3e");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	expect_bssap_clear();
-	gsup_rx("06010809710000004026f0", NULL);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	clear_vlr();
-	comment_end();
-}
-
-void test_hlr_rej_lu()
-{
-	comment_start();
-
-	btw("Location Update request causes a GSUP LU request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends UPDATE_LOCATION_ERROR");
-	expect_bssap_clear();
-	gsup_rx("05" "010809710000004026f0" "020102",
-		NULL);
-	VERBOSE_ASSERT(lu_result_sent, == RES_REJECT, "%d");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	clear_vlr();
-	comment_end();
-}
-
-void test_hlr_no_insert_data()
-{
-	comment_start();
-
-	btw("Location Update request causes a GSUP LU request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends only _UPDATE_LOCATION_RESULT, no INSERT DATA");
-	expect_bssap_clear();
-	gsup_rx("06010809710000004026f0", NULL);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	/* TODO should we wait for OSMO_GSUP_MSGT_INSERT_DATA_REQUEST? */
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-msc_vlr_test_func_t msc_vlr_tests[] = {
-	test_hlr_rej_auth_info_unknown_imsi,
-	test_hlr_rej_auth_info_net_fail,
-	test_hlr_rej_auth_info_net_fail_reuse_tuples,
-	test_hlr_rej_auth_info_net_fail_no_reuse_tuples,
-	test_hlr_rej_auth_info_unkown_imsi_no_reuse_tuples,
-	test_hlr_acc_but_no_auth_tuples,
-	test_hlr_rej_lu,
-	test_hlr_no_insert_data,
-	NULL
-};
diff --git a/tests/msc_vlr/msc_vlr_test_hlr_reject.err b/tests/msc_vlr/msc_vlr_test_hlr_reject.err
deleted file mode 100644
index c946c1e..0000000
--- a/tests/msc_vlr/msc_vlr_test_hlr_reject.err
+++ /dev/null
@@ -1,1165 +0,0 @@
-===== test_hlr_rej_auth_info_unknown_imsi
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _SEND_AUTH_INFO_ERROR = unknown IMSI
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR: 09010809710000004026f0020102
-DVLR GSUP rx 14: 09010809710000004026f0020102
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_NACK
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: GSUP: rx Auth Info Error cause: 2: IMSI unknown in HLR
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Authentication terminating with result VLR_AUTH_RES_UNKNOWN_SUBSCR
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_AUTH_FAILED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-- sending LU Reject for IMSI:901700000004620, cause 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Close event, cause 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=IMSI:901700000004620, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF IMSI:901700000004620: MSC conn use - 1 == 0
-DRLL subscr IMSI:901700000004620: Freeing subscriber connection
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 0
-DREF freeing VLR subscr IMSI:901700000004620
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 0
-  lu_result_sent == 2
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_hlr_rej_auth_info_unknown_imsi: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_hlr_rej_auth_info_net_fail
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _SEND_AUTH_INFO_ERROR = net fail
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR: 09010809710000004026f0020111
-DVLR GSUP rx 14: 09010809710000004026f0020111
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_NACK
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: GSUP: rx Auth Info Error cause: 17: Network failure
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Authentication terminating with result VLR_AUTH_RES_PROC_ERR
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_AUTH_FAILED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-- sending LU Reject for IMSI:901700000004620, cause 17
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Close event, cause 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=IMSI:901700000004620, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF IMSI:901700000004620: MSC conn use - 1 == 0
-DRLL subscr IMSI:901700000004620: Freeing subscriber connection
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 0
-DREF freeing VLR subscr IMSI:901700000004620
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 0
-  lu_result_sent == 2
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_hlr_rej_auth_info_net_fail: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_hlr_rej_auth_info_net_fail_reuse_tuples
----
-- Submit a used auth tuple in the VLR
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a800
-DVLR GSUP rx 47: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a800
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000004620) Received 1 auth tuples
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending GSM Auth Request for IMSI:901700000004620: tuple use_count=1 key_seq=0 auth_types=0x1 and...
-- ...rand=585df1ae287f6e273dce07090d61320b
-- ...expecting sres=2d8b2c3e
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000004620: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000004620: MM GSM AUTHENTICATION RESPONSE (sres = 2d8b2c3e)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000004620) received res: 2d 8b 2c 3e 
-DVLR SUBSCR(IMSI:901700000004620) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
----
-- Now one auth tuple is available, but used.
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub->last_tuple->use_count == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
----
-- Another LU wants to get new tuples; even though HLR sends Network Failure, we are reusing the old tuples.
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _SEND_AUTH_INFO_ERROR = net fail
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR: 09010809710000004026f0020111
-DVLR GSUP rx 14: 09010809710000004026f0020111
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_NACK
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: GSUP: rx Auth Info Error cause: 17: Network failure
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=2 key_seq=0
-- sending GSM Auth Request for MSISDN:46071: tuple use_count=2 key_seq=0 auth_types=0x1 and...
-- ...rand=585df1ae287f6e273dce07090d61320b
-- ...expecting sres=2d8b2c3e
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM MSISDN:46071: MM GSM AUTHENTICATION RESPONSE (sres = 2d8b2c3e)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(MSISDN:46071) received res: 2d 8b 2c 3e 
-DVLR SUBSCR(MSISDN:46071) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
-DREF freeing VLR subscr MSISDN:46071
-===== test_hlr_rej_auth_info_net_fail_reuse_tuples: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_hlr_rej_auth_info_net_fail_no_reuse_tuples
----
-- Submit a used auth tuple in the VLR
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a800
-DVLR GSUP rx 47: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a800
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000004620) Received 1 auth tuples
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending GSM Auth Request for IMSI:901700000004620: tuple use_count=1 key_seq=0 auth_types=0x1 and...
-- ...rand=585df1ae287f6e273dce07090d61320b
-- ...expecting sres=2d8b2c3e
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000004620: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000004620: MM GSM AUTHENTICATION RESPONSE (sres = 2d8b2c3e)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000004620) received res: 2d 8b 2c 3e 
-DVLR SUBSCR(IMSI:901700000004620) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
----
-- Now one auth tuple is available, but used.
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub->last_tuple->use_count == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
----
-- Another LU wants to get new tuples; HLR sends Network Failure, we reject.
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _SEND_AUTH_INFO_ERROR = net fail
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR: 09010809710000004026f0020111
-DVLR GSUP rx 14: 09010809710000004026f0020111
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_NACK
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: GSUP: rx Auth Info Error cause: 17: Network failure
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Authentication terminating with result VLR_AUTH_RES_PROC_ERR
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_AUTH_FAILED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-- sending LU Reject for MSISDN:46071, cause 17
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Close event, cause 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 0
-  lu_result_sent == 2
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-DREF freeing VLR subscr MSISDN:46071
-===== test_hlr_rej_auth_info_net_fail_no_reuse_tuples: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_hlr_rej_auth_info_unkown_imsi_no_reuse_tuples
----
-- Submit a used auth tuple in the VLR
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a800
-DVLR GSUP rx 47: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a800
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000004620) Received 1 auth tuples
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending GSM Auth Request for IMSI:901700000004620: tuple use_count=1 key_seq=0 auth_types=0x1 and...
-- ...rand=585df1ae287f6e273dce07090d61320b
-- ...expecting sres=2d8b2c3e
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000004620: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000004620: MM GSM AUTHENTICATION RESPONSE (sres = 2d8b2c3e)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000004620) received res: 2d 8b 2c 3e 
-DVLR SUBSCR(IMSI:901700000004620) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
----
-- Now one auth tuple is available, but used.
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub->last_tuple->use_count == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
----
-- Another LU wants to get new tuples; HLR sends IMSI Unknown. Even though we would re-use an old tuple, reject the unknown IMSI.
-  net->vlr->cfg.auth_reuse_old_sets_on_error == 1
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _SEND_AUTH_INFO_ERROR = unknown IMSI
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR: 09010809710000004026f0020102
-DVLR GSUP rx 14: 09010809710000004026f0020102
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_NACK
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: GSUP: rx Auth Info Error cause: 2: IMSI unknown in HLR
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Authentication terminating with result VLR_AUTH_RES_UNKNOWN_SUBSCR
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_AUTH_FAILED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-- sending LU Reject for MSISDN:46071, cause 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Close event, cause 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 0
-  lu_result_sent == 2
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-DREF freeing VLR subscr MSISDN:46071
-===== test_hlr_rej_auth_info_unkown_imsi_no_reuse_tuples: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_hlr_acc_but_no_auth_tuples
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT but it lacks auth tuples
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000004026f0
-DVLR GSUP rx 11: 0a010809710000004026f0
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Authentication terminating with result VLR_AUTH_RES_PROC_ERR
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_AUTH_FAILED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTH_FAILED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-- sending LU Reject for IMSI:901700000004620, cause 17
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Close event, cause 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=IMSI:901700000004620, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF IMSI:901700000004620: MSC conn use - 1 == 0
-DRLL subscr IMSI:901700000004620: Freeing subscriber connection
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 0
-DREF freeing VLR subscr IMSI:901700000004620
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 0
-  lu_result_sent == 2
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_hlr_acc_but_no_auth_tuples: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_hlr_rej_lu
-- Location Update request causes a GSUP LU request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends UPDATE_LOCATION_ERROR
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR: 05010809710000004026f0020102
-DVLR GSUP rx 14: 05010809710000004026f0020102
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR SUBSCR(IMSI:901700000004620) UpdateLocation failed; gmm_cause: IMSI unknown in HLR
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_NACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-- sending LU Reject for IMSI:901700000004620, cause 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Close event, cause 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=IMSI:901700000004620, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF IMSI:901700000004620: MSC conn use - 1 == 0
-DRLL subscr IMSI:901700000004620: Freeing subscriber connection
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 0
-DREF freeing VLR subscr IMSI:901700000004620
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 2
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_hlr_rej_lu: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_hlr_no_insert_data
-- Location Update request causes a GSUP LU request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends only _UPDATE_LOCATION_RESULT, no INSERT DATA
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for IMSI:901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=IMSI:901700000004620, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF IMSI:901700000004620: MSC conn use - 1 == 0
-DRLL subscr IMSI:901700000004620: Freeing subscriber connection
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
-DREF freeing VLR subscr IMSI:901700000004620
-===== test_hlr_no_insert_data: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
diff --git a/tests/msc_vlr/msc_vlr_test_hlr_reject.ok b/tests/msc_vlr/msc_vlr_test_hlr_reject.ok
deleted file mode 100644
index a965a70..0000000
--- a/tests/msc_vlr/msc_vlr_test_hlr_reject.ok
+++ /dev/null
@@ -1 +0,0 @@
-Done
diff --git a/tests/msc_vlr/msc_vlr_test_hlr_timeout.c b/tests/msc_vlr/msc_vlr_test_hlr_timeout.c
deleted file mode 100644
index c2f17c8..0000000
--- a/tests/msc_vlr/msc_vlr_test_hlr_timeout.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/* Osmocom MSC+VLR end-to-end tests */
-
-/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- *
- * All Rights Reserved
- *
- * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
- *
- * 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/>.
- *
- */
-
-#include "msc_vlr_tests.h"
-
-#include <osmocom/core/logging.h>
-
-void test_hlr_timeout_lu_auth_info()
-{
-	comment_start();
-
-	fake_time_start();
-
-	net->authentication_required = true;
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	BTW("HLR never replies");
-
-	btw("At first, we're still waiting");
-	fake_time_passes(0, 423);
-	EXPECT_CONN_COUNT(1);
-	fake_time_passes(1, 235);
-	EXPECT_CONN_COUNT(1);
-	fake_time_passes(1, 235);
-	EXPECT_CONN_COUNT(1);
-	fake_time_passes(1, 235);
-	EXPECT_CONN_COUNT(1);
-	fake_time_passes(1, 235);
-	EXPECT_CONN_COUNT(1);
-	expect_bssap_clear();
-	fake_time_passes(1, 235);
-	btw("SUBSCR_CONN_TIMEOUT has passed, conn is gone.");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-	EXPECT_CONN_COUNT(0);
-	VERBOSE_ASSERT(lu_result_sent, == RES_REJECT, "%d");
-
-	clear_vlr();
-	comment_end();
-}
-
-void test_hlr_timeout_lu_upd_loc_result()
-{
-	comment_start();
-
-	fake_time_start();
-
-	btw("Location Update request causes a GSUP LU request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	BTW("HLR never sends GSUP _UPDATE_LOCATION_RESULT");
-
-	btw("At first, we're still waiting");
-	fake_time_passes(0, 423);
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	fake_time_passes(1, 235);
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	fake_time_passes(1, 235);
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	fake_time_passes(1, 235);
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	fake_time_passes(1, 235);
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	expect_bssap_clear();
-	fake_time_passes(1, 235);
-	btw("SUBSCR_CONN_TIMEOUT has passed, conn is gone.");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-	EXPECT_CONN_COUNT(0);
-	VERBOSE_ASSERT(lu_result_sent, == RES_REJECT, "%d");
-
-	clear_vlr();
-	comment_end();
-}
-
-msc_vlr_test_func_t msc_vlr_tests[] = {
-	test_hlr_timeout_lu_auth_info,
-	test_hlr_timeout_lu_upd_loc_result,
-	NULL
-};
diff --git a/tests/msc_vlr/msc_vlr_test_hlr_timeout.err b/tests/msc_vlr/msc_vlr_test_hlr_timeout.err
deleted file mode 100644
index e34490d..0000000
--- a/tests/msc_vlr/msc_vlr_test_hlr_timeout.err
+++ /dev/null
@@ -1,189 +0,0 @@
-===== test_hlr_timeout_lu_auth_info
-- Total time passed: 0.000000 s
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
----
-- HLR never replies
-- At first, we're still waiting
-- Total time passed: 0.000423 s
-  llist_count(&net->subscr_conns) == 1
-- Total time passed: 1.000658 s
-  llist_count(&net->subscr_conns) == 1
-- Total time passed: 2.000893 s
-  llist_count(&net->subscr_conns) == 1
-- Total time passed: 3.001128 s
-  llist_count(&net->subscr_conns) == 1
-- Total time passed: 4.001363 s
-  llist_count(&net->subscr_conns) == 1
-- Total time passed: 5.001598 s
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Timeout of T0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Connection timed out
-- sending LU Reject for IMSI:901700000004620, cause 22
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Close event, cause 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=IMSI:901700000004620, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF IMSI:901700000004620: MSC conn use - 1 == 0
-DRLL subscr IMSI:901700000004620: Freeing subscriber connection
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 0
-DREF freeing VLR subscr IMSI:901700000004620
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Event SUBSCR_CONN_E_CN_CLOSE not permitted
-- SUBSCR_CONN_TIMEOUT has passed, conn is gone.
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-  lu_result_sent == 2
-===== test_hlr_timeout_lu_auth_info: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_hlr_timeout_lu_upd_loc_result
-- Total time passed: 0.000000 s
-- Location Update request causes a GSUP LU request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
----
-- HLR never sends GSUP _UPDATE_LOCATION_RESULT
-- At first, we're still waiting
-- Total time passed: 0.000423 s
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 0
-- Total time passed: 1.000658 s
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 0
-- Total time passed: 2.000893 s
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 0
-- Total time passed: 3.001128 s
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 0
-- Total time passed: 4.001363 s
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 0
-- Total time passed: 5.001598 s
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Timeout of T0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Connection timed out
-- sending LU Reject for MSISDN:46071, cause 22
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Close event, cause 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Event SUBSCR_CONN_E_CN_CLOSE not permitted
-- SUBSCR_CONN_TIMEOUT has passed, conn is gone.
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-  lu_result_sent == 2
-===== test_hlr_timeout_lu_upd_loc_result: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
diff --git a/tests/msc_vlr/msc_vlr_test_hlr_timeout.ok b/tests/msc_vlr/msc_vlr_test_hlr_timeout.ok
deleted file mode 100644
index a965a70..0000000
--- a/tests/msc_vlr/msc_vlr_test_hlr_timeout.ok
+++ /dev/null
@@ -1 +0,0 @@
-Done
diff --git a/tests/msc_vlr/msc_vlr_test_ms_timeout.c b/tests/msc_vlr/msc_vlr_test_ms_timeout.c
deleted file mode 100644
index d8a3a31..0000000
--- a/tests/msc_vlr/msc_vlr_test_ms_timeout.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/* Osmocom MSC+VLR end-to-end tests */
-
-/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- *
- * All Rights Reserved
- *
- * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
- *
- * 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/>.
- *
- */
-
-#include "msc_vlr_tests.h"
-
-void test_ms_timeout_lu_auth_resp()
-{
-	comment_start();
-
-	net->authentication_required = true;
-
-	fake_time_start();
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS");
-	auth_request_sent = false;
-	auth_request_expect_rand = "585df1ae287f6e273dce07090d61320b";
-	auth_request_expect_autn = NULL;
-	/* Based on a Ki of 000102030405060708090a0b0c0d0e0f */
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000004026f0"
-		/* auth vectors... */
-		/* TL    TL     rand */
-		"0322"  "2010" "585df1ae287f6e273dce07090d61320b"
-		/*       TL     sres       TL     kc */
-			"2104" "2d8b2c3e" "2208" "61855fb81fc2a800"
-		,NULL);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	BTW("MS fails to send an Authentication Response");
-
-	btw("At first, we're still waiting");
-	fake_time_passes(0, 423);
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	fake_time_passes(1, 235);
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	fake_time_passes(1, 235);
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	fake_time_passes(1, 235);
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	fake_time_passes(1, 235);
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	expect_bssap_clear();
-	fake_time_passes(1, 235);
-	btw("SUBSCR_CONN_TIMEOUT has passed, conn is gone.");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-	EXPECT_CONN_COUNT(0);
-	VERBOSE_ASSERT(lu_result_sent, == RES_REJECT, "%d");
-
-	comment_end();
-}
-
-void test_ms_timeout_cm_auth_resp()
-{
-	comment_start();
-
-	net->authentication_required = true;
-
-	fake_time_start();
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("08010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS");
-	auth_request_sent = false;
-	auth_request_expect_rand = "585df1ae287f6e273dce07090d61320b";
-	auth_request_expect_autn = NULL;
-	/* Based on a Ki of 000102030405060708090a0b0c0d0e0f */
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000004026f0"
-		/* 5 auth vectors... */
-		/* TL    TL     rand */
-		"0322"  "2010" "585df1ae287f6e273dce07090d61320b"
-		/*       TL     sres       TL     kc */
-			"2104" "2d8b2c3e" "2208" "61855fb81fc2a800"
-		"0322"  "2010" "12aca96fb4ffdea5c985cbafa9b6e18b"
-			"2104" "20bde240" "2208" "07fa7502e07e1c00"
-		"0322"  "2010" "e7c03ba7cf0e2fde82b2dc4d63077d42"
-			"2104" "a29514ae" "2208" "e2b234f807886400"
-		"0322"  "2010" "fa8f20b781b5881329d4fea26b1a3c51"
-			"2104" "5afc8d72" "2208" "2392f14f709ae000"
-		"0322"  "2010" "0fd4cc8dbe8715d1f439e304edfd68dc"
-			"2104" "bc8d1c5b" "2208" "da7cdd6bfe2d7000",
-		NULL);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR");
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("05542d8b2c3e");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	expect_bssap_clear();
-	gsup_rx("06010809710000004026f0", NULL);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("after a while, a new conn sends a CM Service Request. VLR responds with Auth Req, 2nd auth vector");
-	auth_request_sent = false;
-	auth_request_expect_rand = "12aca96fb4ffdea5c985cbafa9b6e18b";
-	cm_service_result_sent = RES_NONE;
-	ms_sends_msg("05247803305886089910070000006402");
-	OSMO_ASSERT(g_conn);
-	OSMO_ASSERT(g_conn->conn_fsm);
-	OSMO_ASSERT(g_conn->vsub);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-
-	BTW("MS fails to send an Authentication Response");
-
-	btw("At first, we're still waiting");
-	fake_time_passes(0, 423);
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-	fake_time_passes(1, 235);
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-	fake_time_passes(1, 235);
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-	fake_time_passes(1, 235);
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-	fake_time_passes(1, 235);
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-	expect_bssap_clear();
-	fake_time_passes(1, 235);
-	btw("SUBSCR_CONN_TIMEOUT has passed, conn is gone.");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-	EXPECT_CONN_COUNT(0);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_REJECT, "%d");
-
-	clear_vlr();
-	comment_end();
-}
-
-msc_vlr_test_func_t msc_vlr_tests[] = {
-	test_ms_timeout_lu_auth_resp,
-	test_ms_timeout_cm_auth_resp,
-	NULL
-};
diff --git a/tests/msc_vlr/msc_vlr_test_ms_timeout.err b/tests/msc_vlr/msc_vlr_test_ms_timeout.err
deleted file mode 100644
index e267c5b..0000000
--- a/tests/msc_vlr/msc_vlr_test_ms_timeout.err
+++ /dev/null
@@ -1,342 +0,0 @@
-===== test_ms_timeout_lu_auth_resp
-- Total time passed: 0.000000 s
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a800
-DVLR GSUP rx 47: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a800
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000004620) Received 1 auth tuples
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending GSM Auth Request for IMSI:901700000004620: tuple use_count=1 key_seq=0 auth_types=0x1 and...
-- ...rand=585df1ae287f6e273dce07090d61320b
-- ...expecting sres=2d8b2c3e
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
----
-- MS fails to send an Authentication Response
-- At first, we're still waiting
-- Total time passed: 0.000423 s
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 0
-- Total time passed: 1.000658 s
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 0
-- Total time passed: 2.000893 s
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 0
-- Total time passed: 3.001128 s
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 0
-- Total time passed: 4.001363 s
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 0
-- Total time passed: 5.001598 s
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Timeout of T0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Connection timed out
-- sending LU Reject for IMSI:901700000004620, cause 22
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Close event, cause 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=IMSI:901700000004620, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF IMSI:901700000004620: MSC conn use - 1 == 0
-DRLL subscr IMSI:901700000004620: Freeing subscriber connection
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 0
-DREF freeing VLR subscr IMSI:901700000004620
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Event SUBSCR_CONN_E_CN_CLOSE not permitted
-- SUBSCR_CONN_TIMEOUT has passed, conn is gone.
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-  lu_result_sent == 2
-===== test_ms_timeout_lu_auth_resp: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_ms_timeout_cm_auth_resp
-- Total time passed: 0.000000 s
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000004026f0
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DVLR GSUP rx 191: 0a010809710000004026f003222010585df1ae287f6e273dce07090d61320b21042d8b2c3e220861855fb81fc2a8000322201012aca96fb4ffdea5c985cbafa9b6e18b210420bde240220807fa7502e07e1c0003222010e7c03ba7cf0e2fde82b2dc4d63077d422104a29514ae2208e2b234f80788640003222010fa8f20b781b5881329d4fea26b1a3c5121045afc8d7222082392f14f709ae000032220100fd4cc8dbe8715d1f439e304edfd68dc2104bc8d1c5b2208da7cdd6bfe2d7000
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000004620) Received 5 auth tuples
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending GSM Auth Request for IMSI:901700000004620: tuple use_count=1 key_seq=0 auth_types=0x1 and...
-- ...rand=585df1ae287f6e273dce07090d61320b
-- ...expecting sres=2d8b2c3e
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000004620: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000004620: MM GSM AUTHENTICATION RESPONSE (sres = 2d8b2c3e)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000004620) received res: 2d 8b 2c 3e 
-DVLR SUBSCR(IMSI:901700000004620) AUTH established GSM security context
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
----
-- after a while, a new conn sends a CM Service Request. VLR responds with Auth Req, 2nd auth vector
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_CM_SERV_REQ
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_CM_SERV_REQ (0x5:0x24)
-DMM <- CM SERVICE REQUEST serv_type=0x08 MI(IMSI)=901700000004620
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: rev=GSM net=GERAN Auth (no Ciph)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: is child of Process_Access_Request_VLR(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=1
-- sending GSM Auth Request for MSISDN:46071: tuple use_count=1 key_seq=1 auth_types=0x1 and...
-- ...rand=12aca96fb4ffdea5c985cbafa9b6e18b
-- ...expecting sres=20bde240
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  cm_service_result_sent == 0
-  auth_request_sent == 1
----
-- MS fails to send an Authentication Response
-- At first, we're still waiting
-- Total time passed: 0.000423 s
-  llist_count(&net->subscr_conns) == 1
-  cm_service_result_sent == 0
-- Total time passed: 1.000658 s
-  llist_count(&net->subscr_conns) == 1
-  cm_service_result_sent == 0
-- Total time passed: 2.000893 s
-  llist_count(&net->subscr_conns) == 1
-  cm_service_result_sent == 0
-- Total time passed: 3.001128 s
-  llist_count(&net->subscr_conns) == 1
-  cm_service_result_sent == 0
-- Total time passed: 4.001363 s
-  llist_count(&net->subscr_conns) == 1
-  cm_service_result_sent == 0
-- Total time passed: 5.001598 s
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Timeout of T0
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: Connection timed out
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: proc_arq_fsm_done(VLR_PR_ARQ_RES_TIMEOUT)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_TIMEOUT
-- sending CM Service Reject for MSISDN:46071, result VLR_PR_ARQ_RES_TIMEOUT
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_CM_SERVICE_REQ
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Close event, cause 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Removing from parent Process_Access_Request_VLR(901700000004620)
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Freeing instance
-DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_WAIT_RESP}: Deallocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Event SUBSCR_CONN_E_CN_CLOSE not permitted
-- SUBSCR_CONN_TIMEOUT has passed, conn is gone.
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-  cm_service_result_sent == 2
-DREF freeing VLR subscr MSISDN:46071
-===== test_ms_timeout_cm_auth_resp: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
diff --git a/tests/msc_vlr/msc_vlr_test_ms_timeout.ok b/tests/msc_vlr/msc_vlr_test_ms_timeout.ok
deleted file mode 100644
index a965a70..0000000
--- a/tests/msc_vlr/msc_vlr_test_ms_timeout.ok
+++ /dev/null
@@ -1 +0,0 @@
-Done
diff --git a/tests/msc_vlr/msc_vlr_test_no_authen.c b/tests/msc_vlr/msc_vlr_test_no_authen.c
deleted file mode 100644
index 34e392e..0000000
--- a/tests/msc_vlr/msc_vlr_test_no_authen.c
+++ /dev/null
@@ -1,534 +0,0 @@
-/* Osmocom MSC+VLR end-to-end tests */
-
-/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- *
- * All Rights Reserved
- *
- * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
- *
- * 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/>.
- *
- */
-
-#include "msc_vlr_tests.h"
-
-void test_no_authen()
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000004620";
-	
-	/* No auth only works on GERAN */
-	rx_from_ran = RAN_GERAN_A;
-
-	comment_start();
-
-	btw("Location Update request causes a GSUP LU request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("having received subscriber data does not mean acceptance");
-	EXPECT_ACCEPTED(false);
-
-	thwart_rx_non_initial_requests();
-
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	expect_bssap_clear();
-	gsup_rx("06010809710000004026f0", NULL);
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("after a while, a new conn sends a CM Service Request");
-	cm_service_result_sent = RES_NONE;
-	ms_sends_msg("05247803305886089910070000006402");
-	OSMO_ASSERT(g_conn);
-	OSMO_ASSERT(g_conn->conn_fsm);
-	OSMO_ASSERT(g_conn->vsub);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_ACCEPTED(true);
-
-	btw("a USSD request is serviced");
-	dtap_expect_tx_ussd("Your extension is 46071\r");
-	expect_bssap_clear();
-	ms_sends_msg("0b3b1c15a11302010002013b300b04010f0406aa510c061b017f0100");
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("all requests serviced, conn has been released");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("an SMS is sent, MS is paged");
-	paging_expect_imsi(imsi);
-	paging_sent = false;
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 0, "%d");
-
-	send_sms(vsub, vsub,
-		 "Privacy in residential applications is a desirable"
-		 " marketing option.");
-
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 1, "%d");
-	vlr_subscr_put(vsub);
-	vsub = NULL;
-	VERBOSE_ASSERT(paging_sent, == true, "%d");
-	VERBOSE_ASSERT(paging_stopped, == false, "%d");
-
-	btw("the subscriber and its pending request should remain");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 1, "%d");
-	vlr_subscr_put(vsub);
-
-	btw("MS replies with Paging Response, we deliver the SMS");
-	dtap_expect_tx("09" /* SMS messages */
-		       "01" /* CP-DATA */
-		       "58" /* length */
-		       "01" /* Network to MS */
-		       "00" /* reference */
-		       /* originator (gsm411_send_sms() hardcodes this weird nr) */
-		       "0791" "447758100650" /* 447785016005 */
-		       "00" /* dest */
-		       /* SMS TPDU */
-		       "4c" /* len */
-		       "00" /* SMS deliver */
-		       "05806470f1" /* originating address 46071 */
-		       "00" /* TP-PID */
-		       "00" /* GSM default alphabet */
-		       "071010" /* Y-M-D (from wrapped gsm340_gen_scts())*/
-		       "000000" /* H-M-S */
-		       "00" /* GMT+0 */
-		       "44" /* data length */
-		       "5079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0e"
-		       "d3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb"
-		       "0c7ac3e9e9b7db05");
-	ms_sends_msg("06270703305882089910070000006402");
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	VERBOSE_ASSERT(paging_stopped, == true, "%d");
-
-	btw("SMS was delivered, no requests pending for subscr");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 0, "%d");
-	vlr_subscr_put(vsub);
-
-	btw("conn is still open to wait for SMS ack dance");
-	EXPECT_CONN_COUNT(1);
-
-	btw("MS replies with CP-ACK for received SMS");
-	ms_sends_msg("8904");
-	EXPECT_CONN_COUNT(1);
-
-	btw("MS also sends RP-ACK, MSC in turn sends CP-ACK for that");
-	dtap_expect_tx("0904");
-	expect_bssap_clear();
-	ms_sends_msg("890106020041020000");
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("SMS is done, conn is gone");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("subscriber detaches");
-	expect_bssap_clear();
-	ms_sends_msg("050130089910070000006402");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_no_authen_tmsi()
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000004620";
-
-	rx_from_ran = RAN_GERAN_A;
-
-	comment_start();
-
-	net->vlr->cfg.assign_tmsi = true;
-
-	btw("Location Update request causes a GSUP LU request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("having received subscriber data does not mean acceptance");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	gsup_rx("06010809710000004026f0", NULL);
-
-	btw("a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl");
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("even though the TMSI is not acked, we can already find the subscr with it");
-	vsub = vlr_subscr_find_by_tmsi(net->vlr, 0x03020100);
-	VERBOSE_ASSERT(vsub != NULL, == true, "%d");
-	VERBOSE_ASSERT(strcmp(vsub->imsi, imsi), == 0, "%d");
-	VERBOSE_ASSERT(vsub->tmsi_new, == 0x03020100, "0x%08x");
-	VERBOSE_ASSERT(vsub->tmsi, == GSM_RESERVED_TMSI, "0x%08x");
-	vlr_subscr_put(vsub);
-
-	btw("MS sends TMSI Realloc Complete");
-	expect_bssap_clear();
-	ms_sends_msg("055b");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	EXPECT_CONN_COUNT(0);
-
-	btw("Subscriber has the new TMSI");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	VERBOSE_ASSERT(vsub != NULL, == true, "%d");
-	VERBOSE_ASSERT(strcmp(vsub->imsi, imsi), == 0, "%d");
-	VERBOSE_ASSERT(vsub->tmsi_new, == GSM_RESERVED_TMSI, "0x%08x");
-	VERBOSE_ASSERT(vsub->tmsi, == 0x03020100, "0x%08x");
-	vlr_subscr_put(vsub);
-
-	BTW("after a while, a new conn sends a CM Service Request using above TMSI");
-	cm_service_result_sent = RES_NONE;
-	ms_sends_msg("05247803305886" "05f4" "03020100");
-	OSMO_ASSERT(g_conn);
-	OSMO_ASSERT(g_conn->conn_fsm);
-	OSMO_ASSERT(g_conn->vsub);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_ACCEPTED(true);
-
-	btw("a USSD request is serviced");
-	dtap_expect_tx_ussd("Your extension is 46071\r");
-	expect_bssap_clear();
-	ms_sends_msg("0b3b1c15a11302010002013b300b04010f0406aa510c061b017f0100");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("all requests serviced, conn has been released");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("an SMS is sent, MS is paged using above TMSI");
-	paging_expect_tmsi(0x03020100);
-	paging_sent = false;
-	vsub = vlr_subscr_find_by_tmsi(net->vlr, 0x03020100);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 0, "%d");
-
-	send_sms(vsub, vsub,
-		 "Privacy in residential applications is a desirable"
-		 " marketing option.");
-
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 1, "%d");
-	vlr_subscr_put(vsub);
-	vsub = NULL;
-	VERBOSE_ASSERT(paging_sent, == true, "%d");
-	VERBOSE_ASSERT(paging_stopped, == false, "%d");
-
-	btw("the subscriber and its pending request should remain");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 1, "%d");
-	vlr_subscr_put(vsub);
-
-	btw("MS replies with Paging Response using TMSI, we deliver the SMS");
-	dtap_expect_tx("09" /* SMS messages */
-		       "01" /* CP-DATA */
-		       "58" /* length */
-		       "01" /* Network to MS */
-		       "00" /* reference */
-		       /* originator (gsm411_send_sms() hardcodes this weird nr) */
-		       "0791" "447758100650" /* 447785016005 */
-		       "00" /* dest */
-		       /* SMS TPDU */
-		       "4c" /* len */
-		       "00" /* SMS deliver */
-		       "05806470f1" /* originating address 46071 */
-		       "00" /* TP-PID */
-		       "00" /* GSM default alphabet */
-		       "071010" /* Y-M-D (from wrapped gsm340_gen_scts())*/
-		       "000000" /* H-M-S */
-		       "00" /* GMT+0 */
-		       "44" /* data length */
-		       "5079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0e"
-		       "d3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb"
-		       "0c7ac3e9e9b7db05");
-	ms_sends_msg("06270703305882" "05f4" "03020100");
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	VERBOSE_ASSERT(paging_stopped, == true, "%d");
-
-	btw("SMS was delivered, no requests pending for subscr");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 0, "%d");
-	vlr_subscr_put(vsub);
-
-	btw("conn is still open to wait for SMS ack dance");
-	EXPECT_CONN_COUNT(1);
-
-	btw("MS replies with CP-ACK for received SMS");
-	ms_sends_msg("8904");
-	EXPECT_CONN_COUNT(1);
-
-	btw("MS also sends RP-ACK, MSC in turn sends CP-ACK for that");
-	dtap_expect_tx("0904");
-	expect_bssap_clear();
-	ms_sends_msg("890106020041020000");
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("SMS is done, conn is gone");
-	EXPECT_CONN_COUNT(0);
-
-	/* TODO: when the subscriber detaches, the vlr_subscr gets
-	 * deallocated and we no longer know the TMSI. This case is covered by
-	 * test_lu_unknown_tmsi(), so here I'd like to still have the TMSI.
-	BTW("subscriber detaches, using TMSI");
-	ms_sends_msg("050130" "05f4" "03020100");
-	EXPECT_CONN_COUNT(0);
-	 */
-
-	BTW("subscriber sends LU Request, this time with the TMSI");
-	btw("Location Update request causes a GSUP LU request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("050802008168000130" "05f4" "03020100");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("having received subscriber data does not mean acceptance");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	gsup_rx("06010809710000004026f0", NULL);
-
-	btw("a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl");
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("even though the TMSI is not acked, we can already find the subscr with it");
-	vsub = vlr_subscr_find_by_tmsi(net->vlr, 0x07060504);
-	VERBOSE_ASSERT(vsub != NULL, == true, "%d");
-	VERBOSE_ASSERT(strcmp(vsub->imsi, imsi), == 0, "%d");
-	VERBOSE_ASSERT(vsub->tmsi_new, == 0x07060504, "0x%08x");
-	VERBOSE_ASSERT(vsub->tmsi, == 0x03020100, "0x%08x");
-	vlr_subscr_put(vsub);
-
-	btw("MS sends TMSI Realloc Complete");
-	expect_bssap_clear();
-	ms_sends_msg("055b");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	EXPECT_CONN_COUNT(0);
-
-	btw("subscriber has the new TMSI");
-	vsub = vlr_subscr_find_by_tmsi(net->vlr, 0x07060504);
-	VERBOSE_ASSERT(vsub != NULL, == true, "%d");
-	VERBOSE_ASSERT(strcmp(vsub->imsi, imsi), == 0, "%d");
-	VERBOSE_ASSERT(vsub->tmsi_new, == GSM_RESERVED_TMSI, "0x%08x");
-	VERBOSE_ASSERT(vsub->tmsi, == 0x07060504, "0x%08x");
-	vlr_subscr_put(vsub);
-
-	BTW("subscriber detaches, using new TMSI");
-	expect_bssap_clear();
-	ms_sends_msg("050130" "05f4" "07060504");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_no_authen_imei()
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000004620";
-
-	rx_from_ran = RAN_GERAN_A;
-
-	comment_start();
-
-	net->vlr->cfg.check_imei_rqd = true;
-
-	btw("Location Update request causes a GSUP LU request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("having received subscriber data does not mean acceptance");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT, and we send an ID Request for the IMEI to the MS");
-	dtap_expect_tx("051802");
-	gsup_rx("06010809710000004026f0", NULL);
-
-	btw("We will only do business when the IMEI is known");
-	EXPECT_CONN_COUNT(1);
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(vsub->imei[0], == 0, "%d");
-	vlr_subscr_put(vsub);
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS replies with an Identity Response");
-	expect_bssap_clear();
-	ms_sends_msg("0559084a32244332244332");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	btw("Subscriber has the IMEI");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(strcmp(vsub->imei, "423423423423423"), == 0, "%d");
-	vlr_subscr_put(vsub);
-
-	BTW("subscriber detaches");
-	expect_bssap_clear();
-	ms_sends_msg("050130089910070000006402");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_no_authen_tmsi_imei()
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000004620";
-
-	rx_from_ran = RAN_GERAN_A;
-
-	comment_start();
-
-	net->vlr->cfg.assign_tmsi = true;
-	net->vlr->cfg.check_imei_rqd = true;
-
-	btw("Location Update request causes a GSUP LU request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("having received subscriber data does not mean acceptance");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT, and we send an ID Request for the IMEI to the MS");
-	dtap_expect_tx("051802");
-	gsup_rx("06010809710000004026f0", NULL);
-
-	btw("We will only do business when the IMEI is known");
-	EXPECT_CONN_COUNT(1);
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(vsub->imei[0], == 0, "%d");
-	vlr_subscr_put(vsub);
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS replies with an Identity Response");
-	ms_sends_msg("0559084a32244332244332");
-
-	btw("a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl");
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS sends TMSI Realloc Complete");
-	expect_bssap_clear();
-	ms_sends_msg("055b");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	btw("Subscriber has the IMEI and TMSI");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(strcmp(vsub->imei, "423423423423423"), == 0, "%d");
-	VERBOSE_ASSERT(vsub->tmsi, == 0x03020100, "0x%08x");
-	vlr_subscr_put(vsub);
-
-	BTW("subscriber detaches");
-	expect_bssap_clear();
-	ms_sends_msg("050130089910070000006402");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-msc_vlr_test_func_t msc_vlr_tests[] = {
-	test_no_authen,
-	test_no_authen_tmsi,
-	test_no_authen_imei,
-	test_no_authen_tmsi_imei,
-	NULL
-};
diff --git a/tests/msc_vlr/msc_vlr_test_no_authen.err b/tests/msc_vlr/msc_vlr_test_no_authen.err
deleted file mode 100644
index 4f40736..0000000
--- a/tests/msc_vlr/msc_vlr_test_no_authen.err
+++ /dev/null
@@ -1,1204 +0,0 @@
-===== test_no_authen
-- Location Update request causes a GSUP LU request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- having received subscriber data does not mean acceptance
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
----
-- after a while, a new conn sends a CM Service Request
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_CM_SERV_REQ
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_CM_SERV_REQ (0x5:0x24)
-DMM <- CM SERVICE REQUEST serv_type=0x08 MI(IMSI)=901700000004620
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: rev=GSM net=GERAN (no Auth)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-- sending CM Service Accept for MSISDN:46071
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_CM_SERVICE_REQ
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: received_cm_service_request = true
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  cm_service_result_sent == 1
-msc_subscr_conn_is_accepted() == true
-- a USSD request is serviced
-  expecting USSD:
-  Your extension is 46071

-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_NC_SS:0x3b
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_PDISC_NC_SS:0x3b (0xb:0x3b)
-DMM MSISDN:46071: rx msg GSM48_PDISC_NC_SS:0x3b: received_cm_service_request changes to false
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM USSD: Own number requested
-DMM MSISDN:46071: MSISDN = 46071
-DMSC msc_tx 43 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_NC_SS:0x2a: 8b2a1c27a225020100302002013b301b04010f0416d9775d0e2ae3e965f73cfd7683d27310cd06bbc51a0d
-- DTAP matches expected message
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  dtap_tx_confirmed == 1
-  bssap_clear_sent == 1
-- all requests serviced, conn has been released
-  llist_count(&net->subscr_conns) == 0
----
-- an SMS is sent, MS is paged
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DMM Subscriber MSISDN:46071 not paged yet, start paging.
-  RAN_GERAN_A sends out paging request to IMSI 901700000004620, TMSI 0xffffffff, LAC 0
-  strcmp(paging_expecting_imsi, imsi) == 0
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-  paging_sent == 1
-  paging_stopped == 0
-- the subscriber and its pending request should remain
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-- MS replies with Paging Response, we deliver the SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_PAG_RESP
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_RR_PAG_RESP (0x6:0x27)
-DRR PAGING RESPONSE: MI(IMSI)=901700000004620
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: rev=GSM net=GERAN (no Auth)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_PAGING_RESP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DPAG Paging success for MSISDN:46071 (event=0)
-DPAG Calling paging cbfn.
-DREF VLR subscr MSISDN:46071 usage increases to: 6
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DMSC msc_tx 91 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x01: 09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 5
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  dtap_tx_confirmed == 1
-  paging_stopped == 1
-- SMS was delivered, no requests pending for subscr
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-- conn is still open to wait for SMS ack dance
-  llist_count(&net->subscr_conns) == 1
-- MS replies with CP-ACK for received SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x04
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x04 (0x9:0x4)
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  llist_count(&net->subscr_conns) == 1
-- MS also sends RP-ACK, MSC in turn sends CP-ACK for that
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x01
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMSC msc_tx 2 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x04: 0904
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DREF MSISDN:46071: MSC conn use - 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  dtap_tx_confirmed == 1
-  bssap_clear_sent == 1
-- SMS is done, conn is gone
-  llist_count(&net->subscr_conns) == 0
----
-- subscriber detaches
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(IMSI)=901700000004620
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DMM IMSI DETACH for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-DMM msc_subscr_conn_close(vsub=unknown, cause=0): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_no_authen: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_no_authen_tmsi
-- Location Update request causes a GSUP LU request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- having received subscriber data does not mean acceptance
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: lu_compl_vlr_new_tmsi()
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_WAIT_TMSI_CNF
-- sending LU Accept for MSISDN:46071, with TMSI 0x03020100
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-- a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- even though the TMSI is not acked, we can already find the subscr with it
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub != NULL == 1
-  strcmp(vsub->imsi, imsi) == 0
-  vsub->tmsi_new == 0x03020100
-  vsub->tmsi == 0xffffffff
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-- MS sends TMSI Realloc Complete
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_TMSI_REALL_COMPL
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_TMSI_REALL_COMPL (0x5:0x1b)
-DMM TMSI Reallocation Completed. Subscriber: MSISDN:46071
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_NEW_TMSI_ACK
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: Received Event LU_COMPL_VLR_E_NEW_TMSI_ACK
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  llist_count(&net->subscr_conns) == 0
-- Subscriber has the new TMSI
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub != NULL == 1
-  strcmp(vsub->imsi, imsi) == 0
-  vsub->tmsi_new == 0xffffffff
-  vsub->tmsi == 0x03020100
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
----
-- after a while, a new conn sends a CM Service Request using above TMSI
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_CM_SERV_REQ
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_CM_SERV_REQ (0x5:0x24)
-DMM <- CM SERVICE REQUEST serv_type=0x08 MI(TMSI)=50462976
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: is child of Subscr_Conn(50462976)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: rev=GSM net=GERAN (no Auth)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-- sending CM Service Accept for MSISDN:46071
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_CM_SERVICE_REQ
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: received_cm_service_request = true
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  cm_service_result_sent == 1
-msc_subscr_conn_is_accepted() == true
-- a USSD request is serviced
-  expecting USSD:
-  Your extension is 46071

-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_NC_SS:0x3b
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_PDISC_NC_SS:0x3b (0xb:0x3b)
-DMM MSISDN:46071: rx msg GSM48_PDISC_NC_SS:0x3b: received_cm_service_request changes to false
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM USSD: Own number requested
-DMM MSISDN:46071: MSISDN = 46071
-DMSC msc_tx 43 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_NC_SS:0x2a: 8b2a1c27a225020100302002013b301b04010f0416d9775d0e2ae3e965f73cfd7683d27310cd06bbc51a0d
-- DTAP matches expected message
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(50462976)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  bssap_clear_sent == 1
-- all requests serviced, conn has been released
-  llist_count(&net->subscr_conns) == 0
----
-- an SMS is sent, MS is paged using above TMSI
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DMM Subscriber MSISDN:46071 not paged yet, start paging.
-  RAN_GERAN_A sends out paging request to IMSI 901700000004620, TMSI 0x03020100, LAC 0
-  paging_expecting_tmsi == 0x03020100
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-  paging_sent == 1
-  paging_stopped == 0
-- the subscriber and its pending request should remain
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-- MS replies with Paging Response using TMSI, we deliver the SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_PAG_RESP
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_RR_PAG_RESP (0x6:0x27)
-DRR PAGING RESPONSE: MI(TMSI)=50462976
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: is child of Subscr_Conn(50462976)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: rev=GSM net=GERAN (no Auth)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_PAGING_RESP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DPAG Paging success for MSISDN:46071 (event=0)
-DPAG Calling paging cbfn.
-DREF VLR subscr MSISDN:46071 usage increases to: 6
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DMSC msc_tx 91 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x01: 09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 5
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  dtap_tx_confirmed == 1
-  paging_stopped == 1
-- SMS was delivered, no requests pending for subscr
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-- conn is still open to wait for SMS ack dance
-  llist_count(&net->subscr_conns) == 1
-- MS replies with CP-ACK for received SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x04
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x04 (0x9:0x4)
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  llist_count(&net->subscr_conns) == 1
-- MS also sends RP-ACK, MSC in turn sends CP-ACK for that
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x01
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMSC msc_tx 2 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x04: 0904
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DREF MSISDN:46071: MSC conn use - 1 == 2
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(50462976)
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  dtap_tx_confirmed == 1
-  bssap_clear_sent == 1
-- SMS is done, conn is gone
-  llist_count(&net->subscr_conns) == 0
----
-- subscriber sends LU Request, this time with the TMSI
-- Location Update request causes a GSUP LU request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(TMSI)=50462976 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_IDLE}: is child of Subscr_Conn(50462976)
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(50462976)
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- having received subscriber data does not mean acceptance
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(50462976)
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(50462976){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(50462976)
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(50462976){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(50462976){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(50462976)
-DVLR sub_pres_vlr_fsm(50462976){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(50462976){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(50462976){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(50462976){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(50462976)
-DVLR sub_pres_vlr_fsm(50462976){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(50462976){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_WAIT_SUB_PRES}: lu_compl_vlr_new_tmsi()
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_WAIT_TMSI_CNF
-- sending LU Accept for MSISDN:46071, with TMSI 0x07060504
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-- a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- even though the TMSI is not acked, we can already find the subscr with it
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-  vsub != NULL == 1
-  strcmp(vsub->imsi, imsi) == 0
-  vsub->tmsi_new == 0x07060504
-  vsub->tmsi == 0x03020100
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-- MS sends TMSI Realloc Complete
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_TMSI_REALL_COMPL
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_TMSI_REALL_COMPL (0x5:0x1b)
-DMM TMSI Reallocation Completed. Subscriber: MSISDN:46071
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_NEW_TMSI_ACK
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: Received Event LU_COMPL_VLR_E_NEW_TMSI_ACK
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(50462976)
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(50462976){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(50462976)
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(50462976){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(50462976){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  llist_count(&net->subscr_conns) == 0
-- subscriber has the new TMSI
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub != NULL == 1
-  strcmp(vsub->imsi, imsi) == 0
-  vsub->tmsi_new == 0xffffffff
-  vsub->tmsi == 0x07060504
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
----
-- subscriber detaches, using new TMSI
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(TMSI)=117835012
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DMM IMSI DETACH for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-DMM msc_subscr_conn_close(vsub=unknown, cause=0): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_no_authen_tmsi: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_no_authen_imei
-- Location Update request causes a GSUP LU request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- having received subscriber data does not mean acceptance
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT, and we send an ID Request for the IMEI to the MS
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_WAIT_IMEI
-DMSC msc_tx 3 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_MT_MM_ID_REQ: 051802
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-- We will only do business when the IMEI is known
-  llist_count(&net->subscr_conns) == 1
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub->imei[0] == 0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS replies with an Identity Response
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_ID_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_ID_RESP (0x5:0x19)
-DMM IDENTITY RESPONSE: MI(IMEI)=423423423423423
-DVLR set IMEI on subscriber; IMSI=901700000004620 IMEI=423423423423423
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_ID_IMEI
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_IMEI}: Received Event LU_COMPL_VLR_E_IMEI_CHECK_ACK
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_IMEI}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
-- Subscriber has the IMEI
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  strcmp(vsub->imei, "423423423423423") == 0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
----
-- subscriber detaches
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(IMSI)=901700000004620
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DMM IMSI DETACH for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-DMM msc_subscr_conn_close(vsub=unknown, cause=0): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_no_authen_imei: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_no_authen_tmsi_imei
-- Location Update request causes a GSUP LU request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- having received subscriber data does not mean acceptance
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT, and we send an ID Request for the IMEI to the MS
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_WAIT_IMEI_TMSI
-DMSC msc_tx 3 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_MT_MM_ID_REQ: 051802
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-- We will only do business when the IMEI is known
-  llist_count(&net->subscr_conns) == 1
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  vsub->imei[0] == 0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS replies with an Identity Response
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_ID_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_ID_RESP (0x5:0x19)
-DMM IDENTITY RESPONSE: MI(IMEI)=423423423423423
-DVLR set IMEI on subscriber; IMSI=901700000004620 IMEI=423423423423423
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_ID_IMEI
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_IMEI_TMSI}: Received Event LU_COMPL_VLR_E_IMEI_CHECK_ACK
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_IMEI_TMSI}: lu_compl_vlr_new_tmsi()
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_IMEI_TMSI}: state_chg to LU_COMPL_VLR_S_WAIT_TMSI_CNF
-- sending LU Accept for MSISDN:46071, with TMSI 0x03020100
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-- a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl
-  llist_count(&net->subscr_conns) == 1
-  lu_result_sent == 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends TMSI Realloc Complete
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_TMSI_REALL_COMPL
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_TMSI_REALL_COMPL (0x5:0x1b)
-DMM TMSI Reallocation Completed. Subscriber: MSISDN:46071
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_NEW_TMSI_ACK
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: Received Event LU_COMPL_VLR_E_NEW_TMSI_ACK
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
-- Subscriber has the IMEI and TMSI
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  strcmp(vsub->imei, "423423423423423") == 0
-  vsub->tmsi == 0x03020100
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
----
-- subscriber detaches
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(IMSI)=901700000004620
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DMM IMSI DETACH for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-DMM msc_subscr_conn_close(vsub=unknown, cause=0): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_no_authen_tmsi_imei: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
diff --git a/tests/msc_vlr/msc_vlr_test_no_authen.ok b/tests/msc_vlr/msc_vlr_test_no_authen.ok
deleted file mode 100644
index a965a70..0000000
--- a/tests/msc_vlr/msc_vlr_test_no_authen.ok
+++ /dev/null
@@ -1 +0,0 @@
-Done
diff --git a/tests/msc_vlr/msc_vlr_test_reject_concurrency.c b/tests/msc_vlr/msc_vlr_test_reject_concurrency.c
deleted file mode 100644
index 2377c19..0000000
--- a/tests/msc_vlr/msc_vlr_test_reject_concurrency.c
+++ /dev/null
@@ -1,397 +0,0 @@
-/* Osmocom MSC+VLR end-to-end tests */
-
-/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- *
- * All Rights Reserved
- *
- * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
- *
- * 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/>.
- *
- */
-
-#include "msc_vlr_tests.h"
-
-void test_reject_2nd_conn()
-{
-	struct gsm_subscriber_connection *conn1;
-	comment_start();
-
-	btw("Location Update Request on one connection");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	EXPECT_CONN_COUNT(1);
-
-	btw("Another Location Update Request from the same subscriber on another connection is rejected");
-	conn1 = g_conn;
-	g_conn = NULL;
-	expect_bssap_clear();
-	ms_sends_msg("050802008168000130089910070000006402");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_REJECT, "%d");
-	EXPECT_CONN_COUNT(1);
-
-
-	BTW("The first connection can still complete its LU");
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	g_conn = conn1;
-	lu_result_sent = RES_NONE;
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	expect_bssap_clear();
-	gsup_rx("06010809710000004026f0", NULL);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	clear_vlr();
-	comment_end();
-}
-
-void _normal_lu_part1()
-{
-	btw("Location Update Request");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	EXPECT_CONN_COUNT(1);
-}
-
-void _normal_lu_part2()
-{
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	lu_result_sent = RES_NONE;
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	expect_bssap_clear();
-	gsup_rx("06010809710000004026f0", NULL);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-}
-
-void _normal_lu()
-{
-	BTW("Subscriber does a normal LU");
-	_normal_lu_part1();
-	_normal_lu_part2();
-}
-
-void _normal_cm_service_req()
-{
-	BTW("Subscriber does a normal CM Service Request");
-	cm_service_result_sent = RES_NONE;
-	ms_sends_msg("05247803305886089910070000006402");
-	OSMO_ASSERT(g_conn);
-	OSMO_ASSERT(g_conn->conn_fsm);
-	OSMO_ASSERT(g_conn->vsub);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_ACCEPTED(true);
-}
-
-void _page()
-{
-	const char *imsi = "901700000004620";
-	struct vlr_subscr *vsub;
-
-	BTW("an SMS is sent, MS is paged");
-	paging_expect_imsi(imsi);
-	paging_sent = false;
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 0, "%d");
-
-	send_sms(vsub, vsub,
-		 "Privacy in residential applications is a desirable"
-		 " marketing option.");
-
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 1, "%d");
-	vlr_subscr_put(vsub);
-	vsub = NULL;
-	VERBOSE_ASSERT(paging_sent, == true, "%d");
-	VERBOSE_ASSERT(paging_stopped, == false, "%d");
-}
-
-void _paging_resp_part1()
-{
-	btw("MS replies with Paging Response, we deliver the SMS");
-	dtap_expect_tx("09" /* SMS messages */
-		       "01" /* CP-DATA */
-		       "58" /* length */
-		       "01" /* Network to MS */
-		       "00" /* reference */
-		       /* originator (gsm411_send_sms() hardcodes this weird nr) */
-		       "0791" "447758100650" /* 447785016005 */
-		       "00" /* dest */
-		       /* SMS TPDU */
-		       "4c" /* len */
-		       "00" /* SMS deliver */
-		       "05806470f1" /* originating address 46071 */
-		       "00" /* TP-PID */
-		       "00" /* GSM default alphabet */
-		       "071010" /* Y-M-D (from wrapped gsm340_gen_scts())*/
-		       "000000" /* H-M-S */
-		       "00" /* GMT+0 */
-		       "44" /* data length */
-		       "5079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0e"
-		       "d3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb"
-		       "0c7ac3e9e9b7db05");
-	ms_sends_msg("06270703305882089910070000006402");
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	VERBOSE_ASSERT(paging_stopped, == true, "%d");
-
-	btw("conn is still open to wait for SMS ack dance");
-	EXPECT_CONN_COUNT(1);
-}
-
-void _paging_resp_part2(int expect_conn_count, bool expect_clear)
-{
-	btw("MS replies with CP-ACK for received SMS");
-	ms_sends_msg("8904");
-	EXPECT_CONN_COUNT(1);
-
-	btw("MS also sends RP-ACK, MSC in turn sends CP-ACK for that");
-	dtap_expect_tx("0904");
-	if (expect_clear)
-		expect_bssap_clear();
-	ms_sends_msg("890106020041020000");
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	if (expect_clear)
-		VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("SMS is done");
-	EXPECT_CONN_COUNT(expect_conn_count);
-}
-
-void test_reject_lu_during_lu()
-{
-	comment_start();
-
-	_normal_lu_part1();
-
-	BTW("Another Location Update Request from the same subscriber on the same conn is dropped silently");
-	ms_sends_msg("050802008168000130089910070000006402");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	EXPECT_CONN_COUNT(1);
-
-	BTW("The first LU can still complete");
-	_normal_lu_part2();
-
-	clear_vlr();
-	comment_end();
-}
-
-void test_reject_cm_during_lu()
-{
-	comment_start();
-
-	_normal_lu_part1();
-
-	BTW("A CM Service Request in the middle of a LU is rejected");
-	cm_service_result_sent = RES_NONE;
-	dtap_expect_tx("052211");
-	ms_sends_msg("05247803305886089910070000006402");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-	EXPECT_CONN_COUNT(1);
-
-	BTW("The first LU can still complete");
-	_normal_lu_part2();
-
-	clear_vlr();
-	comment_end();
-}
-
-void test_reject_paging_resp_during_lu()
-{
-	comment_start();
-
-	_normal_lu_part1();
-
-	BTW("An erratic Paging Response is dropped silently");
-	ms_sends_msg("06270703305882089910070000006402");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	EXPECT_CONN_COUNT(1);
-
-	BTW("The first LU can still complete");
-	_normal_lu_part2();
-
-	clear_vlr();
-	comment_end();
-}
-
-void test_reject_lu_during_cm()
-{
-	comment_start();
-
-	_normal_lu();
-	_normal_cm_service_req();
-
-	btw("A LU request on an open conn is dropped silently");
-	/* TODO: accept periodic LU on an already open conn? */
-	lu_result_sent = RES_NONE;
-	ms_sends_msg("050802008168000130089910070000006402");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	EXPECT_CONN_COUNT(1);
-
-	BTW("subscriber detaches");
-	expect_bssap_clear();
-	ms_sends_msg("050130089910070000006402");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	clear_vlr();
-	comment_end();
-}
-
-void test_reject_cm_during_cm()
-{
-	comment_start();
-
-	_normal_lu();
-	_normal_cm_service_req();
-
-	btw("A second CM Service Request on the same conn is accepted without another auth dance");
-	cm_service_result_sent = RES_NONE;
-	ms_sends_msg("05247803305886089910070000006402");
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(1);
-
-	BTW("subscriber detaches");
-	expect_bssap_clear();
-	ms_sends_msg("050130089910070000006402");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	clear_vlr();
-	comment_end();
-}
-
-void test_reject_paging_resp_during_cm()
-{
-	comment_start();
-
-	_normal_lu();
-	_normal_cm_service_req();
-
-	BTW("An erratic Paging Response on the same conn is dropped silently");
-	ms_sends_msg("06270703305882089910070000006402");
-	EXPECT_CONN_COUNT(1);
-
-	BTW("The original CM Service Request can conclude");
-	btw("a USSD request is serviced");
-	dtap_expect_tx_ussd("Your extension is 46071\r");
-	expect_bssap_clear();
-	ms_sends_msg("0b3b1c15a11302010002013b300b04010f0406aa510c061b017f0100");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("all requests serviced, conn has been released");
-	EXPECT_CONN_COUNT(0);
-
-	clear_vlr();
-	comment_end();
-}
-
-void test_reject_paging_resp_during_paging_resp()
-{
-	comment_start();
-
-	_normal_lu();
-	_page();
-	_paging_resp_part1();
-
-	BTW("MS sends another erratic Paging Response which is dropped silently");
-	ms_sends_msg("06270703305882089910070000006402");
-
-	_paging_resp_part2(0, true);
-
-	clear_vlr();
-	comment_end();
-}
-
-void test_reject_lu_during_paging_resp()
-{
-	comment_start();
-
-	_normal_lu();
-	_page();
-	_paging_resp_part1();
-
-	BTW("MS sends erratic LU Request, which is dropped silently");
-	lu_result_sent = RES_NONE;
-	ms_sends_msg("050802008168000130089910070000006402");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	EXPECT_CONN_COUNT(1);
-
-	_paging_resp_part2(0, true);
-
-	clear_vlr();
-	comment_end();
-}
-
-void test_accept_cm_during_paging_resp()
-{
-	comment_start();
-
-	_normal_lu();
-	_page();
-	_paging_resp_part1();
-
-	BTW("CM Service Request during open connection is accepted");
-	cm_service_result_sent = RES_NONE;
-	ms_sends_msg("05247803305886089910070000006402");
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(1);
-	VERBOSE_ASSERT(g_conn->received_cm_service_request, == true, "%d");
-
-	_paging_resp_part2(1, false);
-
-	BTW("subscriber detaches");
-	expect_bssap_clear();
-	ms_sends_msg("050130089910070000006402");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	clear_vlr();
-	comment_end();
-}
-
-msc_vlr_test_func_t msc_vlr_tests[] = {
-	test_reject_2nd_conn,
-	test_reject_lu_during_lu,
-	test_reject_cm_during_lu,
-	test_reject_paging_resp_during_lu,
-	test_reject_lu_during_cm,
-	test_reject_cm_during_cm,
-	test_reject_paging_resp_during_cm,
-	test_reject_lu_during_paging_resp,
-	test_accept_cm_during_paging_resp,
-	test_reject_paging_resp_during_paging_resp,
-	NULL
-};
diff --git a/tests/msc_vlr/msc_vlr_test_reject_concurrency.err b/tests/msc_vlr/msc_vlr_test_reject_concurrency.err
deleted file mode 100644
index 00945cb..0000000
--- a/tests/msc_vlr/msc_vlr_test_reject_concurrency.err
+++ /dev/null
@@ -1,1817 +0,0 @@
-===== test_reject_2nd_conn
-- Location Update Request on one connection
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-  llist_count(&net->subscr_conns) == 1
-- Another Location Update Request from the same subscriber on another connection is rejected
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: A Location Updating process is already pending for this subscriber. Aborting.
-- sending LU Reject for unknown, cause 22
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Close event, cause 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=unknown, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DRR 901700000004620: internal error during Location Updating attempt
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-  lu_result_sent == 2
-  llist_count(&net->subscr_conns) == 1
----
-- The first connection can still complete its LU
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
-DREF freeing VLR subscr MSISDN:46071
-===== test_reject_2nd_conn: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_reject_lu_during_lu
-- Location Update Request
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-  llist_count(&net->subscr_conns) == 1
----
-- Another Location Update Request from the same subscriber on the same conn is dropped silently
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-DREF IMSI:901700000004620: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DMM 901700000004620: Error: connection already in use
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-  llist_count(&net->subscr_conns) == 1
----
-- The first LU can still complete
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
-DREF freeing VLR subscr MSISDN:46071
-===== test_reject_lu_during_lu: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_reject_cm_during_lu
-- Location Update Request
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-  llist_count(&net->subscr_conns) == 1
----
-- A CM Service Request in the middle of a LU is rejected
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_CM_SERV_REQ
-DREF IMSI:901700000004620: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_CM_SERV_REQ (0x5:0x24)
-DMM <- CM SERVICE REQUEST serv_type=0x08 MI(IMSI)=901700000004620
-DMM IMSI:901700000004620: connection already in use
-DMM -> CM SERVICE Reject cause: 17
-DMSC msc_tx 3 bytes to IMSI:901700000004620 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_MT_MM_CM_SERV_REJ: 052211
-- DTAP matches expected message
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-  cm_service_result_sent == 0
-  llist_count(&net->subscr_conns) == 1
----
-- The first LU can still complete
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
-DREF freeing VLR subscr MSISDN:46071
-===== test_reject_cm_during_lu: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_reject_paging_resp_during_lu
-- Location Update Request
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-  llist_count(&net->subscr_conns) == 1
----
-- An erratic Paging Response is dropped silently
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_PAG_RESP
-DREF IMSI:901700000004620: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_RR_PAG_RESP (0x6:0x27)
-DRR PAGING RESPONSE: MI(IMSI)=901700000004620
-DMM 901700000004620: Error: connection already in use
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-  llist_count(&net->subscr_conns) == 1
----
-- The first LU can still complete
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
-DREF freeing VLR subscr MSISDN:46071
-===== test_reject_paging_resp_during_lu: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_reject_lu_during_cm
----
-- Subscriber does a normal LU
-- Location Update Request
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-  llist_count(&net->subscr_conns) == 1
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
----
-- Subscriber does a normal CM Service Request
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_CM_SERV_REQ
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_CM_SERV_REQ (0x5:0x24)
-DMM <- CM SERVICE REQUEST serv_type=0x08 MI(IMSI)=901700000004620
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: rev=GSM net=GERAN (no Auth)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-- sending CM Service Accept for MSISDN:46071
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_CM_SERVICE_REQ
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: received_cm_service_request = true
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  cm_service_result_sent == 1
-msc_subscr_conn_is_accepted() == true
-- A LU request on an open conn is dropped silently
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DMM 901700000004620: Error: connection already in use
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  lu_result_sent == 0
-  llist_count(&net->subscr_conns) == 1
----
-- subscriber detaches
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(IMSI)=901700000004620
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DMM IMSI DETACH for MSISDN:46071
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_ERROR)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Deallocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=0): already dispatching release, ignore.
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_reject_lu_during_cm: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_reject_cm_during_cm
----
-- Subscriber does a normal LU
-- Location Update Request
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-  llist_count(&net->subscr_conns) == 1
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
----
-- Subscriber does a normal CM Service Request
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_CM_SERV_REQ
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_CM_SERV_REQ (0x5:0x24)
-DMM <- CM SERVICE REQUEST serv_type=0x08 MI(IMSI)=901700000004620
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: rev=GSM net=GERAN (no Auth)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-- sending CM Service Accept for MSISDN:46071
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_CM_SERVICE_REQ
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: received_cm_service_request = true
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  cm_service_result_sent == 1
-msc_subscr_conn_is_accepted() == true
-- A second CM Service Request on the same conn is accepted without another auth dance
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_CM_SERV_REQ
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_CM_SERV_REQ (0x5:0x24)
-DMM <- CM SERVICE REQUEST serv_type=0x08 MI(IMSI)=901700000004620
-DMM MSISDN:46071: re-using already accepted connection
-- sending CM Service Accept for MSISDN:46071
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  cm_service_result_sent == 1
-  llist_count(&net->subscr_conns) == 1
----
-- subscriber detaches
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(IMSI)=901700000004620
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DMM IMSI DETACH for MSISDN:46071
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_ERROR)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Deallocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=0): already dispatching release, ignore.
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_reject_cm_during_cm: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_reject_paging_resp_during_cm
----
-- Subscriber does a normal LU
-- Location Update Request
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-  llist_count(&net->subscr_conns) == 1
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
----
-- Subscriber does a normal CM Service Request
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_CM_SERV_REQ
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_CM_SERV_REQ (0x5:0x24)
-DMM <- CM SERVICE REQUEST serv_type=0x08 MI(IMSI)=901700000004620
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: rev=GSM net=GERAN (no Auth)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-- sending CM Service Accept for MSISDN:46071
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_CM_SERVICE_REQ
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: received_cm_service_request = true
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  cm_service_result_sent == 1
-msc_subscr_conn_is_accepted() == true
----
-- An erratic Paging Response on the same conn is dropped silently
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_PAG_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_RR_PAG_RESP (0x6:0x27)
-DRR PAGING RESPONSE: MI(IMSI)=901700000004620
-DMM 901700000004620: Error: connection already in use
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  llist_count(&net->subscr_conns) == 1
----
-- The original CM Service Request can conclude
-- a USSD request is serviced
-  expecting USSD:
-  Your extension is 46071

-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_NC_SS:0x3b
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_PDISC_NC_SS:0x3b (0xb:0x3b)
-DMM MSISDN:46071: rx msg GSM48_PDISC_NC_SS:0x3b: received_cm_service_request changes to false
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM USSD: Own number requested
-DMM MSISDN:46071: MSISDN = 46071
-DMSC msc_tx 43 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_NC_SS:0x2a: 8b2a1c27a225020100302002013b301b04010f0416d9775d0e2ae3e965f73cfd7683d27310cd06bbc51a0d
-- DTAP matches expected message
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  bssap_clear_sent == 1
-- all requests serviced, conn has been released
-  llist_count(&net->subscr_conns) == 0
-DREF freeing VLR subscr MSISDN:46071
-===== test_reject_paging_resp_during_cm: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_reject_lu_during_paging_resp
----
-- Subscriber does a normal LU
-- Location Update Request
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-  llist_count(&net->subscr_conns) == 1
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
----
-- an SMS is sent, MS is paged
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DMM Subscriber MSISDN:46071 not paged yet, start paging.
-  RAN_GERAN_A sends out paging request to IMSI 901700000004620, TMSI 0xffffffff, LAC 0
-  strcmp(paging_expecting_imsi, imsi) == 0
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-  paging_sent == 1
-  paging_stopped == 0
-- MS replies with Paging Response, we deliver the SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_PAG_RESP
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_RR_PAG_RESP (0x6:0x27)
-DRR PAGING RESPONSE: MI(IMSI)=901700000004620
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: rev=GSM net=GERAN (no Auth)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_PAGING_RESP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DPAG Paging success for MSISDN:46071 (event=0)
-DPAG Calling paging cbfn.
-DREF VLR subscr MSISDN:46071 usage increases to: 6
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DMSC msc_tx 91 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x01: 09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 5
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  dtap_tx_confirmed == 1
-  paging_stopped == 1
-- conn is still open to wait for SMS ack dance
-  llist_count(&net->subscr_conns) == 1
----
-- MS sends erratic LU Request, which is dropped silently
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DMM 901700000004620: Error: connection already in use
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  lu_result_sent == 0
-  llist_count(&net->subscr_conns) == 1
-- MS replies with CP-ACK for received SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x04
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x04 (0x9:0x4)
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  llist_count(&net->subscr_conns) == 1
-- MS also sends RP-ACK, MSC in turn sends CP-ACK for that
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x01
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMSC msc_tx 2 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x04: 0904
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DREF MSISDN:46071: MSC conn use - 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  dtap_tx_confirmed == 1
-  bssap_clear_sent == 1
-- SMS is done
-  llist_count(&net->subscr_conns) == 0
-DREF freeing VLR subscr MSISDN:46071
-===== test_reject_lu_during_paging_resp: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_accept_cm_during_paging_resp
----
-- Subscriber does a normal LU
-- Location Update Request
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-  llist_count(&net->subscr_conns) == 1
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
----
-- an SMS is sent, MS is paged
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DMM Subscriber MSISDN:46071 not paged yet, start paging.
-  RAN_GERAN_A sends out paging request to IMSI 901700000004620, TMSI 0xffffffff, LAC 0
-  strcmp(paging_expecting_imsi, imsi) == 0
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-  paging_sent == 1
-  paging_stopped == 0
-- MS replies with Paging Response, we deliver the SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_PAG_RESP
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_RR_PAG_RESP (0x6:0x27)
-DRR PAGING RESPONSE: MI(IMSI)=901700000004620
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: rev=GSM net=GERAN (no Auth)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_PAGING_RESP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DPAG Paging success for MSISDN:46071 (event=0)
-DPAG Calling paging cbfn.
-DREF VLR subscr MSISDN:46071 usage increases to: 6
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DMSC msc_tx 91 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x01: 09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 5
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  dtap_tx_confirmed == 1
-  paging_stopped == 1
-- conn is still open to wait for SMS ack dance
-  llist_count(&net->subscr_conns) == 1
----
-- CM Service Request during open connection is accepted
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_CM_SERV_REQ
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_MT_MM_CM_SERV_REQ (0x5:0x24)
-DMM <- CM SERVICE REQUEST serv_type=0x08 MI(IMSI)=901700000004620
-DMM MSISDN:46071: re-using already accepted connection
-- sending CM Service Accept for MSISDN:46071
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  cm_service_result_sent == 1
-  llist_count(&net->subscr_conns) == 1
-  g_conn->received_cm_service_request == 1
-- MS replies with CP-ACK for received SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x04
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x04 (0x9:0x4)
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: bump: still awaiting first request after a CM Service Request
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  llist_count(&net->subscr_conns) == 1
-- MS also sends RP-ACK, MSC in turn sends CP-ACK for that
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x01
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMSC msc_tx 2 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x04: 0904
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DREF MSISDN:46071: MSC conn use - 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: bump: still awaiting first request after a CM Service Request
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  dtap_tx_confirmed == 1
-- SMS is done
-  llist_count(&net->subscr_conns) == 1
----
-- subscriber detaches
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-DREF MSISDN:46071: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(IMSI)=901700000004620
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DMM IMSI DETACH for MSISDN:46071
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_ERROR)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Deallocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=0): already dispatching release, ignore.
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_accept_cm_during_paging_resp: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_reject_paging_resp_during_paging_resp
----
-- Subscriber does a normal LU
-- Location Update Request
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-  llist_count(&net->subscr_conns) == 1
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
----
-- an SMS is sent, MS is paged
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DMM Subscriber MSISDN:46071 not paged yet, start paging.
-  RAN_GERAN_A sends out paging request to IMSI 901700000004620, TMSI 0xffffffff, LAC 0
-  strcmp(paging_expecting_imsi, imsi) == 0
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-  paging_sent == 1
-  paging_stopped == 0
-- MS replies with Paging Response, we deliver the SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_PAG_RESP
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_RR_PAG_RESP (0x6:0x27)
-DRR PAGING RESPONSE: MI(IMSI)=901700000004620
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: rev=GSM net=GERAN (no Auth)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:46071 usage increases to: 4
-DREF VLR subscr MSISDN:46071 usage increases to: 5
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_PAGING_RESP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DPAG Paging success for MSISDN:46071 (event=0)
-DPAG Calling paging cbfn.
-DREF VLR subscr MSISDN:46071 usage increases to: 6
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DMSC msc_tx 91 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x01: 09015801000791447758100650004c0005806470f1000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 5
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF VLR subscr MSISDN:46071 usage decreases to: 4
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  dtap_tx_confirmed == 1
-  paging_stopped == 1
-- conn is still open to wait for SMS ack dance
-  llist_count(&net->subscr_conns) == 1
----
-- MS sends another erratic Paging Response which is dropped silently
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_PAG_RESP
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_MT_RR_PAG_RESP (0x6:0x27)
-DRR PAGING RESPONSE: MI(IMSI)=901700000004620
-DMM 901700000004620: Error: connection already in use
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:46071: MSC conn use - 1 == 2
-- MS replies with CP-ACK for received SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x04
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x04 (0x9:0x4)
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:46071: MSC conn use - 1 == 2
-  llist_count(&net->subscr_conns) == 1
-- MS also sends RP-ACK, MSC in turn sends CP-ACK for that
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x01
-DREF MSISDN:46071: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMSC msc_tx 2 bytes to MSISDN:46071 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x04: 0904
-- DTAP matches expected message
-DREF VLR subscr MSISDN:46071 usage decreases to: 3
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DREF MSISDN:46071: MSC conn use - 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-  dtap_tx_confirmed == 1
-  bssap_clear_sent == 1
-- SMS is done
-  llist_count(&net->subscr_conns) == 0
-DREF freeing VLR subscr MSISDN:46071
-===== test_reject_paging_resp_during_paging_resp: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
diff --git a/tests/msc_vlr/msc_vlr_test_reject_concurrency.ok b/tests/msc_vlr/msc_vlr_test_reject_concurrency.ok
deleted file mode 100644
index a965a70..0000000
--- a/tests/msc_vlr/msc_vlr_test_reject_concurrency.ok
+++ /dev/null
@@ -1 +0,0 @@
-Done
diff --git a/tests/msc_vlr/msc_vlr_test_rest.c b/tests/msc_vlr/msc_vlr_test_rest.c
deleted file mode 100644
index c5f7fcf..0000000
--- a/tests/msc_vlr/msc_vlr_test_rest.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/* Osmocom MSC+VLR end-to-end tests */
-
-/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- *
- * All Rights Reserved
- *
- * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
- *
- * 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/>.
- *
- */
-
-#include "msc_vlr_tests.h"
-
-void test_early_stage()
-{
-	comment_start();
-
-	btw("NULL conn");
-	EXPECT_ACCEPTED(false);
-
-	btw("freshly allocated conn");
-	g_conn = msc_subscr_con_allocate(net);
-	g_conn->bts = the_bts;
-	EXPECT_ACCEPTED(false);
-
-	btw("conn_fsm present, in state NEW");
-	OSMO_ASSERT(msc_create_conn_fsm(g_conn, "test") == 0);
-	OSMO_ASSERT(g_conn->conn_fsm);
-	OSMO_ASSERT(g_conn->conn_fsm->state == SUBSCR_CONN_S_NEW);
-	EXPECT_ACCEPTED(false);
-
-	thwart_rx_non_initial_requests();
-
-	btw("fake: acceptance");
-	g_conn->vsub = vlr_subscr_alloc(net->vlr);
-	g_conn->via_ran = RAN_GERAN_A;
-	OSMO_ASSERT(g_conn->vsub);
-	/* mark as silent call so it sticks around */
-	g_conn->silent_call = 1;
-	osmo_fsm_inst_state_chg(g_conn->conn_fsm, SUBSCR_CONN_S_ACCEPTED, 0, 0);
-	EXPECT_CONN_COUNT(1);
-	EXPECT_ACCEPTED(true);
-
-	btw("CLOSE event marks conn_fsm as released and frees the conn");
-	expect_bssap_clear();
-	osmo_fsm_inst_dispatch(g_conn->conn_fsm, SUBSCR_CONN_E_CN_CLOSE, NULL);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	clear_vlr();
-	comment_end();
-}
-
-void test_cm_service_without_lu()
-{
-	comment_start();
-
-	btw("CM Service Request without a prior Location Updating");
-	expect_bssap_clear();
-	ms_sends_msg("05247803305886089910070000006402");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("conn was released");
-	EXPECT_CONN_COUNT(0);
-
-	clear_vlr();
-	comment_end();
-}
-
-void test_two_lu()
-{
-	comment_start();
-
-	btw("Location Update request causes a GSUP LU request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("having received subscriber data does not mean acceptance");
-	EXPECT_ACCEPTED(false);
-
-	thwart_rx_non_initial_requests();
-
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	expect_bssap_clear();
-	gsup_rx("06010809710000004026f0", NULL);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-
-
-	BTW("verify that the MS can send another LU request");
-	btw("Location Update request causes a GSUP LU request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("050802008168000130089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("having received subscriber data does not mean acceptance");
-	EXPECT_ACCEPTED(false);
-
-	thwart_rx_non_initial_requests();
-
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	expect_bssap_clear();
-	gsup_rx("06010809710000004026f0", NULL);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("subscriber detaches");
-	expect_bssap_clear();
-	ms_sends_msg("050130089910070000006402");
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-void test_lu_unknown_tmsi()
-{
-	comment_start();
-
-	btw("Location Update request with unknown TMSI sends ID Request for IMSI");
-	lu_result_sent = RES_NONE;
-	dtap_expect_tx("051801");
-	ms_sends_msg("050802008168000130" "05f4" "23422342");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("MS tells us the IMSI, causes a GSUP LU request to HLR");
-	gsup_expect_tx("04010809710000004026f0");
-	ms_sends_msg("0559089910070000006402");
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000004026f00804036470f1",
-		"12010809710000004026f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("having received subscriber data does not mean acceptance");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	expect_bssap_clear();
-	gsup_rx("06010809710000004026f0", NULL);
-	VERBOSE_ASSERT(bssap_clear_sent, == true, "%d");
-
-	btw("LU was successful, and the conn has already been closed");
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-	comment_end();
-}
-
-msc_vlr_test_func_t msc_vlr_tests[] = {
-	test_early_stage,
-	test_cm_service_without_lu,
-	test_two_lu,
-	test_lu_unknown_tmsi,
-	NULL
-};
diff --git a/tests/msc_vlr/msc_vlr_test_rest.err b/tests/msc_vlr/msc_vlr_test_rest.err
deleted file mode 100644
index 1b5f340..0000000
--- a/tests/msc_vlr/msc_vlr_test_rest.err
+++ /dev/null
@@ -1,493 +0,0 @@
-===== test_early_stage
-- NULL conn
-msc_subscr_conn_is_accepted() == false
-- freshly allocated conn
-msc_subscr_conn_is_accepted() == false
-- conn_fsm present, in state NEW
-DREF unknown: MSC conn use + 1 == 1
-DMM Subscr_Conn(test){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(test){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(test){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr unknown: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr unknown: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr unknown: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr unknown: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- fake: acceptance
-DREF VLR subscr unknown usage increases to: 1
-DMM Subscr_Conn(test){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-  llist_count(&net->subscr_conns) == 1
-msc_subscr_conn_is_accepted() == true
-- CLOSE event marks conn_fsm as released and frees the conn
-DMM Subscr_Conn(test){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(test){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(test){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DMM msc_subscr_conn_close(vsub=unknown, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL subscr unknown: Freeing subscriber connection
-DREF VLR subscr unknown usage decreases to: 0
-DREF freeing VLR subscr unknown
-DMM Subscr_Conn(test){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(test){SUBSCR_CONN_S_RELEASED}: Deallocated
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_early_stage: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_cm_service_without_lu
-- CM Service Request without a prior Location Updating
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_CM_SERV_REQ
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_CM_SERV_REQ (0x5:0x24)
-DMM <- CM SERVICE REQUEST serv_type=0x08 MI(IMSI)=901700000004620
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: rev=GSM net=GERAN (no Auth)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: proc_arq_fsm_done(VLR_PR_ARQ_RES_UNIDENT_SUBSCR)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_UNIDENT_SUBSCR
-- sending CM Service Reject for unknown, result VLR_PR_ARQ_RES_UNIDENT_SUBSCR
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_CN_CLOSE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_CM_SERVICE_REQ
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Close event, cause 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=unknown, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-- conn was released
-  llist_count(&net->subscr_conns) == 0
-===== test_cm_service_without_lu: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_two_lu
-- Location Update request causes a GSUP LU request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR New subscr, IMSI: 901700000004620
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DREF VLR subscr IMSI:901700000004620 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- having received subscriber data does not mean acceptance
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
----
-- verify that the MS can send another LU request
-- Location Update request causes a GSUP LU request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000004620 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:46071: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- having received subscriber data does not mean acceptance
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000004620){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000004620)
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000004620){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000004620)
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000004620){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000004620)
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000004620){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
----
-- subscriber detaches
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(IMSI)=901700000004620
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DMM IMSI DETACH for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-DREF VLR subscr MSISDN:46071 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:46071
-DMM msc_subscr_conn_close(vsub=unknown, cause=0): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_two_lu: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_lu_unknown_tmsi
-- Location Update request with unknown TMSI sends ID Request for IMSI
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(591536962){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(591536962){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(591536962){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(TMSI)=591536962 type=IMSI ATTACH
-DMM LU/new-LAC: 1/0
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_IDLE}: is child of Subscr_Conn(591536962)
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_IDLE}: rev=GSM net=GERAN (no Auth)
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR New subscr, TMSI: 0x23422342
-DREF VLR subscr TMSI:0x23422342 usage increases to: 2
-DREF VLR subscr TMSI:0x23422342 usage decreases to: 1
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_IDLE}: vlr_loc_upd_want_imsi()
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_IMSI
-DMSC msc_tx 3 bytes to TMSI:0x23422342 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_MT_MM_ID_REQ: 051801
-- DTAP matches expected message
-DMM TMSI:0x23422342: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF TMSI:0x23422342: MSC conn use - 1 == 1
-  lu_result_sent == 0
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr TMSI:0x23422342: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr TMSI:0x23422342: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr TMSI:0x23422342: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr TMSI:0x23422342: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS tells us the IMSI, causes a GSUP LU request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_ID_RESP
-DREF TMSI:0x23422342: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_ID_RESP (0x5:0x19)
-DMM IDENTITY RESPONSE: MI(IMSI)=901700000004620
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_WAIT_IMSI}: Received Event VLR_ULA_E_ID_IMSI
-DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_WAIT_IMSI}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_WAIT_IMSI}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_WAIT_IMSI}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_WAIT_IMSI}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_WAIT_IMSI}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(591536962){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(591536962){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(591536962)
-DVLR upd_hlr_vlr_fsm(591536962){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000004026f0
-DVLR upd_hlr_vlr_fsm(591536962){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000004620: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000004026f00804036470f1
-DVLR GSUP rx 17: 10010809710000004026f00804036470f1
-DREF VLR subscr IMSI:901700000004620 usage increases to: 2
-DVLR IMSI:901700000004620 has MSISDN:46071
-DVLR GSUP tx: 12010809710000004026f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- having received subscriber data does not mean acceptance
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:46071: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000004026f0
-DVLR GSUP rx 11: 06010809710000004026f0
-DREF VLR subscr MSISDN:46071 usage increases to: 2
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(591536962){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(591536962){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(591536962){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(591536962){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(591536962)
-DVLR upd_hlr_vlr_fsm(591536962){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(591536962){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(591536962){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(591536962){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(591536962)
-DVLR lu_compl_vlr_fsm(591536962){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(591536962){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(591536962){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(591536962){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(591536962)
-DVLR sub_pres_vlr_fsm(591536962){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(591536962){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(591536962){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(591536962){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(591536962)
-DVLR sub_pres_vlr_fsm(591536962){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(591536962){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(591536962){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-- sending LU Accept for MSISDN:46071
-DREF VLR subscr MSISDN:46071 usage increases to: 3
-DVLR lu_compl_vlr_fsm(591536962){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(591536962){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(591536962){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(591536962)
-DVLR lu_compl_vlr_fsm(591536962){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(591536962){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(591536962){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(591536962){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(591536962){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(591536962){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(591536962){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(591536962){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(591536962){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(591536962)
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(591536962){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:46071, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:46071: MSC conn use - 1 == 0
-DRLL subscr MSISDN:46071: Freeing subscriber connection
-DREF VLR subscr MSISDN:46071 usage decreases to: 2
-DMM Subscr_Conn(591536962){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(591536962){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF VLR subscr MSISDN:46071 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  lu_result_sent == 1
-  llist_count(&net->subscr_conns) == 0
-DREF freeing VLR subscr MSISDN:46071
-===== test_lu_unknown_tmsi: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
diff --git a/tests/msc_vlr/msc_vlr_test_rest.ok b/tests/msc_vlr/msc_vlr_test_rest.ok
deleted file mode 100644
index a965a70..0000000
--- a/tests/msc_vlr/msc_vlr_test_rest.ok
+++ /dev/null
@@ -1 +0,0 @@
-Done
diff --git a/tests/msc_vlr/msc_vlr_test_umts_authen.c b/tests/msc_vlr/msc_vlr_test_umts_authen.c
deleted file mode 100644
index 1175bf8..0000000
--- a/tests/msc_vlr/msc_vlr_test_umts_authen.c
+++ /dev/null
@@ -1,581 +0,0 @@
-/* Osmocom MSC+VLR end-to-end tests */
-
-/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- *
- * All Rights Reserved
- *
- * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
- *
- * 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/>.
- *
- */
-
-#include "msc_vlr_tests.h"
-
-#define ASSERT_RELEASE_CLEAR(via_ran) \
-	switch (via_ran) { \
-	case RAN_GERAN_A: \
-		VERBOSE_ASSERT(bssap_clear_sent, == true, "%d"); \
-		break; \
-	case RAN_UTRAN_IU: \
-		VERBOSE_ASSERT(iu_release_sent, == true, "%d"); \
-		break; \
-	default: \
-		OSMO_ASSERT(false); \
-		break; \
-	}
-
-void _test_umts_authen(enum ran_type via_ran)
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000010650";
-	const char *sms =
-		"09" /* SMS messages */
-		"01" /* CP-DATA */
-		"58" /* length */
-		"01" /* Network to MS */
-		"00" /* reference */
-		/* originator (gsm411_send_sms() hardcodes this weird nr) */
-		"0791" "447758100650" /* 447785016005 */
-		"00" /* dest */
-		/* SMS TPDU */
-		"4c" /* len */
-		"00" /* SMS deliver */
-		"05802443f2" /* originating address 42342 */
-		"00" /* TP-PID */
-		"00" /* GSM default alphabet */
-		"071010" /* Y-M-D (from wrapped gsm340_gen_scts())*/
-		"000000" /* H-M-S */
-		"00" /* GMT+0 */
-		"44" /* data length */
-		"5079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0e"
-		"d3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb"
-		"0c7ac3e9e9b7db05";
-
-	net->authentication_required = true;
-	net->vlr->cfg.assign_tmsi = true;
-	rx_from_ran = via_ran;
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("080108" "09710000000156f0");
-	ms_sends_msg("0508" /* MM LU */
-		     "7" /* ciph key seq: no key available */
-		     "0" /* LU type: normal */
-		     "ffffff" "0000" /* LAI, LAC */
-		     "57" /* classmark 1: R99, early classmark, no power lvl */
-		     "089910070000106005" /* IMSI */
-		     "3303575886" /* classmark 2 */
-		     );
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS");
-	/* based on auc_3g:
-	 * K = 'EB215756028D60E3275E613320AEC880',
-	 * OPC = 'FB2A3D1B360F599ABAB99DB8669F8308'
-	 * SQN = 0
-	 */
-	auth_request_sent = false;
-	auth_request_expect_rand = "39fa2f4e3d523d8619a73b4f65c3e14d";
-	auth_request_expect_autn = "8704f5ba55f30000d2ee44b22c8ea919";
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000000156f0"
-		/* 5 auth vectors... */
-		/* TL    TL     rand */
-		"0362"  "2010" "39fa2f4e3d523d8619a73b4f65c3e14d"
-		/*       TL     sres       TL     kc */
-			"2104" "9b36efdf" "2208" "059a4f668f6fbe39"
-		/*       TL     3G IK */
-			"2310" "27497388b6cb044648f396aa155b95ef"
-		/*       TL     3G CK */
-			"2410" "f64735036e5871319c679f4742a75ea1"
-		/*       TL     AUTN */
-			"2510" "8704f5ba55f30000d2ee44b22c8ea919"
-		/*       TL     RES */
-			"2708" "e229c19e791f2e41"
-		/* TL    TL     rand */
-		"0362"  "2010" "c187a53a5e6b9d573cac7c74451fd46d"
-			"2104" "85aa3130" "2208" "d3d50a000bf04f6e"
-			"2310" "1159ec926a50e98c034a6b7d7c9f418d"
-			"2410" "df3a03d9ca5335641efc8e36d76cd20b"
-			"2510" "1843a645b98d00005b2d666af46c45d9"
-			"2708" "7db47cf7f81e4dc7"
-		"0362"  "2010" "efa9c29a9742148d5c9070348716e1bb"
-			"2104" "69d5f9fb" "2208" "3df176f0c29f1a3d"
-			"2310" "eb50e770ddcc3060101d2f43b6c2b884"
-			"2410" "76542abce5ff9345b0e8947f4c6e019c"
-			"2510" "f9375e6d41e1000096e7fe4ff1c27e39"
-			"2708" "706f996719ba609c"
-		"0362"  "2010" "f023d5a3b24726e0631b64b3840f8253"
-			"2104" "d570c03f" "2208" "ec011be8919883d6"
-			"2310" "c4e58af4ba43f3bcd904e16984f086d7"
-			"2410" "0593f65e752e5cb7f473862bda05aa0a"
-			"2510" "541ff1f077270000c5ea00d658bc7e9a"
-			"2708" "3fd26072eaa2a04d"
-		"0362"  "2010" "2f8f90c780d6a9c0c53da7ac57b6707e"
-			"2104" "b072446f220823f39f9f425ad6e6"
-			"2310" "65af0527fda95b0dc5ae4aa515cdf32f"
-			"2410" "537c3b35a3b13b08d08eeb28098f45cc"
-			"2510" "4bf4e564f75300009bc796706bc65744"
-			"2708" "0edb0eadbea94ac2",
-		NULL);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	if (via_ran == RAN_GERAN_A) {
-		btw("MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR");
-		gsup_expect_tx("04010809710000000156f0");
-		ms_sends_msg("0554" "e229c19e" "2104" "791f2e41");
-		VERBOSE_ASSERT(gsup_tx_confirmed, == true, "%d");
-		VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	} else {
-		/* On UTRAN */
-		btw("MS sends Authen Response, VLR accepts and sends SecurityModeControl");
-		cipher_mode_cmd_sent = false;
-		ms_sends_msg("0554" "e229c19e" "2104" "791f2e41");
-		VERBOSE_ASSERT(cipher_mode_cmd_sent, == true, "%d");
-		VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-		btw("MS sends SecurityModeControl acceptance, VLR accepts and sends GSUP LU Req to HLR");
-		gsup_expect_tx("04010809710000000156f0");
-		ms_sends_security_mode_complete();
-		VERBOSE_ASSERT(gsup_tx_confirmed, == true, "%d");
-		VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	}
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000000156f00804032443f2",
-		"12010809710000000156f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	gsup_rx("06010809710000000156f0", NULL);
-
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-
-	btw("a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl");
-	EXPECT_CONN_COUNT(1);
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("even though the TMSI is not acked, we can already find the subscr with it");
-	vsub = vlr_subscr_find_by_tmsi(net->vlr, 0x03020100);
-	VERBOSE_ASSERT(vsub != NULL, == true, "%d");
-	VERBOSE_ASSERT(strcmp(vsub->imsi, imsi), == 0, "%d");
-	VERBOSE_ASSERT(vsub->tmsi_new, == 0x03020100, "0x%08x");
-	VERBOSE_ASSERT(vsub->tmsi, == GSM_RESERVED_TMSI, "0x%08x");
-	vlr_subscr_put(vsub);
-
-	btw("MS sends TMSI Realloc Complete");
-	expect_release_clear(via_ran);
-	ms_sends_msg("055b");
-	ASSERT_RELEASE_CLEAR(via_ran);
-
-	btw("LU was successful, and the conn has already been closed");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("after a while, a new conn sends a CM Service Request. VLR responds with Auth Req, 2nd auth vector");
-	auth_request_sent = false;
-	auth_request_expect_rand = "c187a53a5e6b9d573cac7c74451fd46d";
-	auth_request_expect_autn = "1843a645b98d00005b2d666af46c45d9";
-	cm_service_result_sent = RES_NONE;
-	ms_sends_msg("052478"
-		     "03575886" /* classmark 2 */
-		     "089910070000106005" /* IMSI */);
-	OSMO_ASSERT(g_conn);
-	OSMO_ASSERT(g_conn->conn_fsm);
-	OSMO_ASSERT(g_conn->vsub);
-	VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-
-	btw("needs auth, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	if (via_ran == RAN_GERAN_A) {
-		btw("MS sends Authen Response, VLR accepts with a CM Service Accept");
-		gsup_expect_tx(NULL);
-		ms_sends_msg("0554" "7db47cf7" "2104" "f81e4dc7"); /* 2nd vector's res, s.a. */
-		VERBOSE_ASSERT(cm_service_result_sent, == RES_ACCEPT, "%d");
-	} else {
-		/* On UTRAN */
-		btw("MS sends Authen Response, VLR accepts and sends SecurityModeControl");
-		cipher_mode_cmd_sent = false;
-		ms_sends_msg("0554" "7db47cf7" "2104" "f81e4dc7"); /* 2nd vector's res, s.a. */
-		VERBOSE_ASSERT(cipher_mode_cmd_sent, == true, "%d");
-		VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-
-		btw("MS sends SecurityModeControl acceptance, VLR accepts; above Ciphering is an implicit CM Service Accept");
-		ms_sends_security_mode_complete();
-		VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
-	}
-
-	btw("a USSD request is serviced");
-	dtap_expect_tx_ussd("Your extension is 42342\r");
-	expect_release_clear(via_ran);
-	ms_sends_msg("0b3b1c15a11302010002013b300b04010f0406aa510c061b017f0100");
-	OSMO_ASSERT(dtap_tx_confirmed);
-	ASSERT_RELEASE_CLEAR(via_ran);
-
-	btw("all requests serviced, conn has been released");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("an SMS is sent, MS is paged");
-	paging_expect_imsi(imsi);
-	paging_sent = false;
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 0, "%d");
-
-	send_sms(vsub, vsub,
-		 "Privacy in residential applications is a desirable"
-		 " marketing option.");
-
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 1, "%d");
-	vlr_subscr_put(vsub);
-	vsub = NULL;
-	VERBOSE_ASSERT(paging_sent, == true, "%d");
-	VERBOSE_ASSERT(paging_stopped, == false, "%d");
-
-	btw("the subscriber and its pending request should remain");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 1, "%d");
-	vlr_subscr_put(vsub);
-
-	btw("MS replies with Paging Response, and VLR sends Auth Request with third key");
-	auth_request_sent = false;
-	auth_request_expect_rand = "efa9c29a9742148d5c9070348716e1bb";
-	auth_request_expect_autn = "f9375e6d41e1000096e7fe4ff1c27e39";
-	ms_sends_msg("062707"
-		     "03575886" /* classmark 2 */
-		     "089910070000106005" /* IMSI */);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-
-	btw("needs auth, not yet accepted");
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	if (via_ran == RAN_GERAN_A) {
-		btw("MS sends Authen Response, VLR accepts and sends pending SMS");
-		dtap_expect_tx(sms);
-		ms_sends_msg("0554" "706f9967" "2104" "19ba609c"); /* 3nd vector's res, s.a. */
-		VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-		VERBOSE_ASSERT(paging_stopped, == true, "%d");
-	} else {
-		/* On UTRAN */
-		btw("MS sends Authen Response, VLR accepts and sends SecurityModeControl");
-		cipher_mode_cmd_sent = false;
-		ms_sends_msg("0554" "706f9967" "2104" "19ba609c"); /* 3nd vector's res, s.a. */
-		VERBOSE_ASSERT(cipher_mode_cmd_sent, == true, "%d");
-		VERBOSE_ASSERT(paging_stopped, == false, "%d");
-
-		btw("MS sends SecurityModeControl acceptance, VLR accepts and sends SMS");
-		dtap_expect_tx(sms);
-		ms_sends_security_mode_complete();
-		VERBOSE_ASSERT(paging_stopped, == true, "%d");
-	}
-
-	btw("SMS was delivered, no requests pending for subscr");
-	vsub = vlr_subscr_find_by_imsi(net->vlr, imsi);
-	OSMO_ASSERT(vsub);
-	VERBOSE_ASSERT(llist_count(&vsub->cs.requests), == 0, "%d");
-	vlr_subscr_put(vsub);
-
-	btw("conn is still open to wait for SMS ack dance");
-	EXPECT_CONN_COUNT(1);
-
-	btw("MS replies with CP-ACK for received SMS");
-	ms_sends_msg("8904");
-	EXPECT_CONN_COUNT(1);
-
-	btw("MS also sends RP-ACK, MSC in turn sends CP-ACK for that");
-	dtap_expect_tx("0904");
-	expect_release_clear(via_ran);
-	ms_sends_msg("890106020041020000");
-	VERBOSE_ASSERT(dtap_tx_confirmed, == true, "%d");
-	ASSERT_RELEASE_CLEAR(via_ran);
-
-	btw("SMS is done, conn is gone");
-	EXPECT_CONN_COUNT(0);
-
-	BTW("subscriber detaches");
-	expect_release_clear(via_ran);
-	ms_sends_msg("050130"
-		     "089910070000106005" /* IMSI */);
-	ASSERT_RELEASE_CLEAR(via_ran);
-
-	EXPECT_CONN_COUNT(0);
-	clear_vlr();
-}
-
-void test_umts_authen_geran()
-{
-	comment_start();
-	_test_umts_authen(RAN_GERAN_A);
-	comment_end();
-}
-
-void test_umts_authen_utran()
-{
-	comment_start();
-	_test_umts_authen(RAN_UTRAN_IU);
-	comment_end();
-}
-
-#define RECALC_AUTS 0
-
-#if RECALC_AUTS
-typedef uint8_t u8;
-extern int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
-			  u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar);
-extern int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
-		       const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s);
-#endif
-
-void _test_umts_authen_resync(enum ran_type via_ran)
-{
-	struct vlr_subscr *vsub;
-	const char *imsi = "901700000010650";
-
-	net->authentication_required = true;
-	net->vlr->cfg.assign_tmsi = true;
-	rx_from_ran = via_ran;
-
-	btw("Location Update request causes a GSUP Send Auth Info request to HLR");
-	lu_result_sent = RES_NONE;
-	gsup_expect_tx("080108" "09710000000156f0");
-	ms_sends_msg("0508" /* MM LU */
-		     "7" /* ciph key seq: no key available */
-		     "0" /* LU type: normal */
-		     "ffffff" "0000" /* LAI, LAC */
-		     "57" /* classmark 1: R99, early classmark, no power lvl */
-		     "089910070000106005" /* IMSI */
-		     "3303575886" /* classmark 2 */
-		     );
-	OSMO_ASSERT(gsup_tx_confirmed);
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS");
-	/* based on auc_3g:
-	 * K = 'EB215756028D60E3275E613320AEC880',
-	 * OPC = 'FB2A3D1B360F599ABAB99DB8669F8308'
-	 * SQN = 0
-	 */
-	auth_request_sent = false;
-	auth_request_expect_rand = "39fa2f4e3d523d8619a73b4f65c3e14d";
-	auth_request_expect_autn = "8704f5ba55f30000d2ee44b22c8ea919";
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000000156f0"
-		/* auth vectors... */
-		/* TL    TL     rand */
-		"0362"  "2010" "39fa2f4e3d523d8619a73b4f65c3e14d"
-		/*       TL     sres       TL     kc */
-			"2104" "9b36efdf" "2208" "059a4f668f6fbe39"
-		/*       TL     3G IK */
-			"2310" "27497388b6cb044648f396aa155b95ef"
-		/*       TL     3G CK */
-			"2410" "f64735036e5871319c679f4742a75ea1"
-		/*       TL     AUTN */
-			"2510" "8704f5ba55f30000d2ee44b22c8ea919"
-		/*       TL     RES */
-			"2708" "e229c19e791f2e41"
-		,NULL);
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	/* The AUTN sent was 8704f5ba55f30000d2ee44b22c8ea919
-	 * (see expected error output)
-	 * with the first 6 bytes being SQN ^ AK.
-	 * K = EB215756028D60E3275E613320AEC880
-	 * OPC = FB2A3D1B360F599ABAB99DB8669F8308
-	 * RAND = 39fa2f4e3d523d8619a73b4f65c3e14d
-	 * --milenage-f5-->
-	 * AK = 8704f5ba55f3
-	 *
-	 * The first six bytes are 8704f5ba55f3,
-	 * and 8704f5ba55f3 ^ AK = 0.
-	 * --> SQN = 0.
-	 *
-	 * Say the USIM doesn't like that, let's say it is at SQN 23.
-	 * SQN_MS = 000000000017
-	 *
-	 * AUTS = Conc(SQN_MS) || MAC-S
-	 * Conc(SQN_MS) = SQN_MS ⊕ f5*[K](RAND)
-	 * MAC-S = f1*[K] (SQN MS || RAND || AMF)
-	 *
-	 * f5*--> Conc(SQN_MS) = 000000000017 ^ 979498b1f73a
-	 *                     = 979498b1f72d
-	 * AMF = 0000 (TS 33.102 v7.0.0, 6.3.3)
-	 *
-	 * MAC-S = f1*[K] (000000000017 || 39fa2f4e3d523d8619a73b4f65c3e14d || 0000)
-	 *       = 3e28c59fa2e72f9c
-	 *
-	 * AUTS = 979498b1f72d || 3e28c59fa2e72f9c
-	 */
-#if RECALC_AUTS
-	uint8_t ak[6];
-	uint8_t akstar[6];
-	uint8_t opc[16];
-	uint8_t k[16];
-	uint8_t rand[16];
-	osmo_hexparse("EB215756028D60E3275E613320AEC880", k, sizeof(k));
-	osmo_hexparse("FB2A3D1B360F599ABAB99DB8669F8308", opc, sizeof(opc));
-	osmo_hexparse("39fa2f4e3d523d8619a73b4f65c3e14d", rand, sizeof(rand));
-	milenage_f2345(opc, k, rand, NULL, NULL, NULL, ak, akstar);
-	btw("ak = %s", osmo_hexdump_nospc(ak, sizeof(ak)));
-	btw("akstar = %s", osmo_hexdump_nospc(akstar, sizeof(akstar)));
-
-	uint8_t sqn_ms[6] = { 0, 0, 0, 0, 0, 23 };
-	uint8_t amf[2] = { 0 };
-	uint8_t mac_s[8];
-	milenage_f1(opc, k, rand, sqn_ms, amf, NULL, mac_s);
-	btw("mac_s = %s", osmo_hexdump_nospc(mac_s, sizeof(mac_s)));
-	/* verify valid AUTS resulting in SQN 23 with:
-	   osmo-auc-gen -3 -a milenage -k EB215756028D60E3275E613320AEC880 \
-	                -o FB2A3D1B360F599ABAB99DB8669F8308 \
-	                -r 39fa2f4e3d523d8619a73b4f65c3e14d \
-	                -A 979498b1f72d3e28c59fa2e72f9c
-	 */
-#endif
-
-	btw("MS sends Authen Failure with Resync cause, VLR sends GSUP to HLR to resync");
-	auth_request_sent = false;
-	gsup_expect_tx("08" /* OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST */
-		       "0108" "09710000000156f0" /* IMSI */
-		       "260e" "979498b1f72d3e28c59fa2e72f9c" /* AUTS */
-		       "2010" "39fa2f4e3d523d8619a73b4f65c3e14d" /* RAND */);
-	ms_sends_msg("051c" /* 05 = MM; 1c = Auth Failure */
-		     "15"   /* cause = Synch Failure */
-		     "220e" "979498b1f72d3e28c59fa2e72f9c" /* AUTS */);
-	VERBOSE_ASSERT(gsup_tx_confirmed, == true, "%d");
-	VERBOSE_ASSERT(auth_request_sent, == false, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR replies with new tuples");
-	auth_request_sent = false;
-	auth_request_expect_rand = "0f1feb1623e1bf626334e37ec448ac18";
-	auth_request_expect_autn = "02a83f62e9470000660d51afc75f169d";
-	gsup_rx("0a"
-		/* imsi */
-		"0108" "09710000000156f0"
-		/* 1 auth vector */
-		/* TL    TL     rand */
-		"0362"  "2010" "0f1feb1623e1bf626334e37ec448ac18"
-		/*       TL     sres       TL     kc */
-			"2104" "efde99da" "2208" "14778c855c523730"
-		/*       TL     3G IK */
-			"2310" "8a90c769b7272f3bb7a1c1fbb1ea9349"
-		/*       TL     3G CK */
-			"2410" "43ffc1cf8c89a7fd6ab94bd8d6162cbf"
-		/*       TL     AUTN */
-			"2510" "02a83f62e9470000660d51afc75f169d"
-		/*       TL     RES */
-			"2708" "1df5f0b4f22b696e"
-		/* TL    TL     rand */
-		"0362"  "2010" "ac21d34937b4e1142a2c757af2949319"
-		/*       TL     sres       TL     kc */
-			"2104" "7818bfdc" "2208" "d175571f41f314a4"
-		/*       TL     3G IK */
-			"2310" "ff8edbceb6dd24799c77c3b9a6790c10"
-		/*       TL     3G CK */
-			"2410" "157c39022ca9d885a7f0766a7dfee448"
-		/*       TL     AUTN */
-			"2510" "8a43b91898e500002cf354c6f5d1f8c3"
-		/*       TL     RES */
-			"2708" "f748a7078f5018db"
-		,NULL);
-
-	VERBOSE_ASSERT(auth_request_sent, == true, "%d");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	if (via_ran == RAN_GERAN_A) {
-		btw("MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR");
-		gsup_expect_tx("04010809710000000156f0");
-		ms_sends_msg("0554" "1df5f0b4" "2104" "f22b696e");
-		VERBOSE_ASSERT(gsup_tx_confirmed, == true, "%d");
-		VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	} else {
-		/* On UTRAN */
-		btw("MS sends Authen Response, VLR accepts and sends SecurityModeControl");
-		cipher_mode_cmd_sent = false;
-		ms_sends_msg("0554" "1df5f0b4" "2104" "f22b696e");
-		VERBOSE_ASSERT(cipher_mode_cmd_sent, == true, "%d");
-		VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-		btw("MS sends SecurityModeControl acceptance, VLR accepts and sends GSUP LU Req to HLR");
-		gsup_expect_tx("04010809710000000156f0");
-		ms_sends_security_mode_complete();
-		VERBOSE_ASSERT(gsup_tx_confirmed, == true, "%d");
-		VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-	}
-
-	btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT");
-	gsup_rx("10010809710000000156f00804032443f2",
-		"12010809710000000156f0");
-	VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
-
-	btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT");
-	gsup_rx("06010809710000000156f0", NULL);
-
-	VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d");
-
-	btw("a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl");
-	EXPECT_CONN_COUNT(1);
-	EXPECT_ACCEPTED(false);
-	thwart_rx_non_initial_requests();
-
-	btw("even though the TMSI is not acked, we can already find the subscr with it");
-	vsub = vlr_subscr_find_by_tmsi(net->vlr, 0x03020100);
-	VERBOSE_ASSERT(vsub != NULL, == true, "%d");
-	VERBOSE_ASSERT(strcmp(vsub->imsi, imsi), == 0, "%d");
-	VERBOSE_ASSERT(vsub->tmsi_new, == 0x03020100, "0x%08x");
-	VERBOSE_ASSERT(vsub->tmsi, == GSM_RESERVED_TMSI, "0x%08x");
-	vlr_subscr_put(vsub);
-
-	btw("MS sends TMSI Realloc Complete");
-	expect_release_clear(via_ran);
-	ms_sends_msg("055b");
-	ASSERT_RELEASE_CLEAR(via_ran);
-
-	btw("LU was successful, and the conn has already been closed");
-	EXPECT_CONN_COUNT(0);
-
-	clear_vlr();
-}
-
-void test_umts_authen_resync_geran()
-{
-	comment_start();
-	_test_umts_authen_resync(RAN_GERAN_A);
-	comment_end();
-}
-
-void test_umts_authen_resync_utran()
-{
-	comment_start();
-	_test_umts_authen_resync(RAN_UTRAN_IU);
-	comment_end();
-}
-
-msc_vlr_test_func_t msc_vlr_tests[] = {
-	test_umts_authen_geran,
-	test_umts_authen_utran,
-	test_umts_authen_resync_geran,
-	test_umts_authen_resync_utran,
-	NULL
-};
diff --git a/tests/msc_vlr/msc_vlr_test_umts_authen.err b/tests/msc_vlr/msc_vlr_test_umts_authen.err
deleted file mode 100644
index 57f5e8e..0000000
--- a/tests/msc_vlr/msc_vlr_test_umts_authen.err
+++ /dev/null
@@ -1,1381 +0,0 @@
-===== test_umts_authen_geran
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000010650 type=NORMAL
-DMM LU/new-LAC: 0/0
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000010650)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: rev=R99 net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000010650 id=901700000010650
-DVLR New subscr, IMSI: 901700000010650
-DREF VLR subscr IMSI:901700000010650 usage increases to: 2
-DREF VLR subscr IMSI:901700000010650 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000000156f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000000156f0
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000010650: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000010650: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000000156f00362201039fa2f4e3d523d8619a73b4f65c3e14d21049b36efdf2208059a4f668f6fbe39231027497388b6cb044648f396aa155b95ef2410f64735036e5871319c679f4742a75ea125108704f5ba55f30000d2ee44b22c8ea9192708e229c19e791f2e4103622010c187a53a5e6b9d573cac7c74451fd46d210485aa31302208d3d50a000bf04f6e23101159ec926a50e98c034a6b7d7c9f418d2410df3a03d9ca5335641efc8e36d76cd20b25101843a645b98d00005b2d666af46c45d927087db47cf7f81e4dc703622010efa9c29a9742148d5c9070348716e1bb210469d5f9fb22083df176f0c29f1a3d2310eb50e770ddcc3060101d2f43b6c2b884241076542abce5ff9345b0e8947f4c6e019c2510f9375e6d41e1000096e7fe4ff1c27e392708706f996719ba609c03622010f023d5a3b24726e0631b64b3840f82532104d570c03f2208ec011be8919883d62310c4e58af4ba43f3bcd904e16984f086d724100593f65e752e5cb7f473862bda05aa0a2510541ff1f077270000c5ea00d658bc7e9a27083fd26072eaa2a04d036220102f8f90c780d6a9c0c53da7ac57b6707e2104b072446f220823f39f9f425ad6e6231065af0527fda95b0dc5ae4aa515cdf32f2410537c3b35a3b13b08d08eeb28098f45cc25104bf4e564f75300009bc796706bc6574427080edb0eadbea94ac2
-DVLR GSUP rx 511: 0a010809710000000156f00362201039fa2f4e3d523d8619a73b4f65c3e14d21049b36efdf2208059a4f668f6fbe39231027497388b6cb044648f396aa155b95ef2410f64735036e5871319c679f4742a75ea125108704f5ba55f30000d2ee44b22c8ea9192708e229c19e791f2e4103622010c187a53a5e6b9d573cac7c74451fd46d210485aa31302208d3d50a000bf04f6e23101159ec926a50e98c034a6b7d7c9f418d2410df3a03d9ca5335641efc8e36d76cd20b25101843a645b98d00005b2d666af46c45d927087db47cf7f81e4dc703622010efa9c29a9742148d5c9070348716e1bb210469d5f9fb22083df176f0c29f1a3d2310eb50e770ddcc3060101d2f43b6c2b884241076542abce5ff9345b0e8947f4c6e019c2510f9375e6d41e1000096e7fe4ff1c27e392708706f996719ba609c03622010f023d5a3b24726e0631b64b3840f82532104d570c03f2208ec011be8919883d62310c4e58af4ba43f3bcd904e16984f086d724100593f65e752e5cb7f473862bda05aa0a2510541ff1f077270000c5ea00d658bc7e9a27083fd26072eaa2a04d036220102f8f90c780d6a9c0c53da7ac57b6707e2104b072446f220823f39f9f425ad6e6231065af0527fda95b0dc5ae4aa515cdf32f2410537c3b35a3b13b08d08eeb28098f45cc25104bf4e564f75300009bc796706bc6574427080edb0eadbea94ac2
-DREF VLR subscr IMSI:901700000010650 usage increases to: 2
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000010650) Received 5 auth tuples
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending UMTS Auth Request for IMSI:901700000010650: tuple use_count=1 key_seq=0 auth_types=0x3 and...
-- ...rand=39fa2f4e3d523d8619a73b4f65c3e14d
-- ...autn=8704f5ba55f30000d2ee44b22c8ea919
-- ...expecting res=e229c19e791f2e41
-DREF VLR subscr IMSI:901700000010650 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000010650: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000010650: MM R99 AUTHENTICATION RESPONSE (res = e229c19e791f2e41)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000010650) received res: e2 29 c1 9e 79 1f 2e 41 
-DVLR SUBSCR(IMSI:901700000010650) AUTH established UMTS security context
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000010650)
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000000156f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000000156f0
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000010650: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000010650: MSC conn use - 1 == 1
-  gsup_tx_confirmed == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000000156f00804032443f2
-DVLR GSUP rx 17: 10010809710000000156f00804032443f2
-DREF VLR subscr IMSI:901700000010650 usage increases to: 2
-DVLR IMSI:901700000010650 has MSISDN:42342
-DVLR GSUP tx: 12010809710000000156f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000000156f0
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000000156f0
-DVLR GSUP rx 11: 06010809710000000156f0
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000010650)
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000010650)
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000010650)
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000010650)
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_SUB_PRES}: lu_compl_vlr_new_tmsi()
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_WAIT_TMSI_CNF
-- sending LU Accept for MSISDN:42342, with TMSI 0x03020100
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 1
-- a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl
-  llist_count(&net->subscr_conns) == 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- even though the TMSI is not acked, we can already find the subscr with it
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-  vsub != NULL == 1
-  strcmp(vsub->imsi, imsi) == 0
-  vsub->tmsi_new == 0x03020100
-  vsub->tmsi == 0xffffffff
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-- MS sends TMSI Realloc Complete
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_TMSI_REALL_COMPL
-DREF MSISDN:42342: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_TMSI_REALL_COMPL (0x5:0x1b)
-DMM TMSI Reallocation Completed. Subscriber: MSISDN:42342
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_NEW_TMSI_ACK
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: Received Event LU_COMPL_VLR_E_NEW_TMSI_ACK
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000010650)
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000010650)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:42342, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:42342: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:42342: MSC conn use - 1 == 0
-DRLL subscr MSISDN:42342: Freeing subscriber connection
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  llist_count(&net->subscr_conns) == 0
----
-- after a while, a new conn sends a CM Service Request. VLR responds with Auth Req, 2nd auth vector
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_CM_SERV_REQ
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_CM_SERV_REQ (0x5:0x24)
-DMM <- CM SERVICE REQUEST serv_type=0x08 MI(IMSI)=901700000010650
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000010650)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: rev=R99 net=GERAN Auth (no Ciph)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-DREF VLR subscr MSISDN:42342 usage increases to: 3
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: is child of Process_Access_Request_VLR(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=1
-- sending UMTS Auth Request for MSISDN:42342: tuple use_count=1 key_seq=1 auth_types=0x3 and...
-- ...rand=c187a53a5e6b9d573cac7c74451fd46d
-- ...autn=1843a645b98d00005b2d666af46c45d9
-- ...expecting res=7db47cf7f81e4dc7
-DREF VLR subscr MSISDN:42342 usage decreases to: 2
-DMM MSISDN:42342: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:42342: MSC conn use - 1 == 1
-  cm_service_result_sent == 0
-  auth_request_sent == 1
-- needs auth, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Authen Response, VLR accepts with a CM Service Accept
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF MSISDN:42342: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM MSISDN:42342: MM R99 AUTHENTICATION RESPONSE (res = 7db47cf7f81e4dc7)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(MSISDN:42342) received res: 7d b4 7c f7 f8 1e 4d c7 
-DVLR SUBSCR(MSISDN:42342) AUTH established UMTS security context
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Removing from parent Process_Access_Request_VLR(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: Received Event PR_ARQ_E_AUTH_RES
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-- sending CM Service Accept for MSISDN:42342
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_CM_SERVICE_REQ
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: received_cm_service_request = true
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-DREF MSISDN:42342: MSC conn use - 1 == 1
-  cm_service_result_sent == 1
-- a USSD request is serviced
-  expecting USSD:
-  Your extension is 42342

-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_NC_SS:0x3b
-DREF MSISDN:42342: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_PDISC_NC_SS:0x3b (0xb:0x3b)
-DMM MSISDN:42342: rx msg GSM48_PDISC_NC_SS:0x3b: received_cm_service_request changes to false
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM USSD: Own number requested
-DMM MSISDN:42342: MSISDN = 42342
-DMSC msc_tx 43 bytes to MSISDN:42342 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_NC_SS:0x2a: 8b2a1c27a225020100302002013b301b04010f0416d9775d0e2ae3e965f73cfd7683d273104d36a3c91a0d
-- DTAP matches expected message
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000010650)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:42342, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:42342: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:42342: MSC conn use - 1 == 0
-DRLL subscr MSISDN:42342: Freeing subscriber connection
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-  bssap_clear_sent == 1
-- all requests serviced, conn has been released
-  llist_count(&net->subscr_conns) == 0
----
-- an SMS is sent, MS is paged
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:42342 usage increases to: 3
-DMM Subscriber MSISDN:42342 not paged yet, start paging.
-  RAN_GERAN_A sends out paging request to IMSI 901700000010650, TMSI 0x03020100, LAC 0
-  strcmp(paging_expecting_imsi, imsi) == 0
-DREF VLR subscr MSISDN:42342 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:42342 usage decreases to: 3
-  paging_sent == 1
-  paging_stopped == 0
-- the subscriber and its pending request should remain
-DREF VLR subscr MSISDN:42342 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:42342 usage decreases to: 3
-- MS replies with Paging Response, and VLR sends Auth Request with third key
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_RR_PAG_RESP
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_RR_PAG_RESP (0x6:0x27)
-DRR PAGING RESPONSE: MI(IMSI)=901700000010650
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000010650)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: rev=R99 net=GERAN Auth (no Ciph)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:42342 usage increases to: 4
-DREF VLR subscr MSISDN:42342 usage increases to: 5
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: is child of Process_Access_Request_VLR(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=2
-- sending UMTS Auth Request for MSISDN:42342: tuple use_count=1 key_seq=2 auth_types=0x3 and...
-- ...rand=efa9c29a9742148d5c9070348716e1bb
-- ...autn=f9375e6d41e1000096e7fe4ff1c27e39
-- ...expecting res=706f996719ba609c
-DREF VLR subscr MSISDN:42342 usage decreases to: 4
-DMM MSISDN:42342: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:42342: MSC conn use - 1 == 1
-  auth_request_sent == 1
-- needs auth, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Authen Response, VLR accepts and sends pending SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF MSISDN:42342: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM MSISDN:42342: MM R99 AUTHENTICATION RESPONSE (res = 706f996719ba609c)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(MSISDN:42342) received res: 70 6f 99 67 19 ba 60 9c 
-DVLR SUBSCR(MSISDN:42342) AUTH established UMTS security context
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Removing from parent Process_Access_Request_VLR(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: Received Event PR_ARQ_E_AUTH_RES
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2_post_ciph()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_PAGING_RESP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DPAG Paging success for MSISDN:42342 (event=0)
-DPAG Calling paging cbfn.
-DREF VLR subscr MSISDN:42342 usage increases to: 5
-DREF MSISDN:42342: MSC conn use + 1 == 3
-DMSC msc_tx 91 bytes to MSISDN:42342 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x01: 09015801000791447758100650004c0005802443f2000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
-- DTAP matches expected message
-DREF VLR subscr MSISDN:42342 usage decreases to: 4
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:42342: MSC conn use - 1 == 2
-  dtap_tx_confirmed == 1
-  paging_stopped == 1
-- SMS was delivered, no requests pending for subscr
-DREF VLR subscr MSISDN:42342 usage increases to: 5
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:42342 usage decreases to: 4
-- conn is still open to wait for SMS ack dance
-  llist_count(&net->subscr_conns) == 1
-- MS replies with CP-ACK for received SMS
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x04
-DREF MSISDN:42342: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x04 (0x9:0x4)
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:42342: MSC conn use - 1 == 2
-  llist_count(&net->subscr_conns) == 1
-- MS also sends RP-ACK, MSC in turn sends CP-ACK for that
-  MSC <--RAN_GERAN_A-- MS: GSM48_PDISC_SMS:0x01
-DREF MSISDN:42342: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMSC msc_tx 2 bytes to MSISDN:42342 via RAN_GERAN_A
-- DTAP --RAN_GERAN_A--> MS: GSM48_PDISC_SMS:0x04: 0904
-- DTAP matches expected message
-DREF VLR subscr MSISDN:42342 usage decreases to: 3
-DREF VLR subscr MSISDN:42342 usage decreases to: 2
-DREF MSISDN:42342: MSC conn use - 1 == 2
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000010650)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:42342, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:42342: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:42342: MSC conn use - 1 == 0
-DRLL subscr MSISDN:42342: Freeing subscriber connection
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-  dtap_tx_confirmed == 1
-  bssap_clear_sent == 1
-- SMS is done, conn is gone
-  llist_count(&net->subscr_conns) == 0
----
-- subscriber detaches
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(IMSI)=901700000010650
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-DMM IMSI DETACH for MSISDN:42342
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-DREF VLR subscr MSISDN:42342 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:42342
-DMM msc_subscr_conn_close(vsub=unknown, cause=0): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  bssap_clear_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_umts_authen_geran: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_umts_authen_utran
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_UTRAN_IU-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000010650 type=NORMAL
-DMM LU/new-LAC: 0/0
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000010650)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: rev=R99 net=UTRAN Auth+Ciph
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000010650 id=901700000010650
-DVLR New subscr, IMSI: 901700000010650
-DREF VLR subscr IMSI:901700000010650 usage increases to: 2
-DREF VLR subscr IMSI:901700000010650 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000000156f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000000156f0
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000010650: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000010650: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000000156f00362201039fa2f4e3d523d8619a73b4f65c3e14d21049b36efdf2208059a4f668f6fbe39231027497388b6cb044648f396aa155b95ef2410f64735036e5871319c679f4742a75ea125108704f5ba55f30000d2ee44b22c8ea9192708e229c19e791f2e4103622010c187a53a5e6b9d573cac7c74451fd46d210485aa31302208d3d50a000bf04f6e23101159ec926a50e98c034a6b7d7c9f418d2410df3a03d9ca5335641efc8e36d76cd20b25101843a645b98d00005b2d666af46c45d927087db47cf7f81e4dc703622010efa9c29a9742148d5c9070348716e1bb210469d5f9fb22083df176f0c29f1a3d2310eb50e770ddcc3060101d2f43b6c2b884241076542abce5ff9345b0e8947f4c6e019c2510f9375e6d41e1000096e7fe4ff1c27e392708706f996719ba609c03622010f023d5a3b24726e0631b64b3840f82532104d570c03f2208ec011be8919883d62310c4e58af4ba43f3bcd904e16984f086d724100593f65e752e5cb7f473862bda05aa0a2510541ff1f077270000c5ea00d658bc7e9a27083fd26072eaa2a04d036220102f8f90c780d6a9c0c53da7ac57b6707e2104b072446f220823f39f9f425ad6e6231065af0527fda95b0dc5ae4aa515cdf32f2410537c3b35a3b13b08d08eeb28098f45cc25104bf4e564f75300009bc796706bc6574427080edb0eadbea94ac2
-DVLR GSUP rx 511: 0a010809710000000156f00362201039fa2f4e3d523d8619a73b4f65c3e14d21049b36efdf2208059a4f668f6fbe39231027497388b6cb044648f396aa155b95ef2410f64735036e5871319c679f4742a75ea125108704f5ba55f30000d2ee44b22c8ea9192708e229c19e791f2e4103622010c187a53a5e6b9d573cac7c74451fd46d210485aa31302208d3d50a000bf04f6e23101159ec926a50e98c034a6b7d7c9f418d2410df3a03d9ca5335641efc8e36d76cd20b25101843a645b98d00005b2d666af46c45d927087db47cf7f81e4dc703622010efa9c29a9742148d5c9070348716e1bb210469d5f9fb22083df176f0c29f1a3d2310eb50e770ddcc3060101d2f43b6c2b884241076542abce5ff9345b0e8947f4c6e019c2510f9375e6d41e1000096e7fe4ff1c27e392708706f996719ba609c03622010f023d5a3b24726e0631b64b3840f82532104d570c03f2208ec011be8919883d62310c4e58af4ba43f3bcd904e16984f086d724100593f65e752e5cb7f473862bda05aa0a2510541ff1f077270000c5ea00d658bc7e9a27083fd26072eaa2a04d036220102f8f90c780d6a9c0c53da7ac57b6707e2104b072446f220823f39f9f425ad6e6231065af0527fda95b0dc5ae4aa515cdf32f2410537c3b35a3b13b08d08eeb28098f45cc25104bf4e564f75300009bc796706bc6574427080edb0eadbea94ac2
-DREF VLR subscr IMSI:901700000010650 usage increases to: 2
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000010650) Received 5 auth tuples
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending UMTS Auth Request for IMSI:901700000010650: tuple use_count=1 key_seq=0 auth_types=0x3 and...
-- ...rand=39fa2f4e3d523d8619a73b4f65c3e14d
-- ...autn=8704f5ba55f30000d2ee44b22c8ea919
-- ...expecting res=e229c19e791f2e41
-DREF VLR subscr IMSI:901700000010650 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends SecurityModeControl
-  MSC <--RAN_UTRAN_IU-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000010650: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000010650: MM R99 AUTHENTICATION RESPONSE (res = e229c19e791f2e41)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000010650) received res: e2 29 c1 9e 79 1f 2e 41 
-DVLR SUBSCR(IMSI:901700000010650) AUTH established UMTS security context
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-- sending SecurityModeControl for IMSI:901700000010650
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_CIPH
-DMM IMSI:901700000010650: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000010650: MSC conn use - 1 == 1
-  cipher_mode_cmd_sent == 1
-  lu_result_sent == 0
-- MS sends SecurityModeControl acceptance, VLR accepts and sends GSUP LU Req to HLR
-DMM <- SECURITY MODE COMPLETE IMSI:901700000010650
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_CIPH}: Received Event VLR_ULA_E_CIPH_RES
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_CIPH}: vlr_loc_upd_post_ciph()
-DIUCS IMSI:901700000010650: tx CommonID 901700000010650
-- Iu Common ID --RAN_UTRAN_IU--> MS (IMSI=901700000010650)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_CIPH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_CIPH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000010650)
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000000156f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000000156f0
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-  gsup_tx_confirmed == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000000156f00804032443f2
-DVLR GSUP rx 17: 10010809710000000156f00804032443f2
-DREF VLR subscr IMSI:901700000010650 usage increases to: 2
-DVLR IMSI:901700000010650 has MSISDN:42342
-DVLR GSUP tx: 12010809710000000156f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000000156f0
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000000156f0
-DVLR GSUP rx 11: 06010809710000000156f0
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000010650)
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000010650)
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000010650)
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000010650)
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_SUB_PRES}: lu_compl_vlr_new_tmsi()
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_WAIT_TMSI_CNF
-- sending LU Accept for MSISDN:42342, with TMSI 0x03020100
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 1
-- a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl
-  llist_count(&net->subscr_conns) == 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- even though the TMSI is not acked, we can already find the subscr with it
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-  vsub != NULL == 1
-  strcmp(vsub->imsi, imsi) == 0
-  vsub->tmsi_new == 0x03020100
-  vsub->tmsi == 0xffffffff
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-- MS sends TMSI Realloc Complete
-  MSC <--RAN_UTRAN_IU-- MS: GSM48_MT_MM_TMSI_REALL_COMPL
-DREF MSISDN:42342: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_TMSI_REALL_COMPL (0x5:0x1b)
-DMM TMSI Reallocation Completed. Subscriber: MSISDN:42342
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_NEW_TMSI_ACK
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: Received Event LU_COMPL_VLR_E_NEW_TMSI_ACK
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000010650)
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000010650)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:42342, cause=2): no conn fsm, releasing directly without release event.
-- Iu Release --RAN_UTRAN_IU--> MS
-DREF MSISDN:42342: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:42342: MSC conn use - 1 == 0
-DRLL subscr MSISDN:42342: Freeing subscriber connection
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-  iu_release_sent == 1
-- LU was successful, and the conn has already been closed
-  llist_count(&net->subscr_conns) == 0
----
-- after a while, a new conn sends a CM Service Request. VLR responds with Auth Req, 2nd auth vector
-  MSC <--RAN_UTRAN_IU-- MS: GSM48_MT_MM_CM_SERV_REQ
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_CM_SERV_REQ (0x5:0x24)
-DMM <- CM SERVICE REQUEST serv_type=0x08 MI(IMSI)=901700000010650
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000010650)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: rev=R99 net=UTRAN Auth+Ciph
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-DREF VLR subscr MSISDN:42342 usage increases to: 3
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: is child of Process_Access_Request_VLR(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=1
-- sending UMTS Auth Request for MSISDN:42342: tuple use_count=1 key_seq=1 auth_types=0x3 and...
-- ...rand=c187a53a5e6b9d573cac7c74451fd46d
-- ...autn=1843a645b98d00005b2d666af46c45d9
-- ...expecting res=7db47cf7f81e4dc7
-DREF VLR subscr MSISDN:42342 usage decreases to: 2
-DMM MSISDN:42342: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:42342: MSC conn use - 1 == 1
-  cm_service_result_sent == 0
-  auth_request_sent == 1
-- needs auth, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Authen Response, VLR accepts and sends SecurityModeControl
-  MSC <--RAN_UTRAN_IU-- MS: GSM48_MT_MM_AUTH_RESP
-DREF MSISDN:42342: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM MSISDN:42342: MM R99 AUTHENTICATION RESPONSE (res = 7db47cf7f81e4dc7)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(MSISDN:42342) received res: 7d b4 7c f7 f8 1e 4d c7 
-DVLR SUBSCR(MSISDN:42342) AUTH established UMTS security context
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Removing from parent Process_Access_Request_VLR(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: Received Event PR_ARQ_E_AUTH_RES
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
-- sending SecurityModeControl for MSISDN:42342
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_WAIT_CIPH
-DMM MSISDN:42342: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:42342: MSC conn use - 1 == 1
-  cipher_mode_cmd_sent == 1
-  cm_service_result_sent == 0
-- MS sends SecurityModeControl acceptance, VLR accepts; above Ciphering is an implicit CM Service Accept
-DMM <- SECURITY MODE COMPLETE MSISDN:42342
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_CIPH}: Received Event PR_ARQ_E_CIPH_RES
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_node2_post_ciph()
-DIUCS MSISDN:42342: tx CommonID 901700000010650
-- Iu Common ID --RAN_UTRAN_IU--> MS (IMSI=901700000010650)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_CIPH}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_CIPH}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_CM_SERVICE_REQ
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: received_cm_service_request = true
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: bump: still awaiting first request after a CM Service Request
-  cm_service_result_sent == 0
-- a USSD request is serviced
-  expecting USSD:
-  Your extension is 42342

-  MSC <--RAN_UTRAN_IU-- MS: GSM48_PDISC_NC_SS:0x3b
-DREF MSISDN:42342: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_PDISC_NC_SS:0x3b (0xb:0x3b)
-DMM MSISDN:42342: rx msg GSM48_PDISC_NC_SS:0x3b: received_cm_service_request changes to false
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM USSD: Own number requested
-DMM MSISDN:42342: MSISDN = 42342
-DMSC msc_tx 43 bytes to MSISDN:42342 via RAN_UTRAN_IU
-- DTAP --RAN_UTRAN_IU--> MS: GSM48_PDISC_NC_SS:0x2a: 8b2a1c27a225020100302002013b301b04010f0416d9775d0e2ae3e965f73cfd7683d273104d36a3c91a0d
-- DTAP matches expected message
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000010650)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:42342, cause=2): no conn fsm, releasing directly without release event.
-- Iu Release --RAN_UTRAN_IU--> MS
-DREF MSISDN:42342: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:42342: MSC conn use - 1 == 0
-DRLL subscr MSISDN:42342: Freeing subscriber connection
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-  iu_release_sent == 1
-- all requests serviced, conn has been released
-  llist_count(&net->subscr_conns) == 0
----
-- an SMS is sent, MS is paged
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:42342 usage increases to: 3
-DMM Subscriber MSISDN:42342 not paged yet, start paging.
-  RAN_UTRAN_IU sends out paging request to IMSI 901700000010650, TMSI 0x03020100, LAC 0
-  strcmp(paging_expecting_imsi, imsi) == 0
-DREF VLR subscr MSISDN:42342 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:42342 usage decreases to: 3
-  paging_sent == 1
-  paging_stopped == 0
-- the subscriber and its pending request should remain
-DREF VLR subscr MSISDN:42342 usage increases to: 4
-  llist_count(&vsub->cs.requests) == 1
-DREF VLR subscr MSISDN:42342 usage decreases to: 3
-- MS replies with Paging Response, and VLR sends Auth Request with third key
-  MSC <--RAN_UTRAN_IU-- MS: GSM48_MT_RR_PAG_RESP
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_RR_PAG_RESP (0x6:0x27)
-DRR PAGING RESPONSE: MI(IMSI)=901700000010650
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: Allocated
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: is child of Subscr_Conn(901700000010650)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: rev=R99 net=UTRAN Auth+Ciph
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START
-DREF VLR subscr MSISDN:42342 usage increases to: 4
-DREF VLR subscr MSISDN:42342 usage increases to: 5
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: is child of Process_Access_Request_VLR(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=2
-- sending UMTS Auth Request for MSISDN:42342: tuple use_count=1 key_seq=2 auth_types=0x3 and...
-- ...rand=efa9c29a9742148d5c9070348716e1bb
-- ...autn=f9375e6d41e1000096e7fe4ff1c27e39
-- ...expecting res=706f996719ba609c
-DREF VLR subscr MSISDN:42342 usage decreases to: 4
-DMM MSISDN:42342: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:42342: MSC conn use - 1 == 1
-  auth_request_sent == 1
-- needs auth, not yet accepted
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- MS sends Authen Response, VLR accepts and sends SecurityModeControl
-  MSC <--RAN_UTRAN_IU-- MS: GSM48_MT_MM_AUTH_RESP
-DREF MSISDN:42342: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM MSISDN:42342: MM R99 AUTHENTICATION RESPONSE (res = 706f996719ba609c)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(MSISDN:42342) received res: 70 6f 99 67 19 ba 60 9c 
-DVLR SUBSCR(MSISDN:42342) AUTH established UMTS security context
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Removing from parent Process_Access_Request_VLR(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: Received Event PR_ARQ_E_AUTH_RES
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
-- sending SecurityModeControl for MSISDN:42342
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_WAIT_CIPH
-DMM MSISDN:42342: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF MSISDN:42342: MSC conn use - 1 == 1
-  cipher_mode_cmd_sent == 1
-  paging_stopped == 0
-- MS sends SecurityModeControl acceptance, VLR accepts and sends SMS
-DMM <- SECURITY MODE COMPLETE MSISDN:42342
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_CIPH}: Received Event PR_ARQ_E_CIPH_RES
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_node2_post_ciph()
-DIUCS MSISDN:42342: tx CommonID 901700000010650
-- Iu Common ID --RAN_UTRAN_IU--> MS (IMSI=901700000010650)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_node2_post_vlr()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_pres()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_trace()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_CIPH}: _proc_arq_vlr_post_imei()
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_CIPH}: proc_arq_fsm_done(VLR_PR_ARQ_RES_PASSED)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_WAIT_CIPH}: state_chg to PR_ARQ_S_DONE
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Process Access Request result: VLR_PR_ARQ_RES_PASSED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_PAGING_RESP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DPAG Paging success for MSISDN:42342 (event=0)
-DPAG Calling paging cbfn.
-DREF VLR subscr MSISDN:42342 usage increases to: 5
-DREF MSISDN:42342: MSC conn use + 1 == 2
-DMSC msc_tx 91 bytes to MSISDN:42342 via RAN_UTRAN_IU
-- DTAP --RAN_UTRAN_IU--> MS: GSM48_PDISC_SMS:0x01: 09015801000791447758100650004c0005802443f2000007101000000000445079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0ed3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb0c7ac3e9e9b7db05
-- DTAP matches expected message
-DREF VLR subscr MSISDN:42342 usage decreases to: 4
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: bump: connection still has active transaction: GSM48_PDISC_SMS
-  paging_stopped == 1
-- SMS was delivered, no requests pending for subscr
-DREF VLR subscr MSISDN:42342 usage increases to: 5
-  llist_count(&vsub->cs.requests) == 0
-DREF VLR subscr MSISDN:42342 usage decreases to: 4
-- conn is still open to wait for SMS ack dance
-  llist_count(&net->subscr_conns) == 1
-- MS replies with CP-ACK for received SMS
-  MSC <--RAN_UTRAN_IU-- MS: GSM48_PDISC_SMS:0x04
-DREF MSISDN:42342: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x04 (0x9:0x4)
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_COMMUNICATING
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: bump: connection still has active transaction: GSM48_PDISC_SMS
-DREF MSISDN:42342: MSC conn use - 1 == 2
-  llist_count(&net->subscr_conns) == 1
-- MS also sends RP-ACK, MSC in turn sends CP-ACK for that
-  MSC <--RAN_UTRAN_IU-- MS: GSM48_PDISC_SMS:0x01
-DREF MSISDN:42342: MSC conn use + 1 == 3
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_COMMUNICATING
-DMSC msc_tx 2 bytes to MSISDN:42342 via RAN_UTRAN_IU
-- DTAP --RAN_UTRAN_IU--> MS: GSM48_PDISC_SMS:0x04: 0904
-- DTAP matches expected message
-DREF VLR subscr MSISDN:42342 usage decreases to: 3
-DREF VLR subscr MSISDN:42342 usage decreases to: 2
-DREF MSISDN:42342: MSC conn use - 1 == 2
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: bump: releasing conn
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_COMMUNICATING}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Removing from parent Subscr_Conn(901700000010650)
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Freeing instance
-DVLR Process_Access_Request_VLR(901700000010650){PR_ARQ_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:42342, cause=2): no conn fsm, releasing directly without release event.
-- Iu Release --RAN_UTRAN_IU--> MS
-DREF MSISDN:42342: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:42342: MSC conn use - 1 == 0
-DRLL subscr MSISDN:42342: Freeing subscriber connection
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-  dtap_tx_confirmed == 1
-  iu_release_sent == 1
-- SMS is done, conn is gone
-  llist_count(&net->subscr_conns) == 0
----
-- subscriber detaches
-  MSC <--RAN_UTRAN_IU-- MS: GSM48_MT_MM_IMSI_DETACH_IND
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_IMSI_DETACH_IND (0x5:0x1)
-DMM IMSI DETACH INDICATION: MI(IMSI)=901700000010650
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-DMM IMSI DETACH for MSISDN:42342
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-DREF VLR subscr MSISDN:42342 usage decreases to: 0
-DREF freeing VLR subscr MSISDN:42342
-DMM msc_subscr_conn_close(vsub=unknown, cause=0): no conn fsm, releasing directly without release event.
-- Iu Release --RAN_UTRAN_IU--> MS
-DREF unknown: MSC conn use - 1 == 0
-DRLL Freeing subscriber connection with NULL subscriber
-  iu_release_sent == 1
-  llist_count(&net->subscr_conns) == 0
-===== test_umts_authen_utran: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_umts_authen_resync_geran
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000010650 type=NORMAL
-DMM LU/new-LAC: 0/0
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000010650)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: rev=R99 net=GERAN Auth (no Ciph)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000010650 id=901700000010650
-DVLR New subscr, IMSI: 901700000010650
-DREF VLR subscr IMSI:901700000010650 usage increases to: 2
-DREF VLR subscr IMSI:901700000010650 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000000156f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000000156f0
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000010650: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000010650: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000000156f00362201039fa2f4e3d523d8619a73b4f65c3e14d21049b36efdf2208059a4f668f6fbe39231027497388b6cb044648f396aa155b95ef2410f64735036e5871319c679f4742a75ea125108704f5ba55f30000d2ee44b22c8ea9192708e229c19e791f2e41
-DVLR GSUP rx 111: 0a010809710000000156f00362201039fa2f4e3d523d8619a73b4f65c3e14d21049b36efdf2208059a4f668f6fbe39231027497388b6cb044648f396aa155b95ef2410f64735036e5871319c679f4742a75ea125108704f5ba55f30000d2ee44b22c8ea9192708e229c19e791f2e41
-DREF VLR subscr IMSI:901700000010650 usage increases to: 2
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000010650) Received 1 auth tuples
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending UMTS Auth Request for IMSI:901700000010650: tuple use_count=1 key_seq=0 auth_types=0x3 and...
-- ...rand=39fa2f4e3d523d8619a73b4f65c3e14d
-- ...autn=8704f5ba55f30000d2ee44b22c8ea919
-- ...expecting res=e229c19e791f2e41
-DREF VLR subscr IMSI:901700000010650 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- MS sends Authen Failure with Resync cause, VLR sends GSUP to HLR to resync
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_FAIL
-DREF IMSI:901700000010650: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_FAIL (0x5:0x1c)
-DMM IMSI:901700000010650: MM R99 AUTHENTICATION SYNCH (AUTS = 979498b1f72d3e28c59fa2e72f9c)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_FAIL
-DVLR GSUP tx: 08010809710000000156f0260e979498b1f72d3e28c59fa2e72f9c201039fa2f4e3d523d8619a73b4f65c3e14d
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000000156f0260e979498b1f72d3e28c59fa2e72f9c201039fa2f4e3d523d8619a73b4f65c3e14d
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_SAI_RESYNC
-DMM IMSI:901700000010650: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000010650: MSC conn use - 1 == 1
-  gsup_tx_confirmed == 1
-  auth_request_sent == 0
-  lu_result_sent == 0
-- HLR replies with new tuples
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000000156f0036220100f1feb1623e1bf626334e37ec448ac182104efde99da220814778c855c52373023108a90c769b7272f3bb7a1c1fbb1ea9349241043ffc1cf8c89a7fd6ab94bd8d6162cbf251002a83f62e9470000660d51afc75f169d27081df5f0b4f22b696e03622010ac21d34937b4e1142a2c757af294931921047818bfdc2208d175571f41f314a42310ff8edbceb6dd24799c77c3b9a6790c102410157c39022ca9d885a7f0766a7dfee44825108a43b91898e500002cf354c6f5d1f8c32708f748a7078f5018db
-DVLR GSUP rx 211: 0a010809710000000156f0036220100f1feb1623e1bf626334e37ec448ac182104efde99da220814778c855c52373023108a90c769b7272f3bb7a1c1fbb1ea9349241043ffc1cf8c89a7fd6ab94bd8d6162cbf251002a83f62e9470000660d51afc75f169d27081df5f0b4f22b696e03622010ac21d34937b4e1142a2c757af294931921047818bfdc2208d175571f41f314a42310ff8edbceb6dd24799c77c3b9a6790c102410157c39022ca9d885a7f0766a7dfee44825108a43b91898e500002cf354c6f5d1f8c32708f748a7078f5018db
-DREF VLR subscr IMSI:901700000010650 usage increases to: 2
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH_WAIT_SAI_RESYNC}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000010650) Received 2 auth tuples
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH_WAIT_SAI_RESYNC}: state_chg to VLR_SUB_AS_WAIT_RESP_RESYNC
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP_RESYNC}: got auth tuple: use_count=1 key_seq=0
-- sending UMTS Auth Request for IMSI:901700000010650: tuple use_count=1 key_seq=0 auth_types=0x3 and...
-- ...rand=0f1feb1623e1bf626334e37ec448ac18
-- ...autn=02a83f62e9470000660d51afc75f169d
-- ...expecting res=1df5f0b4f22b696e
-DREF VLR subscr IMSI:901700000010650 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends GSUP LU Req to HLR
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000010650: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000010650: MM R99 AUTHENTICATION RESPONSE (res = 1df5f0b4f22b696e)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP_RESYNC}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000010650) received res: 1d f5 f0 b4 f2 2b 69 6e 
-DVLR SUBSCR(IMSI:901700000010650) AUTH established UMTS security context
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP_RESYNC}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP_RESYNC}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph()
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000010650)
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000000156f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000000156f0
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-DMM IMSI:901700000010650: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000010650: MSC conn use - 1 == 1
-  gsup_tx_confirmed == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000000156f00804032443f2
-DVLR GSUP rx 17: 10010809710000000156f00804032443f2
-DREF VLR subscr IMSI:901700000010650 usage increases to: 2
-DVLR IMSI:901700000010650 has MSISDN:42342
-DVLR GSUP tx: 12010809710000000156f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000000156f0
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000000156f0
-DVLR GSUP rx 11: 06010809710000000156f0
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000010650)
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000010650)
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000010650)
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000010650)
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_SUB_PRES}: lu_compl_vlr_new_tmsi()
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_WAIT_TMSI_CNF
-- sending LU Accept for MSISDN:42342, with TMSI 0x03020100
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 1
-- a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl
-  llist_count(&net->subscr_conns) == 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- even though the TMSI is not acked, we can already find the subscr with it
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-  vsub != NULL == 1
-  strcmp(vsub->imsi, imsi) == 0
-  vsub->tmsi_new == 0x03020100
-  vsub->tmsi == 0xffffffff
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-- MS sends TMSI Realloc Complete
-  MSC <--RAN_GERAN_A-- MS: GSM48_MT_MM_TMSI_REALL_COMPL
-DREF MSISDN:42342: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_TMSI_REALL_COMPL (0x5:0x1b)
-DMM TMSI Reallocation Completed. Subscriber: MSISDN:42342
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_NEW_TMSI_ACK
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: Received Event LU_COMPL_VLR_E_NEW_TMSI_ACK
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000010650)
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000010650)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:42342, cause=2): no conn fsm, releasing directly without release event.
-- BSSAP Clear --RAN_GERAN_A--> MS
-DREF MSISDN:42342: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:42342: MSC conn use - 1 == 0
-DRLL subscr MSISDN:42342: Freeing subscriber connection
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-  bssap_clear_sent == 1
-- LU was successful, and the conn has already been closed
-  llist_count(&net->subscr_conns) == 0
-DREF freeing VLR subscr MSISDN:42342
-===== test_umts_authen_resync_geran: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-===== test_umts_authen_resync_utran
-- Location Update request causes a GSUP Send Auth Info request to HLR
-  MSC <--RAN_UTRAN_IU-- MS: GSM48_MT_MM_LOC_UPD_REQUEST
-  new conn
-DREF unknown: MSC conn use + 1 == 1
-DRLL Dispatching 04.08 message GSM48_MT_MM_LOC_UPD_REQUEST (0x5:0x8)
-DREF unknown: MSC conn use + 1 == 2
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Allocated
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: Received Event SUBSCR_CONN_E_START
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_INIT}: state_chg to SUBSCR_CONN_S_NEW
-DMM LOCATION UPDATING REQUEST: MI(IMSI)=901700000010650 type=NORMAL
-DMM LU/new-LAC: 0/0
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: Allocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: is child of Subscr_Conn(901700000010650)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: rev=R99 net=UTRAN Auth+Ciph
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA
-DREF VLR subscr unknown usage increases to: 1
-DVLR set IMSI on subscriber; IMSI=901700000010650 id=901700000010650
-DVLR New subscr, IMSI: 901700000010650
-DREF VLR subscr IMSI:901700000010650 usage increases to: 2
-DREF VLR subscr IMSI:901700000010650 usage decreases to: 1
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: vlr_loc_upd_node1()
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_AUTH
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Allocated
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: is child of vlr_lu_fsm(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: Received Event VLR_AUTH_E_START
-DVLR GSUP tx: 08010809710000000156f0
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000000156f0
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_AI
-DMM IMSI:901700000010650: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000010650: MSC conn use - 1 == 1
-  lu_result_sent == 0
-- from HLR, rx _SEND_AUTH_INFO_RESULT; VLR sends Auth Req to MS
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000000156f00362201039fa2f4e3d523d8619a73b4f65c3e14d21049b36efdf2208059a4f668f6fbe39231027497388b6cb044648f396aa155b95ef2410f64735036e5871319c679f4742a75ea125108704f5ba55f30000d2ee44b22c8ea9192708e229c19e791f2e41
-DVLR GSUP rx 111: 0a010809710000000156f00362201039fa2f4e3d523d8619a73b4f65c3e14d21049b36efdf2208059a4f668f6fbe39231027497388b6cb044648f396aa155b95ef2410f64735036e5871319c679f4742a75ea125108704f5ba55f30000d2ee44b22c8ea9192708e229c19e791f2e41
-DREF VLR subscr IMSI:901700000010650 usage increases to: 2
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000010650) Received 1 auth tuples
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_WAIT_RESP
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: got auth tuple: use_count=1 key_seq=0
-- sending UMTS Auth Request for IMSI:901700000010650: tuple use_count=1 key_seq=0 auth_types=0x3 and...
-- ...rand=39fa2f4e3d523d8619a73b4f65c3e14d
-- ...autn=8704f5ba55f30000d2ee44b22c8ea919
-- ...expecting res=e229c19e791f2e41
-DREF VLR subscr IMSI:901700000010650 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- MS sends Authen Failure with Resync cause, VLR sends GSUP to HLR to resync
-  MSC <--RAN_UTRAN_IU-- MS: GSM48_MT_MM_AUTH_FAIL
-DREF IMSI:901700000010650: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_FAIL (0x5:0x1c)
-DMM IMSI:901700000010650: MM R99 AUTHENTICATION SYNCH (AUTS = 979498b1f72d3e28c59fa2e72f9c)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_FAIL
-DVLR GSUP tx: 08010809710000000156f0260e979498b1f72d3e28c59fa2e72f9c201039fa2f4e3d523d8619a73b4f65c3e14d
-GSUP --> HLR: OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: 08010809710000000156f0260e979498b1f72d3e28c59fa2e72f9c201039fa2f4e3d523d8619a73b4f65c3e14d
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_NEEDS_AUTH_WAIT_SAI_RESYNC
-DMM IMSI:901700000010650: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000010650: MSC conn use - 1 == 1
-  gsup_tx_confirmed == 1
-  auth_request_sent == 0
-  lu_result_sent == 0
-- HLR replies with new tuples
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000000156f0036220100f1feb1623e1bf626334e37ec448ac182104efde99da220814778c855c52373023108a90c769b7272f3bb7a1c1fbb1ea9349241043ffc1cf8c89a7fd6ab94bd8d6162cbf251002a83f62e9470000660d51afc75f169d27081df5f0b4f22b696e03622010ac21d34937b4e1142a2c757af294931921047818bfdc2208d175571f41f314a42310ff8edbceb6dd24799c77c3b9a6790c102410157c39022ca9d885a7f0766a7dfee44825108a43b91898e500002cf354c6f5d1f8c32708f748a7078f5018db
-DVLR GSUP rx 211: 0a010809710000000156f0036220100f1feb1623e1bf626334e37ec448ac182104efde99da220814778c855c52373023108a90c769b7272f3bb7a1c1fbb1ea9349241043ffc1cf8c89a7fd6ab94bd8d6162cbf251002a83f62e9470000660d51afc75f169d27081df5f0b4f22b696e03622010ac21d34937b4e1142a2c757af294931921047818bfdc2208d175571f41f314a42310ff8edbceb6dd24799c77c3b9a6790c102410157c39022ca9d885a7f0766a7dfee44825108a43b91898e500002cf354c6f5d1f8c32708f748a7078f5018db
-DREF VLR subscr IMSI:901700000010650 usage increases to: 2
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH_WAIT_SAI_RESYNC}: Received Event VLR_AUTH_E_HLR_SAI_ACK
-DVLR SUBSCR(IMSI:901700000010650) Received 2 auth tuples
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_NEEDS_AUTH_WAIT_SAI_RESYNC}: state_chg to VLR_SUB_AS_WAIT_RESP_RESYNC
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP_RESYNC}: got auth tuple: use_count=1 key_seq=0
-- sending UMTS Auth Request for IMSI:901700000010650: tuple use_count=1 key_seq=0 auth_types=0x3 and...
-- ...rand=0f1feb1623e1bf626334e37ec448ac18
-- ...autn=02a83f62e9470000660d51afc75f169d
-- ...expecting res=1df5f0b4f22b696e
-DREF VLR subscr IMSI:901700000010650 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: vlr_gsupc_read_cb() returns 0
-  auth_request_sent == 1
-  lu_result_sent == 0
-- MS sends Authen Response, VLR accepts and sends SecurityModeControl
-  MSC <--RAN_UTRAN_IU-- MS: GSM48_MT_MM_AUTH_RESP
-DREF IMSI:901700000010650: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_AUTH_RESP (0x5:0x14)
-DMM IMSI:901700000010650: MM R99 AUTHENTICATION RESPONSE (res = 1df5f0b4f22b696e)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP_RESYNC}: Received Event VLR_AUTH_E_MS_AUTH_RESP
-DVLR SUBSCR(IMSI:901700000010650) received res: 1d f5 f0 b4 f2 2b 69 6e 
-DVLR SUBSCR(IMSI:901700000010650) AUTH established UMTS security context
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP_RESYNC}: Authentication terminating with result VLR_AUTH_RES_PASSED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_WAIT_RESP_RESYNC}: state_chg to VLR_SUB_AS_AUTHENTICATED
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(901700000010650)
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Freeing instance
-DVLR VLR_Authenticate(901700000010650){VLR_SUB_AS_AUTHENTICATED}: Deallocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
-- sending SecurityModeControl for IMSI:901700000010650
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_CIPH
-DMM IMSI:901700000010650: bump: conn still being established (SUBSCR_CONN_S_NEW)
-DREF IMSI:901700000010650: MSC conn use - 1 == 1
-  cipher_mode_cmd_sent == 1
-  lu_result_sent == 0
-- MS sends SecurityModeControl acceptance, VLR accepts and sends GSUP LU Req to HLR
-DMM <- SECURITY MODE COMPLETE IMSI:901700000010650
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_CIPH}: Received Event VLR_ULA_E_CIPH_RES
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_CIPH}: vlr_loc_upd_post_ciph()
-DIUCS IMSI:901700000010650: tx CommonID 901700000010650
-- Iu Common ID --RAN_UTRAN_IU--> MS (IMSI=901700000010650)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_CIPH}: vlr_loc_upd_node_4()
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_CIPH}: state_chg to VLR_ULA_S_WAIT_HLR_UPD
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: Allocated
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(901700000010650)
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START
-DVLR GSUP tx: 04010809710000000156f0
-GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000000156f0
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA
-  gsup_tx_confirmed == 1
-  lu_result_sent == 0
-- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000000156f00804032443f2
-DVLR GSUP rx 17: 10010809710000000156f00804032443f2
-DREF VLR subscr IMSI:901700000010650 usage increases to: 2
-DVLR IMSI:901700000010650 has MSISDN:42342
-DVLR GSUP tx: 12010809710000000156f0
-GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000000156f0
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 0
-- HLR also sends GSUP _UPDATE_LOCATION_RESULT
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000000156f0
-DVLR GSUP rx 11: 06010809710000000156f0
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000010650)
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Freeing instance
-DVLR upd_hlr_vlr_fsm(901700000010650){UPD_HLR_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: Allocated
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(901700000010650)
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: Allocated
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: is child of lu_compl_vlr_fsm(901700000010650)
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: Received Event SUB_PRES_VLR_E_START
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_INIT}: state_chg to SUB_PRES_VLR_S_DONE
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Removing from parent lu_compl_vlr_fsm(901700000010650)
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Freeing instance
-DVLR sub_pres_vlr_fsm(901700000010650){SUB_PRES_VLR_S_DONE}: Deallocated
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_SUB_PRES}: lu_compl_vlr_new_tmsi()
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_WAIT_TMSI_CNF
-- sending LU Accept for MSISDN:42342, with TMSI 0x03020100
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0
-  lu_result_sent == 1
-- a LU Accept with a new TMSI was sent, waiting for TMSI Realloc Compl
-  llist_count(&net->subscr_conns) == 1
-msc_subscr_conn_is_accepted() == false
-  requests shall be thwarted
-DRLL Dispatching 04.08 message GSM48_MT_CC_SETUP (0x3:0x5)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_CC_SETUP
-DRLL Dispatching 04.08 message unknown 0x33 (0x5:0x33)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: unknown 0x33
-DRLL Dispatching 04.08 message GSM48_MT_RR_SYSINFO_1 (0x6:0x19)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_MT_RR_SYSINFO_1
-DRLL Dispatching 04.08 message GSM48_PDISC_SMS:0x01 (0x9:0x1)
-DRLL subscr MSISDN:42342: Message not permitted for initial conn: GSM48_PDISC_SMS:0x01
-- even though the TMSI is not acked, we can already find the subscr with it
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-  vsub != NULL == 1
-  strcmp(vsub->imsi, imsi) == 0
-  vsub->tmsi_new == 0x03020100
-  vsub->tmsi == 0xffffffff
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-- MS sends TMSI Realloc Complete
-  MSC <--RAN_UTRAN_IU-- MS: GSM48_MT_MM_TMSI_REALL_COMPL
-DREF MSISDN:42342: MSC conn use + 1 == 2
-DRLL Dispatching 04.08 message GSM48_MT_MM_TMSI_REALL_COMPL (0x5:0x1b)
-DMM TMSI Reallocation Completed. Subscriber: MSISDN:42342
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_NEW_TMSI_ACK
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: Received Event LU_COMPL_VLR_E_NEW_TMSI_ACK
-DREF VLR subscr MSISDN:42342 usage increases to: 2
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_WAIT_TMSI_CNF}: state_chg to LU_COMPL_VLR_S_DONE
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(901700000010650)
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Freeing instance
-DVLR lu_compl_vlr_fsm(901700000010650){LU_COMPL_VLR_S_DONE}: Deallocated
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: Received Event SUBSCR_CONN_E_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: SUBSCR_CONN_FROM_LU
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_NEW}: state_chg to SUBSCR_CONN_S_ACCEPTED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: Received Event SUBSCR_CONN_E_BUMP
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: bump: releasing conn
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_ACCEPTED}: state_chg to SUBSCR_CONN_S_RELEASED
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Terminating (cause = OSMO_FSM_TERM_PARENT)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Removing from parent Subscr_Conn(901700000010650)
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Freeing instance
-DVLR vlr_lu_fsm(901700000010650){VLR_ULA_S_DONE}: Deallocated
-DMM msc_subscr_conn_close(vsub=MSISDN:42342, cause=2): no conn fsm, releasing directly without release event.
-- Iu Release --RAN_UTRAN_IU--> MS
-DREF MSISDN:42342: MSC conn use - 1 == 1
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Freeing instance
-DMM Subscr_Conn(901700000010650){SUBSCR_CONN_S_RELEASED}: Deallocated
-DREF MSISDN:42342: MSC conn use - 1 == 0
-DRLL subscr MSISDN:42342: Freeing subscriber connection
-DREF VLR subscr MSISDN:42342 usage decreases to: 1
-  iu_release_sent == 1
-- LU was successful, and the conn has already been closed
-  llist_count(&net->subscr_conns) == 0
-DREF freeing VLR subscr MSISDN:42342
-===== test_umts_authen_resync_utran: SUCCESS
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
-full talloc report on 'msgb' (total      0 bytes in   1 blocks)
-talloc_total_blocks(tall_bsc_ctx) == 9
-
diff --git a/tests/msc_vlr/msc_vlr_test_umts_authen.ok b/tests/msc_vlr/msc_vlr_test_umts_authen.ok
deleted file mode 100644
index a965a70..0000000
--- a/tests/msc_vlr/msc_vlr_test_umts_authen.ok
+++ /dev/null
@@ -1 +0,0 @@
-Done
diff --git a/tests/msc_vlr/msc_vlr_tests.c b/tests/msc_vlr/msc_vlr_tests.c
deleted file mode 100644
index 71f9713..0000000
--- a/tests/msc_vlr/msc_vlr_tests.c
+++ /dev/null
@@ -1,805 +0,0 @@
-/* Osmocom MSC+VLR end-to-end tests */
-
-/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- *
- * All Rights Reserved
- *
- * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
- *
- * 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/>.
- *
- */
-
-#include <getopt.h>
-#include <stdlib.h>
-
-#include <osmocom/core/logging.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/application.h>
-#include <osmocom/gsm/protocol/gsm_04_11.h>
-#include <osmocom/gsm/gsup.h>
-#include <openbsc/gsup_client.h>
-#include <openbsc/gsm_04_11.h>
-#include <openbsc/bsc_subscriber.h>
-#include <openbsc/debug.h>
-
-#if BUILD_IU
-#include <openbsc/iucs_ranap.h>
-#include <osmocom/ranap/iu_client.h>
-#else
-#include <openbsc/iu_dummy.h>
-#endif
-
-#include "msc_vlr_tests.h"
-
-bool _log_lines = false;
-
-struct gsm_network *net = NULL;
-
-struct gsm_bts *the_bts;
-
-const char *gsup_tx_expected = NULL;
-bool gsup_tx_confirmed;
-
-struct msgb *dtap_tx_expected = NULL;
-bool dtap_tx_confirmed;
-
-enum result_sent lu_result_sent;
-enum result_sent cm_service_result_sent;
-bool auth_request_sent;
-const char *auth_request_expect_rand;
-const char *auth_request_expect_autn;
-bool cipher_mode_cmd_sent;
-bool cipher_mode_cmd_sent_with_imeisv;
-
-bool iu_release_expected = false;
-bool iu_release_sent = false;
-bool bssap_clear_expected = false;
-bool bssap_clear_sent = false;
-
-struct msgb *msgb_from_hex(const char *label, uint16_t size, const char *hex)
-{
-	struct msgb *msg = msgb_alloc(size, label);
-	unsigned char *rc;
-	msg->l2h = msg->head;
-	rc = msgb_put(msg, osmo_hexparse(hex, msg->head, msgb_tailroom(msg)));
-	OSMO_ASSERT(rc == msg->l2h);
-	return msg;
-}
-
-const char *gh_type_name(struct gsm48_hdr *gh)
-{
-	return gsm48_pdisc_msgtype_name(gsm48_hdr_pdisc(gh),
-					gsm48_hdr_msg_type(gh));
-}
-
-const char *msg_type_name(struct msgb *msg)
-{
-	return gh_type_name((void*)msg->data);
-}
-
-void dtap_expect_tx(const char *hex)
-{
-	/* Has the previously expected dtap been received? */
-	OSMO_ASSERT(!dtap_tx_expected);
-	if (!hex)
-		return;
-	dtap_tx_expected = msgb_from_hex("dtap_tx_expected", 1024, hex);
-	dtap_tx_confirmed = false;
-}
-
-void dtap_expect_tx_ussd(char *ussd_text)
-{
-	uint8_t ussd_enc[128];
-	int len;
-	/* header */
-	char ussd_msg_hex[128] = "8b2a1c27a225020100302002013b301b04010f0416";
-
-	log("expecting USSD:\n  %s", ussd_text);
-	/* append encoded USSD text */
-	gsm_7bit_encode_n_ussd(ussd_enc, sizeof(ussd_enc), ussd_text,
-			       &len);
-	strncat(ussd_msg_hex, osmo_hexdump_nospc(ussd_enc, len),
-		sizeof(ussd_msg_hex) - strlen(ussd_msg_hex));
-	dtap_expect_tx(ussd_msg_hex);
-}
-
-int vlr_gsupc_read_cb(struct gsup_client *gsupc, struct msgb *msg);
-
-void gsup_rx(const char *rx_hex, const char *expect_tx_hex)
-{
-	int rc;
-	struct msgb *msg;
-	const char *label;
-
-	gsup_expect_tx(expect_tx_hex);
-
-	msg = msgb_from_hex("gsup", 1024, rx_hex);
-	label = osmo_gsup_message_type_name(msg->l2h[0]);
-	fprintf(stderr, "<-- GSUP rx %s: %s\n", label,
-		osmo_hexdump_nospc(msgb_l2(msg), msgb_l2len(msg)));
-	rc = vlr_gsupc_read_cb(net->vlr->gsup_client, msg);
-	fprintf(stderr, "<-- GSUP rx %s: vlr_gsupc_read_cb() returns %d\n",
-		label, rc);
-	if (expect_tx_hex)
-		OSMO_ASSERT(gsup_tx_confirmed);
-	talloc_free(msg);
-}
-
-bool conn_exists(struct gsm_subscriber_connection *conn)
-{
-	struct gsm_subscriber_connection *c;
-	llist_for_each_entry(c, &net->subscr_conns, entry) {
-		if (c == conn)
-			return true;
-	}
-	return false;
-}
-
-enum ran_type rx_from_ran = RAN_GERAN_A;
-
-struct gsm_subscriber_connection *conn_new(void)
-{
-	struct gsm_subscriber_connection *conn;
-	conn = msc_subscr_con_allocate(net);
-	conn->bts = the_bts;
-	conn->via_ran = rx_from_ran;
-	if (conn->via_ran == RAN_UTRAN_IU) {
-		struct ranap_ue_conn_ctx *ue_ctx = talloc_zero(conn, struct ranap_ue_conn_ctx);
-		*ue_ctx = (struct ranap_ue_conn_ctx){
-			.conn_id = 42,
-		};
-		conn->iu.ue_ctx = ue_ctx;
-	}
-	return conn;
-}
-
-struct gsm_subscriber_connection *g_conn = NULL;
-
-void rx_from_ms(struct msgb *msg)
-{
-	int rc;
-
-	struct gsm48_hdr *gh = msgb_l3(msg);
-
-	log("MSC <--%s-- MS: %s",
-	    ran_type_name(rx_from_ran),
-	    gh_type_name(gh));
-
-	if (g_conn && !conn_exists(g_conn))
-		g_conn = NULL;
-
-	if (!g_conn) {
-		log("new conn");
-		g_conn = conn_new();
-		rc = msc_compl_l3(g_conn, msg, 23);
-		if (rc == BSC_API_CONN_POL_REJECT) {
-			msc_subscr_con_free(g_conn);
-			g_conn = NULL;
-		}
-	} else {
-		if ((gsm48_hdr_pdisc(gh) == GSM48_PDISC_RR)
-		    && (gsm48_hdr_msg_type(gh) == GSM48_MT_RR_CIPH_M_COMPL))
-			msc_cipher_mode_compl(g_conn, msg, 0);
-		else
-			msc_dtap(g_conn, 23, msg);
-	}
-
-	if (g_conn && !conn_exists(g_conn))
-		g_conn = NULL;
-}
-
-void ms_sends_msg(const char *hex)
-{
-	struct msgb *msg;
-
-	msg = msgb_from_hex("ms_sends_msg", 1024, hex);
-	msg->l1h = msg->l2h = msg->l3h = msg->data;
-	rx_from_ms(msg);
-	talloc_free(msg);
-}
-
-int ms_sends_msg_fake(uint8_t pdisc, uint8_t msg_type)
-{
-	int rc;
-	struct msgb *msg;
-	struct gsm48_hdr *gh;
-
-	msg = msgb_alloc(1024, "ms_sends_msg_fake");
-	msg->l1h = msg->l2h = msg->l3h = msg->data;
-
-	gh = (struct gsm48_hdr*)msgb_put(msg, sizeof(*gh));
-	gh->proto_discr = pdisc;
-	gh->msg_type = msg_type;
-	/* some amount of data, whatever */
-	msgb_put(msg, 123);
-
-	rc = gsm0408_dispatch(g_conn, msg);
-
-	talloc_free(msg);
-	return rc;
-}
-
-void thwart_rx_non_initial_requests()
-{
-	log("requests shall be thwarted");
-	OSMO_ASSERT(ms_sends_msg_fake(GSM48_PDISC_CC, GSM48_MT_CC_SETUP) == -EACCES);
-	OSMO_ASSERT(ms_sends_msg_fake(GSM48_PDISC_MM, 0x33 /* nonexistent */) == -EACCES);
-	OSMO_ASSERT(ms_sends_msg_fake(GSM48_PDISC_RR, GSM48_MT_RR_SYSINFO_1) == -EACCES);
-	OSMO_ASSERT(ms_sends_msg_fake(GSM48_PDISC_SMS, GSM411_MT_CP_DATA) == -EACCES);
-}
-
-void send_sms(struct vlr_subscr *receiver,
-	      struct vlr_subscr *sender,
-	      char *str)
-{
-	struct gsm_sms *sms = sms_from_text(receiver, sender, 0, str);
-	gsm411_send_sms_subscr(receiver, sms);
-}
-
-unsigned char next_rand_byte = 0;
-/* override, requires '-Wl,--wrap=RAND_bytes' */
-int __real_RAND_bytes(unsigned char *buf, int num);
-int __wrap_RAND_bytes(unsigned char *buf, int num)
-{
-	int i;
-	for (i = 0; i < num; i++)
-		buf[i] = next_rand_byte++;
-	return 1;
-}
-
-/* override, requires '-Wl,--wrap=gsm340_gen_scts' */
-void __real_gsm340_gen_scts(uint8_t *scts, time_t time);
-void __wrap_gsm340_gen_scts(uint8_t *scts, time_t time)
-{
-	/* Write fixed time bytes for deterministic test results */
-	osmo_hexparse("07101000000000", scts, 7);
-}
-
-const char *paging_expecting_imsi = NULL;
-uint32_t paging_expecting_tmsi;
-bool paging_sent;
-bool paging_stopped;
-
-void paging_expect_imsi(const char *imsi)
-{
-	paging_expecting_imsi = imsi;
-	paging_expecting_tmsi = GSM_RESERVED_TMSI;
-}
-
-void paging_expect_tmsi(uint32_t tmsi)
-{
-	paging_expecting_tmsi = tmsi;
-	paging_expecting_imsi = NULL;
-}
-
-int _paging_sent(enum ran_type via_ran, const char *imsi, uint32_t tmsi, uint32_t lac)
-{
-	log("%s sends out paging request to IMSI %s, TMSI 0x%08x, LAC %u",
-	    ran_type_name(via_ran), imsi, tmsi, lac);
-	OSMO_ASSERT(paging_expecting_imsi || (paging_expecting_tmsi != GSM_RESERVED_TMSI));
-	if (paging_expecting_imsi)
-		VERBOSE_ASSERT(strcmp(paging_expecting_imsi, imsi), == 0, "%d");
-	if (paging_expecting_tmsi != GSM_RESERVED_TMSI) {
-		VERBOSE_ASSERT(paging_expecting_tmsi, == tmsi, "0x%08x");
-	}
-	paging_sent = true;
-	paging_stopped = false;
-	return 1;
-}
-
-/* override, requires '-Wl,--wrap=ranap_iu_page_cs' */
-int __real_ranap_iu_page_cs(const char *imsi, const uint32_t *tmsi, uint16_t lac);
-int __wrap_ranap_iu_page_cs(const char *imsi, const uint32_t *tmsi, uint16_t lac)
-{
-	return _paging_sent(RAN_UTRAN_IU, imsi, tmsi ? *tmsi : GSM_RESERVED_TMSI, lac);
-}
-
-/* override, requires '-Wl,--wrap=a_iface_tx_paging' */
-int __real_a_iface_tx_paging(const char *imsi, uint32_t tmsi, uint16_t lac);
-int __wrap_a_iface_tx_paging(const char *imsi, uint32_t tmsi, uint16_t lac)
-{
-	return _paging_sent(RAN_GERAN_A, imsi, tmsi, lac);
-}
-
-/* override, requires '-Wl,--wrap=msc_stop_paging' */
-void __real_msc_stop_paging(struct vlr_subscr *vsub);
-void __wrap_msc_stop_paging(struct vlr_subscr *vsub)
-{
-	paging_stopped = true;
-}
-
-void clear_vlr()
-{
-	struct vlr_subscr *vsub, *n;
-	llist_for_each_entry_safe(vsub, n, &net->vlr->subscribers, list) {
-		vlr_subscr_free(vsub);
-	}
-
-	net->authentication_required = false;
-	net->a5_encryption = VLR_CIPH_NONE;
-	net->vlr->cfg.check_imei_rqd = false;
-	net->vlr->cfg.assign_tmsi = false;
-	net->vlr->cfg.retrieve_imeisv_early = false;
-	net->vlr->cfg.retrieve_imeisv_ciphered = false;
-
-	rx_from_ran = RAN_GERAN_A;
-	auth_request_sent = false;
-	auth_request_expect_rand = NULL;
-	auth_request_expect_autn = NULL;
-
-	next_rand_byte = 0;
-
-	iu_release_expected = false;
-	iu_release_sent = false;
-	bssap_clear_expected = false;
-	bssap_clear_sent = false;
-
-	osmo_gettimeofday_override = false;
-}
-
-static struct log_info_cat test_categories[] = {
-	[DMSC] = {
-		.name = "DMSC",
-		.description = "Mobile Switching Center",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DRLL] = {
-		.name = "DRLL",
-		.description = "A-bis Radio Link Layer (RLL)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DMM] = {
-		.name = "DMM",
-		.description = "Layer3 Mobility Management (MM)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DRR] = {
-		.name = "DRR",
-		.description = "Layer3 Radio Resource (RR)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DCC] = {
-		.name = "DCC",
-		.description = "Layer3 Call Control (CC)",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DMM] = {
-		.name = "DMM",
-		.description = "Layer3 Mobility Management (MM)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DVLR] = {
-		.name = "DVLR",
-		.description = "Visitor Location Register",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DREF] = {
-		.name = "DREF",
-		.description = "Reference Counting",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DPAG]	= {
-		.name = "DPAG",
-		.description = "Paging Subsystem",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DIUCS] = {
-		.name = "DIUCS",
-		.description = "Iu-CS Protocol",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-};
-
-static struct log_info info = {
-	.cat = test_categories,
-	.num_cat = ARRAY_SIZE(test_categories),
-};
-
-extern void *tall_bsc_ctx;
-
-int fake_mncc_recv(struct gsm_network *net, struct msgb *msg)
-{
-	fprintf(stderr, "rx MNCC\n");
-	return 0;
-}
-
-/* override, requires '-Wl,--wrap=gsup_client_create' */
-struct gsup_client *
-__real_gsup_client_create(const char *ip_addr, unsigned int tcp_port,
-			  gsup_client_read_cb_t read_cb,
-			  struct oap_client_config *oap_config);
-struct gsup_client *
-__wrap_gsup_client_create(const char *ip_addr, unsigned int tcp_port,
-			  gsup_client_read_cb_t read_cb,
-			  struct oap_client_config *oap_config)
-{
-	struct gsup_client *gsupc;
-	gsupc = talloc_zero(tall_bsc_ctx, struct gsup_client);
-	OSMO_ASSERT(gsupc);
-	return gsupc;
-}
-
-/* override, requires '-Wl,--wrap=gsup_client_send' */
-int __real_gsup_client_send(struct gsup_client *gsupc, struct msgb *msg);
-int __wrap_gsup_client_send(struct gsup_client *gsupc, struct msgb *msg)
-{
-	const char *is = osmo_hexdump_nospc(msg->data, msg->len);
-	fprintf(stderr, "GSUP --> HLR: %s: %s\n",
-		osmo_gsup_message_type_name(msg->data[0]), is);
-
-	OSMO_ASSERT(gsup_tx_expected);
-	if (strcmp(gsup_tx_expected, is)) {
-		fprintf(stderr, "Mismatch! Expected:\n%s\n", gsup_tx_expected);
-		abort();
-	}
-
-	talloc_free(msg);
-	gsup_tx_confirmed = true;
-	gsup_tx_expected = NULL;
-	return 0;
-}
-
-int _validate_dtap(struct msgb *msg, enum ran_type to_ran)
-{
-	btw("DTAP --%s--> MS: %s: %s",
-	    ran_type_name(to_ran), msg_type_name(msg),
-	    osmo_hexdump_nospc(msg->data, msg->len));
-
-	OSMO_ASSERT(dtap_tx_expected);
-	if (msg->len != dtap_tx_expected->len
-	    || memcmp(msg->data, dtap_tx_expected->data, msg->len)) {
-		fprintf(stderr, "Mismatch! Expected:\n%s\n",
-		       osmo_hexdump_nospc(dtap_tx_expected->data,
-					  dtap_tx_expected->len));
-		abort();
-	}
-
-	btw("DTAP matches expected message");
-
-	talloc_free(msg);
-	dtap_tx_confirmed = true;
-	talloc_free(dtap_tx_expected);
-	dtap_tx_expected = NULL;
-	return 0;
-}
-
-/* override, requires '-Wl,--wrap=ranap_iu_tx' */
-int __real_ranap_iu_tx(struct msgb *msg, uint8_t sapi);
-int __wrap_ranap_iu_tx(struct msgb *msg, uint8_t sapi)
-{
-	return _validate_dtap(msg, RAN_UTRAN_IU);
-}
-
-/* override, requires '-Wl,--wrap=ranap_iu_tx_release' */
-int __real_ranap_iu_tx_release(struct ranap_ue_conn_ctx *ctx, const struct RANAP_Cause *cause);
-int __wrap_ranap_iu_tx_release(struct ranap_ue_conn_ctx *ctx, const struct RANAP_Cause *cause)
-{
-	btw("Iu Release --%s--> MS", ran_type_name(RAN_UTRAN_IU));
-	OSMO_ASSERT(iu_release_expected);
-	iu_release_expected = false;
-	iu_release_sent = true;
-	return 0;
-}
-
-/* override, requires '-Wl,--wrap=iu_tx_common_id' */
-int __real_ranap_iu_tx_common_id(struct ranap_ue_conn_ctx *ue_ctx, const char *imsi);
-int __wrap_ranap_iu_tx_common_id(struct ranap_ue_conn_ctx *ue_ctx, const char *imsi)
-{
-	btw("Iu Common ID --%s--> MS (IMSI=%s)", ran_type_name(RAN_UTRAN_IU), imsi);
-	return 0;
-}
-
-/* override, requires '-Wl,--wrap=a_iface_tx_dtap' */
-int __real_a_iface_tx_dtap(struct msgb *msg);
-int __wrap_a_iface_tx_dtap(struct msgb *msg)
-{
-	return _validate_dtap(msg, RAN_GERAN_A);
-}
-
-/* override, requires '-Wl,--wrap=a_iface_tx_clear_cmd' */
-int __real_a_iface_tx_clear_cmd(struct gsm_subscriber_connection *conn);
-int __wrap_a_iface_tx_clear_cmd(struct gsm_subscriber_connection *conn)
-{
-	btw("BSSAP Clear --%s--> MS", ran_type_name(RAN_GERAN_A));
-	OSMO_ASSERT(bssap_clear_expected);
-	bssap_clear_expected = false;
-	bssap_clear_sent = true;
-	return 0;
-}
-
-static int fake_vlr_tx_lu_acc(void *msc_conn_ref, uint32_t send_tmsi)
-{
-	struct gsm_subscriber_connection *conn = msc_conn_ref;
-	if (send_tmsi == GSM_RESERVED_TMSI)
-		btw("sending LU Accept for %s", vlr_subscr_name(conn->vsub));
-	else
-		btw("sending LU Accept for %s, with TMSI 0x%08x",
-		    vlr_subscr_name(conn->vsub), send_tmsi);
-	lu_result_sent |= RES_ACCEPT;
-	return 0;
-}
-
-static int fake_vlr_tx_lu_rej(void *msc_conn_ref, uint8_t cause)
-{
-	struct gsm_subscriber_connection *conn = msc_conn_ref;
-	btw("sending LU Reject for %s, cause %u", vlr_subscr_name(conn->vsub), cause);
-	lu_result_sent |= RES_REJECT;
-	return 0;
-}
-
-static int fake_vlr_tx_cm_serv_acc(void *msc_conn_ref)
-{
-	struct gsm_subscriber_connection *conn = msc_conn_ref;
-	btw("sending CM Service Accept for %s", vlr_subscr_name(conn->vsub));
-	cm_service_result_sent |= RES_ACCEPT;
-	return 0;
-}
-
-static int fake_vlr_tx_cm_serv_rej(void *msc_conn_ref,
-				   enum vlr_proc_arq_result result)
-{
-	struct gsm_subscriber_connection *conn = msc_conn_ref;
-	btw("sending CM Service Reject for %s, result %s",
-	    vlr_subscr_name(conn->vsub),
-	    vlr_proc_arq_result_name(result));
-	cm_service_result_sent |= RES_REJECT;
-	return 0;
-}
-
-static int fake_vlr_tx_auth_req(void *msc_conn_ref, struct gsm_auth_tuple *at,
-				bool send_autn)
-{
-	struct gsm_subscriber_connection *conn = msc_conn_ref;
-	char *hex;
-	bool ok = true;
-	btw("sending %s Auth Request for %s: tuple use_count=%d key_seq=%d auth_types=0x%x and...",
-	    send_autn? "UMTS" : "GSM", vlr_subscr_name(conn->vsub),
-	    at->use_count, at->key_seq, at->vec.auth_types);
-
-	hex = osmo_hexdump_nospc((void*)&at->vec.rand, sizeof(at->vec.rand));
-	btw("...rand=%s", hex);
-	if (!auth_request_expect_rand
-	    || strcmp(hex, auth_request_expect_rand) != 0) {
-		ok = false;
-		log("FAILURE: expected rand=%s",
-		    auth_request_expect_rand ? auth_request_expect_rand : "-");
-	}
-
-	if (send_autn) {
-		hex = osmo_hexdump_nospc((void*)&at->vec.autn, sizeof(at->vec.autn));
-		btw("...autn=%s", hex);
-		if (!auth_request_expect_autn
-		    || strcmp(hex, auth_request_expect_autn) != 0) {
-			ok = false;
-			log("FAILURE: expected autn=%s",
-			    auth_request_expect_autn ? auth_request_expect_autn : "-");
-		}
-	} else if (auth_request_expect_autn) {
-		ok = false;
-		log("FAILURE: no AUTN sent, expected AUTN = %s",
-		    auth_request_expect_autn);
-	}
-
-	if (send_autn)
-		btw("...expecting res=%s",
-		    osmo_hexdump_nospc((void*)&at->vec.res, at->vec.res_len));
-	else
-		btw("...expecting sres=%s",
-		    osmo_hexdump_nospc((void*)&at->vec.sres, sizeof(at->vec.sres)));
-
-	auth_request_sent = ok;
-	return 0;
-}
-
-static int fake_vlr_tx_auth_rej(void *msc_conn_ref)
-{
-	struct gsm_subscriber_connection *conn = msc_conn_ref;
-	btw("sending Auth Reject for %s", vlr_subscr_name(conn->vsub));
-	return 0;
-}
-
-static int fake_vlr_tx_ciph_mode_cmd(void *msc_conn_ref, enum vlr_ciph ciph,
-				     bool retrieve_imeisv)
-{
-	/* FIXME: we actually would like to see the message bytes checked here,
-	 * not possible while msc_vlr_set_ciph_mode() calls
-	 * gsm0808_cipher_mode() directly. When the MSCSPLIT is ready, check
-	 * the tx bytes in the sense of dtap_expect_tx() above. */
-	struct gsm_subscriber_connection *conn = msc_conn_ref;
-	switch (conn->via_ran) {
-	case RAN_GERAN_A:
-		btw("sending Ciphering Mode Command for %s: cipher=%s kc=%s"
-		    " retrieve_imeisv=%d",
-		    vlr_subscr_name(conn->vsub),
-		    vlr_ciph_name(conn->network->a5_encryption),
-		    osmo_hexdump_nospc(conn->vsub->last_tuple->vec.kc, 8),
-		    retrieve_imeisv);
-		break;
-	case RAN_UTRAN_IU:
-		btw("sending SecurityModeControl for %s",
-		    vlr_subscr_name(conn->vsub));
-		break;
-	default:
-		btw("UNKNOWN RAN TYPE %d", conn->via_ran);
-		OSMO_ASSERT(false);
-		return -1;
-	}
-	cipher_mode_cmd_sent = true;
-	cipher_mode_cmd_sent_with_imeisv = retrieve_imeisv;
-	return 0;
-}
-
-void ms_sends_security_mode_complete()
-{
-	OSMO_ASSERT(g_conn);
-	OSMO_ASSERT(g_conn->via_ran == RAN_UTRAN_IU);
-	OSMO_ASSERT(g_conn->iu.ue_ctx);
-	msc_rx_sec_mode_compl(g_conn);
-}
-
-const struct timeval fake_time_start_time = { 123, 456 };
-
-void fake_time_start()
-{
-	osmo_gettimeofday_override_time = fake_time_start_time;
-	osmo_gettimeofday_override = true;
-	fake_time_passes(0, 0);
-}
-
-void check_talloc(void *msgb_ctx, void *tall_bsc_ctx, int expected_blocks)
-{
-	talloc_report_full(msgb_ctx, stderr);
-	fprintf(stderr, "talloc_total_blocks(tall_bsc_ctx) == %zu\n",
-		talloc_total_blocks(tall_bsc_ctx));
-	if (talloc_total_blocks(tall_bsc_ctx) != expected_blocks)
-		talloc_report_full(tall_bsc_ctx, stderr);
-	fprintf(stderr, "\n");
-}
-
-static struct {
-	bool verbose;
-	int run_test_nr;
-} cmdline_opts = {
-	.verbose = false,
-	.run_test_nr = -1,
-};
-
-static void print_help(const char *program)
-{
-	printf("Usage:\n"
-	       "  %s [-v] [N [N...]]\n"
-	       "Options:\n"
-	       "  -h --help      show this text.\n"
-	       "  -v --verbose   print source file and line numbers\n"
-	       "  N              run only the Nth test (first test is N=1)\n",
-	       program
-	       );
-}
-
-static void handle_options(int argc, char **argv)
-{
-	while (1) {
-		int option_index = 0, c;
-		static struct option long_options[] = {
-			{"help", 0, 0, 'h'},
-			{"verbose", 1, 0, 'v'},
-			{0, 0, 0, 0}
-		};
-
-		c = getopt_long(argc, argv, "hv",
-				long_options, &option_index);
-		if (c == -1)
-			break;
-
-		switch (c) {
-		case 'h':
-			print_help(argv[0]);
-			exit(0);
-		case 'v':
-			cmdline_opts.verbose = true;
-			break;
-		default:
-			/* catch unknown options *as well as* missing arguments. */
-			fprintf(stderr, "Error in command line options. Exiting.\n");
-			exit(-1);
-			break;
-		}
-	}
-}
-
-void *msgb_ctx = NULL;
-
-void run_tests(int nr)
-{
-	int test_nr;
-	nr --; /* arg's first test is 1, in here it's 0 */
-	for (test_nr = 0; msc_vlr_tests[test_nr]; test_nr ++) {
-		if (nr >= 0 && test_nr != nr)
-			continue;
-
-		if (cmdline_opts.verbose)
-			fprintf(stderr, "(test nr %d)\n", test_nr + 1);
-
-		msc_vlr_tests[test_nr]();
-
-		if (cmdline_opts.verbose)
-			fprintf(stderr, "(test nr %d)\n", test_nr + 1);
-
-		check_talloc(msgb_ctx, tall_bsc_ctx, 9);
-	} while(0);
-}
-
-int main(int argc, char **argv)
-{
-	handle_options(argc, argv);
-
-	tall_bsc_ctx = talloc_named_const(NULL, 0, "subscr_conn_test_ctx");
-	msgb_ctx = msgb_talloc_ctx_init(tall_bsc_ctx, 0);
-	osmo_init_logging(&info);
-
-	_log_lines = cmdline_opts.verbose;
-
-	OSMO_ASSERT(osmo_stderr_target);
-	log_set_use_color(osmo_stderr_target, 0);
-	log_set_print_timestamp(osmo_stderr_target, 0);
-	log_set_print_filename(osmo_stderr_target, _log_lines? 1 : 0);
-	log_set_print_category(osmo_stderr_target, 1);
-
-	net = gsm_network_init(tall_bsc_ctx, 1, 1, fake_mncc_recv);
-	net->gsup_server_addr_str = talloc_strdup(net, "no_gsup_server");
-	net->gsup_server_port = 0;
-
-	osmo_fsm_log_addr(false);
-	OSMO_ASSERT(msc_vlr_alloc(net) == 0);
-	OSMO_ASSERT(msc_vlr_start(net) == 0);
-	OSMO_ASSERT(net->vlr);
-	OSMO_ASSERT(net->vlr->gsup_client);
-	msc_subscr_conn_init();
-
-	net->vlr->ops.tx_lu_acc = fake_vlr_tx_lu_acc;
-	net->vlr->ops.tx_lu_rej = fake_vlr_tx_lu_rej;
-	net->vlr->ops.tx_cm_serv_acc = fake_vlr_tx_cm_serv_acc;
-	net->vlr->ops.tx_cm_serv_rej = fake_vlr_tx_cm_serv_rej;
-	net->vlr->ops.tx_auth_req = fake_vlr_tx_auth_req;
-	net->vlr->ops.tx_auth_rej = fake_vlr_tx_auth_rej;
-	net->vlr->ops.set_ciph_mode = fake_vlr_tx_ciph_mode_cmd;
-
-	clear_vlr();
-
-	if (optind >= argc)
-		run_tests(-1);
-	else {
-		int arg;
-		long int nr;
-		for (arg = optind; arg < argc; arg++) {
-			nr = strtol(argv[arg], NULL, 10);
-			if (errno) {
-				fprintf(stderr, "Invalid argument: %s\n",
-					argv[arg]);
-				exit(1);
-			}
-
-			run_tests(nr);
-		}
-	}
-
-	printf("Done\n");
-
-	talloc_free(the_bts);
-
-	check_talloc(msgb_ctx, tall_bsc_ctx, 9);
-	return 0;
-}
diff --git a/tests/msc_vlr/msc_vlr_tests.h b/tests/msc_vlr/msc_vlr_tests.h
deleted file mode 100644
index c2c5a58..0000000
--- a/tests/msc_vlr/msc_vlr_tests.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* Osmocom MSC+VLR end-to-end tests */
-
-/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
- *
- * All Rights Reserved
- *
- * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
- *
- * 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 <stdbool.h>
-#include <stdio.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/osmo_msc.h>
-#include <openbsc/vlr.h>
-
-extern bool _log_lines;
-#define _log(fmt, args...) do { \
-		if (_log_lines) \
-			fprintf(stderr, " %4d:%s: " fmt "\n", \
-				__LINE__, __FILE__, ## args ); \
-		else \
-			fprintf(stderr, fmt "\n", ## args ); \
-	} while (false)
-
-/* btw means "by the way", the test tells the log what's happening.
- * BTW() marks a larger section, btw() is the usual logging. */
-#define BTW(fmt, args...) _log("---\n- " fmt, ## args )
-#define btw(fmt, args...) _log("- " fmt, ## args )
-#define log(fmt, args...) _log("  " fmt, ## args )
-
-#define comment_start() fprintf(stderr, "===== %s\n", __func__);
-#define comment_end() fprintf(stderr, "===== %s: SUCCESS\n\n", __func__);
-
-extern struct gsm_subscriber_connection *g_conn;
-extern struct gsm_network *net;
-extern struct gsm_bts *the_bts;
-extern void *msgb_ctx;
-
-extern enum ran_type rx_from_ran;
-
-extern const char *gsup_tx_expected;
-extern bool gsup_tx_confirmed;
-
-extern struct msgb *dtap_tx_expected;
-extern bool dtap_tx_confirmed;
-
-enum result_sent {
-	RES_NONE = 0,
-	RES_ACCEPT = 1,
-	RES_REJECT = 2,
-};
-extern enum result_sent lu_result_sent;
-extern enum result_sent cm_service_result_sent;
-
-extern bool auth_request_sent;
-extern const char *auth_request_expect_rand;
-extern const char *auth_request_expect_autn;
-
-extern bool cipher_mode_cmd_sent;
-extern bool cipher_mode_cmd_sent_with_imeisv;
-
-extern bool paging_sent;
-extern bool paging_stopped;
-
-extern bool iu_release_expected;
-extern bool iu_release_sent;
-extern bool bssap_clear_expected;
-extern bool bssap_clear_sent;
-
-static inline void expect_iu_release()
-{
-	iu_release_expected = true;
-	iu_release_sent = false;
-}
-
-static inline void expect_bssap_clear()
-{
-	bssap_clear_expected = true;
-	bssap_clear_sent = false;
-}
-
-static inline void expect_release_clear(enum ran_type via_ran)
-{
-	switch (via_ran) {
-	case RAN_GERAN_A:
-		expect_bssap_clear();
-		return;
-	case RAN_UTRAN_IU:
-		expect_iu_release();
-		return;
-	default:
-		OSMO_ASSERT(false);
-		break;
-	}
-}
-
-struct msc_vlr_test_cmdline_opts {
-	bool verbose;
-	int run_test_nr;
-};
-
-typedef void (* msc_vlr_test_func_t )(void);
-extern msc_vlr_test_func_t msc_vlr_tests[];
-
-struct msgb *msgb_from_hex(const char *label, uint16_t size, const char *hex);
-
-void clear_vlr();
-bool conn_exists(struct gsm_subscriber_connection *conn);
-
-void dtap_expect_tx(const char *hex);
-void dtap_expect_tx_ussd(char *ussd_text);
-void paging_expect_imsi(const char *imsi);
-void paging_expect_tmsi(uint32_t tmsi);
-
-void ms_sends_msg(const char *hex);
-void ms_sends_security_mode_complete();
-void gsup_rx(const char *rx_hex, const char *expect_tx_hex);
-void send_sms(struct vlr_subscr *receiver,
-	      struct vlr_subscr *sender,
-	      char *str);
-
-void thwart_rx_non_initial_requests();
-
-void check_talloc(void *msgb_ctx, void *tall_bsc_ctx, int expected_blocks);
-
-#define EXPECT_ACCEPTED(expect_accepted) do { \
-		if (g_conn) \
-			OSMO_ASSERT(conn_exists(g_conn)); \
-		bool accepted = msc_subscr_conn_is_accepted(g_conn); \
-		fprintf(stderr, "msc_subscr_conn_is_accepted() == %s\n", \
-			accepted ? "true" : "false"); \
-		OSMO_ASSERT(accepted == expect_accepted); \
-	} while (false)
-
-#define VERBOSE_ASSERT(val, expect_op, fmt) \
-	do { \
-		log(#val " == " fmt, (val)); \
-		OSMO_ASSERT((val) expect_op); \
-	} while (0);
-
-#define EXPECT_CONN_COUNT(N) VERBOSE_ASSERT(llist_count(&net->subscr_conns), == N, "%d")
-
-#define gsup_expect_tx(hex) do \
-{ \
-	if (gsup_tx_expected) { \
-		log("Previous expected GSUP tx was not confirmed!"); \
-		OSMO_ASSERT(!gsup_tx_expected); \
-	} \
-	if (!hex) \
-		break; \
-	gsup_tx_expected = hex; \
-	gsup_tx_confirmed = false; \
-} while (0)
-
-void fake_time_start();
-
-/* as macro to get the test file's source line number */
-#define fake_time_passes(secs, usecs) do \
-{ \
-	struct timeval diff; \
-	osmo_gettimeofday_override_add(secs, usecs); \
-	timersub(&osmo_gettimeofday_override_time, &fake_time_start_time, &diff); \
-	btw("Total time passed: %d.%06d s", \
-	    (int)diff.tv_sec, (int)diff.tv_usec); \
-	osmo_timers_prepare(); \
-	osmo_timers_update(); \
-} while (0)
-
-extern const struct timeval fake_time_start_time;
diff --git a/tests/nanobts_omlattr/Makefile.am b/tests/nanobts_omlattr/Makefile.am
deleted file mode 100644
index b03d50c..0000000
--- a/tests/nanobts_omlattr/Makefile.am
+++ /dev/null
@@ -1,34 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	nanobts_omlattr_test \
-	$(NULL)
-
-EXTRA_DIST = \
-	nanobts_omlattr_test.ok \
-	$(NULL)
-
-nanobts_omlattr_test_SOURCES = \
-	nanobts_omlattr_test.c \
-	$(NULL)
-
-nanobts_omlattr_test_LDADD = \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libmsc/libmsc.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	-ldbi \
-	$(NULL)
diff --git a/tests/nanobts_omlattr/nanobts_omlattr_test.c b/tests/nanobts_omlattr/nanobts_omlattr_test.c
deleted file mode 100644
index ee138b8..0000000
--- a/tests/nanobts_omlattr/nanobts_omlattr_test.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/* Test OML attribute generator */
-
-/* (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/>.
- */
-
-#include <openbsc/gprs_llc_xid.h>
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/bts_ipaccess_nanobts_omlattr.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/application.h>
-
-#include <stdio.h>
-#include <string.h>
-
-struct gsm_bts_model bts_model_nanobts = {
-	.type = GSM_BTS_TYPE_NANOBTS,
-	.name = "nanobts",
-	.start = NULL,
-	.oml_rcvmsg = NULL,
-	.e1line_bind_ops = NULL,
-	.nm_att_tlvdef = {
-			  .def = {
-				  /* ip.access specifics */
-				  [NM_ATT_IPACC_DST_IP] = {TLV_TYPE_FIXED, 4},
-				  [NM_ATT_IPACC_DST_IP_PORT] =
-				  {TLV_TYPE_FIXED, 2},
-				  [NM_ATT_IPACC_STREAM_ID] = {TLV_TYPE_TV,},
-				  [NM_ATT_IPACC_SEC_OML_CFG] =
-				  {TLV_TYPE_FIXED, 6},
-				  [NM_ATT_IPACC_IP_IF_CFG] =
-				  {TLV_TYPE_FIXED, 8},
-				  [NM_ATT_IPACC_IP_GW_CFG] =
-				  {TLV_TYPE_FIXED, 12},
-				  [NM_ATT_IPACC_IN_SERV_TIME] =
-				  {TLV_TYPE_FIXED, 4},
-				  [NM_ATT_IPACC_LOCATION] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_PAGING_CFG] =
-				  {TLV_TYPE_FIXED, 2},
-				  [NM_ATT_IPACC_UNIT_ID] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_UNIT_NAME] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_SNMP_CFG] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_PRIM_OML_CFG_LIST] =
-				  {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_NV_FLAGS] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_FREQ_CTRL] =
-				  {TLV_TYPE_FIXED, 2},
-				  [NM_ATT_IPACC_PRIM_OML_FB_TOUT] =
-				  {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_CUR_SW_CFG] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_TIMING_BUS] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_CGI] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_RAC] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_OBJ_VERSION] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_GPRS_PAGING_CFG] =
-				  {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_NSEI] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_BVCI] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_NSVCI] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_NS_CFG] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_BSSGP_CFG] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_NS_LINK_CFG] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_RLC_CFG] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_ALM_THRESH_LIST] =
-				  {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_MONIT_VAL_LIST] =
-				  {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_TIB_CONTROL] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_SUPP_FEATURES] =
-				  {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_CODING_SCHEMES] =
-				  {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_RLC_CFG_2] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_HEARTB_TOUT] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_UPTIME] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_RLC_CFG_3] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_SSL_CFG] = {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_SEC_POSSIBLE] =
-				  {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_IML_SSL_STATE] =
-				  {TLV_TYPE_TL16V},
-				  [NM_ATT_IPACC_REVOC_DATE] = {TLV_TYPE_TL16V},
-				  },
-			  },
-};
-
-static void test_nanobts_attr_bts_get(struct gsm_bts *bts, uint8_t *expected)
-{
-	struct msgb *msgb;
-
-	printf("Testing nanobts_attr_bts_get()...\n");
-
-	msgb = nanobts_attr_bts_get(bts);
-	printf("result=  %s\n", osmo_hexdump_nospc(msgb->data, msgb->len));
-	printf("expected=%s\n", osmo_hexdump_nospc(expected, msgb->len));
-	OSMO_ASSERT(memcmp(msgb->data, expected, msgb->len) == 0);
-	msgb_free(msgb);
-
-	printf("ok.\n");
-	printf("\n");
-}
-
-static void test_nanobts_attr_nse_get(struct gsm_bts *bts, uint8_t *expected)
-{
-	struct msgb *msgb;
-
-	printf("Testing nanobts_attr_nse_get()...\n");
-
-	msgb = nanobts_attr_nse_get(bts);
-	printf("result=  %s\n", osmo_hexdump_nospc(msgb->data, msgb->len));
-	printf("expected=%s\n", osmo_hexdump_nospc(expected, msgb->len));
-	OSMO_ASSERT(memcmp(msgb->data, expected, msgb->len) == 0);
-	msgb_free(msgb);
-
-	printf("ok.\n");
-	printf("\n");
-}
-
-static void test_nanobts_attr_cell_get(struct gsm_bts *bts, uint8_t *expected)
-{
-	struct msgb *msgb;
-
-	printf("Testing nanobts_attr_cell_get()...\n");
-
-	msgb = nanobts_attr_cell_get(bts);
-	printf("result=  %s\n", osmo_hexdump_nospc(msgb->data, msgb->len));
-	printf("expected=%s\n", osmo_hexdump_nospc(expected, msgb->len));
-	OSMO_ASSERT(memcmp(msgb->data, expected, msgb->len) == 0);
-	msgb_free(msgb);
-
-	printf("ok.\n");
-	printf("\n");
-}
-
-static void test_nanobts_attr_nscv_get(struct gsm_bts *bts, uint8_t *expected)
-{
-	struct msgb *msgb;
-
-	printf("Testing nanobts_attr_nscv_get()...\n");
-
-	msgb = nanobts_attr_nscv_get(bts);
-	printf("result=  %s\n", osmo_hexdump_nospc(msgb->data, msgb->len));
-	printf("expected=%s\n", osmo_hexdump_nospc(expected, msgb->len));
-	OSMO_ASSERT(memcmp(msgb->data, expected, msgb->len) == 0);
-	msgb_free(msgb);
-
-	printf("ok.\n");
-	printf("\n");
-}
-
-static void test_nanobts_attr_radio_get(struct gsm_bts *bts,
-					struct gsm_bts_trx *trx,
-					uint8_t *expected)
-{
-	struct msgb *msgb;
-
-	printf("Testing nanobts_attr_nscv_get()...\n");
-
-	msgb = nanobts_attr_radio_get(bts, trx);
-	printf("result=  %s\n", osmo_hexdump_nospc(msgb->data, msgb->len));
-	printf("expected=%s\n", osmo_hexdump_nospc(expected, msgb->len));
-	OSMO_ASSERT(memcmp(msgb->data, expected, msgb->len) == 0);
-	msgb_free(msgb);
-
-	printf("ok.\n");
-	printf("\n");
-}
-
-int main(int argc, char **argv)
-{
-	void *ctx;
-
-	struct gsm_bts *bts;
-	struct gsm_network *net;
-	struct gsm_bts_trx *trx;
-
-	ctx = talloc_named_const(NULL, 0, "ctx");
-
-	/* Allocate environmental structs (bts, net, trx) */
-	net = talloc_zero(ctx, struct gsm_network);
-	INIT_LLIST_HEAD(&net->bts_list);
-	gsm_bts_model_register(&bts_model_nanobts);
-	bts = gsm_bts_alloc_register(net, GSM_BTS_TYPE_NANOBTS, 63);
-	OSMO_ASSERT(bts);
-	trx = talloc_zero(ctx, struct gsm_bts_trx);
-
-	/* Parameters needed by nanobts_attr_bts_get() */
-	bts->rach_b_thresh = -1;
-	bts->rach_ldavg_slots = -1;
-	bts->c0->arfcn = 866;
-	bts->cell_identity = 1337;
-	bts->network->country_code = 1;
-	bts->network->network_code = 1;
-	bts->location_area_code = 1;
-	bts->gprs.rac = 0;
-	uint8_t attr_bts_expected[] =
-	    { 0x19, 0x55, 0x5b, 0x61, 0x67, 0x6d, 0x73, 0x18, 0x06, 0x0e, 0x00,
-		0x02, 0x01, 0x20, 0x33, 0x1e, 0x24, 0x24, 0xa8, 0x34, 0x21,
-		0xa8, 0x1f, 0x3f, 0x25,
-		0x00, 0x01, 0x0a, 0x0c, 0x0a, 0x0b, 0x01, 0x2a, 0x0a, 0x2b,
-		0x03, 0xe8, 0x0a, 0x80,
-		0x23, 0x0a, 0x08, 0x03, 0x62, 0x09, 0x3f, 0x99, 0x00, 0x07,
-		0x00, 0xf1, 0x10, 0x00,
-		0x01, 0x05, 0x39
-	};
-
-	/* Parameters needed to test nanobts_attr_nse_get() */
-	bts->gprs.nse.nsei = 101;
-	uint8_t attr_nse_expected[] =
-	    { 0x9d, 0x00, 0x02, 0x00, 0x65, 0xa0, 0x00, 0x07, 0x03, 0x03, 0x03,
-		0x03, 0x1e, 0x03, 0x0a, 0xa1, 0x00, 0x0b, 0x03, 0x03, 0x03,
-		0x03, 0x03, 0x0a, 0x03,
-		0x0a, 0x03, 0x0a, 0x03
-	};
-
-	/* Parameters needed to test nanobts_attr_cell_get() */
-	bts->gprs.rac = 0x00;
-	bts->gprs.cell.bvci = 2;
-	bts->gprs.mode = BTS_GPRS_GPRS;
-	uint8_t attr_cell_expected[] =
-	    { 0x9a, 0x00, 0x01, 0x00, 0x9c, 0x00, 0x02, 0x05, 0x03, 0x9e, 0x00,
-		0x02, 0x00, 0x02, 0xa3, 0x00, 0x09, 0x14, 0x05, 0x05, 0xa0,
-		0x05, 0x0a, 0x04, 0x08,
-		0x0f, 0xa8, 0x00, 0x02, 0x0f, 0x00, 0xa9, 0x00, 0x05, 0x00,
-		0xfa, 0x00, 0xfa, 0x02
-	};
-
-	/* Parameters needed to test nanobts_attr_nscv_get() */
-	bts->gprs.nsvc[0].nsvci = 0x65;
-	bts->gprs.nsvc[0].remote_port = 0x59d8;
-	bts->gprs.nsvc[0].remote_ip = 0x0a090165;
-	bts->gprs.nsvc[0].local_port = 0x5a3c;
-	uint8_t attr_nscv_expected[] =
-	    { 0x9f, 0x00, 0x02, 0x00, 0x65, 0xa2, 0x00, 0x08, 0x59, 0xd8, 0x0a,
-		0x09, 0x01, 0x65, 0x5a, 0x3c
-	};
-
-	/* Parameters needed to test nanobts_attr_radio_get() */
-	trx->arfcn = 866;
-	trx->max_power_red = 22;
-	bts->c0->max_power_red = 22;
-	uint8_t attr_radio_expected[] =
-	    { 0x2d, 0x0b, 0x05, 0x00, 0x02, 0x03, 0x62 };
-
-	/* Run tests */
-	test_nanobts_attr_bts_get(bts, attr_bts_expected);
-	test_nanobts_attr_nse_get(bts, attr_nse_expected);
-	test_nanobts_attr_cell_get(bts, attr_cell_expected);
-	test_nanobts_attr_nscv_get(bts, attr_nscv_expected);
-	test_nanobts_attr_radio_get(bts, trx, attr_radio_expected);
-
-	printf("Done\n");
-	talloc_free(bts);
-	talloc_free(net);
-	talloc_free(trx);
-	talloc_report_full(ctx, stderr);
-	OSMO_ASSERT(talloc_total_blocks(ctx) == 1);
-	return 0;
-}
-
-/* stubs */
-struct osmo_prim_hdr;
-int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
-{
-	abort();
-}
diff --git a/tests/nanobts_omlattr/nanobts_omlattr_test.ok b/tests/nanobts_omlattr/nanobts_omlattr_test.ok
deleted file mode 100644
index 91b655f..0000000
--- a/tests/nanobts_omlattr/nanobts_omlattr_test.ok
+++ /dev/null
@@ -1,26 +0,0 @@
-Testing nanobts_attr_bts_get()...
-result=  19555b61676d7318060e00020120331e2424a83421a81f3f2500010a0c0a0b012a0a2b03e80a80230a080362093f99000700f11000010539
-expected=19555b61676d7318060e00020120331e2424a83421a81f3f2500010a0c0a0b012a0a2b03e80a80230a080362093f99000700f11000010539
-ok.
-
-Testing nanobts_attr_nse_get()...
-result=  9d00020065a00007030303031e030aa1000b03030303030a030a030a03
-expected=9d00020065a00007030303031e030aa1000b03030303030a030a030a03
-ok.
-
-Testing nanobts_attr_cell_get()...
-result=  9a0001009c000205039e00020002a30009140505a0050a04080fa800020f00a9000500fa00fa02
-expected=9a0001009c000205039e00020002a30009140505a0050a04080fa800020f00a9000500fa00fa02
-ok.
-
-Testing nanobts_attr_nscv_get()...
-result=  9f00020065a2000859d80a0901655a3c
-expected=9f00020065a2000859d80a0901655a3c
-ok.
-
-Testing nanobts_attr_nscv_get()...
-result=  2d0b0500020362
-expected=2d0b0500020362
-ok.
-
-Done
diff --git a/tests/oap/Makefile.am b/tests/oap/Makefile.am
deleted file mode 100644
index 1bb672d..0000000
--- a/tests/oap/Makefile.am
+++ /dev/null
@@ -1,36 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	-ggdb3 \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(NULL)
-
-EXTRA_DIST = \
-	oap_client_test.ok \
-	oap_client_test.err \
-	$(NULL)
-
-if HAVE_LIBGTP
-if HAVE_LIBCARES
-noinst_PROGRAMS = \
-	oap_client_test \
-	$(NULL)
-endif
-endif
-
-oap_client_test_SOURCES = \
-	oap_client_test.c \
-	$(NULL)
-
-oap_client_test_LDADD = \
-	$(top_builddir)/src/gprs/gprs_utils.o \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	-lrt
-
diff --git a/tests/oap/oap_client_test.c b/tests/oap/oap_client_test.c
deleted file mode 100644
index e6501cb..0000000
--- a/tests/oap/oap_client_test.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/* Test Osmocom Authentication Protocol */
-/*
- * (C) 2015 by 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 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/>.
- *
- */
-
-#include <osmocom/core/application.h>
-#include <osmocom/gsm/oap.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/oap_client.h>
-
-#include <stdio.h>
-#include <string.h>
-
-static void test_oap_api(void)
-{
-	printf("Testing OAP API\n");
-
-	struct oap_client_config _config;
-	struct oap_client_config *config = &_config;
-
-	struct oap_client_state _state;
-	struct oap_client_state *state = &_state;
-
-	struct osmo_oap_message oap_rx;
-	struct msgb *msg_rx;
-
-	struct osmo_oap_message oap_tx;
-	struct msgb *msg_tx;
-
-	memset(config, 0, sizeof(*config));
-	memset(state, 0, sizeof(*state));
-
-	OSMO_ASSERT(osmo_hexparse("0102030405060708090a0b0c0d0e0f10", config->secret_k, 16) == 16);
-	OSMO_ASSERT(osmo_hexparse("1112131415161718191a1b1c1d1e1f20", config->secret_opc, 16) == 16);
-
-	fprintf(stderr, "- make sure filling with zeros means uninitialized\n");
-	OSMO_ASSERT(state->state == OAP_UNINITIALIZED);
-
-	fprintf(stderr, "- reject messages in uninitialized state\n");
-	memset(&oap_rx, 0, sizeof(oap_rx));
-	state->client_id = 1;
-	oap_rx.message_type = OAP_MSGT_REGISTER_ERROR;
-	msg_rx = oap_client_encoded(&oap_rx);
-	OSMO_ASSERT(oap_client_handle(state, msg_rx, &msg_tx) < 0);
-	OSMO_ASSERT(state->state == OAP_UNINITIALIZED);
-	msgb_free(msg_rx);
-	OSMO_ASSERT(!msg_tx);
-
-	fprintf(stderr, "- NULL config should disable\n");
-	OSMO_ASSERT( oap_client_init(NULL, state) == 0 );
-	OSMO_ASSERT(state->state == OAP_DISABLED);
-
-	fprintf(stderr, "- reject messages in disabled state\n");
-	memset(state, 0, sizeof(*state));
-	memset(&oap_rx, 0, sizeof(oap_rx));
-	state->state = OAP_DISABLED;
-	state->client_id = 1;
-	oap_rx.message_type = OAP_MSGT_REGISTER_ERROR;
-	msg_rx = oap_client_encoded(&oap_rx);
-	OSMO_ASSERT(oap_client_handle(state, msg_rx, &msg_tx) < 0);
-	OSMO_ASSERT(state->state == OAP_DISABLED);
-	msgb_free(msg_rx);
-	OSMO_ASSERT(!msg_tx);
-
-	fprintf(stderr, "- invalid client_id and shared secret\n");
-	memset(state, 0, sizeof(*state));
-	config->client_id = 0;
-	config->secret_k_present = 0;
-	config->secret_opc_present = 0;
-	OSMO_ASSERT( oap_client_init(config, state) == 0 );
-	OSMO_ASSERT(state->state == OAP_DISABLED);
-
-	fprintf(stderr, "- reset state\n");
-	memset(state, 0, sizeof(*state));
-
-	fprintf(stderr, "- only client_id is invalid\n");
-	config->client_id = 0;
-	config->secret_k_present = 1;
-	config->secret_opc_present = 1;
-	OSMO_ASSERT( oap_client_init(config, state) == 0 );
-	OSMO_ASSERT(state->state == OAP_DISABLED);
-
-	memset(state, 0, sizeof(*state));
-
-	fprintf(stderr, "- valid id, but omitted shared_secret (1/2)\n");
-	config->client_id = 12345;
-	config->secret_k_present = 0;
-	config->secret_opc_present = 1;
-	OSMO_ASSERT( oap_client_init(config, state) == 0 );
-	OSMO_ASSERT(state->state == OAP_DISABLED);
-
-	memset(state, 0, sizeof(*state));
-
-	fprintf(stderr, "- valid id, but omitted shared_secret (2/2)\n");
-	config->client_id = 12345;
-	config->secret_k_present = 1;
-	config->secret_opc_present = 0;
-	OSMO_ASSERT( oap_client_init(config, state) == 0 );
-	OSMO_ASSERT(state->state == OAP_DISABLED);
-
-	memset(state, 0, sizeof(*state));
-
-
-	fprintf(stderr, "- mint configuration\n");
-	config->client_id = 12345;
-	config->secret_k_present = 1;
-	config->secret_opc_present = 1;
-	/*config->secret_* buffers are still set from the top */
-	OSMO_ASSERT( oap_client_init(config, state) == 0 );
-	OSMO_ASSERT(state->state == OAP_INITIALIZED);
-
-
-	fprintf(stderr, "- Missing challenge data\n");
-	memset(&oap_rx, 0, sizeof(oap_rx));
-	oap_rx.message_type = OAP_MSGT_CHALLENGE_REQUEST;
-	oap_rx.rand_present = 0;
-	oap_rx.autn_present = 0;
-	msg_rx = oap_client_encoded(&oap_rx);
-	OSMO_ASSERT(oap_client_handle(state, msg_rx, &msg_tx) == -2);
-	msgb_free(msg_rx);
-	OSMO_ASSERT(!msg_tx);
-
-	fprintf(stderr, "- AUTN missing\n");
-	osmo_hexparse("0102030405060708090a0b0c0d0e0f10",
-		      oap_rx.rand, 16);
-	oap_rx.rand_present = 1;
-	msg_rx = oap_client_encoded(&oap_rx);
-	OSMO_ASSERT(oap_client_handle(state, msg_rx, &msg_tx) == -2);
-	msgb_free(msg_rx);
-	OSMO_ASSERT(!msg_tx);
-
-	fprintf(stderr, "- RAND missing\n");
-	oap_rx.rand_present = 0;
-	osmo_hexparse("cec4e3848a33000086781158ca40f136",
-		      oap_rx.autn, 16);
-	oap_rx.autn_present = 1;
-	msg_rx = oap_client_encoded(&oap_rx);
-	OSMO_ASSERT(oap_client_handle(state, msg_rx, &msg_tx) == -2);
-	msgb_free(msg_rx);
-	OSMO_ASSERT(!msg_tx);
-
-	fprintf(stderr, "- wrong autn (by one bit)\n");
-	osmo_hexparse("0102030405060708090a0b0c0d0e0f10",
-		      oap_rx.rand, 16);
-	osmo_hexparse("dec4e3848a33000086781158ca40f136",
-		      oap_rx.autn, 16);
-	oap_rx.rand_present = 1;
-	oap_rx.autn_present = 1;
-	msg_rx = oap_client_encoded(&oap_rx);
-	OSMO_ASSERT(oap_client_handle(state, msg_rx, &msg_tx) == -2);
-	msgb_free(msg_rx);
-	OSMO_ASSERT(!msg_tx);
-
-	fprintf(stderr, "- all data correct\n");
-	osmo_hexparse("cec4e3848a33000086781158ca40f136",
-		      oap_rx.autn, 16);
-	msg_rx = oap_client_encoded(&oap_rx);
-
-	fprintf(stderr, "- but refuse to evaluate in uninitialized state\n");
-	OSMO_ASSERT(state->state == OAP_INITIALIZED);
-
-	state->state = OAP_UNINITIALIZED;
-	OSMO_ASSERT(oap_client_handle(state, msg_rx, &msg_tx) < 0);
-	OSMO_ASSERT(!msg_tx);
-
-	state->state = OAP_DISABLED;
-	OSMO_ASSERT(oap_client_handle(state, msg_rx, &msg_tx) < 0);
-	OSMO_ASSERT(!msg_tx);
-
-	state->state = OAP_INITIALIZED;
-
-	fprintf(stderr, "- now everything is correct\n");
-	/* a successful return value here indicates correct autn */
-	OSMO_ASSERT(oap_client_handle(state, msg_rx, &msg_tx) == 0);
-	msgb_free(msg_rx);
-
-	fprintf(stderr, "- Expect the challenge response in msg_tx\n");
-	OSMO_ASSERT(msg_tx);
-	OSMO_ASSERT(osmo_oap_decode(&oap_tx, msg_tx->data, msg_tx->len) == 0);
-	OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_CHALLENGE_RESULT);
-	OSMO_ASSERT(strcmp("e2d05b598c61d9ba",
-			   osmo_hexdump_nospc(oap_tx.xres, sizeof(oap_tx.xres)))
-		    == 0);
-	OSMO_ASSERT(state->state == OAP_SENT_CHALLENGE_RESULT);
-	msgb_free(msg_tx);
-	msg_tx = 0;
-
-	struct oap_client_state saved_state = _state;
-
-	fprintf(stderr, "- Receive registration error for the first time.\n");
-
-	memset(&oap_rx, 0, sizeof(oap_rx));
-	oap_rx.message_type = OAP_MSGT_REGISTER_ERROR;
-	oap_rx.cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
-	msg_rx = oap_client_encoded(&oap_rx);
-
-	OSMO_ASSERT(state->registration_failures == 0);
-	OSMO_ASSERT(oap_client_handle(state, msg_rx, &msg_tx) == 0);
-	OSMO_ASSERT(state->registration_failures == 1);
-	OSMO_ASSERT(msg_tx);
-	OSMO_ASSERT(osmo_oap_decode(&oap_tx, msg_tx->data, msg_tx->len) == 0);
-	OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_REGISTER_REQUEST);
-	OSMO_ASSERT(state->state == OAP_REQUESTED_CHALLENGE);
-	msgb_free(msg_tx);
-	msg_tx = 0;
-
-	fprintf(stderr, "- Receive registration error for the Nth time.\n");
-	state->registration_failures = 999;
-	OSMO_ASSERT(oap_client_handle(state, msg_rx, &msg_tx) == -11);
-	OSMO_ASSERT(!msg_tx);
-	OSMO_ASSERT(state->state == OAP_INITIALIZED);
-	msgb_free(msg_tx);
-	msg_tx = 0;
-
-	msgb_free(msg_rx);
-
-	fprintf(stderr, "- Registration success\n");
-
-	_state = saved_state;
-	memset(&oap_rx, 0, sizeof(oap_rx));
-	oap_rx.message_type = OAP_MSGT_REGISTER_RESULT;
-	msg_rx = oap_client_encoded(&oap_rx);
-	OSMO_ASSERT(oap_client_handle(state, msg_rx, &msg_tx) == 0);
-	OSMO_ASSERT(!msg_tx);
-	OSMO_ASSERT(state->state == OAP_REGISTERED);
-	msgb_free(msg_rx);
-}
-
-static struct log_info_cat oap_client_test_categories[] = {
-};
-
-static struct log_info info = {
-	.cat = oap_client_test_categories,
-	.num_cat = ARRAY_SIZE(oap_client_test_categories),
-};
-
-int main(int argc, char **argv)
-{
-	msgb_talloc_ctx_init(NULL, 0);
-	osmo_init_logging(&info);
-
-	OSMO_ASSERT(osmo_stderr_target);
-	log_set_use_color(osmo_stderr_target, 0);
-	log_set_print_timestamp(osmo_stderr_target, 0);
-	log_set_print_filename(osmo_stderr_target, 0);
-	log_set_print_category(osmo_stderr_target, 1);
-	log_parse_category_mask(osmo_stderr_target, "DLOAP,1");
-
-	test_oap_api();
-	printf("Done\n");
-
-	return 0;
-}
-
diff --git a/tests/oap/oap_client_test.err b/tests/oap/oap_client_test.err
deleted file mode 100644
index 62ddc9e..0000000
--- a/tests/oap/oap_client_test.err
+++ /dev/null
@@ -1,35 +0,0 @@
-- make sure filling with zeros means uninitialized
-- reject messages in uninitialized state
-DLOAP Received OAP message 5, but the OAP client is not initialized
-- NULL config should disable
-- reject messages in disabled state
-DLOAP Received OAP message 5, but the OAP client is disabled
-- invalid client_id and shared secret
-- reset state
-- only client_id is invalid
-- valid id, but omitted shared_secret (1/2)
-DLOAP OAP: client ID set, but secret K missing.
-- valid id, but omitted shared_secret (2/2)
-DLOAP OAP: client ID set, but secret OPC missing.
-- mint configuration
-- Missing challenge data
-DLOAP OAP challenge incomplete (rand_present: 0, autn_present: 0)
-- AUTN missing
-DLOAP OAP challenge incomplete (rand_present: 1, autn_present: 0)
-- RAND missing
-DLOAP OAP challenge incomplete (rand_present: 0, autn_present: 1)
-- wrong autn (by one bit)
-DLOAP OAP: AUTN mismatch!
-DLOAP OAP: AUTN from server: dec4e3848a33000086781158ca40f136
-DLOAP OAP: AUTN expected:    cec4e3848a33000086781158ca40f136
-- all data correct
-- but refuse to evaluate in uninitialized state
-DLOAP Received OAP message 8, but the OAP client is not initialized
-DLOAP Received OAP message 8, but the OAP client is disabled
-- now everything is correct
-- Expect the challenge response in msg_tx
-- Receive registration error for the first time.
-DLOAP OAP registration failed
-- Receive registration error for the Nth time.
-DLOAP OAP registration failed
-- Registration success
diff --git a/tests/oap/oap_client_test.ok b/tests/oap/oap_client_test.ok
deleted file mode 100644
index 59108a7..0000000
--- a/tests/oap/oap_client_test.ok
+++ /dev/null
@@ -1,2 +0,0 @@
-Testing OAP API
-Done
diff --git a/tests/sgsn/Makefile.am b/tests/sgsn/Makefile.am
deleted file mode 100644
index ccb8f44..0000000
--- a/tests/sgsn/Makefile.am
+++ /dev/null
@@ -1,81 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	-ggdb3 \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBCARES_CFLAGS) \
-	$(NULL)
-if BUILD_IU
-AM_CFLAGS += \
-	$(LIBASN1C_CFLAGS) \
-	$(LIBOSMOSIGTRAN_CFLAGS) \
-	$(LIBOSMORANAP_CFLAGS) \
-	$(NULL)
-endif
-
-EXTRA_DIST = \
-	sgsn_test.ok \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	sgsn_test \
-	$(NULL)
-
-sgsn_test_SOURCES = \
-	sgsn_test.c \
-	$(NULL)
-
-sgsn_test_LDFLAGS = \
-	-Wl,--wrap=RAND_bytes \
-	-Wl,--wrap=sgsn_update_subscriber_data \
-	-Wl,--wrap=gprs_subscr_request_update_location \
-	-Wl,--wrap=gprs_subscr_request_auth_info \
-	-Wl,--wrap=gsup_client_send \
-	$(NULL)
-
-sgsn_test_LDADD = \
-	$(top_builddir)/src/gprs/gprs_llc_parse.o \
-	$(top_builddir)/src/gprs/gprs_llc.o \
-	$(top_builddir)/src/gprs/crc24.o \
-	$(top_builddir)/src/gprs/gprs_sndcp.o \
-	$(top_builddir)/src/gprs/gprs_gmm.o \
-	$(top_builddir)/src/gprs/gprs_sgsn.o \
-	$(top_builddir)/src/gprs/sgsn_vty.o \
-	$(top_builddir)/src/gprs/sgsn_libgtp.o \
-	$(top_builddir)/src/gprs/sgsn_auth.o \
-	$(top_builddir)/src/gprs/sgsn_ares.o \
-	$(top_builddir)/src/gprs/gprs_utils.o \
-	$(top_builddir)/src/gprs/gprs_subscriber.o \
-	$(top_builddir)/src/gprs/gprs_gb_parse.o \
-        $(top_builddir)/src/gprs/gprs_llc_xid.o \
-	$(top_builddir)/src/gprs/gprs_sndcp_xid.o \
-        $(top_builddir)/src/gprs/slhc.o \
-        $(top_builddir)/src/gprs/gprs_sndcp_comp.o \
-        $(top_builddir)/src/gprs/gprs_sndcp_pcomp.o \
-        $(top_builddir)/src/gprs/v42bis.o \
-        $(top_builddir)/src/gprs/gprs_sndcp_dcomp.o \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOABIS_LIBS) \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOGB_LIBS) \
-	$(LIBCARES_LIBS) \
-	$(LIBCRYPTO_LIBS) \
-	$(LIBGTP_LIBS) \
-	-lrt \
-	-lm \
-	$(NULL)
-
-if BUILD_IU
-sgsn_test_LDADD += \
-	$(LIBOSMORANAP_LIBS) \
-	$(LIBOSMOSIGTRAN_LIBS) \
-	$(LIBASN1C_LIBS) \
-	$(NULL)
-endif
diff --git a/tests/sgsn/sgsn_test.c b/tests/sgsn/sgsn_test.c
deleted file mode 100644
index d66c5dd..0000000
--- a/tests/sgsn/sgsn_test.c
+++ /dev/null
@@ -1,2487 +0,0 @@
-/* Test the SGSN */
-/*
- * (C) 2014 by Holger Hans Peter Freyther
- * (C) 2014 by 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 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/>.
- *
- */
-
-#include <openbsc/gprs_llc.h>
-#include <openbsc/sgsn.h>
-#include <openbsc/gprs_gmm.h>
-#include <openbsc/debug.h>
-#include <openbsc/gprs_subscriber.h>
-#include <osmocom/gsm/gsup.h>
-#include <openbsc/gsup_client.h>
-#include <openbsc/gprs_utils.h>
-#include <openbsc/gprs_gb_parse.h>
-
-#include <osmocom/gprs/gprs_bssgp.h>
-
-#include <osmocom/gsm/gsm_utils.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/rate_ctr.h>
-#include <osmocom/core/utils.h>
-
-#include <stdio.h>
-
-void *tall_bsc_ctx;
-static struct sgsn_instance sgsn_inst = {
-	.config_file = "osmo_sgsn.cfg",
-	.cfg = {
-		.gtp_statedir = "./",
-		.auth_policy = SGSN_AUTH_POLICY_CLOSED,
-	},
-};
-struct sgsn_instance *sgsn = &sgsn_inst;
-unsigned sgsn_tx_counter = 0;
-struct msgb *last_msg = NULL;
-struct gprs_gb_parse_context last_dl_parse_ctx;
-
-static void reset_last_msg()
-{
-	if (last_msg)
-		msgb_free(last_msg);
-
-	last_msg = NULL;
-	memset(&last_dl_parse_ctx, 0, sizeof(last_dl_parse_ctx));
-}
-
-static void cleanup_test()
-{
-	reset_last_msg();
-}
-
-static uint32_t get_new_ptmsi(const struct gprs_gb_parse_context *parse_ctx)
-{
-	uint32_t new_ptmsi = GSM_RESERVED_TMSI;
-
-	if (parse_ctx->new_ptmsi_enc)
-		gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
-
-	return new_ptmsi;
-}
-
-/* override */
-int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime,
-		   struct bssgp_dl_ud_par *dup)
-{
-	int rc;
-
-	reset_last_msg();
-
-	last_msg = msg;
-	OSMO_ASSERT(msgb_data(last_msg) != NULL);
-
-	rc = gprs_gb_parse_llc(msgb_data(last_msg), msgb_length(last_msg),
-		&last_dl_parse_ctx);
-
-	fprintf(stderr, "Got DL LLC message: %s\n",
-		gprs_gb_message_name(&last_dl_parse_ctx, "UNKNOWN"));
-
-	OSMO_ASSERT(rc > 0);
-
-	sgsn_tx_counter += 1;
-	return 0;
-}
-
-/* override, requires '-Wl,--wrap=RAND_bytes' */
-int __real_RAND_bytes(unsigned char *buf, int num);
-int mock_RAND_bytes(unsigned char *buf, int num);
-int (*RAND_bytes_cb)(unsigned char *, int) =
-  &mock_RAND_bytes;
-
-int __wrap_RAND_bytes(unsigned char *buf, int num)
-{
-	return (*RAND_bytes_cb)(buf, num);
-}
-/* make results of A&C ref predictable */
-int mock_RAND_bytes(unsigned char *buf, int num)
-{
-	if (num > 1)
-		return __real_RAND_bytes(buf, num);
-	buf[0] = 0;
-	return 1;
-}
-
-/* override, requires '-Wl,--wrap=sgsn_update_subscriber_data' */
-void __real_sgsn_update_subscriber_data(struct sgsn_mm_ctx *);
-void (*update_subscriber_data_cb)(struct sgsn_mm_ctx *) =
-    &__real_sgsn_update_subscriber_data;
-
-void __wrap_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
-{
-	(*update_subscriber_data_cb)(mmctx);
-}
-
-/* override, requires '-Wl,--wrap=gprs_subscr_request_update_location' */
-int __real_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
-int (*subscr_request_update_location_cb)(struct sgsn_mm_ctx *mmctx) =
-	&__real_gprs_subscr_request_update_location;
-
-int __wrap_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
-	return (*subscr_request_update_location_cb)(mmctx);
-};
-
-/* override, requires '-Wl,--wrap=gprs_subscr_request_auth_info' */
-int __real_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand);
-int (*subscr_request_auth_info_cb)(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand) =
-	&__real_gprs_subscr_request_auth_info;
-
-int __wrap_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand) {
-	return (*subscr_request_auth_info_cb)(mmctx, auts, auts_rand);
-};
-
-/* override, requires '-Wl,--wrap=gsup_client_send' */
-int __real_gsup_client_send(struct gsup_client *gsupc, struct msgb *msg);
-int (*gsup_client_send_cb)(struct gsup_client *gsupc, struct msgb *msg) =
-	&__real_gsup_client_send;
-
-int __wrap_gsup_client_send(struct gsup_client *gsupc, struct msgb *msg)
-{
-	return (*gsup_client_send_cb)(gsupc, msg);
-};
-
-static int count(struct llist_head *head)
-{
-	struct llist_head *cur;
-	int count = 0;
-
-	llist_for_each(cur, head)
-		count += 1;
-
-	return count;		
-}
-
-static struct msgb *create_msg(const uint8_t *data, size_t len)
-{
-	struct msgb *msg = msgb_alloc(len + 8, "test message");
-	msg->l1h = msgb_put(msg, 8);
-	msg->l2h = msgb_put(msg, len);
-	memcpy(msg->l2h, data, len);
-
-	msgb_bcid(msg) = msg->l1h;
-	msgb_gmmh(msg) = msg->l2h;
-	return msg;
-}
-
-/*
- * Create a context and search for it
- */
-static struct sgsn_mm_ctx *alloc_mm_ctx(uint32_t tlli, struct gprs_ra_id *raid)
-{
-	struct sgsn_mm_ctx *ctx, *ictx;
-	struct gprs_llc_lle *lle;
-	int old_count = count(gprs_llme_list());
-
-	lle = gprs_lle_get_or_create(tlli, 3);
-	ctx = sgsn_mm_ctx_alloc_gb(tlli, raid);
-	ctx->gmm_state = GMM_REGISTERED_NORMAL;
-	ctx->gb.llme = lle->llme;
-
-	ictx = sgsn_mm_ctx_by_tlli(tlli, raid);
-	OSMO_ASSERT(ictx == ctx);
-
-	OSMO_ASSERT(count(gprs_llme_list()) == old_count + 1);
-
-	return ctx;
-}
-
-static void send_0408_message(struct gprs_llc_llme *llme, uint32_t tlli,
-			      const struct gprs_ra_id *bssgp_raid,
-			      const uint8_t *data, size_t data_len)
-{
-	struct msgb *msg;
-
-	reset_last_msg();
-	sgsn_tx_counter = 0;
-
-	msg = create_msg(data, data_len);
-	msgb_tlli(msg) = tlli;
-	bssgp_create_cell_id(msgb_bcid(msg), bssgp_raid, 0);
-	gsm0408_gprs_rcvmsg_gb(msg, llme, false);
-	msgb_free(msg);
-}
-
-static void test_llme(void)
-{
-	struct gprs_llc_lle *lle, *lle_copy;
-	uint32_t local_tlli;
-
-	printf("Testing LLME allocations\n");
-	local_tlli = gprs_tmsi2tlli(0x234, TLLI_LOCAL);
-
-	/* initial state */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-
-	/* Create a new entry */
-	lle = gprs_lle_get_or_create(local_tlli, 3);
-	OSMO_ASSERT(lle);
-	OSMO_ASSERT(count(gprs_llme_list()) == 1);
-
-	/* No new entry is created */
-	lle_copy = gprs_lle_get_or_create(local_tlli, 3);
-	OSMO_ASSERT(lle == lle_copy);
-	OSMO_ASSERT(count(gprs_llme_list()) == 1);
-
-	/* unassign which should delete it*/
-	gprs_llgmm_unassign(lle->llme);
-
-	/* Check that everything was cleaned up */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-
-	cleanup_test();
-}
-
-struct gprs_subscr *last_updated_subscr = NULL;
-void my_dummy_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
-{
-	OSMO_ASSERT(mmctx);
-	fprintf(stderr, "Called %s, mmctx = %p, subscr = %p\n",
-		__func__, mmctx, mmctx->subscr);
-	last_updated_subscr = mmctx->subscr;
-}
-
-static void assert_subscr(const struct gprs_subscr *subscr, const char *imsi)
-{
-	struct gprs_subscr *sfound;
-	OSMO_ASSERT(subscr);
-	OSMO_ASSERT(strcmp(subscr->imsi, imsi) == 0);
-
-	sfound = gprs_subscr_get_by_imsi(imsi);
-	OSMO_ASSERT(sfound == subscr);
-
-	gprs_subscr_put(sfound);
-}
-
-static void show_subscrs(FILE *out)
-{
-	struct gprs_subscr *subscr;
-
-	llist_for_each_entry(subscr, gprs_subscribers, entry) {
-		fprintf(out, "  Subscriber: %s, "
-			"use count: %d\n",
-			subscr->imsi, subscr->use_count);
-	}
-}
-
-static void assert_no_subscrs()
-{
-	show_subscrs(stdout);
-	fflush(stdout);
-	OSMO_ASSERT(llist_empty(gprs_subscribers));
-}
-
-#define VERBOSE_ASSERT(val, expect_op, fmt) \
-	do { \
-		printf(#val " == " fmt "\n", (val)); \
-		OSMO_ASSERT((val) expect_op); \
-	} while (0);
-
-static void test_subscriber(void)
-{
-	struct gprs_subscr *s1, *s2, *s3;
-	const char *imsi1 = "1234567890";
-	const char *imsi2 = "9876543210";
-	const char *imsi3 = "5656565656";
-
-	update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
-
-	printf("Testing core subscriber data API\n");
-
-	/* Check for emptiness */
-	OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
-	OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
-	OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
-	VERBOSE_ASSERT(llist_count(gprs_subscribers), == 0, "%d");
-
-	/* Allocate entry 1 */
-	s1 = gprs_subscr_get_or_create(imsi1);
-	VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
-	s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
-	assert_subscr(s1, imsi1);
-	VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
-	OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
-
-	/* Allocate entry 2 */
-	s2 = gprs_subscr_get_or_create(imsi2);
-	VERBOSE_ASSERT(llist_count(gprs_subscribers), == 2, "%d");
-	s2->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
-
-	/* Allocate entry 3 */
-	s3 = gprs_subscr_get_or_create(imsi3);
-	VERBOSE_ASSERT(llist_count(gprs_subscribers), == 3, "%d");
-
-	/* Check entries */
-	assert_subscr(s1, imsi1);
-	assert_subscr(s2, imsi2);
-	assert_subscr(s3, imsi3);
-
-	/* Update entry 1 */
-	last_updated_subscr = NULL;
-	gprs_subscr_update(s1);
-	OSMO_ASSERT(last_updated_subscr == NULL);
-	OSMO_ASSERT(s1->sgsn_data->mm == NULL);
-	OSMO_ASSERT((s1->flags & GPRS_SUBSCRIBER_FIRST_CONTACT) == 0);
-
-	/* There is no subscriber cache. Verify it */
-	gprs_subscr_cleanup(s1);
-	gprs_subscr_put(s1);
-	s1 = NULL;
-	VERBOSE_ASSERT(llist_count(gprs_subscribers), == 2, "%d");
-	OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
-
-	assert_subscr(s2, imsi2);
-	assert_subscr(s3, imsi3);
-
-	/* Free entry 2 (GPRS_SUBSCRIBER_FIRST_CONTACT is set) */
-	gprs_subscr_cleanup(s2);
-	gprs_subscr_put(s2);
-	s2 = NULL;
-	VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
-	OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
-	OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
-	assert_subscr(s3, imsi3);
-
-	/* Try to delete entry 3 */
-	gprs_subscr_cleanup(s3);
-	gprs_subscr_put(s3);
-	s3 = NULL;
-	VERBOSE_ASSERT(llist_count(gprs_subscribers), == 0, "%d");
-	OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
-
-	OSMO_ASSERT(llist_empty(gprs_subscribers));
-
-	update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
-
-	cleanup_test();
-}
-
-static void test_auth_triplets(void)
-{
-	struct gprs_subscr *s1, *s1found;
-	const char *imsi1 = "1234567890";
-	struct gsm_auth_tuple *at;
-	struct sgsn_mm_ctx *ctx;
-	struct gprs_ra_id raid = { 0, };
-	uint32_t local_tlli = 0xffeeddcc;
-
-	printf("Testing authentication triplet handling\n");
-
-	/* Check for emptiness */
-	OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
-
-	/* Allocate entry 1 */
-	s1 = gprs_subscr_get_or_create(imsi1);
-	s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
-	s1found = gprs_subscr_get_by_imsi(imsi1);
-	OSMO_ASSERT(s1found == s1);
-	gprs_subscr_put(s1found);
-
-	/* Create a context */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	ctx = alloc_mm_ctx(local_tlli, &raid);
-
-	/* Attach s1 to ctx */
-	ctx->subscr = gprs_subscr_get(s1);
-	ctx->subscr->sgsn_data->mm = ctx;
-
-	/* Try to get auth tuple */
-	at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
-	OSMO_ASSERT(at == NULL);
-
-	/* Add triplets */
-	s1->sgsn_data->auth_triplets[0].key_seq = 0;
-	s1->sgsn_data->auth_triplets[1].key_seq = 1;
-	s1->sgsn_data->auth_triplets[2].key_seq = 2;
-
-	/* Try to get auth tuple */
-	at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
-	OSMO_ASSERT(at != NULL);
-	OSMO_ASSERT(at->key_seq == 0);
-	OSMO_ASSERT(at->use_count == 1);
-	at = sgsn_auth_get_tuple(ctx, at->key_seq);
-	OSMO_ASSERT(at != NULL);
-	OSMO_ASSERT(at->key_seq == 1);
-	OSMO_ASSERT(at->use_count == 1);
-	at = sgsn_auth_get_tuple(ctx, at->key_seq);
-	OSMO_ASSERT(at != NULL);
-	OSMO_ASSERT(at->key_seq == 2);
-	OSMO_ASSERT(at->use_count == 1);
-	at = sgsn_auth_get_tuple(ctx, at->key_seq);
-	OSMO_ASSERT(at == NULL);
-
-	/* Free MM context and subscriber */
-	gprs_subscr_put(s1);
-	sgsn_mm_ctx_cleanup_free(ctx);
-	s1found = gprs_subscr_get_by_imsi(imsi1);
-	OSMO_ASSERT(s1found == NULL);
-
-	cleanup_test();
-}
-
-#define TEST_GSUP_IMSI1_IE 0x01, 0x05, 0x21, 0x43, 0x65, 0x87, 0x09
-
-static int rx_gsup_message(const uint8_t *data, size_t data_len)
-{
-	struct msgb *msg;
-	int rc;
-
-	msg = msgb_alloc(1024, __func__);
-	msg->l2h = msgb_put(msg, data_len);
-	OSMO_ASSERT(msg->l2h != NULL);
-	memcpy(msg->l2h, data, data_len);
-	rc = gprs_subscr_rx_gsup_message(msg);
-	msgb_free(msg);
-
-	return rc;
-}
-
-static void test_subscriber_gsup(void)
-{
-	struct gprs_subscr *s1, *s1found;
-	const char *imsi1 = "1234567890";
-	struct sgsn_mm_ctx *ctx;
-	struct gprs_ra_id raid = { 0, };
-	uint32_t local_tlli = 0xffeeddcc;
-	struct sgsn_subscriber_pdp_data *pdpd;
-	int rc;
-
-	static const uint8_t send_auth_info_res[] = {
-		0x0a,
-		TEST_GSUP_IMSI1_IE,
-		0x03, 0x22, /* Auth tuple */
-			0x20, 0x10,
-				0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-				0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
-			0x21, 0x04,
-				0x21, 0x22, 0x23, 0x24,
-			0x22, 0x08,
-				0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
-		0x03, 0x22, /* Auth tuple */
-			0x20, 0x10,
-				0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
-				0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
-			0x21, 0x04,
-				0xa1, 0xa2, 0xa3, 0xa4,
-			0x22, 0x08,
-				0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
-	};
-
-	static const uint8_t send_auth_info_err[] = {
-		0x09,
-		TEST_GSUP_IMSI1_IE,
-		0x02, 0x01, 0x07 /* GPRS not allowed */
-	};
-
-#define MSISDN	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09
-
-	static const uint8_t s1_msisdn[] = { MSISDN };
-
-	static const uint8_t update_location_res[] = {
-		0x06,
-		TEST_GSUP_IMSI1_IE,
-		0x08, 0x09, MSISDN,
-		0x04, 0x00, /* PDP info complete */
-		0x05, 0x12,
-			0x10, 0x01, 0x01,
-			0x11, 0x02, 0xf1, 0x21, /* IPv4 */
-			0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
-		0x05, 0x11,
-			0x10, 0x01, 0x02,
-			0x11, 0x02, 0xf1, 0x21, /* IPv4 */
-			0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n',
-	};
-
-#undef MSISDN
-
-	static const uint8_t update_location_err[] = {
-		0x05,
-		TEST_GSUP_IMSI1_IE,
-		0x02, 0x01, 0x07 /* GPRS not allowed */
-	};
-
-	static const uint8_t location_cancellation_req[] = {
-		0x1c,
-		TEST_GSUP_IMSI1_IE,
-		0x06, 0x01, 0x00,
-	};
-
-	static const uint8_t location_cancellation_req_withdraw[] = {
-		0x1c,
-		TEST_GSUP_IMSI1_IE,
-		0x06, 0x01, 0x01,
-	};
-
-	static const uint8_t location_cancellation_req_other[] = {
-		0x1c,
-		0x01, 0x05, 0x11, 0x11, 0x11, 0x11, 0x01,
-		0x06, 0x01, 0x00,
-	};
-
-	static const uint8_t purge_ms_err[] = {
-		0x0d,
-		TEST_GSUP_IMSI1_IE,
-		0x02, 0x01, 0x02, /* IMSI unknown in HLR */
-	};
-
-	static const uint8_t purge_ms_err_no_cause[] = {
-		0x0d,
-		TEST_GSUP_IMSI1_IE,
-	};
-
-	static const uint8_t purge_ms_res[] = {
-		0x0e,
-		TEST_GSUP_IMSI1_IE,
-		0x07, 0x00,
-	};
-
-
-	static const uint8_t insert_data_req[] = {
-		0x10,
-		TEST_GSUP_IMSI1_IE,
-		0x05, 0x11,
-			0x10, 0x01, 0x03,
-			0x11, 0x02, 0xf1, 0x21, /* IPv4 */
-			0x12, 0x08, 0x03, 'b', 'a', 'r', 0x03, 'a', 'p', 'n',
-	};
-
-	static const uint8_t delete_data_req[] = {
-		0x14,
-		TEST_GSUP_IMSI1_IE,
-		0x10, 0x01, 0x03,
-	};
-
-	printf("Testing subscriber GSUP handling\n");
-
-	update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
-
-	/* Check for emptiness */
-	OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
-
-	/* Allocate entry 1 */
-	s1 = gprs_subscr_get_or_create(imsi1);
-	s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
-	s1found = gprs_subscr_get_by_imsi(imsi1);
-	OSMO_ASSERT(s1found == s1);
-	gprs_subscr_put(s1found);
-
-	/* Create a context */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	ctx = alloc_mm_ctx(local_tlli, &raid);
-
-	/* Attach s1 to ctx */
-	ctx->subscr = gprs_subscr_get(s1);
-	ctx->subscr->sgsn_data->mm = ctx;
-
-	/* Inject SendAuthInfoReq GSUP message */
-	rc = rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
-	OSMO_ASSERT(rc >= 0);
-	OSMO_ASSERT(last_updated_subscr == s1);
-
-	/* Check triplets */
-	OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == 0);
-	OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == 1);
-	OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
-
-	/* Inject SendAuthInfoErr GSUP message */
-	rc = rx_gsup_message(send_auth_info_err, sizeof(send_auth_info_err));
-	OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
-	OSMO_ASSERT(last_updated_subscr == s1);
-	OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_GPRS_NOTALLOWED);
-
-	/* Check triplets */
-	OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == GSM_KEY_SEQ_INVAL);
-	OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == GSM_KEY_SEQ_INVAL);
-	OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
-
-	/* Inject UpdateLocRes GSUP message */
-	rc = rx_gsup_message(update_location_res, sizeof(update_location_res));
-	OSMO_ASSERT(rc >= 0);
-	OSMO_ASSERT(last_updated_subscr == s1);
-	OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_ENABLE_PURGE);
-	OSMO_ASSERT(s1->sgsn_data->error_cause == SGSN_ERROR_CAUSE_NONE);
-	OSMO_ASSERT(s1->sgsn_data->msisdn_len == sizeof(s1_msisdn));
-	OSMO_ASSERT(memcmp(s1->sgsn_data->msisdn, s1_msisdn, sizeof(s1_msisdn)) == 0);
-	OSMO_ASSERT(!llist_empty(&s1->sgsn_data->pdp_list));
-	pdpd = llist_entry(s1->sgsn_data->pdp_list.next,
-		struct sgsn_subscriber_pdp_data, list);
-	OSMO_ASSERT(strcmp(pdpd->apn_str, "test.apn") == 0);
-	pdpd = llist_entry(pdpd->list.next,
-		struct sgsn_subscriber_pdp_data, list);
-	OSMO_ASSERT(strcmp(pdpd->apn_str, "foo.apn") == 0);
-
-	/* Check authorization */
-	OSMO_ASSERT(s1->authorized == 1);
-
-	/* Inject UpdateLocErr GSUP message */
-	rc = rx_gsup_message(update_location_err, sizeof(update_location_err));
-	OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
-	OSMO_ASSERT(last_updated_subscr == s1);
-	OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_GPRS_NOTALLOWED);
-
-	/* Check authorization */
-	OSMO_ASSERT(s1->authorized == 0);
-
-	/* Inject InsertSubscrData GSUP message */
-	last_updated_subscr = NULL;
-	rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req));
-	OSMO_ASSERT(rc == -ENOTSUP);	/* not connected */
-	OSMO_ASSERT(last_updated_subscr == s1);
-
-	/* Inject DeleteSubscrData GSUP message */
-	last_updated_subscr = NULL;
-	rc = rx_gsup_message(delete_data_req, sizeof(delete_data_req));
-	if (rc != -GMM_CAUSE_SEM_INCORR_MSG)
-		printf("Unexpected response to DSD: %d\n", rc);
-	OSMO_ASSERT(last_updated_subscr == NULL);
-
-	/* Inject wrong LocCancelReq GSUP message */
-	last_updated_subscr = NULL;
-	rc = rx_gsup_message(location_cancellation_req_other,
-			     sizeof(location_cancellation_req_other));
-	OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
-	OSMO_ASSERT(last_updated_subscr == NULL);
-
-	/* Check cancellation result */
-	OSMO_ASSERT(!(s1->flags & GPRS_SUBSCRIBER_CANCELLED));
-	OSMO_ASSERT(s1->sgsn_data->mm != NULL);
-
-	/* Inject LocCancelReq GSUP message */
-	rc = rx_gsup_message(location_cancellation_req,
-			     sizeof(location_cancellation_req));
-	OSMO_ASSERT(rc >= 0);
-	OSMO_ASSERT(last_updated_subscr == s1);
-	OSMO_ASSERT(s1->sgsn_data->error_cause == SGSN_ERROR_CAUSE_NONE);
-
-	/* Check cancellation result */
-	OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_CANCELLED);
-	OSMO_ASSERT(s1->sgsn_data->mm == NULL);
-
-	/* Inject LocCancelReq(withdraw) GSUP message */
-	rc = rx_gsup_message(location_cancellation_req_withdraw,
-			     sizeof(location_cancellation_req_withdraw));
-	OSMO_ASSERT(rc >= 0);
-	OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_IMPL_DETACHED);
-
-	/* Inject PurgeMsRes GSUP message */
-	rc = rx_gsup_message(purge_ms_res,
-			     sizeof(purge_ms_res));
-	OSMO_ASSERT(rc >= 0);
-	OSMO_ASSERT(!(s1->flags & GPRS_SUBSCRIBER_ENABLE_PURGE));
-
-	/* Free MM context and subscriber */
-	OSMO_ASSERT(ctx->subscr == NULL);
-	sgsn_mm_ctx_cleanup_free(ctx);
-	gprs_subscr_put(s1);
-	s1found = gprs_subscr_get_by_imsi(imsi1);
-	OSMO_ASSERT(s1found == NULL);
-
-	/* Inject PurgeMsRes GSUP message */
-	rc = rx_gsup_message(purge_ms_res,
-			     sizeof(purge_ms_res));
-	OSMO_ASSERT(rc >= 0);
-
-	/* Inject PurgeMsErr(IMSI unknown in HLR) GSUP message */
-	rc = rx_gsup_message(purge_ms_err,
-			     sizeof(purge_ms_err));
-	OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
-
-	/* Inject PurgeMsErr() GSUP message */
-	rc = rx_gsup_message(purge_ms_err_no_cause,
-			     sizeof(purge_ms_err_no_cause));
-	OSMO_ASSERT(rc == -GMM_CAUSE_NET_FAIL);
-
-	/* Inject InsertSubscrData GSUP message (unknown IMSI) */
-	last_updated_subscr = NULL;
-	rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req));
-	OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
-	OSMO_ASSERT(last_updated_subscr == NULL);
-
-	/* Inject DeleteSubscrData GSUP message (unknown IMSI) */
-	rc = rx_gsup_message(delete_data_req, sizeof(delete_data_req));
-	OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
-	OSMO_ASSERT(last_updated_subscr == NULL);
-
-	/* Inject LocCancelReq GSUP message (unknown IMSI) */
-	rc = rx_gsup_message(location_cancellation_req,
-			     sizeof(location_cancellation_req));
-	OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
-	OSMO_ASSERT(last_updated_subscr == NULL);
-
-	update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
-
-	cleanup_test();
-}
-
-int my_gsup_client_send_dummy(struct gsup_client *gsupc, struct msgb *msg)
-{
-	msgb_free(msg);
-	return 0;
-};
-
-/*
- * Test that a GMM Detach will remove the MMCTX and the
- * associated LLME.
- */
-static void test_gmm_detach(void)
-{
-	struct gprs_ra_id raid = { 0, };
-	struct sgsn_mm_ctx *ctx, *ictx;
-	uint32_t local_tlli;
-
-	printf("Testing GMM detach\n");
-
-	/* DTAP - Detach Request (MO) */
-	/* normal detach, power_off = 0 */
-	static const unsigned char detach_req[] = {
-		0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
-		0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
-	};
-
-	local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
-
-	/* Create a context */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	ctx = alloc_mm_ctx(local_tlli, &raid);
-
-	/* inject the detach */
-	send_0408_message(ctx->gb.llme, local_tlli, &raid,
-			  detach_req, ARRAY_SIZE(detach_req));
-
-	/* verify that a single message (hopefully the Detach Accept) has been
-	 * sent by the SGSN */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-
-	/* verify that things are gone */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
-	OSMO_ASSERT(!ictx);
-
-	cleanup_test();
-}
-
-/*
- * Test that a GMM Detach will remove the MMCTX and the associated LLME but
- * will not sent a Detach Accept message (power_off = 1)
- */
-static void test_gmm_detach_power_off(void)
-{
-	struct gprs_ra_id raid = { 0, };
-	struct sgsn_mm_ctx *ctx, *ictx;
-	uint32_t local_tlli;
-
-	printf("Testing GMM detach (power off)\n");
-
-	/* DTAP - Detach Request (MO) */
-	/* normal detach, power_off = 1 */
-	static const unsigned char detach_req[] = {
-		0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
-		0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
-	};
-
-	local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
-
-	/* Create a context */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	ctx = alloc_mm_ctx(local_tlli, &raid);
-
-	/* inject the detach */
-	send_0408_message(ctx->gb.llme, local_tlli, &raid,
-			  detach_req, ARRAY_SIZE(detach_req));
-
-	/* verify that no message (and therefore no Detach Accept) has been
-	 * sent by the SGSN */
-	OSMO_ASSERT(sgsn_tx_counter == 0);
-
-	/* verify that things are gone */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
-	OSMO_ASSERT(!ictx);
-
-	cleanup_test();
-}
-
-/*
- * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
- */
-static void test_gmm_detach_no_mmctx(void)
-{
-	struct gprs_ra_id raid = { 0, };
-	struct gprs_llc_lle *lle;
-	uint32_t local_tlli;
-
-	printf("Testing GMM detach (no MMCTX)\n");
-
-	/* DTAP - Detach Request (MO) */
-	/* normal detach, power_off = 0 */
-	static const unsigned char detach_req[] = {
-		0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
-		0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
-	};
-
-	/* Create an LLME  */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
-	lle = gprs_lle_get_or_create(local_tlli, 3);
-
-	OSMO_ASSERT(count(gprs_llme_list()) == 1);
-
-	/* inject the detach */
-	send_0408_message(lle->llme, local_tlli, &raid,
-			  detach_req, ARRAY_SIZE(detach_req));
-
-	/* verify that the LLME is gone */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-
-	cleanup_test();
-}
-
-/*
- * Test that a single GMM Detach Accept message will not cause the SGSN to send
- * any message or leave an MM context at the SGSN.
- */
-static void test_gmm_detach_accept_unexpected(void)
-{
-	struct gprs_ra_id raid = { 0, };
-	struct gprs_llc_lle *lle;
-	uint32_t local_tlli;
-
-	printf("Testing GMM detach accept (unexpected)\n");
-
-	/* DTAP - Detach Accept (MT) */
-	/* normal detach */
-	static const unsigned char detach_acc[] = {
-		0x08, 0x06
-	};
-
-	/* Create an LLME  */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
-	lle = gprs_lle_get_or_create(local_tlli, 3);
-
-	/* inject the detach */
-	send_0408_message(lle->llme, local_tlli, &raid,
-			  detach_acc, ARRAY_SIZE(detach_acc));
-
-	/* verify that no message (and therefore no Status or XID reset) has been
-	 * sent by the SGSN */
-	OSMO_ASSERT(sgsn_tx_counter == 0);
-
-	/* verify that things are gone */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-
-	cleanup_test();
-}
-
-/*
- * Test that a GMM Status will remove the associated LLME if there is no MMCTX.
- */
-static void test_gmm_status_no_mmctx(void)
-{
-	struct gprs_ra_id raid = { 0, };
-	struct gprs_llc_lle *lle;
-	uint32_t local_tlli;
-
-	printf("Testing GMM Status (no MMCTX)\n");
-
-	/* DTAP - GMM Status, protocol error */
-	static const unsigned char gmm_status[] = {
-		0x08, 0x20, 0x6f
-	};
-
-	/* Create an LLME  */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
-	lle = gprs_lle_get_or_create(local_tlli, 3);
-
-	OSMO_ASSERT(count(gprs_llme_list()) == 1);
-
-	/* inject the detach */
-	send_0408_message(lle->llme, local_tlli, &raid,
-			  gmm_status, ARRAY_SIZE(gmm_status));
-
-	/* verify that no message has been sent by the SGSN */
-	OSMO_ASSERT(sgsn_tx_counter == 0);
-
-	/* verify that the LLME is gone */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-
-	cleanup_test();
-}
-
-/*
- * Test the GMM Attach procedure
- */
-static void test_gmm_attach(int retry)
-{
-	struct gprs_ra_id raid = { 0, };
-	struct sgsn_mm_ctx *ctx = NULL;
-	struct sgsn_mm_ctx *ictx;
-	uint32_t ptmsi1;
-	uint32_t foreign_tlli;
-	uint32_t local_tlli = 0;
-	struct gprs_llc_lle *lle;
-
-	/* DTAP - Attach Request */
-	/* The P-TMSI is not known by the SGSN */
-	static const unsigned char attach_req[] = {
-		0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
-		0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
-		0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
-		0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
-		0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
-	};
-
-	/* DTAP - Identity Response IMEI */
-	static const unsigned char ident_resp_imei[] = {
-		0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
-		0x56
-	};
-
-	/* DTAP - Identity Response IMSI */
-	static const unsigned char ident_resp_imsi[] = {
-		0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
-		0x54
-	};
-
-	/* DTAP - Authentication and Ciphering Resp */
-	static const unsigned char auth_ciph_resp[] = {
-		0x08, 0x13, 0x00, 0x22, 0x51, 0xe5, 0x51, 0xe5, 0x23, 0x09,
-		0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x01
-	};
-
-	/* DTAP - Attach Complete */
-	static const unsigned char attach_compl[] = {
-		0x08, 0x03
-	};
-
-	/* DTAP - Detach Request (MO) */
-	/* normal detach, power_off = 0 */
-	static const unsigned char detach_req[] = {
-		0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xeb, 0x8b,
-		0x45, 0x67, 0x19, 0x03, 0xb9, 0x97, 0xcb
-	};
-
-	printf("Testing GMM attach%s\n", retry ? " with retry" : "");
-
-	foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
-
-	/* Create a LLE/LLME */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	lle = gprs_lle_get_or_create(foreign_tlli, 3);
-	OSMO_ASSERT(count(gprs_llme_list()) == 1);
-
-	/* inject the attach request */
-	send_0408_message(lle->llme, foreign_tlli, &raid,
-			  attach_req, ARRAY_SIZE(attach_req));
-
-	ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
-	OSMO_ASSERT(ctx != NULL);
-	OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
-
-	/* we expect an identity request (IMEI) */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-
-	/* inject the identity response (IMEI) */
-	send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
-			  ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
-
-	/* we expect an identity request (IMSI) */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-
-	/* inject the identity response (IMSI) */
-	send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
-			  ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
-
-	/* check that the MM context has not been removed due to a failed
-	 * authorization */
-	OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
-
-	OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
-
-retry_attach_req:
-
-	if (retry && sgsn_tx_counter == 0) {
-		fprintf(stderr, "Retrying attach request\n");
-		/* re-inject the attach request */
-		send_0408_message(lle->llme, foreign_tlli, &raid,
-				  attach_req, ARRAY_SIZE(attach_req));
-	}
-
-	if (ctx->auth_state == SGSN_AUTH_AUTHENTICATE && sgsn_tx_counter == 1) {
-		/* we got an auth & ciph request */
-
-		/* inject the auth & ciph response */
-		send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
-				  auth_ciph_resp, ARRAY_SIZE(auth_ciph_resp));
-
-		/* check that the MM context has not been removed due to a
-		 * failed authorization */
-		OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
-		if (ctx->subscr && ctx->subscr->sgsn_data->msisdn_len > 0)
-			OSMO_ASSERT(strcmp(ctx->msisdn, "+49166213323") == 0);
-	}
-
-	if (retry && sgsn_tx_counter == 0)
-		goto retry_attach_req;
-
-	/* we expect an attach accept/reject */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-	ptmsi1 = get_new_ptmsi(&last_dl_parse_ctx);
-	OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
-
-	/* this has been randomly assigned by the SGSN */
-	local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
-
-	/* inject the attach complete */
-	send_0408_message(ctx->gb.llme, local_tlli, &raid,
-			  attach_compl, ARRAY_SIZE(attach_compl));
-
-	OSMO_ASSERT(ctx->gmm_state == GMM_REGISTERED_NORMAL);
-
-	/* we don't expect a response */
-	OSMO_ASSERT(sgsn_tx_counter == 0);
-
-	/* inject the detach */
-	send_0408_message(ctx->gb.llme, local_tlli, &raid,
-			  detach_req, ARRAY_SIZE(detach_req));
-
-	/* verify that things are gone */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
-	OSMO_ASSERT(!ictx);
-
-	cleanup_test();
-}
-
-static void test_gmm_attach_acl(void)
-{
-	const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
-
-	sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_CLOSED;
-	sgsn_acl_add("123456789012345", &sgsn->cfg);
-	printf("Auth policy 'closed': ");
-	test_gmm_attach(0);
-	sgsn_acl_del("123456789012345", &sgsn->cfg);
-
-	sgsn->cfg.auth_policy = saved_auth_policy;
-
-	cleanup_test();
-}
-
-int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
-	int rc;
-	rc = __real_gprs_subscr_request_update_location(mmctx);
-	if (rc == -ENOTSUP) {
-		OSMO_ASSERT(mmctx->subscr);
-		gprs_subscr_update(mmctx->subscr);
-	}
-	return rc;
-};
-
-int my_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
-	gprs_subscr_update(mmctx->subscr);
-	return 0;
-};
-
-static void test_gmm_attach_subscr(void)
-{
-	const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
-	struct gprs_subscr *subscr;
-
-	sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
-	subscr_request_update_location_cb = my_subscr_request_update_location;
-	subscr_request_auth_info_cb = my_subscr_request_auth_info;
-
-	subscr = gprs_subscr_get_or_create("123456789012345");
-	subscr->authorized = 1;
-
-	printf("Auth policy 'remote': ");
-	test_gmm_attach(0);
-	gprs_subscr_put(subscr);
-	assert_no_subscrs();
-
-	sgsn->cfg.auth_policy = saved_auth_policy;
-	subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
-	subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
-
-	cleanup_test();
-}
-
-int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx)
-{
-	/* Fake an authentication */
-	OSMO_ASSERT(mmctx->subscr);
-	mmctx->is_authenticated = 1;
-	gprs_subscr_update_auth_info(mmctx->subscr);
-
-	return 0;
-};
-
-static void test_gmm_attach_subscr_fake_auth(void)
-{
-	const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
-	struct gprs_subscr *subscr;
-
-	sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
-	subscr_request_update_location_cb = my_subscr_request_update_location;
-	subscr_request_auth_info_cb = my_subscr_request_auth_info_fake_auth;
-
-	subscr = gprs_subscr_get_or_create("123456789012345");
-	subscr->authorized = 1;
-	sgsn->cfg.require_authentication = 1;
-	sgsn->cfg.require_update_location = 1;
-
-	printf("Auth policy 'remote', auth faked: ");
-	test_gmm_attach(0);
-	gprs_subscr_put(subscr);
-	assert_no_subscrs();
-
-	sgsn->cfg.auth_policy = saved_auth_policy;
-	subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
-	subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
-
-	cleanup_test();
-}
-
-int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand)
-{
-	struct gsm_auth_tuple at = {
-		.vec.sres = {0x51, 0xe5, 0x51, 0xe5},
-		.vec.auth_types = OSMO_AUTH_TYPE_GSM,
-		.key_seq = 0
-	};
-
-	/* Fake an authentication */
-	OSMO_ASSERT(mmctx->subscr);
-	mmctx->subscr->sgsn_data->auth_triplets[0] = at;
-
-	gprs_subscr_update_auth_info(mmctx->subscr);
-
-	return 0;
-};
-
-static void test_gmm_attach_subscr_real_auth(void)
-{
-	const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
-	struct gprs_subscr *subscr;
-
-	sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
-	subscr_request_update_location_cb = my_subscr_request_update_location;
-	subscr_request_auth_info_cb = my_subscr_request_auth_info_real_auth;
-
-	subscr = gprs_subscr_get_or_create("123456789012345");
-	subscr->authorized = 1;
-	sgsn->cfg.require_authentication = 1;
-	sgsn->cfg.require_update_location = 1;
-
-	printf("Auth policy 'remote', triplet based auth: ");
-
-	test_gmm_attach(0);
-	gprs_subscr_put(subscr);
-	assert_no_subscrs();
-
-	sgsn->cfg.auth_policy = saved_auth_policy;
-	subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
-	subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
-
-	cleanup_test();
-}
-
-#define TEST_GSUP_IMSI_LONG_IE 0x01, 0x08, \
-			       0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5
-
-static int auth_info_skip = 0;
-static int upd_loc_skip = 0;
-
-int my_subscr_request_auth_info_gsup_auth(struct sgsn_mm_ctx *mmctx)
-{
-	static const uint8_t send_auth_info_res[] = {
-		0x0a,
-		TEST_GSUP_IMSI_LONG_IE,
-		0x03, 0x22, /* Auth tuple */
-			0x20, 0x10,
-				0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-				0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
-			0x21, 0x04,
-				0x51, 0xe5, 0x51, 0xe5,
-			0x22, 0x08,
-				0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
-	};
-
-	OSMO_ASSERT(!mmctx || mmctx->subscr);
-
-	if (auth_info_skip > 0) {
-		auth_info_skip -= 1;
-		return -EAGAIN;
-	}
-
-	/* Fake an SendAuthInfoRes */
-	rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
-
-	return 0;
-};
-
-int my_subscr_request_update_gsup_auth(struct sgsn_mm_ctx *mmctx) {
-	static const uint8_t update_location_res[] = {
-		0x06,
-		TEST_GSUP_IMSI_LONG_IE,
-		0x04, 0x00, /* PDP info complete */
-		0x05, 0x12,
-			0x10, 0x01, 0x01,
-			0x11, 0x02, 0xf1, 0x21, /* IPv4 */
-			0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
-		0x08, 0x07, /* MSISDN 49166213323 encoded */
-			0x91, 0x94, 0x61, 0x26, 0x31, 0x23, 0xF3,
-		0x09, 0x07, /* MSISDN 38166213323 encoded */
-			0x91, 0x83, 0x61, 0x26, 0x31, 0x23, 0xF3,
-	};
-
-	OSMO_ASSERT(!mmctx || mmctx->subscr);
-
-	if (upd_loc_skip > 0) {
-		upd_loc_skip -= 1;
-		return -EAGAIN;
-	}
-
-	/* Fake an UpdateLocRes */
-	return rx_gsup_message(update_location_res, sizeof(update_location_res));
-};
-
-
-static void test_gmm_attach_subscr_gsup_auth(int retry)
-{
-	const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
-	struct gprs_subscr *subscr;
-
-	sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
-	subscr_request_update_location_cb = my_subscr_request_update_gsup_auth;
-	subscr_request_auth_info_cb = my_subscr_request_auth_info_gsup_auth;
-	if (retry) {
-		upd_loc_skip = 3;
-		auth_info_skip = 3;
-	}
-
-	subscr = gprs_subscr_get_or_create("123456789012345");
-	subscr->authorized = 1;
-	sgsn->cfg.require_authentication = 1;
-	sgsn->cfg.require_update_location = 1;
-	gprs_subscr_put(subscr);
-
-	printf("Auth policy 'remote', GSUP based auth: ");
-	test_gmm_attach(retry);
-	assert_no_subscrs();
-
-	sgsn->cfg.auth_policy = saved_auth_policy;
-	subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
-	subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
-	upd_loc_skip = 0;
-	auth_info_skip = 0;
-
-	cleanup_test();
-}
-
-int my_gsup_client_send(struct gsup_client *gsupc, struct msgb *msg)
-{
-	struct osmo_gsup_message to_peer = {0};
-	struct osmo_gsup_message from_peer = {0};
-	struct msgb *reply_msg;
-	int rc;
-
-	/* Simulate the GSUP peer */
-	rc = osmo_gsup_decode(msgb_data(msg), msgb_length(msg), &to_peer);
-	OSMO_ASSERT(rc >= 0);
-	OSMO_ASSERT(to_peer.imsi[0] != 0);
-	osmo_strlcpy(from_peer.imsi, to_peer.imsi, sizeof(from_peer.imsi));
-
-	/* This invalidates the pointers in to_peer */
-	msgb_free(msg);
-
-	switch (to_peer.message_type) {
-	case OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
-		/* Send UPDATE_LOCATION_RESULT */
-		return my_subscr_request_update_gsup_auth(NULL);
-
-	case OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
-		/* Send SEND_AUTH_INFO_RESULT */
-		return my_subscr_request_auth_info_gsup_auth(NULL);
-
-	case OSMO_GSUP_MSGT_PURGE_MS_REQUEST:
-		from_peer.message_type = OSMO_GSUP_MSGT_PURGE_MS_RESULT;
-		break;
-
-	default:
-		if ((to_peer.message_type & 0b00000011) == 0) {
-			/* Unhandled request */
-			/* Send error(NOT_IMPL) */
-			from_peer.message_type = to_peer.message_type + 1;
-			from_peer.cause = GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
-			break;
-		}
-
-		/* Ignore it */
-		return 0;
-	}
-
-	reply_msg = gsup_client_msgb_alloc();
-	reply_msg->l2h = reply_msg->data;
-	osmo_gsup_encode(reply_msg, &from_peer);
-	gprs_subscr_rx_gsup_message(reply_msg);
-	msgb_free(reply_msg);
-
-	return 0;
-};
-
-static void test_gmm_attach_subscr_real_gsup_auth(int retry)
-{
-	const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
-	struct gprs_subscr *subscr;
-
-	sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
-	gsup_client_send_cb = my_gsup_client_send;
-
-	sgsn->gsup_client = talloc_zero(tall_bsc_ctx, struct gsup_client);
-
-	if (retry) {
-		upd_loc_skip = 3;
-		auth_info_skip = 3;
-	}
-
-	printf("Auth policy 'remote', real GSUP based auth: ");
-	test_gmm_attach(retry);
-
-	subscr = gprs_subscr_get_by_imsi("123456789012345");
-	OSMO_ASSERT(subscr == NULL);
-	assert_no_subscrs();
-
-	sgsn->cfg.auth_policy = saved_auth_policy;
-	gsup_client_send_cb = __real_gsup_client_send;
-	upd_loc_skip = 0;
-	auth_info_skip = 0;
-	talloc_free(sgsn->gsup_client);
-	sgsn->gsup_client = NULL;
-
-	cleanup_test();
-}
-
-/*
- * Test the GMM Rejects
- */
-static void test_gmm_reject(void)
-{
-	struct gprs_ra_id raid = { 0, };
-	struct sgsn_mm_ctx *ctx = NULL;
-	uint32_t foreign_tlli;
-	struct gprs_llc_lle *lle;
-	int idx;
-
-	/* DTAP - Attach Request */
-	/* Invalid MI length */
-	static const unsigned char attach_req_inv_mi_len[] = {
-		0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
-		0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
-		0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
-		0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
-		0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
-	};
-
-	/* DTAP - Attach Request */
-	/* Invalid MI type (IMEI) */
-	static const unsigned char attach_req_inv_mi_type[] = {
-		0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
-		0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
-		0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
-		0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
-		0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
-	};
-
-	/* DTAP - Routing Area Update Request */
-	static const unsigned char dtap_ra_upd_req[] = {
-		0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
-		0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
-		0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
-		0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
-		0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
-		0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
-		0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
-	};
-
-	/* DTAP - Routing Area Update Request */
-	/* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
-	static const unsigned char dtap_ra_upd_req_inv_type[] = {
-		0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
-		0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
-		0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
-		0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
-		0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
-		0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
-		0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
-	};
-
-	/* DTAP - Routing Area Update Request */
-	/* Invalid cap length */
-	static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
-		0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
-		0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-		0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
-		0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
-		0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
-		0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
-		0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
-	};
-
-	struct test {
-		const char *title;
-		const unsigned char *msg;
-		unsigned msg_len;
-		unsigned num_resp;
-
-	};
-	static struct test tests[] = {
-		{
-			.title    = "Attach Request (invalid MI length)",
-			.msg      = attach_req_inv_mi_len,
-			.msg_len  = sizeof(attach_req_inv_mi_len),
-			.num_resp = 1 /* Reject */
-
-		},
-		{
-			.title   = "Attach Request (invalid MI type)",
-			.msg     = attach_req_inv_mi_type,
-			.msg_len = sizeof(attach_req_inv_mi_type),
-			.num_resp = 1 /* Reject */
-		},
-		{
-			.title   = "Routing Area Update Request (valid)",
-			.msg     = dtap_ra_upd_req,
-			.msg_len = sizeof(dtap_ra_upd_req),
-			.num_resp = 2 /* XID Reset + Reject */
-		},
-		{
-			.title   = "Routing Area Update Request (invalid type)",
-			.msg     = dtap_ra_upd_req_inv_type,
-			.msg_len = sizeof(dtap_ra_upd_req_inv_type),
-			.num_resp = 1 /* Reject */
-		},
-		{
-			.title   = "Routing Area Update Request (invalid CAP length)",
-			.msg     = dtap_ra_upd_req_inv_cap_len,
-			.msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
-			.num_resp = 1 /* Reject */
-		},
-	};
-
-	printf("Testing GMM reject\n");
-
-	/* reset the PRNG used by sgsn_alloc_ptmsi */
-	srand(1);
-
-	foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
-
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-
-	for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
-		const struct test *test = &tests[idx];
-		printf("  - %s\n", test->title);
-
-		/* Create a LLE/LLME */
-		lle = gprs_lle_get_or_create(foreign_tlli, 3);
-		OSMO_ASSERT(count(gprs_llme_list()) == 1);
-
-		/* Inject the Request message */
-		send_0408_message(lle->llme, foreign_tlli, &raid,
-				  test->msg, test->msg_len);
-
-		/* We expect a Reject message */
-		fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
-			sgsn_tx_counter, test->num_resp);
-		OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
-
-		/* verify that LLME/MM are removed */
-		ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
-		OSMO_ASSERT(ctx == NULL);
-		OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	}
-
-	cleanup_test();
-}
-
-/*
- * Test cancellation of attached MM contexts
- */
-static void test_gmm_cancel(void)
-{
-	struct gprs_ra_id raid = { 0, };
-	struct sgsn_mm_ctx *ctx = NULL;
-	struct sgsn_mm_ctx *ictx;
-	uint32_t ptmsi1;
-	uint32_t foreign_tlli;
-	uint32_t local_tlli = 0;
-	struct gprs_llc_lle *lle;
-	const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
-
-	/* DTAP - Attach Request */
-	/* The P-TMSI is not known by the SGSN */
-	static const unsigned char attach_req[] = {
-		0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
-		0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
-		0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
-		0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
-		0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
-	};
-
-	/* DTAP - Identity Response IMEI */
-	static const unsigned char ident_resp_imei[] = {
-		0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
-		0x56
-	};
-
-	/* DTAP - Identity Response IMSI */
-	static const unsigned char ident_resp_imsi[] = {
-		0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
-		0x54
-	};
-
-	/* DTAP - Attach Complete */
-	static const unsigned char attach_compl[] = {
-		0x08, 0x03
-	};
-
-	printf("Testing cancellation\n");
-
-	sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
-
-	foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
-
-	/* Create a LLE/LLME */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	lle = gprs_lle_get_or_create(foreign_tlli, 3);
-	OSMO_ASSERT(count(gprs_llme_list()) == 1);
-
-	/* inject the attach request */
-	send_0408_message(lle->llme, foreign_tlli, &raid,
-			  attach_req, ARRAY_SIZE(attach_req));
-
-	ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
-	OSMO_ASSERT(ctx != NULL);
-	OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
-
-	/* we expect an identity request (IMEI) */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-
-	/* inject the identity response (IMEI) */
-	send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
-			  ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
-
-	/* we expect an identity request (IMSI) */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-
-	/* inject the identity response (IMSI) */
-	send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
-			  ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
-
-	/* check that the MM context has not been removed due to a failed
-	 * authorization */
-	OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
-
-	OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
-
-	/* we expect an attach accept/reject */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-	ptmsi1 = get_new_ptmsi(&last_dl_parse_ctx);
-	OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
-
-	/* this has been randomly assigned by the SGSN */
-	local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
-
-	/* inject the attach complete */
-	send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
-			  attach_compl, ARRAY_SIZE(attach_compl));
-
-	OSMO_ASSERT(ctx->gmm_state == GMM_REGISTERED_NORMAL);
-
-	/* we don't expect a response */
-	OSMO_ASSERT(sgsn_tx_counter == 0);
-
-	/* cancel */
-	gsm0408_gprs_access_cancelled(ctx, 0);
-
-	/* verify that things are gone */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
-	OSMO_ASSERT(!ictx);
-
-	sgsn->cfg.auth_policy = saved_auth_policy;
-
-	cleanup_test();
-}
-
-/*
- * Test the dynamic allocation of P-TMSIs
- */
-static void test_gmm_ptmsi_allocation(void)
-{
-	struct gprs_ra_id raid = {332, 112, 16464, 96};
-	struct sgsn_mm_ctx *ctx = NULL;
-	struct sgsn_mm_ctx *ictx;
-	uint32_t foreign_tlli;
-	uint32_t ptmsi1;
-	uint32_t ptmsi2;
-	uint32_t received_ptmsi;
-	uint32_t old_ptmsi;
-	uint32_t local_tlli = 0;
-	struct gprs_llc_lle *lle;
-	const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
-
-	/* DTAP - Attach Request (IMSI 12131415161718) */
-	static const unsigned char attach_req[] = {
-		0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
-		0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-		0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
-		0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
-		0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
-		0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
-		0x00,
-	};
-
-	/* DTAP - Identity Response IMEI */
-	static const unsigned char ident_resp_imei[] = {
-		0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
-		0x56
-	};
-
-	/* DTAP - Attach Complete */
-	static const unsigned char attach_compl[] = {
-		0x08, 0x03
-	};
-
-	/* DTAP - Routing Area Update Request */
-	static const unsigned char ra_upd_req[] = {
-		0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
-		0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
-		0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
-		0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
-		0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
-		0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
-		0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
-	};
-
-	/* DTAP - Routing Area Update Complete */
-	static const unsigned char ra_upd_complete[] = {
-		0x08, 0x0a
-	};
-
-	/* DTAP - Detach Request (MO) */
-	/* normal detach, power_off = 1 */
-	static const unsigned char detach_req[] = {
-		0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
-		0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
-	};
-
-	sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
-
-	printf("Testing P-TMSI allocation\n");
-
-	printf("  - sgsn_alloc_ptmsi\n");
-
-	/* reset the PRNG used by sgsn_alloc_ptmsi */
-	srand(1);
-
-	ptmsi1 = sgsn_alloc_ptmsi();
-	OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
-
-	ptmsi2 = sgsn_alloc_ptmsi();
-	OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
-
-	OSMO_ASSERT(ptmsi1 != ptmsi2);
-
-	ptmsi1 = ptmsi2 = GSM_RESERVED_TMSI;
-
-	printf("  - Repeated Attach Request\n");
-
-	foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
-
-	/* Create a LLE/LLME */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	lle = gprs_lle_get_or_create(foreign_tlli, 3);
-	OSMO_ASSERT(count(gprs_llme_list()) == 1);
-
-	/* inject the attach request */
-	send_0408_message(lle->llme, foreign_tlli, &raid,
-			  attach_req, ARRAY_SIZE(attach_req));
-
-	ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
-	OSMO_ASSERT(ctx != NULL);
-	OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
-	OSMO_ASSERT(ctx->p_tmsi != GSM_RESERVED_TMSI);
-	ptmsi1 = ctx->p_tmsi;
-
-	old_ptmsi = ctx->p_tmsi_old;
-
-	/* we expect an identity request (IMEI) */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-
-	/* inject the identity response (IMEI) */
-	send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
-			  ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
-
-	/* check that the MM context has not been removed due to a failed
-	 * authorization */
-	OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
-
-	OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
-	OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
-
-	/* we expect an attach accept */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-	received_ptmsi = get_new_ptmsi(&last_dl_parse_ctx);
-	OSMO_ASSERT(received_ptmsi == ptmsi1);
-
-	/* we ignore this and send the attach again */
-	send_0408_message(lle->llme, foreign_tlli, &raid,
-			  attach_req, ARRAY_SIZE(attach_req));
-
-	/* the allocated P-TMSI should be the same */
-	ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
-	OSMO_ASSERT(ctx != NULL);
-	OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
-	OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
-	OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
-
-	/* we expect an attach accept */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-	received_ptmsi = get_new_ptmsi(&last_dl_parse_ctx);
-	OSMO_ASSERT(received_ptmsi == ptmsi1);
-
-	/* inject the attach complete */
-	local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
-	send_0408_message(ctx->gb.llme, local_tlli, &raid,
-			  attach_compl, ARRAY_SIZE(attach_compl));
-
-	/* we don't expect a response */
-	OSMO_ASSERT(sgsn_tx_counter == 0);
-
-	OSMO_ASSERT(ctx->gmm_state == GMM_REGISTERED_NORMAL);
-	OSMO_ASSERT(ctx->p_tmsi_old == 0);
-	OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
-
-	printf("  - Repeated RA Update Request\n");
-
-	/* inject the RA update request */
-	send_0408_message(ctx->gb.llme, local_tlli, &raid,
-			  ra_upd_req, ARRAY_SIZE(ra_upd_req));
-
-	/* we expect an RA update accept */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-
-	OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
-	OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
-	OSMO_ASSERT(ctx->p_tmsi != GSM_RESERVED_TMSI);
-	OSMO_ASSERT(ctx->p_tmsi != ptmsi1);
-	ptmsi2 = ctx->p_tmsi;
-
-	/* repeat the RA update request */
-	send_0408_message(ctx->gb.llme, local_tlli, &raid,
-			  ra_upd_req, ARRAY_SIZE(ra_upd_req));
-
-	/* we expect an RA update accept */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-	received_ptmsi = get_new_ptmsi(&last_dl_parse_ctx);
-	OSMO_ASSERT(received_ptmsi == ptmsi2);
-
-	OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
-	OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
-	OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
-
-	/* inject the RA update complete */
-	local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
-	send_0408_message(ctx->gb.llme, local_tlli, &raid,
-			  ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
-
-	/* we don't expect a response */
-	OSMO_ASSERT(sgsn_tx_counter == 0);
-
-	OSMO_ASSERT(ctx->gmm_state == GMM_REGISTERED_NORMAL);
-	OSMO_ASSERT(ctx->p_tmsi_old == 0);
-	OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
-
-	/* inject the detach */
-	send_0408_message(ctx->gb.llme, local_tlli, &raid,
-			  detach_req, ARRAY_SIZE(detach_req));
-
-	/* verify that things are gone */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
-	OSMO_ASSERT(!ictx);
-
-	sgsn->cfg.auth_policy = saved_auth_policy;
-
-	cleanup_test();
-}
-
-/*
- * Test changing of routing areas
- */
-static void test_gmm_routing_areas(void)
-{
-	struct gprs_ra_id raid1 = {332, 112, 16464, 96};
-	struct gprs_ra_id raid2 = {332, 112, 16464, 97};
-	struct sgsn_mm_ctx *ctx = NULL;
-	struct sgsn_mm_ctx *ictx;
-	uint32_t ptmsi1;
-	uint32_t received_ptmsi;
-	uint32_t ms_tlli = 0;
-	struct gprs_llc_lle *lle;
-	const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
-
-	/* DTAP - Attach Request (IMSI 12131415161718) */
-	static const unsigned char attach_req[] = {
-		0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
-		0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-		0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
-		0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
-		0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
-		0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
-		0x00,
-	};
-
-	/* DTAP - Attach Request (IMSI 12131415161718) (RA 2) */
-	static const unsigned char attach_req2[] = {
-		0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
-		0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-		0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x61, 0x19,
-		0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
-		0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
-		0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
-		0x00,
-	};
-
-	/* DTAP - Identity Response IMEI */
-	static const unsigned char ident_resp_imei[] = {
-		0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
-		0x56
-	};
-
-	/* DTAP - Attach Complete */
-	static const unsigned char attach_compl[] = {
-		0x08, 0x03
-	};
-
-	/* DTAP - Routing Area Update Request (coming from RA 1) */
-	static const unsigned char ra_upd_req1[] = {
-		0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
-		0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
-		0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
-		0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
-		0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
-		0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
-		0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
-	};
-
-	/* DTAP - Routing Area Update Request (coming from RA 2) */
-	static const unsigned char ra_upd_req2[] = {
-		0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
-		0x61, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
-		0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
-		0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
-		0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
-		0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
-		0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
-	};
-
-	/* DTAP - Routing Area Update Request (coming from RA other) */
-	/* raid_other = {443, 223, 16464, 98}; */
-	static const unsigned char ra_upd_req_other[] = {
-		0x08, 0x08, 0x10, 0x22, 0x33, 0x44, 0x40, 0x50,
-		0x62, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
-		0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
-		0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
-		0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
-		0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
-		0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
-	};
-
-	/* DTAP - Routing Area Update Complete */
-	static const unsigned char ra_upd_complete[] = {
-		0x08, 0x0a
-	};
-
-	/* DTAP - Detach Request (MO) */
-	/* normal detach, power_off = 1 */
-	static const unsigned char detach_req[] = {
-		0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
-		0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
-	};
-
-	sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
-
-	printf("Testing routing area changes\n");
-
-	/* reset the PRNG used by sgsn_alloc_ptmsi */
-	srand(1);
-
-	ptmsi1 = GSM_RESERVED_TMSI;
-
-	printf("  - Attach Request (RA 1)\n");
-
-	ms_tlli = gprs_tmsi2tlli(0x00000023, TLLI_RANDOM);
-
-	/* Create a LLE/LLME */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	lle = gprs_lle_get_or_create(ms_tlli, 3);
-	OSMO_ASSERT(count(gprs_llme_list()) == 1);
-
-	/* inject the attach request */
-	send_0408_message(lle->llme, ms_tlli, &raid1,
-			  attach_req, ARRAY_SIZE(attach_req));
-
-	ctx = sgsn_mm_ctx_by_tlli(ms_tlli, &raid1);
-	OSMO_ASSERT(ctx != NULL);
-	OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
-	OSMO_ASSERT(ctx->p_tmsi != GSM_RESERVED_TMSI);
-
-	/* we expect an identity request (IMEI) */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-	OSMO_ASSERT(last_dl_parse_ctx.g48_hdr->msg_type == GSM48_MT_GMM_ID_REQ);
-	OSMO_ASSERT(last_dl_parse_ctx.tlli == ms_tlli);
-
-	/* inject the identity response (IMEI) */
-	send_0408_message(ctx->gb.llme, ms_tlli, &raid1,
-			  ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
-
-	/* check that the MM context has not been removed due to a failed
-	 * authorization */
-	OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(ms_tlli, &raid1));
-
-	OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
-
-	/* we expect an attach accept */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-	OSMO_ASSERT(last_dl_parse_ctx.g48_hdr->msg_type == GSM48_MT_GMM_ATTACH_ACK);
-	OSMO_ASSERT(last_dl_parse_ctx.tlli == ms_tlli);
-
-	received_ptmsi = get_new_ptmsi(&last_dl_parse_ctx);
-	OSMO_ASSERT(received_ptmsi == ctx->p_tmsi);
-	ptmsi1 = received_ptmsi;
-
-	/* inject the attach complete */
-	ms_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
-	send_0408_message(ctx->gb.llme, ms_tlli, &raid1,
-			  attach_compl, ARRAY_SIZE(attach_compl));
-
-	/* we don't expect a response */
-	OSMO_ASSERT(sgsn_tx_counter == 0);
-
-	OSMO_ASSERT(ctx->gmm_state == GMM_REGISTERED_NORMAL);
-	OSMO_ASSERT(ctx->p_tmsi_old == 0);
-	OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
-
-	printf("  - RA Update Request (RA 1 -> RA 1)\n");
-
-	/* inject the RA update request */
-	send_0408_message(ctx->gb.llme, ms_tlli, &raid1,
-			  ra_upd_req1, ARRAY_SIZE(ra_upd_req1));
-
-	/* we expect an RA update accept */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-	OSMO_ASSERT(last_dl_parse_ctx.g48_hdr->msg_type == GSM48_MT_GMM_RA_UPD_ACK);
-	// OSMO_ASSERT(last_dl_parse_ctx.tlli == ms_tlli);
-
-	OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
-	OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
-	OSMO_ASSERT(ctx->p_tmsi != GSM_RESERVED_TMSI);
-	OSMO_ASSERT(ctx->p_tmsi != ptmsi1);
-
-	received_ptmsi = get_new_ptmsi(&last_dl_parse_ctx);
-	OSMO_ASSERT(received_ptmsi == ctx->p_tmsi);
-	ptmsi1 = received_ptmsi;
-
-	/* inject the RA update complete */
-	ms_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
-	send_0408_message(ctx->gb.llme, ms_tlli, &raid1,
-			  ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
-
-	/* we don't expect a response */
-	OSMO_ASSERT(sgsn_tx_counter == 0);
-
-	OSMO_ASSERT(ctx->gmm_state == GMM_REGISTERED_NORMAL);
-	OSMO_ASSERT(ctx->p_tmsi_old == 0);
-	OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
-	OSMO_ASSERT(ctx->gb.tlli == ms_tlli);
-
-	printf("  - RA Update Request (RA 1 -> RA 2)\n");
-
-	/* inject the RA update request */
-	ms_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_FOREIGN);
-
-	/* It is coming from RA 1 => ra_upd_req1 */
-	send_0408_message(ctx->gb.llme, ms_tlli, &raid2,
-			  ra_upd_req1, ARRAY_SIZE(ra_upd_req1));
-
-	/* we expect an RA update accept */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-	OSMO_ASSERT(last_dl_parse_ctx.g48_hdr->msg_type == GSM48_MT_GMM_RA_UPD_ACK);
-
-	printf("  - RA Update Request (RA other -> RA 2)\n");
-
-	/* inject the RA update request */
-	ms_tlli = gprs_tmsi2tlli(0x12345678, TLLI_FOREIGN);
-
-	/* It is coming from RA 1 => ra_upd_req1 */
-	send_0408_message(ctx->gb.llme, ms_tlli, &raid2,
-			  ra_upd_req_other, ARRAY_SIZE(ra_upd_req_other));
-
-	/* we expect an RA update reject (and a LLC XID RESET) */
-	OSMO_ASSERT(sgsn_tx_counter == 2);
-	OSMO_ASSERT(last_dl_parse_ctx.g48_hdr->msg_type == GSM48_MT_GMM_RA_UPD_REJ);
-	/* this has killed the LLE/LLME */
-
-	printf("  - Attach Request (RA 2)\n");
-
-	/* Create a LLE/LLME */
-	OSMO_ASSERT(count(gprs_llme_list()) == 1);
-	lle = gprs_lle_get_or_create(ms_tlli, 3);
-	OSMO_ASSERT(count(gprs_llme_list()) == 1);
-
-	/* inject the attach request */
-	send_0408_message(lle->llme, ms_tlli, &raid2,
-			  attach_req2, ARRAY_SIZE(attach_req2));
-
-	ctx = sgsn_mm_ctx_by_tlli(ms_tlli, &raid2);
-	OSMO_ASSERT(ctx != NULL);
-	OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
-	OSMO_ASSERT(ctx->p_tmsi != GSM_RESERVED_TMSI);
-
-	/* we expect an attach accept */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-	OSMO_ASSERT(last_dl_parse_ctx.g48_hdr->msg_type == GSM48_MT_GMM_ATTACH_ACK);
-
-	received_ptmsi = get_new_ptmsi(&last_dl_parse_ctx);
-	OSMO_ASSERT(received_ptmsi == ctx->p_tmsi);
-	ptmsi1 = received_ptmsi;
-
-	/* inject the attach complete */
-	ms_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
-	ictx = sgsn_mm_ctx_by_tlli(ms_tlli, &raid2);
-	OSMO_ASSERT(ictx != NULL);
-	OSMO_ASSERT(ictx == ctx);
-
-	send_0408_message(ctx->gb.llme, ms_tlli, &raid2,
-			  attach_compl, ARRAY_SIZE(attach_compl));
-
-	/* we don't expect a response */
-	OSMO_ASSERT(sgsn_tx_counter == 0);
-
-	OSMO_ASSERT(ctx->gmm_state == GMM_REGISTERED_NORMAL);
-	OSMO_ASSERT(ctx->p_tmsi_old == 0);
-	OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
-
-	printf("  - RA Update Request (RA 2 -> RA 2)\n");
-
-	/* inject the RA update request */
-	send_0408_message(ctx->gb.llme, ms_tlli, &raid2,
-			  ra_upd_req2, ARRAY_SIZE(ra_upd_req2));
-
-	/* we expect an RA update accept */
-	OSMO_ASSERT(sgsn_tx_counter == 1);
-	OSMO_ASSERT(last_dl_parse_ctx.g48_hdr->msg_type == GSM48_MT_GMM_RA_UPD_ACK);
-
-	OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
-	OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
-	OSMO_ASSERT(ctx->p_tmsi != GSM_RESERVED_TMSI);
-	OSMO_ASSERT(ctx->p_tmsi != ptmsi1);
-
-	received_ptmsi = get_new_ptmsi(&last_dl_parse_ctx);
-	OSMO_ASSERT(received_ptmsi == ctx->p_tmsi);
-	ptmsi1 = received_ptmsi;
-
-	/* inject the RA update complete */
-	ms_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
-	send_0408_message(ctx->gb.llme, ms_tlli, &raid2,
-			  ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
-
-	/* we don't expect a response */
-	OSMO_ASSERT(sgsn_tx_counter == 0);
-
-	OSMO_ASSERT(ctx->gmm_state == GMM_REGISTERED_NORMAL);
-	OSMO_ASSERT(ctx->p_tmsi_old == 0);
-	OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
-	OSMO_ASSERT(ctx->gb.tlli == ms_tlli);
-
-
-	/* inject the detach */
-	send_0408_message(ctx->gb.llme, ms_tlli, &raid2,
-			  detach_req, ARRAY_SIZE(detach_req));
-
-	/* verify that things are gone */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	ictx = sgsn_mm_ctx_by_tlli(ms_tlli, &raid2);
-	OSMO_ASSERT(!ictx);
-
-	sgsn->cfg.auth_policy = saved_auth_policy;
-
-	cleanup_test();
-}
-
-static void test_apn_matching(void)
-{
-	struct apn_ctx *actx, *actxs[9];
-
-	printf("Testing APN matching\n");
-
-	actxs[0] = sgsn_apn_ctx_find_alloc("*.test", "");
-	actxs[1] = sgsn_apn_ctx_find_alloc("*.def.test", "");
-	actxs[2] = sgsn_apn_ctx_find_alloc("abc.def.test", "");
-	actxs[3] = NULL;
-
-	actxs[4] = sgsn_apn_ctx_find_alloc("abc.def.test", "456");
-	actxs[5] = sgsn_apn_ctx_find_alloc("abc.def.test", "456123");
-	actxs[6] = sgsn_apn_ctx_find_alloc("*.def.test", "456");
-	actxs[7] = sgsn_apn_ctx_find_alloc("*.def.test", "456123");
-
-	actxs[8] = sgsn_apn_ctx_find_alloc("ghi.def.test", "456");
-
-	actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
-	OSMO_ASSERT(actx == actxs[2]);
-	actx = sgsn_apn_ctx_match("aBc.dEf.test", "12345678");
-	OSMO_ASSERT(actx == actxs[2]);
-	actx = sgsn_apn_ctx_match("xyz.def.test", "12345678");
-	OSMO_ASSERT(actx == actxs[1]);
-	actx = sgsn_apn_ctx_match("xyz.dEf.test", "12345678");
-	OSMO_ASSERT(actx == actxs[1]);
-	actx = sgsn_apn_ctx_match("xyz.uvw.test", "12345678");
-	OSMO_ASSERT(actx == actxs[0]);
-	actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
-	OSMO_ASSERT(actx == NULL);
-
-	actxs[3] = sgsn_apn_ctx_find_alloc("*", "");
-	actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
-	OSMO_ASSERT(actx == actxs[3]);
-
-	actx = sgsn_apn_ctx_match("abc.def.test", "45699900");
-	OSMO_ASSERT(actx == actxs[4]);
-
-	actx = sgsn_apn_ctx_match("xyz.def.test", "45699900");
-	OSMO_ASSERT(actx == actxs[6]);
-
-	actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
-	OSMO_ASSERT(actx == actxs[5]);
-
-	actx = sgsn_apn_ctx_match("xyz.def.test", "45612300");
-	OSMO_ASSERT(actx == actxs[7]);
-
-	actx = sgsn_apn_ctx_match("ghi.def.test", "45699900");
-	OSMO_ASSERT(actx == actxs[8]);
-
-	actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
-	OSMO_ASSERT(actx == actxs[7]);
-
-	/* Free APN contexts and check how the matching changes */
-
-	sgsn_apn_ctx_free(actxs[7]);
-	actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
-	OSMO_ASSERT(actx == actxs[8]);
-
-	sgsn_apn_ctx_free(actxs[8]);
-	actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
-	OSMO_ASSERT(actx == actxs[6]);
-
-	sgsn_apn_ctx_free(actxs[6]);
-	actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
-	OSMO_ASSERT(actx == actxs[1]);
-
-	sgsn_apn_ctx_free(actxs[5]);
-	actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
-	OSMO_ASSERT(actx == actxs[4]);
-
-	sgsn_apn_ctx_free(actxs[4]);
-	actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
-	OSMO_ASSERT(actx == actxs[2]);
-
-	sgsn_apn_ctx_free(actxs[2]);
-	actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
-	OSMO_ASSERT(actx == actxs[1]);
-
-	sgsn_apn_ctx_free(actxs[1]);
-	actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
-	OSMO_ASSERT(actx == actxs[0]);
-
-	sgsn_apn_ctx_free(actxs[0]);
-	actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
-	OSMO_ASSERT(actx == actxs[3]);
-
-	sgsn_apn_ctx_free(actxs[3]);
-	actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
-	OSMO_ASSERT(actx == NULL);
-
-	cleanup_test();
-}
-
-struct sgsn_subscriber_pdp_data* sgsn_subscriber_pdp_data_alloc(
-	struct sgsn_subscriber_data *sdata);
-
-static void test_ggsn_selection(void)
-{
-	struct apn_ctx *actxs[4];
-	struct sgsn_ggsn_ctx *ggc, *ggcs[3];
-	struct gprs_subscr *s1;
-	const char *imsi1 = "1234567890";
-	struct sgsn_mm_ctx *ctx;
-	struct gprs_ra_id raid = { 0, };
-	uint32_t local_tlli = 0xffeeddcc;
-	enum gsm48_gsm_cause gsm_cause;
-	struct tlv_parsed tp;
-	uint8_t apn_enc[GSM_APN_LENGTH + 10];
-	struct sgsn_subscriber_pdp_data *pdp_data;
-	char apn_str[GSM_APN_LENGTH];
-
-	printf("Testing GGSN selection\n");
-
-	gsup_client_send_cb = my_gsup_client_send_dummy;
-
-	/* Check for emptiness */
-	OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
-
-	/* Create a context */
-	OSMO_ASSERT(count(gprs_llme_list()) == 0);
-	ctx = alloc_mm_ctx(local_tlli, &raid);
-	osmo_strlcpy(ctx->imsi, imsi1, sizeof(ctx->imsi));
-
-	/* Allocate and attach a subscriber */
-	s1 = gprs_subscr_get_or_create_by_mmctx(ctx);
-	assert_subscr(s1, imsi1);
-
-	tp.lv[GSM48_IE_GSM_APN].len = 0;
-	tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
-
-	/* TODO: Add PDP info entries to s1 */
-
-	ggcs[0] = sgsn_ggsn_ctx_find_alloc(0);
-	ggcs[1] = sgsn_ggsn_ctx_find_alloc(1);
-	ggcs[2] = sgsn_ggsn_ctx_find_alloc(2);
-
-	actxs[0] = sgsn_apn_ctx_find_alloc("test.apn", "123456");
-	actxs[0]->ggsn = ggcs[0];
-	actxs[1] = sgsn_apn_ctx_find_alloc("*.apn", "123456");
-	actxs[1]->ggsn = ggcs[1];
-	actxs[2] = sgsn_apn_ctx_find_alloc("*", "456789");
-	actxs[2]->ggsn = ggcs[2];
-
-	pdp_data = sgsn_subscriber_pdp_data_alloc(s1->sgsn_data);
-	pdp_data->context_id = 1;
-	pdp_data->pdp_type = 0x0121;
-	osmo_strlcpy(pdp_data->apn_str, "*", sizeof(pdp_data->apn_str));
-
-	/* Resolve GGSNs */
-
-	tp.lv[GSM48_IE_GSM_APN].len =
-		gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
-
-	ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
-	OSMO_ASSERT(ggc != NULL);
-	OSMO_ASSERT(ggc->id == 0);
-	OSMO_ASSERT(strcmp(apn_str, "Test.Apn") == 0);
-
-	tp.lv[GSM48_IE_GSM_APN].len =
-		gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
-
-	ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
-	OSMO_ASSERT(ggc != NULL);
-	OSMO_ASSERT(ggc->id == 1);
-	OSMO_ASSERT(strcmp(apn_str, "Other.Apn") == 0);
-
-	tp.lv[GSM48_IE_GSM_APN].len = 0;
-	tp.lv[GSM48_IE_GSM_APN].val = NULL;
-
-	ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
-	OSMO_ASSERT(ggc != NULL);
-	OSMO_ASSERT(ggc->id == 0);
-	OSMO_ASSERT(strcmp(apn_str, "") == 0);
-
-	actxs[3] = sgsn_apn_ctx_find_alloc("*", "123456");
-	actxs[3]->ggsn = ggcs[2];
-	ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
-	OSMO_ASSERT(ggc != NULL);
-	OSMO_ASSERT(ggc->id == 2);
-	OSMO_ASSERT(strcmp(apn_str, "") == 0);
-
-	sgsn_apn_ctx_free(actxs[3]);
-	tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
-
-	tp.lv[GSM48_IE_GSM_APN].len =
-		gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Foo.Bar");
-
-	ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
-	OSMO_ASSERT(ggc == NULL);
-	OSMO_ASSERT(gsm_cause == GSM_CAUSE_MISSING_APN);
-	OSMO_ASSERT(strcmp(apn_str, "Foo.Bar") == 0);
-
-	tp.lv[GSM48_IE_GSM_APN].len = sizeof(apn_enc);
-	ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
-	OSMO_ASSERT(ggc == NULL);
-	OSMO_ASSERT(gsm_cause == GSM_CAUSE_INV_MAND_INFO);
-
-	/* Add PDP data entry to subscriber */
-
-	osmo_strlcpy(pdp_data->apn_str, "Test.Apn", sizeof(pdp_data->apn_str));
-
-	tp.lv[GSM48_IE_GSM_APN].len =
-		gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
-
-	ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
-	OSMO_ASSERT(ggc != NULL);
-	OSMO_ASSERT(ggc->id == 0);
-	OSMO_ASSERT(strcmp(apn_str, "Test.Apn") == 0);
-
-	tp.lv[GSM48_IE_GSM_APN].len =
-		gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
-
-	ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
-	OSMO_ASSERT(ggc == NULL);
-	OSMO_ASSERT(gsm_cause == GSM_CAUSE_REQ_SERV_OPT_NOTSUB);
-	OSMO_ASSERT(strcmp(apn_str, "") == 0);
-
-	/* Cleanup */
-
-	gprs_subscr_put(s1);
-	sgsn_mm_ctx_cleanup_free(ctx);
-
-	assert_no_subscrs();
-
-	sgsn_apn_ctx_free(actxs[0]);
-	sgsn_apn_ctx_free(actxs[1]);
-	sgsn_apn_ctx_free(actxs[2]);
-
-	sgsn_ggsn_ctx_free(ggcs[0]);
-	sgsn_ggsn_ctx_free(ggcs[1]);
-	sgsn_ggsn_ctx_free(ggcs[2]);
-
-	gsup_client_send_cb = __real_gsup_client_send;
-
-	cleanup_test();
-}
-
-static struct log_info_cat gprs_categories[] = {
-	[DMM] = {
-		.name = "DMM",
-		.description = "Layer3 Mobility Management (MM)",
-		.color = "\033[1;33m",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DPAG]	= {
-		.name = "DPAG",
-		.description = "Paging Subsystem",
-		.color = "\033[1;38m",
-		.enabled = 1, .loglevel = LOGL_NOTICE,
-	},
-	[DMEAS] = {
-		.name = "DMEAS",
-		.description = "Radio Measurement Processing",
-		.enabled = 0, .loglevel = LOGL_NOTICE,
-	},
-	[DREF] = {
-		.name = "DREF",
-		.description = "Reference Counting",
-		.enabled = 0, .loglevel = LOGL_NOTICE,
-	},
-	[DGPRS] = {
-		.name = "DGPRS",
-		.description = "GPRS Packet Service",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DNS] = {
-		.name = "DNS",
-		.description = "GPRS Network Service (NS)",
-		.enabled = 1, .loglevel = LOGL_INFO,
-	},
-	[DBSSGP] = {
-		.name = "DBSSGP",
-		.description = "GPRS BSS Gateway Protocol (BSSGP)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DLLC] = {
-		.name = "DLLC",
-		.description = "GPRS Logical Link Control Protocol (LLC)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-	[DSNDCP] = {
-		.name = "DSNDCP",
-		.description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
-		.enabled = 1, .loglevel = LOGL_DEBUG,
-	},
-};
-
-static struct log_info info = {
-	.cat = gprs_categories,
-	.num_cat = ARRAY_SIZE(gprs_categories),
-};
-
-int main(int argc, char **argv)
-{
-	void *osmo_sgsn_ctx;
-	void *msgb_ctx;
-
-	osmo_init_logging(&info);
-	osmo_sgsn_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
-	tall_bsc_ctx = talloc_named_const(osmo_sgsn_ctx, 0, "bsc");
-	msgb_ctx = msgb_talloc_ctx_init(osmo_sgsn_ctx, 0);
-
-	sgsn_rate_ctr_init();
-	sgsn_auth_init();
-	gprs_subscr_init(sgsn);
-
-	test_llme();
-	test_subscriber();
-	test_auth_triplets();
-	test_subscriber_gsup();
-	test_gmm_detach();
-	test_gmm_detach_power_off();
-	test_gmm_detach_no_mmctx();
-	test_gmm_detach_accept_unexpected();
-	test_gmm_status_no_mmctx();
-	test_gmm_attach_acl();
-	test_gmm_attach_subscr();
-	test_gmm_attach_subscr_fake_auth();
-	test_gmm_attach_subscr_real_auth();
-	test_gmm_attach_subscr_gsup_auth(0);
-	test_gmm_attach_subscr_gsup_auth(1);
-	test_gmm_attach_subscr_real_gsup_auth(0);
-	test_gmm_reject();
-	test_gmm_cancel();
-	test_gmm_ptmsi_allocation();
-	test_gmm_routing_areas();
-	test_apn_matching();
-	test_ggsn_selection();
-	printf("Done\n");
-
-	talloc_report_full(osmo_sgsn_ctx, stderr);
-	OSMO_ASSERT(talloc_total_blocks(msgb_ctx) == 1);
-	OSMO_ASSERT(talloc_total_blocks(tall_bsc_ctx) == 2);
-	return 0;
-}
-
-
-/* stubs */
-struct osmo_prim_hdr;
-int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
-{
-	abort();
-}
diff --git a/tests/sgsn/sgsn_test.ok b/tests/sgsn/sgsn_test.ok
deleted file mode 100644
index f38d730..0000000
--- a/tests/sgsn/sgsn_test.ok
+++ /dev/null
@@ -1,45 +0,0 @@
-Testing LLME allocations
-Testing core subscriber data API
-llist_count(gprs_subscribers) == 0
-llist_count(gprs_subscribers) == 1
-llist_count(gprs_subscribers) == 1
-llist_count(gprs_subscribers) == 2
-llist_count(gprs_subscribers) == 3
-llist_count(gprs_subscribers) == 2
-llist_count(gprs_subscribers) == 1
-llist_count(gprs_subscribers) == 0
-Testing authentication triplet handling
-Testing subscriber GSUP handling
-Testing GMM detach
-Testing GMM detach (power off)
-Testing GMM detach (no MMCTX)
-Testing GMM detach accept (unexpected)
-Testing GMM Status (no MMCTX)
-Auth policy 'closed': Testing GMM attach
-Auth policy 'remote': Testing GMM attach
-Auth policy 'remote', auth faked: Testing GMM attach
-Auth policy 'remote', triplet based auth: Testing GMM attach
-Auth policy 'remote', GSUP based auth: Testing GMM attach
-Auth policy 'remote', GSUP based auth: Testing GMM attach with retry
-Auth policy 'remote', real GSUP based auth: Testing GMM attach
-Testing GMM reject
-  - Attach Request (invalid MI length)
-  - Attach Request (invalid MI type)
-  - Routing Area Update Request (valid)
-  - Routing Area Update Request (invalid type)
-  - Routing Area Update Request (invalid CAP length)
-Testing cancellation
-Testing P-TMSI allocation
-  - sgsn_alloc_ptmsi
-  - Repeated Attach Request
-  - Repeated RA Update Request
-Testing routing area changes
-  - Attach Request (RA 1)
-  - RA Update Request (RA 1 -> RA 1)
-  - RA Update Request (RA 1 -> RA 2)
-  - RA Update Request (RA other -> RA 2)
-  - Attach Request (RA 2)
-  - RA Update Request (RA 2 -> RA 2)
-Testing APN matching
-Testing GGSN selection
-Done
diff --git a/tests/slhc/Makefile.am b/tests/slhc/Makefile.am
deleted file mode 100644
index 32a3cc4..0000000
--- a/tests/slhc/Makefile.am
+++ /dev/null
@@ -1,15 +0,0 @@
-AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
-AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBCARES_CFLAGS)
-
-EXTRA_DIST = slhc_test.ok
-
-noinst_PROGRAMS = slhc_test
-
-slhc_test_SOURCES = slhc_test.c
-
-slhc_test_LDADD = \
-	$(top_builddir)/src/gprs/slhc.o \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS)
-
-
diff --git a/tests/slhc/slhc_test.c b/tests/slhc/slhc_test.c
deleted file mode 100644
index d2e1cd9..0000000
--- a/tests/slhc/slhc_test.c
+++ /dev/null
@@ -1,272 +0,0 @@
-/* Test SLHC/RFC1144 TCP/IP Header compression/decompression */
-
-/* (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/>.
- */
-
-#include <openbsc/slhc.h>
-#include <openbsc/debug.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-
-#include <osmocom/core/application.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <arpa/inet.h>
-
-/* Number of compression slots (S0-1) */
-#define SLOTS 8
-
-/* Maximum packet bytes to display */
-#define DISP_MAX_BYTES 100
-
-/* Sample packets to test with */
-#define PACKETS_LEN 15
-char *packets[] = {
-	/* With TCP Option 10 (Timestamps) in place (forces UNCOMPRESSED_TCP) */
-	"4510004046dd40004006a9a7c0a8646ec0a864640017ad8b81980100f3ac984d801800e32a1600000101080a000647de06d1bf5efffd18fffd20fffd23fffd27",
-	"4510005b46de40004006a98bc0a8646ec0a864640017ad8b8198010cf3ac984d801800e3867500000101080a000647df06d1bf61fffb03fffd1ffffd21fffe22fffb05fffa2001fff0fffa2301fff0fffa2701fff0fffa1801fff0",
-	"4510003746df40004006a9aec0a8646ec0a864640017ad8b81980133f3ac989f801800e35fd700000101080a000647e106d1bf63fffd01",
-	"4510003746e040004006a9adc0a8646ec0a864640017ad8b81980136f3ac98a2801800e35fd200000101080a000647e106d1bf64fffb01",
-	"4510007446e140004006a96fc0a8646ec0a864640017ad8b81980139f3ac98a5801800e37b9b00000101080a000647e206d1bf640d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a57656c6c636f6d6520746f20706f6c6c75780d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a0d0a",
-	"4510004246e240004006a9a0c0a8646ec0a864640017ad8b81980179f3ac98a5801800e3dab000000101080a000647ec06d1bf6f706f6c6c7578206c6f67696e3a20",
-	/* Regular TCP packets (COMPRESSED_TCP) */
-	"4510003446dd40004006a9b3c0a8646ec0a864640017ad8b81980100f3ac984d501800e371410000fffd18fffd20fffd23fffd27",
-	"4510004f46de40004006a997c0a8646ec0a864640017ad8b8198010cf3ac984d501800e3cda40000fffb03fffd1ffffd21fffe22fffb05fffa2001fff0fffa2301fff0fffa2701fff0fffa1801fff0",
-	"4510002b46df40004006a9bac0a8646ec0a864640017ad8b81980133f3ac989f501800e3a70a0000fffd01",
-	"4510002b46e040004006a9b9c0a8646ec0a864640017ad8b81980136f3ac98a2501800e3a7060000fffb01",
-	"4510006846e140004006a97bc0a8646ec0a864640017ad8b81980139f3ac98a5501800e3c2d000000d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a57656c6c636f6d6520746f20706f6c6c75780d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a0d0a",
-	"4510003646e240004006a9acc0a8646ec0a864640017ad8b81980179f3ac98a5501800e321fb0000706f6c6c7578206c6f67696e3a20",
-	/* UDP packets (TYPE_IP */
-	"450000396e0b40004011a0310a0901650a09170105da003500255489a60f01000001000000000000076f736d6f636f6d036f72670000010001",
-	"450000dc9eeb00004011aeae0a0917010a090165003505da00c83fbaa60f81800001000100030004076f736d6f636f6d036f72670000010001c00c00010001000079be0004904c2b4cc00c000200010000173d00130773756e6265616d08676e756d6f6e6b73c014c00c000200010000173d000603646e73c041c00c000200010000173d000a0767616e65736861c041c058000100010000173d0004d55f2e45c058001c00010000173d0010200107800045f0460000000000690001c06a0001000100006a710004d55f1b78c039000100010000173d000453ecb2cb",
-	"45000037652340004011a91b0a0901650a091701ef1b0035002376a2c3910100000100000000000006676f6f676c650264650000010001",
-	"0050b6162c10000db93a3ff908004500004726a6000038114083080808080a0901650035ef1b00338a8cc3918180000100010000000006676f6f676c650264650000010001c00c000100010000012b0004d83ad503",
-};
-
-/* Compress a packet using Van Jacobson RFC1144 header compression */
-static int compress(uint8_t *data_o, uint8_t *data_i, int len,
-		    struct slcompress *comp)
-{
-	uint8_t *comp_ptr;	/* Not used */
-	int compr_len;
-
-	/* Create a working copy of the incoming data */
-	memcpy(data_o, data_i, len);
-
-	/* Run compressor */
-	compr_len = slhc_compress(comp, data_i, len, data_o, &comp_ptr, 0);
-	return compr_len;
-}
-
-/* Expand a packet using Van Jacobson RFC1144 header compression */
-static int expand(uint8_t *data_o, uint8_t *data_i, int len,
-		  struct slcompress *comp)
-{
-	int data_decompressed_len;
-
-	/* Create a working copy of the incoming data */
-	memcpy(data_o, data_i, len);
-
-	/* Handle an uncompressed packet (learn header information */
-	if ((data_i[0] & SL_TYPE_UNCOMPRESSED_TCP) == SL_TYPE_UNCOMPRESSED_TCP) {
-		data_o[0] &= 0x4F;
-		data_decompressed_len = slhc_remember(comp, data_o, len);
-		return data_decompressed_len;
-	}
-
-	/* Uncompress compressed packets */
-	else if (data_o[0] & SL_TYPE_COMPRESSED_TCP) {
-		data_decompressed_len = slhc_uncompress(comp, data_o, len);
-		return data_decompressed_len;
-	}
-
-	/* Regular or unknown packets will not be touched */
-	return len;
-}
-
-/* Calculate IP Header checksum */
-static uint16_t calc_ip_csum(uint8_t *data, int len)
-{
-	int i;
-	uint32_t accumulator = 0;
-	uint16_t *pointer = (uint16_t *) data;
-
-	for (i = len; i > 1; i -= 2) {
-		accumulator += *pointer;
-		pointer++;
-	}
-
-	if (len % 2)
-		accumulator += *pointer;
-
-	accumulator = (accumulator & 0xffff) + ((accumulator >> 16) & 0xffff);
-	accumulator += (accumulator >> 16) & 0xffff;
-	return (~accumulator);
-}
-
-/* Calculate TCP/IP checksum */
-static uint16_t calc_tcpip_csum(const void *ctx, uint8_t *packet, int len)
-{
-	uint8_t *buf;
-	uint16_t csum;
-
-	buf = talloc_zero_size(ctx, len);
-	memset(buf, 0, len);
-	memcpy(buf, packet + 12, 8);
-	buf[9] = packet[9];
-	buf[11] = (len - 20) & 0xFF;
-	buf[10] = (len - 20) >> 8 & 0xFF;
-	memcpy(buf + 12, packet + 20, len - 20);
-	csum = calc_ip_csum(buf, len - 20 + 12);
-	talloc_free(buf);
-	return csum;
-}
-
-/* Check TCP/IP packet */
-static void check_packet(const void *ctx, uint8_t *packet, int len)
-{
-	/* Check IP header */
-	OSMO_ASSERT(len > 20);
-	OSMO_ASSERT(calc_ip_csum(packet, 20) == 0);
-
-	printf("packet[9]=%02x\n", packet[9]);
-
-	/* Check TCP packet */
-	if (packet[9] != 0x06)
-		return;
-	OSMO_ASSERT(len > 40);
-	OSMO_ASSERT(calc_tcpip_csum(ctx, packet, len) == 0);
-}
-
-/* Compress / Decompress packets */
-static void test_slhc(const void *ctx)
-{
-	char packet_ascii[2048];
-	int i;
-
-	struct slcompress *comp;
-	uint8_t packet[1024];
-	int packet_len;
-	uint8_t packet_compr[1024];
-	int packet_compr_len;
-	uint8_t packet_decompr[1024];
-	int packet_decompr_len;
-
-	printf("Allocating compression state...\n");
-	comp = slhc_init(ctx, SLOTS, SLOTS);
-	OSMO_ASSERT(comp);
-
-	for (i = 0; i < PACKETS_LEN; i++) {
-		printf("Testing with packet No. %d\n", i);
-
-		/* Read input file */
-		memset(packet_ascii, 0, sizeof(packet_ascii));
-		memset(packet, 0, sizeof(packet));
-		memset(packet_compr, 0, sizeof(packet_compr));
-		memset(packet_decompr, 0, sizeof(packet_decompr));
-
-		OSMO_ASSERT(strlen(packets[i]) < sizeof(packet_ascii));
-		strcpy(packet_ascii, packets[i]);
-
-		packet_len =
-		    osmo_hexparse(packet_ascii, packet, sizeof(packet));
-		check_packet(ctx, packet, packet_len);
-
-		/* Run compression/decompression algorithm */
-		printf("Compressing...\n");
-		packet_compr_len =
-		    compress(packet_compr, packet, packet_len, comp);
-		printf("Decompressing...\n");
-		packet_decompr_len =
-		    expand(packet_decompr, packet_compr, packet_compr_len,
-			   comp);
-		OSMO_ASSERT(packet_decompr_len == packet_len);
-		check_packet(ctx, packet_decompr, packet_decompr_len);
-
-		/* Display results */
-		printf("Results:\n");
-		if (packet_compr_len > DISP_MAX_BYTES)
-			packet_compr_len = DISP_MAX_BYTES;
-		if (packet_len > DISP_MAX_BYTES)
-			packet_len = DISP_MAX_BYTES;
-		if (packet_decompr_len > DISP_MAX_BYTES)
-			packet_decompr_len = DISP_MAX_BYTES;
-		printf("Original Packet:    (%i bytes) %s\n", packet_len,
-		       osmo_hexdump_nospc(packet, packet_len));
-		printf("DecompressedPacket: (%i bytes) %s\n",
-		       packet_decompr_len, osmo_hexdump_nospc(packet_decompr,
-							      packet_decompr_len));
-		printf("CompressedPacket:   (%i bytes) %s\n", packet_compr_len,
-		       osmo_hexdump_nospc(packet_compr, packet_compr_len));
-		slhc_o_status(comp);
-		slhc_o_status(comp);
-
-		printf("\n");
-	}
-
-	printf("Freeing compression state...\n");
-	slhc_free(comp);
-	printf("\n");
-}
-
-static struct log_info_cat gprs_categories[] = {
-	[DSNDCP] = {
-		    .name = "DSNDCP",
-		    .description =
-		    "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
-		    .enabled = 1,.loglevel = LOGL_DEBUG,
-		    },
-	[DSLHC] = {
-		   .name = "DSLHC",
-		   .description =
-		   "Van Jacobson RFC1144 TCP/IP header compression (SLHC)",
-		   .enabled = 1,.loglevel = LOGL_DEBUG,
-		   }
-};
-
-static struct log_info info = {
-	.cat = gprs_categories,
-	.num_cat = ARRAY_SIZE(gprs_categories),
-};
-
-int main(int argc, char **argv)
-{
-	void *ctx;
-
-	osmo_init_logging(&info);
-
-	ctx = talloc_named_const(NULL, 0, "slhc_ctx");
-
-	test_slhc(ctx);
-
-	printf("Done\n");
-
-	talloc_report_full(ctx, stderr);
-	OSMO_ASSERT(talloc_total_blocks(ctx) == 1);
-	return 0;
-}
-
-/* stubs */
-struct osmo_prim_hdr;
-int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
-{
-	abort();
-}
diff --git a/tests/slhc/slhc_test.ok b/tests/slhc/slhc_test.ok
deleted file mode 100644
index 71f48a1..0000000
--- a/tests/slhc/slhc_test.ok
+++ /dev/null
@@ -1,154 +0,0 @@
-Allocating compression state...
-Testing with packet No. 0
-packet[9]=06
-Compressing...
-Decompressing...
-packet[9]=06
-Results:
-Original Packet:    (64 bytes) 4510004046dd40004006a9a7c0a8646ec0a864640017ad8b81980100f3ac984d801800e32a1600000101080a000647de06d1bf5efffd18fffd20fffd23fffd27
-DecompressedPacket: (64 bytes) 4510004046dd40004006a9a7c0a8646ec0a864640017ad8b81980100f3ac984d801800e32a1600000101080a000647de06d1bf5efffd18fffd20fffd23fffd27
-CompressedPacket:   (64 bytes) 7510004046dd40004000a9a7c0a8646ec0a864640017ad8b81980100f3ac984d801800e32a1600000101080a000647de06d1bf5efffd18fffd20fffd23fffd27
-
-Testing with packet No. 1
-packet[9]=06
-Compressing...
-Decompressing...
-packet[9]=06
-Results:
-Original Packet:    (91 bytes) 4510005b46de40004006a98bc0a8646ec0a864640017ad8b8198010cf3ac984d801800e3867500000101080a000647df06d1bf61fffb03fffd1ffffd21fffe22fffb05fffa2001fff0fffa2301fff0fffa2701fff0fffa1801fff0
-DecompressedPacket: (91 bytes) 4510005b46de40004006a98bc0a8646ec0a864640017ad8b8198010cf3ac984d801800e3867500000101080a000647df06d1bf61fffb03fffd1ffffd21fffe22fffb05fffa2001fff0fffa2301fff0fffa2701fff0fffa1801fff0
-CompressedPacket:   (91 bytes) 7510005b46de40004000a98bc0a8646ec0a864640017ad8b8198010cf3ac984d801800e3867500000101080a000647df06d1bf61fffb03fffd1ffffd21fffe22fffb05fffa2001fff0fffa2301fff0fffa2701fff0fffa1801fff0
-
-Testing with packet No. 2
-packet[9]=06
-Compressing...
-Decompressing...
-packet[9]=06
-Results:
-Original Packet:    (55 bytes) 4510003746df40004006a9aec0a8646ec0a864640017ad8b81980133f3ac989f801800e35fd700000101080a000647e106d1bf63fffd01
-DecompressedPacket: (55 bytes) 4510003746df40004006a9aec0a8646ec0a864640017ad8b81980133f3ac989f801800e35fd700000101080a000647e106d1bf63fffd01
-CompressedPacket:   (55 bytes) 7510003746df40004000a9aec0a8646ec0a864640017ad8b81980133f3ac989f801800e35fd700000101080a000647e106d1bf63fffd01
-
-Testing with packet No. 3
-packet[9]=06
-Compressing...
-Decompressing...
-packet[9]=06
-Results:
-Original Packet:    (55 bytes) 4510003746e040004006a9adc0a8646ec0a864640017ad8b81980136f3ac98a2801800e35fd200000101080a000647e106d1bf64fffb01
-DecompressedPacket: (55 bytes) 4510003746e040004006a9adc0a8646ec0a864640017ad8b81980136f3ac98a2801800e35fd200000101080a000647e106d1bf64fffb01
-CompressedPacket:   (55 bytes) 7510003746e040004000a9adc0a8646ec0a864640017ad8b81980136f3ac98a2801800e35fd200000101080a000647e106d1bf64fffb01
-
-Testing with packet No. 4
-packet[9]=06
-Compressing...
-Decompressing...
-packet[9]=06
-Results:
-Original Packet:    (100 bytes) 4510007446e140004006a96fc0a8646ec0a864640017ad8b81980139f3ac98a5801800e37b9b00000101080a000647e206d1bf640d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a57656c6c636f6d6520746f20706f6c6c75780d0a2d2d2d2d2d2d
-DecompressedPacket: (100 bytes) 4510007446e140004006a96fc0a8646ec0a864640017ad8b81980139f3ac98a5801800e37b9b00000101080a000647e206d1bf640d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a57656c6c636f6d6520746f20706f6c6c75780d0a2d2d2d2d2d2d
-CompressedPacket:   (100 bytes) 7510007446e140004000a96fc0a8646ec0a864640017ad8b81980139f3ac98a5801800e37b9b00000101080a000647e206d1bf640d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a57656c6c636f6d6520746f20706f6c6c75780d0a2d2d2d2d2d2d
-
-Testing with packet No. 5
-packet[9]=06
-Compressing...
-Decompressing...
-packet[9]=06
-Results:
-Original Packet:    (66 bytes) 4510004246e240004006a9a0c0a8646ec0a864640017ad8b81980179f3ac98a5801800e3dab000000101080a000647ec06d1bf6f706f6c6c7578206c6f67696e3a20
-DecompressedPacket: (66 bytes) 4510004246e240004006a9a0c0a8646ec0a864640017ad8b81980179f3ac98a5801800e3dab000000101080a000647ec06d1bf6f706f6c6c7578206c6f67696e3a20
-CompressedPacket:   (66 bytes) 7510004246e240004000a9a0c0a8646ec0a864640017ad8b81980179f3ac98a5801800e3dab000000101080a000647ec06d1bf6f706f6c6c7578206c6f67696e3a20
-
-Testing with packet No. 6
-packet[9]=06
-Compressing...
-Decompressing...
-packet[9]=06
-Results:
-Original Packet:    (52 bytes) 4510003446dd40004006a9b3c0a8646ec0a864640017ad8b81980100f3ac984d501800e371410000fffd18fffd20fffd23fffd27
-DecompressedPacket: (52 bytes) 4510003446dd40004006a9b3c0a8646ec0a864640017ad8b81980100f3ac984d501800e371410000fffd18fffd20fffd23fffd27
-CompressedPacket:   (52 bytes) 7510003446dd40004000a9b3c0a8646ec0a864640017ad8b81980100f3ac984d501800e371410000fffd18fffd20fffd23fffd27
-
-Testing with packet No. 7
-packet[9]=06
-Compressing...
-Decompressing...
-packet[9]=06
-Results:
-Original Packet:    (79 bytes) 4510004f46de40004006a997c0a8646ec0a864640017ad8b8198010cf3ac984d501800e3cda40000fffb03fffd1ffffd21fffe22fffb05fffa2001fff0fffa2301fff0fffa2701fff0fffa1801fff0
-DecompressedPacket: (79 bytes) 4510004f46de40004006a997c0a8646ec0a864640017ad8b8198010cf3ac984d501800e3cda40000fffb03fffd1ffffd21fffe22fffb05fffa2001fff0fffa2301fff0fffa2701fff0fffa1801fff0
-CompressedPacket:   (43 bytes) df00cda4fffb03fffd1ffffd21fffe22fffb05fffa2001fff0fffa2301fff0fffa2701fff0fffa1801fff0
-
-Testing with packet No. 8
-packet[9]=06
-Compressing...
-Decompressing...
-packet[9]=06
-Results:
-Original Packet:    (43 bytes) 4510002b46df40004006a9bac0a8646ec0a864640017ad8b81980133f3ac989f501800e3a70a0000fffd01
-DecompressedPacket: (43 bytes) 4510002b46df40004006a9bac0a8646ec0a864640017ad8b81980133f3ac989f501800e3a70a0000fffd01
-CompressedPacket:   (9 bytes) dc00a70a5227fffd01
-
-Testing with packet No. 9
-packet[9]=06
-Compressing...
-Decompressing...
-packet[9]=06
-Results:
-Original Packet:    (43 bytes) 4510002b46e040004006a9b9c0a8646ec0a864640017ad8b81980136f3ac98a2501800e3a7060000fffb01
-DecompressedPacket: (43 bytes) 4510002b46e040004006a9b9c0a8646ec0a864640017ad8b81980136f3ac98a2501800e3a7060000fffb01
-CompressedPacket:   (7 bytes) db00a706fffb01
-
-Testing with packet No. 10
-packet[9]=06
-Compressing...
-Decompressing...
-packet[9]=06
-Results:
-Original Packet:    (100 bytes) 4510006846e140004006a97bc0a8646ec0a864640017ad8b81980139f3ac98a5501800e3c2d000000d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a57656c6c636f6d6520746f20706f6c6c75780d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
-DecompressedPacket: (100 bytes) 4510006846e140004006a97bc0a8646ec0a864640017ad8b81980139f3ac98a5501800e3c2d000000d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a57656c6c636f6d6520746f20706f6c6c75780d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d
-CompressedPacket:   (68 bytes) db00c2d00d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a57656c6c636f6d6520746f20706f6c6c75780d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a0d0a
-
-Testing with packet No. 11
-packet[9]=06
-Compressing...
-Decompressing...
-packet[9]=06
-Results:
-Original Packet:    (54 bytes) 4510003646e240004006a9acc0a8646ec0a864640017ad8b81980179f3ac98a5501800e321fb0000706f6c6c7578206c6f67696e3a20
-DecompressedPacket: (54 bytes) 4510003646e240004006a9acc0a8646ec0a864640017ad8b81980179f3ac98a5501800e321fb0000706f6c6c7578206c6f67696e3a20
-CompressedPacket:   (18 bytes) df0021fb706f6c6c7578206c6f67696e3a20
-
-Testing with packet No. 12
-packet[9]=11
-Compressing...
-Decompressing...
-packet[9]=11
-Results:
-Original Packet:    (57 bytes) 450000396e0b40004011a0310a0901650a09170105da003500255489a60f01000001000000000000076f736d6f636f6d036f72670000010001
-DecompressedPacket: (57 bytes) 450000396e0b40004011a0310a0901650a09170105da003500255489a60f01000001000000000000076f736d6f636f6d036f72670000010001
-CompressedPacket:   (57 bytes) 450000396e0b40004011a0310a0901650a09170105da003500255489a60f01000001000000000000076f736d6f636f6d036f72670000010001
-
-Testing with packet No. 13
-packet[9]=11
-Compressing...
-Decompressing...
-packet[9]=11
-Results:
-Original Packet:    (100 bytes) 450000dc9eeb00004011aeae0a0917010a090165003505da00c83fbaa60f81800001000100030004076f736d6f636f6d036f72670000010001c00c00010001000079be0004904c2b4cc00c000200010000173d00130773756e6265616d08676e756d6f6e
-DecompressedPacket: (100 bytes) 450000dc9eeb00004011aeae0a0917010a090165003505da00c83fbaa60f81800001000100030004076f736d6f636f6d036f72670000010001c00c00010001000079be0004904c2b4cc00c000200010000173d00130773756e6265616d08676e756d6f6e
-CompressedPacket:   (100 bytes) 450000dc9eeb00004011aeae0a0917010a090165003505da00c83fbaa60f81800001000100030004076f736d6f636f6d036f72670000010001c00c00010001000079be0004904c2b4cc00c000200010000173d00130773756e6265616d08676e756d6f6e
-
-Testing with packet No. 14
-packet[9]=11
-Compressing...
-Decompressing...
-packet[9]=11
-Results:
-Original Packet:    (55 bytes) 45000037652340004011a91b0a0901650a091701ef1b0035002376a2c3910100000100000000000006676f6f676c650264650000010001
-DecompressedPacket: (55 bytes) 45000037652340004011a91b0a0901650a091701ef1b0035002376a2c3910100000100000000000006676f6f676c650264650000010001
-CompressedPacket:   (55 bytes) 45000037652340004011a91b0a0901650a091701ef1b0035002376a2c3910100000100000000000006676f6f676c650264650000010001
-
-Freeing compression state...
-
-Done
diff --git a/tests/smpp/Makefile.am b/tests/smpp/Makefile.am
deleted file mode 100644
index 5082707..0000000
--- a/tests/smpp/Makefile.am
+++ /dev/null
@@ -1,40 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	-I$(top_srcdir)/src/libmsc \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	-ggdb3 \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOSCCP_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(LIBSMPP34_CFLAGS) \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(COVERAGE_LDFLAGS) \
-	$(NULL)
-
-EXTRA_DIST = \
-	smpp_test.ok \
-	smpp_test.err \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	smpp_test \
-	$(NULL)
-
-smpp_test_SOURCES = \
-	smpp_test.c \
-	$(top_builddir)/src/libmsc/smpp_utils.c \
-	$(NULL)
-
-smpp_test_LDADD = \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(NULL)
diff --git a/tests/smpp/smpp_test.c b/tests/smpp/smpp_test.c
deleted file mode 100644
index 62fa9d2..0000000
--- a/tests/smpp/smpp_test.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * (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/>.
- *
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <openbsc/debug.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/backtrace.h>
-
-#include "smpp_smsc.h"
-
-struct coding_test {
-	uint8_t dcs;
-	uint8_t coding;
-	int	mode;
-	int	res;
-};
-
-static struct coding_test codecs[] = {
-	{ .dcs = 0xf6		, .coding = 0x02, .mode = MODE_8BIT,	.res = 0  },
-	{ .dcs = 0xf2		, .coding = 0x01, .mode = MODE_7BIT,	.res = 0  },
-	{ .dcs = 0x02		, .coding = 0x01, .mode = MODE_7BIT,	.res = 0  },
-	{ .dcs = 0x06		, .coding = 0x02, .mode = MODE_8BIT,	.res = 0  },
-	{ .dcs = 0x0A		, .coding = 0x08, .mode = MODE_8BIT,	.res = 0  },
-	{ .dcs = 0x0E		, .coding = 0xFF, .mode = 0xFF,		.res = -1 },
-	{ .dcs = 0xE0		, .coding = 0xFF, .mode = 0xFF,		.res = -1 },
-};
-
-static void test_coding_scheme(void)
-{
-	int i;
-	printf("Testing coding scheme support\n");
-
-	for (i = 0; i < ARRAY_SIZE(codecs); ++i) {
-		uint8_t coding;
-		int mode, res;
-
-		res = smpp_determine_scheme(codecs[i].dcs, &coding, &mode);
-		OSMO_ASSERT(res == codecs[i].res);
-		if (res != -1) {
-			OSMO_ASSERT(mode == codecs[i].mode);
-			OSMO_ASSERT(coding == codecs[i].coding);
-		}
-	}
-}
-
-int main(int argc, char **argv)
-{
-	osmo_init_logging(&log_info);
-	log_set_use_color(osmo_stderr_target, 0);
-	log_set_print_filename(osmo_stderr_target, 0);
-
-	test_coding_scheme();
-	return EXIT_SUCCESS;
-}
diff --git a/tests/smpp/smpp_test.err b/tests/smpp/smpp_test.err
deleted file mode 100644
index ec966ba..0000000
--- a/tests/smpp/smpp_test.err
+++ /dev/null
@@ -1,2 +0,0 @@
-SMPP MO Unknown Data Coding 0x0e
-SMPP MO Unknown Data Coding 0xe0
diff --git a/tests/smpp/smpp_test.ok b/tests/smpp/smpp_test.ok
deleted file mode 100644
index fd44804..0000000
--- a/tests/smpp/smpp_test.ok
+++ /dev/null
@@ -1 +0,0 @@
-Testing coding scheme support
diff --git a/tests/smpp_test_runner.py b/tests/smpp_test_runner.py
deleted file mode 100644
index 7a3a342..0000000
--- a/tests/smpp_test_runner.py
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/usr/bin/env python
-
-# (C) 2014 by Holger Hans Peter Freyther
-# based on vty_test_runner.py:
-# (C) 2013 by Katerina Barone-Adesi <kat.obsc@gmail.com>
-# (C) 2013 by Holger Hans Peter Freyther
-# 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, see <http://www.gnu.org/licenses/>.
-
-import os
-import sys
-import time
-import unittest
-import socket
-
-import osmopy.obscvty as obscvty
-import osmopy.osmoutil as osmoutil
-
-confpath = os.path.join(sys.path[0], '..')
-
-class TestVTYBase(unittest.TestCase):
-
-    def vty_command(self):
-        raise Exception("Needs to be implemented by a subclass")
-
-    def vty_app(self):
-        raise Exception("Needs to be implemented by a subclass")
-
-    def setUp(self):
-        osmo_vty_cmd = self.vty_command()[:]
-        config_index = osmo_vty_cmd.index('-c')
-        if config_index:
-            cfi = config_index + 1
-            osmo_vty_cmd[cfi] = os.path.join(confpath, osmo_vty_cmd[cfi])
-
-        try:
-            self.proc = osmoutil.popen_devnull(osmo_vty_cmd)
-        except OSError:
-            print >> sys.stderr, "Current directory: %s" % os.getcwd()
-            print >> sys.stderr, "Consider setting -b"
-
-        appstring = self.vty_app()[2]
-        appport = self.vty_app()[0]
-        self.vty = obscvty.VTYInteract(appstring, "127.0.0.1", appport)
-
-    def tearDown(self):
-        if self.vty:
-            self.vty._close_socket()
-        self.vty = None
-        osmoutil.end_proc(self.proc)
-
-
-class TestSMPPMSC(TestVTYBase):
-
-    def vty_command(self):
-        return ["./src/osmo-msc/osmo-msc", "-c",
-                "doc/examples/osmo-msc/osmo-msc.cfg"]
-
-    def vty_app(self):
-        return (4254, "./src/osmo-msc/osmo-msc", "OsmoMSC", "msc")
-
-    def testSMPPCrashes(self):
-        # Enable the configuration
-        self.vty.enable()
-        self.assertTrue(self.vty.verify("configure terminal", ['']))
-        self.assertEquals(self.vty.node(), 'config')
-
-        self.assertTrue(self.vty.verify('smpp', ['']))
-        self.assertEquals(self.vty.node(), 'config-smpp')
-        self.assertTrue(self.vty.verify('system-id test', ['']))
-        self.assertTrue(self.vty.verify('local-tcp-port 2775', ['']))
-        self.assertTrue(self.vty.verify('esme test', ['']))
-        self.assertEquals(self.vty.node(), 'config-smpp-esme')
-        self.assertTrue(self.vty.verify('default-route', ['']))
-        self.assertTrue(self.vty.verify('end', ['']))
-
-        # MSC should listen to 2775 now!
-        sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        sck.setblocking(1)
-        sck.connect(('0.0.0.0', 2775))
-        sck.sendall('\x00\x00\x00\x02\x00')
-        sck.close()
-
-        # Check if the VTY is still there
-        self.vty.verify('disable',[''])
-
-        # Now for the second packet
-        sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        sck.setblocking(1)
-        sck.connect(('0.0.0.0', 2775))
-        sck.sendall('\x00\x01\x00\x01\x01')
-        sck.close()
-
-        self.vty.verify('enable',[''])
-
-if __name__ == '__main__':
-    import argparse
-    import sys
-
-    workdir = '.'
-
-    parser = argparse.ArgumentParser()
-    parser.add_argument("-v", "--verbose", dest="verbose",
-                        action="store_true", help="verbose mode")
-    parser.add_argument("-p", "--pythonconfpath", dest="p",
-                        help="searchpath for config")
-    parser.add_argument("-w", "--workdir", dest="w",
-                        help="Working directory")
-    args = parser.parse_args()
-
-    verbose_level = 1
-    if args.verbose:
-        verbose_level = 2
-
-    if args.w:
-        workdir = args.w
-
-    if args.p:
-        confpath = args.p
-
-    print "confpath %s, workdir %s" % (confpath, workdir)
-    os.chdir(workdir)
-    print "Running tests for specific SMPP"
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestSMPPMSC))
-    res = unittest.TextTestRunner(verbosity=verbose_level).run(suite)
-    sys.exit(len(res.errors) + len(res.failures))
diff --git a/tests/sms_queue/Makefile.am b/tests/sms_queue/Makefile.am
deleted file mode 100644
index 62c479b..0000000
--- a/tests/sms_queue/Makefile.am
+++ /dev/null
@@ -1,55 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	-ggdb3 \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBCRYPTO_CFLAGS) \
-	$(LIBOSMOVTY_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(LIBOSMOSIGTRAN_CFLAGS) \
-	$(LIBOSMORANAP_CFLAGS) \
-	$(LIBASN1C_CFLAGS) \
-	$(NULL)
-
-EXTRA_DIST = \
-	sms_queue_test.ok \
-	sms_queue_test.err \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	sms_queue_test \
-	$(NULL)
-
-sms_queue_test_SOURCES = \
-	sms_queue_test.c \
-	$(NULL)
-
-sms_queue_test_LDADD = \
-	$(top_builddir)/src/libmsc/libmsc.a \
-	$(top_builddir)/src/libvlr/libvlr.a \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libmgcp/libmgcp.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
-	$(LIBSMPP34_LIBS) \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBCRYPTO_LIBS) \
-	$(LIBOSMOVTY_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	$(LIBOSMOSIGTRAN_LIBS) \
-	$(LIBOSMORANAP_LIBS) \
-	$(LIBASN1C_LIBS) \
-	-ldbi \
-	-lrt \
-	$(NULL)
-
-sms_queue_test_LDFLAGS = \
-	-Wl,--wrap=db_sms_get_next_unsent_rr_msisdn \
-	$(NULL)
diff --git a/tests/sms_queue/sms_queue_test.c b/tests/sms_queue/sms_queue_test.c
deleted file mode 100644
index af25b06..0000000
--- a/tests/sms_queue/sms_queue_test.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/* Test Osmocom SMS queue */
-
-/*
- * (C) 2017 by sysmocom s.f.m.c. GmbH
- * All Rights Reserved
- *
- * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
- *
- * 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/>.
- *
- */
-
-#include <osmocom/core/application.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/vlr.h>
-
-static void *talloc_ctx = NULL;
-
-struct gsm_sms *smsq_take_next_sms(struct gsm_network *net,
-				   char *last_msisdn,
-				   size_t last_msisdn_buflen);
-
-static void _test_take_next_sms_print(int i,
-				      struct gsm_sms *sms,
-				      const char *last_msisdn)
-{
-	printf("#%d: ", i);
-	if (sms)
-		printf("sending SMS to %s", sms->text);
-	else
-		printf("no SMS to send");
-	printf(" (last_msisdn='%s')\n", last_msisdn? last_msisdn : "NULL");
-}
-
-static struct gsm_sms fake_sms = { 0 };
-
-struct {
-	const char *msisdn;
-	int nr_of_sms;
-	int failed_attempts;
-	bool vsub_attached;
-} fake_sms_db[] = {
-	{
-		.msisdn = "1111",
-		.nr_of_sms = 0,
-		.vsub_attached = true,
-	},
-	{
-		.msisdn = "2222",
-		.nr_of_sms = 2,
-		.failed_attempts = 2,
-		.vsub_attached = true,
-	},
-	{
-		.msisdn = "3333",
-		.nr_of_sms = 2,
-		.failed_attempts = 3,
-		.vsub_attached = true,
-	},
-	{
-		.msisdn = "4444",
-		.nr_of_sms = 0,
-		.vsub_attached = true,
-	},
-	{
-		.msisdn = "5555",
-		.nr_of_sms = 2,
-		.failed_attempts = 5,
-		.vsub_attached = false,
-	},
-};
-
-/* override, requires '-Wl,--wrap=db_sms_get_next_unsent_rr_msisdn' */
-struct gsm_sms *__real_db_sms_get_next_unsent_rr_msisdn(struct gsm_network *net,
-							const char *last_msisdn,
-							unsigned int max_failed);
-struct gsm_sms *__wrap_db_sms_get_next_unsent_rr_msisdn(struct gsm_network *net,
-							const char *last_msisdn,
-							unsigned int max_failed)
-{
-	static struct vlr_subscr arbitrary_vsub = { .lu_complete = true };
-	int i;
-	printf("     hitting database: looking for MSISDN > '%s', failed_attempts <= %d\n",
-	       last_msisdn, max_failed);
-
-	for (i = 0; i < ARRAY_SIZE(fake_sms_db); i++) {
-		if (!fake_sms_db[i].nr_of_sms)
-			continue;
-		if (strcmp(fake_sms_db[i].msisdn, last_msisdn) <= 0)
-			continue;
-		if (fake_sms_db[i].failed_attempts > max_failed)
-			continue;
-		osmo_strlcpy(fake_sms.dst.addr, fake_sms_db[i].msisdn,
-			     sizeof(fake_sms.dst.addr));
-		fake_sms.receiver = fake_sms_db[i].vsub_attached? &arbitrary_vsub : NULL;
-		osmo_strlcpy(fake_sms.text, fake_sms_db[i].msisdn, sizeof(fake_sms.text));
-		if (fake_sms_db[i].vsub_attached)
-			fake_sms_db[i].nr_of_sms --;
-		return &fake_sms;
-	}
-	return NULL;
-}
-
-void show_fake_sms_db()
-{
-	int i;
-	for (i = 0; i < ARRAY_SIZE(fake_sms_db); i++) {
-		printf("  %s%s has %u SMS pending, %u failed attempts\n",
-		       fake_sms_db[i].msisdn,
-		       fake_sms_db[i].vsub_attached ? "" : " (NOT attached)",
-		       fake_sms_db[i].nr_of_sms,
-		       fake_sms_db[i].failed_attempts);
-	}
-	printf("-->\n");
-}
-
-static void test_next_sms()
-{
-	int i;
-	char last_msisdn[GSM_EXTENSION_LENGTH+1] = "";
-
-	printf("Testing smsq_take_next_sms()\n");
-
-	printf("\n- vsub 2, 3 and 5 each have 2 SMS pending, but 5 is not attached\n");
-	last_msisdn[0] = '\0';
-	show_fake_sms_db();
-	for (i = 0; i < 7; i++) {
-		struct gsm_sms *sms = smsq_take_next_sms(NULL, last_msisdn, sizeof(last_msisdn));
-		_test_take_next_sms_print(i, sms, last_msisdn);
-		OSMO_ASSERT(i >= 4 || sms);
-	}
-
-	printf("\n- SMS are pending at various nr failed attempts (cutoff at >= 10)\n");
-	last_msisdn[0] = '\0';
-	for (i = 0; i < ARRAY_SIZE(fake_sms_db); i++) {
-		fake_sms_db[i].vsub_attached = true;
-		fake_sms_db[i].nr_of_sms = 1 + i;
-		fake_sms_db[i].failed_attempts = i*5;
-
-	}
-	show_fake_sms_db();
-	for (i = 0; i < 7; i++) {
-		struct gsm_sms *sms = smsq_take_next_sms(NULL, last_msisdn, sizeof(last_msisdn));
-		_test_take_next_sms_print(i, sms, last_msisdn);
-		OSMO_ASSERT(i >= 2 || sms);
-	}
-
-	printf("\n- iterate the SMS DB at most once\n");
-	osmo_strlcpy(last_msisdn, "2345", sizeof(last_msisdn));
-	for (i = 0; i < ARRAY_SIZE(fake_sms_db); i++) {
-		fake_sms_db[i].vsub_attached = false;
-		fake_sms_db[i].nr_of_sms = 1;
-		fake_sms_db[i].failed_attempts = 0;
-	}
-	show_fake_sms_db();
-	for (i = 0; i < 3; i++) {
-		struct gsm_sms *sms = smsq_take_next_sms(NULL, last_msisdn, sizeof(last_msisdn));
-		_test_take_next_sms_print(i, sms, last_msisdn);
-		OSMO_ASSERT(!sms);
-	}
-
-	printf("\n- there are no SMS in the DB\n");
-	last_msisdn[0] = '\0';
-	for (i = 0; i < ARRAY_SIZE(fake_sms_db); i++) {
-		fake_sms_db[i].vsub_attached = true;
-		fake_sms_db[i].nr_of_sms = 0;
-		fake_sms_db[i].failed_attempts = 0;
-	}
-	show_fake_sms_db();
-	for (i = 0; i < 3; i++) {
-		struct gsm_sms *sms = smsq_take_next_sms(NULL, last_msisdn, sizeof(last_msisdn));
-		_test_take_next_sms_print(i, sms, last_msisdn);
-		OSMO_ASSERT(!sms);
-	}
-}
-
-
-static struct log_info_cat sms_queue_test_categories[] = {
-};
-
-static struct log_info info = {
-	.cat = sms_queue_test_categories,
-	.num_cat = ARRAY_SIZE(sms_queue_test_categories),
-};
-
-int main(int argc, char **argv)
-{
-	talloc_ctx = talloc_named_const(NULL, 1, "sms_queue_test");
-	msgb_talloc_ctx_init(talloc_ctx, 0);
-	osmo_init_logging(&info);
-
-	OSMO_ASSERT(osmo_stderr_target);
-	log_set_use_color(osmo_stderr_target, 0);
-	log_set_print_timestamp(osmo_stderr_target, 0);
-	log_set_print_filename(osmo_stderr_target, 0);
-	log_set_print_category(osmo_stderr_target, 1);
-	log_parse_category_mask(osmo_stderr_target, "DLOAP,1");
-
-	test_next_sms();
-	printf("Done\n");
-
-	return 0;
-}
diff --git a/tests/sms_queue/sms_queue_test.err b/tests/sms_queue/sms_queue_test.err
deleted file mode 100644
index e69de29..0000000
--- a/tests/sms_queue/sms_queue_test.err
+++ /dev/null
diff --git a/tests/sms_queue/sms_queue_test.ok b/tests/sms_queue/sms_queue_test.ok
deleted file mode 100644
index 146400d..0000000
--- a/tests/sms_queue/sms_queue_test.ok
+++ /dev/null
@@ -1,98 +0,0 @@
-Testing smsq_take_next_sms()
-
-- vsub 2, 3 and 5 each have 2 SMS pending, but 5 is not attached
-  1111 has 0 SMS pending, 0 failed attempts
-  2222 has 2 SMS pending, 2 failed attempts
-  3333 has 2 SMS pending, 3 failed attempts
-  4444 has 0 SMS pending, 0 failed attempts
-  5555 (NOT attached) has 2 SMS pending, 5 failed attempts
--->
-     hitting database: looking for MSISDN > '', failed_attempts <= 9
-#0: sending SMS to 2222 (last_msisdn='2222')
-     hitting database: looking for MSISDN > '2222', failed_attempts <= 9
-#1: sending SMS to 3333 (last_msisdn='3333')
-     hitting database: looking for MSISDN > '3333', failed_attempts <= 9
-     hitting database: looking for MSISDN > '5555', failed_attempts <= 9
-     hitting database: looking for MSISDN > '', failed_attempts <= 9
-#2: sending SMS to 2222 (last_msisdn='2222')
-     hitting database: looking for MSISDN > '2222', failed_attempts <= 9
-#3: sending SMS to 3333 (last_msisdn='3333')
-     hitting database: looking for MSISDN > '3333', failed_attempts <= 9
-     hitting database: looking for MSISDN > '5555', failed_attempts <= 9
-     hitting database: looking for MSISDN > '', failed_attempts <= 9
-#4: no SMS to send (last_msisdn='5555')
-     hitting database: looking for MSISDN > '5555', failed_attempts <= 9
-     hitting database: looking for MSISDN > '', failed_attempts <= 9
-#5: no SMS to send (last_msisdn='5555')
-     hitting database: looking for MSISDN > '5555', failed_attempts <= 9
-     hitting database: looking for MSISDN > '', failed_attempts <= 9
-#6: no SMS to send (last_msisdn='5555')
-
-- SMS are pending at various nr failed attempts (cutoff at >= 10)
-  1111 has 1 SMS pending, 0 failed attempts
-  2222 has 2 SMS pending, 5 failed attempts
-  3333 has 3 SMS pending, 10 failed attempts
-  4444 has 4 SMS pending, 15 failed attempts
-  5555 has 5 SMS pending, 20 failed attempts
--->
-     hitting database: looking for MSISDN > '', failed_attempts <= 9
-#0: sending SMS to 1111 (last_msisdn='1111')
-     hitting database: looking for MSISDN > '1111', failed_attempts <= 9
-#1: sending SMS to 2222 (last_msisdn='2222')
-     hitting database: looking for MSISDN > '2222', failed_attempts <= 9
-     hitting database: looking for MSISDN > '', failed_attempts <= 9
-#2: sending SMS to 2222 (last_msisdn='2222')
-     hitting database: looking for MSISDN > '2222', failed_attempts <= 9
-     hitting database: looking for MSISDN > '', failed_attempts <= 9
-#3: no SMS to send (last_msisdn='')
-     hitting database: looking for MSISDN > '', failed_attempts <= 9
-#4: no SMS to send (last_msisdn='')
-     hitting database: looking for MSISDN > '', failed_attempts <= 9
-#5: no SMS to send (last_msisdn='')
-     hitting database: looking for MSISDN > '', failed_attempts <= 9
-#6: no SMS to send (last_msisdn='')
-
-- iterate the SMS DB at most once
-  1111 (NOT attached) has 1 SMS pending, 0 failed attempts
-  2222 (NOT attached) has 1 SMS pending, 0 failed attempts
-  3333 (NOT attached) has 1 SMS pending, 0 failed attempts
-  4444 (NOT attached) has 1 SMS pending, 0 failed attempts
-  5555 (NOT attached) has 1 SMS pending, 0 failed attempts
--->
-     hitting database: looking for MSISDN > '2345', failed_attempts <= 9
-     hitting database: looking for MSISDN > '3333', failed_attempts <= 9
-     hitting database: looking for MSISDN > '4444', failed_attempts <= 9
-     hitting database: looking for MSISDN > '5555', failed_attempts <= 9
-     hitting database: looking for MSISDN > '', failed_attempts <= 9
-     hitting database: looking for MSISDN > '1111', failed_attempts <= 9
-     hitting database: looking for MSISDN > '2222', failed_attempts <= 9
-#0: no SMS to send (last_msisdn='3333')
-     hitting database: looking for MSISDN > '3333', failed_attempts <= 9
-     hitting database: looking for MSISDN > '4444', failed_attempts <= 9
-     hitting database: looking for MSISDN > '5555', failed_attempts <= 9
-     hitting database: looking for MSISDN > '', failed_attempts <= 9
-     hitting database: looking for MSISDN > '1111', failed_attempts <= 9
-     hitting database: looking for MSISDN > '2222', failed_attempts <= 9
-#1: no SMS to send (last_msisdn='3333')
-     hitting database: looking for MSISDN > '3333', failed_attempts <= 9
-     hitting database: looking for MSISDN > '4444', failed_attempts <= 9
-     hitting database: looking for MSISDN > '5555', failed_attempts <= 9
-     hitting database: looking for MSISDN > '', failed_attempts <= 9
-     hitting database: looking for MSISDN > '1111', failed_attempts <= 9
-     hitting database: looking for MSISDN > '2222', failed_attempts <= 9
-#2: no SMS to send (last_msisdn='3333')
-
-- there are no SMS in the DB
-  1111 has 0 SMS pending, 0 failed attempts
-  2222 has 0 SMS pending, 0 failed attempts
-  3333 has 0 SMS pending, 0 failed attempts
-  4444 has 0 SMS pending, 0 failed attempts
-  5555 has 0 SMS pending, 0 failed attempts
--->
-     hitting database: looking for MSISDN > '', failed_attempts <= 9
-#0: no SMS to send (last_msisdn='')
-     hitting database: looking for MSISDN > '', failed_attempts <= 9
-#1: no SMS to send (last_msisdn='')
-     hitting database: looking for MSISDN > '', failed_attempts <= 9
-#2: no SMS to send (last_msisdn='')
-Done
diff --git a/tests/sndcp_xid/Makefile.am b/tests/sndcp_xid/Makefile.am
deleted file mode 100644
index d09c41b..0000000
--- a/tests/sndcp_xid/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
-AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBCARES_CFLAGS)
-
-EXTRA_DIST = sndcp_xid_test.ok
-
-noinst_PROGRAMS = sndcp_xid_test
-
-sndcp_xid_test_SOURCES = sndcp_xid_test.c
-
-sndcp_xid_test_LDADD = \
-	$(top_builddir)/src/gprs/gprs_sndcp_xid.o \
-	$(LIBOSMOABIS_LIBS) \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOGB_LIBS) \
-	$(LIBCARES_LIBS) \
-	$(LIBCRYPTO_LIBS) \
-	$(LIBGTP_LIBS) \
-	-lrt -lm
-
-
diff --git a/tests/sndcp_xid/sndcp_xid_test.c b/tests/sndcp_xid/sndcp_xid_test.c
deleted file mode 100644
index 151dd2b..0000000
--- a/tests/sndcp_xid/sndcp_xid_test.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/* Test SNDCP-XID Encoding/Decoding */
-
-/* (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/>.
- */
-
-#include <openbsc/gprs_sndcp_xid.h>
-#include <openbsc/debug.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-
-#include <osmocom/core/application.h>
-
-#include <stdio.h>
-#include <string.h>
-
-/* Test SNDCP-XID decoding with a real world sample */
-static void test_xid_decode_realworld(const void *ctx)
-{
-	struct llist_head *comp_fields;
-	int rc;
-	printf("Testing SNDCP XID-Decoder/Encoder (real world data)\n");
-
-	/* Example of a real world SNDCP-XID message */
-	uint8_t xid[] =
-	    { 0x00, 0x01, 0x00, 0x02, 0x31, 0x82, 0x02, 0x27, 0x89, 0xff, 0xe0,
-	0x00, 0x0f, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02,
-	0x01, 0x02, 0x00, 0x03, 0x01, 0x03, 0x00, 0x04, 0x01, 0x04, 0x00, 0x05,
-	0x01, 0x05, 0x00, 0x06, 0x00, 0x07, 0x01, 0x07, 0x00, 0x08, 0x01, 0x08,
-	0x80, 0x00, 0x04, 0x12, 0x00, 0x40, 0x07 };
-	uint8_t xid_r[512];
-
-	/* Parse and show contained comp fields */
-	comp_fields = gprs_sndcp_parse_xid(NULL, ctx, xid, sizeof(xid), NULL);
-	OSMO_ASSERT(comp_fields);
-	printf("Decoded:\n");
-	gprs_sndcp_dump_comp_fields(comp_fields, DSNDCP);
-
-	/* Encode comp-fields again */
-	rc = gprs_sndcp_compile_xid(xid_r,sizeof(xid_r), comp_fields,
-				    DEFAULT_SNDCP_VERSION);
-	printf("Result length=%i\n",rc);
-	printf("Encoded:  %s\n", osmo_hexdump_nospc(xid, sizeof(xid)));
-	printf("Rencoded: %s\n", osmo_hexdump_nospc(xid_r, rc));
-
-	OSMO_ASSERT(rc == 54);
-	OSMO_ASSERT(memcmp(xid, xid_r, sizeof(xid)) == 0);
-
-	/* Free comp fields */
-	talloc_free(comp_fields);
-
-	printf("\n");
-}
-
-/* Encode and decode test with artificial test data */
-static void test_xid_encode_decode(const void *ctx)
-{
-	printf("Testing SNDCP XID-Encoder/Decoder\n");
-
-	LLIST_HEAD(comp_fields);
-	struct gprs_sndcp_pcomp_rfc1144_params rfc1144_params;
-	struct gprs_sndcp_comp_field rfc1144_comp_field;
-	struct gprs_sndcp_pcomp_rfc2507_params rfc2507_params;
-	struct gprs_sndcp_comp_field rfc2507_comp_field;
-	struct gprs_sndcp_pcomp_rohc_params rohc_params;
-	struct gprs_sndcp_comp_field rohc_comp_field;
-	struct gprs_sndcp_dcomp_v42bis_params v42bis_params;
-	struct gprs_sndcp_comp_field v42bis_comp_field;
-	struct gprs_sndcp_dcomp_v44_params v44_params;
-	struct gprs_sndcp_comp_field v44_comp_field;
-	struct llist_head *comp_fields_dec;
-
-	uint8_t xid[512];
-	unsigned int xid_len = sizeof(xid);
-	int rc;
-
-	memset(&rfc1144_comp_field, 0, sizeof(struct gprs_sndcp_comp_field));
-	memset(&rfc2507_comp_field, 0, sizeof(struct gprs_sndcp_comp_field));
-	memset(&rohc_comp_field, 0, sizeof(struct gprs_sndcp_comp_field));
-	memset(&v42bis_comp_field, 0, sizeof(struct gprs_sndcp_comp_field));
-	memset(&v44_comp_field, 0, sizeof(struct gprs_sndcp_comp_field));
-
-	/* Setup which NSAPIs shall make use of rfc1144 */
-	rfc1144_params.nsapi[0] = 5;
-	rfc1144_params.nsapi_len = 1;
-
-	/* Setup rfc1144 operating parameters */
-	rfc1144_params.s01 = 7;
-
-	/* Setup rfc1144 compression field */
-	rfc1144_comp_field.p = 1;
-	rfc1144_comp_field.entity = 0;
-	rfc1144_comp_field.algo = RFC_1144;
-	rfc1144_comp_field.comp[RFC1144_PCOMP1] = 1;
-	rfc1144_comp_field.comp[RFC1144_PCOMP2] = 2;
-	rfc1144_comp_field.comp_len = RFC1144_PCOMP_NUM;
-	rfc1144_comp_field.rfc1144_params = &rfc1144_params;
-
-	/* Setup which NSAPIs shall make use of rfc1144 */
-	rfc2507_params.nsapi[0] = 6;
-	rfc2507_params.nsapi_len = 1;
-
-	/* Setup rfc2507 operating parameters */
-	rfc2507_params.f_max_period = 256;
-	rfc2507_params.f_max_time = 5;
-	rfc2507_params.max_header = 168;
-	rfc2507_params.tcp_space = 15;
-	rfc2507_params.non_tcp_space = 15;
-
-	/* Setup rfc2507 compression field */
-	rfc2507_comp_field.p = 1;
-	rfc2507_comp_field.entity = 1;
-	rfc2507_comp_field.algo = RFC_2507;
-	rfc2507_comp_field.comp[RFC2507_PCOMP1] = 3;
-	rfc2507_comp_field.comp[RFC2507_PCOMP2] = 4;
-	rfc2507_comp_field.comp[RFC2507_PCOMP3] = 5;
-	rfc2507_comp_field.comp[RFC2507_PCOMP4] = 6;
-	rfc2507_comp_field.comp[RFC2507_PCOMP5] = 7;
-	rfc2507_comp_field.comp_len = RFC2507_PCOMP_NUM;
-	rfc2507_comp_field.rfc2507_params = &rfc2507_params;
-
-	/* Setup which NSAPIs shall make use of ROHC */
-	rohc_params.nsapi[0] = 5;
-	rohc_params.nsapi[1] = 6;
-	rohc_params.nsapi[2] = 7;
-	rohc_params.nsapi[3] = 8;
-	rohc_params.nsapi[4] = 9;
-	rohc_params.nsapi[5] = 10;
-	rohc_params.nsapi[6] = 11;
-	rohc_params.nsapi[7] = 12;
-	rohc_params.nsapi[8] = 13;
-	rohc_params.nsapi[9] = 14;
-	rohc_params.nsapi[10] = 15;
-	rohc_params.nsapi_len = 11;
-
-	/* Setup ROHC operating parameters */
-	rohc_params.max_cid = 15;	/* default */
-	rohc_params.max_header = 168;	/* default */
-	rohc_params.profile[0] = ROHC_UNCOMPRESSED;
-	rohc_params.profile[1] = ROHC_RTP;
-	rohc_params.profile[2] = ROHCV2_RTP;
-	rohc_params.profile[3] = ROHC_UDP;
-	rohc_params.profile[4] = ROHCv2_UDP;
-	rohc_params.profile[5] = ROHC_ESP;
-	rohc_params.profile[6] = ROHCV2_ESP;
-	rohc_params.profile[7] = ROHC_IP;
-	rohc_params.profile[8] = ROHCV2_IP;
-	rohc_params.profile[9] = ROHC_LLA;
-	rohc_params.profile[10] = ROHC_LLA_WITH_R_MODE;
-	rohc_params.profile[11] = ROHC_TCP;
-	rohc_params.profile[12] = ROHC_RTP_UDP_LITE;
-	rohc_params.profile[13] = ROHCV2_RTP_UDP_LITE;
-	rohc_params.profile[14] = ROHC_UDP_LITE;
-	rohc_params.profile[15] = ROHCV2_UDP_LITE;
-	rohc_params.profile_len = 16;
-
-	/* Setup ROHC compression field */
-	rohc_comp_field.p = 1;
-	rohc_comp_field.entity = 2;
-	rohc_comp_field.algo = ROHC;
-	rohc_comp_field.comp[ROHC_PCOMP1] = 8;
-	rohc_comp_field.comp[ROHC_PCOMP2] = 9;
-	rohc_comp_field.comp_len = ROHC_PCOMP_NUM;
-	rohc_comp_field.rohc_params = &rohc_params;
-
-	/* Setup which NSAPIs shall make use of v42bis */
-	v42bis_params.nsapi[0] = 5;
-	v42bis_params.nsapi_len = 1;
-
-	/* Setup v42bis operating parameters */
-	v42bis_params.p0 = 3;
-	v42bis_params.p1 = 2048;
-	v42bis_params.p2 = 20;
-
-	/* Setup v42bis compression field */
-	v42bis_comp_field.p = 1;
-	v42bis_comp_field.entity = 3;
-	v42bis_comp_field.algo = V42BIS;
-	v42bis_comp_field.comp[V42BIS_DCOMP1] = 10;
-	v42bis_comp_field.comp_len = V42BIS_DCOMP_NUM;
-	v42bis_comp_field.v42bis_params = &v42bis_params;
-
-	/* Setup which NSAPIs shall make use of v44 */
-	v44_params.nsapi[0] = 5;
-	v44_params.nsapi_len = 1;
-
-	/* Setup v44 operating parameters */
-	v44_params.c0 = 0x80;
-	v44_params.p0 = 3;
-	v44_params.p1t = 300;
-	v44_params.p1r = 300;
-	v44_params.p3t = 600;
-	v44_params.p3r = 600;
-
-	/* Setup v44 compression field */
-	v44_comp_field.p = 1;
-	v44_comp_field.entity = 3;
-	v44_comp_field.algo = V44;
-	v44_comp_field.comp[V44_DCOMP1] = 10;
-	v44_comp_field.comp[V44_DCOMP2] = 11;
-	v44_comp_field.comp_len = V44_DCOMP_NUM;
-	v44_comp_field.v44_params = &v44_params;
-
-	/* Add compression field(s) to list */
-	llist_add(&v44_comp_field.list, &comp_fields);
-	llist_add(&v42bis_comp_field.list, &comp_fields);
-	llist_add(&rfc1144_comp_field.list, &comp_fields);
-	llist_add(&rfc2507_comp_field.list, &comp_fields);
-	llist_add(&rohc_comp_field.list, &comp_fields);
-	printf("Test input data:\n");
-	gprs_sndcp_dump_comp_fields(&comp_fields, DSNDCP);
-
-	/* Encode SNDCP-XID fields */
-	rc = gprs_sndcp_compile_xid(xid, xid_len, &comp_fields,
-				    DEFAULT_SNDCP_VERSION);
-	OSMO_ASSERT(rc > 0);
-
-	printf("Encoded:  %s (%i bytes)\n", osmo_hexdump_nospc(xid, rc), rc);
-
-	/* Parse and show contained comp fields */
-	comp_fields_dec = gprs_sndcp_parse_xid(NULL, ctx, xid, rc, NULL);
-	OSMO_ASSERT(comp_fields_dec);
-
-	printf("Decoded:\n");
-	gprs_sndcp_dump_comp_fields(comp_fields_dec, DSNDCP);
-
-	/* Free comp fields */
-	talloc_free(comp_fields_dec);
-}
-
-static struct log_info_cat gprs_categories[] = {
-	[DSNDCP] = {
-		    .name = "DSNDCP",
-		    .description =
-		    "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
-		    .enabled = 1,.loglevel = LOGL_DEBUG,
-		    }
-};
-
-static struct log_info info = {
-	.cat = gprs_categories,
-	.num_cat = ARRAY_SIZE(gprs_categories),
-};
-
-int main(int argc, char **argv)
-{
-	void *xid_ctx;
-
-	osmo_init_logging(&info);
-
-	xid_ctx = talloc_named_const(NULL, 0, "xid_ctx");
-
-	test_xid_decode_realworld(xid_ctx);
-	test_xid_encode_decode(xid_ctx);
-
-	printf("Done\n");
-
-	talloc_report_full(xid_ctx, stderr);
-	OSMO_ASSERT(talloc_total_blocks(xid_ctx) == 1);
-	return 0;
-}
-
-/* stubs */
-struct osmo_prim_hdr;
-int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
-{
-        abort();
-}
diff --git a/tests/sndcp_xid/sndcp_xid_test.ok b/tests/sndcp_xid/sndcp_xid_test.ok
deleted file mode 100644
index f357282..0000000
--- a/tests/sndcp_xid/sndcp_xid_test.ok
+++ /dev/null
@@ -1,11 +0,0 @@
-Testing SNDCP XID-Decoder/Encoder (real world data)
-Decoded:
-Result length=54
-Encoded:  000100023182022789ffe0000f00a8000000010101000201020003010300040104000501050006000701070008010880000412004007
-Rencoded: 000100023182022789ffe0000f00a8000000010101000201020003010300040104000501050006000701070008010880000412004007
-
-Testing SNDCP XID-Encoder/Decoder
-Test input data:
-Encoded:  000100011a83010dab00208003012c012c02580258830007a000200308001402408000041200200781010c3456700040010005a80f000f82022789ffe0000f00a80000000101010002010200030103000401040005010500060007010700080108 (97 bytes)
-Decoded:
-Done
diff --git a/tests/subscr/Makefile.am b/tests/subscr/Makefile.am
deleted file mode 100644
index 5b770bc..0000000
--- a/tests/subscr/Makefile.am
+++ /dev/null
@@ -1,43 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	-ggdb3 \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(LIBSMPP34_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(COVERAGE_LDFLAGS) \
-	$(NULL)
-
-EXTRA_DIST = \
-	bsc_subscr_test.ok \
-	bsc_subscr_test.err \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	bsc_subscr_test \
-	$(NULL)
-
-bsc_subscr_test_SOURCES = \
-	bsc_subscr_test.c \
-	$(NULL)
-
-bsc_subscr_test_LDADD = \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBSMPP34_LIBS) \
-	$(LIBOSMOVTY_LIBS) \
-	$(NULL)
diff --git a/tests/subscr/bsc_subscr_test.c b/tests/subscr/bsc_subscr_test.c
deleted file mode 100644
index 60d687d..0000000
--- a/tests/subscr/bsc_subscr_test.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/* (C) 2008 by Jan Luebbe <jluebbe@debian.org>
- * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2014 by Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
- * 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 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/>.
- *
- */
-
-#include <openbsc/debug.h>
-#include <openbsc/bsc_subscriber.h>
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/utils.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <inttypes.h>
-
-struct llist_head *bsc_subscribers;
-
-#define VERBOSE_ASSERT(val, expect_op, fmt) \
-	do { \
-		printf(#val " == " fmt "\n", (val)); \
-		OSMO_ASSERT((val) expect_op); \
-	} while (0);
-
-static void assert_bsc_subscr(const struct bsc_subscr *bsub, const char *imsi)
-{
-	struct bsc_subscr *sfound;
-	OSMO_ASSERT(bsub);
-	OSMO_ASSERT(strcmp(bsub->imsi, imsi) == 0);
-
-	sfound = bsc_subscr_find_by_imsi(bsc_subscribers, imsi);
-	OSMO_ASSERT(sfound == bsub);
-
-	bsc_subscr_put(sfound);
-}
-
-static void test_bsc_subscr(void)
-{
-	struct bsc_subscr *s1, *s2, *s3;
-	const char *imsi1 = "1234567890";
-	const char *imsi2 = "9876543210";
-	const char *imsi3 = "5656565656";
-
-	printf("Test BSC subscriber allocation and deletion\n");
-
-	/* Check for emptiness */
-	VERBOSE_ASSERT(llist_count(bsc_subscribers), == 0, "%d");
-	OSMO_ASSERT(bsc_subscr_find_by_imsi(bsc_subscribers, imsi1) == NULL);
-	OSMO_ASSERT(bsc_subscr_find_by_imsi(bsc_subscribers, imsi2) == NULL);
-	OSMO_ASSERT(bsc_subscr_find_by_imsi(bsc_subscribers, imsi3) == NULL);
-
-	/* Allocate entry 1 */
-	s1 = bsc_subscr_find_or_create_by_imsi(bsc_subscribers, imsi1);
-	VERBOSE_ASSERT(llist_count(bsc_subscribers), == 1, "%d");
-	assert_bsc_subscr(s1, imsi1);
-	VERBOSE_ASSERT(llist_count(bsc_subscribers), == 1, "%d");
-	OSMO_ASSERT(bsc_subscr_find_by_imsi(bsc_subscribers, imsi2) == NULL);
-
-	/* Allocate entry 2 */
-	s2 = bsc_subscr_find_or_create_by_imsi(bsc_subscribers, imsi2);
-	VERBOSE_ASSERT(llist_count(bsc_subscribers), == 2, "%d");
-
-	/* Allocate entry 3 */
-	s3 = bsc_subscr_find_or_create_by_imsi(bsc_subscribers, imsi3);
-	VERBOSE_ASSERT(llist_count(bsc_subscribers), == 3, "%d");
-
-	/* Check entries */
-	assert_bsc_subscr(s1, imsi1);
-	assert_bsc_subscr(s2, imsi2);
-	assert_bsc_subscr(s3, imsi3);
-
-	/* Free entry 1 */
-	bsc_subscr_put(s1);
-	s1 = NULL;
-	VERBOSE_ASSERT(llist_count(bsc_subscribers), == 2, "%d");
-	OSMO_ASSERT(bsc_subscr_find_by_imsi(bsc_subscribers, imsi1) == NULL);
-
-	assert_bsc_subscr(s2, imsi2);
-	assert_bsc_subscr(s3, imsi3);
-
-	/* Free entry 2 */
-	bsc_subscr_put(s2);
-	s2 = NULL;
-	VERBOSE_ASSERT(llist_count(bsc_subscribers), == 1, "%d");
-	OSMO_ASSERT(bsc_subscr_find_by_imsi(bsc_subscribers, imsi1) == NULL);
-	OSMO_ASSERT(bsc_subscr_find_by_imsi(bsc_subscribers, imsi2) == NULL);
-	assert_bsc_subscr(s3, imsi3);
-
-	/* Free entry 3 */
-	bsc_subscr_put(s3);
-	s3 = NULL;
-	VERBOSE_ASSERT(llist_count(bsc_subscribers), == 0, "%d");
-	OSMO_ASSERT(bsc_subscr_find_by_imsi(bsc_subscribers, imsi3) == NULL);
-
-	OSMO_ASSERT(llist_empty(bsc_subscribers));
-}
-
-int main()
-{
-	printf("Testing BSC subscriber core code.\n");
-	osmo_init_logging(&log_info);
-	log_set_print_filename(osmo_stderr_target, 0);
-	log_set_print_timestamp(osmo_stderr_target, 0);
-	log_set_use_color(osmo_stderr_target, 0);
-	log_set_print_category(osmo_stderr_target, 1);
-	log_set_category_filter(osmo_stderr_target, DREF, 1, LOGL_DEBUG);
-
-	bsc_subscribers = talloc_zero(NULL, struct llist_head);
-	INIT_LLIST_HEAD(bsc_subscribers);
-
-	test_bsc_subscr();
-
-	printf("Done\n");
-	return 0;
-}
diff --git a/tests/subscr/bsc_subscr_test.err b/tests/subscr/bsc_subscr_test.err
deleted file mode 100644
index a66317a..0000000
--- a/tests/subscr/bsc_subscr_test.err
+++ /dev/null
@@ -1,17 +0,0 @@
-DREF BSC subscr IMSI:1234567890 usage increases to: 2
-DREF BSC subscr IMSI:1234567890 usage decreases to: 1
-DREF BSC subscr IMSI:1234567890 usage increases to: 2
-DREF BSC subscr IMSI:1234567890 usage decreases to: 1
-DREF BSC subscr IMSI:9876543210 usage increases to: 2
-DREF BSC subscr IMSI:9876543210 usage decreases to: 1
-DREF BSC subscr IMSI:5656565656 usage increases to: 2
-DREF BSC subscr IMSI:5656565656 usage decreases to: 1
-DREF BSC subscr IMSI:1234567890 usage decreases to: 0
-DREF BSC subscr IMSI:9876543210 usage increases to: 2
-DREF BSC subscr IMSI:9876543210 usage decreases to: 1
-DREF BSC subscr IMSI:5656565656 usage increases to: 2
-DREF BSC subscr IMSI:5656565656 usage decreases to: 1
-DREF BSC subscr IMSI:9876543210 usage decreases to: 0
-DREF BSC subscr IMSI:5656565656 usage increases to: 2
-DREF BSC subscr IMSI:5656565656 usage decreases to: 1
-DREF BSC subscr IMSI:5656565656 usage decreases to: 0
diff --git a/tests/subscr/bsc_subscr_test.ok b/tests/subscr/bsc_subscr_test.ok
deleted file mode 100644
index 0f6a8be..0000000
--- a/tests/subscr/bsc_subscr_test.ok
+++ /dev/null
@@ -1,11 +0,0 @@
-Testing BSC subscriber core code.
-Test BSC subscriber allocation and deletion
-llist_count(bsc_subscribers) == 0
-llist_count(bsc_subscribers) == 1
-llist_count(bsc_subscribers) == 1
-llist_count(bsc_subscribers) == 2
-llist_count(bsc_subscribers) == 3
-llist_count(bsc_subscribers) == 2
-llist_count(bsc_subscribers) == 1
-llist_count(bsc_subscribers) == 0
-Done
diff --git a/tests/testsuite.at b/tests/testsuite.at
index f21ba0c..dd59f2c 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -1,224 +1,22 @@
 AT_INIT
 AT_BANNER([Regression tests.])
 
-AT_SETUP([gsm0408])
-AT_KEYWORDS([gsm0408])
-cat $abs_srcdir/gsm0408/gsm0408_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/gsm0408/gsm0408_test], [], [expout], [ignore])
+AT_SETUP([legacy_mgcp])
+AT_KEYWORDS([legacy_mgcp])
+cat $abs_srcdir/legacy_mgcp/mgcp_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/legacy_mgcp/mgcp_test], [], [expout], [ignore])
 AT_CLEANUP
 
-AT_SETUP([bsc_subscr])
-AT_KEYWORDS([bsc_subscr])
-cat $abs_srcdir/subscr/bsc_subscr_test.ok > expout
-cat $abs_srcdir/subscr/bsc_subscr_test.err > experr
-AT_CHECK([$abs_top_builddir/tests/subscr/bsc_subscr_test], [], [expout], [experr])
-AT_CLEANUP
-
-AT_SETUP([channel])
-AT_KEYWORDS([channel])
-cat $abs_srcdir/channel/channel_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/channel/channel_test], [], [expout], [ignore])
-AT_CLEANUP
-
-AT_SETUP([mgcp])
-AT_KEYWORDS([mgcp])
-cat $abs_srcdir/mgcp/mgcp_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/mgcp/mgcp_test], [], [expout], [ignore])
-AT_CLEANUP
-
-AT_SETUP([mgcp-trans])
-AT_KEYWORDS([mgcp-trans])
+AT_SETUP([legacy_mgcp-trans])
+AT_KEYWORDS([legacy_mgcp-trans])
 AT_CHECK([test "$enable_mgcp_transcoding_test" == yes || exit 77])
-cat $abs_srcdir/mgcp/mgcp_transcoding_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/mgcp/mgcp_transcoding_test], [], [expout], [ignore])
+cat $abs_srcdir/legacy_mgcp/mgcp_transcoding_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/legacy_mgcp/mgcp_transcoding_test], [], [expout], [ignore])
 AT_CLEANUP
 
-AT_SETUP([mgcpgw_client])
-AT_KEYWORDS([mgcpgw_client])
-cat $abs_srcdir/mgcp/mgcpgw_client_test.ok > expout
-cat $abs_srcdir/mgcp/mgcpgw_client_test.err > experr
-AT_CHECK([$abs_top_builddir/tests/mgcp/mgcpgw_client_test], [], [expout], [experr])
-AT_CLEANUP
-
-AT_SETUP([gprs])
-AT_KEYWORDS([gprs])
-cat $abs_srcdir/gprs/gprs_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/gprs/gprs_test], [], [expout], [ignore])
-AT_CLEANUP
-
-AT_SETUP([bsc-nat])
-AT_KEYWORDS([bsc-nat])
-AT_CHECK([test "$enable_nat_test" != no || exit 77])
-cp $abs_srcdir/bsc-nat/prefixes.csv .
-cp $abs_srcdir/bsc-nat/barr.cfg .
-cp $abs_srcdir/bsc-nat/barr_dup.cfg .
-cat $abs_srcdir/bsc-nat/bsc_nat_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/bsc-nat/bsc_nat_test], [], [expout], [ignore])
-AT_CLEANUP
-
-AT_SETUP([smpp])
-AT_KEYWORDS([smpp])
-AT_CHECK([test "$enable_smpp_test" != no || exit 77])
-cat $abs_srcdir/smpp/smpp_test.ok > expout
-cat $abs_srcdir/smpp/smpp_test.err > experr
-AT_CHECK([$abs_top_builddir/tests/smpp/smpp_test], [], [expout], [experr])
-AT_CLEANUP
-
-AT_SETUP([bsc-nat-trie])
-AT_KEYWORDS([bsc-nat-trie])
-AT_CHECK([test "$enable_nat_test" != no || exit 77])
-cp $abs_srcdir/bsc-nat-trie/prefixes.csv .
-cat $abs_srcdir/bsc-nat-trie/bsc_nat_trie_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/bsc-nat-trie/bsc_nat_trie_test], [], [expout], [ignore])
-AT_CLEANUP
-
-AT_SETUP([abis])
-AT_KEYWORDS([abis])
-cat $abs_srcdir/abis/abis_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/abis/abis_test], [], [expout], [ignore])
-AT_CLEANUP
-
-AT_SETUP([bsc])
-AT_KEYWORDS([bsc])
-AT_CHECK([test "$enable_bsc_test" != no || exit 77])
-cat $abs_srcdir/bsc/bsc_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/bsc/bsc_test], [], [expout], [ignore])
-AT_CLEANUP
-
-AT_SETUP([gbproxy])
-AT_KEYWORDS([gbproxy])
-cat $abs_srcdir/gbproxy/gbproxy_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/gbproxy/gbproxy_test], [], [expout], [ignore])
-AT_CLEANUP
-
-AT_SETUP([trau])
-AT_KEYWORDS([trau])
-cat $abs_srcdir/trau/trau_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/trau/trau_test], [], [expout], [ignore])
-AT_CLEANUP
-
-AT_SETUP([sgsn])
-AT_KEYWORDS([sgsn])
-AT_CHECK([test "$enable_sgsn_test" != no || exit 77])
-cat $abs_srcdir/sgsn/sgsn_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/sgsn/sgsn_test], [], [expout], [ignore])
-AT_CLEANUP
-
-AT_SETUP([oap])
-AT_KEYWORDS([oap])
-AT_CHECK([test "$enable_oap_test" != no || exit 77])
-cat $abs_srcdir/oap/oap_client_test.ok > expout
-cat $abs_srcdir/oap/oap_client_test.err > experr
-AT_CHECK([$abs_top_builddir/tests/oap/oap_client_test], [], [expout], [experr])
-AT_CLEANUP
-
-AT_SETUP([gtphub])
-AT_KEYWORDS([gtphub])
-AT_CHECK([test "$enable_gtphub_test" != no || exit 77])
-cat $abs_srcdir/gtphub/gtphub_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/gtphub/gtphub_test], [], [expout], [ignore])
-AT_CLEANUP
-
-AT_SETUP([xid])
-AT_KEYWORDS([xid])
-AT_CHECK([test "$enable_sgsn_test" != no || exit 77])
-cat $abs_srcdir/xid/xid_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/xid/xid_test], [], [expout], [ignore])
-AT_CLEANUP
-
-AT_SETUP([sndcp_xid])
-AT_KEYWORDS([sndcp_xid])
-AT_CHECK([test "$enable_sgsn_test" != no || exit 77])
-cat $abs_srcdir/sndcp_xid/sndcp_xid_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/sndcp_xid/sndcp_xid_test], [], [expout], [ignore])
-AT_CLEANUP
-
-AT_SETUP([slhc])
-AT_KEYWORDS([slhc])
-AT_CHECK([test "$enable_sgsn_test" != no || exit 77])
-cat $abs_srcdir/slhc/slhc_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/slhc/slhc_test], [], [expout], [ignore])
-AT_CLEANUP
-
-AT_SETUP([v42bis])
-AT_KEYWORDS([v42bis])
-AT_CHECK([test "$enable_sgsn_test" != no || exit 77])
-cat $abs_srcdir/v42bis/v42bis_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/v42bis/v42bis_test], [], [expout], [ignore])
-AT_CLEANUP
-
-AT_SETUP([nanobts_omlattr])
-AT_KEYWORDS([nanobts_omlattr])
-cat $abs_srcdir/nanobts_omlattr/nanobts_omlattr_test.ok > expout
-AT_CHECK([$abs_top_builddir/tests/nanobts_omlattr/nanobts_omlattr_test], [], [expout], [ignore])
-AT_CLEANUP
-
-AT_SETUP([sms_queue_test])
-AT_KEYWORDS([sms_queue_test])
-cat $abs_srcdir/sms_queue/sms_queue_test.ok > expout
-cat $abs_srcdir/sms_queue/sms_queue_test.err > experr
-AT_CHECK([$abs_top_builddir/tests/sms_queue/sms_queue_test], [], [expout], [experr])
-AT_CLEANUP
-
-AT_SETUP([msc_vlr_test_no_authen])
-AT_KEYWORDS([msc_vlr_test_no_authen])
-cat $abs_srcdir/msc_vlr/msc_vlr_test_no_authen.ok > expout
-cat $abs_srcdir/msc_vlr/msc_vlr_test_no_authen.err > experr
-AT_CHECK([$abs_top_builddir/tests/msc_vlr/msc_vlr_test_no_authen], [], [expout], [experr])
-AT_CLEANUP
-
-AT_SETUP([msc_vlr_test_gsm_authen])
-AT_KEYWORDS([msc_vlr_test_gsm_authen])
-cat $abs_srcdir/msc_vlr/msc_vlr_test_gsm_authen.ok > expout
-cat $abs_srcdir/msc_vlr/msc_vlr_test_gsm_authen.err > experr
-AT_CHECK([$abs_top_builddir/tests/msc_vlr/msc_vlr_test_gsm_authen], [], [expout], [experr])
-AT_CLEANUP
-
-AT_SETUP([msc_vlr_test_gsm_ciph])
-AT_KEYWORDS([msc_vlr_test_gsm_ciph])
-cat $abs_srcdir/msc_vlr/msc_vlr_test_gsm_ciph.ok > expout
-cat $abs_srcdir/msc_vlr/msc_vlr_test_gsm_ciph.err > experr
-AT_CHECK([$abs_top_builddir/tests/msc_vlr/msc_vlr_test_gsm_ciph], [], [expout], [experr])
-AT_CLEANUP
-
-AT_SETUP([msc_vlr_test_umts_authen])
-AT_KEYWORDS([msc_vlr_test_umts_authen])
-cat $abs_srcdir/msc_vlr/msc_vlr_test_umts_authen.ok > expout
-cat $abs_srcdir/msc_vlr/msc_vlr_test_umts_authen.err > experr
-AT_CHECK([$abs_top_builddir/tests/msc_vlr/msc_vlr_test_umts_authen], [], [expout], [experr])
-AT_CLEANUP
-
-AT_SETUP([msc_vlr_test_hlr_reject])
-AT_KEYWORDS([msc_vlr_test_hlr_reject])
-cat $abs_srcdir/msc_vlr/msc_vlr_test_hlr_reject.ok > expout
-cat $abs_srcdir/msc_vlr/msc_vlr_test_hlr_reject.err > experr
-AT_CHECK([$abs_top_builddir/tests/msc_vlr/msc_vlr_test_hlr_reject], [], [expout], [experr])
-AT_CLEANUP
-
-AT_SETUP([msc_vlr_test_hlr_timeout])
-AT_KEYWORDS([msc_vlr_test_hlr_timeout])
-cat $abs_srcdir/msc_vlr/msc_vlr_test_hlr_timeout.ok > expout
-cat $abs_srcdir/msc_vlr/msc_vlr_test_hlr_timeout.err > experr
-AT_CHECK([$abs_top_builddir/tests/msc_vlr/msc_vlr_test_hlr_timeout], [], [expout], [experr])
-AT_CLEANUP
-
-AT_SETUP([msc_vlr_test_ms_timeout])
-AT_KEYWORDS([msc_vlr_test_ms_timeout])
-cat $abs_srcdir/msc_vlr/msc_vlr_test_ms_timeout.ok > expout
-cat $abs_srcdir/msc_vlr/msc_vlr_test_ms_timeout.err > experr
-AT_CHECK([$abs_top_builddir/tests/msc_vlr/msc_vlr_test_ms_timeout], [], [expout], [experr])
-AT_CLEANUP
-
-AT_SETUP([msc_vlr_test_reject_concurrency])
-AT_KEYWORDS([msc_vlr_test_reject_concurrency])
-cat $abs_srcdir/msc_vlr/msc_vlr_test_reject_concurrency.ok > expout
-cat $abs_srcdir/msc_vlr/msc_vlr_test_reject_concurrency.err > experr
-AT_CHECK([$abs_top_builddir/tests/msc_vlr/msc_vlr_test_reject_concurrency], [], [expout], [experr])
-AT_CLEANUP
-
-AT_SETUP([msc_vlr_test_rest])
-AT_KEYWORDS([msc_vlr_test_rest])
-cat $abs_srcdir/msc_vlr/msc_vlr_test_rest.ok > expout
-cat $abs_srcdir/msc_vlr/msc_vlr_test_rest.err > experr
-AT_CHECK([$abs_top_builddir/tests/msc_vlr/msc_vlr_test_rest], [], [expout], [experr])
+AT_SETUP([legacy_mgcpgw_client])
+AT_KEYWORDS([legacy_mgcpgw_client])
+cat $abs_srcdir/legacy_mgcp/mgcpgw_client_test.ok > expout
+cat $abs_srcdir/legacy_mgcp/mgcpgw_client_test.err > experr
+AT_CHECK([$abs_top_builddir/tests/legacy_mgcp/mgcpgw_client_test], [], [expout], [experr])
 AT_CLEANUP
diff --git a/tests/trau/Makefile.am b/tests/trau/Makefile.am
deleted file mode 100644
index 1d014ba..0000000
--- a/tests/trau/Makefile.am
+++ /dev/null
@@ -1,45 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	-ggdb3 \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(LIBSMPP34_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(COVERAGE_LDFLAGS) \
-	$(NULL)
-
-EXTRA_DIST = \
-	trau_test.ok \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	trau_test \
-	$(NULL)
-
-trau_test_SOURCES = \
-	trau_test.c \
-	$(NULL)
-
-trau_test_LDADD = \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBSMPP34_LIBS) \
-	$(LIBOSMOVTY_LIBS) \
-	$(LIBRARY_DL) \
-	-ldbi \
-	$(NULL)
-
diff --git a/tests/trau/trau_test.c b/tests/trau/trau_test.c
deleted file mode 100644
index c74e6db..0000000
--- a/tests/trau/trau_test.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
- * 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 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/>.
- *
- */
-
-#include <osmocom/abis/trau_frame.h>
-#include <openbsc/trau_mux.h>
-#include <osmocom/core/msgb.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-void test_trau_fr_efr(unsigned char *data)
-{
-	struct decoded_trau_frame tf;
-	struct msgb *msg;
-	struct gsm_data_frame *frame;
-
-	printf("Testing TRAU FR transcoding.\n");
-	data[0] = 0xd0;
-	trau_encode_fr(&tf, data);
-	tf.c_bits[11] = 0; /* clear BFI */
-	msg = trau_decode_fr(1, &tf);
-	OSMO_ASSERT(msg != NULL);
-	frame = (struct gsm_data_frame *)msg->data;
-	OSMO_ASSERT(frame->msg_type == GSM_TCHF_FRAME);
-	OSMO_ASSERT(!memcmp(frame->data, data, 33));
-	msgb_free(msg);
-
-	printf("Testing TRAU EFR transcoding.\n");
-	data[0] = 0xc0;
-	trau_encode_efr(&tf, data);
-	OSMO_ASSERT(tf.d_bits[0] == 1); /* spare bit must be 1 */
-	tf.c_bits[11] = 0; /* clear BFI */
-	msg = trau_decode_efr(1, &tf);
-	OSMO_ASSERT(msg != NULL);
-	frame = (struct gsm_data_frame *)msg->data;
-	OSMO_ASSERT(frame->msg_type == GSM_TCHF_FRAME_EFR);
-	OSMO_ASSERT(!memcmp(frame->data, data, 31));
-
-	printf("Testing TRAU EFR decoding with CRC error.\n");
-	tf.d_bits[0] = 0; /* spare bit must be included */
-	msg = trau_decode_efr(1, &tf);
-	OSMO_ASSERT(msg != NULL);
-	frame = (struct gsm_data_frame *)msg->data;
-	OSMO_ASSERT(frame->msg_type == GSM_BAD_FRAME);
-	msgb_free(msg);
-}
-
-int main()
-{
-	unsigned char data[33];
-	int i;
-
-	msgb_talloc_ctx_init(NULL, 0);
-
-	memset(data, 0x00, sizeof(data));
-	test_trau_fr_efr(data);
-	memset(data, 0xff, sizeof(data));
-	test_trau_fr_efr(data);
-	srandom(42);
-	for (i = 0; i < sizeof(data); i++)
-		data[i] = random();
-	test_trau_fr_efr(data);
-	printf("Done\n");
-	return 0;
-}
-
-/* stubs */
-void vty_out() {}
diff --git a/tests/trau/trau_test.ok b/tests/trau/trau_test.ok
deleted file mode 100644
index ef71230..0000000
--- a/tests/trau/trau_test.ok
+++ /dev/null
@@ -1,10 +0,0 @@
-Testing TRAU FR transcoding.
-Testing TRAU EFR transcoding.
-Testing TRAU EFR decoding with CRC error.
-Testing TRAU FR transcoding.
-Testing TRAU EFR transcoding.
-Testing TRAU EFR decoding with CRC error.
-Testing TRAU FR transcoding.
-Testing TRAU EFR transcoding.
-Testing TRAU EFR decoding with CRC error.
-Done
diff --git a/tests/v42bis/Makefile.am b/tests/v42bis/Makefile.am
deleted file mode 100644
index a031e33..0000000
--- a/tests/v42bis/Makefile.am
+++ /dev/null
@@ -1,15 +0,0 @@
-AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
-AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBCARES_CFLAGS)
-
-EXTRA_DIST = v42bis_test.ok
-
-noinst_PROGRAMS = v42bis_test
-
-v42bis_test_SOURCES = v42bis_test.c
-
-v42bis_test_LDADD = \
-	$(top_builddir)/src/gprs/v42bis.o \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOCORE_LIBS)
-
-
diff --git a/tests/v42bis/v42bis_test.c b/tests/v42bis/v42bis_test.c
deleted file mode 100644
index 7e90785..0000000
--- a/tests/v42bis/v42bis_test.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/* Test v42bis Compression/Decompression */
-
-/* (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/>.
- */
-
-#include <openbsc/v42bis.h>
-#include <openbsc/v42bis_private.h>
-#include <openbsc/debug.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-
-#include <osmocom/core/application.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <stdbool.h>
-
-/* V.42bis compression parameters */
-#define P0 3			/* Direction */
-#define P1 512			/* Max number of codewords */
-#define P2 20			/* Max string length */
-
-/* V.42bis compression buffer size
- * (Does not affect the compression/decompression result) */
-#define MAX_BLOCK_SIZE 1024
-
-/* Compressed sample packets, sniffed from real communication */
-#define COMPR_PACKETS_LEN 33
-char *compr_packets[] = {
-	/* K800i */
-	"4500010268000700004006cefac0a80002550d93d740000050462c7ba7e4d1753a80184000aad500000101080a0001a670084dafb4474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d6978656433005ab97a052b960d59b368d5b2ddb3e60e9c372ef610b6dbf56bd8b165030f2e7cf88dd63b68f64c3d9b76ed1cb58847b490d122e8d0a24761185913d50e1aa423f0dc49036387d6d7b169e4d0cac68e1cd93b70f0804123f7eee03372dcc801038f193b306a68b5b2864d9a3b629a30b1a2b5081b35384613357a07c6133271d4e021a3064d52347182ee81b119c69c3a72d2b079b37e4409c177e6f4902163738cdd71f8a0a903d68ec21866e4c0918185087dfb329cec9831834d951a337c4a2e1174891c3badf5e8d113a38f1c336e24520c8a65751d1844d4c7696d852c1f240e992becf8918d0c9145465441939fcc6a1950a206b7e1fca38e1145eaebc129230aeb24f57bcab011c3c68829f5efe7bfcbe4c814e731668c3042f6fef93a62d9909561e4c91123c163d0085a3a4e1c3466c6c649ea048d519d5ff3a0f95ef4280c2471269e61633ee9193469de8845a3554d9fa74199c48622e7fa7dac30ac602f9af40a9ef0236a54268247cd7f923946d0a8d1c3c68d1e35788c5002e54ad0a00100",
-	"4500010268000900004006cef8c0a80002550d93d740000050462c7ba7e4d1753a801840007e7f00000101080a0001d1cc084db0ae474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d6978656433005ab97a052b960d59b368d5b2ddb3e60e9c372ef610b6dbf56bd8b165030f2e7cf88dd63b68f64c3d9b76ed1cb58847b490d122e8d0a24761185913d50e1aa423f0dc49036387d6d7b169e4d0cac68e1cd93b70f0804123f7eee03372dcc801038f193b306a68b5b2864d9a3b629a30b1a2b5081b35384613357a07c6133271d4e021a3064d52347182ee81b119c69c3a72d2b079b37e4409c177e6f4902163738cdd71f8a0a903d68ec21866e4c0918185087dfb329cec9831834d951a337c4a2e1174891c3badf5e8d113a38f1c336e24520c8a65751d1844d4c7696d852c1f240e992becf8918d0c9145465441939fcc6a1950a206b7e1fca38e1145eaebc129230aeb24f57bcab011c3c68829f5efe7bfcbe4c814e731668c3042f6fef93a62d9909561e4c91123c163d0085a3a4e1c3466c6c649ea048d519d5ff3a0f95ef4280c2471269e61633ee9193469de8845a3554d9fa74199c48622e7fa7dac30ac602f9af40a9ef0236a54268247cd7f923946d0a8d1c3c68d1e35788c5002e54ad0a00100",
-	"4500010268000b00004006cef6c0a80002550d93d740000050462c7ba7e4d1753b80193fff131c00000101080a00022884084dc558474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d6978656433005ab97a052b960d59b368d5b2ddb3e60e9c372ef610b6dbf56bd8b165030f2e7cf88dd63b68f64c3d9b76ed1cb58847b490d122e8d0a24761185913d50e1aa423f0dc49036387d6d7b169e4d0cac68e1cd93b70f0804123f7eee03372dcc801038f193b306a68b5b2864d9a3b629a30b1a2b5081b35384613357a07c6133271d4e021a3064d52347182ee81b119c69c3a72d2b079b37e4409c177e6f4902163738cdd71f8a0a903d68ec21866e4c0918185087dfb329cec9831834d951a337c4a2e1174891c3badf5e8d113a38f1c336e24520c8a65751d1844d4c7696d852c1f240e992be4e8918d8c9045465441939fcc6a1950a206b7e1dca38e1145eaebb929230aeb24f579cab011c3c68829f5efe7afcbe4c814e731668c3042f6fef93a62d9909561e4c91123c163d0084a3a4e1c3466c6c649ea048dd19c5ff3a0f95ef4280c2471269e61633ee9193469de8845a3554d9fa74199c48622c7fa7dac30ac5c2f9af40a1ef0236a502682478dff913946d0a8d1c3c68d1e35788c5002e54ad0a00100",
-	"4500010268000c00004006cef5c0a80002550d93d740000050462c7ba7e4d1753b80193fff65ab00000101080a0002d5f4084dc558474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d6978656433005ab97a052b960d59b368d5b2ddb3e60e9c372ef610b6dbf56bd8b165030f2e7cf88dd63b68f64c3d9b76ed1cb58847b490d122e8d0a24761185913d50e1aa423f0dc49036387d6d7b169e4d0cac68e1cd93b70f0804123f7eee03372dcc801038f193b306a68b5b2864d9a3b629a30b1a2b5081b35384613357a07c6133271d4e021a3064d52347182ee81b119c69c3a72d2b079b37e4409c177e6f4902163738cdd71f8a0a903d68ec21866e4c0918185087dfb329cec9831834d951a337c4a2e1174891c3badf5e8d113a38f1c336e24520c8a65751d1844d4c7696d852c1f240e992be4e8918d8c9045465441939fcc6a1950a206b7e1dca38e1145eaebb929230aeb24f579cab011c3c68829f5efe7afcbe4c814e731668c3042f6fef93a62d9909561e4c91123c163d0084a3a4e1c3466c6c649ea048dd19c5ff3a0f95ef4280c2471269e61633ee9193469de8845a3554d9fa74199c48622c7fa7dac30ac5c2f9af40a1ef0236a502682478dff913946d0a8d1c3c68d1e35788c5002e54ad0a00100",
-	"450001022d000f00004006ac5ec0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e33005cbd8215bb67cd1d386f5cecd1cb766ad5ab59b7decdbbb7ef1ba877d0ec49daf56bd83960fd8e6821a3c5cd9c3b7bc230b2e6a81d343e47e0b99306c60ea8a54fd3c801958d1d39a877e0e00183c6ebd8b767e4b89103061e337660d4806a650d9b3477c4346162056a11366a7064d6c9f30e8c2764e2a8c143460d9a9f68e2dcdc0323328c3975e4a461f326fc881278efcce9214346e418b1e3f04153c7aa9dfd31ccc88123030b11f5ec6538d93163069b2a3566d0445ce2e612397646d398118347cd9a3a68f49848f12696d0756010011f67b415ad7c90fc17be5f224536322e16195105cd7b32a16540397adb06718a3a461459afe7a58c28a293acb729c3460c1b23a6ac6ffffe2d93235388c79831c288d6f6ddeb6065a355869127478cdcae79b3739c3868cc648df3d3091a9e31abe641537d674f1848e2203cc386fbcf3368d2bcc18a06aa9a3e456fde0c00",
-	"450001022d001000004006ac5dc0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e33005cbd8215bb67cd1d386f5cecd1cb766ad5ab59b7decdbbb7ef1ba877d0ec49daf56bd83960fd8e6821a3c5cd9c3b7bc230b2e6a81d343e47e0b99306c60ea8a54fd3c801958d1d39a877e0e00183c6ebd8b767e4b89103061e337660d4806a650d9b3477c4346162056a11366a7064d6c9f30e8c2764e2a8c143460d9a9f68e2dcdc0323328c3975e4a461f326fc881278efcce9214346e418b1e3f04153c7aa9dfd31ccc88123030b11f5ec6538d93163069b2a3566d0445ce2e612397646d398118347cd9a3a68f49848f12696d0756010011f67b415ad7c90fc17be5f224536322e16195105cd7b32a16540397adb06718a3a461459afe7a58c28a293acb729c3460c1b23a6ac6ffffe2d93235388c79831c288d6f6ddeb6065a355869127478cdcae79b3739c3868cc648df3d3091a9e31abe641537d674f1848e2203cc386fbcf3368d2bcc18a06aa9a3e456fde0c00",
-	"450001022d001100004006ac5cc0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e33005cbd8215bb67cd1d386f5cecd1cb766ad5ab59b7decdbbb7ef1ba877d0ec49daf56bd83960fd8e6821a3c5cd9c3b7bc230b2e6a81d343e47e0b99306c60ea8a54fd3c801958d1d39a877e0e00183c6ebd8b767e4b89103061e337660d4806a650d9b3477c4346162056a11366a7064d6c9f30e8c2764e2a8c143460d9a9f68e2dcdc0323328c3975e4a461f326fc881278efcce9214346e418b1e3f04153c7aa9dfd31ccc88123030b11f5ec6538d93163069b2a3566d0445ce2e612397646d398118347cd9a3a68f49848f12696d0756010011f67b415ad7c90fc17be5f224536322e16195105cd7b32a16540397adb06718a3a461459afe7a58c28a293acb729c3460c1b23a6ac6ffffe2d93235388c79831c288d6f6ddeb6065a355869127478cdcae79b3739c3868cc648df3d3091a9e31abe641537d674f1848e2203cc386fbcf3368d2bcc18a06aa9a3e456fde0c00",
-	"450001022d001200004006ac5bc0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e33005cbd8215bb67cd1d386f5cecd1cb766ad5ab59b7decdbbb7ef1ba877d0ec49daf56bd83960fd8e6821a3c5cd9c3b7bc230b2e6a81d343e47e0b99306c60ea8a54fd3c801958d1d39a877e0e00183c6ebd8b767e4b89103061e337660d4806a650d9b3477c4346162056a11366a7064d6c9f30e8c2764e2a8c143460d9a9f68e2dcdc0323328c3975e4a461f326fc881278efcce9214346e418b1e3f04153c7aa9dfd31ccc88123030b11f5ec6538d93163069b2a3566d0445ce2e612397646d398118347cd9a3a68f49848f12696d0756010011f67b415ad7c90fc17be5f224536322e16195105cd7b32a16540397adb06718a3a461459afe7a58c28a293acb729c3460c1b23a6ac6ffffe2d93235388c79831c288d6f6ddeb6065a355869127478cdcae79b3739c3868cc648df3d3091a9e31abe641537d674f1848e2203cc386fbcf3368d2bcc18a06aa9a3e456fde0c00",
-	"4500010268001300004006ceeec0a80002550d93d740000050462c7ba7e4d1753b80193fff7b4a00000101080a0003c054084dc558474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d6978656433005bbb7e0d3b964dd9b369d7b6ddb3e60e9c372ef614beeb15ac58b2660513368cf8cdd63b68f65045ab96ed9cb58947b490d1422851a34861185923d50e9aa423f0dc490363c756d8b269e4d8cac68e9cd93b70f0804143376fe13372dcc801038f193b306a6cb5b2864d9a3b629a30b1b2b5081b353848173d7a07c6133271d4e021a3068d52347184ee81c119c69c3a72d2b079c37e4489c177e6f4902183730cde71f8a0a913d6cec21866e4c091818548fdfb329cec9831834d951a337e4e2e2174891c3baef5e8d113a38f1c336e2656148a85751d1844d6c7716da52c1f240f9b2fecf8918d0c9145465441a39f0c6b1950a40ab7f1fca38e1145ecebc129234aeb24f67bcab011c3c68829f6f1ebb7cbe4c894e731668c3052163ffa3a63d9949561e4c91123c263d0105a3a4e1c3466c8c651ea04cd519d60f3a0016f14290c2471289e61735ee9193469de8c45b3554d1fa84299c88622e73afeac30ac6037aaf40a9ef0236a54268247cd7f923946d0a8d1c3c68d1e35788c5002e58a50a10100",
-	"450001022d001400004006ac59c0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e33005cbd8215bb67cd1d386f5cecd1cb766ad5ab59b7decdbbb7ef1ba877d0ec49daf56bd83960fd8e6821a3c5cd9c3b7bc230b2e6a81d343e47e0b99306c60ea8a54fd3c801958d1d39a877e0e00183c6ebd8b767e4b89103061e337660d4806a650d9b3477c4346162056a11366a7064d6c9f30e8c2764e2a8c143460d9a9f68e2dcdc0323328c3975e4a461f326fc881278efcce9214346e418b1e3f04153c7aa9dfd31ccc88123030b11f5ec6538d93163069b2a3566d0445ce2e612397646d398118347cd9a3a68f49848f12696d0756010011f67b415ad7c90fc17be5f224536322e16195105cd7b32a16540397adb06718a3a461459afe7a58c28a293acb729c3460c1b23a6ac6ffffe2d93235388c79831c288d6f6ddeb6065a355869127478cdcae79b3739c3868cc648df3d3091a9e31abe641537d674f1848e2203cc386fbcf3368d2bcc18a06aa9a3e456fde0c00",
-	"450001022d001500004006ac58c0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e33005cbd8215bb67cd1d386f5cecd1cb766ad5ab59b7decdbbb7ef1ba877d0ec49daf56bd83960fd8e6821a3c5cd9c3b7bc230b2e6a81d343e47e0b99306c60ea8a54fd3c801958d1d39a877e0e00183c6ebd8b767e4b89103061e337660d4806a650d9b3477c4346162056a11366a7064d6c9f30e8c2764e2a8c143460d9a9f68e2dcdc0323328c3975e4a461f326fc881278efcce9214346e418b1e3f04153c7aa9dfd31ccc88123030b11f5ec6538d93163069b2a3566d0445ce2e612397646d398118347cd9a3a68f49848f12696d0756010011f67b415ad7c90fc17be5f224536322e16195105cd7b32a16540397adb06718a3a461459afe7a58c28a293acb729c3460c1b23a6ac6ffffe2d93235388c79831c288d6f6ddeb6065a355869127478cdcae79b3739c3868cc648df3d3091a9e31abe641537d674f1848e2203cc386fbcf3368d2bcc18a06aa9a3e456fde0c00",
-	"4500010239000500004006ac5cc0a800020a0901ab40001f90c286afa741a348cb801840007fcb0000050a41a348dc41a34a440000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d69786564330057b36eedfa954dd8b165cfa6ddb3e60e9c372ef6049eab95ab57b062fd02164cf8cdd53b68f640256b16ed9cb38547b490d1e22791a043efc030b2c6a91d344547e0b99306c68eabad5fd3c871958d1d39b077e0e00183c6eddcbf67e4b89103061e337660d4b86a650d9b3477c4346162e56a11366a7080164d14c6133271d4e021a3068d5134717eee818119c69c3a72d2b079837e4489bf77e6f4902103738cdc71f8a0a9d3d58ec11866e4c091818548fcf9329cec9831834d951a33783e2ef173891c3bab69cc88c1a3674f1d347a6cdcf8134bea3a30889c8fb3da4a583e48162a37a891231b19208b8ca882c63e99d432a038fd6d8339471d238ac8d793534614d549e40b956123868d1153e4d3b77f97c99129cc63cc1861242c7df275beb2092bc3c89323467ef7fc693a4e1c3466c0c631ea04cdd09d5cf3a0e96e66e81d1848e2403cc366bcd13368d2bcf98ae6aa9a3e4c7ffe0c00",
-	"450001025b000a00004006ac35c0a800020a0901ab40011f90c293b0a8af5e58be5018400072a60000474554202f72656470686f6e652e706e6720485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c33005cbd82154b368e59b46ad9ee597307ce1b177b066fedfa35ec583665010b266cf8cdd63b68f6543d9b76ed1cb58747b490d16268d1a34961185933d50e1aa523f0dc490363c7d6d7b169e4d8cac68e1cd93b70f0804123f7eee03372dcc801038f193b306a6cb5b2864d9a3b629a30b1b2b5081b3538461b457a07c6133238f190518366299a3843f7c0d80c634e1d3969d8bc513fa244e03b737ac890b139c6ee387cd0d4096b07610c3372e0c8c042647e7d194e76cc98c1a64a8d1940259718ba448e9dd63466c4e01134a80e1a3d38721c8a65751d1844d2c7696d65261f240d9923dcd8918d0c9045465441839fcc6a1950a606b7e1bca38e1145e8ebd929230aeb24f485cab011c3c68829f4ede3d7cbe4c814e731668c3032d3be1a3c75c6b2296be4c91123c1830e451d270e1a3364e32c758206694fb079d07c3f9a1406923812cfb0c1b9f40c9a346fc6a2d9aaa64fd4a175d33064b894bfff812b5bc2a421b3e60c8e32860e0d00",
-	"4500010267001200004006ac21c0a800020a0901ab40011f90c293b0a8af5e58be80184000ee770000050aaf5e6437af5e8c230000474554202f72656470686f6e652e706e6720485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d33006fc8de41b3c72b5cb974e7cc853ca2858c164c9d42950ac3c81aae76d04c1d81e74e1a183bc8e2d64d2307593676e4ecde8183070c1ac2892b9f91e3460e1878ccd8815183ac95356cd2dc11d3848915b245d8a8c1c1fa69d43b309e90098a878c1a3454d1c461ba0706691873eac849c3e6cdfc112514df99d343860cd23188c7e183a68e5a3b126398910347061622fcfdcb70b263c60c36556acc48bab904d32572ecd8a63123060fa54a75d0e861d224532cb4ebc020223f8e6d2b3cf920b1585d62c9936c64a82c32a20a9a826468cb80c255b98deb27758c28d25f4f5119516a27e9df54868d1836464ce9ffbf20612647a65c8f316384119effd5e0a9c3968d5b234f8e1851ae94a9ec3871d098691b87aa1334518fa6cd83063d54a93090c4d978864d50aa67d0a479c3160d59357db432fd9ba66245aa0a193aac7953278d9e3f679894c1946900",
-	"4500010236003000004006cf03c0a80002550d93d740020050c30e84a9441d06ac80184000c2f400000101080a00052df410fc31bd474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d6978656433005cbd82154b968d59b46ad9baddb3e60e9c372ef618c6fb35ecd8b26707173e9cf80dd73b68f6544dbbb6ed1cb68a47b490d16268d1a34961185933d50e1aa523f0dc49036307d7d8b369e4e0cac68e1cda3b70f080416377efe13372dcc801038f193b306a70b5b2864d9a3b629a30b1c2b5081b35384a1b457a07c6133271d4e021a306cd52347186ee81d119c69c3a72d2b079d37e4409c277e6f49021a3738cde71f8a0a923d60ec31866e4c0918185887dfc329cec9831834d951a3380522e3174891c3baff5e8d113a38f1c336e285a1c8aa5751d1844d8c7796dc52c1f24109d33f408928d8c9145465441b39f4c6b1950a60eb7011da48e1145eeebc929238aeb24f77dcab011c3c68829f7f3efbfcbe4c814e831668c3062367ffa3a64d9989561e4c91123c363d0186a3a4e1c3466cac659ea040dd29d61f3a0097f34290c24712a9e61837ee9193469de9045c3554d9fa843870600",
-	"4500010260004500004006cec4c0a80002550d93d740030050c3134faac89c8b2980184000578d00000101080a000535c010fc34c8474554202f6e697276616e612e63737320485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d33006fcede41b3072c5dbb78e7dcad3ca2858c164ea14aa50ac3c81aaf76d0541d81e74e1a183bcef2f64d23c7593676e4fcde8183070c1ac6913b9f91e3460e187884c2a871d6ca1a3669ee8869c2c4cad9226cd4e0801d75ea1d184f7caac143460d1aab68e238dd0303358c3975e4a461f3c6fe88128fefcce9214306ea18c8e3f04153a7edd0b841e5c0918185c87f83329cec9831834d951a33967e2ee174891c3bbaf5e8d113a38f1c336e3ac2718a05771d1844eac7d16d252e1f241985563489928d8c954546544193900c6e1950bc3ab7a11da58e11450aea292a234aee240595cab011c3c68829050f2624cce4c814ed31668c3012f7a0fc3a6fd9c49561e4c91123ce63d0702a3b4e1c3466e0c6b1ea04cdd4a36cf3a0592f952a0c2471ccc839c3268e1aab67d0a479f316cd59357db83af59b062346ab0d1f46b47933e7ce9e329c3a0d00",
-	"4500010264004600004006cebfc0a80002550d93d740040050c3135bab2189da61801840008f2d00000101080a000535c410fc34dc474554202f382d4269742f4c6162656c2e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d3300952fbf517b07cd1e9f77f3ee9da317f38816325a48a56a152b0c236bc4da419375049e3b6960ec50fb3b388d1c6ad9d891237c070e1e3068245f1e7d468e1b3960e0316307460db556d6b04973474c132656d4f254836376d5ab7760008da3060f193568b4a28923750f8cd530e6d4919386cd9bfc234a48be33a7870c19ab632c8fc3074d1db87630c63023078e0c2c440c2294e164c78c196caad498f1547409a94be4d8e9ad478f9e187de498710352a4542cbbebc020823f4e6f2b74f920e1c81da34a966c64bc2c32a20a1a866476cb802236ba0def2c758c2872500f521951782739d854868d1836464c39a89061612647a6788f31638411ba0aebd791cb86ae0c234f8e18891e838654da71e2a03133378e562768ae2a7d9b078d7bab5861208913f20c1bfa5acfa049f3462e1ab56afa80950a38cdc68d5a214aa4a873e74fa144474a951a00",
-	"4500010264005800004006ceadc0a80002550d93d740050050c31389acaf7b26538018400075c900000101080a000537d010fc354a474554202f382d4269742f41636f726e2e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d3300942dbf497b07cd1e9f76f1ea9d93f7f28816325a48a56af50e0c236bc2da418375049e3b6960ec48eb1b388d1c69d9d891137c070e1e306820570e7d468e1b3960e0316307468db456d6b04973474c132656d2f2548343b699aa57613c2113470d1e326ad064451347ea1e18aa61cca923270d9b37f94794887c674e0f193254c7501e870f9a3a6fed608c11148e0c2c440c2294e164c78c196caad498f1347409a94be4d8e1ad478f9e187de4987103520e1ca95874d78141047f1cde56e6f241c2713bc6942bd9c87059644415340cc9e89601252c741bdd57ea1851e4a09ea432a2ec4e72d0a90c1b316c8c9872502143c34c8e4ce91e63c608237315d6af1397cd5c19469e1c31023d060da9b4e3c44163466e9cac4ed0585dea360f9af6efefc0401227e81936f4b39e4193e64d5c3469d5f4f92a15709a8d1bb342944831a7ce9e42898a942a3500",
-	"4500010266007600004006ce8dc0a80002550d93d740060050c31431ada11fa06780184000f08e00000101080a00053b3c10fc35ef474554202f382d4269742f416d73747261642e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d33009733bf597b07cd9e9e78f5f2d5a379440b192da656bd9a1586913563eda0d13a02cf9d343076ac052e9c468eb56cecc819be03070f18349433973e23c78d1c30f098b103a3c65a2b6bd8a4b923a609132b6b77aac141db2ad63b309e9089a3060f193568b6a28933750f0cc830e6d4919386cd9bfd234a50be33a7870c199063308fc3074d9db87636c63023078e0c2c44103294e164c78c196caad49801957489a94be404ddaa478f9e187de4987133b2e4542cbcebc020a23f8e6f2b75f920f9d87d63cb976c64c82c32a20a9a876478cb803256ba8def2f758c28a2500f5319517a27512855868d1836464c51d8f061622647a67c8f31638491ba0defd799cba6ae0c234f8e18911e83c6d4db71e2a0314337ce562768b03a859b07cdfbab5961208943f20c1bfb5bcfa049f3662e9ab56afa849d3a388d478f5b2756bcf813e850a3484d4e9d1a00",
-	"4500010264007700004006ce8ec0a80002550d93d740040050c3135ddb2189e0108018400060d600000101080a00053b4010fc35e7474554202f382d4269742f41746172692e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d3300932bbf497b07cd1e9f76f1ea9d93d7f28816325a48a56a152b0c236b84da419375049e3b6960ec48dbfb378d1c69d9d891037c070e1e30681c4ffe7c468e1b3960e0316307468db456d6b04973474c132656d2f254832376d5ab77603c2113470d1e326ad068451347ea1e18a961cca923270d9b37f84794807c674e0f193252c7481e870f9aa1da2fc63023078e0c2c440a1e94e164c78c196caad498f1147409a94be4d8d9ad478f9e187de49871e311a4542cb9ebc020723fce6e2b73f920d968e7224a956c64b42c32a20a9a856472cb8022f4b90dee2a758c286250cf511951742731c854868d1836464c31887061612647a6708f31638491b908e9d789cb66ae0c234f8e18791e8386d4d971e2a03123378e562768ae26759b070d7bab58612089f3f10c9bf95acfa049f3262e9ab46afa8095fa378d468d5a1f469c8833e7ce9f41434a951a00",
-	"4500010264007c00004006ce89c0a80002550d93d740070050c314f3aefa37ceb18018400009f900000101080a00053e3410fc369e474554202f382d4269742f4170706c652e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d3300942dbf517b07cd1e9f76f1ea9d93f7f28816325a48a56a152b0c236bc4da419375049e3b6960ec50dbfb378d1c6ad9d891037c070e1e30681c4ffe7c468e1b3960e0316307460db556d6b04973474c132656d4f254832376d5ab77603c2113470d1e326ad068451347ea1e18a961cca923270d9ba15a4b44be33a7870c19a963248fc3074d9db7762cc63023078e0c2c400da691e164c78c196caad498f1147409a94be4d8d9ad478f9e187de49871e311a4542cb9ebc020723fce6e2b73f920d1a8dd224a956c64b42c32a20a9aa16472cb8022f6b90dee2a758c2862504f521951742731e854868d1836464c29a910cd602647a6708f31638491b908e9d789cb66ae0c234f8e18791e8386d4d971e2a03123378e562768ae2e7dc3260f1af656b1c24012e7e31936f3b59e4193e64d5c346ad5f4012bd56f9a8c19b53a84281167ce9d3f8b86942a3500",
-	"4500010265007d00004006ce87c0a80002550d93d740050050c3138bdcaf7b296780183cec0de600000101080a00053e3410fc368e474554202f382d4269742f447261676f6e2e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d33009631bf597b07cd1e9f8df5f2d59379440b192da656bd9a1586913563eda0d13a02cf9d343076ac052e9c468eb56cecc819be03070f18349433973e23c78d1c30f098b103a3c65a2b6bd8a4b923a609132b6b79aac141db2ad63b309e9089a3068f50345bd1c499ba07c6631873eac849c3e68dfe112526df99d343868cc73198c7e183a64e5c3b1963989103470616220715ca70b263c60c36556acc804abac4d42572ecf8d6a3474f8c3e72ccb80939722a16de75601051c3dfb715a27c9074ec9e71654b363260161951054d4332bc6540192bddc6f7963a461441a847a98c28bd93208ce3d3460c1b23a6205cd89030932353bec79831c208d185f7ebcc6553d7c8932346a4c7a03175769c3868ccd08db3d5091aac4ce1e641f3fe6a561848e2883cc3c6fed63368d2bc998b66ad9a3e61a7fe4dc391e3d688132beeec0974a8519253a70600",
-	"4500010269008000004006ce80c0a80002550d93d740060050c3143301dfa11fa3de80183c892b5d00000101080a0005412c10fc3761474554202f382d4269742f456e74657270726973652e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f6600952f67defcc66dd03d3df7f6fd3bc72fe7112d64b4b08a552b571846d6983dda75049e3b6960ec701b7c388d1c6e8dca21be03070f183496db694e63468e1b3960e0316307460db756d6b04973474c132656dcee5483c376d6ad77603c2113470d1e326ad0784513c7ea1e18ae6110959386cd1bfe234a58be33a7870c19ae63548fc347285d3b1b63989103470616220ad3c870b263c60c36556acc986aba84d52572ecfcd6a3474f8c3e72ccb81149d22a96a3756010d91fe7b715bc7c90d4f9b891a54b36326216195105cd4332476540312bdd0678973a4614a923478f531951d0dc49d299aa0c1b316c8c98d2b9e143c64c8e4c011f63c60823781be2af63970d5e19469e1c31223d060dabbce3c44163e66e1caf4ed06c853a370f1af85ab9c2401267e41936f7bd9e4193e68d5d346ed5f4216bd5701aa142bd4eac78d1e7cfa1489596b46a3500",
-	"4500010268008100004006ce80c0a80002550d93d740040050c313600b2189e30280183d0e896b00000101080a000541d810fc379d474554202f382d4269742f436f6d6d6f646f72652e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f3300952f67defcc6ed1d347b7ceeedfb778e5fce235ac8686115ab56ae308cac316b074dd71178eea481b1c3edf0e23472b86563478ef11d3878c0a0d1fc79f519396ee48081c78c1d1835dc5a59c326cd1d314d985871cb530d8edb59b7de81f1844c1c3578c8a841e3154d1cab7b60bc8631a78e9c346cdef81f51c2f29d393d64c8781de3791c3e68ead0b5d3318699a032b01061e85086931d3366b0a95263c654d325ac2e916327b81e3d7a62f49163c64dc9a056b1fcae038348ff38c1ade0e5832424f88e2e61b29131b3c8882a682292f92d038ad9ea36c4c3d431a248433d4c6544019ea46154193662d81831a5e1c38889991c99223ec68c1146f03ed45fc72e1bbc328c3c3962a47a0c1a5671c78983c6ccdd385e9da0d9ea746e1e34f2b5728581248ec9336cf27b3d8326cd1bbb68dcaae943d62ae13420417aad78312350a1448d228523c3aad500",
-	"4500010263008200004006ce84c0a80002550d93d740050050c3138e0daf7b2cf180183962cb2f00000101080a000542b410fc3822474554202f382d4269742f454143412e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b330096dfa4bd83668f4fbb78f5cec97b79440b192da24ead7a1586913561eda0c13a02cf9d343076a4f50d9c468eb46cecc809be03070f1834902b873e23c78d1c30f098b103a3465a2b6bd8a4b923a609132b6979aac1219baad53b309e9089a3060f193568b2a28913750f0cd530e6d4919386cd9bfc234a44be33a7870c19aa63288fc3074d9db77630c63023078e0c2c440c2294e164c78c196caad498e1347489a84be4d8e1ad478f9e187de49871035264542cbaebc020823f0e6f2b73f920e1b81da34a966c64bc2c32a20a1a866474cb801216ba8dee2c758c287250cf511951762739c854868d1836464c39a89021612647a6748f31638491b90aebd789cb66ae0c234f8e18811e8346d4d971e2a03123374e562768ac26759b074dfbaa5761208913f20c1bfa59cfa049f3262e9ab46afa7c8dfa37cdc68d59214aa4a873e7cfa04347468d1a00",
-	"4500010262008500004006ce82c0a80002550d93d740070050c314f5defa37d29b80183c168b6100000101080a000542c810fc37e5474554202f382d4269742f4d53582e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b330095dfa0bd83668fcfba77f3cec16b79440b192da04aa56a1586913560eda0b93a02cf9d343076a0edfd9b460eb46cecc801be03070f18348e277f3e23c78d1c30f098b103a3065a2b6bd8a4b923a609132b6879aac1117b6ad53b309e9089a3060f193568b0a28903750f8cd430e6d4919386cd1bfc234a40be33a7870c19a963248fc3074d1db7762ec63023078e0c2c440a1e94e164c78c196caad498d1147409a84be4d8d9ad478f9e187de49871f33124542cb9ebc020723fce6e2b72f920d9a8fd62ca956c64b82c32a20a9a856472cb8002f6b90dee2b758c2862508f511951742731b854868d1836464c318870e1602647a6708f31638411b908e9d781cb46ae0c234f8e18791e830654d971e2a03113370e562768aa226d9b070d7baa5661208903f20c9bf958cfa049f3062e1ab46afa7885ea378d468d581f469c9853674fa0424542851a00",
-	"4500010265009400004006ce70c0a80002550d93d740060050c3143614a11fa986801836e1f43c00000101080a000545b010fc38b7474554202f382d4269742f4d617474656c2e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d3300942dbf512b744fcfbb79f7ced17b79440b192da452b58a1586913562eda0c93a02cf9d343076a8edfd9b460eb56cecc801be03070f18348e277f3e23c78d1c30f098b103a3865a2b6bd8a4b923a609132b6a77aac111bbead53b309e9089a3060f193568b4a28923750f8cd430e6d4919386cd1bfc234a44be33a7870c19a963248fc3074d1db87630c63023078e0c2c440a1e94e164c78c196caad498f1347409a94be4d8d9ad478f9e187de498710352a4542cb9ebc020723fce6e2b74f920e1a81da34a966c64bc2c32a20a1a866472cb8022f6b90dee2c758c2862504f521951742731e854868d1836464c31889021612647a6708f31638411ba08e9d791bbd8c89323469ec7a02195769c3868cc7ca5abd5099aab4bdfe641c3de2a561848e2843cc366bed63368d2bc018a46ad9a3e60a5fe4db371a356881229eae4f97368d19152a50600",
-	"4500010263009900004006ce6dc0a80002550d93d740040050c313623f2189e66b801839a5739a00000101080a0005464c10fc38f3474554202f382d4269742f4f7269632e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b330095dfa4bd83668f4fc578f5eab13ca2858c1651a756bd0ac3c89ab076d0601d81e74e1a183bd2fa064e23475a3676e404df8183070c1ac895439f91e3460e1878ccd8815123ad95356cd2dc11d3848995b43cd5e0904dd5ea1d184fc8c45183878c1a3459d1c489ba0706631873eac849c3e64dfe112520df99d343860cc63194c7e18326e8768c31ccc88123030b1183086538d93163069b2a356638155d22ea12397678ebd1a327461f3966dc7c0c19158bee3a3088e08fc3db8a5c3e4838dac19872251b192e8b8ca882862119dd32a084856ea3fb4a1d238a1cd483544694dd490e36956123868d11530e2a642898c99129dd63cc186144aec2fa75e0b2912bc3c8932346a0c7a01135769c3868ccc48d93d5091aab4adde641d3beea551848e2803cc3867ed63368d2bc818b26ad9a3e5fa3f64db3716356881229e6d4d91328519151a30600",
-	"4500010269009e00004006ce62c0a80002550d93d740060050c3143845a11fab60801840003c1c00000101080a000547d810fc38b7474554202f382d4269742f526164696f536861636b2e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f330096316be6fcc6ed1d347b7a46f60b584fe7112d64b4b08a552b5718468ad6b183a6eb083c77d2c0d8e17678711a39dcb2b123c7f80e1c3c60d068febcfa8c1c3772c0c063c60e8c1a6e89b24973474c132656dcee5483e376d6ad77603c2113470d1e326ad0784513c7ea1e189361cca923270d9b37fd4794b87c674e0f193226c7781e870f9a3a74ed748c61460e1c195888307428c3c98e1933d854a93163eae9125697c8b1135c8f1e3d31fac831e3a6e449ab587ed78141847f9ce056f0f24112127cc79731d9c8a0596444153411c9fc9601c56c751be263ea1851a4a19ea732a2004fd2b0aa0c1b316c8c98d2f061c4c54c8e4c111f63c60823781fe6af6357685e234f8e18a91e838655dd71e2a03173378e572768b6469d9b074d7cad5c61208963f20c1bfc5ecfa049f3c62e1ab76afa90b55a380d48905e2b5ecc1874e8d1a44b515ab51a00",
-	"4500010266009f00004006ce64c0a80002550d93d740050050c313903caf7b2f9580183d5ce4ef00000101080a0005481810fc3934474554202f382d4269742f5068696c6970732e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d3300952fbf597b07cd1e9f8cf5f2d58379440b192da85ac5aa1586913563eda0d93a02cf9d343076acfd1d9c468eb56cecc811be03070f1834922f8f3e23c78d1c30f098b103a3c65a2b41d3dc11d3848995b53cd5e0987d35eb1d184fc8c45183878c1a345cd1c4a1ba0786631873eac8492334ff881292efcce9214386e318cbe3f0415307b19d8b31ccc88123030b1183086538d93163069b2a3566441d5d82ea1239767aebd1a327461f3966dc7c0c4915cbee3a3088e08fd3db0a5d3e483672bf9872251b192e8b8ca882e60d1a32bb6540191bdd86f7953a461439a847a98c28bc931c7c2ac3460c1b23a61c5428f830932353bcc79831c2085d85f5ebc8654357869127478c448f4183eaed3871d098991b87ab133459990ecd83a63d56ad3090c40179860d7dae67d0a4792317cd5a357d8852059c46a346ae0f234ecca9b32750a322a9520d00",
-	"450001049b00ae00004006cc20c0a80002550d93d740050050c31396ceaf7b396e801840009ad400000101080a0005611010fc3d6b474554202f382d4269742f6d72776f6e672e67696620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d33009733bf617b07cd9e9f8ef7f6d5a379440b192da85ac5aa1586913564eda0d93a02cf9d343076b00d3e9c460eb66cecc821be03070f183496379f3e23c78d1c30f098b103a3065b2b6b92de11d3848915b63dd5e0a87d35eb1d184fc814c543460d1aae68e250dd0303328c3975e4a461f346ff881294efcce9214306e418cde3f0415347ae1d8c31ccc88123030b1183086538d93163069b2a3566442d5d82ea1239767eebd1a327461f3966dc801449154bef3a3088e48ff3db0a513e48387ac7a892251b192f8b8ca882862199de32a0909d6e033c4b1d238a1cd4a3544614df490e3e956123868d11530e2a644898c99129e063cc186184a8423578ead06563d7c8932346a6c7a04175769c3868ccd48dc3d5099aac4ce3e641f31eab561848e2843cc3a628d73368d2bca18b86ad9a3e62a9fe4db3712357881229eadce933e8d09154a92a417265848c1d307afec489074e198678e6108d31a7e8882557ae4c9111357903abdf7f7b052b96ec4f3868d51e7e1b77ae74198ef7f63d1a76ce52bf50cf4c9d7355b7ddb290634cae7cb9b4dec05f135b76c178c41d347b7e16eeabc732db16325a74cf7a07869135647bff0e3e7c075bdad3732c6f4e7c070e1ed37dcb993e23c78d1c30f07807cfd6ca1a3669ee8869c2c40adb9e6a70a8d60ae30999a278c8e4e78a260ed53d3020c33088900d43ae25204aa46818239f8d6cbc631c3a120b11ff6964a864c9e6e58ca8a54b505d220727579d3b7d06bd48158b52a6f99f72b542940f923a13ed600c39838d8c974546fc6548a63761b2d36d8067a96344913a72f428951105cd9d248a9fcab011c3c688298ad30c444398c99129e063cc18313bce683578eae8b66be4c91123d363246f003b0e1a33d2b93a41939569dc3c68d6df8181248e193967d814e57a064d9a3774d1b055d387cd1caa7fd36cdcc835618f853a63d07473510655aa0100",
-
-	/* SGSN with IAXMODEM V.42bis */
-	"45000101a0f3d84000400679210a0901abc0a800021f90400538e210f07a827bb1501900ed7be90000485454502f312e3020323030204f4b0d0a5365727665723a2053696d706c65485454502f302e3620507974686f6e2f322e372e360d0a446174653a205765642c203301312041756720323031362030393a32383a353220474d540d0a436f6e74656e742d747970653a20746578742f68746d6c3b20636861727365743d5554462d380d0a436f6e74656e742d4c656e6774683a203232320d0a0d0a66003f481c9162e40a97294800002068746d6c20506600588a3c6162644409183200002f5733432f2f4454442048544d4c20332e322046696e616c2f2f454e223e3c68746d66006f8234f87187cd1d006c653e4469726563746f7279206c697374696e672066016f72202f3c2f7469746c990068bcff2823e70c9fff6b6a943f9f7e7dfbf7f1e7d7bf9f5fb1c2ef6beafcc7d3fd3b7ced646aa34f03a404fa3373a4c64113630efdec27534e7509538d7e32ff657044a8f1bb0c82067f72f71e00",
-	"45000101a0e9a54000400683540a0901abc0a800021f904004437442f17a4ab3b1501900ed04900000485454502f312e3020323030204f4b0d0a5365727665723a2053696d706c65485454502f302e3620507974686f6e2f322e372e360d0a446174653a205765642c203301312041756720323031362030393a32373a353520474d540d0a436f6e74656e742d747970653a20746578742f68746d6c3b20636861727365743d5554462d380d0a436f6e74656e742d4c656e6774683a203232320d0a0d0a66003f481c9162e40a97294800002068746d6c20506600588a3c6162644409183200002f5733432f2f4454442048544d4c20332e322046696e616c2f2f454e223e3c68746d6c3e0a3c7469746c653e4469726563746f7279206c697374696e672066016f72202f3c2f7469746c990068beff2823e70c9f816b6a9847af9ebd7bf8f2e9dbc7af5ff142f06bea0cc4e31d7cfced646aa74f03a444fa3373a4c64113634e7ded28554e7d1953cd7e320365744cb811bc8c82078376ff1e00",
-};
-
-/* Uncompressed sample packets, sniffed from real communication */
-#define UNCOMPR_PACKETS_LEN 11
-char *uncompr_packets[] = {
-	"45000236000700004006cf2cc0a80002550d93d7400000501e200da7c0c95a70801840002e3700000101080a000174140853d489474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a0d0a",
-	"4510004046dd40004006a9a7c0a8646ec0a864640017ad8b81980100f3ac984d801800e32a1600000101080a000647de06d1bf5efffd18fffd20fffd23fffd27",
-	"4510005b46de40004006a98bc0a8646ec0a864640017ad8b8198010cf3ac984d801800e3867500000101080a000647df06d1bf61fffb03fffd1ffffd21fffe22fffb05fffa2001fff0fffa2301fff0fffa2701fff0fffa1801fff0",
-	"4510003746df40004006a9aec0a8646ec0a864640017ad8b81980133f3ac989f801800e35fd700000101080a000647e106d1bf63fffd01",
-	"4510003746e040004006a9adc0a8646ec0a864640017ad8b81980136f3ac98a2801800e35fd200000101080a000647e106d1bf64fffb01",
-	"4510007446e140004006a96fc0a8646ec0a864640017ad8b81980139f3ac98a5801800e37b9b00000101080a000647e206d1bf640d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a57656c6c636f6d6520746f20706f6c6c75780d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a0d0a",
-	"4510004246e240004006a9a0c0a8646ec0a864640017ad8b81980179f3ac98a5801800e3dab000000101080a000647ec06d1bf6f706f6c6c7578206c6f67696e3a20",
-	"450001a0b41140004006b8e80a0901abc0a800021f904002d5b860b5bab240ae501900ed861d0000485454502f312e3020323030204f4b0d0a5365727665723a2053696d706c65485454502f302e3620507974686f6e2f322e372e360d0a446174653a205475652c2033302041756720323031362030393a34333a303720474d540d0a436f6e74656e742d747970653a20746578742f68746d6c3b20636861727365743d5554462d380d0a436f6e74656e742d4c656e6774683a203232320d0a0d0a3c21444f43545950452068746d6c205055424c494320222d2f2f5733432f2f4454442048544d4c20332e322046696e616c2f2f454e223e3c68746d6c3e0a3c7469746c653e4469726563746f7279206c697374696e6720666f72202f3c2f7469746c653e0a3c626f64793e0a3c68323e4469726563746f7279206c697374696e6720666f72202f3c2f68323e0a3c68723e0a3c756c3e0a3c6c693e3c6120687265663d2272656470686f6e652e706e67223e72656470686f6e652e706e673c2f613e0a3c2f756c3e0a3c68723e0a3c2f626f64793e0a3c2f68746d6c3e0a",
-	"450000e2971b40003706026c550d93d7c0a8000200504047217f5922c903759c8018007c4fb400000101080a1153ce39002cf6e8485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613134392d3436652d34323736386138656338656330220d0a0d0a",
-	"450000e224f1400037067496550d93d7c0a80002005040489387ebf0c904389f8018007cec5700000101080a1153cf01002cf8fc485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613338302d3861362d34323736383761323236383830220d0a0d0a",
-	"450000e2b66140003706e325550d93d7c0a8000200504049fbb679bcc9051ea48018007cebea00000101080a1153cfdc002cfdb4485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343120474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338313336642d3138642d34353832306530393638303430220d0a0d0a",
-};
-
-/* Calculate IP Header checksum */
-static uint16_t calc_ip_csum(uint8_t *data, int len)
-{
-	int i;
-	uint32_t accumulator = 0;
-	uint16_t *pointer = (uint16_t *) data;
-
-	for (i = len; i > 1; i -= 2) {
-		accumulator += *pointer;
-		pointer++;
-	}
-
-	if (len % 2)
-		accumulator += *pointer;
-
-	accumulator = (accumulator & 0xffff) + ((accumulator >> 16) & 0xffff);
-	accumulator += (accumulator >> 16) & 0xffff;
-	return (~accumulator);
-}
-
-/* Calculate TCP/IP checksum */
-static uint16_t calc_tcpip_csum(const void *ctx, uint8_t *packet, int len)
-{
-	uint8_t *buf;
-	uint16_t csum;
-
-	buf = talloc_zero_size(ctx, len);
-	memset(buf, 0, len);
-	memcpy(buf, packet + 12, 8);
-	buf[9] = packet[9];
-	buf[11] = (len - 20) & 0xFF;
-	buf[10] = (len - 20) >> 8 & 0xFF;
-	memcpy(buf + 12, packet + 20, len - 20);
-	csum = calc_ip_csum(buf, len - 20 + 12);
-	talloc_free(buf);
-	return csum;
-}
-
-/* A simple function to show the ascii content of a packet */
-void show_packet(uint8_t *packet, int len)
-{
-	int i;
-	char c;
-	for (i = 0; i < len; i++) {
-		c = packet[i];
-		if (c >= 0x20 && c <= 0x7E)
-			printf("%c", c);
-		else
-			printf(".");
-	}
-	printf("\n");
-}
-
-/* A struct to capture the output data of compressor and decompressor */
-struct v42bis_output_buffer {
-	uint8_t *buf;
-	uint8_t *buf_pointer;
-	int len;
-};
-
-/* A simple testpattern generator */
-static void gen_test_pattern(uint8_t *data, int len)
-{
-	int i;
-	for (i = 0; i < len; i++)
-		data[i] = i & 0xF0;
-}
-
-/* Handler to capture the output data from the compressor */
-void tx_v42bis_frame_handler(void *user_data, const uint8_t *pkt, int len)
-{
-	struct v42bis_output_buffer *output_buffer =
-	    (struct v42bis_output_buffer *)user_data;
-	memcpy(output_buffer->buf_pointer, pkt, len);
-	output_buffer->buf_pointer += len;
-	output_buffer->len += len;
-	return;
-}
-
-/* Handler to capture the output data from the decompressor */
-void tx_v42bis_data_handler(void *user_data, const uint8_t *buf, int len)
-{
-	/* stub, never used */
-	OSMO_ASSERT(false);
-	return;
-}
-
-/* Handler to capture the output data from the compressor */
-void rx_v42bis_frame_handler(void *user_data, const uint8_t *pkt, int len)
-{
-	/* stub, never used */
-	OSMO_ASSERT(false);
-	return;
-}
-
-/* Handler to capture the output data from the decompressor */
-void rx_v42bis_data_handler(void *user_data, const uint8_t *buf, int len)
-{
-	struct v42bis_output_buffer *output_buffer =
-	    (struct v42bis_output_buffer *)user_data;
-	memcpy(output_buffer->buf_pointer, buf, len);
-	output_buffer->buf_pointer += len;
-	output_buffer->len += len;
-	return;
-}
-
-/* Test V.42bis compression and decompression */
-static void v42bis(const void *ctx, int mode, uint8_t *testvec, int len)
-{
-	v42bis_state_t *tx_state;
-	v42bis_state_t *rx_state;
-	uint8_t *uncompressed_original;
-	uint8_t *compressed;
-	uint8_t *uncompressed;
-
-	uncompressed_original = talloc_zero_size(ctx, len);
-	uncompressed = talloc_zero_size(ctx, len);
-
-	/* Note: We allocate double the size for the compressed buffer,
-	 * because in some cases the compression may increase the amount.
-	 * of data. */
-	compressed = talloc_zero_size(ctx, len * 2);
-
-	int rc;
-	int rc_sum = 0;
-	struct v42bis_output_buffer compressed_data;
-	struct v42bis_output_buffer uncompressed_data;
-
-	/* Initalize */
-	tx_state =
-	    v42bis_init(ctx, NULL, P0, P1, P2,
-			&tx_v42bis_frame_handler, NULL, MAX_BLOCK_SIZE,
-			&tx_v42bis_data_handler, NULL, MAX_BLOCK_SIZE);
-	OSMO_ASSERT(tx_state);
-	rx_state =
-	    v42bis_init(ctx, NULL, P0, P1, P2,
-			&rx_v42bis_frame_handler, NULL, MAX_BLOCK_SIZE,
-			&rx_v42bis_data_handler, NULL, MAX_BLOCK_SIZE);
-	OSMO_ASSERT(rx_state);
-	v42bis_compression_control(tx_state, mode);
-
-	/* Setup input data */
-	memcpy(uncompressed_original, testvec, len);
-
-	/* Run compressor */
-	compressed_data.buf = compressed;
-	compressed_data.buf_pointer = compressed;
-	compressed_data.len = 0;
-	tx_state->compress.user_data = (&compressed_data);
-	rc = v42bis_compress(tx_state, uncompressed_original, len);
-	printf("v42bis_compress() rc=%d\n", rc);
-	OSMO_ASSERT(rc == 0);
-	rc = v42bis_compress_flush(tx_state);
-	printf("v42bis_compress_flush() rc=%d\n", rc);
-	OSMO_ASSERT(rc == 0);
-
-	/* Decompress again */
-	uncompressed_data.buf = uncompressed;
-	uncompressed_data.buf_pointer = uncompressed;
-	uncompressed_data.len = 0;
-	rx_state->decompress.user_data = (&uncompressed_data);
-	rc = v42bis_decompress(rx_state, compressed_data.buf,
-			       compressed_data.len);
-	printf("v42bis_decompress() rc=%d\n", rc);
-	rc = v42bis_decompress_flush(rx_state);
-	rc_sum += rc;
-	printf("v42bis_decompress_flush() rc=%d\n", rc);
-	rc_sum += rc;
-
-	/* Check results */
-	printf("Mode: %i\n", mode);
-
-	printf("uncompressed_original= %s ASCII:",
-	       osmo_hexdump_nospc(uncompressed_original, len));
-	show_packet(uncompressed_original, len);
-	printf("uncompressed=          %s ASCII:",
-	       osmo_hexdump_nospc(uncompressed_data.buf,
-				  uncompressed_data.len));
-	show_packet(uncompressed_data.buf, uncompressed_data.len);
-	printf("compressed=            %s ASCII:",
-	       osmo_hexdump_nospc(compressed_data.buf, compressed_data.len));
-	show_packet(compressed_data.buf, compressed_data.len);
-
-	rc = memcmp(uncompressed, uncompressed_original, len);
-	printf("memcmp() rc=%d\n", rc);
-	rc_sum += rc;
-	OSMO_ASSERT(rc_sum == 0);
-
-	/* Free buffers and exit */
-	v42bis_free(tx_state);
-	v42bis_free(rx_state);
-	talloc_free(uncompressed_original);
-	talloc_free(compressed);
-	talloc_free(uncompressed);
-	printf("\n");
-}
-
-/* Test V.42bis compression and decompression with generated data*/
-static void test_v42bis(const void *ctx)
-{
-	printf("Testing compression/decompression with generated data:\n");
-	uint8_t testvec[1024];
-	int len = sizeof(testvec);
-	gen_test_pattern(testvec, len);
-	v42bis(ctx, V42BIS_COMPRESSION_MODE_DYNAMIC, testvec, len);
-	v42bis(ctx, V42BIS_COMPRESSION_MODE_ALWAYS, testvec, len);
-	v42bis(ctx, V42BIS_COMPRESSION_MODE_NEVER, testvec, len);
-}
-
-/* Test V.42bis compression and decompression with some TCP/IP packets */
-static void test_v42bis_tcpip(const void *ctx, int packet_id)
-{
-	uint8_t *testvec;
-	int len;
-	printf
-	    ("Testing compression/decompression with realistic TCP/IP packets:\n");
-	printf("Packet No.: %i\n", packet_id);
-	len = strlen(uncompr_packets[packet_id]);
-	testvec = talloc_zero_size(ctx, len);
-	len = osmo_hexparse(uncompr_packets[packet_id], testvec, len);
-	OSMO_ASSERT(len > 0);
-	v42bis(ctx, V42BIS_COMPRESSION_MODE_DYNAMIC, testvec, len);
-	v42bis(ctx, V42BIS_COMPRESSION_MODE_ALWAYS, testvec, len);
-	v42bis(ctx, V42BIS_COMPRESSION_MODE_NEVER, testvec, len);
-	talloc_free(testvec);
-}
-
-/* Test V.42bis decompression with real, sniffed packets */
-static void test_v42bis_tcpip_decompress(const void *ctx, int packet_id)
-{
-	uint8_t *compressed;
-	int compressed_len;
-	uint8_t *uncompressed;
-	v42bis_state_t *rx_state;
-	int rc;
-	int rc_sum = 0;
-	int len;
-	struct v42bis_output_buffer uncompressed_data;
-
-	printf
-	    ("Testing decompression with sniffed compressed TCP/IP packets:\n");
-	printf("Packet No.: %i\n", packet_id);
-	len = strlen(compr_packets[packet_id]);
-
-	uncompressed = talloc_zero_size(ctx, len);
-	compressed = talloc_zero_size(ctx, len);
-
-	/* Initalize */
-	rx_state =
-	    v42bis_init(ctx, NULL, P0, P1, P2,
-			&rx_v42bis_frame_handler, NULL, MAX_BLOCK_SIZE,
-			&rx_v42bis_data_handler, NULL, MAX_BLOCK_SIZE);
-	OSMO_ASSERT(rx_state);
-
-	/* Setup input data */
-	compressed_len =
-	    osmo_hexparse(compr_packets[packet_id], compressed, len);
-
-	/* Decompress */
-	uncompressed_data.buf = uncompressed;
-	uncompressed_data.buf_pointer = uncompressed;
-	uncompressed_data.len = 0;
-	rx_state->decompress.user_data = (&uncompressed_data);
-	rc = v42bis_decompress_flush(rx_state);
-	printf("v42bis_decompress_flush() rc=%d\n", rc);
-	rc_sum += rc;
-	rc = v42bis_decompress(rx_state, compressed, compressed_len);
-	printf("v42bis_decompress() rc=%d\n", rc);
-	rc_sum += rc;
-	rc = v42bis_decompress_flush(rx_state);
-	printf("v42bis_decompress_flush() rc=%d\n", rc);
-	rc_sum += rc;
-
-	/* Check results */
-	printf("compressed=   %s ASCII:",
-	       osmo_hexdump_nospc(compressed, compressed_len));
-	show_packet(compressed, compressed_len);
-	printf("uncompressed= %s ASCII:",
-	       osmo_hexdump_nospc(uncompressed_data.buf,
-				  uncompressed_data.len));
-	show_packet(uncompressed_data.buf, uncompressed_data.len);
-
-	OSMO_ASSERT(calc_ip_csum(uncompressed_data.buf, 20) == 0);
-	OSMO_ASSERT(calc_tcpip_csum(ctx, uncompressed_data.buf,
-				    uncompressed_data.len) == 0);
-
-	/* Free buffers and exit */
-	v42bis_free(rx_state);
-	talloc_free(uncompressed);
-	talloc_free(compressed);
-	printf("\n");
-}
-
-static struct log_info_cat gprs_categories[] = {
-	[DV42BIS] = {
-		     .name = "DV42BIS",
-		     .description = "V.42bis data compression (SNDCP)",
-		     .enabled = 1,.loglevel = LOGL_DEBUG,
-		     }
-};
-
-static struct log_info info = {
-	.cat = gprs_categories,
-	.num_cat = ARRAY_SIZE(gprs_categories),
-};
-
-int main(int argc, char **argv)
-{
-	void *v42bis_ctx;
-	int i;
-
-	osmo_init_logging(&info);
-
-	v42bis_ctx = talloc_named_const(NULL, 0, "v42bis_ctx");
-
-	test_v42bis(v42bis_ctx);
-
-	for (i = 0; i < UNCOMPR_PACKETS_LEN; i++)
-		test_v42bis_tcpip(v42bis_ctx, i);
-
-	for (i = 0; i < COMPR_PACKETS_LEN; i++)
-		test_v42bis_tcpip_decompress(v42bis_ctx, i);
-
-	printf("Done\n");
-	talloc_report_full(v42bis_ctx, stderr);
-	OSMO_ASSERT(talloc_total_blocks(v42bis_ctx) == 1);
-	return 0;
-}
-
-/* stubs */
-struct osmo_prim_hdr;
-int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
-{
-	abort();
-}
diff --git a/tests/v42bis/v42bis_test.ok b/tests/v42bis/v42bis_test.ok
deleted file mode 100644
index 0707674..0000000
--- a/tests/v42bis/v42bis_test.ok
+++ /dev/null
@@ -1,648 +0,0 @@
-Testing compression/decompression with generated data:
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 0
-uncompressed_original= 00000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0 ASCII:................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................
-uncompressed=          00000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0 ASCII:................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................
-compressed=            000100000000000000003300040b4e9870f020428409478c58b89021c38633663c7c081162c42143264ea448b1e29429172f62c49871cc988d1b3972ec3867cec78f2041861c3468e44892244b4e9a74f2244a9429478d5ab99225cb96b366bd7c091366cc61c366cea449b3e6b469376fe2c49973dcb89d3b79f2ec396fdecf9f4081062d587028c184098d226cd83029c388119942ac58f129c58c19a562ecd8b12ac79021b1822c59722bc99429bda26cd9322ccb9831c9c2ac59f32ccd9c39d5e2ecd9b32dcfa041e102254ad4e0d1a348952a5ddab4a953a850a34e9d4ad5aad5ab59b36ae5cab5ebd7af60c58a1d5bb6ac59b468d3ae5dcbd6addbb771e3ca9d3b7740ddba07efde5d9837efc3bd7b27f6ed7bf1efdf8d81037f1c3c7864e1c2270f1f5e9938f1cbc58b67366e7cf3f1e39d9123ff0c00 ASCII:..........3...N.p. B..G.X..!..3f<|..b.!C&N.H...)./b..q....9r.8g... A..4h.H.$KN.t.$J.)G.Z..%...f.|..f.a.f..I...i7o...s...;y..9o...@..-Xp(...."l.0)....B.X.)....b...*..!..,Yr+..)..l.2,..1...Y.,..9.....-..A..%J....H.*]...S.P.N.J....Y.j......`...[..Y.h..].....q...;w@.....].7...{'..{........<xd..'..^.8....g6n|.....#...
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 1
-uncompressed_original= 00000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0 ASCII:................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................
-uncompressed=          00000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0 ASCII:................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................
-compressed=            0001330003060e2448b0e08409070f22449870c488850b19326c3863c6c3871021461c3264e2448a142b4e9972f122468c19c78cd9b89123c78e73e67cfc081264c84183468e2449b2e4a449274fa2449972d4a8952b59b26c396bd6cb973061c61c366ce64c9a346b4e9b76f3264e9c39c78ddbb99327cf9ef3e6fdfc091468d0820587124c98d028c2860d93328c189129c48a159f52cc98512ac68e1dab720c19122bc89225b7924c99d22bca962dc3b28c19932ccc9a35cfd2cc99532dce9e3ddbf20c1a142e50a2440d1e3d8a54a9d2a54d9b3a850a35ead4a954ad5abd9a35ab56ae5cbb7efd0a56acd8b165cb9a458b36eddab56cddba7d1b37aedcb97307d4ad7bf0eedd8579f33edcbb7762dfbe17fffedd1838f0c7c18347162e7cf2f0e1958913bf5cbc7866e3c6371f3fde1939f2cf00 ASCII:..3....$H......"D.p.....2l8c....!F.2d.D..+N.r."F.......#..s.|...d.A.F.$I...I'O.D.r...+Y.l9k...0a..6l.L.4kN.v.&N.9.....'........h.....L..(....2...)....R..Q*....r...+..%..L..+..-.....,..5....S-..=......P.D..=.T...M.:..5...T.Z..5.V.\.~..V...e..E.6...l..}.7...s...{....y.>..wb.......8....G..|.......\.xf..7.?..9...
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 2
-uncompressed_original= 00000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0 ASCII:................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................
-uncompressed=          00000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0 ASCII:................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................
-compressed=            0001000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f000000000000000000000000000000000101010101010101010101010101010102020202020202020202020202020202030303030303030303030303030303030404040404040404040404040404040405050505050505050505050505050505060606060606060606060606060606060707070707070707070707070707070708080808080808080808080808080808090909090909090909090909090909090a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0 ASCII:.................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................................................                0000000000000000@@@@@@@@@@@@@@@@PPPPPPPPPPPPPPPP````````````````pppppppppppppppp................................................................................................................................
-memcmp() rc=0
-
-Testing compression/decompression with realistic TCP/IP packets:
-Packet No.: 0
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 0
-uncompressed_original= 45000236000700004006cf2cc0a80002550d93d7400000501e200da7c0c95a70801840002e3700000101080a000174140853d489474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a0d0a ASCII:E..6....@..,....U...@..P. ....Zp..@..7........t..S..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip....
-uncompressed=          45000236000700004006cf2cc0a80002550d93d7400000501e200da7c0c95a70801840002e3700000101080a000174140853d489474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a0d0a ASCII:E..6....@..,....U...@..P. ....Zp..@..7........t..S..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip....
-compressed=            4500010236000700004006cf2cc0a80002550d93d7400000501e200da7c0c95a70801840002e3700000101080a000174140853d489474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c6963330062d990358b562ddb3d6beec079e3620f61bb5dbf861d5b36f0e0c287df68bd8366cfd4b369d7ce518b78440b192d820e2d7a1486913551eda0413a02cf9d343076687d1d9b460ead6cecc891bd03070f183472ef0e3e23c78d1c30f098b103a386562b6bd8a4b923a609132b5a8bb05183633451a377603c2113470d1e326ad024451327e81e189b61cca923270d9b37eb4794107c674e0f193236c7d81d870f9a3a60ed288c61460e1c195888d0b72fc3c98e1933d854a931c3a7e4124197c8b1d35a8f1e3d31fac831e34622c5a05856d78141447d9cd656c8f241e290b9c28e1fd9c8105964441534f9c9ac9601256a701bce3fea1851a4be1e9c32a2b04e52bfa70c1b316c8c9852ff7efebb4c8e4c711e63c6082364ef9faf23960d5919469e1c31123c068da0a5e3c44163666c9ca44ed018d5f9350f9aef458fc2401267e21936e6939e4193e68d58345ad5f4791a346800 ASCII:E...6....@..,....U...@..P. ....Zp..@..7........t..S..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, applic3.b..5.V-.=k..y.b.a.]...[6.....h..f...i..Q.xD..-..-z...5Q..A:...40vh}..F..l........4r..>#...0......V+k...#...+Z..Q.c4Q.w`<!.G..2j.$E.'....a..#'..7.G..|gN..26......:`.(.aF...X.../....3.T.1....A....Z..=1..1.F"..XV..AD}..V..A.........YdD.4.....%jp..?..Q....2..NR....1l..R.~..L.Lq.c..#d...#..Y.F..1.<......Acfl..N....5...E..@.g..6...A...X4Z..y.4h.
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 1
-uncompressed_original= 45000236000700004006cf2cc0a80002550d93d7400000501e200da7c0c95a70801840002e3700000101080a000174140853d489474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a0d0a ASCII:E..6....@..,....U...@..P. ....Zp..@..7........t..S..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip....
-uncompressed=          45000236000700004006cf2cc0a80002550d93d7400000501e200da7c0c95a70801840002e3700000101080a000174140853d489474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a0d0a ASCII:E..6....@..,....U...@..P. ....Zp..@..7........t..S..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip....
-compressed=            450000030ae418a060c0802109a4bd18b68a20160896b40d493825c40808aa8631eb3267d0068b31742424406041830104ee5c5860e51a232548ae8c903162c9952b5364d088410342032266cca09973a7c7083878dedc6133874c9d3b32e0b0d983e6cc8b1164e6cc79c3c60c19a772e2c8c813e74c0c3d5c632c6dfa34ea9db656b16ae5ea15ac583664cda255cb76cf9a3b70deb8d843d86ed7af61c7960d3cb8f0e1375aefa0d933f56cdab573d4221ed142468ba0438b1e8561644d543b68908ec073270d8c1d5a5fc7a691432b1b3b7264efc0c103068ddcbb83cfc87123070c3c66ecc0a8a1d5ca1a3669ee8869c2c48ad6226cd4e0184dd4e81d184fc8c45183878c1a3449d1c409ba07c6661873eac849c3e6cdfa112504df99d343868ccd3176c7e183a60e583b0a6398910347061622f4edcb70b263c60c36556accf029b944d02572ecb4d6a3474f8c3e72ccb89148312896d5756010511fa7b515b27c903864aeb0e347363244161951054d7e32ab6540891adc86f38f3a4614a9af07a78c28ac93d4ef29c3460c1b23a6d4bf9fff2e9323539cc79831c208d9fbe7eb88654356869127478c048f412368e93871d098191b27a9133446757ecd83e67bd1a33090c49978868df9a467d0a47923168d56357d9e060d1a00 ASCII:E.......`..!...... .....I8%.....1.2g...1t$$@`A....\X`..#%H...1b..+Sd..A.B."f...s...8x..a3.L.;2........d..y.....r.....L.=\c,m.4...V.j....X6d..U.v..;p...C.n..a...<...7Z...3.l..s."..BF..C...adMT;h...s'...Z_...C+.;rd...........q#..<f.......6i..i...."l...M....O..Q....4I......f.s..I.....%....C...1v.....X;.c...G.."...p.c..6Uj..).D.%r....GO.>r...H1(..u`.Q.....|.8d...G62D..Q.M~2.e@......:F......(....).F..#.......#S...1.......eCV..'G...A#h.8q....'..4Fu~...{..0...x....g..y#..V5}.....
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 2
-uncompressed_original= 45000236000700004006cf2cc0a80002550d93d7400000501e200da7c0c95a70801840002e3700000101080a000174140853d489474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a0d0a ASCII:E..6....@..,....U...@..P. ....Zp..@..7........t..S..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip....
-uncompressed=          45000236000700004006cf2cc0a80002550d93d7400000501e200da7c0c95a70801840002e3700000101080a000174140853d489474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a0d0a ASCII:E..6....@..,....U...@..P. ....Zp..@..7........t..S..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip....
-compressed=            4500010236000700004006cf2cc0a80002550d93d7400000501e200da7c0c95a70801840002e3700000101080a000174140853d489474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d3133012d323030372042726f777365722f4e657446726f6e742f332e332050726f6601696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a0d0a ASCII:E...6....@..,....U...@..P. ....Zp..@..7........t..S..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13.-2007 Browser/NetFront/3.3 Prof.ile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip....
-memcmp() rc=0
-
-Testing compression/decompression with realistic TCP/IP packets:
-Packet No.: 1
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 0
-uncompressed_original= 4510004046dd40004006a9a7c0a8646ec0a864640017ad8b81980100f3ac984d801800e32a1600000101080a000647de06d1bf5efffd18fffd20fffd23fffd27 ASCII:E..@F.@.@.....dn..dd...........M....*.........G....^..... ..#..'
-uncompressed=          4510004046dd40004006a9a7c0a8646ec0a864640017ad8b81980100f3ac984d801800e32a1600000101080a000647de06d1bf5efffd18fffd20fffd23fffd27 ASCII:E..@F.@.@.....dn..dd...........M....*.........G....^..... ..#..'
-compressed=            451000014046dd40004006a9a7c0a8646ec0a864640017ad8b81980100f3ac984d801800e32a1600000101080a000647de06d1bf5efffd18fffd20fffd23fffd27 ASCII:E...@F.@.@.....dn..dd...........M....*.........G....^..... ..#..'
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 1
-uncompressed_original= 4510004046dd40004006a9a7c0a8646ec0a864640017ad8b81980100f3ac984d801800e32a1600000101080a000647de06d1bf5efffd18fffd20fffd23fffd27 ASCII:E..@F.@.@.....dn..dd...........M....*.........G....^..... ..#..'
-uncompressed=          4510004046dd40004006a9a7c0a8646ec0a864640017ad8b81980100f3ac984d801800e32a1600000101080a000647de06d1bf5efffd18fffd20fffd23fffd27 ASCII:E..@F.@.@.....dn..dd...........M....*.........G....^..... ..#..'
-compressed=            45000013060c49026e48c104ac540d5b75268ec33367066880e588d0260203ecbdda0465d08601e65a641830800081050d062450122e013561610402dc5073444d1335550400 ASCII:E.....I.nH...T.[u&..3g.h....&......e....Zd.0......$P...5aa...PsDM.5U..
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 2
-uncompressed_original= 4510004046dd40004006a9a7c0a8646ec0a864640017ad8b81980100f3ac984d801800e32a1600000101080a000647de06d1bf5efffd18fffd20fffd23fffd27 ASCII:E..@F.@.@.....dn..dd...........M....*.........G....^..... ..#..'
-uncompressed=          4510004046dd40004006a9a7c0a8646ec0a864640017ad8b81980100f3ac984d801800e32a1600000101080a000647de06d1bf5efffd18fffd20fffd23fffd27 ASCII:E..@F.@.@.....dn..dd...........M....*.........G....^..... ..#..'
-compressed=            451000014046dd40004006a9a7c0a8646ec0a864640017ad8b81980100f3ac984d801800e32a1600000101080a000647de06d1bf5efffd18fffd20fffd23fffd27 ASCII:E...@F.@.@.....dn..dd...........M....*.........G....^..... ..#..'
-memcmp() rc=0
-
-Testing compression/decompression with realistic TCP/IP packets:
-Packet No.: 2
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 0
-uncompressed_original= 4510005b46de40004006a98bc0a8646ec0a864640017ad8b8198010cf3ac984d801800e3867500000101080a000647df06d1bf61fffb03fffd1ffffd21fffe22fffb05fffa2001fff0fffa2301fff0fffa2701fff0fffa1801fff0 ASCII:E..[F.@.@.....dn..dd...........M.....u........G....a........!.."..... .....#.....'.........
-uncompressed=          4510005b46de40004006a98bc0a8646ec0a864640017ad8b8198010cf3ac984d801800e3867500000101080a000647df06d1bf61fffb03fffd1ffffd21fffe22fffb05fffa2001fff0fffa2301fff0fffa2701fff0fffa1801fff0 ASCII:E..[F.@.@.....dn..dd...........M.....u........G....a........!.."..... .....#.....'.........
-compressed=            451000015b46de40004006a98bc0a8646ec0a864640017ad8b8198010cf3ac984d801800e3867500000101080a000647df06d1bf61fffb03fffd1ffffd21fffe22fffb05fffa2001fff0fffa2301fff0fffa2701fff0fffa1801fff0 ASCII:E...[F.@.@.....dn..dd...........M.....u........G....a........!.."..... .....#.....'.........
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 1
-uncompressed_original= 4510005b46de40004006a98bc0a8646ec0a864640017ad8b8198010cf3ac984d801800e3867500000101080a000647df06d1bf61fffb03fffd1ffffd21fffe22fffb05fffa2001fff0fffa2301fff0fffa2701fff0fffa1801fff0 ASCII:E..[F.@.@.....dn..dd...........M.....u........G....a........!.."..... .....#.....'.........
-uncompressed=          4510005b46de40004006a98bc0a8646ec0a864640017ad8b8198010cf3ac984d801800e3867500000101080a000647df06d1bf61fffb03fffd1ffffd21fffe22fffb05fffa2001fff0fffa2301fff0fffa2701fff0fffa1801fff0 ASCII:E..[F.@.@.....dn..dd...........M.....u........G....a........!.."..... .....#.....'.........
-compressed=            45000013067849126ec880210958391ab6ea4c9c8767ce0cd000cb11a14d041ed87bb509caa00d03cc25c233600001020b1a0c48a0445c026ac2c808f467402040113949080c58c2260281fd461010386fa809a348fba9583a74c3d200 ASCII:E....xI.n..!.X9...L..g.......M...{.......%.3`......H.D\.j....g@ @.9I..X.&...F..8o...H..X:t...
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 2
-uncompressed_original= 4510005b46de40004006a98bc0a8646ec0a864640017ad8b8198010cf3ac984d801800e3867500000101080a000647df06d1bf61fffb03fffd1ffffd21fffe22fffb05fffa2001fff0fffa2301fff0fffa2701fff0fffa1801fff0 ASCII:E..[F.@.@.....dn..dd...........M.....u........G....a........!.."..... .....#.....'.........
-uncompressed=          4510005b46de40004006a98bc0a8646ec0a864640017ad8b8198010cf3ac984d801800e3867500000101080a000647df06d1bf61fffb03fffd1ffffd21fffe22fffb05fffa2001fff0fffa2301fff0fffa2701fff0fffa1801fff0 ASCII:E..[F.@.@.....dn..dd...........M.....u........G....a........!.."..... .....#.....'.........
-compressed=            451000015b46de40004006a98bc0a8646ec0a864640017ad8b8198010cf3ac984d801800e3867500000101080a000647df06d1bf61fffb03fffd1ffffd21fffe22fffb05fffa2001fff0fffa2301fff0fffa2701fff0fffa1801fff0 ASCII:E...[F.@.@.....dn..dd...........M.....u........G....a........!.."..... .....#.....'.........
-memcmp() rc=0
-
-Testing compression/decompression with realistic TCP/IP packets:
-Packet No.: 3
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 0
-uncompressed_original= 4510003746df40004006a9aec0a8646ec0a864640017ad8b81980133f3ac989f801800e35fd700000101080a000647e106d1bf63fffd01 ASCII:E..7F.@.@.....dn..dd.......3........_.........G....c...
-uncompressed=          4510003746df40004006a9aec0a8646ec0a864640017ad8b81980133f3ac989f801800e35fd700000101080a000647e106d1bf63fffd01 ASCII:E..7F.@.@.....dn..dd.......3........_.........G....c...
-compressed=            451000013746df40004006a9aec0a8646ec0a864640017ad8b8198013301f3ac989f801800e35fd700000101080a000647e106d1bf63fffd01 ASCII:E...7F.@.@.....dn..dd.......3........._.........G....c...
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 1
-uncompressed_original= 4510003746df40004006a9aec0a8646ec0a864640017ad8b81980133f3ac989f801800e35fd700000101080a000647e106d1bf63fffd01 ASCII:E..7F.@.@.....dn..dd.......3........_.........G....c...
-uncompressed=          4510003746df40004006a9aec0a8646ec0a864640017ad8b81980133f3ac989f801800e35fd700000101080a000647e106d1bf63fffd01 ASCII:E..7F.@.@.....dn..dd.......3........_.........G....c...
-compressed=            4500001306e848226ec880210958c51ab6ea4c9c8767ce0cd000cb11a14d046cd87bb549d4a00d03cc89d136600001020b1a0c48a0845c026ac2cc0804482000 ASCII:E.....H"n..!.X....L..g.......M.l.{.I.......6`......H..\.j....H .
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 2
-uncompressed_original= 4510003746df40004006a9aec0a8646ec0a864640017ad8b81980133f3ac989f801800e35fd700000101080a000647e106d1bf63fffd01 ASCII:E..7F.@.@.....dn..dd.......3........_.........G....c...
-uncompressed=          4510003746df40004006a9aec0a8646ec0a864640017ad8b81980133f3ac989f801800e35fd700000101080a000647e106d1bf63fffd01 ASCII:E..7F.@.@.....dn..dd.......3........_.........G....c...
-compressed=            451000013746df40004006a9aec0a8646ec0a864640017ad8b8198013301f3ac989f801800e35fd700000101080a000647e106d1bf63fffd01 ASCII:E...7F.@.@.....dn..dd.......3........._.........G....c...
-memcmp() rc=0
-
-Testing compression/decompression with realistic TCP/IP packets:
-Packet No.: 4
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 0
-uncompressed_original= 4510003746e040004006a9adc0a8646ec0a864640017ad8b81980136f3ac98a2801800e35fd200000101080a000647e106d1bf64fffb01 ASCII:E..7F.@.@.....dn..dd.......6........_.........G....d...
-uncompressed=          4510003746e040004006a9adc0a8646ec0a864640017ad8b81980136f3ac98a2801800e35fd200000101080a000647e106d1bf64fffb01 ASCII:E..7F.@.@.....dn..dd.......6........_.........G....d...
-compressed=            451000013746e040004006a9adc0a8646ec0a864640017ad8b81980136f3ac98a2801800e35fd200000101080a000647e106d1bf64fffb01 ASCII:E...7F.@.@.....dn..dd.......6........_.........G....d...
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 1
-uncompressed_original= 4510003746e040004006a9adc0a8646ec0a864640017ad8b81980136f3ac98a2801800e35fd200000101080a000647e106d1bf64fffb01 ASCII:E..7F.@.@.....dn..dd.......6........_.........G....d...
-uncompressed=          4510003746e040004006a9adc0a8646ec0a864640017ad8b81980136f3ac98a2801800e35fd200000101080a000647e106d1bf64fffb01 ASCII:E..7F.@.@.....dn..dd.......6........_.........G....d...
-compressed=            4500001306e848326ec880210958c11ab6ea4c9c8767ce0cd000cb11a14d0472d87bb5a9d4a00d03cc89a936600001020b1a0c48a0845c026ac2ce08f4472000 ASCII:E.....H2n..!.X....L..g.......M.r.{.........6`......H..\.j....G .
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 2
-uncompressed_original= 4510003746e040004006a9adc0a8646ec0a864640017ad8b81980136f3ac98a2801800e35fd200000101080a000647e106d1bf64fffb01 ASCII:E..7F.@.@.....dn..dd.......6........_.........G....d...
-uncompressed=          4510003746e040004006a9adc0a8646ec0a864640017ad8b81980136f3ac98a2801800e35fd200000101080a000647e106d1bf64fffb01 ASCII:E..7F.@.@.....dn..dd.......6........_.........G....d...
-compressed=            451000013746e040004006a9adc0a8646ec0a864640017ad8b81980136f3ac98a2801800e35fd200000101080a000647e106d1bf64fffb01 ASCII:E...7F.@.@.....dn..dd.......6........_.........G....d...
-memcmp() rc=0
-
-Testing compression/decompression with realistic TCP/IP packets:
-Packet No.: 5
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 0
-uncompressed_original= 4510007446e140004006a96fc0a8646ec0a864640017ad8b81980139f3ac98a5801800e37b9b00000101080a000647e206d1bf640d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a57656c6c636f6d6520746f20706f6c6c75780d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a0d0a ASCII:E..tF.@.@..o..dn..dd.......9........{.........G....d..------------------..Wellcome to pollux..------------------....
-uncompressed=          4510007446e140004006a96fc0a8646ec0a864640017ad8b81980139f3ac98a5801800e37b9b00000101080a000647e206d1bf640d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a57656c6c636f6d6520746f20706f6c6c75780d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a0d0a ASCII:E..tF.@.@..o..dn..dd.......9........{.........G....d..------------------..Wellcome to pollux..------------------....
-compressed=            451000017446e140004006a96fc0a8646ec0a864640017ad8b81980139f3ac98a5801800e37b9b00000101080a000647e206d1bf640d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d3300386d6a41f3e68d193970d08cb82367c41c3940f1ecb1b97327549e0d6c0600 ASCII:E...tF.@.@..o..dn..dd.......9........{.........G....d..----------------3.8mjA....9p...#g..9@....s'T..l..
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 1
-uncompressed_original= 4510007446e140004006a96fc0a8646ec0a864640017ad8b81980139f3ac98a5801800e37b9b00000101080a000647e206d1bf640d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a57656c6c636f6d6520746f20706f6c6c75780d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a0d0a ASCII:E..tF.@.@..o..dn..dd.......9........{.........G....d..------------------..Wellcome to pollux..------------------....
-uncompressed=          4510007446e140004006a96fc0a8646ec0a864640017ad8b81980139f3ac98a5801800e37b9b00000101080a000647e206d1bf640d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a57656c6c636f6d6520746f20706f6c6c75780d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a0d0a ASCII:E..tF.@.@..o..dn..dd.......9........{.........G....d..------------------..Wellcome to pollux..------------------....
-compressed=            4500001306dc49426ec880210958c919b6ea4c9c8767ce0cd000cb11a14d0478d87bb509d5a00d03ccf9f134600001020b1a0c48a0a45c026ac2ce40680003064e9c3973eac469530b9a376fccc8818366c41d3923e6c8018a678fcd9d3ba1f26c603300 ASCII:E.....IBn..!.X....L..g.......M.x.{.........4`......H..\.j..@h...N.9s..iS..7o....f..9#....g...;..l`3.
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 2
-uncompressed_original= 4510007446e140004006a96fc0a8646ec0a864640017ad8b81980139f3ac98a5801800e37b9b00000101080a000647e206d1bf640d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a57656c6c636f6d6520746f20706f6c6c75780d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a0d0a ASCII:E..tF.@.@..o..dn..dd.......9........{.........G....d..------------------..Wellcome to pollux..------------------....
-uncompressed=          4510007446e140004006a96fc0a8646ec0a864640017ad8b81980139f3ac98a5801800e37b9b00000101080a000647e206d1bf640d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a57656c6c636f6d6520746f20706f6c6c75780d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a0d0a ASCII:E..tF.@.@..o..dn..dd.......9........{.........G....d..------------------..Wellcome to pollux..------------------....
-compressed=            451000017446e140004006a96fc0a8646ec0a864640017ad8b81980139f3ac98a5801800e37b9b00000101080a000647e206d1bf640d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a57656c6c636f6d6520746f20706f6c6c75780d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d0d0a0d0a ASCII:E...tF.@.@..o..dn..dd.......9........{.........G....d..------------------..Wellcome to pollux..------------------....
-memcmp() rc=0
-
-Testing compression/decompression with realistic TCP/IP packets:
-Packet No.: 6
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 0
-uncompressed_original= 4510004246e240004006a9a0c0a8646ec0a864640017ad8b81980179f3ac98a5801800e3dab000000101080a000647ec06d1bf6f706f6c6c7578206c6f67696e3a20 ASCII:E..BF.@.@.....dn..dd.......y..................G....opollux login: 
-uncompressed=          4510004246e240004006a9a0c0a8646ec0a864640017ad8b81980179f3ac98a5801800e3dab000000101080a000647ec06d1bf6f706f6c6c7578206c6f67696e3a20 ASCII:E..BF.@.@.....dn..dd.......y..................G....opollux login: 
-compressed=            451000014246e240004006a9a0c0a8646ec0a864640017ad8b81980179f3ac98a5801800e3dab000000101080a000647ec06d1bf6f706f6c6c7578206c6f67696e3a20 ASCII:E...BF.@.@.....dn..dd.......y..................G....opollux login: 
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 1
-uncompressed_original= 4510004246e240004006a9a0c0a8646ec0a864640017ad8b81980179f3ac98a5801800e3dab000000101080a000647ec06d1bf6f706f6c6c7578206c6f67696e3a20 ASCII:E..BF.@.@.....dn..dd.......y..................G....opollux login: 
-uncompressed=          4510004246e240004006a9a0c0a8646ec0a864640017ad8b81980179f3ac98a5801800e3dab000000101080a000647ec06d1bf6f706f6c6c7578206c6f67696e3a20 ASCII:E..BF.@.@.....dn..dd.......y..................G....opollux login: 
-compressed=            45000013061449526ec8802109588d1ab6ea4c9c8767ce0cd000cb11a14d04f8d87bb509d5a00d03cc759b35600001020b1a0c48a0e45d026ac2e4cc91f3e60d9e3d23dec851c3264e8f110100 ASCII:E.....IRn..!.X....L..g.......M...{.......u.5`......H..].j........=#..Q.&N....
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 2
-uncompressed_original= 4510004246e240004006a9a0c0a8646ec0a864640017ad8b81980179f3ac98a5801800e3dab000000101080a000647ec06d1bf6f706f6c6c7578206c6f67696e3a20 ASCII:E..BF.@.@.....dn..dd.......y..................G....opollux login: 
-uncompressed=          4510004246e240004006a9a0c0a8646ec0a864640017ad8b81980179f3ac98a5801800e3dab000000101080a000647ec06d1bf6f706f6c6c7578206c6f67696e3a20 ASCII:E..BF.@.@.....dn..dd.......y..................G....opollux login: 
-compressed=            451000014246e240004006a9a0c0a8646ec0a864640017ad8b81980179f3ac98a5801800e3dab000000101080a000647ec06d1bf6f706f6c6c7578206c6f67696e3a20 ASCII:E...BF.@.@.....dn..dd.......y..................G....opollux login: 
-memcmp() rc=0
-
-Testing compression/decompression with realistic TCP/IP packets:
-Packet No.: 7
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 0
-uncompressed_original= 450001a0b41140004006b8e80a0901abc0a800021f904002d5b860b5bab240ae501900ed861d0000485454502f312e3020323030204f4b0d0a5365727665723a2053696d706c65485454502f302e3620507974686f6e2f322e372e360d0a446174653a205475652c2033302041756720323031362030393a34333a303720474d540d0a436f6e74656e742d747970653a20746578742f68746d6c3b20636861727365743d5554462d380d0a436f6e74656e742d4c656e6774683a203232320d0a0d0a3c21444f43545950452068746d6c205055424c494320222d2f2f5733432f2f4454442048544d4c20332e322046696e616c2f2f454e223e3c68746d6c3e0a3c7469746c653e4469726563746f7279206c697374696e6720666f72202f3c2f7469746c653e0a3c626f64793e0a3c68323e4469726563746f7279206c697374696e6720666f72202f3c2f68323e0a3c68723e0a3c756c3e0a3c6c693e3c6120687265663d2272656470686f6e652e706e67223e72656470686f6e652e706e673c2f613e0a3c2f756c3e0a3c68723e0a3c2f626f64793e0a3c2f68746d6c3e0a ASCII:E.....@.@.............@...`...@.P.......HTTP/1.0 200 OK..Server: SimpleHTTP/0.6 Python/2.7.6..Date: Tue, 30 Aug 2016 09:43:07 GMT..Content-type: text/html; charset=UTF-8..Content-Length: 222....<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>.<title>Directory listing for /</title>.<body>.<h2>Directory listing for /</h2>.<hr>.<ul>.<li><a href="redphone.png">redphone.png</a>.</ul>.<hr>.</body>.</html>.
-uncompressed=          450001a0b41140004006b8e80a0901abc0a800021f904002d5b860b5bab240ae501900ed861d0000485454502f312e3020323030204f4b0d0a5365727665723a2053696d706c65485454502f302e3620507974686f6e2f322e372e360d0a446174653a205475652c2033302041756720323031362030393a34333a303720474d540d0a436f6e74656e742d747970653a20746578742f68746d6c3b20636861727365743d5554462d380d0a436f6e74656e742d4c656e6774683a203232320d0a0d0a3c21444f43545950452068746d6c205055424c494320222d2f2f5733432f2f4454442048544d4c20332e322046696e616c2f2f454e223e3c68746d6c3e0a3c7469746c653e4469726563746f7279206c697374696e6720666f72202f3c2f7469746c653e0a3c626f64793e0a3c68323e4469726563746f7279206c697374696e6720666f72202f3c2f68323e0a3c68723e0a3c756c3e0a3c6c693e3c6120687265663d2272656470686f6e652e706e67223e72656470686f6e652e706e673c2f613e0a3c2f756c3e0a3c68723e0a3c2f626f64793e0a3c2f68746d6c3e0a ASCII:E.....@.@.............@...`...@.P.......HTTP/1.0 200 OK..Server: SimpleHTTP/0.6 Python/2.7.6..Date: Tue, 30 Aug 2016 09:43:07 GMT..Content-type: text/html; charset=UTF-8..Content-Length: 222....<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>.<title>Directory listing for /</title>.<body>.<h2>Directory listing for /</h2>.<hr>.<ul>.<li><a href="redphone.png">redphone.png</a>.</ul>.<hr>.</body>.</html>.
-compressed=            45000101a0b41140004006b8e80a0901abc0a800021f904002d5b860b5bab240ae501900ed861d0000485454502f312e3020323030204f4b0d0a5365727665723a2053696d706c65485454502f302e3620507974686f6e2f322e372e360d0a446174653a205475652c203301302041756720323031362030393a34333a303720474d540d0a436f6e74656e742d747970653a20746578742f68746d6c3b20636861727365743d5554462d380d0a436f6e74656e742d4c656e6774683a206600356ad4c899f3078923528c5ce13205c908c58c9d6229f2848991112560c890a1050033432f2f4454442048544d4c20332e322046696e616c2f2f454e223e3c68746d6c3e0a3c7469746c653e4469726563746f7279206c697374696e672066016f72202f3c2f7469746c990068bcff2823e70c9fff6b6a943f9f7e7dfbf7f1e7d7bf9f3fb1c2ef6beafcc7d3fd3b7ced6468a34f03a404fa3373a4c64113630efdec27534e7509538d7e32ff657044a8f1bb0c82067f72f71e00 ASCII:E......@.@.............@...`...@.P.......HTTP/1.0 200 OK..Server: SimpleHTTP/0.6 Python/2.7.6..Date: Tue, 3.0 Aug 2016 09:43:07 GMT..Content-type: text/html; charset=UTF-8..Content-Length: f.5j......#R.\.2......b).....%`.....3C//DTD HTML 3.2 Final//EN"><html>.<title>Directory listing f.or /</titl..h..(#....kj.?.~}.......?...k.....;|.dh.O....3s..A.c...'SNu.S.~2.epD.......r...
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 1
-uncompressed_original= 450001a0b41140004006b8e80a0901abc0a800021f904002d5b860b5bab240ae501900ed861d0000485454502f312e3020323030204f4b0d0a5365727665723a2053696d706c65485454502f302e3620507974686f6e2f322e372e360d0a446174653a205475652c2033302041756720323031362030393a34333a303720474d540d0a436f6e74656e742d747970653a20746578742f68746d6c3b20636861727365743d5554462d380d0a436f6e74656e742d4c656e6774683a203232320d0a0d0a3c21444f43545950452068746d6c205055424c494320222d2f2f5733432f2f4454442048544d4c20332e322046696e616c2f2f454e223e3c68746d6c3e0a3c7469746c653e4469726563746f7279206c697374696e6720666f72202f3c2f7469746c653e0a3c626f64793e0a3c68323e4469726563746f7279206c697374696e6720666f72202f3c2f68323e0a3c68723e0a3c756c3e0a3c6c693e3c6120687265663d2272656470686f6e652e706e67223e72656470686f6e652e706e673c2f613e0a3c2f756c3e0a3c68723e0a3c2f626f64793e0a3c2f68746d6c3e0a ASCII:E.....@.@.............@...`...@.P.......HTTP/1.0 200 OK..Server: SimpleHTTP/0.6 Python/2.7.6..Date: Tue, 30 Aug 2016 09:43:07 GMT..Content-type: text/html; charset=UTF-8..Content-Length: 222....<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>.<title>Directory listing for /</title>.<body>.<h2>Directory listing for /</h2>.<hr>.<ul>.<li><a href="redphone.png">redphone.png</a>.</ul>.<hr>.</body>.</html>.
-uncompressed=          450001a0b41140004006b8e80a0901abc0a800021f904002d5b860b5bab240ae501900ed861d0000485454502f312e3020323030204f4b0d0a5365727665723a2053696d706c65485454502f302e3620507974686f6e2f322e372e360d0a446174653a205475652c2033302041756720323031362030393a34333a303720474d540d0a436f6e74656e742d747970653a20746578742f68746d6c3b20636861727365743d5554462d380d0a436f6e74656e742d4c656e6774683a203232320d0a0d0a3c21444f43545950452068746d6c205055424c494320222d2f2f5733432f2f4454442048544d4c20332e322046696e616c2f2f454e223e3c68746d6c3e0a3c7469746c653e4469726563746f7279206c697374696e6720666f72202f3c2f7469746c653e0a3c626f64793e0a3c68323e4469726563746f7279206c697374696e6720666f72202f3c2f68323e0a3c68723e0a3c756c3e0a3c6c693e3c6120687265663d2272656470686f6e652e706e67223e72656470686f6e652e706e673c2f613e0a3c2f756c3e0a3c68723e0a3c2f626f64793e0a3c2f68746d6c3e0a ASCII:E.....@.@.............@...`...@.P.......HTTP/1.0 200 OK..Server: SimpleHTTP/0.6 Python/2.7.6..Date: Tue, 30 Aug 2016 09:43:07 GMT..Content-type: text/html; charset=UTF-8..Content-Length: 222....<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>.<title>Directory listing for /</title>.<body>.<h2>Directory listing for /</h2>.<hr>.<ul>.<li><a href="redphone.png">redphone.png</a>.</ul>.<hr>.</body>.</html>.
-compressed=            45000003088cba4561c880210976ad6bc08080ab61ab061410316948016cbbc6e0ea556b48ac291c06c04b0462c0802557ae4c914123c68c113566c894e20442032b68eae4e1d96384153670e6bc41b3b2a58c1931728c98c2e7ce1a397164d488a18369ce2364eea0017a050f9a17236cc8248247cdcc19349acee0d1e3868d1e33748c5002e54a4e2353bbc6b903e30e9f395e4774dd7347c69a3b70def81861660d993a76d0dc0182e54a12183bf4f245e317c693cf6aa202ad51a346ce9c3f481c9162e40a972948462866ec144b91274c8c8c280143860c2d368c003f72e5c88895509e908d516344123671c8bc018e244a89203f6abf09d2e0c71d36778c0639c2a60e1a3377e4d4e133e20d1b3be1e3a44dc37e848c1f32c28f47e3fd47193967f8fc5f53a3fcf9f4ebdbbf8f3fbffefdfc89157e5f53e73f9eeedfe16b27431b7d1a2025d09f9923350e9a1873e8673f9972aa4b986af493f92f8323428ddf651034f893bbf700 ASCII:E......Ea..!.v.k....a....1iH.l....UkH.)...K.b..%W.L.A#...5f....B.+h....c..6p..A.....1r......9qd....i.#d...z....#l.$.G...4........3t.P..JN#S.......9^Gt.sG..;p...af..:v.....J..;..E.....j...Q.F..?H..b...)HF(f..K.'L..(.C..-6..?r....P...QcD.6q....$J. ?j......6w..9....3w...3...;...M.~...2..G..G.9g.._S........?......~_S.?....k'C.}. %...#5...s.g?.r.K.j.../.#B..e.4.....
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 2
-uncompressed_original= 450001a0b41140004006b8e80a0901abc0a800021f904002d5b860b5bab240ae501900ed861d0000485454502f312e3020323030204f4b0d0a5365727665723a2053696d706c65485454502f302e3620507974686f6e2f322e372e360d0a446174653a205475652c2033302041756720323031362030393a34333a303720474d540d0a436f6e74656e742d747970653a20746578742f68746d6c3b20636861727365743d5554462d380d0a436f6e74656e742d4c656e6774683a203232320d0a0d0a3c21444f43545950452068746d6c205055424c494320222d2f2f5733432f2f4454442048544d4c20332e322046696e616c2f2f454e223e3c68746d6c3e0a3c7469746c653e4469726563746f7279206c697374696e6720666f72202f3c2f7469746c653e0a3c626f64793e0a3c68323e4469726563746f7279206c697374696e6720666f72202f3c2f68323e0a3c68723e0a3c756c3e0a3c6c693e3c6120687265663d2272656470686f6e652e706e67223e72656470686f6e652e706e673c2f613e0a3c2f756c3e0a3c68723e0a3c2f626f64793e0a3c2f68746d6c3e0a ASCII:E.....@.@.............@...`...@.P.......HTTP/1.0 200 OK..Server: SimpleHTTP/0.6 Python/2.7.6..Date: Tue, 30 Aug 2016 09:43:07 GMT..Content-type: text/html; charset=UTF-8..Content-Length: 222....<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>.<title>Directory listing for /</title>.<body>.<h2>Directory listing for /</h2>.<hr>.<ul>.<li><a href="redphone.png">redphone.png</a>.</ul>.<hr>.</body>.</html>.
-uncompressed=          450001a0b41140004006b8e80a0901abc0a800021f904002d5b860b5bab240ae501900ed861d0000485454502f312e3020323030204f4b0d0a5365727665723a2053696d706c65485454502f302e3620507974686f6e2f322e372e360d0a446174653a205475652c2033302041756720323031362030393a34333a303720474d540d0a436f6e74656e742d747970653a20746578742f68746d6c3b20636861727365743d5554462d380d0a436f6e74656e742d4c656e6774683a203232320d0a0d0a3c21444f43545950452068746d6c205055424c494320222d2f2f5733432f2f4454442048544d4c20332e322046696e616c2f2f454e223e3c68746d6c3e0a3c7469746c653e4469726563746f7279206c697374696e6720666f72202f3c2f7469746c653e0a3c626f64793e0a3c68323e4469726563746f7279206c697374696e6720666f72202f3c2f68323e0a3c68723e0a3c756c3e0a3c6c693e3c6120687265663d2272656470686f6e652e706e67223e72656470686f6e652e706e673c2f613e0a3c2f756c3e0a3c68723e0a3c2f626f64793e0a3c2f68746d6c3e0a ASCII:E.....@.@.............@...`...@.P.......HTTP/1.0 200 OK..Server: SimpleHTTP/0.6 Python/2.7.6..Date: Tue, 30 Aug 2016 09:43:07 GMT..Content-type: text/html; charset=UTF-8..Content-Length: 222....<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>.<title>Directory listing for /</title>.<body>.<h2>Directory listing for /</h2>.<hr>.<ul>.<li><a href="redphone.png">redphone.png</a>.</ul>.<hr>.</body>.</html>.
-compressed=            45000101a0b41140004006b8e80a0901abc0a800021f904002d5b860b5bab240ae501900ed861d0000485454502f312e3020323030204f4b0d0a5365727665723a2053696d706c65485454502f302e3620507974686f6e2f322e372e360d0a446174653a205475652c203301302041756720323031362030393a34333a303720474d540d0a436f6e74656e742d747970653a20746578742f68746d6c3b20636861727365743d5554462d380d0a436f6e74656e742d4c656e6774683a203232320d0a0d0a3c21444f43545950452068746d6c205055424c494320222d2f2f5733432f2f4454442048544d4c20332e322046696e616c2f2f454e223e3c68746d6c3e0a3c7469746c653e4469726563746f7279206c697374696e672066016f72202f3c2f7469746c653e0a3c626f64793e0a3c68323e4469726563746f7279206c697374696e6720666f72202f3c2f68323e0a3c68723e0a3c756c3e0a3c6c693e3c6120687265663d2272656470686f6e652e706e67223e72656470686f6e652e706e673c2f613e0a3c2f756c3e0a3c68723e0a3c2f626f64793e0a3c2f68746d6c3e0a ASCII:E......@.@.............@...`...@.P.......HTTP/1.0 200 OK..Server: SimpleHTTP/0.6 Python/2.7.6..Date: Tue, 3.0 Aug 2016 09:43:07 GMT..Content-type: text/html; charset=UTF-8..Content-Length: 222....<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>.<title>Directory listing f.or /</title>.<body>.<h2>Directory listing for /</h2>.<hr>.<ul>.<li><a href="redphone.png">redphone.png</a>.</ul>.<hr>.</body>.</html>.
-memcmp() rc=0
-
-Testing compression/decompression with realistic TCP/IP packets:
-Packet No.: 8
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 0
-uncompressed_original= 450000e2971b40003706026c550d93d7c0a8000200504047217f5922c903759c8018007c4fb400000101080a1153ce39002cf6e8485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613134392d3436652d34323736386138656338656330220d0a0d0a ASCII:E.....@.7..lU........P@G!.Y"..u....|O........S.9.,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:40 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8a149-46e-42768a8ec8ec0"....
-uncompressed=          450000e2971b40003706026c550d93d7c0a8000200504047217f5922c903759c8018007c4fb400000101080a1153ce39002cf6e8485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613134392d3436652d34323736386138656338656330220d0a0d0a ASCII:E.....@.7..lU........P@G!.Y"..u....|O........S.9.,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:40 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8a149-46e-42768a8ec8ec0"....
-compressed=            45000100e2971b40003706026c550d93d7c0a8000200504047217f5922c903759c8018007c4fb400000101080a1153ce39002cf6e8485454502f312e312033013034204e6f74204d6f646966016965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613134392d3436652d3432373638613865633865990066669478fa3400 ASCII:E......@.7..lU........P@G!.Y"..u....|O........S.9.,..HTTP/1.1 3.04 Not Modif.ied..Date: Tue, 30 Aug 2016 16:36:40 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8a149-46e-42768a8ec8e..ff.x.4.
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 1
-uncompressed_original= 450000e2971b40003706026c550d93d7c0a8000200504047217f5922c903759c8018007c4fb400000101080a1153ce39002cf6e8485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613134392d3436652d34323736386138656338656330220d0a0d0a ASCII:E.....@.7..lU........P@G!.Y"..u....|O........S.9.,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:40 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8a149-46e-42768a8ec8ec0"....
-uncompressed=          450000e2971b40003706026c550d93d7c0a8000200504047217f5922c903759c8018007c4fb400000101080a1153ce39002cf6e8485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613134392d3436652d34323736386138656338656330220d0a0d0a ASCII:E.....@.7..lU........P@G!.Y"..u....|O........S.9.,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:40 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8a149-46e-42768a8ec8ec0"....
-compressed=            450000030694d3e461c8001d090abcc102c192b661ab061418306588121282b894606600cfa7411b06fc91728b2001020b1a50b0128dc78017f9d62db972658a0c1a31688cb031e3c6882872ee8c8022e70c9b346cd09c81d0e008993b687a8cb88207cd0b9f334610c1a366448d1934728c20dbc3468e1e37b82a8172e5a9153475f2ccad4a640e19336bd03c3522274e1c3466eeb0015cd5091a3473601079c3a6eed3c48b1b3fae5bb5301c3472f0dc0152432b1c327b80d0983163c6532457c8a8a95ae286991d6468dce001e3460e34b76be8c8217bc760e066669478fa3400 ASCII:E.......a...........a....0e......`f...A....r. ....P........-.re...1h..1...(r..."...4l.......;hz.......3F...fD..4r. ..F..7.*.r...4u...Jd..3k.<5"'N.4f...\...4s`.y.......?.[.0.4r...RC+.2{...1c.S$W...Z....dh....F.4.k..!{.`.ff.x.4.
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 2
-uncompressed_original= 450000e2971b40003706026c550d93d7c0a8000200504047217f5922c903759c8018007c4fb400000101080a1153ce39002cf6e8485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613134392d3436652d34323736386138656338656330220d0a0d0a ASCII:E.....@.7..lU........P@G!.Y"..u....|O........S.9.,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:40 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8a149-46e-42768a8ec8ec0"....
-uncompressed=          450000e2971b40003706026c550d93d7c0a8000200504047217f5922c903759c8018007c4fb400000101080a1153ce39002cf6e8485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613134392d3436652d34323736386138656338656330220d0a0d0a ASCII:E.....@.7..lU........P@G!.Y"..u....|O........S.9.,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:40 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8a149-46e-42768a8ec8ec0"....
-compressed=            45000100e2971b40003706026c550d93d7c0a8000200504047217f5922c903759c8018007c4fb400000101080a1153ce39002cf6e8485454502f312e312033013034204e6f74204d6f646966016965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613134392d3436652d34323736386138656338656330220d0a0d0a ASCII:E......@.7..lU........P@G!.Y"..u....|O........S.9.,..HTTP/1.1 3.04 Not Modif.ied..Date: Tue, 30 Aug 2016 16:36:40 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8a149-46e-42768a8ec8ec0"....
-memcmp() rc=0
-
-Testing compression/decompression with realistic TCP/IP packets:
-Packet No.: 9
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 0
-uncompressed_original= 450000e224f1400037067496550d93d7c0a80002005040489387ebf0c904389f8018007cec5700000101080a1153cf01002cf8fc485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613338302d3861362d34323736383761323236383830220d0a0d0a ASCII:E...$.@.7.t.U........P@H......8....|.W.......S...,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:40 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8a380-8a6-427687a226880"....
-uncompressed=          450000e224f1400037067496550d93d7c0a80002005040489387ebf0c904389f8018007cec5700000101080a1153cf01002cf8fc485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613338302d3861362d34323736383761323236383830220d0a0d0a ASCII:E...$.@.7.t.U........P@H......8....|.W.......S...,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:40 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8a380-8a6-427687a226880"....
-compressed=            45000100e224f1400037067496550d93d7c0a80002005040489387ebf0c904389f8018007cec5700000101080a1153cf01002cf8fc485454502f312e312033013034204e6f74204d6f646966016965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613338302d3861362d34323736383761323236383830220d0a0d0a ASCII:E....$.@.7.t.U........P@H......8....|.W.......S...,..HTTP/1.1 3.04 Not Modif.ied..Date: Tue, 30 Aug 2016 16:36:40 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8a380-8a6-427687a226880"....
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 1
-uncompressed_original= 450000e224f1400037067496550d93d7c0a80002005040489387ebf0c904389f8018007cec5700000101080a1153cf01002cf8fc485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613338302d3861362d34323736383761323236383830220d0a0d0a ASCII:E...$.@.7.t.U........P@H......8....|.W.......S...,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:40 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8a380-8a6-427687a226880"....
-uncompressed=          450000e224f1400037067496550d93d7c0a80002005040489387ebf0c904389f8018007cec5700000101080a1153cf01002cf8fc485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613338302d3861362d34323736383761323236383830220d0a0d0a ASCII:E...$.@.7.t.U........P@H......8....|.W.......S...,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:40 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8a380-8a6-427687a226880"....
-compressed=            4500000306943b416fc8001d09ee64c202c192b661ab0614183065c8124b8adccd63766087a8411b06fc79a7852001020b1a50b0228dc08017fbfe2db972658a0c1a31688cb031e3c6882872ee8c8022e70c9b346cd09c81d0e008993b687a8cb88207cd0b9f334610c1a366448d1934728c20dbc3468e1e37b82a8172e5a9153475f2ccad4a640e19336bd03c3522274e1c3466eeb0015cd5091a3473601079c3a6eed3c48b1b3fae5bb5301c3472f0dc0152432b1c327b80d0983163c6532457c8a8a95ae286991d646cec980143760e18376ae8c8b14307991a357cd72ef1f46900 ASCII:E.....;Ao.....d.....a....0e..K...cv`..A...y.. ....P."......-.re...1h..1...(r..."...4l.......;hz.......3F...fD..4r. ..F..7.*.r...4u...Jd..3k.<5"'N.4f...\...4s`.y.......?.[.0.4r...RC+.2{...1c.S$W...Z....dl...Cv..7j...C...5|....i.
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 2
-uncompressed_original= 450000e224f1400037067496550d93d7c0a80002005040489387ebf0c904389f8018007cec5700000101080a1153cf01002cf8fc485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613338302d3861362d34323736383761323236383830220d0a0d0a ASCII:E...$.@.7.t.U........P@H......8....|.W.......S...,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:40 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8a380-8a6-427687a226880"....
-uncompressed=          450000e224f1400037067496550d93d7c0a80002005040489387ebf0c904389f8018007cec5700000101080a1153cf01002cf8fc485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613338302d3861362d34323736383761323236383830220d0a0d0a ASCII:E...$.@.7.t.U........P@H......8....|.W.......S...,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:40 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8a380-8a6-427687a226880"....
-compressed=            45000100e224f1400037067496550d93d7c0a80002005040489387ebf0c904389f8018007cec5700000101080a1153cf01002cf8fc485454502f312e312033013034204e6f74204d6f646966016965640d0a446174653a205475652c2033302041756720323031362031363a33363a343020474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338613338302d3861362d34323736383761323236383830220d0a0d0a ASCII:E....$.@.7.t.U........P@H......8....|.W.......S...,..HTTP/1.1 3.04 Not Modif.ied..Date: Tue, 30 Aug 2016 16:36:40 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8a380-8a6-427687a226880"....
-memcmp() rc=0
-
-Testing compression/decompression with realistic TCP/IP packets:
-Packet No.: 10
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 0
-uncompressed_original= 450000e2b66140003706e325550d93d7c0a8000200504049fbb679bcc9051ea48018007cebea00000101080a1153cfdc002cfdb4485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343120474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338313336642d3138642d34353832306530393638303430220d0a0d0a ASCII:E....a@.7..%U........P@I..y........|.........S...,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:41 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8136d-18d-45820e0968040"....
-uncompressed=          450000e2b66140003706e325550d93d7c0a8000200504049fbb679bcc9051ea48018007cebea00000101080a1153cfdc002cfdb4485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343120474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338313336642d3138642d34353832306530393638303430220d0a0d0a ASCII:E....a@.7..%U........P@I..y........|.........S...,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:41 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8136d-18d-45820e0968040"....
-compressed=            45000100e2b66140003706e325550d93d7c0a8000200504049fbb679bcc9051ea48018007cebea00000101080a1153cfdc002cfdb4485454502f312e312033013034204e6f74204d6f646966016965640d0a446174653a205475652c2033302041756720323031362031363a33363a343120474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338313336642d3138642d34353832306530393638303430220d0a0d0a ASCII:E.....a@.7..%U........P@I..y........|.........S...,..HTTP/1.1 3.04 Not Modif.ied..Date: Tue, 30 Aug 2016 16:36:41 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8136d-18d-45820e0968040"....
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 1
-uncompressed_original= 450000e2b66140003706e325550d93d7c0a8000200504049fbb679bcc9051ea48018007cebea00000101080a1153cfdc002cfdb4485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343120474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338313336642d3138642d34353832306530393638303430220d0a0d0a ASCII:E....a@.7..%U........P@I..y........|.........S...,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:41 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8136d-18d-45820e0968040"....
-uncompressed=          450000e2b66140003706e325550d93d7c0a8000200504049fbb679bcc9051ea48018007cebea00000101080a1153cfdc002cfdb4485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343120474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338313336642d3138642d34353832306530393638303430220d0a0d0a ASCII:E....a@.7..%U........P@I..y........|.........S...,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:41 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8136d-18d-45820e0968040"....
-compressed=            450000030694cb4566c8001d09cca1c002c192b661ab061418306508137fb9f8fc628620c4a9411b06fc71d78e2001020b1a50b022eddb8017006f2db972658a0c1a31688cb031e3c6882872ee8c8022e70c9b346cd09c81d0e008993b687a8cb88207cd0b9f334610c1a366448d1934728c20dbc3468e1e377a2a8172e5a9153475f2ccad4a640e19336bd03c3522274e1c3466eeb0015cd5091a3473601079c3a6eed3c48b1b3fae5bb5301c3472f0dc0152432b1c327b80d0983163c6532457c8a8a95ae286991d34d29e81416347ed1b387688453383478e1d40679478fa3400 ASCII:E......Ef...........a....0e......b. ..A...q.. ....P.".....o-.re...1h..1...(r..."...4l.......;hz.......3F...fD..4r. ..F..7z*.r...4u...Jd..3k.<5"'N.4f...\...4s`.y.......?.[.0.4r...RC+.2{...1c.S$W...Z....4...AcG..8v.E3.G..@g.x.4.
-memcmp() rc=0
-
-v42bis_compress() rc=0
-v42bis_compress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-Mode: 2
-uncompressed_original= 450000e2b66140003706e325550d93d7c0a8000200504049fbb679bcc9051ea48018007cebea00000101080a1153cfdc002cfdb4485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343120474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338313336642d3138642d34353832306530393638303430220d0a0d0a ASCII:E....a@.7..%U........P@I..y........|.........S...,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:41 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8136d-18d-45820e0968040"....
-uncompressed=          450000e2b66140003706e325550d93d7c0a8000200504049fbb679bcc9051ea48018007cebea00000101080a1153cfdc002cfdb4485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a205475652c2033302041756720323031362031363a33363a343120474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338313336642d3138642d34353832306530393638303430220d0a0d0a ASCII:E....a@.7..%U........P@I..y........|.........S...,..HTTP/1.1 304 Not Modified..Date: Tue, 30 Aug 2016 16:36:41 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8136d-18d-45820e0968040"....
-compressed=            45000100e2b66140003706e325550d93d7c0a8000200504049fbb679bcc9051ea48018007cebea00000101080a1153cfdc002cfdb4485454502f312e312033013034204e6f74204d6f646966016965640d0a446174653a205475652c2033302041756720323031362031363a33363a343120474d540d0a5365727665723a204170616368650d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4b6565702d416c6976653a2074696d656f75743d322c206d61783d313030300d0a455461673a2022346338313336642d3138642d34353832306530393638303430220d0a0d0a ASCII:E.....a@.7..%U........P@I..y........|.........S...,..HTTP/1.1 3.04 Not Modif.ied..Date: Tue, 30 Aug 2016 16:36:41 GMT..Server: Apache..Connection: Keep-Alive..Keep-Alive: timeout=2, max=1000..ETag: "4c8136d-18d-45820e0968040"....
-memcmp() rc=0
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 0
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010268000700004006cefac0a80002550d93d740000050462c7ba7e4d1753a80184000aad500000101080a0001a670084dafb4474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d6978656433005ab97a052b960d59b368d5b2ddb3e60e9c372ef610b6dbf56bd8b165030f2e7cf88dd63b68f64c3d9b76ed1cb58847b490d122e8d0a24761185913d50e1aa423f0dc49036387d6d7b169e4d0cac68e1cd93b70f0804123f7eee03372dcc801038f193b306a68b5b2864d9a3b629a30b1a2b5081b35384613357a07c6133271d4e021a3064d52347182ee81b119c69c3a72d2b079b37e4409c177e6f4902163738cdd71f8a0a903d68ec21866e4c0918185087dfb329cec9831834d951a337c4a2e1174891c3badf5e8d113a38f1c336e24520c8a65751d1844d4c7696d852c1f240e992becf8918d0c9145465441939fcc6a1950a206b7e1fca38e1145eaebc129230aeb24f57bcab011c3c68829f5efe7bfcbe4c814e731668c3042f6fef93a62d9909561e4c91123c163d0085a3a4e1c3466c6c649ea048d519d5ff3a0f95ef4280c2471269e61633ee9193469de8845a3554d9fa74199c48622e7fa7dac30ac602f9af40a9ef0236a54268247cd7f923946d0a8d1c3c68d1e35788c5002e54ad0a00100 ASCII:E...h....@.......U...@..PF,{...u:..@............p.M..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed3.Z.z.+..Y.h.......7......k..e...|...;h.L=.v....G..."...Ga.Y.....#..I.c....i.......;p..A#...3r......;0jh...M.;b.0.....58F.5z...2q..!..MR4q.......:r..y.~D..w...!cs..q........f......}.2...1.M..3|J..t..;........3n$R..eu..D..im.,.$..+......EFTA...j.P........E...)#..$.{......).........1f.0B...:b...a...#.c..Z:N.4f..I...Q._...^.(.$q&.ac>..4i..E.UM..A..."..}.0.`/.....#jT&.G...9F.......5x.P..J....
-uncompressed= 45000268000700004006cefac0a80002550d93d740000050462c7ba7e4d1753a80184000aad500000101080a0001a670084dafb4474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a49662d4d6f6469666965642d53696e63653a205475652c2032332041756720323031362031323a33343a323920474d540d0a0d0a ASCII:E..h....@.......U...@..PF,{...u:..@............p.M..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..If-Modified-Since: Tue, 23 Aug 2016 12:34:29 GMT....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 1
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010268000900004006cef8c0a80002550d93d740000050462c7ba7e4d1753a801840007e7f00000101080a0001d1cc084db0ae474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d6978656433005ab97a052b960d59b368d5b2ddb3e60e9c372ef610b6dbf56bd8b165030f2e7cf88dd63b68f64c3d9b76ed1cb58847b490d122e8d0a24761185913d50e1aa423f0dc49036387d6d7b169e4d0cac68e1cd93b70f0804123f7eee03372dcc801038f193b306a68b5b2864d9a3b629a30b1a2b5081b35384613357a07c6133271d4e021a3064d52347182ee81b119c69c3a72d2b079b37e4409c177e6f4902163738cdd71f8a0a903d68ec21866e4c0918185087dfb329cec9831834d951a337c4a2e1174891c3badf5e8d113a38f1c336e24520c8a65751d1844d4c7696d852c1f240e992becf8918d0c9145465441939fcc6a1950a206b7e1fca38e1145eaebc129230aeb24f57bcab011c3c68829f5efe7bfcbe4c814e731668c3042f6fef93a62d9909561e4c91123c163d0085a3a4e1c3466c6c649ea048d519d5ff3a0f95ef4280c2471269e61633ee9193469de8845a3554d9fa74199c48622e7fa7dac30ac602f9af40a9ef0236a54268247cd7f923946d0a8d1c3c68d1e35788c5002e54ad0a00100 ASCII:E...h....@.......U...@..PF,{...u:..@.~............M..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed3.Z.z.+..Y.h.......7......k..e...|...;h.L=.v....G..."...Ga.Y.....#..I.c....i.......;p..A#...3r......;0jh...M.;b.0.....58F.5z...2q..!..MR4q.......:r..y.~D..w...!cs..q........f......}.2...1.M..3|J..t..;........3n$R..eu..D..im.,.$..+......EFTA...j.P........E...)#..$.{......).........1f.0B...:b...a...#.c..Z:N.4f..I...Q._...^.(.$q&.ac>..4i..E.UM..A..."..}.0.`/.....#jT&.G...9F.......5x.P..J....
-uncompressed= 45000268000900004006cef8c0a80002550d93d740000050462c7ba7e4d1753a801840007e7f00000101080a0001d1cc084db0ae474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a49662d4d6f6469666965642d53696e63653a205475652c2032332041756720323031362031323a33343a323920474d540d0a0d0a ASCII:E..h....@.......U...@..PF,{...u:..@.~............M..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..If-Modified-Since: Tue, 23 Aug 2016 12:34:29 GMT....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 2
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010268000b00004006cef6c0a80002550d93d740000050462c7ba7e4d1753b80193fff131c00000101080a00022884084dc558474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d6978656433005ab97a052b960d59b368d5b2ddb3e60e9c372ef610b6dbf56bd8b165030f2e7cf88dd63b68f64c3d9b76ed1cb58847b490d122e8d0a24761185913d50e1aa423f0dc49036387d6d7b169e4d0cac68e1cd93b70f0804123f7eee03372dcc801038f193b306a68b5b2864d9a3b629a30b1a2b5081b35384613357a07c6133271d4e021a3064d52347182ee81b119c69c3a72d2b079b37e4409c177e6f4902163738cdd71f8a0a903d68ec21866e4c0918185087dfb329cec9831834d951a337c4a2e1174891c3badf5e8d113a38f1c336e24520c8a65751d1844d4c7696d852c1f240e992be4e8918d8c9045465441939fcc6a1950a206b7e1dca38e1145eaebb929230aeb24f579cab011c3c68829f5efe7afcbe4c814e731668c3042f6fef93a62d9909561e4c91123c163d0084a3a4e1c3466c6c649ea048dd19c5ff3a0f95ef4280c2471269e61633ee9193469de8845a3554d9fa74199c48622c7fa7dac30ac5c2f9af40a1ef0236a502682478dff913946d0a8d1c3c68d1e35788c5002e54ad0a00100 ASCII:E...h....@.......U...@..PF,{...u;..?...........(..M.XGET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed3.Z.z.+..Y.h.......7......k..e...|...;h.L=.v....G..."...Ga.Y.....#..I.c....i.......;p..A#...3r......;0jh...M.;b.0.....58F.5z...2q..!..MR4q.......:r..y.~D..w...!cs..q........f......}.2...1.M..3|J..t..;........3n$R..eu..D..im.,.$..+......EFTA...j.P........E...)#..$.y......).........1f.0B...:b...a...#.c..J:N.4f..I....._...^.(.$q&.ac>..4i..E.UM..A..."..}.0.\/.....#jP&.G...9F.......5x.P..J....
-uncompressed= 45000268000b00004006cef6c0a80002550d93d740000050462c7ba7e4d1753b80193fff131c00000101080a00022884084dc558474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a49662d4d6f6469666965642d53696e63653a205475652c2032332041756720323031362031323a33343a323920474d540d0a0d0a ASCII:E..h....@.......U...@..PF,{...u;..?...........(..M.XGET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..If-Modified-Since: Tue, 23 Aug 2016 12:34:29 GMT....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 3
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010268000c00004006cef5c0a80002550d93d740000050462c7ba7e4d1753b80193fff65ab00000101080a0002d5f4084dc558474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d6978656433005ab97a052b960d59b368d5b2ddb3e60e9c372ef610b6dbf56bd8b165030f2e7cf88dd63b68f64c3d9b76ed1cb58847b490d122e8d0a24761185913d50e1aa423f0dc49036387d6d7b169e4d0cac68e1cd93b70f0804123f7eee03372dcc801038f193b306a68b5b2864d9a3b629a30b1a2b5081b35384613357a07c6133271d4e021a3064d52347182ee81b119c69c3a72d2b079b37e4409c177e6f4902163738cdd71f8a0a903d68ec21866e4c0918185087dfb329cec9831834d951a337c4a2e1174891c3badf5e8d113a38f1c336e24520c8a65751d1844d4c7696d852c1f240e992be4e8918d8c9045465441939fcc6a1950a206b7e1dca38e1145eaebb929230aeb24f579cab011c3c68829f5efe7afcbe4c814e731668c3042f6fef93a62d9909561e4c91123c163d0084a3a4e1c3466c6c649ea048dd19c5ff3a0f95ef4280c2471269e61633ee9193469de8845a3554d9fa74199c48622c7fa7dac30ac5c2f9af40a1ef0236a502682478dff913946d0a8d1c3c68d1e35788c5002e54ad0a00100 ASCII:E...h....@.......U...@..PF,{...u;..?.e............M.XGET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed3.Z.z.+..Y.h.......7......k..e...|...;h.L=.v....G..."...Ga.Y.....#..I.c....i.......;p..A#...3r......;0jh...M.;b.0.....58F.5z...2q..!..MR4q.......:r..y.~D..w...!cs..q........f......}.2...1.M..3|J..t..;........3n$R..eu..D..im.,.$..+......EFTA...j.P........E...)#..$.y......).........1f.0B...:b...a...#.c..J:N.4f..I....._...^.(.$q&.ac>..4i..E.UM..A..."..}.0.\/.....#jP&.G...9F.......5x.P..J....
-uncompressed= 45000268000c00004006cef5c0a80002550d93d740000050462c7ba7e4d1753b80193fff65ab00000101080a0002d5f4084dc558474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a49662d4d6f6469666965642d53696e63653a205475652c2032332041756720323031362031323a33343a323920474d540d0a0d0a ASCII:E..h....@.......U...@..PF,{...u;..?.e............M.XGET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..If-Modified-Since: Tue, 23 Aug 2016 12:34:29 GMT....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 4
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   450001022d000f00004006ac5ec0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e33005cbd8215bb67cd1d386f5cecd1cb766ad5ab59b7decdbbb7ef1ba877d0ec49daf56bd83960fd8e6821a3c5cd9c3b7bc230b2e6a81d343e47e0b99306c60ea8a54fd3c801958d1d39a877e0e00183c6ebd8b767e4b89103061e337660d4806a650d9b3477c4346162056a11366a7064d6c9f30e8c2764e2a8c143460d9a9f68e2dcdc0323328c3975e4a461f326fc881278efcce9214346e418b1e3f04153c7aa9dfd31ccc88123030b11f5ec6538d93163069b2a3566d0445ce2e612397646d398118347cd9a3a68f49848f12696d0756010011f67b415ad7c90fc17be5f224536322e16195105cd7b32a16540397adb06718a3a461459afe7a58c28a293acb729c3460c1b23a6ac6ffffe2d93235388c79831c288d6f6ddeb6065a355869127478cdcae79b3739c3868cc648df3d3091a9e31abe641537d674f1848e2203cc386fbcf3368d2bcc18a06aa9a3e456fde0c00 ASCII:E...-....@..^........@..@F.......P.@..H..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application3.\....g..8o\...vj..Y........w..I..k.9`..h!....;{.0....4>G........O......9.w........g......3v`..je..4w.4ab.j.6jpd.....'d...CF...h....#2.9u..a.&...x...!CF.....AS....1...#.....e8.1c..*5f.D\...9vF....G..:h..H.&..u`...g...|...._"E62...Q..{2.e@9z..q.:F.Y....(....).F..#..o..-.#S...1......`e.U..'G...y.s.8h.d......1..AS}gO.H. <....3h.......>Eo...
-uncompressed= 4500022d000f00004006ac5ec0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a2031302e392e312e3137313a383030300d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a0d0a ASCII:E..-....@..^........@..@F.......P.@..H..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: 10.9.1.171:8000..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 5
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   450001022d001000004006ac5dc0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e33005cbd8215bb67cd1d386f5cecd1cb766ad5ab59b7decdbbb7ef1ba877d0ec49daf56bd83960fd8e6821a3c5cd9c3b7bc230b2e6a81d343e47e0b99306c60ea8a54fd3c801958d1d39a877e0e00183c6ebd8b767e4b89103061e337660d4806a650d9b3477c4346162056a11366a7064d6c9f30e8c2764e2a8c143460d9a9f68e2dcdc0323328c3975e4a461f326fc881278efcce9214346e418b1e3f04153c7aa9dfd31ccc88123030b11f5ec6538d93163069b2a3566d0445ce2e612397646d398118347cd9a3a68f49848f12696d0756010011f67b415ad7c90fc17be5f224536322e16195105cd7b32a16540397adb06718a3a461459afe7a58c28a293acb729c3460c1b23a6ac6ffffe2d93235388c79831c288d6f6ddeb6065a355869127478cdcae79b3739c3868cc648df3d3091a9e31abe641537d674f1848e2203cc386fbcf3368d2bcc18a06aa9a3e456fde0c00 ASCII:E...-....@..]........@..@F.......P.@..H..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application3.\....g..8o\...vj..Y........w..I..k.9`..h!....;{.0....4>G........O......9.w........g......3v`..je..4w.4ab.j.6jpd.....'d...CF...h....#2.9u..a.&...x...!CF.....AS....1...#.....e8.1c..*5f.D\...9vF....G..:h..H.&..u`...g...|...._"E62...Q..{2.e@9z..q.:F.Y....(....).F..#..o..-.#S...1......`e.U..'G...y.s.8h.d......1..AS}gO.H. <....3h.......>Eo...
-uncompressed= 4500022d001000004006ac5dc0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a2031302e392e312e3137313a383030300d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a0d0a ASCII:E..-....@..]........@..@F.......P.@..H..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: 10.9.1.171:8000..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 6
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   450001022d001100004006ac5cc0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e33005cbd8215bb67cd1d386f5cecd1cb766ad5ab59b7decdbbb7ef1ba877d0ec49daf56bd83960fd8e6821a3c5cd9c3b7bc230b2e6a81d343e47e0b99306c60ea8a54fd3c801958d1d39a877e0e00183c6ebd8b767e4b89103061e337660d4806a650d9b3477c4346162056a11366a7064d6c9f30e8c2764e2a8c143460d9a9f68e2dcdc0323328c3975e4a461f326fc881278efcce9214346e418b1e3f04153c7aa9dfd31ccc88123030b11f5ec6538d93163069b2a3566d0445ce2e612397646d398118347cd9a3a68f49848f12696d0756010011f67b415ad7c90fc17be5f224536322e16195105cd7b32a16540397adb06718a3a461459afe7a58c28a293acb729c3460c1b23a6ac6ffffe2d93235388c79831c288d6f6ddeb6065a355869127478cdcae79b3739c3868cc648df3d3091a9e31abe641537d674f1848e2203cc386fbcf3368d2bcc18a06aa9a3e456fde0c00 ASCII:E...-....@..\........@..@F.......P.@..H..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application3.\....g..8o\...vj..Y........w..I..k.9`..h!....;{.0....4>G........O......9.w........g......3v`..je..4w.4ab.j.6jpd.....'d...CF...h....#2.9u..a.&...x...!CF.....AS....1...#.....e8.1c..*5f.D\...9vF....G..:h..H.&..u`...g...|...._"E62...Q..{2.e@9z..q.:F.Y....(....).F..#..o..-.#S...1......`e.U..'G...y.s.8h.d......1..AS}gO.H. <....3h.......>Eo...
-uncompressed= 4500022d001100004006ac5cc0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a2031302e392e312e3137313a383030300d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a0d0a ASCII:E..-....@..\........@..@F.......P.@..H..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: 10.9.1.171:8000..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 7
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   450001022d001200004006ac5bc0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e33005cbd8215bb67cd1d386f5cecd1cb766ad5ab59b7decdbbb7ef1ba877d0ec49daf56bd83960fd8e6821a3c5cd9c3b7bc230b2e6a81d343e47e0b99306c60ea8a54fd3c801958d1d39a877e0e00183c6ebd8b767e4b89103061e337660d4806a650d9b3477c4346162056a11366a7064d6c9f30e8c2764e2a8c143460d9a9f68e2dcdc0323328c3975e4a461f326fc881278efcce9214346e418b1e3f04153c7aa9dfd31ccc88123030b11f5ec6538d93163069b2a3566d0445ce2e612397646d398118347cd9a3a68f49848f12696d0756010011f67b415ad7c90fc17be5f224536322e16195105cd7b32a16540397adb06718a3a461459afe7a58c28a293acb729c3460c1b23a6ac6ffffe2d93235388c79831c288d6f6ddeb6065a355869127478cdcae79b3739c3868cc648df3d3091a9e31abe641537d674f1848e2203cc386fbcf3368d2bcc18a06aa9a3e456fde0c00 ASCII:E...-....@..[........@..@F.......P.@..H..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application3.\....g..8o\...vj..Y........w..I..k.9`..h!....;{.0....4>G........O......9.w........g......3v`..je..4w.4ab.j.6jpd.....'d...CF...h....#2.9u..a.&...x...!CF.....AS....1...#.....e8.1c..*5f.D\...9vF....G..:h..H.&..u`...g...|...._"E62...Q..{2.e@9z..q.:F.Y....(....).F..#..o..-.#S...1......`e.U..'G...y.s.8h.d......1..AS}gO.H. <....3h.......>Eo...
-uncompressed= 4500022d001200004006ac5bc0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a2031302e392e312e3137313a383030300d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a0d0a ASCII:E..-....@..[........@..@F.......P.@..H..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: 10.9.1.171:8000..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 8
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010268001300004006ceeec0a80002550d93d740000050462c7ba7e4d1753b80193fff7b4a00000101080a0003c054084dc558474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d6978656433005bbb7e0d3b964dd9b369d7b6ddb3e60e9c372ef614beeb15ac58b2660513368cf8cdd63b68f65045ab96ed9cb58947b490d1422851a34861185923d50e9aa423f0dc490363c756d8b269e4d8cac68e9cd93b70f0804143376fe13372dcc801038f193b306a6cb5b2864d9a3b629a30b1b2b5081b353848173d7a07c6133271d4e021a3068d52347184ee81c119c69c3a72d2b079c37e4489c177e6f4902183730cde71f8a0a913d6cec21866e4c091818548fdfb329cec9831834d951a337e4e2e2174891c3baef5e8d113a38f1c336e2656148a85751d1844d6c7716da52c1f240f9b2fecf8918d0c9145465441a39f0c6b1950a40ab7f1fca38e1145ecebc129234aeb24f67bcab011c3c68829f6f1ebb7cbe4c894e731668c3052163ffa3a63d9949561e4c91123c263d0105a3a4e1c3466c8c651ea04cd519d60f3a0016f14290c2471289e61735ee9193469de8c45b3554d1fa84299c88622e73afeac30ac6037aaf40a9ef0236a54268247cd7f923946d0a8d1c3c68d1e35788c5002e58a50a10100 ASCII:E...h....@.......U...@..PF,{...u;..?.{J.........T.M.XGET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed3.[.~.;.M..i.......7.......X.f..6....;h.PE......G...B(Q.Ha.Y#....#..I.c.V..i.......;p..AC7o.3r......;0jl...M.;b.0.....58H.=z...2q..!...R4q.......:r..y.~D..w...!.s..q........f.....H..2...1.M..3~N.!t..;........3n&V...u..D..qm.,.$../......EFTA...k.P........E...)#J.$.{......).........1f.0R.?.:c...a...#.c..Z:N.4f..Q...Q.`...o.).$q(.as^..4i..E.UM..B...".:..0.`7.....#jT&.G...9F.......5x.P...P...
-uncompressed= 45000268001300004006ceeec0a80002550d93d740000050462c7ba7e4d1753b80193fff7b4a00000101080a0003c054084dc558474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a49662d4d6f6469666965642d53696e63653a205475652c2032332041756720323031362031323a33343a323920474d540d0a0d0a ASCII:E..h....@.......U...@..PF,{...u;..?.{J.........T.M.XGET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..If-Modified-Since: Tue, 23 Aug 2016 12:34:29 GMT....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 9
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   450001022d001400004006ac59c0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e33005cbd8215bb67cd1d386f5cecd1cb766ad5ab59b7decdbbb7ef1ba877d0ec49daf56bd83960fd8e6821a3c5cd9c3b7bc230b2e6a81d343e47e0b99306c60ea8a54fd3c801958d1d39a877e0e00183c6ebd8b767e4b89103061e337660d4806a650d9b3477c4346162056a11366a7064d6c9f30e8c2764e2a8c143460d9a9f68e2dcdc0323328c3975e4a461f326fc881278efcce9214346e418b1e3f04153c7aa9dfd31ccc88123030b11f5ec6538d93163069b2a3566d0445ce2e612397646d398118347cd9a3a68f49848f12696d0756010011f67b415ad7c90fc17be5f224536322e16195105cd7b32a16540397adb06718a3a461459afe7a58c28a293acb729c3460c1b23a6ac6ffffe2d93235388c79831c288d6f6ddeb6065a355869127478cdcae79b3739c3868cc648df3d3091a9e31abe641537d674f1848e2203cc386fbcf3368d2bcc18a06aa9a3e456fde0c00 ASCII:E...-....@..Y........@..@F.......P.@..H..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application3.\....g..8o\...vj..Y........w..I..k.9`..h!....;{.0....4>G........O......9.w........g......3v`..je..4w.4ab.j.6jpd.....'d...CF...h....#2.9u..a.&...x...!CF.....AS....1...#.....e8.1c..*5f.D\...9vF....G..:h..H.&..u`...g...|...._"E62...Q..{2.e@9z..q.:F.Y....(....).F..#..o..-.#S...1......`e.U..'G...y.s.8h.d......1..AS}gO.H. <....3h.......>Eo...
-uncompressed= 4500022d001400004006ac59c0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a2031302e392e312e3137313a383030300d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a0d0a ASCII:E..-....@..Y........@..@F.......P.@..H..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: 10.9.1.171:8000..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 10
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   450001022d001500004006ac58c0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e33005cbd8215bb67cd1d386f5cecd1cb766ad5ab59b7decdbbb7ef1ba877d0ec49daf56bd83960fd8e6821a3c5cd9c3b7bc230b2e6a81d343e47e0b99306c60ea8a54fd3c801958d1d39a877e0e00183c6ebd8b767e4b89103061e337660d4806a650d9b3477c4346162056a11366a7064d6c9f30e8c2764e2a8c143460d9a9f68e2dcdc0323328c3975e4a461f326fc881278efcce9214346e418b1e3f04153c7aa9dfd31ccc88123030b11f5ec6538d93163069b2a3566d0445ce2e612397646d398118347cd9a3a68f49848f12696d0756010011f67b415ad7c90fc17be5f224536322e16195105cd7b32a16540397adb06718a3a461459afe7a58c28a293acb729c3460c1b23a6ac6ffffe2d93235388c79831c288d6f6ddeb6065a355869127478cdcae79b3739c3868cc648df3d3091a9e31abe641537d674f1848e2203cc386fbcf3368d2bcc18a06aa9a3e456fde0c00 ASCII:E...-....@..X........@..@F.......P.@..H..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application3.\....g..8o\...vj..Y........w..I..k.9`..h!....;{.0....4>G........O......9.w........g......3v`..je..4w.4ab.j.6jpd.....'d...CF...h....#2.9u..a.&...x...!CF.....AS....1...#.....e8.1c..*5f.D\...9vF....G..:h..H.&..u`...g...|...._"E62...Q..{2.e@9z..q.:F.Y....(....).F..#..o..-.#S...1......`e.U..'G...y.s.8h.d......1..AS}gO.H. <....3h.......>Eo...
-uncompressed= 4500022d001500004006ac58c0a800020a0901ab40011f4046a2f5a8e0a618025018400093480000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a2031302e392e312e3137313a383030300d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a0d0a ASCII:E..-....@..X........@..@F.......P.@..H..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: 10.9.1.171:8000..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 11
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010239000500004006ac5cc0a800020a0901ab40001f90c286afa741a348cb801840007fcb0000050a41a348dc41a34a440000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d69786564330057b36eedfa954dd8b165cfa6ddb3e60e9c372ef6049eab95ab57b062fd02164cf8cdd53b68f640256b16ed9cb38547b490d1e22791a043efc030b2c6a91d344547e0b99306c68eabad5fd3c871958d1d39b077e0e00183c6eddcbf67e4b89103061e337660d4b86a650d9b3477c4346162e56a11366a7080164d14c6133271d4e021a3068d5134717eee818119c69c3a72d2b079837e4489bf77e6f4902103738cdc71f8a0a9d3d58ec11866e4c091818548fcf9329cec9831834d951a33783e2ef173891c3bab69cc88c1a3674f1d347a6cdcf8134bea3a30889c8fb3da4a583e48162a37a891231b19208b8ca882c63e99d432a038fd6d8339471d238ac8d793534614d549e40b956123868d1153e4d3b77f97c99129cc63cc1861242c7df275beb2092bc3c89323467ef7fc693a4e1c3466c0c631ea04cdd09d5cf3a0e96e66e81d1848e2403cc366bcd13368d2bcf98ae6aa9a3e4c7ffe0c00 ASCII:E...9....@..\........@.......A.H...@.......A.H.A.JD..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed3.W.n...M..e.......7.......W.b...L...;h.@%k.....G....'..C..0....4EG........_..q...9.w........g......3v`..je..4w.4ab.j.6jp..M...2q..!...Q4q~......:r..y.~D..w...!.s..q........f.....H..2...1.M..3x>..s..;.i....gO.4zl...K.:0.....JX>H.*7..#.. .....>..2.8.m.9G.#....SF..I...a#...S.......).c..a$,}.u...+...#F~..i:N.4f..1.....\...nf...H.@<.f..3h.......>L....
-uncompressed= 45000239000500004006ac5cc0a800020a0901ab40001f90c286afa741a348cb801840007fcb0000050a41a348dc41a34a440000474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a2031302e392e312e3137313a383038300d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a0d0a ASCII:E..9....@..\........@.......A.H...@.......A.H.A.JD..GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: 10.9.1.171:8080..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 12
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   450001025b000a00004006ac35c0a800020a0901ab40011f90c293b0a8af5e58be5018400072a60000474554202f72656470686f6e652e706e6720485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c33005cbd82154b368e59b46ad9ee597307ce1b177b066fedfa35ec583665010b266cf8cdd63b68f6543d9b76ed1cb58747b490d16268d1a34961185933d50e1aa523f0dc490363c7d6d7b169e4d8cac68e1cd93b70f0804123f7eee03372dcc801038f193b306a6cb5b2864d9a3b629a30b1b2b5081b3538461b457a07c6133238f190518366299a3843f7c0d80c634e1d3969d8bc513fa244e03b737ac890b139c6ee387cd0d4096b07610c3372e0c8c042647e7d194e76cc98c1a64a8d1940259718ba448e9dd63466c4e01134a80e1a3d38721c8a65751d1844d2c7696d65261f240d9923dcd8918d0c9045465441839fcc6a1950a606b7e1bca38e1145e8ebd929230aeb24f485cab011c3c68829f4ede3d7cbe4c814e731668c3032d3be1a3c75c6b2296be4c91123c1830e451d270e1a3364e32c758206694fb079d07c3f9a1406923812cfb0c1b9f40c9a346fc6a2d9aaa64fd4a175d33064b894bfff812b5bc2a421b3e60c8e32860e0d00 ASCII:E...[....@..5........@........^X.P.@.r...GET /redphone.png HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed,3.\...K6.Y.j..Ys....{.o..5.X6e..&l...;h.T=.v....G...bh..Ia.Y3....#..I.c....i.......;p..A#...3r......;0jl...M.;b.0.....58F.Ez...28..Q.f).8C....cN.9i..Q?.D.;sz...9..8|...k.a.3r...Bd~}.Nv....J..@%...D...4f...4...=8r..eu..D..ime&.$..#......EFTA...j.P........E...)#..$........).........1f.02...<u..)k...#...E.'..3d.,u..iO.y.|?....8........4o.....O..u.0d.....+[..!....2....
-uncompressed= 4500025b000a00004006ac35c0a800020a0901ab40011f90c293b0a8af5e58be5018400072a60000474554202f72656470686f6e652e706e6720485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a2031302e392e312e3137313a383038300d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f31302e392e312e3137313a383038302f0d0a0d0a ASCII:E..[....@..5........@........^X.P.@.r...GET /redphone.png HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: 10.9.1.171:8080..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://10.9.1.171:8080/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 13
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010267001200004006ac21c0a800020a0901ab40011f90c293b0a8af5e58be80184000ee770000050aaf5e6437af5e8c230000474554202f72656470686f6e652e706e6720485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d33006fc8de41b3c72b5cb974e7cc853ca2858c164c9d42950ac3c81aae76d04c1d81e74e1a183bc8e2d64d2307593676e4ecde8183070c1ac2892b9f91e3460e1878ccd8815183ac95356cd2dc11d3848915b245d8a8c1c1fa69d43b309e90098a878c1a3454d1c461ba0706691873eac849c3e6cdfc112514df99d343860cd23188c7e183a68e5a3b126398910347061622fcfdcb70b263c60c36556acc48bab904d32572ecd8a63123060fa54a75d0e861d224532cb4ebc020223f8e6d2b3cf920b1585d62c9936c64a82c32a20a9a826468cb80c255b98deb27758c28d25f4f5119516a27e9df54868d1836464ce9ffbf20612647a65c8f316384119effd5e0a9c3968d5b234f8e1851ae94a9ec3871d098691b87aa1334518fa6cd83063d54a93090c4d978864d50aa67d0a479c3160d59357db432fd9ba66245aa0a193aac7953278d9e3f679894c1946900 ASCII:E...g....@..!........@........^X...@..w.....^d7.^.#..GET /redphone.png HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xm3.o..A..+\.t...<....L.B......v.L...N..;...M#.Y6v..........+...F..x...Q...5l........E.....i.;0.......4T..a...i.s..I.....%....C...1......Z;.c...G.."...p.c..6Uj.H....%r...1#...Ju..a.$S,... "?.m+<. .X]b..ld.,2....dh...U...'u.(._OQ.Qj'..T...6FL... a&G.\.1c..........[#O..Q....8q..i....4Q.....=T.0...x.MP.g..y...Y5}.2...bE...:.yS'..?g....i.
-uncompressed= 45000267001200004006ac21c0a800020a0901ab40011f90c293b0a8af5e58be80184000ee770000050aaf5e6437af5e8c230000474554202f72656470686f6e652e706e6720485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a2031302e392e312e3137313a383038300d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f31302e392e312e3137313a383038302f0d0a0d0a ASCII:E..g....@..!........@........^X...@..w.....^d7.^.#..GET /redphone.png HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: 10.9.1.171:8080..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://10.9.1.171:8080/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 14
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010236003000004006cf03c0a80002550d93d740020050c30e84a9441d06ac80184000c2f400000101080a00052df410fc31bd474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d6978656433005cbd82154b968d59b46ad9baddb3e60e9c372ef618c6fb35ecd8b26707173e9cf80dd73b68f6544dbbb6ed1cb68a47b490d16268d1a34961185933d50e1aa523f0dc49036307d7d8b369e4e0cac68e1cda3b70f080416377efe13372dcc801038f193b306a70b5b2864d9a3b629a30b1c2b5081b35384a1b457a07c6133271d4e021a306cd52347186ee81d119c69c3a72d2b079d37e4409c277e6f49021a3738cde71f8a0a923d60ec31866e4c0918185887dfc329cec9831834d951a3380522e3174891c3baff5e8d113a38f1c336e285a1c8aa5751d1844d8c7796dc52c1f24109d33f408928d8c9145465441b39f4c6b1950a60eb7011da48e1145eeebc929238aeb24f77dcab011c3c68829f7f3efbfcbe4c814e831668c3062367ffa3a64d9989561e4c91123c363d0186a3a4e1c3466cac659ea040dd29d61f3a0097f34290c24712a9e61837ee9193469de9045c3554d9fa843870600 ASCII:E...6.0..@.......U...@..P....D.....@...........-...1.GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed3.\...K..Y.j.......7.....5...g..>....;h.TM......G...bh..Ia.Y3....#..I.c....i.......;p..Acw..3r......;0jp...M.;b.0.....58J.Ez...2q..!...R4q.......:r..y.~D..w...!.s..q...#....f......}.2...1.M..3.R.1t..;........3n(Z...u..D..ym.,.$..3......EFTA..Lk.P........E...)#..$.}......).........1f.0b6..:d...a...#.c..j:N.4f..Y.....a....4).$q*.a.~..4i..E.UM..C...
-uncompressed= 45000236003000004006cf03c0a80002550d93d740020050c30e84a9441d06ac80184000c2f400000101080a00052df410fc31bd474554202f20485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a0d0a ASCII:E..6.0..@.......U...@..P....D.....@...........-...1.GET / HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 15
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010260004500004006cec4c0a80002550d93d740030050c3134faac89c8b2980184000578d00000101080a000535c010fc34c8474554202f6e697276616e612e63737320485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d33006fcede41b3072c5dbb78e7dcad3ca2858c164ea14aa50ac3c81aaf76d0541d81e74e1a183bcef2f64d23c7593676e4fcde8183070c1ac6913b9f91e3460e187884c2a871d6ca1a3669ee8869c2c4cad9226cd4e0801d75ea1d184f7caac143460d1aab68e238dd0303358c3975e4a461f3c6fe88128fefcce9214306ea18c8e3f04153a7edd0b841e5c0918185c87f83329cec9831834d951a33967e2ee174891c3bbaf5e8d113a38f1c336e3ac2718a05771d1844eac7d16d252e1f241985563489928d8c954546544193900c6e1950bc3ab7a11da58e11450aea292a234aee240595cab011c3c68829050f2624cce4c814ed31668c3012f7a0fc3a6fd9c49561e4c91123ce63d0702a3b4e1c3466e0c6b1ea04cdd4a36cf3a0592f952a0c2471ccc839c3268e1aab67d0a479f316cd59357db83af59b062346ab0d1f46b47933e7ce9e329c3a0d00 ASCII:E...`.E..@.......U...@..P..O....)..@.W.........5...4.GET /nirvana.css HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xm3.o..A..,].x...<....N.J......v.T...N..;...M#.Y6v..........;...F..x...q...6i..i...."l....u...O|..CF...h.8...5.9u..a.........!C......AS....A........2...1.M..3.~..t..;........3n:.q..w..D...m%..$..V4.....EFTA...n.P.:......E..)*#J.$........)..&$.....1f.0....:o...a...#.c.p*;N.4f........l..Y/.*.$q..9.&...g..y...Y5}.:...#F...F.y3...2.:..
-uncompressed= 45000260004500004006cec4c0a80002550d93d740030050c3134faac89c8b2980184000578d00000101080a000535c010fc34c8474554202f6e697276616e612e63737320485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f7777772e7a6f636b2e636f6d2f0d0a0d0a ASCII:E..`.E..@.......U...@..P..O....)..@.W.........5...4.GET /nirvana.css HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://www.zock.com/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 16
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010264004600004006cebfc0a80002550d93d740040050c3135bab2189da61801840008f2d00000101080a000535c410fc34dc474554202f382d4269742f4c6162656c2e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d3300952fbf517b07cd1e9f77f3ee9da317f38816325a48a56a152b0c236bc4da419375049e3b6960ec50fb3b388d1c6ad9d891237c070e1e3068245f1e7d468e1b3960e0316307460db556d6b04973474c132656d4f254836376d5ab7760008da3060f193568b4a28923750f8cd530e6d4919386cd9bfc234a48be33a7870c19ab632c8fc3074d1db87630c63023078e0c2c440c2294e164c78c196caad498f1547409a94be4d8e9ad478f9e187de498710352a4542cbbebc020823f4e6f2b74f920e1c81da34a966c64bc2c32a20a1a866476cb802236ba0def2c758c2872500f521951782739d854868d1836464c39a89061612647a6788f31638411ba0aebd791cb86ae0c234f8e18891e838654da71e2a03133378e562768ae2a7d9b078d7bab5861208913f20c1bfa5acfa049f3462e1ab56afa80950a38cdc68d5a214aa4a873e74fa144474a951a00 ASCII:E...d.F..@.......U...@..P..[.!..a..@..-........5...4.GET /8-Bit/Label.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtm3../.Q{....w........2ZH.j.+.#k..A.u..;i`.P.;8..j...#|...0h$_.}F..9`.1c.F..V..IsGL.&V..T.cv..w`......5h...#u...0........#JH.3.....c,...M..v0.0#...,D."..d...l....Tt..K....G...}..q.R.T,... .?No+t. ....J.ld.,2....dv.."6...,u.(rP.R.Qx'9.T...6FL9..aa&G.x.1c...........#O......T.q..137.V'h.*}...{.Xa ......Z..I.F...j....8...Z!J..s.O.DGJ...
-uncompressed= 45000264004600004006cebfc0a80002550d93d740040050c3135bab2189da61801840008f2d00000101080a000535c410fc34dc474554202f382d4269742f4c6162656c2e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f7777772e7a6f636b2e636f6d2f0d0a0d0a ASCII:E..d.F..@.......U...@..P..[.!..a..@..-........5...4.GET /8-Bit/Label.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://www.zock.com/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 17
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010264005800004006ceadc0a80002550d93d740050050c31389acaf7b26538018400075c900000101080a000537d010fc354a474554202f382d4269742f41636f726e2e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d3300942dbf497b07cd1e9f76f1ea9d93f7f28816325a48a56af50e0c236bc2da418375049e3b6960ec48eb1b388d1c69d9d891137c070e1e306820570e7d468e1b3960e0316307468db456d6b04973474c132656d2f2548343b699aa57613c2113470d1e326ad064451347ea1e18aa61cca923270d9b37f94794887c674e0f193254c7501e870f9a3a6fed608c11148e0c2c440c2294e164c78c196caad498f1347409a94be4d8e1ad478f9e187de4987103520e1ca95874d78141047f1cde56e6f241c2713bc6942bd9c87059644415340cc9e89601252c741bdd57ea1851e4a09ea432a2ec4e72d0a90c1b316c8c9872502143c34c8e4ce91e63c608237315d6af1397cd5c19469e1c31023d060da9b4e3c44163466e9cac4ed0585dea360f9af6efefc0401227e81936f4b39e4193e64d5c3469d5f4f92a15709a8d1bb342944831a7ce9e42898a942a3500 ASCII:E...d.X..@.......U...@..P.....{&S..@.u.........7...5JGET /8-Bit/Acorn.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtm3..-.I{....v........2ZH.j...#k..A.u..;i`.H..8..i....|...0h W.}F..9`.1c.F..V..IsGL.&V..T.C...Wa<!.G..2j.dE.G....a..#'..7.G..|gN..2T.P....:o.`.....,D."..d...l....4t..K....G...}..q.R...Xt..A....V..A.q;..+..pYdD.4.....%,t..W..Q....2..Nr....1l..rP!C.L.L..c..#s......\.F..1.=......AcFn..N.X].6......@.'..6...A..M\4i...*.p....B.H1...B...*5.
-uncompressed= 45000264005800004006ceadc0a80002550d93d740050050c31389acaf7b26538018400075c900000101080a000537d010fc354a474554202f382d4269742f41636f726e2e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f7777772e7a6f636b2e636f6d2f0d0a0d0a ASCII:E..d.X..@.......U...@..P.....{&S..@.u.........7...5JGET /8-Bit/Acorn.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://www.zock.com/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 18
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010266007600004006ce8dc0a80002550d93d740060050c31431ada11fa06780184000f08e00000101080a00053b3c10fc35ef474554202f382d4269742f416d73747261642e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d33009733bf597b07cd9e9e78f5f2d5a379440b192da656bd9a1586913563eda0d13a02cf9d343076ac052e9c468eb56cecc819be03070f18349433973e23c78d1c30f098b103a3c65a2b6bd8a4b923a609132b6b77aac141db2ad63b309e9089a3060f193568b6a28933750f0cc830e6d4919386cd9bfd234a50be33a7870c199063308fc3074d9db87636c63023078e0c2c44103294e164c78c196caad49801957489a94be404ddaa478f9e187de4987133b2e4542cbcebc020a23f8e6f2b75f920f9d87d63cb976c64c82c32a20a9a876478cb803256ba8def2f758c28a2500f5319517a27512855868d1836464c51d8f061622647a67c8f31638491ba0defd799cba6ae0c234f8e18911e83c6d4db71e2a0314337ce562768b03a859b07cdfbab5961208943f20c1bfb5bcfa049f3662e9ab56afa849d3a388d478f5b2756bcf813e850a3484d4e9d1a00 ASCII:E...f.v..@.......U...@..P..1....g..@...........;<..5.GET /8-Bit/Amstrad.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtm3..3.Y{....x....yD..-.V.....5c...:...40v....F..l........4.3.>#...0......Z+k...#...+kw..A.*.;0.......5h...3u...0........#JP.3.....c0...M..v6.0#...,D.2..d...l.....t..K....G...}..q3..T,... .?.o+u. ..}c..ld.,2....dx..2V.../u.(.P.S.Qz'Q(U...6FLQ..ab&G.|.1c...........#O........q..1C7.V'h.:......Ya .C....[..I.f...j...:8.G.['V....P.HMN...
-uncompressed= 45000266007600004006ce8dc0a80002550d93d740060050c31431ada11fa06780184000f08e00000101080a00053b3c10fc35ef474554202f382d4269742f416d73747261642e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f7777772e7a6f636b2e636f6d2f0d0a0d0a ASCII:E..f.v..@.......U...@..P..1....g..@...........;<..5.GET /8-Bit/Amstrad.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://www.zock.com/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 19
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010264007700004006ce8ec0a80002550d93d740040050c3135ddb2189e0108018400060d600000101080a00053b4010fc35e7474554202f382d4269742f41746172692e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d3300932bbf497b07cd1e9f76f1ea9d93d7f28816325a48a56a152b0c236b84da419375049e3b6960ec48dbfb378d1c69d9d891037c070e1e30681c4ffe7c468e1b3960e0316307468db456d6b04973474c132656d2f254832376d5ab77603c2113470d1e326ad068451347ea1e18a961cca923270d9b37f84794807c674e0f193252c7481e870f9aa1da2fc63023078e0c2c440a1e94e164c78c196caad498f1147409a94be4d8d9ad478f9e187de49871e311a4542cb9ebc020723fce6e2b73f920d968e7224a956c64b42c32a20a9a856472cb8022f4b90dee2a758c286250cf511951742731c854868d1836464c31887061612647a6708f31638491b908e9d789cb66ae0c234f8e18791e8386d4d971e2a03123378e562768ae26759b070d7bab58612089f3f10c9bf95acfa049f3262e9ab46afa8095fa378d468d5a1f469c8833e7ce9f41434a951a00 ASCII:E...d.w..@.......U...@..P..].!.....@.`.........;@..5.GET /8-Bit/Atari.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtm3..+.I{....v........2ZH.j.+.#k..A.u..;i`.H..7..i....|...0h.O.|F..9`.1c.F..V..IsGL.&V..T.#v..w`<!.G..2j.hE.G....a..#'..7.G..|gN..2R.H....../.0#...,D....d...l.....t..K....G...}..q...T,... r?.n+s. .h."J.ld.,2....dr.."....*u.(bP.Q.Qt'1.T...6FL1.paa&G.p.1c........f..#O..y.....q..1#7.V'h.&u...{.Xa ......Z..I.&...j....7.F.Z.F..3...ACJ...
-uncompressed= 45000264007700004006ce8ec0a80002550d93d740040050c3135ddb2189e0108018400060d600000101080a00053b4010fc35e7474554202f382d4269742f41746172692e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f7777772e7a6f636b2e636f6d2f0d0a0d0a ASCII:E..d.w..@.......U...@..P..].!.....@.`.........;@..5.GET /8-Bit/Atari.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://www.zock.com/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 20
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010264007c00004006ce89c0a80002550d93d740070050c314f3aefa37ceb18018400009f900000101080a00053e3410fc369e474554202f382d4269742f4170706c652e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d3300942dbf517b07cd1e9f76f1ea9d93f7f28816325a48a56a152b0c236bc4da419375049e3b6960ec50dbfb378d1c6ad9d891037c070e1e30681c4ffe7c468e1b3960e0316307460db556d6b04973474c132656d4f254832376d5ab77603c2113470d1e326ad068451347ea1e18a961cca923270d9ba15a4b44be33a7870c19a963248fc3074d9db7762cc63023078e0c2c400da691e164c78c196caad498f1147409a94be4d8d9ad478f9e187de49871e311a4542cb9ebc020723fce6e2b73f920d1a8dd224a956c64b42c32a20a9aa16472cb8022f6b90dee2a758c2862504f521951742731e854868d1836464c29a910cd602647a6708f31638491b908e9d789cb66ae0c234f8e18791e8386d4d971e2a03123378e562768ae2e7dc3260f1af656b1c24012e7e31936f3b59e4193e64d5c346ad5f4012bd56f9a8c19b53a84281167ce9d3f8b86942a3500 ASCII:E...d.|..@.......U...@..P.....7....@...........>4..6.GET /8-Bit/Apple.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtm3..-.Q{....v........2ZH.j.+.#k..A.u..;i`.P..7..j....|...0h.O.|F..9`.1c.F..V..IsGL.&V..T.#v..w`<!.G..2j.hE.G....a..#'...ZKD.3.....c$...M..v,.0#...,@....d...l.....t..K....G...}..q...T,... r?.n+s. ..."J.ld.,2....dr.."....*u.(bPOR.Qt'1.T...6FL)...`&G.p.1c........f..#O..y.....q..1#7.V'h..}.&...V..@....6...A..M\4j...+.o....:.(.g..?...*5.
-uncompressed= 45000264007c00004006ce89c0a80002550d93d740070050c314f3aefa37ceb18018400009f900000101080a00053e3410fc369e474554202f382d4269742f4170706c652e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f7777772e7a6f636b2e636f6d2f0d0a0d0a ASCII:E..d.|..@.......U...@..P.....7....@...........>4..6.GET /8-Bit/Apple.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://www.zock.com/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 21
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010265007d00004006ce87c0a80002550d93d740050050c3138bdcaf7b296780183cec0de600000101080a00053e3410fc368e474554202f382d4269742f447261676f6e2e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d33009631bf597b07cd1e9f8df5f2d59379440b192da656bd9a1586913563eda0d13a02cf9d343076ac052e9c468eb56cecc819be03070f18349433973e23c78d1c30f098b103a3c65a2b6bd8a4b923a609132b6b79aac141db2ad63b309e9089a3068f50345bd1c499ba07c6631873eac849c3e68dfe112526df99d343868cc73198c7e183a64e5c3b1963989103470616220715ca70b263c60c36556acc804abac4d42572ecf8d6a3474f8c3e72ccb80939722a16de75601051c3dfb715a27c9074ec9e71654b363260161951054d4332bc6540192bddc6f7963a461441a847a98c28bd93208ce3d3460c1b23a6205cd89030932353bec79831c208d185f7ebcc6553d7c8932346a4c7a03175769c3868ccd08db3d5091aac4ce1e641f3fe6a561848e2883cc3c6fed63368d2bc998b66ad9a3e61a7fe4dc391e3d688132beeec0974a8519253a70600 ASCII:E...e.}..@.......U...@..P.....{)g..<...........>4..6.GET /8-Bit/Dragon.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtm3..1.Y{.........yD..-.V.....5c...:...40v....F..l........4.3.>#...0......Z+k...#...+ky..A.*.;0......P4[......c.s..I.....%&...C...1.....N\;.c...G.."...p.c..6Uj..J...%r....GO.>r...9r*..u`.Q.....|.t..qeK62`..Q.MC2.e@.+....:F.A.G..(.. ...F..#. \..0.#S...1.......eS...#F...1uv.8h........L..A..jV.H..<....3h....f..>a..M......+...t.Q.S...
-uncompressed= 45000265007d00004006ce87c0a80002550d93d740050050c3138bdcaf7b296780183cec0de600000101080a00053e3410fc368e474554202f382d4269742f447261676f6e2e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f7777772e7a6f636b2e636f6d2f0d0a0d0a ASCII:E..e.}..@.......U...@..P.....{)g..<...........>4..6.GET /8-Bit/Dragon.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://www.zock.com/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 22
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010269008000004006ce80c0a80002550d93d740060050c3143301dfa11fa3de80183c892b5d00000101080a0005412c10fc3761474554202f382d4269742f456e74657270726973652e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f6600952f67defcc66dd03d3df7f6fd3bc72fe7112d64b4b08a552b571846d6983dda75049e3b6960ec701b7c388d1c6e8dca21be03070f183496db694e63468e1b3960e0316307460db756d6b04973474c132656dcee5483c376d6ad77603c2113470d1e326ad0784513c7ea1e18ae6110959386cd1bfe234a58be33a7870c19ae63548fc347285d3b1b63989103470616220ad3c870b263c60c36556acc986aba84d52572ecfcd6a3474f8c3e72ccb81149d22a96a3756010d91fe7b715bc7c90d4f9b891a54b36326216195105cd4332476540312bdd0678973a4614a923478f531951d0dc49d299aa0c1b316c8c98d2b9e143c64c8e4c011f63c60823781be2af63970d5e19469e1c31223d060dabbce3c44163e66e1caf4ed06c853a370f1af85ab9c2401267e41936f7bd9e4193e68d5d346ed5f4216bd5701aa142bd4eac78d1e7cfa1489596b46a3500 ASCII:E...i....@.......U...@..P..3........<.+]........A,..7aGET /8-Bit/Enterprise.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/f../g...m.==...;./..-d...U+W.F..=.u..;i`.p.|8..n..!.....4..iNcF..9`.1c.F..V..IsGL.&V..T..v..w`<!.G..2j.xE......a.......#JX.3.....cT..G(];.c...G.."...p.c..6Uj..j...%r....GO.>r...I.*..u`.......|......K62b..Q..C2Ge@1+..x.:F..#G.S.Q..I.....1l.....C.L.L..c..#x...c..^.F..1"=......Ac.n..N.l.:7...Z..@.g..6...A...]4n..!k.p..B.N.x....H...j5.
-uncompressed= 45000269008000004006ce80c0a80002550d93d740060050c31433dfa11fa3de80183c892b5d00000101080a0005412c10fc3761474554202f382d4269742f456e74657270726973652e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f7777772e7a6f636b2e636f6d2f0d0a0d0a ASCII:E..i....@.......U...@..P..3.......<.+]........A,..7aGET /8-Bit/Enterprise.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://www.zock.com/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 23
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010268008100004006ce80c0a80002550d93d740040050c313600b2189e30280183d0e896b00000101080a000541d810fc379d474554202f382d4269742f436f6d6d6f646f72652e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f3300952f67defcc6ed1d347b7ceeedfb778e5fce235ac8686115ab56ae308cac316b074dd71178eea481b1c3edf0e23472b86563478ef11d3878c0a0d1fc79f519396ee48081c78c1d1835dc5a59c326cd1d314d985871cb530d8edb59b7de81f1844c1c3578c8a841e3154d1cab7b60bc8631a78e9c346cdef81f51c2f29d393d64c8781de3791c3e68ead0b5d3318699a032b01061e85086931d3366b0a95263c654d325ac2e916327b81e3d7a62f49163c64dc9a056b1fcae038348ff38c1ade0e5832424f88e2e61b29131b3c8882a682292f92d038ad9ea36c4c3d431a248433d4c6544019ea46154193662d81831a5e1c38889991c99223ec68c1146f03ed45fc72e1bbc328c3c3962a47a0c1a5671c78983c6ccdd385e9da0d9ea746e1e34f2b5728581248ec9336cf27b3d8326cd1bbb68dcaae943d62ae13420417aad78312350a1448d228523c3aad500 ASCII:E...h....@.......U...@..P..`.!.....=..k........A...7.GET /8-Bit/Commodore.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/3../g.....4{|...w._.#Z.ha..V.0..1k.M..x........4r.ecG...8x....y..9n.......5.ZY.&..1M.Xq.S...Y.....L.5x..A..M..{`..1...4l...Q...9=d.x..y.>h....1...2..a.P...3f..Rc.T.%...c'..=zb..c.M..V.....H.8.....$$...a..1...*h"..-....6...1.HC=LeD...aT.6b..1........">...F.>._....2.<9b.z..Vq......8^....tn.4..r..$..3l.{=.&...h...C.*.4 Az.x1#P.D.".#....
-uncompressed= 45000268008100004006ce80c0a80002550d93d740040050c313600b2189e30280183d0e896b00000101080a000541d810fc379d474554202f382d4269742f436f6d6d6f646f72652e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f7777772e7a6f636b2e636f6d2f0d0a0d0a ASCII:E..h....@.......U...@..P..`.!.....=..k........A...7.GET /8-Bit/Commodore.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://www.zock.com/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 24
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010263008200004006ce84c0a80002550d93d740050050c3138e0daf7b2cf180183962cb2f00000101080a000542b410fc3822474554202f382d4269742f454143412e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b330096dfa4bd83668f4fbb78f5cec97b79440b192da24ead7a1586913561eda0c13a02cf9d343076a4f50d9c468eb46cecc809be03070f1834902b873e23c78d1c30f098b103a3465a2b6bd8a4b923a609132b6979aac1219baad53b309e9089a3060f193568b2a28913750f0cd530e6d4919386cd9bfc234a44be33a7870c19aa63288fc3074d9db77630c63023078e0c2c440c2294e164c78c196caad498e1347489a84be4d8e1ad478f9e187de49871035264542cbaebc020823f0e6f2b73f920e1b81da34a966c64bc2c32a20a1a866474cb801216ba8dee2c758c287250cf511951762739c854868d1836464c39a89021612647a6748f31638491b90aebd789cb66ae0c234f8e18811e8346d4d971e2a03123374e562768ac26759b074dfbaa5761208913f20c1bfa59cfa049f3262e9ab46afa7c8dfa37cdc68d59214aa4a873e7cfa04347468d1a00 ASCII:E...c....@.......U...@..P.....{,...9b./........B...8"GET /8-Bit/EACA.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+3......f.O.x...{yD..-.N.z...5a...:...40v....F..l........4.+.>#...0.....FZ+k...#...+iy..!...;0.......5h....u...0........#JD.3.....c(...M..v0.0#...,D."..d...l....4t..K....G...}..q.RdT,... .?.o+s. ....J.ld.,2....dt.......,u.(rP.Q.Qv'9.T...6FL9..!a&G.t.1c........f..#O.....F..q..1#7NV'h.&u..M..Wa ......Y..I.&...j.|..7...Y!J..s...CGF...
-uncompressed= 45000263008200004006ce84c0a80002550d93d740050050c3138e0daf7b2cf180183962cb2f00000101080a000542b410fc3822474554202f382d4269742f454143412e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f7777772e7a6f636b2e636f6d2f0d0a0d0a ASCII:E..c....@.......U...@..P.....{,...9b./........B...8"GET /8-Bit/EACA.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://www.zock.com/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 25
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010262008500004006ce82c0a80002550d93d740070050c314f5defa37d29b80183c168b6100000101080a000542c810fc37e5474554202f382d4269742f4d53582e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b330095dfa0bd83668fcfba77f3cec16b79440b192da04aa56a1586913560eda0b93a02cf9d343076a0edfd9b460eb46cecc801be03070f18348e277f3e23c78d1c30f098b103a3065a2b6bd8a4b923a609132b6879aac1117b6ad53b309e9089a3060f193568b0a28903750f8cd430e6d4919386cd1bfc234a40be33a7870c19a963248fc3074d1db7762ec63023078e0c2c440a1e94e164c78c196caad498d1147409a84be4d8d9ad478f9e187de49871f33124542cb9ebc020723fce6e2b72f920d9a8fd62ca956c64b82c32a20a9a856472cb8002f6b90dee2b758c2862508f511951742731b854868d1836464c318870e1602647a6708f31638411b908e9d781cb46ae0c234f8e18791e830654d971e2a03113370e562768aa226d9b070d7baa5661208903f20c9bf958cfa049f3062e1ab46afa7885ea378d468d581f469c9853674fa0424542851a00 ASCII:E...b....@.......U...@..P.....7....<..a........B...7.GET /8-Bit/MSX.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+3......f...w...kyD..-.J.j...5`...:...40v....F..l........4.'.>#...0......Z+k...#...+hy...{j.;0.......5h....u...0........#J@.3.....c$...M..v..0#...,D....d...l.....t..K....G...}..q.1$T,... r?.n+r. ...b..ld.,2....dr.......+u.(bP.Q.Qt'1.T...6FL1.p.`&G.p.1c........F..#O..y...T.q..1.7.V'h."m...{.Va ......X..I.....j.x..7.F.X.F..SgO.BEB...
-uncompressed= 45000262008500004006ce82c0a80002550d93d740070050c314f5defa37d29b80183c168b6100000101080a000542c810fc37e5474554202f382d4269742f4d53582e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f7777772e7a6f636b2e636f6d2f0d0a0d0a ASCII:E..b....@.......U...@..P.....7....<..a........B...7.GET /8-Bit/MSX.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://www.zock.com/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 26
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010265009400004006ce70c0a80002550d93d740060050c3143614a11fa986801836e1f43c00000101080a000545b010fc38b7474554202f382d4269742f4d617474656c2e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d3300942dbf512b744fcfbb79f7ced17b79440b192da452b58a1586913562eda0c93a02cf9d343076a8edfd9b460eb56cecc801be03070f18348e277f3e23c78d1c30f098b103a3865a2b6bd8a4b923a609132b6a77aac111bbead53b309e9089a3060f193568b4a28923750f8cd430e6d4919386cd1bfc234a44be33a7870c19a963248fc3074d1db87630c63023078e0c2c440a1e94e164c78c196caad498f1347409a94be4d8d9ad478f9e187de498710352a4542cb9ebc020723fce6e2b74f920e1a81da34a966c64bc2c32a20a1a866472cb8022f6b90dee2c758c2862504f521951742731e854868d1836464c31889021612647a6708f31638411ba08e9d791bbd8c89323469ec7a02195769c3868cc7ca5abd5099aab4bdfe641c3de2a561848e2843cc366bed63368d2bc018a46ad9a3e60a5fe4db371a356881229eae4f97368d19152a50600 ASCII:E...e....@..p....U...@..P..6.......6..<........E...8.GET /8-Bit/Mattel.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtm3..-.Q+tO..y...{yD..-.R.....5b...:...40v....F..l........4.'.>#...0......Z+k...#...+jw......;0.......5h...#u...0........#JD.3.....c$...M..v0.0#...,D....d...l....4t..K....G...}..q.R.T,... r?.n+t. ....J.ld.,2....dr.."....,u.(bPOR.Qt'1.T...6FL1..!a&G.p.1c...........#F...!.v.8h.|......K..A..*V.H..<.f..3h....F..>`..M.q.V..)...sh..R...
-uncompressed= 45000265009400004006ce70c0a80002550d93d740060050c3143614a11fa986801836e1f43c00000101080a000545b010fc38b7474554202f382d4269742f4d617474656c2e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f7777772e7a6f636b2e636f6d2f0d0a0d0a ASCII:E..e....@..p....U...@..P..6.......6..<........E...8.GET /8-Bit/Mattel.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://www.zock.com/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 27
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010263009900004006ce6dc0a80002550d93d740040050c313623f2189e66b801839a5739a00000101080a0005464c10fc38f3474554202f382d4269742f4f7269632e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b330095dfa4bd83668f4fc578f5eab13ca2858c1651a756bd0ac3c89ab076d0601d81e74e1a183bd2fa064e23475a3676e404df8183070c1ac895439f91e3460e1878ccd8815123ad95356cd2dc11d3848995b43cd5e0904dd5ea1d184fc8c45183878c1a3459d1c489ba0706631873eac849c3e64dfe112520df99d343860cc63194c7e18326e8768c31ccc88123030b1183086538d93163069b2a356638155d22ea12397678ebd1a327461f3966dc7c0c19158bee3a3088e08fc3db8a5c3e4838dac19872251b192e8b8ca882862119dd32a084856ea3fb4a1d238a1cd483544694dd490e36956123868d11530e2a642898c99129dd63cc186144aec2fa75e0b2912bc3c8932346a0c7a01135769c3868ccc48d93d5091aab4adde641d3beea551848e2803cc3867ed63368d2bc818b26ad9a3e5fa3f64db3716356881229e6d4d91328519151a30600 ASCII:E...c....@..m....U...@..P..b?!..k..9.s.........FL..8.GET /8-Bit/Oric.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+3......f.O.x...<....Q.V......v.`...N..;...N#GZ6v..........C...F..x...Q#..5l........<...M....O..Q....4Y......c.s..I..M..% ...C...1....&.v.1...#.....e8.1c..*5f8.]"..9vx...'F.9f.|.....:0......\>H8...r%........!..2...n..J.#....TF..I.6.a#...S.*d(...).c..aD...u...+...#F....5v.8h........J..A...U.H..<..~.3h....&..>_..M.qcV..)....(Q.Q...
-uncompressed= 45000263009900004006ce6dc0a80002550d93d740040050c313623f2189e66b801839a5739a00000101080a0005464c10fc38f3474554202f382d4269742f4f7269632e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f7777772e7a6f636b2e636f6d2f0d0a0d0a ASCII:E..c....@..m....U...@..P..b?!..k..9.s.........FL..8.GET /8-Bit/Oric.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://www.zock.com/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 28
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010269009e00004006ce62c0a80002550d93d740060050c3143845a11fab60801840003c1c00000101080a000547d810fc38b7474554202f382d4269742f526164696f536861636b2e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f330096316be6fcc6ed1d347b7a46f60b584fe7112d64b4b08a552b5718468ad6b183a6eb083c77d2c0d8e17678711a39dcb2b123c7f80e1c3c60d068febcfa8c1c3772c0c063c60e8c1a6e89b24973474c132656dcee5483e376d6ad77603c2113470d1e326ad0784513c7ea1e189361cca923270d9b37fd4794b87c674e0f193226c7781e870f9a3a74ed748c61460e1c195888307428c3c98e1933d854a93163eae9125697c8b1135c8f1e3d31fac831e3a6e449ab587ed78141847f9ce056f0f24112127cc79731d9c8a0596444153411c9fc9601c56c751be263ea1851a4a19ea732a2004fd2b0aa0c1b316c8c98d2f061c4c54c8e4c111f63c60823781fe6af6357685e234f8e18a91e838655dd71e2a03173378e572768b6469d9b074d7cad5c61208963f20c1bfc5ecfa049f3c62e1ab76afa90b55a380d48905e2b5ecc1874e8d1a44b515ab51a00 ASCII:E...i....@..b....U...@..P..8E...`..@.<.........G...8.GET /8-Bit/RadioShack.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/3..1k.....4{zF..XO..-d...U+W.F.......<w....vxq.9...#....<`.h.....7r..c....n..IsGL.&V..T..v..w`<!.G..2j.xE......a..#'..7.G..|gN..2&.x....:t.t.aF...X.0t(....3.T.1c...V....\..=1..1...I.X~..A....V..A..|..1...YdD.4......lu..c..Q....2..O.....1l....a..L.L..c..#x...cWh^#O......U.q..1s7.W'h.F...M|.\a .c....^..I.....j...Z8.H.^+^..t...KQZ...
-uncompressed= 45000269009e00004006ce62c0a80002550d93d740060050c3143845a11fab60801840003c1c00000101080a000547d810fc38b7474554202f382d4269742f526164696f536861636b2e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f7777772e7a6f636b2e636f6d2f0d0a0d0a ASCII:E..i....@..b....U...@..P..8E...`..@.<.........G...8.GET /8-Bit/RadioShack.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://www.zock.com/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 29
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   4500010266009f00004006ce64c0a80002550d93d740050050c313903caf7b2f9580183d5ce4ef00000101080a0005481810fc3934474554202f382d4269742f5068696c6970732e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d3300952fbf597b07cd1e9f8cf5f2d58379440b192da85ac5aa1586913563eda0d93a02cf9d343076acfd1d9c468eb56cecc811be03070f1834922f8f3e23c78d1c30f098b103a3c65a2b41d3dc11d3848995b53cd5e0987d35eb1d184fc8c45183878c1a345cd1c4a1ba0786631873eac8492334ff881292efcce9214386e318cbe3f0415307b19d8b31ccc88123030b1183086538d93163069b2a3566441d5d82ea1239767aebd1a327461f3966dc7c0c4915cbee3a3088e08fd3db0a5d3e483672bf9872251b192e8b8ca882e60d1a32bb6540191bdd86f7953a461439a847a98c28bc931c7c2ac3460c1b23a61c5428f830932353bcc79831c2085d85f5ebc8654357869127478c448f4183eaed3871d098991b87ab133459990ecd83a63d56ad3090c40179860d7dae67d0a4792317cd5a357d8852059c46a346ae0f234ecca9b32750a322a9520d00 ASCII:E...f....@..d....U...@..P...<.{/...=\..........H...94GET /8-Bit/Philips.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtm3../.Y{.........yD..-.Z.....5c...:...40v....F..l........4./.>#...0......Z+A........<...}5...O..Q....4\......c.s..I#4.......!C......AS....1...#.....e8.1c..*5fD.]...9vz...'F.9f.|.I...:0......]>H6r..r%..........2.e@......:F.9.G..(...|*.F..#..T(.0.#S...1..]....eCW..'G.D.A...8q.......4Y.....=V.0...y..}.g..y#..Z5}.R..F.F..#N...'P.".R..
-uncompressed= 45000266009f00004006ce64c0a80002550d93d740050050c313903caf7b2f9580183d5ce4ef00000101080a0005481810fc3934474554202f382d4269742f5068696c6970732e47494620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f7777772e7a6f636b2e636f6d2f0d0a0d0a ASCII:E..f....@..d....U...@..P...<.{/...=\..........H...94GET /8-Bit/Philips.GIF HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://www.zock.com/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 30
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   450001049b00ae00004006cc20c0a80002550d93d740050050c31396ceaf7b396e801840009ad400000101080a0005611010fc3d6b474554202f382d4269742f6d72776f6e672e67696620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d33009733bf617b07cd9e9f8ef7f6d5a379440b192da85ac5aa1586913564eda0d93a02cf9d343076b00d3e9c460eb66cecc821be03070f183496379f3e23c78d1c30f098b103a3065b2b6b92de11d3848915b63dd5e0a87d35eb1d184fc814c543460d1aae68e250dd0303328c3975e4a461f346ff881294efcce9214306e418cde3f0415347ae1d8c31ccc88123030b1183086538d93163069b2a3566442d5d82ea1239767eebd1a327461f3966dc801449154bef3a3088e48ff3db0a513e48387ac7a892251b192f8b8ca882862199de32a0909d6e033c4b1d238a1cd4a3544614df490e3e956123868d11530e2a644898c99129e063cc186184a8423578ead06563d7c8932346a6c7a04175769c3868ccd48dc3d5099aac4ce3e641f31eab561848e2843cc3a628d73368d2bca18b86ad9a3e62a9fe4db3712357881229eadce933e8d09154a92a417265848c1d307afec489074e198678e6108d31a7e8882557ae4c9111357903abdf7f7b052b96ec4f3868d51e7e1b77ae74198ef7f63d1a76ce52bf50cf4c9d7355b7ddb290634cae7cb9b4dec05f135b76c178c41d347b7e16eeabc732db16325a74cf7a07869135647bff0e3e7c075bdad3732c6f4e7c070e1ed37dcb993e23c78d1c30f07807cfd6ca1a3669ee8869c2c40adb9e6a70a8d60ae30999a278c8e4e78a260ed53d3020c33088900d43ae25204aa46818239f8d6cbc631c3a120b11ff6964a864c9e6e58ca8a54b505d220727579d3b7d06bd48158b52a6f99f72b542940f923a13ed600c39838d8c974546fc6548a63761b2d36d8067a96344913a72f428951105cd9d248a9fcab011c3c688298ad30c444398c99129e063cc18313bce683578eae8b66be4c91123d363246f003b0e1a33d2b93a41939569dc3c68d6df8181248e193967d814e57a064d9a3774d1b055d387cd1caa7fd36cdcc835618f853a63d07473510655aa0100 ASCII:E........@.. ....U...@..P.....{9n..@...........a...=kGET /8-Bit/mrwong.gif HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtm3..3.a{.........yD..-.Z.....5d...:...40v..>.F..l..!.....4.7.>#...0......[+k........=...}5...O...CF...h.P...2.9u..a.F.......!C......ASG...1...#.....e8.1c..*5fD-]...9v~...'F.9f...I.K.:0......Q>H8z...%../.....!..2...n.<K.#....TF..I.>.a#...S.*dH...).c..a..B5x..ec...#F...Auv.8h........L..A...V.H..<..(.3h.......>b..M.q#W..)...3...T.*Are...0z....N..x...1...%W.L..5y....{.+..O8h..~.w.t....=.v.R.P.L.sU....cL.|...._.[v.x..4{~....2..2Zt.z...5d{..>|.[..s,oN|....}..>#...0.x.....6i..i.....jp.......x....&..=0 .0...C.% J.h.#..l.c.:....id.d......KP]".'W.;}..H..R...r.B...:..`.9....EF.eH.7a..m.g.cD.:r.(.....$........)...DC...).c..1;.h5x...k...#.c$o.;..3..:A..i.<h....$..9g...z.M.7t..U.......l..5a..:c.tsQ.U...
-uncompressed= 4500049b00ae00004006cc20c0a80002550d93d740050050c31396ceaf7b396e801840009ad400000101080a0005611010fc3d6b474554202f382d4269742f6d72776f6e672e67696620485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f7777772e7a6f636b2e636f6d2f0d0a0d0a474554202f382d4269742f7374756d626c6575706f6e2e706e6720485454502f312e310d0a4163636570743a206d756c7469706172742f6d697865642c206170706c69636174696f6e2f766e642e7761702e6d756c7469706172742e6d697865642c206170706c69636174696f6e2f766e642e7761702e7868746d6c2b786d6c2c206170706c69636174696f6e2f7868746d6c2b786d6c2c20746578742f766e642e7761702e776d6c2c202a2f2a0d0a4163636570742d436861727365743a207574662d382c207574662d31362c2069736f2d383835392d312c2069736f2d31303634362d7563732d322c2053686966745f4a49532c20426967350d0a4163636570742d4c616e67756167653a20656e0d0a782d7761702d70726f66696c653a2022687474703a2f2f7761702e736f6e796572696373736f6e2e636f6d2f554170726f662f4b38303069523230312e786d6c220d0a486f73743a207777772e7a6f636b2e636f6d0d0a557365722d4167656e743a20536f6e794572696373736f6e4b383030692f5232422052656c656173652f4d61722d31332d323030372042726f777365722f4e657446726f6e742f332e332050726f66696c652f4d4944502d322e3020436f6e66696775726174696f6e2f434c44432d312e310d0a436f6e6e656374696f6e3a204b6565702d416c6976650d0a4163636570742d456e636f64696e673a206465666c6174652c20677a69700d0a526566657265723a20687474703a2f2f7777772e7a6f636b2e636f6d2f0d0a0d0a ASCII:E.......@.. ....U...@..P.....{9n..@...........a...=kGET /8-Bit/mrwong.gif HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://www.zock.com/....GET /8-Bit/stumbleupon.png HTTP/1.1..Accept: multipart/mixed, application/vnd.wap.multipart.mixed, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/vnd.wap.wml, */*..Accept-Charset: utf-8, utf-16, iso-8859-1, iso-10646-ucs-2, Shift_JIS, Big5..Accept-Language: en..x-wap-profile: "http://wap.sonyericsson.com/UAprof/K800iR201.xml"..Host: www.zock.com..User-Agent: SonyEricssonK800i/R2B Release/Mar-13-2007 Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1..Connection: Keep-Alive..Accept-Encoding: deflate, gzip..Referer: http://www.zock.com/....
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 31
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   45000101a0f3d84000400679210a0901abc0a800021f90400538e210f07a827bb1501900ed7be90000485454502f312e3020323030204f4b0d0a5365727665723a2053696d706c65485454502f302e3620507974686f6e2f322e372e360d0a446174653a205765642c203301312041756720323031362030393a32383a353220474d540d0a436f6e74656e742d747970653a20746578742f68746d6c3b20636861727365743d5554462d380d0a436f6e74656e742d4c656e6774683a203232320d0a0d0a66003f481c9162e40a97294800002068746d6c20506600588a3c6162644409183200002f5733432f2f4454442048544d4c20332e322046696e616c2f2f454e223e3c68746d66006f8234f87187cd1d006c653e4469726563746f7279206c697374696e672066016f72202f3c2f7469746c990068bcff2823e70c9fff6b6a943f9f7e7dfbf7f1e7d7bf9f5fb1c2ef6beafcc7d3fd3b7ced646aa34f03a404fa3373a4c64113630efdec27534e7509538d7e32ff657044a8f1bb0c82067f72f71e00 ASCII:E......@.@.y!..........@.8...z.{.P...{...HTTP/1.0 200 OK..Server: SimpleHTTP/0.6 Python/2.7.6..Date: Wed, 3.1 Aug 2016 09:28:52 GMT..Content-type: text/html; charset=UTF-8..Content-Length: 222....f.?H..b...)H.. html Pf.X.<abdD..2../W3C//DTD HTML 3.2 Final//EN"><htmf.o.4.q....le>Directory listing f.or /</titl..h..(#....kj.?.~}......._...k.....;|.dj.O....3s..A.c...'SNu.S.~2.epD.......r...
-uncompressed= 450001a0f3d84000400679210a0901abc0a800021f90400538e210f07a827bb1501900ed7be90000485454502f312e3020323030204f4b0d0a5365727665723a2053696d706c65485454502f302e3620507974686f6e2f322e372e360d0a446174653a205765642c2033312041756720323031362030393a32383a353220474d540d0a436f6e74656e742d747970653a20746578742f68746d6c3b20636861727365743d5554462d380d0a436f6e74656e742d4c656e6774683a203232320d0a0d0a3c21444f43545950452068746d6c205055424c494320222d2f2f5733432f2f4454442048544d4c20332e322046696e616c2f2f454e223e3c68746d6c3e0a3c7469746c653e4469726563746f7279206c697374696e6720666f72202f3c2f7469746c653e0a3c626f64793e0a3c68323e4469726563746f7279206c697374696e6720666f72202f3c2f68323e0a3c68723e0a3c756c3e0a3c6c693e3c6120687265663d2272656470686f6e652e706e67223e72656470686f6e652e706e673c2f613e0a3c2f756c3e0a3c68723e0a3c2f626f64793e0a3c2f68746d6c3e0a ASCII:E.....@.@.y!..........@.8...z.{.P...{...HTTP/1.0 200 OK..Server: SimpleHTTP/0.6 Python/2.7.6..Date: Wed, 31 Aug 2016 09:28:52 GMT..Content-type: text/html; charset=UTF-8..Content-Length: 222....<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>.<title>Directory listing for /</title>.<body>.<h2>Directory listing for /</h2>.<hr>.<ul>.<li><a href="redphone.png">redphone.png</a>.</ul>.<hr>.</body>.</html>.
-
-Testing decompression with sniffed compressed TCP/IP packets:
-Packet No.: 32
-v42bis_decompress_flush() rc=0
-v42bis_decompress() rc=0
-v42bis_decompress_flush() rc=0
-compressed=   45000101a0e9a54000400683540a0901abc0a800021f904004437442f17a4ab3b1501900ed04900000485454502f312e3020323030204f4b0d0a5365727665723a2053696d706c65485454502f302e3620507974686f6e2f322e372e360d0a446174653a205765642c203301312041756720323031362030393a32373a353520474d540d0a436f6e74656e742d747970653a20746578742f68746d6c3b20636861727365743d5554462d380d0a436f6e74656e742d4c656e6774683a203232320d0a0d0a66003f481c9162e40a97294800002068746d6c20506600588a3c6162644409183200002f5733432f2f4454442048544d4c20332e322046696e616c2f2f454e223e3c68746d6c3e0a3c7469746c653e4469726563746f7279206c697374696e672066016f72202f3c2f7469746c990068beff2823e70c9f816b6a9847af9ebd7bf8f2e9dbc7af5ff142f06bea0cc4e31d7cfced646aa74f03a444fa3373a4c64113634e7ded28554e7d1953cd7e320365744cb811bc8c82078376ff1e00 ASCII:E......@.@..T..........@.CtB.zJ..P.......HTTP/1.0 200 OK..Server: SimpleHTTP/0.6 Python/2.7.6..Date: Wed, 3.1 Aug 2016 09:27:55 GMT..Content-type: text/html; charset=UTF-8..Content-Length: 222....f.?H..b...)H.. html Pf.X.<abdD..2../W3C//DTD HTML 3.2 Final//EN"><html>.<title>Directory listing f.or /</titl..h..(#....kj.G...{......_.B.k.....|..dj.O..D.3s..A.cN}.(UN}.S.~2.etL.......v...
-uncompressed= 450001a0e9a54000400683540a0901abc0a800021f904004437442f17a4ab3b1501900ed04900000485454502f312e3020323030204f4b0d0a5365727665723a2053696d706c65485454502f302e3620507974686f6e2f322e372e360d0a446174653a205765642c2033312041756720323031362030393a32373a353520474d540d0a436f6e74656e742d747970653a20746578742f68746d6c3b20636861727365743d5554462d380d0a436f6e74656e742d4c656e6774683a203232320d0a0d0a3c21444f43545950452068746d6c205055424c494320222d2f2f5733432f2f4454442048544d4c20332e322046696e616c2f2f454e223e3c68746d6c3e0a3c7469746c653e4469726563746f7279206c697374696e6720666f72202f3c2f7469746c653e0a3c626f64793e0a3c68323e4469726563746f7279206c697374696e6720666f72202f3c2f68323e0a3c68723e0a3c756c3e0a3c6c693e3c6120687265663d2272656470686f6e652e706e67223e72656470686f6e652e706e673c2f613e0a3c2f756c3e0a3c68723e0a3c2f626f64793e0a3c2f68746d6c3e0a ASCII:E.....@.@..T..........@.CtB.zJ..P.......HTTP/1.0 200 OK..Server: SimpleHTTP/0.6 Python/2.7.6..Date: Wed, 31 Aug 2016 09:27:55 GMT..Content-type: text/html; charset=UTF-8..Content-Length: 222....<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>.<title>Directory listing for /</title>.<body>.<h2>Directory listing for /</h2>.<hr>.<ul>.<li><a href="redphone.png">redphone.png</a>.</ul>.<hr>.</body>.</html>.
-
-Done
diff --git a/tests/vty_test_runner.py b/tests/vty_test_runner.py
index 7d4e121..05bc3bf 100644
--- a/tests/vty_test_runner.py
+++ b/tests/vty_test_runner.py
@@ -130,998 +130,6 @@
         self.assertEquals(res.find('  rtp net-bind-ip'), -1)
 
 
-class TestVTYGenericBSC(TestVTYBase):
-
-    def _testConfigNetworkTree(self, include_bsc_items=True):
-        self.vty.enable()
-        self.assertTrue(self.vty.verify("configure terminal",['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify("network",['']))
-        self.assertEquals(self.vty.node(), 'config-net')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify("bts 0",['']))
-        self.assertEquals(self.vty.node(), 'config-net-bts')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify("trx 0",['']))
-        self.assertEquals(self.vty.node(), 'config-net-bts-trx')
-        self.checkForEndAndExit()
-        self.vty.command("write terminal")
-        self.assertTrue(self.vty.verify("exit",['']))
-        self.assertEquals(self.vty.node(), 'config-net-bts')
-        self.assertTrue(self.vty.verify("exit",['']))
-        self.assertTrue(self.vty.verify("bts 1",['']))
-        self.assertEquals(self.vty.node(), 'config-net-bts')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify("trx 1",['']))
-        self.assertEquals(self.vty.node(), 'config-net-bts-trx')
-        self.checkForEndAndExit()
-        self.vty.command("write terminal")
-        self.assertTrue(self.vty.verify("exit",['']))
-        self.assertEquals(self.vty.node(), 'config-net-bts')
-        self.assertTrue(self.vty.verify("exit",['']))
-        self.assertEquals(self.vty.node(), 'config-net')
-        self.assertTrue(self.vty.verify("exit",['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.assertTrue(self.vty.verify("exit",['']))
-        self.assertTrue(self.vty.node() is None)
-
-class TestVTYMSC(TestVTYBase):
-
-    def vty_command(self):
-        return ["./src/osmo-msc/osmo-msc", "-c",
-                "doc/examples/osmo-msc/osmo-msc.cfg"]
-
-    def vty_app(self):
-        return (4254, "./src/osmo-msc/osmo-msc", "OsmoMSC", "msc")
-
-    def testConfigNetworkTree(self, include_bsc_items=True):
-        self.vty.enable()
-        self.assertTrue(self.vty.verify("configure terminal",['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify("network",['']))
-        self.assertEquals(self.vty.node(), 'config-net')
-        self.checkForEndAndExit()
-        self.vty.command("write terminal")
-        self.assertTrue(self.vty.verify("exit",['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.assertTrue(self.vty.verify("exit",['']))
-        self.assertTrue(self.vty.node() is None)
-
-    def checkForSmpp(self):
-        """SMPP is not always enabled, check if it is"""
-        res = self.vty.command("list")
-        return "smpp" in res
-
-    def testSmppFirst(self):
-        # enable the configuration
-        self.vty.enable()
-        self.vty.command("configure terminal")
-
-        if not self.checkForSmpp():
-            return
-
-        self.vty.command("smpp")
-
-        # check the default
-        res = self.vty.command("write terminal")
-        self.assert_(res.find(' no smpp-first') > 0)
-
-        self.vty.verify("smpp-first", [''])
-        res = self.vty.command("write terminal")
-        self.assert_(res.find(' smpp-first') > 0)
-        self.assertEquals(res.find('no smpp-first'), -1)
-
-        self.vty.verify("no smpp-first", [''])
-        res = self.vty.command("write terminal")
-        self.assert_(res.find('no smpp-first') > 0)
-
-    def testVtyTree(self):
-        self.vty.enable()
-        self.assertTrue(self.vty.verify("configure terminal", ['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify('mncc-int', ['']))
-        self.assertEquals(self.vty.node(), 'config-mncc-int')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify('exit', ['']))
-
-        if self.checkForSmpp():
-            self.assertEquals(self.vty.node(), 'config')
-            self.assertTrue(self.vty.verify('smpp', ['']))
-            self.assertEquals(self.vty.node(), 'config-smpp')
-            self.checkForEndAndExit()
-            self.assertTrue(self.vty.verify("exit", ['']))
-
-        self.assertEquals(self.vty.node(), 'config')
-        self.assertTrue(self.vty.verify("exit", ['']))
-        self.assertTrue(self.vty.node() is None)
-
-        # Check searching for outer node's commands
-        self.vty.command("configure terminal")
-        self.vty.command('mncc-int')
-
-        if self.checkForSmpp():
-            self.vty.command('smpp')
-            self.assertEquals(self.vty.node(), 'config-smpp')
-            self.vty.command('mncc-int')
-
-        self.assertEquals(self.vty.node(), 'config-mncc-int')
-
-    def testVtyAuthorization(self):
-        self.vty.enable()
-        self.vty.command("configure terminal")
-        self.vty.command("network")
-        self.assertTrue(self.vty.verify("auth policy closed", ['']))
-        self.assertTrue(self.vty.verify("auth policy regexp", ['']))
-        self.assertTrue(self.vty.verify("authorized-regexp ^001", ['']))
-        self.assertTrue(self.vty.verify("authorized-regexp 02$", ['']))
-        self.assertTrue(self.vty.verify("authorized-regexp *123.*", ['']))
-        self.vty.command("end")
-
-    def testSi2Q(self):
-        self.vty.enable()
-        self.vty.command("configure terminal")
-        self.vty.command("network")
-        self.vty.command("bts 0")
-        before = self.vty.command("show running-config")
-        self.vty.command("si2quater neighbor-list add earfcn 1911 threshold 11 2")
-        self.vty.command("si2quater neighbor-list add earfcn 1924 threshold 11 3")
-        self.vty.command("si2quater neighbor-list add earfcn 2111 threshold 11")
-        self.vty.command("si2quater neighbor-list del earfcn 1911")
-        self.vty.command("si2quater neighbor-list del earfcn 1924")
-        self.vty.command("si2quater neighbor-list del earfcn 2111")
-        self.assertEquals(before, self.vty.command("show running-config"))
-        self.vty.command("si2quater neighbor-list add uarfcn 1976 13 1")
-        self.vty.command("si2quater neighbor-list add uarfcn 1976 38 1")
-        self.vty.command("si2quater neighbor-list add uarfcn 1976 44 1")
-        self.vty.command("si2quater neighbor-list add uarfcn 1976 120 1")
-        self.vty.command("si2quater neighbor-list add uarfcn 1976 140 1")
-        self.vty.command("si2quater neighbor-list add uarfcn 1976 163 1")
-        self.vty.command("si2quater neighbor-list add uarfcn 1976 166 1")
-        self.vty.command("si2quater neighbor-list add uarfcn 1976 217 1")
-        self.vty.command("si2quater neighbor-list add uarfcn 1976 224 1")
-        self.vty.command("si2quater neighbor-list add uarfcn 1976 225 1")
-        self.vty.command("si2quater neighbor-list add uarfcn 1976 226 1")
-        self.vty.command("si2quater neighbor-list del uarfcn 1976 13")
-        self.vty.command("si2quater neighbor-list del uarfcn 1976 38")
-        self.vty.command("si2quater neighbor-list del uarfcn 1976 44")
-        self.vty.command("si2quater neighbor-list del uarfcn 1976 120")
-        self.vty.command("si2quater neighbor-list del uarfcn 1976 140")
-        self.vty.command("si2quater neighbor-list del uarfcn 1976 163")
-        self.vty.command("si2quater neighbor-list del uarfcn 1976 166")
-        self.vty.command("si2quater neighbor-list del uarfcn 1976 217")
-        self.vty.command("si2quater neighbor-list del uarfcn 1976 224")
-        self.vty.command("si2quater neighbor-list del uarfcn 1976 225")
-        self.vty.command("si2quater neighbor-list del uarfcn 1976 226")
-        self.assertEquals(before, self.vty.command("show running-config"))
-
-    def testEnableDisablePeriodicLU(self):
-        self.vty.enable()
-        self.vty.command("configure terminal")
-        self.vty.command("network")
-        self.vty.command("bts 0")
-
-        # Test invalid input
-        self.vty.verify("periodic location update 0", ['% Unknown command.'])
-        self.vty.verify("periodic location update 5", ['% Unknown command.'])
-        self.vty.verify("periodic location update 1531", ['% Unknown command.'])
-
-        # Enable periodic lu..
-        self.vty.verify("periodic location update 60", [''])
-        res = self.vty.command("write terminal")
-        self.assert_(res.find('periodic location update 60') > 0)
-        self.assertEquals(res.find('no periodic location update'), -1)
-
-        # Now disable it..
-        self.vty.verify("no periodic location update", [''])
-        res = self.vty.command("write terminal")
-        self.assertEquals(res.find('periodic location update 60'), -1)
-        self.assert_(res.find('no periodic location update') > 0)
-
-    def testShowNetwork(self):
-        res = self.vty.command("show network")
-        self.assert_(res.startswith('BSC is on Country Code') >= 0)
-
-    def testMeasurementFeed(self):
-        self.vty.enable()
-        self.vty.command("configure terminal")
-        self.vty.command("mncc-int")
-
-        res = self.vty.command("write terminal")
-        self.assertEquals(res.find('meas-feed scenario'), -1)
-
-        self.vty.command("meas-feed scenario bla")
-        res = self.vty.command("write terminal")
-        self.assert_(res.find('meas-feed scenario bla') > 0)
-
-        self.vty.command("meas-feed scenario abcdefghijklmnopqrstuvwxyz01234567890")
-        res = self.vty.command("write terminal")
-        self.assertEquals(res.find('meas-feed scenario abcdefghijklmnopqrstuvwxyz01234567890'), -1)
-        self.assertEquals(res.find('meas-feed scenario abcdefghijklmnopqrstuvwxyz012345'), -1)
-        self.assert_(res.find('meas-feed scenario abcdefghijklmnopqrstuvwxyz01234') > 0)
-
-
-class TestVTYBSC(TestVTYGenericBSC):
-
-    def vty_command(self):
-        return ["./src/osmo-bsc/osmo-bsc", "-c",
-                "doc/examples/osmo-bsc/osmo-bsc.cfg"]
-
-    def vty_app(self):
-        return (4242, "./src/osmo-bsc/osmo-bsc", "OsmoBSC", "bsc")
-
-    def testConfigNetworkTree(self):
-        self._testConfigNetworkTree()
-
-    def testVtyTree(self):
-        self.vty.enable()
-        self.assertTrue(self.vty.verify("configure terminal", ['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify("msc 0", ['']))
-        self.assertEquals(self.vty.node(), 'config-msc')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify("exit", ['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.assertTrue(self.vty.verify("bsc", ['']))
-        self.assertEquals(self.vty.node(), 'config-bsc')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify("exit", ['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.assertTrue(self.vty.verify("exit", ['']))
-        self.assertTrue(self.vty.node() is None)
-
-        # Check searching for outer node's commands
-        self.vty.command("configure terminal")
-        self.vty.command('msc 0')
-        self.vty.command("bsc")
-        self.assertEquals(self.vty.node(), 'config-bsc')
-        self.vty.command("msc 0")
-        self.assertEquals(self.vty.node(), 'config-msc')
-
-    def testUssdNotificationsMsc(self):
-        self.vty.enable()
-        self.vty.command("configure terminal")
-        self.vty.command("msc")
-
-        # Test invalid input
-        self.vty.verify("bsc-msc-lost-text", ['% Command incomplete.'])
-        self.vty.verify("bsc-welcome-text", ['% Command incomplete.'])
-        self.vty.verify("bsc-grace-text", ['% Command incomplete.'])
-
-        # Enable USSD notifications
-        self.vty.verify("bsc-msc-lost-text MSC disconnected", [''])
-        self.vty.verify("bsc-welcome-text Hello MS", [''])
-        self.vty.verify("bsc-grace-text In grace period", [''])
-
-        # Verify settings
-        res = self.vty.command("write terminal")
-        self.assert_(res.find('bsc-msc-lost-text MSC disconnected') > 0)
-        self.assertEquals(res.find('no bsc-msc-lost-text'), -1)
-        self.assert_(res.find('bsc-welcome-text Hello MS') > 0)
-        self.assertEquals(res.find('no bsc-welcome-text'), -1)
-        self.assert_(res.find('bsc-grace-text In grace period') > 0)
-        self.assertEquals(res.find('no bsc-grace-text'), -1)
-
-        # Now disable it..
-        self.vty.verify("no bsc-msc-lost-text", [''])
-        self.vty.verify("no bsc-welcome-text", [''])
-        self.vty.verify("no bsc-grace-text", [''])
-
-        # Verify settings
-        res = self.vty.command("write terminal")
-        self.assertEquals(res.find('bsc-msc-lost-text MSC disconnected'), -1)
-        self.assert_(res.find('no bsc-msc-lost-text') > 0)
-        self.assertEquals(res.find('bsc-welcome-text Hello MS'), -1)
-        self.assert_(res.find('no bsc-welcome-text') > 0)
-        self.assertEquals(res.find('bsc-grace-text In grace period'), -1)
-        self.assert_(res.find('no bsc-grace-text') > 0)
-
-    def testUssdNotificationsBsc(self):
-        self.vty.enable()
-        self.vty.command("configure terminal")
-        self.vty.command("bsc")
-
-        # Test invalid input
-        self.vty.verify("missing-msc-text", ['% Command incomplete.'])
-
-        # Enable USSD notifications
-        self.vty.verify("missing-msc-text No MSC found", [''])
-
-        # Verify settings
-        res = self.vty.command("write terminal")
-        self.assert_(res.find('missing-msc-text No MSC found') > 0)
-        self.assertEquals(res.find('no missing-msc-text'), -1)
-
-        # Now disable it..
-        self.vty.verify("no missing-msc-text", [''])
-
-        # Verify settings
-        res = self.vty.command("write terminal")
-        self.assertEquals(res.find('missing-msc-text No MSC found'), -1)
-        self.assert_(res.find('no missing-msc-text') > 0)
-
-    def testNetworkTimezone(self):
-        self.vty.enable()
-        self.vty.verify("configure terminal", [''])
-        self.vty.verify("network", [''])
-
-        # Test invalid input
-        self.vty.verify("timezone", ['% Command incomplete.'])
-        self.vty.verify("timezone 20 0", ['% Unknown command.'])
-        self.vty.verify("timezone 0 11", ['% Unknown command.'])
-        self.vty.verify("timezone 0 0 99", ['% Unknown command.'])
-
-        # Set time zone without DST
-        self.vty.verify("timezone 2 30", [''])
-
-        # Verify settings
-        res = self.vty.command("write terminal")
-        self.assert_(res.find('timezone 2 30') > 0)
-        self.assertEquals(res.find('timezone 2 30 '), -1)
-
-        # Set time zone with DST
-        self.vty.verify("timezone 2 30 1", [''])
-
-        # Verify settings
-        res = self.vty.command("write terminal")
-        self.assert_(res.find('timezone 2 30 1') > 0)
-
-        # Now disable it..
-        self.vty.verify("no timezone", [''])
-
-        # Verify settings
-        res = self.vty.command("write terminal")
-        self.assertEquals(res.find(' timezone'), -1)
-
-    def testShowNetwork(self):
-        res = self.vty.command("show network")
-        self.assert_(res.startswith('BSC is on Country Code') >= 0)
-
-    def testPingPongConfiguration(self):
-        self.vty.enable()
-        self.vty.verify("configure terminal", [''])
-        self.vty.verify("network", [''])
-        self.vty.verify("msc 0", [''])
-
-        self.vty.verify("timeout-ping 12", [''])
-        self.vty.verify("timeout-pong 14", [''])
-        res = self.vty.command("show running-config")
-        self.assert_(res.find(" timeout-ping 12") > 0)
-        self.assert_(res.find(" timeout-pong 14") > 0)
-        self.assert_(res.find(" no timeout-ping advanced") > 0)
-
-        self.vty.verify("timeout-ping advanced", [''])
-        res = self.vty.command("show running-config")
-        self.assert_(res.find(" timeout-ping 12") > 0)
-        self.assert_(res.find(" timeout-pong 14") > 0)
-        self.assert_(res.find(" timeout-ping advanced") > 0)
-
-        self.vty.verify("no timeout-ping advanced", [''])
-        res = self.vty.command("show running-config")
-        self.assert_(res.find(" timeout-ping 12") > 0)
-        self.assert_(res.find(" timeout-pong 14") > 0)
-        self.assert_(res.find(" no timeout-ping advanced") > 0)
-
-        self.vty.verify("no timeout-ping", [''])
-        res = self.vty.command("show running-config")
-        self.assertEquals(res.find(" timeout-ping 12"), -1)
-        self.assertEquals(res.find(" timeout-pong 14"), -1)
-        self.assertEquals(res.find(" no timeout-ping advanced"), -1)
-        self.assert_(res.find(" no timeout-ping") > 0)
-
-        self.vty.verify("timeout-ping advanced", ['%ping handling is disabled. Enable it first.'])
-
-        # And back to enabling it
-        self.vty.verify("timeout-ping 12", [''])
-        self.vty.verify("timeout-pong 14", [''])
-        res = self.vty.command("show running-config")
-        self.assert_(res.find(" timeout-ping 12") > 0)
-        self.assert_(res.find(" timeout-pong 14") > 0)
-        self.assert_(res.find(" timeout-ping advanced") > 0)
-
-    def testMscDataCoreLACCI(self):
-        self.vty.enable()
-        res = self.vty.command("show running-config")
-        self.assertEquals(res.find("core-location-area-code"), -1)
-        self.assertEquals(res.find("core-cell-identity"), -1)
-
-        self.vty.command("configure terminal")
-        self.vty.command("msc 0")
-        self.vty.command("core-location-area-code 666")
-        self.vty.command("core-cell-identity 333")
-
-        res = self.vty.command("show running-config")
-        self.assert_(res.find("core-location-area-code 666") > 0)
-        self.assert_(res.find("core-cell-identity 333") > 0)
-
-class TestVTYNAT(TestVTYGenericBSC):
-
-    def vty_command(self):
-        return ["./src/osmo-bsc_nat/osmo-bsc_nat", "-l", "127.0.0.1", "-c",
-                "doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg"]
-
-    def vty_app(self):
-        return (4244, "src/osmo-bsc_nat/osmo-bsc_nat",  "OsmoBSCNAT", "nat")
-
-    def testBSCreload(self):
-        # Use different port for the mock msc to avoid clashing with
-        # the osmo-bsc_nat itself
-        ip = "127.0.0.1"
-        port = 5522
-        self.vty.enable()
-        bscs1 = self.vty.command("show bscs-config")
-        nat_bsc_reload(self)
-        bscs2 = self.vty.command("show bscs-config")
-        # check that multiple calls to bscs-config-file give the same result
-        self.assertEquals(bscs1, bscs2)
-
-        # add new bsc
-        self.vty.command("configure terminal")
-        self.vty.command("nat")
-        self.vty.command("bsc 5")
-        self.vty.command("token key")
-        self.vty.command("location_area_code 666")
-        self.vty.command("end")
-
-        # update bsc token
-        self.vty.command("configure terminal")
-        self.vty.command("nat")
-        self.vty.command("bsc 1")
-        self.vty.command("token xyu")
-        self.vty.command("end")
-
-        nat_msc_ip(self, ip, port)
-        msc_socket, msc = nat_msc_test(self, ip, port, verbose=True)
-        try:
-            b0 = nat_bsc_sock_test(0, "lol", verbose=True, proc=self.proc)
-            b1 = nat_bsc_sock_test(1, "xyu", verbose=True, proc=self.proc)
-            b2 = nat_bsc_sock_test(5, "key", verbose=True, proc=self.proc)
-
-            self.assertEquals("3 BSCs configured", self.vty.command("show nat num-bscs-configured"))
-            self.assertTrue(3 == nat_bsc_num_con(self))
-            self.assertEquals("MSC is connected: 1", self.vty.command("show msc connection"))
-
-            nat_bsc_reload(self)
-            bscs2 = self.vty.command("show bscs-config")
-            # check that the reset to initial config succeeded
-            self.assertEquals(bscs1, bscs2)
-
-            self.assertEquals("2 BSCs configured", self.vty.command("show nat num-bscs-configured"))
-            self.assertTrue(1 == nat_bsc_num_con(self))
-            rem = self.vty.command("show bsc connections").split(' ')
-            # remaining connection is for BSC0
-            self.assertEquals('0', rem[2])
-            # remaining connection is authorized
-            self.assertEquals('1', rem[4])
-            self.assertEquals("MSC is connected: 1", self.vty.command("show msc connection"))
-        finally:
-            msc.close()
-            msc_socket.close()
-
-    def testVtyTree(self):
-        self.vty.enable()
-        self.assertTrue(self.vty.verify('configure terminal', ['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify('mgcp', ['']))
-        self.assertEquals(self.vty.node(), 'config-mgcp')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify('exit', ['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.assertTrue(self.vty.verify('nat', ['']))
-        self.assertEquals(self.vty.node(), 'config-nat')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify('bsc 0', ['']))
-        self.assertEquals(self.vty.node(), 'config-nat-bsc')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify('exit', ['']))
-        self.assertEquals(self.vty.node(), 'config-nat')
-        self.assertTrue(self.vty.verify('exit', ['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.assertTrue(self.vty.verify('exit', ['']))
-        self.assertTrue(self.vty.node() is None)
-
-        # Check searching for outer node's commands
-        self.vty.command('configure terminal')
-        self.vty.command('mgcp')
-        self.vty.command('nat')
-        self.assertEquals(self.vty.node(), 'config-nat')
-        self.vty.command('mgcp')
-        self.assertEquals(self.vty.node(), 'config-mgcp')
-        self.vty.command('nat')
-        self.assertEquals(self.vty.node(), 'config-nat')
-        self.vty.command('bsc 0')
-        self.vty.command('mgcp')
-        self.assertEquals(self.vty.node(), 'config-mgcp')
-
-    def testRewriteNoRewrite(self):
-        self.vty.enable()
-        res = self.vty.command("configure terminal")
-        res = self.vty.command("nat")
-        res = self.vty.command("number-rewrite rewrite.cfg")
-        res = self.vty.command("no number-rewrite")
-
-    def testEnsureNoEnsureModeSet(self):
-        self.vty.enable()
-        res = self.vty.command("configure terminal")
-        res = self.vty.command("nat")
-
-        # Ensure the default
-        res = self.vty.command("show running-config")
-        self.assert_(res.find('\n sdp-ensure-amr-mode-set') > 0)
-
-        self.vty.command("sdp-ensure-amr-mode-set")
-        res = self.vty.command("show running-config")
-        self.assert_(res.find('\n sdp-ensure-amr-mode-set') > 0)
-
-        self.vty.command("no sdp-ensure-amr-mode-set")
-        res = self.vty.command("show running-config")
-        self.assert_(res.find('\n no sdp-ensure-amr-mode-set') > 0)
-
-    def testRewritePostNoRewrite(self):
-        self.vty.enable()
-        self.vty.command("configure terminal")
-        self.vty.command("nat")
-        self.vty.verify("number-rewrite-post rewrite.cfg", [''])
-        self.vty.verify("no number-rewrite-post", [''])
-
-
-    def testPrefixTreeLoading(self):
-        cfg = os.path.join(confpath, "tests/bsc-nat-trie/prefixes.csv")
-
-        self.vty.enable()
-        self.vty.command("configure terminal")
-        self.vty.command("nat")
-        res = self.vty.command("prefix-tree %s" % cfg)
-        self.assertEqual(res, "% prefix-tree loaded 17 rules.")
-        self.vty.command("end")
-
-        res = self.vty.command("show prefix-tree")
-        self.assertEqual(res, '1,1\r\n12,2\r\n123,3\r\n1234,4\r\n12345,5\r\n123456,6\r\n1234567,7\r\n12345678,8\r\n123456789,9\r\n1234567890,10\r\n13,11\r\n14,12\r\n15,13\r\n16,14\r\n82,16\r\n823455,15\r\n+49123,17')
-
-        self.vty.command("configure terminal")
-        self.vty.command("nat")
-        self.vty.command("no prefix-tree")
-        self.vty.command("end")
-
-        res = self.vty.command("show prefix-tree")
-        self.assertEqual(res, "% there is now prefix tree loaded.")
-
-    def testUssdSideChannelProvider(self):
-        self.vty.command("end")
-        self.vty.enable()
-        self.vty.command("configure terminal")
-        self.vty.command("nat")
-        self.vty.command("ussd-token key")
-        self.vty.command("end")
-
-        res = self.vty.verify("show ussd-connection", ['The USSD side channel provider is not connected and not authorized.'])
-        self.assertTrue(res)
-
-        ussdSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        ussdSocket.connect(('127.0.0.1', 5001))
-        ussdSocket.settimeout(2.0)
-        print "Connected to %s:%d" % ussdSocket.getpeername()
-
-        print "Expecting ID_GET request"
-        data = ussdSocket.recv(4)
-        self.assertEqual(data, "\x00\x01\xfe\x04")
-
-        print "Going to send ID_RESP response"
-        res = ussdSocket.send(IPA().id_resp(IPA().tag_name('key')))
-        self.assertEqual(res, 10)
-
-        # initiating PING/PONG cycle to know, that the ID_RESP message has been processed
-
-        print "Going to send PING request"
-        res = ussdSocket.send(IPA().ping())
-        self.assertEqual(res, 4)
-
-        print "Expecting PONG response"
-        data = ussdSocket.recv(4)
-        self.assertEqual(data, "\x00\x01\xfe\x01")
-
-        res = self.vty.verify("show ussd-connection", ['The USSD side channel provider is connected and authorized.'])
-        self.assertTrue(res)
-
-        print "Going to shut down connection"
-        ussdSocket.shutdown(socket.SHUT_WR)
-
-        print "Expecting EOF"
-        data = ussdSocket.recv(4)
-        self.assertEqual(data, "")
-
-        ussdSocket.close()
-
-        res = self.vty.verify("show ussd-connection", ['The USSD side channel provider is not connected and not authorized.'])
-        self.assertTrue(res)
-
-    def testAccessList(self):
-        """
-        Verify that the imsi-deny can have a reject cause or no reject cause
-        """
-        self.vty.enable()
-        self.vty.command("configure terminal")
-        self.vty.command("nat")
-
-        # Old default
-        self.vty.command("access-list test-default imsi-deny ^123[0-9]*$")
-        res = self.vty.command("show running-config").split("\r\n")
-        asserted = False
-        for line in res:
-           if line.startswith(" access-list test-default"):
-                self.assertEqual(line, " access-list test-default imsi-deny ^123[0-9]*$ 11 11")
-                asserted = True
-        self.assert_(asserted)
-
-        # Check the optional CM Service Reject Cause
-        self.vty.command("access-list test-cm-deny imsi-deny ^123[0-9]*$ 42").split("\r\n")
-        res = self.vty.command("show running-config").split("\r\n")
-        asserted = False
-        for line in res:
-           if line.startswith(" access-list test-cm"):
-                self.assertEqual(line, " access-list test-cm-deny imsi-deny ^123[0-9]*$ 42 11")
-                asserted = True
-        self.assert_(asserted)
-
-        # Check the optional LU Reject Cause
-        self.vty.command("access-list test-lu-deny imsi-deny ^123[0-9]*$ 23 42").split("\r\n")
-        res = self.vty.command("show running-config").split("\r\n")
-        asserted = False
-        for line in res:
-           if line.startswith(" access-list test-lu"):
-                self.assertEqual(line, " access-list test-lu-deny imsi-deny ^123[0-9]*$ 23 42")
-                asserted = True
-        self.assert_(asserted)
-
-class TestVTYGbproxy(TestVTYGenericBSC):
-
-    def vty_command(self):
-        return ["./src/gprs/osmo-gbproxy", "-c",
-                "doc/examples/osmo-gbproxy/osmo-gbproxy.cfg"]
-
-    def vty_app(self):
-        return (4246, "./src/gprs/osmo-gbproxy", "OsmoGbProxy", "bsc")
-
-    def testVtyTree(self):
-        self.vty.enable()
-        self.assertTrue(self.vty.verify('configure terminal', ['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify('ns', ['']))
-        self.assertEquals(self.vty.node(), 'config-ns')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify('exit', ['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.assertTrue(self.vty.verify('gbproxy', ['']))
-        self.assertEquals(self.vty.node(), 'config-gbproxy')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify('exit', ['']))
-        self.assertEquals(self.vty.node(), 'config')
-
-    def testVtyShow(self):
-        res = self.vty.command("show ns")
-        self.assert_(res.find('Encapsulation NS-UDP-IP') >= 0)
-
-        res = self.vty.command("show gbproxy stats")
-        self.assert_(res.find('GBProxy Global Statistics') >= 0)
-
-    def testVtyDeletePeer(self):
-        self.vty.enable()
-        self.assertTrue(self.vty.verify('delete-gbproxy-peer 9999 bvci 7777', ['BVC not found']))
-        res = self.vty.command("delete-gbproxy-peer 9999 all dry-run")
-        self.assert_(res.find('Not Deleted 0 BVC') >= 0)
-        self.assert_(res.find('Not Deleted 0 NS-VC') >= 0)
-        res = self.vty.command("delete-gbproxy-peer 9999 only-bvc dry-run")
-        self.assert_(res.find('Not Deleted 0 BVC') >= 0)
-        self.assert_(res.find('Not Deleted 0 NS-VC') < 0)
-        res = self.vty.command("delete-gbproxy-peer 9999 only-nsvc dry-run")
-        self.assert_(res.find('Not Deleted 0 BVC') < 0)
-        self.assert_(res.find('Not Deleted 0 NS-VC') >= 0)
-        res = self.vty.command("delete-gbproxy-peer 9999 all")
-        self.assert_(res.find('Deleted 0 BVC') >= 0)
-        self.assert_(res.find('Deleted 0 NS-VC') >= 0)
-
-class TestVTYSGSN(TestVTYGenericBSC):
-
-    def vty_command(self):
-        return ["./src/gprs/osmo-sgsn", "-c",
-                "doc/examples/osmo-sgsn/osmo-sgsn-accept-all.cfg"]
-
-    def vty_app(self):
-        return (4245, "./src/gprs/osmo-sgsn", "OsmoSGSN", "sgsn")
-
-    def testVtyTree(self):
-        self.vty.enable()
-        self.assertTrue(self.vty.verify('configure terminal', ['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify('ns', ['']))
-        self.assertEquals(self.vty.node(), 'config-ns')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify('exit', ['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.assertTrue(self.vty.verify('sgsn', ['']))
-        self.assertEquals(self.vty.node(), 'config-sgsn')
-        self.checkForEndAndExit()
-        self.assertTrue(self.vty.verify('exit', ['']))
-        self.assertEquals(self.vty.node(), 'config')
-
-    def testVtyShow(self):
-        res = self.vty.command("show ns")
-        self.assert_(res.find('Encapsulation NS-UDP-IP') >= 0)
-        self.assertTrue(self.vty.verify('show bssgp', ['']))
-        self.assertTrue(self.vty.verify('show bssgp stats', ['']))
-        # TODO: uncomment when the command does not segfault anymore
-        # self.assertTrue(self.vty.verify('show bssgp nsei 123', ['']))
-        # self.assertTrue(self.vty.verify('show bssgp nsei 123 stats', ['']))
-
-        self.assertTrue(self.vty.verify('show sgsn', ['']))
-        self.assertTrue(self.vty.verify('show mm-context all', ['']))
-        self.assertTrue(self.vty.verify('show mm-context imsi 000001234567', ['No MM context for IMSI 000001234567']))
-        self.assertTrue(self.vty.verify('show pdp-context all', ['']))
-
-        res = self.vty.command("show sndcp")
-        self.assert_(res.find('State of SNDCP Entities') >= 0)
-
-        res = self.vty.command("show llc")
-        self.assert_(res.find('State of LLC Entities') >= 0)
-
-    def testVtyAuth(self):
-        self.vty.enable()
-        self.assertTrue(self.vty.verify('configure terminal', ['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.assertTrue(self.vty.verify('sgsn', ['']))
-        self.assertEquals(self.vty.node(), 'config-sgsn')
-        self.assertTrue(self.vty.verify('auth-policy accept-all', ['']))
-        res = self.vty.command("show running-config")
-        self.assert_(res.find('auth-policy accept-all') > 0)
-        self.assertTrue(self.vty.verify('auth-policy acl-only', ['']))
-        res = self.vty.command("show running-config")
-        self.assert_(res.find('auth-policy acl-only') > 0)
-        self.assertTrue(self.vty.verify('auth-policy closed', ['']))
-        res = self.vty.command("show running-config")
-        self.assert_(res.find('auth-policy closed') > 0)
-        self.assertTrue(self.vty.verify('gsup remote-ip 127.0.0.4', ['']))
-        self.assertTrue(self.vty.verify('gsup remote-port 2222', ['']))
-        self.assertTrue(self.vty.verify('auth-policy remote', ['']))
-        res = self.vty.command("show running-config")
-        self.assert_(res.find('auth-policy remote') > 0)
-
-    def testVtySubscriber(self):
-        self.vty.enable()
-        res = self.vty.command('show subscriber cache')
-        self.assert_(res.find('1234567890') < 0)
-        self.assertTrue(self.vty.verify('update-subscriber imsi 1234567890 create', ['']))
-        res = self.vty.command('show subscriber cache')
-        self.assert_(res.find('1234567890') >= 0)
-        self.assert_(res.find('Authorized: 0') >= 0)
-        self.assertTrue(self.vty.verify('update-subscriber imsi 1234567890 update-location-result ok', ['']))
-        res = self.vty.command('show subscriber cache')
-        self.assert_(res.find('1234567890') >= 0)
-        self.assert_(res.find('Authorized: 1') >= 0)
-        self.assertTrue(self.vty.verify('update-subscriber imsi 1234567890 cancel update-procedure', ['']))
-        res = self.vty.command('show subscriber cache')
-        self.assert_(res.find('1234567890') >= 0)
-        self.assertTrue(self.vty.verify('update-subscriber imsi 1234567890 destroy', ['']))
-        res = self.vty.command('show subscriber cache')
-        self.assert_(res.find('1234567890') < 0)
-
-    def testVtyGgsn(self):
-        self.vty.enable()
-        self.assertTrue(self.vty.verify('configure terminal', ['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.assertTrue(self.vty.verify('sgsn', ['']))
-        self.assertEquals(self.vty.node(), 'config-sgsn')
-        self.assertTrue(self.vty.verify('ggsn 0 remote-ip 127.99.99.99', ['']))
-        self.assertTrue(self.vty.verify('ggsn 0 gtp-version 1', ['']))
-        self.assertTrue(self.vty.verify('apn * ggsn 0', ['']))
-        self.assertTrue(self.vty.verify('apn apn1.test ggsn 0', ['']))
-        self.assertTrue(self.vty.verify('apn apn1.test ggsn 1', ['% a GGSN with id 1 has not been defined']))
-        self.assertTrue(self.vty.verify('apn apn1.test imsi-prefix 123456 ggsn 0', ['']))
-        self.assertTrue(self.vty.verify('apn apn2.test imsi-prefix 123456 ggsn 0', ['']))
-        res = self.vty.command("show running-config")
-        self.assert_(res.find('ggsn 0 remote-ip 127.99.99.99') >= 0)
-        self.assert_(res.find('ggsn 0 gtp-version 1') >= 0)
-        self.assert_(res.find('apn * ggsn 0') >= 0)
-        self.assert_(res.find('apn apn1.test ggsn 0') >= 0)
-        self.assert_(res.find('apn apn1.test imsi-prefix 123456 ggsn 0') >= 0)
-        self.assert_(res.find('apn apn2.test imsi-prefix 123456 ggsn 0') >= 0)
-
-    def testVtyEasyAPN(self):
-        self.vty.enable()
-        self.assertTrue(self.vty.verify('configure terminal', ['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.assertTrue(self.vty.verify('sgsn', ['']))
-        self.assertEquals(self.vty.node(), 'config-sgsn')
-
-        res = self.vty.command("show running-config")
-        self.assertEquals(res.find("apn internet"), -1)
-
-        self.assertTrue(self.vty.verify("access-point-name internet.apn", ['']))
-        res = self.vty.command("show running-config")
-        self.assert_(res.find("apn internet.apn ggsn 0") >= 0)
-
-        self.assertTrue(self.vty.verify("no access-point-name internet.apn", ['']))
-        res = self.vty.command("show running-config")
-        self.assertEquals(res.find("apn internet"), -1)
-
-    def testVtyCDR(self):
-        self.vty.enable()
-        self.assertTrue(self.vty.verify('configure terminal', ['']))
-        self.assertEquals(self.vty.node(), 'config')
-        self.assertTrue(self.vty.verify('sgsn', ['']))
-        self.assertEquals(self.vty.node(), 'config-sgsn')
-
-        res = self.vty.command("show running-config")
-        self.assert_(res.find("no cdr filename") > 0)
-
-        self.vty.command("cdr filename bla.cdr")
-        res = self.vty.command("show running-config")
-        self.assertEquals(res.find("no cdr filename"), -1)
-        self.assert_(res.find(" cdr filename bla.cdr") > 0)
-
-        self.vty.command("no cdr filename")
-        res = self.vty.command("show running-config")
-        self.assert_(res.find("no cdr filename") > 0)
-        self.assertEquals(res.find(" cdr filename bla.cdr"), -1)
-
-        res = self.vty.command("show running-config")
-        self.assert_(res.find(" cdr interval 600") > 0)
-
-        self.vty.command("cdr interval 900")
-        res = self.vty.command("show running-config")
-        self.assert_(res.find(" cdr interval 900") > 0)
-        self.assertEquals(res.find(" cdr interval 600"), -1)
-
-def add_nat_test(suite, workdir):
-    if not os.path.isfile(os.path.join(workdir, "src/osmo-bsc_nat/osmo-bsc_nat")):
-        print("Skipping the NAT test")
-        return
-    test = unittest.TestLoader().loadTestsFromTestCase(TestVTYNAT)
-    suite.addTest(test)
-
-def nat_bsc_reload(x):
-    x.vty.command("configure terminal")
-    x.vty.command("nat")
-    x.vty.command("bscs-config-file bscs.cfg")
-    x.vty.command("end")
-
-def nat_msc_ip(x, ip, port):
-    x.vty.command("configure terminal")
-    x.vty.command("nat")
-    x.vty.command("msc ip " + ip)
-    x.vty.command("msc port " + str(port))
-    x.vty.command("end")
-
-def data2str(d):
-    return d.encode('hex').lower()
-
-def nat_msc_test(x, ip, port, verbose = False):
-    msc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-    msc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-    msc.settimeout(5)
-    msc.bind((ip, port))
-    msc.listen(5)
-    if (verbose):
-        print "MSC is ready at " + ip
-    conn = None
-    while True:
-        vty_response = x.vty.command("show msc connection")
-        print "'show msc connection' says: %r" % vty_response
-        if vty_response == "MSC is connected: 1":
-            # success
-            break;
-        if vty_response != "MSC is connected: 0":
-            raise Exception("Unexpected response to 'show msc connection'"
-                            " vty command: %r" % vty_response)
-
-        timeout_retries = 6
-        while timeout_retries > 0:
-            try:
-                conn, addr = msc.accept()
-                print "MSC got connection from ", addr
-                break
-            except socket.timeout:
-                print "socket timed out."
-                timeout_retries -= 1
-                continue
-
-    if not conn:
-        raise Exception("VTY reports MSC is connected, but I haven't"
-                        " connected yet: %r %r" % (ip, port))
-    return msc, conn
-
-def ipa_handle_small(x, verbose = False):
-    s = data2str(x.recv(4))
-    if len(s) != 4*2:
-      raise Exception("expected to receive 4 bytes, but got %d (%r)" % (len(s)/2, s))
-    if "0001fe00" == s:
-        if (verbose):
-            print "\tBSC <- NAT: PING?"
-        x.send(IPA().pong())
-    elif "0001fe06" == s:
-        if (verbose):
-            print "\tBSC <- NAT: IPA ID ACK"
-        x.send(IPA().id_ack())
-    elif "0001fe00" == s:
-        if (verbose):
-            print "\tBSC <- NAT: PONG!"
-    else:
-        if (verbose):
-            print "\tBSC <- NAT: ", s
-
-def ipa_handle_resp(x, tk, verbose = False, proc=None):
-    s = data2str(x.recv(38))
-    if "0023fe040108010701020103010401050101010011" in s:
-        retries = 3
-        while True:
-            print "\tsending IPA identity(%s) at %s" % (tk, time.strftime("%T"))
-            try:
-                x.send(IPA().id_resp(IPA().identity(name = tk.encode('utf-8'))))
-                print "\tdone sending IPA identity(%s) at %s" % (tk,
-                                                            time.strftime("%T"))
-                break
-            except:
-                print "\tfailed sending IPA identity at", time.strftime("%T")
-                if proc:
-                  print "\tproc.poll() = %r" % proc.poll()
-                if retries < 1:
-                    print "\tgiving up"
-                    raise
-                print "\tretrying (%d attempts left)" % retries
-                retries -= 1
-    else:
-        if (verbose):
-            print "\tBSC <- NAT: ", s
-
-def nat_bsc_num_con(x):
-    return len(x.vty.command("show bsc connections").split('\n'))
-
-def nat_bsc_sock_test(nr, tk, verbose = False, proc=None):
-    bsc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-    bsc.bind(('127.0.0.1', 0))
-    bsc.connect(('127.0.0.1', 5000))
-    if (verbose):
-        print "BSC%d " %nr
-        print "\tconnected to %s:%d" % bsc.getpeername()
-    if proc:
-      print "\tproc.poll() = %r" % proc.poll()
-      print "\tproc.pid = %r" % proc.pid
-    ipa_handle_small(bsc, verbose)
-    ipa_handle_resp(bsc, tk, verbose, proc=proc)
-    if proc:
-      print "\tproc.poll() = %r" % proc.poll()
-    bsc.recv(27) # MGCP msg
-    if proc:
-      print "\tproc.poll() = %r" % proc.poll()
-    ipa_handle_small(bsc, verbose)
-    return bsc
-
-def add_bsc_test(suite, workdir):
-    if not os.path.isfile(os.path.join(workdir, "src/osmo-bsc/osmo-bsc")):
-        print("Skipping the BSC test")
-        return
-    test = unittest.TestLoader().loadTestsFromTestCase(TestVTYBSC)
-    suite.addTest(test)
-
-def add_gbproxy_test(suite, workdir):
-    if not os.path.isfile(os.path.join(workdir, "src/gprs/osmo-gbproxy")):
-        print("Skipping the Gb-Proxy test")
-        return
-    test = unittest.TestLoader().loadTestsFromTestCase(TestVTYGbproxy)
-    suite.addTest(test)
-
-def add_sgsn_test(suite, workdir):
-    if not os.path.isfile(os.path.join(workdir, "src/gprs/osmo-sgsn")):
-        print("Skipping the SGSN test")
-        return
-    test = unittest.TestLoader().loadTestsFromTestCase(TestVTYSGSN)
-    suite.addTest(test)
-
 if __name__ == '__main__':
     import argparse
     import sys
@@ -1153,11 +161,6 @@
     print "Running tests for specific VTY commands"
     suite = unittest.TestSuite()
     suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestVTYMGCP))
-    suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestVTYMSC))
-    add_bsc_test(suite, workdir)
-    add_nat_test(suite, workdir)
-    add_gbproxy_test(suite, workdir)
-    add_sgsn_test(suite, workdir)
 
     if args.test_name:
         osmoutil.pick_tests(suite, *args.test_name)
diff --git a/tests/xid/Makefile.am b/tests/xid/Makefile.am
deleted file mode 100644
index aaf17ed..0000000
--- a/tests/xid/Makefile.am
+++ /dev/null
@@ -1,39 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	-ggdb3 \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBCARES_CFLAGS) \
-	$(NULL)
-
-EXTRA_DIST = \
-	xid_test.ok \
-	$(NULL)
-
-noinst_PROGRAMS = \
-	xid_test \
-	$(NULL)
-
-xid_test_SOURCES = \
-	xid_test.c \
-	$(NULL)
-
-xid_test_LDADD = \
-	$(top_builddir)/src/gprs/gprs_llc_xid.o \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(LIBOSMOABIS_LIBS) \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOGB_LIBS) \
-	$(LIBCARES_LIBS) \
-	$(LIBCRYPTO_LIBS) \
-	$(LIBGTP_LIBS) \
-	-lrt \
-	-lm \
-	$(NULL)
-
diff --git a/tests/xid/xid_test.c b/tests/xid/xid_test.c
deleted file mode 100644
index b77a4ae..0000000
--- a/tests/xid/xid_test.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/* Test LLC-XID Encoding/Decoding */
-
-/* (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/>.
- */
-
-#include <openbsc/gprs_llc_xid.h>
-#include <openbsc/debug.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/utils.h>
-
-#include <osmocom/core/application.h>
-
-#include <stdio.h>
-#include <string.h>
-
-/* Test XID encoding */
-static void test_xid_encode(const void *ctx)
-{
-	struct gprs_llc_xid_field xid_field_1;
-	struct gprs_llc_xid_field xid_field_2;
-	struct gprs_llc_xid_field xid_field_3;
-	struct gprs_llc_xid_field xid_field_4;
-	LLIST_HEAD(xid_fields);
-	uint8_t xid[255];
-	uint8_t xid_expected[] =
-	    { 0x10, 0x8c, 0x14, 0x43, 0x43, 0x43, 0x43, 0x43, 0x0b, 0x42, 0x42,
-	0x42, 0x05, 0x41 };
-	int rc;
-
-	printf("Testing LLC XID-Encoder\n");
-
-	/* Setup some simple XID data */
-	xid_field_1.type = 1;
-	xid_field_2.type = 2;
-	xid_field_3.type = 3;
-	xid_field_4.type = 4;
-
-	xid_field_1.data = (uint8_t *) "A";
-	xid_field_2.data = (uint8_t *) "BBB";
-	xid_field_3.data = (uint8_t *) "CCCCC";
-	xid_field_4.data = NULL;
-
-	xid_field_1.data_len = 1;
-	xid_field_2.data_len = 3;
-	xid_field_3.data_len = 5;
-	xid_field_4.data_len = 0;
-
-	llist_add(&xid_field_4.list, &xid_fields);
-	llist_add(&xid_field_3.list, &xid_fields);
-	llist_add(&xid_field_2.list, &xid_fields);
-	llist_add(&xid_field_1.list, &xid_fields);
-
-	printf("Data to encode:\n");
-	gprs_llc_dump_xid_fields(&xid_fields, DSNDCP);
-
-	/* Encode data */
-	rc = gprs_llc_compile_xid(xid, sizeof(xid), &xid_fields);
-	OSMO_ASSERT(rc == 14);
-	printf("Encoded:  %s (%i bytes)\n", osmo_hexdump_nospc(xid, rc), rc);
-	printf("Expected: %s (%i bytes)\n",
-	       osmo_hexdump_nospc(xid_expected, sizeof(xid_expected)),
-	       (int)sizeof(xid_expected));
-
-	OSMO_ASSERT(memcmp(xid_expected, xid, sizeof(xid_expected)) == 0);
-
-	printf("\n");
-}
-
-/* Test XID decoding */
-static void test_xid_decode(const void *ctx)
-{
-	struct llist_head *xid_fields;
-	int rc;
-
-	printf("Testing LLC XID-Decoder/Encoder\n");
-
-	/* Example of a real world LLC-XID message */
-	uint8_t xid[] =
-	    { 0x01, 0x00, 0x16, 0x05, 0xf0, 0x1a, 0x05, 0xf0, 0xac, 0xd8, 0x00,
-	0x01, 0x00, 0x02, 0x31, 0x82, 0x02, 0x27, 0x89, 0xff, 0xe0, 0x00, 0x0f,
-	0x00, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x01, 0x02,
-	0x00, 0x03, 0x01, 0x03, 0x00, 0x04, 0x01, 0x04, 0x00, 0x05, 0x01, 0x05,
-	0x00, 0x06, 0x00, 0x07, 0x01, 0x07, 0x00, 0x08, 0x01, 0x08, 0x80, 0x00,
-	0x04, 0x12, 0x00, 0x40, 0x07 };
-
-	uint8_t xid_r[512];
-
-	/* Decode and display XID fields */
-	xid_fields = gprs_llc_parse_xid(ctx, xid, sizeof(xid));
-	OSMO_ASSERT(xid_fields);
-
-	printf("Decoded:\n");
-	gprs_llc_dump_xid_fields(xid_fields, DSNDCP);
-
-
-	/* Encode xid-fields again */
-	rc = gprs_llc_compile_xid(xid_r, sizeof(xid_r), xid_fields);
-	printf("Result length=%i\n",rc);
-	printf("Encoded:  %s\n", osmo_hexdump_nospc(xid, sizeof(xid)));
-	printf("Rencoded: %s\n", osmo_hexdump_nospc(xid_r, rc));
-
-	OSMO_ASSERT(rc == 64);
-	OSMO_ASSERT(memcmp(xid, xid_r, sizeof(xid)) == 0);
-
-	/* Free xid fields */
-	talloc_free(xid_fields);
-
-	printf("\n");
-}
-
-static struct log_info_cat gprs_categories[] = {
-	[DSNDCP] = {
-		    .name = "DSNDCP",
-		    .description =
-		    "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
-		    .enabled = 1,.loglevel = LOGL_DEBUG,
-		    }
-};
-
-static struct log_info info = {
-	.cat = gprs_categories,
-	.num_cat = ARRAY_SIZE(gprs_categories),
-};
-
-int main(int argc, char **argv)
-{
-	void *xid_ctx;
-
-	osmo_init_logging(&info);
-
-	xid_ctx = talloc_named_const(NULL, 0, "xid_ctx");
-
-	test_xid_decode(xid_ctx);
-	test_xid_encode(xid_ctx);
-	printf("Done\n");
-
-	talloc_report_full(xid_ctx, stderr);
-	OSMO_ASSERT(talloc_total_blocks(xid_ctx) == 1);
-	return 0;
-}
-
-/* stubs */
-struct osmo_prim_hdr;
-int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
-{
-        abort();
-}
diff --git a/tests/xid/xid_test.ok b/tests/xid/xid_test.ok
deleted file mode 100644
index 4cf825c..0000000
--- a/tests/xid/xid_test.ok
+++ /dev/null
@@ -1,12 +0,0 @@
-Testing LLC XID-Decoder/Encoder
-Decoded:
-Result length=64
-Encoded:  01001605f01a05f0acd8000100023182022789ffe0000f00a8000000010101000201020003010300040104000501050006000701070008010880000412004007
-Rencoded: 01001605f01a05f0acd8000100023182022789ffe0000f00a8000000010101000201020003010300040104000501050006000701070008010880000412004007
-
-Testing LLC XID-Encoder
-Data to encode:
-Encoded:  108c1443434343430b4242420541 (14 bytes)
-Expected: 108c1443434343430b4242420541 (14 bytes)
-
-Done