From 03fd8d014f9871896a86534432c8757d65a576fe Mon Sep 17 00:00:00 2001 From: Jonathan Santos Date: Wed, 25 May 2011 13:54:02 -0400 Subject: Import upstream version 0.9.13 --- include/Makefile.am | 3 + include/Makefile.in | 541 +++++++++++++++++++++ include/compat_af_isdn.h | 39 ++ include/mISDNif.h | 387 +++++++++++++++ include/openbsc/Makefile.am | 17 + include/openbsc/Makefile.in | 449 ++++++++++++++++++ include/openbsc/abis_nm.h | 172 +++++++ include/openbsc/abis_om2000.h | 78 ++++ include/openbsc/abis_rsl.h | 99 ++++ include/openbsc/auth.h | 17 + include/openbsc/bsc_api.h | 37 ++ include/openbsc/bsc_msc.h | 51 ++ include/openbsc/bsc_nat.h | 355 ++++++++++++++ include/openbsc/bsc_nat_sccp.h | 95 ++++ include/openbsc/bsc_rll.h | 19 + include/openbsc/chan_alloc.h | 65 +++ include/openbsc/crc24.h | 8 + include/openbsc/db.h | 83 ++++ include/openbsc/debug.h | 70 +++ include/openbsc/e1_input.h | 187 ++++++++ include/openbsc/gb_proxy.h | 39 ++ include/openbsc/gprs_bssgp.h | 232 +++++++++ include/openbsc/gprs_gmm.h | 19 + include/openbsc/gprs_llc.h | 162 +++++++ include/openbsc/gprs_ns.h | 232 +++++++++ include/openbsc/gprs_ns_frgre.h | 6 + include/openbsc/gprs_sgsn.h | 220 +++++++++ include/openbsc/gsm_04_08.h | 70 +++ include/openbsc/gsm_04_08_gprs.h | 383 +++++++++++++++ include/openbsc/gsm_04_11.h | 40 ++ include/openbsc/gsm_04_80.h | 20 + include/openbsc/gsm_data.h | 879 +++++++++++++++++++++++++++++++++++ include/openbsc/gsm_subscriber.h | 107 +++++ include/openbsc/handover.h | 14 + include/openbsc/ipaccess.h | 131 ++++++ include/openbsc/meas_rep.h | 85 ++++ include/openbsc/mgcp.h | 194 ++++++++ include/openbsc/mgcp_internal.h | 154 ++++++ include/openbsc/misdn.h | 27 ++ include/openbsc/mncc.h | 172 +++++++ include/openbsc/network_listen.h | 16 + include/openbsc/openbscdefines.h | 34 ++ include/openbsc/osmo_bsc.h | 43 ++ include/openbsc/osmo_bsc_grace.h | 28 ++ include/openbsc/osmo_bsc_rf.h | 35 ++ include/openbsc/osmo_msc.h | 11 + include/openbsc/osmo_msc_data.h | 76 +++ include/openbsc/paging.h | 71 +++ include/openbsc/rest_octets.h | 133 ++++++ include/openbsc/rs232.h | 9 + include/openbsc/rtp_proxy.h | 90 ++++ include/openbsc/sgsn.h | 65 +++ include/openbsc/signal.h | 255 ++++++++++ include/openbsc/silent_call.h | 12 + include/openbsc/sms_queue.h | 17 + include/openbsc/socket.h | 14 + include/openbsc/subchan_demux.h | 101 ++++ include/openbsc/system_information.h | 45 ++ include/openbsc/transaction.h | 75 +++ include/openbsc/trau_frame.h | 64 +++ include/openbsc/trau_mux.h | 48 ++ include/openbsc/ussd.h | 10 + include/openbsc/vty.h | 46 ++ 63 files changed, 7256 insertions(+) create mode 100644 include/Makefile.am create mode 100644 include/Makefile.in create mode 100644 include/compat_af_isdn.h create mode 100644 include/mISDNif.h create mode 100644 include/openbsc/Makefile.am create mode 100644 include/openbsc/Makefile.in create mode 100644 include/openbsc/abis_nm.h create mode 100644 include/openbsc/abis_om2000.h create mode 100644 include/openbsc/abis_rsl.h create mode 100644 include/openbsc/auth.h create mode 100644 include/openbsc/bsc_api.h create mode 100644 include/openbsc/bsc_msc.h create mode 100644 include/openbsc/bsc_nat.h create mode 100644 include/openbsc/bsc_nat_sccp.h create mode 100644 include/openbsc/bsc_rll.h create mode 100644 include/openbsc/chan_alloc.h create mode 100644 include/openbsc/crc24.h create mode 100644 include/openbsc/db.h create mode 100644 include/openbsc/debug.h create mode 100644 include/openbsc/e1_input.h create mode 100644 include/openbsc/gb_proxy.h create mode 100644 include/openbsc/gprs_bssgp.h create mode 100644 include/openbsc/gprs_gmm.h create mode 100644 include/openbsc/gprs_llc.h create mode 100644 include/openbsc/gprs_ns.h create mode 100644 include/openbsc/gprs_ns_frgre.h create mode 100644 include/openbsc/gprs_sgsn.h create mode 100644 include/openbsc/gsm_04_08.h create mode 100644 include/openbsc/gsm_04_08_gprs.h create mode 100644 include/openbsc/gsm_04_11.h create mode 100644 include/openbsc/gsm_04_80.h create mode 100644 include/openbsc/gsm_data.h create mode 100644 include/openbsc/gsm_subscriber.h create mode 100644 include/openbsc/handover.h create mode 100644 include/openbsc/ipaccess.h create mode 100644 include/openbsc/meas_rep.h create mode 100644 include/openbsc/mgcp.h create mode 100644 include/openbsc/mgcp_internal.h create mode 100644 include/openbsc/misdn.h create mode 100644 include/openbsc/mncc.h create mode 100644 include/openbsc/network_listen.h create mode 100644 include/openbsc/openbscdefines.h create mode 100644 include/openbsc/osmo_bsc.h create mode 100644 include/openbsc/osmo_bsc_grace.h create mode 100644 include/openbsc/osmo_bsc_rf.h create mode 100644 include/openbsc/osmo_msc.h create mode 100644 include/openbsc/osmo_msc_data.h create mode 100644 include/openbsc/paging.h create mode 100644 include/openbsc/rest_octets.h create mode 100644 include/openbsc/rs232.h create mode 100644 include/openbsc/rtp_proxy.h create mode 100644 include/openbsc/sgsn.h create mode 100644 include/openbsc/signal.h create mode 100644 include/openbsc/silent_call.h create mode 100644 include/openbsc/sms_queue.h create mode 100644 include/openbsc/socket.h create mode 100644 include/openbsc/subchan_demux.h create mode 100644 include/openbsc/system_information.h create mode 100644 include/openbsc/transaction.h create mode 100644 include/openbsc/trau_frame.h create mode 100644 include/openbsc/trau_mux.h create mode 100644 include/openbsc/ussd.h create mode 100644 include/openbsc/vty.h (limited to 'include') diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 000000000..4596b6e3c --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = openbsc + +noinst_HEADERS = mISDNif.h compat_af_isdn.h diff --git a/include/Makefile.in b/include/Makefile.in new file mode 100644 index 000000000..ecbeebe28 --- /dev/null +++ b/include/Makefile.in @@ -0,0 +1,541 @@ +# 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 +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/bscconfig.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +HEADERS = $(noinst_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GPRS_LIBGTP = @GPRS_LIBGTP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@ +LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@ +LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@ +LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@ +LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@ +LIBOSMOVTY_LIBS = @LIBOSMOVTY_LIBS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYMBOL_VISIBILITY = @SYMBOL_VISIBILITY@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = openbsc +noinst_HEADERS = mISDNif.h compat_af_isdn.h +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu include/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic ctags \ + ctags-recursive distclean distclean-generic distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ + tags-recursive uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/include/compat_af_isdn.h b/include/compat_af_isdn.h new file mode 100644 index 000000000..56cbfb3f2 --- /dev/null +++ b/include/compat_af_isdn.h @@ -0,0 +1,39 @@ +#ifdef MISDN_OLD_AF_COMPATIBILITY +#undef AF_ISDN +#undef PF_ISDN + +extern int AF_ISDN; +#define PF_ISDN AF_ISDN + +int AF_ISDN; + +#endif + +extern void init_af_isdn(void); + +#ifdef AF_COMPATIBILITY_FUNC +#ifdef MISDN_OLD_AF_COMPATIBILITY +void init_af_isdn(void) +{ + int s; + + /* test for new value */ + AF_ISDN = 34; + s = socket(AF_ISDN, SOCK_RAW, ISDN_P_BASE); + if (s >= 0) { + close(s); + return; + } + AF_ISDN = 27; + s = socket(AF_ISDN, SOCK_RAW, ISDN_P_BASE); + if (s >= 0) { + close(s); + return; + } +} +#else +void init_af_isdn(void) +{ +} +#endif +#endif diff --git a/include/mISDNif.h b/include/mISDNif.h new file mode 100644 index 000000000..8e065d24b --- /dev/null +++ b/include/mISDNif.h @@ -0,0 +1,387 @@ +/* + * + * Author Karsten Keil + * + * Copyright 2008 by Karsten Keil + * + * This code is free software; you can redistribute it and/or modify + * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE + * version 2.1 as published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU LESSER GENERAL PUBLIC LICENSE for more details. + * + */ + +#ifndef mISDNIF_H +#define mISDNIF_H + +#include +#ifdef linux +#include +#include +#include +#else +#include +#include +#include +#endif + +/* + * ABI Version 32 bit + * + * <8 bit> Major version + * - changed if any interface become backwards incompatible + * + * <8 bit> Minor version + * - changed if any interface is extended but backwards compatible + * + * <16 bit> Release number + * - should be incremented on every checkin + */ +#define MISDN_MAJOR_VERSION 1 +#define MISDN_MINOR_VERSION 1 +#define MISDN_RELEASE 20 + +/* primitives for information exchange + * generell format + * <16 bit 0 > + * <8 bit command> + * BIT 8 = 1 LAYER private + * BIT 7 = 1 answer + * BIT 6 = 1 DATA + * <8 bit target layer mask> + * + * Layer = 00 is reserved for general commands + Layer = 01 L2 -> HW + Layer = 02 HW -> L2 + Layer = 04 L3 -> L2 + Layer = 08 L2 -> L3 + * Layer = FF is reserved for broadcast commands + */ + +#define MISDN_CMDMASK 0xff00 +#define MISDN_LAYERMASK 0x00ff + +/* generell commands */ +#define OPEN_CHANNEL 0x0100 +#define CLOSE_CHANNEL 0x0200 +#define CONTROL_CHANNEL 0x0300 +#define CHECK_DATA 0x0400 + +/* layer 2 -> layer 1 */ +#define PH_ACTIVATE_REQ 0x0101 +#define PH_DEACTIVATE_REQ 0x0201 +#define PH_DATA_REQ 0x2001 +#define MPH_ACTIVATE_REQ 0x0501 +#define MPH_DEACTIVATE_REQ 0x0601 +#define MPH_INFORMATION_REQ 0x0701 +#define PH_CONTROL_REQ 0x0801 + +/* layer 1 -> layer 2 */ +#define PH_ACTIVATE_IND 0x0102 +#define PH_ACTIVATE_CNF 0x4102 +#define PH_DEACTIVATE_IND 0x0202 +#define PH_DEACTIVATE_CNF 0x4202 +#define PH_DATA_IND 0x2002 +#define PH_DATA_E_IND 0x3002 +#define MPH_ACTIVATE_IND 0x0502 +#define MPH_DEACTIVATE_IND 0x0602 +#define MPH_INFORMATION_IND 0x0702 +#define PH_DATA_CNF 0x6002 +#define PH_CONTROL_IND 0x0802 +#define PH_CONTROL_CNF 0x4802 + +/* layer 3 -> layer 2 */ +#define DL_ESTABLISH_REQ 0x1004 +#define DL_RELEASE_REQ 0x1104 +#define DL_DATA_REQ 0x3004 +#define DL_UNITDATA_REQ 0x3104 +#define DL_INFORMATION_REQ 0x0004 + +/* layer 2 -> layer 3 */ +#define DL_ESTABLISH_IND 0x1008 +#define DL_ESTABLISH_CNF 0x5008 +#define DL_RELEASE_IND 0x1108 +#define DL_RELEASE_CNF 0x5108 +#define DL_DATA_IND 0x3008 +#define DL_UNITDATA_IND 0x3108 +#define DL_INFORMATION_IND 0x0008 + +/* intern layer 2 managment */ +#define MDL_ASSIGN_REQ 0x1804 +#define MDL_ASSIGN_IND 0x1904 +#define MDL_REMOVE_REQ 0x1A04 +#define MDL_REMOVE_IND 0x1B04 +#define MDL_STATUS_UP_IND 0x1C04 +#define MDL_STATUS_DOWN_IND 0x1D04 +#define MDL_STATUS_UI_IND 0x1E04 +#define MDL_ERROR_IND 0x1F04 +#define MDL_ERROR_RSP 0x5F04 + +/* DL_INFORMATION_IND types */ +#define DL_INFO_L2_CONNECT 0x0001 +#define DL_INFO_L2_REMOVED 0x0002 + +/* PH_CONTROL types */ +/* TOUCH TONE IS 0x20XX XX "0"..."9", "A","B","C","D","*","#" */ +#define DTMF_TONE_VAL 0x2000 +#define DTMF_TONE_MASK 0x007F +#define DTMF_TONE_START 0x2100 +#define DTMF_TONE_STOP 0x2200 +#define DTMF_HFC_COEF 0x4000 +#define DSP_CONF_JOIN 0x2403 +#define DSP_CONF_SPLIT 0x2404 +#define DSP_RECEIVE_OFF 0x2405 +#define DSP_RECEIVE_ON 0x2406 +#define DSP_ECHO_ON 0x2407 +#define DSP_ECHO_OFF 0x2408 +#define DSP_MIX_ON 0x2409 +#define DSP_MIX_OFF 0x240a +#define DSP_DELAY 0x240b +#define DSP_JITTER 0x240c +#define DSP_TXDATA_ON 0x240d +#define DSP_TXDATA_OFF 0x240e +#define DSP_TX_DEJITTER 0x240f +#define DSP_TX_DEJ_OFF 0x2410 +#define DSP_TONE_PATT_ON 0x2411 +#define DSP_TONE_PATT_OFF 0x2412 +#define DSP_VOL_CHANGE_TX 0x2413 +#define DSP_VOL_CHANGE_RX 0x2414 +#define DSP_BF_ENABLE_KEY 0x2415 +#define DSP_BF_DISABLE 0x2416 +#define DSP_BF_ACCEPT 0x2416 +#define DSP_BF_REJECT 0x2417 +#define DSP_PIPELINE_CFG 0x2418 +#define HFC_VOL_CHANGE_TX 0x2601 +#define HFC_VOL_CHANGE_RX 0x2602 +#define HFC_SPL_LOOP_ON 0x2603 +#define HFC_SPL_LOOP_OFF 0x2604 + +/* DSP_TONE_PATT_ON parameter */ +#define TONE_OFF 0x0000 +#define TONE_GERMAN_DIALTONE 0x0001 +#define TONE_GERMAN_OLDDIALTONE 0x0002 +#define TONE_AMERICAN_DIALTONE 0x0003 +#define TONE_GERMAN_DIALPBX 0x0004 +#define TONE_GERMAN_OLDDIALPBX 0x0005 +#define TONE_AMERICAN_DIALPBX 0x0006 +#define TONE_GERMAN_RINGING 0x0007 +#define TONE_GERMAN_OLDRINGING 0x0008 +#define TONE_AMERICAN_RINGPBX 0x000b +#define TONE_GERMAN_RINGPBX 0x000c +#define TONE_GERMAN_OLDRINGPBX 0x000d +#define TONE_AMERICAN_RINGING 0x000e +#define TONE_GERMAN_BUSY 0x000f +#define TONE_GERMAN_OLDBUSY 0x0010 +#define TONE_AMERICAN_BUSY 0x0011 +#define TONE_GERMAN_HANGUP 0x0012 +#define TONE_GERMAN_OLDHANGUP 0x0013 +#define TONE_AMERICAN_HANGUP 0x0014 +#define TONE_SPECIAL_INFO 0x0015 +#define TONE_GERMAN_GASSENBESETZT 0x0016 +#define TONE_GERMAN_AUFSCHALTTON 0x0016 + +/* MPH_INFORMATION_IND */ +#define L1_SIGNAL_LOS_OFF 0x0010 +#define L1_SIGNAL_LOS_ON 0x0011 +#define L1_SIGNAL_AIS_OFF 0x0012 +#define L1_SIGNAL_AIS_ON 0x0013 +#define L1_SIGNAL_RDI_OFF 0x0014 +#define L1_SIGNAL_RDI_ON 0x0015 +#define L1_SIGNAL_SLIP_RX 0x0020 +#define L1_SIGNAL_SLIP_TX 0x0021 + +/* + * protocol ids + * D channel 1-31 + * B channel 33 - 63 + */ + +#define ISDN_P_NONE 0 +#define ISDN_P_BASE 0 +#define ISDN_P_TE_S0 0x01 +#define ISDN_P_NT_S0 0x02 +#define ISDN_P_TE_E1 0x03 +#define ISDN_P_NT_E1 0x04 +#define ISDN_P_TE_UP0 0x05 +#define ISDN_P_NT_UP0 0x06 + +#define IS_ISDN_P_TE(p) ((p == ISDN_P_TE_S0) || (p == ISDN_P_TE_E1) || \ + (p == ISDN_P_TE_UP0) || (p == ISDN_P_LAPD_TE)) +#define IS_ISDN_P_NT(p) ((p == ISDN_P_NT_S0) || (p == ISDN_P_NT_E1) || \ + (p == ISDN_P_NT_UP0) || (p == ISDN_P_LAPD_NT)) +#define IS_ISDN_P_S0(p) ((p == ISDN_P_TE_S0) || (p == ISDN_P_NT_S0)) +#define IS_ISDN_P_E1(p) ((p == ISDN_P_TE_E1) || (p == ISDN_P_NT_E1)) +#define IS_ISDN_P_UP0(p) ((p == ISDN_P_TE_UP0) || (p == ISDN_P_NT_UP0)) + + +#define ISDN_P_LAPD_TE 0x10 +#define ISDN_P_LAPD_NT 0x11 + +#define ISDN_P_B_MASK 0x1f +#define ISDN_P_B_START 0x20 + +#define ISDN_P_B_RAW 0x21 +#define ISDN_P_B_HDLC 0x22 +#define ISDN_P_B_X75SLP 0x23 +#define ISDN_P_B_L2DTMF 0x24 +#define ISDN_P_B_L2DSP 0x25 +#define ISDN_P_B_L2DSPHDLC 0x26 + +#define OPTION_L2_PMX 1 +#define OPTION_L2_PTP 2 +#define OPTION_L2_FIXEDTEI 3 +#define OPTION_L2_CLEANUP 4 + +/* should be in sync with linux/kobject.h:KOBJ_NAME_LEN */ +#define MISDN_MAX_IDLEN 20 + +struct mISDNhead { + unsigned int prim; + unsigned int id; +} __attribute__((packed)); + +#define MISDN_HEADER_LEN sizeof(struct mISDNhead) +#define MAX_DATA_SIZE 2048 +#define MAX_DATA_MEM (MAX_DATA_SIZE + MISDN_HEADER_LEN) +#define MAX_DFRAME_LEN 260 + +#define MISDN_ID_ADDR_MASK 0xFFFF +#define MISDN_ID_TEI_MASK 0xFF00 +#define MISDN_ID_SAPI_MASK 0x00FF +#define MISDN_ID_TEI_ANY 0x7F00 + +#define MISDN_ID_ANY 0xFFFF +#define MISDN_ID_NONE 0xFFFE + +#define GROUP_TEI 127 +#define TEI_SAPI 63 +#define CTRL_SAPI 0 + +#define MISDN_MAX_CHANNEL 127 +#define MISDN_CHMAP_SIZE ((MISDN_MAX_CHANNEL + 1) >> 3) + +#define SOL_MISDN 0 + +struct sockaddr_mISDN { + sa_family_t family; + unsigned char dev; + unsigned char channel; + unsigned char sapi; + unsigned char tei; +}; + +struct mISDNversion { + unsigned char major; + unsigned char minor; + unsigned short release; +}; + +#define MAX_DEVICE_ID 63 + +struct mISDN_devinfo { + u_int id; + u_int Dprotocols; + u_int Bprotocols; + u_int protocol; + u_char channelmap[MISDN_CHMAP_SIZE]; + u_int nrbchan; + char name[MISDN_MAX_IDLEN]; +}; + +struct mISDN_devrename { + u_int id; + char name[MISDN_MAX_IDLEN]; +}; + +struct ph_info_ch { + int32_t protocol; + int64_t Flags; +}; + +struct ph_info_dch { + struct ph_info_ch ch; + int16_t state; + int16_t num_bch; +}; + +struct ph_info { + struct ph_info_dch dch; + struct ph_info_ch bch[]; +}; + +/* timer device ioctl */ +#define IMADDTIMER _IOR('I', 64, int) +#define IMDELTIMER _IOR('I', 65, int) +/* socket ioctls */ +#define IMGETVERSION _IOR('I', 66, int) +#define IMGETCOUNT _IOR('I', 67, int) +#define IMGETDEVINFO _IOR('I', 68, int) +#define IMCTRLREQ _IOR('I', 69, int) +#define IMCLEAR_L2 _IOR('I', 70, int) +#define IMSETDEVNAME _IOR('I', 71, struct mISDN_devrename) + +static inline int +test_channelmap(u_int nr, u_char *map) +{ + if (nr <= MISDN_MAX_CHANNEL) + return map[nr >> 3] & (1 << (nr & 7)); + else + return 0; +} + +static inline void +set_channelmap(u_int nr, u_char *map) +{ + map[nr >> 3] |= (1 << (nr & 7)); +} + +static inline void +clear_channelmap(u_int nr, u_char *map) +{ + map[nr >> 3] &= ~(1 << (nr & 7)); +} + +/* CONTROL_CHANNEL parameters */ +#define MISDN_CTRL_GETOP 0x0000 +#define MISDN_CTRL_LOOP 0x0001 +#define MISDN_CTRL_CONNECT 0x0002 +#define MISDN_CTRL_DISCONNECT 0x0004 +#define MISDN_CTRL_PCMCONNECT 0x0010 +#define MISDN_CTRL_PCMDISCONNECT 0x0020 +#define MISDN_CTRL_SETPEER 0x0040 +#define MISDN_CTRL_UNSETPEER 0x0080 +#define MISDN_CTRL_RX_OFF 0x0100 +#define MISDN_CTRL_FILL_EMPTY 0x0200 +#define MISDN_CTRL_GETPEER 0x0400 +#define MISDN_CTRL_HW_FEATURES_OP 0x2000 +#define MISDN_CTRL_HW_FEATURES 0x2001 +#define MISDN_CTRL_HFC_OP 0x4000 +#define MISDN_CTRL_HFC_PCM_CONN 0x4001 +#define MISDN_CTRL_HFC_PCM_DISC 0x4002 +#define MISDN_CTRL_HFC_CONF_JOIN 0x4003 +#define MISDN_CTRL_HFC_CONF_SPLIT 0x4004 +#define MISDN_CTRL_HFC_RECEIVE_OFF 0x4005 +#define MISDN_CTRL_HFC_RECEIVE_ON 0x4006 +#define MISDN_CTRL_HFC_ECHOCAN_ON 0x4007 +#define MISDN_CTRL_HFC_ECHOCAN_OFF 0x4008 + + +/* socket options */ +#define MISDN_TIME_STAMP 0x0001 + +struct mISDN_ctrl_req { + int op; + int channel; + int p1; + int p2; +}; + +/* muxer options */ +#define MISDN_OPT_ALL 1 +#define MISDN_OPT_TEIMGR 2 + +#endif /* mISDNIF_H */ diff --git a/include/openbsc/Makefile.am b/include/openbsc/Makefile.am new file mode 100644 index 000000000..325d66d93 --- /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 000000000..faca5a31e --- /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 000000000..c93db582c --- /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 + * 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 . + * + */ + +#ifndef _NM_H +#define _NM_H + +#include +#include +#include + +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 000000000..e4f19cf9c --- /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 + * + * 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 . + * + */ + +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 000000000..295b01fd3 --- /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 + * 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 . + * + */ + +#ifndef _RSL_H +#define _RSL_H + +#include + +#include + +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 000000000..2364fb3d2 --- /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 000000000..36ec3705c --- /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 000000000..d06ae0511 --- /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 + * (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 . + * + */ + +#ifndef BSC_MSC_H +#define BSC_MSC_H + +#include +#include + +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 000000000..f74cae2a8 --- /dev/null +++ b/include/openbsc/bsc_nat.h @@ -0,0 +1,355 @@ +/* + * (C) 2010 by Holger Hans Peter Freyther + * (C) 2010 by On-Waves + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#ifndef BSC_NAT_H +#define BSC_NAT_H + +#include "mgcp.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 000000000..0ade668c4 --- /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 + * (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 . + * + */ + +#ifndef BSC_NAT_SCCP_H +#define BSC_NAT_SCCP_H + +#include +#include + +/* + * 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 000000000..b2898d1b0 --- /dev/null +++ b/include/openbsc/bsc_rll.h @@ -0,0 +1,19 @@ +#ifndef _BSC_RLL_H +#define _BSC_RLL_H + +#include + +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 000000000..5eda312ac --- /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 + * (C) 2009 by Holger Hans Peter Freyther + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +#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 000000000..358fcb58f --- /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 000000000..a939b0d63 --- /dev/null +++ b/include/openbsc/db.h @@ -0,0 +1,83 @@ +/* (C) 2008 by Jan Luebbe + * (C) 2009 by Holger Hans Peter Freyther + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#ifndef _DB_H +#define _DB_H + +#include + +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 000000000..eb290e416 --- /dev/null +++ b/include/openbsc/debug.h @@ -0,0 +1,70 @@ +#ifndef _DEBUG_H +#define _DEBUG_H + +#include +#include + +#define DEBUG +#include + +/* 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 000000000..3c8af3877 --- /dev/null +++ b/include/openbsc/e1_input.h @@ -0,0 +1,187 @@ +#ifndef _E1_INPUT_H +#define _E1_INPUT_H + +#include +#include + +#include +#include +#include +#include +#include + +#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 000000000..18ded2295 --- /dev/null +++ b/include/openbsc/gb_proxy.h @@ -0,0 +1,39 @@ +#ifndef _GB_PROXY_H +#define _GB_PROXY_H + +#include + +#include + +#include +#include + +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 000000000..e432cf750 --- /dev/null +++ b/include/openbsc/gprs_bssgp.h @@ -0,0 +1,232 @@ +#ifndef _GPRS_BSSGP_H +#define _GPRS_BSSGP_H + +#include + +/* 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 + +/* 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 000000000..bd129ae4d --- /dev/null +++ b/include/openbsc/gprs_gmm.h @@ -0,0 +1,19 @@ +#ifndef _GPRS_GMM_H +#define _GPRS_GMM_H + +#include +#include + +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 000000000..02945e164 --- /dev/null +++ b/include/openbsc/gprs_llc.h @@ -0,0 +1,162 @@ +#ifndef _GPRS_LLC_H +#define _GPRS_LLC_H + +#include +#include + +/* 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 000000000..953c364b8 --- /dev/null +++ b/include/openbsc/gprs_ns.h @@ -0,0 +1,232 @@ +#ifndef _GPRS_NS_H +#define _GPRS_NS_H + +#include + +/* 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 +#include +#include +#include +#include + +#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 000000000..abcd43ffb --- /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 000000000..b470c536c --- /dev/null +++ b/include/openbsc/gprs_sgsn.h @@ -0,0 +1,220 @@ +#ifndef _GPRS_SGSN_H +#define _GPRS_SGSN_H + +#include +#include + +#include + +#include + +#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 000000000..1c879edce --- /dev/null +++ b/include/openbsc/gsm_04_08.h @@ -0,0 +1,70 @@ +#ifndef _GSM_04_08_H +#define _GSM_04_08_H + +#include + +#include +#include + +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 000000000..8de636293 --- /dev/null +++ b/include/openbsc/gsm_04_08_gprs.h @@ -0,0 +1,383 @@ +#ifndef _GSM48_GPRS_H +#define _GSM48_GPRS_H + +#include +#include + +/* 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 000000000..5969788d5 --- /dev/null +++ b/include/openbsc/gsm_04_11.h @@ -0,0 +1,40 @@ +#ifndef _GSM_04_11_H +#define _GSM_04_11_H + +#include + +#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 000000000..796a1c11e --- /dev/null +++ b/include/openbsc/gsm_04_80.h @@ -0,0 +1,20 @@ +#ifndef _GSM_04_80_H +#define _GSM_04_80_H + +#include +#include +#include + +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 000000000..ae448c4c1 --- /dev/null +++ b/include/openbsc/gsm_data.h @@ -0,0 +1,879 @@ +#ifndef _GSM_DATA_H +#define _GSM_DATA_H + +#include + +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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + + +#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 000000000..c365bc7d7 --- /dev/null +++ b/include/openbsc/gsm_subscriber.h @@ -0,0 +1,107 @@ +#ifndef _GSM_SUBSCR_H +#define _GSM_SUBSCR_H + +#include +#include "gsm_data.h" +#include + +#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 000000000..9d9a90b84 --- /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 000000000..1d00d9792 --- /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 + +#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 000000000..3c2c8d1c1 --- /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 000000000..516b76edf --- /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 + * (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 . + * + */ + +#ifndef OPENBSC_MGCP_H +#define OPENBSC_MGCP_H + +#include +#include + +#include "debug.h" + +#include + +#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 000000000..7c6bb5425 --- /dev/null +++ b/include/openbsc/mgcp_internal.h @@ -0,0 +1,154 @@ +/* MGCP Private Data */ + +/* + * (C) 2009-2011 by Holger Hans Peter Freyther + * (C) 2009-2011 by On-Waves + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#ifndef OPENBSC_MGCP_DATA_H +#define OPENBSC_MGCP_DATA_H + +#include + +#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 000000000..0a8b063a4 --- /dev/null +++ b/include/openbsc/misdn.h @@ -0,0 +1,27 @@ +/* (C) 2008 by Harald Welte + * 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 . + * + */ + +#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 000000000..e514c19ae --- /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 + * (C) 2008, 2009 by Holger Hans Peter Freyther + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#ifndef _MNCC_H +#define _MNCC_H + +#include +#include + +#include + +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 000000000..67d1f4ef7 --- /dev/null +++ b/include/openbsc/network_listen.h @@ -0,0 +1,16 @@ +#ifndef _OPENBSC_NWL_H +#define _OPENBSC_NWL_H + +#include +#include + +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 000000000..c6ac153b8 --- /dev/null +++ b/include/openbsc/openbscdefines.h @@ -0,0 +1,34 @@ +/* + * (C) 2009 by Holger Hans Peter Freyther + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#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 000000000..ef0f11a3b --- /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 000000000..45d4db8ec --- /dev/null +++ b/include/openbsc/osmo_bsc_grace.h @@ -0,0 +1,28 @@ +/* + * (C) 2010 by Holger Hans Peter Freyther + * (C) 2010 by On-Waves + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#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 000000000..e43ae2e3f --- /dev/null +++ b/include/openbsc/osmo_bsc_rf.h @@ -0,0 +1,35 @@ +#ifndef OSMO_BSC_RF +#define OSMO_BSC_RF + +#include +#include + +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 000000000..beb3f5e4c --- /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 000000000..8f9ca6856 --- /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 + * (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 . + * + */ + +#ifndef _OSMO_MSC_DATA_H +#define _OSMO_MSC_DATA_H + +#include "bsc_msc.h" + +#include + +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 000000000..f71919916 --- /dev/null +++ b/include/openbsc/paging.h @@ -0,0 +1,71 @@ +/* Paging helper and manager.... */ +/* (C) 2009 by Holger Hans Peter Freyther + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#ifndef PAGING_H +#define PAGING_H + +#include +#include + +#include +#include "gsm_data.h" +#include "gsm_subscriber.h" +#include + +/** + * 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 000000000..6d9011963 --- /dev/null +++ b/include/openbsc/rest_octets.h @@ -0,0 +1,133 @@ +#ifndef _REST_OCTETS_H +#define _REST_OCTETS_H + +#include +#include + +/* 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 000000000..61187ca62 --- /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 000000000..53b58b4b5 --- /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 + * 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 . + * + */ + + +#include + +#include +#include + +#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 000000000..84db87e91 --- /dev/null +++ b/include/openbsc/sgsn.h @@ -0,0 +1,65 @@ +#ifndef _SGSN_H +#define _SGSN_H + +#include + +#include + +#include +#include + +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 000000000..a2257db73 --- /dev/null +++ b/include/openbsc/signal.h @@ -0,0 +1,255 @@ +/* Generic signalling/notification infrastructure */ +/* (C) 2009-2010 by Holger Hans Peter Freyther + * (C) 2009 by Harald Welte + * (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 . + * + */ + +#ifndef OPENBSC_SIGNAL_H +#define OPENBSC_SIGNAL_H + +#include +#include + +#include + +#include + +/* + * 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 000000000..2492903c2 --- /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 000000000..2a8bd5850 --- /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 000000000..4d3161146 --- /dev/null +++ b/include/openbsc/socket.h @@ -0,0 +1,14 @@ +#ifndef _BSC_SOCKET_H +#define _BSC_SOCKET_H + +#include +#include + +#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 000000000..da2a7f325 --- /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 + * 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 . + * + */ + +#include +#include + +#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 000000000..da662e912 --- /dev/null +++ b/include/openbsc/system_information.h @@ -0,0 +1,45 @@ +#ifndef _SYSTEM_INFO_H +#define _SYSTEM_INFO_H + +#include + +#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 000000000..e41d8ef91 --- /dev/null +++ b/include/openbsc/transaction.h @@ -0,0 +1,75 @@ +#ifndef _TRANSACT_H +#define _TRANSACT_H + +#include +#include +#include +#include + +/* 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 000000000..c594c38cb --- /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 + * 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 . + * + */ + +#include + +/* 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 000000000..dcf33ee8f --- /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 + * 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 . + * + */ + +/* 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 000000000..6f80d23d8 --- /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 + +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 000000000..516c8c2a0 --- /dev/null +++ b/include/openbsc/vty.h @@ -0,0 +1,46 @@ +#ifndef OPENBSC_VTY_H +#define OPENBSC_VTY_H + +#include +#include +#include + +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 -- cgit v1.2.3