New upstream version 0.9.14
diff --git a/.tarball-version b/.tarball-version
index 62ea259..6d44d22 100644
--- a/.tarball-version
+++ b/.tarball-version
@@ -1 +1 @@
-0.9.13
+0.9.14
diff --git a/Makefile.am b/Makefile.am
index c4d0aa1..b966e69 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,12 +1,13 @@
 AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
 
 INCLUDES = $(all_includes) -I$(top_srcdir)/include
-SUBDIRS = include src tests
+SUBDIRS = doc include src tests
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = openbsc.pc
 
 BUILT_SOURCES = $(top_srcdir)/.version
+EXTRA_DIST = git-version-gen
 $(top_srcdir)/.version:
 	echo $(VERSION) > $@-t && mv $@-t $@
 dist-hook:
diff --git a/Makefile.in b/Makefile.in
index 86bce3e..4a31572 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -38,7 +38,7 @@
 	$(srcdir)/openbsc.pc.in $(top_srcdir)/configure AUTHORS \
 	COPYING depcomp install-sh missing
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
@@ -162,6 +162,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -232,10 +234,11 @@
 top_srcdir = @top_srcdir@
 AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
 INCLUDES = $(all_includes) -I$(top_srcdir)/include
-SUBDIRS = include src tests
+SUBDIRS = doc include src tests
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = openbsc.pc
 BUILT_SOURCES = $(top_srcdir)/.version
+EXTRA_DIST = git-version-gen
 all: $(BUILT_SOURCES) bscconfig.h
 	$(MAKE) $(AM_MAKEFLAGS) all-recursive
 
diff --git a/aclocal.m4 b/aclocal.m4
index f239233..cb931b8 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -13,8 +13,8 @@
 
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
-m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.67],,
-[m4_warning([this file was generated for autoconf 2.67.
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],,
+[m4_warning([this file was generated for autoconf 2.68.
 You have another version of autoconf.  It may work, but is not guaranteed to.
 If you have problems, you may need to regenerate the build system entirely.
 To do so, use the procedure documented by the package, typically `autoreconf'.])])
@@ -47,7 +47,8 @@
 # ----------------------------------
 AC_DEFUN([PKG_PROG_PKG_CONFIG],
 [m4_pattern_forbid([^_?PKG_[A-Z_]+$])
-m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
 AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
 AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
 AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
@@ -93,7 +94,8 @@
     pkg_cv_[]$1="$$1"
  elif test -n "$PKG_CONFIG"; then
     PKG_CHECK_EXISTS([$3],
-                     [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+                     [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes ],
 		     [pkg_failed=yes])
  else
     pkg_failed=untried
@@ -141,9 +143,9 @@
    	AC_MSG_RESULT([no])
         _PKG_SHORT_ERRORS_SUPPORTED
         if test $_pkg_short_errors_supported = yes; then
-	        $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1`
+	        $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
         else 
-	        $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1`
+	        $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
diff --git a/bscconfig.h.in b/bscconfig.h.in
index fc5dfde..4cc89a1 100644
--- a/bscconfig.h.in
+++ b/bscconfig.h.in
@@ -1,8 +1,11 @@
-/* bscconfig.h.in.  Generated from configure.in by autoheader.  */
+/* bscconfig.h.in.  Generated from configure.ac by autoheader.  */
 
 /* Define to 1 if you have the <dahdi/user.h> header file. */
 #undef HAVE_DAHDI_USER_H
 
+/* Define to 1 if you have the <dbi/dbd.h> header file. */
+#undef HAVE_DBI_DBD_H
+
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
diff --git a/configure b/configure
index 86e47ae..1e7e628 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.67 for openbsc 0.9.13.
+# Generated by GNU Autoconf 2.68 for openbsc 0.9.14.
 #
 # Report bugs to <openbsc-devel@lists.openbsc.org>.
 #
@@ -91,6 +91,7 @@
 IFS=" ""	$as_nl"
 
 # Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
 case $0 in #((
   *[\\/]* ) as_myself=$0 ;;
   *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -216,11 +217,18 @@
   # We cannot yet assume a decent shell, so we have to provide a
 	# neutralization value for shells without unset; and this also
 	# works around shells that cannot unset nonexistent variables.
+	# Preserve -v and -x to the replacement shell.
 	BASH_ENV=/dev/null
 	ENV=/dev/null
 	(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
 	export CONFIG_SHELL
-	exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+	case $- in # ((((
+	  *v*x* | *x*v* ) as_opts=-vx ;;
+	  *v* ) as_opts=-v ;;
+	  *x* ) as_opts=-x ;;
+	  * ) as_opts= ;;
+	esac
+	exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
 fi
 
     if test x$as_have_required = xno; then :
@@ -552,8 +560,8 @@
 # Identity of this package.
 PACKAGE_NAME='openbsc'
 PACKAGE_TARNAME='openbsc'
-PACKAGE_VERSION='0.9.13'
-PACKAGE_STRING='openbsc 0.9.13'
+PACKAGE_VERSION='0.9.14'
+PACKAGE_STRING='openbsc 0.9.14'
 PACKAGE_BUGREPORT='openbsc-devel@lists.openbsc.org'
 PACKAGE_URL=''
 
@@ -603,6 +611,8 @@
 EGREP
 GREP
 CPP
+LIBOSMOGSM_LIBS
+LIBOSMOGSM_CFLAGS
 LIBOSMOVTY_LIBS
 LIBOSMOVTY_CFLAGS
 LIBOSMOCORE_LIBS
@@ -725,6 +735,8 @@
 LIBOSMOCORE_LIBS
 LIBOSMOVTY_CFLAGS
 LIBOSMOVTY_LIBS
+LIBOSMOGSM_CFLAGS
+LIBOSMOGSM_LIBS
 CPP'
 
 
@@ -1130,7 +1142,7 @@
     $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
     expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
       $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
-    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
     ;;
 
   esac
@@ -1268,7 +1280,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures openbsc 0.9.13 to adapt to many kinds of systems.
+\`configure' configures openbsc 0.9.14 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1334,7 +1346,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of openbsc 0.9.13:";;
+     short | recursive ) echo "Configuration of openbsc 0.9.14:";;
    esac
   cat <<\_ACEOF
 
@@ -1375,6 +1387,10 @@
               C compiler flags for LIBOSMOVTY, overriding pkg-config
   LIBOSMOVTY_LIBS
               linker flags for LIBOSMOVTY, overriding pkg-config
+  LIBOSMOGSM_CFLAGS
+              C compiler flags for LIBOSMOGSM, overriding pkg-config
+  LIBOSMOGSM_LIBS
+              linker flags for LIBOSMOGSM, overriding pkg-config
   CPP         C preprocessor
 
 Use these variables to override the choices made by `configure' or to help
@@ -1443,8 +1459,8 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-openbsc configure 0.9.13
-generated by GNU Autoconf 2.67
+openbsc configure 0.9.14
+generated by GNU Autoconf 2.68
 
 Copyright (C) 2010 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
@@ -1490,7 +1506,7 @@
 
 	ac_retval=1
 fi
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_c_try_compile
@@ -1536,7 +1552,7 @@
   # interfere with the next link command; also delete a directory that is
   # left behind by Apple's compiler.  We do this before executing the actions.
   rm -rf conftest.dSYM conftest_ipa8_conftest.oo
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_c_try_link
@@ -1573,7 +1589,7 @@
 
     ac_retval=1
 fi
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_c_try_cpp
@@ -1615,7 +1631,7 @@
        ac_retval=$ac_status
 fi
   rm -rf conftest.dSYM conftest_ipa8_conftest.oo
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
   as_fn_set_status $ac_retval
 
 } # ac_fn_c_try_run
@@ -1628,10 +1644,10 @@
 ac_fn_c_check_header_mongrel ()
 {
   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  if eval "test \"\${$3+set}\"" = set; then :
+  if eval \${$3+:} false; then :
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
 $as_echo_n "checking for $2... " >&6; }
-if eval "test \"\${$3+set}\"" = set; then :
+if eval \${$3+:} false; then :
   $as_echo_n "(cached) " >&6
 fi
 eval ac_res=\$$3
@@ -1698,7 +1714,7 @@
 esac
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
 $as_echo_n "checking for $2... " >&6; }
-if eval "test \"\${$3+set}\"" = set; then :
+if eval \${$3+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   eval "$3=\$ac_header_compiler"
@@ -1707,7 +1723,7 @@
 	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
 $as_echo "$ac_res" >&6; }
 fi
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
 
 } # ac_fn_c_check_header_mongrel
 
@@ -1720,7 +1736,7 @@
   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
 $as_echo_n "checking for $2... " >&6; }
-if eval "test \"\${$3+set}\"" = set; then :
+if eval \${$3+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -1738,15 +1754,15 @@
 eval ac_res=\$$3
 	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
 $as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
 
 } # ac_fn_c_check_header_compile
 cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by openbsc $as_me 0.9.13, which was
-generated by GNU Autoconf 2.67.  Invocation command line was
+It was created by openbsc $as_me 0.9.14, which was
+generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
 
@@ -2004,7 +2020,7 @@
       || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "failed to load site script $ac_site_file
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
   fi
 done
 
@@ -2142,7 +2158,7 @@
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
 $as_echo_n "checking for a BSD-compatible install... " >&6; }
 if test -z "$INSTALL"; then
-if test "${ac_cv_path_install+set}" = set; then :
+if ${ac_cv_path_install+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -2229,11 +2245,11 @@
 '
 case `pwd` in
   *[\\\"\#\$\&\'\`$am_lf]*)
-    as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5 ;;
+    as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
 esac
 case $srcdir in
   *[\\\"\#\$\&\'\`$am_lf\ \	]*)
-    as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5 ;;
+    as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;;
 esac
 
 # Do `set' in a subshell so we don't clobber the current shell's
@@ -2319,7 +2335,7 @@
 set dummy ${ac_tool_prefix}strip; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_STRIP+set}" = set; then :
+if ${ac_cv_prog_STRIP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$STRIP"; then
@@ -2359,7 +2375,7 @@
 set dummy strip; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then :
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_STRIP"; then
@@ -2412,7 +2428,7 @@
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
 if test -z "$MKDIR_P"; then
-  if test "${ac_cv_path_mkdir+set}" = set; then :
+  if ${ac_cv_path_mkdir+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -2463,7 +2479,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_AWK+set}" = set; then :
+if ${ac_cv_prog_AWK+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$AWK"; then
@@ -2503,7 +2519,7 @@
 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
 set x ${MAKE-make}
 ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
-if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\"" = set; then :
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat >conftest.make <<\_ACEOF
@@ -2561,7 +2577,7 @@
 
 # Define the identity of the package.
  PACKAGE='openbsc'
- VERSION='0.9.13'
+ VERSION='0.9.14'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -2619,7 +2635,7 @@
 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
 set x ${MAKE-make}
 ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
-if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\"" = set; then :
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat >conftest.make <<\_ACEOF
@@ -2656,7 +2672,7 @@
 set dummy ${ac_tool_prefix}gcc; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then :
+if ${ac_cv_prog_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
@@ -2696,7 +2712,7 @@
 set dummy gcc; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_CC"; then
@@ -2749,7 +2765,7 @@
 set dummy ${ac_tool_prefix}cc; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then :
+if ${ac_cv_prog_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
@@ -2789,7 +2805,7 @@
 set dummy cc; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then :
+if ${ac_cv_prog_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
@@ -2848,7 +2864,7 @@
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_CC+set}" = set; then :
+if ${ac_cv_prog_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$CC"; then
@@ -2892,7 +2908,7 @@
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_CC"; then
@@ -2947,7 +2963,7 @@
 test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "no acceptable C compiler found in \$PATH
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 
 # Provide some information about the compiler.
 $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
@@ -3062,7 +3078,7 @@
 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error 77 "C compiler cannot create executables
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
@@ -3105,7 +3121,7 @@
   { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 fi
 rm -f conftest conftest$ac_cv_exeext
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
@@ -3164,7 +3180,7 @@
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "cannot run C compiled programs.
 If you meant to cross compile, use \`--host'.
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
     fi
   fi
 fi
@@ -3175,7 +3191,7 @@
 ac_clean_files=$ac_clean_files_save
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
 $as_echo_n "checking for suffix of object files... " >&6; }
-if test "${ac_cv_objext+set}" = set; then :
+if ${ac_cv_objext+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -3216,7 +3232,7 @@
 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "cannot compute suffix of object files: cannot compile
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 fi
 rm -f conftest.$ac_cv_objext conftest.$ac_ext
 fi
@@ -3226,7 +3242,7 @@
 ac_objext=$OBJEXT
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+if ${ac_cv_c_compiler_gnu+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -3263,7 +3279,7 @@
 ac_save_CFLAGS=$CFLAGS
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
 $as_echo_n "checking whether $CC accepts -g... " >&6; }
-if test "${ac_cv_prog_cc_g+set}" = set; then :
+if ${ac_cv_prog_cc_g+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_save_c_werror_flag=$ac_c_werror_flag
@@ -3341,7 +3357,7 @@
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if test "${ac_cv_prog_cc_c89+set}" = set; then :
+if ${ac_cv_prog_cc_c89+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_cv_prog_cc_c89=no
@@ -3502,7 +3518,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
 $as_echo_n "checking dependency style of $depcc... " >&6; }
-if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then :
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
@@ -3631,7 +3647,7 @@
 set dummy ${ac_tool_prefix}ranlib; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_RANLIB+set}" = set; then :
+if ${ac_cv_prog_RANLIB+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$RANLIB"; then
@@ -3671,7 +3687,7 @@
 set dummy ranlib; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -n "$ac_ct_RANLIB"; then
@@ -3722,7 +3738,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing crypt" >&5
 $as_echo_n "checking for library containing crypt... " >&6; }
-if test "${ac_cv_search_crypt+set}" = set; then :
+if ${ac_cv_search_crypt+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_func_search_save_LIBS=$LIBS
@@ -3756,11 +3772,11 @@
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext
-  if test "${ac_cv_search_crypt+set}" = set; then :
+  if ${ac_cv_search_crypt+:} false; then :
   break
 fi
 done
-if test "${ac_cv_search_crypt+set}" = set; then :
+if ${ac_cv_search_crypt+:} false; then :
 
 else
   ac_cv_search_crypt=no
@@ -3780,7 +3796,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gtp_new" >&5
 $as_echo_n "checking for library containing gtp_new... " >&6; }
-if test "${ac_cv_search_gtp_new+set}" = set; then :
+if ${ac_cv_search_gtp_new+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_func_search_save_LIBS=$LIBS
@@ -3814,11 +3830,11 @@
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext
-  if test "${ac_cv_search_gtp_new+set}" = set; then :
+  if ${ac_cv_search_gtp_new+:} false; then :
   break
 fi
 done
-if test "${ac_cv_search_gtp_new+set}" = set; then :
+if ${ac_cv_search_gtp_new+:} false; then :
 
 else
   ac_cv_search_gtp_new=no
@@ -3852,13 +3868,14 @@
 
 
 
+
 if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
 	if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
 set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_PKG_CONFIG+set}" = set; then :
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $PKG_CONFIG in
@@ -3901,7 +3918,7 @@
 set dummy pkg-config; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then :
+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   case $ac_pt_PKG_CONFIG in
@@ -3983,6 +4000,7 @@
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_LIBOSMOSCCP_CFLAGS=`$PKG_CONFIG --cflags "libosmo-sccp >= 0.0.2" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
@@ -3999,6 +4017,7 @@
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_LIBOSMOSCCP_LIBS=`$PKG_CONFIG --libs "libosmo-sccp >= 0.0.2" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
@@ -4018,9 +4037,9 @@
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-	        LIBOSMOSCCP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libosmo-sccp >= 0.0.2" 2>&1`
+	        LIBOSMOSCCP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libosmo-sccp >= 0.0.2" 2>&1`
         else
-	        LIBOSMOSCCP_PKG_ERRORS=`$PKG_CONFIG --print-errors "libosmo-sccp >= 0.0.2" 2>&1`
+	        LIBOSMOSCCP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libosmo-sccp >= 0.0.2" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$LIBOSMOSCCP_PKG_ERRORS" >&5
@@ -4049,7 +4068,7 @@
 See the pkg-config man page for more details.
 
 To get pkg-config, see <http://pkg-config.freedesktop.org/>.
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 else
 	LIBOSMOSCCP_CFLAGS=$pkg_cv_LIBOSMOSCCP_CFLAGS
 	LIBOSMOSCCP_LIBS=$pkg_cv_LIBOSMOSCCP_LIBS
@@ -4092,6 +4111,7 @@
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_LIBOSMOSCCP_CFLAGS=`$PKG_CONFIG --cflags "libosmo-sccp >= 0.0.2" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
@@ -4108,6 +4128,7 @@
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
   pkg_cv_LIBOSMOSCCP_LIBS=`$PKG_CONFIG --libs "libosmo-sccp >= 0.0.2" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
@@ -4127,9 +4148,9 @@
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-	        LIBOSMOSCCP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libosmo-sccp >= 0.0.2" 2>&1`
+	        LIBOSMOSCCP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libosmo-sccp >= 0.0.2" 2>&1`
         else
-	        LIBOSMOSCCP_PKG_ERRORS=`$PKG_CONFIG --print-errors "libosmo-sccp >= 0.0.2" 2>&1`
+	        LIBOSMOSCCP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libosmo-sccp >= 0.0.2" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$LIBOSMOSCCP_PKG_ERRORS" >&5
@@ -4158,7 +4179,7 @@
 See the pkg-config man page for more details.
 
 To get pkg-config, see <http://pkg-config.freedesktop.org/>.
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 else
 	LIBOSMOSCCP_CFLAGS=$pkg_cv_LIBOSMOSCCP_CFLAGS
 	LIBOSMOSCCP_LIBS=$pkg_cv_LIBOSMOSCCP_LIBS
@@ -4192,12 +4213,13 @@
     pkg_cv_LIBOSMOCORE_CFLAGS="$LIBOSMOCORE_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libosmocore >= 0.1.30\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "libosmocore >= 0.1.30") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libosmocore >= 0.3.2\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libosmocore >= 0.3.2") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_LIBOSMOCORE_CFLAGS=`$PKG_CONFIG --cflags "libosmocore >= 0.1.30" 2>/dev/null`
+  pkg_cv_LIBOSMOCORE_CFLAGS=`$PKG_CONFIG --cflags "libosmocore >= 0.3.2" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
@@ -4208,12 +4230,13 @@
     pkg_cv_LIBOSMOCORE_LIBS="$LIBOSMOCORE_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libosmocore >= 0.1.30\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "libosmocore >= 0.1.30") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libosmocore >= 0.3.2\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libosmocore >= 0.3.2") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_LIBOSMOCORE_LIBS=`$PKG_CONFIG --libs "libosmocore >= 0.1.30" 2>/dev/null`
+  pkg_cv_LIBOSMOCORE_LIBS=`$PKG_CONFIG --libs "libosmocore >= 0.3.2" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
@@ -4233,14 +4256,14 @@
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-	        LIBOSMOCORE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libosmocore >= 0.1.30" 2>&1`
+	        LIBOSMOCORE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libosmocore >= 0.3.2" 2>&1`
         else
-	        LIBOSMOCORE_PKG_ERRORS=`$PKG_CONFIG --print-errors "libosmocore >= 0.1.30" 2>&1`
+	        LIBOSMOCORE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libosmocore >= 0.3.2" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$LIBOSMOCORE_PKG_ERRORS" >&5
 
-	as_fn_error $? "Package requirements (libosmocore >= 0.1.30) were not met:
+	as_fn_error $? "Package requirements (libosmocore >= 0.3.2) were not met:
 
 $LIBOSMOCORE_PKG_ERRORS
 
@@ -4264,7 +4287,7 @@
 See the pkg-config man page for more details.
 
 To get pkg-config, see <http://pkg-config.freedesktop.org/>.
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 else
 	LIBOSMOCORE_CFLAGS=$pkg_cv_LIBOSMOCORE_CFLAGS
 	LIBOSMOCORE_LIBS=$pkg_cv_LIBOSMOCORE_LIBS
@@ -4281,12 +4304,13 @@
     pkg_cv_LIBOSMOVTY_CFLAGS="$LIBOSMOVTY_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libosmovty >= 0.1.28\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "libosmovty >= 0.1.28") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libosmovty >= 0.3.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libosmovty >= 0.3.0") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_LIBOSMOVTY_CFLAGS=`$PKG_CONFIG --cflags "libosmovty >= 0.1.28" 2>/dev/null`
+  pkg_cv_LIBOSMOVTY_CFLAGS=`$PKG_CONFIG --cflags "libosmovty >= 0.3.0" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
@@ -4297,12 +4321,13 @@
     pkg_cv_LIBOSMOVTY_LIBS="$LIBOSMOVTY_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libosmovty >= 0.1.28\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "libosmovty >= 0.1.28") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libosmovty >= 0.3.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libosmovty >= 0.3.0") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_LIBOSMOVTY_LIBS=`$PKG_CONFIG --libs "libosmovty >= 0.1.28" 2>/dev/null`
+  pkg_cv_LIBOSMOVTY_LIBS=`$PKG_CONFIG --libs "libosmovty >= 0.3.0" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
 fi
@@ -4322,14 +4347,14 @@
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-	        LIBOSMOVTY_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libosmovty >= 0.1.28" 2>&1`
+	        LIBOSMOVTY_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libosmovty >= 0.3.0" 2>&1`
         else
-	        LIBOSMOVTY_PKG_ERRORS=`$PKG_CONFIG --print-errors "libosmovty >= 0.1.28" 2>&1`
+	        LIBOSMOVTY_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libosmovty >= 0.3.0" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$LIBOSMOVTY_PKG_ERRORS" >&5
 
-	as_fn_error $? "Package requirements (libosmovty >= 0.1.28) were not met:
+	as_fn_error $? "Package requirements (libosmovty >= 0.3.0) were not met:
 
 $LIBOSMOVTY_PKG_ERRORS
 
@@ -4353,7 +4378,7 @@
 See the pkg-config man page for more details.
 
 To get pkg-config, see <http://pkg-config.freedesktop.org/>.
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 else
 	LIBOSMOVTY_CFLAGS=$pkg_cv_LIBOSMOVTY_CFLAGS
 	LIBOSMOVTY_LIBS=$pkg_cv_LIBOSMOVTY_LIBS
@@ -4362,6 +4387,97 @@
 
 fi
 
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBOSMOGSM" >&5
+$as_echo_n "checking for LIBOSMOGSM... " >&6; }
+
+if test -n "$LIBOSMOGSM_CFLAGS"; then
+    pkg_cv_LIBOSMOGSM_CFLAGS="$LIBOSMOGSM_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libosmogsm >= 0.3.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libosmogsm >= 0.3.0") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_LIBOSMOGSM_CFLAGS=`$PKG_CONFIG --cflags "libosmogsm >= 0.3.0" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$LIBOSMOGSM_LIBS"; then
+    pkg_cv_LIBOSMOGSM_LIBS="$LIBOSMOGSM_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libosmogsm >= 0.3.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libosmogsm >= 0.3.0") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_LIBOSMOGSM_LIBS=`$PKG_CONFIG --libs "libosmogsm >= 0.3.0" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        LIBOSMOGSM_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libosmogsm >= 0.3.0" 2>&1`
+        else
+	        LIBOSMOGSM_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libosmogsm >= 0.3.0" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$LIBOSMOGSM_PKG_ERRORS" >&5
+
+	as_fn_error $? "Package requirements (libosmogsm >= 0.3.0) were not met:
+
+$LIBOSMOGSM_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables LIBOSMOGSM_CFLAGS
+and LIBOSMOGSM_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables LIBOSMOGSM_CFLAGS
+and LIBOSMOGSM_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+	LIBOSMOGSM_CFLAGS=$pkg_cv_LIBOSMOGSM_CFLAGS
+	LIBOSMOGSM_LIBS=$pkg_cv_LIBOSMOGSM_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -4374,7 +4490,7 @@
   CPP=
 fi
 if test -z "$CPP"; then
-  if test "${ac_cv_prog_CPP+set}" = set; then :
+  if ${ac_cv_prog_CPP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
       # Double quotes because CPP needs to be expanded
@@ -4490,7 +4606,7 @@
   { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details" "$LINENO" 5 ; }
+See \`config.log' for more details" "$LINENO" 5; }
 fi
 
 ac_ext=c
@@ -4502,7 +4618,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
 $as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if test "${ac_cv_path_GREP+set}" = set; then :
+if ${ac_cv_path_GREP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if test -z "$GREP"; then
@@ -4565,7 +4681,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
 $as_echo_n "checking for egrep... " >&6; }
-if test "${ac_cv_path_EGREP+set}" = set; then :
+if ${ac_cv_path_EGREP+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
@@ -4632,7 +4748,7 @@
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
 $as_echo_n "checking for ANSI C header files... " >&6; }
-if test "${ac_cv_header_stdc+set}" = set; then :
+if ${ac_cv_header_stdc+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4762,7 +4878,7 @@
 for ac_header in dahdi/user.h
 do :
   ac_fn_c_check_header_mongrel "$LINENO" "dahdi/user.h" "ac_cv_header_dahdi_user_h" "$ac_includes_default"
-if test "x$ac_cv_header_dahdi_user_h" = x""yes; then :
+if test "x$ac_cv_header_dahdi_user_h" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_DAHDI_USER_H 1
 _ACEOF
@@ -4774,6 +4890,20 @@
 
 done
 
+for ac_header in dbi/dbd.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "dbi/dbd.h" "ac_cv_header_dbi_dbd_h" "$ac_includes_default"
+if test "x$ac_cv_header_dbi_dbd_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DBI_DBD_H 1
+_ACEOF
+
+else
+  as_fn_error $? "DBI library is not installed" "$LINENO" 5
+fi
+
+done
+
 
 
 
@@ -4821,7 +4951,7 @@
 ac_config_headers="$ac_config_headers bscconfig.h"
 
 
-ac_config_files="$ac_config_files openbsc.pc include/openbsc/Makefile include/Makefile src/Makefile src/libtrau/Makefile src/libabis/Makefile src/libbsc/Makefile src/libmsc/Makefile src/libmgcp/Makefile src/libcommon/Makefile src/osmo-nitb/Makefile src/osmo-bsc/Makefile src/osmo-bsc_nat/Makefile src/osmo-bsc_mgcp/Makefile src/ipaccess/Makefile src/utils/Makefile src/libgb/Makefile src/gprs/Makefile tests/Makefile tests/debug/Makefile tests/gsm0408/Makefile tests/db/Makefile tests/channel/Makefile tests/bsc-nat/Makefile tests/mgcp/Makefile Makefile"
+ac_config_files="$ac_config_files openbsc.pc include/openbsc/Makefile include/Makefile src/Makefile src/libtrau/Makefile src/libabis/Makefile src/libbsc/Makefile src/libmsc/Makefile src/libmgcp/Makefile src/libcommon/Makefile src/osmo-nitb/Makefile src/osmo-bsc/Makefile src/osmo-bsc_nat/Makefile src/osmo-bsc_mgcp/Makefile src/ipaccess/Makefile src/utils/Makefile src/libgb/Makefile src/gprs/Makefile tests/Makefile tests/debug/Makefile tests/gsm0408/Makefile tests/db/Makefile tests/channel/Makefile tests/bsc-nat/Makefile tests/mgcp/Makefile doc/Makefile doc/examples/Makefile Makefile"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -4887,10 +5017,21 @@
      :end' >>confcache
 if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
   if test -w "$cache_file"; then
-    test "x$cache_file" != "x/dev/null" &&
+    if test "x$cache_file" != "x/dev/null"; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
 $as_echo "$as_me: updating cache $cache_file" >&6;}
-    cat confcache >$cache_file
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
   else
     { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
@@ -4950,7 +5091,7 @@
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
 
-: ${CONFIG_STATUS=./config.status}
+: "${CONFIG_STATUS=./config.status}"
 ac_write_fail=0
 ac_clean_files_save=$ac_clean_files
 ac_clean_files="$ac_clean_files $CONFIG_STATUS"
@@ -5051,6 +5192,7 @@
 IFS=" ""	$as_nl"
 
 # Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
 case $0 in #((
   *[\\/]* ) as_myself=$0 ;;
   *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
@@ -5357,8 +5499,8 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by openbsc $as_me 0.9.13, which was
-generated by GNU Autoconf 2.67.  Invocation command line was
+This file was extended by openbsc $as_me 0.9.14, which was
+generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
@@ -5423,8 +5565,8 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-openbsc config.status 0.9.13
-configured by $0, generated by GNU Autoconf 2.67,
+openbsc config.status 0.9.14
+configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -5579,9 +5721,11 @@
     "tests/channel/Makefile") CONFIG_FILES="$CONFIG_FILES tests/channel/Makefile" ;;
     "tests/bsc-nat/Makefile") CONFIG_FILES="$CONFIG_FILES tests/bsc-nat/Makefile" ;;
     "tests/mgcp/Makefile") CONFIG_FILES="$CONFIG_FILES tests/mgcp/Makefile" ;;
+    "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
+    "doc/examples/Makefile") CONFIG_FILES="$CONFIG_FILES doc/examples/Makefile" ;;
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
 
-  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;;
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
   esac
 done
 
@@ -5604,9 +5748,10 @@
 # after its creation but before its name has been assigned to `$tmp'.
 $debug ||
 {
-  tmp=
+  tmp= ac_tmp=
   trap 'exit_status=$?
-  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
 ' 0
   trap 'as_fn_exit 1' 1 2 13 15
 }
@@ -5614,12 +5759,13 @@
 
 {
   tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
-  test -n "$tmp" && test -d "$tmp"
+  test -d "$tmp"
 }  ||
 {
   tmp=./conf$$-$RANDOM
   (umask 077 && mkdir "$tmp")
 } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
 
 # Set up the scripts for CONFIG_FILES section.
 # No need to generate them if there are no CONFIG_FILES.
@@ -5641,7 +5787,7 @@
   ac_cs_awk_cr=$ac_cr
 fi
 
-echo 'BEGIN {' >"$tmp/subs1.awk" &&
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
 _ACEOF
 
 
@@ -5669,7 +5815,7 @@
 rm -f conf$$subs.sh
 
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
 _ACEOF
 sed -n '
 h
@@ -5717,7 +5863,7 @@
 rm -f conf$$subs.awk
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 _ACAWK
-cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
   for (key in S) S_is_set[key] = 1
   FS = ""
 
@@ -5749,7 +5895,7 @@
   sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
 else
   cat
-fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
   || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
 _ACEOF
 
@@ -5783,7 +5929,7 @@
 # No need to generate them if there are no CONFIG_HEADERS.
 # This happens for instance with `./config.status Makefile'.
 if test -n "$CONFIG_HEADERS"; then
-cat >"$tmp/defines.awk" <<\_ACAWK ||
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
 BEGIN {
 _ACEOF
 
@@ -5795,8 +5941,8 @@
 # handling of long lines.
 ac_delim='%!_!# '
 for ac_last_try in false false :; do
-  ac_t=`sed -n "/$ac_delim/p" confdefs.h`
-  if test -z "$ac_t"; then
+  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_tt"; then
     break
   elif $ac_last_try; then
     as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
@@ -5897,7 +6043,7 @@
   esac
   case $ac_mode$ac_tag in
   :[FHL]*:*);;
-  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
   :[FH]-) ac_tag=-:-;;
   :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
   esac
@@ -5916,7 +6062,7 @@
     for ac_f
     do
       case $ac_f in
-      -) ac_f="$tmp/stdin";;
+      -) ac_f="$ac_tmp/stdin";;
       *) # Look for the file first in the build tree, then in the source tree
 	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
 	 # because $ac_f cannot contain `:'.
@@ -5925,7 +6071,7 @@
 	   [\\/$]*) false;;
 	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
 	   esac ||
-	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;;
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
       esac
       case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
       as_fn_append ac_file_inputs " '$ac_f'"
@@ -5951,8 +6097,8 @@
     esac
 
     case $ac_tag in
-    *:-:* | *:-) cat >"$tmp/stdin" \
-      || as_fn_error $? "could not create $ac_file" "$LINENO" 5  ;;
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
     esac
     ;;
   esac
@@ -6088,21 +6234,22 @@
 s&@MKDIR_P@&$ac_MKDIR_P&;t t
 $ac_datarootdir_hack
 "
-eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
-  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
 
 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
-  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
-  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
 which seems to be undefined.  Please make sure it is defined" >&5
 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
 which seems to be undefined.  Please make sure it is defined" >&2;}
 
-  rm -f "$tmp/stdin"
+  rm -f "$ac_tmp/stdin"
   case $ac_file in
-  -) cat "$tmp/out" && rm -f "$tmp/out";;
-  *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
   esac \
   || as_fn_error $? "could not create $ac_file" "$LINENO" 5
  ;;
@@ -6113,20 +6260,20 @@
   if test x"$ac_file" != x-; then
     {
       $as_echo "/* $configure_input  */" \
-      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
-    } >"$tmp/config.h" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+    } >"$ac_tmp/config.h" \
       || as_fn_error $? "could not create $ac_file" "$LINENO" 5
-    if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
+    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
 $as_echo "$as_me: $ac_file is unchanged" >&6;}
     else
       rm -f "$ac_file"
-      mv "$tmp/config.h" "$ac_file" \
+      mv "$ac_tmp/config.h" "$ac_file" \
 	|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
     fi
   else
     $as_echo "/* $configure_input  */" \
-      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
       || as_fn_error $? "could not create -" "$LINENO" 5
   fi
 # Compute "$ac_file"'s index in $config_headers.
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..5951618
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,115 @@
+dnl Process this file with autoconf to produce a configure script
+AC_INIT([openbsc],
+	m4_esyscmd([./git-version-gen .tarball-version]),
+	[openbsc-devel@lists.openbsc.org])
+
+AM_INIT_AUTOMAKE([dist-bzip2])
+
+dnl kernel style compile messages
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+dnl checks for programs
+AC_PROG_MAKE_SET
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_RANLIB
+
+dnl checks for libraries
+AC_SEARCH_LIBS(crypt, crypt,
+    [LIBCRYPT="-lcrypt"; AC_DEFINE([VTY_CRYPT_PW], [], [Use crypt functionality of vty.])])
+AC_SEARCH_LIBS(gtp_new, gtp,
+    [LIBCRYPT="-lgtp"; AC_SUBST([GPRS_LIBGTP], [1])])
+
+AM_CONDITIONAL(HAVE_LIBGTP, test "x$GPRS_LIBGTP" != "x")
+
+
+AC_ARG_ENABLE([nat], [AS_HELP_STRING([--enable-nat], [Build the BSC NAT. Requires SCCP])],
+    [
+        PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 0.0.2)
+        osmo_ac_build_nat="yes"
+    ],
+    [
+        osmo_ac_build_nat="no"
+    ])
+AM_CONDITIONAL(BUILD_NAT, test "x$osmo_ac_build_nat" = "xyes")
+
+AC_ARG_ENABLE([osmo-bsc], [AS_HELP_STRING([--enable-osmo-bsc], [Build the Osmo BSC])],
+    [
+        PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 0.0.2)
+        osmo_ac_build_bsc="yes"
+    ],
+    [
+        osmo_ac_build_bsc="no"
+    ])
+AM_CONDITIONAL(BUILD_BSC, test "x$osmo_ac_build_bsc" = "xyes")
+
+PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.3.2)
+PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.3.0)
+PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.3.0)
+
+dnl checks for header files
+AC_HEADER_STDC
+AC_CHECK_HEADERS(dahdi/user.h,,AC_MSG_WARN(DAHDI input driver will not be built))
+AC_CHECK_HEADERS(dbi/dbd.h,,AC_MSG_ERROR(DBI library is not installed))
+
+
+dnl Checks for typedefs, structures and compiler characteristics
+
+# The following test is taken from WebKit's webkit.m4
+saved_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -fvisibility=hidden "
+AC_MSG_CHECKING([if ${CC} supports -fvisibility=hidden])
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([char foo;])],
+      [ AC_MSG_RESULT([yes])
+        SYMBOL_VISIBILITY="-fvisibility=hidden"],
+        AC_MSG_RESULT([no]))
+CFLAGS="$saved_CFLAGS"
+AC_SUBST(SYMBOL_VISIBILITY)
+
+# Coverage build taken from WebKit's configure.in
+AC_MSG_CHECKING([whether to enable code coverage support])
+AC_ARG_ENABLE(coverage,
+              AC_HELP_STRING([--enable-coverage],
+                             [enable code coverage support [default=no]]),
+              [],[enable_coverage="no"])
+AC_MSG_RESULT([$enable_coverage])
+if test "$enable_coverage" = "yes"; then
+   COVERAGE_CFLAGS="-ftest-coverage -fprofile-arcs"
+   COVERAGE_LDFLAGS="-ftest-coverage -fprofile-arcs"
+   AC_SUBST([COVERAGE_CFLAGS])
+   AC_SUBST([COVERAGE_LDFLAGS])
+fi
+
+
+dnl Generate the output
+AM_CONFIG_HEADER(bscconfig.h)
+
+AC_OUTPUT(
+    openbsc.pc
+    include/openbsc/Makefile
+    include/Makefile
+    src/Makefile
+    src/libtrau/Makefile
+    src/libabis/Makefile
+    src/libbsc/Makefile
+    src/libmsc/Makefile
+    src/libmgcp/Makefile
+    src/libcommon/Makefile
+    src/osmo-nitb/Makefile
+    src/osmo-bsc/Makefile
+    src/osmo-bsc_nat/Makefile
+    src/osmo-bsc_mgcp/Makefile
+    src/ipaccess/Makefile
+    src/utils/Makefile
+    src/libgb/Makefile
+    src/gprs/Makefile
+    tests/Makefile
+    tests/debug/Makefile
+    tests/gsm0408/Makefile
+    tests/db/Makefile
+    tests/channel/Makefile
+    tests/bsc-nat/Makefile
+    tests/mgcp/Makefile
+    doc/Makefile
+    doc/examples/Makefile
+    Makefile)
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..aee2d7b
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = examples
diff --git a/doc/Makefile.in b/doc/Makefile.in
new file mode 100644
index 0000000..f036d6a
--- /dev/null
+++ b/doc/Makefile.in
@@ -0,0 +1,539 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+subdir = doc
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/bscconfig.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo "  GEN   " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-dvi-recursive install-exec-recursive \
+	install-html-recursive install-info-recursive \
+	install-pdf-recursive install-ps-recursive install-recursive \
+	installcheck-recursive installdirs-recursive pdf-recursive \
+	ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+	$(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+	distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+  dir0=`pwd`; \
+  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+  sed_rest='s,^[^/]*/*,,'; \
+  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+  sed_butlast='s,/*[^/]*$$,,'; \
+  while test -n "$$dir1"; do \
+    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+    if test "$$first" != "."; then \
+      if test "$$first" = ".."; then \
+        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+      else \
+        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+        if test "$$first2" = "$$first"; then \
+          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+        else \
+          dir2="../$$dir2"; \
+        fi; \
+        dir0="$$dir0"/"$$first"; \
+      fi; \
+    fi; \
+    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+  done; \
+  reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GPRS_LIBGTP = @GPRS_LIBGTP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
+LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
+LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
+LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
+LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
+LIBOSMOVTY_LIBS = @LIBOSMOVTY_LIBS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYMBOL_VISIBILITY = @SYMBOL_VISIBILITY@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build_alias = @build_alias@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host_alias = @host_alias@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = examples
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu doc/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@fail= failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+	@fail= failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(MKDIR_P) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	  fi; \
+	done
+	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+	    $(am__relativize); \
+	    new_distdir=$$reldir; \
+	    dir1=$$subdir; dir2="$(top_distdir)"; \
+	    $(am__relativize); \
+	    new_top_distdir=$$reldir; \
+	    echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+	    echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+	    ($(am__cd) $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$new_top_distdir" \
+	        distdir="$$new_distdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+		am__skip_mode_fix=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+	install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+	all all-am check check-am clean clean-generic ctags \
+	ctags-recursive distclean distclean-generic distclean-tags \
+	distdir dvi dvi-am html html-am info info-am install \
+	install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	installdirs-am maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \
+	tags-recursive uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am
new file mode 100644
index 0000000..8f14fdc
--- /dev/null
+++ b/doc/examples/Makefile.am
@@ -0,0 +1,23 @@
+
+CFG_FILES = find $(srcdir) -name '*.cfg*' | sed -e 's,^$(srcdir),,'
+
+dist-hook:
+	for f in $$($(CFG_FILES)); do \
+		j="$(distdir)/$$f" && \
+		mkdir -p "$$(dirname $$j)" && \
+		$(INSTALL_DATA) $(srcdir)/$$f $$j; \
+	done
+
+install-data-hook:
+	for f in $$($(CFG_FILES)); do \
+		j="$(DESTDIR)$(docdir)/examples/$$f" && \
+		mkdir -p "$$(dirname $$j)" && \
+		$(INSTALL_DATA) $(srcdir)/$$f $$j; \
+	done
+
+uninstall-hook:
+	@$(PRE_UNINSTALL)
+	for f in $$($(CFG_FILES)); do \
+		j="$(DESTDIR)$(docdir)/examples/$$f" && \
+		$(RM) $$j; \
+	done
diff --git a/doc/examples/Makefile.in b/doc/examples/Makefile.in
new file mode 100644
index 0000000..6142a0c
--- /dev/null
+++ b/doc/examples/Makefile.in
@@ -0,0 +1,364 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+subdir = doc/examples
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/bscconfig.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo "  GEN   " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GPRS_LIBGTP = @GPRS_LIBGTP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
+LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
+LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
+LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
+LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
+LIBOSMOVTY_LIBS = @LIBOSMOVTY_LIBS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYMBOL_VISIBILITY = @SYMBOL_VISIBILITY@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build_alias = @build_alias@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host_alias = @host_alias@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+CFG_FILES = find $(srcdir) -name '*.cfg*' | sed -e 's,^$(srcdir),,'
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/examples/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu doc/examples/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+	$(MAKE) $(AM_MAKEFLAGS) \
+	  top_distdir="$(top_distdir)" distdir="$(distdir)" \
+	  dist-hook
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) install-data-hook
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) uninstall-hook
+.MAKE: install-am install-data-am install-strip uninstall-am
+
+.PHONY: all all-am check check-am clean clean-generic dist-hook \
+	distclean distclean-generic distdir dvi dvi-am html html-am \
+	info info-am install install-am install-data install-data-am \
+	install-data-hook install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+	pdf-am ps ps-am uninstall uninstall-am uninstall-hook
+
+
+dist-hook:
+	for f in $$($(CFG_FILES)); do \
+		j="$(distdir)/$$f" && \
+		mkdir -p "$$(dirname $$j)" && \
+		$(INSTALL_DATA) $(srcdir)/$$f $$j; \
+	done
+
+install-data-hook:
+	for f in $$($(CFG_FILES)); do \
+		j="$(DESTDIR)$(docdir)/examples/$$f" && \
+		mkdir -p "$$(dirname $$j)" && \
+		$(INSTALL_DATA) $(srcdir)/$$f $$j; \
+	done
+
+uninstall-hook:
+	@$(PRE_UNINSTALL)
+	for f in $$($(CFG_FILES)); do \
+		j="$(DESTDIR)$(docdir)/examples/$$f" && \
+		$(RM) $$j; \
+	done
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/doc/examples/osmo-bsc_mgcp/mgcp.cfg b/doc/examples/osmo-bsc_mgcp/mgcp.cfg
new file mode 100644
index 0000000..678f546
--- /dev/null
+++ b/doc/examples/osmo-bsc_mgcp/mgcp.cfg
@@ -0,0 +1,19 @@
+!
+! MGCP configuration hand edited
+!   !
+password foo
+!
+line vty
+ no login
+!
+mgcp
+!  local ip 213.167.134.14
+  bts ip 172.16.252.43
+  bind ip 213.167.134.141
+  bind port 2427
+  bind early 1
+  rtp base 4000
+  sdp audio payload number 98
+  sdp audio payload name AMR/8000
+  number endpoints 31
+  loop 1
diff --git a/doc/examples/osmo-nitb/bs11/openbsc-1bts-2trx-hopping.cfg b/doc/examples/osmo-nitb/bs11/openbsc-1bts-2trx-hopping.cfg
new file mode 100644
index 0000000..654d397
--- /dev/null
+++ b/doc/examples/osmo-nitb/bs11/openbsc-1bts-2trx-hopping.cfg
@@ -0,0 +1,164 @@
+!
+! OpenBSC (0.9.0.845-57c4) configuration saved from vty
+!!
+password foo
+!
+line vty
+ no login
+!
+e1_input
+ e1_line 0 driver misdn
+network
+ network country code 1
+ mobile network code 1
+ short name OpenBSC
+ long name OpenBSC
+ auth policy closed
+ location updating reject cause 13
+ encryption a5 0
+ neci 1
+ rrlp mode none
+ mm info 0
+ handover 0
+ handover window rxlev averaging 10
+ handover window rxqual averaging 1
+ handover window rxlev neighbor averaging 10
+ handover power budget interval 6
+ handover power budget hysteresis 3
+ handover maximum distance 9999
+ timer t3101 10
+ timer t3103 0
+ timer t3105 0
+ timer t3107 0
+ timer t3109 0
+ timer t3111 0
+ timer t3113 60
+ timer t3115 0
+ timer t3117 0
+ timer t3119 0
+ timer t3141 0
+ bts 0
+  type bs11
+  band GSM900
+  cell_identity 0
+  location_area_code 1
+  training_sequence_code 7
+  base_station_id_code 63
+  ms max power 15
+  cell reselection hysteresis 4
+  rxlev access min 0
+  channel allocator descending
+  rach tx integer 9
+  rach max transmission 7
+  oml e1 line 0 timeslot 1 sub-slot full
+  oml e1 tei 25
+  gprs mode none
+  trx 0
+   rf_locked 0
+   arfcn 121
+   nominal power 24
+   max_power_red 12
+   rsl e1 line 0 timeslot 1 sub-slot full
+   rsl e1 tei 1
+    timeslot 0
+     phys_chan_config CCCH
+     hopping enabled 0
+     e1 line 0 timeslot 1 sub-slot full
+    timeslot 1
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 2 sub-slot 1
+    timeslot 2
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 2 sub-slot 2
+    timeslot 3
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 2 sub-slot 3
+    timeslot 4
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 3 sub-slot 0
+    timeslot 5
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 3 sub-slot 1
+    timeslot 6
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 3 sub-slot 2
+    timeslot 7
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 3 sub-slot 3
+  trx 1
+   rf_locked 0
+   arfcn 119
+   nominal power 24
+   max_power_red 12
+   rsl e1 line 0 timeslot 1 sub-slot full
+   rsl e1 tei 2
+    timeslot 0
+     phys_chan_config SDCCH8
+     hopping enabled 1
+     hopping sequence-number 0
+     hopping maio 0
+     hopping arfcn add 117
+     hopping arfcn add 119
+    timeslot 1
+     phys_chan_config TCH/F
+     hopping enabled 1
+     hopping sequence-number 0
+     hopping maio 0
+     hopping arfcn add 117
+     hopping arfcn add 119
+     e1 line 0 timeslot 4 sub-slot 1
+    timeslot 2
+     phys_chan_config TCH/F
+     hopping enabled 1
+     hopping sequence-number 0
+     hopping maio 0
+     hopping arfcn add 117
+     hopping arfcn add 119
+     e1 line 0 timeslot 4 sub-slot 2
+    timeslot 3
+     phys_chan_config TCH/F
+     hopping enabled 1
+     hopping sequence-number 0
+     hopping maio 0
+     hopping arfcn add 117
+     hopping arfcn add 119
+     e1 line 0 timeslot 4 sub-slot 3
+    timeslot 4
+     phys_chan_config TCH/F
+     hopping enabled 1
+     hopping sequence-number 0
+     hopping maio 0
+     hopping arfcn add 117
+     hopping arfcn add 119
+     e1 line 0 timeslot 5 sub-slot 0
+    timeslot 5
+     phys_chan_config TCH/F
+     hopping enabled 1
+     hopping sequence-number 0
+     hopping maio 0
+     hopping arfcn add 117
+     hopping arfcn add 119
+     e1 line 0 timeslot 5 sub-slot 1
+    timeslot 6
+     phys_chan_config TCH/F
+     hopping enabled 1
+     hopping sequence-number 0
+     hopping maio 0
+     hopping arfcn add 117
+     hopping arfcn add 119
+     e1 line 0 timeslot 5 sub-slot 2
+    timeslot 7
+     phys_chan_config TCH/F
+     hopping enabled 1
+     hopping sequence-number 0
+     hopping maio 0
+     hopping arfcn add 117
+     hopping arfcn add 119
+     e1 line 0 timeslot 5 sub-slot 3
diff --git a/doc/examples/osmo-nitb/bs11/openbsc-1bts-2trx.cfg b/doc/examples/osmo-nitb/bs11/openbsc-1bts-2trx.cfg
new file mode 100644
index 0000000..ebe6cc6
--- /dev/null
+++ b/doc/examples/osmo-nitb/bs11/openbsc-1bts-2trx.cfg
@@ -0,0 +1,84 @@
+!
+! OpenBSC configuration saved from vty
+!   !
+password foo
+!
+line vty
+ no login
+!
+e1_input
+ e1_line 0 driver misdn
+network
+ network country code 1
+ mobile network code 1
+ short name OpenBSC
+ long name OpenBSC
+ timer t3101 10
+ timer t3113 60
+ bts 0
+  type bs11
+  band GSM900
+  cell_identity 1
+  location_area_code 1
+  training_sequence_code 7
+  base_station_id_code 63
+  oml e1 line 0 timeslot 1 sub-slot full
+  oml e1 tei 25
+  trx 0
+   arfcn 121
+   max_power_red 0
+   rsl e1 line 0 timeslot 1 sub-slot full
+   rsl e1 tei 1
+    timeslot 0
+     phys_chan_config CCCH+SDCCH4
+     e1 line 0 timeslot 1 sub-slot full
+    timeslot 1
+     phys_chan_config SDCCH8
+     e1 line 0 timeslot 2 sub-slot 1
+    timeslot 2
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 2 sub-slot 2
+    timeslot 3
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 2 sub-slot 3
+    timeslot 4
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 3 sub-slot 0
+    timeslot 5
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 3 sub-slot 1
+    timeslot 6
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 3 sub-slot 2
+    timeslot 7
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 3 sub-slot 3
+  trx 1
+   arfcn 123
+   max_power_red 0
+   rsl e1 line 0 timeslot 1 sub-slot full
+   rsl e1 tei 2
+    timeslot 0
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 4 sub-slot 0
+    timeslot 1
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 4 sub-slot 1
+    timeslot 2
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 4 sub-slot 2
+    timeslot 3
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 4 sub-slot 3
+    timeslot 4
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 5 sub-slot 0
+    timeslot 5
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 5 sub-slot 1
+    timeslot 6
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 5 sub-slot 2
+    timeslot 7
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 5 sub-slot 3
diff --git a/doc/examples/osmo-nitb/bs11/openbsc-2bts-2trx.cfg b/doc/examples/osmo-nitb/bs11/openbsc-2bts-2trx.cfg
new file mode 100644
index 0000000..9ae8003
--- /dev/null
+++ b/doc/examples/osmo-nitb/bs11/openbsc-2bts-2trx.cfg
@@ -0,0 +1,148 @@
+!
+! OpenBSC configuration saved from vty
+!   !
+password foo
+!
+line vty
+ no login
+!
+network
+ network country code 1
+ mobile network code 1
+ short name OpenBSC
+ long name OpenBSC
+ timer t3101 10
+ timer t3113 60
+ bts 0
+  type bs11
+  band GSM900
+  cell_identity 1
+  location_area_code 1
+  training_sequence_code 7
+  base_station_id_code 63
+  oml e1 line 0 timeslot 1 sub-slot full
+  oml e1 tei 25
+  trx 0
+   arfcn 121
+   max_power_red 0
+   rsl e1 line 0 timeslot 1 sub-slot full
+   rsl e1 tei 1
+    timeslot 0
+     phys_chan_config CCCH+SDCCH4
+     e1 line 0 timeslot 1 sub-slot full
+    timeslot 1
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 2 sub-slot 1
+    timeslot 2
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 2 sub-slot 2
+    timeslot 3
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 2 sub-slot 3
+    timeslot 4
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 3 sub-slot 0
+    timeslot 5
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 3 sub-slot 1
+    timeslot 6
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 3 sub-slot 2
+    timeslot 7
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 3 sub-slot 3
+  trx 1
+   arfcn 123
+   max_power_red 0
+   rsl e1 line 0 timeslot 1 sub-slot full
+   rsl e1 tei 2
+    timeslot 0
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 4 sub-slot 0
+    timeslot 1
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 4 sub-slot 1
+    timeslot 2
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 4 sub-slot 2
+    timeslot 3
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 4 sub-slot 3
+    timeslot 4
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 5 sub-slot 0
+    timeslot 5
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 5 sub-slot 1
+    timeslot 6
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 5 sub-slot 2
+    timeslot 7
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 5 sub-slot 3
+ bts 1
+  type bs11
+  band GSM900
+  location_area_code 2
+  training_sequence_code 7
+  base_station_id_code 63
+  oml e1 line 1 timeslot 6 sub-slot full
+  oml e1 tei 25
+  trx 0
+   arfcn 122
+   max_power_red 0
+   rsl e1 line 1 timeslot 6 sub-slot full
+   rsl e1 tei 1
+    timeslot 0
+     phys_chan_config CCCH+SDCCH4
+     e1 line 1 timeslot 7 sub-slot 0
+    timeslot 1
+     phys_chan_config SDCCH8
+     e1 line 1 timeslot 7 sub-slot 1
+    timeslot 2
+     phys_chan_config TCH/F
+     e1 line 1 timeslot 7 sub-slot 2
+    timeslot 3
+     phys_chan_config TCH/F
+     e1 line 1 timeslot 7 sub-slot 3
+    timeslot 4
+     phys_chan_config TCH/F
+     e1 line 1 timeslot 8 sub-slot 0
+    timeslot 5
+     phys_chan_config TCH/F
+     e1 line 1 timeslot 8 sub-slot 1
+    timeslot 6
+     phys_chan_config TCH/F
+     e1 line 1 timeslot 8 sub-slot 2
+    timeslot 7
+     phys_chan_config TCH/F
+     e1 line 1 timeslot 8 sub-slot 3
+  trx 1
+   arfcn 124
+   max_power_red 0
+   rsl e1 line 1 timeslot 6 sub-slot full
+   rsl e1 tei 2
+    timeslot 0
+     phys_chan_config TCH/F
+     e1 line 1 timeslot 9 sub-slot 0
+    timeslot 1
+     phys_chan_config TCH/F
+     e1 line 1 timeslot 9 sub-slot 1
+    timeslot 2
+     phys_chan_config TCH/F
+     e1 line 1 timeslot 9 sub-slot 2
+    timeslot 3
+     phys_chan_config TCH/F
+     e1 line 1 timeslot 9 sub-slot 3
+    timeslot 4
+     phys_chan_config TCH/F
+     e1 line 1 timeslot 10 sub-slot 0
+    timeslot 5
+     phys_chan_config TCH/F
+     e1 line 1 timeslot 10 sub-slot 1
+    timeslot 6
+     phys_chan_config TCH/F
+     e1 line 1 timeslot 10 sub-slot 2
+    timeslot 7
+     phys_chan_config TCH/F
+     e1 line 1 timeslot 10 sub-slot 3
diff --git a/doc/examples/osmo-nitb/bs11/openbsc.cfg b/doc/examples/osmo-nitb/bs11/openbsc.cfg
new file mode 100644
index 0000000..542edd6
--- /dev/null
+++ b/doc/examples/osmo-nitb/bs11/openbsc.cfg
@@ -0,0 +1,56 @@
+!
+! OpenBSC configuration saved from vty
+!   !
+password foo
+!
+line vty
+ no login
+!
+e1_input
+ e1_line 0 driver misdn
+network
+ network country code 1
+ mobile network code 1
+ short name OpenBSC
+ long name OpenBSC
+ timer t3101 10
+ timer t3113 60
+ bts 0
+  type bs11
+  band GSM900
+  cell_identity 1
+  location_area_code 1
+  training_sequence_code 7
+  base_station_id_code 63
+  oml e1 line 0 timeslot 1 sub-slot full
+  oml e1 tei 25
+  trx 0
+   arfcn 121
+   max_power_red 0
+   rsl e1 line 0 timeslot 1 sub-slot full
+   rsl e1 tei 1
+    timeslot 0
+     phys_chan_config CCCH+SDCCH4
+     e1 line 0 timeslot 1 sub-slot full
+    timeslot 1
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 2 sub-slot 1
+    timeslot 2
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 2 sub-slot 2
+    timeslot 3
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 2 sub-slot 3
+    timeslot 4
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 3 sub-slot 0
+    timeslot 5
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 3 sub-slot 1
+    timeslot 6
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 3 sub-slot 2
+    timeslot 7
+     phys_chan_config TCH/F
+     e1 line 0 timeslot 3 sub-slot 3
+
diff --git a/doc/examples/osmo-nitb/hsl/openbsc.cfg b/doc/examples/osmo-nitb/hsl/openbsc.cfg
new file mode 100644
index 0000000..831f6bb
--- /dev/null
+++ b/doc/examples/osmo-nitb/hsl/openbsc.cfg
@@ -0,0 +1,87 @@
+!
+! OpenBSC (0.9.11.261-32c0) configuration saved from vty
+!!
+password foo
+!
+line vty
+ no login
+!
+network
+ network country code 262
+ mobile network code 42
+ short name OpenBSC
+ long name OpenBSC
+ auth policy closed
+ location updating reject cause 13
+ encryption a5 0
+ neci 1
+ paging any use tch 0
+ rrlp mode none
+ mm info 0
+ handover 0
+ handover window rxlev averaging 10
+ handover window rxqual averaging 1
+ handover window rxlev neighbor averaging 10
+ handover power budget interval 6
+ handover power budget hysteresis 3
+ handover maximum distance 9999
+ timer t3101 10
+ timer t3103 0
+ timer t3105 0
+ timer t3107 0
+ timer t3109 0
+ timer t3111 0
+ timer t3113 60
+ timer t3115 0
+ timer t3117 0
+ timer t3119 0
+ timer t3122 0
+ timer t3141 0
+ dtx-used 1
+ subscriber-keep-in-ram 0
+ bts 0
+  type hsl_femto
+  band DCS1800
+  cell_identity 0
+  location_area_code 1
+  training_sequence_code 0
+  base_station_id_code 0
+  ms max power 15
+  cell reselection hysteresis 4
+  rxlev access min 0
+  channel allocator ascending
+  rach tx integer 9
+  rach max transmission 1
+  hsl serial-number 8303701
+  neighbor-list mode automatic
+  gprs mode none
+  trx 0
+   rf_locked 0
+   arfcn 871
+   nominal power 23
+   max_power_red 20
+   rsl e1 tei 0
+    timeslot 0
+     phys_chan_config CCCH+SDCCH4
+     hopping enabled 0
+    timeslot 1
+     phys_chan_config TCH/F
+     hopping enabled 0
+    timeslot 2
+     phys_chan_config TCH/F
+     hopping enabled 0
+    timeslot 3
+     phys_chan_config TCH/F
+     hopping enabled 0
+    timeslot 4
+     phys_chan_config TCH/F
+     hopping enabled 0
+    timeslot 5
+     phys_chan_config TCH/F
+     hopping enabled 0
+    timeslot 6
+     phys_chan_config TCH/F
+     hopping enabled 0
+    timeslot 7
+     phys_chan_config TCH/F
+     hopping enabled 0
diff --git a/doc/examples/osmo-nitb/nanobts/openbsc-multitrx.cfg b/doc/examples/osmo-nitb/nanobts/openbsc-multitrx.cfg
new file mode 100644
index 0000000..9c9108c
--- /dev/null
+++ b/doc/examples/osmo-nitb/nanobts/openbsc-multitrx.cfg
@@ -0,0 +1,97 @@
+!
+! OpenBSC configuration saved from vty
+!   !
+password foo
+!
+line vty
+ no login
+!
+network
+ network country code 1
+ mobile network code 1
+ short name OpenBSC
+ long name OpenBSC
+ auth policy closed
+ location updating reject cause 13
+ encryption a5 0
+ neci 1
+ rrlp mode none
+ mm info 0
+ handover 0
+ handover window rxlev averaging 10
+ handover window rxqual averaging 1
+ handover window rxlev neighbor averaging 10
+ handover power budget interval 6
+ handover power budget hysteresis 3
+ handover maximum distance 9999
+ timer t3101 10
+ timer t3103 0
+ timer t3105 0
+ timer t3107 0
+ timer t3109 0
+ timer t3111 0
+ timer t3113 60
+ timer t3115 0
+ timer t3117 0
+ timer t3119 0
+ timer t3141 0
+ bts 0
+  type nanobts
+  band DCS1800
+  cell_identity 0
+  location_area_code 1
+  training_sequence_code 7
+  base_station_id_code 63
+  ms max power 15
+  cell reselection hysteresis 4
+  rxlev access min 0
+  channel allocator ascending
+  rach tx integer 9
+  rach max transmission 7
+  ip.access unit_id 1800 0
+  oml ip.access stream_id 255
+  gprs mode none
+  trx 0
+   rf_locked 0
+   arfcn 871
+   nominal power 23
+   max_power_red 0
+   rsl e1 tei 0
+    timeslot 0
+     phys_chan_config CCCH+SDCCH4
+    timeslot 1
+     phys_chan_config SDCCH8
+    timeslot 2
+     phys_chan_config TCH/F
+    timeslot 3
+     phys_chan_config TCH/F
+    timeslot 4
+     phys_chan_config TCH/F
+    timeslot 5
+     phys_chan_config TCH/F
+    timeslot 6
+     phys_chan_config TCH/F
+    timeslot 7
+     phys_chan_config TCH/F
+  trx 1
+   rf_locked 0
+   arfcn 873
+   nominal power 23
+   max_power_red 0
+   rsl e1 tei 0
+    timeslot 0
+     phys_chan_config SDCCH8
+    timeslot 1
+     phys_chan_config TCH/F
+    timeslot 2
+     phys_chan_config TCH/F
+    timeslot 3
+     phys_chan_config TCH/F
+    timeslot 4
+     phys_chan_config TCH/F
+    timeslot 5
+     phys_chan_config TCH/F
+    timeslot 6
+     phys_chan_config TCH/F
+    timeslot 7
+     phys_chan_config TCH/F
diff --git a/doc/examples/osmo-nitb/nanobts/openbsc.cfg b/doc/examples/osmo-nitb/nanobts/openbsc.cfg
new file mode 100644
index 0000000..3e7b932
--- /dev/null
+++ b/doc/examples/osmo-nitb/nanobts/openbsc.cfg
@@ -0,0 +1,75 @@
+!
+! OpenBSC configuration saved from vty
+!   !
+password foo
+!
+line vty
+ no login
+!
+network
+ network country code 1
+ mobile network code 1
+ short name OpenBSC
+ long name OpenBSC
+ auth policy closed
+ location updating reject cause 13
+ encryption a5 0
+ neci 1
+ rrlp mode none
+ mm info 1
+ handover 0
+ handover window rxlev averaging 10
+ handover window rxqual averaging 1
+ handover window rxlev neighbor averaging 10
+ handover power budget interval 6
+ handover power budget hysteresis 3
+ handover maximum distance 9999
+ timer t3101 10
+ timer t3103 0
+ timer t3105 0
+ timer t3107 0
+ timer t3109 0
+ timer t3111 0
+ timer t3113 60
+ timer t3115 0
+ timer t3117 0
+ timer t3119 0
+ timer t3141 0
+ bts 0
+  type nanobts
+  band DCS1800
+  cell_identity 0
+  location_area_code 1
+  training_sequence_code 7
+  base_station_id_code 63
+  ms max power 15
+  cell reselection hysteresis 4
+  rxlev access min 0
+  channel allocator ascending
+  rach tx integer 9
+  rach max transmission 7
+  ip.access unit_id 1801 0
+  oml ip.access stream_id 255
+  gprs mode none
+  trx 0
+   rf_locked 0
+   arfcn 514
+   nominal power 23
+   max_power_red 20
+   rsl e1 tei 0
+    timeslot 0
+     phys_chan_config CCCH+SDCCH4
+    timeslot 1
+     phys_chan_config SDCCH8
+    timeslot 2
+     phys_chan_config TCH/F
+    timeslot 3
+     phys_chan_config TCH/F
+    timeslot 4
+     phys_chan_config TCH/F
+    timeslot 5
+     phys_chan_config TCH/F
+    timeslot 6
+     phys_chan_config TCH/F
+    timeslot 7
+     phys_chan_config TCH/F
diff --git a/doc/examples/osmo-nitb/rbs2308/openbsc.cfg b/doc/examples/osmo-nitb/rbs2308/openbsc.cfg
new file mode 100644
index 0000000..7135042
--- /dev/null
+++ b/doc/examples/osmo-nitb/rbs2308/openbsc.cfg
@@ -0,0 +1,221 @@
+!
+! OpenBSC (0.9.11.308-62d46) configuration saved from vty
+!!
+password foo
+!
+line vty
+ no login
+!
+network
+ network country code 262
+ mobile network code 42
+ short name OpenBSC
+ long name OpenBSC
+ auth policy closed
+ location updating reject cause 13
+ encryption a5 0
+ neci 0
+ paging any use tch 0
+ rrlp mode none
+ mm info 0
+ handover 0
+ handover window rxlev averaging 10
+ handover window rxqual averaging 1
+ handover window rxlev neighbor averaging 10
+ handover power budget interval 6
+ handover power budget hysteresis 3
+ handover maximum distance 9999
+ timer t3101 10
+ timer t3103 0
+ timer t3105 0
+ timer t3107 0
+ timer t3109 0
+ timer t3111 0
+ timer t3113 60
+ timer t3115 0
+ timer t3117 0
+ timer t3119 0
+ timer t3122 0
+ timer t3141 0
+ dtx-used 0
+ subscriber-keep-in-ram 0
+ bts 0
+  type rbs2000
+  band GSM900
+  cell_identity 0
+  location_area_code 1
+  training_sequence_code 7
+  base_station_id_code 63
+  ms max power 15
+  cell reselection hysteresis 4
+  rxlev access min 0
+  channel allocator descending
+  rach tx integer 9
+  rach max transmission 7
+  oml e1 line 0 timeslot 1 sub-slot full
+  oml e1 tei 62
+  neighbor-list mode automatic
+  gprs mode none
+  is-connection-list add 4 512 12
+  is-connection-list add 16 524 12
+  is-connection-list add 28 536 12
+  is-connection-list add 40 548 12
+  trx 0
+   rf_locked 0
+   arfcn 55
+   nominal power 24
+   max_power_red 12
+   rsl e1 line 0 timeslot 1 sub-slot full
+   rsl e1 tei 0
+    timeslot 0
+     phys_chan_config CCCH+SDCCH4
+     hopping enabled 0
+     e1 line 0 timeslot 1 sub-slot full
+    timeslot 1
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 2 sub-slot 1
+    timeslot 2
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 2 sub-slot 2
+    timeslot 3
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 2 sub-slot 3
+    timeslot 4
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 3 sub-slot 0
+    timeslot 5
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 3 sub-slot 1
+    timeslot 6
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 3 sub-slot 2
+    timeslot 7
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 3 sub-slot 3
+  trx 1
+   rf_locked 0
+   arfcn 57
+   nominal power 24
+   max_power_red 12
+   rsl e1 line 0 timeslot 4 sub-slot full
+   rsl e1 tei 1
+    timeslot 0
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 5 sub-slot 0
+    timeslot 1
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 5 sub-slot 1
+    timeslot 2
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 5 sub-slot 2
+    timeslot 3
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 5 sub-slot 3
+    timeslot 4
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 6 sub-slot 0
+    timeslot 5
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 6 sub-slot 1
+    timeslot 6
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 6 sub-slot 2
+    timeslot 7
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 6 sub-slot 3
+  trx 2
+   rf_locked 0
+   arfcn 59
+   nominal power 24
+   max_power_red 12
+   rsl e1 line 0 timeslot 7 sub-slot full
+   rsl e1 tei 2
+    timeslot 0
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 8 sub-slot 0
+    timeslot 1
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 8 sub-slot 1
+    timeslot 2
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 8 sub-slot 2
+    timeslot 3
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 8 sub-slot 3
+    timeslot 4
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 9 sub-slot 0
+    timeslot 5
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 9 sub-slot 1
+    timeslot 6
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 9 sub-slot 2
+    timeslot 7
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 9 sub-slot 3
+  trx 3
+   rf_locked 0
+   arfcn 61
+   nominal power 24
+   max_power_red 12
+   rsl e1 line 0 timeslot 10 sub-slot full
+   rsl e1 tei 3
+    timeslot 0
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 11 sub-slot 0
+    timeslot 1
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 11 sub-slot 1
+    timeslot 2
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 11 sub-slot 2
+    timeslot 3
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 11 sub-slot 3
+    timeslot 4
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 12 sub-slot 0
+    timeslot 5
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 12 sub-slot 1
+    timeslot 6
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 12 sub-slot 2
+    timeslot 7
+     phys_chan_config TCH/F
+     hopping enabled 0
+     e1 line 0 timeslot 12 sub-slot 3
+
+e1_input
+ e1_line 0 driver dahdi
diff --git a/git-version-gen b/git-version-gen
new file mode 100755
index 0000000..f2ad4a7
--- /dev/null
+++ b/git-version-gen
@@ -0,0 +1,151 @@
+#!/bin/sh
+# Print a version string.
+scriptversion=2010-01-28.01
+
+# Copyright (C) 2007-2010 Free Software Foundation, Inc.
+#
+# 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/>.
+
+# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
+# It may be run two ways:
+# - from a git repository in which the "git describe" command below
+#   produces useful output (thus requiring at least one signed tag)
+# - from a non-git-repo directory containing a .tarball-version file, which
+#   presumes this script is invoked like "./git-version-gen .tarball-version".
+
+# In order to use intra-version strings in your project, you will need two
+# separate generated version string files:
+#
+# .tarball-version - present only in a distribution tarball, and not in
+#   a checked-out repository.  Created with contents that were learned at
+#   the last time autoconf was run, and used by git-version-gen.  Must not
+#   be present in either $(srcdir) or $(builddir) for git-version-gen to
+#   give accurate answers during normal development with a checked out tree,
+#   but must be present in a tarball when there is no version control system.
+#   Therefore, it cannot be used in any dependencies.  GNUmakefile has
+#   hooks to force a reconfigure at distribution time to get the value
+#   correct, without penalizing normal development with extra reconfigures.
+#
+# .version - present in a checked-out repository and in a distribution
+#   tarball.  Usable in dependencies, particularly for files that don't
+#   want to depend on config.h but do want to track version changes.
+#   Delete this file prior to any autoconf run where you want to rebuild
+#   files to pick up a version string change; and leave it stale to
+#   minimize rebuild time after unrelated changes to configure sources.
+#
+# It is probably wise to add these two files to .gitignore, so that you
+# don't accidentally commit either generated file.
+#
+# Use the following line in your configure.ac, so that $(VERSION) will
+# automatically be up-to-date each time configure is run (and note that
+# since configure.ac no longer includes a version string, Makefile rules
+# should not depend on configure.ac for version updates).
+#
+# AC_INIT([GNU project],
+#         m4_esyscmd([build-aux/git-version-gen .tarball-version]),
+#         [bug-project@example])
+#
+# Then use the following lines in your Makefile.am, so that .version
+# will be present for dependencies, and so that .tarball-version will
+# exist in distribution tarballs.
+#
+# BUILT_SOURCES = $(top_srcdir)/.version
+# $(top_srcdir)/.version:
+#	echo $(VERSION) > $@-t && mv $@-t $@
+# dist-hook:
+#	echo $(VERSION) > $(distdir)/.tarball-version
+
+case $# in
+    1) ;;
+    *) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"; exit 1;;
+esac
+
+tarball_version_file=$1
+nl='
+'
+
+# First see if there is a tarball-only version file.
+# then try "git describe", then default.
+if test -f $tarball_version_file
+then
+    v=`cat $tarball_version_file` || exit 1
+    case $v in
+	*$nl*) v= ;; # reject multi-line output
+	[0-9]*) ;;
+	*) v= ;;
+    esac
+    test -z "$v" \
+	&& echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2
+fi
+
+if test -n "$v"
+then
+    : # use $v
+elif test -d ./../.git \
+    && v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
+	  || git describe --abbrev=4 HEAD 2>/dev/null` \
+    && case $v in
+	 [0-9]*) ;;
+	 v[0-9]*) ;;
+	 *) (exit 1) ;;
+       esac
+then
+    # Is this a new git that lists number of commits since the last
+    # tag or the previous older version that did not?
+    #   Newer: v6.10-77-g0f8faeb
+    #   Older: v6.10-g0f8faeb
+    case $v in
+	*-*-*) : git describe is okay three part flavor ;;
+	*-*)
+	    : git describe is older two part flavor
+	    # Recreate the number of commits and rewrite such that the
+	    # result is the same as if we were using the newer version
+	    # of git describe.
+	    vtag=`echo "$v" | sed 's/-.*//'`
+	    numcommits=`git rev-list "$vtag"..HEAD | wc -l`
+	    v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
+	    ;;
+    esac
+
+    # Change the first '-' to a '.', so version-comparing tools work properly.
+    # Remove the "g" in git describe's output string, to save a byte.
+    v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
+else
+    v=UNKNOWN
+fi
+
+v=`echo "$v" |sed 's/^v//'`
+
+# Don't declare a version "dirty" merely because a time stamp has changed.
+git status > /dev/null 2>&1
+
+dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
+case "$dirty" in
+    '') ;;
+    *) # Append the suffix only if there isn't one already.
+	case $v in
+	  *-dirty) ;;
+	  *) v="$v-dirty" ;;
+	esac ;;
+esac
+
+# Omit the trailing newline, so that m4_esyscmd can use the result directly.
+echo "$v" | tr -d '\012'
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/include/Makefile.in b/include/Makefile.in
index ecbeebe..1d7fb81 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -36,7 +36,7 @@
 DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
 	$(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -126,6 +126,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
diff --git a/include/openbsc/Makefile.am b/include/openbsc/Makefile.am
index 325d66d..9ec92c1 100644
--- a/include/openbsc/Makefile.am
+++ b/include/openbsc/Makefile.am
@@ -11,7 +11,8 @@
 		gb_proxy.h gprs_sgsn.h gsm_04_08_gprs.h sgsn.h \
 		gprs_ns_frgre.h auth.h osmo_msc.h bsc_msc.h bsc_nat.h \
 		osmo_bsc_rf.h osmo_bsc.h network_listen.h bsc_nat_sccp.h \
-		osmo_msc_data.h osmo_bsc_grace.h sms_queue.h abis_om2000.h
+		osmo_msc_data.h osmo_bsc_grace.h sms_queue.h abis_om2000.h \
+		bss.h gsm_data_shared.h
 
 openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h
 openbscdir = $(includedir)/openbsc
diff --git a/include/openbsc/Makefile.in b/include/openbsc/Makefile.in
index faca5a3..8d61f4a 100644
--- a/include/openbsc/Makefile.in
+++ b/include/openbsc/Makefile.in
@@ -36,7 +36,7 @@
 DIST_COMMON = $(noinst_HEADERS) $(openbsc_HEADERS) \
 	$(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -110,6 +110,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -191,7 +193,8 @@
 		gb_proxy.h gprs_sgsn.h gsm_04_08_gprs.h sgsn.h \
 		gprs_ns_frgre.h auth.h osmo_msc.h bsc_msc.h bsc_nat.h \
 		osmo_bsc_rf.h osmo_bsc.h network_listen.h bsc_nat_sccp.h \
-		osmo_msc_data.h osmo_bsc_grace.h sms_queue.h abis_om2000.h
+		osmo_msc_data.h osmo_bsc_grace.h sms_queue.h abis_om2000.h \
+		bss.h gsm_data_shared.h
 
 openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h
 openbscdir = $(includedir)/openbsc
diff --git a/include/openbsc/abis_nm.h b/include/openbsc/abis_nm.h
index c93db58..ae4f625 100644
--- a/include/openbsc/abis_nm.h
+++ b/include/openbsc/abis_nm.h
@@ -22,15 +22,15 @@
 #ifndef _NM_H
 #define _NM_H
 
-#include <sys/types.h>
-#include <osmocore/tlv.h>
-#include <osmocore/protocol/gsm_12_21.h>
+#include <osmocom/gsm/tlv.h>
+#include <osmocom/gsm/abis_nm.h>
+#include <osmocom/gsm/protocol/gsm_12_21.h>
 
 struct cell_global_id {
-	u_int16_t mcc;
-	u_int16_t mnc;
-	u_int16_t lac;
-	u_int16_t ci;
+	uint16_t mcc;
+	uint16_t mnc;
+	uint16_t lac;
+	uint16_t ci;
 };
 
 /* The BCCH info from an ip.access test, in host byte order
@@ -38,26 +38,22 @@
 struct ipac_bcch_info {
 	struct llist_head list;
 
-	u_int16_t info_type;
-	u_int8_t freq_qual;
-	u_int16_t arfcn;
-	u_int8_t rx_lev;
-	u_int8_t rx_qual;
+	uint16_t info_type;
+	uint8_t freq_qual;
+	uint16_t arfcn;
+	uint8_t rx_lev;
+	uint8_t rx_qual;
 	int16_t freq_err;
-	u_int16_t frame_offset;
-	u_int32_t frame_nr_offset;
-	u_int8_t bsic;
+	uint16_t frame_offset;
+	uint32_t frame_nr_offset;
+	uint8_t bsic;
 	struct cell_global_id cgi;
-	u_int8_t ba_list_si2[16];
-	u_int8_t ba_list_si2bis[16];
-	u_int8_t ba_list_si2ter[16];
-	u_int8_t ca_list_si1[16];
+	uint8_t ba_list_si2[16];
+	uint8_t ba_list_si2bis[16];
+	uint8_t ba_list_si2ter[16];
+	uint8_t ca_list_si1[16];
 };
 
-extern const struct value_string abis_nm_adm_state_names[];
-extern const struct value_string abis_nm_obj_class_names[];
-extern const struct tlv_definition nm_att_tlvdef;
-
 /* PUBLIC */
 
 struct msgb;
@@ -72,60 +68,58 @@
 
 extern int abis_nm_rcvmsg(struct msgb *msg);
 
-int abis_nm_tlv_parse(struct tlv_parsed *tp, struct gsm_bts *bts, const u_int8_t *buf, int len);
+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, u_int8_t obj_class, u_int8_t i0, u_int8_t i1, u_int8_t i2);
-int abis_nm_chg_adm_state(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i0,
-			  u_int8_t i1, u_int8_t i2, enum abis_nm_adm_state adm_state);
-int abis_nm_establish_tei(struct gsm_bts *bts, u_int8_t trx_nr,
-			  u_int8_t e1_port, u_int8_t e1_timeslot, u_int8_t e1_subslot,
-			  u_int8_t tei);
+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,
-			   u_int8_t e1_port, u_int8_t e1_timeslot, u_int8_t e1_subslot);
+			   uint8_t e1_port, uint8_t e1_timeslot, uint8_t e1_subslot);
 int abis_nm_conn_terr_traf(struct gsm_bts_trx_ts *ts,
-			   u_int8_t e1_port, u_int8_t e1_timeslot,
-			   u_int8_t e1_subslot);
-int abis_nm_set_bts_attr(struct gsm_bts *bts, u_int8_t *attr, int attr_len);
-int abis_nm_set_radio_attr(struct gsm_bts_trx *trx, u_int8_t *attr, int attr_len);
-int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, u_int8_t chan_comb);
-int abis_nm_sw_act_req_ack(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i1,
-			u_int8_t i2, u_int8_t i3, int nack, u_int8_t *attr, int att_len);
-int abis_nm_raw_msg(struct gsm_bts *bts, int len, u_int8_t *msg);
+			   uint8_t e1_port, uint8_t e1_timeslot,
+			   uint8_t e1_subslot);
+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,
-			  u_int8_t win_size, int forced,
+			  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, u_int8_t e1_port0, u_int8_t ts0,
-			    u_int8_t e1_port1, u_int8_t ts1);
+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, u_int8_t obj_class,
-			 u_int8_t bts_nr, u_int8_t trx_nr, u_int8_t ts_nr,
-			 u_int8_t test_nr, u_int8_t auton_report, struct msgb *msg);
-
-int abis_nm_chcomb4pchan(enum gsm_phys_chan_config pchan);
+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,
-			  u_int8_t idx, u_int8_t attr_len, const u_int8_t *attr);
-int abis_nm_bs11_create_envaBTSE(struct gsm_bts *bts, u_int8_t idx);
-int abis_nm_bs11_create_bport(struct gsm_bts *bts, u_int8_t idx);
+			  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, u_int8_t idx);
-int abis_nm_bs11_delete_bport(struct gsm_bts *bts, u_int8_t idx);
-int abis_nm_bs11_conn_oml_tei(struct gsm_bts *bts, u_int8_t e1_port,
-			  u_int8_t e1_timeslot, u_int8_t e1_subslot, u_int8_t tei);
+				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, u_int8_t level);
+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, u_int8_t level, const char *name, int on);
+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);
@@ -135,33 +129,31 @@
 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,
-			  u_int8_t win_size, int forced, gsm_cbfn *cbfn);
+			  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, u_int8_t bport);
-int abis_nm_bs11_set_bport_line_cfg(struct gsm_bts *bts, u_int8_t bport, enum abis_bs11_line_cfg line_cfg);
+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, u_int8_t msg_type,
-			 u_int8_t obj_class, u_int8_t bts_nr,
-			 u_int8_t trx_nr, u_int8_t ts_nr,
-			 u_int8_t *attr, int attr_len);
-int abis_nm_ipaccess_set_nvattr(struct gsm_bts_trx *trx, u_int8_t *attr,
+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, u_int8_t obj_class,
-				u_int8_t bts_nr, u_int8_t trx_nr, u_int8_t ts_nr,
-				u_int8_t *attr, u_int8_t attr_len);
+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, 
-				 u_int32_t ip, u_int16_t port, u_int8_t stream);
-void abis_nm_ipaccess_cgi(u_int8_t *buf, struct gsm_bts *bts);
-int ipac_parse_bcch_info(struct ipac_bcch_info *binf, u_int8_t *buf);
-const char *ipacc_testres_name(u_int8_t res);
+				 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 */
-const char *nm_opstate_name(u_int8_t os);
-const char *nm_avail_name(u_int8_t avail);
 int nm_is_running(struct gsm_nm_state *s);
 
 int abis_nm_vty_init(void);
diff --git a/include/openbsc/abis_om2000.h b/include/openbsc/abis_om2000.h
index e4f19cf..2ff7270 100644
--- a/include/openbsc/abis_om2000.h
+++ b/include/openbsc/abis_om2000.h
@@ -34,6 +34,13 @@
 	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,
+};
+
 struct abis_om2k_mo {
 	uint8_t class;
 	uint8_t bts;
@@ -41,12 +48,26 @@
 	uint8_t inst;
 } __attribute__ ((packed));
 
+/* 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;
+};
+
+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);
@@ -63,8 +84,7 @@
 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_is_conf_req(struct gsm_bts *bts, struct om2k_is_conn_grp *cg,
-			     unsigned int num_cg);
+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);
diff --git a/include/openbsc/abis_rsl.h b/include/openbsc/abis_rsl.h
index 295b01f..3b4df90 100644
--- a/include/openbsc/abis_rsl.h
+++ b/include/openbsc/abis_rsl.h
@@ -22,9 +22,9 @@
 #ifndef _RSL_H
 #define _RSL_H
 
-#include <osmocore/protocol/gsm_08_58.h>
+#include <osmocom/gsm/protocol/gsm_08_58.h>
 
-#include <osmocore/msgb.h>
+#include <osmocom/core/msgb.h>
 
 struct gsm_bts;
 struct gsm_lchan;
@@ -32,61 +32,56 @@
 struct gsm_bts_trx_ts;
 
 
-int rsl_bcch_info(struct gsm_bts_trx *trx, u_int8_t type,
-		  const u_int8_t *data, int len);
-int rsl_sacch_filling(struct gsm_bts_trx *trx, u_int8_t type, 
-		      const u_int8_t *data, int len);
-int rsl_chan_activate(struct gsm_bts_trx *trx, u_int8_t chan_nr,
-		      u_int8_t act_type,
+int rsl_bcch_info(struct gsm_bts_trx *trx, uint8_t 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,
-		      u_int8_t bs_power, u_int8_t ms_power,
-		      u_int8_t ta);
-int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type, 
-			    u_int8_t ta, u_int8_t ho_ref);
+		      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 ta, 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, u_int8_t paging_group, u_int8_t len,
-		   u_int8_t *ms_ident, u_int8_t chan_needed);
-int rsl_imm_assign_cmd(struct gsm_bts *bts, u_int8_t len, u_int8_t *val);
+int rsl_paging_cmd(struct gsm_bts *bts, uint8_t paging_group, uint8_t len,
+		   uint8_t *ms_ident, uint8_t chan_needed);
+int rsl_imm_assign_cmd(struct gsm_bts *bts, uint8_t len, uint8_t *val);
 
-int rsl_data_request(struct msgb *msg, u_int8_t link_id);
-int rsl_establish_request(struct gsm_lchan *lchan, u_int8_t link_id);
-int rsl_relase_request(struct gsm_lchan *lchan, u_int8_t link_id);
+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);
 
 /* 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, u_int32_t ip,
-		   u_int16_t port, u_int8_t rtp_payload2);
+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);
 
-unsigned int get_paging_group(u_int64_t imsi, unsigned int bs_cc_chans,
-			      int n_pag_blocks);
-unsigned int n_pag_blocks(int bs_ccch_sdcch_comb, unsigned int bs_ag_blks_res);
-u_int64_t str_to_imsi(const char *imsi_str);
-u_int8_t lchan2chan_nr(const struct gsm_lchan *lchan);
-int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id, u_int8_t reason);
+uint64_t str_to_imsi(const char *imsi_str);
+int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id, uint8_t reason);
 
 int rsl_lchan_set_state(struct gsm_lchan *lchan, int);
 
 /* to be provided by external code */
 int abis_rsl_sendmsg(struct msgb *msg);
 int rsl_deact_sacch(struct gsm_lchan *lchan);
-int rsl_lchan_rll_release(struct gsm_lchan *lchan, u_int8_t link_id);
+int rsl_lchan_rll_release(struct gsm_lchan *lchan, uint8_t link_id);
 
 /* 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_number_of_paging_subchannels(struct gsm_bts *bts);
 
-int rsl_sacch_info_modify(struct gsm_lchan *lchan, u_int8_t type,
-			  const u_int8_t *data, int len);
+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);
diff --git a/include/openbsc/bsc_msc.h b/include/openbsc/bsc_msc.h
index d06ae05..9543002 100644
--- a/include/openbsc/bsc_msc.h
+++ b/include/openbsc/bsc_msc.h
@@ -22,25 +22,33 @@
 #ifndef BSC_MSC_H
 #define BSC_MSC_H
 
-#include <osmocore/write_queue.h>
-#include <osmocore/timer.h>
+#include <osmocom/core/write_queue.h>
+#include <osmocom/core/timer.h>
+
+struct bsc_msc_dest {
+	struct llist_head list;
+
+	char *ip;
+	int port;
+	int dscp;
+};
+
 
 struct bsc_msc_connection {
-	struct write_queue write_queue;
+	struct osmo_wqueue write_queue;
 	int is_connected;
 	int is_authenticated;
 	int first_contact;
-	const char *ip;
-	int port;
-	int prio;
+
+	struct llist_head *dests;
 
 	void (*connection_loss) (struct bsc_msc_connection *);
 	void (*connected) (struct bsc_msc_connection *);
-	struct timer_list reconnect_timer;
-	struct timer_list timeout_timer;
+	struct osmo_timer_list reconnect_timer;
+	struct osmo_timer_list timeout_timer;
 };
 
-struct bsc_msc_connection *bsc_msc_create(const char *ip, int port, int prio);
+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 *);
 
diff --git a/include/openbsc/bsc_nat.h b/include/openbsc/bsc_nat.h
index f74cae2..97fa4fe 100644
--- a/include/openbsc/bsc_nat.h
+++ b/include/openbsc/bsc_nat.h
@@ -1,6 +1,6 @@
 /*
- * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010 by On-Waves
+ * (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
@@ -23,22 +23,23 @@
 
 #include "mgcp.h"
 
-#include <sys/types.h>
 
-#include <osmocore/select.h>
-#include <osmocore/msgb.h>
-#include <osmocore/msgfile.h>
-#include <osmocore/timer.h>
-#include <osmocore/write_queue.h>
-#include <osmocore/rate_ctr.h>
-#include <osmocore/statistics.h>
-#include <osmocore/protocol/gsm_04_08.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>
 
 #define DIR_BSC 1
 #define DIR_MSC 2
 
+#define PAGIN_GROUP_UNASSIGNED -1
+
 struct sccp_source_reference;
 struct sccp_connections;
 struct bsc_nat_parsed;
@@ -56,6 +57,16 @@
 };
 
 /*
+ * 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,
+};
+
+/*
  * Per BSC data structure
  */
 struct bsc_connection {
@@ -65,17 +76,17 @@
 	int authenticated;
 
 	/* the fd we use to communicate */
-	struct write_queue write_queue;
+	struct osmo_wqueue write_queue;
 
 	/* the BSS associated */
 	struct bsc_config *cfg;
 
 	/* a timeout node */
-	struct timer_list id_timeout;
+	struct osmo_timer_list id_timeout;
 
 	/* pong timeout */
-	struct timer_list ping_timeout;
-	struct timer_list pong_timeout;
+	struct osmo_timer_list ping_timeout;
+	struct osmo_timer_list pong_timeout;
 
 	/* mgcp related code */
 	char *_endpoint_status;
@@ -125,6 +136,7 @@
 	char *acc_lst_name;
 
 	int forbid_paging;
+	int paging_group;
 
 	/* audio handling */
 	int max_endpoints;
@@ -142,6 +154,14 @@
 	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
  */
@@ -159,21 +179,21 @@
  */
 struct bsc_nat_statistics {
 	struct {
-		struct counter *conn;
-		struct counter *calls;
+		struct osmo_counter *conn;
+		struct osmo_counter *calls;
 	} sccp;
 
 	struct {
-		struct counter *reconn;
-                struct counter *auth_fail;
+		struct osmo_counter *reconn;
+                struct osmo_counter *auth_fail;
 	} bsc;
 
 	struct {
-		struct counter *reconn;
+		struct osmo_counter *reconn;
 	} msc;
 
 	struct {
-		struct counter *reconn;
+		struct osmo_counter *reconn;
 	} ussd;
 };
 
@@ -216,6 +236,9 @@
 	/* 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;
@@ -227,8 +250,8 @@
 	int mgcp_length;
 
 	/* msc things */
-	char *msc_ip;
-	int msc_port;
+	struct llist_head dests;
+	struct bsc_msc_dest *main_dest;
 	struct bsc_msc_connection *msc_con;
 	char *token;
 
@@ -244,20 +267,37 @@
 
 	/* number rewriting */
 	char *num_rewr_name;
-	struct msg_entries *num_rewr;
+	struct llist_head num_rewr;
+
+	char *smsc_rewr_name;
+	struct llist_head smsc_rewr;
+	char *tpdest_match_name;
+	struct llist_head tpdest_match;
 
 	/* 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 bsc_fd ussd_listen;
+	struct osmo_fd ussd_listen;
 	struct bsc_nat_ussd_con *ussd_con;
 
+	/* for maintainenance */
+	int blocked;
+
 	/* statistics */
 	struct bsc_nat_statistics stats;
 };
 
+struct bsc_nat_ussd_con {
+	struct osmo_wqueue queue;
+	struct bsc_nat *nat;
+	int authorized;
+
+	struct osmo_timer_list auth_timeout;
+};
+
 /* create and init the structures */
 struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token);
 struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num);
@@ -285,7 +325,7 @@
  */
 int bsc_nat_filter_ipa(int direction, struct msgb *msg, struct bsc_nat_parsed *parsed);
 int bsc_nat_vty_init(struct bsc_nat *nat);
-struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg, int *_lac);
+int bsc_nat_find_paging(struct msgb *msg, const uint8_t **,int *len);
 
 /**
  * Content filtering.
@@ -326,12 +366,12 @@
 
 
 int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int id);
-int bsc_do_write(struct write_queue *queue, struct msgb *msg, int id);
-int bsc_write_msg(struct write_queue *queue, struct msgb *msg);
-int bsc_write_cb(struct bsc_fd *bfd, struct msgb *msg);
+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);
 
 /* IMSI allow/deny handling */
-void bsc_parse_reg(void *ctx, regex_t *reg, char **imsi, int argc, const char **argv);
+int bsc_parse_reg(void *ctx, regex_t *reg, char **imsi, int argc, const char **argv) __attribute__ ((warn_unused_result));
 struct bsc_nat_acc_lst *bsc_nat_acc_lst_find(struct bsc_nat *nat, const char *name);
 struct bsc_nat_acc_lst *bsc_nat_acc_lst_get(struct bsc_nat *nat, const char *name);
 void bsc_nat_acc_lst_delete(struct bsc_nat_acc_lst *lst);
@@ -350,6 +390,27 @@
 int bsc_check_ussd(struct sccp_connections *con, struct bsc_nat_parsed *parsed, struct msgb *msg);
 int bsc_close_ussd_connections(struct bsc_nat *nat);
 
-struct msgb *bsc_nat_rewrite_setup(struct bsc_nat *nat, struct msgb *msg, struct bsc_nat_parsed *, const char *imsi);
+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;
+};
+
+void bsc_nat_num_rewr_entry_adapt(void *ctx, struct llist_head *head, const struct osmo_config_list *);
 
 #endif
diff --git a/include/openbsc/bsc_nat_sccp.h b/include/openbsc/bsc_nat_sccp.h
index 0ade668..20db2c1 100644
--- a/include/openbsc/bsc_nat_sccp.h
+++ b/include/openbsc/bsc_nat_sccp.h
@@ -22,7 +22,6 @@
 #ifndef BSC_NAT_SCCP_H
 #define BSC_NAT_SCCP_H
 
-#include <sys/types.h>
 #include <osmocom/sccp/sccp_types.h>
 
 /*
@@ -77,9 +76,13 @@
 	/* status */
 	int con_type;
 	int con_local;
+	int authorized;
 	int imsi_checked;
 	char *imsi;
 
+	/* 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.
diff --git a/include/openbsc/bsc_rll.h b/include/openbsc/bsc_rll.h
index b2898d1..729ba60 100644
--- a/include/openbsc/bsc_rll.h
+++ b/include/openbsc/bsc_rll.h
@@ -10,10 +10,10 @@
 	BSC_RLLR_IND_TIMEOUT,
 };
 
-int rll_establish(struct gsm_lchan *lchan, u_int8_t link_id,
-		  void (*cb)(struct gsm_lchan *, u_int8_t, void *,
+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, u_int8_t link_id, u_int8_t type);
+void rll_indication(struct gsm_lchan *lchan, uint8_t link_id, uint8_t type);
 
 #endif /* _BSC_RLL_H */
diff --git a/include/openbsc/bss.h b/include/openbsc/bss.h
new file mode 100644
index 0000000..05495dd
--- /dev/null
+++ b/include/openbsc/bss.h
@@ -0,0 +1,17 @@
+#ifndef _BSS_H_
+#define _BSS_H_
+
+struct gsm_network;
+struct msgb;
+
+/* start and stop network */
+extern int bsc_bootstrap_network(int (*mncc_recv)(struct gsm_network *, struct msgb *), 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_hslfemto_init(void);
+#endif
diff --git a/include/openbsc/crc24.h b/include/openbsc/crc24.h
index 358fcb5..756638c 100644
--- a/include/openbsc/crc24.h
+++ b/include/openbsc/crc24.h
@@ -1,8 +1,10 @@
 #ifndef _CRC24_H
 #define _CRC24_H
 
+#include <stdint.h>
+
 #define INIT_CRC24	0xffffff
 
-u_int32_t crc24_calc(u_int32_t fcs, u_int8_t *cp, unsigned int len);
+uint32_t crc24_calc(uint32_t fcs, uint8_t *cp, unsigned int len);
 
 #endif
diff --git a/include/openbsc/db.h b/include/openbsc/db.h
index a939b0d..37011a1 100644
--- a/include/openbsc/db.h
+++ b/include/openbsc/db.h
@@ -20,7 +20,7 @@
 #ifndef _DB_H
 #define _DB_H
 
-#include <sys/types.h>
+#include "gsm_subscriber.h"
 
 struct gsm_equipment;
 struct gsm_network;
@@ -29,8 +29,6 @@
 struct gsm_sms;
 struct gsm_subscriber;
 
-enum gsm_subscriber_field;
-
 /* one time initialisation */
 int db_init(const char *name);
 int db_prepare();
@@ -45,7 +43,7 @@
 int db_sync_subscriber(struct gsm_subscriber *subscriber);
 int db_subscriber_alloc_tmsi(struct gsm_subscriber *subscriber);
 int db_subscriber_alloc_exten(struct gsm_subscriber *subscriber);
-int db_subscriber_alloc_token(struct gsm_subscriber *subscriber, u_int32_t* token);
+int db_subscriber_alloc_token(struct gsm_subscriber *subscriber, uint32_t* token);
 int db_subscriber_assoc_imei(struct gsm_subscriber *subscriber, char *imei);
 int db_sync_equipment(struct gsm_equipment *equip);
 int db_subscriber_update(struct gsm_subscriber *subscriber);
@@ -71,12 +69,12 @@
 
 /* APDU blob storage */
 int db_apdu_blob_store(struct gsm_subscriber *subscr, 
-			u_int8_t apdu_id_flags, u_int8_t len,
-			u_int8_t *apdu);
+			uint8_t apdu_id_flags, uint8_t len,
+			uint8_t *apdu);
 
 /* Statistics counter storage */
-struct counter;
-int db_store_counter(struct counter *ctr);
+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);
 
diff --git a/include/openbsc/debug.h b/include/openbsc/debug.h
index eb290e4..ff4aec1 100644
--- a/include/openbsc/debug.h
+++ b/include/openbsc/debug.h
@@ -2,10 +2,10 @@
 #define _DEBUG_H
 
 #include <stdio.h>
-#include <osmocore/linuxlist.h>
+#include <osmocom/core/linuxlist.h>
 
 #define DEBUG
-#include <osmocore/logging.h>
+#include <osmocom/core/logging.h>
 
 /* Debug Areas of the code */
 enum {
diff --git a/include/openbsc/e1_input.h b/include/openbsc/e1_input.h
index 3c8af38..0d79c7d 100644
--- a/include/openbsc/e1_input.h
+++ b/include/openbsc/e1_input.h
@@ -4,10 +4,10 @@
 #include <stdlib.h>
 #include <netinet/in.h>
 
-#include <osmocore/linuxlist.h>
+#include <osmocom/core/linuxlist.h>
 #include <openbsc/gsm_data.h>
-#include <osmocore/msgb.h>
-#include <osmocore/select.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/select.h>
 #include <openbsc/subchan_demux.h>
 
 #define NUM_E1_TS   32
@@ -37,12 +37,12 @@
 	struct llist_head tx_list;
 
 	/* SAPI and TEI on the E1 TS */
-	u_int8_t sapi;
-	u_int8_t tei;
+	uint8_t sapi;
+	uint8_t tei;
 
 	union {
 		struct {
-			u_int8_t channel;
+			uint8_t channel;
 		} misdn;
 	} driver;
 };
@@ -69,7 +69,7 @@
 			/* delay for the queue */
 			int delay;
 			/* timer when to dequeue next frame */
-			struct timer_list tx_timer;
+			struct osmo_timer_list tx_timer;
 		} sign;
 		struct {
 			/* subchannel demuxer for frames from E1 */
@@ -81,15 +81,15 @@
 	union {
 		struct {
 			/* mISDN driver has one fd for each ts */
-			struct bsc_fd fd;
+			struct osmo_fd fd;
 		} misdn;
 		struct {
 			/* ip.access driver has one fd for each ts */
-			struct bsc_fd fd;
+			struct osmo_fd fd;
 		} ipaccess;
 		struct {
 			/* DAHDI driver has one fd for each ts */
-			struct bsc_fd fd;
+			struct osmo_fd fd;
 			struct lapd_instance *lapd;
 		} dahdi;
 	} driver;
@@ -125,21 +125,21 @@
 int e1inp_line_register(struct e1inp_line *line);
 
 /* get a line by its ID */
-struct e1inp_line *e1inp_line_get(u_int8_t e1_nr);
+struct e1inp_line *e1inp_line_get(uint8_t e1_nr);
 
 /* create a line in the E1 input core */
-struct e1inp_line *e1inp_line_create(u_int8_t e1_nr, const char *driver_name);
+struct e1inp_line *e1inp_line_create(uint8_t e1_nr, const char *driver_name);
 
 /* find a sign_link for given TEI and SAPI in a TS */
 struct e1inp_sign_link *
-e1inp_lookup_sign_link(struct e1inp_ts *ts, u_int8_t tei,
-			u_int8_t sapi);
+e1inp_lookup_sign_link(struct e1inp_ts *ts, uint8_t tei,
+			uint8_t sapi);
 
 /* create a new signalling link in a E1 timeslot */
 struct e1inp_sign_link *
 e1inp_sign_link_create(struct e1inp_ts *ts, enum e1inp_sign_type type,
-			struct gsm_bts_trx *trx, u_int8_t tei,
-			u_int8_t sapi);
+			struct gsm_bts_trx *trx, uint8_t tei,
+			uint8_t sapi);
 
 /* configure and initialize one e1inp_ts */
 int e1inp_ts_config(struct e1inp_ts *ts, struct e1inp_line *line,
@@ -150,20 +150,20 @@
 
 /* Receive a packet from the E1 driver */
 int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg,
-		u_int8_t tei, u_int8_t sapi);
+		uint8_t tei, uint8_t sapi);
 
 /* called by driver if it wants to transmit on a given TS */
 struct msgb *e1inp_tx_ts(struct e1inp_ts *e1i_ts,
 			 struct e1inp_sign_link **sign_link);
 
 /* called by driver in case some kind of link state event */
-int e1inp_event(struct e1inp_ts *ts, int evt, u_int8_t tei, u_int8_t sapi);
+int e1inp_event(struct e1inp_ts *ts, int evt, uint8_t tei, uint8_t sapi);
 
 /* Write LAPD frames to the fd. */
 void e1_set_pcap_fd(int fd);
 
 /* called by TRAU muxer to obtain the destination mux entity */
-struct subch_mux *e1inp_get_mux(u_int8_t e1_nr, u_int8_t ts_nr);
+struct subch_mux *e1inp_get_mux(uint8_t e1_nr, uint8_t ts_nr);
 
 void e1inp_sign_link_destroy(struct e1inp_sign_link *link);
 int e1inp_line_update(struct e1inp_line *line);
@@ -175,6 +175,7 @@
 
 int ia_config_connect(struct gsm_bts *bts, struct sockaddr_in *sin);
 int ipaccess_setup(struct gsm_network *gsmnet);
+int hsl_setup(struct gsm_network *gsmnet);
 
 extern struct llist_head e1inp_driver_list;
 extern struct llist_head e1inp_line_list;
diff --git a/include/openbsc/gb_proxy.h b/include/openbsc/gb_proxy.h
index 18ded22..c0cdcbf 100644
--- a/include/openbsc/gb_proxy.h
+++ b/include/openbsc/gb_proxy.h
@@ -1,16 +1,15 @@
 #ifndef _GB_PROXY_H
 #define _GB_PROXY_H
 
-#include <sys/types.h>
 
-#include <osmocore/msgb.h>
+#include <osmocom/core/msgb.h>
 
 #include <openbsc/gprs_ns.h>
 #include <osmocom/vty/command.h>
 
 struct gbproxy_config {
 	/* parsed from config file */
-	u_int16_t nsip_sgsn_nsei;
+	uint16_t nsip_sgsn_nsei;
 
 	/* misc */
 	struct gprs_ns_inst *nsi;
diff --git a/include/openbsc/gprs_bssgp.h b/include/openbsc/gprs_bssgp.h
index e432cf7..cef4c30 100644
--- a/include/openbsc/gprs_bssgp.h
+++ b/include/openbsc/gprs_bssgp.h
@@ -182,7 +182,7 @@
 /* Find a BTS context based on BVCI+NSEI tuple */
 struct bssgp_bvc_ctx *btsctx_by_bvci_nsei(uint16_t bvci, uint16_t nsei);
 
-#include <osmocore/tlv.h>
+#include <osmocom/gsm/tlv.h>
 
 /* BSSGP-UL-UNITDATA.ind */
 int gprs_bssgp_rcvmsg(struct msgb *msg);
diff --git a/include/openbsc/gprs_gmm.h b/include/openbsc/gprs_gmm.h
index bd129ae..f6b3e5e 100644
--- a/include/openbsc/gprs_gmm.h
+++ b/include/openbsc/gprs_gmm.h
@@ -1,7 +1,7 @@
 #ifndef _GPRS_GMM_H
 #define _GPRS_GMM_H
 
-#include <osmocore/msgb.h>
+#include <osmocom/core/msgb.h>
 #include <openbsc/gprs_sgsn.h>
 
 int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause);
diff --git a/include/openbsc/gprs_llc.h b/include/openbsc/gprs_llc.h
index 02945e1..9f17605 100644
--- a/include/openbsc/gprs_llc.h
+++ b/include/openbsc/gprs_llc.h
@@ -99,8 +99,8 @@
 
 	enum gprs_llc_lle_state state;
 
-	struct timer_list t200;
-	struct timer_list t201;	/* wait for acknowledgement */
+	struct osmo_timer_list t200;
+	struct osmo_timer_list t201;	/* wait for acknowledgement */
 
 	uint16_t v_sent;
 	uint16_t v_ack;
diff --git a/include/openbsc/gprs_ns.h b/include/openbsc/gprs_ns.h
index 953c364..8f28d46 100644
--- a/include/openbsc/gprs_ns.h
+++ b/include/openbsc/gprs_ns.h
@@ -77,10 +77,10 @@
 
 /* Our Implementation */
 #include <netinet/in.h>
-#include <osmocore/linuxlist.h>
-#include <osmocore/msgb.h>
-#include <osmocore/timer.h>
-#include <osmocore/select.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/core/select.h>
 
 #define NS_TIMERS_COUNT 7
 #define NS_TIMERS "(tns-block|tns-block-retries|tns-reset|tns-reset-retries|tns-test|tns-alive|tns-alive-retries)"
@@ -133,13 +133,13 @@
 
 	/* NS-over-IP specific bits */
 	struct {
-		struct bsc_fd fd;
+		struct osmo_fd fd;
 		uint32_t local_ip;
 		uint16_t local_port;
 	} nsip;
 	/* NS-over-FR-over-GRE-over-IP specific bits */
 	struct {
-		struct bsc_fd fd;
+		struct osmo_fd fd;
 		uint32_t local_ip;
 		int enabled:1;
 	} frgre;
@@ -163,7 +163,7 @@
 	uint32_t state;
 	uint32_t remote_state;
 
-	struct timer_list timer;
+	struct osmo_timer_list timer;
 	enum nsvc_timer_mode timer_mode;
 	int alive_retries;
 
diff --git a/include/openbsc/gprs_sgsn.h b/include/openbsc/gprs_sgsn.h
index b470c53..5023d06 100644
--- a/include/openbsc/gprs_sgsn.h
+++ b/include/openbsc/gprs_sgsn.h
@@ -4,7 +4,7 @@
 #include <stdint.h>
 #include <netinet/in.h>
 
-#include <osmocore/gsm48.h>
+#include <osmocom/gsm/gsm48.h>
 
 #include <osmocom/crypt/gprs_cipher.h>
 
@@ -102,7 +102,7 @@
 	uint16_t		nsei;
 	uint16_t		bvci;
 	struct rate_ctr_group	*ctrg;
-	struct timer_list	timer;
+	struct osmo_timer_list	timer;
 	unsigned int		T;		/* Txxxx number */
 	unsigned int		num_T_exp;	/* number of consecutive T expirations */
 
@@ -168,7 +168,7 @@
 	//uint32_t		charging_id;
 	int			reordering_reqd;
 
-	struct timer_list	timer;
+	struct osmo_timer_list	timer;
 	unsigned int		T;		/* Txxxx number */
 	unsigned int		num_T_exp;	/* number of consecutive T expirations */
 };
diff --git a/include/openbsc/gsm_04_08.h b/include/openbsc/gsm_04_08.h
index 1c879ed..b9b89e6 100644
--- a/include/openbsc/gsm_04_08.h
+++ b/include/openbsc/gsm_04_08.h
@@ -3,8 +3,8 @@
 
 #include <openbsc/meas_rep.h>
 
-#include <osmocore/protocol/gsm_04_08.h>
-#include <osmocore/gsm48.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/gsm48.h>
 
 struct msgb;
 struct gsm_bts;
@@ -28,37 +28,37 @@
 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, u_int8_t link_id);
+int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id);
 int gsm0408_new_conn(struct gsm_subscriber_connection *conn);
-enum gsm_chan_t get_ctype_by_chreq(struct gsm_network *bts, u_int8_t ra);
-enum gsm_chreq_reason_t get_reason_by_chreq(u_int8_t ra, int neci);
+enum gsm_chan_t get_ctype_by_chreq(struct gsm_network *bts, uint8_t ra);
+enum gsm_chreq_reason_t 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, u_int8_t *rand, int key_seq);
+int gsm48_tx_mm_auth_req(struct gsm_subscriber_connection *conn, uint8_t *rand, int key_seq);
 int gsm48_tx_mm_auth_rej(struct gsm_subscriber_connection *conn);
 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, u_int8_t apdu_id,
-			   u_int8_t apdu_len, const u_int8_t *apdu);
-int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, u_int8_t power_class);
+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,
-		      u_int8_t power_command, u_int8_t ho_ref);
+		      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(u_int8_t *bcd_lv, u_int8_t max_len,
+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 u_int8_t *bcd_lv,
+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, u_int8_t *classmark2_lv);
+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, u_int8_t *mi_type);
+int gsm48_paging_extract_mi(struct gsm48_pag_resp *pag, int length, char *mi_string, uint8_t *mi_type);
 int gsm48_handle_paging_resp(struct gsm_subscriber_connection *conn, struct msgb *msg, struct gsm_subscriber *subscr);
 
-int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode);
+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);
 
diff --git a/include/openbsc/gsm_04_08_gprs.h b/include/openbsc/gsm_04_08_gprs.h
index 8de6362..e5c3edd 100644
--- a/include/openbsc/gsm_04_08_gprs.h
+++ b/include/openbsc/gsm_04_08_gprs.h
@@ -2,7 +2,7 @@
 #define _GSM48_GPRS_H
 
 #include <stdint.h>
-#include <osmocore/protocol/gsm_04_08.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
 
 /* Table 10.4 / 10.4a, GPRS Mobility Management (GMM) */
 #define GSM48_MT_GMM_ATTACH_REQ		0x01
diff --git a/include/openbsc/gsm_04_11.h b/include/openbsc/gsm_04_11.h
index 5969788..2abe3e2 100644
--- a/include/openbsc/gsm_04_11.h
+++ b/include/openbsc/gsm_04_11.h
@@ -1,26 +1,26 @@
 #ifndef _GSM_04_11_H
 #define _GSM_04_11_H
 
-#include <osmocore/protocol/gsm_04_11.h>
+#include <osmocom/gsm/protocol/gsm_04_11.h>
 
 #define UM_SAPI_SMS 3	/* See GSM 04.05/04.06 */
 
 /* SMS deliver PDU */
 struct sms_deliver {
-	u_int8_t mti:2;		/* message type indicator */
-	u_int8_t mms:1;		/* more messages to send */
-	u_int8_t rp:1;		/* reply path */
-	u_int8_t udhi:1;	/* user data header indicator */
-	u_int8_t sri:1;		/* status report indication */
-	u_int8_t *orig_addr;	/* originating address */
-	u_int8_t pid;		/* protocol identifier */
-	u_int8_t dcs;		/* data coding scheme */
+	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 */
-	u_int8_t ud_len;	/* user data length */
-	u_int8_t *user_data;	/* user data */
+	uint8_t ud_len;	/* user data length */
+	uint8_t *user_data;	/* user data */
 
-	u_int8_t msg_ref;	/* message reference */
-	u_int8_t *smsc;
+	uint8_t msg_ref;	/* message reference */
+	uint8_t *smsc;
 };
 
 struct msgb;
diff --git a/include/openbsc/gsm_04_80.h b/include/openbsc/gsm_04_80.h
index 796a1c1..0a60652 100644
--- a/include/openbsc/gsm_04_80.h
+++ b/include/openbsc/gsm_04_80.h
@@ -1,9 +1,9 @@
 #ifndef _GSM_04_80_H
 #define _GSM_04_80_H
 
-#include <osmocore/msgb.h>
-#include <osmocore/protocol/gsm_04_80.h>
-#include <osmocore/gsm0480.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/protocol/gsm_04_80.h>
+#include <osmocom/gsm/gsm0480.h>
 
 struct gsm_subscriber_connection;
 
diff --git a/include/openbsc/gsm_data.h b/include/openbsc/gsm_data.h
index ae448c4..715ff1b 100644
--- a/include/openbsc/gsm_data.h
+++ b/include/openbsc/gsm_data.h
@@ -1,97 +1,12 @@
 #ifndef _GSM_DATA_H
 #define _GSM_DATA_H
 
-#include <sys/types.h>
+#include <stdint.h>
 
-struct osmo_msc_data;
-struct osmo_bsc_sccp_con;
-struct gsm_sms_queue;
+#include <osmocom/core/timer.h>
+#include <osmocom/core/select.h>
 
-enum gsm_phys_chan_config {
-	GSM_PCHAN_NONE,
-	GSM_PCHAN_CCCH,
-	GSM_PCHAN_CCCH_SDCCH4,
-	GSM_PCHAN_TCH_F,
-	GSM_PCHAN_TCH_H,
-	GSM_PCHAN_SDCCH8_SACCH8C,
-	GSM_PCHAN_PDCH,		/* GPRS PDCH */
-	GSM_PCHAN_TCH_F_PDCH,	/* TCH/F if used, PDCH otherwise */
-	GSM_PCHAN_UNKNOWN,
-};
-
-enum gsm_chan_t {
-	GSM_LCHAN_NONE,
-	GSM_LCHAN_SDCCH,
-	GSM_LCHAN_TCH_F,
-	GSM_LCHAN_TCH_H,
-	GSM_LCHAN_UNKNOWN,
-};
-
-/* 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,
-};
-
-#include <osmocore/timer.h>
-#include <openbsc/system_information.h>
 #include <openbsc/rest_octets.h>
-#include <openbsc/mncc.h>
-
-#include <osmocore/tlv.h>
-#include <osmocore/bitvec.h>
-#include <osmocore/statistics.h>
-#include <osmocore/gsm_utils.h>
-#include <osmocore/utils.h>
-#include <osmocore/rxlev_stat.h>
-
-#include <osmocore/protocol/gsm_08_58.h>
-
-
-#define TRX_NR_TS	8
-#define TS_MAX_LCHAN	8
-
-#define HARDCODED_ARFCN 123
-#define HARDCODED_TSC	7
-#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
-
-/* reserved according to GSM 03.03 § 2.4 */
-#define GSM_RESERVED_TMSI   0xFFFFFFFF
-
-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,
-};
 
 #define OBSC_NM_W_ACK_CB(__msgb) (__msgb)->cb[3]
 
@@ -104,11 +19,11 @@
 	unsigned char *bssgp_cell_id;
 
 	/* Identifiers of a BTS, equal to 'struct bssgp_bts_ctx' */
-	u_int16_t nsei;
-	u_int16_t bvci;
+	uint16_t nsei;
+	uint16_t bvci;
 
 	/* Identifier of a MS (inside BTS), equal to 'struct sgsn_mm_ctx' */
-	u_int32_t tlli;
+	uint32_t tlli;
 } __attribute__((packed));
 #define OBSC_MSGB_CB(__msgb)	((struct openbsc_msgb_cb *)&((__msgb)->cb[0]))
 #define msgb_tlli(__x)		OBSC_MSGB_CB(__x)->tlli
@@ -144,32 +59,18 @@
 struct gsm_auth_info {
 	enum gsm_auth_algo auth_algo;
 	unsigned int a3a8_ki_len;
-	u_int8_t a3a8_ki[16];
+	uint8_t a3a8_ki[16];
 };
 
 struct gsm_auth_tuple {
 	int use_count;
 	int key_seq;
-	u_int8_t rand[16];
-	u_int8_t sres[4];
-	u_int8_t kc[8];
+	uint8_t rand[16];
+	uint8_t sres[4];
+	uint8_t kc[8];
 };
 #define GSM_KEY_SEQ_INVAL	7	/* GSM 04.08 - 10.5.1.2 */
 
-
-struct gsm_lchan;
-struct gsm_subscriber;
-struct gsm_mncc;
-struct rtp_socket;
-struct bsc_api;
-
-/* Network Management State */
-struct gsm_nm_state {
-	u_int8_t operational;
-	u_int8_t administrative;
-	u_int8_t availability;
-};
-
 /*
  * LOCATION UPDATING REQUEST state
  *
@@ -178,7 +79,7 @@
  *	- Accept/Reject according to global policy
  */
 struct gsm_loc_updating_operation {
-        struct timer_list updating_timer;
+        struct osmo_timer_list updating_timer;
 	unsigned int waiting_for_imsi : 1;
 	unsigned int waiting_for_imei : 1;
 	unsigned int key_seq : 4;
@@ -198,7 +99,7 @@
  * a couple of seconds to work around MSC issues.
  */
 struct gsm_anchor_operation {
-	struct timer_list timeout;
+	struct osmo_timer_list timeout;
 };
 
 /* Maximum number of neighbor cells whose average we track */
@@ -208,32 +109,11 @@
 
 /* processed neighbor measurements for one cell */
 struct neigh_meas_proc {
-	u_int16_t arfcn;
-	u_int8_t bsic;
-	u_int8_t rxlev[MAX_WIN_NEIGH_AVG];
+	uint16_t arfcn;
+	uint8_t bsic;
+	uint8_t rxlev[MAX_WIN_NEIGH_AVG];
 	unsigned int rxlev_cnt;
-	u_int8_t last_seen_nr;
-};
-
-#define MAX_A5_KEY_LEN	(128/8)
-#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)
-
-/* is the data link established? who established it? */
-#define LCHAN_SAPI_UNUSED	0
-#define LCHAN_SAPI_MS		1
-#define LCHAN_SAPI_NET		2
-
-/* state of a logical channel */
-enum gsm_lchan_state {
-	LCHAN_S_NONE,		/* channel is not active */
-	LCHAN_S_ACT_REQ,	/* channel activatin 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_INACTIVE,	/* channel is set inactive */
+	uint8_t last_seen_nr;
 };
 
 /* the per subscriber data for lchan */
@@ -264,427 +144,65 @@
 	struct gsm_bts *bts;
 
 	/* for assignment handling */
-	struct timer_list T10;
+	struct osmo_timer_list T10;
 	struct gsm_lchan *secondary_lchan;
 
 };
 
-struct gsm_lchan {
-	/* The TS that we're part of */
-	struct gsm_bts_trx_ts *ts;
-	/* The logical subslot number in the TS */
-	u_int8_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;
-	/* State */
-	enum gsm_lchan_state state;
-	/* Power levels for MS and BTS */
-	u_int8_t bs_power;
-	u_int8_t ms_power;
-	/* Encryption information */
-	struct {
-		u_int8_t alg_id;
-		u_int8_t key_len;
-		u_int8_t key[MAX_A5_KEY_LEN];
-	} encr;
 
-	struct timer_list T3101;
-	struct timer_list T3111;
-	struct timer_list error_timer;
+#define ROLE_BSC
+#include "gsm_data_shared.h"
 
-	/* AMR bits */
-	struct gsm48_multi_rate_conf mr_conf;
-	
-	/* Established data link layer services */
-	u_int8_t sapis[8];
-	int sach_deact;
-	int release_reason;
-
-	/* GSM Random Access data */
-	struct gsm48_req_ref *rqd_ref;
-	uint8_t rqd_ta;
-
-	/* cache of last measurement reports on this lchan */
-	struct gsm_meas_rep meas_rep[6];
-	int meas_rep_idx;
-
-	/* table of neighbor cell measurements */
-	struct neigh_meas_proc neigh_meas[MAX_NEIGH_MEAS];
-
-	struct {
-		u_int32_t bound_ip;
-		u_int32_t connect_ip;
-		u_int16_t bound_port;
-		u_int16_t connect_port;
-		u_int16_t conn_id;
-		u_int8_t rtp_payload;
-		u_int8_t rtp_payload2;
-		u_int8_t speech_mode;
-		struct rtp_socket *rtp_socket;
-	} abis_ip;
-
-	struct gsm_subscriber_connection *conn;
-};
-
-struct gsm_e1_subslot {
-	/* Number of E1 link */
-	u_int8_t	e1_nr;
-	/* Number of E1 TS inside E1 link */
-	u_int8_t	e1_ts;
-	/* Sub-slot within the E1 TS, 0xff if full TS */
-	u_int8_t	e1_ts_ss;
-};
-
-#define TS_F_PDCH_MODE	0x1000
-/* One Timeslot in a TRX */
-struct gsm_bts_trx_ts {
-	struct gsm_bts_trx *trx;
-	/* number of this timeslot at the TRX */
-	u_int8_t nr;
-
-	enum gsm_phys_chan_config pchan;
-
-	unsigned int flags;
-	struct gsm_nm_state nm_state;
-	struct tlv_parsed nm_attr;
-	u_int8_t nm_chan_comb;
-
-	struct {
-		/* Parameters below are configured by VTY */
-		int enabled;
-		u_int8_t maio;
-		u_int8_t hsn;
-		struct bitvec arfcns;
-		u_int8_t arfcns_data[1024/8];
-		/* This is the pre-computed MA for channel assignments */
-		struct bitvec ma;
-		u_int8_t ma_len;	/* part of ma_data that is used */
-		u_int8_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;
-
-	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 */
-	u_int8_t nr;
-	/* human readable name / description */
-	char *description;
-	/* how do we talk RSL with this TRX? */
-	struct gsm_e1_subslot rsl_e1_link;
-	u_int8_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_nm_state nm_state;
-	struct tlv_parsed nm_attr;
-	struct {
-		struct gsm_nm_state nm_state;
-	} bb_transc;
-
-	u_int16_t arfcn;
-	int nominal_power;		/* in dBm */
-	unsigned int max_power_red;	/* in actual dB */
-
-	union {
-		struct {
-			struct {
-				struct gsm_nm_state nm_state;
-			} bbsig;
-			struct {
-				struct gsm_nm_state nm_state;
-			} pa;
-		} bs11;
-		struct {
-			unsigned int test_state;
-			u_int8_t test_nr;
-			struct rxlev_stats rxlev_stat;
-		} ipaccess;
-	};
-	struct gsm_bts_trx_ts ts[TRX_NR_TS];
-};
-
-#define GSM_BTS_SI(bts, i)	(void *)(bts->si_buf[i])
-
-enum gsm_bts_type {
-	GSM_BTS_TYPE_UNKNOWN,
-	GSM_BTS_TYPE_BS11,
-	GSM_BTS_TYPE_NANOBTS,
-	GSM_BTS_TYPE_RBS2000,
-	GSM_BTS_TYPE_HSL_FEMTO,
-};
-
-struct vty;
-
-struct gsm_bts_model {
-	struct llist_head list;
-
-	enum gsm_bts_type type;
-	const char *name;
-
-	int (*oml_rcvmsg)(struct msgb *msg);
-
-	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;
-
-	struct bitvec features;
-	uint8_t _features_data[128/8];
-};
-
-enum gsm_bts_features {
-	BTS_FEAT_HSCSD,
-	BTS_FEAT_GPRS,
-	BTS_FEAT_EGPRS,
-	BTS_FEAT_ECSD,
-	BTS_FEAT_HOPPING,
-};
-
-/*
- * 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 timer_list work_timer;
-	struct timer_list credit_timer;
-
-	/* free chans needed */
-	int free_chans_need;
-
-	/* load */
-	u_int16_t available_slots;
-};
-
-struct gsm_envabtse {
-	struct gsm_nm_state nm_state;
-};
-
-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;
-	u_int16_t nsvci;
-	u_int16_t local_port;	/* on the BTS */
-	u_int16_t remote_port;	/* on the SGSN */
-	u_int32_t remote_ip;	/* on the SGSN */
-
-	struct gsm_nm_state nm_state;
-};
-
-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 */
-};
-
-/* One BTS */
-struct gsm_bts {
-	/* list header in net->bts_list */
-	struct llist_head list;
-
-	struct gsm_network *network;
-	/* number of ths BTS in network */
-	u_int8_t nr;
-	/* human readable name / description */
-	char *description;
-	/* Cell Identity */
-	u_int16_t cell_identity;
-	/* location area code of this BTS */
-	u_int16_t location_area_code;
-	/* Training Sequence Code */
-	u_int8_t tsc;
-	/* Base Station Identification Code (BSIC) */
-	u_int8_t bsic;
-	/* type of BTS */
-	enum gsm_bts_type type;
-	struct gsm_bts_model *model;
-	enum gsm_band band;
-	/* should the channel allocator allocate channels from high TRX to TRX0,
-	 * rather than starting from TRX0 and go upwards? */
-	int chan_alloc_reverse;
-	/* 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;
-	u_int8_t oml_tei;
-	struct e1inp_sign_link *oml_link;
-
-	/* Abis network management O&M handle */
-	struct abis_nm_h *nmh;
-	struct gsm_nm_state nm_state;
-	struct tlv_parsed nm_attr;
-
-	/* number of this BTS on given E1 link */
-	u_int8_t bts_nr;
-
-	/* paging state and control */
-	struct gsm_bts_paging_state paging;
-
-	/* CCCH is on C0 */
-	struct gsm_bts_trx *c0;
-
-	struct {
-		struct gsm_nm_state nm_state;
-	} site_mgr;
-
-	enum neigh_list_manual_mode neigh_list_manual_mode;
-	/* parameters from which we build SYSTEM INFORMATION */
-	struct {
-		struct gsm48_rach_control rach_control;
-		u_int8_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 {
-			/* bitmask large enough for all possible ARFCN's */
-			u_int8_t neigh_list[1024/8];
-			u_int8_t cell_alloc[1024/8];
-			/* If the user wants a different neighbor list in SI5 than in SI2 */
-			u_int8_t si5_neigh_list[1024/8];
-		} data;
-	} si_common;
-
-	/* do we use static (user-defined) system information messages? (bitmask) */
-	uint32_t si_mode_static;
-	/* bitmask of all SI that are present/valid in si_buf */
-	uint32_t si_valid;
-	/* buffers where we put the pre-computed SI */
-	sysinfo_buf_t si_buf[_MAX_SYSINFO_TYPE];
-
-	/* ip.accesss Unit ID's have Site/BTS/TRX layout */
-	union {
-		struct {
-			u_int16_t site_id;
-			u_int16_t bts_id;
-			u_int32_t flags;
-		} ip_access;
-		struct {
-			struct {
-				struct gsm_nm_state nm_state;
-			} cclk;
-			struct {
-				struct gsm_nm_state nm_state;
-			} rack;
-			struct gsm_envabtse envabtse[4];
-		} bs11;
-		struct {
-			struct {
-				struct llist_head conn_groups;
-			} is;
-			struct {
-				struct llist_head conn_groups;
-			} con;
-		} rbs2000;
-		struct {
-			unsigned long serno;
-		} hsl;
-	};
-
-	/* Not entirely sure how ip.access specific this is */
-	struct {
-		enum bts_gprs_mode mode;
-		struct {
-			struct gsm_nm_state nm_state;
-			u_int16_t nsei;
-			uint8_t timer[7];
-		} nse;
-		struct {
-			struct gsm_nm_state nm_state;
-			u_int16_t bvci;
-			uint8_t timer[11];
-		} cell;
-		struct gsm_bts_gprs_nsvc nsvc[2];
-		u_int8_t rac;
-	} gprs;
-
-	/* RACH NM values */
-	int rach_b_thresh;
-	int rach_ldavg_slots;
-	
-	/* transceivers */
-	int num_trx;
-	struct llist_head trx_list;
-
-	/* Abis NM queue */
-	struct llist_head abis_queue;
-	int abis_nm_pend;
-};
 
 /* Some statistics of our network */
 struct gsmnet_stats {
 	struct {
-		struct counter *total;
-		struct counter *no_channel;
+		struct osmo_counter *total;
+		struct osmo_counter *no_channel;
 	} chreq;
 	struct {
-		struct counter *attempted;
-		struct counter *no_channel;	/* no channel available */
-		struct counter *timeout;		/* T3103 timeout */
-		struct counter *completed;	/* HO COMPL received */
-		struct counter *failed;		/* HO FAIL received */
+		struct osmo_counter *attempted;
+		struct osmo_counter *no_channel;	/* no channel available */
+		struct osmo_counter *timeout;		/* T3103 timeout */
+		struct osmo_counter *completed;	/* HO COMPL received */
+		struct osmo_counter *failed;		/* HO FAIL received */
 	} handover;
 	struct {
-		struct counter *attach;
-		struct counter *normal;
-		struct counter *periodic;
-		struct counter *detach;
+		struct osmo_counter *attach;
+		struct osmo_counter *normal;
+		struct osmo_counter *periodic;
+		struct osmo_counter *detach;
 	} loc_upd_type;
 	struct {
-		struct counter *reject;
-		struct counter *accept;
+		struct osmo_counter *reject;
+		struct osmo_counter *accept;
 	} loc_upd_resp;
 	struct {
-		struct counter *attempted;
-		struct counter *detached;
-		struct counter *completed;
-		struct counter *expired;
+		struct osmo_counter *attempted;
+		struct osmo_counter *detached;
+		struct osmo_counter *completed;
+		struct osmo_counter *expired;
 	} paging;
 	struct {
-		struct counter *submitted; /* MO SMS submissions */
-		struct counter *no_receiver;
-		struct counter *delivered; /* MT SMS deliveries */
-		struct counter *rp_err_mem;
-		struct counter *rp_err_other;
+		struct osmo_counter *submitted; /* MO SMS submissions */
+		struct osmo_counter *no_receiver;
+		struct osmo_counter *delivered; /* MT SMS deliveries */
+		struct osmo_counter *rp_err_mem;
+		struct osmo_counter *rp_err_other;
 	} sms;
 	struct {
-		struct counter *mo_setup;
-		struct counter *mo_connect_ack;
-		struct counter *mt_setup;
-		struct counter *mt_connect;
+		struct osmo_counter *mo_setup;
+		struct osmo_counter *mo_connect_ack;
+		struct osmo_counter *mt_setup;
+		struct osmo_counter *mt_connect;
 	} call;
 	struct {
-		struct counter *rf_fail;
-		struct counter *rll_err;
+		struct osmo_counter *rf_fail;
+		struct osmo_counter *rll_err;
 	} chan;
 	struct {
-		struct counter *oml_fail;
-		struct counter *rsl_fail;
+		struct osmo_counter *oml_fail;
+		struct osmo_counter *rsl_fail;
 	} bts;
 };
 
@@ -699,8 +217,8 @@
 
 struct gsm_network {
 	/* global parameters */
-	u_int16_t country_code;
-	u_int16_t network_code;
+	uint16_t country_code;
+	uint16_t network_code;
 	char *name_long;
 	char *name_short;
 	enum gsm_auth_policy auth_policy;
@@ -780,50 +298,32 @@
 	struct gsm_subscriber *receiver;
 
 	unsigned long validity_minutes;
-	u_int8_t reply_path_req;
-	u_int8_t status_rep_req;
-	u_int8_t ud_hdr_ind;
-	u_int8_t protocol_id;
-	u_int8_t data_coding_scheme;
-	u_int8_t msg_ref;
+	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;
 	char dest_addr[20+1];	/* DA LV is 12 bytes max, i.e. 10 bytes
 				 * BCD == 20 bytes string */
-	u_int8_t user_data_len;
-	u_int8_t user_data[SMS_TEXT_SIZE];
+	uint8_t user_data_len;
+	uint8_t user_data[SMS_TEXT_SIZE];
 
 	char text[SMS_TEXT_SIZE];
 };
 
-
-struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_code,
+struct gsm_network *gsm_network_init(uint16_t country_code, uint16_t network_code,
 				     int (*mncc_recv)(struct gsm_network *, struct msgb *));
-struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type,
-			      u_int8_t tsc, u_int8_t bsic);
-struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts);
 int gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type);
 
 struct gsm_bts *gsm_bts_num(struct gsm_network *net, int num);
 
 /* Get reference to a neighbor cell on a given BCCH ARFCN */
 struct gsm_bts *gsm_bts_neighbor(const struct gsm_bts *bts,
-				 u_int16_t arfcn, u_int8_t bsic);
+				 uint16_t arfcn, uint8_t bsic);
 
-struct gsm_bts_trx *gsm_bts_trx_num(struct gsm_bts *bts, int num);
-
-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(struct gsm_bts_trx *trx);
-char *gsm_ts_name(struct gsm_bts_trx_ts *ts);
-char *gsm_lchan_name(struct gsm_lchan *lchan);
-const char *gsm_lchans_name(enum gsm_lchan_state s);
-
-void set_ts_e1link(struct gsm_bts_trx_ts *ts, u_int8_t e1_nr,
-		   u_int8_t e1_ts, u_int8_t e1_ts_ss);
 enum gsm_bts_type parse_btstype(const char *arg);
 const char *btstype2str(enum gsm_bts_type type);
-struct gsm_bts_trx *gsm_bts_trx_by_nr(struct gsm_bts *bts, int nr);
 struct gsm_bts *gsm_bts_by_lac(struct gsm_network *net, unsigned int lac,
 				struct gsm_bts *start_bts);
 
@@ -853,7 +353,6 @@
 	return 0;
 }
 
-
 enum gsm_auth_policy gsm_auth_policy_parse(const char *arg);
 const char *gsm_auth_policy_name(enum gsm_auth_policy policy);
 
@@ -863,17 +362,24 @@
 enum bts_gprs_mode bts_gprs_mode_parse(const char *arg);
 const char *bts_gprs_mode_name(enum bts_gprs_mode mode);
 
-void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked);
-
-int gsm48_ra_id_by_bts(u_int8_t *buf, struct gsm_bts *bts);
+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);
 struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan);
 
 int gsm_btsmodel_set_feature(struct gsm_bts_model *model, enum gsm_bts_features feat);
-int gsm_bts_has_feature(struct gsm_bts *bts, enum gsm_bts_features feat);
 int gsm_bts_model_register(struct gsm_bts_model *model);
 
 struct gsm_subscriber_connection *subscr_con_allocate(struct gsm_lchan *lchan);
 void subscr_con_free(struct gsm_subscriber_connection *conn);
 
-#endif
+struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net,
+					enum gsm_bts_type type,
+					uint8_t tsc, 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);
+int gsm_bts_has_feature(struct gsm_bts *bts, enum gsm_bts_features feat);
+struct gsm_bts_trx *gsm_bts_trx_by_nr(struct gsm_bts *bts, int nr);
+
+#endif /* _GSM_DATA_H */
diff --git a/include/openbsc/gsm_data_shared.h b/include/openbsc/gsm_data_shared.h
new file mode 100644
index 0000000..011e0aa
--- /dev/null
+++ b/include/openbsc/gsm_data_shared.h
@@ -0,0 +1,590 @@
+#ifndef _GSM_DATA_SHAREDH
+#define _GSM_DATA_SHAREDH
+
+#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/protocol/gsm_08_58.h>
+#include <osmocom/gsm/protocol/gsm_12_21.h>
+
+struct osmo_msc_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,
+};
+
+#define TRX_NR_TS	8
+#define TS_MAX_LCHAN	8
+
+#define HARDCODED_ARFCN 123
+#define HARDCODED_TSC	7
+#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
+
+/* reserved according to GSM 03.03 § 2.4 */
+#define GSM_RESERVED_TMSI   0xFFFFFFFF
+
+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_subscriber;
+struct gsm_mncc;
+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;
+	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;
+};
+
+#define MAX_A5_KEY_LEN	(128/8)
+#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)
+
+/* is the data link established? who established it? */
+#define LCHAN_SAPI_UNUSED	0
+#define LCHAN_SAPI_MS		1
+#define LCHAN_SAPI_NET		2
+
+/* state of a logical channel */
+enum gsm_lchan_state {
+	LCHAN_S_NONE,		/* channel is not active */
+	LCHAN_S_ACT_REQ,	/* channel activatin 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_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;
+};
+/* /BTS ONLY */
+
+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;
+	/* State */
+	enum gsm_lchan_state state;
+	/* Power levels for MS and BTS */
+	uint8_t bs_power;
+	uint8_t ms_power;
+	/* Encryption information */
+	struct {
+		uint8_t alg_id;
+		uint8_t key_len;
+		uint8_t key[MAX_A5_KEY_LEN];
+	} encr;
+
+	/* AMR bits */
+	struct gsm48_multi_rate_conf mr_conf;
+
+	/* Established data link layer services */
+	uint8_t sapis[8];
+	int sach_deact;
+	int release_reason;
+
+	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;
+		struct rtp_socket *rtp_socket;
+	} abis_ip;
+
+	uint8_t rqd_ta;
+
+#ifdef ROLE_BSC
+	struct osmo_timer_list T3101;
+	struct osmo_timer_list T3111;
+	struct osmo_timer_list error_timer;
+
+	/* 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;
+#else
+	struct lapdm_channel lapdm_ch;
+	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 */
+		sysinfo_buf_t buf[_MAX_SYSINFO_TYPE];
+	} 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 {
+			uint8_t rxlev_full;
+			uint8_t rxlev_sub;
+			uint8_t rxqual_full;
+			uint8_t rxqual_sub;
+		} res;
+	} meas;
+#endif
+};
+
+
+struct gsm_e1_subslot {
+	/* Number of E1 link */
+	uint8_t	e1_nr;
+	/* Number of E1 TS inside E1 link */
+	uint8_t	e1_ts;
+	/* Sub-slot within the E1 TS, 0xff if full TS */
+	uint8_t	e1_ts_ss;
+};
+
+#define TS_F_PDCH_MODE	0x1000
+/* 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;
+
+	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;
+
+	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 */
+
+	struct {
+		void *l1h;
+	} role_bts;
+
+	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 gsm_bts_trx_ts ts[TRX_NR_TS];
+};
+
+#define GSM_BTS_SI(bts, i)	(void *)(bts->si_buf[i])
+
+enum gsm_bts_type {
+	GSM_BTS_TYPE_UNKNOWN,
+	GSM_BTS_TYPE_BS11,
+	GSM_BTS_TYPE_NANOBTS,
+	GSM_BTS_TYPE_RBS2000,
+	GSM_BTS_TYPE_HSL_FEMTO,
+};
+
+struct vty;
+
+struct gsm_bts_model {
+	struct llist_head list;
+
+	enum gsm_bts_type type;
+	const char *name;
+
+	bool started;
+	int (*start)(struct gsm_network *net);
+	int (*oml_rcvmsg)(struct msgb *msg);
+
+	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;
+
+	struct bitvec features;
+	uint8_t _features_data[128/8];
+};
+
+enum gsm_bts_features {
+	BTS_FEAT_HSCSD,
+	BTS_FEAT_GPRS,
+	BTS_FEAT_EGPRS,
+	BTS_FEAT_ECSD,
+	BTS_FEAT_HOPPING,
+};
+
+/*
+ * 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 neigh_list_manual_mode {
+	NL_MODE_AUTOMATIC = 0,
+	NL_MODE_MANUAL = 1,
+	NL_MODE_MANUAL_SI5SEP = 2, /* SI2 and SI5 have separate neighbor lists */
+};
+
+/* One BTS */
+struct gsm_bts {
+	/* list header in net->bts_list */
+	struct llist_head 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;
+	/* Training Sequence Code */
+	uint8_t tsc;
+	/* Base Station Identification Code (BSIC) */
+	uint8_t bsic;
+	/* type of BTS */
+	enum gsm_bts_type type;
+	struct gsm_bts_model *model;
+	enum gsm_band band;
+	/* 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;
+
+	/* 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;
+	/* buffers where we put the pre-computed SI */
+	sysinfo_buf_t si_buf[_MAX_SYSINFO_TYPE];
+
+	/* ip.accesss Unit ID's have Site/BTS/TRX layout */
+	union {
+		struct {
+			uint16_t site_id;
+			uint16_t bts_id;
+			uint32_t flags;
+		} 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 gsm_abis_mo mo;
+				struct llist_head conn_groups;
+			} is;
+			struct {
+				struct gsm_abis_mo mo;
+				struct llist_head conn_groups;
+			} con;
+			struct {
+				struct gsm_abis_mo mo;
+			} dp;
+			struct {
+				struct gsm_abis_mo mo;
+			} tf;
+		} rbs2000;
+		struct {
+			unsigned long serno;
+		} hsl;
+	};
+
+	/* Not entirely sure how ip.access specific this is */
+	struct {
+		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];
+		} cell;
+		struct gsm_bts_gprs_nsvc nsvc[2];
+		uint8_t rac;
+	} gprs;
+
+	/* RACH NM values */
+	int rach_b_thresh;
+	int rach_ldavg_slots;
+
+	/* transceivers */
+	int num_trx;
+	struct llist_head trx_list;
+
+#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 {
+			/* 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];
+		} data;
+	} si_common;
+
+	/* do we use static (user-defined) system information messages? (bitmask) */
+	uint32_t si_mode_static;
+#endif /* ROLE_BSC */
+	void *role;
+};
+
+
+struct gsm_bts *gsm_bts_alloc(void *talloc_ctx);
+struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts);
+
+struct gsm_bts_trx *gsm_bts_trx_num(struct gsm_bts *bts, int num);
+
+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(struct gsm_bts_trx *trx);
+char *gsm_ts_name(struct gsm_bts_trx_ts *ts);
+char *gsm_lchan_name(struct gsm_lchan *lchan);
+const char *gsm_lchans_name(enum gsm_lchan_state s);
+
+
+void gsm_abis_mo_reset(struct gsm_abis_mo *mo);
+
+struct gsm_abis_mo *
+gsm_objclass2mo(struct gsm_bts *bts, uint8_t obj_class,
+	    struct abis_om_obj_inst *obj_inst);
+
+struct gsm_nm_state *
+gsm_objclass2nmstate(struct gsm_bts *bts, uint8_t obj_class,
+		 struct abis_om_obj_inst *obj_inst);
+void *
+gsm_objclass2obj(struct gsm_bts *bts, uint8_t obj_class,
+	     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_ts2chan_nr(const struct gsm_bts_trx_ts *ts, uint8_t lchan_nr);
+uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan);
+
+#endif
diff --git a/include/openbsc/gsm_subscriber.h b/include/openbsc/gsm_subscriber.h
index c365bc7..6cf8573 100644
--- a/include/openbsc/gsm_subscriber.h
+++ b/include/openbsc/gsm_subscriber.h
@@ -1,9 +1,8 @@
 #ifndef _GSM_SUBSCR_H
 #define _GSM_SUBSCR_H
 
-#include <sys/types.h>
 #include "gsm_data.h"
-#include <osmocore/linuxlist.h>
+#include <osmocom/core/linuxlist.h>
 
 #define GSM_IMEI_LENGTH 17
 #define GSM_IMSI_LENGTH 17
@@ -24,24 +23,24 @@
 	char name[GSM_NAME_LENGTH];
 
 	struct gsm48_classmark1 classmark1;
-	u_int8_t classmark2_len;
-	u_int8_t classmark2[3];
-	u_int8_t classmark3_len;
-	u_int8_t classmark3[14];
+	uint8_t classmark2_len;
+	uint8_t classmark2[3];
+	uint8_t classmark3_len;
+	uint8_t classmark3[14];
 };
 
 struct gsm_subscriber {
 	struct gsm_network *net;
 	long long unsigned int id;
 	char imsi[GSM_IMSI_LENGTH];
-	u_int32_t tmsi;
-	u_int16_t lac;
+	uint32_t tmsi;
+	uint16_t lac;
 	char name[GSM_NAME_LENGTH];
 	char extension[GSM_EXTENSION_LENGTH];
 	int authorized;
 
 	/* Temporary field which is not stored in the DB/HLR */
-	u_int32_t flags;
+	uint32_t flags;
 
 	/* Every user can only have one equipment in use at any given
 	 * point in time */
@@ -72,7 +71,7 @@
 struct gsm_subscriber *subscr_get(struct gsm_subscriber *subscr);
 struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr);
 struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_network *net,
-					  u_int32_t tmsi);
+					  uint32_t tmsi);
 struct gsm_subscriber *subscr_get_by_imsi(struct gsm_network *net,
 					  const char *imsi);
 struct gsm_subscriber *subscr_get_by_extension(struct gsm_network *net,
diff --git a/include/openbsc/ipaccess.h b/include/openbsc/ipaccess.h
index 1d00d97..c2ca2a5 100644
--- a/include/openbsc/ipaccess.h
+++ b/include/openbsc/ipaccess.h
@@ -3,56 +3,8 @@
 
 #include "e1_input.h"
 #include "gsm_subscriber.h"
-#include <osmocore/linuxlist.h>
-
-#define IPA_TCP_PORT_OML	3002
-#define IPA_TCP_PORT_RSL	3003
-
-struct ipaccess_head {
-	u_int16_t len;	/* network byte order */
-	u_int8_t proto;
-	u_int8_t data[0];
-} __attribute__ ((packed));
-
-struct ipaccess_head_ext {
-	uint8_t proto;
-	uint8_t data[0];
-} __attribute__ ((packed));
-
-enum ipaccess_proto {
-	IPAC_PROTO_RSL		= 0x00,
-	IPAC_PROTO_IPACCESS	= 0xfe,
-	IPAC_PROTO_SCCP		= 0xfd,
-	IPAC_PROTO_OML		= 0xff,
-
-
-	/* OpenBSC extensions */
-	IPAC_PROTO_OSMO		= 0xee,
-	IPAC_PROTO_MGCP_OLD	= 0xfc,
-};
-
-enum ipaccess_msgtype {
-	IPAC_MSGT_PING		= 0x00,
-	IPAC_MSGT_PONG		= 0x01,
-	IPAC_MSGT_ID_GET	= 0x04,
-	IPAC_MSGT_ID_RESP	= 0x05,
-	IPAC_MSGT_ID_ACK	= 0x06,
-
-	/* OpenBSC extension */
-	IPAC_MSGT_SCCP_OLD	= 0xff,
-};
-
-enum ipaccess_id_tags {
-	IPAC_IDTAG_SERNR		= 0x00,
-	IPAC_IDTAG_UNITNAME		= 0x01,
-	IPAC_IDTAG_LOCATION1		= 0x02,
-	IPAC_IDTAG_LOCATION2		= 0x03,
-	IPAC_IDTAG_EQUIPVERS		= 0x04,
-	IPAC_IDTAG_SWVERSION		= 0x05,
-	IPAC_IDTAG_IPADDR		= 0x06,
-	IPAC_IDTAG_MACADDR		= 0x07,
-	IPAC_IDTAG_UNIT			= 0x08,
-};
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/gsm/protocol/ipaccess.h>
 
 struct ipac_msgt_sccp_state {
 	uint8_t	src_ref[3];
@@ -62,54 +14,38 @@
 	char		imsi[GSM_IMSI_LENGTH];
 } __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));
+
 int ipaccess_connect(struct e1inp_line *line, struct sockaddr_in *sa);
 
 /*
  * methods for parsing and sending a message
  */
-int ipaccess_rcvmsg_base(struct msgb *msg, struct bsc_fd *bfd);
-struct msgb *ipaccess_read_msg(struct bsc_fd *bfd, int *error);
+int ipaccess_rcvmsg_base(struct msgb *msg, struct osmo_fd *bfd);
+struct msgb *ipaccess_read_msg(struct osmo_fd *bfd, int *error);
 void ipaccess_prepend_header(struct msgb *msg, int proto);
+void ipaccess_prepend_header_ext(struct msgb *msg, int proto);
+int ipaccess_send_pong(int fd);
 int ipaccess_send_id_ack(int fd);
 int ipaccess_send_id_req(int fd);
 
+const char *ipaccess_idtag_name(uint8_t tag);
 int ipaccess_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len);
+int ipaccess_parse_unitid(const char *str, uint16_t *site_id, uint16_t *bts_id, uint16_t *trx_id);
 
 int ipaccess_drop_oml(struct gsm_bts *bts);
 int ipaccess_drop_rsl(struct gsm_bts_trx *trx);
 
-/*
- * Firmware specific header
- */
-struct sdp_firmware {
-	char magic[4];
-	char more_magic[2];
-	u_int16_t more_more_magic;
-	u_int32_t header_length;
-	u_int32_t file_length;
-	char sw_part[20];
-	char text1[64];
-	char time[12];
-	char date[14];
-	char text2[10];
-	char version[20];
-	u_int16_t table_offset;
-	/* stuff i don't know */
-} __attribute__((packed));
-
-struct sdp_header_entry {
-	u_int16_t something1;
-	char text1[64];
-	char time[12];
-	char date[14];
-	char text2[10];
-	char version[20];
-	u_int32_t length;
-	u_int32_t addr1;
-	u_int32_t addr2;
-	u_int32_t start;
-} __attribute__((packed));
-
 struct sdp_header_item {
 	struct sdp_header_entry header_entry;
 	struct llist_head entry;
diff --git a/include/openbsc/meas_rep.h b/include/openbsc/meas_rep.h
index 3c2c8d1..f235df6 100644
--- a/include/openbsc/meas_rep.h
+++ b/include/openbsc/meas_rep.h
@@ -1,21 +1,23 @@
 #ifndef _MEAS_REP_H
 #define _MEAS_REP_H
 
+#include <stdint.h>
+
 #define MRC_F_PROCESSED	0x0001
 
 /* extracted from a L3 measurement report IE */
 struct gsm_meas_rep_cell {
-	u_int8_t rxlev;
-	u_int8_t bsic;
-	u_int8_t neigh_idx;
-	u_int16_t arfcn;
+	uint8_t rxlev;
+	uint8_t bsic;
+	uint8_t neigh_idx;
+	uint16_t arfcn;
 	unsigned int flags;
 };
 
 /* RX Level and RX Quality */
 struct gsm_rx_lev_qual {
-	u_int8_t rx_lev;
-	u_int8_t rx_qual;
+	uint8_t rx_lev;
+	uint8_t rx_qual;
 };
 
 /* unidirectional measumrement report */
@@ -38,7 +40,7 @@
 	struct gsm_lchan *lchan;
 
 	/* number of the measurement report */
-	u_int8_t nr;
+	uint8_t nr;
 	/* flags, see MEAS_REP_F_* */
 	unsigned int flags;
 
@@ -46,11 +48,11 @@
 	struct gsm_meas_rep_unidir ul;
 	struct gsm_meas_rep_unidir dl;
 
-	u_int8_t bs_power;
-	u_int8_t ms_timing_offset;
+	uint8_t bs_power;
+	uint8_t ms_timing_offset;
 	struct {
 		int8_t pwr;	/* MS power in dBm */
-		u_int8_t ta;	/* MS timing advance */
+		uint8_t ta;	/* MS timing advance */
 	} ms_l1;
 
 	/* neighbor measurement reports for up to 6 cells */
diff --git a/include/openbsc/mgcp.h b/include/openbsc/mgcp.h
index 516b76e..b9f8116 100644
--- a/include/openbsc/mgcp.h
+++ b/include/openbsc/mgcp.h
@@ -23,8 +23,8 @@
 #ifndef OPENBSC_MGCP_H
 #define OPENBSC_MGCP_H
 
-#include <osmocore/msgb.h>
-#include <osmocore/write_queue.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/write_queue.h>
 
 #include "debug.h"
 
@@ -135,7 +135,7 @@
 	struct in_addr transcoder_in;
 	int transcoder_remote_base;
 
-	struct write_queue gw_fd;
+	struct osmo_wqueue gw_fd;
 
 	struct mgcp_port_range bts_ports;
 	struct mgcp_port_range net_ports;
diff --git a/include/openbsc/mgcp_internal.h b/include/openbsc/mgcp_internal.h
index 7c6bb54..a9d5149 100644
--- a/include/openbsc/mgcp_internal.h
+++ b/include/openbsc/mgcp_internal.h
@@ -23,7 +23,7 @@
 #ifndef OPENBSC_MGCP_DATA_H
 #define OPENBSC_MGCP_DATA_H
 
-#include <osmocore/select.h>
+#include <osmocom/core/select.h>
 
 #define CI_UNUSED 0
 
@@ -66,8 +66,8 @@
 	/*
 	 * Each end has a socket...
 	 */
-	struct bsc_fd rtp;
-	struct bsc_fd rtcp;
+	struct osmo_fd rtp;
+	struct osmo_fd rtcp;
 
 	int local_port;
 	int local_alloc;
diff --git a/include/openbsc/mncc.h b/include/openbsc/mncc.h
index e514c19..ed1bfd6 100644
--- a/include/openbsc/mncc.h
+++ b/include/openbsc/mncc.h
@@ -24,8 +24,8 @@
 #ifndef _MNCC_H
 #define _MNCC_H
 
-#include <osmocore/linuxlist.h>
-#include <osmocore/mncc.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/gsm/mncc.h>
 
 #include <stdint.h>
 
diff --git a/include/openbsc/osmo_bsc.h b/include/openbsc/osmo_bsc.h
index ef0f11a..2620147 100644
--- a/include/openbsc/osmo_bsc.h
+++ b/include/openbsc/osmo_bsc.h
@@ -16,8 +16,8 @@
 	/* SCCP connection realted */
 	struct sccp_connection *sccp;
 	struct bsc_msc_connection *msc_con;
-	struct timer_list sccp_it_timeout;
-	struct timer_list sccp_cc_timeout;
+	struct osmo_timer_list sccp_it_timeout;
+	struct osmo_timer_list sccp_cc_timeout;
 
 	struct llist_head sccp_queue;
 	unsigned int sccp_queue_size;
diff --git a/include/openbsc/osmo_bsc_rf.h b/include/openbsc/osmo_bsc_rf.h
index e43ae2e..6db28cd 100644
--- a/include/openbsc/osmo_bsc_rf.h
+++ b/include/openbsc/osmo_bsc_rf.h
@@ -1,32 +1,32 @@
 #ifndef OSMO_BSC_RF
 #define OSMO_BSC_RF
 
-#include <osmocore/write_queue.h>
-#include <osmocore/timer.h>
+#include <osmocom/core/write_queue.h>
+#include <osmocom/core/timer.h>
 
 struct gsm_network;
 
 struct osmo_bsc_rf {
 	/* the value of signal.h */
 	int policy;
-	struct bsc_fd listen;
+	struct osmo_fd listen;
 	struct gsm_network *gsm_network;
 
 	const char *last_state_command;
 
 	/* delay the command */
 	char last_request;
-	struct timer_list delay_cmd;
+	struct osmo_timer_list delay_cmd;
 
 	/* verify that RF is up as it should be */
-	struct timer_list rf_check;
+	struct osmo_timer_list rf_check;
 
 	/* some handling for the automatic grace switch */
-	struct timer_list grace_timeout;
+	struct osmo_timer_list grace_timeout;
 };
 
 struct osmo_bsc_rf_conn {
-	struct write_queue queue;
+	struct osmo_wqueue queue;
 	struct osmo_bsc_rf *rf;
 };
 
diff --git a/include/openbsc/osmo_msc_data.h b/include/openbsc/osmo_msc_data.h
index 8f9ca68..3212b36 100644
--- a/include/openbsc/osmo_msc_data.h
+++ b/include/openbsc/osmo_msc_data.h
@@ -25,7 +25,7 @@
 
 #include "bsc_msc.h"
 
-#include <osmocore/timer.h>
+#include <osmocom/core/timer.h>
 
 struct osmo_bsc_rf;
 struct gsm_network;
@@ -36,15 +36,15 @@
 };
 
 struct osmo_msc_data {
+	/* Back pointer */
+	struct gsm_network *network;
+
 	/* Connection data */
 	char *bsc_token;
-	int msc_port;
-	int msc_ip_dscp;
-	char *msc_ip;
 	int ping_timeout;
 	int pong_timeout;
-	struct timer_list ping_timer;
-	struct timer_list pong_timer;
+	struct osmo_timer_list ping_timer;
+	struct osmo_timer_list pong_timer;
 	struct bsc_msc_connection *msc_con;
 	int core_ncc;
 	int core_mcc;
@@ -54,13 +54,17 @@
 	struct gsm_audio_support **audio_support;
 	int audio_length;
 
+	/* destinations */
+	struct llist_head dests;
+
 
 	/* mgcp agent */
-	struct write_queue mgcp_agent;
+	struct osmo_wqueue mgcp_agent;
 
 	/* rf ctl related bits */
 	char *mid_call_txt;
 	int mid_call_timeout;
+	char *rf_ctrl_name;
 	struct osmo_bsc_rf *rf_ctl;
 
 	/* ussd welcome text */
diff --git a/include/openbsc/paging.h b/include/openbsc/paging.h
index f719199..0872eb8 100644
--- a/include/openbsc/paging.h
+++ b/include/openbsc/paging.h
@@ -23,10 +23,10 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <osmocore/linuxlist.h>
+#include <osmocom/core/linuxlist.h>
 #include "gsm_data.h"
 #include "gsm_subscriber.h"
-#include <osmocore/timer.h>
+#include <osmocom/core/timer.h>
 
 /**
  * A pending paging request
@@ -43,7 +43,7 @@
 	int chan_type;
 
 	/* Timer 3113: how long do we try to page? */
-	struct timer_list T3113;
+	struct osmo_timer_list T3113;
 
 	/* How often did we ask the BTS to page? */
 	int attempts;
@@ -53,9 +53,6 @@
 	void *cbfn_param;
 };
 
-/* call once for every gsm_bts... */
-void paging_init(struct gsm_bts *bts);
-
 /* schedule paging request */
 int paging_request(struct gsm_network *network, struct gsm_subscriber *subscr,
 		   int type, gsm_cbfn *cbfn, void *data);
@@ -66,6 +63,9 @@
 			 struct msgb *msg);
 
 /* update paging load */
-void paging_update_buffer_space(struct gsm_bts *bts, u_int16_t);
+void paging_update_buffer_space(struct gsm_bts *bts, uint16_t);
+
+/* pending paging requests */
+unsigned int paging_pending_requests_nr(struct gsm_bts *bts);
 
 #endif
diff --git a/include/openbsc/rest_octets.h b/include/openbsc/rest_octets.h
index 6d90119..2d16a1f 100644
--- a/include/openbsc/rest_octets.h
+++ b/include/openbsc/rest_octets.h
@@ -1,14 +1,13 @@
 #ifndef _REST_OCTETS_H
 #define _REST_OCTETS_H
 
-#include <sys/types.h>
 #include <openbsc/gsm_04_08.h>
 
 /* generate SI1 rest octets */
-int rest_octets_si1(u_int8_t *data, u_int8_t *nch_pos);
+int rest_octets_si1(uint8_t *data, uint8_t *nch_pos);
 
 struct gsm48_si_selection_params {
-	u_int16_t penalty_time:5,
+	uint16_t penalty_time:5,
 		  temp_offs:3,
 		  cell_resel_off:6,
 		  cbq:1,
@@ -16,18 +15,18 @@
 };
 
 struct gsm48_si_power_offset {
-	u_int8_t power_offset:2,
+	uint8_t power_offset:2,
 		 present:1;
 };
 
 struct gsm48_si3_gprs_ind {
-	u_int8_t si13_position:1,
+	uint8_t si13_position:1,
 		 ra_colour:3,
 		 present:1;
 };
 
 struct gsm48_lsa_params {
-	u_int32_t prio_thr:3,
+	uint32_t prio_thr:3,
 		 lsa_offset:3,
 		 mcc:12,
 		 mnc:12;
@@ -37,26 +36,26 @@
 struct gsm48_si_ro_info {
 	struct gsm48_si_selection_params selection_params;
 	struct gsm48_si_power_offset power_offset;
-	u_int8_t si2ter_indicator;
-	u_int8_t early_cm_ctrl;
+	uint8_t si2ter_indicator;
+	uint8_t early_cm_ctrl;
 	struct {
-		u_int8_t where:3,
+		uint8_t where:3,
 			 present:1;
 	} scheduling;
 	struct gsm48_si3_gprs_ind gprs_ind;
 
 	/* SI 4 specific */
 	struct gsm48_lsa_params lsa_params;
-	u_int16_t cell_id;
-	u_int8_t break_ind;	/* do we have SI7 + SI8 ? */
+	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(u_int8_t *data, const struct gsm48_si_ro_info *si3);
+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(u_int8_t *data, const struct gsm48_si_ro_info *si4);
+int rest_octets_si4(uint8_t *data, const struct gsm48_si_ro_info *si4);
 
 enum pbcch_carrier_type {
 	PBCCH_BCCH,
@@ -75,59 +74,59 @@
 struct gprs_cell_options {
 	enum gprs_nmo nmo;
 	/* T3168: wait for packet uplink assignment message */
-	u_int32_t t3168;	/* in milliseconds */
+	uint32_t t3168;	/* in milliseconds */
 	/* T3192: wait for release of the TBF after reception of the final block */
-	u_int32_t t3192;	/* in milliseconds */
-	u_int32_t drx_timer_max;/* in seconds */
-	u_int32_t bs_cv_max;
+	uint32_t t3192;	/* in milliseconds */
+	uint32_t drx_timer_max;/* in seconds */
+	uint32_t bs_cv_max;
 
-	u_int8_t ext_info_present;
+	uint8_t ext_info_present;
 	struct {
-		u_int8_t egprs_supported;
-			u_int8_t use_egprs_p_ch_req;
-			u_int8_t bep_period;
-		u_int8_t pfc_supported;
-		u_int8_t dtm_supported;
-		u_int8_t bss_paging_coordination;
+		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 {
-	u_int8_t alpha;
-	u_int8_t t_avg_w;
-	u_int8_t t_avg_t;
-	u_int8_t pc_meas_chan;
-	u_int8_t n_avg_i;
+	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;
-	u_int8_t bcch_change_mark;
-	u_int8_t si_change_field;
-	u_int8_t pbcch_present;
+	uint8_t bcch_change_mark;
+	uint8_t si_change_field;
+	uint8_t pbcch_present;
 
 	union {
 		struct {
-			u_int8_t rac;
-			u_int8_t spgc_ccch_sup;
-			u_int8_t net_ctrl_ord;
-			u_int8_t prio_acc_thr;
+			uint8_t rac;
+			uint8_t spgc_ccch_sup;
+			uint8_t net_ctrl_ord;
+			uint8_t prio_acc_thr;
 		} no_pbcch;
 		struct {
-			u_int8_t psi1_rep_per;
-			u_int8_t pb;
-			u_int8_t tsc;
-			u_int8_t tn;
+			uint8_t psi1_rep_per;
+			uint8_t pb;
+			uint8_t tsc;
+			uint8_t tn;
 			enum pbcch_carrier_type carrier_type;
-			u_int16_t arfcn;
-			u_int8_t maio;
+			uint16_t arfcn;
+			uint8_t maio;
 		} pbcch;
 	};
 };
 
 /* Generate SI13 Rest Octests (Chapter 10.5.2.37b) */
-int rest_octets_si13(u_int8_t *data, const struct gsm48_si13_info *si13);
+int rest_octets_si13(uint8_t *data, const struct gsm48_si13_info *si13);
 
 #endif /* _REST_OCTETS_H */
diff --git a/include/openbsc/rtp_proxy.h b/include/openbsc/rtp_proxy.h
index 53b58b4..94d2579 100644
--- a/include/openbsc/rtp_proxy.h
+++ b/include/openbsc/rtp_proxy.h
@@ -24,8 +24,10 @@
 
 #include <netinet/in.h>
 
-#include <osmocore/linuxlist.h>
-#include <osmocore/select.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
@@ -48,7 +50,7 @@
 	struct sockaddr_in sin_local;
 	struct sockaddr_in sin_remote;
 
-	struct bsc_fd bfd;
+	struct osmo_fd bfd;
 	/* linked list of to-be-transmitted msgb's */
 	struct llist_head tx_queue;
 };
@@ -67,23 +69,23 @@
 		} proxy;
 		struct {
 			struct gsm_network *net;
-			u_int32_t callref;
+			uint32_t callref;
 		} receive;
 	};
 	enum rtp_tx_action tx_action;
 	struct {
-		u_int16_t sequence;
-		u_int32_t timestamp;
-		u_int32_t ssrc;
+		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, u_int32_t ip);
-int rtp_socket_connect(struct rtp_socket *rs, u_int32_t ip, u_int16_t port);
+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, u_int32_t callref);
+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);
 
diff --git a/include/openbsc/sgsn.h b/include/openbsc/sgsn.h
index 84db87e..7456614 100644
--- a/include/openbsc/sgsn.h
+++ b/include/openbsc/sgsn.h
@@ -1,9 +1,8 @@
 #ifndef _SGSN_H
 #define _SGSN_H
 
-#include <sys/types.h>
 
-#include <osmocore/msgb.h>
+#include <osmocom/core/msgb.h>
 
 #include <openbsc/gprs_ns.h>
 #include <openbsc/gprs_sgsn.h>
@@ -22,11 +21,11 @@
 	char *config_file;
 	struct sgsn_config cfg;
 	/* File descriptor wrappers for LibGTP */
-	struct bsc_fd gtp_fd0;
-	struct bsc_fd gtp_fd1c;
-	struct bsc_fd gtp_fd1u;
+	struct osmo_fd gtp_fd0;
+	struct osmo_fd gtp_fd1c;
+	struct osmo_fd gtp_fd1u;
 	/* Timer for libGTP */
-	struct timer_list gtp_timer;
+	struct osmo_timer_list gtp_timer;
 	/* GSN instance for libgtp */
 	struct gsn_t *gsn;
 };
diff --git a/include/openbsc/signal.h b/include/openbsc/signal.h
index a2257db..2991cfa 100644
--- a/include/openbsc/signal.h
+++ b/include/openbsc/signal.h
@@ -27,7 +27,7 @@
 
 #include <openbsc/gsm_data.h>
 
-#include <osmocore/signal.h>
+#include <osmocom/core/signal.h>
 
 /*
  * Signalling subsystems
@@ -84,6 +84,7 @@
 	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 */
@@ -169,15 +170,30 @@
 
 struct ipacc_ack_signal_data {
 	struct gsm_bts_trx *trx;
-	u_int8_t msg_type;	
+	uint8_t msg_type;
 };
 
+struct abis_om2k_mo;
+
 struct nm_statechg_signal_data {
-	u_int8_t obj_class;
+	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 {
diff --git a/include/openbsc/socket.h b/include/openbsc/socket.h
index 4d31611..0fd85f1 100644
--- a/include/openbsc/socket.h
+++ b/include/openbsc/socket.h
@@ -1,14 +1,14 @@
 #ifndef _BSC_SOCKET_H
 #define _BSC_SOCKET_H
 
-#include <sys/types.h>
-#include <osmocore/select.h>
+#include <osmocom/core/select.h>
 
 #ifndef IPPROTO_GRE
 #define IPPROTO_GRE 47
 #endif
 
-int make_sock(struct bsc_fd *bfd, int proto, u_int32_t ip, u_int16_t port,
-	      int (*cb)(struct bsc_fd *fd, unsigned int what));
+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/subchan_demux.h b/include/openbsc/subchan_demux.h
index da2a7f3..b71c856 100644
--- a/include/openbsc/subchan_demux.h
+++ b/include/openbsc/subchan_demux.h
@@ -20,8 +20,8 @@
  *
  */
 
-#include <sys/types.h>
-#include <osmocore/linuxlist.h>
+#include <stdint.h>
+#include <osmocom/core/linuxlist.h>
 
 #define NR_SUBCH	4
 #define TRAU_FRAME_SIZE	40
@@ -32,8 +32,8 @@
 /***********************************************************************/
 
 struct demux_subch {
-	u_int8_t out_bitbuf[TRAU_FRAME_BITS];
-	u_int16_t out_idx; /* next bit to be written in out_bitbuf */
+	uint8_t out_bitbuf[TRAU_FRAME_BITS];
+	uint16_t out_idx; /* next bit to be written in out_bitbuf */
 	/* number of consecutive zeros that we have received (for sync) */
 	unsigned int consecutive_zeros;
 	/* are we in TRAU frame sync or not? */
@@ -42,12 +42,12 @@
 
 struct subch_demux {
 	/* bitmask of currently active subchannels */
-	u_int8_t chan_activ;
+	uint8_t chan_activ;
 	/* one demux_subch struct for every subchannel */
 	struct demux_subch subch[NR_SUBCH];
 	/* callback to be called once we have received a complete
 	 * frame on a given subchannel */
-	int (*out_cb)(struct subch_demux *dmx, int ch, u_int8_t *data, int len,
+	int (*out_cb)(struct subch_demux *dmx, int ch, uint8_t *data, int len,
 		      void *);
 	/* user-provided data, transparently passed to out_cb() */
 	void *data;
@@ -57,7 +57,7 @@
 int subch_demux_init(struct subch_demux *dmx);
 
 /* feed 'len' number of muxed bytes into the demultiplexer */
-int subch_demux_in(struct subch_demux *dmx, u_int8_t *data, int len);
+int subch_demux_in(struct subch_demux *dmx, uint8_t *data, int len);
 
 /* activate decoding/processing for one subchannel */
 int subch_demux_activate(struct subch_demux *dmx, int subch);
@@ -76,7 +76,7 @@
 	unsigned int bit_len;	/* total number of bits in 'bits' */
 	unsigned int next_bit;	/* next bit to be transmitted */
 
-	u_int8_t bits[0];	/* one bit per byte */
+	uint8_t bits[0];	/* one bit per byte */
 };
 
 struct mux_subch {
@@ -92,10 +92,10 @@
 int subchan_mux_init(struct subch_mux *mx);
 
 /* request the output of 'len' multiplexed bytes */
-int subchan_mux_out(struct subch_mux *mx, u_int8_t *data, int len);
+int subchan_mux_out(struct subch_mux *mx, uint8_t *data, int len);
 
 /* enqueue some data into one sub-channel of the muxer */
-int subchan_mux_enqueue(struct subch_mux *mx, int s_nr, const u_int8_t *data,
+int subchan_mux_enqueue(struct subch_mux *mx, int s_nr, const uint8_t *data,
 			int len);
 
 #endif /* _SUBCH_DEMUX_H */
diff --git a/include/openbsc/system_information.h b/include/openbsc/system_information.h
index da662e9..6a56848 100644
--- a/include/openbsc/system_information.h
+++ b/include/openbsc/system_information.h
@@ -1,45 +1,10 @@
 #ifndef _SYSTEM_INFO_H
 #define _SYSTEM_INFO_H
 
-#include <osmocore/utils.h>
-
-#define GSM_MACBLOCK_LEN 		23
+#include <osmocom/gsm/sysinfo.h>
 
 struct gsm_bts;
 
-
-enum osmo_sysinfo_type {
-	SYSINFO_TYPE_NONE,
-	SYSINFO_TYPE_1,
-	SYSINFO_TYPE_2,
-	SYSINFO_TYPE_3,
-	SYSINFO_TYPE_4,
-	SYSINFO_TYPE_5,
-	SYSINFO_TYPE_6,
-	SYSINFO_TYPE_7,
-	SYSINFO_TYPE_8,
-	SYSINFO_TYPE_9,
-	SYSINFO_TYPE_10,
-	SYSINFO_TYPE_13,
-	SYSINFO_TYPE_16,
-	SYSINFO_TYPE_17,
-	SYSINFO_TYPE_18,
-	SYSINFO_TYPE_19,
-	SYSINFO_TYPE_20,
-	SYSINFO_TYPE_2bis,
-	SYSINFO_TYPE_2ter,
-	SYSINFO_TYPE_2quater,
-	SYSINFO_TYPE_5bis,
-	SYSINFO_TYPE_5ter,
-	/* FIXME all the various bis and ter */
-	_MAX_SYSINFO_TYPE
-};
-
-typedef u_int8_t sysinfo_buf_t[GSM_MACBLOCK_LEN];
-
-extern const struct value_string osmo_sitype_strs[_MAX_SYSINFO_TYPE];
-uint8_t gsm_sitype2rsl(enum osmo_sysinfo_type si_type);
-const char *gsm_sitype_name(enum osmo_sysinfo_type si_type);
 int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type type);
 
 #endif
diff --git a/include/openbsc/transaction.h b/include/openbsc/transaction.h
index e41d8ef..acb2e6c 100644
--- a/include/openbsc/transaction.h
+++ b/include/openbsc/transaction.h
@@ -3,8 +3,9 @@
 
 #include <openbsc/gsm_data.h>
 #include <openbsc/gsm_subscriber.h>
-#include <osmocore/linuxlist.h>
+#include <osmocom/core/linuxlist.h>
 #include <openbsc/gsm_04_11.h>
+#include <openbsc/mncc.h>
 
 /* One transaction */
 struct gsm_trans {
@@ -12,10 +13,10 @@
 	struct llist_head entry;
 
 	/* The protocol within which we live */
-	u_int8_t protocol;
+	uint8_t protocol;
 
 	/* The current transaction ID */
-	u_int8_t transaction_id;
+	uint8_t transaction_id;
 	
 	/* To whom we belong, unique identifier of remote MM entity */
 	struct gsm_subscriber *subscr;
@@ -24,7 +25,7 @@
 	struct gsm_subscriber_connection *conn;
 
 	/* reference from MNCC or other application */
-	u_int32_t callref;
+	uint32_t callref;
 
 	/* if traffic channel receive was requested */
 	int tch_recv;
@@ -41,14 +42,14 @@
 			/* current timer and message queue */
 			int Tcurrent;		/* current CC timer */
 			int T308_second;	/* used to send release again */
-			struct timer_list timer;
+			struct osmo_timer_list timer;
 			struct gsm_mncc msg;	/* stores setup/disconnect/release message */
 		} cc;
 		struct {
-			u_int8_t link_id;	/* RSL Link ID to be used for this trans */
+			uint8_t link_id;	/* RSL Link ID to be used for this trans */
 			int is_mt;	/* is this a MO (0) or MT (1) transfer */
 			enum gsm411_cp_state cp_state;
-			struct timer_list cp_timer;
+			struct osmo_timer_list cp_timer;
 
 			enum gsm411_rp_state rp_state;
 
@@ -60,16 +61,16 @@
 
 
 struct gsm_trans *trans_find_by_id(struct gsm_subscriber *subscr,
-				   u_int8_t proto, u_int8_t trans_id);
+				   uint8_t proto, uint8_t trans_id);
 struct gsm_trans *trans_find_by_callref(struct gsm_network *net,
-					u_int32_t callref);
+					uint32_t callref);
 
 struct gsm_trans *trans_alloc(struct gsm_subscriber *subscr,
-			      u_int8_t protocol, u_int8_t trans_id,
-			      u_int32_t callref);
+			      uint8_t protocol, uint8_t trans_id,
+			      uint32_t callref);
 void trans_free(struct gsm_trans *trans);
 
 int trans_assign_trans_id(struct gsm_subscriber *subscr,
-			  u_int8_t protocol, u_int8_t ti_flag);
+			  uint8_t protocol, uint8_t ti_flag);
 
 #endif
diff --git a/include/openbsc/trau_frame.h b/include/openbsc/trau_frame.h
index c594c38..c15e24b 100644
--- a/include/openbsc/trau_frame.h
+++ b/include/openbsc/trau_frame.h
@@ -20,7 +20,7 @@
  *
  */
 
-#include <sys/types.h>
+#include <stdint.h>
 
 /* 21 for FR/EFR, 25 for AMR, 15 for OM, 15 for data, 13 for E-data, 21 idle */
 #define MAX_C_BITS	25
@@ -34,11 +34,11 @@
 #define MAX_M_BITS	2
 
 struct decoded_trau_frame {
-	u_int8_t c_bits[MAX_C_BITS];
-	u_int8_t d_bits[MAX_D_BITS];
-	u_int8_t t_bits[MAX_T_BITS];
-	u_int8_t s_bits[MAX_S_BITS];
-	u_int8_t m_bits[MAX_M_BITS];
+	uint8_t c_bits[MAX_C_BITS];
+	uint8_t d_bits[MAX_D_BITS];
+	uint8_t t_bits[MAX_T_BITS];
+	uint8_t s_bits[MAX_S_BITS];
+	uint8_t m_bits[MAX_M_BITS];
 };
 
 #define TRAU_FT_FR_UP		0x02	/* 0 0 0 1 0 - 3.5.1.1.1 */
@@ -55,10 +55,10 @@
 #define TRAU_FT_IDLE_DOWN	0x0e	/* 0 1 1 1 0 - 3.5.5 */
 
 
-int decode_trau_frame(struct decoded_trau_frame *fr, const u_int8_t *trau_bits);
-int encode_trau_frame(u_int8_t *trau_bits, const struct decoded_trau_frame *fr);
+int decode_trau_frame(struct decoded_trau_frame *fr, const uint8_t *trau_bits);
+int encode_trau_frame(uint8_t *trau_bits, const struct decoded_trau_frame *fr);
 int trau_frame_up2down(struct decoded_trau_frame *fr);
-u_int8_t *trau_idle_frame(void);
+uint8_t *trau_idle_frame(void);
 
 
 #endif /* _TRAU_FRAME_H */
diff --git a/include/openbsc/trau_mux.h b/include/openbsc/trau_mux.h
index dcf33ee..9936ba1 100644
--- a/include/openbsc/trau_mux.h
+++ b/include/openbsc/trau_mux.h
@@ -28,6 +28,10 @@
  * optimization to routing them externally.
  */
 
+#include <stdint.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/mncc.h>
+
 /* map a TRAU mux map entry */
 int trau_mux_map(const struct gsm_e1_subslot *src,
 		 const struct gsm_e1_subslot *dst);
@@ -35,14 +39,14 @@
 			const struct gsm_lchan *dst);
 
 /* unmap a TRAU mux map entry */
-int trau_mux_unmap(const struct gsm_e1_subslot *ss, u_int32_t callref);
+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 u_int8_t *trau_bits, int num_bits);
+		   const uint8_t *trau_bits, int num_bits);
 
 /* add a trau receiver */
-int trau_recv_lchan(struct gsm_lchan *lchan, u_int32_t callref);
+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);
diff --git a/include/openbsc/ussd.h b/include/openbsc/ussd.h
index 6f80d23..2665468 100644
--- a/include/openbsc/ussd.h
+++ b/include/openbsc/ussd.h
@@ -3,7 +3,7 @@
 
 /* Handler function for mobile-originated USSD messages */
 
-#include <osmocore/msgb.h>
+#include <osmocom/core/msgb.h>
 
 int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg);
 
diff --git a/include/openbsc/vty.h b/include/openbsc/vty.h
index 516c8c2..6635896 100644
--- a/include/openbsc/vty.h
+++ b/include/openbsc/vty.h
@@ -35,12 +35,14 @@
 	MSC_NODE,
 	OM2K_NODE,
 	TRUNK_NODE,
+	PGROUP_NODE,
 };
 
 extern int bsc_vty_is_config_node(struct vty *vty, int node);
 extern void bsc_replace_string(void *ctx, char **dst, const char *newstr);
 
-int bsc_vty_init(void);
+struct log_info;
+int bsc_vty_init(const struct log_info *cat);
 int bsc_vty_init_extra(void);
 
 #endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 1573563..df7b936 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,6 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 
 SUBDIRS = libcommon libabis libmgcp libbsc libmsc libtrau osmo-nitb osmo-bsc_mgcp utils ipaccess libgb gprs
 
diff --git a/src/Makefile.in b/src/Makefile.in
index b1c2f08..e3683e0 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -38,7 +38,7 @@
 subdir = src
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -129,6 +129,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -198,8 +200,8 @@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 SUBDIRS = libcommon libabis libmgcp libbsc libmsc libtrau osmo-nitb \
 	osmo-bsc_mgcp utils ipaccess libgb gprs $(am__append_1) \
 	$(am__append_2)
diff --git a/src/gprs/Makefile.am b/src/gprs/Makefile.am
index 16c2200..b6eccee 100644
--- a/src/gprs/Makefile.am
+++ b/src/gprs/Makefile.am
@@ -1,6 +1,6 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS=-Wall -fno-strict-aliasing $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS=-Wall -fno-strict-aliasing $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
 
 noinst_HEADERS = gprs_sndcp.h
 
diff --git a/src/gprs/Makefile.in b/src/gprs/Makefile.in
index 99ea739..a32ab4d 100644
--- a/src/gprs/Makefile.in
+++ b/src/gprs/Makefile.in
@@ -40,7 +40,7 @@
 DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
 	$(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -120,6 +120,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -189,8 +191,8 @@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS = -Wall -fno-strict-aliasing $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS = -Wall -fno-strict-aliasing $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
 noinst_HEADERS = gprs_sndcp.h
 osmo_gbproxy_SOURCES = gb_proxy.c gb_proxy_main.c gb_proxy_vty.c
 osmo_gbproxy_LDADD = $(top_builddir)/src/libgb/libgb.a \
diff --git a/src/gprs/crc24.c b/src/gprs/crc24.c
index 4d65e6e..1a420ed 100644
--- a/src/gprs/crc24.c
+++ b/src/gprs/crc24.c
@@ -19,11 +19,10 @@
  *
  */
 
-#include <sys/types.h>
 #include <openbsc/crc24.h>
 
 /* CRC24 table - FCS */
-static const u_int32_t tbl_crc24[256] = {
+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,
@@ -60,7 +59,7 @@
 
 #define INIT_CRC24	0xffffff
 
-u_int32_t crc24_calc(u_int32_t fcs, u_int8_t *cp, unsigned int len)
+uint32_t crc24_calc(uint32_t fcs, uint8_t *cp, unsigned int len)
 {
 	while (len--)
 		fcs = (fcs >> 8) ^ tbl_crc24[(fcs ^ *cp++) & 0xff];
diff --git a/src/gprs/gb_proxy.c b/src/gprs/gb_proxy.c
index 8df93a9..1261ccc 100644
--- a/src/gprs/gb_proxy.c
+++ b/src/gprs/gb_proxy.c
@@ -27,11 +27,10 @@
 #include <errno.h>
 #include <sys/fcntl.h>
 #include <sys/stat.h>
-#include <sys/types.h>
 #include <arpa/inet.h>
 
-#include <osmocore/talloc.h>
-#include <osmocore/select.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/select.h>
 
 #include <openbsc/signal.h>
 #include <openbsc/debug.h>
diff --git a/src/gprs/gb_proxy_main.c b/src/gprs/gb_proxy_main.c
index b53e985..028f989 100644
--- a/src/gprs/gb_proxy_main.c
+++ b/src/gprs/gb_proxy_main.c
@@ -28,15 +28,15 @@
 #include <signal.h>
 #include <sys/fcntl.h>
 #include <sys/stat.h>
-#include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include <osmocore/talloc.h>
-#include <osmocore/select.h>
-#include <osmocore/rate_ctr.h>
-#include <osmocore/process.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/process.h>
 
 #include <openbsc/signal.h>
 #include <openbsc/debug.h>
@@ -47,6 +47,7 @@
 
 #include <osmocom/vty/command.h>
 #include <osmocom/vty/telnet_interface.h>
+#include <osmocom/vty/logging.h>
 
 #include "../../bscconfig.h"
 
@@ -64,7 +65,6 @@
 	"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_target *stderr_target;
 static char *config_file = "osmo_gbproxy.cfg";
 struct gbproxy_config gbcfg;
 static int daemonize = 0;
@@ -74,7 +74,7 @@
 
 /* call-back function for the NS protocol */
 static int proxy_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
-		      struct msgb *msg, u_int16_t bvci)
+		      struct msgb *msg, uint16_t bvci)
 {
 	int rc = 0;
 
@@ -98,7 +98,7 @@
 
 	switch (signal) {
 	case SIGINT:
-		dispatch_signal(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
+		osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
 		sleep(1);
 		exit(0);
 		break;
@@ -162,10 +162,10 @@
 			print_help();
 			exit(0);
 		case 's':
-			log_set_use_color(stderr_target, 0);
+			log_set_use_color(osmo_stderr_target, 0);
 			break;
 		case 'd':
-			log_parse_category_mask(stderr_target, optarg);
+			log_parse_category_mask(osmo_stderr_target, optarg);
 			break;
 		case 'D':
 			daemonize = 1;
@@ -174,10 +174,10 @@
 			config_file = strdup(optarg);
 			break;
 		case 'T':
-			log_set_print_timestamp(stderr_target, 1);
+			log_set_print_timestamp(osmo_stderr_target, 1);
 			break;
 		case 'e':
-			log_set_log_level(stderr_target, atoi(optarg));
+			log_set_log_level(osmo_stderr_target, atoi(optarg));
 			break;
 		case 'V':
 			print_version(1);
@@ -212,16 +212,13 @@
 	signal(SIGABRT, &signal_handler);
 	signal(SIGUSR1, &signal_handler);
 	signal(SIGUSR2, &signal_handler);
-	signal(SIGPIPE, SIG_IGN);
+	osmo_init_ignore_signals();
 
-	log_init(&log_info);
-	stderr_target = log_target_create_stderr();
-	log_add_target(stderr_target);
-	log_set_all_filter(stderr_target, 1);
+	osmo_init_logging(&log_info);
 
 	vty_info.copyright = openbsc_copyright;
 	vty_init(&vty_info);
-	logging_vty_add_cmds();
+	logging_vty_add_cmds(&log_info);
 	gbproxy_vty_init();
 
 	handle_options(argc, argv);
@@ -239,7 +236,7 @@
 	}
 	gbcfg.nsi = bssgp_nsi;
 	gprs_ns_vty_init(bssgp_nsi);
-	register_signal_handler(SS_NS, &gbprox_signal, NULL);
+	osmo_signal_register_handler(SS_NS, &gbprox_signal, NULL);
 
 	rc = gbproxy_parse_config(config_file, &gbcfg);
 	if (rc < 0) {
@@ -279,7 +276,7 @@
 	gbprox_reset_persistent_nsvcs(bssgp_nsi);
 
 	while (1) {
-		rc = bsc_select_main(0);
+		rc = osmo_select_main(0);
 		if (rc < 0)
 			exit(3);
 	}
diff --git a/src/gprs/gb_proxy_vty.c b/src/gprs/gb_proxy_vty.c
index 05f5b1e..1aa4ff5 100644
--- a/src/gprs/gb_proxy_vty.c
+++ b/src/gprs/gb_proxy_vty.c
@@ -18,12 +18,11 @@
  *
  */
 
-#include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 
 #include <openbsc/debug.h>
 #include <openbsc/gb_proxy.h>
diff --git a/src/gprs/gprs_gmm.c b/src/gprs/gprs_gmm.c
index 949cd96..46c4931 100644
--- a/src/gprs/gprs_gmm.c
+++ b/src/gprs/gprs_gmm.c
@@ -31,12 +31,12 @@
 #include <arpa/inet.h>
 
 #include <openbsc/db.h>
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.h>
-#include <osmocore/gsm_utils.h>
-#include <osmocore/signal.h>
-#include <osmocore/talloc.h>
-#include <osmocore/rate_ctr.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 <openbsc/debug.h>
 #include <openbsc/gsm_data.h>
@@ -208,7 +208,7 @@
 static void mmctx_timer_start(struct sgsn_mm_ctx *mm, unsigned int T,
 				unsigned int seconds)
 {
-	if (bsc_timer_pending(&mm->timer))
+	if (osmo_timer_pending(&mm->timer))
 		LOGP(DMM, LOGL_ERROR, "Starting MM timer %u while old "
 			"timer %u pending\n", T, mm->T);
 	mm->T = T;
@@ -218,7 +218,7 @@
 	mm->timer.data = mm;
 	mm->timer.cb = &mmctx_timer_cb;
 
-	bsc_schedule_timer(&mm->timer, seconds, 0);
+	osmo_timer_schedule(&mm->timer, seconds, 0);
 }
 
 static void mmctx_timer_stop(struct sgsn_mm_ctx *mm, unsigned int T)
@@ -226,7 +226,7 @@
 	if (mm->T != T)
 		LOGP(DMM, LOGL_ERROR, "Stopping MM timer %u but "
 			"%u is running\n", T, mm->T);
-	bsc_del_timer(&mm->timer);
+	osmo_timer_del(&mm->timer);
 }
 
 /* Send a message through the underlying layer */
@@ -463,7 +463,7 @@
 	uint8_t *m_rand, *m_cksn;
 
 	DEBUGP(DMM, "<- GPRS AUTH AND CIPHERING REQ (rand = %s)\n",
-		hexdump(rand, 16));
+		osmo_hexdump(rand, 16));
 
 	mmctx2msgid(msg, mm);
 
@@ -1087,7 +1087,7 @@
 			/* FIXME */
 			break;
 		}
-		bsc_schedule_timer(&mm->timer, GSM0408_T3350_SECS, 0);
+		osmo_timer_schedule(&mm->timer, GSM0408_T3350_SECS, 0);
 		break;
 	case 3360:	/* waiting for AUTH AND CIPH RESP */
 		if (mm->num_T_exp >= 5) {
@@ -1096,7 +1096,7 @@
 			break;
 		}
 		/* FIXME: re-transmit the respective msg and re-start timer */
-		bsc_schedule_timer(&mm->timer, GSM0408_T3360_SECS, 0);
+		osmo_timer_schedule(&mm->timer, GSM0408_T3360_SECS, 0);
 		break;
 	case 3370:	/* waiting for IDENTITY RESPONSE */
 		if (mm->num_T_exp >= 5) {
@@ -1107,7 +1107,7 @@
 		}
 		/* re-tranmit IDENTITY REQUEST and re-start timer */
 		gsm48_tx_gmm_id_req(mm, mm->t3370_id_type);
-		bsc_schedule_timer(&mm->timer, GSM0408_T3370_SECS, 0);
+		osmo_timer_schedule(&mm->timer, GSM0408_T3370_SECS, 0);
 		break;
 	default:
 		LOGP(DMM, LOGL_ERROR, "timer expired in unknown mode %u\n",
@@ -1122,7 +1122,7 @@
 static void pdpctx_timer_start(struct sgsn_pdp_ctx *pdp, unsigned int T,
 				unsigned int seconds)
 {
-	if (bsc_timer_pending(&pdp->timer))
+	if (osmo_timer_pending(&pdp->timer))
 		LOGP(DMM, LOGL_ERROR, "Starting MM timer %u while old "
 			"timer %u pending\n", T, pdp->T);
 	pdp->T = T;
@@ -1132,7 +1132,7 @@
 	pdp->timer.data = pdp;
 	pdp->timer.cb = &pdpctx_timer_cb;
 
-	bsc_schedule_timer(&pdp->timer, seconds, 0);
+	osmo_timer_schedule(&pdp->timer, seconds, 0);
 }
 
 
@@ -1457,7 +1457,7 @@
 			break;
 		}
 		gsm48_tx_gsm_deact_pdp_req(pdp, GSM_CAUSE_NET_FAIL); 
-		bsc_schedule_timer(&pdp->timer, GSM0408_T3395_SECS, 0);
+		osmo_timer_schedule(&pdp->timer, GSM0408_T3395_SECS, 0);
 		break;
 	default:
 		LOGP(DMM, LOGL_ERROR, "timer expired in unknown mode %u\n",
diff --git a/src/gprs/gprs_llc.c b/src/gprs/gprs_llc.c
index 7991f4c..f7408ef 100644
--- a/src/gprs/gprs_llc.c
+++ b/src/gprs/gprs_llc.c
@@ -22,10 +22,10 @@
 #include <errno.h>
 #include <stdint.h>
 
-#include <osmocore/msgb.h>
-#include <osmocore/linuxlist.h>
-#include <osmocore/timer.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/core/talloc.h>
 
 #include <openbsc/gsm_data.h>
 #include <openbsc/debug.h>
diff --git a/src/gprs/gprs_llc_vty.c b/src/gprs/gprs_llc_vty.c
index d4f743b..ab52699 100644
--- a/src/gprs/gprs_llc_vty.c
+++ b/src/gprs/gprs_llc_vty.c
@@ -27,11 +27,11 @@
 #include <arpa/inet.h>
 
 #include <openbsc/gsm_data.h>
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.h>
-#include <osmocore/talloc.h>
-#include <osmocore/select.h>
-#include <osmocore/rate_ctr.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>
diff --git a/src/gprs/gprs_sgsn.c b/src/gprs/gprs_sgsn.c
index 4436554..85f7105 100644
--- a/src/gprs/gprs_sgsn.c
+++ b/src/gprs/gprs_sgsn.c
@@ -21,10 +21,10 @@
 
 #include <stdint.h>
 
-#include <osmocore/linuxlist.h>
-#include <osmocore/talloc.h>
-#include <osmocore/timer.h>
-#include <osmocore/rate_ctr.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/core/rate_ctr.h>
 #include <openbsc/gsm_subscriber.h>
 #include <openbsc/debug.h>
 #include <openbsc/gprs_sgsn.h>
diff --git a/src/gprs/gprs_sndcp.c b/src/gprs/gprs_sndcp.c
index 4f421e4..1307fe5 100644
--- a/src/gprs/gprs_sndcp.c
+++ b/src/gprs/gprs_sndcp.c
@@ -23,10 +23,10 @@
 #include <errno.h>
 #include <stdint.h>
 
-#include <osmocore/msgb.h>
-#include <osmocore/linuxlist.h>
-#include <osmocore/timer.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/core/talloc.h>
 
 #include <openbsc/gsm_data.h>
 #include <openbsc/debug.h>
diff --git a/src/gprs/gprs_sndcp.h b/src/gprs/gprs_sndcp.h
index e9a50be..fef871a 100644
--- a/src/gprs/gprs_sndcp.h
+++ b/src/gprs/gprs_sndcp.h
@@ -2,7 +2,7 @@
 #define _INT_SNDCP_H
 
 #include <stdint.h>
-#include <osmocore/linuxlist.h>
+#include <osmocom/core/linuxlist.h>
 
 /* A fragment queue header, maintaining list of fragments for one N-PDU */
 struct defrag_state {
@@ -20,7 +20,7 @@
 	/* linked list of defrag_queue_entry: one for each fragment  */
 	struct llist_head frag_list;
 
-	struct timer_list timer;
+	struct osmo_timer_list timer;
 };
 
 /* See 6.7.1.2 Reassembly */
diff --git a/src/gprs/gprs_sndcp_vty.c b/src/gprs/gprs_sndcp_vty.c
index 5a755d5..28fdc63 100644
--- a/src/gprs/gprs_sndcp_vty.c
+++ b/src/gprs/gprs_sndcp_vty.c
@@ -27,11 +27,11 @@
 #include <arpa/inet.h>
 
 #include <openbsc/gsm_data.h>
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.h>
-#include <osmocore/talloc.h>
-#include <osmocore/select.h>
-#include <osmocore/rate_ctr.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>
diff --git a/src/gprs/sgsn_libgtp.c b/src/gprs/sgsn_libgtp.c
index 7b10a45..f193aa3 100644
--- a/src/gprs/sgsn_libgtp.c
+++ b/src/gprs/sgsn_libgtp.c
@@ -29,14 +29,13 @@
 #include <signal.h>
 #include <sys/fcntl.h>
 #include <sys/stat.h>
-#include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include <osmocore/talloc.h>
-#include <osmocore/select.h>
-#include <osmocore/rate_ctr.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/rate_ctr.h>
 #include <openbsc/gsm_04_08_gprs.h>
 
 #include <openbsc/signal.h>
@@ -506,7 +505,7 @@
 }
 
 /* libgtp select loop integration */
-static int sgsn_gtp_fd_cb(struct bsc_fd *fd, unsigned int what)
+static int sgsn_gtp_fd_cb(struct osmo_fd *fd, unsigned int what)
 {
 	struct sgsn_instance *sgi = fd->data;
 	int rc;
@@ -539,7 +538,7 @@
 	gtp_retranstimeout(sgi->gsn, &next);
 
 	/* re-schedule the timer */
-	bsc_schedule_timer(&sgi->gtp_timer, next.tv_sec, next.tv_usec/1000);
+	osmo_timer_schedule(&sgi->gtp_timer, next.tv_sec, next.tv_usec/1000);
 }
 
 /* timer callback for libgtp retransmissions and ping */
@@ -571,7 +570,7 @@
 	sgi->gtp_fd0.data = sgi;
 	sgi->gtp_fd0.when = BSC_FD_READ;
 	sgi->gtp_fd0.cb = sgsn_gtp_fd_cb;
-	rc = bsc_register_fd(&sgi->gtp_fd0);
+	rc = osmo_fd_register(&sgi->gtp_fd0);
 	if (rc < 0)
 		return rc;
 
@@ -580,7 +579,7 @@
 	sgi->gtp_fd1c.data = sgi;
 	sgi->gtp_fd1c.when = BSC_FD_READ;
 	sgi->gtp_fd1c.cb = sgsn_gtp_fd_cb;
-	bsc_register_fd(&sgi->gtp_fd1c);
+	osmo_fd_register(&sgi->gtp_fd1c);
 	if (rc < 0)
 		return rc;
 
@@ -589,7 +588,7 @@
 	sgi->gtp_fd1u.data = sgi;
 	sgi->gtp_fd1u.when = BSC_FD_READ;
 	sgi->gtp_fd1u.cb = sgsn_gtp_fd_cb;
-	bsc_register_fd(&sgi->gtp_fd1u);
+	osmo_fd_register(&sgi->gtp_fd1u);
 	if (rc < 0)
 		return rc;
 
diff --git a/src/gprs/sgsn_main.c b/src/gprs/sgsn_main.c
index c59265f..bfa2e52 100644
--- a/src/gprs/sgsn_main.c
+++ b/src/gprs/sgsn_main.c
@@ -28,18 +28,19 @@
 #include <signal.h>
 #include <sys/fcntl.h>
 #include <sys/stat.h>
-#include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include <osmocore/talloc.h>
-#include <osmocore/select.h>
-#include <osmocore/rate_ctr.h>
-#include <osmocore/logging.h>
-#include <osmocore/process.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/process.h>
 
 #include <osmocom/vty/telnet_interface.h>
+#include <osmocom/vty/logging.h>
 
 #include <openbsc/signal.h>
 #include <openbsc/debug.h>
@@ -62,7 +63,6 @@
 void *tall_bsc_ctx;
 
 struct gprs_ns_inst *sgsn_nsi;
-static struct log_target *stderr_target;
 static int daemonize = 0;
 const char *openbsc_copyright =
 	"Copyright (C) 2010 Harald Welte and On-Waves\r\n"
@@ -80,7 +80,7 @@
 
 /* call-back function for the NS protocol */
 static int sgsn_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
-		      struct msgb *msg, u_int16_t bvci)
+		      struct msgb *msg, uint16_t bvci)
 {
 	int rc = 0;
 
@@ -105,7 +105,7 @@
 
 	switch (signal) {
 	case SIGINT:
-		dispatch_signal(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
+		osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
 		sleep(1);
 		exit(0);
 		break;
@@ -174,10 +174,10 @@
 			print_help();
 			exit(0);
 		case 's':
-			log_set_use_color(stderr_target, 0);
+			log_set_use_color(osmo_stderr_target, 0);
 			break;
 		case 'd':
-			log_parse_category_mask(stderr_target, optarg);
+			log_parse_category_mask(osmo_stderr_target, optarg);
 			break;
 		case 'D':
 			daemonize = 1;
@@ -186,10 +186,10 @@
 			sgsn_inst.config_file = strdup(optarg);
 			break;
 		case 'T':
-			log_set_print_timestamp(stderr_target, 1);
+			log_set_print_timestamp(osmo_stderr_target, 1);
 			break;
 		case 'e':
-			log_set_log_level(stderr_target, atoi(optarg));
+			log_set_log_level(osmo_stderr_target, atoi(optarg));
 			break;
 		default:
 			/* ignore */
@@ -211,16 +211,13 @@
 	signal(SIGABRT, &signal_handler);
 	signal(SIGUSR1, &signal_handler);
 	signal(SIGUSR2, &signal_handler);
-	signal(SIGPIPE, SIG_IGN);
 
-	log_init(&log_info);
-	stderr_target = log_target_create_stderr();
-	log_add_target(stderr_target);
-	log_set_all_filter(stderr_target, 1);
+	osmo_init_ignore_signals();
+	osmo_init_logging(&log_info);
 
 	vty_info.copyright = openbsc_copyright;
 	vty_init(&vty_info);
-	logging_vty_add_cmds();
+	logging_vty_add_cmds(&log_info);
         sgsn_vty_init();
 
 	handle_options(argc, argv);
@@ -279,7 +276,7 @@
 	}
 
 	while (1) {
-		rc = bsc_select_main(0);
+		rc = osmo_select_main(0);
 		if (rc < 0)
 			exit(3);
 	}
diff --git a/src/gprs/sgsn_vty.c b/src/gprs/sgsn_vty.c
index 74669ff..4c9cf28 100644
--- a/src/gprs/sgsn_vty.c
+++ b/src/gprs/sgsn_vty.c
@@ -18,14 +18,13 @@
  *
  */
 
-#include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include <osmocore/talloc.h>
-#include <osmocore/utils.h>
-#include <osmocore/rate_ctr.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/rate_ctr.h>
 
 #include <openbsc/debug.h>
 #include <openbsc/sgsn.h>
@@ -36,6 +35,7 @@
 
 #include <osmocom/vty/command.h>
 #include <osmocom/vty/vty.h>
+#include <osmocom/vty/misc.h>
 
 #include <pdp.h>
 
diff --git a/src/ipaccess/Makefile.am b/src/ipaccess/Makefile.am
index 144cca1..4fe1e37 100644
--- a/src/ipaccess/Makefile.am
+++ b/src/ipaccess/Makefile.am
@@ -1,9 +1,15 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 
 bin_PROGRAMS = ipaccess-find ipaccess-config ipaccess-proxy
 
+ipaccess_find_LDADD = $(top_builddir)/src/libbsc/libbsc.a \
+		      $(top_builddir)/src/libmsc/libmsc.a \
+		      $(top_builddir)/src/libabis/libabis.a \
+		      $(top_builddir)/src/libbsc/libbsc.a \
+		      $(top_builddir)/src/libtrau/libtrau.a \
+		      $(top_builddir)/src/libcommon/libcommon.a
 ipaccess_find_SOURCES = ipaccess-find.c
 
 ipaccess_config_SOURCES = ipaccess-config.c ipaccess-firmware.c network_listen.c
@@ -18,4 +24,9 @@
 			-ldl -ldbi $(LIBCRYPT)
 
 ipaccess_proxy_SOURCES = ipaccess-proxy.c
-ipaccess_proxy_LDADD = $(top_builddir)/src/libcommon/libcommon.a
+ipaccess_proxy_LDADD = $(top_builddir)/src/libbsc/libbsc.a \
+		       $(top_builddir)/src/libmsc/libmsc.a \
+		       $(top_builddir)/src/libabis/libabis.a \
+		       $(top_builddir)/src/libbsc/libbsc.a \
+		       $(top_builddir)/src/libtrau/libtrau.a \
+		       $(top_builddir)/src/libcommon/libcommon.a
diff --git a/src/ipaccess/Makefile.in b/src/ipaccess/Makefile.in
index 864fa31..790a871 100644
--- a/src/ipaccess/Makefile.in
+++ b/src/ipaccess/Makefile.in
@@ -37,7 +37,7 @@
 subdir = src/ipaccess
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -57,10 +57,19 @@
 	$(top_builddir)/src/libcommon/libcommon.a
 am_ipaccess_find_OBJECTS = ipaccess-find.$(OBJEXT)
 ipaccess_find_OBJECTS = $(am_ipaccess_find_OBJECTS)
-ipaccess_find_LDADD = $(LDADD)
+ipaccess_find_DEPENDENCIES = $(top_builddir)/src/libbsc/libbsc.a \
+	$(top_builddir)/src/libmsc/libmsc.a \
+	$(top_builddir)/src/libabis/libabis.a \
+	$(top_builddir)/src/libbsc/libbsc.a \
+	$(top_builddir)/src/libtrau/libtrau.a \
+	$(top_builddir)/src/libcommon/libcommon.a
 am_ipaccess_proxy_OBJECTS = ipaccess-proxy.$(OBJEXT)
 ipaccess_proxy_OBJECTS = $(am_ipaccess_proxy_OBJECTS)
-ipaccess_proxy_DEPENDENCIES =  \
+ipaccess_proxy_DEPENDENCIES = $(top_builddir)/src/libbsc/libbsc.a \
+	$(top_builddir)/src/libmsc/libmsc.a \
+	$(top_builddir)/src/libabis/libabis.a \
+	$(top_builddir)/src/libbsc/libbsc.a \
+	$(top_builddir)/src/libtrau/libtrau.a \
 	$(top_builddir)/src/libcommon/libcommon.a
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -122,6 +131,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -191,8 +202,15 @@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
+ipaccess_find_LDADD = $(top_builddir)/src/libbsc/libbsc.a \
+		      $(top_builddir)/src/libmsc/libmsc.a \
+		      $(top_builddir)/src/libabis/libabis.a \
+		      $(top_builddir)/src/libbsc/libbsc.a \
+		      $(top_builddir)/src/libtrau/libtrau.a \
+		      $(top_builddir)/src/libcommon/libcommon.a
+
 ipaccess_find_SOURCES = ipaccess-find.c
 ipaccess_config_SOURCES = ipaccess-config.c ipaccess-firmware.c network_listen.c
 
@@ -206,7 +224,13 @@
 			-ldl -ldbi $(LIBCRYPT)
 
 ipaccess_proxy_SOURCES = ipaccess-proxy.c
-ipaccess_proxy_LDADD = $(top_builddir)/src/libcommon/libcommon.a
+ipaccess_proxy_LDADD = $(top_builddir)/src/libbsc/libbsc.a \
+		       $(top_builddir)/src/libmsc/libmsc.a \
+		       $(top_builddir)/src/libabis/libabis.a \
+		       $(top_builddir)/src/libbsc/libbsc.a \
+		       $(top_builddir)/src/libtrau/libtrau.a \
+		       $(top_builddir)/src/libcommon/libcommon.a
+
 all: all-am
 
 .SUFFIXES:
diff --git a/src/ipaccess/ipaccess-config.c b/src/ipaccess/ipaccess-config.c
index d02faea..368f788 100644
--- a/src/ipaccess/ipaccess-config.c
+++ b/src/ipaccess/ipaccess-config.c
@@ -1,7 +1,7 @@
 /* ip.access nanoBTS configuration tool */
 
 /* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009-2010 by Holger Hans Peter Freyther
+ * (C) 2009-2011 by Holger Hans Peter Freyther
  * (C) 2009-2010 by On-Waves
  * All Rights Reserved
  *
@@ -28,15 +28,15 @@
 #include <errno.h>
 #include <sys/fcntl.h>
 #include <sys/stat.h>
-#include <sys/types.h>
 
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
 
-#include <osmocore/select.h>
-#include <osmocore/timer.h>
+#include <osmocom/core/application.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/timer.h>
 #include <openbsc/ipaccess.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/e1_input.h>
@@ -44,7 +44,7 @@
 #include <openbsc/signal.h>
 #include <openbsc/debug.h>
 #include <openbsc/network_listen.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 
 static struct gsm_network *gsmnet;
 
@@ -53,21 +53,22 @@
 static char *prim_oml_ip;
 static char *bts_ip_addr, *bts_ip_mask, *bts_ip_gw;
 static char *unit_id;
-static u_int16_t nv_flags;
-static u_int16_t nv_mask;
+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;
 
 struct sw_load {
-	u_int8_t file_id[255];
-	u_int8_t file_id_len;
+	uint8_t file_id[255];
+	uint8_t file_id_len;
 
-	u_int8_t file_version[255];
-	u_int8_t file_version_len;
+	uint8_t file_version[255];
+	uint8_t file_version_len;
 };
 
 static void *tall_ctx_config = NULL;
@@ -75,8 +76,8 @@
 static struct sw_load *sw_load2 = NULL;
 
 /*
-static u_int8_t prim_oml_attr[] = { 0x95, 0x00, 7, 0x88, 192, 168, 100, 11, 0x00, 0x00 };
-static u_int8_t unit_id_attr[] = { 0x91, 0x00, 9, '2', '3', '4', '2', '/' , '0', '/', '0', 0x00 };
+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 };
 */
 
 /*
@@ -86,7 +87,7 @@
  * result. The nanoBTS will send us a NACK when we did something the
  * BTS didn't like.
  */
-static int ipacc_msg_nack(u_int8_t mt)
+static int ipacc_msg_nack(uint8_t mt)
 {
 	fprintf(stderr, "Failure to set attribute. This seems fatal\n");
 	exit(-1);
@@ -102,7 +103,7 @@
 	}
 }
 
-static int ipacc_msg_ack(u_int8_t mt, struct gsm_bts_trx *trx)
+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");
@@ -129,7 +130,7 @@
 	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", hexdump(physconf_buf, arfcnlist_size+4));
+	DEBUGP(DNM, "physconf_buf (%s)\n", osmo_hexdump(physconf_buf, arfcnlist_size+4));
 	return arfcnlist_size+4;
 }
 
@@ -166,14 +167,14 @@
 					    physconf_buf, physconf_len);
 			break;
 		case NM_IPACC_TESTNO_BCCH_INFO:
-#if 0
 			/* re-start full process with CHAN_USAGE */
-			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);
-#endif
+			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;
@@ -181,7 +182,7 @@
 	return 0;
 }
 
-static int nm_state_event(int evt, u_int8_t obj_class, void *obj,
+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);
 
@@ -348,6 +349,36 @@
 	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" },
@@ -464,7 +495,7 @@
 	msgb_free(nmsg);
 }
 
-static int nm_state_event(int evt, u_int8_t obj_class, void *obj,
+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)
 {
@@ -691,13 +722,37 @@
 	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();
@@ -707,14 +762,9 @@
 	struct gsm_bts *bts;
 	struct sockaddr_in sin;
 	int rc, option_index = 0, stream_id = 0xff;
-	struct log_target *stderr_target;
 
-	log_init(&log_info);
-	stderr_target = log_target_create_stderr();
-	log_add_target(stderr_target);
-	log_set_all_filter(stderr_target, 1);
-	log_set_log_level(stderr_target, 0);
-	log_parse_category_mask(stderr_target, "DNM,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");
@@ -734,16 +784,19 @@
 			{ "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:hs:d:f:wc", long_options,
+		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)
@@ -790,6 +843,15 @@
 		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);
+			}
 		case 's':
 			stream_id = atoi(optarg);
 			break;
@@ -805,12 +867,18 @@
 			dump_files = 1;
 			break;
 		case 'c':
-			log_set_use_color(stderr_target, 0);
+			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);
 		}
 	};
 
@@ -828,16 +896,16 @@
 	if (!gsmnet)
 		exit(1);
 
-	bts = gsm_bts_alloc(gsmnet, GSM_BTS_TYPE_NANOBTS, HARDCODED_TSC,
-				HARDCODED_BSIC);
+	bts = gsm_bts_alloc_register(gsmnet, GSM_BTS_TYPE_NANOBTS, HARDCODED_TSC,
+				     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;
 	
-	register_signal_handler(SS_NM, nm_sig_cb, NULL);
-	register_signal_handler(SS_IPAC_NWL, nwl_sig_cb, NULL);
+	osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL);
+	osmo_signal_register_handler(SS_IPAC_NWL, nwl_sig_cb, NULL);
 
 	ipac_nwl_init();
 
@@ -855,7 +923,7 @@
 	bts->oml_link->ts->sign.delay = 10;
 	bts->c0->rsl_link->ts->sign.delay = 10;
 	while (1) {
-		rc = bsc_select_main(0);
+		rc = osmo_select_main(0);
 		if (rc < 0)
 			exit(3);
 	}
diff --git a/src/ipaccess/ipaccess-find.c b/src/ipaccess/ipaccess-find.c
index bea4b77..3f9bf41 100644
--- a/src/ipaccess/ipaccess-find.c
+++ b/src/ipaccess/ipaccess-find.c
@@ -21,37 +21,16 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
 
-#include <osmocore/select.h>
-#include <osmocore/timer.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/timer.h>
 #include <openbsc/ipaccess.h>
 #include <openbsc/gsm_data.h>
 
-static const char *idtag_names[] = {
-	[IPAC_IDTAG_SERNR]	= "Serial Number",
-	[IPAC_IDTAG_UNITNAME]	= "Unit Name",
-	[IPAC_IDTAG_LOCATION1]	= "Location 1",
-	[IPAC_IDTAG_LOCATION2]	= "Location 2",
-	[IPAC_IDTAG_EQUIPVERS]	= "Equipment Version",
-	[IPAC_IDTAG_SWVERSION]	= "Software Version",
-	[IPAC_IDTAG_IPADDR]	= "IP Address",
-	[IPAC_IDTAG_MACADDR]	= "MAC Address",
-	[IPAC_IDTAG_UNIT]	= "Unit ID",
-};
-
-static const char *ipac_idtag_name(int tag)
-{
-	if (tag >= ARRAY_SIZE(idtag_names))
-		return "unknown";
-
-	return idtag_names[tag];
-}
-
 static int udp_sock(const char *ifname)
 {
 	int fd, rc, bc = 1;
@@ -125,15 +104,15 @@
 
 static int parse_response(unsigned char *buf, int len)
 {
-	u_int8_t t_len;
-	u_int8_t t_tag;
-	u_int8_t *cur = buf;
+	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'  ", ipac_idtag_name(t_tag), cur);
+		printf("%s='%s'  ", ipaccess_idtag_name(t_tag), cur);
 
 		cur += t_len;
 	}
@@ -162,7 +141,7 @@
 	return parse_response(buf+6, len-6);
 }
 
-static int bfd_cb(struct bsc_fd *bfd, unsigned int flags)
+static int bfd_cb(struct osmo_fd *bfd, unsigned int flags)
 {
 	if (flags & BSC_FD_READ)
 		return read_response(bfd->fd);
@@ -173,21 +152,21 @@
 	return 0;
 }
 
-static struct timer_list timer;
+static struct osmo_timer_list timer;
 
 static void timer_cb(void *_data)
 {
-	struct bsc_fd *bfd = _data;
+	struct osmo_fd *bfd = _data;
 
 	bfd->when |= BSC_FD_WRITE;
 
-	bsc_schedule_timer(&timer, 5, 0);
+	osmo_timer_schedule(&timer, 5, 0);
 }
 
 int main(int argc, char **argv)
 {
-	struct bsc_fd bfd;
-	char *ifname;
+	struct osmo_fd bfd;
+	char *ifname = NULL;
 	int rc;
 
 	printf("ipaccess-find (C) 2009 by Harald Welte\n");
@@ -196,9 +175,10 @@
 	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];
 	}
 
-	ifname = argv[1];
 	bfd.cb = bfd_cb;
 	bfd.when = BSC_FD_READ | BSC_FD_WRITE;
 	bfd.fd = udp_sock(ifname);
@@ -207,17 +187,17 @@
 		exit(1);
 	}
 
-	bsc_register_fd(&bfd);
+	osmo_fd_register(&bfd);
 
 	timer.cb = timer_cb;
 	timer.data = &bfd;
 
-	bsc_schedule_timer(&timer, 5, 0);
+	osmo_timer_schedule(&timer, 5, 0);
 
 	printf("Trying to find ip.access BTS by broadcast UDP...\n");
 
 	while (1) {
-		rc = bsc_select_main(0);
+		rc = osmo_select_main(0);
 		if (rc < 0)
 			exit(3);
 	}
diff --git a/src/ipaccess/ipaccess-firmware.c b/src/ipaccess/ipaccess-firmware.c
index 7fdd0f8..6d39107 100644
--- a/src/ipaccess/ipaccess-firmware.c
+++ b/src/ipaccess/ipaccess-firmware.c
@@ -20,7 +20,7 @@
 
 #include <openbsc/debug.h>
 #include <openbsc/ipaccess.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -29,8 +29,8 @@
 
 #define PART_LENGTH 138
 
-static_assert(sizeof(struct sdp_header_entry) == 138, right_entry);
-static_assert(sizeof(struct sdp_firmware) == 158, _right_header_length);
+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 };
@@ -41,8 +41,8 @@
 	struct sdp_header *header;
 	char buf[4096];
 	int rc, i;
-	u_int16_t table_size;
-	u_int16_t table_offset;
+	uint16_t table_size;
+	uint16_t table_offset;
 	off_t table_start;
 
 
diff --git a/src/ipaccess/ipaccess-proxy.c b/src/ipaccess/ipaccess-proxy.c
index 2dc1b2f..b4d17e2 100644
--- a/src/ipaccess/ipaccess-proxy.c
+++ b/src/ipaccess/ipaccess-proxy.c
@@ -29,7 +29,6 @@
 #include <signal.h>
 #include <time.h>
 #include <sys/fcntl.h>
-#include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <arpa/inet.h>
@@ -39,25 +38,25 @@
 #include <getopt.h>
 
 #include <openbsc/gsm_data.h>
-#include <osmocore/select.h>
-#include <osmocore/tlv.h>
-#include <osmocore/msgb.h>
+#include <osmocom/core/application.h>
+#include <osmocom/core/select.h>
+#include <osmocom/gsm/tlv.h>
+#include <osmocom/core/msgb.h>
 #include <openbsc/debug.h>
 #include <openbsc/ipaccess.h>
-#include <osmocore/talloc.h>
-
-static struct log_target *stderr_target;
+#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 bsc_fd oml_listen_fd;
+	struct osmo_fd oml_listen_fd;
 	/* socket where we listen for incoming RSL from BTS */
-	struct bsc_fd rsl_listen_fd;
+	struct osmo_fd rsl_listen_fd;
 	/* list of BTS's (struct ipa_bts_conn */
 	struct llist_head bts_list;
 	/* the BSC reconnect timer */
-	struct timer_list reconn_timer;
+	struct osmo_timer_list reconn_timer;
 	/* global GPRS NS data */
 	struct in_addr gprs_addr;
 	struct in_addr listen_addr;
@@ -67,7 +66,7 @@
 static struct ipa_proxy *ipp;
 
 struct ipa_proxy_conn {
-	struct bsc_fd fd;
+	struct osmo_fd fd;
 	struct llist_head tx_queue;
 	struct ipa_bts_conn *bts_conn;
 };
@@ -81,8 +80,8 @@
 	struct ipa_proxy *ipp;
 	/* the unit ID as determined by CCM */
 	struct {
-		u_int16_t site_id;
-		u_int16_t bts_id;
+		uint16_t site_id;
+		uint16_t bts_id;
 	} unit_id;
 
 	/* incoming connections from BTS */
@@ -94,18 +93,18 @@
 	struct ipa_proxy_conn *bsc_rsl_conn[MAX_TRX];
 
 	/* UDP sockets for BTS and BSC injection */
-	struct bsc_fd udp_bts_fd;
-	struct bsc_fd udp_bsc_fd;
+	struct osmo_fd udp_bts_fd;
+	struct osmo_fd udp_bsc_fd;
 
 	/* NS data */
 	struct in_addr bts_addr;
-	struct bsc_fd gprs_ns_fd;
+	struct osmo_fd gprs_ns_fd;
 	int gprs_local_port;
 	uint16_t gprs_orig_port;
 	uint32_t gprs_orig_ip;
 
 	char *id_tags[0xff];
-	u_int8_t *id_resp;
+	uint8_t *id_resp;
 	unsigned int id_resp_len;
 };
 
@@ -125,104 +124,13 @@
 static char *bsc_ipaddr;
 static char *gprs_ns_ipaddr;
 
-static int make_gprs_sock(struct bsc_fd *bfd, int (*cb)(struct bsc_fd*,unsigned int), void *);
-static int gprs_ns_cb(struct bsc_fd *bfd, unsigned int what);
+static int gprs_ns_cb(struct osmo_fd *bfd, unsigned int what);
 
 #define PROXY_ALLOC_SIZE	1200
 
-static const u_int8_t pong[] = { 0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_PONG };
-static const u_int8_t id_ack[] = { 0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_ID_ACK };
-static const u_int8_t id_req[] = { 0, 17, IPAC_PROTO_IPACCESS, 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,
-				};
-
-static const char *idtag_names[] = {
-	[IPAC_IDTAG_SERNR]	= "Serial_Number",
-	[IPAC_IDTAG_UNITNAME]	= "Unit_Name",
-	[IPAC_IDTAG_LOCATION1]	= "Location_1",
-	[IPAC_IDTAG_LOCATION2]	= "Location_2",
-	[IPAC_IDTAG_EQUIPVERS]	= "Equipment_Version",
-	[IPAC_IDTAG_SWVERSION]	= "Software_Version",
-	[IPAC_IDTAG_IPADDR]	= "IP_Address",
-	[IPAC_IDTAG_MACADDR]	= "MAC_Address",
-	[IPAC_IDTAG_UNIT]	= "Unit_ID",
-};
-
-static const char *ipac_idtag_name(int tag)
-{
-	if (tag >= ARRAY_SIZE(idtag_names))
-		return "unknown";
-
-	return idtag_names[tag];
-}
-
-static int ipac_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len)
-{
-	u_int8_t t_len;
-	u_int8_t t_tag;
-	u_int8_t *cur = buf;
-
-	while (cur < buf + len) {
-		t_len = *cur++;
-		t_tag = *cur++;
-
-		DEBUGPC(DMI, "%s='%s' ", ipac_idtag_name(t_tag), cur);
-
-		dec->lv[t_tag].len = t_len;
-		dec->lv[t_tag].val = cur;
-
-		cur += t_len;
-	}
-	return 0;
-}
-
-static int parse_unitid(const char *str, u_int16_t *site_id, u_int16_t *bts_id,
-			u_int16_t *trx_id)
-{
-	unsigned long ul;
-	char *endptr;
-	const char *nptr;
-
-	nptr = str;
-	ul = strtoul(nptr, &endptr, 10);
-	if (endptr <= nptr)
-		return -EINVAL;
-	if (site_id)
-		*site_id = ul & 0xffff;
-
-	if (*endptr++ != '/')
-		return -EINVAL;
-
-	nptr = endptr;
-	ul = strtoul(nptr, &endptr, 10);
-	if (endptr <= nptr)
-		return -EINVAL;
-	if (bts_id)
-		*bts_id = ul & 0xffff;
-
-	if (*endptr++ != '/')
-		return -EINVAL;
-
-	nptr = endptr;
-	ul = strtoul(nptr, &endptr, 10);
-	if (endptr <= nptr)
-		return -EINVAL;
-	if (trx_id)
-		*trx_id = ul & 0xffff;
-
-	return 0;
-}
-
 static struct ipa_bts_conn *find_bts_by_unitid(struct ipa_proxy *ipp,
-						u_int16_t site_id,
-						u_int16_t bts_id)
+						uint16_t site_id,
+						uint16_t bts_id)
 {
 	struct ipa_bts_conn *ipbc;
 
@@ -279,7 +187,7 @@
 #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, u_int8_t trx_id)
+			   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,
@@ -288,44 +196,7 @@
 		logp2(ss, lvl, file, line, 0, "unknown ");
 }
 
-/* UDP socket handling */
-
-static int make_sock(struct bsc_fd *bfd, u_int16_t port, int proto, int priv_nr,
-		     int (*cb)(struct bsc_fd *fd, unsigned int what),
-		     void *data)
-{
-	struct sockaddr_in addr;
-	int ret, on = 1;
-
-	bfd->fd = socket(AF_INET, SOCK_DGRAM, proto);
-	bfd->cb = cb;
-	bfd->when = BSC_FD_READ;
-	bfd->data = data;
-	bfd->priv_nr = priv_nr;
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sin_family = AF_INET;
-	addr.sin_port = htons(port);
-	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(DINP, LOGL_ERROR, "could not bind socket: %s\n",
-			strerror(errno));
-		return -EIO;
-	}
-
-	ret = bsc_register_fd(bfd);
-	if (ret < 0) {
-		perror("register UDP fd");
-		return ret;
-	}
-	return 0;
-}
-
-static int handle_udp_read(struct bsc_fd *bfd)
+static int handle_udp_read(struct osmo_fd *bfd)
 {
 	struct ipa_bts_conn *ipbc = bfd->data;
 	struct ipa_proxy_conn *other_conn = NULL;
@@ -345,7 +216,7 @@
 	}
 	if (ret == 0) {
 		DEBUGP(DINP, "UDP peer disappeared, dead socket\n");
-		bsc_unregister_fd(bfd);
+		osmo_fd_unregister(bfd);
 		close(bfd->fd);
 		bfd->fd = -1;
 		msgb_free(msg);
@@ -358,7 +229,7 @@
 	}
 	msgb_put(msg, ret);
 	msg->l2h = msg->data + sizeof(*hh);
-	DEBUGP(DMI, "UDP RX: %s\n", hexdump(msg->data, msg->len));
+	DEBUGP(DMI, "UDP RX: %s\n", osmo_hexdump(msg->data, msg->len));
 
 	if (hh->len != msg->len - sizeof(*hh)) {
 		DEBUGP(DINP, "length (%u/%u) disagrees with header(%u)\n",
@@ -416,7 +287,7 @@
 	return 0;
 }
 
-static int handle_udp_write(struct bsc_fd *bfd)
+static int handle_udp_write(struct osmo_fd *bfd)
 {
 	/* not implemented yet */
 	bfd->when &= ~BSC_FD_WRITE;
@@ -425,7 +296,7 @@
 }
 
 /* callback from select.c in case one of the fd's can be read/written */
-static int udp_fd_cb(struct bsc_fd *bfd, unsigned int what)
+static int udp_fd_cb(struct osmo_fd *bfd, unsigned int what)
 {
 	int rc = 0;
 
@@ -438,13 +309,13 @@
 }
 
 
-static int ipbc_alloc_connect(struct ipa_proxy_conn *ipc, struct bsc_fd *bfd,
-			      u_int16_t site_id, u_int16_t bts_id,
-			      u_int16_t trx_id, struct tlv_parsed *tlvp,
+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;
-	u_int16_t udp_port;
+	uint16_t udp_port;
 	int ret = 0;
 	struct sockaddr_in sin;
 
@@ -494,7 +365,7 @@
 
 	/* Create UDP socket for BTS packet injection */
 	udp_port = 10000 + (site_id % 1000)*100 + (bts_id % 100);
-	ret = make_sock(&ipbc->udp_bts_fd, udp_port, IPPROTO_UDP,
+	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;
@@ -503,7 +374,7 @@
 
 	/* Create UDP socket for BSC packet injection */
 	udp_port = 20000 + (site_id % 1000)*100 + (bts_id % 100);
-	ret = make_sock(&ipbc->udp_bsc_fd, udp_port, IPPROTO_UDP,
+	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;
@@ -515,7 +386,13 @@
 	if (gprs_ns_ipaddr) {
 		struct sockaddr_in sock;
 		socklen_t len = sizeof(sock);
-		ret = make_gprs_sock(&ipbc->gprs_ns_fd, gprs_ns_cb, ipbc);
+		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(DINP, LOGL_ERROR, "Creating the GPRS socket failed.\n");
 			goto err_udp_bsc;
@@ -536,9 +413,9 @@
 	return 0;
 
 err_udp_bsc:
-	bsc_unregister_fd(&ipbc->udp_bts_fd);
+	osmo_fd_unregister(&ipbc->udp_bts_fd);
 err_udp_bts:
-	bsc_unregister_fd(&ipbc->bsc_oml_conn->fd);
+	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;
@@ -546,7 +423,7 @@
 	talloc_free(ipbc->id_resp);
 	talloc_free(ipbc);
 #if 0
-	bsc_unregister_fd(bfd);
+	osmo_fd_unregister(bfd);
 	close(bfd->fd);
 	talloc_free(bfd);
 #endif
@@ -555,23 +432,17 @@
 }
 
 static int ipaccess_rcvmsg(struct ipa_proxy_conn *ipc, struct msgb *msg,
-			   struct bsc_fd *bfd)
+			   struct osmo_fd *bfd)
 {
 	struct tlv_parsed tlvp;
-	u_int8_t msg_type = *(msg->l2h);
-	u_int16_t site_id, bts_id, trx_id;
+	uint8_t msg_type = *(msg->l2h);
+	uint16_t site_id, bts_id, trx_id;
 	struct ipa_bts_conn *ipbc;
 	int ret = 0;
 
 	switch (msg_type) {
 	case IPAC_MSGT_PING:
-		ret = write(bfd->fd, pong, sizeof(pong));
-		if (ret < 0)
-			return ret;
-		if (ret < sizeof(pong)) {
-			DEBUGP(DINP, "short write\n");
-			return -EIO;
-		}
+		ret = ipaccess_send_pong(bfd->fd);
 		break;
 	case IPAC_MSGT_PONG:
 		DEBUGP(DMI, "PONG!\n");
@@ -579,8 +450,8 @@
 	case IPAC_MSGT_ID_RESP:
 		DEBUGP(DMI, "ID_RESP ");
 		/* parse tags, search for Unit ID */
-		ipac_idtag_parse(&tlvp, (u_int8_t *)msg->l2h + 2,
-				 msgb_l2len(msg)-2);
+		ipaccess_idtag_parse(&tlvp, (uint8_t *)msg->l2h + 2,
+				     msgb_l2len(msg)-2);
 		DEBUGP(DMI, "\n");
 
 		if (!TLVP_PRESENT(&tlvp, IPAC_IDTAG_UNIT)) {
@@ -590,8 +461,8 @@
 
 		/* lookup BTS, create sign_link, ... */
 		site_id = bts_id = trx_id = 0;
-		parse_unitid((char *)TLVP_VAL(&tlvp, IPAC_IDTAG_UNIT),
-			     &site_id, &bts_id, &trx_id);
+		ipaccess_parse_unitid((char *)TLVP_VAL(&tlvp, IPAC_IDTAG_UNIT),
+				      &site_id, &bts_id, &trx_id);
 		ipbc = find_bts_by_unitid(ipp, site_id, bts_id);
 		if (!ipbc) {
 			/* We have not found an ipbc (per-bts proxy instance)
@@ -654,7 +525,7 @@
 		break;
 	case IPAC_MSGT_ID_ACK:
 		DEBUGP(DMI, "ID_ACK? -> ACK!\n");
-		ret = write(bfd->fd, id_ack, sizeof(id_ack));
+		ret = ipaccess_send_id_ack(bfd->fd);
 		break;
 	default:
 		LOGP(DMI, LOGL_ERROR, "Unhandled IPA type; %d\n", msg_type);
@@ -664,7 +535,7 @@
 	return 0;
 }
 
-struct msgb *ipaccess_read_msg(struct bsc_fd *bfd, int *error)
+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;
@@ -785,10 +656,10 @@
 	return;
 
 reschedule:
-	bsc_schedule_timer(&ipp->reconn_timer, 5, 0);
+	osmo_timer_schedule(&ipp->reconn_timer, 5, 0);
 }
 
-static void handle_dead_socket(struct bsc_fd *bfd)
+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 */
@@ -796,7 +667,7 @@
 	unsigned int trx_id = bfd->priv_nr >> 8;
 	struct msgb *msg, *msg2;
 
-	bsc_unregister_fd(bfd);
+	osmo_fd_unregister(bfd);
 	close(bfd->fd);
 	bfd->fd = -1;
 
@@ -806,10 +677,15 @@
 
 	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 */
-		bsc_unregister_fd(&bsc_conn->fd);
+		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);
@@ -821,7 +697,7 @@
 		ipbc->rsl_conn[trx_id] = NULL;
 		bsc_conn = ipbc->bsc_rsl_conn[trx_id];
 		/* close the connection to the BSC */
-		bsc_unregister_fd(&bsc_conn->fd);
+		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);
@@ -832,13 +708,13 @@
 		ipbc->bsc_oml_conn = NULL;
 		bsc_conn = ipbc->oml_conn;
 		/* start reconnect timer */
-		bsc_schedule_timer(&ipp->reconn_timer, 5, 0);
+		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 */
-		bsc_schedule_timer(&ipp->reconn_timer, 5, 0);
+		osmo_timer_schedule(&ipp->reconn_timer, 5, 0);
 		break;
 	default:
 		bsc_conn = NULL;
@@ -871,20 +747,20 @@
 	    msg->l2h[2] == 0x00 && msg->l2h[3] == 0x15 &&
 	    msg->l2h[18] == 0xf5 && msg->l2h[19] == 0xf2) {
 		nsvci = &msg->l2h[23];
-		ipbc->gprs_orig_port =  *(u_int16_t *)(nsvci+8);
-		ipbc->gprs_orig_ip = *(u_int32_t *)(nsvci+10);
-		*(u_int16_t *)(nsvci+8) = htons(ipbc->gprs_local_port);
-		*(u_int32_t *)(nsvci+10) = ipbc->ipp->listen_addr.s_addr;
+		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];
-		*(u_int16_t *)(nsvci+8) = ipbc->gprs_orig_port;
-		*(u_int32_t *)(nsvci+10) = ipbc->gprs_orig_ip;
+		*(uint16_t *)(nsvci+8) = ipbc->gprs_orig_port;
+		*(uint32_t *)(nsvci+10) = ipbc->gprs_orig_ip;
 	}
 }
 
-static int handle_tcp_read(struct bsc_fd *bfd)
+static int handle_tcp_read(struct osmo_fd *bfd)
 {
 	struct ipa_proxy_conn *ipc = bfd->data;
 	struct ipa_bts_conn *ipbc = ipc->bts_conn;
@@ -899,7 +775,7 @@
 	else
 		btsbsc = "BSC";
 
-	msg = ipaccess_read_msg(bfd, &ret);
+	msg = ipaccess_proxy_read_msg(bfd, &ret);
 	if (!msg) {
 		if (ret == 0) {
 			logp_ipbc_uid(DINP, LOGL_NOTICE, ipbc, bfd->priv_nr >> 8);
@@ -912,13 +788,13 @@
 
 	msgb_put(msg, ret);
 	logp_ipbc_uid(DMI, LOGL_DEBUG, ipbc, bfd->priv_nr >> 8);
-	DEBUGPC(DMI, "RX<-%s: %s\n", btsbsc, hexdump(msg->data, msg->len));
+	DEBUGPC(DMI, "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) {
-			bsc_unregister_fd(bfd);
+			osmo_fd_unregister(bfd);
 			close(bfd->fd);
 			bfd->fd = -1;
 			talloc_free(bfd);
@@ -958,7 +834,7 @@
 }
 
 /* a TCP socket is ready to be written to */
-static int handle_tcp_write(struct bsc_fd *bfd)
+static int handle_tcp_write(struct osmo_fd *bfd)
 {
 	struct ipa_proxy_conn *ipc = bfd->data;
 	struct ipa_bts_conn *ipbc = ipc->bts_conn;
@@ -984,7 +860,7 @@
 
 	logp_ipbc_uid(DMI, LOGL_DEBUG, ipbc, bfd->priv_nr >> 8);
 	DEBUGPC(DMI, "TX %04x: %s\n", bfd->priv_nr,
-		hexdump(msg->data, msg->len));
+		osmo_hexdump(msg->data, msg->len));
 
 	ret = send(bfd->fd, msg->data, msg->len, 0);
 	msgb_free(msg);
@@ -999,7 +875,7 @@
 }
 
 /* callback from select.c in case one of the fd's can be read/written */
-static int ipaccess_fd_cb(struct bsc_fd *bfd, unsigned int what)
+static int ipaccess_fd_cb(struct osmo_fd *bfd, unsigned int what)
 {
 	int rc = 0;
 
@@ -1015,11 +891,11 @@
 }
 
 /* callback of the listening filedescriptor */
-static int listen_fd_cb(struct bsc_fd *listen_bfd, unsigned int what)
+static int listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what)
 {
 	int ret;
 	struct ipa_proxy_conn *ipc;
-	struct bsc_fd *bfd;
+	struct osmo_fd *bfd;
 	struct sockaddr_in sa;
 	socklen_t sa_len = sizeof(sa);
 
@@ -1047,7 +923,7 @@
 	bfd->priv_nr = listen_bfd->priv_nr;
 	bfd->cb = ipaccess_fd_cb;
 	bfd->when = BSC_FD_READ;
-	ret = bsc_register_fd(bfd);
+	ret = osmo_fd_register(bfd);
 	if (ret < 0) {
 		LOGP(DINP, LOGL_ERROR, "could not register FD\n");
 		close(bfd->fd);
@@ -1056,7 +932,7 @@
 	}
 
 	/* Request ID. FIXME: request LOCATION, HW/SW VErsion, Unit Name, Serno */
-	ret = write(bfd->fd, id_req, sizeof(id_req));
+	ret = ipaccess_send_id_req(bfd->fd);
 
 	return 0;
 }
@@ -1078,7 +954,7 @@
 	}
 }
 
-static int gprs_ns_cb(struct bsc_fd *bfd, unsigned int what)
+static int gprs_ns_cb(struct osmo_fd *bfd, unsigned int what)
 {
 	struct ipa_bts_conn *bts;
 	char buf[4096];
@@ -1109,85 +985,11 @@
 	return 0;
 }
 
-static int make_listen_sock(struct bsc_fd *bfd, u_int16_t port, int priv_nr,
-		     int (*cb)(struct bsc_fd *fd, unsigned int what))
-{
-	struct sockaddr_in addr;
-	int ret, on = 1;
-
-	bfd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-	bfd->cb = cb;
-	bfd->when = BSC_FD_READ;
-	bfd->priv_nr = priv_nr;
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sin_family = AF_INET;
-	addr.sin_port = htons(port);
-	if (!listen_ipaddr)
-		addr.sin_addr.s_addr = INADDR_ANY;
-	else
-		inet_aton(listen_ipaddr, &addr.sin_addr);
-
-	setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-
-	ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
-	if (ret < 0) {
-		LOGP(DINP, LOGL_ERROR,
-			"Could not bind listen socket for IP %s with error: %s.\n",
-			listen_ipaddr, strerror(errno));
-		return -EIO;
-	}
-
-	ret = listen(bfd->fd, 1);
-	if (ret < 0) {
-		perror("listen");
-		return ret;
-	}
-
-	ret = bsc_register_fd(bfd);
-	if (ret < 0) {
-		perror("register_listen_fd");
-		return ret;
-	}
-	return 0;
-}
-
-static int make_gprs_sock(struct bsc_fd *bfd, int (*cb)(struct bsc_fd*,unsigned int), void *data)
-{
-	struct sockaddr_in addr;
-	int ret;
-
-	bfd->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-	bfd->cb = cb;
-	bfd->data = data;
-	bfd->when = BSC_FD_READ;
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sin_family = AF_INET;
-	addr.sin_port = 0;
-	inet_aton(listen_ipaddr, &addr.sin_addr);
-
-	ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
-	if (ret < 0) {
-		LOGP(DINP, LOGL_ERROR,
-			"Could not bind n socket for IP %s with error: %s.\n",
-			listen_ipaddr, strerror(errno));
-		return -EIO;
-	}
-
-	ret = bsc_register_fd(bfd);
-	if (ret < 0) {
-		perror("register_listen_fd");
-		return ret;
-	}
-	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 bsc_fd *bfd;
+	struct osmo_fd *bfd;
 	int ret, on = 1;
 
 	ipc = alloc_conn();
@@ -1215,7 +1017,7 @@
 	}
 
 	/* pre-fill tx_queue with identity request */
-	ret = bsc_register_fd(bfd);
+	ret = osmo_fd_register(bfd);
 	if (ret < 0) {
 		close(bfd->fd);
 		talloc_free(ipc);
@@ -1237,14 +1039,14 @@
 	ipp->reconn_timer.data = ipp;
 
 	/* Listen for OML connections */
-	ret = make_listen_sock(&ipp->oml_listen_fd, IPA_TCP_PORT_OML,
-				OML_FROM_BTS, listen_fd_cb);
+	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_listen_sock(&ipp->rsl_listen_fd, IPA_TCP_PORT_RSL,
-				RSL_FROM_BTS, listen_fd_cb);
+	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;
@@ -1290,11 +1092,22 @@
 
 static void print_usage()
 {
-	printf("Usage: ipaccess-proxy\n");
+	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[] = {
@@ -1304,7 +1117,6 @@
 			{"log-level", 1, 0, 'e'},
 			{"listen", 1, 0, 'l'},
 			{"bsc", 1, 0, 'b'},
-			{"udp", 1, 0, 'u'},
 			{0, 0, 0, 0}
 		};
 
@@ -1320,43 +1132,59 @@
 			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(stderr_target, 0);
+			log_set_use_color(osmo_stderr_target, 0);
 			break;
 		case 'T':
-			log_set_print_timestamp(stderr_target, 1);
+			log_set_print_timestamp(osmo_stderr_target, 1);
 			break;
 		case 'e':
-			log_set_log_level(stderr_target, atoi(optarg));
+			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;
 
-	listen_ipaddr = "192.168.100.11";
-	bsc_ipaddr = "192.168.100.239";
-
 	tall_bsc_ctx = talloc_named_const(NULL, 1, "ipaccess-proxy");
 
-	log_init(&log_info);
-	stderr_target = log_target_create_stderr();
-	log_add_target(stderr_target);
-	log_set_all_filter(stderr_target, 1);
-	log_parse_category_mask(stderr_target, "DINP:DMI");
+	osmo_init_logging(&log_info);
+	log_parse_category_mask(osmo_stderr_target, "DINP:DMI");
 
 	handle_options(argc, argv);
 
@@ -1366,8 +1194,9 @@
 
 	signal(SIGUSR1, &signal_handler);
 	signal(SIGABRT, &signal_handler);
+	osmo_init_ignore_signals();
 
 	while (1) {
-		bsc_select_main(0);
+		osmo_select_main(0);
 	}
 }
diff --git a/src/ipaccess/network_listen.c b/src/ipaccess/network_listen.c
index aaf7c97..a719903 100644
--- a/src/ipaccess/network_listen.c
+++ b/src/ipaccess/network_listen.c
@@ -28,10 +28,10 @@
 
 #include <arpa/inet.h>
 
-#include <osmocore/talloc.h>
-#include <osmocore/timer.h>
-#include <osmocore/rxlev_stat.h>
-#include <osmocore/gsm48_ie.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>
@@ -191,17 +191,17 @@
 			last_arfcn = binfo.arfcn;
 		}
 		if (binfo.info_type & IPAC_BINF_NEIGH_BA_SI2) {
-			DEBUGP(DNM, "BA SI2: %s\n", hexdump(binfo.ba_list_si2, sizeof(binfo.ba_list_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", hexdump(binfo.ba_list_si2bis, sizeof(binfo.ba_list_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", hexdump(binfo.ba_list_si2ter, sizeof(binfo.ba_list_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);
 		}
@@ -222,7 +222,7 @@
 		msg->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");
-		dispatch_signal(SS_IPAC_NWL, S_IPAC_NWL_COMPLETE, msg->trx);
+		osmo_signal_dispatch(SS_IPAC_NWL, S_IPAC_NWL_COMPLETE, msg->trx);
 		break;
 	case NM_IPACC_TESTRES_PARTIAL:
 		msg->trx->ipaccess.test_state = IPAC_TEST_S_PARTIAL;
@@ -247,5 +247,5 @@
 
 void ipac_nwl_init(void)
 {
-	register_signal_handler(SS_NM, nwl_sig_cb, NULL);
+	osmo_signal_register_handler(SS_NM, nwl_sig_cb, NULL);
 }
diff --git a/src/libabis/Makefile.am b/src/libabis/Makefile.am
index 0df7b5a..ffaa201 100644
--- a/src/libabis/Makefile.am
+++ b/src/libabis/Makefile.am
@@ -1,6 +1,6 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 
 noinst_LIBRARIES = libabis.a
 
diff --git a/src/libabis/Makefile.in b/src/libabis/Makefile.in
index 90d6287..a47ca70 100644
--- a/src/libabis/Makefile.in
+++ b/src/libabis/Makefile.in
@@ -35,7 +35,7 @@
 subdir = src/libabis
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -115,6 +115,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -184,8 +186,8 @@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 noinst_LIBRARIES = libabis.a
 libabis_a_SOURCES = e1_input.c e1_input_vty.c \
 			input/misdn.c		\
diff --git a/src/libabis/e1_input.c b/src/libabis/e1_input.c
index 3b6644e..97dcd33 100644
--- a/src/libabis/e1_input.c
+++ b/src/libabis/e1_input.c
@@ -26,7 +26,6 @@
 #include <string.h>
 #include <time.h>
 #include <sys/fcntl.h>
-#include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <arpa/inet.h>
@@ -39,18 +38,18 @@
 #define PF_ISDN AF_ISDN
 #endif
 
-#include <osmocore/select.h>
-#include <osmocore/msgb.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/msgb.h>
 #include <openbsc/debug.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/e1_input.h>
 #include <openbsc/abis_nm.h>
 #include <openbsc/abis_rsl.h>
-#include <osmocore/linuxlist.h>
+#include <osmocom/core/linuxlist.h>
 #include <openbsc/subchan_demux.h>
 #include <openbsc/trau_frame.h>
 #include <openbsc/trau_mux.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/signal.h>
 #include <openbsc/misdn.h>
 
@@ -75,44 +74,44 @@
 #define PCAP_OUTPUT		1
 
 struct pcap_hdr {
-	u_int32_t magic_number;
-	u_int16_t version_major;
-	u_int16_t version_minor;
+	uint32_t magic_number;
+	uint16_t version_major;
+	uint16_t version_minor;
 	int32_t  thiszone;
-	u_int32_t sigfigs;
-	u_int32_t snaplen;
-	u_int32_t network;
+	uint32_t sigfigs;
+	uint32_t snaplen;
+	uint32_t network;
 } __attribute__((packed));
 
 struct pcaprec_hdr {
-	u_int32_t ts_sec;
-	u_int32_t ts_usec;
-	u_int32_t incl_len;
-	u_int32_t orig_len;
+	uint32_t ts_sec;
+	uint32_t ts_usec;
+	uint32_t incl_len;
+	uint32_t orig_len;
 } __attribute__((packed));
 
 struct fake_linux_lapd_header {
-        u_int16_t pkttype;
-	u_int16_t hatype;
-	u_int16_t halen;
-	u_int64_t addr;
+        uint16_t pkttype;
+	uint16_t hatype;
+	uint16_t halen;
+	uint64_t addr;
 	int16_t protocol;
 } __attribute__((packed));
 
 struct lapd_header {
-	u_int8_t ea1 : 1;
-	u_int8_t cr : 1;
-	u_int8_t sapi : 6;
-	u_int8_t ea2 : 1;
-	u_int8_t tei : 7;
-	u_int8_t control_foo; /* fake UM's ... */
+	uint8_t ea1 : 1;
+	uint8_t cr : 1;
+	uint8_t sapi : 6;
+	uint8_t ea2 : 1;
+	uint8_t tei : 7;
+	uint8_t control_foo; /* fake UM's ... */
 } __attribute__((packed));
 
-static_assert(offsetof(struct fake_linux_lapd_header, hatype) == 2,    hatype_offset);
-static_assert(offsetof(struct fake_linux_lapd_header, halen) == 4,     halen_offset);
-static_assert(offsetof(struct fake_linux_lapd_header, addr) == 6,      addr_offset);
-static_assert(offsetof(struct fake_linux_lapd_header, protocol) == 14, proto_offset);
-static_assert(sizeof(struct fake_linux_lapd_header) == 16,	       lapd_header_size);
+osmo_static_assert(offsetof(struct fake_linux_lapd_header, hatype) == 2,    hatype_offset);
+osmo_static_assert(offsetof(struct fake_linux_lapd_header, halen) == 4,     halen_offset);
+osmo_static_assert(offsetof(struct fake_linux_lapd_header, addr) == 6,      addr_offset);
+osmo_static_assert(offsetof(struct fake_linux_lapd_header, protocol) == 14, proto_offset);
+osmo_static_assert(sizeof(struct fake_linux_lapd_header) == 16,	       lapd_header_size);
 
 
 static int pcap_fd = -1;
@@ -207,7 +206,7 @@
 }
 
 /* callback when a TRAU frame was received */
-static int subch_cb(struct subch_demux *dmx, int ch, u_int8_t *data, int len,
+static int subch_cb(struct subch_demux *dmx, int ch, uint8_t *data, int len,
 		    void *_priv)
 {
 	struct e1inp_ts *e1i_ts = _priv;
@@ -230,19 +229,19 @@
 
 	if (!msg->trx) {
 		LOGP(DRSL, LOGL_ERROR, "rsl_sendmsg: msg->trx == NULL: %s\n",
-			hexdump(msg->data, msg->len));
+			osmo_hexdump(msg->data, msg->len));
 		talloc_free(msg);
 		return -EINVAL;
 	} else if (!msg->trx->rsl_link) {
 		LOGP(DRSL, LOGL_ERROR, "rsl_sendmsg: msg->trx->rsl_link == NULL: %s\n",
-			hexdump(msg->data, msg->len));
+			osmo_hexdump(msg->data, msg->len));
 		talloc_free(msg);
 		return -EIO;
 	}
 
 	sign_link = msg->trx->rsl_link;
 	e1i_ts = sign_link->ts;
-	if (!bsc_timer_pending(&e1i_ts->sign.tx_timer)) {
+	if (!osmo_timer_pending(&e1i_ts->sign.tx_timer)) {
 		/* notify the driver we have something to write */
 		e1inp_driver = sign_link->ts->line->driver;
 		e1inp_driver->want_write(e1i_ts);
@@ -277,7 +276,7 @@
 		sign_link = msg->trx->bts->oml_link;
 
 	e1i_ts = sign_link->ts;
-	if (!bsc_timer_pending(&e1i_ts->sign.tx_timer)) {
+	if (!osmo_timer_pending(&e1i_ts->sign.tx_timer)) {
 		/* notify the driver we have something to write */
 		e1inp_driver = sign_link->ts->line->driver;
 		e1inp_driver->want_write(e1i_ts);
@@ -324,7 +323,7 @@
 	return 0;
 }
 
-struct e1inp_line *e1inp_line_get(u_int8_t e1_nr)
+struct e1inp_line *e1inp_line_get(uint8_t e1_nr)
 {
 	struct e1inp_line *e1i_line;
 
@@ -336,7 +335,7 @@
 	return NULL;
 }
 
-struct e1inp_line *e1inp_line_create(u_int8_t e1_nr, const char *driver_name)
+struct e1inp_line *e1inp_line_create(uint8_t e1_nr, const char *driver_name)
 {
 	struct e1inp_driver *driver;
 	struct e1inp_line *line;
@@ -373,7 +372,7 @@
 }
 
 #if 0
-struct e1inp_line *e1inp_line_get_create(u_int8_t e1_nr)
+struct e1inp_line *e1inp_line_get_create(uint8_t e1_nr)
 {
 	struct e1inp_line *line;
 	int i;
@@ -397,7 +396,7 @@
 }
 #endif
 
-static struct e1inp_ts *e1inp_ts_get(u_int8_t e1_nr, u_int8_t ts_nr)
+static struct e1inp_ts *e1inp_ts_get(uint8_t e1_nr, uint8_t ts_nr)
 {
 	struct e1inp_line *e1i_line;
 
@@ -408,7 +407,7 @@
 	return &e1i_line->ts[ts_nr-1];
 }
 
-struct subch_mux *e1inp_get_mux(u_int8_t e1_nr, u_int8_t ts_nr)
+struct subch_mux *e1inp_get_mux(uint8_t e1_nr, uint8_t ts_nr)
 {
 	struct e1inp_ts *e1i_ts = e1inp_ts_get(e1_nr, ts_nr);
 
@@ -421,7 +420,7 @@
 /* Signalling Link */
 
 struct e1inp_sign_link *e1inp_lookup_sign_link(struct e1inp_ts *e1i,
-					 	u_int8_t tei, u_int8_t sapi)
+						uint8_t tei, uint8_t sapi)
 {
 	struct e1inp_sign_link *link;
 
@@ -437,8 +436,8 @@
 
 struct e1inp_sign_link *
 e1inp_sign_link_create(struct e1inp_ts *ts, enum e1inp_sign_type type,
-			struct gsm_bts_trx *trx, u_int8_t tei,
-			u_int8_t sapi)
+			struct gsm_bts_trx *trx, uint8_t tei,
+			uint8_t sapi)
 {
 	struct e1inp_sign_link *link;
 
@@ -472,14 +471,14 @@
 	}
 
 	if (link->ts->type == E1INP_TS_TYPE_SIGN)
-		bsc_del_timer(&link->ts->sign.tx_timer);
+		osmo_timer_del(&link->ts->sign.tx_timer);
 
 	talloc_free(link);
 }
 
 /* the E1 driver tells us he has received something on a TS */
 int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg,
-		u_int8_t tei, u_int8_t sapi)
+		uint8_t tei, uint8_t sapi)
 {
 	struct e1inp_sign_link *link;
 	struct gsm_bts *bts;
@@ -562,7 +561,7 @@
 }
 
 /* called by driver in case some kind of link state event */
-int e1inp_event(struct e1inp_ts *ts, int evt, u_int8_t tei, u_int8_t sapi)
+int e1inp_event(struct e1inp_ts *ts, int evt, uint8_t tei, uint8_t sapi)
 {
 	struct e1inp_sign_link *link;
 	struct input_signal_data isd;
@@ -577,7 +576,7 @@
 	isd.sapi = sapi;
 
 	/* report further upwards */
-	dispatch_signal(SS_INPUT, evt, &isd);
+	osmo_signal_dispatch(SS_INPUT, evt, &isd);
 	return 0;
 }
 
@@ -613,7 +612,7 @@
 	 * configured */
 	memset(&isd, 0, sizeof(isd));
 	isd.line = line;
-	dispatch_signal(SS_INPUT, S_INP_LINE_INIT, &isd);
+	osmo_signal_dispatch(SS_INPUT, S_INP_LINE_INIT, &isd);
 
 	return rc;
 }
@@ -635,15 +634,19 @@
 
 void e1inp_misdn_init(void);
 void e1inp_dahdi_init(void);
+void e1inp_ipaccess_init(void);
+void e1inp_hsl_init(void);
 
 void e1inp_init(void)
 {
 	tall_sigl_ctx = talloc_named_const(tall_bsc_ctx, 1,
 					   "e1inp_sign_link");
-	register_signal_handler(SS_GLOBAL, e1i_sig_cb, NULL);
+	osmo_signal_register_handler(SS_GLOBAL, e1i_sig_cb, NULL);
 
 	e1inp_misdn_init();
 #ifdef HAVE_DAHDI_USER_H
 	e1inp_dahdi_init();
 #endif
+	e1inp_ipaccess_init();
+	e1inp_hsl_init();
 }
diff --git a/src/libabis/e1_input_vty.c b/src/libabis/e1_input_vty.c
index 66bf655..b211e81 100644
--- a/src/libabis/e1_input_vty.c
+++ b/src/libabis/e1_input_vty.c
@@ -19,7 +19,6 @@
 
 #include <stdlib.h>
 #include <unistd.h>
-#include <sys/types.h>
 
 #include <osmocom/vty/command.h>
 #include <osmocom/vty/buffer.h>
@@ -27,12 +26,12 @@
 #include <osmocom/vty/logging.h>
 #include <osmocom/vty/telnet_interface.h>
 
-#include <osmocore/linuxlist.h>
+#include <osmocom/core/linuxlist.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/e1_input.h>
-#include <osmocore/utils.h>
-#include <osmocore/gsm_utils.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/vty.h>
 #include <openbsc/debug.h>
 
@@ -77,6 +76,9 @@
 {
 	struct e1inp_line *line;
 
+	if (llist_empty(&e1inp_line_list))
+		return CMD_SUCCESS;
+
 	vty_out(vty, "e1_input%s", VTY_NEWLINE);
 
 	llist_for_each_entry(line, &e1inp_line_list, list) {
diff --git a/src/libabis/input/dahdi.c b/src/libabis/input/dahdi.c
index 572bb5a..6f89837 100644
--- a/src/libabis/input/dahdi.c
+++ b/src/libabis/input/dahdi.c
@@ -33,14 +33,13 @@
 #include <string.h>
 #include <time.h>
 #include <sys/fcntl.h>
-#include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <arpa/inet.h>
 #include <dahdi/user.h>
 
-#include <osmocore/select.h>
-#include <osmocore/msgb.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/msgb.h>
 #include <openbsc/debug.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/abis_nm.h>
@@ -48,7 +47,7 @@
 #include <openbsc/subchan_demux.h>
 #include <openbsc/e1_input.h>
 #include <openbsc/signal.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 
 #include "lapd.h"
 
@@ -84,16 +83,16 @@
 	switch (evt) {
 	case DAHDI_EVENT_ALARM:
 		/* we should notify the code that the line is gone */
-		dispatch_signal(SS_INPUT, S_INP_LINE_ALARM, &isd);
+		osmo_signal_dispatch(SS_INPUT, S_INP_LINE_ALARM, &isd);
 		break;
 	case DAHDI_EVENT_NOALARM:
 		/* alarm has gone, we should re-start the SABM requests */
-		dispatch_signal(SS_INPUT, S_INP_LINE_NOALARM, &isd);
+		osmo_signal_dispatch(SS_INPUT, S_INP_LINE_NOALARM, &isd);
 		break;
 	}
 }
 
-static int handle_ts1_read(struct bsc_fd *bfd)
+static int handle_ts1_read(struct osmo_fd *bfd)
 {
 	struct e1inp_line *line = bfd->data;
 	unsigned int ts_nr = bfd->priv_nr;
@@ -148,7 +147,7 @@
 			msg->l2h = msg->data + 2;
 		else
 			msg->l2h = msg->data + 1;
-		DEBUGP(DMI, "RX: %s\n", hexdump(msgb_l2(msg), ret));
+		DEBUGP(DMI, "RX: %s\n", osmo_hexdump(msgb_l2(msg), ret));
 		ret = e1inp_rx_ts(e1i_ts, msg, tei, sapi);
 		break;
 	default:
@@ -185,7 +184,7 @@
 
 static void dahdi_write_msg(uint8_t *data, int len, void *cbdata)
 {
-	struct bsc_fd *bfd = cbdata;
+	struct osmo_fd *bfd = cbdata;
 	struct e1inp_line *line = bfd->data;
 	unsigned int ts_nr = bfd->priv_nr;
 	struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
@@ -198,7 +197,7 @@
 		LOGP(DMI, LOGL_NOTICE, "%s write failed %d\n", __func__, ret);
 }
 
-static int handle_ts1_write(struct bsc_fd *bfd)
+static int handle_ts1_write(struct osmo_fd *bfd)
 {
 	struct e1inp_line *line = bfd->data;
 	unsigned int ts_nr = bfd->priv_nr;
@@ -215,7 +214,7 @@
 		return 0;
 	}
 
-	DEBUGP(DMI, "TX: %s\n", hexdump(msg->data, msg->len));
+	DEBUGP(DMI, "TX: %s\n", osmo_hexdump(msg->data, msg->len));
 	lapd_transmit(e1i_ts->driver.dahdi.lapd, sign_link->tei,
 		      sign_link->sapi, msg->data, msg->len);
 	msgb_free(msg);
@@ -223,7 +222,7 @@
 	/* set tx delay timer for next event */
 	e1i_ts->sign.tx_timer.cb = timeout_ts1_write;
 	e1i_ts->sign.tx_timer.data = e1i_ts;
-	bsc_schedule_timer(&e1i_ts->sign.tx_timer, 0, 50000);
+	osmo_timer_schedule(&e1i_ts->sign.tx_timer, 0, 50000);
 
 	return 0;
 }
@@ -231,14 +230,14 @@
 
 static int invertbits = 1;
 
-static u_int8_t flip_table[256];
+static uint8_t flip_table[256];
 
 static void init_flip_bits(void)
 {
         int i,k;
 
         for (i = 0 ; i < 256 ; i++) {
-                u_int8_t sample = 0 ;
+                uint8_t sample = 0 ;
                 for (k = 0; k<8; k++) {
                         if ( i & 1 << k ) sample |= 0x80 >>  k;
                 }
@@ -246,13 +245,13 @@
         }
 }
 
-static u_int8_t * flip_buf_bits ( u_int8_t * buf , int len)
+static uint8_t * flip_buf_bits ( uint8_t * buf , int len)
 {
         int i;
-        u_int8_t * start = buf;
+        uint8_t * start = buf;
 
         for (i = 0 ; i < len; i++) {
-                buf[i] = flip_table[(u_int8_t)buf[i]];
+                buf[i] = flip_table[(uint8_t)buf[i]];
         }
 
         return start;
@@ -260,12 +259,12 @@
 
 #define D_BCHAN_TX_GRAN 160
 /* write to a B channel TS */
-static int handle_tsX_write(struct bsc_fd *bfd)
+static int handle_tsX_write(struct osmo_fd *bfd)
 {
 	struct e1inp_line *line = bfd->data;
 	unsigned int ts_nr = bfd->priv_nr;
 	struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
-	u_int8_t tx_buf[D_BCHAN_TX_GRAN];
+	uint8_t tx_buf[D_BCHAN_TX_GRAN];
 	struct subch_mux *mx = &e1i_ts->trau.mux;
 	int ret;
 
@@ -278,7 +277,7 @@
 	}
 
 	DEBUGP(DMIB, "BCHAN TX: %s\n",
-		hexdump(tx_buf, D_BCHAN_TX_GRAN));
+		osmo_hexdump(tx_buf, D_BCHAN_TX_GRAN));
 
 	if (invertbits) {
 		flip_buf_bits(tx_buf, ret);
@@ -294,7 +293,7 @@
 
 #define D_TSX_ALLOC_SIZE (D_BCHAN_TX_GRAN)
 /* FIXME: read from a B channel TS */
-static int handle_tsX_read(struct bsc_fd *bfd)
+static int handle_tsX_read(struct osmo_fd *bfd)
 {
 	struct e1inp_line *line = bfd->data;
 	unsigned int ts_nr = bfd->priv_nr;
@@ -319,7 +318,7 @@
 
 	msg->l2h = msg->data;
 	DEBUGP(DMIB, "BCHAN RX: %s\n",
-		hexdump(msgb_l2(msg), ret));
+		osmo_hexdump(msgb_l2(msg), ret));
 	ret = e1inp_rx_ts(e1i_ts, msg, 0, 0);
 	/* physical layer indicates that data has been sent,
 	 * we thus can send some more data */
@@ -330,7 +329,7 @@
 }
 
 /* callback from select.c in case one of the fd's can be read/written */
-static int dahdi_fd_cb(struct bsc_fd *bfd, unsigned int what)
+static int dahdi_fd_cb(struct osmo_fd *bfd, unsigned int what)
 {
 	struct e1inp_line *line = bfd->data;
 	unsigned int ts_nr = bfd->priv_nr;
@@ -421,7 +420,7 @@
 		unsigned int idx = ts-1;
 		char openstr[128];
 		struct e1inp_ts *e1i_ts = &line->ts[idx];
-		struct bsc_fd *bfd = &e1i_ts->driver.dahdi.fd;
+		struct osmo_fd *bfd = &e1i_ts->driver.dahdi.fd;
 
 		bfd->data = line;
 		bfd->priv_nr = ts;
@@ -464,7 +463,7 @@
 			return bfd->fd;
 		}
 
-		ret = bsc_register_fd(bfd);
+		ret = osmo_fd_register(bfd);
 		if (ret < 0) {
 			fprintf(stderr, "could not register FD: %s\n",
 				strerror(ret));
diff --git a/src/libabis/input/hsl.c b/src/libabis/input/hsl.c
index 1afe82b..c98a22c 100644
--- a/src/libabis/input/hsl.c
+++ b/src/libabis/input/hsl.c
@@ -38,14 +38,13 @@
 #include <string.h>
 #include <time.h>
 #include <sys/fcntl.h>
-#include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <arpa/inet.h>
 
-#include <osmocore/select.h>
-#include <osmocore/tlv.h>
-#include <osmocore/msgb.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 <openbsc/abis_nm.h>
@@ -55,7 +54,7 @@
 #include <openbsc/ipaccess.h>
 #include <openbsc/socket.h>
 #include <openbsc/signal.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 
 #define HSL_TCP_PORT	2500
 #define HSL_PROTO_DEBUG	0xdd
@@ -65,7 +64,7 @@
 
 /* data structure for one E1 interface with A-bis */
 struct hsl_e1_handle {
-	struct bsc_fd listen_fd;
+	struct osmo_fd listen_fd;
 	struct gsm_network *gsmnet;
 };
 
@@ -82,7 +81,7 @@
 	struct gsm_bts_trx *trx;
 	struct e1inp_ts *ts;
 	struct e1inp_line *line;
-	struct bsc_fd *bfd;
+	struct osmo_fd *bfd;
 
 	if (!bts || !bts->oml_link)
 		return -1;
@@ -93,7 +92,7 @@
 	e1inp_event(ts, S_INP_TEI_DN, bts->oml_link->tei, bts->oml_link->sapi);
 
 	bfd = &ts->driver.ipaccess.fd;
-	bsc_unregister_fd(bfd);
+	osmo_fd_unregister(bfd);
 	close(bfd->fd);
 	bfd->fd = -1;
 
@@ -110,7 +109,7 @@
 	return -1;
 }
 
-static int hsl_drop_ts_fd(struct e1inp_ts *ts, struct bsc_fd *bfd)
+static int hsl_drop_ts_fd(struct e1inp_ts *ts, struct osmo_fd *bfd)
 {
 	struct e1inp_sign_link *link, *link2;
 	int bts_nr = -1;
@@ -120,7 +119,7 @@
 		e1inp_sign_link_destroy(link);
 	}
 
-	bsc_unregister_fd(bfd);
+	osmo_fd_unregister(bfd);
 	close(bfd->fd);
 	bfd->fd = -1;
 
@@ -196,7 +195,7 @@
 	return 0;
 }
 
-static int handle_ts1_read(struct bsc_fd *bfd)
+static int handle_ts1_read(struct osmo_fd *bfd)
 {
 	struct e1inp_line *line = bfd->data;
 	unsigned int ts_nr = bfd->priv_nr;
@@ -219,7 +218,7 @@
 		return error;
 	}
 
-	DEBUGP(DMI, "RX %u: %s\n", ts_nr, hexdump(msgb_l2(msg), msgb_l2len(msg)));
+	DEBUGP(DMI, "RX %u: %s\n", ts_nr, osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
 
 	hh = (struct ipaccess_head *) msg->data;
 	if (hh->proto == HSL_PROTO_DEBUG) {
@@ -291,14 +290,14 @@
 	ts_want_write(e1i_ts);
 }
 
-static int handle_ts1_write(struct bsc_fd *bfd)
+static int handle_ts1_write(struct osmo_fd *bfd)
 {
 	struct e1inp_line *line = bfd->data;
 	unsigned int ts_nr = bfd->priv_nr;
 	struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
 	struct e1inp_sign_link *sign_link;
 	struct msgb *msg;
-	u_int8_t proto;
+	uint8_t proto;
 	int ret;
 
 	bfd->when &= ~BSC_FD_WRITE;
@@ -331,7 +330,7 @@
 	msg->l2h = msg->data;
 	ipaccess_prepend_header(msg, sign_link->tei);
 
-	DEBUGP(DMI, "TX %u: %s\n", ts_nr, hexdump(msg->l2h, msgb_l2len(msg)));
+	DEBUGP(DMI, "TX %u: %s\n", ts_nr, osmo_hexdump(msg->l2h, msgb_l2len(msg)));
 
 	ret = send(bfd->fd, msg->data, msg->len, 0);
 	msgb_free(msg);
@@ -341,13 +340,13 @@
 	e1i_ts->sign.tx_timer.data = e1i_ts;
 
 	/* Reducing this might break the nanoBTS 900 init. */
-	bsc_schedule_timer(&e1i_ts->sign.tx_timer, 0, e1i_ts->sign.delay);
+	osmo_timer_schedule(&e1i_ts->sign.tx_timer, 0, e1i_ts->sign.delay);
 
 	return ret;
 }
 
 /* callback from select.c in case one of the fd's can be read/written */
-static int hsl_fd_cb(struct bsc_fd *bfd, unsigned int what)
+static int hsl_fd_cb(struct osmo_fd *bfd, unsigned int what)
 {
 	struct e1inp_line *line = bfd->data;
 	unsigned int ts_nr = bfd->priv_nr;
@@ -378,14 +377,14 @@
 };
 
 /* callback of the OML listening filedescriptor */
-static int listen_fd_cb(struct bsc_fd *listen_bfd, unsigned int what)
+static int listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what)
 {
 	int ret;
 	int idx = 0;
 	int i;
 	struct e1inp_line *line;
 	struct e1inp_ts *e1i_ts;
-	struct bsc_fd *bfd;
+	struct osmo_fd *bfd;
 	struct sockaddr_in sa;
 	socklen_t sa_len = sizeof(sa);
 
@@ -422,7 +421,7 @@
 	bfd->priv_nr = PRIV_OML;
 	bfd->cb = hsl_fd_cb;
 	bfd->when = BSC_FD_READ;
-	ret = bsc_register_fd(bfd);
+	ret = osmo_fd_register(bfd);
 	if (ret < 0) {
 		LOGP(DINP, LOGL_ERROR, "could not register FD\n");
 		close(bfd->fd);
@@ -438,12 +437,6 @@
 {
 	int ret;
 
-	/* register the driver with the core */
-	/* FIXME: do this in the plugin initializer function */
-	ret = e1inp_driver_register(&hsl_driver);
-	if (ret)
-		return ret;
-
 	e1h = talloc_zero(tall_bsc_ctx, struct hsl_e1_handle);
 	if (!e1h)
 		return -ENOMEM;
@@ -451,10 +444,15 @@
 	e1h->gsmnet = gsmnet;
 
 	/* Listen for connections */
-	ret = make_sock(&e1h->listen_fd, IPPROTO_TCP, 0, HSL_TCP_PORT,
-			listen_fd_cb);
+	ret = make_sock(&e1h->listen_fd, IPPROTO_TCP, INADDR_ANY, HSL_TCP_PORT,
+			0, listen_fd_cb, NULL);
 	if (ret < 0)
 		return ret;
 
 	return 0;
 }
+
+void e1inp_hsl_init(void)
+{
+	e1inp_driver_register(&hsl_driver);
+}
diff --git a/src/libabis/input/ipaccess.c b/src/libabis/input/ipaccess.c
index dcf8d1a..cc2a7a0 100644
--- a/src/libabis/input/ipaccess.c
+++ b/src/libabis/input/ipaccess.c
@@ -28,15 +28,14 @@
 #include <string.h>
 #include <time.h>
 #include <sys/fcntl.h>
-#include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <arpa/inet.h>
 
-#include <osmocore/select.h>
-#include <osmocore/tlv.h>
-#include <osmocore/msgb.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/select.h>
+#include <osmocom/gsm/tlv.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/debug.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/abis_nm.h>
@@ -52,8 +51,8 @@
 
 /* data structure for one E1 interface with A-bis */
 struct ia_e1_handle {
-	struct bsc_fd listen_fd;
-	struct bsc_fd rsl_listen_fd;
+	struct osmo_fd listen_fd;
+	struct osmo_fd rsl_listen_fd;
 	struct gsm_network *gsmnet;
 };
 
@@ -62,18 +61,31 @@
 
 #define TS1_ALLOC_SIZE	900
 
-static const u_int8_t pong[] = { 0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_PONG };
-static const u_int8_t id_ack[] = { 0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_ID_ACK };
-static const u_int8_t id_req[] = { 0, 17, IPAC_PROTO_IPACCESS, 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,
-				};
+/*
+ * Common propietary IPA messages:
+ *	- PONG: in reply to PING.
+ *	- ID_REQUEST: first messages once OML has been established.
+ *	- ID_ACK: in reply to ID_ACK.
+ */
+const uint8_t ipa_pong_msg[] = {
+        0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_PONG
+};
+
+const uint8_t ipa_id_ack_msg[] = {
+        0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_ID_ACK
+};
+
+const uint8_t ipa_id_req_msg[] = {
+        0, 17, IPAC_PROTO_IPACCESS, 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,
+};
 
 static const char *idtag_names[] = {
 	[IPAC_IDTAG_SERNR]	= "Serial_Number",
@@ -87,7 +99,7 @@
 	[IPAC_IDTAG_UNIT]	= "Unit_ID",
 };
 
-static const char *ipac_idtag_name(int tag)
+const char *ipaccess_idtag_name(uint8_t tag)
 {
 	if (tag >= ARRAY_SIZE(idtag_names))
 		return "unknown";
@@ -97,9 +109,9 @@
 
 int ipaccess_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len)
 {
-	u_int8_t t_len;
-	u_int8_t t_tag;
-	u_int8_t *cur = buf;
+	uint8_t t_len;
+	uint8_t t_tag;
+	uint8_t *cur = buf;
 
 	memset(dec, 0, sizeof(*dec));
 
@@ -110,10 +122,10 @@
 
 		if (t_len > len + 1) {
 			LOGP(DMI, LOGL_ERROR, "The tag does not fit: %d\n", t_len);
-			return -1;
+			return -EINVAL;
 		}
 
-		DEBUGPC(DMI, "%s='%s' ", ipac_idtag_name(t_tag), cur);
+		DEBUGPC(DMI, "%s='%s' ", ipaccess_idtag_name(t_tag), cur);
 
 		dec->lv[t_tag].len = t_len;
 		dec->lv[t_tag].val = cur;
@@ -125,7 +137,7 @@
 }
 
 struct gsm_bts *find_bts_by_unitid(struct gsm_network *net,
-				   u_int16_t site_id, u_int16_t bts_id)
+				   uint16_t site_id, uint16_t bts_id)
 {
 	struct gsm_bts *bts;
 
@@ -142,8 +154,8 @@
 	return NULL;
 }
 
-static int parse_unitid(const char *str, u_int16_t *site_id, u_int16_t *bts_id,
-			u_int16_t *trx_id)
+int ipaccess_parse_unitid(const char *str, uint16_t *site_id,
+			  uint16_t *bts_id, uint16_t *trx_id)
 {
 	unsigned long ul;
 	char *endptr;
@@ -179,27 +191,45 @@
 	return 0;
 }
 
-/* send the id ack */
+static int ipaccess_send(int fd, const void *msg, size_t msglen)
+{
+	int ret;
+
+	ret = write(fd, msg, msglen);
+	if (ret < 0)
+		return ret;
+	if (ret < msglen) {
+		LOGP(DINP, LOGL_ERROR, "ipaccess_send: short write\n");
+		return -EIO;
+	}
+	return ret;
+}
+
+int ipaccess_send_pong(int fd)
+{
+	return ipaccess_send(fd, ipa_pong_msg, sizeof(ipa_pong_msg));
+}
+
 int ipaccess_send_id_ack(int fd)
 {
-	return write(fd, id_ack, sizeof(id_ack));
+	return ipaccess_send(fd, ipa_id_ack_msg, sizeof(ipa_id_ack_msg));
 }
 
 int ipaccess_send_id_req(int fd)
 {
-	return write(fd, id_req, sizeof(id_req));
+	return ipaccess_send(fd, ipa_id_req_msg, sizeof(ipa_id_req_msg));
 }
 
 /* base handling of the ip.access protocol */
 int ipaccess_rcvmsg_base(struct msgb *msg,
-			 struct bsc_fd *bfd)
+			 struct osmo_fd *bfd)
 {
-	u_int8_t msg_type = *(msg->l2h);
+	uint8_t msg_type = *(msg->l2h);
 	int ret = 0;
 
 	switch (msg_type) {
 	case IPAC_MSGT_PING:
-		ret = write(bfd->fd, pong, sizeof(pong));
+		ret = ipaccess_send_pong(bfd->fd);
 		break;
 	case IPAC_MSGT_PONG:
 		DEBUGP(DMI, "PONG!\n");
@@ -213,14 +243,14 @@
 }
 
 static int ipaccess_rcvmsg(struct e1inp_line *line, struct msgb *msg,
-			   struct bsc_fd *bfd)
+			   struct osmo_fd *bfd)
 {
 	struct tlv_parsed tlvp;
-	u_int8_t msg_type = *(msg->l2h);
-	u_int16_t site_id = 0, bts_id = 0, trx_id = 0;
+	uint8_t msg_type = *(msg->l2h);
+	uint16_t site_id = 0, bts_id = 0, trx_id = 0;
 	struct gsm_bts *bts;
 	char *unitid;
-	int len;
+	int len, ret;
 
 	/* handle base messages */
 	ipaccess_rcvmsg_base(msg, bfd);
@@ -229,10 +259,14 @@
 	case IPAC_MSGT_ID_RESP:
 		DEBUGP(DMI, "ID_RESP ");
 		/* parse tags, search for Unit ID */
-		ipaccess_idtag_parse(&tlvp, (u_int8_t *)msg->l2h + 2,
-				 msgb_l2len(msg)-2);
+		ret = ipaccess_idtag_parse(&tlvp, (uint8_t *)msg->l2h + 2,
+					   msgb_l2len(msg)-2);
 		DEBUGP(DMI, "\n");
-
+		if (ret < 0) {
+			LOGP(DINP, LOGL_ERROR, "ignoring IPA response message "
+					       "with malformed TLVs\n");
+			return ret;
+		}
 		if (!TLVP_PRESENT(&tlvp, IPAC_IDTAG_UNIT))
 			break;
 
@@ -243,7 +277,7 @@
 		/* lookup BTS, create sign_link, ... */
 		unitid = (char *) TLVP_VAL(&tlvp, IPAC_IDTAG_UNIT);
 		unitid[len - 1] = '\0';
-		parse_unitid(unitid, &site_id, &bts_id, &trx_id);
+		ipaccess_parse_unitid(unitid, &site_id, &bts_id, &trx_id);
 		bts = find_bts_by_unitid(e1h->gsmnet, site_id, bts_id);
 		if (!bts) {
 			LOGP(DINP, LOGL_ERROR, "Unable to find BTS configuration for "
@@ -260,14 +294,14 @@
 						  bts->oml_tei, 0);
 		} else if (bfd->priv_nr == PRIV_RSL) {
 			struct e1inp_ts *e1i_ts;
-			struct bsc_fd *newbfd;
+			struct osmo_fd *newbfd;
 			struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, trx_id);
 
 			/* drop any old rsl connection */
 			ipaccess_drop_rsl(trx);
 
 			if (!bts->oml_link) {
-				bsc_unregister_fd(bfd);
+				osmo_fd_unregister(bfd);
 				close(bfd->fd);
 				bfd->fd = -1;
 				talloc_free(bfd);
@@ -287,10 +321,10 @@
 			/* get rid of our old temporary bfd */
 			memcpy(newbfd, bfd, sizeof(*newbfd));
 			newbfd->priv_nr = PRIV_RSL + trx_id;
-			bsc_unregister_fd(bfd);
+			osmo_fd_unregister(bfd);
 			bfd->fd = -1;
 			talloc_free(bfd);
-			bsc_register_fd(newbfd);
+			osmo_fd_register(newbfd);
 		}
 		break;
 	}
@@ -304,7 +338,7 @@
  * read one ipa message from the socket
  * return NULL in case of error
  */
-struct msgb *ipaccess_read_msg(struct bsc_fd *bfd, int *error)
+struct msgb *ipaccess_read_msg(struct osmo_fd *bfd, int *error)
 {
 	struct msgb *msg = msgb_alloc(TS1_ALLOC_SIZE, "Abis/IP");
 	struct ipaccess_head *hh;
@@ -360,7 +394,7 @@
 	struct gsm_bts_trx *trx;
 	struct e1inp_ts *ts;
 	struct e1inp_line *line;
-	struct bsc_fd *bfd;
+	struct osmo_fd *bfd;
 
 	if (!bts || !bts->oml_link)
 		return -1;
@@ -371,7 +405,7 @@
 	e1inp_event(ts, S_INP_TEI_DN, bts->oml_link->tei, bts->oml_link->sapi);
 
 	bfd = &ts->driver.ipaccess.fd;
-	bsc_unregister_fd(bfd);
+	osmo_fd_unregister(bfd);
 	close(bfd->fd);
 	bfd->fd = -1;
 
@@ -390,19 +424,22 @@
 	return -1;
 }
 
-static int ipaccess_drop(struct e1inp_ts *ts, struct bsc_fd *bfd)
+static int ipaccess_drop(struct e1inp_ts *ts, struct osmo_fd *bfd)
 {
 	struct e1inp_sign_link *link;
 	int bts_nr;
 
-	if (!ts) {
+	if (!ts || !bfd->data) {
 		/*
 		 * If we don't have a TS this means that this is a RSL
 		 * connection but we are not past the authentication
 		 * handling yet. So we can safely delete this bfd and
 		 * wait for a reconnect.
+		 * If we don't have bfd->data this means that a RSL
+		 * connection was accept()ed, but nothing was recv()ed
+		 * and the connection gets close()ed.
 		 */
-		bsc_unregister_fd(bfd);
+		osmo_fd_unregister(bfd);
 		close(bfd->fd);
 		bfd->fd = -1;
 		talloc_free(bfd);
@@ -421,7 +458,7 @@
 
 	/* error case */
 	LOGP(DINP, LOGL_ERROR, "Failed to find a signalling link for ts: %p\n", ts);
-	bsc_unregister_fd(bfd);
+	osmo_fd_unregister(bfd);
 	close(bfd->fd);
 	bfd->fd = -1;
 	return -1;
@@ -429,7 +466,7 @@
 
 int ipaccess_drop_rsl(struct gsm_bts_trx *trx)
 {
-	struct bsc_fd *bfd;
+	struct osmo_fd *bfd;
 	struct e1inp_ts *ts;
 
 	if (!trx || !trx->rsl_link)
@@ -441,7 +478,7 @@
 
 	/* close the socket */
 	bfd = &ts->driver.ipaccess.fd;
-	bsc_unregister_fd(bfd);
+	osmo_fd_unregister(bfd);
 	close(bfd->fd);
 	bfd->fd = -1;
 
@@ -452,7 +489,7 @@
 	return -1;
 }
 
-static int handle_ts1_read(struct bsc_fd *bfd)
+static int handle_ts1_read(struct osmo_fd *bfd)
 {
 	struct e1inp_line *line = bfd->data;
 	unsigned int ts_nr = bfd->priv_nr;
@@ -475,7 +512,7 @@
 		return error;
 	}
 
-	DEBUGP(DMI, "RX %u: %s\n", ts_nr, hexdump(msgb_l2(msg), msgb_l2len(msg)));
+	DEBUGP(DMI, "RX %u: %s\n", ts_nr, osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
 
 	hh = (struct ipaccess_head *) msg->data;
 	if (hh->proto == IPAC_PROTO_IPACCESS) {
@@ -520,6 +557,15 @@
 	return ret;
 }
 
+void ipaccess_prepend_header_ext(struct msgb *msg, int proto)
+{
+	struct ipaccess_head_ext *hh_ext;
+
+	/* prepend the osmo ip.access header extension */
+	hh_ext = (struct ipaccess_head_ext *) msgb_push(msg, sizeof(*hh_ext));
+	hh_ext->proto = proto;
+}
+
 void ipaccess_prepend_header(struct msgb *msg, int proto)
 {
 	struct ipaccess_head *hh;
@@ -545,14 +591,14 @@
 	ts_want_write(e1i_ts);
 }
 
-static int handle_ts1_write(struct bsc_fd *bfd)
+static int handle_ts1_write(struct osmo_fd *bfd)
 {
 	struct e1inp_line *line = bfd->data;
 	unsigned int ts_nr = bfd->priv_nr;
 	struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
 	struct e1inp_sign_link *sign_link;
 	struct msgb *msg;
-	u_int8_t proto;
+	uint8_t proto;
 	int ret;
 
 	bfd->when &= ~BSC_FD_WRITE;
@@ -580,7 +626,7 @@
 	msg->l2h = msg->data;
 	ipaccess_prepend_header(msg, sign_link->tei);
 
-	DEBUGP(DMI, "TX %u: %s\n", ts_nr, hexdump(msg->l2h, msgb_l2len(msg)));
+	DEBUGP(DMI, "TX %u: %s\n", ts_nr, osmo_hexdump(msg->l2h, msgb_l2len(msg)));
 
 	ret = send(bfd->fd, msg->data, msg->len, 0);
 	msgb_free(msg);
@@ -590,13 +636,13 @@
 	e1i_ts->sign.tx_timer.data = e1i_ts;
 
 	/* Reducing this might break the nanoBTS 900 init. */
-	bsc_schedule_timer(&e1i_ts->sign.tx_timer, 0, e1i_ts->sign.delay);
+	osmo_timer_schedule(&e1i_ts->sign.tx_timer, 0, e1i_ts->sign.delay);
 
 	return ret;
 }
 
 /* callback from select.c in case one of the fd's can be read/written */
-static int ipaccess_fd_cb(struct bsc_fd *bfd, unsigned int what)
+static int ipaccess_fd_cb(struct osmo_fd *bfd, unsigned int what)
 {
 	struct e1inp_line *line = bfd->data;
 	unsigned int ts_nr = bfd->priv_nr;
@@ -627,14 +673,14 @@
 };
 
 /* callback of the OML listening filedescriptor */
-static int listen_fd_cb(struct bsc_fd *listen_bfd, unsigned int what)
+static int listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what)
 {
 	int ret;
 	int idx = 0;
 	int i;
 	struct e1inp_line *line;
 	struct e1inp_ts *e1i_ts;
-	struct bsc_fd *bfd;
+	struct osmo_fd *bfd;
 	struct sockaddr_in sa;
 	socklen_t sa_len = sizeof(sa);
 
@@ -671,7 +717,7 @@
 	bfd->priv_nr = PRIV_OML;
 	bfd->cb = ipaccess_fd_cb;
 	bfd->when = BSC_FD_READ;
-	ret = bsc_register_fd(bfd);
+	ret = osmo_fd_register(bfd);
 	if (ret < 0) {
 		LOGP(DINP, LOGL_ERROR, "could not register FD\n");
 		close(bfd->fd);
@@ -686,17 +732,17 @@
 	//return e1inp_line_register(line);
 }
 
-static int rsl_listen_fd_cb(struct bsc_fd *listen_bfd, unsigned int what)
+static int rsl_listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what)
 {
 	struct sockaddr_in sa;
 	socklen_t sa_len = sizeof(sa);
-	struct bsc_fd *bfd;
+	struct osmo_fd *bfd;
 	int ret;
 
 	if (!(what & BSC_FD_READ))
 		return 0;
 
-	bfd = talloc_zero(tall_bsc_ctx, struct bsc_fd);
+	bfd = talloc_zero(tall_bsc_ctx, struct osmo_fd);
 	if (!bfd)
 		return -ENOMEM;
 
@@ -713,7 +759,7 @@
 	bfd->priv_nr = PRIV_RSL;
 	bfd->cb = ipaccess_fd_cb;
 	bfd->when = BSC_FD_READ;
-	ret = bsc_register_fd(bfd);
+	ret = osmo_fd_register(bfd);
 	if (ret < 0) {
 		LOGP(DINP, LOGL_ERROR, "could not register FD\n");
 		close(bfd->fd);
@@ -721,7 +767,7 @@
 		return ret;
 	}
 	/* Request ID. FIXME: request LOCATION, HW/SW VErsion, Unit Name, Serno */
-	ret = write(bfd->fd, id_req, sizeof(id_req));
+	ret = ipaccess_send_id_req(bfd->fd);
 
 	return 0;
 }
@@ -730,7 +776,7 @@
 int ipaccess_connect(struct e1inp_line *line, struct sockaddr_in *sa)
 {
 	struct e1inp_ts *e1i_ts = &line->ts[0];
-	struct bsc_fd *bfd = &e1i_ts->driver.ipaccess.fd;
+	struct osmo_fd *bfd = &e1i_ts->driver.ipaccess.fd;
 	int ret, on = 1;
 
 	bfd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
@@ -753,7 +799,7 @@
 		return ret;
 	}
 
-	ret = bsc_register_fd(bfd);
+	ret = osmo_fd_register(bfd);
 	if (ret < 0) {
 		close(bfd->fd);
 		return ret;
@@ -769,12 +815,6 @@
 {
 	int ret;
 
-	/* register the driver with the core */
-	/* FIXME: do this in the plugin initializer function */
-	ret = e1inp_driver_register(&ipaccess_driver);
-	if (ret)
-		return ret;
-
 	e1h = talloc_zero(tall_bsc_ctx, struct ia_e1_handle);
 	if (!e1h)
 		return -ENOMEM;
@@ -782,16 +822,21 @@
 	e1h->gsmnet = gsmnet;
 
 	/* Listen for OML connections */
-	ret = make_sock(&e1h->listen_fd, IPPROTO_TCP, 0, IPA_TCP_PORT_OML,
-			listen_fd_cb);
+	ret = make_sock(&e1h->listen_fd, IPPROTO_TCP, INADDR_ANY,
+			IPA_TCP_PORT_OML, 0, listen_fd_cb, NULL);
 	if (ret < 0)
 		return ret;
 
 	/* Listen for RSL connections */
-	ret = make_sock(&e1h->rsl_listen_fd, IPPROTO_TCP, 0,
-			IPA_TCP_PORT_RSL, rsl_listen_fd_cb);
+	ret = make_sock(&e1h->rsl_listen_fd, IPPROTO_TCP, INADDR_ANY,
+			IPA_TCP_PORT_RSL, 0, rsl_listen_fd_cb, NULL);
 	if (ret < 0)
 		return ret;
 
 	return ret;
 }
+
+void e1inp_ipaccess_init(void)
+{
+	e1inp_driver_register(&ipaccess_driver);
+}
diff --git a/src/libabis/input/lapd.c b/src/libabis/input/lapd.c
index 7bce6cc..d0fab18 100644
--- a/src/libabis/input/lapd.c
+++ b/src/libabis/input/lapd.c
@@ -36,10 +36,10 @@
 
 #include "lapd.h"
 
-#include <osmocore/linuxlist.h>
-#include <osmocore/talloc.h>
-#include <osmocore/msgb.h>
-#include <osmocore/timer.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/timer.h>
 #include <openbsc/debug.h>
 
 #define SABM_INTERVAL		0, 300000
@@ -137,7 +137,7 @@
 	int va;			/* last acked by peer */
 	int vr;			/* next expected to be received */
 
-	struct timer_list sabme_timer;	/* timer to re-transmit SABM message */
+	struct osmo_timer_list sabme_timer;	/* timer to re-transmit SABM message */
 };
 
 /* 3.5.2.2   Send state variable V(S)
@@ -259,11 +259,11 @@
 	switch (sap->state) {
 	case SAP_STATE_SABM_RETRANS:
 		if (newstate != SAP_STATE_SABM_RETRANS)
-			bsc_del_timer(&sap->sabme_timer);
+			osmo_timer_del(&sap->sabme_timer);
 		break;
 	default:
 		if (newstate == SAP_STATE_SABM_RETRANS)
-			bsc_schedule_timer(&sap->sabme_timer, SABM_INTERVAL);
+			osmo_timer_schedule(&sap->sabme_timer, SABM_INTERVAL);
 		break;
 	}
 
@@ -290,7 +290,7 @@
 		teip = teip_from_tei(li, action);
 		if (!teip) {
 			LOGP(DMI, LOGL_INFO, "TEI MGR: New TEI %u\n", action);
-			lapd_tei_alloc(li, action);
+			teip = lapd_tei_alloc(li, action);
 		}
 
 		/* Send ACCEPT */
@@ -608,7 +608,7 @@
 	lapd_send_sabm(sap->tei->li, sap->tei->tei, sap->sapi);
 
 	if (sap->state == SAP_STATE_SABM_RETRANS)
-		bsc_schedule_timer(&sap->sabme_timer, SABM_INTERVAL);
+		osmo_timer_schedule(&sap->sabme_timer, SABM_INTERVAL);
 }
 
 /* Start a (user-side) SAP for the specified TEI/SAPI on the LAPD instance */
diff --git a/src/libabis/input/lapd.h b/src/libabis/input/lapd.h
index fd11eda..fb980d1 100644
--- a/src/libabis/input/lapd.h
+++ b/src/libabis/input/lapd.h
@@ -3,7 +3,7 @@
 
 #include <stdint.h>
 
-#include <osmocore/linuxlist.h>
+#include <osmocom/core/linuxlist.h>
 
 typedef enum {
 	LAPD_MPH_NONE	= 0,
diff --git a/src/libabis/input/misdn.c b/src/libabis/input/misdn.c
index 4598879..ab92d61 100644
--- a/src/libabis/input/misdn.c
+++ b/src/libabis/input/misdn.c
@@ -27,7 +27,6 @@
 #include <string.h>
 #include <time.h>
 #include <sys/fcntl.h>
-#include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <arpa/inet.h>
@@ -40,9 +39,9 @@
 #define PF_ISDN AF_ISDN
 #endif
 
-#include <osmocore/select.h>
-#include <osmocore/msgb.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/debug.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/abis_nm.h>
@@ -86,7 +85,7 @@
 	return "UNKNOWN";
 }
 
-static int handle_ts1_read(struct bsc_fd *bfd)
+static int handle_ts1_read(struct osmo_fd *bfd)
 {
 	struct e1inp_line *line = bfd->data;
 	unsigned int ts_nr = bfd->priv_nr;
@@ -163,7 +162,7 @@
 	case DL_DATA_IND:
 	case DL_UNITDATA_IND:
 		msg->l2h = msg->data + MISDN_HEADER_LEN;
-		DEBUGP(DMI, "RX: %s\n", hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN));
+		DEBUGP(DMI, "RX: %s\n", osmo_hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN));
 		ret = e1inp_rx_ts(e1i_ts, msg, l2addr.tei, l2addr.sapi);
 		break;
 	case PH_ACTIVATE_IND:
@@ -201,7 +200,7 @@
 	ts_want_write(e1i_ts);
 }
 
-static int handle_ts1_write(struct bsc_fd *bfd)
+static int handle_ts1_write(struct osmo_fd *bfd)
 {
 	struct e1inp_line *line = bfd->data;
 	unsigned int ts_nr = bfd->priv_nr;
@@ -210,7 +209,7 @@
 	struct sockaddr_mISDN sa;
 	struct msgb *msg;
 	struct mISDNhead *hh;
-	u_int8_t *l2_data;
+	uint8_t *l2_data;
 	int ret;
 
 	bfd->when &= ~BSC_FD_WRITE;
@@ -230,7 +229,7 @@
 
 	DEBUGP(DMI, "TX channel(%d) TEI(%d) SAPI(%d): %s\n",
 		sign_link->driver.misdn.channel, sign_link->tei,
-		sign_link->sapi, hexdump(l2_data, msg->len - MISDN_HEADER_LEN));
+		sign_link->sapi, osmo_hexdump(l2_data, msg->len - MISDN_HEADER_LEN));
 
 	/* construct the sockaddr */
 	sa.family = AF_ISDN;
@@ -247,20 +246,20 @@
 	/* set tx delay timer for next event */
 	e1i_ts->sign.tx_timer.cb = timeout_ts1_write;
 	e1i_ts->sign.tx_timer.data = e1i_ts;
-	bsc_schedule_timer(&e1i_ts->sign.tx_timer, 0, e1i_ts->sign.delay);
+	osmo_timer_schedule(&e1i_ts->sign.tx_timer, 0, e1i_ts->sign.delay);
 
 	return ret;
 }
 
 #define BCHAN_TX_GRAN	160
 /* write to a B channel TS */
-static int handle_tsX_write(struct bsc_fd *bfd)
+static int handle_tsX_write(struct osmo_fd *bfd)
 {
 	struct e1inp_line *line = bfd->data;
 	unsigned int ts_nr = bfd->priv_nr;
 	struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
 	struct mISDNhead *hh;
-	u_int8_t tx_buf[BCHAN_TX_GRAN + sizeof(*hh)];
+	uint8_t tx_buf[BCHAN_TX_GRAN + sizeof(*hh)];
 	struct subch_mux *mx = &e1i_ts->trau.mux;
 	int ret;
 
@@ -270,7 +269,7 @@
 	subchan_mux_out(mx, tx_buf+sizeof(*hh), BCHAN_TX_GRAN);
 
 	DEBUGP(DMIB, "BCHAN TX: %s\n",
-		hexdump(tx_buf+sizeof(*hh), BCHAN_TX_GRAN));
+		osmo_hexdump(tx_buf+sizeof(*hh), BCHAN_TX_GRAN));
 
 	ret = send(bfd->fd, tx_buf, sizeof(*hh) + BCHAN_TX_GRAN, 0);
 	if (ret < sizeof(*hh) + BCHAN_TX_GRAN)
@@ -282,7 +281,7 @@
 
 #define TSX_ALLOC_SIZE 4096
 /* FIXME: read from a B channel TS */
-static int handle_tsX_read(struct bsc_fd *bfd)
+static int handle_tsX_read(struct osmo_fd *bfd)
 {
 	struct e1inp_line *line = bfd->data;
 	unsigned int ts_nr = bfd->priv_nr;
@@ -312,7 +311,7 @@
 	case PH_DATA_IND:
 		msg->l2h = msg->data + MISDN_HEADER_LEN;
 		DEBUGP(DMIB, "BCHAN RX: %s\n",
-			hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN));
+			osmo_hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN));
 		ret = e1inp_rx_ts(e1i_ts, msg, 0, 0);
 		break;
 	case PH_ACTIVATE_IND:
@@ -330,7 +329,7 @@
 }
 
 /* callback from select.c in case one of the fd's can be read/written */
-static int misdn_fd_cb(struct bsc_fd *bfd, unsigned int what)
+static int misdn_fd_cb(struct osmo_fd *bfd, unsigned int what)
 {
 	struct e1inp_line *line = bfd->data;
 	unsigned int ts_nr = bfd->priv_nr;
@@ -366,7 +365,7 @@
 	int ret;
 	unsigned int idx = ts-1;
 	struct e1inp_ts *e1i_ts = &line->ts[idx];
-	struct bsc_fd *bfd = &e1i_ts->driver.misdn.fd;
+	struct osmo_fd *bfd = &e1i_ts->driver.misdn.fd;
 
 	fprintf(stdout, "activate bchan\n");
 	if (act)
@@ -401,7 +400,7 @@
 	for (ts = 1; ts < NUM_E1_TS; ts++) {
 		unsigned int idx = ts-1;
 		struct e1inp_ts *e1i_ts = &line->ts[idx];
-		struct bsc_fd *bfd = &e1i_ts->driver.misdn.fd;
+		struct osmo_fd *bfd = &e1i_ts->driver.misdn.fd;
 		struct sockaddr_mISDN addr;
 
 		bfd->data = line;
@@ -471,7 +470,7 @@
 		if (e1i_ts->type == E1INP_TS_TYPE_TRAU)
 			activate_bchan(line, ts, 1);
 
-		ret = bsc_register_fd(bfd);
+		ret = osmo_fd_register(bfd);
 		if (ret < 0) {
 			fprintf(stderr, "could not register FD: %s\n",
 				strerror(ret));
diff --git a/src/libbsc/Makefile.am b/src/libbsc/Makefile.am
index de76929..3af4a2a 100644
--- a/src/libbsc/Makefile.am
+++ b/src/libbsc/Makefile.am
@@ -1,6 +1,6 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 
 noinst_LIBRARIES = libbsc.a
 
@@ -18,8 +18,7 @@
 			handover_decision.c handover_logic.c meas_rep.c \
 			rest_octets.c system_information.c \
 			e1_config.c \
-			transaction.c \
 			bsc_api.c bsc_msc.c bsc_vty.c \
 			gsm_04_08_utils.c \
-			bsc_init.c
+			bsc_init.c bts_init.c
 
diff --git a/src/libbsc/Makefile.in b/src/libbsc/Makefile.in
index e5d3d20..a39c86f 100644
--- a/src/libbsc/Makefile.in
+++ b/src/libbsc/Makefile.in
@@ -35,7 +35,7 @@
 subdir = src/libbsc
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -62,9 +62,9 @@
 	gsm_subscriber_base.$(OBJEXT) handover_decision.$(OBJEXT) \
 	handover_logic.$(OBJEXT) meas_rep.$(OBJEXT) \
 	rest_octets.$(OBJEXT) system_information.$(OBJEXT) \
-	e1_config.$(OBJEXT) transaction.$(OBJEXT) bsc_api.$(OBJEXT) \
-	bsc_msc.$(OBJEXT) bsc_vty.$(OBJEXT) gsm_04_08_utils.$(OBJEXT) \
-	bsc_init.$(OBJEXT)
+	e1_config.$(OBJEXT) bsc_api.$(OBJEXT) bsc_msc.$(OBJEXT) \
+	bsc_vty.$(OBJEXT) gsm_04_08_utils.$(OBJEXT) bsc_init.$(OBJEXT) \
+	bts_init.$(OBJEXT)
 libbsc_a_OBJECTS = $(am_libbsc_a_OBJECTS)
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -121,6 +121,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -190,8 +192,8 @@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 noinst_LIBRARIES = libbsc.a
 libbsc_a_SOURCES = abis_nm.c abis_nm_vty.c \
 			abis_om2000.c abis_om2000_vty.c \
@@ -207,10 +209,9 @@
 			handover_decision.c handover_logic.c meas_rep.c \
 			rest_octets.c system_information.c \
 			e1_config.c \
-			transaction.c \
 			bsc_api.c bsc_msc.c bsc_vty.c \
 			gsm_04_08_utils.c \
-			bsc_init.c
+			bsc_init.c bts_init.c
 
 all: all-am
 
@@ -272,6 +273,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsc_vty.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bts_ericsson_rbs2000.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bts_hsl_femtocell.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bts_init.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bts_ipaccess_nanobts.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bts_siemens_bs11.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bts_unknown.Po@am__quote@
@@ -285,7 +287,6 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/paging.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rest_octets.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/system_information.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transaction.Po@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff --git a/src/libbsc/abis_nm.c b/src/libbsc/abis_nm.c
index 0e7fc8d..494d4ca 100644
--- a/src/libbsc/abis_nm.c
+++ b/src/libbsc/abis_nm.c
@@ -30,16 +30,16 @@
 #include <time.h>
 #include <limits.h>
 
-#include <sys/types.h>
 #include <sys/stat.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
 #include <openbsc/gsm_data.h>
 #include <openbsc/debug.h>
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/tlv.h>
+#include <osmocom/gsm/abis_nm.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/abis_nm.h>
 #include <openbsc/misdn.h>
 #include <openbsc/signal.h>
@@ -48,302 +48,7 @@
 #define OM_HEADROOM_SIZE	128
 #define IPACC_SEGMENT_SIZE	245
 
-/* unidirectional messages from BTS to BSC */
-static const enum abis_nm_msgtype reports[] = {
-	NM_MT_SW_ACTIVATED_REP,
-	NM_MT_TEST_REP,
-	NM_MT_STATECHG_EVENT_REP,
-	NM_MT_FAILURE_EVENT_REP,
-};
-
-/* messages without ACK/NACK */
-static const enum abis_nm_msgtype no_ack_nack[] = {
-	NM_MT_MEAS_RES_REQ,
-	NM_MT_STOP_MEAS,
-	NM_MT_START_MEAS,
-};
-
-/* Messages related to software load */
-static const enum abis_nm_msgtype sw_load_msgs[] = {
-	NM_MT_LOAD_INIT_ACK,
-	NM_MT_LOAD_INIT_NACK,
-	NM_MT_LOAD_SEG_ACK,
-	NM_MT_LOAD_ABORT,
-	NM_MT_LOAD_END_ACK,
-	NM_MT_LOAD_END_NACK,
-	//NM_MT_SW_ACT_REQ,
-	NM_MT_ACTIVATE_SW_ACK,
-	NM_MT_ACTIVATE_SW_NACK,
-	NM_MT_SW_ACTIVATED_REP,
-};
-
-static const enum abis_nm_msgtype nacks[] = {
-	NM_MT_LOAD_INIT_NACK,
-	NM_MT_LOAD_END_NACK,
-	NM_MT_SW_ACT_REQ_NACK,
-	NM_MT_ACTIVATE_SW_NACK,
-	NM_MT_ESTABLISH_TEI_NACK,
-	NM_MT_CONN_TERR_SIGN_NACK,
-	NM_MT_DISC_TERR_SIGN_NACK,
-	NM_MT_CONN_TERR_TRAF_NACK,
-	NM_MT_DISC_TERR_TRAF_NACK,
-	NM_MT_CONN_MDROP_LINK_NACK,
-	NM_MT_DISC_MDROP_LINK_NACK,
-	NM_MT_SET_BTS_ATTR_NACK,
-	NM_MT_SET_RADIO_ATTR_NACK,
-	NM_MT_SET_CHAN_ATTR_NACK,
-	NM_MT_PERF_TEST_NACK,
-	NM_MT_SEND_TEST_REP_NACK,
-	NM_MT_STOP_TEST_NACK,
-	NM_MT_STOP_EVENT_REP_NACK,
-	NM_MT_REST_EVENT_REP_NACK,
-	NM_MT_CHG_ADM_STATE_NACK,
-	NM_MT_CHG_ADM_STATE_REQ_NACK,
-	NM_MT_REP_OUTST_ALARMS_NACK,
-	NM_MT_CHANGEOVER_NACK,
-	NM_MT_OPSTART_NACK,
-	NM_MT_REINIT_NACK,
-	NM_MT_SET_SITE_OUT_NACK,
-	NM_MT_CHG_HW_CONF_NACK,
-	NM_MT_GET_ATTR_NACK,
-	NM_MT_SET_ALARM_THRES_NACK,
-	NM_MT_BS11_BEGIN_DB_TX_NACK,
-	NM_MT_BS11_END_DB_TX_NACK,
-	NM_MT_BS11_CREATE_OBJ_NACK,
-	NM_MT_BS11_DELETE_OBJ_NACK,
-};
-
-static const struct value_string nack_names[] = {
-	{ NM_MT_LOAD_INIT_NACK,		"SOFTWARE LOAD INIT" },
-	{ NM_MT_LOAD_END_NACK,		"SOFTWARE LOAD END" },
-	{ NM_MT_SW_ACT_REQ_NACK,	"SOFTWARE ACTIVATE REQUEST" },
-	{ NM_MT_ACTIVATE_SW_NACK,	"ACTIVATE SOFTWARE" },
-	{ NM_MT_ESTABLISH_TEI_NACK,	"ESTABLISH TEI" },
-	{ NM_MT_CONN_TERR_SIGN_NACK,	"CONNECT TERRESTRIAL SIGNALLING" },
-	{ NM_MT_DISC_TERR_SIGN_NACK,	"DISCONNECT TERRESTRIAL SIGNALLING" },
-	{ NM_MT_CONN_TERR_TRAF_NACK,	"CONNECT TERRESTRIAL TRAFFIC" },
-	{ NM_MT_DISC_TERR_TRAF_NACK,	"DISCONNECT TERRESTRIAL TRAFFIC" },
-	{ NM_MT_CONN_MDROP_LINK_NACK,	"CONNECT MULTI-DROP LINK" },
-	{ NM_MT_DISC_MDROP_LINK_NACK,	"DISCONNECT MULTI-DROP LINK" },
-	{ NM_MT_SET_BTS_ATTR_NACK,	"SET BTS ATTRIBUTE" },
-	{ NM_MT_SET_RADIO_ATTR_NACK,	"SET RADIO ATTRIBUTE" },
-	{ NM_MT_SET_CHAN_ATTR_NACK,	"SET CHANNEL ATTRIBUTE" },
-	{ NM_MT_PERF_TEST_NACK,		"PERFORM TEST" },
-	{ NM_MT_SEND_TEST_REP_NACK,	"SEND TEST REPORT" },
-	{ NM_MT_STOP_TEST_NACK,		"STOP TEST" },
-	{ NM_MT_STOP_EVENT_REP_NACK,	"STOP EVENT REPORT" },
-	{ NM_MT_REST_EVENT_REP_NACK,	"RESET EVENT REPORT" },
-	{ NM_MT_CHG_ADM_STATE_NACK,	"CHANGE ADMINISTRATIVE STATE" },
-	{ NM_MT_CHG_ADM_STATE_REQ_NACK,
-				"CHANGE ADMINISTRATIVE STATE REQUEST" },
-	{ NM_MT_REP_OUTST_ALARMS_NACK,	"REPORT OUTSTANDING ALARMS" },
-	{ NM_MT_CHANGEOVER_NACK,	"CHANGEOVER" },
-	{ NM_MT_OPSTART_NACK,		"OPSTART" },
-	{ NM_MT_REINIT_NACK,		"REINIT" },
-	{ NM_MT_SET_SITE_OUT_NACK,	"SET SITE OUTPUT" },
-	{ NM_MT_CHG_HW_CONF_NACK,	"CHANGE HARDWARE CONFIGURATION" },
-	{ NM_MT_GET_ATTR_NACK,		"GET ATTRIBUTE" },
-	{ NM_MT_SET_ALARM_THRES_NACK,	"SET ALARM THRESHOLD" },
-	{ NM_MT_BS11_BEGIN_DB_TX_NACK,	"BS11 BEGIN DATABASE TRANSMISSION" },
-	{ NM_MT_BS11_END_DB_TX_NACK,	"BS11 END DATABASE TRANSMISSION" },
-	{ NM_MT_BS11_CREATE_OBJ_NACK,	"BS11 CREATE OBJECT" },
-	{ NM_MT_BS11_DELETE_OBJ_NACK,	"BS11 DELETE OBJECT" },
-	{ 0,				NULL }
-};
-
-/* Chapter 9.4.36 */
-static const struct value_string nack_cause_names[] = {
-	/* General Nack Causes */
-	{ NM_NACK_INCORR_STRUCT,	"Incorrect message structure" },
-	{ NM_NACK_MSGTYPE_INVAL,	"Invalid message type value" },
-	{ NM_NACK_OBJCLASS_INVAL,	"Invalid Object class value" },
-	{ NM_NACK_OBJCLASS_NOTSUPP,	"Object class not supported" },
-	{ NM_NACK_BTSNR_UNKN,		"BTS no. unknown" },
-	{ NM_NACK_TRXNR_UNKN,		"Baseband Transceiver no. unknown" },
-	{ NM_NACK_OBJINST_UNKN,		"Object Instance unknown" },
-	{ NM_NACK_ATTRID_INVAL,		"Invalid attribute identifier value" },
-	{ NM_NACK_ATTRID_NOTSUPP,	"Attribute identifier not supported" },
-	{ NM_NACK_PARAM_RANGE,		"Parameter value outside permitted range" },
-	{ NM_NACK_ATTRLIST_INCONSISTENT,"Inconsistency in attribute list" },
-	{ NM_NACK_SPEC_IMPL_NOTSUPP,	"Specified implementation not supported" },
-	{ NM_NACK_CANT_PERFORM,		"Message cannot be performed" },
-	/* Specific Nack Causes */
-	{ NM_NACK_RES_NOTIMPL,		"Resource not implemented" },
-	{ NM_NACK_RES_NOTAVAIL,		"Resource not available" },
-	{ NM_NACK_FREQ_NOTAVAIL,	"Frequency not available" },
-	{ NM_NACK_TEST_NOTSUPP,		"Test not supported" },
-	{ NM_NACK_CAPACITY_RESTR,	"Capacity restrictions" },
-	{ NM_NACK_PHYSCFG_NOTPERFORM,	"Physical configuration cannot be performed" },
-	{ NM_NACK_TEST_NOTINIT,		"Test not initiated" },
-	{ NM_NACK_PHYSCFG_NOTRESTORE,	"Physical configuration cannot be restored" },
-	{ NM_NACK_TEST_NOSUCH,		"No such test" },
-	{ NM_NACK_TEST_NOSTOP,		"Test cannot be stopped" },
-	{ NM_NACK_MSGINCONSIST_PHYSCFG,	"Message inconsistent with physical configuration" },
-	{ NM_NACK_FILE_INCOMPLETE,	"Complete file notreceived" },
-	{ NM_NACK_FILE_NOTAVAIL,	"File not available at destination" },
-	{ NM_NACK_FILE_NOTACTIVATE,	"File cannot be activate" },
-	{ NM_NACK_REQ_NOT_GRANT,	"Request not granted" },
-	{ NM_NACK_WAIT,			"Wait" },
-	{ NM_NACK_NOTH_REPORT_EXIST,	"Nothing reportable existing" },
-	{ NM_NACK_MEAS_NOTSUPP,		"Measurement not supported" },
-	{ NM_NACK_MEAS_NOTSTART,	"Measurement not started" },
-	{ 0,				NULL }
-};
-
-static const char *nack_cause_name(u_int8_t cause)
-{
-	return get_value_string(nack_cause_names, cause);
-}
-
-/* Chapter 9.4.16: Event Type */
-static const struct value_string event_type_names[] = {
-	{ NM_EVT_COMM_FAIL,		"communication failure" },
-	{ NM_EVT_QOS_FAIL,		"quality of service failure" },
-	{ NM_EVT_PROC_FAIL,		"processing failure" },
-	{ NM_EVT_EQUIP_FAIL,		"equipment failure" },
-	{ NM_EVT_ENV_FAIL,		"environment failure" },
-	{ 0,				NULL }
-};
-
-static const char *event_type_name(u_int8_t cause)
-{
-	return get_value_string(event_type_names, cause);
-}
-
-/* Chapter 9.4.63: Perceived Severity */
-static const struct value_string severity_names[] = {
-	{ NM_SEVER_CEASED,		"failure ceased" },
-	{ NM_SEVER_CRITICAL,		"critical failure" },
-	{ NM_SEVER_MAJOR,		"major failure" },
-	{ NM_SEVER_MINOR,		"minor failure" },
-	{ NM_SEVER_WARNING,		"warning level failure" },
-	{ NM_SEVER_INDETERMINATE,	"indeterminate failure" },
-	{ 0,				NULL }
-};
-
-static const char *severity_name(u_int8_t cause)
-{
-	return get_value_string(severity_names, cause);
-}
-
-/* Attributes that the BSC can set, not only get, according to Section 9.4 */
-static const enum abis_nm_attr nm_att_settable[] = {
-	NM_ATT_ADD_INFO,
-	NM_ATT_ADD_TEXT,
-	NM_ATT_DEST,
-	NM_ATT_EVENT_TYPE,
-	NM_ATT_FILE_DATA,
-	NM_ATT_GET_ARI,
-	NM_ATT_HW_CONF_CHG,
-	NM_ATT_LIST_REQ_ATTR,
-	NM_ATT_MDROP_LINK,
-	NM_ATT_MDROP_NEXT,
-	NM_ATT_NACK_CAUSES,
-	NM_ATT_OUTST_ALARM,
-	NM_ATT_PHYS_CONF,
-	NM_ATT_PROB_CAUSE,
-	NM_ATT_RAD_SUBC,
-	NM_ATT_SOURCE,
-	NM_ATT_SPEC_PROB,
-	NM_ATT_START_TIME,
-	NM_ATT_TEST_DUR,
-	NM_ATT_TEST_NO,
-	NM_ATT_TEST_REPORT,
-	NM_ATT_WINDOW_SIZE,
-	NM_ATT_SEVERITY,
-	NM_ATT_MEAS_RES,
-	NM_ATT_MEAS_TYPE,
-};
-
-const struct tlv_definition nm_att_tlvdef = {
-	.def = {
-		[NM_ATT_ABIS_CHANNEL] =		{ TLV_TYPE_FIXED, 3 },
-		[NM_ATT_ADD_INFO] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_ADD_TEXT] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_ADM_STATE] =		{ TLV_TYPE_TV },
-		[NM_ATT_ARFCN_LIST]=		{ TLV_TYPE_TL16V },
-		[NM_ATT_AUTON_REPORT] =		{ TLV_TYPE_TV },
-		[NM_ATT_AVAIL_STATUS] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_BCCH_ARFCN] =		{ TLV_TYPE_FIXED, 2 },
-		[NM_ATT_BSIC] =			{ TLV_TYPE_TV },
-		[NM_ATT_BTS_AIR_TIMER] =	{ TLV_TYPE_TV },
-		[NM_ATT_CCCH_L_I_P] =		{ TLV_TYPE_TV },
-		[NM_ATT_CCCH_L_T] =		{ TLV_TYPE_TV },
-		[NM_ATT_CHAN_COMB] =		{ TLV_TYPE_TV },
-		[NM_ATT_CONN_FAIL_CRIT] =	{ TLV_TYPE_TL16V },
-		[NM_ATT_DEST] =			{ TLV_TYPE_TL16V },
-		[NM_ATT_EVENT_TYPE] =		{ TLV_TYPE_TV },
-		[NM_ATT_FILE_DATA] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_FILE_ID] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_FILE_VERSION] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_GSM_TIME] =		{ TLV_TYPE_FIXED, 2 },
-		[NM_ATT_HSN] =			{ TLV_TYPE_TV },
-		[NM_ATT_HW_CONFIG] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_HW_DESC] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_INTAVE_PARAM] =		{ TLV_TYPE_TV },
-		[NM_ATT_INTERF_BOUND] =		{ TLV_TYPE_FIXED, 6 },
-		[NM_ATT_LIST_REQ_ATTR] =	{ TLV_TYPE_TL16V },
-		[NM_ATT_MAIO] =			{ TLV_TYPE_TV },
-		[NM_ATT_MANUF_STATE] =		{ TLV_TYPE_TV },
-		[NM_ATT_MANUF_THRESH] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_MANUF_ID] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_MAX_TA] =		{ TLV_TYPE_TV },
-		[NM_ATT_MDROP_LINK] =		{ TLV_TYPE_FIXED, 2 },
-		[NM_ATT_MDROP_NEXT] =		{ TLV_TYPE_FIXED, 2 },
-		[NM_ATT_NACK_CAUSES] =		{ TLV_TYPE_TV },
-		[NM_ATT_NY1] =			{ TLV_TYPE_TV },
-		[NM_ATT_OPER_STATE] =		{ TLV_TYPE_TV },
-		[NM_ATT_OVERL_PERIOD] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_PHYS_CONF] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_POWER_CLASS] =		{ TLV_TYPE_TV },
-		[NM_ATT_POWER_THRESH] =		{ TLV_TYPE_FIXED, 3 },
-		[NM_ATT_PROB_CAUSE] =		{ TLV_TYPE_FIXED, 3 },
-		[NM_ATT_RACH_B_THRESH] =	{ TLV_TYPE_TV },
-		[NM_ATT_LDAVG_SLOTS] =		{ TLV_TYPE_FIXED, 2 },
-		[NM_ATT_RAD_SUBC] =		{ TLV_TYPE_TV },
-		[NM_ATT_RF_MAXPOWR_R] =		{ TLV_TYPE_TV },
-		[NM_ATT_SITE_INPUTS] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_SITE_OUTPUTS] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_SOURCE] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_SPEC_PROB] =		{ TLV_TYPE_TV },
-		[NM_ATT_START_TIME] =		{ TLV_TYPE_FIXED, 2 },
-		[NM_ATT_T200] =			{ TLV_TYPE_FIXED, 7 },
-		[NM_ATT_TEI] =			{ TLV_TYPE_TV },
-		[NM_ATT_TEST_DUR] =		{ TLV_TYPE_FIXED, 2 },
-		[NM_ATT_TEST_NO] =		{ TLV_TYPE_TV },
-		[NM_ATT_TEST_REPORT] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_VSWR_THRESH] =		{ TLV_TYPE_FIXED, 2 },
-		[NM_ATT_WINDOW_SIZE] = 		{ TLV_TYPE_TV },
-		[NM_ATT_TSC] =			{ TLV_TYPE_TV },
-		[NM_ATT_SW_CONFIG] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_SEVERITY] = 		{ TLV_TYPE_TV },
-		[NM_ATT_GET_ARI] =		{ TLV_TYPE_TL16V },
-		[NM_ATT_HW_CONF_CHG] = 		{ TLV_TYPE_TL16V },
-		[NM_ATT_OUTST_ALARM] =		{ TLV_TYPE_TV },
-		[NM_ATT_MEAS_RES] =		{ TLV_TYPE_TL16V },
-	},
-};
-
-static const enum abis_nm_chan_comb chcomb4pchan[] = {
-	[GSM_PCHAN_CCCH]	= NM_CHANC_mainBCCH,
-	[GSM_PCHAN_CCCH_SDCCH4]	= NM_CHANC_BCCHComb,
-	[GSM_PCHAN_TCH_F]	= NM_CHANC_TCHFull,
-	[GSM_PCHAN_TCH_H]	= NM_CHANC_TCHHalf,
-	[GSM_PCHAN_SDCCH8_SACCH8C] = NM_CHANC_SDCCH,
-	[GSM_PCHAN_PDCH]	= NM_CHANC_IPAC_PDCH,
-	[GSM_PCHAN_TCH_F_PDCH]	= NM_CHANC_IPAC_TCHFull_PDCH,
-	/* FIXME: bounds check */
-};
-
-int abis_nm_chcomb4pchan(enum gsm_phys_chan_config pchan)
-{
-	if (pchan < ARRAY_SIZE(chcomb4pchan))
-		return chcomb4pchan[pchan];
-
-	return -EINVAL;
-}
-
-int abis_nm_tlv_parse(struct tlv_parsed *tp, struct gsm_bts *bts, const u_int8_t *buf, int len)
+int abis_nm_tlv_parse(struct tlv_parsed *tp, struct gsm_bts *bts, const uint8_t *buf, int len)
 {
 	if (!bts->model)
 		return -EIO;
@@ -373,13 +78,13 @@
 /* is this msgtype a report ? */
 static int is_report(enum abis_nm_msgtype mt)
 {
-	return is_in_arr(mt, reports, ARRAY_SIZE(reports));
+	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, u_int8_t len)
+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;
@@ -387,9 +92,9 @@
 	oh->length = len;
 }
 
-static void fill_om_fom_hdr(struct abis_om_hdr *oh, u_int8_t len,
-			    u_int8_t msg_type, u_int8_t obj_class,
-			    u_int8_t bts_nr, u_int8_t trx_nr, u_int8_t ts_nr)
+static void 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;
@@ -438,90 +143,6 @@
 
 static int abis_nm_rcvmsg_sw(struct msgb *mb);
 
-const struct value_string abis_nm_obj_class_names[] = {
-	{ NM_OC_SITE_MANAGER,	"SITE-MANAGER" },
-	{ NM_OC_BTS,		"BTS" },
-	{ NM_OC_RADIO_CARRIER,	"RADIO-CARRIER" },
-	{ NM_OC_BASEB_TRANSC,	"BASEBAND-TRANSCEIVER" },
-	{ NM_OC_CHANNEL,	"CHANNEL" },
-	{ NM_OC_BS11_ADJC,	"ADJC" },
-	{ NM_OC_BS11_HANDOVER,	"HANDOVER" },
-	{ NM_OC_BS11_PWR_CTRL,	"POWER-CONTROL" },
-	{ NM_OC_BS11_BTSE,	"BTSE" },
-	{ NM_OC_BS11_RACK,	"RACK" },
-	{ NM_OC_BS11_TEST,	"TEST" },
-	{ NM_OC_BS11_ENVABTSE,	"ENVABTSE" },
-	{ NM_OC_BS11_BPORT,	"BPORT" },
-	{ NM_OC_GPRS_NSE,	"GPRS-NSE" },
-	{ NM_OC_GPRS_CELL,	"GPRS-CELL" },
-	{ NM_OC_GPRS_NSVC,	"GPRS-NSVC" },
-	{ NM_OC_BS11,		"SIEMENSHW" },
-	{ 0,			NULL }
-};
-
-static const char *obj_class_name(u_int8_t oc)
-{
-	return get_value_string(abis_nm_obj_class_names, oc);
-}
-
-const char *nm_opstate_name(u_int8_t os)
-{
-	switch (os) {
-	case NM_OPSTATE_DISABLED:
-		return "Disabled";
-	case NM_OPSTATE_ENABLED:
-		return "Enabled";
-	case NM_OPSTATE_NULL:
-		return "NULL";
-	default:
-		return "RFU";
-	}
-}
-
-/* Chapter 9.4.7 */
-static const struct value_string avail_names[] = {
-	{ 0, 	"In test" },
-	{ 1,	"Failed" },
-	{ 2,	"Power off" },
-	{ 3,	"Off line" },
-	/* Not used */
-	{ 5,	"Dependency" },
-	{ 6,	"Degraded" },
-	{ 7,	"Not installed" },
-	{ 0xff, "OK" },
-	{ 0,	NULL }
-};
-
-const char *nm_avail_name(u_int8_t avail)
-{
-	return get_value_string(avail_names, avail);
-}
-
-static struct value_string test_names[] = {
-	/* FIXME: standard test names */
-	{ NM_IPACC_TESTNO_CHAN_USAGE, "Channel Usage" },
-	{ NM_IPACC_TESTNO_BCCH_CHAN_USAGE, "BCCH Channel Usage" },
-	{ NM_IPACC_TESTNO_FREQ_SYNC, "Frequency Synchronization" },
-	{ NM_IPACC_TESTNO_BCCH_INFO, "BCCH Info" },
-	{ NM_IPACC_TESTNO_TX_BEACON, "Transmit Beacon" },
-	{ NM_IPACC_TESTNO_SYSINFO_MONITOR, "System Info Monitor" },
-	{ NM_IPACC_TESTNO_BCCCH_MONITOR, "BCCH Monitor" },
-	{ 0, NULL }
-};
-
-const struct value_string abis_nm_adm_state_names[] = {
-	{ NM_STATE_LOCKED,	"Locked" },
-	{ NM_STATE_UNLOCKED,	"Unlocked" },
-	{ NM_STATE_SHUTDOWN,	"Shutdown" },
-	{ NM_STATE_NULL,	"NULL" },
-	{ 0, NULL }
-};
-
-const char *nm_adm_name(u_int8_t adm)
-{
-	return get_value_string(abis_nm_adm_state_names, adm);
-}
-
 int nm_is_running(struct gsm_nm_state *s) {
 	return (s->operational == NM_OPSTATE_ENABLED) && (
 		(s->availability == NM_AVSTATE_OK) ||
@@ -529,177 +150,32 @@
 	);
 }
 
-static void debugp_foh(struct abis_om_fom_hdr *foh)
-{
-	DEBUGP(DNM, "OC=%s(%02x) INST=(%02x,%02x,%02x) ",
-		obj_class_name(foh->obj_class), foh->obj_class,
-		foh->obj_inst.bts_nr, foh->obj_inst.trx_nr,
-		foh->obj_inst.ts_nr);
-}
-
-/* obtain the gsm_nm_state data structure for a given object instance */
-static struct gsm_nm_state *
-objclass2nmstate(struct gsm_bts *bts, u_int8_t obj_class,
-		 struct abis_om_obj_inst *obj_inst)
-{
-	struct gsm_bts_trx *trx;
-	struct gsm_nm_state *nm_state = NULL;
-
-	switch (obj_class) {
-	case NM_OC_BTS:
-		nm_state = &bts->nm_state;
-		break;
-	case NM_OC_RADIO_CARRIER:
-		if (obj_inst->trx_nr >= bts->num_trx) {
-			DEBUGPC(DNM, "TRX %u does not exist ", obj_inst->trx_nr);
-			return NULL;
-		}
-		trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
-		nm_state = &trx->nm_state;
-		break;
-	case NM_OC_BASEB_TRANSC:
-		if (obj_inst->trx_nr >= bts->num_trx) {
-			DEBUGPC(DNM, "TRX %u does not exist ", obj_inst->trx_nr);
-			return NULL;
-		}
-		trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
-		nm_state = &trx->bb_transc.nm_state;
-		break;
-	case NM_OC_CHANNEL:
-		if (obj_inst->trx_nr >= bts->num_trx) {
-			DEBUGPC(DNM, "TRX %u does not exist ", obj_inst->trx_nr);
-			return NULL;
-		}
-		trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
-		if (obj_inst->ts_nr >= TRX_NR_TS)
-			return NULL;
-		nm_state = &trx->ts[obj_inst->ts_nr].nm_state;
-		break;
-	case NM_OC_SITE_MANAGER:
-		nm_state = &bts->site_mgr.nm_state;
-		break;
-	case NM_OC_BS11:
-		switch (obj_inst->bts_nr) {
-		case BS11_OBJ_CCLK:
-			nm_state = &bts->bs11.cclk.nm_state;
-			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);
-			nm_state = &trx->bs11.bbsig.nm_state;
-			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);
-			nm_state = &trx->bs11.pa.nm_state;
-			break;
-		default:
-			return NULL;
-		}
-	case NM_OC_BS11_RACK:
-		nm_state = &bts->bs11.rack.nm_state;
-		break;
-	case NM_OC_BS11_ENVABTSE:
-		if (obj_inst->trx_nr >= ARRAY_SIZE(bts->bs11.envabtse))
-			return NULL;
-		nm_state = &bts->bs11.envabtse[obj_inst->trx_nr].nm_state;
-		break;
-	case NM_OC_GPRS_NSE:
-		nm_state = &bts->gprs.nse.nm_state;
-		break;
-	case NM_OC_GPRS_CELL:
-		nm_state = &bts->gprs.cell.nm_state;
-		break;
-	case NM_OC_GPRS_NSVC:
-		if (obj_inst->trx_nr >= ARRAY_SIZE(bts->gprs.nsvc))
-			return NULL;
-		nm_state = &bts->gprs.nsvc[obj_inst->trx_nr].nm_state;
-		break;
-	}
-	return nm_state;
-}
-
-/* obtain the in-memory data structure of a given object instance */
-static void *
-objclass2obj(struct gsm_bts *bts, u_int8_t obj_class,
-	     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) {
-			DEBUGPC(DNM, "TRX %u does not exist ", obj_inst->trx_nr);
-			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) {
-			DEBUGPC(DNM, "TRX %u does not exist ", obj_inst->trx_nr);
-			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) {
-			DEBUGPC(DNM, "TRX %u does not exist ", obj_inst->trx_nr);
-			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;
-}
-
 /* 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, u_int8_t obj_class,
-			   struct abis_om_obj_inst *obj_inst, u_int8_t adm_state)
+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;
 
-	nsd.obj = objclass2obj(bts, obj_class, obj_inst);
+	memset(&nsd, 0, sizeof(nsd));
+
+	nsd.obj = gsm_objclass2obj(bts, obj_class, obj_inst);
 	if (!nsd.obj)
 		return -EINVAL;
-	nm_state = objclass2nmstate(bts, obj_class, obj_inst);
+	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;
-	dispatch_signal(SS_NM, S_NM_STATECHG_ADM, &nsd);
+	osmo_signal_dispatch(SS_NM, S_NM_STATECHG_ADM, &nsd);
 
 	nm_state->administrative = adm_state;
 
@@ -718,7 +194,7 @@
 
 	memset(&new_state, 0, sizeof(new_state));
 
-	nm_state = objclass2nmstate(bts, foh->obj_class, &foh->obj_inst);
+	nm_state = gsm_objclass2nmstate(bts, foh->obj_class, &foh->obj_inst);
 	if (!nm_state) {
 		DEBUGPC(DNM, "unknown object class\n");
 		return -EINVAL;
@@ -729,20 +205,24 @@
 	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 ", nm_opstate_name(new_state.operational));
+		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) ", nm_avail_name(new_state.availability),
+		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 ", nm_adm_name(new_state.administrative));
+		DEBUGPC(DNM, "ADM=%2s ",
+			get_value_string(abis_nm_adm_state_names,
+					 new_state.administrative));
 	}
 	DEBUGPC(DNM, "\n");
 
@@ -752,12 +232,13 @@
 		/* 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 = objclass2obj(bts, foh->obj_class, &foh->obj_inst);
+		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;
-		dispatch_signal(SS_NM, S_NM_STATECHG_OPER, &nsd);
+		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)
@@ -783,28 +264,30 @@
 	const uint8_t *p_val;
 	char *p_text;
 
-	DEBUGPC(DNM, "Failure Event Report ");
+	LOGPC(DNM, LOGL_ERROR, "Failure Event Report ");
 	
 	abis_nm_tlv_parse(&tp, mb->trx->bts, foh->data, oh->length-sizeof(*foh));
 
 	if (TLVP_PRESENT(&tp, NM_ATT_EVENT_TYPE))
-		DEBUGPC(DNM, "Type=%s ", event_type_name(*TLVP_VAL(&tp, NM_ATT_EVENT_TYPE)));
+		LOGPC(DNM, LOGL_ERROR, "Type=%s ",
+		      abis_nm_event_type_name(*TLVP_VAL(&tp, NM_ATT_EVENT_TYPE)));
 	if (TLVP_PRESENT(&tp, NM_ATT_SEVERITY))
-		DEBUGPC(DNM, "Severity=%s ", severity_name(*TLVP_VAL(&tp, NM_ATT_SEVERITY)));
+		LOGPC(DNM, LOGL_ERROR, "Severity=%s ",
+		      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);
-		DEBUGPC(DNM, "Probable cause= %02X %02X %02X ", p_val[0], p_val[1], p_val[2]);
+		LOGPC(DNM, LOGL_ERROR, "Probable cause= %02X %02X %02X ", p_val[0], p_val[1], p_val[2]);
 	}
 	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 (p_text) {
-			DEBUGPC(DNM, "Additional Text=%s ", p_text);
+			LOGPC(DNM, LOGL_ERROR, "Additional Text=%s ", p_text);
 			talloc_free(p_text);
 		}
 	}
 
-	DEBUGPC(DNM, "\n");
+	LOGPC(DNM, LOGL_ERROR, "\n");
 
 	return 0;
 }
@@ -812,9 +295,9 @@
 static int abis_nm_rcvmsg_report(struct msgb *mb)
 {
 	struct abis_om_fom_hdr *foh = msgb_l3(mb);
-	u_int8_t mt = foh->msg_type;
+	uint8_t mt = foh->msg_type;
 
-	debugp_foh(foh);
+	abis_nm_debugp_foh(DNM, foh);
 
 	//nmh->cfg->report_cb(mb, foh);
 
@@ -824,15 +307,15 @@
 		break;
 	case NM_MT_SW_ACTIVATED_REP:
 		DEBUGPC(DNM, "Software Activated Report\n");
-		dispatch_signal(SS_NM, S_NM_SW_ACTIV_REP, mb);
+		osmo_signal_dispatch(SS_NM, S_NM_SW_ACTIV_REP, mb);
 		break;
 	case NM_MT_FAILURE_EVENT_REP:
 		rx_fail_evt_rep(mb);
-		dispatch_signal(SS_NM, S_NM_FAIL_REP, mb);
+		osmo_signal_dispatch(SS_NM, S_NM_FAIL_REP, mb);
 		break;
 	case NM_MT_TEST_REP:
 		DEBUGPC(DNM, "Test Report\n");
-		dispatch_signal(SS_NM, S_NM_TEST_REP, mb);
+		osmo_signal_dispatch(SS_NM, S_NM_TEST_REP, mb);
 		break;
 	default:
 		DEBUGPC(DNM, "reporting NM MT 0x%02x\n", mt);
@@ -844,13 +327,13 @@
 }
 
 /* Activate the specified software into the BTS */
-static int ipacc_sw_activate(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i0, u_int8_t i1,
-			     u_int8_t i2, const u_int8_t *sw_desc, u_int8_t swdesc_len)
+static int ipacc_sw_activate(struct gsm_bts *bts, uint8_t obj_class, uint8_t i0, uint8_t i1,
+			     uint8_t i2, const uint8_t *sw_desc, uint8_t swdesc_len)
 {
 	struct abis_om_hdr *oh;
 	struct msgb *msg = nm_msgb_alloc();
-	u_int8_t len = swdesc_len;
-	u_int8_t *trailer;
+	uint8_t len = swdesc_len;
+	uint8_t *trailer;
 
 	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);
@@ -861,7 +344,7 @@
 	return abis_nm_sendmsg(bts, msg);
 }
 
-static int abis_nm_parse_sw_descr(const u_int8_t *sw_descr, int sw_descr_len)
+static int abis_nm_parse_sw_descr(const uint8_t *sw_descr, int sw_descr_len)
 {
 	static const struct tlv_definition sw_descr_def = {
 		.def = {
@@ -870,9 +353,9 @@
 		},
 	};
 
-	u_int8_t tag;
-	u_int16_t tag_len;
-	const u_int8_t *val;
+	uint8_t tag;
+	uint16_t tag_len;
+	const uint8_t *val;
 	int ofs = 0, len;
 
 	/* Classic TLV parsing doesn't work well with SW_DESCR because of it's
@@ -909,10 +392,10 @@
 	struct abis_om_hdr *oh = msgb_l2(mb);
 	struct abis_om_fom_hdr *foh = msgb_l3(mb);
 	struct tlv_parsed tp;
-	const u_int8_t *sw_config;
+	const uint8_t *sw_config;
 	int ret, sw_config_len, sw_descr_len;
 
-	debugp_foh(foh);
+	abis_nm_debugp_foh(DNM, foh);
 
 	DEBUGPC(DNM, "SW Activate Request: ");
 
@@ -931,7 +414,7 @@
 		DEBUGP(DNM, "SW config not found! Can't continue.\n");
 		return -EINVAL;
 	} else {
-		DEBUGP(DNM, "Found SW config: %s\n", hexdump(sw_config, sw_config_len));
+		DEBUGP(DNM, "Found SW config: %s\n", osmo_hexdump(sw_config, sw_config_len));
 	}
 
 		/* Use the first SW_DESCR present in SW config */
@@ -952,7 +435,7 @@
 	struct abis_om_hdr *oh = msgb_l2(mb);
 	struct abis_om_fom_hdr *foh = msgb_l3(mb);
 	struct tlv_parsed tp;
-	u_int8_t adm_state;
+	uint8_t adm_state;
 
 	abis_nm_tlv_parse(&tp, mb->trx->bts, foh->data, oh->length-sizeof(*foh));
 	if (!TLVP_PRESENT(&tp, NM_ATT_ADM_STATE))
@@ -973,12 +456,12 @@
 	abis_nm_tlv_parse(&tp, mb->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) {
-		u_int8_t onoff = *TLVP_VAL(&tp, NM_ATT_BS11_LMT_LOGON_SESSION);
+		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) {
-		u_int8_t level = *TLVP_VAL(&tp, NM_ATT_BS11_LMT_USER_ACC_LEV);
+		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) &&
@@ -1013,34 +496,34 @@
 {
 	struct abis_om_hdr *oh = msgb_l2(mb);
 	struct abis_om_fom_hdr *foh = msgb_l3(mb);
-	u_int8_t mt = foh->msg_type;
+	uint8_t mt = foh->msg_type;
 	int ret = 0;
 
 	/* check for unsolicited message */
 	if (is_report(mt))
 		return abis_nm_rcvmsg_report(mb);
 
-	if (is_in_arr(mt, sw_load_msgs, ARRAY_SIZE(sw_load_msgs)))
+	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, nacks, ARRAY_SIZE(nacks))) {
+	if (is_in_arr(mt, abis_nm_nacks, ARRAY_SIZE(abis_nm_nacks))) {
 		struct nm_nack_signal_data nack_data;
 		struct tlv_parsed tp;
 
-		debugp_foh(foh);
+		abis_nm_debugp_foh(DNM, foh);
 
-		DEBUGPC(DNM, "%s NACK ", get_value_string(nack_names, mt));
+		DEBUGPC(DNM, "%s NACK ", abis_nm_nack_name(mt));
 
 		abis_nm_tlv_parse(&tp, mb->trx->bts, foh->data, oh->length-sizeof(*foh));
 		if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
 			DEBUGPC(DNM, "CAUSE=%s\n",
-				nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
+				abis_nm_nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
 		else
 			DEBUGPC(DNM, "\n");
 
 		nack_data.msg = mb;
 		nack_data.mt = mt;
-		dispatch_signal(SS_NM, S_NM_NACK, &nack_data);
+		osmo_signal_dispatch(SS_NM, S_NM_NACK, &nack_data);
 		abis_nm_queue_send_next(mb->trx->bts);
 		return 0;
 	}
@@ -1075,10 +558,10 @@
 		DEBUGP(DNM, "CONN MDROP LINK ACK\n");
 		break;
 	case NM_MT_IPACC_RESTART_ACK:
-		dispatch_signal(SS_NM, S_NM_IPACC_RESTART_ACK, NULL);
+		osmo_signal_dispatch(SS_NM, S_NM_IPACC_RESTART_ACK, NULL);
 		break;
 	case NM_MT_IPACC_RESTART_NACK:
-		dispatch_signal(SS_NM, S_NM_IPACC_RESTART_NACK, NULL);
+		osmo_signal_dispatch(SS_NM, S_NM_IPACC_RESTART_NACK, NULL);
 		break;
 	case NM_MT_SET_BTS_ATTR_ACK:
 		/* The HSL wants an OPSTART _after_ the SI has been set */
@@ -1134,7 +617,7 @@
 		return -EINVAL;
 	}
 #if 0
-	unsigned int l2_len = msg->tail - (u_int8_t *)msgb_l2(msg);
+	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",
@@ -1215,17 +698,17 @@
 	int forced;
 
 	/* this will become part of the SW LOAD INITIATE */
-	u_int8_t obj_class;
-	u_int8_t obj_instance[3];
+	uint8_t obj_class;
+	uint8_t obj_instance[3];
 
-	u_int8_t file_id[255];
-	u_int8_t file_id_len;
+	uint8_t file_id[255];
+	uint8_t file_id_len;
 
-	u_int8_t file_version[255];
-	u_int8_t file_version_len;
+	uint8_t file_version[255];
+	uint8_t file_version_len;
 
-	u_int8_t window_size;
-	u_int8_t seg_in_window;
+	uint8_t window_size;
+	uint8_t seg_in_window;
 
 	int fd;
 	FILE *stream;
@@ -1256,7 +739,7 @@
 {
 	struct abis_om_hdr *oh;
 	struct msgb *msg = nm_msgb_alloc();
-	u_int8_t len = 3*2 + sw->file_id_len + sw->file_version_len;
+	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,
@@ -1293,7 +776,7 @@
 	char seg_buf[256];
 	char *line_buf = seg_buf+2;
 	unsigned char *tlv;
-	u_int8_t len;
+	uint8_t len;
 
 	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
 
@@ -1314,7 +797,7 @@
 
 		len = strlen(line_buf) + 2;
 		tlv = msgb_put(msg, TLV_GROSS_LEN(len));
-		tlv_put(tlv, NM_ATT_BS11_FILE_DATA, len, (u_int8_t *)seg_buf);
+		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;
 
@@ -1322,7 +805,7 @@
 		len = strlen(line_buf)+2;
 		break;
 	case GSM_BTS_TYPE_NANOBTS: {
-		static_assert(sizeof(seg_buf) >= IPACC_SEGMENT_SIZE, buffer_big_enough);
+		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");
@@ -1333,7 +816,7 @@
 			sw->last_seg = 1;
 
 		++sw->seg_in_window;
-		msgb_tl16v_put(msg, NM_ATT_IPACC_FILE_DATA, len, (const u_int8_t *) seg_buf);
+		msgb_tl16v_put(msg, NM_ATT_IPACC_FILE_DATA, len, (const uint8_t *) seg_buf);
 		len += 3;
 		break;
 	}
@@ -1355,7 +838,7 @@
 {
 	struct abis_om_hdr *oh;
 	struct msgb *msg = nm_msgb_alloc();
-	u_int8_t len = 2*2 + sw->file_id_len + sw->file_version_len;
+	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,
@@ -1371,7 +854,7 @@
 {
 	struct abis_om_hdr *oh;
 	struct msgb *msg = nm_msgb_alloc();
-	u_int8_t len = 2*2 + sw->file_id_len + sw->file_version_len;
+	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,
@@ -1671,7 +1154,7 @@
 
 /* Load the specified software into the BTS */
 int abis_nm_software_load(struct gsm_bts *bts, int trx_nr, const char *fname,
-			  u_int8_t win_size, int forced,
+			  uint8_t win_size, int forced,
 			  gsm_cbfn *cbfn, void *cb_data)
 {
 	struct abis_nm_sw *sw = &g_sw;
@@ -1772,8 +1255,8 @@
 	return sw_activate(sw);
 }
 
-static void fill_nm_channel(struct abis_nm_channel *ch, u_int8_t bts_port,
-		       u_int8_t ts_nr, u_int8_t subslot_nr)
+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;
@@ -1781,13 +1264,13 @@
 	ch->subslot = subslot_nr;	
 }
 
-int abis_nm_establish_tei(struct gsm_bts *bts, u_int8_t trx_nr,
-			  u_int8_t e1_port, u_int8_t e1_timeslot, u_int8_t e1_subslot,
-			  u_int8_t tei)
+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;
-	u_int8_t len = sizeof(*ch) + 2;
+	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);
@@ -1804,7 +1287,7 @@
 
 /* connect signalling of one (BTS,TRX) to a particular timeslot on the E1 */
 int abis_nm_conn_terr_sign(struct gsm_bts_trx *trx,
-			   u_int8_t e1_port, u_int8_t e1_timeslot, u_int8_t e1_subslot)
+			   uint8_t e1_port, uint8_t e1_timeslot, uint8_t e1_subslot)
 {
 	struct gsm_bts *bts = trx->bts;
 	struct abis_om_hdr *oh;
@@ -1829,8 +1312,8 @@
 #endif
 
 int abis_nm_conn_terr_traf(struct gsm_bts_trx_ts *ts,
-			   u_int8_t e1_port, u_int8_t e1_timeslot,
-			   u_int8_t e1_subslot)
+			   uint8_t e1_port, uint8_t e1_timeslot,
+			   uint8_t e1_subslot)
 {
 	struct gsm_bts *bts = ts->trx->bts;
 	struct abis_om_hdr *oh;
@@ -1854,17 +1337,17 @@
 #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,
-			   u_int8_t subchan)
+			   uint8_t subchan)
 {
 }
 #endif
 
 /* Chapter 8.6.1 */
-int abis_nm_set_bts_attr(struct gsm_bts *bts, u_int8_t *attr, int attr_len)
+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();
-	u_int8_t *cur;
+	uint8_t *cur;
 
 	DEBUGP(DNM, "Set BTS Attr (bts=%d)\n", bts->nr);
 
@@ -1877,11 +1360,11 @@
 }
 
 /* Chapter 8.6.2 */
-int abis_nm_set_radio_attr(struct gsm_bts_trx *trx, u_int8_t *attr, int attr_len)
+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();
-	u_int8_t *cur;
+	uint8_t *cur;
 
 	DEBUGP(DNM, "Set TRX Attr (bts=%d,trx=%d)\n", trx->bts->nr, trx->nr);
 
@@ -1894,7 +1377,7 @@
 	return abis_nm_sendmsg(trx->bts, msg);
 }
 
-static int verify_chan_comb(struct gsm_bts_trx_ts *ts, u_int8_t chan_comb)
+static int verify_chan_comb(struct gsm_bts_trx_ts *ts, uint8_t chan_comb)
 {
 	int i;
 
@@ -2029,13 +1512,13 @@
 }
 
 /* Chapter 8.6.3 */
-int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, u_int8_t chan_comb)
+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;
-	u_int8_t zero = 0x00;
+	uint8_t zero = 0x00;
 	struct msgb *msg = nm_msgb_alloc();
-	u_int8_t len = 2 + 2;
+	uint8_t len = 2 + 2;
 
 	if (bts->type == GSM_BTS_TYPE_BS11)
 		len += 4 + 2 + 2 + 3;
@@ -2075,20 +1558,23 @@
 			}
 		}
 	}
-	msgb_tv_put(msg, NM_ATT_TSC, bts->tsc);	/* training sequence */
+	if (ts->tsc == -1)
+		msgb_tv_put(msg, NM_ATT_TSC, bts->tsc);	/* training sequence */
+	else
+		msgb_tv_put(msg, NM_ATT_TSC, ts->tsc);	/* 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, u_int8_t obj_class, u_int8_t i1,
-			u_int8_t i2, u_int8_t i3, int nack, u_int8_t *attr, int att_len)
+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();
-	u_int8_t msgtype = NM_MT_SW_ACT_REQ_ACK;
-	u_int8_t len = att_len;
+	uint8_t msgtype = NM_MT_SW_ACT_REQ_ACK;
+	uint8_t len = att_len;
 
 	if (nack) {
 		len += 2;
@@ -2099,7 +1585,7 @@
 	fill_om_fom_hdr(oh, att_len, msgtype, obj_class, i1, i2, i3);
 
 	if (attr) {
-		u_int8_t *ptr = msgb_put(msg, att_len);
+		uint8_t *ptr = msgb_put(msg, att_len);
 		memcpy(ptr, attr, att_len);
 	}
 	if (nack)
@@ -2108,11 +1594,11 @@
 	return abis_nm_sendmsg_direct(bts, msg);
 }
 
-int abis_nm_raw_msg(struct gsm_bts *bts, int len, u_int8_t *rawmsg)
+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;
-	u_int8_t *data;
+	uint8_t *data;
 
 	oh = (struct abis_om_hdr *) msgb_put(msg, sizeof(*oh));
 	fill_om_hdr(oh, len);
@@ -2123,7 +1609,7 @@
 }
 
 /* Siemens specific commands */
-static int __simple_cmd(struct gsm_bts *bts, u_int8_t msg_type)
+static int __simple_cmd(struct gsm_bts *bts, uint8_t msg_type)
 {
 	struct abis_om_hdr *oh;
 	struct msgb *msg = nm_msgb_alloc();
@@ -2136,7 +1622,7 @@
 }
 
 /* Chapter 8.9.2 */
-int abis_nm_opstart(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i0, u_int8_t i1, u_int8_t i2)
+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 msgb *msg = nm_msgb_alloc();
@@ -2144,15 +1630,15 @@
 	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
 	fill_om_fom_hdr(oh, 0, NM_MT_OPSTART, obj_class, i0, i1, i2);
 
-	debugp_foh((struct abis_om_fom_hdr *) oh->data);
+	abis_nm_debugp_foh(DNM, (struct abis_om_fom_hdr *) oh->data);
 	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, u_int8_t obj_class, u_int8_t i0,
-			  u_int8_t i1, u_int8_t i2, enum abis_nm_adm_state adm_state)
+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();
@@ -2164,12 +1650,12 @@
 	return abis_nm_sendmsg(bts, msg);
 }
 
-int abis_nm_conn_mdrop_link(struct gsm_bts *bts, u_int8_t e1_port0, u_int8_t ts0,
-			    u_int8_t e1_port1, u_int8_t ts1)
+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();
-	u_int8_t *attr;
+	uint8_t *attr;
 
 	DEBUGP(DNM, "CONNECT MDROP LINK E1=(%u,%u) -> E1=(%u, %u)\n",
 		e1_port0, ts0, e1_port1, ts1);
@@ -2192,13 +1678,13 @@
 }
 
 /* Chapter 8.7.1 */
-int abis_nm_perform_test(struct gsm_bts *bts, u_int8_t obj_class,
-			 u_int8_t bts_nr, u_int8_t trx_nr, u_int8_t ts_nr,
-			 u_int8_t test_nr, u_int8_t auton_report, struct msgb *msg)
+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", get_value_string(test_names, test_nr));
+	DEBUGP(DNM, "PEFORM TEST %s\n", abis_nm_test_name(test_nr));
 
 	if (!msg)
 		msg = nm_msgb_alloc();
@@ -2237,12 +1723,12 @@
 
 
 struct bs11_date_time {
-	u_int16_t	year;
-	u_int8_t	month;
-	u_int8_t	day;
-	u_int8_t	hour;
-	u_int8_t	min;
-	u_int8_t	sec;
+	uint16_t	year;
+	uint8_t	month;
+	uint8_t	day;
+	uint8_t	hour;
+	uint8_t	min;
+	uint8_t	sec;
 } __attribute__((packed));
 
 
@@ -2275,12 +1761,12 @@
 }
 
 int abis_nm_bs11_create_object(struct gsm_bts *bts,
-				enum abis_bs11_objtype type, u_int8_t idx,
-				u_int8_t attr_len, const u_int8_t *attr)
+				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();
-	u_int8_t *cur;
+	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,
@@ -2292,7 +1778,7 @@
 }
 
 int abis_nm_bs11_delete_object(struct gsm_bts *bts,
-				enum abis_bs11_objtype type, u_int8_t idx)
+				enum abis_bs11_objtype type, uint8_t idx)
 {
 	struct abis_om_hdr *oh;
 	struct msgb *msg = nm_msgb_alloc();
@@ -2304,11 +1790,11 @@
 	return abis_nm_sendmsg(bts, msg);
 }
 
-int abis_nm_bs11_create_envaBTSE(struct gsm_bts *bts, u_int8_t idx)
+int abis_nm_bs11_create_envaBTSE(struct gsm_bts *bts, uint8_t idx)
 {
 	struct abis_om_hdr *oh;
 	struct msgb *msg = nm_msgb_alloc();
-	u_int8_t zero = 0x00;
+	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,
@@ -2318,7 +1804,7 @@
 	return abis_nm_sendmsg(bts, msg);
 }
 
-int abis_nm_bs11_create_bport(struct gsm_bts *bts, u_int8_t idx)
+int abis_nm_bs11_create_bport(struct gsm_bts *bts, uint8_t idx)
 {
 	struct abis_om_hdr *oh;
 	struct msgb *msg = nm_msgb_alloc();
@@ -2330,7 +1816,7 @@
 	return abis_nm_sendmsg(bts, msg);
 }
 
-int abis_nm_bs11_delete_bport(struct gsm_bts *bts, u_int8_t idx)
+int abis_nm_bs11_delete_bport(struct gsm_bts *bts, uint8_t idx)
 {
 	struct abis_om_hdr *oh;
 	struct msgb *msg = nm_msgb_alloc();
@@ -2342,7 +1828,7 @@
 	return abis_nm_sendmsg(bts, msg);
 }
 
-static const u_int8_t sm_attr[] = { NM_ATT_TEI, NM_ATT_ABIS_CHANNEL };
+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;
@@ -2357,9 +1843,9 @@
 }
 
 /* like abis_nm_conn_terr_traf + set_tei */
-int abis_nm_bs11_conn_oml_tei(struct gsm_bts *bts, u_int8_t e1_port,
-			  u_int8_t e1_timeslot, u_int8_t e1_subslot,
-			  u_int8_t 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;
@@ -2376,7 +1862,7 @@
 	return abis_nm_sendmsg(bts, msg);
 }
 
-int abis_nm_bs11_set_trx_power(struct gsm_bts_trx *trx, u_int8_t level)
+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();
@@ -2393,7 +1879,7 @@
 {
 	struct abis_om_hdr *oh;
 	struct msgb *msg = nm_msgb_alloc();
-	u_int8_t attr = NM_ATT_BS11_TXPWR;
+	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,
@@ -2407,7 +1893,7 @@
 {
 	struct abis_om_hdr *oh;
 	struct msgb *msg = nm_msgb_alloc();
-	u_int8_t attr[] = { NM_ATT_BS11_PLL_MODE };
+	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,
@@ -2421,7 +1907,7 @@
 {
 	struct abis_om_hdr *oh;
 	struct msgb *msg = nm_msgb_alloc();
-	u_int8_t attr[] = { NM_ATT_BS11_CCLK_ACCURACY,
+	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);
@@ -2433,7 +1919,7 @@
 
 }
 
-//static const u_int8_t bs11_logon_c7[] = { 0x07, 0xd9, 0x01, 0x11, 0x0d, 0x10, 0x20 };
+//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)
 {
@@ -2445,7 +1931,7 @@
 	return abis_nm_bs11_logon(bts, 0x03, "FIELD  ", on);
 }
 
-int abis_nm_bs11_logon(struct gsm_bts *bts, u_int8_t level, const char *name, int 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();
@@ -2455,16 +1941,16 @@
 
 	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
 	if (on) {
-		u_int8_t len = 3*2 + sizeof(bdt)
+		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), (u_int8_t *) &bdt);
+			     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), (u_int8_t *)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);
@@ -2485,7 +1971,7 @@
 	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 u_int8_t *)password);
+	msgb_tlv_put(msg, NM_ATT_BS11_PASSWORD, 10, (const uint8_t *)password);
 
 	return abis_nm_sendmsg(bts, msg);
 }
@@ -2495,7 +1981,7 @@
 {
 	struct abis_om_hdr *oh;
 	struct msgb *msg;
-	u_int8_t tlv_value;
+	uint8_t tlv_value;
 	
 	msg = nm_msgb_alloc();
 	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
@@ -2518,7 +2004,7 @@
 {
 	struct abis_om_hdr *oh;
 	struct msgb *msg;
-	u_int8_t tlv_value[2];
+	uint8_t tlv_value[2];
 
 	msg = nm_msgb_alloc();
 	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
@@ -2545,7 +2031,7 @@
 struct abis_nm_bs11_sw {
 	struct gsm_bts *bts;
 	char swl_fname[PATH_MAX];
-	u_int8_t win_size;
+	uint8_t win_size;
 	int forced;
 	struct llist_head file_list;
 	gsm_cbfn *user_cb;	/* specified by the user */
@@ -2671,7 +2157,7 @@
  * 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,
-			  u_int8_t win_size, int forced, gsm_cbfn *cbfn)
+			  uint8_t win_size, int forced, gsm_cbfn *cbfn)
 {
 	struct abis_nm_bs11_sw *bs11_sw = g_bs11_sw;
 	struct file_list_entry *fle;
@@ -2701,7 +2187,7 @@
 }
 
 #if 0
-static u_int8_t req_attr_btse[] = {
+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,
@@ -2712,14 +2198,14 @@
 
 	NM_ATT_BS11_SW_LOAD_STORED };
 
-static u_int8_t req_attr_btsm[] = {
+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 u_int8_t req_attr[] = {
+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 };
@@ -2749,16 +2235,16 @@
 	/* 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), (u_int8_t *) &aet);
+	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, u_int8_t bport)
+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();
-	u_int8_t attr = NM_ATT_BS11_LINE_CFG;
+	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,
@@ -2768,7 +2254,7 @@
 	return abis_nm_sendmsg(bts, msg);
 }
 
-int abis_nm_bs11_set_bport_line_cfg(struct gsm_bts *bts, u_int8_t bport, enum abis_bs11_line_cfg line_cfg)
+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();
@@ -2792,7 +2278,7 @@
 	struct in_addr addr;
 	struct abis_om_hdr *oh = msgb_l2(msg);
 	struct abis_om_fom_hdr *foh;
-	u_int8_t idstrlen = oh->data[0];
+	uint8_t idstrlen = oh->data[0];
 	struct tlv_parsed tp;
 	struct ipacc_ack_signal_data signal;
 
@@ -2804,7 +2290,7 @@
 	foh = (struct abis_om_fom_hdr *) (oh->data + 1 + idstrlen);
 	abis_nm_tlv_parse(&tp, msg->trx->bts, foh->data, oh->length-sizeof(*foh));
 
-	debugp_foh(foh);
+	abis_nm_debugp_foh(DNM, foh);
 
 	DEBUGPC(DNM, "IPACCESS(0x%02x): ", foh->msg_type);
 
@@ -2819,7 +2305,7 @@
 		}
 		if (TLVP_PRESENT(&tp, NM_ATT_IPACC_DST_IP_PORT))
 			DEBUGPC(DNM, "PORT=%u ",
-				ntohs(*((u_int16_t *)
+				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 ",
@@ -2830,7 +2316,7 @@
 		LOGP(DNM, LOGL_ERROR, "RSL CONNECT NACK ");
 		if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
 			DEBUGPC(DNM, " CAUSE=%s\n",
-				nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
+				abis_nm_nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
 		else
 			DEBUGPC(DNM, "\n");
 		break;
@@ -2842,7 +2328,7 @@
 		LOGP(DNM, LOGL_ERROR, "SET NVATTR NACK ");
 		if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
 			LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n",
-				nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
+				abis_nm_nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
 		else
 			LOGPC(DNM, LOGL_ERROR, "\n");
 		break;
@@ -2854,7 +2340,7 @@
 		LOGPC(DNM, LOGL_ERROR, "GET NVATTR NACK ");
 		if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
 			LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n",
-				nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
+				abis_nm_nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
 		else
 			LOGPC(DNM, LOGL_ERROR, "\n");
 		break;
@@ -2865,7 +2351,7 @@
 		LOGPC(DNM, LOGL_ERROR, "SET ATTR NACK ");
 		if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
 			LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n",
-				nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
+				abis_nm_nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
 		else
 			LOGPC(DNM, LOGL_ERROR, "\n");
 		break;
@@ -2881,12 +2367,12 @@
 	case NM_MT_IPACC_GET_NVATTR_NACK:
 		signal.trx = gsm_bts_trx_by_nr(msg->trx->bts, foh->obj_inst.trx_nr);
 		signal.msg_type = foh->msg_type;
-		dispatch_signal(SS_NM, S_NM_IPACC_NACK, &signal);
+		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(msg->trx->bts, foh->obj_inst.trx_nr);
 		signal.msg_type = foh->msg_type;
-		dispatch_signal(SS_NM, S_NM_IPACC_ACK, &signal);
+		osmo_signal_dispatch(SS_NM, S_NM_IPACC_ACK, &signal);
 		break;
 	default:
 		break;
@@ -2896,15 +2382,15 @@
 }
 
 /* send an ip-access manufacturer specific message */
-int abis_nm_ipaccess_msg(struct gsm_bts *bts, u_int8_t msg_type,
-			 u_int8_t obj_class, u_int8_t bts_nr,
-			 u_int8_t trx_nr, u_int8_t ts_nr,
-			 u_int8_t *attr, int attr_len)
+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;
-	u_int8_t *data;
+	uint8_t *data;
 
 	/* construct the 12.21 OM header, observe the erroneous length */
 	oh = (struct abis_om_hdr *) msgb_put(msg, sizeof(*oh));
@@ -2933,7 +2419,7 @@
 }
 
 /* set some attributes in NVRAM */
-int abis_nm_ipaccess_set_nvattr(struct gsm_bts_trx *trx, u_int8_t *attr,
+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,
@@ -2942,10 +2428,10 @@
 }
 
 int abis_nm_ipaccess_rsl_connect(struct gsm_bts_trx *trx,
-				 u_int32_t ip, u_int16_t port, u_int8_t stream)
+				 uint32_t ip, uint16_t port, uint8_t stream)
 {
 	struct in_addr ia;
-	u_int8_t attr[] = { NM_ATT_IPACC_STREAM_ID, 0,
+	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 };
 
@@ -2955,7 +2441,7 @@
 	attr[1] = stream;
 	attr[3] = port >> 8;
 	attr[4] = port & 0xff;
-	*(u_int32_t *)(attr+6) = ia.s_addr;
+	*(uint32_t *)(attr+6) = ia.s_addr;
 
 	/* if ip == 0, we use the default IP */
 	if (ip == 0)
@@ -2982,28 +2468,28 @@
 	return abis_nm_sendmsg(trx->bts, msg);
 }
 
-int abis_nm_ipaccess_set_attr(struct gsm_bts *bts, u_int8_t obj_class,
-				u_int8_t bts_nr, u_int8_t trx_nr, u_int8_t ts_nr,
-				u_int8_t *attr, u_int8_t attr_len)
+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(u_int8_t *buf, struct gsm_bts *bts)
+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);
-	*((u_int16_t *)(buf + 5)) = htons(bts->cell_identity);
+	*((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->nm_state.administrative = new_state;
+	trx->mo.nm_state.administrative = new_state;
 	if (!trx->bts || !trx->bts->oml_link)
 		return;
 
@@ -3021,12 +2507,12 @@
 	{ 0,				NULL }
 };
 
-const char *ipacc_testres_name(u_int8_t res)
+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 u_int8_t *buf)
+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;
@@ -3041,15 +2527,15 @@
 		cid->mnc += (buf[1] >> 4) *   1;
 	}
 
-	cid->lac = ntohs(*((u_int16_t *)&buf[3]));
-	cid->ci = ntohs(*((u_int16_t *)&buf[5]));
+	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, u_int8_t *buf)
+int ipac_parse_bcch_info(struct ipac_bcch_info *binf, uint8_t *buf)
 {
-	u_int8_t *cur = buf;
-	u_int16_t len;
+	uint8_t *cur = buf;
+	uint16_t len;
 
 	memset(binf, 0, sizeof(*binf));
 
@@ -3057,10 +2543,10 @@
 		return -EINVAL;
 	cur++;
 
-	len = ntohs(*(u_int16_t *)cur);
+	len = ntohs(*(uint16_t *)cur);
 	cur += 2;
 
-	binf->info_type = ntohs(*(u_int16_t *)cur);
+	binf->info_type = ntohs(*(uint16_t *)cur);
 	cur += 2;
 
 	if (binf->info_type & IPAC_BINF_FREQ_ERR_QUAL)
@@ -3078,15 +2564,15 @@
 	cur++;
 
 	if (binf->info_type & IPAC_BINF_FREQ_ERR_QUAL)
-		binf->freq_err = ntohs(*(u_int16_t *)cur);
+		binf->freq_err = ntohs(*(uint16_t *)cur);
 	cur += 2;
 
 	if (binf->info_type & IPAC_BINF_FRAME_OFFSET)
-		binf->frame_offset = ntohs(*(u_int16_t *)cur);
+		binf->frame_offset = ntohs(*(uint16_t *)cur);
 	cur += 2;
 
 	if (binf->info_type & IPAC_BINF_FRAME_NR_OFFSET)
-		binf->frame_nr_offset = ntohl(*(u_int32_t *)cur);
+		binf->frame_nr_offset = ntohl(*(uint32_t *)cur);
 	cur += 4;
 
 #if 0
diff --git a/src/libbsc/abis_nm_vty.c b/src/libbsc/abis_nm_vty.c
index 996a857..bcbc92d 100644
--- a/src/libbsc/abis_nm_vty.c
+++ b/src/libbsc/abis_nm_vty.c
@@ -26,10 +26,12 @@
 
 #include <arpa/inet.h>
 
+#include <osmocom/gsm/abis_nm.h>
+
 #include <openbsc/gsm_data.h>
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.h>
-#include <osmocore/talloc.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>
diff --git a/src/libbsc/abis_om2000.c b/src/libbsc/abis_om2000.c
index 805b844..b636e73 100644
--- a/src/libbsc/abis_om2000.c
+++ b/src/libbsc/abis_om2000.c
@@ -30,10 +30,10 @@
 
 #include <arpa/inet.h>
 
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.h>
-#include <osmocore/talloc.h>
-#include <osmocore/utils.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/tlv.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/utils.h>
 
 #include <openbsc/gsm_data.h>
 #include <openbsc/debug.h>
@@ -165,30 +165,141 @@
 };
 
 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_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			= 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,
+};
+
+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_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 },
+	},
 };
 
 static const struct value_string om2k_msgcode_vals[] = {
@@ -214,7 +325,7 @@
 	{ 0x001a, "CON Configuration Result" },
 	{ 0x001c, "Connect Command" },
 	{ 0x001e, "Connect Complete" },
-	{ 0x001f, "Connect Rejecte" },
+	{ 0x001f, "Connect Reject" },
 	{ 0x0028, "Disable Request" },
 	{ 0x002a, "Disable Request Accept" },
 	{ 0x002b, "Disable Request Reject" },
@@ -520,6 +631,16 @@
 				   "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);
+}
+
 static char *om2k_mo_name(const struct abis_om2k_mo *mo)
 {
 	static char mo_buf[64];
@@ -531,6 +652,151 @@
 	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->assoc_so);
+		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->assoc_so);
+		if (!trx)
+			return NULL;
+		break;
+	case OM2K_MO_CLS_RX:
+		trx = gsm_bts_trx_num(bts, mo->assoc_so);
+		if (!trx)
+			return NULL;
+		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->assoc_so);
+	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 void signal_op_state(struct gsm_bts *bts, struct abis_om2k_mo *mo)
+{
+	struct gsm_nm_state *nm_state = mo2nm_state(bts, mo);
+	struct nm_statechg_signal_data nsd;
+
+	nsd.bts = bts;
+	nsd.obj = mo2obj(bts, mo);
+	nsd.old_state = nm_state;
+	nsd.new_state = nm_state;
+	nsd.om2k_mo = mo;
+
+	osmo_signal_dispatch(SS_NM, S_NM_STATECHG_OPER, &nsd);
+}
+
 static int abis_om2k_sendmsg(struct gsm_bts *bts, struct msgb *msg)
 {
 	struct abis_om2k_hdr *o2h;
@@ -539,11 +805,13 @@
 	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:
-	case OM2K_MO_CLS_TS:
 		/* Route through per-TRX OML Link to the appropriate TRX */
 		to_trx_oml = 1;
 		msg->trx = gsm_bts_trx_by_nr(bts, o2h->mo.inst);
@@ -553,6 +821,16 @@
 			return -ENODEV;
 		}
 		break;
+	case OM2K_MO_CLS_TS:
+		/* Route through per-TRX OML Link to the appropriate TRX */
+		to_trx_oml = 1;
+		msg->trx = gsm_bts_trx_by_nr(bts, o2h->mo.assoc_so);
+		if (!msg->trx) {
+			LOGP(DNM, LOGL_ERROR, "MO=%s Tx Dropping msg to "
+				"non-existing TRX\n", om2k_mo_name(&o2h->mo));
+			return -ENODEV;
+		}
+		break;
 	default:
 		/* Route through the IXU/DXU OML Link */
 		msg->trx = bts->c0;
@@ -564,12 +842,12 @@
 }
 
 static void fill_om2k_hdr(struct abis_om2k_hdr *o2h, const struct abis_om2k_mo *mo,
-			 uint16_t msg_type, uint8_t attr_len)
+			  uint16_t msg_type)
 {
 	o2h->om.mdisc = ABIS_OM_MDISC_FOM;
 	o2h->om.placement = ABIS_OM_PLACEMENT_ONLY;
 	o2h->om.sequence = 0;
-	o2h->om.length = 6 + attr_len;
+	/* We fill o2h->om.length later during om2k_sendmsg() */
 	o2h->msg_type = htons(msg_type);
 	memcpy(&o2h->mo, mo, sizeof(o2h->mo));
 }
@@ -587,7 +865,7 @@
 	struct tm *tm;
 
 	o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
-	fill_om2k_hdr(o2k, &om2k_mo_cf, OM2K_MSGT_CAL_TIME_RESP, 7);
+	fill_om2k_hdr(o2k, &om2k_mo_cf, OM2K_MSGT_CAL_TIME_RESP);
 
 	tm_t = time(NULL);
 	tm = localtime(&tm_t);
@@ -610,7 +888,7 @@
 	struct abis_om2k_hdr *o2k;
 
 	o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
-	fill_om2k_hdr(o2k, mo, msg_type, 0);
+	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));
@@ -665,31 +943,59 @@
 	struct abis_om2k_hdr *o2k;
 
 	o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
-	fill_om2k_hdr(o2k, mo, OM2K_MSGT_OP_INFO, 2);
+	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_is_conf_req(struct gsm_bts *bts, struct om2k_is_conn_grp *cg,
-			     unsigned int num_cg )
+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, &om2k_mo_is, OM2K_MSGT_IS_CONF_REQ,
-		      2 + 2 + TLV_GROSS_LEN(num_cg * sizeof(*cg)));
+	fill_om2k_hdr(o2k, &om2k_mo_is, 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_cg * sizeof(*cg), (uint8_t *)cg);
+		     num_grps * sizeof(*cg), (uint8_t *)cg);
+
+	talloc_free(cg);
 
 	return abis_om2k_sendmsg(bts, msg);
 }
@@ -701,8 +1007,7 @@
 	struct abis_om2k_hdr *o2k;
 
 	o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
-	fill_om2k_hdr(o2k, &om2k_mo_con, OM2K_MSGT_CON_CONF_REQ,
-		      2 + 2 + TLV_GROSS_LEN(len));
+	fill_om2k_hdr(o2k, &om2k_mo_con, OM2K_MSGT_CON_CONF_REQ);
 
 	msgb_tv_put(msg, OM2K_DEI_LIST_NR, 1);
 	msgb_tv_put(msg, OM2K_DEI_END_LIST_NR, 1);
@@ -719,7 +1024,7 @@
 	mo->class = cls;
 	mo->bts = 0;
 	mo->inst = trx->nr;
-	mo->assoc_so = 0;
+	mo->assoc_so = 255;
 }
 
 static void om2k_ts_to_mo(struct abis_om2k_mo *mo,
@@ -741,10 +1046,10 @@
 	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, 3+2);
+	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, 0x03); /* A+B */
+	msgb_tv_put(msg, OM2K_DEI_RX_DIVERSITY, 0x02); /* A */
 
 	return abis_om2k_sendmsg(trx->bts, msg);
 }
@@ -759,7 +1064,7 @@
 	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, 3+2+2+2);
+	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);
@@ -785,10 +1090,10 @@
 	struct abis_om2k_hdr *o2k;
 
 	o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k));
-	fill_om2k_hdr(o2k, &om2k_mo_tf, OM2K_MSGT_TF_CONF_REQ,
-			2+1+sizeof(fs_offset_undef));
+	fill_om2k_hdr(o2k, &om2k_mo_tf, 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);
 
@@ -814,28 +1119,37 @@
 	}
 }
 
+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++ = 0x00;
-				*cur++ = i >> 8;
-				*cur++ = i & 0xff;
-			}
+			if (bitvec_get_bit_pos(&ts->hopping.arfcns, i))
+				cur += put_freq_list(cur, i);
 		}
-	} else {
-		*cur++ = 0x00; /* TX/RX address */
-		*cur++ = ts->trx->arfcn >> 8;
-		*cur++ = ts->trx->arfcn && 0xff;
-	}
-	return (cur - list);
+	} 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();
@@ -846,13 +1160,13 @@
 
 	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,
-			2+2+TLV_GROSS_LEN(freq_list_len)+2+2+2+2+3+2);
+	fill_om2k_hdr(o2k, &mo, OM2K_MSGT_TS_CONF_REQ);
 
 	msgb_tv_put(msg, OM2K_DEI_COMBINATION, pchan2comb(ts->pchan));
 	msgb_tv_put(msg, OM2K_DEI_TS_NR, ts->nr);
@@ -860,10 +1174,62 @@
 	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, 0x03); /* A+B */
+	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, 0x04);
+		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, ts->trx->bts->tsc);
+		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, 0x04);
+		msgb_tv_put(msg, OM2K_DEI_NY1, 35);
+		msgb_tv_put(msg, OM2K_DEI_CBCH_INDICATOR, 0);
+		msgb_tv_put(msg, OM2K_DEI_TSC, ts->trx->bts->tsc);
+		/* 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, 0x04);
+		msgb_tv_put(msg, OM2K_DEI_NY1, 35);
+		msgb_tv_put(msg, OM2K_DEI_TSC, ts->trx->bts->tsc);
+		/* 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);
+		break;
+	}
 
 	return abis_om2k_sendmsg(ts->trx->bts, msg);
 }
@@ -875,7 +1241,7 @@
 	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, 2+len);
+	fill_om2k_hdr(o2k, mo, OM2K_MSGT_NEGOT_REQ_ACK);
 
 	msgb_tlv_put(msg, OM2K_DEI_NEGOT_REC2, len, data);
 
@@ -968,7 +1334,129 @@
 {
 	struct abis_om2k_hdr *o2h = msgb_l2(msg);
 
-	/* FIXME: update Operational state in our structures */
+	/* This Acknowledgement does not contain the actual operational state,
+	 * so we signal whatever state we saved when we sent the Op Info
+	 * request */
+
+	signal_op_state(msg->trx->bts, &o2h->mo);
+
+	return 0;
+}
+
+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 }
+};
+
+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;
+}
+
+/* Process a Configuration Result message */
+static int process_conf_res(struct gsm_bts *bts, struct msgb *msg)
+{
+	struct abis_om2k_hdr *o2h = msgb_l2(msg);
+	uint16_t msg_type = ntohs(o2h->msg_type);
+	struct nm_om2k_signal_data nsd;
+	struct tlv_parsed tp;
+	uint8_t acc;
+	unsigned int log_level;
+	int ret;
+
+	memset(&nsd, 0, sizeof(nsd));
+
+	abis_om2k_msg_tlv_parse(&tp, o2h);
+	if (!TLVP_PRESENT(&tp, OM2K_DEI_ACCORDANCE_IND))
+		return -EIO;
+
+	acc = *TLVP_VAL(&tp, OM2K_DEI_ACCORDANCE_IND);
+
+	switch (acc) {
+	case 0:
+		log_level = LOGL_DEBUG;
+		ret = 0;
+		break;
+	default:
+		log_level = LOGL_ERROR;
+		ret = -EINVAL;
+		break;
+	}
+
+	LOGP(DNM, log_level, "Rx MO=%s %s, Accordance: %s\n",
+		om2k_mo_name(&o2h->mo),
+		get_value_string(om2k_msgcode_vals, msg_type),
+		get_value_string(om2k_accordance_strings, acc));
+
+	nsd.bts = bts;
+	nsd.obj = mo2obj(bts, &o2h->mo);
+	nsd.om2k_mo = &o2h->mo;
+	nsd.accordance_ind = acc;
+	osmo_signal_dispatch(SS_NM, S_NM_OM2K_CONF_RES, &nsd);
+
+	return ret;
+}
+
+static int process_mo_state(struct gsm_bts *bts, struct msgb *msg)
+{
+	struct abis_om2k_hdr *o2h = msgb_l2(msg);
+	uint16_t msg_type = ntohs(o2h->msg_type);
+	struct tlv_parsed tp;
+	uint8_t mo_state;
+
+	abis_om2k_msg_tlv_parse(&tp, o2h);
+	if (!TLVP_PRESENT(&tp, OM2K_DEI_MO_STATE))
+		return -EIO;
+	mo_state = *TLVP_VAL(&tp, OM2K_DEI_MO_STATE);
+
+	LOGP(DNM, LOGL_DEBUG, "Rx MO=%s %s, MO State: %s\n",
+		om2k_mo_name(&o2h->mo),
+		get_value_string(om2k_msgcode_vals, msg_type),
+		get_value_string(om2k_mostate_vals, mo_state));
+
+	update_mo_state(bts, &o2h->mo, mo_state);
 
 	return 0;
 }
@@ -1004,7 +1492,7 @@
 
 	DEBUGP(DNM, "Rx MO=%s %s (%s)\n", om2k_mo_name(&o2h->mo),
 		get_value_string(om2k_msgcode_vals, msg_type),
-		hexdump(msg->l2h, msgb_l2len(msg)));
+		osmo_hexdump(msg->l2h, msgb_l2len(msg)));
 
 	switch (msg_type) {
 	case OM2K_MSGT_CAL_TIME_REQ:
@@ -1012,33 +1500,41 @@
 		break;
 	case OM2K_MSGT_FAULT_REP:
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_FAULT_REP_ACK);
+		process_mo_state(bts, msg);
 		break;
 	case OM2K_MSGT_NEGOT_REQ:
 		rc = om2k_rx_negot_req(msg);
 		break;
 	case OM2K_MSGT_START_RES:
 		rc = om2k_rx_start_res(msg);
+		process_mo_state(bts, msg);
 		break;
 	case OM2K_MSGT_OP_INFO_ACK:
 		rc = om2k_rx_op_info_ack(msg);
 		break;
 	case OM2K_MSGT_IS_CONF_RES:
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_IS_CONF_RES_ACK);
+		process_conf_res(bts, msg);
 		break;
 	case OM2K_MSGT_CON_CONF_RES:
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_CON_CONF_RES_ACK);
+		process_conf_res(bts, msg);
 		break;
 	case OM2K_MSGT_TX_CONF_RES:
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TX_CONF_RES_ACK);
+		process_conf_res(bts, msg);
 		break;
 	case OM2K_MSGT_RX_CONF_RES:
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_RX_CONF_RES_ACK);
+		process_conf_res(bts, msg);
 		break;
 	case OM2K_MSGT_TS_CONF_RES:
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TS_CONF_RES_ACK);
+		process_conf_res(bts, msg);
 		break;
 	case OM2K_MSGT_TF_CONF_RES:
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TF_CONF_RES_ACK);
+		process_conf_res(bts, msg);
 		break;
 	case OM2K_MSGT_CONNECT_COMPL:
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_RESET_CMD);
@@ -1048,14 +1544,18 @@
 		break;
 	case OM2K_MSGT_ENABLE_RES:
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_ENABLE_RES_ACK);
+		process_mo_state(bts, msg);
 		break;
 	case OM2K_MSGT_DISABLE_RES:
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_DISABLE_RES_ACK);
+		process_mo_state(bts, msg);
 		break;
 	case OM2K_MSGT_TEST_RES:
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TEST_RES_ACK);
+		process_mo_state(bts, msg);
 		break;
 	case OM2K_MSGT_STATUS_RESP:
+		process_mo_state(bts, msg);
 		break;
 	case OM2K_MSGT_START_REQ_ACK:
 	case OM2K_MSGT_CON_CONF_REQ_ACK:
@@ -1068,6 +1568,22 @@
 	case OM2K_MSGT_ALARM_STATUS_REQ_ACK:
 	case OM2K_MSGT_DISABLE_REQ_ACK:
 		break;
+	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;
 	default:
 		LOGP(DNM, LOGL_NOTICE, "Rx unhandled OM2000 msg %s\n",
 			get_value_string(om2k_msgcode_vals, msg_type));
diff --git a/src/libbsc/abis_om2000_vty.c b/src/libbsc/abis_om2000_vty.c
index 5ebb2a3..704f955 100644
--- a/src/libbsc/abis_om2000_vty.c
+++ b/src/libbsc/abis_om2000_vty.c
@@ -27,9 +27,9 @@
 #include <arpa/inet.h>
 
 #include <openbsc/gsm_data.h>
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.h>
-#include <osmocore/talloc.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>
@@ -324,21 +324,6 @@
 	return CMD_SUCCESS;
 }
 
-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;
-}
-
-struct is_conn_group {
-	struct llist_head list;
-	uint16_t icp1;
-	uint16_t icp2;
-	uint8_t ci;
-};
-
 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 Connnection List\n"
@@ -375,41 +360,6 @@
 }
 
 
-DEFUN(om2k_is_conf_req, om2k_is_conf_req_cmd,
-	"is-conf-req",
-	"Send IS Configuration Request\n")
-{
-	struct oml_node_state *oms = vty->index;
-	struct gsm_bts *bts = oms->bts;
-	struct is_conn_group *grp;
-	unsigned int num_grps = 0, i = 0;
-	struct om2k_is_conn_grp *o2grps;
-
-	/* count number of groups in linked list */
-	llist_for_each_entry(grp, &bts->rbs2000.is.conn_groups, list)
-		num_grps++;
-
-	if (!num_grps) {
-		vty_out(vty, "%% No IS connection groups configured!%s",
-			VTY_NEWLINE);
-		return CMD_WARNING;
-	}
-
-	/* allocate buffer for oml group array */
-	o2grps = 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(&o2grps[i++], grp->icp1, grp->icp2, grp->ci);
-
-	/* send the actual OML request */
-	abis_om2k_tx_is_conf_req(oms->bts, o2grps, num_grps);
-
-	talloc_free(o2grps);
-
-	return CMD_SUCCESS;
-}
-
 DEFUN(om2k_conf_req, om2k_conf_req_cmd,
 	"configuration-request",
 	"Send the configuration request for current MO\n")
@@ -420,6 +370,9 @@
 	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) {
@@ -449,7 +402,7 @@
 			abis_om2k_tx_rx_conf_req(trx);
 			break;
 		case OM2K_MO_CLS_TX:
-			abis_om2k_tx_rx_conf_req(trx);
+			abis_om2k_tx_tx_conf_req(trx);
 			break;
 		default:
 			break;
@@ -503,7 +456,6 @@
 	install_element(OM2K_NODE, &om2k_op_info_cmd);
 	install_element(OM2K_NODE, &om2k_test_cmd);
 	install_element(OM2K_NODE, &om2k_conf_req_cmd);
-	install_element(OM2K_NODE, &om2k_is_conf_req_cmd);
 	install_element(OM2K_NODE, &om2k_con_list_dec_cmd);
 	install_element(OM2K_NODE, &om2k_con_list_tei_cmd);
 
diff --git a/src/libbsc/abis_rsl.c b/src/libbsc/abis_rsl.c
index 9a4dc5b..8356bd9 100644
--- a/src/libbsc/abis_rsl.c
+++ b/src/libbsc/abis_rsl.c
@@ -23,31 +23,28 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
-#include <sys/types.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
 #include <openbsc/gsm_data.h>
 #include <openbsc/gsm_04_08.h>
-#include <osmocore/gsm_utils.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 <osmocore/tlv.h>
+#include <osmocom/gsm/tlv.h>
 #include <openbsc/paging.h>
 #include <openbsc/signal.h>
 #include <openbsc/meas_rep.h>
 #include <openbsc/rtp_proxy.h>
-#include <osmocore/rsl.h>
+#include <osmocom/gsm/rsl.h>
 
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 
 #define RSL_ALLOC_SIZE		1024
 #define RSL_ALLOC_HEADROOM	128
 
-#define MAX(a, b) (a) >= (b) ? (a) : (b)
-
 static int rsl_send_imm_assignment(struct gsm_lchan *lchan);
 
 static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan,
@@ -56,10 +53,10 @@
 	struct lchan_signal_data sig;
 	sig.lchan = lchan;
 	sig.mr = resp;
-	dispatch_signal(SS_LCHAN, sig_no, &sig);
+	osmo_signal_dispatch(SS_LCHAN, sig_no, &sig);
 }
 
-static u_int8_t mdisc_by_msgtype(u_int8_t msg_type)
+static uint8_t mdisc_by_msgtype(uint8_t msg_type)
 {
 	/* mask off the transparent bit ? */
 	msg_type &= 0xfe;
@@ -79,7 +76,7 @@
 }
 
 static inline void init_dchan_hdr(struct abis_rsl_dchan_hdr *dh,
-				  u_int8_t msg_type)
+				  uint8_t msg_type)
 {
 	dh->c.msg_discr = mdisc_by_msgtype(msg_type);
 	dh->c.msg_type = msg_type;
@@ -87,12 +84,12 @@
 }
 
 /* determine logical channel based on TRX and channel number IE */
-struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, u_int8_t chan_nr)
+struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr)
 {
 	struct gsm_lchan *lchan;
-	u_int8_t ts_nr = chan_nr & 0x07;
-	u_int8_t cbits = chan_nr >> 3;
-	u_int8_t lch_idx;
+	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];
 
 	if (cbits == 0x01) {
@@ -137,78 +134,16 @@
 	return lchan;
 }
 
-/* See Table 10.5.25 of GSM04.08 */
-static u_int8_t ts2chan_nr(const struct gsm_bts_trx_ts *ts, uint8_t lchan_nr)
-{
-	u_int8_t cbits, chan_nr;
-
-	switch (ts->pchan) {
-	case GSM_PCHAN_TCH_F:
-	case GSM_PCHAN_PDCH:
-	case GSM_PCHAN_TCH_F_PDCH:
-		cbits = 0x01;
-		break;
-	case GSM_PCHAN_TCH_H:
-		cbits = 0x02;
-		cbits += lchan_nr;
-		break;
-	case GSM_PCHAN_CCCH_SDCCH4:
-		cbits = 0x04;
-		cbits += lchan_nr;
-		break;
-	case GSM_PCHAN_SDCCH8_SACCH8C:
-		cbits = 0x08;
-		cbits += lchan_nr;
-		break;
-	default:
-	case GSM_PCHAN_CCCH:
-		cbits = 0x10;
-		break;
-	}
-
-	chan_nr = (cbits << 3) | (ts->nr & 0x7);
-
-	return chan_nr;
-}
-
-u_int8_t lchan2chan_nr(const struct gsm_lchan *lchan)
-{
-	return ts2chan_nr(lchan->ts, lchan->nr);
-}
-
 /* As per TS 03.03 Section 2.2, the IMSI has 'not more than 15 digits' */
-u_int64_t str_to_imsi(const char *imsi_str)
+uint64_t str_to_imsi(const char *imsi_str)
 {
-	u_int64_t ret;
+	uint64_t ret;
 
 	ret = strtoull(imsi_str, NULL, 10);
 
 	return ret;
 }
 
-/* Table 5 Clause 7 TS 05.02 */
-unsigned int n_pag_blocks(int bs_ccch_sdcch_comb, unsigned int bs_ag_blks_res)
-{
-	if (!bs_ccch_sdcch_comb)
-		return 9 - bs_ag_blks_res;
-	else
-		return 3 - bs_ag_blks_res;
-}
-
-/* Chapter 6.5.2 of TS 05.02 */
-unsigned int get_ccch_group(u_int64_t imsi, unsigned int bs_cc_chans,
-			    unsigned int n_pag_blocks)
-{
-	return (imsi % 1000) % (bs_cc_chans * n_pag_blocks) / n_pag_blocks;
-}
-
-/* Chapter 6.5.2 of TS 05.02 */
-unsigned int get_paging_group(u_int64_t imsi, unsigned int bs_cc_chans,
-			      int n_pag_blocks)
-{
-	return (imsi % 1000) % (bs_cc_chans * n_pag_blocks) % n_pag_blocks;
-}
-
 static struct msgb *rsl_msgb_alloc(void)
 {
 	return msgb_alloc_headroom(RSL_ALLOC_SIZE, RSL_ALLOC_HEADROOM,
@@ -216,7 +151,7 @@
 }
 
 #define MACBLOCK_SIZE	23
-static void pad_macblock(u_int8_t *out, const u_int8_t *in, int len)
+static void pad_macblock(uint8_t *out, const uint8_t *in, int len)
 {
 	memcpy(out, in, len);
 
@@ -225,7 +160,7 @@
 }
 
 /* Chapter 9.3.7: Encryption Information */
-static int build_encr_info(u_int8_t *out, struct gsm_lchan *lchan)
+static int build_encr_info(uint8_t *out, struct gsm_lchan *lchan)
 {
 	*out++ = lchan->encr.alg_id & 0xff;
 	if (lchan->encr.key_len)
@@ -233,7 +168,7 @@
 	return lchan->encr.key_len + 1;
 }
 
-static void print_rsl_cause(int lvl, const u_int8_t *cause_v, u_int8_t cause_len)
+static void print_rsl_cause(int lvl, const uint8_t *cause_v, uint8_t cause_len)
 {
 	int i;
 
@@ -244,8 +179,8 @@
 }
 
 /* Send a BCCH_INFO message as per Chapter 8.5.1 */
-int rsl_bcch_info(struct gsm_bts_trx *trx, u_int8_t type,
-		  const u_int8_t *data, int len)
+int rsl_bcch_info(struct gsm_bts_trx *trx, uint8_t type,
+		  const uint8_t *data, int len)
 {
 	struct abis_rsl_dchan_hdr *dh;
 	struct msgb *msg = rsl_msgb_alloc();
@@ -262,8 +197,8 @@
 	return abis_rsl_sendmsg(msg);
 }
 
-int rsl_sacch_filling(struct gsm_bts_trx *trx, u_int8_t type,
-		      const u_int8_t *data, int len)
+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();
@@ -280,12 +215,12 @@
 	return abis_rsl_sendmsg(msg);
 }
 
-int rsl_sacch_info_modify(struct gsm_lchan *lchan, u_int8_t type,
-			  const u_int8_t *data, int len)
+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();
-	u_int8_t chan_nr = lchan2chan_nr(lchan);
+	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);
@@ -303,7 +238,7 @@
 {
 	struct abis_rsl_dchan_hdr *dh;
 	struct msgb *msg;
-	u_int8_t chan_nr = lchan2chan_nr(lchan);
+	uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
 
 	db = abs(db);
 	if (db > 30)
@@ -330,7 +265,7 @@
 {
 	struct abis_rsl_dchan_hdr *dh;
 	struct msgb *msg;
-	u_int8_t chan_nr = lchan2chan_nr(lchan);
+	uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
 	int ctl_lvl;
 
 	ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, dbm);
@@ -421,12 +356,12 @@
 
 /* Chapter 8.4.1 */
 #if 0
-int rsl_chan_activate(struct gsm_bts_trx *trx, u_int8_t chan_nr,
-		      u_int8_t act_type,
+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,
-		      u_int8_t bs_power, u_int8_t ms_power,
-		      u_int8_t ta)
+		      uint8_t bs_power, uint8_t ms_power,
+		      uint8_t ta)
 {
 	struct abis_rsl_dchan_hdr *dh;
 	struct msgb *msg = rsl_msgb_alloc();
@@ -438,12 +373,12 @@
 	msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
 	/* For compatibility with Phase 1 */
 	msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(*chan_mode),
-		     (u_int8_t *) chan_mode);
+		     (uint8_t *) chan_mode);
 	msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
-		     (u_int8_t *) chan_ident);
+		     (uint8_t *) chan_ident);
 #if 0
 	msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
-		     (u_int8_t *) &encr_info);
+		     (uint8_t *) &encr_info);
 #endif
 	msgb_tv_put(msg, RSL_IE_BS_POWER, bs_power);
 	msgb_tv_put(msg, RSL_IE_MS_POWER, ms_power);
@@ -455,15 +390,15 @@
 }
 #endif
 
-int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type,
-			    u_int8_t ta, u_int8_t ho_ref)
+int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type,
+			    uint8_t ta, uint8_t ho_ref)
 {
 	struct abis_rsl_dchan_hdr *dh;
 	struct msgb *msg;
 	int rc;
 	uint8_t *len;
 
-	u_int8_t chan_nr = lchan2chan_nr(lchan);
+	uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
 	struct rsl_ie_chan_mode cm;
 	struct gsm48_chan_desc cd;
 
@@ -481,7 +416,7 @@
 
 	msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
 	msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
-		     (u_int8_t *) &cm);
+		     (uint8_t *) &cm);
 
 	/*
 	 * The Channel Identification is needed for Phase1 phones
@@ -505,7 +440,7 @@
 	*len = msgb_l3len(msg);
 
 	if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
-		u_int8_t encr_info[MAX_A5_KEY_LEN+2];
+		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);
@@ -526,7 +461,7 @@
 
 	if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
 		msgb_tlv_put(msg, RSL_IE_MR_CONFIG, sizeof(lchan->mr_conf),
-			     (u_int8_t *) &lchan->mr_conf);
+			     (uint8_t *) &lchan->mr_conf);
 
 	msg->trx = lchan->ts->trx;
 
@@ -540,7 +475,7 @@
 	struct msgb *msg;
 	int rc;
 
-	u_int8_t chan_nr = lchan2chan_nr(lchan);
+	uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
 	struct rsl_ie_chan_mode cm;
 
 	rc = channel_mode_from_lchan(&cm, lchan);
@@ -553,10 +488,10 @@
 	dh->chan_nr = chan_nr;
 
 	msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
-		     (u_int8_t *) &cm);
+		     (uint8_t *) &cm);
 
 	if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
-		u_int8_t encr_info[MAX_A5_KEY_LEN+2];
+		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);
@@ -564,7 +499,7 @@
 
 	if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR) {
 		msgb_tlv_put(msg, RSL_IE_MR_CONFIG, sizeof(lchan->mr_conf),
-			     (u_int8_t *) &lchan->mr_conf);
+			     (uint8_t *) &lchan->mr_conf);
 	}
 
 	msg->trx = lchan->ts->trx;
@@ -577,9 +512,9 @@
 {
 	struct abis_rsl_dchan_hdr *dh;
 	struct gsm_lchan *lchan = msg->lchan;
-	u_int8_t chan_nr = lchan2chan_nr(lchan);
-	u_int8_t encr_info[MAX_A5_KEY_LEN+2];
-	u_int8_t l3_len = msg->len;
+	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 */
@@ -612,7 +547,7 @@
 
 	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
 	init_dchan_hdr(dh, RSL_MT_DEACTIVATE_SACCH);
-	dh->chan_nr = lchan2chan_nr(lchan);
+	dh->chan_nr = gsm_lchan2chan_nr(lchan);
 
 	msg->lchan = lchan;
 	msg->trx = lchan->ts->trx;
@@ -654,7 +589,7 @@
 	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 = lchan2chan_nr(lchan);
+	dh->chan_nr = gsm_lchan2chan_nr(lchan);
 
 	msg->lchan = lchan;
 	msg->trx = lchan->ts->trx;
@@ -670,7 +605,7 @@
 		rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
 		lchan->error_timer.data = lchan;
 		lchan->error_timer.cb = error_timeout_cb;
-		bsc_schedule_timer(&lchan->error_timer,
+		osmo_timer_schedule(&lchan->error_timer,
 				   msg->trx->bts->network->T3111 + 2, 0);
 	}
 
@@ -695,7 +630,7 @@
 		LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
 			gsm_lchan_name(lchan),
 			gsm_lchans_name(lchan->state));
-	bsc_del_timer(&lchan->T3111);
+	osmo_timer_del(&lchan->T3111);
 	/* we have an error timer pending to release that */
 	if (lchan->state != LCHAN_S_REL_ERR)
 		rsl_lchan_set_state(lchan, LCHAN_S_NONE);
@@ -704,8 +639,8 @@
 	return 0;
 }
 
-int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len,
-		   u_int8_t *ms_ident, u_int8_t chan_needed)
+int rsl_paging_cmd(struct gsm_bts *bts, uint8_t paging_group, uint8_t len,
+		   uint8_t *ms_ident, uint8_t chan_needed)
 {
 	struct abis_rsl_dchan_hdr *dh;
 	struct msgb *msg = rsl_msgb_alloc();
@@ -723,7 +658,7 @@
 	return abis_rsl_sendmsg(msg);
 }
 
-int imsi_str2bcd(u_int8_t *bcd_out, const char *str_in)
+int imsi_str2bcd(uint8_t *bcd_out, const char *str_in)
 {
 	int i, len = strlen(str_in);
 
@@ -741,11 +676,11 @@
 }
 
 /* Chapter 8.5.6 */
-int rsl_imm_assign_cmd(struct gsm_bts *bts, u_int8_t len, u_int8_t *val)
+int rsl_imm_assign_cmd(struct gsm_bts *bts, uint8_t len, uint8_t *val)
 {
 	struct msgb *msg = rsl_msgb_alloc();
 	struct abis_rsl_dchan_hdr *dh;
-	u_int8_t buf[MACBLOCK_SIZE];
+	uint8_t buf[MACBLOCK_SIZE];
 
 	dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
 	init_dchan_hdr(dh, RSL_MT_IMMEDIATE_ASSIGN_CMD);
@@ -776,11 +711,11 @@
 	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 = lchan2chan_nr(lchan);
-	msgb_tv_put(msg, RSL_IE_SIEMENS_MRPCI, *(u_int8_t *)mrpci);
+	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), *(u_int8_t *)mrpci);
+		gsm_lchan_name(lchan), *(uint8_t *)mrpci);
 
 	msg->trx = lchan->ts->trx;
 
@@ -790,14 +725,14 @@
 
 /* Send "DATA REQUEST" message with given L3 Info payload */
 /* Chapter 8.3.1 */
-int rsl_data_request(struct msgb *msg, u_int8_t link_id)
+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, lchan2chan_nr(msg->lchan),
+	rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, gsm_lchan2chan_nr(msg->lchan),
 			link_id, 1);
 
 	msg->trx = msg->lchan->ts->trx;
@@ -807,11 +742,11 @@
 
 /* Send "ESTABLISH REQUEST" message with given L3 Info payload */
 /* Chapter 8.3.1 */
-int rsl_establish_request(struct gsm_lchan *lchan, u_int8_t link_id)
+int rsl_establish_request(struct gsm_lchan *lchan, uint8_t link_id)
 {
 	struct msgb *msg;
 
-	msg = rsl_rll_simple(RSL_MT_EST_REQ, lchan2chan_nr(lchan),
+	msg = rsl_rll_simple(RSL_MT_EST_REQ, gsm_lchan2chan_nr(lchan),
 			     link_id, 0);
 	msg->trx = lchan->ts->trx;
 
@@ -823,12 +758,12 @@
    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, u_int8_t link_id, u_int8_t reason)
+int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id, uint8_t reason)
 {
 
 	struct msgb *msg;
 
-	msg = rsl_rll_simple(RSL_MT_REL_REQ, lchan2chan_nr(lchan),
+	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, reason);
@@ -889,7 +824,7 @@
 
 	rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
 	if (TLVP_PRESENT(&tp, RSL_IE_CAUSE)) {
-		const u_int8_t *cause = TLVP_VAL(&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));
 		if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC)
@@ -923,7 +858,7 @@
 
 	LOGPC(DRSL, LOGL_NOTICE, "\n");
 	/* FIXME: only free it after channel release ACK */
-	counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail);
+	osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail);
 	return rsl_rf_chan_release(msg->lchan, 1);
 }
 
@@ -982,8 +917,8 @@
 	struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
 	struct tlv_parsed tp;
 	struct gsm_meas_rep *mr = lchan_next_meas_rep(msg->lchan);
-	u_int8_t len;
-	const u_int8_t *val;
+	uint8_t len;
+	const uint8_t *val;
 	int rc;
 
 	/* check if this channel is actually active */
@@ -1034,7 +969,7 @@
 		mr->ms_l1.ta = val[1];
 	}
 	if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
-		msg->l3h = (u_int8_t *) TLVP_VAL(&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;
@@ -1247,11 +1182,11 @@
 	enum gsm_chan_t lctype;
 	enum gsm_chreq_reason_t chreq_reason;
 	struct gsm_lchan *lchan;
-	u_int8_t rqd_ta;
+	uint8_t rqd_ta;
 	int is_lu;
 
-	u_int16_t arfcn;
-	u_int8_t ts_number, subch;
+	uint16_t arfcn;
+	uint8_t ts_number, subch;
 
 	/* parse request reference to be used in immediate assign */
 	if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
@@ -1269,7 +1204,7 @@
 	lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
 	chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
 
-	counter_inc(bts->network->stats.chreq.total);
+	osmo_counter_inc(bts->network->stats.chreq.total);
 
 	/*
 	 * We want LOCATION UPDATES to succeed and will assign a TCH
@@ -1282,7 +1217,7 @@
 	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);
-		counter_inc(bts->network->stats.chreq.no_channel);
+		osmo_counter_inc(bts->network->stats.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);
@@ -1329,7 +1264,7 @@
 static int rsl_send_imm_assignment(struct gsm_lchan *lchan)
 {
 	struct gsm_bts *bts = lchan->ts->trx->bts;
-	u_int8_t buf[GSM_MACBLOCK_LEN];
+	uint8_t buf[GSM_MACBLOCK_LEN];
 	struct gsm48_imm_ass *ia = (struct gsm48_imm_ass *) buf;
 
 	/* create IMMEDIATE ASSIGN 04.08 messge */
@@ -1355,20 +1290,20 @@
 	/* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
 	lchan->T3101.cb = t3101_expired;
 	lchan->T3101.data = lchan;
-	bsc_schedule_timer(&lchan->T3101, bts->network->T3101, 0);
+	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, (u_int8_t *) ia);
+	return rsl_imm_assign_cmd(bts, sizeof(*ia)+ia->mob_alloc_len, (uint8_t *) ia);
 }
 
 /* MS has requested a channel on the RACH */
 static int rsl_rx_ccch_load(struct msgb *msg)
 {
 	struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
-	u_int16_t pg_buf_space;
-	u_int16_t rach_slot_count = -1;
-	u_int16_t rach_busy_count = -1;
-	u_int16_t rach_access_count = -1;
+	uint16_t pg_buf_space;
+	uint16_t rach_slot_count = -1;
+	uint16_t rach_busy_count = -1;
+	uint16_t rach_access_count = -1;
 
 	switch (rslh->data[0]) {
 	case RSL_IE_PAGING_LOAD:
@@ -1428,7 +1363,7 @@
 static int rsl_rx_rll_err_ind(struct msgb *msg)
 {
 	struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
-	u_int8_t *rlm_cause = rllh->data;
+	uint8_t *rlm_cause = rllh->data;
 
 	LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s\n",
 		gsm_lchan_name(msg->lchan),
@@ -1437,7 +1372,7 @@
 	rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
 
 	if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) {
-		counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err);
+		osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err);
 		return rsl_rf_chan_release(msg->lchan, 1);
 	}
 
@@ -1467,7 +1402,7 @@
 	lchan->T3111.cb = t3111_expired;
 	lchan->T3111.data = lchan;
 	bts = lchan->ts->trx->bts;
-	bsc_schedule_timer(&lchan->T3111, bts->network->T3111, 0);
+	osmo_timer_schedule(&lchan->T3111, bts->network->T3111, 0);
 }
 
 /*	ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
@@ -1481,7 +1416,7 @@
 	struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
 	int rc = 0;
 	char *ts_name;
-	u_int8_t sapi = rllh->link_id & 7;
+	uint8_t sapi = rllh->link_id & 7;
 
 	msg->lchan = lchan_lookup(msg->trx, rllh->chan_nr);
 	ts_name = gsm_lchan_name(msg->lchan);
@@ -1501,7 +1436,7 @@
 		DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
 		/* lchan is established, stop T3101 */
 		msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_MS;
-		bsc_del_timer(&msg->lchan->T3101);
+		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) {
@@ -1546,7 +1481,7 @@
 	return rc;
 }
 
-static u_int8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
+static uint8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
 {
 	switch (lchan->tch_mode) {
 	case GSM48_CMODE_SPEECH_V1:
@@ -1583,7 +1518,7 @@
 	return 0;
 }
 
-static u_int8_t ipa_rtp_pt_for_lchan(struct gsm_lchan *lchan)
+static uint8_t ipa_rtp_pt_for_lchan(struct gsm_lchan *lchan)
 {
 	struct gsm_network *net = lchan->ts->trx->bts->network;
 
@@ -1631,23 +1566,23 @@
 static void ipac_parse_rtp(struct gsm_lchan *lchan, struct tlv_parsed *tv)
 {
 	struct in_addr ip;
-	u_int16_t port, conn_id;
+	uint16_t port, conn_id;
 
 	if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_IP)) {
-		ip.s_addr = *((u_int32_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_IP));
+		ip.s_addr = *((uint32_t *) TLVP_VAL(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 = *((u_int16_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_PORT));
+		port = *((uint16_t *) TLVP_VAL(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 = *((u_int16_t *) TLVP_VAL(tv, RSL_IE_IPAC_CONN_ID));
+		conn_id = *((uint16_t *) TLVP_VAL(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;
@@ -1668,13 +1603,13 @@
 	}
 
 	if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_IP)) {
-		ip.s_addr = *((u_int32_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_IP));
+		ip.s_addr = *((uint32_t *) TLVP_VAL(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 = *((u_int16_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_PORT));
+		port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_PORT));
 		port = ntohs(port);
 		DEBUGPC(DRSL, "REMOTE_PORT=%u ", port);
 		lchan->abis_ip.connect_port = port;
@@ -1689,7 +1624,7 @@
 	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 = lchan2chan_nr(lchan);
+	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);
@@ -1706,18 +1641,18 @@
 	return abis_rsl_sendmsg(msg);
 }
 
-int rsl_ipacc_mdcx(struct gsm_lchan *lchan, u_int32_t ip, u_int16_t port,
-		   u_int8_t rtp_payload2)
+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;
-	u_int32_t *att_ip;
+	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 = lchan2chan_nr(lchan);
+	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;
@@ -1736,7 +1671,7 @@
 
 	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 = (u_int32_t *) msgb_put(msg, sizeof(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);
@@ -1767,7 +1702,7 @@
 {
 	struct msgb *msg = rsl_msgb_alloc();
 	struct abis_rsl_dchan_hdr *dh;
-	u_int8_t msg_type;
+	uint8_t msg_type;
 
 	if (act)
 		msg_type = RSL_MT_IPAC_PDCH_ACT;
@@ -1777,7 +1712,7 @@
 	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 = ts2chan_nr(ts, 0);
+	dh->chan_nr = gsm_ts2chan_nr(ts, 0);
 
 	DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_ts_name(ts),
 		act ? "" : "DE");
@@ -1807,7 +1742,7 @@
 
 	ipac_parse_rtp(lchan, &tv);
 
-	dispatch_signal(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
+	osmo_signal_dispatch(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
 
 	return 0;
 }
@@ -1824,7 +1759,7 @@
 
 	rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
 	ipac_parse_rtp(lchan, &tv);
-	dispatch_signal(SS_ABISIP, S_ABISIP_MDCX_ACK, msg->lchan);
+	osmo_signal_dispatch(SS_ABISIP, S_ABISIP_MDCX_ACK, msg->lchan);
 
 	return 0;
 }
@@ -1840,7 +1775,7 @@
 		print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
 				TLVP_LEN(&tv, RSL_IE_CAUSE));
 
-	dispatch_signal(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
+	osmo_signal_dispatch(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
 
 	return 0;
 }
@@ -1936,18 +1871,6 @@
 	return rc;
 }
 
-/* From Table 10.5.33 of GSM 04.08 */
-int rsl_number_of_paging_subchannels(struct gsm_bts *bts)
-{
-	if (bts->si_common.chan_desc.ccch_conf == RSL_BCCH_CCCH_CONF_1_C) {
-		return MAX(1, (3 - bts->si_common.chan_desc.bs_ag_blks_res))
-			* (bts->si_common.chan_desc.bs_pa_mfrms + 2);
-	} else {
-		return (9 - bts->si_common.chan_desc.bs_ag_blks_res)
-			* (bts->si_common.chan_desc.bs_pa_mfrms + 2);
-	}
-}
-
 int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
 		       uint8_t cb_command, const uint8_t *data, int len)
 {
diff --git a/src/libbsc/bsc_api.c b/src/libbsc/bsc_api.c
index 0f09aec..70d6413 100644
--- a/src/libbsc/bsc_api.c
+++ b/src/libbsc/bsc_api.c
@@ -32,9 +32,9 @@
 #include <openbsc/debug.h>
 #include <openbsc/gsm_04_08.h>
 
-#include <osmocore/protocol/gsm_08_08.h>
+#include <osmocom/gsm/protocol/gsm_08_08.h>
 
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 
 #define GSM0808_T10_VALUE    6, 0
 
@@ -47,9 +47,9 @@
 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 u_int8_t lchan_to_chosen_channel(struct gsm_lchan *lchan)
+static uint8_t lchan_to_chosen_channel(struct gsm_lchan *lchan)
 {
-	u_int8_t channel_mode = 0, channel = 0;
+	uint8_t channel_mode = 0, channel = 0;
 
 	switch (lchan->tch_mode) {
 	case GSM48_CMODE_SPEECH_V1:
@@ -95,7 +95,7 @@
 	return channel_mode << 4 | channel;
 }
 
-static u_int8_t chan_mode_to_speech(struct gsm_lchan *lchan)
+static uint8_t chan_mode_to_speech(struct gsm_lchan *lchan)
 {
 	int mode = 0;
 
@@ -325,7 +325,7 @@
 	/* we will now start the timer to complete the assignment */
 	conn->T10.cb = assignment_t10_timeout;
 	conn->T10.data = conn;
-	bsc_schedule_timer(&conn->T10, GSM0808_T10_VALUE);
+	osmo_timer_schedule(&conn->T10, GSM0808_T10_VALUE);
 	return 0;
 
 error:
@@ -358,7 +358,7 @@
 	}
 
 	/* swap channels */
-	bsc_del_timer(&conn->T10);
+	osmo_timer_del(&conn->T10);
 
 	lchan_release(conn->lchan, 0, 1);
 	conn->lchan = conn->secondary_lchan;
@@ -387,7 +387,7 @@
 	}
 
 	/* stop the timer and release it */
-	bsc_del_timer(&conn->T10);
+	osmo_timer_del(&conn->T10);
 	lchan_release(conn->secondary_lchan, 0, 1);
 	conn->secondary_lchan = NULL;
 
@@ -435,7 +435,7 @@
 			handle_ass_fail(conn, msg);
 			break;
 		case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
-			bsc_del_timer(&conn->T10);
+			osmo_timer_del(&conn->T10);
 			rc = gsm48_rx_rr_modif_ack(msg);
 			if (rc < 0 && api->assign_fail) {
 				api->assign_fail(conn,
@@ -536,7 +536,7 @@
 	conn->ho_lchan = NULL;
 	conn->bts = NULL;
 
-	bsc_del_timer(&conn->T10);
+	osmo_timer_del(&conn->T10);
 
 	return 0;
 }
@@ -621,7 +621,7 @@
 	int destruct = 1;
 
 	if (conn->secondary_lchan == lchan) {
-		bsc_del_timer(&conn->T10);
+		osmo_timer_del(&conn->T10);
 		conn->secondary_lchan = NULL;
 
 		bsc->assign_fail(conn,
@@ -671,5 +671,5 @@
 
 static __attribute__((constructor)) void on_dso_load_bsc(void)
 {
-	register_signal_handler(SS_LCHAN, bsc_handle_lchan_signal, NULL);
+	osmo_signal_register_handler(SS_LCHAN, bsc_handle_lchan_signal, NULL);
 }
diff --git a/src/libbsc/bsc_init.c b/src/libbsc/bsc_init.c
index 0072bb6..1be8cb7 100644
--- a/src/libbsc/bsc_init.c
+++ b/src/libbsc/bsc_init.c
@@ -20,7 +20,7 @@
  */
 
 #include <openbsc/gsm_data.h>
-#include <osmocore/gsm_utils.h>
+#include <osmocom/gsm/gsm_utils.h>
 #include <openbsc/gsm_04_08.h>
 #include <openbsc/abis_rsl.h>
 #include <openbsc/abis_nm.h>
@@ -31,13 +31,12 @@
 #include <openbsc/paging.h>
 #include <openbsc/signal.h>
 #include <openbsc/chan_alloc.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/ipaccess.h>
 
 /* global pointer to the gsm network data structure */
 extern struct gsm_network *bsc_gsmnet;
-
-static void patch_nm_tables(struct gsm_bts *bts);
+extern int hsl_setup(struct gsm_network *gsmnet);
 
 /* Callback function for NACK on the OML NM */
 static int oml_msg_nack(struct nm_nack_signal_data *nack)
@@ -83,7 +82,7 @@
 
 	llist_for_each_entry(bts, &net->bts_list, list) {
 		LOGP(DNM, LOGL_NOTICE, "shutting down OML for BTS %u\n", bts->nr);
-		dispatch_signal(SS_GLOBAL, S_GLOBAL_BTS_CLOSE_OM, bts);
+		osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_BTS_CLOSE_OM, bts);
 	}
 
 	return 0;
@@ -102,8 +101,8 @@
 		si_len = rc;
 	}
 
-	DEBUGP(DRR, "SI%s: %s\n", gsm_sitype_name(i),
-		hexdump(GSM_BTS_SI(bts, i), GSM_MACBLOCK_LEN));
+	DEBUGP(DRR, "SI%s: %s\n", get_value_string(osmo_sitype_strs, i),
+		osmo_hexdump(GSM_BTS_SI(bts, i), GSM_MACBLOCK_LEN));
 
 	switch (i) {
 	case SYSINFO_TYPE_5:
@@ -116,22 +115,22 @@
 			/* This assumes a combined BCCH and TCH on TS1...7 */
 			for (j = 0; j < 4; j++)
 				rsl_sacch_info_modify(&trx->ts[0].lchan[j],
-						      gsm_sitype2rsl(i),
+						      osmo_sitype2rsl(i),
 						      GSM_BTS_SI(bts, i), si_len);
 			for (j = 1; j < 8; j++) {
 				rsl_sacch_info_modify(&trx->ts[j].lchan[0],
-						      gsm_sitype2rsl(i),
+						      osmo_sitype2rsl(i),
 						      GSM_BTS_SI(bts, i), si_len);
 				rsl_sacch_info_modify(&trx->ts[j].lchan[1],
-						      gsm_sitype2rsl(i),
+						      osmo_sitype2rsl(i),
 						      GSM_BTS_SI(bts, i), si_len);
 			}
 		} else
-			rc = rsl_sacch_filling(trx, gsm_sitype2rsl(i),
+			rc = rsl_sacch_filling(trx, osmo_sitype2rsl(i),
 					       GSM_BTS_SI(bts, i), rc);
 		break;
 	default:
-		rc = rsl_bcch_info(trx, gsm_sitype2rsl(i),
+		rc = rsl_bcch_info(trx, osmo_sitype2rsl(i),
 				   GSM_BTS_SI(bts, i), rc);
 		break;
 	}
@@ -276,9 +275,9 @@
 		LOGP(DMI, LOGL_ERROR, "Lost some E1 TEI link: %d %p\n", isd->link_type, trx);
 
 		if (isd->link_type == E1INP_SIGN_OML)
-			counter_inc(trx->bts->network->stats.bts.oml_fail);
+			osmo_counter_inc(trx->bts->network->stats.bts.oml_fail);
 		else if (isd->link_type == E1INP_SIGN_RSL)
-			counter_inc(trx->bts->network->stats.bts.rsl_fail);
+			osmo_counter_inc(trx->bts->network->stats.bts.rsl_fail);
 
 		/*
 		 * free all allocated channels. change the nm_state so the
@@ -293,15 +292,9 @@
 					lchan_free(&ts->lchan[lchan_no]);
 				lchan_reset(&ts->lchan[lchan_no]);
 			}
-
-			ts->nm_state.operational = 0;
-			ts->nm_state.availability = 0;
 		}
 
-		trx->nm_state.operational = 0;
-		trx->nm_state.availability = 0;
-		trx->bb_transc.nm_state.operational = 0;
-		trx->bb_transc.nm_state.availability = 0;
+		gsm_bts_mo_reset(trx->bts);
 
 		abis_nm_clear_queue(trx->bts);
 		break;
@@ -316,6 +309,14 @@
 {
 	int i, n;
 
+	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) {
@@ -405,8 +406,6 @@
 
 	bts->si_common.ncc_permitted = 0xff;
 
-	paging_init(bts);
-
 	return 0;
 }
 
@@ -437,12 +436,15 @@
 	if (rc < 0)
 		return rc;
 
-	register_signal_handler(SS_NM, nm_sig_cb, NULL);
-	register_signal_handler(SS_INPUT, inp_sig_cb, NULL);
+	osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL);
+	osmo_signal_register_handler(SS_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;
+		}
 		switch (bts->type) {
 		case GSM_BTS_TYPE_NANOBTS:
 		case GSM_BTS_TYPE_HSL_FEMTO:
@@ -451,16 +453,10 @@
 			rc = e1_reconfig_bts(bts);
 			break;
 		}
-
 		if (rc < 0) {
-			fprintf(stderr, "Error in E1 input driver setup\n");
-			exit (1);
+			LOGP(DNM, LOGL_FATAL, "Error enabling E1 input driver\n");
+			return rc;
 		}
 	}
-
-	/* initialize nanoBTS support omce */
-	rc = ipaccess_setup(bsc_gsmnet);
-	rc = hsl_setup(bsc_gsmnet);
-
 	return 0;
 }
diff --git a/src/libbsc/bsc_msc.c b/src/libbsc/bsc_msc.c
index 508697a..e9ffce3 100644
--- a/src/libbsc/bsc_msc.c
+++ b/src/libbsc/bsc_msc.c
@@ -23,8 +23,8 @@
 #include <openbsc/debug.h>
 #include <openbsc/ipaccess.h>
 
-#include <osmocore/write_queue.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/write_queue.h>
+#include <osmocom/core/talloc.h>
 
 #include <arpa/inet.h>
 #include <sys/socket.h>
@@ -36,13 +36,13 @@
 
 static void connection_loss(struct bsc_msc_connection *con)
 {
-	struct bsc_fd *fd;
+	struct osmo_fd *fd;
 
 	fd = &con->write_queue.bfd;
 
 	close(fd->fd);
 	fd->fd = -1;
-	fd->cb = write_queue_bfd_cb;
+	fd->cb = osmo_wqueue_bfd_cb;
 	fd->when = 0;
 
 	con->is_connected = 0;
@@ -59,12 +59,12 @@
 }
 
 /* called in the case of a non blocking connect */
-static int msc_connection_connect(struct bsc_fd *fd, unsigned int what)
+static int msc_connection_connect(struct osmo_fd *fd, unsigned int what)
 {
 	int rc;
 	int val;
 	struct bsc_msc_connection *con;
-	struct write_queue *queue;
+	struct osmo_wqueue *queue;
 
 	socklen_t len = sizeof(val);
 
@@ -73,11 +73,11 @@
 		return -1;
 	}
 
-	queue = container_of(fd, struct write_queue, bfd);
+	queue = container_of(fd, struct osmo_wqueue, bfd);
 	con = container_of(queue, struct bsc_msc_connection, write_queue);
 
 	/* From here on we will either be connected or reconnect */
-	bsc_del_timer(&con->timeout_timer);
+	osmo_timer_del(&con->timeout_timer);
 
 	/* check the socket state */
 	rc = getsockopt(fd->fd, SOL_SOCKET, SO_ERROR, &val, &len);
@@ -92,7 +92,7 @@
 
 
 	/* go to full operation */
-	fd->cb = write_queue_bfd_cb;
+	fd->cb = osmo_wqueue_bfd_cb;
 	fd->when = BSC_FD_READ | BSC_FD_EXCEPT;
 
 	con->is_connected = 1;
@@ -102,11 +102,11 @@
 	return 0;
 
 error:
-	bsc_unregister_fd(fd);
+	osmo_fd_unregister(fd);
 	connection_loss(con);
 	return -1;
 }
-static void setnonblocking(struct bsc_fd *fd)
+static void setnonblocking(struct osmo_fd *fd)
 {
 	int flags;
 
@@ -130,11 +130,24 @@
 
 int bsc_msc_connect(struct bsc_msc_connection *con)
 {
-	struct bsc_fd *fd;
+	struct bsc_msc_dest *dest;
+	struct osmo_fd *fd;
 	struct sockaddr_in sin;
 	int on = 1, ret;
 
-	LOGP(DMSC, LOGL_NOTICE, "Attempting to connect MSC at %s:%d\n", con->ip, con->port);
+	if (llist_empty(con->dests)) {
+		LOGP(DMSC, LOGL_ERROR, "No MSC connections configured.\n");
+		connection_loss(con);
+		return -1;
+	}
+
+	/* 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 at %s:%d\n",
+	     dest->ip, dest->port);
 
 	con->is_connected = 0;
 
@@ -152,15 +165,15 @@
 
 	/* set the socket priority */
 	ret = setsockopt(fd->fd, IPPROTO_IP, IP_TOS,
-			 &con->prio, sizeof(con->prio));
+			 &dest->dscp, sizeof(dest->dscp));
 	if (ret != 0)
-		LOGP(DMSC, LOGL_ERROR, "Failed to set prio to %d. %s\n",
-		     con->prio, strerror(errno));
+		LOGP(DMSC, LOGL_ERROR, "Failed to set DSCP to %d. %s\n",
+		     dest->dscp, strerror(errno));
 
 	memset(&sin, 0, sizeof(sin));
 	sin.sin_family = AF_INET;
-	sin.sin_port = htons(con->port);
-	inet_aton(con->ip, &sin.sin_addr);
+	sin.sin_port = htons(dest->port);
+	inet_aton(dest->ip, &sin.sin_addr);
 
 	setsockopt(fd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
 	ret = connect(fd->fd, (struct sockaddr *) &sin, sizeof(sin));
@@ -171,20 +184,20 @@
 		fd->cb = msc_connection_connect;
 		con->timeout_timer.cb = msc_con_timeout;
 		con->timeout_timer.data = con;
-		bsc_schedule_timer(&con->timeout_timer, 20, 0);
+		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 = write_queue_bfd_cb;
+		fd->cb = osmo_wqueue_bfd_cb;
 		con->is_connected = 1;
 		if (con->connected)
 			con->connected(con);
 	}
 
-	ret = bsc_register_fd(fd);
+	ret = osmo_fd_register(fd);
 	if (ret < 0) {
 		perror("Registering the fd failed");
 		close(fd->fd);
@@ -194,7 +207,7 @@
 	return ret;
 }
 
-struct bsc_msc_connection *bsc_msc_create(const char *ip, int port, int prio)
+struct bsc_msc_connection *bsc_msc_create(void *ctx, struct llist_head *dests)
 {
 	struct bsc_msc_connection *con;
 
@@ -204,20 +217,19 @@
 		return NULL;
 	}
 
-	con->ip = ip;
-	con->port = port;
-	con->prio = prio;
-	write_queue_init(&con->write_queue, 100);
+	con->dests = dests;
+	con->write_queue.bfd.fd = -1;
+	osmo_wqueue_init(&con->write_queue, 100);
 	return con;
 }
 
 void bsc_msc_lost(struct bsc_msc_connection *con)
 {
-	write_queue_clear(&con->write_queue);
-	bsc_del_timer(&con->timeout_timer);
+	osmo_wqueue_clear(&con->write_queue);
+	osmo_timer_del(&con->timeout_timer);
 
 	if (con->write_queue.bfd.fd >= 0)
-		bsc_unregister_fd(&con->write_queue.bfd);
+		osmo_fd_unregister(&con->write_queue.bfd);
 	connection_loss(con);
 }
 
@@ -234,7 +246,7 @@
 	LOGP(DMSC, LOGL_NOTICE, "Attempting to reconnect to the MSC.\n");
 	con->reconnect_timer.cb = reconnect_msc;
 	con->reconnect_timer.data = con;
-	bsc_schedule_timer(&con->reconnect_timer, 5, 0);
+	osmo_timer_schedule(&con->reconnect_timer, 5, 0);
 }
 
 struct msgb *bsc_msc_id_get_resp(const char *token)
@@ -254,6 +266,6 @@
 
 	msg->l2h = msgb_v_put(msg, IPAC_MSGT_ID_RESP);
 	msgb_l16tv_put(msg, strlen(token) + 1,
-			IPAC_IDTAG_UNITNAME, (u_int8_t *) token);
+			IPAC_IDTAG_UNITNAME, (uint8_t *) token);
 	return msg;
 }
diff --git a/src/libbsc/bsc_rll.c b/src/libbsc/bsc_rll.c
index 722f3fa..d12aeee 100644
--- a/src/libbsc/bsc_rll.c
+++ b/src/libbsc/bsc_rll.c
@@ -23,9 +23,9 @@
 #include <errno.h>
 
 #include <openbsc/debug.h>
-#include <osmocore/talloc.h>
-#include <osmocore/timer.h>
-#include <osmocore/linuxlist.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>
@@ -34,12 +34,12 @@
 
 struct bsc_rll_req {
 	struct llist_head list;
-	struct timer_list timer;
+	struct osmo_timer_list timer;
 
 	struct gsm_lchan *lchan;
-	u_int8_t link_id;
+	uint8_t link_id;
 
-	void (*cb)(struct gsm_lchan *lchan, u_int8_t link_id,
+	void (*cb)(struct gsm_lchan *lchan, uint8_t link_id,
 		   void *data, enum bsc_rllr_ind);
 	void *data;
 };
@@ -64,13 +64,13 @@
 }
 
 /* establish a RLL connection with given SAPI / priority */
-int rll_establish(struct gsm_lchan *lchan, u_int8_t sapi,
-		  void (*cb)(struct gsm_lchan *, u_int8_t, void *,
+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);
-	u_int8_t link_id;
+	uint8_t link_id;
 	if (!rllr)
 		return -ENOMEM;
 
@@ -92,7 +92,7 @@
 	rllr->timer.cb = &timer_cb;
 	rllr->timer.data = rllr;
 
-	bsc_schedule_timer(&rllr->timer, 10, 0);
+	osmo_timer_schedule(&rllr->timer, 10, 0);
 
 	/* send the RSL RLL ESTablish REQuest */
 	return rsl_establish_request(rllr->lchan, rllr->link_id);
@@ -100,14 +100,14 @@
 
 /* Called from RSL code in case we have received an indication regarding
  * any RLL link */
-void rll_indication(struct gsm_lchan *lchan, u_int8_t link_id, u_int8_t type)
+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)) {
-			bsc_del_timer(&rllr->timer);
+			osmo_timer_del(&rllr->timer);
 			complete_rllr(rllr, type);
 			return;
 		}
@@ -127,7 +127,7 @@
 
 	llist_for_each_entry_safe(rllr, rllr2, &bsc_rll_reqs, list) {
 		if (rllr->lchan == challoc->lchan) {
-			bsc_del_timer(&rllr->timer);
+			osmo_timer_del(&rllr->timer);
 			complete_rllr(rllr, BSC_RLLR_IND_ERR_IND);
 		}
 	}
@@ -137,5 +137,5 @@
 
 static __attribute__((constructor)) void on_dso_load_rll(void)
 {
-	register_signal_handler(SS_CHALLOC, rll_lchan_signal, NULL);
+	osmo_signal_register_handler(SS_CHALLOC, rll_lchan_signal, NULL);
 }
diff --git a/src/libbsc/bsc_vty.c b/src/libbsc/bsc_vty.c
index c0909db..971cdf7 100644
--- a/src/libbsc/bsc_vty.c
+++ b/src/libbsc/bsc_vty.c
@@ -19,7 +19,6 @@
 
 #include <stdlib.h>
 #include <unistd.h>
-#include <sys/types.h>
 
 #include <osmocom/vty/command.h>
 #include <osmocom/vty/buffer.h>
@@ -29,17 +28,18 @@
 
 #include <arpa/inet.h>
 
-#include <osmocore/linuxlist.h>
+#include <osmocom/core/linuxlist.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/e1_input.h>
 #include <openbsc/abis_nm.h>
 #include <openbsc/abis_om2000.h>
-#include <osmocore/utils.h>
-#include <osmocore/gsm_utils.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 <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/vty.h>
 #include <openbsc/gprs_ns.h>
 #include <openbsc/system_information.h>
@@ -133,8 +133,8 @@
 static void net_dump_nmstate(struct vty *vty, struct gsm_nm_state *nms)
 {
 	vty_out(vty,"Oper '%s', Admin %u, Avail '%s'%s",
-		nm_opstate_name(nms->operational), nms->administrative,
-		nm_avail_name(nms->availability), VTY_NEWLINE);
+		abis_nm_opstate_name(nms->operational), nms->administrative,
+		abis_nm_avail_name(nms->availability), VTY_NEWLINE);
 }
 
 static void dump_pchan_load_vty(struct vty *vty, char *prefix,
@@ -189,7 +189,7 @@
 	dump_pchan_load_vty(vty, "    ", &pl);
 
 	/* show rf */
-	if (net->msc_data)
+	if (net->msc_data && net->msc_data->rf_ctl)
 		vty_out(vty, "  Last RF Command: %s%s",
 			net->msc_data->rf_ctl->last_state_command,
 			VTY_NEWLINE);
@@ -256,10 +256,11 @@
 	else if (bts->type == GSM_BTS_TYPE_HSL_FEMTO)
 		vty_out(vty, "  Serial Number: %lu%s", bts->hsl.serno, VTY_NEWLINE);
 	vty_out(vty, "  NM State: ");
-	net_dump_nmstate(vty, &bts->nm_state);
+	net_dump_nmstate(vty, &bts->mo.nm_state);
 	vty_out(vty, "  Site Mgr NM State: ");
-	net_dump_nmstate(vty, &bts->site_mgr.nm_state);
-	vty_out(vty, "  Paging: FIXME pending requests, %u free slots%s",
+	net_dump_nmstate(vty, &bts->site_mgr.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",
@@ -332,6 +333,8 @@
 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 && ts->tsc != ts->trx->bts->tsc)
+		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);
@@ -365,7 +368,7 @@
 		vty_out(vty, "   description %s%s", trx->description,
 			VTY_NEWLINE);
 	vty_out(vty, "   rf_locked %u%s",
-		trx->nm_state.administrative == NM_STATE_LOCKED ? 1 : 0,
+		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);
@@ -495,7 +498,7 @@
 				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),
-				hexdump_nospc(bts->si_buf[i], sizeof(bts->si_buf[i])),
+				osmo_osmo_hexdump_nospc(bts->si_buf[i], sizeof(bts->si_buf[i])),
 				VTY_NEWLINE);
 		}
 	}
@@ -616,9 +619,9 @@
 		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->nm_state);
+	net_dump_nmstate(vty, &trx->mo.nm_state);
 	vty_out(vty, "  Baseband Transceiver NM State: ");
-	net_dump_nmstate(vty, &trx->bb_transc.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);
@@ -684,15 +687,15 @@
 
 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",
+	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_pchan_name(ts->pchan), ts->tsc);
 	if (ts->pchan == GSM_PCHAN_TCH_F_PDCH)
 		vty_out(vty, " (%s mode)",
 			ts->flags & TS_F_PDCH_MODE ? "PDCH" : "TCH/F");
 	vty_out(vty, "%s", VTY_NEWLINE);
 	vty_out(vty, "  NM State: ");
-	net_dump_nmstate(vty, &ts->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,
@@ -1439,8 +1442,8 @@
 		return CMD_WARNING;
 	} else if (bts_nr == gsmnet->num_bts) {
 		/* allocate a new one */
-		bts = gsm_bts_alloc(gsmnet, GSM_BTS_TYPE_UNKNOWN,
-				    HARDCODED_TSC, HARDCODED_BSIC);
+		bts = gsm_bts_alloc_register(gsmnet, GSM_BTS_TYPE_UNKNOWN,
+					     HARDCODED_TSC, HARDCODED_BSIC);
 	} else
 		bts = gsm_bts_num(gsmnet, bts_nr);
 
@@ -2171,7 +2174,7 @@
 	memset(bts->si_buf[type], 0x2b, sizeof(bts->si_buf[type]));
 
 	/* Parse the user-specified SI in hex format, [partially] overwriting padding */
-	rc = hexparse(argv[1], bts->si_buf[type], sizeof(bts->si_buf[0]));
+	rc = osmo_hexparse(argv[1], bts->si_buf[type], sizeof(bts->si_buf[0]));
 	if (rc < 0 || rc > sizeof(bts->si_buf[0])) {
 		vty_out(vty, "Error parsing HEXSTRING%s", VTY_NEWLINE);
 		return CMD_WARNING;
@@ -2427,6 +2430,18 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_ts_tsc,
+      cfg_ts_tsc_cmd,
+      "training_sequence_code <0-7>",
+      "Training Sequence Code")
+{
+	struct gsm_bts_trx_ts *ts = vty->index;
+
+	ts->tsc = atoi(argv[0]);
+
+	return CMD_SUCCESS;
+}
+
 #define HOPPING_STR "Configure frequency hopping\n"
 
 DEFUN(cfg_ts_hopping,
@@ -2518,18 +2533,18 @@
 void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *net)
 {
 	vty_out(vty, "Channel Requests        : %lu total, %lu no channel%s",
-		counter_get(net->stats.chreq.total),
-		counter_get(net->stats.chreq.no_channel), VTY_NEWLINE);
+		osmo_counter_get(net->stats.chreq.total),
+		osmo_counter_get(net->stats.chreq.no_channel), VTY_NEWLINE);
 	vty_out(vty, "Channel Failures        : %lu rf_failures, %lu rll failures%s",
-		counter_get(net->stats.chan.rf_fail),
-		counter_get(net->stats.chan.rll_err), VTY_NEWLINE);
+		osmo_counter_get(net->stats.chan.rf_fail),
+		osmo_counter_get(net->stats.chan.rll_err), VTY_NEWLINE);
 	vty_out(vty, "Paging                  : %lu attempted, %lu complete, %lu expired%s",
-		counter_get(net->stats.paging.attempted),
-		counter_get(net->stats.paging.completed),
-		counter_get(net->stats.paging.expired), VTY_NEWLINE);
+		osmo_counter_get(net->stats.paging.attempted),
+		osmo_counter_get(net->stats.paging.completed),
+		osmo_counter_get(net->stats.paging.expired), VTY_NEWLINE);
 	vty_out(vty, "BTS failures            : %lu OML, %lu RSL%s",
-		counter_get(net->stats.bts.oml_fail),
-		counter_get(net->stats.bts.rsl_fail), VTY_NEWLINE);
+		osmo_counter_get(net->stats.bts.oml_fail),
+		osmo_counter_get(net->stats.bts.rsl_fail), VTY_NEWLINE);
 }
 
 DEFUN(logging_fltr_imsi,
@@ -2650,7 +2665,7 @@
 extern int bsc_vty_init_extra(void);
 extern const char *openbsc_copyright;
 
-int bsc_vty_init(void)
+int bsc_vty_init(const struct log_info *cat)
 {
 	install_element_ve(&show_net_cmd);
 	install_element_ve(&show_bts_cmd);
@@ -2666,7 +2681,7 @@
 
 	install_element_ve(&show_paging_cmd);
 
-	logging_vty_add_cmds();
+	logging_vty_add_cmds(cat);
 	install_element(CFG_LOG_NODE, &logging_fltr_imsi_cmd);
 
 	install_element(CONFIG_NODE, &cfg_net_cmd);
@@ -2779,6 +2794,7 @@
 	install_element(TS_NODE, &ournode_exit_cmd);
 	install_element(TS_NODE, &ournode_end_cmd);
 	install_element(TS_NODE, &cfg_ts_pchan_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);
diff --git a/src/libbsc/bts_ericsson_rbs2000.c b/src/libbsc/bts_ericsson_rbs2000.c
index 27d5ce6..9c98a9f 100644
--- a/src/libbsc/bts_ericsson_rbs2000.c
+++ b/src/libbsc/bts_ericsson_rbs2000.c
@@ -19,13 +19,13 @@
  *
  */
 
-#include <sys/types.h>
 
-#include <osmocore/tlv.h>
+#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 <openbsc/e1_input.h>
 #include <openbsc/signal.h>
 
@@ -40,9 +40,12 @@
 
 static void bootstrap_om_trx(struct gsm_bts_trx *trx)
 {
+	struct abis_om2k_mo trx_mo = { OM2K_MO_CLS_TRXC, 0, 255, trx->nr };
+
 	LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for TRX %u/%u\n",
 	     trx->bts->nr, trx->nr);
-	/* FIXME */
+
+	abis_om2k_tx_reset_cmd(trx->bts, &trx_mo);
 }
 
 static int shutdown_om(struct gsm_bts *bts)
@@ -137,19 +140,119 @@
 	return 0;
 }
 
+static void nm_statechg_evt(unsigned int signal,
+			    struct nm_statechg_signal_data *nsd)
+{
+	struct abis_om2k_mo mo;
+
+	if (nsd->bts->type != GSM_BTS_TYPE_RBS2000)
+		return;
+
+	switch (nsd->om2k_mo->class) {
+	case OM2K_MO_CLS_CF:
+		if (nsd->new_state->operational != NM_OPSTATE_ENABLED ||
+		    nsd->new_state->availability != OM2K_MO_S_STARTED)
+			break;
+		/* CF has started, we can trigger IS and TF start */
+		abis_om2k_tx_connect_cmd(nsd->bts, &om2k_mo_is);
+		abis_om2k_tx_connect_cmd(nsd->bts, &om2k_mo_tf);
+		break;
+	case OM2K_MO_CLS_IS:
+		if (nsd->new_state->availability == OM2K_MO_S_ENABLED) {
+			/* IS is enabled, we can proceed with TRXC/RX/TX/TS */
+			break;
+		}
+		if (nsd->new_state->operational != NM_OPSTATE_ENABLED)
+			break;
+		/* IS has started, we can configure + enable it */
+		abis_om2k_tx_is_conf_req(nsd->bts);
+		break;
+	case OM2K_MO_CLS_TF:
+		if (nsd->new_state->operational != NM_OPSTATE_ENABLED ||
+		    nsd->new_state->availability == OM2K_MO_S_DISABLED)
+			break;
+		if (nsd->new_state->availability == OM2K_MO_S_STARTED) {
+			/* TF has started, configure + enable it */
+			abis_om2k_tx_is_conf_req(nsd->bts);
+		}
+		break;
+	case OM2K_MO_CLS_TRXC:
+		if (nsd->new_state->availability != OM2K_MO_S_STARTED)
+			break;
+		/* TRXC is started, connect the TX and RX objects */
+		memcpy(&mo, nsd->om2k_mo, sizeof(mo));
+		mo.class = OM2K_MO_CLS_TX;
+		abis_om2k_tx_connect_cmd(nsd->bts, &mo);
+		mo.class = OM2K_MO_CLS_RX;
+		abis_om2k_tx_connect_cmd(nsd->bts, &mo);
+		break;
+	case OM2K_MO_CLS_RX:
+		if (nsd->new_state->operational != NM_OPSTATE_ENABLED ||
+		    nsd->new_state->availability != OM2K_MO_S_STARTED)
+			break;
+		/* RX is started, configure + enable it */
+		abis_om2k_tx_rx_conf_req(nsd->obj);
+		break;
+	case OM2K_MO_CLS_TX:
+		if (nsd->new_state->operational != NM_OPSTATE_ENABLED ||
+		    nsd->new_state->availability != OM2K_MO_S_STARTED)
+			break;
+		/* RX is started, configure + enable it */
+		abis_om2k_tx_tx_conf_req(nsd->obj);
+		break;
+	}
+}
+
+static void nm_conf_res(struct nm_om2k_signal_data *nsd)
+{
+	switch (nsd->om2k_mo->class) {
+	case OM2K_MO_CLS_IS:
+	case OM2K_MO_CLS_TF:
+	case OM2K_MO_CLS_RX:
+	case OM2K_MO_CLS_TX:
+		/* If configuration was a success, enable it */
+		abis_om2k_tx_enable_req(nsd->bts, nsd->om2k_mo);
+		break;
+	}
+}
+
+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;
+	case S_NM_OM2K_CONF_RES:
+		nm_conf_res(signal_data);
+		break;
+	default:
+		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 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,
 };
 
-int bts_model_rbs2k_init(void)
+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);
@@ -157,8 +260,14 @@
 	gsm_btsmodel_set_feature(&model_rbs2k, BTS_FEAT_HOPPING);
 	gsm_btsmodel_set_feature(&model_rbs2k, BTS_FEAT_HSCSD);
 
-	register_signal_handler(SS_INPUT, inp_sig_cb, NULL);
-	register_signal_handler(SS_GLOBAL, gbl_sig_cb, NULL);
+	osmo_signal_register_handler(SS_INPUT, inp_sig_cb, NULL);
+	osmo_signal_register_handler(SS_GLOBAL, gbl_sig_cb, NULL);
+	osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL);
 
+	return 0;
+}
+
+int bts_model_rbs2k_init(void)
+{
 	return gsm_bts_model_register(&model_rbs2k);
 }
diff --git a/src/libbsc/bts_hsl_femtocell.c b/src/libbsc/bts_hsl_femtocell.c
index e01634c..f943693 100644
--- a/src/libbsc/bts_hsl_femtocell.c
+++ b/src/libbsc/bts_hsl_femtocell.c
@@ -20,19 +20,21 @@
  *
  */
 
-#include <sys/types.h>
 
 #include <arpa/inet.h>
 
-#include <osmocore/tlv.h>
+#include <osmocom/gsm/tlv.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/abis_nm.h>
 #include <openbsc/abis_rsl.h>
 #include <openbsc/signal.h>
 #include <openbsc/e1_input.h>
 
+static int bts_model_hslfemto_start(struct gsm_network *net);
+
 static struct gsm_bts_model model_hslfemto = {
 	.type = GSM_BTS_TYPE_HSL_FEMTO,
+	.start = bts_model_hslfemto_start,
 	.nm_att_tlvdef = {
 		.def = {
 			/* no HSL specific OML attributes that we know of */
@@ -140,7 +142,8 @@
 	case S_INP_TEI_UP:
 		switch (isd->link_type) {
 		case E1INP_SIGN_OML:
-			hslfemto_bootstrap_om(isd->trx->bts);
+			if (isd->trx->bts->type == GSM_BTS_TYPE_HSL_FEMTO)
+				hslfemto_bootstrap_om(isd->trx->bts);
 			break;
 		}
 	}
@@ -148,7 +151,7 @@
 	return 0;
 }
 
-int bts_model_hslfemto_init(void)
+static int bts_model_hslfemto_start(struct gsm_network *net)
 {
 	model_hslfemto.features.data = &model_hslfemto._features_data[0];
 	model_hslfemto.features.data_len = sizeof(model_hslfemto._features_data);
@@ -156,7 +159,13 @@
 	gsm_btsmodel_set_feature(&model_hslfemto, BTS_FEAT_GPRS);
 	gsm_btsmodel_set_feature(&model_hslfemto, BTS_FEAT_EGPRS);
 
-	register_signal_handler(SS_INPUT, inp_sig_cb, NULL);
+	osmo_signal_register_handler(SS_INPUT, inp_sig_cb, NULL);
 
+	/* Call A-bis input driver, start socket for OML and RSL. */
+	return hsl_setup(net);
+}
+
+int bts_model_hslfemto_init(void)
+{
 	return gsm_bts_model_register(&model_hslfemto);
 }
diff --git a/src/libbsc/bts_init.c b/src/libbsc/bts_init.c
new file mode 100644
index 0000000..87bdde0
--- /dev/null
+++ b/src/libbsc/bts_init.c
@@ -0,0 +1,29 @@
+/* (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_hslfemto_init();
+	/* Your new BTS here. */
+	return 0;
+}
diff --git a/src/libbsc/bts_ipaccess_nanobts.c b/src/libbsc/bts_ipaccess_nanobts.c
index 25dc0c8..e756f2a 100644
--- a/src/libbsc/bts_ipaccess_nanobts.c
+++ b/src/libbsc/bts_ipaccess_nanobts.c
@@ -19,18 +19,21 @@
  *
  */
 
-#include <sys/types.h>
 #include <arpa/inet.h>
 
-#include <osmocore/tlv.h>
+#include <osmocom/gsm/tlv.h>
 
 #include <openbsc/gsm_data.h>
 #include <openbsc/signal.h>
 #include <openbsc/abis_nm.h>
+#include <openbsc/e1_input.h> /* for ipaccess_setup() */
+
+static int bts_model_nanobts_start(struct gsm_network *net);
 
 static struct gsm_bts_model model_nanobts = {
 	.type = GSM_BTS_TYPE_NANOBTS,
 	.name = "nanobts",
+	.start = bts_model_nanobts_start,
 	.oml_rcvmsg = &abis_nm_rcvmsg,
 	.nm_att_tlvdef = {
 		.def = {
@@ -182,8 +185,8 @@
  */
 static void patch_nm_tables(struct gsm_bts *bts)
 {
-	u_int8_t arfcn_low = bts->c0->arfcn & 0xff;
-	u_int8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f;
+	uint8_t arfcn_low = bts->c0->arfcn & 0xff;
+	uint8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f;
 
 	/* patch ARFCN into BTS Attributes */
 	nanobts_attr_bts[42] &= 0xf0;
@@ -196,8 +199,8 @@
 	}
 
 	if (bts->rach_ldavg_slots != -1) {
-		u_int8_t avg_high = bts->rach_ldavg_slots & 0xff;
-		u_int8_t avg_low = (bts->rach_ldavg_slots >> 8) & 0x0f;
+		uint8_t avg_high = bts->rach_ldavg_slots & 0xff;
+		uint8_t avg_low = (bts->rach_ldavg_slots >> 8) & 0x0f;
 
 		nanobts_attr_bts[35] = avg_high;
 		nanobts_attr_bts[36] = avg_low;
@@ -249,7 +252,7 @@
 /* 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)
 {
-	u_int8_t obj_class = nsd->obj_class;
+	uint8_t obj_class = nsd->obj_class;
 	void *obj = nsd->obj;
 	struct gsm_nm_state *new_state = nsd->new_state;
 
@@ -258,6 +261,9 @@
 	struct gsm_bts_trx_ts *ts;
 	struct gsm_bts_gprs_nsvc *nsvc;
 
+	if (nsd->bts->type != GSM_BTS_TYPE_NANOBTS)
+		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
@@ -396,7 +402,7 @@
 		 * This code is here to make sure that on start
 		 * a TRX remains locked.
 		 */
-		int rc_state = trx->nm_state.administrative;
+		int rc_state = trx->mo.nm_state.administrative;
 		/* Patch ARFCN into radio attribute */
 		nanobts_attr_radio[5] &= 0xf0;
 		nanobts_attr_radio[5] |= trx->arfcn >> 8;
@@ -433,7 +439,7 @@
 	return 0;
 }
 
-int bts_model_nanobts_init(void)
+static int bts_model_nanobts_start(struct gsm_network *net)
 {
 	model_nanobts.features.data = &model_nanobts._features_data[0];
 	model_nanobts.features.data_len = sizeof(model_nanobts._features_data);
@@ -441,7 +447,13 @@
 	gsm_btsmodel_set_feature(&model_nanobts, BTS_FEAT_GPRS);
 	gsm_btsmodel_set_feature(&model_nanobts, BTS_FEAT_EGPRS);
 
-	register_signal_handler(SS_NM, nm_sig_cb, NULL);
+	osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL);
 
+	/* Call A-bis input driver, start server sockets for OML and RSL. */
+	return ipaccess_setup(net);
+}
+
+int bts_model_nanobts_init(void)
+{
 	return gsm_bts_model_register(&model_nanobts);
 }
diff --git a/src/libbsc/bts_siemens_bs11.c b/src/libbsc/bts_siemens_bs11.c
index 5a5f883..df4a1dc 100644
--- a/src/libbsc/bts_siemens_bs11.c
+++ b/src/libbsc/bts_siemens_bs11.c
@@ -19,9 +19,8 @@
  *
  */
 
-#include <sys/types.h>
 
-#include <osmocore/tlv.h>
+#include <osmocom/gsm/tlv.h>
 
 #include <openbsc/debug.h>
 #include <openbsc/gsm_data.h>
@@ -29,9 +28,12 @@
 #include <openbsc/e1_input.h>
 #include <openbsc/signal.h>
 
+static int bts_model_bs11_start(struct gsm_network *net);
+
 static struct gsm_bts_model model_bs11 = {
 	.type = GSM_BTS_TYPE_BS11,
 	.name = "bs11",
+	.start = bts_model_bs11_start,
 	.oml_rcvmsg = &abis_nm_rcvmsg,
 	.nm_att_tlvdef = {
 		.def = {
@@ -346,8 +348,8 @@
  */
 static void patch_nm_tables(struct gsm_bts *bts)
 {
-	u_int8_t arfcn_low = bts->c0->arfcn & 0xff;
-	u_int8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f;
+	uint8_t arfcn_low = bts->c0->arfcn & 0xff;
+	uint8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f;
 
 	/* patch ARFCN into BTS Attributes */
 	bs11_attr_bts[69] &= 0xf0;
@@ -364,8 +366,8 @@
 		bs11_attr_bts[33] = bts->rach_b_thresh & 0xff;
 
 	if (bts->rach_ldavg_slots != -1) {
-		u_int8_t avg_high = bts->rach_ldavg_slots & 0xff;
-		u_int8_t avg_low = (bts->rach_ldavg_slots >> 8) & 0x0f;
+		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;
@@ -425,9 +427,9 @@
 			abis_nm_set_radio_attr(trx, bs11_attr_radio,
 					       sizeof(bs11_attr_radio));
 		else {
-			u_int8_t trx1_attr_radio[sizeof(bs11_attr_radio)];
-			u_int8_t arfcn_low = trx->arfcn & 0xff;
-			u_int8_t arfcn_high = (trx->arfcn >> 8) & 0x0f;
+			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));
 
@@ -576,7 +578,7 @@
 	return 0;
 }
 
-int bts_model_bs11_init(void)
+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);
@@ -584,8 +586,13 @@
 	gsm_btsmodel_set_feature(&model_bs11, BTS_FEAT_HOPPING);
 	gsm_btsmodel_set_feature(&model_bs11, BTS_FEAT_HSCSD);
 
-	register_signal_handler(SS_INPUT, inp_sig_cb, NULL);
-	register_signal_handler(SS_GLOBAL, gbl_sig_cb, NULL);
+	osmo_signal_register_handler(SS_INPUT, inp_sig_cb, NULL);
+	osmo_signal_register_handler(SS_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_unknown.c b/src/libbsc/bts_unknown.c
index f954599..f113529 100644
--- a/src/libbsc/bts_unknown.c
+++ b/src/libbsc/bts_unknown.c
@@ -19,10 +19,9 @@
  *
  */
 
-#include <sys/types.h>
 
 #include <openbsc/gsm_data.h>
-#include <osmocore/tlv.h>
+#include <osmocom/gsm/tlv.h>
 #include <openbsc/abis_nm.h>
 
 static struct gsm_bts_model model_unknown = {
diff --git a/src/libbsc/chan_alloc.c b/src/libbsc/chan_alloc.c
index 167381b..c0bdc1b 100644
--- a/src/libbsc/chan_alloc.c
+++ b/src/libbsc/chan_alloc.c
@@ -32,13 +32,13 @@
 #include <openbsc/debug.h>
 #include <openbsc/signal.h>
 
-#include <osmocore/talloc.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->nm_state))
+		if (!nm_is_running(&ts->mo.nm_state))
 			return 0;
 	}
 
@@ -49,8 +49,8 @@
 {
 	/* FIXME: How does this behave for BS-11 ? */
 	if (is_ipaccess_bts(trx->bts)) {
-		if (!nm_is_running(&trx->nm_state) ||
-		    !nm_is_running(&trx->bb_transc.nm_state))
+		if (!nm_is_running(&trx->mo.nm_state) ||
+		    !nm_is_running(&trx->bb_transc.mo.nm_state))
 			return 0;
 	}
 
@@ -143,7 +143,7 @@
 	ts->pchan = GSM_PCHAN_NONE;
 }
 
-static const u_int8_t subslots_per_pchan[] = {
+static const uint8_t subslots_per_pchan[] = {
 	[GSM_PCHAN_NONE] = 0,
 	[GSM_PCHAN_CCCH] = 0,
 	[GSM_PCHAN_CCCH_SDCCH4] = 4,
@@ -284,7 +284,7 @@
 		struct challoc_signal_data sig;
 		sig.bts = bts;
 		sig.type = type;
-		dispatch_signal(SS_CHALLOC, S_CHALLOC_ALLOC_FAIL, &sig);
+		osmo_signal_dispatch(SS_CHALLOC, S_CHALLOC_ALLOC_FAIL, &sig);
 	}
 
 	return lchan;
@@ -306,12 +306,12 @@
 		/* We might kill an active channel... */
 		sig.lchan = lchan;
 		sig.mr = NULL;
-		dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, &sig);
+		osmo_signal_dispatch(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, &sig);
 	}
 
 
 	/* stop the timer */
-	bsc_del_timer(&lchan->T3101);
+	osmo_timer_del(&lchan->T3101);
 
 	/* clear cached measuement reports */
 	lchan->meas_rep_idx = 0;
@@ -330,7 +330,7 @@
 
 	sig.lchan = lchan;
 	sig.bts = lchan->ts->trx->bts;
-	dispatch_signal(SS_CHALLOC, S_CHALLOC_FREED, &sig);
+	osmo_signal_dispatch(SS_CHALLOC, S_CHALLOC_FREED, &sig);
 
 	if (lchan->conn) {
 		LOGP(DRLL, LOGL_ERROR, "the subscriber connection should be gone.\n");
@@ -356,9 +356,9 @@
  */
 void lchan_reset(struct gsm_lchan *lchan)
 {
-	bsc_del_timer(&lchan->T3101);
-	bsc_del_timer(&lchan->T3111);
-	bsc_del_timer(&lchan->error_timer);
+	osmo_timer_del(&lchan->T3101);
+	osmo_timer_del(&lchan->T3111);
+	osmo_timer_del(&lchan->error_timer);
 
 	lchan->type = GSM_LCHAN_NONE;
 	lchan->state = LCHAN_S_NONE;
@@ -370,7 +370,7 @@
 	int sapi;
 
 	for (sapi = 1; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
-		u_int8_t link_id;
+		uint8_t link_id;
 		if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
 			continue;
 
@@ -401,7 +401,7 @@
 }
 
 /* called from abis rsl */
-int rsl_lchan_rll_release(struct gsm_lchan *lchan, u_int8_t link_id)
+int rsl_lchan_rll_release(struct gsm_lchan *lchan, uint8_t link_id)
 {
 	if (lchan->state != LCHAN_S_REL_REQ)
 		return -1;
@@ -465,8 +465,8 @@
 		int i;
 
 		/* skip administratively deactivated tranxsceivers */
-		if (!nm_is_running(&trx->nm_state) ||
-		    !nm_is_running(&trx->bb_transc.nm_state))
+		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++) {
@@ -475,7 +475,7 @@
 			int j;
 
 			/* skip administratively deactivated timeslots */
-			if (!nm_is_running(&ts->nm_state))
+			if (!nm_is_running(&ts->mo.nm_state))
 				continue;
 
 			for (j = 0; j < subslots_per_pchan[ts->pchan]; j++) {
diff --git a/src/libbsc/e1_config.c b/src/libbsc/e1_config.c
index 958839d..bd6ebba 100644
--- a/src/libbsc/e1_config.c
+++ b/src/libbsc/e1_config.c
@@ -29,7 +29,7 @@
 #include <openbsc/trau_mux.h>
 #include <openbsc/misdn.h>
 #include <openbsc/ipaccess.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/debug.h>
 
 #define SAPI_L2ML	0
diff --git a/src/libbsc/gsm_04_08_utils.c b/src/libbsc/gsm_04_08_utils.c
index 6d12cc0..17bce85 100644
--- a/src/libbsc/gsm_04_08_utils.c
+++ b/src/libbsc/gsm_04_08_utils.c
@@ -27,8 +27,8 @@
 #include <errno.h>
 #include <netinet/in.h>
 
-#include <osmocore/msgb.h>
-#include <osmocore/gsm48.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/gsm48.h>
 
 #include <openbsc/abis_rsl.h>
 #include <openbsc/debug.h>
@@ -52,8 +52,8 @@
 
 /* Section 9.1.8 / Table 9.9 */
 struct chreq {
-	u_int8_t val;
-	u_int8_t mask;
+	uint8_t val;
+	uint8_t mask;
 	enum chreq_type type;
 };
 
@@ -134,7 +134,7 @@
 };
 
 /* verify that the two tables match */
-static_assert(sizeof(ctype_by_chreq) ==
+osmo_static_assert(sizeof(ctype_by_chreq) ==
 	      sizeof(((struct gsm_network *) NULL)->ctype_by_chreq), assert_size);
 
 /*
@@ -166,7 +166,7 @@
 	}
 }
 
-enum gsm_chan_t get_ctype_by_chreq(struct gsm_network *network, u_int8_t ra)
+enum gsm_chan_t get_ctype_by_chreq(struct gsm_network *network, uint8_t ra)
 {
 	int i;
 	int length;
@@ -190,7 +190,7 @@
 	return GSM_LCHAN_SDCCH;
 }
 
-enum gsm_chreq_reason_t get_reason_by_chreq(u_int8_t ra, int neci)
+enum gsm_chreq_reason_t get_reason_by_chreq(uint8_t ra, int neci)
 {
 	int i;
 	int length;
@@ -218,7 +218,7 @@
 {
 	struct msgb *msg = gsm48_msgb_alloc();
 	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	u_int8_t *cause;
+	uint8_t *cause;
 
 	msg->lchan = lchan;
 	gh->proto_discr = GSM48_PDISC_RR;
@@ -239,7 +239,7 @@
 }
 
 int send_siemens_mrpci(struct gsm_lchan *lchan,
-		       u_int8_t *classmark2_lv)
+		       uint8_t *classmark2_lv)
 {
 	struct rsl_mrpci mrpci;
 
@@ -260,7 +260,7 @@
 	if (length < 1 + *classmark2_lv)
 		return -1;
 
-	u_int8_t *mi_lv = classmark2_lv + *classmark2_lv + 1;
+	uint8_t *mi_lv = classmark2_lv + *classmark2_lv + 1;
 	if (length < 2 + *classmark2_lv + mi_lv[0])
 		return -2;
 
@@ -269,11 +269,11 @@
 }
 
 int gsm48_paging_extract_mi(struct gsm48_pag_resp *resp, int length,
-			    char *mi_string, u_int8_t *mi_type)
+			    char *mi_string, uint8_t *mi_type)
 {
 	static const uint32_t classmark_offset =
 		offsetof(struct gsm48_pag_resp, classmark2);
-	u_int8_t *classmark2_lv = (uint8_t *) &resp->classmark2;
+	uint8_t *classmark2_lv = (uint8_t *) &resp->classmark2;
 	return gsm48_extract_mi(classmark2_lv, length - classmark_offset,
 				mi_string, mi_type);
 }
@@ -283,7 +283,7 @@
 {
 	struct gsm_bts *bts = msg->lchan->ts->trx->bts;
 	struct gsm48_hdr *gh = msgb_l3(msg);
-	u_int8_t *classmark2_lv = gh->data + 1;
+	uint8_t *classmark2_lv = gh->data + 1;
 
 	if (is_siemens_bts(bts))
 		send_siemens_mrpci(msg->lchan, classmark2_lv);
@@ -300,7 +300,7 @@
 		subscr = conn->subscr;
 	}
 
-	counter_inc(bts->network->stats.paging.completed);
+	osmo_counter_inc(bts->network->stats.paging.completed);
 
 	/* Stop paging on the bts we received the paging response */
 	paging_request_stop(conn->bts, subscr, conn, msg);
@@ -312,7 +312,7 @@
 {
 	struct msgb *msg = gsm48_msgb_alloc();
 	struct gsm48_hdr *gh;
-	u_int8_t ciph_mod_set;
+	uint8_t ciph_mod_set;
 
 	msg->lchan = lchan;
 
@@ -343,9 +343,9 @@
 void gsm48_lchan2chan_desc(struct gsm48_chan_desc *cd,
 			   const struct gsm_lchan *lchan)
 {
-	u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
+	uint16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
 
-	cd->chan_nr = lchan2chan_nr(lchan);
+	cd->chan_nr = gsm_lchan2chan_nr(lchan);
 	if (!lchan->ts->hopping.enabled) {
 		cd->h0.tsc = lchan->ts->trx->bts->tsc;
 		cd->h0.h = 0;
@@ -364,7 +364,7 @@
 
 /* Chapter 9.1.15: Handover Command */
 int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan,
-		      u_int8_t power_command, u_int8_t ho_ref)
+		      uint8_t power_command, uint8_t ho_ref)
 {
 	struct msgb *msg = gsm48_msgb_alloc();
 	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
@@ -403,7 +403,7 @@
 }
 
 /* Chapter 9.1.2: Assignment Command */
-int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, u_int8_t power_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();
 	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
@@ -443,7 +443,7 @@
 			LOGP(DRR, LOGL_ERROR, "BUG: Using multirate codec "
 				"without multirate config.\n");
 		} else {
-			u_int8_t *data = msgb_put(msg, 4);
+			uint8_t *data = msgb_put(msg, 4);
 			data[0] = GSM48_IE_MUL_RATE_CFG;
 			data[1] = 0x2;
 			memcpy(&data[2], &lchan->mr_conf, 2);
@@ -454,7 +454,7 @@
 }
 
 /* 9.1.5 Channel mode modify: Modify the mode on the MS side */
-int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
+int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, uint8_t mode)
 {
 	struct msgb *msg = gsm48_msgb_alloc();
 	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
@@ -479,7 +479,7 @@
 			LOGP(DRR, LOGL_ERROR, "BUG: Using multirate codec "
 				"without multirate config.\n");
 		} else {
-			u_int8_t *data = msgb_put(msg, 4);
+			uint8_t *data = msgb_put(msg, 4);
 			data[0] = GSM48_IE_MUL_RATE_CFG;
 			data[1] = 0x2;
 			memcpy(&data[2], &lchan->mr_conf, 2);
@@ -489,7 +489,7 @@
 	return gsm48_sendmsg(msg);
 }
 
-int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode)
+int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t lchan_mode)
 {
 	int rc;
 
@@ -547,7 +547,7 @@
 int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg)
 {
 	struct gsm48_hdr *gh = msgb_l3(msg);
-	u_int8_t *data = gh->data;
+	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;
diff --git a/src/libbsc/gsm_subscriber_base.c b/src/libbsc/gsm_subscriber_base.c
index caf84e7..11afb35 100644
--- a/src/libbsc/gsm_subscriber_base.c
+++ b/src/libbsc/gsm_subscriber_base.c
@@ -27,7 +27,7 @@
 #include <string.h>
 #include <assert.h>
 
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/gsm_subscriber.h>
 #include <openbsc/debug.h>
 
diff --git a/src/libbsc/handover_decision.c b/src/libbsc/handover_decision.c
index d3f843a..24c0f79 100644
--- a/src/libbsc/handover_decision.c
+++ b/src/libbsc/handover_decision.c
@@ -24,18 +24,18 @@
 #include <stdlib.h>
 #include <errno.h>
 
-#include <osmocore/msgb.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 <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/handover.h>
-#include <osmocore/gsm_utils.h>
+#include <osmocom/gsm/gsm_utils.h>
 
 /* issue handover to a cell identified by ARFCN and BSIC */
 static int handover_to_arfcn_bsic(struct gsm_lchan *lchan,
-				  u_int16_t arfcn, u_int8_t bsic)
+				  uint16_t arfcn, uint8_t bsic)
 {
 	struct gsm_bts *new_bts;
 
@@ -53,7 +53,7 @@
 
 /* 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,
-				 u_int16_t arfcn, u_int8_t bsic)
+				 uint16_t arfcn, uint8_t bsic)
 {
 	int i;
 
@@ -93,7 +93,7 @@
 static struct neigh_meas_proc *find_evict_neigh(struct gsm_lchan *lchan)
 {
 	int j, worst = 999999;
-	struct neigh_meas_proc *nmp_worst;
+	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++) {
@@ -106,7 +106,7 @@
 	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 (avg < worst) {
+		if (!nmp_worst || avg < worst) {
 			worst = avg;
 			nmp_worst = nmp;
 		}
@@ -293,5 +293,5 @@
 
 void on_dso_load_ho_dec(void)
 {
-	register_signal_handler(SS_LCHAN, ho_dec_sig_cb, NULL);
+	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
index c2e3f8c..0f1582e 100644
--- a/src/libbsc/handover_logic.c
+++ b/src/libbsc/handover_logic.c
@@ -28,16 +28,16 @@
 #include <time.h>
 #include <netinet/in.h>
 
-#include <osmocore/msgb.h>
+#include <osmocom/core/msgb.h>
 #include <openbsc/debug.h>
 #include <openbsc/gsm_data.h>
-#include <osmocore/gsm_utils.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 <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/transaction.h>
 #include <openbsc/rtp_proxy.h>
 
@@ -47,9 +47,9 @@
 	struct gsm_lchan *old_lchan;
 	struct gsm_lchan *new_lchan;
 
-	struct timer_list T3103;
+	struct osmo_timer_list T3103;
 
-	u_int8_t ho_ref;
+	uint8_t ho_ref;
 };
 
 static LLIST_HEAD(bsc_handovers);
@@ -85,7 +85,7 @@
 {
 	struct gsm_lchan *new_lchan;
 	struct bsc_handover *ho;
-	static u_int8_t ho_ref;
+	static uint8_t ho_ref;
 	int rc;
 
 	/* don't attempt multiple handovers for the same lchan at
@@ -96,7 +96,7 @@
 	DEBUGP(DHO, "(old_lchan on BTS %u, new BTS %u)\n",
 		old_lchan->ts->trx->bts->nr, bts->nr);
 
-	counter_inc(bts->network->stats.handover.attempted);
+	osmo_counter_inc(bts->network->stats.handover.attempted);
 
 	if (!old_lchan->conn) {
 		LOGP(DHO, LOGL_ERROR, "Old lchan lacks connection data.\n");
@@ -106,7 +106,7 @@
 	new_lchan = lchan_alloc(bts, old_lchan->type, 0);
 	if (!new_lchan) {
 		LOGP(DHO, LOGL_NOTICE, "No free channel\n");
-		counter_inc(bts->network->stats.handover.no_channel);
+		osmo_counter_inc(bts->network->stats.handover.no_channel);
 		return -ENOSPC;
 	}
 
@@ -170,7 +170,7 @@
 	if (free_lchan)
 		lchan_release(ho->new_lchan, 0, 1);
 
-	bsc_del_timer(&ho->T3103);
+	osmo_timer_del(&ho->T3103);
 	llist_del(&ho->list);
 	talloc_free(ho);
 }
@@ -182,7 +182,7 @@
 	struct gsm_network *net = ho->new_lchan->ts->trx->bts->network;
 
 	DEBUGP(DHO, "HO T3103 expired\n");
-	counter_inc(net->stats.handover.timeout);
+	osmo_counter_inc(net->stats.handover.timeout);
 
 	ho->new_lchan->conn->ho_lchan = NULL;
 	ho->new_lchan->conn = NULL;
@@ -214,7 +214,7 @@
 	 * 04.08 HANDOVER COMPLETE or 04.08 HANDOVER FAIL */
 	ho->T3103.cb = ho_T3103_cb;
 	ho->T3103.data = ho;
-	bsc_schedule_timer(&ho->T3103, 10, 0);
+	osmo_timer_schedule(&ho->T3103, 10, 0);
 
 	/* create a RTP connection */
 	if (is_ipaccess_bts(new_lchan->ts->trx->bts))
@@ -262,9 +262,9 @@
 	     ho->old_lchan->ts->trx->bts->nr, new_lchan->ts->trx->bts->nr,
 	     ho->old_lchan->ts->trx->arfcn, new_lchan->ts->trx->arfcn);
 
-	counter_inc(net->stats.handover.completed);
+	osmo_counter_inc(net->stats.handover.completed);
 
-	bsc_del_timer(&ho->T3103);
+	osmo_timer_del(&ho->T3103);
 
 	/* Replace the ho lchan with the primary one */
 	if (ho->old_lchan != new_lchan->conn->lchan)
@@ -300,9 +300,9 @@
 		return -ENODEV;
 	}
 
-	counter_inc(net->stats.handover.failed);
+	osmo_counter_inc(net->stats.handover.failed);
 
-	bsc_del_timer(&ho->T3103);
+	osmo_timer_del(&ho->T3103);
 	llist_del(&ho->list);
 
 	/* release the channel and forget about it */
@@ -344,7 +344,7 @@
 
 	sig_ho.old_lchan = ho->old_lchan;
 	sig_ho.new_lchan = new_lchan;
-	dispatch_signal(SS_HO, S_HANDOVER_ACK, &sig_ho);
+	osmo_signal_dispatch(SS_HO, S_HANDOVER_ACK, &sig_ho);
 	return 0;
 }
 
@@ -388,6 +388,6 @@
 
 static __attribute__((constructor)) void on_dso_load_ho_logic(void)
 {
-	register_signal_handler(SS_LCHAN, ho_logic_sig_cb, NULL);
-	register_signal_handler(SS_ABISIP, ho_logic_sig_cb, NULL);
+	osmo_signal_register_handler(SS_LCHAN, ho_logic_sig_cb, NULL);
+	osmo_signal_register_handler(SS_ABISIP, ho_logic_sig_cb, NULL);
 }
diff --git a/src/libbsc/meas_rep.c b/src/libbsc/meas_rep.c
index 788a9ba..808103d 100644
--- a/src/libbsc/meas_rep.c
+++ b/src/libbsc/meas_rep.c
@@ -19,7 +19,6 @@
  *
  */
 
-#include <sys/types.h>
 
 #include <openbsc/gsm_data.h>
 #include <openbsc/meas_rep.h>
diff --git a/src/libbsc/paging.c b/src/libbsc/paging.c
index 6502545..4dfa921 100644
--- a/src/libbsc/paging.c
+++ b/src/libbsc/paging.c
@@ -38,8 +38,11 @@
 #include <stdlib.h>
 #include <assert.h>
 
+#include <osmocom/core/talloc.h>
+#include <osmocom/gsm/gsm48.h>
+#include <osmocom/gsm/gsm0502.h>
+
 #include <openbsc/paging.h>
-#include <osmocore/talloc.h>
 #include <openbsc/debug.h>
 #include <openbsc/signal.h>
 #include <openbsc/abis_rsl.h>
@@ -51,29 +54,13 @@
 
 #define PAGING_TIMER 0, 500000
 
-static unsigned int calculate_group(struct gsm_bts *bts, struct gsm_subscriber *subscr)
-{
-	int ccch_conf;
-	int bs_cc_chans;
-	int blocks;
-	unsigned int group;
-	
-	ccch_conf = bts->si_common.chan_desc.ccch_conf;
-	bs_cc_chans = rsl_ccch_conf_to_bs_cc_chans(ccch_conf);
-	/* code word + 2, as 2 channels equals 0x0 */
-	blocks = rsl_number_of_paging_subchannels(bts);
-	group = get_paging_group(str_to_imsi(subscr->imsi),
-					bs_cc_chans, blocks);
-	return group;
-}
-
 /*
  * 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)
 {
-	bsc_del_timer(&to_be_deleted->T3113);
+	osmo_timer_del(&to_be_deleted->T3113);
 	llist_del(&to_be_deleted->entry);
 	subscr_put(to_be_deleted->subscr);
 	talloc_free(to_be_deleted);
@@ -81,9 +68,10 @@
 
 static void page_ms(struct gsm_paging_request *request)
 {
-	u_int8_t mi[128];
+	uint8_t mi[128];
 	unsigned int mi_len;
 	unsigned int page_group;
+	struct gsm_bts *bts = request->bts;
 
 	LOGP(DPAG, LOGL_INFO, "Going to send paging commands: imsi: '%s' tmsi: '0x%x'\n",
 		request->subscr->imsi, request->subscr->tmsi);
@@ -93,8 +81,9 @@
 	else
 		mi_len = gsm48_generate_mid_from_tmsi(mi, request->subscr->tmsi);
 
-	page_group = calculate_group(request->bts, request->subscr);
-	gsm0808_page(request->bts, page_group, mi_len, mi, request->chan_type);
+	page_group = gsm0502_calc_paging_group(&bts->si_common.chan_desc,
+						str_to_imsi(request->subscr->imsi));
+	gsm0808_page(bts, page_group, mi_len, mi, request->chan_type);
 }
 
 static void paging_schedule_if_needed(struct gsm_bts_paging_state *paging_bts)
@@ -102,8 +91,8 @@
 	if (llist_empty(&paging_bts->pending_requests))
 		return;
 
-	if (!bsc_timer_pending(&paging_bts->work_timer))
-		bsc_schedule_timer(&paging_bts->work_timer, PAGING_TIMER);
+	if (!osmo_timer_pending(&paging_bts->work_timer))
+		osmo_timer_schedule(&paging_bts->work_timer, PAGING_TIMER);
 }
 
 
@@ -192,7 +181,7 @@
 	if (paging_bts->available_slots == 0) {
 		paging_bts->credit_timer.cb = paging_give_credit;
 		paging_bts->credit_timer.data = paging_bts;
-		bsc_schedule_timer(&paging_bts->credit_timer, 5, 0);
+		osmo_timer_schedule(&paging_bts->credit_timer, 5, 0);
 		return;
 	}
 
@@ -215,7 +204,7 @@
 	llist_add_tail(&request->entry, &paging_bts->pending_requests);
 
 skip_paging:
-	bsc_schedule_timer(&paging_bts->work_timer, PAGING_TIMER);
+	osmo_timer_schedule(&paging_bts->work_timer, PAGING_TIMER);
 }
 
 static void paging_worker(void *data)
@@ -225,8 +214,11 @@
 	paging_handle_pending_requests(paging_bts);
 }
 
-void paging_init(struct gsm_bts *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);
 	bts->paging.work_timer.cb = paging_worker;
@@ -259,7 +251,7 @@
 		req, req->subscr->imsi);
 
 	/* must be destroyed before calling cbfn, to prevent double free */
-	counter_inc(req->bts->network->stats.paging.expired);
+	osmo_counter_inc(req->bts->network->stats.paging.expired);
 	cbfn_param = req->cbfn_param;
 	cbfn = req->cbfn;
 
@@ -295,7 +287,7 @@
 	req->cbfn_param = data;
 	req->T3113.cb = paging_T3113_expired;
 	req->T3113.data = req;
-	bsc_schedule_timer(&req->T3113, bts->network->T3113, 0);
+	osmo_timer_schedule(&req->T3113, bts->network->T3113, 0);
 	llist_add_tail(&req->entry, &bts_entry->pending_requests);
 	paging_schedule_if_needed(bts_entry);
 
@@ -308,7 +300,7 @@
 	struct gsm_bts *bts = NULL;
 	int num_pages = 0;
 
-	counter_inc(network->stats.paging.attempted);
+	osmo_counter_inc(network->stats.paging.attempted);
 
 	/* start paging subscriber on all BTS within Location Area */
 	do {
@@ -322,6 +314,9 @@
 		if (!trx_is_usable(bts->c0))
 			continue;
 
+		/* maybe it is the first time we use it */
+		paging_init_if_needed(bts);
+
 		num_pages++;
 
 		/* Trigger paging, pass any error to caller */
@@ -331,7 +326,7 @@
 	} while (1);
 
 	if (num_pages == 0)
-		counter_inc(network->stats.paging.detached);
+		osmo_counter_inc(network->stats.paging.detached);
 
 	return num_pages;
 }
@@ -345,6 +340,8 @@
 	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->subscr == subscr) {
@@ -387,9 +384,24 @@
 	} while (1);
 }
 
-void paging_update_buffer_space(struct gsm_bts *bts, u_int16_t free_slots)
+void paging_update_buffer_space(struct gsm_bts *bts, uint16_t free_slots)
 {
-	bsc_del_timer(&bts->paging.credit_timer);
+	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;
+}
diff --git a/src/libbsc/rest_octets.c b/src/libbsc/rest_octets.c
index 084f144..0545426 100644
--- a/src/libbsc/rest_octets.c
+++ b/src/libbsc/rest_octets.c
@@ -26,11 +26,11 @@
 #include <errno.h>
 
 #include <openbsc/gsm_data.h>
-#include <osmocore/bitvec.h>
+#include <osmocom/core/bitvec.h>
 #include <openbsc/rest_octets.h>
 
 /* generate SI1 rest octets */
-int rest_octets_si1(u_int8_t *data, u_int8_t *nch_pos)
+int rest_octets_si1(uint8_t *data, uint8_t *nch_pos)
 {
 	struct bitvec bv;
 
@@ -88,7 +88,7 @@
 
 
 /* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */
-int rest_octets_si3(u_int8_t *data, const struct gsm48_si_ro_info *si3)
+int rest_octets_si3(uint8_t *data, const struct gsm48_si_ro_info *si3)
 {
 	struct bitvec bv;
 
@@ -136,7 +136,7 @@
 }
 
 /* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
-int rest_octets_si4(u_int8_t *data, const struct gsm48_si_ro_info *si4)
+int rest_octets_si4(uint8_t *data, const struct gsm48_si_ro_info *si4)
 {
 	struct bitvec bv;
 
@@ -366,7 +366,7 @@
 }
 
 /* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */
-int rest_octets_si13(u_int8_t *data, const struct gsm48_si13_info *si13)
+int rest_octets_si13(uint8_t *data, const struct gsm48_si13_info *si13)
 {
 	struct bitvec bv;
 
diff --git a/src/libbsc/system_information.c b/src/libbsc/system_information.c
index dc71938..353b3dd 100644
--- a/src/libbsc/system_information.c
+++ b/src/libbsc/system_information.c
@@ -23,40 +23,23 @@
 #include <errno.h>
 #include <string.h>
 #include <stdio.h>
-#include <sys/types.h>
 #include <netinet/in.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 <osmocore/bitvec.h>
-#include <osmocore/utils.h>
-#include <openbsc/debug.h>
 
-#define GSM48_CELL_CHAN_DESC_SIZE	16
-#define GSM_MACBLOCK_PADDING		0x2b
-
-/* verify the sizes of the system information type structs */
-
-/* rest octets are not part of the struct */
-static_assert(sizeof(struct gsm48_system_information_type_header) == 3, _si_header_size);
-static_assert(sizeof(struct gsm48_rach_control) == 3, _si_rach_control);
-static_assert(sizeof(struct gsm48_system_information_type_1) == 22, _si1_size);
-static_assert(sizeof(struct gsm48_system_information_type_2) == 23, _si2_size);
-static_assert(sizeof(struct gsm48_system_information_type_3) == 19, _si3_size);
-static_assert(sizeof(struct gsm48_system_information_type_4) == 13, _si4_size);
-
-/* bs11 forgot the l2 len, 0-6 rest octets */
-static_assert(sizeof(struct gsm48_system_information_type_5) == 18, _si5_size);
-static_assert(sizeof(struct gsm48_system_information_type_6) == 11, _si6_size);
-
-static_assert(sizeof(struct gsm48_system_information_type_13) == 3, _si13_size);
 
 /* 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(u_int8_t *chan_list, unsigned int arfcn)
+static int freq_list_bm0_set_arfcn(uint8_t *chan_list, unsigned int arfcn)
 {
 	unsigned int byte, bit;
 
@@ -77,7 +60,7 @@
 }
 
 /* 10.5.2.13.7: Variable bit map format */
-static int freq_list_bmrel_set_arfcn(u_int8_t *chan_list, unsigned int arfcn)
+static int freq_list_bmrel_set_arfcn(uint8_t *chan_list, unsigned int arfcn)
 {
 	unsigned int byte, bit;
 	unsigned int min_arfcn;
@@ -110,7 +93,7 @@
 }
 
 /* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
-static int bitvec2freq_list(u_int8_t *chan_list, struct bitvec *bv,
+static int bitvec2freq_list(uint8_t *chan_list, struct bitvec *bv,
 			    const struct gsm_bts *bts)
 {
 	int i, rc, min = 1024, max = -1;
@@ -171,7 +154,7 @@
 }
 
 /* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
-static int generate_cell_chan_list(u_int8_t *chan_list, struct gsm_bts *bts)
+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;
@@ -199,7 +182,7 @@
 }
 
 /* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
-static int generate_bcch_chan_list(u_int8_t *chan_list, struct gsm_bts *bts, int si5)
+static int generate_bcch_chan_list(uint8_t *chan_list, struct gsm_bts *bts, int si5)
 {
 	struct gsm_bts *cur_bts;
 	struct bitvec *bv;
@@ -226,7 +209,7 @@
 	return bitvec2freq_list(chan_list, bv, bts);
 }
 
-static int generate_si1(u_int8_t *output, struct gsm_bts *bts)
+static int generate_si1(uint8_t *output, struct gsm_bts *bts)
 {
 	int rc;
 	struct gsm48_system_information_type_1 *si1 =
@@ -251,7 +234,7 @@
 	return sizeof(*si1) + rc;
 }
 
-static int generate_si2(u_int8_t *output, struct gsm_bts *bts)
+static int generate_si2(uint8_t *output, struct gsm_bts *bts)
 {
 	int rc;
 	struct gsm48_system_information_type_2 *si2 =
@@ -298,7 +281,7 @@
 	.break_ind = 0,
 };
 
-static int generate_si3(u_int8_t *output, struct gsm_bts *bts)
+static int generate_si3(uint8_t *output, struct gsm_bts *bts)
 {
 	int rc;
 	struct gsm48_system_information_type_3 *si3 =
@@ -329,7 +312,7 @@
 	return sizeof(*si3) + rc;
 }
 
-static int generate_si4(u_int8_t *output, struct gsm_bts *bts)
+static int generate_si4(uint8_t *output, struct gsm_bts *bts)
 {
 	int rc;
 	struct gsm48_system_information_type_4 *si4 =
@@ -362,7 +345,7 @@
 	return sizeof(*si4) + rc;
 }
 
-static int generate_si5(u_int8_t *output, struct gsm_bts *bts)
+static int generate_si5(uint8_t *output, struct gsm_bts *bts)
 {
 	struct gsm48_system_information_type_5 *si5;
 	int rc, l2_plen = 18;
@@ -394,7 +377,7 @@
 	return l2_plen;
 }
 
-static int generate_si6(u_int8_t *output, struct gsm_bts *bts)
+static int generate_si6(uint8_t *output, struct gsm_bts *bts)
 {
 	struct gsm48_system_information_type_6 *si6;
 	int l2_plen = 11;
@@ -468,7 +451,7 @@
 	},
 };
 
-static int generate_si13(u_int8_t *output, struct gsm_bts *bts)
+static int generate_si13(uint8_t *output, struct gsm_bts *bts)
 {
 	struct gsm48_system_information_type_13 *si13 =
 		(struct gsm48_system_information_type_13 *) output;
@@ -492,54 +475,6 @@
 	return sizeof (*si13) + ret;
 }
 
-static const uint8_t sitype2rsl[_MAX_SYSINFO_TYPE] = {
-	[SYSINFO_TYPE_1]	= RSL_SYSTEM_INFO_1,
-	[SYSINFO_TYPE_2]	= RSL_SYSTEM_INFO_2,
-	[SYSINFO_TYPE_3]	= RSL_SYSTEM_INFO_3,
-	[SYSINFO_TYPE_4]	= RSL_SYSTEM_INFO_4,
-	[SYSINFO_TYPE_5]	= RSL_SYSTEM_INFO_5,
-	[SYSINFO_TYPE_6]	= RSL_SYSTEM_INFO_6,
-	[SYSINFO_TYPE_7]	= RSL_SYSTEM_INFO_7,
-	[SYSINFO_TYPE_8]	= RSL_SYSTEM_INFO_8,
-	[SYSINFO_TYPE_9]	= RSL_SYSTEM_INFO_9,
-	[SYSINFO_TYPE_10]	= RSL_SYSTEM_INFO_10,
-	[SYSINFO_TYPE_13]	= RSL_SYSTEM_INFO_13,
-	[SYSINFO_TYPE_16]	= RSL_SYSTEM_INFO_16,
-	[SYSINFO_TYPE_17]	= RSL_SYSTEM_INFO_17,
-	[SYSINFO_TYPE_18]	= RSL_SYSTEM_INFO_18,
-	[SYSINFO_TYPE_19]	= RSL_SYSTEM_INFO_19,
-	[SYSINFO_TYPE_20]	= RSL_SYSTEM_INFO_20,
-	[SYSINFO_TYPE_2bis]	= RSL_SYSTEM_INFO_2bis,
-	[SYSINFO_TYPE_2ter]	= RSL_SYSTEM_INFO_2ter,
-	[SYSINFO_TYPE_2quater]	= RSL_SYSTEM_INFO_2quater,
-	[SYSINFO_TYPE_5bis]	= RSL_SYSTEM_INFO_5bis,
-	[SYSINFO_TYPE_5ter]	= RSL_SYSTEM_INFO_5ter,
-};
-
-static const uint8_t rsl2sitype[0xff] = {
-	[RSL_SYSTEM_INFO_1] = SYSINFO_TYPE_1,
-	[RSL_SYSTEM_INFO_2] = SYSINFO_TYPE_2,
-	[RSL_SYSTEM_INFO_3] = SYSINFO_TYPE_3,
-	[RSL_SYSTEM_INFO_4] = SYSINFO_TYPE_4,
-	[RSL_SYSTEM_INFO_5] = SYSINFO_TYPE_5,
-	[RSL_SYSTEM_INFO_6] = SYSINFO_TYPE_6,
-	[RSL_SYSTEM_INFO_7] = SYSINFO_TYPE_7,
-	[RSL_SYSTEM_INFO_8] = SYSINFO_TYPE_8,
-	[RSL_SYSTEM_INFO_9] = SYSINFO_TYPE_9,
-	[RSL_SYSTEM_INFO_10] = SYSINFO_TYPE_10,
-	[RSL_SYSTEM_INFO_13] = SYSINFO_TYPE_13,
-	[RSL_SYSTEM_INFO_16] = SYSINFO_TYPE_16,
-	[RSL_SYSTEM_INFO_17] = SYSINFO_TYPE_17,
-	[RSL_SYSTEM_INFO_18] = SYSINFO_TYPE_18,
-	[RSL_SYSTEM_INFO_19] = SYSINFO_TYPE_19,
-	[RSL_SYSTEM_INFO_20] = SYSINFO_TYPE_20,
-	[RSL_SYSTEM_INFO_2bis] = SYSINFO_TYPE_2bis,
-	[RSL_SYSTEM_INFO_2ter] = SYSINFO_TYPE_2ter,
-	[RSL_SYSTEM_INFO_2quater] = SYSINFO_TYPE_2quater,
-	[RSL_SYSTEM_INFO_5bis] = SYSINFO_TYPE_5bis,
-	[RSL_SYSTEM_INFO_5ter] = SYSINFO_TYPE_5ter,
-};
-
 typedef int (*gen_si_fn_t)(uint8_t *output, struct gsm_bts *bts);
 
 static const gen_si_fn_t gen_si_fn[_MAX_SYSINFO_TYPE] = {
@@ -552,41 +487,6 @@
 	[SYSINFO_TYPE_13] = &generate_si13,
 };
 
-const struct value_string osmo_sitype_strs[_MAX_SYSINFO_TYPE] = {
-	{ SYSINFO_TYPE_1,	"1" },
-	{ SYSINFO_TYPE_2,	"2" },
-	{ SYSINFO_TYPE_3,	"3" },
-	{ SYSINFO_TYPE_4,	"4" },
-	{ SYSINFO_TYPE_5,	"5" },
-	{ SYSINFO_TYPE_6,	"6" },
-	{ SYSINFO_TYPE_7,	"7" },
-	{ SYSINFO_TYPE_8,	"8" },
-	{ SYSINFO_TYPE_9,	"9" },
-	{ SYSINFO_TYPE_10,	"10" },
-	{ SYSINFO_TYPE_13,	"13" },
-	{ SYSINFO_TYPE_16,	"16" },
-	{ SYSINFO_TYPE_17,	"17" },
-	{ SYSINFO_TYPE_18,	"18" },
-	{ SYSINFO_TYPE_19,	"19" },
-	{ SYSINFO_TYPE_20,	"20" },
-	{ SYSINFO_TYPE_2bis,	"2bis" },
-	{ SYSINFO_TYPE_2ter,	"2ter" },
-	{ SYSINFO_TYPE_2quater,	"2quater" },
-	{ SYSINFO_TYPE_5bis,	"5bis" },
-	{ SYSINFO_TYPE_5ter,	"5ter" },
-	{ 0, NULL }
-};
-
-uint8_t gsm_sitype2rsl(enum osmo_sysinfo_type si_type)
-{
-	return sitype2rsl[si_type];
-}
-
-const char *gsm_sitype_name(enum osmo_sysinfo_type si_type)
-{
-	return get_value_string(osmo_sitype_strs, si_type);
-}
-
 int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type si_type)
 {
 	gen_si_fn_t gen_si;
diff --git a/src/libcommon/Makefile.am b/src/libcommon/Makefile.am
index 2895452..a832b75 100644
--- a/src/libcommon/Makefile.am
+++ b/src/libcommon/Makefile.am
@@ -1,7 +1,7 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 
 noinst_LIBRARIES = libcommon.a
 
-libcommon_a_SOURCES = bsc_version.c common_vty.c debug.c gsm_data.c socket.c talloc_ctx.c
+libcommon_a_SOURCES = bsc_version.c common_vty.c debug.c gsm_data.c gsm_data_shared.c socket.c talloc_ctx.c
diff --git a/src/libcommon/Makefile.in b/src/libcommon/Makefile.in
index 41d52fc..c3e417e 100644
--- a/src/libcommon/Makefile.in
+++ b/src/libcommon/Makefile.in
@@ -35,7 +35,7 @@
 subdir = src/libcommon
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -54,8 +54,8 @@
 libcommon_a_AR = $(AR) $(ARFLAGS)
 libcommon_a_LIBADD =
 am_libcommon_a_OBJECTS = bsc_version.$(OBJEXT) common_vty.$(OBJEXT) \
-	debug.$(OBJEXT) gsm_data.$(OBJEXT) socket.$(OBJEXT) \
-	talloc_ctx.$(OBJEXT)
+	debug.$(OBJEXT) gsm_data.$(OBJEXT) gsm_data_shared.$(OBJEXT) \
+	socket.$(OBJEXT) talloc_ctx.$(OBJEXT)
 libcommon_a_OBJECTS = $(am_libcommon_a_OBJECTS)
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -112,6 +112,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -181,10 +183,10 @@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 noinst_LIBRARIES = libcommon.a
-libcommon_a_SOURCES = bsc_version.c common_vty.c debug.c gsm_data.c socket.c talloc_ctx.c
+libcommon_a_SOURCES = bsc_version.c common_vty.c debug.c gsm_data.c gsm_data_shared.c socket.c talloc_ctx.c
 all: all-am
 
 .SUFFIXES:
@@ -237,6 +239,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common_vty.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_data.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_data_shared.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/talloc_ctx.Po@am__quote@
 
diff --git a/src/libcommon/common_vty.c b/src/libcommon/common_vty.c
index 84375a2..5b4b296 100644
--- a/src/libcommon/common_vty.c
+++ b/src/libcommon/common_vty.c
@@ -21,7 +21,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 
 #include <openbsc/vty.h>
 #include <openbsc/gsm_data.h>
@@ -83,8 +83,11 @@
 			vty->index = bsc_config->nat;
 		}
 		break;
+	case PGROUP_NODE:
+		vty->node = NAT_NODE;
+		break;
 	case MSC_NODE:
-		vty->node = GSMNET_NODE;
+		vty->node = CONFIG_NODE;
 		break;
 	case TRUNK_NODE:
 		vty->node = MGCP_NODE;
@@ -139,6 +142,9 @@
 			vty->index = bsc_config->nat;
 		}
 		break;
+	case PGROUP_NODE:
+		vty->node = NAT_NODE;
+		break;
 	case MGCP_NODE:
 	case GBPROXY_NODE:
 	case SGSN_NODE:
@@ -155,7 +161,7 @@
 		vty->index = NULL;
 		break;
 	case MSC_NODE:
-		vty->node = GSMNET_NODE;
+		vty->node = CONFIG_NODE;
 		break;
 	case TRUNK_NODE:
 		vty->node = MGCP_NODE;
@@ -189,6 +195,7 @@
 	case VTY_NODE:
 	case NAT_NODE:
 	case NAT_BSC_NODE:
+	case PGROUP_NODE:
 	case MSC_NODE:
 		vty_config_unlock(vty);
 		vty->node = ENABLE_NODE;
diff --git a/src/libcommon/debug.c b/src/libcommon/debug.c
index ea5db49..1372150 100644
--- a/src/libcommon/debug.c
+++ b/src/libcommon/debug.c
@@ -27,9 +27,9 @@
 #include <time.h>
 #include <errno.h>
 
-#include <osmocore/talloc.h>
-#include <osmocore/utils.h>
-#include <osmocore/logging.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/logging.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/gsm_subscriber.h>
 #include <openbsc/debug.h>
diff --git a/src/libcommon/gsm_data.c b/src/libcommon/gsm_data.c
index b2c52e4..6b15bd0 100644
--- a/src/libcommon/gsm_data.c
+++ b/src/libcommon/gsm_data.c
@@ -26,10 +26,11 @@
 
 #include <netinet/in.h>
 
-#include <osmocore/linuxlist.h>
-#include <osmocore/talloc.h>
-#include <osmocore/gsm_utils.h>
-#include <osmocore/statistics.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>
 #include <openbsc/osmo_msc_data.h>
@@ -39,80 +40,14 @@
 
 static LLIST_HEAD(bts_models);
 
-void set_ts_e1link(struct gsm_bts_trx_ts *ts, u_int8_t e1_nr,
-		   u_int8_t e1_ts, u_int8_t e1_ts_ss)
+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 const struct value_string pchan_names[] = {
-	{ 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" },
-	{ 0,			NULL }
-};
-
-const char *gsm_pchan_name(enum gsm_phys_chan_config c)
-{
-	return get_value_string(pchan_names, c);
-}
-
-enum gsm_phys_chan_config gsm_pchan_parse(const char *name)
-{
-	return get_string_value(pchan_names, name);
-}
-
-static const struct value_string lchant_names[] = {
-	{ GSM_LCHAN_NONE,	"NONE" },
-	{ GSM_LCHAN_SDCCH,	"SDCCH" },
-	{ GSM_LCHAN_TCH_F,	"TCH/F" },
-	{ GSM_LCHAN_TCH_H,	"TCH/H" },
-	{ GSM_LCHAN_UNKNOWN,	"UNKNOWN" },
-	{ 0,			NULL }
-};
-
-const char *gsm_lchant_name(enum gsm_chan_t c)
-{
-	return get_value_string(lchant_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" },
-	{ 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);
-}
-
 static struct gsm_bts_model *bts_model_find(enum gsm_bts_type type)
 {
 	struct gsm_bts_model *model;
@@ -130,129 +65,12 @@
 	if (bts_model_find(model->type))
 		return -EEXIST;
 
-	tlv_def_patch(&model->nm_att_tlvdef, &nm_att_tlvdef);
+	tlv_def_patch(&model->nm_att_tlvdef, &abis_nm_att_tlvdef);
 	llist_add_tail(&model->list, &bts_models);
 	return 0;
 }
 
-
-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->nm_state.administrative = NM_STATE_UNLOCKED;
-
-	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->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;
-			lchan = &ts->lchan[l];
-
-			lchan->ts = ts;
-			lchan->nr = l;
-			lchan->type = GSM_LCHAN_NONE;
-		}
-	}
-
-	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 };
-
-struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type,
-			      u_int8_t tsc, u_int8_t bsic)
-{
-	struct gsm_bts *bts = talloc_zero(net, struct gsm_bts);
-	struct gsm_bts_model *model = bts_model_find(type);
-	int i;
-
-	if (!bts)
-		return NULL;
-
-	if (!model && type != GSM_BTS_TYPE_UNKNOWN) {
-		talloc_free(bts);
-		return NULL;
-	}
-
-	bts->network = net;
-	bts->nr = net->num_bts++;
-	bts->type = type;
-	bts->model = model;
-	bts->tsc = tsc;
-	bts->bsic = bsic;
-	bts->num_trx = 0;
-	INIT_LLIST_HEAD(&bts->trx_list);
-	bts->ms_max_power = 15;	/* dBm */
-
-	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.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 */
-
-	for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) {
-		bts->gprs.nsvc[i].bts = bts;
-		bts->gprs.nsvc[i].id = i;
-	}
-	memcpy(&bts->gprs.nse.timer, bts_nse_timer_default,
-		sizeof(bts->gprs.nse.timer));
-	memcpy(&bts->gprs.cell.timer, bts_cell_timer_default,
-		sizeof(bts->gprs.cell.timer));
-
-	/* 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;
-	INIT_LLIST_HEAD(&bts->abis_queue);
-
-	llist_add_tail(&bts->list, &net->bts_list);
-
-	return bts;
-}
-
-struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_code,
+struct gsm_network *gsm_network_init(uint16_t country_code, uint16_t network_code,
 				     int (*mncc_recv)(struct gsm_network *, struct msgb *))
 {
 	struct gsm_network *net;
@@ -267,6 +85,9 @@
 		return NULL;
 	}
 
+	/* Init back pointer */
+	net->msc_data->network = net;
+
 	net->country_code = country_code;
 	net->network_code = network_code;
 	net->num_bts = 0;
@@ -287,41 +108,40 @@
 	INIT_LLIST_HEAD(&net->upqueue);
 	INIT_LLIST_HEAD(&net->bts_list);
 
-	net->stats.chreq.total = counter_alloc("net.chreq.total");
-	net->stats.chreq.no_channel = counter_alloc("net.chreq.no_channel");
-	net->stats.handover.attempted = counter_alloc("net.handover.attempted");
-	net->stats.handover.no_channel = counter_alloc("net.handover.no_channel");
-	net->stats.handover.timeout = counter_alloc("net.handover.timeout");
-	net->stats.handover.completed = counter_alloc("net.handover.completed");
-	net->stats.handover.failed = counter_alloc("net.handover.failed");
-	net->stats.loc_upd_type.attach = counter_alloc("net.loc_upd_type.attach");
-	net->stats.loc_upd_type.normal = counter_alloc("net.loc_upd_type.normal");
-	net->stats.loc_upd_type.periodic = counter_alloc("net.loc_upd_type.periodic");
-	net->stats.loc_upd_type.detach = counter_alloc("net.imsi_detach.count");
-	net->stats.loc_upd_resp.reject = counter_alloc("net.loc_upd_resp.reject");
-	net->stats.loc_upd_resp.accept = counter_alloc("net.loc_upd_resp.accept");
-	net->stats.paging.attempted = counter_alloc("net.paging.attempted");
-	net->stats.paging.detached = counter_alloc("net.paging.detached");
-	net->stats.paging.completed = counter_alloc("net.paging.completed");
-	net->stats.paging.expired = counter_alloc("net.paging.expired");
-	net->stats.sms.submitted = counter_alloc("net.sms.submitted");
-	net->stats.sms.no_receiver = counter_alloc("net.sms.no_receiver");
-	net->stats.sms.delivered = counter_alloc("net.sms.delivered");
-	net->stats.sms.rp_err_mem = counter_alloc("net.sms.rp_err_mem");
-	net->stats.sms.rp_err_other = counter_alloc("net.sms.rp_err_other");
-	net->stats.call.mo_setup = counter_alloc("net.call.mo_setup");
-	net->stats.call.mo_connect_ack = counter_alloc("net.call.mo_connect_ack");
-	net->stats.call.mt_setup = counter_alloc("net.call.mt_setup");
-	net->stats.call.mt_connect = counter_alloc("net.call.mt_connect");
-	net->stats.chan.rf_fail = counter_alloc("net.chan.rf_fail");
-	net->stats.chan.rll_err = counter_alloc("net.chan.rll_err");
-	net->stats.bts.oml_fail = counter_alloc("net.bts.oml_fail");
-	net->stats.bts.rsl_fail = counter_alloc("net.bts.rsl_fail");
+	net->stats.chreq.total = osmo_counter_alloc("net.chreq.total");
+	net->stats.chreq.no_channel = osmo_counter_alloc("net.chreq.no_channel");
+	net->stats.handover.attempted = osmo_counter_alloc("net.handover.attempted");
+	net->stats.handover.no_channel = osmo_counter_alloc("net.handover.no_channel");
+	net->stats.handover.timeout = osmo_counter_alloc("net.handover.timeout");
+	net->stats.handover.completed = osmo_counter_alloc("net.handover.completed");
+	net->stats.handover.failed = osmo_counter_alloc("net.handover.failed");
+	net->stats.loc_upd_type.attach = osmo_counter_alloc("net.loc_upd_type.attach");
+	net->stats.loc_upd_type.normal = osmo_counter_alloc("net.loc_upd_type.normal");
+	net->stats.loc_upd_type.periodic = osmo_counter_alloc("net.loc_upd_type.periodic");
+	net->stats.loc_upd_type.detach = osmo_counter_alloc("net.imsi_detach.count");
+	net->stats.loc_upd_resp.reject = osmo_counter_alloc("net.loc_upd_resp.reject");
+	net->stats.loc_upd_resp.accept = osmo_counter_alloc("net.loc_upd_resp.accept");
+	net->stats.paging.attempted = osmo_counter_alloc("net.paging.attempted");
+	net->stats.paging.detached = osmo_counter_alloc("net.paging.detached");
+	net->stats.paging.completed = osmo_counter_alloc("net.paging.completed");
+	net->stats.paging.expired = osmo_counter_alloc("net.paging.expired");
+	net->stats.sms.submitted = osmo_counter_alloc("net.sms.submitted");
+	net->stats.sms.no_receiver = osmo_counter_alloc("net.sms.no_receiver");
+	net->stats.sms.delivered = osmo_counter_alloc("net.sms.delivered");
+	net->stats.sms.rp_err_mem = osmo_counter_alloc("net.sms.rp_err_mem");
+	net->stats.sms.rp_err_other = osmo_counter_alloc("net.sms.rp_err_other");
+	net->stats.call.mo_setup = osmo_counter_alloc("net.call.mo_setup");
+	net->stats.call.mo_connect_ack = osmo_counter_alloc("net.call.mo_connect_ack");
+	net->stats.call.mt_setup = osmo_counter_alloc("net.call.mt_setup");
+	net->stats.call.mt_connect = osmo_counter_alloc("net.call.mt_connect");
+	net->stats.chan.rf_fail = osmo_counter_alloc("net.chan.rf_fail");
+	net->stats.chan.rll_err = osmo_counter_alloc("net.chan.rll_err");
+	net->stats.bts.oml_fail = osmo_counter_alloc("net.bts.oml_fail");
+	net->stats.bts.rsl_fail = osmo_counter_alloc("net.bts.rsl_fail");
 
 	net->mncc_recv = mncc_recv;
 
-	net->msc_data->msc_ip = talloc_strdup(net, "127.0.0.1");
-	net->msc_data->msc_port = 5000;
+	INIT_LLIST_HEAD(&net->msc_data->dests);
 	net->msc_data->ping_timeout = 20;
 	net->msc_data->pong_timeout = 5;
 	net->msc_data->core_ncc = -1;
@@ -350,7 +170,7 @@
 
 /* Get reference to a neighbor cell on a given BCCH ARFCN */
 struct gsm_bts *gsm_bts_neighbor(const struct gsm_bts *bts,
-				 u_int16_t arfcn, u_int8_t bsic)
+				 uint16_t arfcn, uint8_t bsic)
 {
 	struct gsm_bts *neigh;
 	/* FIXME: use some better heuristics here to determine which cell
@@ -367,50 +187,6 @@
 	return NULL;
 }
 
-struct gsm_bts_trx *gsm_bts_trx_num(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(struct gsm_bts_trx *trx)
-{
-	snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d)",
-		 trx->bts->nr, trx->nr);
-
-	return ts2str;
-}
-
-
-char *gsm_ts_name(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;
-}
-
-char *gsm_lchan_name(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;
-}
-
 static const struct value_string bts_types[] = {
 	{ GSM_BTS_TYPE_UNKNOWN,	"unknown" },
 	{ GSM_BTS_TYPE_BS11,	"bs11" },
@@ -485,23 +261,6 @@
 	return get_value_string(auth_policy_names, policy);
 }
 
-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(u_int8_t *buf, struct gsm_bts *bts)
-{
-	struct gprs_ra_id raid;
-
-	gprs_ra_id_by_bts(&raid, bts);
-
-	return gsm48_construct_ra(buf, &raid);
-}
-
 static const struct value_string rrlp_mode_names[] = {
 	{ RRLP_MODE_NONE,	"none" },
 	{ RRLP_MODE_MS_BASED,	"ms-based" },
@@ -571,6 +330,14 @@
 	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_HSL_FEMTO:
 		bts->c0->rsl_tei = 0;
@@ -590,3 +357,64 @@
 
 	return 0;
 }
+
+struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net, enum gsm_bts_type type,
+					uint8_t tsc, 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);
+	if (!bts)
+		return NULL;
+
+	bts->network = net;
+	bts->nr = net->num_bts++;
+	bts->type = type;
+	bts->model = model;
+	bts->tsc = tsc;
+	bts->bsic = bsic;
+
+	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.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 */
+
+	llist_add_tail(&bts->list, &net->bts_list);
+
+	INIT_LLIST_HEAD(&bts->abis_queue);
+
+	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);
+}
diff --git a/src/libcommon/gsm_data_shared.c b/src/libcommon/gsm_data_shared.c
new file mode 100644
index 0000000..58e3bed
--- /dev/null
+++ b/src/libcommon/gsm_data_shared.c
@@ -0,0 +1,478 @@
+/* (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.administrative = NM_STATE_NULL;
+	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);
+}
+
+static const struct value_string pchan_names[] = {
+	{ 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" },
+	{ 0,			NULL }
+};
+
+const char *gsm_pchan_name(enum gsm_phys_chan_config c)
+{
+	return get_value_string(pchan_names, c);
+}
+
+enum gsm_phys_chan_config gsm_pchan_parse(const char *name)
+{
+	return get_string_value(pchan_names, name);
+}
+
+static const struct value_string lchant_names[] = {
+	{ GSM_LCHAN_NONE,	"NONE" },
+	{ GSM_LCHAN_SDCCH,	"SDCCH" },
+	{ GSM_LCHAN_TCH_F,	"TCH/F" },
+	{ GSM_LCHAN_TCH_H,	"TCH/H" },
+	{ GSM_LCHAN_UNKNOWN,	"UNKNOWN" },
+	{ 0,			NULL }
+};
+
+const char *gsm_lchant_name(enum gsm_chan_t c)
+{
+	return get_value_string(lchant_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" },
+	{ 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_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->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;
+			lchan = &ts->lchan[l];
+
+			lchan->ts = ts;
+			lchan->nr = l;
+			lchan->type = GSM_LCHAN_NONE;
+		}
+	}
+
+	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 };
+
+struct gsm_bts *gsm_bts_alloc(void *ctx)
+{
+	struct gsm_bts *bts = talloc_zero(ctx, struct gsm_bts);
+	int i;
+
+	if (!bts)
+		return NULL;
+
+	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);
+
+	/* 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;
+
+	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(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(struct gsm_bts_trx *trx)
+{
+	snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d)",
+		 trx->bts->nr, trx->nr);
+
+	return ts2str;
+}
+
+
+char *gsm_ts_name(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;
+}
+
+char *gsm_lchan_name(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,
+	    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;
+		}
+	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,
+		 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,
+	     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_ts2chan_nr(const struct gsm_bts_trx_ts *ts, uint8_t lchan_nr)
+{
+	uint8_t cbits, chan_nr;
+
+	switch (ts->pchan) {
+	case GSM_PCHAN_TCH_F:
+	case GSM_PCHAN_PDCH:
+	case GSM_PCHAN_TCH_F_PDCH:
+		cbits = 0x01;
+		break;
+	case GSM_PCHAN_TCH_H:
+		cbits = 0x02;
+		cbits += lchan_nr;
+		break;
+	case GSM_PCHAN_CCCH_SDCCH4:
+		cbits = 0x04;
+		cbits += lchan_nr;
+		break;
+	case GSM_PCHAN_SDCCH8_SACCH8C:
+		cbits = 0x08;
+		cbits += lchan_nr;
+		break;
+	default:
+	case GSM_PCHAN_CCCH:
+		cbits = 0x10;
+		break;
+	}
+
+	chan_nr = (cbits << 3) | (ts->nr & 0x7);
+
+	return chan_nr;
+}
+
+uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan)
+{
+	return gsm_ts2chan_nr(lchan->ts, lchan->nr);
+}
diff --git a/src/libcommon/socket.c b/src/libcommon/socket.c
index 47778e7..ff846aa 100644
--- a/src/libcommon/socket.c
+++ b/src/libcommon/socket.c
@@ -28,20 +28,20 @@
 #include <string.h>
 #include <time.h>
 #include <sys/fcntl.h>
-#include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <arpa/inet.h>
 
-#include <osmocore/select.h>
-#include <osmocore/tlv.h>
-#include <osmocore/msgb.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 <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 
-int make_sock(struct bsc_fd *bfd, int proto, u_int32_t ip, u_int16_t port,
-	      int (*cb)(struct bsc_fd *fd, unsigned int what))
+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;
@@ -64,7 +64,8 @@
 	bfd->fd = socket(AF_INET, type, proto);
 	bfd->cb = cb;
 	bfd->when = BSC_FD_READ;
-	//bfd->data = line;
+	bfd->data = data;
+	bfd->priv_nr = priv_nr;
 
 	if (bfd->fd < 0) {
 		LOGP(DINP, LOGL_ERROR, "could not create socket.\n");
@@ -74,7 +75,7 @@
 	memset(&addr, 0, sizeof(addr));
 	addr.sin_family = AF_INET;
 	addr.sin_port = htons(port);
-	if (ip)
+	if (ip != INADDR_ANY)
 		addr.sin_addr.s_addr = htonl(ip);
 	else
 		addr.sin_addr.s_addr = INADDR_ANY;
@@ -98,7 +99,7 @@
 		}
 	}
 
-	ret = bsc_register_fd(bfd);
+	ret = osmo_fd_register(bfd);
 	if (ret < 0) {
 		perror("register_listen_fd");
 		close(bfd->fd);
diff --git a/src/libcommon/talloc_ctx.c b/src/libcommon/talloc_ctx.c
index 8e7ec23..ae6a156 100644
--- a/src/libcommon/talloc_ctx.c
+++ b/src/libcommon/talloc_ctx.c
@@ -1,4 +1,4 @@
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/gsm_data.h>
 
 extern void *tall_msgb_ctx;
diff --git a/src/libgb/Makefile.am b/src/libgb/Makefile.am
index b48b177..8ec1006 100644
--- a/src/libgb/Makefile.am
+++ b/src/libgb/Makefile.am
@@ -1,6 +1,6 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
 AM_CFLAGS=-Wall -fno-strict-aliasing $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOCORE_GSM) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
 
 noinst_LIBRARIES = libgb.a
 
diff --git a/src/libgb/Makefile.in b/src/libgb/Makefile.in
index 7b9dbd9..c21201c 100644
--- a/src/libgb/Makefile.in
+++ b/src/libgb/Makefile.in
@@ -35,7 +35,7 @@
 subdir = src/libgb
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -112,6 +112,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -182,7 +184,7 @@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
 AM_CFLAGS = -Wall -fno-strict-aliasing $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOCORE_GSM) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
 noinst_LIBRARIES = libgb.a
 libgb_a_SOURCES = gprs_ns.c gprs_ns_frgre.c gprs_ns_vty.c \
 		  gprs_bssgp.c gprs_bssgp_util.c gprs_bssgp_vty.c
diff --git a/src/libgb/gprs_bssgp.c b/src/libgb/gprs_bssgp.c
index eca34b9..b74791c 100644
--- a/src/libgb/gprs_bssgp.c
+++ b/src/libgb/gprs_bssgp.c
@@ -27,10 +27,10 @@
 
 #include <netinet/in.h>
 
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.h>
-#include <osmocore/talloc.h>
-#include <osmocore/rate_ctr.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/tlv.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/rate_ctr.h>
 
 #include <openbsc/debug.h>
 #include <openbsc/gsm_data.h>
diff --git a/src/libgb/gprs_bssgp_util.c b/src/libgb/gprs_bssgp_util.c
index f8e3b56..b539323 100644
--- a/src/libgb/gprs_bssgp_util.c
+++ b/src/libgb/gprs_bssgp_util.c
@@ -24,9 +24,9 @@
 
 #include <netinet/in.h>
 
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/tlv.h>
+#include <osmocom/core/talloc.h>
 
 #include <openbsc/debug.h>
 #include <openbsc/gsm_data.h>
diff --git a/src/libgb/gprs_bssgp_vty.c b/src/libgb/gprs_bssgp_vty.c
index 9ebd090..a0d74ac 100644
--- a/src/libgb/gprs_bssgp_vty.c
+++ b/src/libgb/gprs_bssgp_vty.c
@@ -27,11 +27,11 @@
 #include <arpa/inet.h>
 
 #include <openbsc/gsm_data.h>
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.h>
-#include <osmocore/talloc.h>
-#include <osmocore/select.h>
-#include <osmocore/rate_ctr.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_ns.h>
@@ -42,6 +42,7 @@
 #include <osmocom/vty/command.h>
 #include <osmocom/vty/logging.h>
 #include <osmocom/vty/telnet_interface.h>
+#include <osmocom/vty/misc.h>
 
 /* FIXME: this should go to some common file as it is copied
  * in vty_interface.c of the BSC */
diff --git a/src/libgb/gprs_ns.c b/src/libgb/gprs_ns.c
index 5a8e358..dab57e6 100644
--- a/src/libgb/gprs_ns.c
+++ b/src/libgb/gprs_ns.c
@@ -59,11 +59,11 @@
 #include <arpa/inet.h>
 
 #include <openbsc/gsm_data.h>
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.h>
-#include <osmocore/talloc.h>
-#include <osmocore/select.h>
-#include <osmocore/rate_ctr.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_ns.h>
@@ -166,13 +166,13 @@
 
 void nsvc_delete(struct gprs_nsvc *nsvc)
 {
-	if (bsc_timer_pending(&nsvc->timer))
-		bsc_del_timer(&nsvc->timer);
+	if (osmo_timer_pending(&nsvc->timer))
+		osmo_timer_del(&nsvc->timer);
 	llist_del(&nsvc->list);
 	talloc_free(nsvc);
 }
 
-static void ns_dispatch_signal(struct gprs_nsvc *nsvc, unsigned int signal,
+static void ns_osmo_signal_dispatch(struct gprs_nsvc *nsvc, unsigned int signal,
 			       uint8_t cause)
 {
 	struct ns_signal_data nssd;
@@ -180,7 +180,7 @@
 	nssd.nsvc = nsvc;
 	nssd.cause = cause;
 
-	dispatch_signal(SS_NS, signal, &nssd);
+	osmo_signal_dispatch(SS_NS, signal, &nssd);
 }
 
 /* Section 10.3.2, Table 13 */
@@ -405,11 +405,11 @@
 		nsvc->nsei, get_value_string(timer_mode_strs, mode),
 		seconds);
 		
-	if (bsc_timer_pending(&nsvc->timer))
-		bsc_del_timer(&nsvc->timer);
+	if (osmo_timer_pending(&nsvc->timer))
+		osmo_timer_del(&nsvc->timer);
 
 	nsvc->timer_mode = mode;
-	bsc_schedule_timer(&nsvc->timer, seconds, 0);
+	osmo_timer_schedule(&nsvc->timer, seconds, 0);
 }
 
 static void gprs_ns_timer_cb(void *data)
@@ -437,8 +437,8 @@
 				"NSEI=%u Tns-alive expired more then "
 				"%u times, blocking NS-VC\n", nsvc->nsei,
 				nsvc->nsi->timeout[NS_TOUT_TNS_ALIVE_RETRIES]);
-			ns_dispatch_signal(nsvc, S_NS_ALIVE_EXP, 0);
-			ns_dispatch_signal(nsvc, S_NS_BLOCK, NS_CAUSE_NSVC_BLOCKED);
+			ns_osmo_signal_dispatch(nsvc, S_NS_ALIVE_EXP, 0);
+			ns_osmo_signal_dispatch(nsvc, S_NS_BLOCK, NS_CAUSE_NSVC_BLOCKED);
 			return;
 		}
 		/* Tns-test case: send NS-ALIVE PDU */
@@ -631,7 +631,7 @@
 
 	/* inform interested parties about the fact that this NSVC
 	 * has received RESET */
-	ns_dispatch_signal(nsvc, S_NS_RESET, *cause);
+	ns_osmo_signal_dispatch(nsvc, S_NS_RESET, *cause);
 
 	return gprs_ns_tx_reset_ack(nsvc);
 }
@@ -665,7 +665,7 @@
 	cause = (uint8_t *) TLVP_VAL(&tp, NS_IE_CAUSE);
 	//nsvci = (uint16_t *) TLVP_VAL(&tp, NS_IE_VCI);
 
-	ns_dispatch_signal(nsvc, S_NS_BLOCK, *cause);
+	ns_osmo_signal_dispatch(nsvc, S_NS_BLOCK, *cause);
 	rate_ctr_inc(&nsvc->ctrg->ctr[NS_CTR_BLOCKED]);
 
 	return gprs_ns_tx_simple(nsvc, NS_PDUT_BLOCK_ACK);
@@ -786,7 +786,7 @@
 		rate_ctr_inc(&nsvc->ctrg->ctr[NS_CTR_BLOCKED]);
 		if (nsvc->persistent || nsvc->remote_end_is_sgsn) {
 			/* stop RESET timer */
-			bsc_del_timer(&nsvc->timer);
+			osmo_timer_del(&nsvc->timer);
 		}
 		/* Initiate TEST proc.: Send ALIVE and start timer */
 		rc = gprs_ns_tx_simple(nsvc, NS_PDUT_ALIVE);
@@ -796,7 +796,7 @@
 		/* Section 7.2: unblocking procedure */
 		LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS UNBLOCK\n", nsvc->nsei);
 		nsvc->state &= ~NSE_S_BLOCKED;
-		ns_dispatch_signal(nsvc, S_NS_UNBLOCK, 0);
+		ns_osmo_signal_dispatch(nsvc, S_NS_UNBLOCK, 0);
 		rc = gprs_ns_tx_simple(nsvc, NS_PDUT_UNBLOCK_ACK);
 		break;
 	case NS_PDUT_UNBLOCK_ACK:
@@ -804,7 +804,7 @@
 		/* mark NS-VC as unblocked + active */
 		nsvc->state = NSE_S_ALIVE;
 		nsvc->remote_state = NSE_S_ALIVE;
-		ns_dispatch_signal(nsvc, S_NS_UNBLOCK, 0);
+		ns_osmo_signal_dispatch(nsvc, S_NS_UNBLOCK, 0);
 		break;
 	case NS_PDUT_BLOCK:
 		rc = gprs_ns_rx_block(nsvc, msg);
@@ -858,7 +858,7 @@
  * We don't support Size Procedure, Configuration Procedure, ChangeWeight Procedure */
 
 /* Read a single NS-over-IP message */
-static struct msgb *read_nsip_msg(struct bsc_fd *bfd, int *error,
+static struct msgb *read_nsip_msg(struct osmo_fd *bfd, int *error,
 				  struct sockaddr_in *saddr)
 {
 	struct msgb *msg = gprs_ns_msgb_alloc();
@@ -890,7 +890,7 @@
 	return msg;
 }
 
-static int handle_nsip_read(struct bsc_fd *bfd)
+static int handle_nsip_read(struct osmo_fd *bfd)
 {
 	int error;
 	struct sockaddr_in saddr;
@@ -907,7 +907,7 @@
 	return error;
 }
 
-static int handle_nsip_write(struct bsc_fd *bfd)
+static int handle_nsip_write(struct osmo_fd *bfd)
 {
 	/* FIXME: actually send the data here instead of nsip_sendmsg() */
 	return -EIO;
@@ -928,7 +928,7 @@
 }
 
 /* UDP Port 23000 carries the LLC-in-BSSGP-in-NS protocol stack */
-static int nsip_fd_cb(struct bsc_fd *bfd, unsigned int what)
+static int nsip_fd_cb(struct osmo_fd *bfd, unsigned int what)
 {
 	int rc = 0;
 
@@ -946,7 +946,7 @@
 	int ret;
 
 	ret = make_sock(&nsi->nsip.fd, IPPROTO_UDP, nsi->nsip.local_ip,
-			nsi->nsip.local_port, nsip_fd_cb);
+			nsi->nsip.local_port, 0, nsip_fd_cb, NULL);
 	if (ret < 0)
 		return ret;
 
diff --git a/src/libgb/gprs_ns_frgre.c b/src/libgb/gprs_ns_frgre.c
index 106f410..3662572 100644
--- a/src/libgb/gprs_ns_frgre.c
+++ b/src/libgb/gprs_ns_frgre.c
@@ -31,9 +31,9 @@
 #include <netinet/ip.h>
 #include <arpa/inet.h>
 
-#include <osmocore/select.h>
-#include <osmocore/msgb.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/talloc.h>
 
 #include <openbsc/socket.h>
 #include <openbsc/debug.h>
@@ -49,7 +49,7 @@
 } __attribute__ ((packed));
 
 /* IPv4 messages inside the GRE tunnel might be GRE keepalives */
-static int handle_rx_gre_ipv4(struct bsc_fd *bfd, struct msgb *msg,
+static int handle_rx_gre_ipv4(struct osmo_fd *bfd, struct msgb *msg,
 				struct iphdr *iph, struct gre_hdr *greh)
 {
 	struct gprs_ns_inst *nsi = bfd->data;
@@ -101,7 +101,7 @@
 		      (struct sockaddr *)&daddr, sizeof(daddr));
 }
 
-static struct msgb *read_nsfrgre_msg(struct bsc_fd *bfd, int *error,
+static struct msgb *read_nsfrgre_msg(struct osmo_fd *bfd, int *error,
 					struct sockaddr_in *saddr)
 {
 	struct msgb *msg = msgb_alloc(NS_ALLOC_SIZE, "Gb/NS/FR/GRE Rx");
@@ -203,7 +203,7 @@
 int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
 		   struct sockaddr_in *saddr, enum gprs_ns_ll ll);
 
-static int handle_nsfrgre_read(struct bsc_fd *bfd)
+static int handle_nsfrgre_read(struct osmo_fd *bfd)
 {
 	int rc;
 	struct sockaddr_in saddr;
@@ -230,7 +230,7 @@
 	return rc;
 }
 
-static int handle_nsfrgre_write(struct bsc_fd *bfd)
+static int handle_nsfrgre_write(struct osmo_fd *bfd)
 {
 	/* FIXME: actually send the data here instead of nsip_sendmsg() */
 	return -EIO;
@@ -268,7 +268,7 @@
 	return rc;
 }
 
-static int nsfrgre_fd_cb(struct bsc_fd *bfd, unsigned int what)
+static int nsfrgre_fd_cb(struct osmo_fd *bfd, unsigned int what)
 {
 	int rc = 0;
 
@@ -292,7 +292,7 @@
 		return 0;
 
 	rc = make_sock(&nsi->frgre.fd, IPPROTO_GRE, nsi->frgre.local_ip,
-			0, nsfrgre_fd_cb);
+			0, 0, nsfrgre_fd_cb, NULL);
 	if (rc < 0) {
 		LOGP(DNS, LOGL_ERROR, "Error creating GRE socket (%s)\n",
 			strerror(errno));
diff --git a/src/libgb/gprs_ns_vty.c b/src/libgb/gprs_ns_vty.c
index 39277fc..14d7691 100644
--- a/src/libgb/gprs_ns_vty.c
+++ b/src/libgb/gprs_ns_vty.c
@@ -27,11 +27,11 @@
 #include <arpa/inet.h>
 
 #include <openbsc/gsm_data.h>
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.h>
-#include <osmocore/talloc.h>
-#include <osmocore/select.h>
-#include <osmocore/rate_ctr.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_ns.h>
@@ -42,6 +42,7 @@
 #include <osmocom/vty/command.h>
 #include <osmocom/vty/logging.h>
 #include <osmocom/vty/telnet_interface.h>
+#include <osmocom/vty/misc.h>
 
 static struct gprs_ns_inst *vty_nsi = NULL;
 
diff --git a/src/libmgcp/Makefile.am b/src/libmgcp/Makefile.am
index b1d1d15..6347eac 100644
--- a/src/libmgcp/Makefile.am
+++ b/src/libmgcp/Makefile.am
@@ -1,6 +1,6 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
 AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 
 noinst_LIBRARIES = libmgcp.a
 
diff --git a/src/libmgcp/Makefile.in b/src/libmgcp/Makefile.in
index 942aeea..8966384 100644
--- a/src/libmgcp/Makefile.in
+++ b/src/libmgcp/Makefile.in
@@ -35,7 +35,7 @@
 subdir = src/libmgcp
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -111,6 +111,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -181,7 +183,7 @@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
 AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 noinst_LIBRARIES = libmgcp.a
 libmgcp_a_SOURCES = mgcp_protocol.c mgcp_network.c mgcp_vty.c
 all: all-am
diff --git a/src/libmgcp/mgcp_network.c b/src/libmgcp/mgcp_network.c
index 51c08d1..9ff2943 100644
--- a/src/libmgcp/mgcp_network.c
+++ b/src/libmgcp/mgcp_network.c
@@ -29,17 +29,15 @@
 #include <sys/socket.h>
 #include <arpa/inet.h>
 
-#include <osmocore/msgb.h>
-#include <osmocore/select.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/select.h>
 
-#include <openbsc/debug.h>
 #include <openbsc/mgcp.h>
 #include <openbsc/mgcp_internal.h>
 
 #warning "Make use of the rtp proxy code"
 
 /* attempt to determine byte order */
-#include <sys/types.h>
 #include <sys/param.h>
 #include <limits.h>
 
@@ -234,8 +232,8 @@
 	}
 }
 
-static int recevice_from(struct mgcp_endpoint *endp, int fd, struct sockaddr_in *addr,
-			 char *buf, int bufsize)
+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);
@@ -257,7 +255,7 @@
 	return rc;
 }
 
-static int rtp_data_net(struct bsc_fd *fd, unsigned int what)
+static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
 {
 	char buf[4096];
 	struct sockaddr_in addr;
@@ -266,7 +264,7 @@
 
 	endp = (struct mgcp_endpoint *) fd->data;
 
-	rc = recevice_from(endp, fd->fd, &addr, buf, sizeof(buf));
+	rc = receive_from(endp, fd->fd, &addr, buf, sizeof(buf));
 	if (rc <= 0)
 		return -1;
 
@@ -329,7 +327,7 @@
 	}
 }
 
-static int rtp_data_bts(struct bsc_fd *fd, unsigned int what)
+static int rtp_data_bts(struct osmo_fd *fd, unsigned int what)
 {
 	char buf[4096];
 	struct sockaddr_in addr;
@@ -340,7 +338,7 @@
 	endp = (struct mgcp_endpoint *) fd->data;
 	cfg = endp->cfg;
 
-	rc = recevice_from(endp, fd->fd, &addr, buf, sizeof(buf));
+	rc = receive_from(endp, fd->fd, &addr, buf, sizeof(buf));
 	if (rc <= 0)
 		return -1;
 
@@ -383,7 +381,7 @@
 }
 
 static int rtp_data_transcoder(struct mgcp_rtp_end *end, struct mgcp_endpoint *_endp,
-			      int dest, struct bsc_fd *fd)
+			      int dest, struct osmo_fd *fd)
 {
 	char buf[4096];
 	struct sockaddr_in addr;
@@ -391,7 +389,7 @@
 	int rc, proto;
 
 	cfg = _endp->cfg;
-	rc = recevice_from(_endp, fd->fd, &addr, buf, sizeof(buf));
+	rc = receive_from(_endp, fd->fd, &addr, buf, sizeof(buf));
 	if (rc <= 0)
 		return -1;
 
@@ -423,7 +421,7 @@
 	return send_to(_endp, dest, proto == PROTO_RTP, &addr, &buf[0], rc);
 }
 
-static int rtp_data_trans_net(struct bsc_fd *fd, unsigned int what)
+static int rtp_data_trans_net(struct osmo_fd *fd, unsigned int what)
 {
 	struct mgcp_endpoint *endp;
 	endp = (struct mgcp_endpoint *) fd->data;
@@ -431,7 +429,7 @@
 	return rtp_data_transcoder(&endp->trans_net, endp, DEST_NETWORK, fd);
 }
 
-static int rtp_data_trans_bts(struct bsc_fd *fd, unsigned int what)
+static int rtp_data_trans_bts(struct osmo_fd *fd, unsigned int what)
 {
 	struct mgcp_endpoint *endp;
 	endp = (struct mgcp_endpoint *) fd->data;
@@ -439,7 +437,7 @@
 	return rtp_data_transcoder(&endp->trans_bts, endp, DEST_BTS, fd);
 }
 
-static int create_bind(const char *source_addr, struct bsc_fd *fd, int port)
+static int create_bind(const char *source_addr, struct osmo_fd *fd, int port)
 {
 	struct sockaddr_in addr;
 	int on = 1;
@@ -491,14 +489,14 @@
 	set_ip_tos(rtp_end->rtcp.fd, cfg->endp_dscp);
 
 	rtp_end->rtp.when = BSC_FD_READ;
-	if (bsc_register_fd(&rtp_end->rtp) != 0) {
+	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 (bsc_register_fd(&rtp_end->rtcp) != 0) {
+	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;
@@ -507,7 +505,7 @@
 	return 0;
 
 cleanup3:
-	bsc_unregister_fd(&rtp_end->rtp);
+	osmo_fd_unregister(&rtp_end->rtp);
 cleanup2:
 	close(rtp_end->rtcp.fd);
 	rtp_end->rtcp.fd = -1;
@@ -519,7 +517,7 @@
 }
 
 static int int_bind(const char *port,
-		    struct mgcp_rtp_end *end, int (*cb)(struct bsc_fd *, unsigned),
+		    struct mgcp_rtp_end *end, int (*cb)(struct osmo_fd *, unsigned),
 		    struct mgcp_endpoint *_endp, int rtp_port)
 {
 	if (end->rtp.fd != -1 || end->rtcp.fd != -1) {
@@ -566,13 +564,13 @@
 	if (end->rtp.fd != -1) {
 		close(end->rtp.fd);
 		end->rtp.fd = -1;
-		bsc_unregister_fd(&end->rtp);
+		osmo_fd_unregister(&end->rtp);
 	}
 
 	if (end->rtcp.fd != -1) {
 		close(end->rtcp.fd);
 		end->rtcp.fd = -1;
-		bsc_unregister_fd(&end->rtcp);
+		osmo_fd_unregister(&end->rtcp);
 	}
 
 	return 0;
diff --git a/src/libmgcp/mgcp_protocol.c b/src/libmgcp/mgcp_protocol.c
index ba290dd..1d26850 100644
--- a/src/libmgcp/mgcp_protocol.c
+++ b/src/libmgcp/mgcp_protocol.c
@@ -29,11 +29,10 @@
 #include <limits.h>
 #include <unistd.h>
 
-#include <openbsc/debug.h>
-#include <osmocore/msgb.h>
-#include <osmocore/talloc.h>
-#include <openbsc/gsm_data.h>
-#include <osmocore/select.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>
 
@@ -605,7 +604,7 @@
 	return create_response_with_sdp(endp, "CRCX", trans_id);
 error:
 	LOGP(DMGCP, LOGL_ERROR, "Malformed line: %s on 0x%x with: line_start: %d %d\n",
-		    hexdump(msg->l3h, msgb_l3len(msg)),
+		    osmo_hexdump(msg->l3h, msgb_l3len(msg)),
 		    ENDPOINT_NUMBER(endp), line_start, i);
 	return create_err_response(error_code, "CRCX", trans_id);
 
@@ -730,7 +729,7 @@
 
 error:
 	LOGP(DMGCP, LOGL_ERROR, "Malformed line: %s on 0x%x with: line_start: %d %d %d\n",
-		    hexdump(msg->l3h, msgb_l3len(msg)),
+		    osmo_hexdump(msg->l3h, msgb_l3len(msg)),
 		    ENDPOINT_NUMBER(endp), line_start, i, msg->l3h[line_start]);
 	return create_err_response(error_code, "MDCX", trans_id);
 
@@ -819,7 +818,7 @@
 
 error:
 	LOGP(DMGCP, LOGL_ERROR, "Malformed line: %s on 0x%x with: line_start: %d %d\n",
-		    hexdump(msg->l3h, msgb_l3len(msg)),
+		    osmo_hexdump(msg->l3h, msgb_l3len(msg)),
 		    ENDPOINT_NUMBER(endp), line_start, i);
 	return create_err_response(error_code, "DLCX", trans_id);
 
diff --git a/src/libmgcp/mgcp_vty.c b/src/libmgcp/mgcp_vty.c
index c299a98..0b7a97e 100644
--- a/src/libmgcp/mgcp_vty.c
+++ b/src/libmgcp/mgcp_vty.c
@@ -21,18 +21,13 @@
  *
  */
 
-#include <sys/types.h>
 
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 
-#include <openbsc/debug.h>
 #include <openbsc/mgcp.h>
 #include <openbsc/mgcp_internal.h>
 #include <openbsc/vty.h>
 
-#include <osmocom/vty/command.h>
-#include <osmocom/vty/vty.h>
-
 #include <string.h>
 
 static struct mgcp_config *g_cfg = NULL;
diff --git a/src/libmsc/Makefile.am b/src/libmsc/Makefile.am
index 7d895c3..8d5034c 100644
--- a/src/libmsc/Makefile.am
+++ b/src/libmsc/Makefile.am
@@ -1,6 +1,6 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
 AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_CFLAGS) $(COVERAGE_LDFLAGS)
 
 noinst_LIBRARIES = libmsc.a
 
@@ -15,5 +15,6 @@
 			token_auth.c \
 			ussd.c \
 			vty_interface_layer3.c \
+			transaction.c \
 			osmo_msc.c
 
diff --git a/src/libmsc/Makefile.in b/src/libmsc/Makefile.in
index 1ebc032..2214259 100644
--- a/src/libmsc/Makefile.in
+++ b/src/libmsc/Makefile.in
@@ -35,7 +35,7 @@
 subdir = src/libmsc
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -58,7 +58,8 @@
 	gsm_subscriber.$(OBJEXT) mncc.$(OBJEXT) mncc_builtin.$(OBJEXT) \
 	mncc_sock.$(OBJEXT) rrlp.$(OBJEXT) silent_call.$(OBJEXT) \
 	sms_queue.$(OBJEXT) token_auth.$(OBJEXT) ussd.$(OBJEXT) \
-	vty_interface_layer3.$(OBJEXT) osmo_msc.$(OBJEXT)
+	vty_interface_layer3.$(OBJEXT) transaction.$(OBJEXT) \
+	osmo_msc.$(OBJEXT)
 libmsc_a_OBJECTS = $(am_libmsc_a_OBJECTS)
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -115,6 +116,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -185,7 +188,7 @@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
 AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_CFLAGS) $(COVERAGE_LDFLAGS)
 noinst_LIBRARIES = libmsc.a
 libmsc_a_SOURCES = auth.c \
 			db.c \
@@ -198,6 +201,7 @@
 			token_auth.c \
 			ussd.c \
 			vty_interface_layer3.c \
+			transaction.c \
 			osmo_msc.c
 
 all: all-am
@@ -262,6 +266,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/silent_call.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sms_queue.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/token_auth.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transaction.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ussd.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vty_interface_layer3.Po@am__quote@
 
diff --git a/src/libmsc/auth.c b/src/libmsc/auth.c
index e09bde5..10d8edf 100644
--- a/src/libmsc/auth.c
+++ b/src/libmsc/auth.c
@@ -25,7 +25,7 @@
 #include <openbsc/auth.h>
 #include <openbsc/gsm_data.h>
 
-#include <osmocore/comp128.h>
+#include <osmocom/gsm/comp128.h>
 
 #include <stdlib.h>
 
@@ -38,7 +38,7 @@
 	if ((l > A38_XOR_MAX_KEY_LEN) || (l < A38_XOR_MIN_KEY_LEN)) {
 		LOGP(DMM, LOGL_ERROR, "Invalid XOR key (len=%d) %s\n",
 			ainfo->a3a8_ki_len,
-			hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
+			osmo_hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
 		return -1;
 	}
 
@@ -56,7 +56,7 @@
 	if (ainfo->a3a8_ki_len != A38_COMP128_KEY_LEN) {
 		LOGP(DMM, LOGL_ERROR, "Invalid COMP128v1 key (len=%d) %s\n",
 			ainfo->a3a8_ki_len,
-			hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
+			osmo_hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
 		return -1;
 	}
 
diff --git a/src/libmsc/db.c b/src/libmsc/db.c
index 95a7d36..1ddd3fd 100644
--- a/src/libmsc/db.c
+++ b/src/libmsc/db.c
@@ -34,9 +34,9 @@
 #include <openbsc/db.h>
 #include <openbsc/debug.h>
 
-#include <osmocore/talloc.h>
-#include <osmocore/statistics.h>
-#include <osmocore/rate_ctr.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/statistics.h>
+#include <osmocom/core/rate_ctr.h>
 
 static char *db_basename = NULL;
 static char *db_dirname = NULL;
@@ -297,7 +297,7 @@
 	return subscr;
 }
 
-static_assert(sizeof(unsigned char) == sizeof(struct gsm48_classmark1), classmark1_size);
+osmo_static_assert(sizeof(unsigned char) == sizeof(struct gsm48_classmark1), classmark1_size);
 
 static int get_equipment_by_subscr(struct gsm_subscriber *subscr)
 {
@@ -737,17 +737,17 @@
 	dbi_result result;
 	unsigned char *cm2, *cm3;
 	char *q_imei;
-	u_int8_t classmark1;
+	uint8_t classmark1;
 
 	memcpy(&classmark1, &equip->classmark1, sizeof(classmark1));
 	DEBUGP(DDB, "Sync Equipment IMEI=%s, classmark1=%02x",
 		equip->imei, classmark1);
 	if (equip->classmark2_len)
 		DEBUGPC(DDB, ", classmark2=%s",
-			hexdump(equip->classmark2, equip->classmark2_len));
+			osmo_hexdump(equip->classmark2, equip->classmark2_len));
 	if (equip->classmark3_len)
 		DEBUGPC(DDB, ", classmark3=%s",
-			hexdump(equip->classmark3, equip->classmark3_len));
+			osmo_hexdump(equip->classmark3, equip->classmark3_len));
 	DEBUGPC(DDB, "\n");
 
 	dbi_conn_quote_binary_copy(conn, equip->classmark2,
@@ -821,7 +821,7 @@
 int db_subscriber_alloc_exten(struct gsm_subscriber *subscriber)
 {
 	dbi_result result = NULL;
-	u_int32_t try;
+	uint32_t try;
 
 	for (;;) {
 		try = (rand()%(GSM_MAX_EXTEN-GSM_MIN_EXTEN+1)+GSM_MIN_EXTEN);
@@ -855,10 +855,10 @@
  * an error.
  */
 
-int db_subscriber_alloc_token(struct gsm_subscriber *subscriber, u_int32_t *token)
+int db_subscriber_alloc_token(struct gsm_subscriber *subscriber, uint32_t *token)
 {
 	dbi_result result;
-	u_int32_t try;
+	uint32_t try;
 
 	for (;;) {
 		try = rand();
@@ -1060,7 +1060,7 @@
 	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 = (u_int8_t) 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");
@@ -1219,8 +1219,8 @@
 }
 
 int db_apdu_blob_store(struct gsm_subscriber *subscr,
-			u_int8_t apdu_id_flags, u_int8_t len,
-			u_int8_t *apdu)
+			uint8_t apdu_id_flags, uint8_t len,
+			uint8_t *apdu)
 {
 	dbi_result result;
 	unsigned char *q_apdu;
@@ -1242,7 +1242,7 @@
 	return 0;
 }
 
-int db_store_counter(struct counter *ctr)
+int db_store_counter(struct osmo_counter *ctr)
 {
 	dbi_result result;
 	char *q_name;
diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c
index 2b61aa9..a6ed3e8 100644
--- a/src/libmsc/gsm_04_08.c
+++ b/src/libmsc/gsm_04_08.c
@@ -49,31 +49,31 @@
 #include <openbsc/silent_call.h>
 #include <openbsc/bsc_api.h>
 #include <openbsc/osmo_msc.h>
-#include <osmocore/bitvec.h>
+#include <osmocom/core/bitvec.h>
 
-#include <osmocore/gsm48.h>
-#include <osmocore/gsm0480.h>
-#include <osmocore/gsm_utils.h>
-#include <osmocore/msgb.h>
-#include <osmocore/talloc.h>
-#include <osmocore/tlv.h>
+#include <osmocom/gsm/gsm48.h>
+#include <osmocom/gsm/gsm0480.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/gsm/tlv.h>
 
 void *tall_locop_ctx;
 void *tall_authciphop_ctx;
 
-int gsm0408_loc_upd_acc(struct gsm_subscriber_connection *conn, u_int32_t tmsi);
+int gsm0408_loc_upd_acc(struct gsm_subscriber_connection *conn, uint32_t tmsi);
 static int gsm48_tx_simple(struct gsm_subscriber_connection *conn,
-			   u_int8_t pdisc, u_int8_t msg_type);
+			   uint8_t pdisc, uint8_t msg_type);
 static void schedule_reject(struct gsm_subscriber_connection *conn);
 static void release_anchor(struct gsm_subscriber_connection *conn);
 
 struct gsm_lai {
-	u_int16_t mcc;
-	u_int16_t mnc;
-	u_int16_t lac;
+	uint16_t mcc;
+	uint16_t mnc;
+	uint16_t lac;
 };
 
-static u_int32_t new_callref = 0x80000001;
+static uint32_t new_callref = 0x80000001;
 
 void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg)
 {
@@ -243,7 +243,7 @@
 	/* No need to keep the connection up */
 	release_anchor(conn);
 
-	bsc_del_timer(&conn->loc_operation->updating_timer);
+	osmo_timer_del(&conn->loc_operation->updating_timer);
 	talloc_free(conn->loc_operation);
 	conn->loc_operation = NULL;
 	msc_release_connection(conn);
@@ -356,12 +356,12 @@
 }
 
 /* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
-int gsm0408_loc_upd_rej(struct gsm_subscriber_connection *conn, u_int8_t cause)
+int gsm0408_loc_upd_rej(struct gsm_subscriber_connection *conn, uint8_t cause)
 {
 	struct gsm_bts *bts = conn->bts;
 	struct msgb *msg;
 
-	counter_inc(bts->network->stats.loc_upd_resp.reject);
+	osmo_counter_inc(bts->network->stats.loc_upd_resp.reject);
 
 	msg = gsm48_create_loc_upd_rej(cause);
 	if (!msg) {
@@ -380,13 +380,13 @@
 }
 
 /* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
-int gsm0408_loc_upd_acc(struct gsm_subscriber_connection *conn, u_int32_t tmsi)
+int gsm0408_loc_upd_acc(struct gsm_subscriber_connection *conn, uint32_t tmsi)
 {
 	struct gsm_bts *bts = conn->bts;
 	struct msgb *msg = gsm48_msgb_alloc();
 	struct gsm48_hdr *gh;
 	struct gsm48_loc_area_id *lai;
-	u_int8_t *mid;
+	uint8_t *mid;
 	
 	msg->lchan = conn->lchan;
 
@@ -403,13 +403,13 @@
 
 	DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
 
-	counter_inc(bts->network->stats.loc_upd_resp.accept);
+	osmo_counter_inc(bts->network->stats.loc_upd_resp.accept);
 
 	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, u_int8_t id_type)
+static int mm_tx_identity_req(struct gsm_subscriber_connection *conn, uint8_t id_type)
 {
 	struct msgb *msg = gsm48_msgb_alloc();
 	struct gsm48_hdr *gh;
@@ -432,14 +432,14 @@
 	struct gsm_lchan *lchan = msg->lchan;
 	struct gsm_bts *bts = lchan->ts->trx->bts;
 	struct gsm_network *net = bts->network;
-	u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
+	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]);
 	DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
 		mi_type, mi_string);
 
-	dispatch_signal(SS_SUBSCR, S_SUBSCR_IDENTITY, gh->data);
+	osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_IDENTITY, gh->data);
 
 	switch (mi_type) {
 	case GSM_MI_TYPE_IMSI:
@@ -483,10 +483,10 @@
 {
 	conn->loc_operation->updating_timer.cb = loc_upd_rej_cb;
 	conn->loc_operation->updating_timer.data = conn;
-	bsc_schedule_timer(&conn->loc_operation->updating_timer, 5, 0);
+	osmo_timer_schedule(&conn->loc_operation->updating_timer, 5, 0);
 }
 
-static const char *lupd_name(u_int8_t type)
+static const char *lupd_name(uint8_t type)
 {
 	switch (type) {
 	case GSM48_LUPD_NORMAL:
@@ -507,7 +507,7 @@
 	struct gsm48_loc_upd_req *lu;
 	struct gsm_subscriber *subscr = NULL;
 	struct gsm_bts *bts = conn->bts;
-	u_int8_t mi_type;
+	uint8_t mi_type;
 	char mi_string[GSM48_MI_SIZE];
 	int rc;
 
@@ -520,17 +520,17 @@
 	DEBUGPC(DMM, "mi_type=0x%02x MI(%s) type=%s ", mi_type, mi_string,
 		lupd_name(lu->type));
 
-	dispatch_signal(SS_SUBSCR, S_SUBSCR_IDENTITY, &lu->mi_len);
+	osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_IDENTITY, &lu->mi_len);
 
 	switch (lu->type) {
 	case GSM48_LUPD_NORMAL:
-		counter_inc(bts->network->stats.loc_upd_type.normal);
+		osmo_counter_inc(bts->network->stats.loc_upd_type.normal);
 		break;
 	case GSM48_LUPD_IMSI_ATT:
-		counter_inc(bts->network->stats.loc_upd_type.attach);
+		osmo_counter_inc(bts->network->stats.loc_upd_type.attach);
 		break;
 	case GSM48_LUPD_PERIODIC:
-		counter_inc(bts->network->stats.loc_upd_type.periodic);
+		osmo_counter_inc(bts->network->stats.loc_upd_type.periodic);
 		break;
 	}
 
@@ -604,7 +604,7 @@
 }
 
 #if 0
-static u_int8_t to_bcd8(u_int8_t val)
+static uint8_t to_bcd8(uint8_t val)
 {
        return ((val / 10) << 4) | (val % 10);
 }
@@ -616,7 +616,7 @@
 	struct msgb *msg = gsm48_msgb_alloc();
 	struct gsm48_hdr *gh;
 	struct gsm_network *net = conn->bts->network;
-	u_int8_t *ptr8;
+	uint8_t *ptr8;
 	int name_len, name_pad;
 #if 0
 	time_t cur_t;
@@ -639,7 +639,7 @@
 		ptr8[1] = name_len*2 +1;
 		ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
 
-		ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
+		ptr16 = (uint16_t *) msgb_put(msg, name_len*2);
 		for (i = 0; i < name_len; i++)
 			ptr16[i] = htons(net->name_long[i]);
 
@@ -665,12 +665,12 @@
 #if 0
 		name_len = strlen(net->name_short);
 		/* 10.5.3.5a */
-		ptr8 = (u_int8_t *) msgb_put(msg, 3);
+		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 = (u_int16_t *) msgb_put(msg, name_len*2);
+		ptr16 = (uint16_t *) msgb_put(msg, name_len*2);
 		for (i = 0; i < name_len; i++)
 			ptr16[i] = htons(net->name_short[i]);
 #endif
@@ -679,7 +679,7 @@
 		if (name_pad > 0)
 			name_len++;
 		/* 10.5.3.5a */
-		ptr8 = (u_int8_t *) msgb_put(msg, 3);
+		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 */
@@ -714,13 +714,13 @@
 }
 
 /* Section 9.2.2 */
-int gsm48_tx_mm_auth_req(struct gsm_subscriber_connection *conn, u_int8_t *rand, int key_seq)
+int gsm48_tx_mm_auth_req(struct gsm_subscriber_connection *conn, uint8_t *rand, int key_seq)
 {
 	struct msgb *msg = gsm48_msgb_alloc();
 	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", hexdump(rand, 16));
+	DEBUGP(DMM, "-> AUTH REQ (rand = %s)\n", osmo_hexdump(rand, 16));
 
 	msg->lchan = conn->lchan;
 	gh->proto_discr = GSM48_PDISC_MM;
@@ -804,7 +804,7 @@
  */
 static int gsm48_rx_mm_serv_req(struct gsm_subscriber_connection *conn, struct msgb *msg)
 {
-	u_int8_t mi_type;
+	uint8_t mi_type;
 	char mi_string[GSM48_MI_SIZE];
 
 	struct gsm_bts *bts = conn->bts;
@@ -813,10 +813,10 @@
 	struct gsm48_service_request *req =
 			(struct gsm48_service_request *)gh->data;
 	/* unfortunately in Phase1 the classmark2 length is variable */
-	u_int8_t classmark2_len = gh->data[1];
-	u_int8_t *classmark2 = gh->data+2;
-	u_int8_t mi_len = *(classmark2 + classmark2_len);
-	u_int8_t *mi = (classmark2 + classmark2_len + 1);
+	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);
 
 	DEBUGP(DMM, "<- CM SERVICE REQUEST ");
 	if (msg->data_len < sizeof(struct gsm48_service_request*)) {
@@ -842,7 +842,7 @@
 	DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
 		req->cm_service_type, mi_type, mi_string);
 
-	dispatch_signal(SS_SUBSCR, S_SUBSCR_IDENTITY, (classmark2 + classmark2_len));
+	osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_IDENTITY, (classmark2 + classmark2_len));
 
 	if (is_siemens_bts(bts))
 		send_siemens_mrpci(msg->lchan, classmark2-1);
@@ -878,7 +878,7 @@
 	struct gsm48_hdr *gh = msgb_l3(msg);
 	struct gsm48_imsi_detach_ind *idi =
 				(struct gsm48_imsi_detach_ind *) gh->data;
-	u_int8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
+	uint8_t mi_type = idi->mi[0] & GSM_MI_TYPE_MASK;
 	char mi_string[GSM48_MI_SIZE];
 	struct gsm_subscriber *subscr = NULL;
 
@@ -886,7 +886,7 @@
 	DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
 		mi_type, mi_string);
 
-	counter_inc(bts->network->stats.loc_upd_type.detach);
+	osmo_counter_inc(bts->network->stats.loc_upd_type.detach);
 
 	switch (mi_type) {
 	case GSM_MI_TYPE_TMSI:
@@ -942,7 +942,7 @@
 	struct gsm_network *net = conn->bts->network;
 
 	DEBUGP(DMM, "MM AUTHENTICATION RESPONSE (sres = %s): ",
-		hexdump(ar->sres, 4));
+		osmo_hexdump(ar->sres, 4));
 
 	/* Safety check */
 	if (!conn->sec_operation) {
@@ -956,7 +956,7 @@
 		gsm_cbfn *cb = conn->sec_operation->cb;
 
 		DEBUGPC(DMM, "Invalid (expected %s)\n",
-			hexdump(conn->sec_operation->atuple.sres, 4));
+			osmo_hexdump(conn->sec_operation->atuple.sres, 4));
 
 		if (cb)
 			cb(GSM_HOOK_RR_SECURITY, GSM_SECURITY_AUTH_FAILED,
@@ -1025,8 +1025,8 @@
 	struct gsm_bts *bts = conn->bts;
 	struct gsm48_hdr *gh = msgb_l3(msg);
 	struct gsm48_pag_resp *resp;
-	u_int8_t *classmark2_lv = gh->data + 1;
-	u_int8_t mi_type;
+	uint8_t *classmark2_lv = gh->data + 1;
+	uint8_t mi_type;
 	char mi_string[GSM48_MI_SIZE];
 	struct gsm_subscriber *subscr = NULL;
 	int rc = 0;
@@ -1068,8 +1068,8 @@
 	struct gsm48_hdr *gh = msgb_l3(msg);
 	struct gsm_subscriber *subscr = conn->subscr;
 	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
-	u_int8_t cm2_len, cm3_len = 0;
-	u_int8_t *cm2, *cm3 = NULL;
+	uint8_t cm2_len, cm3_len = 0;
+	uint8_t *cm2, *cm3 = NULL;
 
 	DEBUGP(DRR, "CLASSMARK CHANGE ");
 
@@ -1136,16 +1136,16 @@
 static int gsm48_rx_rr_app_info(struct gsm_subscriber_connection *conn, struct msgb *msg)
 {
 	struct gsm48_hdr *gh = msgb_l3(msg);
-	u_int8_t apdu_id_flags;
-	u_int8_t apdu_len;
-	u_int8_t *apdu_data;
+	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(DNM, "RX APPLICATION INFO id/flags=0x%02x apdu_len=%u apdu=%s",
-		apdu_id_flags, apdu_len, hexdump(apdu_data, apdu_len));
+		apdu_id_flags, apdu_len, osmo_hexdump(apdu_data, apdu_len));
 
 	return db_apdu_blob_store(conn->subscr, apdu_id_flags, apdu_len, apdu_data);
 }
@@ -1190,7 +1190,7 @@
 
 	sig.lchan = msg->lchan;
 	sig.mr = NULL;
-	dispatch_signal(SS_LCHAN, S_LCHAN_HANDOVER_COMPL, &sig);
+	osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_COMPL, &sig);
 	/* FIXME: release old channel */
 
 	return 0;
@@ -1207,7 +1207,7 @@
 
 	sig.lchan = msg->lchan;
 	sig.mr = NULL;
-	dispatch_signal(SS_LCHAN, S_LCHAN_HANDOVER_FAIL, &sig);
+	osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_FAIL, &sig);
 	/* FIXME: release allocated new channel */
 
 	return 0;
@@ -1256,8 +1256,8 @@
 	return rc;
 }
 
-int gsm48_send_rr_app_info(struct gsm_subscriber_connection *conn, u_int8_t apdu_id,
-			   u_int8_t apdu_len, const u_int8_t *apdu)
+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();
 	struct gsm48_hdr *gh;
@@ -1300,7 +1300,7 @@
 {
 	struct msgb *msg = gsm48_msgb_alloc();
 	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-	u_int8_t *cause, *call_state;
+	uint8_t *cause, *call_state;
 
 	gh->msg_type = GSM48_MT_CC_STATUS;
 
@@ -1316,7 +1316,7 @@
 }
 
 static int gsm48_tx_simple(struct gsm_subscriber_connection *conn,
-			   u_int8_t pdisc, u_int8_t msg_type)
+			   uint8_t pdisc, uint8_t msg_type)
 {
 	struct msgb *msg = gsm48_msgb_alloc();
 	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
@@ -1331,9 +1331,9 @@
 
 static void gsm48_stop_cc_timer(struct gsm_trans *trans)
 {
-	if (bsc_timer_pending(&trans->cc.timer)) {
+	if (osmo_timer_pending(&trans->cc.timer)) {
 		DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
-		bsc_del_timer(&trans->cc.timer);
+		osmo_timer_del(&trans->cc.timer);
 		trans->cc.Tcurrent = 0;
 	}
 }
@@ -1377,7 +1377,7 @@
 }
 
 int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
-		     u_int32_t callref, int location, int value)
+		     uint32_t callref, int location, int value)
 {
 	struct gsm_mncc rel;
 
@@ -1475,7 +1475,7 @@
 	return 0;
 }
 
-static int tch_recv_mncc(struct gsm_network *net, u_int32_t callref, int enable);
+static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable);
 
 /* handle audio path for handover */
 static int handle_ho_signal(unsigned int subsys, unsigned int signal,
@@ -1633,6 +1633,7 @@
 		}
 		break;
 	case GSM_BTS_TYPE_BS11:
+	case GSM_BTS_TYPE_RBS2000:
 		trau_mux_map_lchan(lchan, remote_lchan);
 		break;
 	default:
@@ -1644,7 +1645,7 @@
 }
 
 /* bridge channels of two transactions */
-static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
+static int tch_bridge(struct gsm_network *net, uint32_t *refs)
 {
 	struct gsm_trans *trans1 = trans_find_by_callref(net, refs[0]);
 	struct gsm_trans *trans2 = trans_find_by_callref(net, refs[1]);
@@ -1660,7 +1661,7 @@
 }
 
 /* enable receive of channels to MNCC upqueue */
-static int tch_recv_mncc(struct gsm_network *net, u_int32_t callref, int enable)
+static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable)
 {
 	struct gsm_trans *trans;
 	struct gsm_lchan *lchan;
@@ -1702,6 +1703,7 @@
 				net, 0);
 		break;
 	case GSM_BTS_TYPE_BS11:
+	case GSM_BTS_TYPE_RBS2000:
 		if (enable)
 			return trau_recv_lchan(lchan, callref);
 		return trau_mux_unmap(NULL, callref);
@@ -1814,14 +1816,14 @@
 	DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
 	trans->cc.timer.cb = gsm48_cc_timeout;
 	trans->cc.timer.data = trans;
-	bsc_schedule_timer(&trans->cc.timer, sec, micro);
+	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);
-	u_int8_t msg_type = gh->msg_type & 0xbf;
+	uint8_t msg_type = gh->msg_type & 0xbf;
 	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
 	struct tlv_parsed tp;
 	struct gsm_mncc setup;
@@ -1890,7 +1892,7 @@
 	     subscr_name(trans->subscr), trans->subscr->extension,
 	     setup.called.number);
 
-	counter_inc(trans->subscr->net->stats.call.mo_setup);
+	osmo_counter_inc(trans->subscr->net->stats.call.mo_setup);
 
 	/* indicate setup to MNCC */
 	mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
@@ -1967,7 +1969,7 @@
 	
 	new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
 
-	counter_inc(trans->subscr->net->stats.call.mt_setup);
+	osmo_counter_inc(trans->subscr->net->stats.call.mt_setup);
 
 	return gsm48_conn_sendmsg(msg, trans->conn, trans);
 }
@@ -2188,7 +2190,7 @@
 	}
 
 	new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
-	counter_inc(trans->subscr->net->stats.call.mt_connect);
+	osmo_counter_inc(trans->subscr->net->stats.call.mt_connect);
 
 	return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_CNF, &connect);
 }
@@ -2201,7 +2203,7 @@
 	gsm48_stop_cc_timer(trans);
 
 	new_cc_state(trans, GSM_CSTATE_ACTIVE);
-	counter_inc(trans->subscr->net->stats.call.mo_connect_ack);
+	osmo_counter_inc(trans->subscr->net->stats.call.mo_connect_ack);
 	
 	memset(&connect_ack, 0, sizeof(struct gsm_mncc));
 	connect_ack.callref = trans->callref;
@@ -2880,7 +2882,7 @@
 }
 
 static struct downstate {
-	u_int32_t	states;
+	uint32_t	states;
 	int		type;
 	int		(*rout) (struct gsm_trans *trans, void *arg);
 } downstatelist[] = {
@@ -2986,6 +2988,7 @@
 			}
 			return rtp_send_frame(trans->conn->lchan->abis_ip.rtp_socket, arg);
 		case GSM_BTS_TYPE_BS11:
+		case GSM_BTS_TYPE_RBS2000:
 			return trau_send_frame(trans->conn->lchan, arg);
 		default:
 			DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
@@ -3151,7 +3154,7 @@
 
 
 static struct datastate {
-	u_int32_t	states;
+	uint32_t	states;
 	int		type;
 	int		(*rout) (struct gsm_trans *trans, struct msgb *msg);
 } datastatelist[] = {
@@ -3207,8 +3210,8 @@
 static int gsm0408_rcv_cc(struct gsm_subscriber_connection *conn, struct msgb *msg)
 {
 	struct gsm48_hdr *gh = msgb_l3(msg);
-	u_int8_t msg_type = gh->msg_type & 0xbf;
-	u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
+	uint8_t msg_type = gh->msg_type & 0xbf;
+	uint8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
 	struct gsm_trans *trans = NULL;
 	int i, rc = 0;
 
@@ -3266,7 +3269,7 @@
 	if (!conn->anch_operation)
 		return;
 
-	bsc_del_timer(&conn->anch_operation->timeout);
+	osmo_timer_del(&conn->anch_operation->timeout);
 	talloc_free(conn->anch_operation);
 	conn->anch_operation = NULL;
 }
@@ -3287,7 +3290,7 @@
 
 	conn->anch_operation->timeout.data = conn;
 	conn->anch_operation->timeout.cb = anchor_timeout;
-	bsc_schedule_timer(&conn->anch_operation->timeout, 5, 0);
+	osmo_timer_schedule(&conn->anch_operation->timeout, 5, 0);
 	return 0;
 }
 
@@ -3295,7 +3298,7 @@
 int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg)
 {
 	struct gsm48_hdr *gh = msgb_l3(msg);
-	u_int8_t pdisc = gh->proto_discr & 0x0f;
+	uint8_t pdisc = gh->proto_discr & 0x0f;
 	int rc = 0;
 
 	if (silent_call_reroute(conn, msg))
@@ -3340,6 +3343,6 @@
  */
 static __attribute__((constructor)) void on_dso_load_0408(void)
 {
-	register_signal_handler(SS_HO, handle_ho_signal, NULL);
-	register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
+	osmo_signal_register_handler(SS_HO, handle_ho_signal, NULL);
+	osmo_signal_register_handler(SS_ABISIP, handle_abisip_signal, NULL);
 }
diff --git a/src/libmsc/gsm_04_11.c b/src/libmsc/gsm_04_11.c
index 812e758..ba72c37 100644
--- a/src/libmsc/gsm_04_11.c
+++ b/src/libmsc/gsm_04_11.c
@@ -32,19 +32,19 @@
 #include <time.h>
 #include <netinet/in.h>
 
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/tlv.h>
 #include <openbsc/debug.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/db.h>
 #include <openbsc/gsm_subscriber.h>
 #include <openbsc/gsm_04_11.h>
 #include <openbsc/gsm_04_08.h>
-#include <osmocore/gsm_utils.h>
+#include <osmocom/gsm/gsm_utils.h>
 #include <openbsc/abis_rsl.h>
 #include <openbsc/signal.h>
 #include <openbsc/db.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/transaction.h>
 #include <openbsc/paging.h>
 #include <openbsc/bsc_rll.h>
@@ -55,7 +55,7 @@
 #define GSM411_ALLOC_HEADROOM	128
 
 void *tall_gsms_ctx;
-static u_int32_t new_callref = 0x40000001;
+static uint32_t new_callref = 0x40000001;
 
 static const struct value_string cp_cause_strs[] = {
 	{ GSM411_CP_CAUSE_NET_FAIL,	"Network Failure" },
@@ -151,7 +151,7 @@
 	sig.trans = trans;
 	sig.sms = sms;
 	sig.paging_result = paging_result;
-	dispatch_signal(SS_SMS, sig_no, &sig);
+	osmo_signal_dispatch(SS_SMS, sig_no, &sig);
 }
 
 /*
@@ -173,9 +173,9 @@
 				   "GSM 04.11");
 }
 
-static int gsm411_sendmsg(struct gsm_subscriber_connection *conn, struct msgb *msg, u_int8_t link_id)
+static int gsm411_sendmsg(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t link_id)
 {
-	DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len));
+	DEBUGP(DSMS, "GSM4.11 TX %s\n", osmo_hexdump(msg->data, msg->len));
 	msg->l3h = msg->data;
 	return gsm0808_submit_dtap(conn, msg, link_id, 1);
 }
@@ -192,7 +192,7 @@
 
 /* Prefix msg with a 04.08/04.11 CP header */
 static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
-			     u_int8_t msg_type)
+			     uint8_t msg_type)
 {
 	struct gsm48_hdr *gh;
 
@@ -210,7 +210,7 @@
 		trans->sms.cp_timer.data = trans;
 		trans->sms.cp_timer.cb = cp_timer_expired;
 		/* 5.3.2.1: Set Timer TC1A */
-		bsc_schedule_timer(&trans->sms.cp_timer, GSM411_TMR_TC1A);
+		osmo_timer_schedule(&trans->sms.cp_timer, GSM411_TMR_TC1A);
 		DEBUGP(DSMS, "TX: CP-DATA ");
 		break;
 	case GSM411_MT_CP_ACK:
@@ -228,10 +228,10 @@
 
 /* Prefix msg with a RP-DATA header and send as CP-DATA */
 static int gsm411_rp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
-			     u_int8_t rp_msg_type, u_int8_t rp_msg_ref)
+			     uint8_t rp_msg_type, uint8_t rp_msg_ref)
 {
 	struct gsm411_rp_hdr *rp;
-	u_int8_t len = msg->len;
+	uint8_t len = msg->len;
 
 	/* GSM 04.11 RP-DATA header */
 	rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
@@ -243,9 +243,9 @@
 }
 
 /* Turn int into semi-octet representation: 98 => 0x89 */
-static u_int8_t bcdify(u_int8_t value)
+static uint8_t bcdify(uint8_t value)
 {
-	u_int8_t ret;
+	uint8_t ret;
 
 	ret = value / 10;
 	ret |= (value % 10) << 4;
@@ -254,9 +254,9 @@
 }
 
 /* Turn semi-octet representation into int: 0x89 => 98 */
-static u_int8_t unbcdify(u_int8_t value)
+static uint8_t unbcdify(uint8_t value)
 {
-	u_int8_t ret;
+	uint8_t ret;
 
 	if ((value & 0x0F) > 9 || (value >> 4) > 9)
 		LOGP(DSMS, LOGL_ERROR,
@@ -269,7 +269,7 @@
 }
 
 /* Generate 03.40 TP-SCTS */
-static void gsm340_gen_scts(u_int8_t *scts, time_t time)
+static void gsm340_gen_scts(uint8_t *scts, time_t time)
 {
 	struct tm *tm = localtime(&time);
 
@@ -283,11 +283,11 @@
 }
 
 /* Decode 03.40 TP-SCTS (into utc/gmt timestamp) */
-static time_t gsm340_scts(u_int8_t *scts)
+static time_t gsm340_scts(uint8_t *scts)
 {
 	struct tm tm;
 
-	u_int8_t yr = unbcdify(*scts++);
+	uint8_t yr = unbcdify(*scts++);
 
 	if (yr <= 80)
 		tm.tm_year = 100 + yr;
@@ -315,10 +315,10 @@
 }
 
 /* Decode validity period format 'relative' */
-static unsigned long gsm340_vp_relative(u_int8_t *sms_vp)
+static unsigned long gsm340_vp_relative(uint8_t *sms_vp)
 {
 	/* Chapter 9.2.3.12.1 */
-	u_int8_t vp;
+	uint8_t vp;
 	unsigned long minutes;
 
 	vp = *(sms_vp);
@@ -334,7 +334,7 @@
 }
 
 /* Decode validity period format 'absolute' */
-static unsigned long gsm340_vp_absolute(u_int8_t *sms_vp)
+static unsigned long gsm340_vp_absolute(uint8_t *sms_vp)
 {
 	/* Chapter 9.2.3.12.2 */
 	time_t expires, now;
@@ -350,9 +350,9 @@
 }
 
 /* Decode validity period format 'relative in integer representation' */
-static unsigned long gsm340_vp_relative_integer(u_int8_t *sms_vp)
+static unsigned long gsm340_vp_relative_integer(uint8_t *sms_vp)
 {
-	u_int8_t vp;
+	uint8_t vp;
 	unsigned long minutes;
 	vp = *(sms_vp);
 	if (vp == 0) {
@@ -365,7 +365,7 @@
 }
 
 /* Decode validity period format 'relative in semi-octet representation' */
-static unsigned long gsm340_vp_relative_semioctet(u_int8_t *sms_vp)
+static unsigned long gsm340_vp_relative_semioctet(uint8_t *sms_vp)
 {
 	unsigned long minutes;
 	minutes = unbcdify(*sms_vp++)*60;  /* hours */
@@ -375,9 +375,9 @@
 }
 
 /* decode validity period. return minutes */
-static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
+static unsigned long gsm340_validity_period(uint8_t sms_vpf, uint8_t *sms_vp)
 {
-	u_int8_t fi; /* functionality indicator */
+	uint8_t fi; /* functionality indicator */
 
 	switch (sms_vpf) {
 	case GSM340_TP_VPF_RELATIVE:
@@ -413,9 +413,9 @@
 }
 
 /* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
-enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
+enum sms_alphabet gsm338_get_sms_alphabet(uint8_t dcs)
 {
-	u_int8_t cgbits = dcs >> 4;
+	uint8_t cgbits = dcs >> 4;
 	enum sms_alphabet alpha = DCS_NONE;
 
 	if ((cgbits & 0xc) == 0) {
@@ -463,7 +463,7 @@
 }
 
 /* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
-static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
+static int gsm340_gen_oa(uint8_t *oa, unsigned int oa_len,
 			 struct gsm_subscriber *subscr)
 {
 	int len_in_bytes;
@@ -482,10 +482,10 @@
  * returns total size of TPDU */
 static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
 {
-	u_int8_t *smsp;
-	u_int8_t oa[12];	/* max len per 03.40 */
-	u_int8_t oa_len = 0;
-	u_int8_t octet_len;
+	uint8_t *smsp;
+	uint8_t oa[12];	/* max len per 03.40 */
+	uint8_t oa_len = 0;
+	uint8_t octet_len;
 	unsigned int old_msg_len = msg->len;
 
 	/* generate first octet with masked bits */
@@ -552,15 +552,15 @@
  * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
 static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *msg)
 {
-	u_int8_t *smsp = msgb_sms(msg);
+	uint8_t *smsp = msgb_sms(msg);
 	struct gsm_sms *gsms;
-	u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
-	u_int8_t *sms_vp;
-	u_int8_t da_len_bytes;
-	u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
+	uint8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
+	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;
 
-	counter_inc(conn->bts->network->stats.sms.submitted);
+	osmo_counter_inc(conn->bts->network->stats.sms.submitted);
 
 	gsms = sms_alloc();
 	if (!gsms)
@@ -645,7 +645,7 @@
 	     gsms->protocol_id, gsms->data_coding_scheme, gsms->dest_addr,
 	     gsms->user_data_len,
 			sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
-				hexdump(gsms->user_data, gsms->user_data_len));
+				osmo_hexdump(gsms->user_data, gsms->user_data_len));
 
 	gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
 
@@ -656,7 +656,7 @@
 	gsms->receiver = subscr_get_by_extension(conn->bts->network, gsms->dest_addr);
 	if (!gsms->receiver) {
 		rc = 1; /* cause 1: unknown subscriber */
-		counter_inc(conn->bts->network->stats.sms.no_receiver);
+		osmo_counter_inc(conn->bts->network->stats.sms.no_receiver);
 		goto out;
 	}
 
@@ -685,7 +685,7 @@
 	return rc;
 }
 
-static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
+static int gsm411_send_rp_ack(struct gsm_trans *trans, uint8_t msg_ref)
 {
 	struct msgb *msg = gsm411_msgb_alloc();
 
@@ -695,7 +695,7 @@
 }
 
 static int gsm411_send_rp_error(struct gsm_trans *trans,
-				u_int8_t msg_ref, u_int8_t cause)
+				uint8_t msg_ref, uint8_t cause)
 {
 	struct msgb *msg = gsm411_msgb_alloc();
 
@@ -710,9 +710,9 @@
 /* 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,
-			  u_int8_t src_len, u_int8_t *src,
-			  u_int8_t dst_len, u_int8_t *dst,
-			  u_int8_t tpdu_len, u_int8_t *tpdu)
+			  uint8_t src_len, uint8_t *src,
+			  uint8_t dst_len, uint8_t *dst,
+			  uint8_t tpdu_len, uint8_t *tpdu)
 {
 	int rc = 0;
 
@@ -728,7 +728,7 @@
 	}
 	msg->l4h = tpdu;
 
-	DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
+	DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, osmo_hexdump(dst, dst_len));
 
 	rc = gsm340_rx_tpdu(trans->conn, msg);
 	if (rc == 0)
@@ -743,8 +743,8 @@
 static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
 			     struct gsm411_rp_hdr *rph)
 {
-	u_int8_t src_len, dst_len, rpud_len;
-	u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
+	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];
@@ -812,8 +812,8 @@
 {
 	struct gsm_network *net = trans->conn->bts->network;
 	struct gsm_sms *sms = trans->sms.sms;
-	u_int8_t cause_len = rph->data[0];
-	u_int8_t cause = rph->data[1];
+	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
@@ -846,10 +846,10 @@
 		 * to store this in our database and wait for a SMMA message */
 		/* FIXME */
 		send_signal(S_SMS_MEM_EXCEEDED, trans, sms, 0);
-		counter_inc(net->stats.sms.rp_err_mem);
+		osmo_counter_inc(net->stats.sms.rp_err_mem);
 	} else {
 		send_signal(S_SMS_UNKNOWN_ERROR, trans, sms, 0);
-		counter_inc(net->stats.sms.rp_err_other);
+		osmo_counter_inc(net->stats.sms.rp_err_other);
 	}
 
 	sms_free(sms);
@@ -886,7 +886,7 @@
 			     struct gsm_trans *trans)
 {
 	struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
-	u_int8_t msg_type =  rp_data->msg_type & 0x07;
+	uint8_t msg_type =  rp_data->msg_type & 0x07;
 	int rc = 0;
 
 	switch (msg_type) {
@@ -936,10 +936,10 @@
 	return rc;
 }
 
-static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
+static int gsm411_tx_cp_error(struct gsm_trans *trans, uint8_t cause)
 {
 	struct msgb *msg = gsm411_msgb_alloc();
-	u_int8_t *causep;
+	uint8_t *causep;
 
 	LOGP(DSMS, LOGL_NOTICE, "TX CP-ERROR, cause %d (%s)\n", cause,
 		get_value_string(cp_cause_strs, cause));
@@ -955,8 +955,8 @@
 		    struct msgb *msg)
 {
 	struct gsm48_hdr *gh = msgb_l3(msg);
-	u_int8_t msg_type = gh->msg_type;
-	u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
+	uint8_t msg_type = gh->msg_type;
+	uint8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
 	struct gsm_trans *trans;
 	int rc = 0;
 
@@ -1008,7 +1008,7 @@
 				DEBUGP(DSMS, "Implicit CP-ACK for trans_id=%x\n", i);
 
 				/* Finish it for good */
-				bsc_del_timer(&ptrans->sms.cp_timer);
+				osmo_timer_del(&ptrans->sms.cp_timer);
 				ptrans->sms.cp_state = GSM411_CPS_IDLE;
 				trans_free(ptrans);
 			}
@@ -1039,7 +1039,7 @@
 		/* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
 		trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
 		/* Stop TC1* after CP-ACK has been received */
-		bsc_del_timer(&trans->sms.cp_timer);
+		osmo_timer_del(&trans->sms.cp_timer);
 
 		if (!trans->sms.is_mt) {
 			/* FIXME: we have sent one CP-DATA, which was now
@@ -1052,7 +1052,7 @@
 	case GSM411_MT_CP_ERROR:
 		DEBUGPC(DSMS, "RX SMS CP-ERROR, cause %d (%s)\n", gh->data[0],
 			get_value_string(cp_cause_strs, gh->data[0]));
-		bsc_del_timer(&trans->sms.cp_timer);
+		osmo_timer_del(&trans->sms.cp_timer);
 		trans->sms.cp_state = GSM411_CPS_IDLE;
 		trans_free(trans);
 		break;
@@ -1074,8 +1074,8 @@
 {
 	struct msgb *msg = gsm411_msgb_alloc();
 	struct gsm_trans *trans;
-	u_int8_t *data, *rp_ud_len;
-	u_int8_t msg_ref = 42;
+	uint8_t *data, *rp_ud_len;
+	uint8_t msg_ref = 42;
 	int transaction_id;
 	int rc;
 
@@ -1108,7 +1108,7 @@
 	trans->conn = conn;
 
 	/* Hardcode SMSC Originating Address for now */
-	data = (u_int8_t *)msgb_put(msg, 8);
+	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 */
@@ -1119,11 +1119,11 @@
 	data[7] = 0x50;
 
 	/* Hardcoded Destination Address */
-	data = (u_int8_t *)msgb_put(msg, 1);
+	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 = (u_int8_t *)msgb_put(msg, 1);
+	rp_ud_len = (uint8_t *)msgb_put(msg, 1);
 
 	/* generate the 03.40 TPDU */
 	rc = gsm340_gen_tpdu(msg, sms);
@@ -1139,7 +1139,7 @@
 
 	DEBUGP(DSMS, "TX: SMS DELIVER\n");
 
-	counter_inc(conn->bts->network->stats.sms.delivered);
+	osmo_counter_inc(conn->bts->network->stats.sms.delivered);
 	db_sms_inc_deliver_attempts(trans->sms.sms);
 
 	return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
@@ -1208,7 +1208,7 @@
 		trans->sms.sms = NULL;
 	}
 
-	bsc_del_timer(&trans->sms.cp_timer);
+	osmo_timer_del(&trans->sms.cp_timer);
 }
 
 void gsm411_sapi_n_reject(struct gsm_subscriber_connection *conn)
diff --git a/src/libmsc/gsm_04_80.c b/src/libmsc/gsm_04_80.c
index 494c319..39738a5 100644
--- a/src/libmsc/gsm_04_80.c
+++ b/src/libmsc/gsm_04_80.c
@@ -34,12 +34,12 @@
 #include <openbsc/gsm_04_80.h>
 #include <openbsc/bsc_api.h>
 
-#include <osmocore/gsm0480.h>
-#include <osmocore/gsm_utils.h>
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.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, u_int8_t tag)
+static inline unsigned char *msgb_wrap_with_TL(struct msgb *msgb, uint8_t tag)
 {
 	uint8_t *data = msgb_push(msgb, 2);
 
@@ -48,8 +48,8 @@
 	return data;
 }
 
-static inline unsigned char *msgb_push_TLV1(struct msgb *msgb, u_int8_t tag,
-					    u_int8_t value)
+static inline unsigned char *msgb_push_TLV1(struct msgb *msgb, uint8_t tag,
+					    uint8_t value)
 {
 	uint8_t *data = msgb_push(msgb, 3);
 
@@ -67,7 +67,7 @@
 {
 	struct msgb *msg = gsm48_msgb_alloc();
 	struct gsm48_hdr *gh;
-	u_int8_t *ptr8;
+	uint8_t *ptr8;
 	int response_len;
 
 	/* First put the payload text into the message */
diff --git a/src/libmsc/gsm_subscriber.c b/src/libmsc/gsm_subscriber.c
index db61f25..f9eebc8 100644
--- a/src/libmsc/gsm_subscriber.c
+++ b/src/libmsc/gsm_subscriber.c
@@ -26,7 +26,7 @@
 #include <string.h>
 #include <assert.h>
 
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 
 #include <osmocom/vty/vty.h>
 
@@ -97,7 +97,7 @@
 	sig_data.bts	= conn ? conn->bts : NULL;
 	sig_data.conn	= conn;
 	sig_data.paging_result = event;
-	dispatch_signal(
+	osmo_signal_dispatch(
 		SS_PAGING,
 		event == GSM_PAGING_SUCCEEDED ?
 			S_PAGING_SUCCEEDED : S_PAGING_EXPIRED,
@@ -266,7 +266,7 @@
 
 
 struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_network *net,
-					  u_int32_t tmsi)
+					  uint32_t tmsi)
 {
 	char tmsi_string[14];
 	struct gsm_subscriber *subscr;
@@ -337,7 +337,7 @@
 			subscr_name(s), s->lac);
 		rc = db_sync_subscriber(s);
 		db_subscriber_update(s);
-		dispatch_signal(SS_SUBSCR, S_SUBSCR_ATTACHED, s);
+		osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_ATTACHED, s);
 		break;
 	case GSM_SUBSCRIBER_UPDATE_DETACHED:
 		/* Only detach if we are currently in this area */
@@ -346,7 +346,7 @@
 		LOGP(DMM, LOGL_INFO, "Subscriber %s DETACHED\n", subscr_name(s));
 		rc = db_sync_subscriber(s);
 		db_subscriber_update(s);
-		dispatch_signal(SS_SUBSCR, S_SUBSCR_DETACHED, s);
+		osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_DETACHED, s);
 		break;
 	default:
 		fprintf(stderr, "subscr_update with unknown reason: %d\n",
diff --git a/src/libmsc/mncc.c b/src/libmsc/mncc.c
index 3630b91..b484772 100644
--- a/src/libmsc/mncc.c
+++ b/src/libmsc/mncc.c
@@ -25,12 +25,11 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <sys/types.h>
 
 #include <openbsc/gsm_04_08.h>
 #include <openbsc/debug.h>
 #include <openbsc/mncc.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/transaction.h>
 #include <openbsc/rtp_proxy.h>
diff --git a/src/libmsc/mncc_builtin.c b/src/libmsc/mncc_builtin.c
index 0226b27..105f1dd 100644
--- a/src/libmsc/mncc_builtin.c
+++ b/src/libmsc/mncc_builtin.c
@@ -26,12 +26,11 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <sys/types.h>
 
 #include <openbsc/gsm_04_08.h>
 #include <openbsc/debug.h>
 #include <openbsc/mncc.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/transaction.h>
 #include <openbsc/rtp_proxy.h>
@@ -40,7 +39,7 @@
 
 static LLIST_HEAD(call_list);
 
-static u_int32_t new_callref = 0x00000001;
+static uint32_t new_callref = 0x00000001;
 
 static void free_call(struct gsm_call *call)
 {
@@ -50,7 +49,7 @@
 }
 
 
-static struct gsm_call *get_call_ref(u_int32_t callref)
+static struct gsm_call *get_call_ref(uint32_t callref)
 {
 	struct gsm_call *callt;
 
@@ -168,7 +167,7 @@
 	struct gsm_mncc connect_ack, frame_recv;
 	struct gsm_network *net = call->net;
 	struct gsm_call *remote;
-	u_int32_t refs[2];
+	uint32_t refs[2];
 
 	/* acknowledge connect */
 	memset(&connect_ack, 0, sizeof(struct gsm_mncc));
diff --git a/src/libmsc/mncc_sock.c b/src/libmsc/mncc_sock.c
index 2eef7c8..5ef9922 100644
--- a/src/libmsc/mncc_sock.c
+++ b/src/libmsc/mncc_sock.c
@@ -26,13 +26,12 @@
 #include <string.h>
 #include <errno.h>
 #include <assert.h>
-#include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 
-#include <osmocore/talloc.h>
-#include <osmocore/select.h>
-#include <osmocore/protocol/gsm_04_08.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/select.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
 
 #include <openbsc/debug.h>
 #include <openbsc/mncc.h>
@@ -40,8 +39,8 @@
 
 struct mncc_sock_state {
 	struct gsm_network *net;
-	struct bsc_fd listen_bfd;	/* fd for listen socket */
-	struct bsc_fd conn_bfd;		/* fd for connection to lcr */
+	struct osmo_fd listen_bfd;	/* fd for listen socket */
+	struct osmo_fd conn_bfd;		/* fd for connection to lcr */
 };
 
 /* FIXME: avoid this */
@@ -86,17 +85,17 @@
 }
 
 /* FIXME: move this to libosmocore */
-int osmo_unixsock_listen(struct bsc_fd *bfd, int type, const char *path);
+int osmo_unixsock_listen(struct osmo_fd *bfd, int type, const char *path);
 
 static void mncc_sock_close(struct mncc_sock_state *state)
 {
-	struct bsc_fd *bfd = &state->conn_bfd;
+	struct osmo_fd *bfd = &state->conn_bfd;
 
 	LOGP(DMNCC, LOGL_NOTICE, "MNCC Socket has LOST connection\n");
 
 	close(bfd->fd);
 	bfd->fd = -1;
-	bsc_unregister_fd(bfd);
+	osmo_fd_unregister(bfd);
 
 	/* re-enable the generation of ACCEPT for new connections */
 	state->listen_bfd.when |= BSC_FD_READ;
@@ -113,7 +112,7 @@
 	}
 }
 
-static int mncc_sock_read(struct bsc_fd *bfd)
+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;
@@ -150,7 +149,7 @@
 	return -1;
 }
 
-static int mncc_sock_write(struct bsc_fd *bfd)
+static int mncc_sock_write(struct osmo_fd *bfd)
 {
 	struct mncc_sock_state *state = bfd->data;
 	struct gsm_network *net = state->net;
@@ -190,7 +189,7 @@
 	return -1;
 }
 
-static int mncc_sock_cb(struct bsc_fd *bfd, unsigned int flags)
+static int mncc_sock_cb(struct osmo_fd *bfd, unsigned int flags)
 {
 	int rc = 0;
 
@@ -206,10 +205,10 @@
 }
 
 /* accept a new connection */
-static int mncc_sock_accept(struct bsc_fd *bfd, unsigned int flags)
+static int mncc_sock_accept(struct osmo_fd *bfd, unsigned int flags)
 {
 	struct mncc_sock_state *state = (struct mncc_sock_state *)bfd->data;
-	struct bsc_fd *conn_bfd = &state->conn_bfd;
+	struct osmo_fd *conn_bfd = &state->conn_bfd;
 	struct sockaddr_un un_addr;
 	socklen_t len;
 	int rc;
@@ -235,11 +234,10 @@
 	conn_bfd->cb = mncc_sock_cb;
 	conn_bfd->data = state;
 
-	if (bsc_register_fd(conn_bfd) != 0) {
+	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;
-		state->listen_bfd.when |= ~BSC_FD_READ;
 		return -1;
 	}
 
@@ -253,7 +251,7 @@
 int mncc_sock_init(struct gsm_network *net)
 {
 	struct mncc_sock_state *state;
-	struct bsc_fd *bfd;
+	struct osmo_fd *bfd;
 	int rc;
 
 	state = talloc_zero(tall_bsc_ctx, struct mncc_sock_state);
@@ -277,7 +275,7 @@
 	bfd->cb = mncc_sock_accept;
 	bfd->data = state;
 
-	rc = bsc_register_fd(bfd);
+	rc = osmo_fd_register(bfd);
 	if (rc < 0) {
 		LOGP(DMNCC, LOGL_ERROR, "Could not register listen fd: %d\n", rc);
 		close(bfd->fd);
@@ -291,7 +289,7 @@
 }
 
 /* FIXME: move this to libosmocore */
-int osmo_unixsock_listen(struct bsc_fd *bfd, int type, const char *path)
+int osmo_unixsock_listen(struct osmo_fd *bfd, int type, const char *path)
 {
 	struct sockaddr_un local;
 	unsigned int namelen;
diff --git a/src/libmsc/rrlp.c b/src/libmsc/rrlp.c
index ae5ca47..161456a 100644
--- a/src/libmsc/rrlp.c
+++ b/src/libmsc/rrlp.c
@@ -20,7 +20,6 @@
  */
 
 
-#include <sys/types.h>
 
 #include <openbsc/gsm_04_08.h>
 #include <openbsc/signal.h>
@@ -29,20 +28,20 @@
 
 /* RRLP msPositionReq, nsBased,
  *	Accuracy=60, Method=gps, ResponseTime=2, oneSet */
-static const u_int8_t ms_based_pos_req[] = { 0x40, 0x01, 0x78, 0xa8 };
+static const uint8_t ms_based_pos_req[] = { 0x40, 0x01, 0x78, 0xa8 };
 
 /* RRLP msPositionReq, msBasedPref,
 	Accuracy=60, Method=gpsOrEOTD, ResponseTime=5, multipleSets */
-static const u_int8_t ms_pref_pos_req[]  = { 0x40, 0x02, 0x79, 0x50 };
+static const uint8_t ms_pref_pos_req[]  = { 0x40, 0x02, 0x79, 0x50 };
 
 /* RRLP msPositionReq, msAssistedPref,
 	Accuracy=60, Method=gpsOrEOTD, ResponseTime=5, multipleSets */
-static const u_int8_t ass_pref_pos_req[] = { 0x40, 0x03, 0x79, 0x50 };
+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->bts->network;
-	const u_int8_t *req;
+	const uint8_t *req;
 
 	switch (net->rrlp.mode) {
 	case RRLP_MODE_MS_BASED:
@@ -100,6 +99,6 @@
 
 void on_dso_load_rrlp(void)
 {
-	register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
-	register_signal_handler(SS_PAGING, paging_sig_cb, NULL);
+	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
index 64ebdfd..6a188c8 100644
--- a/src/libmsc/silent_call.c
+++ b/src/libmsc/silent_call.c
@@ -24,7 +24,7 @@
 #include <unistd.h>
 #include <errno.h>
 
-#include <osmocore/msgb.h>
+#include <osmocom/core/msgb.h>
 #include <openbsc/signal.h>
 #include <openbsc/debug.h>
 #include <openbsc/paging.h>
@@ -56,13 +56,13 @@
 			conn->lchan->ts->nr, conn->lchan->ts->trx->arfcn);
 		conn->silent_call = 1;
 		/* increment lchan reference count */
-		dispatch_signal(SS_SCALL, S_SCALL_SUCCESS, &sigdata);
+		osmo_signal_dispatch(SS_SCALL, S_SCALL_SUCCESS, &sigdata);
 		break;
 	case GSM_PAGING_EXPIRED:
 	case GSM_PAGING_BUSY:
 	case GSM_PAGING_OOM:
 		DEBUGP(DSMS, "expired\n");
-		dispatch_signal(SS_SCALL, S_SCALL_EXPIRED, &sigdata);
+		osmo_signal_dispatch(SS_SCALL, S_SCALL_EXPIRED, &sigdata);
 		break;
 	default:
 		rc = -EINVAL;
@@ -80,8 +80,8 @@
 }
 
 struct msg_match {
-	u_int8_t pdisc;
-	u_int8_t msg_type;
+	uint8_t pdisc;
+	uint8_t msg_type;
 };
 
 /* list of messages that are handled inside OpenBSC, even in a silent call */
@@ -94,7 +94,7 @@
 int silent_call_reroute(struct gsm_subscriber_connection *conn, struct msgb *msg)
 {
 	struct gsm48_hdr *gh = msgb_l3(msg);
-	u_int8_t pdisc = gh->proto_discr & 0x0f;
+	uint8_t pdisc = gh->proto_discr & 0x0f;
 	int i;
 
 	/* if we're not part of a silent call, never reroute */
diff --git a/src/libmsc/sms_queue.c b/src/libmsc/sms_queue.c
index 079755d..30fa5f0 100644
--- a/src/libmsc/sms_queue.c
+++ b/src/libmsc/sms_queue.c
@@ -37,7 +37,7 @@
 #include <openbsc/gsm_subscriber.h>
 #include <openbsc/signal.h>
 
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 
 #include <osmocom/vty/vty.h>
 
@@ -54,8 +54,8 @@
 };
 
 struct gsm_sms_queue {
-	struct timer_list resend_pending;
-	struct timer_list push_queue;
+	struct osmo_timer_list resend_pending;
+	struct osmo_timer_list push_queue;
 	struct gsm_network *network;
 	int max_fail;
 	int max_pending;
@@ -129,10 +129,10 @@
 	pending->resend = 1;
 
 	smsq = pending->subscr->net->sms_queue;
-	if (bsc_timer_pending(&smsq->resend_pending))
+	if (osmo_timer_pending(&smsq->resend_pending))
 		return;
 
-	bsc_schedule_timer(&smsq->resend_pending, 1, 0);
+	osmo_timer_schedule(&smsq->resend_pending, 1, 0);
 }
 
 static void sms_pending_failed(struct gsm_sms_pending *pending, int paging_error)
@@ -288,10 +288,10 @@
  */
 int sms_queue_trigger(struct gsm_sms_queue *smsq)
 {
-	if (bsc_timer_pending(&smsq->push_queue))
+	if (osmo_timer_pending(&smsq->push_queue))
 		return 0;
 
-	bsc_schedule_timer(&smsq->push_queue, 1, 0);
+	osmo_timer_schedule(&smsq->push_queue, 1, 0);
 	return 0;
 }
 
@@ -303,8 +303,8 @@
 		return -1;
 	}
 
-	register_signal_handler(SS_SUBSCR, sms_subscr_cb, network);
-	register_signal_handler(SS_SMS, sms_sms_cb, network);
+	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);
diff --git a/src/libmsc/token_auth.c b/src/libmsc/token_auth.c
index 3404dd4..cf26ba8 100644
--- a/src/libmsc/token_auth.c
+++ b/src/libmsc/token_auth.c
@@ -20,7 +20,7 @@
  */
 
 #include <stdio.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/signal.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/gsm_04_11.h>
@@ -32,7 +32,7 @@
 #define TOKEN_SMS_TEXT "HAR 2009 GSM.  Register at http://har2009.gnumonks.org/ " \
 			"Your IMSI is %s, auth token is %08X, phone no is %s."
 
-static char *build_sms_string(struct gsm_subscriber *subscr, u_int32_t token)
+static char *build_sms_string(struct gsm_subscriber *subscr, uint32_t token)
 {
 	char *sms_str;
 	unsigned int len;
@@ -63,7 +63,7 @@
 		return 0;
 
 	if (subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT) {
-		u_int32_t token;
+		uint32_t token;
 		char *sms_str;
 
 		/* we've seen this subscriber for the first time. */
@@ -97,7 +97,7 @@
 		if (rc) {
 			struct gsm_subscriber_connection *conn = connection_for_subscr(subscr);
 			if (conn) {
-				u_int8_t auth_rand[16];
+				uint8_t auth_rand[16];
 				/* kick the subscriber off the network */
 				gsm48_tx_mm_auth_req(conn, auth_rand, 0);
 				gsm48_tx_mm_auth_rej(conn);
@@ -116,7 +116,7 @@
 	struct sms_signal_data *sig = signal_data;
 	struct gsm_sms *sms = sig->sms;;
 	struct gsm_subscriber_connection *conn;
-	u_int8_t auth_rand[16];
+	uint8_t auth_rand[16];
 
 
 	if (signal != S_SMS_DELIVERED)
@@ -148,6 +148,6 @@
 //static __attribute__((constructor)) void on_dso_load_token(void)
 void on_dso_load_token(void)
 {
-	register_signal_handler(SS_SUBSCR, token_subscr_cb, NULL);
-	register_signal_handler(SS_SMS, token_sms_cb, NULL);
+	osmo_signal_register_handler(SS_SUBSCR, token_subscr_cb, NULL);
+	osmo_signal_register_handler(SS_SMS, token_sms_cb, NULL);
 }
diff --git a/src/libmsc/transaction.c b/src/libmsc/transaction.c
new file mode 100644
index 0000000..8a181b7
--- /dev/null
+++ b/src/libmsc/transaction.c
@@ -0,0 +1,151 @@
+/* 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_subscriber.h>
+#include <openbsc/gsm_04_08.h>
+#include <openbsc/mncc.h>
+#include <openbsc/paging.h>
+#include <openbsc/osmo_msc.h>
+
+void *tall_trans_ctx;
+
+void _gsm48_cc_trans_free(struct gsm_trans *trans);
+
+struct gsm_trans *trans_find_by_id(struct gsm_subscriber *subscr,
+				   uint8_t proto, uint8_t trans_id)
+{
+	struct gsm_trans *trans;
+	struct gsm_network *net = subscr->net;
+
+	llist_for_each_entry(trans, &net->trans_list, entry) {
+		if (trans->subscr == subscr &&
+		    trans->protocol == proto &&
+		    trans->transaction_id == trans_id)
+			return trans;
+	}
+	return NULL;
+}
+
+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;
+}
+
+struct gsm_trans *trans_alloc(struct gsm_subscriber *subscr,
+			      uint8_t protocol, uint8_t trans_id,
+			      uint32_t callref)
+{
+	struct gsm_trans *trans;
+
+	DEBUGP(DCC, "subscr=%p, subscr->net=%p\n", subscr, subscr->net);
+
+	trans = talloc_zero(tall_trans_ctx, struct gsm_trans);
+	if (!trans)
+		return NULL;
+
+	trans->subscr = subscr;
+	subscr_get(trans->subscr);
+
+	trans->protocol = protocol;
+	trans->transaction_id = trans_id;
+	trans->callref = callref;
+
+	llist_add_tail(&trans->entry, &subscr->net->trans_list);
+
+	return trans;
+}
+
+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;
+	}
+
+	/* FIXME: implement a sane way to stop this. */
+	if (!trans->conn && trans->paging_request) {
+		LOGP(DNM, LOGL_ERROR,
+		     "Transaction freed while paging for sub: %llu\n",
+		     trans->subscr->id);
+		trans->paging_request = NULL;
+	}
+
+	if (trans->subscr)
+		subscr_put(trans->subscr);
+
+	llist_del(&trans->entry);
+
+	if (trans->conn)
+		msc_release_connection(trans->conn);
+
+
+	talloc_free(trans);
+}
+
+/* allocate an unused transaction ID for the given subscriber
+ * in the given protocol using the ti_flag specified */
+int trans_assign_trans_id(struct gsm_subscriber *subscr,
+			  uint8_t protocol, uint8_t ti_flag)
+{
+	struct gsm_network *net = subscr->net;
+	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->subscr != subscr ||
+		    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;
+}
diff --git a/src/libmsc/vty_interface_layer3.c b/src/libmsc/vty_interface_layer3.c
index a38d15b..f31f05b 100644
--- a/src/libmsc/vty_interface_layer3.c
+++ b/src/libmsc/vty_interface_layer3.c
@@ -1,6 +1,6 @@
 /* OpenBSC interface to quagga VTY */
 /* (C) 2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009 by Holger Hans Peter Freyther
+ * (C) 2009-2011 by Holger Hans Peter Freyther
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -21,7 +21,6 @@
 #include <stdlib.h>
 #include <limits.h>
 #include <unistd.h>
-#include <sys/types.h>
 
 #include <osmocom/vty/command.h>
 #include <osmocom/vty/buffer.h>
@@ -29,17 +28,17 @@
 
 #include <arpa/inet.h>
 
-#include <osmocore/linuxlist.h>
+#include <osmocom/core/linuxlist.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/gsm_subscriber.h>
 #include <openbsc/silent_call.h>
 #include <openbsc/gsm_04_11.h>
 #include <openbsc/e1_input.h>
 #include <openbsc/abis_nm.h>
-#include <osmocore/gsm_utils.h>
-#include <osmocore/utils.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/core/utils.h>
 #include <openbsc/db.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/signal.h>
 #include <openbsc/debug.h>
 #include <openbsc/vty.h>
@@ -75,7 +74,7 @@
 		vty_out(vty, "    A3A8 algorithm id: %d%s",
 			ainfo.auth_algo, VTY_NEWLINE);
 		vty_out(vty, "    A3A8 Ki: %s%s",
-			hexdump(ainfo.a3a8_ki, ainfo.a3a8_ki_len),
+			osmo_hexdump(ainfo.a3a8_ki, ainfo.a3a8_ki_len),
 			VTY_NEWLINE);
 	}
 
@@ -86,13 +85,13 @@
 		vty_out(vty, "     seq # : %d%s",
 			atuple.key_seq, VTY_NEWLINE);
 		vty_out(vty, "     RAND  : %s%s",
-			hexdump(atuple.rand, sizeof(atuple.rand)),
+			osmo_hexdump(atuple.rand, sizeof(atuple.rand)),
 			VTY_NEWLINE);
 		vty_out(vty, "     SRES  : %s%s",
-			hexdump(atuple.sres, sizeof(atuple.sres)),
+			osmo_hexdump(atuple.sres, sizeof(atuple.sres)),
 			VTY_NEWLINE);
 		vty_out(vty, "     Kc    : %s%s",
-			hexdump(atuple.kc, sizeof(atuple.kc)),
+			osmo_hexdump(atuple.kc, sizeof(atuple.kc)),
 			VTY_NEWLINE);
 	}
 	if (pending)
@@ -142,7 +141,7 @@
 }
 
 static int _send_sms_str(struct gsm_subscriber *receiver, char *str,
-			 u_int8_t tp_pid)
+			 uint8_t tp_pid)
 {
 	struct gsm_sms *sms;
 
@@ -456,7 +455,7 @@
 	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
 	struct gsm_subscriber *subscr =
 			get_subscr_by_argv(gsmnet, argv[0], argv[1]);
-	const char *name = argv[2];
+	const char *ext = argv[2];
 
 	if (!subscr) {
 		vty_out(vty, "%% No subscriber found for %s %s%s",
@@ -464,7 +463,7 @@
 		return CMD_WARNING;
 	}
 
-	strncpy(subscr->extension, name, sizeof(subscr->name));
+	strncpy(subscr->extension, ext, sizeof(subscr->extension));
 	db_sync_subscriber(subscr);
 
 	subscr_put(subscr);
@@ -576,13 +575,17 @@
 	} else {
 		/* Unknown method */
 		subscr_put(subscr);
+		vty_out(vty, "%% Unknown auth method %s%s",
+				alg_str, VTY_NEWLINE);
 		return CMD_WARNING;
 	}
 
 	if (ki_str) {
-		rc = hexparse(ki_str, ainfo.a3a8_ki, sizeof(ainfo.a3a8_ki));
+		rc = osmo_hexparse(ki_str, ainfo.a3a8_ki, sizeof(ainfo.a3a8_ki));
 		if ((rc > maxlen) || (rc < minlen)) {
 			subscr_put(subscr);
+			vty_out(vty, "%% Wrong Ki `%s'%s",
+				ki_str, VTY_NEWLINE);
 			return CMD_WARNING;
 		}
 		ainfo.a3a8_ki_len = rc;
@@ -590,6 +593,7 @@
 		ainfo.a3a8_ki_len = 0;
 		if (minlen) {
 			subscr_put(subscr);
+			vty_out(vty, "%% Missing Ki argument%s", VTY_NEWLINE);
 			return CMD_WARNING;
 		}
 	}
@@ -602,7 +606,11 @@
 	db_sync_lastauthtuple_for_subscr(NULL, subscr);
 	subscr_put(subscr);
 
-	return rc ? CMD_WARNING : CMD_SUCCESS;
+	if (rc) {
+		vty_out(vty, "%% Operation has failed%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	return CMD_SUCCESS;
 }
 
 DEFUN(subscriber_purge,
@@ -665,37 +673,37 @@
 
 	openbsc_vty_print_statistics(vty, net);
 	vty_out(vty, "Channel Requests        : %lu total, %lu no channel%s",
-		counter_get(net->stats.chreq.total),
-		counter_get(net->stats.chreq.no_channel), VTY_NEWLINE);
+		osmo_counter_get(net->stats.chreq.total),
+		osmo_counter_get(net->stats.chreq.no_channel), VTY_NEWLINE);
 	vty_out(vty, "Location Update         : %lu attach, %lu normal, %lu periodic%s",
-		counter_get(net->stats.loc_upd_type.attach),
-		counter_get(net->stats.loc_upd_type.normal),
-		counter_get(net->stats.loc_upd_type.periodic), VTY_NEWLINE);
+		osmo_counter_get(net->stats.loc_upd_type.attach),
+		osmo_counter_get(net->stats.loc_upd_type.normal),
+		osmo_counter_get(net->stats.loc_upd_type.periodic), VTY_NEWLINE);
 	vty_out(vty, "IMSI Detach Indications : %lu%s",
-		counter_get(net->stats.loc_upd_type.detach), VTY_NEWLINE);
+		osmo_counter_get(net->stats.loc_upd_type.detach), VTY_NEWLINE);
 	vty_out(vty, "Location Update Response: %lu accept, %lu reject%s",
-		counter_get(net->stats.loc_upd_resp.accept),
-		counter_get(net->stats.loc_upd_resp.reject), VTY_NEWLINE);
+		osmo_counter_get(net->stats.loc_upd_resp.accept),
+		osmo_counter_get(net->stats.loc_upd_resp.reject), VTY_NEWLINE);
 	vty_out(vty, "Handover                : %lu attempted, %lu no_channel, %lu timeout, "
 		"%lu completed, %lu failed%s",
-		counter_get(net->stats.handover.attempted),
-		counter_get(net->stats.handover.no_channel),
-		counter_get(net->stats.handover.timeout),
-		counter_get(net->stats.handover.completed),
-		counter_get(net->stats.handover.failed), VTY_NEWLINE);
+		osmo_counter_get(net->stats.handover.attempted),
+		osmo_counter_get(net->stats.handover.no_channel),
+		osmo_counter_get(net->stats.handover.timeout),
+		osmo_counter_get(net->stats.handover.completed),
+		osmo_counter_get(net->stats.handover.failed), VTY_NEWLINE);
 	vty_out(vty, "SMS MO                  : %lu submitted, %lu no receiver%s",
-		counter_get(net->stats.sms.submitted),
-		counter_get(net->stats.sms.no_receiver), VTY_NEWLINE);
+		osmo_counter_get(net->stats.sms.submitted),
+		osmo_counter_get(net->stats.sms.no_receiver), VTY_NEWLINE);
 	vty_out(vty, "SMS MT                  : %lu delivered, %lu no memory, %lu other error%s",
-		counter_get(net->stats.sms.delivered),
-		counter_get(net->stats.sms.rp_err_mem),
-		counter_get(net->stats.sms.rp_err_other), VTY_NEWLINE);
+		osmo_counter_get(net->stats.sms.delivered),
+		osmo_counter_get(net->stats.sms.rp_err_mem),
+		osmo_counter_get(net->stats.sms.rp_err_other), VTY_NEWLINE);
 	vty_out(vty, "MO Calls                : %lu setup, %lu connect ack%s",
-		counter_get(net->stats.call.mo_setup),
-		counter_get(net->stats.call.mo_connect_ack), VTY_NEWLINE);
+		osmo_counter_get(net->stats.call.mo_setup),
+		osmo_counter_get(net->stats.call.mo_connect_ack), VTY_NEWLINE);
 	vty_out(vty, "MT Calls                : %lu setup, %lu connect%s",
-		counter_get(net->stats.call.mt_setup),
-		counter_get(net->stats.call.mt_connect), VTY_NEWLINE);
+		osmo_counter_get(net->stats.call.mt_setup),
+		osmo_counter_get(net->stats.call.mt_connect), VTY_NEWLINE);
 	return CMD_SUCCESS;
 }
 
@@ -756,7 +764,7 @@
 
 int bsc_vty_init_extra(void)
 {
-	register_signal_handler(SS_SCALL, scall_cbfn, NULL);
+	osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL);
 
 	install_element_ve(&show_subscr_cmd);
 	install_element_ve(&show_subscr_cache_cmd);
diff --git a/src/libtrau/Makefile.am b/src/libtrau/Makefile.am
index 01ed251..6b70a9a 100644
--- a/src/libtrau/Makefile.am
+++ b/src/libtrau/Makefile.am
@@ -1,6 +1,6 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
 AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 
 noinst_LIBRARIES = libtrau.a
 
diff --git a/src/libtrau/Makefile.in b/src/libtrau/Makefile.in
index 9da0496..0aacd1c 100644
--- a/src/libtrau/Makefile.in
+++ b/src/libtrau/Makefile.in
@@ -35,7 +35,7 @@
 subdir = src/libtrau
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -111,6 +111,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -181,7 +183,7 @@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
 AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 noinst_LIBRARIES = libtrau.a
 libtrau_a_SOURCES = rtp_proxy.c subchan_demux.c trau_frame.c trau_mux.c trau_upqueue.c
 all: all-am
diff --git a/src/libtrau/rtp_proxy.c b/src/libtrau/rtp_proxy.c
index eefc0e1..4c5f12e 100644
--- a/src/libtrau/rtp_proxy.c
+++ b/src/libtrau/rtp_proxy.c
@@ -28,15 +28,15 @@
 #include <time.h>        /* clock() */
 #include <sys/utsname.h> /* uname() */
 
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/gsm_data.h>
-#include <osmocore/msgb.h>
-#include <osmocore/select.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/select.h>
 #include <openbsc/debug.h>
 #include <openbsc/rtp_proxy.h>
+#include <openbsc/mncc.h>
 
 /* attempt to determine byte order */
-#include <sys/types.h>
 #include <sys/param.h>
 #include <limits.h>
 
@@ -60,9 +60,9 @@
 
 /* according to RFC 1889 */
 struct rtcp_hdr {
-	u_int8_t byte0;
-	u_int8_t type;
-	u_int16_t length;
+	uint8_t byte0;
+	uint8_t type;
+	uint16_t length;
 } __attribute__((packed));
 
 #define RTCP_TYPE_SDES	202
@@ -72,40 +72,40 @@
 /* according to RFC 3550 */
 struct rtp_hdr {
 #if __BYTE_ORDER == __LITTLE_ENDIAN
-	u_int8_t  csrc_count:4,
+	uint8_t  csrc_count:4,
 		  extension:1,
 		  padding:1,
 		  version:2;
-	u_int8_t  payload_type:7,
+	uint8_t  payload_type:7,
 		  marker:1;
 #elif __BYTE_ORDER == __BIG_ENDIAN
-	u_int8_t  version:2,
+	uint8_t  version:2,
 		  padding:1,
 		  extension:1,
 		  csrc_count:4;
-	u_int8_t  marker:1,
+	uint8_t  marker:1,
 		  payload_type:7;
 #endif
-	u_int16_t sequence;
-	u_int32_t timestamp;
-	u_int32_t ssrc;
+	uint16_t sequence;
+	uint32_t timestamp;
+	uint32_t ssrc;
 } __attribute__((packed));
 
 struct rtp_x_hdr {
-	u_int16_t by_profile;
-	u_int16_t length;
+	uint16_t by_profile;
+	uint16_t length;
 } __attribute__((packed));
 
 #define RTP_VERSION	2
 
 /* decode an rtp frame and create a new buffer with payload */
-static int rtp_decode(struct msgb *msg, u_int32_t callref, struct msgb **data)
+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;
-	u_int8_t *payload;
+	uint8_t *payload;
 	int payload_len;
 	int msg_type;
 	int x_len;
@@ -286,11 +286,11 @@
 /* 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,
-				  u_int16_t *rtcp_len, const char *new_cname)
+				  uint16_t *rtcp_len, const char *new_cname)
 {
-	u_int8_t *rtcp_end;
-	u_int8_t *cur = (u_int8_t *) rh;
-	u_int8_t tag, len = 0;
+	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 */
@@ -343,7 +343,7 @@
 {
 	struct rtp_sub_socket *rss = &rs->rtcp;
 	struct rtcp_hdr *rtph;
-	u_int16_t old_len;
+	uint16_t old_len;
 	int rc;
 
 	if (!mangle_rtcp_cname)
@@ -483,7 +483,7 @@
 
 
 /* callback for the select.c:bfd_* layer */
-static int rtp_bfd_cb(struct bsc_fd *bfd, unsigned int flags)
+static int rtp_bfd_cb(struct osmo_fd *bfd, unsigned int flags)
 {
 	struct rtp_socket *rs = bfd->data;
 	struct rtp_sub_socket *rss;
@@ -537,7 +537,7 @@
 		goto out_free;
 
 	init_rss(&rs->rtp, rs, rc, RTP_PRIV_RTP);
-	rc = bsc_register_fd(&rs->rtp.bfd);
+	rc = osmo_fd_register(&rs->rtp.bfd);
 	if (rc < 0)
 		goto out_rtp_socket;
 
@@ -546,7 +546,7 @@
 		goto out_rtp_bfd;
 
 	init_rss(&rs->rtcp, rs, rc, RTP_PRIV_RTCP);
-	rc = bsc_register_fd(&rs->rtcp.bfd);
+	rc = osmo_fd_register(&rs->rtcp.bfd);
 	if (rc < 0)
 		goto out_rtcp_socket;
 
@@ -559,11 +559,11 @@
 	return rs;
 
 out_rtcp_bfd:
-	bsc_unregister_fd(&rs->rtcp.bfd);
+	osmo_fd_unregister(&rs->rtcp.bfd);
 out_rtcp_socket:
 	close(rs->rtcp.bfd.fd);
 out_rtp_bfd:
-	bsc_unregister_fd(&rs->rtp.bfd);
+	osmo_fd_unregister(&rs->rtp.bfd);
 out_rtp_socket:
 	close(rs->rtp.bfd.fd);
 out_free:
@@ -572,8 +572,8 @@
 	return NULL;
 }
 
-static int rtp_sub_socket_bind(struct rtp_sub_socket *rss, u_int32_t ip,
-				u_int16_t port)
+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);
@@ -598,7 +598,7 @@
 static unsigned int next_udp_port = RTP_PORT_BASE;
 
 /* bind a RTP socket to a local address */
-int rtp_socket_bind(struct rtp_socket *rs, u_int32_t ip)
+int rtp_socket_bind(struct rtp_socket *rs, uint32_t ip)
 {
 	int rc = -EIO;
 	struct in_addr ia;
@@ -630,7 +630,7 @@
 }
 
 static int rtp_sub_socket_connect(struct rtp_sub_socket *rss,
-				  u_int32_t ip, u_int16_t port)
+				  uint32_t ip, uint16_t port)
 {
 	int rc;
 	socklen_t alen = sizeof(rss->sin_local);
@@ -649,7 +649,7 @@
 }
 
 /* 'connect' a RTP socket to a remote peer */
-int rtp_socket_connect(struct rtp_socket *rs, u_int32_t ip, u_int16_t port)
+int rtp_socket_connect(struct rtp_socket *rs, uint32_t ip, uint16_t port)
 {
 	int rc;
 	struct in_addr ia;
@@ -682,7 +682,7 @@
 
 /* bind RTP/RTCP socket to application */
 int rtp_socket_upstream(struct rtp_socket *this, struct gsm_network *net,
-			u_int32_t callref)
+			uint32_t callref)
 {
 	DEBUGP(DMUX, "rtp_socket_proxy(this=%p, callref=%u)\n",
 		this, callref);
@@ -714,11 +714,11 @@
 	    rs->proxy.other_sock)
 		rs->proxy.other_sock->proxy.other_sock = NULL;
 
-	bsc_unregister_fd(&rs->rtp.bfd);
+	osmo_fd_unregister(&rs->rtp.bfd);
 	close(rs->rtp.bfd.fd);
 	free_tx_queue(&rs->rtp);
 
-	bsc_unregister_fd(&rs->rtcp.bfd);
+	osmo_fd_unregister(&rs->rtcp.bfd);
 	close(rs->rtcp.bfd.fd);
 	free_tx_queue(&rs->rtcp);
 
diff --git a/src/libtrau/subchan_demux.c b/src/libtrau/subchan_demux.c
index 6bcf279..740d2ca 100644
--- a/src/libtrau/subchan_demux.c
+++ b/src/libtrau/subchan_demux.c
@@ -27,22 +27,22 @@
 #include <openbsc/subchan_demux.h>
 #include <openbsc/trau_frame.h>
 #include <openbsc/debug.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/gsm_data.h>
 
 void *tall_tqe_ctx;
 
-static inline void append_bit(struct demux_subch *sch, u_int8_t bit)
+static inline void append_bit(struct demux_subch *sch, uint8_t bit)
 {
 	sch->out_bitbuf[sch->out_idx++] = bit;
 }
 
 #define SYNC_HDR_BITS	16
-static const u_int8_t nullbytes[SYNC_HDR_BITS];
+static const uint8_t nullbytes[SYNC_HDR_BITS];
 
 /* check if we have just completed the 16 bit zero sync header,
  * in accordance with GSM TS 08.60 Chapter 4.8.1 */
-static int sync_hdr_complete(struct demux_subch *sch, u_int8_t bit)
+static int sync_hdr_complete(struct demux_subch *sch, uint8_t bit)
 {
 	if (bit == 0)
 		sch->consecutive_zeros++;
@@ -83,7 +83,7 @@
 
 /* input some arbitrary (modulo 4) number of bytes of a 64k E1 channel,
  * split it into the 16k subchannels */
-int subch_demux_in(struct subch_demux *dmx, u_int8_t *data, int len)
+int subch_demux_in(struct subch_demux *dmx, uint8_t *data, int len)
 {
 	int i, c;
 
@@ -92,12 +92,12 @@
 		return -EINVAL;
 
 	for (i = 0; i < len; i++) {
-		u_int8_t inbyte = data[i];
+		uint8_t inbyte = data[i];
 
 		for (c = 0; c < NR_SUBCH; c++) {
 			struct demux_subch *sch = &dmx->subch[c];
-			u_int8_t inbits;
-			u_int8_t bit;
+			uint8_t inbits;
+			uint8_t bit;
 
 			/* ignore inactive subchannels */
 			if (!(dmx->chan_activ & (1 << c)))
@@ -171,7 +171,7 @@
 
 /* return the requested number of bits from the specified subchannel */
 static int get_subch_bits(struct subch_mux *mx, int subch,
-			  u_int8_t *bits, int num_requested)
+			  uint8_t *bits, int num_requested)
 {
 	struct mux_subch *sch = &mx->subch[subch];
 	int num_bits = 0;
@@ -215,9 +215,9 @@
 }
 
 /* compact an array of 8 single-bit bytes into one byte of 8 bits */
-static u_int8_t compact_bits(const u_int8_t *bits)
+static uint8_t compact_bits(const uint8_t *bits)
 {
-	u_int8_t ret = 0;
+	uint8_t ret = 0;
 	int i;
 
 	for (i = 0; i < 8; i++)
@@ -227,9 +227,9 @@
 }
 
 /* obtain a single output byte from the subchannel muxer */
-static int mux_output_byte(struct subch_mux *mx, u_int8_t *byte)
+static int mux_output_byte(struct subch_mux *mx, uint8_t *byte)
 {
-	u_int8_t bits[8];
+	uint8_t bits[8];
 	int rc;
 
 	/* combine two bits of every subchan */
@@ -244,7 +244,7 @@
 }
 
 /* Request the output of some muxed bytes from the subchan muxer */
-int subchan_mux_out(struct subch_mux *mx, u_int8_t *data, int len)
+int subchan_mux_out(struct subch_mux *mx, uint8_t *data, int len)
 {
 	int i;
 
@@ -285,7 +285,7 @@
 }
 
 /* enqueue some data into the tx_queue of a given subchannel */
-int subchan_mux_enqueue(struct subch_mux *mx, int s_nr, const u_int8_t *data,
+int subchan_mux_enqueue(struct subch_mux *mx, int s_nr, const uint8_t *data,
 			int len)
 {
 	struct mux_subch *sch = &mx->subch[s_nr];
diff --git a/src/libtrau/trau_frame.c b/src/libtrau/trau_frame.c
index d4d6447..15cbe4f 100644
--- a/src/libtrau/trau_frame.c
+++ b/src/libtrau/trau_frame.c
@@ -28,10 +28,10 @@
 #include <openbsc/subchan_demux.h>
 #include <openbsc/debug.h>
 
-static u_int32_t get_bits(const u_int8_t *bitbuf, int offset, int num)
+static uint32_t get_bits(const uint8_t *bitbuf, int offset, int num)
 {
 	int i;
-	u_int32_t ret = 0;
+	uint32_t ret = 0;
 
 	for (i = offset; i < offset + num; i++) {
 		ret = ret << 1;
@@ -42,7 +42,7 @@
 }
 
 /* Decode according to 3.1.1 */
-static void decode_fr(struct decoded_trau_frame *fr, const u_int8_t *trau_bits)
+static void decode_fr(struct decoded_trau_frame *fr, const uint8_t *trau_bits)
 {
 	int i;
 	int d_idx = 0;
@@ -63,7 +63,7 @@
 }
 
 /* Decode according to 3.1.2 */
-static void decode_amr(struct decoded_trau_frame *fr, const u_int8_t *trau_bits)
+static void decode_amr(struct decoded_trau_frame *fr, const uint8_t *trau_bits)
 {
 	int i;
 	int d_idx = 0;
@@ -85,9 +85,9 @@
 	memcpy(fr->d_bits + d_idx, trau_bits + 305, 11);
 }
 
-int decode_trau_frame(struct decoded_trau_frame *fr, const u_int8_t *trau_bits)
+int decode_trau_frame(struct decoded_trau_frame *fr, const uint8_t *trau_bits)
 {
-	u_int8_t cbits5 = get_bits(trau_bits, 17, 5);
+	uint8_t cbits5 = get_bits(trau_bits, 17, 5);
 
 	switch (cbits5) {
 	case TRAU_FT_FR_UP:
@@ -120,13 +120,13 @@
 	return 0;
 }
 
-const u_int8_t ft_fr_down_bits[] = { 1, 1, 1, 0, 0 };
-const u_int8_t ft_idle_down_bits[] = { 0, 1, 1, 1, 0 };
+const uint8_t ft_fr_down_bits[] = { 1, 1, 1, 0, 0 };
+const uint8_t ft_idle_down_bits[] = { 0, 1, 1, 1, 0 };
 
 /* modify an uplink TRAU frame so we can send it downlink */
 int trau_frame_up2down(struct decoded_trau_frame *fr)
 {
-	u_int8_t cbits5 = get_bits(fr->c_bits, 0, 5);
+	uint8_t cbits5 = get_bits(fr->c_bits, 0, 5);
 
 	switch (cbits5) {
 	case TRAU_FT_FR_UP:
@@ -178,7 +178,7 @@
 
 }
 
-static void encode_fr(u_int8_t *trau_bits, const struct decoded_trau_frame *fr)
+static void encode_fr(uint8_t *trau_bits, const struct decoded_trau_frame *fr)
 {
 	int i;
 	int d_idx = 0;
@@ -205,9 +205,9 @@
 }
 
 
-int encode_trau_frame(u_int8_t *trau_bits, const struct decoded_trau_frame *fr)
+int encode_trau_frame(uint8_t *trau_bits, const struct decoded_trau_frame *fr)
 {
-	u_int8_t cbits5 = get_bits(fr->c_bits, 0, 5);
+	uint8_t cbits5 = get_bits(fr->c_bits, 0, 5);
 	
 	/* 16 bits of sync header */
 	memset(trau_bits, 0, 16);
@@ -245,10 +245,10 @@
 	.c_bits = { 0, 1, 1, 1, 0 },	/* IDLE DOWNLINK 3.5.5 */
 	.t_bits = { 1, 1, 1, 1 },
 };
-static u_int8_t encoded_idle_frame[TRAU_FRAME_BITS];
+static uint8_t encoded_idle_frame[TRAU_FRAME_BITS];
 static int dbits_initted;
 
-u_int8_t *trau_idle_frame(void)
+uint8_t *trau_idle_frame(void)
 {
 	/* only initialize during the first call */
 	if (!dbits_initted) {
diff --git a/src/libtrau/trau_mux.c b/src/libtrau/trau_mux.c
index 712e22d..b8b90bd 100644
--- a/src/libtrau/trau_mux.c
+++ b/src/libtrau/trau_mux.c
@@ -21,7 +21,6 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/types.h>
 
 #include <openbsc/gsm_data.h>
 #include <openbsc/trau_frame.h>
@@ -29,9 +28,9 @@
 #include <openbsc/subchan_demux.h>
 #include <openbsc/e1_input.h>
 #include <openbsc/debug.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 
-u_int8_t gsm_fr_map[] = {
+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,
@@ -53,7 +52,7 @@
 	struct llist_head list;
 	struct gsm_network *net;
 	struct gsm_e1_subslot src;
-	u_int32_t callref;
+	uint32_t callref;
 };
 
 static LLIST_HEAD(ss_map);
@@ -102,7 +101,7 @@
 
 
 /* unmap one particular subslot from another subslot */
-int trau_mux_unmap(const struct gsm_e1_subslot *ss, u_int32_t callref)
+int trau_mux_unmap(const struct gsm_e1_subslot *ss, uint32_t callref)
 {
 	struct map_entry *me, *me2;
 	struct upqueue_entry *ue, *ue2;
@@ -156,14 +155,14 @@
 	return NULL;
 }
 
-static const u_int8_t c_bits_check[] = { 0, 0, 0, 1, 0 };
+static const uint8_t c_bits_check[] = { 0, 0, 0, 1, 0 };
 
 /* we get called by subchan_demux */
 int trau_mux_input(struct gsm_e1_subslot *src_e1_ss,
-		   const u_int8_t *trau_bits, int num_bits)
+		   const uint8_t *trau_bits, int num_bits)
 {
 	struct decoded_trau_frame tf;
-	u_int8_t trau_bits_out[TRAU_FRAME_BITS];
+	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;
@@ -186,7 +185,7 @@
 			return -EINVAL;
 		if (memcmp(tf.c_bits, c_bits_check, sizeof(c_bits_check)))
 			DEBUGPC(DMUX, "illegal trau (C1-C5) %s\n",
-				hexdump(tf.c_bits, sizeof(c_bits_check)));
+				osmo_hexdump(tf.c_bits, sizeof(c_bits_check)));
 		msg = msgb_alloc(sizeof(struct gsm_data_frame) + 33,
 				 "GSM-DATA");
 		if (!msg)
@@ -231,7 +230,7 @@
 }
 
 /* add receiver instance for lchan and callref */
-int trau_recv_lchan(struct gsm_lchan *lchan, u_int32_t callref)
+int trau_recv_lchan(struct gsm_lchan *lchan, uint32_t callref)
 {
 	struct gsm_e1_subslot *src_ss;
 	struct upqueue_entry *ue;
@@ -260,7 +259,7 @@
 
 int trau_send_frame(struct gsm_lchan *lchan, struct gsm_data_frame *frame)
 {
-	u_int8_t trau_bits_out[TRAU_FRAME_BITS];
+	uint8_t trau_bits_out[TRAU_FRAME_BITS];
 	struct gsm_e1_subslot *dst_e1_ss = &lchan->ts->e1_link;
 	struct subch_mux *mx;
 	int i, j, k, l, o;
diff --git a/src/osmo-bsc/Makefile.am b/src/osmo-bsc/Makefile.am
index 95b9ef4..9a7619b 100644
--- a/src/osmo-bsc/Makefile.am
+++ b/src/osmo-bsc/Makefile.am
@@ -1,6 +1,6 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
 
 bin_PROGRAMS = osmo-bsc
 
diff --git a/src/osmo-bsc/Makefile.in b/src/osmo-bsc/Makefile.in
index d83952c..b173f15 100644
--- a/src/osmo-bsc/Makefile.in
+++ b/src/osmo-bsc/Makefile.in
@@ -36,7 +36,7 @@
 subdir = src/osmo-bsc
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -117,6 +117,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -186,8 +188,8 @@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
 osmo_bsc_SOURCES = osmo_bsc_main.c osmo_bsc_rf.c osmo_bsc_vty.c osmo_bsc_api.c \
 		   osmo_bsc_grace.c osmo_bsc_msc.c osmo_bsc_sccp.c \
 		   osmo_bsc_filter.c osmo_bsc_bssap.c osmo_bsc_audio.c
diff --git a/src/osmo-bsc/osmo_bsc_api.c b/src/osmo-bsc/osmo_bsc_api.c
index b8cbcf2..a943a0c 100644
--- a/src/osmo-bsc/osmo_bsc_api.c
+++ b/src/osmo-bsc/osmo_bsc_api.c
@@ -21,8 +21,8 @@
 #include <openbsc/osmo_msc_data.h>
 #include <openbsc/debug.h>
 
-#include <osmocore/protocol/gsm_08_08.h>
-#include <osmocore/gsm0808.h>
+#include <osmocom/gsm/protocol/gsm_08_08.h>
+#include <osmocom/gsm/gsm0808.h>
 
 #define return_when_not_connected(conn) \
 	if (!conn->sccp_con) {\
diff --git a/src/osmo-bsc/osmo_bsc_audio.c b/src/osmo-bsc/osmo_bsc_audio.c
index 515cfa7..64260aa 100644
--- a/src/osmo-bsc/osmo_bsc_audio.c
+++ b/src/osmo-bsc/osmo_bsc_audio.c
@@ -65,6 +65,6 @@
 int osmo_bsc_audio_init(struct gsm_network *net)
 {
 	net->hardcoded_rtp_payload = 98;
-	register_signal_handler(SS_ABISIP, handle_abisip_signal, 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
index f871131..a3ba2ad 100644
--- a/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/src/osmo-bsc/osmo_bsc_bssap.c
@@ -26,8 +26,8 @@
 #include <openbsc/mgcp.h>
 #include <openbsc/paging.h>
 
-#include <osmocore/gsm0808.h>
-#include <osmocore/protocol/gsm_08_08.h>
+#include <osmocom/gsm/protocol/gsm_08_08.h>
+#include <osmocom/gsm/gsm0808.h>
 
 #include <arpa/inet.h>
 
@@ -158,7 +158,7 @@
 	if (data_length == 3 && data[0] == CELL_IDENT_LAC) {
 		lac = ntohs(read_data16(&data[1]));
 	} else if (data_length > 1 || (data[0] & 0x0f) != CELL_IDENT_BSS) {
-		LOGP(DMSC, LOGL_ERROR, "Unsupported Cell Identifier List: %s\n", hexdump(data, data_length));
+		LOGP(DMSC, LOGL_ERROR, "Unsupported Cell Identifier List: %s\n", osmo_hexdump(data, data_length));
 		return -1;
 	}
 
@@ -467,13 +467,13 @@
 	header = (struct dtap_header *) msg->l3h;
 	if (sizeof(*header) >= length) {
 		LOGP(DMSC, LOGL_ERROR, "The DTAP header does not fit. Wanted: %u got: %u\n", sizeof(*header), length);
-                LOGP(DMSC, LOGL_ERROR, "hex: %s\n", hexdump(msg->l3h, 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", hexdump(msg->l3h, length));
+                LOGP(DMSC, LOGL_ERROR, "hex: %s\n", osmo_hexdump(msg->l3h, length));
 		return -1;
 	}
 
@@ -502,7 +502,7 @@
 	struct bssmap_header *bs;
 
 	LOGP(DMSC, LOGL_DEBUG, "Incoming SCCP message ftom MSC: %s\n",
-		hexdump(msgb->l3h, length));
+		osmo_hexdump(msgb->l3h, length));
 
 	if (length < sizeof(*bs)) {
 		LOGP(DMSC, LOGL_ERROR, "The header is too short.\n");
diff --git a/src/osmo-bsc/osmo_bsc_grace.c b/src/osmo-bsc/osmo_bsc_grace.c
index f699cf3..c67984b 100644
--- a/src/osmo-bsc/osmo_bsc_grace.c
+++ b/src/osmo-bsc/osmo_bsc_grace.c
@@ -103,5 +103,5 @@
 
 static __attribute__((constructor)) void on_dso_load_grace(void)
 {
-	register_signal_handler(SS_RF, handle_rf_signal, NULL);
+	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
index b5f64ab..42c74cc 100644
--- a/src/osmo-bsc/osmo_bsc_main.c
+++ b/src/osmo-bsc/osmo_bsc_main.c
@@ -1,6 +1,6 @@
 /* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2010 by On-Waves
+ * (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
@@ -26,8 +26,9 @@
 #include <openbsc/signal.h>
 #include <openbsc/vty.h>
 
-#include <osmocore/talloc.h>
-#include <osmocore/process.h>
+#include <osmocom/core/application.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/process.h>
 
 #include <osmocom/sccp/sccp.h>
 
@@ -43,18 +44,15 @@
 
 #include "../../bscconfig.h"
 
-static struct log_target *stderr_target;
 struct gsm_network *bsc_gsmnet = 0;
 static const char *config_file = "openbsc.cfg";
 static const char *rf_ctl = NULL;
 extern const char *openbsc_copyright;
 static int daemonize = 0;
 
-extern int bsc_bootstrap_network(int (*layer4)(struct gsm_network *, struct msgb *), const char *cfg_file);
-
 static void print_usage()
 {
-	printf("Usage: bsc_msc_ip\n");
+	printf("Usage: osmo-bsc\n");
 }
 
 static void print_help()
@@ -101,10 +99,10 @@
 			print_help();
 			exit(0);
 		case 's':
-			log_set_use_color(stderr_target, 0);
+			log_set_use_color(osmo_stderr_target, 0);
 			break;
 		case 'd':
-			log_parse_category_mask(stderr_target, optarg);
+			log_parse_category_mask(osmo_stderr_target, optarg);
 			break;
 		case 'D':
 			daemonize = 1;
@@ -113,13 +111,10 @@
 			config_file = strdup(optarg);
 			break;
 		case 'T':
-			log_set_print_timestamp(stderr_target, 1);
-			break;
-		case 'P':
-			ipacc_rtp_direct = 0;
+			log_set_print_timestamp(osmo_stderr_target, 1);
 			break;
 		case 'e':
-			log_set_log_level(stderr_target, atoi(optarg));
+			log_set_log_level(osmo_stderr_target, atoi(optarg));
 			break;
 		case 'r':
 			rf_ctl = optarg;
@@ -131,10 +126,6 @@
 	}
 }
 
-extern int bts_model_unknown_init(void);
-extern int bts_model_bs11_init(void);
-extern int bts_model_nanobts_init(void);
-
 extern enum node_type bsc_vty_go_parent(struct vty *vty);
 
 static struct vty_app_info vty_info = {
@@ -152,7 +143,7 @@
 	switch (signal) {
 	case SIGINT:
 		bsc_shutdown_net(bsc_gsmnet);
-		dispatch_signal(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
+		osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
 		sleep(3);
 		exit(0);
 		break;
@@ -179,24 +170,22 @@
 
 int main(int argc, char **argv)
 {
+	struct osmo_msc_data *data;
 	int rc;
 
-	log_init(&log_info);
 	tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
-	stderr_target = log_target_create_stderr();
-	log_add_target(stderr_target);
 
-	bts_model_unknown_init();
-	bts_model_bs11_init();
-	bts_model_nanobts_init();
+	osmo_init_logging(&log_info);
+
+	bts_init();
+	e1inp_init();
 
 	/* enable filters */
-	log_set_all_filter(stderr_target, 1);
 
 	/* This needs to precede handle_options() */
 	vty_info.copyright = openbsc_copyright;
 	vty_init(&vty_info);
-	bsc_vty_init();
+	bsc_vty_init(&log_info);
 
 	/* parse options */
 	handle_options(argc, argv);
@@ -215,9 +204,13 @@
 	}
 	bsc_api_init(bsc_gsmnet, osmo_bsc_api());
 
-	if (rf_ctl) {
-		struct osmo_msc_data *data = bsc_gsmnet->msc_data;
-		data->rf_ctl = osmo_bsc_rf_create(rf_ctl, bsc_gsmnet);
+	data = bsc_gsmnet->msc_data;
+	if (rf_ctl)
+		bsc_replace_string(data, &data->rf_ctrl_name, rf_ctl);
+
+	if (data->rf_ctrl_name) {
+		data->rf_ctl = osmo_bsc_rf_create(data->rf_ctrl_name,
+						  bsc_gsmnet);
 		if (!data->rf_ctl) {
 			fprintf(stderr, "Failed to create the RF service.\n");
 			exit(1);
@@ -243,7 +236,7 @@
 	signal(SIGABRT, &signal_handler);
 	signal(SIGUSR1, &signal_handler);
 	signal(SIGUSR2, &signal_handler);
-	signal(SIGPIPE, SIG_IGN);
+	osmo_init_ignore_signals();
 
 	if (daemonize) {
 		rc = osmo_daemonize();
@@ -254,7 +247,7 @@
 	}
 
 	while (1) {
-		bsc_select_main(0);
+		osmo_select_main(0);
 	}
 
 	return 0;
diff --git a/src/osmo-bsc/osmo_bsc_msc.c b/src/osmo-bsc/osmo_bsc_msc.c
index 2e8cf05..2a32227 100644
--- a/src/osmo-bsc/osmo_bsc_msc.c
+++ b/src/osmo-bsc/osmo_bsc_msc.c
@@ -1,8 +1,8 @@
 /*
  * Handle the connection to the MSC. This include ping/timeout/reconnect
  * (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2010 by On-Waves
+ * (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
@@ -27,7 +27,7 @@
 #include <openbsc/osmo_msc_data.h>
 #include <openbsc/signal.h>
 
-#include <osmocore/gsm0808.h>
+#include <osmocom/gsm/gsm0808.h>
 
 #include <osmocom/sccp/sccp.h>
 
@@ -37,13 +37,14 @@
 
 
 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 osmo_msc_data *data, int fd);
 static void send_ping(struct osmo_msc_data *data);
 
 /*
  * MGCP forwarding code
  */
-static int mgcp_do_read(struct bsc_fd *fd)
+static int mgcp_do_read(struct osmo_fd *fd)
 {
 	struct osmo_msc_data *data = (struct osmo_msc_data *) fd->data;
 	struct msgb *mgcp;
@@ -71,7 +72,7 @@
 	return 0;
 }
 
-static int mgcp_do_write(struct bsc_fd *fd, struct msgb *msg)
+static int mgcp_do_write(struct osmo_fd *fd, struct msgb *msg)
 {
 	int ret;
 
@@ -101,7 +102,7 @@
 
 	msgb_put(mgcp, msgb_l2len(msg));
 	memcpy(mgcp->data, msg->l2h, mgcp->len);
-	if (write_queue_enqueue(&data->mgcp_agent, mgcp) != 0) {
+	if (osmo_wqueue_enqueue(&data->mgcp_agent, mgcp) != 0) {
 		LOGP(DMGCP, LOGL_FATAL, "Could not queue message to MGCP GW.\n");
 		msgb_free(mgcp);
 	}
@@ -143,13 +144,13 @@
 		return -1;
 	}
 
-	write_queue_init(&data->mgcp_agent, 10);
+	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 (bsc_register_fd(&data->mgcp_agent.bfd) != 0) {
+	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;
@@ -165,7 +166,7 @@
 int msc_queue_write(struct bsc_msc_connection *conn, struct msgb *msg, int proto)
 {
 	ipaccess_prepend_header(msg, proto);
-	if (write_queue_enqueue(&conn->write_queue, msg) != 0) {
+	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;
@@ -174,12 +175,12 @@
 	return 0;
 }
 
-static int msc_alink_do_write(struct bsc_fd *fd, struct msgb *msg)
+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(DMI, LOGL_DEBUG, "MSC TX %s\n", hexdump(msg->data, msg->len));
+	LOGP(DMI, LOGL_DEBUG, "MSC TX %s\n", osmo_hexdump(msg->data, msg->len));
 
 	ret = write(fd->fd, msg->data, msg->len);
 	if (ret < msg->len)
@@ -188,7 +189,26 @@
 	return ret;
 }
 
-static int ipaccess_a_fd_cb(struct bsc_fd *bfd)
+static void osmo_ext_handle(struct osmo_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);
+}
+
+static int ipaccess_a_fd_cb(struct osmo_fd *bfd)
 {
 	int error;
 	struct msgb *msg = ipaccess_read_msg(bfd, &error);
@@ -206,7 +226,7 @@
 		return -1;
 	}
 
-	LOGP(DMSC, LOGL_DEBUG, "From MSC: %s proto: %d\n", hexdump(msg->data, msg->len), msg->l2h[0]);
+	LOGP(DMSC, 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;
@@ -219,12 +239,14 @@
 		else if (msg->l2h[0] == IPAC_MSGT_ID_GET) {
 			send_id_get_response(data, bfd->fd);
 		} else if (msg->l2h[0] == IPAC_MSGT_PONG) {
-			bsc_del_timer(&data->pong_timer);
+			osmo_timer_del(&data->pong_timer);
 		}
 	} else if (hh->proto == IPAC_PROTO_SCCP) {
 		sccp_system_incoming(msg);
 	} 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);
@@ -256,10 +278,10 @@
 	send_ping(data);
 
 	/* send another ping in 20 seconds */
-	bsc_schedule_timer(&data->ping_timer, data->ping_timeout, 0);
+	osmo_timer_schedule(&data->ping_timer, data->ping_timeout, 0);
 
 	/* also start a pong timer */
-	bsc_schedule_timer(&data->pong_timer, data->pong_timeout, 0);
+	osmo_timer_schedule(&data->pong_timer, data->pong_timeout, 0);
 }
 
 static void msc_pong_timeout_cb(void *_data)
@@ -284,7 +306,7 @@
 	msc_ping_timeout_cb(data);
 
 	sig.data = data;
-	dispatch_signal(SS_MSC, S_MSC_CONNECTED, &sig);
+	osmo_signal_dispatch(SS_MSC, S_MSC_CONNECTED, &sig);
 }
 
 /*
@@ -299,16 +321,49 @@
 	LOGP(DMSC, LOGL_ERROR, "Lost MSC connection. Freing stuff.\n");
 
 	data = (struct osmo_msc_data *) msc->write_queue.bfd.data;
-	bsc_del_timer(&data->ping_timer);
-	bsc_del_timer(&data->pong_timer);
+	osmo_timer_del(&data->ping_timer);
+	osmo_timer_del(&data->pong_timer);
 
 	sig.data = data;
-	dispatch_signal(SS_MSC, S_MSC_LOST, &sig);
+	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;
+	ipaccess_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;
@@ -344,9 +399,7 @@
 	if (mgcp_create_port(data) != 0)
 		return -1;
 
-	data->msc_con = bsc_msc_create(data->msc_ip,
-				       data->msc_port,
-				       data->msc_ip_dscp);
+	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;
diff --git a/src/osmo-bsc/osmo_bsc_rf.c b/src/osmo-bsc/osmo_bsc_rf.c
index 5652c9d..cd64b52 100644
--- a/src/osmo-bsc/osmo_bsc_rf.c
+++ b/src/osmo-bsc/osmo_bsc_rf.c
@@ -25,9 +25,10 @@
 #include <openbsc/gsm_data.h>
 #include <openbsc/signal.h>
 #include <openbsc/osmo_msc_data.h>
+#include <openbsc/ipaccess.h>
 
-#include <osmocore/talloc.h>
-#include <osmocore/protocol/gsm_12_21.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/gsm/protocol/gsm_12_21.h>
 
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -68,7 +69,7 @@
 	msg->l2h = msgb_put(msg, 1);
 	msg->l2h[0] = send;
 
-	if (write_queue_enqueue(&conn->queue, msg) != 0) {
+	if (osmo_wqueue_enqueue(&conn->queue, msg) != 0) {
 		LOGP(DINP, LOGL_ERROR, "Failed to enqueue the answer.\n");
 		msgb_free(msg);
 		return;
@@ -95,8 +96,8 @@
 	llist_for_each_entry(bts, &conn->rf->gsm_network->bts_list, list) {
 		struct gsm_bts_trx *trx;
 		llist_for_each_entry(trx, &bts->trx_list, list) {
-			if (trx->nm_state.availability == NM_AVSTATE_OK &&
-			    trx->nm_state.operational != NM_STATE_LOCKED) {
+			if (trx->mo.nm_state.availability == NM_AVSTATE_OK &&
+			    trx->mo.nm_state.operational != NM_STATE_LOCKED) {
 					send = RF_CMD_ON;
 					break;
 			}
@@ -119,9 +120,9 @@
 			continue;
 
 		llist_for_each_entry(trx, &bts->trx_list, list) {
-			if (trx->nm_state.availability != NM_AVSTATE_OK ||
-			    trx->nm_state.operational != NM_OPSTATE_ENABLED ||
-			    trx->nm_state.administrative != NM_STATE_UNLOCKED) {
+			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;
@@ -136,7 +137,7 @@
 	sig.net = rf->gsm_network;
 
 	rf->policy = val;
-	dispatch_signal(SS_RF, val, &sig);
+	osmo_signal_dispatch(SS_RF, val, &sig);
 }
 
 static int switch_rf_off(struct osmo_bsc_rf *rf)
@@ -159,7 +160,7 @@
 {
 	rf->grace_timeout.cb = grace_timeout;
 	rf->grace_timeout.data = rf;
-	bsc_schedule_timer(&rf->grace_timeout, rf->gsm_network->msc_data->mid_call_timeout, 0);
+	osmo_timer_schedule(&rf->grace_timeout, rf->gsm_network->msc_data->mid_call_timeout, 0);
 	LOGP(DINP, LOGL_NOTICE, "Going to switch RF off in %d seconds.\n",
 	     rf->gsm_network->msc_data->mid_call_timeout);
 
@@ -174,26 +175,26 @@
 	switch (rf->last_request) {
 	case RF_CMD_D_OFF:
 		rf->last_state_command = "RF Direct Off";
-		bsc_del_timer(&rf->rf_check);
-		bsc_del_timer(&rf->grace_timeout);
+		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";
-		bsc_del_timer(&rf->grace_timeout);
+		osmo_timer_del(&rf->grace_timeout);
 		lock_each_trx(rf->gsm_network, 0);
 		send_signal(rf, S_RF_ON);
-		bsc_schedule_timer(&rf->rf_check, 3, 0);
+		osmo_timer_schedule(&rf->rf_check, 3, 0);
 		break;
 	case RF_CMD_OFF:
 		rf->last_state_command = "RF Scheduled Off";
-		bsc_del_timer(&rf->rf_check);
+		osmo_timer_del(&rf->rf_check);
 		enter_grace(rf);
 		break;
 	}
 }
 
-static int rf_read_cmd(struct bsc_fd *fd)
+static int rf_read_cmd(struct osmo_fd *fd)
 {
 	struct osmo_bsc_rf_conn *conn = fd->data;
 	char buf[1];
@@ -202,9 +203,9 @@
 	rc = read(fd->fd, buf, sizeof(buf));
 	if (rc != sizeof(buf)) {
 		LOGP(DINP, LOGL_ERROR, "Short read %d/%s\n", errno, strerror(errno));
-		bsc_unregister_fd(fd);
+		osmo_fd_unregister(fd);
 		close(fd->fd);
-		write_queue_clear(&conn->queue);
+		osmo_wqueue_clear(&conn->queue);
 		talloc_free(conn);
 		return -1;
 	}
@@ -217,8 +218,8 @@
 	case RF_CMD_ON:
 	case RF_CMD_OFF:
 		conn->rf->last_request = buf[0];
-		if (!bsc_timer_pending(&conn->rf->delay_cmd))
-			bsc_schedule_timer(&conn->rf->delay_cmd, 1, 0);
+		if (!osmo_timer_pending(&conn->rf->delay_cmd))
+			osmo_timer_schedule(&conn->rf->delay_cmd, 1, 0);
 		break;
 	default:
 		conn->rf->last_state_command = "Unknown command";
@@ -229,7 +230,7 @@
 	return 0;
 }
 
-static int rf_write_cmd(struct bsc_fd *fd, struct msgb *msg)
+static int rf_write_cmd(struct osmo_fd *fd, struct msgb *msg)
 {
 	int rc;
 
@@ -242,7 +243,7 @@
 	return 0;
 }
 
-static int rf_ctl_accept(struct bsc_fd *bfd, unsigned int what)
+static int rf_ctl_accept(struct osmo_fd *bfd, unsigned int what)
 {
 	struct osmo_bsc_rf_conn *conn;
 	struct osmo_bsc_rf *rf = bfd->data;
@@ -264,7 +265,7 @@
 		return -1;
 	}
 
-	write_queue_init(&conn->queue, 10);
+	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;
@@ -272,7 +273,7 @@
 	conn->queue.write_cb = rf_write_cmd;
 	conn->rf = rf;
 
-	if (bsc_register_fd(&conn->queue.bfd) != 0) {
+	if (osmo_fd_register(&conn->queue.bfd) != 0) {
 		close(fd);
 		talloc_free(conn);
 		return -1;
@@ -285,7 +286,7 @@
 {
 	unsigned int namelen;
 	struct sockaddr_un local;
-	struct bsc_fd *bfd;
+	struct osmo_fd *bfd;
 	struct osmo_bsc_rf *rf;
 	int rc;
 
@@ -340,7 +341,7 @@
 	bfd->cb = rf_ctl_accept;
 	bfd->data = rf;
 
-	if (bsc_register_fd(bfd) != 0) {
+	if (osmo_fd_register(bfd) != 0) {
 		LOGP(DINP, LOGL_ERROR, "Failed to register bfd.\n");
 		close(bfd->fd);
 		talloc_free(rf);
diff --git a/src/osmo-bsc/osmo_bsc_sccp.c b/src/osmo-bsc/osmo_bsc_sccp.c
index 1abb473..f4cdf36 100644
--- a/src/osmo-bsc/osmo_bsc_sccp.c
+++ b/src/osmo-bsc/osmo_bsc_sccp.c
@@ -27,9 +27,9 @@
 #include <openbsc/ipaccess.h>
 #include <openbsc/signal.h>
 
-#include <osmocore/gsm0808.h>
-#include <osmocore/talloc.h>
-#include <osmocore/protocol/gsm_08_08.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/gsm/gsm0808.h>
+#include <osmocom/gsm/protocol/gsm_08_08.h>
 
 #include <osmocom/sccp/sccp.h>
 
@@ -95,8 +95,8 @@
 		LOGP(DMSC, LOGL_DEBUG, "Connection established: %p\n", conn);
 		con_data = (struct osmo_bsc_sccp_con *) conn->data_ctx;
 
-		bsc_del_timer(&con_data->sccp_cc_timeout);
-		bsc_schedule_timer(&con_data->sccp_it_timeout, SCCP_IT_TIMER, 0);
+		osmo_timer_del(&con_data->sccp_cc_timeout);
+		osmo_timer_schedule(&con_data->sccp_it_timeout, SCCP_IT_TIMER, 0);
 
 		send_queued(con_data);
 	}
@@ -122,7 +122,7 @@
 		(struct osmo_bsc_sccp_con *) _data;
 
 	sccp_connection_send_it(data->sccp);
-	bsc_schedule_timer(&data->sccp_it_timeout, SCCP_IT_TIMER, 0);
+	osmo_timer_schedule(&data->sccp_it_timeout, SCCP_IT_TIMER, 0);
 }
 
 static void sccp_cc_timeout(void *_data)
@@ -231,7 +231,7 @@
 
 int bsc_open_connection(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
 {
-	bsc_schedule_timer(&conn->sccp_cc_timeout, 10, 0);
+	osmo_timer_schedule(&conn->sccp_cc_timeout, 10, 0);
 	sccp_connection_connect(conn->sccp, &sccp_ssn_bssap, msg);
 	msgb_free(msg);
 	return 0;
@@ -246,8 +246,8 @@
 		LOGP(DMSC, LOGL_ERROR, "Should have been cleared.\n");
 
 	llist_del(&sccp->entry);
-	bsc_del_timer(&sccp->sccp_it_timeout);
-	bsc_del_timer(&sccp->sccp_cc_timeout);
+	osmo_timer_del(&sccp->sccp_it_timeout);
+	osmo_timer_del(&sccp->sccp_cc_timeout);
 	talloc_free(sccp);
 	return 0;
 }
@@ -282,7 +282,7 @@
 	sccp_connection_set_incoming(&sccp_ssn_bssap, msc_sccp_accept, NULL);
 	sccp_set_read(&sccp_ssn_bssap, msc_sccp_read, gsmnet);
 
-	register_signal_handler(SS_MSC, handle_msc_signal, gsmnet);
+	osmo_signal_register_handler(SS_MSC, handle_msc_signal, gsmnet);
 
 	return 0;
 }
diff --git a/src/osmo-bsc/osmo_bsc_vty.c b/src/osmo-bsc/osmo_bsc_vty.c
index 1667742..0b1698e 100644
--- a/src/osmo-bsc/osmo_bsc_vty.c
+++ b/src/osmo-bsc/osmo_bsc_vty.c
@@ -1,6 +1,6 @@
 /* Osmo BSC VTY Configuration */
-/* (C) 2009-2010 by Holger Hans Peter Freyther
- * (C) 2009-2010 by On-Waves
+/* (C) 2009-2011 by Holger Hans Peter Freyther
+ * (C) 2009-2011 by On-Waves
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -22,7 +22,7 @@
 #include <openbsc/osmo_msc_data.h>
 #include <openbsc/vty.h>
 
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 
 
 #define IPA_STR "IP.ACCESS specific\n"
@@ -51,33 +51,34 @@
 
 static int config_write_msc(struct vty *vty)
 {
+	struct bsc_msc_dest *dest;
 	struct osmo_msc_data *data = osmo_msc_data(vty);
 
-	vty_out(vty, " msc%s", VTY_NEWLINE);
+	vty_out(vty, "msc%s", VTY_NEWLINE);
 	if (data->bsc_token)
-		vty_out(vty, "  token %s%s", data->bsc_token, VTY_NEWLINE);
+		vty_out(vty, " token %s%s", data->bsc_token, VTY_NEWLINE);
 	if (data->core_ncc != -1)
-		vty_out(vty, "  core-mobile-network-code %d%s",
+		vty_out(vty, " core-mobile-network-code %d%s",
 			data->core_ncc, VTY_NEWLINE);
 	if (data->core_mcc != -1)
-		vty_out(vty, "  core-mobile-country-code %d%s",
+		vty_out(vty, " core-mobile-country-code %d%s",
 			data->core_mcc, VTY_NEWLINE);
-	vty_out(vty, "  ip.access rtp-base %d%s", data->rtp_base, VTY_NEWLINE);
-	vty_out(vty, "  ip %s%s", data->msc_ip, VTY_NEWLINE);
-	vty_out(vty, "  port %d%s", data->msc_port, VTY_NEWLINE);
-	vty_out(vty, "  ip-dscp %d%s", data->msc_ip_dscp, VTY_NEWLINE);
-	vty_out(vty, "  timeout-ping %d%s", data->ping_timeout, VTY_NEWLINE);
-	vty_out(vty, "  timeout-pong %d%s", data->pong_timeout, VTY_NEWLINE);
+	vty_out(vty, " ip.access rtp-base %d%s", data->rtp_base, VTY_NEWLINE);
+	vty_out(vty, " timeout-ping %d%s", data->ping_timeout, VTY_NEWLINE);
+	vty_out(vty, " timeout-pong %d%s", data->pong_timeout, VTY_NEWLINE);
 	if (data->mid_call_txt)
-		vty_out(vty, "mid-call-text %s%s", data->mid_call_txt, VTY_NEWLINE);
+		vty_out(vty, " mid-call-text %s%s", data->mid_call_txt, VTY_NEWLINE);
 	vty_out(vty, " mid-call-timeout %d%s", data->mid_call_timeout, VTY_NEWLINE);
 	if (data->ussd_welcome_txt)
 		vty_out(vty, " bsc-welcome-text %s%s", data->ussd_welcome_txt, VTY_NEWLINE);
+	if (data->rf_ctrl_name)
+		vty_out(vty, " bsc-rf-socket %s%s",
+			data->rf_ctrl_name, VTY_NEWLINE);
 
 	if (data->audio_length != 0) {
 		int i;
 
-		vty_out(vty, " codec_list ");
+		vty_out(vty, " codec-list ");
 		for (i = 0; i < data->audio_length; ++i) {
 			if (i != 0)
 				vty_out(vty, ", ");
@@ -91,6 +92,10 @@
 
 	}
 
+	llist_for_each_entry(dest, &data->dests, list)
+		vty_out(vty, " dest %s %d %d%s", dest->ip, dest->port,
+			dest->dscp, VTY_NEWLINE);
+
 	return CMD_SUCCESS;
 }
 
@@ -197,34 +202,55 @@
 	return CMD_ERR_INCOMPLETE;
 }
 
-DEFUN(cfg_net_msc_ip,
-      cfg_net_msc_ip_cmd,
-      "ip A.B.C.D", "Set the MSC/MUX IP address.")
+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 osmo_msc_data *data = osmo_msc_data(vty);
 
-	bsc_replace_string(data, &data->msc_ip, argv[0]);
+	dest = talloc_zero(data, struct bsc_msc_dest);
+	if (!dest) {
+		vty_out(vty, "%%Failed to create structure.%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	dest->ip = talloc_strdup(data, 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_port,
-      cfg_net_msc_port_cmd,
-      "port <1-65000>",
-      "Set the MSC/MUX port.")
+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 osmo_msc_data *data = osmo_msc_data(vty);
-	data->msc_port = atoi(argv[0]);
-	return CMD_SUCCESS;
-}
 
+	int port = atoi(argv[1]);
+	int dscp = atoi(argv[2]);
 
-DEFUN(cfg_net_msc_prio,
-      cfg_net_msc_prio_cmd,
-      "ip-dscp <0-255>",
-      "Set the IP_TOS socket attribite")
-{
-	struct osmo_msc_data *data = osmo_msc_data(vty);
-	data->msc_ip_dscp = atoi(argv[0]);
+	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;
 }
 
@@ -288,9 +314,29 @@
 	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_msc_data *data = osmo_msc_data(vty);
+
+	bsc_replace_string(data, &data->rf_ctrl_name, argv[0]);
+	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;
+}
+
 int bsc_vty_init_extra(void)
 {
-	install_element(GSMNET_NODE, &cfg_net_msc_cmd);
+	install_element(CONFIG_NODE, &cfg_net_msc_cmd);
 	install_node(&msc_node, config_write_msc);
 	install_default(MSC_NODE);
 	install_element(MSC_NODE, &cfg_net_bsc_token_cmd);
@@ -298,14 +344,16 @@
 	install_element(MSC_NODE, &cfg_net_bsc_mcc_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_ip_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_port_cmd);
-	install_element(MSC_NODE, &cfg_net_msc_prio_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_ping_time_cmd);
 	install_element(MSC_NODE, &cfg_net_msc_pong_time_cmd);
 	install_element(MSC_NODE, &cfg_net_msc_mid_call_text_cmd);
 	install_element(MSC_NODE, &cfg_net_msc_mid_call_timeout_cmd);
 	install_element(MSC_NODE, &cfg_net_msc_welcome_ussd_cmd);
+	install_element(MSC_NODE, &cfg_net_rf_socket_cmd);
+
+	install_element_ve(&show_statistics_cmd);
 
 	return 0;
 }
diff --git a/src/osmo-bsc_mgcp/Makefile.am b/src/osmo-bsc_mgcp/Makefile.am
index 32cc813..e6aae42 100644
--- a/src/osmo-bsc_mgcp/Makefile.am
+++ b/src/osmo-bsc_mgcp/Makefile.am
@@ -1,6 +1,6 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 
 bin_PROGRAMS = bsc_mgcp
 
diff --git a/src/osmo-bsc_mgcp/Makefile.in b/src/osmo-bsc_mgcp/Makefile.in
index 714fae3..afc2bc0 100644
--- a/src/osmo-bsc_mgcp/Makefile.in
+++ b/src/osmo-bsc_mgcp/Makefile.in
@@ -36,7 +36,7 @@
 subdir = src/osmo-bsc_mgcp
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -108,6 +108,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -177,8 +179,8 @@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 bsc_mgcp_SOURCES = mgcp_main.c
 bsc_mgcp_LDADD = $(top_builddir)/src/libcommon/libcommon.a \
 		 $(top_builddir)/src/libmgcp/libmgcp.a \
diff --git a/src/osmo-bsc_mgcp/mgcp_main.c b/src/osmo-bsc_mgcp/mgcp_main.c
index c8d9a62..921fa09 100644
--- a/src/osmo-bsc_mgcp/mgcp_main.c
+++ b/src/osmo-bsc_mgcp/mgcp_main.c
@@ -32,16 +32,19 @@
 #include <sys/socket.h>
 
 #include <openbsc/debug.h>
-#include <osmocore/msgb.h>
-#include <osmocore/talloc.h>
-#include <osmocore/process.h>
 #include <openbsc/gsm_data.h>
-#include <osmocore/select.h>
 #include <openbsc/mgcp.h>
 #include <openbsc/mgcp_internal.h>
+#include <openbsc/vty.h>
+
+#include <osmocom/core/application.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/process.h>
+#include <osmocom/core/select.h>
+
 #include <osmocom/vty/telnet_interface.h>
 #include <osmocom/vty/logging.h>
-#include <openbsc/vty.h>
 
 #include <osmocom/vty/command.h>
 
@@ -135,7 +138,7 @@
 	return 0;
 }
 
-static int read_call_agent(struct bsc_fd *fd, unsigned int what)
+static int read_call_agent(struct osmo_fd *fd, unsigned int what)
 {
 	struct sockaddr_in addr;
 	socklen_t slen = sizeof(addr);
@@ -193,14 +196,11 @@
 	struct gsm_network dummy_network;
 	struct sockaddr_in addr;
 	int on = 1, rc;
-	struct log_target *stderr_target;
 
 	tall_bsc_ctx = talloc_named_const(NULL, 1, "mgcp-callagent");
 
-	log_init(&log_info);
-	stderr_target = log_target_create_stderr();
-	log_add_target(stderr_target);
-	log_set_all_filter(stderr_target, 1);
+	osmo_init_ignore_signals();
+	osmo_init_logging(&log_info);
 
 	cfg = mgcp_config_alloc();
 	if (!cfg)
@@ -208,7 +208,7 @@
 
 	vty_info.copyright = openbsc_copyright;
 	vty_init(&vty_info);
-	logging_vty_add_cmds();
+	logging_vty_add_cmds(&log_info);
 	mgcp_vty_init();
 
 	handle_options(argc, argv);
@@ -254,7 +254,7 @@
 		}
 
 
-		if (bsc_register_fd(&cfg->gw_fd.bfd) != 0) {
+		if (osmo_fd_register(&cfg->gw_fd.bfd) != 0) {
 			LOGP(DMGCP, LOGL_FATAL, "Failed to register the fd\n");
 			return -1;
 		}
@@ -275,7 +275,7 @@
 
 	/* main loop */
 	while (1) {
-		bsc_select_main(0);
+		osmo_select_main(0);
 	}
 
 
diff --git a/src/osmo-bsc_nat/Makefile.am b/src/osmo-bsc_nat/Makefile.am
index 98a3431..03fe62b 100644
--- a/src/osmo-bsc_nat/Makefile.am
+++ b/src/osmo-bsc_nat/Makefile.am
@@ -1,6 +1,6 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
 
 bin_PROGRAMS = osmo-bsc_nat
 
diff --git a/src/osmo-bsc_nat/Makefile.in b/src/osmo-bsc_nat/Makefile.in
index ba69f7e..6a51109 100644
--- a/src/osmo-bsc_nat/Makefile.in
+++ b/src/osmo-bsc_nat/Makefile.in
@@ -36,7 +36,7 @@
 subdir = src/osmo-bsc_nat
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -114,6 +114,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -183,8 +185,8 @@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(COVERAGE_LDFLAGS)
 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
 
diff --git a/src/osmo-bsc_nat/bsc_filter.c b/src/osmo-bsc_nat/bsc_filter.c
index 73e9878..74a5d19 100644
--- a/src/osmo-bsc_nat/bsc_filter.c
+++ b/src/osmo-bsc_nat/bsc_filter.c
@@ -25,8 +25,8 @@
 #include <openbsc/ipaccess.h>
 #include <openbsc/debug.h>
 
-#include <osmocore/talloc.h>
-#include <osmocore/protocol/gsm_08_08.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/gsm/protocol/gsm_08_08.h>
 
 #include <osmocom/sccp/sccp.h>
 
diff --git a/src/osmo-bsc_nat/bsc_mgcp_utils.c b/src/osmo-bsc_nat/bsc_mgcp_utils.c
index 9eac00b..9ac54da 100644
--- a/src/osmo-bsc_nat/bsc_mgcp_utils.c
+++ b/src/osmo-bsc_nat/bsc_mgcp_utils.c
@@ -28,9 +28,9 @@
 
 #include <osmocom/sccp/sccp.h>
 
-#include <osmocore/talloc.h>
-#include <osmocore/gsm0808.h>
-#include <osmocore/protocol/gsm_08_08.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>
@@ -478,7 +478,7 @@
 		return;
 	}
 
-	if (write_queue_enqueue(&bsc->nat->mgcp_cfg->gw_fd, output) != 0) {
+	if (osmo_wqueue_enqueue(&bsc->nat->mgcp_cfg->gw_fd, output) != 0) {
 		LOGP(DMGCP, LOGL_ERROR, "Failed to queue MGCP msg.\n");
 		msgb_free(output);
 	}
@@ -598,7 +598,7 @@
 	return output;
 }
 
-static int mgcp_do_read(struct bsc_fd *fd)
+static int mgcp_do_read(struct osmo_fd *fd)
 {
 	struct bsc_nat *nat;
 	struct msgb *msg, *resp;
@@ -628,7 +628,7 @@
 
 	/* we do have a direct answer... e.g. AUEP */
 	if (resp) {
-		if (write_queue_enqueue(&nat->mgcp_cfg->gw_fd, resp) != 0) {
+		if (osmo_wqueue_enqueue(&nat->mgcp_cfg->gw_fd, resp) != 0) {
 			LOGP(DMGCP, LOGL_ERROR, "Failed to enqueue msg.\n");
 			msgb_free(resp);
 		}
@@ -637,7 +637,7 @@
 	return 0;
 }
 
-static int mgcp_do_write(struct bsc_fd *bfd, struct msgb *msg)
+static int mgcp_do_write(struct osmo_fd *bfd, struct msgb *msg)
 {
 	int rc;
 
@@ -681,7 +681,8 @@
 	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. errno: %d\n", errno);
+		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;
@@ -697,13 +698,13 @@
 		return -1;
 	}
 
-	write_queue_init(&cfg->gw_fd, 10);
+	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 (bsc_register_fd(&cfg->gw_fd.bfd) != 0) {
+	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;
diff --git a/src/osmo-bsc_nat/bsc_nat.c b/src/osmo-bsc_nat/bsc_nat.c
index 643b3c4..e0eb635 100644
--- a/src/osmo-bsc_nat/bsc_nat.c
+++ b/src/osmo-bsc_nat/bsc_nat.c
@@ -1,8 +1,8 @@
 /* BSC Multiplexer/NAT */
 
 /*
- * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010 by On-Waves
+ * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2011 by On-Waves
  * (C) 2009 by Harald Welte <laforge@gnumonks.org>
  * All Rights Reserved
  *
@@ -44,14 +44,16 @@
 #include <openbsc/socket.h>
 #include <openbsc/vty.h>
 
-#include <osmocore/gsm0808.h>
-#include <osmocore/talloc.h>
-#include <osmocore/process.h>
+#include <osmocom/core/application.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/process.h>
 
-#include <osmocore/protocol/gsm_08_08.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/sccp/sccp.h>
 
@@ -60,12 +62,11 @@
 #define SCCP_CLOSE_TIME 20
 #define SCCP_CLOSE_TIME_TIMEOUT 19
 
-struct log_target *stderr_target;
 static const char *config_file = "bsc-nat.cfg";
 static struct in_addr local_addr;
-static struct bsc_fd bsc_listen;
+static struct osmo_fd bsc_listen;
 static const char *msc_ip = NULL;
-static struct timer_list sccp_close;
+static struct osmo_timer_list sccp_close;
 static int daemonize = 0;
 
 const char *openbsc_copyright =
@@ -99,7 +100,7 @@
 	}
 
 
-	if (write_queue_enqueue(&con->write_queue, msg) != 0) {
+	if (osmo_wqueue_enqueue(&con->write_queue, msg) != 0) {
 		LOGP(DINP, LOGL_ERROR, "Failed to enqueue the write.\n");
 		msgb_free(msg);
 	}
@@ -152,10 +153,10 @@
 	send_ping(bsc);
 
 	/* send another ping in 20 seconds */
-	bsc_schedule_timer(&bsc->ping_timeout, bsc->nat->ping_timeout, 0);
+	osmo_timer_schedule(&bsc->ping_timeout, bsc->nat->ping_timeout, 0);
 
 	/* also start a pong timer */
-	bsc_schedule_timer(&bsc->pong_timeout, bsc->nat->pong_timeout, 0);
+	osmo_timer_schedule(&bsc->pong_timeout, bsc->nat->pong_timeout, 0);
 }
 
 static void start_ping_pong(struct bsc_connection *bsc)
@@ -194,15 +195,15 @@
 	bsc_send_data(bsc, id_req, sizeof(id_req), IPAC_PROTO_IPACCESS);
 }
 
-static void nat_send_rlsd_msc(struct sccp_connections *conn)
+static struct msgb *nat_create_rlsd(struct sccp_connections *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 clear command.\n");
-		return;
+		LOGP(DNAT, LOGL_ERROR, "Failed to allocate released.\n");
+		return NULL;
 	}
 
 	msg->l2h = msgb_put(msg, sizeof(*rel));
@@ -212,15 +213,39 @@
 	rel->destination_local_reference = conn->remote_ref;
 	rel->source_local_reference = conn->patched_ref;
 
-	ipaccess_prepend_header(msg, IPAC_PROTO_SCCP);
+	return msg;
+}
 
+static void nat_send_rlsd_ussd(struct bsc_nat *nat, struct sccp_connections *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 sccp_connections *conn)
+{
+	struct msgb *msg;
+
+	msg = nat_create_rlsd(conn);
+	if (!msg)
+		return;
+
+	ipaccess_prepend_header(msg, IPAC_PROTO_SCCP);
 	queue_for_msc(conn->msc_con, msg);
 }
 
 static void nat_send_rlsd_bsc(struct sccp_connections *conn)
 {
-	struct sccp_connection_released *rel;
 	struct msgb *msg;
+	struct sccp_connection_released *rel;
 
 	msg = msgb_alloc_headroom(4096, 128, "rlsd");
 	if (!msg) {
@@ -398,7 +423,7 @@
 		ipaccess_prepend_header(rlsd, IPAC_PROTO_SCCP);
 		queue_for_msc(con->msc_con, rlsd);
 	}
-	con->con_local = 1;
+	con->con_local = NAT_CON_END_LOCAL;
 	con->msc_con = NULL;
 
 	/* 2. release the BSC side */
@@ -464,7 +489,7 @@
 
 		/* declare it local and assign a unique remote_ref */
 		con->con_type = NAT_CON_TYPE_LOCAL_REJECT;
-		con->con_local = 1;
+		con->con_local = NAT_CON_END_LOCAL;
 		con->has_remote_ref = 1;
 		con->remote_ref = con->patched_ref;
 
@@ -524,6 +549,82 @@
 	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 COMAMND or
+ * a CM Serivce Accept. Maybe also LU Accept or such in the future.
+ */
+static void update_con_authorize(struct sccp_connections *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 = hdr48->proto_discr & 0x0f;
+		msg_type = hdr48->msg_type & 0xbf;
+		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)
 {
@@ -552,12 +653,17 @@
 			goto send_to_all;
 			break;
 		case SCCP_MSG_TYPE_RLSD:
+			if (con && con->con_local == NAT_CON_END_USSD) {
+				LOGP(DNAT, LOGL_NOTICE, "RLSD for a USSD connection. Ignoring.\n");
+				con = NULL;
+			}
+			/* fall through */
 		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) {
-				counter_inc(nat->stats.sccp.calls);
+				osmo_counter_inc(nat->stats.sccp.calls);
 
 				if (con) {
 					struct rate_ctr_group *ctrg;
@@ -567,6 +673,10 @@
 						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:
@@ -600,6 +710,8 @@
 		return -1;
 	}
 
+	update_con_authorize(con, parsed, msg);
+
 	bsc_send_data(con->bsc, msg->l2h, msgb_l2len(msg), proto);
 	return 0;
 
@@ -610,16 +722,7 @@
 	 * message and then send it to the authenticated messages...
 	 */
 	if (parsed->ipa_proto == IPAC_PROTO_SCCP && parsed->gsm_type == BSS_MAP_MSG_PAGING) {
-		int lac;
-		bsc = bsc_nat_find_bsc(nat, msg, &lac);
-		if (bsc && bsc->cfg->forbid_paging)
-			LOGP(DNAT, LOGL_DEBUG, "Paging forbidden for BTS: %d\n", bsc->cfg->nr);
-		else if (bsc)
-			bsc_send_data(bsc, msg->l2h, msgb_l2len(msg), parsed->ipa_proto);
-		else if (lac != -1)
-			LOGP(DNAT, LOGL_ERROR, "Could not determine BSC for paging on lac: %d/0x%x\n",
-			     lac, lac);
-
+		bsc_nat_handle_paging(nat, msg);
 		goto exit;
 	}
 	/* currently send this to every BSC connected */
@@ -649,7 +752,7 @@
 
 static void msc_connection_connected(struct bsc_msc_connection *con)
 {
-	counter_inc(nat->stats.msc.reconn);
+	osmo_counter_inc(nat->stats.msc.reconn);
 }
 
 static void msc_send_reset(struct bsc_msc_connection *msc_con)
@@ -677,7 +780,7 @@
 	LOGP(DMSC, LOGL_NOTICE, "Scheduled GSM0808 reset msg for the MSC.\n");
 }
 
-static int ipaccess_msc_read_cb(struct bsc_fd *bfd)
+static int ipaccess_msc_read_cb(struct osmo_fd *bfd)
 {
 	int error;
 	struct bsc_msc_connection *msc_con;
@@ -696,7 +799,7 @@
 		return -1;
 	}
 
-	LOGP(DNAT, LOGL_DEBUG, "MSG from MSC: %s proto: %d\n", hexdump(msg->data, msg->len), msg->l2h[0]);
+	LOGP(DNAT, LOGL_DEBUG, "MSG 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;
@@ -715,7 +818,7 @@
 	return 0;
 }
 
-static int ipaccess_msc_write_cb(struct bsc_fd *bfd, struct msgb *msg)
+static int ipaccess_msc_write_cb(struct osmo_fd *bfd, struct msgb *msg)
 {
 	int rc;
 	rc = write(bfd->fd, msg->data, msg->len);
@@ -745,9 +848,9 @@
 	struct rate_ctr *ctr = NULL;
 
 	/* stop the timeout timer */
-	bsc_del_timer(&connection->id_timeout);
-	bsc_del_timer(&connection->ping_timeout);
-	bsc_del_timer(&connection->pong_timeout);
+	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];
@@ -759,22 +862,44 @@
 
 		if (ctr)
 			rate_ctr_inc(ctr);
-		if (sccp_patch->has_remote_ref && !sccp_patch->con_local)
-			nat_send_rlsd_msc(sccp_patch);
+		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);
 	}
 
 	/* close endpoints allocated by this BSC */
 	bsc_mgcp_clear_endpoints_for(connection);
 
-	bsc_unregister_fd(&connection->write_queue.bfd);
+	osmo_fd_unregister(&connection->write_queue.bfd);
 	close(connection->write_queue.bfd.fd);
-	write_queue_clear(&connection->write_queue);
+	osmo_wqueue_clear(&connection->write_queue);
 	llist_del(&connection->list_entry);
 
 	talloc_free(connection);
 }
 
+static void bsc_maybe_close(struct bsc_connection *bsc)
+{
+	struct sccp_connections *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;
@@ -805,7 +930,7 @@
 			rate_ctr_inc(&conf->stats.ctrg->ctr[BCFG_CTR_NET_RECONN]);
 			bsc->authenticated = 1;
 			bsc->cfg = conf;
-			bsc_del_timer(&bsc->id_timeout);
+			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);
@@ -908,16 +1033,18 @@
 
 					/* hand data to a side channel */
 					if (bsc_check_ussd(con, parsed, msg) == 1) 
-						con->con_local = 2;
+						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_setup(bsc->nat, msg, parsed, con->imsi);
+					msg = bsc_nat_rewrite_msg(bsc->nat, msg, parsed, con->imsi);
 					talloc_free(parsed);
 					parsed = NULL;
+				} else if (con->con_local == NAT_CON_END_USSD) {
+					bsc_check_ussd(con, parsed, msg);
 				}
 
 				con_bsc = con->bsc;
@@ -934,6 +1061,7 @@
 				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 */
@@ -986,9 +1114,15 @@
 		/* do we know who is handling this? */
 		if (msg->l2h[0] == IPAC_MSGT_ID_RESP) {
 			struct tlv_parsed tvp;
-			ipaccess_idtag_parse(&tvp,
+			int ret;
+			ret = ipaccess_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");
+				return ret;
+			}
 			if (TLVP_PRESENT(&tvp, IPAC_IDTAG_UNITNAME))
 				ipaccess_auth_bsc(&tvp, bsc);
 		}
@@ -1013,7 +1147,7 @@
 	return -1;
 }
 
-static int ipaccess_bsc_read_cb(struct bsc_fd *bfd)
+static int ipaccess_bsc_read_cb(struct osmo_fd *bfd)
 {
 	int error;
 	struct bsc_connection *bsc = bfd->data;
@@ -1035,7 +1169,7 @@
 	}
 
 
-	LOGP(DNAT, LOGL_DEBUG, "MSG from BSC: %s proto: %d\n", hexdump(msg->data, msg->len), msg->l2h[0]);
+	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;
@@ -1043,7 +1177,7 @@
 	/* stop the pong timeout */
 	if (hh->proto == IPAC_PROTO_IPACCESS) {
 		if (msg->l2h[0] == IPAC_MSGT_PONG) {
-			bsc_del_timer(&bsc->pong_timeout);
+			osmo_timer_del(&bsc->pong_timeout);
 			msgb_free(msg);
 			return 0;
 		} else if (msg->l2h[0] == IPAC_MSGT_PING) {
@@ -1060,7 +1194,7 @@
 	return 0;
 }
 
-static int ipaccess_listen_bsc_cb(struct bsc_fd *bfd, unsigned int what)
+static int ipaccess_listen_bsc_cb(struct osmo_fd *bfd, unsigned int what)
 {
 	struct bsc_connection *bsc;
 	int fd, rc, on;
@@ -1077,7 +1211,7 @@
 	}
 
 	/* count the reconnect */
-	counter_inc(nat->stats.bsc.reconn);
+	osmo_counter_inc(nat->stats.bsc.reconn);
 
 	/*
 	 * if we are not connected to a msc... just close the socket
@@ -1088,6 +1222,12 @@
 		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)
@@ -1116,7 +1256,7 @@
 	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 (bsc_register_fd(&bsc->write_queue.bfd) < 0) {
+	if (osmo_fd_register(&bsc->write_queue.bfd) < 0) {
 		LOGP(DNAT, LOGL_ERROR, "Failed to register BSC fd.\n");
 		close(fd);
 		talloc_free(bsc);
@@ -1135,7 +1275,7 @@
 	 */
 	bsc->id_timeout.data = bsc;
 	bsc->id_timeout.cb = ipaccess_close_bsc;
-	bsc_schedule_timer(&bsc->id_timeout, nat->auth_timeout, 0);
+	osmo_timer_schedule(&bsc->id_timeout, nat->auth_timeout, 0);
 	return 0;
 }
 
@@ -1182,16 +1322,16 @@
 			print_help();
 			exit(0);
 		case 's':
-			log_set_use_color(stderr_target, 0);
+			log_set_use_color(osmo_stderr_target, 0);
 			break;
 		case 'd':
-			log_parse_category_mask(stderr_target, optarg);
+			log_parse_category_mask(osmo_stderr_target, optarg);
 			break;
 		case 'c':
 			config_file = strdup(optarg);
 			break;
 		case 'T':
-			log_set_print_timestamp(stderr_target, 1);
+			log_set_print_timestamp(osmo_stderr_target, 1);
 			break;
 		case 'm':
 			msc_ip = optarg;
@@ -1222,6 +1362,8 @@
 
 static void sccp_close_unconfirmed(void *_data)
 {
+	int destroyed = 0;
+	struct bsc_connection *bsc, *bsc_tmp;
 	struct sccp_connections *conn, *tmp1;
 	struct timespec now;
 	clock_gettime(CLOCK_MONOTONIC, &now);
@@ -1238,9 +1380,18 @@
 		     sccp_src_ref_to_int(&conn->real_ref),
 		     sccp_src_ref_to_int(&conn->patched_ref));
 		sccp_connection_destroy(conn);
+		destroyed = 1;
 	}
 
-	bsc_schedule_timer(&sccp_close, SCCP_CLOSE_TIME, 0);
+	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_msgb_ctx;
@@ -1267,10 +1418,7 @@
 
 	talloc_init_ctx();
 
-	log_init(&log_info);
-	stderr_target = log_target_create_stderr();
-	log_add_target(stderr_target);
-	log_set_all_filter(stderr_target, 1);
+	osmo_init_logging(&log_info);
 
 	nat = bsc_nat_alloc();
 	if (!nat) {
@@ -1286,7 +1434,7 @@
 
 	vty_info.copyright = openbsc_copyright;
 	vty_init(&vty_info);
-	logging_vty_add_cmds();
+	logging_vty_add_cmds(&log_info);
 	bsc_nat_vty_init(nat);
 
 
@@ -1317,7 +1465,7 @@
 		return -4;
 
 	/* connect to the MSC */
-	nat->msc_con = bsc_msc_create(nat->msc_ip, nat->msc_port, 0);
+	nat->msc_con = bsc_msc_create(nat, &nat->dests);
 	if (!nat->msc_con) {
 		fprintf(stderr, "Creating a bsc_msc_connection failed.\n");
 		exit(1);
@@ -1332,7 +1480,7 @@
 
 	/* wait for the BSC */
 	rc = make_sock(&bsc_listen, IPPROTO_TCP, ntohl(local_addr.s_addr),
-		       5000, ipaccess_listen_bsc_cb);
+		       5000, 0, ipaccess_listen_bsc_cb, nat);
 	if (rc != 0) {
 		fprintf(stderr, "Failed to listen for BSC.\n");
 		exit(1);
@@ -1346,7 +1494,7 @@
 
 	signal(SIGABRT, &signal_handler);
 	signal(SIGUSR1, &signal_handler);
-	signal(SIGPIPE, SIG_IGN);
+	osmo_init_ignore_signals();
 
 	if (daemonize) {
 		rc = osmo_daemonize();
@@ -1360,10 +1508,10 @@
 	sccp_set_log_area(DSCCP);
 	sccp_close.cb = sccp_close_unconfirmed;
 	sccp_close.data = NULL;
-	bsc_schedule_timer(&sccp_close, SCCP_CLOSE_TIME, 0);
+	osmo_timer_schedule(&sccp_close, SCCP_CLOSE_TIME, 0);
 
 	while (1) {
-		bsc_select_main(0);
+		osmo_select_main(0);
 	}
 
 	return 0;
@@ -1374,7 +1522,7 @@
 {
 	struct sccp_connections *con;
 	llist_for_each_entry(con, &nat->sccp_connections, list_entry) {
-		if (con->con_local != 2)
+		if (con->con_local != NAT_CON_END_USSD)
 			continue;
 		if (!con->bsc)
 			continue;
diff --git a/src/osmo-bsc_nat/bsc_nat_utils.c b/src/osmo-bsc_nat/bsc_nat_utils.c
index cd294cc..4834340 100644
--- a/src/osmo-bsc_nat/bsc_nat_utils.c
+++ b/src/osmo-bsc_nat/bsc_nat_utils.c
@@ -2,8 +2,8 @@
 /* BSC Multiplexer/NAT Utilities */
 
 /*
- * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010 by On-Waves
+ * (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
@@ -29,11 +29,12 @@
 #include <openbsc/ipaccess.h>
 #include <openbsc/vty.h>
 
-#include <osmocore/linuxlist.h>
-#include <osmocore/talloc.h>
-#include <osmocore/gsm0808.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/gsm/gsm0808.h>
 
-#include <osmocore/protocol/gsm_08_08.h>
+#include <osmocom/gsm/protocol/gsm_08_08.h>
+#include <osmocom/gsm/protocol/gsm_04_11.h>
 
 #include <osmocom/sccp/sccp.h>
 
@@ -82,28 +83,42 @@
 	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->smsc_rewr);
+	INIT_LLIST_HEAD(&nat->tpdest_match);
 
-	nat->stats.sccp.conn = counter_alloc("nat.sccp.conn");
-	nat->stats.sccp.calls = counter_alloc("nat.sccp.calls");
-	nat->stats.bsc.reconn = counter_alloc("nat.bsc.conn");
-	nat->stats.bsc.auth_fail = counter_alloc("nat.bsc.auth_fail");
-	nat->stats.msc.reconn = counter_alloc("nat.msc.conn");
-	nat->stats.ussd.reconn = counter_alloc("nat.ussd.conn");
-	nat->msc_ip = talloc_strdup(nat, "127.0.0.1");
-	nat->msc_port = 5000;
+	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_set_msc_ip(struct bsc_nat *nat, const char *ip)
 {
-	bsc_replace_string(nat, &nat->msc_ip, ip);
+	bsc_replace_string(nat, &nat->main_dest->ip, ip);
 }
 
 struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat)
@@ -113,7 +128,7 @@
 		return NULL;
 
 	con->nat = nat;
-	write_queue_init(&con->write_queue, 100);
+	osmo_wqueue_init(&con->write_queue, 100);
 	return con;
 }
 
@@ -127,6 +142,7 @@
 	conf->nr = nat->num_bsc;
 	conf->nat = nat;
 	conf->max_endpoints = 32;
+	conf->paging_group = PAGIN_GROUP_UNASSIGNED;
 
 	INIT_LLIST_HEAD(&conf->lac_list);
 
@@ -147,29 +163,29 @@
 	rate_ctr_group_free(cfg->stats.ctrg);
 }
 
-void bsc_config_add_lac(struct bsc_config *cfg, int _lac)
+static void _add_lac(void *ctx, struct llist_head *list, int _lac)
 {
 	struct bsc_lac_entry *lac;
 
-	llist_for_each_entry(lac, &cfg->lac_list, entry)
+	llist_for_each_entry(lac, list, entry)
 		if (lac->lac == _lac)
 			return;
 
-	lac = talloc_zero(cfg, struct bsc_lac_entry);
+	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, &cfg->lac_list);
+	llist_add_tail(&lac->entry, list);
 }
 
-void bsc_config_del_lac(struct bsc_config *cfg, int _lac)
+static void _del_lac(struct llist_head *list, int _lac)
 {
 	struct bsc_lac_entry *lac;
 
-	llist_for_each_entry(lac, &cfg->lac_list, entry)
+	llist_for_each_entry(lac, list, entry)
 		if (lac->lac == _lac) {
 			llist_del(&lac->entry);
 			talloc_free(lac);
@@ -177,14 +193,77 @@
 		}
 }
 
+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;
 }
 
@@ -198,25 +277,23 @@
 	talloc_free(conn);
 }
 
-struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg, int *lac_out)
+
+int bsc_nat_find_paging(struct msgb *msg,
+			const uint8_t **out_data, int *out_leng)
 {
-	struct bsc_connection *bsc;
 	int data_length;
 	const uint8_t *data;
 	struct tlv_parsed tp;
-	int i = 0;
-
-	*lac_out = -1;
 
 	if (!msg->l3h || msgb_l3len(msg) < 3) {
 		LOGP(DNAT, LOGL_ERROR, "Paging message is too short.\n");
-		return NULL;
+		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 NULL;
+		return -2;
 	}
 
 	data_length = TLVP_LEN(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
@@ -224,29 +301,15 @@
 
 	/* No need to try a different BSS */
 	if (data[0] == CELL_IDENT_BSS) {
-		return NULL;
+		return -3;
 	} else if (data[0] != CELL_IDENT_LAC) {
 		LOGP(DNAT, LOGL_ERROR, "Unhandled cell ident discrminator: %d\n", data[0]);
-		return NULL;
+		return -4;
 	}
 
-	/* Currently we only handle one BSC */
-	for (i = 1; i < data_length - 1; i += 2) {
-		unsigned int _lac = ntohs(*(unsigned int *) &data[i]);
-		*lac_out = _lac;
-		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;
-
-			return bsc;
-		}
-	}
-
-	return NULL;
+	*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)
@@ -276,16 +339,16 @@
 	return bsc_do_write(&bsc->write_queue, msg, proto);
 }
 
-int bsc_do_write(struct write_queue *queue, struct msgb *msg, int proto)
+int bsc_do_write(struct osmo_wqueue *queue, struct msgb *msg, int proto)
 {
 	/* prepend the header */
 	ipaccess_prepend_header(msg, proto);
 	return bsc_write_msg(queue, msg);
 }
 
-int bsc_write_msg(struct write_queue *queue, struct msgb *msg)
+int bsc_write_msg(struct osmo_wqueue *queue, struct msgb *msg)
 {
-	if (write_queue_enqueue(queue, msg) != 0) {
+	if (osmo_wqueue_enqueue(queue, msg) != 0) {
 		LOGP(DINP, LOGL_ERROR, "Failed to enqueue the write.\n");
 		msgb_free(msg);
 		return -1;
@@ -500,7 +563,7 @@
 	struct gsm48_hdr *hdr48;
 	int hdr48_len;
 	int len;
-	uint8_t msg_type;
+	uint8_t msg_type, proto;
 
 	*con_type = NAT_CON_TYPE_NONE;
 	*imsi = NULL;
@@ -538,18 +601,19 @@
 
 	hdr48 = (struct gsm48_hdr *) TLVP_VAL(&tp, GSM0808_IE_LAYER_3_INFORMATION);
 
+	proto = hdr48->proto_discr & 0x0f;
 	msg_type = hdr48->msg_type & 0xbf;
-	if (hdr48->proto_discr == GSM48_PDISC_MM &&
+	if (proto == GSM48_PDISC_MM &&
 	    msg_type == GSM48_MT_MM_LOC_UPD_REQUEST) {
 		*con_type = NAT_CON_TYPE_LU;
 		return _cr_check_loc_upd(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48), imsi);
-	} else if (hdr48->proto_discr == GSM48_PDISC_MM &&
+	} else if (proto == GSM48_PDISC_MM &&
 		  msg_type == GSM48_MT_MM_CM_SERV_REQ) {
 		*con_type = NAT_CON_TYPE_CM_SERV_REQ;
 		return _cr_check_cm_serv_req(bsc, &hdr48->data[0],
 					     hdr48_len - sizeof(*hdr48),
 					     con_type, imsi);
-	} else if (hdr48->proto_discr == GSM48_PDISC_RR &&
+	} else if (proto == GSM48_PDISC_RR &&
 		   msg_type == GSM48_MT_RR_PAG_RESP) {
 		*con_type = NAT_CON_TYPE_PAG_RESP;
 		return _cr_check_pag_resp(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48), imsi);
@@ -583,7 +647,7 @@
 		      struct sccp_connections *con, struct bsc_nat_parsed *parsed)
 {
 	uint32_t len;
-	uint8_t msg_type;
+	uint8_t msg_type, proto;
 	struct gsm48_hdr *hdr48;
 
 	if (con->imsi_checked)
@@ -597,8 +661,9 @@
 	if (!hdr48)
 		return -1;
 
+	proto = hdr48->proto_discr & 0x0f;
 	msg_type = hdr48->msg_type & 0xbf;
-	if (hdr48->proto_discr == GSM48_PDISC_MM &&
+	if (proto == GSM48_PDISC_MM &&
 	    msg_type == GSM48_MT_MM_ID_RESP) {
 		return _dt_check_id_resp(bsc, &hdr48->data[0], len - sizeof(*hdr48), con);
 	} else {
@@ -606,8 +671,11 @@
 	}
 }
 
-void bsc_parse_reg(void *ctx, regex_t *reg, char **imsi, int argc, const char **argv)
+int bsc_parse_reg(void *ctx, regex_t *reg, char **imsi, int argc, const char **argv)
 {
+	int ret;
+
+	ret = 0;
 	if (*imsi) {
 		talloc_free(*imsi);
 		*imsi = NULL;
@@ -616,8 +684,16 @@
 
 	if (argc > 0) {
 		*imsi = talloc_strdup(ctx, argv[0]);
-		regcomp(reg, argv[0], 0);
+		ret = regcomp(reg, argv[0], 0);
+
+		/* handle compilation failures */
+		if (ret != 0) {
+			talloc_free(*imsi);
+			*imsi = NULL;
+		}
 	}
+
+	return ret;
 }
 
 static const char *con_types [] = {
@@ -715,7 +791,7 @@
 	return con_to_ctr[conn->con_type];
 }
 
-int bsc_write_cb(struct bsc_fd *bfd, struct msgb *msg)
+int bsc_write_cb(struct osmo_fd *bfd, struct msgb *msg)
 {
 	int rc;
 
@@ -726,109 +802,82 @@
 	return rc;
 }
 
+static char *rewrite_non_international(struct bsc_nat *nat, void *ctx, const char *imsi,
+				       struct gsm_mncc_number *called)
+{
+	struct bsc_nat_num_rewr_entry *entry;
+	char *new_number = NULL;
+
+	if (llist_empty(&nat->num_rewr))
+		return NULL;
+
+	if (called->plan != 1)
+		return NULL;
+	if (called->type == 1)
+		return NULL;
+
+	/* need to find a replacement and then fix it */
+	llist_for_each_entry(entry, &nat->num_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, called->number, 2, matches, 0) == 0 &&
+		    matches[1].rm_eo != -1)
+			new_number = talloc_asprintf(ctx, "%s%s",
+					entry->replace,
+					&called->number[matches[1].rm_so]);
+		if (new_number)
+			break;
+	}
+
+	return new_number;
+}
+
+
 /**
  * Rewrite non global numbers... according to rules based on the IMSI
  */
-struct msgb *bsc_nat_rewrite_setup(struct bsc_nat *nat, struct msgb *msg, struct bsc_nat_parsed *parsed, const char *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;
-	struct gsm48_hdr *hdr48;
-	uint32_t len;
-	uint8_t msg_type;
 	unsigned int payload_len;
 	struct gsm_mncc_number called;
-	struct msg_entry *entry;
+	struct msgb *out;
 	char *new_number = NULL;
-	struct msgb *out, *sccp;
 	uint8_t *outptr;
 	const uint8_t *msgptr;
 	int sec_len;
 
-	if (!imsi || strlen(imsi) < 5)
-		return msg;
-
-	if (!nat->num_rewr)
-		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;
-
-	msg_type = hdr48->msg_type & 0xbf;
-	if (hdr48->proto_discr != GSM48_PDISC_CC ||
-	    msg_type != GSM48_MT_CC_SETUP)
-		return msg;
-
 	/* 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 msg;
+		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 */
-	if (called.plan != 1)
-		return msg;
-	if (called.type == 1)
-		return msg;
-	if (strncmp(called.number, "00", 2) == 0)
-		return msg;
-
-	/* need to find a replacement and then fix it */
-	llist_for_each_entry(entry, &nat->num_rewr->entry, list) {
-		regex_t reg;
-		regmatch_t matches[2];
-
-		if (entry->mcc[0] != '*' && strncmp(entry->mcc, imsi, 3) != 0)
-			continue;
-		if (entry->mnc[0] != '*' && strncmp(entry->mnc, imsi + 3, 2) != 0)
-			continue;
-
-		if (entry->text[0] == '+') {
-			LOGP(DNAT, LOGL_ERROR,
-				"Plus is not allowed in the number");
-			continue;
-		}
-
-		/* We have an entry for the IMSI. Need to match now */
-		if (regcomp(&reg, entry->option, REG_EXTENDED) != 0) {
-			LOGP(DNAT, LOGL_ERROR,
-				"Regexp '%s' is not valid.\n", entry->option);
-			continue;
-		}
-
-		/* this regexp matches... */
-		if (regexec(&reg, called.number, 2, matches, 0) == 0 &&
-		    matches[1].rm_eo != -1)
-			new_number = talloc_asprintf(msg, "%s%s",
-					entry->text,
-					&called.number[matches[1].rm_so]);
-		regfree(&reg);
-
-		if (new_number)
-			break;
-	}
+	new_number = rewrite_non_international(nat, msg, imsi, &called);
 
 	if (!new_number) {
 		LOGP(DNAT, LOGL_DEBUG, "No IMSI match found, returning message.\n");
-		return msg;
+		return NULL;
 	}
 
 	if (strlen(new_number) > sizeof(called.number)) {
 		LOGP(DNAT, LOGL_ERROR, "Number is too long for structure.\n");
 		talloc_free(new_number);
-		return msg;
+		return NULL;
 	}
 
 	/*
@@ -841,7 +890,7 @@
 	if (!out) {
 		LOGP(DNAT, LOGL_ERROR, "Failed to allocate.\n");
 		talloc_free(new_number);
-		return msg;
+		return NULL;
 	}
 
 	/* copy the header */
@@ -869,25 +918,324 @@
 	outptr = msgb_put(out, sec_len);
 	memcpy(outptr, msgptr, sec_len);
 
+	talloc_free(new_number);
+	return out;
+}
+
+static struct msgb *rewrite_smsc(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 new_addr[12];
+
+
+	uint8_t dest_len;
+	char _dest_nr[30];
+	char *dest_nr;
+	uint8_t dest_match = 0;
+
+	struct bsc_nat_num_rewr_entry *entry;
+	char *new_number = NULL;
+	uint8_t new_addr_len;
+	struct gsm48_hdr *new_hdr48;
+	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;
+	}
+
+	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;
+	}
+
+	/* look into the phone number */
+	if ((data_ptr[0] & 0x01) != 1)
+		return NULL;
+
+	if (data_len < 3) {
+		LOGP(DNAT, LOGL_ERROR, "SMS-SUBMIT is too short.\n");
+		return NULL;
+	}
+
+	dest_len = data_ptr[2];
+	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 not a ISDN number.\n");
+		return NULL;
+	}
+
+	gsm48_decode_bcd_number(_dest_nr + 2, ARRAY_SIZE(_dest_nr) - 2,
+				&data_ptr[2], 1);
+	if ((data_ptr[3] & 0x70) == 0x10) {
+		_dest_nr[0] = _dest_nr[1] = '0';
+		dest_nr = &_dest_nr[0];
+	} else {
+		dest_nr = &_dest_nr[2];
+	}
+
+	/* 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(msg, "%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;
+	}
+
+	/*
+	 * 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->l3h = 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);
+
+	/*
+	 * Copy the new number. We let libosmocore encode it, then set
+	 * the extension followed after the length. For our convenience
+	 * we let the TLV code re-add the length so we start copying
+	 * from &new_addr[1].
+	 */
+	new_addr_len = gsm48_encode_bcd_number(new_addr, ARRAY_SIZE(new_addr),
+					       1, new_number);
+	new_addr[1] = 0x91;
+	msgb_lv_put(out, new_addr_len - 1, new_addr + 1);
+
+	msgb_lv_put(out, data_len, data_ptr);
+
+	new_hdr48 = (struct gsm48_hdr *) msgb_push(out, sizeof(*hdr48) + 1);
+	memcpy(new_hdr48, hdr48, sizeof(*hdr48));
+	new_hdr48->data[0] = msgb_l3len(out);
+
+	talloc_free(new_number);
+	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;
+
+	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;
+
+	proto = hdr48->proto_discr & 0x0f;
+	msg_type = hdr48->msg_type & 0xbf;
+
+	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_smsc(nat, msg, parsed, imsi, hdr48, len);
+
+	if (!new_msg)
+		return msg;
+
 	/* wrap with DTAP, SCCP, then IPA. TODO: Stop copying */
-	gsm0808_prepend_dtap_header(out, 0);
-	sccp = sccp_create_dt1(parsed->dest_local_ref, out->data, out->len);
+	gsm0808_prepend_dtap_header(new_msg, 0);
+	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");
-		talloc_free(new_number);
-		talloc_free(out);
 		return msg;
 	}
 
 	ipaccess_prepend_header(sccp, IPAC_PROTO_SCCP);
 
-	/* give up memory, we are done */
-	talloc_free(new_number);
 	/* the parsed hangs off from msg but it needs to survive */
 	talloc_steal(sccp, parsed);
 	msgb_free(msg);
-	msgb_free(out);
-	out = NULL;
 	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,
+				"Allication 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;
+		}
+
+		/* 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_vty.c b/src/osmo-bsc_nat/bsc_nat_vty.c
index 786db2d..b5c1cf2 100644
--- a/src/osmo-bsc_nat/bsc_nat_vty.c
+++ b/src/osmo-bsc_nat/bsc_nat_vty.c
@@ -1,6 +1,6 @@
 /* OpenBSC NAT interface to quagga VTY */
-/* (C) 2010 by Holger Hans Peter Freyther
- * (C) 2010 by On-Waves
+/* (C) 2010-2011 by Holger Hans Peter Freyther
+ * (C) 2010-2011 by On-Waves
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -26,9 +26,11 @@
 #include <openbsc/mgcp.h>
 #include <openbsc/vty.h>
 
-#include <osmocore/talloc.h>
-#include <osmocore/rate_ctr.h>
-#include <osmocore/utils.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 <osmocom/sccp/sccp.h>
 
@@ -36,6 +38,10 @@
 
 static struct bsc_nat *_nat;
 
+
+#define PAGING_STR "Paging\n"
+#define SMSC_REWRITE "SMSC Rewriting\n"
+
 static struct cmd_node nat_node = {
 	NAT_NODE,
 	"%s(nat)#",
@@ -48,6 +54,17 @@
 	1,
 };
 
+static struct cmd_node pgroup_node = {
+	PGROUP_NODE,
+	"%s(paging-group)#",
+	1,
+};
+
+static int config_write_pgroup(struct vty *vty)
+{
+	return CMD_SUCCESS;
+}
+
 static void write_acc_lst(struct vty *vty, struct bsc_nat_acc_lst *lst)
 {
 	struct bsc_nat_acc_lst_entry *entry;
@@ -62,13 +79,28 @@
 	}
 }
 
+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_nat_acc_lst *lst;
+	struct bsc_nat_paging_group *pgroup;
 
 	vty_out(vty, "nat%s", VTY_NEWLINE);
-	vty_out(vty, " msc ip %s%s", _nat->msc_ip, VTY_NEWLINE);
-	vty_out(vty, " msc port %d%s", _nat->msc_port, 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);
@@ -88,32 +120,34 @@
 
 	if (_nat->num_rewr_name)
 		vty_out(vty, " number-rewrite %s%s", _nat->num_rewr_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);
 
-	llist_for_each_entry(lst, &_nat->access_lists, list) {
+	llist_for_each_entry(lst, &_nat->access_lists, list)
 		write_acc_lst(vty, lst);
-	}
+	llist_for_each_entry(pgroup, &_nat->paging_groups, entry)
+		write_pgroup_lst(vty, pgroup);
 
 	return CMD_SUCCESS;
 }
 
-static void dump_lac(struct vty *vty, struct bsc_config *cfg)
-{
-	struct bsc_lac_entry *lac;
-	llist_for_each_entry(lac, &cfg->lac_list, entry)
-		vty_out(vty, "  location_area_code %u%s", lac->lac, VTY_NEWLINE);
-}
-
 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);
-	dump_lac(vty, bsc);
-	vty_out(vty, "  paging forbidden %d%s", bsc->forbid_paging, 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);
 }
 
 static int config_write_bsc(struct vty *vty)
@@ -226,15 +260,15 @@
 {
 	vty_out(vty, "NAT statistics%s", VTY_NEWLINE);
 	vty_out(vty, " SCCP Connections %lu total, %lu calls%s",
-		counter_get(nat->stats.sccp.conn),
-		counter_get(nat->stats.sccp.calls), VTY_NEWLINE);
+		osmo_counter_get(nat->stats.sccp.conn),
+		osmo_counter_get(nat->stats.sccp.calls), VTY_NEWLINE);
 	vty_out(vty, " MSC Connections %lu%s",
-		counter_get(nat->stats.msc.reconn), VTY_NEWLINE);
+		osmo_counter_get(nat->stats.msc.reconn), VTY_NEWLINE);
 	vty_out(vty, " MSC Connected: %d%s",
 		nat->msc_con->is_connected, VTY_NEWLINE);
 	vty_out(vty, " BSC Connections %lu total, %lu auth failed.%s",
-		counter_get(nat->stats.bsc.reconn),
-		counter_get(nat->stats.bsc.auth_fail), VTY_NEWLINE);
+		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)
@@ -309,8 +343,7 @@
 		return CMD_WARNING;
 	}
 
-	vty_out(vty, "MSC on %s:%d is connected: %d%s\n",
-		_nat->msc_con->ip, _nat->msc_con->port,
+	vty_out(vty, "MSC is connected: %d%s\n",
 		_nat->msc_con->is_connected, VTY_NEWLINE);
 	return CMD_SUCCESS;
 }
@@ -355,7 +388,7 @@
       "msc port <1-65500>",
       "Set the port of the MSC.")
 {
-	_nat->msc_port = atoi(argv[0]);
+	_nat->main_dest->port = atoi(argv[0]);
 	return CMD_SUCCESS;
 }
 
@@ -417,23 +450,65 @@
 	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;
+}
+
+static int replace_rules(struct bsc_nat *nat, char **name,
+			 struct llist_head *head, const char *file)
+{
+	struct osmo_config_list *rewr = NULL;
+
+	bsc_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")
 {
-	bsc_replace_string(_nat, &_nat->num_rewr_name, argv[0]);
-	if (_nat->num_rewr_name) {
-		if (_nat->num_rewr)
-			talloc_free(_nat->num_rewr);
-		_nat->num_rewr = msg_entry_parse(_nat, _nat->num_rewr_name);
-		return _nat->num_rewr == NULL ? CMD_WARNING : CMD_SUCCESS;
-	} else {
-		if (_nat->num_rewr)
-			talloc_free(_nat->num_rewr);
-		_nat->num_rewr = NULL;
-		return CMD_SUCCESS;
-	}
+	return replace_rules(_nat, &_nat->num_rewr_name,
+			     &_nat->num_rewr, argv[0]);
+}
+
+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_ussd_lst_name,
@@ -448,11 +523,12 @@
 
 DEFUN(cfg_nat_ussd_query,
       cfg_nat_ussd_query_cmd,
-      "ussd-query QUERY",
+      "ussd-query REGEXP",
       "Set the USSD query to match with the ussd-list-name\n"
       "The query to match")
 {
-	bsc_replace_string(_nat, &_nat->ussd_query, argv[0]);
+	if (bsc_parse_reg(_nat, &_nat->ussd_query_re, &_nat->ussd_query, argc, argv) != 0)
+		return CMD_WARNING;
 	return CMD_SUCCESS;
 }
 
@@ -508,7 +584,7 @@
 }
 
 DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>",
-      "Set the Location Area Code (LAC) of this BSC")
+      "Add the Location Area Code (LAC) of this BSC\n" "LAC\n")
 {
 	struct bsc_config *tmp;
 	struct bsc_config *conf = vty->index;
@@ -536,7 +612,7 @@
 
 DEFUN(cfg_bsc_no_lac, cfg_bsc_no_lac_cmd,
       "no location_area_code <0-65535>",
-      NO_STR "Set the Location Area Code (LAC) of this BSC")
+      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;
@@ -550,7 +626,7 @@
 DEFUN(cfg_lst_imsi_allow,
       cfg_lst_imsi_allow_cmd,
       "access-list NAME imsi-allow [REGEXP]",
-      "Allow IMSIs matching the REGEXP\n"
+      "Add the regexp to the allowed list\n"
       "The name of the access-list\n"
       "The regexp of allowed IMSIs\n")
 {
@@ -565,14 +641,15 @@
 	if (!entry)
 		return CMD_WARNING;
 
-	bsc_parse_reg(acc, &entry->imsi_allow_re, &entry->imsi_allow, argc - 1, &argv[1]);
+	if (bsc_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]",
-      "Allow IMSIs matching the REGEXP\n"
+      "Add the regexp to the deny list\n"
       "The name of the access-list\n"
       "The regexp of to be denied IMSIs\n")
 {
@@ -587,7 +664,8 @@
 	if (!entry)
 		return CMD_WARNING;
 
-	bsc_parse_reg(acc, &entry->imsi_deny_re, &entry->imsi_deny, argc - 1, &argv[1]);
+	if (bsc_parse_reg(acc, &entry->imsi_deny_re, &entry->imsi_deny, argc - 1, &argv[1]) != 0)
+		return CMD_WARNING;
 	return CMD_SUCCESS;
 }
 
@@ -636,6 +714,21 @@
 	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")
@@ -649,7 +742,7 @@
 DEFUN(cfg_bsc_paging,
       cfg_bsc_paging_cmd,
       "paging forbidden (0|1)",
-      "Forbid sending PAGING REQUESTS to the BSC.")
+      PAGING_STR "Forbid sending PAGING REQUESTS to the BSC.")
 {
 	struct bsc_config *conf = vty->index;
 
@@ -672,6 +765,30 @@
 	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",
       "Check if the string is matching the current pattern.")
@@ -680,7 +797,8 @@
 	char *str = NULL;
 
 	memset(&reg, 0, sizeof(reg));
-	bsc_parse_reg(_nat, &reg, &str, 1, argv);
+	if (bsc_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);
@@ -715,6 +833,81 @@
 	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")
+{
+	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;
+}
+
 int bsc_nat_vty_init(struct bsc_nat *nat)
 {
 	_nat = nat;
@@ -732,6 +925,7 @@
 	install_element_ve(&show_acc_lst_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);
@@ -748,6 +942,7 @@
 	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_ussd_lst_name_cmd);
 	install_element(NAT_NODE, &cfg_nat_ussd_query_cmd);
 	install_element(NAT_NODE, &cfg_nat_ussd_token_cmd);
@@ -760,6 +955,15 @@
 
 	/* number rewriting */
 	install_element(NAT_NODE, &cfg_nat_number_rewrite_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_pgroup_cmd);
+	install_element(NAT_NODE, &cfg_nat_no_pgroup_cmd);
+	install_node(&pgroup_node, config_write_pgroup);
+	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);
@@ -773,7 +977,11 @@
 	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);
 
 	mgcp_vty_init();
 
@@ -782,7 +990,8 @@
 
 
 /* called by the telnet interface... we have our own init above */
-int bsc_vty_init(void)
+int bsc_vty_init(const struct log_info *cat)
 {
+	logging_vty_add_cmds(cat);
 	return 0;
 }
diff --git a/src/osmo-bsc_nat/bsc_sccp.c b/src/osmo-bsc_nat/bsc_sccp.c
index 72de112..de6b421 100644
--- a/src/osmo-bsc_nat/bsc_sccp.c
+++ b/src/osmo-bsc_nat/bsc_sccp.c
@@ -25,7 +25,7 @@
 
 #include <osmocom/sccp/sccp.h>
 
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 
 #include <string.h>
 #include <time.h>
@@ -129,7 +129,7 @@
 	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]);
-	counter_inc(bsc->cfg->nat->stats.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),
diff --git a/src/osmo-bsc_nat/bsc_ussd.c b/src/osmo-bsc_nat/bsc_ussd.c
index c121abe..bbbeead 100644
--- a/src/osmo-bsc_nat/bsc_ussd.c
+++ b/src/osmo-bsc_nat/bsc_ussd.c
@@ -1,8 +1,8 @@
 /* USSD Filter Code */
 
 /*
- * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010 by On-Waves
+ * (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
@@ -25,10 +25,10 @@
 #include <openbsc/ipaccess.h>
 #include <openbsc/socket.h>
 
-#include <osmocore/protocol/gsm_08_08.h>
-#include <osmocore/gsm0480.h>
-#include <osmocore/talloc.h>
-#include <osmocore/tlv.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/sccp/sccp.h>
 
@@ -36,14 +36,6 @@
 #include <string.h>
 #include <unistd.h>
 
-struct bsc_nat_ussd_con {
-	struct write_queue queue;
-	struct bsc_nat *nat;
-	int authorized;
-
-	struct timer_list auth_timeout;
-};
-
 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)
@@ -66,9 +58,9 @@
 	}
 
 	close(con->queue.bfd.fd);
-	bsc_unregister_fd(&con->queue.bfd);
-	bsc_del_timer(&con->auth_timeout);
-	write_queue_clear(&con->queue);
+	osmo_fd_unregister(&con->queue.bfd);
+	osmo_timer_del(&con->auth_timeout);
+	osmo_wqueue_clear(&con->queue);
 	talloc_free(con);
 }
 
@@ -103,7 +95,7 @@
 	return 0;
 }
 
-static int ussd_read_cb(struct bsc_fd *bfd)
+static int ussd_read_cb(struct osmo_fd *bfd)
 {
 	int error;
 	struct bsc_nat_ussd_con *conn = bfd->data;
@@ -117,15 +109,21 @@
 	}
 
 	LOGP(DNAT, LOGL_NOTICE, "MSG from USSD: %s proto: %d\n",
-		hexdump(msg->data, msg->len), msg->l2h[0]);
+		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;
-			ipaccess_idtag_parse(&tvp,
+			int ret;
+			ret = ipaccess_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");
+				return ret;
+			}
 			if (TLVP_PRESENT(&tvp, IPAC_IDTAG_UNITNAME))
 				ussd_auth_con(&tvp, conn);
 		}
@@ -170,7 +168,7 @@
 		bsc_nat_ussd_destroy(conn->nat->ussd_con);
 
 	LOGP(DNAT, LOGL_ERROR, "USSD token specified. USSD provider is connected.\n");
-	bsc_del_timer(&conn->auth_timeout);
+	osmo_timer_del(&conn->auth_timeout);
 	conn->authorized = 1;
 	conn->nat->ussd_con = conn;
 }
@@ -181,7 +179,7 @@
 
 	conn->auth_timeout.data = conn;
 	conn->auth_timeout.cb = ussd_auth_cb;
-	bsc_schedule_timer(&conn->auth_timeout, conn->nat->auth_timeout, 0);
+	osmo_timer_schedule(&conn->auth_timeout, conn->nat->auth_timeout, 0);
 
 	msg = msgb_alloc_headroom(4096, 128, "auth message");
 	if (!msg) {
@@ -193,7 +191,7 @@
 	bsc_do_write(&conn->queue, msg, IPAC_PROTO_IPACCESS);
 }
 
-static int ussd_listen_cb(struct bsc_fd *bfd, unsigned int what)
+static int ussd_listen_cb(struct osmo_fd *bfd, unsigned int what)
 {
 	struct bsc_nat_ussd_con *conn;
 	struct bsc_nat *nat;
@@ -211,7 +209,7 @@
 	}
 
 	nat = (struct bsc_nat *) bfd->data;
-	counter_inc(nat->stats.ussd.reconn);
+	osmo_counter_inc(nat->stats.ussd.reconn);
 
 	conn = bsc_nat_ussd_alloc(nat);
 	if (!conn) {
@@ -220,14 +218,14 @@
 		return -1;
 	}
 
-	write_queue_init(&conn->queue, 10);
+	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 (bsc_register_fd(&conn->queue.bfd) < 0) {
+	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;
@@ -251,7 +249,31 @@
 
 	nat->ussd_listen.data = nat;
 	return make_sock(&nat->ussd_listen, IPPROTO_TCP,
-			 ntohl(addr.s_addr), 5001, ussd_listen_cb);
+			 ntohl(addr.s_addr), 5001, 0, ussd_listen_cb, nat);
+}
+
+static int forward_ussd_simple(struct sccp_connections *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 sccp_connections *con, const struct ussd_request *req,
@@ -303,6 +325,8 @@
 {
 	uint32_t len;
 	uint8_t msg_type;
+	uint8_t proto;
+	uint8_t ti;
 	struct gsm48_hdr *hdr48;
 	struct bsc_nat_acc_lst *lst;
 	struct ussd_request req;
@@ -318,6 +342,10 @@
 	if (!con->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)
@@ -333,31 +361,47 @@
 	if (!hdr48)
 		return 0;
 
+	proto = hdr48->proto_discr & 0x0f;
 	msg_type = hdr48->msg_type & 0xbf;
-	if (hdr48->proto_discr != GSM48_PDISC_NC_SS || msg_type != GSM0480_MTYPE_REGISTER)
+	ti = (hdr48->proto_discr & 0x70) >> 4;
+	if (proto != GSM48_PDISC_NC_SS)
 		return 0;
 
-	/* now check if it is a IMSI we care about */
-	lst = bsc_nat_acc_lst_find(con->bsc->nat, con->bsc->nat->ussd_lst_name);
-	if (!lst)
-		return 0;
+	if (msg_type == GSM0480_MTYPE_REGISTER) {
 
-	if (bsc_nat_lst_check_allow(lst, con->imsi) != 0)
-		return 0;
+		/* now check if it is a IMSI we care about */
+		lst = bsc_nat_acc_lst_find(con->bsc->nat,
+					   con->bsc->nat->ussd_lst_name);
+		if (!lst)
+			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 (bsc_nat_lst_check_allow(lst, con->imsi) != 0)
+			return 0;
 
-	if (strcmp(req.text, con->bsc->nat->ussd_query) != 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;
 
-	/* found a USSD query for our subscriber */
-	LOGP(DNAT, LOGL_NOTICE, "Found USSD query for %s\n", con->imsi);
-	if (forward_ussd(con, &req, msg) != 0)
-		return 0;
-	return 1;
+		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->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->imsi);
+		if (forward_ussd_simple(con, msg) != 0)
+			return 0;
+		return 1;
+	}
+
+	return 0;
 }
diff --git a/src/osmo-nitb/Makefile.am b/src/osmo-nitb/Makefile.am
index 44cb023..f067f43 100644
--- a/src/osmo-nitb/Makefile.am
+++ b/src/osmo-nitb/Makefile.am
@@ -1,11 +1,11 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 
 bin_PROGRAMS = osmo-nitb
 
 osmo_nitb_SOURCES = bsc_hack.c
-osmo_nitb_LDADD = -ldl -ldbi $(LIBCRYPT) $(LIBOSMOVTY_LIBS) \
+osmo_nitb_LDADD = -ldl -ldbi $(LIBCRYPT) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) \
 		$(top_builddir)/src/libbsc/libbsc.a \
 		$(top_builddir)/src/libmsc/libmsc.a \
 		$(top_builddir)/src/libbsc/libbsc.a \
diff --git a/src/osmo-nitb/Makefile.in b/src/osmo-nitb/Makefile.in
index 8e94435..5fd4c08 100644
--- a/src/osmo-nitb/Makefile.in
+++ b/src/osmo-nitb/Makefile.in
@@ -36,7 +36,7 @@
 subdir = src/osmo-nitb
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -48,7 +48,7 @@
 am_osmo_nitb_OBJECTS = bsc_hack.$(OBJEXT)
 osmo_nitb_OBJECTS = $(am_osmo_nitb_OBJECTS)
 am__DEPENDENCIES_1 =
-osmo_nitb_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+osmo_nitb_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
 	$(top_builddir)/src/libbsc/libbsc.a \
 	$(top_builddir)/src/libmsc/libmsc.a \
 	$(top_builddir)/src/libbsc/libbsc.a \
@@ -113,6 +113,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -182,10 +184,10 @@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 osmo_nitb_SOURCES = bsc_hack.c
-osmo_nitb_LDADD = -ldl -ldbi $(LIBCRYPT) $(LIBOSMOVTY_LIBS) \
+osmo_nitb_LDADD = -ldl -ldbi $(LIBCRYPT) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) \
 		$(top_builddir)/src/libbsc/libbsc.a \
 		$(top_builddir)/src/libmsc/libmsc.a \
 		$(top_builddir)/src/libbsc/libbsc.a \
diff --git a/src/osmo-nitb/bsc_hack.c b/src/osmo-nitb/bsc_hack.c
index 357ec7a..e548a95 100644
--- a/src/osmo-nitb/bsc_hack.c
+++ b/src/osmo-nitb/bsc_hack.c
@@ -30,20 +30,22 @@
 #include <getopt.h>
 
 #include <openbsc/db.h>
-#include <osmocore/select.h>
-#include <osmocore/process.h>
+#include <osmocom/core/application.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/process.h>
 #include <openbsc/debug.h>
 #include <openbsc/e1_input.h>
-#include <osmocore/talloc.h>
+#include <osmocom/core/talloc.h>
 #include <openbsc/signal.h>
 #include <openbsc/osmo_msc.h>
 #include <openbsc/sms_queue.h>
 #include <openbsc/vty.h>
+#include <openbsc/bss.h>
+#include <openbsc/mncc.h>
 
 #include "../../bscconfig.h"
 
 /* MCC and MNC for the Location Area Identifier */
-static struct log_target *stderr_target;
 struct gsm_network *bsc_gsmnet = 0;
 static const char *database_name = "hlr.sqlite3";
 static const char *config_file = "openbsc.cfg";
@@ -53,11 +55,7 @@
 
 /* timer to store statistics */
 #define DB_SYNC_INTERVAL	60, 0
-static struct timer_list db_sync_timer;
-
-extern int bsc_bootstrap_network(int (*mncc_recv)(struct gsm_network *, struct msgb *),
-				 const char *cfg_file);
-extern int bsc_shutdown_net(struct gsm_network *net);
+static struct osmo_timer_list db_sync_timer;
 
 static void create_pcap_file(char *file)
 {
@@ -127,10 +125,10 @@
 			print_help();
 			exit(0);
 		case 's':
-			log_set_use_color(stderr_target, 0);
+			log_set_use_color(osmo_stderr_target, 0);
 			break;
 		case 'd':
-			log_parse_category_mask(stderr_target, optarg);
+			log_parse_category_mask(osmo_stderr_target, optarg);
 			break;
 		case 'D':
 			daemonize = 1;
@@ -145,13 +143,13 @@
 			create_pcap_file(optarg);
 			break;
 		case 'T':
-			log_set_print_timestamp(stderr_target, 1);
+			log_set_print_timestamp(osmo_stderr_target, 1);
 			break;
 		case 'P':
 			ipacc_rtp_direct = 0;
 			break;
 		case 'e':
-			log_set_log_level(stderr_target, atoi(optarg));
+			log_set_log_level(osmo_stderr_target, atoi(optarg));
 			break;
 		case 'm':
 			use_mncc_sock = 1;
@@ -175,7 +173,7 @@
 	switch (signal) {
 	case SIGINT:
 		bsc_shutdown_net(bsc_gsmnet);
-		dispatch_signal(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
+		osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
 		sleep(3);
 		exit(0);
 		break;
@@ -195,7 +193,7 @@
 }
 
 /* timer handling */
-static int _db_store_counter(struct counter *counter, void *data)
+static int _db_store_counter(struct osmo_counter *counter, void *data)
 {
 	return db_store_counter(counter);
 }
@@ -203,15 +201,10 @@
 static void db_sync_timer_cb(void *data)
 {
 	/* store counters to database and re-schedule */
-	counters_for_each(_db_store_counter, NULL);
-	bsc_schedule_timer(&db_sync_timer, DB_SYNC_INTERVAL);
+	osmo_counters_for_each(_db_store_counter, NULL);
+	osmo_timer_schedule(&db_sync_timer, DB_SYNC_INTERVAL);
 }
 
-extern int bts_model_unknown_init(void);
-extern int bts_model_bs11_init(void);
-extern int bts_model_nanobts_init(void);
-extern int bts_model_rbs2k_init(void);
-extern int bts_model_hslfemto_init(void);
 void talloc_ctx_init(void);
 
 extern enum node_type bsc_vty_go_parent(struct vty *vty);
@@ -229,29 +222,20 @@
 
 	vty_info.copyright = openbsc_copyright;
 
-	log_init(&log_info);
 	tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
 	talloc_ctx_init();
 	on_dso_load_token();
 	on_dso_load_rrlp();
 	on_dso_load_ho_dec();
-	stderr_target = log_target_create_stderr();
-	log_add_target(stderr_target);
 
-	bts_model_unknown_init();
-	bts_model_bs11_init();
-	bts_model_nanobts_init();
-	bts_model_rbs2k_init();
-	bts_model_hslfemto_init();
+	osmo_init_logging(&log_info);
 
+	bts_init();
 	e1inp_init();
 
-	/* enable filters */
-	log_set_all_filter(stderr_target, 1);
-
 	/* This needs to precede handle_options() */
 	vty_init(&vty_info);
-	bsc_vty_init();
+	bsc_vty_init(&log_info);
 
 	/* parse options */
 	handle_options(argc, argv);
@@ -266,7 +250,6 @@
 	if (rc < 0)
 		exit(1);
 	bsc_api_init(bsc_gsmnet, msc_bsc_api());
-	mncc_sock_init(bsc_gsmnet);
 
 	/* seed the PRNG */
 	srand(time(NULL));
@@ -286,13 +269,13 @@
 	/* setup the timer */
 	db_sync_timer.cb = db_sync_timer_cb;
 	db_sync_timer.data = NULL;
-	bsc_schedule_timer(&db_sync_timer, DB_SYNC_INTERVAL);
+	osmo_timer_schedule(&db_sync_timer, DB_SYNC_INTERVAL);
 
 	signal(SIGINT, &signal_handler);
 	signal(SIGABRT, &signal_handler);
 	signal(SIGUSR1, &signal_handler);
 	signal(SIGUSR2, &signal_handler);
-	signal(SIGPIPE, SIG_IGN);
+	osmo_init_ignore_signals();
 
 	/* start the SMS queue */
 	if (sms_queue_start(bsc_gsmnet, 20) != 0)
@@ -308,6 +291,6 @@
 
 	while (1) {
 		log_reset_context();
-		bsc_select_main(0);
+		osmo_select_main(0);
 	}
 }
diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am
index 2351f8a..c2d2085 100644
--- a/src/utils/Makefile.am
+++ b/src/utils/Makefile.am
@@ -1,6 +1,6 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 
 bin_PROGRAMS = bs11_config isdnsync
 
diff --git a/src/utils/Makefile.in b/src/utils/Makefile.in
index 17e8ad6..25f0f4e 100644
--- a/src/utils/Makefile.in
+++ b/src/utils/Makefile.in
@@ -36,7 +36,7 @@
 subdir = src/utils
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -111,6 +111,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -180,8 +182,8 @@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
 bs11_config_SOURCES = bs11_config.c rs232.c
 bs11_config_LDADD = $(top_builddir)/src/libcommon/libcommon.a \
 		    $(top_builddir)/src/libabis/libabis.a \
diff --git a/src/utils/bs11_config.c b/src/utils/bs11_config.c
index eaed8b7..41acd69 100644
--- a/src/utils/bs11_config.c
+++ b/src/utils/bs11_config.c
@@ -30,16 +30,16 @@
 #include <fcntl.h>
 #include <signal.h>
 
-#include <sys/types.h>
 #include <sys/stat.h>
 
 #include <openbsc/gsm_data.h>
 #include <openbsc/abis_nm.h>
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/tlv.h>
 #include <openbsc/debug.h>
-#include <osmocore/select.h>
+#include <osmocom/core/select.h>
 #include <openbsc/rs232.h>
+#include <osmocom/core/application.h>
 
 /* state of our bs11_config application */
 enum bs11cfg_state {
@@ -51,29 +51,27 @@
 };
 static enum bs11cfg_state bs11cfg_state = STATE_NONE;
 static char *command, *value;
-struct timer_list status_timer;
+struct osmo_timer_list status_timer;
 
-static const u_int8_t obj_li_attr[] = {
+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 u_int8_t obj_bbsig0_attr[] = {
+static const uint8_t obj_bbsig0_attr[] = {
 	NM_ATT_BS11_RSSI_OFFS, 0x02, 0x00, 0x00,
 	NM_ATT_BS11_DIVERSITY, 0x01, 0x00,
 };
-static const u_int8_t obj_pa0_attr[] = {
+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
 
-static const u_int8_t too_fast[] = { 0x12, 0x80, 0x00, 0x00, 0x02, 0x02 };
-
-static struct log_target *stderr_target;
+static const uint8_t too_fast[] = { 0x12, 0x80, 0x00, 0x00, 0x02, 0x02 };
 
 /* dummy function to keep gsm_data.c happy */
-struct counter *counter_alloc(const char *name)
+struct osmo_counter *osmo_counter_alloc(const char *name)
 {
 	return NULL;
 }
@@ -113,8 +111,8 @@
 
 static int create_trx1(struct gsm_bts *bts)
 {
-	u_int8_t bbsig1_attr[sizeof(obj_bbsig0_attr)+12];
-	u_int8_t *cur = bbsig1_attr;
+	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)
@@ -127,7 +125,7 @@
 	sleep(1);
 
 	cur = tlv_put(cur, NM_ATT_BS11_PASSWORD, 10,
-		      (u_int8_t *)trx1_password);
+		      (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);
@@ -217,7 +215,7 @@
 	[0x02]	= "Restoring",
 };
 
-static const char *linkstate_name(u_int8_t linkstate)
+static const char *linkstate_name(uint8_t linkstate)
 {
 	if (linkstate > ARRAY_SIZE(bs11_link_state))
 		return "Unknown";
@@ -234,7 +232,7 @@
 	[5]	= "Load",
 };
 
-static const char *mbccu_load_name(u_int8_t linkstate)
+static const char *mbccu_load_name(uint8_t linkstate)
 {
 	if (linkstate > ARRAY_SIZE(mbccu_load))
 		return "Unknown";
@@ -242,7 +240,7 @@
 	return mbccu_load[linkstate];
 }
 
-static const char *bts_phase_name(u_int8_t phase)
+static const char *bts_phase_name(uint8_t phase)
 {
 	switch (phase) {
 	case BS11_STATE_WARM_UP:
@@ -280,7 +278,7 @@
 	}
 }
 
-static const char *trx_power_name(u_int8_t pwr)
+static const char *trx_power_name(uint8_t pwr)
 {
 	switch (pwr) {
 	case BS11_TRX_POWER_GSM_2W:	
@@ -304,7 +302,7 @@
 	}
 }
 
-static const char *pll_mode_name(u_int8_t mode)
+static const char *pll_mode_name(uint8_t mode)
 {
 	switch (mode) {
 	case BS11_LI_PLL_LOCKED:
@@ -316,7 +314,7 @@
 	}
 }
 
-static const char *cclk_acc_name(u_int8_t acc)
+static const char *cclk_acc_name(uint8_t acc)
 {
 	switch (acc) {
 	case 0:
@@ -330,7 +328,7 @@
 	}
 }
 
-static const char *bport_lcfg_name(u_int8_t lcfg)
+static const char *bport_lcfg_name(uint8_t lcfg)
 {
 	switch (lcfg) {
 	case BS11_LINE_CFG_STAR:
@@ -378,7 +376,7 @@
 static void print_state(struct tlv_parsed *tp)
 {
 	if (TLVP_PRESENT(tp, NM_ATT_BS11_BTS_STATE)) {
-		u_int8_t phase, mbccu;
+		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,
@@ -392,7 +390,7 @@
 	}
 	if (TLVP_PRESENT(tp, NM_ATT_BS11_E1_STATE) &&
 	    TLVP_LEN(tp, NM_ATT_BS11_E1_STATE) >= 1) {
-		u_int8_t e1_state = *TLVP_VAL(tp, NM_ATT_BS11_E1_STATE);
+		uint8_t e1_state = *TLVP_VAL(tp, NM_ATT_BS11_E1_STATE);
 		printf("Abis-link: %-9s ", linkstate_name(e1_state & 0xf));
 	}
 	printf("\n");
@@ -420,7 +418,7 @@
 #endif
 	if (TLVP_PRESENT(tp, NM_ATT_ABIS_CHANNEL) &&
 	    TLVP_LEN(tp, NM_ATT_ABIS_CHANNEL) >= 3) {
-		const u_int8_t *chan = TLVP_VAL(tp, NM_ATT_ABIS_CHANNEL);
+		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)
@@ -442,23 +440,23 @@
 	}
 	if (TLVP_PRESENT(tp, NM_ATT_BS11_PLL) &&
 	    TLVP_LEN(tp, NM_ATT_BS11_PLL) >= 4) {
-		const u_int8_t *vp = TLVP_VAL(tp, NM_ATT_BS11_PLL);
+		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 u_int8_t *acc = TLVP_VAL(tp, NM_ATT_BS11_CCLK_ACCURACY);
+		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 u_int8_t *acc = TLVP_VAL(tp, NM_ATT_BS11_CCLK_TYPE);
+		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 u_int8_t *lcfg = TLVP_VAL(tp, NM_ATT_BS11_LINE_CFG);
+		const uint8_t *lcfg = TLVP_VAL(tp, NM_ATT_BS11_LINE_CFG);
 		printf("\tLine Configuration: %s (%d)\n",
 			bport_lcfg_name(*lcfg), *lcfg);
 	}
@@ -689,7 +687,7 @@
 		printf("\n%sATTRIBUTES:\n", obj_name(foh));
 		abis_nm_tlv_parse(&tp, g_bts, foh->data, oh->length-sizeof(*foh));
 		rc = print_attr(&tp);
-		//hexdump(foh->data, oh->length-sizeof(*foh));
+		//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",
@@ -732,7 +730,7 @@
 		abis_nm_bs11_factory_logon(g_bts, 1);
 		break;
 	case STATE_LOGON_ACK:
-		bsc_schedule_timer(&status_timer, 5, 0);
+		osmo_timer_schedule(&status_timer, 5, 0);
 		break;
 	default:
 		break;
@@ -818,7 +816,7 @@
 			serial_port = optarg;
 			break;
 		case 'b':
-			log_parse_category_mask(stderr_target, optarg);
+			log_parse_category_mask(osmo_stderr_target, optarg);
 			break;
 		case 's':
 			fname_software = optarg;
@@ -875,10 +873,7 @@
 	struct gsm_network *gsmnet;
 	int rc;
 
-	log_init(&log_info);
-	stderr_target = log_target_create_stderr();
-	log_add_target(stderr_target);
-	log_set_all_filter(stderr_target, 1);
+	osmo_init_logging(&log_info);
 	handle_options(argc, argv);
 	bts_model_bs11_init();
 
@@ -887,8 +882,8 @@
 		fprintf(stderr, "Unable to allocate gsm network\n");
 		exit(1);
 	}
-	g_bts = gsm_bts_alloc(gsmnet, GSM_BTS_TYPE_BS11, HARDCODED_TSC,
-				HARDCODED_BSIC);
+	g_bts = gsm_bts_alloc_register(gsmnet, GSM_BTS_TYPE_BS11, HARDCODED_TSC,
+					HARDCODED_BSIC);
 
 	rc = rs232_setup(serial_port, delay_ms, g_bts);
 	if (rc < 0) {
@@ -904,7 +899,7 @@
 	status_timer.cb = status_timer_cb;
 
 	while (1) {
-		bsc_select_main(0);
+		osmo_select_main(0);
 	}
 
 	abis_nm_bs11_factory_logon(g_bts, 0);
diff --git a/src/utils/isdnsync.c b/src/utils/isdnsync.c
index 1c4aa5d..d8fca76 100644
--- a/src/utils/isdnsync.c
+++ b/src/utils/isdnsync.c
@@ -23,7 +23,6 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/ioctl.h>
-#include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <errno.h>
diff --git a/src/utils/rs232.c b/src/utils/rs232.c
index 7550571..4e35cb0 100644
--- a/src/utils/rs232.c
+++ b/src/utils/rs232.c
@@ -27,8 +27,8 @@
 #include <termios.h>
 #include <fcntl.h>
 
-#include <osmocore/select.h>
-#include <osmocore/msgb.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/msgb.h>
 #include <openbsc/debug.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/rs232.h>
@@ -36,7 +36,7 @@
 /* adaption layer from GSM 08.59 + 12.21 to RS232 */
 
 struct serial_handle {
-	struct bsc_fd fd;
+	struct osmo_fd fd;
 	struct llist_head tx_queue;
 
 	struct msgb *rx_msg;
@@ -51,13 +51,13 @@
 
 #define LAPD_HDR_LEN	10
 
-static int handle_ser_write(struct bsc_fd *bfd);
+static int handle_ser_write(struct osmo_fd *bfd);
 
 /* callback from abis_nm */
 int _abis_nm_sendmsg(struct msgb *msg, int to_trx_oml)
 {
 	struct serial_handle *sh = ser_handle;
-	u_int8_t *lapd;
+	uint8_t *lapd;
 	unsigned int len;
 
 	msg->l2h = msg->data;
@@ -88,7 +88,7 @@
 }
 
 /* select.c callback in case we can write to the RS232 */
-static int handle_ser_write(struct bsc_fd *bfd)
+static int handle_ser_write(struct osmo_fd *bfd)
 {
 	struct serial_handle *sh = bfd->data;
 	struct msgb *msg;
@@ -100,7 +100,7 @@
 		return 0;
 	}
 
-	DEBUGP(DMI, "RS232 TX: %s\n", hexdump(msg->data, msg->len));
+	DEBUGP(DMI, "RS232 TX: %s\n", osmo_hexdump(msg->data, msg->len));
 
 	/* send over serial line */
 	written = write(bfd->fd, msg->data, msg->len);
@@ -119,7 +119,7 @@
 #define SERIAL_ALLOC_SIZE	300
 
 /* select.c callback in case we can read from the RS232 */
-static int handle_ser_read(struct bsc_fd *bfd)
+static int handle_ser_read(struct osmo_fd *bfd)
 {
 	struct serial_handle *sh = bfd->data;
 	struct msgb *msg;
@@ -173,7 +173,7 @@
 			if (msg->len > LAPD_HDR_LEN)
 				msg->l2h = msg->data + LAPD_HDR_LEN;
 
-			DEBUGP(DMI, "RS232 RX: %s\n", hexdump(msg->data, msg->len));
+			DEBUGP(DMI, "RS232 RX: %s\n", osmo_hexdump(msg->data, msg->len));
 			rc = handle_serial_msg(msg);
 		}
 	}
@@ -182,7 +182,7 @@
 }
 
 /* select.c callback */
-static int serial_fd_cb(struct bsc_fd *bfd, unsigned int what)
+static int serial_fd_cb(struct osmo_fd *bfd, unsigned int what)
 {
 	int rc = 0;
 
@@ -237,7 +237,7 @@
 	ser_handle->fd.data = ser_handle;
 	ser_handle->delay_ms = delay_ms;
 	ser_handle->bts = bts;
-	rc = bsc_register_fd(&ser_handle->fd);
+	rc = osmo_fd_register(&ser_handle->fd);
 	if (rc < 0) {
 		fprintf(stderr, "could not register FD: %s\n",
 			strerror(rc));
diff --git a/tests/Makefile.in b/tests/Makefile.in
index f5e61eb..116ab92 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -35,7 +35,7 @@
 subdir = tests
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -124,6 +124,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
diff --git a/tests/bsc-nat/Makefile.am b/tests/bsc-nat/Makefile.am
index 04bdb97..4785098 100644
--- a/tests/bsc-nat/Makefile.am
+++ b/tests/bsc-nat/Makefile.am
@@ -1,5 +1,5 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include
-AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(COVERAGE_CFLAGS)
+AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(COVERAGE_CFLAGS)
 AM_LDFLAGS = $(COVERAGE_LDFLAGS)
 
 EXTRA_DIST = bsc_data.c
@@ -16,4 +16,4 @@
 			$(top_srcdir)/src/libabis/libabis.a \
 			$(top_srcdir)/src/libtrau/libtrau.a \
 			$(top_srcdir)/src/libcommon/libcommon.a \
-			$(LIBOSMOCORE_LIBS) -lrt $(LIBOSMOSCCP_LIBS) $(LIBOSMOVTY_LIBS)
+			$(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -lrt $(LIBOSMOSCCP_LIBS) $(LIBOSMOVTY_LIBS)
diff --git a/tests/bsc-nat/Makefile.in b/tests/bsc-nat/Makefile.in
index 280d22d..6e1d094 100644
--- a/tests/bsc-nat/Makefile.in
+++ b/tests/bsc-nat/Makefile.in
@@ -36,7 +36,7 @@
 subdir = tests/bsc-nat
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -54,7 +54,8 @@
 	$(top_srcdir)/src/libabis/libabis.a \
 	$(top_srcdir)/src/libtrau/libtrau.a \
 	$(top_srcdir)/src/libcommon/libcommon.a $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
@@ -116,6 +117,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -185,7 +188,7 @@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include
-AM_CFLAGS = -Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(COVERAGE_CFLAGS)
+AM_CFLAGS = -Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(COVERAGE_CFLAGS)
 AM_LDFLAGS = $(COVERAGE_LDFLAGS)
 EXTRA_DIST = bsc_data.c
 bsc_nat_test_SOURCES = bsc_nat_test.c \
@@ -199,7 +202,7 @@
 			$(top_srcdir)/src/libabis/libabis.a \
 			$(top_srcdir)/src/libtrau/libtrau.a \
 			$(top_srcdir)/src/libcommon/libcommon.a \
-			$(LIBOSMOCORE_LIBS) -lrt $(LIBOSMOSCCP_LIBS) $(LIBOSMOVTY_LIBS)
+			$(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -lrt $(LIBOSMOSCCP_LIBS) $(LIBOSMOVTY_LIBS)
 
 all: all-am
 
diff --git a/tests/bsc-nat/bsc_data.c b/tests/bsc-nat/bsc_data.c
index 0475523..8a06348 100644
--- a/tests/bsc-nat/bsc_data.c
+++ b/tests/bsc-nat/bsc_data.c
@@ -96,6 +96,28 @@
 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, 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[] = {
+0x00, 0x31, 0xfd, 0x06, 0x01, 0x13, 0x1e, 0x00,
+0x01, 0x2a, 0x01, 0x00, 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
+};
+
+
 /*
  * MGCP messages
  */
diff --git a/tests/bsc-nat/bsc_nat_test.c b/tests/bsc-nat/bsc_nat_test.c
index 504b691..d198424 100644
--- a/tests/bsc-nat/bsc_nat_test.c
+++ b/tests/bsc-nat/bsc_nat_test.c
@@ -27,10 +27,11 @@
 #include <openbsc/bsc_nat.h>
 #include <openbsc/bsc_nat_sccp.h>
 
-#include <osmocore/talloc.h>
+#include <osmocom/core/application.h>
+#include <osmocom/core/talloc.h>
 
 #include <osmocom/sccp/sccp.h>
-#include <osmocore/protocol/gsm_08_08.h>
+#include <osmocom/gsm/protocol/gsm_08_08.h>
 
 #include <stdio.h>
 
@@ -384,12 +385,9 @@
 
 static void test_paging(void)
 {
-	int lac;
 	struct bsc_nat *nat;
 	struct bsc_connection *con;
-	struct bsc_nat_parsed *parsed;
 	struct bsc_config *cfg;
-	struct msgb *msg;
 
 	fprintf(stderr, "Testing paging by lac.\n");
 
@@ -400,34 +398,20 @@
 	bsc_config_add_lac(cfg, 23);
 	con->authenticated = 1;
 	llist_add(&con->list_entry, &nat->bsc_connections);
-	msg = msgb_alloc(4096, "test");
-
-	/* Test completely bad input */
-	copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
-	if (bsc_nat_find_bsc(nat, msg, &lac) != 0) {
-		fprintf(stderr, "Should have not found anything.\n");
-		abort();
-	}
 
 	/* Test it by not finding it */
-	copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
-	parsed = bsc_nat_parse(msg);
-	if (bsc_nat_find_bsc(nat, msg, &lac) != 0) {
-		fprintf(stderr, "Should have not found aynthing.\n");
+	if (bsc_config_handles_lac(cfg, 8213) != 0) {
+		fprintf(stderr, "Should not be handled.\n");
 		abort();
 	}
-	talloc_free(parsed);
 
 	/* Test by finding it */
 	bsc_config_del_lac(cfg, 23);
 	bsc_config_add_lac(cfg, 8213);
-	copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
-	parsed = bsc_nat_parse(msg);
-	if (bsc_nat_find_bsc(nat, msg, &lac) != con) {
+	if (bsc_config_handles_lac(cfg, 8213) == 0) {
 		fprintf(stderr, "Should have found it.\n");
 		abort();
 	}
-	talloc_free(parsed);
 }
 
 static void test_mgcp_allocations(void)
@@ -506,7 +490,7 @@
 	if (msg->l2h[16] != 0 ||
 	    msg->l2h[17] != 0x1) {
 		fprintf(stderr, "Input is not as expected.. %s 0x%x\n",
-			hexdump(msg->l2h, msgb_l2len(msg)),
+			osmo_hexdump(msg->l2h, msgb_l2len(msg)),
 			msg->l2h[17]);
 		abort();
 	}
@@ -536,7 +520,7 @@
 	uint16_t cic = htons(timeslot & 0x1f);
 	if (memcmp(&cic, &msg->l2h[16], sizeof(cic)) != 0) {
 		fprintf(stderr, "Message was not patched properly\n");
-		fprintf(stderr, "data cic: 0x%x %s\n", cic, hexdump(msg->l2h, msgb_l2len(msg)));
+		fprintf(stderr, "data cic: 0x%x %s\n", cic, osmo_hexdump(msg->l2h, msgb_l2len(msg)));
 		abort();
 	}
 
@@ -761,15 +745,18 @@
 		nat_lst = bsc_nat_acc_lst_get(nat, "nat");
 		bsc_lst = bsc_nat_acc_lst_get(nat, "bsc");
 
-		bsc_parse_reg(nat_entry, &nat_entry->imsi_deny_re, &nat_entry->imsi_deny,
+		if (bsc_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);
-		bsc_parse_reg(bsc_entry, &bsc_entry->imsi_allow_re, &bsc_entry->imsi_allow,
+			      &cr_filter[i].nat_imsi_deny) != 0)
+			abort();
+		if (bsc_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);
-		bsc_parse_reg(bsc_entry, &bsc_entry->imsi_deny_re, &bsc_entry->imsi_deny,
+			      &cr_filter[i].bsc_imsi_allow) != 0)
+			abort();
+		if (bsc_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);
+			      &cr_filter[i].bsc_imsi_deny) != 0)
+			abort();
 
 		parsed = bsc_nat_parse(msg);
 		if (!parsed) {
@@ -858,8 +845,8 @@
 	struct bsc_nat *nat = bsc_nat_alloc();
 
 	/* a fake list */
-	struct msg_entries entries;
-	struct msg_entry entry;
+	struct osmo_config_list entries;
+	struct osmo_config_entry entry;
 
 	INIT_LLIST_HEAD(&entries.entry);
 	entry.mcc = "274";
@@ -867,7 +854,7 @@
 	entry.option = "^0([1-9])";
 	entry.text = "0049";
 	llist_add_tail(&entry.list, &entries.entry);
-	nat->num_rewr = &entries;
+	bsc_nat_num_rewr_entry_adapt(nat, &nat->num_rewr, &entries);
 
 	/* verify that nothing changed */
 	msgb_reset(msg);
@@ -878,7 +865,7 @@
 		abort();
 	}
 
-	out = bsc_nat_rewrite_setup(nat, msg, parsed, imsi);
+	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
 	if (msg != out) {
 		fprintf(stderr, "FAIL: The message should not have been changed\n");
 		abort();
@@ -904,7 +891,7 @@
 		abort();
 	}
 
-	out = bsc_nat_rewrite_setup(nat, msg, parsed, imsi);
+	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
 	if (!out) {
 		fprintf(stderr, "FAIL: A new message should be created.\n");
 		abort();
@@ -922,7 +909,7 @@
 
 	if (memcmp(cc_setup_national_patched, out->data, out->len) != 0) {
 		fprintf(stderr, "FAIL: Data is wrong.\n");
-		fprintf(stderr, "Data was: %s\n", hexdump(out->data, out->len));
+		fprintf(stderr, "Data was: %s\n", osmo_hexdump(out->data, out->len));
 		abort();
 	}
 
@@ -930,6 +917,7 @@
 
 	/* 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);
@@ -938,7 +926,7 @@
 		abort();
 	}
 
-	out = bsc_nat_rewrite_setup(nat, msg, parsed, imsi);
+	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
 	if (!out) {
 		fprintf(stderr, "FAIL: A new message should be created.\n");
 		abort();
@@ -956,7 +944,7 @@
 
 	if (memcmp(cc_setup_national_patched, out->data, out->len) != 0) {
 		fprintf(stderr, "FAIL: Data is wrong.\n");
-		fprintf(stderr, "Data was: %s\n", hexdump(out->data, out->len));
+		fprintf(stderr, "Data was: %s\n", osmo_hexdump(out->data, out->len));
 		abort();
 	}
 
@@ -964,6 +952,7 @@
 
 	/* 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);
@@ -972,7 +961,7 @@
 		abort();
 	}
 
-	out = bsc_nat_rewrite_setup(nat, msg, parsed, imsi);
+	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
 	if (out != msg) {
 		fprintf(stderr, "FAIL: The message should be unchanged.\n");
 		abort();
@@ -991,15 +980,61 @@
 	msgb_free(out);
 }
 
+static void test_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;
+	struct osmo_config_entry smsc_entry, dest_entry;
+
+	INIT_LLIST_HEAD(&smsc_entries.entry);
+	INIT_LLIST_HEAD(&dest_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);
+
+	bsc_nat_num_rewr_entry_adapt(nat, &nat->smsc_rewr, &smsc_entries);
+	bsc_nat_num_rewr_entry_adapt(nat, &nat->tpdest_match, &dest_entries);
+
+	copy_to_msg(msg, smsc_rewrite, ARRAY_SIZE(smsc_rewrite));
+	parsed = bsc_nat_parse(msg);
+	if (!parsed) {
+		fprintf(stderr, "FAIL: Could not parse SMS\n");
+		abort();
+	}
+
+	out = bsc_nat_rewrite_msg(nat, msg, parsed, imsi);
+	if (out == msg) {
+		fprintf(stderr, "FAIL: This should have changed.\n");
+		abort();
+	}
+
+	if (out->len != ARRAY_SIZE(smsc_rewrite_patched)) {
+		fprintf(stderr, "FAIL: The size should match.\n");
+		abort();
+	}
+
+	if (memcmp(out->data, smsc_rewrite_patched, out->len) != 0) {
+		fprintf(stderr, "FAIL: the data should be changed.\n");
+		abort();
+	}
+}
+
 int main(int argc, char **argv)
 {
-	struct log_target *stderr_target;
-
 	sccp_set_log_area(DSCCP);
-	log_init(&log_info);
-	stderr_target = log_target_create_stderr();
-	log_add_target(stderr_target);
-	log_set_all_filter(stderr_target, 1);
+	osmo_init_logging(&log_info);
 
 	test_filter();
 	test_contrack();
@@ -1011,6 +1046,7 @@
 	test_cr_filter();
 	test_dt_filter();
 	test_setup_rewrite();
+	test_smsc_rewrite();
 	test_mgcp_allocations();
 	return 0;
 }
diff --git a/tests/channel/Makefile.am b/tests/channel/Makefile.am
index bf709ff..df98f68 100644
--- a/tests/channel/Makefile.am
+++ b/tests/channel/Makefile.am
@@ -1,10 +1,10 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include
-AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS)
+AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS)
 
 noinst_PROGRAMS = channel_test
 
 channel_test_SOURCES = channel_test.c
-channel_test_LDADD = -ldl -ldbi $(LIBOSMOCORE_LIBS) \
+channel_test_LDADD = -ldl -ldbi $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) \
 	$(top_builddir)/src/libcommon/libcommon.a \
 	$(top_builddir)/src/libbsc/libbsc.a \
 	$(top_builddir)/src/libmsc/libmsc.a
diff --git a/tests/channel/Makefile.in b/tests/channel/Makefile.in
index de4b45e..94f35c0 100644
--- a/tests/channel/Makefile.in
+++ b/tests/channel/Makefile.in
@@ -36,7 +36,7 @@
 subdir = tests/channel
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -48,6 +48,7 @@
 channel_test_OBJECTS = $(am_channel_test_OBJECTS)
 am__DEPENDENCIES_1 =
 channel_test_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) \
 	$(top_builddir)/src/libcommon/libcommon.a \
 	$(top_builddir)/src/libbsc/libbsc.a \
 	$(top_builddir)/src/libmsc/libmsc.a
@@ -109,6 +110,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -178,9 +181,9 @@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include
-AM_CFLAGS = -Wall -ggdb3 $(LIBOSMOCORE_CFLAGS)
+AM_CFLAGS = -Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS)
 channel_test_SOURCES = channel_test.c
-channel_test_LDADD = -ldl -ldbi $(LIBOSMOCORE_LIBS) \
+channel_test_LDADD = -ldl -ldbi $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) \
 	$(top_builddir)/src/libcommon/libcommon.a \
 	$(top_builddir)/src/libbsc/libbsc.a \
 	$(top_builddir)/src/libmsc/libmsc.a
diff --git a/tests/channel/channel_test.c b/tests/channel/channel_test.c
index 4f3c593..1121dd5 100644
--- a/tests/channel/channel_test.c
+++ b/tests/channel/channel_test.c
@@ -22,7 +22,7 @@
 
 #include <assert.h>
 
-#include <osmocore/select.h>
+#include <osmocom/core/select.h>
 #include <openbsc/gsm_subscriber.h>
 #include <openbsc/abis_rsl.h>
 
@@ -56,7 +56,7 @@
 	network = gsm_network_init(1, 1, NULL);
 	if (!network)
 		exit(1);
-	bts = gsm_bts_alloc(network, GSM_BTS_TYPE_BS11, 0, 0);
+	bts = gsm_bts_alloc(network);
 	bts->location_area_code = 23;
 
 	/* Create a dummy subscriber */
@@ -68,7 +68,7 @@
 	subscr_get_channel(subscr, RSL_CHANNEED_TCH_F, subscr_cb, (void*)0x2342L);
 
 	while (1) {
-		bsc_select_main(0);
+		osmo_select_main(0);
 	}
 }
 
diff --git a/tests/db/Makefile.am b/tests/db/Makefile.am
index a4395ae..98fdccc 100644
--- a/tests/db/Makefile.am
+++ b/tests/db/Makefile.am
@@ -1,5 +1,5 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include
-AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(COVERAGE_CFLAGS)
+AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(COVERAGE_CFLAGS)
 AM_LDFLAGS = $(COVERAGE_LDFLAGS)
 
 noinst_PROGRAMS = db_test
@@ -11,5 +11,5 @@
 		$(top_builddir)/src/libabis/libabis.a \
 		$(top_builddir)/src/libtrau/libtrau.a \
 		$(top_builddir)/src/libcommon/libcommon.a \
-		$(LIBOSMOCORE_LIBS) -ldl -ldbi
+		$(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -ldl -ldbi
 
diff --git a/tests/db/Makefile.in b/tests/db/Makefile.in
index 5fd1244..c6fa38a 100644
--- a/tests/db/Makefile.in
+++ b/tests/db/Makefile.in
@@ -36,7 +36,7 @@
 subdir = tests/db
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -53,7 +53,7 @@
 	$(top_builddir)/src/libabis/libabis.a \
 	$(top_builddir)/src/libtrau/libtrau.a \
 	$(top_builddir)/src/libcommon/libcommon.a \
-	$(am__DEPENDENCIES_1)
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
@@ -112,6 +112,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -181,7 +183,7 @@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include
-AM_CFLAGS = -Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(COVERAGE_CFLAGS)
+AM_CFLAGS = -Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(COVERAGE_CFLAGS)
 AM_LDFLAGS = $(COVERAGE_LDFLAGS)
 db_test_SOURCES = db_test.c
 db_test_LDADD = $(top_builddir)/src/libbsc/libbsc.a \
@@ -190,7 +192,7 @@
 		$(top_builddir)/src/libabis/libabis.a \
 		$(top_builddir)/src/libtrau/libtrau.a \
 		$(top_builddir)/src/libcommon/libcommon.a \
-		$(LIBOSMOCORE_LIBS) -ldl -ldbi
+		$(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -ldl -ldbi
 
 all: all-am
 
diff --git a/tests/debug/Makefile.in b/tests/debug/Makefile.in
index c87c169..13dfba1 100644
--- a/tests/debug/Makefile.in
+++ b/tests/debug/Makefile.in
@@ -36,7 +36,7 @@
 subdir = tests/debug
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -107,6 +107,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
diff --git a/tests/debug/debug_test.c b/tests/debug/debug_test.c
index 6800021..fb5ce7a 100644
--- a/tests/debug/debug_test.c
+++ b/tests/debug/debug_test.c
@@ -25,7 +25,7 @@
 {
 	struct log_target *stderr_target;
 
-	log_init(&log_info);
+	log_init(&log_info, NULL);
 	stderr_target = log_target_create_stderr();
 	log_add_target(stderr_target);
 	log_set_all_filter(stderr_target, 1);
diff --git a/tests/gsm0408/Makefile.am b/tests/gsm0408/Makefile.am
index de6feb2..90ca05b 100644
--- a/tests/gsm0408/Makefile.am
+++ b/tests/gsm0408/Makefile.am
@@ -1,9 +1,9 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include
-AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS)
+AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS)
 noinst_PROGRAMS = gsm0408_test
 
 gsm0408_test_SOURCES = gsm0408_test.c
 gsm0408_test_LDADD =	$(top_builddir)/src/libbsc/libbsc.a \
 			$(top_builddir)/src/libmsc/libmsc.a \
 			$(top_builddir)/src/libbsc/libbsc.a \
-			$(LIBOSMOCORE_LIBS) -ldbi
+			$(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -ldbi
diff --git a/tests/gsm0408/Makefile.in b/tests/gsm0408/Makefile.in
index dc7d625..1916c9a 100644
--- a/tests/gsm0408/Makefile.in
+++ b/tests/gsm0408/Makefile.in
@@ -36,7 +36,7 @@
 subdir = tests/gsm0408
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -49,7 +49,8 @@
 am__DEPENDENCIES_1 =
 gsm0408_test_DEPENDENCIES = $(top_builddir)/src/libbsc/libbsc.a \
 	$(top_builddir)/src/libmsc/libmsc.a \
-	$(top_builddir)/src/libbsc/libbsc.a $(am__DEPENDENCIES_1)
+	$(top_builddir)/src/libbsc/libbsc.a $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
@@ -108,6 +109,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
@@ -177,12 +180,12 @@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include
-AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS)
+AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS)
 gsm0408_test_SOURCES = gsm0408_test.c
 gsm0408_test_LDADD = $(top_builddir)/src/libbsc/libbsc.a \
 			$(top_builddir)/src/libmsc/libmsc.a \
 			$(top_builddir)/src/libbsc/libbsc.a \
-			$(LIBOSMOCORE_LIBS) -ldbi
+			$(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -ldbi
 
 all: all-am
 
diff --git a/tests/gsm0408/gsm0408_test.c b/tests/gsm0408/gsm0408_test.c
index e8998c3..679ce66 100644
--- a/tests/gsm0408/gsm0408_test.c
+++ b/tests/gsm0408/gsm0408_test.c
@@ -70,8 +70,8 @@
 {
 	const char *imsi_odd  = "987654321098763";
 	const char *imsi_even = "9876543210987654";
-	const u_int32_t tmsi = 0xfabeacd0;
-	u_int8_t mi[128];
+	const uint32_t tmsi = 0xfabeacd0;
+	uint8_t mi[128];
 	unsigned int mi_len;
 	char mi_parsed[GSM48_MI_SIZE];
 
@@ -80,17 +80,17 @@
 	/* 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((u_int32_t)strtoul(mi_parsed, NULL, 10), ==, tmsi);
+	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", hexdump(mi, mi_len));
+	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", hexdump(mi, mi_len));
+	printf("hex: %s\n", osmo_hexdump(mi, mi_len));
 	COMPARE_STR(mi_parsed, imsi_even);
 }
 
diff --git a/tests/mgcp/Makefile.in b/tests/mgcp/Makefile.in
index a8df766..c9f26d1 100644
--- a/tests/mgcp/Makefile.in
+++ b/tests/mgcp/Makefile.in
@@ -36,7 +36,7 @@
 subdir = tests/mgcp
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -110,6 +110,8 @@
 LIBOBJS = @LIBOBJS@
 LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@
 LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@
+LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@
+LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@
 LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@
 LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@
 LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@
diff --git a/tests/mgcp/mgcp_test.c b/tests/mgcp/mgcp_test.c
index 4052377..b7273de 100644
--- a/tests/mgcp/mgcp_test.c
+++ b/tests/mgcp/mgcp_test.c
@@ -20,7 +20,8 @@
 #include <openbsc/mgcp.h>
 #include <openbsc/mgcp_internal.h>
 
-#include <osmocore/talloc.h>
+#include <osmocom/core/application.h>
+#include <osmocom/core/talloc.h>
 #include <string.h>
 
 static struct msgb *create_auep1()
@@ -74,11 +75,7 @@
 
 int main(int argc, char **argv)
 {
-	struct log_target *stderr_target;
-	log_init(&log_info);
-	stderr_target = log_target_create_stderr();
-	log_add_target(stderr_target);
-	log_set_all_filter(stderr_target, 1);
+	osmo_init_logging(&log_info);
 
 	test_auep();
 	return 0;