aboutsummaryrefslogtreecommitdiffstats
path: root/include/openbsc
diff options
context:
space:
mode:
Diffstat (limited to 'include/openbsc')
-rw-r--r--include/openbsc/Makefile.am17
-rw-r--r--include/openbsc/Makefile.in449
-rw-r--r--include/openbsc/abis_nm.h172
-rw-r--r--include/openbsc/abis_om2000.h78
-rw-r--r--include/openbsc/abis_rsl.h99
-rw-r--r--include/openbsc/auth.h17
-rw-r--r--include/openbsc/bsc_api.h37
-rw-r--r--include/openbsc/bsc_msc.h51
-rw-r--r--include/openbsc/bsc_nat.h355
-rw-r--r--include/openbsc/bsc_nat_sccp.h95
-rw-r--r--include/openbsc/bsc_rll.h19
-rw-r--r--include/openbsc/chan_alloc.h65
-rw-r--r--include/openbsc/crc24.h8
-rw-r--r--include/openbsc/db.h83
-rw-r--r--include/openbsc/debug.h70
-rw-r--r--include/openbsc/e1_input.h187
-rw-r--r--include/openbsc/gb_proxy.h39
-rw-r--r--include/openbsc/gprs_bssgp.h232
-rw-r--r--include/openbsc/gprs_gmm.h19
-rw-r--r--include/openbsc/gprs_llc.h162
-rw-r--r--include/openbsc/gprs_ns.h232
-rw-r--r--include/openbsc/gprs_ns_frgre.h6
-rw-r--r--include/openbsc/gprs_sgsn.h220
-rw-r--r--include/openbsc/gsm_04_08.h70
-rw-r--r--include/openbsc/gsm_04_08_gprs.h383
-rw-r--r--include/openbsc/gsm_04_11.h40
-rw-r--r--include/openbsc/gsm_04_80.h20
-rw-r--r--include/openbsc/gsm_data.h879
-rw-r--r--include/openbsc/gsm_subscriber.h107
-rw-r--r--include/openbsc/handover.h14
-rw-r--r--include/openbsc/ipaccess.h131
-rw-r--r--include/openbsc/meas_rep.h85
-rw-r--r--include/openbsc/mgcp.h194
-rw-r--r--include/openbsc/mgcp_internal.h154
-rw-r--r--include/openbsc/misdn.h27
-rw-r--r--include/openbsc/mncc.h172
-rw-r--r--include/openbsc/network_listen.h16
-rw-r--r--include/openbsc/openbscdefines.h34
-rw-r--r--include/openbsc/osmo_bsc.h43
-rw-r--r--include/openbsc/osmo_bsc_grace.h28
-rw-r--r--include/openbsc/osmo_bsc_rf.h35
-rw-r--r--include/openbsc/osmo_msc.h11
-rw-r--r--include/openbsc/osmo_msc_data.h76
-rw-r--r--include/openbsc/paging.h71
-rw-r--r--include/openbsc/rest_octets.h133
-rw-r--r--include/openbsc/rs232.h9
-rw-r--r--include/openbsc/rtp_proxy.h90
-rw-r--r--include/openbsc/sgsn.h65
-rw-r--r--include/openbsc/signal.h255
-rw-r--r--include/openbsc/silent_call.h12
-rw-r--r--include/openbsc/sms_queue.h17
-rw-r--r--include/openbsc/socket.h14
-rw-r--r--include/openbsc/subchan_demux.h101
-rw-r--r--include/openbsc/system_information.h45
-rw-r--r--include/openbsc/transaction.h75
-rw-r--r--include/openbsc/trau_frame.h64
-rw-r--r--include/openbsc/trau_mux.h48
-rw-r--r--include/openbsc/ussd.h10
-rw-r--r--include/openbsc/vty.h46
59 files changed, 6286 insertions, 0 deletions
diff --git a/include/openbsc/Makefile.am b/include/openbsc/Makefile.am
new file mode 100644
index 00000000..325d66d9
--- /dev/null
+++ b/include/openbsc/Makefile.am
@@ -0,0 +1,17 @@
+noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \
+ gsm_subscriber.h gsm_04_11.h debug.h signal.h \
+ misdn.h chan_alloc.h paging.h \
+ subchan_demux.h trau_frame.h e1_input.h trau_mux.h \
+ ipaccess.h rs232.h openbscdefines.h rtp_proxy.h \
+ bsc_rll.h mncc.h transaction.h ussd.h gsm_04_80.h \
+ silent_call.h mgcp.h meas_rep.h rest_octets.h \
+ system_information.h handover.h mgcp_internal.h \
+ vty.h socket.h \
+ crc24.h gprs_bssgp.h gprs_llc.h gprs_ns.h gprs_gmm.h \
+ 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
+
+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
new file mode 100644
index 00000000..faca5a31
--- /dev/null
+++ b/include/openbsc/Makefile.in
@@ -0,0 +1,449 @@
+# 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 = include/openbsc
+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__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 =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(openbscdir)"
+HEADERS = $(noinst_HEADERS) $(openbsc_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+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@
+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@
+noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \
+ gsm_subscriber.h gsm_04_11.h debug.h signal.h \
+ misdn.h chan_alloc.h paging.h \
+ subchan_demux.h trau_frame.h e1_input.h trau_mux.h \
+ ipaccess.h rs232.h openbscdefines.h rtp_proxy.h \
+ bsc_rll.h mncc.h transaction.h ussd.h gsm_04_80.h \
+ silent_call.h mgcp.h meas_rep.h rest_octets.h \
+ system_information.h handover.h mgcp_internal.h \
+ vty.h socket.h \
+ crc24.h gprs_bssgp.h gprs_llc.h gprs_ns.h gprs_gmm.h \
+ 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
+
+openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h
+openbscdir = $(includedir)/openbsc
+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 include/openbsc/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu include/openbsc/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):
+install-openbscHEADERS: $(openbsc_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(openbscdir)" || $(MKDIR_P) "$(DESTDIR)$(openbscdir)"
+ @list='$(openbsc_HEADERS)'; test -n "$(openbscdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(openbscdir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(openbscdir)" || exit $$?; \
+ done
+
+uninstall-openbscHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(openbsc_HEADERS)'; test -n "$(openbscdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(openbscdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(openbscdir)" && rm -f $$files
+
+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: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ 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: $(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
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(openbscdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+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 distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-openbscHEADERS
+
+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: uninstall-openbscHEADERS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ ctags 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-openbscHEADERS 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 tags \
+ uninstall uninstall-am uninstall-openbscHEADERS
+
+
+# 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/include/openbsc/abis_nm.h b/include/openbsc/abis_nm.h
new file mode 100644
index 00000000..c93db582
--- /dev/null
+++ b/include/openbsc/abis_nm.h
@@ -0,0 +1,172 @@
+/* GSM Network Management messages on the A-bis interface
+ * 3GPP TS 12.21 version 8.0.0 Release 1999 / ETSI TS 100 623 V8.0.0 */
+
+/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _NM_H
+#define _NM_H
+
+#include <sys/types.h>
+#include <osmocore/tlv.h>
+#include <osmocore/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;
+};
+
+/* The BCCH info from an ip.access test, in host byte order
+ * and already parsed... */
+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;
+ int16_t freq_err;
+ u_int16_t frame_offset;
+ u_int32_t frame_nr_offset;
+ u_int8_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];
+};
+
+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;
+
+struct abis_nm_cfg {
+ /* callback for unidirectional reports */
+ int (*report_cb)(struct msgb *,
+ struct abis_om_fom_hdr *);
+ /* callback for software activate requests from BTS */
+ int (*sw_act_req)(struct msgb *);
+};
+
+extern int abis_nm_rcvmsg(struct msgb *msg);
+
+int abis_nm_tlv_parse(struct tlv_parsed *tp, struct gsm_bts *bts, const u_int8_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_conn_terr_sign(struct gsm_bts_trx *trx,
+ u_int8_t e1_port, u_int8_t e1_timeslot, u_int8_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);
+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,
+ 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_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);
+
+/* 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);
+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);
+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_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_factory_logon(struct gsm_bts *bts, int on);
+int abis_nm_bs11_infield_logon(struct gsm_bts *bts, int on);
+int abis_nm_bs11_set_trx1_pw(struct gsm_bts *bts, const char *password);
+int abis_nm_bs11_set_pll_locked(struct gsm_bts *bts, int locked);
+int abis_nm_bs11_get_pll_mode(struct gsm_bts *bts);
+int abis_nm_bs11_set_pll(struct gsm_bts *bts, int value);
+int abis_nm_bs11_get_cclk(struct gsm_bts *bts);
+int abis_nm_bs11_get_state(struct gsm_bts *bts);
+int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname,
+ u_int8_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_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 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_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);
+
+/* 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);
+
+void abis_nm_clear_queue(struct gsm_bts *bts);
+
+
+#endif /* _NM_H */
diff --git a/include/openbsc/abis_om2000.h b/include/openbsc/abis_om2000.h
new file mode 100644
index 00000000..e4f19cf9
--- /dev/null
+++ b/include/openbsc/abis_om2000.h
@@ -0,0 +1,78 @@
+#ifndef OPENBSC_ABIS_OM2K_H
+#define OPENBSC_ABIS_OM2K_H
+/* Ericsson RBS 2xxx GSM O&M (OM2000) messages on the A-bis interface
+ * implemented based on protocol trace analysis, no formal documentation */
+
+/* (C) 2010-2011 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+enum abis_om2k_mo_cls {
+ OM2K_MO_CLS_TRXC = 0x01,
+ OM2K_MO_CLS_TS = 0x03,
+ OM2K_MO_CLS_TF = 0x04,
+ OM2K_MO_CLS_IS = 0x05,
+ OM2K_MO_CLS_CON = 0x06,
+ OM2K_MO_CLS_DP = 0x07,
+ OM2K_MO_CLS_CF = 0x0a,
+ OM2K_MO_CLS_TX = 0x0b,
+ OM2K_MO_CLS_RX = 0x0c,
+};
+
+struct abis_om2k_mo {
+ uint8_t class;
+ uint8_t bts;
+ uint8_t assoc_so;
+ uint8_t inst;
+} __attribute__ ((packed));
+
+struct om2k_is_conn_grp {
+ uint16_t icp1;
+ uint16_t icp2;
+ uint8_t cont_idx;
+} __attribute__ ((packed));
+
+extern const struct value_string om2k_mo_class_short_vals[];
+
+int abis_om2k_rcvmsg(struct msgb *msg);
+
+extern const struct abis_om2k_mo om2k_mo_cf;
+
+int abis_om2k_tx_reset_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
+int abis_om2k_tx_start_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
+int abis_om2k_tx_status_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
+int abis_om2k_tx_connect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
+int abis_om2k_tx_disconnect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
+int abis_om2k_tx_enable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
+int abis_om2k_tx_disable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
+int abis_om2k_tx_test_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
+int abis_om2k_tx_op_info(struct gsm_bts *bts, const struct abis_om2k_mo *mo,
+ uint8_t operational);
+int abis_om2k_tx_is_conf_req(struct gsm_bts *bts, struct om2k_is_conn_grp *cg,
+ unsigned int num_cg);
+int abis_om2k_tx_tf_conf_req(struct gsm_bts *bts);
+int abis_om2k_tx_rx_conf_req(struct gsm_bts_trx *trx);
+int abis_om2k_tx_tx_conf_req(struct gsm_bts_trx *trx);
+int abis_om2k_tx_ts_conf_req(struct gsm_bts_trx_ts *ts);
+
+int abis_om2k_vty_init(void);
+
+struct vty;
+void abis_om2k_config_write_bts(struct vty *vty, struct gsm_bts *bts);
+
+#endif /* OPENBCS_ABIS_OM2K_H */
diff --git a/include/openbsc/abis_rsl.h b/include/openbsc/abis_rsl.h
new file mode 100644
index 00000000..295b01fd
--- /dev/null
+++ b/include/openbsc/abis_rsl.h
@@ -0,0 +1,99 @@
+/* GSM Radio Signalling Link messages on the A-bis interface
+ * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
+
+/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _RSL_H
+#define _RSL_H
+
+#include <osmocore/protocol/gsm_08_58.h>
+
+#include <osmocore/msgb.h>
+
+struct gsm_bts;
+struct gsm_lchan;
+struct gsm_subscriber;
+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,
+ 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);
+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_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);
+
+/* 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_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);
+
+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);
+
+/* 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_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db);
+int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm);
+
+/* SMSCB functionality */
+int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
+ uint8_t cb_command, const uint8_t *data, int len);
+
+#endif /* RSL_MT_H */
+
diff --git a/include/openbsc/auth.h b/include/openbsc/auth.h
new file mode 100644
index 00000000..2364fb3d
--- /dev/null
+++ b/include/openbsc/auth.h
@@ -0,0 +1,17 @@
+#ifndef _AUTH_H
+#define _AUTH_H
+
+struct gsm_auth_tuple;
+struct gsm_subscriber;
+
+enum auth_action {
+ AUTH_NOT_AVAIL = 0, /* No auth tuple available */
+ AUTH_DO_AUTH_THAN_CIPH = 1, /* Firsth authenticate, then cipher */
+ AUTH_DO_CIPH = 2, /* Only ciphering */
+ AUTH_DO_AUTH = 3, /* Only authentication, no ciphering */
+};
+
+int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
+ struct gsm_subscriber *subscr, int key_seq);
+
+#endif /* _AUTH_H */
diff --git a/include/openbsc/bsc_api.h b/include/openbsc/bsc_api.h
new file mode 100644
index 00000000..36ec3705
--- /dev/null
+++ b/include/openbsc/bsc_api.h
@@ -0,0 +1,37 @@
+/* GSM 08.08 like API for OpenBSC */
+
+#ifndef OPENBSC_BSC_API_H
+#define OPENBSC_BSC_API_H
+
+#include "gsm_data.h"
+
+#define BSC_API_CONN_POL_ACCEPT 0
+#define BSC_API_CONN_POL_REJECT 1
+
+struct bsc_api {
+ void (*sapi_n_reject)(struct gsm_subscriber_connection *conn, int dlci);
+ void (*cipher_mode_compl)(struct gsm_subscriber_connection *conn,
+ struct msgb *msg, uint8_t chosen_encr);
+ int (*compl_l3)(struct gsm_subscriber_connection *conn,
+ struct msgb *msg, uint16_t chosen_channel);
+ void (*dtap)(struct gsm_subscriber_connection *conn, uint8_t link_id,
+ struct msgb *msg);
+ void (*assign_compl)(struct gsm_subscriber_connection *conn,
+ uint8_t rr_cause, uint8_t chosen_channel,
+ uint8_t encr_alg_id, uint8_t speech_mode);
+ void (*assign_fail)(struct gsm_subscriber_connection *conn,
+ uint8_t cause, uint8_t *rr_cause);
+ int (*clear_request)(struct gsm_subscriber_connection *conn,
+ uint32_t cause);
+};
+
+int bsc_api_init(struct gsm_network *network, struct bsc_api *api);
+int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, int link_id, int allow_sach);
+int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, int full_rate);
+int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,
+ const uint8_t *key, int len, int include_imeisv);
+int gsm0808_page(struct gsm_bts *bts, unsigned int page_group,
+ unsigned int mi_len, uint8_t *mi, int chan_type);
+int gsm0808_clear(struct gsm_subscriber_connection *conn);
+
+#endif
diff --git a/include/openbsc/bsc_msc.h b/include/openbsc/bsc_msc.h
new file mode 100644
index 00000000..d06ae051
--- /dev/null
+++ b/include/openbsc/bsc_msc.h
@@ -0,0 +1,51 @@
+/* Routines to talk to the MSC using the IPA Protocol */
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef BSC_MSC_H
+#define BSC_MSC_H
+
+#include <osmocore/write_queue.h>
+#include <osmocore/timer.h>
+
+struct bsc_msc_connection {
+ struct write_queue write_queue;
+ int is_connected;
+ int is_authenticated;
+ int first_contact;
+ const char *ip;
+ int port;
+ int prio;
+
+ void (*connection_loss) (struct bsc_msc_connection *);
+ void (*connected) (struct bsc_msc_connection *);
+ struct timer_list reconnect_timer;
+ struct timer_list timeout_timer;
+};
+
+struct bsc_msc_connection *bsc_msc_create(const char *ip, int port, int prio);
+int bsc_msc_connect(struct bsc_msc_connection *);
+void bsc_msc_schedule_connect(struct bsc_msc_connection *);
+
+void bsc_msc_lost(struct bsc_msc_connection *);
+
+struct msgb *bsc_msc_id_get_resp(const char *token);
+
+#endif
diff --git a/include/openbsc/bsc_nat.h b/include/openbsc/bsc_nat.h
new file mode 100644
index 00000000..f74cae2a
--- /dev/null
+++ b/include/openbsc/bsc_nat.h
@@ -0,0 +1,355 @@
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef BSC_NAT_H
+#define BSC_NAT_H
+
+#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 <regex.h>
+
+#define DIR_BSC 1
+#define DIR_MSC 2
+
+struct sccp_source_reference;
+struct sccp_connections;
+struct bsc_nat_parsed;
+struct bsc_nat;
+struct bsc_nat_ussd_con;
+
+enum {
+ NAT_CON_TYPE_NONE,
+ NAT_CON_TYPE_LU,
+ NAT_CON_TYPE_CM_SERV_REQ,
+ NAT_CON_TYPE_PAG_RESP,
+ NAT_CON_TYPE_SSA,
+ NAT_CON_TYPE_LOCAL_REJECT,
+ NAT_CON_TYPE_OTHER,
+};
+
+/*
+ * Per BSC data structure
+ */
+struct bsc_connection {
+ struct llist_head list_entry;
+
+ /* do we know anything about this BSC? */
+ int authenticated;
+
+ /* the fd we use to communicate */
+ struct write_queue write_queue;
+
+ /* the BSS associated */
+ struct bsc_config *cfg;
+
+ /* a timeout node */
+ struct timer_list id_timeout;
+
+ /* pong timeout */
+ struct timer_list ping_timeout;
+ struct timer_list pong_timeout;
+
+ /* mgcp related code */
+ char *_endpoint_status;
+ int number_multiplexes;
+ int max_endpoints;
+ int last_endpoint;
+
+ /* a back pointer */
+ struct bsc_nat *nat;
+};
+
+/**
+ * Stats per BSC
+ */
+struct bsc_config_stats {
+ struct rate_ctr_group *ctrg;
+};
+
+enum bsc_cfg_ctr {
+ BCFG_CTR_SCCP_CONN,
+ BCFG_CTR_SCCP_CALLS,
+ BCFG_CTR_NET_RECONN,
+ BCFG_CTR_DROPPED_SCCP,
+ BCFG_CTR_DROPPED_CALLS,
+ BCFG_CTR_REJECTED_CR,
+ BCFG_CTR_REJECTED_MSG,
+ BCFG_CTR_ILL_PACKET,
+ BCFG_CTR_CON_TYPE_LU,
+ BCFG_CTR_CON_CMSERV_RQ,
+ BCFG_CTR_CON_PAG_RESP,
+ BCFG_CTR_CON_SSA,
+ BCFG_CTR_CON_OTHER,
+};
+
+/**
+ * One BSC entry in the config
+ */
+struct bsc_config {
+ struct llist_head entry;
+
+ char *token;
+ int nr;
+
+ char *description;
+
+ /* imsi white and blacklist */
+ char *acc_lst_name;
+
+ int forbid_paging;
+
+ /* audio handling */
+ int max_endpoints;
+
+ /* backpointer */
+ struct bsc_nat *nat;
+
+ struct bsc_config_stats stats;
+
+ struct llist_head lac_list;
+};
+
+struct bsc_lac_entry {
+ struct llist_head entry;
+ uint16_t lac;
+};
+
+/**
+ * BSCs point of view of endpoints
+ */
+struct bsc_endpoint {
+ /* the operation that is carried out */
+ int transaction_state;
+ /* the pending transaction id */
+ char *transaction_id;
+ /* the bsc we are talking to */
+ struct bsc_connection *bsc;
+};
+
+/**
+ * Statistic for the nat.
+ */
+struct bsc_nat_statistics {
+ struct {
+ struct counter *conn;
+ struct counter *calls;
+ } sccp;
+
+ struct {
+ struct counter *reconn;
+ struct counter *auth_fail;
+ } bsc;
+
+ struct {
+ struct counter *reconn;
+ } msc;
+
+ struct {
+ struct counter *reconn;
+ } ussd;
+};
+
+enum bsc_nat_acc_ctr {
+ ACC_LIST_BSC_FILTER,
+ ACC_LIST_NAT_FILTER,
+};
+
+struct bsc_nat_acc_lst {
+ struct llist_head list;
+
+ /* counter */
+ struct rate_ctr_group *stats;
+
+ /* the name of the list */
+ const char *name;
+ struct llist_head fltr_list;
+};
+
+struct bsc_nat_acc_lst_entry {
+ struct llist_head list;
+
+ /* the filter */
+ char *imsi_allow;
+ regex_t imsi_allow_re;
+ char *imsi_deny;
+ regex_t imsi_deny_re;
+};
+
+/**
+ * the structure of the "nat" network
+ */
+struct bsc_nat {
+ /* active SCCP connections that need patching */
+ struct llist_head sccp_connections;
+
+ /* active BSC connections that need patching */
+ struct llist_head bsc_connections;
+
+ /* access lists */
+ struct llist_head access_lists;
+
+ /* known BSC's */
+ struct llist_head bsc_configs;
+ int num_bsc;
+ int bsc_ip_dscp;
+
+ /* MGCP config */
+ struct mgcp_config *mgcp_cfg;
+ uint8_t mgcp_msg[4096];
+ int mgcp_length;
+
+ /* msc things */
+ char *msc_ip;
+ int msc_port;
+ struct bsc_msc_connection *msc_con;
+ char *token;
+
+ /* timeouts */
+ int auth_timeout;
+ int ping_timeout;
+ int pong_timeout;
+
+ struct bsc_endpoint *bsc_endpoints;
+
+ /* filter */
+ char *acc_lst_name;
+
+ /* number rewriting */
+ char *num_rewr_name;
+ struct msg_entries *num_rewr;
+
+ /* USSD messages we want to match */
+ char *ussd_lst_name;
+ char *ussd_query;
+ char *ussd_token;
+ char *ussd_local;
+ struct bsc_fd ussd_listen;
+ struct bsc_nat_ussd_con *ussd_con;
+
+ /* statistics */
+ struct bsc_nat_statistics stats;
+};
+
+/* 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);
+void bsc_config_free(struct bsc_config *);
+void bsc_config_add_lac(struct bsc_config *cfg, int lac);
+void bsc_config_del_lac(struct bsc_config *cfg, int lac);
+int bsc_config_handles_lac(struct bsc_config *cfg, int lac);
+
+struct bsc_nat *bsc_nat_alloc(void);
+struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat);
+void bsc_nat_set_msc_ip(struct bsc_nat *bsc, const char *ip);
+
+void sccp_connection_destroy(struct sccp_connections *);
+void bsc_close_connection(struct bsc_connection *);
+
+const char *bsc_con_type_to_string(int type);
+
+/**
+ * parse the given message into the above structure
+ */
+struct bsc_nat_parsed *bsc_nat_parse(struct msgb *msg);
+
+/**
+ * filter based on IP Access header in both directions
+ */
+int bsc_nat_filter_ipa(int direction, struct msgb *msg, struct bsc_nat_parsed *parsed);
+int bsc_nat_vty_init(struct bsc_nat *nat);
+struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg, int *_lac);
+
+/**
+ * Content filtering.
+ */
+int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg,
+ struct bsc_nat_parsed *, int *con_type, char **imsi);
+int bsc_nat_filter_dt(struct bsc_connection *bsc, struct msgb *msg,
+ struct sccp_connections *con, struct bsc_nat_parsed *parsed);
+
+/**
+ * SCCP patching and handling
+ */
+struct sccp_connections *create_sccp_src_ref(struct bsc_connection *bsc, struct bsc_nat_parsed *parsed);
+int update_sccp_src_ref(struct sccp_connections *sccp, struct bsc_nat_parsed *parsed);
+void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed);
+struct sccp_connections *patch_sccp_src_ref_to_bsc(struct msgb *, struct bsc_nat_parsed *, struct bsc_nat *);
+struct sccp_connections *patch_sccp_src_ref_to_msc(struct msgb *, struct bsc_nat_parsed *, struct bsc_connection *);
+struct sccp_connections *bsc_nat_find_con_by_bsc(struct bsc_nat *, struct sccp_source_reference *);
+
+/**
+ * MGCP/Audio handling
+ */
+int bsc_mgcp_nr_multiplexes(int max_endpoints);
+int bsc_write_mgcp(struct bsc_connection *bsc, const uint8_t *data, unsigned int length);
+int bsc_mgcp_assign_patch(struct sccp_connections *, struct msgb *msg);
+void bsc_mgcp_init(struct sccp_connections *);
+void bsc_mgcp_dlcx(struct sccp_connections *);
+void bsc_mgcp_free_endpoints(struct bsc_nat *nat);
+int bsc_mgcp_nat_init(struct bsc_nat *nat);
+
+struct sccp_connections *bsc_mgcp_find_con(struct bsc_nat *, int endpoint_number);
+struct msgb *bsc_mgcp_rewrite(char *input, int length, int endp, const char *ip, int port);
+void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg);
+
+void bsc_mgcp_clear_endpoints_for(struct bsc_connection *bsc);
+int bsc_mgcp_parse_response(const char *str, int *code, char transaction[60]);
+uint32_t bsc_mgcp_extract_ci(const char *resp);
+
+
+int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int id);
+int bsc_do_write(struct 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);
+
+/* IMSI allow/deny handling */
+void bsc_parse_reg(void *ctx, regex_t *reg, char **imsi, int argc, const char **argv);
+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);
+
+struct bsc_nat_acc_lst_entry *bsc_nat_acc_lst_entry_create(struct bsc_nat_acc_lst *);
+int bsc_nat_lst_check_allow(struct bsc_nat_acc_lst *lst, const char *imsi);
+
+int bsc_nat_msc_is_connected(struct bsc_nat *nat);
+
+int bsc_conn_type_to_ctr(struct sccp_connections *conn);
+
+struct gsm48_hdr *bsc_unpack_dtap(struct bsc_nat_parsed *parsed, struct msgb *msg, uint32_t *len);
+
+/** USSD filtering */
+int bsc_ussd_init(struct bsc_nat *nat);
+int bsc_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);
+
+#endif
diff --git a/include/openbsc/bsc_nat_sccp.h b/include/openbsc/bsc_nat_sccp.h
new file mode 100644
index 00000000..0ade668c
--- /dev/null
+++ b/include/openbsc/bsc_nat_sccp.h
@@ -0,0 +1,95 @@
+/* NAT utilities using SCCP types */
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef BSC_NAT_SCCP_H
+#define BSC_NAT_SCCP_H
+
+#include <sys/types.h>
+#include <osmocom/sccp/sccp_types.h>
+
+/*
+ * For the NAT we will need to analyze and later patch
+ * the received message. This would require us to parse
+ * the IPA and SCCP header twice. Instead of doing this
+ * we will have one analyze structure and have the patching
+ * and filter operate on the same structure.
+ */
+struct bsc_nat_parsed {
+ /* ip access prototype */
+ int ipa_proto;
+
+ /* source local reference */
+ struct sccp_source_reference *src_local_ref;
+
+ /* destination local reference */
+ struct sccp_source_reference *dest_local_ref;
+
+ /* called ssn number */
+ int called_ssn;
+
+ /* calling ssn number */
+ int calling_ssn;
+
+ /* sccp message type */
+ int sccp_type;
+
+ /* bssap type, e.g. 0 for BSS Management */
+ int bssap;
+
+ /* the gsm0808 message type */
+ int gsm_type;
+};
+
+/*
+ * Per SCCP source local reference patch table. It needs to
+ * be updated on new SCCP connections, connection confirm and reject,
+ * and on the loss of the BSC connection.
+ */
+struct sccp_connections {
+ struct llist_head list_entry;
+
+ struct bsc_connection *bsc;
+ struct bsc_msc_connection *msc_con;
+
+ struct sccp_source_reference real_ref;
+ struct sccp_source_reference patched_ref;
+ struct sccp_source_reference remote_ref;
+ int has_remote_ref;
+
+ /* status */
+ int con_type;
+ int con_local;
+ int imsi_checked;
+ char *imsi;
+
+ /*
+ * audio handling. Remember if we have ever send a CRCX,
+ * remember the endpoint used by the MSC and BSC.
+ */
+ int msc_endp;
+ int bsc_endp;
+
+ /* timeout handling */
+ struct timespec creation_time;
+};
+
+
+#endif
diff --git a/include/openbsc/bsc_rll.h b/include/openbsc/bsc_rll.h
new file mode 100644
index 00000000..b2898d1b
--- /dev/null
+++ b/include/openbsc/bsc_rll.h
@@ -0,0 +1,19 @@
+#ifndef _BSC_RLL_H
+#define _BSC_RLL_H
+
+#include <openbsc/gsm_data.h>
+
+enum bsc_rllr_ind {
+ BSC_RLLR_IND_EST_CONF,
+ BSC_RLLR_IND_REL_IND,
+ BSC_RLLR_IND_ERR_IND,
+ BSC_RLLR_IND_TIMEOUT,
+};
+
+int rll_establish(struct gsm_lchan *lchan, u_int8_t link_id,
+ void (*cb)(struct gsm_lchan *, u_int8_t, void *,
+ enum bsc_rllr_ind),
+ void *data);
+void rll_indication(struct gsm_lchan *lchan, u_int8_t link_id, u_int8_t type);
+
+#endif /* _BSC_RLL_H */
diff --git a/include/openbsc/chan_alloc.h b/include/openbsc/chan_alloc.h
new file mode 100644
index 00000000..5eda312a
--- /dev/null
+++ b/include/openbsc/chan_alloc.h
@@ -0,0 +1,65 @@
+/* Management functions to allocate/release struct gsm_lchan */
+/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#ifndef _CHAN_ALLOC_H
+#define _CHAN_ALLOC_H
+
+#include "gsm_data.h"
+
+struct gsm_subscriber_connection;
+
+/* Special allocator for C0 of BTS */
+struct gsm_bts_trx_ts *ts_c0_alloc(struct gsm_bts *bts,
+ enum gsm_phys_chan_config pchan);
+
+/* Regular physical channel allocator */
+struct gsm_bts_trx_ts *ts_alloc(struct gsm_bts *bts,
+ enum gsm_phys_chan_config pchan);
+
+/* Regular physical channel (TS) */
+void ts_free(struct gsm_bts_trx_ts *ts);
+
+/* Find an allocated channel for a specified subscriber */
+struct gsm_subscriber_connection *connection_for_subscr(struct gsm_subscriber *subscr);
+
+/* Allocate a logical channel (SDCCH, TCH, ...) */
+struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type, int allow_bigger);
+
+/* Free a logical channel (SDCCH, TCH, ...) */
+void lchan_free(struct gsm_lchan *lchan);
+void lchan_reset(struct gsm_lchan *lchan);
+
+/* Release the given lchan */
+int lchan_release(struct gsm_lchan *lchan, int sach_deact, int reason);
+
+struct load_counter {
+ unsigned int total;
+ unsigned int used;
+};
+
+struct pchan_load {
+ struct load_counter pchan[GSM_PCHAN_UNKNOWN];
+};
+
+void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts);
+void network_chan_load(struct pchan_load *pl, struct gsm_network *net);
+
+int trx_is_usable(struct gsm_bts_trx *trx);
+
+#endif /* _CHAN_ALLOC_H */
diff --git a/include/openbsc/crc24.h b/include/openbsc/crc24.h
new file mode 100644
index 00000000..358fcb58
--- /dev/null
+++ b/include/openbsc/crc24.h
@@ -0,0 +1,8 @@
+#ifndef _CRC24_H
+#define _CRC24_H
+
+#define INIT_CRC24 0xffffff
+
+u_int32_t crc24_calc(u_int32_t fcs, u_int8_t *cp, unsigned int len);
+
+#endif
diff --git a/include/openbsc/db.h b/include/openbsc/db.h
new file mode 100644
index 00000000..a939b0d6
--- /dev/null
+++ b/include/openbsc/db.h
@@ -0,0 +1,83 @@
+/* (C) 2008 by Jan Luebbe <jluebbe@debian.org>
+ * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _DB_H
+#define _DB_H
+
+#include <sys/types.h>
+
+struct gsm_equipment;
+struct gsm_network;
+struct gsm_auth_info;
+struct gsm_auth_tuple;
+struct gsm_sms;
+struct gsm_subscriber;
+
+enum gsm_subscriber_field;
+
+/* one time initialisation */
+int db_init(const char *name);
+int db_prepare();
+int db_fini();
+
+/* subscriber management */
+struct gsm_subscriber *db_create_subscriber(struct gsm_network *net,
+ char *imsi);
+struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
+ enum gsm_subscriber_field field,
+ const char *subscr);
+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_assoc_imei(struct gsm_subscriber *subscriber, char *imei);
+int db_sync_equipment(struct gsm_equipment *equip);
+int db_subscriber_update(struct gsm_subscriber *subscriber);
+
+/* auth info */
+int db_get_authinfo_for_subscr(struct gsm_auth_info *ainfo,
+ struct gsm_subscriber *subscr);
+int db_sync_authinfo_for_subscr(struct gsm_auth_info *ainfo,
+ struct gsm_subscriber *subscr);
+int db_get_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple,
+ struct gsm_subscriber *subscr);
+int db_sync_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple,
+ struct gsm_subscriber *subscr);
+
+/* SMS store-and-forward */
+int db_sms_store(struct gsm_sms *sms);
+struct gsm_sms *db_sms_get(struct gsm_network *net, unsigned long long id);
+struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, unsigned long long min_id);
+struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, unsigned long long min_subscr_id, unsigned int failed);
+struct gsm_sms *db_sms_get_unsent_for_subscr(struct gsm_subscriber *subscr);
+int db_sms_mark_sent(struct gsm_sms *sms);
+int db_sms_inc_deliver_attempts(struct gsm_sms *sms);
+
+/* 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);
+
+/* Statistics counter storage */
+struct counter;
+int db_store_counter(struct counter *ctr);
+struct rate_ctr_group;
+int db_store_rate_ctr_group(struct rate_ctr_group *ctrg);
+
+#endif /* _DB_H */
diff --git a/include/openbsc/debug.h b/include/openbsc/debug.h
new file mode 100644
index 00000000..eb290e41
--- /dev/null
+++ b/include/openbsc/debug.h
@@ -0,0 +1,70 @@
+#ifndef _DEBUG_H
+#define _DEBUG_H
+
+#include <stdio.h>
+#include <osmocore/linuxlist.h>
+
+#define DEBUG
+#include <osmocore/logging.h>
+
+/* Debug Areas of the code */
+enum {
+ DRLL,
+ DCC,
+ DMM,
+ DRR,
+ DRSL,
+ DNM,
+ DMNCC,
+ DSMS,
+ DPAG,
+ DMEAS,
+ DMI,
+ DMIB,
+ DMUX,
+ DINP,
+ DSCCP,
+ DMSC,
+ DMGCP,
+ DHO,
+ DDB,
+ DREF,
+ DGPRS,
+ DNS,
+ DBSSGP,
+ DLLC,
+ DSNDCP,
+ DNAT,
+ Debug_LastEntry,
+};
+
+/* context */
+#define BSC_CTX_LCHAN 0
+#define BSC_CTX_SUBSCR 1
+#define BSC_CTX_BTS 2
+#define BSC_CTX_SCCP 3
+#define BSC_CTX_NSVC 4
+#define BSC_CTX_BVC 5
+
+/* target */
+
+enum {
+ //DEBUG_FILTER_ALL = 1 << 0,
+ LOG_FILTER_IMSI = 1 << 1,
+ LOG_FILTER_NSVC = 1 << 2,
+ LOG_FILTER_BVC = 1 << 3,
+};
+
+/* we don't need a header dependency for this... */
+struct gprs_nsvc;
+struct bssgp_bvc_ctx;
+
+void log_set_imsi_filter(struct log_target *target, const char *imsi);
+void log_set_nsvc_filter(struct log_target *target,
+ struct gprs_nsvc *nsvc);
+void log_set_bvc_filter(struct log_target *target,
+ struct bssgp_bvc_ctx *bctx);
+
+extern const struct log_info log_info;
+
+#endif /* _DEBUG_H */
diff --git a/include/openbsc/e1_input.h b/include/openbsc/e1_input.h
new file mode 100644
index 00000000..3c8af387
--- /dev/null
+++ b/include/openbsc/e1_input.h
@@ -0,0 +1,187 @@
+#ifndef _E1_INPUT_H
+#define _E1_INPUT_H
+
+#include <stdlib.h>
+#include <netinet/in.h>
+
+#include <osmocore/linuxlist.h>
+#include <openbsc/gsm_data.h>
+#include <osmocore/msgb.h>
+#include <osmocore/select.h>
+#include <openbsc/subchan_demux.h>
+
+#define NUM_E1_TS 32
+
+enum e1inp_sign_type {
+ E1INP_SIGN_NONE,
+ E1INP_SIGN_OML,
+ E1INP_SIGN_RSL,
+};
+const char *e1inp_signtype_name(enum e1inp_sign_type tp);
+
+struct e1inp_ts;
+
+struct e1inp_sign_link {
+ /* list of signalling links */
+ struct llist_head list;
+
+ /* to which timeslot do we belong? */
+ struct e1inp_ts *ts;
+
+ enum e1inp_sign_type type;
+
+ /* trx for msg->trx of received msgs */
+ struct gsm_bts_trx *trx;
+
+ /* msgb queue of to-be-transmitted msgs */
+ struct llist_head tx_list;
+
+ /* SAPI and TEI on the E1 TS */
+ u_int8_t sapi;
+ u_int8_t tei;
+
+ union {
+ struct {
+ u_int8_t channel;
+ } misdn;
+ } driver;
+};
+
+enum e1inp_ts_type {
+ E1INP_TS_TYPE_NONE,
+ E1INP_TS_TYPE_SIGN,
+ E1INP_TS_TYPE_TRAU,
+};
+const char *e1inp_tstype_name(enum e1inp_ts_type tp);
+
+/* A timeslot in the E1 interface */
+struct e1inp_ts {
+ enum e1inp_ts_type type;
+ int num;
+
+ /* to which line do we belong ? */
+ struct e1inp_line *line;
+
+ union {
+ struct {
+ /* list of all signalling links on this TS */
+ struct llist_head sign_links;
+ /* delay for the queue */
+ int delay;
+ /* timer when to dequeue next frame */
+ struct timer_list tx_timer;
+ } sign;
+ struct {
+ /* subchannel demuxer for frames from E1 */
+ struct subch_demux demux;
+ /* subchannel muxer for frames to E1 */
+ struct subch_mux mux;
+ } trau;
+ };
+ union {
+ struct {
+ /* mISDN driver has one fd for each ts */
+ struct bsc_fd fd;
+ } misdn;
+ struct {
+ /* ip.access driver has one fd for each ts */
+ struct bsc_fd fd;
+ } ipaccess;
+ struct {
+ /* DAHDI driver has one fd for each ts */
+ struct bsc_fd fd;
+ struct lapd_instance *lapd;
+ } dahdi;
+ } driver;
+};
+
+struct e1inp_driver {
+ struct llist_head list;
+ const char *name;
+ int (*want_write)(struct e1inp_ts *ts);
+ int (*line_update)(struct e1inp_line *line);
+ int default_delay;
+};
+
+struct e1inp_line {
+ struct llist_head list;
+ unsigned int num;
+ const char *name;
+
+ /* array of timestlots */
+ struct e1inp_ts ts[NUM_E1_TS];
+
+ struct e1inp_driver *driver;
+ void *driver_data;
+};
+
+/* register a driver with the E1 core */
+int e1inp_driver_register(struct e1inp_driver *drv);
+
+/* fine a previously registered driver */
+struct e1inp_driver *e1inp_driver_find(const char *name);
+
+/* register a line with the E1 core */
+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);
+
+/* create a line in the E1 input core */
+struct e1inp_line *e1inp_line_create(u_int8_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);
+
+/* 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);
+
+/* configure and initialize one e1inp_ts */
+int e1inp_ts_config(struct e1inp_ts *ts, struct e1inp_line *line,
+ enum e1inp_ts_type type);
+
+/* Call from the Stack: configuration of this TS has changed */
+int e1inp_update_ts(struct e1inp_ts *ts);
+
+/* 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);
+
+/* 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);
+
+/* 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);
+
+void e1inp_sign_link_destroy(struct e1inp_sign_link *link);
+int e1inp_line_update(struct e1inp_line *line);
+
+/* e1_config.c */
+int e1_reconfig_ts(struct gsm_bts_trx_ts *ts);
+int e1_reconfig_trx(struct gsm_bts_trx *trx);
+int e1_reconfig_bts(struct gsm_bts *bts);
+
+int ia_config_connect(struct gsm_bts *bts, struct sockaddr_in *sin);
+int ipaccess_setup(struct gsm_network *gsmnet);
+
+extern struct llist_head e1inp_driver_list;
+extern struct llist_head e1inp_line_list;
+
+int e1inp_vty_init(void);
+void e1inp_init(void);
+
+int _abis_nm_sendmsg(struct msgb *msg, int to_trx_oml);
+
+#endif /* _E1_INPUT_H */
diff --git a/include/openbsc/gb_proxy.h b/include/openbsc/gb_proxy.h
new file mode 100644
index 00000000..18ded229
--- /dev/null
+++ b/include/openbsc/gb_proxy.h
@@ -0,0 +1,39 @@
+#ifndef _GB_PROXY_H
+#define _GB_PROXY_H
+
+#include <sys/types.h>
+
+#include <osmocore/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;
+
+ /* misc */
+ struct gprs_ns_inst *nsi;
+};
+
+extern struct gbproxy_config gbcfg;
+extern struct cmd_element show_gbproxy_cmd;
+
+/* gb_proxy_vty .c */
+
+int gbproxy_vty_init(void);
+int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg);
+
+
+/* gb_proxy.c */
+
+/* Main input function for Gb proxy */
+int gbprox_rcvmsg(struct msgb *msg, struct gprs_nsvc *nsvc, uint16_t ns_bvci);
+
+int gbprox_signal(unsigned int subsys, unsigned int signal,
+ void *handler_data, void *signal_data);
+
+/* Reset all persistent NS-VC's */
+int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi);
+
+#endif
diff --git a/include/openbsc/gprs_bssgp.h b/include/openbsc/gprs_bssgp.h
new file mode 100644
index 00000000..e432cf75
--- /dev/null
+++ b/include/openbsc/gprs_bssgp.h
@@ -0,0 +1,232 @@
+#ifndef _GPRS_BSSGP_H
+#define _GPRS_BSSGP_H
+
+#include <stdint.h>
+
+/* Section 5.4.1 */
+#define BVCI_SIGNALLING 0x0000
+#define BVCI_PTM 0x0001
+
+/* Section 11.3.26 / Table 11.27 */
+enum bssgp_pdu_type {
+ /* PDUs between RL and BSSGP SAPs */
+ BSSGP_PDUT_DL_UNITDATA = 0x00,
+ BSSGP_PDUT_UL_UNITDATA = 0x01,
+ BSSGP_PDUT_RA_CAPABILITY = 0x02,
+ BSSGP_PDUT_PTM_UNITDATA = 0x03,
+ /* PDUs between GMM SAPs */
+ BSSGP_PDUT_PAGING_PS = 0x06,
+ BSSGP_PDUT_PAGING_CS = 0x07,
+ BSSGP_PDUT_RA_CAPA_UDPATE = 0x08,
+ BSSGP_PDUT_RA_CAPA_UPDATE_ACK = 0x09,
+ BSSGP_PDUT_RADIO_STATUS = 0x0a,
+ BSSGP_PDUT_SUSPEND = 0x0b,
+ BSSGP_PDUT_SUSPEND_ACK = 0x0c,
+ BSSGP_PDUT_SUSPEND_NACK = 0x0d,
+ BSSGP_PDUT_RESUME = 0x0e,
+ BSSGP_PDUT_RESUME_ACK = 0x0f,
+ BSSGP_PDUT_RESUME_NACK = 0x10,
+ /* PDus between NM SAPs */
+ BSSGP_PDUT_BVC_BLOCK = 0x20,
+ BSSGP_PDUT_BVC_BLOCK_ACK = 0x21,
+ BSSGP_PDUT_BVC_RESET = 0x22,
+ BSSGP_PDUT_BVC_RESET_ACK = 0x23,
+ BSSGP_PDUT_BVC_UNBLOCK = 0x24,
+ BSSGP_PDUT_BVC_UNBLOCK_ACK = 0x25,
+ BSSGP_PDUT_FLOW_CONTROL_BVC = 0x26,
+ BSSGP_PDUT_FLOW_CONTROL_BVC_ACK = 0x27,
+ BSSGP_PDUT_FLOW_CONTROL_MS = 0x28,
+ BSSGP_PDUT_FLOW_CONTROL_MS_ACK = 0x29,
+ BSSGP_PDUT_FLUSH_LL = 0x2a,
+ BSSGP_PDUT_FLUSH_LL_ACK = 0x2b,
+ BSSGP_PDUT_LLC_DISCARD = 0x2c,
+ BSSGP_PDUT_SGSN_INVOKE_TRACE = 0x40,
+ BSSGP_PDUT_STATUS = 0x41,
+ /* PDUs between PFM SAP's */
+ BSSGP_PDUT_DOWNLOAD_BSS_PFC = 0x50,
+ BSSGP_PDUT_CREATE_BSS_PFC = 0x51,
+ BSSGP_PDUT_CREATE_BSS_PFC_ACK = 0x52,
+ BSSGP_PDUT_CREATE_BSS_PFC_NACK = 0x53,
+ BSSGP_PDUT_MODIFY_BSS_PFC = 0x54,
+ BSSGP_PDUT_MODIFY_BSS_PFC_ACK = 0x55,
+ BSSGP_PDUT_DELETE_BSS_PFC = 0x56,
+ BSSGP_PDUT_DELETE_BSS_PFC_ACK = 0x57,
+};
+
+/* Section 10.2.1 and 10.2.2 */
+struct bssgp_ud_hdr {
+ uint8_t pdu_type;
+ uint32_t tlli;
+ uint8_t qos_profile[3];
+ uint8_t data[0]; /* TLV's */
+} __attribute__((packed));
+
+struct bssgp_normal_hdr {
+ uint8_t pdu_type;
+ uint8_t data[0]; /* TLV's */
+};
+
+enum bssgp_iei_type {
+ BSSGP_IE_ALIGNMENT = 0x00,
+ BSSGP_IE_BMAX_DEFAULT_MS = 0x01,
+ BSSGP_IE_BSS_AREA_ID = 0x02,
+ BSSGP_IE_BUCKET_LEAK_RATE = 0x03,
+ BSSGP_IE_BVCI = 0x04,
+ BSSGP_IE_BVC_BUCKET_SIZE = 0x05,
+ BSSGP_IE_BVC_MEASUREMENT = 0x06,
+ BSSGP_IE_CAUSE = 0x07,
+ BSSGP_IE_CELL_ID = 0x08,
+ BSSGP_IE_CHAN_NEEDED = 0x09,
+ BSSGP_IE_DRX_PARAMS = 0x0a,
+ BSSGP_IE_EMLPP_PRIO = 0x0b,
+ BSSGP_IE_FLUSH_ACTION = 0x0c,
+ BSSGP_IE_IMSI = 0x0d,
+ BSSGP_IE_LLC_PDU = 0x0e,
+ BSSGP_IE_LLC_FRAMES_DISCARDED = 0x0f,
+ BSSGP_IE_LOCATION_AREA = 0x10,
+ BSSGP_IE_MOBILE_ID = 0x11,
+ BSSGP_IE_MS_BUCKET_SIZE = 0x12,
+ BSSGP_IE_MS_RADIO_ACCESS_CAP = 0x13,
+ BSSGP_IE_OMC_ID = 0x14,
+ BSSGP_IE_PDU_IN_ERROR = 0x15,
+ BSSGP_IE_PDU_LIFETIME = 0x16,
+ BSSGP_IE_PRIORITY = 0x17,
+ BSSGP_IE_QOS_PROFILE = 0x18,
+ BSSGP_IE_RADIO_CAUSE = 0x19,
+ BSSGP_IE_RA_CAP_UPD_CAUSE = 0x1a,
+ BSSGP_IE_ROUTEING_AREA = 0x1b,
+ BSSGP_IE_R_DEFAULT_MS = 0x1c,
+ BSSGP_IE_SUSPEND_REF_NR = 0x1d,
+ BSSGP_IE_TAG = 0x1e,
+ BSSGP_IE_TLLI = 0x1f,
+ BSSGP_IE_TMSI = 0x20,
+ BSSGP_IE_TRACE_REFERENC = 0x21,
+ BSSGP_IE_TRACE_TYPE = 0x22,
+ BSSGP_IE_TRANSACTION_ID = 0x23,
+ BSSGP_IE_TRIGGER_ID = 0x24,
+ BSSGP_IE_NUM_OCT_AFF = 0x25,
+ BSSGP_IE_LSA_ID_LIST = 0x26,
+ BSSGP_IE_LSA_INFORMATION = 0x27,
+ BSSGP_IE_PACKET_FLOW_ID = 0x28,
+ BSSGP_IE_PACKET_FLOW_TIMER = 0x29,
+ BSSGP_IE_AGG_BSS_QOS_PROFILE = 0x3a,
+ BSSGP_IE_FEATURE_BITMAP = 0x3b,
+ BSSGP_IE_BUCKET_FULL_RATIO = 0x3c,
+ BSSGP_IE_SERVICE_UTRAN_CCO = 0x3d,
+};
+
+/* Section 11.3.8 / Table 11.10: Cause coding */
+enum gprs_bssgp_cause {
+ BSSGP_CAUSE_PROC_OVERLOAD = 0x00,
+ BSSGP_CAUSE_EQUIP_FAIL = 0x01,
+ BSSGP_CAUSE_TRASIT_NET_FAIL = 0x02,
+ BSSGP_CAUSE_CAPA_GREATER_0KPBS = 0x03,
+ BSSGP_CAUSE_UNKNOWN_MS = 0x04,
+ BSSGP_CAUSE_UNKNOWN_BVCI = 0x05,
+ BSSGP_CAUSE_CELL_TRAF_CONG = 0x06,
+ BSSGP_CAUSE_SGSN_CONG = 0x07,
+ BSSGP_CAUSE_OML_INTERV = 0x08,
+ BSSGP_CAUSE_BVCI_BLOCKED = 0x09,
+ BSSGP_CAUSE_PFC_CREATE_FAIL = 0x0a,
+ BSSGP_CAUSE_SEM_INCORR_PDU = 0x20,
+ BSSGP_CAUSE_INV_MAND_INF = 0x21,
+ BSSGP_CAUSE_MISSING_MAND_IE = 0x22,
+ BSSGP_CAUSE_MISSING_COND_IE = 0x23,
+ BSSGP_CAUSE_UNEXP_COND_IE = 0x24,
+ BSSGP_CAUSE_COND_IE_ERR = 0x25,
+ BSSGP_CAUSE_PDU_INCOMP_STATE = 0x26,
+ BSSGP_CAUSE_PROTO_ERR_UNSPEC = 0x27,
+ BSSGP_CAUSE_PDU_INCOMP_FEAT = 0x28,
+};
+
+/* Our implementation */
+
+/* gprs_bssgp_util.c */
+extern struct gprs_ns_inst *bssgp_nsi;
+struct msgb *bssgp_msgb_alloc(void);
+const char *bssgp_cause_str(enum gprs_bssgp_cause cause);
+/* Transmit a simple response such as BLOCK/UNBLOCK/RESET ACK/NACK */
+int bssgp_tx_simple_bvci(uint8_t pdu_type, uint16_t nsei,
+ uint16_t bvci, uint16_t ns_bvci);
+/* Chapter 10.4.14: Status */
+int bssgp_tx_status(uint8_t cause, uint16_t *bvci, struct msgb *orig_msg);
+
+/* gprs_bssgp.c */
+
+#define BVC_S_BLOCKED 0x0001
+
+/* The per-BTS context that we keep on the SGSN side of the BSSGP link */
+struct bssgp_bvc_ctx {
+ struct llist_head list;
+
+ /* parsed RA ID and Cell ID of the remote BTS */
+ struct gprs_ra_id ra_id;
+ uint16_t cell_id;
+
+ /* NSEI and BVCI of underlying Gb link. Together they
+ * uniquely identify a link to a BTS (5.4.4) */
+ uint16_t bvci;
+ uint16_t nsei;
+
+ uint32_t state;
+
+ struct rate_ctr_group *ctrg;
+
+ /* we might want to add this as a shortcut later, avoiding the NSVC
+ * lookup for every packet, similar to a routing cache */
+ //struct gprs_nsvc *nsvc;
+};
+extern struct llist_head bssgp_bvc_ctxts;
+/* Find a BTS Context based on parsed RA ID and Cell ID */
+struct bssgp_bvc_ctx *btsctx_by_raid_cid(const struct gprs_ra_id *raid, uint16_t cid);
+/* 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>
+
+/* BSSGP-UL-UNITDATA.ind */
+int gprs_bssgp_rcvmsg(struct msgb *msg);
+
+/* BSSGP-DL-UNITDATA.req */
+struct sgsn_mm_ctx;
+int gprs_bssgp_tx_dl_ud(struct msgb *msg, struct sgsn_mm_ctx *mmctx);
+
+uint16_t bssgp_parse_cell_id(struct gprs_ra_id *raid, const uint8_t *buf);
+
+/* Wrapper around TLV parser to parse BSSGP IEs */
+static inline int bssgp_tlv_parse(struct tlv_parsed *tp, uint8_t *buf, int len)
+{
+ return tlv_parse(tp, &tvlv_att_def, buf, len, 0, 0);
+}
+
+enum bssgp_paging_mode {
+ BSSGP_PAGING_PS,
+ BSSGP_PAGING_CS,
+};
+
+enum bssgp_paging_scope {
+ BSSGP_PAGING_BSS_AREA, /* all cells in BSS */
+ BSSGP_PAGING_LOCATION_AREA, /* all cells in LA */
+ BSSGP_PAGING_ROUTEING_AREA, /* all cells in RA */
+ BSSGP_PAGING_BVCI, /* one cell */
+};
+
+struct bssgp_paging_info {
+ enum bssgp_paging_mode mode;
+ enum bssgp_paging_scope scope;
+ struct gprs_ra_id raid;
+ uint16_t bvci;
+ const char *imsi;
+ uint32_t *ptmsi;
+ uint16_t drx_params;
+ uint8_t qos[3];
+};
+
+/* Send a single GMM-PAGING.req to a given NSEI/NS-BVCI */
+int gprs_bssgp_tx_paging(uint16_t nsei, uint16_t ns_bvci,
+ struct bssgp_paging_info *pinfo);
+
+/* gprs_bssgp_vty.c */
+int gprs_bssgp_vty_init(void);
+
+#endif /* _GPRS_BSSGP_H */
diff --git a/include/openbsc/gprs_gmm.h b/include/openbsc/gprs_gmm.h
new file mode 100644
index 00000000..bd129ae4
--- /dev/null
+++ b/include/openbsc/gprs_gmm.h
@@ -0,0 +1,19 @@
+#ifndef _GPRS_GMM_H
+#define _GPRS_GMM_H
+
+#include <osmocore/msgb.h>
+#include <openbsc/gprs_sgsn.h>
+
+int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause);
+int gsm48_tx_gsm_act_pdp_rej(struct sgsn_mm_ctx *mm, uint8_t tid,
+ uint8_t cause, uint8_t pco_len, uint8_t *pco_v);
+int gsm48_tx_gsm_act_pdp_acc(struct sgsn_pdp_ctx *pdp);
+int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp);
+
+int gsm0408_gprs_rcvmsg(struct msgb *msg, struct gprs_llc_llme *llme);
+
+int gprs_gmm_rx_suspend(struct gprs_ra_id *raid, uint32_t tlli);
+int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli,
+ uint8_t suspend_ref);
+
+#endif /* _GPRS_GMM_H */
diff --git a/include/openbsc/gprs_llc.h b/include/openbsc/gprs_llc.h
new file mode 100644
index 00000000..02945e16
--- /dev/null
+++ b/include/openbsc/gprs_llc.h
@@ -0,0 +1,162 @@
+#ifndef _GPRS_LLC_H
+#define _GPRS_LLC_H
+
+#include <stdint.h>
+#include <openbsc/gprs_sgsn.h>
+
+/* Section 4.7 LLC Layer Structure */
+enum gprs_llc_sapi {
+ GPRS_SAPI_GMM = 1,
+ GPRS_SAPI_TOM2 = 2,
+ GPRS_SAPI_SNDCP3 = 3,
+ GPRS_SAPI_SNDCP5 = 5,
+ GPRS_SAPI_SMS = 7,
+ GPRS_SAPI_TOM8 = 8,
+ GPRS_SAPI_SNDCP9 = 9,
+ GPRS_SAPI_SNDCP11 = 11,
+};
+
+/* Section 6.4 Commands and Responses */
+enum gprs_llc_u_cmd {
+ GPRS_LLC_U_DM_RESP = 0x01,
+ GPRS_LLC_U_DISC_CMD = 0x04,
+ GPRS_LLC_U_UA_RESP = 0x06,
+ GPRS_LLC_U_SABM_CMD = 0x07,
+ GPRS_LLC_U_FRMR_RESP = 0x08,
+ GPRS_LLC_U_XID = 0x0b,
+ GPRS_LLC_U_NULL_CMD = 0x00,
+};
+
+/* TS 04.64 Section 7.1.2 Table 7: LLC layer primitives (GMM/SNDCP/SMS/TOM) */
+/* TS 04.65 Section 5.1.2 Table 2: Service primitives used by SNDCP */
+enum gprs_llc_primitive {
+ /* GMM <-> LLME */
+ LLGMM_ASSIGN_REQ, /* GMM tells us new TLLI: TLLI old, TLLI new, Kc, CiphAlg */
+ LLGMM_RESET_REQ, /* GMM tells us to perform XID negotiation: TLLI */
+ LLGMM_RESET_CNF, /* LLC informs GMM that XID has completed: TLLI */
+ LLGMM_SUSPEND_REQ, /* GMM tells us MS has suspended: TLLI, Page */
+ LLGMM_RESUME_REQ, /* GMM tells us MS has resumed: TLLI */
+ LLGMM_PAGE_IND, /* LLC asks GMM to page MS: TLLI */
+ LLGMM_IOV_REQ, /* GMM tells us to perform XID: TLLI */
+ LLGMM_STATUS_IND, /* LLC informs GMM about error: TLLI, Cause */
+ /* LLE <-> (GMM/SNDCP/SMS/TOM) */
+ LL_RESET_IND, /* TLLI */
+ LL_ESTABLISH_REQ, /* TLLI, XID Req */
+ LL_ESTABLISH_IND, /* TLLI, XID Req, N201-I, N201-U */
+ LL_ESTABLISH_RESP, /* TLLI, XID Negotiated */
+ LL_ESTABLISH_CONF, /* TLLI, XID Neg, N201-i, N201-U */
+ LL_RELEASE_REQ, /* TLLI, Local */
+ LL_RELEASE_IND, /* TLLI, Cause */
+ LL_RELEASE_CONF, /* TLLI */
+ LL_XID_REQ, /* TLLI, XID Requested */
+ LL_XID_IND, /* TLLI, XID Req, N201-I, N201-U */
+ LL_XID_RESP, /* TLLI, XID Negotiated */
+ LL_XID_CONF, /* TLLI, XID Neg, N201-I, N201-U */
+ LL_DATA_REQ, /* TLLI, SN-PDU, Ref, QoS, Radio Prio, Ciph */
+ LL_DATA_IND, /* TLLI, SN-PDU */
+ LL_DATA_CONF, /* TLLI, Ref */
+ LL_UNITDATA_REQ, /* TLLI, SN-PDU, Ref, QoS, Radio Prio, Ciph */
+ LL_UNITDATA_IND, /* TLLI, SN-PDU */
+ LL_STATUS_IND, /* TLLI, Cause */
+};
+
+/* Section 4.5.2 Logical Link States + Annex C.2 */
+enum gprs_llc_lle_state {
+ GPRS_LLES_UNASSIGNED = 1, /* No TLLI yet */
+ GPRS_LLES_ASSIGNED_ADM = 2, /* TLLI assigned */
+ GPRS_LLES_LOCAL_EST = 3, /* Local Establishment */
+ GPRS_LLES_REMOTE_EST = 4, /* Remote Establishment */
+ GPRS_LLES_ABM = 5,
+ GPRS_LLES_LOCAL_REL = 6, /* Local Release */
+ GPRS_LLES_TIMER_REC = 7, /* Timer Recovery */
+};
+
+enum gprs_llc_llme_state {
+ GPRS_LLMS_UNASSIGNED = 1, /* No TLLI yet */
+ GPRS_LLMS_ASSIGNED = 2, /* TLLI assigned */
+};
+
+/* Section 8.9.9 LLC layer parameter default values */
+struct gprs_llc_params {
+ uint16_t iov_i_exp;
+ uint16_t t200_201;
+ uint16_t n200;
+ uint16_t n201_u;
+ uint16_t n201_i;
+ uint16_t mD;
+ uint16_t mU;
+ uint16_t kD;
+ uint16_t kU;
+};
+
+/* Section 4.7.1: Logical Link Entity: One per DLCI (TLLI + SAPI) */
+struct gprs_llc_lle {
+ struct llist_head list;
+
+ uint32_t sapi;
+
+ struct gprs_llc_llme *llme;
+
+ enum gprs_llc_lle_state state;
+
+ struct timer_list t200;
+ struct timer_list t201; /* wait for acknowledgement */
+
+ uint16_t v_sent;
+ uint16_t v_ack;
+ uint16_t v_recv;
+
+ uint16_t vu_send;
+ uint16_t vu_recv;
+
+ /* Overflow Counter for ABM */
+ uint32_t oc_i_send;
+ uint32_t oc_i_recv;
+
+ /* Overflow Counter for unconfirmed transfer */
+ uint32_t oc_ui_send;
+ uint32_t oc_ui_recv;
+
+ unsigned int retrans_ctr;
+
+ struct gprs_llc_params params;
+};
+
+#define NUM_SAPIS 16
+
+struct gprs_llc_llme {
+ struct llist_head list;
+
+ enum gprs_llc_llme_state state;
+
+ uint32_t tlli;
+ uint32_t old_tlli;
+
+ /* Crypto parameters */
+ enum gprs_ciph_algo algo;
+ uint8_t kc[8];
+
+ /* over which BSSGP BTS ctx do we need to transmit */
+ uint16_t bvci;
+ uint16_t nsei;
+ struct gprs_llc_lle lle[NUM_SAPIS];
+};
+
+extern struct llist_head gprs_llc_llmes;
+
+/* BSSGP-UL-UNITDATA.ind */
+int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv);
+
+/* LL-UNITDATA.req */
+int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command,
+ void *mmctx);
+
+/* 04.64 Chapter 7.2.1.1 LLGMM-ASSIGN */
+int gprs_llgmm_assign(struct gprs_llc_llme *llme,
+ uint32_t old_tlli, uint32_t new_tlli,
+ enum gprs_ciph_algo alg, const uint8_t *kc);
+
+int gprs_llc_init(const char *cipher_plugin_path);
+int gprs_llc_vty_init(void);
+
+#endif
diff --git a/include/openbsc/gprs_ns.h b/include/openbsc/gprs_ns.h
new file mode 100644
index 00000000..953c364b
--- /dev/null
+++ b/include/openbsc/gprs_ns.h
@@ -0,0 +1,232 @@
+#ifndef _GPRS_NS_H
+#define _GPRS_NS_H
+
+#include <stdint.h>
+
+/* GPRS Networks Service (NS) messages on the Gb interface
+ * 3GPP TS 08.16 version 8.0.1 Release 1999 / ETSI TS 101 299 V8.0.1 (2002-05)
+ * 3GPP TS 48.016 version 6.5.0 Release 6 / ETSI TS 148 016 V6.5.0 (2005-11) */
+
+struct gprs_ns_hdr {
+ uint8_t pdu_type;
+ uint8_t data[0];
+} __attribute__((packed));
+
+/* TS 08.16, Section 10.3.7, Table 14 */
+enum ns_pdu_type {
+ NS_PDUT_UNITDATA = 0x00,
+ NS_PDUT_RESET = 0x02,
+ NS_PDUT_RESET_ACK = 0x03,
+ NS_PDUT_BLOCK = 0x04,
+ NS_PDUT_BLOCK_ACK = 0x05,
+ NS_PDUT_UNBLOCK = 0x06,
+ NS_PDUT_UNBLOCK_ACK = 0x07,
+ NS_PDUT_STATUS = 0x08,
+ NS_PDUT_ALIVE = 0x0a,
+ NS_PDUT_ALIVE_ACK = 0x0b,
+ /* TS 48.016 Section 10.3.7, Table 10.3.7.1 */
+ SNS_PDUT_ACK = 0x0c,
+ SNS_PDUT_ADD = 0x0d,
+ SNS_PDUT_CHANGE_WEIGHT = 0x0e,
+ SNS_PDUT_CONFIG = 0x0f,
+ SNS_PDUT_CONFIG_ACK = 0x10,
+ SNS_PDUT_DELETE = 0x11,
+ SNS_PDUT_SIZE = 0x12,
+ SNS_PDUT_SIZE_ACK = 0x13,
+};
+
+/* TS 08.16, Section 10.3, Table 12 */
+enum ns_ctrl_ie {
+ NS_IE_CAUSE = 0x00,
+ NS_IE_VCI = 0x01,
+ NS_IE_PDU = 0x02,
+ NS_IE_BVCI = 0x03,
+ NS_IE_NSEI = 0x04,
+ /* TS 48.016 Section 10.3, Table 10.3.1 */
+ NS_IE_IPv4_LIST = 0x05,
+ NS_IE_IPv6_LIST = 0x06,
+ NS_IE_MAX_NR_NSVC = 0x07,
+ NS_IE_IPv4_EP_NR = 0x08,
+ NS_IE_IPv6_EP_NR = 0x09,
+ NS_IE_RESET_FLAG = 0x0a,
+ NS_IE_IP_ADDR = 0x0b,
+};
+
+/* TS 08.16, Section 10.3.2, Table 13 */
+enum ns_cause {
+ NS_CAUSE_TRANSIT_FAIL = 0x00,
+ NS_CAUSE_OM_INTERVENTION = 0x01,
+ NS_CAUSE_EQUIP_FAIL = 0x02,
+ NS_CAUSE_NSVC_BLOCKED = 0x03,
+ NS_CAUSE_NSVC_UNKNOWN = 0x04,
+ NS_CAUSE_BVCI_UNKNOWN = 0x05,
+ NS_CAUSE_SEM_INCORR_PDU = 0x08,
+ NS_CAUSE_PDU_INCOMP_PSTATE = 0x0a,
+ NS_CAUSE_PROTO_ERR_UNSPEC = 0x0b,
+ NS_CAUSE_INVAL_ESSENT_IE = 0x0c,
+ NS_CAUSE_MISSING_ESSENT_IE = 0x0d,
+ /* TS 48.016 Section 10.3.2, Table 10.3.2.1 */
+ NS_CAUSE_INVAL_NR_IPv4_EP = 0x0e,
+ NS_CAUSE_INVAL_NR_IPv6_EP = 0x0f,
+ NS_CAUSE_INVAL_NR_NS_VC = 0x10,
+ NS_CAUSE_INVAL_WEIGH = 0x11,
+ NS_CAUSE_UNKN_IP_EP = 0x12,
+ NS_CAUSE_UNKN_IP_ADDR = 0x13,
+ NS_CAUSE_UNKN_IP_TEST_FAILED = 0x14,
+};
+
+/* Our Implementation */
+#include <netinet/in.h>
+#include <osmocore/linuxlist.h>
+#include <osmocore/msgb.h>
+#include <osmocore/timer.h>
+#include <osmocore/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)"
+#define NS_TIMERS_HELP \
+ "(un)blocking Timer (Tns-block) timeout\n" \
+ "(un)blocking Timer (Tns-block) number of retries\n" \
+ "Reset Timer (Tns-reset) timeout\n" \
+ "Reset Timer (Tns-reset) number of retries\n" \
+ "Test Timer (Tns-test) timeout\n" \
+
+enum ns_timeout {
+ NS_TOUT_TNS_BLOCK,
+ NS_TOUT_TNS_BLOCK_RETRIES,
+ NS_TOUT_TNS_RESET,
+ NS_TOUT_TNS_RESET_RETRIES,
+ NS_TOUT_TNS_TEST,
+ NS_TOUT_TNS_ALIVE,
+ NS_TOUT_TNS_ALIVE_RETRIES,
+};
+
+#define NSE_S_BLOCKED 0x0001
+#define NSE_S_ALIVE 0x0002
+
+enum gprs_ns_ll {
+ GPRS_NS_LL_UDP,
+ GPRS_NS_LL_E1,
+ GPRS_NS_LL_FR_GRE,
+};
+
+enum gprs_ns_evt {
+ GPRS_NS_EVT_UNIT_DATA,
+};
+
+struct gprs_nsvc;
+typedef int gprs_ns_cb_t(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
+ struct msgb *msg, uint16_t bvci);
+
+/* An instance of the NS protocol stack */
+struct gprs_ns_inst {
+ /* callback to the user for incoming UNIT DATA IND */
+ gprs_ns_cb_t *cb;
+
+ /* linked lists of all NSVC in this instance */
+ struct llist_head gprs_nsvcs;
+
+ /* a NSVC object that's needed to deal with packets for unknown NSVC */
+ struct gprs_nsvc *unknown_nsvc;
+
+ uint16_t timeout[NS_TIMERS_COUNT];
+
+ /* NS-over-IP specific bits */
+ struct {
+ struct bsc_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;
+ uint32_t local_ip;
+ int enabled:1;
+ } frgre;
+};
+
+enum nsvc_timer_mode {
+ /* standard timers */
+ NSVC_TIMER_TNS_TEST,
+ NSVC_TIMER_TNS_ALIVE,
+ NSVC_TIMER_TNS_RESET,
+ _NSVC_TIMER_NR,
+};
+
+struct gprs_nsvc {
+ struct llist_head list;
+ struct gprs_ns_inst *nsi;
+
+ uint16_t nsei; /* end-to-end significance */
+ uint16_t nsvci; /* uniquely identifies NS-VC at SGSN */
+
+ uint32_t state;
+ uint32_t remote_state;
+
+ struct timer_list timer;
+ enum nsvc_timer_mode timer_mode;
+ int alive_retries;
+
+ unsigned int remote_end_is_sgsn:1;
+ unsigned int persistent:1;
+
+ struct rate_ctr_group *ctrg;
+
+ /* which link-layer are we based on? */
+ enum gprs_ns_ll ll;
+
+ union {
+ struct {
+ struct sockaddr_in bts_addr;
+ } ip;
+ struct {
+ struct sockaddr_in bts_addr;
+ } frgre;
+ };
+};
+
+/* Create a new NS protocol instance */
+struct gprs_ns_inst *gprs_ns_instantiate(gprs_ns_cb_t *cb);
+
+/* Destroy a NS protocol instance */
+void gprs_ns_destroy(struct gprs_ns_inst *nsi);
+
+/* Listen for incoming GPRS packets via NS/UDP */
+int gprs_ns_nsip_listen(struct gprs_ns_inst *nsi);
+
+struct sockaddr_in;
+
+/* main function for higher layers (BSSGP) to send NS messages */
+int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg);
+
+int gprs_ns_tx_reset(struct gprs_nsvc *nsvc, uint8_t cause);
+int gprs_ns_tx_block(struct gprs_nsvc *nsvc, uint8_t cause);
+int gprs_ns_tx_unblock(struct gprs_nsvc *nsvc);
+
+/* Listen for incoming GPRS packets via NS/FR/GRE */
+int gprs_ns_frgre_listen(struct gprs_ns_inst *nsi);
+
+/* Establish a connection (from the BSS) to the SGSN */
+struct gprs_nsvc *nsip_connect(struct gprs_ns_inst *nsi,
+ struct sockaddr_in *dest, uint16_t nsei,
+ uint16_t nsvci);
+
+struct gprs_nsvc *nsvc_create(struct gprs_ns_inst *nsi, uint16_t nsvci);
+void nsvc_delete(struct gprs_nsvc *nsvc);
+struct gprs_nsvc *nsvc_by_nsei(struct gprs_ns_inst *nsi, uint16_t nsei);
+struct gprs_nsvc *nsvc_by_nsvci(struct gprs_ns_inst *nsi, uint16_t nsvci);
+
+/* Initiate a RESET procedure (including timer start, ...)*/
+void gprs_nsvc_reset(struct gprs_nsvc *nsvc, uint8_t cause);
+
+/* Add NS-specific VTY stuff */
+int gprs_ns_vty_init(struct gprs_ns_inst *nsi);
+
+#define NS_ALLOC_SIZE 2048
+#define NS_ALLOC_HEADROOM 20
+static inline struct msgb *gprs_ns_msgb_alloc(void)
+{
+ return msgb_alloc_headroom(NS_ALLOC_SIZE, NS_ALLOC_HEADROOM, "GPRS/NS");
+}
+
+#endif
diff --git a/include/openbsc/gprs_ns_frgre.h b/include/openbsc/gprs_ns_frgre.h
new file mode 100644
index 00000000..abcd43ff
--- /dev/null
+++ b/include/openbsc/gprs_ns_frgre.h
@@ -0,0 +1,6 @@
+#ifndef _GPRS_NS_FRGRE_H
+#define _GPRS_NS_FRGRE_H
+
+int gprs_ns_frgre_sendmsg(struct gprs_nsvc *nsvc, struct msgb *msg);
+
+#endif
diff --git a/include/openbsc/gprs_sgsn.h b/include/openbsc/gprs_sgsn.h
new file mode 100644
index 00000000..b470c536
--- /dev/null
+++ b/include/openbsc/gprs_sgsn.h
@@ -0,0 +1,220 @@
+#ifndef _GPRS_SGSN_H
+#define _GPRS_SGSN_H
+
+#include <stdint.h>
+#include <netinet/in.h>
+
+#include <osmocore/gsm48.h>
+
+#include <osmocom/crypt/gprs_cipher.h>
+
+#define GSM_IMSI_LENGTH 17
+#define GSM_IMEI_LENGTH 17
+#define GSM_EXTENSION_LENGTH 15
+
+struct gprs_llc_lle;
+
+/* TS 04.08 4.1.3.3 GMM mobility management states on the network side */
+enum gprs_mm_state {
+ GMM_DEREGISTERED, /* 4.1.3.3.1.1 */
+ GMM_COMMON_PROC_INIT, /* 4.1.3.3.1.2 */
+ GMM_REGISTERED_NORMAL, /* 4.1.3.3.2.1 */
+ GMM_REGISTERED_SUSPENDED, /* 4.1.3.3.2.2 */
+ GMM_DEREGISTERED_INIT, /* 4.1.3.3.1.4 */
+};
+
+enum gprs_mm_ctr {
+ GMM_CTR_PKTS_SIG_IN,
+ GMM_CTR_PKTS_SIG_OUT,
+ GMM_CTR_PKTS_UDATA_IN,
+ GMM_CTR_PKTS_UDATA_OUT,
+ GMM_CTR_BYTES_UDATA_IN,
+ GMM_CTR_BYTES_UDATA_OUT,
+ GMM_CTR_PDP_CTX_ACT,
+ GMM_CTR_SUSPEND,
+ GMM_CTR_PAGING_PS,
+ GMM_CTR_PAGING_CS,
+ GMM_CTR_RA_UPDATE,
+};
+
+enum gprs_pdp_ctx {
+ PDP_CTR_PKTS_UDATA_IN,
+ PDP_CTR_PKTS_UDATA_OUT,
+ PDP_CTR_BYTES_UDATA_IN,
+ PDP_CTR_BYTES_UDATA_OUT,
+};
+
+enum gprs_t3350_mode {
+ GMM_T3350_MODE_ATT,
+ GMM_T3350_MODE_RAU,
+ GMM_T3350_MODE_PTMSI_REALL,
+};
+
+#define MS_RADIO_ACCESS_CAPA
+
+/* According to TS 03.60, Table 5: SGSN MM and PDP Contexts */
+/* Extended by 3GPP TS 23.060, Table 6: SGSN MM and PDP Contexts */
+struct sgsn_mm_ctx {
+ struct llist_head list;
+
+ char imsi[GSM_IMSI_LENGTH];
+ enum gprs_mm_state mm_state;
+ uint32_t p_tmsi;
+ uint32_t p_tmsi_old; /* old P-TMSI before new is confirmed */
+ uint32_t p_tmsi_sig;
+ char imei[GSM_IMEI_LENGTH];
+ /* Opt: Software Version Numbber / TS 23.195 */
+ char msisdn[GSM_EXTENSION_LENGTH];
+ struct gprs_ra_id ra;
+ uint16_t cell_id;
+ uint32_t cell_id_age;
+ uint16_t sac; /* Iu: Service Area Code */
+ uint32_t sac_age;/* Iu: Service Area Code age */
+ /* VLR number */
+ uint32_t new_sgsn_addr;
+ /* Authentication Triplets */
+ /* Kc */
+ /* Iu: CK, IK, KSI */
+ /* CKSN */
+ enum gprs_ciph_algo ciph_algo;
+ struct {
+ uint8_t buf[14]; /* 10.5.5.12a */
+ uint8_t len;
+ } ms_radio_access_capa;
+ struct {
+ uint8_t buf[4]; /* 10.5.5.12 */
+ uint8_t len;
+ } ms_network_capa;
+ uint16_t drx_parms;
+ int mnrg; /* MS reported to HLR? */
+ int ngaf; /* MS reported to MSC/VLR? */
+ int ppf; /* paging for GPRS + non-GPRS? */
+ /* SMS Parameters */
+ int recovery;
+ uint8_t radio_prio_sms;
+
+ struct llist_head pdp_list;
+
+ /* Additional bits not present in the GSM TS */
+ struct gprs_llc_llme *llme;
+ uint32_t tlli;
+ uint32_t tlli_new;
+ uint16_t nsei;
+ uint16_t bvci;
+ struct rate_ctr_group *ctrg;
+ struct timer_list timer;
+ unsigned int T; /* Txxxx number */
+ unsigned int num_T_exp; /* number of consecutive T expirations */
+
+ enum gprs_t3350_mode t3350_mode;
+ uint8_t t3370_id_type;
+};
+
+/* look-up a SGSN MM context based on TLLI + RAI */
+struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
+ const struct gprs_ra_id *raid);
+struct sgsn_mm_ctx *sgsn_mm_ctx_by_ptmsi(uint32_t tmsi);
+struct sgsn_mm_ctx *sgsn_mm_ctx_by_imsi(const char *imsi);
+
+/* Allocate a new SGSN MM context */
+struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t tlli,
+ const struct gprs_ra_id *raid);
+void sgsn_mm_ctx_free(struct sgsn_mm_ctx *mm);
+
+
+enum pdp_ctx_state {
+ PDP_STATE_NONE,
+ PDP_STATE_CR_REQ,
+ PDP_STATE_CR_CONF,
+
+ /* 04.08 / Figure 6.2 / 6.1.2.2 */
+ PDP_STATE_INACT_PEND,
+ PDP_STATE_INACTIVE = PDP_STATE_NONE,
+};
+
+enum pdp_type {
+ PDP_TYPE_NONE,
+ PDP_TYPE_ETSI_PPP,
+ PDP_TYPE_IANA_IPv4,
+ PDP_TYPE_IANA_IPv6,
+};
+
+struct sgsn_pdp_ctx {
+ struct llist_head list; /* list_head for mmctx->pdp_list */
+ struct llist_head g_list; /* list_head for global list */
+ struct sgsn_mm_ctx *mm; /* back pointer to MM CTX */
+ struct sgsn_ggsn_ctx *ggsn; /* which GGSN serves this PDP */
+ struct rate_ctr_group *ctrg;
+
+ //unsigned int id;
+ struct pdp_t *lib; /* pointer to libgtp PDP ctx */
+ enum pdp_ctx_state state;
+ enum pdp_type type;
+ uint32_t address;
+ char *apn_subscribed;
+ //char *apn_used;
+ uint16_t nsapi; /* SNDCP */
+ uint16_t sapi; /* LLC */
+ uint8_t ti; /* transaction identifier */
+ int vplmn_allowed;
+ uint32_t qos_profile_subscr;
+ //uint32_t qos_profile_req;
+ //uint32_t qos_profile_neg;
+ uint8_t radio_prio;
+ uint32_t tx_npdu_nr;
+ uint32_t rx_npdu_nr;
+ uint32_t tx_gtp_snd;
+ uint32_t rx_gtp_snu;
+ //uint32_t charging_id;
+ int reordering_reqd;
+
+ struct timer_list timer;
+ unsigned int T; /* Txxxx number */
+ unsigned int num_T_exp; /* number of consecutive T expirations */
+};
+
+
+/* look up PDP context by MM context and NSAPI */
+struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_nsapi(const struct sgsn_mm_ctx *mm,
+ uint8_t nsapi);
+/* look up PDP context by MM context and transaction ID */
+struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm,
+ uint8_t tid);
+
+struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
+ uint8_t nsapi);
+void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp);
+
+
+struct sgsn_ggsn_ctx {
+ struct llist_head list;
+ uint32_t id;
+ unsigned int gtp_version;
+ struct in_addr remote_addr;
+ int remote_restart_ctr;
+ struct gsn_t *gsn;
+};
+struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id);
+struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(uint32_t id);
+struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct in_addr *addr);
+struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(uint32_t id);
+
+struct apn_ctx {
+ struct llist_head list;
+ struct sgsn_ggsn_ctx *ggsn;
+ char *name;
+ char *description;
+};
+
+extern struct llist_head sgsn_mm_ctxts;
+extern struct llist_head sgsn_ggsn_ctxts;
+extern struct llist_head sgsn_apn_ctxts;
+extern struct llist_head sgsn_pdp_ctxts;
+
+uint32_t sgsn_alloc_ptmsi(void);
+
+/* High-level function to be called in case a GGSN has disappeared or
+ * ottherwise lost state (recovery procedure) */
+int drop_all_pdp_for_ggsn(struct sgsn_ggsn_ctx *ggsn);
+
+#endif /* _GPRS_SGSN_H */
diff --git a/include/openbsc/gsm_04_08.h b/include/openbsc/gsm_04_08.h
new file mode 100644
index 00000000..1c879edc
--- /dev/null
+++ b/include/openbsc/gsm_04_08.h
@@ -0,0 +1,70 @@
+#ifndef _GSM_04_08_H
+#define _GSM_04_08_H
+
+#include <openbsc/meas_rep.h>
+
+#include <osmocore/protocol/gsm_04_08.h>
+#include <osmocore/gsm48.h>
+
+struct msgb;
+struct gsm_bts;
+struct gsm_subscriber;
+struct gsm_network;
+struct gsm_trans;
+struct gsm_subscriber_connection;
+
+#define GSM48_ALLOC_SIZE 2048
+#define GSM48_ALLOC_HEADROOM 256
+
+static inline struct msgb *gsm48_msgb_alloc(void)
+{
+ return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
+ "GSM 04.08");
+}
+
+/* config options controlling the behaviour of the lower leves */
+void gsm0408_allow_everyone(int allow);
+void gsm0408_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause);
+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_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);
+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_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_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan,
+ u_int8_t power_command, u_int8_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 h_len, const char *input);
+int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv,
+ int h_len);
+
+int send_siemens_mrpci(struct gsm_lchan *lchan, u_int8_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_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_rx_rr_modif_ack(struct msgb *msg);
+int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg);
+
+struct msgb *gsm48_create_mm_serv_rej(enum gsm48_reject_value value);
+struct msgb *gsm48_create_loc_upd_rej(uint8_t cause);
+void gsm48_lchan2chan_desc(struct gsm48_chan_desc *cd,
+ const struct gsm_lchan *lchan);
+
+#endif
diff --git a/include/openbsc/gsm_04_08_gprs.h b/include/openbsc/gsm_04_08_gprs.h
new file mode 100644
index 00000000..8de63629
--- /dev/null
+++ b/include/openbsc/gsm_04_08_gprs.h
@@ -0,0 +1,383 @@
+#ifndef _GSM48_GPRS_H
+#define _GSM48_GPRS_H
+
+#include <stdint.h>
+#include <osmocore/protocol/gsm_04_08.h>
+
+/* Table 10.4 / 10.4a, GPRS Mobility Management (GMM) */
+#define GSM48_MT_GMM_ATTACH_REQ 0x01
+#define GSM48_MT_GMM_ATTACH_ACK 0x02
+#define GSM48_MT_GMM_ATTACH_COMPL 0x03
+#define GSM48_MT_GMM_ATTACH_REJ 0x04
+#define GSM48_MT_GMM_DETACH_REQ 0x05
+#define GSM48_MT_GMM_DETACH_ACK 0x06
+
+#define GSM48_MT_GMM_RA_UPD_REQ 0x08
+#define GSM48_MT_GMM_RA_UPD_ACK 0x09
+#define GSM48_MT_GMM_RA_UPD_COMPL 0x0a
+#define GSM48_MT_GMM_RA_UPD_REJ 0x0b
+
+#define GSM48_MT_GMM_PTMSI_REALL_CMD 0x10
+#define GSM48_MT_GMM_PTMSI_REALL_COMPL 0x11
+#define GSM48_MT_GMM_AUTH_CIPH_REQ 0x12
+#define GSM48_MT_GMM_AUTH_CIPH_RESP 0x13
+#define GSM48_MT_GMM_AUTH_CIPH_REJ 0x14
+#define GSM48_MT_GMM_ID_REQ 0x15
+#define GSM48_MT_GMM_ID_RESP 0x16
+#define GSM48_MT_GMM_STATUS 0x20
+#define GSM48_MT_GMM_INFO 0x21
+
+/* Table 10.4a, GPRS Session Management (GSM) */
+#define GSM48_MT_GSM_ACT_PDP_REQ 0x41
+#define GSM48_MT_GSM_ACT_PDP_ACK 0x42
+#define GSM48_MT_GSM_ACT_PDP_REJ 0x43
+#define GSM48_MT_GSM_REQ_PDP_ACT 0x44
+#define GSM48_MT_GSM_REQ_PDP_ACT_REJ 0x45
+#define GSM48_MT_GSM_DEACT_PDP_REQ 0x46
+#define GSM48_MT_GSM_DEACT_PDP_ACK 0x47
+#define GSM48_MT_GSM_ACT_AA_PDP_REQ 0x50
+#define GSM48_MT_GSM_ACT_AA_PDP_ACK 0x51
+#define GSM48_MT_GSM_ACT_AA_PDP_REJ 0x52
+#define GSM48_MT_GSM_DEACT_AA_PDP_REQ 0x53
+#define GSM48_MT_GSM_DEACT_AA_PDP_ACK 0x54
+#define GSM48_MT_GSM_STATUS 0x55
+
+/* Chapter 10.5.5.2 / Table 10.5.135 */
+#define GPRS_ATT_T_ATTACH 1
+#define GPRS_ATT_T_ATT_WHILE_IMSI 2
+#define GPRS_ATT_T_COMBINED 3
+
+/* Chapter 10.5.5.5 / Table 10.5.138 */
+#define GPRS_DET_T_MO_GPRS 1
+#define GPRS_DET_T_MO_IMSI 2
+#define GPRS_DET_T_MO_COMBINED 3
+/* Network to MS direction */
+#define GPRS_DET_T_MT_REATT_REQ 1
+#define GPRS_DET_T_MT_REATT_NOTREQ 2
+#define GPRS_DET_T_MT_IMSI 3
+
+/* Chapter 10.5.5.18 / Table 105.150 */
+#define GPRS_UPD_T_RA 0
+#define GPRS_UPD_T_RA_LA 1
+#define GPRS_UPD_T_RA_LA_IMSI_ATT 2
+#define GPRS_UPD_T_PERIODIC 3
+
+enum gsm48_gprs_ie_mm {
+ GSM48_IE_GMM_CIPH_CKSN = 0x08, /* 10.5.1.2 */
+ GSM48_IE_GMM_TIMER_READY = 0x17, /* 10.5.7.3 */
+ GSM48_IE_GMM_ALLOC_PTMSI = 0x18, /* 10.5.1.4 */
+ GSM48_IE_GMM_PTMSI_SIG = 0x19, /* 10.5.5.8 */
+ GSM48_IE_GMM_AUTH_RAND = 0x21, /* 10.5.3.1 */
+ GSM48_IE_GMM_AUTH_SRES = 0x22, /* 10.5.3.2 */
+ GSM48_IE_GMM_IMEISV = 0x23, /* 10.5.1.4 */
+ GSM48_IE_GMM_DRX_PARAM = 0x27, /* 10.5.5.6 */
+ GSM48_IE_GMM_MS_NET_CAPA = 0x31, /* 10.5.5.12 */
+ GSM48_IE_GMM_PDP_CTX_STATUS = 0x32, /* 10.5.7.1 */
+ GSM48_IE_GMM_PS_LCS_CAPA = 0x33, /* 10.5.5.22 */
+ GSM48_IE_GMM_GMM_MBMS_CTX_ST = 0x35, /* 10.5.7.6 */
+};
+
+enum gsm48_gprs_ie_sm {
+ GSM48_IE_GSM_APN = 0x28, /* 10.5.6.1 */
+ GSM48_IE_GSM_PROTO_CONF_OPT = 0x27, /* 10.5.6.3 */
+ GSM48_IE_GSM_PDP_ADDR = 0x2b, /* 10.5.6.4 */
+ GSM48_IE_GSM_AA_TMR = 0x29, /* 10.5.7.3 */
+ GSM48_IE_GSM_NAME_FULL = 0x43, /* 10.5.3.5a */
+ GSM48_IE_GSM_NAME_SHORT = 0x45, /* 10.5.3.5a */
+ GSM48_IE_GSM_TIMEZONE = 0x46, /* 10.5.3.8 */
+ GSM48_IE_GSM_UTC_AND_TZ = 0x47, /* 10.5.3.9 */
+ GSM48_IE_GSM_LSA_ID = 0x48, /* 10.5.3.11 */
+
+ /* Fake IEs that are not present on the Layer3 air interface,
+ * but which we use to simplify internal APIs */
+ OSMO_IE_GSM_REQ_QOS = 0xfd,
+ OSMO_IE_GSM_REQ_PDP_ADDR = 0xfe,
+};
+
+/* Chapter 9.4.15 / Table 9.4.15 */
+struct gsm48_ra_upd_ack {
+ uint8_t force_stby:4, /* 10.5.5.7 */
+ upd_result:4; /* 10.5.5.17 */
+ uint8_t ra_upd_timer; /* 10.5.7.3 */
+ struct gsm48_ra_id ra_id; /* 10.5.5.15 */
+ uint8_t data[0];
+} __attribute__((packed));
+
+/* Chapter 10.5.7.3 */
+enum gsm48_gprs_tmr_unit {
+ GPRS_TMR_2SECONDS = 0 << 5,
+ GPRS_TMR_MINUTE = 1 << 5,
+ GPRS_TMR_6MINUTE = 2 << 5,
+ GPRS_TMR_DEACTIVATED = 3 << 5,
+};
+
+/* Chapter 9.4.2 / Table 9.4.2 */
+struct gsm48_attach_ack {
+ uint8_t att_result:4, /* 10.5.5.7 */
+ force_stby:4; /* 10.5.5.1 */
+ uint8_t ra_upd_timer; /* 10.5.7.3 */
+ uint8_t radio_prio; /* 10.5.7.2 */
+ struct gsm48_ra_id ra_id; /* 10.5.5.15 */
+ uint8_t data[0];
+} __attribute__((packed));
+
+/* Chapter 9.4.9 / Table 9.4.9 */
+struct gsm48_auth_ciph_req {
+ uint8_t ciph_alg:4, /* 10.5.5.3 */
+ imeisv_req:4; /* 10.5.5.10 */
+ uint8_t force_stby:4, /* 10.5.5.7 */
+ ac_ref_nr:4; /* 10.5.5.19 */
+ uint8_t data[0];
+} __attribute__((packed));
+/* optional: TV RAND, TV CKSN */
+
+struct gsm48_auth_ciph_resp {
+ uint8_t ac_ref_nr:4,
+ spare:4;
+ uint8_t data[0];
+} __attribute__((packed));
+
+/* Chapter 9.5.1 / Table 9.5.1 */
+struct gsm48_act_pdp_ctx_req {
+ uint8_t req_nsapi;
+ uint8_t req_llc_sapi;
+ uint8_t data[0];
+} __attribute__((packed));
+
+/* Chapter 10.5.5.14 / Table 10.5.147 */
+enum gsm48_gmm_cause {
+ GMM_CAUSE_IMSI_UNKNOWN = 0x02,
+ GMM_CAUSE_ILLEGAL_MS = 0x03,
+ GMM_CAUSE_ILLEGAL_ME = 0x06,
+ GMM_CAUSE_GPRS_NOTALLOWED = 0x07,
+ GMM_CAUSE_GPRS_OTHER_NOTALLOWED = 0x08,
+ GMM_CAUSE_MS_ID_NOT_DERIVED = 0x09,
+ GMM_CAUSE_IMPL_DETACHED = 0x0a,
+ GMM_CAUSE_PLMN_NOTALLOWED = 0x0b,
+ GMM_CAUSE_LA_NOTALLOWED = 0x0c,
+ GMM_CAUSE_ROAMING_NOTALLOWED = 0x0d,
+ GMM_CAUSE_NO_GPRS_PLMN = 0x0e,
+ GMM_CAUSE_MSC_TEMP_NOTREACH = 0x10,
+ GMM_CAUSE_NET_FAIL = 0x11,
+ GMM_CAUSE_CONGESTION = 0x16,
+ GMM_CAUSE_SEM_INCORR_MSG = 0x5f,
+ GMM_CAUSE_INV_MAND_INFO = 0x60,
+ GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL = 0x61,
+ GMM_CAUSE_MSGT_INCOMP_P_STATE = 0x62,
+ GMM_CAUSE_IE_NOTEXIST_NOTIMPL = 0x63,
+ GMM_CAUSE_COND_IE_ERR = 0x64,
+ GMM_CAUSE_MSG_INCOMP_P_STATE = 0x65,
+ GMM_CAUSE_PROTO_ERR_UNSPEC = 0x6f,
+};
+
+/* Chapter 10.4.6.6 / Table 10.5.157 */
+enum gsm48_gsm_cause {
+ GSM_CAUSE_INSUFF_RSRC = 0x1a,
+ GSM_CAUSE_MISSING_APN = 0x1b,
+ GSM_CAUSE_UNKNOWN_PDP = 0x1c,
+ GSM_CAUSE_AUTH_FAILED = 0x1d,
+ GSM_CAUSE_ACT_REJ_GGSN = 0x1e,
+ GSM_CAUSE_ACT_REJ_UNSPEC = 0x1f,
+ GSM_CAUSE_SERV_OPT_NOTSUPP = 0x20,
+ GSM_CAUSE_REQ_SERV_OPT_NOTSUB = 0x21,
+ GSM_CAUSE_SERV_OPT_TEMP_OOO = 0x22,
+ GSM_CAUSE_NSAPI_IN_USE = 0x23,
+ GSM_CAUSE_DEACT_REGULAR = 0x24,
+ GSM_CAUSE_QOS_NOT_ACCEPTED = 0x25,
+ GSM_CAUSE_NET_FAIL = 0x26,
+ GSM_CAUSE_REACT_RQD = 0x27,
+ GSM_CAUSE_FEATURE_NOTSUPP = 0x28,
+ GSM_CAUSE_INVALID_TRANS_ID = 0x51,
+ GSM_CAUSE_SEM_INCORR_MSG = 0x5f,
+ GSM_CAUSE_INV_MAND_INFO = 0x60,
+ GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL = 0x61,
+ GSM_CAUSE_MSGT_INCOMP_P_STATE = 0x62,
+ GSM_CAUSE_IE_NOTEXIST_NOTIMPL = 0x63,
+ GSM_CAUSE_COND_IE_ERR = 0x64,
+ GSM_CAUSE_MSG_INCOMP_P_STATE = 0x65,
+ GSM_CAUSE_PROTO_ERR_UNSPEC = 0x6f,
+};
+
+/* Section 6.1.2.2: Session management states on the network side */
+enum gsm48_pdp_state {
+ PDP_S_INACTIVE,
+ PDP_S_ACTIVE_PENDING,
+ PDP_S_ACTIVE,
+ PDP_S_INACTIVE_PENDING,
+ PDP_S_MODIFY_PENDING,
+};
+
+/* Table 10.5.155/3GPP TS 24.008 */
+enum gsm48_pdp_type_org {
+ PDP_TYPE_ORG_ETSI = 0x00,
+ PDP_TYPE_ORG_IETF = 0x01,
+};
+enum gsm48_pdp_type_nr {
+ PDP_TYPE_N_ETSI_RESERVED = 0x00,
+ PDP_TYPE_N_ETSI_PPP = 0x01,
+ PDP_TYPE_N_IETF_IPv4 = 0x21,
+ PDP_TYPE_N_IETF_IPv6 = 0x57,
+};
+
+/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
+enum gsm48_qos_reliab_class {
+ GSM48_QOS_RC_LLC_ACK_RLC_ACK_DATA_PROT = 2,
+ GSM48_QOS_RC_LLC_UN_RLC_ACK_DATA_PROT = 3,
+ GSM48_QOS_RC_LLC_UN_RLC_UN_PROT_DATA = 4,
+ GSM48_QOS_RC_LLC_UN_RLC_UN_DATA_UN = 5,
+};
+
+/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
+enum gsm48_qos_preced_class {
+ GSM48_QOS_PC_HIGH = 1,
+ GSM48_QOS_PC_NORMAL = 2,
+ GSM48_QOS_PC_LOW = 3,
+};
+
+/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
+enum gsm48_qos_peak_tput {
+ GSM48_QOS_PEAK_TPUT_1000bps = 1,
+ GSM48_QOS_PEAK_TPUT_2000bps = 2,
+ GSM48_QOS_PEAK_TPUT_4000bps = 3,
+ GSM48_QOS_PEAK_TPUT_8000bps = 4,
+ GSM48_QOS_PEAK_TPUT_16000bps = 5,
+ GSM48_QOS_PEAK_TPUT_32000bps = 6,
+ GSM48_QOS_PEAK_TPUT_64000bps = 7,
+ GSM48_QOS_PEAK_TPUT_128000bps = 8,
+ GSM48_QOS_PEAK_TPUT_256000bps = 9,
+};
+
+/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
+enum gsm48_qos_mean_tput {
+ GSM48_QOS_MEAN_TPUT_100bph = 1,
+ GSM48_QOS_MEAN_TPUT_200bph = 2,
+ GSM48_QOS_MEAN_TPUT_500bph = 3,
+ GSM48_QOS_MEAN_TPUT_1000bph = 4,
+ GSM48_QOS_MEAN_TPUT_2000bph = 5,
+ GSM48_QOS_MEAN_TPUT_5000bph = 6,
+ GSM48_QOS_MEAN_TPUT_10000bph = 7,
+ GSM48_QOS_MEAN_TPUT_20000bph = 8,
+ GSM48_QOS_MEAN_TPUT_50000bph = 9,
+ GSM48_QOS_MEAN_TPUT_100kbph = 10,
+ GSM48_QOS_MEAN_TPUT_200kbph = 11,
+ GSM48_QOS_MEAN_TPUT_500kbph = 0xc,
+ GSM48_QOS_MEAN_TPUT_1Mbph = 0xd,
+ GSM48_QOS_MEAN_TPUT_2Mbph = 0xe,
+ GSM48_QOS_MEAN_TPUT_5Mbph = 0xf,
+ GSM48_QOS_MEAN_TPUT_10Mbph = 0x10,
+ GSM48_QOS_MEAN_TPUT_20Mbph = 0x11,
+ GSM48_QOS_MEAN_TPUT_50Mbph = 0x12,
+ GSM48_QOS_MEAN_TPUT_BEST_EFFORT = 0x1f,
+};
+
+/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
+enum gsm48_qos_err_sdu {
+ GSM48_QOS_ERRSDU_NODETECT = 1,
+ GSM48_QOS_ERRSDU_YES = 2,
+ GSM48_QOS_ERRSDU_NO = 3,
+};
+
+/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
+enum gsm48_qos_deliv_order {
+ GSM48_QOS_DO_ORDERED = 1,
+ GSM48_QOS_DO_UNORDERED = 2,
+};
+
+/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
+enum gsm48_qos_traf_class {
+ GSM48_QOS_TC_CONVERSATIONAL = 1,
+ GSM48_QOS_TC_STREAMING = 2,
+ GSM48_QOS_TC_INTERACTIVE = 3,
+ GSM48_QOS_TC_BACKGROUND = 4,
+};
+
+/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
+enum gsm48_qos_max_sdu_size {
+ /* values below in 10 octet granularity */
+ GSM48_QOS_MAXSDU_1502 = 0x97,
+ GSM48_QOS_MAXSDU_1510 = 0x98,
+ GSM48_QOS_MAXSDU_1520 = 0x99,
+};
+
+/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
+enum gsm48_qos_max_bitrate {
+ GSM48_QOS_MBRATE_1k = 0x01,
+ GSM48_QOS_MBRATE_63k = 0x3f,
+ GSM48_QOS_MBRATE_64k = 0x40,
+ GSM48_QOS_MBRATE_568k = 0x7f,
+ GSM48_QOS_MBRATE_576k = 0x80,
+ GSM48_QOS_MBRATE_8640k = 0xfe,
+ GSM48_QOS_MBRATE_0k = 0xff,
+};
+
+/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
+enum gsm48_qos_resid_ber {
+ GSM48_QOS_RBER_5e_2 = 0x01,
+ GSM48_QOS_RBER_1e_2 = 0x02,
+ GSM48_QOS_RBER_5e_3 = 0x03,
+ GSM48_QOS_RBER_4e_3 = 0x04,
+ GSM48_QOS_RBER_1e_3 = 0x05,
+ GSM48_QOS_RBER_1e_4 = 0x06,
+ GSM48_QOS_RBER_1e_5 = 0x07,
+ GSM48_QOS_RBER_1e_6 = 0x08,
+ GSM48_QOS_RBER_6e_8 = 0x09,
+};
+
+/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
+enum gsm48_qos_sdu_err {
+ GSM48_QOS_SERR_1e_2 = 0x01,
+ GSM48_QOS_SERR_7e_2 = 0x02,
+ GSM48_QOS_SERR_1e_3 = 0x03,
+ GSM48_QOS_SERR_1e_4 = 0x04,
+ GSM48_QOS_SERR_1e_5 = 0x05,
+ GSM48_QOS_SERR_1e_6 = 0x06,
+ GSM48_QOS_SERR_1e_1 = 0x07,
+};
+
+/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
+struct gsm48_qos {
+ /* octet 3 */
+ uint8_t reliab_class:3;
+ uint8_t delay_class:3;
+ uint8_t spare:2;
+ /* octet 4 */
+ uint8_t preced_class:3;
+ uint8_t spare2:1;
+ uint8_t peak_tput:4;
+ /* octet 5 */
+ uint8_t mean_tput:5;
+ uint8_t spare3:3;
+ /* octet 6 */
+ uint8_t deliv_err_sdu:3;
+ uint8_t deliv_order:2;
+ uint8_t traf_class:3;
+ /* octet 7 */
+ uint8_t max_sdu_size;
+ /* octet 8 */
+ uint8_t max_bitrate_up;
+ /* octet 9 */
+ uint8_t max_bitrate_down;
+ /* octet 10 */
+ uint8_t sdu_err_ratio:4;
+ uint8_t resid_ber:4;
+ /* octet 11 */
+ uint8_t handling_prio:2;
+ uint8_t xfer_delay:6;
+ /* octet 12 */
+ uint8_t guar_bitrate_up;
+ /* octet 13 */
+ uint8_t guar_bitrate_down;
+ /* octet 14 */
+ uint8_t src_stats_desc:4;
+ uint8_t sig_ind:1;
+ uint8_t spare5:3;
+ /* octet 15 */
+ uint8_t max_bitrate_down_ext;
+ /* octet 16 */
+ uint8_t guar_bitrate_down_ext;
+};
+
+
+int gprs_tlli_type(uint32_t tlli);
+
+#endif /* _GSM48_GPRS_H */
diff --git a/include/openbsc/gsm_04_11.h b/include/openbsc/gsm_04_11.h
new file mode 100644
index 00000000..5969788d
--- /dev/null
+++ b/include/openbsc/gsm_04_11.h
@@ -0,0 +1,40 @@
+#ifndef _GSM_04_11_H
+#define _GSM_04_11_H
+
+#include <osmocore/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 */
+ /* service centre time stamp */
+ u_int8_t ud_len; /* user data length */
+ u_int8_t *user_data; /* user data */
+
+ u_int8_t msg_ref; /* message reference */
+ u_int8_t *smsc;
+};
+
+struct msgb;
+
+int gsm0411_rcv_sms(struct gsm_subscriber_connection *conn, struct msgb *msg);
+
+struct gsm_sms *sms_alloc(void);
+void sms_free(struct gsm_sms *sms);
+struct gsm_sms *sms_from_text(struct gsm_subscriber *receiver, int dcs, const char *text);
+
+void _gsm411_sms_trans_free(struct gsm_trans *trans);
+int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
+ struct gsm_sms *sms);
+int gsm411_send_sms(struct gsm_subscriber_connection *conn,
+ struct gsm_sms *sms);
+void gsm411_sapi_n_reject(struct gsm_subscriber_connection *conn);
+#endif
diff --git a/include/openbsc/gsm_04_80.h b/include/openbsc/gsm_04_80.h
new file mode 100644
index 00000000..796a1c11
--- /dev/null
+++ b/include/openbsc/gsm_04_80.h
@@ -0,0 +1,20 @@
+#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>
+
+struct gsm_subscriber_connection;
+
+int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn,
+ const struct msgb *in_msg, const char* response_text,
+ const struct ussd_request *req);
+int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn,
+ const struct msgb *msg,
+ const struct ussd_request *request);
+
+int gsm0480_send_ussdNotify(struct gsm_subscriber_connection *conn, int level, const char *text);
+int gsm0480_send_releaseComplete(struct gsm_subscriber_connection *conn);
+
+#endif
diff --git a/include/openbsc/gsm_data.h b/include/openbsc/gsm_data.h
new file mode 100644
index 00000000..ae448c4c
--- /dev/null
+++ b/include/openbsc/gsm_data.h
@@ -0,0 +1,879 @@
+#ifndef _GSM_DATA_H
+#define _GSM_DATA_H
+
+#include <sys/types.h>
+
+struct osmo_msc_data;
+struct osmo_bsc_sccp_con;
+struct gsm_sms_queue;
+
+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]
+
+/* the data structure stored in msgb->cb for openbsc apps */
+struct openbsc_msgb_cb {
+ unsigned char *bssgph;
+ unsigned char *llch;
+
+ /* Cell Identifier */
+ unsigned char *bssgp_cell_id;
+
+ /* Identifiers of a BTS, equal to 'struct bssgp_bts_ctx' */
+ u_int16_t nsei;
+ u_int16_t bvci;
+
+ /* Identifier of a MS (inside BTS), equal to 'struct sgsn_mm_ctx' */
+ u_int32_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
+#define msgb_nsei(__x) OBSC_MSGB_CB(__x)->nsei
+#define msgb_bvci(__x) OBSC_MSGB_CB(__x)->bvci
+#define msgb_gmmh(__x) (__x)->l3h
+#define msgb_bssgph(__x) OBSC_MSGB_CB(__x)->bssgph
+#define msgb_bssgp_len(__x) ((__x)->tail - (uint8_t *)msgb_bssgph(__x))
+#define msgb_bcid(__x) OBSC_MSGB_CB(__x)->bssgp_cell_id
+#define msgb_llch(__x) OBSC_MSGB_CB(__x)->llch
+
+#define OBSC_LINKID_CB(__msgb) (__msgb)->cb[3]
+
+enum gsm_security_event {
+ GSM_SECURITY_NOAVAIL,
+ GSM_SECURITY_AUTH_FAILED,
+ GSM_SECURITY_SUCCEEDED,
+};
+
+struct msgb;
+typedef int gsm_cbfn(unsigned int hooknum,
+ unsigned int event,
+ struct msgb *msg,
+ void *data, void *param);
+
+/* Real authentication information containing Ki */
+enum gsm_auth_algo {
+ AUTH_ALGO_NONE,
+ AUTH_ALGO_XOR,
+ AUTH_ALGO_COMP128v1,
+};
+
+struct gsm_auth_info {
+ enum gsm_auth_algo auth_algo;
+ unsigned int a3a8_ki_len;
+ u_int8_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];
+};
+#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
+ *
+ * Our current operation is:
+ * - Get imei/tmsi
+ * - Accept/Reject according to global policy
+ */
+struct gsm_loc_updating_operation {
+ struct timer_list updating_timer;
+ unsigned int waiting_for_imsi : 1;
+ unsigned int waiting_for_imei : 1;
+ unsigned int key_seq : 4;
+};
+
+/*
+ * AUTHENTICATION/CIPHERING state
+ */
+struct gsm_security_operation {
+ struct gsm_auth_tuple atuple;
+ gsm_cbfn *cb;
+ void *cb_data;
+};
+
+/*
+ * A dummy to keep a connection up for at least
+ * a couple of seconds to work around MSC issues.
+ */
+struct gsm_anchor_operation {
+ struct timer_list timeout;
+};
+
+/* Maximum number of neighbor cells whose average we track */
+#define MAX_NEIGH_MEAS 10
+/* Maximum size of the averaging window for neighbor cells */
+#define MAX_WIN_NEIGH_AVG 10
+
+/* processed neighbor measurements for one cell */
+struct neigh_meas_proc {
+ u_int16_t arfcn;
+ u_int8_t bsic;
+ u_int8_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 */
+};
+
+/* the per subscriber data for lchan */
+struct gsm_subscriber_connection {
+ struct llist_head entry;
+
+ /* To whom we are allocated at the moment */
+ struct gsm_subscriber *subscr;
+
+ /*
+ * Operations that have a state and might be pending
+ */
+ struct gsm_loc_updating_operation *loc_operation;
+ struct gsm_security_operation *sec_operation;
+ struct gsm_anchor_operation *anch_operation;
+
+ /* Are we part of a special "silent" call */
+ int silent_call;
+ int put_channel;
+
+ /* bsc structures */
+ struct osmo_bsc_sccp_con *sccp_con;
+
+ /* back pointers */
+ int in_release;
+ struct gsm_lchan *lchan;
+ struct gsm_lchan *ho_lchan;
+ struct gsm_bts *bts;
+
+ /* for assignment handling */
+ struct 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;
+
+ /* 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;
+ } 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 */
+ } handover;
+ struct {
+ struct counter *attach;
+ struct counter *normal;
+ struct counter *periodic;
+ struct counter *detach;
+ } loc_upd_type;
+ struct {
+ struct counter *reject;
+ struct counter *accept;
+ } loc_upd_resp;
+ struct {
+ struct counter *attempted;
+ struct counter *detached;
+ struct counter *completed;
+ struct 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;
+ } sms;
+ struct {
+ struct counter *mo_setup;
+ struct counter *mo_connect_ack;
+ struct counter *mt_setup;
+ struct counter *mt_connect;
+ } call;
+ struct {
+ struct counter *rf_fail;
+ struct counter *rll_err;
+ } chan;
+ struct {
+ struct counter *oml_fail;
+ struct counter *rsl_fail;
+ } bts;
+};
+
+enum gsm_auth_policy {
+ GSM_AUTH_POLICY_CLOSED, /* only subscribers authorized in DB */
+ GSM_AUTH_POLICY_ACCEPT_ALL, /* accept everyone, even if not authorized in DB */
+ GSM_AUTH_POLICY_TOKEN, /* accept first, send token per sms, then revoke authorization */
+};
+
+#define GSM_T3101_DEFAULT 10
+#define GSM_T3113_DEFAULT 60
+
+struct gsm_network {
+ /* global parameters */
+ u_int16_t country_code;
+ u_int16_t network_code;
+ char *name_long;
+ char *name_short;
+ enum gsm_auth_policy auth_policy;
+ enum gsm48_reject_value reject_cause;
+ int a5_encryption;
+ int neci;
+ int send_mm_info;
+ struct {
+ int active;
+ /* Window RXLEV averaging */
+ unsigned int win_rxlev_avg; /* number of SACCH frames */
+ /* Window RXQUAL averaging */
+ unsigned int win_rxqual_avg; /* number of SACCH frames */
+ /* Window RXLEV neighbouring cells averaging */
+ unsigned int win_rxlev_avg_neigh; /* number of SACCH frames */
+
+ /* how often should we check for power budget HO */
+ unsigned int pwr_interval; /* SACCH frames */
+ /* how much better does a neighbor cell have to be ? */
+ unsigned int pwr_hysteresis; /* dBm */
+ /* maximum distacne before we try a handover */
+ unsigned int max_distance; /* TA values */
+ } handover;
+
+ struct gsmnet_stats stats;
+
+ /* layer 4 */
+ int (*mncc_recv) (struct gsm_network *net, struct msgb *msg);
+ struct llist_head upqueue;
+ struct llist_head trans_list;
+ struct bsc_api *bsc_api;
+
+ unsigned int num_bts;
+ struct llist_head bts_list;
+
+ /* timer values */
+ int T3101;
+ int T3103;
+ int T3105;
+ int T3107;
+ int T3109;
+ int T3111;
+ int T3113;
+ int T3115;
+ int T3117;
+ int T3119;
+ int T3122;
+ int T3141;
+
+ /* Radio Resource Location Protocol (TS 04.31) */
+ struct {
+ enum rrlp_mode mode;
+ } rrlp;
+
+ /* enable the DTXu and DTXd for this network */
+ int dtx_enabled;
+
+ enum gsm_chan_t ctype_by_chreq[16];
+
+ /* Use a TCH for handling requests of type paging any */
+ int pag_any_tch;
+
+ /* MSC data in case we are a true BSC */
+ struct osmo_msc_data *msc_data;
+ int hardcoded_rtp_payload;
+
+ /* subscriber related features */
+ int keep_subscr;
+ struct gsm_sms_queue *sms_queue;
+};
+
+#define SMS_HDR_SIZE 128
+#define SMS_TEXT_SIZE 256
+struct gsm_sms {
+ unsigned long long id;
+ struct gsm_subscriber *sender;
+ 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;
+ 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];
+
+ char text[SMS_TEXT_SIZE];
+};
+
+
+struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_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);
+
+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);
+
+extern void *tall_bsc_ctx;
+extern int ipacc_rtp_direct;
+
+static inline int is_ipaccess_bts(struct gsm_bts *bts)
+{
+ switch (bts->type) {
+ case GSM_BTS_TYPE_NANOBTS:
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static inline int is_siemens_bts(struct gsm_bts *bts)
+{
+ switch (bts->type) {
+ case GSM_BTS_TYPE_BS11:
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+enum gsm_auth_policy gsm_auth_policy_parse(const char *arg);
+const char *gsm_auth_policy_name(enum gsm_auth_policy policy);
+
+enum rrlp_mode rrlp_mode_parse(const char *arg);
+const char *rrlp_mode_name(enum rrlp_mode mode);
+
+enum bts_gprs_mode bts_gprs_mode_parse(const char *arg);
+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);
+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
diff --git a/include/openbsc/gsm_subscriber.h b/include/openbsc/gsm_subscriber.h
new file mode 100644
index 00000000..c365bc7d
--- /dev/null
+++ b/include/openbsc/gsm_subscriber.h
@@ -0,0 +1,107 @@
+#ifndef _GSM_SUBSCR_H
+#define _GSM_SUBSCR_H
+
+#include <sys/types.h>
+#include "gsm_data.h"
+#include <osmocore/linuxlist.h>
+
+#define GSM_IMEI_LENGTH 17
+#define GSM_IMSI_LENGTH 17
+#define GSM_NAME_LENGTH 160
+
+#define GSM_EXTENSION_LENGTH 15 /* MSISDN can only be 15 digits length */
+#define GSM_MIN_EXTEN 20000
+#define GSM_MAX_EXTEN 49999
+
+#define GSM_SUBSCRIBER_FIRST_CONTACT 0x00000001
+#define tmsi_from_string(str) strtoul(str, NULL, 10)
+
+struct vty;
+
+struct gsm_equipment {
+ long long unsigned int id;
+ char imei[GSM_IMEI_LENGTH];
+ 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];
+};
+
+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;
+ 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;
+
+ /* Every user can only have one equipment in use at any given
+ * point in time */
+ struct gsm_equipment equipment;
+
+ /* for internal management */
+ int use_count;
+ struct llist_head entry;
+
+ /* pending requests */
+ int in_callback;
+ struct llist_head requests;
+};
+
+enum gsm_subscriber_field {
+ GSM_SUBSCRIBER_IMSI,
+ GSM_SUBSCRIBER_TMSI,
+ GSM_SUBSCRIBER_EXTENSION,
+ GSM_SUBSCRIBER_ID,
+};
+
+enum gsm_subscriber_update_reason {
+ GSM_SUBSCRIBER_UPDATE_ATTACHED,
+ GSM_SUBSCRIBER_UPDATE_DETACHED,
+ GSM_SUBSCRIBER_UPDATE_EQUIPMENT,
+};
+
+struct 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);
+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,
+ const char *ext);
+struct gsm_subscriber *subscr_get_by_id(struct gsm_network *net,
+ unsigned long long id);
+struct gsm_subscriber *subscr_get_or_create(struct gsm_network *net,
+ const char *imsi);
+int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason);
+void subscr_put_channel(struct gsm_subscriber *subscr);
+void subscr_get_channel(struct gsm_subscriber *subscr,
+ int type, gsm_cbfn *cbfn, void *param);
+struct gsm_subscriber *subscr_active_by_tmsi(struct gsm_network *net,
+ uint32_t tmsi);
+struct gsm_subscriber *subscr_active_by_imsi(struct gsm_network *net,
+ const char *imsi);
+
+int subscr_pending_requests(struct gsm_subscriber *subscr);
+int subscr_pending_clear(struct gsm_subscriber *subscr);
+int subscr_pending_dump(struct gsm_subscriber *subscr, struct vty *vty);
+int subscr_pending_kick(struct gsm_subscriber *subscr);
+
+char *subscr_name(struct gsm_subscriber *subscr);
+
+int subscr_purge_inactive(struct gsm_network *net);
+void subscr_update_from_db(struct gsm_subscriber *subscr);
+
+/* internal */
+struct gsm_subscriber *subscr_alloc(void);
+extern struct llist_head active_subscribers;
+
+#endif /* _GSM_SUBSCR_H */
diff --git a/include/openbsc/handover.h b/include/openbsc/handover.h
new file mode 100644
index 00000000..9d9a90b8
--- /dev/null
+++ b/include/openbsc/handover.h
@@ -0,0 +1,14 @@
+#ifndef _HANDOVER_H
+#define _HANDOVER_H
+
+struct gsm_subscriber_connection;
+
+/* Hand over the specified logical channel to the specified new BTS.
+ * This is the main entry point for the actual handover algorithm,
+ * after it has decided it wants to initiate HO to a specific BTS */
+int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts);
+
+/* clear any operation for this connection */
+void bsc_clear_handover(struct gsm_subscriber_connection *conn, int free_lchan);
+
+#endif /* _HANDOVER_H */
diff --git a/include/openbsc/ipaccess.h b/include/openbsc/ipaccess.h
new file mode 100644
index 00000000..1d00d979
--- /dev/null
+++ b/include/openbsc/ipaccess.h
@@ -0,0 +1,131 @@
+#ifndef _IPACCESS_H
+#define _IPACCESS_H
+
+#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,
+};
+
+struct ipac_msgt_sccp_state {
+ uint8_t src_ref[3];
+ uint8_t dst_ref[3];
+ uint8_t trans_id;
+ uint8_t invoke_id;
+ char imsi[GSM_IMSI_LENGTH];
+} __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);
+void ipaccess_prepend_header(struct msgb *msg, int proto);
+int ipaccess_send_id_ack(int fd);
+int ipaccess_send_id_req(int fd);
+
+int ipaccess_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len);
+
+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;
+ off_t absolute_offset;
+};
+
+struct sdp_header {
+ struct sdp_firmware firmware_info;
+
+ /* for more_magic a list of sdp_header_entry_list */
+ struct llist_head header_list;
+
+ /* the entry of the sdp_header */
+ struct llist_head entry;
+};
+
+int ipaccess_analyze_file(int fd, const unsigned int st_size, const unsigned base_offset, struct llist_head *list);
+
+#endif /* _IPACCESS_H */
diff --git a/include/openbsc/meas_rep.h b/include/openbsc/meas_rep.h
new file mode 100644
index 00000000..3c2c8d1c
--- /dev/null
+++ b/include/openbsc/meas_rep.h
@@ -0,0 +1,85 @@
+#ifndef _MEAS_REP_H
+#define _MEAS_REP_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;
+ unsigned int flags;
+};
+
+/* RX Level and RX Quality */
+struct gsm_rx_lev_qual {
+ u_int8_t rx_lev;
+ u_int8_t rx_qual;
+};
+
+/* unidirectional measumrement report */
+struct gsm_meas_rep_unidir {
+ struct gsm_rx_lev_qual full;
+ struct gsm_rx_lev_qual sub;
+};
+
+#define MEAS_REP_F_UL_DTX 0x01
+#define MEAS_REP_F_DL_VALID 0x02
+#define MEAS_REP_F_BA1 0x04
+#define MEAS_REP_F_DL_DTX 0x08
+#define MEAS_REP_F_MS_TO 0x10
+#define MEAS_REP_F_MS_L1 0x20
+#define MEAS_REP_F_FPC 0x40
+
+/* parsed uplink and downlink measurement result */
+struct gsm_meas_rep {
+ /* back-pointer to the logical channel */
+ struct gsm_lchan *lchan;
+
+ /* number of the measurement report */
+ u_int8_t nr;
+ /* flags, see MEAS_REP_F_* */
+ unsigned int flags;
+
+ /* uplink and downlink rxlev, rxqual; full and sub */
+ struct gsm_meas_rep_unidir ul;
+ struct gsm_meas_rep_unidir dl;
+
+ u_int8_t bs_power;
+ u_int8_t ms_timing_offset;
+ struct {
+ int8_t pwr; /* MS power in dBm */
+ u_int8_t ta; /* MS timing advance */
+ } ms_l1;
+
+ /* neighbor measurement reports for up to 6 cells */
+ int num_cell;
+ struct gsm_meas_rep_cell cell[6];
+};
+
+enum meas_rep_field {
+ MEAS_REP_DL_RXLEV_FULL,
+ MEAS_REP_DL_RXLEV_SUB,
+ MEAS_REP_DL_RXQUAL_FULL,
+ MEAS_REP_DL_RXQUAL_SUB,
+ MEAS_REP_UL_RXLEV_FULL,
+ MEAS_REP_UL_RXLEV_SUB,
+ MEAS_REP_UL_RXQUAL_FULL,
+ MEAS_REP_UL_RXQUAL_SUB,
+};
+
+/* obtain an average over the last 'num' fields in the meas reps */
+int get_meas_rep_avg(const struct gsm_lchan *lchan,
+ enum meas_rep_field field, unsigned int num);
+
+/* Check if N out of M last values for FIELD are >= bd */
+int meas_rep_n_out_of_m_be(const struct gsm_lchan *lchan,
+ enum meas_rep_field field,
+ unsigned int n, unsigned int m, int be);
+
+unsigned int calc_initial_idx(unsigned int array_size,
+ unsigned int meas_rep_idx,
+ unsigned int num_values);
+
+#endif /* _MEAS_REP_H */
diff --git a/include/openbsc/mgcp.h b/include/openbsc/mgcp.h
new file mode 100644
index 00000000..516b76ed
--- /dev/null
+++ b/include/openbsc/mgcp.h
@@ -0,0 +1,194 @@
+/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
+
+/*
+ * (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2011 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef OPENBSC_MGCP_H
+#define OPENBSC_MGCP_H
+
+#include <osmocore/msgb.h>
+#include <osmocore/write_queue.h>
+
+#include "debug.h"
+
+#include <arpa/inet.h>
+
+#define RTP_PORT_DEFAULT 4000
+#define RTP_PORT_NET_DEFAULT 16000
+
+/**
+ * Calculate the RTP audio port for the given multiplex
+ * and the direction. This allows a semi static endpoint
+ * to port calculation removing the need for the BSC
+ * and the MediaGateway to communicate.
+ *
+ * Port usage explained:
+ * base + (multiplex * 2) + 0 == local port to wait for network packets
+ * base + (multiplex * 2) + 1 == local port for rtcp
+ *
+ * The above port will receive packets from the BTS that need
+ * to be patched and forwarded to the network.
+ * The above port will receive packets from the network that
+ * need to be patched and forwarded to the BTS.
+ *
+ * We assume to have a static BTS IP address so we can differentiate
+ * network and BTS.
+ *
+ */
+static inline int rtp_calculate_port(int multiplex, int base)
+{
+ return base + (multiplex * 2);
+}
+
+
+/*
+ * Handling of MGCP Endpoints and the MGCP Config
+ */
+struct mgcp_endpoint;
+struct mgcp_config;
+struct mgcp_trunk_config;
+
+#define MGCP_ENDP_CRCX 1
+#define MGCP_ENDP_DLCX 2
+#define MGCP_ENDP_MDCX 3
+
+/*
+ * what to do with the msg?
+ * - continue as usual?
+ * - reject and send a failure code?
+ * - defer? do not send anything
+ */
+#define MGCP_POLICY_CONT 4
+#define MGCP_POLICY_REJECT 5
+#define MGCP_POLICY_DEFER 6
+
+typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint);
+typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state);
+typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id);
+typedef int (*mgcp_reset)(struct mgcp_config *cfg);
+
+#define PORT_ALLOC_STATIC 0
+#define PORT_ALLOC_DYNAMIC 1
+
+/**
+ * This holds information on how to allocate ports
+ */
+struct mgcp_port_range {
+ int mode;
+
+ /* pre-allocated from a base? */
+ int base_port;
+
+ /* dynamically allocated */
+ int range_start;
+ int range_end;
+ int last_port;
+};
+
+struct mgcp_trunk_config {
+ struct llist_head entry;
+
+ struct mgcp_config *cfg;
+
+ int trunk_nr;
+ int trunk_type;
+
+ char *audio_name;
+ int audio_payload;
+ int audio_loop;
+
+ /* spec handling */
+ int force_realloc;
+
+ unsigned int number_endpoints;
+ struct mgcp_endpoint *endpoints;
+};
+
+struct mgcp_config {
+ int source_port;
+ char *local_ip;
+ char *source_addr;
+ char *bts_ip;
+ char *call_agent_addr;
+
+ struct in_addr bts_in;
+
+ /* transcoder handling */
+ char *transcoder_ip;
+ struct in_addr transcoder_in;
+ int transcoder_remote_base;
+
+ struct write_queue gw_fd;
+
+ struct mgcp_port_range bts_ports;
+ struct mgcp_port_range net_ports;
+ struct mgcp_port_range transcoder_ports;
+ int endp_dscp;
+
+ mgcp_change change_cb;
+ mgcp_policy policy_cb;
+ mgcp_reset reset_cb;
+ mgcp_realloc realloc_cb;
+ void *data;
+
+ uint32_t last_call_id;
+
+ /* trunk handling */
+ struct mgcp_trunk_config trunk;
+ struct llist_head trunks;
+
+ /* only used for start with a static configuration */
+ int last_net_port;
+ int last_bts_port;
+};
+
+/* config management */
+struct mgcp_config *mgcp_config_alloc(void);
+int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg);
+int mgcp_vty_init(void);
+int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg);
+void mgcp_free_endp(struct mgcp_endpoint *endp);
+int mgcp_reset_transcoder(struct mgcp_config *cfg);
+
+/*
+ * format helper functions
+ */
+struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
+struct msgb *mgcp_create_response_with_data(int code, const char *txt, const char *msg, const char *trans, const char *data);
+
+/* adc helper */
+static inline int mgcp_timeslot_to_endpoint(int multiplex, int timeslot)
+{
+ if (timeslot == 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Timeslot should not be 0\n");
+ timeslot = 255;
+ }
+
+ return timeslot + (32 * multiplex);
+}
+
+static inline void mgcp_endpoint_to_timeslot(int endpoint, int *multiplex, int *timeslot)
+{
+ *multiplex = endpoint / 32;
+ *timeslot = endpoint % 32;
+}
+
+
+#endif
diff --git a/include/openbsc/mgcp_internal.h b/include/openbsc/mgcp_internal.h
new file mode 100644
index 00000000..7c6bb542
--- /dev/null
+++ b/include/openbsc/mgcp_internal.h
@@ -0,0 +1,154 @@
+/* MGCP Private Data */
+
+/*
+ * (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2011 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef OPENBSC_MGCP_DATA_H
+#define OPENBSC_MGCP_DATA_H
+
+#include <osmocore/select.h>
+
+#define CI_UNUSED 0
+
+enum mgcp_connection_mode {
+ MGCP_CONN_NONE = 0,
+ MGCP_CONN_RECV_ONLY = 1,
+ MGCP_CONN_SEND_ONLY = 2,
+ MGCP_CONN_RECV_SEND = MGCP_CONN_RECV_ONLY | MGCP_CONN_SEND_ONLY,
+ MGCP_CONN_LOOPBACK = 4,
+};
+
+enum mgcp_trunk_type {
+ MGCP_TRUNK_VIRTUAL,
+ MGCP_TRUNK_E1,
+};
+
+struct mgcp_rtp_state {
+ int initialized;
+ int patch;
+
+ uint32_t orig_ssrc;
+ uint32_t ssrc;
+ uint16_t seq_no;
+ int lost_no;
+ int seq_offset;
+ uint32_t last_timestamp;
+ int32_t timestamp_offset;
+};
+
+struct mgcp_rtp_end {
+ /* statistics */
+ unsigned int packets;
+ struct in_addr addr;
+
+ /* in network byte order */
+ int rtp_port, rtcp_port;
+
+ int payload_type;
+
+ /*
+ * Each end has a socket...
+ */
+ struct bsc_fd rtp;
+ struct bsc_fd rtcp;
+
+ int local_port;
+ int local_alloc;
+};
+
+enum {
+ MGCP_TAP_BTS_IN,
+ MGCP_TAP_BTS_OUT,
+ MGCP_TAP_NET_IN,
+ MGCP_TAP_NET_OUT,
+
+ /* last element */
+ MGCP_TAP_COUNT
+};
+
+struct mgcp_rtp_tap {
+ int enabled;
+ struct sockaddr_in forward;
+};
+
+struct mgcp_endpoint {
+ int allocated;
+ uint32_t ci;
+ char *callid;
+ char *local_options;
+ int conn_mode;
+ int orig_mode;
+
+ /* backpointer */
+ struct mgcp_config *cfg;
+ struct mgcp_trunk_config *tcfg;
+
+ /* port status for bts/net */
+ struct mgcp_rtp_end bts_end;
+ struct mgcp_rtp_end net_end;
+
+ /*
+ * For transcoding we will send from the local_port
+ * of trans_bts and it will arrive at trans_net from
+ * where we will forward it to the network.
+ */
+ struct mgcp_rtp_end trans_bts;
+ struct mgcp_rtp_end trans_net;
+ int is_transcoded;
+
+ /* sequence bits */
+ struct mgcp_rtp_state net_state;
+ struct mgcp_rtp_state bts_state;
+
+ /* SSRC/seq/ts patching for loop */
+ int allow_patch;
+
+ /* tap for the endpoint */
+ struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
+};
+
+#define ENDPOINT_NUMBER(endp) abs(endp - endp->tcfg->endpoints)
+
+struct mgcp_msg_ptr {
+ unsigned int start;
+ unsigned int length;
+};
+
+int mgcp_analyze_header(struct mgcp_config *cfg, struct msgb *msg,
+ struct mgcp_msg_ptr *ptr, int size,
+ const char **transaction_id, struct mgcp_endpoint **endp);
+int mgcp_send_dummy(struct mgcp_endpoint *endp);
+int mgcp_bind_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
+int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
+int mgcp_bind_trans_bts_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
+int mgcp_bind_trans_net_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
+int mgcp_free_rtp_port(struct mgcp_rtp_end *end);
+
+/* For transcoding we need to manage an in and an output that are connected */
+static inline int endp_back_channel(int endpoint)
+{
+ return endpoint + 60;
+}
+
+struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index);
+struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
+
+
+#endif
diff --git a/include/openbsc/misdn.h b/include/openbsc/misdn.h
new file mode 100644
index 00000000..0a8b063a
--- /dev/null
+++ b/include/openbsc/misdn.h
@@ -0,0 +1,27 @@
+/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MISDN_H
+#define MISDN_H
+
+#include "e1_input.h"
+
+int mi_setup(int cardnr, struct e1inp_line *line, int release_l2);
+int mi_e1_line_update(struct e1inp_line *line);
+
+#endif
diff --git a/include/openbsc/mncc.h b/include/openbsc/mncc.h
new file mode 100644
index 00000000..e514c19a
--- /dev/null
+++ b/include/openbsc/mncc.h
@@ -0,0 +1,172 @@
+/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
+ * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
+
+/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _MNCC_H
+#define _MNCC_H
+
+#include <osmocore/linuxlist.h>
+#include <osmocore/mncc.h>
+
+#include <stdint.h>
+
+struct gsm_network;
+struct msgb;
+
+
+/* One end of a call */
+struct gsm_call {
+ struct llist_head entry;
+
+ /* network handle */
+ void *net;
+
+ /* the 'local' transaction */
+ uint32_t callref;
+ /* the 'remote' transaction */
+ uint32_t remote_ref;
+};
+
+#define MNCC_SETUP_REQ 0x0101
+#define MNCC_SETUP_IND 0x0102
+#define MNCC_SETUP_RSP 0x0103
+#define MNCC_SETUP_CNF 0x0104
+#define MNCC_SETUP_COMPL_REQ 0x0105
+#define MNCC_SETUP_COMPL_IND 0x0106
+/* MNCC_REJ_* is perfomed via MNCC_REL_* */
+#define MNCC_CALL_CONF_IND 0x0107
+#define MNCC_CALL_PROC_REQ 0x0108
+#define MNCC_PROGRESS_REQ 0x0109
+#define MNCC_ALERT_REQ 0x010a
+#define MNCC_ALERT_IND 0x010b
+#define MNCC_NOTIFY_REQ 0x010c
+#define MNCC_NOTIFY_IND 0x010d
+#define MNCC_DISC_REQ 0x010e
+#define MNCC_DISC_IND 0x010f
+#define MNCC_REL_REQ 0x0110
+#define MNCC_REL_IND 0x0111
+#define MNCC_REL_CNF 0x0112
+#define MNCC_FACILITY_REQ 0x0113
+#define MNCC_FACILITY_IND 0x0114
+#define MNCC_START_DTMF_IND 0x0115
+#define MNCC_START_DTMF_RSP 0x0116
+#define MNCC_START_DTMF_REJ 0x0117
+#define MNCC_STOP_DTMF_IND 0x0118
+#define MNCC_STOP_DTMF_RSP 0x0119
+#define MNCC_MODIFY_REQ 0x011a
+#define MNCC_MODIFY_IND 0x011b
+#define MNCC_MODIFY_RSP 0x011c
+#define MNCC_MODIFY_CNF 0x011d
+#define MNCC_MODIFY_REJ 0x011e
+#define MNCC_HOLD_IND 0x011f
+#define MNCC_HOLD_CNF 0x0120
+#define MNCC_HOLD_REJ 0x0121
+#define MNCC_RETRIEVE_IND 0x0122
+#define MNCC_RETRIEVE_CNF 0x0123
+#define MNCC_RETRIEVE_REJ 0x0124
+#define MNCC_USERINFO_REQ 0x0125
+#define MNCC_USERINFO_IND 0x0126
+#define MNCC_REJ_REQ 0x0127
+#define MNCC_REJ_IND 0x0128
+
+#define MNCC_BRIDGE 0x0200
+#define MNCC_FRAME_RECV 0x0201
+#define MNCC_FRAME_DROP 0x0202
+#define MNCC_LCHAN_MODIFY 0x0203
+
+#define GSM_TCHF_FRAME 0x0300
+#define GSM_TCHF_FRAME_EFR 0x0301
+
+#define GSM_MAX_FACILITY 128
+#define GSM_MAX_SSVERSION 128
+#define GSM_MAX_USERUSER 128
+
+#define MNCC_F_BEARER_CAP 0x0001
+#define MNCC_F_CALLED 0x0002
+#define MNCC_F_CALLING 0x0004
+#define MNCC_F_REDIRECTING 0x0008
+#define MNCC_F_CONNECTED 0x0010
+#define MNCC_F_CAUSE 0x0020
+#define MNCC_F_USERUSER 0x0040
+#define MNCC_F_PROGRESS 0x0080
+#define MNCC_F_EMERGENCY 0x0100
+#define MNCC_F_FACILITY 0x0200
+#define MNCC_F_SSVERSION 0x0400
+#define MNCC_F_CCCAP 0x0800
+#define MNCC_F_KEYPAD 0x1000
+#define MNCC_F_SIGNAL 0x2000
+
+struct gsm_mncc {
+ /* context based information */
+ uint32_t msg_type;
+ uint32_t callref;
+
+ /* which fields are present */
+ uint32_t fields;
+
+ /* data derived informations (MNCC_F_ based) */
+ struct gsm_mncc_bearer_cap bearer_cap;
+ struct gsm_mncc_number called;
+ struct gsm_mncc_number calling;
+ struct gsm_mncc_number redirecting;
+ struct gsm_mncc_number connected;
+ struct gsm_mncc_cause cause;
+ struct gsm_mncc_progress progress;
+ struct gsm_mncc_useruser useruser;
+ struct gsm_mncc_facility facility;
+ struct gsm_mncc_cccap cccap;
+ struct gsm_mncc_ssversion ssversion;
+ struct {
+ int sup;
+ int inv;
+ } clir;
+ int signal;
+
+ /* data derived information, not MNCC_F based */
+ int keypad;
+ int more;
+ int notify; /* 0..127 */
+ int emergency;
+ char imsi[16];
+
+ unsigned char lchan_mode;
+};
+
+struct gsm_data_frame {
+ uint32_t msg_type;
+ uint32_t callref;
+ unsigned char data[0];
+};
+
+char *get_mncc_name(int value);
+void mncc_set_cause(struct gsm_mncc *data, int loc, int val);
+void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg);
+
+/* input from CC code into mncc_builtin */
+int int_mncc_recv(struct gsm_network *net, struct msgb *msg);
+
+/* input from CC code into mncc_sock */
+int mncc_sock_from_cc(struct gsm_network *net, struct msgb *msg);
+
+int mncc_sock_init(struct gsm_network *gsmnet);
+
+#endif
diff --git a/include/openbsc/network_listen.h b/include/openbsc/network_listen.h
new file mode 100644
index 00000000..67d1f4ef
--- /dev/null
+++ b/include/openbsc/network_listen.h
@@ -0,0 +1,16 @@
+#ifndef _OPENBSC_NWL_H
+#define _OPENBSC_NWL_H
+
+#include <stdint.h>
+#include <openbsc/gsm_data.h>
+
+void ipac_nwl_init(void);
+
+/* Start a NWL test. It will raise the S_IPAC_TEST_COMPLETE signal. */
+int ipac_nwl_test_start(struct gsm_bts_trx *trx, uint8_t testnr,
+ const uint8_t *phys_conf, unsigned int phys_conf_len);
+
+int ipac_rxlevstat2whitelist(uint16_t *buf, const struct rxlev_stats *st, uint8_t min_rxlev,
+ uint16_t max_num_arfcns);
+
+#endif /* _OPENBSC_NWL_H */
diff --git a/include/openbsc/openbscdefines.h b/include/openbsc/openbscdefines.h
new file mode 100644
index 00000000..c6ac153b
--- /dev/null
+++ b/include/openbsc/openbscdefines.h
@@ -0,0 +1,34 @@
+/*
+ * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef OPENBSCDEFINES_H
+#define OPENBSCDEFINES_H
+
+#ifdef BUILDING_ON_WINDOWS
+ #ifdef BUILDING_OPENBSC
+ #define BSC_API __declspec(dllexport)
+ #else
+ #define BSC_API __declspec(dllimport)
+ #endif
+#else
+ #define BSC_API __attribute__((visibility("default")))
+#endif
+
+#endif
diff --git a/include/openbsc/osmo_bsc.h b/include/openbsc/osmo_bsc.h
new file mode 100644
index 00000000..ef0f11a3
--- /dev/null
+++ b/include/openbsc/osmo_bsc.h
@@ -0,0 +1,43 @@
+/* OpenBSC BSC code */
+
+#ifndef OSMO_BSC_H
+#define OSMO_BSC_H
+
+#include "bsc_api.h"
+
+struct sccp_connection;
+
+struct osmo_bsc_sccp_con {
+ struct llist_head entry;
+
+ int ciphering_handled;
+ int rtp_port;
+
+ /* 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 llist_head sccp_queue;
+ unsigned int sccp_queue_size;
+
+ struct gsm_subscriber_connection *conn;
+ uint8_t new_subscriber;
+};
+
+struct bsc_api *osmo_bsc_api();
+
+int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg);
+int bsc_open_connection(struct osmo_bsc_sccp_con *sccp, struct msgb *msg);
+int bsc_create_new_connection(struct gsm_subscriber_connection *conn);
+int bsc_delete_connection(struct osmo_bsc_sccp_con *sccp);
+
+int bsc_scan_bts_msg(struct gsm_subscriber_connection *conn, struct msgb *msg);
+int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg);
+
+int bsc_handle_udt(struct gsm_network *net, struct bsc_msc_connection *conn, struct msgb *msg, unsigned int length);
+int bsc_handle_dt1(struct osmo_bsc_sccp_con *conn, struct msgb *msg, unsigned int len);
+
+
+#endif
diff --git a/include/openbsc/osmo_bsc_grace.h b/include/openbsc/osmo_bsc_grace.h
new file mode 100644
index 00000000..45d4db8e
--- /dev/null
+++ b/include/openbsc/osmo_bsc_grace.h
@@ -0,0 +1,28 @@
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef OSMO_BSC_GRACE_H
+#define OSMO_BSC_GRACE_H
+
+#include "gsm_data.h"
+
+int bsc_grace_allow_new_connection(struct gsm_network *network);
+
+#endif
diff --git a/include/openbsc/osmo_bsc_rf.h b/include/openbsc/osmo_bsc_rf.h
new file mode 100644
index 00000000..e43ae2e3
--- /dev/null
+++ b/include/openbsc/osmo_bsc_rf.h
@@ -0,0 +1,35 @@
+#ifndef OSMO_BSC_RF
+#define OSMO_BSC_RF
+
+#include <osmocore/write_queue.h>
+#include <osmocore/timer.h>
+
+struct gsm_network;
+
+struct osmo_bsc_rf {
+ /* the value of signal.h */
+ int policy;
+ struct bsc_fd listen;
+ struct gsm_network *gsm_network;
+
+ const char *last_state_command;
+
+ /* delay the command */
+ char last_request;
+ struct timer_list delay_cmd;
+
+ /* verify that RF is up as it should be */
+ struct timer_list rf_check;
+
+ /* some handling for the automatic grace switch */
+ struct timer_list grace_timeout;
+};
+
+struct osmo_bsc_rf_conn {
+ struct write_queue queue;
+ struct osmo_bsc_rf *rf;
+};
+
+struct osmo_bsc_rf *osmo_bsc_rf_create(const char *path, struct gsm_network *net);
+
+#endif
diff --git a/include/openbsc/osmo_msc.h b/include/openbsc/osmo_msc.h
new file mode 100644
index 00000000..beb3f5e4
--- /dev/null
+++ b/include/openbsc/osmo_msc.h
@@ -0,0 +1,11 @@
+/* Routines for the MSC handling */
+
+#ifndef OSMO_MSC_H
+#define OSMO_MSC_H
+
+#include "bsc_api.h"
+
+struct bsc_api *msc_bsc_api();
+void msc_release_connection(struct gsm_subscriber_connection *conn);
+
+#endif
diff --git a/include/openbsc/osmo_msc_data.h b/include/openbsc/osmo_msc_data.h
new file mode 100644
index 00000000..8f9ca685
--- /dev/null
+++ b/include/openbsc/osmo_msc_data.h
@@ -0,0 +1,76 @@
+/*
+ * Data for the true BSC
+ *
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _OSMO_MSC_DATA_H
+#define _OSMO_MSC_DATA_H
+
+#include "bsc_msc.h"
+
+#include <osmocore/timer.h>
+
+struct osmo_bsc_rf;
+struct gsm_network;
+
+struct gsm_audio_support {
+ uint8_t hr : 1,
+ ver : 7;
+};
+
+struct osmo_msc_data {
+ /* 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 bsc_msc_connection *msc_con;
+ int core_ncc;
+ int core_mcc;
+ int rtp_base;
+
+ /* audio codecs */
+ struct gsm_audio_support **audio_support;
+ int audio_length;
+
+
+ /* mgcp agent */
+ struct write_queue mgcp_agent;
+
+ /* rf ctl related bits */
+ char *mid_call_txt;
+ int mid_call_timeout;
+ struct osmo_bsc_rf *rf_ctl;
+
+ /* ussd welcome text */
+ char *ussd_welcome_txt;
+};
+
+int osmo_bsc_msc_init(struct gsm_network *network);
+int osmo_bsc_sccp_init(struct gsm_network *gsmnet);
+int msc_queue_write(struct bsc_msc_connection *conn, struct msgb *msg, int proto);
+
+int osmo_bsc_audio_init(struct gsm_network *network);
+
+#endif
diff --git a/include/openbsc/paging.h b/include/openbsc/paging.h
new file mode 100644
index 00000000..f7191991
--- /dev/null
+++ b/include/openbsc/paging.h
@@ -0,0 +1,71 @@
+/* Paging helper and manager.... */
+/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef PAGING_H
+#define PAGING_H
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <osmocore/linuxlist.h>
+#include "gsm_data.h"
+#include "gsm_subscriber.h"
+#include <osmocore/timer.h>
+
+/**
+ * A pending paging request
+ */
+struct gsm_paging_request {
+ /* list_head for list of all paging requests */
+ struct llist_head entry;
+ /* the subscriber which we're paging. Later gsm_paging_request
+ * should probably become a part of the gsm_subscriber struct? */
+ struct gsm_subscriber *subscr;
+ /* back-pointer to the BTS on which we are paging */
+ struct gsm_bts *bts;
+ /* what kind of channel type do we ask the MS to establish */
+ int chan_type;
+
+ /* Timer 3113: how long do we try to page? */
+ struct timer_list T3113;
+
+ /* How often did we ask the BTS to page? */
+ int attempts;
+
+ /* callback to be called in case paging completes */
+ gsm_cbfn *cbfn;
+ void *cbfn_param;
+};
+
+/* 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);
+
+/* stop paging requests */
+void paging_request_stop(struct gsm_bts *bts, struct gsm_subscriber *subscr,
+ struct gsm_subscriber_connection *conn,
+ struct msgb *msg);
+
+/* update paging load */
+void paging_update_buffer_space(struct gsm_bts *bts, u_int16_t);
+
+#endif
diff --git a/include/openbsc/rest_octets.h b/include/openbsc/rest_octets.h
new file mode 100644
index 00000000..6d901196
--- /dev/null
+++ b/include/openbsc/rest_octets.h
@@ -0,0 +1,133 @@
+#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);
+
+struct gsm48_si_selection_params {
+ u_int16_t penalty_time:5,
+ temp_offs:3,
+ cell_resel_off:6,
+ cbq:1,
+ present:1;
+};
+
+struct gsm48_si_power_offset {
+ u_int8_t power_offset:2,
+ present:1;
+};
+
+struct gsm48_si3_gprs_ind {
+ u_int8_t si13_position:1,
+ ra_colour:3,
+ present:1;
+};
+
+struct gsm48_lsa_params {
+ u_int32_t prio_thr:3,
+ lsa_offset:3,
+ mcc:12,
+ mnc:12;
+ unsigned int present;
+};
+
+struct gsm48_si_ro_info {
+ struct gsm48_si_selection_params selection_params;
+ struct gsm48_si_power_offset power_offset;
+ u_int8_t si2ter_indicator;
+ u_int8_t early_cm_ctrl;
+ struct {
+ u_int8_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 ? */
+};
+
+
+/* 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);
+
+/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
+int rest_octets_si4(u_int8_t *data, const struct gsm48_si_ro_info *si4);
+
+enum pbcch_carrier_type {
+ PBCCH_BCCH,
+ PBCCH_ARFCN,
+ PBCCH_MAIO
+};
+
+/* TS 03.60 Chapter 6.3.3.1: Network Mode of Operation */
+enum gprs_nmo {
+ GPRS_NMO_I = 0, /* CS pagin on GPRS paging or traffic channel */
+ GPRS_NMO_II = 1, /* all paging on CCCH */
+ GPRS_NMO_III = 2, /* no paging coordination */
+};
+
+/* TS 04.60 12.24 */
+struct gprs_cell_options {
+ enum gprs_nmo nmo;
+ /* T3168: wait for packet uplink assignment message */
+ u_int32_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;
+
+ u_int8_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;
+ } 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;
+};
+
+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;
+
+ union {
+ struct {
+ u_int8_t rac;
+ u_int8_t spgc_ccch_sup;
+ u_int8_t net_ctrl_ord;
+ u_int8_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;
+ enum pbcch_carrier_type carrier_type;
+ u_int16_t arfcn;
+ u_int8_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);
+
+#endif /* _REST_OCTETS_H */
diff --git a/include/openbsc/rs232.h b/include/openbsc/rs232.h
new file mode 100644
index 00000000..61187ca6
--- /dev/null
+++ b/include/openbsc/rs232.h
@@ -0,0 +1,9 @@
+#ifndef _RS232_H
+#define _RS232_H
+
+int rs232_setup(const char *serial_port, unsigned int delay_ms,
+ struct gsm_bts *bts);
+
+int handle_serial_msg(struct msgb *msg);
+
+#endif /* _RS232_H */
diff --git a/include/openbsc/rtp_proxy.h b/include/openbsc/rtp_proxy.h
new file mode 100644
index 00000000..53b58b4b
--- /dev/null
+++ b/include/openbsc/rtp_proxy.h
@@ -0,0 +1,90 @@
+#ifndef _RTP_PROXY_H
+#define _RTP_PROXY_H
+
+/* RTP proxy handling for ip.access nanoBTS */
+
+/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include <netinet/in.h>
+
+#include <osmocore/linuxlist.h>
+#include <osmocore/select.h>
+
+#define RTP_PT_GSM_FULL 3
+#define RTP_PT_GSM_HALF 96
+#define RTP_PT_GSM_EFR 97
+#define RTP_PT_AMR_FULL 98
+#define RTP_PT_AMR_HALF 99
+
+enum rtp_rx_action {
+ RTP_NONE,
+ RTP_PROXY,
+ RTP_RECV_UPSTREAM,
+};
+
+enum rtp_tx_action {
+ RTP_SEND_NONE,
+ RTP_SEND_DOWNSTREAM,
+};
+
+struct rtp_sub_socket {
+ struct sockaddr_in sin_local;
+ struct sockaddr_in sin_remote;
+
+ struct bsc_fd bfd;
+ /* linked list of to-be-transmitted msgb's */
+ struct llist_head tx_queue;
+};
+
+struct rtp_socket {
+ struct llist_head list;
+
+ struct rtp_sub_socket rtp;
+ struct rtp_sub_socket rtcp;
+
+ /* what should we do on receive? */
+ enum rtp_rx_action rx_action;
+ union {
+ struct {
+ struct rtp_socket *other_sock;
+ } proxy;
+ struct {
+ struct gsm_network *net;
+ u_int32_t callref;
+ } receive;
+ };
+ enum rtp_tx_action tx_action;
+ struct {
+ u_int16_t sequence;
+ u_int32_t timestamp;
+ u_int32_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_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_free(struct rtp_socket *rs);
+int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame);
+
+#endif /* _RTP_PROXY_H */
diff --git a/include/openbsc/sgsn.h b/include/openbsc/sgsn.h
new file mode 100644
index 00000000..84db87e9
--- /dev/null
+++ b/include/openbsc/sgsn.h
@@ -0,0 +1,65 @@
+#ifndef _SGSN_H
+#define _SGSN_H
+
+#include <sys/types.h>
+
+#include <osmocore/msgb.h>
+
+#include <openbsc/gprs_ns.h>
+#include <openbsc/gprs_sgsn.h>
+
+struct sgsn_config {
+ /* parsed from config file */
+
+ char *gtp_statedir;
+ struct sockaddr_in gtp_listenaddr;
+
+ /* misc */
+ struct gprs_ns_inst *nsi;
+};
+
+struct sgsn_instance {
+ 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;
+ /* Timer for libGTP */
+ struct timer_list gtp_timer;
+ /* GSN instance for libgtp */
+ struct gsn_t *gsn;
+};
+
+extern struct sgsn_instance *sgsn;
+
+/* sgsn_vty.c */
+
+int sgsn_vty_init(void);
+int sgsn_parse_config(const char *config_file, struct sgsn_config *cfg);
+
+/* sgsn.c */
+
+/* Main input function for Gb proxy */
+int sgsn_rcvmsg(struct msgb *msg, struct gprs_nsvc *nsvc, uint16_t ns_bvci);
+
+
+struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
+ struct sgsn_mm_ctx *mmctx,
+ uint16_t nsapi,
+ struct tlv_parsed *tp);
+int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx);
+
+/* gprs_sndcp.c */
+
+/* Entry point for the SNSM-ACTIVATE.indication */
+int sndcp_sm_activate_ind(struct gprs_llc_lle *lle, uint8_t nsapi);
+/* Entry point for the SNSM-DEACTIVATE.indication */
+int sndcp_sm_deactivate_ind(struct gprs_llc_lle *lle, uint8_t nsapi);
+/* Called by SNDCP when it has received/re-assembled a N-PDU */
+int sgsn_rx_sndcp_ud_ind(struct gprs_ra_id *ra_id, int32_t tlli, uint8_t nsapi,
+ struct msgb *msg, uint32_t npdu_len, uint8_t *npdu);
+int sndcp_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi,
+ void *mmcontext);
+
+#endif
diff --git a/include/openbsc/signal.h b/include/openbsc/signal.h
new file mode 100644
index 00000000..a2257db7
--- /dev/null
+++ b/include/openbsc/signal.h
@@ -0,0 +1,255 @@
+/* Generic signalling/notification infrastructure */
+/* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef OPENBSC_SIGNAL_H
+#define OPENBSC_SIGNAL_H
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include <openbsc/gsm_data.h>
+
+#include <osmocore/signal.h>
+
+/*
+ * Signalling subsystems
+ */
+enum signal_subsystems {
+ SS_PAGING,
+ SS_SMS,
+ SS_ABISIP,
+ SS_NM,
+ SS_LCHAN,
+ SS_SUBSCR,
+ SS_SCALL,
+ SS_GLOBAL,
+ SS_CHALLOC,
+ SS_NS,
+ SS_IPAC_NWL,
+ SS_RF,
+ SS_MSC,
+ SS_HO,
+ SS_INPUT,
+};
+
+/* SS_PAGING signals */
+enum signal_paging {
+ S_PAGING_SUCCEEDED,
+ S_PAGING_EXPIRED,
+};
+
+/* SS_SMS signals */
+enum signal_sms {
+ S_SMS_SUBMITTED, /* A SMS has been successfully submitted to us */
+ S_SMS_DELIVERED, /* A SMS has been successfully delivered to a MS */
+ S_SMS_SMMA, /* A MS tells us it has more space available */
+ S_SMS_MEM_EXCEEDED, /* A MS tells us it has no more space available */
+ S_SMS_UNKNOWN_ERROR, /* A MS tells us it has an error */
+};
+
+/* SS_ABISIP signals */
+enum signal_abisip {
+ S_ABISIP_CRCX_ACK,
+ S_ABISIP_MDCX_ACK,
+ S_ABISIP_DLCX_IND,
+};
+
+/* SS_NM signals */
+enum signal_nm {
+ S_NM_SW_ACTIV_REP, /* GSM 12.21 software activated report */
+ S_NM_FAIL_REP, /* GSM 12.21 failure event report */
+ S_NM_NACK, /* GSM 12.21 various NM_MT_*_NACK happened */
+ S_NM_IPACC_NACK, /* GSM 12.21 nanoBTS extensions NM_MT_IPACC_*_*_NACK happened */
+ S_NM_IPACC_ACK, /* GSM 12.21 nanoBTS extensions NM_MT_IPACC_*_*_ACK happened */
+ S_NM_IPACC_RESTART_ACK, /* nanoBTS has send a restart ack */
+ S_NM_IPACC_RESTART_NACK,/* nanoBTS has send a restart ack */
+ S_NM_TEST_REP, /* GSM 12.21 Test Report */
+ S_NM_STATECHG_OPER, /* Operational State changed*/
+ S_NM_STATECHG_ADM, /* Administrative State changed */
+};
+
+/* SS_LCHAN signals */
+enum signal_lchan {
+ /*
+ * The lchan got freed with an use_count != 0 and error
+ * recovery needs to be carried out from within the
+ * signal handler.
+ */
+ S_LCHAN_UNEXPECTED_RELEASE,
+ S_LCHAN_ACTIVATE_ACK, /* 08.58 Channel Activate ACK */
+ S_LCHAN_ACTIVATE_NACK, /* 08.58 Channel Activate NACK */
+ S_LCHAN_HANDOVER_COMPL, /* 04.08 Handover Completed */
+ S_LCHAN_HANDOVER_FAIL, /* 04.08 Handover Failed */
+ S_LCHAN_HANDOVER_DETECT, /* 08.58 Handover Detect */
+ S_LCHAN_MEAS_REP, /* 08.58 Measurement Report */
+};
+
+/* SS_CHALLOC signals */
+enum signal_challoc {
+ S_CHALLOC_ALLOC_FAIL, /* allocation of lchan has failed */
+ S_CHALLOC_FREED, /* lchan has been successfully freed */
+};
+
+/* SS_SUBSCR signals */
+enum signal_subscr {
+ S_SUBSCR_ATTACHED,
+ S_SUBSCR_DETACHED,
+ S_SUBSCR_IDENTITY, /* we've received some identity information */
+};
+
+/* SS_SCALL signals */
+enum signal_scall {
+ S_SCALL_SUCCESS,
+ S_SCALL_EXPIRED,
+ S_SCALL_DETACHED,
+};
+
+/* SS_IPAC_NWL signals */
+enum signal_ipaccess {
+ S_IPAC_NWL_COMPLETE,
+};
+
+enum signal_global {
+ S_GLOBAL_SHUTDOWN,
+ S_GLOBAL_BTS_CLOSE_OM,
+};
+
+/* SS_RF signals */
+enum signal_rf {
+ S_RF_OFF,
+ S_RF_ON,
+ S_RF_GRACE,
+};
+
+/* SS_INPUT signals */
+enum signal_input {
+ S_INP_NONE,
+ S_INP_TEI_UP,
+ S_INP_TEI_DN,
+ S_INP_LINE_INIT,
+ S_INP_LINE_ALARM,
+ S_INP_LINE_NOALARM,
+};
+
+struct gsm_subscriber;
+
+struct paging_signal_data {
+ struct gsm_subscriber *subscr;
+ struct gsm_bts *bts;
+
+ int paging_result;
+
+ /* NULL in case the paging didn't work */
+ struct gsm_subscriber_connection *conn;
+};
+
+struct scall_signal_data {
+ struct gsm_subscriber *subscr;
+ struct gsm_subscriber_connection *conn;
+ void *data;
+};
+
+struct ipacc_ack_signal_data {
+ struct gsm_bts_trx *trx;
+ u_int8_t msg_type;
+};
+
+struct nm_statechg_signal_data {
+ u_int8_t obj_class;
+ void *obj;
+ struct gsm_nm_state *old_state;
+ struct gsm_nm_state *new_state;
+ struct abis_om_obj_inst *obj_inst;
+};
+
+struct nm_nack_signal_data {
+ struct msgb *msg;
+ uint8_t mt;
+};
+
+struct challoc_signal_data {
+ struct gsm_bts *bts;
+ struct gsm_lchan *lchan;
+ enum gsm_chan_t type;
+};
+
+struct rf_signal_data {
+ struct gsm_network *net;
+};
+
+struct sms_signal_data {
+ /* The transaction where this occured */
+ struct gsm_trans *trans;
+ /* Can be NULL for SMMA */
+ struct gsm_sms *sms;
+ /* int paging result. Only the ones with > 0 */
+ int paging_result;
+};
+
+struct lchan_signal_data {
+ /* The lchan the signal happened on */
+ struct gsm_lchan *lchan;
+ /* Measurement reports on this lchan */
+ struct gsm_meas_rep *mr;
+};
+
+enum signal_ns {
+ S_NS_RESET,
+ S_NS_BLOCK,
+ S_NS_UNBLOCK,
+ S_NS_ALIVE_EXP, /* Tns-alive expired more than N times */
+};
+
+struct ns_signal_data {
+ struct gprs_nsvc *nsvc;
+ uint8_t cause;
+};
+
+/* MSC signals */
+enum signal_msc {
+ S_MSC_LOST,
+ S_MSC_CONNECTED,
+};
+
+struct osmo_msc_data;
+struct msc_signal_data {
+ struct osmo_msc_data *data;
+};
+
+/* handover */
+enum signal_ho {
+ S_HANDOVER_ACK,
+};
+
+struct ho_signal_data {
+ struct gsm_lchan *old_lchan;
+ struct gsm_lchan *new_lchan;
+};
+
+struct input_signal_data {
+ int link_type;
+ uint8_t tei;
+ uint8_t sapi;
+ struct gsm_bts_trx *trx;
+ struct e1inp_line *line;
+};
+
+#endif
diff --git a/include/openbsc/silent_call.h b/include/openbsc/silent_call.h
new file mode 100644
index 00000000..2492903c
--- /dev/null
+++ b/include/openbsc/silent_call.h
@@ -0,0 +1,12 @@
+#ifndef _SILENT_CALL_H
+#define _SILENT_CALL_H
+
+struct gsm_subscriber_connection;
+
+extern int gsm_silent_call_start(struct gsm_subscriber *subscr,
+ void *data, int type);
+extern int gsm_silent_call_stop(struct gsm_subscriber *subscr);
+extern int silent_call_rx(struct gsm_subscriber_connection *conn, struct msgb *msg);
+extern int silent_call_reroute(struct gsm_subscriber_connection *conn, struct msgb *msg);
+
+#endif /* _SILENT_CALL_H */
diff --git a/include/openbsc/sms_queue.h b/include/openbsc/sms_queue.h
new file mode 100644
index 00000000..2a8bd585
--- /dev/null
+++ b/include/openbsc/sms_queue.h
@@ -0,0 +1,17 @@
+#ifndef SMS_QUEUE_H
+#define SMS_QUEUE_H
+
+struct gsm_network;
+struct gsm_sms_queue;
+struct vty;
+
+int sms_queue_start(struct gsm_network *, int in_flight);
+int sms_queue_trigger(struct gsm_sms_queue *);
+
+/* vty helper functions */
+int sms_queue_stats(struct gsm_sms_queue *, struct vty* vty);
+int sms_queue_set_max_pending(struct gsm_sms_queue *, int max);
+int sms_queue_set_max_failure(struct gsm_sms_queue *, int fail);
+int sms_queue_clear(struct gsm_sms_queue *);
+
+#endif
diff --git a/include/openbsc/socket.h b/include/openbsc/socket.h
new file mode 100644
index 00000000..4d316114
--- /dev/null
+++ b/include/openbsc/socket.h
@@ -0,0 +1,14 @@
+#ifndef _BSC_SOCKET_H
+#define _BSC_SOCKET_H
+
+#include <sys/types.h>
+#include <osmocore/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));
+
+#endif /* _BSC_SOCKET_H */
diff --git a/include/openbsc/subchan_demux.h b/include/openbsc/subchan_demux.h
new file mode 100644
index 00000000..da2a7f32
--- /dev/null
+++ b/include/openbsc/subchan_demux.h
@@ -0,0 +1,101 @@
+#ifndef _SUBCH_DEMUX_H
+#define _SUBCH_DEMUX_H
+/* A E1 sub-channel (de)multiplexer with TRAU frame sync */
+
+/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/types.h>
+#include <osmocore/linuxlist.h>
+
+#define NR_SUBCH 4
+#define TRAU_FRAME_SIZE 40
+#define TRAU_FRAME_BITS (TRAU_FRAME_SIZE*8)
+
+/***********************************************************************/
+/* DEMULTIPLEXER */
+/***********************************************************************/
+
+struct demux_subch {
+ u_int8_t out_bitbuf[TRAU_FRAME_BITS];
+ u_int16_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? */
+ unsigned int in_sync;
+};
+
+struct subch_demux {
+ /* bitmask of currently active subchannels */
+ u_int8_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,
+ void *);
+ /* user-provided data, transparently passed to out_cb() */
+ void *data;
+};
+
+/* initialize one demultiplexer instance */
+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);
+
+/* activate decoding/processing for one subchannel */
+int subch_demux_activate(struct subch_demux *dmx, int subch);
+
+/* deactivate decoding/processing for one subchannel */
+int subch_demux_deactivate(struct subch_demux *dmx, int subch);
+
+/***********************************************************************/
+/* MULTIPLEXER */
+/***********************************************************************/
+
+/* one element in the tx_queue of a muxer sub-channel */
+struct subch_txq_entry {
+ struct llist_head list;
+
+ 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 */
+};
+
+struct mux_subch {
+ struct llist_head tx_queue;
+};
+
+/* structure representing one instance of the subchannel muxer */
+struct subch_mux {
+ struct mux_subch subch[NR_SUBCH];
+};
+
+/* initialize a subchannel muxer instance */
+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);
+
+/* 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 len);
+
+#endif /* _SUBCH_DEMUX_H */
diff --git a/include/openbsc/system_information.h b/include/openbsc/system_information.h
new file mode 100644
index 00000000..da662e91
--- /dev/null
+++ b/include/openbsc/system_information.h
@@ -0,0 +1,45 @@
+#ifndef _SYSTEM_INFO_H
+#define _SYSTEM_INFO_H
+
+#include <osmocore/utils.h>
+
+#define GSM_MACBLOCK_LEN 23
+
+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
new file mode 100644
index 00000000..e41d8ef9
--- /dev/null
+++ b/include/openbsc/transaction.h
@@ -0,0 +1,75 @@
+#ifndef _TRANSACT_H
+#define _TRANSACT_H
+
+#include <openbsc/gsm_data.h>
+#include <openbsc/gsm_subscriber.h>
+#include <osmocore/linuxlist.h>
+#include <openbsc/gsm_04_11.h>
+
+/* One transaction */
+struct gsm_trans {
+ /* Entry in list of all transactions */
+ struct llist_head entry;
+
+ /* The protocol within which we live */
+ u_int8_t protocol;
+
+ /* The current transaction ID */
+ u_int8_t transaction_id;
+
+ /* To whom we belong, unique identifier of remote MM entity */
+ struct gsm_subscriber *subscr;
+
+ /* The associated connection we are using to transmit messages */
+ struct gsm_subscriber_connection *conn;
+
+ /* reference from MNCC or other application */
+ u_int32_t callref;
+
+ /* if traffic channel receive was requested */
+ int tch_recv;
+
+ /* is thats one paging? */
+ struct gsm_network **paging_request;
+
+ union {
+ struct {
+
+ /* current call state */
+ int state;
+
+ /* current timer and message queue */
+ int Tcurrent; /* current CC timer */
+ int T308_second; /* used to send release again */
+ struct 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 */
+ int is_mt; /* is this a MO (0) or MT (1) transfer */
+ enum gsm411_cp_state cp_state;
+ struct timer_list cp_timer;
+
+ enum gsm411_rp_state rp_state;
+
+ struct gsm_sms *sms;
+ } sms;
+ };
+};
+
+
+
+struct gsm_trans *trans_find_by_id(struct gsm_subscriber *subscr,
+ u_int8_t proto, u_int8_t trans_id);
+struct gsm_trans *trans_find_by_callref(struct gsm_network *net,
+ u_int32_t callref);
+
+struct gsm_trans *trans_alloc(struct gsm_subscriber *subscr,
+ u_int8_t protocol, u_int8_t trans_id,
+ u_int32_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);
+
+#endif
diff --git a/include/openbsc/trau_frame.h b/include/openbsc/trau_frame.h
new file mode 100644
index 00000000..c594c38c
--- /dev/null
+++ b/include/openbsc/trau_frame.h
@@ -0,0 +1,64 @@
+#ifndef _TRAU_FRAME_H
+#define _TRAU_FRAME_H
+/* TRAU frame handling according to GSM TS 08.60 */
+
+/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/types.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
+/* 260 for FR/EFR, 256 for AMR, 264 for OM, 288 for E-data */
+#define MAX_D_BITS 288
+/* for all speech frames */
+#define MAX_T_BITS 4
+/* for OM */
+#define MAX_S_BITS 6
+/* for E-data */
+#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];
+};
+
+#define TRAU_FT_FR_UP 0x02 /* 0 0 0 1 0 - 3.5.1.1.1 */
+#define TRAU_FT_FR_DOWN 0x1c /* 1 1 1 0 0 - 3.5.1.1.1 */
+#define TRAU_FT_EFR 0x1a /* 1 1 0 1 0 - 3.5.1.1.1 */
+#define TRAU_FT_AMR 0x06 /* 0 0 1 1 0 - 3.5.1.2 */
+#define TRAU_FT_OM_UP 0x07 /* 0 0 1 0 1 - 3.5.2 */
+#define TRAU_FT_OM_DOWN 0x1b /* 1 1 0 1 1 - 3.5.2 */
+#define TRAU_FT_DATA_UP 0x08 /* 0 1 0 0 0 - 3.5.3 */
+#define TRAU_FT_DATA_DOWN 0x16 /* 1 0 1 1 0 - 3.5.3 */
+#define TRAU_FT_D145_SYNC 0x14 /* 1 0 1 0 0 - 3.5.3 */
+#define TRAU_FT_EDATA 0x1f /* 1 1 1 1 1 - 3.5.4 */
+#define TRAU_FT_IDLE_UP 0x10 /* 1 0 0 0 0 - 3.5.5 */
+#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 trau_frame_up2down(struct decoded_trau_frame *fr);
+u_int8_t *trau_idle_frame(void);
+
+
+#endif /* _TRAU_FRAME_H */
diff --git a/include/openbsc/trau_mux.h b/include/openbsc/trau_mux.h
new file mode 100644
index 00000000..dcf33ee8
--- /dev/null
+++ b/include/openbsc/trau_mux.h
@@ -0,0 +1,48 @@
+/* Simple TRAU frame reflector to route voice calls */
+
+/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/* The "TRAU mux map" defines which particular 16kbit sub-slot (in which E1
+ * timeslot on which E1 interface) should be directly muxed to which other
+ * sub-slot. Entries in the mux map are always bi-directional.
+ *
+ * The idea of all this is to directly switch voice channels in the BSC
+ * from one phone to another. We do this right now since we don't support
+ * any external interface for voice channels, and in the future as an
+ * optimization to routing them externally.
+ */
+
+/* map a TRAU mux map entry */
+int trau_mux_map(const struct gsm_e1_subslot *src,
+ const struct gsm_e1_subslot *dst);
+int trau_mux_map_lchan(const struct gsm_lchan *src,
+ const struct gsm_lchan *dst);
+
+/* unmap a TRAU mux map entry */
+int trau_mux_unmap(const struct gsm_e1_subslot *ss, u_int32_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);
+
+/* add a trau receiver */
+int trau_recv_lchan(struct gsm_lchan *lchan, u_int32_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
new file mode 100644
index 00000000..6f80d23d
--- /dev/null
+++ b/include/openbsc/ussd.h
@@ -0,0 +1,10 @@
+#ifndef _USSD_H
+#define _USSD_H
+
+/* Handler function for mobile-originated USSD messages */
+
+#include <osmocore/msgb.h>
+
+int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg);
+
+#endif
diff --git a/include/openbsc/vty.h b/include/openbsc/vty.h
new file mode 100644
index 00000000..516c8c2a
--- /dev/null
+++ b/include/openbsc/vty.h
@@ -0,0 +1,46 @@
+#ifndef OPENBSC_VTY_H
+#define OPENBSC_VTY_H
+
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/buffer.h>
+#include <osmocom/vty/command.h>
+
+struct gsm_network;
+struct vty;
+
+void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *);
+
+struct buffer *vty_argv_to_buffer(int argc, const char *argv[], int base);
+
+extern struct cmd_element cfg_description_cmd;
+extern struct cmd_element cfg_no_description_cmd;
+extern struct cmd_element ournode_exit_cmd;
+extern struct cmd_element ournode_end_cmd;
+
+enum bsc_vty_node {
+ GSMNET_NODE = _LAST_OSMOVTY_NODE + 1,
+ BTS_NODE,
+ TRX_NODE,
+ TS_NODE,
+ SUBSCR_NODE,
+ MGCP_NODE,
+ GBPROXY_NODE,
+ SGSN_NODE,
+ NS_NODE,
+ BSSGP_NODE,
+ OML_NODE,
+ E1INP_NODE,
+ NAT_NODE,
+ NAT_BSC_NODE,
+ MSC_NODE,
+ OM2K_NODE,
+ TRUNK_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);
+int bsc_vty_init_extra(void);
+
+#endif