Merge branch 'on-waves/mgcp'
diff --git a/libosmocore/.gitignore b/libosmocore/.gitignore
deleted file mode 100644
index 06904fa..0000000
--- a/libosmocore/.gitignore
+++ /dev/null
@@ -1,30 +0,0 @@
-Makefile
-Makefile.in
-.deps
-.libs
-*.o
-*.lo
-*.la
-*.pc
-aclocal.m4
-m4/*.m4
-autom4te.cache
-config.h*
-config.sub
-config.log
-config.status
-config.guess
-configure
-depcomp
-missing
-ltmain.sh
-install-sh
-stamp-h1
-libtool
-
-.tarball-version
-.version
-
-tests/sms/sms_test
-tests/timer/timer_test
-
diff --git a/libosmocore/COPYING b/libosmocore/COPYING
deleted file mode 100644
index d511905..0000000
--- a/libosmocore/COPYING
+++ /dev/null
@@ -1,339 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
diff --git a/libosmocore/Makefile.am b/libosmocore/Makefile.am
deleted file mode 100644
index 2adf502..0000000
--- a/libosmocore/Makefile.am
+++ /dev/null
@@ -1,14 +0,0 @@
-AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
-ACLOCAL_AMFLAGS = -I m4
-
-INCLUDES = $(all_includes) -I$(top_srcdir)/include
-SUBDIRS = include src tests
-
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = libosmocore.pc
-
-BUILT_SOURCES = $(top_srcdir)/.version
-$(top_srcdir)/.version:
- echo $(VERSION) > $@-t && mv $@-t $@
-dist-hook:
- echo $(VERSION) > $(distdir)/.tarball-version
diff --git a/libosmocore/configure.in b/libosmocore/configure.in
deleted file mode 100644
index 9879ebc..0000000
--- a/libosmocore/configure.in
+++ /dev/null
@@ -1,56 +0,0 @@
-AC_INIT([libosmocore],
- m4_esyscmd([./git-version-gen .tarball-version]),
- [openbsc-devel@lists.openbsc.org])
-
-AM_INIT_AUTOMAKE([dist-bzip2])
-
-dnl kernel style compile messages
-m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
-
-dnl checks for programs
-AC_PROG_MAKE_SET
-AC_PROG_CC
-AC_PROG_INSTALL
-LT_INIT
-AC_PROG_LIBTOOL
-
-AC_CONFIG_MACRO_DIR([m4])
-
-dnl checks for header files
-AC_HEADER_STDC
-AC_CHECK_HEADERS(execinfo.h sys/select.h)
-
-# The following test is taken from WebKit's webkit.m4
-saved_CFLAGS="$CFLAGS"
-CFLAGS="$CFLAGS -fvisibility=hidden "
-AC_MSG_CHECKING([if ${CC} supports -fvisibility=hidden])
-AC_COMPILE_IFELSE([char foo;],
- [ AC_MSG_RESULT([yes])
- SYMBOL_VISIBILITY="-fvisibility=hidden"],
- AC_MSG_RESULT([no]))
-CFLAGS="$saved_CFLAGS"
-AC_SUBST(SYMBOL_VISIBILITY)
-
-dnl Generate the output
-AM_CONFIG_HEADER(config.h)
-
-AC_ARG_ENABLE(talloc,
- [ --disable-talloc Disable building talloc memory allocator ],
- [enable_talloc=0], [enable_talloc=1])
-AM_CONDITIONAL(ENABLE_TALLOC, test "x$enable_talloc" = "x1")
-
-AC_ARG_ENABLE(tests,
- [ --disable-tests Disable building test programs ],
- [enable_tests=0], [enable_tests=1])
-AM_CONDITIONAL(ENABLE_TESTS, test "x$enable_tests" = "x1")
-
-AC_OUTPUT(
- libosmocore.pc
- include/osmocore/Makefile
- include/osmocore/protocol/Makefile
- include/Makefile
- src/Makefile
- tests/Makefile
- tests/timer/Makefile
- tests/sms/Makefile
- Makefile)
diff --git a/libosmocore/git-version-gen b/libosmocore/git-version-gen
deleted file mode 100755
index 42cf3d2..0000000
--- a/libosmocore/git-version-gen
+++ /dev/null
@@ -1,151 +0,0 @@
-#!/bin/sh
-# Print a version string.
-scriptversion=2010-01-28.01
-
-# Copyright (C) 2007-2010 Free Software Foundation, Inc.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
-# It may be run two ways:
-# - from a git repository in which the "git describe" command below
-# produces useful output (thus requiring at least one signed tag)
-# - from a non-git-repo directory containing a .tarball-version file, which
-# presumes this script is invoked like "./git-version-gen .tarball-version".
-
-# In order to use intra-version strings in your project, you will need two
-# separate generated version string files:
-#
-# .tarball-version - present only in a distribution tarball, and not in
-# a checked-out repository. Created with contents that were learned at
-# the last time autoconf was run, and used by git-version-gen. Must not
-# be present in either $(srcdir) or $(builddir) for git-version-gen to
-# give accurate answers during normal development with a checked out tree,
-# but must be present in a tarball when there is no version control system.
-# Therefore, it cannot be used in any dependencies. GNUmakefile has
-# hooks to force a reconfigure at distribution time to get the value
-# correct, without penalizing normal development with extra reconfigures.
-#
-# .version - present in a checked-out repository and in a distribution
-# tarball. Usable in dependencies, particularly for files that don't
-# want to depend on config.h but do want to track version changes.
-# Delete this file prior to any autoconf run where you want to rebuild
-# files to pick up a version string change; and leave it stale to
-# minimize rebuild time after unrelated changes to configure sources.
-#
-# It is probably wise to add these two files to .gitignore, so that you
-# don't accidentally commit either generated file.
-#
-# Use the following line in your configure.ac, so that $(VERSION) will
-# automatically be up-to-date each time configure is run (and note that
-# since configure.ac no longer includes a version string, Makefile rules
-# should not depend on configure.ac for version updates).
-#
-# AC_INIT([GNU project],
-# m4_esyscmd([build-aux/git-version-gen .tarball-version]),
-# [bug-project@example])
-#
-# Then use the following lines in your Makefile.am, so that .version
-# will be present for dependencies, and so that .tarball-version will
-# exist in distribution tarballs.
-#
-# BUILT_SOURCES = $(top_srcdir)/.version
-# $(top_srcdir)/.version:
-# echo $(VERSION) > $@-t && mv $@-t $@
-# dist-hook:
-# echo $(VERSION) > $(distdir)/.tarball-version
-
-case $# in
- 1) ;;
- *) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"; exit 1;;
-esac
-
-tarball_version_file=$1
-nl='
-'
-
-# First see if there is a tarball-only version file.
-# then try "git describe", then default.
-if test -f $tarball_version_file
-then
- v=`cat $tarball_version_file` || exit 1
- case $v in
- *$nl*) v= ;; # reject multi-line output
- [0-9]*) ;;
- *) v= ;;
- esac
- test -z "$v" \
- && echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2
-fi
-
-if test -n "$v"
-then
- : # use $v
-elif
- v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
- || git describe --abbrev=4 HEAD 2>/dev/null` \
- && case $v in
- [0-9]*) ;;
- v[0-9]*) ;;
- *) (exit 1) ;;
- esac
-then
- # Is this a new git that lists number of commits since the last
- # tag or the previous older version that did not?
- # Newer: v6.10-77-g0f8faeb
- # Older: v6.10-g0f8faeb
- case $v in
- *-*-*) : git describe is okay three part flavor ;;
- *-*)
- : git describe is older two part flavor
- # Recreate the number of commits and rewrite such that the
- # result is the same as if we were using the newer version
- # of git describe.
- vtag=`echo "$v" | sed 's/-.*//'`
- numcommits=`git rev-list "$vtag"..HEAD | wc -l`
- v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
- ;;
- esac
-
- # Change the first '-' to a '.', so version-comparing tools work properly.
- # Remove the "g" in git describe's output string, to save a byte.
- v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
-else
- v=UNKNOWN
-fi
-
-v=`echo "$v" |sed 's/^v//'`
-
-# Don't declare a version "dirty" merely because a time stamp has changed.
-git status > /dev/null 2>&1
-
-dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
-case "$dirty" in
- '') ;;
- *) # Append the suffix only if there isn't one already.
- case $v in
- *-dirty) ;;
- *) v="$v-dirty" ;;
- esac ;;
-esac
-
-# Omit the trailing newline, so that m4_esyscmd can use the result directly.
-echo "$v" | tr -d '\012'
-
-# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "scriptversion="
-# time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-end: "$"
-# End:
diff --git a/libosmocore/include/Makefile.am b/libosmocore/include/Makefile.am
deleted file mode 100644
index f0015d5..0000000
--- a/libosmocore/include/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-SUBDIRS = osmocore
diff --git a/libosmocore/include/osmocore/Makefile.am b/libosmocore/include/osmocore/Makefile.am
deleted file mode 100644
index fde0102..0000000
--- a/libosmocore/include/osmocore/Makefile.am
+++ /dev/null
@@ -1,12 +0,0 @@
-osmocore_HEADERS = signal.h linuxlist.h timer.h select.h msgb.h \
- tlv.h bitvec.h comp128.h statistics.h gsm_utils.h utils.h \
- gsmtap.h write_queue.h rsl.h gsm48.h rxlev_stat.h mncc.h \
- gsm48_ie.h logging.h gsm0808.h rate_ctr.h
-
-if ENABLE_TALLOC
-osmocore_HEADERS += talloc.h
-endif
-
-osmocoredir = $(includedir)/osmocore
-
-SUBDIRS = protocol
diff --git a/libosmocore/include/osmocore/bitvec.h b/libosmocore/include/osmocore/bitvec.h
deleted file mode 100644
index 7a26bce..0000000
--- a/libosmocore/include/osmocore/bitvec.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef _BITVEC_H
-#define _BITVEC_H
-
-/* bit vector utility routines */
-
-/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-
-/* In GSM mac blocks, every bit can be 0 or 1, or L or H. L/H are
- * defined relative to the 0x2b padding pattern */
-enum bit_value {
- ZERO = 0,
- ONE = 1,
- L = 2,
- H = 3,
-};
-
-struct bitvec {
- unsigned int cur_bit; /* curser to the next unused bit */
- unsigned int data_len; /* length of data array in bytes */
- uint8_t *data; /* pointer to data array */
-};
-
-/* check if the bit is 0 or 1 for a given position inside a bitvec */
-enum bit_value bitvec_get_bit_pos(const struct bitvec *bv, unsigned int bitnr);
-
-/* get the Nth set bit inside the bit vector */
-unsigned int bitvec_get_nth_set_bit(const struct bitvec *bv, unsigned int n);
-
-/* Set a bit at given position */
-int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnum,
- enum bit_value bit);
-
-/* Set the next bit in the vector */
-int bitvec_set_bit(struct bitvec *bv, enum bit_value bit);
-
-/* Set multiple bits at the current position */
-int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count);
-
-/* Add an unsigned integer (of length count bits) to current position */
-int bitvec_set_uint(struct bitvec *bv, unsigned int in, int count);
-
-
-/* Pad the bit vector up to a certain bit position */
-int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit);
-
-#endif /* _BITVEC_H */
diff --git a/libosmocore/include/osmocore/comp128.h b/libosmocore/include/osmocore/comp128.h
deleted file mode 100644
index c37808f..0000000
--- a/libosmocore/include/osmocore/comp128.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * COMP128 header
- *
- * See comp128.c for details
- */
-
-#ifndef __COMP128_H__
-#define __COMP128_H__
-
-#include <stdint.h>
-
-/*
- * Performs the COMP128 algorithm (used as A3/A8)
- * ki : uint8_t [16]
- * srand : uint8_t [16]
- * sres : uint8_t [4]
- * kc : uint8_t [8]
- */
-void comp128(uint8_t *ki, uint8_t *srand, uint8_t *sres, uint8_t *kc);
-
-#endif /* __COMP128_H__ */
-
diff --git a/libosmocore/include/osmocore/gsm0808.h b/libosmocore/include/osmocore/gsm0808.h
deleted file mode 100644
index a40713f..0000000
--- a/libosmocore/include/osmocore/gsm0808.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* (C) 2009,2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009,2010 by On-Waves
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-#ifndef OSMOCORE_GSM0808_H
-#define OSMOCORE_GSM0808_H
-
-#include "tlv.h"
-
-struct msgb;
-
-struct msgb *gsm0808_create_layer3(struct msgb *msg, uint16_t netcode, uint16_t countrycode, int lac, int ci);
-struct msgb *gsm0808_create_reset(void);
-struct msgb *gsm0808_create_clear_complete(void);
-struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id);
-struct msgb *gsm0808_create_cipher_reject(uint8_t cause);
-struct msgb *gsm0808_create_classmark_update(const uint8_t *classmark, uint8_t length);
-struct msgb *gsm0808_create_sapi_reject(uint8_t link_id);
-struct msgb *gsm0808_create_assignment_completed(struct gsm_lchan *lchan, uint8_t rr_cause,
- uint8_t chosen_channel, uint8_t encr_alg_id,
- uint8_t speech_mode);
-struct msgb *gsm0808_create_assignment_failure(uint8_t cause, uint8_t *rr_cause);
-
-const struct tlv_definition *gsm0808_att_tlvdef();
-
-#endif
diff --git a/libosmocore/include/osmocore/gsm48.h b/libosmocore/include/osmocore/gsm48.h
deleted file mode 100644
index be9fbbd..0000000
--- a/libosmocore/include/osmocore/gsm48.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef _OSMOCORE_GSM48_H
-#define _OSMOCORE_GSM48_H
-
-#include <osmocore/tlv.h>
-#include <osmocore/protocol/gsm_04_08.h>
-#include <osmocore/gsm48_ie.h>
-
-/* A parsed GPRS routing area */
-struct gprs_ra_id {
- uint16_t mnc;
- uint16_t mcc;
- uint16_t lac;
- uint8_t rac;
-};
-
-extern const struct tlv_definition gsm48_att_tlvdef;
-const char *gsm48_cc_state_name(uint8_t state);
-const char *gsm48_cc_msg_name(uint8_t msgtype);
-const char *rr_cause_name(uint8_t cause);
-
-void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
- uint16_t mnc, uint16_t lac);
-int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi);
-int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi);
-
-/* Convert Mobile Identity (10.5.1.4) to string */
-int gsm48_mi_to_string(char *string, const int str_len,
- const uint8_t *mi, const int mi_len);
-
-/* Parse Routeing Area Identifier */
-void gsm48_parse_ra(struct gprs_ra_id *raid, const uint8_t *buf);
-int gsm48_construct_ra(uint8_t *buf, const struct gprs_ra_id *raid);
-
-#endif
diff --git a/libosmocore/include/osmocore/gsm48_ie.h b/libosmocore/include/osmocore/gsm48_ie.h
deleted file mode 100644
index 200619a..0000000
--- a/libosmocore/include/osmocore/gsm48_ie.h
+++ /dev/null
@@ -1,107 +0,0 @@
-#ifndef _OSMOCORE_GSM48_IE_H
-#define _OSMOCORE_GSM48_IE_H
-
-#include <stdint.h>
-#include <string.h>
-#include <errno.h>
-
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.h>
-#include <osmocore/mncc.h>
-#include <osmocore/protocol/gsm_04_08.h>
-
-/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
-int gsm48_decode_bcd_number(char *output, int output_len,
- const uint8_t *bcd_lv, int h_len);
-
-/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
-int gsm48_encode_bcd_number(uint8_t *bcd_lv, uint8_t max_len,
- int h_len, const char *input);
-/* decode 'bearer capability' */
-int gsm48_decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
- const uint8_t *lv);
-/* encode 'bearer capability' */
-int gsm48_encode_bearer_cap(struct msgb *msg, int lv_only,
- const struct gsm_mncc_bearer_cap *bcap);
-/* decode 'call control cap' */
-int gsm48_decode_cccap(struct gsm_mncc_cccap *ccap, const uint8_t *lv);
-/* encode 'call control cap' */
-int gsm48_encode_cccap(struct msgb *msg,
- const struct gsm_mncc_cccap *ccap);
-/* decode 'called party BCD number' */
-int gsm48_decode_called(struct gsm_mncc_number *called,
- const uint8_t *lv);
-/* encode 'called party BCD number' */
-int gsm48_encode_called(struct msgb *msg,
- const struct gsm_mncc_number *called);
-/* decode callerid of various IEs */
-int gsm48_decode_callerid(struct gsm_mncc_number *callerid,
- const uint8_t *lv);
-/* encode callerid of various IEs */
-int gsm48_encode_callerid(struct msgb *msg, int ie, int max_len,
- const struct gsm_mncc_number *callerid);
-/* decode 'cause' */
-int gsm48_decode_cause(struct gsm_mncc_cause *cause,
- const uint8_t *lv);
-/* encode 'cause' */
-int gsm48_encode_cause(struct msgb *msg, int lv_only,
- const struct gsm_mncc_cause *cause);
-/* decode 'calling number' */
-int gsm48_decode_calling(struct gsm_mncc_number *calling,
- const uint8_t *lv);
-/* encode 'calling number' */
-int gsm48_encode_calling(struct msgb *msg,
- const struct gsm_mncc_number *calling);
-/* decode 'connected number' */
-int gsm48_decode_connected(struct gsm_mncc_number *connected,
- const uint8_t *lv);
-/* encode 'connected number' */
-int gsm48_encode_connected(struct msgb *msg,
- const struct gsm_mncc_number *connected);
-/* decode 'redirecting number' */
-int gsm48_decode_redirecting(struct gsm_mncc_number *redirecting,
- const uint8_t *lv);
-/* encode 'redirecting number' */
-int gsm48_encode_redirecting(struct msgb *msg,
- const struct gsm_mncc_number *redirecting);
-/* decode 'facility' */
-int gsm48_decode_facility(struct gsm_mncc_facility *facility,
- const uint8_t *lv);
-/* encode 'facility' */
-int gsm48_encode_facility(struct msgb *msg, int lv_only,
- const struct gsm_mncc_facility *facility);
-/* decode 'notify' */
-int gsm48_decode_notify(int *notify, const uint8_t *v);
-/* encode 'notify' */
-int gsm48_encode_notify(struct msgb *msg, int notify);
-/* decode 'signal' */
-int gsm48_decode_signal(int *signal, const uint8_t *v);
-/* encode 'signal' */
-int gsm48_encode_signal(struct msgb *msg, int signal);
-/* decode 'keypad' */
-int gsm48_decode_keypad(int *keypad, const uint8_t *lv);
-/* encode 'keypad' */
-int gsm48_encode_keypad(struct msgb *msg, int keypad);
-/* decode 'progress' */
-int gsm48_decode_progress(struct gsm_mncc_progress *progress,
- const uint8_t *lv);
-/* encode 'progress' */
-int gsm48_encode_progress(struct msgb *msg, int lv_only,
- const struct gsm_mncc_progress *p);
-/* decode 'user-user' */
-int gsm48_decode_useruser(struct gsm_mncc_useruser *uu,
- const uint8_t *lv);
-/* encode 'useruser' */
-int gsm48_encode_useruser(struct msgb *msg, int lv_only,
- const struct gsm_mncc_useruser *uu);
-/* decode 'ss version' */
-int gsm48_decode_ssversion(struct gsm_mncc_ssversion *ssv,
- const uint8_t *lv);
-/* encode 'ss version' */
-int gsm48_encode_ssversion(struct msgb *msg,
- const struct gsm_mncc_ssversion *ssv);
-/* decode 'more data' does not require a function, because it has no value */
-/* encode 'more data' */
-int gsm48_encode_more(struct msgb *msg);
-
-#endif
diff --git a/libosmocore/include/osmocore/gsm_utils.h b/libosmocore/include/osmocore/gsm_utils.h
deleted file mode 100644
index 51e9f2e..0000000
--- a/libosmocore/include/osmocore/gsm_utils.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* GSM utility functions, e.g. coding and decoding */
-/*
- * (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
- * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef GSM_UTILS_H
-#define GSM_UTILS_H
-
-#include <stdint.h>
-
-#define ADD_MODULO(sum, delta, modulo) do { \
- if ((sum += delta) >= modulo) \
- sum -= modulo; \
- } while (0)
-
-#define GSM_MAX_FN (26*51*2048)
-
-struct gsm_time {
- uint32_t fn; /* FN count */
- uint16_t t1; /* FN div (26*51) */
- uint8_t t2; /* FN modulo 26 */
- uint8_t t3; /* FN modulo 51 */
- uint8_t tc;
-};
-
-enum gsm_band {
- GSM_BAND_850 = 1,
- GSM_BAND_900 = 2,
- GSM_BAND_1800 = 4,
- GSM_BAND_1900 = 8,
- GSM_BAND_450 = 0x10,
- GSM_BAND_480 = 0x20,
- GSM_BAND_750 = 0x40,
- GSM_BAND_810 = 0x80,
-};
-
-const char *gsm_band_name(enum gsm_band band);
-enum gsm_band gsm_band_parse(const char *mhz);
-
-int gsm_7bit_decode(char *decoded, const uint8_t *user_data, uint8_t length);
-int gsm_7bit_encode(uint8_t *result, const char *data);
-
-int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm);
-int ms_pwr_dbm(enum gsm_band band, uint8_t lvl);
-
-/* According to TS 08.05 Chapter 8.1.4 */
-int rxlev2dbm(uint8_t rxlev);
-uint8_t dbm2rxlev(int dbm);
-
-/* According to GSM 04.08 Chapter 10.5.2.29 */
-static inline int rach_max_trans_val2raw(int val) { return (val >> 1) & 3; }
-static inline int rach_max_trans_raw2val(int raw) {
- const int tbl[4] = { 1, 2, 4, 7 };
- return tbl[raw & 3];
-}
-
-#define ARFCN_PCS 0x8000
-#define ARFCN_UPLINK 0x4000
-
-enum gsm_band gsm_arfcn2band(uint16_t arfcn);
-
-/* Convert an ARFCN to the frequency in MHz * 10 */
-uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink);
-
-/* Convert from frame number to GSM time */
-void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn);
-
-/* Convert from GSM time to frame number */
-uint32_t gsm_gsmtime2fn(struct gsm_time *time);
-
-/* GSM TS 03.03 Chapter 2.6 */
-enum gprs_tlli_tyoe {
- TLLI_LOCAL,
- TLLI_FOREIGN,
- TLLI_RANDOM,
- TLLI_AUXILIARY,
- TLLI_RESERVED,
-};
-
-/* TS 03.03 Chapter 2.6 */
-int gprs_tlli_type(uint32_t tlli);
-
-void generate_backtrace();
-#endif
diff --git a/libosmocore/include/osmocore/gsmtap.h b/libosmocore/include/osmocore/gsmtap.h
deleted file mode 100644
index dcd64bd..0000000
--- a/libosmocore/include/osmocore/gsmtap.h
+++ /dev/null
@@ -1,72 +0,0 @@
-#ifndef _GSMTAP_H
-#define _GSMTAP_H
-
-/* gsmtap header, pseudo-header in front of the actua GSM payload */
-
-/* GSMTAP is a generic header format for GSM protocol captures,
- * it uses the IANA-assigned UDP port number 4729 and carries
- * payload in various formats of GSM interfaces such as Um MAC
- * blocks or Um bursts.
- *
- * Example programs generating GSMTAP data are airprobe
- * (http://airprobe.org/) or OsmocomBB (http://bb.osmocom.org/)
- */
-
-#include <stdint.h>
-
-#define GSMTAP_VERSION 0x02
-
-#define GSMTAP_TYPE_UM 0x01
-#define GSMTAP_TYPE_ABIS 0x02
-#define GSMTAP_TYPE_UM_BURST 0x03 /* raw burst bits */
-
-#define GSMTAP_BURST_UNKNOWN 0x00
-#define GSMTAP_BURST_FCCH 0x01
-#define GSMTAP_BURST_PARTIAL_SCH 0x02
-#define GSMTAP_BURST_SCH 0x03
-#define GSMTAP_BURST_CTS_SCH 0x04
-#define GSMTAP_BURST_COMPACT_SCH 0x05
-#define GSMTAP_BURST_NORMAL 0x06
-#define GSMTAP_BURST_DUMMY 0x07
-#define GSMTAP_BURST_ACCESS 0x08
-#define GSMTAP_BURST_NONE 0x09
-
-#define GSMTAP_CHANNEL_UNKNOWN 0x00
-#define GSMTAP_CHANNEL_BCCH 0x01
-#define GSMTAP_CHANNEL_CCCH 0x02
-#define GSMTAP_CHANNEL_RACH 0x03
-#define GSMTAP_CHANNEL_AGCH 0x04
-#define GSMTAP_CHANNEL_PCH 0x05
-#define GSMTAP_CHANNEL_SDCCH 0x06
-#define GSMTAP_CHANNEL_SDCCH4 0x07
-#define GSMTAP_CHANNEL_SDCCH8 0x08
-#define GSMTAP_CHANNEL_TCH_F 0x09
-#define GSMTAP_CHANNEL_TCH_H 0x0a
-#define GSMTAP_CHANNEL_ACCH 0x80
-
-#define GSMTAP_ARFCN_F_PCS 0x8000
-#define GSMTAP_ARFCN_F_UPLINK 0x4000
-#define GSMTAP_ARFCN_MASK 0x3fff
-
-#define GSMTAP_UDP_PORT 4729
-
-struct gsmtap_hdr {
- uint8_t version; /* version, set to 0x01 currently */
- uint8_t hdr_len; /* length in number of 32bit words */
- uint8_t type; /* see GSMTAP_TYPE_* */
- uint8_t timeslot; /* timeslot (0..7 on Um) */
-
- uint16_t arfcn; /* ARFCN (frequency) */
- int8_t signal_dbm; /* signal level in dBm */
- int8_t snr_db; /* signal/noise ratio in dB */
-
- uint32_t frame_number; /* GSM Frame Number (FN) */
-
- uint8_t sub_type; /* Type of burst/channel, see above */
- uint8_t antenna_nr; /* Antenna Number */
- uint8_t sub_slot; /* sub-slot within timeslot */
- uint8_t res; /* reserved for future use (RFU) */
-
-} __attribute__((packed));
-
-#endif /* _GSMTAP_H */
diff --git a/libosmocore/include/osmocore/linuxlist.h b/libosmocore/include/osmocore/linuxlist.h
deleted file mode 100644
index fb99c5e..0000000
--- a/libosmocore/include/osmocore/linuxlist.h
+++ /dev/null
@@ -1,360 +0,0 @@
-#ifndef _LINUX_LLIST_H
-#define _LINUX_LLIST_H
-
-#include <stddef.h>
-
-#ifndef inline
-#define inline __inline__
-#endif
-
-static inline void prefetch(const void *x) {;}
-
-/**
- * container_of - cast a member of a structure out to the containing structure
- *
- * @ptr: the pointer to the member.
- * @type: the type of the container struct this is embedded in.
- * @member: the name of the member within the struct.
- *
- */
-#define container_of(ptr, type, member) ({ \
- const typeof( ((type *)0)->member ) *__mptr = (typeof( ((type *)0)->member ) *)(ptr); \
- (type *)( (char *)__mptr - offsetof(type, member) );})
-
-
-/*
- * These are non-NULL pointers that will result in page faults
- * under normal circumstances, used to verify that nobody uses
- * non-initialized llist entries.
- */
-#define LLIST_POISON1 ((void *) 0x00100100)
-#define LLIST_POISON2 ((void *) 0x00200200)
-
-/*
- * Simple doubly linked llist implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole llists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-
-struct llist_head {
- struct llist_head *next, *prev;
-};
-
-#define LLIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LLIST_HEAD(name) \
- struct llist_head name = LLIST_HEAD_INIT(name)
-
-#define INIT_LLIST_HEAD(ptr) do { \
- (ptr)->next = (ptr); (ptr)->prev = (ptr); \
-} while (0)
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal llist manipulation where we know
- * the prev/next entries already!
- */
-static inline void __llist_add(struct llist_head *_new,
- struct llist_head *prev,
- struct llist_head *next)
-{
- next->prev = _new;
- _new->next = next;
- _new->prev = prev;
- prev->next = _new;
-}
-
-/**
- * llist_add - add a new entry
- * @new: new entry to be added
- * @head: llist head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-static inline void llist_add(struct llist_head *_new, struct llist_head *head)
-{
- __llist_add(_new, head, head->next);
-}
-
-/**
- * llist_add_tail - add a new entry
- * @new: new entry to be added
- * @head: llist head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-static inline void llist_add_tail(struct llist_head *_new, struct llist_head *head)
-{
- __llist_add(_new, head->prev, head);
-}
-
-/*
- * Delete a llist entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal llist manipulation where we know
- * the prev/next entries already!
- */
-static inline void __llist_del(struct llist_head * prev, struct llist_head * next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-/**
- * llist_del - deletes entry from llist.
- * @entry: the element to delete from the llist.
- * Note: llist_empty on entry does not return true after this, the entry is
- * in an undefined state.
- */
-static inline void llist_del(struct llist_head *entry)
-{
- __llist_del(entry->prev, entry->next);
- entry->next = (struct llist_head *)LLIST_POISON1;
- entry->prev = (struct llist_head *)LLIST_POISON2;
-}
-
-/**
- * llist_del_init - deletes entry from llist and reinitialize it.
- * @entry: the element to delete from the llist.
- */
-static inline void llist_del_init(struct llist_head *entry)
-{
- __llist_del(entry->prev, entry->next);
- INIT_LLIST_HEAD(entry);
-}
-
-/**
- * llist_move - delete from one llist and add as another's head
- * @llist: the entry to move
- * @head: the head that will precede our entry
- */
-static inline void llist_move(struct llist_head *llist, struct llist_head *head)
-{
- __llist_del(llist->prev, llist->next);
- llist_add(llist, head);
-}
-
-/**
- * llist_move_tail - delete from one llist and add as another's tail
- * @llist: the entry to move
- * @head: the head that will follow our entry
- */
-static inline void llist_move_tail(struct llist_head *llist,
- struct llist_head *head)
-{
- __llist_del(llist->prev, llist->next);
- llist_add_tail(llist, head);
-}
-
-/**
- * llist_empty - tests whether a llist is empty
- * @head: the llist to test.
- */
-static inline int llist_empty(const struct llist_head *head)
-{
- return head->next == head;
-}
-
-static inline void __llist_splice(struct llist_head *llist,
- struct llist_head *head)
-{
- struct llist_head *first = llist->next;
- struct llist_head *last = llist->prev;
- struct llist_head *at = head->next;
-
- first->prev = head;
- head->next = first;
-
- last->next = at;
- at->prev = last;
-}
-
-/**
- * llist_splice - join two llists
- * @llist: the new llist to add.
- * @head: the place to add it in the first llist.
- */
-static inline void llist_splice(struct llist_head *llist, struct llist_head *head)
-{
- if (!llist_empty(llist))
- __llist_splice(llist, head);
-}
-
-/**
- * llist_splice_init - join two llists and reinitialise the emptied llist.
- * @llist: the new llist to add.
- * @head: the place to add it in the first llist.
- *
- * The llist at @llist is reinitialised
- */
-static inline void llist_splice_init(struct llist_head *llist,
- struct llist_head *head)
-{
- if (!llist_empty(llist)) {
- __llist_splice(llist, head);
- INIT_LLIST_HEAD(llist);
- }
-}
-
-/**
- * llist_entry - get the struct for this entry
- * @ptr: the &struct llist_head pointer.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the llist_struct within the struct.
- */
-#define llist_entry(ptr, type, member) \
- container_of(ptr, type, member)
-
-/**
- * llist_for_each - iterate over a llist
- * @pos: the &struct llist_head to use as a loop counter.
- * @head: the head for your llist.
- */
-#define llist_for_each(pos, head) \
- for (pos = (head)->next, prefetch(pos->next); pos != (head); \
- pos = pos->next, prefetch(pos->next))
-
-/**
- * __llist_for_each - iterate over a llist
- * @pos: the &struct llist_head to use as a loop counter.
- * @head: the head for your llist.
- *
- * This variant differs from llist_for_each() in that it's the
- * simplest possible llist iteration code, no prefetching is done.
- * Use this for code that knows the llist to be very short (empty
- * or 1 entry) most of the time.
- */
-#define __llist_for_each(pos, head) \
- for (pos = (head)->next; pos != (head); pos = pos->next)
-
-/**
- * llist_for_each_prev - iterate over a llist backwards
- * @pos: the &struct llist_head to use as a loop counter.
- * @head: the head for your llist.
- */
-#define llist_for_each_prev(pos, head) \
- for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
- pos = pos->prev, prefetch(pos->prev))
-
-/**
- * llist_for_each_safe - iterate over a llist safe against removal of llist entry
- * @pos: the &struct llist_head to use as a loop counter.
- * @n: another &struct llist_head to use as temporary storage
- * @head: the head for your llist.
- */
-#define llist_for_each_safe(pos, n, head) \
- for (pos = (head)->next, n = pos->next; pos != (head); \
- pos = n, n = pos->next)
-
-/**
- * llist_for_each_entry - iterate over llist of given type
- * @pos: the type * to use as a loop counter.
- * @head: the head for your llist.
- * @member: the name of the llist_struct within the struct.
- */
-#define llist_for_each_entry(pos, head, member) \
- for (pos = llist_entry((head)->next, typeof(*pos), member), \
- prefetch(pos->member.next); \
- &pos->member != (head); \
- pos = llist_entry(pos->member.next, typeof(*pos), member), \
- prefetch(pos->member.next))
-
-/**
- * llist_for_each_entry_reverse - iterate backwards over llist of given type.
- * @pos: the type * to use as a loop counter.
- * @head: the head for your llist.
- * @member: the name of the llist_struct within the struct.
- */
-#define llist_for_each_entry_reverse(pos, head, member) \
- for (pos = llist_entry((head)->prev, typeof(*pos), member), \
- prefetch(pos->member.prev); \
- &pos->member != (head); \
- pos = llist_entry(pos->member.prev, typeof(*pos), member), \
- prefetch(pos->member.prev))
-
-/**
- * llist_for_each_entry_continue - iterate over llist of given type
- * continuing after existing point
- * @pos: the type * to use as a loop counter.
- * @head: the head for your llist.
- * @member: the name of the llist_struct within the struct.
- */
-#define llist_for_each_entry_continue(pos, head, member) \
- for (pos = llist_entry(pos->member.next, typeof(*pos), member), \
- prefetch(pos->member.next); \
- &pos->member != (head); \
- pos = llist_entry(pos->member.next, typeof(*pos), member), \
- prefetch(pos->member.next))
-
-/**
- * llist_for_each_entry_safe - iterate over llist of given type safe against removal of llist entry
- * @pos: the type * to use as a loop counter.
- * @n: another type * to use as temporary storage
- * @head: the head for your llist.
- * @member: the name of the llist_struct within the struct.
- */
-#define llist_for_each_entry_safe(pos, n, head, member) \
- for (pos = llist_entry((head)->next, typeof(*pos), member), \
- n = llist_entry(pos->member.next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = n, n = llist_entry(n->member.next, typeof(*n), member))
-
-/**
- * llist_for_each_rcu - iterate over an rcu-protected llist
- * @pos: the &struct llist_head to use as a loop counter.
- * @head: the head for your llist.
- */
-#define llist_for_each_rcu(pos, head) \
- for (pos = (head)->next, prefetch(pos->next); pos != (head); \
- pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next))
-
-#define __llist_for_each_rcu(pos, head) \
- for (pos = (head)->next; pos != (head); \
- pos = pos->next, ({ smp_read_barrier_depends(); 0;}))
-
-/**
- * llist_for_each_safe_rcu - iterate over an rcu-protected llist safe
- * against removal of llist entry
- * @pos: the &struct llist_head to use as a loop counter.
- * @n: another &struct llist_head to use as temporary storage
- * @head: the head for your llist.
- */
-#define llist_for_each_safe_rcu(pos, n, head) \
- for (pos = (head)->next, n = pos->next; pos != (head); \
- pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next)
-
-/**
- * llist_for_each_entry_rcu - iterate over rcu llist of given type
- * @pos: the type * to use as a loop counter.
- * @head: the head for your llist.
- * @member: the name of the llist_struct within the struct.
- */
-#define llist_for_each_entry_rcu(pos, head, member) \
- for (pos = llist_entry((head)->next, typeof(*pos), member), \
- prefetch(pos->member.next); \
- &pos->member != (head); \
- pos = llist_entry(pos->member.next, typeof(*pos), member), \
- ({ smp_read_barrier_depends(); 0;}), \
- prefetch(pos->member.next))
-
-
-/**
- * llist_for_each_continue_rcu - iterate over an rcu-protected llist
- * continuing after existing point.
- * @pos: the &struct llist_head to use as a loop counter.
- * @head: the head for your llist.
- */
-#define llist_for_each_continue_rcu(pos, head) \
- for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \
- (pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next))
-
-
-#endif
diff --git a/libosmocore/include/osmocore/logging.h b/libosmocore/include/osmocore/logging.h
deleted file mode 100644
index 2e82959..0000000
--- a/libosmocore/include/osmocore/logging.h
+++ /dev/null
@@ -1,135 +0,0 @@
-#ifndef _OSMOCORE_LOGGING_H
-#define _OSMOCORE_LOGGING_H
-
-#include <stdio.h>
-#include <stdint.h>
-#include <osmocore/linuxlist.h>
-
-#define LOG_MAX_CATEGORY 32
-#define LOG_MAX_CTX 8
-#define LOG_MAX_FILTERS 8
-
-#define DEBUG
-
-#ifdef DEBUG
-#define DEBUGP(ss, fmt, args...) logp(ss, __FILE__, __LINE__, 0, fmt, ## args)
-#define DEBUGPC(ss, fmt, args...) logp(ss, __FILE__, __LINE__, 1, fmt, ## args)
-#else
-#define DEBUGP(xss, fmt, args...)
-#define DEBUGPC(ss, fmt, args...)
-#endif
-
-#define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1];
-
-char *hexdump(const unsigned char *buf, int len);
-void logp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6)));
-
-/* new logging interface */
-#define LOGP(ss, level, fmt, args...) \
- logp2(ss, level, __FILE__, __LINE__, 0, fmt, ##args)
-#define LOGPC(ss, level, fmt, args...) \
- logp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args)
-
-/* different levels */
-#define LOGL_DEBUG 1 /* debugging information */
-#define LOGL_INFO 3
-#define LOGL_NOTICE 5 /* abnormal/unexpected condition */
-#define LOGL_ERROR 7 /* error condition, requires user action */
-#define LOGL_FATAL 8 /* fatal, program aborted */
-
-#define LOG_FILTER_ALL 0x0001
-
-struct log_category {
- uint8_t loglevel;
- uint8_t enabled;
-};
-
-struct log_info_cat {
- const char *name;
- const char *color;
- const char *description;
- uint8_t loglevel;
- uint8_t enabled;
-};
-
-/* log context information, passed to filter */
-struct log_context {
- void *ctx[LOG_MAX_CTX+1];
-};
-
-struct log_target;
-
-typedef int log_filter(const struct log_context *ctx,
- struct log_target *target);
-
-struct log_info {
- /* filter callback function */
- log_filter *filter_fn;
-
- /* per-category information */
- const struct log_info_cat *cat;
- unsigned int num_cat;
-};
-
-struct log_target {
- struct llist_head entry;
-
- int filter_map;
- void *filter_data[LOG_MAX_FILTERS+1];
-
- struct log_category categories[LOG_MAX_CATEGORY+1];
- uint8_t loglevel;
- int use_color:1;
- int print_timestamp:1;
-
- union {
- struct {
- FILE *out;
- } tgt_stdout;
-
- struct {
- int priority;
- } tgt_syslog;
-
- struct {
- void *vty;
- } tgt_vty;
- };
-
- void (*output) (struct log_target *target, const char *string);
-};
-
-/* use the above macros */
-void logp2(unsigned int subsys, unsigned int level, char *file,
- int line, int cont, const char *format, ...)
- __attribute__ ((format (printf, 6, 7)));
-void log_init(const struct log_info *cat);
-
-/* context management */
-void log_reset_context(void);
-int log_set_context(uint8_t ctx, void *value);
-
-/* filter on the targets */
-void log_set_all_filter(struct log_target *target, int);
-
-void log_set_use_color(struct log_target *target, int);
-void log_set_print_timestamp(struct log_target *target, int);
-void log_set_log_level(struct log_target *target, int log_level);
-void log_parse_category_mask(struct log_target *target, const char* mask);
-int log_parse_level(const char *lvl);
-const char *log_level_str(unsigned int lvl);
-int log_parse_category(const char *category);
-void log_set_category_filter(struct log_target *target, int category,
- int enable, int level);
-
-/* management of the targets */
-struct log_target *log_target_create(void);
-struct log_target *log_target_create_stderr(void);
-void log_add_target(struct log_target *target);
-void log_del_target(struct log_target *target);
-
-/* Gernerate command argument strings for VTY use */
-const char *log_vty_category_string(struct log_info *info);
-const char *log_vty_level_string(struct log_info *info);
-
-#endif /* _OSMOCORE_LOGGING_H */
diff --git a/libosmocore/include/osmocore/mncc.h b/libosmocore/include/osmocore/mncc.h
deleted file mode 100644
index a094bb9..0000000
--- a/libosmocore/include/osmocore/mncc.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef _OSMOCORE_MNCC_H
-#define _OSMOCORE_MNCC_H
-
-#define GSM_MAX_FACILITY 128
-#define GSM_MAX_SSVERSION 128
-#define GSM_MAX_USERUSER 128
-
-/* Expanded fields from GSM TS 04.08, Table 10.5.102 */
-struct gsm_mncc_bearer_cap {
- int transfer; /* Information Transfer Capability */
- int mode; /* Transfer Mode */
- int coding; /* Coding Standard */
- int radio; /* Radio Channel Requirement */
- int speech_ctm; /* CTM text telephony indication */
- int speech_ver[8]; /* Speech version indication */
-};
-
-struct gsm_mncc_number {
- int type;
- int plan;
- int present;
- int screen;
- char number[33];
-};
-
-struct gsm_mncc_cause {
- int location;
- int coding;
- int rec;
- int rec_val;
- int value;
- int diag_len;
- char diag[32];
-};
-
-struct gsm_mncc_useruser {
- int proto;
- char info[GSM_MAX_USERUSER + 1]; /* + termination char */
-};
-
-struct gsm_mncc_progress {
- int coding;
- int location;
- int descr;
-};
-
-struct gsm_mncc_facility {
- int len;
- char info[GSM_MAX_FACILITY];
-};
-
-struct gsm_mncc_ssversion {
- int len;
- char info[GSM_MAX_SSVERSION];
-};
-
-struct gsm_mncc_cccap {
- int dtmf;
- int pcp;
-};
-
-enum {
- GSM_MNCC_BCAP_SPEECH = 0,
- GSM_MNCC_BCAP_UNR_DIG = 1,
- GSM_MNCC_BCAP_AUDIO = 2,
- GSM_MNCC_BCAP_FAX_G3 = 3,
- GSM_MNCC_BCAP_OTHER_ITC = 5,
- GSM_MNCC_BCAP_RESERVED = 7,
-};
-
-#endif
diff --git a/libosmocore/include/osmocore/msgb.h b/libosmocore/include/osmocore/msgb.h
deleted file mode 100644
index 2841dc5..0000000
--- a/libosmocore/include/osmocore/msgb.h
+++ /dev/null
@@ -1,165 +0,0 @@
-#ifndef _MSGB_H
-#define _MSGB_H
-
-/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include "linuxlist.h"
-
-struct msgb {
- struct llist_head list;
-
- /* Part of which TRX logical channel we were received / transmitted */
- /* FIXME: move them into the control buffer */
- struct gsm_bts_trx *trx;
- struct gsm_lchan *lchan;
-
- /* the Layer1 header (if any) */
- unsigned char *l1h;
- /* the A-bis layer 2 header: OML, RSL(RLL), NS */
- unsigned char *l2h;
- /* the layer 3 header. For OML: FOM; RSL: 04.08; GPRS: BSSGP */
- unsigned char *l3h;
- /* the layer 4 header */
- unsigned char *l4h;
-
- /* the 'control buffer', large enough to contain 5 pointers */
- unsigned long cb[5];
-
- uint16_t data_len;
- uint16_t len;
-
- unsigned char *head;
- unsigned char *tail;
- unsigned char *data;
- unsigned char _data[0];
-};
-
-extern struct msgb *msgb_alloc(uint16_t size, const char *name);
-extern void msgb_free(struct msgb *m);
-extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg);
-extern struct msgb *msgb_dequeue(struct llist_head *queue);
-extern void msgb_reset(struct msgb *m);
-
-#define msgb_l1(m) ((void *)(m->l1h))
-#define msgb_l2(m) ((void *)(m->l2h))
-#define msgb_l3(m) ((void *)(m->l3h))
-#define msgb_sms(m) ((void *)(m->l4h))
-
-static inline unsigned int msgb_l1len(const struct msgb *msgb)
-{
- return msgb->tail - (uint8_t *)msgb_l1(msgb);
-}
-
-static inline unsigned int msgb_l2len(const struct msgb *msgb)
-{
- return msgb->tail - (uint8_t *)msgb_l2(msgb);
-}
-
-static inline unsigned int msgb_l3len(const struct msgb *msgb)
-{
- return msgb->tail - (uint8_t *)msgb_l3(msgb);
-}
-
-static inline unsigned int msgb_headlen(const struct msgb *msgb)
-{
- return msgb->len - msgb->data_len;
-}
-static inline unsigned char *msgb_put(struct msgb *msgb, unsigned int len)
-{
- unsigned char *tmp = msgb->tail;
- msgb->tail += len;
- msgb->len += len;
- return tmp;
-}
-static inline void msgb_put_u8(struct msgb *msgb, uint8_t word)
-{
- uint8_t *space = msgb_put(msgb, 1);
- space[0] = word & 0xFF;
-}
-static inline void msgb_put_u16(struct msgb *msgb, uint16_t word)
-{
- uint8_t *space = msgb_put(msgb, 2);
- space[0] = word >> 8 & 0xFF;
- space[1] = word & 0xFF;
-}
-static inline void msgb_put_u32(struct msgb *msgb, uint32_t word)
-{
- uint8_t *space = msgb_put(msgb, 4);
- space[0] = word >> 24 & 0xFF;
- space[1] = word >> 16 & 0xFF;
- space[2] = word >> 8 & 0xFF;
- space[3] = word & 0xFF;
-}
-static inline unsigned char *msgb_get(struct msgb *msgb, unsigned int len)
-{
- unsigned char *tmp = msgb->data;
- msgb->data += len;
- msgb->len -= len;
- return tmp;
-}
-static inline uint8_t msgb_get_u8(struct msgb *msgb)
-{
- uint8_t *space = msgb_get(msgb, 1);
- return space[0];
-}
-static inline uint16_t msgb_get_u16(struct msgb *msgb)
-{
- uint8_t *space = msgb_get(msgb, 2);
- return space[0] << 8 | space[1];
-}
-static inline uint32_t msgb_get_u32(struct msgb *msgb)
-{
- uint8_t *space = msgb_get(msgb, 4);
- return space[0] << 24 | space[1] << 16 | space[2] << 8 | space[3];
-}
-static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len)
-{
- msgb->data -= len;
- msgb->len += len;
- return msgb->data;
-}
-static inline unsigned char *msgb_pull(struct msgb *msgb, unsigned int len)
-{
- msgb->len -= len;
- return msgb->data += len;
-}
-static inline int msgb_tailroom(const struct msgb *msgb)
-{
- return (msgb->head + msgb->data_len) - msgb->tail;
-}
-
-/* increase the headroom of an empty msgb, reducing the tailroom */
-static inline void msgb_reserve(struct msgb *msg, int len)
-{
- msg->data += len;
- msg->tail += len;
-}
-
-static inline struct msgb *msgb_alloc_headroom(int size, int headroom,
- const char *name)
-{
- struct msgb *msg = msgb_alloc(size, name);
- if (msg)
- msgb_reserve(msg, headroom);
- return msg;
-}
-
-#endif /* _MSGB_H */
diff --git a/libosmocore/include/osmocore/protocol/Makefile.am b/libosmocore/include/osmocore/protocol/Makefile.am
deleted file mode 100644
index 557950e..0000000
--- a/libosmocore/include/osmocore/protocol/Makefile.am
+++ /dev/null
@@ -1,3 +0,0 @@
-osmocore_proto_HEADERS = gsm_04_08.h gsm_04_11.h gsm_04_80.h gsm_08_58.h gsm_12_21.h gsm_08_08.h
-
-osmocore_protodir = $(includedir)/osmocore/protocol
diff --git a/libosmocore/include/osmocore/protocol/gsm_04_08.h b/libosmocore/include/osmocore/protocol/gsm_04_08.h
deleted file mode 100644
index 1a112a0..0000000
--- a/libosmocore/include/osmocore/protocol/gsm_04_08.h
+++ /dev/null
@@ -1,751 +0,0 @@
-#ifndef PROTO_GSM_04_08_H
-#define PROTO_GSM_04_08_H
-
-#include <stdint.h>
-
-/* GSM TS 04.08 definitions */
-struct gsm_lchan;
-
-struct gsm48_classmark1 {
- uint8_t spare:1,
- rev_level:2,
- es_ind:1,
- a5_1:1,
- pwr_lev:3;
-} __attribute__ ((packed));
-
-/* Chapter 10.5.2.5 */
-struct gsm48_chan_desc {
- uint8_t chan_nr;
- union {
- struct {
- uint8_t maio_high:4,
- h:1,
- tsc:3;
- uint8_t hsn:6,
- maio_low:2;
- } h1;
- struct {
- uint8_t arfcn_high:2,
- spare:2,
- h:1,
- tsc:3;
- uint8_t arfcn_low;
- } h0;
- };
-} __attribute__ ((packed));
-
-/* Chapter 10.5.2.21aa */
-struct gsm48_multi_rate_conf {
- uint8_t smod : 2,
- spare: 1,
- icmi : 1,
- nscb : 1,
- ver : 3;
- uint8_t m4_75 : 1,
- m5_15 : 1,
- m5_90 : 1,
- m6_70 : 1,
- m7_40 : 1,
- m7_95 : 1,
- m10_2 : 1,
- m12_2 : 1;
-} __attribute__((packed));
-
-/* Chapter 10.5.2.30 */
-struct gsm48_req_ref {
- uint8_t ra;
- uint8_t t3_high:3,
- t1_:5;
- uint8_t t2:5,
- t3_low:3;
-} __attribute__ ((packed));
-
-/*
- * Chapter 9.1.5/9.1.6
- *
- * For 9.1.6 the chan_desc has the meaning of 10.5.2.5a
- */
-struct gsm48_chan_mode_modify {
- struct gsm48_chan_desc chan_desc;
- uint8_t mode;
-} __attribute__ ((packed));
-
-enum gsm48_chan_mode {
- GSM48_CMODE_SIGN = 0x00,
- GSM48_CMODE_SPEECH_V1 = 0x01,
- GSM48_CMODE_SPEECH_EFR = 0x21,
- GSM48_CMODE_SPEECH_AMR = 0x41,
- GSM48_CMODE_DATA_14k5 = 0x0f,
- GSM48_CMODE_DATA_12k0 = 0x03,
- GSM48_CMODE_DATA_6k0 = 0x0b,
- GSM48_CMODE_DATA_3k6 = 0x23,
-};
-
-/* Chapter 9.1.2 */
-struct gsm48_ass_cmd {
- /* Semantic is from 10.5.2.5a */
- struct gsm48_chan_desc chan_desc;
- uint8_t power_command;
- uint8_t data[0];
-} __attribute__((packed));
-
-/* Chapter 10.5.2.2 */
-struct gsm48_cell_desc {
- uint8_t bcc:3,
- ncc:3,
- arfcn_hi:2;
- uint8_t arfcn_lo;
-} __attribute__((packed));
-
-/* Chapter 9.1.15 */
-struct gsm48_ho_cmd {
- struct gsm48_cell_desc cell_desc;
- struct gsm48_chan_desc chan_desc;
- uint8_t ho_ref;
- uint8_t power_command;
- uint8_t data[0];
-} __attribute__((packed));
-
-/* Chapter 9.1.18 */
-struct gsm48_imm_ass {
- uint8_t l2_plen;
- uint8_t proto_discr;
- uint8_t msg_type;
- uint8_t page_mode;
- struct gsm48_chan_desc chan_desc;
- struct gsm48_req_ref req_ref;
- uint8_t timing_advance;
- uint8_t mob_alloc_len;
- uint8_t mob_alloc[0];
-} __attribute__ ((packed));
-
-/* Chapter 10.5.1.3 */
-struct gsm48_loc_area_id {
- uint8_t digits[3]; /* BCD! */
- uint16_t lac;
-} __attribute__ ((packed));
-
-/* Section 9.2.2 */
-struct gsm48_auth_req {
- uint8_t key_seq:4,
- spare:4;
- uint8_t rand[16];
-} __attribute__ ((packed));
-
-/* Section 9.2.15 */
-struct gsm48_loc_upd_req {
- uint8_t type:4,
- key_seq:4;
- struct gsm48_loc_area_id lai;
- struct gsm48_classmark1 classmark1;
- uint8_t mi_len;
- uint8_t mi[0];
-} __attribute__ ((packed));
-
-/* Section 10.1 */
-struct gsm48_hdr {
- uint8_t proto_discr;
- uint8_t msg_type;
- uint8_t data[0];
-} __attribute__ ((packed));
-
-/* Section 9.1.3x System information Type header */
-struct gsm48_system_information_type_header {
- uint8_t l2_plen;
- uint8_t rr_protocol_discriminator :4,
- skip_indicator:4;
- uint8_t system_information;
-} __attribute__ ((packed));
-
-struct gsm48_rach_control {
- uint8_t re :1,
- cell_bar :1,
- tx_integer :4,
- max_trans :2;
- uint8_t t2;
- uint8_t t3;
-} __attribute__ ((packed));
-
-/* Section 10.5.2.4 Cell Selection Parameters */
-struct gsm48_cell_sel_par {
- uint8_t ms_txpwr_max_ccch:5, /* GSM 05.08 MS-TXPWR-MAX-CCCH */
- cell_resel_hyst:3; /* GSM 05.08 CELL-RESELECT-HYSTERESIS */
- uint8_t rxlev_acc_min:6, /* GSM 05.08 RXLEV-ACCESS-MIN */
- neci:1,
- acs:1;
-} __attribute__ ((packed));
-
-/* Section 10.5.2.11 Control Channel Description , Figure 10.5.33 */
-struct gsm48_control_channel_descr {
- uint8_t ccch_conf :3,
- bs_ag_blks_res :3,
- att :1,
- spare1 :1;
- uint8_t bs_pa_mfrms : 3,
- spare2 :5;
- uint8_t t3212;
-} __attribute__ ((packed));
-
-struct gsm48_cell_options {
- uint8_t radio_link_timeout:4,
- dtx:2,
- pwrc:1,
- spare:1;
-} __attribute__ ((packed));
-
-/* Section 9.2.9 CM service request */
-struct gsm48_service_request {
- uint8_t cm_service_type : 4,
- cipher_key_seq : 4;
- /* length + 3 bytes */
- uint32_t classmark;
- uint8_t mi_len;
- uint8_t mi[0];
- /* optional priority level */
-} __attribute__ ((packed));
-
-/* Section 9.1.31 System information Type 1 */
-struct gsm48_system_information_type_1 {
- struct gsm48_system_information_type_header header;
- uint8_t cell_channel_description[16];
- struct gsm48_rach_control rach_control;
- uint8_t rest_octets[0]; /* NCH position on the CCCH */
-} __attribute__ ((packed));
-
-/* Section 9.1.32 System information Type 2 */
-struct gsm48_system_information_type_2 {
- struct gsm48_system_information_type_header header;
- uint8_t bcch_frequency_list[16];
- uint8_t ncc_permitted;
- struct gsm48_rach_control rach_control;
-} __attribute__ ((packed));
-
-/* Section 9.1.35 System information Type 3 */
-struct gsm48_system_information_type_3 {
- struct gsm48_system_information_type_header header;
- uint16_t cell_identity;
- struct gsm48_loc_area_id lai;
- struct gsm48_control_channel_descr control_channel_desc;
- struct gsm48_cell_options cell_options;
- struct gsm48_cell_sel_par cell_sel_par;
- struct gsm48_rach_control rach_control;
- uint8_t rest_octets[0];
-} __attribute__ ((packed));
-
-/* Section 9.1.36 System information Type 4 */
-struct gsm48_system_information_type_4 {
- struct gsm48_system_information_type_header header;
- struct gsm48_loc_area_id lai;
- struct gsm48_cell_sel_par cell_sel_par;
- struct gsm48_rach_control rach_control;
- /* optional CBCH conditional CBCH... followed by
- mandantory SI 4 Reset Octets
- */
- uint8_t data[0];
-} __attribute__ ((packed));
-
-/* Section 9.1.37 System information Type 5 */
-struct gsm48_system_information_type_5 {
- uint8_t rr_protocol_discriminator :4,
- skip_indicator:4;
- uint8_t system_information;
- uint8_t bcch_frequency_list[16];
-} __attribute__ ((packed));
-
-/* Section 9.1.40 System information Type 6 */
-struct gsm48_system_information_type_6 {
- uint8_t rr_protocol_discriminator :4,
- skip_indicator:4;
- uint8_t system_information;
- uint16_t cell_identity;
- struct gsm48_loc_area_id lai;
- struct gsm48_cell_options cell_options;
- uint8_t ncc_permitted;
- uint8_t rest_octets[0];
-} __attribute__ ((packed));
-
-/* Section 9.1.43a System Information type 13 */
-struct gsm48_system_information_type_13 {
- struct gsm48_system_information_type_header header;
- uint8_t rest_octets[0];
-} __attribute__ ((packed));
-
-/* Section 9.2.12 IMSI Detach Indication */
-struct gsm48_imsi_detach_ind {
- struct gsm48_classmark1 classmark1;
- uint8_t mi_len;
- uint8_t mi[0];
-} __attribute__ ((packed));
-
-/* Section 10.2 + GSM 04.07 12.2.3.1.1 */
-#define GSM48_PDISC_GROUP_CC 0x00
-#define GSM48_PDISC_BCAST_CC 0x01
-#define GSM48_PDISC_PDSS1 0x02
-#define GSM48_PDISC_CC 0x03
-#define GSM48_PDISC_PDSS2 0x04
-#define GSM48_PDISC_MM 0x05
-#define GSM48_PDISC_RR 0x06
-#define GSM48_PDISC_MM_GPRS 0x08
-#define GSM48_PDISC_SMS 0x09
-#define GSM48_PDISC_SM_GPRS 0x0a
-#define GSM48_PDISC_NC_SS 0x0b
-#define GSM48_PDISC_LOC 0x0c
-#define GSM48_PDISC_MASK 0x0f
-#define GSM48_PDISC_USSD 0x11
-
-/* Section 10.4 */
-#define GSM48_MT_RR_INIT_REQ 0x3c
-#define GSM48_MT_RR_ADD_ASS 0x3b
-#define GSM48_MT_RR_IMM_ASS 0x3f
-#define GSM48_MT_RR_IMM_ASS_EXT 0x39
-#define GSM48_MT_RR_IMM_ASS_REJ 0x3a
-
-#define GSM48_MT_RR_CIPH_M_CMD 0x35
-#define GSM48_MT_RR_CIPH_M_COMPL 0x32
-
-#define GSM48_MT_RR_CFG_CHG_CMD 0x30
-#define GSM48_MT_RR_CFG_CHG_ACK 0x31
-#define GSM48_MT_RR_CFG_CHG_REJ 0x33
-
-#define GSM48_MT_RR_ASS_CMD 0x2e
-#define GSM48_MT_RR_ASS_COMPL 0x29
-#define GSM48_MT_RR_ASS_FAIL 0x2f
-#define GSM48_MT_RR_HANDO_CMD 0x2b
-#define GSM48_MT_RR_HANDO_COMPL 0x2c
-#define GSM48_MT_RR_HANDO_FAIL 0x28
-#define GSM48_MT_RR_HANDO_INFO 0x2d
-
-#define GSM48_MT_RR_CELL_CHG_ORDER 0x08
-#define GSM48_MT_RR_PDCH_ASS_CMD 0x23
-
-#define GSM48_MT_RR_CHAN_REL 0x0d
-#define GSM48_MT_RR_PART_REL 0x0a
-#define GSM48_MT_RR_PART_REL_COMP 0x0f
-
-#define GSM48_MT_RR_PAG_REQ_1 0x21
-#define GSM48_MT_RR_PAG_REQ_2 0x22
-#define GSM48_MT_RR_PAG_REQ_3 0x24
-#define GSM48_MT_RR_PAG_RESP 0x27
-#define GSM48_MT_RR_NOTIF_NCH 0x20
-#define GSM48_MT_RR_NOTIF_FACCH 0x25
-#define GSM48_MT_RR_NOTIF_RESP 0x26
-
-#define GSM48_MT_RR_SYSINFO_8 0x18
-#define GSM48_MT_RR_SYSINFO_1 0x19
-#define GSM48_MT_RR_SYSINFO_2 0x1a
-#define GSM48_MT_RR_SYSINFO_3 0x1b
-#define GSM48_MT_RR_SYSINFO_4 0x1c
-#define GSM48_MT_RR_SYSINFO_5 0x1d
-#define GSM48_MT_RR_SYSINFO_6 0x1e
-#define GSM48_MT_RR_SYSINFO_7 0x1f
-
-#define GSM48_MT_RR_SYSINFO_2bis 0x02
-#define GSM48_MT_RR_SYSINFO_2ter 0x03
-#define GSM48_MT_RR_SYSINFO_5bis 0x05
-#define GSM48_MT_RR_SYSINFO_5ter 0x06
-#define GSM48_MT_RR_SYSINFO_9 0x04
-#define GSM48_MT_RR_SYSINFO_13 0x00
-
-#define GSM48_MT_RR_SYSINFO_16 0x3d
-#define GSM48_MT_RR_SYSINFO_17 0x3e
-
-#define GSM48_MT_RR_CHAN_MODE_MODIF 0x10
-#define GSM48_MT_RR_STATUS 0x12
-#define GSM48_MT_RR_CHAN_MODE_MODIF_ACK 0x17
-#define GSM48_MT_RR_FREQ_REDEF 0x14
-#define GSM48_MT_RR_MEAS_REP 0x15
-#define GSM48_MT_RR_CLSM_CHG 0x16
-#define GSM48_MT_RR_CLSM_ENQ 0x13
-#define GSM48_MT_RR_EXT_MEAS_REP 0x36
-#define GSM48_MT_RR_EXT_MEAS_REP_ORD 0x37
-#define GSM48_MT_RR_GPRS_SUSP_REQ 0x34
-
-#define GSM48_MT_RR_VGCS_UPL_GRANT 0x08
-#define GSM48_MT_RR_UPLINK_RELEASE 0x0e
-#define GSM48_MT_RR_UPLINK_FREE 0x0c
-#define GSM48_MT_RR_UPLINK_BUSY 0x2a
-#define GSM48_MT_RR_TALKER_IND 0x11
-
-#define GSM48_MT_RR_APP_INFO 0x38
-
-/* Table 10.2/3GPP TS 04.08 */
-#define GSM48_MT_MM_IMSI_DETACH_IND 0x01
-#define GSM48_MT_MM_LOC_UPD_ACCEPT 0x02
-#define GSM48_MT_MM_LOC_UPD_REJECT 0x04
-#define GSM48_MT_MM_LOC_UPD_REQUEST 0x08
-
-#define GSM48_MT_MM_AUTH_REJ 0x11
-#define GSM48_MT_MM_AUTH_REQ 0x12
-#define GSM48_MT_MM_AUTH_RESP 0x14
-#define GSM48_MT_MM_ID_REQ 0x18
-#define GSM48_MT_MM_ID_RESP 0x19
-#define GSM48_MT_MM_TMSI_REALL_CMD 0x1a
-#define GSM48_MT_MM_TMSI_REALL_COMPL 0x1b
-
-#define GSM48_MT_MM_CM_SERV_ACC 0x21
-#define GSM48_MT_MM_CM_SERV_REJ 0x22
-#define GSM48_MT_MM_CM_SERV_ABORT 0x23
-#define GSM48_MT_MM_CM_SERV_REQ 0x24
-#define GSM48_MT_MM_CM_SERV_PROMPT 0x25
-#define GSM48_MT_MM_CM_REEST_REQ 0x28
-#define GSM48_MT_MM_ABORT 0x29
-
-#define GSM48_MT_MM_NULL 0x30
-#define GSM48_MT_MM_STATUS 0x31
-#define GSM48_MT_MM_INFO 0x32
-
-/* Table 10.3/3GPP TS 04.08 */
-#define GSM48_MT_CC_ALERTING 0x01
-#define GSM48_MT_CC_CALL_CONF 0x08
-#define GSM48_MT_CC_CALL_PROC 0x02
-#define GSM48_MT_CC_CONNECT 0x07
-#define GSM48_MT_CC_CONNECT_ACK 0x0f
-#define GSM48_MT_CC_EMERG_SETUP 0x0e
-#define GSM48_MT_CC_PROGRESS 0x03
-#define GSM48_MT_CC_ESTAB 0x04
-#define GSM48_MT_CC_ESTAB_CONF 0x06
-#define GSM48_MT_CC_RECALL 0x0b
-#define GSM48_MT_CC_START_CC 0x09
-#define GSM48_MT_CC_SETUP 0x05
-
-#define GSM48_MT_CC_MODIFY 0x17
-#define GSM48_MT_CC_MODIFY_COMPL 0x1f
-#define GSM48_MT_CC_MODIFY_REJECT 0x13
-#define GSM48_MT_CC_USER_INFO 0x10
-#define GSM48_MT_CC_HOLD 0x18
-#define GSM48_MT_CC_HOLD_ACK 0x19
-#define GSM48_MT_CC_HOLD_REJ 0x1a
-#define GSM48_MT_CC_RETR 0x1c
-#define GSM48_MT_CC_RETR_ACK 0x1d
-#define GSM48_MT_CC_RETR_REJ 0x1e
-
-#define GSM48_MT_CC_DISCONNECT 0x25
-#define GSM48_MT_CC_RELEASE 0x2d
-#define GSM48_MT_CC_RELEASE_COMPL 0x2a
-
-#define GSM48_MT_CC_CONG_CTRL 0x39
-#define GSM48_MT_CC_NOTIFY 0x3e
-#define GSM48_MT_CC_STATUS 0x3d
-#define GSM48_MT_CC_STATUS_ENQ 0x34
-#define GSM48_MT_CC_START_DTMF 0x35
-#define GSM48_MT_CC_STOP_DTMF 0x31
-#define GSM48_MT_CC_STOP_DTMF_ACK 0x32
-#define GSM48_MT_CC_START_DTMF_ACK 0x36
-#define GSM48_MT_CC_START_DTMF_REJ 0x37
-#define GSM48_MT_CC_FACILITY 0x3a
-
-/* FIXME: Table 10.4 / 10.4a (GPRS) */
-
-/* Section 10.5.2.26, Table 10.5.64 */
-#define GSM48_PM_MASK 0x03
-#define GSM48_PM_NORMAL 0x00
-#define GSM48_PM_EXTENDED 0x01
-#define GSM48_PM_REORG 0x02
-#define GSM48_PM_SAME 0x03
-
-/* Chapter 10.5.3.5 / Table 10.5.93 */
-#define GSM48_LUPD_NORMAL 0x0
-#define GSM48_LUPD_PERIODIC 0x1
-#define GSM48_LUPD_IMSI_ATT 0x2
-#define GSM48_LUPD_RESERVED 0x3
-
-/* Table 10.5.4 */
-#define GSM_MI_TYPE_MASK 0x07
-#define GSM_MI_TYPE_NONE 0x00
-#define GSM_MI_TYPE_IMSI 0x01
-#define GSM_MI_TYPE_IMEI 0x02
-#define GSM_MI_TYPE_IMEISV 0x03
-#define GSM_MI_TYPE_TMSI 0x04
-#define GSM_MI_ODD 0x08
-
-#define GSM48_IE_MUL_RATE_CFG 0x03 /* 10.5.2.21aa */
-#define GSM48_IE_MOBILE_ID 0x17
-#define GSM48_IE_NAME_LONG 0x43 /* 10.5.3.5a */
-#define GSM48_IE_NAME_SHORT 0x45 /* 10.5.3.5a */
-#define GSM48_IE_UTC 0x46 /* 10.5.3.8 */
-#define GSM48_IE_NET_TIME_TZ 0x47 /* 10.5.3.9 */
-#define GSM48_IE_LSA_IDENT 0x48 /* 10.5.3.11 */
-
-#define GSM48_IE_BEARER_CAP 0x04 /* 10.5.4.5 */
-#define GSM48_IE_CAUSE 0x08 /* 10.5.4.11 */
-#define GSM48_IE_CC_CAP 0x15 /* 10.5.4.5a */
-#define GSM48_IE_ALERT 0x19 /* 10.5.4.26 */
-#define GSM48_IE_FACILITY 0x1c /* 10.5.4.15 */
-#define GSM48_IE_PROGR_IND 0x1e /* 10.5.4.21 */
-#define GSM48_IE_AUX_STATUS 0x24 /* 10.5.4.4 */
-#define GSM48_IE_NOTIFY 0x27 /* 10.5.4.20 */
-#define GSM48_IE_KPD_FACILITY 0x2c /* 10.5.4.17 */
-#define GSM48_IE_SIGNAL 0x34 /* 10.5.4.23 */
-#define GSM48_IE_CONN_BCD 0x4c /* 10.5.4.13 */
-#define GSM48_IE_CONN_SUB 0x4d /* 10.5.4.14 */
-#define GSM48_IE_CALLING_BCD 0x5c /* 10.5.4.9 */
-#define GSM48_IE_CALLING_SUB 0x5d /* 10.5.4.10 */
-#define GSM48_IE_CALLED_BCD 0x5e /* 10.5.4.7 */
-#define GSM48_IE_CALLED_SUB 0x6d /* 10.5.4.8 */
-#define GSM48_IE_REDIR_BCD 0x74 /* 10.5.4.21a */
-#define GSM48_IE_REDIR_SUB 0x75 /* 10.5.4.21b */
-#define GSM48_IE_LOWL_COMPAT 0x7c /* 10.5.4.18 */
-#define GSM48_IE_HIGHL_COMPAT 0x7d /* 10.5.4.16 */
-#define GSM48_IE_USER_USER 0x7e /* 10.5.4.25 */
-#define GSM48_IE_SS_VERS 0x7f /* 10.5.4.24 */
-#define GSM48_IE_MORE_DATA 0xa0 /* 10.5.4.19 */
-#define GSM48_IE_CLIR_SUPP 0xa1 /* 10.5.4.11a */
-#define GSM48_IE_CLIR_INVOC 0xa2 /* 10.5.4.11b */
-#define GSM48_IE_REV_C_SETUP 0xa3 /* 10.5.4.22a */
-#define GSM48_IE_REPEAT_CIR 0xd1 /* 10.5.4.22 */
-#define GSM48_IE_REPEAT_SEQ 0xd3 /* 10.5.4.22 */
-
-/* Section 10.5.4.11 / Table 10.5.122 */
-#define GSM48_CAUSE_CS_GSM 0x60
-
-/* Section 9.1.2 / Table 9.3 */
-#define GSM48_IE_FRQLIST_AFTER 0x05
-#define GSM48_IE_CELL_CH_DESC 0x62
-#define GSM48_IE_MSLOT_DESC 0x10
-#define GSM48_IE_CHANMODE_1 0x63
-#define GSM48_IE_CHANMODE_2 0x11
-#define GSM48_IE_CHANMODE_3 0x13
-#define GSM48_IE_CHANMODE_4 0x14
-#define GSM48_IE_CHANMODE_5 0x15
-#define GSM48_IE_CHANMODE_6 0x16
-#define GSM48_IE_CHANMODE_7 0x17
-#define GSM48_IE_CHANMODE_8 0x18
-#define GSM48_IE_CHANDESC_2 0x64
-/* FIXME */
-
-/* Section 10.5.4.23 / Table 10.5.130 */
-enum gsm48_signal_val {
- GSM48_SIGNAL_DIALTONE = 0x00,
- GSM48_SIGNAL_RINGBACK = 0x01,
- GSM48_SIGNAL_INTERCEPT = 0x02,
- GSM48_SIGNAL_NET_CONG = 0x03,
- GSM48_SIGNAL_BUSY = 0x04,
- GSM48_SIGNAL_CONFIRM = 0x05,
- GSM48_SIGNAL_ANSWER = 0x06,
- GSM48_SIGNAL_CALL_WAIT = 0x07,
- GSM48_SIGNAL_OFF_HOOK = 0x08,
- GSM48_SIGNAL_OFF = 0x3f,
- GSM48_SIGNAL_ALERT_OFF = 0x4f,
-};
-
-enum gsm48_cause_loc {
- GSM48_CAUSE_LOC_USER = 0x00,
- GSM48_CAUSE_LOC_PRN_S_LU = 0x01,
- GSM48_CAUSE_LOC_PUN_S_LU = 0x02,
- GSM48_CAUSE_LOC_TRANS_NET = 0x03,
- GSM48_CAUSE_LOC_PUN_S_RU = 0x04,
- GSM48_CAUSE_LOC_PRN_S_RU = 0x05,
- /* not defined */
- GSM48_CAUSE_LOC_INN_NET = 0x07,
- GSM48_CAUSE_LOC_NET_BEYOND = 0x0a,
-};
-
-/* Section 10.5.2.31 RR Cause / Table 10.5.70 */
-enum gsm48_rr_cause {
- GSM48_RR_CAUSE_NORMAL = 0x00,
- GSM48_RR_CAUSE_ABNORMAL_UNSPEC = 0x01,
- GSM48_RR_CAUSE_ABNORMAL_UNACCT = 0x02,
- GSM48_RR_CAUSE_ABNORMAL_TIMER = 0x03,
- GSM48_RR_CAUSE_ABNORMAL_NOACT = 0x04,
- GSM48_RR_CAUSE_PREMPTIVE_REL = 0x05,
- GSM48_RR_CAUSE_HNDOVER_IMP = 0x06,
- GSM48_RR_CAUSE_CHAN_MODE_UNACCT = 0x07,
- GSM48_RR_CAUSE_FREQ_NOT_IMPL = 0x08,
- GSM48_RR_CAUSE_CALL_CLEARED = 0x41,
- GSM48_RR_CAUSE_SEMANT_INCORR = 0x5f,
- GSM48_RR_CAUSE_INVALID_MAND_INF = 0x60,
- GSM48_RR_CAUSE_MSG_TYPE_N = 0x61,
- GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT= 0x62,
- GSM48_RR_CAUSE_COND_IE_ERROR = 0x64,
- GSM48_RR_CAUSE_NO_CELL_ALLOC_A = 0x65,
- GSM48_RR_CAUSE_PROT_ERROR_UNSPC = 0x6f,
-};
-
-/* Section 10.5.4.11 CC Cause / Table 10.5.123 */
-enum gsm48_cc_cause {
- GSM48_CC_CAUSE_UNASSIGNED_NR = 1,
- GSM48_CC_CAUSE_NO_ROUTE = 3,
- GSM48_CC_CAUSE_CHAN_UNACCEPT = 6,
- GSM48_CC_CAUSE_OP_DET_BARRING = 8,
- GSM48_CC_CAUSE_NORM_CALL_CLEAR = 16,
- GSM48_CC_CAUSE_USER_BUSY = 17,
- GSM48_CC_CAUSE_USER_NOTRESPOND = 18,
- GSM48_CC_CAUSE_USER_ALERTING_NA = 19,
- GSM48_CC_CAUSE_CALL_REJECTED = 21,
- GSM48_CC_CAUSE_NUMBER_CHANGED = 22,
- GSM48_CC_CAUSE_PRE_EMPTION = 25,
- GSM48_CC_CAUSE_NONSE_USER_CLR = 26,
- GSM48_CC_CAUSE_DEST_OOO = 27,
- GSM48_CC_CAUSE_INV_NR_FORMAT = 28,
- GSM48_CC_CAUSE_FACILITY_REJ = 29,
- GSM48_CC_CAUSE_RESP_STATUS_INQ = 30,
- GSM48_CC_CAUSE_NORMAL_UNSPEC = 31,
- GSM48_CC_CAUSE_NO_CIRCUIT_CHAN = 34,
- GSM48_CC_CAUSE_NETWORK_OOO = 38,
- GSM48_CC_CAUSE_TEMP_FAILURE = 41,
- GSM48_CC_CAUSE_SWITCH_CONG = 42,
- GSM48_CC_CAUSE_ACC_INF_DISCARD = 43,
- GSM48_CC_CAUSE_REQ_CHAN_UNAVAIL = 44,
- GSM48_CC_CAUSE_RESOURCE_UNAVAIL = 47,
- GSM48_CC_CAUSE_QOS_UNAVAIL = 49,
- GSM48_CC_CAUSE_REQ_FAC_NOT_SUBSC= 50,
- GSM48_CC_CAUSE_INC_BARRED_CUG = 55,
- GSM48_CC_CAUSE_BEARER_CAP_UNAUTH= 57,
- GSM48_CC_CAUSE_BEARER_CA_UNAVAIL= 58,
- GSM48_CC_CAUSE_SERV_OPT_UNAVAIL = 63,
- GSM48_CC_CAUSE_BEARERSERV_UNIMPL= 65,
- GSM48_CC_CAUSE_ACM_GE_ACM_MAX = 68,
- GSM48_CC_CAUSE_REQ_FAC_NOTIMPL = 69,
- GSM48_CC_CAUSE_RESTR_BCAP_AVAIL = 70,
- GSM48_CC_CAUSE_SERV_OPT_UNIMPL = 79,
- GSM48_CC_CAUSE_INVAL_TRANS_ID = 81,
- GSM48_CC_CAUSE_USER_NOT_IN_CUG = 87,
- GSM48_CC_CAUSE_INCOMPAT_DEST = 88,
- GSM48_CC_CAUSE_INVAL_TRANS_NET = 91,
- GSM48_CC_CAUSE_SEMANTIC_INCORR = 95,
- GSM48_CC_CAUSE_INVAL_MAND_INF = 96,
- GSM48_CC_CAUSE_MSGTYPE_NOTEXIST = 97,
- GSM48_CC_CAUSE_MSGTYPE_INCOMPAT = 98,
- GSM48_CC_CAUSE_IE_NOTEXIST = 99,
- GSM48_CC_CAUSE_COND_IE_ERR = 100,
- GSM48_CC_CAUSE_MSG_INCOMP_STATE = 101,
- GSM48_CC_CAUSE_RECOVERY_TIMER = 102,
- GSM48_CC_CAUSE_PROTO_ERR = 111,
- GSM48_CC_CAUSE_INTERWORKING = 127,
-};
-
-/* Annex G, GSM specific cause values for mobility management */
-enum gsm48_reject_value {
- GSM48_REJECT_IMSI_UNKNOWN_IN_HLR = 2,
- GSM48_REJECT_ILLEGAL_MS = 3,
- GSM48_REJECT_IMSI_UNKNOWN_IN_VLR = 4,
- GSM48_REJECT_IMEI_NOT_ACCEPTED = 5,
- GSM48_REJECT_ILLEGAL_ME = 6,
- GSM48_REJECT_PLMN_NOT_ALLOWED = 11,
- GSM48_REJECT_LOC_NOT_ALLOWED = 12,
- GSM48_REJECT_ROAMING_NOT_ALLOWED = 13,
- GSM48_REJECT_NETWORK_FAILURE = 17,
- GSM48_REJECT_CONGESTION = 22,
- GSM48_REJECT_SRV_OPT_NOT_SUPPORTED = 32,
- GSM48_REJECT_RQD_SRV_OPT_NOT_SUPPORTED = 33,
- GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER = 34,
- GSM48_REJECT_CALL_CAN_NOT_BE_IDENTIFIED = 38,
- GSM48_REJECT_INCORRECT_MESSAGE = 95,
- GSM48_REJECT_INVALID_MANDANTORY_INF = 96,
- GSM48_REJECT_MSG_TYPE_NOT_IMPLEMENTED = 97,
- GSM48_REJECT_MSG_TYPE_NOT_COMPATIBLE = 98,
- GSM48_REJECT_INF_ELEME_NOT_IMPLEMENTED = 99,
- GSM48_REJECT_CONDTIONAL_IE_ERROR = 100,
- GSM48_REJECT_MSG_NOT_COMPATIBLE = 101,
- GSM48_REJECT_PROTOCOL_ERROR = 111,
-
- /* according to G.6 Additional cause codes for GMM */
- GSM48_REJECT_GPRS_NOT_ALLOWED = 7,
- GSM48_REJECT_SERVICES_NOT_ALLOWED = 8,
- GSM48_REJECT_MS_IDENTITY_NOT_DERVIVABLE = 9,
- GSM48_REJECT_IMPLICITLY_DETACHED = 10,
- GSM48_REJECT_GPRS_NOT_ALLOWED_IN_PLMN = 14,
- GSM48_REJECT_MSC_TMP_NOT_REACHABLE = 16,
-};
-
-enum chreq_type {
- CHREQ_T_EMERG_CALL,
- CHREQ_T_CALL_REEST_TCH_F,
- CHREQ_T_CALL_REEST_TCH_H,
- CHREQ_T_CALL_REEST_TCH_H_DBL,
- CHREQ_T_SDCCH,
- CHREQ_T_TCH_F,
- CHREQ_T_VOICE_CALL_TCH_H,
- CHREQ_T_DATA_CALL_TCH_H,
- CHREQ_T_LOCATION_UPD,
- CHREQ_T_PAG_R_ANY_NECI0,
- CHREQ_T_PAG_R_ANY_NECI1,
- CHREQ_T_PAG_R_TCH_F,
- CHREQ_T_PAG_R_TCH_FH,
- CHREQ_T_LMU,
- CHREQ_T_RESERVED_SDCCH,
- CHREQ_T_RESERVED_IGNORE,
-};
-
-/* Chapter 11.3 */
-#define GSM48_T301 180, 0
-#define GSM48_T303 30, 0
-#define GSM48_T305 30, 0
-#define GSM48_T306 30, 0
-#define GSM48_T308 10, 0
-#define GSM48_T310 180, 0
-#define GSM48_T313 30, 0
-#define GSM48_T323 30, 0
-#define GSM48_T331 30, 0
-#define GSM48_T333 30, 0
-#define GSM48_T334 25, 0 /* min 15 */
-#define GSM48_T338 30, 0
-
-/* Chapter 5.1.2.2 */
-#define GSM_CSTATE_NULL 0
-#define GSM_CSTATE_INITIATED 1
-#define GSM_CSTATE_MM_CONNECTION_PEND 2 /* see 10.5.4.6 */
-#define GSM_CSTATE_MO_CALL_PROC 3
-#define GSM_CSTATE_CALL_DELIVERED 4
-#define GSM_CSTATE_CALL_PRESENT 6
-#define GSM_CSTATE_CALL_RECEIVED 7
-#define GSM_CSTATE_CONNECT_REQUEST 8
-#define GSM_CSTATE_MO_TERM_CALL_CONF 9
-#define GSM_CSTATE_ACTIVE 10
-#define GSM_CSTATE_DISCONNECT_REQ 12
-#define GSM_CSTATE_DISCONNECT_IND 12
-#define GSM_CSTATE_RELEASE_REQ 19
-#define GSM_CSTATE_MO_ORIG_MODIFY 26
-#define GSM_CSTATE_MO_TERM_MODIFY 27
-#define GSM_CSTATE_CONNECT_IND 28
-
-#define SBIT(a) (1 << a)
-#define ALL_STATES 0xffffffff
-
-/* Table 10.5.3/3GPP TS 04.08: Location Area Identification information element */
-#define GSM_LAC_RESERVED_DETACHED 0x0
-#define GSM_LAC_RESERVED_ALL_BTS 0xfffe
-
-/* GSM 04.08 Bearer Capability: Information Transfer Capability */
-enum gsm48_bcap_itcap {
- GSM48_BCAP_ITCAP_SPEECH = 0,
- GSM48_BCAP_ITCAP_UNR_DIG_INF = 1,
- GSM48_BCAP_ITCAP_3k1_AUDIO = 2,
- GSM48_BCAP_ITCAP_FAX_G3 = 3,
- GSM48_BCAP_ITCAP_OTHER = 5,
- GSM48_BCAP_ITCAP_RESERVED = 7,
-};
-
-/* GSM 04.08 Bearer Capability: Transfer Mode */
-enum gsm48_bcap_tmod {
- GSM48_BCAP_TMOD_CIRCUIT = 0,
- GSM48_BCAP_TMOD_PACKET = 1,
-};
-
-/* GSM 04.08 Bearer Capability: Coding Standard */
-enum gsm48_bcap_coding {
- GSM48_BCAP_CODING_GSM_STD = 0,
-};
-
-/* GSM 04.08 Bearer Capability: Radio Channel Requirements */
-enum gsm48_bcap_rrq {
- GSM48_BCAP_RRQ_FR_ONLY = 1,
- GSM48_BCAP_RRQ_DUAL_HR = 2,
- GSM48_BCAP_RRQ_DUAL_FR = 3,
-};
-
-#define GSM48_TMSI_LEN 5
-#define GSM48_MID_TMSI_LEN (GSM48_TMSI_LEN + 2)
-#define GSM48_MI_SIZE 32
-
-/* Chapter 10.4.4.15 */
-struct gsm48_ra_id {
- uint8_t digits[3]; /* MCC + MNC BCD digits */
- uint16_t lac; /* Location Area Code */
- uint8_t rac; /* Routing Area Code */
-} __attribute__ ((packed));
-
-
-
-#endif /* PROTO_GSM_04_08_H */
diff --git a/libosmocore/include/osmocore/protocol/gsm_04_11.h b/libosmocore/include/osmocore/protocol/gsm_04_11.h
deleted file mode 100644
index c6a2b19..0000000
--- a/libosmocore/include/osmocore/protocol/gsm_04_11.h
+++ /dev/null
@@ -1,188 +0,0 @@
-#ifndef PROTO_GSM_04_11_H
-#define PROTO_GSM_04_11_H
-
-#include <stdint.h>
-
-/* GSM TS 04.11 definitions */
-
-/* Chapter 5.2.3: SMC-CS states at the network side */
-enum gsm411_cp_state {
- GSM411_CPS_IDLE = 0,
- GSM411_CPS_MM_CONN_PENDING = 1, /* only MT ! */
- GSM411_CPS_WAIT_CP_ACK = 2,
- GSM411_CPS_MM_ESTABLISHED = 3,
-};
-
-/* Chapter 6.2.2: SMR states at the network side */
-enum gsm411_rp_state {
- GSM411_RPS_IDLE = 0,
- GSM411_RPS_WAIT_FOR_RP_ACK = 1,
- GSM411_RPS_WAIT_TO_TX_RP_ACK = 3,
-};
-
-/* Chapter 8.1.2 (refers to GSM 04.07 Chapter 11.2.3.1.1 */
-#define GSM411_PDISC_SMS 0x09
-
-/* Chapter 8.1.3 */
-#define GSM411_MT_CP_DATA 0x01
-#define GSM411_MT_CP_ACK 0x04
-#define GSM411_MT_CP_ERROR 0x10
-
-enum gsm411_cp_ie {
- GSM411_CP_IE_USER_DATA = 0x01, /* 8.1.4.1 */
- GSM411_CP_IE_CAUSE = 0x02, /* 8.1.4.2. */
-};
-
-/* Section 8.1.4.2 / Table 8.2 */
-enum gsm411_cp_cause {
- GSM411_CP_CAUSE_NET_FAIL = 17,
- GSM411_CP_CAUSE_CONGESTION = 22,
- GSM411_CP_CAUSE_INV_TRANS_ID = 81,
- GSM411_CP_CAUSE_SEMANT_INC_MSG = 95,
- GSM411_CP_CAUSE_INV_MAND_INF = 96,
- GSM411_CP_CAUSE_MSGTYPE_NOTEXIST= 97,
- GSM411_CP_CAUSE_MSG_INCOMP_STATE= 98,
- GSM411_CP_CAUSE_IE_NOTEXIST = 99,
- GSM411_CP_CAUSE_PROTOCOL_ERR = 111,
-};
-
-/* Chapter 8.2.2 */
-#define GSM411_MT_RP_DATA_MO 0x00
-#define GSM411_MT_RP_DATA_MT 0x01
-#define GSM411_MT_RP_ACK_MO 0x02
-#define GSM411_MT_RP_ACK_MT 0x03
-#define GSM411_MT_RP_ERROR_MO 0x04
-#define GSM411_MT_RP_ERROR_MT 0x05
-#define GSM411_MT_RP_SMMA_MO 0x06
-
-enum gsm411_rp_ie {
- GSM411_IE_RP_USER_DATA = 0x41, /* 8.2.5.3 */
- GSM411_IE_RP_CAUSE = 0x42, /* 8.2.5.4 */
-};
-
-/* Chapter 8.2.5.4 Table 8.4 */
-enum gsm411_rp_cause {
- /* valid only for MO */
- GSM411_RP_CAUSE_MO_NUM_UNASSIGNED = 1,
- GSM411_RP_CAUSE_MO_OP_DET_BARR = 8,
- GSM411_RP_CAUSE_MO_CALL_BARRED = 10,
- GSM411_RP_CAUSE_MO_SMS_REJECTED = 21,
- GSM411_RP_CAUSE_MO_DEST_OUT_OF_ORDER = 27,
- GSM411_RP_CAUSE_MO_UNIDENTIFIED_SUBSCR = 28,
- GSM411_RP_CAUSE_MO_FACILITY_REJ = 29,
- GSM411_RP_CAUSE_MO_UNKNOWN_SUBSCR = 30,
- GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER = 38,
- GSM411_RP_CAUSE_MO_TEMP_FAIL = 41,
- GSM411_RP_CAUSE_MO_CONGESTION = 42,
- GSM411_RP_CAUSE_MO_RES_UNAVAIL = 47,
- GSM411_RP_CAUSE_MO_REQ_FAC_NOTSUBSCR = 50,
- GSM411_RP_CAUSE_MO_REQ_FAC_NOTIMPL = 69,
- GSM411_RP_CAUSE_MO_INTERWORKING = 127,
- /* valid only for MT */
- GSM411_RP_CAUSE_MT_MEM_EXCEEDED = 22,
- /* valid for both directions */
- GSM411_RP_CAUSE_INV_TRANS_REF = 81,
- GSM411_RP_CAUSE_SEMANT_INC_MSG = 95,
- GSM411_RP_CAUSE_INV_MAND_INF = 96,
- GSM411_RP_CAUSE_MSGTYPE_NOTEXIST = 97,
- GSM411_RP_CAUSE_MSG_INCOMP_STATE = 98,
- GSM411_RP_CAUSE_IE_NOTEXIST = 99,
- GSM411_RP_CAUSE_PROTOCOL_ERR = 111,
-};
-
-/* Chapter 10: Timers */
-#define GSM411_TMR_TR1M 40, 0 /* 35 < x < 45 seconds */
-#define GSM411_TMR_TRAM 30, 0 /* 25 < x < 35 seconds */
-#define GSM411_TMR_TR2M 15, 0 /* 12 < x < 20 seconds */
-
-#define GSM411_TMR_TC1A 30, 0
-
-/* Chapter 8.2.1 */
-struct gsm411_rp_hdr {
- uint8_t len;
- uint8_t msg_type;
- uint8_t msg_ref;
- uint8_t data[0];
-} __attribute__ ((packed));
-
-/* our own enum, not related to on-air protocol */
-enum sms_alphabet {
- DCS_NONE,
- DCS_7BIT_DEFAULT,
- DCS_UCS2,
- DCS_8BIT_DATA,
-};
-
-/* GSM 03.40 / Chapter 9.2.3.1: TP-Message-Type-Indicator */
-#define GSM340_SMS_DELIVER_SC2MS 0x00
-#define GSM340_SMS_DELIVER_REP_MS2SC 0x00
-#define GSM340_SMS_STATUS_REP_SC2MS 0x02
-#define GSM340_SMS_COMMAND_MS2SC 0x02
-#define GSM340_SMS_SUBMIT_MS2SC 0x01
-#define GSM340_SMS_SUBMIT_REP_SC2MS 0x01
-#define GSM340_SMS_RESSERVED 0x03
-
-/* GSM 03.40 / Chapter 9.2.3.2: TP-More-Messages-to-Send */
-#define GSM340_TP_MMS_MORE 0
-#define GSM340_TP_MMS_NO_MORE 1
-
-/* GSM 03.40 / Chapter 9.2.3.3: TP-Validity-Period-Format */
-#define GSM340_TP_VPF_NONE 0
-#define GSM340_TP_VPF_RELATIVE 2
-#define GSM340_TP_VPF_ENHANCED 1
-#define GSM340_TP_VPF_ABSOLUTE 3
-
-/* GSM 03.40 / Chapter 9.2.3.4: TP-Status-Report-Indication */
-#define GSM340_TP_SRI_NONE 0
-#define GSM340_TP_SRI_PRESENT 1
-
-/* GSM 03.40 / Chapter 9.2.3.5: TP-Status-Report-Request */
-#define GSM340_TP_SRR_NONE 0
-#define GSM340_TP_SRR_REQUESTED 1
-
-/* GSM 03.40 / Chapter 9.2.3.9: TP-Protocol-Identifier */
-/* telematic interworking (001 or 111 in bits 7-5) */
-#define GSM340_TP_PID_IMPLICIT 0x00
-#define GSM340_TP_PID_TELEX 0x01
-#define GSM340_TP_PID_FAX_G3 0x02
-#define GSM340_TP_PID_FAX_G4 0x03
-#define GSM340_TP_PID_VOICE 0x04
-#define GSM430_TP_PID_ERMES 0x05
-#define GSM430_TP_PID_NATIONAL_PAGING 0x06
-#define GSM430_TP_PID_VIDEOTEX 0x07
-#define GSM430_TP_PID_TELETEX_UNSPEC 0x08
-#define GSM430_TP_PID_TELETEX_PSPDN 0x09
-#define GSM430_TP_PID_TELETEX_CSPDN 0x0a
-#define GSM430_TP_PID_TELETEX_PSTN 0x0b
-#define GSM430_TP_PID_TELETEX_ISDN 0x0c
-#define GSM430_TP_PID_TELETEX_UCI 0x0d
-#define GSM430_TP_PID_MSG_HANDLING 0x10
-#define GSM430_TP_PID_MSG_X400 0x11
-#define GSM430_TP_PID_EMAIL 0x12
-#define GSM430_TP_PID_GSM_MS 0x1f
-/* if bit 7 = 0 and bit 6 = 1 */
-#define GSM430_TP_PID_SMS_TYPE_0 0
-#define GSM430_TP_PID_SMS_TYPE_1 1
-#define GSM430_TP_PID_SMS_TYPE_2 2
-#define GSM430_TP_PID_SMS_TYPE_3 3
-#define GSM430_TP_PID_SMS_TYPE_4 4
-#define GSM430_TP_PID_SMS_TYPE_5 5
-#define GSM430_TP_PID_SMS_TYPE_6 6
-#define GSM430_TP_PID_SMS_TYPE_7 7
-#define GSM430_TP_PID_RETURN_CALL_MSG 0x1f
-#define GSM430_TP_PID_ME_DATA_DNLOAD 0x3d
-#define GSM430_TP_PID_ME_DE_PERSONAL 0x3e
-#define GSM430_TP_PID_ME_SIM_DNLOAD 0x3f
-
-/* GSM 03.38 Chapter 4: SMS Data Coding Scheme */
-#define GSM338_DCS_00_
-
-#define GSM338_DCS_1110_7BIT (0 << 2)
-#define GSM338_DCS_1111_7BIT (0 << 2)
-#define GSM338_DCS_1111_8BIT_DATA (1 << 2)
-#define GSM338_DCS_1111_CLASS0 0
-#define GSM338_DCS_1111_CLASS1_ME 1
-#define GSM338_DCS_1111_CLASS2_SIM 2
-#define GSM338_DCS_1111_CLASS3_TE 3 /* See TS 07.05 */
-
-#endif /* PROTO_GSM_04_11_H */
diff --git a/libosmocore/include/osmocore/protocol/gsm_04_80.h b/libosmocore/include/osmocore/protocol/gsm_04_80.h
deleted file mode 100644
index fa5c945..0000000
--- a/libosmocore/include/osmocore/protocol/gsm_04_80.h
+++ /dev/null
@@ -1,126 +0,0 @@
-#ifndef PROTO_GSM_04_80_H
-#define PROTO_GSM_04_80_H
-
-/* GSM TS 04.80 definitions (Supplementary Services Specification, Formats and Coding) */
-
-/* Section 3.4 */
-#define GSM0480_MTYPE_RELEASE_COMPLETE 0x2A
-#define GSM0480_MTYPE_FACILITY 0x3A
-#define GSM0480_MTYPE_REGISTER 0x3B
-
-/* Section 3.5 */
-#define GSM0480_IE_FACILITY 0x1C
-#define GSM0480_IE_SS_VERSION 0x7F
-
-/* Section 3.6.2 */
-#define GSM0480_CTYPE_INVOKE 0xA1
-#define GSM0480_CTYPE_RETURN_RESULT 0xA2
-#define GSM0480_CTYPE_RETURN_ERROR 0xA3
-#define GSM0480_CTYPE_REJECT 0xA4
-
-/* Section 3.6.3 */
-#define GSM0480_COMPIDTAG_INVOKE_ID 0x02
-#define GSM0480_COMPIDTAG_LINKED_ID 0x80
-
-/* Section 3.6.4 */
-#define GSM0480_OPERATION_CODE 0x02
-
-/* Section 3.6.5 */
-#define GSM_0480_SEQUENCE_TAG 0x30
-#define GSM_0480_SET_TAG 0x31
-
-/* Section 3.6.6 */
-#define GSM_0480_ERROR_CODE_TAG 0x02
-
-/* Section 3.6.7 */
-/* Table 3.13 */
-#define GSM_0480_PROBLEM_CODE_TAG_GENERAL 0x80
-#define GSM_0480_PROBLEM_CODE_TAG_INVOKE 0x81
-#define GSM_0480_PROBLEM_CODE_TAG_RETURN_RESULT 0x82
-#define GSM_0480_PROBLEM_CODE_TAG_RETURN_ERROR 0x83
-
-/* Table 3.14 */
-#define GSM_0480_GEN_PROB_CODE_UNRECOGNISED 0x00
-#define GSM_0480_GEN_PROB_CODE_MISTYPED 0x01
-#define GSM_0480_GEN_PROB_CODE_BAD_STRUCTURE 0x02
-
-/* Table 3.15 */
-#define GSM_0480_INVOKE_PROB_CODE_DUPLICATE_INVOKE_ID 0x00
-#define GSM_0480_INVOKE_PROB_CODE_UNRECOGNISED_OPERATION 0x01
-#define GSM_0480_INVOKE_PROB_CODE_MISTYPED_PARAMETER 0x02
-#define GSM_0480_INVOKE_PROB_CODE_RESOURCE_LIMITATION 0x03
-#define GSM_0480_INVOKE_PROB_CODE_INITIATING_RELEASE 0x04
-#define GSM_0480_INVOKE_PROB_CODE_UNRECOGNISED_LINKED_ID 0x05
-#define GSM_0480_INVOKE_PROB_CODE_UNEXPECTED_LINKED_RESPONSE 0x06
-#define GSM_0480_INVOKE_PROB_CODE_UNEXPECTED_LINKED_OPERATION 0x07
-
-/* Table 3.16 */
-#define GSM_0480_RESULT_PROB_CODE_UNRECOGNISED_INVOKE_ID 0x00
-#define GSM_0480_RESULT_PROB_CODE_RETURN_RESULT_UNEXPECTED 0x01
-#define GSM_0480_RESULT_PROB_CODE_MISTYPED_PARAMETER 0x02
-
-/* Table 3.17 */
-#define GSM_0480_ERROR_PROB_CODE_UNRECOGNISED_INVOKE_ID 0x00
-#define GSM_0480_ERROR_PROB_CODE_RETURN_ERROR_UNEXPECTED 0x01
-#define GSM_0480_ERROR_PROB_CODE_UNRECOGNISED_ERROR 0x02
-#define GSM_0480_ERROR_PROB_CODE_UNEXPECTED_ERROR 0x03
-#define GSM_0480_ERROR_PROB_CODE_MISTYPED_PARAMETER 0x04
-
-/* Section 4.5 */
-#define GSM0480_OP_CODE_REGISTER_SS 0x0A
-#define GSM0480_OP_CODE_ERASE_SS 0x0B
-#define GSM0480_OP_CODE_ACTIVATE_SS 0x0C
-#define GSM0480_OP_CODE_DEACTIVATE_SS 0x0D
-#define GSM0480_OP_CODE_INTERROGATE_SS 0x0E
-#define GSM0480_OP_CODE_NOTIFY_SS 0x10
-#define GSM0480_OP_CODE_REGISTER_PASSWORD 0x11
-#define GSM0480_OP_CODE_GET_PASSWORD 0x12
-#define GSM0480_OP_CODE_PROCESS_USS_DATA 0x13
-#define GSM0480_OP_CODE_FORWARD_CHECK_SS_IND 0x26
-#define GSM0480_OP_CODE_PROCESS_USS_REQ 0x3B
-#define GSM0480_OP_CODE_USS_REQUEST 0x3C
-#define GSM0480_OP_CODE_USS_NOTIFY 0x3D
-#define GSM0480_OP_CODE_FORWARD_CUG_INFO 0x78
-#define GSM0480_OP_CODE_SPLIT_MPTY 0x79
-#define GSM0480_OP_CODE_RETRIEVE_MPTY 0x7A
-#define GSM0480_OP_CODE_HOLD_MPTY 0x7B
-#define GSM0480_OP_CODE_BUILD_MPTY 0x7C
-#define GSM0480_OP_CODE_FORWARD_CHARGE_ADVICE 0x7D
-
-#define GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER 0x01
-#define GSM0480_ERR_CODE_ILLEGAL_SUBSCRIBER 0x09
-#define GSM0480_ERR_CODE_BEARER_SERVICE_NOT_PROVISIONED 0x0A
-#define GSM0480_ERR_CODE_TELESERVICE_NOT_PROVISIONED 0x0B
-#define GSM0480_ERR_CODE_ILLEGAL_EQUIPMENT 0x0C
-#define GSM0480_ERR_CODE_CALL_BARRED 0x0D
-#define GSM0480_ERR_CODE_ILLEGAL_SS_OPERATION 0x10
-#define GSM0480_ERR_CODE_SS_ERROR_STATUS 0x11
-#define GSM0480_ERR_CODE_SS_NOT_AVAILABLE 0x12
-#define GSM0480_ERR_CODE_SS_SUBSCRIPTION_VIOLATION 0x13
-#define GSM0480_ERR_CODE_SS_INCOMPATIBILITY 0x14
-#define GSM0480_ERR_CODE_FACILITY_NOT_SUPPORTED 0x15
-#define GSM0480_ERR_CODE_ABSENT_SUBSCRIBER 0x1B
-#define GSM0480_ERR_CODE_SYSTEM_FAILURE 0x22
-#define GSM0480_ERR_CODE_DATA_MISSING 0x23
-#define GSM0480_ERR_CODE_UNEXPECTED_DATA_VALUE 0x24
-#define GSM0480_ERR_CODE_PW_REGISTRATION_FAILURE 0x25
-#define GSM0480_ERR_CODE_NEGATIVE_PW_CHECK 0x26
-#define GSM0480_ERR_CODE_NUM_PW_ATTEMPTS_VIOLATION 0x2B
-#define GSM0480_ERR_CODE_UNKNOWN_ALPHABET 0x47
-#define GSM0480_ERR_CODE_USSD_BUSY 0x48
-#define GSM0480_ERR_CODE_MAX_MPTY_PARTICIPANTS 0x7E
-#define GSM0480_ERR_CODE_RESOURCES_NOT_AVAILABLE 0x7F
-
-/* ASN.1 type-tags */
-#define ASN1_BOOLEAN_TAG 0x01
-#define ASN1_INTEGER_TAG 0x02
-#define ASN1_BIT_STRING_TAG 0x03
-#define ASN1_OCTET_STRING_TAG 0x04
-#define ASN1_NULL_TYPE_TAG 0x05
-#define ASN1_OBJECT_ID_TAG 0x06
-#define ASN1_UTF8_STRING_TAG 0x0C
-#define ASN1_PRINTABLE_STRING_TAG 0x13
-#define ASN1_IA5_STRING_TAG 0x16
-#define ASN1_UNICODE_STRING_TAG 0x1E
-
-#endif /* PROTO_GSM_04_80_H */
diff --git a/libosmocore/include/osmocore/protocol/gsm_08_08.h b/libosmocore/include/osmocore/protocol/gsm_08_08.h
deleted file mode 100644
index 6b8f935..0000000
--- a/libosmocore/include/osmocore/protocol/gsm_08_08.h
+++ /dev/null
@@ -1,303 +0,0 @@
-/* From GSM08.08 */
-
-#ifndef GSM_0808_H
-#define GSM_0808_H
-
-#include <stdlib.h>
-
-/*
- * this is from GSM 03.03 CGI but is copied in GSM 08.08
- * in § 3.2.2.27 for Cell Identifier List
- */
-enum CELL_IDENT {
- CELL_IDENT_WHOLE_GLOBAL = 0,
- CELL_IDENT_LAC_AND_CI = 1,
- CELL_IDENT_CI = 2,
- CELL_IDENT_NO_CELL = 3,
- CELL_IDENT_LAI_AND_LAC = 4,
- CELL_IDENT_LAC = 5,
- CELL_IDENT_BSS = 6,
- CELL_IDENT_UTRAN_PLMN_LAC_RNC = 8,
- CELL_IDENT_UTRAN_RNC = 9,
- CELL_IDENT_UTRAN_LAC_RNC = 10,
-};
-
-
-/* GSM 08.06 § 6.3 */
-enum BSSAP_MSG_TYPE {
- BSSAP_MSG_BSS_MANAGEMENT = 0x0,
- BSSAP_MSG_DTAP = 0x1,
-};
-
-struct bssmap_header {
- uint8_t type;
- uint8_t length;
-} __attribute__((packed));
-
-struct dtap_header {
- uint8_t type;
- uint8_t link_id;
- uint8_t length;
-} __attribute__((packed));
-
-
-enum BSS_MAP_MSG_TYPE {
- BSS_MAP_MSG_RESERVED_0 = 0,
-
- /* ASSIGNMENT MESSAGES */
- BSS_MAP_MSG_ASSIGMENT_RQST = 1,
- BSS_MAP_MSG_ASSIGMENT_COMPLETE = 2,
- BSS_MAP_MSG_ASSIGMENT_FAILURE = 3,
-
- /* HANDOVER MESSAGES */
- BSS_MAP_MSG_HANDOVER_RQST = 16,
- BSS_MAP_MSG_HANDOVER_REQUIRED = 17,
- BSS_MAP_MSG_HANDOVER_RQST_ACKNOWLEDGE= 18,
- BSS_MAP_MSG_HANDOVER_CMD = 19,
- BSS_MAP_MSG_HANDOVER_COMPLETE = 20,
- BSS_MAP_MSG_HANDOVER_SUCCEEDED = 21,
- BSS_MAP_MSG_HANDOVER_FAILURE = 22,
- BSS_MAP_MSG_HANDOVER_PERFORMED = 23,
- BSS_MAP_MSG_HANDOVER_CANDIDATE_ENQUIRE = 24,
- BSS_MAP_MSG_HANDOVER_CANDIDATE_RESPONSE = 25,
- BSS_MAP_MSG_HANDOVER_REQUIRED_REJECT = 26,
- BSS_MAP_MSG_HANDOVER_DETECT = 27,
-
- /* RELEASE MESSAGES */
- BSS_MAP_MSG_CLEAR_CMD = 32,
- BSS_MAP_MSG_CLEAR_COMPLETE = 33,
- BSS_MAP_MSG_CLEAR_RQST = 34,
- BSS_MAP_MSG_RESERVED_1 = 35,
- BSS_MAP_MSG_RESERVED_2 = 36,
- BSS_MAP_MSG_SAPI_N_REJECT = 37,
- BSS_MAP_MSG_CONFUSION = 38,
-
- /* OTHER CONNECTION RELATED MESSAGES */
- BSS_MAP_MSG_SUSPEND = 40,
- BSS_MAP_MSG_RESUME = 41,
- BSS_MAP_MSG_CONNECTION_ORIENTED_INFORMATION = 42,
- BSS_MAP_MSG_PERFORM_LOCATION_RQST = 43,
- BSS_MAP_MSG_LSA_INFORMATION = 44,
- BSS_MAP_MSG_PERFORM_LOCATION_RESPONSE = 45,
- BSS_MAP_MSG_PERFORM_LOCATION_ABORT = 46,
- BSS_MAP_MSG_COMMON_ID = 47,
-
- /* GENERAL MESSAGES */
- BSS_MAP_MSG_RESET = 48,
- BSS_MAP_MSG_RESET_ACKNOWLEDGE = 49,
- BSS_MAP_MSG_OVERLOAD = 50,
- BSS_MAP_MSG_RESERVED_3 = 51,
- BSS_MAP_MSG_RESET_CIRCUIT = 52,
- BSS_MAP_MSG_RESET_CIRCUIT_ACKNOWLEDGE = 53,
- BSS_MAP_MSG_MSC_INVOKE_TRACE = 54,
- BSS_MAP_MSG_BSS_INVOKE_TRACE = 55,
- BSS_MAP_MSG_CONNECTIONLESS_INFORMATION = 58,
-
- /* TERRESTRIAL RESOURCE MESSAGES */
- BSS_MAP_MSG_BLOCK = 64,
- BSS_MAP_MSG_BLOCKING_ACKNOWLEDGE = 65,
- BSS_MAP_MSG_UNBLOCK = 66,
- BSS_MAP_MSG_UNBLOCKING_ACKNOWLEDGE = 67,
- BSS_MAP_MSG_CIRCUIT_GROUP_BLOCK = 68,
- BSS_MAP_MSG_CIRCUIT_GROUP_BLOCKING_ACKNOWLEDGE = 69,
- BSS_MAP_MSG_CIRCUIT_GROUP_UNBLOCK = 70,
- BSS_MAP_MSG_CIRCUIT_GROUP_UNBLOCKING_ACKNOWLEDGE = 71,
- BSS_MAP_MSG_UNEQUIPPED_CIRCUIT = 72,
- BSS_MAP_MSG_CHANGE_CIRCUIT = 78,
- BSS_MAP_MSG_CHANGE_CIRCUIT_ACKNOWLEDGE = 79,
-
- /* RADIO RESOURCE MESSAGES */
- BSS_MAP_MSG_RESOURCE_RQST = 80,
- BSS_MAP_MSG_RESOURCE_INDICATION = 81,
- BSS_MAP_MSG_PAGING = 82,
- BSS_MAP_MSG_CIPHER_MODE_CMD = 83,
- BSS_MAP_MSG_CLASSMARK_UPDATE = 84,
- BSS_MAP_MSG_CIPHER_MODE_COMPLETE = 85,
- BSS_MAP_MSG_QUEUING_INDICATION = 86,
- BSS_MAP_MSG_COMPLETE_LAYER_3 = 87,
- BSS_MAP_MSG_CLASSMARK_RQST = 88,
- BSS_MAP_MSG_CIPHER_MODE_REJECT = 89,
- BSS_MAP_MSG_LOAD_INDICATION = 90,
-
- /* VGCS/VBS */
- BSS_MAP_MSG_VGCS_VBS_SETUP = 4,
- BSS_MAP_MSG_VGCS_VBS_SETUP_ACK = 5,
- BSS_MAP_MSG_VGCS_VBS_SETUP_REFUSE = 6,
- BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RQST = 7,
- BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RESULT = 28,
- BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_FAILURE = 29,
- BSS_MAP_MSG_VGCS_VBS_QUEUING_INDICATION = 30,
- BSS_MAP_MSG_UPLINK_RQST = 31,
- BSS_MAP_MSG_UPLINK_RQST_ACKNOWLEDGE = 39,
- BSS_MAP_MSG_UPLINK_RQST_CONFIRMATION = 73,
- BSS_MAP_MSG_UPLINK_RELEASE_INDICATION = 74,
- BSS_MAP_MSG_UPLINK_REJECT_CMD = 75,
- BSS_MAP_MSG_UPLINK_RELEASE_CMD = 76,
- BSS_MAP_MSG_UPLINK_SEIZED_CMD = 77,
-};
-
-enum GSM0808_IE_CODING {
- GSM0808_IE_CIRCUIT_IDENTITY_CODE = 1,
- GSM0808_IE_RESERVED_0 = 2,
- GSM0808_IE_RESOURCE_AVAILABLE = 3,
- GSM0808_IE_CAUSE = 4,
- GSM0808_IE_CELL_IDENTIFIER = 5,
- GSM0808_IE_PRIORITY = 6,
- GSM0808_IE_LAYER_3_HEADER_INFORMATION = 7,
- GSM0808_IE_IMSI = 8,
- GSM0808_IE_TMSI = 9,
- GSM0808_IE_ENCRYPTION_INFORMATION = 10,
- GSM0808_IE_CHANNEL_TYPE = 11,
- GSM0808_IE_PERIODICITY = 12,
- GSM0808_IE_EXTENDED_RESOURCE_INDICATOR = 13,
- GSM0808_IE_NUMBER_OF_MSS = 14,
- GSM0808_IE_RESERVED_1 = 15,
- GSM0808_IE_RESERVED_2 = 16,
- GSM0808_IE_RESERVED_3 = 17,
- GSM0808_IE_CLASSMARK_INFORMATION_T2 = 18,
- GSM0808_IE_CLASSMARK_INFORMATION_T3 = 19,
- GSM0808_IE_INTERFERENCE_BAND_TO_USE = 20,
- GSM0808_IE_RR_CAUSE = 21,
- GSM0808_IE_RESERVED_4 = 22,
- GSM0808_IE_LAYER_3_INFORMATION = 23,
- GSM0808_IE_DLCI = 24,
- GSM0808_IE_DOWNLINK_DTX_FLAG = 25,
- GSM0808_IE_CELL_IDENTIFIER_LIST = 26,
- GSM0808_IE_RESPONSE_RQST = 27,
- GSM0808_IE_RESOURCE_INDICATION_METHOD = 28,
- GSM0808_IE_CLASSMARK_INFORMATION_TYPE_1 = 29,
- GSM0808_IE_CIRCUIT_IDENTITY_CODE_LIST = 30,
- GSM0808_IE_DIAGNOSTIC = 31,
- GSM0808_IE_LAYER_3_MESSAGE_CONTENTS = 32,
- GSM0808_IE_CHOSEN_CHANNEL = 33,
- GSM0808_IE_TOTAL_RESOURCE_ACCESSIBLE = 34,
- GSM0808_IE_CIPHER_RESPONSE_MODE = 35,
- GSM0808_IE_CHANNEL_NEEDED = 36,
- GSM0808_IE_TRACE_TYPE = 37,
- GSM0808_IE_TRIGGERID = 38,
- GSM0808_IE_TRACE_REFERENCE = 39,
- GSM0808_IE_TRANSACTIONID = 40,
- GSM0808_IE_MOBILE_IDENTITY = 41,
- GSM0808_IE_OMCID = 42,
- GSM0808_IE_FORWARD_INDICATOR = 43,
- GSM0808_IE_CHOSEN_ENCR_ALG = 44,
- GSM0808_IE_CIRCUIT_POOL = 45,
- GSM0808_IE_CIRCUIT_POOL_LIST = 46,
- GSM0808_IE_TIME_INDICATION = 47,
- GSM0808_IE_RESOURCE_SITUATION = 48,
- GSM0808_IE_CURRENT_CHANNEL_TYPE_1 = 49,
- GSM0808_IE_QUEUEING_INDICATOR = 50,
- GSM0808_IE_SPEECH_VERSION = 64,
- GSM0808_IE_ASSIGNMENT_REQUIREMENT = 51,
- GSM0808_IE_TALKER_FLAG = 53,
- GSM0808_IE_CONNECTION_RELEASE_RQSTED = 54,
- GSM0808_IE_GROUP_CALL_REFERENCE = 55,
- GSM0808_IE_EMLPP_PRIORITY = 56,
- GSM0808_IE_CONFIG_EVO_INDI = 57,
- GSM0808_IE_OLD_BSS_TO_NEW_BSS_INFORMATION = 58,
- GSM0808_IE_LSA_IDENTIFIER = 59,
- GSM0808_IE_LSA_IDENTIFIER_LIST = 60,
- GSM0808_IE_LSA_INFORMATION = 61,
- GSM0808_IE_LCS_QOS = 62,
- GSM0808_IE_LSA_ACCESS_CTRL_SUPPR = 63,
- GSM0808_IE_LCS_PRIORITY = 67,
- GSM0808_IE_LOCATION_TYPE = 68,
- GSM0808_IE_LOCATION_ESTIMATE = 69,
- GSM0808_IE_POSITIONING_DATA = 70,
- GSM0808_IE_LCS_CAUSE = 71,
- GSM0808_IE_LCS_CLIENT_TYPE = 72,
- GSM0808_IE_APDU = 73,
- GSM0808_IE_NETWORK_ELEMENT_IDENTITY = 74,
- GSM0808_IE_GPS_ASSISTANCE_DATA = 75,
- GSM0808_IE_DECIPHERING_KEYS = 76,
- GSM0808_IE_RETURN_ERROR_RQST = 77,
- GSM0808_IE_RETURN_ERROR_CAUSE = 78,
- GSM0808_IE_SEGMENTATION = 79,
- GSM0808_IE_SERVICE_HANDOVER = 80,
- GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_UMTS = 81,
- GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_CDMA2000= 82,
- GSM0808_IE_RESERVED_5 = 65,
- GSM0808_IE_RESERVED_6 = 66,
-};
-
-enum gsm0808_cause {
- GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE = 0,
- GSM0808_CAUSE_RADIO_INTERFACE_FAILURE = 1,
- GSM0808_CAUSE_UPLINK_QUALITY = 2,
- GSM0808_CAUSE_UPLINK_STRENGTH = 3,
- GSM0808_CAUSE_DOWNLINK_QUALITY = 4,
- GSM0808_CAUSE_DOWNLINK_STRENGTH = 5,
- GSM0808_CAUSE_DISTANCE = 6,
- GSM0808_CAUSE_O_AND_M_INTERVENTION = 7,
- GSM0808_CAUSE_RESPONSE_TO_MSC_INVOCATION = 8,
- GSM0808_CAUSE_CALL_CONTROL = 9,
- GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION = 10,
- GSM0808_CAUSE_HANDOVER_SUCCESSFUL = 11,
- GSM0808_CAUSE_BETTER_CELL = 12,
- GSM0808_CAUSE_DIRECTED_RETRY = 13,
- GSM0808_CAUSE_JOINED_GROUP_CALL_CHANNEL = 14,
- GSM0808_CAUSE_TRAFFIC = 15,
- GSM0808_CAUSE_EQUIPMENT_FAILURE = 32,
- GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE = 33,
- GSM0808_CAUSE_RQSTED_TERRESTRIAL_RESOURCE_UNAVAILABLE = 34,
- GSM0808_CAUSE_CCCH_OVERLOAD = 35,
- GSM0808_CAUSE_PROCESSOR_OVERLOAD = 36,
- GSM0808_CAUSE_BSS_NOT_EQUIPPED = 37,
- GSM0808_CAUSE_MS_NOT_EQUIPPED = 38,
- GSM0808_CAUSE_INVALID_CELL = 39,
- GSM0808_CAUSE_TRAFFIC_LOAD = 40,
- GSM0808_CAUSE_PREEMPTION = 41,
- GSM0808_CAUSE_RQSTED_TRANSCODING_RATE_ADAPTION_UNAVAILABLE = 48,
- GSM0808_CAUSE_CIRCUIT_POOL_MISMATCH = 49,
- GSM0808_CAUSE_SWITCH_CIRCUIT_POOL = 50,
- GSM0808_CAUSE_RQSTED_SPEECH_VERSION_UNAVAILABLE = 51,
- GSM0808_CAUSE_LSA_NOT_ALLOWED = 52,
- GSM0808_CAUSE_CIPHERING_ALGORITHM_NOT_SUPPORTED = 64,
- GSM0808_CAUSE_TERRESTRIAL_CIRCUIT_ALREADY_ALLOCATED = 80,
- GSM0808_CAUSE_INVALID_MESSAGE_CONTENTS = 81,
- GSM0808_CAUSE_INFORMATION_ELEMENT_OR_FIELD_MISSING = 82,
- GSM0808_CAUSE_INCORRECT_VALUE = 83,
- GSM0808_CAUSE_UNKNOWN_MESSAGE_TYPE = 84,
- GSM0808_CAUSE_UNKNOWN_INFORMATION_ELEMENT = 85,
- GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC = 96,
-};
-
-/* GSM 08.08 3.2.2.11 Channel Type */
-enum gsm0808_chan_indicator {
- GSM0808_CHAN_SPEECH = 1,
- GSM0808_CHAN_DATA = 2,
- GSM0808_CHAN_SIGN = 3,
-};
-
-enum gsm0808_chan_rate_type_data {
- GSM0808_DATA_FULL_BM = 0x8,
- GSM0808_DATA_HALF_LM = 0x9,
- GSM0808_DATA_FULL_RPREF = 0xa,
- GSM0808_DATA_HALF_PREF = 0xb,
- GSM0808_DATA_FULL_PREF_NO_CHANGE = 0x1a,
- GSM0808_DATA_HALF_PREF_NO_CHANGE = 0x1b,
- GSM0808_DATA_MULTI_MASK = 0x20,
- GSM0808_DATA_MULTI_MASK_NO_CHANGE = 0x30,
-};
-
-enum gsm0808_chan_rate_type_speech {
- GSM0808_SPEECH_FULL_BM = 0x8,
- GSM0808_SPEECH_HALF_LM = 0x9,
- GSM0808_SPEECH_FULL_PREF= 0xa,
- GSM0808_SPEECH_HALF_PREF= 0xb,
- GSM0808_SPEECH_FULL_PREF_NO_CHANGE = 0x1a,
- GSM0808_SPEECH_HALF_PREF_NO_CHANGE = 0x1b,
- GSM0808_SPEECH_PERM = 0xf,
- GSM0808_SPEECH_PERM_NO_CHANGE = 0x1f,
-};
-
-enum gsm0808_permitted_speech {
- GSM0808_PERM_FR1 = 0x01,
- GSM0808_PERM_FR2 = 0x11,
- GSM0808_PERM_FR3 = 0x21,
- GSM0808_PERM_HR1 = GSM0808_PERM_FR1 | 0x4,
- GSM0808_PERM_HR2 = GSM0808_PERM_FR2 | 0x4,
- GSM0808_PERM_HR3 = GSM0808_PERM_FR3 | 0x4,
-};
-
-#endif
diff --git a/libosmocore/include/osmocore/protocol/gsm_08_58.h b/libosmocore/include/osmocore/protocol/gsm_08_58.h
deleted file mode 100644
index ca9398f..0000000
--- a/libosmocore/include/osmocore/protocol/gsm_08_58.h
+++ /dev/null
@@ -1,512 +0,0 @@
-#ifndef PROTO_GSM_08_58_H
-#define PROTO_GSM_08_58_H
-
-/* GSM Radio Signalling Link messages on the A-bis interface
- * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
-
-/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-
-struct abis_rsl_common_hdr {
- uint8_t msg_discr;
- uint8_t msg_type;
- uint8_t data[0];
-} __attribute__ ((packed));
-
-/* Chapter 8.3 */
-struct abis_rsl_rll_hdr {
- struct abis_rsl_common_hdr c;
- uint8_t ie_chan;
- uint8_t chan_nr;
- uint8_t ie_link_id;
- uint8_t link_id;
- uint8_t data[0];
-} __attribute__ ((packed));
-
-/* Chapter 8.3 and 8.4 */
-struct abis_rsl_dchan_hdr {
- struct abis_rsl_common_hdr c;
- uint8_t ie_chan;
- uint8_t chan_nr;
- uint8_t data[0];
-} __attribute__ ((packed));
-
-
-/* Chapter 9.1 */
-#define ABIS_RSL_MDISC_RLL 0x02
-#define ABIS_RSL_MDISC_DED_CHAN 0x08
-#define ABIS_RSL_MDISC_COM_CHAN 0x0c
-#define ABIS_RSL_MDISC_TRX 0x10
-#define ABIS_RSL_MDISC_LOC 0x20
-#define ABIS_RSL_MDISC_IPACCESS 0x7e
-#define ABIS_RSL_MDISC_TRANSP 0x01
-
-#define ABIS_RSL_MDISC_IS_TRANSP(x) (x & 0x01)
-
-/* Chapter 9.1 */
-enum abis_rsl_msgtype {
- /* Radio Link Layer Management */
- RSL_MT_DATA_REQ = 0x01,
- RSL_MT_DATA_IND,
- RSL_MT_ERROR_IND,
- RSL_MT_EST_REQ,
- RSL_MT_EST_CONF,
- RSL_MT_EST_IND,
- RSL_MT_REL_REQ,
- RSL_MT_REL_CONF,
- RSL_MT_REL_IND,
- RSL_MT_UNIT_DATA_REQ,
- RSL_MT_UNIT_DATA_IND, /* 0x0b */
-
- /* Common Channel Management / TRX Management */
- RSL_MT_BCCH_INFO = 0x11,
- RSL_MT_CCCH_LOAD_IND,
- RSL_MT_CHAN_RQD,
- RSL_MT_DELETE_IND,
- RSL_MT_PAGING_CMD,
- RSL_MT_IMMEDIATE_ASSIGN_CMD,
- RSL_MT_SMS_BC_REQ,
- /* empty */
- RSL_MT_RF_RES_IND = 0x19,
- RSL_MT_SACCH_FILL,
- RSL_MT_OVERLOAD,
- RSL_MT_ERROR_REPORT,
- RSL_MT_SMS_BC_CMD,
- RSL_MT_CBCH_LOAD_IND,
- RSL_MT_NOT_CMD, /* 0x1f */
-
- /* Dedicate Channel Management */
- RSL_MT_CHAN_ACTIV = 0x21,
- RSL_MT_CHAN_ACTIV_ACK,
- RSL_MT_CHAN_ACTIV_NACK,
- RSL_MT_CONN_FAIL,
- RSL_MT_DEACTIVATE_SACCH,
- RSL_MT_ENCR_CMD,
- RSL_MT_HANDO_DET,
- RSL_MT_MEAS_RES,
- RSL_MT_MODE_MODIFY_REQ,
- RSL_MT_MODE_MODIFY_ACK,
- RSL_MT_MODE_MODIFY_NACK,
- RSL_MT_PHY_CONTEXT_REQ,
- RSL_MT_PHY_CONTEXT_CONF,
- RSL_MT_RF_CHAN_REL,
- RSL_MT_MS_POWER_CONTROL,
- RSL_MT_BS_POWER_CONTROL, /* 0x30 */
- RSL_MT_PREPROC_CONFIG,
- RSL_MT_PREPROC_MEAS_RES,
- RSL_MT_RF_CHAN_REL_ACK,
- RSL_MT_SACCH_INFO_MODIFY,
- RSL_MT_TALKER_DET,
- RSL_MT_LISTENER_DET,
- RSL_MT_REMOTE_CODEC_CONF_REP,
- RSL_MT_RTD_REP,
- RSL_MT_PRE_HANDO_NOTIF,
- RSL_MT_MR_CODEC_MOD_REQ,
- RSL_MT_MR_CODEC_MOD_ACK,
- RSL_MT_MR_CODEC_MOD_NACK,
- RSL_MT_MR_CODEC_MOD_PER,
- RSL_MT_TFO_REP,
- RSL_MT_TFO_MOD_REQ, /* 0x3f */
- RSL_MT_LOCATION_INFO = 0x41,
-
- /* ip.access specific RSL message types */
- RSL_MT_IPAC_DIR_RETR_ENQ = 0x40,
- RSL_MT_IPAC_PDCH_ACT = 0x48,
- RSL_MT_IPAC_PDCH_ACT_ACK,
- RSL_MT_IPAC_PDCH_ACT_NACK,
- RSL_MT_IPAC_PDCH_DEACT = 0x4b,
- RSL_MT_IPAC_PDCH_DEACT_ACK,
- RSL_MT_IPAC_PDCH_DEACT_NACK,
- RSL_MT_IPAC_CONNECT_MUX = 0x50,
- RSL_MT_IPAC_CONNECT_MUX_ACK,
- RSL_MT_IPAC_CONNECT_MUX_NACK,
- RSL_MT_IPAC_BIND_MUX = 0x53,
- RSL_MT_IPAC_BIND_MUX_ACK,
- RSL_MT_IPAC_BIND_MUX_NACK,
- RSL_MT_IPAC_DISC_MUX = 0x56,
- RSL_MT_IPAC_DISC_MUX_ACK,
- RSL_MT_IPAC_DISC_MUX_NACK,
- RSL_MT_IPAC_CRCX = 0x70, /* Bind to local BTS RTP port */
- RSL_MT_IPAC_CRCX_ACK,
- RSL_MT_IPAC_CRCX_NACK,
- RSL_MT_IPAC_MDCX = 0x73,
- RSL_MT_IPAC_MDCX_ACK,
- RSL_MT_IPAC_MDCX_NACK,
- RSL_MT_IPAC_DLCX_IND = 0x76,
- RSL_MT_IPAC_DLCX = 0x77,
- RSL_MT_IPAC_DLCX_ACK,
- RSL_MT_IPAC_DLCX_NACK,
-};
-
-/* Siemens vendor-specific */
-enum abis_rsl_msgtype_siemens {
- RSL_MT_SIEMENS_MRPCI = 0x41,
- RSL_MT_SIEMENS_INTRAC_HO_COND_IND = 0x42,
- RSL_MT_SIEMENS_INTERC_HO_COND_IND = 0x43,
- RSL_MT_SIEMENS_FORCED_HO_REQ = 0x44,
- RSL_MT_SIEMENS_PREF_AREA_REQ = 0x45,
- RSL_MT_SIEMENS_PREF_AREA = 0x46,
- RSL_MT_SIEMENS_START_TRACE = 0x47,
- RSL_MT_SIEMENS_START_TRACE_ACK = 0x48,
- RSL_MT_SIEMENS_STOP_TRACE = 0x49,
- RSL_MT_SIEMENS_TRMR = 0x4a,
- RSL_MT_SIEMENS_HO_FAIL_IND = 0x4b,
- RSL_MT_SIEMENS_STOP_TRACE_ACK = 0x4c,
- RSL_MT_SIEMENS_UPLF = 0x4d,
- RSL_MT_SIEMENS_UPLB = 0x4e,
- RSL_MT_SIEMENS_SET_SYS_INFO_10 = 0x4f,
- RSL_MT_SIEMENS_MODIF_COND_IND = 0x50,
-};
-
-/* Chapter 9.3 */
-enum abis_rsl_ie {
- RSL_IE_CHAN_NR = 0x01,
- RSL_IE_LINK_IDENT,
- RSL_IE_ACT_TYPE,
- RSL_IE_BS_POWER,
- RSL_IE_CHAN_IDENT,
- RSL_IE_CHAN_MODE,
- RSL_IE_ENCR_INFO,
- RSL_IE_FRAME_NUMBER,
- RSL_IE_HANDO_REF,
- RSL_IE_L1_INFO,
- RSL_IE_L3_INFO,
- RSL_IE_MS_IDENTITY,
- RSL_IE_MS_POWER,
- RSL_IE_PAGING_GROUP,
- RSL_IE_PAGING_LOAD,
- RSL_IE_PYHS_CONTEXT = 0x10,
- RSL_IE_ACCESS_DELAY,
- RSL_IE_RACH_LOAD,
- RSL_IE_REQ_REFERENCE,
- RSL_IE_RELEASE_MODE,
- RSL_IE_RESOURCE_INFO,
- RSL_IE_RLM_CAUSE,
- RSL_IE_STARTNG_TIME,
- RSL_IE_TIMING_ADVANCE,
- RSL_IE_UPLINK_MEAS,
- RSL_IE_CAUSE,
- RSL_IE_MEAS_RES_NR,
- RSL_IE_MSG_ID,
- /* reserved */
- RSL_IE_SYSINFO_TYPE = 0x1e,
- RSL_IE_MS_POWER_PARAM,
- RSL_IE_BS_POWER_PARAM,
- RSL_IE_PREPROC_PARAM,
- RSL_IE_PREPROC_MEAS,
- RSL_IE_IMM_ASS_INFO, /* Phase 1 (3.6.0), later Full below */
- RSL_IE_SMSCB_INFO = 0x24,
- RSL_IE_MS_TIMING_OFFSET,
- RSL_IE_ERR_MSG,
- RSL_IE_FULL_BCCH_INFO,
- RSL_IE_CHAN_NEEDED,
- RSL_IE_CB_CMD_TYPE,
- RSL_IE_SMSCB_MSG,
- RSL_IE_FULL_IMM_ASS_INFO,
- RSL_IE_SACCH_INFO,
- RSL_IE_CBCH_LOAD_INFO,
- RSL_IE_SMSCB_CHAN_INDICATOR,
- RSL_IE_GROUP_CALL_REF,
- RSL_IE_CHAN_DESC = 0x30,
- RSL_IE_NCH_DRX_INFO,
- RSL_IE_CMD_INDICATOR,
- RSL_IE_EMLPP_PRIO,
- RSL_IE_UIC,
- RSL_IE_MAIN_CHAN_REF,
- RSL_IE_MR_CONFIG,
- RSL_IE_MR_CONTROL,
- RSL_IE_SUP_CODEC_TYPES,
- RSL_IE_CODEC_CONFIG,
- RSL_IE_RTD,
- RSL_IE_TFO_STATUS,
- RSL_IE_LLP_APDU,
- /* Siemens vendor-specific */
- RSL_IE_SIEMENS_MRPCI = 0x40,
- RSL_IE_SIEMENS_PREF_AREA_TYPE = 0x43,
- RSL_IE_SIEMENS_ININ_CELL_HO_PAR = 0x45,
- RSL_IE_SIEMENS_TRACE_REF_NR = 0x46,
- RSL_IE_SIEMENS_INT_TRACE_IDX = 0x47,
- RSL_IE_SIEMENS_L2_HDR_INFO = 0x48,
- RSL_IE_SIEMENS_HIGHEST_RATE = 0x4e,
- RSL_IE_SIEMENS_SUGGESTED_RATE = 0x4f,
-
- /* ip.access */
- RSL_IE_IPAC_SRTP_CONFIG = 0xe0,
- RSL_IE_IPAC_PROXY_UDP = 0xe1,
- RSL_IE_IPAC_BSCMPL_TOUT = 0xe2,
- RSL_IE_IPAC_REMOTE_IP = 0xf0,
- RSL_IE_IPAC_REMOTE_PORT = 0xf1,
- RSL_IE_IPAC_RTP_PAYLOAD = 0xf2,
- RSL_IE_IPAC_LOCAL_PORT = 0xf3,
- RSL_IE_IPAC_SPEECH_MODE = 0xf4,
- RSL_IE_IPAC_LOCAL_IP = 0xf5,
- RSL_IE_IPAC_CONN_STAT = 0xf6,
- RSL_IE_IPAC_HO_C_PARMS = 0xf7,
- RSL_IE_IPAC_CONN_ID = 0xf8,
- RSL_IE_IPAC_RTP_CSD_FMT = 0xf9,
- RSL_IE_IPAC_RTP_JIT_BUF = 0xfa,
- RSL_IE_IPAC_RTP_COMPR = 0xfb,
- RSL_IE_IPAC_RTP_PAYLOAD2= 0xfc,
- RSL_IE_IPAC_RTP_MPLEX = 0xfd,
- RSL_IE_IPAC_RTP_MPLEX_ID= 0xfe,
-};
-
-/* Chapter 9.3.1 */
-#define RSL_CHAN_NR_MASK 0xf8
-#define RSL_CHAN_Bm_ACCHs 0x08
-#define RSL_CHAN_Lm_ACCHs 0x10 /* .. 0x18 */
-#define RSL_CHAN_SDCCH4_ACCH 0x20 /* .. 0x38 */
-#define RSL_CHAN_SDCCH8_ACCH 0x40 /* ...0x78 */
-#define RSL_CHAN_BCCH 0x80
-#define RSL_CHAN_RACH 0x88
-#define RSL_CHAN_PCH_AGCH 0x90
-
-/* Chapter 9.3.3 */
-#define RSL_ACT_TYPE_INITIAL 0x00
-#define RSL_ACT_TYPE_REACT 0x80
-#define RSL_ACT_INTRA_IMM_ASS 0x00
-#define RSL_ACT_INTRA_NORM_ASS 0x01
-#define RSL_ACT_INTER_ASYNC 0x02
-#define RSL_ACT_INTER_SYNC 0x03
-#define RSL_ACT_SECOND_ADD 0x04
-#define RSL_ACT_SECOND_MULTI 0x05
-
-/* Chapter 9.3.6 */
-struct rsl_ie_chan_mode {
- uint8_t dtx_dtu;
- uint8_t spd_ind;
- uint8_t chan_rt;
- uint8_t chan_rate;
-} __attribute__ ((packed));
-#define RSL_CMOD_DTXu 0x01 /* uplink */
-#define RSL_CMOD_DTXd 0x02 /* downlink */
-enum rsl_cmod_spd {
- RSL_CMOD_SPD_SPEECH = 0x01,
- RSL_CMOD_SPD_DATA = 0x02,
- RSL_CMOD_SPD_SIGN = 0x03,
-};
-#define RSL_CMOD_CRT_SDCCH 0x01
-#define RSL_CMOD_CRT_TCH_Bm 0x08 /* full-rate */
-#define RSL_CMOD_CRT_TCH_Lm 0x09 /* half-rate */
-/* FIXME: More CRT types */
-/* Speech */
-#define RSL_CMOD_SP_GSM1 0x01
-#define RSL_CMOD_SP_GSM2 0x11
-#define RSL_CMOD_SP_GSM3 0x21
-/* Data */
-#define RSL_CMOD_SP_NT_14k5 0x58
-#define RSL_CMOD_SP_NT_12k0 0x50
-#define RSL_CMOD_SP_NT_6k0 0x51
-
-/* Chapter 9.3.5 */
-struct rsl_ie_chan_ident {
- /* GSM 04.08 10.5.2.5 */
- struct {
- uint8_t iei;
- uint8_t chan_nr; /* enc_chan_nr */
- uint8_t oct3;
- uint8_t oct4;
- } chan_desc;
-#if 0 /* spec says we need this but Abissim doesn't use it */
- struct {
- uint8_t tag;
- uint8_t len;
- } mobile_alloc;
-#endif
-} __attribute__ ((packed));
-
-/* Chapter 9.3.22 */
-#define RLL_CAUSE_T200_EXPIRED 0x01
-#define RLL_CAUSE_REEST_REQ 0x02
-#define RLL_CAUSE_UNSOL_UA_RESP 0x03
-#define RLL_CAUSE_UNSOL_DM_RESP 0x04
-#define RLL_CAUSE_UNSOL_DM_RESP_MF 0x05
-#define RLL_CAUSE_UNSOL_SPRV_RESP 0x06
-#define RLL_CAUSE_SEQ_ERR 0x07
-#define RLL_CAUSE_UFRM_INC_PARAM 0x08
-#define RLL_CAUSE_SFRM_INC_PARAM 0x09
-#define RLL_CAUSE_IFRM_INC_MBITS 0x0a
-#define RLL_CAUSE_IFRM_INC_LEN 0x0b
-#define RLL_CAUSE_FRM_UNIMPL 0x0c
-#define RLL_CAUSE_SABM_MF 0x0d
-#define RLL_CAUSE_SABM_INFO_NOTALL 0x0e
-
-/* Chapter 9.3.26 */
-#define RSL_ERRCLS_NORMAL 0x00
-#define RSL_ERRCLS_RESOURCE_UNAVAIL 0x20
-#define RSL_ERRCLS_SERVICE_UNAVAIL 0x30
-#define RSL_ERRCLS_SERVICE_UNIMPL 0x40
-#define RSL_ERRCLS_INVAL_MSG 0x50
-#define RSL_ERRCLS_PROTO_ERROR 0x60
-#define RSL_ERRCLS_INTERWORKING 0x70
-
-/* normal event */
-#define RSL_ERR_RADIO_IF_FAIL 0x00
-#define RSL_ERR_RADIO_LINK_FAIL 0x01
-#define RSL_ERR_HANDOVER_ACC_FAIL 0x02
-#define RSL_ERR_TALKER_ACC_FAIL 0x03
-#define RSL_ERR_OM_INTERVENTION 0x07
-#define RSL_ERR_NORMAL_UNSPEC 0x0f
-#define RSL_ERR_T_MSRFPCI_EXP 0x18
-/* resource unavailable */
-#define RSL_ERR_EQUIPMENT_FAIL 0x20
-#define RSL_ERR_RR_UNAVAIL 0x21
-#define RSL_ERR_TERR_CH_FAIL 0x22
-#define RSL_ERR_CCCH_OVERLOAD 0x23
-#define RSL_ERR_ACCH_OVERLOAD 0x24
-#define RSL_ERR_PROCESSOR_OVERLOAD 0x25
-#define RSL_ERR_RES_UNAVAIL 0x2f
-/* service or option not available */
-#define RSL_ERR_TRANSC_UNAVAIL 0x30
-#define RSL_ERR_SERV_OPT_UNAVAIL 0x3f
-/* service or option not implemented */
-#define RSL_ERR_ENCR_UNIMPL 0x40
-#define RSL_ERR_SERV_OPT_UNIMPL 0x4f
-/* invalid message */
-#define RSL_ERR_RCH_ALR_ACTV_ALLOC 0x50
-#define RSL_ERR_INVALID_MESSAGE 0x5f
-/* protocol error */
-#define RSL_ERR_MSG_DISCR 0x60
-#define RSL_ERR_MSG_TYPE 0x61
-#define RSL_ERR_MSG_SEQ 0x62
-#define RSL_ERR_IE_ERROR 0x63
-#define RSL_ERR_MAND_IE_ERROR 0x64
-#define RSL_ERR_OPT_IE_ERROR 0x65
-#define RSL_ERR_IE_NONEXIST 0x66
-#define RSL_ERR_IE_LENGTH 0x67
-#define RSL_ERR_IE_CONTENT 0x68
-#define RSL_ERR_PROTO 0x6f
-/* interworking */
-#define RSL_ERR_INTERWORKING 0x7f
-
-/* Chapter 9.3.30 */
-#define RSL_SYSTEM_INFO_8 0x00
-#define RSL_SYSTEM_INFO_1 0x01
-#define RSL_SYSTEM_INFO_2 0x02
-#define RSL_SYSTEM_INFO_3 0x03
-#define RSL_SYSTEM_INFO_4 0x04
-#define RSL_SYSTEM_INFO_5 0x05
-#define RSL_SYSTEM_INFO_6 0x06
-#define RSL_SYSTEM_INFO_7 0x07
-#define RSL_SYSTEM_INFO_16 0x08
-#define RSL_SYSTEM_INFO_17 0x09
-#define RSL_SYSTEM_INFO_2bis 0x0a
-#define RSL_SYSTEM_INFO_2ter 0x0b
-#define RSL_SYSTEM_INFO_5bis 0x0d
-#define RSL_SYSTEM_INFO_5ter 0x0e
-#define RSL_SYSTEM_INFO_10 0x0f
-#define REL_EXT_MEAS_ORDER 0x47
-#define RSL_MEAS_INFO 0x48
-#define RSL_SYSTEM_INFO_13 0x28
-#define RSL_SYSTEM_INFO_2quater 0x29
-#define RSL_SYSTEM_INFO_9 0x2a
-#define RSL_SYSTEM_INFO_18 0x2b
-#define RSL_SYSTEM_INFO_19 0x2c
-#define RSL_SYSTEM_INFO_20 0x2d
-
-/* Chapter 9.3.40 */
-#define RSL_CHANNEED_ANY 0x00
-#define RSL_CHANNEED_SDCCH 0x01
-#define RSL_CHANNEED_TCH_F 0x02
-#define RSL_CHANNEED_TCH_ForH 0x03
-
-/* Chapter 3.3.2.3 Brocast control channel */
-/* CCCH-CONF, NC is not combined */
-#define RSL_BCCH_CCCH_CONF_1_NC 0x00
-#define RSL_BCCH_CCCH_CONF_1_C 0x01
-#define RSL_BCCH_CCCH_CONF_2_NC 0x02
-#define RSL_BCCH_CCCH_CONF_3_NC 0x04
-#define RSL_BCCH_CCCH_CONF_4_NC 0x06
-
-/* BS-PA-MFRMS */
-#define RSL_BS_PA_MFRMS_2 0x00
-#define RSL_BS_PA_MFRMS_3 0x01
-#define RSL_BS_PA_MFRMS_4 0x02
-#define RSL_BS_PA_MFRMS_5 0x03
-#define RSL_BS_PA_MFRMS_6 0x04
-#define RSL_BS_PA_MFRMS_7 0x05
-#define RSL_BS_PA_MFRMS_8 0x06
-#define RSL_BS_PA_MFRMS_9 0x07
-
-/* RSL_IE_IPAC_RTP_PAYLOAD[2] */
-enum rsl_ipac_rtp_payload {
- RSL_IPAC_RTP_GSM = 1,
- RSL_IPAC_RTP_EFR,
- RSL_IPAC_RTP_AMR,
- RSL_IPAC_RTP_CSD,
- RSL_IPAC_RTP_MUX,
-};
-
-/* RSL_IE_IPAC_SPEECH_MODE, lower four bits */
-enum rsl_ipac_speech_mode_s {
- RSL_IPAC_SPEECH_GSM_FR = 0, /* GSM FR (Type 1, FS) */
- RSL_IPAC_SPEECH_GSM_EFR = 1, /* GSM EFR (Type 2, FS) */
- RSL_IPAC_SPEECH_GSM_AMR_FR = 2, /* GSM AMR/FR (Type 3, FS) */
- RSL_IPAC_SPEECH_GSM_HR = 3, /* GSM HR (Type 1, HS) */
- RSL_IPAC_SPEECH_GSM_AMR_HR = 5, /* GSM AMR/hr (Type 3, HS) */
- RSL_IPAC_SPEECH_AS_RTP = 0xf, /* As specified by RTP Payload IE */
-};
-/* RSL_IE_IPAC_SPEECH_MODE, upper four bits */
-enum rsl_ipac_speech_mode_m {
- RSL_IPAC_SPEECH_M_RXTX = 0, /* Send and Receive */
- RSL_IPAC_SPEECH_M_RX = 1, /* Receive only */
- RSL_IPAC_SPEECH_M_TX = 2, /* Send only */
-};
-
-/* RSL_IE_IPAC_RTP_CSD_FMT, lower four bits */
-enum rsl_ipac_rtp_csd_format_d {
- RSL_IPAC_RTP_CSD_EXT_TRAU = 0,
- RSL_IPAC_RTP_CSD_NON_TRAU = 1,
- RSL_IPAC_RTP_CSD_TRAU_BTS = 2,
- RSL_IPAC_RTP_CSD_IWF_FREE = 3,
-};
-/* RSL_IE_IPAC_RTP_CSD_FMT, upper four bits */
-enum rsl_ipac_rtp_csd_format_ir {
- RSL_IPAC_RTP_CSD_IR_8k = 0,
- RSL_IPAC_RTP_CSD_IR_16k = 1,
- RSL_IPAC_RTP_CSD_IR_32k = 2,
- RSL_IPAC_RTP_CSD_IR_64k = 3,
-};
-
-/* Siemens vendor-specific RSL extensions */
-struct rsl_mrpci {
- uint8_t power_class:3,
- vgcs_capable:1,
- vbs_capable:1,
- gsm_phase:2;
-} __attribute__ ((packed));
-
-enum rsl_mrpci_pwrclass {
- RSL_MRPCI_PWRC_1 = 0,
- RSL_MRPCI_PWRC_2 = 1,
- RSL_MRPCI_PWRC_3 = 2,
- RSL_MRPCI_PWRC_4 = 3,
- RSL_MRPCI_PWRC_5 = 4,
-};
-enum rsl_mrpci_phase {
- RSL_MRPCI_PHASE_1 = 0,
- /* reserved */
- RSL_MRPCI_PHASE_2 = 2,
- RSL_MRPCI_PHASE_2PLUS = 3,
-};
-
-
-#endif /* PROTO_GSM_08_58_H */
diff --git a/libosmocore/include/osmocore/protocol/gsm_12_21.h b/libosmocore/include/osmocore/protocol/gsm_12_21.h
deleted file mode 100644
index 9cae45d..0000000
--- a/libosmocore/include/osmocore/protocol/gsm_12_21.h
+++ /dev/null
@@ -1,713 +0,0 @@
-#ifndef PROTO_GSM_12_21_H
-#define PROTO_GSM_12_21_H
-
-/* GSM Network Management messages on the A-bis interface
- * 3GPP TS 12.21 version 8.0.0 Release 1999 / ETSI TS 100 623 V8.0.0 */
-
-/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <osmocore/tlv.h>
-
-/* generic header in front of every OML message according to TS 08.59 */
-struct abis_om_hdr {
- uint8_t mdisc;
- uint8_t placement;
- uint8_t sequence;
- uint8_t length;
- uint8_t data[0];
-} __attribute__ ((packed));
-
-#define ABIS_OM_MDISC_FOM 0x80
-#define ABIS_OM_MDISC_MMI 0x40
-#define ABIS_OM_MDISC_TRAU 0x20
-#define ABIS_OM_MDISC_MANUF 0x10
-#define ABIS_OM_PLACEMENT_ONLY 0x80
-#define ABIS_OM_PLACEMENT_FIRST 0x40
-#define ABIS_OM_PLACEMENT_MIDDLE 0x20
-#define ABIS_OM_PLACEMENT_LAST 0x10
-
-struct abis_om_obj_inst {
- uint8_t bts_nr;
- uint8_t trx_nr;
- uint8_t ts_nr;
-} __attribute__ ((packed));
-
-struct abis_om_fom_hdr {
- uint8_t msg_type;
- uint8_t obj_class;
- struct abis_om_obj_inst obj_inst;
- uint8_t data[0];
-} __attribute__ ((packed));
-
-#define ABIS_OM_FOM_HDR_SIZE (sizeof(struct abis_om_hdr) + sizeof(struct abis_om_fom_hdr))
-
-/* Section 9.1: Message Types */
-enum abis_nm_msgtype {
- /* SW Download Management Messages */
- NM_MT_LOAD_INIT = 0x01,
- NM_MT_LOAD_INIT_ACK,
- NM_MT_LOAD_INIT_NACK,
- NM_MT_LOAD_SEG,
- NM_MT_LOAD_SEG_ACK,
- NM_MT_LOAD_ABORT,
- NM_MT_LOAD_END,
- NM_MT_LOAD_END_ACK,
- NM_MT_LOAD_END_NACK,
- NM_MT_SW_ACT_REQ, /* BTS->BSC */
- NM_MT_SW_ACT_REQ_ACK,
- NM_MT_SW_ACT_REQ_NACK,
- NM_MT_ACTIVATE_SW, /* BSC->BTS */
- NM_MT_ACTIVATE_SW_ACK,
- NM_MT_ACTIVATE_SW_NACK,
- NM_MT_SW_ACTIVATED_REP, /* 0x10 */
- /* A-bis Interface Management Messages */
- NM_MT_ESTABLISH_TEI = 0x21,
- NM_MT_ESTABLISH_TEI_ACK,
- NM_MT_ESTABLISH_TEI_NACK,
- NM_MT_CONN_TERR_SIGN,
- NM_MT_CONN_TERR_SIGN_ACK,
- NM_MT_CONN_TERR_SIGN_NACK,
- NM_MT_DISC_TERR_SIGN,
- NM_MT_DISC_TERR_SIGN_ACK,
- NM_MT_DISC_TERR_SIGN_NACK,
- NM_MT_CONN_TERR_TRAF,
- NM_MT_CONN_TERR_TRAF_ACK,
- NM_MT_CONN_TERR_TRAF_NACK,
- NM_MT_DISC_TERR_TRAF,
- NM_MT_DISC_TERR_TRAF_ACK,
- NM_MT_DISC_TERR_TRAF_NACK,
- /* Transmission Management Messages */
- NM_MT_CONN_MDROP_LINK = 0x31,
- NM_MT_CONN_MDROP_LINK_ACK,
- NM_MT_CONN_MDROP_LINK_NACK,
- NM_MT_DISC_MDROP_LINK,
- NM_MT_DISC_MDROP_LINK_ACK,
- NM_MT_DISC_MDROP_LINK_NACK,
- /* Air Interface Management Messages */
- NM_MT_SET_BTS_ATTR = 0x41,
- NM_MT_SET_BTS_ATTR_ACK,
- NM_MT_SET_BTS_ATTR_NACK,
- NM_MT_SET_RADIO_ATTR,
- NM_MT_SET_RADIO_ATTR_ACK,
- NM_MT_SET_RADIO_ATTR_NACK,
- NM_MT_SET_CHAN_ATTR,
- NM_MT_SET_CHAN_ATTR_ACK,
- NM_MT_SET_CHAN_ATTR_NACK,
- /* Test Management Messages */
- NM_MT_PERF_TEST = 0x51,
- NM_MT_PERF_TEST_ACK,
- NM_MT_PERF_TEST_NACK,
- NM_MT_TEST_REP,
- NM_MT_SEND_TEST_REP,
- NM_MT_SEND_TEST_REP_ACK,
- NM_MT_SEND_TEST_REP_NACK,
- NM_MT_STOP_TEST,
- NM_MT_STOP_TEST_ACK,
- NM_MT_STOP_TEST_NACK,
- /* State Management and Event Report Messages */
- NM_MT_STATECHG_EVENT_REP = 0x61,
- NM_MT_FAILURE_EVENT_REP,
- NM_MT_STOP_EVENT_REP,
- NM_MT_STOP_EVENT_REP_ACK,
- NM_MT_STOP_EVENT_REP_NACK,
- NM_MT_REST_EVENT_REP,
- NM_MT_REST_EVENT_REP_ACK,
- NM_MT_REST_EVENT_REP_NACK,
- NM_MT_CHG_ADM_STATE,
- NM_MT_CHG_ADM_STATE_ACK,
- NM_MT_CHG_ADM_STATE_NACK,
- NM_MT_CHG_ADM_STATE_REQ,
- NM_MT_CHG_ADM_STATE_REQ_ACK,
- NM_MT_CHG_ADM_STATE_REQ_NACK,
- NM_MT_REP_OUTST_ALARMS = 0x93,
- NM_MT_REP_OUTST_ALARMS_ACK,
- NM_MT_REP_OUTST_ALARMS_NACK,
- /* Equipment Management Messages */
- NM_MT_CHANGEOVER = 0x71,
- NM_MT_CHANGEOVER_ACK,
- NM_MT_CHANGEOVER_NACK,
- NM_MT_OPSTART,
- NM_MT_OPSTART_ACK,
- NM_MT_OPSTART_NACK,
- NM_MT_REINIT,
- NM_MT_REINIT_ACK,
- NM_MT_REINIT_NACK,
- NM_MT_SET_SITE_OUT, /* BS11: get alarm ?!? */
- NM_MT_SET_SITE_OUT_ACK,
- NM_MT_SET_SITE_OUT_NACK,
- NM_MT_CHG_HW_CONF = 0x90,
- NM_MT_CHG_HW_CONF_ACK,
- NM_MT_CHG_HW_CONF_NACK,
- /* Measurement Management Messages */
- NM_MT_MEAS_RES_REQ = 0x8a,
- NM_MT_MEAS_RES_RESP,
- NM_MT_STOP_MEAS,
- NM_MT_START_MEAS,
- /* Other Messages */
- NM_MT_GET_ATTR = 0x81,
- NM_MT_GET_ATTR_RESP,
- NM_MT_GET_ATTR_NACK,
- NM_MT_SET_ALARM_THRES,
- NM_MT_SET_ALARM_THRES_ACK,
- NM_MT_SET_ALARM_THRES_NACK,
-};
-
-enum abis_nm_msgtype_bs11 {
- NM_MT_BS11_RESET_RESOURCE = 0x74,
-
- NM_MT_BS11_BEGIN_DB_TX = 0xa3,
- NM_MT_BS11_BEGIN_DB_TX_ACK,
- NM_MT_BS11_BEGIN_DB_TX_NACK,
- NM_MT_BS11_END_DB_TX = 0xa6,
- NM_MT_BS11_END_DB_TX_ACK,
- NM_MT_BS11_END_DB_TX_NACK,
- NM_MT_BS11_CREATE_OBJ = 0xa9,
- NM_MT_BS11_CREATE_OBJ_ACK,
- NM_MT_BS11_CREATE_OBJ_NACK,
- NM_MT_BS11_DELETE_OBJ = 0xac,
- NM_MT_BS11_DELETE_OBJ_ACK,
- NM_MT_BS11_DELETE_OBJ_NACK,
-
- NM_MT_BS11_SET_ATTR = 0xd0,
- NM_MT_BS11_SET_ATTR_ACK,
- NM_MT_BS11_SET_ATTR_NACK,
- NM_MT_BS11_LMT_SESSION = 0xdc,
-
- NM_MT_BS11_GET_STATE = 0xe3,
- NM_MT_BS11_GET_STATE_ACK,
- NM_MT_BS11_LMT_LOGON = 0xe5,
- NM_MT_BS11_LMT_LOGON_ACK,
- NM_MT_BS11_RESTART = 0xe7,
- NM_MT_BS11_RESTART_ACK,
- NM_MT_BS11_DISCONNECT = 0xe9,
- NM_MT_BS11_DISCONNECT_ACK,
- NM_MT_BS11_LMT_LOGOFF = 0xec,
- NM_MT_BS11_LMT_LOGOFF_ACK,
- NM_MT_BS11_RECONNECT = 0xf1,
- NM_MT_BS11_RECONNECT_ACK,
-};
-
-enum abis_nm_msgtype_ipacc {
- NM_MT_IPACC_RESTART = 0x87,
- NM_MT_IPACC_RESTART_ACK,
- NM_MT_IPACC_RESTART_NACK,
- NM_MT_IPACC_RSL_CONNECT = 0xe0,
- NM_MT_IPACC_RSL_CONNECT_ACK,
- NM_MT_IPACC_RSL_CONNECT_NACK,
- NM_MT_IPACC_RSL_DISCONNECT = 0xe3,
- NM_MT_IPACC_RSL_DISCONNECT_ACK,
- NM_MT_IPACC_RSL_DISCONNECT_NACK,
- NM_MT_IPACC_CONN_TRAF = 0xe6,
- NM_MT_IPACC_CONN_TRAF_ACK,
- NM_MT_IPACC_CONN_TRAF_NACK,
- NM_MT_IPACC_DEF_BOOT_SW = 0xec,
- NM_MT_IPACC_DEF_BOOT_SW_ACK,
- MN_MT_IPACC_DEF_BOOT_SW_NACK,
- NM_MT_IPACC_SET_NVATTR = 0xef,
- NM_MT_IPACC_SET_NVATTR_ACK,
- NM_MT_IPACC_SET_NVATTR_NACK,
- NM_MT_IPACC_GET_NVATTR = 0xf2,
- NM_MT_IPACC_GET_NVATTR_ACK,
- NM_MT_IPACC_GET_NVATTR_NACK,
- NM_MT_IPACC_SET_ATTR = 0xf5,
- NM_MT_IPACC_SET_ATTR_ACK,
- NM_MT_IPACC_SET_ATTR_NACK,
-};
-
-enum abis_nm_bs11_cell_alloc {
- NM_BS11_CANR_GSM = 0x00,
- NM_BS11_CANR_DCS1800 = 0x01,
-};
-
-/* Section 9.2: Object Class */
-enum abis_nm_obj_class {
- NM_OC_SITE_MANAGER = 0x00,
- NM_OC_BTS,
- NM_OC_RADIO_CARRIER,
- NM_OC_CHANNEL,
- NM_OC_BASEB_TRANSC,
- /* RFU: 05-FE */
-
- NM_OC_IPAC_E1_TRUNK = 0x0e,
- NM_OC_IPAC_E1_PORT = 0x0f,
- NM_OC_IPAC_E1_CHAN = 0x10,
- NM_OC_IPAC_CLK_MODULE = 0x22,
-
- NM_OC_BS11_ADJC = 0xa0,
- NM_OC_BS11_HANDOVER = 0xa1,
- NM_OC_BS11_PWR_CTRL = 0xa2,
- NM_OC_BS11_BTSE = 0xa3, /* LMT? */
- NM_OC_BS11_RACK = 0xa4,
- NM_OC_BS11 = 0xa5, /* 01: ALCO */
- NM_OC_BS11_TEST = 0xa6,
- NM_OC_BS11_ENVABTSE = 0xa8,
- NM_OC_BS11_BPORT = 0xa9,
-
- NM_OC_GPRS_NSE = 0xf0,
- NM_OC_GPRS_CELL = 0xf1,
- NM_OC_GPRS_NSVC = 0xf2,
-
- NM_OC_NULL = 0xff,
-};
-
-/* Section 9.4: Attributes */
-enum abis_nm_attr {
- NM_ATT_ABIS_CHANNEL = 0x01,
- NM_ATT_ADD_INFO,
- NM_ATT_ADD_TEXT,
- NM_ATT_ADM_STATE,
- NM_ATT_ARFCN_LIST,
- NM_ATT_AUTON_REPORT,
- NM_ATT_AVAIL_STATUS,
- NM_ATT_BCCH_ARFCN,
- NM_ATT_BSIC,
- NM_ATT_BTS_AIR_TIMER,
- NM_ATT_CCCH_L_I_P,
- NM_ATT_CCCH_L_T,
- NM_ATT_CHAN_COMB,
- NM_ATT_CONN_FAIL_CRIT,
- NM_ATT_DEST,
- /* res */
- NM_ATT_EVENT_TYPE = 0x11, /* BS11: file data ?!? */
- NM_ATT_FILE_ID,
- NM_ATT_FILE_VERSION,
- NM_ATT_GSM_TIME,
- NM_ATT_HSN,
- NM_ATT_HW_CONFIG,
- NM_ATT_HW_DESC,
- NM_ATT_INTAVE_PARAM,
- NM_ATT_INTERF_BOUND,
- NM_ATT_LIST_REQ_ATTR,
- NM_ATT_MAIO,
- NM_ATT_MANUF_STATE,
- NM_ATT_MANUF_THRESH,
- NM_ATT_MANUF_ID,
- NM_ATT_MAX_TA,
- NM_ATT_MDROP_LINK, /* 0x20 */
- NM_ATT_MDROP_NEXT,
- NM_ATT_NACK_CAUSES,
- NM_ATT_NY1,
- NM_ATT_OPER_STATE,
- NM_ATT_OVERL_PERIOD,
- NM_ATT_PHYS_CONF,
- NM_ATT_POWER_CLASS,
- NM_ATT_POWER_THRESH,
- NM_ATT_PROB_CAUSE,
- NM_ATT_RACH_B_THRESH,
- NM_ATT_LDAVG_SLOTS,
- NM_ATT_RAD_SUBC,
- NM_ATT_RF_MAXPOWR_R,
- NM_ATT_SITE_INPUTS,
- NM_ATT_SITE_OUTPUTS,
- NM_ATT_SOURCE, /* 0x30 */
- NM_ATT_SPEC_PROB,
- NM_ATT_START_TIME,
- NM_ATT_T200,
- NM_ATT_TEI,
- NM_ATT_TEST_DUR,
- NM_ATT_TEST_NO,
- NM_ATT_TEST_REPORT,
- NM_ATT_VSWR_THRESH,
- NM_ATT_WINDOW_SIZE,
- /* Res */
- NM_ATT_BS11_RSSI_OFFS = 0x3d,
- NM_ATT_BS11_TXPWR = 0x3e,
- NM_ATT_BS11_DIVERSITY = 0x3f,
- /* Res */
- NM_ATT_TSC = 0x40,
- NM_ATT_SW_CONFIG,
- NM_ATT_SW_DESCR,
- NM_ATT_SEVERITY,
- NM_ATT_GET_ARI,
- NM_ATT_HW_CONF_CHG,
- NM_ATT_OUTST_ALARM,
- NM_ATT_FILE_DATA,
- NM_ATT_MEAS_RES,
- NM_ATT_MEAS_TYPE,
-
- NM_ATT_BS11_ESN_FW_CODE_NO = 0x4c,
- NM_ATT_BS11_ESN_HW_CODE_NO = 0x4f,
-
- NM_ATT_BS11_ESN_PCB_SERIAL = 0x55,
- NM_ATT_BS11_EXCESSIVE_DISTANCE = 0x58,
-
- NM_ATT_BS11_ALL_TEST_CATG = 0x60,
- NM_ATT_BS11_BTSLS_HOPPING,
- NM_ATT_BS11_CELL_ALLOC_NR,
- NM_ATT_BS11_CELL_GLOBAL_ID,
- NM_ATT_BS11_ENA_INTERF_CLASS = 0x66,
- NM_ATT_BS11_ENA_INT_INTEC_HANDO = 0x67,
- NM_ATT_BS11_ENA_INT_INTRC_HANDO = 0x68,
- NM_ATT_BS11_ENA_MS_PWR_CTRL = 0x69,
- NM_ATT_BS11_ENA_PWR_BDGT_HO = 0x6a,
- NM_ATT_BS11_ENA_PWR_CTRL_RLFW = 0x6b,
- NM_ATT_BS11_ENA_RXLEV_HO = 0x6c,
- NM_ATT_BS11_ENA_RXQUAL_HO = 0x6d,
- NM_ATT_BS11_FACCH_QUAL = 0x6e,
-
- NM_ATT_IPACC_DST_IP = 0x80,
- NM_ATT_IPACC_DST_IP_PORT = 0x81,
- NM_ATT_IPACC_SSRC = 0x82,
- NM_ATT_IPACC_RTP_PAYLD_TYPE = 0x83,
- NM_ATT_IPACC_BASEB_ID = 0x84,
- NM_ATT_IPACC_STREAM_ID = 0x85,
- NM_ATT_IPACC_NV_FLAGS = 0x86,
- NM_ATT_IPACC_FREQ_CTRL = 0x87,
- NM_ATT_IPACC_PRIM_OML_CFG = 0x88,
- NM_ATT_IPACC_SEC_OML_CFG = 0x89,
- NM_ATT_IPACC_IP_IF_CFG = 0x8a, /* IP interface */
- NM_ATT_IPACC_IP_GW_CFG = 0x8b, /* IP gateway */
- NM_ATT_IPACC_IN_SERV_TIME = 0x8c,
- NM_ATT_IPACC_TRX_BTS_ASS = 0x8d,
- NM_ATT_IPACC_LOCATION = 0x8e, /* string describing location */
- NM_ATT_IPACC_PAGING_CFG = 0x8f,
- NM_ATT_IPACC_FILE_DATA = 0x90,
- NM_ATT_IPACC_UNIT_ID = 0x91, /* Site/BTS/TRX */
- NM_ATT_IPACC_PARENT_UNIT_ID = 0x92,
- NM_ATT_IPACC_UNIT_NAME = 0x93, /* default: nbts-<mac-as-string> */
- NM_ATT_IPACC_SNMP_CFG = 0x94,
- NM_ATT_IPACC_PRIM_OML_CFG_LIST = 0x95,
- NM_ATT_IPACC_PRIM_OML_FB_TOUT = 0x96,
- NM_ATT_IPACC_CUR_SW_CFG = 0x97,
- NM_ATT_IPACC_TIMING_BUS = 0x98,
- NM_ATT_IPACC_CGI = 0x99,
- NM_ATT_IPACC_RAC = 0x9a,
- NM_ATT_IPACC_OBJ_VERSION = 0x9b,
- NM_ATT_IPACC_GPRS_PAGING_CFG = 0x9c,
- NM_ATT_IPACC_NSEI = 0x9d,
- NM_ATT_IPACC_BVCI = 0x9e,
- NM_ATT_IPACC_NSVCI = 0x9f,
- NM_ATT_IPACC_NS_CFG = 0xa0,
- NM_ATT_IPACC_BSSGP_CFG = 0xa1,
- NM_ATT_IPACC_NS_LINK_CFG = 0xa2,
- NM_ATT_IPACC_RLC_CFG = 0xa3,
- NM_ATT_IPACC_ALM_THRESH_LIST = 0xa4,
- NM_ATT_IPACC_MONIT_VAL_LIST = 0xa5,
- NM_ATT_IPACC_TIB_CONTROL = 0xa6,
- NM_ATT_IPACC_SUPP_FEATURES = 0xa7,
- NM_ATT_IPACC_CODING_SCHEMES = 0xa8,
- NM_ATT_IPACC_RLC_CFG_2 = 0xa9,
- NM_ATT_IPACC_HEARTB_TOUT = 0xaa,
- NM_ATT_IPACC_UPTIME = 0xab,
- NM_ATT_IPACC_RLC_CFG_3 = 0xac,
- NM_ATT_IPACC_SSL_CFG = 0xad,
- NM_ATT_IPACC_SEC_POSSIBLE = 0xae,
- NM_ATT_IPACC_IML_SSL_STATE = 0xaf,
- NM_ATT_IPACC_REVOC_DATE = 0xb0,
-
-
- NM_ATT_BS11_RF_RES_IND_PER = 0x8f,
-
- NM_ATT_BS11_RX_LEV_MIN_CELL = 0x90,
- NM_ATT_BS11_ABIS_EXT_TIME = 0x91,
- NM_ATT_BS11_TIMER_HO_REQUEST = 0x92,
- NM_ATT_BS11_TIMER_NCELL = 0x93,
- NM_ATT_BS11_TSYNC = 0x94,
- NM_ATT_BS11_TTRAU = 0x95,
- NM_ATT_BS11_EMRG_CFG_MEMBER = 0x9b,
- NM_ATT_BS11_TRX_AREA = 0x9f,
-
- NM_ATT_BS11_BCCH_RECONF = 0xd7,
- NM_ATT_BS11_BIT_ERR_THESH = 0xa0,
- NM_ATT_BS11_BOOT_SW_VERS = 0xa1,
- NM_ATT_BS11_CCLK_ACCURACY = 0xa3,
- NM_ATT_BS11_CCLK_TYPE = 0xa4,
- NM_ATT_BS11_INP_IMPEDANCE = 0xaa,
- NM_ATT_BS11_L1_PROT_TYPE = 0xab,
- NM_ATT_BS11_LINE_CFG = 0xac,
- NM_ATT_BS11_LI_PORT_1 = 0xad,
- NM_ATT_BS11_LI_PORT_2 = 0xae,
-
- NM_ATT_BS11_L1_REM_ALM_TYPE = 0xb0,
- NM_ATT_BS11_SW_LOAD_INTENDED = 0xbb,
- NM_ATT_BS11_SW_LOAD_SAFETY = 0xbc,
- NM_ATT_BS11_SW_LOAD_STORED = 0xbd,
-
- NM_ATT_BS11_VENDOR_NAME = 0xc1,
- NM_ATT_BS11_HOPPING_MODE = 0xc5,
- NM_ATT_BS11_LMT_LOGON_SESSION = 0xc6,
- NM_ATT_BS11_LMT_LOGIN_TIME = 0xc7,
- NM_ATT_BS11_LMT_USER_ACC_LEV = 0xc8,
- NM_ATT_BS11_LMT_USER_NAME = 0xc9,
-
- NM_ATT_BS11_L1_CONTROL_TS = 0xd8,
- NM_ATT_BS11_RADIO_MEAS_GRAN = 0xdc, /* in SACCH multiframes */
- NM_ATT_BS11_RADIO_MEAS_REP = 0xdd,
-
- NM_ATT_BS11_SH_LAPD_INT_TIMER = 0xe8,
-
- NM_ATT_BS11_BTS_STATE = 0xf0,
- NM_ATT_BS11_E1_STATE = 0xf1,
- NM_ATT_BS11_PLL = 0xf2,
- NM_ATT_BS11_RX_OFFSET = 0xf3,
- NM_ATT_BS11_ANT_TYPE = 0xf4,
- NM_ATT_BS11_PLL_MODE = 0xfc,
- NM_ATT_BS11_PASSWORD = 0xfd,
-};
-#define NM_ATT_BS11_FILE_DATA NM_ATT_EVENT_TYPE
-
-/* Section 9.4.4: Administrative State */
-enum abis_nm_adm_state {
- NM_STATE_LOCKED = 0x01,
- NM_STATE_UNLOCKED = 0x02,
- NM_STATE_SHUTDOWN = 0x03,
- NM_STATE_NULL = 0xff,
-};
-
-/* Section 9.4.7: Administrative State */
-enum abis_nm_avail_state {
- NM_AVSTATE_IN_TEST = 1,
- NM_AVSTATE_POWER_OFF = 2,
- NM_AVSTATE_OFF_LINE = 3,
- NM_AVSTATE_DEPENDENCY = 5,
- NM_AVSTATE_DEGRADED = 6,
- NM_AVSTATE_NOT_INSTALLED= 7,
- NM_AVSTATE_OK = 0xff,
-};
-
-enum abis_nm_op_state {
- NM_OPSTATE_DISABLED = 1,
- NM_OPSTATE_ENABLED = 2,
- NM_OPSTATE_NULL = 0xff,
-};
-
-/* Section 9.4.13: Channel Combination */
-enum abis_nm_chan_comb {
- NM_CHANC_TCHFull = 0x00, /* TCH/F + TCH/H + SACCH/TF */
- NM_CHANC_TCHHalf = 0x01, /* TCH/H(0,1) + FACCH/H(0,1) +
- SACCH/TH(0,1) */
- NM_CHANC_TCHHalf2 = 0x02, /* TCH/H(0) + FACCH/H(0) + SACCH/TH(0) +
- TCH/H(1) */
- NM_CHANC_SDCCH = 0x03, /* SDCCH/8 + SACCH/8 */
- NM_CHANC_mainBCCH = 0x04, /* FCCH + SCH + BCCH + CCCH */
- NM_CHANC_BCCHComb = 0x05, /* FCCH + SCH + BCCH + CCCH + SDCCH/4 +
- SACCH/C4 */
- NM_CHANC_BCCH = 0x06, /* BCCH + CCCH */
- NM_CHANC_BCCH_CBCH = 0x07, /* CHANC_BCCHComb + CBCH */
- NM_CHANC_SDCCH_CBCH = 0x08, /* CHANC_SDCCH8 + CBCH */
- /* ip.access */
- NM_CHANC_IPAC_bPDCH = 0x0b, /* PBCCH + PCCCH + PDTCH/F + PACCH/F +
- PTCCH/F */
- NM_CHANC_IPAC_cPDCH = 0x0c, /* PBCCH + PDTCH/F + PACCH/F + PTCCH/F */
- NM_CHANC_IPAC_PDCH = 0x0d, /* PDTCH/F + PACCH/F + PTCCH/F */
- NM_CHANC_IPAC_TCHFull_PDCH = 0x80,
- NM_CHANC_IPAC_TCHFull_TCHHalf = 0x81,
-};
-
-/* Section 9.4.16: Event Type */
-enum abis_nm_event_type {
- NM_EVT_COMM_FAIL = 0x00,
- NM_EVT_QOS_FAIL = 0x01,
- NM_EVT_PROC_FAIL = 0x02,
- NM_EVT_EQUIP_FAIL = 0x03,
- NM_EVT_ENV_FAIL = 0x04,
-};
-
-/* Section: 9.4.63: Perceived Severity */
-enum abis_nm_severity {
- NM_SEVER_CEASED = 0x00,
- NM_SEVER_CRITICAL = 0x01,
- NM_SEVER_MAJOR = 0x02,
- NM_SEVER_MINOR = 0x03,
- NM_SEVER_WARNING = 0x04,
- NM_SEVER_INDETERMINATE = 0x05,
-};
-
-/* Section 9.4.43: Probable Cause Type */
-enum abis_nm_pcause_type {
- NM_PCAUSE_T_X721 = 0x01,
- NM_PCAUSE_T_GSM = 0x02,
- NM_PCAUSE_T_MANUF = 0x03,
-};
-
-/* Section 9.4.36: NACK Causes */
-enum abis_nm_nack_cause {
- /* General Nack Causes */
- NM_NACK_INCORR_STRUCT = 0x01,
- NM_NACK_MSGTYPE_INVAL = 0x02,
- NM_NACK_OBJCLASS_INVAL = 0x05,
- NM_NACK_OBJCLASS_NOTSUPP = 0x06,
- NM_NACK_BTSNR_UNKN = 0x07,
- NM_NACK_TRXNR_UNKN = 0x08,
- NM_NACK_OBJINST_UNKN = 0x09,
- NM_NACK_ATTRID_INVAL = 0x0c,
- NM_NACK_ATTRID_NOTSUPP = 0x0d,
- NM_NACK_PARAM_RANGE = 0x0e,
- NM_NACK_ATTRLIST_INCONSISTENT = 0x0f,
- NM_NACK_SPEC_IMPL_NOTSUPP = 0x10,
- NM_NACK_CANT_PERFORM = 0x11,
- /* Specific Nack Causes */
- NM_NACK_RES_NOTIMPL = 0x19,
- NM_NACK_RES_NOTAVAIL = 0x1a,
- NM_NACK_FREQ_NOTAVAIL = 0x1b,
- NM_NACK_TEST_NOTSUPP = 0x1c,
- NM_NACK_CAPACITY_RESTR = 0x1d,
- NM_NACK_PHYSCFG_NOTPERFORM = 0x1e,
- NM_NACK_TEST_NOTINIT = 0x1f,
- NM_NACK_PHYSCFG_NOTRESTORE = 0x20,
- NM_NACK_TEST_NOSUCH = 0x21,
- NM_NACK_TEST_NOSTOP = 0x22,
- NM_NACK_MSGINCONSIST_PHYSCFG = 0x23,
- NM_NACK_FILE_INCOMPLETE = 0x25,
- NM_NACK_FILE_NOTAVAIL = 0x26,
- NM_NACK_FILE_NOTACTIVATE = 0x27,
- NM_NACK_REQ_NOT_GRANT = 0x28,
- NM_NACK_WAIT = 0x29,
- NM_NACK_NOTH_REPORT_EXIST = 0x2a,
- NM_NACK_MEAS_NOTSUPP = 0x2b,
- NM_NACK_MEAS_NOTSTART = 0x2c,
-};
-
-/* Section 9.4.1 */
-struct abis_nm_channel {
- uint8_t attrib;
- uint8_t bts_port;
- uint8_t timeslot;
- uint8_t subslot;
-} __attribute__ ((packed));
-
-/* Siemens BS-11 specific objects in the SienemsHW (0xA5) object class */
-enum abis_bs11_objtype {
- BS11_OBJ_ALCO = 0x01,
- BS11_OBJ_BBSIG = 0x02, /* obj_class: 0,1 */
- BS11_OBJ_TRX1 = 0x03, /* only DEACTIVATE TRX1 */
- BS11_OBJ_CCLK = 0x04,
- BS11_OBJ_GPSU = 0x06,
- BS11_OBJ_LI = 0x07,
- BS11_OBJ_PA = 0x09, /* obj_class: 0, 1*/
-};
-
-enum abis_bs11_trx_power {
- BS11_TRX_POWER_GSM_2W = 0x06,
- BS11_TRX_POWER_GSM_250mW= 0x07,
- BS11_TRX_POWER_GSM_80mW = 0x08,
- BS11_TRX_POWER_GSM_30mW = 0x09,
- BS11_TRX_POWER_DCS_3W = 0x0a,
- BS11_TRX_POWER_DCS_1W6 = 0x0b,
- BS11_TRX_POWER_DCS_500mW= 0x0c,
- BS11_TRX_POWER_DCS_160mW= 0x0d,
-};
-
-enum abis_bs11_li_pll_mode {
- BS11_LI_PLL_LOCKED = 2,
- BS11_LI_PLL_STANDALONE = 3,
-};
-
-enum abis_bs11_line_cfg {
- BS11_LINE_CFG_STAR = 0x00,
- BS11_LINE_CFG_MULTIDROP = 0x01,
- BS11_LINE_CFG_LOOP = 0x02,
-};
-
-enum abis_bs11_phase {
- BS11_STATE_SOFTWARE_RQD = 0x01,
- BS11_STATE_LOAD_SMU_INTENDED = 0x11,
- BS11_STATE_LOAD_SMU_SAFETY = 0x21,
- BS11_STATE_LOAD_FAILED = 0x31,
- BS11_STATE_LOAD_DIAGNOSTIC = 0x41,
- BS11_STATE_WARM_UP = 0x51,
- BS11_STATE_WARM_UP_2 = 0x52,
- BS11_STATE_WAIT_MIN_CFG = 0x62,
- BS11_STATE_MAINTENANCE = 0x72,
- BS11_STATE_LOAD_MBCCU = 0x92,
- BS11_STATE_WAIT_MIN_CFG_2 = 0xA2,
- BS11_STATE_NORMAL = 0x03,
- BS11_STATE_ABIS_LOAD = 0x13,
-};
-
-enum abis_nm_ipacc_test_no {
- NM_IPACC_TESTNO_RLOOP_ANT = 0x01,
- NM_IPACC_TESTNO_RLOOP_XCVR = 0x02,
- NM_IPACC_TESTNO_FUNC_OBJ = 0x03,
- NM_IPACC_TESTNO_CHAN_USAGE = 0x40,
- NM_IPACC_TESTNO_BCCH_CHAN_USAGE = 0x41,
- NM_IPACC_TESTNO_FREQ_SYNC = 0x42,
- NM_IPACC_TESTNO_BCCH_INFO = 0x43,
- NM_IPACC_TESTNO_TX_BEACON = 0x44,
- NM_IPACC_TESTNO_SYSINFO_MONITOR = 0x45,
- NM_IPACC_TESTNO_BCCCH_MONITOR = 0x46,
-};
-
-/* first byte after length inside NM_ATT_TEST_REPORT */
-enum abis_nm_ipacc_test_res {
- NM_IPACC_TESTRES_SUCCESS = 0,
- NM_IPACC_TESTRES_TIMEOUT = 1,
- NM_IPACC_TESTRES_NO_CHANS = 2,
- NM_IPACC_TESTRES_PARTIAL = 3,
- NM_IPACC_TESTRES_STOPPED = 4,
-};
-
-/* internal IE inside NM_ATT_TEST_REPORT */
-enum abis_nm_ipacc_testres_ie {
- NM_IPACC_TR_IE_FREQ_ERR_LIST = 3,
- NM_IPACC_TR_IE_CHAN_USAGE = 4,
- NM_IPACC_TR_IE_BCCH_INFO = 6,
- NM_IPACC_TR_IE_RESULT_DETAILS = 8,
- NM_IPACC_TR_IE_FREQ_ERR = 18,
-};
-
-enum ipac_eie {
- NM_IPAC_EIE_ARFCN_WHITE = 0x01,
- NM_IPAC_EIE_ARFCH_BLACK = 0x02,
- NM_IPAC_EIE_FREQ_ERR_LIST = 0x03,
- NM_IPAC_EIE_CHAN_USE_LIST = 0x04,
- NM_IPAC_EIE_BCCH_INFO_TYPE = 0x05,
- NM_IPAC_EIE_BCCH_INFO = 0x06,
- NM_IPAC_EIE_CONFIG = 0x07,
- NM_IPAC_EIE_RES_DETAILS = 0x08,
- NM_IPAC_EIE_RXLEV_THRESH = 0x09,
- NM_IPAC_EIE_FREQ_SYNC_OPTS = 0x0a,
- NM_IPAC_EIE_MAC_ADDR = 0x0b,
- NM_IPAC_EIE_HW_SW_COMPAT_NR = 0x0c,
- NM_IPAC_EIE_MANUF_SER_NR = 0x0d,
- NM_IPAC_EIE_OEM_ID = 0x0e,
- NM_IPAC_EIE_DATE_TIME_MANUF = 0x0f,
- NM_IPAC_EIE_DATE_TIME_CALIB = 0x10,
- NM_IPAC_EIE_BEACON_INFO = 0x11,
- NM_IPAC_EIE_FREQ_ERR = 0x12,
- /* FIXME */
- NM_IPAC_EIE_FREQ_BANDS = 0x1c,
- NM_IPAC_EIE_MAX_TA = 0x1d,
- NM_IPAC_EIE_CIPH_ALGOS = 0x1e,
- NM_IPAC_EIE_CHAN_TYPES = 0x1f,
- NM_IPAC_EIE_CHAN_MODES = 0x20,
- NM_IPAC_EIE_GPRS_CODING = 0x21,
- NM_IPAC_EIE_RTP_FEATURES = 0x22,
- NM_IPAC_EIE_RSL_FEATURES = 0x23,
- NM_IPAC_EIE_BTS_HW_CLASS = 0x24,
- NM_IPAC_EIE_BTS_ID = 0x25,
-};
-
-enum ipac_bcch_info_type {
- IPAC_BINF_RXLEV = (1 << 8),
- IPAC_BINF_RXQUAL = (1 << 9),
- IPAC_BINF_FREQ_ERR_QUAL = (1 << 10),
- IPAC_BINF_FRAME_OFFSET = (1 << 11),
- IPAC_BINF_FRAME_NR_OFFSET = (1 << 12),
- IPAC_BINF_BSIC = (1 << 13),
- IPAC_BINF_CGI = (1 << 14),
- IPAC_BINF_NEIGH_BA_SI2 = (1 << 15),
- IPAC_BINF_NEIGH_BA_SI2bis = (1 << 0),
- IPAC_BINF_NEIGH_BA_SI2ter = (1 << 1),
- IPAC_BINF_CELL_ALLOC = (1 << 2),
-};
-
-#endif /* PROTO_GSM_12_21_H */
diff --git a/libosmocore/include/osmocore/rate_ctr.h b/libosmocore/include/osmocore/rate_ctr.h
deleted file mode 100644
index 88c9de5..0000000
--- a/libosmocore/include/osmocore/rate_ctr.h
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifndef _RATE_CTR_H
-#define _RATE_CTR_H
-
-#include <stdint.h>
-
-#include <osmocore/linuxlist.h>
-
-#define RATE_CTR_INTV_NUM 4
-
-enum rate_ctr_intv {
- RATE_CTR_INTV_SEC,
- RATE_CTR_INTV_MIN,
- RATE_CTR_INTV_HOUR,
- RATE_CTR_INTV_DAY,
-};
-
-/* for each of the intervals, we keep the following values */
-struct rate_ctr_per_intv {
- uint64_t last;
- uint64_t rate;
-};
-
-/* for each actual value, we keep the following data */
-struct rate_ctr {
- uint64_t current;
- struct rate_ctr_per_intv intv[RATE_CTR_INTV_NUM];
-};
-
-struct rate_ctr_desc {
- const char *name;
- const char *description;
-};
-
-/* Describe a counter group class */
-struct rate_ctr_group_desc {
- /* The prefix to the name of all counters in this group */
- char *group_name_prefix;
- /* The human-readable description of the group */
- char *group_description;
- /* The number of counters in this group */
- unsigned int num_ctr;
- /* Pointer to array of counter names */
- struct rate_ctr_desc *ctr_desc;
-};
-
-/* One instance of a counter group class */
-struct rate_ctr_group {
- /* Linked list of all counter groups in the system */
- struct llist_head list;
- /* Pointer to the counter group class */
- const struct rate_ctr_group_desc *desc;
- /* The index of this ctr_group within its class */
- unsigned int idx;
- /* Actual counter structures below */
- struct rate_ctr ctr[0];
-};
-
-/* Allocate a new group of counters according to description */
-struct rate_ctr_group *rate_ctr_group_alloc(void *ctx,
- const struct rate_ctr_group_desc *desc,
- unsigned int idx);
-
-/* Free the memory for the specified group of counters */
-void rate_ctr_group_free(struct rate_ctr_group *grp);
-
-/* Add a number to the counter */
-void rate_ctr_add(struct rate_ctr *ctr, int inc);
-
-/* Increment the counter by 1 */
-static inline void rate_ctr_inc(struct rate_ctr *ctr)
-{
- rate_ctr_add(ctr, 1);
-}
-
-/* Initialize the counter module */
-int rate_ctr_init(void *tall_ctx);
-
-struct vty;
-void vty_out_rate_ctr_group(struct vty *vty, const char *prefix,
- struct rate_ctr_group *ctrg);
-#endif /* RATE_CTR_H */
diff --git a/libosmocore/include/osmocore/rsl.h b/libosmocore/include/osmocore/rsl.h
deleted file mode 100644
index 99b90d6..0000000
--- a/libosmocore/include/osmocore/rsl.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef _OSMOCORE_RSL_H
-#define _OSMOCORE_RSL_H
-
-#include <stdint.h>
-#include <osmocore/utils.h>
-#include <osmocore/protocol/gsm_08_58.h>
-
-void rsl_init_rll_hdr(struct abis_rsl_rll_hdr *dh, uint8_t msg_type);
-
-extern const struct tlv_definition rsl_att_tlvdef;
-#define rsl_tlv_parse(dec, buf, len) \
- tlv_parse(dec, &rsl_att_tlvdef, buf, len, 0, 0)
-
-/* encode channel number as per Section 9.3.1 */
-uint8_t rsl_enc_chan_nr(uint8_t type, uint8_t subch, uint8_t timeslot);
-/* decode channel number as per Section 9.3.1 */
-int rsl_dec_chan_nr(uint8_t chan_nr, uint8_t *type, uint8_t *subch, uint8_t *timeslot);
-
-const char *rsl_err_name(uint8_t err);
-const char *rsl_rlm_cause_name(uint8_t err);
-
-/* Section 3.3.2.3 TS 05.02. I think this looks like a table */
-int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf);
-
-/* Push a RSL RLL header with L3_INFO IE */
-void rsl_rll_push_l3(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr,
- uint8_t link_id, int transparent);
-
-/* Allocate msgb and fill with simple RSL RLL header */
-struct msgb *rsl_rll_simple(uint8_t msg_type, uint8_t chan_nr,
- uint8_t link_id, int transparent);
-#endif /* _OSMOCORE_RSL_H */
diff --git a/libosmocore/include/osmocore/rxlev_stat.h b/libosmocore/include/osmocore/rxlev_stat.h
deleted file mode 100644
index 415509d..0000000
--- a/libosmocore/include/osmocore/rxlev_stat.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef _OSMOCORE_RXLEV_STATS_H
-#define _OSMOCORE_RXLEV_STATS_H
-
-#define NUM_RXLEVS 32
-#define NUM_ARFCNS 1024
-
-struct rxlev_stats {
- /* the maximum number of ARFCN's is 1024, and there are 32 RxLevels,
- * so in we keep one 1024bit-bitvec for each RxLev */
- uint8_t rxlev_buckets[NUM_RXLEVS][NUM_ARFCNS/8];
-};
-
-void rxlev_stat_input(struct rxlev_stats *st, uint16_t arfcn, uint8_t rxlev);
-
-/* get the next ARFCN that has the specified Rxlev */
-int16_t rxlev_stat_get_next(const struct rxlev_stats *st, uint8_t rxlev, int16_t arfcn);
-
-void rxlev_stat_reset(struct rxlev_stats *st);
-
-void rxlev_stat_dump(const struct rxlev_stats *st);
-
-#endif /* _OSMOCORE_RXLEV_STATS_H */
diff --git a/libosmocore/include/osmocore/select.h b/libosmocore/include/osmocore/select.h
deleted file mode 100644
index 2d8b3ec..0000000
--- a/libosmocore/include/osmocore/select.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef _BSC_SELECT_H
-#define _BSC_SELECT_H
-
-#include "linuxlist.h"
-
-#define BSC_FD_READ 0x0001
-#define BSC_FD_WRITE 0x0002
-#define BSC_FD_EXCEPT 0x0004
-
-struct bsc_fd {
- struct llist_head list;
- int fd;
- unsigned int when;
- int (*cb)(struct bsc_fd *fd, unsigned int what);
- void *data;
- unsigned int priv_nr;
-};
-
-int bsc_register_fd(struct bsc_fd *fd);
-void bsc_unregister_fd(struct bsc_fd *fd);
-int bsc_select_main(int polling);
-#endif /* _BSC_SELECT_H */
diff --git a/libosmocore/include/osmocore/signal.h b/libosmocore/include/osmocore/signal.h
deleted file mode 100644
index 02d83d2..0000000
--- a/libosmocore/include/osmocore/signal.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef OSMOCORE_SIGNAL_H
-#define OSMOCORE_SIGNAL_H
-
-typedef int signal_cbfn(unsigned int subsys, unsigned int signal,
- void *handler_data, void *signal_data);
-
-
-/* Management */
-int register_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data);
-void unregister_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data);
-
-/* Dispatch */
-void dispatch_signal(unsigned int subsys, unsigned int signal, void *signal_data);
-
-#endif /* OSMOCORE_SIGNAL_H */
diff --git a/libosmocore/include/osmocore/statistics.h b/libosmocore/include/osmocore/statistics.h
deleted file mode 100644
index 1d56054..0000000
--- a/libosmocore/include/osmocore/statistics.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _STATISTICS_H
-#define _STATISTICS_H
-
-struct counter {
- struct llist_head list;
- const char *name;
- const char *description;
- unsigned long value;
-};
-
-static inline void counter_inc(struct counter *ctr)
-{
- ctr->value++;
-}
-
-static inline unsigned long counter_get(struct counter *ctr)
-{
- return ctr->value;
-}
-
-static inline void counter_reset(struct counter *ctr)
-{
- ctr->value = 0;
-}
-
-struct counter *counter_alloc(const char *name);
-void counter_free(struct counter *ctr);
-
-int counters_for_each(int (*handle_counter)(struct counter *, void *), void *data);
-
-#endif /* _STATISTICS_H */
diff --git a/libosmocore/include/osmocore/talloc.h b/libosmocore/include/osmocore/talloc.h
deleted file mode 100644
index f7f7643..0000000
--- a/libosmocore/include/osmocore/talloc.h
+++ /dev/null
@@ -1,192 +0,0 @@
-#ifndef _TALLOC_H_
-#define _TALLOC_H_
-/*
- Unix SMB/CIFS implementation.
- Samba temporary memory allocation functions
-
- Copyright (C) Andrew Tridgell 2004-2005
- Copyright (C) Stefan Metzmacher 2006
-
- ** NOTE! The following LGPL license applies to the talloc
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-#define HAVE_VA_COPY
-
-/* this is only needed for compatibility with the old talloc */
-typedef void TALLOC_CTX;
-
-/*
- this uses a little trick to allow __LINE__ to be stringified
-*/
-#ifndef __location__
-#define __TALLOC_STRING_LINE1__(s) #s
-#define __TALLOC_STRING_LINE2__(s) __TALLOC_STRING_LINE1__(s)
-#define __TALLOC_STRING_LINE3__ __TALLOC_STRING_LINE2__(__LINE__)
-#define __location__ __FILE__ ":" __TALLOC_STRING_LINE3__
-#endif
-
-#ifndef TALLOC_DEPRECATED
-#define TALLOC_DEPRECATED 0
-#endif
-
-#ifndef PRINTF_ATTRIBUTE
-#if (__GNUC__ >= 3)
-/** Use gcc attribute to check printf fns. a1 is the 1-based index of
- * the parameter containing the format, and a2 the index of the first
- * argument. Note that some gcc 2.x versions don't handle this
- * properly **/
-#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
-#else
-#define PRINTF_ATTRIBUTE(a1, a2)
-#endif
-#endif
-
-/* try to make talloc_set_destructor() and talloc_steal() type safe,
- if we have a recent gcc */
-#if (__GNUC__ >= 3)
-#define _TALLOC_TYPEOF(ptr) __typeof__(ptr)
-#define talloc_set_destructor(ptr, function) \
- do { \
- int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function); \
- _talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \
- } while(0)
-/* this extremely strange macro is to avoid some braindamaged warning
- stupidity in gcc 4.1.x */
-#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)); __talloc_steal_ret; })
-#else
-#define talloc_set_destructor(ptr, function) \
- _talloc_set_destructor((ptr), (int (*)(void *))(function))
-#define _TALLOC_TYPEOF(ptr) void *
-#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr))
-#endif
-
-#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr))
-#define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(*(ptr)))_talloc_move((ctx),(void *)(ptr))
-
-/* useful macros for creating type checked pointers */
-#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type)
-#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__)
-#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr)))
-
-#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__)
-
-#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type)
-#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__)
-
-#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type)
-#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type)
-#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__)
-#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count)
-#define talloc_array_length(ctx) (talloc_get_size(ctx)/sizeof(*ctx))
-
-#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type)
-#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__)
-
-#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__)
-
-#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type)
-#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type)
-#define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__)
-
-#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type)
-
-#if TALLOC_DEPRECATED
-#define talloc_zero_p(ctx, type) talloc_zero(ctx, type)
-#define talloc_p(ctx, type) talloc(ctx, type)
-#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count)
-#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count)
-#define talloc_destroy(ctx) talloc_free(ctx)
-#define talloc_append_string(c, s, a) (s?talloc_strdup_append(s,a):talloc_strdup(c, a))
-#endif
-
-#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0)
-
-/* The following definitions come from talloc.c */
-void *_talloc(const void *context, size_t size);
-void *talloc_pool(const void *context, size_t size);
-void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *));
-int talloc_increase_ref_count(const void *ptr);
-size_t talloc_reference_count(const void *ptr);
-void *_talloc_reference(const void *context, const void *ptr);
-int talloc_unlink(const void *context, void *ptr);
-const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
-void talloc_set_name_const(const void *ptr, const char *name);
-void *talloc_named(const void *context, size_t size,
- const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
-void *talloc_named_const(const void *context, size_t size, const char *name);
-const char *talloc_get_name(const void *ptr);
-void *talloc_check_name(const void *ptr, const char *name);
-void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location);
-void *talloc_parent(const void *ptr);
-const char *talloc_parent_name(const void *ptr);
-void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
-int talloc_free(void *ptr);
-void talloc_free_children(void *ptr);
-void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name);
-void *_talloc_steal(const void *new_ctx, const void *ptr);
-void *_talloc_move(const void *new_ctx, const void *pptr);
-size_t talloc_total_size(const void *ptr);
-size_t talloc_total_blocks(const void *ptr);
-void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
- void (*callback)(const void *ptr,
- int depth, int max_depth,
- int is_ref,
- void *private_data),
- void *private_data);
-void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f);
-void talloc_report_full(const void *ptr, FILE *f);
-void talloc_report(const void *ptr, FILE *f);
-void talloc_enable_null_tracking(void);
-void talloc_disable_null_tracking(void);
-void talloc_enable_leak_report(void);
-void talloc_enable_leak_report_full(void);
-void *_talloc_zero(const void *ctx, size_t size, const char *name);
-void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name);
-void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name);
-void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name);
-void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name);
-void *talloc_realloc_fn(const void *context, void *ptr, size_t size);
-void *talloc_autofree_context(void);
-size_t talloc_get_size(const void *ctx);
-void *talloc_find_parent_byname(const void *ctx, const char *name);
-void talloc_show_parents(const void *context, FILE *file);
-int talloc_is_parent(const void *context, const void *ptr);
-
-char *talloc_strdup(const void *t, const char *p);
-char *talloc_strdup_append(char *s, const char *a);
-char *talloc_strdup_append_buffer(char *s, const char *a);
-
-char *talloc_strndup(const void *t, const char *p, size_t n);
-char *talloc_strndup_append(char *s, const char *a, size_t n);
-char *talloc_strndup_append_buffer(char *s, const char *a, size_t n);
-
-char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
-char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
-char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
-
-char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
-char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
-char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
-
-void talloc_set_abort_fn(void (*abort_fn)(const char *reason));
-
-#endif
diff --git a/libosmocore/include/osmocore/timer.h b/libosmocore/include/osmocore/timer.h
deleted file mode 100644
index fee888b..0000000
--- a/libosmocore/include/osmocore/timer.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef TIMER_H
-#define TIMER_H
-
-#include <sys/time.h>
-
-#include "linuxlist.h"
-
-/**
- * Timer management:
- * - Create a struct timer_list
- * - Fill out timeout and use add_timer or
- * use schedule_timer to schedule a timer in
- * x seconds and microseconds from now...
- * - Use del_timer to remove the timer
- *
- * Internally:
- * - We hook into select.c to give a timeval of the
- * nearest timer. On already passed timers we give
- * it a 0 to immediately fire after the select
- * - update_timers will call the callbacks and remove
- * the timers.
- *
- */
-struct timer_list {
- struct llist_head entry;
- struct timeval timeout;
- unsigned int active : 1;
- unsigned int handled : 1;
- unsigned int in_list : 1;
-
- void (*cb)(void*);
- void *data;
-};
-
-/**
- * timer management
- */
-void bsc_add_timer(struct timer_list *timer);
-void bsc_schedule_timer(struct timer_list *timer, int seconds, int microseconds);
-void bsc_del_timer(struct timer_list *timer);
-int bsc_timer_pending(struct timer_list *timer);
-
-
-/**
- * internal timer list management
- */
-struct timeval *bsc_nearest_timer();
-void bsc_prepare_timers();
-int bsc_update_timers();
-int bsc_timer_check(void);
-
-#endif
diff --git a/libosmocore/include/osmocore/tlv.h b/libosmocore/include/osmocore/tlv.h
deleted file mode 100644
index c733dbc..0000000
--- a/libosmocore/include/osmocore/tlv.h
+++ /dev/null
@@ -1,244 +0,0 @@
-#ifndef _TLV_H
-#define _TLV_H
-
-#include <stdint.h>
-#include <string.h>
-
-#include <osmocore/msgb.h>
-
-/* Terminology / wording
- tag length value (in bits)
-
- V - - 8
- LV - 8 N * 8
- TLV 8 8 N * 8
- TL16V 8 16 N * 8
- TLV16 8 8 N * 16
- TvLV 8 8/16 N * 8
-
-*/
-
-#define LV_GROSS_LEN(x) (x+1)
-#define TLV_GROSS_LEN(x) (x+2)
-#define TLV16_GROSS_LEN(x) ((2*x)+2)
-#define TL16V_GROSS_LEN(x) (x+3)
-#define L16TV_GROSS_LEN(x) (x+3)
-
-#define TVLV_MAX_ONEBYTE 0x7f
-
-static inline uint16_t TVLV_GROSS_LEN(uint16_t len)
-{
- if (len <= TVLV_MAX_ONEBYTE)
- return TLV_GROSS_LEN(len);
- else
- return TL16V_GROSS_LEN(len);
-}
-
-/* TLV generation */
-
-static inline uint8_t *lv_put(uint8_t *buf, uint8_t len,
- const uint8_t *val)
-{
- *buf++ = len;
- memcpy(buf, val, len);
- return buf + len;
-}
-
-static inline uint8_t *tlv_put(uint8_t *buf, uint8_t tag, uint8_t len,
- const uint8_t *val)
-{
- *buf++ = tag;
- *buf++ = len;
- memcpy(buf, val, len);
- return buf + len;
-}
-
-static inline uint8_t *tlv16_put(uint8_t *buf, uint8_t tag, uint8_t len,
- const uint16_t *val)
-{
- *buf++ = tag;
- *buf++ = len;
- memcpy(buf, val, len*2);
- return buf + len*2;
-}
-
-static inline uint8_t *tl16v_put(uint8_t *buf, uint8_t tag, uint16_t len,
- const uint8_t *val)
-{
- *buf++ = tag;
- *buf++ = len >> 8;
- *buf++ = len & 0xff;
- memcpy(buf, val, len);
- return buf + len*2;
-}
-
-static inline uint8_t *tvlv_put(uint8_t *buf, uint8_t tag, uint16_t len,
- const uint8_t *val)
-{
- uint8_t *ret;
-
- if (len <= TVLV_MAX_ONEBYTE) {
- ret = tlv_put(buf, tag, len, val);
- buf[1] |= 0x80;
- } else
- ret = tl16v_put(buf, tag, len, val);
-
- return ret;
-}
-
-static inline uint8_t *msgb_tlv16_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint16_t *val)
-{
- uint8_t *buf = msgb_put(msg, TLV16_GROSS_LEN(len));
- return tlv16_put(buf, tag, len, val);
-}
-
-static inline uint8_t *msgb_tl16v_put(struct msgb *msg, uint8_t tag, uint16_t len,
- const uint8_t *val)
-{
- uint8_t *buf = msgb_put(msg, TL16V_GROSS_LEN(len));
- return tl16v_put(buf, tag, len, val);
-}
-
-static inline uint8_t *msgb_tvlv_put(struct msgb *msg, uint8_t tag, uint16_t len,
- const uint8_t *val)
-{
- uint8_t *buf = msgb_put(msg, TVLV_GROSS_LEN(len));
- return tvlv_put(buf, tag, len, val);
-}
-
-static inline uint8_t *msgb_l16tv_put(struct msgb *msg, uint16_t len, uint8_t tag,
- const uint8_t *val)
-{
- uint8_t *buf = msgb_put(msg, L16TV_GROSS_LEN(len));
-
- *buf++ = len >> 8;
- *buf++ = len & 0xff;
- *buf++ = tag;
- memcpy(buf, val, len);
- return buf + len;
-}
-
-static inline uint8_t *v_put(uint8_t *buf, uint8_t val)
-{
- *buf++ = val;
- return buf;
-}
-
-static inline uint8_t *tv_put(uint8_t *buf, uint8_t tag,
- uint8_t val)
-{
- *buf++ = tag;
- *buf++ = val;
- return buf;
-}
-
-/* 'val' is still in host byte order! */
-static inline uint8_t *tv16_put(uint8_t *buf, uint8_t tag,
- uint16_t val)
-{
- *buf++ = tag;
- *buf++ = val >> 8;
- *buf++ = val & 0xff;
- return buf;
-}
-
-static inline uint8_t *msgb_lv_put(struct msgb *msg, uint8_t len, const uint8_t *val)
-{
- uint8_t *buf = msgb_put(msg, LV_GROSS_LEN(len));
- return lv_put(buf, len, val);
-}
-
-static inline uint8_t *msgb_tlv_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val)
-{
- uint8_t *buf = msgb_put(msg, TLV_GROSS_LEN(len));
- return tlv_put(buf, tag, len, val);
-}
-
-static inline uint8_t *msgb_tv_put(struct msgb *msg, uint8_t tag, uint8_t val)
-{
- uint8_t *buf = msgb_put(msg, 2);
- return tv_put(buf, tag, val);
-}
-
-static inline uint8_t *msgb_v_put(struct msgb *msg, uint8_t val)
-{
- uint8_t *buf = msgb_put(msg, 1);
- return v_put(buf, val);
-}
-
-static inline uint8_t *msgb_tv16_put(struct msgb *msg, uint8_t tag, uint16_t val)
-{
- uint8_t *buf = msgb_put(msg, 3);
- return tv16_put(buf, tag, val);
-}
-
-static inline uint8_t *msgb_tlv_push(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val)
-{
- uint8_t *buf = msgb_push(msg, TLV_GROSS_LEN(len));
- return tlv_put(buf, tag, len, val);
-}
-
-static inline uint8_t *msgb_tv_push(struct msgb *msg, uint8_t tag, uint8_t val)
-{
- uint8_t *buf = msgb_push(msg, 2);
- return tv_put(buf, tag, val);
-}
-
-static inline uint8_t *msgb_tv16_push(struct msgb *msg, uint8_t tag, uint16_t val)
-{
- uint8_t *buf = msgb_push(msg, 3);
- return tv16_put(buf, tag, val);
-}
-
-static inline uint8_t *msgb_tvlv_push(struct msgb *msg, uint8_t tag, uint16_t len,
- const uint8_t *val)
-{
- uint8_t *buf = msgb_push(msg, TVLV_GROSS_LEN(len));
- return tvlv_put(buf, tag, len, val);
-}
-
-/* TLV parsing */
-
-struct tlv_p_entry {
- uint16_t len;
- const uint8_t *val;
-};
-
-enum tlv_type {
- TLV_TYPE_NONE,
- TLV_TYPE_FIXED,
- TLV_TYPE_T,
- TLV_TYPE_TV,
- TLV_TYPE_TLV,
- TLV_TYPE_TL16V,
- TLV_TYPE_TvLV,
-};
-
-struct tlv_def {
- enum tlv_type type;
- uint8_t fixed_len;
-};
-
-struct tlv_definition {
- struct tlv_def def[0xff];
-};
-
-struct tlv_parsed {
- struct tlv_p_entry lv[0xff];
-};
-
-extern struct tlv_definition tvlv_att_def;
-
-int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val,
- const struct tlv_definition *def,
- const uint8_t *buf, int buf_len);
-int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
- const uint8_t *buf, int buf_len, uint8_t lv_tag, uint8_t lv_tag2);
-/* take a master (src) tlvdev and fill up all empty slots in 'dst' */
-void tlv_def_patch(struct tlv_definition *dst, const struct tlv_definition *src);
-
-#define TLVP_PRESENT(x, y) ((x)->lv[y].val)
-#define TLVP_LEN(x, y) (x)->lv[y].len
-#define TLVP_VAL(x, y) (x)->lv[y].val
-
-#endif /* _TLV_H */
diff --git a/libosmocore/include/osmocore/utils.h b/libosmocore/include/osmocore/utils.h
deleted file mode 100644
index 51c6f03..0000000
--- a/libosmocore/include/osmocore/utils.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef OSMOCORE_UTIL_H
-#define OSMOCORE_UTIL_H
-
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
-#include <stdint.h>
-
-struct value_string {
- unsigned int value;
- const char *str;
-};
-
-const char *get_value_string(const struct value_string *vs, uint32_t val);
-int get_string_value(const struct value_string *vs, const char *str);
-
-char bcd2char(uint8_t bcd);
-/* only works for numbers in ascci */
-uint8_t char2bcd(char c);
-
-#endif
diff --git a/libosmocore/include/osmocore/write_queue.h b/libosmocore/include/osmocore/write_queue.h
deleted file mode 100644
index ef244c3..0000000
--- a/libosmocore/include/osmocore/write_queue.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Generic write queue implementation */
-/*
- * (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 General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-#ifndef write_queue_h
-#define write_queue_h
-
-#include "select.h"
-#include "msgb.h"
-
-struct write_queue {
- struct bsc_fd bfd;
- unsigned int max_length;
- unsigned int current_length;
-
- struct llist_head msg_queue;
-
- int (*read_cb)(struct bsc_fd *fd);
- int (*write_cb)(struct bsc_fd *fd, struct msgb *msg);
- int (*except_cb)(struct bsc_fd *fd);
-};
-
-void write_queue_init(struct write_queue *queue, int max_length);
-void write_queue_clear(struct write_queue *queue);
-int write_queue_enqueue(struct write_queue *queue, struct msgb *data);
-int write_queue_bfd_cb(struct bsc_fd *fd, unsigned int what);
-
-#endif
diff --git a/libosmocore/libosmocore.pc.in b/libosmocore/libosmocore.pc.in
deleted file mode 100644
index 7c29869..0000000
--- a/libosmocore/libosmocore.pc.in
+++ /dev/null
@@ -1,11 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: Osmocom Core Library
-Description: C Utility Library
-Version: @VERSION@
-Libs: -L${libdir} -losmocore
-Cflags: -I${includedir}/
-
diff --git a/libosmocore/m4/DUMMY b/libosmocore/m4/DUMMY
deleted file mode 100644
index fda557a..0000000
--- a/libosmocore/m4/DUMMY
+++ /dev/null
@@ -1 +0,0 @@
-Dummply placeholder.
diff --git a/libosmocore/src/Makefile.am b/libosmocore/src/Makefile.am
deleted file mode 100644
index ce063d0..0000000
--- a/libosmocore/src/Makefile.am
+++ /dev/null
@@ -1,17 +0,0 @@
-# This is _NOT_ the library release version, it's an API version.
-# Please read Chapter 6 "Library interface versions" of the libtool documentation before making any modification
-LIBVERSION=0:0:0
-
-INCLUDES = $(all_includes) -I$(top_srcdir)/include
-AM_CFLAGS = -fPIC -Wall
-
-lib_LTLIBRARIES = libosmocore.la
-
-libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c rxlev_stat.c \
- tlv_parser.c bitvec.c comp128.c gsm_utils.c statistics.c \
- write_queue.c utils.c rsl.c gsm48.c gsm48_ie.c \
- logging.c gsm0808.c rate_ctr.c
-
-if ENABLE_TALLOC
-libosmocore_la_SOURCES += talloc.c
-endif
diff --git a/libosmocore/src/bitvec.c b/libosmocore/src/bitvec.c
deleted file mode 100644
index eb83ac6..0000000
--- a/libosmocore/src/bitvec.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/* bit vector utility routines */
-
-/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-
-#include <errno.h>
-#include <stdint.h>
-
-#include <osmocore/bitvec.h>
-
-#define BITNUM_FROM_COMP(byte, bit) ((byte*8)+bit)
-
-static inline unsigned int bytenum_from_bitnum(unsigned int bitnum)
-{
- unsigned int bytenum = bitnum / 8;
-
- return bytenum;
-}
-
-/* convert ZERO/ONE/L/H to a bitmask at given pos in a byte */
-static uint8_t bitval2mask(enum bit_value bit, uint8_t bitnum)
-{
- int bitval;
-
- switch (bit) {
- case ZERO:
- bitval = (0 << bitnum);
- break;
- case ONE:
- bitval = (1 << bitnum);
- break;
- case L:
- bitval = ((0x2b ^ (0 << bitnum)) & (1 << bitnum));
- break;
- case H:
- bitval = ((0x2b ^ (1 << bitnum)) & (1 << bitnum));
- break;
- default:
- return 0;
- }
- return bitval;
-}
-
-/* check if the bit is 0 or 1 for a given position inside a bitvec */
-enum bit_value bitvec_get_bit_pos(const struct bitvec *bv, unsigned int bitnr)
-{
- unsigned int bytenum = bytenum_from_bitnum(bitnr);
- unsigned int bitnum = 7 - (bitnr % 8);
- uint8_t bitval;
-
- if (bytenum >= bv->data_len)
- return -EINVAL;
-
- bitval = bitval2mask(ONE, bitnum);
-
- if (bv->data[bytenum] & bitval)
- return ONE;
-
- return ZERO;
-}
-
-/* get the Nth set bit inside the bit vector */
-unsigned int bitvec_get_nth_set_bit(const struct bitvec *bv, unsigned int n)
-{
- unsigned int i, k = 0;
-
- for (i = 0; i < bv->data_len*8; i++) {
- if (bitvec_get_bit_pos(bv, i) == ONE) {
- k++;
- if (k == n)
- return i;
- }
- }
-
- return 0;
-}
-
-/* set the bit at a given position inside a bitvec */
-int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnr,
- enum bit_value bit)
-{
- unsigned int bytenum = bytenum_from_bitnum(bitnr);
- unsigned int bitnum = 7 - (bitnr % 8);
- uint8_t bitval;
-
- if (bytenum >= bv->data_len)
- return -EINVAL;
-
- /* first clear the bit */
- bitval = bitval2mask(ONE, bitnum);
- bv->data[bytenum] &= ~bitval;
-
- /* then set it to desired value */
- bitval = bitval2mask(bit, bitnum);
- bv->data[bytenum] |= bitval;
-
- return 0;
-}
-
-/* set the next bit inside a bitvec */
-int bitvec_set_bit(struct bitvec *bv, enum bit_value bit)
-{
- int rc;
-
- rc = bitvec_set_bit_pos(bv, bv->cur_bit, bit);
- if (!rc)
- bv->cur_bit++;
-
- return rc;
-}
-
-/* set multiple bits (based on array of bitvals) at current pos */
-int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count)
-{
- int i, rc;
-
- for (i = 0; i < count; i++) {
- rc = bitvec_set_bit(bv, bits[i]);
- if (rc)
- return rc;
- }
-
- return 0;
-}
-
-/* set multiple bits (based on numeric value) at current pos */
-int bitvec_set_uint(struct bitvec *bv, unsigned int ui, int num_bits)
-{
- int i, rc;
-
- for (i = 0; i < num_bits; i++) {
- int bit = 0;
- if (ui & (1 << (num_bits - i - 1)))
- bit = 1;
- rc = bitvec_set_bit(bv, bit);
- if (rc)
- return rc;
- }
-
- return 0;
-}
-
-/* pad all remaining bits up to num_bits */
-int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit)
-{
- unsigned int i;
-
- for (i = bv->cur_bit; i <= up_to_bit; i++)
- bitvec_set_bit(bv, L);
-
- return 0;
-}
diff --git a/libosmocore/src/comp128.c b/libosmocore/src/comp128.c
deleted file mode 100644
index 5d5680c..0000000
--- a/libosmocore/src/comp128.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * COMP128 implementation
- *
- *
- * This code is inspired by original code from :
- * Marc Briceno <marc@scard.org>, Ian Goldberg <iang@cs.berkeley.edu>,
- * and David Wagner <daw@cs.berkeley.edu>
- *
- * But it has been fully rewritten from various PDFs found online describing
- * the algorithm because the licence of the code referenced above was unclear.
- * A comment snippet from the original code is included below, it describes
- * where the doc came from and how the algorithm was reverse engineered.
- *
- *
- * (C) 2009 by Sylvain Munaut <tnt@246tNt.com>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-/*
- * --- SNIP ---
- *
- * This code derived from a leaked document from the GSM standards.
- * Some missing pieces were filled in by reverse-engineering a working SIM.
- * We have verified that this is the correct COMP128 algorithm.
- *
- * The first page of the document identifies it as
- * _Technical Information: GSM System Security Study_.
- * 10-1617-01, 10th June 1988.
- * The bottom of the title page is marked
- * Racal Research Ltd.
- * Worton Drive, Worton Grange Industrial Estate,
- * Reading, Berks. RG2 0SB, England.
- * Telephone: Reading (0734) 868601 Telex: 847152
- * The relevant bits are in Part I, Section 20 (pages 66--67). Enjoy!
- *
- * Note: There are three typos in the spec (discovered by
- * reverse-engineering).
- * First, "z = (2 * x[n] + x[n]) mod 2^(9-j)" should clearly read
- * "z = (2 * x[m] + x[n]) mod 2^(9-j)".
- * Second, the "k" loop in the "Form bits from bytes" section is severely
- * botched: the k index should run only from 0 to 3, and clearly the range
- * on "the (8-k)th bit of byte j" is also off (should be 0..7, not 1..8,
- * to be consistent with the subsequent section).
- * Third, SRES is taken from the first 8 nibbles of x[], not the last 8 as
- * claimed in the document. (And the document doesn't specify how Kc is
- * derived, but that was also easily discovered with reverse engineering.)
- * All of these typos have been corrected in the following code.
- *
- * --- /SNIP ---
- */
-
-#include <string.h>
-#include <stdint.h>
-
-/* The compression tables (just copied ...) */
-static const uint8_t table_0[512] = {
- 102, 177, 186, 162, 2, 156, 112, 75, 55, 25, 8, 12, 251, 193, 246, 188,
- 109, 213, 151, 53, 42, 79, 191, 115, 233, 242, 164, 223, 209, 148, 108, 161,
- 252, 37, 244, 47, 64, 211, 6, 237, 185, 160, 139, 113, 76, 138, 59, 70,
- 67, 26, 13, 157, 63, 179, 221, 30, 214, 36, 166, 69, 152, 124, 207, 116,
- 247, 194, 41, 84, 71, 1, 49, 14, 95, 35, 169, 21, 96, 78, 215, 225,
- 182, 243, 28, 92, 201, 118, 4, 74, 248, 128, 17, 11, 146, 132, 245, 48,
- 149, 90, 120, 39, 87, 230, 106, 232, 175, 19, 126, 190, 202, 141, 137, 176,
- 250, 27, 101, 40, 219, 227, 58, 20, 51, 178, 98, 216, 140, 22, 32, 121,
- 61, 103, 203, 72, 29, 110, 85, 212, 180, 204, 150, 183, 15, 66, 172, 196,
- 56, 197, 158, 0, 100, 45, 153, 7, 144, 222, 163, 167, 60, 135, 210, 231,
- 174, 165, 38, 249, 224, 34, 220, 229, 217, 208, 241, 68, 206, 189, 125, 255,
- 239, 54, 168, 89, 123, 122, 73, 145, 117, 234, 143, 99, 129, 200, 192, 82,
- 104, 170, 136, 235, 93, 81, 205, 173, 236, 94, 105, 52, 46, 228, 198, 5,
- 57, 254, 97, 155, 142, 133, 199, 171, 187, 50, 65, 181, 127, 107, 147, 226,
- 184, 218, 131, 33, 77, 86, 31, 44, 88, 62, 238, 18, 24, 43, 154, 23,
- 80, 159, 134, 111, 9, 114, 3, 91, 16, 130, 83, 10, 195, 240, 253, 119,
- 177, 102, 162, 186, 156, 2, 75, 112, 25, 55, 12, 8, 193, 251, 188, 246,
- 213, 109, 53, 151, 79, 42, 115, 191, 242, 233, 223, 164, 148, 209, 161, 108,
- 37, 252, 47, 244, 211, 64, 237, 6, 160, 185, 113, 139, 138, 76, 70, 59,
- 26, 67, 157, 13, 179, 63, 30, 221, 36, 214, 69, 166, 124, 152, 116, 207,
- 194, 247, 84, 41, 1, 71, 14, 49, 35, 95, 21, 169, 78, 96, 225, 215,
- 243, 182, 92, 28, 118, 201, 74, 4, 128, 248, 11, 17, 132, 146, 48, 245,
- 90, 149, 39, 120, 230, 87, 232, 106, 19, 175, 190, 126, 141, 202, 176, 137,
- 27, 250, 40, 101, 227, 219, 20, 58, 178, 51, 216, 98, 22, 140, 121, 32,
- 103, 61, 72, 203, 110, 29, 212, 85, 204, 180, 183, 150, 66, 15, 196, 172,
- 197, 56, 0, 158, 45, 100, 7, 153, 222, 144, 167, 163, 135, 60, 231, 210,
- 165, 174, 249, 38, 34, 224, 229, 220, 208, 217, 68, 241, 189, 206, 255, 125,
- 54, 239, 89, 168, 122, 123, 145, 73, 234, 117, 99, 143, 200, 129, 82, 192,
- 170, 104, 235, 136, 81, 93, 173, 205, 94, 236, 52, 105, 228, 46, 5, 198,
- 254, 57, 155, 97, 133, 142, 171, 199, 50, 187, 181, 65, 107, 127, 226, 147,
- 218, 184, 33, 131, 86, 77, 44, 31, 62, 88, 18, 238, 43, 24, 23, 154,
- 159, 80, 111, 134, 114, 9, 91, 3, 130, 16, 10, 83, 240, 195, 119, 253,
-}, table_1[256] = {
- 19, 11, 80, 114, 43, 1, 69, 94, 39, 18, 127, 117, 97, 3, 85, 43,
- 27, 124, 70, 83, 47, 71, 63, 10, 47, 89, 79, 4, 14, 59, 11, 5,
- 35, 107, 103, 68, 21, 86, 36, 91, 85, 126, 32, 50, 109, 94, 120, 6,
- 53, 79, 28, 45, 99, 95, 41, 34, 88, 68, 93, 55, 110, 125, 105, 20,
- 90, 80, 76, 96, 23, 60, 89, 64, 121, 56, 14, 74, 101, 8, 19, 78,
- 76, 66, 104, 46, 111, 50, 32, 3, 39, 0, 58, 25, 92, 22, 18, 51,
- 57, 65, 119, 116, 22, 109, 7, 86, 59, 93, 62, 110, 78, 99, 77, 67,
- 12, 113, 87, 98, 102, 5, 88, 33, 38, 56, 23, 8, 75, 45, 13, 75,
- 95, 63, 28, 49, 123, 120, 20, 112, 44, 30, 15, 98, 106, 2, 103, 29,
- 82, 107, 42, 124, 24, 30, 41, 16, 108, 100, 117, 40, 73, 40, 7, 114,
- 82, 115, 36, 112, 12, 102, 100, 84, 92, 48, 72, 97, 9, 54, 55, 74,
- 113, 123, 17, 26, 53, 58, 4, 9, 69, 122, 21, 118, 42, 60, 27, 73,
- 118, 125, 34, 15, 65, 115, 84, 64, 62, 81, 70, 1, 24, 111, 121, 83,
- 104, 81, 49, 127, 48, 105, 31, 10, 6, 91, 87, 37, 16, 54, 116, 126,
- 31, 38, 13, 0, 72, 106, 77, 61, 26, 67, 46, 29, 96, 37, 61, 52,
- 101, 17, 44, 108, 71, 52, 66, 57, 33, 51, 25, 90, 2, 119, 122, 35,
-}, table_2[128] = {
- 52, 50, 44, 6, 21, 49, 41, 59, 39, 51, 25, 32, 51, 47, 52, 43,
- 37, 4, 40, 34, 61, 12, 28, 4, 58, 23, 8, 15, 12, 22, 9, 18,
- 55, 10, 33, 35, 50, 1, 43, 3, 57, 13, 62, 14, 7, 42, 44, 59,
- 62, 57, 27, 6, 8, 31, 26, 54, 41, 22, 45, 20, 39, 3, 16, 56,
- 48, 2, 21, 28, 36, 42, 60, 33, 34, 18, 0, 11, 24, 10, 17, 61,
- 29, 14, 45, 26, 55, 46, 11, 17, 54, 46, 9, 24, 30, 60, 32, 0,
- 20, 38, 2, 30, 58, 35, 1, 16, 56, 40, 23, 48, 13, 19, 19, 27,
- 31, 53, 47, 38, 63, 15, 49, 5, 37, 53, 25, 36, 63, 29, 5, 7,
-}, table_3[64] = {
- 1, 5, 29, 6, 25, 1, 18, 23, 17, 19, 0, 9, 24, 25, 6, 31,
- 28, 20, 24, 30, 4, 27, 3, 13, 15, 16, 14, 18, 4, 3, 8, 9,
- 20, 0, 12, 26, 21, 8, 28, 2, 29, 2, 15, 7, 11, 22, 14, 10,
- 17, 21, 12, 30, 26, 27, 16, 31, 11, 7, 13, 23, 10, 5, 22, 19,
-}, table_4[32] = {
- 15, 12, 10, 4, 1, 14, 11, 7, 5, 0, 14, 7, 1, 2, 13, 8,
- 10, 3, 4, 9, 6, 0, 3, 2, 5, 6, 8, 9, 11, 13, 15, 12,
-};
-
-static const uint8_t *_comp128_table[5] = { table_0, table_1, table_2, table_3, table_4 };
-
-
-static inline void
-_comp128_compression_round(uint8_t *x, int n, const uint8_t *tbl)
-{
- int i, j, m, a, b, y, z;
- m = 4 - n;
- for (i=0; i<(1<<n); i++)
- for (j=0; j<(1<<m); j++) {
- a = j + i * (2<<m);
- b = a + (1<<m);
- y = (x[a] + (x[b]<<1)) & ((32<<m)-1);
- z = ((x[a]<<1) + x[b]) & ((32<<m)-1);
- x[a] = tbl[y];
- x[b] = tbl[z];
- }
-}
-
-static inline void
-_comp128_compression(uint8_t *x)
-{
- int n;
- for (n=0; n<5; n++)
- _comp128_compression_round(x, n, _comp128_table[n]);
-}
-
-static inline void
-_comp128_bitsfrombytes(uint8_t *x, uint8_t *bits)
-{
- int i;
- memset(bits, 0x00, 128);
- for (i=0; i<128; i++)
- if (x[i>>2] & (1<<(3-(i&3))))
- bits[i] = 1;
-}
-
-static inline void
-_comp128_permutation(uint8_t *x, uint8_t *bits)
-{
- int i;
- memset(&x[16], 0x00, 16);
- for (i=0; i<128; i++)
- x[(i>>3)+16] |= bits[(i*17) & 127] << (7-(i&7));
-}
-
-void
-comp128(uint8_t *ki, uint8_t *rand, uint8_t *sres, uint8_t *kc)
-{
- int i;
- uint8_t x[32], bits[128];
-
- /* x[16-31] = RAND */
- memcpy(&x[16], rand, 16);
-
- /* Round 1-7 */
- for (i=0; i<7; i++) {
- /* x[0-15] = Ki */
- memcpy(x, ki, 16);
-
- /* Compression */
- _comp128_compression(x);
-
- /* FormBitFromBytes */
- _comp128_bitsfrombytes(x, bits);
-
- /* Permutation */
- _comp128_permutation(x, bits);
- }
-
- /* Round 8 (final) */
- /* x[0-15] = Ki */
- memcpy(x, ki, 16);
-
- /* Compression */
- _comp128_compression(x);
-
- /* Output stage */
- for (i=0; i<8; i+=2)
- sres[i>>1] = x[i]<<4 | x[i+1];
-
- for (i=0; i<12; i+=2)
- kc[i>>1] = (x[i + 18] << 6) |
- (x[i + 19] << 2) |
- (x[i + 20] >> 2);
-
- kc[6] = (x[30]<<6) | (x[31]<<2);
- kc[7] = 0;
-}
-
diff --git a/libosmocore/src/gsm0808.c b/libosmocore/src/gsm0808.c
deleted file mode 100644
index 7a7eb3a..0000000
--- a/libosmocore/src/gsm0808.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/* (C) 2009,2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009,2010 by On-Waves
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <osmocore/gsm0808.h>
-#include <osmocore/protocol/gsm_08_08.h>
-#include <osmocore/gsm48.h>
-
-#include <arpa/inet.h>
-
-#define BSSMAP_MSG_SIZE 512
-#define BSSMAP_MSG_HEADROOM 128
-
-struct msgb *gsm0808_create_layer3(struct msgb *msg_l3, uint16_t nc, uint16_t cc, int lac, int _ci)
-{
- uint8_t *data;
- uint16_t *ci;
- struct msgb* msg;
- struct gsm48_loc_area_id *lai;
-
- msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
- "bssmap cmpl l3");
- if (!msg)
- return NULL;
-
- /* create the bssmap header */
- msg->l3h = msgb_put(msg, 2);
- msg->l3h[0] = 0x0;
-
- /* create layer 3 header */
- data = msgb_put(msg, 1);
- data[0] = BSS_MAP_MSG_COMPLETE_LAYER_3;
-
- /* create the cell header */
- data = msgb_put(msg, 3);
- data[0] = GSM0808_IE_CELL_IDENTIFIER;
- data[1] = 1 + sizeof(*lai) + 2;
- data[2] = CELL_IDENT_WHOLE_GLOBAL;
-
- lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
- gsm48_generate_lai(lai, cc, nc, lac);
-
- ci = (uint16_t *) msgb_put(msg, 2);
- *ci = htons(_ci);
-
- /* copy the layer3 data */
- data = msgb_put(msg, msgb_l3len(msg_l3) + 2);
- data[0] = GSM0808_IE_LAYER_3_INFORMATION;
- data[1] = msgb_l3len(msg_l3);
- memcpy(&data[2], msg_l3->l3h, data[1]);
-
- /* update the size */
- msg->l3h[1] = msgb_l3len(msg) - 2;
-
- return msg;
-}
-
-struct msgb *gsm0808_create_reset(void)
-{
- struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
- "bssmap: reset");
- if (!msg)
- return NULL;
-
- msg->l3h = msgb_put(msg, 6);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 0x04;
- msg->l3h[2] = 0x30;
- msg->l3h[3] = 0x04;
- msg->l3h[4] = 0x01;
- msg->l3h[5] = 0x20;
- return msg;
-}
-
-struct msgb *gsm0808_create_clear_complete(void)
-{
- struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
- "bssmap: clear complete");
- if (!msg)
- return NULL;
-
- msg->l3h = msgb_put(msg, 3);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 1;
- msg->l3h[2] = BSS_MAP_MSG_CLEAR_COMPLETE;
-
- return msg;
-}
-
-struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id)
-{
- struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
- "cipher-complete");
- if (!msg)
- return NULL;
-
- /* send response with BSS override for A5/1... cheating */
- msg->l3h = msgb_put(msg, 3);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 0xff;
- msg->l3h[2] = BSS_MAP_MSG_CIPHER_MODE_COMPLETE;
-
- /* include layer3 in case we have at least two octets */
- if (layer3 && msgb_l3len(layer3) > 2) {
- msg->l4h = msgb_put(msg, msgb_l3len(layer3) + 2);
- msg->l4h[0] = GSM0808_IE_LAYER_3_MESSAGE_CONTENTS;
- msg->l4h[1] = msgb_l3len(layer3);
- memcpy(&msg->l4h[2], layer3->l3h, msgb_l3len(layer3));
- }
-
- /* and the optional BSS message */
- msg->l4h = msgb_put(msg, 2);
- msg->l4h[0] = GSM0808_IE_CHOSEN_ENCR_ALG;
- msg->l4h[1] = alg_id;
-
- /* update the size */
- msg->l3h[1] = msgb_l3len(msg) - 2;
- return msg;
-}
-
-struct msgb *gsm0808_create_cipher_reject(uint8_t cause)
-{
- struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
- "bssmap: clear complete");
- if (!msg)
- return NULL;
-
- msg->l3h = msgb_put(msg, 3);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 2;
- msg->l3h[2] = BSS_MAP_MSG_CIPHER_MODE_REJECT;
- msg->l3h[3] = cause;
-
- return msg;
-}
-
-struct msgb *gsm0808_create_classmark_update(const uint8_t *classmark_data, uint8_t length)
-{
- struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
- "classmark-update");
- if (!msg)
- return NULL;
-
- msg->l3h = msgb_put(msg, 3);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 0xff;
- msg->l3h[2] = BSS_MAP_MSG_CLASSMARK_UPDATE;
-
- msg->l4h = msgb_put(msg, length);
- memcpy(msg->l4h, classmark_data, length);
-
- /* update the size */
- msg->l3h[1] = msgb_l3len(msg) - 2;
- return msg;
-}
-
-struct msgb *gsm0808_create_sapi_reject(uint8_t link_id)
-{
- struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
- "bssmap: sapi 'n' reject");
- if (!msg)
- return NULL;
-
- msg->l3h = msgb_put(msg, 5);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 3;
- msg->l3h[2] = BSS_MAP_MSG_SAPI_N_REJECT;
- msg->l3h[3] = link_id;
- msg->l3h[4] = GSM0808_CAUSE_BSS_NOT_EQUIPPED;
-
- return msg;
-}
-
-struct msgb *gsm0808_create_assignment_completed(struct gsm_lchan *lchan, uint8_t rr_cause,
- uint8_t chosen_channel, uint8_t encr_alg_id,
- uint8_t speech_mode)
-{
- uint8_t *data;
-
- struct msgb *msg = msgb_alloc(35, "bssmap: ass compl");
- if (!msg)
- return NULL;
-
- msg->l3h = msgb_put(msg, 3);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 0xff;
- msg->l3h[2] = BSS_MAP_MSG_ASSIGMENT_COMPLETE;
-
- /* write 3.2.2.22 */
- data = msgb_put(msg, 2);
- data[0] = GSM0808_IE_RR_CAUSE;
- data[1] = rr_cause;
-
- /* write cirtcuit identity code 3.2.2.2 */
- /* write cell identifier 3.2.2.17 */
- /* write chosen channel 3.2.2.33 when BTS picked it */
- data = msgb_put(msg, 2);
- data[0] = GSM0808_IE_CHOSEN_CHANNEL;
- data[1] = chosen_channel;
-
- /* write chosen encryption algorithm 3.2.2.44 */
- data = msgb_put(msg, 2);
- data[0] = GSM0808_IE_CHOSEN_ENCR_ALG;
- data[1] = encr_alg_id;
-
- /* write circuit pool 3.2.2.45 */
- /* write speech version chosen: 3.2.2.51 when BTS picked it */
- if (speech_mode != 0) {
- data = msgb_put(msg, 2);
- data[0] = GSM0808_IE_SPEECH_VERSION;
- data[1] = speech_mode;
- }
-
- /* write LSA identifier 3.2.2.15 */
-
-
- /* update the size */
- msg->l3h[1] = msgb_l3len(msg) - 2;
- return msg;
-}
-
-struct msgb *gsm0808_create_assignment_failure(uint8_t cause, uint8_t *rr_cause)
-{
- uint8_t *data;
- struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
- "bssmap: ass fail");
- if (!msg)
- return NULL;
-
- msg->l3h = msgb_put(msg, 6);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 0xff;
- msg->l3h[2] = BSS_MAP_MSG_ASSIGMENT_FAILURE;
- msg->l3h[3] = GSM0808_IE_CAUSE;
- msg->l3h[4] = 1;
- msg->l3h[5] = cause;
-
- /* RR cause 3.2.2.22 */
- if (rr_cause) {
- data = msgb_put(msg, 2);
- data[0] = GSM0808_IE_RR_CAUSE;
- data[1] = *rr_cause;
- }
-
- /* Circuit pool 3.22.45 */
- /* Circuit pool list 3.2.2.46 */
-
- /* update the size */
- msg->l3h[1] = msgb_l3len(msg) - 2;
- return msg;
-}
-
-static const struct tlv_definition bss_att_tlvdef = {
- .def = {
- [GSM0808_IE_IMSI] = { TLV_TYPE_TLV },
- [GSM0808_IE_TMSI] = { TLV_TYPE_TLV },
- [GSM0808_IE_CELL_IDENTIFIER_LIST] = { TLV_TYPE_TLV },
- [GSM0808_IE_CHANNEL_NEEDED] = { TLV_TYPE_TV },
- [GSM0808_IE_EMLPP_PRIORITY] = { TLV_TYPE_TV },
- [GSM0808_IE_CHANNEL_TYPE] = { TLV_TYPE_TLV },
- [GSM0808_IE_PRIORITY] = { TLV_TYPE_TLV },
- [GSM0808_IE_CIRCUIT_IDENTITY_CODE] = { TLV_TYPE_TV },
- [GSM0808_IE_DOWNLINK_DTX_FLAG] = { TLV_TYPE_TV },
- [GSM0808_IE_INTERFERENCE_BAND_TO_USE] = { TLV_TYPE_TV },
- [GSM0808_IE_CLASSMARK_INFORMATION_T2] = { TLV_TYPE_TLV },
- [GSM0808_IE_GROUP_CALL_REFERENCE] = { TLV_TYPE_TLV },
- [GSM0808_IE_TALKER_FLAG] = { TLV_TYPE_T },
- [GSM0808_IE_CONFIG_EVO_INDI] = { TLV_TYPE_TV },
- [GSM0808_IE_LSA_ACCESS_CTRL_SUPPR] = { TLV_TYPE_TV },
- [GSM0808_IE_SERVICE_HANDOVER] = { TLV_TYPE_TV},
- [GSM0808_IE_ENCRYPTION_INFORMATION] = { TLV_TYPE_TLV },
- [GSM0808_IE_CIPHER_RESPONSE_MODE] = { TLV_TYPE_TV },
- },
-};
-
-const struct tlv_definition *gsm0808_att_tlvdef()
-{
- return &bss_att_tlvdef;
-}
diff --git a/libosmocore/src/gsm48.c b/libosmocore/src/gsm48.c
deleted file mode 100644
index d957aef..0000000
--- a/libosmocore/src/gsm48.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/* GSM Mobile Radio Interface Layer 3 messages
- * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
-
-/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <arpa/inet.h>
-
-#include <osmocore/utils.h>
-#include <osmocore/tlv.h>
-#include <osmocore/gsm48.h>
-
-#include <osmocore/protocol/gsm_04_08.h>
-
-const struct tlv_definition gsm48_att_tlvdef = {
- .def = {
- [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV },
- [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV },
- [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV },
- [GSM48_IE_UTC] = { TLV_TYPE_TV },
- [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 },
- [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV },
-
- [GSM48_IE_BEARER_CAP] = { TLV_TYPE_TLV },
- [GSM48_IE_CAUSE] = { TLV_TYPE_TLV },
- [GSM48_IE_CC_CAP] = { TLV_TYPE_TLV },
- [GSM48_IE_ALERT] = { TLV_TYPE_TLV },
- [GSM48_IE_FACILITY] = { TLV_TYPE_TLV },
- [GSM48_IE_PROGR_IND] = { TLV_TYPE_TLV },
- [GSM48_IE_AUX_STATUS] = { TLV_TYPE_TLV },
- [GSM48_IE_NOTIFY] = { TLV_TYPE_TV },
- [GSM48_IE_KPD_FACILITY] = { TLV_TYPE_TV },
- [GSM48_IE_SIGNAL] = { TLV_TYPE_TV },
- [GSM48_IE_CONN_BCD] = { TLV_TYPE_TLV },
- [GSM48_IE_CONN_SUB] = { TLV_TYPE_TLV },
- [GSM48_IE_CALLING_BCD] = { TLV_TYPE_TLV },
- [GSM48_IE_CALLING_SUB] = { TLV_TYPE_TLV },
- [GSM48_IE_CALLED_BCD] = { TLV_TYPE_TLV },
- [GSM48_IE_CALLED_SUB] = { TLV_TYPE_TLV },
- [GSM48_IE_REDIR_BCD] = { TLV_TYPE_TLV },
- [GSM48_IE_REDIR_SUB] = { TLV_TYPE_TLV },
- [GSM48_IE_LOWL_COMPAT] = { TLV_TYPE_TLV },
- [GSM48_IE_HIGHL_COMPAT] = { TLV_TYPE_TLV },
- [GSM48_IE_USER_USER] = { TLV_TYPE_TLV },
- [GSM48_IE_SS_VERS] = { TLV_TYPE_TLV },
- [GSM48_IE_MORE_DATA] = { TLV_TYPE_T },
- [GSM48_IE_CLIR_SUPP] = { TLV_TYPE_T },
- [GSM48_IE_CLIR_INVOC] = { TLV_TYPE_T },
- [GSM48_IE_REV_C_SETUP] = { TLV_TYPE_T },
- [GSM48_IE_REPEAT_CIR] = { TLV_TYPE_T },
- [GSM48_IE_REPEAT_SEQ] = { TLV_TYPE_T },
- /* FIXME: more elements */
- },
-};
-
-static const struct value_string rr_cause_names[] = {
- { GSM48_RR_CAUSE_NORMAL, "Normal event" },
- { GSM48_RR_CAUSE_ABNORMAL_UNSPEC, "Abnormal release, unspecified" },
- { GSM48_RR_CAUSE_ABNORMAL_UNACCT, "Abnormal release, channel unacceptable" },
- { GSM48_RR_CAUSE_ABNORMAL_TIMER, "Abnormal release, timer expired" },
- { GSM48_RR_CAUSE_ABNORMAL_NOACT, "Abnormal release, no activity on radio path" },
- { GSM48_RR_CAUSE_PREMPTIVE_REL, "Preemptive release" },
- { GSM48_RR_CAUSE_HNDOVER_IMP, "Handover impossible, timing advance out of range" },
- { GSM48_RR_CAUSE_CHAN_MODE_UNACCT, "Channel mode unacceptable" },
- { GSM48_RR_CAUSE_FREQ_NOT_IMPL, "Frequency not implemented" },
- { GSM48_RR_CAUSE_CALL_CLEARED, "Call already cleared" },
- { GSM48_RR_CAUSE_SEMANT_INCORR, "Semantically incorrect message" },
- { GSM48_RR_CAUSE_INVALID_MAND_INF, "Invalid mandatory information" },
- { GSM48_RR_CAUSE_MSG_TYPE_N, "Message type non-existant or not implemented" },
- { GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT, "Message type not compatible with protocol state" },
- { GSM48_RR_CAUSE_COND_IE_ERROR, "Conditional IE error" },
- { GSM48_RR_CAUSE_NO_CELL_ALLOC_A, "No cell allocation available" },
- { GSM48_RR_CAUSE_PROT_ERROR_UNSPC, "Protocol error unspecified" },
- { 0, NULL },
-};
-
-/* FIXME: convert to value_string */
-static const char *cc_state_names[33] = {
- "NULL",
- "INITIATED",
- "MM_CONNECTION_PEND",
- "MO_CALL_PROC",
- "CALL_DELIVERED",
- "illegal state 5",
- "CALL_PRESENT",
- "CALL_RECEIVED",
- "CONNECT_REQUEST",
- "MO_TERM_CALL_CONF",
- "ACTIVE",
- "DISCONNECT_REQ",
- "DISCONNECT_IND",
- "illegal state 13",
- "illegal state 14",
- "illegal state 15",
- "illegal state 16",
- "illegal state 17",
- "illegal state 18",
- "RELEASE_REQ",
- "illegal state 20",
- "illegal state 21",
- "illegal state 22",
- "illegal state 23",
- "illegal state 24",
- "illegal state 25",
- "MO_ORIG_MODIFY",
- "MO_TERM_MODIFY",
- "CONNECT_IND",
- "illegal state 29",
- "illegal state 30",
- "illegal state 31",
-};
-
-const char *gsm48_cc_state_name(uint8_t state)
-{
- if (state < ARRAY_SIZE(cc_state_names))
- return cc_state_names[state];
-
- return "invalid";
-}
-
-static const struct value_string cc_msg_names[] = {
- { GSM48_MT_CC_ALERTING, "ALERTING" },
- { GSM48_MT_CC_CALL_PROC, "CALL_PROC" },
- { GSM48_MT_CC_PROGRESS, "PROGRESS" },
- { GSM48_MT_CC_ESTAB, "ESTAB" },
- { GSM48_MT_CC_SETUP, "SETUP" },
- { GSM48_MT_CC_ESTAB_CONF, "ESTAB_CONF" },
- { GSM48_MT_CC_CONNECT, "CONNECT" },
- { GSM48_MT_CC_CALL_CONF, "CALL_CONF" },
- { GSM48_MT_CC_START_CC, "START_CC" },
- { GSM48_MT_CC_RECALL, "RECALL" },
- { GSM48_MT_CC_EMERG_SETUP, "EMERG_SETUP" },
- { GSM48_MT_CC_CONNECT_ACK, "CONNECT_ACK" },
- { GSM48_MT_CC_USER_INFO, "USER_INFO" },
- { GSM48_MT_CC_MODIFY_REJECT, "MODIFY_REJECT" },
- { GSM48_MT_CC_MODIFY, "MODIFY" },
- { GSM48_MT_CC_HOLD, "HOLD" },
- { GSM48_MT_CC_HOLD_ACK, "HOLD_ACK" },
- { GSM48_MT_CC_HOLD_REJ, "HOLD_REJ" },
- { GSM48_MT_CC_RETR, "RETR" },
- { GSM48_MT_CC_RETR_ACK, "RETR_ACK" },
- { GSM48_MT_CC_RETR_REJ, "RETR_REJ" },
- { GSM48_MT_CC_MODIFY_COMPL, "MODIFY_COMPL" },
- { GSM48_MT_CC_DISCONNECT, "DISCONNECT" },
- { GSM48_MT_CC_RELEASE_COMPL, "RELEASE_COMPL" },
- { GSM48_MT_CC_RELEASE, "RELEASE" },
- { GSM48_MT_CC_STOP_DTMF, "STOP_DTMF" },
- { GSM48_MT_CC_STOP_DTMF_ACK, "STOP_DTMF_ACK" },
- { GSM48_MT_CC_STATUS_ENQ, "STATUS_ENQ" },
- { GSM48_MT_CC_START_DTMF, "START_DTMF" },
- { GSM48_MT_CC_START_DTMF_ACK, "START_DTMF_ACK" },
- { GSM48_MT_CC_START_DTMF_REJ, "START_DTMF_REJ" },
- { GSM48_MT_CC_CONG_CTRL, "CONG_CTRL" },
- { GSM48_MT_CC_FACILITY, "FACILITY" },
- { GSM48_MT_CC_STATUS, "STATUS" },
- { GSM48_MT_CC_NOTIFY, "NOTFIY" },
- { 0, NULL }
-};
-
-const char *gsm48_cc_msg_name(uint8_t msgtype)
-{
- return get_value_string(cc_msg_names, msgtype);
-}
-
-const char *rr_cause_name(uint8_t cause)
-{
- return get_value_string(rr_cause_names, cause);
-}
-
-static void to_bcd(uint8_t *bcd, uint16_t val)
-{
- bcd[2] = val % 10;
- val = val / 10;
- bcd[1] = val % 10;
- val = val / 10;
- bcd[0] = val % 10;
- val = val / 10;
-}
-
-void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
- uint16_t mnc, uint16_t lac)
-{
- uint8_t bcd[3];
-
- to_bcd(bcd, mcc);
- lai48->digits[0] = bcd[0] | (bcd[1] << 4);
- lai48->digits[1] = bcd[2];
-
- to_bcd(bcd, mnc);
- /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
-#if 0
- lai48->digits[1] |= bcd[2] << 4;
- lai48->digits[2] = bcd[0] | (bcd[1] << 4);
-#else
- lai48->digits[1] |= 0xf << 4;
- lai48->digits[2] = bcd[1] | (bcd[2] << 4);
-#endif
-
- lai48->lac = htons(lac);
-}
-
-int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi)
-{
- uint32_t *tptr = (uint32_t *) &buf[3];
-
- buf[0] = GSM48_IE_MOBILE_ID;
- buf[1] = GSM48_TMSI_LEN;
- buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
- *tptr = htonl(tmsi);
-
- return 7;
-}
-
-int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi)
-{
- unsigned int length = strlen(imsi), i, off = 0;
- uint8_t odd = (length & 0x1) == 1;
-
- buf[0] = GSM48_IE_MOBILE_ID;
- buf[2] = char2bcd(imsi[0]) << 4 | GSM_MI_TYPE_IMSI | (odd << 3);
-
- /* if the length is even we will fill half of the last octet */
- if (odd)
- buf[1] = (length + 1) >> 1;
- else
- buf[1] = (length + 2) >> 1;
-
- for (i = 1; i < buf[1]; ++i) {
- uint8_t lower, upper;
-
- lower = char2bcd(imsi[++off]);
- if (!odd && off + 1 == length)
- upper = 0x0f;
- else
- upper = char2bcd(imsi[++off]) & 0x0f;
-
- buf[2 + i] = (upper << 4) | lower;
- }
-
- return 2 + buf[1];
-}
-
-/* Convert Mobile Identity (10.5.1.4) to string */
-int gsm48_mi_to_string(char *string, const int str_len, const uint8_t *mi,
- const int mi_len)
-{
- int i;
- uint8_t mi_type;
- char *str_cur = string;
- uint32_t tmsi;
-
- mi_type = mi[0] & GSM_MI_TYPE_MASK;
-
- switch (mi_type) {
- case GSM_MI_TYPE_NONE:
- break;
- case GSM_MI_TYPE_TMSI:
- /* Table 10.5.4.3, reverse generate_mid_from_tmsi */
- if (mi_len == GSM48_TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
- memcpy(&tmsi, &mi[1], 4);
- tmsi = ntohl(tmsi);
- return snprintf(string, str_len, "%u", tmsi);
- }
- break;
- case GSM_MI_TYPE_IMSI:
- case GSM_MI_TYPE_IMEI:
- case GSM_MI_TYPE_IMEISV:
- *str_cur++ = bcd2char(mi[0] >> 4);
-
- for (i = 1; i < mi_len; i++) {
- if (str_cur + 2 >= string + str_len)
- return str_cur - string;
- *str_cur++ = bcd2char(mi[i] & 0xf);
- /* skip last nibble in last input byte when GSM_EVEN */
- if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
- *str_cur++ = bcd2char(mi[i] >> 4);
- }
- break;
- default:
- break;
- }
- *str_cur++ = '\0';
-
- return str_cur - string;
-}
-
-void gsm48_parse_ra(struct gprs_ra_id *raid, const uint8_t *buf)
-{
- raid->mcc = (buf[0] & 0xf) * 100;
- raid->mcc += (buf[0] >> 4) * 10;
- raid->mcc += (buf[1] & 0xf) * 1;
-
- /* I wonder who came up with the stupidity of encoding the MNC
- * differently depending on how many digits its decimal number has! */
- if ((buf[1] >> 4) == 0xf) {
- raid->mnc = (buf[2] & 0xf) * 10;
- raid->mnc += (buf[2] >> 4) * 1;
- } else {
- raid->mnc = (buf[2] & 0xf) * 100;
- raid->mnc += (buf[2] >> 4) * 10;
- raid->mnc += (buf[1] >> 4) * 1;
- }
-
- raid->lac = ntohs(*(uint16_t *)(buf + 3));
- raid->rac = buf[5];
-}
-
-int gsm48_construct_ra(uint8_t *buf, const struct gprs_ra_id *raid)
-{
- uint16_t mcc = raid->mcc;
- uint16_t mnc = raid->mnc;
-
- buf[0] = ((mcc / 100) % 10) | (((mcc / 10) % 10) << 4);
- buf[1] = (mcc % 10);
-
- /* I wonder who came up with the stupidity of encoding the MNC
- * differently depending on how many digits its decimal number has! */
- if (mnc < 100) {
- buf[1] |= 0xf0;
- buf[2] = ((mnc / 10) % 10) | ((mnc % 10) << 4);
- } else {
- buf[1] |= (mnc % 10) << 4;
- buf[2] = ((mnc / 100) % 10) | (((mcc / 10) % 10) << 4);
- }
-
- *(uint16_t *)(buf+3) = htons(raid->lac);
-
- buf[5] = raid->rac;
-
- return 6;
-}
diff --git a/libosmocore/src/gsm48_ie.c b/libosmocore/src/gsm48_ie.c
deleted file mode 100644
index 3c2a1f7..0000000
--- a/libosmocore/src/gsm48_ie.c
+++ /dev/null
@@ -1,659 +0,0 @@
-/* GSM Mobile Radio Interface Layer 3 messages
- * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
-
-/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009-2010 by Andreas Eversberg
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-
-#include <stdint.h>
-#include <string.h>
-#include <errno.h>
-
-#include <osmocore/utils.h>
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.h>
-#include <osmocore/mncc.h>
-#include <osmocore/protocol/gsm_04_08.h>
-
-static const char bcd_num_digits[] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', '*', '#', 'a', 'b', 'c', '\0'
-};
-
-/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
-int gsm48_decode_bcd_number(char *output, int output_len,
- const uint8_t *bcd_lv, int h_len)
-{
- uint8_t in_len = bcd_lv[0];
- int i;
-
- for (i = 1 + h_len; i <= in_len; i++) {
- /* lower nibble */
- output_len--;
- if (output_len <= 1)
- break;
- *output++ = bcd_num_digits[bcd_lv[i] & 0xf];
-
- /* higher nibble */
- output_len--;
- if (output_len <= 1)
- break;
- *output++ = bcd_num_digits[bcd_lv[i] >> 4];
- }
- if (output_len >= 1)
- *output++ = '\0';
-
- return 0;
-}
-
-/* convert a single ASCII character to call-control BCD */
-static int asc_to_bcd(const char asc)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bcd_num_digits); i++) {
- if (bcd_num_digits[i] == asc)
- return i;
- }
- return -EINVAL;
-}
-
-/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
-int gsm48_encode_bcd_number(uint8_t *bcd_lv, uint8_t max_len,
- int h_len, const char *input)
-{
- int in_len = strlen(input);
- int i;
- uint8_t *bcd_cur = bcd_lv + 1 + h_len;
-
- /* two digits per byte, plus type byte */
- bcd_lv[0] = in_len/2 + h_len;
- if (in_len % 2)
- bcd_lv[0]++;
-
- if (bcd_lv[0] > max_len)
- return -EIO;
-
- for (i = 0; i < in_len; i++) {
- int rc = asc_to_bcd(input[i]);
- if (rc < 0)
- return rc;
- if (i % 2 == 0)
- *bcd_cur = rc;
- else
- *bcd_cur++ |= (rc << 4);
- }
- /* append padding nibble in case of odd length */
- if (i % 2)
- *bcd_cur++ |= 0xf0;
-
- /* return how many bytes we used */
- return (bcd_cur - bcd_lv);
-}
-
-/* decode 'bearer capability' */
-int gsm48_decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
- const uint8_t *lv)
-{
- uint8_t in_len = lv[0];
- int i, s;
-
- if (in_len < 1)
- return -EINVAL;
-
- bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */
-
- /* octet 3 */
- bcap->transfer = lv[1] & 0x07;
- bcap->mode = (lv[1] & 0x08) >> 3;
- bcap->coding = (lv[1] & 0x10) >> 4;
- bcap->radio = (lv[1] & 0x60) >> 5;
-
- if (bcap->transfer == GSM_MNCC_BCAP_SPEECH) {
- i = 1;
- s = 0;
- while(!(lv[i] & 0x80)) {
- i++; /* octet 3a etc */
- if (in_len < i)
- return 0;
- bcap->speech_ver[s++] = lv[i] & 0x0f;
- bcap->speech_ver[s] = -1; /* end of list */
- if (i == 2) /* octet 3a */
- bcap->speech_ctm = (lv[i] & 0x20) >> 5;
- if (s == 7) /* maximum speech versions + end of list */
- return 0;
- }
- } else {
- i = 1;
- while (!(lv[i] & 0x80)) {
- i++; /* octet 3a etc */
- if (in_len < i)
- return 0;
- /* ignore them */
- }
- /* FIXME: implement OCTET 4+ parsing */
- }
-
- return 0;
-}
-
-/* encode 'bearer capability' */
-int gsm48_encode_bearer_cap(struct msgb *msg, int lv_only,
- const struct gsm_mncc_bearer_cap *bcap)
-{
- uint8_t lv[32 + 1];
- int i = 1, s;
-
- lv[1] = bcap->transfer;
- lv[1] |= bcap->mode << 3;
- lv[1] |= bcap->coding << 4;
- lv[1] |= bcap->radio << 5;
-
- if (bcap->transfer == GSM_MNCC_BCAP_SPEECH) {
- for (s = 0; bcap->speech_ver[s] >= 0; s++) {
- i++; /* octet 3a etc */
- lv[i] = bcap->speech_ver[s];
- if (i == 2) /* octet 3a */
- lv[i] |= bcap->speech_ctm << 5;
- }
- lv[i] |= 0x80; /* last IE of octet 3 etc */
- } else {
- /* FIXME: implement OCTET 4+ encoding */
- }
-
- lv[0] = i;
- if (lv_only)
- msgb_lv_put(msg, lv[0], lv+1);
- else
- msgb_tlv_put(msg, GSM48_IE_BEARER_CAP, lv[0], lv+1);
-
- return 0;
-}
-
-/* decode 'call control cap' */
-int gsm48_decode_cccap(struct gsm_mncc_cccap *ccap, const uint8_t *lv)
-{
- uint8_t in_len = lv[0];
-
- if (in_len < 1)
- return -EINVAL;
-
- /* octet 3 */
- ccap->dtmf = lv[1] & 0x01;
- ccap->pcp = (lv[1] & 0x02) >> 1;
-
- return 0;
-}
-
-/* encode 'call control cap' */
-int gsm48_encode_cccap(struct msgb *msg,
- const struct gsm_mncc_cccap *ccap)
-{
- uint8_t lv[2];
-
- lv[0] = 1;
- lv[1] = 0;
- if (ccap->dtmf)
- lv [1] |= 0x01;
- if (ccap->pcp)
- lv [1] |= 0x02;
-
- msgb_tlv_put(msg, GSM48_IE_CC_CAP, lv[0], lv+1);
-
- return 0;
-}
-
-/* decode 'called party BCD number' */
-int gsm48_decode_called(struct gsm_mncc_number *called,
- const uint8_t *lv)
-{
- uint8_t in_len = lv[0];
-
- if (in_len < 1)
- return -EINVAL;
-
- /* octet 3 */
- called->plan = lv[1] & 0x0f;
- called->type = (lv[1] & 0x70) >> 4;
-
- /* octet 4..N */
- gsm48_decode_bcd_number(called->number, sizeof(called->number), lv, 1);
-
- return 0;
-}
-
-/* encode 'called party BCD number' */
-int gsm48_encode_called(struct msgb *msg,
- const struct gsm_mncc_number *called)
-{
- uint8_t lv[18];
- int ret;
-
- /* octet 3 */
- lv[1] = called->plan;
- lv[1] |= called->type << 4;
-
- /* octet 4..N, octet 2 */
- ret = gsm48_encode_bcd_number(lv, sizeof(lv), 1, called->number);
- if (ret < 0)
- return ret;
-
- msgb_tlv_put(msg, GSM48_IE_CALLED_BCD, lv[0], lv+1);
-
- return 0;
-}
-
-/* decode callerid of various IEs */
-int gsm48_decode_callerid(struct gsm_mncc_number *callerid,
- const uint8_t *lv)
-{
- uint8_t in_len = lv[0];
- int i = 1;
-
- if (in_len < 1)
- return -EINVAL;
-
- /* octet 3 */
- callerid->plan = lv[1] & 0x0f;
- callerid->type = (lv[1] & 0x70) >> 4;
-
- /* octet 3a */
- if (!(lv[1] & 0x80)) {
- callerid->screen = lv[2] & 0x03;
- callerid->present = (lv[2] & 0x60) >> 5;
- i = 2;
- }
-
- /* octet 4..N */
- gsm48_decode_bcd_number(callerid->number, sizeof(callerid->number), lv, i);
-
- return 0;
-}
-
-/* encode callerid of various IEs */
-int gsm48_encode_callerid(struct msgb *msg, int ie, int max_len,
- const struct gsm_mncc_number *callerid)
-{
- uint8_t lv[max_len - 1];
- int h_len = 1;
- int ret;
-
- /* octet 3 */
- lv[1] = callerid->plan;
- lv[1] |= callerid->type << 4;
-
- if (callerid->present || callerid->screen) {
- /* octet 3a */
- lv[2] = callerid->screen;
- lv[2] |= callerid->present << 5;
- lv[2] |= 0x80;
- h_len++;
- } else
- lv[1] |= 0x80;
-
- /* octet 4..N, octet 2 */
- ret = gsm48_encode_bcd_number(lv, sizeof(lv), h_len, callerid->number);
- if (ret < 0)
- return ret;
-
- msgb_tlv_put(msg, ie, lv[0], lv+1);
-
- return 0;
-}
-
-/* decode 'cause' */
-int gsm48_decode_cause(struct gsm_mncc_cause *cause,
- const uint8_t *lv)
-{
- uint8_t in_len = lv[0];
- int i;
-
- if (in_len < 2)
- return -EINVAL;
-
- cause->diag_len = 0;
-
- /* octet 3 */
- cause->location = lv[1] & 0x0f;
- cause->coding = (lv[1] & 0x60) >> 5;
-
- i = 1;
- if (!(lv[i] & 0x80)) {
- i++; /* octet 3a */
- if (in_len < i+1)
- return 0;
- cause->rec = 1;
- cause->rec_val = lv[i] & 0x7f;
- }
- i++;
-
- /* octet 4 */
- cause->value = lv[i] & 0x7f;
- i++;
-
- if (in_len < i) /* no diag */
- return 0;
-
- if (in_len - (i-1) > 32) /* maximum 32 octets */
- return 0;
-
- /* octet 5-N */
- memcpy(cause->diag, lv + i, in_len - (i-1));
- cause->diag_len = in_len - (i-1);
-
- return 0;
-}
-
-/* encode 'cause' */
-int gsm48_encode_cause(struct msgb *msg, int lv_only,
- const struct gsm_mncc_cause *cause)
-{
- uint8_t lv[32+4];
- int i;
-
- if (cause->diag_len > 32)
- return -EINVAL;
-
- /* octet 3 */
- lv[1] = cause->location;
- lv[1] |= cause->coding << 5;
-
- i = 1;
- if (cause->rec) {
- i++; /* octet 3a */
- lv[i] = cause->rec_val;
- }
- lv[i] |= 0x80; /* end of octet 3 */
-
- /* octet 4 */
- i++;
- lv[i] = 0x80 | cause->value;
-
- /* octet 5-N */
- if (cause->diag_len) {
- memcpy(lv + i, cause->diag, cause->diag_len);
- i += cause->diag_len;
- }
-
- lv[0] = i;
- if (lv_only)
- msgb_lv_put(msg, lv[0], lv+1);
- else
- msgb_tlv_put(msg, GSM48_IE_CAUSE, lv[0], lv+1);
-
- return 0;
-}
-
-/* decode 'calling number' */
-int gsm48_decode_calling(struct gsm_mncc_number *calling,
- const uint8_t *lv)
-{
- return gsm48_decode_callerid(calling, lv);
-}
-
-/* encode 'calling number' */
-int gsm48_encode_calling(struct msgb *msg,
- const struct gsm_mncc_number *calling)
-{
- return gsm48_encode_callerid(msg, GSM48_IE_CALLING_BCD, 14, calling);
-}
-
-/* decode 'connected number' */
-int gsm48_decode_connected(struct gsm_mncc_number *connected,
- const uint8_t *lv)
-{
- return gsm48_decode_callerid(connected, lv);
-}
-
-/* encode 'connected number' */
-int gsm48_encode_connected(struct msgb *msg,
- const struct gsm_mncc_number *connected)
-{
- return gsm48_encode_callerid(msg, GSM48_IE_CONN_BCD, 14, connected);
-}
-
-/* decode 'redirecting number' */
-int gsm48_decode_redirecting(struct gsm_mncc_number *redirecting,
- const uint8_t *lv)
-{
- return gsm48_decode_callerid(redirecting, lv);
-}
-
-/* encode 'redirecting number' */
-int gsm48_encode_redirecting(struct msgb *msg,
- const struct gsm_mncc_number *redirecting)
-{
- return gsm48_encode_callerid(msg, GSM48_IE_REDIR_BCD, 19, redirecting);
-}
-
-/* decode 'facility' */
-int gsm48_decode_facility(struct gsm_mncc_facility *facility,
- const uint8_t *lv)
-{
- uint8_t in_len = lv[0];
-
- if (in_len < 1)
- return -EINVAL;
-
- if (in_len > sizeof(facility->info))
- return -EINVAL;
-
- memcpy(facility->info, lv+1, in_len);
- facility->len = in_len;
-
- return 0;
-}
-
-/* encode 'facility' */
-int gsm48_encode_facility(struct msgb *msg, int lv_only,
- const struct gsm_mncc_facility *facility)
-{
- uint8_t lv[GSM_MAX_FACILITY + 1];
-
- if (facility->len < 1 || facility->len > GSM_MAX_FACILITY)
- return -EINVAL;
-
- memcpy(lv+1, facility->info, facility->len);
- lv[0] = facility->len;
- if (lv_only)
- msgb_lv_put(msg, lv[0], lv+1);
- else
- msgb_tlv_put(msg, GSM48_IE_FACILITY, lv[0], lv+1);
-
- return 0;
-}
-
-/* decode 'notify' */
-int gsm48_decode_notify(int *notify, const uint8_t *v)
-{
- *notify = v[0] & 0x7f;
-
- return 0;
-}
-
-/* encode 'notify' */
-int gsm48_encode_notify(struct msgb *msg, int notify)
-{
- msgb_v_put(msg, notify | 0x80);
-
- return 0;
-}
-
-/* decode 'signal' */
-int gsm48_decode_signal(int *signal, const uint8_t *v)
-{
- *signal = v[0];
-
- return 0;
-}
-
-/* encode 'signal' */
-int gsm48_encode_signal(struct msgb *msg, int signal)
-{
- msgb_tv_put(msg, GSM48_IE_SIGNAL, signal);
-
- return 0;
-}
-
-/* decode 'keypad' */
-int gsm48_decode_keypad(int *keypad, const uint8_t *lv)
-{
- uint8_t in_len = lv[0];
-
- if (in_len < 1)
- return -EINVAL;
-
- *keypad = lv[1] & 0x7f;
-
- return 0;
-}
-
-/* encode 'keypad' */
-int gsm48_encode_keypad(struct msgb *msg, int keypad)
-{
- msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad);
-
- return 0;
-}
-
-/* decode 'progress' */
-int gsm48_decode_progress(struct gsm_mncc_progress *progress,
- const uint8_t *lv)
-{
- uint8_t in_len = lv[0];
-
- if (in_len < 2)
- return -EINVAL;
-
- progress->coding = (lv[1] & 0x60) >> 5;
- progress->location = lv[1] & 0x0f;
- progress->descr = lv[2] & 0x7f;
-
- return 0;
-}
-
-/* encode 'progress' */
-int gsm48_encode_progress(struct msgb *msg, int lv_only,
- const struct gsm_mncc_progress *p)
-{
- uint8_t lv[3];
-
- lv[0] = 2;
- lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf);
- lv[2] = 0x80 | (p->descr & 0x7f);
- if (lv_only)
- msgb_lv_put(msg, lv[0], lv+1);
- else
- msgb_tlv_put(msg, GSM48_IE_PROGR_IND, lv[0], lv+1);
-
- return 0;
-}
-
-/* decode 'user-user' */
-int gsm48_decode_useruser(struct gsm_mncc_useruser *uu,
- const uint8_t *lv)
-{
- uint8_t in_len = lv[0];
- char *info = uu->info;
- int info_len = sizeof(uu->info);
- int i;
-
- if (in_len < 1)
- return -EINVAL;
-
- uu->proto = lv[1];
-
- for (i = 2; i <= in_len; i++) {
- info_len--;
- if (info_len <= 1)
- break;
- *info++ = lv[i];
- }
- if (info_len >= 1)
- *info++ = '\0';
-
- return 0;
-}
-
-/* encode 'useruser' */
-int gsm48_encode_useruser(struct msgb *msg, int lv_only,
- const struct gsm_mncc_useruser *uu)
-{
- uint8_t lv[GSM_MAX_USERUSER + 2];
-
- if (strlen(uu->info) > GSM_MAX_USERUSER)
- return -EINVAL;
-
- lv[0] = 1 + strlen(uu->info);
- lv[1] = uu->proto;
- memcpy(lv + 2, uu->info, strlen(uu->info));
- if (lv_only)
- msgb_lv_put(msg, lv[0], lv+1);
- else
- msgb_tlv_put(msg, GSM48_IE_USER_USER, lv[0], lv+1);
-
- return 0;
-}
-
-/* decode 'ss version' */
-int gsm48_decode_ssversion(struct gsm_mncc_ssversion *ssv,
- const uint8_t *lv)
-{
- uint8_t in_len = lv[0];
-
- if (in_len < 1 || in_len < sizeof(ssv->info))
- return -EINVAL;
-
- memcpy(ssv->info, lv + 1, in_len);
- ssv->len = in_len;
-
- return 0;
-}
-
-/* encode 'ss version' */
-int gsm48_encode_ssversion(struct msgb *msg,
- const struct gsm_mncc_ssversion *ssv)
-{
- uint8_t lv[GSM_MAX_SSVERSION + 1];
-
- if (ssv->len > GSM_MAX_SSVERSION)
- return -EINVAL;
-
- lv[0] = ssv->len;
- memcpy(lv + 1, ssv->info, ssv->len);
- msgb_tlv_put(msg, GSM48_IE_SS_VERS, lv[0], lv+1);
-
- return 0;
-}
-
-/* decode 'more data' does not require a function, because it has no value */
-
-/* encode 'more data' */
-int gsm48_encode_more(struct msgb *msg)
-{
- uint8_t *ie;
-
- ie = msgb_put(msg, 1);
- ie[0] = GSM48_IE_MORE_DATA;
-
- return 0;
-}
-
diff --git a/libosmocore/src/gsm_utils.c b/libosmocore/src/gsm_utils.c
deleted file mode 100644
index b392fd3..0000000
--- a/libosmocore/src/gsm_utils.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
- * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-//#include <openbsc/gsm_data.h>
-#include <osmocore/utils.h>
-#include <osmocore/gsm_utils.h>
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <ctype.h>
-
-#include "../config.h"
-
-/* GSM 03.38 6.2.1 Charachter packing */
-int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t length)
-{
- int i = 0;
- int l = 0;
-
- /* FIXME: We need to account for user data headers here */
- i += l;
- for (; i < length; i ++)
- *(text ++) =
- ((user_data[(i * 7 + 7) >> 3] <<
- (7 - ((i * 7 + 7) & 7))) |
- (user_data[(i * 7) >> 3] >>
- ((i * 7) & 7))) & 0x7f;
- *text = '\0';
-
- return i - l;
-}
-
-
-/* GSM 03.38 6.2.1 Charachter packing */
-int gsm_7bit_encode(uint8_t *result, const char *data)
-{
- int i,j = 0;
- unsigned char ch1, ch2;
- int shift = 0;
-
- for ( i=0; i<strlen(data); i++ ) {
-
- ch1 = data[i] & 0x7F;
- ch1 = ch1 >> shift;
- ch2 = data[(i+1)] & 0x7F;
- ch2 = ch2 << (7-shift);
-
- ch1 = ch1 | ch2;
-
- result[j++] = ch1;
-
- shift++;
-
- if ((shift == 7) && (i+1<strlen(data))) {
- shift = 0;
- i++;
- }
- }
-
- return i;
-}
-
-/* determine power control level for given dBm value, as indicated
- * by the tables in chapter 4.1.1 of GSM TS 05.05 */
-int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
-{
- switch (band) {
- case GSM_BAND_450:
- case GSM_BAND_480:
- case GSM_BAND_750:
- case GSM_BAND_900:
- case GSM_BAND_810:
- case GSM_BAND_850:
- if (dbm >= 39)
- return 0;
- else if (dbm < 5)
- return 19;
- else {
- /* we are guaranteed to have (5 <= dbm < 39) */
- return 2 + ((39 - dbm) / 2);
- }
- break;
- case GSM_BAND_1800:
- if (dbm >= 36)
- return 29;
- else if (dbm >= 34)
- return 30;
- else if (dbm >= 32)
- return 31;
- else if (dbm == 31)
- return 0;
- else {
- /* we are guaranteed to have (0 <= dbm < 31) */
- return (30 - dbm) / 2;
- }
- break;
- case GSM_BAND_1900:
- if (dbm >= 33)
- return 30;
- else if (dbm >= 32)
- return 31;
- else if (dbm == 31)
- return 0;
- else {
- /* we are guaranteed to have (0 <= dbm < 31) */
- return (30 - dbm) / 2;
- }
- break;
- }
- return -EINVAL;
-}
-
-int ms_pwr_dbm(enum gsm_band band, uint8_t lvl)
-{
- lvl &= 0x1f;
-
- switch (band) {
- case GSM_BAND_450:
- case GSM_BAND_480:
- case GSM_BAND_750:
- case GSM_BAND_900:
- case GSM_BAND_810:
- case GSM_BAND_850:
- if (lvl < 2)
- return 39;
- else if (lvl < 20)
- return 39 - ((lvl - 2) * 2) ;
- else
- return 5;
- break;
- case GSM_BAND_1800:
- if (lvl < 16)
- return 30 - (lvl * 2);
- else if (lvl < 29)
- return 0;
- else
- return 36 - ((lvl - 29) * 2);
- break;
- case GSM_BAND_1900:
- if (lvl < 16)
- return 30 - (lvl * 2);
- else if (lvl < 30)
- return -EINVAL;
- else
- return 33 - (lvl - 30);
- break;
- }
- return -EINVAL;
-}
-
-/* According to TS 08.05 Chapter 8.1.4 */
-int rxlev2dbm(uint8_t rxlev)
-{
- if (rxlev > 63)
- rxlev = 63;
-
- return -110 + rxlev;
-}
-
-/* According to TS 08.05 Chapter 8.1.4 */
-uint8_t dbm2rxlev(int dbm)
-{
- int rxlev = dbm + 110;
-
- if (rxlev > 63)
- rxlev = 63;
- else if (rxlev < 0)
- rxlev = 0;
-
- return rxlev;
-}
-
-const char *gsm_band_name(enum gsm_band band)
-{
- switch (band) {
- case GSM_BAND_450:
- return "GSM450";
- case GSM_BAND_480:
- return "GSM450";
- case GSM_BAND_750:
- return "GSM750";
- case GSM_BAND_810:
- return "GSM810";
- case GSM_BAND_850:
- return "GSM850";
- case GSM_BAND_900:
- return "GSM900";
- case GSM_BAND_1800:
- return "DCS1800";
- case GSM_BAND_1900:
- return "PCS1900";
- }
- return "invalid";
-}
-
-enum gsm_band gsm_band_parse(const char* mhz)
-{
- while (*mhz && !isdigit(*mhz))
- mhz++;
-
- if (*mhz == '\0')
- return -EINVAL;
-
- switch (strtol(mhz, NULL, 10)) {
- case 450:
- return GSM_BAND_450;
- case 480:
- return GSM_BAND_480;
- case 750:
- return GSM_BAND_750;
- case 810:
- return GSM_BAND_810;
- case 850:
- return GSM_BAND_850;
- case 900:
- return GSM_BAND_900;
- case 1800:
- return GSM_BAND_1800;
- case 1900:
- return GSM_BAND_1900;
- default:
- return -EINVAL;
- }
-}
-
-
-#ifdef HAVE_EXECINFO_H
-#include <execinfo.h>
-void generate_backtrace()
-{
- int i, nptrs;
- void *buffer[100];
- char **strings;
-
- nptrs = backtrace(buffer, ARRAY_SIZE(buffer));
- printf("backtrace() returned %d addresses\n", nptrs);
-
- strings = backtrace_symbols(buffer, nptrs);
- if (!strings)
- return;
-
- for (i = 1; i < nptrs; i++)
- printf("%s\n", strings[i]);
-
- free(strings);
-}
-#endif
-
-enum gsm_band gsm_arfcn2band(uint16_t arfcn)
-{
- if (arfcn & ARFCN_PCS)
- return GSM_BAND_1900;
- else if (arfcn <= 124)
- return GSM_BAND_900;
- else if (arfcn >= 955 && arfcn <= 1023)
- return GSM_BAND_900;
- else if (arfcn >= 128 && arfcn <= 251)
- return GSM_BAND_850;
- else if (arfcn >= 512 && arfcn <= 885)
- return GSM_BAND_1800;
- else if (arfcn >= 259 && arfcn <= 293)
- return GSM_BAND_450;
- else if (arfcn >= 306 && arfcn <= 340)
- return GSM_BAND_480;
- else if (arfcn >= 350 && arfcn <= 425)
- return GSM_BAND_810;
- else if (arfcn >= 438 && arfcn <= 511)
- return GSM_BAND_750;
- else
- return GSM_BAND_1800;
-}
-
-/* Convert an ARFCN to the frequency in MHz * 10 */
-uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink)
-{
- uint16_t freq10_ul;
- uint16_t freq10_dl;
-
- if (arfcn & ARFCN_PCS) {
- /* DCS 1900 */
- arfcn &= ~ARFCN_PCS;
- freq10_ul = 18502 + 2 * (arfcn-512);
- freq10_dl = freq10_ul + 800;
- } else if (arfcn <= 124) {
- /* Primary GSM + ARFCN 0 of E-GSM */
- freq10_ul = 8900 + 2 * arfcn;
- freq10_dl = freq10_ul + 450;
- } else if (arfcn >= 955 && arfcn <= 1023) {
- /* E-GSM and R-GSM */
- freq10_ul = 8900 + 2 * (arfcn - 1024);
- freq10_dl = freq10_ul + 450;
- } else if (arfcn >= 128 && arfcn <= 251) {
- /* GSM 850 */
- freq10_ul = 8242 + 2 * (arfcn - 128);
- freq10_dl = freq10_ul + 450;
- } else if (arfcn >= 512 && arfcn <= 885) {
- /* DCS 1800 */
- freq10_ul = 17102 + 2 * (arfcn - 512);
- freq10_dl = freq10_ul + 950;
- } else if (arfcn >= 259 && arfcn <= 293) {
- /* GSM 450 */
- freq10_ul = 4506 + 2 * (arfcn - 259);
- freq10_dl = freq10_ul + 100;
- } else if (arfcn >= 306 && arfcn <= 340) {
- /* GSM 480 */
- freq10_ul = 4790 + 2 * (arfcn - 306);
- freq10_dl = freq10_ul + 100;
- } else if (arfcn >= 350 && arfcn <= 425) {
- /* GSM 810 */
- freq10_ul = 8060 + 2 * (arfcn - 350);
- freq10_dl = freq10_ul + 450;
- } else if (arfcn >= 438 && arfcn <= 511) {
- /* GSM 750 */
- freq10_ul = 7472 + 2 * (arfcn - 438);
- freq10_dl = freq10_ul + 300;
- } else
- return 0xffff;
-
- if (uplink)
- return freq10_ul;
- else
- return freq10_dl;
-}
-
-void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn)
-{
- time->fn = fn;
- time->t1 = time->fn / (26*51);
- time->t2 = time->fn % 26;
- time->t3 = time->fn % 51;
- time->tc = (time->fn / 51) % 8;
-}
-
-uint32_t gsm_gsmtime2fn(struct gsm_time *time)
-{
- /* TS 05.02 Chapter 4.3.3 TDMA frame number */
- return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1));
-}
-
-/* TS 03.03 Chapter 2.6 */
-int gprs_tlli_type(uint32_t tlli)
-{
- if ((tlli & 0xc0000000) == 0xc0000000)
- return TLLI_LOCAL;
- else if ((tlli & 0xc0000000) == 0x80000000)
- return TLLI_FOREIGN;
- else if ((tlli & 0xf8000000) == 0x78000000)
- return TLLI_RANDOM;
- else if ((tlli & 0xf8000000) == 0x70000000)
- return TLLI_AUXILIARY;
-
- return TLLI_RESERVED;
-}
diff --git a/libosmocore/src/logging.c b/libosmocore/src/logging.c
deleted file mode 100644
index e72a6e2..0000000
--- a/libosmocore/src/logging.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/* Debugging/Logging support code */
-
-/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2008 by Holger Hans Peter Freyther <zecke@selfish.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include "../config.h"
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#include <time.h>
-#include <errno.h>
-
-#include <osmocore/talloc.h>
-#include <osmocore/utils.h>
-#include <osmocore/logging.h>
-
-static const struct log_info *log_info;
-
-static struct log_context log_context;
-static void *tall_log_ctx = NULL;
-static LLIST_HEAD(target_list);
-
-static const struct value_string loglevel_strs[] = {
- { 0, "EVERYTHING" },
- { LOGL_DEBUG, "DEBUG" },
- { LOGL_INFO, "INFO" },
- { LOGL_NOTICE, "NOTICE" },
- { LOGL_ERROR, "ERROR" },
- { LOGL_FATAL, "FATAL" },
- { 0, NULL },
-};
-
-int log_parse_level(const char *lvl)
-{
- return get_string_value(loglevel_strs, lvl);
-}
-
-const char *log_level_str(unsigned int lvl)
-{
- return get_value_string(loglevel_strs, lvl);
-}
-
-int log_parse_category(const char *category)
-{
- int i;
-
- for (i = 0; i < log_info->num_cat; ++i) {
- if (!strcasecmp(log_info->cat[i].name+1, category))
- return i;
- }
-
- return -EINVAL;
-}
-
-/*
- * Parse the category mask.
- * The format can be this: category1:category2:category3
- * or category1,2:category2,3:...
- */
-void log_parse_category_mask(struct log_target* target, const char *_mask)
-{
- int i = 0;
- char *mask = strdup(_mask);
- char *category_token = NULL;
-
- /* Disable everything to enable it afterwards */
- for (i = 0; i < ARRAY_SIZE(target->categories); ++i)
- target->categories[i].enabled = 0;
-
- category_token = strtok(mask, ":");
- do {
- for (i = 0; i < log_info->num_cat; ++i) {
- char* colon = strstr(category_token, ",");
- int length = strlen(category_token);
-
- if (colon)
- length = colon - category_token;
-
- if (strncasecmp(log_info->cat[i].name, category_token,
- length) == 0) {
- int level = 0;
-
- if (colon)
- level = atoi(colon+1);
-
- target->categories[i].enabled = 1;
- target->categories[i].loglevel = level;
- }
- }
- } while ((category_token = strtok(NULL, ":")));
-
- free(mask);
-}
-
-static const char* color(int subsys)
-{
- if (subsys < log_info->num_cat)
- return log_info->cat[subsys].color;
-
- return NULL;
-}
-
-static void _output(struct log_target *target, unsigned int subsys,
- char *file, int line, int cont, const char *format,
- va_list ap)
-{
- char col[30];
- char sub[30];
- char tim[30];
- char buf[4096];
- char final[4096];
-
- /* prepare the data */
- col[0] = '\0';
- sub[0] = '\0';
- tim[0] = '\0';
- buf[0] = '\0';
-
- /* are we using color */
- if (target->use_color) {
- const char *c = color(subsys);
- if (c) {
- snprintf(col, sizeof(col), "%s", color(subsys));
- col[sizeof(col)-1] = '\0';
- }
- }
- vsnprintf(buf, sizeof(buf), format, ap);
- buf[sizeof(buf)-1] = '\0';
-
- if (!cont) {
- if (target->print_timestamp) {
- char *timestr;
- time_t tm;
- tm = time(NULL);
- timestr = ctime(&tm);
- timestr[strlen(timestr)-1] = '\0';
- snprintf(tim, sizeof(tim), "%s ", timestr);
- tim[sizeof(tim)-1] = '\0';
- }
- snprintf(sub, sizeof(sub), "<%4.4x> %s:%d ", subsys, file, line);
- sub[sizeof(sub)-1] = '\0';
- }
-
- snprintf(final, sizeof(final), "%s%s%s%s\033[0;m", col, tim, sub, buf);
- final[sizeof(final)-1] = '\0';
- target->output(target, final);
-}
-
-
-static void _logp(unsigned int subsys, int level, char *file, int line,
- int cont, const char *format, va_list ap)
-{
- struct log_target *tar;
-
- llist_for_each_entry(tar, &target_list, entry) {
- struct log_category *category;
- int output = 0;
-
- category = &tar->categories[subsys];
- /* subsystem is not supposed to be logged */
- if (!category->enabled)
- continue;
-
- /* Check the global log level */
- if (tar->loglevel != 0 && level < tar->loglevel)
- continue;
-
- /* Check the category log level */
- if (tar->loglevel == 0 && category->loglevel != 0 &&
- level < category->loglevel)
- continue;
-
- /* Apply filters here... if that becomes messy we will
- * need to put filters in a list and each filter will
- * say stop, continue, output */
- if ((tar->filter_map & LOG_FILTER_ALL) != 0)
- output = 1;
- else if (log_info->filter_fn)
- output = log_info->filter_fn(&log_context,
- tar);
-
- if (output) {
- /* FIXME: copying the va_list is an ugly
- * workaround against a bug hidden somewhere in
- * _output. If we do not copy here, the first
- * call to _output() will corrupt the va_list
- * contents, and any further _output() calls
- * with the same va_list will segfault */
- va_list bp;
- va_copy(bp, ap);
- _output(tar, subsys, file, line, cont, format, bp);
- va_end(bp);
- }
- }
-}
-
-void logp(unsigned int subsys, char *file, int line, int cont,
- const char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- _logp(subsys, LOGL_DEBUG, file, line, cont, format, ap);
- va_end(ap);
-}
-
-void logp2(unsigned int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- _logp(subsys, level, file, line, cont, format, ap);
- va_end(ap);
-}
-
-static char hexd_buff[4096];
-
-char *hexdump(const unsigned char *buf, int len)
-{
- int i;
- char *cur = hexd_buff;
-
- hexd_buff[0] = 0;
- for (i = 0; i < len; i++) {
- int len_remain = sizeof(hexd_buff) - (cur - hexd_buff);
- int rc = snprintf(cur, len_remain, "%02x ", buf[i]);
- if (rc <= 0)
- break;
- cur += rc;
- }
- hexd_buff[sizeof(hexd_buff)-1] = 0;
- return hexd_buff;
-}
-
-void log_add_target(struct log_target *target)
-{
- llist_add_tail(&target->entry, &target_list);
-}
-
-void log_del_target(struct log_target *target)
-{
- llist_del(&target->entry);
-}
-
-void log_reset_context(void)
-{
- memset(&log_context, 0, sizeof(log_context));
-}
-
-int log_set_context(uint8_t ctx_nr, void *value)
-{
- if (ctx_nr > LOG_MAX_CTX)
- return -EINVAL;
-
- log_context.ctx[ctx_nr] = value;
-
- return 0;
-}
-
-void log_set_all_filter(struct log_target *target, int all)
-{
- if (all)
- target->filter_map |= LOG_FILTER_ALL;
- else
- target->filter_map &= ~LOG_FILTER_ALL;
-}
-
-void log_set_use_color(struct log_target *target, int use_color)
-{
- target->use_color = use_color;
-}
-
-void log_set_print_timestamp(struct log_target *target, int print_timestamp)
-{
- target->print_timestamp = print_timestamp;
-}
-
-void log_set_log_level(struct log_target *target, int log_level)
-{
- target->loglevel = log_level;
-}
-
-void log_set_category_filter(struct log_target *target, int category,
- int enable, int level)
-{
- if (category >= log_info->num_cat)
- return;
- target->categories[category].enabled = !!enable;
- target->categories[category].loglevel = level;
-}
-
-/* since C89/C99 says stderr is a macro, we can safely do this! */
-#ifdef stderr
-static void _stderr_output(struct log_target *target, const char *log)
-{
- fprintf(target->tgt_stdout.out, "%s", log);
- fflush(target->tgt_stdout.out);
-}
-#endif
-
-struct log_target *log_target_create(void)
-{
- struct log_target *target;
- unsigned int i;
-
- target = talloc_zero(tall_log_ctx, struct log_target);
- if (!target)
- return NULL;
-
- INIT_LLIST_HEAD(&target->entry);
-
- /* initialize the per-category enabled/loglevel from defaults */
- for (i = 0; i < log_info->num_cat; i++) {
- struct log_category *cat = &target->categories[i];
- cat->enabled = log_info->cat[i].enabled;
- cat->loglevel = log_info->cat[i].loglevel;
- }
-
- /* global settings */
- target->use_color = 1;
- target->print_timestamp = 0;
-
- /* global log level */
- target->loglevel = 0;
- return target;
-}
-
-struct log_target *log_target_create_stderr(void)
-{
-/* since C89/C99 says stderr is a macro, we can safely do this! */
-#ifdef stderr
- struct log_target *target;
-
- target = log_target_create();
- if (!target)
- return NULL;
-
- target->tgt_stdout.out = stderr;
- target->output = _stderr_output;
- return target;
-#else
- return NULL;
-#endif /* stderr */
-}
-
-const char *log_vty_level_string(struct log_info *info)
-{
- const struct value_string *vs;
- unsigned int len = 3; /* ()\0 */
- char *str;
-
- for (vs = loglevel_strs; vs->value || vs->str; vs++)
- len += strlen(vs->str) + 1;
-
- str = talloc_zero_size(NULL, len);
- if (!str)
- return NULL;
-
- str[0] = '(';
- for (vs = loglevel_strs; vs->value || vs->str; vs++) {
- strcat(str, vs->str);
- strcat(str, "|");
- }
- str[strlen(str)-1] = ')';
-
- return str;
-}
-
-const char *log_vty_category_string(struct log_info *info)
-{
- unsigned int len = 3; /* "()\0" */
- unsigned int i;
- char *str;
-
- for (i = 0; i < info->num_cat; i++)
- len += strlen(info->cat[i].name) + 1;
-
- str = talloc_zero_size(NULL, len);
- if (!str)
- return NULL;
-
- str[0] = '(';
- for (i = 0; i < info->num_cat; i++) {
- strcat(str, info->cat[i].name+1);
- strcat(str, "|");
- }
- str[strlen(str)-1] = ')';
-
- return str;
-}
-
-void log_init(const struct log_info *cat)
-{
- tall_log_ctx = talloc_named_const(NULL, 1, "logging");
- log_info = cat;
-}
diff --git a/libosmocore/src/msgb.c b/libosmocore/src/msgb.c
deleted file mode 100644
index a60e2ff..0000000
--- a/libosmocore/src/msgb.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/types.h>
-
-#include <osmocore/msgb.h>
-//#include <openbsc/gsm_data.h>
-#include <osmocore/talloc.h>
-//#include <openbsc/debug.h>
-
-void *tall_msgb_ctx;
-
-struct msgb *msgb_alloc(uint16_t size, const char *name)
-{
- struct msgb *msg;
-
- msg = _talloc_zero(tall_msgb_ctx, sizeof(*msg) + size, name);
-
- if (!msg) {
- //LOGP(DRSL, LOGL_FATAL, "unable to allocate msgb\n");
- return NULL;
- }
-
- msg->data_len = size;
- msg->len = 0;
- msg->data = msg->_data;
- msg->head = msg->_data;
- msg->tail = msg->_data;
-
- return msg;
-}
-
-void msgb_free(struct msgb *m)
-{
- talloc_free(m);
-}
-
-void msgb_enqueue(struct llist_head *queue, struct msgb *msg)
-{
- llist_add_tail(&msg->list, queue);
-}
-
-struct msgb *msgb_dequeue(struct llist_head *queue)
-{
- struct llist_head *lh;
-
- if (llist_empty(queue))
- return NULL;
-
- lh = queue->next;
- llist_del(lh);
-
- return llist_entry(lh, struct msgb, list);
-}
-
-void msgb_reset(struct msgb *msg)
-{
- msg->len = 0;
- msg->data = msg->_data;
- msg->head = msg->_data;
- msg->tail = msg->_data;
-
- msg->trx = NULL;
- msg->lchan = NULL;
- msg->l2h = NULL;
- msg->l3h = NULL;
- msg->l4h = NULL;
-
- memset(&msg->cb, 0, sizeof(msg->cb));
-}
diff --git a/libosmocore/src/rate_ctr.c b/libosmocore/src/rate_ctr.c
deleted file mode 100644
index e48c779..0000000
--- a/libosmocore/src/rate_ctr.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/* utility routines for keeping conters about events and the event rates */
-
-/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <inttypes.h>
-#include <string.h>
-
-#include <osmocore/linuxlist.h>
-#include <osmocore/talloc.h>
-#include <osmocore/timer.h>
-#include <osmocore/rate_ctr.h>
-
-static LLIST_HEAD(rate_ctr_groups);
-
-static void *tall_rate_ctr_ctx;
-
-struct rate_ctr_group *rate_ctr_group_alloc(void *ctx,
- const struct rate_ctr_group_desc *desc,
- unsigned int idx)
-{
- unsigned int size;
- struct rate_ctr_group *group;
-
- size = sizeof(struct rate_ctr_group) +
- desc->num_ctr * sizeof(struct rate_ctr);
-
- if (!ctx)
- ctx = tall_rate_ctr_ctx;
-
- group = talloc_zero_size(ctx, size);
- if (!group)
- return NULL;
-
- group->desc = desc;
- group->idx = idx;
-
- llist_add(&group->list, &rate_ctr_groups);
-
- return group;
-}
-
-void rate_ctr_group_free(struct rate_ctr_group *grp)
-{
- llist_del(&grp->list);
- talloc_free(grp);
-}
-
-void rate_ctr_add(struct rate_ctr *ctr, int inc)
-{
- ctr->current += inc;
-}
-
-static void interval_expired(struct rate_ctr *ctr, enum rate_ctr_intv intv)
-{
- /* calculate rate over last interval */
- ctr->intv[intv].rate = ctr->current - ctr->intv[intv].last;
- /* save current counter for next interval */
- ctr->intv[intv].last = ctr->current;
-}
-
-static struct timer_list rate_ctr_timer;
-static uint64_t timer_ticks;
-
-/* The one-second interval has expired */
-static void rate_ctr_group_intv(struct rate_ctr_group *grp)
-{
- unsigned int i;
-
- for (i = 0; i < grp->desc->num_ctr; i++) {
- struct rate_ctr *ctr = &grp->ctr[i];
-
- interval_expired(ctr, RATE_CTR_INTV_SEC);
- if ((timer_ticks % 60) == 0)
- interval_expired(ctr, RATE_CTR_INTV_MIN);
- if ((timer_ticks % (60*60)) == 0)
- interval_expired(ctr, RATE_CTR_INTV_HOUR);
- if ((timer_ticks % (24*60*60)) == 0)
- interval_expired(ctr, RATE_CTR_INTV_DAY);
- }
-}
-
-static void rate_ctr_timer_cb(void *data)
-{
- struct rate_ctr_group *ctrg;
-
- /* Increment number of ticks before we calculate intervals,
- * as a counter value of 0 would already wrap all counters */
- timer_ticks++;
-
- llist_for_each_entry(ctrg, &rate_ctr_groups, list)
- rate_ctr_group_intv(ctrg);
-
- bsc_schedule_timer(&rate_ctr_timer, 1, 0);
-}
-
-int rate_ctr_init(void *tall_ctx)
-{
- tall_rate_ctr_ctx = tall_ctx;
- rate_ctr_timer.cb = rate_ctr_timer_cb;
- bsc_schedule_timer(&rate_ctr_timer, 1, 0);
-
- return 0;
-}
diff --git a/libosmocore/src/rsl.c b/libosmocore/src/rsl.c
deleted file mode 100644
index c002d33..0000000
--- a/libosmocore/src/rsl.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/* GSM Radio Signalling Link messages on the A-bis interface
- * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
-
-/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <errno.h>
-
-#include <osmocore/tlv.h>
-#include <osmocore/rsl.h>
-
-#define RSL_ALLOC_SIZE 200
-#define RSL_ALLOC_HEADROOM 56
-
-void rsl_init_rll_hdr(struct abis_rsl_rll_hdr *dh, uint8_t msg_type)
-{
- dh->c.msg_discr = ABIS_RSL_MDISC_RLL;
- dh->c.msg_type = msg_type;
- dh->ie_chan = RSL_IE_CHAN_NR;
- dh->ie_link_id = RSL_IE_LINK_IDENT;
-}
-
-const struct tlv_definition rsl_att_tlvdef = {
- .def = {
- [RSL_IE_CHAN_NR] = { TLV_TYPE_TV },
- [RSL_IE_LINK_IDENT] = { TLV_TYPE_TV },
- [RSL_IE_ACT_TYPE] = { TLV_TYPE_TV },
- [RSL_IE_BS_POWER] = { TLV_TYPE_TV },
- [RSL_IE_CHAN_IDENT] = { TLV_TYPE_TLV },
- [RSL_IE_CHAN_MODE] = { TLV_TYPE_TLV },
- [RSL_IE_ENCR_INFO] = { TLV_TYPE_TLV },
- [RSL_IE_FRAME_NUMBER] = { TLV_TYPE_FIXED, 2 },
- [RSL_IE_HANDO_REF] = { TLV_TYPE_TV },
- [RSL_IE_L1_INFO] = { TLV_TYPE_FIXED, 2 },
- [RSL_IE_L3_INFO] = { TLV_TYPE_TL16V },
- [RSL_IE_MS_IDENTITY] = { TLV_TYPE_TLV },
- [RSL_IE_MS_POWER] = { TLV_TYPE_TV },
- [RSL_IE_PAGING_GROUP] = { TLV_TYPE_TV },
- [RSL_IE_PAGING_LOAD] = { TLV_TYPE_FIXED, 2 },
- [RSL_IE_PYHS_CONTEXT] = { TLV_TYPE_TLV },
- [RSL_IE_ACCESS_DELAY] = { TLV_TYPE_TV },
- [RSL_IE_RACH_LOAD] = { TLV_TYPE_TLV },
- [RSL_IE_REQ_REFERENCE] = { TLV_TYPE_FIXED, 3 },
- [RSL_IE_RELEASE_MODE] = { TLV_TYPE_TV },
- [RSL_IE_RESOURCE_INFO] = { TLV_TYPE_TLV },
- [RSL_IE_RLM_CAUSE] = { TLV_TYPE_TLV },
- [RSL_IE_STARTNG_TIME] = { TLV_TYPE_FIXED, 2 },
- [RSL_IE_TIMING_ADVANCE] = { TLV_TYPE_TV },
- [RSL_IE_UPLINK_MEAS] = { TLV_TYPE_TLV },
- [RSL_IE_CAUSE] = { TLV_TYPE_TLV },
- [RSL_IE_MEAS_RES_NR] = { TLV_TYPE_TV },
- [RSL_IE_MSG_ID] = { TLV_TYPE_TV },
- [RSL_IE_SYSINFO_TYPE] = { TLV_TYPE_TV },
- [RSL_IE_MS_POWER_PARAM] = { TLV_TYPE_TLV },
- [RSL_IE_BS_POWER_PARAM] = { TLV_TYPE_TLV },
- [RSL_IE_PREPROC_PARAM] = { TLV_TYPE_TLV },
- [RSL_IE_PREPROC_MEAS] = { TLV_TYPE_TLV },
- [RSL_IE_IMM_ASS_INFO] = { TLV_TYPE_TLV },
- [RSL_IE_SMSCB_INFO] = { TLV_TYPE_FIXED, 23 },
- [RSL_IE_MS_TIMING_OFFSET] = { TLV_TYPE_TV },
- [RSL_IE_ERR_MSG] = { TLV_TYPE_TLV },
- [RSL_IE_FULL_BCCH_INFO] = { TLV_TYPE_TLV },
- [RSL_IE_CHAN_NEEDED] = { TLV_TYPE_TV },
- [RSL_IE_CB_CMD_TYPE] = { TLV_TYPE_TV },
- [RSL_IE_SMSCB_MSG] = { TLV_TYPE_TLV },
- [RSL_IE_FULL_IMM_ASS_INFO] = { TLV_TYPE_TLV },
- [RSL_IE_SACCH_INFO] = { TLV_TYPE_TLV },
- [RSL_IE_CBCH_LOAD_INFO] = { TLV_TYPE_TV },
- [RSL_IE_SMSCB_CHAN_INDICATOR] = { TLV_TYPE_TV },
- [RSL_IE_GROUP_CALL_REF] = { TLV_TYPE_TLV },
- [RSL_IE_CHAN_DESC] = { TLV_TYPE_TLV },
- [RSL_IE_NCH_DRX_INFO] = { TLV_TYPE_TLV },
- [RSL_IE_CMD_INDICATOR] = { TLV_TYPE_TLV },
- [RSL_IE_EMLPP_PRIO] = { TLV_TYPE_TV },
- [RSL_IE_UIC] = { TLV_TYPE_TLV },
- [RSL_IE_MAIN_CHAN_REF] = { TLV_TYPE_TV },
- [RSL_IE_MR_CONFIG] = { TLV_TYPE_TLV },
- [RSL_IE_MR_CONTROL] = { TLV_TYPE_TV },
- [RSL_IE_SUP_CODEC_TYPES] = { TLV_TYPE_TLV },
- [RSL_IE_CODEC_CONFIG] = { TLV_TYPE_TLV },
- [RSL_IE_RTD] = { TLV_TYPE_TV },
- [RSL_IE_TFO_STATUS] = { TLV_TYPE_TV },
- [RSL_IE_LLP_APDU] = { TLV_TYPE_TLV },
- [RSL_IE_SIEMENS_MRPCI] = { TLV_TYPE_TV },
- [RSL_IE_IPAC_PROXY_UDP] = { TLV_TYPE_FIXED, 2 },
- [RSL_IE_IPAC_BSCMPL_TOUT] = { TLV_TYPE_TV },
- [RSL_IE_IPAC_REMOTE_IP] = { TLV_TYPE_FIXED, 4 },
- [RSL_IE_IPAC_REMOTE_PORT] = { TLV_TYPE_FIXED, 2 },
- [RSL_IE_IPAC_RTP_PAYLOAD] = { TLV_TYPE_TV },
- [RSL_IE_IPAC_LOCAL_PORT] = { TLV_TYPE_FIXED, 2 },
- [RSL_IE_IPAC_SPEECH_MODE] = { TLV_TYPE_TV },
- [RSL_IE_IPAC_LOCAL_IP] = { TLV_TYPE_FIXED, 4 },
- [RSL_IE_IPAC_CONN_ID] = { TLV_TYPE_FIXED, 2 },
- [RSL_IE_IPAC_RTP_CSD_FMT] = { TLV_TYPE_TV },
- [RSL_IE_IPAC_RTP_JIT_BUF] = { TLV_TYPE_FIXED, 2 },
- [RSL_IE_IPAC_RTP_COMPR] = { TLV_TYPE_TV },
- [RSL_IE_IPAC_RTP_PAYLOAD2] = { TLV_TYPE_TV },
- [RSL_IE_IPAC_RTP_MPLEX] = { TLV_TYPE_FIXED, 8 },
- [RSL_IE_IPAC_RTP_MPLEX_ID] = { TLV_TYPE_TV },
- },
-};
-
-/* encode channel number as per Section 9.3.1 */
-uint8_t rsl_enc_chan_nr(uint8_t type, uint8_t subch, uint8_t timeslot)
-{
- uint8_t ret;
-
- ret = (timeslot & 0x07) | type;
-
- switch (type) {
- case RSL_CHAN_Lm_ACCHs:
- subch &= 0x01;
- break;
- case RSL_CHAN_SDCCH4_ACCH:
- subch &= 0x03;
- break;
- case RSL_CHAN_SDCCH8_ACCH:
- subch &= 0x07;
- break;
- default:
- /* no subchannels allowed */
- subch = 0x00;
- break;
- }
- ret |= (subch << 3);
-
- return ret;
-}
-
-int rsl_dec_chan_nr(uint8_t chan_nr, uint8_t *type, uint8_t *subch, uint8_t *timeslot)
-{
- *timeslot = chan_nr & 0x7;
-
- if ((chan_nr & 0xf8) == RSL_CHAN_Bm_ACCHs) {
- *type = RSL_CHAN_Bm_ACCHs;
- *subch = 0;
- } else if ((chan_nr & 0xf0) == RSL_CHAN_Lm_ACCHs) {
- *type = RSL_CHAN_Lm_ACCHs;
- *subch = (chan_nr >> 3) & 0x1;
- } else if ((chan_nr & 0xe0) == RSL_CHAN_SDCCH4_ACCH) {
- *type = RSL_CHAN_SDCCH4_ACCH;
- *subch = (chan_nr >> 3) & 0x3;
- } else if ((chan_nr & 0xc0) == RSL_CHAN_SDCCH8_ACCH) {
- *type = RSL_CHAN_SDCCH8_ACCH;
- *subch = (chan_nr >> 3) & 0x7;
- } else if ((chan_nr & 0xf8) == RSL_CHAN_BCCH) {
- *type = RSL_CHAN_BCCH;
- *subch = 0;
- } else if ((chan_nr & 0xf8) == RSL_CHAN_RACH) {
- *type = RSL_CHAN_RACH;
- *subch = 0;
- } else if ((chan_nr & 0xf8) == RSL_CHAN_PCH_AGCH) {
- *type = RSL_CHAN_PCH_AGCH;
- *subch = 0;
- } else
- return -EINVAL;
-
- return 0;
-}
-
-static const struct value_string rsl_err_vals[] = {
- { RSL_ERR_RADIO_IF_FAIL, "Radio Interface Failure" },
- { RSL_ERR_RADIO_LINK_FAIL, "Radio Link Failure" },
- { RSL_ERR_HANDOVER_ACC_FAIL, "Handover Access Failure" },
- { RSL_ERR_TALKER_ACC_FAIL, "Talker Access Failure" },
- { RSL_ERR_OM_INTERVENTION, "O&M Intervention" },
- { RSL_ERR_NORMAL_UNSPEC, "Normal event, unspecified" },
- { RSL_ERR_T_MSRFPCI_EXP, "Siemens: T_MSRFPCI Expired" },
- { RSL_ERR_EQUIPMENT_FAIL, "Equipment Failure" },
- { RSL_ERR_RR_UNAVAIL, "Radio Resource not available" },
- { RSL_ERR_TERR_CH_FAIL, "Terrestrial Channel Failure" },
- { RSL_ERR_CCCH_OVERLOAD, "CCCH Overload" },
- { RSL_ERR_ACCH_OVERLOAD, "ACCH Overload" },
- { RSL_ERR_PROCESSOR_OVERLOAD, "Processor Overload" },
- { RSL_ERR_RES_UNAVAIL, "Resource not available, unspecified" },
- { RSL_ERR_TRANSC_UNAVAIL, "Transcoding not available" },
- { RSL_ERR_SERV_OPT_UNAVAIL, "Service or Option not available" },
- { RSL_ERR_ENCR_UNIMPL, "Encryption algorithm not implemented" },
- { RSL_ERR_SERV_OPT_UNIMPL, "Service or Option not implemented" },
- { RSL_ERR_RCH_ALR_ACTV_ALLOC, "Radio channel already activated" },
- { RSL_ERR_INVALID_MESSAGE, "Invalid Message, unspecified" },
- { RSL_ERR_MSG_DISCR, "Message Discriminator Error" },
- { RSL_ERR_MSG_TYPE, "Message Type Error" },
- { RSL_ERR_MSG_SEQ, "Message Sequence Error" },
- { RSL_ERR_IE_ERROR, "General IE error" },
- { RSL_ERR_MAND_IE_ERROR, "Mandatory IE error" },
- { RSL_ERR_OPT_IE_ERROR, "Optional IE error" },
- { RSL_ERR_IE_NONEXIST, "IE non-existent" },
- { RSL_ERR_IE_LENGTH, "IE length error" },
- { RSL_ERR_IE_CONTENT, "IE content error" },
- { RSL_ERR_PROTO, "Protocol error, unspecified" },
- { RSL_ERR_INTERWORKING, "Interworking error, unspecified" },
- { 0, NULL }
-};
-
-const char *rsl_err_name(uint8_t err)
-{
- return get_value_string(rsl_err_vals, err);
-}
-
-static const struct value_string rsl_rlm_cause_strs[] = {
- { RLL_CAUSE_T200_EXPIRED, "Timer T200 expired (N200+1) times" },
- { RLL_CAUSE_REEST_REQ, "Re-establishment request" },
- { RLL_CAUSE_UNSOL_UA_RESP, "Unsolicited UA response" },
- { RLL_CAUSE_UNSOL_DM_RESP, "Unsolicited DM response" },
- { RLL_CAUSE_UNSOL_DM_RESP_MF, "Unsolicited DM response, multiple frame" },
- { RLL_CAUSE_UNSOL_SPRV_RESP, "Unsolicited supervisory response" },
- { RLL_CAUSE_SEQ_ERR, "Sequence Error" },
- { RLL_CAUSE_UFRM_INC_PARAM, "U-Frame with incorrect parameters" },
- { RLL_CAUSE_SFRM_INC_PARAM, "S-Frame with incorrect parameters" },
- { RLL_CAUSE_IFRM_INC_MBITS, "I-Frame with incorrect use of M bit" },
- { RLL_CAUSE_IFRM_INC_LEN, "I-Frame with incorrect length" },
- { RLL_CAUSE_FRM_UNIMPL, "Fraeme not implemented" },
- { RLL_CAUSE_SABM_MF, "SABM command, multiple frame established state" },
- { RLL_CAUSE_SABM_INFO_NOTALL, "SABM frame with information not allowed in this state" },
- { 0, NULL },
-};
-
-const char *rsl_rlm_cause_name(uint8_t err)
-{
- return get_value_string(rsl_rlm_cause_strs, err);
-}
-
-/* Section 3.3.2.3 TS 05.02. I think this looks like a table */
-int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf)
-{
- switch (ccch_conf) {
- case RSL_BCCH_CCCH_CONF_1_NC:
- return 1;
- case RSL_BCCH_CCCH_CONF_1_C:
- return 1;
- case RSL_BCCH_CCCH_CONF_2_NC:
- return 2;
- case RSL_BCCH_CCCH_CONF_3_NC:
- return 3;
- case RSL_BCCH_CCCH_CONF_4_NC:
- return 4;
- default:
- return -1;
- }
-}
-
-/* Section 3.3.2.3 TS 05.02 */
-int rsl_ccch_conf_to_bs_ccch_sdcch_comb(int ccch_conf)
-{
- switch (ccch_conf) {
- case RSL_BCCH_CCCH_CONF_1_NC:
- return 0;
- case RSL_BCCH_CCCH_CONF_1_C:
- return 1;
- case RSL_BCCH_CCCH_CONF_2_NC:
- return 0;
- case RSL_BCCH_CCCH_CONF_3_NC:
- return 0;
- case RSL_BCCH_CCCH_CONF_4_NC:
- return 0;
- default:
- return -1;
- }
-}
-
-/* Push a RSL RLL header with L3_INFO IE */
-void rsl_rll_push_l3(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr,
- uint8_t link_id, int transparent)
-{
- uint8_t l3_len = msg->tail - (uint8_t *)msgb_l3(msg);
- struct abis_rsl_rll_hdr *rh;
-
- /* construct a RSLms RLL message (DATA INDICATION, UNIT DATA
- * INDICATION) and send it off via RSLms */
-
- /* Push the L3 IE tag and lengh */
- msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
-
- /* Then push the RSL header */
- rh = (struct abis_rsl_rll_hdr *) msgb_push(msg, sizeof(*rh));
- rsl_init_rll_hdr(rh, msg_type);
- if (transparent)
- rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
- rh->chan_nr = chan_nr;
- rh->link_id = link_id;
-
- /* set the l2 header pointer */
- msg->l2h = (uint8_t *)rh;
-}
-
-struct msgb *rsl_rll_simple(uint8_t msg_type, uint8_t chan_nr,
- uint8_t link_id, int transparent)
-{
- struct abis_rsl_rll_hdr *rh;
- struct msgb *msg;
-
- msg = msgb_alloc_headroom(RSL_ALLOC_SIZE+RSL_ALLOC_HEADROOM,
- RSL_ALLOC_HEADROOM, "rsl_rll_simple");
-
- if (!msg)
- return NULL;
-
- /* put the RSL header */
- rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh));
- rsl_init_rll_hdr(rh, msg_type);
- if (transparent)
- rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
- rh->chan_nr = chan_nr;
- rh->link_id = link_id;
-
- /* set the l2 header pointer */
- msg->l2h = (uint8_t *)rh;
-
- return msg;
-}
diff --git a/libosmocore/src/rxlev_stat.c b/libosmocore/src/rxlev_stat.c
deleted file mode 100644
index 1bfd679..0000000
--- a/libosmocore/src/rxlev_stat.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/* Rx Level statistics */
-
-/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <stdint.h>
-
-#include <osmocore/bitvec.h>
-#include <osmocore/rxlev_stat.h>
-
-int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n, enum bit_value val)
-{
- unsigned int i;
-
- for (i = n; i < bv->data_len*8; i++) {
- if (bitvec_get_bit_pos(bv, i) == val)
- return i;
- }
-
- return -1;
-}
-
-void rxlev_stat_input(struct rxlev_stats *st, uint16_t arfcn, uint8_t rxlev)
-{
- struct bitvec bv;
-
- if (rxlev >= NUM_RXLEVS)
- rxlev = NUM_RXLEVS-1;
-
- bv.data_len = NUM_ARFCNS/8;
- bv.data = st->rxlev_buckets[rxlev];
-
- bitvec_set_bit_pos(&bv, arfcn, ONE);
-}
-
-/* get the next ARFCN that has the specified Rxlev */
-int16_t rxlev_stat_get_next(const struct rxlev_stats *st, uint8_t rxlev, int16_t arfcn)
-{
- struct bitvec bv;
-
- if (rxlev >= NUM_RXLEVS)
- rxlev = NUM_RXLEVS-1;
-
- bv.data_len = NUM_ARFCNS/8;
-
- if (arfcn < 0)
- arfcn = -1;
-
- bv.data = st->rxlev_buckets[rxlev];
-
- return bitvec_find_bit_pos(&bv, arfcn+1, ONE);
-}
-
-void rxlev_stat_reset(struct rxlev_stats *st)
-{
- memset(st, 0, sizeof(*st));
-}
-
-void rxlev_stat_dump(const struct rxlev_stats *st)
-{
- int i;
-
- for (i = NUM_RXLEVS-1; i >= 0; i--) {
- int16_t arfcn = -1;
-
- printf("ARFCN with RxLev %u: ", i);
- while ((arfcn = rxlev_stat_get_next(st, i, arfcn)) >= 0) {
- printf("%u ", arfcn);
- }
- printf("\n");
- }
-}
diff --git a/libosmocore/src/select.c b/libosmocore/src/select.c
deleted file mode 100644
index 2f6afa7..0000000
--- a/libosmocore/src/select.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/* select filedescriptor handling, taken from:
- * userspace logging daemon for the iptables ULOG target
- * of the linux 2.4 netfilter subsystem.
- *
- * (C) 2000-2009 by Harald Welte <laforge@gnumonks.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <fcntl.h>
-#include <osmocore/select.h>
-#include <osmocore/linuxlist.h>
-#include <osmocore/timer.h>
-
-#include "../config.h"
-
-#ifdef HAVE_SYS_SELECT_H
-
-static int maxfd = 0;
-static LLIST_HEAD(bsc_fds);
-static int unregistered_count;
-
-int bsc_register_fd(struct bsc_fd *fd)
-{
- int flags;
-
- /* make FD nonblocking */
- flags = fcntl(fd->fd, F_GETFL);
- if (flags < 0)
- return flags;
- flags |= O_NONBLOCK;
- flags = fcntl(fd->fd, F_SETFL, flags);
- if (flags < 0)
- return flags;
-
- /* Register FD */
- if (fd->fd > maxfd)
- maxfd = fd->fd;
-
- llist_add_tail(&fd->list, &bsc_fds);
-
- return 0;
-}
-
-void bsc_unregister_fd(struct bsc_fd *fd)
-{
- unregistered_count++;
- llist_del(&fd->list);
-}
-
-int bsc_select_main(int polling)
-{
- struct bsc_fd *ufd, *tmp;
- fd_set readset, writeset, exceptset;
- int work = 0, rc;
- struct timeval no_time = {0, 0};
-
- FD_ZERO(&readset);
- FD_ZERO(&writeset);
- FD_ZERO(&exceptset);
-
- /* prepare read and write fdsets */
- llist_for_each_entry(ufd, &bsc_fds, list) {
- if (ufd->when & BSC_FD_READ)
- FD_SET(ufd->fd, &readset);
-
- if (ufd->when & BSC_FD_WRITE)
- FD_SET(ufd->fd, &writeset);
-
- if (ufd->when & BSC_FD_EXCEPT)
- FD_SET(ufd->fd, &exceptset);
- }
-
- bsc_timer_check();
-
- if (!polling)
- bsc_prepare_timers();
- rc = select(maxfd+1, &readset, &writeset, &exceptset, polling ? &no_time : bsc_nearest_timer());
- if (rc < 0)
- return 0;
-
- /* fire timers */
- bsc_update_timers();
-
- /* call registered callback functions */
-restart:
- unregistered_count = 0;
- llist_for_each_entry_safe(ufd, tmp, &bsc_fds, list) {
- int flags = 0;
-
- if (FD_ISSET(ufd->fd, &readset)) {
- flags |= BSC_FD_READ;
- FD_CLR(ufd->fd, &readset);
- }
-
- if (FD_ISSET(ufd->fd, &writeset)) {
- flags |= BSC_FD_WRITE;
- FD_CLR(ufd->fd, &writeset);
- }
-
- if (FD_ISSET(ufd->fd, &exceptset)) {
- flags |= BSC_FD_EXCEPT;
- FD_CLR(ufd->fd, &exceptset);
- }
-
- if (flags) {
- work = 1;
- ufd->cb(ufd, flags);
- }
- /* ugly, ugly hack. If more than one filedescriptors were
- * unregistered, they might have been consecutive and
- * llist_for_each_entry_safe() is no longer safe */
- /* this seems to happen with the last element of the list as well */
- if (unregistered_count >= 1)
- goto restart;
- }
- return work;
-}
-
-#endif /* _HAVE_SYS_SELECT_H */
diff --git a/libosmocore/src/signal.c b/libosmocore/src/signal.c
deleted file mode 100644
index c7ca86c..0000000
--- a/libosmocore/src/signal.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* Generic signalling/notification infrastructure */
-/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <osmocore/signal.h>
-#include <osmocore/talloc.h>
-#include <osmocore/linuxlist.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-void *tall_sigh_ctx;
-static LLIST_HEAD(signal_handler_list);
-
-struct signal_handler {
- struct llist_head entry;
- unsigned int subsys;
- signal_cbfn *cbfn;
- void *data;
-};
-
-
-int register_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data)
-{
- struct signal_handler *sig_data;
-
- sig_data = talloc(tall_sigh_ctx, struct signal_handler);
- if (!sig_data)
- return -ENOMEM;
-
- memset(sig_data, 0, sizeof(*sig_data));
-
- sig_data->subsys = subsys;
- sig_data->data = data;
- sig_data->cbfn = cbfn;
-
- /* FIXME: check if we already have a handler for this subsys/cbfn/data */
-
- llist_add_tail(&sig_data->entry, &signal_handler_list);
-
- return 0;
-}
-
-void unregister_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data)
-{
- struct signal_handler *handler;
-
- llist_for_each_entry(handler, &signal_handler_list, entry) {
- if (handler->cbfn == cbfn && handler->data == data
- && subsys == handler->subsys) {
- llist_del(&handler->entry);
- talloc_free(handler);
- break;
- }
- }
-}
-
-
-void dispatch_signal(unsigned int subsys, unsigned int signal, void *signal_data)
-{
- struct signal_handler *handler;
-
- llist_for_each_entry(handler, &signal_handler_list, entry) {
- if (handler->subsys != subsys)
- continue;
- (*handler->cbfn)(subsys, signal, handler->data, signal_data);
- }
-}
diff --git a/libosmocore/src/statistics.c b/libosmocore/src/statistics.c
deleted file mode 100644
index 34e6a40..0000000
--- a/libosmocore/src/statistics.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/* utility routines for keeping some statistics */
-
-/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-
-#include <sys/types.h>
-
-#include <osmocore/linuxlist.h>
-#include <osmocore/talloc.h>
-#include <osmocore/statistics.h>
-
-static LLIST_HEAD(counters);
-
-void *tall_ctr_ctx;
-
-struct counter *counter_alloc(const char *name)
-{
- struct counter *ctr = talloc_zero(tall_ctr_ctx, struct counter);
-
- if (!ctr)
- return NULL;
-
- ctr->name = name;
- llist_add_tail(&ctr->list, &counters);
-
- return ctr;
-}
-
-void counter_free(struct counter *ctr)
-{
- llist_del(&ctr->list);
- talloc_free(ctr);
-}
-
-int counters_for_each(int (*handle_counter)(struct counter *, void *), void *data)
-{
- struct counter *ctr;
- int rc = 0;
-
- llist_for_each_entry(ctr, &counters, list) {
- rc = handle_counter(ctr, data);
- if (rc < 0)
- return rc;
- }
-
- return rc;
-}
-
diff --git a/libosmocore/src/talloc.c b/libosmocore/src/talloc.c
deleted file mode 100644
index 98c2ee0..0000000
--- a/libosmocore/src/talloc.c
+++ /dev/null
@@ -1,1805 +0,0 @@
-/*
- Samba Unix SMB/CIFS implementation.
-
- Samba trivial allocation library - new interface
-
- NOTE: Please read talloc_guide.txt for full documentation
-
- Copyright (C) Andrew Tridgell 2004
- Copyright (C) Stefan Metzmacher 2006
-
- ** NOTE! The following LGPL license applies to the talloc
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-/*
- inspired by http://swapped.cc/halloc/
-*/
-
-#ifdef _SAMBA_BUILD_
-#include "version.h"
-#if (SAMBA_VERSION_MAJOR<4)
-#include "includes.h"
-/* This is to circumvent SAMBA3's paranoid malloc checker. Here in this file
- * we trust ourselves... */
-#ifdef malloc
-#undef malloc
-#endif
-#ifdef realloc
-#undef realloc
-#endif
-#define _TALLOC_SAMBA3
-#endif /* (SAMBA_VERSION_MAJOR<4) */
-#endif /* _SAMBA_BUILD_ */
-
-#ifndef _TALLOC_SAMBA3
-//#include "replace.h"
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdbool.h>
-#define __USE_GNU
-#include <string.h>
-#undef __USE_GNU
-#include <osmocore/talloc.h>
-#define MIN(x,y) ((x) < (y) ? (x) : (y))
-#endif /* not _TALLOC_SAMBA3 */
-
-/* use this to force every realloc to change the pointer, to stress test
- code that might not cope */
-#define ALWAYS_REALLOC 0
-
-
-#define MAX_TALLOC_SIZE 0x10000000
-#define TALLOC_MAGIC 0xe814ec70
-#define TALLOC_FLAG_FREE 0x01
-#define TALLOC_FLAG_LOOP 0x02
-#define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */
-#define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */
-#define TALLOC_MAGIC_REFERENCE ((const char *)1)
-
-/* by default we abort when given a bad pointer (such as when talloc_free() is called
- on a pointer that came from malloc() */
-#ifndef TALLOC_ABORT
-#define TALLOC_ABORT(reason) abort()
-#endif
-
-#ifndef discard_const_p
-#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
-# define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr)))
-#else
-# define discard_const_p(type, ptr) ((type *)(ptr))
-#endif
-#endif
-
-/* these macros gain us a few percent of speed on gcc */
-#if (__GNUC__ >= 3)
-/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1
- as its first argument */
-#ifndef likely
-#define likely(x) __builtin_expect(!!(x), 1)
-#endif
-#ifndef unlikely
-#define unlikely(x) __builtin_expect(!!(x), 0)
-#endif
-#else
-#ifndef likely
-#define likely(x) (x)
-#endif
-#ifndef unlikely
-#define unlikely(x) (x)
-#endif
-#endif
-
-#ifdef __APPLE__
-/* taken from http://insanecoding.blogspot.com/2007/03/methods-for-safe-string-handling.html */
-size_t strnlen(const char *s, size_t n)
-{
- const char *p = (const char *)memchr(s, 0, n);
- return(p ? p-s : n);
-}
-#endif
-
-/* this null_context is only used if talloc_enable_leak_report() or
- talloc_enable_leak_report_full() is called, otherwise it remains
- NULL
-*/
-static void *null_context;
-static void *autofree_context;
-
-struct talloc_reference_handle {
- struct talloc_reference_handle *next, *prev;
- void *ptr;
-};
-
-typedef int (*talloc_destructor_t)(void *);
-
-struct talloc_chunk {
- struct talloc_chunk *next, *prev;
- struct talloc_chunk *parent, *child;
- struct talloc_reference_handle *refs;
- talloc_destructor_t destructor;
- const char *name;
- size_t size;
- unsigned flags;
-
- /*
- * "pool" has dual use:
- *
- * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool"
- * marks the end of the currently allocated area.
- *
- * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool"
- * is a pointer to the struct talloc_chunk of the pool that it was
- * allocated from. This way children can quickly find the pool to chew
- * from.
- */
- void *pool;
-};
-
-/* 16 byte alignment seems to keep everyone happy */
-#define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
-#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
-
-static void (*talloc_abort_fn)(const char *reason);
-
-void talloc_set_abort_fn(void (*abort_fn)(const char *reason))
-{
- talloc_abort_fn = abort_fn;
-}
-
-static void talloc_abort(const char *reason)
-{
- if (!talloc_abort_fn) {
- TALLOC_ABORT(reason);
- }
-
- talloc_abort_fn(reason);
-}
-
-static void talloc_abort_double_free(void)
-{
- talloc_abort("Bad talloc magic value - double free");
-}
-
-static void talloc_abort_unknown_value(void)
-{
- talloc_abort("Bad talloc magic value - unknown value");
-}
-
-/* panic if we get a bad magic value */
-static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
-{
- const char *pp = (const char *)ptr;
- struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
- if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) {
- if (tc->flags & TALLOC_FLAG_FREE) {
- talloc_abort_double_free();
- } else {
- talloc_abort_unknown_value();
- }
- }
- return tc;
-}
-
-/* hook into the front of the list */
-#define _TLIST_ADD(list, p) \
-do { \
- if (!(list)) { \
- (list) = (p); \
- (p)->next = (p)->prev = NULL; \
- } else { \
- (list)->prev = (p); \
- (p)->next = (list); \
- (p)->prev = NULL; \
- (list) = (p); \
- }\
-} while (0)
-
-/* remove an element from a list - element doesn't have to be in list. */
-#define _TLIST_REMOVE(list, p) \
-do { \
- if ((p) == (list)) { \
- (list) = (p)->next; \
- if (list) (list)->prev = NULL; \
- } else { \
- if ((p)->prev) (p)->prev->next = (p)->next; \
- if ((p)->next) (p)->next->prev = (p)->prev; \
- } \
- if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
-} while (0)
-
-
-/*
- return the parent chunk of a pointer
-*/
-static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr)
-{
- struct talloc_chunk *tc;
-
- if (unlikely(ptr == NULL)) {
- return NULL;
- }
-
- tc = talloc_chunk_from_ptr(ptr);
- while (tc->prev) tc=tc->prev;
-
- return tc->parent;
-}
-
-void *talloc_parent(const void *ptr)
-{
- struct talloc_chunk *tc = talloc_parent_chunk(ptr);
- return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
-}
-
-/*
- find parents name
-*/
-const char *talloc_parent_name(const void *ptr)
-{
- struct talloc_chunk *tc = talloc_parent_chunk(ptr);
- return tc? tc->name : NULL;
-}
-
-/*
- A pool carries an in-pool object count count in the first 16 bytes.
- bytes. This is done to support talloc_steal() to a parent outside of the
- pool. The count includes the pool itself, so a talloc_free() on a pool will
- only destroy the pool if the count has dropped to zero. A talloc_free() of a
- pool member will reduce the count, and eventually also call free(3) on the
- pool memory.
-
- The object count is not put into "struct talloc_chunk" because it is only
- relevant for talloc pools and the alignment to 16 bytes would increase the
- memory footprint of each talloc chunk by those 16 bytes.
-*/
-
-#define TALLOC_POOL_HDR_SIZE 16
-
-static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc)
-{
- return (unsigned int *)((char *)tc + sizeof(struct talloc_chunk));
-}
-
-/*
- Allocate from a pool
-*/
-
-static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent,
- size_t size)
-{
- struct talloc_chunk *pool_ctx = NULL;
- size_t space_left;
- struct talloc_chunk *result;
- size_t chunk_size;
-
- if (parent == NULL) {
- return NULL;
- }
-
- if (parent->flags & TALLOC_FLAG_POOL) {
- pool_ctx = parent;
- }
- else if (parent->flags & TALLOC_FLAG_POOLMEM) {
- pool_ctx = (struct talloc_chunk *)parent->pool;
- }
-
- if (pool_ctx == NULL) {
- return NULL;
- }
-
- space_left = ((char *)pool_ctx + TC_HDR_SIZE + pool_ctx->size)
- - ((char *)pool_ctx->pool);
-
- /*
- * Align size to 16 bytes
- */
- chunk_size = ((size + 15) & ~15);
-
- if (space_left < chunk_size) {
- return NULL;
- }
-
- result = (struct talloc_chunk *)pool_ctx->pool;
-
-#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED)
- VALGRIND_MAKE_MEM_UNDEFINED(result, size);
-#endif
-
- pool_ctx->pool = (void *)((char *)result + chunk_size);
-
- result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM;
- result->pool = pool_ctx;
-
- *talloc_pool_objectcount(pool_ctx) += 1;
-
- return result;
-}
-
-/*
- Allocate a bit of memory as a child of an existing pointer
-*/
-static inline void *__talloc(const void *context, size_t size)
-{
- struct talloc_chunk *tc = NULL;
-
- if (unlikely(context == NULL)) {
- context = null_context;
- }
-
- if (unlikely(size >= MAX_TALLOC_SIZE)) {
- return NULL;
- }
-
- if (context != NULL) {
- tc = talloc_alloc_pool(talloc_chunk_from_ptr(context),
- TC_HDR_SIZE+size);
- }
-
- if (tc == NULL) {
- tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size);
- if (unlikely(tc == NULL)) return NULL;
- tc->flags = TALLOC_MAGIC;
- tc->pool = NULL;
- }
-
- tc->size = size;
- tc->destructor = NULL;
- tc->child = NULL;
- tc->name = NULL;
- tc->refs = NULL;
-
- if (likely(context)) {
- struct talloc_chunk *parent = talloc_chunk_from_ptr(context);
-
- if (parent->child) {
- parent->child->parent = NULL;
- tc->next = parent->child;
- tc->next->prev = tc;
- } else {
- tc->next = NULL;
- }
- tc->parent = parent;
- tc->prev = NULL;
- parent->child = tc;
- } else {
- tc->next = tc->prev = tc->parent = NULL;
- }
-
- return TC_PTR_FROM_CHUNK(tc);
-}
-
-/*
- * Create a talloc pool
- */
-
-void *talloc_pool(const void *context, size_t size)
-{
- void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE);
- struct talloc_chunk *tc;
-
- if (unlikely(result == NULL)) {
- return NULL;
- }
-
- tc = talloc_chunk_from_ptr(result);
-
- tc->flags |= TALLOC_FLAG_POOL;
- tc->pool = (char *)result + TALLOC_POOL_HDR_SIZE;
-
- *talloc_pool_objectcount(tc) = 1;
-
-#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
- VALGRIND_MAKE_MEM_NOACCESS(tc->pool, size);
-#endif
-
- return result;
-}
-
-/*
- setup a destructor to be called on free of a pointer
- the destructor should return 0 on success, or -1 on failure.
- if the destructor fails then the free is failed, and the memory can
- be continued to be used
-*/
-void _talloc_set_destructor(const void *ptr, int (*destructor)(void *))
-{
- struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
- tc->destructor = destructor;
-}
-
-/*
- increase the reference count on a piece of memory.
-*/
-int talloc_increase_ref_count(const void *ptr)
-{
- if (unlikely(!talloc_reference(null_context, ptr))) {
- return -1;
- }
- return 0;
-}
-
-/*
- helper for talloc_reference()
-
- this is referenced by a function pointer and should not be inline
-*/
-static int talloc_reference_destructor(struct talloc_reference_handle *handle)
-{
- struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr);
- _TLIST_REMOVE(ptr_tc->refs, handle);
- return 0;
-}
-
-/*
- more efficient way to add a name to a pointer - the name must point to a
- true string constant
-*/
-static inline void _talloc_set_name_const(const void *ptr, const char *name)
-{
- struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
- tc->name = name;
-}
-
-/*
- internal talloc_named_const()
-*/
-static inline void *_talloc_named_const(const void *context, size_t size, const char *name)
-{
- void *ptr;
-
- ptr = __talloc(context, size);
- if (unlikely(ptr == NULL)) {
- return NULL;
- }
-
- _talloc_set_name_const(ptr, name);
-
- return ptr;
-}
-
-/*
- make a secondary reference to a pointer, hanging off the given context.
- the pointer remains valid until both the original caller and this given
- context are freed.
-
- the major use for this is when two different structures need to reference the
- same underlying data, and you want to be able to free the two instances separately,
- and in either order
-*/
-void *_talloc_reference(const void *context, const void *ptr)
-{
- struct talloc_chunk *tc;
- struct talloc_reference_handle *handle;
- if (unlikely(ptr == NULL)) return NULL;
-
- tc = talloc_chunk_from_ptr(ptr);
- handle = (struct talloc_reference_handle *)_talloc_named_const(context,
- sizeof(struct talloc_reference_handle),
- TALLOC_MAGIC_REFERENCE);
- if (unlikely(handle == NULL)) return NULL;
-
- /* note that we hang the destructor off the handle, not the
- main context as that allows the caller to still setup their
- own destructor on the context if they want to */
- talloc_set_destructor(handle, talloc_reference_destructor);
- handle->ptr = discard_const_p(void, ptr);
- _TLIST_ADD(tc->refs, handle);
- return handle->ptr;
-}
-
-
-/*
- internal talloc_free call
-*/
-static inline int _talloc_free(void *ptr)
-{
- struct talloc_chunk *tc;
-
- if (unlikely(ptr == NULL)) {
- return -1;
- }
-
- tc = talloc_chunk_from_ptr(ptr);
-
- if (unlikely(tc->refs)) {
- int is_child;
- /* check this is a reference from a child or grantchild
- * back to it's parent or grantparent
- *
- * in that case we need to remove the reference and
- * call another instance of talloc_free() on the current
- * pointer.
- */
- is_child = talloc_is_parent(tc->refs, ptr);
- _talloc_free(tc->refs);
- if (is_child) {
- return _talloc_free(ptr);
- }
- return -1;
- }
-
- if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) {
- /* we have a free loop - stop looping */
- return 0;
- }
-
- if (unlikely(tc->destructor)) {
- talloc_destructor_t d = tc->destructor;
- if (d == (talloc_destructor_t)-1) {
- return -1;
- }
- tc->destructor = (talloc_destructor_t)-1;
- if (d(ptr) == -1) {
- tc->destructor = d;
- return -1;
- }
- tc->destructor = NULL;
- }
-
- if (tc->parent) {
- _TLIST_REMOVE(tc->parent->child, tc);
- if (tc->parent->child) {
- tc->parent->child->parent = tc->parent;
- }
- } else {
- if (tc->prev) tc->prev->next = tc->next;
- if (tc->next) tc->next->prev = tc->prev;
- }
-
- tc->flags |= TALLOC_FLAG_LOOP;
-
- while (tc->child) {
- /* we need to work out who will own an abandoned child
- if it cannot be freed. In priority order, the first
- choice is owner of any remaining reference to this
- pointer, the second choice is our parent, and the
- final choice is the null context. */
- void *child = TC_PTR_FROM_CHUNK(tc->child);
- const void *new_parent = null_context;
- if (unlikely(tc->child->refs)) {
- struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
- if (p) new_parent = TC_PTR_FROM_CHUNK(p);
- }
- if (unlikely(_talloc_free(child) == -1)) {
- if (new_parent == null_context) {
- struct talloc_chunk *p = talloc_parent_chunk(ptr);
- if (p) new_parent = TC_PTR_FROM_CHUNK(p);
- }
- talloc_steal(new_parent, child);
- }
- }
-
- tc->flags |= TALLOC_FLAG_FREE;
-
- if (tc->flags & (TALLOC_FLAG_POOL|TALLOC_FLAG_POOLMEM)) {
- struct talloc_chunk *pool;
- unsigned int *pool_object_count;
-
- pool = (tc->flags & TALLOC_FLAG_POOL)
- ? tc : (struct talloc_chunk *)tc->pool;
-
- pool_object_count = talloc_pool_objectcount(pool);
-
- if (*pool_object_count == 0) {
- talloc_abort("Pool object count zero!");
- }
-
- *pool_object_count -= 1;
-
- if (*pool_object_count == 0) {
- free(pool);
- }
- }
- else {
- free(tc);
- }
- return 0;
-}
-
-/*
- move a lump of memory from one talloc context to another return the
- ptr on success, or NULL if it could not be transferred.
- passing NULL as ptr will always return NULL with no side effects.
-*/
-void *_talloc_steal(const void *new_ctx, const void *ptr)
-{
- struct talloc_chunk *tc, *new_tc;
-
- if (unlikely(!ptr)) {
- return NULL;
- }
-
- if (unlikely(new_ctx == NULL)) {
- new_ctx = null_context;
- }
-
- tc = talloc_chunk_from_ptr(ptr);
-
- if (unlikely(new_ctx == NULL)) {
- if (tc->parent) {
- _TLIST_REMOVE(tc->parent->child, tc);
- if (tc->parent->child) {
- tc->parent->child->parent = tc->parent;
- }
- } else {
- if (tc->prev) tc->prev->next = tc->next;
- if (tc->next) tc->next->prev = tc->prev;
- }
-
- tc->parent = tc->next = tc->prev = NULL;
- return discard_const_p(void, ptr);
- }
-
- new_tc = talloc_chunk_from_ptr(new_ctx);
-
- if (unlikely(tc == new_tc || tc->parent == new_tc)) {
- return discard_const_p(void, ptr);
- }
-
- if (tc->parent) {
- _TLIST_REMOVE(tc->parent->child, tc);
- if (tc->parent->child) {
- tc->parent->child->parent = tc->parent;
- }
- } else {
- if (tc->prev) tc->prev->next = tc->next;
- if (tc->next) tc->next->prev = tc->prev;
- }
-
- tc->parent = new_tc;
- if (new_tc->child) new_tc->child->parent = NULL;
- _TLIST_ADD(new_tc->child, tc);
-
- return discard_const_p(void, ptr);
-}
-
-
-
-/*
- remove a secondary reference to a pointer. This undo's what
- talloc_reference() has done. The context and pointer arguments
- must match those given to a talloc_reference()
-*/
-static inline int talloc_unreference(const void *context, const void *ptr)
-{
- struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
- struct talloc_reference_handle *h;
-
- if (unlikely(context == NULL)) {
- context = null_context;
- }
-
- for (h=tc->refs;h;h=h->next) {
- struct talloc_chunk *p = talloc_parent_chunk(h);
- if (p == NULL) {
- if (context == NULL) break;
- } else if (TC_PTR_FROM_CHUNK(p) == context) {
- break;
- }
- }
- if (h == NULL) {
- return -1;
- }
-
- return _talloc_free(h);
-}
-
-/*
- remove a specific parent context from a pointer. This is a more
- controlled varient of talloc_free()
-*/
-int talloc_unlink(const void *context, void *ptr)
-{
- struct talloc_chunk *tc_p, *new_p;
- void *new_parent;
-
- if (ptr == NULL) {
- return -1;
- }
-
- if (context == NULL) {
- context = null_context;
- }
-
- if (talloc_unreference(context, ptr) == 0) {
- return 0;
- }
-
- if (context == NULL) {
- if (talloc_parent_chunk(ptr) != NULL) {
- return -1;
- }
- } else {
- if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
- return -1;
- }
- }
-
- tc_p = talloc_chunk_from_ptr(ptr);
-
- if (tc_p->refs == NULL) {
- return _talloc_free(ptr);
- }
-
- new_p = talloc_parent_chunk(tc_p->refs);
- if (new_p) {
- new_parent = TC_PTR_FROM_CHUNK(new_p);
- } else {
- new_parent = NULL;
- }
-
- if (talloc_unreference(new_parent, ptr) != 0) {
- return -1;
- }
-
- talloc_steal(new_parent, ptr);
-
- return 0;
-}
-
-/*
- add a name to an existing pointer - va_list version
-*/
-static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
-
-static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap)
-{
- struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
- tc->name = talloc_vasprintf(ptr, fmt, ap);
- if (likely(tc->name)) {
- _talloc_set_name_const(tc->name, ".name");
- }
- return tc->name;
-}
-
-/*
- add a name to an existing pointer
-*/
-const char *talloc_set_name(const void *ptr, const char *fmt, ...)
-{
- const char *name;
- va_list ap;
- va_start(ap, fmt);
- name = talloc_set_name_v(ptr, fmt, ap);
- va_end(ap);
- return name;
-}
-
-
-/*
- create a named talloc pointer. Any talloc pointer can be named, and
- talloc_named() operates just like talloc() except that it allows you
- to name the pointer.
-*/
-void *talloc_named(const void *context, size_t size, const char *fmt, ...)
-{
- va_list ap;
- void *ptr;
- const char *name;
-
- ptr = __talloc(context, size);
- if (unlikely(ptr == NULL)) return NULL;
-
- va_start(ap, fmt);
- name = talloc_set_name_v(ptr, fmt, ap);
- va_end(ap);
-
- if (unlikely(name == NULL)) {
- _talloc_free(ptr);
- return NULL;
- }
-
- return ptr;
-}
-
-/*
- return the name of a talloc ptr, or "UNNAMED"
-*/
-const char *talloc_get_name(const void *ptr)
-{
- struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
- if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) {
- return ".reference";
- }
- if (likely(tc->name)) {
- return tc->name;
- }
- return "UNNAMED";
-}
-
-
-/*
- check if a pointer has the given name. If it does, return the pointer,
- otherwise return NULL
-*/
-void *talloc_check_name(const void *ptr, const char *name)
-{
- const char *pname;
- if (unlikely(ptr == NULL)) return NULL;
- pname = talloc_get_name(ptr);
- if (likely(pname == name || strcmp(pname, name) == 0)) {
- return discard_const_p(void, ptr);
- }
- return NULL;
-}
-
-static void talloc_abort_type_missmatch(const char *location,
- const char *name,
- const char *expected)
-{
- const char *reason;
-
- reason = talloc_asprintf(NULL,
- "%s: Type mismatch: name[%s] expected[%s]",
- location,
- name?name:"NULL",
- expected);
- if (!reason) {
- reason = "Type mismatch";
- }
-
- talloc_abort(reason);
-}
-
-void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location)
-{
- const char *pname;
-
- if (unlikely(ptr == NULL)) {
- talloc_abort_type_missmatch(location, NULL, name);
- return NULL;
- }
-
- pname = talloc_get_name(ptr);
- if (likely(pname == name || strcmp(pname, name) == 0)) {
- return discard_const_p(void, ptr);
- }
-
- talloc_abort_type_missmatch(location, pname, name);
- return NULL;
-}
-
-/*
- this is for compatibility with older versions of talloc
-*/
-void *talloc_init(const char *fmt, ...)
-{
- va_list ap;
- void *ptr;
- const char *name;
-
- /*
- * samba3 expects talloc_report_depth_cb(NULL, ...)
- * reports all talloc'ed memory, so we need to enable
- * null_tracking
- */
- talloc_enable_null_tracking();
-
- ptr = __talloc(NULL, 0);
- if (unlikely(ptr == NULL)) return NULL;
-
- va_start(ap, fmt);
- name = talloc_set_name_v(ptr, fmt, ap);
- va_end(ap);
-
- if (unlikely(name == NULL)) {
- _talloc_free(ptr);
- return NULL;
- }
-
- return ptr;
-}
-
-/*
- this is a replacement for the Samba3 talloc_destroy_pool functionality. It
- should probably not be used in new code. It's in here to keep the talloc
- code consistent across Samba 3 and 4.
-*/
-void talloc_free_children(void *ptr)
-{
- struct talloc_chunk *tc;
-
- if (unlikely(ptr == NULL)) {
- return;
- }
-
- tc = talloc_chunk_from_ptr(ptr);
-
- while (tc->child) {
- /* we need to work out who will own an abandoned child
- if it cannot be freed. In priority order, the first
- choice is owner of any remaining reference to this
- pointer, the second choice is our parent, and the
- final choice is the null context. */
- void *child = TC_PTR_FROM_CHUNK(tc->child);
- const void *new_parent = null_context;
- if (unlikely(tc->child->refs)) {
- struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
- if (p) new_parent = TC_PTR_FROM_CHUNK(p);
- }
- if (unlikely(_talloc_free(child) == -1)) {
- if (new_parent == null_context) {
- struct talloc_chunk *p = talloc_parent_chunk(ptr);
- if (p) new_parent = TC_PTR_FROM_CHUNK(p);
- }
- talloc_steal(new_parent, child);
- }
- }
-
- if ((tc->flags & TALLOC_FLAG_POOL)
- && (*talloc_pool_objectcount(tc) == 1)) {
- tc->pool = ((char *)tc + TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE);
-#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS)
- VALGRIND_MAKE_MEM_NOACCESS(
- tc->pool, tc->size - TALLOC_POOL_HDR_SIZE);
-#endif
- }
-}
-
-/*
- Allocate a bit of memory as a child of an existing pointer
-*/
-void *_talloc(const void *context, size_t size)
-{
- return __talloc(context, size);
-}
-
-/*
- externally callable talloc_set_name_const()
-*/
-void talloc_set_name_const(const void *ptr, const char *name)
-{
- _talloc_set_name_const(ptr, name);
-}
-
-/*
- create a named talloc pointer. Any talloc pointer can be named, and
- talloc_named() operates just like talloc() except that it allows you
- to name the pointer.
-*/
-void *talloc_named_const(const void *context, size_t size, const char *name)
-{
- return _talloc_named_const(context, size, name);
-}
-
-/*
- free a talloc pointer. This also frees all child pointers of this
- pointer recursively
-
- return 0 if the memory is actually freed, otherwise -1. The memory
- will not be freed if the ref_count is > 1 or the destructor (if
- any) returns non-zero
-*/
-int talloc_free(void *ptr)
-{
- return _talloc_free(ptr);
-}
-
-
-
-/*
- A talloc version of realloc. The context argument is only used if
- ptr is NULL
-*/
-void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name)
-{
- struct talloc_chunk *tc;
- void *new_ptr;
- bool malloced = false;
-
- /* size zero is equivalent to free() */
- if (unlikely(size == 0)) {
- _talloc_free(ptr);
- return NULL;
- }
-
- if (unlikely(size >= MAX_TALLOC_SIZE)) {
- return NULL;
- }
-
- /* realloc(NULL) is equivalent to malloc() */
- if (ptr == NULL) {
- return _talloc_named_const(context, size, name);
- }
-
- tc = talloc_chunk_from_ptr(ptr);
-
- /* don't allow realloc on referenced pointers */
- if (unlikely(tc->refs)) {
- return NULL;
- }
-
- /* don't let anybody try to realloc a talloc_pool */
- if (unlikely(tc->flags & TALLOC_FLAG_POOL)) {
- return NULL;
- }
-
- /* don't shrink if we have less than 1k to gain */
- if ((size < tc->size) && ((tc->size - size) < 1024)) {
- tc->size = size;
- return ptr;
- }
-
- /* by resetting magic we catch users of the old memory */
- tc->flags |= TALLOC_FLAG_FREE;
-
-#if ALWAYS_REALLOC
- new_ptr = malloc(size + TC_HDR_SIZE);
- if (new_ptr) {
- memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
- free(tc);
- }
-#else
- if (tc->flags & TALLOC_FLAG_POOLMEM) {
-
- new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE);
- *talloc_pool_objectcount((struct talloc_chunk *)
- (tc->pool)) -= 1;
-
- if (new_ptr == NULL) {
- new_ptr = malloc(TC_HDR_SIZE+size);
- malloced = true;
- }
-
- if (new_ptr) {
- memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE);
- }
- }
- else {
- new_ptr = realloc(tc, size + TC_HDR_SIZE);
- }
-#endif
- if (unlikely(!new_ptr)) {
- tc->flags &= ~TALLOC_FLAG_FREE;
- return NULL;
- }
-
- tc = (struct talloc_chunk *)new_ptr;
- tc->flags &= ~TALLOC_FLAG_FREE;
- if (malloced) {
- tc->flags &= ~TALLOC_FLAG_POOLMEM;
- }
- if (tc->parent) {
- tc->parent->child = tc;
- }
- if (tc->child) {
- tc->child->parent = tc;
- }
-
- if (tc->prev) {
- tc->prev->next = tc;
- }
- if (tc->next) {
- tc->next->prev = tc;
- }
-
- tc->size = size;
- _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
-
- return TC_PTR_FROM_CHUNK(tc);
-}
-
-/*
- a wrapper around talloc_steal() for situations where you are moving a pointer
- between two structures, and want the old pointer to be set to NULL
-*/
-void *_talloc_move(const void *new_ctx, const void *_pptr)
-{
- const void **pptr = discard_const_p(const void *,_pptr);
- void *ret = _talloc_steal(new_ctx, *pptr);
- (*pptr) = NULL;
- return ret;
-}
-
-/*
- return the total size of a talloc pool (subtree)
-*/
-size_t talloc_total_size(const void *ptr)
-{
- size_t total = 0;
- struct talloc_chunk *c, *tc;
-
- if (ptr == NULL) {
- ptr = null_context;
- }
- if (ptr == NULL) {
- return 0;
- }
-
- tc = talloc_chunk_from_ptr(ptr);
-
- if (tc->flags & TALLOC_FLAG_LOOP) {
- return 0;
- }
-
- tc->flags |= TALLOC_FLAG_LOOP;
-
- total = tc->size;
- for (c=tc->child;c;c=c->next) {
- total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
- }
-
- tc->flags &= ~TALLOC_FLAG_LOOP;
-
- return total;
-}
-
-/*
- return the total number of blocks in a talloc pool (subtree)
-*/
-size_t talloc_total_blocks(const void *ptr)
-{
- size_t total = 0;
- struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
-
- if (tc->flags & TALLOC_FLAG_LOOP) {
- return 0;
- }
-
- tc->flags |= TALLOC_FLAG_LOOP;
-
- total++;
- for (c=tc->child;c;c=c->next) {
- total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
- }
-
- tc->flags &= ~TALLOC_FLAG_LOOP;
-
- return total;
-}
-
-/*
- return the number of external references to a pointer
-*/
-size_t talloc_reference_count(const void *ptr)
-{
- struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
- struct talloc_reference_handle *h;
- size_t ret = 0;
-
- for (h=tc->refs;h;h=h->next) {
- ret++;
- }
- return ret;
-}
-
-/*
- report on memory usage by all children of a pointer, giving a full tree view
-*/
-void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
- void (*callback)(const void *ptr,
- int depth, int max_depth,
- int is_ref,
- void *private_data),
- void *private_data)
-{
- struct talloc_chunk *c, *tc;
-
- if (ptr == NULL) {
- ptr = null_context;
- }
- if (ptr == NULL) return;
-
- tc = talloc_chunk_from_ptr(ptr);
-
- if (tc->flags & TALLOC_FLAG_LOOP) {
- return;
- }
-
- callback(ptr, depth, max_depth, 0, private_data);
-
- if (max_depth >= 0 && depth >= max_depth) {
- return;
- }
-
- tc->flags |= TALLOC_FLAG_LOOP;
- for (c=tc->child;c;c=c->next) {
- if (c->name == TALLOC_MAGIC_REFERENCE) {
- struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c);
- callback(h->ptr, depth + 1, max_depth, 1, private_data);
- } else {
- talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data);
- }
- }
- tc->flags &= ~TALLOC_FLAG_LOOP;
-}
-
-static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f)
-{
- const char *name = talloc_get_name(ptr);
- FILE *f = (FILE *)_f;
-
- if (is_ref) {
- fprintf(f, "%*sreference to: %s\n", depth*4, "", name);
- return;
- }
-
- if (depth == 0) {
- fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n",
- (max_depth < 0 ? "full " :""), name,
- (unsigned long)talloc_total_size(ptr),
- (unsigned long)talloc_total_blocks(ptr));
- return;
- }
-
- fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n",
- depth*4, "",
- name,
- (unsigned long)talloc_total_size(ptr),
- (unsigned long)talloc_total_blocks(ptr),
- (int)talloc_reference_count(ptr), ptr);
-
-#if 0
- fprintf(f, "content: ");
- if (talloc_total_size(ptr)) {
- int tot = talloc_total_size(ptr);
- int i;
-
- for (i = 0; i < tot; i++) {
- if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) {
- fprintf(f, "%c", ((char *)ptr)[i]);
- } else {
- fprintf(f, "~%02x", ((char *)ptr)[i]);
- }
- }
- }
- fprintf(f, "\n");
-#endif
-}
-
-/*
- report on memory usage by all children of a pointer, giving a full tree view
-*/
-void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f)
-{
- talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f);
- fflush(f);
-}
-
-/*
- report on memory usage by all children of a pointer, giving a full tree view
-*/
-void talloc_report_full(const void *ptr, FILE *f)
-{
- talloc_report_depth_file(ptr, 0, -1, f);
-}
-
-/*
- report on memory usage by all children of a pointer
-*/
-void talloc_report(const void *ptr, FILE *f)
-{
- talloc_report_depth_file(ptr, 0, 1, f);
-}
-
-/*
- report on any memory hanging off the null context
-*/
-static void talloc_report_null(void)
-{
- if (talloc_total_size(null_context) != 0) {
- talloc_report(null_context, stderr);
- }
-}
-
-/*
- report on any memory hanging off the null context
-*/
-static void talloc_report_null_full(void)
-{
- if (talloc_total_size(null_context) != 0) {
- talloc_report_full(null_context, stderr);
- }
-}
-
-/*
- enable tracking of the NULL context
-*/
-void talloc_enable_null_tracking(void)
-{
- if (null_context == NULL) {
- null_context = _talloc_named_const(NULL, 0, "null_context");
- }
-}
-
-/*
- disable tracking of the NULL context
-*/
-void talloc_disable_null_tracking(void)
-{
- _talloc_free(null_context);
- null_context = NULL;
-}
-
-/*
- enable leak reporting on exit
-*/
-void talloc_enable_leak_report(void)
-{
- talloc_enable_null_tracking();
- atexit(talloc_report_null);
-}
-
-/*
- enable full leak reporting on exit
-*/
-void talloc_enable_leak_report_full(void)
-{
- talloc_enable_null_tracking();
- atexit(talloc_report_null_full);
-}
-
-/*
- talloc and zero memory.
-*/
-void *_talloc_zero(const void *ctx, size_t size, const char *name)
-{
- void *p = _talloc_named_const(ctx, size, name);
-
- if (p) {
- memset(p, '\0', size);
- }
-
- return p;
-}
-
-/*
- memdup with a talloc.
-*/
-void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name)
-{
- void *newp = _talloc_named_const(t, size, name);
-
- if (likely(newp)) {
- memcpy(newp, p, size);
- }
-
- return newp;
-}
-
-static inline char *__talloc_strlendup(const void *t, const char *p, size_t len)
-{
- char *ret;
-
- ret = (char *)__talloc(t, len + 1);
- if (unlikely(!ret)) return NULL;
-
- memcpy(ret, p, len);
- ret[len] = 0;
-
- _talloc_set_name_const(ret, ret);
- return ret;
-}
-
-/*
- strdup with a talloc
-*/
-char *talloc_strdup(const void *t, const char *p)
-{
- if (unlikely(!p)) return NULL;
- return __talloc_strlendup(t, p, strlen(p));
-}
-
-/*
- strndup with a talloc
-*/
-char *talloc_strndup(const void *t, const char *p, size_t n)
-{
- if (unlikely(!p)) return NULL;
- return __talloc_strlendup(t, p, strnlen(p, n));
-}
-
-static inline char *__talloc_strlendup_append(char *s, size_t slen,
- const char *a, size_t alen)
-{
- char *ret;
-
- ret = talloc_realloc(NULL, s, char, slen + alen + 1);
- if (unlikely(!ret)) return NULL;
-
- /* append the string and the trailing \0 */
- memcpy(&ret[slen], a, alen);
- ret[slen+alen] = 0;
-
- _talloc_set_name_const(ret, ret);
- return ret;
-}
-
-/*
- * Appends at the end of the string.
- */
-char *talloc_strdup_append(char *s, const char *a)
-{
- if (unlikely(!s)) {
- return talloc_strdup(NULL, a);
- }
-
- if (unlikely(!a)) {
- return s;
- }
-
- return __talloc_strlendup_append(s, strlen(s), a, strlen(a));
-}
-
-/*
- * Appends at the end of the talloc'ed buffer,
- * not the end of the string.
- */
-char *talloc_strdup_append_buffer(char *s, const char *a)
-{
- size_t slen;
-
- if (unlikely(!s)) {
- return talloc_strdup(NULL, a);
- }
-
- if (unlikely(!a)) {
- return s;
- }
-
- slen = talloc_get_size(s);
- if (likely(slen > 0)) {
- slen--;
- }
-
- return __talloc_strlendup_append(s, slen, a, strlen(a));
-}
-
-/*
- * Appends at the end of the string.
- */
-char *talloc_strndup_append(char *s, const char *a, size_t n)
-{
- if (unlikely(!s)) {
- return talloc_strdup(NULL, a);
- }
-
- if (unlikely(!a)) {
- return s;
- }
-
- return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n));
-}
-
-/*
- * Appends at the end of the talloc'ed buffer,
- * not the end of the string.
- */
-char *talloc_strndup_append_buffer(char *s, const char *a, size_t n)
-{
- size_t slen;
-
- if (unlikely(!s)) {
- return talloc_strdup(NULL, a);
- }
-
- if (unlikely(!a)) {
- return s;
- }
-
- slen = talloc_get_size(s);
- if (likely(slen > 0)) {
- slen--;
- }
-
- return __talloc_strlendup_append(s, slen, a, strnlen(a, n));
-}
-
-#ifndef HAVE_VA_COPY
-#ifdef HAVE___VA_COPY
-#define va_copy(dest, src) __va_copy(dest, src)
-#else
-#define va_copy(dest, src) (dest) = (src)
-#endif
-#endif
-
-char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
-{
- int len;
- char *ret;
- va_list ap2;
- char c;
-
- /* this call looks strange, but it makes it work on older solaris boxes */
- va_copy(ap2, ap);
- len = vsnprintf(&c, 1, fmt, ap2);
- va_end(ap2);
- if (unlikely(len < 0)) {
- return NULL;
- }
-
- ret = (char *)__talloc(t, len+1);
- if (unlikely(!ret)) return NULL;
-
- va_copy(ap2, ap);
- vsnprintf(ret, len+1, fmt, ap2);
- va_end(ap2);
-
- _talloc_set_name_const(ret, ret);
- return ret;
-}
-
-
-/*
- Perform string formatting, and return a pointer to newly allocated
- memory holding the result, inside a memory pool.
- */
-char *talloc_asprintf(const void *t, const char *fmt, ...)
-{
- va_list ap;
- char *ret;
-
- va_start(ap, fmt);
- ret = talloc_vasprintf(t, fmt, ap);
- va_end(ap);
- return ret;
-}
-
-static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
- const char *fmt, va_list ap)
- PRINTF_ATTRIBUTE(3,0);
-
-static inline char *__talloc_vaslenprintf_append(char *s, size_t slen,
- const char *fmt, va_list ap)
-{
- ssize_t alen;
- va_list ap2;
- char c;
-
- va_copy(ap2, ap);
- alen = vsnprintf(&c, 1, fmt, ap2);
- va_end(ap2);
-
- if (alen <= 0) {
- /* Either the vsnprintf failed or the format resulted in
- * no characters being formatted. In the former case, we
- * ought to return NULL, in the latter we ought to return
- * the original string. Most current callers of this
- * function expect it to never return NULL.
- */
- return s;
- }
-
- s = talloc_realloc(NULL, s, char, slen + alen + 1);
- if (!s) return NULL;
-
- va_copy(ap2, ap);
- vsnprintf(s + slen, alen + 1, fmt, ap2);
- va_end(ap2);
-
- _talloc_set_name_const(s, s);
- return s;
-}
-
-/**
- * Realloc @p s to append the formatted result of @p fmt and @p ap,
- * and return @p s, which may have moved. Good for gradually
- * accumulating output into a string buffer. Appends at the end
- * of the string.
- **/
-char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
-{
- if (unlikely(!s)) {
- return talloc_vasprintf(NULL, fmt, ap);
- }
-
- return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap);
-}
-
-/**
- * Realloc @p s to append the formatted result of @p fmt and @p ap,
- * and return @p s, which may have moved. Always appends at the
- * end of the talloc'ed buffer, not the end of the string.
- **/
-char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap)
-{
- size_t slen;
-
- if (unlikely(!s)) {
- return talloc_vasprintf(NULL, fmt, ap);
- }
-
- slen = talloc_get_size(s);
- if (likely(slen > 0)) {
- slen--;
- }
-
- return __talloc_vaslenprintf_append(s, slen, fmt, ap);
-}
-
-/*
- Realloc @p s to append the formatted result of @p fmt and return @p
- s, which may have moved. Good for gradually accumulating output
- into a string buffer.
- */
-char *talloc_asprintf_append(char *s, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- s = talloc_vasprintf_append(s, fmt, ap);
- va_end(ap);
- return s;
-}
-
-/*
- Realloc @p s to append the formatted result of @p fmt and return @p
- s, which may have moved. Good for gradually accumulating output
- into a buffer.
- */
-char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- s = talloc_vasprintf_append_buffer(s, fmt, ap);
- va_end(ap);
- return s;
-}
-
-/*
- alloc an array, checking for integer overflow in the array size
-*/
-void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
-{
- if (count >= MAX_TALLOC_SIZE/el_size) {
- return NULL;
- }
- return _talloc_named_const(ctx, el_size * count, name);
-}
-
-/*
- alloc an zero array, checking for integer overflow in the array size
-*/
-void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name)
-{
- if (count >= MAX_TALLOC_SIZE/el_size) {
- return NULL;
- }
- return _talloc_zero(ctx, el_size * count, name);
-}
-
-/*
- realloc an array, checking for integer overflow in the array size
-*/
-void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
-{
- if (count >= MAX_TALLOC_SIZE/el_size) {
- return NULL;
- }
- return _talloc_realloc(ctx, ptr, el_size * count, name);
-}
-
-/*
- a function version of talloc_realloc(), so it can be passed as a function pointer
- to libraries that want a realloc function (a realloc function encapsulates
- all the basic capabilities of an allocation library, which is why this is useful)
-*/
-void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
-{
- return _talloc_realloc(context, ptr, size, NULL);
-}
-
-
-static int talloc_autofree_destructor(void *ptr)
-{
- autofree_context = NULL;
- return 0;
-}
-
-static void talloc_autofree(void)
-{
- _talloc_free(autofree_context);
-}
-
-/*
- return a context which will be auto-freed on exit
- this is useful for reducing the noise in leak reports
-*/
-void *talloc_autofree_context(void)
-{
- if (autofree_context == NULL) {
- autofree_context = _talloc_named_const(NULL, 0, "autofree_context");
- talloc_set_destructor(autofree_context, talloc_autofree_destructor);
- atexit(talloc_autofree);
- }
- return autofree_context;
-}
-
-size_t talloc_get_size(const void *context)
-{
- struct talloc_chunk *tc;
-
- if (context == NULL)
- return 0;
-
- tc = talloc_chunk_from_ptr(context);
-
- return tc->size;
-}
-
-/*
- find a parent of this context that has the given name, if any
-*/
-void *talloc_find_parent_byname(const void *context, const char *name)
-{
- struct talloc_chunk *tc;
-
- if (context == NULL) {
- return NULL;
- }
-
- tc = talloc_chunk_from_ptr(context);
- while (tc) {
- if (tc->name && strcmp(tc->name, name) == 0) {
- return TC_PTR_FROM_CHUNK(tc);
- }
- while (tc && tc->prev) tc = tc->prev;
- if (tc) {
- tc = tc->parent;
- }
- }
- return NULL;
-}
-
-/*
- show the parentage of a context
-*/
-void talloc_show_parents(const void *context, FILE *file)
-{
- struct talloc_chunk *tc;
-
- if (context == NULL) {
- fprintf(file, "talloc no parents for NULL\n");
- return;
- }
-
- tc = talloc_chunk_from_ptr(context);
- fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
- while (tc) {
- fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
- while (tc && tc->prev) tc = tc->prev;
- if (tc) {
- tc = tc->parent;
- }
- }
- fflush(file);
-}
-
-/*
- return 1 if ptr is a parent of context
-*/
-int talloc_is_parent(const void *context, const void *ptr)
-{
- struct talloc_chunk *tc;
-
- if (context == NULL) {
- return 0;
- }
-
- tc = talloc_chunk_from_ptr(context);
- while (tc) {
- if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1;
- while (tc && tc->prev) tc = tc->prev;
- if (tc) {
- tc = tc->parent;
- }
- }
- return 0;
-}
diff --git a/libosmocore/src/timer.c b/libosmocore/src/timer.c
deleted file mode 100644
index 37d7d16..0000000
--- a/libosmocore/src/timer.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * (C) 2008,2009 by Holger Hans Peter Freyther <zecke@selfish.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <assert.h>
-#include <string.h>
-#include <osmocore/timer.h>
-
-static LLIST_HEAD(timer_list);
-static struct timeval s_nearest_time;
-static struct timeval s_select_time;
-
-#define MICRO_SECONDS 1000000LL
-
-#define TIME_SMALLER(left, right) \
- (left.tv_sec*MICRO_SECONDS+left.tv_usec) <= (right.tv_sec*MICRO_SECONDS+right.tv_usec)
-
-void bsc_add_timer(struct timer_list *timer)
-{
- struct timer_list *list_timer;
-
- /* TODO: Optimize and remember the closest item... */
- timer->active = 1;
-
- /* this might be called from within update_timers */
- llist_for_each_entry(list_timer, &timer_list, entry)
- if (timer == list_timer)
- return;
-
- timer->in_list = 1;
- llist_add(&timer->entry, &timer_list);
-}
-
-void bsc_schedule_timer(struct timer_list *timer, int seconds, int microseconds)
-{
- struct timeval current_time;
-
- gettimeofday(¤t_time, NULL);
- unsigned long long currentTime = current_time.tv_sec * MICRO_SECONDS + current_time.tv_usec;
- currentTime += seconds * MICRO_SECONDS + microseconds;
- timer->timeout.tv_sec = currentTime / MICRO_SECONDS;
- timer->timeout.tv_usec = currentTime % MICRO_SECONDS;
- bsc_add_timer(timer);
-}
-
-void bsc_del_timer(struct timer_list *timer)
-{
- if (timer->in_list) {
- timer->active = 0;
- timer->in_list = 0;
- llist_del(&timer->entry);
- }
-}
-
-int bsc_timer_pending(struct timer_list *timer)
-{
- return timer->active;
-}
-
-/*
- * if we have a nearest time return the delta between the current
- * time and the time of the nearest timer.
- * If the nearest timer timed out return NULL and then we will
- * dispatch everything after the select
- */
-struct timeval *bsc_nearest_timer()
-{
- struct timeval current_time;
-
- if (s_nearest_time.tv_sec == 0 && s_nearest_time.tv_usec == 0)
- return NULL;
-
- if (gettimeofday(¤t_time, NULL) == -1)
- return NULL;
-
- unsigned long long nearestTime = s_nearest_time.tv_sec * MICRO_SECONDS + s_nearest_time.tv_usec;
- unsigned long long currentTime = current_time.tv_sec * MICRO_SECONDS + current_time.tv_usec;
-
- if (nearestTime < currentTime) {
- s_select_time.tv_sec = 0;
- s_select_time.tv_usec = 0;
- } else {
- s_select_time.tv_sec = (nearestTime - currentTime) / MICRO_SECONDS;
- s_select_time.tv_usec = (nearestTime - currentTime) % MICRO_SECONDS;
- }
-
- return &s_select_time;
-}
-
-/*
- * Find the nearest time and update s_nearest_time
- */
-void bsc_prepare_timers()
-{
- struct timer_list *timer, *nearest_timer = NULL;
- llist_for_each_entry(timer, &timer_list, entry) {
- if (!nearest_timer || TIME_SMALLER(timer->timeout, nearest_timer->timeout)) {
- nearest_timer = timer;
- }
- }
-
- if (nearest_timer) {
- s_nearest_time = nearest_timer->timeout;
- } else {
- memset(&s_nearest_time, 0, sizeof(struct timeval));
- }
-}
-
-/*
- * fire all timers... and remove them
- */
-int bsc_update_timers()
-{
- struct timeval current_time;
- struct timer_list *timer, *tmp;
- int work = 0;
-
- gettimeofday(¤t_time, NULL);
-
- /*
- * The callbacks might mess with our list and in this case
- * even llist_for_each_entry_safe is not safe to use. To allow
- * del_timer, add_timer, schedule_timer to be called from within
- * the callback we jump through some loops.
- *
- * First we set the handled flag of each active timer to zero,
- * then we iterate over the list and execute the callbacks. As the
- * list might have been changed (specially the next) from within
- * the callback we have to start over again. Once every callback
- * is dispatched we will remove the non-active from the list.
- *
- * TODO: If this is a performance issue we can poison a global
- * variable in add_timer and del_timer and only then restart.
- */
- llist_for_each_entry(timer, &timer_list, entry) {
- timer->handled = 0;
- }
-
-restart:
- llist_for_each_entry(timer, &timer_list, entry) {
- if (!timer->handled && TIME_SMALLER(timer->timeout, current_time)) {
- timer->handled = 1;
- timer->active = 0;
- (*timer->cb)(timer->data);
- work = 1;
- goto restart;
- }
- }
-
- llist_for_each_entry_safe(timer, tmp, &timer_list, entry) {
- timer->handled = 0;
- if (!timer->active) {
- bsc_del_timer(timer);
- }
- }
-
- return work;
-}
-
-int bsc_timer_check(void)
-{
- struct timer_list *timer;
- int i = 0;
-
- llist_for_each_entry(timer, &timer_list, entry) {
- i++;
- }
- return i;
-}
diff --git a/libosmocore/src/tlv_parser.c b/libosmocore/src/tlv_parser.c
deleted file mode 100644
index 407e57a..0000000
--- a/libosmocore/src/tlv_parser.c
+++ /dev/null
@@ -1,171 +0,0 @@
-#include <stdio.h>
-#include <stdint.h>
-#include <osmocore/utils.h>
-#include <osmocore/tlv.h>
-
-struct tlv_definition tvlv_att_def;
-
-int tlv_dump(struct tlv_parsed *dec)
-{
- int i;
-
- for (i = 0; i <= 0xff; i++) {
- if (!dec->lv[i].val)
- continue;
- printf("T=%02x L=%d\n", i, dec->lv[i].len);
- }
- return 0;
-}
-
-/* o_tag: output: tag found
- * o_len: output: length of the data
- * o_val: output: pointer to the data
- * def: input: a structure defining the valid TLV tags / configurations
- * buf: input: the input data buffer to be parsed
- * buf_len: input: the length of the input data buffer
- *
- * Also, returns the number of bytes consumed by the TLV entry
- */
-int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val,
- const struct tlv_definition *def,
- const uint8_t *buf, int buf_len)
-{
- uint8_t tag;
- int len;
-
- tag = *buf;
- *o_tag = tag;
-
- /* FIXME: use tables for knwon IEI */
- switch (def->def[tag].type) {
- case TLV_TYPE_T:
- /* GSM TS 04.07 11.2.4: Type 1 TV or Type 2 T */
- *o_val = buf;
- *o_len = 0;
- len = 1;
- break;
- case TLV_TYPE_TV:
- *o_val = buf+1;
- *o_len = 1;
- len = 2;
- break;
- case TLV_TYPE_FIXED:
- *o_val = buf+1;
- *o_len = def->def[tag].fixed_len;
- len = def->def[tag].fixed_len + 1;
- break;
- case TLV_TYPE_TLV:
- /* GSM TS 04.07 11.2.4: Type 4 TLV */
- if (buf + 1 > buf + buf_len)
- return -1;
- *o_val = buf+2;
- *o_len = *(buf+1);
- len = *o_len + 2;
- if (len > buf_len)
- return -2;
- break;
- case TLV_TYPE_TvLV:
- if (*(buf+1) & 0x80) {
- /* like TLV, but without highest bit of len */
- if (buf + 1 > buf + buf_len)
- return -1;
- *o_val = buf+2;
- *o_len = *(buf+1) & 0x7f;
- len = *o_len + 2;
- if (len > buf_len)
- return -2;
- break;
- }
- /* like TL16V, fallthrough */
- case TLV_TYPE_TL16V:
- if (2 > buf_len)
- return -1;
- *o_val = buf+3;
- *o_len = *(buf+1) << 8 | *(buf+2);
- len = *o_len + 3;
- if (len > buf_len)
- return -2;
- break;
- default:
- return -3;
- }
-
- return len;
-}
-
-/* dec: output: a caller-allocated pointer to a struct tlv_parsed,
- * def: input: a structure defining the valid TLV tags / configurations
- * buf: input: the input data buffer to be parsed
- * buf_len: input: the length of the input data buffer
- * lv_tag: input: an initial LV tag at the start of the buffer
- * lv_tag2: input: a second initial LV tag following lv_tag
- */
-int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
- const uint8_t *buf, int buf_len, uint8_t lv_tag,
- uint8_t lv_tag2)
-{
- int ofs = 0, num_parsed = 0;
- uint16_t len;
-
- memset(dec, 0, sizeof(*dec));
-
- if (lv_tag) {
- if (ofs > buf_len)
- return -1;
- dec->lv[lv_tag].val = &buf[ofs+1];
- dec->lv[lv_tag].len = buf[ofs];
- len = dec->lv[lv_tag].len + 1;
- if (ofs + len > buf_len)
- return -2;
- num_parsed++;
- ofs += len;
- }
- if (lv_tag2) {
- if (ofs > buf_len)
- return -1;
- dec->lv[lv_tag2].val = &buf[ofs+1];
- dec->lv[lv_tag2].len = buf[ofs];
- len = dec->lv[lv_tag2].len + 1;
- if (ofs + len > buf_len)
- return -2;
- num_parsed++;
- ofs += len;
- }
-
- while (ofs < buf_len) {
- int rv;
- uint8_t tag;
- const uint8_t *val;
-
- rv = tlv_parse_one(&tag, &len, &val, def,
- &buf[ofs], buf_len-ofs);
- if (rv < 0)
- return rv;
- dec->lv[tag].val = val;
- dec->lv[tag].len = len;
- ofs += rv;
- num_parsed++;
- }
- //tlv_dump(dec);
- return num_parsed;
-}
-
-/* take a master (src) tlvdev and fill up all empty slots in 'dst' */
-void tlv_def_patch(struct tlv_definition *dst, const struct tlv_definition *src)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(dst->def); i++) {
- if (src->def[i].type == TLV_TYPE_NONE)
- continue;
- if (dst->def[i].type == TLV_TYPE_NONE)
- dst->def[i] = src->def[i];
- }
-}
-
-static __attribute__((constructor)) void on_dso_load_tlv(void)
-{
- int i;
- for (i = 0; i < ARRAY_SIZE(tvlv_att_def.def); i++)
- tvlv_att_def.def[i].type = TLV_TYPE_TvLV;
-}
diff --git a/libosmocore/src/utils.c b/libosmocore/src/utils.c
deleted file mode 100644
index 4dab064..0000000
--- a/libosmocore/src/utils.c
+++ /dev/null
@@ -1,50 +0,0 @@
-
-#include <string.h>
-#include <stdint.h>
-#include <errno.h>
-#include <stdio.h>
-
-#include <osmocore/utils.h>
-
-static char namebuf[255];
-const char *get_value_string(const struct value_string *vs, uint32_t val)
-{
- int i;
-
- for (i = 0;; i++) {
- if (vs[i].value == 0 && vs[i].str == NULL)
- break;
- if (vs[i].value == val)
- return vs[i].str;
- }
-
- snprintf(namebuf, sizeof(namebuf), "unknown 0x%x", val);
- return namebuf;
-}
-
-int get_string_value(const struct value_string *vs, const char *str)
-{
- int i;
-
- for (i = 0;; i++) {
- if (vs[i].value == 0 && vs[i].str == NULL)
- break;
- if (!strcasecmp(vs[i].str, str))
- return vs[i].value;
- }
- return -EINVAL;
-}
-
-char bcd2char(uint8_t bcd)
-{
- if (bcd < 0xa)
- return '0' + bcd;
- else
- return 'A' + (bcd - 0xa);
-}
-
-/* only works for numbers in ascci */
-uint8_t char2bcd(char c)
-{
- return c - 0x30;
-}
diff --git a/libosmocore/src/write_queue.c b/libosmocore/src/write_queue.c
deleted file mode 100644
index 618a8c0..0000000
--- a/libosmocore/src/write_queue.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Generic write queue implementation */
-/*
- * (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 General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <osmocore/write_queue.h>
-
-int write_queue_bfd_cb(struct bsc_fd *fd, unsigned int what)
-{
- struct write_queue *queue;
-
- queue = container_of(fd, struct write_queue, bfd);
-
- if (what & BSC_FD_READ)
- queue->read_cb(fd);
-
- if (what & BSC_FD_EXCEPT)
- queue->except_cb(fd);
-
- if (what & BSC_FD_WRITE) {
- struct msgb *msg;
-
- fd->when &= ~BSC_FD_WRITE;
- msg = msgb_dequeue(&queue->msg_queue);
- if (!msg)
- return -1;
-
- --queue->current_length;
- queue->write_cb(fd, msg);
- msgb_free(msg);
-
- if (!llist_empty(&queue->msg_queue))
- fd->when |= BSC_FD_WRITE;
- }
-
- return 0;
-}
-
-void write_queue_init(struct write_queue *queue, int max_length)
-{
- queue->max_length = max_length;
- queue->current_length = 0;
- queue->read_cb = NULL;
- queue->write_cb = NULL;
- queue->bfd.cb = write_queue_bfd_cb;
- INIT_LLIST_HEAD(&queue->msg_queue);
-}
-
-int write_queue_enqueue(struct write_queue *queue, struct msgb *data)
-{
-// if (queue->current_length + 1 >= queue->max_length)
-// LOGP(DMSC, LOGL_ERROR, "The queue is full. Dropping not yet implemented.\n");
-
- ++queue->current_length;
- msgb_enqueue(&queue->msg_queue, data);
- queue->bfd.when |= BSC_FD_WRITE;
-
- return 0;
-}
-
-void write_queue_clear(struct write_queue *queue)
-{
- while (!llist_empty(&queue->msg_queue)) {
- struct msgb *msg = msgb_dequeue(&queue->msg_queue);
- msgb_free(msg);
- }
-
- queue->current_length = 0;
- queue->bfd.when &= ~BSC_FD_WRITE;
-}
diff --git a/libosmocore/tests/Makefile.am b/libosmocore/tests/Makefile.am
deleted file mode 100644
index 0119a02c..0000000
--- a/libosmocore/tests/Makefile.am
+++ /dev/null
@@ -1,3 +0,0 @@
-if ENABLE_TESTS
-SUBDIRS = timer sms
-endif
diff --git a/libosmocore/tests/sms/Makefile.am b/libosmocore/tests/sms/Makefile.am
deleted file mode 100644
index a8f1ff6..0000000
--- a/libosmocore/tests/sms/Makefile.am
+++ /dev/null
@@ -1,5 +0,0 @@
-INCLUDES = $(all_includes) -I$(top_srcdir)/include
-noinst_PROGRAMS = sms_test
-
-sms_test_SOURCES = sms_test.c
-sms_test_LDADD = $(top_builddir)/src/libosmocore.la
diff --git a/libosmocore/tests/sms/sms_test.c b/libosmocore/tests/sms/sms_test.c
deleted file mode 100644
index f5183d5..0000000
--- a/libosmocore/tests/sms/sms_test.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <osmocore/msgb.h>
-#include <osmocore/gsm_utils.h>
-
-int main(int argc, char** argv)
-{
- printf("SMS testing\n");
- struct msgb *msg;
- uint8_t *sms;
- uint8_t i;
-
- /* test 7-bit coding/decoding */
- const char *input = "test text";
- uint8_t length;
- uint8_t coded[256];
- char result[256];
-
- length = gsm_7bit_encode(coded, input);
- gsm_7bit_decode(result, coded, length);
- if (strcmp(result, input) != 0) {
- printf("7 Bit coding failed... life sucks\n");
- printf("Wanted: '%s' got '%s'\n", input, result);
- }
-}
diff --git a/libosmocore/tests/timer/Makefile.am b/libosmocore/tests/timer/Makefile.am
deleted file mode 100644
index d3decf5..0000000
--- a/libosmocore/tests/timer/Makefile.am
+++ /dev/null
@@ -1,6 +0,0 @@
-INCLUDES = $(all_includes) -I$(top_srcdir)/include
-noinst_PROGRAMS = timer_test
-
-timer_test_SOURCES = timer_test.c
-timer_test_LDADD = $(top_builddir)/src/libosmocore.la
-
diff --git a/libosmocore/tests/timer/timer_test.c b/libosmocore/tests/timer/timer_test.c
deleted file mode 100644
index 1b458d8..0000000
--- a/libosmocore/tests/timer/timer_test.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * (C) 2008 by Holger Hans Peter Freyther <zecke@selfish.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdio.h>
-
-#include <osmocore/timer.h>
-#include <osmocore/select.h>
-
-#include "../../config.h"
-
-static void timer_fired(void *data);
-
-static struct timer_list timer_one = {
- .cb = timer_fired,
- .data = (void*)1,
-};
-
-static struct timer_list timer_two = {
- .cb = timer_fired,
- .data = (void*)2,
-};
-
-static struct timer_list timer_three = {
- .cb = timer_fired,
- .data = (void*)3,
-};
-
-static void timer_fired(void *_data)
-{
- unsigned long data = (unsigned long) _data;
- printf("Fired timer: %lu\n", data);
-
- if (data == 1) {
- bsc_schedule_timer(&timer_one, 3, 0);
- bsc_del_timer(&timer_two);
- } else if (data == 2) {
- printf("Should not be fired... bug in del_timer\n");
- } else if (data == 3) {
- printf("Timer fired not registering again\n");
- } else {
- printf("wtf... wrong data\n");
- }
-}
-
-int main(int argc, char** argv)
-{
- printf("Starting... timer\n");
-
- bsc_schedule_timer(&timer_one, 3, 0);
- bsc_schedule_timer(&timer_two, 5, 0);
- bsc_schedule_timer(&timer_three, 4, 0);
-
-#ifdef HAVE_SYS_SELECT_H
- while (1) {
- bsc_select_main(0);
- }
-#else
- printf("Select not supported on this platform!\n");
-#endif
-}
diff --git a/openbsc/configure.in b/openbsc/configure.in
index 66d4ee1..ef95920 100644
--- a/openbsc/configure.in
+++ b/openbsc/configure.in
@@ -17,8 +17,13 @@
dnl checks for libraries
AC_SEARCH_LIBS(crypt, crypt,
[LIBCRYPT="-lcrypt"; AC_DEFINE([VTY_CRYPT_PW], [], [Use crypt functionality of vty.])])
+AC_SEARCH_LIBS(gtp_new, gtp,
+ [LIBCRYPT="-lgtp"; AC_SUBST([GPRS_LIBGTP], [1])])
-PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.6)
+AM_CONDITIONAL(HAVE_LIBGTP, test "x$GPRS_LIBGTP" != "x")
+
+PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.11)
+PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.1.9)
dnl checks for header files
AC_HEADER_STDC
@@ -44,16 +49,17 @@
openbsc.pc
libsccp.pc
include/openbsc/Makefile
- include/vty/Makefile
include/sccp/Makefile
include/Makefile
src/Makefile
src/ipaccess/Makefile
src/gprs/Makefile
+ src/nat/Makefile
tests/Makefile
tests/debug/Makefile
tests/gsm0408/Makefile
tests/db/Makefile
tests/channel/Makefile
tests/sccp/Makefile
+ tests/bsc-nat/Makefile
Makefile)
diff --git a/openbsc/contrib/gprs/gb-proxy-unblock-bug.py b/openbsc/contrib/gprs/gb-proxy-unblock-bug.py
new file mode 100755
index 0000000..0cd4b87
--- /dev/null
+++ b/openbsc/contrib/gprs/gb-proxy-unblock-bug.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+
+"""
+demonstrate a unblock bug on the GB Proxy..
+"""
+
+bts_ns_reset = "\x02\x00\x81\x01\x01\x82\x1f\xe7\x04\x82\x1f\xe7"
+ns_reset_ack = "\x03\x01\x82\x1f\xe7\x04\x82\x1f\xe7"
+
+bts_ns_unblock = "\x06"
+ns_unblock_ack = "\x07"
+
+bts_bvc_reset_0 = "\x00\x00\x00\x00\x22\x04\x82\x00\x00\x07\x81\x03\x3b\x81\x02"
+ns_bvc_reset_0_ack = "\x00\x00\x00\x00\x23\x04\x82\x00\x00"
+
+bts_bvc_reset_8167 = "\x00\x00\x00\x00\x22\x04\x82\x1f\xe7\x07\x81\x08\x08\x88\x72\xf4\x80\x10\x1c\x00\x9c\x40"
+
+
+import socket
+socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+socket.bind(("0.0.0.0", 0))
+socket.setblocking(1)
+
+
+import sys
+port = int(sys.argv[1])
+print "Sending data to port: %d" % port
+
+def send_and_receive(packet):
+ socket.sendto(packet, ("127.0.0.1", port))
+
+ try:
+ data, addr = socket.recvfrom(4096)
+ except socket.error, e:
+ print "ERROR", e
+ import sys
+ sys.exit(0)
+ return data
+
+#send stuff once
+
+to_send = [
+ (bts_ns_reset, ns_reset_ack, "reset ack"),
+ (bts_ns_unblock, ns_unblock_ack, "unblock ack"),
+ (bts_bvc_reset_0, ns_bvc_reset_0_ack, "BVCI=0 reset ack"),
+]
+
+
+for (out, inp, type) in to_send:
+ res = send_and_receive(out)
+ if res != inp:
+ print "Failed to get the %s" % type
+ sys.exit(-1)
+
+import time
+time.sleep(3)
+res = send_and_receive(bts_bvc_reset_8167)
+print "Sent all messages... check wireshark for the last response"
diff --git a/openbsc/contrib/gprs/gprs-bssgp-histogram.lua b/openbsc/contrib/gprs/gprs-bssgp-histogram.lua
new file mode 100644
index 0000000..b1ab5df
--- /dev/null
+++ b/openbsc/contrib/gprs/gprs-bssgp-histogram.lua
@@ -0,0 +1,78 @@
+-- Simple LUA script to print the size of BSSGP messages over their type...
+
+do
+ local ip_bucket = {}
+
+ local pdu_types = {}
+ pdu_types[ 6] = "PAGING"
+ pdu_types[11] = "SUSPEND"
+ pdu_types[12] = "SUSPEND-ACK"
+ pdu_types[32] = "BVC-BLOCK"
+ pdu_types[33] = "BVC-BLOCK-ACK"
+ pdu_types[34] = "BVC-RESET"
+ pdu_types[35] = "BVC-RESET-ACK"
+ pdu_types[36] = "UNBLOCK"
+ pdu_types[37] = "UNBLOCK-ACK"
+ pdu_types[38] = "FLOW-CONTROL-BVC"
+ pdu_types[39] = "FLOW-CONTROL-BVC-ACK"
+ pdu_types[40] = "FLOW-CONTROL-MS"
+ pdu_types[41] = "FLOW-CONTROL-MS-ACK"
+ pdu_types[44] = "LLC-DISCARDED"
+
+ local function init_listener()
+ -- handle the port as NS over IP
+ local udp_port_table = DissectorTable.get("udp.port")
+ local gprs_ns_dis = Dissector.get("gprs_ns")
+ udp_port_table:add(23000,gprs_ns_dis)
+
+ -- bssgp filters
+ local bssgp_pdu_get = Field.new("bssgp.pdu_type")
+ local udp_length_get = Field.new("udp.length")
+
+ local tap = Listener.new("ip", "udp.port == 23000")
+ function tap.packet(pinfo,tvb,ip)
+ local pdu = bssgp_pdu_get()
+ local len = udp_length_get()
+
+ -- only handle bssgp, but we also want the IP frame
+ if not pdu then
+ return
+ end
+
+ pdu = tostring(pdu)
+ if tonumber(pdu) == 0 or tonumber(pdu) == 1 then
+ return
+ end
+
+ local ip_src = tostring(ip.ip_src)
+ local bssgp_histo = ip_bucket[ip_src]
+ if not bssgp_histo then
+ bssgp_histo = {}
+ ip_bucket[ip_src] = bssgp_histo
+ end
+
+ local key = pdu
+ local bucket = bssgp_histo[key]
+ if not bucket then
+ bucket = {}
+ bssgp_histo[key] = bucket
+ end
+
+ table.insert(bucket, tostring(len))
+ print("IP: " .. ip_src .. " PDU: " .. pdu_types[tonumber(pdu)] .. " Length: " .. tostring(len))
+ end
+
+ function tap.draw()
+ -- well... this will not be called...
+-- for ip,bssgp_histo in pairs(dumpers) do
+-- print("IP " .. ip)
+-- end
+ end
+
+ function tap.reset()
+ -- well... this will not be called...
+ end
+ end
+
+ init_listener()
+end
diff --git a/openbsc/contrib/gprs/gprs-split-trace-by-tlli.lua b/openbsc/contrib/gprs/gprs-split-trace-by-tlli.lua
new file mode 100644
index 0000000..018c377
--- /dev/null
+++ b/openbsc/contrib/gprs/gprs-split-trace-by-tlli.lua
@@ -0,0 +1,46 @@
+-- Create a file named by_ip/''ip_addess''.cap with all ip traffic of each ip host. (works for tshark only)
+-- Dump files are created for both source and destination hosts
+do
+ local dir = "by_tlli"
+ local dumpers = {}
+ local function init_listener()
+ local udp_port_table = DissectorTable.get("udp.port")
+ local gprs_ns_dis = Dissector.get("gprs_ns")
+ udp_port_table:add(23000,gprs_ns_dis)
+
+ local field_tlli = Field.new("bssgp.tlli")
+ local tap = Listener.new("ip", "udp.port == 23000")
+
+ -- we will be called once for every IP Header.
+ -- If there's more than one IP header in a given packet we'll dump the packet once per every header
+ function tap.packet(pinfo,tvb,ip)
+ local tlli = field_tlli()
+ if not tlli then
+ return
+ end
+
+ local tlli_str = tostring(tlli)
+ tlli_dmp = dumpers[tlli_str]
+ if not tlli_dmp then
+ local tlli_hex = string.format("0x%x", tonumber(tlli_str))
+ print("Creating dump for TLLI " .. tlli_hex)
+ tlli_dmp = Dumper.new_for_current(dir .. "/" .. tlli_hex .. ".pcap")
+ dumpers[tlli_str] = tlli_dmp
+ end
+ tlli_dmp:dump_current()
+ tlli_dmp:flush()
+ end
+ function tap.draw()
+ for tlli,dumper in pairs(dumpers) do
+ dumper:flush()
+ end
+ end
+ function tap.reset()
+ for tlli,dumper in pairs(dumpers) do
+ dumper:close()
+ end
+ dumpers = {}
+ end
+ end
+ init_listener()
+end
diff --git a/openbsc/contrib/gprs/gprs-verify-nu.lua b/openbsc/contrib/gprs/gprs-verify-nu.lua
new file mode 100644
index 0000000..e44fdd1
--- /dev/null
+++ b/openbsc/contrib/gprs/gprs-verify-nu.lua
@@ -0,0 +1,59 @@
+-- This script verifies that the N(U) is increasing...
+--
+do
+ local nu_state_src = {}
+
+ local function init_listener()
+ -- handle the port as NS over IP
+ local udp_port_table = DissectorTable.get("udp.port")
+ local gprs_ns_dis = Dissector.get("gprs_ns")
+ udp_port_table:add(23000,gprs_ns_dis)
+
+ -- we want to look here...
+ local llc_sapi_get = Field.new("llcgprs.sapib")
+ local llc_nu_get = Field.new("llcgprs.nu")
+ local bssgp_tlli_get = Field.new("bssgp.tlli")
+
+ local tap = Listener.new("ip", "udp.port == 23000")
+ function tap.packet(pinfo,tvb,ip)
+ local llc_sapi = llc_sapi_get()
+ local llc_nu = llc_nu_get()
+ local bssgp_tlli = bssgp_tlli_get()
+
+ if not llc_sapi or not llc_nu or not bssgp_tlli then
+ return
+ end
+
+ local ip_src = tostring(ip.ip_src)
+ local bssgp_tlli = tostring(bssgp_tlli)
+ local llc_nu = tostring(llc_nu)
+ local llc_sapi = tostring(llc_sapi)
+
+ local src_key = ip_src .. "-" .. bssgp_tlli .. "-" .. llc_sapi
+ local last_nu = nu_state_src[src_key]
+ if not last_nu then
+ -- print("Establishing mapping for " .. src_key)
+ nu_state_src[src_key] = llc_nu
+ return
+ end
+
+ local function tohex(number)
+ return string.format("0x%x", tonumber(number))
+ end
+
+ nu_state_src[src_key] = llc_nu
+ if tonumber(last_nu) + 1 ~= tonumber(llc_nu) then
+ print("JUMP in N(U) on TLLI " .. tohex(bssgp_tlli) .. " and SAPI: " .. llc_sapi .. " src: " .. ip_src)
+ print("\t last: " .. last_nu .. " now: " .. llc_nu)
+ end
+ end
+
+ function tap.draw()
+ end
+
+ function tap.reset()
+ end
+ end
+ init_listener()
+end
+
diff --git a/openbsc/include/Makefile.am b/openbsc/include/Makefile.am
index 56b2a33..a4acc23 100644
--- a/openbsc/include/Makefile.am
+++ b/openbsc/include/Makefile.am
@@ -1,3 +1,3 @@
-SUBDIRS = openbsc vty sccp
+SUBDIRS = openbsc sccp
noinst_HEADERS = mISDNif.h compat_af_isdn.h
diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am
index afb62de..465b21a 100644
--- a/openbsc/include/openbsc/Makefile.am
+++ b/openbsc/include/openbsc/Makefile.am
@@ -1,14 +1,15 @@
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 telnet_interface.h paging.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 \
- crc24.h gprs_bssgp.h gprs_llc.h gprs_ns.h \
- gb_proxy.h gprs_sgsn.h gsm_04_08_gprs.h sgsn.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
openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h
openbscdir = $(includedir)/openbsc
diff --git a/openbsc/include/openbsc/abis_nm.h b/openbsc/include/openbsc/abis_nm.h
index c20e4e1..b3bf27e 100644
--- a/openbsc/include/openbsc/abis_nm.h
+++ b/openbsc/include/openbsc/abis_nm.h
@@ -55,6 +55,8 @@
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 */
@@ -170,4 +172,7 @@
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);
+
#endif /* _NM_H */
diff --git a/openbsc/include/openbsc/abis_rsl.h b/openbsc/include/openbsc/abis_rsl.h
index 8e6774d..e87f430 100644
--- a/openbsc/include/openbsc/abis_rsl.h
+++ b/openbsc/include/openbsc/abis_rsl.h
@@ -68,7 +68,7 @@
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);
+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);
diff --git a/openbsc/include/openbsc/auth.h b/openbsc/include/openbsc/auth.h
new file mode 100644
index 0000000..0e5cad6
--- /dev/null
+++ b/openbsc/include/openbsc/auth.h
@@ -0,0 +1,10 @@
+#ifndef _AUTH_H
+#define _AUTH_H
+
+struct gsm_auth_tuple;
+struct gsm_subscriber;
+
+int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
+ struct gsm_subscriber *subscr, int key_seq);
+
+#endif /* _AUTH_H */
diff --git a/openbsc/include/openbsc/bsc_api.h b/openbsc/include/openbsc/bsc_api.h
index 51e344f..7747ada 100644
--- a/openbsc/include/openbsc/bsc_api.h
+++ b/openbsc/include/openbsc/bsc_api.h
@@ -1,6 +1,28 @@
/* GSM 08.08 like API for OpenBSC */
+#ifndef OPENBSC_BSC_API_H
+#define OPENBSC_BSC_API_H
+
#include "gsm_data.h"
+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, uint16_t ind);
+ void (*compl_l3)(struct gsm_subscriber_connection *conn,
+ struct msgb *msg, uint16_t chosen_channel);
+ void (*ass_compl)(struct gsm_subscriber_connection *conn,
+ uint16_t rr_cause);
+ void (*ass_fail)(struct gsm_subscriber_connection *conn,
+ uint16_t rr_cause);
+ void (*clear_request)(struct gsm_subscriber_connection *conn,
+ uint32_t cause);
+ void (*clear_compl)(struct gsm_subscriber_connection *conn);
+};
+int bsc_api_init(struct gsm_network *network, struct bsc_api *api);
int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, int link_id);
+int gsm0808_page(struct gsm_bts *bts, unsigned int page_group,
+ unsigned int mi_len, uint8_t *mi, int chan_type);
+
+#endif
diff --git a/openbsc/include/openbsc/bsc_msc.h b/openbsc/include/openbsc/bsc_msc.h
new file mode 100644
index 0000000..faf6faa
--- /dev/null
+++ b/openbsc/include/openbsc/bsc_msc.h
@@ -0,0 +1,51 @@
+/* Routines to talk to the MSC using the IPA Protocol */
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef BSC_MSC_H
+#define BSC_MSC_H
+
+#include <osmocore/write_queue.h>
+#include <osmocore/timer.h>
+
+struct bsc_msc_connection {
+ struct write_queue write_queue;
+ int is_connected;
+ int is_authenticated;
+ 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/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
new file mode 100644
index 0000000..cb0f761
--- /dev/null
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -0,0 +1,338 @@
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef BSC_NAT_H
+#define BSC_NAT_H
+
+#include "mgcp.h"
+
+#include <sys/types.h>
+#include <sccp/sccp_types.h>
+
+#include <osmocore/select.h>
+#include <osmocore/msgb.h>
+#include <osmocore/timer.h>
+#include <osmocore/write_queue.h>
+#include <osmocore/statistics.h>
+
+#include <regex.h>
+
+#define DIR_BSC 1
+#define DIR_MSC 2
+
+#define NAT_IPAC_PROTO_MGCP 0xfc
+
+struct bsc_nat;
+
+enum {
+ NAT_CON_TYPE_NONE,
+ NAT_CON_TYPE_LU,
+ NAT_CON_TYPE_CM_SERV_REQ,
+ NAT_CON_TYPE_PAG_RESP,
+ NAT_CON_TYPE_LOCAL_REJECT,
+ NAT_CON_TYPE_OTHER,
+};
+
+/*
+ * 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 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;
+
+ /* a back pointer */
+ struct bsc_nat *nat;
+};
+
+/*
+ * 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 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;
+
+ /* GSM audio handling. That is 32 * multiplex + ts */
+ int crcx;
+ int msc_timeslot;
+ int bsc_timeslot;
+
+ /* timeout handling */
+ struct timespec creation_time;
+};
+
+/**
+ * Stats per BSC
+ */
+struct bsc_config_stats {
+ struct {
+ struct counter *conn;
+ struct counter *calls;
+ } sccp;
+
+ struct {
+ struct counter *reconn;
+ } net;
+};
+
+/**
+ * One BSC entry in the config
+ */
+struct bsc_config {
+ struct llist_head entry;
+
+ char *token;
+ unsigned int lac;
+ int nr;
+
+ char *description;
+
+ /* imsi white and blacklist */
+ char *acc_lst_name;
+
+ int forbid_paging;
+
+ /* backpointer */
+ struct bsc_nat *nat;
+
+ struct bsc_config_stats stats;
+};
+
+/**
+ * BSCs point of view of endpoints
+ */
+struct bsc_endpoint {
+ /* 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 bsc_nat_acc_lst {
+ struct llist_head list;
+
+ /* 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_tos;
+
+ /* MGCP config */
+ struct mgcp_config *mgcp_cfg;
+ struct write_queue mgcp_queue;
+ u_int8_t mgcp_msg[4096];
+ int mgcp_length;
+
+ /* msc things */
+ char *msc_ip;
+ int msc_port;
+ int first_contact;
+ 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;
+
+ /* statistics */
+ struct bsc_nat_statistics stats;
+};
+
+/* create and init the structures */
+struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, unsigned int lac);
+struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num);
+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);
+
+/**
+ * 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 *);
+
+/**
+ * MGCP/Audio handling
+ */
+int bsc_write_mgcp(struct bsc_connection *bsc, const u_int8_t *data, unsigned int length);
+int bsc_mgcp_assign(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, 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]);
+int bsc_mgcp_extract_ci(const char *resp);
+
+
+int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int id);
+
+/* 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 *);
+
+#endif
diff --git a/openbsc/include/openbsc/chan_alloc.h b/openbsc/include/openbsc/chan_alloc.h
index d4f5858..bbbe536 100644
--- a/openbsc/include/openbsc/chan_alloc.h
+++ b/openbsc/include/openbsc/chan_alloc.h
@@ -23,6 +23,8 @@
#include "gsm_subscriber.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);
@@ -34,11 +36,8 @@
/* Regular physical channel (TS) */
void ts_free(struct gsm_bts_trx_ts *ts);
-/* Find an allocated channel */
-struct gsm_lchan *lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr);
-
/* Find an allocated channel for a specified subscriber */
-struct gsm_lchan *lchan_for_subscr(struct gsm_subscriber *subscr);
+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);
diff --git a/openbsc/include/openbsc/db.h b/openbsc/include/openbsc/db.h
index 1782efb..2a521f0 100644
--- a/openbsc/include/openbsc/db.h
+++ b/openbsc/include/openbsc/db.h
@@ -44,14 +44,14 @@
int db_sync_equipment(struct gsm_equipment *equip);
/* auth info */
-int get_authinfo_by_subscr(struct gsm_auth_info *ainfo,
- struct gsm_subscriber *subscr);
-int set_authinfo_for_subscr(struct gsm_auth_info *ainfo,
- struct gsm_subscriber *subscr);
-int get_authtuple_by_subscr(struct gsm_auth_tuple *atuple,
- struct gsm_subscriber *subscr);
-int set_authtuple_for_subscr(struct gsm_auth_tuple *atuple,
- struct gsm_subscriber *subscr);
+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);
diff --git a/openbsc/include/openbsc/debug.h b/openbsc/include/openbsc/debug.h
index 65fd0bb..eb290e4 100644
--- a/openbsc/include/openbsc/debug.h
+++ b/openbsc/include/openbsc/debug.h
@@ -32,6 +32,9 @@
DGPRS,
DNS,
DBSSGP,
+ DLLC,
+ DSNDCP,
+ DNAT,
Debug_LastEntry,
};
@@ -40,15 +43,27 @@
#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;
diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h
index db236b5..18ded22 100644
--- a/openbsc/include/openbsc/gb_proxy.h
+++ b/openbsc/include/openbsc/gb_proxy.h
@@ -6,18 +6,11 @@
#include <osmocore/msgb.h>
#include <openbsc/gprs_ns.h>
-#include <vty/command.h>
+#include <osmocom/vty/command.h>
struct gbproxy_config {
/* parsed from config file */
- u_int32_t nsip_listen_ip;
- u_int16_t nsip_listen_port;
-
- u_int32_t nsip_sgsn_ip;
- u_int16_t nsip_sgsn_port;
-
u_int16_t nsip_sgsn_nsei;
- u_int16_t nsip_sgsn_nsvci;
/* misc */
struct gprs_ns_inst *nsi;
@@ -39,4 +32,8 @@
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/openbsc/include/openbsc/gprs_bssgp.h b/openbsc/include/openbsc/gprs_bssgp.h
index d3ccb12..e432cf7 100644
--- a/openbsc/include/openbsc/gprs_bssgp.h
+++ b/openbsc/include/openbsc/gprs_bssgp.h
@@ -3,6 +3,10 @@
#include <stdint.h>
+/* Section 5.4.1 */
+#define BVCI_SIGNALLING 0x0000
+#define BVCI_PTM 0x0001
+
/* Section 11.3.26 / Table 11.27 */
enum bssgp_pdu_type {
/* PDUs between RL and BSSGP SAPs */
@@ -149,9 +153,44 @@
/* gprs_bssgp.c */
+#define BVC_S_BLOCKED 0x0001
+
+/* The per-BTS context that we keep on the SGSN side of the BSSGP link */
+struct bssgp_bvc_ctx {
+ struct llist_head list;
+
+ /* parsed RA ID and Cell ID of the remote BTS */
+ struct gprs_ra_id ra_id;
+ uint16_t cell_id;
+
+ /* NSEI and BVCI of underlying Gb link. Together they
+ * uniquely identify a link to a BTS (5.4.4) */
+ uint16_t bvci;
+ uint16_t nsei;
+
+ uint32_t state;
+
+ struct rate_ctr_group *ctrg;
+
+ /* we might want to add this as a shortcut later, avoiding the NSVC
+ * lookup for every packet, similar to a routing cache */
+ //struct gprs_nsvc *nsvc;
+};
+extern struct llist_head bssgp_bvc_ctxts;
+/* Find a BTS Context based on parsed RA ID and Cell ID */
+struct bssgp_bvc_ctx *btsctx_by_raid_cid(const struct gprs_ra_id *raid, uint16_t cid);
+/* Find a BTS context based on BVCI+NSEI tuple */
+struct bssgp_bvc_ctx *btsctx_by_bvci_nsei(uint16_t bvci, uint16_t nsei);
+
#include <osmocore/tlv.h>
-extern int gprs_bssgp_rcvmsg(struct msgb *msg);
+/* 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 */
@@ -160,4 +199,34 @@
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/openbsc/include/openbsc/gprs_gmm.h b/openbsc/include/openbsc/gprs_gmm.h
new file mode 100644
index 0000000..b91b489
--- /dev/null
+++ b/openbsc/include/openbsc/gprs_gmm.h
@@ -0,0 +1,18 @@
+#ifndef _GPRS_GMM_H
+#define _GPRS_GMM_H
+
+#include <osmocore/msgb.h>
+#include <openbsc/gprs_sgsn.h>
+
+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/openbsc/include/openbsc/gprs_llc.h b/openbsc/include/openbsc/gprs_llc.h
index 5a6682d..0ddb518 100644
--- a/openbsc/include/openbsc/gprs_llc.h
+++ b/openbsc/include/openbsc/gprs_llc.h
@@ -2,6 +2,7 @@
#define _GPRS_LLC_H
#include <stdint.h>
+#include <openbsc/gprs_sgsn.h>
/* Section 4.7 LLC Layer Structure */
enum gprs_llc_sapi {
@@ -26,7 +27,123 @@
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;
+
+ 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;
+
+ /* 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);
-int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command);
+
+/* 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_vty_init(void);
#endif
diff --git a/openbsc/include/openbsc/gprs_ns.h b/openbsc/include/openbsc/gprs_ns.h
index 4ccf4c7..953c364 100644
--- a/openbsc/include/openbsc/gprs_ns.h
+++ b/openbsc/include/openbsc/gprs_ns.h
@@ -107,6 +107,7 @@
enum gprs_ns_ll {
GPRS_NS_LL_UDP,
GPRS_NS_LL_E1,
+ GPRS_NS_LL_FR_GRE,
};
enum gprs_ns_evt {
@@ -130,15 +131,18 @@
uint16_t timeout[NS_TIMERS_COUNT];
- /* which link-layer are we based on? */
- enum gprs_ns_ll ll;
-
- union {
- /* NS-over-IP specific bits */
- struct {
- struct bsc_fd fd;
- } nsip;
- };
+ /* 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 {
@@ -168,10 +172,16 @@
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;
};
};
@@ -181,15 +191,11 @@
/* Destroy a NS protocol instance */
void gprs_ns_destroy(struct gprs_ns_inst *nsi);
-/* Listen for incoming GPRS packets */
-int nsip_listen(struct gprs_ns_inst *nsi, uint16_t udp_port);
+/* Listen for incoming GPRS packets via NS/UDP */
+int gprs_ns_nsip_listen(struct gprs_ns_inst *nsi);
struct sockaddr_in;
-/* main entry point, here incoming NS frames enter */
-int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
- struct sockaddr_in *saddr);
-
/* main function for higher layers (BSSGP) to send NS messages */
int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg);
@@ -197,8 +203,8 @@
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 */
-int nsip_listen(struct gprs_ns_inst *nsi, uint16_t udp_port);
+/* 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,
@@ -208,8 +214,19 @@
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/openbsc/include/openbsc/gprs_ns_frgre.h b/openbsc/include/openbsc/gprs_ns_frgre.h
new file mode 100644
index 0000000..abcd43f
--- /dev/null
+++ b/openbsc/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/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h
index bdc0b1c..0801150 100644
--- a/openbsc/include/openbsc/gprs_sgsn.h
+++ b/openbsc/include/openbsc/gprs_sgsn.h
@@ -2,6 +2,15 @@
#define _GPRS_SGSN_H
#include <stdint.h>
+#include <netinet/in.h>
+
+#include <osmocore/gsm48.h>
+
+#define GSM_IMSI_LENGTH 17
+#define GSM_IMEI_LENGTH 17
+#define GSM_EXTENSION_LENGTH 15
+
+struct gprs_llc_lle;
/* TS 04.08 4.1.3.3 GMM mobility management states on the network side */
enum gprs_mm_state {
@@ -16,6 +25,34 @@
GPRS_ALGO_GEA0,
GPRS_ALGO_GEA1,
GPRS_ALGO_GEA2,
+ GPRS_ALGO_GEA3,
+};
+
+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
@@ -28,6 +65,7 @@
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 */
@@ -63,42 +101,18 @@
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;
-};
+ unsigned int T; /* Txxxx number */
+ unsigned int num_T_exp; /* number of consecutive T expirations */
-enum pdp_ctx_state {
- PDP_STAE_NONE,
-};
-
-enum pdp_type {
- PDP_TYPE_NONE,
-};
-
-struct sgsn_pdp_ctx {
- struct llist_head list;
-
- unsigned int id;
- enum pdp_ctx_state state;
- enum pdp_type type;
- uint32_t addresss;
- char *apn_subscribed;
- char *apn_used;
- uint16_t nsapi;
- uint8_t ti; /* transaction identifier */
- uint32_t ggsn_in_use;
- 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;
+ enum gprs_t3350_mode t3350_mode;
+ uint8_t t3370_id_type;
};
/* look-up a SGSN MM context based on TLLI + RAI */
@@ -111,4 +125,86 @@
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t tlli,
const struct gprs_ra_id *raid);
+
+enum pdp_ctx_state {
+ PDP_STATE_NONE,
+ PDP_STATE_CR_REQ,
+ PDP_STATE_CR_CONF,
+};
+
+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;
+};
+
+
+/* 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;
+ 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_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);
+
#endif /* _GPRS_SGSN_H */
diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h
index 74dcbe5..11bca54 100644
--- a/openbsc/include/openbsc/gsm_04_08.h
+++ b/openbsc/include/openbsc/gsm_04_08.h
@@ -11,6 +11,7 @@
struct gsm_subscriber;
struct gsm_network;
struct gsm_trans;
+struct gsm_subscriber_connection;
#define GSM48_ALLOC_SIZE 1024
#define GSM48_ALLOC_HEADROOM 128
@@ -23,19 +24,18 @@
/* 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);
int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id);
enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci);
enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci);
-int gsm48_tx_mm_info(struct gsm_lchan *lchan);
-int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand, int key_seq);
-int gsm48_tx_mm_auth_rej(struct gsm_lchan *lchan);
-int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans);
-
+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_lchan *lchan, u_int8_t apdu_id,
+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,
@@ -52,12 +52,15 @@
int h_len);
int send_siemens_mrpci(struct gsm_lchan *lchan, u_int8_t *classmark2_lv);
-int gsm48_paging_extract_mi(struct msgb *msg, char *mi_string, u_int8_t *mi_type);
+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 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);
#endif
diff --git a/openbsc/include/openbsc/gsm_04_08_gprs.h b/openbsc/include/openbsc/gsm_04_08_gprs.h
index 344b277..baa513b 100644
--- a/openbsc/include/openbsc/gsm_04_08_gprs.h
+++ b/openbsc/include/openbsc/gsm_04_08_gprs.h
@@ -2,6 +2,7 @@
#define _GSM48_GPRS_H
#include <stdint.h>
+#include <osmocore/protocol/gsm_04_08.h>
/* Table 10.4 / 10.4a, GPRS Mobility Management (GMM) */
#define GSM48_MT_GMM_ATTACH_REQ 0x01
@@ -46,6 +47,15 @@
#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
@@ -53,13 +63,17 @@
#define GPRS_UPD_T_PERIODIC 3
enum gsm48_gprs_ie_mm {
- GSM48_IE_GMM_TIMER_READY = 0x17, /* 10.5.7.3 */
+ 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_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 {
@@ -72,6 +86,11 @@
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 */
@@ -344,7 +363,4 @@
int gprs_tlli_type(uint32_t tlli);
-struct gsm_bts *gsm48_bts_by_ra_id(struct gsm_network *net,
- const uint8_t *buf, unsigned int len);
-
#endif /* _GSM48_GPRS_H */
diff --git a/openbsc/include/openbsc/gsm_04_11.h b/openbsc/include/openbsc/gsm_04_11.h
index 8127af1..61eaffd 100644
--- a/openbsc/include/openbsc/gsm_04_11.h
+++ b/openbsc/include/openbsc/gsm_04_11.h
@@ -3,6 +3,8 @@
#include <osmocore/protocol/gsm_04_11.h>
+#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */
+
/* SMS deliver PDU */
struct sms_deliver {
u_int8_t mti:2; /* message type indicator */
@@ -23,9 +25,7 @@
struct msgb;
-int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id);
-
-int gsm411_send_sms_lchan(struct gsm_subscriber_connection *conn, struct gsm_sms *sms);
+int gsm0411_rcv_sms(struct gsm_subscriber_connection *conn, struct msgb *msg, u_int8_t link_id);
struct gsm_sms *sms_alloc(void);
void sms_free(struct gsm_sms *sms);
@@ -33,4 +33,5 @@
void _gsm411_sms_trans_free(struct gsm_trans *trans);
int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
struct gsm_sms *sms);
+void gsm411_sapi_n_reject(struct gsm_subscriber_connection *conn);
#endif
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 91527c9..f3f4ed3 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -65,6 +65,7 @@
enum gsm_hooks {
GSM_HOOK_NM_SWLOAD,
GSM_HOOK_RR_PAGING,
+ GSM_HOOK_RR_SECURITY,
};
enum gsm_paging_event {
@@ -104,6 +105,14 @@
#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,
@@ -150,12 +159,14 @@
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 {
@@ -175,6 +186,16 @@
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;
};
/* Maximum number of neighbor cells whose average we track */
@@ -192,6 +213,9 @@
};
#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? */
@@ -205,6 +229,7 @@
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 */
};
@@ -220,6 +245,7 @@
* Operations that have a state and might be pending
*/
struct gsm_loc_updating_operation *loc_operation;
+ struct gsm_security_operation *sec_operation;
/* use count. how many users use this channel */
unsigned int use_count;
@@ -256,6 +282,8 @@
} encr;
struct timer_list T3101;
+ struct timer_list T3111;
+ struct timer_list error_timer;
/* AMR bits */
struct gsm48_multi_rate_conf mr_conf;
@@ -322,6 +350,8 @@
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;
@@ -428,6 +458,8 @@
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 */
@@ -623,6 +655,7 @@
int (*mncc_recv) (struct gsm_network *net, int msg_type, void *arg);
struct llist_head upqueue;
struct llist_head trans_list;
+ struct bsc_api *bsc_api;
unsigned int num_bts;
struct llist_head bts_list;
@@ -644,6 +677,7 @@
struct {
enum rrlp_mode mode;
} rrlp;
+ int msc_prio;
};
#define SMS_HDR_SIZE 128
diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h
index 0653996..527056b 100644
--- a/openbsc/include/openbsc/gsm_subscriber.h
+++ b/openbsc/include/openbsc/gsm_subscriber.h
@@ -82,7 +82,7 @@
struct gsm_subscriber *subscr_get_by_id(struct gsm_network *net,
unsigned long long id);
int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason);
-void subscr_put_channel(struct gsm_lchan *lchan);
+void subscr_put_channel(struct gsm_subscriber_connection *conn);
void subscr_get_channel(struct gsm_subscriber *subscr,
int type, gsm_cbfn *cbfn, void *param);
diff --git a/openbsc/include/openbsc/osmo_msc.h b/openbsc/include/openbsc/osmo_msc.h
new file mode 100644
index 0000000..d5d8917
--- /dev/null
+++ b/openbsc/include/openbsc/osmo_msc.h
@@ -0,0 +1,10 @@
+/* Routines for the MSC handling */
+
+#ifndef OSMO_MSC_H
+#define OSMO_MSC_H
+
+#include "bsc_api.h"
+
+struct bsc_api *msc_bsc_api();
+
+#endif
diff --git a/openbsc/include/openbsc/sgsn.h b/openbsc/include/openbsc/sgsn.h
index 2dc53c1..eccfdea 100644
--- a/openbsc/include/openbsc/sgsn.h
+++ b/openbsc/include/openbsc/sgsn.h
@@ -6,16 +6,32 @@
#include <osmocore/msgb.h>
#include <openbsc/gprs_ns.h>
+#include <openbsc/gprs_sgsn.h>
struct sgsn_config {
/* parsed from config file */
- u_int32_t nsip_listen_ip;
- u_int16_t nsip_listen_port;
+
+ 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 */
@@ -27,4 +43,23 @@
/* 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(uint32_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/openbsc/include/openbsc/socket.h b/openbsc/include/openbsc/socket.h
new file mode 100644
index 0000000..4d31611
--- /dev/null
+++ b/openbsc/include/openbsc/socket.h
@@ -0,0 +1,14 @@
+#ifndef _BSC_SOCKET_H
+#define _BSC_SOCKET_H
+
+#include <sys/types.h>
+#include <osmocore/select.h>
+
+#ifndef IPPROTO_GRE
+#define IPPROTO_GRE 47
+#endif
+
+int make_sock(struct bsc_fd *bfd, int proto, u_int32_t ip, u_int16_t port,
+ int (*cb)(struct bsc_fd *fd, unsigned int what));
+
+#endif /* _BSC_SOCKET_H */
diff --git a/openbsc/include/openbsc/telnet_interface.h b/openbsc/include/openbsc/telnet_interface.h
deleted file mode 100644
index b8c36b6..0000000
--- a/openbsc/include/openbsc/telnet_interface.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* minimalistic telnet/network interface it might turn into a wire interface */
-/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef TELNET_INTERFACE_H
-#define TELNET_INTERFACE_H
-
-#include "gsm_data.h"
-#include <openbsc/debug.h>
-#include <osmocore/select.h>
-
-#include <vty/vty.h>
-
-struct telnet_connection {
- struct llist_head entry;
- struct gsm_network *network;
- struct bsc_fd fd;
- struct vty *vty;
- struct log_target *dbg;
-};
-
-
-void telnet_init(struct gsm_network *network, int port);
-
-int bsc_vty_init(struct gsm_network *net);
-
-#endif
diff --git a/openbsc/include/openbsc/vty.h b/openbsc/include/openbsc/vty.h
index f1b1148..3346a2c 100644
--- a/openbsc/include/openbsc/vty.h
+++ b/openbsc/include/openbsc/vty.h
@@ -1,10 +1,37 @@
#ifndef OPENBSC_VTY_H
#define OPENBSC_VTY_H
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/buffer.h>
+#include <osmocom/vty/command.h>
+
struct gsm_network;
struct vty;
-void openbsc_vty_add_cmds(void);
+void logging_vty_add_cmds(void);
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,
+ NAT_NODE,
+ BSC_NODE,
+};
+
#endif
diff --git a/openbsc/include/sccp/sccp.h b/openbsc/include/sccp/sccp.h
index 604a2ac..84ae914 100644
--- a/openbsc/include/sccp/sccp.h
+++ b/openbsc/include/sccp/sccp.h
@@ -148,6 +148,11 @@
u_int32_t sccp_src_ref_to_int(struct sccp_source_reference *ref);
struct sccp_source_reference sccp_src_ref_from_int(u_int32_t);
+struct msgb *sccp_create_refuse(struct sccp_source_reference *src_ref, int cause, uint8_t *data, int length);
+struct msgb *sccp_create_cc(struct sccp_source_reference *src_ref, struct sccp_source_reference *dst_ref);
+struct msgb *sccp_create_rlsd(struct sccp_source_reference *src_ref, struct sccp_source_reference *dst_ref, int cause);
+struct msgb *sccp_create_dt1(struct sccp_source_reference *dst_ref, uint8_t *data, uint8_t len);
+
/**
* Below this are helper functions and structs for parsing SCCP messages
*/
diff --git a/openbsc/include/vty/Makefile.am b/openbsc/include/vty/Makefile.am
deleted file mode 100644
index 1674766..0000000
--- a/openbsc/include/vty/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-noinst_HEADERS = buffer.h command.h vector.h vty.h
diff --git a/openbsc/include/vty/buffer.h b/openbsc/include/vty/buffer.h
deleted file mode 100644
index c9467a9..0000000
--- a/openbsc/include/vty/buffer.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Buffering to output and input.
- * Copyright (C) 1998 Kunihiro Ishiguro
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef _ZEBRA_BUFFER_H
-#define _ZEBRA_BUFFER_H
-
-#include <sys/types.h>
-
-/* Create a new buffer. Memory will be allocated in chunks of the given
- size. If the argument is 0, the library will supply a reasonable
- default size suitable for buffering socket I/O. */
-struct buffer *buffer_new(void *ctx, size_t);
-
-/* Free all data in the buffer. */
-void buffer_reset(struct buffer *);
-
-/* This function first calls buffer_reset to release all buffered data.
- Then it frees the struct buffer itself. */
-void buffer_free(struct buffer *);
-
-/* Add the given data to the end of the buffer. */
-extern void buffer_put(struct buffer *, const void *, size_t);
-/* Add a single character to the end of the buffer. */
-extern void buffer_putc(struct buffer *, u_char);
-/* Add a NUL-terminated string to the end of the buffer. */
-extern void buffer_putstr(struct buffer *, const char *);
-
-/* Combine all accumulated (and unflushed) data inside the buffer into a
- single NUL-terminated string allocated using XMALLOC(MTYPE_TMP). Note
- that this function does not alter the state of the buffer, so the data
- is still inside waiting to be flushed. */
-char *buffer_getstr(struct buffer *);
-
-/* Returns 1 if there is no pending data in the buffer. Otherwise returns 0. */
-int buffer_empty(struct buffer *);
-
-typedef enum {
- /* An I/O error occurred. The buffer should be destroyed and the
- file descriptor should be closed. */
- BUFFER_ERROR = -1,
-
- /* The data was written successfully, and the buffer is now empty
- (there is no pending data waiting to be flushed). */
- BUFFER_EMPTY = 0,
-
- /* There is pending data in the buffer waiting to be flushed. Please
- try flushing the buffer when select indicates that the file descriptor
- is writeable. */
- BUFFER_PENDING = 1
-} buffer_status_t;
-
-/* Try to write this data to the file descriptor. Any data that cannot
- be written immediately is added to the buffer queue. */
-extern buffer_status_t buffer_write(struct buffer *, int fd,
- const void *, size_t);
-
-/* This function attempts to flush some (but perhaps not all) of
- the queued data to the given file descriptor. */
-extern buffer_status_t buffer_flush_available(struct buffer *, int fd);
-
-/* The following 2 functions (buffer_flush_all and buffer_flush_window)
- are for use in lib/vty.c only. They should not be used elsewhere. */
-
-/* Call buffer_flush_available repeatedly until either all data has been
- flushed, or an I/O error has been encountered, or the operation would
- block. */
-extern buffer_status_t buffer_flush_all(struct buffer *, int fd);
-
-/* Attempt to write enough data to the given fd to fill a window of the
- given width and height (and remove the data written from the buffer).
-
- If !no_more, then a message saying " --More-- " is appended.
- If erase is true, then first overwrite the previous " --More-- " message
- with spaces.
-
- Any write error (including EAGAIN or EINTR) will cause this function
- to return -1 (because the logic for handling the erase and more features
- is too complicated to retry the write later).
-*/
-extern buffer_status_t buffer_flush_window(struct buffer *, int fd, int width,
- int height, int erase, int no_more);
-
-#endif /* _ZEBRA_BUFFER_H */
diff --git a/openbsc/include/vty/command.h b/openbsc/include/vty/command.h
deleted file mode 100644
index 1b6e0a7..0000000
--- a/openbsc/include/vty/command.h
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * Zebra configuration command interface routine
- * Copyright (C) 1997, 98 Kunihiro Ishiguro
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef _ZEBRA_COMMAND_H
-#define _ZEBRA_COMMAND_H
-
-#include <stdio.h>
-#include <sys/types.h>
-#include "vector.h"
-#include "vty.h"
-
-/* Host configuration variable */
-struct host {
- /* Host name of this router. */
- char *name;
-
- /* Password for vty interface. */
- char *password;
- char *password_encrypt;
-
- /* Enable password */
- char *enable;
- char *enable_encrypt;
-
- /* System wide terminal lines. */
- int lines;
-
- /* Log filename. */
- char *logfile;
-
- /* config file name of this host */
- char *config;
-
- /* Flags for services */
- int advanced;
- int encrypt;
-
- /* Banner configuration. */
- const char *motd;
- char *motdfile;
-};
-
-/* There are some command levels which called from command node. */
-enum node_type {
- AUTH_NODE, /* Authentication mode of vty interface. */
- VIEW_NODE, /* View node. Default mode of vty interface. */
- AUTH_ENABLE_NODE, /* Authentication mode for change enable. */
- ENABLE_NODE, /* Enable node. */
- CONFIG_NODE, /* Config node. Default mode of config file. */
- SERVICE_NODE, /* Service node. */
- DEBUG_NODE, /* Debug node. */
-#if 0
- AAA_NODE, /* AAA node. */
- KEYCHAIN_NODE, /* Key-chain node. */
- KEYCHAIN_KEY_NODE, /* Key-chain key node. */
- INTERFACE_NODE, /* Interface mode node. */
- ZEBRA_NODE, /* zebra connection node. */
- TABLE_NODE, /* rtm_table selection node. */
- RIP_NODE, /* RIP protocol mode node. */
- RIPNG_NODE, /* RIPng protocol mode node. */
- BGP_NODE, /* BGP protocol mode which includes BGP4+ */
- BGP_VPNV4_NODE, /* BGP MPLS-VPN PE exchange. */
- BGP_IPV4_NODE, /* BGP IPv4 unicast address family. */
- BGP_IPV4M_NODE, /* BGP IPv4 multicast address family. */
- BGP_IPV6_NODE, /* BGP IPv6 address family */
- OSPF_NODE, /* OSPF protocol mode */
- OSPF6_NODE, /* OSPF protocol for IPv6 mode */
- ISIS_NODE, /* ISIS protocol mode */
- MASC_NODE, /* MASC for multicast. */
- IRDP_NODE, /* ICMP Router Discovery Protocol mode. */
- IP_NODE, /* Static ip route node. */
- ACCESS_NODE, /* Access list node. */
- PREFIX_NODE, /* Prefix list node. */
- ACCESS_IPV6_NODE, /* Access list node. */
- PREFIX_IPV6_NODE, /* Prefix list node. */
- AS_LIST_NODE, /* AS list node. */
- COMMUNITY_LIST_NODE, /* Community list node. */
- RMAP_NODE, /* Route map node. */
- SMUX_NODE, /* SNMP configuration node. */
- DUMP_NODE, /* Packet dump node. */
- FORWARDING_NODE, /* IP forwarding node. */
-#endif
- VTY_NODE, /* Vty node. */
-
- GSMNET_NODE,
- BTS_NODE,
- TRX_NODE,
- TS_NODE,
- SUBSCR_NODE,
- MGCP_NODE,
- GBPROXY_NODE,
- SGSN_NODE,
- NS_NODE,
-};
-
-/* Node which has some commands and prompt string and configuration
- function pointer . */
-struct cmd_node {
- /* Node index. */
- enum node_type node;
-
- /* Prompt character at vty interface. */
- const char *prompt;
-
- /* Is this node's configuration goes to vtysh ? */
- int vtysh;
-
- /* Node's configuration write function */
- int (*func) (struct vty *);
-
- /* Vector of this node's command list. */
- vector cmd_vector;
-};
-
-enum {
- CMD_ATTR_DEPRECATED = 1,
- CMD_ATTR_HIDDEN,
-};
-
-/* Structure of command element. */
-struct cmd_element {
- const char *string; /* Command specification by string. */
- int (*func) (struct cmd_element *, struct vty *, int, const char *[]);
- const char *doc; /* Documentation of this command. */
- int daemon; /* Daemon to which this command belong. */
- vector strvec; /* Pointing out each description vector. */
- unsigned int cmdsize; /* Command index count. */
- char *config; /* Configuration string */
- vector subconfig; /* Sub configuration string */
- u_char attr; /* Command attributes */
-};
-
-/* Command description structure. */
-struct desc {
- const char *cmd; /* Command string. */
- const char *str; /* Command's description. */
-};
-
-/* Return value of the commands. */
-#define CMD_SUCCESS 0
-#define CMD_WARNING 1
-#define CMD_ERR_NO_MATCH 2
-#define CMD_ERR_AMBIGUOUS 3
-#define CMD_ERR_INCOMPLETE 4
-#define CMD_ERR_EXEED_ARGC_MAX 5
-#define CMD_ERR_NOTHING_TODO 6
-#define CMD_COMPLETE_FULL_MATCH 7
-#define CMD_COMPLETE_MATCH 8
-#define CMD_COMPLETE_LIST_MATCH 9
-#define CMD_SUCCESS_DAEMON 10
-
-/* Argc max counts. */
-#define CMD_ARGC_MAX 25
-
-/* Turn off these macros when uisng cpp with extract.pl */
-#ifndef VTYSH_EXTRACT_PL
-
-/* helper defines for end-user DEFUN* macros */
-#define DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attrs, dnum) \
- static struct cmd_element cmdname = \
- { \
- .string = cmdstr, \
- .func = funcname, \
- .doc = helpstr, \
- .attr = attrs, \
- .daemon = dnum, \
- };
-
-/* global (non static) cmd_element */
-#define gDEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attrs, dnum) \
- struct cmd_element cmdname = \
- { \
- .string = cmdstr, \
- .func = funcname, \
- .doc = helpstr, \
- .attr = attrs, \
- .daemon = dnum, \
- };
-
-#define DEFUN_CMD_FUNC_DECL(funcname) \
- static int funcname (struct cmd_element *, struct vty *, int, const char *[]); \
-
-#define DEFUN_CMD_FUNC_TEXT(funcname) \
- static int funcname \
- (struct cmd_element *self, struct vty *vty, int argc, const char *argv[])
-
-/* DEFUN for vty command interafce. Little bit hacky ;-). */
-#define DEFUN(funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_FUNC_DECL(funcname) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \
- DEFUN_CMD_FUNC_TEXT(funcname)
-
-/* global (non static) cmd_element */
-#define gDEFUN(funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_FUNC_DECL(funcname) \
- gDEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \
- DEFUN_CMD_FUNC_TEXT(funcname)
-
-#define DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \
- DEFUN_CMD_FUNC_DECL(funcname) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0) \
- DEFUN_CMD_FUNC_TEXT(funcname)
-
-#define DEFUN_HIDDEN(funcname, cmdname, cmdstr, helpstr) \
- DEFUN_ATTR (funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN)
-
-#define DEFUN_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \
- DEFUN_ATTR (funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED) \
-
-/* DEFUN_NOSH for commands that vtysh should ignore */
-#define DEFUN_NOSH(funcname, cmdname, cmdstr, helpstr) \
- DEFUN(funcname, cmdname, cmdstr, helpstr)
-
-/* DEFSH for vtysh. */
-#define DEFSH(daemon, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(NULL, cmdname, cmdstr, helpstr, 0, daemon) \
-
-/* DEFUN + DEFSH */
-#define DEFUNSH(daemon, funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_FUNC_DECL(funcname) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon) \
- DEFUN_CMD_FUNC_TEXT(funcname)
-
-/* DEFUN + DEFSH with attributes */
-#define DEFUNSH_ATTR(daemon, funcname, cmdname, cmdstr, helpstr, attr) \
- DEFUN_CMD_FUNC_DECL(funcname) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, daemon) \
- DEFUN_CMD_FUNC_TEXT(funcname)
-
-#define DEFUNSH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \
- DEFUNSH_ATTR (daemon, funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN)
-
-#define DEFUNSH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \
- DEFUNSH_ATTR (daemon, funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED)
-
-/* ALIAS macro which define existing command's alias. */
-#define ALIAS(funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0)
-
-/* global (non static) cmd_element */
-#define gALIAS(funcname, cmdname, cmdstr, helpstr) \
- gDEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0)
-
-#define ALIAS_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0)
-
-#define ALIAS_HIDDEN(funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, 0)
-
-#define ALIAS_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, 0)
-
-#define ALIAS_SH(daemon, funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon)
-
-#define ALIAS_SH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, daemon)
-
-#define ALIAS_SH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \
- DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, daemon)
-
-#endif /* VTYSH_EXTRACT_PL */
-
-/* Some macroes */
-#define CMD_OPTION(S) ((S[0]) == '[')
-#define CMD_VARIABLE(S) (((S[0]) >= 'A' && (S[0]) <= 'Z') || ((S[0]) == '<'))
-#define CMD_VARARG(S) ((S[0]) == '.')
-#define CMD_RANGE(S) ((S[0] == '<'))
-
-#define CMD_IPV4(S) ((strcmp ((S), "A.B.C.D") == 0))
-#define CMD_IPV4_PREFIX(S) ((strcmp ((S), "A.B.C.D/M") == 0))
-#define CMD_IPV6(S) ((strcmp ((S), "X:X::X:X") == 0))
-#define CMD_IPV6_PREFIX(S) ((strcmp ((S), "X:X::X:X/M") == 0))
-
-/* Common descriptions. */
-#define SHOW_STR "Show running system information\n"
-#define IP_STR "IP information\n"
-#define IPV6_STR "IPv6 information\n"
-#define NO_STR "Negate a command or set its defaults\n"
-#define CLEAR_STR "Reset functions\n"
-#define RIP_STR "RIP information\n"
-#define BGP_STR "BGP information\n"
-#define OSPF_STR "OSPF information\n"
-#define NEIGHBOR_STR "Specify neighbor router\n"
-#define DEBUG_STR "Debugging functions (see also 'undebug')\n"
-#define UNDEBUG_STR "Disable debugging functions (see also 'debug')\n"
-#define ROUTER_STR "Enable a routing process\n"
-#define AS_STR "AS number\n"
-#define MBGP_STR "MBGP information\n"
-#define MATCH_STR "Match values from routing table\n"
-#define SET_STR "Set values in destination routing protocol\n"
-#define OUT_STR "Filter outgoing routing updates\n"
-#define IN_STR "Filter incoming routing updates\n"
-#define V4NOTATION_STR "specify by IPv4 address notation(e.g. 0.0.0.0)\n"
-#define OSPF6_NUMBER_STR "Specify by number\n"
-#define INTERFACE_STR "Interface infomation\n"
-#define IFNAME_STR "Interface name(e.g. ep0)\n"
-#define IP6_STR "IPv6 Information\n"
-#define OSPF6_STR "Open Shortest Path First (OSPF) for IPv6\n"
-#define OSPF6_ROUTER_STR "Enable a routing process\n"
-#define OSPF6_INSTANCE_STR "<1-65535> Instance ID\n"
-#define SECONDS_STR "<1-65535> Seconds\n"
-#define ROUTE_STR "Routing Table\n"
-#define PREFIX_LIST_STR "Build a prefix list\n"
-#define OSPF6_DUMP_TYPE_LIST \
-"(neighbor|interface|area|lsa|zebra|config|dbex|spf|route|lsdb|redistribute|hook|asbr|prefix|abr)"
-#define ISIS_STR "IS-IS information\n"
-#define AREA_TAG_STR "[area tag]\n"
-
-#define CONF_BACKUP_EXT ".sav"
-
-/* IPv4 only machine should not accept IPv6 address for peer's IP
- address. So we replace VTY command string like below. */
-#ifdef HAVE_IPV6
-#define NEIGHBOR_CMD "neighbor (A.B.C.D|X:X::X:X) "
-#define NO_NEIGHBOR_CMD "no neighbor (A.B.C.D|X:X::X:X) "
-#define NEIGHBOR_ADDR_STR "Neighbor address\nIPv6 address\n"
-#define NEIGHBOR_CMD2 "neighbor (A.B.C.D|X:X::X:X|WORD) "
-#define NO_NEIGHBOR_CMD2 "no neighbor (A.B.C.D|X:X::X:X|WORD) "
-#define NEIGHBOR_ADDR_STR2 "Neighbor address\nNeighbor IPv6 address\nNeighbor tag\n"
-#else
-#define NEIGHBOR_CMD "neighbor A.B.C.D "
-#define NO_NEIGHBOR_CMD "no neighbor A.B.C.D "
-#define NEIGHBOR_ADDR_STR "Neighbor address\n"
-#define NEIGHBOR_CMD2 "neighbor (A.B.C.D|WORD) "
-#define NO_NEIGHBOR_CMD2 "no neighbor (A.B.C.D|WORD) "
-#define NEIGHBOR_ADDR_STR2 "Neighbor address\nNeighbor tag\n"
-#endif /* HAVE_IPV6 */
-
-/* Prototypes. */
-void install_node(struct cmd_node *, int (*)(struct vty *));
-void install_default(enum node_type);
-void install_element(enum node_type, struct cmd_element *);
-void install_element_ve(struct cmd_element *cmd);
-void sort_node();
-
-/* Concatenates argv[shift] through argv[argc-1] into a single NUL-terminated
- string with a space between each element (allocated using
- XMALLOC(MTYPE_TMP)). Returns NULL if shift >= argc. */
-char *argv_concat(const char **argv, int argc, int shift);
-
-vector cmd_make_strvec(const char *);
-void cmd_free_strvec(vector);
-vector cmd_describe_command();
-char **cmd_complete_command();
-const char *cmd_prompt(enum node_type);
-int config_from_file(struct vty *, FILE *);
-enum node_type node_parent(enum node_type);
-int cmd_execute_command(vector, struct vty *, struct cmd_element **, int);
-int cmd_execute_command_strict(vector, struct vty *, struct cmd_element **);
-void config_replace_string(struct cmd_element *, char *, ...);
-void cmd_init(int);
-
-/* Export typical functions. */
-extern struct cmd_element config_end_cmd;
-extern struct cmd_element config_exit_cmd;
-extern struct cmd_element config_quit_cmd;
-extern struct cmd_element config_help_cmd;
-extern struct cmd_element config_list_cmd;
-char *host_config_file();
-void host_config_set(const char *);
-
-void print_version(const char *);
-
-extern void *tall_vty_cmd_ctx;
-
-#endif /* _ZEBRA_COMMAND_H */
diff --git a/openbsc/include/vty/vector.h b/openbsc/include/vty/vector.h
deleted file mode 100644
index 22a184d..0000000
--- a/openbsc/include/vty/vector.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Generic vector interface header.
- * Copyright (C) 1997, 98 Kunihiro Ishiguro
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-#ifndef _ZEBRA_VECTOR_H
-#define _ZEBRA_VECTOR_H
-
-/* struct for vector */
-struct _vector {
- unsigned int active; /* number of active slots */
- unsigned int alloced; /* number of allocated slot */
- void **index; /* index to data */
-};
-typedef struct _vector *vector;
-
-#define VECTOR_MIN_SIZE 1
-
-/* (Sometimes) usefull macros. This macro convert index expression to
- array expression. */
-/* Reference slot at given index, caller must ensure slot is active */
-#define vector_slot(V,I) ((V)->index[(I)])
-/* Number of active slots.
- * Note that this differs from vector_count() as it the count returned
- * will include any empty slots
- */
-#define vector_active(V) ((V)->active)
-
-/* Prototypes. */
-vector vector_init(unsigned int size);
-void vector_ensure(vector v, unsigned int num);
-int vector_empty_slot(vector v);
-int vector_set(vector v, void *val);
-int vector_set_index(vector v, unsigned int i, void *val);
-void vector_unset(vector v, unsigned int i);
-unsigned int vector_count(vector v);
-void vector_only_wrapper_free(vector v);
-void vector_only_index_free(void *index);
-void vector_free(vector v);
-vector vector_copy(vector v);
-
-void *vector_lookup(vector, unsigned int);
-void *vector_lookup_ensure(vector, unsigned int);
-
-extern void *tall_vty_vec_ctx;
-
-#endif /* _ZEBRA_VECTOR_H */
diff --git a/openbsc/include/vty/vty.h b/openbsc/include/vty/vty.h
deleted file mode 100644
index 0441fc5..0000000
--- a/openbsc/include/vty/vty.h
+++ /dev/null
@@ -1,151 +0,0 @@
-#ifndef _VTY_H
-#define _VTY_H
-
-#include <stdio.h>
-#include <stdarg.h>
-
-/* GCC have printf type attribute check. */
-#ifdef __GNUC__
-#define VTY_PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
-#else
-#define VTY_PRINTF_ATTRIBUTE(a,b)
-#endif /* __GNUC__ */
-
-/* Does the I/O error indicate that the operation should be retried later? */
-#define ERRNO_IO_RETRY(EN) \
- (((EN) == EAGAIN) || ((EN) == EWOULDBLOCK) || ((EN) == EINTR))
-
-/* Vty read buffer size. */
-#define VTY_READ_BUFSIZ 512
-
-#define VTY_BUFSIZ 512
-#define VTY_MAXHIST 20
-
-/* Vty events */
-enum event {
- VTY_SERV,
- VTY_READ,
- VTY_WRITE,
- VTY_CLOSED,
- VTY_TIMEOUT_RESET,
-#ifdef VTYSH
- VTYSH_SERV,
- VTYSH_READ,
- VTYSH_WRITE
-#endif /* VTYSH */
-};
-
-struct vty {
- FILE *file;
-
- /* private data, specified by creator */
- void *priv;
-
- /* File descripter of this vty. */
- int fd;
-
- /* Is this vty connect to file or not */
- enum { VTY_TERM, VTY_FILE, VTY_SHELL, VTY_SHELL_SERV } type;
-
- /* Node status of this vty */
- int node;
-
- /* Failure count */
- int fail;
-
- /* Output buffer. */
- struct buffer *obuf;
-
- /* Command input buffer */
- char *buf;
-
- /* Command cursor point */
- int cp;
-
- /* Command length */
- int length;
-
- /* Command max length. */
- int max;
-
- /* Histry of command */
- char *hist[VTY_MAXHIST];
-
- /* History lookup current point */
- int hp;
-
- /* History insert end point */
- int hindex;
-
- /* For current referencing point of interface, route-map,
- access-list etc... */
- void *index;
-
- /* For multiple level index treatment such as key chain and key. */
- void *index_sub;
-
- /* For escape character. */
- unsigned char escape;
-
- /* Current vty status. */
- enum { VTY_NORMAL, VTY_CLOSE, VTY_MORE, VTY_MORELINE } status;
-
- /* IAC handling: was the last character received the IAC
- * (interpret-as-command) escape character (and therefore the next
- * character will be the command code)? Refer to Telnet RFC 854. */
- unsigned char iac;
-
- /* IAC SB (option subnegotiation) handling */
- unsigned char iac_sb_in_progress;
- /* At the moment, we care only about the NAWS (window size) negotiation,
- * and that requires just a 5-character buffer (RFC 1073):
- * <NAWS char> <16-bit width> <16-bit height> */
-#define TELNET_NAWS_SB_LEN 5
- unsigned char sb_buf[TELNET_NAWS_SB_LEN];
- /* How many subnegotiation characters have we received? We just drop
- * those that do not fit in the buffer. */
- size_t sb_len;
-
- /* Window width/height. */
- int width;
- int height;
-
- /* Configure lines. */
- int lines;
-
- int monitor;
-
- /* In configure mode. */
- int config;
-};
-
-/* Small macro to determine newline is newline only or linefeed needed. */
-#define VTY_NEWLINE ((vty->type == VTY_TERM) ? "\r\n" : "\n")
-
-static inline char *vty_newline(struct vty *vty)
-{
- return VTY_NEWLINE;
-}
-
-/* Prototypes. */
-void vty_init (void);
-int vty_read_config_file(const char *file_name);
-void vty_init_vtysh (void);
-void vty_reset (void);
-struct vty *vty_new (void);
-struct vty *vty_create (int vty_sock, void *priv);
-int vty_out (struct vty *, const char *, ...) VTY_PRINTF_ATTRIBUTE(2, 3);
-int vty_out_newline(struct vty *);
-int vty_read(struct vty *vty);
-//void vty_time_print (struct vty *, int);
-void vty_close (struct vty *);
-char *vty_get_cwd (void);
-void vty_log (const char *level, const char *proto, const char *fmt, va_list);
-int vty_config_lock (struct vty *);
-int vty_config_unlock (struct vty *);
-int vty_shell (struct vty *);
-int vty_shell_serv (struct vty *);
-void vty_hello (struct vty *);
-
-void *tall_vty_ctx;
-#endif
diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am
index 177c410..2c92a86 100644
--- a/openbsc/src/Makefile.am
+++ b/openbsc/src/Makefile.am
@@ -1,44 +1,45 @@
INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS)
+AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS)
AM_LDFLAGS = $(LIBOSMOCORE_LIBS)
# build current directory before building gprs
-SUBDIRS = . ipaccess gprs
+SUBDIRS = . ipaccess gprs nat
sbin_PROGRAMS = bsc_hack bs11_config isdnsync bsc_mgcp
-noinst_LIBRARIES = libbsc.a libmsc.a libvty.a libsccp.a
-noinst_HEADERS = vty/cardshell.h
+noinst_LIBRARIES = libbsc.a libmsc.a libvty.a libsccp.a libmgcp.a
bscdir = $(libdir)
bsc_LIBRARIES = libsccp.a
libbsc_a_SOURCES = abis_rsl.c abis_nm.c gsm_data.c gsm_04_08_utils.c \
- chan_alloc.c debug.c socket.c \
+ chan_alloc.c debug.c socket.c abis_nm_vty.c \
gsm_subscriber_base.c subchan_demux.c bsc_rll.c transaction.c \
trau_frame.c trau_mux.c paging.c e1_config.c e1_input.c \
input/misdn.c input/ipaccess.c \
talloc_ctx.c system_information.c rest_octets.c \
rtp_proxy.c bts_siemens_bs11.c bts_ipaccess_nanobts.c \
- bts_unknown.c bsc_version.c bsc_api.c
+ bts_unknown.c bsc_version.c bsc_api.c bsc_vty.c
libmsc_a_SOURCES = gsm_subscriber.c db.c \
mncc.c gsm_04_08.c gsm_04_11.c transaction.c \
token_auth.c rrlp.c gsm_04_80.c ussd.c silent_call.c \
- handover_logic.c handover_decision.c meas_rep.c
+ handover_logic.c handover_decision.c meas_rep.c auth.c \
+ osmo_msc.c
-libvty_a_SOURCES = vty/buffer.c vty/command.c vty/vector.c vty/vty.c \
- telnet_interface.c vty_interface_cmds.c vty/utils.c
+libvty_a_SOURCES = common_vty.c
libsccp_a_SOURCES = sccp/sccp.c
-bsc_hack_SOURCES = bsc_hack.c bsc_init.c vty_interface.c vty_interface_layer3.c
-bsc_hack_LDADD = libmsc.a libbsc.a libmsc.a libvty.a -ldl -ldbi $(LIBCRYPT)
+libmgcp_a_SOURCES = mgcp/mgcp_protocol.c mgcp/mgcp_network.c mgcp/mgcp_vty.c
+
+bsc_hack_SOURCES = bsc_hack.c bsc_init.c bsc_vty.c vty_interface_layer3.c
+bsc_hack_LDADD = libmsc.a libbsc.a libvty.a libmsc.a \
+ -ldl -ldbi $(LIBCRYPT) $(LIBOSMOVTY_LIBS)
bs11_config_SOURCES = bs11_config.c abis_nm.c gsm_data.c debug.c \
rs232.c bts_siemens_bs11.c
isdnsync_SOURCES = isdnsync.c
-bsc_mgcp_SOURCES = mgcp/mgcp_main.c mgcp/mgcp_protocol.c mgcp/mgcp_network.c mgcp/mgcp_vty.c \
- debug.c
-bsc_mgcp_LDADD = libvty.a
+bsc_mgcp_SOURCES = mgcp/mgcp_main.c debug.c
+bsc_mgcp_LDADD = libvty.a libmgcp.a $(LIBOSMOVTY_LIBS)
diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c
index 09285bd..6837305 100644
--- a/openbsc/src/abis_nm.c
+++ b/openbsc/src/abis_nm.c
@@ -419,30 +419,30 @@
static int abis_nm_rcvmsg_sw(struct msgb *mb);
-static struct value_string obj_class_names[] = {
- { NM_OC_SITE_MANAGER, "SITE MANAGER" },
+const struct value_string abis_nm_obj_class_names[] = {
+ { NM_OC_SITE_MANAGER, "SITE-MANAGER" },
{ NM_OC_BTS, "BTS" },
- { NM_OC_RADIO_CARRIER, "RADIO CARRIER" },
- { NM_OC_BASEB_TRANSC, "BASEBAND TRANSCEIVER" },
+ { NM_OC_RADIO_CARRIER, "RADIO-CARRIER" },
+ { NM_OC_BASEB_TRANSC, "BASEBAND-TRANSCEIVER" },
{ NM_OC_CHANNEL, "CHANNEL" },
{ NM_OC_BS11_ADJC, "ADJC" },
{ NM_OC_BS11_HANDOVER, "HANDOVER" },
- { NM_OC_BS11_PWR_CTRL, "POWER CONTROL" },
+ { NM_OC_BS11_PWR_CTRL, "POWER-CONTROL" },
{ NM_OC_BS11_BTSE, "BTSE" },
{ NM_OC_BS11_RACK, "RACK" },
{ NM_OC_BS11_TEST, "TEST" },
{ NM_OC_BS11_ENVABTSE, "ENVABTSE" },
{ NM_OC_BS11_BPORT, "BPORT" },
- { NM_OC_GPRS_NSE, "GPRS NSE" },
- { NM_OC_GPRS_CELL, "GPRS CELL" },
- { NM_OC_GPRS_NSVC, "GPRS NSVC" },
+ { NM_OC_GPRS_NSE, "GPRS-NSE" },
+ { NM_OC_GPRS_CELL, "GPRS-CELL" },
+ { NM_OC_GPRS_NSVC, "GPRS-NSVC" },
{ NM_OC_BS11, "SIEMENSHW" },
{ 0, NULL }
};
static const char *obj_class_name(u_int8_t oc)
{
- return get_value_string(obj_class_names, oc);
+ return get_value_string(abis_nm_obj_class_names, oc);
}
const char *nm_opstate_name(u_int8_t os)
@@ -490,18 +490,17 @@
{ 0, NULL }
};
+const struct value_string abis_nm_adm_state_names[] = {
+ { NM_STATE_LOCKED, "Locked" },
+ { NM_STATE_UNLOCKED, "Unlocked" },
+ { NM_STATE_SHUTDOWN, "Shutdown" },
+ { NM_STATE_NULL, "NULL" },
+ { 0, NULL }
+};
+
const char *nm_adm_name(u_int8_t adm)
{
- switch (adm) {
- case 1:
- return "Locked";
- case 2:
- return "Unlocked";
- case 3:
- return "Shutdown";
- default:
- return "<not used>";
- }
+ return get_value_string(abis_nm_adm_state_names, adm);
}
int nm_is_running(struct gsm_nm_state *s) {
diff --git a/openbsc/src/abis_nm_vty.c b/openbsc/src/abis_nm_vty.c
new file mode 100644
index 0000000..b6eca3b
--- /dev/null
+++ b/openbsc/src/abis_nm_vty.c
@@ -0,0 +1,198 @@
+/* VTY interface for A-bis OML (Netowrk Management) */
+
+/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <arpa/inet.h>
+
+#include <openbsc/gsm_data.h>
+#include <osmocore/msgb.h>
+#include <osmocore/tlv.h>
+#include <osmocore/talloc.h>
+#include <openbsc/debug.h>
+#include <openbsc/signal.h>
+#include <openbsc/abis_nm.h>
+#include <openbsc/vty.h>
+
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/command.h>
+#include <osmocom/vty/logging.h>
+#include <osmocom/vty/telnet_interface.h>
+
+extern struct gsm_network *bsc_gsmnet;
+
+static struct cmd_node oml_node = {
+ OML_NODE,
+ "%s(oml)# ",
+ 1,
+};
+
+struct oml_node_state {
+ struct gsm_bts *bts;
+ uint8_t obj_class;
+ uint8_t obj_inst[3];
+};
+
+static int dummy_config_write(struct vty *v)
+{
+ return CMD_SUCCESS;
+}
+
+/* FIXME: auto-generate those strings from the value_string lists */
+#define NM_OBJCLASS_VTY "(site-manager|bts|radio-carrier|baseband-transceiver|channel|adjc|handover|power-contorl|btse|rack|test|envabtse|bport|gprs-nse|gprs-cell|gprs-nsvc|siemenshw)"
+#define NM_OBJCLASS_VTY_HELP "FIXME"
+
+DEFUN(oml_class_inst, oml_class_inst_cmd,
+ "bts <0-255> oml class " NM_OBJCLASS_VTY
+ " instance <0-255> <0-255> <0-255>",
+ "BTS related commands\n" "BTS Number\n"
+ "Manipulate the OML managed objects\n"
+ "Object Class\n" NM_OBJCLASS_VTY_HELP
+ "Object Instance\n" "BTS Number\n" "TRX Number\n" "TS Number\n")
+{
+ struct gsm_bts *bts;
+ struct oml_node_state *oms;
+ int bts_nr = atoi(argv[0]);
+
+ bts = gsm_bts_num(bsc_gsmnet, bts_nr);
+ if (!bts) {
+ vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
+ if (!oms)
+ return CMD_WARNING;
+
+ oms->bts = bts;
+ oms->obj_class = get_string_value(abis_nm_obj_class_names, argv[1]);
+ oms->obj_inst[0] = atoi(argv[2]);
+ oms->obj_inst[1] = atoi(argv[3]);
+ oms->obj_inst[2] = atoi(argv[4]);
+
+ vty->index = oms;
+ vty->node = OML_NODE;
+
+ return CMD_SUCCESS;
+
+}
+
+DEFUN(oml_classnum_inst, oml_classnum_inst_cmd,
+ "bts <0-255> oml class <0-255> instance <0-255> <0-255> <0-255>",
+ "BTS related commands\n" "BTS Number\n"
+ "Manipulate the OML managed objects\n"
+ "Object Class\n" "Object Class\n"
+ "Object Instance\n" "BTS Number\n" "TRX Number\n" "TS Number\n")
+{
+ struct gsm_bts *bts;
+ struct oml_node_state *oms;
+ int bts_nr = atoi(argv[0]);
+
+ bts = gsm_bts_num(bsc_gsmnet, bts_nr);
+ if (!bts) {
+ vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
+ if (!oms)
+ return CMD_WARNING;
+
+ oms->bts = bts;
+ oms->obj_class = atoi(argv[1]);
+ oms->obj_inst[0] = atoi(argv[2]);
+ oms->obj_inst[1] = atoi(argv[3]);
+ oms->obj_inst[2] = atoi(argv[4]);
+
+ vty->index = oms;
+ vty->node = OML_NODE;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(oml_attrib_get, oml_attrib_get_cmd,
+ "attribute get <0-255>",
+ "OML Attribute Actions\n" "Get a single OML Attribute\n"
+ "OML Attribute Number\n")
+{
+ struct oml_node_state *oms = vty->index;
+
+ /* FIXME */
+ return CMD_SUCCESS;
+}
+
+DEFUN(oml_attrib_set, oml_attrib_set_cmd,
+ "attribute set <0-255> .HEX",
+ "OML Attribute Actions\n" "Set a single OML Attribute\n"
+ "OML Attribute Number\n")
+{
+ struct oml_node_state *oms = vty->index;
+
+ /* FIXME */
+ return CMD_SUCCESS;
+}
+
+DEFUN(oml_chg_adm_state, oml_chg_adm_state_cmd,
+ "change-adm-state (locked|unlocked|shutdown|null)",
+ "Change the Administrative State\n"
+ "Locked\n" "Unlocked\n" "Shutdown\n" "NULL\n")
+{
+ struct oml_node_state *oms = vty->index;
+ enum abis_nm_adm_state state;
+
+ state = get_string_value(abis_nm_adm_state_names, argv[0]);
+
+ abis_nm_chg_adm_state(oms->bts, oms->obj_class, oms->obj_inst[0],
+ oms->obj_inst[1], oms->obj_inst[2], state);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(oml_opstart, oml_opstart_cmd,
+ "opstart", "Send an OPSTART message to the object")
+{
+ struct oml_node_state *oms = vty->index;
+
+ abis_nm_opstart(oms->bts, oms->obj_class, oms->obj_inst[0],
+ oms->obj_inst[1], oms->obj_inst[2]);
+
+ return CMD_SUCCESS;
+}
+
+int abis_nm_vty_init(void)
+{
+ install_element(ENABLE_NODE, &oml_class_inst_cmd);
+ install_element(ENABLE_NODE, &oml_classnum_inst_cmd);
+ install_node(&oml_node, dummy_config_write);
+
+ install_default(OML_NODE);
+ install_element(OML_NODE, &ournode_exit_cmd);
+ install_element(OML_NODE, &oml_attrib_get_cmd);
+ install_element(OML_NODE, &oml_attrib_set_cmd);
+ install_element(OML_NODE, &oml_chg_adm_state_cmd);
+ install_element(OML_NODE, &oml_opstart_cmd);
+
+ return 0;
+}
diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c
index 53b2982..451c80d 100644
--- a/openbsc/src/abis_rsl.c
+++ b/openbsc/src/abis_rsl.c
@@ -568,12 +568,33 @@
return abis_rsl_sendmsg(msg);
}
+static void error_timeout_cb(void *data)
+{
+ struct gsm_lchan *lchan = data;
+ if (lchan->state != LCHAN_S_REL_ERR) {
+ LOGP(DRSL, LOGL_ERROR, "%s error timeout but not in error state: %d\n",
+ gsm_lchan_name(lchan), lchan->state);
+ return;
+ }
+
+ /* go back to the none state */
+ LOGP(DRSL, LOGL_NOTICE, "%s is back in operation.\n", gsm_lchan_name(lchan));
+ rsl_lchan_set_state(lchan, LCHAN_S_NONE);
+}
+
/* Chapter 8.4.14 / 4.7: Tell BTS to release the radio channel */
-int rsl_rf_chan_release(struct gsm_lchan *lchan)
+static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error)
{
struct abis_rsl_dchan_hdr *dh;
- struct msgb *msg = rsl_msgb_alloc();
+ struct msgb *msg;
+ if (lchan->state == LCHAN_S_REL_ERR) {
+ LOGP(DRSL, LOGL_NOTICE, "%s is in error state not sending release.\n",
+ gsm_lchan_name(lchan));
+ return -1;
+ }
+
+ msg = rsl_msgb_alloc();
dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
init_dchan_hdr(dh, RSL_MT_RF_CHAN_REL);
dh->chan_nr = lchan2chan_nr(lchan);
@@ -581,7 +602,20 @@
msg->lchan = lchan;
msg->trx = lchan->ts->trx;
- DEBUGP(DRSL, "%s RF Channel Release CMD\n", gsm_lchan_name(lchan));
+ DEBUGP(DRSL, "%s RF Channel Release CMD due error %d\n", gsm_lchan_name(lchan), error);
+
+ if (error) {
+ /*
+ * the nanoBTS sends RLL release indications after the channel release. This can
+ * be a problem when we have reassigned the channel to someone else and then can
+ * not figure out who used this channel.
+ */
+ rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
+ lchan->error_timer.data = lchan;
+ lchan->error_timer.cb = error_timeout_cb;
+ bsc_schedule_timer(&lchan->error_timer,
+ msg->trx->bts->network->T3111 + 2, 0);
+ }
/* BTS will respond by RF CHAN REL ACK */
return abis_rsl_sendmsg(msg);
@@ -718,14 +752,15 @@
RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
lchan_free() */
-int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id)
+int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id, u_int8_t reason)
{
struct msgb *msg;
msg = rsl_rll_simple(RSL_MT_REL_REQ, lchan2chan_nr(lchan),
link_id, 0);
- msgb_tv_put(msg, RSL_IE_RELEASE_MODE, 0); /* normal release */
+ /* 0 is normal release, 1 is local end */
+ msgb_tv_put(msg, RSL_IE_RELEASE_MODE, reason);
/* FIXME: start some timer in case we don't receive a REL ACK ? */
@@ -811,7 +846,7 @@
LOGPC(DRSL, LOGL_NOTICE, "\n");
/* FIXME: only free it after channel release ACK */
counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail);
- return rsl_rf_chan_release(msg->lchan);
+ return rsl_rf_chan_release(msg->lchan, 1);
}
static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru,
@@ -983,11 +1018,14 @@
break;
case RSL_MT_RF_CHAN_REL_ACK:
DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", ts_name);
- if (msg->lchan->state != LCHAN_S_REL_REQ)
+ if (msg->lchan->state != LCHAN_S_REL_REQ && msg->lchan->state != LCHAN_S_REL_ERR)
LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
gsm_lchan_name(msg->lchan),
gsm_lchans_name(msg->lchan->state));
- rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
+ bsc_del_timer(&msg->lchan->T3111);
+ /* we have an error timer pending to release that */
+ if (msg->lchan->state != LCHAN_S_REL_ERR)
+ rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
lchan_free(msg->lchan);
break;
case RSL_MT_MODE_MODIFY_ACK:
@@ -1079,7 +1117,15 @@
{
struct gsm_lchan *lchan = data;
- rsl_rf_chan_release(lchan);
+ rsl_rf_chan_release(lchan, 1);
+}
+
+/* If T3111 expires, we will send the RF Channel Request */
+static void t3111_expired(void *data)
+{
+ struct gsm_lchan *lchan = data;
+
+ rsl_rf_chan_release(lchan, 0);
}
/* MS has requested a channel on the RACH */
@@ -1252,12 +1298,28 @@
if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) {
counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err);
- return rsl_rf_chan_release(msg->lchan);
+ return rsl_rf_chan_release(msg->lchan, 1);
}
return 0;
}
+static void rsl_handle_release(struct gsm_lchan *lchan)
+{
+ struct gsm_bts *bts;
+ if (lchan->state != LCHAN_S_REL_REQ)
+ LOGP(DRSL, LOGL_ERROR, "RF release on %s but state %s\n",
+ gsm_lchan_name(lchan),
+ gsm_lchans_name(lchan->state));
+
+
+ /* wait a bit to send the RF Channel Release */
+ lchan->T3111.cb = t3111_expired;
+ lchan->T3111.data = lchan;
+ bts = lchan->ts->trx->bts;
+ bsc_schedule_timer(&lchan->T3111, bts->network->T3111, 0);
+}
+
/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
0x02, 0x06,
0x01, 0x20,
@@ -1309,20 +1371,14 @@
msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
rll_indication(msg->lchan, rllh->link_id,
BSC_RLLR_IND_REL_IND);
- /* we can now releae the channel on the BTS/Abis side */
- /* FIXME: officially we need to start T3111 and wait for
- * some grace period */
- rsl_rf_chan_release(msg->lchan);
+ rsl_handle_release(msg->lchan);
break;
case RSL_MT_REL_CONF:
/* BTS informs us of having received UA from MS,
* in response to DISC that we've sent earlier */
DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
- /* we can now releae the channel on the BTS/Abis side */
- /* FIXME: officially we need to start T3111 and wait for
- * some grace period */
- rsl_rf_chan_release(msg->lchan);
+ rsl_handle_release(msg->lchan);
break;
case RSL_MT_ERROR_IND:
rc = rsl_rx_rll_err_ind(msg);
diff --git a/openbsc/src/auth.c b/openbsc/src/auth.c
new file mode 100644
index 0000000..f57b668
--- /dev/null
+++ b/openbsc/src/auth.c
@@ -0,0 +1,128 @@
+/* Authentication related functions */
+
+/*
+ * (C) 2010 by Sylvain Munaut <tnt@246tNt.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <openbsc/db.h>
+#include <openbsc/debug.h>
+#include <openbsc/gsm_data.h>
+
+#include <osmocore/comp128.h>
+
+#include <stdlib.h>
+
+
+static int
+_use_xor(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
+{
+ int i, l = ainfo->a3a8_ki_len;
+
+ if ((l > A38_XOR_MAX_KEY_LEN) || (l < A38_XOR_MIN_KEY_LEN)) {
+ DEBUGP(DMM, "Invalid XOR key (len=%d) %s",
+ ainfo->a3a8_ki_len,
+ hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
+ return -1;
+ }
+
+ for (i=0; i<4; i++)
+ atuple->sres[i] = atuple->rand[i] ^ ainfo->a3a8_ki[i];
+ for (i=8; i<12; i++)
+ atuple->kc[i-4] = atuple->rand[i] ^ ainfo->a3a8_ki[i];
+
+ return 0;
+}
+
+static int
+_use_comp128_v1(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
+{
+ if (ainfo->a3a8_ki_len != A38_COMP128_KEY_LEN) {
+ DEBUGP(DMM, "Invalid COMP128v1 key (len=%d) %s",
+ ainfo->a3a8_ki_len,
+ hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
+ return -1;
+ }
+
+ comp128(ainfo->a3a8_ki, atuple->rand, atuple->sres, atuple->kc);
+
+ return 0;
+}
+
+/* Return values
+ * -1 -> Internal error
+ * 0 -> Not available
+ * 1 -> Tuple returned, need to do auth, then enable cipher
+ * 2 -> Tuple returned, need to enable cipher
+ */
+int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
+ struct gsm_subscriber *subscr, int key_seq)
+{
+ struct gsm_auth_info ainfo;
+ int i, rc;
+
+ /* Get subscriber info (if any) */
+ rc = db_get_authinfo_for_subscr(&ainfo, subscr);
+ if (rc < 0) {
+ DEBUGP(DMM, "No retrievable Ki for subscriber, skipping auth");
+ return rc == -ENOENT ? 0 : -1;
+ }
+
+ /* If possible, re-use the last tuple and skip auth */
+ rc = db_get_lastauthtuple_for_subscr(atuple, subscr);
+ if ((rc == 0) &&
+ (atuple->key_seq != GSM_KEY_SEQ_INVAL) &&
+ (atuple->use_count < 3))
+ {
+ atuple->use_count++;
+ db_sync_lastauthtuple_for_subscr(atuple, subscr);
+ return 2;
+ }
+
+ /* Generate a new one */
+ atuple->use_count = 1;
+ atuple->key_seq = (atuple->key_seq + 1) % 7;
+ for (i=0; i<sizeof(atuple->rand); i++)
+ atuple->rand[i] = random() & 0xff;
+
+ switch (ainfo.auth_algo) {
+ case AUTH_ALGO_NONE:
+ return 0;
+
+ case AUTH_ALGO_XOR:
+ if (_use_xor(&ainfo, atuple))
+ return 0;
+ break;
+
+ case AUTH_ALGO_COMP128v1:
+ if (_use_comp128_v1(&ainfo, atuple))
+ return 0;
+ break;
+
+ default:
+ DEBUGP(DMM, "Unsupported auth type algo_id=%d\n",
+ ainfo.auth_algo);
+ return 0;
+ }
+
+ db_sync_lastauthtuple_for_subscr(atuple, subscr);
+
+ return 1;
+}
+
diff --git a/openbsc/src/bs11_config.c b/openbsc/src/bs11_config.c
index 8f6de8a..44cef0a 100644
--- a/openbsc/src/bs11_config.c
+++ b/openbsc/src/bs11_config.c
@@ -830,6 +830,7 @@
}
}
+extern int bts_model_bs11_init(void);
int main(int argc, char **argv)
{
struct gsm_network *gsmnet;
diff --git a/openbsc/src/bsc_api.c b/openbsc/src/bsc_api.c
index b504752..28fc324 100644
--- a/openbsc/src/bsc_api.c
+++ b/openbsc/src/bsc_api.c
@@ -1,6 +1,8 @@
/* GSM 08.08 like API for OpenBSC. The bridge from MSC to BSC */
/* (C) 2010 by Holger Hans Peter Freyther
+ * (C) 2010 by On Waves
+ * (C) 2009 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
@@ -21,13 +23,118 @@
*/
#include <openbsc/bsc_api.h>
+#include <openbsc/bsc_rll.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/signal.h>
#include <openbsc/abis_rsl.h>
+#include <osmocore/talloc.h>
+
+static void rll_ind_cb(struct gsm_lchan *, uint8_t, void *, enum bsc_rllr_ind);
+static void send_sapi_reject(struct gsm_subscriber_connection *conn, int link_id);
+
+int bsc_api_init(struct gsm_network *network, struct bsc_api *api)
+{
+ network->bsc_api = api;
+ return 0;
+}
int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn,
struct msgb *msg, int link_id)
{
+ uint8_t sapi = link_id & 0x7;
msg->lchan = conn->lchan;
msg->trx = msg->lchan->ts->trx;
- return rsl_data_request(msg, link_id);
+
+ if (conn->lchan->sapis[sapi] == LCHAN_SAPI_UNUSED) {
+ OBSC_LINKID_CB(msg) = link_id;
+ if (rll_establish(msg->lchan, sapi, rll_ind_cb, msg) != 0) {
+ msgb_free(msg);
+ send_sapi_reject(conn, link_id);
+ return -1;
+ }
+ return 0;
+ } else {
+ return rsl_data_request(msg, link_id);
+ }
+}
+
+int gsm0808_page(struct gsm_bts *bts, unsigned int page_group, unsigned int mi_len,
+ uint8_t *mi, int chan_type)
+{
+ return rsl_paging_cmd(bts, page_group, mi_len, mi, chan_type);
+}
+
+/* dequeue messages to layer 4 */
+int bsc_upqueue(struct gsm_network *net)
+{
+ struct gsm_mncc *mncc;
+ struct msgb *msg;
+ int work = 0;
+
+ if (net)
+ while ((msg = msgb_dequeue(&net->upqueue))) {
+ mncc = (struct gsm_mncc *)msg->data;
+ if (net->mncc_recv)
+ net->mncc_recv(net, mncc->msg_type, mncc);
+ work = 1; /* work done */
+ talloc_free(msg);
+ }
+
+ return work;
+}
+
+static void send_sapi_reject(struct gsm_subscriber_connection *conn, int link_id)
+{
+ struct bsc_api *api;
+
+ api = conn->bts->network->bsc_api;
+ if (!api || !api->sapi_n_reject)
+ return;
+
+ api->sapi_n_reject(conn, link_id);
+}
+
+static void rll_ind_cb(struct gsm_lchan *lchan, uint8_t link_id, void *_data, enum bsc_rllr_ind rllr_ind)
+{
+ struct msgb *msg = _data;
+
+ switch (rllr_ind) {
+ case BSC_RLLR_IND_EST_CONF:
+ rsl_data_request(msg, OBSC_LINKID_CB(msg));
+ break;
+ case BSC_RLLR_IND_REL_IND:
+ case BSC_RLLR_IND_ERR_IND:
+ case BSC_RLLR_IND_TIMEOUT:
+ send_sapi_reject(&lchan->conn, OBSC_LINKID_CB(msg));
+ msgb_free(msg);
+ break;
+ }
+}
+
+static int bsc_handle_lchan_signal(unsigned int subsys, unsigned int signal,
+ void *handler_data, void *signal_data)
+{
+ struct bsc_api *bsc;
+ struct gsm_lchan *lchan;
+
+ if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
+ return 0;
+
+ lchan = (struct gsm_lchan *)signal_data;
+ if (!lchan)
+ return 0;
+
+
+ bsc = lchan->ts->trx->bts->network->bsc_api;
+ if (!bsc || !bsc->clear_request)
+ return 0;
+
+ bsc->clear_request(&lchan->conn, 0);
+ return 0;
+}
+
+static __attribute__((constructor)) void on_dso_load_bsc(void)
+{
+ register_signal_handler(SS_LCHAN, bsc_handle_lchan_signal, NULL);
}
diff --git a/openbsc/src/bsc_hack.c b/openbsc/src/bsc_hack.c
index a50d4ab..7be0360 100644
--- a/openbsc/src/bsc_hack.c
+++ b/openbsc/src/bsc_hack.c
@@ -37,12 +37,15 @@
#include <osmocore/talloc.h>
#include <openbsc/signal.h>
+#include <osmocom/vty/command.h>
+
+#include "../bscconfig.h"
+
/* MCC and MNC for the Location Area Identifier */
static struct log_target *stderr_target;
struct gsm_network *bsc_gsmnet = 0;
static const char *database_name = "hlr.sqlite3";
static const char *config_file = "openbsc.cfg";
-extern const char *openbsc_version;
extern const char *openbsc_copyright;
/* timer to store statistics */
@@ -87,16 +90,6 @@
printf(" -e --log-level number. Set a global loglevel.\n");
}
-static void print_version()
-{
- printf("%s\n", openbsc_version);
-}
-
-static void print_copyright()
-{
- puts(openbsc_copyright);
-}
-
static void handle_options(int argc, char** argv)
{
while (1) {
@@ -151,9 +144,7 @@
log_set_log_level(stderr_target, atoi(optarg));
break;
case 'V':
- print_version();
- printf("\n");
- print_copyright();
+ print_version(1);
exit(0);
break;
default:
@@ -207,10 +198,20 @@
extern int bts_model_bs11_init(void);
extern int bts_model_nanobts_init(void);
+extern enum node_type bsc_vty_go_parent(struct vty *vty);
+
+static struct vty_app_info vty_info = {
+ .name = "OpenBSC",
+ .version = PACKAGE_VERSION,
+ .go_parent_cb = bsc_vty_go_parent,
+};
+
int main(int argc, char **argv)
{
int rc;
+ vty_info.copyright = openbsc_copyright;
+
log_init(&log_info);
tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
talloc_ctx_init();
@@ -227,9 +228,17 @@
/* enable filters */
log_set_all_filter(stderr_target, 1);
+ /* This needs to precede handle_options() */
+ vty_init(&vty_info);
+ bsc_vty_init();
+
/* parse options */
handle_options(argc, argv);
+ rc = bsc_bootstrap_network(mncc_recv, config_file);
+ if (rc < 0)
+ exit(1);
+
/* seed the PRNG */
srand(time(NULL));
@@ -250,10 +259,6 @@
db_sync_timer.data = NULL;
bsc_schedule_timer(&db_sync_timer, DB_SYNC_INTERVAL);
- rc = bsc_bootstrap_network(mncc_recv, config_file);
- if (rc < 0)
- exit(1);
-
signal(SIGINT, &signal_handler);
signal(SIGABRT, &signal_handler);
signal(SIGUSR1, &signal_handler);
diff --git a/openbsc/src/bsc_init.c b/openbsc/src/bsc_init.c
index 77446a2..ddb53ba 100644
--- a/openbsc/src/bsc_init.c
+++ b/openbsc/src/bsc_init.c
@@ -1,6 +1,6 @@
/* A hackish minimal BSC (+MSC +HLR) implementation */
-/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
+/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
* All Rights Reserved
*
@@ -27,7 +27,8 @@
#include <openbsc/abis_nm.h>
#include <openbsc/debug.h>
#include <openbsc/misdn.h>
-#include <openbsc/telnet_interface.h>
+#include <openbsc/osmo_msc.h>
+#include <osmocom/vty/telnet_interface.h>
#include <openbsc/system_information.h>
#include <openbsc/paging.h>
#include <openbsc/signal.h>
@@ -419,9 +420,9 @@
switch (obj_class) {
case NM_OC_SITE_MANAGER:
bts = container_of(obj, struct gsm_bts, site_mgr);
- if ((new_state->operational == 2 &&
+ if ((new_state->operational == NM_OPSTATE_ENABLED &&
new_state->availability == NM_AVSTATE_OK) ||
- (new_state->operational == 1 &&
+ (new_state->operational == NM_OPSTATE_DISABLED &&
new_state->availability == NM_AVSTATE_OFF_LINE))
abis_nm_opstart(bts, obj_class, 0xff, 0xff, 0xff);
break;
@@ -441,7 +442,7 @@
case NM_OC_CHANNEL:
ts = obj;
trx = ts->trx;
- if (new_state->operational == 1 &&
+ if (new_state->operational == NM_OPSTATE_DISABLED &&
new_state->availability == NM_AVSTATE_DEPENDENCY) {
patch_nm_tables(trx->bts);
enum abis_nm_chan_comb ccomb =
@@ -456,7 +457,7 @@
break;
case NM_OC_RADIO_CARRIER:
trx = obj;
- if (new_state->operational == 1 &&
+ if (new_state->operational == NM_OPSTATE_DISABLED &&
new_state->availability == NM_AVSTATE_OK)
abis_nm_opstart(trx->bts, obj_class, trx->bts->bts_nr,
trx->nr, 0xff);
@@ -465,7 +466,7 @@
bts = container_of(obj, struct gsm_bts, gprs.nse);
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
- if (new_state->availability == 5) {
+ if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
0xff, 0xff, nanobts_attr_nse,
sizeof(nanobts_attr_nse));
@@ -479,7 +480,7 @@
bts = container_of(obj, struct gsm_bts, gprs.cell);
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
- if (new_state->availability == 5) {
+ if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
0, 0xff, nanobts_attr_cell,
sizeof(nanobts_attr_cell));
@@ -981,6 +982,8 @@
{
int i, n;
+ /* FIXME: What about secondary TRX of a BTS? What about a BTS that has TRX
+ * in different bands? Why is 'band' a parameter of the BTS and not of the TRX? */
switch (bts->band) {
case GSM_BAND_1800:
if (bts->c0->arfcn < 512 || bts->c0->arfcn > 885) {
@@ -1002,6 +1005,12 @@
return -EINVAL;
}
break;
+ case GSM_BAND_850:
+ if (bts->c0->arfcn < 128 || bts->c0->arfcn > 251) {
+ LOGP(DNM, LOGL_ERROR, "GSM850 channel must be between 128-251.\n");
+ return -EINVAL;
+ }
+ break;
default:
LOGP(DNM, LOGL_ERROR, "Unsupported frequency band.\n");
return -EINVAL;
@@ -1062,6 +1071,7 @@
int bsc_bootstrap_network(int (*mncc_recv)(struct gsm_network *, int, void *),
const char *config_file)
{
+ struct telnet_connection dummy_conn;
struct gsm_bts *bts;
int rc;
@@ -1072,14 +1082,20 @@
bsc_gsmnet->name_long = talloc_strdup(bsc_gsmnet, "OpenBSC");
bsc_gsmnet->name_short = talloc_strdup(bsc_gsmnet, "OpenBSC");
+ bsc_api_init(bsc_gsmnet, msc_bsc_api());
- telnet_init(bsc_gsmnet, 4242);
- rc = vty_read_config_file(config_file);
+ /* our vty command code expects vty->priv to point to a telnet_connection */
+ dummy_conn.priv = bsc_gsmnet;
+ rc = vty_read_config_file(config_file, &dummy_conn);
if (rc < 0) {
LOGP(DNM, LOGL_FATAL, "Failed to parse the config file: '%s'\n", config_file);
return rc;
}
+ rc = telnet_init(tall_bsc_ctx, bsc_gsmnet, 4242);
+ if (rc < 0)
+ return rc;
+
register_signal_handler(SS_NM, nm_sig_cb, NULL);
llist_for_each_entry(bts, &bsc_gsmnet->bts_list, list) {
diff --git a/openbsc/src/bsc_msc.c b/openbsc/src/bsc_msc.c
new file mode 100644
index 0000000..42b4c20
--- /dev/null
+++ b/openbsc/src/bsc_msc.c
@@ -0,0 +1,270 @@
+/* Routines to talk to the MSC using the IPA Protocol */
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <openbsc/bsc_msc.h>
+#include <openbsc/debug.h>
+#include <openbsc/ipaccess.h>
+
+#include <osmocore/write_queue.h>
+#include <osmocore/talloc.h>
+
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+static void connection_loss(struct bsc_msc_connection *con)
+{
+ struct bsc_fd *fd;
+
+ fd = &con->write_queue.bfd;
+
+ close(fd->fd);
+ fd->fd = -1;
+ fd->cb = write_queue_bfd_cb;
+ fd->when = 0;
+
+ con->is_connected = 0;
+ con->connection_loss(con);
+}
+
+static void msc_con_timeout(void *_con)
+{
+ struct bsc_msc_connection *con = _con;
+
+ LOGP(DMSC, LOGL_ERROR, "MSC Connection timeout.\n");
+ bsc_msc_lost(con);
+}
+
+static int bsc_msc_except(struct bsc_fd *bfd)
+{
+ struct write_queue *wrt;
+ struct bsc_msc_connection *con;
+
+ LOGP(DMSC, LOGL_ERROR, "Exception on the BFD. Closing down.\n");
+
+ wrt = container_of(bfd, struct write_queue, bfd);
+ con = container_of(wrt, struct bsc_msc_connection, write_queue);
+
+ connection_loss(con);
+ return 0;
+}
+
+/* called in the case of a non blocking connect */
+static int msc_connection_connect(struct bsc_fd *fd, unsigned int what)
+{
+ int rc;
+ int val;
+ struct bsc_msc_connection *con;
+ struct write_queue *queue;
+
+ socklen_t len = sizeof(val);
+
+ if ((what & BSC_FD_WRITE) == 0) {
+ LOGP(DMSC, LOGL_ERROR, "Callback but not readable.\n");
+ return -1;
+ }
+
+ queue = container_of(fd, struct write_queue, bfd);
+ con = container_of(queue, struct bsc_msc_connection, write_queue);
+
+ /* check the socket state */
+ rc = getsockopt(fd->fd, SOL_SOCKET, SO_ERROR, &val, &len);
+ if (rc != 0) {
+ LOGP(DMSC, LOGL_ERROR, "getsockopt for the MSC socket failed.\n");
+ goto error;
+ }
+ if (val != 0) {
+ LOGP(DMSC, LOGL_ERROR, "Not connected to the MSC: %d\n", val);
+ goto error;
+ }
+
+
+ /* go to full operation */
+ fd->cb = write_queue_bfd_cb;
+ fd->when = BSC_FD_READ | BSC_FD_EXCEPT;
+
+ con->is_connected = 1;
+ bsc_del_timer(&con->timeout_timer);
+ LOGP(DMSC, LOGL_NOTICE, "(Re)Connected to the MSC.\n");
+ if (con->connected)
+ con->connected(con);
+ return 0;
+
+error:
+ bsc_unregister_fd(fd);
+ connection_loss(con);
+ return -1;
+}
+static void setnonblocking(struct bsc_fd *fd)
+{
+ int flags;
+
+ flags = fcntl(fd->fd, F_GETFL);
+ if (flags < 0) {
+ perror("fcntl get failed");
+ close(fd->fd);
+ fd->fd = -1;
+ return;
+ }
+
+ flags |= O_NONBLOCK;
+ flags = fcntl(fd->fd, F_SETFL, flags);
+ if (flags < 0) {
+ perror("fcntl get failed");
+ close(fd->fd);
+ fd->fd = -1;
+ return;
+ }
+}
+
+int bsc_msc_connect(struct bsc_msc_connection *con)
+{
+ struct bsc_fd *fd;
+ struct sockaddr_in sin;
+ int on = 1, ret;
+
+ LOGP(DMSC, LOGL_NOTICE, "Attempting to connect MSC at %s:%d\n", con->ip, con->port);
+
+ con->is_connected = 0;
+
+ fd = &con->write_queue.bfd;
+ fd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ fd->data = NULL;
+ fd->priv_nr = 1;
+
+ if (fd->fd < 0) {
+ perror("Creating TCP socket failed");
+ return fd->fd;
+ }
+
+ /* make it non blocking */
+ setnonblocking(fd);
+
+ /* set the socket priority */
+ ret = setsockopt(fd->fd, IPPROTO_IP, IP_TOS,
+ &con->prio, sizeof(con->prio));
+ if (ret != 0)
+ LOGP(DMSC, LOGL_ERROR, "Failed to set prio to %d. %s\n",
+ con->prio, strerror(errno));
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(con->port);
+ inet_aton(con->ip, &sin.sin_addr);
+
+ setsockopt(fd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ ret = connect(fd->fd, (struct sockaddr *) &sin, sizeof(sin));
+
+ if (ret == -1 && errno == EINPROGRESS) {
+ LOGP(DMSC, LOGL_ERROR, "MSC Connection in progress\n");
+ fd->when = BSC_FD_WRITE;
+ fd->cb = msc_connection_connect;
+ con->timeout_timer.cb = msc_con_timeout;
+ con->timeout_timer.data = con;
+ bsc_schedule_timer(&con->timeout_timer, 20, 0);
+ } else if (ret < 0) {
+ perror("Connection failed");
+ connection_loss(con);
+ return ret;
+ } else {
+ fd->when = BSC_FD_READ | BSC_FD_EXCEPT;
+ fd->cb = write_queue_bfd_cb;
+ con->is_connected = 1;
+ if (con->connected)
+ con->connected(con);
+ }
+
+ ret = bsc_register_fd(fd);
+ if (ret < 0) {
+ perror("Registering the fd failed");
+ close(fd->fd);
+ return ret;
+ }
+
+ return ret;
+}
+
+struct bsc_msc_connection *bsc_msc_create(const char *ip, int port, int prio)
+{
+ struct bsc_msc_connection *con;
+
+ con = talloc_zero(NULL, struct bsc_msc_connection);
+ if (!con) {
+ LOGP(DMSC, LOGL_FATAL, "Failed to create the MSC connection.\n");
+ return NULL;
+ }
+
+ con->ip = ip;
+ con->port = port;
+ con->prio = prio;
+ write_queue_init(&con->write_queue, 100);
+ con->write_queue.except_cb = bsc_msc_except;
+ return con;
+}
+
+void bsc_msc_lost(struct bsc_msc_connection *con)
+{
+ write_queue_clear(&con->write_queue);
+ bsc_unregister_fd(&con->write_queue.bfd);
+ connection_loss(con);
+}
+
+static void reconnect_msc(void *_msc)
+{
+ struct bsc_msc_connection *con = _msc;
+
+ LOGP(DMSC, LOGL_NOTICE, "Attempting to reconnect to the MSC.\n");
+ bsc_msc_connect(con);
+}
+
+void bsc_msc_schedule_connect(struct bsc_msc_connection *con)
+{
+ LOGP(DMSC, LOGL_NOTICE, "Attempting to reconnect to the MSC.\n");
+ con->reconnect_timer.cb = reconnect_msc;
+ con->reconnect_timer.data = con;
+ bsc_schedule_timer(&con->reconnect_timer, 5, 0);
+}
+
+struct msgb *bsc_msc_id_get_resp(const char *token)
+{
+ struct msgb *msg;
+
+ if (!token) {
+ LOGP(DMSC, LOGL_ERROR, "No token specified.\n");
+ return NULL;
+ }
+
+ msg = msgb_alloc_headroom(4096, 128, "id resp");
+ if (!msg) {
+ LOGP(DMSC, LOGL_ERROR, "Failed to create the message.\n");
+ return NULL;
+ }
+
+ msg->l2h = msgb_v_put(msg, IPAC_MSGT_ID_RESP);
+ msgb_l16tv_put(msg, strlen(token) + 1,
+ IPAC_IDTAG_UNITNAME, (u_int8_t *) token);
+ return msg;
+}
\ No newline at end of file
diff --git a/openbsc/src/bsc_rll.c b/openbsc/src/bsc_rll.c
index 9a4f5aa..a8e642f 100644
--- a/openbsc/src/bsc_rll.c
+++ b/openbsc/src/bsc_rll.c
@@ -31,6 +31,7 @@
#include <openbsc/gsm_data.h>
#include <openbsc/chan_alloc.h>
#include <openbsc/abis_rsl.h>
+#include <openbsc/signal.h>
struct bsc_rll_req {
struct llist_head list;
@@ -55,7 +56,6 @@
conn = &rllr->lchan->conn;
llist_del(&rllr->list);
- put_subscr_con(conn);
rllr->cb(rllr->lchan, rllr->link_id, rllr->data, type);
talloc_free(rllr);
}
@@ -88,7 +88,6 @@
link_id |= 0x40;
conn = &lchan->conn;
- use_subscr_con(conn);
rllr->lchan = lchan;
rllr->link_id = link_id;
rllr->cb = cb;
@@ -120,3 +119,29 @@
}
}
}
+
+static int rll_lchan_signal(unsigned int subsys, unsigned int signal,
+ void *handler_data, void *signal_data)
+{
+ struct challoc_signal_data *challoc;
+ struct bsc_rll_req *rllr, *rllr2;
+
+ if (subsys != SS_CHALLOC || signal != S_CHALLOC_FREED)
+ return 0;
+
+ challoc = (struct challoc_signal_data *) signal_data;
+
+ llist_for_each_entry_safe(rllr, rllr2, &bsc_rll_reqs, list) {
+ if (rllr->lchan == challoc->lchan) {
+ bsc_del_timer(&rllr->timer);
+ complete_rllr(rllr, BSC_RLLR_IND_ERR_IND);
+ }
+ }
+
+ return 0;
+}
+
+static __attribute__((constructor)) void on_dso_load_rll(void)
+{
+ register_signal_handler(SS_CHALLOC, rll_lchan_signal, NULL);
+}
diff --git a/openbsc/src/bsc_version.c b/openbsc/src/bsc_version.c
index 0266194..432e63b 100644
--- a/openbsc/src/bsc_version.c
+++ b/openbsc/src/bsc_version.c
@@ -20,7 +20,6 @@
#include "bscconfig.h"
-const char *openbsc_version = "OpenBSC " PACKAGE_VERSION;
const char *openbsc_copyright =
"Copyright (C) 2008-2010 Harald Welte, Holger Freyther\n"
"Contributions by Daniel Willmann, Jan Lübbe,Stefan Schmidt\n"
diff --git a/openbsc/src/vty_interface.c b/openbsc/src/bsc_vty.c
similarity index 90%
rename from openbsc/src/vty_interface.c
rename to openbsc/src/bsc_vty.c
index 2799706..a17064d 100644
--- a/openbsc/src/vty_interface.c
+++ b/openbsc/src/bsc_vty.c
@@ -22,9 +22,11 @@
#include <unistd.h>
#include <sys/types.h>
-#include <vty/command.h>
-#include <vty/buffer.h>
-#include <vty/vty.h>
+#include <osmocom/vty/command.h>
+#include <osmocom/vty/buffer.h>
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/logging.h>
+#include <osmocom/vty/telnet_interface.h>
#include <arpa/inet.h>
@@ -37,11 +39,11 @@
#include <openbsc/meas_rep.h>
#include <openbsc/db.h>
#include <osmocore/talloc.h>
-#include <openbsc/telnet_interface.h>
#include <openbsc/vty.h>
#include <openbsc/gprs_ns.h>
+#include <openbsc/debug.h>
-static struct gsm_network *gsmnet;
+#include "../bscconfig.h"
/* FIXME: this should go to some common file */
static const struct value_string gprs_ns_timer_strs[] = {
@@ -94,6 +96,21 @@
1,
};
+extern struct gsm_network *bsc_gsmnet;
+
+struct gsm_network *gsmnet_from_vty(struct vty *v)
+{
+ /* In case we read from the config file, the vty->priv cannot
+ * point to a struct telnet_connection, and thus conn->priv
+ * will not point to the gsm_network structure */
+#if 0
+ struct telnet_connection *conn = v->priv;
+ return (struct gsm_network *) conn->priv;
+#else
+ return bsc_gsmnet;
+#endif
+}
+
static int dummy_config_write(struct vty *v)
{
return CMD_SUCCESS;
@@ -159,7 +176,7 @@
DEFUN(show_net, show_net_cmd, "show network",
SHOW_STR "Display information about a GSM NETWORK\n")
{
- struct gsm_network *net = gsmnet;
+ struct gsm_network *net = gsmnet_from_vty(vty);
net_dump_vty(vty, net);
return CMD_SUCCESS;
@@ -193,6 +210,8 @@
bts->cell_identity,
bts->location_area_code, bts->bsic, bts->tsc,
bts->num_trx, VTY_NEWLINE);
+ vty_out(vty, "Description: %s%s",
+ bts->description ? bts->description : "(null)", VTY_NEWLINE);
vty_out(vty, "MS Max power: %u dBm%s", bts->ms_max_power, VTY_NEWLINE);
vty_out(vty, "Minimum Rx Level for Access: %i dBm%s",
rxlev2dbm(bts->si_common.cell_sel_par.rxlev_acc_min),
@@ -231,7 +250,7 @@
SHOW_STR "Display information about a BTS\n"
"BTS number")
{
- struct gsm_network *net = gsmnet;
+ struct gsm_network *net = gsmnet_from_vty(vty);
int bts_nr;
if (argc != 0) {
@@ -294,6 +313,9 @@
int i;
vty_out(vty, " trx %u%s", trx->nr, VTY_NEWLINE);
+ if (trx->description)
+ vty_out(vty, " description %s%s", trx->description,
+ VTY_NEWLINE);
vty_out(vty, " rf_locked %u%s",
trx->nm_state.administrative == NM_STATE_LOCKED ? 1 : 0,
VTY_NEWLINE);
@@ -352,6 +374,8 @@
vty_out(vty, " bts %u%s", bts->nr, VTY_NEWLINE);
vty_out(vty, " type %s%s", btstype2str(bts->type), VTY_NEWLINE);
+ if (bts->description)
+ vty_out(vty, " description %s%s", bts->description, VTY_NEWLINE);
vty_out(vty, " band %s%s", gsm_band_name(bts->band), VTY_NEWLINE);
vty_out(vty, " cell_identity %u%s", bts->cell_identity, VTY_NEWLINE);
vty_out(vty, " location_area_code %u%s", bts->location_area_code,
@@ -401,6 +425,7 @@
static int config_write_bts(struct vty *v)
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(v);
struct gsm_bts *bts;
llist_for_each_entry(bts, &gsmnet->bts_list, list)
@@ -411,6 +436,8 @@
static int config_write_net(struct vty *vty)
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+
vty_out(vty, "network%s", VTY_NEWLINE);
vty_out(vty, " network country code %u%s", gsmnet->country_code, VTY_NEWLINE);
vty_out(vty, " mobile network code %u%s", gsmnet->network_code, VTY_NEWLINE);
@@ -456,6 +483,8 @@
{
vty_out(vty, "TRX %u of BTS %u is on ARFCN %u%s",
trx->nr, trx->bts->nr, trx->arfcn, VTY_NEWLINE);
+ vty_out(vty, "Description: %s%s",
+ trx->description ? trx->description : "(null)", VTY_NEWLINE);
vty_out(vty, " RF Nominal Power: %d dBm, reduced by %u dB, "
"resulting BS power: %d dBm%s",
trx->nominal_power, trx->max_power_red,
@@ -480,7 +509,7 @@
"BTS Number\n"
"TRX Number\n")
{
- struct gsm_network *net = gsmnet;
+ struct gsm_network *net = gsmnet_from_vty(vty);
struct gsm_bts *bts = NULL;
struct gsm_bts_trx *trx;
int bts_nr, trx_nr;
@@ -546,7 +575,7 @@
SHOW_STR "Display information about a TS\n"
"BTS Number\n" "TRX Number\n" "Timeslot Number\n")
{
- struct gsm_network *net = gsmnet;
+ struct gsm_network *net = gsmnet_from_vty(vty);
struct gsm_bts *bts;
struct gsm_bts_trx *trx;
struct gsm_bts_trx_ts *ts;
@@ -706,7 +735,7 @@
static int lchan_summary(struct vty *vty, int argc, const char **argv,
void (*dump_cb)(struct vty *, struct gsm_lchan *))
{
- struct gsm_network *net = gsmnet;
+ struct gsm_network *net = gsmnet_from_vty(vty);
struct gsm_bts *bts;
struct gsm_bts_trx *trx;
struct gsm_bts_trx_ts *ts;
@@ -924,7 +953,7 @@
SHOW_STR "Display information about paging reuqests of a BTS\n"
"BTS Number\n")
{
- struct gsm_network *net = gsmnet;
+ struct gsm_network *net = gsmnet_from_vty(vty);
struct gsm_bts *bts;
int bts_nr;
@@ -955,7 +984,7 @@
cfg_net_cmd,
"network", NETWORK_STR)
{
- vty->index = gsmnet;
+ vty->index = gsmnet_from_vty(vty);
vty->node = GSMNET_NODE;
return CMD_SUCCESS;
@@ -967,6 +996,8 @@
"network country code <1-999>",
"Set the GSM network country code")
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+
gsmnet->country_code = atoi(argv[0]);
return CMD_SUCCESS;
@@ -977,6 +1008,8 @@
"mobile network code <1-999>",
"Set the GSM mobile network code")
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+
gsmnet->network_code = atoi(argv[0]);
return CMD_SUCCESS;
@@ -987,6 +1020,8 @@
"short name NAME",
"Set the short GSM network name")
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+
if (gsmnet->name_short)
talloc_free(gsmnet->name_short);
@@ -1000,6 +1035,8 @@
"long name NAME",
"Set the long GSM network name")
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+
if (gsmnet->name_long)
talloc_free(gsmnet->name_long);
@@ -1018,6 +1055,7 @@
"Use SMS-token based authentication\n")
{
enum gsm_auth_policy policy = gsm_auth_policy_parse(argv[0]);
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
gsmnet->auth_policy = policy;
@@ -1029,6 +1067,8 @@
"location updating reject cause <2-111>",
"Set the reject cause of location updating reject\n")
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+
gsmnet->reject_cause = atoi(argv[0]);
return CMD_SUCCESS;
@@ -1037,8 +1077,12 @@
DEFUN(cfg_net_encryption,
cfg_net_encryption_cmd,
"encryption a5 (0|1|2)",
- "Enable or disable encryption (A5) for this network\n")
+ "Encryption options\n"
+ "A5 encryption\n" "A5/0: No encryption\n"
+ "A5/1: Encryption\n" "A5/2: Export-grade Encryption\n")
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+
gsmnet->a5_encryption= atoi(argv[0]);
return CMD_SUCCESS;
@@ -1047,8 +1091,11 @@
DEFUN(cfg_net_neci,
cfg_net_neci_cmd,
"neci (0|1)",
- "Set if NECI of cell selection is to be set")
+ "New Establish Cause Indication\n"
+ "Don't set the NECI bit\n" "Set the NECI bit\n")
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+
gsmnet->neci = atoi(argv[0]);
return CMD_SUCCESS;
}
@@ -1062,6 +1109,8 @@
"Request any location, prefer MS-based\n"
"Request any location, prefer MS-assisted\n")
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+
gsmnet->rrlp.mode = rrlp_mode_parse(argv[0]);
return CMD_SUCCESS;
@@ -1071,6 +1120,8 @@
"mm info (0|1)",
"Whether to send MM INFO after LOC UPD ACCEPT")
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+
gsmnet->send_mm_info = atoi(argv[0]);
return CMD_SUCCESS;
@@ -1085,6 +1136,7 @@
"Perform in-call handover\n")
{
int enable = atoi(argv[0]);
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
if (enable && ipacc_rtp_direct) {
vty_out(vty, "%% Cannot enable handover unless RTP Proxy mode "
@@ -1107,6 +1159,7 @@
HO_WIN_RXLEV_STR
"How many RxLev measurements are used for averaging")
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
gsmnet->handover.win_rxlev_avg = atoi(argv[0]);
return CMD_SUCCESS;
}
@@ -1116,6 +1169,7 @@
HO_WIN_RXQUAL_STR
"How many RxQual measurements are used for averaging")
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
gsmnet->handover.win_rxqual_avg = atoi(argv[0]);
return CMD_SUCCESS;
}
@@ -1125,6 +1179,7 @@
HO_WIN_RXLEV_STR
"How many RxQual measurements are used for averaging")
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
gsmnet->handover.win_rxlev_avg_neigh = atoi(argv[0]);
return CMD_SUCCESS;
}
@@ -1134,6 +1189,7 @@
HO_PBUDGET_STR
"How often to check if we have a better cell (SACCH frames)")
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
gsmnet->handover.pwr_interval = atoi(argv[0]);
return CMD_SUCCESS;
}
@@ -1143,6 +1199,7 @@
HO_PBUDGET_STR
"How many dB does a neighbor to be stronger to become a HO candidate")
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
gsmnet->handover.pwr_hysteresis = atoi(argv[0]);
return CMD_SUCCESS;
}
@@ -1152,6 +1209,7 @@
HANDOVER_STR
"How big is the maximum timing advance before HO is forced")
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
gsmnet->handover.max_distance = atoi(argv[0]);
return CMD_SUCCESS;
}
@@ -1163,6 +1221,7 @@
"Configure GSM Timers\n" \
doc) \
{ \
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty); \
int value = atoi(argv[0]); \
\
if (value < 0 || value > 65535) { \
@@ -1180,7 +1239,7 @@
DECLARE_TIMER(3105, "Currently not used.")
DECLARE_TIMER(3107, "Currently not used.")
DECLARE_TIMER(3109, "Currently not used.")
-DECLARE_TIMER(3111, "Currently not used.")
+DECLARE_TIMER(3111, "Set the RSL timeout to wait before releasing the RF Channel.")
DECLARE_TIMER(3113, "Set the time to try paging a subscriber.")
DECLARE_TIMER(3115, "Currently not used.")
DECLARE_TIMER(3117, "Currently not used.")
@@ -1195,6 +1254,7 @@
"Select a BTS to configure\n"
"BTS Number\n")
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
int bts_nr = atoi(argv[0]);
struct gsm_bts *bts;
@@ -1216,6 +1276,7 @@
}
vty->index = bts;
+ vty->index_sub = &bts->description;
vty->node = BTS_NODE;
return CMD_SUCCESS;
@@ -1679,7 +1740,18 @@
}
#define BSSGP_TIMERS "(blocking-timer|blocking-retries|unblocking-retries|reset-timer|reset-retries|suspend-timer|suspend-retries|resume-timer|resume-retries|capability-update-timer|capability-update-retries)"
-#define BSSGP_TIMERS_HELP ""
+#define BSSGP_TIMERS_HELP \
+ "Tbvc-block timeout\n" \
+ "Tbvc-block retries\n" \
+ "Tbvc-unblock retries\n" \
+ "Tbvcc-reset timeout\n" \
+ "Tbvc-reset retries\n" \
+ "Tbvc-suspend timeout\n" \
+ "Tbvc-suspend retries\n" \
+ "Tbvc-resume timeout\n" \
+ "Tbvc-resume retries\n" \
+ "Tbvc-capa-update timeout\n" \
+ "Tbvc-capa-update retries\n"
DEFUN(cfg_bts_gprs_cell_timer, cfg_bts_gprs_cell_timer_cmd,
"gprs cell timer " BSSGP_TIMERS " <0-255>",
@@ -1763,6 +1835,7 @@
return CMD_WARNING;
vty->index = trx;
+ vty->index_sub = &trx->description;
vty->node = TRX_NODE;
return CMD_SUCCESS;
@@ -1770,7 +1843,7 @@
DEFUN(cfg_trx_arfcn,
cfg_trx_arfcn_cmd,
- "arfcn <1-1024>",
+ "arfcn <0-1024>",
"Set the ARFCN for this TRX\n")
{
int arfcn = atoi(argv[0]);
@@ -1916,21 +1989,53 @@
return CMD_SUCCESS;
}
-extern int bsc_vty_init_extra(struct gsm_network *net);
-
-int bsc_vty_init(struct gsm_network *net)
+void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *net)
{
- gsmnet = net;
+ vty_out(vty, "Channel Requests : %lu total, %lu no channel%s",
+ counter_get(net->stats.chreq.total),
+ counter_get(net->stats.chreq.no_channel), VTY_NEWLINE);
+ vty_out(vty, "Channel Failures : %lu rf_failures, %lu rll failures%s",
+ counter_get(net->stats.chan.rf_fail),
+ counter_get(net->stats.chan.rll_err), VTY_NEWLINE);
+ vty_out(vty, "Paging : %lu attempted, %lu complete, %lu expired%s",
+ counter_get(net->stats.paging.attempted),
+ counter_get(net->stats.paging.completed),
+ counter_get(net->stats.paging.expired), VTY_NEWLINE);
+ vty_out(vty, "BTS failures : %lu OML, %lu RSL%s",
+ counter_get(net->stats.bts.oml_fail),
+ counter_get(net->stats.bts.rsl_fail), VTY_NEWLINE);
+}
- cmd_init(1);
- vty_init();
+DEFUN(logging_fltr_imsi,
+ logging_fltr_imsi_cmd,
+ "logging filter imsi IMSI",
+ LOGGING_STR FILTER_STR
+ "Filter log messages by IMSI\n" "IMSI to be used as filter\n")
+{
+ struct telnet_connection *conn;
+ conn = (struct telnet_connection *) vty->priv;
+ if (!conn->dbg) {
+ vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ log_set_imsi_filter(conn->dbg, argv[0]);
+ return CMD_SUCCESS;
+}
+
+extern int bsc_vty_init_extra(void);
+extern const char *openbsc_copyright;
+
+int bsc_vty_init(void)
+{
install_element_ve(&show_net_cmd);
install_element_ve(&show_bts_cmd);
install_element_ve(&show_trx_cmd);
install_element_ve(&show_ts_cmd);
install_element_ve(&show_lchan_cmd);
install_element_ve(&show_lchan_summary_cmd);
+ install_element_ve(&logging_fltr_imsi_cmd);
install_element_ve(&show_e1drv_cmd);
install_element_ve(&show_e1line_cmd);
@@ -1938,11 +2043,13 @@
install_element_ve(&show_paging_cmd);
- openbsc_vty_add_cmds();
+ logging_vty_add_cmds();
install_element(CONFIG_NODE, &cfg_net_cmd);
install_node(&net_node, config_write_net);
install_default(GSMNET_NODE);
+ install_element(GSMNET_NODE, &ournode_exit_cmd);
+ install_element(GSMNET_NODE, &ournode_end_cmd);
install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
@@ -1975,7 +2082,11 @@
install_element(GSMNET_NODE, &cfg_bts_cmd);
install_node(&bts_node, config_write_bts);
install_default(BTS_NODE);
+ install_element(BTS_NODE, &ournode_exit_cmd);
+ install_element(BTS_NODE, &ournode_end_cmd);
install_element(BTS_NODE, &cfg_bts_type_cmd);
+ install_element(BTS_NODE, &cfg_description_cmd);
+ install_element(BTS_NODE, &cfg_no_description_cmd);
install_element(BTS_NODE, &cfg_bts_band_cmd);
install_element(BTS_NODE, &cfg_bts_ci_cmd);
install_element(BTS_NODE, &cfg_bts_lac_cmd);
@@ -2010,7 +2121,11 @@
install_element(BTS_NODE, &cfg_trx_cmd);
install_node(&trx_node, dummy_config_write);
install_default(TRX_NODE);
+ install_element(TRX_NODE, &ournode_exit_cmd);
+ install_element(TRX_NODE, &ournode_end_cmd);
install_element(TRX_NODE, &cfg_trx_arfcn_cmd);
+ install_element(TRX_NODE, &cfg_description_cmd);
+ install_element(TRX_NODE, &cfg_no_description_cmd);
install_element(TRX_NODE, &cfg_trx_nominal_power_cmd);
install_element(TRX_NODE, &cfg_trx_max_power_red_cmd);
install_element(TRX_NODE, &cfg_trx_rsl_e1_cmd);
@@ -2020,10 +2135,14 @@
install_element(TRX_NODE, &cfg_ts_cmd);
install_node(&ts_node, dummy_config_write);
install_default(TS_NODE);
+ install_element(TS_NODE, &ournode_exit_cmd);
+ install_element(TS_NODE, &ournode_end_cmd);
install_element(TS_NODE, &cfg_ts_pchan_cmd);
install_element(TS_NODE, &cfg_ts_e1_subslot_cmd);
- bsc_vty_init_extra(net);
+ abis_nm_vty_init();
+
+ bsc_vty_init_extra();
return 0;
}
diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c
index 107abdc..d6e4ff1 100644
--- a/openbsc/src/chan_alloc.c
+++ b/openbsc/src/chan_alloc.c
@@ -338,6 +338,8 @@
void lchan_reset(struct gsm_lchan *lchan)
{
bsc_del_timer(&lchan->T3101);
+ bsc_del_timer(&lchan->T3111);
+ bsc_del_timer(&lchan->error_timer);
lchan->type = GSM_LCHAN_NONE;
lchan->state = LCHAN_S_NONE;
@@ -363,7 +365,7 @@
DEBUGP(DRLL, "%s Recycling Channel\n", gsm_lchan_name(lchan));
rsl_lchan_set_state(lchan, LCHAN_S_REL_REQ);
- rsl_release_request(lchan, 0);
+ rsl_release_request(lchan, 0, 0);
return 1;
}
@@ -376,7 +378,7 @@
bsc_schedule_timer(&lchan->conn.release_timer, LCHAN_RELEASE_TIMEOUT);
}
-struct gsm_lchan* lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr) {
+static struct gsm_lchan* lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr) {
struct gsm_bts_trx *trx;
int ts_no, lchan_no;
@@ -394,7 +396,7 @@
return NULL;
}
-struct gsm_lchan *lchan_for_subscr(struct gsm_subscriber *subscr)
+struct gsm_subscriber_connection *connection_for_subscr(struct gsm_subscriber *subscr)
{
struct gsm_bts *bts;
struct gsm_network *net = subscr->net;
@@ -403,7 +405,7 @@
llist_for_each_entry(bts, &net->bts_list, list) {
lchan = lchan_find(bts, subscr);
if (lchan)
- return lchan;
+ return &lchan->conn;
}
return NULL;
diff --git a/openbsc/src/common_vty.c b/openbsc/src/common_vty.c
new file mode 100644
index 0000000..ffa676d
--- /dev/null
+++ b/openbsc/src/common_vty.c
@@ -0,0 +1,185 @@
+/* OpenBSC VTY common helpers */
+/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2009-2010 by Holger Hans Peter Freyther
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <osmocore/talloc.h>
+
+#include <openbsc/vty.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/debug.h>
+#include <openbsc/gsm_subscriber.h>
+#include <openbsc/bsc_nat.h>
+
+#include <osmocom/vty/telnet_interface.h>
+#include <osmocom/vty/command.h>
+#include <osmocom/vty/buffer.h>
+#include <osmocom/vty/vty.h>
+
+
+enum node_type bsc_vty_go_parent(struct vty *vty)
+{
+ switch (vty->node) {
+ case GSMNET_NODE:
+ vty->node = CONFIG_NODE;
+ vty->index = NULL;
+ break;
+ case BTS_NODE:
+ vty->node = GSMNET_NODE;
+ {
+ /* set vty->index correctly ! */
+ struct gsm_bts *bts = vty->index;
+ vty->index = bts->network;
+ }
+ break;
+ case TRX_NODE:
+ vty->node = BTS_NODE;
+ {
+ /* set vty->index correctly ! */
+ struct gsm_bts_trx *trx = vty->index;
+ vty->index = trx->bts;
+ }
+ break;
+ case TS_NODE:
+ vty->node = TRX_NODE;
+ {
+ /* set vty->index correctly ! */
+ struct gsm_bts_trx_ts *ts = vty->index;
+ vty->index = ts->trx;
+ }
+ break;
+ case OML_NODE:
+ vty->node = ENABLE_NODE;
+ talloc_free(vty->index);
+ vty->index = NULL;
+ break;
+ case NAT_NODE:
+ vty->node = CONFIG_NODE;
+ vty->index = NULL;
+ break;
+ case BSC_NODE:
+ vty->node = NAT_NODE;
+ {
+ struct bsc_config *bsc_config = vty->index;
+ vty->index = bsc_config->nat;
+ }
+ break;
+ default:
+ vty->node = CONFIG_NODE;
+ }
+
+ return vty->node;
+}
+
+/* Down vty node level. */
+gDEFUN(ournode_exit,
+ ournode_exit_cmd, "exit", "Exit current mode and down to previous mode\n")
+{
+ switch (vty->node) {
+ case GSMNET_NODE:
+ vty->node = CONFIG_NODE;
+ vty->index = NULL;
+ break;
+ case BTS_NODE:
+ vty->node = GSMNET_NODE;
+ {
+ /* set vty->index correctly ! */
+ struct gsm_bts *bts = vty->index;
+ vty->index = bts->network;
+ vty->index_sub = NULL;
+ }
+ break;
+ case TRX_NODE:
+ vty->node = BTS_NODE;
+ {
+ /* set vty->index correctly ! */
+ struct gsm_bts_trx *trx = vty->index;
+ vty->index = trx->bts;
+ vty->index_sub = &trx->bts->description;
+ }
+ break;
+ case TS_NODE:
+ vty->node = TRX_NODE;
+ {
+ /* set vty->index correctly ! */
+ struct gsm_bts_trx_ts *ts = vty->index;
+ vty->index = ts->trx;
+ vty->index_sub = &ts->trx->description;
+ }
+ break;
+ case BSC_NODE:
+ vty->node = NAT_NODE;
+ {
+ struct bsc_config *bsc_config = vty->index;
+ vty->index = bsc_config->nat;
+ }
+ break;
+ case MGCP_NODE:
+ case GBPROXY_NODE:
+ case SGSN_NODE:
+ case NS_NODE:
+ case BSSGP_NODE:
+ case NAT_NODE:
+ vty->node = CONFIG_NODE;
+ vty->index = NULL;
+ break;
+ case OML_NODE:
+ vty->node = ENABLE_NODE;
+ talloc_free(vty->index);
+ vty->index = NULL;
+ break;
+ default:
+ break;
+ }
+ return CMD_SUCCESS;
+}
+
+/* End of configuration. */
+gDEFUN(ournode_end,
+ ournode_end_cmd, "end", "End current mode and change to enable mode.")
+{
+ switch (vty->node) {
+ case VIEW_NODE:
+ case ENABLE_NODE:
+ /* Nothing to do. */
+ break;
+ case CONFIG_NODE:
+ case GSMNET_NODE:
+ case BTS_NODE:
+ case TRX_NODE:
+ case TS_NODE:
+ case MGCP_NODE:
+ case GBPROXY_NODE:
+ case SGSN_NODE:
+ case NS_NODE:
+ case VTY_NODE:
+ vty_config_unlock(vty);
+ vty->node = ENABLE_NODE;
+ vty->index = NULL;
+ vty->index_sub = NULL;
+ break;
+ default:
+ break;
+ }
+ return CMD_SUCCESS;
+}
+
diff --git a/openbsc/src/db.c b/openbsc/src/db.c
index 57a7863..72e6bd3 100644
--- a/openbsc/src/db.c
+++ b/openbsc/src/db.c
@@ -132,17 +132,15 @@
"timestamp TIMESTAMP NOT NULL, "
"value INTEGER NOT NULL, "
"name TEXT NOT NULL, "
- "index INTEGER NOT NULL "
+ "idx INTEGER NOT NULL "
")",
"CREATE TABLE IF NOT EXISTS AuthKeys ("
- "id INTEGER PRIMARY KEY AUTOINCREMENT, "
- "subscriber_id INTEGER UNIQUE NOT NULL, "
+ "subscriber_id INTEGER PRIMARY KEY, "
"algorithm_id INTEGER NOT NULL, "
"a3a8_ki BLOB "
")",
- "CREATE TABLE IF NOT EXISTS AuthTuples ("
- "id INTEGER PRIMARY KEY AUTOINCREMENT, "
- "subscriber_id NUMERIC UNIQUE NOT NULL, "
+ "CREATE TABLE IF NOT EXISTS AuthLastTuples ("
+ "subscriber_id INTEGER PRIMARY KEY, "
"issued TIMESTAMP NOT NULL, "
"use_count INTEGER NOT NULL DEFAULT 0, "
"key_seq INTEGER NOT NULL, "
@@ -350,8 +348,8 @@
return 0;
}
-int get_authinfo_by_subscr(struct gsm_auth_info *ainfo,
- struct gsm_subscriber *subscr)
+int db_get_authinfo_for_subscr(struct gsm_auth_info *ainfo,
+ struct gsm_subscriber *subscr)
{
dbi_result result;
const unsigned char *a3a8_ki;
@@ -379,8 +377,8 @@
return 0;
}
-int set_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)
{
dbi_result result;
struct gsm_auth_info ainfo_old;
@@ -402,7 +400,7 @@
}
/* Check if already existing */
- rc = get_authinfo_by_subscr(&ainfo_old, subscr);
+ rc = db_get_authinfo_for_subscr(&ainfo_old, subscr);
if (rc && rc != -ENOENT)
return rc;
upd = rc ? 0 : 1;
@@ -435,15 +433,15 @@
return 0;
}
-int get_authtuple_by_subscr(struct gsm_auth_tuple *atuple,
- struct gsm_subscriber *subscr)
+int db_get_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple,
+ struct gsm_subscriber *subscr)
{
dbi_result result;
int len;
const unsigned char *blob;
result = dbi_conn_queryf(conn,
- "SELECT * FROM AuthTuples WHERE subscriber_id=%u",
+ "SELECT * FROM AuthLastTuples WHERE subscriber_id=%u",
subscr->id);
if (!result)
return -EIO;
@@ -488,8 +486,8 @@
return -EIO;
}
-int set_authtuple_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)
{
dbi_result result;
int rc, upd;
@@ -499,7 +497,7 @@
/* Deletion ? */
if (atuple == NULL) {
result = dbi_conn_queryf(conn,
- "DELETE FROM AuthTuples WHERE subscriber_id=%u",
+ "DELETE FROM AuthLastTuples WHERE subscriber_id=%u",
subscr->id);
if (!result)
@@ -511,7 +509,7 @@
}
/* Check if already existing */
- rc = get_authtuple_by_subscr(&atuple_old, subscr);
+ rc = db_get_lastauthtuple_for_subscr(&atuple_old, subscr);
if (rc && rc != -ENOENT)
return rc;
upd = rc ? 0 : 1;
@@ -526,7 +524,7 @@
if (!upd) {
result = dbi_conn_queryf(conn,
- "INSERT INTO AuthTuples "
+ "INSERT INTO AuthLastTuples "
"(subscriber_id, issued, use_count, "
"key_seq, rand, sres, kc) "
"VALUES (%u, datetime('now'), %u, "
@@ -537,7 +535,7 @@
char *issued = atuple->key_seq == atuple_old.key_seq ?
"issued" : "datetime('now')";
result = dbi_conn_queryf(conn,
- "UPDATE AuthKeys "
+ "UPDATE AuthLastTuples "
"SET issued=%s, use_count=%u, "
"key_seq=%u, rand=%s, sres=%s, kc=%s "
"WHERE subscriber_id = %u",
@@ -1202,7 +1200,7 @@
result = dbi_conn_queryf(conn,
"Insert INTO RateCounters "
- "(timestamp,name,index,value) VALUES "
+ "(timestamp,name,idx,value) VALUES "
"(datetime('now'),%s.%s,%u,%"PRIu64")",
q_prefix, q_name, ctrg->idx, ctrg->ctr[num].current);
diff --git a/openbsc/src/debug.c b/openbsc/src/debug.c
index 9218f64..c701f50 100644
--- a/openbsc/src/debug.c
+++ b/openbsc/src/debug.c
@@ -154,33 +154,58 @@
[DNS] = {
.name = "DNS",
.description = "GPRS Network Service (NS)",
- .enabled = 1, .loglevel = LOGL_DEBUG,
+ .enabled = 1, .loglevel = LOGL_INFO,
},
[DBSSGP] = {
.name = "DBSSGP",
.description = "GPRS BSS Gateway Protocol (BSSGP)",
.enabled = 1, .loglevel = LOGL_DEBUG,
},
-};
-
-enum log_ctxt {
- CTX_SUBSCRIBER,
+ [DLLC] = {
+ .name = "DLLC",
+ .description = "GPRS Logical Link Control Protocol (LLC)",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DSNDCP] = {
+ .name = "DSNDCP",
+ .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DNAT] = {
+ .name = "DNAT",
+ .description = "GSM 08.08 NAT/Multipkexer",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
};
enum log_filter {
_FLT_ALL = LOG_FILTER_ALL, /* libosmocore */
FLT_IMSI = 1,
+ FLT_NSVC = 2,
+ FLT_BVC = 3,
};
static int filter_fn(const struct log_context *ctx,
struct log_target *tar)
{
- struct gsm_subscriber *subscr = ctx->ctx[CTX_SUBSCRIBER];
+ struct gsm_subscriber *subscr = ctx->ctx[BSC_CTX_SUBSCR];
+ const struct gprs_nsvc *nsvc = ctx->ctx[BSC_CTX_NSVC];
+ const struct gprs_nsvc *bvc = ctx->ctx[BSC_CTX_BVC];
if ((tar->filter_map & (1 << FLT_IMSI)) != 0
&& subscr && strcmp(subscr->imsi, tar->filter_data[FLT_IMSI]) == 0)
return 1;
+ /* Filter on the NS Virtual Connection */
+ if ((tar->filter_map & (1 << FLT_NSVC)) != 0
+ && nsvc && (nsvc == tar->filter_data[FLT_NSVC]))
+ return 1;
+
+ /* Filter on the NS Virtual Connection */
+ if ((tar->filter_map & (1 << FLT_BVC)) != 0
+ && bvc && (bvc == tar->filter_data[FLT_BVC]))
+ return 1;
+
return 0;
}
@@ -201,3 +226,25 @@
target->filter_data[FLT_IMSI] = NULL;
}
}
+
+void log_set_nsvc_filter(struct log_target *target, struct gprs_nsvc *nsvc)
+{
+ if (nsvc) {
+ target->filter_map |= (1 << FLT_NSVC);
+ target->filter_data[FLT_NSVC] = nsvc;
+ } else if (target->filter_data[FLT_NSVC]) {
+ target->filter_map = ~(1 << FLT_NSVC);
+ target->filter_data[FLT_NSVC] = NULL;
+ }
+}
+
+void log_set_bvc_filter(struct log_target *target, struct bssgp_bvc_ctx *bctx)
+{
+ if (bctx) {
+ target->filter_map |= (1 << FLT_BVC);
+ target->filter_data[FLT_BVC] = bctx;
+ } else if (target->filter_data[FLT_NSVC]) {
+ target->filter_map = ~(1 << FLT_BVC);
+ target->filter_data[FLT_BVC] = NULL;
+ }
+}
diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am
index 88c358a..30b45f6 100644
--- a/openbsc/src/gprs/Makefile.am
+++ b/openbsc/src/gprs/Makefile.am
@@ -1,18 +1,25 @@
INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS)
+AM_CFLAGS=-Wall -fno-strict-aliasing $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS)
+noinst_LIBRARIES = libgb.a
+
+if HAVE_LIBGTP
sbin_PROGRAMS = osmo-gbproxy osmo-sgsn
-noinst_LIBRARIES = libsgsn.a
+else
+sbin_PROGRAMS = osmo-gbproxy
+endif
-libsgsn_a_SOURCES = gprs_ns.c gprs_bssgp.c gprs_llc.c gsm_04_08_gprs.c \
- crc24.c gprs_sgsn.c gprs_bssgp_util.c
+
+libgb_a_SOURCES = gprs_ns.c gprs_ns_frgre.c gprs_ns_vty.c \
+ gprs_bssgp.c gprs_bssgp_util.c gprs_bssgp_vty.c \
+ gprs_llc.c gprs_llc_vty.c crc24.c
osmo_gbproxy_SOURCES = gb_proxy.c gb_proxy_main.c gb_proxy_vty.c \
- gprs_ns.c gprs_ns_vty.c gprs_bssgp_util.c \
$(top_srcdir)/src/socket.c $(top_srcdir)/src/debug.c
-osmo_gbproxy_LDADD = $(top_builddir)/src/libvty.a
+osmo_gbproxy_LDADD = libgb.a $(top_builddir)/src/libvty.a
-osmo_sgsn_SOURCES = sgsn_main.c sgsn_vty.c gprs_ns_vty.c \
+osmo_sgsn_SOURCES = gprs_gmm.c gprs_sgsn.c gprs_sndcp.c \
+ sgsn_main.c sgsn_vty.c sgsn_libgtp.c \
$(top_srcdir)/src/socket.c $(top_srcdir)/src/debug.c
-osmo_sgsn_LDADD = $(top_builddir)/src/libvty.a libsgsn.a
+osmo_sgsn_LDADD = libgb.a $(top_builddir)/src/libvty.a -lgtp
diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c
index 5fbf9bf..a95929b 100644
--- a/openbsc/src/gprs/gb_proxy.c
+++ b/openbsc/src/gprs/gb_proxy.c
@@ -122,16 +122,38 @@
/* FIXME: this needs to go to libosmocore/msgb.c */
static struct msgb *msgb_copy(const struct msgb *msg, const char *name)
{
+ struct openbsc_msgb_cb *old_cb, *new_cb;
struct msgb *new_msg;
new_msg = msgb_alloc(msg->data_len, name);
if (!new_msg)
return NULL;
- /* copy header */
- memcpy(new_msg, msg, sizeof(*new_msg));
/* copy data */
- memcpy(new_msg->data, msg->data, new_msg->data_len);
+ memcpy(new_msg->_data, msg->_data, new_msg->data_len);
+
+ /* copy header */
+ new_msg->len = msg->len;
+ new_msg->data += msg->data - msg->_data;
+ new_msg->head += msg->head - msg->_data;
+ new_msg->tail += msg->tail - msg->_data;
+
+ new_msg->l1h = new_msg->_data + (msg->l1h - msg->_data);
+ new_msg->l2h = new_msg->_data + (msg->l2h - msg->_data);
+ new_msg->l3h = new_msg->_data + (msg->l3h - msg->_data);
+ new_msg->l4h = new_msg->_data + (msg->l4h - msg->_data);
+
+ /* copy GB specific data */
+ old_cb = OBSC_MSGB_CB(msg);
+ new_cb = OBSC_MSGB_CB(new_msg);
+
+ new_cb->bssgph = new_msg->_data + (old_cb->bssgph - msg->_data);
+ new_cb->llch = new_msg->_data + (old_cb->llch - msg->_data);
+
+ new_cb->bssgp_cell_id = old_cb->bssgp_cell_id;
+ new_cb->nsei = old_cb->nsei;
+ new_cb->bvci = old_cb->bvci;
+ new_cb->tlli = old_cb->tlli;
return new_msg;
}
@@ -320,11 +342,11 @@
} else if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA)) {
peer = peer_by_rac(TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA));
LOGPC(DGPRS, LOGL_INFO, "routing by RAC to peer BVCI=%u\n",
- peer->bvci);
+ peer ? peer->bvci : -1);
} else if (TLVP_PRESENT(tp, BSSGP_IE_LOCATION_AREA)) {
peer = peer_by_lac(TLVP_VAL(tp, BSSGP_IE_LOCATION_AREA));
LOGPC(DGPRS, LOGL_INFO, "routing by LAC to peer BVCI=%u\n",
- peer->bvci);
+ peer ? peer->bvci : -1);
} else
LOGPC(DGPRS, LOGL_INFO, "\n");
@@ -507,6 +529,18 @@
return rc;
}
+int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi)
+{
+ struct gprs_nsvc *nsvc;
+
+ llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
+ if (!nsvc->persistent)
+ continue;
+ gprs_nsvc_reset(nsvc, NS_CAUSE_OM_INTERVENTION);
+ }
+ return 0;
+}
+
/* Signal handler for signals from NS layer */
int gbprox_signal(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
@@ -555,7 +589,7 @@
}
-#include <vty/command.h>
+#include <osmocom/vty/command.h>
gDEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy",
SHOW_STR "Display information about the Gb proxy")
@@ -567,14 +601,16 @@
struct gprs_ra_id raid;
gsm48_parse_ra(&raid, peer->ra);
- vty_out(vty, "NSEI %5u, NS-VC %5u, PTP-BVCI %u, "
- "RAC %u-%u-%u-%u%s",
+ vty_out(vty, "NSEI %5u, NS-VC %5u, PTP-BVCI %5u, "
+ "RAC %u-%u-%u-%u",
nsvc->nsei, nsvc->nsvci, peer->bvci,
- raid.mcc, raid.mnc, raid.lac, raid.rac, VTY_NEWLINE);
- if (nsvc->nsi->ll == GPRS_NS_LL_UDP)
- vty_out(vty, " remote address %s:%u%s",
+ raid.mcc, raid.mnc, raid.lac, raid.rac);
+ if (nsvc->ll == GPRS_NS_LL_UDP || nsvc->ll == GPRS_NS_LL_FR_GRE)
+ vty_out(vty, " %s:%u%s",
inet_ntoa(nsvc->ip.bts_addr.sin_addr),
ntohs(nsvc->ip.bts_addr.sin_port), VTY_NEWLINE);
+ else
+ vty_out(vty, "%s", VTY_NEWLINE);
}
return CMD_SUCCESS;
}
diff --git a/openbsc/src/gprs/gb_proxy_main.c b/openbsc/src/gprs/gb_proxy_main.c
index fc8f164..32bbe38 100644
--- a/openbsc/src/gprs/gb_proxy_main.c
+++ b/openbsc/src/gprs/gb_proxy_main.c
@@ -42,10 +42,12 @@
#include <openbsc/debug.h>
#include <openbsc/gprs_ns.h>
#include <openbsc/gprs_bssgp.h>
-#include <openbsc/telnet_interface.h>
#include <openbsc/vty.h>
#include <openbsc/gb_proxy.h>
+#include <osmocom/vty/command.h>
+#include <osmocom/vty/telnet_interface.h>
+
#include "../../bscconfig.h"
/* this is here for the vty... it will never be called */
@@ -56,15 +58,13 @@
void *tall_bsc_ctx;
-const char *openbsc_version = "Osmocom NSIP Proxy " PACKAGE_VERSION;
const char *openbsc_copyright =
"Copyright (C) 2010 Harald Welte and On-Waves\n"
- "Contributions by Daniel Willmann, Jan Lübbe, Stefan Schmidt\n"
- "Dieter Spaar, Andreas Eversberg, Holger Freyther\n\n"
"License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n";
+static struct log_target *stderr_target;
static char *config_file = "osmo_gbproxy.cfg";
struct gbproxy_config gbcfg;
@@ -116,13 +116,86 @@
}
}
+static void print_usage()
+{
+ printf("Usage: bsc_hack\n");
+}
+
+static void print_help()
+{
+ printf(" Some useful help...\n");
+ printf(" -h --help this text\n");
+ printf(" -d option --debug=DNS:DGPRS,0:0 enable debugging\n");
+ printf(" -c --config-file filename The config file to use.\n");
+ printf(" -s --disable-color\n");
+ printf(" -T --timestamp Prefix every log line with a timestamp\n");
+ printf(" -V --version. Print the version of OpenBSC.\n");
+ printf(" -e --log-level number. Set a global loglevel.\n");
+}
+
+static void handle_options(int argc, char **argv)
+{
+ while (1) {
+ int option_index = 0, c;
+ static struct option long_options[] = {
+ { "help", 0, 0, 'h' },
+ { "debug", 1, 0, 'd' },
+ { "config-file", 1, 0, 'c' },
+ { "disable-color", 0, 0, 's' },
+ { "timestamp", 0, 0, 'T' },
+ { "version", 0, 0, 'V' },
+ { "log-level", 1, 0, 'e' },
+ { 0, 0, 0, 0 }
+ };
+
+ c = getopt_long(argc, argv, "hd:c:sTVe:",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_usage();
+ print_help();
+ exit(0);
+ case 's':
+ log_set_use_color(stderr_target, 0);
+ break;
+ case 'd':
+ log_parse_category_mask(stderr_target, optarg);
+ break;
+ case 'c':
+ config_file = strdup(optarg);
+ break;
+ case 'T':
+ log_set_print_timestamp(stderr_target, 1);
+ break;
+ case 'e':
+ log_set_log_level(stderr_target, atoi(optarg));
+ break;
+ case 'V':
+ print_version(1);
+ exit(0);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
extern void *tall_msgb_ctx;
+extern enum node_type bsc_vty_go_parent(struct vty *vty);
+
+static struct vty_app_info vty_info = {
+ .name = "Osmocom Gb Proxy",
+ .version = PACKAGE_VERSION,
+ .go_parent_cb = bsc_vty_go_parent,
+};
+
int main(int argc, char **argv)
{
struct gsm_network dummy_network;
- struct log_target *stderr_target;
- struct sockaddr_in sin;
int rc;
tall_bsc_ctx = talloc_named_const(NULL, 0, "nsip_proxy");
@@ -139,8 +212,18 @@
log_add_target(stderr_target);
log_set_all_filter(stderr_target, 1);
+ vty_info.copyright = openbsc_copyright;
+ vty_init(&vty_info);
+ logging_vty_add_cmds();
+ gbproxy_vty_init();
+
+ handle_options(argc, argv);
+
rate_ctr_init(tall_bsc_ctx);
- telnet_init(&dummy_network, 4246);
+
+ rc = telnet_init(tall_bsc_ctx, &dummy_network, 4246);
+ if (rc < 0)
+ exit(1);
bssgp_nsi = gprs_ns_instantiate(&proxy_ns_cb);
if (!bssgp_nsi) {
@@ -157,14 +240,28 @@
exit(2);
}
- nsip_listen(bssgp_nsi, gbcfg.nsip_listen_port);
+ if (!nsvc_by_nsei(gbcfg.nsi, gbcfg.nsip_sgsn_nsei)) {
+ LOGP(DGPRS, LOGL_FATAL, "You cannot proxy to NSEI %u "
+ "without creating that NSEI before\n",
+ gbcfg.nsip_sgsn_nsei);
+ exit(2);
+ }
- /* 'establish' the outgoing connection to the SGSN */
- sin.sin_family = AF_INET;
- sin.sin_port = htons(gbcfg.nsip_sgsn_port);
- sin.sin_addr.s_addr = htonl(gbcfg.nsip_sgsn_ip);
- nsip_connect(bssgp_nsi, &sin, gbcfg.nsip_sgsn_nsei,
- gbcfg.nsip_sgsn_nsvci);
+ rc = gprs_ns_nsip_listen(bssgp_nsi);
+ if (rc < 0) {
+ LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen on NSIP socket\n");
+ exit(2);
+ }
+
+ rc = gprs_ns_frgre_listen(bssgp_nsi);
+ if (rc < 0) {
+ LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen GRE "
+ "socket. Do you have CAP_NET_RAW?\n");
+ exit(2);
+ }
+
+ /* Reset all the persistent NS-VCs that we've read from the config */
+ gbprox_reset_persistent_nsvcs(bssgp_nsi);
while (1) {
rc = bsc_select_main(0);
@@ -174,15 +271,3 @@
exit(0);
}
-
-struct gsm_network;
-int bsc_vty_init(struct gsm_network *dummy)
-{
- cmd_init(1);
- vty_init();
-
- openbsc_vty_add_cmds();
- gbproxy_vty_init();
- return 0;
-}
-
diff --git a/openbsc/src/gprs/gb_proxy_vty.c b/openbsc/src/gprs/gb_proxy_vty.c
index e1cf97e..7b6d2da 100644
--- a/openbsc/src/gprs/gb_proxy_vty.c
+++ b/openbsc/src/gprs/gb_proxy_vty.c
@@ -29,9 +29,10 @@
#include <openbsc/debug.h>
#include <openbsc/gb_proxy.h>
#include <openbsc/gprs_ns.h>
+#include <openbsc/vty.h>
-#include <vty/command.h>
-#include <vty/vty.h>
+#include <osmocom/vty/command.h>
+#include <osmocom/vty/vty.h>
static struct gbproxy_config *g_cfg = NULL;
@@ -46,25 +47,9 @@
static int config_write_gbproxy(struct vty *vty)
{
- struct in_addr ia;
-
vty_out(vty, "gbproxy%s", VTY_NEWLINE);
- if (g_cfg->nsip_listen_ip) {
- ia.s_addr = htonl(g_cfg->nsip_listen_ip);
- vty_out(vty, " nsip bss local ip %s%s", inet_ntoa(ia),
- VTY_NEWLINE);
- }
- vty_out(vty, " nsip bss local port %u%s", g_cfg->nsip_listen_port,
- VTY_NEWLINE);
- ia.s_addr = htonl(g_cfg->nsip_sgsn_ip);
- vty_out(vty, " nsip sgsn remote ip %s%s", inet_ntoa(ia),
- VTY_NEWLINE);
- vty_out(vty, " nsip sgsn remote port %u%s", g_cfg->nsip_sgsn_port,
- VTY_NEWLINE);
- vty_out(vty, " nsip sgsn nsei %u%s", g_cfg->nsip_sgsn_nsei,
- VTY_NEWLINE);
- vty_out(vty, " nsip sgsn nsvci %u%s", g_cfg->nsip_sgsn_nsvci,
+ vty_out(vty, " sgsn nsei %u%s", g_cfg->nsip_sgsn_nsei,
VTY_NEWLINE);
return CMD_SUCCESS;
@@ -79,58 +64,9 @@
return CMD_SUCCESS;
}
-DEFUN(cfg_nsip_bss_local_ip,
- cfg_nsip_bss_local_ip_cmd,
- "nsip bss local ip A.B.C.D",
- "Set the IP address on which we listen for BSS connects")
-{
- struct in_addr ia;
-
- inet_aton(argv[0], &ia);
- g_cfg->nsip_listen_ip = ntohl(ia.s_addr);
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nsip_bss_local_port,
- cfg_nsip_bss_local_port_cmd,
- "nsip bss local port <0-65534>",
- "Set the UDP port on which we listen for BSS connects")
-{
- unsigned int port = atoi(argv[0]);
-
- g_cfg->nsip_listen_port = port;
- return CMD_SUCCESS;
-}
-
-
-DEFUN(cfg_nsip_sgsn_ip,
- cfg_nsip_sgsn_ip_cmd,
- "nsip sgsn remote ip A.B.C.D",
- "Set the IP of the SGSN to which the proxy shall connect")
-{
- struct in_addr ia;
-
- inet_aton(argv[0], &ia);
- g_cfg->nsip_sgsn_ip = ntohl(ia.s_addr);
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_nsip_sgsn_port,
- cfg_nsip_sgsn_port_cmd,
- "nsip sgsn remote port <0-65534>",
- "Set the UDP port of the SGSN to which the proxy shall connect")
-{
- unsigned int port = atoi(argv[0]);
-
- g_cfg->nsip_sgsn_port = port;
- return CMD_SUCCESS;
-}
-
DEFUN(cfg_nsip_sgsn_nsei,
cfg_nsip_sgsn_nsei_cmd,
- "nsip sgsn nsei <0-65534>",
+ "sgsn nsei <0-65534>",
"Set the NSEI to be used in the connection with the SGSN")
{
unsigned int port = atoi(argv[0]);
@@ -139,17 +75,6 @@
return CMD_SUCCESS;
}
-DEFUN(cfg_nsip_sgsn_nsvci,
- cfg_nsip_sgsn_nsvci_cmd,
- "nsip sgsn nsvci <0-65534>",
- "Set the NSVCI to be used in the connection with the SGSN")
-{
- unsigned int port = atoi(argv[0]);
-
- g_cfg->nsip_sgsn_nsvci = port;
- return CMD_SUCCESS;
-}
-
int gbproxy_vty_init(void)
{
install_element_ve(&show_gbproxy_cmd);
@@ -157,12 +82,9 @@
install_element(CONFIG_NODE, &cfg_gbproxy_cmd);
install_node(&gbproxy_node, config_write_gbproxy);
install_default(GBPROXY_NODE);
- install_element(GBPROXY_NODE, &cfg_nsip_bss_local_ip_cmd);
- install_element(GBPROXY_NODE, &cfg_nsip_bss_local_port_cmd);
- install_element(GBPROXY_NODE, &cfg_nsip_sgsn_ip_cmd);
- install_element(GBPROXY_NODE, &cfg_nsip_sgsn_port_cmd);
+ install_element(GBPROXY_NODE, &ournode_exit_cmd);
+ install_element(GBPROXY_NODE, &ournode_end_cmd);
install_element(GBPROXY_NODE, &cfg_nsip_sgsn_nsei_cmd);
- install_element(GBPROXY_NODE, &cfg_nsip_sgsn_nsvci_cmd);
return 0;
}
@@ -172,7 +94,7 @@
int rc;
g_cfg = cfg;
- rc = vty_read_config_file(config_file);
+ rc = vty_read_config_file(config_file, NULL);
if (rc < 0) {
fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
return rc;
diff --git a/openbsc/src/gprs/gprs_bssgp.c b/openbsc/src/gprs/gprs_bssgp.c
index 9fdfd32..0ec873c 100644
--- a/openbsc/src/gprs/gprs_bssgp.c
+++ b/openbsc/src/gprs/gprs_bssgp.c
@@ -18,6 +18,9 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
+ * TODO:
+ * o properly count incoming BVC-RESET packets in counter group
+ * o set log context as early as possible for outgoing packets
*/
#include <errno.h>
@@ -28,6 +31,7 @@
#include <osmocore/msgb.h>
#include <osmocore/tlv.h>
#include <osmocore/talloc.h>
+#include <osmocore/rate_ctr.h>
#include <openbsc/debug.h>
#include <openbsc/gsm_data.h>
@@ -35,38 +39,46 @@
#include <openbsc/gprs_bssgp.h>
#include <openbsc/gprs_llc.h>
#include <openbsc/gprs_ns.h>
+#include <openbsc/gprs_sgsn.h>
+#include <openbsc/gprs_gmm.h>
void *bssgp_tall_ctx = NULL;
#define BVC_F_BLOCKED 0x0001
-/* The per-BTS context that we keep on the SGSN side of the BSSGP link */
-struct bssgp_bts_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 bvc_state;
-
- /* 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;
+enum bssgp_ctr {
+ BSSGP_CTR_PKTS_IN,
+ BSSGP_CTR_PKTS_OUT,
+ BSSGP_CTR_BYTES_IN,
+ BSSGP_CTR_BYTES_OUT,
+ BSSGP_CTR_BLOCKED,
+ BSSGP_CTR_DISCARDED,
};
-static LLIST_HEAD(bts_ctxts);
+
+static const struct rate_ctr_desc bssgp_ctr_description[] = {
+ { "packets.in", "Packets at BSSGP Level ( In)" },
+ { "packets.out","Packets at BSSGP Level (Out)" },
+ { "bytes.in", "Bytes at BSSGP Level ( In)" },
+ { "bytes.out", "Bytes at BSSGP Level (Out)" },
+ { "blocked", "BVC Blocking count" },
+ { "discarded", "BVC LLC Discarded count" },
+};
+
+static const struct rate_ctr_group_desc bssgp_ctrg_desc = {
+ .group_name_prefix = "bssgp.bss_ctx",
+ .group_description = "BSSGP Peer Statistics",
+ .num_ctr = ARRAY_SIZE(bssgp_ctr_description),
+ .ctr_desc = bssgp_ctr_description,
+};
+
+LLIST_HEAD(bssgp_bvc_ctxts);
/* Find a BTS Context based on parsed RA ID and Cell ID */
-struct bssgp_bts_ctx *btsctx_by_raid_cid(const struct gprs_ra_id *raid, uint16_t cid)
+struct bssgp_bvc_ctx *btsctx_by_raid_cid(const struct gprs_ra_id *raid, uint16_t cid)
{
- struct bssgp_bts_ctx *bctx;
+ struct bssgp_bvc_ctx *bctx;
- llist_for_each_entry(bctx, &bts_ctxts, list) {
+ llist_for_each_entry(bctx, &bssgp_bvc_ctxts, list) {
if (!memcmp(&bctx->ra_id, raid, sizeof(bctx->ra_id)) &&
bctx->cell_id == cid)
return bctx;
@@ -75,27 +87,30 @@
}
/* Find a BTS context based on BVCI+NSEI tuple */
-struct bssgp_bts_ctx *btsctx_by_bvci_nsei(uint16_t bvci, uint16_t nsei)
+struct bssgp_bvc_ctx *btsctx_by_bvci_nsei(uint16_t bvci, uint16_t nsei)
{
- struct bssgp_bts_ctx *bctx;
+ struct bssgp_bvc_ctx *bctx;
- llist_for_each_entry(bctx, &bts_ctxts, list) {
+ llist_for_each_entry(bctx, &bssgp_bvc_ctxts, list) {
if (bctx->nsei == nsei && bctx->bvci == bvci)
return bctx;
}
return NULL;
}
-struct bssgp_bts_ctx *btsctx_alloc(uint16_t bvci, uint16_t nsei)
+struct bssgp_bvc_ctx *btsctx_alloc(uint16_t bvci, uint16_t nsei)
{
- struct bssgp_bts_ctx *ctx;
+ struct bssgp_bvc_ctx *ctx;
- ctx = talloc_zero(bssgp_tall_ctx, struct bssgp_bts_ctx);
+ ctx = talloc_zero(bssgp_tall_ctx, struct bssgp_bvc_ctx);
if (!ctx)
return NULL;
ctx->bvci = bvci;
ctx->nsei = nsei;
- llist_add(&ctx->list, &bts_ctxts);
+ /* FIXME: BVCI is not unique, only BVCI+NSEI ?!? */
+ ctx->ctrg = rate_ctr_group_alloc(ctx, &bssgp_ctrg_desc, bvci);
+
+ llist_add(&ctx->list, &bssgp_bvc_ctxts);
return ctx;
}
@@ -116,6 +131,96 @@
return gprs_ns_sendmsg(bssgp_nsi, msg);
}
+/* 10.3.7 SUSPEND-ACK PDU */
+int bssgp_tx_suspend_ack(uint16_t nsei, uint32_t tlli,
+ const struct gprs_ra_id *ra_id, uint8_t suspend_ref)
+{
+ struct msgb *msg = bssgp_msgb_alloc();
+ struct bssgp_normal_hdr *bgph =
+ (struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
+ uint32_t _tlli;
+ uint8_t ra[6];
+
+ msgb_nsei(msg) = nsei;
+ msgb_bvci(msg) = 0; /* Signalling */
+ bgph->pdu_type = BSSGP_PDUT_SUSPEND_ACK;
+
+ _tlli = htonl(tlli);
+ msgb_tvlv_put(msg, BSSGP_IE_TLLI, 4, (uint8_t *) &_tlli);
+ gsm48_construct_ra(ra, ra_id);
+ msgb_tvlv_put(msg, BSSGP_IE_ROUTEING_AREA, 6, ra);
+ msgb_tvlv_put(msg, BSSGP_IE_SUSPEND_REF_NR, 1, &suspend_ref);
+
+ return gprs_ns_sendmsg(bssgp_nsi, msg);
+}
+
+/* 10.3.8 SUSPEND-NACK PDU */
+int bssgp_tx_suspend_nack(uint16_t nsei, uint32_t tlli,
+ uint8_t *cause)
+{
+ struct msgb *msg = bssgp_msgb_alloc();
+ struct bssgp_normal_hdr *bgph =
+ (struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
+ uint32_t _tlli;
+
+ msgb_nsei(msg) = nsei;
+ msgb_bvci(msg) = 0; /* Signalling */
+ bgph->pdu_type = BSSGP_PDUT_SUSPEND_NACK;
+
+ _tlli = htonl(tlli);
+ msgb_tvlv_put(msg, BSSGP_IE_TLLI, 4, (uint8_t *) &_tlli);
+ if (cause)
+ msgb_tvlv_put(msg, BSSGP_IE_CAUSE, 1, cause);
+
+ return gprs_ns_sendmsg(bssgp_nsi, msg);
+}
+
+/* 10.3.10 RESUME-ACK PDU */
+int bssgp_tx_resume_ack(uint16_t nsei, uint32_t tlli,
+ const struct gprs_ra_id *ra_id)
+{
+ struct msgb *msg = bssgp_msgb_alloc();
+ struct bssgp_normal_hdr *bgph =
+ (struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
+ uint32_t _tlli;
+ uint8_t ra[6];
+
+ msgb_nsei(msg) = nsei;
+ msgb_bvci(msg) = 0; /* Signalling */
+ bgph->pdu_type = BSSGP_PDUT_RESUME_ACK;
+
+ _tlli = htonl(tlli);
+ msgb_tvlv_put(msg, BSSGP_IE_TLLI, 4, (uint8_t *) &_tlli);
+ gsm48_construct_ra(ra, ra_id);
+ msgb_tvlv_put(msg, BSSGP_IE_ROUTEING_AREA, 6, ra);
+
+ return gprs_ns_sendmsg(bssgp_nsi, msg);
+}
+
+/* 10.3.11 RESUME-NACK PDU */
+int bssgp_tx_resume_nack(uint16_t nsei, uint32_t tlli,
+ const struct gprs_ra_id *ra_id, uint8_t *cause)
+{
+ struct msgb *msg = bssgp_msgb_alloc();
+ struct bssgp_normal_hdr *bgph =
+ (struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
+ uint32_t _tlli;
+ uint8_t ra[6];
+
+ msgb_nsei(msg) = nsei;
+ msgb_bvci(msg) = 0; /* Signalling */
+ bgph->pdu_type = BSSGP_PDUT_SUSPEND_NACK;
+
+ _tlli = htonl(tlli);
+ msgb_tvlv_put(msg, BSSGP_IE_TLLI, 4, (uint8_t *) &_tlli);
+ gsm48_construct_ra(ra, ra_id);
+ msgb_tvlv_put(msg, BSSGP_IE_ROUTEING_AREA, 6, ra);
+ if (cause)
+ msgb_tvlv_put(msg, BSSGP_IE_CAUSE, 1, cause);
+
+ return gprs_ns_sendmsg(bssgp_nsi, msg);
+}
+
uint16_t bssgp_parse_cell_id(struct gprs_ra_id *raid, const uint8_t *buf)
{
/* 6 octets RAC */
@@ -128,13 +233,13 @@
static int bssgp_rx_bvc_reset(struct msgb *msg, struct tlv_parsed *tp,
uint16_t ns_bvci)
{
- struct bssgp_bts_ctx *bctx;
+ struct bssgp_bvc_ctx *bctx;
uint16_t nsei = msgb_nsei(msg);
uint16_t bvci;
int rc;
bvci = ntohs(*(uint16_t *)TLVP_VAL(tp, BSSGP_IE_BVCI));
- DEBUGPC(DBSSGP, "BVCI=%u, cause=%s\n", bvci,
+ DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx RESET cause=%s\n", bvci,
bssgp_cause_str(*TLVP_VAL(tp, BSSGP_IE_CAUSE)));
/* look-up or create the BTS context for this BVC */
@@ -142,11 +247,14 @@
if (!bctx)
bctx = btsctx_alloc(bvci, nsei);
+ /* As opposed to NS-VCs, BVCs are NOT blocked after RESET */
+ bctx->state &= ~BVC_S_BLOCKED;
+
/* When we receive a BVC-RESET PDU (at least of a PTP BVCI), the BSS
* informs us about its RAC + Cell ID, so we can create a mapping */
if (bvci != 0 && bvci != 1) {
if (!TLVP_PRESENT(tp, BSSGP_IE_CELL_ID)) {
- LOGP(DBSSGP, LOGL_ERROR, "BSSGP RESET BVCI=%u "
+ LOGP(DBSSGP, LOGL_ERROR, "BSSGP BVCI=%u RESET "
"missing mandatory IE\n", bvci);
return -EINVAL;
}
@@ -164,90 +272,200 @@
return 0;
}
+static int bssgp_rx_bvc_block(struct msgb *msg, struct tlv_parsed *tp)
+{
+ uint16_t bvci;
+ struct bssgp_bvc_ctx *ptp_ctx;
+
+ bvci = ntohs(*(uint16_t *)TLVP_VAL(tp, BSSGP_IE_BVCI));
+ if (bvci == BVCI_SIGNALLING) {
+ /* 8.3.2: Signalling BVC shall never be blocked */
+ LOGP(DBSSGP, LOGL_ERROR, "NSEI=%u/BVCI=%u "
+ "received block for signalling BVC!?!\n",
+ msgb_nsei(msg), msgb_bvci(msg));
+ return 0;
+ }
+
+ LOGP(DBSSGP, LOGL_INFO, "BSSGP BVCI=%u BVC-BLOCK\n", bvci);
+
+ ptp_ctx = btsctx_by_bvci_nsei(bvci, msgb_nsei(msg));
+ if (!ptp_ctx)
+ return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, &bvci, msg);
+
+ ptp_ctx->state |= BVC_S_BLOCKED;
+ rate_ctr_inc(&ptp_ctx->ctrg->ctr[BSSGP_CTR_BLOCKED]);
+
+ /* FIXME: Send NM_BVC_BLOCK.ind to NM */
+
+ /* We always acknowledge the BLOCKing */
+ return bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_BLOCK_ACK, msgb_nsei(msg),
+ bvci, msgb_bvci(msg));
+};
+
+static int bssgp_rx_bvc_unblock(struct msgb *msg, struct tlv_parsed *tp)
+{
+ uint16_t bvci;
+ struct bssgp_bvc_ctx *ptp_ctx;
+
+ bvci = ntohs(*(uint16_t *)TLVP_VAL(tp, BSSGP_IE_BVCI));
+ if (bvci == BVCI_SIGNALLING) {
+ /* 8.3.2: Signalling BVC shall never be blocked */
+ LOGP(DBSSGP, LOGL_ERROR, "NSEI=%u/BVCI=%u "
+ "received unblock for signalling BVC!?!\n",
+ msgb_nsei(msg), msgb_bvci(msg));
+ return 0;
+ }
+
+ DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx BVC-UNBLOCK\n", bvci);
+
+ ptp_ctx = btsctx_by_bvci_nsei(bvci, msgb_nsei(msg));
+ if (!ptp_ctx)
+ return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, &bvci, msg);
+
+ ptp_ctx->state &= ~BVC_S_BLOCKED;
+
+ /* FIXME: Send NM_BVC_UNBLOCK.ind to NM */
+
+ /* We always acknowledge the unBLOCKing */
+ return bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_UNBLOCK_ACK, msgb_nsei(msg),
+ bvci, msgb_bvci(msg));
+};
+
/* Uplink unit-data */
-static int bssgp_rx_ul_ud(struct msgb *msg)
+static int bssgp_rx_ul_ud(struct msgb *msg, struct tlv_parsed *tp,
+ struct bssgp_bvc_ctx *ctx)
{
struct bssgp_ud_hdr *budh = (struct bssgp_ud_hdr *) msgb_bssgph(msg);
- int data_len = msgb_bssgp_len(msg) - sizeof(*budh);
- struct tlv_parsed tp;
- int rc;
-
- DEBUGP(DBSSGP, "BSSGP UL-UD\n");
/* extract TLLI and parse TLV IEs */
msgb_tlli(msg) = ntohl(budh->tlli);
- rc = bssgp_tlv_parse(&tp, budh->data, data_len);
+
+ DEBUGP(DBSSGP, "BSSGP TLLI=0x%08x UPLINK-UNITDATA\n", msgb_tlli(msg));
/* Cell ID and LLC_PDU are the only mandatory IE */
- if (!TLVP_PRESENT(&tp, BSSGP_IE_CELL_ID) ||
- !TLVP_PRESENT(&tp, BSSGP_IE_LLC_PDU))
- return -EIO;
-
- /* FIXME: lookup bssgp_bts_ctx based on BVCI + NSEI */
+ if (!TLVP_PRESENT(tp, BSSGP_IE_CELL_ID) ||
+ !TLVP_PRESENT(tp, BSSGP_IE_LLC_PDU)) {
+ LOGP(DBSSGP, LOGL_ERROR, "BSSGP TLLI=0x%08x Rx UL-UD "
+ "missing mandatory IE\n", msgb_tlli(msg));
+ return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg);
+ }
/* store pointer to LLC header and CELL ID in msgb->cb */
- msgb_llch(msg) = TLVP_VAL(&tp, BSSGP_IE_LLC_PDU);
- msgb_bcid(msg) = TLVP_VAL(&tp, BSSGP_IE_CELL_ID);
+ msgb_llch(msg) = (uint8_t *) TLVP_VAL(tp, BSSGP_IE_LLC_PDU);
+ msgb_bcid(msg) = (uint8_t *) TLVP_VAL(tp, BSSGP_IE_CELL_ID);
- return gprs_llc_rcvmsg(msg, &tp);
+ return gprs_llc_rcvmsg(msg, tp);
}
-static int bssgp_rx_suspend(struct msgb *msg)
+static int bssgp_rx_suspend(struct msgb *msg, struct tlv_parsed *tp,
+ struct bssgp_bvc_ctx *ctx)
{
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_bssgph(msg);
- int data_len = msgb_bssgp_len(msg) - sizeof(*bgph);
- struct tlv_parsed tp;
+ struct gprs_ra_id raid;
+ uint32_t tlli;
int rc;
- DEBUGP(DBSSGP, "BSSGP SUSPEND\n");
+ if (!TLVP_PRESENT(tp, BSSGP_IE_TLLI) ||
+ !TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA)) {
+ LOGP(DBSSGP, LOGL_ERROR, "BSSGP BVCI=%u Rx SUSPEND "
+ "missing mandatory IE\n", ctx->bvci);
+ return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg);
+ }
- rc = bssgp_tlv_parse(&tp, bgph->data, data_len);
+ tlli = ntohl(*(uint32_t *)TLVP_VAL(tp, BSSGP_IE_TLLI));
+
+ DEBUGP(DBSSGP, "BSSGP BVCI=%u TLLI=0x%08x Rx SUSPEND\n",
+ ctx->bvci, tlli);
+
+ gsm48_parse_ra(&raid, TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA));
+
+ /* Inform GMM about the SUSPEND request */
+ rc = gprs_gmm_rx_suspend(&raid, tlli);
if (rc < 0)
- return rc;
+ return bssgp_tx_suspend_nack(msgb_nsei(msg), tlli, NULL);
- if (!TLVP_PRESENT(&tp, BSSGP_IE_TLLI) ||
- !TLVP_PRESENT(&tp, BSSGP_IE_ROUTEING_AREA))
- return -EIO;
+ bssgp_tx_suspend_ack(msgb_nsei(msg), tlli, &raid, 0);
- /* FIXME: pass the SUSPEND request to GMM */
- /* SEND SUSPEND_ACK or SUSPEND_NACK */
+ return 0;
}
-static int bssgp_rx_resume(struct msgb *msg)
+static int bssgp_rx_resume(struct msgb *msg, struct tlv_parsed *tp,
+ struct bssgp_bvc_ctx *ctx)
{
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_bssgph(msg);
- int data_len = msgb_bssgp_len(msg) - sizeof(*bgph);
- struct tlv_parsed tp;
+ struct gprs_ra_id raid;
+ uint32_t tlli;
+ uint8_t suspend_ref;
int rc;
- DEBUGP(DBSSGP, "BSSGP RESUME\n");
+ if (!TLVP_PRESENT(tp, BSSGP_IE_TLLI) ||
+ !TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA) ||
+ !TLVP_PRESENT(tp, BSSGP_IE_SUSPEND_REF_NR)) {
+ LOGP(DBSSGP, LOGL_ERROR, "BSSGP BVCI=%u Rx RESUME "
+ "missing mandatory IE\n", ctx->bvci);
+ return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg);
+ }
- rc = bssgp_tlv_parse(&tp, bgph->data, data_len);
+ tlli = ntohl(*(uint32_t *)TLVP_VAL(tp, BSSGP_IE_TLLI));
+ suspend_ref = *TLVP_VAL(tp, BSSGP_IE_SUSPEND_REF_NR);
+
+ DEBUGP(DBSSGP, "BSSGP BVCI=%u TLLI=0x%08x RESUME\n", ctx->bvci, tlli);
+
+ gsm48_parse_ra(&raid, TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA));
+
+ /* Inform GMM about the RESUME request */
+ rc = gprs_gmm_rx_resume(&raid, tlli, suspend_ref);
if (rc < 0)
- return rc;
+ return bssgp_tx_resume_nack(msgb_nsei(msg), tlli, &raid,
+ NULL);
- if (!TLVP_PRESENT(&tp, BSSGP_IE_TLLI) ||
- !TLVP_PRESENT(&tp, BSSGP_IE_ROUTEING_AREA) ||
- !TLVP_PRESENT(&tp, BSSGP_IE_SUSPEND_REF_NR))
- return -EIO;
-
- /* FIXME: pass the RESUME request to GMM */
- /* SEND RESUME_ACK or RESUME_NACK */
+ bssgp_tx_resume_ack(msgb_nsei(msg), tlli, &raid);
+ return 0;
}
-static int bssgp_rx_fc_bvc(struct msgb *msg, struct tlv_parsed *tp)
+
+static int bssgp_rx_llc_disc(struct msgb *msg, struct tlv_parsed *tp,
+ struct bssgp_bvc_ctx *ctx)
+{
+ uint32_t tlli;
+
+ if (!TLVP_PRESENT(tp, BSSGP_IE_TLLI) ||
+ !TLVP_PRESENT(tp, BSSGP_IE_LLC_FRAMES_DISCARDED) ||
+ !TLVP_PRESENT(tp, BSSGP_IE_BVCI) ||
+ !TLVP_PRESENT(tp, BSSGP_IE_NUM_OCT_AFF)) {
+ LOGP(DBSSGP, LOGL_ERROR, "BSSGP BVCI=%u Rx LLC DISCARDED "
+ "missing mandatory IE\n", ctx->bvci);
+ }
+
+ tlli = ntohl(*(uint32_t *)TLVP_VAL(tp, BSSGP_IE_TLLI));
+
+ DEBUGP(DBSSGP, "BSSGP BVCI=%u TLLI=%u LLC DISCARDED\n",
+ ctx->bvci, tlli);
+
+ rate_ctr_inc(&ctx->ctrg->ctr[BSSGP_CTR_DISCARDED]);
+
+ /* FIXME: send NM_LLC_DISCARDED to NM */
+ return 0;
+}
+
+static int bssgp_rx_fc_bvc(struct msgb *msg, struct tlv_parsed *tp,
+ struct bssgp_bvc_ctx *bctx)
{
- DEBUGP(DBSSGP, "BSSGP FC BVC\n");
+ DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx Flow Control BVC\n",
+ bctx->bvci);
if (!TLVP_PRESENT(tp, BSSGP_IE_TAG) ||
!TLVP_PRESENT(tp, BSSGP_IE_BVC_BUCKET_SIZE) ||
!TLVP_PRESENT(tp, BSSGP_IE_BUCKET_LEAK_RATE) ||
!TLVP_PRESENT(tp, BSSGP_IE_BMAX_DEFAULT_MS) ||
- !TLVP_PRESENT(tp, BSSGP_IE_R_DEFAULT_MS))
+ !TLVP_PRESENT(tp, BSSGP_IE_R_DEFAULT_MS)) {
+ LOGP(DBSSGP, LOGL_ERROR, "BSSGP BVCI=%u Rx FC BVC "
+ "missing mandatory IE\n", bctx->bvci);
return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg);
+ }
/* FIXME: actually implement flow control */
@@ -256,133 +474,168 @@
msgb_bvci(msg));
}
-/* We expect msgb_bssgph() to point to the BSSGP header */
-int gprs_bssgp_rcvmsg(struct msgb *msg)
+/* Receive a BSSGP PDU from a BSS on a PTP BVCI */
+static int gprs_bssgp_rx_ptp(struct msgb *msg, struct tlv_parsed *tp,
+ struct bssgp_bvc_ctx *bctx)
{
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_bssgph(msg);
- struct tlv_parsed tp;
uint8_t pdu_type = bgph->pdu_type;
- int data_len = msgb_bssgp_len(msg) - sizeof(*bgph);
- uint16_t bvci; /* PTP BVCI */
- uint16_t ns_bvci = msgb_bvci(msg);
int rc = 0;
- /* Identifiers from DOWN: NSEI, BVCI (both in msg->cb) */
-
- /* UNITDATA BSSGP headers have TLLI in front */
- if (pdu_type != BSSGP_PDUT_UL_UNITDATA &&
- pdu_type != BSSGP_PDUT_DL_UNITDATA)
- rc = bssgp_tlv_parse(&tp, bgph->data, data_len);
+ /* If traffic is received on a BVC that is marked as blocked, the
+ * received PDU shall not be accepted and a STATUS PDU (Cause value:
+ * BVC Blocked) shall be sent to the peer entity on the signalling BVC */
+ if (bctx->state & BVC_S_BLOCKED && pdu_type != BSSGP_PDUT_STATUS) {
+ uint16_t bvci = msgb_bvci(msg);
+ return bssgp_tx_status(BSSGP_CAUSE_BVCI_BLOCKED, &bvci, msg);
+ }
switch (pdu_type) {
case BSSGP_PDUT_UL_UNITDATA:
/* some LLC data from the MS */
- rc = bssgp_rx_ul_ud(msg);
+ rc = bssgp_rx_ul_ud(msg, tp, bctx);
break;
case BSSGP_PDUT_RA_CAPABILITY:
/* BSS requests RA capability or IMSI */
- DEBUGP(DBSSGP, "BSSGP RA CAPABILITY UPDATE\n");
+ DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx RA CAPABILITY UPDATE\n",
+ bctx->bvci);
+ /* FIXME: send GMM_RA_CAPABILITY_UPDATE.ind to GMM */
/* FIXME: send RA_CAPA_UPDATE_ACK */
break;
case BSSGP_PDUT_RADIO_STATUS:
- DEBUGP(DBSSGP, "BSSGP RADIO STATUS\n");
+ DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx RADIO STATUS\n", bctx->bvci);
/* BSS informs us of some exception */
- /* FIXME: notify GMM */
- break;
- case BSSGP_PDUT_SUSPEND:
- /* MS wants to suspend */
- rc = bssgp_rx_suspend(msg);
- break;
- case BSSGP_PDUT_RESUME:
- /* MS wants to resume */
- rc = bssgp_rx_resume(msg);
- break;
- case BSSGP_PDUT_FLUSH_LL:
- /* BSS informs MS has moved to one cell to other cell */
- DEBUGP(DBSSGP, "BSSGP FLUSH LL\n");
- /* FIXME: notify GMM */
- /* Send FLUSH_LL_ACK */
- break;
- case BSSGP_PDUT_LLC_DISCARD:
- /* BSS informs that some LLC PDU's have been discarded */
- DEBUGP(DBSSGP, "BSSGP LLC DISCARDED\n");
- /* FIXME: notify GMM */
+ /* FIXME: send GMM_RADIO_STATUS.ind to GMM */
break;
case BSSGP_PDUT_FLOW_CONTROL_BVC:
/* BSS informs us of available bandwidth in Gb interface */
- rc = bssgp_rx_fc_bvc(msg, &tp);
+ rc = bssgp_rx_fc_bvc(msg, tp, bctx);
break;
case BSSGP_PDUT_FLOW_CONTROL_MS:
/* BSS informs us of available bandwidth to one MS */
- DEBUGP(DBSSGP, "BSSGP FC MS\n");
+ DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx Flow Control MS\n",
+ bctx->bvci);
/* FIXME: actually implement flow control */
/* FIXME: Send FLOW_CONTROL_MS_ACK */
break;
- case BSSGP_PDUT_BVC_BLOCK:
- /* BSS tells us that BVC shall be blocked */
- DEBUGP(DBSSGP, "BSSGP BVC BLOCK ");
- if (!TLVP_PRESENT(&tp, BSSGP_IE_BVCI) ||
- !TLVP_PRESENT(&tp, BSSGP_IE_CAUSE))
- goto err_mand_ie;
- bvci = ntohs(*(uint16_t *)TLVP_VAL(&tp, BSSGP_IE_BVCI));
- DEBUGPC(DBSSGP, "BVCI=%u, cause=%s\n", bvci,
- bssgp_cause_str(*TLVP_VAL(&tp, BSSGP_IE_CAUSE)));
- /* We always acknowledge the BLOCKing */
- rc = bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_BLOCK_ACK,
- msgb_nsei(msg), bvci, ns_bvci);
- break;
- case BSSGP_PDUT_BVC_UNBLOCK:
- /* BSS tells us that BVC shall be unblocked */
- DEBUGP(DBSSGP, "BSSGP BVC UNBLOCK ");
- if (!TLVP_PRESENT(&tp, BSSGP_IE_BVCI))
- goto err_mand_ie;
- bvci = ntohs(*(uint16_t *)TLVP_VAL(&tp, BSSGP_IE_BVCI));
- DEBUGPC(DBSSGP, "BVCI=%u\n", bvci);
- /* We always acknowledge the unBLOCKing */
- rc = bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_UNBLOCK_ACK,
- msgb_nsei(msg), bvci, ns_bvci);
- break;
- case BSSGP_PDUT_BVC_RESET:
- /* BSS tells us that BVC init is required */
- DEBUGP(DBSSGP, "BSSGP BVC RESET ");
- if (!TLVP_PRESENT(&tp, BSSGP_IE_BVCI) ||
- !TLVP_PRESENT(&tp, BSSGP_IE_CAUSE))
- goto err_mand_ie;
- rc = bssgp_rx_bvc_reset(msg, &tp, ns_bvci);
- break;
case BSSGP_PDUT_STATUS:
/* Some exception has occurred */
- /* FIXME: notify GMM */
+ /* FIXME: send NM_STATUS.ind to NM */
case BSSGP_PDUT_DOWNLOAD_BSS_PFC:
case BSSGP_PDUT_CREATE_BSS_PFC_ACK:
case BSSGP_PDUT_CREATE_BSS_PFC_NACK:
case BSSGP_PDUT_MODIFY_BSS_PFC:
case BSSGP_PDUT_DELETE_BSS_PFC_ACK:
- DEBUGP(DBSSGP, "BSSGP PDU type 0x%02x not [yet] implemented\n",
- pdu_type);
+ DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx PDU type 0x%02x not [yet] "
+ "implemented\n", bctx->bvci, pdu_type);
+ rc = bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_FEAT, NULL, msg);
break;
/* those only exist in the SGSN -> BSS direction */
case BSSGP_PDUT_DL_UNITDATA:
case BSSGP_PDUT_PAGING_PS:
case BSSGP_PDUT_PAGING_CS:
case BSSGP_PDUT_RA_CAPA_UPDATE_ACK:
+ case BSSGP_PDUT_FLOW_CONTROL_BVC_ACK:
+ case BSSGP_PDUT_FLOW_CONTROL_MS_ACK:
+ DEBUGP(DBSSGP, "BSSGP BVCI=%u PDU type 0x%02x only exists "
+ "in DL\n", bctx->bvci, pdu_type);
+ bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg);
+ rc = -EINVAL;
+ break;
+ default:
+ DEBUGP(DBSSGP, "BSSGP BVCI=%u PDU type 0x%02x unknown\n",
+ bctx->bvci, pdu_type);
+ rc = bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg);
+ break;
+ }
+
+ return rc;
+}
+
+/* Receive a BSSGP PDU from a BSS on a SIGNALLING BVCI */
+static int gprs_bssgp_rx_sign(struct msgb *msg, struct tlv_parsed *tp,
+ struct bssgp_bvc_ctx *bctx)
+{
+ struct bssgp_normal_hdr *bgph =
+ (struct bssgp_normal_hdr *) msgb_bssgph(msg);
+ uint8_t pdu_type = bgph->pdu_type;
+ int rc = 0;
+ uint16_t ns_bvci = msgb_bvci(msg);
+ uint16_t bvci;
+
+ switch (bgph->pdu_type) {
+ case BSSGP_PDUT_SUSPEND:
+ /* MS wants to suspend */
+ rc = bssgp_rx_suspend(msg, tp, bctx);
+ break;
+ case BSSGP_PDUT_RESUME:
+ /* MS wants to resume */
+ rc = bssgp_rx_resume(msg, tp, bctx);
+ break;
+ case BSSGP_PDUT_FLUSH_LL_ACK:
+ /* BSS informs us it has performed LL FLUSH */
+ DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx FLUSH LL ACK\n", bctx->bvci);
+ /* FIXME: send NM_FLUSH_LL.res to NM */
+ break;
+ case BSSGP_PDUT_LLC_DISCARD:
+ /* BSS informs that some LLC PDU's have been discarded */
+ rc = bssgp_rx_llc_disc(msg, tp, bctx);
+ break;
+ case BSSGP_PDUT_BVC_BLOCK:
+ /* BSS tells us that BVC shall be blocked */
+ if (!TLVP_PRESENT(tp, BSSGP_IE_BVCI) ||
+ !TLVP_PRESENT(tp, BSSGP_IE_CAUSE)) {
+ LOGP(DBSSGP, LOGL_ERROR, "BSSGP Rx BVC-BLOCK "
+ "missing mandatory IE\n");
+ goto err_mand_ie;
+ }
+ rc = bssgp_rx_bvc_block(msg, tp);
+ break;
+ case BSSGP_PDUT_BVC_UNBLOCK:
+ /* BSS tells us that BVC shall be unblocked */
+ if (!TLVP_PRESENT(tp, BSSGP_IE_BVCI)) {
+ LOGP(DBSSGP, LOGL_ERROR, "BSSGP Rx BVC-UNBLOCK "
+ "missing mandatory IE\n");
+ goto err_mand_ie;
+ }
+ rc = bssgp_rx_bvc_unblock(msg, tp);
+ break;
+ case BSSGP_PDUT_BVC_RESET:
+ /* BSS tells us that BVC init is required */
+ if (!TLVP_PRESENT(tp, BSSGP_IE_BVCI) ||
+ !TLVP_PRESENT(tp, BSSGP_IE_CAUSE)) {
+ LOGP(DBSSGP, LOGL_ERROR, "BSSGP Rx BVC-RESET "
+ "missing mandatory IE\n");
+ goto err_mand_ie;
+ }
+ rc = bssgp_rx_bvc_reset(msg, tp, ns_bvci);
+ break;
+ case BSSGP_PDUT_STATUS:
+ /* Some exception has occurred */
+ DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx BVC STATUS\n", bctx->bvci);
+ /* FIXME: send NM_STATUS.ind to NM */
+ break;
+ /* those only exist in the SGSN -> BSS direction */
+ case BSSGP_PDUT_PAGING_PS:
+ case BSSGP_PDUT_PAGING_CS:
case BSSGP_PDUT_SUSPEND_ACK:
case BSSGP_PDUT_SUSPEND_NACK:
case BSSGP_PDUT_RESUME_ACK:
case BSSGP_PDUT_RESUME_NACK:
- case BSSGP_PDUT_FLUSH_LL_ACK:
- case BSSGP_PDUT_FLOW_CONTROL_BVC_ACK:
- case BSSGP_PDUT_FLOW_CONTROL_MS_ACK:
+ case BSSGP_PDUT_FLUSH_LL:
case BSSGP_PDUT_BVC_BLOCK_ACK:
case BSSGP_PDUT_BVC_UNBLOCK_ACK:
case BSSGP_PDUT_SGSN_INVOKE_TRACE:
- DEBUGP(DBSSGP, "BSSGP PDU type 0x%02x only exists in DL\n",
- pdu_type);
+ DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx PDU type 0x%02x only exists "
+ "in DL\n", bctx->bvci, pdu_type);
+ bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg);
rc = -EINVAL;
break;
default:
- DEBUGP(DBSSGP, "BSSGP PDU type 0x%02x unknown\n", pdu_type);
+ DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx PDU type 0x%02x unknown\n",
+ bctx->bvci, pdu_type);
+ rc = bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg);
break;
}
@@ -391,30 +644,85 @@
return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg);
}
+/* We expect msgb_bssgph() to point to the BSSGP header */
+int gprs_bssgp_rcvmsg(struct msgb *msg)
+{
+ struct bssgp_normal_hdr *bgph =
+ (struct bssgp_normal_hdr *) msgb_bssgph(msg);
+ struct bssgp_ud_hdr *budh = (struct bssgp_ud_hdr *) msgb_bssgph(msg);
+ struct tlv_parsed tp;
+ struct bssgp_bvc_ctx *bctx;
+ uint8_t pdu_type = bgph->pdu_type;
+ uint16_t ns_bvci = msgb_bvci(msg);
+ int data_len;
+ int rc = 0;
+
+ /* Identifiers from DOWN: NSEI, BVCI (both in msg->cb) */
+
+ /* UNITDATA BSSGP headers have TLLI in front */
+ if (pdu_type != BSSGP_PDUT_UL_UNITDATA &&
+ pdu_type != BSSGP_PDUT_DL_UNITDATA) {
+ data_len = msgb_bssgp_len(msg) - sizeof(*bgph);
+ rc = bssgp_tlv_parse(&tp, bgph->data, data_len);
+ } else {
+ data_len = msgb_bssgp_len(msg) - sizeof(*budh);
+ rc = bssgp_tlv_parse(&tp, budh->data, data_len);
+ }
+
+ /* look-up or create the BTS context for this BVC */
+ bctx = btsctx_by_bvci_nsei(ns_bvci, msgb_nsei(msg));
+ /* Only a RESET PDU can create a new BVC context */
+ if (!bctx && pdu_type != BSSGP_PDUT_BVC_RESET) {
+ LOGP(DBSSGP, LOGL_NOTICE, "NSEI=%u/BVCI=%u Rejecting PDU "
+ "type %u for unknown BVCI\n", msgb_nsei(msg), ns_bvci,
+ pdu_type);
+ return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg);
+ }
+
+ if (bctx) {
+ log_set_context(BSC_CTX_BVC, bctx);
+ rate_ctr_inc(&bctx->ctrg->ctr[BSSGP_CTR_PKTS_IN]);
+ rate_ctr_add(&bctx->ctrg->ctr[BSSGP_CTR_BYTES_IN],
+ msgb_bssgp_len(msg));
+ }
+
+ if (ns_bvci == BVCI_SIGNALLING)
+ rc = gprs_bssgp_rx_sign(msg, &tp, bctx);
+ else if (ns_bvci == BVCI_PTM)
+ rc = bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_FEAT, NULL, msg);
+ else
+ rc = gprs_bssgp_rx_ptp(msg, &tp, bctx);
+
+ return rc;
+}
+
/* Entry function from upper level (LLC), asking us to transmit a BSSGP PDU
* to a remote MS (identified by TLLI) at a BTS identified by its BVCI and NSEI */
-int gprs_bssgp_tx_dl_ud(struct msgb *msg)
+int gprs_bssgp_tx_dl_ud(struct msgb *msg, struct sgsn_mm_ctx *mmctx)
{
- struct bssgp_bts_ctx *bctx;
+ struct bssgp_bvc_ctx *bctx;
struct bssgp_ud_hdr *budh;
uint8_t llc_pdu_tlv_hdr_len = 2;
uint8_t *llc_pdu_tlv, *qos_profile;
uint16_t pdu_lifetime = 1000; /* centi-seconds */
- uint8_t qos_profile_default[3] = { 0x00, 0x00, 0x21 };
+ uint8_t qos_profile_default[3] = { 0x00, 0x00, 0x20 };
uint16_t msg_len = msg->len;
uint16_t bvci = msgb_bvci(msg);
uint16_t nsei = msgb_nsei(msg);
+ uint16_t drx_params;
/* Identifiers from UP: TLLI, BVCI, NSEI (all in msgb->cb) */
- if (bvci < 2) {
+ if (bvci <= BVCI_PTM ) {
LOGP(DBSSGP, LOGL_ERROR, "Cannot send DL-UD to BVCI %u\n",
bvci);
return -EINVAL;
}
bctx = btsctx_by_bvci_nsei(bvci, nsei);
- if (!bctx)
+ if (!bctx) {
+ /* FIXME: don't simply create missing context, but reject message */
bctx = btsctx_alloc(bvci, nsei);
+ }
if (msg->len > TVLV_MAX_ONEBYTE)
llc_pdu_tlv_hdr_len += 1;
@@ -426,11 +734,41 @@
llc_pdu_tlv[1] = msg_len >> 8;
llc_pdu_tlv[2] = msg_len & 0xff;
} else {
- llc_pdu_tlv[1] = msg_len & 0x3f;
+ llc_pdu_tlv[1] = msg_len & 0x7f;
llc_pdu_tlv[1] |= 0x80;
}
- /* FIXME: optional elements */
+ /* FIXME: optional elements: Alignment, UTRAN CCO, LSA, PFI */
+
+ if (mmctx) {
+ /* Old TLLI to help BSS map from old->new */
+#if 0
+ if (mmctx->tlli_old)
+ msgb_tvlv_push(msg, BSSGP_IE_TLLI, 4, htonl(*tlli_old));
+#endif
+
+ /* IMSI */
+ if (strlen(mmctx->imsi)) {
+ uint8_t mi[10];
+ int imsi_len = gsm48_generate_mid_from_imsi(mi, mmctx->imsi);
+ if (imsi_len > 2)
+ msgb_tvlv_push(msg, BSSGP_IE_IMSI,
+ imsi_len-2, mi+2);
+ }
+
+ /* DRX parameters */
+ drx_params = htons(mmctx->drx_parms);
+ msgb_tvlv_push(msg, BSSGP_IE_DRX_PARAMS, 2,
+ (uint8_t *) &drx_params);
+
+ /* FIXME: Priority */
+
+ /* MS Radio Access Capability */
+ if (mmctx->ms_radio_access_capa.len)
+ msgb_tvlv_push(msg, BSSGP_IE_MS_RADIO_ACCESS_CAP,
+ mmctx->ms_radio_access_capa.len,
+ mmctx->ms_radio_access_capa.buf);
+ }
/* prepend the pdu lifetime */
pdu_lifetime = htons(pdu_lifetime);
@@ -442,7 +780,73 @@
budh->tlli = htonl(msgb_tlli(msg));
budh->pdu_type = BSSGP_PDUT_DL_UNITDATA;
+ rate_ctr_inc(&bctx->ctrg->ctr[BSSGP_CTR_PKTS_OUT]);
+ rate_ctr_add(&bctx->ctrg->ctr[BSSGP_CTR_BYTES_OUT], msg->len);
+
/* Identifiers down: BVCI, NSEI (in msgb->cb) */
return gprs_ns_sendmsg(bssgp_nsi, msg);
}
+
+/* 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)
+{
+ struct msgb *msg = bssgp_msgb_alloc();
+ struct bssgp_normal_hdr *bgph =
+ (struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
+ uint16_t drx_params = htons(pinfo->drx_params);
+ uint8_t mi[10];
+ int imsi_len = gsm48_generate_mid_from_imsi(mi, pinfo->imsi);
+ uint8_t ra[6];
+
+ if (imsi_len < 2)
+ return -EINVAL;
+
+ msgb_nsei(msg) = nsei;
+ msgb_bvci(msg) = ns_bvci;
+
+ if (pinfo->mode == BSSGP_PAGING_PS)
+ bgph->pdu_type = BSSGP_PDUT_PAGING_PS;
+ else
+ bgph->pdu_type = BSSGP_PDUT_PAGING_CS;
+ /* IMSI */
+ msgb_tvlv_put(msg, BSSGP_IE_IMSI, imsi_len-2, mi+2);
+ /* DRX Parameters */
+ msgb_tvlv_put(msg, BSSGP_IE_DRX_PARAMS, 2,
+ (uint8_t *) &drx_params);
+ /* Scope */
+ switch (pinfo->scope) {
+ case BSSGP_PAGING_BSS_AREA:
+ {
+ uint8_t null = 0;
+ msgb_tvlv_put(msg, BSSGP_IE_BSS_AREA_ID, 1, &null);
+ }
+ break;
+ case BSSGP_PAGING_LOCATION_AREA:
+ gsm48_construct_ra(ra, &pinfo->raid);
+ msgb_tvlv_put(msg, BSSGP_IE_LOCATION_AREA, 4, ra);
+ break;
+ case BSSGP_PAGING_ROUTEING_AREA:
+ gsm48_construct_ra(ra, &pinfo->raid);
+ msgb_tvlv_put(msg, BSSGP_IE_ROUTEING_AREA, 6, ra);
+ break;
+ case BSSGP_PAGING_BVCI:
+ {
+ uint16_t bvci = htons(pinfo->bvci);
+ msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *)&bvci);
+ }
+ break;
+ }
+ /* QoS profile mandatory for PS */
+ if (pinfo->mode == BSSGP_PAGING_PS)
+ msgb_tvlv_put(msg, BSSGP_IE_QOS_PROFILE, 3, pinfo->qos);
+
+ /* Optional (P-)TMSI */
+ if (pinfo->ptmsi) {
+ uint32_t ptmsi = htonl(*pinfo->ptmsi);
+ msgb_tvlv_put(msg, BSSGP_IE_TMSI, 4, (uint8_t *) &ptmsi);
+ }
+
+ return gprs_ns_sendmsg(bssgp_nsi, msg);
+}
diff --git a/openbsc/src/gprs/gprs_bssgp_util.c b/openbsc/src/gprs/gprs_bssgp_util.c
index d9b5175..e760252 100644
--- a/openbsc/src/gprs/gprs_bssgp_util.c
+++ b/openbsc/src/gprs/gprs_bssgp_util.c
@@ -101,7 +101,8 @@
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
- DEBUGPC(DBSSGP, "BSSGP: TX STATUS, cause=%s\n", bssgp_cause_str(cause));
+ LOGP(DBSSGP, LOGL_NOTICE, "BSSGP BVCI=%u Tx STATUS, cause=%s\n",
+ bvci ? *bvci : 0, bssgp_cause_str(cause));
msgb_nsei(msg) = msgb_nsei(orig_msg);
msgb_bvci(msg) = 0;
diff --git a/openbsc/src/gprs/gprs_bssgp_vty.c b/openbsc/src/gprs/gprs_bssgp_vty.c
new file mode 100644
index 0000000..dc1f65c
--- /dev/null
+++ b/openbsc/src/gprs/gprs_bssgp_vty.c
@@ -0,0 +1,178 @@
+/* VTY interface for our GPRS BSS Gateway Protocol (BSSGP) implementation */
+
+/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <arpa/inet.h>
+
+#include <openbsc/gsm_data.h>
+#include <osmocore/msgb.h>
+#include <osmocore/tlv.h>
+#include <osmocore/talloc.h>
+#include <osmocore/select.h>
+#include <osmocore/rate_ctr.h>
+#include <openbsc/debug.h>
+#include <openbsc/signal.h>
+#include <openbsc/gprs_ns.h>
+#include <openbsc/gprs_bssgp.h>
+#include <openbsc/vty.h>
+
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/command.h>
+#include <osmocom/vty/logging.h>
+#include <osmocom/vty/telnet_interface.h>
+
+/* FIXME: this should go to some common file as it is copied
+ * in vty_interface.c of the BSC */
+static const struct value_string gprs_bssgp_timer_strs[] = {
+ { 0, NULL }
+};
+
+static struct cmd_node bssgp_node = {
+ BSSGP_NODE,
+ "%s(bssgp)#",
+ 1,
+};
+
+static int config_write_bssgp(struct vty *vty)
+{
+ vty_out(vty, "bssgp%s", VTY_NEWLINE);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bssgp, cfg_bssgp_cmd,
+ "bssgp",
+ "Configure the GPRS BSS Gateway Protocol")
+{
+ vty->node = BSSGP_NODE;
+ return CMD_SUCCESS;
+}
+
+static void dump_bvc(struct vty *vty, struct bssgp_bvc_ctx *bvc, int stats)
+{
+ vty_out(vty, "NSEI %5u, BVCI %5u, RA-ID: %u-%u-%u-%u, CID: %u, "
+ "STATE: %s%s", bvc->nsei, bvc->bvci, bvc->ra_id.mcc,
+ bvc->ra_id.mnc, bvc->ra_id.lac, bvc->ra_id.rac, bvc->cell_id,
+ bvc->state & BVC_S_BLOCKED ? "BLOCKED" : "UNBLOCKED",
+ VTY_NEWLINE);
+ if (stats)
+ vty_out_rate_ctr_group(vty, " ", bvc->ctrg);
+}
+
+static void dump_bssgp(struct vty *vty, int stats)
+{
+ struct bssgp_bvc_ctx *bvc;
+
+ llist_for_each_entry(bvc, &bssgp_bvc_ctxts, list) {
+ dump_bvc(vty, bvc, stats);
+ }
+}
+
+#define BSSGP_STR "Show information about the BSSGP protocol\n"
+
+DEFUN(show_bssgp, show_bssgp_cmd, "show bssgp",
+ SHOW_STR BSSGP_STR)
+{
+ dump_bssgp(vty, 0);
+ return CMD_SUCCESS;
+}
+
+DEFUN(show_bssgp_stats, show_bssgp_stats_cmd, "show bssgp stats",
+ SHOW_STR BSSGP_STR
+ "Include statistics\n")
+{
+ dump_bssgp(vty, 1);
+ return CMD_SUCCESS;
+}
+
+DEFUN(show_bvc, show_bvc_cmd, "show bssgp nsei <0-65535> [stats]",
+ SHOW_STR BSSGP_STR
+ "Show all BVCs on one NSE\n"
+ "The NSEI\n" "Include Statistics\n")
+{
+ struct bssgp_bvc_ctx *bvc;
+ uint16_t nsei = atoi(argv[1]);
+ int show_stats = 0;
+
+ if (argc >= 2)
+ show_stats = 1;
+
+ llist_for_each_entry(bvc, &bssgp_bvc_ctxts, list) {
+ if (bvc->nsei != nsei)
+ continue;
+ dump_bvc(vty, bvc, show_stats);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(logging_fltr_bvc,
+ logging_fltr_bvc_cmd,
+ "logging filter bvc nsei <0-65535> bvci <0-65535>",
+ LOGGING_STR FILTER_STR
+ "Filter based on BSSGP Virtual Connection\n"
+ "NSEI of the BVC to be filtered\n"
+ "Network Service Entity Identifier (NSEI)\n"
+ "BVCI of the BVC to be filtered\n"
+ "BSSGP Virtual Connection Identifier (BVCI)\n")
+{
+ struct telnet_connection *conn;
+ struct bssgp_bvc_ctx *bvc;
+ uint16_t nsei = atoi(argv[0]);
+ uint16_t bvci = atoi(argv[1]);
+
+ conn = (struct telnet_connection *) vty->priv;
+ if (!conn->dbg) {
+ vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ bvc = btsctx_by_bvci_nsei(bvci, nsei);
+ if (!bvc) {
+ vty_out(vty, "No BVC by that identifier%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ log_set_bvc_filter(conn->dbg, bvc);
+ return CMD_SUCCESS;
+}
+
+int gprs_bssgp_vty_init(void)
+{
+ install_element_ve(&show_bssgp_cmd);
+ install_element_ve(&show_bssgp_stats_cmd);
+ install_element_ve(&show_bvc_cmd);
+ install_element_ve(&logging_fltr_bvc_cmd);
+
+ install_element(CONFIG_NODE, &cfg_bssgp_cmd);
+ install_node(&bssgp_node, config_write_bssgp);
+ install_default(BSSGP_NODE);
+ install_element(BSSGP_NODE, &ournode_exit_cmd);
+ install_element(BSSGP_NODE, &ournode_end_cmd);
+ //install_element(BSSGP_NODE, &cfg_bssgp_timer_cmd);
+
+ return 0;
+}
diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
new file mode 100644
index 0000000..17d2ed0
--- /dev/null
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -0,0 +1,1320 @@
+/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
+ * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
+
+/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by On-Waves
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <openbsc/db.h>
+#include <osmocore/msgb.h>
+#include <osmocore/tlv.h>
+#include <osmocore/gsm_utils.h>
+#include <osmocore/signal.h>
+#include <osmocore/talloc.h>
+#include <osmocore/rate_ctr.h>
+
+#include <openbsc/debug.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/gsm_subscriber.h>
+#include <openbsc/gsm_04_08.h>
+#include <openbsc/gsm_04_08_gprs.h>
+#include <openbsc/paging.h>
+#include <openbsc/transaction.h>
+#include <openbsc/gprs_bssgp.h>
+#include <openbsc/gprs_llc.h>
+#include <openbsc/gprs_sgsn.h>
+#include <openbsc/gprs_gmm.h>
+#include <openbsc/sgsn.h>
+
+#include <pdp.h>
+
+#define PTMSI_ALLOC
+
+/* Section 11.2.2 / Table 11.4 MM timers netowkr side */
+#define GSM0408_T3322_SECS 6 /* DETACH_REQ -> DETACH_ACC */
+#define GSM0408_T3350_SECS 6 /* waiting for ATT/RAU/TMSI COMPL */
+#define GSM0408_T3360_SECS 6 /* waiting for AUTH/CIPH RESP */
+#define GSM0408_T3370_SECS 6 /* waiting for ID RESP */
+
+/* Section 11.2.2 / Table 11.4a MM timers netowkr side */
+#define GSM0408_T3313_SECS 30 /* waiting for paging response */
+#define GSM0408_T3314_SECS 44 /* force to STBY on expiry */
+#define GSM0408_T3316_SECS 44
+
+extern struct sgsn_instance *sgsn;
+
+/* Protocol related stuff, should go into libosmocore */
+
+/* 10.5.5.14 GPRS MM Cause / Table 10.5.147 */
+const struct value_string gmm_cause_names[] = {
+ /* FIXME */
+ { GMM_CAUSE_SEM_INCORR_MSG, "Semantically incorrect message" },
+ { GMM_CAUSE_INV_MAND_INFO, "Invalid mandatory information" },
+ { GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL,
+ "Message type non-existant or not implemented" },
+ { GMM_CAUSE_MSGT_INCOMP_P_STATE,
+ "Message type not compatible with protocol state" },
+ { GMM_CAUSE_IE_NOTEXIST_NOTIMPL,
+ "Information element non-existent or not implemented" },
+ { GMM_CAUSE_COND_IE_ERR, "Conditional IE error" },
+ { GMM_CAUSE_MSG_INCOMP_P_STATE,
+ "Message not compatible with protocol state " },
+ { GMM_CAUSE_PROTO_ERR_UNSPEC, "Protocol error, unspecified" },
+ { 0, NULL }
+};
+
+/* 10.5.6.6 SM Cause / Table 10.5.157 */
+const struct value_string gsm_cause_names[] = {
+ { GSM_CAUSE_INSUFF_RSRC, "Insufficient resources" },
+ { GSM_CAUSE_MISSING_APN, "Missing or unknown APN" },
+ { GSM_CAUSE_UNKNOWN_PDP, "Unknown PDP address or PDP type" },
+ { GSM_CAUSE_AUTH_FAILED, "User Authentication failed" },
+ { GSM_CAUSE_ACT_REJ_GGSN, "Activation rejected by GGSN" },
+ { GSM_CAUSE_ACT_REJ_UNSPEC, "Activation rejected, unspecified" },
+ { GSM_CAUSE_SERV_OPT_NOTSUPP, "Service option not supported" },
+ { GSM_CAUSE_REQ_SERV_OPT_NOTSUB,
+ "Requested service option not subscribed" },
+ { GSM_CAUSE_SERV_OPT_TEMP_OOO,
+ "Service option temporarily out of order" },
+ { GSM_CAUSE_NSAPI_IN_USE, "NSAPI already used" },
+ { GSM_CAUSE_DEACT_REGULAR, "Regular deactivation" },
+ { GSM_CAUSE_QOS_NOT_ACCEPTED, "QoS not accepted" },
+ { GSM_CAUSE_NET_FAIL, "Network Failure" },
+ { GSM_CAUSE_REACT_RQD, "Reactivation required" },
+ { GSM_CAUSE_FEATURE_NOTSUPP, "Feature not supported " },
+ { GSM_CAUSE_INVALID_TRANS_ID, "Invalid transaction identifier" },
+ { GSM_CAUSE_SEM_INCORR_MSG, "Semantically incorrect message" },
+ { GSM_CAUSE_INV_MAND_INFO, "Invalid mandatory information" },
+ { GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL,
+ "Message type non-existant or not implemented" },
+ { GSM_CAUSE_MSGT_INCOMP_P_STATE,
+ "Message type not compatible with protocol state" },
+ { GSM_CAUSE_IE_NOTEXIST_NOTIMPL,
+ "Information element non-existent or not implemented" },
+ { GSM_CAUSE_COND_IE_ERR, "Conditional IE error" },
+ { GSM_CAUSE_MSG_INCOMP_P_STATE,
+ "Message not compatible with protocol state " },
+ { GSM_CAUSE_PROTO_ERR_UNSPEC, "Protocol error, unspecified" },
+ { 0, NULL }
+};
+
+/* 10.5.5.2 */
+const struct value_string gprs_att_t_strs[] = {
+ { GPRS_ATT_T_ATTACH, "GPRS attach" },
+ { GPRS_ATT_T_ATT_WHILE_IMSI, "GPRS attach while IMSI attached" },
+ { GPRS_ATT_T_COMBINED, "Combined GPRS/IMSI attach" },
+ { 0, NULL }
+};
+
+const struct value_string gprs_upd_t_strs[] = {
+ { GPRS_UPD_T_RA, "RA updating" },
+ { GPRS_UPD_T_RA_LA, "combined RA/LA updating" },
+ { GPRS_UPD_T_RA_LA_IMSI_ATT, "combined RA/LA updating + IMSI attach" },
+ { GPRS_UPD_T_PERIODIC, "periodic updating" },
+ { 0, NULL }
+};
+
+/* 10.5.5.5 */
+const struct value_string gprs_det_t_mo_strs[] = {
+ { GPRS_DET_T_MO_GPRS, "GPRS detach" },
+ { GPRS_DET_T_MO_IMSI, "IMSI detach" },
+ { GPRS_DET_T_MO_COMBINED, "Combined GPRS/IMSI detach" },
+ { 0, NULL }
+};
+
+static const struct tlv_definition gsm48_gmm_att_tlvdef = {
+ .def = {
+ [GSM48_IE_GMM_TIMER_READY] = { TLV_TYPE_TV, 1 },
+ [GSM48_IE_GMM_ALLOC_PTMSI] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GMM_PTMSI_SIG] = { TLV_TYPE_TV, 3 },
+ [GSM48_IE_GMM_AUTH_RAND] = { TLV_TYPE_TV, 16 },
+ [GSM48_IE_GMM_AUTH_SRES] = { TLV_TYPE_TV, 4 },
+ [GSM48_IE_GMM_IMEISV] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GMM_DRX_PARAM] = { TLV_TYPE_TV, 2 },
+ [GSM48_IE_GMM_MS_NET_CAPA] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GMM_PDP_CTX_STATUS] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GMM_PS_LCS_CAPA] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GMM_GMM_MBMS_CTX_ST] = { TLV_TYPE_TLV, 0 },
+ },
+};
+
+static const struct tlv_definition gsm48_sm_att_tlvdef = {
+ .def = {
+ [GSM48_IE_GSM_APN] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GSM_PROTO_CONF_OPT] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GSM_PDP_ADDR] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GSM_AA_TMR] = { TLV_TYPE_TV, 1 },
+ [GSM48_IE_GSM_NAME_FULL] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GSM_NAME_SHORT] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GSM_TIMEZONE] = { TLV_TYPE_TV, 1 },
+ [GSM48_IE_GSM_UTC_AND_TZ] = { TLV_TYPE_TV, 7 },
+ [GSM48_IE_GSM_LSA_ID] = { TLV_TYPE_TLV, 0 },
+ },
+};
+
+/* Our implementation, should be kept in SGSN */
+
+static void mmctx_timer_cb(void *_mm);
+
+static void mmctx_timer_start(struct sgsn_mm_ctx *mm, unsigned int T,
+ unsigned int seconds)
+{
+ if (bsc_timer_pending(&mm->timer))
+ LOGP(DMM, LOGL_ERROR, "Starting MM timer %u while old "
+ "timer %u pending\n", T, mm->T);
+ mm->T = T;
+ mm->num_T_exp = 0;
+
+ /* FIXME: we should do this only once ? */
+ mm->timer.data = mm;
+ mm->timer.cb = &mmctx_timer_cb;
+
+ bsc_schedule_timer(&mm->timer, seconds, 0);
+}
+
+static void mmctx_timer_stop(struct sgsn_mm_ctx *mm, unsigned int T)
+{
+ if (mm->T != T)
+ LOGP(DMM, LOGL_ERROR, "Stopping MM timer %u but "
+ "%u is running\n", T, mm->T);
+ bsc_del_timer(&mm->timer);
+}
+
+/* Send a message through the underlying layer */
+static int gsm48_gmm_sendmsg(struct msgb *msg, int command,
+ const struct sgsn_mm_ctx *mm)
+{
+ if (mm)
+ rate_ctr_inc(&mm->ctrg->ctr[GMM_CTR_PKTS_SIG_OUT]);
+
+ /* caller needs to provide TLLI, BVCI and NSEI */
+ return gprs_llc_tx_ui(msg, GPRS_SAPI_GMM, command, mm);
+}
+
+/* copy identifiers from old message to new message, this
+ * is required so lower layers can route it correctly */
+static void gmm_copy_id(struct msgb *msg, const struct msgb *old)
+{
+ msgb_tlli(msg) = msgb_tlli(old);
+ msgb_bvci(msg) = msgb_bvci(old);
+ msgb_nsei(msg) = msgb_nsei(old);
+}
+
+/* Store BVCI/NSEI in MM context */
+static void msgid2mmctx(struct sgsn_mm_ctx *mm, const struct msgb *msg)
+{
+ mm->bvci = msgb_bvci(msg);
+ mm->nsei = msgb_nsei(msg);
+}
+
+/* Store BVCI/NSEI in MM context */
+static void mmctx2msgid(struct msgb *msg, const struct sgsn_mm_ctx *mm)
+{
+ msgb_tlli(msg) = mm->tlli;
+ msgb_bvci(msg) = mm->bvci;
+ msgb_nsei(msg) = mm->nsei;
+}
+
+/* Chapter 9.4.18 */
+static int _tx_status(struct msgb *msg, uint8_t cause,
+ struct sgsn_mm_ctx *mmctx, int sm)
+{
+ struct gsm48_hdr *gh;
+
+ /* MMCTX might be NULL! */
+
+ DEBUGP(DMM, "<- GPRS MM STATUS (cause: %s)\n",
+ get_value_string(gmm_cause_names, cause));
+
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
+ if (sm) {
+ gh->proto_discr = GSM48_PDISC_SM_GPRS;
+ gh->msg_type = GSM48_MT_GSM_STATUS;
+ } else {
+ gh->proto_discr = GSM48_PDISC_MM_GPRS;
+ gh->msg_type = GSM48_MT_GMM_STATUS;
+ }
+ gh->data[0] = cause;
+
+ return gsm48_gmm_sendmsg(msg, 0, mmctx);
+}
+static int gsm48_tx_gmm_status(struct sgsn_mm_ctx *mmctx, uint8_t cause)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+
+ mmctx2msgid(msg, mmctx);
+ return _tx_status(msg, cause, mmctx, 0);
+};
+static int gsm48_tx_gmm_status_oldmsg(struct msgb *oldmsg, uint8_t cause)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+
+ gmm_copy_id(msg, oldmsg);
+ return _tx_status(msg, cause, NULL, 0);
+}
+static int gsm48_tx_sm_status(struct sgsn_mm_ctx *mmctx, uint8_t cause)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+
+ mmctx2msgid(msg, mmctx);
+ return _tx_status(msg, cause, mmctx, 1);
+};
+static int gsm48_tx_sm_status_oldmsg(struct msgb *oldmsg, uint8_t cause)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+
+ gmm_copy_id(msg, oldmsg);
+ return _tx_status(msg, cause, NULL, 1);
+}
+
+
+static struct gsm48_qos default_qos = {
+ .delay_class = 4, /* best effort */
+ .reliab_class = GSM48_QOS_RC_LLC_UN_RLC_ACK_DATA_PROT,
+ .peak_tput = GSM48_QOS_PEAK_TPUT_32000bps,
+ .preced_class = GSM48_QOS_PC_NORMAL,
+ .mean_tput = GSM48_QOS_MEAN_TPUT_BEST_EFFORT,
+ .traf_class = GSM48_QOS_TC_INTERACTIVE,
+ .deliv_order = GSM48_QOS_DO_UNORDERED,
+ .deliv_err_sdu = GSM48_QOS_ERRSDU_YES,
+ .max_sdu_size = GSM48_QOS_MAXSDU_1520,
+ .max_bitrate_up = GSM48_QOS_MBRATE_63k,
+ .max_bitrate_down = GSM48_QOS_MBRATE_63k,
+ .resid_ber = GSM48_QOS_RBER_5e_2,
+ .sdu_err_ratio = GSM48_QOS_SERR_1e_2,
+ .handling_prio = 3,
+ .xfer_delay = 0x10, /* 200ms */
+ .guar_bitrate_up = GSM48_QOS_MBRATE_0k,
+ .guar_bitrate_down = GSM48_QOS_MBRATE_0k,
+ .sig_ind = 0, /* not optimised for signalling */
+ .max_bitrate_down_ext = 0, /* use octet 9 */
+ .guar_bitrate_down_ext = 0, /* use octet 13 */
+};
+
+/* Chapter 9.4.2: Attach accept */
+static int gsm48_tx_gmm_att_ack(struct sgsn_mm_ctx *mm)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+ struct gsm48_hdr *gh;
+ struct gsm48_attach_ack *aa;
+ uint8_t *ptsig, *mid;
+
+ DEBUGP(DMM, "<- GPRS ATTACH ACCEPT (new P-TMSI=0x%08x)\n", mm->p_tmsi);
+
+ mmctx2msgid(msg, mm);
+
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+ gh->proto_discr = GSM48_PDISC_MM_GPRS;
+ gh->msg_type = GSM48_MT_GMM_ATTACH_ACK;
+
+ aa = (struct gsm48_attach_ack *) msgb_put(msg, sizeof(*aa));
+ aa->force_stby = 0; /* not indicated */
+ aa->att_result = 1; /* GPRS only */
+ aa->ra_upd_timer = GPRS_TMR_MINUTE | 10;
+ aa->radio_prio = 4; /* lowest */
+ gsm48_construct_ra(aa->ra_id.digits, &mm->ra);
+
+#if 0
+ /* Optional: P-TMSI signature */
+ msgb_v_put(msg, GSM48_IE_GMM_PTMSI_SIG);
+ ptsig = msgb_put(msg, 3);
+ ptsig[0] = mm->p_tmsi_sig >> 16;
+ ptsig[1] = mm->p_tmsi_sig >> 8;
+ ptsig[2] = mm->p_tmsi_sig & 0xff;
+
+ /* Optional: Negotiated Ready timer value */
+#endif
+
+#ifdef PTMSI_ALLOC
+ /* Optional: Allocated P-TMSI */
+ mid = msgb_put(msg, GSM48_MID_TMSI_LEN);
+ gsm48_generate_mid_from_tmsi(mid, mm->p_tmsi);
+ mid[0] = GSM48_IE_GMM_ALLOC_PTMSI;
+#endif
+
+ /* Optional: MS-identity (combined attach) */
+ /* Optional: GMM cause (partial attach result for combined attach) */
+
+ return gsm48_gmm_sendmsg(msg, 0, mm);
+}
+
+/* Chapter 9.4.5: Attach reject */
+static int _tx_gmm_att_rej(struct msgb *msg, uint8_t gmm_cause)
+{
+ struct gsm48_hdr *gh;
+
+ DEBUGP(DMM, "<- GPRS ATTACH REJECT\n");
+
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
+ gh->proto_discr = GSM48_PDISC_MM_GPRS;
+ gh->msg_type = GSM48_MT_GMM_ATTACH_REJ;
+ gh->data[0] = gmm_cause;
+
+ return gsm48_gmm_sendmsg(msg, 0, NULL);
+}
+static int gsm48_tx_gmm_att_rej_oldmsg(const struct msgb *old_msg,
+ uint8_t gmm_cause)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+ gmm_copy_id(msg, old_msg);
+ return _tx_gmm_att_rej(msg, gmm_cause);
+}
+static int gsm48_tx_gmm_att_rej(struct sgsn_mm_ctx *mm,
+ uint8_t gmm_cause)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+ mmctx2msgid(msg, mm);
+ return _tx_gmm_att_rej(msg, gmm_cause);
+}
+
+/* Chapter 9.4.6.2 Detach accept */
+static int gsm48_tx_gmm_det_ack(struct sgsn_mm_ctx *mm, uint8_t force_stby)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+ struct gsm48_hdr *gh;
+
+ DEBUGP(DMM, "<- GPRS DETACH ACCEPT\n");
+
+ mmctx2msgid(msg, mm);
+
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
+ gh->proto_discr = GSM48_PDISC_MM_GPRS;
+ gh->msg_type = GSM48_MT_GMM_DETACH_ACK;
+ gh->data[0] = force_stby;
+
+ return gsm48_gmm_sendmsg(msg, 0, mm);
+}
+
+/* Transmit Chapter 9.4.12 Identity Request */
+static int gsm48_tx_gmm_id_req(struct sgsn_mm_ctx *mm, uint8_t id_type)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+ struct gsm48_hdr *gh;
+
+ DEBUGP(DMM, "<- GPRS IDENTITY REQUEST: mi_type=%02x\n", id_type);
+
+ mmctx2msgid(msg, mm);
+
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
+ gh->proto_discr = GSM48_PDISC_MM_GPRS;
+ gh->msg_type = GSM48_MT_GMM_ID_REQ;
+ /* 10.5.5.9 ID type 2 + identity type and 10.5.5.7 'force to standby' IE */
+ gh->data[0] = id_type & 0xf;
+
+ return gsm48_gmm_sendmsg(msg, 1, mm);
+}
+
+/* Check if we can already authorize a subscriber */
+static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx,
+ enum gprs_t3350_mode t3350_mode)
+{
+ if (strlen(ctx->imei) && strlen(ctx->imsi)) {
+#ifdef PTMSI_ALLOC
+ /* Start T3350 and re-transmit up to 5 times until ATTACH COMPLETE */
+ ctx->t3350_mode = t3350_mode;
+ mmctx_timer_start(ctx, 3350, GSM0408_T3350_SECS);
+#endif
+ ctx->mm_state = GMM_REGISTERED_NORMAL;
+ return gsm48_tx_gmm_att_ack(ctx);
+ }
+ if (!strlen(ctx->imei)) {
+ ctx->mm_state = GMM_COMMON_PROC_INIT;
+ ctx->t3370_id_type = GSM_MI_TYPE_IMEI;
+ mmctx_timer_start(ctx, 3370, GSM0408_T3370_SECS);
+ return gsm48_tx_gmm_id_req(ctx, GSM_MI_TYPE_IMEI);
+ }
+
+ if (!strlen(ctx->imsi)) {
+ ctx->mm_state = GMM_COMMON_PROC_INIT;
+ ctx->t3370_id_type = GSM_MI_TYPE_IMSI;
+ mmctx_timer_start(ctx, 3370, GSM0408_T3370_SECS);
+ return gsm48_tx_gmm_id_req(ctx, GSM_MI_TYPE_IMSI);
+ }
+
+ return 0;
+}
+
+/* Parse Chapter 9.4.13 Identity Response */
+static int gsm48_rx_gmm_id_resp(struct sgsn_mm_ctx *ctx, struct msgb *msg)
+{
+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
+ uint8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
+ char mi_string[GSM48_MI_SIZE];
+
+ gsm48_mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
+ DEBUGP(DMM, "-> GMM IDENTITY RESPONSE: mi_type=0x%02x MI(%s) ",
+ mi_type, mi_string);
+
+ if (!ctx) {
+ DEBUGP(DMM, "from unknown TLLI 0x%08x?!?\n", msgb_tlli(msg));
+ return -EINVAL;
+ }
+
+ if (mi_type == ctx->t3370_id_type)
+ mmctx_timer_stop(ctx, 3370);
+
+ switch (mi_type) {
+ case GSM_MI_TYPE_IMSI:
+ /* we already have a mm context with current TLLI, but no
+ * P-TMSI / IMSI yet. What we now need to do is to fill
+ * this initial context with data from the HLR */
+ strncpy(ctx->imsi, mi_string, sizeof(ctx->imei));
+ break;
+ case GSM_MI_TYPE_IMEI:
+ strncpy(ctx->imei, mi_string, sizeof(ctx->imei));
+ break;
+ case GSM_MI_TYPE_IMEISV:
+ break;
+ }
+
+ DEBUGPC(DMM, "\n");
+ /* Check if we can let the mobile station enter */
+ return gsm48_gmm_authorize(ctx, ctx->t3350_mode);
+}
+
+/* Section 9.4.1 Attach request */
+static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
+ struct gprs_llc_llme *llme)
+{
+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
+ uint8_t *cur = gh->data, *msnc, *mi, *old_ra_info, *ms_ra_acc_cap;
+ uint8_t msnc_len, att_type, mi_len, mi_type, ms_ra_acc_cap_len;
+ uint16_t drx_par;
+ uint32_t tmsi;
+ char mi_string[GSM48_MI_SIZE];
+ struct gprs_ra_id ra_id;
+ uint16_t cid;
+
+ DEBUGP(DMM, "-> GMM ATTACH REQUEST ");
+
+ /* As per TS 04.08 Chapter 4.7.1.4, the attach request arrives either
+ * with a foreign TLLI (P-TMSI that was allocated to the MS before),
+ * or with random TLLI. */
+
+ cid = bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
+
+ /* MS network capability 10.5.5.12 */
+ msnc_len = *cur++;
+ msnc = cur;
+ if (msnc_len > 2)
+ goto err_inval;
+ cur += msnc_len;
+
+ /* aTTACH Type 10.5.5.2 */
+ att_type = *cur++ & 0x0f;
+
+ /* DRX parameter 10.5.5.6 */
+ drx_par = *cur++ << 8;
+ drx_par |= *cur++;
+
+ /* Mobile Identity (P-TMSI or IMSI) 10.5.1.4 */
+ mi_len = *cur++;
+ mi = cur;
+ if (mi_len > 8)
+ goto err_inval;
+ mi_type = *mi & GSM_MI_TYPE_MASK;
+ cur += mi_len;
+
+ gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
+
+ DEBUGPC(DMM, "MI(%s) type=\"%s\" ", mi_string,
+ get_value_string(gprs_att_t_strs, att_type));
+
+ /* Old routing area identification 10.5.5.15 */
+ old_ra_info = cur;
+ cur += 6;
+
+ /* MS Radio Access Capability 10.5.5.12a */
+ ms_ra_acc_cap_len = *cur++;
+ ms_ra_acc_cap = cur;
+
+ /* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status */
+
+ switch (mi_type) {
+ case GSM_MI_TYPE_IMSI:
+ /* Try to find MM context based on IMSI */
+ if (!ctx)
+ ctx = sgsn_mm_ctx_by_imsi(mi_string);
+ if (!ctx) {
+#if 0
+ return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_IMSI_UNKNOWN);
+#else
+ /* As a temorary hack, we simply assume that the IMSI exists */
+ ctx = sgsn_mm_ctx_alloc(0, &ra_id);
+ if (!ctx)
+ return gsm48_tx_gmm_att_rej_oldmsg(msg, GMM_CAUSE_NET_FAIL);
+ strncpy(ctx->imsi, mi_string, sizeof(ctx->imsi));
+#endif
+ }
+ ctx->tlli = msgb_tlli(msg);
+ ctx->llme = llme;
+ msgid2mmctx(ctx, msg);
+ break;
+ case GSM_MI_TYPE_TMSI:
+ memcpy(&tmsi, mi+1, 4);
+ tmsi = ntohl(tmsi);
+ /* Try to find MM context based on P-TMSI */
+ if (!ctx)
+ ctx = sgsn_mm_ctx_by_ptmsi(tmsi);
+ if (!ctx) {
+ ctx = sgsn_mm_ctx_alloc(msgb_tlli(msg), &ra_id);
+ ctx->p_tmsi = tmsi;
+ }
+ ctx->tlli = msgb_tlli(msg);
+ ctx->llme = llme;
+ msgid2mmctx(ctx, msg);
+ break;
+ default:
+ LOGP(DMM, LOGL_NOTICE, "Rejecting ATTACH REQUEST with "
+ "MI type %u\n", mi_type);
+ return gsm48_tx_gmm_att_rej_oldmsg(msg, GMM_CAUSE_MS_ID_NOT_DERIVED);
+ }
+ /* Update MM Context with currient RA and Cell ID */
+ ctx->ra = ra_id;
+ ctx->cell_id = cid;
+ /* Update MM Context with other data */
+ ctx->drx_parms = drx_par;
+ ctx->ms_radio_access_capa.len = ms_ra_acc_cap_len;
+ memcpy(ctx->ms_radio_access_capa.buf, ms_ra_acc_cap, ms_ra_acc_cap_len);
+ ctx->ms_network_capa.len = msnc_len;
+ memcpy(ctx->ms_network_capa.buf, msnc, msnc_len);
+
+#ifdef PTMSI_ALLOC
+ /* Allocate a new P-TMSI (+ P-TMSI signature) and update TLLI */
+ ctx->p_tmsi_old = ctx->p_tmsi;
+ ctx->p_tmsi = sgsn_alloc_ptmsi();
+#endif
+ /* Even if there is no P-TMSI allocated, the MS will switch from
+ * foreign TLLI to local TLLI */
+ ctx->tlli_new = gprs_tmsi2tlli(ctx->p_tmsi, TLLI_LOCAL);
+
+ /* Inform LLC layer about new TLLI but keep old active */
+ gprs_llgmm_assign(ctx->llme, ctx->tlli, ctx->tlli_new, 0, NULL);
+
+ DEBUGPC(DMM, "\n");
+ return ctx ? gsm48_gmm_authorize(ctx, GMM_T3350_MODE_ATT) : 0;
+
+err_inval:
+ DEBUGPC(DMM, "\n");
+ return gsm48_tx_gmm_att_rej_oldmsg(msg, GMM_CAUSE_SEM_INCORR_MSG);
+}
+
+/* Section 4.7.4.1 / 9.4.5.2 MO Detach request */
+static int gsm48_rx_gmm_det_req(struct sgsn_mm_ctx *ctx, struct msgb *msg)
+{
+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
+ uint8_t detach_type, power_off;
+
+ detach_type = gh->data[0] & 0x7;
+ power_off = gh->data[0] & 0x8;
+
+ /* FIXME: In 24.008 there is an optional P-TMSI and P-TMSI signature IE */
+
+ DEBUGP(DMM, "-> GMM DETACH REQUEST TLLI=0x%08x type=%s %s\n",
+ msgb_tlli(msg), get_value_string(gprs_det_t_mo_strs, detach_type),
+ power_off ? "Power-off" : "");
+
+ /* Mark MM state as deregistered */
+ ctx->mm_state = GMM_DEREGISTERED;
+
+ /* force_stby = 0 */
+ return gsm48_tx_gmm_det_ack(ctx, 0);
+}
+
+/* Chapter 9.4.15: Routing area update accept */
+static int gsm48_tx_gmm_ra_upd_ack(struct sgsn_mm_ctx *mm)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+ struct gsm48_hdr *gh;
+ struct gsm48_ra_upd_ack *rua;
+ uint8_t *mid;
+
+ DEBUGP(DMM, "<- ROUTING AREA UPDATE ACCEPT\n");
+
+ mmctx2msgid(msg, mm);
+
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+ gh->proto_discr = GSM48_PDISC_MM_GPRS;
+ gh->msg_type = GSM48_MT_GMM_RA_UPD_ACK;
+
+ rua = (struct gsm48_ra_upd_ack *) msgb_put(msg, sizeof(*rua));
+ rua->force_stby = 0; /* not indicated */
+ rua->upd_result = 0; /* RA updated */
+ rua->ra_upd_timer = GPRS_TMR_MINUTE | 10;
+
+ gsm48_construct_ra(rua->ra_id.digits, &mm->ra);
+
+#if 0
+ /* Optional: P-TMSI signature */
+ msgb_v_put(msg, GSM48_IE_GMM_PTMSI_SIG);
+ ptsig = msgb_put(msg, 3);
+ ptsig[0] = mm->p_tmsi_sig >> 16;
+ ptsig[1] = mm->p_tmsi_sig >> 8;
+ ptsig[2] = mm->p_tmsi_sig & 0xff;
+#endif
+
+#ifdef PTMSI_ALLOC
+ /* Optional: Allocated P-TMSI */
+ mid = msgb_put(msg, GSM48_MID_TMSI_LEN);
+ gsm48_generate_mid_from_tmsi(mid, mm->p_tmsi);
+ mid[0] = GSM48_IE_GMM_ALLOC_PTMSI;
+#endif
+
+ /* Option: MS ID, ... */
+ return gsm48_gmm_sendmsg(msg, 0, mm);
+}
+
+/* Chapter 9.4.17: Routing area update reject */
+static int gsm48_tx_gmm_ra_upd_rej(struct msgb *old_msg, uint8_t cause)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+ struct gsm48_hdr *gh;
+
+ DEBUGP(DMM, "<- ROUTING AREA UPDATE REJECT\n");
+
+ gmm_copy_id(msg, old_msg);
+
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 2);
+ gh->proto_discr = GSM48_PDISC_MM_GPRS;
+ gh->msg_type = GSM48_MT_GMM_RA_UPD_REJ;
+ gh->data[0] = cause;
+ gh->data[1] = 0; /* ? */
+
+ /* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
+ return gsm48_gmm_sendmsg(msg, 0, NULL);
+}
+
+static void process_ms_ctx_status(struct sgsn_mm_ctx *mmctx,
+ uint16_t pdp_status)
+{
+ struct sgsn_pdp_ctx *pdp, *pdp2;
+ /* 24.008 4.7.5.1.3: If the PDP context status information element is
+ * included in ROUTING AREA UPDATE REQUEST message, then the network
+ * shall deactivate all those PDP contexts locally (without peer to
+ * peer signalling between the MS and the network), which are not in SM
+ * state PDP-INACTIVE on network side but are indicated by the MS as
+ * being in state PDP-INACTIVE. */
+
+ llist_for_each_entry_safe(pdp, pdp2, &mmctx->pdp_list, list) {
+ if (!(pdp_status & (1 << pdp->nsapi))) {
+ LOGP(DMM, LOGL_NOTICE, "Dropping PDP context for NSAPI=%u "
+ "due to PDP CTX STATUS IE= 0x%04x\n",
+ pdp->nsapi, pdp_status);
+ sgsn_delete_pdp_ctx(pdp);
+ }
+ }
+}
+
+/* Chapter 9.4.14: Routing area update request */
+static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
+ struct gprs_llc_llme *llme)
+{
+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
+ uint8_t *cur = gh->data;
+ uint8_t *ms_ra_acc_cap;
+ uint8_t ms_ra_acc_cap_len;
+ struct gprs_ra_id old_ra_id;
+ struct tlv_parsed tp;
+ uint8_t upd_type;
+ int rc;
+
+ /* Update Type 10.5.5.18 */
+ upd_type = *cur++ & 0x0f;
+
+ DEBUGP(DMM, "-> GMM RA UPDATE REQUEST type=\"%s\" ",
+ get_value_string(gprs_upd_t_strs, upd_type));
+
+ /* Old routing area identification 10.5.5.15 */
+ gsm48_parse_ra(&old_ra_id, cur);
+ cur += 6;
+
+ /* MS Radio Access Capability 10.5.5.12a */
+ ms_ra_acc_cap_len = *cur++;
+ ms_ra_acc_cap = cur;
+
+ /* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status,
+ * DRX parameter, MS network capability */
+ rc = tlv_parse(&tp, &gsm48_gmm_att_tlvdef, cur,
+ (msg->data + msg->len) - cur, 0, 0);
+
+ switch (upd_type) {
+ case GPRS_UPD_T_RA_LA:
+ case GPRS_UPD_T_RA_LA_IMSI_ATT:
+ DEBUGPC(DMM, " unsupported in Mode III, is your SI13 corrupt?\n");
+ return gsm48_tx_gmm_ra_upd_rej(msg, GMM_CAUSE_PROTO_ERR_UNSPEC);
+ break;
+ case GPRS_UPD_T_RA:
+ case GPRS_UPD_T_PERIODIC:
+ break;
+ }
+
+ /* Look-up the MM context based on old RA-ID and TLLI */
+ if (!mmctx || mmctx->mm_state == GMM_DEREGISTERED) {
+ /* The MS has to perform GPRS attach */
+ DEBUGPC(DMM, " REJECT\n");
+ /* Device is still IMSI atached for CS but initiate GPRS ATTACH */
+ return gsm48_tx_gmm_ra_upd_rej(msg, GMM_CAUSE_MS_ID_NOT_DERIVED);
+ }
+
+ /* Update the MM context with the new RA-ID */
+ bssgp_parse_cell_id(&mmctx->ra, msgb_bcid(msg));
+ /* Update the MM context with the new TLLI */
+ mmctx->tlli = msgb_tlli(msg);
+ /* FIXME: Update the MM context with the MS radio acc capabilities */
+ /* FIXME: Update the MM context with the MS network capabilities */
+
+ rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_RA_UPDATE]);
+
+ DEBUGPC(DMM, " ACCEPT\n");
+#ifdef PTMSI_ALLOC
+ mmctx->p_tmsi_old = mmctx->p_tmsi;
+ mmctx->p_tmsi = sgsn_alloc_ptmsi();
+ /* Start T3350 and re-transmit up to 5 times until ATTACH COMPLETE */
+ mmctx->t3350_mode = GMM_T3350_MODE_RAU;
+ mmctx_timer_start(mmctx, 3350, GSM0408_T3350_SECS);
+#endif
+ /* Even if there is no P-TMSI allocated, the MS will switch from
+ * foreign TLLI to local TLLI */
+ mmctx->tlli_new = gprs_tmsi2tlli(mmctx->p_tmsi, TLLI_LOCAL);
+
+ /* Inform LLC layer about new TLLI but keep old active */
+ gprs_llgmm_assign(mmctx->llme, mmctx->tlli, mmctx->tlli_new, 0, NULL);
+
+ /* Look at PDP Context Status IE and see if MS's view of
+ * activated/deactivated NSAPIs agrees with our view */
+ if (TLVP_PRESENT(&tp, GSM48_IE_GMM_PDP_CTX_STATUS)) {
+ uint16_t pdp_status = ntohs(*(uint16_t *)
+ TLVP_VAL(&tp, GSM48_IE_GMM_PDP_CTX_STATUS));
+ process_ms_ctx_status(mmctx, pdp_status);
+ }
+
+ /* Send RA UPDATE ACCEPT */
+ return gsm48_tx_gmm_ra_upd_ack(mmctx);
+}
+
+static int gsm48_rx_gmm_status(struct sgsn_mm_ctx *mmctx, struct msgb *msg)
+{
+ struct gsm48_hdr *gh = msgb_l3(msg);
+
+ DEBUGP(DMM, "-> GPRS MM STATUS (cause: %s)\n",
+ get_value_string(gmm_cause_names, gh->data[0]));
+
+ return 0;
+}
+
+/* GPRS Mobility Management */
+static int gsm0408_rcv_gmm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
+ struct gprs_llc_llme *llme)
+{
+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
+ int rc;
+
+ /* MMCTX can be NULL when called */
+
+ if (!mmctx &&
+ gh->msg_type != GSM48_MT_GMM_ATTACH_REQ &&
+ gh->msg_type != GSM48_MT_GMM_RA_UPD_REQ) {
+ LOGP(DMM, LOGL_NOTICE, "Cannot handle GMM for unknown MM CTX\n");
+ return gsm48_tx_gmm_status_oldmsg(msg, GMM_CAUSE_MS_ID_NOT_DERIVED);
+ }
+
+ switch (gh->msg_type) {
+ case GSM48_MT_GMM_RA_UPD_REQ:
+ rc = gsm48_rx_gmm_ra_upd_req(mmctx, msg, llme);
+ break;
+ case GSM48_MT_GMM_ATTACH_REQ:
+ rc = gsm48_rx_gmm_att_req(mmctx, msg, llme);
+ break;
+ case GSM48_MT_GMM_ID_RESP:
+ rc = gsm48_rx_gmm_id_resp(mmctx, msg);
+ break;
+ case GSM48_MT_GMM_STATUS:
+ rc = gsm48_rx_gmm_status(mmctx, msg);
+ break;
+ case GSM48_MT_GMM_DETACH_REQ:
+ rc = gsm48_rx_gmm_det_req(mmctx, msg);
+ break;
+ case GSM48_MT_GMM_ATTACH_COMPL:
+ /* only in case SGSN offered new P-TMSI */
+ DEBUGP(DMM, "-> ATTACH COMPLETE\n");
+ mmctx_timer_stop(mmctx, 3350);
+ mmctx->p_tmsi_old = 0;
+ /* Unassign the old TLLI */
+ mmctx->tlli = mmctx->tlli_new;
+ //gprs_llgmm_assign(mmctx->llme, 0xffffffff, mmctx->tlli_new, 0, NULL);
+ break;
+ case GSM48_MT_GMM_RA_UPD_COMPL:
+ /* only in case SGSN offered new P-TMSI */
+ DEBUGP(DMM, "-> ROUTEING AREA UPDATE COMPLETE\n");
+ mmctx_timer_stop(mmctx, 3350);
+ mmctx->p_tmsi_old = 0;
+ /* Unassign the old TLLI */
+ mmctx->tlli = mmctx->tlli_new;
+ //gprs_llgmm_assign(mmctx->llme, 0xffffffff, mmctx->tlli_new, 0, NULL);
+ break;
+ case GSM48_MT_GMM_PTMSI_REALL_COMPL:
+ DEBUGP(DMM, "-> PTMSI REALLLICATION COMPLETE\n");
+ mmctx_timer_stop(mmctx, 3350);
+ mmctx->p_tmsi_old = 0;
+ /* Unassign the old TLLI */
+ mmctx->tlli = mmctx->tlli_new;
+ //gprs_llgmm_assign(mmctx->llme, 0xffffffff, mmctx->tlli_new, 0, NULL);
+ break;
+ case GSM48_MT_GMM_AUTH_CIPH_RESP:
+ DEBUGP(DMM, "Unimplemented GSM 04.08 GMM msg type 0x%02x\n",
+ gh->msg_type);
+ rc = gsm48_tx_gmm_status(mmctx, GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
+ break;
+ default:
+ DEBUGP(DMM, "Unknown GSM 04.08 GMM msg type 0x%02x\n",
+ gh->msg_type);
+ rc = gsm48_tx_gmm_status(mmctx, GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
+ break;
+ }
+
+ return rc;
+}
+
+static void mmctx_timer_cb(void *_mm)
+{
+ struct sgsn_mm_ctx *mm = _mm;
+
+ mm->num_T_exp++;
+
+ switch (mm->T) {
+ case 3350: /* waiting for ATTACH COMPLETE */
+ if (mm->num_T_exp >= 5) {
+ LOGP(DMM, LOGL_NOTICE, "T3350 expired >= 5 times\n");
+ mm->mm_state = GMM_DEREGISTERED;
+ /* FIXME: should we return some error? */
+ break;
+ }
+ /* re-transmit the respective msg and re-start timer */
+ switch (mm->t3350_mode) {
+ case GMM_T3350_MODE_ATT:
+ gsm48_tx_gmm_att_ack(mm);
+ break;
+ case GMM_T3350_MODE_RAU:
+ gsm48_tx_gmm_ra_upd_ack(mm);
+ break;
+ case GMM_T3350_MODE_PTMSI_REALL:
+ /* FIXME */
+ break;
+ }
+ bsc_schedule_timer(&mm->timer, GSM0408_T3350_SECS, 0);
+ break;
+ case 3370: /* waiting for IDENTITY RESPONSE */
+ if (mm->num_T_exp >= 5) {
+ LOGP(DMM, LOGL_NOTICE, "T3370 expired >= 5 times\n");
+ gsm48_tx_gmm_att_rej(mm, GMM_CAUSE_MS_ID_NOT_DERIVED);
+ mm->mm_state = GMM_DEREGISTERED;
+ break;
+ }
+ /* re-tranmit IDENTITY REQUEST and re-start timer */
+ gsm48_tx_gmm_id_req(mm, mm->t3370_id_type);
+ bsc_schedule_timer(&mm->timer, GSM0408_T3370_SECS, 0);
+ break;
+ default:
+ LOGP(DMM, LOGL_ERROR, "timer expired in unknown mode %u\n",
+ mm->T);
+ }
+}
+
+/* GPRS SESSION MANAGEMENT */
+
+static void msgb_put_pdp_addr_ipv4(struct msgb *msg, uint32_t ipaddr)
+{
+ uint8_t v[6];
+
+ v[0] = PDP_TYPE_ORG_IETF;
+ v[1] = PDP_TYPE_N_IETF_IPv4;
+ *(uint32_t *)(v+2) = htonl(ipaddr);
+
+ msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR, sizeof(v), v);
+}
+
+static void msgb_put_pdp_addr_ppp(struct msgb *msg)
+{
+ uint8_t v[2];
+
+ v[0] = PDP_TYPE_ORG_ETSI;
+ v[1] = PDP_TYPE_N_ETSI_PPP;
+
+ msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR, sizeof(v), v);
+}
+
+/* Section 9.5.2: Ativate PDP Context Accept */
+int gsm48_tx_gsm_act_pdp_acc(struct sgsn_pdp_ctx *pdp)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+ struct gsm48_hdr *gh;
+ uint8_t transaction_id = pdp->ti ^ 0x8; /* flip */
+
+ DEBUGP(DMM, "<- ACTIVATE PDP CONTEXT ACK\n");
+
+ mmctx2msgid(msg, pdp->mm);
+
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+ gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
+ gh->msg_type = GSM48_MT_GSM_ACT_PDP_ACK;
+
+ /* Negotiated LLC SAPI */
+ msgb_v_put(msg, pdp->sapi);
+
+ /* FIXME: copy QoS parameters from original request */
+ //msgb_lv_put(msg, pdp->lib->qos_neg.l, pdp->lib->qos_neg.v);
+ msgb_lv_put(msg, sizeof(default_qos), (uint8_t *)&default_qos);
+
+ /* Radio priority 10.5.7.2 */
+ msgb_v_put(msg, pdp->lib->radio_pri);
+
+ /* PDP address */
+ /* Highest 4 bits of first byte need to be set to 1, otherwise
+ * the IE is identical with the 04.08 PDP Address IE */
+ pdp->lib->eua.v[0] &= ~0xf0;
+ msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR,
+ pdp->lib->eua.l, pdp->lib->eua.v);
+ pdp->lib->eua.v[0] |= 0xf0;
+
+ /* Optional: Protocol configuration options (FIXME: why 'req') */
+ if (pdp->lib->pco_req.l && pdp->lib->pco_req.v)
+ msgb_tlv_put(msg, GSM48_IE_GSM_PROTO_CONF_OPT,
+ pdp->lib->pco_req.l, pdp->lib->pco_req.v);
+
+ /* Optional: Packet Flow Identifier */
+
+ return gsm48_gmm_sendmsg(msg, 0, pdp->mm);
+}
+
+/* Section 9.5.3: Activate PDP Context reject */
+int gsm48_tx_gsm_act_pdp_rej(struct sgsn_mm_ctx *mm, uint8_t tid,
+ uint8_t cause, uint8_t pco_len, uint8_t *pco_v)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+ struct gsm48_hdr *gh;
+ uint8_t transaction_id = tid ^ 0x8; /* flip */
+
+ DEBUGP(DMM, "<- ACTIVATE PDP CONTEXT REJ(cause=%u)\n", cause);
+
+ mmctx2msgid(msg, mm);
+
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+ gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
+ gh->msg_type = GSM48_MT_GSM_ACT_PDP_REJ;
+
+ msgb_v_put(msg, cause);
+ if (pco_len && pco_v)
+ msgb_tlv_put(msg, GSM48_IE_GSM_PROTO_CONF_OPT, pco_len, pco_v);
+
+ return gsm48_gmm_sendmsg(msg, 0, mm);
+}
+
+/* Section 9.5.9: Deactivate PDP Context Accept */
+static int _gsm48_tx_gsm_deact_pdp_acc(struct sgsn_mm_ctx *mm, uint8_t tid)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+ struct gsm48_hdr *gh;
+ uint8_t transaction_id = tid ^ 0x8; /* flip */
+
+ DEBUGP(DMM, "<- DEACTIVATE PDP CONTEXT ACK\n");
+
+ mmctx2msgid(msg, mm);
+
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+ gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
+ gh->msg_type = GSM48_MT_GSM_DEACT_PDP_ACK;
+
+ return gsm48_gmm_sendmsg(msg, 0, mm);
+}
+int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp)
+{
+ return _gsm48_tx_gsm_deact_pdp_acc(pdp->mm, pdp->ti);
+}
+
+/* Section 9.5.1: Activate PDP Context Request */
+static int gsm48_rx_gsm_act_pdp_req(struct sgsn_mm_ctx *mmctx,
+ struct msgb *msg)
+{
+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
+ struct gsm48_act_pdp_ctx_req *act_req = (struct gsm48_act_pdp_ctx_req *) gh->data;
+ uint8_t req_qos_len, req_pdpa_len;
+ uint8_t *req_qos, *req_pdpa;
+ struct tlv_parsed tp;
+ uint8_t transaction_id = (gh->proto_discr >> 4);
+ struct sgsn_pdp_ctx *pdp;
+
+ memset(&tp, 0, sizeof(tp));
+
+ DEBUGP(DMM, "-> ACTIVATE PDP CONTEXT REQ: SAPI=%u NSAPI=%u ",
+ act_req->req_llc_sapi, act_req->req_nsapi);
+
+ rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PDP_CTX_ACT]);
+
+ req_qos_len = act_req->data[0];
+ req_qos = act_req->data + 1; /* 10.5.6.5 */
+ req_pdpa_len = act_req->data[1 + req_qos_len];
+ req_pdpa = act_req->data + 1 + req_qos_len + 1; /* 10.5.6.4 */
+
+ switch (req_pdpa[0] & 0xf) {
+ case 0x0:
+ DEBUGPC(DMM, "ETSI ");
+ break;
+ case 0x1:
+ DEBUGPC(DMM, "IETF ");
+ break;
+ case 0xf:
+ DEBUGPC(DMM, "Empty ");
+ break;
+ }
+
+ switch (req_pdpa[1]) {
+ case 0x21:
+ DEBUGPC(DMM, "IPv4 ");
+ if (req_pdpa_len >= 6) {
+ struct in_addr ia;
+ ia.s_addr = ntohl(*((uint32_t *) (req_pdpa+2)));
+ DEBUGPC(DMM, "%s ", inet_ntoa(ia));
+ }
+ break;
+ case 0x57:
+ DEBUGPC(DMM, "IPv6 ");
+ if (req_pdpa_len >= 18) {
+ /* FIXME: print IPv6 address */
+ }
+ break;
+ default:
+ DEBUGPC(DMM, "0x%02x ", req_pdpa[1]);
+ break;
+ }
+
+ DEBUGPC(DMM, "\n");
+
+ /* put the non-TLV elements in the TLV parser structure to
+ * pass them on to the SGSN / GTP code */
+ tp.lv[OSMO_IE_GSM_REQ_QOS].len = req_qos_len;
+ tp.lv[OSMO_IE_GSM_REQ_QOS].val = req_qos;
+ tp.lv[OSMO_IE_GSM_REQ_PDP_ADDR].len = req_pdpa_len;
+ tp.lv[OSMO_IE_GSM_REQ_PDP_ADDR].val = req_pdpa;
+
+ /* FIXME: determine GGSN based on APN and subscription options */
+ if (TLVP_PRESENT(&tp, GSM48_IE_GSM_APN)) {}
+
+ /* Check if NSAPI is out of range (TS 04.65 / 7.2) */
+ if (act_req->req_nsapi < 5 || act_req->req_nsapi > 15) {
+ /* Send reject with GSM_CAUSE_INV_MAND_INFO */
+ return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
+ GSM_CAUSE_INV_MAND_INFO,
+ 0, NULL);
+ }
+
+ /* Check if NSAPI is already in use */
+ if (sgsn_pdp_ctx_by_nsapi(mmctx, act_req->req_nsapi)) {
+ /* FIXME: send reject with GSM_CAUSE_NSAPI_IN_USE */
+ return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
+ GSM_CAUSE_NSAPI_IN_USE,
+ 0, NULL);
+ }
+
+#if 1
+ {
+ struct sgsn_ggsn_ctx *ggsn = sgsn_ggsn_ctx_by_id(0);
+ if (!ggsn) {
+ LOGP(DGPRS, LOGL_ERROR, "No GGSN context 0 found!\n");
+ return -EIO;
+ }
+ ggsn->gsn = sgsn->gsn;
+ pdp = sgsn_create_pdp_ctx(ggsn, mmctx, act_req->req_nsapi, &tp);
+ if (!pdp)
+ return -1;
+ pdp->sapi = act_req->req_llc_sapi;
+ pdp->ti = transaction_id;
+
+ }
+ return 0;
+#else
+ return gsm48_tx_gsm_act_pdp_acc(mmctx, transaction_id, act_req);
+#endif
+}
+
+/* Section 9.5.8: Deactivate PDP Context Request */
+static int gsm48_rx_gsm_deact_pdp_req(struct sgsn_mm_ctx *mm, struct msgb *msg)
+{
+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
+ uint8_t transaction_id = (gh->proto_discr >> 4);
+ struct sgsn_pdp_ctx *pdp;
+
+ DEBUGP(DMM, "-> DEACTIVATE PDP CONTEXT REQ (cause: %s)\n",
+ get_value_string(gsm_cause_names, gh->data[0]));
+
+ pdp = sgsn_pdp_ctx_by_tid(mm, transaction_id);
+ if (!pdp) {
+ LOGP(DMM, LOGL_NOTICE, "Deactivate PDP Context Request for "
+ "non-existing PDP Context (IMSI=%s, TI=%u)\n",
+ mm->imsi, transaction_id);
+ return _gsm48_tx_gsm_deact_pdp_acc(mm, transaction_id);
+ }
+
+ return sgsn_delete_pdp_ctx(pdp);
+}
+
+static int gsm48_rx_gsm_status(struct sgsn_mm_ctx *ctx, struct msgb *msg)
+{
+ struct gsm48_hdr *gh = msgb_l3(msg);
+
+ DEBUGP(DMM, "-> GPRS SM STATUS (cause: %s)\n",
+ get_value_string(gsm_cause_names, gh->data[0]));
+
+ return 0;
+}
+
+/* GPRS Session Management */
+static int gsm0408_rcv_gsm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
+ struct gprs_llc_llme *llme)
+{
+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
+ int rc;
+
+ /* MMCTX can be NULL when called */
+
+ if (!mmctx) {
+ LOGP(DMM, LOGL_NOTICE, "Cannot handle SM for unknown MM CTX\n");
+ return gsm48_tx_gmm_status_oldmsg(msg, GSM_CAUSE_PROTO_ERR_UNSPEC);
+ }
+
+ switch (gh->msg_type) {
+ case GSM48_MT_GSM_ACT_PDP_REQ:
+ rc = gsm48_rx_gsm_act_pdp_req(mmctx, msg);
+ break;
+ case GSM48_MT_GSM_DEACT_PDP_REQ:
+ rc = gsm48_rx_gsm_deact_pdp_req(mmctx, msg);
+ break;
+ case GSM48_MT_GSM_STATUS:
+ rc = gsm48_rx_gsm_status(mmctx, msg);
+ break;
+ case GSM48_MT_GSM_REQ_PDP_ACT_REJ:
+ case GSM48_MT_GSM_ACT_AA_PDP_REQ:
+ case GSM48_MT_GSM_DEACT_AA_PDP_REQ:
+ DEBUGP(DMM, "Unimplemented GSM 04.08 GSM msg type 0x%02x\n",
+ gh->msg_type);
+ rc = gsm48_tx_sm_status(mmctx, GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
+ break;
+ default:
+ DEBUGP(DMM, "Unknown GSM 04.08 GSM msg type 0x%02x\n",
+ gh->msg_type);
+ rc = gsm48_tx_sm_status(mmctx, GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
+ break;
+
+ }
+
+ return rc;
+}
+
+/* Main entry point for incoming 04.08 GPRS messages */
+int gsm0408_gprs_rcvmsg(struct msgb *msg, struct gprs_llc_llme *llme)
+{
+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
+ uint8_t pdisc = gh->proto_discr & 0x0f;
+ struct sgsn_mm_ctx *mmctx;
+ struct gprs_ra_id ra_id;
+ int rc = -EINVAL;
+
+ bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
+ mmctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &ra_id);
+ if (mmctx) {
+ msgid2mmctx(mmctx, msg);
+ rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PKTS_SIG_IN]);
+ mmctx->llme = llme;
+ }
+
+ /* MMCTX can be NULL */
+
+ switch (pdisc) {
+ case GSM48_PDISC_MM_GPRS:
+ rc = gsm0408_rcv_gmm(mmctx, msg, llme);
+ break;
+ case GSM48_PDISC_SM_GPRS:
+ rc = gsm0408_rcv_gsm(mmctx, msg, llme);
+ break;
+ default:
+ DEBUGP(DMM, "Unknown GSM 04.08 discriminator 0x%02x\n",
+ pdisc);
+ /* FIXME: return status message */
+ break;
+ }
+
+ return rc;
+}
+
+int gprs_gmm_rx_suspend(struct gprs_ra_id *raid, uint32_t tlli)
+{
+ struct sgsn_mm_ctx *mmctx;
+
+ mmctx = sgsn_mm_ctx_by_tlli(tlli, raid);
+ if (!mmctx) {
+ LOGP(DMM, LOGL_NOTICE, "SUSPEND request for unknown "
+ "TLLI=%08x\n", tlli);
+ return -EINVAL;
+ }
+
+ if (mmctx->mm_state != GMM_REGISTERED_NORMAL) {
+ LOGP(DMM, LOGL_NOTICE, "SUSPEND request while state "
+ "!= REGISTERED (TLLI=%08x)\n", tlli);
+ return -EINVAL;
+ }
+
+ /* Transition from REGISTERED_NORMAL to REGISTERED_SUSPENDED */
+ mmctx->mm_state = GMM_REGISTERED_SUSPENDED;
+ return 0;
+}
+
+int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli,
+ uint8_t suspend_ref)
+{
+ struct sgsn_mm_ctx *mmctx;
+
+ /* FIXME: make use of suspend reference? */
+
+ mmctx = sgsn_mm_ctx_by_tlli(tlli, raid);
+ if (!mmctx) {
+ LOGP(DMM, LOGL_NOTICE, "RESUME request for unknown "
+ "TLLI=%08x\n", tlli);
+ return -EINVAL;
+ }
+
+ if (mmctx->mm_state != GMM_REGISTERED_SUSPENDED) {
+ LOGP(DMM, LOGL_NOTICE, "RESUME request while state "
+ "!= SUSPENDED (TLLI=%08x)\n", tlli);
+ /* FIXME: should we not simply ignore it? */
+ return -EINVAL;
+ }
+
+ /* Transition from SUSPENDED to NORMAL */
+ mmctx->mm_state = GMM_REGISTERED_NORMAL;
+ return 0;
+}
diff --git a/openbsc/src/gprs/gprs_llc.c b/openbsc/src/gprs/gprs_llc.c
index 9c75a3d..54f06f9 100644
--- a/openbsc/src/gprs/gprs_llc.c
+++ b/openbsc/src/gprs/gprs_llc.c
@@ -30,73 +30,125 @@
#include <openbsc/gsm_data.h>
#include <openbsc/debug.h>
+#include <openbsc/gprs_sgsn.h>
+#include <openbsc/gprs_gmm.h>
#include <openbsc/gprs_bssgp.h>
#include <openbsc/gprs_llc.h>
#include <openbsc/crc24.h>
-/* Section 4.5.2 Logical Link States + Annex C.2 */
-enum gprs_llc_ll_state {
- GPRS_LLS_UNASSIGNED = 1, /* No TLLI yet */
- GPRS_LLS_ASSIGNED_ADM = 2, /* TLLI assigned */
- GPRS_LLS_LOCAL_EST = 3, /* Local Establishment */
- GPRS_LLS_REMOTE_EST = 4, /* Remote Establishment */
- GPRS_LLS_ABM = 5,
- GPRS_LLS_LOCAL_REL = 6, /* Local Release */
- GPRS_LLS_TIMER_REC = 7, /* Timer Recovery */
+/* Section 8.9.9 LLC layer parameter default values */
+static const struct gprs_llc_params llc_default_params[] = {
+ [1] = {
+ .t200_201 = 5,
+ .n200 = 3,
+ .n201_u = 400,
+ },
+ [2] = {
+ .t200_201 = 5,
+ .n200 = 3,
+ .n201_u = 270,
+ },
+ [3] = {
+ .iov_i_exp = 27,
+ .t200_201 = 5,
+ .n200 = 3,
+ .n201_u = 500,
+ .n201_i = 1503,
+ .mD = 1520,
+ .mU = 1520,
+ .kD = 16,
+ .kU = 16,
+ },
+ [5] = {
+ .iov_i_exp = 27,
+ .t200_201 = 10,
+ .n200 = 3,
+ .n201_u = 500,
+ .n201_i = 1503,
+ .mD = 760,
+ .mU = 760,
+ .kD = 8,
+ .kU = 8,
+ },
+ [7] = {
+ .t200_201 = 20,
+ .n200 = 3,
+ .n201_u = 270,
+ },
+ [8] = {
+ .t200_201 = 20,
+ .n200 = 3,
+ .n201_u = 270,
+ },
+ [9] = {
+ .iov_i_exp = 27,
+ .t200_201 = 20,
+ .n200 = 3,
+ .n201_u = 500,
+ .n201_i = 1503,
+ .mD = 380,
+ .mU = 380,
+ .kD = 4,
+ .kU = 4,
+ },
+ [11] = {
+ .iov_i_exp = 27,
+ .t200_201 = 40,
+ .n200 = 3,
+ .n201_u = 500,
+ .n201_i = 1503,
+ .mD = 190,
+ .mU = 190,
+ .kD = 2,
+ .kU = 2,
+ },
};
-/* Section 4.7.1: Logical Link Entity: One per DLCI (TLLI + SAPI) */
-struct gprs_llc_lle {
- struct llist_head list;
- struct timer_list t200;
- struct timer_list t201; /* wait for acknowledgement */
-
- enum gprs_llc_ll_state state;
-
- uint32_t tlli;
- uint32_t sapi;
-
- uint8_t v_sent;
- uint8_t v_ack;
- uint8_t v_recv;
-
- unsigned int n200;
- unsigned int retrans_ctr;
-
- /* over which BSSGP BTS ctx do we need to transmit */
- uint16_t bvci;
- uint16_t nsei;
-};
-
-static LLIST_HEAD(gprs_llc_lles);
+LLIST_HEAD(gprs_llc_llmes);
void *llc_tall_ctx;
/* lookup LLC Entity based on DLCI (TLLI+SAPI tuple) */
-static struct gprs_llc_lle *lle_by_tlli_sapi(uint32_t tlli, uint32_t sapi)
+static struct gprs_llc_lle *lle_by_tlli_sapi(uint32_t tlli, uint8_t sapi)
{
- struct gprs_llc_lle *lle;
+ struct gprs_llc_llme *llme;
- llist_for_each_entry(lle, &gprs_llc_lles, list) {
- if (lle->tlli == tlli && lle->sapi == sapi)
- return lle;
+ llist_for_each_entry(llme, &gprs_llc_llmes, list) {
+ if (llme->tlli == tlli || llme->old_tlli == tlli)
+ return &llme->lle[sapi];
}
return NULL;
}
-static struct gprs_llc_lle *lle_alloc(uint32_t tlli, uint32_t sapi)
+static void lle_init(struct gprs_llc_llme *llme, uint8_t sapi)
{
- struct gprs_llc_lle *lle;
+ struct gprs_llc_lle *lle = &llme->lle[sapi];
- lle = talloc_zero(llc_tall_ctx, struct gprs_llc_lle);
- if (!lle)
+ lle->llme = llme;
+ lle->sapi = sapi;
+ lle->state = GPRS_LLES_UNASSIGNED;
+
+ /* Initialize according to parameters */
+ memcpy(&lle->params, &llc_default_params[sapi], sizeof(lle->params));
+}
+
+static struct gprs_llc_llme *llme_alloc(uint32_t tlli)
+{
+ struct gprs_llc_llme *llme;
+ uint32_t i;
+
+ llme = talloc_zero(llc_tall_ctx, struct gprs_llc_llme);
+ if (!llme)
return NULL;
- lle->tlli = tlli;
- lle->sapi = sapi;
- lle->state = GPRS_LLS_UNASSIGNED;
- llist_add(&lle->list, &gprs_llc_lles);
+ llme->tlli = tlli;
+ llme->state = GPRS_LLMS_UNASSIGNED;
- return lle;
+ for (i = 0; i < ARRAY_SIZE(llme->lle); i++)
+ lle_init(llme, i);
+
+ llist_add(&llme->list, &gprs_llc_llmes);
+
+ return llme;
}
enum gprs_llc_cmd {
@@ -111,6 +163,23 @@
GPRS_LLC_SABM,
GPRS_LLC_FRMR,
GPRS_LLC_XID,
+ GPRS_LLC_UI,
+};
+
+static const struct value_string llc_cmd_strs[] = {
+ { GPRS_LLC_NULL, "NULL" },
+ { GPRS_LLC_RR, "RR" },
+ { GPRS_LLC_ACK, "ACK" },
+ { GPRS_LLC_RNR, "RNR" },
+ { GPRS_LLC_SACK, "SACK" },
+ { GPRS_LLC_DM, "DM" },
+ { GPRS_LLC_DISC, "DISC" },
+ { GPRS_LLC_UA, "UA" },
+ { GPRS_LLC_SABM, "SABM" },
+ { GPRS_LLC_FRMR, "FRMR" },
+ { GPRS_LLC_XID, "XID" },
+ { GPRS_LLC_UI, "UI" },
+ { 0, NULL }
};
struct gprs_llc_hdr_parsed {
@@ -149,20 +218,20 @@
/* 8.5.1.3: Expiry of T200 */
- if (lle->retrans_ctr >= lle->n200) {
+ if (lle->retrans_ctr >= lle->params.n200) {
/* FIXME: LLGM-STATUS-IND, LL-RELEASE-IND/CNF */
- lle->state = GPRS_LLS_ASSIGNED_ADM;
+ lle->state = GPRS_LLES_ASSIGNED_ADM;
}
switch (lle->state) {
- case GPRS_LLS_LOCAL_EST:
- /* retransmit SABM */
- /* re-start T200 */
+ case GPRS_LLES_LOCAL_EST:
+ /* FIXME: retransmit SABM */
+ /* FIXME: re-start T200 */
lle->retrans_ctr++;
break;
- case GPRS_LLS_LOCAL_REL:
- /* retransmit DISC */
- /* re-start T200 */
+ case GPRS_LLES_LOCAL_REL:
+ /* FIXME: retransmit DISC */
+ /* FIXME: re-start T200 */
lle->retrans_ctr++;
break;
}
@@ -173,9 +242,9 @@
{
struct gprs_llc_lle *lle = data;
- if (lle->retrans_ctr < lle->n200) {
- /* transmit apropriate supervisory frame (8.6.4.1) */
- /* set timer T201 */
+ if (lle->retrans_ctr < lle->params.n200) {
+ /* FIXME: transmit apropriate supervisory frame (8.6.4.1) */
+ /* FIXME: set timer T201 */
lle->retrans_ctr++;
}
}
@@ -213,22 +282,24 @@
/* Identifiers passed down: (BVCI, NSEI) */
- return gprs_bssgp_tx_dl_ud(msg);
+ /* Send BSSGP-DL-UNITDATA.req */
+ return gprs_bssgp_tx_dl_ud(msg, NULL);
}
/* Send XID response to LLE */
static int gprs_llc_tx_xid(struct gprs_llc_lle *lle, struct msgb *msg)
{
/* copy identifiers from LLE to ensure lower layers can route */
- msgb_tlli(msg) = lle->tlli;
- msgb_bvci(msg) = lle->bvci;
- msgb_nsei(msg) = lle->nsei;
+ msgb_tlli(msg) = lle->llme->tlli;
+ msgb_bvci(msg) = lle->llme->bvci;
+ msgb_nsei(msg) = lle->llme->nsei;
return gprs_llc_tx_u(msg, lle->sapi, 0, GPRS_LLC_U_XID, 1);
}
/* Transmit a UI frame over the given SAPI */
-int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command)
+int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command,
+ void *mmctx)
{
struct gprs_llc_lle *lle;
uint8_t *fcs, *llch;
@@ -240,11 +311,25 @@
/* look-up or create the LL Entity for this (TLLI, SAPI) tuple */
lle = lle_by_tlli_sapi(msgb_tlli(msg), sapi);
- if (!lle)
- lle = lle_alloc(msgb_tlli(msg), sapi);
+ if (!lle) {
+ struct gprs_llc_llme *llme;
+ llme = llme_alloc(msgb_tlli(msg));
+ lle = &llme->lle[sapi];
+ }
+
+ if (msg->len > lle->params.n201_u) {
+ LOGP(DLLC, LOGL_ERROR, "Cannot Tx %u bytes (N201-U=%u)\n",
+ msg->len, lle->params.n201_u);
+ return -EFBIG;
+ }
+
/* Update LLE's (BVCI, NSEI) tuple */
- lle->bvci = msgb_bvci(msg);
- lle->nsei = msgb_nsei(msg);
+ lle->llme->bvci = msgb_bvci(msg);
+ lle->llme->nsei = msgb_nsei(msg);
+
+ /* Increment V(U) */
+ nu = lle->vu_send;
+ lle->vu_send = (lle->vu_send + 1) % 512;
/* Address Field */
addr = sapi & 0xf;
@@ -272,22 +357,23 @@
/* Identifiers passed down: (BVCI, NSEI) */
- return gprs_bssgp_tx_dl_ud(msg);
+ /* Send BSSGP-DL-UNITDATA.req */
+ return gprs_bssgp_tx_dl_ud(msg, mmctx);
}
-static int gprs_llc_hdr_dump(struct gprs_llc_hdr_parsed *gph)
+static void gprs_llc_hdr_dump(struct gprs_llc_hdr_parsed *gph)
{
- DEBUGP(DGPRS, "LLC SAPI=%u %c %c FCS=0x%06x(%s) ",
+ DEBUGP(DLLC, "LLC SAPI=%u %c %c FCS=0x%06x(%s) ",
gph->sapi, gph->is_cmd ? 'C' : 'R', gph->ack_req ? 'A' : ' ',
gph->fcs, gph->fcs_calc == gph->fcs ? "correct" : "WRONG");
if (gph->cmd)
- DEBUGPC(DGPRS, "CMD=%u ", gph->cmd);
+ DEBUGPC(DLLC, "CMD=%s ", get_value_string(llc_cmd_strs, gph->cmd));
if (gph->data)
- DEBUGPC(DGPRS, "DATA ");
+ DEBUGPC(DLLC, "DATA ");
- DEBUGPC(DGPRS, "\n");
+ DEBUGPC(DLLC, "\n");
}
static int gprs_llc_hdr_rx(struct gprs_llc_hdr_parsed *gph,
struct gprs_llc_lle *lle)
@@ -295,26 +381,26 @@
switch (gph->cmd) {
case GPRS_LLC_SABM: /* Section 6.4.1.1 */
lle->v_sent = lle->v_ack = lle->v_recv = 0;
- if (lle->state == GPRS_LLS_ASSIGNED_ADM) {
+ if (lle->state == GPRS_LLES_ASSIGNED_ADM) {
/* start re-establishment (8.7.1) */
}
- lle->state = GPRS_LLS_REMOTE_EST;
+ lle->state = GPRS_LLES_REMOTE_EST;
/* FIXME: Send UA */
- lle->state = GPRS_LLS_ABM;
+ lle->state = GPRS_LLES_ABM;
/* FIXME: process data */
break;
case GPRS_LLC_DISC: /* Section 6.4.1.2 */
/* FIXME: Send UA */
/* terminate ABM */
- lle->state = GPRS_LLS_ASSIGNED_ADM;
+ lle->state = GPRS_LLES_ASSIGNED_ADM;
break;
case GPRS_LLC_UA: /* Section 6.4.1.3 */
- if (lle->state == GPRS_LLS_LOCAL_EST)
- lle->state = GPRS_LLS_ABM;
+ if (lle->state == GPRS_LLES_LOCAL_EST)
+ lle->state = GPRS_LLES_ABM;
break;
case GPRS_LLC_DM: /* Section 6.4.1.4: ABM cannot be performed */
- if (lle->state == GPRS_LLS_LOCAL_EST)
- lle->state = GPRS_LLS_ASSIGNED_ADM;
+ if (lle->state == GPRS_LLES_LOCAL_EST)
+ lle->state = GPRS_LLES_ASSIGNED_ADM;
break;
case GPRS_LLC_FRMR: /* Section 6.4.1.5 */
break;
@@ -329,6 +415,15 @@
gprs_llc_tx_xid(lle, resp);
}
break;
+ case GPRS_LLC_UI:
+ if (gph->seq_tx < lle->vu_recv) {
+ LOGP(DLLC, "TLLI=%08x dropping UI, vurecv %u <= %u\n",
+ gph->seq_tx, lle->vu_recv);
+ return -EIO;
+ }
+ /* Increment the sequence number that we expect in the next frame */
+ lle->vu_recv = (gph->seq_tx + 1) % 512;
+ break;
}
return 0;
@@ -336,7 +431,7 @@
/* parse a GPRS LLC header, also check for invalid frames */
static int gprs_llc_hdr_parse(struct gprs_llc_hdr_parsed *ghp,
- const uint8_t *llc_hdr, int len)
+ uint8_t *llc_hdr, int len)
{
uint8_t *ctrl = llc_hdr+1;
int is_sack = 0;
@@ -437,6 +532,7 @@
}
} else if ((ctrl[0] & 0xe0) == 0xc0) {
/* UI (Unconfirmed Inforamtion) format */
+ ghp->cmd = GPRS_LLC_UI;
ghp->data = ctrl + 2;
ghp->data_len = (llc_hdr + len - 3) - ghp->data;
@@ -491,6 +587,12 @@
ghp->fcs_calc = gprs_llc_fcs(llc_hdr, crc_length);
/* FIXME: parse sack frame */
+ if (ghp->cmd == GPRS_LLC_SACK) {
+ LOGP(DLLC, LOGL_NOTICE, "Unsupported SACK frame\n");
+ return -EIO;
+ }
+
+ return 0;
}
/* receive an incoming LLC PDU (BSSGP-UL-UNITDATA-IND, 7.2.4.2) */
@@ -504,42 +606,81 @@
/* Identifiers from DOWN: NSEI, BVCI, TLLI */
- rc = gprs_llc_hdr_parse(&llhp, lh, TLVP_LEN(tv, BSSGP_IE_LLC_PDU));
- /* FIXME */
-
+ memset(&llhp, 0, sizeof(llhp));
+ rc = gprs_llc_hdr_parse(&llhp, (uint8_t *) lh, TLVP_LEN(tv, BSSGP_IE_LLC_PDU));
gprs_llc_hdr_dump(&llhp);
+ if (rc < 0) {
+ LOGP(DLLC, LOGL_NOTICE, "Error during LLC header parsing\n");
+ return rc;
+ }
+
+ if (llhp.fcs != llhp.fcs_calc) {
+ LOGP(DLLC, LOGL_INFO, "Dropping frame with invalid FCS\n");
+ return -EIO;
+ }
+
+ switch (gprs_tlli_type(msgb_tlli(msg))) {
+ case TLLI_LOCAL:
+ case TLLI_FOREIGN:
+ case TLLI_RANDOM:
+ case TLLI_AUXILIARY:
+ break;
+ default:
+ LOGP(DLLC, LOGL_ERROR,
+ "Discarding frame with strange TLLI type\n");
+ break;
+ }
/* find the LLC Entity for this TLLI+SAPI tuple */
lle = lle_by_tlli_sapi(msgb_tlli(msg), llhp.sapi);
- /* allocate a new LLE if needed */
- if (!lle)
- lle = lle_alloc(msgb_tlli(msg), llhp.sapi);
+
+ /* 7.2.1.1 LLC belonging to unassigned TLLI+SAPI shall be discarded,
+ * except UID and XID frames with SAPI=1 */
+ if (!lle) {
+ if (llhp.sapi == GPRS_SAPI_GMM &&
+ (llhp.cmd == GPRS_LLC_XID || llhp.cmd == GPRS_LLC_UI)) {
+ struct gprs_llc_llme *llme;
+ /* FIXME: don't use the TLLI but the 0xFFFF unassigned? */
+ llme = llme_alloc(msgb_tlli(msg));
+ lle = &llme->lle[llhp.sapi];
+ } else {
+ LOGP(DLLC, LOGL_NOTICE,
+ "unknown TLLI/SAPI: Silently dropping\n");
+ return 0;
+ }
+ }
/* Update LLE's (BVCI, NSEI) tuple */
- lle->bvci = msgb_bvci(msg);
- lle->nsei = msgb_nsei(msg);
+ lle->llme->bvci = msgb_bvci(msg);
+ lle->llme->nsei = msgb_nsei(msg);
+ /* Receive and Process the actual LLC frame */
rc = gprs_llc_hdr_rx(&llhp, lle);
- /* FIXME */
+ if (rc < 0)
+ return rc;
+ /* llhp.data is only set when we need to send LL_[UNIT]DATA_IND up */
if (llhp.data) {
msgb_gmmh(msg) = llhp.data;
switch (llhp.sapi) {
case GPRS_SAPI_GMM:
- rc = gsm0408_gprs_rcvmsg(msg);
+ /* send LL_UNITDATA_IND to GMM */
+ rc = gsm0408_gprs_rcvmsg(msg, lle->llme);
break;
- case GPRS_SAPI_TOM2:
- case GPRS_SAPI_TOM8:
- /* FIXME */
case GPRS_SAPI_SNDCP3:
case GPRS_SAPI_SNDCP5:
case GPRS_SAPI_SNDCP9:
case GPRS_SAPI_SNDCP11:
- /* FIXME */
+ /* send LL_DATA_IND/LL_UNITDATA_IND to SNDCP */
+ rc = sndcp_llunitdata_ind(msg, lle, llhp.data, llhp.data_len);
+ break;
case GPRS_SAPI_SMS:
/* FIXME */
+ case GPRS_SAPI_TOM2:
+ case GPRS_SAPI_TOM8:
+ /* FIXME: send LL_DATA_IND/LL_UNITDATA_IND to TOM */
default:
- LOGP(DGPRS, LOGL_NOTICE, "Unsupported SAPI %u\n", llhp.sapi);
+ LOGP(DLLC, LOGL_NOTICE, "Unsupported SAPI %u\n", llhp.sapi);
rc = -EINVAL;
break;
}
@@ -547,3 +688,51 @@
return rc;
}
+
+/* 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)
+{
+ unsigned int i;
+
+ if (old_tlli == 0xffffffff && new_tlli != 0xffffffff) {
+ /* TLLI Assignment 8.3.1 */
+ /* New TLLI shall be assigned and used when (re)transmitting LLC frames */
+ /* If old TLLI != 0xffffffff was assigned to LLME, then TLLI
+ * old is unassigned. Only TLLI new shall be accepted when
+ * received from peer. */
+
+ /* If TLLI old == 0xffffffff was assigned to LLME, then this is
+ * TLLI assignmemt according to 8.3.1 */
+ llme->old_tlli = 0;
+ llme->tlli = new_tlli;
+ llme->state = GPRS_LLMS_ASSIGNED;
+ /* 8.5.3.1 For all LLE's */
+ for (i = 0; i < ARRAY_SIZE(llme->lle); i++) {
+ struct gprs_llc_lle *l = &llme->lle[i];
+ l->vu_send = l->vu_recv = 0;
+ l->retrans_ctr = 0;
+ l->state = GPRS_LLES_ASSIGNED_ADM;
+ /* FIXME Set parameters according to table 9 */
+ }
+ } else if (old_tlli != 0xffffffff && new_tlli != 0xffffffff) {
+ /* TLLI Change 8.3.2 */
+ /* Both TLLI Old and TLLI New are assigned; use New when
+ * (re)transmitting. Accept toth Old and New on Rx */
+ llme->old_tlli = llme->tlli;
+ llme->tlli = new_tlli;
+ llme->state = GPRS_LLMS_ASSIGNED;
+ } else if (old_tlli != 0xffffffff && new_tlli == 0xffffffff) {
+ /* TLLI Unassignment 8.3.3) */
+ llme->tlli = llme->old_tlli = 0;
+ llme->state = GPRS_LLMS_UNASSIGNED;
+ for (i = 0; i < ARRAY_SIZE(llme->lle); i++) {
+ struct gprs_llc_lle *l = &llme->lle[i];
+ l->state = GPRS_LLES_UNASSIGNED;
+ }
+ } else
+ return -EINVAL;
+
+ return 0;
+}
diff --git a/openbsc/src/gprs/gprs_llc_vty.c b/openbsc/src/gprs/gprs_llc_vty.c
new file mode 100644
index 0000000..cb91a3a
--- /dev/null
+++ b/openbsc/src/gprs/gprs_llc_vty.c
@@ -0,0 +1,109 @@
+/* VTY interface for our GPRS LLC implementation */
+
+/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <arpa/inet.h>
+
+#include <openbsc/gsm_data.h>
+#include <osmocore/msgb.h>
+#include <osmocore/tlv.h>
+#include <osmocore/talloc.h>
+#include <osmocore/select.h>
+#include <osmocore/rate_ctr.h>
+#include <openbsc/debug.h>
+#include <openbsc/signal.h>
+#include <openbsc/gprs_llc.h>
+
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/command.h>
+
+struct value_string gprs_llc_state_strs[] = {
+ { GPRS_LLES_UNASSIGNED, "TLLI Unassigned" },
+ { GPRS_LLES_ASSIGNED_ADM, "TLLI Assigned" },
+ { GPRS_LLES_LOCAL_EST, "Local Establishment" },
+ { GPRS_LLES_REMOTE_EST, "Remote Establishment" },
+ { GPRS_LLES_ABM, "Asynchronous Balanced Mode" },
+ { GPRS_LLES_LOCAL_REL, "Local Release" },
+ { GPRS_LLES_TIMER_REC, "Timer Recovery" },
+};
+
+static void vty_dump_lle(struct vty *vty, struct gprs_llc_lle *lle)
+{
+ struct gprs_llc_params *par = &lle->params;
+ vty_out(vty, " SAPI %2u State %s VUsend=%u, VUrecv=%u", lle->sapi,
+ get_value_string(gprs_llc_state_strs, lle->state),
+ lle->vu_send, lle->vu_recv);
+ vty_out(vty, " Vsent=%u Vack=%u Vrecv=%u, RetransCtr=%u%s",
+ lle->v_sent, lle->v_ack, lle->v_recv,
+ lle->retrans_ctr, VTY_NEWLINE);
+ vty_out(vty, " T200=%u, N200=%u, N201-U=%u, N201-I=%u, mD=%u, "
+ "mU=%u, kD=%u, kU=%u%s", par->t200_201, par->n200,
+ par->n201_u, par->n201_i, par->mD, par->mU, par->kD,
+ par->kU, VTY_NEWLINE);
+}
+
+static uint8_t valid_sapis[] = { 1, 2, 3, 5, 7, 8, 9, 11 };
+
+static void vty_dump_llme(struct vty *vty, struct gprs_llc_llme *llme)
+{
+ unsigned int i;
+
+ vty_out(vty, "TLLI %08x (Old TLLI %08x) BVCI=%u NSEI=%u: State %s%s",
+ llme->tlli, llme->old_tlli, llme->bvci, llme->nsei,
+ get_value_string(gprs_llc_state_strs, llme->state), VTY_NEWLINE);
+
+ for (i = 0; i < ARRAY_SIZE(valid_sapis); i++) {
+ struct gprs_llc_lle *lle;
+ uint8_t sapi = valid_sapis[i];
+
+ if (sapi >= ARRAY_SIZE(llme->lle))
+ continue;
+
+ lle = &llme->lle[sapi];
+ vty_dump_lle(vty, lle);
+ }
+}
+
+
+DEFUN(show_llc, show_llc_cmd,
+ "show llc",
+ SHOW_STR "Display information about the LLC protocol")
+{
+ struct gprs_llc_llme *llme;
+
+ vty_out(vty, "State of LLC Entities%s", VTY_NEWLINE);
+ llist_for_each_entry(llme, &gprs_llc_llmes, list) {
+ vty_dump_llme(vty, llme);
+ }
+ return CMD_SUCCESS;
+}
+
+int gprs_llc_vty_init(void)
+{
+ install_element_ve(&show_llc_cmd);
+
+ return 0;
+}
diff --git a/openbsc/src/gprs/gprs_ns.c b/openbsc/src/gprs/gprs_ns.c
index dc12953..3db1d67 100644
--- a/openbsc/src/gprs/gprs_ns.c
+++ b/openbsc/src/gprs/gprs_ns.c
@@ -69,8 +69,8 @@
#include <openbsc/signal.h>
#include <openbsc/gprs_ns.h>
#include <openbsc/gprs_bssgp.h>
-
-#define NS_ALLOC_SIZE 1024
+#include <openbsc/gprs_ns_frgre.h>
+#include <openbsc/socket.h>
static const struct tlv_definition ns_att_tlvdef = {
.def = {
@@ -108,8 +108,7 @@
};
/* Lookup struct gprs_nsvc based on NSVCI */
-static struct gprs_nsvc *nsvc_by_nsvci(struct gprs_ns_inst *nsi,
- uint16_t nsvci)
+struct gprs_nsvc *nsvc_by_nsvci(struct gprs_ns_inst *nsi, uint16_t nsvci)
{
struct gprs_nsvc *nsvc;
llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
@@ -150,6 +149,8 @@
{
struct gprs_nsvc *nsvc;
+ LOGP(DNS, LOGL_INFO, "NSVCI=%u Creating NS-VC\n", nsvci);
+
nsvc = talloc_zero(nsi, struct gprs_nsvc);
nsvc->nsvci = nsvci;
/* before RESET procedure: BLOCKED and DEAD */
@@ -205,21 +206,27 @@
}
static int nsip_sendmsg(struct gprs_nsvc *nsvc, struct msgb *msg);
+extern int grps_ns_frgre_sendmsg(struct gprs_nsvc *nsvc, struct msgb *msg);
static int gprs_ns_tx(struct gprs_nsvc *nsvc, struct msgb *msg)
{
int ret;
+ log_set_context(BSC_CTX_NSVC, nsvc);
+
/* Increment number of Uplink bytes */
rate_ctr_inc(&nsvc->ctrg->ctr[NS_CTR_PKTS_OUT]);
rate_ctr_add(&nsvc->ctrg->ctr[NS_CTR_BYTES_OUT], msgb_l2len(msg));
- switch (nsvc->nsi->ll) {
+ switch (nsvc->ll) {
case GPRS_NS_LL_UDP:
ret = nsip_sendmsg(nsvc, msg);
break;
+ case GPRS_NS_LL_FR_GRE:
+ ret = gprs_ns_frgre_sendmsg(nsvc, msg);
+ break;
default:
- LOGP(DNS, LOGL_ERROR, "unsupported NS linklayer %u\n", nsvc->nsi->ll);
+ LOGP(DNS, LOGL_ERROR, "unsupported NS linklayer %u\n", nsvc->ll);
msgb_free(msg);
ret = -EIO;
break;
@@ -229,9 +236,11 @@
static int gprs_ns_tx_simple(struct gprs_nsvc *nsvc, uint8_t pdu_type)
{
- struct msgb *msg = msgb_alloc(NS_ALLOC_SIZE, "GPRS/NS");
+ struct msgb *msg = gprs_ns_msgb_alloc();
struct gprs_ns_hdr *nsh;
+ log_set_context(BSC_CTX_NSVC, nsvc);
+
if (!msg)
return -ENOMEM;
@@ -245,11 +254,13 @@
int gprs_ns_tx_reset(struct gprs_nsvc *nsvc, uint8_t cause)
{
- struct msgb *msg = msgb_alloc(NS_ALLOC_SIZE, "GPRS/NS");
+ struct msgb *msg = gprs_ns_msgb_alloc();
struct gprs_ns_hdr *nsh;
uint16_t nsvci = htons(nsvc->nsvci);
uint16_t nsei = htons(nsvc->nsei);
+ log_set_context(BSC_CTX_NSVC, nsvc);
+
if (!msg)
return -ENOMEM;
@@ -271,16 +282,18 @@
int gprs_ns_tx_status(struct gprs_nsvc *nsvc, uint8_t cause,
uint16_t bvci, struct msgb *orig_msg)
{
- struct msgb *msg = msgb_alloc(NS_ALLOC_SIZE, "GPRS/NS");
+ struct msgb *msg = gprs_ns_msgb_alloc();
struct gprs_ns_hdr *nsh;
uint16_t nsvci = htons(nsvc->nsvci);
+ log_set_context(BSC_CTX_NSVC, nsvc);
+
bvci = htons(bvci);
if (!msg)
return -ENOMEM;
- LOGP(DNS, LOGL_INFO, "NSEI=%u Tx NS STATUS (NSVCI=%u, cause=%s)\n",
+ LOGP(DNS, LOGL_NOTICE, "NSEI=%u Tx NS STATUS (NSVCI=%u, cause=%s)\n",
nsvc->nsei, nsvc->nsvci, gprs_ns_cause_str(cause));
msg->l2h = msgb_put(msg, sizeof(*nsh));
@@ -317,10 +330,12 @@
int gprs_ns_tx_block(struct gprs_nsvc *nsvc, uint8_t cause)
{
- struct msgb *msg = msgb_alloc(NS_ALLOC_SIZE, "GPRS/NS");
+ struct msgb *msg = gprs_ns_msgb_alloc();
struct gprs_ns_hdr *nsh;
uint16_t nsvci = htons(nsvc->nsvci);
+ log_set_context(BSC_CTX_NSVC, nsvc);
+
if (!msg)
return -ENOMEM;
@@ -343,6 +358,7 @@
int gprs_ns_tx_unblock(struct gprs_nsvc *nsvc)
{
+ log_set_context(BSC_CTX_NSVC, nsvc);
LOGP(DNS, LOGL_INFO, "NSEI=%u Tx NS UNBLOCK (NSVCI=%u)\n",
nsvc->nsei, nsvc->nsvci);
@@ -351,6 +367,7 @@
int gprs_ns_tx_alive(struct gprs_nsvc *nsvc)
{
+ log_set_context(BSC_CTX_NSVC, nsvc);
LOGP(DNS, LOGL_DEBUG, "NSEI=%u Tx NS ALIVE (NSVCI=%u)\n",
nsvc->nsei, nsvc->nsvci);
@@ -359,6 +376,7 @@
int gprs_ns_tx_alive_ack(struct gprs_nsvc *nsvc)
{
+ log_set_context(BSC_CTX_NSVC, nsvc);
LOGP(DNS, LOGL_DEBUG, "NSEI=%u Tx NS ALIVE_ACK (NSVCI=%u)\n",
nsvc->nsei, nsvc->nsvci);
@@ -383,6 +401,7 @@
enum ns_timeout tout = timer_mode_tout[mode];
unsigned int seconds = nsvc->nsi->timeout[tout];
+ log_set_context(BSC_CTX_NSVC, nsvc);
DEBUGP(DNS, "NSEI=%u Starting timer in mode %s (%u seconds)\n",
nsvc->nsei, get_value_string(timer_mode_strs, mode),
seconds);
@@ -400,6 +419,7 @@
enum ns_timeout tout = timer_mode_tout[nsvc->timer_mode];
unsigned int seconds = nsvc->nsi->timeout[tout];
+ log_set_context(BSC_CTX_NSVC, nsvc);
DEBUGP(DNS, "NSEI=%u Timer expired in mode %s (%u seconds)\n",
nsvc->nsei, get_value_string(timer_mode_strs, nsvc->timer_mode),
seconds);
@@ -449,10 +469,11 @@
/* Section 9.2.6 */
static int gprs_ns_tx_reset_ack(struct gprs_nsvc *nsvc)
{
- struct msgb *msg = msgb_alloc(NS_ALLOC_SIZE, "GPRS/NS");
+ struct msgb *msg = gprs_ns_msgb_alloc();
struct gprs_ns_hdr *nsh;
uint16_t nsvci, nsei;
+ log_set_context(BSC_CTX_NSVC, nsvc);
if (!msg)
return -ENOMEM;
@@ -486,6 +507,7 @@
"to NS-VC!\n", msgb_nsei(msg));
return -EINVAL;
}
+ log_set_context(BSC_CTX_NSVC, nsvc);
if (!(nsvc->state & NSE_S_ALIVE)) {
LOGP(DNS, LOGL_ERROR, "NSEI=%u is not alive, cannot send\n",
@@ -540,9 +562,16 @@
uint8_t cause;
int rc;
- LOGP(DNS, LOGL_INFO, "NSEI=%u NS STATUS ", nsvc->nsei);
+ LOGP(DNS, LOGL_NOTICE, "NSEI=%u Rx NS STATUS ", nsvc->nsei);
- rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data, msgb_l2len(msg), 0, 0);
+ rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data,
+ msgb_l2len(msg) - sizeof(*nsh), 0, 0);
+ if (rc < 0) {
+ LOGPC(DNS, LOGL_NOTICE, "Error during TLV Parse\n");
+ LOGP(DNS, LOGL_ERROR, "NSEI=%u Rx NS STATUS: "
+ "Error during TLV Parse\n", nsvc->nsei);
+ return rc;
+ }
if (!TLVP_PRESENT(&tp, NS_IE_CAUSE)) {
LOGPC(DNS, LOGL_INFO, "missing cause IE\n");
@@ -550,7 +579,7 @@
}
cause = *TLVP_VAL(&tp, NS_IE_CAUSE);
- LOGPC(DNS, LOGL_INFO, "cause=%s\n", gprs_ns_cause_str(cause));
+ LOGPC(DNS, LOGL_NOTICE, "cause=%s\n", gprs_ns_cause_str(cause));
return 0;
}
@@ -564,7 +593,13 @@
uint16_t *nsvci, *nsei;
int rc;
- rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data, msgb_l2len(msg), 0, 0);
+ rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data,
+ msgb_l2len(msg) - sizeof(*nsh), 0, 0);
+ if (rc < 0) {
+ LOGP(DNS, LOGL_ERROR, "NSEI=%u Rx NS RESET "
+ "Error during TLV Parse\n", nsvc->nsei);
+ return rc;
+ }
if (!TLVP_PRESENT(&tp, NS_IE_CAUSE) ||
!TLVP_PRESENT(&tp, NS_IE_VCI) ||
@@ -588,7 +623,8 @@
nsvc->nsvci = ntohs(*nsvci);
/* start the test procedure */
- nsvc_start_timer(nsvc, NSVC_TIMER_TNS_ALIVE);
+ gprs_ns_tx_simple(nsvc, NS_PDUT_ALIVE);
+ nsvc_start_timer(nsvc, NSVC_TIMER_TNS_TEST);
/* inform interested parties about the fact that this NSVC
* has received RESET */
@@ -608,7 +644,13 @@
nsvc->state |= NSE_S_BLOCKED;
- rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data, msgb_l2len(msg), 0, 0);
+ rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data,
+ msgb_l2len(msg) - sizeof(*nsh), 0, 0);
+ if (rc < 0) {
+ LOGP(DNS, LOGL_ERROR, "NSEI=%u Rx NS BLOCK "
+ "Error during TLV Parse\n", nsvc->nsei);
+ return rc;
+ }
if (!TLVP_PRESENT(&tp, NS_IE_CAUSE) ||
!TLVP_PRESENT(&tp, NS_IE_VCI)) {
@@ -628,7 +670,7 @@
/* main entry point, here incoming NS frames enter */
int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
- struct sockaddr_in *saddr)
+ struct sockaddr_in *saddr, enum gprs_ns_ll ll)
{
struct gprs_ns_hdr *nsh = (struct gprs_ns_hdr *) msg->l2h;
struct gprs_nsvc *nsvc;
@@ -639,10 +681,17 @@
if (!nsvc) {
struct tlv_parsed tp;
uint16_t nsei;
+ if (nsh->pdu_type == NS_PDUT_STATUS) {
+ LOGP(DNS, LOGL_INFO, "Ignoring NS STATUS from %s:%u "
+ "for non-existing NS-VC\n",
+ inet_ntoa(saddr->sin_addr), ntohs(saddr->sin_port));
+ return 0;
+ }
/* Only the RESET procedure creates a new NSVC */
if (nsh->pdu_type != NS_PDUT_RESET) {
/* Since we have no NSVC, we have to use a fake */
nsvc = nsi->unknown_nsvc;
+ log_set_context(BSC_CTX_NSVC, nsvc);
LOGP(DNS, LOGL_INFO, "Rejecting NS PDU type 0x%0x "
"from %s:%u for non-existing NS-VC\n",
nsh->pdu_type, inet_ntoa(saddr->sin_addr),
@@ -650,12 +699,22 @@
nsvc->nsvci = nsvc->nsei = 0xfffe;
nsvc->ip.bts_addr = *saddr;
nsvc->state = NSE_S_ALIVE;
+ nsvc->ll = ll;
+#if 0
+ return gprs_ns_tx_reset(nsvc, NS_CAUSE_PDU_INCOMP_PSTATE);
+#else
return gprs_ns_tx_status(nsvc,
NS_CAUSE_PDU_INCOMP_PSTATE, 0,
msg);
+#endif
}
rc = tlv_parse(&tp, &ns_att_tlvdef, nsh->data,
- msgb_l2len(msg), 0, 0);
+ msgb_l2len(msg) - sizeof(*nsh), 0, 0);
+ if (rc < 0) {
+ LOGP(DNS, LOGL_ERROR, "Rx NS RESET Error %d during "
+ "TLV Parse\n", rc);
+ return rc;
+ }
if (!TLVP_PRESENT(&tp, NS_IE_CAUSE) ||
!TLVP_PRESENT(&tp, NS_IE_VCI) ||
!TLVP_PRESENT(&tp, NS_IE_NSEI)) {
@@ -669,15 +728,19 @@
* simply have changed addresses, or it is a SGSN */
nsvc = nsvc_by_nsei(nsi, nsei);
if (!nsvc) {
+ nsvc = nsvc_create(nsi, 0xffff);
+ nsvc->ll = ll;
+ log_set_context(BSC_CTX_NSVC, nsvc);
LOGP(DNS, LOGL_INFO, "Creating NS-VC for BSS at %s:%u\n",
inet_ntoa(saddr->sin_addr), ntohs(saddr->sin_port));
- nsvc = nsvc_create(nsi, 0xffff);
}
/* Update the remote peer IP address/port */
nsvc->ip.bts_addr = *saddr;
} else
msgb_nsei(msg) = nsvc->nsei;
+ log_set_context(BSC_CTX_NSVC, nsvc);
+
/* Increment number of Incoming bytes */
rate_ctr_inc(&nsvc->ctrg->ctr[NS_CTR_PKTS_IN]);
rate_ctr_add(&nsvc->ctrg->ctr[NS_CTR_BYTES_IN], msgb_l2len(msg));
@@ -694,9 +757,7 @@
rc = gprs_ns_tx_alive_ack(nsvc);
break;
case NS_PDUT_ALIVE_ACK:
- /* stop Tns-alive */
- bsc_del_timer(&nsvc->timer);
- /* start Tns-test */
+ /* stop Tns-alive and start Tns-test */
nsvc_start_timer(nsvc, NSVC_TIMER_TNS_TEST);
if (nsvc->remote_end_is_sgsn) {
/* FIXME: this should be one level higher */
@@ -720,13 +781,13 @@
nsvc->state = NSE_S_BLOCKED | NSE_S_ALIVE;
nsvc->remote_state = NSE_S_BLOCKED | NSE_S_ALIVE;
rate_ctr_inc(&nsvc->ctrg->ctr[NS_CTR_BLOCKED]);
- if (nsvc->remote_end_is_sgsn) {
+ if (nsvc->persistent || nsvc->remote_end_is_sgsn) {
/* stop RESET timer */
bsc_del_timer(&nsvc->timer);
- /* Initiate TEST proc.: Send ALIVE and start timer */
- rc = gprs_ns_tx_simple(nsvc, NS_PDUT_ALIVE);
- nsvc_start_timer(nsvc, NSVC_TIMER_TNS_ALIVE);
}
+ /* Initiate TEST proc.: Send ALIVE and start timer */
+ rc = gprs_ns_tx_simple(nsvc, NS_PDUT_ALIVE);
+ nsvc_start_timer(nsvc, NSVC_TIMER_TNS_TEST);
break;
case NS_PDUT_UNBLOCK:
/* Section 7.2: unblocking procedure */
@@ -797,7 +858,7 @@
static struct msgb *read_nsip_msg(struct bsc_fd *bfd, int *error,
struct sockaddr_in *saddr)
{
- struct msgb *msg = msgb_alloc(NS_ALLOC_SIZE, "Abis/IP/GPRS-NS");
+ struct msgb *msg = gprs_ns_msgb_alloc();
int ret = 0;
socklen_t saddr_len = sizeof(*saddr);
@@ -806,7 +867,7 @@
return NULL;
}
- ret = recvfrom(bfd->fd, msg->data, NS_ALLOC_SIZE, 0,
+ ret = recvfrom(bfd->fd, msg->data, NS_ALLOC_SIZE - NS_ALLOC_HEADROOM, 0,
(struct sockaddr *)saddr, &saddr_len);
if (ret < 0) {
LOGP(DNS, LOGL_ERROR, "recv error %s during NSIP recv\n",
@@ -836,7 +897,7 @@
if (!msg)
return error;
- error = gprs_ns_rcvmsg(nsi, msg, &saddr);
+ error = gprs_ns_rcvmsg(nsi, msg, &saddr, GPRS_NS_LL_UDP);
msgb_free(msg);
@@ -849,7 +910,7 @@
return -EIO;
}
-int nsip_sendmsg(struct gprs_nsvc *nsvc, struct msgb *msg)
+static int nsip_sendmsg(struct gprs_nsvc *nsvc, struct msgb *msg)
{
int rc;
struct gprs_ns_inst *nsi = nsvc->nsi;
@@ -876,24 +937,38 @@
return rc;
}
-extern int make_sock(struct bsc_fd *bfd, int proto, uint16_t port,
- int (*cb)(struct bsc_fd *fd, unsigned int what));
-
/* Listen for incoming GPRS packets */
-int nsip_listen(struct gprs_ns_inst *nsi, uint16_t udp_port)
+int gprs_ns_nsip_listen(struct gprs_ns_inst *nsi)
{
int ret;
- ret = make_sock(&nsi->nsip.fd, IPPROTO_UDP, udp_port, nsip_fd_cb);
+ ret = make_sock(&nsi->nsip.fd, IPPROTO_UDP, nsi->nsip.local_ip,
+ nsi->nsip.local_port, nsip_fd_cb);
if (ret < 0)
return ret;
- nsi->ll = GPRS_NS_LL_UDP;
nsi->nsip.fd.data = nsi;
return ret;
}
+/* Initiate a RESET procedure */
+void gprs_nsvc_reset(struct gprs_nsvc *nsvc, uint8_t cause)
+{
+ LOGP(DNS, LOGL_INFO, "NSEI=%u RESET procedure based on API request\n",
+ nsvc->nsei);
+
+ /* Mark NS-VC locally as blocked and dead */
+ nsvc->state = NSE_S_BLOCKED;
+ /* Send NS-RESET PDU */
+ if (gprs_ns_tx_reset(nsvc, cause) < 0) {
+ LOGP(DNS, LOGL_ERROR, "NSEI=%u, error resetting NS-VC\n",
+ nsvc->nsei);
+ }
+ /* Start Tns-reset */
+ nsvc_start_timer(nsvc, NSVC_TIMER_TNS_RESET);
+}
+
/* 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,
@@ -909,18 +984,6 @@
nsvc->nsvci = nsvci;
nsvc->remote_end_is_sgsn = 1;
- /* Initiate a RESET procedure */
- /* Mark NS-VC locally as blocked and dead */
- nsvc->state = NSE_S_BLOCKED;
- /* Send NS-RESET PDU */
- if (gprs_ns_tx_reset(nsvc, NS_CAUSE_OM_INTERVENTION) < 0) {
- LOGP(DNS, LOGL_ERROR, "NSEI=%u, error resetting NS-VC\n",
- nsei);
- }
- /* Start Tns-reset */
- nsvc_start_timer(nsvc, NSVC_TIMER_TNS_RESET);
-
+ gprs_nsvc_reset(nsvc, NS_CAUSE_OM_INTERVENTION);
return nsvc;
}
-
-
diff --git a/openbsc/src/gprs/gprs_ns_frgre.c b/openbsc/src/gprs/gprs_ns_frgre.c
new file mode 100644
index 0000000..7436d0d
--- /dev/null
+++ b/openbsc/src/gprs/gprs_ns_frgre.c
@@ -0,0 +1,305 @@
+/* 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) */
+
+/* NS-over-FR-over-GRE implementation */
+
+/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <arpa/inet.h>
+
+#include <osmocore/select.h>
+#include <osmocore/msgb.h>
+#include <osmocore/talloc.h>
+
+#include <openbsc/socket.h>
+#include <openbsc/debug.h>
+#include <openbsc/gprs_ns.h>
+
+#define GRE_PTYPE_FR 0x6559
+#define GRE_PTYPE_IPv4 0x0800
+#define GRE_PTYPE_KAR 0x0000 /* keepalive response */
+
+struct gre_hdr {
+ uint16_t flags;
+ uint16_t ptype;
+} __attribute__ ((packed));
+
+/* IPv4 messages inside the GRE tunnel might be GRE keepalives */
+static int handle_rx_gre_ipv4(struct bsc_fd *bfd, struct msgb *msg,
+ struct iphdr *iph, struct gre_hdr *greh)
+{
+ struct gprs_ns_inst *nsi = bfd->data;
+ int gre_payload_len;
+ struct iphdr *inner_iph;
+ struct gre_hdr *inner_greh;
+ struct sockaddr_in daddr;
+ struct in_addr ia;
+
+ gre_payload_len = msg->len - (iph->ihl*4 + sizeof(*greh));
+
+ inner_iph = (struct iphdr *) ((uint8_t *)greh + sizeof(*greh));
+
+ if (gre_payload_len < inner_iph->ihl*4 + sizeof(*inner_greh)) {
+ LOGP(DNS, LOGL_ERROR, "GRE keepalive too short\n");
+ return -EIO;
+ }
+
+ if (inner_iph->saddr != iph->daddr ||
+ inner_iph->daddr != iph->saddr) {
+ LOGP(DNS, LOGL_ERROR,
+ "GRE keepalive with wrong tunnel addresses\n");
+ return -EIO;
+ }
+
+ if (inner_iph->protocol != IPPROTO_GRE) {
+ LOGP(DNS, LOGL_ERROR, "GRE keepalive with wrong protocol\n");
+ return -EIO;
+ }
+
+ inner_greh = (struct gre_hdr *) ((uint8_t *)inner_iph + iph->ihl*4);
+ if (inner_greh->ptype != htons(GRE_PTYPE_KAR)) {
+ LOGP(DNS, LOGL_ERROR, "GRE keepalive inner GRE type != 0\n");
+ return -EIO;
+ }
+
+ /* Actually send the response back */
+
+ daddr.sin_family = AF_INET;
+ daddr.sin_addr.s_addr = inner_iph->daddr;
+ daddr.sin_port = IPPROTO_GRE;
+
+ ia.s_addr = iph->saddr;
+ LOGP(DNS, LOGL_DEBUG, "GRE keepalive from %s, responding\n",
+ inet_ntoa(ia));
+
+ return sendto(nsi->frgre.fd.fd, inner_greh,
+ gre_payload_len - inner_iph->ihl*4, 0,
+ (struct sockaddr *)&daddr, sizeof(daddr));
+}
+
+static struct msgb *read_nsfrgre_msg(struct bsc_fd *bfd, int *error,
+ struct sockaddr_in *saddr)
+{
+ struct msgb *msg = msgb_alloc(NS_ALLOC_SIZE, "Gb/NS/FR/GRE Rx");
+ int ret = 0;
+ socklen_t saddr_len = sizeof(*saddr);
+ struct iphdr *iph;
+ struct gre_hdr *greh;
+ uint8_t *frh;
+ uint16_t dlci;
+
+ if (!msg) {
+ *error = -ENOMEM;
+ return NULL;
+ }
+
+ ret = recvfrom(bfd->fd, msg->data, NS_ALLOC_SIZE, 0,
+ (struct sockaddr *)saddr, &saddr_len);
+ if (ret < 0) {
+ LOGP(DNS, LOGL_ERROR, "recv error %s during NS-FR-GRE recv\n",
+ strerror(errno));
+ *error = ret;
+ goto out_err;
+ } else if (ret == 0) {
+ *error = ret;
+ goto out_err;
+ }
+
+ msgb_put(msg, ret);
+
+ if (msg->len < sizeof(*iph) + sizeof(*greh) + 2) {
+ LOGP(DNS, LOGL_ERROR, "Short IP packet: %u bytes\n", msg->len);
+ *error = -EIO;
+ goto out_err;
+ }
+
+ iph = (struct iphdr *) msg->data;
+ if (msg->len < (iph->ihl*4 + sizeof(*greh) + 2)) {
+ LOGP(DNS, LOGL_ERROR, "Short IP packet: %u bytes\n", msg->len);
+ *error = -EIO;
+ goto out_err;
+ }
+
+ greh = (struct gre_hdr *) (msg->data + iph->ihl*4);
+ if (greh->flags) {
+ LOGP(DNS, LOGL_NOTICE, "Unknown GRE flags 0x%04x\n",
+ ntohs(greh->flags));
+ }
+
+ switch (ntohs(greh->ptype)) {
+ case GRE_PTYPE_IPv4:
+ /* IPv4 messages might be GRE keepalives */
+ *error = handle_rx_gre_ipv4(bfd, msg, iph, greh);
+ goto out_err;
+ break;
+ case GRE_PTYPE_FR:
+ /* continue as usual */
+ break;
+ default:
+ LOGP(DNS, LOGL_NOTICE, "Unknown GRE protocol 0x%04x != FR\n",
+ ntohs(greh->ptype));
+ *error = -EIO;
+ goto out_err;
+ break;
+ }
+
+ if (msg->len < sizeof(*greh) + 2) {
+ LOGP(DNS, LOGL_ERROR, "Short FR header: %u bytes\n", msg->len);
+ *error = -EIO;
+ goto out_err;
+ }
+
+ frh = (uint8_t *)greh + sizeof(*greh);
+ if (frh[0] & 0x01) {
+ LOGP(DNS, LOGL_NOTICE, "Unsupported single-byte FR address\n");
+ *error = -EIO;
+ goto out_err;
+ }
+ dlci = ((frh[0] & 0xfc) << 2);
+ if ((frh[1] & 0x0f) != 0x01) {
+ LOGP(DNS, LOGL_NOTICE, "Unknown second FR octet 0x%02x\n",
+ frh[1]);
+ *error = -EIO;
+ goto out_err;
+ }
+ dlci |= (frh[1] >> 4);
+
+ msg->l2h = frh+2;
+
+ /* Store DLCI in NETWORK BYTEORDER in sockaddr port member */
+ saddr->sin_port = htons(dlci);
+
+ return msg;
+
+out_err:
+ msgb_free(msg);
+ return NULL;
+}
+
+int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
+ struct sockaddr_in *saddr, enum gprs_ns_ll ll);
+
+static int handle_nsfrgre_read(struct bsc_fd *bfd)
+{
+ int rc;
+ struct sockaddr_in saddr;
+ struct gprs_ns_inst *nsi = bfd->data;
+ struct msgb *msg;
+ uint16_t dlci;
+
+ msg = read_nsfrgre_msg(bfd, &rc, &saddr);
+ if (!msg)
+ return rc;
+
+ dlci = ntohs(saddr.sin_port);
+ if (dlci == 0 || dlci == 1023) {
+ LOGP(DNS, LOGL_INFO, "Received FR on LMI DLCI %u - ignoring\n",
+ dlci);
+ rc = 0;
+ goto out;
+ }
+
+ rc = gprs_ns_rcvmsg(nsi, msg, &saddr, GPRS_NS_LL_FR_GRE);
+out:
+ msgb_free(msg);
+
+ return rc;
+}
+
+static int handle_nsfrgre_write(struct bsc_fd *bfd)
+{
+ /* FIXME: actually send the data here instead of nsip_sendmsg() */
+ return -EIO;
+}
+
+int gprs_ns_frgre_sendmsg(struct gprs_nsvc *nsvc, struct msgb *msg)
+{
+ int rc;
+ struct gprs_ns_inst *nsi = nsvc->nsi;
+ struct sockaddr_in daddr;
+ uint16_t dlci = ntohs(nsvc->frgre.bts_addr.sin_port);
+ uint8_t *frh;
+ struct gre_hdr *greh;
+
+ /* Build socket address for the packet destionation */
+ daddr.sin_family = AF_INET;
+ daddr.sin_addr = nsvc->frgre.bts_addr.sin_addr;
+ daddr.sin_port = IPPROTO_GRE;
+
+ /* Prepend the FR header */
+ frh = msgb_push(msg, 2);
+ frh[0] = (dlci >> 2) & 0xfc;
+ frh[1] = ((dlci & 0xf)<<4) | 0x01;
+
+ /* Prepend the GRE header */
+ greh = (struct gre_hdr *) msgb_push(msg, sizeof(*greh));
+ greh->flags = 0;
+ greh->ptype = htons(GRE_PTYPE_FR);
+
+ rc = sendto(nsi->frgre.fd.fd, msg->data, msg->len, 0,
+ (struct sockaddr *)&daddr, sizeof(daddr));
+
+ talloc_free(msg);
+
+ return rc;
+}
+
+static int nsfrgre_fd_cb(struct bsc_fd *bfd, unsigned int what)
+{
+ int rc = 0;
+
+ if (what & BSC_FD_READ)
+ rc = handle_nsfrgre_read(bfd);
+ if (what & BSC_FD_WRITE)
+ rc = handle_nsfrgre_write(bfd);
+
+ return rc;
+}
+
+int gprs_ns_frgre_listen(struct gprs_ns_inst *nsi)
+{
+ int rc;
+
+ /* Make sure we close any existing socket before changing it */
+ if (nsi->frgre.fd.fd)
+ close(nsi->frgre.fd.fd);
+
+ if (!nsi->frgre.enabled)
+ return 0;
+
+ rc = make_sock(&nsi->frgre.fd, IPPROTO_GRE, nsi->frgre.local_ip,
+ 0, nsfrgre_fd_cb);
+ if (rc < 0) {
+ LOGP(DNS, LOGL_ERROR, "Error creating GRE socket (%s)\n",
+ strerror(errno));
+ return rc;
+ }
+ nsi->frgre.fd.data = nsi;
+
+ return rc;
+}
diff --git a/openbsc/src/gprs/gprs_ns_vty.c b/openbsc/src/gprs/gprs_ns_vty.c
index 8f0628a..e395df7 100644
--- a/openbsc/src/gprs/gprs_ns_vty.c
+++ b/openbsc/src/gprs/gprs_ns_vty.c
@@ -37,9 +37,12 @@
#include <openbsc/signal.h>
#include <openbsc/gprs_ns.h>
#include <openbsc/gprs_bssgp.h>
+#include <openbsc/vty.h>
-#include <vty/vty.h>
-#include <vty/command.h>
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/command.h>
+#include <osmocom/vty/logging.h>
+#include <osmocom/vty/telnet_interface.h>
static struct gprs_ns_inst *vty_nsi = NULL;
@@ -66,6 +69,7 @@
{
struct gprs_nsvc *nsvc;
unsigned int i;
+ struct in_addr ia;
vty_out(vty, "ns%s", VTY_NEWLINE);
@@ -77,7 +81,10 @@
vty_out(vty, " nse %u remote-role %s%s",
nsvc->nsei, nsvc->remote_end_is_sgsn ? "sgsn" : "bss",
VTY_NEWLINE);
- if (nsvc->nsi->ll == GPRS_NS_LL_UDP) {
+ switch (nsvc->ll) {
+ case GPRS_NS_LL_UDP:
+ vty_out(vty, " nse %u encapsulation udp%s", nsvc->nsei,
+ VTY_NEWLINE);
vty_out(vty, " nse %u remote-ip %s%s",
nsvc->nsei,
inet_ntoa(nsvc->ip.bts_addr.sin_addr),
@@ -85,6 +92,19 @@
vty_out(vty, " nse %u remote-port %u%s",
nsvc->nsei, ntohs(nsvc->ip.bts_addr.sin_port),
VTY_NEWLINE);
+ break;
+ case GPRS_NS_LL_FR_GRE:
+ vty_out(vty, " nse %u encapsulation framerelay-gre%s",
+ nsvc->nsei, VTY_NEWLINE);
+ vty_out(vty, " nse %u remote-ip %s%s",
+ nsvc->nsei,
+ inet_ntoa(nsvc->frgre.bts_addr.sin_addr),
+ VTY_NEWLINE);
+ vty_out(vty, " nse %u fr-dlci %u%s",
+ nsvc->nsei, ntohs(nsvc->frgre.bts_addr.sin_port),
+ VTY_NEWLINE);
+ default:
+ break;
}
}
@@ -93,6 +113,23 @@
get_value_string(gprs_ns_timer_strs, i),
vty_nsi->timeout[i], VTY_NEWLINE);
+ if (vty_nsi->nsip.local_ip) {
+ ia.s_addr = htonl(vty_nsi->nsip.local_ip);
+ vty_out(vty, " encapsulation udp local-ip %s%s",
+ inet_ntoa(ia), VTY_NEWLINE);
+ }
+ if (vty_nsi->nsip.local_port)
+ vty_out(vty, " encapsulation udp local-port %u%s",
+ vty_nsi->nsip.local_port, VTY_NEWLINE);
+
+ vty_out(vty, " encapsulation framerelay-gre enabled %u%s",
+ vty_nsi->frgre.enabled ? 1 : 0, VTY_NEWLINE);
+ if (vty_nsi->frgre.local_ip) {
+ ia.s_addr = htonl(vty_nsi->frgre.local_ip);
+ vty_out(vty, " encapsulation framerelay-gre local-ip %s%s",
+ inet_ntoa(ia), VTY_NEWLINE);
+ }
+
return CMD_SUCCESS;
}
@@ -104,25 +141,40 @@
return CMD_SUCCESS;
}
+static void dump_nse(struct vty *vty, struct gprs_nsvc *nsvc, int stats)
+{
+ vty_out(vty, "NSEI %5u, NS-VC %5u, Remote: %-4s, %5s %9s",
+ nsvc->nsei, nsvc->nsvci,
+ nsvc->remote_end_is_sgsn ? "SGSN" : "BSS",
+ nsvc->state & NSE_S_ALIVE ? "ALIVE" : "DEAD",
+ nsvc->state & NSE_S_BLOCKED ? "BLOCKED" : "UNBLOCKED");
+ if (nsvc->ll == GPRS_NS_LL_UDP || nsvc->ll == GPRS_NS_LL_FR_GRE)
+ vty_out(vty, ", %s %15s:%u",
+ nsvc->ll == GPRS_NS_LL_UDP ? "UDP " : "FR-GRE",
+ inet_ntoa(nsvc->ip.bts_addr.sin_addr),
+ ntohs(nsvc->ip.bts_addr.sin_port));
+ vty_out(vty, "%s", VTY_NEWLINE);
+ if (stats)
+ vty_out_rate_ctr_group(vty, " ", nsvc->ctrg);
+}
+
static void dump_ns(struct vty *vty, struct gprs_ns_inst *nsi, int stats)
{
struct gprs_nsvc *nsvc;
+ struct in_addr ia;
+
+ ia.s_addr = htonl(vty_nsi->nsip.local_ip);
+ vty_out(vty, "Encapsulation NS-UDP-IP Local IP: %s, UDP Port: %u%s",
+ inet_ntoa(ia), vty_nsi->nsip.local_port, VTY_NEWLINE);
+
+ ia.s_addr = htonl(vty_nsi->frgre.local_ip);
+ vty_out(vty, "Encapsulation NS-FR-GRE-IP Local IP: %s%s",
+ inet_ntoa(ia), VTY_NEWLINE);
llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
if (nsvc == nsi->unknown_nsvc)
continue;
- vty_out(vty, "NSEI %5u, NS-VC %5u, Remote: %-4s, %5s %9s",
- nsvc->nsei, nsvc->nsvci,
- nsvc->remote_end_is_sgsn ? "SGSN" : "BSS",
- nsvc->state & NSE_S_ALIVE ? "ALIVE" : "DEAD",
- nsvc->state & NSE_S_BLOCKED ? "BLOCKED" : "UNBLOCKED");
- if (nsvc->nsi->ll == GPRS_NS_LL_UDP)
- vty_out(vty, ", %15s:%u",
- inet_ntoa(nsvc->ip.bts_addr.sin_addr),
- ntohs(nsvc->ip.bts_addr.sin_port));
- vty_out(vty, "%s", VTY_NEWLINE);
- if (stats)
- vty_out_rate_ctr_group(vty, " ", nsvc->ctrg);
+ dump_nse(vty, nsvc, stats);
}
}
@@ -144,7 +196,36 @@
return CMD_SUCCESS;
}
-#define NSE_CMD_STR "NS Entity\n" "NS Entity ID (NSEI)\n"
+DEFUN(show_nse, show_nse_cmd, "show ns (nsei|nsvc) <0-65535> [stats]",
+ SHOW_STR "Display information about the NS protocol\n"
+ "Select one NSE by its NSE Identifier\n"
+ "Select one NSE by its NS-VC Identifier\n"
+ "The Identifier of selected type\n"
+ "Include Statistics\n")
+{
+ struct gprs_ns_inst *nsi = vty_nsi;
+ struct gprs_nsvc *nsvc;
+ uint16_t id = atoi(argv[1]);
+ int show_stats = 0;
+
+ if (!strcmp(argv[0], "nsei"))
+ nsvc = nsvc_by_nsei(nsi, id);
+ else
+ nsvc = nsvc_by_nsvci(nsi, id);
+
+ if (!nsvc) {
+ vty_out(vty, "No such NS Entity%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (argc >= 3)
+ show_stats = 1;
+
+ dump_nse(vty, nsvc, show_stats);
+ return CMD_SUCCESS;
+}
+
+#define NSE_CMD_STR "Persistent NS Entity\n" "NS Entity ID (NSEI)\n"
DEFUN(cfg_nse_nsvc, cfg_nse_nsvci_cmd,
"nse <0-65535> nsvci <0-65534>",
@@ -207,11 +288,68 @@
return CMD_WARNING;
}
+ if (nsvc->ll != GPRS_NS_LL_UDP) {
+ vty_out(vty, "Cannot set UDP Port on non-UDP NSE%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
nsvc->ip.bts_addr.sin_port = htons(port);
return CMD_SUCCESS;
}
+DEFUN(cfg_nse_fr_dlci, cfg_nse_fr_dlci_cmd,
+ "nse <0-65535> fr-dlci <16-1007>",
+ NSE_CMD_STR
+ "Frame Relay DLCI\n"
+ "Frame Relay DLCI Number\n")
+{
+ uint16_t nsei = atoi(argv[0]);
+ uint16_t dlci = atoi(argv[1]);
+ struct gprs_nsvc *nsvc;
+
+ nsvc = nsvc_by_nsei(vty_nsi, nsei);
+ if (!nsvc) {
+ vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (nsvc->ll != GPRS_NS_LL_FR_GRE) {
+ vty_out(vty, "Cannot set FR DLCI on non-FR NSE%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ nsvc->frgre.bts_addr.sin_port = htons(dlci);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_nse_encaps, cfg_nse_encaps_cmd,
+ "nse <0-65535> encapsulation (udp|framerelay-gre)",
+ NSE_CMD_STR
+ "Encapsulation for NS\n"
+ "UDP/IP Encapsulation\n" "Frame-Relay/GRE/IP Encapsulation\n")
+{
+ uint16_t nsei = atoi(argv[0]);
+ struct gprs_nsvc *nsvc;
+
+ nsvc = nsvc_by_nsei(vty_nsi, nsei);
+ if (!nsvc) {
+ vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (!strcmp(argv[1], "udp"))
+ nsvc->ll = GPRS_NS_LL_UDP;
+ else
+ nsvc->ll = GPRS_NS_LL_FR_GRE;
+
+ return CMD_SUCCESS;
+}
+
+
DEFUN(cfg_nse_remoterole, cfg_nse_remoterole_cmd,
"nse <0-65535> remote-role (sgsn|bss)",
NSE_CMD_STR
@@ -238,7 +376,7 @@
DEFUN(cfg_no_nse, cfg_no_nse_cmd,
"no nse <0-65535>",
- "Delete NS Entity\n"
+ "Delete Persistent NS Entity\n"
"Delete " NSE_CMD_STR)
{
uint16_t nsei = atoi(argv[0]);
@@ -250,7 +388,13 @@
return CMD_WARNING;
}
- nsvc_delete(nsvc);
+ if (!nsvc->persistent) {
+ vty_out(vty, "NSEI %u is not a persistent NSE%s",
+ nsei, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ nsvc->persistent = 0;
return CMD_SUCCESS;
}
@@ -271,22 +415,157 @@
return CMD_SUCCESS;
}
+#define ENCAPS_STR "NS encapsulation options\n"
+
+DEFUN(cfg_nsip_local_ip, cfg_nsip_local_ip_cmd,
+ "encapsulation udp local-ip A.B.C.D",
+ ENCAPS_STR "NS over UDP Encapsulation\n"
+ "Set the IP address on which we listen for NS/UDP\n"
+ "IP Address\n")
+{
+ struct in_addr ia;
+
+ inet_aton(argv[0], &ia);
+ vty_nsi->nsip.local_ip = ntohl(ia.s_addr);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_nsip_local_port, cfg_nsip_local_port_cmd,
+ "encapsulation udp local-port <0-65535>",
+ ENCAPS_STR "NS over UDP Encapsulation\n"
+ "Set the UDP port on which we listen for NS/UDP\n"
+ "UDP port number\n")
+{
+ unsigned int port = atoi(argv[0]);
+
+ vty_nsi->nsip.local_port = port;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_frgre_local_ip, cfg_frgre_local_ip_cmd,
+ "encapsulation framerelay-gre local-ip A.B.C.D",
+ ENCAPS_STR "NS over Frame Relay over GRE Encapsulation\n"
+ "Set the IP address on which we listen for NS/FR/GRE\n"
+ "IP Address\n")
+{
+ struct in_addr ia;
+
+ if (!vty_nsi->frgre.enabled) {
+ vty_out(vty, "FR/GRE is not enabled%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ inet_aton(argv[0], &ia);
+ vty_nsi->frgre.local_ip = ntohl(ia.s_addr);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_frgre_enable, cfg_frgre_enable_cmd,
+ "encapsulation framerelay-gre enabled (1|0)",
+ ENCAPS_STR "NS over Frame Relay over GRE Encapsulation\n"
+ "Enable or disable Frame Relay over GRE\n"
+ "Enable\n" "Disable\n")
+{
+ int enabled = atoi(argv[0]);
+
+ vty_nsi->frgre.enabled = enabled;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(nsvc_nsei, nsvc_nsei_cmd,
+ "nsvc nsei <0-65535> (block|unblock|reset)",
+ "Perform an operation on a NSVC\n"
+ "NS-VC Identifier (NS-VCI)\n"
+ "Initiate BLOCK procedure\n"
+ "Initiate UNBLOCK procedure\n"
+ "Initiate RESET procedure\n")
+{
+ uint16_t nsvci = atoi(argv[0]);
+ const char *operation = argv[1];
+ struct gprs_nsvc *nsvc;
+
+ nsvc = nsvc_by_nsei(vty_nsi, nsvci);
+ if (!nsvc) {
+ vty_out(vty, "No such NSVCI (%u)%s", nsvci, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (!strcmp(operation, "block"))
+ gprs_ns_tx_block(nsvc, NS_CAUSE_OM_INTERVENTION);
+ else if (!strcmp(operation, "unblock"))
+ gprs_ns_tx_unblock(nsvc);
+ else if (!strcmp(operation, "reset"))
+ gprs_nsvc_reset(nsvc, NS_CAUSE_OM_INTERVENTION);
+ else
+ return CMD_WARNING;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(logging_fltr_nsvc,
+ logging_fltr_nsvc_cmd,
+ "logging filter nsvc (nsei|nsvci) <0-65535>",
+ LOGGING_STR FILTER_STR
+ "Filter based on NS Virtual Connection\n"
+ "Identify NS-VC by NSEI\n"
+ "Identify NS-VC by NSVCI\n"
+ "Numeric identifier\n")
+{
+ struct telnet_connection *conn;
+ struct gprs_nsvc *nsvc;
+ uint16_t id = atoi(argv[1]);
+
+ conn = (struct telnet_connection *) vty->priv;
+ if (!conn->dbg) {
+ vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (!strcmp(argv[0], "nsei"))
+ nsvc = nsvc_by_nsei(vty_nsi, id);
+ else
+ nsvc = nsvc_by_nsvci(vty_nsi, id);
+
+ if (!nsvc) {
+ vty_out(vty, "No NS-VC by that identifier%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ log_set_nsvc_filter(conn->dbg, nsvc);
+ return CMD_SUCCESS;
+}
+
int gprs_ns_vty_init(struct gprs_ns_inst *nsi)
{
vty_nsi = nsi;
install_element_ve(&show_ns_cmd);
install_element_ve(&show_ns_stats_cmd);
+ install_element_ve(&show_nse_cmd);
+ install_element_ve(&logging_fltr_nsvc_cmd);
install_element(CONFIG_NODE, &cfg_ns_cmd);
install_node(&ns_node, config_write_ns);
install_default(NS_NODE);
+ install_element(NS_NODE, &ournode_exit_cmd);
+ install_element(NS_NODE, &ournode_end_cmd);
install_element(NS_NODE, &cfg_nse_nsvci_cmd);
install_element(NS_NODE, &cfg_nse_remoteip_cmd);
install_element(NS_NODE, &cfg_nse_remoteport_cmd);
+ install_element(NS_NODE, &cfg_nse_fr_dlci_cmd);
+ install_element(NS_NODE, &cfg_nse_encaps_cmd);
install_element(NS_NODE, &cfg_nse_remoterole_cmd);
install_element(NS_NODE, &cfg_no_nse_cmd);
install_element(NS_NODE, &cfg_ns_timer_cmd);
+ install_element(NS_NODE, &cfg_nsip_local_ip_cmd);
+ install_element(NS_NODE, &cfg_nsip_local_port_cmd);
+ install_element(NS_NODE, &cfg_frgre_enable_cmd);
+ install_element(NS_NODE, &cfg_frgre_local_ip_cmd);
+
+ install_element(ENABLE_NODE, &nsvc_nsei_cmd);
return 0;
}
diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c
index ba46719..9a76cee 100644
--- a/openbsc/src/gprs/gprs_sgsn.c
+++ b/openbsc/src/gprs/gprs_sgsn.c
@@ -25,13 +25,55 @@
#include <osmocore/linuxlist.h>
#include <osmocore/talloc.h>
#include <osmocore/timer.h>
+#include <osmocore/rate_ctr.h>
#include <openbsc/gsm_subscriber.h>
#include <openbsc/debug.h>
#include <openbsc/gprs_sgsn.h>
#include <openbsc/gprs_ns.h>
#include <openbsc/gprs_bssgp.h>
+#include <openbsc/sgsn.h>
-static LLIST_HEAD(sgsn_mm_ctxts);
+extern struct sgsn_instance *sgsn;
+
+LLIST_HEAD(sgsn_mm_ctxts);
+LLIST_HEAD(sgsn_ggsn_ctxts);
+LLIST_HEAD(sgsn_apn_ctxts);
+LLIST_HEAD(sgsn_pdp_ctxts);
+
+static const struct rate_ctr_desc mmctx_ctr_description[] = {
+ { "sign.packets.in", "Signalling Messages ( In)" },
+ { "sign.packets.out", "Signalling Messages (Out)" },
+ { "udata.packets.in", "User Data Messages ( In)" },
+ { "udata.packets.out", "User Data Messages (Out)" },
+ { "udata.bytes.in", "User Data Bytes ( In)" },
+ { "udata.bytes.out", "User Data Bytes (Out)" },
+ { "pdp_ctx_act", "PDP Context Activations " },
+ { "suspend", "SUSPEND Count " },
+ { "paging.ps", "Paging Packet Switched " },
+ { "paging.cs", "Paging Circuit Switched " },
+ { "ra_update", "Routing Area Update " },
+};
+
+static const struct rate_ctr_group_desc mmctx_ctrg_desc = {
+ .group_name_prefix = "sgsn.mmctx",
+ .group_description = "SGSN MM Context Statistics",
+ .num_ctr = ARRAY_SIZE(mmctx_ctr_description),
+ .ctr_desc = mmctx_ctr_description,
+};
+
+static const struct rate_ctr_desc pdpctx_ctr_description[] = {
+ { "udata.packets.in", "User Data Messages ( In)" },
+ { "udata.packets.out", "User Data Messages (Out)" },
+ { "udata.bytes.in", "User Data Bytes ( In)" },
+ { "udata.bytes.out", "User Data Bytes (Out)" },
+};
+
+static const struct rate_ctr_group_desc pdpctx_ctrg_desc = {
+ .group_name_prefix = "sgsn.pdpctx",
+ .group_description = "SGSN PDP Context Statistics",
+ .num_ctr = ARRAY_SIZE(pdpctx_ctr_description),
+ .ctr_desc = pdpctx_ctr_description,
+};
static int ra_id_equals(const struct gprs_ra_id *id1,
const struct gprs_ra_id *id2)
@@ -45,12 +87,25 @@
const struct gprs_ra_id *raid)
{
struct sgsn_mm_ctx *ctx;
+ int tlli_type;
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
if (tlli == ctx->tlli &&
ra_id_equals(raid, &ctx->ra))
return ctx;
}
+
+ tlli_type = gprs_tlli_type(tlli);
+ if (tlli_type == TLLI_LOCAL) {
+ llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
+ if ((ctx->p_tmsi | 0xC0000000) == tlli ||
+ (ctx->p_tmsi_old && (ctx->p_tmsi_old | 0xC0000000) == tlli)) {
+ ctx->tlli = tlli;
+ return ctx;
+ }
+ }
+ }
+
return NULL;
}
@@ -59,7 +114,8 @@
struct sgsn_mm_ctx *ctx;
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
- if (p_tmsi == ctx->p_tmsi)
+ if (p_tmsi == ctx->p_tmsi ||
+ (ctx->p_tmsi_old && ctx->p_tmsi_old == p_tmsi))
return ctx;
}
return NULL;
@@ -81,16 +137,168 @@
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t tlli,
const struct gprs_ra_id *raid)
{
- struct sgsn_mm_ctx *ctx = talloc_zero(NULL, struct sgsn_mm_ctx);
+ struct sgsn_mm_ctx *ctx;
+ ctx = talloc_zero(tall_bsc_ctx, struct sgsn_mm_ctx);
if (!ctx)
return NULL;
memcpy(&ctx->ra, raid, sizeof(ctx->ra));
ctx->tlli = tlli;
ctx->mm_state = GMM_DEREGISTERED;
+ ctx->ctrg = rate_ctr_group_alloc(ctx, &mmctx_ctrg_desc, tlli);
+ INIT_LLIST_HEAD(&ctx->pdp_list);
llist_add(&ctx->list, &sgsn_mm_ctxts);
return ctx;
}
+
+
+/* look up PDP context by MM context and NSAPI */
+struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_nsapi(const struct sgsn_mm_ctx *mm,
+ uint8_t nsapi)
+{
+ struct sgsn_pdp_ctx *pdp;
+
+ llist_for_each_entry(pdp, &mm->pdp_list, list) {
+ if (pdp->nsapi == nsapi)
+ return pdp;
+ }
+ return NULL;
+}
+
+/* look up PDP context by MM context and transaction ID */
+struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm,
+ uint8_t tid)
+{
+ struct sgsn_pdp_ctx *pdp;
+
+ llist_for_each_entry(pdp, &mm->pdp_list, list) {
+ if (pdp->ti == tid)
+ return pdp;
+ }
+ return NULL;
+}
+
+struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
+ uint8_t nsapi)
+{
+ struct sgsn_pdp_ctx *pdp;
+
+ pdp = sgsn_pdp_ctx_by_nsapi(mm, nsapi);
+ if (pdp)
+ return NULL;
+
+ pdp = talloc_zero(tall_bsc_ctx, struct sgsn_pdp_ctx);
+ if (!pdp)
+ return NULL;
+
+ pdp->mm = mm;
+ pdp->nsapi = nsapi;
+ pdp->ctrg = rate_ctr_group_alloc(pdp, &pdpctx_ctrg_desc, nsapi);
+ llist_add(&pdp->list, &mm->pdp_list);
+ llist_add(&pdp->g_list, &sgsn_pdp_ctxts);
+
+ return pdp;
+}
+
+void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp)
+{
+ llist_del(&pdp->list);
+ llist_del(&pdp->g_list);
+ talloc_free(pdp);
+}
+
+/* GGSN contexts */
+
+struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id)
+{
+ struct sgsn_ggsn_ctx *ggc;
+
+ ggc = talloc_zero(tall_bsc_ctx, struct sgsn_ggsn_ctx);
+ if (!ggc)
+ return NULL;
+
+ ggc->id = id;
+ ggc->gtp_version = 1;
+ /* if we are called from config file parse, this gsn doesn't exist yet */
+ ggc->gsn = sgsn->gsn;
+ llist_add(&ggc->list, &sgsn_ggsn_ctxts);
+
+ return ggc;
+}
+
+struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(uint32_t id)
+{
+ struct sgsn_ggsn_ctx *ggc;
+
+ llist_for_each_entry(ggc, &sgsn_ggsn_ctxts, list) {
+ if (id == ggc->id)
+ return ggc;
+ }
+ return NULL;
+}
+
+struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(uint32_t id)
+{
+ struct sgsn_ggsn_ctx *ggc;
+
+ ggc = sgsn_ggsn_ctx_by_id(id);
+ if (!ggc)
+ ggc = sgsn_ggsn_ctx_alloc(id);
+ return ggc;
+}
+
+/* APN contexts */
+
+#if 0
+struct apn_ctx *apn_ctx_alloc(const char *ap_name)
+{
+ struct apn_ctx *actx;
+
+ actx = talloc_zero(talloc_bsc_ctx, struct apn_ctx);
+ if (!actx)
+ return NULL;
+ actx->name = talloc_strdup(actx, ap_name);
+
+ return actx;
+}
+
+struct apn_ctx *apn_ctx_by_name(const char *name)
+{
+ struct apn_ctx *actx;
+
+ llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
+ if (!strcmp(name, actx->name))
+ return actx;
+ }
+ return NULL;
+}
+
+struct apn_ctx *apn_ctx_find_alloc(const char *name)
+{
+ struct apn_ctx *actx;
+
+ actx = apn_ctx_by_name(name);
+ if (!actx)
+ actx = apn_ctx_alloc(name);
+
+ return actx;
+}
+#endif
+
+uint32_t sgsn_alloc_ptmsi(void)
+{
+ struct sgsn_mm_ctx *mm;
+ uint32_t ptmsi;
+
+restart:
+ ptmsi = rand();
+ llist_for_each_entry(mm, &sgsn_mm_ctxts, list) {
+ if (mm->p_tmsi == ptmsi)
+ goto restart;
+ }
+
+ return ptmsi;
+}
diff --git a/openbsc/src/gprs/gprs_sndcp.c b/openbsc/src/gprs/gprs_sndcp.c
index 0d1a390..8433326 100644
--- a/openbsc/src/gprs/gprs_sndcp.c
+++ b/openbsc/src/gprs/gprs_sndcp.c
@@ -1,6 +1,7 @@
/* GPRS SNDCP protocol implementation as per 3GPP TS 04.65 */
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by On-Waves
*
* All Rights Reserved
*
@@ -32,6 +33,7 @@
#include <openbsc/debug.h>
#include <openbsc/gprs_bssgp.h>
#include <openbsc/gprs_llc.h>
+#include <openbsc/sgsn.h>
/* Chapter 7.2: SN-PDU Formats */
struct sndcp_common_hdr {
@@ -41,10 +43,14 @@
uint8_t type:1;
uint8_t first:1;
uint8_t spare:1;
+} __attribute__((packed));
+
+/* PCOMP / DCOMP only exist in first fragment */
+struct sndcp_comp_hdr {
/* octet 2 */
- uint8_t pcomp;
- uint8_t dcomp;
-};
+ uint8_t pcomp:4;
+ uint8_t dcomp:4;
+} __attribute__((packed));
struct sndcp_udata_hdr {
/* octet 3 */
@@ -52,19 +58,578 @@
uint8_t seg_nr:4;
/* octet 4 */
uint8_t npdu_low;
+} __attribute__((packed));
+
+/* See 6.7.1.2 Reassembly */
+enum sndcp_rx_state {
+ SNDCP_RX_S_FIRST,
+ SNDCP_RX_S_SUBSEQ,
+ SNDCP_RX_S_DISCARD,
};
-/* Entry point for the LL-UNITDATA.indication */
-int sndcp_unitdata_ind(struct msgb *msg, uint8_t sapi, uint8_t *hdr, uint8_t len)
-{
- struct sndcp_udata_hdr *suh;
- uint16_t npdu;
- if (suh->type == 0) {
- LOGP(DGPRS, LOGL_ERROR, "SN-DATA PDU at unitdata_ind() function\n");
+static void *tall_sndcp_ctx;
+
+/* A fragment queue entry, containing one framgent of a N-PDU */
+struct defrag_queue_entry {
+ struct llist_head list;
+ /* segment number of this fragment */
+ uint32_t seg_nr;
+ /* length of the data area of this fragment */
+ uint32_t data_len;
+ /* pointer to the data of this fragment */
+ uint8_t *data;
+};
+
+/* A fragment queue header, maintaining list of fragments for one N-PDU */
+struct defrag_state {
+ /* PDU number for which the defragmentation state applies */
+ uint16_t npdu;
+ /* highest segment number we have received so far */
+ uint8_t highest_seg;
+ /* bitmask of the segments we already have */
+ uint32_t seg_have;
+ /* do we still expect more segments? */
+ unsigned int no_more;
+ /* total length of all segments together */
+ unsigned int tot_len;
+
+ /* linked list of defrag_queue_entry: one for each fragment */
+ struct llist_head frag_list;
+
+ struct timer_list timer;
+};
+
+struct sndcp_entity {
+ struct llist_head list;
+
+ /* reference to the LLC Entity below this SNDCP entity */
+ struct gprs_llc_lle *lle;
+ /* The NSAPI we shall use on top of LLC */
+ uint8_t nsapi;
+
+ /* NPDU number for the GTP->SNDCP side */
+ uint16_t tx_npdu_nr;
+ /* SNDCP eeceiver state */
+ enum sndcp_rx_state rx_state;
+ /* The defragmentation queue */
+ struct defrag_state defrag;
+};
+
+LLIST_HEAD(sndcp_entities);
+
+/* Enqueue a fragment into the defragment queue */
+static int defrag_enqueue(struct sndcp_entity *sne, uint8_t seg_nr,
+ uint32_t data_len, uint8_t *data)
+{
+ struct defrag_queue_entry *dqe;
+
+ dqe = talloc_zero(tall_sndcp_ctx, struct defrag_queue_entry);
+ if (!dqe)
+ return -ENOMEM;
+ dqe->data = talloc_zero_size(dqe, data_len);
+ if (!dqe->data) {
+ talloc_free(dqe);
+ return -ENOMEM;
+ }
+ dqe->seg_nr = seg_nr;
+ dqe->data_len = data_len;
+
+ llist_add(&dqe->list, &sne->defrag.frag_list);
+
+ if (seg_nr > sne->defrag.highest_seg)
+ sne->defrag.highest_seg = seg_nr;
+
+ sne->defrag.seg_have |= (1 << seg_nr);
+ sne->defrag.tot_len += data_len;
+
+ return 0;
+}
+
+/* return if we have all segments of this N-PDU */
+static int defrag_have_all_segments(struct sndcp_entity *sne)
+{
+ uint32_t seg_needed = 0;
+ unsigned int i;
+
+ /* create a bitmask of needed segments */
+ for (i = 0; i < sne->defrag.highest_seg; i++)
+ seg_needed |= (1 << i);
+
+ if (seg_needed == sne->defrag.seg_have)
+ return 1;
+
+ return 0;
+}
+
+static struct defrag_queue_entry *defrag_get_seg(struct sndcp_entity *sne,
+ uint32_t seg_nr)
+{
+ struct defrag_queue_entry *dqe;
+
+ llist_for_each_entry(dqe, &sne->defrag.frag_list, list) {
+ if (dqe->seg_nr == seg_nr) {
+ llist_del(&dqe->list);
+ return dqe;
+ }
+ }
+ return NULL;
+}
+
+static int defrag_segments(struct sndcp_entity *sne)
+{
+ struct msgb *msg;
+ unsigned int seg_nr;
+ uint8_t *npdu;
+
+ msg = msgb_alloc_headroom(sne->defrag.tot_len+256, 128, "SNDCP Defrag");
+ if (!msg)
+ return -ENOMEM;
+
+ /* FIXME: message headers + identifiers */
+
+ npdu = msg->data;
+
+ for (seg_nr = 0; seg_nr < sne->defrag.highest_seg; seg_nr++) {
+ struct defrag_queue_entry *dqe;
+ uint8_t *data;
+
+ dqe = defrag_get_seg(sne, seg_nr);
+ if (!dqe) {
+ LOGP(DSNDCP, LOGL_ERROR, "Segment %u missing\n", seg_nr);
+ talloc_free(msg);
+ return -EIO;
+ }
+ /* actually append the segment to the N-PDU */
+ data = msgb_put(msg, dqe->data_len);
+ memcpy(data, dqe->data, dqe->data_len);
+
+ /* release memory for the fragment queue entry */
+ talloc_free(dqe);
+ }
+
+ /* actually send the N-PDU to the SGSN core code, which then
+ * hands it off to the correct GTP tunnel + GGSN via gtp_data_req() */
+ return sgsn_rx_sndcp_ud_ind(sne->lle->llme->tlli, sne->nsapi, msg,
+ sne->defrag.tot_len, npdu);
+}
+
+static int defrag_input(struct sndcp_entity *sne, struct msgb *msg, uint8_t *hdr)
+{
+ struct sndcp_common_hdr *sch;
+ struct sndcp_comp_hdr *scomph = NULL;
+ struct sndcp_udata_hdr *suh;
+ uint16_t npdu_num;
+ uint8_t *data;
+ int rc;
+
+ sch = (struct sndcp_common_hdr *) hdr;
+ if (sch->first) {
+ scomph = (struct sndcp_comp_hdr *) (hdr + 1);
+ suh = (struct sndcp_udata_hdr *) (hdr + 1 + sizeof(struct sndcp_common_hdr));
+ } else
+ suh = (struct sndcp_udata_hdr *) (hdr + sizeof(struct sndcp_common_hdr));
+
+ data = (uint8_t *)suh + sizeof(struct sndcp_udata_hdr);
+
+ npdu_num = (suh->npdu_high << 8) | suh->npdu_low;
+
+ if (sch->first) {
+ /* first segment of a new packet. Discard all leftover fragments of
+ * previous packet */
+ if (!llist_empty(&sne->defrag.frag_list)) {
+ struct defrag_queue_entry *dqe;
+ LOGP(DSNDCP, LOGL_INFO, "Dropping SN-PDU due to "
+ "insufficient segments\n");
+ llist_for_each_entry(dqe, &sne->defrag.frag_list, list) {
+ llist_del(&dqe->list);
+ talloc_free(dqe);
+ }
+ }
+ /* store the currently de-fragmented PDU number */
+ sne->defrag.npdu = npdu_num;
+ sne->defrag.no_more = sne->defrag.highest_seg = sne->defrag.seg_have = 0;
+ /* FIXME: Start timer */
+ }
+
+ if (sne->defrag.npdu != npdu_num) {
+ LOGP(DSNDCP, LOGL_INFO, "Segment for different SN-PDU "
+ "(%u != %u)\n", npdu_num, sne->defrag.npdu);
+ /* FIXME */
+ }
+
+ /* FIXME: check if seg_nr already exists */
+ rc = defrag_enqueue(sne, suh->seg_nr, (msg->data + msg->len) - data, data);
+ if (rc < 0)
+ return rc;
+
+ if (!sch->more) {
+ /* this is suppsed to be the last segment of the N-PDU, but it
+ * might well be not the last to arrive */
+ sne->defrag.no_more = 1;
+ }
+
+ if (sne->defrag.no_more) {
+ /* we have already received the last segment before, let's check
+ * if all the previous segments exist */
+ if (defrag_have_all_segments(sne))
+ return defrag_segments(sne);
+ }
+
+ return 0;
+}
+
+static struct sndcp_entity *sndcp_entity_by_lle(const struct gprs_llc_lle *lle,
+ uint8_t nsapi)
+{
+ struct sndcp_entity *sne;
+
+ llist_for_each_entry(sne, &sndcp_entities, list) {
+ if (sne->lle == lle && sne->nsapi == nsapi)
+ return sne;
+ }
+ return NULL;
+}
+
+static struct sndcp_entity *sndcp_entity_alloc(struct gprs_llc_lle *lle,
+ uint8_t nsapi)
+{
+ struct sndcp_entity *sne;
+
+ sne = talloc_zero(tall_sndcp_ctx, struct sndcp_entity);
+ if (!sne)
+ return NULL;
+
+ sne->lle = lle;
+ sne->nsapi = nsapi;
+ sne->defrag.timer.data = sne;
+ //sne->fqueue.timer.cb = FIXME;
+ sne->rx_state = SNDCP_RX_S_FIRST;
+
+ llist_add(&sne->list, &sndcp_entities);
+
+ return sne;
+}
+
+/* Entry point for the SNSM-ACTIVATE.indication */
+int sndcp_sm_activate_ind(struct gprs_llc_lle *lle, uint8_t nsapi)
+{
+ LOGP(DSNDCP, LOGL_INFO, "SNSM-ACTIVATE.ind (lle=%p TLLI=%08x, "
+ "SAPI=%u, NSAPI=%u)\n", lle, lle->llme->tlli, lle->sapi, nsapi);
+
+ if (sndcp_entity_by_lle(lle, nsapi)) {
+ LOGP(DSNDCP, LOGL_ERROR, "Trying to ACTIVATE "
+ "already-existing entity (TLLI=%08x, NSAPI=%u)\n",
+ lle->llme->tlli, nsapi);
+ return -EEXIST;
+ }
+
+ if (!sndcp_entity_alloc(lle, nsapi)) {
+ LOGP(DSNDCP, LOGL_ERROR, "Out of memory during ACTIVATE\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+/* Entry point for the SNSM-DEACTIVATE.indication */
+int sndcp_sm_deactivate_ind(struct gprs_llc_lle *lle, uint8_t nsapi)
+{
+ struct sndcp_entity *sne;
+
+ LOGP(DSNDCP, LOGL_INFO, "SNSM-DEACTIVATE.ind (lle=%p, TLLI=%08x, "
+ "SAPI=%u, NSAPI=%u)\n", lle, lle->llme->tlli, lle->sapi, nsapi);
+
+ sne = sndcp_entity_by_lle(lle, nsapi);
+ if (!sne) {
+ LOGP(DSNDCP, LOGL_ERROR, "SNSM-DEACTIVATE.ind for non-"
+ "existing TLLI=%08x SAPI=%u NSAPI=%u\n", lle->llme->tlli,
+ lle->sapi, nsapi);
+ return -ENOENT;
+ }
+ llist_del(&sne->list);
+ /* frag queue entries are hierarchically allocated, so no need to
+ * free them explicitly here */
+ talloc_free(sne);
+
+ return 0;
+}
+
+/* Fragmenter state */
+struct sndcp_frag_state {
+ uint8_t frag_nr;
+ struct msgb *msg; /* original message */
+ uint8_t *next_byte; /* first byte of next fragment */
+
+ struct sndcp_entity *sne;
+ void *mmcontext;
+};
+
+/* returns '1' if there are more fragments to send, '0' if none */
+static int sndcp_send_ud_frag(struct sndcp_frag_state *fs)
+{
+ struct sndcp_entity *sne = fs->sne;
+ struct gprs_llc_lle *lle = sne->lle;
+ struct sndcp_common_hdr *sch;
+ struct sndcp_comp_hdr *scomph;
+ struct sndcp_udata_hdr *suh;
+ struct msgb *fmsg;
+ unsigned int max_payload_len;
+ unsigned int len;
+ uint8_t *data;
+ int rc, more;
+
+ fmsg = msgb_alloc_headroom(fs->sne->lle->params.n201_u+256, 128,
+ "SNDCP Frag");
+ if (!fmsg)
+ return -ENOMEM;
+
+ /* make sure lower layers route the fragment like the original */
+ msgb_tlli(fmsg) = msgb_tlli(fs->msg);
+ msgb_bvci(fmsg) = msgb_bvci(fs->msg);
+ msgb_nsei(fmsg) = msgb_nsei(fs->msg);
+
+ /* prepend common SNDCP header */
+ sch = (struct sndcp_common_hdr *) msgb_put(fmsg, sizeof(*sch));
+ sch->nsapi = sne->nsapi;
+ /* Set FIRST bit if we are the first fragment in a series */
+ if (fs->frag_nr == 0)
+ sch->first = 1;
+ sch->type = 1;
+
+ /* append the compression header for first fragment */
+ if (sch->first) {
+ scomph = (struct sndcp_comp_hdr *)
+ msgb_put(fmsg, sizeof(*scomph));
+ scomph->pcomp = 0;
+ scomph->dcomp = 0;
+ }
+
+ /* append the user-data header */
+ suh = (struct sndcp_udata_hdr *) msgb_put(fmsg, sizeof(*suh));
+ suh->npdu_low = sne->tx_npdu_nr & 0xff;
+ suh->npdu_high = (sne->tx_npdu_nr >> 8) & 0xf;
+ suh->seg_nr = fs->frag_nr % 0xf;
+
+ /* calculate remaining length to be sent */
+ len = (fs->msg->data + fs->msg->len) - fs->next_byte;
+ /* how much payload can we actually send via LLC? */
+ max_payload_len = lle->params.n201_u - (sizeof(*sch) + sizeof(*suh));
+ if (sch->first)
+ max_payload_len -= sizeof(*scomph);
+ /* check if we're exceeding the max */
+ if (len > max_payload_len)
+ len = max_payload_len;
+
+ /* copy the actual fragment data into our fmsg */
+ data = msgb_put(fmsg, len);
+ memcpy(data, fs->next_byte, len);
+
+ /* Increment fragment number and data pointer to next fragment */
+ fs->frag_nr++;
+ fs->next_byte += len;
+
+ /* determine if we have more fragemnts to send */
+ if ((fs->msg->data + fs->msg->len) <= fs->next_byte)
+ more = 0;
+ else
+ more = 1;
+
+ /* set the MORE bit of the SNDCP header accordingly */
+ sch->more = more;
+
+ rc = gprs_llc_tx_ui(fmsg, lle->sapi, 0, fs->mmcontext);
+ if (rc < 0) {
+ /* abort in case of error, do not advance frag_nr / next_byte */
+ msgb_free(fmsg);
+ return rc;
+ }
+
+ if (!more) {
+ /* we've sent all fragments */
+ msgb_free(fs->msg);
+ memset(fs, 0, sizeof(*fs));
+ /* increment NPDU number for next frame */
+ sne->tx_npdu_nr = (sne->tx_npdu_nr + 1) % 0xfff;
+ return 0;
+ }
+
+ /* default: more fragments to send */
+ return 1;
+}
+
+/* Request transmission of a SN-PDU over specified LLC Entity + SAPI */
+int sndcp_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi,
+ void *mmcontext)
+{
+ struct sndcp_entity *sne;
+ struct sndcp_common_hdr *sch;
+ struct sndcp_comp_hdr *scomph;
+ struct sndcp_udata_hdr *suh;
+ struct sndcp_frag_state fs;
+
+ /* Identifiers from UP: (TLLI, SAPI) + (BVCI, NSEI) */
+
+ sne = sndcp_entity_by_lle(lle, nsapi);
+ if (!sne) {
+ LOGP(DSNDCP, LOGL_ERROR, "Cannot find SNDCP Entity\n");
+ return -EIO;
+ }
+
+ /* Check if we need to fragment this N-PDU into multiple SN-PDUs */
+ if (msg->len > lle->params.n201_u -
+ (sizeof(*sch) + sizeof(*suh) + sizeof(*scomph))) {
+ /* initialize the fragmenter state */
+ fs.msg = msg;
+ fs.frag_nr = 0;
+ fs.next_byte = msg->data;
+ fs.sne = sne;
+ fs.mmcontext = mmcontext;
+
+ /* call function to generate and send fragments until all
+ * of the N-PDU has been sent */
+ while (1) {
+ int rc = sndcp_send_ud_frag(&fs);
+ if (rc == 0)
+ return 0;
+ if (rc < 0)
+ return rc;
+ }
+ /* not reached */
+ return 0;
+ }
+
+ /* this is the non-fragmenting case where we only build 1 SN-PDU */
+
+ /* prepend the user-data header */
+ suh = (struct sndcp_udata_hdr *) msgb_push(msg, sizeof(*suh));
+ suh->npdu_low = sne->tx_npdu_nr & 0xff;
+ suh->npdu_high = (sne->tx_npdu_nr >> 8) & 0xf;
+ suh->seg_nr = 0;
+ sne->tx_npdu_nr = (sne->tx_npdu_nr + 1) % 0xfff;
+
+ scomph = (struct sndcp_comp_hdr *) msgb_push(msg, sizeof(*scomph));
+ scomph->pcomp = 0;
+ scomph->dcomp = 0;
+
+ /* prepend common SNDCP header */
+ sch = (struct sndcp_common_hdr *) msgb_push(msg, sizeof(*sch));
+ sch->first = 1;
+ sch->type = 1;
+ sch->nsapi = nsapi;
+
+ return gprs_llc_tx_ui(msg, lle->sapi, 0, mmcontext);
+}
+
+/* Section 5.1.2.17 LL-UNITDATA.ind */
+int sndcp_llunitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t *hdr, uint8_t len)
+{
+ struct sndcp_entity *sne;
+ struct sndcp_common_hdr *sch = (struct sndcp_common_hdr *)hdr;
+ struct sndcp_comp_hdr *scomph = NULL;
+ struct sndcp_udata_hdr *suh;
+ uint8_t *npdu;
+ uint16_t npdu_num;
+ int npdu_len;
+
+ sch = (struct sndcp_common_hdr *) hdr;
+ if (sch->first) {
+ scomph = (struct sndcp_comp_hdr *) (hdr + 1);
+ suh = (struct sndcp_udata_hdr *) (hdr + 1 + sizeof(struct sndcp_common_hdr));
+ } else
+ suh = (struct sndcp_udata_hdr *) (hdr + sizeof(struct sndcp_common_hdr));
+
+ if (sch->type == 0) {
+ LOGP(DSNDCP, LOGL_ERROR, "SN-DATA PDU at unitdata_ind() function\n");
return -EINVAL;
}
- npdu = (suh->npdu_high << 8) | suh->npdu_low;
+ if (len < sizeof(*sch) + sizeof(*suh)) {
+ LOGP(DSNDCP, LOGL_ERROR, "SN-UNITDATA PDU too short (%u)\n", len);
+ return -EIO;
+ }
+
+ sne = sndcp_entity_by_lle(lle, sch->nsapi);
+ if (!sne) {
+ LOGP(DSNDCP, LOGL_ERROR, "Message for non-existing SNDCP Entity "
+ "(lle=%p, TLLI=%08x, SAPI=%u, NSAPI=%u)\n", lle,
+ lle->llme->tlli, lle->sapi, sch->nsapi);
+ return -EIO;
+ }
+
+ if (!sch->first || sch->more) {
+ /* FIXME: implement fragment re-assembly */
+ LOGP(DSNDCP, LOGL_ERROR, "We don't support reassembly yet\n");
+ return -EIO;
+ }
+
+ if (scomph && (scomph->pcomp || scomph->dcomp)) {
+ LOGP(DSNDCP, LOGL_ERROR, "We don't support compression yet\n");
+ return -EIO;
+ }
+
+ npdu_num = (suh->npdu_high << 8) | suh->npdu_low;
+ npdu = (uint8_t *)suh + sizeof(*suh);
+ npdu_len = (msg->data + msg->len) - npdu;
+ if (npdu_len <= 0) {
+ LOGP(DSNDCP, LOGL_ERROR, "Short SNDCP N-PDU: %d\n", npdu_len);
+ return -EIO;
+ }
+ /* actually send the N-PDU to the SGSN core code, which then
+ * hands it off to the correct GTP tunnel + GGSN via gtp_data_req() */
+ return sgsn_rx_sndcp_ud_ind(lle->llme->tlli, sne->nsapi, msg, npdu_len, npdu);
}
+/* Section 5.1.2.1 LL-RESET.ind */
+static int sndcp_ll_reset_ind(struct sndcp_entity *se)
+{
+ /* treat all outstanding SNDCP-LLC request type primitives as not sent */
+ /* reset all SNDCP XID parameters to default values */
+}
+
+static int sndcp_ll_status_ind()
+{
+ /* inform the SM sub-layer by means of SNSM-STATUS.req */
+}
+
+#if 0
+static struct sndcp_state_list {{
+ uint32_t states;
+ unsigned int type;
+ int (*rout)(struct sndcp_entity *se, struct msgb *msg);
+} sndcp_state_list[] = {
+ { ALL_STATES,
+ LL_RESET_IND, sndcp_ll_reset_ind },
+ { ALL_STATES,
+ LL_ESTABLISH_IND, sndcp_ll_est_ind },
+ { SBIT(SNDCP_S_EST_RQD),
+ LL_ESTABLISH_RESP, sndcp_ll_est_ind },
+ { SBIT(SNDCP_S_EST_RQD),
+ LL_ESTABLISH_CONF, sndcp_ll_est_conf },
+ { SBIT(SNDCP_S_
+};
+
+static int sndcp_rx_llc_prim()
+{
+ case LL_ESTABLISH_REQ:
+ case LL_RELEASE_REQ:
+ case LL_XID_REQ:
+ case LL_DATA_REQ:
+ LL_UNITDATA_REQ, /* TLLI, SN-PDU, Ref, QoS, Radio Prio, Ciph */
+
+ switch (prim) {
+ case LL_RESET_IND:
+ case LL_ESTABLISH_IND:
+ case LL_ESTABLISH_RESP:
+ case LL_ESTABLISH_CONF:
+ case LL_RELEASE_IND:
+ case LL_RELEASE_CONF:
+ case LL_XID_IND:
+ case LL_XID_RESP:
+ case LL_XID_CONF:
+ case LL_DATA_IND:
+ case LL_DATA_CONF:
+ case LL_UNITDATA_IND:
+ case LL_STATUS_IND:
+}
+#endif
diff --git a/openbsc/src/gprs/gsm_04_08_gprs.c b/openbsc/src/gprs/gsm_04_08_gprs.c
deleted file mode 100644
index 4a42113..0000000
--- a/openbsc/src/gprs/gsm_04_08_gprs.c
+++ /dev/null
@@ -1,762 +0,0 @@
-/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
- * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
-
-/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <errno.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <openbsc/db.h>
-#include <osmocore/msgb.h>
-#include <osmocore/tlv.h>
-#include <osmocore/gsm_utils.h>
-#include <osmocore/signal.h>
-#include <osmocore/talloc.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/gsm_04_08_gprs.h>
-#include <openbsc/paging.h>
-#include <openbsc/transaction.h>
-#include <openbsc/gprs_bssgp.h>
-#include <openbsc/gprs_llc.h>
-#include <openbsc/gprs_sgsn.h>
-
-/* 10.5.5.14 GPRS MM Cause / Table 10.5.147 */
-struct value_string gmm_cause_names[] = {
- /* FIXME */
- { GMM_CAUSE_SEM_INCORR_MSG, "Semantically incorrect message" },
- { GMM_CAUSE_INV_MAND_INFO, "Invalid mandatory information" },
- { GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL,
- "Message type non-existant or not implemented" },
- { GMM_CAUSE_MSGT_INCOMP_P_STATE,
- "Message type not compatible with protocol state" },
- { GMM_CAUSE_IE_NOTEXIST_NOTIMPL,
- "Information element non-existent or not implemented" },
- { GMM_CAUSE_COND_IE_ERR, "Conditional IE error" },
- { GMM_CAUSE_MSG_INCOMP_P_STATE,
- "Message not compatible with protocol state " },
- { GMM_CAUSE_PROTO_ERR_UNSPEC, "Protocol error, unspecified" },
- { 0, NULL }
-};
-
-/* 10.5.6.6 SM Cause / Table 10.5.157 */
-struct value_string gsm_cause_names[] = {
- { GSM_CAUSE_INSUFF_RSRC, "Insufficient resources" },
- { GSM_CAUSE_MISSING_APN, "Missing or unknown APN" },
- { GSM_CAUSE_UNKNOWN_PDP, "Unknown PDP address or PDP type" },
- { GSM_CAUSE_AUTH_FAILED, "User Authentication failed" },
- { GSM_CAUSE_ACT_REJ_GGSN, "Activation rejected by GGSN" },
- { GSM_CAUSE_ACT_REJ_UNSPEC, "Activation rejected, unspecified" },
- { GSM_CAUSE_SERV_OPT_NOTSUPP, "Service option not supported" },
- { GSM_CAUSE_REQ_SERV_OPT_NOTSUB,
- "Requested service option not subscribed" },
- { GSM_CAUSE_SERV_OPT_TEMP_OOO,
- "Service option temporarily out of order" },
- { GSM_CAUSE_NSAPI_IN_USE, "NSAPI already used" },
- { GSM_CAUSE_DEACT_REGULAR, "Regular deactivation" },
- { GSM_CAUSE_QOS_NOT_ACCEPTED, "QoS not accepted" },
- { GSM_CAUSE_NET_FAIL, "Network Failure" },
- { GSM_CAUSE_REACT_RQD, "Reactivation required" },
- { GSM_CAUSE_FEATURE_NOTSUPP, "Feature not supported " },
- { GSM_CAUSE_INVALID_TRANS_ID, "Invalid transaction identifier" },
- { GSM_CAUSE_SEM_INCORR_MSG, "Semantically incorrect message" },
- { GSM_CAUSE_INV_MAND_INFO, "Invalid mandatory information" },
- { GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL,
- "Message type non-existant or not implemented" },
- { GSM_CAUSE_MSGT_INCOMP_P_STATE,
- "Message type not compatible with protocol state" },
- { GSM_CAUSE_IE_NOTEXIST_NOTIMPL,
- "Information element non-existent or not implemented" },
- { GSM_CAUSE_COND_IE_ERR, "Conditional IE error" },
- { GSM_CAUSE_MSG_INCOMP_P_STATE,
- "Message not compatible with protocol state " },
- { GSM_CAUSE_PROTO_ERR_UNSPEC, "Protocol error, unspecified" },
- { 0, NULL }
-};
-
-static const char *att_name(uint8_t type)
-{
- switch (type) {
- case GPRS_ATT_T_ATTACH:
- return "GPRS attach";
- case GPRS_ATT_T_ATT_WHILE_IMSI:
- return "GPRS attach while IMSI attached";
- case GPRS_ATT_T_COMBINED:
- return "Combined GPRS/IMSI attach";
- default:
- return "unknown";
- }
-}
-
-static const char *upd_name(uint8_t type)
-{
- switch (type) {
- case GPRS_UPD_T_RA:
- return "RA updating";
- case GPRS_UPD_T_RA_LA:
- return "combined RA/LA updating";
- case GPRS_UPD_T_RA_LA_IMSI_ATT:
- return "combined RA/LA updating + IMSI attach";
- case GPRS_UPD_T_PERIODIC:
- return "periodic updating";
- }
- return "unknown";
-}
-
-/* Send a message through the underlying layer */
-static int gsm48_gmm_sendmsg(struct msgb *msg, int command)
-{
- /* caller needs to provide TLLI, BVCI and NSEI */
- return gprs_llc_tx_ui(msg, GPRS_SAPI_GMM, command);
-}
-
-/* copy identifiers from old message to new message, this
- * is required so lower layers can route it correctly */
-static void gmm_copy_id(struct msgb *msg, const struct msgb *old)
-{
- msgb_tlli(msg) = msgb_tlli(old);
- msgb_bvci(msg) = msgb_bvci(old);
- msgb_nsei(msg) = msgb_nsei(old);
-}
-
-static struct gsm48_qos default_qos = {
- .delay_class = 4, /* best effort */
- .reliab_class = GSM48_QOS_RC_LLC_UN_RLC_ACK_DATA_PROT,
- .peak_tput = GSM48_QOS_PEAK_TPUT_32000bps,
- .preced_class = GSM48_QOS_PC_NORMAL,
- .mean_tput = GSM48_QOS_MEAN_TPUT_BEST_EFFORT,
- .traf_class = GSM48_QOS_TC_INTERACTIVE,
- .deliv_order = GSM48_QOS_DO_UNORDERED,
- .deliv_err_sdu = GSM48_QOS_ERRSDU_YES,
- .max_sdu_size = GSM48_QOS_MAXSDU_1520,
- .max_bitrate_up = GSM48_QOS_MBRATE_63k,
- .max_bitrate_down = GSM48_QOS_MBRATE_63k,
- .resid_ber = GSM48_QOS_RBER_5e_2,
- .sdu_err_ratio = GSM48_QOS_SERR_1e_2,
- .handling_prio = 3,
- .xfer_delay = 0x10, /* 200ms */
- .guar_bitrate_up = GSM48_QOS_MBRATE_0k,
- .guar_bitrate_down = GSM48_QOS_MBRATE_0k,
- .sig_ind = 0, /* not optimised for signalling */
- .max_bitrate_down_ext = 0, /* use octet 9 */
- .guar_bitrate_down_ext = 0, /* use octet 13 */
-};
-
-/* Chapter 9.4.2: Attach accept */
-static int gsm48_tx_gmm_att_ack(struct msgb *old_msg)
-{
- struct msgb *msg = gsm48_msgb_alloc();
- struct gsm48_hdr *gh;
- struct gsm48_attach_ack *aa;
- struct gprs_ra_id ra_id;
-
- DEBUGP(DMM, "<- GPRS ATTACH ACCEPT\n");
-
- gmm_copy_id(msg, old_msg);
-
- gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_MM_GPRS;
- gh->msg_type = GSM48_MT_GMM_ATTACH_ACK;
-
- aa = (struct gsm48_attach_ack *) msgb_put(msg, sizeof(*aa));
- aa->force_stby = 0; /* not indicated */
- aa->att_result = 1; /* GPRS only */
- aa->ra_upd_timer = GPRS_TMR_MINUTE | 10;
- aa->radio_prio = 4; /* lowest */
- bssgp_parse_cell_id(&ra_id, msgb_bcid(old_msg));
- gsm48_construct_ra(aa->ra_id.digits, &ra_id);
-
- /* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
- return gsm48_gmm_sendmsg(msg, 0);
-}
-
-/* Chapter 9.4.5: Attach reject */
-static int gsm48_tx_gmm_att_rej(struct msgb *old_msg, uint8_t gmm_cause)
-{
- struct msgb *msg = gsm48_msgb_alloc();
- struct gsm48_hdr *gh;
-
- DEBUGP(DMM, "<- GPRS ATTACH REJECT\n");
-
- gmm_copy_id(msg, old_msg);
-
- gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
- gh->proto_discr = GSM48_PDISC_MM_GPRS;
- gh->msg_type = GSM48_MT_GMM_ATTACH_REJ;
- gh->data[0] = gmm_cause;
-
- return gsm48_gmm_sendmsg(msg, 0);
-}
-
-/* Transmit Chapter 9.4.12 Identity Request */
-static int gsm48_tx_gmm_id_req(struct msgb *old_msg, uint8_t id_type)
-{
- struct msgb *msg = gsm48_msgb_alloc();
- struct gsm48_hdr *gh;
-
- DEBUGP(DMM, "-> GPRS IDENTITY REQUEST: mi_type=%02x\n", id_type);
-
- gmm_copy_id(msg, old_msg);
-
- gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
- gh->proto_discr = GSM48_PDISC_MM_GPRS;
- gh->msg_type = GSM48_MT_GMM_ID_REQ;
- /* 10.5.5.9 ID type 2 + identity type and 10.5.5.7 'force to standby' IE */
- gh->data[0] = id_type & 0xf;
-
- return gsm48_gmm_sendmsg(msg, 0);
-}
-
-/* Check if we can already authorize a subscriber */
-static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx, struct msgb *msg)
-{
- if (strlen(ctx->imei) && strlen(ctx->imsi)) {
- ctx->mm_state = GMM_REGISTERED_NORMAL;
- return gsm48_tx_gmm_att_ack(msg);
- }
- if (!strlen(ctx->imei))
- return gsm48_tx_gmm_id_req(msg, GSM_MI_TYPE_IMEI);
-
- if (!strlen(ctx->imsi))
- return gsm48_tx_gmm_id_req(msg, GSM_MI_TYPE_IMSI);
-
- return 0;
-}
-
-/* Parse Chapter 9.4.13 Identity Response */
-static int gsm48_rx_gmm_id_resp(struct msgb *msg)
-{
- struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
- uint8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
- char mi_string[GSM48_MI_SIZE];
- struct gprs_ra_id ra_id;
- struct sgsn_mm_ctx *ctx;
-
- gsm48_mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
- DEBUGP(DMM, "GMM IDENTITY RESPONSE: mi_type=0x%02x MI(%s) ",
- mi_type, mi_string);
-
- bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
- ctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &ra_id);
- if (!ctx) {
- DEBUGP(DMM, "from unknown TLLI 0x%08x?!?\n", msgb_tlli(msg));
- return -EINVAL;
- }
-
- switch (mi_type) {
- case GSM_MI_TYPE_IMSI:
- /* we already have a mm context with current TLLI, but no
- * P-TMSI / IMSI yet. What we now need to do is to fill
- * this initial context with data from the HLR */
- strncpy(ctx->imsi, mi_string, sizeof(ctx->imei));
- break;
- case GSM_MI_TYPE_IMEI:
- strncpy(ctx->imei, mi_string, sizeof(ctx->imei));
- break;
- case GSM_MI_TYPE_IMEISV:
- break;
- }
-
- DEBUGPC(DMM, "\n");
- /* Check if we can let the mobile station enter */
- return gsm48_gmm_authorize(ctx, msg);
-}
-
-static void attach_rej_cb(void *data)
-{
- struct sgsn_mm_ctx *ctx = data;
-
- /* FIXME: determine through which BTS/TRX to send this */
- //gsm48_tx_gmm_att_rej(ctx->tlli, GMM_CAUSE_MS_ID_NOT_DERIVED);
- ctx->mm_state = GMM_DEREGISTERED;
- /* FIXME: release the context */
-}
-
-static void schedule_reject(struct sgsn_mm_ctx *ctx)
-{
- ctx->T = 3370;
- ctx->timer.cb = attach_rej_cb;
- ctx->timer.data = ctx;
- bsc_schedule_timer(&ctx->timer, 6, 0);
-}
-
-/* Section 9.4.1 Attach request */
-static int gsm48_rx_gmm_att_req(struct msgb *msg)
-{
- struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
- uint8_t *cur = gh->data, *msnc, *mi, *old_ra_info;
- uint8_t msnc_len, att_type, mi_len, mi_type;
- uint16_t drx_par;
- uint32_t tmsi;
- char mi_string[GSM48_MI_SIZE];
- struct gprs_ra_id ra_id;
- uint16_t cid;
- struct sgsn_mm_ctx *ctx;
-
- DEBUGP(DMM, "GMM ATTACH REQUEST ");
-
- /* As per TS 04.08 Chapter 4.7.1.4, the attach request arrives either
- * with a foreign TLLI (P-TMSI that was allocated to the MS before),
- * or with random TLLI. */
-
- cid = bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
-
- /* MS network capability 10.5.5.12 */
- msnc_len = *cur++;
- msnc = cur;
- if (msnc_len > 2)
- goto err_inval;
- cur += msnc_len;
-
- /* aTTACH Type 10.5.5.2 */
- att_type = *cur++ & 0x0f;
-
- /* DRX parameter 10.5.5.6 */
- drx_par = *cur++;
- drx_par |= *cur++ << 8;
-
- /* Mobile Identity (P-TMSI or IMSI) 10.5.1.4 */
- mi_len = *cur++;
- mi = cur;
- if (mi_len > 8)
- goto err_inval;
- mi_type = *mi & GSM_MI_TYPE_MASK;
- cur += mi_len;
-
- gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
-
- DEBUGPC(DMM, "MI(%s) type=\"%s\" ", mi_string, att_name(att_type));
-
- /* Old routing area identification 10.5.5.15 */
- old_ra_info = cur;
- cur += 6;
-
- /* MS Radio Access Capability 10.5.5.12a */
-
- /* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status */
-
- switch (mi_type) {
- case GSM_MI_TYPE_IMSI:
- /* Try to find MM context based on IMSI */
- ctx = sgsn_mm_ctx_by_imsi(mi_string);
- if (!ctx) {
-#if 0
- return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_IMSI_UNKNOWN);
-#else
- /* As a temorary hack, we simply assume that the IMSI exists */
- ctx = sgsn_mm_ctx_alloc(0, &ra_id);
- if (!ctx)
- return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_NET_FAIL);
- strncpy(ctx->imsi, mi_string, sizeof(ctx->imsi));
-#endif
- }
- /* FIXME: Start some timer */
- ctx->mm_state = GMM_COMMON_PROC_INIT;
- ctx->tlli = msgb_tlli(msg);
- break;
- case GSM_MI_TYPE_TMSI:
- tmsi = strtoul(mi_string, NULL, 10);
- /* Try to find MM context based on P-TMSI */
- ctx = sgsn_mm_ctx_by_ptmsi(tmsi);
- if (!ctx) {
- ctx = sgsn_mm_ctx_alloc(msgb_tlli(msg), &ra_id);
- /* FIXME: Start some timer */
- ctx->mm_state = GMM_COMMON_PROC_INIT;
- ctx->tlli = msgb_tlli(msg);
- }
- break;
- default:
- return 0;
- }
- /* Update MM Context with currient RA and Cell ID */
- ctx->ra = ra_id;
- ctx->cell_id = cid;
-
- /* FIXME: allocate a new P-TMSI (+ P-TMSI signature) */
- /* FIXME: update the TLLI with the new local TLLI based on the P-TMSI */
-
- DEBUGPC(DMM, "\n");
-
- return ctx ? gsm48_gmm_authorize(ctx, msg) : 0;
-
-err_inval:
- DEBUGPC(DMM, "\n");
- return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_SEM_INCORR_MSG);
-}
-
-/* Chapter 9.4.15: Routing area update accept */
-static int gsm48_tx_gmm_ra_upd_ack(struct msgb *old_msg)
-{
- struct msgb *msg = gsm48_msgb_alloc();
- struct gsm48_hdr *gh;
- struct gsm48_ra_upd_ack *rua;
- struct gprs_ra_id ra_id;
-
- DEBUGP(DMM, "<- ROUTING AREA UPDATE ACCEPT\n");
-
- gmm_copy_id(msg, old_msg);
-
- gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_MM_GPRS;
- gh->msg_type = GSM48_MT_GMM_RA_UPD_ACK;
-
- rua = (struct gsm48_ra_upd_ack *) msgb_put(msg, sizeof(*rua));
- rua->force_stby = 0; /* not indicated */
- rua->upd_result = 0; /* RA updated */
- rua->ra_upd_timer = GPRS_TMR_MINUTE | 10;
-
- bssgp_parse_cell_id(&ra_id, msgb_bcid(old_msg));
- gsm48_construct_ra(rua->ra_id.digits, &ra_id);
-
- /* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
- return gsm48_gmm_sendmsg(msg, 0);
-}
-
-/* Chapter 9.4.17: Routing area update reject */
-static int gsm48_tx_gmm_ra_upd_rej(struct msgb *old_msg, uint8_t cause)
-{
- struct msgb *msg = gsm48_msgb_alloc();
- struct gsm48_hdr *gh;
-
- DEBUGP(DMM, "<- ROUTING AREA UPDATE REJECT\n");
-
- gmm_copy_id(msg, old_msg);
-
- gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 2);
- gh->proto_discr = GSM48_PDISC_MM_GPRS;
- gh->msg_type = GSM48_MT_GMM_RA_UPD_REJ;
- gh->data[0] = cause;
- gh->data[1] = 0; /* ? */
-
- /* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
- return gsm48_gmm_sendmsg(msg, 0);
-}
-
-/* Chapter 9.4.14: Routing area update request */
-static int gsm48_rx_gmm_ra_upd_req(struct msgb *msg)
-{
- struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
- struct sgsn_mm_ctx *mmctx;
- uint8_t *cur = gh->data;
- struct gprs_ra_id old_ra_id;
- uint8_t upd_type;
-
- /* Update Type 10.5.5.18 */
- upd_type = *cur++ & 0x0f;
-
- DEBUGP(DMM, "GMM RA UPDATE REQUEST type=\"%s\" ", upd_name(upd_type));
-
- /* Old routing area identification 10.5.5.15 */
- gsm48_parse_ra(&old_ra_id, cur);
- cur += 6;
-
- /* MS Radio Access Capability 10.5.5.12a */
-
- /* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status,
- * DRX parameter, MS network capability */
-
- switch (upd_type) {
- case GPRS_UPD_T_RA_LA:
- case GPRS_UPD_T_RA_LA_IMSI_ATT:
- DEBUGPC(DMM, " unsupported in Mode III, is your SI13 corrupt?\n");
- return gsm48_tx_gmm_ra_upd_rej(msg, GMM_CAUSE_PROTO_ERR_UNSPEC);
- break;
- case GPRS_UPD_T_RA:
- case GPRS_UPD_T_PERIODIC:
- break;
- }
-
- /* Look-up the MM context based on old RA-ID and TLLI */
- mmctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &old_ra_id);
- if (!mmctx || mmctx->mm_state == GMM_DEREGISTERED) {
- /* The MS has to perform GPRS attach */
- DEBUGPC(DMM, " REJECT\n");
- return gsm48_tx_gmm_ra_upd_rej(msg, GMM_CAUSE_IMPL_DETACHED);
- }
-
- /* Update the MM context with the new RA-ID */
- bssgp_parse_cell_id(&mmctx->ra, msgb_bcid(msg));
- /* Update the MM context with the new TLLI */
- mmctx->tlli = msgb_tlli(msg);
- /* FIXME: Update the MM context with the MS radio acc capabilities */
- /* FIXME: Update the MM context with the MS network capabilities */
-
- DEBUGPC(DMM, " ACCEPT\n");
- return gsm48_tx_gmm_ra_upd_ack(msg);
-}
-
-static int gsm48_rx_gmm_status(struct msgb *msg)
-{
- struct gsm48_hdr *gh = msgb_l3(msg);
-
- DEBUGP(DMM, "GPRS MM STATUS (cause: %s)\n",
- get_value_string(gmm_cause_names, gh->data[0]));
-
- return 0;
-}
-
-/* GPRS Mobility Management */
-static int gsm0408_rcv_gmm(struct msgb *msg)
-{
- struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
- int rc;
-
- switch (gh->msg_type) {
- case GSM48_MT_GMM_RA_UPD_REQ:
- rc = gsm48_rx_gmm_ra_upd_req(msg);
- break;
- case GSM48_MT_GMM_ATTACH_REQ:
- rc = gsm48_rx_gmm_att_req(msg);
- break;
- case GSM48_MT_GMM_ID_RESP:
- rc = gsm48_rx_gmm_id_resp(msg);
- break;
- case GSM48_MT_GMM_STATUS:
- rc = gsm48_rx_gmm_status(msg);
- break;
- case GSM48_MT_GMM_RA_UPD_COMPL:
- /* only in case SGSN offered new P-TMSI */
- case GSM48_MT_GMM_ATTACH_COMPL:
- /* only in case SGSN offered new P-TMSI */
- case GSM48_MT_GMM_DETACH_REQ:
- case GSM48_MT_GMM_PTMSI_REALL_COMPL:
- case GSM48_MT_GMM_AUTH_CIPH_RESP:
- DEBUGP(DMM, "Unimplemented GSM 04.08 GMM msg type 0x%02x\n",
- gh->msg_type);
- break;
- default:
- DEBUGP(DMM, "Unknown GSM 04.08 GMM msg type 0x%02x\n",
- gh->msg_type);
- break;
- }
-
- return rc;
-}
-
-static void msgb_put_pdp_addr_ipv4(struct msgb *msg, uint32_t ipaddr)
-{
- uint8_t v[6];
-
- v[0] = PDP_TYPE_ORG_IETF;
- v[1] = PDP_TYPE_N_IETF_IPv4;
- *(uint32_t *)(v+2) = htonl(ipaddr);
-
- msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR, sizeof(v), v);
-}
-
-static void msgb_put_pdp_addr_ppp(struct msgb *msg)
-{
- uint8_t v[2];
-
- v[0] = PDP_TYPE_ORG_ETSI;
- v[1] = PDP_TYPE_N_ETSI_PPP;
-
- msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR, sizeof(v), v);
-}
-
-/* Section 9.5.2: Ativate PDP Context Accept */
-static int gsm48_tx_gsm_act_pdp_acc(struct msgb *old_msg, struct gsm48_act_pdp_ctx_req *req)
-{
- struct gsm48_hdr *old_gh = (struct gsm48_hdr *) msgb_gmmh(old_msg);
- struct msgb *msg = gsm48_msgb_alloc();
- struct gsm48_act_pdp_ctx_ack *act_ack;
- struct gsm48_hdr *gh;
- uint8_t transaction_id = ((old_gh->proto_discr >> 4) ^ 0x8); /* flip */
-
- DEBUGP(DMM, "<- ACTIVATE PDP CONTEXT ACK\n");
-
- gmm_copy_id(msg, old_msg);
-
- gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
- gh->msg_type = GSM48_MT_GSM_ACT_PDP_ACK;
-
- /* Negotiated LLC SAPI */
- msgb_v_put(msg, req->req_llc_sapi);
- /* copy QoS parameters from original request */
- msgb_lv_put(msg, sizeof(default_qos), (uint8_t *)&default_qos);
- /* Radio priority 10.5.7.2 */
- msgb_v_put(msg, 4);
- /* PDP address */
- msgb_put_pdp_addr_ipv4(msg, 0x01020304);
- /* Optional: Protocol configuration options */
- /* Optional: Packet Flow Identifier */
-
- return gsm48_gmm_sendmsg(msg, 0);
-}
-
-/* Section 9.5.9: Deactivate PDP Context Accept */
-static int gsm48_tx_gsm_deact_pdp_acc(struct msgb *old_msg)
-{
- struct gsm48_hdr *old_gh = (struct gsm48_hdr *) msgb_gmmh(old_msg);
- struct msgb *msg = gsm48_msgb_alloc();
- struct gsm48_hdr *gh;
- uint8_t transaction_id = ((old_gh->proto_discr >> 4) ^ 0x8); /* flip */
-
- DEBUGP(DMM, "<- DEACTIVATE PDP CONTEXT ACK\n");
-
- gmm_copy_id(msg, old_msg);
-
- gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
- gh->msg_type = GSM48_MT_GSM_DEACT_PDP_ACK;
-
- return gsm48_gmm_sendmsg(msg, 0);
-}
-
-/* Section 9.5.1: Activate PDP Context Request */
-static int gsm48_rx_gsm_act_pdp_req(struct msgb *msg)
-{
- struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
- struct gsm48_act_pdp_ctx_req *act_req = (struct gsm48_act_pdp_ctx_req *) gh->data;
- uint8_t *pdp_addr_lv = act_req->data;
- uint8_t req_qos_len, req_pdpa_len;
- uint8_t *req_qos, *req_pdpa;
- struct tlv_parsed tp;
-
- DEBUGP(DMM, "ACTIVATE PDP CONTEXT REQ: ");
- req_qos_len = act_req->data[0];
- req_qos = act_req->data + 1; /* 10.5.6.5 */
- req_pdpa_len = act_req->data[1 + req_qos_len];
- req_pdpa = act_req->data + 1 + req_qos_len + 1; /* 10.5.6.4 */
-
- switch (req_pdpa[0] & 0xf) {
- case 0x0:
- DEBUGPC(DMM, "ETSI ");
- break;
- case 0x1:
- DEBUGPC(DMM, "IETF ");
- break;
- case 0xf:
- DEBUGPC(DMM, "Empty ");
- break;
- }
-
- switch (req_pdpa[1]) {
- case 0x21:
- DEBUGPC(DMM, "IPv4 ");
- if (req_pdpa_len >= 6) {
- struct in_addr ia;
- ia.s_addr = ntohl(*((uint32_t *) (req_pdpa+2)));
- DEBUGPC(DMM, "%s ", inet_ntoa(ia));
- }
- break;
- case 0x57:
- DEBUGPC(DMM, "IPv6 ");
- if (req_pdpa_len >= 18) {
- /* FIXME: print IPv6 address */
- }
- break;
- default:
- DEBUGPC(DMM, "0x%02x ", req_pdpa[1]);
- break;
- }
-
- /* FIXME: parse TLV for AP name and protocol config options */
- if (TLVP_PRESENT(&tp, GSM48_IE_GSM_APN)) {}
- if (TLVP_PRESENT(&tp, GSM48_IE_GSM_PROTO_CONF_OPT)) {}
-
- return gsm48_tx_gsm_act_pdp_acc(msg, act_req);
-}
-
-/* Section 9.5.8: Deactivate PDP Context Request */
-static int gsm48_rx_gsm_deact_pdp_req(struct msgb *msg)
-{
- struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
-
- DEBUGP(DMM, "DEACTIVATE PDP CONTEXT REQ (cause: %s)\n",
- get_value_string(gsm_cause_names, gh->data[0]));
-
- return gsm48_tx_gsm_deact_pdp_acc(msg);
-}
-
-static int gsm48_rx_gsm_status(struct msgb *msg)
-{
- struct gsm48_hdr *gh = msgb_l3(msg);
-
- DEBUGP(DMM, "GPRS SM STATUS (cause: %s)\n",
- get_value_string(gsm_cause_names, gh->data[0]));
-
- return 0;
-}
-
-/* GPRS Session Management */
-static int gsm0408_rcv_gsm(struct msgb *msg)
-{
- struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
- int rc;
-
- switch (gh->msg_type) {
- case GSM48_MT_GSM_ACT_PDP_REQ:
- rc = gsm48_rx_gsm_act_pdp_req(msg);
- break;
- case GSM48_MT_GSM_DEACT_PDP_REQ:
- rc = gsm48_rx_gsm_deact_pdp_req(msg);
- case GSM48_MT_GSM_STATUS:
- rc = gsm48_rx_gsm_status(msg);
- break;
- case GSM48_MT_GSM_REQ_PDP_ACT_REJ:
- case GSM48_MT_GSM_ACT_AA_PDP_REQ:
- case GSM48_MT_GSM_DEACT_AA_PDP_REQ:
- DEBUGP(DMM, "Unimplemented GSM 04.08 GSM msg type 0x%02x\n",
- gh->msg_type);
- break;
- default:
- DEBUGP(DMM, "Unknown GSM 04.08 GSM msg type 0x%02x\n",
- gh->msg_type);
- break;
-
- }
-
- return rc;
-}
-
-/* Main entry point for incoming 04.08 GPRS messages */
-int gsm0408_gprs_rcvmsg(struct msgb *msg)
-{
- struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
- uint8_t pdisc = gh->proto_discr & 0x0f;
- int rc = -EINVAL;
-
- switch (pdisc) {
- case GSM48_PDISC_MM_GPRS:
- rc = gsm0408_rcv_gmm(msg);
- break;
- case GSM48_PDISC_SM_GPRS:
- rc = gsm0408_rcv_gsm(msg);
- break;
- default:
- DEBUGP(DMM, "Unknown GSM 04.08 discriminator 0x%02x\n",
- pdisc);
- break;
- }
-
- return rc;
-}
diff --git a/openbsc/src/gprs/osmo_gbproxy.cfg b/openbsc/src/gprs/osmo_gbproxy.cfg
index d51b04a..d6b5619 100644
--- a/openbsc/src/gprs/osmo_gbproxy.cfg
+++ b/openbsc/src/gprs/osmo_gbproxy.cfg
@@ -1,13 +1,24 @@
!
-! OpenBSC configuration saved from vty
-! !
+! Osmocom Gb Proxy (0.9.0.404-6463) configuration saved from vty
+!!
!
line vty
no login
!
gbproxy
- nsip bss local port 23000
- nsip sgsn remote ip 127.0.0.1
- nsip sgsn remote port 7777
- nsip sgsn nsei 101
- nsip sgsn nsvci 101
+ sgsn nsei 101
+ns
+ nse 101 nsvci 101
+ nse 101 remote-role sgsn
+ nse 101 encapsulation udp
+ nse 101 remote-ip 192.168.100.239
+ nse 101 remote-port 7777
+ timer tns-block 3
+ timer tns-block-retries 3
+ timer tns-reset 3
+ timer tns-reset-retries 3
+ timer tns-test 30
+ timer tns-alive 3
+ timer tns-alive-retries 10
+ encapsulation framerelay-gre enabled 1
+ encapsulation framerelay-gre local-ip 0.0.0.0
diff --git a/openbsc/src/gprs/osmo_sgsn.cfg b/openbsc/src/gprs/osmo_sgsn.cfg
index f39e853..c4c9ec1 100644
--- a/openbsc/src/gprs/osmo_sgsn.cfg
+++ b/openbsc/src/gprs/osmo_sgsn.cfg
@@ -1,9 +1,23 @@
!
-! OpenBSC configuration saved from vty
-! !
+! Osmocom SGSN (0.9.0.474-0ede2) configuration saved from vty
+!!
!
line vty
no login
!
sgsn
- nsip local port 23000
+ gtp local-ip 192.168.100.11
+ ggsn 0 remote-ip 192.168.100.239
+ ggsn 0 gtp-version 1
+ns
+ timer tns-block 3
+ timer tns-block-retries 3
+ timer tns-reset 3
+ timer tns-reset-retries 3
+ timer tns-test 30
+ timer tns-alive 3
+ timer tns-alive-retries 10
+ encapsulation udp local-ip 192.168.100.11
+ encapsulation udp local-port 23000
+ encapsulation framerelay-gre enabled 0
+bssgp
diff --git a/openbsc/src/gprs/sgsn_libgtp.c b/openbsc/src/gprs/sgsn_libgtp.c
new file mode 100644
index 0000000..0eface3
--- /dev/null
+++ b/openbsc/src/gprs/sgsn_libgtp.c
@@ -0,0 +1,557 @@
+/* GPRS SGSN integration with libgtp of OpenGGSN */
+/* libgtp implements the GPRS Tunelling Protocol GTP per TS 09.60 / 29.060 */
+
+/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by On Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <osmocore/talloc.h>
+#include <osmocore/select.h>
+#include <osmocore/rate_ctr.h>
+#include <openbsc/gsm_04_08_gprs.h>
+
+#include <openbsc/signal.h>
+#include <openbsc/debug.h>
+#include <openbsc/sgsn.h>
+#include <openbsc/gprs_llc.h>
+#include <openbsc/gprs_bssgp.h>
+#include <openbsc/gprs_sgsn.h>
+#include <openbsc/gprs_gmm.h>
+
+#include <gtp.h>
+#include <pdp.h>
+
+const struct value_string gtp_cause_strs[] = {
+ { GTPCAUSE_REQ_IMSI, "Request IMSI" },
+ { GTPCAUSE_REQ_IMEI, "Request IMEI" },
+ { GTPCAUSE_REQ_IMSI_IMEI, "Request IMSI and IMEI" },
+ { GTPCAUSE_NO_ID_NEEDED, "No identity needed" },
+ { GTPCAUSE_MS_REFUSES_X, "MS refuses" },
+ { GTPCAUSE_MS_NOT_RESP_X, "MS is not GPRS responding" },
+ { GTPCAUSE_ACC_REQ, "Request accepted" },
+ { GTPCAUSE_NON_EXIST, "Non-existent" },
+ { GTPCAUSE_INVALID_MESSAGE, "Invalid message format" },
+ { GTPCAUSE_IMSI_NOT_KNOWN, "IMSI not known" },
+ { GTPCAUSE_MS_DETACHED, "MS is GPRS detached" },
+ { GTPCAUSE_MS_NOT_RESP, "MS is not GPRS responding" },
+ { GTPCAUSE_MS_REFUSES, "MS refuses" },
+ { GTPCAUSE_NO_RESOURCES, "No resources available" },
+ { GTPCAUSE_NOT_SUPPORTED, "Service not supported" },
+ { GTPCAUSE_MAN_IE_INCORRECT, "Mandatory IE incorrect" },
+ { GTPCAUSE_MAN_IE_MISSING, "Mandatory IE missing" },
+ { GTPCAUSE_OPT_IE_INCORRECT, "Optional IE incorrect" },
+ { GTPCAUSE_SYS_FAIL, "System failure" },
+ { GTPCAUSE_ROAMING_REST, "Roaming restrictions" },
+ { GTPCAUSE_PTIMSI_MISMATCH, "P-TMSI Signature mismatch" },
+ { GTPCAUSE_CONN_SUSP, "GPRS connection suspended" },
+ { GTPCAUSE_AUTH_FAIL, "Authentication failure" },
+ { GTPCAUSE_USER_AUTH_FAIL, "User authentication failed" },
+ { GTPCAUSE_CONTEXT_NOT_FOUND, "Context not found" },
+ { GTPCAUSE_ADDR_OCCUPIED, "All dynamic PDP addresses occupied" },
+ { GTPCAUSE_NO_MEMORY, "No memory is available" },
+ { GTPCAUSE_RELOC_FAIL, "Relocation failure" },
+ { GTPCAUSE_UNKNOWN_MAN_EXTHEADER, "Unknown mandatory ext. header" },
+ { GTPCAUSE_SEM_ERR_TFT, "Semantic error in TFT operation" },
+ { GTPCAUSE_SYN_ERR_TFT, "Syntactic error in TFT operation" },
+ { GTPCAUSE_SEM_ERR_FILTER, "Semantic errors in packet filter" },
+ { GTPCAUSE_SYN_ERR_FILTER, "Syntactic errors in packet filter" },
+ { GTPCAUSE_MISSING_APN, "Missing or unknown APN" },
+ { GTPCAUSE_UNKNOWN_PDP, "Unknown PDP address or PDP type" },
+ { 0, NULL }
+};
+
+/* generate a PDP context based on the IE's from the 04.08 message,
+ * and send the GTP create pdp context request to the GGSN */
+struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
+ struct sgsn_mm_ctx *mmctx,
+ uint16_t nsapi,
+ struct tlv_parsed *tp)
+{
+ struct sgsn_pdp_ctx *pctx;
+ struct pdp_t *pdp;
+ uint64_t imsi_ui64 = 0;
+ int rc;
+
+ LOGP(DGPRS, LOGL_ERROR, "Create PDP Context\n");
+ pctx = sgsn_pdp_ctx_alloc(mmctx, nsapi);
+ if (!pctx) {
+ LOGP(DGPRS, LOGL_ERROR, "Couldn't allocate PDP Ctx\n");
+ return NULL;
+ }
+
+ rc = pdp_newpdp(&pdp, imsi_ui64, nsapi, NULL);
+ if (rc) {
+ LOGP(DGPRS, LOGL_ERROR, "Out of libgtp PDP Contexts\n");
+ return NULL;
+ }
+ pdp->priv = pctx;
+ pctx->lib = pdp;
+ pctx->ggsn = ggsn;
+
+ //pdp->peer = /* sockaddr_in of GGSN (receive) */
+ //pdp->ipif = /* not used by library */
+ pdp->version = ggsn->gtp_version;
+ pdp->hisaddr0 = ggsn->remote_addr;
+ pdp->hisaddr1 = ggsn->remote_addr;
+ //pdp->cch_pdp = 512; /* Charging Flat Rate */
+
+ /* MS provided APN, subscription not verified */
+ pdp->selmode = 0x01;
+
+ /* IMSI, TEID/TEIC, FLLU/FLLC, TID, NSAPI set in pdp_newpdp */
+
+ /* FIXME: MSISDN in BCD format from mmctx */
+ //pdp->msisdn.l/.v
+
+ /* End User Address from GMM requested PDP address */
+ pdp->eua.l = TLVP_LEN(tp, OSMO_IE_GSM_REQ_PDP_ADDR);
+ if (pdp->eua.l > sizeof(pdp->eua.v))
+ pdp->eua.l = sizeof(pdp->eua.v);
+ memcpy(pdp->eua.v, TLVP_VAL(tp, OSMO_IE_GSM_REQ_PDP_ADDR),
+ pdp->eua.l);
+ /* Highest 4 bits of first byte need to be set to 1, otherwise
+ * the IE is identical with the 04.08 PDP Address IE */
+ pdp->eua.v[0] |= 0xf0;
+
+ /* APN name from GMM */
+ pdp->apn_use.l = TLVP_LEN(tp, GSM48_IE_GSM_APN);
+ if (pdp->apn_use.l > sizeof(pdp->apn_use.v))
+ pdp->apn_use.l = sizeof(pdp->apn_use.v);
+ memcpy(pdp->apn_use.v, TLVP_VAL(tp, GSM48_IE_GSM_APN),
+ pdp->apn_use.l);
+
+ /* Protocol Configuration Options from GMM */
+ pdp->pco_req.l = TLVP_LEN(tp, GSM48_IE_GSM_PROTO_CONF_OPT);
+ if (pdp->pco_req.l > sizeof(pdp->pco_req.v))
+ pdp->pco_req.l = sizeof(pdp->pco_req.v);
+ memcpy(pdp->pco_req.v, TLVP_VAL(tp, GSM48_IE_GSM_PROTO_CONF_OPT),
+ pdp->pco_req.l);
+
+ /* QoS options from GMM */
+ pdp->qos_req.l = TLVP_LEN(tp, OSMO_IE_GSM_REQ_QOS);
+ if (pdp->qos_req.l > sizeof(pdp->qos_req.v))
+ pdp->qos_req.l = sizeof(pdp->qos_req.v);
+ memcpy(pdp->qos_req.v, TLVP_VAL(tp, OSMO_IE_GSM_REQ_QOS),
+ pdp->qos_req.l);
+
+ /* SGSN address for control plane */
+ pdp->gsnlc.l = sizeof(sgsn->cfg.gtp_listenaddr.sin_addr);
+ memcpy(pdp->gsnlc.v, &sgsn->cfg.gtp_listenaddr.sin_addr,
+ sizeof(sgsn->cfg.gtp_listenaddr.sin_addr));
+
+ /* SGSN address for user plane */
+ pdp->gsnlu.l = sizeof(sgsn->cfg.gtp_listenaddr.sin_addr);
+ memcpy(pdp->gsnlu.v, &sgsn->cfg.gtp_listenaddr.sin_addr,
+ sizeof(sgsn->cfg.gtp_listenaddr.sin_addr));
+
+ /* change pdp state to 'requested' */
+ pctx->state = PDP_STATE_CR_REQ;
+
+ rc = gtp_create_context_req(ggsn->gsn, pdp, pctx);
+ /* FIXME */
+
+ return pctx;
+}
+
+int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx)
+{
+ LOGP(DGPRS, LOGL_ERROR, "Delete PDP Context\n");
+
+ /* FIXME: decide if we need teardown or not ! */
+ return gtp_delete_context_req(pctx->ggsn->gsn, pctx->lib, pctx, 1);
+}
+
+struct cause_map {
+ uint8_t cause_in;
+ uint8_t cause_out;
+};
+
+static uint8_t cause_map(const struct cause_map *map, uint8_t in, uint8_t deflt)
+{
+ const struct cause_map *m;
+
+ for (m = map; m->cause_in && m->cause_out; m++) {
+ if (m->cause_in == in)
+ return m->cause_out;
+ }
+ return deflt;
+}
+
+/* how do we map from gtp cause to SM cause */
+static const struct cause_map gtp2sm_cause_map[] = {
+ { GTPCAUSE_NO_RESOURCES, GSM_CAUSE_INSUFF_RSRC },
+ { GTPCAUSE_NOT_SUPPORTED, GSM_CAUSE_SERV_OPT_NOTSUPP },
+ { GTPCAUSE_MAN_IE_INCORRECT, GSM_CAUSE_INV_MAND_INFO },
+ { GTPCAUSE_MAN_IE_MISSING, GSM_CAUSE_INV_MAND_INFO },
+ { GTPCAUSE_OPT_IE_INCORRECT, GSM_CAUSE_PROTO_ERR_UNSPEC },
+ { GTPCAUSE_SYS_FAIL, GSM_CAUSE_NET_FAIL },
+ { GTPCAUSE_ROAMING_REST, GSM_CAUSE_REQ_SERV_OPT_NOTSUB },
+ { GTPCAUSE_PTIMSI_MISMATCH, GSM_CAUSE_PROTO_ERR_UNSPEC },
+ { GTPCAUSE_CONN_SUSP, GSM_CAUSE_PROTO_ERR_UNSPEC },
+ { GTPCAUSE_AUTH_FAIL, GSM_CAUSE_AUTH_FAILED },
+ { GTPCAUSE_USER_AUTH_FAIL, GSM_CAUSE_ACT_REJ_GGSN },
+ { GTPCAUSE_CONTEXT_NOT_FOUND, GSM_CAUSE_PROTO_ERR_UNSPEC },
+ { GTPCAUSE_ADDR_OCCUPIED, GSM_CAUSE_INSUFF_RSRC },
+ { GTPCAUSE_NO_MEMORY, GSM_CAUSE_INSUFF_RSRC },
+ { GTPCAUSE_RELOC_FAIL, GSM_CAUSE_PROTO_ERR_UNSPEC },
+ { GTPCAUSE_UNKNOWN_MAN_EXTHEADER, GSM_CAUSE_PROTO_ERR_UNSPEC },
+ { GTPCAUSE_MISSING_APN, GSM_CAUSE_MISSING_APN },
+ { GTPCAUSE_UNKNOWN_PDP, GSM_CAUSE_UNKNOWN_PDP },
+ { 0, 0 }
+};
+
+/* The GGSN has confirmed the creation of a PDP Context */
+static int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
+{
+ struct sgsn_pdp_ctx *pctx = cbp;
+ uint8_t reject_cause;
+ int rc;
+
+ DEBUGP(DGPRS, "Received CREATE PDP CTX CONF, cause=%d(%s)\n",
+ cause, get_value_string(gtp_cause_strs, cause));
+
+ /* Check for cause value if it was really successful */
+ if (cause < 0) {
+ LOGP(DGPRS, LOGL_NOTICE, "Create PDP ctx req timed out\n");
+ if (pdp && pdp->version == 1) {
+ pdp->version = 0;
+ gtp_create_context_req(sgsn->gsn, pdp, cbp);
+ return 0;
+ } else {
+ reject_cause = GSM_CAUSE_NET_FAIL;
+ goto reject;
+ }
+ }
+
+ /* Check for cause value if it was really successful */
+ if (cause != GTPCAUSE_ACC_REQ) {
+ reject_cause = cause_map(gtp2sm_cause_map, cause,
+ GSM_CAUSE_ACT_REJ_GGSN);
+ goto reject;
+ }
+
+ /* Activate the SNDCP layer */
+ sndcp_sm_activate_ind(&pctx->mm->llme->lle[pctx->sapi], pctx->nsapi);
+
+ /* Send PDP CTX ACT to MS */
+ return gsm48_tx_gsm_act_pdp_acc(pctx);
+
+reject:
+ pctx->state = PDP_STATE_NONE;
+ if (pdp)
+ pdp_freepdp(pdp);
+ /* Send PDP CTX ACT REJ to MS */
+ rc = gsm48_tx_gsm_act_pdp_rej(pctx->mm, pctx->ti, reject_cause,
+ 0, NULL);
+ sgsn_pdp_ctx_free(pctx);
+
+ return EOF;
+}
+
+/* Confirmation of a PDP Context Delete */
+static int delete_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
+{
+ struct sgsn_pdp_ctx *pctx = cbp;
+ int rc;
+
+ DEBUGP(DGPRS, "Received DELETE PDP CTX CONF, cause=%d(%s)\n",
+ cause, get_value_string(gtp_cause_strs, cause));
+
+ /* Confirm deactivation of PDP context to MS */
+ rc = gsm48_tx_gsm_deact_pdp_acc(pctx);
+
+ sgsn_pdp_ctx_free(pctx);
+
+ return rc;
+}
+
+/* Confirmation of an GTP ECHO request */
+static int echo_conf(int recovery)
+{
+ if (recovery < 0) {
+ DEBUGP(DGPRS, "GTP Echo Request timed out\n");
+ /* FIXME: if version == 1, retry with version 0 */
+ } else {
+ DEBUGP(DGPRS, "GTP Rx Echo Response\n");
+ }
+ return 0;
+}
+
+/* libgtp callback for confirmations */
+static int cb_conf(int type, int cause, struct pdp_t *pdp, void *cbp)
+{
+ DEBUGP(DGPRS, "libgtp cb_conf(type=%d, cause=%d, pdp=%p, cbp=%p)\n",
+ type, cause, pdp, cbp);
+
+ if (cause == EOF)
+ LOGP(DGPRS, LOGL_ERROR, "libgtp EOF (type=%u, pdp=%p, cbp=%p)\n",
+ type, pdp, cbp);
+
+ switch (type) {
+ case GTP_ECHO_REQ:
+ return echo_conf(cause);
+ case GTP_CREATE_PDP_REQ:
+ return create_pdp_conf(pdp, cbp, cause);
+ case GTP_DELETE_PDP_REQ:
+ return delete_pdp_conf(pdp, cbp, cause);
+ default:
+ break;
+ }
+ return 0;
+}
+
+/* Called whenever a PDP context is deleted for any reason */
+static int cb_delete_context(struct pdp_t *pdp)
+{
+ LOGP(DGPRS, LOGL_INFO, "PDP Context was deleted\n");
+ return 0;
+}
+
+/* Called when we receive a Version Not Supported message */
+static int cb_unsup_ind(struct sockaddr_in *peer)
+{
+ LOGP(DGPRS, LOGL_INFO, "GTP Version not supported Indication "
+ "from %s:%u\n", inet_ntoa(peer->sin_addr),
+ ntohs(peer->sin_port));
+ return 0;
+}
+
+/* Called when we receive a Supported Ext Headers Notification */
+static int cb_extheader_ind(struct sockaddr_in *peer)
+{
+ LOGP(DGPRS, LOGL_INFO, "GTP Supported Ext Headers Noficiation "
+ "from %s:%u\n", inet_ntoa(peer->sin_addr),
+ ntohs(peer->sin_port));
+ return 0;
+}
+
+/* Called whenever we recive a DATA packet */
+static int cb_data_ind(struct pdp_t *lib, void *packet, unsigned int len)
+{
+ struct bssgp_paging_info pinfo;
+ struct sgsn_pdp_ctx *pdp;
+ struct sgsn_mm_ctx *mm;
+ struct msgb *msg;
+ uint8_t *ud;
+ int rc;
+
+ DEBUGP(DGPRS, "GTP DATA IND from GGSN, length=%u\n", len);
+
+ pdp = lib->priv;
+ if (!pdp) {
+ DEBUGP(DGPRS, "GTP DATA IND from GGSN for unknown PDP\n");
+ return -EIO;
+ }
+ mm = pdp->mm;
+
+ msg = msgb_alloc_headroom(len+256, 128, "GTP->SNDCP");
+ ud = msgb_put(msg, len);
+ memcpy(ud, packet, len);
+
+ msgb_tlli(msg) = mm->tlli;
+ msgb_bvci(msg) = mm->bvci;
+ msgb_nsei(msg) = mm->nsei;
+
+ switch (mm->mm_state) {
+ case GMM_REGISTERED_SUSPENDED:
+ /* initiate PS PAGING procedure */
+ memset(&pinfo, 0, sizeof(pinfo));
+ pinfo.mode = BSSGP_PAGING_PS;
+ pinfo.scope = BSSGP_PAGING_BVCI;
+ pinfo.bvci = mm->bvci;
+ pinfo.imsi = mm->imsi;
+ pinfo.ptmsi = mm->p_tmsi;
+ pinfo.drx_params = mm->drx_parms;
+ pinfo.qos[0] = 0; // FIXME
+ rc = gprs_bssgp_tx_paging(mm->nsei, 0, &pinfo);
+ rate_ctr_inc(&mm->ctrg->ctr[GMM_CTR_PAGING_PS]);
+ /* FIXME: queue the packet we received from GTP */
+ break;
+ case GMM_REGISTERED_NORMAL:
+ break;
+ default:
+ LOGP(DGPRS, LOGL_ERROR, "GTP DATA IND for TLLI %08X in state "
+ "%u\n", mm->tlli, mm->mm_state);
+ msgb_free(msg);
+ return -1;
+ }
+
+ rate_ctr_inc(&pdp->ctrg->ctr[PDP_CTR_PKTS_UDATA_OUT]);
+ rate_ctr_add(&pdp->ctrg->ctr[PDP_CTR_BYTES_UDATA_OUT], len);
+ rate_ctr_inc(&mm->ctrg->ctr[GMM_CTR_PKTS_UDATA_OUT]);
+ rate_ctr_add(&mm->ctrg->ctr[GMM_CTR_BYTES_UDATA_OUT], len);
+
+ return sndcp_unitdata_req(msg, &mm->llme->lle[pdp->sapi],
+ pdp->nsapi, mm);
+}
+
+/* Called by SNDCP when it has received/re-assembled a N-PDU */
+int sgsn_rx_sndcp_ud_ind(uint32_t tlli, uint8_t nsapi, struct msgb *msg,
+ uint32_t npdu_len, uint8_t *npdu)
+{
+ struct sgsn_mm_ctx *mmctx;
+ struct sgsn_pdp_ctx *pdp;
+ struct gprs_ra_id ra_id;
+
+ /* look-up the MM context for this message */
+ bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
+ mmctx = sgsn_mm_ctx_by_tlli(tlli, &ra_id);
+ if (!mmctx) {
+ LOGP(DGPRS, LOGL_ERROR,
+ "Cannot find MM CTX for TLLI %08x\n", tlli);
+ return -EIO;
+ }
+ /* look-up the PDP context for this message */
+ pdp = sgsn_pdp_ctx_by_nsapi(mmctx, nsapi);
+ if (!pdp) {
+ LOGP(DGPRS, LOGL_ERROR, "Cannot find PDP CTX for "
+ "TLLI=%08x, NSAPI=%u\n", tlli, nsapi);
+ return -EIO;
+ }
+ if (!pdp->lib) {
+ LOGP(DGPRS, LOGL_ERROR, "PDP CTX without libgtp\n");
+ return -EIO;
+ }
+
+ rate_ctr_inc(&pdp->ctrg->ctr[PDP_CTR_PKTS_UDATA_IN]);
+ rate_ctr_add(&pdp->ctrg->ctr[PDP_CTR_BYTES_UDATA_IN], npdu_len);
+ rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PKTS_UDATA_IN]);
+ rate_ctr_add(&mmctx->ctrg->ctr[GMM_CTR_BYTES_UDATA_IN], npdu_len);
+
+ return gtp_data_req(pdp->ggsn->gsn, pdp->lib, npdu, npdu_len);
+
+ return gtp_data_req(pdp->ggsn->gsn, pdp->lib, npdu, npdu_len);
+}
+
+/* libgtp select loop integration */
+static int sgsn_gtp_fd_cb(struct bsc_fd *fd, unsigned int what)
+{
+ struct sgsn_instance *sgi = fd->data;
+ int rc;
+
+ if (!(what & BSC_FD_READ))
+ return 0;
+
+ switch (fd->priv_nr) {
+ case 0:
+ rc = gtp_decaps0(sgi->gsn);
+ break;
+ case 1:
+ rc = gtp_decaps1c(sgi->gsn);
+ break;
+ case 2:
+ rc = gtp_decaps1u(sgi->gsn);
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+ return rc;
+}
+
+static void sgsn_gtp_tmr_start(struct sgsn_instance *sgi)
+{
+ struct timeval next;
+
+ /* Retrieve next retransmission as struct timeval */
+ gtp_retranstimeout(sgi->gsn, &next);
+
+ /* re-schedule the timer */
+ bsc_schedule_timer(&sgi->gtp_timer, next.tv_sec, next.tv_usec/1000);
+}
+
+/* timer callback for libgtp retransmissions and ping */
+static void sgsn_gtp_tmr_cb(void *data)
+{
+ struct sgsn_instance *sgi = data;
+
+ /* Do all the retransmissions as needed */
+ gtp_retrans(sgi->gsn);
+
+ sgsn_gtp_tmr_start(sgi);
+}
+
+int sgsn_gtp_init(struct sgsn_instance *sgi)
+{
+ int rc;
+ struct gsn_t *gsn;
+
+ rc = gtp_new(&sgi->gsn, sgi->cfg.gtp_statedir,
+ &sgi->cfg.gtp_listenaddr.sin_addr, GTP_MODE_SGSN);
+ if (rc) {
+ LOGP(DGPRS, LOGL_ERROR, "Failed to create GTP: %d\n", rc);
+ return rc;
+ }
+ gsn = sgi->gsn;
+
+ sgi->gtp_fd0.fd = gsn->fd0;
+ sgi->gtp_fd0.priv_nr = 0;
+ sgi->gtp_fd0.data = sgi;
+ sgi->gtp_fd0.when = BSC_FD_READ;
+ sgi->gtp_fd0.cb = sgsn_gtp_fd_cb;
+ rc = bsc_register_fd(&sgi->gtp_fd0);
+ if (rc < 0)
+ return rc;
+
+ sgi->gtp_fd1c.fd = gsn->fd1c;
+ sgi->gtp_fd1c.priv_nr = 1;
+ sgi->gtp_fd1c.data = sgi;
+ sgi->gtp_fd1c.when = BSC_FD_READ;
+ sgi->gtp_fd1c.cb = sgsn_gtp_fd_cb;
+ bsc_register_fd(&sgi->gtp_fd1c);
+ if (rc < 0)
+ return rc;
+
+ sgi->gtp_fd1u.fd = gsn->fd1u;
+ sgi->gtp_fd1u.priv_nr = 2;
+ sgi->gtp_fd1u.data = sgi;
+ sgi->gtp_fd1u.when = BSC_FD_READ;
+ sgi->gtp_fd1u.cb = sgsn_gtp_fd_cb;
+ bsc_register_fd(&sgi->gtp_fd1u);
+ if (rc < 0)
+ return rc;
+
+ /* Start GTP re-transmission timer */
+ sgi->gtp_timer.cb = sgsn_gtp_tmr_cb;
+ sgi->gtp_timer.data = sgi;
+ sgsn_gtp_tmr_start(sgi);
+
+ /* Register callbackcs with libgtp */
+ gtp_set_cb_delete_context(gsn, cb_delete_context);
+ gtp_set_cb_conf(gsn, cb_conf);
+ gtp_set_cb_data_ind(gsn, cb_data_ind);
+ gtp_set_cb_unsup_ind(gsn, cb_unsup_ind);
+ gtp_set_cb_extheader_ind(gsn, cb_extheader_ind);
+
+ return 0;
+}
diff --git a/openbsc/src/gprs/sgsn_main.c b/openbsc/src/gprs/sgsn_main.c
index b355fb5..27d156a 100644
--- a/openbsc/src/gprs/sgsn_main.c
+++ b/openbsc/src/gprs/sgsn_main.c
@@ -38,13 +38,17 @@
#include <osmocore/select.h>
#include <osmocore/rate_ctr.h>
+#include <osmocom/vty/telnet_interface.h>
+
#include <openbsc/signal.h>
#include <openbsc/debug.h>
-#include <openbsc/telnet_interface.h>
#include <openbsc/vty.h>
#include <openbsc/sgsn.h>
#include <openbsc/gprs_ns.h>
#include <openbsc/gprs_bssgp.h>
+#include <openbsc/gprs_llc.h>
+
+#include <gtp.h>
#include "../../bscconfig.h"
@@ -57,18 +61,19 @@
void *tall_bsc_ctx;
struct gprs_ns_inst *sgsn_nsi;
-
-const char *openbsc_version = "Osmocom NSIP Proxy " PACKAGE_VERSION;
const char *openbsc_copyright =
"Copyright (C) 2010 Harald Welte and On-Waves\n"
- "Contributions by Daniel Willmann, Jan Lübbe, Stefan Schmidt\n"
- "Dieter Spaar, Andreas Eversberg, Holger Freyther\n\n"
"License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n";
-static char *config_file = "osmo_sgsn.cfg";
-static struct sgsn_config sgcfg;
+static struct sgsn_instance sgsn_inst = {
+ .config_file = "osmo_sgsn.cfg",
+ .cfg = {
+ .gtp_statedir = "./",
+ },
+};
+struct sgsn_instance *sgsn = &sgsn_inst;
/* call-back function for the NS protocol */
static int sgsn_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
@@ -120,6 +125,14 @@
extern struct gprs_ns_inst *bssgp_nsi;
extern void *tall_msgb_ctx;
+extern enum node_type bsc_vty_go_parent(struct vty *vty);
+
+static struct vty_app_info vty_info = {
+ .name = "Osmocom SGSN",
+ .version = PACKAGE_VERSION,
+ .go_parent_cb = bsc_vty_go_parent,
+};
+
int main(int argc, char **argv)
{
struct gsm_network dummy_network;
@@ -141,25 +154,51 @@
log_add_target(stderr_target);
log_set_all_filter(stderr_target, 1);
+ vty_info.copyright = openbsc_copyright;
+ vty_init(&vty_info);
+ logging_vty_add_cmds();
+ sgsn_vty_init();
+
rate_ctr_init(tall_bsc_ctx);
- telnet_init(&dummy_network, 4245);
+ rc = telnet_init(tall_bsc_ctx, &dummy_network, 4245);
+ if (rc < 0)
+ exit(1);
sgsn_nsi = gprs_ns_instantiate(&sgsn_ns_cb);
if (!sgsn_nsi) {
LOGP(DGPRS, LOGL_ERROR, "Unable to instantiate NS\n");
exit(1);
}
- bssgp_nsi = sgcfg.nsi = sgsn_nsi;
+ bssgp_nsi = sgsn_inst.cfg.nsi = sgsn_nsi;
gprs_ns_vty_init(bssgp_nsi);
+ gprs_bssgp_vty_init();
+ gprs_llc_vty_init();
/* FIXME: register signal handler for SS_NS */
- rc = sgsn_parse_config(config_file, &sgcfg);
+ rc = sgsn_parse_config(sgsn_inst.config_file, &sgsn_inst.cfg);
if (rc < 0) {
LOGP(DGPRS, LOGL_FATAL, "Cannot parse config file\n");
exit(2);
}
- nsip_listen(sgsn_nsi, sgcfg.nsip_listen_port);
+ rc = sgsn_gtp_init(&sgsn_inst);
+ if (rc) {
+ LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen on GTP socket\n");
+ exit(2);
+ }
+
+ rc = gprs_ns_nsip_listen(sgsn_nsi);
+ if (rc < 0) {
+ LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen on NSIP socket\n");
+ exit(2);
+ }
+
+ rc = gprs_ns_frgre_listen(sgsn_nsi);
+ if (rc < 0) {
+ LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen GRE "
+ "socket. Do you have CAP_NET_RAW?\n");
+ exit(2);
+ }
while (1) {
rc = bsc_select_main(0);
@@ -169,15 +208,3 @@
exit(0);
}
-
-struct gsm_network;
-int bsc_vty_init(struct gsm_network *dummy)
-{
- cmd_init(1);
- vty_init();
-
- openbsc_vty_add_cmds();
- sgsn_vty_init();
- return 0;
-}
-
diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c
index ec18fcb..873fa20 100644
--- a/openbsc/src/gprs/sgsn_vty.c
+++ b/openbsc/src/gprs/sgsn_vty.c
@@ -25,13 +25,19 @@
#include <arpa/inet.h>
#include <osmocore/talloc.h>
+#include <osmocore/utils.h>
+#include <osmocore/rate_ctr.h>
#include <openbsc/debug.h>
#include <openbsc/sgsn.h>
#include <openbsc/gprs_ns.h>
+#include <openbsc/gprs_sgsn.h>
+#include <openbsc/vty.h>
-#include <vty/command.h>
-#include <vty/vty.h>
+#include <osmocom/vty/command.h>
+#include <osmocom/vty/vty.h>
+
+#include <pdp.h>
static struct sgsn_config *g_cfg = NULL;
@@ -43,90 +49,227 @@
static int config_write_sgsn(struct vty *vty)
{
- struct in_addr ia;
+ struct sgsn_ggsn_ctx *gctx;
vty_out(vty, "sgsn%s", VTY_NEWLINE);
- if (g_cfg->nsip_listen_ip) {
- ia.s_addr = htonl(g_cfg->nsip_listen_ip);
- vty_out(vty, " nsip local ip %s%s", inet_ntoa(ia),
- VTY_NEWLINE);
- }
- vty_out(vty, " nsip local port %u%s", g_cfg->nsip_listen_port,
- VTY_NEWLINE);
+ vty_out(vty, " gtp local-ip %s%s",
+ inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
- return CMD_SUCCESS;
-}
-
-DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
- SHOW_STR "Display information about the SGSN")
-{
- /* FIXME: iterate over list of NS-VC's and display their state */
- struct gprs_ns_inst *nsi = g_cfg->nsi;
- struct gprs_nsvc *nsvc;
-
- llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
- vty_out(vty, "NSEI %5u, NS-VC %5u, %s-mode, %s %s%s",
- nsvc->nsei, nsvc->nsvci,
- nsvc->remote_end_is_sgsn ? "BSS" : "SGSN",
- nsvc->state & NSE_S_ALIVE ? "ALIVE" : "DEAD",
- nsvc->state & NSE_S_BLOCKED ? "BLOCKED" : "UNBLOCKED",
- VTY_NEWLINE);
- if (nsvc->nsi->ll == GPRS_NS_LL_UDP)
- vty_out(vty, " remote peer %s:%u%s",
- inet_ntoa(nsvc->ip.bts_addr.sin_addr),
- ntohs(nsvc->ip.bts_addr.sin_port), VTY_NEWLINE);
+ llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
+ vty_out(vty, " ggsn %u remote-ip %s%s", gctx->id,
+ inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
+ vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
+ gctx->gtp_version, VTY_NEWLINE);
}
return CMD_SUCCESS;
}
-DEFUN(cfg_sgsn,
- cfg_sgsn_cmd,
- "sgsn",
- "Configure the SGSN")
+#define SGSN_STR "Configure the SGSN"
+
+DEFUN(cfg_sgsn, cfg_sgsn_cmd,
+ "sgsn",
+ SGSN_STR)
{
vty->node = SGSN_NODE;
return CMD_SUCCESS;
}
-
-DEFUN(cfg_nsip_local_ip,
- cfg_nsip_local_ip_cmd,
- "nsip local ip A.B.C.D",
- "Set the IP address on which we listen for BSS connects")
+DEFUN(cfg_sgsn_bind_addr, cfg_sgsn_bind_addr_cmd,
+ "gtp local-ip A.B.C.D",
+ "GTP Parameters\n"
+ "Set the IP address for the local GTP bind\n")
{
- struct in_addr ia;
-
- inet_aton(argv[0], &ia);
- g_cfg->nsip_listen_ip = ntohl(ia.s_addr);
+ inet_aton(argv[0], &g_cfg->gtp_listenaddr.sin_addr);
return CMD_SUCCESS;
}
-DEFUN(cfg_nsip_local_port,
- cfg_nsip_local_port_cmd,
- "nsip local port <0-65534>",
- "Set the UDP port on which we listen for BSS connects")
+DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
+ "ggsn <0-255> remote-ip A.B.C.D",
+ "")
{
- unsigned int port = atoi(argv[0]);
+ uint32_t id = atoi(argv[0]);
+ struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
- g_cfg->nsip_listen_port = port;
+ inet_aton(argv[1], &ggc->remote_addr);
+
return CMD_SUCCESS;
}
+#if 0
+DEFUN(cfg_ggsn_remote_port, cfg_ggsn_remote_port_cmd,
+ "ggsn <0-255> remote-port <0-65535>",
+ "")
+{
+ uint32_t id = atoi(argv[0]);
+ struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
+ uint16_t port = atoi(argv[1]);
+}
+#endif
+DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
+ "ggsn <0-255> gtp-version (0|1)",
+ "")
+{
+ uint32_t id = atoi(argv[0]);
+ struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
+
+ if (atoi(argv[1]))
+ ggc->gtp_version = 1;
+ else
+ ggc->gtp_version = 0;
+
+ return CMD_SUCCESS;
+}
+
+#if 0
+DEFUN(cfg_apn_ggsn, cfg_apn_ggsn_cmd,
+ "apn APNAME ggsn <0-255>",
+ "")
+{
+ struct apn_ctx **
+}
+#endif
+
+const struct value_string gprs_mm_st_strs[] = {
+ { GMM_DEREGISTERED, "DEREGISTERED" },
+ { GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },
+ { GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },
+ { GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
+ { GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
+ { 0, NULL }
+};
+
+static void vty_dump_pdp(struct vty *vty, const char *pfx,
+ struct sgsn_pdp_ctx *pdp)
+{
+ vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u%s",
+ pfx, pdp->mm->imsi, pdp->sapi, pdp->nsapi, VTY_NEWLINE);
+ vty_out(vty, "%s APN: %s\n", pfx, pdp->lib->apn_use.v);
+ vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
+}
+
+static void vty_dump_mmctx(struct vty *vty, const char *pfx,
+ struct sgsn_mm_ctx *mm, int pdp)
+{
+ vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
+ pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
+ vty_out(vty, "%s MSISDN: %s, TLLI: %08x%s", pfx, mm->msisdn,
+ mm->tlli, VTY_NEWLINE);
+ vty_out(vty, "%s MM State: %s, Routeing Area: %u-%u-%u-%u, "
+ "Cell ID: %u%s", pfx,
+ get_value_string(gprs_mm_st_strs, mm->mm_state),
+ mm->ra.mcc, mm->ra.mnc, mm->ra.lac, mm->ra.rac,
+ mm->cell_id, VTY_NEWLINE);
+
+ vty_out_rate_ctr_group(vty, " ", mm->ctrg);
+
+ if (pdp) {
+ struct sgsn_pdp_ctx *pdp;
+
+ llist_for_each_entry(pdp, &mm->pdp_list, list)
+ vty_dump_pdp(vty, " ", pdp);
+ }
+}
+
+DEFUN(show_sgsn, show_sgsn_cmd, "show sgsn",
+ SHOW_STR "Display information about the SGSN")
+{
+ /* FIXME: statistics */
+ return CMD_SUCCESS;
+}
+
+#define MMCTX_STR "MM Context\n"
+#define INCLUDE_PDP_STR "Include PDP Context Information\n"
+
+#if 0
+DEFUN(show_mmctx_tlli, show_mmctx_tlli_cmd,
+ "show mm-context tlli HEX [pdp]",
+ SHOW_STR MMCTX_STR "Identify by TLLI\n" "TLLI\n" INCLUDE_PDP_STR)
+{
+ uint32_t tlli;
+ struct sgsn_mm_ctx *mm;
+
+ tlli = strtoul(argv[0], NULL, 16);
+ mm = sgsn_mm_ctx_by_tlli(tlli);
+ if (!mm) {
+ vty_out(vty, "No MM context for TLLI %08x%s",
+ tlli, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
+ return CMD_SUCCESS;
+}
+#endif
+
+DEFUN(swow_mmctx_imsi, show_mmctx_imsi_cmd,
+ "show mm-context imsi IMSI [pdp]",
+ SHOW_STR MMCTX_STR "Identify by IMSI\n" "IMSI of the MM Context\n"
+ INCLUDE_PDP_STR)
+{
+ struct sgsn_mm_ctx *mm;
+
+ mm = sgsn_mm_ctx_by_imsi(argv[0]);
+ if (!mm) {
+ vty_out(vty, "No MM context for IMSI %s%s",
+ argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ vty_dump_mmctx(vty, "", mm, argv[1] ? 1 : 0);
+ return CMD_SUCCESS;
+}
+
+DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
+ "show mm-context all [pdp]",
+ SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
+{
+ struct sgsn_mm_ctx *mm;
+
+ llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
+ vty_dump_mmctx(vty, "", mm, argv[0] ? 1 : 0);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(show_ggsn, show_ggsn_cmd,
+ "show ggsn",
+ "")
+{
+
+}
+
+DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
+ "show pdp-context all",
+ SHOW_STR "Display information on PDP Context\n")
+{
+ struct sgsn_pdp_ctx *pdp;
+
+ llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
+ vty_dump_pdp(vty, "", pdp);
+
+ return CMD_SUCCESS;
+}
int sgsn_vty_init(void)
{
- install_element(VIEW_NODE, &show_sgsn_cmd);
+ install_element_ve(&show_sgsn_cmd);
+ //install_element_ve(&show_mmctx_tlli_cmd);
+ install_element_ve(&show_mmctx_imsi_cmd);
+ install_element_ve(&show_mmctx_all_cmd);
+ install_element_ve(&show_pdpctx_all_cmd);
install_element(CONFIG_NODE, &cfg_sgsn_cmd);
install_node(&sgsn_node, config_write_sgsn);
install_default(SGSN_NODE);
- install_element(SGSN_NODE, &cfg_nsip_local_ip_cmd);
- install_element(SGSN_NODE, &cfg_nsip_local_port_cmd);
+ install_element(SGSN_NODE, &ournode_exit_cmd);
+ install_element(SGSN_NODE, &ournode_end_cmd);
+ install_element(SGSN_NODE, &cfg_sgsn_bind_addr_cmd);
+ install_element(SGSN_NODE, &cfg_ggsn_remote_ip_cmd);
+ //install_element(SGSN_NODE, &cfg_ggsn_remote_port_cmd);
+ install_element(SGSN_NODE, &cfg_ggsn_gtp_version_cmd);
return 0;
}
@@ -136,7 +279,7 @@
int rc;
g_cfg = cfg;
- rc = vty_read_config_file(config_file);
+ rc = vty_read_config_file(config_file, NULL);
if (rc < 0) {
fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
return rc;
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c
index b0e5541..297a2c9 100644
--- a/openbsc/src/gsm_04_08.c
+++ b/openbsc/src/gsm_04_08.c
@@ -30,6 +30,7 @@
#include <time.h>
#include <netinet/in.h>
+#include <openbsc/auth.h>
#include <openbsc/db.h>
#include <osmocore/msgb.h>
#include <osmocore/bitvec.h>
@@ -52,11 +53,13 @@
#include <openbsc/transaction.h>
#include <openbsc/ussd.h>
#include <openbsc/silent_call.h>
+#include <openbsc/bsc_api.h>
void *tall_locop_ctx;
+void *tall_authciphop_ctx;
-int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
-static int gsm48_tx_simple(struct gsm_lchan *lchan,
+int gsm0408_loc_upd_acc(struct gsm_subscriber_connection *conn, u_int32_t tmsi);
+static int gsm48_tx_simple(struct gsm_subscriber_connection *conn,
u_int8_t pdisc, u_int8_t msg_type);
static void schedule_reject(struct gsm_subscriber_connection *conn);
@@ -68,6 +71,122 @@
static u_int32_t new_callref = 0x80000001;
+static int gsm48_conn_sendmsg(struct msgb *msg, struct gsm_subscriber_connection *conn,
+ struct gsm_trans *trans)
+{
+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
+
+ /* if we get passed a transaction reference, do some common
+ * work that the caller no longer has to do */
+ if (trans) {
+ gh->proto_discr = trans->protocol | (trans->transaction_id << 4);
+ msg->lchan = trans->conn->lchan;
+ }
+
+
+ if (msg->lchan) {
+ msg->trx = msg->lchan->ts->trx;
+ if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
+ DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
+ "Sending '%s' to MS.\n", msg->trx->bts->nr,
+ msg->trx->nr, msg->lchan->ts->nr,
+ gh->proto_discr & 0xf0,
+ gsm48_cc_msg_name(gh->msg_type));
+ else
+ DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
+ "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
+ msg->trx->nr, msg->lchan->ts->nr,
+ gh->proto_discr, gh->msg_type);
+ }
+
+ msg->l3h = msg->data;
+ return gsm0808_submit_dtap(conn, msg, 0);
+}
+
+static void release_security_operation(struct gsm_subscriber_connection *conn)
+{
+ if (!conn->sec_operation)
+ return;
+
+ talloc_free(conn->sec_operation);
+ conn->sec_operation = NULL;
+ put_subscr_con(conn);
+}
+
+static void allocate_security_operation(struct gsm_subscriber_connection *conn)
+{
+ use_subscr_con(conn)
+
+ conn->sec_operation = talloc_zero(tall_authciphop_ctx,
+ struct gsm_security_operation);
+}
+
+static int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq,
+ gsm_cbfn *cb, void *cb_data)
+{
+ struct gsm_network *net = conn->bts->network;
+ struct gsm_subscriber *subscr = conn->subscr;
+ struct gsm_security_operation *op;
+ struct gsm_auth_tuple atuple;
+ int status = -1, rc;
+
+ /* Check if we _can_ enable encryption. Cases where we can't:
+ * - Encryption disabled in config
+ * - Channel already secured (nothing to do)
+ * - Subscriber equipment doesn't support configured encryption
+ */
+ if (!net->a5_encryption) {
+ status = GSM_SECURITY_NOAVAIL;
+ } else if (conn->lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
+ DEBUGP(DMM, "Requesting to secure an already secure channel");
+ status = GSM_SECURITY_SUCCEEDED;
+ } else if (!ms_cm2_a5n_support(subscr->equipment.classmark2,
+ net->a5_encryption)) {
+ DEBUGP(DMM, "Subscriber equipment doesn't support requested encryption");
+ status = GSM_SECURITY_NOAVAIL;
+ }
+
+ /* If not done yet, try to get info for this user */
+ if (status < 0) {
+ rc = auth_get_tuple_for_subscr(&atuple, subscr, key_seq);
+ if (rc <= 0)
+ status = GSM_SECURITY_NOAVAIL;
+ }
+
+ /* Are we done yet ? */
+ if (status >= 0)
+ return cb ?
+ cb(GSM_HOOK_RR_SECURITY, status, NULL, conn, cb_data) :
+ 0;
+
+ /* Start an operation (can't have more than one pending !!!) */
+ if (conn->sec_operation)
+ return -EBUSY;
+
+ allocate_security_operation(conn);
+ op = conn->sec_operation;
+ op->cb = cb;
+ op->cb_data = cb_data;
+ memcpy(&op->atuple, &atuple, sizeof(struct gsm_auth_tuple));
+
+ /* FIXME: Should start a timer for completion ... */
+
+ /* Then do whatever is needed ... */
+ if (rc == 1) {
+ /* Start authentication */
+ return gsm48_tx_mm_auth_req(conn, op->atuple.rand, op->atuple.key_seq);
+ } else if (rc == 2) {
+ /* Start ciphering directly */
+ conn->lchan->encr.alg_id = RSL_ENC_ALG_A5(net->a5_encryption);
+ conn->lchan->encr.key_len = 8;
+ memcpy(conn->lchan->encr.key, op->atuple.kc, 8);
+
+ return gsm48_send_rr_ciph_mode(conn->lchan, 0);
+ }
+
+ return -EINVAL; /* not reached */
+}
+
static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
struct gsm_subscriber *subscriber)
{
@@ -116,99 +235,108 @@
struct gsm_loc_updating_operation);
}
+static int _gsm0408_authorize_sec_cb(unsigned int hooknum, unsigned int event,
+ struct msgb *msg, void *data, void *param)
+{
+ struct gsm_subscriber_connection *conn = data;
+ int rc = 0;
+
+ switch (event) {
+ case GSM_SECURITY_AUTH_FAILED:
+ release_loc_updating_req(conn);
+ break;
+
+ case GSM_SECURITY_NOAVAIL:
+ case GSM_SECURITY_SUCCEEDED:
+ /* We're all good */
+ db_subscriber_alloc_tmsi(conn->subscr);
+ rc = gsm0408_loc_upd_acc(conn, conn->subscr->tmsi);
+ if (conn->bts->network->send_mm_info) {
+ /* send MM INFO with network name */
+ rc = gsm48_tx_mm_info(conn);
+ }
+
+ /* call subscr_update after putting the loc_upd_acc
+ * in the transmit queue, since S_SUBSCR_ATTACHED might
+ * trigger further action like SMS delivery */
+ subscr_update(conn->subscr, conn->bts,
+ GSM_SUBSCRIBER_UPDATE_ATTACHED);
+
+ /* try to close channel ASAP */
+ release_loc_updating_req(conn);
+ lchan_auto_release(conn->lchan);
+ break;
+
+ default:
+ rc = -EINVAL;
+ };
+
+ return rc;
+}
+
static int gsm0408_authorize(struct gsm_subscriber_connection *conn, struct msgb *msg)
{
- if (authorize_subscriber(conn->loc_operation, conn->subscr)) {
- int rc;
-
- db_subscriber_alloc_tmsi(conn->subscr);
- release_loc_updating_req(conn);
- rc = gsm0408_loc_upd_acc(msg->lchan, conn->subscr->tmsi);
- if (msg->lchan->ts->trx->bts->network->send_mm_info) {
- /* send MM INFO with network name */
- rc = gsm48_tx_mm_info(msg->lchan);
- }
-
- /* call subscr_update after putting the loc_upd_acc
- * in the transmit queue, since S_SUBSCR_ATTACHED might
- * trigger further action like SMS delivery */
- subscr_update(conn->subscr, msg->trx->bts,
- GSM_SUBSCRIBER_UPDATE_ATTACHED);
-
- /* try to close channel ASAP */
- lchan_auto_release(conn->lchan);
- return rc;
- }
-
+ if (authorize_subscriber(conn->loc_operation, conn->subscr))
+ return gsm48_secure_channel(conn,
+ conn->loc_operation->key_seq,
+ _gsm0408_authorize_sec_cb, NULL);
return 0;
}
-static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
- void *handler_data, void *signal_data)
+void gsm0408_clear_request(struct gsm_subscriber_connection* conn, uint32_t cause)
{
struct gsm_trans *trans, *temp;
-
- if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
- return 0;
-
/*
* Cancel any outstanding location updating request
- * operation taking place on the lchan.
+ * operation taking place on the subscriber connection.
*/
- struct gsm_lchan *lchan = (struct gsm_lchan *)signal_data;
- if (!lchan)
- return 0;
-
- release_loc_updating_req(&lchan->conn);
+ release_loc_updating_req(conn);
+ release_security_operation(conn);
/* Free all transactions that are associated with the released lchan */
/* FIXME: this is not neccessarily the right thing to do, we should
* only set trans->lchan to NULL and wait for another lchan to be
* established to the same MM entity (phone/subscriber) */
- llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
- if (trans->conn && trans->conn->lchan == lchan)
+ llist_for_each_entry_safe(trans, temp, &conn->bts->network->trans_list, entry) {
+ if (trans->conn == conn)
trans_free(trans);
}
-
- return 0;
}
/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
-int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
+int gsm0408_loc_upd_rej(struct gsm_subscriber_connection *conn, u_int8_t cause)
{
- struct gsm_subscriber_connection *conn;
- struct gsm_bts *bts = lchan->ts->trx->bts;
- struct msgb *msg = gsm48_msgb_alloc();
- struct gsm48_hdr *gh;
-
- msg->lchan = lchan;
- conn = &lchan->conn;
+ struct gsm_bts *bts = conn->bts;
+ struct msgb *msg;
- gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
- gh->proto_discr = GSM48_PDISC_MM;
- gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
- gh->data[0] = cause;
+ counter_inc(bts->network->stats.loc_upd_resp.reject);
+
+ msg = gsm48_create_loc_upd_rej(cause);
+ if (!msg) {
+ LOGP(DMM, LOGL_ERROR, "Failed to create msg for LOCATION UPDATING REJECT.\n");
+ return -1;
+ }
+
+ msg->lchan = conn->lchan;
LOGP(DMM, LOGL_INFO, "Subscriber %s: LOCATION UPDATING REJECT "
"LAC=%u BTS=%u\n", conn->subscr ?
subscr_name(conn->subscr) : "unknown",
- lchan->ts->trx->bts->location_area_code, lchan->ts->trx->bts->nr);
+ bts->location_area_code, bts->nr);
- counter_inc(bts->network->stats.loc_upd_resp.reject);
-
- return gsm48_sendmsg(msg, NULL);
+ return gsm48_conn_sendmsg(msg, conn, NULL);
}
/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
-int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
+int gsm0408_loc_upd_acc(struct gsm_subscriber_connection *conn, u_int32_t tmsi)
{
- struct gsm_bts *bts = lchan->ts->trx->bts;
+ struct gsm_bts *bts = conn->bts;
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh;
struct gsm48_loc_area_id *lai;
u_int8_t *mid;
- msg->lchan = lchan;
+ msg->lchan = conn->lchan;
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
gh->proto_discr = GSM48_PDISC_MM;
@@ -225,23 +353,23 @@
counter_inc(bts->network->stats.loc_upd_resp.accept);
- return gsm48_sendmsg(msg, NULL);
+ return gsm48_conn_sendmsg(msg, conn, NULL);
}
/* Transmit Chapter 9.2.10 Identity Request */
-static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
+static int mm_tx_identity_req(struct gsm_subscriber_connection *conn, u_int8_t id_type)
{
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh;
- msg->lchan = lchan;
+ msg->lchan = conn->lchan;
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
gh->proto_discr = GSM48_PDISC_MM;
gh->msg_type = GSM48_MT_MM_ID_REQ;
gh->data[0] = id_type;
- return gsm48_sendmsg(msg, NULL);
+ return gsm48_conn_sendmsg(msg, conn, NULL);
}
@@ -298,8 +426,8 @@
struct gsm_lchan *lchan = conn->lchan;
struct gsm_bts *bts = lchan->ts->trx->bts;
+ gsm0408_loc_upd_rej(conn, bts->network->reject_cause);
release_loc_updating_req(conn);
- gsm0408_loc_upd_rej(lchan, bts->network->reject_cause);
lchan_auto_release(lchan);
}
@@ -368,17 +496,19 @@
if (conn->loc_operation) {
DEBUGPC(DMM, "ignoring request due an existing one: %p.\n",
conn->loc_operation);
- gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
+ gsm0408_loc_upd_rej(conn, GSM48_REJECT_PROTOCOL_ERROR);
return 0;
}
allocate_loc_updating_req(&lchan->conn);
+ conn->loc_operation->key_seq = lu->key_seq;
+
switch (mi_type) {
case GSM_MI_TYPE_IMSI:
DEBUGPC(DMM, "\n");
/* we always want the IMEI, too */
- rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
+ rc = mm_tx_identity_req(conn, GSM_MI_TYPE_IMEI);
conn->loc_operation->waiting_for_imei = 1;
/* look up subscriber based on IMSI, create if not found */
@@ -389,18 +519,17 @@
break;
case GSM_MI_TYPE_TMSI:
DEBUGPC(DMM, "\n");
- /* we always want the IMEI, too */
- rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
- conn->loc_operation->waiting_for_imei = 1;
-
/* look up the subscriber based on TMSI, request IMSI if it fails */
subscr = subscr_get_by_tmsi(bts->network,
tmsi_from_string(mi_string));
if (!subscr) {
/* send IDENTITY REQUEST message to get IMSI */
- rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
+ rc = mm_tx_identity_req(conn, GSM_MI_TYPE_IMSI);
conn->loc_operation->waiting_for_imsi = 1;
}
+ /* we always want the IMEI, too */
+ rc = mm_tx_identity_req(conn, GSM_MI_TYPE_IMEI);
+ conn->loc_operation->waiting_for_imei = 1;
break;
case GSM_MI_TYPE_IMEI:
case GSM_MI_TYPE_IMEISV:
@@ -437,11 +566,11 @@
#endif
/* Section 9.2.15a */
-int gsm48_tx_mm_info(struct gsm_lchan *lchan)
+int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn)
{
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh;
- struct gsm_network *net = lchan->ts->trx->bts->network;
+ struct gsm_network *net = conn->bts->network;
u_int8_t *ptr8;
int name_len, name_pad;
#if 0
@@ -450,7 +579,7 @@
int tz15min;
#endif
- msg->lchan = lchan;
+ msg->lchan = conn->lchan;
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
gh->proto_discr = GSM48_PDISC_MM;
@@ -536,11 +665,11 @@
DEBUGP(DMM, "-> MM INFO\n");
- return gsm48_sendmsg(msg, NULL);
+ return gsm48_conn_sendmsg(msg, conn, NULL);
}
/* Section 9.2.2 */
-int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand, int key_seq)
+int gsm48_tx_mm_auth_req(struct gsm_subscriber_connection *conn, u_int8_t *rand, int key_seq)
{
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
@@ -548,7 +677,7 @@
DEBUGP(DMM, "-> AUTH REQ (rand = %s)\n", hexdump(rand, 16));
- msg->lchan = lchan;
+ msg->lchan = conn->lchan;
gh->proto_discr = GSM48_PDISC_MM;
gh->msg_type = GSM48_MT_MM_AUTH_REQ;
@@ -558,40 +687,66 @@
if (rand)
memcpy(ar->rand, rand, 16);
- return gsm48_sendmsg(msg, NULL);
+ return gsm48_conn_sendmsg(msg, conn, NULL);
}
/* Section 9.2.1 */
-int gsm48_tx_mm_auth_rej(struct gsm_lchan *lchan)
+int gsm48_tx_mm_auth_rej(struct gsm_subscriber_connection *conn)
{
DEBUGP(DMM, "-> AUTH REJECT\n");
- return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_AUTH_REJ);
+ return gsm48_tx_simple(conn, GSM48_PDISC_MM, GSM48_MT_MM_AUTH_REJ);
}
-static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
+static int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn)
{
DEBUGP(DMM, "-> CM SERVICE ACK\n");
- return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
+ return gsm48_tx_simple(conn, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
}
/* 9.2.6 CM service reject */
static int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
enum gsm48_reject_value value)
{
- struct msgb *msg = gsm48_msgb_alloc();
- struct gsm48_hdr *gh;
+ struct msgb *msg;
- gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
+ msg = gsm48_create_mm_serv_rej(value);
+ if (!msg) {
+ LOGP(DMM, LOGL_ERROR, "Failed to allocate CM Service Reject.\n");
+ return -1;
+ }
+ DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
msg->lchan = conn->lchan;
use_subscr_con(conn);
+ return gsm48_conn_sendmsg(msg, conn, NULL);
+}
- gh->proto_discr = GSM48_PDISC_MM;
- gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
- gh->data[0] = value;
- DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
+static int _gsm48_rx_mm_serv_req_sec_cb(
+ unsigned int hooknum, unsigned int event,
+ struct msgb *msg, void *data, void *param)
+{
+ struct gsm_subscriber_connection *conn = data;
+ int rc = 0;
- return gsm48_sendmsg(msg, NULL);
+ switch (event) {
+ case GSM_SECURITY_AUTH_FAILED:
+ /* Nothing to do */
+ break;
+
+ case GSM_SECURITY_NOAVAIL:
+ rc = gsm48_tx_mm_serv_ack(conn);
+ break;
+
+ case GSM_SECURITY_SUCCEEDED:
+ /* nothing to do. CIPHER MODE COMMAND is
+ * implicit CM SERV ACK */
+ break;
+
+ default:
+ rc = -EINVAL;
+ };
+
+ return rc;
}
/*
@@ -613,7 +768,7 @@
struct gsm48_hdr *gh = msgb_l3(msg);
struct gsm48_service_request *req =
(struct gsm48_service_request *)gh->data;
- /* unfortunately in Phase1 the classmar2 length is variable */
+ /* unfortunately in Phase1 the classmark2 length is variable */
u_int8_t classmark2_len = gh->data[1];
u_int8_t *classmark2 = gh->data+2;
u_int8_t mi_len = *(classmark2 + classmark2_len);
@@ -669,7 +824,8 @@
memcpy(subscr->equipment.classmark2, classmark2, classmark2_len);
db_sync_equipment(&subscr->equipment);
- return gsm48_tx_mm_serv_ack(msg->lchan);
+ return gsm48_secure_channel(&msg->lchan->conn, req->cipher_key_seq,
+ _gsm48_rx_mm_serv_req_sec_cb, NULL);
}
static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
@@ -736,6 +892,48 @@
return 0;
}
+/* Chapter 9.2.3: Authentication Response */
+static int gsm48_rx_mm_auth_resp(struct msgb *msg)
+{
+ struct gsm48_hdr *gh = msgb_l3(msg);
+ struct gsm48_auth_resp *ar = (struct gsm48_auth_resp*) gh->data;
+ struct gsm_subscriber_connection *conn = &msg->lchan->conn;
+ struct gsm_network *net = conn->bts->network;
+
+ DEBUGP(DMM, "MM AUTHENTICATION RESPONSE (sres = %s): ",
+ hexdump(ar->sres, 4));
+
+ /* Safety check */
+ if (!conn->sec_operation) {
+ DEBUGP(DMM, "No authentication/cipher operation in progress !!!\n");
+ return -EIO;
+ }
+
+ /* Validate SRES */
+ if (memcmp(conn->sec_operation->atuple.sres, ar->sres,4)) {
+ gsm_cbfn *cb = conn->sec_operation->cb;
+
+ DEBUGPC(DMM, "Invalid (expected %s)\n",
+ hexdump(conn->sec_operation->atuple.sres, 4));
+
+ if (cb)
+ cb(GSM_HOOK_RR_SECURITY, GSM_SECURITY_AUTH_FAILED,
+ NULL, conn, conn->sec_operation->cb_data);
+
+ release_security_operation(conn);
+ return gsm48_tx_mm_auth_rej(conn);
+ }
+
+ DEBUGPC(DMM, "OK\n");
+
+ /* Start ciphering */
+ conn->lchan->encr.alg_id = RSL_ENC_ALG_A5(net->a5_encryption);
+ conn->lchan->encr.key_len = 8;
+ memcpy(conn->lchan->encr.key, conn->sec_operation->atuple.kc, 8);
+
+ return gsm48_send_rr_ciph_mode(msg->lchan, 0);
+}
+
/* Receive a GSM 04.08 Mobility Management (MM) message */
static int gsm0408_rcv_mm(struct msgb *msg)
{
@@ -769,7 +967,7 @@
DEBUGP(DMM, "CM REESTABLISH REQUEST: Not implemented\n");
break;
case GSM48_MT_MM_AUTH_RESP:
- DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
+ rc = gsm48_rx_mm_auth_resp(msg);
break;
default:
LOGP(DMM, LOGL_NOTICE, "Unknown GSM 04.08 MM msg type 0x%02x\n",
@@ -785,13 +983,16 @@
{
struct gsm_bts *bts = msg->lchan->ts->trx->bts;
struct gsm48_hdr *gh = msgb_l3(msg);
+ struct gsm48_pag_resp *resp;
u_int8_t *classmark2_lv = gh->data + 1;
u_int8_t mi_type;
char mi_string[GSM48_MI_SIZE];
struct gsm_subscriber *subscr = NULL;
int rc = 0;
- gsm48_paging_extract_mi(msg, mi_string, &mi_type);
+ resp = (struct gsm48_pag_resp *) &gh->data[0];
+ gsm48_paging_extract_mi(resp, msgb_l3len(msg) - sizeof(*gh),
+ mi_string, &mi_type);
DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
mi_type, mi_string);
@@ -908,6 +1109,36 @@
return db_apdu_blob_store(msg->lchan->conn.subscr, apdu_id_flags, apdu_len, apdu_data);
}
+/* Chapter 9.1.10 Ciphering Mode Complete */
+static int gsm48_rx_rr_ciph_m_compl(struct msgb *msg)
+{
+ struct gsm_subscriber_connection *conn = &msg->lchan->conn;
+ gsm_cbfn *cb;
+ int rc = 0;
+
+ DEBUGP(DRR, "CIPHERING MODE COMPLETE\n");
+
+ /* Safety check */
+ if (!conn->sec_operation) {
+ DEBUGP(DRR, "No authentication/cipher operation in progress !!!\n");
+ return -EIO;
+ }
+
+ /* FIXME: check for MI (if any) */
+
+ /* Call back whatever was in progress (if anything) ... */
+ cb = conn->sec_operation->cb;
+ if (cb) {
+ rc = cb(GSM_HOOK_RR_SECURITY, GSM_SECURITY_SUCCEEDED,
+ NULL, conn, conn->sec_operation->cb_data);
+ }
+
+ /* Complete the operation */
+ release_security_operation(conn);
+
+ return rc;
+}
+
/* Chapter 9.1.16 Handover complete */
static int gsm48_rx_rr_ho_compl(struct msgb *msg)
{
@@ -965,8 +1196,7 @@
rc = gsm48_rx_rr_app_info(msg);
break;
case GSM48_MT_RR_CIPH_M_COMPL:
- DEBUGP(DRR, "CIPHERING MODE COMPLETE\n");
- /* FIXME: check for MI (if any) */
+ rc = gsm48_rx_rr_ciph_m_compl(msg);
break;
case GSM48_MT_RR_HANDO_COMPL:
rc = gsm48_rx_rr_ho_compl(msg);
@@ -983,13 +1213,13 @@
return rc;
}
-int gsm48_send_rr_app_info(struct gsm_lchan *lchan, u_int8_t apdu_id,
+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)
{
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh;
- msg->lchan = lchan;
+ msg->lchan = conn->lchan;
DEBUGP(DRR, "TX APPLICATION INFO id=0x%02x, len=%u\n",
apdu_id, apdu_len);
@@ -1001,7 +1231,7 @@
gh->data[1] = apdu_len;
memcpy(gh->data+2, apdu, apdu_len);
- return gsm48_sendmsg(msg, NULL);
+ return gsm48_conn_sendmsg(msg, conn, NULL);
}
/* Call Control */
@@ -1039,21 +1269,21 @@
call_state = msgb_put(msg, 1);
call_state[0] = 0xc0 | 0x00;
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
-static int gsm48_tx_simple(struct gsm_lchan *lchan,
+static int gsm48_tx_simple(struct gsm_subscriber_connection *conn,
u_int8_t pdisc, u_int8_t msg_type)
{
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- msg->lchan = lchan;
+ msg->lchan = conn->lchan;
gh->proto_discr = pdisc;
gh->msg_type = msg_type;
- return gsm48_sendmsg(msg, NULL);
+ return gsm48_conn_sendmsg(msg, conn, NULL);
}
static void gsm48_stop_cc_timer(struct gsm_trans *trans)
@@ -1595,7 +1825,7 @@
new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
@@ -1663,7 +1893,7 @@
if (proceeding->fields & MNCC_F_PROGRESS)
gsm48_encode_progress(msg, 0, &proceeding->progress);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
@@ -1725,7 +1955,7 @@
new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
@@ -1742,7 +1972,7 @@
if (progress->fields & MNCC_F_USERUSER)
gsm48_encode_useruser(msg, 0, &progress->useruser);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
@@ -1771,7 +2001,7 @@
new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
@@ -1842,7 +2072,7 @@
new_cc_state(trans, GSM_CSTATE_ACTIVE);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
@@ -1930,7 +2160,7 @@
new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
@@ -1975,7 +2205,7 @@
/* release collision 5.4.5 */
rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel);
} else {
- rc = gsm48_tx_simple(msg->lchan,
+ rc = gsm48_tx_simple(trans->conn,
GSM48_PDISC_CC | (trans->transaction_id << 4),
GSM48_MT_CC_RELEASE_COMPL);
rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
@@ -2018,7 +2248,7 @@
if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
@@ -2108,7 +2338,7 @@
trans_free(trans);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
@@ -2148,7 +2378,7 @@
/* facility */
gsm48_encode_facility(msg, 1, &fac->facility);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
@@ -2167,7 +2397,7 @@
gh->msg_type = GSM48_MT_CC_HOLD_ACK;
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
@@ -2184,7 +2414,7 @@
else
gsm48_encode_cause(msg, 1, &default_cause);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
@@ -2204,7 +2434,7 @@
gh->msg_type = GSM48_MT_CC_RETR_ACK;
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
@@ -2221,7 +2451,7 @@
else
gsm48_encode_cause(msg, 1, &default_cause);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
@@ -2256,7 +2486,7 @@
if (dtmf->fields & MNCC_F_KEYPAD)
gsm48_encode_keypad(msg, dtmf->keypad);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
@@ -2273,7 +2503,7 @@
else
gsm48_encode_cause(msg, 1, &default_cause);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
@@ -2283,7 +2513,7 @@
gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
@@ -2333,7 +2563,7 @@
new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
@@ -2373,7 +2603,7 @@
new_cc_state(trans, GSM_CSTATE_ACTIVE);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
@@ -2421,7 +2651,7 @@
new_cc_state(trans, GSM_CSTATE_ACTIVE);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
@@ -2435,7 +2665,7 @@
/* notify */
gsm48_encode_notify(msg, notify->notify);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
@@ -2469,7 +2699,7 @@
if (user->more)
gsm48_encode_more(msg);
- return gsm48_sendmsg(msg, trans);
+ return gsm48_conn_sendmsg(msg, trans->conn, trans);
}
static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
@@ -2568,7 +2798,7 @@
{
int i, rc = 0;
struct gsm_trans *trans = NULL, *transt;
- struct gsm_lchan *lchan = NULL;
+ struct gsm_subscriber_connection *conn = NULL;
struct gsm_bts *bts = NULL;
struct gsm_mncc *data = arg, rel;
@@ -2673,10 +2903,10 @@
return -ENOMEM;
}
/* Find lchan */
- lchan = lchan_for_subscr(subscr);
+ conn = connection_for_subscr(subscr);
/* If subscriber has no lchan */
- if (!lchan) {
+ if (!conn) {
/* find transaction with this subscriber already paging */
llist_for_each_entry(transt, &net->trans_list, entry) {
/* Transaction of our lchan? */
@@ -2702,16 +2932,16 @@
return 0;
}
/* Assign lchan */
- trans->conn = &lchan->conn;
+ trans->conn = conn;
use_subscr_con(trans->conn);
subscr_put(subscr);
}
if (trans->conn)
- lchan = trans->conn->lchan;
+ conn = trans->conn;
/* if paging did not respond yet */
- if (!lchan) {
+ if (!conn) {
DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
"Received '%s' from MNCC in paging state\n",
(trans->subscr)?(trans->subscr->extension):"-",
@@ -2729,7 +2959,7 @@
DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
"Received '%s' from MNCC in state %d (%s)\n",
- lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
+ conn->bts->nr, conn->lchan->ts->trx->nr, conn->lchan->ts->nr,
trans->transaction_id,
(trans->conn->subscr)?(trans->conn->subscr->extension):"-",
get_mncc_name(msg_type), trans->cc.state,
@@ -2841,7 +3071,7 @@
transaction_id, new_callref++);
if (!trans) {
DEBUGP(DCC, "No memory for trans.\n");
- rc = gsm48_tx_simple(msg->lchan,
+ rc = gsm48_tx_simple(trans->conn,
GSM48_PDISC_CC | (transaction_id << 4),
GSM48_MT_CC_RELEASE_COMPL);
return -ENOMEM;
@@ -2887,7 +3117,7 @@
rc = gsm0408_rcv_rr(msg);
break;
case GSM48_PDISC_SMS:
- rc = gsm0411_rcv_sms(msg, link_id);
+ rc = gsm0411_rcv_sms(&msg->lchan->conn, msg, link_id);
break;
case GSM48_PDISC_MM_GPRS:
case GSM48_PDISC_SM_GPRS:
@@ -2906,31 +3136,11 @@
return rc;
}
-/* dequeue messages to layer 4 */
-int bsc_upqueue(struct gsm_network *net)
-{
- struct gsm_mncc *mncc;
- struct msgb *msg;
- int work = 0;
-
- if (net)
- while ((msg = msgb_dequeue(&net->upqueue))) {
- mncc = (struct gsm_mncc *)msg->data;
- if (net->mncc_recv)
- net->mncc_recv(net, mncc->msg_type, mncc);
- work = 1; /* work done */
- talloc_free(msg);
- }
-
- return work;
-}
-
/*
* This will be ran by the linker when loading the DSO. We use it to
* do system initialization, e.g. registration of signal handlers.
*/
static __attribute__((constructor)) void on_dso_load_0408(void)
{
- register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
}
diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c
index 1b3ed25..952d724 100644
--- a/openbsc/src/gsm_04_08_utils.c
+++ b/openbsc/src/gsm_04_08_utils.c
@@ -40,35 +40,12 @@
* or should OpenBSC always act as RTP relay/proxy in between (0) ? */
int ipacc_rtp_direct = 1;
-int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans)
+static int gsm48_sendmsg(struct msgb *msg)
{
- struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
-
- /* if we get passed a transaction reference, do some common
- * work that the caller no longer has to do */
- if (trans) {
- gh->proto_discr = trans->protocol | (trans->transaction_id << 4);
- msg->lchan = trans->conn->lchan;
- }
-
- if (msg->lchan) {
+ if (msg->lchan)
msg->trx = msg->lchan->ts->trx;
- if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
- DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x) "
- "Sending '%s' to MS.\n", msg->trx->bts->nr,
- msg->trx->nr, msg->lchan->ts->nr,
- gh->proto_discr & 0xf0,
- gsm48_cc_msg_name(gh->msg_type));
- else
- DEBUGP(DCC, "(bts %d trx %d ts %d pd %02x) "
- "Sending 0x%02x to MS.\n", msg->trx->bts->nr,
- msg->trx->nr, msg->lchan->ts->nr,
- gh->proto_discr, gh->msg_type);
- }
-
msg->l3h = msg->data;
-
return rsl_data_request(msg, 0);
}
@@ -220,7 +197,7 @@
lchan->nr, lchan->type);
/* Send actual release request to MS */
- gsm48_sendmsg(msg, NULL);
+ gsm48_sendmsg(msg);
/* FIXME: Start Timer T3109 */
/* Deactivate the SACCH on the BTS side */
@@ -243,16 +220,30 @@
return rsl_siemens_mrpci(lchan, &mrpci);
}
-int gsm48_paging_extract_mi(struct msgb *msg, char *mi_string, u_int8_t *mi_type)
+int gsm48_extract_mi(uint8_t *classmark2_lv, int length, char *mi_string, uint8_t *mi_type)
{
- struct gsm48_hdr *gh = msgb_l3(msg);
- u_int8_t *classmark2_lv = gh->data + 1;
- u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
- *mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
+ /* Check the size for the classmark */
+ if (length < 1 + *classmark2_lv)
+ return -1;
+ u_int8_t *mi_lv = classmark2_lv + *classmark2_lv + 1;
+ if (length < 2 + *classmark2_lv + mi_lv[0])
+ return -2;
+
+ *mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
return gsm48_mi_to_string(mi_string, GSM48_MI_SIZE, mi_lv+1, *mi_lv);
}
+int gsm48_paging_extract_mi(struct gsm48_pag_resp *resp, int length,
+ char *mi_string, u_int8_t *mi_type)
+{
+ static const uint32_t classmark_offset =
+ offsetof(struct gsm48_pag_resp, classmark2);
+ u_int8_t *classmark2_lv = (uint8_t *) &resp->classmark2;
+ return gsm48_extract_mi(classmark2_lv, length - classmark_offset,
+ mi_string, mi_type);
+}
+
int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr)
{
struct gsm_bts *bts = msg->lchan->ts->trx->bts;
@@ -354,7 +345,7 @@
/* FIXME: optional bits for type of synchronization? */
- return gsm48_sendmsg(msg, NULL);
+ return gsm48_sendmsg(msg);
}
/* Chapter 9.1.2: Assignment Command */
@@ -397,7 +388,7 @@
}
}
- return gsm48_sendmsg(msg, NULL);
+ return gsm48_sendmsg(msg);
}
/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
@@ -438,7 +429,7 @@
}
}
- return gsm48_sendmsg(msg, NULL);
+ return gsm48_sendmsg(msg);
}
int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode)
@@ -573,3 +564,36 @@
return 0;
}
+
+struct msgb *gsm48_create_mm_serv_rej(enum gsm48_reject_value value)
+{
+ struct msgb *msg;
+ struct gsm48_hdr *gh;
+
+ msg = gsm48_msgb_alloc();
+ if (!msg)
+ return NULL;
+
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
+ gh->proto_discr = GSM48_PDISC_MM;
+ gh->msg_type = GSM48_MT_MM_CM_SERV_REJ;
+ gh->data[0] = value;
+
+ return msg;
+}
+
+struct msgb *gsm48_create_loc_upd_rej(uint8_t cause)
+{
+ struct gsm48_hdr *gh;
+ struct msgb *msg;
+
+ msg = gsm48_msgb_alloc();
+ if (!msg)
+ return NULL;
+
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
+ gh->proto_discr = GSM48_PDISC_MM;
+ gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
+ gh->data[0] = cause;
+ return msg;
+}
diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c
index 3492f1f..ee0aba5 100644
--- a/openbsc/src/gsm_04_11.c
+++ b/openbsc/src/gsm_04_11.c
@@ -4,6 +4,8 @@
/* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
* (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On Waves
*
* All Rights Reserved
*
@@ -24,7 +26,6 @@
*/
-#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -48,12 +49,11 @@
#include <openbsc/paging.h>
#include <openbsc/bsc_rll.h>
#include <openbsc/chan_alloc.h>
+#include <openbsc/bsc_api.h>
#define GSM411_ALLOC_SIZE 1024
#define GSM411_ALLOC_HEADROOM 128
-#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */
-
void *tall_gsms_ctx;
static u_int32_t new_callref = 0x40000001;
@@ -100,6 +100,8 @@
{ 0, NULL }
};
+static int gsm411_send_sms(struct gsm_subscriber_connection *conn, struct gsm_sms *sms);
+
struct gsm_sms *sms_alloc(void)
{
return talloc_zero(tall_gsms_ctx, struct gsm_sms);
@@ -116,6 +118,19 @@
talloc_free(sms);
}
+/*
+ * This should be called whenever all SMS to a given subscriber
+ * on a given connection has been sent. This will inform the higher
+ * layers that a channel can be given up.
+ */
+static void gsm411_release_conn(struct gsm_subscriber_connection *conn)
+{
+ if (!conn)
+ return;
+
+ subscr_put_channel(conn);
+}
+
struct msgb *gsm411_msgb_alloc(void)
{
return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
@@ -368,9 +383,11 @@
enum sms_alphabet alpha = DCS_NONE;
if ((cgbits & 0xc) == 0) {
- if (cgbits & 2)
+ if (cgbits & 2) {
LOGP(DSMS, LOGL_NOTICE,
"Compressed SMS not supported yet\n");
+ return 0xffffffff;
+ }
switch ((dcs >> 2)&0x03) {
case 0:
@@ -405,8 +422,6 @@
}
/* dispatch a signal to tell higher level about it */
dispatch_signal(SS_SMS, S_SMS_SUBMITTED, gsms);
- /* try delivering the SMS right now */
- //gsm411_send_sms_subscr(gsms->receiver, gsms);
return 0;
}
@@ -450,11 +465,6 @@
/* TP-UDHI (indicating TP-UD contains a header) */
if (sms->ud_hdr_ind)
*smsp |= 0x40;
-#if 0
- /* TP-RP (indicating that a reply path exists) */
- if (sms->
- *smsp |= 0x80;
-#endif
/* generate originator address */
oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
@@ -550,6 +560,10 @@
gsms->data_coding_scheme = *smsp++;
sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
+ if (sms_alphabet == 0xffffffff) {
+ sms_free(gsms);
+ return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
+ }
switch (sms_vpf) {
case GSM340_TP_VPF_RELATIVE:
@@ -586,7 +600,7 @@
}
}
- gsms->sender = subscr_get(msg->lchan->conn.subscr);
+ gsms->sender = subscr_get(conn->subscr);
LOGP(DSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, "
"MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, "
@@ -745,20 +759,14 @@
trans->sms.sms = NULL;
/* check for more messages for this subscriber */
- assert(msg->lchan->conn.subscr == trans->subscr);
-
sms = db_sms_get_unsent_for_subscr(trans->subscr);
if (sms)
- gsm411_send_sms_lchan(trans->conn, sms);
+ gsm411_send_sms(trans->conn, sms);
+ else
+ gsm411_release_conn(trans->conn);
/* free the transaction here */
trans_free(trans);
-
- /* release channel if done */
-#warning "BROKEN. The SAPI will be released automatically by the BSC"
- if (!sms)
- rsl_release_request(msg->lchan, trans->sms.link_id);
-
return 0;
}
@@ -808,8 +816,6 @@
sms_free(sms);
trans->sms.sms = NULL;
- //trans_free(trans);
-
return 0;
}
@@ -828,13 +834,11 @@
dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
/* check for more messages for this subscriber */
- assert(msg->lchan->conn.subscr == trans->subscr);
sms = db_sms_get_unsent_for_subscr(trans->subscr);
if (sms)
- gsm411_send_sms_lchan(trans->conn, sms);
+ gsm411_send_sms(trans->conn, sms);
else
- rsl_release_request(msg->lchan, trans->sms.link_id);
-#warning "BROKEN: The SAPI=3 will be released automatically by the BSC"
+ gsm411_release_conn(trans->conn);
return rc;
}
@@ -908,25 +912,25 @@
}
/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
-int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
+int gsm0411_rcv_sms(struct gsm_subscriber_connection *conn,
+ struct msgb *msg, u_int8_t link_id)
{
struct gsm48_hdr *gh = msgb_l3(msg);
u_int8_t msg_type = gh->msg_type;
u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
- struct gsm_lchan *lchan = msg->lchan;
struct gsm_trans *trans;
int rc = 0;
- if (!lchan->conn.subscr)
+ if (!conn->subscr)
return -EIO;
/* FIXME: send some error message */
DEBUGP(DSMS, "trans_id=%x ", transaction_id);
- trans = trans_find_by_id(lchan->conn.subscr, GSM48_PDISC_SMS,
+ trans = trans_find_by_id(conn->subscr, GSM48_PDISC_SMS,
transaction_id);
if (!trans) {
DEBUGPC(DSMS, "(new) ");
- trans = trans_alloc(lchan->conn.subscr, GSM48_PDISC_SMS,
+ trans = trans_alloc(conn->subscr, GSM48_PDISC_SMS,
transaction_id, new_callref++);
if (!trans) {
DEBUGPC(DSMS, "No memory for trans\n");
@@ -938,7 +942,7 @@
trans->sms.is_mt = 0;
trans->sms.link_id = link_id;
- trans->conn = &lchan->conn;
+ trans->conn = conn;
use_subscr_con(trans->conn);
}
@@ -958,7 +962,7 @@
if (i == transaction_id)
continue;
- ptrans = trans_find_by_id(lchan->conn.subscr,
+ ptrans = trans_find_by_id(conn->subscr,
GSM48_PDISC_SMS, i);
if (!ptrans)
continue;
@@ -1000,7 +1004,7 @@
bsc_del_timer(&trans->sms.cp_timer);
if (!trans->sms.is_mt) {
- /* FIXME: we have sont one CP-DATA, which was now
+ /* FIXME: we have sent one CP-DATA, which was now
* acknowledged. Check if we want to transfer more,
* i.e. multi-part message */
trans->sms.cp_state = GSM411_CPS_IDLE;
@@ -1025,20 +1029,10 @@
return rc;
}
-#if 0
-/* Test TPDU - ALL YOUR */
-static u_int8_t tpdu_test[] = {
- 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
- 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
- 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
- 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
-};
-#endif
-
/* Take a SMS in gsm_sms structure and send it through an already
* existing lchan. We also assume that the caller ensured this lchan already
* has a SAPI3 RLL connection! */
-int gsm411_send_sms_lchan(struct gsm_subscriber_connection *conn, struct gsm_sms *sms)
+static int gsm411_send_sms(struct gsm_subscriber_connection *conn, struct gsm_sms *sms)
{
struct msgb *msg = gsm411_msgb_alloc();
struct gsm_trans *trans;
@@ -1050,6 +1044,7 @@
transaction_id = trans_assign_trans_id(conn->subscr, GSM48_PDISC_SMS, 0);
if (transaction_id == -1) {
LOGP(DSMS, LOGL_ERROR, "No available transaction ids\n");
+ sms_free(sms);
return -EBUSY;
}
@@ -1060,6 +1055,7 @@
transaction_id, new_callref++);
if (!trans) {
LOGP(DSMS, LOGL_ERROR, "No memory for trans\n");
+ sms_free(sms);
/* FIXME: send some error message */
return -ENOMEM;
}
@@ -1090,20 +1086,16 @@
/* obtain a pointer for the rp_ud_len, so we can fill it later */
rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
-#if 1
/* generate the 03.40 TPDU */
rc = gsm340_gen_tpdu(msg, sms);
if (rc < 0) {
+ trans_free(trans);
+ sms_free(sms);
msgb_free(msg);
return rc;
}
*rp_ud_len = rc;
-#else
- data = msgb_put(msg, sizeof(tpdu_test));
- memcpy(data, tpdu_test, sizeof(tpdu_test));
- *rp_ud_len = sizeof(tpdu_test);
-#endif
DEBUGP(DSMS, "TX: SMS DELIVER\n");
@@ -1113,30 +1105,6 @@
/* FIXME: enter 'wait for RP-ACK' state, start TR1N */
}
-/* RLL SAPI3 establish callback. Now we have a RLL connection and
- * can deliver the actual message */
-static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
- void *_sms, enum bsc_rllr_ind type)
-{
- struct gsm_sms *sms = _sms;
-
- DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
- lchan, link_id, sms, type);
-
- switch (type) {
- case BSC_RLLR_IND_EST_CONF:
-#warning "BROKEN: The BSC will establish this transparently"
- gsm411_send_sms_lchan(&lchan->conn, sms);
- break;
- case BSC_RLLR_IND_REL_IND:
- case BSC_RLLR_IND_ERR_IND:
- case BSC_RLLR_IND_TIMEOUT:
-#warning "BROKEN: We will need to handle SAPI n Reject"
- sms_free(sms);
- break;
- }
-}
-
/* paging callback. Here we get called if paging a subscriber has
* succeeded or failed. */
static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
@@ -1144,7 +1112,7 @@
{
struct gsm_lchan *lchan = _lchan;
struct gsm_sms *sms = _sms;
- int rc;
+ int rc = 0;
DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
"lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
@@ -1154,22 +1122,14 @@
switch (event) {
case GSM_PAGING_SUCCEEDED:
- /* Paging aborted without lchan ?!? */
- if (!lchan) {
- sms_free(sms);
- rc = -EIO;
- break;
- }
- /* Establish a SAPI3 RLL connection for SMS */
- rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
+ use_subscr_con(&lchan->conn);
+ gsm411_send_sms(&lchan->conn, sms);
break;
case GSM_PAGING_EXPIRED:
+ case GSM_PAGING_OOM:
sms_free(sms);
rc = -ETIMEDOUT;
break;
- default:
- rc = -EINVAL;
- break;
}
return rc;
@@ -1181,22 +1141,18 @@
int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
struct gsm_sms *sms)
{
- struct gsm_lchan *lchan;
- int rc;
+ struct gsm_subscriber_connection *conn;
/* check if we already have an open lchan to the subscriber.
* if yes, send the SMS this way */
- lchan = lchan_for_subscr(subscr);
- if (lchan)
- return rll_establish(lchan, UM_SAPI_SMS,
- rll_ind_cb, sms);
+ conn = connection_for_subscr(subscr);
+ if (conn) {
+ use_subscr_con(conn);
+ return gsm411_send_sms(conn, sms);
+ }
/* if not, we have to start paging */
- rc = paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
- paging_cb_send_sms, sms);
- if (rc <= 0)
- sms_free(sms);
-
+ subscr_get_channel(subscr, RSL_CHANNEED_SDCCH, paging_cb_send_sms, sms);
return 0;
}
@@ -1204,7 +1160,7 @@
void *handler_data, void *signal_data)
{
struct gsm_subscriber *subscr;
- struct gsm_lchan *lchan;
+ struct gsm_subscriber_connection *conn;
struct gsm_sms *sms;
switch (signal) {
@@ -1212,14 +1168,14 @@
/* A subscriber has attached. Check if there are
* any pending SMS for him to be delivered */
subscr = signal_data;
- lchan = lchan_for_subscr(subscr);
- if (!lchan)
+ conn = connection_for_subscr(subscr);
+ if (!conn)
break;
sms = db_sms_get_unsent_for_subscr(subscr);
if (!sms)
break;
- /* Establish a SAPI3 RLL connection for SMS */
- rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
+ use_subscr_con(conn);
+ gsm411_send_sms(conn, sms);
break;
default:
break;
@@ -1229,9 +1185,35 @@
void _gsm411_sms_trans_free(struct gsm_trans *trans)
{
+ if (trans->sms.sms) {
+ LOGP(DSMS, LOGL_ERROR, "Transaction contains SMS.\n");
+ sms_free(trans->sms.sms);
+ trans->sms.sms = NULL;
+ }
+
bsc_del_timer(&trans->sms.cp_timer);
}
+void gsm411_sapi_n_reject(struct gsm_subscriber_connection *conn)
+{
+ struct gsm_trans *trans, *tmp;
+
+ llist_for_each_entry_safe(trans, tmp, &conn->bts->network->trans_list, entry)
+ if (trans->conn == conn) {
+ struct gsm_sms *sms = trans->sms.sms;
+ if (!sms) {
+ LOGP(DSMS, LOGL_ERROR, "SAPI Reject but no SMS.\n");
+ continue;
+ }
+
+ sms_free(sms);
+ trans->sms.sms = NULL;
+ trans_free(trans);
+ }
+
+ gsm411_release_conn(conn);
+}
+
static __attribute__((constructor)) void on_dso_load_sms(void)
{
register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
diff --git a/openbsc/src/gsm_04_80.c b/openbsc/src/gsm_04_80.c
index ef10b17..7d6679b 100644
--- a/openbsc/src/gsm_04_80.c
+++ b/openbsc/src/gsm_04_80.c
@@ -36,6 +36,7 @@
#include <osmocore/gsm_utils.h>
#include <openbsc/gsm_04_08.h>
#include <openbsc/gsm_04_80.h>
+#include <openbsc/bsc_api.h>
/* Forward declarations */
static int parse_ussd(u_int8_t *ussd, struct ussd_request *req);
@@ -294,7 +295,7 @@
| (1<<7); /* TI direction = 1 */
gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE;
- return gsm48_sendmsg(msg, NULL);
+ return gsm0808_submit_dtap(&msg->lchan->conn, msg, 0);
}
int gsm0480_send_ussd_reject(const struct msgb *in_msg,
@@ -324,5 +325,5 @@
gh->proto_discr |= req->transaction_id | (1<<7); /* TI direction = 1 */
gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE;
- return gsm48_sendmsg(msg, NULL);
+ return gsm0808_submit_dtap(&msg->lchan->conn, msg, 0);
}
diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c
index a4b3212..9de4c1f 100644
--- a/openbsc/src/gsm_data.c
+++ b/openbsc/src/gsm_data.c
@@ -88,6 +88,7 @@
{ LCHAN_S_ACTIVE, "ACTIVE" },
{ LCHAN_S_INACTIVE, "INACTIVE" },
{ LCHAN_S_REL_REQ, "RELEASE REQUESTED" },
+ { LCHAN_S_REL_ERR, "RELEASE DUE ERROR" },
{ 0, NULL }
};
@@ -534,6 +535,8 @@
break;
case GSM_BTS_TYPE_BS11:
break;
+ case GSM_BTS_TYPE_UNKNOWN:
+ break;
}
return 0;
diff --git a/openbsc/src/gsm_subscriber_base.c b/openbsc/src/gsm_subscriber_base.c
index 40c3bbd..264f128 100644
--- a/openbsc/src/gsm_subscriber_base.c
+++ b/openbsc/src/gsm_subscriber_base.c
@@ -106,7 +106,7 @@
/* paging failed, quit now */
if (rc <= 0) {
subscr_paging_cb(GSM_HOOK_RR_PAGING, GSM_PAGING_EXPIRED,
- NULL, NULL, request->param);
+ NULL, NULL, subscr);
}
}
@@ -185,9 +185,8 @@
}
}
-void subscr_put_channel(struct gsm_lchan *lchan)
+void subscr_put_channel(struct gsm_subscriber_connection *conn)
{
- struct gsm_subscriber_connection *conn = &lchan->conn;
/*
* FIXME: Continue with other requests now... by checking
* the gsm_subscriber inside the gsm_lchan. Drop the ref count
@@ -208,7 +207,7 @@
put_subscr_con(conn);
- if (lchan->conn.subscr && !llist_empty(&lchan->conn.subscr->requests))
- subscr_send_paging_request(lchan->conn.subscr);
+ if (conn->subscr && !llist_empty(&conn->subscr->requests))
+ subscr_send_paging_request(conn->subscr);
}
diff --git a/openbsc/src/input/ipaccess.c b/openbsc/src/input/ipaccess.c
index 721cadd..4968e80 100644
--- a/openbsc/src/input/ipaccess.c
+++ b/openbsc/src/input/ipaccess.c
@@ -44,6 +44,7 @@
#include <openbsc/subchan_demux.h>
#include <openbsc/e1_input.h>
#include <openbsc/ipaccess.h>
+#include <openbsc/socket.h>
#include <osmocore/talloc.h>
#define PRIV_OML 1
@@ -763,13 +764,13 @@
e1h->gsmnet = gsmnet;
/* Listen for OML connections */
- ret = make_sock(&e1h->listen_fd, IPPROTO_TCP, IPA_TCP_PORT_OML,
+ ret = make_sock(&e1h->listen_fd, IPPROTO_TCP, 0, IPA_TCP_PORT_OML,
listen_fd_cb);
if (ret < 0)
return ret;
/* Listen for RSL connections */
- ret = make_sock(&e1h->rsl_listen_fd, IPPROTO_TCP,
+ ret = make_sock(&e1h->rsl_listen_fd, IPPROTO_TCP, 0,
IPA_TCP_PORT_RSL, rsl_listen_fd_cb);
if (ret < 0)
return ret;
diff --git a/openbsc/src/ipaccess/ipaccess-config.c b/openbsc/src/ipaccess/ipaccess-config.c
index f27e51f..52b18e2 100644
--- a/openbsc/src/ipaccess/ipaccess-config.c
+++ b/openbsc/src/ipaccess/ipaccess-config.c
@@ -602,18 +602,20 @@
static void print_help(void)
{
- printf(" -u --unit-id UNIT_ID\n");
- printf(" -o --oml-ip ip\n");
- printf(" -r --restart\n");
- printf(" -n flags/mask\tSet NVRAM attributes.\n");
- printf(" -l --listen testnr \tPerform specified test number\n");
- printf(" -h --help this text\n");
- printf(" -s --stream-id ID\n");
- printf(" -d --software firmware\n");
+ printf(" -u --unit-id UNIT_ID\tSet the Unit ID of the BTS\n");
+ printf(" -o --oml-ip IP\tSet primary OML IP (IP of your BSC)\n");
+ printf(" -r --restart\t\tRestart the BTS (after other operations)\n");
+ printf(" -n flags/mask\t\tSet NVRAM attributes.\n");
+ printf(" -l --listen testnr\tPerform specified test number\n");
+ printf(" -h --help\t\tthis text\n");
+ printf(" -s --stream-id ID\tSet the IPA Stream Identifier for OML\n");
+ printf(" -d --software firmware Download firmware into BTS\n");
printf(" -f --firmware firmware Provide firmware information\n");
- printf(" -w --write-firmware. This will dump the firmware parts to the filesystem. Use with -f.\n");
+ printf(" -w --write-firmware This will dump the firmware parts to the filesystem. Use with -f.\n");
}
+extern void bts_model_nanobts_init();
+
int main(int argc, char **argv)
{
struct gsm_bts *bts;
diff --git a/openbsc/src/ipaccess/ipaccess-proxy.c b/openbsc/src/ipaccess/ipaccess-proxy.c
index 3860813..0310749 100644
--- a/openbsc/src/ipaccess/ipaccess-proxy.c
+++ b/openbsc/src/ipaccess/ipaccess-proxy.c
@@ -1,6 +1,8 @@
/* OpenBSC Abis/IP proxy ip.access nanoBTS */
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by On Waves
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
*
* All Rights Reserved
*
@@ -34,6 +36,9 @@
#include <arpa/inet.h>
#include <netinet/in.h>
+#define _GNU_SOURCE
+#include <getopt.h>
+
#include <openbsc/gsm_data.h>
#include <osmocore/select.h>
#include <osmocore/tlv.h>
@@ -54,6 +59,9 @@
struct llist_head bts_list;
/* the BSC reconnect timer */
struct timer_list reconn_timer;
+ /* global GPRS NS data */
+ struct in_addr gprs_addr;
+ struct in_addr listen_addr;
};
/* global pointer to the proxy structure */
@@ -64,7 +72,6 @@
struct llist_head tx_queue;
struct ipa_bts_conn *bts_conn;
};
-
#define MAX_TRX 4
/* represents a particular BTS in our proxy */
@@ -91,6 +98,13 @@
struct bsc_fd udp_bts_fd;
struct bsc_fd udp_bsc_fd;
+ /* NS data */
+ struct in_addr bts_addr;
+ struct bsc_fd gprs_ns_fd;
+ int gprs_local_port;
+ uint16_t gprs_orig_port;
+ uint32_t gprs_orig_ip;
+
char *id_tags[0xff];
u_int8_t *id_resp;
unsigned int id_resp_len;
@@ -110,8 +124,12 @@
static char *listen_ipaddr;
static char *bsc_ipaddr;
+static char *gprs_ns_ipaddr;
-#define PROXY_ALLOC_SIZE 300
+static int make_gprs_sock(struct bsc_fd *bfd, int (*cb)(struct bsc_fd*,unsigned int), void *);
+static int gprs_ns_cb(struct bsc_fd *bfd, unsigned int what);
+
+#define PROXY_ALLOC_SIZE 1200
static const u_int8_t pong[] = { 0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_PONG };
static const u_int8_t id_ack[] = { 0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_ID_ACK };
@@ -492,6 +510,28 @@
goto err_udp_bsc;
DEBUGP(DINP, "(%u/%u/%u) Created UDP socket for injection "
"towards BSC at port %u\n", site_id, bts_id, trx_id, udp_port);
+
+
+ /* GPRS NS related code */
+ if (gprs_ns_ipaddr) {
+ struct sockaddr_in sock;
+ socklen_t len = sizeof(sock);
+ ret = make_gprs_sock(&ipbc->gprs_ns_fd, gprs_ns_cb, ipbc);
+ if (ret < 0) {
+ LOGP(DINP, LOGL_ERROR, "Creating the GPRS socket failed.\n");
+ goto err_udp_bsc;
+ }
+
+ ret = getsockname(ipbc->gprs_ns_fd.fd, (struct sockaddr* ) &sock, &len);
+ ipbc->gprs_local_port = ntohs(sock.sin_port);
+ LOGP(DINP, LOGL_NOTICE,
+ "Created GPRS NS Socket. Listening on: %s:%d\n",
+ inet_ntoa(sock.sin_addr), ipbc->gprs_local_port);
+
+ ret = getpeername(bfd->fd, (struct sockaddr* ) &sock, &len);
+ ipbc->bts_addr = sock.sin_addr;
+ }
+
llist_add(&ipbc->list, &ipp->bts_list);
return 0;
@@ -617,6 +657,10 @@
DEBUGP(DMI, "ID_ACK? -> ACK!\n");
ret = write(bfd->fd, id_ack, sizeof(id_ack));
break;
+ default:
+ LOGP(DMI, LOGL_ERROR, "Unhandled IPA type; %d\n", msg_type);
+ return 1;
+ break;
}
return 0;
}
@@ -805,6 +849,42 @@
talloc_free(ipc);
}
+static void patch_gprs_msg(struct ipa_bts_conn *ipbc, int priv_nr, struct msgb *msg)
+{
+ uint8_t *nsvci;
+
+ if ((priv_nr & 0xff) != OML_FROM_BTS && (priv_nr & 0xff) != OML_TO_BSC)
+ return;
+
+ if (msgb_l2len(msg) != 39)
+ return;
+
+ /*
+ * Check if this is a IPA Set Attribute or IPA Set Attribute ACK
+ * and if the FOM Class is GPRS NSVC0 and then we will patch it.
+ *
+ * The patch assumes the message looks like the one from the trace
+ * but we only match messages with a specific size anyway... So
+ * this hack should work just fine.
+ */
+
+ if (msg->l2h[0] == 0x10 && msg->l2h[1] == 0x80 &&
+ msg->l2h[2] == 0x00 && msg->l2h[3] == 0x15 &&
+ msg->l2h[18] == 0xf5 && msg->l2h[19] == 0xf2) {
+ nsvci = &msg->l2h[23];
+ ipbc->gprs_orig_port = *(u_int16_t *)(nsvci+8);
+ ipbc->gprs_orig_ip = *(u_int32_t *)(nsvci+10);
+ *(u_int16_t *)(nsvci+8) = htons(ipbc->gprs_local_port);
+ *(u_int32_t *)(nsvci+10) = ipbc->ipp->listen_addr.s_addr;
+ } else if (msg->l2h[0] == 0x10 && msg->l2h[1] == 0x80 &&
+ msg->l2h[2] == 0x00 && msg->l2h[3] == 0x15 &&
+ msg->l2h[18] == 0xf6 && msg->l2h[19] == 0xf2) {
+ nsvci = &msg->l2h[23];
+ *(u_int16_t *)(nsvci+8) = ipbc->gprs_orig_port;
+ *(u_int32_t *)(nsvci+10) = ipbc->gprs_orig_ip;
+ }
+}
+
static int handle_tcp_read(struct bsc_fd *bfd)
{
struct ipa_proxy_conn *ipc = bfd->data;
@@ -843,11 +923,14 @@
close(bfd->fd);
bfd->fd = -1;
talloc_free(bfd);
+ msgb_free(msg);
+ return ret;
+ } else if (ret == 0) {
+ /* we do not forward parts of the CCM protocol
+ * through the proxy but rather terminate it ourselves. */
+ msgb_free(msg);
+ return ret;
}
- /* we do not forward the CCM protocol through the
- * proxy but rather terminate it ourselves */
- msgb_free(msg);
- return ret;
}
if (!ipbc) {
@@ -859,6 +942,8 @@
bsc_conn = ipc_by_priv_nr(ipbc, bfd->priv_nr);
if (bsc_conn) {
+ if (gprs_ns_ipaddr)
+ patch_gprs_msg(ipbc, bfd->priv_nr, msg);
/* enqueue packet towards BSC */
msgb_enqueue(&bsc_conn->tx_queue, msg);
/* mark respective filedescriptor as 'we want to write' */
@@ -977,6 +1062,54 @@
return 0;
}
+static void send_ns(int fd, const char *buf, int size, struct in_addr ip, int port)
+{
+ int ret;
+ struct sockaddr_in addr;
+ socklen_t len = sizeof(addr);
+ memset(&addr, 0, sizeof(addr));
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr = ip;
+
+ ret = sendto(fd, buf, size, 0, (struct sockaddr *) &addr, len);
+ if (ret < 0) {
+ LOGP(DINP, LOGL_ERROR, "Failed to forward GPRS message.\n");
+ }
+}
+
+static int gprs_ns_cb(struct bsc_fd *bfd, unsigned int what)
+{
+ struct ipa_bts_conn *bts;
+ char buf[4096];
+ int ret;
+ struct sockaddr_in sock;
+ socklen_t len = sizeof(sock);
+
+ /* 1. get the data... */
+ ret = recvfrom(bfd->fd, buf, sizeof(buf), 0, (struct sockaddr *) &sock, &len);
+ if (ret < 0) {
+ LOGP(DINP, LOGL_ERROR, "Failed to recv GPRS NS msg: %s.\n", strerror(errno));
+ return -1;
+ }
+
+ bts = bfd->data;
+
+ /* 2. figure out where to send it to */
+ if (memcmp(&sock.sin_addr, &ipp->gprs_addr, sizeof(sock.sin_addr)) == 0) {
+ LOGP(DINP, LOGL_DEBUG, "GPRS NS msg from network.\n");
+ send_ns(bfd->fd, buf, ret, bts->bts_addr, 23000);
+ } else if (memcmp(&sock.sin_addr, &bts->bts_addr, sizeof(sock.sin_addr)) == 0) {
+ LOGP(DINP, LOGL_DEBUG, "GPRS NS msg from BTS.\n");
+ send_ns(bfd->fd, buf, ret, ipp->gprs_addr, 23000);
+ } else {
+ LOGP(DINP, LOGL_ERROR, "Unknown GPRS source: %s\n", inet_ntoa(sock.sin_addr));
+ }
+
+ return 0;
+}
+
static int make_listen_sock(struct bsc_fd *bfd, u_int16_t port, int priv_nr,
int (*cb)(struct bsc_fd *fd, unsigned int what))
{
@@ -1000,8 +1133,9 @@
ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
- LOGP(DINP, LOGL_ERROR, "could not bind listen socket %s\n",
- strerror(errno));
+ LOGP(DINP, LOGL_ERROR,
+ "Could not bind listen socket for IP %s with error: %s.\n",
+ listen_ipaddr, strerror(errno));
return -EIO;
}
@@ -1019,6 +1153,37 @@
return 0;
}
+static int make_gprs_sock(struct bsc_fd *bfd, int (*cb)(struct bsc_fd*,unsigned int), void *data)
+{
+ struct sockaddr_in addr;
+ int ret;
+
+ bfd->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ bfd->cb = cb;
+ bfd->data = data;
+ bfd->when = BSC_FD_READ;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = 0;
+ inet_aton(listen_ipaddr, &addr.sin_addr);
+
+ ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
+ if (ret < 0) {
+ LOGP(DINP, LOGL_ERROR,
+ "Could not bind n socket for IP %s with error: %s.\n",
+ listen_ipaddr, strerror(errno));
+ return -EIO;
+ }
+
+ ret = bsc_register_fd(bfd);
+ if (ret < 0) {
+ perror("register_listen_fd");
+ return ret;
+ }
+ return 0;
+}
+
/* Actively connect to a BSC. */
static struct ipa_proxy_conn *connect_bsc(struct sockaddr_in *sa, int priv_nr, void *data)
{
@@ -1043,7 +1208,8 @@
ret = connect(bfd->fd, (struct sockaddr *) sa, sizeof(*sa));
if (ret < 0) {
- LOGP(DINP, LOGL_ERROR, "could not connect socket\n");
+ LOGP(DINP, LOGL_ERROR, "Could not connect socket: %s\n",
+ inet_ntoa(sa->sin_addr));
close(bfd->fd);
talloc_free(ipc);
return NULL;
@@ -1081,6 +1247,15 @@
ret = make_listen_sock(&ipp->rsl_listen_fd, IPA_TCP_PORT_RSL,
RSL_FROM_BTS, listen_fd_cb);
+ if (ret < 0)
+ return ret;
+
+ /* Connect the GPRS NS Socket */
+ if (gprs_ns_ipaddr) {
+ inet_aton(gprs_ns_ipaddr, &ipp->gprs_addr);
+ inet_aton(listen_ipaddr, &ipp->listen_addr);
+ }
+
return ret;
}
@@ -1100,6 +1275,75 @@
}
}
+static void print_help()
+{
+ printf(" ipaccess-proxy is a proxy BTS.\n");
+ printf(" -h --help. This help text.\n");
+ printf(" -l --listen IP. The ip to listen to.\n");
+ printf(" -b --bsc IP. The BSC IP address.\n");
+ printf(" -g --gprs IP. Take GPRS NS from that IP.\n");
+ printf("\n");
+ printf(" -s --disable-color. Disable the color inside the logging message.\n");
+ printf(" -e --log-level number. Set the global loglevel.\n");
+ printf(" -T --timestamp. Prefix every log message with a timestamp.\n");
+ printf(" -V --version. Print the version of OpenBSC.\n");
+}
+
+static void print_usage()
+{
+ printf("Usage: ipaccess-proxy\n");
+}
+
+static void handle_options(int argc, char** argv)
+{
+ while (1) {
+ int option_index = 0, c;
+ static struct option long_options[] = {
+ {"help", 0, 0, 'h'},
+ {"disable-color", 0, 0, 's'},
+ {"timestamp", 0, 0, 'T'},
+ {"log-level", 1, 0, 'e'},
+ {"listen", 1, 0, 'l'},
+ {"bsc", 1, 0, 'b'},
+ {"udp", 1, 0, 'u'},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long(argc, argv, "hsTe:l:b:g:",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_usage();
+ print_help();
+ exit(0);
+ case 'l':
+ listen_ipaddr = optarg;
+ break;
+ case 'b':
+ bsc_ipaddr = optarg;
+ break;
+ case 'g':
+ gprs_ns_ipaddr = optarg;
+ break;
+ case 's':
+ log_set_use_color(stderr_target, 0);
+ break;
+ case 'T':
+ log_set_print_timestamp(stderr_target, 1);
+ break;
+ case 'e':
+ log_set_log_level(stderr_target, atoi(optarg));
+ break;
+ default:
+ /* ignore */
+ break;
+ }
+ }
+}
+
int main(int argc, char **argv)
{
int rc;
@@ -1115,6 +1359,8 @@
log_set_all_filter(stderr_target, 1);
log_parse_category_mask(stderr_target, "DINP:DMI");
+ handle_options(argc, argv);
+
rc = ipaccess_proxy_setup();
if (rc < 0)
exit(1);
diff --git a/openbsc/src/mgcp/mgcp_main.c b/openbsc/src/mgcp/mgcp_main.c
index f7f1f80..d5b6502 100644
--- a/openbsc/src/mgcp/mgcp_main.c
+++ b/openbsc/src/mgcp/mgcp_main.c
@@ -39,10 +39,10 @@
#include <osmocore/select.h>
#include <openbsc/mgcp.h>
#include <openbsc/mgcp_internal.h>
-#include <openbsc/telnet_interface.h>
+#include <osmocom/vty//telnet_interface.h>
#include <openbsc/vty.h>
-#include <vty/command.h>
+#include <osmocom/vty/command.h>
#include "../../bscconfig.h"
@@ -58,7 +58,6 @@
static struct mgcp_config *cfg;
static int reset_endpoints = 0;
-const char *openbsc_version = "OpenBSC MGCP " PACKAGE_VERSION;
const char *openbsc_copyright =
"Copyright (C) 2009-2010 Holger Freyther and On-Waves\n"
"Contributions by Daniel Willmann, Jan Lübbe,Stefan Schmidt\n"
@@ -79,12 +78,6 @@
printf(" -c --config-file filename The config file to use.\n");
}
-static void print_mgcp_version()
-{
- printf("%s\n\n", openbsc_version);
- printf("%s", openbsc_copyright);
-}
-
static void handle_options(int argc, char** argv)
{
while (1) {
@@ -110,7 +103,7 @@
config_file = talloc_strdup(tall_bsc_ctx, optarg);
break;
case 'V':
- print_mgcp_version();
+ print_version(1);
exit(0);
break;
default:
@@ -181,6 +174,13 @@
return 0;
}
+extern enum node_type bsc_vty_go_parent(struct vty *vty);
+
+static struct vty_app_info vty_info = {
+ .name = "OpenBSC MGCP",
+ .version = PACKAGE_VERSION,
+ .go_parent_cb = bsc_vty_go_parent,
+};
int main(int argc, char** argv)
{
@@ -200,13 +200,21 @@
if (!cfg)
return -1;
+ vty_info.copyright = openbsc_copyright;
+ vty_init(&vty_info);
+ logging_vty_add_cmds();
+ mgcp_vty_init();
+
handle_options(argc, argv);
- telnet_init(&dummy_network, 4243);
rc = mgcp_parse_config(config_file, cfg);
if (rc < 0)
return rc;
+ rc = telnet_init(tall_bsc_ctx, &dummy_network, 4243);
+ if (rc < 0)
+ return rc;
+
/* set some callbacks */
cfg->reset_cb = mgcp_rsip_cb;
cfg->change_cb = mgcp_change_cb;
@@ -259,15 +267,3 @@
return 0;
}
-
-struct gsm_network;
-int bsc_vty_init(struct gsm_network *dummy)
-{
- cmd_init(1);
- vty_init();
-
- openbsc_vty_add_cmds();
- mgcp_vty_init();
- return 0;
-}
-
diff --git a/openbsc/src/mgcp/mgcp_vty.c b/openbsc/src/mgcp/mgcp_vty.c
index 3286198..f923b22 100644
--- a/openbsc/src/mgcp/mgcp_vty.c
+++ b/openbsc/src/mgcp/mgcp_vty.c
@@ -29,9 +29,10 @@
#include <openbsc/debug.h>
#include <openbsc/mgcp.h>
#include <openbsc/mgcp_internal.h>
+#include <openbsc/vty.h>
-#include <vty/command.h>
-#include <vty/vty.h>
+#include <osmocom/vty/command.h>
+#include <osmocom/vty/vty.h>
#include <string.h>
@@ -254,6 +255,8 @@
install_element(CONFIG_NODE, &cfg_mgcp_cmd);
install_node(&mgcp_node, config_write_mgcp);
install_default(MGCP_NODE);
+ install_element(MGCP_NODE, &ournode_exit_cmd);
+ install_element(MGCP_NODE, &ournode_end_cmd);
install_element(MGCP_NODE, &cfg_mgcp_local_ip_cmd);
install_element(MGCP_NODE, &cfg_mgcp_bts_ip_cmd);
install_element(MGCP_NODE, &cfg_mgcp_bind_ip_cmd);
@@ -276,7 +279,7 @@
int i, rc;
g_cfg = cfg;
- rc = vty_read_config_file(config_file);
+ rc = vty_read_config_file(config_file, NULL);
if (rc < 0) {
fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
return rc;
diff --git a/openbsc/src/nat/Makefile.am b/openbsc/src/nat/Makefile.am
new file mode 100644
index 0000000..0ca3bdf
--- /dev/null
+++ b/openbsc/src/nat/Makefile.am
@@ -0,0 +1,13 @@
+INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
+AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS)
+
+bin_PROGRAMS = bsc_nat
+
+
+bsc_nat_SOURCES = bsc_filter.c bsc_mgcp_utils.c bsc_nat.c bsc_nat_utils.c \
+ bsc_nat_vty.c bsc_sccp.c \
+ $(top_srcdir)/src/debug.c $(top_srcdir)/src/bsc_msc.c
+bsc_nat_LDADD = $(top_builddir)/src/libvty.a $(top_builddir)/src/libsccp.a \
+ $(top_builddir)/src/libmgcp.a $(top_builddir)/src/libbsc.a \
+ -lrt
diff --git a/openbsc/src/nat/bsc_filter.c b/openbsc/src/nat/bsc_filter.c
new file mode 100644
index 0000000..8f79f00
--- /dev/null
+++ b/openbsc/src/nat/bsc_filter.c
@@ -0,0 +1,216 @@
+/* BSC Multiplexer/NAT */
+
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <openbsc/bsc_nat.h>
+#include <openbsc/ipaccess.h>
+#include <openbsc/debug.h>
+
+#include <osmocore/talloc.h>
+#include <osmocore/protocol/gsm_08_08.h>
+
+#include <sccp/sccp.h>
+
+/*
+ * The idea is to have a simple struct describing a IPA packet with
+ * SCCP SSN and the GSM 08.08 payload and decide. We will both have
+ * a white and a blacklist of packets we want to handle.
+ *
+ * TODO: Implement a "NOT" in the filter language.
+ */
+
+#define ALLOW_ANY -1
+
+#define FILTER_TO_BSC 1
+#define FILTER_TO_MSC 2
+#define FILTER_TO_BOTH 3
+
+
+struct bsc_pkt_filter {
+ int ipa_proto;
+ int dest_ssn;
+ int bssap;
+ int gsm;
+ int filter_dir;
+};
+
+static struct bsc_pkt_filter black_list[] = {
+ /* filter reset messages to the MSC */
+ { IPAC_PROTO_SCCP, SCCP_SSN_BSSAP, 0, BSS_MAP_MSG_RESET, FILTER_TO_MSC },
+
+ /* filter reset ack messages to the BSC */
+ { IPAC_PROTO_SCCP, SCCP_SSN_BSSAP, 0, BSS_MAP_MSG_RESET_ACKNOWLEDGE, FILTER_TO_BSC },
+
+ /* filter ip access */
+ { IPAC_PROTO_IPACCESS, ALLOW_ANY, ALLOW_ANY, ALLOW_ANY, FILTER_TO_MSC },
+};
+
+static struct bsc_pkt_filter white_list[] = {
+ /* allow IPAC_PROTO_SCCP messages to both sides */
+ { IPAC_PROTO_SCCP, ALLOW_ANY, ALLOW_ANY, ALLOW_ANY, FILTER_TO_BOTH },
+
+ /* allow MGCP messages to both sides */
+ { NAT_IPAC_PROTO_MGCP, ALLOW_ANY, ALLOW_ANY, ALLOW_ANY, FILTER_TO_BOTH },
+};
+
+struct bsc_nat_parsed* bsc_nat_parse(struct msgb *msg)
+{
+ struct sccp_parse_result result;
+ struct bsc_nat_parsed *parsed;
+ struct ipaccess_head *hh;
+
+ /* quick fail */
+ if (msg->len < 4)
+ return NULL;
+
+ parsed = talloc_zero(msg, struct bsc_nat_parsed);
+ if (!parsed)
+ return NULL;
+
+ /* more init */
+ parsed->ipa_proto = parsed->called_ssn = parsed->calling_ssn = -1;
+ parsed->sccp_type = parsed->bssap = parsed->gsm_type = -1;
+
+ /* start parsing */
+ hh = (struct ipaccess_head *) msg->data;
+ parsed->ipa_proto = hh->proto;
+
+ msg->l2h = &hh->data[0];
+
+ /* do a size check on the input */
+ if (ntohs(hh->len) != msgb_l2len(msg)) {
+ LOGP(DINP, LOGL_ERROR, "Wrong input length?\n");
+ talloc_free(parsed);
+ return NULL;
+ }
+
+ /* analyze sccp down here */
+ if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
+ memset(&result, 0, sizeof(result));
+ if (sccp_parse_header(msg, &result) != 0) {
+ talloc_free(parsed);
+ return 0;
+ }
+
+ if (msg->l3h && msgb_l3len(msg) < 3) {
+ LOGP(DNAT, LOGL_ERROR, "Not enough space or GSM payload\n");
+ talloc_free(parsed);
+ return 0;
+ }
+
+ parsed->sccp_type = sccp_determine_msg_type(msg);
+ parsed->src_local_ref = result.source_local_reference;
+ parsed->dest_local_ref = result.destination_local_reference;
+ parsed->called_ssn = result.called.ssn;
+ parsed->calling_ssn = result.calling.ssn;
+
+ /* in case of connection confirm we have no payload */
+ if (msg->l3h) {
+ parsed->bssap = msg->l3h[0];
+ parsed->gsm_type = msg->l3h[2];
+ }
+ }
+
+ return parsed;
+}
+
+int bsc_nat_filter_ipa(int dir, struct msgb *msg, struct bsc_nat_parsed *parsed)
+{
+ int i;
+
+ /* go through the blacklist now */
+ for (i = 0; i < ARRAY_SIZE(black_list); ++i) {
+ /* ignore the rule? */
+ if (black_list[i].filter_dir != FILTER_TO_BOTH
+ && black_list[i].filter_dir != dir)
+ continue;
+
+ /* the proto is not blacklisted */
+ if (black_list[i].ipa_proto != ALLOW_ANY
+ && black_list[i].ipa_proto != parsed->ipa_proto)
+ continue;
+
+ if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
+ /* the SSN is not blacklisted */
+ if (black_list[i].dest_ssn != ALLOW_ANY
+ && black_list[i].dest_ssn != parsed->called_ssn)
+ continue;
+
+ /* bssap */
+ if (black_list[i].bssap != ALLOW_ANY
+ && black_list[i].bssap != parsed->bssap)
+ continue;
+
+ /* gsm */
+ if (black_list[i].gsm != ALLOW_ANY
+ && black_list[i].gsm != parsed->gsm_type)
+ continue;
+
+ /* blacklisted */
+ LOGP(DNAT, LOGL_INFO, "Blacklisted with rule %d\n", i);
+ return 1;
+ } else {
+ /* blacklisted, we have no content sniffing yet */
+ LOGP(DNAT, LOGL_INFO, "Blacklisted with rule %d\n", i);
+ return 1;
+ }
+ }
+
+ /* go through the whitelust now */
+ for (i = 0; i < ARRAY_SIZE(white_list); ++i) {
+ /* ignore the rule? */
+ if (white_list[i].filter_dir != FILTER_TO_BOTH
+ && white_list[i].filter_dir != dir)
+ continue;
+
+ /* the proto is not whitelisted */
+ if (white_list[i].ipa_proto != ALLOW_ANY
+ && white_list[i].ipa_proto != parsed->ipa_proto)
+ continue;
+
+ if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
+ /* the SSN is not whitelisted */
+ if (white_list[i].dest_ssn != ALLOW_ANY
+ && white_list[i].dest_ssn != parsed->called_ssn)
+ continue;
+
+ /* bssap */
+ if (white_list[i].bssap != ALLOW_ANY
+ && white_list[i].bssap != parsed->bssap)
+ continue;
+
+ /* gsm */
+ if (white_list[i].gsm != ALLOW_ANY
+ && white_list[i].gsm != parsed->gsm_type)
+ continue;
+
+ /* whitelisted */
+ LOGP(DNAT, LOGL_INFO, "Whitelisted with rule %d\n", i);
+ return 0;
+ } else {
+ /* whitelisted */
+ return 0;
+ }
+ }
+
+ return 1;
+}
diff --git a/openbsc/src/nat/bsc_mgcp_utils.c b/openbsc/src/nat/bsc_mgcp_utils.c
new file mode 100644
index 0000000..5d24acf
--- /dev/null
+++ b/openbsc/src/nat/bsc_mgcp_utils.c
@@ -0,0 +1,559 @@
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <openbsc/bsc_nat.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/debug.h>
+#include <openbsc/mgcp.h>
+#include <openbsc/mgcp_internal.h>
+
+#include <sccp/sccp.h>
+
+#include <osmocore/talloc.h>
+#include <osmocore/gsm0808.h>
+#include <osmocore/protocol/gsm_08_08.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+int bsc_mgcp_assign(struct sccp_connections *con, struct msgb *msg)
+{
+ struct sccp_connections *mcon;
+ struct tlv_parsed tp;
+ u_int16_t cic;
+ u_int8_t timeslot;
+ u_int8_t multiplex;
+ int combined;
+
+ if (!msg->l3h) {
+ LOGP(DNAT, LOGL_ERROR, "Assignment message should have l3h pointer.\n");
+ return -1;
+ }
+
+ if (msgb_l3len(msg) < 3) {
+ LOGP(DNAT, LOGL_ERROR, "Assignment message has not enough space for GSM0808.\n");
+ return -1;
+ }
+
+ tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 3, msgb_l3len(msg) - 3, 0, 0);
+ if (!TLVP_PRESENT(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE)) {
+ LOGP(DNAT, LOGL_ERROR, "Circuit identity code not found in assignment message.\n");
+ return -1;
+ }
+
+ cic = ntohs(*(u_int16_t *)TLVP_VAL(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE));
+ timeslot = cic & 0x1f;
+ multiplex = (cic & ~0x1f) >> 5;
+
+
+ combined = (32 * multiplex) + timeslot;
+
+ /* find stale connections using that endpoint */
+ llist_for_each_entry(mcon, &con->bsc->nat->sccp_connections, list_entry) {
+ if (mcon->msc_timeslot == combined) {
+ LOGP(DNAT, LOGL_ERROR,
+ "Timeslot %d was assigned to 0x%x and now 0x%x\n",
+ combined,
+ sccp_src_ref_to_int(&mcon->patched_ref),
+ sccp_src_ref_to_int(&con->patched_ref));
+ bsc_mgcp_dlcx(mcon);
+ }
+ }
+
+ con->msc_timeslot = combined;
+ con->bsc_timeslot = con->msc_timeslot;
+ return 0;
+}
+
+static void bsc_mgcp_free_endpoint(struct bsc_nat *nat, int i)
+{
+ if (nat->bsc_endpoints[i].transaction_id) {
+ talloc_free(nat->bsc_endpoints[i].transaction_id);
+ nat->bsc_endpoints[i].transaction_id = NULL;
+ }
+
+ nat->bsc_endpoints[i].bsc = NULL;
+}
+
+void bsc_mgcp_free_endpoints(struct bsc_nat *nat)
+{
+ int i;
+
+ for (i = 1; i < nat->mgcp_cfg->number_endpoints; ++i){
+ bsc_mgcp_free_endpoint(nat, i);
+ mgcp_free_endp(&nat->mgcp_cfg->endpoints[i]);
+ }
+}
+
+/* send a MDCX where we do not want a response */
+static void bsc_mgcp_send_mdcx(struct bsc_connection *bsc, struct mgcp_endpoint *endp)
+{
+ char buf[2096];
+ int len;
+
+ len = snprintf(buf, sizeof(buf),
+ "MDCX 23 %x@mgw MGCP 1.0\r\n"
+ "Z: noanswer\r\n"
+ "\r\n"
+ "c=IN IP4 %s\r\n"
+ "m=audio %d RTP/AVP 255\r\n",
+ ENDPOINT_NUMBER(endp),
+ bsc->nat->mgcp_cfg->source_addr,
+ endp->rtp_port);
+ if (len < 0) {
+ LOGP(DMGCP, LOGL_ERROR, "snprintf for DLCX failed.\n");
+ return;
+ }
+}
+
+static void bsc_mgcp_send_dlcx(struct bsc_connection *bsc, int endpoint)
+{
+ char buf[2096];
+ int len;
+
+ len = snprintf(buf, sizeof(buf),
+ "DLCX 23 %x@mgw MGCP 1.0\r\n"
+ "Z: noanswer\r\n", endpoint);
+ if (len < 0) {
+ LOGP(DMGCP, LOGL_ERROR, "snprintf for DLCX failed.\n");
+ return;
+ }
+
+ bsc_write_mgcp(bsc, (u_int8_t *) buf, len);
+}
+
+void bsc_mgcp_init(struct sccp_connections *con)
+{
+ con->msc_timeslot = -1;
+ con->bsc_timeslot = -1;
+ con->crcx = 0;
+}
+
+void bsc_mgcp_dlcx(struct sccp_connections *con)
+{
+ /* send a DLCX down the stream */
+ if (con->bsc_timeslot != -1 && con->crcx) {
+ int endp = mgcp_timeslot_to_endpoint(0, con->msc_timeslot);
+ bsc_mgcp_send_dlcx(con->bsc, endp);
+ bsc_mgcp_free_endpoint(con->bsc->nat, endp);
+ }
+
+ bsc_mgcp_init(con);
+}
+
+
+struct sccp_connections *bsc_mgcp_find_con(struct bsc_nat *nat, int endpoint)
+{
+ struct sccp_connections *con = NULL;
+ struct sccp_connections *sccp;
+
+ llist_for_each_entry(sccp, &nat->sccp_connections, list_entry) {
+ if (sccp->msc_timeslot == -1)
+ continue;
+ if (mgcp_timeslot_to_endpoint(0, sccp->msc_timeslot) != endpoint)
+ continue;
+
+ con = sccp;
+ }
+
+ if (con)
+ return con;
+
+ LOGP(DMGCP, LOGL_ERROR, "Failed to find the connection.\n");
+ return NULL;
+}
+
+int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const char *transaction_id)
+{
+ struct bsc_nat *nat;
+ struct bsc_endpoint *bsc_endp;
+ struct sccp_connections *sccp;
+ struct mgcp_endpoint *mgcp_endp;
+ struct msgb *bsc_msg;
+
+ nat = cfg->data;
+ bsc_endp = &nat->bsc_endpoints[endpoint];
+ mgcp_endp = &nat->mgcp_cfg->endpoints[endpoint];
+
+ if (bsc_endp->transaction_id) {
+ LOGP(DMGCP, LOGL_ERROR, "Endpoint 0x%x had pending transaction: '%s'\n",
+ endpoint, bsc_endp->transaction_id);
+ talloc_free(bsc_endp->transaction_id);
+ bsc_endp->transaction_id = NULL;
+ }
+ bsc_endp->bsc = NULL;
+
+ sccp = bsc_mgcp_find_con(nat, endpoint);
+
+ if (!sccp) {
+ LOGP(DMGCP, LOGL_ERROR, "Did not find BSC for change on endpoint: 0x%x state: %d\n", endpoint, state);
+
+ switch (state) {
+ case MGCP_ENDP_CRCX:
+ return MGCP_POLICY_REJECT;
+ break;
+ case MGCP_ENDP_DLCX:
+ return MGCP_POLICY_CONT;
+ break;
+ case MGCP_ENDP_MDCX:
+ return MGCP_POLICY_CONT;
+ break;
+ default:
+ LOGP(DMGCP, LOGL_FATAL, "Unhandled state: %d\n", state);
+ return MGCP_POLICY_CONT;
+ break;
+ }
+ }
+
+ /* we need to generate a new and patched message */
+ bsc_msg = bsc_mgcp_rewrite((char *) nat->mgcp_msg, nat->mgcp_length,
+ nat->mgcp_cfg->source_addr, mgcp_endp->rtp_port);
+ if (!bsc_msg) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to patch the msg.\n");
+ return MGCP_POLICY_CONT;
+ }
+
+
+ bsc_endp->transaction_id = talloc_strdup(nat, transaction_id);
+ bsc_endp->bsc = sccp->bsc;
+
+ /* we need to update some bits */
+ if (state == MGCP_ENDP_CRCX) {
+ struct sockaddr_in sock;
+ socklen_t len = sizeof(sock);
+ if (getpeername(sccp->bsc->write_queue.bfd.fd, (struct sockaddr *) &sock, &len) != 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Can not get the peername...%d/%s\n",
+ errno, strerror(errno));
+ } else {
+ mgcp_endp->bts = sock.sin_addr;
+ }
+
+ /* send the message and a fake MDCX for force sending of a dummy packet */
+ sccp->crcx = 1;
+ bsc_write(sccp->bsc, bsc_msg, NAT_IPAC_PROTO_MGCP);
+ bsc_mgcp_send_mdcx(sccp->bsc, mgcp_endp);
+ return MGCP_POLICY_DEFER;
+ } else if (state == MGCP_ENDP_DLCX) {
+ /* we will free the endpoint now and send a DLCX to the BSC */
+ msgb_free(bsc_msg);
+ bsc_mgcp_dlcx(sccp);
+ return MGCP_POLICY_CONT;
+ } else {
+ bsc_write(sccp->bsc, bsc_msg, NAT_IPAC_PROTO_MGCP);
+ return MGCP_POLICY_DEFER;
+ }
+}
+
+/*
+ * We have received a msg from the BSC. We will see if we know
+ * this transaction and if it belongs to the BSC. Then we will
+ * need to patch the content to point to the local network and we
+ * need to update the I: that was assigned by the BSS.
+ */
+void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg)
+{
+ struct msgb *output;
+ struct bsc_endpoint *bsc_endp = NULL;
+ struct mgcp_endpoint *endp = NULL;
+ int i, code;
+ char transaction_id[60];
+
+ /* Some assumption that our buffer is big enough.. and null terminate */
+ if (msgb_l2len(msg) > 2000) {
+ LOGP(DMGCP, LOGL_ERROR, "MGCP message too long.\n");
+ return;
+ }
+
+ msg->l2h[msgb_l2len(msg)] = '\0';
+
+ if (bsc_mgcp_parse_response((const char *) msg->l2h, &code, transaction_id) != 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to parse response code.\n");
+ return;
+ }
+
+ for (i = 1; i < bsc->nat->mgcp_cfg->number_endpoints; ++i) {
+ if (bsc->nat->bsc_endpoints[i].bsc != bsc)
+ continue;
+ /* no one listening? a bug? */
+ if (!bsc->nat->bsc_endpoints[i].transaction_id)
+ continue;
+ if (strcmp(transaction_id, bsc->nat->bsc_endpoints[i].transaction_id) != 0)
+ continue;
+
+ endp = &bsc->nat->mgcp_cfg->endpoints[i];
+ bsc_endp = &bsc->nat->bsc_endpoints[i];
+ break;
+ }
+
+ if (!bsc_endp) {
+ LOGP(DMGCP, LOGL_ERROR, "Could not find active endpoint: %s for msg: '%s'\n",
+ transaction_id, (const char *) msg->l2h);
+ return;
+ }
+
+ endp->ci = bsc_mgcp_extract_ci((const char *) msg->l2h);
+
+ /* free some stuff */
+ talloc_free(bsc_endp->transaction_id);
+ bsc_endp->transaction_id = NULL;
+
+ /*
+ * rewrite the information. In case the endpoint was deleted
+ * there should be nothing for us to rewrite so putting endp->rtp_port
+ * with the value of 0 should be no problem.
+ */
+ output = bsc_mgcp_rewrite((char * ) msg->l2h, msgb_l2len(msg),
+ bsc->nat->mgcp_cfg->source_addr, endp->rtp_port);
+
+ if (!output) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to rewrite MGCP msg.\n");
+ return;
+ }
+
+ if (write_queue_enqueue(&bsc->nat->mgcp_queue, output) != 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to queue MGCP msg.\n");
+ msgb_free(output);
+ }
+}
+
+int bsc_mgcp_parse_response(const char *str, int *code, char transaction[60])
+{
+ /* we want to parse two strings */
+ return sscanf(str, "%3d %59s\n", code, transaction) != 2;
+}
+
+int bsc_mgcp_extract_ci(const char *str)
+{
+ int ci;
+ char *res = strstr(str, "I: ");
+ if (!res)
+ return CI_UNUSED;
+
+ if (sscanf(res, "I: %d", &ci) != 1)
+ return CI_UNUSED;
+ return ci;
+}
+
+/* we need to replace some strings... */
+struct msgb *bsc_mgcp_rewrite(char *input, int length, const char *ip, int port)
+{
+ static const char *ip_str = "c=IN IP4 ";
+ static const char *aud_str = "m=audio ";
+
+ char buf[128];
+ char *running, *token;
+ struct msgb *output;
+
+ if (length > 4096 - 128) {
+ LOGP(DMGCP, LOGL_ERROR, "Input is too long.\n");
+ return NULL;
+ }
+
+ output = msgb_alloc_headroom(4096, 128, "MGCP rewritten");
+ if (!output) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to allocate new MGCP msg.\n");
+ return NULL;
+ }
+
+ running = input;
+ output->l2h = output->data;
+ for (token = strsep(&running, "\n"); running; token = strsep(&running, "\n")) {
+ int len = strlen(token);
+ int cr = len > 0 && token[len - 1] == '\r';
+
+ if (strncmp(ip_str, token, (sizeof ip_str) - 1) == 0) {
+ output->l3h = msgb_put(output, strlen(ip_str));
+ memcpy(output->l3h, ip_str, strlen(ip_str));
+ output->l3h = msgb_put(output, strlen(ip));
+ memcpy(output->l3h, ip, strlen(ip));
+
+ if (cr) {
+ output->l3h = msgb_put(output, 2);
+ output->l3h[0] = '\r';
+ output->l3h[1] = '\n';
+ } else {
+ output->l3h = msgb_put(output, 1);
+ output->l3h[0] = '\n';
+ }
+ } else if (strncmp(aud_str, token, (sizeof aud_str) - 1) == 0) {
+ int payload;
+ if (sscanf(token, "m=audio %*d RTP/AVP %d", &payload) != 1) {
+ LOGP(DMGCP, LOGL_ERROR, "Could not parsed audio line.\n");
+ msgb_free(output);
+ return NULL;
+ }
+
+ snprintf(buf, sizeof(buf)-1, "m=audio %d RTP/AVP %d%s",
+ port, payload, cr ? "\r\n" : "\n");
+ buf[sizeof(buf)-1] = '\0';
+
+ output->l3h = msgb_put(output, strlen(buf));
+ memcpy(output->l3h, buf, strlen(buf));
+ } else {
+ output->l3h = msgb_put(output, len + 1);
+ memcpy(output->l3h, token, len);
+ output->l3h[len] = '\n';
+ }
+ }
+
+ return output;
+}
+
+static int mgcp_do_read(struct bsc_fd *fd)
+{
+ struct bsc_nat *nat;
+ struct msgb *msg, *resp;
+ int rc;
+
+ nat = fd->data;
+
+ rc = read(fd->fd, nat->mgcp_msg, sizeof(nat->mgcp_msg) - 1);
+ if (rc <= 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to read errno: %d\n", errno);
+ return -1;
+ }
+
+ nat->mgcp_msg[rc] = '\0';
+ nat->mgcp_length = rc;
+
+ msg = msgb_alloc(sizeof(nat->mgcp_msg), "MGCP GW Read");
+ if (!msg) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to create buffer.\n");
+ return -1;
+ }
+
+ msg->l2h = msgb_put(msg, rc);
+ memcpy(msg->l2h, nat->mgcp_msg, msgb_l2len(msg));
+ resp = mgcp_handle_message(nat->mgcp_cfg, msg);
+ msgb_free(msg);
+
+ /* we do have a direct answer... e.g. AUEP */
+ if (resp) {
+ if (write_queue_enqueue(&nat->mgcp_queue, resp) != 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to enqueue msg.\n");
+ msgb_free(resp);
+ }
+ }
+
+ return 0;
+}
+
+static int mgcp_do_write(struct bsc_fd *bfd, struct msgb *msg)
+{
+ int rc;
+
+ rc = write(bfd->fd, msg->data, msg->len);
+
+ if (rc != msg->len) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to write msg to MGCP CallAgent.\n");
+ return -1;
+ }
+
+ return rc;
+}
+
+int bsc_mgcp_nat_init(struct bsc_nat *nat)
+{
+ int on;
+ struct sockaddr_in addr;
+
+ if (!nat->mgcp_cfg->call_agent_addr) {
+ LOGP(DMGCP, LOGL_ERROR, "The BSC nat requires the call agent ip to be set.\n");
+ return -1;
+ }
+
+ if (nat->mgcp_cfg->bts_ip) {
+ LOGP(DMGCP, LOGL_ERROR, "Do not set the BTS ip for the nat.\n");
+ return -1;
+ }
+
+ nat->mgcp_queue.bfd.fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (nat->mgcp_queue.bfd.fd < 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to create MGCP socket. errno: %d\n", errno);
+ return -1;
+ }
+
+ on = 1;
+ setsockopt(nat->mgcp_queue.bfd.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(nat->mgcp_cfg->source_port);
+ inet_aton(nat->mgcp_cfg->source_addr, &addr.sin_addr);
+
+ if (bind(nat->mgcp_queue.bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to bind. errno: %d\n", errno);
+ close(nat->mgcp_queue.bfd.fd);
+ nat->mgcp_queue.bfd.fd = -1;
+ return -1;
+ }
+
+ addr.sin_port = htons(2727);
+ inet_aton(nat->mgcp_cfg->call_agent_addr, &addr.sin_addr);
+ if (connect(nat->mgcp_queue.bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to connect to: '%s'. errno: %d\n",
+ nat->mgcp_cfg->call_agent_addr, errno);
+ close(nat->mgcp_queue.bfd.fd);
+ nat->mgcp_queue.bfd.fd = -1;
+ return -1;
+ }
+
+ write_queue_init(&nat->mgcp_queue, 10);
+ nat->mgcp_queue.bfd.when = BSC_FD_READ;
+ nat->mgcp_queue.bfd.data = nat;
+ nat->mgcp_queue.read_cb = mgcp_do_read;
+ nat->mgcp_queue.write_cb = mgcp_do_write;
+
+ if (bsc_register_fd(&nat->mgcp_queue.bfd) != 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Failed to register MGCP fd.\n");
+ close(nat->mgcp_queue.bfd.fd);
+ nat->mgcp_queue.bfd.fd = -1;
+ return -1;
+ }
+
+ /* some more MGCP config handling */
+ nat->mgcp_cfg->audio_payload = -1;
+ nat->mgcp_cfg->data = nat;
+ nat->mgcp_cfg->policy_cb = bsc_mgcp_policy_cb;
+ nat->mgcp_cfg->force_realloc = 1;
+ nat->mgcp_cfg->bts_ip = "";
+ nat->bsc_endpoints = talloc_zero_array(nat,
+ struct bsc_endpoint,
+ nat->mgcp_cfg->number_endpoints + 1);
+
+ return 0;
+}
+
+void bsc_mgcp_clear_endpoints_for(struct bsc_connection *bsc)
+{
+ int i;
+ for (i = 1; i < bsc->nat->mgcp_cfg->number_endpoints; ++i) {
+ struct bsc_endpoint *bsc_endp = &bsc->nat->bsc_endpoints[i];
+
+ if (bsc_endp->bsc != bsc)
+ continue;
+
+ bsc_mgcp_free_endpoint(bsc->nat, i);
+ mgcp_free_endp(&bsc->nat->mgcp_cfg->endpoints[i]);
+ }
+}
diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c
new file mode 100644
index 0000000..2e8a00d
--- /dev/null
+++ b/openbsc/src/nat/bsc_nat.c
@@ -0,0 +1,1171 @@
+/* BSC Multiplexer/NAT */
+
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+#include <openbsc/debug.h>
+#include <openbsc/bsc_msc.h>
+#include <openbsc/bsc_nat.h>
+#include <openbsc/ipaccess.h>
+#include <openbsc/abis_nm.h>
+#include <openbsc/vty.h>
+
+#include <osmocore/gsm0808.h>
+#include <osmocore/talloc.h>
+
+#include <osmocore/protocol/gsm_08_08.h>
+
+#include <osmocom/vty/telnet_interface.h>
+#include <osmocom/vty/vty.h>
+
+#include <sccp/sccp.h>
+
+#include "../../bscconfig.h"
+
+#define SCCP_CLOSE_TIME 20
+#define SCCP_CLOSE_TIME_TIMEOUT 19
+
+struct log_target *stderr_target;
+static const char *config_file = "bsc-nat.cfg";
+static struct in_addr local_addr;
+static struct bsc_fd bsc_listen;
+static const char *msc_ip = NULL;
+static struct timer_list sccp_close;
+
+const char *openbsc_copyright =
+ "Copyright (C) 2010 Holger Hans Peter Freyther and On-Waves\n"
+ "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>\n"
+ "This is free software: you are free to change and redistribute it.\n"
+ "There is NO WARRANTY, to the extent permitted by law.\n";
+
+static struct bsc_nat *nat;
+static void bsc_send_data(struct bsc_connection *bsc, const u_int8_t *data, unsigned int length, int);
+static void msc_send_reset(struct bsc_msc_connection *con);
+
+struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num)
+{
+ struct bsc_config *conf;
+
+ llist_for_each_entry(conf, &nat->bsc_configs, entry)
+ if (conf->nr == num)
+ return conf;
+
+ return NULL;
+}
+
+/*
+ * below are stubs we need to link
+ */
+int nm_state_event(enum nm_evt evt, 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_ins)
+{
+ return -1;
+}
+
+void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
+{}
+
+int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id)
+{
+ return -1;
+}
+
+static void queue_for_msc(struct bsc_msc_connection *con, struct msgb *msg)
+{
+ if (write_queue_enqueue(&nat->msc_con->write_queue, msg) != 0) {
+ LOGP(DINP, LOGL_ERROR, "Failed to enqueue the write.\n");
+ msgb_free(msg);
+ }
+}
+
+static void send_reset_ack(struct bsc_connection *bsc)
+{
+ static const u_int8_t gsm_reset_ack[] = {
+ 0x09, 0x00, 0x03, 0x07, 0x0b, 0x04, 0x43, 0x01,
+ 0x00, 0xfe, 0x04, 0x43, 0x5c, 0x00, 0xfe, 0x03,
+ 0x00, 0x01, 0x31,
+ };
+
+ bsc_send_data(bsc, gsm_reset_ack, sizeof(gsm_reset_ack), IPAC_PROTO_SCCP);
+}
+
+static void send_ping(struct bsc_connection *bsc)
+{
+ static const u_int8_t id_ping[] = {
+ IPAC_MSGT_PING,
+ };
+
+ bsc_send_data(bsc, id_ping, sizeof(id_ping), IPAC_PROTO_IPACCESS);
+}
+
+static void send_pong(struct bsc_connection *bsc)
+{
+ static const u_int8_t id_pong[] = {
+ IPAC_MSGT_PONG,
+ };
+
+ bsc_send_data(bsc, id_pong, sizeof(id_pong), IPAC_PROTO_IPACCESS);
+}
+
+static void bsc_pong_timeout(void *_bsc)
+{
+ struct bsc_connection *bsc = _bsc;
+
+ LOGP(DNAT, LOGL_ERROR, "BSC Nr: %d PONG timeout.\n", bsc->cfg->nr);
+ bsc_close_connection(bsc);
+}
+
+static void bsc_ping_timeout(void *_bsc)
+{
+ struct bsc_connection *bsc = _bsc;
+
+ if (bsc->nat->ping_timeout < 0)
+ return;
+
+ send_ping(bsc);
+
+ /* send another ping in 20 seconds */
+ bsc_schedule_timer(&bsc->ping_timeout, bsc->nat->ping_timeout, 0);
+
+ /* also start a pong timer */
+ bsc_schedule_timer(&bsc->pong_timeout, bsc->nat->pong_timeout, 0);
+}
+
+static void start_ping_pong(struct bsc_connection *bsc)
+{
+ bsc->pong_timeout.data = bsc;
+ bsc->pong_timeout.cb = bsc_pong_timeout;
+ bsc->ping_timeout.data = bsc;
+ bsc->ping_timeout.cb = bsc_ping_timeout;
+
+ bsc_ping_timeout(bsc);
+}
+
+static void send_id_ack(struct bsc_connection *bsc)
+{
+ static const u_int8_t id_ack[] = {
+ IPAC_MSGT_ID_ACK
+ };
+
+ bsc_send_data(bsc, id_ack, sizeof(id_ack), IPAC_PROTO_IPACCESS);
+}
+
+static void send_id_req(struct bsc_connection *bsc)
+{
+ static const u_int8_t id_req[] = {
+ IPAC_MSGT_ID_GET,
+ 0x01, IPAC_IDTAG_UNIT,
+ 0x01, IPAC_IDTAG_MACADDR,
+ 0x01, IPAC_IDTAG_LOCATION1,
+ 0x01, IPAC_IDTAG_LOCATION2,
+ 0x01, IPAC_IDTAG_EQUIPVERS,
+ 0x01, IPAC_IDTAG_SWVERSION,
+ 0x01, IPAC_IDTAG_UNITNAME,
+ 0x01, IPAC_IDTAG_SERNR,
+ };
+
+ bsc_send_data(bsc, id_req, sizeof(id_req), IPAC_PROTO_IPACCESS);
+}
+
+static void nat_send_rlsd(struct sccp_connections *conn)
+{
+ struct sccp_connection_released *rel;
+ struct msgb *msg;
+
+ msg = msgb_alloc_headroom(4096, 128, "rlsd");
+ if (!msg) {
+ LOGP(DNAT, LOGL_ERROR, "Failed to allocate clear command.\n");
+ return;
+ }
+
+ msg->l2h = msgb_put(msg, sizeof(*rel));
+ rel = (struct sccp_connection_released *) msg->l2h;
+ rel->type = SCCP_MSG_TYPE_RLSD;
+ rel->release_cause = SCCP_RELEASE_CAUSE_SCCP_FAILURE;
+ rel->destination_local_reference = conn->remote_ref;
+ rel->source_local_reference = conn->patched_ref;
+
+ ipaccess_prepend_header(msg, IPAC_PROTO_SCCP);
+
+ queue_for_msc(nat->msc_con, msg);
+}
+
+static void nat_send_rlc(struct sccp_source_reference *src,
+ struct sccp_source_reference *dst)
+{
+ struct sccp_connection_release_complete *rlc;
+ struct msgb *msg;
+
+ msg = msgb_alloc_headroom(4096, 128, "rlc");
+ if (!msg) {
+ LOGP(DNAT, LOGL_ERROR, "Failed to allocate clear command.\n");
+ return;
+ }
+
+ msg->l2h = msgb_put(msg, sizeof(*rlc));
+ rlc = (struct sccp_connection_release_complete *) msg->l2h;
+ rlc->type = SCCP_MSG_TYPE_RLC;
+ rlc->destination_local_reference = *dst;
+ rlc->source_local_reference = *src;
+
+ ipaccess_prepend_header(msg, IPAC_PROTO_SCCP);
+
+ queue_for_msc(nat->msc_con, msg);
+}
+
+static void send_mgcp_reset(struct bsc_connection *bsc)
+{
+ static const u_int8_t mgcp_reset[] = {
+ "RSIP 1 13@mgw MGCP 1.0\r\n"
+ };
+
+ bsc_write_mgcp(bsc, mgcp_reset, sizeof mgcp_reset - 1);
+}
+
+/*
+ * Below is the handling of messages coming
+ * from the MSC and need to be forwarded to
+ * a real BSC.
+ */
+static void initialize_msc_if_needed()
+{
+ if (nat->first_contact)
+ return;
+
+ nat->first_contact = 1;
+ msc_send_reset(nat->msc_con);
+}
+
+static void send_id_get_response()
+{
+ struct msgb *msg = bsc_msc_id_get_resp(nat->token);
+ if (!msg)
+ return;
+
+ ipaccess_prepend_header(msg, IPAC_PROTO_IPACCESS);
+ queue_for_msc(nat->msc_con, msg);
+}
+
+/*
+ * Currently we are lacking refcounting so we need to copy each message.
+ */
+static void bsc_send_data(struct bsc_connection *bsc, const u_int8_t *data, unsigned int length, int proto)
+{
+ struct msgb *msg;
+
+ if (length > 4096 - 128) {
+ LOGP(DINP, LOGL_ERROR, "Can not send message of that size.\n");
+ return;
+ }
+
+ msg = msgb_alloc_headroom(4096, 128, "to-bsc");
+ if (!msg) {
+ LOGP(DINP, LOGL_ERROR, "Failed to allocate memory for BSC msg.\n");
+ return;
+ }
+
+ msg->l2h = msgb_put(msg, length);
+ memcpy(msg->data, data, length);
+
+ bsc_write(bsc, msg, proto);
+}
+
+static void bsc_send_con_refuse(struct bsc_connection *bsc,
+ struct bsc_nat_parsed *parsed, int con_type)
+{
+ struct msgb *payload;
+ struct msgb *refuse;
+
+ if (con_type == NAT_CON_TYPE_LU)
+ payload = gsm48_create_loc_upd_rej(GSM48_REJECT_PLMN_NOT_ALLOWED);
+ else if (con_type == NAT_CON_TYPE_CM_SERV_REQ)
+ payload = gsm48_create_mm_serv_rej(GSM48_REJECT_PLMN_NOT_ALLOWED);
+
+ /*
+ * Some BSCs do not handle the payload inside a SCCP CREF msg
+ * so we will need to:
+ * 1.) Allocate a local connection and mark it as local..
+ * 2.) queue data for downstream.. and the RLC should delete everything
+ */
+ if (payload) {
+ struct msgb *cc, *udt, *rlsd;
+ struct sccp_connections *con;
+ con = create_sccp_src_ref(bsc, parsed);
+ if (!con)
+ goto send_refuse;
+
+ /* declare it local and assign a unique remote_ref */
+ con->con_type = NAT_CON_TYPE_LOCAL_REJECT;
+ con->con_local = 1;
+ con->has_remote_ref = 1;
+ con->remote_ref = con->patched_ref;
+
+ /* 1. create a confirmation */
+ cc = sccp_create_cc(&con->remote_ref, &con->real_ref);
+ if (!cc)
+ goto send_refuse;
+
+ /* 2. create the DT1 */
+ gsm0808_prepend_dtap_header(payload, 0);
+ udt = sccp_create_dt1(&con->real_ref, payload->data, payload->len);
+ if (!udt) {
+ msgb_free(cc);
+ goto send_refuse;
+ }
+
+ /* 3. send a RLSD */
+ rlsd = sccp_create_rlsd(&con->remote_ref, &con->real_ref,
+ SCCP_RELEASE_CAUSE_END_USER_ORIGINATED);
+ if (!rlsd) {
+ msgb_free(cc);
+ msgb_free(udt);
+ goto send_refuse;
+ }
+
+ bsc_write(bsc, cc, IPAC_PROTO_SCCP);
+ bsc_write(bsc, udt, IPAC_PROTO_SCCP);
+ bsc_write(bsc, rlsd, IPAC_PROTO_SCCP);
+ msgb_free(payload);
+ return;
+ }
+
+
+send_refuse:
+ if (payload)
+ msgb_free(payload);
+
+ refuse = sccp_create_refuse(parsed->src_local_ref,
+ SCCP_REFUSAL_SCCP_FAILURE, NULL, 0);
+ if (!refuse) {
+ LOGP(DNAT, LOGL_ERROR,
+ "Creating refuse msg failed for SCCP 0x%x on BSC Nr: %d.\n",
+ sccp_src_ref_to_int(parsed->src_local_ref), bsc->cfg->nr);
+ return;
+ }
+
+ bsc_write(bsc, refuse, IPAC_PROTO_SCCP);
+}
+
+
+static int forward_sccp_to_bts(struct msgb *msg)
+{
+ struct sccp_connections *con;
+ struct bsc_connection *bsc;
+ struct bsc_nat_parsed *parsed;
+ int proto;
+
+ /* filter, drop, patch the message? */
+ parsed = bsc_nat_parse(msg);
+ if (!parsed) {
+ LOGP(DNAT, LOGL_ERROR, "Can not parse msg from BSC.\n");
+ return -1;
+ }
+
+ if (bsc_nat_filter_ipa(DIR_BSC, msg, parsed))
+ goto exit;
+
+ proto = parsed->ipa_proto;
+
+ /* Route and modify the SCCP packet */
+ if (proto == IPAC_PROTO_SCCP) {
+ switch (parsed->sccp_type) {
+ case SCCP_MSG_TYPE_UDT:
+ /* forward UDT messages to every BSC */
+ goto send_to_all;
+ break;
+ case SCCP_MSG_TYPE_RLSD:
+ case SCCP_MSG_TYPE_CREF:
+ case SCCP_MSG_TYPE_DT1:
+ case SCCP_MSG_TYPE_IT:
+ con = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
+ if (parsed->gsm_type == BSS_MAP_MSG_ASSIGMENT_RQST) {
+ counter_inc(nat->stats.sccp.calls);
+
+ if (con) {
+ counter_inc(con->bsc->cfg->stats.sccp.calls);
+ if (bsc_mgcp_assign(con, msg) != 0)
+ LOGP(DNAT, LOGL_ERROR, "Failed to assign...\n");
+ } else
+ LOGP(DNAT, LOGL_ERROR, "Assignment command but no BSC.\n");
+ }
+ break;
+ case SCCP_MSG_TYPE_CC:
+ con = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
+ if (!con || update_sccp_src_ref(con, parsed) != 0)
+ goto exit;
+ break;
+ case SCCP_MSG_TYPE_RLC:
+ LOGP(DNAT, LOGL_ERROR, "Unexpected release complete from MSC.\n");
+ goto exit;
+ break;
+ case SCCP_MSG_TYPE_CR:
+ /* MSC never opens a SCCP connection, fall through */
+ default:
+ goto exit;
+ }
+
+ if (!con && parsed->sccp_type == SCCP_MSG_TYPE_RLSD) {
+ LOGP(DNAT, LOGL_NOTICE, "Sending fake RLC on RLSD message to network.\n");
+ /* Exchange src/dest for the reply */
+ nat_send_rlc(parsed->dest_local_ref, parsed->src_local_ref);
+ } else if (!con)
+ LOGP(DNAT, LOGL_ERROR, "Unknown connection for msg type: 0x%x from the MSC.\n", parsed->sccp_type);
+ }
+
+ talloc_free(parsed);
+ if (!con)
+ return -1;
+ if (!con->bsc->authenticated) {
+ LOGP(DNAT, LOGL_ERROR, "Selected BSC not authenticated.\n");
+ return -1;
+ }
+
+ bsc_send_data(con->bsc, msg->l2h, msgb_l2len(msg), proto);
+ return 0;
+
+send_to_all:
+ /*
+ * Filter Paging from the network. We do not want to send a PAGING
+ * Command to every BSC in our network. We will analys the PAGING
+ * message and then send it to the authenticated messages...
+ */
+ if (parsed->ipa_proto == IPAC_PROTO_SCCP && parsed->gsm_type == BSS_MAP_MSG_PAGING) {
+ int lac;
+ bsc = bsc_nat_find_bsc(nat, msg, &lac);
+ if (bsc && bsc->cfg->forbid_paging)
+ LOGP(DNAT, LOGL_DEBUG, "Paging forbidden for BTS: %d\n", bsc->cfg->nr);
+ else if (bsc)
+ bsc_send_data(bsc, msg->l2h, msgb_l2len(msg), parsed->ipa_proto);
+ else
+ LOGP(DNAT, LOGL_ERROR, "Could not determine BSC for paging on lac: %d/0x%x\n",
+ lac, lac);
+
+ goto exit;
+ }
+ /* currently send this to every BSC connected */
+ llist_for_each_entry(bsc, &nat->bsc_connections, list_entry) {
+ if (!bsc->authenticated)
+ continue;
+
+ bsc_send_data(bsc, msg->l2h, msgb_l2len(msg), parsed->ipa_proto);
+ }
+
+exit:
+ talloc_free(parsed);
+ return 0;
+}
+
+static void msc_connection_was_lost(struct bsc_msc_connection *con)
+{
+ struct bsc_connection *bsc, *tmp;
+
+ counter_inc(nat->stats.msc.reconn);
+
+ LOGP(DMSC, LOGL_ERROR, "Closing all connections downstream.\n");
+ llist_for_each_entry_safe(bsc, tmp, &nat->bsc_connections, list_entry)
+ bsc_close_connection(bsc);
+
+ nat->first_contact = 0;
+ bsc_mgcp_free_endpoints(nat);
+ bsc_msc_schedule_connect(con);
+}
+
+static void msc_send_reset(struct bsc_msc_connection *msc_con)
+{
+ static const u_int8_t reset[] = {
+ 0x00, 0x12, 0xfd,
+ 0x09, 0x00, 0x03, 0x05, 0x07, 0x02, 0x42, 0xfe,
+ 0x02, 0x42, 0xfe, 0x06, 0x00, 0x04, 0x30, 0x04,
+ 0x01, 0x20
+ };
+
+ struct msgb *msg;
+
+ msg = msgb_alloc_headroom(4096, 128, "08.08 reset");
+ if (!msg) {
+ LOGP(DMSC, LOGL_ERROR, "Failed to allocate reset msg.\n");
+ return;
+ }
+
+ msg->l2h = msgb_put(msg, sizeof(reset));
+ memcpy(msg->l2h, reset, msgb_l2len(msg));
+
+ queue_for_msc(nat->msc_con, msg);
+
+ LOGP(DMSC, LOGL_NOTICE, "Scheduled GSM0808 reset msg for the MSC.\n");
+}
+
+static int ipaccess_msc_read_cb(struct bsc_fd *bfd)
+{
+ int error;
+ struct msgb *msg = ipaccess_read_msg(bfd, &error);
+ struct ipaccess_head *hh;
+
+ if (!msg) {
+ if (error == 0)
+ LOGP(DNAT, LOGL_FATAL, "The connection the MSC was lost, exiting\n");
+ else
+ LOGP(DNAT, LOGL_ERROR, "Failed to parse ip access message: %d\n", error);
+
+ bsc_msc_lost(nat->msc_con);
+ return -1;
+ }
+
+ LOGP(DNAT, LOGL_DEBUG, "MSG from MSC: %s proto: %d\n", hexdump(msg->data, msg->len), msg->l2h[0]);
+
+ /* handle base message handling */
+ hh = (struct ipaccess_head *) msg->data;
+ ipaccess_rcvmsg_base(msg, bfd);
+
+ /* initialize the networking. This includes sending a GSM08.08 message */
+ if (hh->proto == IPAC_PROTO_IPACCESS) {
+ if (msg->l2h[0] == IPAC_MSGT_ID_ACK)
+ initialize_msc_if_needed();
+ else if (msg->l2h[0] == IPAC_MSGT_ID_GET)
+ send_id_get_response();
+ } else if (hh->proto == IPAC_PROTO_SCCP)
+ forward_sccp_to_bts(msg);
+
+ msgb_free(msg);
+ return 0;
+}
+
+static int ipaccess_msc_write_cb(struct bsc_fd *bfd, struct msgb *msg)
+{
+ int rc;
+ rc = write(bfd->fd, msg->data, msg->len);
+
+ if (rc != msg->len) {
+ LOGP(DNAT, LOGL_ERROR, "Failed to write MSG to MSC.\n");
+ return -1;
+ }
+
+ return rc;
+}
+
+/*
+ * Below is the handling of messages coming
+ * from the BSC and need to be forwarded to
+ * a real BSC.
+ */
+
+/*
+ * Remove the connection from the connections list,
+ * remove it from the patching of SCCP header lists
+ * as well. Maybe in the future even close connection..
+ */
+void bsc_close_connection(struct bsc_connection *connection)
+{
+ struct sccp_connections *sccp_patch, *tmp;
+
+ /* stop the timeout timer */
+ bsc_del_timer(&connection->id_timeout);
+ bsc_del_timer(&connection->ping_timeout);
+ bsc_del_timer(&connection->pong_timeout);
+
+ /* remove all SCCP connections */
+ llist_for_each_entry_safe(sccp_patch, tmp, &nat->sccp_connections, list_entry) {
+ if (sccp_patch->bsc != connection)
+ continue;
+
+ if (sccp_patch->has_remote_ref)
+ nat_send_rlsd(sccp_patch);
+ sccp_connection_destroy(sccp_patch);
+ }
+
+ /* close endpoints allocated by this BSC */
+ bsc_mgcp_clear_endpoints_for(connection);
+
+ bsc_unregister_fd(&connection->write_queue.bfd);
+ close(connection->write_queue.bfd.fd);
+ write_queue_clear(&connection->write_queue);
+ llist_del(&connection->list_entry);
+
+ talloc_free(connection);
+}
+
+static void ipaccess_close_bsc(void *data)
+{
+ struct sockaddr_in sock;
+ socklen_t len = sizeof(sock);
+ struct bsc_connection *conn = data;
+
+
+ getpeername(conn->write_queue.bfd.fd, (struct sockaddr *) &sock, &len);
+ LOGP(DNAT, LOGL_ERROR, "BSC on %s didn't respond to identity request. Closing.\n",
+ inet_ntoa(sock.sin_addr));
+ bsc_close_connection(conn);
+}
+
+static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc)
+{
+ struct bsc_config *conf;
+ const char* token = (const char *) TLVP_VAL(tvp, IPAC_IDTAG_UNITNAME);
+
+ if (bsc->cfg) {
+ LOGP(DNAT, LOGL_ERROR, "Reauth on fd %d bsc nr %d\n",
+ bsc->write_queue.bfd.fd, bsc->cfg->nr);
+ return;
+ }
+
+ llist_for_each_entry(conf, &bsc->nat->bsc_configs, entry) {
+ if (strcmp(conf->token, token) == 0) {
+ counter_inc(conf->stats.net.reconn);
+ bsc->authenticated = 1;
+ bsc->cfg = conf;
+ bsc_del_timer(&bsc->id_timeout);
+ LOGP(DNAT, LOGL_NOTICE, "Authenticated bsc nr: %d lac: %d on fd %d\n",
+ conf->nr, conf->lac, bsc->write_queue.bfd.fd);
+ start_ping_pong(bsc);
+ return;
+ }
+ }
+
+ LOGP(DNAT, LOGL_ERROR, "No bsc found for token %s on fd: %d.\n", token,
+ bsc->write_queue.bfd.fd);
+}
+
+static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
+{
+ int con_found = 0;
+ int con_filter = 0;
+ struct bsc_connection *con_bsc = NULL;
+ int con_type;
+ struct bsc_nat_parsed *parsed;
+
+ /* Parse and filter messages */
+ parsed = bsc_nat_parse(msg);
+ if (!parsed) {
+ LOGP(DNAT, LOGL_ERROR, "Can not parse msg from BSC.\n");
+ msgb_free(msg);
+ return -1;
+ }
+
+ if (bsc_nat_filter_ipa(DIR_MSC, msg, parsed))
+ goto exit;
+
+ /*
+ * check authentication after filtering to not reject auth
+ * responses coming from the BSC. We have to make sure that
+ * nothing from the exit path will forward things to the MSC
+ */
+ if (!bsc->authenticated) {
+ LOGP(DNAT, LOGL_ERROR, "BSC is not authenticated.\n");
+ msgb_free(msg);
+ return -1;
+ }
+
+
+ /* modify the SCCP entries */
+ if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
+ struct sccp_connections *con;
+ switch (parsed->sccp_type) {
+ case SCCP_MSG_TYPE_CR:
+ if (bsc_nat_filter_sccp_cr(bsc, msg, parsed, &con_type) != 0)
+ goto exit3;
+ if (!create_sccp_src_ref(bsc, parsed))
+ goto exit2;
+ con = patch_sccp_src_ref_to_msc(msg, parsed, bsc);
+ con->con_type = con_type;
+ con_found = 1;
+ con_bsc = con->bsc;
+ break;
+ case SCCP_MSG_TYPE_RLSD:
+ case SCCP_MSG_TYPE_CREF:
+ case SCCP_MSG_TYPE_DT1:
+ case SCCP_MSG_TYPE_CC:
+ case SCCP_MSG_TYPE_IT:
+ con = patch_sccp_src_ref_to_msc(msg, parsed, bsc);
+ if (con) {
+ con_found = 1;
+ con_bsc = con->bsc;
+ con_filter = con->con_local;
+ }
+ break;
+ case SCCP_MSG_TYPE_RLC:
+ con = patch_sccp_src_ref_to_msc(msg, parsed, bsc);
+ if (con) {
+ con_found = 1;
+ con_bsc = con->bsc;
+ con_filter = con->con_local;
+ }
+ remove_sccp_src_ref(bsc, msg, parsed);
+ break;
+ case SCCP_MSG_TYPE_UDT:
+ /* simply forward everything */
+ con = NULL;
+ break;
+ default:
+ LOGP(DNAT, LOGL_ERROR, "Not forwarding to msc sccp type: 0x%x\n", parsed->sccp_type);
+ con = NULL;
+ goto exit2;
+ break;
+ }
+ } else if (parsed->ipa_proto == NAT_IPAC_PROTO_MGCP) {
+ bsc_mgcp_forward(bsc, msg);
+ goto exit2;
+ } else {
+ LOGP(DNAT, LOGL_ERROR, "Not forwarding unknown stream id: 0x%x\n", parsed->ipa_proto);
+ goto exit2;
+ }
+
+ if (con_found && con_bsc != bsc) {
+ LOGP(DNAT, LOGL_ERROR, "The connection belongs to a different BTS: input: %d con: %d\n",
+ bsc->cfg->nr, con_bsc->cfg->nr);
+ goto exit2;
+ }
+
+ /* do not forward messages to the MSC */
+ if (con_filter)
+ goto exit2;
+
+ /* send the non-filtered but maybe modified msg */
+ queue_for_msc(nat->msc_con, msg);
+ talloc_free(parsed);
+ return 0;
+
+exit:
+ /* if we filter out the reset send an ack to the BSC */
+ if (parsed->bssap == 0 && parsed->gsm_type == BSS_MAP_MSG_RESET) {
+ send_reset_ack(bsc);
+ send_reset_ack(bsc);
+ } else if (parsed->ipa_proto == IPAC_PROTO_IPACCESS) {
+ /* do we know who is handling this? */
+ if (msg->l2h[0] == IPAC_MSGT_ID_RESP) {
+ struct tlv_parsed tvp;
+ ipaccess_idtag_parse(&tvp,
+ (unsigned char *) msg->l2h + 2,
+ msgb_l2len(msg) - 2);
+ if (TLVP_PRESENT(&tvp, IPAC_IDTAG_UNITNAME))
+ ipaccess_auth_bsc(&tvp, bsc);
+ }
+
+ goto exit2;
+ }
+
+exit2:
+ talloc_free(parsed);
+ msgb_free(msg);
+ return -1;
+
+exit3:
+ /* send a SCCP Connection Refused */
+ bsc_send_con_refuse(bsc, parsed, con_type);
+ talloc_free(parsed);
+ msgb_free(msg);
+ return -1;
+}
+
+static int ipaccess_bsc_read_cb(struct bsc_fd *bfd)
+{
+ int error;
+ struct bsc_connection *bsc = bfd->data;
+ struct msgb *msg = ipaccess_read_msg(bfd, &error);
+ struct ipaccess_head *hh;
+
+ if (!msg) {
+ if (error == 0)
+ LOGP(DNAT, LOGL_ERROR,
+ "The connection to the BSC Nr: %d was lost. Cleaning it\n",
+ bsc->cfg ? bsc->cfg->nr : -1);
+ else
+ LOGP(DNAT, LOGL_ERROR,
+ "Stream error on BSC Nr: %d. Failed to parse ip access message: %d\n",
+ bsc->cfg ? bsc->cfg->nr : -1, error);
+
+ bsc_close_connection(bsc);
+ return -1;
+ }
+
+
+ LOGP(DNAT, LOGL_DEBUG, "MSG from BSC: %s proto: %d\n", hexdump(msg->data, msg->len), msg->l2h[0]);
+
+ /* Handle messages from the BSC */
+ hh = (struct ipaccess_head *) msg->data;
+
+ /* stop the pong timeout */
+ if (hh->proto == IPAC_PROTO_IPACCESS) {
+ if (msg->l2h[0] == IPAC_MSGT_PONG) {
+ bsc_del_timer(&bsc->pong_timeout);
+ msgb_free(msg);
+ return 0;
+ } else if (msg->l2h[0] == IPAC_MSGT_PING) {
+ send_pong(bsc);
+ msgb_free(msg);
+ return 0;
+ }
+ }
+
+ /* FIXME: Currently no PONG is sent to the BSC */
+ /* FIXME: Currently no ID ACK is sent to the BSC */
+ forward_sccp_to_msc(bsc, msg);
+
+ return 0;
+}
+
+static int ipaccess_bsc_write_cb(struct bsc_fd *bfd, struct msgb *msg)
+{
+ int rc;
+
+ rc = write(bfd->fd, msg->data, msg->len);
+ if (rc != msg->len)
+ LOGP(DNAT, LOGL_ERROR, "Failed to write message to the BSC.\n");
+
+ return rc;
+}
+
+static int ipaccess_listen_bsc_cb(struct bsc_fd *bfd, unsigned int what)
+{
+ struct bsc_connection *bsc;
+ int fd, rc, on;
+ struct sockaddr_in sa;
+ socklen_t sa_len = sizeof(sa);
+
+ if (!(what & BSC_FD_READ))
+ return 0;
+
+ fd = accept(bfd->fd, (struct sockaddr *) &sa, &sa_len);
+ if (fd < 0) {
+ perror("accept");
+ return fd;
+ }
+
+ /* count the reconnect */
+ counter_inc(nat->stats.bsc.reconn);
+
+ /*
+ * if we are not connected to a msc... just close the socket
+ */
+ if (!nat->msc_con->is_connected) {
+ LOGP(DNAT, LOGL_NOTICE, "Disconnecting BSC due lack of MSC connection.\n");
+ close(fd);
+ return 0;
+ }
+
+ on = 1;
+ rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
+ if (rc != 0)
+ LOGP(DNAT, LOGL_ERROR, "Failed to set TCP_NODELAY: %s\n", strerror(errno));
+
+ rc = setsockopt(fd, IPPROTO_IP, IP_TOS,
+ &nat->bsc_ip_tos, sizeof(nat->bsc_ip_tos));
+ if (rc != 0)
+ LOGP(DNAT, LOGL_ERROR, "Failed to set IP_TOS: %s\n", strerror(errno));
+
+ /* todo... do something with the connection */
+ /* todo... use GNUtls to see if we want to trust this as a BTS */
+
+ /*
+ *
+ */
+ bsc = bsc_connection_alloc(nat);
+ if (!bsc) {
+ LOGP(DNAT, LOGL_ERROR, "Failed to allocate BSC struct.\n");
+ close(fd);
+ return -1;
+ }
+
+ bsc->write_queue.bfd.data = bsc;
+ bsc->write_queue.bfd.fd = fd;
+ bsc->write_queue.read_cb = ipaccess_bsc_read_cb;
+ bsc->write_queue.write_cb = ipaccess_bsc_write_cb;
+ bsc->write_queue.bfd.when = BSC_FD_READ;
+ if (bsc_register_fd(&bsc->write_queue.bfd) < 0) {
+ LOGP(DNAT, LOGL_ERROR, "Failed to register BSC fd.\n");
+ close(fd);
+ talloc_free(bsc);
+ return -2;
+ }
+
+ LOGP(DNAT, LOGL_NOTICE, "BSC connection on %d with IP: %s\n",
+ fd, inet_ntoa(sa.sin_addr));
+ llist_add(&bsc->list_entry, &nat->bsc_connections);
+ send_id_ack(bsc);
+ send_id_req(bsc);
+ send_mgcp_reset(bsc);
+
+ /*
+ * start the hangup timer
+ */
+ bsc->id_timeout.data = bsc;
+ bsc->id_timeout.cb = ipaccess_close_bsc;
+ bsc_schedule_timer(&bsc->id_timeout, nat->auth_timeout, 0);
+ return 0;
+}
+
+static int listen_for_bsc(struct bsc_fd *bfd, struct in_addr *in_addr, int port)
+{
+ struct sockaddr_in addr;
+ int ret, on = 1;
+
+ bfd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ bfd->cb = ipaccess_listen_bsc_cb;
+ bfd->when = BSC_FD_READ;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = in_addr->s_addr;
+
+ setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+
+ ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
+ if (ret < 0) {
+ fprintf(stderr, "Could not bind the BSC socket %s\n",
+ strerror(errno));
+ return -EIO;
+ }
+
+ ret = listen(bfd->fd, 1);
+ if (ret < 0) {
+ perror("listen");
+ return ret;
+ }
+
+ ret = bsc_register_fd(bfd);
+ if (ret < 0) {
+ perror("register_listen_fd");
+ return ret;
+ }
+ return 0;
+}
+
+static void print_usage()
+{
+ printf("Usage: bsc_nat\n");
+}
+
+static void print_help()
+{
+ printf(" Some useful help...\n");
+ printf(" -h --help this text\n");
+ printf(" -d option --debug=DRLL:DCC:DMM:DRR:DRSL:DNM enable debugging\n");
+ printf(" -s --disable-color\n");
+ printf(" -c --config-file filename The config file to use.\n");
+ printf(" -m --msc=IP. The address of the MSC.\n");
+ printf(" -l --local=IP. The local address of this BSC.\n");
+}
+
+static void handle_options(int argc, char** argv)
+{
+ while (1) {
+ int option_index = 0, c;
+ static struct option long_options[] = {
+ {"help", 0, 0, 'h'},
+ {"debug", 1, 0, 'd'},
+ {"config-file", 1, 0, 'c'},
+ {"disable-color", 0, 0, 's'},
+ {"timestamp", 0, 0, 'T'},
+ {"msc", 1, 0, 'm'},
+ {"local", 1, 0, 'l'},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long(argc, argv, "hd:sTPc:m:l:",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_usage();
+ print_help();
+ exit(0);
+ case 's':
+ log_set_use_color(stderr_target, 0);
+ break;
+ case 'd':
+ log_parse_category_mask(stderr_target, optarg);
+ break;
+ case 'c':
+ config_file = strdup(optarg);
+ break;
+ case 'T':
+ log_set_print_timestamp(stderr_target, 1);
+ break;
+ case 'm':
+ msc_ip = optarg;
+ break;
+ case 'l':
+ inet_aton(optarg, &local_addr);
+ break;
+ default:
+ /* ignore */
+ break;
+ }
+ }
+}
+
+static void signal_handler(int signal)
+{
+ switch (signal) {
+ case SIGABRT:
+ /* in case of abort, we want to obtain a talloc report
+ * and then return to the caller, who will abort the process */
+ case SIGUSR1:
+ talloc_report_full(tall_bsc_ctx, stderr);
+ break;
+ default:
+ break;
+ }
+}
+
+static void sccp_close_unconfirmed(void *_data)
+{
+ struct sccp_connections *conn, *tmp1;
+ struct timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+
+ llist_for_each_entry_safe(conn, tmp1, &nat->sccp_connections, list_entry) {
+ if (conn->has_remote_ref)
+ continue;
+
+ int diff = (now.tv_sec - conn->creation_time.tv_sec) / 60;
+ if (diff < SCCP_CLOSE_TIME_TIMEOUT)
+ continue;
+
+ LOGP(DNAT, LOGL_ERROR, "SCCP connection 0x%x/0x%x was never confirmed.\n",
+ sccp_src_ref_to_int(&conn->real_ref),
+ sccp_src_ref_to_int(&conn->patched_ref));
+ sccp_connection_destroy(conn);
+ }
+
+ bsc_schedule_timer(&sccp_close, SCCP_CLOSE_TIME, 0);
+}
+
+extern void *tall_msgb_ctx;
+extern void *tall_ctr_ctx;
+static void talloc_init_ctx()
+{
+ tall_bsc_ctx = talloc_named_const(NULL, 0, "nat");
+ tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
+ tall_ctr_ctx = talloc_named_const(tall_bsc_ctx, 0, "counter");
+}
+
+extern enum node_type bsc_vty_go_parent(struct vty *vty);
+
+static struct vty_app_info vty_info = {
+ .name = "BSC NAT",
+ .version = PACKAGE_VERSION,
+ .go_parent_cb = bsc_vty_go_parent,
+};
+
+int main(int argc, char** argv)
+{
+ talloc_init_ctx();
+
+
+ log_init(&log_info);
+ stderr_target = log_target_create_stderr();
+ log_add_target(stderr_target);
+ log_set_all_filter(stderr_target, 1);
+
+ nat = bsc_nat_alloc();
+ if (!nat) {
+ fprintf(stderr, "Failed to allocate the BSC nat.\n");
+ return -4;
+ }
+
+ nat->mgcp_cfg = talloc_zero(nat, struct mgcp_config);
+ if (!nat->mgcp_cfg) {
+ fprintf(stderr, "Failed to allocate MGCP cfg.\n");
+ return -5;
+ }
+
+ vty_info.copyright = openbsc_copyright;
+ vty_init(&vty_info);
+ logging_vty_add_cmds();
+ bsc_nat_vty_init(nat);
+
+
+ /* parse options */
+ local_addr.s_addr = INADDR_ANY;
+ handle_options(argc, argv);
+
+ /* init vty and parse */
+ telnet_init(tall_bsc_ctx, NULL, 4244);
+ if (mgcp_parse_config(config_file, nat->mgcp_cfg) < 0) {
+ fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
+ return -3;
+ }
+
+ /* over rule the VTY config */
+ if (msc_ip)
+ bsc_nat_set_msc_ip(nat, msc_ip);
+
+ /* seed the PRNG */
+ srand(time(NULL));
+
+ /*
+ * Setup the MGCP code..
+ */
+ if (bsc_mgcp_nat_init(nat) != 0)
+ return -4;
+
+ /* connect to the MSC */
+ nat->msc_con = bsc_msc_create(nat->msc_ip, nat->msc_port, 0);
+ if (!nat->msc_con) {
+ fprintf(stderr, "Creating a bsc_msc_connection failed.\n");
+ exit(1);
+ }
+
+ nat->msc_con->connection_loss = msc_connection_was_lost;
+ nat->msc_con->write_queue.read_cb = ipaccess_msc_read_cb;
+ nat->msc_con->write_queue.write_cb = ipaccess_msc_write_cb;;
+ bsc_msc_connect(nat->msc_con);
+
+ /* wait for the BSC */
+ if (listen_for_bsc(&bsc_listen, &local_addr, 5000) < 0) {
+ fprintf(stderr, "Failed to listen for BSC.\n");
+ exit(1);
+ }
+
+ signal(SIGABRT, &signal_handler);
+ signal(SIGUSR1, &signal_handler);
+ signal(SIGPIPE, SIG_IGN);
+
+ /* recycle timer */
+ sccp_close.cb = sccp_close_unconfirmed;
+ sccp_close.data = NULL;
+ bsc_schedule_timer(&sccp_close, SCCP_CLOSE_TIME, 0);
+
+ while (1) {
+ bsc_select_main(0);
+ }
+
+ return 0;
+}
diff --git a/openbsc/src/nat/bsc_nat_utils.c b/openbsc/src/nat/bsc_nat_utils.c
new file mode 100644
index 0000000..eed7f3a
--- /dev/null
+++ b/openbsc/src/nat/bsc_nat_utils.c
@@ -0,0 +1,492 @@
+
+/* BSC Multiplexer/NAT Utilities */
+
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <openbsc/bsc_nat.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/debug.h>
+#include <openbsc/ipaccess.h>
+
+#include <osmocore/linuxlist.h>
+#include <osmocore/talloc.h>
+#include <osmocore/gsm0808.h>
+
+#include <osmocore/protocol/gsm_08_08.h>
+
+#include <sccp/sccp.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+struct bsc_nat *bsc_nat_alloc(void)
+{
+ struct bsc_nat *nat = talloc_zero(tall_bsc_ctx, struct bsc_nat);
+ if (!nat)
+ return NULL;
+
+ INIT_LLIST_HEAD(&nat->sccp_connections);
+ INIT_LLIST_HEAD(&nat->bsc_connections);
+ INIT_LLIST_HEAD(&nat->bsc_configs);
+ INIT_LLIST_HEAD(&nat->access_lists);
+
+ nat->stats.sccp.conn = counter_alloc("nat.sccp.conn");
+ nat->stats.sccp.calls = counter_alloc("nat.sccp.calls");
+ nat->stats.bsc.reconn = counter_alloc("nat.bsc.conn");
+ nat->stats.bsc.auth_fail = counter_alloc("nat.bsc.auth_fail");
+ nat->stats.msc.reconn = counter_alloc("nat.msc.conn");
+ nat->msc_ip = talloc_strdup(nat, "127.0.0.1");
+ nat->msc_port = 5000;
+ nat->auth_timeout = 2;
+ nat->ping_timeout = 20;
+ nat->pong_timeout = 5;
+ return nat;
+}
+
+void bsc_nat_set_msc_ip(struct bsc_nat *nat, const char *ip)
+{
+ if (nat->msc_ip)
+ talloc_free(nat->msc_ip);
+ nat->msc_ip = talloc_strdup(nat, ip);
+}
+
+struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat)
+{
+ struct bsc_connection *con = talloc_zero(nat, struct bsc_connection);
+ if (!con)
+ return NULL;
+
+ con->nat = nat;
+ write_queue_init(&con->write_queue, 100);
+ return con;
+}
+
+struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, unsigned int lac)
+{
+ struct bsc_config *conf = talloc_zero(nat, struct bsc_config);
+ if (!conf)
+ return NULL;
+
+ conf->token = talloc_strdup(conf, token);
+ conf->lac = lac;
+ conf->nr = nat->num_bsc;
+ conf->nat = nat;
+
+ llist_add_tail(&conf->entry, &nat->bsc_configs);
+ ++nat->num_bsc;
+
+ conf->stats.sccp.conn = counter_alloc("nat.bsc.sccp.conn");
+ conf->stats.sccp.calls = counter_alloc("nat.bsc.sccp.calls");
+ conf->stats.net.reconn = counter_alloc("nat.bsc.net.reconnects");
+
+ return conf;
+}
+
+void sccp_connection_destroy(struct sccp_connections *conn)
+{
+ LOGP(DNAT, LOGL_DEBUG, "Destroy 0x%x <-> 0x%x mapping for con %p\n",
+ sccp_src_ref_to_int(&conn->real_ref),
+ sccp_src_ref_to_int(&conn->patched_ref), conn->bsc);
+ bsc_mgcp_dlcx(conn);
+ llist_del(&conn->list_entry);
+ talloc_free(conn);
+}
+
+struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg, int *lac_out)
+{
+ struct bsc_connection *bsc;
+ int data_length;
+ const u_int8_t *data;
+ struct tlv_parsed tp;
+ int i = 0;
+
+ *lac_out = -1;
+
+ if (!msg->l3h || msgb_l3len(msg) < 3) {
+ LOGP(DNAT, LOGL_ERROR, "Paging message is too short.\n");
+ return NULL;
+ }
+
+ tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 3, msgb_l3len(msg) - 3, 0, 0);
+ if (!TLVP_PRESENT(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST)) {
+ LOGP(DNAT, LOGL_ERROR, "No CellIdentifier List inside paging msg.\n");
+ return NULL;
+ }
+
+ data_length = TLVP_LEN(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
+ data = TLVP_VAL(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
+
+ /* No need to try a different BSS */
+ if (data[0] == CELL_IDENT_BSS) {
+ return NULL;
+ } else if (data[0] != CELL_IDENT_LAC) {
+ LOGP(DNAT, LOGL_ERROR, "Unhandled cell ident discrminator: %d\n", data[0]);
+ return NULL;
+ }
+
+ /* Currently we only handle one BSC */
+ for (i = 1; i < data_length - 1; i += 2) {
+ unsigned int _lac = ntohs(*(unsigned int *) &data[i]);
+ *lac_out = _lac;
+ llist_for_each_entry(bsc, &nat->bsc_connections, list_entry) {
+ if (!bsc->cfg)
+ continue;
+ if (!bsc->authenticated || _lac != bsc->cfg->lac)
+ continue;
+
+ return bsc;
+ }
+ }
+
+ return NULL;
+}
+
+int bsc_write_mgcp(struct bsc_connection *bsc, const u_int8_t *data, unsigned int length)
+{
+ struct msgb *msg;
+
+ if (length > 4096 - 128) {
+ LOGP(DINP, LOGL_ERROR, "Can not send message of that size.\n");
+ return -1;
+ }
+
+ msg = msgb_alloc_headroom(4096, 128, "to-bsc");
+ if (!msg) {
+ LOGP(DINP, LOGL_ERROR, "Failed to allocate memory for BSC msg.\n");
+ return -1;
+ }
+
+ /* copy the data */
+ msg->l3h = msgb_put(msg, length);
+ memcpy(msg->l3h, data, length);
+
+ return bsc_write(bsc, msg, NAT_IPAC_PROTO_MGCP);
+}
+
+int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int proto)
+{
+ /* prepend the header */
+ ipaccess_prepend_header(msg, proto);
+
+ if (write_queue_enqueue(&bsc->write_queue, msg) != 0) {
+ LOGP(DINP, LOGL_ERROR, "Failed to enqueue the write.\n");
+ msgb_free(msg);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int lst_check_allow(struct bsc_nat_acc_lst *lst, const char *mi_string)
+{
+ struct bsc_nat_acc_lst_entry *entry;
+
+ llist_for_each_entry(entry, &lst->fltr_list, list) {
+ if (!entry->imsi_allow)
+ continue;
+ if (regexec(&entry->imsi_allow_re, mi_string, 0, NULL, 0) == 0)
+ return 0;
+ }
+
+ return 1;
+}
+
+static int lst_check_deny(struct bsc_nat_acc_lst *lst, const char *mi_string)
+{
+ struct bsc_nat_acc_lst_entry *entry;
+
+ llist_for_each_entry(entry, &lst->fltr_list, list) {
+ if (!entry->imsi_deny)
+ continue;
+ if (regexec(&entry->imsi_deny_re, mi_string, 0, NULL, 0) == 0)
+ return 0;
+ }
+
+ return 1;
+}
+
+/* apply white/black list */
+static int auth_imsi(struct bsc_connection *bsc, const char *mi_string)
+{
+ /*
+ * Now apply blacklist/whitelist of the BSC and the NAT.
+ * 1.) Reject if the IMSI is not allowed at the BSC
+ * 2.) Allow directly if the IMSI is allowed at the BSC
+ * 3.) Reject if the IMSI not allowed at the global level.
+ * 4.) Allow directly if the IMSI is allowed at the global level
+ */
+ struct bsc_nat_acc_lst *nat_lst = NULL;
+ struct bsc_nat_acc_lst *bsc_lst = NULL;
+
+ bsc_lst = bsc_nat_acc_lst_find(bsc->nat, bsc->cfg->acc_lst_name);
+ nat_lst = bsc_nat_acc_lst_find(bsc->nat, bsc->nat->acc_lst_name);
+
+
+ if (bsc_lst) {
+ /* 1. BSC deny */
+ if (lst_check_deny(bsc_lst, mi_string) == 0) {
+ LOGP(DNAT, LOGL_ERROR,
+ "Filtering %s by imsi_deny on bsc nr: %d.\n", mi_string, bsc->cfg->nr);
+ return -2;
+ }
+
+ /* 2. BSC allow */
+ if (lst_check_allow(bsc_lst, mi_string) == 0)
+ return 0;
+ }
+
+ /* 3. NAT deny */
+ if (nat_lst) {
+ if (lst_check_deny(nat_lst, mi_string) == 0) {
+ LOGP(DNAT, LOGL_ERROR,
+ "Filtering %s by nat imsi_deny on bsc nr: %d.\n", mi_string, bsc->cfg->nr);
+ return -3;
+ }
+ }
+
+ return 0;
+}
+
+static int _cr_check_loc_upd(struct bsc_connection *bsc, uint8_t *data, unsigned int length)
+{
+ u_int8_t mi_type;
+ struct gsm48_loc_upd_req *lu;
+ char mi_string[GSM48_MI_SIZE];
+
+ if (length < sizeof(*lu)) {
+ LOGP(DNAT, LOGL_ERROR,
+ "LU does not fit. Length is %d \n", length);
+ return -1;
+ }
+
+ lu = (struct gsm48_loc_upd_req *) data;
+ mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
+
+ /*
+ * We can only deal with the IMSI. This will fail for a phone that
+ * will send the TMSI of a previous network to us.
+ */
+ if (mi_type != GSM_MI_TYPE_IMSI)
+ return 0;
+
+ gsm48_mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
+ return auth_imsi(bsc, mi_string);
+}
+
+static int _cr_check_cm_serv_req(struct bsc_connection *bsc, uint8_t *data, unsigned int length)
+{
+ static const uint32_t classmark_offset =
+ offsetof(struct gsm48_service_request, classmark);
+
+ char mi_string[GSM48_MI_SIZE];
+ uint8_t mi_type;
+ int rc;
+ struct gsm48_service_request *req;
+
+ /* unfortunately in Phase1 the classmark2 length is variable */
+
+ if (length < sizeof(*req)) {
+ LOGP(DNAT, LOGL_ERROR,
+ "CM Serv Req does not fit. Length is %d\n", length);
+ return -1;
+ }
+
+ req = (struct gsm48_service_request *) data;
+ rc = gsm48_extract_mi((uint8_t *) &req->classmark,
+ length - classmark_offset, mi_string, &mi_type);
+ if (rc < 0) {
+ LOGP(DNAT, LOGL_ERROR, "Failed to parse the classmark2/mi. error: %d\n", rc);
+ return -1;
+ }
+
+ /* we have to let the TMSI or such pass */
+ if (mi_type != GSM_MI_TYPE_IMSI)
+ return 0;
+
+ return auth_imsi(bsc, mi_string);
+}
+
+static int _cr_check_pag_resp(struct bsc_connection *bsc, uint8_t *data, unsigned int length)
+{
+ struct gsm48_pag_resp *resp;
+ char mi_string[GSM48_MI_SIZE];
+ u_int8_t mi_type;
+
+ if (length < sizeof(*resp)) {
+ LOGP(DNAT, LOGL_ERROR, "PAG RESP does not fit. Length was %d.\n", length);
+ return -1;
+ }
+
+ resp = (struct gsm48_pag_resp *) data;
+ if (gsm48_paging_extract_mi(resp, length, mi_string, &mi_type) < 0) {
+ LOGP(DNAT, LOGL_ERROR, "Failed to extract the MI.\n");
+ return -1;
+ }
+
+ /* we need to let it pass for now */
+ if (mi_type != GSM_MI_TYPE_IMSI)
+ return 0;
+
+ return auth_imsi(bsc, mi_string);
+}
+
+/* Filter out CR data... */
+int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed, int *con_type)
+{
+ struct tlv_parsed tp;
+ struct gsm48_hdr *hdr48;
+ int hdr48_len;
+ int len;
+
+ *con_type = NAT_CON_TYPE_NONE;
+
+ if (parsed->gsm_type != BSS_MAP_MSG_COMPLETE_LAYER_3) {
+ LOGP(DNAT, LOGL_ERROR,
+ "Rejecting CR message due wrong GSM Type %d\n", parsed->gsm_type);
+ return -1;
+ }
+
+ /* the parsed has had some basic l3 length check */
+ len = msg->l3h[1];
+ if (msgb_l3len(msg) - 3 < len) {
+ LOGP(DNAT, LOGL_ERROR,
+ "The CR Data has not enough space...\n");
+ return -1;
+ }
+
+ msg->l4h = &msg->l3h[3];
+ len -= 1;
+
+ tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h, len, 0, 0);
+
+ if (!TLVP_PRESENT(&tp, GSM0808_IE_LAYER_3_INFORMATION)) {
+ LOGP(DNAT, LOGL_ERROR, "CR Data does not contain layer3 information.\n");
+ return -1;
+ }
+
+ hdr48_len = TLVP_LEN(&tp, GSM0808_IE_LAYER_3_INFORMATION);
+
+ if (hdr48_len < sizeof(*hdr48)) {
+ LOGP(DNAT, LOGL_ERROR, "GSM48 header does not fit.\n");
+ return -1;
+ }
+
+ hdr48 = (struct gsm48_hdr *) TLVP_VAL(&tp, GSM0808_IE_LAYER_3_INFORMATION);
+
+ if (hdr48->proto_discr == GSM48_PDISC_MM &&
+ hdr48->msg_type == GSM48_MT_MM_LOC_UPD_REQUEST) {
+ *con_type = NAT_CON_TYPE_LU;
+ return _cr_check_loc_upd(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48));
+ } else if (hdr48->proto_discr == GSM48_PDISC_MM &&
+ hdr48->msg_type == GSM48_MT_MM_CM_SERV_REQ) {
+ *con_type = NAT_CON_TYPE_CM_SERV_REQ;
+ return _cr_check_cm_serv_req(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48));
+ } else if (hdr48->proto_discr == GSM48_PDISC_RR &&
+ hdr48->msg_type == GSM48_MT_RR_PAG_RESP) {
+ *con_type = NAT_CON_TYPE_PAG_RESP;
+ return _cr_check_pag_resp(bsc, &hdr48->data[0], hdr48_len - sizeof(*hdr48));
+ } else {
+ /* We only want to filter the above, let other things pass */
+ *con_type = NAT_CON_TYPE_OTHER;
+ return 0;
+ }
+}
+
+void bsc_parse_reg(void *ctx, regex_t *reg, char **imsi, int argc, const char **argv)
+{
+ if (*imsi) {
+ talloc_free(*imsi);
+ *imsi = NULL;
+ }
+ regfree(reg);
+
+ if (argc > 0) {
+ *imsi = talloc_strdup(ctx, argv[0]);
+ regcomp(reg, argv[0], 0);
+ }
+}
+
+static const char *con_types [] = {
+ [NAT_CON_TYPE_NONE] = "n/a",
+ [NAT_CON_TYPE_LU] = "Location Update",
+ [NAT_CON_TYPE_CM_SERV_REQ] = "CM Serv Req",
+ [NAT_CON_TYPE_PAG_RESP] = "Paging Response",
+ [NAT_CON_TYPE_LOCAL_REJECT] = "Local Reject",
+ [NAT_CON_TYPE_OTHER] = "Other",
+};
+
+const char *bsc_con_type_to_string(int type)
+{
+ return con_types[type];
+}
+
+struct bsc_nat_acc_lst *bsc_nat_acc_lst_find(struct bsc_nat *nat, const char *name)
+{
+ struct bsc_nat_acc_lst *lst;
+
+ if (!name)
+ return NULL;
+
+ llist_for_each_entry(lst, &nat->access_lists, list)
+ if (strcmp(lst->name, name) == 0)
+ return lst;
+
+ return NULL;
+}
+
+struct bsc_nat_acc_lst *bsc_nat_acc_lst_get(struct bsc_nat *nat, const char *name)
+{
+ struct bsc_nat_acc_lst *lst;
+
+ lst = bsc_nat_acc_lst_find(nat, name);
+ if (lst)
+ return lst;
+
+ lst = talloc_zero(nat, struct bsc_nat_acc_lst);
+ if (!lst) {
+ LOGP(DNAT, LOGL_ERROR, "Failed to allocate access list");
+ return NULL;
+ }
+
+ INIT_LLIST_HEAD(&lst->fltr_list);
+ lst->name = talloc_strdup(lst, name);
+ llist_add_tail(&lst->list, &nat->access_lists);
+ return lst;
+}
+
+void bsc_nat_acc_lst_delete(struct bsc_nat_acc_lst *lst)
+{
+ llist_del(&lst->list);
+ talloc_free(lst);
+}
+
+struct bsc_nat_acc_lst_entry *bsc_nat_acc_lst_entry_create(struct bsc_nat_acc_lst *lst)
+{
+ struct bsc_nat_acc_lst_entry *entry;
+
+ entry = talloc_zero(lst, struct bsc_nat_acc_lst_entry);
+ if (!entry)
+ return NULL;
+
+ llist_add_tail(&entry->list, &lst->fltr_list);
+ return entry;
+}
\ No newline at end of file
diff --git a/openbsc/src/nat/bsc_nat_vty.c b/openbsc/src/nat/bsc_nat_vty.c
new file mode 100644
index 0000000..ea168a4
--- /dev/null
+++ b/openbsc/src/nat/bsc_nat_vty.c
@@ -0,0 +1,557 @@
+/* OpenBSC NAT interface to quagga VTY */
+/* (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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <openbsc/vty.h>
+#include <openbsc/bsc_nat.h>
+#include <openbsc/bsc_msc.h>
+#include <openbsc/gsm_04_08.h>
+#include <openbsc/mgcp.h>
+#include <openbsc/vty.h>
+
+#include <osmocore/talloc.h>
+
+#include <sccp/sccp.h>
+
+#include <stdlib.h>
+
+static struct bsc_nat *_nat;
+
+static struct cmd_node nat_node = {
+ NAT_NODE,
+ "%s(nat)#",
+ 1,
+};
+
+static struct cmd_node bsc_node = {
+ BSC_NODE,
+ "%s(bsc)#",
+ 1,
+};
+
+static void write_acc_lst(struct vty *vty, struct bsc_nat_acc_lst *lst)
+{
+ struct bsc_nat_acc_lst_entry *entry;
+
+ llist_for_each_entry(entry, &lst->fltr_list, list) {
+ if (entry->imsi_allow)
+ vty_out(vty, " access-list %s imsi-allow %s%s",
+ lst->name, entry->imsi_allow, VTY_NEWLINE);
+ if (entry->imsi_deny)
+ vty_out(vty, " access-list %s imsi-deny %s%s",
+ lst->name, entry->imsi_deny, VTY_NEWLINE);
+ }
+}
+
+static int config_write_nat(struct vty *vty)
+{
+ struct bsc_nat_acc_lst *lst;
+
+ vty_out(vty, "nat%s", VTY_NEWLINE);
+ vty_out(vty, " msc ip %s%s", _nat->msc_ip, VTY_NEWLINE);
+ vty_out(vty, " msc port %d%s", _nat->msc_port, VTY_NEWLINE);
+ vty_out(vty, " timeout auth %d%s", _nat->auth_timeout, VTY_NEWLINE);
+ vty_out(vty, " timeout ping %d%s", _nat->ping_timeout, VTY_NEWLINE);
+ vty_out(vty, " timeout pong %d%s", _nat->pong_timeout, VTY_NEWLINE);
+ if (_nat->token)
+ vty_out(vty, " token %s%s", _nat->token, VTY_NEWLINE);
+ vty_out(vty, " ip-tos %d%s", _nat->bsc_ip_tos, VTY_NEWLINE);
+ if (_nat->acc_lst_name)
+ vty_out(vty, " access-list-name %s%s", _nat->acc_lst_name, VTY_NEWLINE);
+
+ llist_for_each_entry(lst, &_nat->access_lists, list) {
+ write_acc_lst(vty, lst);
+ }
+
+ return CMD_SUCCESS;
+}
+
+static void config_write_bsc_single(struct vty *vty, struct bsc_config *bsc)
+{
+ vty_out(vty, " bsc %u%s", bsc->nr, VTY_NEWLINE);
+ vty_out(vty, " token %s%s", bsc->token, VTY_NEWLINE);
+ vty_out(vty, " location_area_code %u%s", bsc->lac, VTY_NEWLINE);
+ vty_out(vty, " paging forbidden %d%s", bsc->forbid_paging, VTY_NEWLINE);
+ if (bsc->description)
+ vty_out(vty, " description %s%s", bsc->description, VTY_NEWLINE);
+ if (bsc->acc_lst_name)
+ vty_out(vty, " access-list-name %s%s", bsc->acc_lst_name, VTY_NEWLINE);
+}
+
+static int config_write_bsc(struct vty *vty)
+{
+ struct bsc_config *bsc;
+
+ llist_for_each_entry(bsc, &_nat->bsc_configs, entry)
+ config_write_bsc_single(vty, bsc);
+ return CMD_SUCCESS;
+}
+
+
+DEFUN(show_sccp, show_sccp_cmd, "show sccp connections",
+ SHOW_STR "Display information about current SCCP connections")
+{
+ struct sccp_connections *con;
+ vty_out(vty, "Listing all opening SCCP connections%s", VTY_NEWLINE);
+
+ llist_for_each_entry(con, &_nat->sccp_connections, list_entry) {
+ vty_out(vty, "For BSC Nr: %d lac: %d; BSC ref: 0x%x; MUX ref: 0x%x; Network has ref: %d ref: 0x%x MSC/BSC mux: 0x%x/0x%x type: %s%s",
+ con->bsc->cfg ? con->bsc->cfg->nr : -1,
+ con->bsc->cfg ? con->bsc->cfg->lac : -1,
+ sccp_src_ref_to_int(&con->real_ref),
+ sccp_src_ref_to_int(&con->patched_ref),
+ con->has_remote_ref,
+ sccp_src_ref_to_int(&con->remote_ref),
+ con->msc_timeslot, con->bsc_timeslot,
+ bsc_con_type_to_string(con->con_type),
+ VTY_NEWLINE);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(show_bsc, show_bsc_cmd, "show bsc connections",
+ SHOW_STR "Display information about current BSCs")
+{
+ struct bsc_connection *con;
+ struct sockaddr_in sock;
+ socklen_t len = sizeof(sock);
+
+ llist_for_each_entry(con, &_nat->bsc_connections, list_entry) {
+ getpeername(con->write_queue.bfd.fd, (struct sockaddr *) &sock, &len);
+ vty_out(vty, "BSC nr: %d lac: %d auth: %d fd: %d peername: %s%s",
+ con->cfg ? con->cfg->nr : -1,
+ con->cfg ? con->cfg->lac : -1,
+ con->authenticated, con->write_queue.bfd.fd,
+ inet_ntoa(sock.sin_addr), VTY_NEWLINE);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(show_bsc_cfg, show_bsc_cfg_cmd, "show bsc config",
+ SHOW_STR "Display information about known BSC configs")
+{
+ struct bsc_config *conf;
+ llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
+ vty_out(vty, "BSC token: '%s' lac: %u nr: %u%s",
+ conf->token, conf->lac, conf->nr, VTY_NEWLINE);
+ if (conf->acc_lst_name)
+ vty_out(vty, " access-list: %s%s",
+ conf->acc_lst_name, VTY_NEWLINE);
+ vty_out(vty, " paging forbidden: %d%s",
+ conf->forbid_paging, VTY_NEWLINE);
+ if (conf->description)
+ vty_out(vty, " description: %s%s", conf->description, VTY_NEWLINE);
+ else
+ vty_out(vty, " No description.%s", VTY_NEWLINE);
+
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(show_stats,
+ show_stats_cmd,
+ "show statistics [NR]",
+ SHOW_STR "Display network statistics")
+{
+ struct bsc_config *conf;
+
+ int nr = -1;
+
+ if (argc == 1)
+ nr = atoi(argv[0]);
+
+ vty_out(vty, "NAT statistics%s", VTY_NEWLINE);
+ vty_out(vty, " SCCP Connections %lu total, %lu calls%s",
+ counter_get(_nat->stats.sccp.conn),
+ counter_get(_nat->stats.sccp.calls), VTY_NEWLINE);
+ vty_out(vty, " MSC Connections %lu%s",
+ counter_get(_nat->stats.msc.reconn), VTY_NEWLINE);
+ vty_out(vty, " BSC Connections %lu total, %lu auth failed.%s",
+ counter_get(_nat->stats.bsc.reconn),
+ counter_get(_nat->stats.bsc.auth_fail), VTY_NEWLINE);
+
+ llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
+ if (argc == 1 && nr != conf->nr)
+ continue;
+
+ vty_out(vty, " BSC lac: %d nr: %d%s",
+ conf->lac, conf->nr, VTY_NEWLINE);
+ vty_out(vty, " SCCP Connnections %lu total, %lu calls%s",
+ counter_get(conf->stats.sccp.conn),
+ counter_get(conf->stats.sccp.calls), VTY_NEWLINE);
+ vty_out(vty, " BSC Connections %lu total%s",
+ counter_get(conf->stats.net.reconn), VTY_NEWLINE);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(show_msc,
+ show_msc_cmd,
+ "show msc connection",
+ SHOW_STR "Show the status of the MSC connection.")
+{
+ if (!_nat->msc_con) {
+ vty_out(vty, "The MSC is not yet configured.\n");
+ return CMD_WARNING;
+ }
+
+ vty_out(vty, "MSC on %s:%d is connected: %d%s\n",
+ _nat->msc_con->ip, _nat->msc_con->port,
+ _nat->msc_con->is_connected, VTY_NEWLINE);
+ return CMD_SUCCESS;
+}
+
+DEFUN(close_bsc,
+ close_bsc_cmd,
+ "close bsc connection BSC_NR",
+ "Close the connection with the BSC identified by the config number.")
+{
+ struct bsc_connection *bsc;
+ int bsc_nr = atoi(argv[0]);
+
+ llist_for_each_entry(bsc, &_nat->bsc_connections, list_entry) {
+ if (!bsc->cfg || bsc->cfg->nr != bsc_nr)
+ continue;
+ bsc_close_connection(bsc);
+ break;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_nat, cfg_nat_cmd, "nat", "Configute the NAT")
+{
+ vty->index = _nat;
+ vty->node = NAT_NODE;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_nat_msc_ip,
+ cfg_nat_msc_ip_cmd,
+ "msc ip A.B.C.D",
+ "Set the IP address of the MSC.")
+{
+ bsc_nat_set_msc_ip(_nat, argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_nat_msc_port,
+ cfg_nat_msc_port_cmd,
+ "msc port <1-65500>",
+ "Set the port of the MSC.")
+{
+ _nat->msc_port = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_nat_auth_time,
+ cfg_nat_auth_time_cmd,
+ "timeout auth <1-256>",
+ "The time to wait for an auth response.")
+{
+ _nat->auth_timeout = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_nat_ping_time,
+ cfg_nat_ping_time_cmd,
+ "timeout ping NR",
+ "Send a ping every NR seconds. Negative to disable.")
+{
+ _nat->ping_timeout = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_nat_pong_time,
+ cfg_nat_pong_time_cmd,
+ "timeout pong NR",
+ "Wait NR seconds for the PONG response. Should be smaller than ping.")
+{
+ _nat->pong_timeout = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_nat_token, cfg_nat_token_cmd,
+ "token TOKEN",
+ "Set a token for the NAT")
+{
+ if (_nat->token)
+ talloc_free(_nat->token);
+ _nat->token = talloc_strdup(_nat, argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_nat_bsc_ip_tos, cfg_nat_bsc_ip_tos_cmd,
+ "ip-tos <0-255>",
+ "Set the IP_TOS for the BSCs to use\n" "Set the IP_TOS attribute")
+{
+ _nat->bsc_ip_tos = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_nat_acc_lst_name,
+ cfg_nat_acc_lst_name_cmd,
+ "access-list-name NAME",
+ "Set the name of the access list to use.\n"
+ "The name of the to be used access list.")
+{
+ if (_nat->acc_lst_name)
+ talloc_free(_nat->acc_lst_name);
+ _nat->acc_lst_name = talloc_strdup(_nat, argv[0]);
+ return CMD_SUCCESS;
+}
+
+/* per BSC configuration */
+DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", "Select a BSC to configure")
+{
+ int bsc_nr = atoi(argv[0]);
+ struct bsc_config *bsc;
+
+ if (bsc_nr > _nat->num_bsc) {
+ vty_out(vty, "%% The next unused BSC number is %u%s",
+ _nat->num_bsc, VTY_NEWLINE);
+ return CMD_WARNING;
+ } else if (bsc_nr == _nat->num_bsc) {
+ /* allocate a new one */
+ bsc = bsc_config_alloc(_nat, "unknown", 0);
+ } else
+ bsc = bsc_config_num(_nat, bsc_nr);
+
+ if (!bsc)
+ return CMD_WARNING;
+
+ vty->index = bsc;
+ vty->node = BSC_NODE;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bsc_token, cfg_bsc_token_cmd, "token TOKEN", "Set the token")
+{
+ struct bsc_config *conf = vty->index;
+
+ if (conf->token)
+ talloc_free(conf->token);
+ conf->token = talloc_strdup(conf, argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>",
+ "Set the Location Area Code (LAC) of this BSC")
+{
+ struct bsc_config *tmp;
+ struct bsc_config *conf = vty->index;
+
+ int lac = atoi(argv[0]);
+
+ if (lac == GSM_LAC_RESERVED_DETACHED || lac == GSM_LAC_RESERVED_ALL_BTS) {
+ vty_out(vty, "%% LAC %d is reserved by GSM 04.08%s",
+ lac, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ /* verify that the LACs are unique */
+ llist_for_each_entry(tmp, &_nat->bsc_configs, entry) {
+ if (tmp->lac == lac) {
+ vty_out(vty, "%% LAC %d is already used.%s", lac, VTY_NEWLINE);
+ return CMD_ERR_INCOMPLETE;
+ }
+ }
+
+ conf->lac = lac;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_lst_imsi_allow,
+ cfg_lst_imsi_allow_cmd,
+ "access-list NAME imsi-allow [REGEXP]",
+ "Allow IMSIs matching the REGEXP\n"
+ "The name of the access-list\n"
+ "The regexp of allowed IMSIs\n")
+{
+ struct bsc_nat_acc_lst *acc;
+ struct bsc_nat_acc_lst_entry *entry;
+
+ acc = bsc_nat_acc_lst_get(_nat, argv[0]);
+ if (!acc)
+ return CMD_WARNING;
+
+ entry = bsc_nat_acc_lst_entry_create(acc);
+ if (!entry)
+ return CMD_WARNING;
+
+ bsc_parse_reg(acc, &entry->imsi_allow_re, &entry->imsi_allow, argc - 1, &argv[1]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_lst_imsi_deny,
+ cfg_lst_imsi_deny_cmd,
+ "access-list NAME imsi-deny [REGEXP]",
+ "Allow IMSIs matching the REGEXP\n"
+ "The name of the access-list\n"
+ "The regexp of to be denied IMSIs\n")
+{
+ struct bsc_nat_acc_lst *acc;
+ struct bsc_nat_acc_lst_entry *entry;
+
+ acc = bsc_nat_acc_lst_get(_nat, argv[0]);
+ if (!acc)
+ return CMD_WARNING;
+
+ entry = bsc_nat_acc_lst_entry_create(acc);
+ if (!entry)
+ return CMD_WARNING;
+
+ bsc_parse_reg(acc, &entry->imsi_deny_re, &entry->imsi_deny, argc - 1, &argv[1]);
+ return CMD_SUCCESS;
+}
+
+/* naming to follow Zebra... */
+DEFUN(cfg_lst_no,
+ cfg_lst_no_cmd,
+ "no access-list NAME",
+ NO_STR "Remove an access-list by name\n"
+ "The access-list to remove\n")
+{
+ struct bsc_nat_acc_lst *acc;
+ acc = bsc_nat_acc_lst_find(_nat, argv[0]);
+ if (!acc)
+ return CMD_WARNING;
+
+ bsc_nat_acc_lst_delete(acc);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bsc_acc_lst_name,
+ cfg_bsc_acc_lst_name_cmd,
+ "access-list-name NAME",
+ "Set the name of the access list to use.\n"
+ "The name of the to be used access list.")
+{
+ struct bsc_config *conf = vty->index;
+
+ if (conf->acc_lst_name)
+ talloc_free(conf->acc_lst_name);
+ conf->acc_lst_name = talloc_strdup(conf, argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bsc_paging,
+ cfg_bsc_paging_cmd,
+ "paging forbidden (0|1)",
+ "Forbid sending PAGING REQUESTS to the BSC.")
+{
+ struct bsc_config *conf = vty->index;
+
+ if (strcmp("1", argv[0]) == 0)
+ conf->forbid_paging = 1;
+ else
+ conf->forbid_paging = 0;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bsc_desc,
+ cfg_bsc_desc_cmd,
+ "description DESC",
+ "Provide a description for the given BSC.")
+{
+ struct bsc_config *conf = vty->index;
+
+ if (conf->description)
+ talloc_free(conf->description);
+ conf->description = talloc_strdup(conf, argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(test_regex, test_regex_cmd,
+ "test regex PATTERN STRING",
+ "Check if the string is matching the current pattern.")
+{
+ regex_t reg;
+ char *str = NULL;
+
+ memset(®, 0, sizeof(reg));
+ bsc_parse_reg(_nat, ®, &str, 1, argv);
+
+ vty_out(vty, "String matches allow pattern: %d%s",
+ regexec(®, argv[1], 0, NULL, 0) == 0, VTY_NEWLINE);
+
+ talloc_free(str);
+ regfree(®);
+ return CMD_SUCCESS;
+}
+
+int bsc_nat_vty_init(struct bsc_nat *nat)
+{
+ _nat = nat;
+
+ /* show commands */
+ install_element_ve(&show_sccp_cmd);
+ install_element_ve(&show_bsc_cmd);
+ install_element_ve(&show_bsc_cfg_cmd);
+ install_element_ve(&show_stats_cmd);
+ install_element_ve(&close_bsc_cmd);
+ install_element_ve(&show_msc_cmd);
+ install_element_ve(&test_regex_cmd);
+
+ /* nat group */
+ install_element(CONFIG_NODE, &cfg_nat_cmd);
+ install_node(&nat_node, config_write_nat);
+ install_default(NAT_NODE);
+ install_element(NAT_NODE, &cfg_nat_msc_ip_cmd);
+ install_element(NAT_NODE, &cfg_nat_msc_port_cmd);
+ install_element(NAT_NODE, &cfg_nat_auth_time_cmd);
+ install_element(NAT_NODE, &cfg_nat_ping_time_cmd);
+ install_element(NAT_NODE, &cfg_nat_pong_time_cmd);
+ install_element(NAT_NODE, &cfg_nat_token_cmd);
+ install_element(NAT_NODE, &cfg_nat_bsc_ip_tos_cmd);
+ install_element(NAT_NODE, &cfg_nat_acc_lst_name_cmd);
+
+ /* access-list */
+ install_element(NAT_NODE, &cfg_lst_imsi_allow_cmd);
+ install_element(NAT_NODE, &cfg_lst_imsi_deny_cmd);
+ install_element(NAT_NODE, &cfg_lst_no_cmd);
+
+ /* BSC subgroups */
+ install_element(NAT_NODE, &cfg_bsc_cmd);
+ install_node(&bsc_node, config_write_bsc);
+ install_default(BSC_NODE);
+ install_element(BSC_NODE, &cfg_bsc_token_cmd);
+ install_element(BSC_NODE, &cfg_bsc_lac_cmd);
+ install_element(BSC_NODE, &cfg_bsc_paging_cmd);
+ install_element(BSC_NODE, &cfg_bsc_desc_cmd);
+ install_element(BSC_NODE, &cfg_bsc_acc_lst_name_cmd);
+
+ mgcp_vty_init();
+
+ return 0;
+}
+
+
+/* called by the telnet interface... we have our own init above */
+void bsc_vty_init()
+{}
diff --git a/openbsc/src/nat/bsc_sccp.c b/openbsc/src/nat/bsc_sccp.c
new file mode 100644
index 0000000..94b332a
--- /dev/null
+++ b/openbsc/src/nat/bsc_sccp.c
@@ -0,0 +1,236 @@
+/* SCCP patching and handling routines */
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <openbsc/debug.h>
+#include <openbsc/bsc_nat.h>
+
+#include <sccp/sccp.h>
+
+#include <osmocore/talloc.h>
+
+#include <string.h>
+#include <time.h>
+
+static int equal(struct sccp_source_reference *ref1, struct sccp_source_reference *ref2)
+{
+ return memcmp(ref1, ref2, sizeof(*ref1)) == 0;
+}
+
+/*
+ * SCCP patching below
+ */
+
+/* check if we are using this ref for patched already */
+static int sccp_ref_is_free(struct sccp_source_reference *ref, struct bsc_nat *nat)
+{
+ struct sccp_connections *conn;
+
+ llist_for_each_entry(conn, &nat->sccp_connections, list_entry) {
+ if (memcmp(ref, &conn->patched_ref, sizeof(*ref)) == 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* copied from sccp.c */
+static int assign_src_local_reference(struct sccp_source_reference *ref, struct bsc_nat *nat)
+{
+ static u_int32_t last_ref = 0x50000;
+ int wrapped = 0;
+
+ do {
+ struct sccp_source_reference reference;
+ reference.octet1 = (last_ref >> 0) & 0xff;
+ reference.octet2 = (last_ref >> 8) & 0xff;
+ reference.octet3 = (last_ref >> 16) & 0xff;
+
+ ++last_ref;
+ /* do not use the reversed word and wrap around */
+ if ((last_ref & 0x00FFFFFF) == 0x00FFFFFF) {
+ LOGP(DNAT, LOGL_NOTICE, "Wrapped searching for a free code\n");
+ last_ref = 0;
+ ++wrapped;
+ }
+
+ if (sccp_ref_is_free(&reference, nat) == 0) {
+ *ref = reference;
+ return 0;
+ }
+ } while (wrapped != 2);
+
+ LOGP(DNAT, LOGL_ERROR, "Finding a free reference failed\n");
+ return -1;
+}
+
+struct sccp_connections *create_sccp_src_ref(struct bsc_connection *bsc,
+ struct bsc_nat_parsed *parsed)
+{
+ struct sccp_connections *conn;
+
+ /* Some commercial BSCs like to reassign there SRC ref */
+ llist_for_each_entry(conn, &bsc->nat->sccp_connections, list_entry) {
+ if (conn->bsc != bsc)
+ continue;
+ if (memcmp(&conn->real_ref, parsed->src_local_ref, sizeof(conn->real_ref)) != 0)
+ continue;
+
+ /* the BSC has reassigned the SRC ref and we failed to keep track */
+ memset(&conn->remote_ref, 0, sizeof(conn->remote_ref));
+ if (assign_src_local_reference(&conn->patched_ref, bsc->nat) != 0) {
+ LOGP(DNAT, LOGL_ERROR, "BSC %d reused src ref: %d and we failed to generate a new id.\n",
+ bsc->cfg->nr, sccp_src_ref_to_int(parsed->src_local_ref));
+ bsc_mgcp_dlcx(conn);
+ llist_del(&conn->list_entry);
+ talloc_free(conn);
+ return NULL;
+ } else {
+ clock_gettime(CLOCK_MONOTONIC, &conn->creation_time);
+ bsc_mgcp_dlcx(conn);
+ return conn;
+ }
+ }
+
+
+ conn = talloc_zero(bsc->nat, struct sccp_connections);
+ if (!conn) {
+ LOGP(DNAT, LOGL_ERROR, "Memory allocation failure.\n");
+ return NULL;
+ }
+
+ conn->bsc = bsc;
+ clock_gettime(CLOCK_MONOTONIC, &conn->creation_time);
+ conn->real_ref = *parsed->src_local_ref;
+ if (assign_src_local_reference(&conn->patched_ref, bsc->nat) != 0) {
+ LOGP(DNAT, LOGL_ERROR, "Failed to assign a ref.\n");
+ talloc_free(conn);
+ return NULL;
+ }
+
+ bsc_mgcp_init(conn);
+ llist_add_tail(&conn->list_entry, &bsc->nat->sccp_connections);
+ counter_inc(bsc->cfg->stats.sccp.conn);
+ counter_inc(bsc->cfg->nat->stats.sccp.conn);
+
+ LOGP(DNAT, LOGL_DEBUG, "Created 0x%x <-> 0x%x mapping for con %p\n",
+ sccp_src_ref_to_int(&conn->real_ref),
+ sccp_src_ref_to_int(&conn->patched_ref), bsc);
+
+ return conn;
+}
+
+int update_sccp_src_ref(struct sccp_connections *sccp, struct bsc_nat_parsed *parsed)
+{
+ if (!parsed->dest_local_ref || !parsed->src_local_ref) {
+ LOGP(DNAT, LOGL_ERROR, "CC MSG should contain both local and dest address.\n");
+ return -1;
+ }
+
+ sccp->remote_ref = *parsed->src_local_ref;
+ sccp->has_remote_ref = 1;
+ LOGP(DNAT, LOGL_DEBUG, "Updating 0x%x to remote 0x%x on %p\n",
+ sccp_src_ref_to_int(&sccp->patched_ref),
+ sccp_src_ref_to_int(&sccp->remote_ref), sccp->bsc);
+
+ return 0;
+}
+
+void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed)
+{
+ struct sccp_connections *conn;
+
+ llist_for_each_entry(conn, &bsc->nat->sccp_connections, list_entry) {
+ if (memcmp(parsed->src_local_ref,
+ &conn->patched_ref, sizeof(conn->patched_ref)) == 0) {
+
+ sccp_connection_destroy(conn);
+ return;
+ }
+ }
+
+ LOGP(DNAT, LOGL_ERROR, "Can not remove connection: 0x%x\n",
+ sccp_src_ref_to_int(parsed->src_local_ref));
+}
+
+/*
+ * We have a message from the MSC to the BSC. The MSC is using
+ * an address that was assigned by the MUX, we need to update the
+ * dest reference to the real network.
+ */
+struct sccp_connections *patch_sccp_src_ref_to_bsc(struct msgb *msg,
+ struct bsc_nat_parsed *parsed,
+ struct bsc_nat *nat)
+{
+ struct sccp_connections *conn;
+
+ if (!parsed->dest_local_ref) {
+ LOGP(DNAT, LOGL_ERROR, "MSG should contain dest_local_ref.\n");
+ return NULL;
+ }
+
+
+ llist_for_each_entry(conn, &nat->sccp_connections, list_entry) {
+ if (!equal(parsed->dest_local_ref, &conn->patched_ref))
+ continue;
+
+ /* Change the dest address to the real one */
+ *parsed->dest_local_ref = conn->real_ref;
+ return conn;
+ }
+
+ return NULL;
+}
+
+/*
+ * These are message to the MSC. We will need to find the BSC
+ * Connection by either the SRC or the DST local reference.
+ *
+ * In case of a CR we need to work by the SRC local reference
+ * in all other cases we need to work by the destination local
+ * reference..
+ */
+struct sccp_connections *patch_sccp_src_ref_to_msc(struct msgb *msg,
+ struct bsc_nat_parsed *parsed,
+ struct bsc_connection *bsc)
+{
+ struct sccp_connections *conn;
+
+ llist_for_each_entry(conn, &bsc->nat->sccp_connections, list_entry) {
+ if (conn->bsc != bsc)
+ continue;
+
+ if (parsed->src_local_ref) {
+ if (equal(parsed->src_local_ref, &conn->real_ref)) {
+ *parsed->src_local_ref = conn->patched_ref;
+ return conn;
+ }
+ } else if (parsed->dest_local_ref) {
+ if (equal(parsed->dest_local_ref, &conn->remote_ref))
+ return conn;
+ } else {
+ LOGP(DNAT, LOGL_ERROR, "Header has neither loc/dst ref.\n");
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
diff --git a/openbsc/src/osmo_msc.c b/openbsc/src/osmo_msc.c
new file mode 100644
index 0000000..b647a81
--- /dev/null
+++ b/openbsc/src/osmo_msc.c
@@ -0,0 +1,50 @@
+/* main MSC management code... */
+
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On Waves
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <openbsc/bsc_api.h>
+#include <openbsc/debug.h>
+
+#include <openbsc/gsm_04_11.h>
+
+static void msc_sapi_n_reject(struct gsm_subscriber_connection* conn, int dlci)
+{
+ int sapi = dlci & 0x7;
+
+ if (sapi == UM_SAPI_SMS)
+ gsm411_sapi_n_reject(conn);
+}
+
+static void msc_clear_request(struct gsm_subscriber_connection* conn, uint32_t cause)
+{
+ gsm0408_clear_request(conn, cause);
+}
+
+static struct bsc_api msc_handler = {
+ .sapi_n_reject = msc_sapi_n_reject,
+ .clear_request = msc_clear_request,
+};
+
+struct bsc_api *msc_bsc_api() {
+ return &msc_handler;
+}
diff --git a/openbsc/src/paging.c b/openbsc/src/paging.c
index 12ed903..ca37678 100644
--- a/openbsc/src/paging.c
+++ b/openbsc/src/paging.c
@@ -92,8 +92,7 @@
mi_len = gsm48_generate_mid_from_tmsi(mi, request->subscr->tmsi);
page_group = calculate_group(request->bts, request->subscr);
- rsl_paging_cmd(request->bts, page_group, mi_len, mi,
- request->chan_type);
+ gsm0808_page(request->bts, page_group, mi_len, mi, request->chan_type);
}
/*
diff --git a/openbsc/src/rest_octets.c b/openbsc/src/rest_octets.c
index 039d2c8..d9f5da5 100644
--- a/openbsc/src/rest_octets.c
+++ b/openbsc/src/rest_octets.c
@@ -316,8 +316,16 @@
bitvec_set_bit(bv, 1);
bitvec_set_uint(bv, gco->bs_cv_max, 4);
- /* hard-code no PAN_{DEC,INC,MAX} */
- bitvec_set_bit(bv, 0);
+ if (0) {
+ /* hard-code no PAN_{DEC,INC,MAX} */
+ bitvec_set_bit(bv, 0);
+ } else {
+ /* copied from ip.access BSC protocol trace */
+ bitvec_set_bit(bv, 1);
+ bitvec_set_uint(bv, 1, 3); /* DEC */
+ bitvec_set_uint(bv, 1, 3); /* INC */
+ bitvec_set_uint(bv, 15, 3); /* MAX */
+ }
if (!gco->ext_info_present) {
/* no extension information */
diff --git a/openbsc/src/rrlp.c b/openbsc/src/rrlp.c
index 3504451..b5c7daf 100644
--- a/openbsc/src/rrlp.c
+++ b/openbsc/src/rrlp.c
@@ -40,9 +40,9 @@
Accuracy=60, Method=gpsOrEOTD, ResponseTime=5, multipleSets */
static const u_int8_t ass_pref_pos_req[] = { 0x40, 0x03, 0x79, 0x50 };
-static int send_rrlp_req(struct gsm_lchan *lchan)
+static int send_rrlp_req(struct gsm_subscriber_connection *conn)
{
- struct gsm_network *net = lchan->ts->trx->bts->network;
+ struct gsm_network *net = conn->bts->network;
const u_int8_t *req;
switch (net->rrlp.mode) {
@@ -60,7 +60,7 @@
return 0;
}
- return gsm48_send_rr_app_info(lchan, 0x00,
+ return gsm48_send_rr_app_info(conn, 0x00,
sizeof(ms_based_pos_req), req);
}
@@ -68,16 +68,16 @@
void *handler_data, void *signal_data)
{
struct gsm_subscriber *subscr;
- struct gsm_lchan *lchan;
+ struct gsm_subscriber_connection *conn;
switch (signal) {
case S_SUBSCR_ATTACHED:
/* A subscriber has attached. */
subscr = signal_data;
- lchan = lchan_for_subscr(subscr);
- if (!lchan)
+ conn = connection_for_subscr(subscr);
+ if (!conn)
break;
- send_rrlp_req(lchan);
+ send_rrlp_req(conn);
break;
}
return 0;
@@ -91,7 +91,7 @@
switch (signal) {
case S_PAGING_SUCCEEDED:
/* A subscriber has attached. */
- send_rrlp_req(psig_data->lchan);
+ send_rrlp_req(&psig_data->lchan->conn);
break;
case S_PAGING_EXPIRED:
break;
diff --git a/openbsc/src/sccp/sccp.c b/openbsc/src/sccp/sccp.c
index de18614..f4335c0 100644
--- a/openbsc/src/sccp/sccp.c
+++ b/openbsc/src/sccp/sccp.c
@@ -638,7 +638,7 @@
connection->state_cb(connection, old_state);
}
-static int _sccp_send_refuse(struct sccp_source_reference *src_ref, int cause)
+struct msgb *sccp_create_refuse(struct sccp_source_reference *src_ref, int cause, uint8_t *inp, int length)
{
struct msgb *msgb;
struct sccp_connection_refused *ref;
@@ -646,6 +646,11 @@
msgb = msgb_alloc_headroom(SCCP_MSG_SIZE,
SCCP_MSG_HEADROOM, "sccp ref");
+ if (!msgb) {
+ LOGP(DSCCP, LOGL_ERROR, "Failed to allocate refusal msg.\n");
+ return NULL;
+ }
+
msgb->l2h = &msgb->data[0];
ref = (struct sccp_connection_refused *) msgb_put(msgb, sizeof(*ref));
@@ -655,40 +660,70 @@
ref->cause = cause;
ref->optional_start = 1;
+ if (inp) {
+ data = msgb_put(msgb, 1 + 1 + length);
+ data[0] = SCCP_PNC_DATA;
+ data[1] = length;
+ memcpy(&data[2], inp, length);
+ }
+
data = msgb_put(msgb, 1);
data[0] = SCCP_PNC_END_OF_OPTIONAL;
+ return msgb;
+}
+
+static int _sccp_send_refuse(struct sccp_source_reference *src_ref, int cause)
+{
+ struct msgb *msgb = sccp_create_refuse(src_ref, cause, NULL, 0);
+ if (!msgb)
+ return -1;
_send_msg(msgb);
return 0;
}
-static int _sccp_send_connection_confirm(struct sccp_connection *connection)
+struct msgb *sccp_create_cc(struct sccp_source_reference *src_ref,
+ struct sccp_source_reference *dst_ref)
{
struct msgb *response;
struct sccp_connection_confirm *confirm;
u_int8_t *optional_data;
- if (assign_source_local_reference(connection) != 0)
- return -1;
-
response = msgb_alloc_headroom(SCCP_MSG_SIZE,
SCCP_MSG_HEADROOM, "sccp confirm");
+ if (!response) {
+ LOGP(DSCCP, LOGL_ERROR, "Failed to create SCCP Confirm.\n");
+ return NULL;
+ }
+
response->l2h = &response->data[0];
confirm = (struct sccp_connection_confirm *) msgb_put(response, sizeof(*confirm));
confirm->type = SCCP_MSG_TYPE_CC;
memcpy(&confirm->destination_local_reference,
- &connection->destination_local_reference,
- sizeof(connection->destination_local_reference));
+ dst_ref, sizeof(*dst_ref));
memcpy(&confirm->source_local_reference,
- &connection->source_local_reference,
- sizeof(connection->source_local_reference));
+ src_ref, sizeof(*src_ref));
confirm->proto_class = 2;
confirm->optional_start = 1;
optional_data = (u_int8_t *) msgb_put(response, 1);
optional_data[0] = SCCP_PNC_END_OF_OPTIONAL;
+ return response;
+}
+
+static int _sccp_send_connection_confirm(struct sccp_connection *connection)
+{
+ struct msgb *response;
+
+ if (assign_source_local_reference(connection) != 0)
+ return -1;
+
+ response = sccp_create_cc(&connection->source_local_reference,
+ &connection->destination_local_reference);
+ if (!response)
+ return -1;
_send_msg(response);
_sccp_set_connection_state(connection, SCCP_CONNECTION_STATE_ESTABLISHED);
@@ -755,34 +790,49 @@
return 0;
}
-static int _sccp_send_connection_data(struct sccp_connection *conn, struct msgb *_data)
+struct msgb *sccp_create_dt1(struct sccp_source_reference *dst_ref, uint8_t *inp_data, uint8_t len)
{
struct msgb *msgb;
struct sccp_data_form1 *dt1;
u_int8_t *data;
- int extra_size;
+
+ msgb = msgb_alloc_headroom(SCCP_MSG_SIZE,
+ SCCP_MSG_HEADROOM, "sccp dt1");
+ if (!msgb) {
+ LOGP(DSCCP, LOGL_ERROR, "Failed to create DT1 msg.\n");
+ return NULL;
+ }
+
+ msgb->l2h = &msgb->data[0];
+
+ dt1 = (struct sccp_data_form1 *) msgb_put(msgb, sizeof(*dt1));
+ dt1->type = SCCP_MSG_TYPE_DT1;
+ memcpy(&dt1->destination_local_reference, dst_ref,
+ sizeof(struct sccp_source_reference));
+ dt1->segmenting = 0;
+
+ /* copy the data */
+ dt1->variable_start = 1;
+ data = msgb_put(msgb, 1 + len);
+ data[0] = len;
+ memcpy(&data[1], inp_data, len);
+
+ return msgb;
+}
+
+static int _sccp_send_connection_data(struct sccp_connection *conn, struct msgb *_data)
+{
+ struct msgb *msgb;
if (msgb_l3len(_data) < 2 || msgb_l3len(_data) > 256) {
LOGP(DSCCP, LOGL_ERROR, "data size too big, segmenting unimplemented.\n");
return -1;
}
- extra_size = 1 + msgb_l3len(_data);
- msgb = msgb_alloc_headroom(SCCP_MSG_SIZE,
- SCCP_MSG_HEADROOM, "sccp dt1");
- msgb->l2h = &msgb->data[0];
-
- dt1 = (struct sccp_data_form1 *) msgb_put(msgb, sizeof(*dt1));
- dt1->type = SCCP_MSG_TYPE_DT1;
- memcpy(&dt1->destination_local_reference, &conn->destination_local_reference,
- sizeof(struct sccp_source_reference));
- dt1->segmenting = 0;
-
- /* copy the data */
- dt1->variable_start = 1;
- data = msgb_put(msgb, extra_size);
- data[0] = extra_size - 1;
- memcpy(&data[1], _data->l3h, extra_size - 1);
+ msgb = sccp_create_dt1(&conn->destination_local_reference,
+ _data->l3h, msgb_l3len(_data));
+ if (!msgb)
+ return -1;
_send_msg(msgb);
return 0;
@@ -811,7 +861,8 @@
return 0;
}
-static int _sccp_send_connection_released(struct sccp_connection *conn, int cause)
+struct msgb *sccp_create_rlsd(struct sccp_source_reference *src_ref,
+ struct sccp_source_reference *dst_ref, int cause)
{
struct msgb *msg;
struct sccp_connection_released *rel;
@@ -819,19 +870,36 @@
msg = msgb_alloc_headroom(SCCP_MSG_SIZE, SCCP_MSG_HEADROOM,
"sccp: connection released");
+ if (!msg) {
+ LOGP(DSCCP, LOGL_ERROR, "Failed to allocate RLSD.\n");
+ return NULL;
+ }
+
msg->l2h = &msg->data[0];
rel = (struct sccp_connection_released *) msgb_put(msg, sizeof(*rel));
rel->type = SCCP_MSG_TYPE_RLSD;
rel->release_cause = cause;
/* copy the source references */
- memcpy(&rel->destination_local_reference, &conn->destination_local_reference,
+ memcpy(&rel->destination_local_reference, dst_ref,
sizeof(struct sccp_source_reference));
- memcpy(&rel->source_local_reference, &conn->source_local_reference,
+ memcpy(&rel->source_local_reference, src_ref,
sizeof(struct sccp_source_reference));
data = msgb_put(msg, 1);
data[0] = SCCP_PNC_END_OF_OPTIONAL;
+ return msg;
+}
+
+static int _sccp_send_connection_released(struct sccp_connection *conn, int cause)
+{
+ struct msgb *msg;
+
+ msg = sccp_create_rlsd(&conn->source_local_reference,
+ &conn->destination_local_reference,
+ cause);
+ if (!msg)
+ return -1;
_sccp_set_connection_state(conn, SCCP_CONNECTION_STATE_RELEASE);
_send_msg(msg);
diff --git a/openbsc/src/silent_call.c b/openbsc/src/silent_call.c
index 8bd5341..00acc1d 100644
--- a/openbsc/src/silent_call.c
+++ b/openbsc/src/silent_call.c
@@ -128,15 +128,13 @@
/* end a silent call with a given subscriber */
int gsm_silent_call_stop(struct gsm_subscriber *subscr)
{
- struct gsm_lchan *lchan;
struct gsm_subscriber_connection *conn;
- lchan = lchan_for_subscr(subscr);
- if (!lchan)
+ conn = connection_for_subscr(subscr);
+ if (!conn)
return -EINVAL;
/* did we actually establish a silent call for this guy? */
- conn = &lchan->conn;
if (!conn->silent_call)
return -EINVAL;
diff --git a/openbsc/src/socket.c b/openbsc/src/socket.c
index 3ed4d42..d60c43e 100644
--- a/openbsc/src/socket.c
+++ b/openbsc/src/socket.c
@@ -41,15 +41,26 @@
#include <openbsc/gsm_data.h>
#include <osmocore/talloc.h>
-int make_sock(struct bsc_fd *bfd, int proto, u_int16_t port,
+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))
{
struct sockaddr_in addr;
int ret, on = 1;
int type = SOCK_STREAM;
- if (proto == IPPROTO_UDP)
+ switch (proto) {
+ case IPPROTO_TCP:
+ type = SOCK_STREAM;
+ break;
+ case IPPROTO_UDP:
type = SOCK_DGRAM;
+ break;
+ case IPPROTO_GRE:
+ type = SOCK_RAW;
+ break;
+ default:
+ return -EINVAL;
+ }
bfd->fd = socket(AF_INET, type, proto);
bfd->cb = cb;
@@ -57,26 +68,29 @@
//bfd->data = line;
if (bfd->fd < 0) {
- LOGP(DINP, LOGL_ERROR, "could not create TCP socket.\n");
+ LOGP(DINP, LOGL_ERROR, "could not create socket.\n");
return -EIO;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
- addr.sin_addr.s_addr = INADDR_ANY;
+ if (ip)
+ addr.sin_addr.s_addr = htonl(ip);
+ else
+ addr.sin_addr.s_addr = INADDR_ANY;
setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
- LOGP(DINP, LOGL_ERROR, "could not bind l2 socket %s\n",
+ LOGP(DINP, LOGL_ERROR, "could not bind socket %s\n",
strerror(errno));
close(bfd->fd);
return -EIO;
}
- if (proto != IPPROTO_UDP) {
+ if (proto == IPPROTO_TCP) {
ret = listen(bfd->fd, 1);
if (ret < 0) {
perror("listen");
diff --git a/openbsc/src/system_information.c b/openbsc/src/system_information.c
index 3bd833a..337f756 100644
--- a/openbsc/src/system_information.c
+++ b/openbsc/src/system_information.c
@@ -397,17 +397,17 @@
static struct gsm48_si13_info si13_default = {
.cell_opts = {
- .nmo = GPRS_NMO_III,
- .t3168 = 1500,
- .t3192 = 500,
+ .nmo = GPRS_NMO_II,
+ .t3168 = 2000,
+ .t3192 = 200,
.drx_timer_max = 3,
.bs_cv_max = 15,
- .ext_info_present = 0,
+ .ext_info_present = 1,
.ext_info = {
/* The values below are just guesses ! */
.egprs_supported = 0,
.use_egprs_p_ch_req = 1,
- .bep_period = 4,
+ .bep_period = 5,
.pfc_supported = 0,
.dtm_supported = 0,
.bss_paging_coordination = 0,
@@ -415,10 +415,10 @@
},
.pwr_ctrl_pars = {
.alpha = 10, /* a = 1.0 */
- .t_avg_w = 25,
- .t_avg_t = 25,
+ .t_avg_w = 16,
+ .t_avg_t = 16,
.pc_meas_chan = 0, /* downling measured on CCCH */
- .n_avg_i = 15,
+ .n_avg_i = 8,
},
.bcch_change_mark = 1,
.si_change_field = 0,
@@ -451,7 +451,8 @@
if (ret < 0)
return ret;
- si13->header.l2_plen = ret & 0xff;
+ /* length is coded in bit 2 an up */
+ si13->header.l2_plen = 0x01;
return sizeof (*si13) + ret;
}
diff --git a/openbsc/src/talloc_ctx.c b/openbsc/src/talloc_ctx.c
index 4b373b4..8e7ec23 100644
--- a/openbsc/src/talloc_ctx.c
+++ b/openbsc/src/talloc_ctx.c
@@ -4,6 +4,7 @@
extern void *tall_msgb_ctx;
extern void *tall_fle_ctx;
extern void *tall_locop_ctx;
+extern void *tall_authciphop_ctx;
extern void *tall_gsms_ctx;
extern void *tall_subscr_ctx;
extern void *tall_sub_req_ctx;
@@ -22,6 +23,7 @@
tall_fle_ctx = talloc_named_const(tall_bsc_ctx, 0,
"bs11_file_list_entry");
tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 0, "loc_updating_oper");
+ tall_authciphop_ctx = talloc_named_const(tall_bsc_ctx, 0, "auth_ciph_oper");
tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 0, "sms");
tall_subscr_ctx = talloc_named_const(tall_bsc_ctx, 0, "subscriber");
tall_sub_req_ctx = talloc_named_const(tall_bsc_ctx, 0, "subscr_request");
diff --git a/openbsc/src/telnet_interface.c b/openbsc/src/telnet_interface.c
deleted file mode 100644
index c7de026..0000000
--- a/openbsc/src/telnet_interface.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/* minimalistic telnet/network interface it might turn into a wire interface */
-/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <openbsc/telnet_interface.h>
-#include <openbsc/gsm_subscriber.h>
-#include <openbsc/chan_alloc.h>
-#include <openbsc/gsm_04_08.h>
-#include <openbsc/gsm_04_11.h>
-#include <osmocore/msgb.h>
-#include <openbsc/abis_rsl.h>
-#include <openbsc/paging.h>
-#include <openbsc/signal.h>
-#include <osmocore/talloc.h>
-#include <openbsc/debug.h>
-
-#include <vty/buffer.h>
-
-#define WRITE_CONNECTION(fd, msg...) \
- int ret; \
- char buf[4096]; \
- snprintf(buf, sizeof(buf), msg); \
- ret = write(fd, buf, strlen(buf));
-
-
-/* per connection data */
-LLIST_HEAD(active_connections);
-
-static void *tall_telnet_ctx;
-
-/* per network data */
-static int telnet_new_connection(struct bsc_fd *fd, unsigned int what);
-
-static struct bsc_fd server_socket = {
- .when = BSC_FD_READ,
- .cb = telnet_new_connection,
- .priv_nr = 0,
-};
-
-void telnet_init(struct gsm_network *network, int port) {
- struct sockaddr_in sock_addr;
- int fd, on = 1;
-
- tall_telnet_ctx = talloc_named_const(tall_bsc_ctx, 1,
- "telnet_connection");
-
- bsc_vty_init(network);
-
- fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
-
- if (fd < 0) {
- LOGP(DNM, LOGL_ERROR, "Telnet interface socket creation failed\n");
- return;
- }
-
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-
- memset(&sock_addr, 0, sizeof(sock_addr));
- sock_addr.sin_family = AF_INET;
- sock_addr.sin_port = htons(port);
- sock_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
- if (bind(fd, (struct sockaddr*)&sock_addr, sizeof(sock_addr)) < 0) {
- LOGP(DNM, LOGL_ERROR, "Telnet interface failed to bind\n");
- return;
- }
-
- if (listen(fd, 0) < 0) {
- LOGP(DNM, LOGL_ERROR, "Telnet interface failed to listen\n");
- return;
- }
-
- server_socket.data = network;
- server_socket.fd = fd;
- bsc_register_fd(&server_socket);
-}
-
-extern const char *openbsc_copyright;
-extern const char *openbsc_version;
-
-static void print_welcome(int fd) {
- int ret;
- static char *msg =
- "Welcome to the OpenBSC Control interface\n";
-
- ret = write(fd, msg, strlen(msg));
- ret = write(fd, openbsc_copyright, strlen(openbsc_copyright));
-}
-
-int telnet_close_client(struct bsc_fd *fd) {
- struct telnet_connection *conn = (struct telnet_connection*)fd->data;
-
- close(fd->fd);
- bsc_unregister_fd(fd);
-
- if (conn->dbg) {
- log_del_target(conn->dbg);
- talloc_free(conn->dbg);
- }
-
- llist_del(&conn->entry);
- talloc_free(conn);
- return 0;
-}
-
-static int client_data(struct bsc_fd *fd, unsigned int what)
-{
- struct telnet_connection *conn = fd->data;
- int rc = 0;
-
- if (what & BSC_FD_READ) {
- conn->fd.when &= ~BSC_FD_READ;
- rc = vty_read(conn->vty);
- }
-
- /* vty might have been closed from vithin vty_read() */
- if (!conn->vty)
- return rc;
-
- if (what & BSC_FD_WRITE) {
- rc = buffer_flush_all(conn->vty->obuf, fd->fd);
- if (rc == BUFFER_EMPTY)
- conn->fd.when &= ~BSC_FD_WRITE;
- }
-
- return rc;
-}
-
-static int telnet_new_connection(struct bsc_fd *fd, unsigned int what) {
- struct telnet_connection *connection;
- struct sockaddr_in sockaddr;
- socklen_t len = sizeof(sockaddr);
- int new_connection = accept(fd->fd, (struct sockaddr*)&sockaddr, &len);
-
- if (new_connection < 0) {
- LOGP(DNM, LOGL_ERROR, "telnet accept failed\n");
- return -1;
- }
-
-
- connection = talloc_zero(tall_telnet_ctx, struct telnet_connection);
- connection->network = (struct gsm_network*)fd->data;
- connection->fd.data = connection;
- connection->fd.fd = new_connection;
- connection->fd.when = BSC_FD_READ;
- connection->fd.cb = client_data;
- bsc_register_fd(&connection->fd);
- llist_add_tail(&connection->entry, &active_connections);
-
- print_welcome(new_connection);
-
- connection->vty = vty_create(new_connection, connection);
- if (!connection->vty) {
- LOGP(DNM, LOGL_ERROR, "couldn't create VTY\n");
- return -1;
- }
-
- return 0;
-}
-
-/* callback from VTY code */
-void vty_event(enum event event, int sock, struct vty *vty)
-{
- struct telnet_connection *connection = vty->priv;
- struct bsc_fd *bfd = &connection->fd;
-
- if (vty->type != VTY_TERM)
- return;
-
- switch (event) {
- case VTY_READ:
- bfd->when |= BSC_FD_READ;
- break;
- case VTY_WRITE:
- bfd->when |= BSC_FD_WRITE;
- break;
- case VTY_CLOSED:
- /* vty layer is about to free() vty */
- connection->vty = NULL;
- telnet_close_client(bfd);
- break;
- default:
- break;
- }
-}
-
diff --git a/openbsc/src/token_auth.c b/openbsc/src/token_auth.c
index 7fefea5..dc8cce2 100644
--- a/openbsc/src/token_auth.c
+++ b/openbsc/src/token_auth.c
@@ -99,12 +99,12 @@
subscr->authorized = 0;
db_sync_subscriber(subscr);
if (rc) {
- struct gsm_lchan *lchan = lchan_for_subscr(subscr);
- if (lchan) {
+ struct gsm_subscriber_connection *conn = connection_for_subscr(subscr);
+ if (conn) {
u_int8_t auth_rand[16];
/* kick the subscriber off the network */
- gsm48_tx_mm_auth_req(lchan, auth_rand, 0);
- gsm48_tx_mm_auth_rej(lchan);
+ gsm48_tx_mm_auth_req(conn, auth_rand, 0);
+ gsm48_tx_mm_auth_rej(conn);
/* FIXME: close the channel early ?*/
//gsm48_send_rr_Release(lchan);
}
@@ -118,7 +118,7 @@
void *handler_data, void *signal_data)
{
struct gsm_sms *sms = signal_data;
- struct gsm_lchan *lchan;
+ struct gsm_subscriber_connection *conn;
u_int8_t auth_rand[16];
@@ -136,11 +136,11 @@
return 0;
- lchan = lchan_for_subscr(sms->receiver);
- if (lchan) {
+ conn = connection_for_subscr(sms->receiver);
+ if (conn) {
/* kick the subscriber off the network */
- gsm48_tx_mm_auth_req(lchan, auth_rand, 0);
- gsm48_tx_mm_auth_rej(lchan);
+ gsm48_tx_mm_auth_req(conn, auth_rand, 0);
+ gsm48_tx_mm_auth_rej(conn);
/* FIXME: close the channel early ?*/
//gsm48_send_rr_Release(lchan);
}
diff --git a/openbsc/src/vty/buffer.c b/openbsc/src/vty/buffer.c
deleted file mode 100644
index 0bc1760..0000000
--- a/openbsc/src/vty/buffer.c
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- * Buffering of output and input.
- * Copyright (C) 1998 Kunihiro Ishiguro
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <stddef.h>
-#include <sys/uio.h>
-
-#include <osmocore/talloc.h>
-#include <vty/buffer.h>
-#include <vty/vty.h>
-
-/* Buffer master. */
-struct buffer {
- /* Data list. */
- struct buffer_data *head;
- struct buffer_data *tail;
-
- /* Size of each buffer_data chunk. */
- size_t size;
-};
-
-/* Data container. */
-struct buffer_data {
- struct buffer_data *next;
-
- /* Location to add new data. */
- size_t cp;
-
- /* Pointer to data not yet flushed. */
- size_t sp;
-
- /* Actual data stream (variable length). */
- unsigned char data[0]; /* real dimension is buffer->size */
-};
-
-/* It should always be true that: 0 <= sp <= cp <= size */
-
-/* Default buffer size (used if none specified). It is rounded up to the
- next page boundery. */
-#define BUFFER_SIZE_DEFAULT 4096
-
-#define BUFFER_DATA_FREE(D) talloc_free((D))
-
-/* Make new buffer. */
-struct buffer *buffer_new(void *ctx, size_t size)
-{
- struct buffer *b;
-
- b = talloc_zero(ctx, struct buffer);
-
- if (size)
- b->size = size;
- else {
- static size_t default_size;
- if (!default_size) {
- long pgsz = sysconf(_SC_PAGESIZE);
- default_size =
- ((((BUFFER_SIZE_DEFAULT - 1) / pgsz) + 1) * pgsz);
- }
- b->size = default_size;
- }
-
- return b;
-}
-
-/* Free buffer. */
-void buffer_free(struct buffer *b)
-{
- buffer_reset(b);
- talloc_free(b);
-}
-
-/* Make string clone. */
-char *buffer_getstr(struct buffer *b)
-{
- size_t totlen = 0;
- struct buffer_data *data;
- char *s;
- char *p;
-
- for (data = b->head; data; data = data->next)
- totlen += data->cp - data->sp;
- if (!(s = _talloc_zero(tall_vty_ctx, (totlen + 1), "buffer_getstr")))
- return NULL;
- p = s;
- for (data = b->head; data; data = data->next) {
- memcpy(p, data->data + data->sp, data->cp - data->sp);
- p += data->cp - data->sp;
- }
- *p = '\0';
- return s;
-}
-
-/* Return 1 if buffer is empty. */
-int buffer_empty(struct buffer *b)
-{
- return (b->head == NULL);
-}
-
-/* Clear and free all allocated data. */
-void buffer_reset(struct buffer *b)
-{
- struct buffer_data *data;
- struct buffer_data *next;
-
- for (data = b->head; data; data = next) {
- next = data->next;
- BUFFER_DATA_FREE(data);
- }
- b->head = b->tail = NULL;
-}
-
-/* Add buffer_data to the end of buffer. */
-static struct buffer_data *buffer_add(struct buffer *b)
-{
- struct buffer_data *d;
-
- d = _talloc_zero(b,
- offsetof(struct buffer_data, data[b->size]),
- "buffer_add");
- if (!d)
- return NULL;
- d->cp = d->sp = 0;
- d->next = NULL;
-
- if (b->tail)
- b->tail->next = d;
- else
- b->head = d;
- b->tail = d;
-
- return d;
-}
-
-/* Write data to buffer. */
-void buffer_put(struct buffer *b, const void *p, size_t size)
-{
- struct buffer_data *data = b->tail;
- const char *ptr = p;
-
- /* We use even last one byte of data buffer. */
- while (size) {
- size_t chunk;
-
- /* If there is no data buffer add it. */
- if (data == NULL || data->cp == b->size)
- data = buffer_add(b);
-
- chunk =
- ((size <=
- (b->size - data->cp)) ? size : (b->size - data->cp));
- memcpy((data->data + data->cp), ptr, chunk);
- size -= chunk;
- ptr += chunk;
- data->cp += chunk;
- }
-}
-
-/* Insert character into the buffer. */
-void buffer_putc(struct buffer *b, u_char c)
-{
- buffer_put(b, &c, 1);
-}
-
-/* Put string to the buffer. */
-void buffer_putstr(struct buffer *b, const char *c)
-{
- buffer_put(b, c, strlen(c));
-}
-
-/* Keep flushing data to the fd until the buffer is empty or an error is
- encountered or the operation would block. */
-buffer_status_t buffer_flush_all(struct buffer *b, int fd)
-{
- buffer_status_t ret;
- struct buffer_data *head;
- size_t head_sp;
-
- if (!b->head)
- return BUFFER_EMPTY;
- head_sp = (head = b->head)->sp;
- /* Flush all data. */
- while ((ret = buffer_flush_available(b, fd)) == BUFFER_PENDING) {
- if ((b->head == head) && (head_sp == head->sp)
- && (errno != EINTR))
- /* No data was flushed, so kernel buffer must be full. */
- return ret;
- head_sp = (head = b->head)->sp;
- }
-
- return ret;
-}
-
-#if 0
-/* Flush enough data to fill a terminal window of the given scene (used only
- by vty telnet interface). */
-buffer_status_t
-buffer_flush_window(struct buffer * b, int fd, int width, int height,
- int erase_flag, int no_more_flag)
-{
- int nbytes;
- int iov_alloc;
- int iov_index;
- struct iovec *iov;
- struct iovec small_iov[3];
- char more[] = " --More-- ";
- char erase[] =
- { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
- ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
- 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
- };
- struct buffer_data *data;
- int column;
-
- if (!b->head)
- return BUFFER_EMPTY;
-
- if (height < 1) {
- zlog_warn
- ("%s called with non-positive window height %d, forcing to 1",
- __func__, height);
- height = 1;
- } else if (height >= 2)
- height--;
- if (width < 1) {
- zlog_warn
- ("%s called with non-positive window width %d, forcing to 1",
- __func__, width);
- width = 1;
- }
-
- /* For erase and more data add two to b's buffer_data count. */
- if (b->head->next == NULL) {
- iov_alloc = sizeof(small_iov) / sizeof(small_iov[0]);
- iov = small_iov;
- } else {
- iov_alloc = ((height * (width + 2)) / b->size) + 10;
- iov = XMALLOC(MTYPE_TMP, iov_alloc * sizeof(*iov));
- }
- iov_index = 0;
-
- /* Previously print out is performed. */
- if (erase_flag) {
- iov[iov_index].iov_base = erase;
- iov[iov_index].iov_len = sizeof erase;
- iov_index++;
- }
-
- /* Output data. */
- column = 1; /* Column position of next character displayed. */
- for (data = b->head; data && (height > 0); data = data->next) {
- size_t cp;
-
- cp = data->sp;
- while ((cp < data->cp) && (height > 0)) {
- /* Calculate lines remaining and column position after displaying
- this character. */
- if (data->data[cp] == '\r')
- column = 1;
- else if ((data->data[cp] == '\n') || (column == width)) {
- column = 1;
- height--;
- } else
- column++;
- cp++;
- }
- iov[iov_index].iov_base = (char *)(data->data + data->sp);
- iov[iov_index++].iov_len = cp - data->sp;
- data->sp = cp;
-
- if (iov_index == iov_alloc)
- /* This should not ordinarily happen. */
- {
- iov_alloc *= 2;
- if (iov != small_iov) {
- zlog_warn("%s: growing iov array to %d; "
- "width %d, height %d, size %lu",
- __func__, iov_alloc, width, height,
- (u_long) b->size);
- iov =
- XREALLOC(MTYPE_TMP, iov,
- iov_alloc * sizeof(*iov));
- } else {
- /* This should absolutely never occur. */
- zlog_err
- ("%s: corruption detected: iov_small overflowed; "
- "head %p, tail %p, head->next %p",
- __func__, b->head, b->tail, b->head->next);
- iov =
- XMALLOC(MTYPE_TMP,
- iov_alloc * sizeof(*iov));
- memcpy(iov, small_iov, sizeof(small_iov));
- }
- }
- }
-
- /* In case of `more' display need. */
- if (b->tail && (b->tail->sp < b->tail->cp) && !no_more_flag) {
- iov[iov_index].iov_base = more;
- iov[iov_index].iov_len = sizeof more;
- iov_index++;
- }
-#ifdef IOV_MAX
- /* IOV_MAX are normally defined in <sys/uio.h> , Posix.1g.
- example: Solaris2.6 are defined IOV_MAX size at 16. */
- {
- struct iovec *c_iov = iov;
- nbytes = 0; /* Make sure it's initialized. */
-
- while (iov_index > 0) {
- int iov_size;
-
- iov_size =
- ((iov_index > IOV_MAX) ? IOV_MAX : iov_index);
- if ((nbytes = writev(fd, c_iov, iov_size)) < 0) {
- zlog_warn("%s: writev to fd %d failed: %s",
- __func__, fd, safe_strerror(errno));
- break;
- }
-
- /* move pointer io-vector */
- c_iov += iov_size;
- iov_index -= iov_size;
- }
- }
-#else /* IOV_MAX */
- if ((nbytes = writev(fd, iov, iov_index)) < 0)
- zlog_warn("%s: writev to fd %d failed: %s",
- __func__, fd, safe_strerror(errno));
-#endif /* IOV_MAX */
-
- /* Free printed buffer data. */
- while (b->head && (b->head->sp == b->head->cp)) {
- struct buffer_data *del;
- if (!(b->head = (del = b->head)->next))
- b->tail = NULL;
- BUFFER_DATA_FREE(del);
- }
-
- if (iov != small_iov)
- XFREE(MTYPE_TMP, iov);
-
- return (nbytes < 0) ? BUFFER_ERROR :
- (b->head ? BUFFER_PENDING : BUFFER_EMPTY);
-}
-#endif
-
-/* This function (unlike other buffer_flush* functions above) is designed
-to work with non-blocking sockets. It does not attempt to write out
-all of the queued data, just a "big" chunk. It returns 0 if it was
-able to empty out the buffers completely, 1 if more flushing is
-required later, or -1 on a fatal write error. */
-buffer_status_t buffer_flush_available(struct buffer * b, int fd)
-{
-
-/* These are just reasonable values to make sure a significant amount of
-data is written. There's no need to go crazy and try to write it all
-in one shot. */
-#ifdef IOV_MAX
-#define MAX_CHUNKS ((IOV_MAX >= 16) ? 16 : IOV_MAX)
-#else
-#define MAX_CHUNKS 16
-#endif
-#define MAX_FLUSH 131072
-
- struct buffer_data *d;
- size_t written;
- struct iovec iov[MAX_CHUNKS];
- size_t iovcnt = 0;
- size_t nbyte = 0;
-
- for (d = b->head; d && (iovcnt < MAX_CHUNKS) && (nbyte < MAX_FLUSH);
- d = d->next, iovcnt++) {
- iov[iovcnt].iov_base = d->data + d->sp;
- nbyte += (iov[iovcnt].iov_len = d->cp - d->sp);
- }
-
- if (!nbyte)
- /* No data to flush: should we issue a warning message? */
- return BUFFER_EMPTY;
-
- /* only place where written should be sign compared */
- if ((ssize_t) (written = writev(fd, iov, iovcnt)) < 0) {
- if (ERRNO_IO_RETRY(errno))
- /* Calling code should try again later. */
- return BUFFER_PENDING;
- return BUFFER_ERROR;
- }
-
- /* Free printed buffer data. */
- while (written > 0) {
- struct buffer_data *d;
- if (!(d = b->head))
- break;
- if (written < d->cp - d->sp) {
- d->sp += written;
- return BUFFER_PENDING;
- }
-
- written -= (d->cp - d->sp);
- if (!(b->head = d->next))
- b->tail = NULL;
- BUFFER_DATA_FREE(d);
- }
-
- return b->head ? BUFFER_PENDING : BUFFER_EMPTY;
-
-#undef MAX_CHUNKS
-#undef MAX_FLUSH
-}
-
-buffer_status_t
-buffer_write(struct buffer * b, int fd, const void *p, size_t size)
-{
- ssize_t nbytes;
-
-#if 0
- /* Should we attempt to drain any previously buffered data? This could help reduce latency in pushing out the data if we are stuck in a long-running thread that is preventing the main select loop from calling the flush thread... */
-
- if (b->head && (buffer_flush_available(b, fd) == BUFFER_ERROR))
- return BUFFER_ERROR;
-#endif
- if (b->head)
- /* Buffer is not empty, so do not attempt to write the new data. */
- nbytes = 0;
- else if ((nbytes = write(fd, p, size)) < 0) {
- if (ERRNO_IO_RETRY(errno))
- nbytes = 0;
- else
- return BUFFER_ERROR;
- }
- /* Add any remaining data to the buffer. */
- {
- size_t written = nbytes;
- if (written < size)
- buffer_put(b, ((const char *)p) + written,
- size - written);
- }
- return b->head ? BUFFER_PENDING : BUFFER_EMPTY;
-}
diff --git a/openbsc/src/vty/cardshell.h b/openbsc/src/vty/cardshell.h
deleted file mode 100644
index 85164d2..0000000
--- a/openbsc/src/vty/cardshell.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#include "../../bscconfig.h"
-#define QUAGGA_PROGNAME PACKAGE_NAME
-#define QUAGGA_VERSION PACKAGE_VERSION
-#define QUAGGA_COPYRIGHT "Harald Welte <laforge@gnumonks.org>"
-#define CONFIGFILE_MASK 022
-#define SYSCONFDIR "/usr/local/etc"
diff --git a/openbsc/src/vty/command.c b/openbsc/src/vty/command.c
deleted file mode 100644
index a1130b6..0000000
--- a/openbsc/src/vty/command.c
+++ /dev/null
@@ -1,3424 +0,0 @@
-/*
- $Id: command.c,v 1.47 2005/04/25 16:26:42 paul Exp $
-
- Command interpreter routine for virtual terminal [aka TeletYpe]
- Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
-
-This file is part of GNU Zebra.
-
-GNU Zebra is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published
-by the Free Software Foundation; either version 2, or (at your
-option) any later version.
-
-GNU Zebra is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Zebra; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include "cardshell.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <errno.h>
-#define _XOPEN_SOURCE
-#include <unistd.h>
-#include <assert.h>
-#include <ctype.h>
-#include <time.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-
-//#include "memory.h"
-//#include "log.h"
-//#include <lib/version.h>
-//#include "thread.h"
-#include <vty/vector.h>
-#include <vty/vty.h>
-#include <vty/command.h>
-//#include "workqueue.h"
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/gsm_subscriber.h>
-#include <osmocore/talloc.h>
-
-void *tall_vty_cmd_ctx;
-
-/* Command vector which includes some level of command lists. Normally
- each daemon maintains each own cmdvec. */
-vector cmdvec;
-
-/* Host information structure. */
-struct host host;
-
-/* Standard command node structures. */
-struct cmd_node auth_node = {
- AUTH_NODE,
- "Password: ",
-};
-
-struct cmd_node view_node = {
- VIEW_NODE,
- "%s> ",
-};
-
-struct cmd_node auth_enable_node = {
- AUTH_ENABLE_NODE,
- "Password: ",
-};
-
-struct cmd_node enable_node = {
- ENABLE_NODE,
- "%s# ",
-};
-
-struct cmd_node config_node = {
- CONFIG_NODE,
- "%s(config)# ",
- 1
-};
-
-/* Default motd string. */
-const char *default_motd = "\r\n\
-Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\
-" QUAGGA_COPYRIGHT "\r\n\
-\r\n";
-
-#if 0
-static struct facility_map {
- int facility;
- const char *name;
- size_t match;
-} syslog_facilities[] = {
- {
- LOG_KERN, "kern", 1}, {
- LOG_USER, "user", 2}, {
- LOG_MAIL, "mail", 1}, {
- LOG_DAEMON, "daemon", 1}, {
- LOG_AUTH, "auth", 1}, {
- LOG_SYSLOG, "syslog", 1}, {
- LOG_LPR, "lpr", 2}, {
- LOG_NEWS, "news", 1}, {
- LOG_UUCP, "uucp", 2}, {
- LOG_CRON, "cron", 1},
-#ifdef LOG_FTP
- {
- LOG_FTP, "ftp", 1},
-#endif
- {
- LOG_LOCAL0, "local0", 6}, {
- LOG_LOCAL1, "local1", 6}, {
- LOG_LOCAL2, "local2", 6}, {
- LOG_LOCAL3, "local3", 6}, {
- LOG_LOCAL4, "local4", 6}, {
- LOG_LOCAL5, "local5", 6}, {
- LOG_LOCAL6, "local6", 6}, {
- LOG_LOCAL7, "local7", 6}, {
-0, NULL, 0},};
-
-static const char *facility_name(int facility)
-{
- struct facility_map *fm;
-
- for (fm = syslog_facilities; fm->name; fm++)
- if (fm->facility == facility)
- return fm->name;
- return "";
-}
-
-static int facility_match(const char *str)
-{
- struct facility_map *fm;
-
- for (fm = syslog_facilities; fm->name; fm++)
- if (!strncmp(str, fm->name, fm->match))
- return fm->facility;
- return -1;
-}
-
-static int level_match(const char *s)
-{
- int level;
-
- for (level = 0; zlog_priority[level] != NULL; level++)
- if (!strncmp(s, zlog_priority[level], 2))
- return level;
- return ZLOG_DISABLED;
-}
-#endif
-
-/* This is called from main when a daemon is invoked with -v or --version. */
-void print_version(const char *progname)
-{
- printf("%s version %s\n", progname, QUAGGA_VERSION);
- printf("%s\n", QUAGGA_COPYRIGHT);
-}
-
-/* Utility function to concatenate argv argument into a single string
- with inserting ' ' character between each argument. */
-char *argv_concat(const char **argv, int argc, int shift)
-{
- int i;
- size_t len;
- char *str;
- char *p;
-
- len = 0;
- for (i = shift; i < argc; i++)
- len += strlen(argv[i]) + 1;
- if (!len)
- return NULL;
- p = str = _talloc_zero(tall_vty_cmd_ctx, len, "arvg_concat");
- for (i = shift; i < argc; i++) {
- size_t arglen;
- memcpy(p, argv[i], (arglen = strlen(argv[i])));
- p += arglen;
- *p++ = ' ';
- }
- *(p - 1) = '\0';
- return str;
-}
-
-/* Install top node of command vector. */
-void install_node(struct cmd_node *node, int (*func) (struct vty *))
-{
- vector_set_index(cmdvec, node->node, node);
- node->func = func;
- node->cmd_vector = vector_init(VECTOR_MIN_SIZE);
-}
-
-/* Compare two command's string. Used in sort_node (). */
-static int cmp_node(const void *p, const void *q)
-{
- struct cmd_element *a = *(struct cmd_element **)p;
- struct cmd_element *b = *(struct cmd_element **)q;
-
- return strcmp(a->string, b->string);
-}
-
-static int cmp_desc(const void *p, const void *q)
-{
- struct desc *a = *(struct desc **)p;
- struct desc *b = *(struct desc **)q;
-
- return strcmp(a->cmd, b->cmd);
-}
-
-/* Sort each node's command element according to command string. */
-void sort_node()
-{
- unsigned int i, j;
- struct cmd_node *cnode;
- vector descvec;
- struct cmd_element *cmd_element;
-
- for (i = 0; i < vector_active(cmdvec); i++)
- if ((cnode = vector_slot(cmdvec, i)) != NULL) {
- vector cmd_vector = cnode->cmd_vector;
- qsort(cmd_vector->index, vector_active(cmd_vector),
- sizeof(void *), cmp_node);
-
- for (j = 0; j < vector_active(cmd_vector); j++)
- if ((cmd_element =
- vector_slot(cmd_vector, j)) != NULL
- && vector_active(cmd_element->strvec)) {
- descvec =
- vector_slot(cmd_element->strvec,
- vector_active
- (cmd_element->strvec) -
- 1);
- qsort(descvec->index,
- vector_active(descvec),
- sizeof(void *), cmp_desc);
- }
- }
-}
-
-/* Breaking up string into each command piece. I assume given
- character is separated by a space character. Return value is a
- vector which includes char ** data element. */
-vector cmd_make_strvec(const char *string)
-{
- const char *cp, *start;
- char *token;
- int strlen;
- vector strvec;
-
- if (string == NULL)
- return NULL;
-
- cp = string;
-
- /* Skip white spaces. */
- while (isspace((int)*cp) && *cp != '\0')
- cp++;
-
- /* Return if there is only white spaces */
- if (*cp == '\0')
- return NULL;
-
- if (*cp == '!' || *cp == '#')
- return NULL;
-
- /* Prepare return vector. */
- strvec = vector_init(VECTOR_MIN_SIZE);
-
- /* Copy each command piece and set into vector. */
- while (1) {
- start = cp;
- while (!(isspace((int)*cp) || *cp == '\r' || *cp == '\n') &&
- *cp != '\0')
- cp++;
- strlen = cp - start;
- token = _talloc_zero(tall_vty_cmd_ctx, strlen + 1, "make_strvec");
- memcpy(token, start, strlen);
- *(token + strlen) = '\0';
- vector_set(strvec, token);
-
- while ((isspace((int)*cp) || *cp == '\n' || *cp == '\r') &&
- *cp != '\0')
- cp++;
-
- if (*cp == '\0')
- return strvec;
- }
-}
-
-/* Free allocated string vector. */
-void cmd_free_strvec(vector v)
-{
- unsigned int i;
- char *cp;
-
- if (!v)
- return;
-
- for (i = 0; i < vector_active(v); i++)
- if ((cp = vector_slot(v, i)) != NULL)
- talloc_free(cp);
-
- vector_free(v);
-}
-
-/* Fetch next description. Used in cmd_make_descvec(). */
-static char *cmd_desc_str(const char **string)
-{
- const char *cp, *start;
- char *token;
- int strlen;
-
- cp = *string;
-
- if (cp == NULL)
- return NULL;
-
- /* Skip white spaces. */
- while (isspace((int)*cp) && *cp != '\0')
- cp++;
-
- /* Return if there is only white spaces */
- if (*cp == '\0')
- return NULL;
-
- start = cp;
-
- while (!(*cp == '\r' || *cp == '\n') && *cp != '\0')
- cp++;
-
- strlen = cp - start;
- token = _talloc_zero(tall_vty_cmd_ctx, strlen + 1, "cmd_desc_str");
- memcpy(token, start, strlen);
- *(token + strlen) = '\0';
-
- *string = cp;
-
- return token;
-}
-
-/* New string vector. */
-static vector cmd_make_descvec(const char *string, const char *descstr)
-{
- int multiple = 0;
- const char *sp;
- char *token;
- int len;
- const char *cp;
- const char *dp;
- vector allvec;
- vector strvec = NULL;
- struct desc *desc;
-
- cp = string;
- dp = descstr;
-
- if (cp == NULL)
- return NULL;
-
- allvec = vector_init(VECTOR_MIN_SIZE);
-
- while (1) {
- while (isspace((int)*cp) && *cp != '\0')
- cp++;
-
- if (*cp == '(') {
- multiple = 1;
- cp++;
- }
- if (*cp == ')') {
- multiple = 0;
- cp++;
- }
- if (*cp == '|') {
- if (!multiple) {
- fprintf(stderr, "Command parse error!: %s\n",
- string);
- exit(1);
- }
- cp++;
- }
-
- while (isspace((int)*cp) && *cp != '\0')
- cp++;
-
- if (*cp == '(') {
- multiple = 1;
- cp++;
- }
-
- if (*cp == '\0')
- return allvec;
-
- sp = cp;
-
- while (!
- (isspace((int)*cp) || *cp == '\r' || *cp == '\n'
- || *cp == ')' || *cp == '|') && *cp != '\0')
- cp++;
-
- len = cp - sp;
-
- token = _talloc_zero(tall_vty_cmd_ctx, len + 1, "cmd_make_descvec");
- memcpy(token, sp, len);
- *(token + len) = '\0';
-
- desc = talloc_zero(tall_vty_cmd_ctx, struct desc);
- desc->cmd = token;
- desc->str = cmd_desc_str(&dp);
-
- if (multiple) {
- if (multiple == 1) {
- strvec = vector_init(VECTOR_MIN_SIZE);
- vector_set(allvec, strvec);
- }
- multiple++;
- } else {
- strvec = vector_init(VECTOR_MIN_SIZE);
- vector_set(allvec, strvec);
- }
- vector_set(strvec, desc);
- }
-}
-
-/* Count mandantory string vector size. This is to determine inputed
- command has enough command length. */
-static int cmd_cmdsize(vector strvec)
-{
- unsigned int i;
- int size = 0;
- vector descvec;
- struct desc *desc;
-
- for (i = 0; i < vector_active(strvec); i++)
- if ((descvec = vector_slot(strvec, i)) != NULL) {
- if ((vector_active(descvec)) == 1
- && (desc = vector_slot(descvec, 0)) != NULL) {
- if (desc->cmd == NULL || CMD_OPTION(desc->cmd))
- return size;
- else
- size++;
- } else
- size++;
- }
- return size;
-}
-
-/* Return prompt character of specified node. */
-const char *cmd_prompt(enum node_type node)
-{
- struct cmd_node *cnode;
-
- cnode = vector_slot(cmdvec, node);
- return cnode->prompt;
-}
-
-/* Install a command into a node. */
-void install_element(enum node_type ntype, struct cmd_element *cmd)
-{
- struct cmd_node *cnode;
-
- cnode = vector_slot(cmdvec, ntype);
-
- if (cnode == NULL) {
- fprintf(stderr,
- "Command node %d doesn't exist, please check it\n",
- ntype);
- exit(1);
- }
-
- vector_set(cnode->cmd_vector, cmd);
-
- cmd->strvec = cmd_make_descvec(cmd->string, cmd->doc);
- cmd->cmdsize = cmd_cmdsize(cmd->strvec);
-}
-
-/* Install a command into VIEW and ENABLE node */
-void install_element_ve(struct cmd_element *cmd)
-{
- install_element(VIEW_NODE, cmd);
- install_element(ENABLE_NODE, cmd);
-}
-
-#ifdef VTY_CRYPT_PW
-static unsigned char itoa64[] =
- "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-
-static void to64(char *s, long v, int n)
-{
- while (--n >= 0) {
- *s++ = itoa64[v & 0x3f];
- v >>= 6;
- }
-}
-
-static char *zencrypt(const char *passwd)
-{
- char salt[6];
- struct timeval tv;
- char *crypt(const char *, const char *);
-
- gettimeofday(&tv, 0);
-
- to64(&salt[0], random(), 3);
- to64(&salt[3], tv.tv_usec, 3);
- salt[5] = '\0';
-
- return crypt(passwd, salt);
-}
-#endif
-
-/* This function write configuration of this host. */
-static int config_write_host(struct vty *vty)
-{
- if (host.name)
- vty_out(vty, "hostname %s%s", host.name, VTY_NEWLINE);
-
- if (host.encrypt) {
- if (host.password_encrypt)
- vty_out(vty, "password 8 %s%s", host.password_encrypt,
- VTY_NEWLINE);
- if (host.enable_encrypt)
- vty_out(vty, "enable password 8 %s%s",
- host.enable_encrypt, VTY_NEWLINE);
- } else {
- if (host.password)
- vty_out(vty, "password %s%s", host.password,
- VTY_NEWLINE);
- if (host.enable)
- vty_out(vty, "enable password %s%s", host.enable,
- VTY_NEWLINE);
- }
-
-#if 0
- if (zlog_default->default_lvl != LOG_DEBUG) {
- vty_out(vty, "! N.B. The 'log trap' command is deprecated.%s",
- VTY_NEWLINE);
- vty_out(vty, "log trap %s%s",
- zlog_priority[zlog_default->default_lvl], VTY_NEWLINE);
- }
-
- if (host.logfile
- && (zlog_default->maxlvl[ZLOG_DEST_FILE] != ZLOG_DISABLED)) {
- vty_out(vty, "log file %s", host.logfile);
- if (zlog_default->maxlvl[ZLOG_DEST_FILE] !=
- zlog_default->default_lvl)
- vty_out(vty, " %s",
- zlog_priority[zlog_default->
- maxlvl[ZLOG_DEST_FILE]]);
- vty_out(vty, "%s", VTY_NEWLINE);
- }
-
- if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != ZLOG_DISABLED) {
- vty_out(vty, "log stdout");
- if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] !=
- zlog_default->default_lvl)
- vty_out(vty, " %s",
- zlog_priority[zlog_default->
- maxlvl[ZLOG_DEST_STDOUT]]);
- vty_out(vty, "%s", VTY_NEWLINE);
- }
-
- if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED)
- vty_out(vty, "no log monitor%s", VTY_NEWLINE);
- else if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] !=
- zlog_default->default_lvl)
- vty_out(vty, "log monitor %s%s",
- zlog_priority[zlog_default->maxlvl[ZLOG_DEST_MONITOR]],
- VTY_NEWLINE);
-
- if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) {
- vty_out(vty, "log syslog");
- if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] !=
- zlog_default->default_lvl)
- vty_out(vty, " %s",
- zlog_priority[zlog_default->
- maxlvl[ZLOG_DEST_SYSLOG]]);
- vty_out(vty, "%s", VTY_NEWLINE);
- }
-
- if (zlog_default->facility != LOG_DAEMON)
- vty_out(vty, "log facility %s%s",
- facility_name(zlog_default->facility), VTY_NEWLINE);
-
- if (zlog_default->record_priority == 1)
- vty_out(vty, "log record-priority%s", VTY_NEWLINE);
-#endif
- if (host.advanced)
- vty_out(vty, "service advanced-vty%s", VTY_NEWLINE);
-
- if (host.encrypt)
- vty_out(vty, "service password-encryption%s", VTY_NEWLINE);
-
- if (host.lines >= 0)
- vty_out(vty, "service terminal-length %d%s", host.lines,
- VTY_NEWLINE);
-
- if (host.motdfile)
- vty_out(vty, "banner motd file %s%s", host.motdfile,
- VTY_NEWLINE);
- else if (!host.motd)
- vty_out(vty, "no banner motd%s", VTY_NEWLINE);
-
- return 1;
-}
-
-/* Utility function for getting command vector. */
-static vector cmd_node_vector(vector v, enum node_type ntype)
-{
- struct cmd_node *cnode = vector_slot(v, ntype);
- return cnode->cmd_vector;
-}
-
-#if 0
-/* Filter command vector by symbol. This function is not actually used;
- * should it be deleted? */
-static int cmd_filter_by_symbol(char *command, char *symbol)
-{
- int i, lim;
-
- if (strcmp(symbol, "IPV4_ADDRESS") == 0) {
- i = 0;
- lim = strlen(command);
- while (i < lim) {
- if (!
- (isdigit((int)command[i]) || command[i] == '.'
- || command[i] == '/'))
- return 1;
- i++;
- }
- return 0;
- }
- if (strcmp(symbol, "STRING") == 0) {
- i = 0;
- lim = strlen(command);
- while (i < lim) {
- if (!
- (isalpha((int)command[i]) || command[i] == '_'
- || command[i] == '-'))
- return 1;
- i++;
- }
- return 0;
- }
- if (strcmp(symbol, "IFNAME") == 0) {
- i = 0;
- lim = strlen(command);
- while (i < lim) {
- if (!isalnum((int)command[i]))
- return 1;
- i++;
- }
- return 0;
- }
- return 0;
-}
-#endif
-
-/* Completion match types. */
-enum match_type {
- no_match,
- extend_match,
- ipv4_prefix_match,
- ipv4_match,
- ipv6_prefix_match,
- ipv6_match,
- range_match,
- vararg_match,
- partly_match,
- exact_match
-};
-
-static enum match_type cmd_ipv4_match(const char *str)
-{
- const char *sp;
- int dots = 0, nums = 0;
- char buf[4];
-
- if (str == NULL)
- return partly_match;
-
- for (;;) {
- memset(buf, 0, sizeof(buf));
- sp = str;
- while (*str != '\0') {
- if (*str == '.') {
- if (dots >= 3)
- return no_match;
-
- if (*(str + 1) == '.')
- return no_match;
-
- if (*(str + 1) == '\0')
- return partly_match;
-
- dots++;
- break;
- }
- if (!isdigit((int)*str))
- return no_match;
-
- str++;
- }
-
- if (str - sp > 3)
- return no_match;
-
- strncpy(buf, sp, str - sp);
- if (atoi(buf) > 255)
- return no_match;
-
- nums++;
-
- if (*str == '\0')
- break;
-
- str++;
- }
-
- if (nums < 4)
- return partly_match;
-
- return exact_match;
-}
-
-static enum match_type cmd_ipv4_prefix_match(const char *str)
-{
- const char *sp;
- int dots = 0;
- char buf[4];
-
- if (str == NULL)
- return partly_match;
-
- for (;;) {
- memset(buf, 0, sizeof(buf));
- sp = str;
- while (*str != '\0' && *str != '/') {
- if (*str == '.') {
- if (dots == 3)
- return no_match;
-
- if (*(str + 1) == '.' || *(str + 1) == '/')
- return no_match;
-
- if (*(str + 1) == '\0')
- return partly_match;
-
- dots++;
- break;
- }
-
- if (!isdigit((int)*str))
- return no_match;
-
- str++;
- }
-
- if (str - sp > 3)
- return no_match;
-
- strncpy(buf, sp, str - sp);
- if (atoi(buf) > 255)
- return no_match;
-
- if (dots == 3) {
- if (*str == '/') {
- if (*(str + 1) == '\0')
- return partly_match;
-
- str++;
- break;
- } else if (*str == '\0')
- return partly_match;
- }
-
- if (*str == '\0')
- return partly_match;
-
- str++;
- }
-
- sp = str;
- while (*str != '\0') {
- if (!isdigit((int)*str))
- return no_match;
-
- str++;
- }
-
- if (atoi(sp) > 32)
- return no_match;
-
- return exact_match;
-}
-
-#define IPV6_ADDR_STR "0123456789abcdefABCDEF:.%"
-#define IPV6_PREFIX_STR "0123456789abcdefABCDEF:.%/"
-#define STATE_START 1
-#define STATE_COLON 2
-#define STATE_DOUBLE 3
-#define STATE_ADDR 4
-#define STATE_DOT 5
-#define STATE_SLASH 6
-#define STATE_MASK 7
-
-#ifdef HAVE_IPV6
-
-static enum match_type cmd_ipv6_match(const char *str)
-{
- int state = STATE_START;
- int colons = 0, nums = 0, double_colon = 0;
- const char *sp = NULL;
- struct sockaddr_in6 sin6_dummy;
- int ret;
-
- if (str == NULL)
- return partly_match;
-
- if (strspn(str, IPV6_ADDR_STR) != strlen(str))
- return no_match;
-
- /* use inet_pton that has a better support,
- * for example inet_pton can support the automatic addresses:
- * ::1.2.3.4
- */
- ret = inet_pton(AF_INET6, str, &sin6_dummy.sin6_addr);
-
- if (ret == 1)
- return exact_match;
-
- while (*str != '\0') {
- switch (state) {
- case STATE_START:
- if (*str == ':') {
- if (*(str + 1) != ':' && *(str + 1) != '\0')
- return no_match;
- colons--;
- state = STATE_COLON;
- } else {
- sp = str;
- state = STATE_ADDR;
- }
-
- continue;
- case STATE_COLON:
- colons++;
- if (*(str + 1) == ':')
- state = STATE_DOUBLE;
- else {
- sp = str + 1;
- state = STATE_ADDR;
- }
- break;
- case STATE_DOUBLE:
- if (double_colon)
- return no_match;
-
- if (*(str + 1) == ':')
- return no_match;
- else {
- if (*(str + 1) != '\0')
- colons++;
- sp = str + 1;
- state = STATE_ADDR;
- }
-
- double_colon++;
- nums++;
- break;
- case STATE_ADDR:
- if (*(str + 1) == ':' || *(str + 1) == '\0') {
- if (str - sp > 3)
- return no_match;
-
- nums++;
- state = STATE_COLON;
- }
- if (*(str + 1) == '.')
- state = STATE_DOT;
- break;
- case STATE_DOT:
- state = STATE_ADDR;
- break;
- default:
- break;
- }
-
- if (nums > 8)
- return no_match;
-
- if (colons > 7)
- return no_match;
-
- str++;
- }
-
-#if 0
- if (nums < 11)
- return partly_match;
-#endif /* 0 */
-
- return exact_match;
-}
-
-static enum match_type cmd_ipv6_prefix_match(const char *str)
-{
- int state = STATE_START;
- int colons = 0, nums = 0, double_colon = 0;
- int mask;
- const char *sp = NULL;
- char *endptr = NULL;
-
- if (str == NULL)
- return partly_match;
-
- if (strspn(str, IPV6_PREFIX_STR) != strlen(str))
- return no_match;
-
- while (*str != '\0' && state != STATE_MASK) {
- switch (state) {
- case STATE_START:
- if (*str == ':') {
- if (*(str + 1) != ':' && *(str + 1) != '\0')
- return no_match;
- colons--;
- state = STATE_COLON;
- } else {
- sp = str;
- state = STATE_ADDR;
- }
-
- continue;
- case STATE_COLON:
- colons++;
- if (*(str + 1) == '/')
- return no_match;
- else if (*(str + 1) == ':')
- state = STATE_DOUBLE;
- else {
- sp = str + 1;
- state = STATE_ADDR;
- }
- break;
- case STATE_DOUBLE:
- if (double_colon)
- return no_match;
-
- if (*(str + 1) == ':')
- return no_match;
- else {
- if (*(str + 1) != '\0' && *(str + 1) != '/')
- colons++;
- sp = str + 1;
-
- if (*(str + 1) == '/')
- state = STATE_SLASH;
- else
- state = STATE_ADDR;
- }
-
- double_colon++;
- nums += 1;
- break;
- case STATE_ADDR:
- if (*(str + 1) == ':' || *(str + 1) == '.'
- || *(str + 1) == '\0' || *(str + 1) == '/') {
- if (str - sp > 3)
- return no_match;
-
- for (; sp <= str; sp++)
- if (*sp == '/')
- return no_match;
-
- nums++;
-
- if (*(str + 1) == ':')
- state = STATE_COLON;
- else if (*(str + 1) == '.')
- state = STATE_DOT;
- else if (*(str + 1) == '/')
- state = STATE_SLASH;
- }
- break;
- case STATE_DOT:
- state = STATE_ADDR;
- break;
- case STATE_SLASH:
- if (*(str + 1) == '\0')
- return partly_match;
-
- state = STATE_MASK;
- break;
- default:
- break;
- }
-
- if (nums > 11)
- return no_match;
-
- if (colons > 7)
- return no_match;
-
- str++;
- }
-
- if (state < STATE_MASK)
- return partly_match;
-
- mask = strtol(str, &endptr, 10);
- if (*endptr != '\0')
- return no_match;
-
- if (mask < 0 || mask > 128)
- return no_match;
-
-/* I don't know why mask < 13 makes command match partly.
- Forgive me to make this comments. I Want to set static default route
- because of lack of function to originate default in ospf6d; sorry
- yasu
- if (mask < 13)
- return partly_match;
-*/
-
- return exact_match;
-}
-
-#endif /* HAVE_IPV6 */
-
-#define DECIMAL_STRLEN_MAX 10
-
-static int cmd_range_match(const char *range, const char *str)
-{
- char *p;
- char buf[DECIMAL_STRLEN_MAX + 1];
- char *endptr = NULL;
- unsigned long min, max, val;
-
- if (str == NULL)
- return 1;
-
- val = strtoul(str, &endptr, 10);
- if (*endptr != '\0')
- return 0;
-
- range++;
- p = strchr(range, '-');
- if (p == NULL)
- return 0;
- if (p - range > DECIMAL_STRLEN_MAX)
- return 0;
- strncpy(buf, range, p - range);
- buf[p - range] = '\0';
- min = strtoul(buf, &endptr, 10);
- if (*endptr != '\0')
- return 0;
-
- range = p + 1;
- p = strchr(range, '>');
- if (p == NULL)
- return 0;
- if (p - range > DECIMAL_STRLEN_MAX)
- return 0;
- strncpy(buf, range, p - range);
- buf[p - range] = '\0';
- max = strtoul(buf, &endptr, 10);
- if (*endptr != '\0')
- return 0;
-
- if (val < min || val > max)
- return 0;
-
- return 1;
-}
-
-/* Make completion match and return match type flag. */
-static enum match_type
-cmd_filter_by_completion(char *command, vector v, unsigned int index)
-{
- unsigned int i;
- const char *str;
- struct cmd_element *cmd_element;
- enum match_type match_type;
- vector descvec;
- struct desc *desc;
-
- match_type = no_match;
-
- /* If command and cmd_element string does not match set NULL to vector */
- for (i = 0; i < vector_active(v); i++)
- if ((cmd_element = vector_slot(v, i)) != NULL) {
- if (index >= vector_active(cmd_element->strvec))
- vector_slot(v, i) = NULL;
- else {
- unsigned int j;
- int matched = 0;
-
- descvec =
- vector_slot(cmd_element->strvec, index);
-
- for (j = 0; j < vector_active(descvec); j++)
- if ((desc = vector_slot(descvec, j))) {
- str = desc->cmd;
-
- if (CMD_VARARG(str)) {
- if (match_type <
- vararg_match)
- match_type =
- vararg_match;
- matched++;
- } else if (CMD_RANGE(str)) {
- if (cmd_range_match
- (str, command)) {
- if (match_type <
- range_match)
- match_type
- =
- range_match;
-
- matched++;
- }
- }
-#ifdef HAVE_IPV6
- else if (CMD_IPV6(str)) {
- if (cmd_ipv6_match
- (command)) {
- if (match_type <
- ipv6_match)
- match_type
- =
- ipv6_match;
-
- matched++;
- }
- } else if (CMD_IPV6_PREFIX(str)) {
- if (cmd_ipv6_prefix_match(command)) {
- if (match_type <
- ipv6_prefix_match)
- match_type
- =
- ipv6_prefix_match;
-
- matched++;
- }
- }
-#endif /* HAVE_IPV6 */
- else if (CMD_IPV4(str)) {
- if (cmd_ipv4_match
- (command)) {
- if (match_type <
- ipv4_match)
- match_type
- =
- ipv4_match;
-
- matched++;
- }
- } else if (CMD_IPV4_PREFIX(str)) {
- if (cmd_ipv4_prefix_match(command)) {
- if (match_type <
- ipv4_prefix_match)
- match_type
- =
- ipv4_prefix_match;
- matched++;
- }
- } else
- /* Check is this point's argument optional ? */
- if (CMD_OPTION(str)
- ||
- CMD_VARIABLE(str)) {
- if (match_type <
- extend_match)
- match_type =
- extend_match;
- matched++;
- } else
- if (strncmp
- (command, str,
- strlen(command)) ==
- 0) {
- if (strcmp(command, str)
- == 0)
- match_type =
- exact_match;
- else {
- if (match_type <
- partly_match)
- match_type
- =
- partly_match;
- }
- matched++;
- }
- }
- if (!matched)
- vector_slot(v, i) = NULL;
- }
- }
- return match_type;
-}
-
-/* Filter vector by command character with index. */
-static enum match_type
-cmd_filter_by_string(char *command, vector v, unsigned int index)
-{
- unsigned int i;
- const char *str;
- struct cmd_element *cmd_element;
- enum match_type match_type;
- vector descvec;
- struct desc *desc;
-
- match_type = no_match;
-
- /* If command and cmd_element string does not match set NULL to vector */
- for (i = 0; i < vector_active(v); i++)
- if ((cmd_element = vector_slot(v, i)) != NULL) {
- /* If given index is bigger than max string vector of command,
- set NULL */
- if (index >= vector_active(cmd_element->strvec))
- vector_slot(v, i) = NULL;
- else {
- unsigned int j;
- int matched = 0;
-
- descvec =
- vector_slot(cmd_element->strvec, index);
-
- for (j = 0; j < vector_active(descvec); j++)
- if ((desc = vector_slot(descvec, j))) {
- str = desc->cmd;
-
- if (CMD_VARARG(str)) {
- if (match_type <
- vararg_match)
- match_type =
- vararg_match;
- matched++;
- } else if (CMD_RANGE(str)) {
- if (cmd_range_match
- (str, command)) {
- if (match_type <
- range_match)
- match_type
- =
- range_match;
- matched++;
- }
- }
-#ifdef HAVE_IPV6
- else if (CMD_IPV6(str)) {
- if (cmd_ipv6_match
- (command) ==
- exact_match) {
- if (match_type <
- ipv6_match)
- match_type
- =
- ipv6_match;
- matched++;
- }
- } else if (CMD_IPV6_PREFIX(str)) {
- if (cmd_ipv6_prefix_match(command) == exact_match) {
- if (match_type <
- ipv6_prefix_match)
- match_type
- =
- ipv6_prefix_match;
- matched++;
- }
- }
-#endif /* HAVE_IPV6 */
- else if (CMD_IPV4(str)) {
- if (cmd_ipv4_match
- (command) ==
- exact_match) {
- if (match_type <
- ipv4_match)
- match_type
- =
- ipv4_match;
- matched++;
- }
- } else if (CMD_IPV4_PREFIX(str)) {
- if (cmd_ipv4_prefix_match(command) == exact_match) {
- if (match_type <
- ipv4_prefix_match)
- match_type
- =
- ipv4_prefix_match;
- matched++;
- }
- } else if (CMD_OPTION(str)
- || CMD_VARIABLE(str))
- {
- if (match_type <
- extend_match)
- match_type =
- extend_match;
- matched++;
- } else {
- if (strcmp(command, str)
- == 0) {
- match_type =
- exact_match;
- matched++;
- }
- }
- }
- if (!matched)
- vector_slot(v, i) = NULL;
- }
- }
- return match_type;
-}
-
-/* Check ambiguous match */
-static int
-is_cmd_ambiguous(char *command, vector v, int index, enum match_type type)
-{
- unsigned int i;
- unsigned int j;
- const char *str = NULL;
- struct cmd_element *cmd_element;
- const char *matched = NULL;
- vector descvec;
- struct desc *desc;
-
- for (i = 0; i < vector_active(v); i++)
- if ((cmd_element = vector_slot(v, i)) != NULL) {
- int match = 0;
-
- descvec = vector_slot(cmd_element->strvec, index);
-
- for (j = 0; j < vector_active(descvec); j++)
- if ((desc = vector_slot(descvec, j))) {
- enum match_type ret;
-
- str = desc->cmd;
-
- switch (type) {
- case exact_match:
- if (!
- (CMD_OPTION(str)
- || CMD_VARIABLE(str))
-&& strcmp(command, str) == 0)
- match++;
- break;
- case partly_match:
- if (!
- (CMD_OPTION(str)
- || CMD_VARIABLE(str))
-&& strncmp(command, str, strlen(command)) == 0) {
- if (matched
- && strcmp(matched,
- str) != 0)
- return 1; /* There is ambiguous match. */
- else
- matched = str;
- match++;
- }
- break;
- case range_match:
- if (cmd_range_match
- (str, command)) {
- if (matched
- && strcmp(matched,
- str) != 0)
- return 1;
- else
- matched = str;
- match++;
- }
- break;
-#ifdef HAVE_IPV6
- case ipv6_match:
- if (CMD_IPV6(str))
- match++;
- break;
- case ipv6_prefix_match:
- if ((ret =
- cmd_ipv6_prefix_match
- (command)) != no_match) {
- if (ret == partly_match)
- return 2; /* There is incomplete match. */
-
- match++;
- }
- break;
-#endif /* HAVE_IPV6 */
- case ipv4_match:
- if (CMD_IPV4(str))
- match++;
- break;
- case ipv4_prefix_match:
- if ((ret =
- cmd_ipv4_prefix_match
- (command)) != no_match) {
- if (ret == partly_match)
- return 2; /* There is incomplete match. */
-
- match++;
- }
- break;
- case extend_match:
- if (CMD_OPTION(str)
- || CMD_VARIABLE(str))
- match++;
- break;
- case no_match:
- default:
- break;
- }
- }
- if (!match)
- vector_slot(v, i) = NULL;
- }
- return 0;
-}
-
-/* If src matches dst return dst string, otherwise return NULL */
-static const char *cmd_entry_function(const char *src, const char *dst)
-{
- /* Skip variable arguments. */
- if (CMD_OPTION(dst) || CMD_VARIABLE(dst) || CMD_VARARG(dst) ||
- CMD_IPV4(dst) || CMD_IPV4_PREFIX(dst) || CMD_RANGE(dst))
- return NULL;
-
- /* In case of 'command \t', given src is NULL string. */
- if (src == NULL)
- return dst;
-
- /* Matched with input string. */
- if (strncmp(src, dst, strlen(src)) == 0)
- return dst;
-
- return NULL;
-}
-
-/* If src matches dst return dst string, otherwise return NULL */
-/* This version will return the dst string always if it is
- CMD_VARIABLE for '?' key processing */
-static const char *cmd_entry_function_desc(const char *src, const char *dst)
-{
- if (CMD_VARARG(dst))
- return dst;
-
- if (CMD_RANGE(dst)) {
- if (cmd_range_match(dst, src))
- return dst;
- else
- return NULL;
- }
-#ifdef HAVE_IPV6
- if (CMD_IPV6(dst)) {
- if (cmd_ipv6_match(src))
- return dst;
- else
- return NULL;
- }
-
- if (CMD_IPV6_PREFIX(dst)) {
- if (cmd_ipv6_prefix_match(src))
- return dst;
- else
- return NULL;
- }
-#endif /* HAVE_IPV6 */
-
- if (CMD_IPV4(dst)) {
- if (cmd_ipv4_match(src))
- return dst;
- else
- return NULL;
- }
-
- if (CMD_IPV4_PREFIX(dst)) {
- if (cmd_ipv4_prefix_match(src))
- return dst;
- else
- return NULL;
- }
-
- /* Optional or variable commands always match on '?' */
- if (CMD_OPTION(dst) || CMD_VARIABLE(dst))
- return dst;
-
- /* In case of 'command \t', given src is NULL string. */
- if (src == NULL)
- return dst;
-
- if (strncmp(src, dst, strlen(src)) == 0)
- return dst;
- else
- return NULL;
-}
-
-/* Check same string element existence. If it isn't there return
- 1. */
-static int cmd_unique_string(vector v, const char *str)
-{
- unsigned int i;
- char *match;
-
- for (i = 0; i < vector_active(v); i++)
- if ((match = vector_slot(v, i)) != NULL)
- if (strcmp(match, str) == 0)
- return 0;
- return 1;
-}
-
-/* Compare string to description vector. If there is same string
- return 1 else return 0. */
-static int desc_unique_string(vector v, const char *str)
-{
- unsigned int i;
- struct desc *desc;
-
- for (i = 0; i < vector_active(v); i++)
- if ((desc = vector_slot(v, i)) != NULL)
- if (strcmp(desc->cmd, str) == 0)
- return 1;
- return 0;
-}
-
-static int cmd_try_do_shortcut(enum node_type node, char *first_word)
-{
- if (first_word != NULL &&
- node != AUTH_NODE &&
- node != VIEW_NODE &&
- node != AUTH_ENABLE_NODE &&
- node != ENABLE_NODE && 0 == strcmp("do", first_word))
- return 1;
- return 0;
-}
-
-/* '?' describe command support. */
-static vector
-cmd_describe_command_real(vector vline, struct vty *vty, int *status)
-{
- unsigned int i;
- vector cmd_vector;
-#define INIT_MATCHVEC_SIZE 10
- vector matchvec;
- struct cmd_element *cmd_element;
- unsigned int index;
- int ret;
- enum match_type match;
- char *command;
- static struct desc desc_cr = { "<cr>", "" };
-
- /* Set index. */
- if (vector_active(vline) == 0) {
- *status = CMD_ERR_NO_MATCH;
- return NULL;
- } else
- index = vector_active(vline) - 1;
-
- /* Make copy vector of current node's command vector. */
- cmd_vector = vector_copy(cmd_node_vector(cmdvec, vty->node));
-
- /* Prepare match vector */
- matchvec = vector_init(INIT_MATCHVEC_SIZE);
-
- /* Filter commands. */
- /* Only words precedes current word will be checked in this loop. */
- for (i = 0; i < index; i++)
- if ((command = vector_slot(vline, i))) {
- match =
- cmd_filter_by_completion(command, cmd_vector, i);
-
- if (match == vararg_match) {
- struct cmd_element *cmd_element;
- vector descvec;
- unsigned int j, k;
-
- for (j = 0; j < vector_active(cmd_vector); j++)
- if ((cmd_element =
- vector_slot(cmd_vector, j)) != NULL
- &&
- (vector_active
- (cmd_element->strvec))) {
- descvec =
- vector_slot(cmd_element->
- strvec,
- vector_active
- (cmd_element->
- strvec) - 1);
- for (k = 0;
- k < vector_active(descvec);
- k++) {
- struct desc *desc =
- vector_slot(descvec,
- k);
- vector_set(matchvec,
- desc);
- }
- }
-
- vector_set(matchvec, &desc_cr);
- vector_free(cmd_vector);
-
- return matchvec;
- }
-
- if ((ret =
- is_cmd_ambiguous(command, cmd_vector, i,
- match)) == 1) {
- vector_free(cmd_vector);
- *status = CMD_ERR_AMBIGUOUS;
- return NULL;
- } else if (ret == 2) {
- vector_free(cmd_vector);
- *status = CMD_ERR_NO_MATCH;
- return NULL;
- }
- }
-
- /* Prepare match vector */
- /* matchvec = vector_init (INIT_MATCHVEC_SIZE); */
-
- /* Make sure that cmd_vector is filtered based on current word */
- command = vector_slot(vline, index);
- if (command)
- match = cmd_filter_by_completion(command, cmd_vector, index);
-
- /* Make description vector. */
- for (i = 0; i < vector_active(cmd_vector); i++)
- if ((cmd_element = vector_slot(cmd_vector, i)) != NULL) {
- const char *string = NULL;
- vector strvec = cmd_element->strvec;
-
- /* if command is NULL, index may be equal to vector_active */
- if (command && index >= vector_active(strvec))
- vector_slot(cmd_vector, i) = NULL;
- else {
- /* Check if command is completed. */
- if (command == NULL
- && index == vector_active(strvec)) {
- string = "<cr>";
- if (!desc_unique_string
- (matchvec, string))
- vector_set(matchvec, &desc_cr);
- } else {
- unsigned int j;
- vector descvec =
- vector_slot(strvec, index);
- struct desc *desc;
-
- for (j = 0; j < vector_active(descvec);
- j++)
- if ((desc =
- vector_slot(descvec, j))) {
- string =
- cmd_entry_function_desc
- (command,
- desc->cmd);
- if (string) {
- /* Uniqueness check */
- if (!desc_unique_string(matchvec, string))
- vector_set
- (matchvec,
- desc);
- }
- }
- }
- }
- }
- vector_free(cmd_vector);
-
- if (vector_slot(matchvec, 0) == NULL) {
- vector_free(matchvec);
- *status = CMD_ERR_NO_MATCH;
- } else
- *status = CMD_SUCCESS;
-
- return matchvec;
-}
-
-vector cmd_describe_command(vector vline, struct vty * vty, int *status)
-{
- vector ret;
-
- if (cmd_try_do_shortcut(vty->node, vector_slot(vline, 0))) {
- enum node_type onode;
- vector shifted_vline;
- unsigned int index;
-
- onode = vty->node;
- vty->node = ENABLE_NODE;
- /* We can try it on enable node, cos' the vty is authenticated */
-
- shifted_vline = vector_init(vector_count(vline));
- /* use memcpy? */
- for (index = 1; index < vector_active(vline); index++) {
- vector_set_index(shifted_vline, index - 1,
- vector_lookup(vline, index));
- }
-
- ret = cmd_describe_command_real(shifted_vline, vty, status);
-
- vector_free(shifted_vline);
- vty->node = onode;
- return ret;
- }
-
- return cmd_describe_command_real(vline, vty, status);
-}
-
-/* Check LCD of matched command. */
-static int cmd_lcd(char **matched)
-{
- int i;
- int j;
- int lcd = -1;
- char *s1, *s2;
- char c1, c2;
-
- if (matched[0] == NULL || matched[1] == NULL)
- return 0;
-
- for (i = 1; matched[i] != NULL; i++) {
- s1 = matched[i - 1];
- s2 = matched[i];
-
- for (j = 0; (c1 = s1[j]) && (c2 = s2[j]); j++)
- if (c1 != c2)
- break;
-
- if (lcd < 0)
- lcd = j;
- else {
- if (lcd > j)
- lcd = j;
- }
- }
- return lcd;
-}
-
-/* Command line completion support. */
-static char **cmd_complete_command_real(vector vline, struct vty *vty,
- int *status)
-{
- unsigned int i;
- vector cmd_vector = vector_copy(cmd_node_vector(cmdvec, vty->node));
-#define INIT_MATCHVEC_SIZE 10
- vector matchvec;
- struct cmd_element *cmd_element;
- unsigned int index;
- char **match_str;
- struct desc *desc;
- vector descvec;
- char *command;
- int lcd;
-
- if (vector_active(vline) == 0) {
- *status = CMD_ERR_NO_MATCH;
- return NULL;
- } else
- index = vector_active(vline) - 1;
-
- /* First, filter by preceeding command string */
- for (i = 0; i < index; i++)
- if ((command = vector_slot(vline, i))) {
- enum match_type match;
- int ret;
-
- /* First try completion match, if there is exactly match return 1 */
- match =
- cmd_filter_by_completion(command, cmd_vector, i);
-
- /* If there is exact match then filter ambiguous match else check
- ambiguousness. */
- if ((ret =
- is_cmd_ambiguous(command, cmd_vector, i,
- match)) == 1) {
- vector_free(cmd_vector);
- *status = CMD_ERR_AMBIGUOUS;
- return NULL;
- }
- /*
- else if (ret == 2)
- {
- vector_free (cmd_vector);
- *status = CMD_ERR_NO_MATCH;
- return NULL;
- }
- */
- }
-
- /* Prepare match vector. */
- matchvec = vector_init(INIT_MATCHVEC_SIZE);
-
- /* Now we got into completion */
- for (i = 0; i < vector_active(cmd_vector); i++)
- if ((cmd_element = vector_slot(cmd_vector, i))) {
- const char *string;
- vector strvec = cmd_element->strvec;
-
- /* Check field length */
- if (index >= vector_active(strvec))
- vector_slot(cmd_vector, i) = NULL;
- else {
- unsigned int j;
-
- descvec = vector_slot(strvec, index);
- for (j = 0; j < vector_active(descvec); j++)
- if ((desc = vector_slot(descvec, j))) {
- if ((string = cmd_entry_function(vector_slot(vline, index), desc->cmd)))
- if (cmd_unique_string (matchvec, string))
- vector_set (matchvec, talloc_strdup(tall_vty_cmd_ctx, string));
- }
- }
- }
-
- /* We don't need cmd_vector any more. */
- vector_free(cmd_vector);
-
- /* No matched command */
- if (vector_slot(matchvec, 0) == NULL) {
- vector_free(matchvec);
-
- /* In case of 'command \t' pattern. Do you need '?' command at
- the end of the line. */
- if (vector_slot(vline, index) == '\0')
- *status = CMD_ERR_NOTHING_TODO;
- else
- *status = CMD_ERR_NO_MATCH;
- return NULL;
- }
-
- /* Only one matched */
- if (vector_slot(matchvec, 1) == NULL) {
- match_str = (char **)matchvec->index;
- vector_only_wrapper_free(matchvec);
- *status = CMD_COMPLETE_FULL_MATCH;
- return match_str;
- }
- /* Make it sure last element is NULL. */
- vector_set(matchvec, NULL);
-
- /* Check LCD of matched strings. */
- if (vector_slot(vline, index) != NULL) {
- lcd = cmd_lcd((char **)matchvec->index);
-
- if (lcd) {
- int len = strlen(vector_slot(vline, index));
-
- if (len < lcd) {
- char *lcdstr;
-
- lcdstr = _talloc_zero(tall_vty_cmd_ctx, lcd + 1,
- "complete-lcdstr");
- memcpy(lcdstr, matchvec->index[0], lcd);
- lcdstr[lcd] = '\0';
-
- /* match_str = (char **) &lcdstr; */
-
- /* Free matchvec. */
- for (i = 0; i < vector_active(matchvec); i++) {
- if (vector_slot(matchvec, i))
- talloc_free(vector_slot(matchvec, i));
- }
- vector_free(matchvec);
-
- /* Make new matchvec. */
- matchvec = vector_init(INIT_MATCHVEC_SIZE);
- vector_set(matchvec, lcdstr);
- match_str = (char **)matchvec->index;
- vector_only_wrapper_free(matchvec);
-
- *status = CMD_COMPLETE_MATCH;
- return match_str;
- }
- }
- }
-
- match_str = (char **)matchvec->index;
- vector_only_wrapper_free(matchvec);
- *status = CMD_COMPLETE_LIST_MATCH;
- return match_str;
-}
-
-char **cmd_complete_command(vector vline, struct vty *vty, int *status)
-{
- char **ret;
-
- if (cmd_try_do_shortcut(vty->node, vector_slot(vline, 0))) {
- enum node_type onode;
- vector shifted_vline;
- unsigned int index;
-
- onode = vty->node;
- vty->node = ENABLE_NODE;
- /* We can try it on enable node, cos' the vty is authenticated */
-
- shifted_vline = vector_init(vector_count(vline));
- /* use memcpy? */
- for (index = 1; index < vector_active(vline); index++) {
- vector_set_index(shifted_vline, index - 1,
- vector_lookup(vline, index));
- }
-
- ret = cmd_complete_command_real(shifted_vline, vty, status);
-
- vector_free(shifted_vline);
- vty->node = onode;
- return ret;
- }
-
- return cmd_complete_command_real(vline, vty, status);
-}
-
-/* return parent node */
-/* MUST eventually converge on CONFIG_NODE */
-enum node_type vty_go_parent(struct vty *vty)
-{
- assert(vty->node > CONFIG_NODE);
-
- switch (vty->node) {
- case GSMNET_NODE:
- vty->node = CONFIG_NODE;
- vty->index = NULL;
- break;
- case BTS_NODE:
- vty->node = GSMNET_NODE;
- {
- /* set vty->index correctly ! */
- struct gsm_bts *bts = vty->index;
- vty->index = bts->network;
- }
- break;
- case TRX_NODE:
- vty->node = BTS_NODE;
- {
- /* set vty->index correctly ! */
- struct gsm_bts_trx *trx = vty->index;
- vty->index = trx->bts;
- }
- break;
- case TS_NODE:
- vty->node = TRX_NODE;
- {
- /* set vty->index correctly ! */
- struct gsm_bts_trx_ts *ts = vty->index;
- vty->index = ts->trx;
- }
- break;
- case SUBSCR_NODE:
- vty->node = VIEW_NODE;
- subscr_put(vty->index);
- vty->index = NULL;
- break;
- default:
- vty->node = CONFIG_NODE;
- }
-
- return vty->node;
-}
-
-/* Execute command by argument vline vector. */
-static int
-cmd_execute_command_real(vector vline, struct vty *vty,
- struct cmd_element **cmd)
-{
- unsigned int i;
- unsigned int index;
- vector cmd_vector;
- struct cmd_element *cmd_element;
- struct cmd_element *matched_element;
- unsigned int matched_count, incomplete_count;
- int argc;
- const char *argv[CMD_ARGC_MAX];
- enum match_type match = 0;
- int varflag;
- char *command;
-
- /* Make copy of command elements. */
- cmd_vector = vector_copy(cmd_node_vector(cmdvec, vty->node));
-
- for (index = 0; index < vector_active(vline); index++)
- if ((command = vector_slot(vline, index))) {
- int ret;
-
- match =
- cmd_filter_by_completion(command, cmd_vector,
- index);
-
- if (match == vararg_match)
- break;
-
- ret =
- is_cmd_ambiguous(command, cmd_vector, index, match);
-
- if (ret == 1) {
- vector_free(cmd_vector);
- return CMD_ERR_AMBIGUOUS;
- } else if (ret == 2) {
- vector_free(cmd_vector);
- return CMD_ERR_NO_MATCH;
- }
- }
-
- /* Check matched count. */
- matched_element = NULL;
- matched_count = 0;
- incomplete_count = 0;
-
- for (i = 0; i < vector_active(cmd_vector); i++)
- if ((cmd_element = vector_slot(cmd_vector, i))) {
- if (match == vararg_match
- || index >= cmd_element->cmdsize) {
- matched_element = cmd_element;
-#if 0
- printf("DEBUG: %s\n", cmd_element->string);
-#endif
- matched_count++;
- } else {
- incomplete_count++;
- }
- }
-
- /* Finish of using cmd_vector. */
- vector_free(cmd_vector);
-
- /* To execute command, matched_count must be 1. */
- if (matched_count == 0) {
- if (incomplete_count)
- return CMD_ERR_INCOMPLETE;
- else
- return CMD_ERR_NO_MATCH;
- }
-
- if (matched_count > 1)
- return CMD_ERR_AMBIGUOUS;
-
- /* Argument treatment */
- varflag = 0;
- argc = 0;
-
- for (i = 0; i < vector_active(vline); i++) {
- if (varflag)
- argv[argc++] = vector_slot(vline, i);
- else {
- vector descvec =
- vector_slot(matched_element->strvec, i);
-
- if (vector_active(descvec) == 1) {
- struct desc *desc = vector_slot(descvec, 0);
-
- if (CMD_VARARG(desc->cmd))
- varflag = 1;
-
- if (varflag || CMD_VARIABLE(desc->cmd)
- || CMD_OPTION(desc->cmd))
- argv[argc++] = vector_slot(vline, i);
- } else
- argv[argc++] = vector_slot(vline, i);
- }
-
- if (argc >= CMD_ARGC_MAX)
- return CMD_ERR_EXEED_ARGC_MAX;
- }
-
- /* For vtysh execution. */
- if (cmd)
- *cmd = matched_element;
-
- if (matched_element->daemon)
- return CMD_SUCCESS_DAEMON;
-
- /* Execute matched command. */
- return (*matched_element->func) (matched_element, vty, argc, argv);
-}
-
-int
-cmd_execute_command(vector vline, struct vty *vty, struct cmd_element **cmd,
- int vtysh)
-{
- int ret, saved_ret, tried = 0;
- enum node_type onode;
- void *oindex;
-
- onode = vty->node;
- oindex = vty->index;
-
- if (cmd_try_do_shortcut(vty->node, vector_slot(vline, 0))) {
- vector shifted_vline;
- unsigned int index;
-
- vty->node = ENABLE_NODE;
- /* We can try it on enable node, cos' the vty is authenticated */
-
- shifted_vline = vector_init(vector_count(vline));
- /* use memcpy? */
- for (index = 1; index < vector_active(vline); index++) {
- vector_set_index(shifted_vline, index - 1,
- vector_lookup(vline, index));
- }
-
- ret = cmd_execute_command_real(shifted_vline, vty, cmd);
-
- vector_free(shifted_vline);
- vty->node = onode;
- return ret;
- }
-
- saved_ret = ret = cmd_execute_command_real(vline, vty, cmd);
-
- if (vtysh)
- return saved_ret;
-
- /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */
- while (ret != CMD_SUCCESS && ret != CMD_WARNING
- && vty->node > CONFIG_NODE) {
- vty_go_parent(vty);
- ret = cmd_execute_command_real(vline, vty, cmd);
- tried = 1;
- if (ret == CMD_SUCCESS || ret == CMD_WARNING) {
- /* succesfull command, leave the node as is */
- return ret;
- }
- }
- /* no command succeeded, reset the vty to the original node and
- return the error for this node */
- if (tried) {
- vty->node = onode;
- vty->index = oindex;
- }
- return saved_ret;
-}
-
-/* Execute command by argument readline. */
-int
-cmd_execute_command_strict(vector vline, struct vty *vty,
- struct cmd_element **cmd)
-{
- unsigned int i;
- unsigned int index;
- vector cmd_vector;
- struct cmd_element *cmd_element;
- struct cmd_element *matched_element;
- unsigned int matched_count, incomplete_count;
- int argc;
- const char *argv[CMD_ARGC_MAX];
- int varflag;
- enum match_type match = 0;
- char *command;
-
- /* Make copy of command element */
- cmd_vector = vector_copy(cmd_node_vector(cmdvec, vty->node));
-
- for (index = 0; index < vector_active(vline); index++)
- if ((command = vector_slot(vline, index))) {
- int ret;
-
- match = cmd_filter_by_string(vector_slot(vline, index),
- cmd_vector, index);
-
- /* If command meets '.VARARG' then finish matching. */
- if (match == vararg_match)
- break;
-
- ret =
- is_cmd_ambiguous(command, cmd_vector, index, match);
- if (ret == 1) {
- vector_free(cmd_vector);
- return CMD_ERR_AMBIGUOUS;
- }
- if (ret == 2) {
- vector_free(cmd_vector);
- return CMD_ERR_NO_MATCH;
- }
- }
-
- /* Check matched count. */
- matched_element = NULL;
- matched_count = 0;
- incomplete_count = 0;
- for (i = 0; i < vector_active(cmd_vector); i++)
- if (vector_slot(cmd_vector, i) != NULL) {
- cmd_element = vector_slot(cmd_vector, i);
-
- if (match == vararg_match
- || index >= cmd_element->cmdsize) {
- matched_element = cmd_element;
- matched_count++;
- } else
- incomplete_count++;
- }
-
- /* Finish of using cmd_vector. */
- vector_free(cmd_vector);
-
- /* To execute command, matched_count must be 1. */
- if (matched_count == 0) {
- if (incomplete_count)
- return CMD_ERR_INCOMPLETE;
- else
- return CMD_ERR_NO_MATCH;
- }
-
- if (matched_count > 1)
- return CMD_ERR_AMBIGUOUS;
-
- /* Argument treatment */
- varflag = 0;
- argc = 0;
-
- for (i = 0; i < vector_active(vline); i++) {
- if (varflag)
- argv[argc++] = vector_slot(vline, i);
- else {
- vector descvec =
- vector_slot(matched_element->strvec, i);
-
- if (vector_active(descvec) == 1) {
- struct desc *desc = vector_slot(descvec, 0);
-
- if (CMD_VARARG(desc->cmd))
- varflag = 1;
-
- if (varflag || CMD_VARIABLE(desc->cmd)
- || CMD_OPTION(desc->cmd))
- argv[argc++] = vector_slot(vline, i);
- } else
- argv[argc++] = vector_slot(vline, i);
- }
-
- if (argc >= CMD_ARGC_MAX)
- return CMD_ERR_EXEED_ARGC_MAX;
- }
-
- /* For vtysh execution. */
- if (cmd)
- *cmd = matched_element;
-
- if (matched_element->daemon)
- return CMD_SUCCESS_DAEMON;
-
- /* Now execute matched command */
- return (*matched_element->func) (matched_element, vty, argc, argv);
-}
-
-/* Configration make from file. */
-int config_from_file(struct vty *vty, FILE * fp)
-{
- int ret;
- vector vline;
-
- while (fgets(vty->buf, VTY_BUFSIZ, fp)) {
- vline = cmd_make_strvec(vty->buf);
-
- /* In case of comment line */
- if (vline == NULL)
- continue;
- /* Execute configuration command : this is strict match */
- ret = cmd_execute_command_strict(vline, vty, NULL);
-
- /* Try again with setting node to CONFIG_NODE */
- while (ret != CMD_SUCCESS && ret != CMD_WARNING
- && ret != CMD_ERR_NOTHING_TODO
- && vty->node != CONFIG_NODE) {
- vty_go_parent(vty);
- ret = cmd_execute_command_strict(vline, vty, NULL);
- }
-
- cmd_free_strvec(vline);
-
- if (ret != CMD_SUCCESS && ret != CMD_WARNING
- && ret != CMD_ERR_NOTHING_TODO)
- return ret;
- }
- return CMD_SUCCESS;
-}
-
-/* Configration from terminal */
-DEFUN(config_terminal,
- config_terminal_cmd,
- "configure terminal",
- "Configuration from vty interface\n" "Configuration terminal\n")
-{
- if (vty_config_lock(vty))
- vty->node = CONFIG_NODE;
- else {
- vty_out(vty, "VTY configuration is locked by other VTY%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- return CMD_SUCCESS;
-}
-
-/* Enable command */
-DEFUN(enable, config_enable_cmd, "enable", "Turn on privileged mode command\n")
-{
- /* If enable password is NULL, change to ENABLE_NODE */
- if ((host.enable == NULL && host.enable_encrypt == NULL) ||
- vty->type == VTY_SHELL_SERV)
- vty->node = ENABLE_NODE;
- else
- vty->node = AUTH_ENABLE_NODE;
-
- return CMD_SUCCESS;
-}
-
-/* Disable command */
-DEFUN(disable,
- config_disable_cmd, "disable", "Turn off privileged mode command\n")
-{
- if (vty->node == ENABLE_NODE)
- vty->node = VIEW_NODE;
- return CMD_SUCCESS;
-}
-
-/* Down vty node level. */
-gDEFUN(config_exit,
- config_exit_cmd, "exit", "Exit current mode and down to previous mode\n")
-{
- switch (vty->node) {
- case GSMNET_NODE:
- vty->node = CONFIG_NODE;
- vty->index = NULL;
- break;
- case BTS_NODE:
- vty->node = GSMNET_NODE;
- {
- /* set vty->index correctly ! */
- struct gsm_bts *bts = vty->index;
- vty->index = bts->network;
- }
- break;
- case TRX_NODE:
- vty->node = BTS_NODE;
- {
- /* set vty->index correctly ! */
- struct gsm_bts_trx *trx = vty->index;
- vty->index = trx->bts;
- }
- break;
- case TS_NODE:
- vty->node = TRX_NODE;
- {
- /* set vty->index correctly ! */
- struct gsm_bts_trx_ts *ts = vty->index;
- vty->index = ts->trx;
- }
- break;
- case SUBSCR_NODE:
- vty->node = VIEW_NODE;
- subscr_put(vty->index);
- vty->index = NULL;
- break;
- case VIEW_NODE:
- case ENABLE_NODE:
- if (0) //vty_shell (vty))
- exit(0);
- else
- vty->status = VTY_CLOSE;
- break;
- case CONFIG_NODE:
- vty->node = ENABLE_NODE;
- vty_config_unlock(vty);
- break;
- case VTY_NODE:
- vty->node = CONFIG_NODE;
- break;
- case MGCP_NODE:
- case GBPROXY_NODE:
- case SGSN_NODE:
- case NS_NODE:
- vty->node = CONFIG_NODE;
- vty->index = NULL;
- default:
- break;
- }
- return CMD_SUCCESS;
-}
-
-/* quit is alias of exit. */
-gALIAS(config_exit,
- config_quit_cmd, "quit", "Exit current mode and down to previous mode\n")
-
-/* End of configuration. */
- gDEFUN(config_end,
- config_end_cmd, "end", "End current mode and change to enable mode.")
-{
- switch (vty->node) {
- case VIEW_NODE:
- case ENABLE_NODE:
- /* Nothing to do. */
- break;
- case CONFIG_NODE:
- case VTY_NODE:
- vty_config_unlock(vty);
- vty->node = ENABLE_NODE;
- break;
- default:
- break;
- }
- return CMD_SUCCESS;
-}
-
-/* Show version. */
-DEFUN(show_version,
- show_version_cmd, "show version", SHOW_STR "Displays program version\n")
-{
- vty_out(vty, "%s %s (%s).%s", QUAGGA_PROGNAME, QUAGGA_VERSION,
- host.name ? host.name : "", VTY_NEWLINE);
- vty_out(vty, "%s%s", QUAGGA_COPYRIGHT, VTY_NEWLINE);
-
- return CMD_SUCCESS;
-}
-
-/* Help display function for all node. */
-gDEFUN(config_help,
- config_help_cmd, "help", "Description of the interactive help system\n")
-{
- vty_out(vty,
- "This VTY provides advanced help features. When you need help,%s\
-anytime at the command line please press '?'.%s\
-%s\
-If nothing matches, the help list will be empty and you must backup%s\
- until entering a '?' shows the available options.%s\
-Two styles of help are provided:%s\
-1. Full help is available when you are ready to enter a%s\
-command argument (e.g. 'show ?') and describes each possible%s\
-argument.%s\
-2. Partial help is provided when an abbreviated argument is entered%s\
- and you want to know what arguments match the input%s\
- (e.g. 'show me?'.)%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
- VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
- return CMD_SUCCESS;
-}
-
-/* Help display function for all node. */
-gDEFUN(config_list, config_list_cmd, "list", "Print command list\n")
-{
- unsigned int i;
- struct cmd_node *cnode = vector_slot(cmdvec, vty->node);
- struct cmd_element *cmd;
-
- for (i = 0; i < vector_active(cnode->cmd_vector); i++)
- if ((cmd = vector_slot(cnode->cmd_vector, i)) != NULL
- && !(cmd->attr == CMD_ATTR_DEPRECATED
- || cmd->attr == CMD_ATTR_HIDDEN))
- vty_out(vty, " %s%s", cmd->string, VTY_NEWLINE);
- return CMD_SUCCESS;
-}
-
-/* Write current configuration into file. */
-DEFUN(config_write_file,
- config_write_file_cmd,
- "write file",
- "Write running configuration to memory, network, or terminal\n"
- "Write to configuration file\n")
-{
- unsigned int i;
- int fd;
- struct cmd_node *node;
- char *config_file;
- char *config_file_tmp = NULL;
- char *config_file_sav = NULL;
- struct vty *file_vty;
-
- /* Check and see if we are operating under vtysh configuration */
- if (host.config == NULL) {
- vty_out(vty, "Can't save to configuration file, using vtysh.%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- /* Get filename. */
- config_file = host.config;
-
- config_file_sav =
- _talloc_zero(tall_vty_cmd_ctx,
- strlen(config_file) + strlen(CONF_BACKUP_EXT) + 1,
- "config_file_sav");
- strcpy(config_file_sav, config_file);
- strcat(config_file_sav, CONF_BACKUP_EXT);
-
- config_file_tmp = _talloc_zero(tall_vty_cmd_ctx, strlen(config_file) + 8,
- "config_file_tmp");
- sprintf(config_file_tmp, "%s.XXXXXX", config_file);
-
- /* Open file to configuration write. */
- fd = mkstemp(config_file_tmp);
- if (fd < 0) {
- vty_out(vty, "Can't open configuration file %s.%s",
- config_file_tmp, VTY_NEWLINE);
- talloc_free(config_file_tmp);
- talloc_free(config_file_sav);
- return CMD_WARNING;
- }
-
- /* Make vty for configuration file. */
- file_vty = vty_new();
- file_vty->fd = fd;
- file_vty->type = VTY_FILE;
-
- /* Config file header print. */
- vty_out(file_vty, "!\n! OpenBSC configuration saved from vty\n! ");
- //vty_time_print (file_vty, 1);
- vty_out(file_vty, "!\n");
-
- for (i = 0; i < vector_active(cmdvec); i++)
- if ((node = vector_slot(cmdvec, i)) && node->func) {
- if ((*node->func) (file_vty))
- vty_out(file_vty, "!\n");
- }
- vty_close(file_vty);
-
- if (unlink(config_file_sav) != 0)
- if (errno != ENOENT) {
- vty_out(vty,
- "Can't unlink backup configuration file %s.%s",
- config_file_sav, VTY_NEWLINE);
- talloc_free(config_file_sav);
- talloc_free(config_file_tmp);
- unlink(config_file_tmp);
- return CMD_WARNING;
- }
- if (link(config_file, config_file_sav) != 0) {
- vty_out(vty, "Can't backup old configuration file %s.%s",
- config_file_sav, VTY_NEWLINE);
- talloc_free(config_file_sav);
- talloc_free(config_file_tmp);
- unlink(config_file_tmp);
- return CMD_WARNING;
- }
- sync();
- if (unlink(config_file) != 0) {
- vty_out(vty, "Can't unlink configuration file %s.%s",
- config_file, VTY_NEWLINE);
- talloc_free(config_file_sav);
- talloc_free(config_file_tmp);
- unlink(config_file_tmp);
- return CMD_WARNING;
- }
- if (link(config_file_tmp, config_file) != 0) {
- vty_out(vty, "Can't save configuration file %s.%s", config_file,
- VTY_NEWLINE);
- talloc_free(config_file_sav);
- talloc_free(config_file_tmp);
- unlink(config_file_tmp);
- return CMD_WARNING;
- }
- unlink(config_file_tmp);
- sync();
-
- talloc_free(config_file_sav);
- talloc_free(config_file_tmp);
-
- if (chmod(config_file, 0666 & ~CONFIGFILE_MASK) != 0) {
- vty_out(vty, "Can't chmod configuration file %s: %s (%d).%s",
- config_file, strerror(errno), errno, VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- vty_out(vty, "Configuration saved to %s%s", config_file, VTY_NEWLINE);
- return CMD_SUCCESS;
-}
-
-ALIAS(config_write_file,
- config_write_cmd,
- "write", "Write running configuration to memory, network, or terminal\n")
-
- ALIAS(config_write_file,
- config_write_memory_cmd,
- "write memory",
- "Write running configuration to memory, network, or terminal\n"
- "Write configuration to the file (same as write file)\n")
-
- ALIAS(config_write_file,
- copy_runningconfig_startupconfig_cmd,
- "copy running-config startup-config",
- "Copy configuration\n"
- "Copy running config to... \n"
- "Copy running config to startup config (same as write file)\n")
-
-/* Write current configuration into the terminal. */
- DEFUN(config_write_terminal,
- config_write_terminal_cmd,
- "write terminal",
- "Write running configuration to memory, network, or terminal\n"
- "Write to terminal\n")
-{
- unsigned int i;
- struct cmd_node *node;
-
- if (vty->type == VTY_SHELL_SERV) {
- for (i = 0; i < vector_active(cmdvec); i++)
- if ((node = vector_slot(cmdvec, i)) && node->func
- && node->vtysh) {
- if ((*node->func) (vty))
- vty_out(vty, "!%s", VTY_NEWLINE);
- }
- } else {
- vty_out(vty, "%sCurrent configuration:%s", VTY_NEWLINE,
- VTY_NEWLINE);
- vty_out(vty, "!%s", VTY_NEWLINE);
-
- for (i = 0; i < vector_active(cmdvec); i++)
- if ((node = vector_slot(cmdvec, i)) && node->func) {
- if ((*node->func) (vty))
- vty_out(vty, "!%s", VTY_NEWLINE);
- }
- vty_out(vty, "end%s", VTY_NEWLINE);
- }
- return CMD_SUCCESS;
-}
-
-/* Write current configuration into the terminal. */
-ALIAS(config_write_terminal,
- show_running_config_cmd,
- "show running-config", SHOW_STR "running configuration\n")
-
-/* Write startup configuration into the terminal. */
- DEFUN(show_startup_config,
- show_startup_config_cmd,
- "show startup-config", SHOW_STR "Contentes of startup configuration\n")
-{
- char buf[BUFSIZ];
- FILE *confp;
-
- confp = fopen(host.config, "r");
- if (confp == NULL) {
- vty_out(vty, "Can't open configuration file [%s]%s",
- host.config, VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- while (fgets(buf, BUFSIZ, confp)) {
- char *cp = buf;
-
- while (*cp != '\r' && *cp != '\n' && *cp != '\0')
- cp++;
- *cp = '\0';
-
- vty_out(vty, "%s%s", buf, VTY_NEWLINE);
- }
-
- fclose(confp);
-
- return CMD_SUCCESS;
-}
-
-/* Hostname configuration */
-DEFUN(config_hostname,
- hostname_cmd,
- "hostname WORD",
- "Set system's network name\n" "This system's network name\n")
-{
- if (!isalpha((int)*argv[0])) {
- vty_out(vty, "Please specify string starting with alphabet%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- if (host.name)
- talloc_free(host.name);
-
- host.name = talloc_strdup(tall_vty_cmd_ctx, argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(config_no_hostname,
- no_hostname_cmd,
- "no hostname [HOSTNAME]",
- NO_STR "Reset system's network name\n" "Host name of this router\n")
-{
- if (host.name)
- talloc_free(host.name);
- host.name = NULL;
- return CMD_SUCCESS;
-}
-
-/* VTY interface password set. */
-DEFUN(config_password, password_cmd,
- "password (8|) WORD",
- "Assign the terminal connection password\n"
- "Specifies a HIDDEN password will follow\n"
- "dummy string \n" "The HIDDEN line password string\n")
-{
- /* Argument check. */
- if (argc == 0) {
- vty_out(vty, "Please specify password.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- if (argc == 2) {
- if (*argv[0] == '8') {
- if (host.password)
- talloc_free(host.password);
- host.password = NULL;
- if (host.password_encrypt)
- talloc_free(host.password_encrypt);
- host.password_encrypt = talloc_strdup(tall_vty_cmd_ctx, argv[1]);
- return CMD_SUCCESS;
- } else {
- vty_out(vty, "Unknown encryption type.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- }
-
- if (!isalnum((int)*argv[0])) {
- vty_out(vty,
- "Please specify string starting with alphanumeric%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- if (host.password)
- talloc_free(host.password);
- host.password = NULL;
-
-#ifdef VTY_CRYPT_PW
- if (host.encrypt) {
- if (host.password_encrypt)
- talloc_free(host.password_encrypt);
- host.password_encrypt = talloc_strdup(tall_vty_cmd_ctx, zencrypt(argv[0]));
- } else
-#endif
- host.password = talloc_strdup(tall_vty_cmd_ctx, argv[0]);
-
- return CMD_SUCCESS;
-}
-
-ALIAS(config_password, password_text_cmd,
- "password LINE",
- "Assign the terminal connection password\n"
- "The UNENCRYPTED (cleartext) line password\n")
-
-/* VTY enable password set. */
- DEFUN(config_enable_password, enable_password_cmd,
- "enable password (8|) WORD",
- "Modify enable password parameters\n"
- "Assign the privileged level password\n"
- "Specifies a HIDDEN password will follow\n"
- "dummy string \n" "The HIDDEN 'enable' password string\n")
-{
- /* Argument check. */
- if (argc == 0) {
- vty_out(vty, "Please specify password.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- /* Crypt type is specified. */
- if (argc == 2) {
- if (*argv[0] == '8') {
- if (host.enable)
- talloc_free(host.enable);
- host.enable = NULL;
-
- if (host.enable_encrypt)
- talloc_free(host.enable_encrypt);
- host.enable_encrypt = talloc_strdup(tall_vty_cmd_ctx, argv[1]);
-
- return CMD_SUCCESS;
- } else {
- vty_out(vty, "Unknown encryption type.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- }
-
- if (!isalnum((int)*argv[0])) {
- vty_out(vty,
- "Please specify string starting with alphanumeric%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- if (host.enable)
- talloc_free(host.enable);
- host.enable = NULL;
-
- /* Plain password input. */
-#ifdef VTY_CRYPT_PW
- if (host.encrypt) {
- if (host.enable_encrypt)
- talloc_free(host.enable_encrypt);
- host.enable_encrypt = talloc_strdup(tall_vty_cmd_ctx, zencrypt(argv[0]));
- } else
-#endif
- host.enable = talloc_strdup(tall_vty_cmd_ctx, argv[0]);
-
- return CMD_SUCCESS;
-}
-
-ALIAS(config_enable_password,
- enable_password_text_cmd,
- "enable password LINE",
- "Modify enable password parameters\n"
- "Assign the privileged level password\n"
- "The UNENCRYPTED (cleartext) 'enable' password\n")
-
-/* VTY enable password delete. */
- DEFUN(no_config_enable_password, no_enable_password_cmd,
- "no enable password",
- NO_STR
- "Modify enable password parameters\n"
- "Assign the privileged level password\n")
-{
- if (host.enable)
- talloc_free(host.enable);
- host.enable = NULL;
-
- if (host.enable_encrypt)
- talloc_free(host.enable_encrypt);
- host.enable_encrypt = NULL;
-
- return CMD_SUCCESS;
-}
-
-#ifdef VTY_CRYPT_PW
-DEFUN(service_password_encrypt,
- service_password_encrypt_cmd,
- "service password-encryption",
- "Set up miscellaneous service\n" "Enable encrypted passwords\n")
-{
- if (host.encrypt)
- return CMD_SUCCESS;
-
- host.encrypt = 1;
-
- if (host.password) {
- if (host.password_encrypt)
- talloc_free(host.password_encrypt);
- host.password_encrypt = talloc_strdup(tall_vty_cmd_ctx, zencrypt(host.password));
- }
- if (host.enable) {
- if (host.enable_encrypt)
- talloc_free(host.enable_encrypt);
- host.enable_encrypt = talloc_strdup(tall_vty_cmd_ctx, zencrypt(host.enable));
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN(no_service_password_encrypt,
- no_service_password_encrypt_cmd,
- "no service password-encryption",
- NO_STR "Set up miscellaneous service\n" "Enable encrypted passwords\n")
-{
- if (!host.encrypt)
- return CMD_SUCCESS;
-
- host.encrypt = 0;
-
- if (host.password_encrypt)
- talloc_free(host.password_encrypt);
- host.password_encrypt = NULL;
-
- if (host.enable_encrypt)
- talloc_free(host.enable_encrypt);
- host.enable_encrypt = NULL;
-
- return CMD_SUCCESS;
-}
-#endif
-
-DEFUN(config_terminal_length, config_terminal_length_cmd,
- "terminal length <0-512>",
- "Set terminal line parameters\n"
- "Set number of lines on a screen\n"
- "Number of lines on screen (0 for no pausing)\n")
-{
- int lines;
- char *endptr = NULL;
-
- lines = strtol(argv[0], &endptr, 10);
- if (lines < 0 || lines > 512 || *endptr != '\0') {
- vty_out(vty, "length is malformed%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- vty->lines = lines;
-
- return CMD_SUCCESS;
-}
-
-DEFUN(config_terminal_no_length, config_terminal_no_length_cmd,
- "terminal no length",
- "Set terminal line parameters\n"
- NO_STR "Set number of lines on a screen\n")
-{
- vty->lines = -1;
- return CMD_SUCCESS;
-}
-
-DEFUN(service_terminal_length, service_terminal_length_cmd,
- "service terminal-length <0-512>",
- "Set up miscellaneous service\n"
- "System wide terminal length configuration\n"
- "Number of lines of VTY (0 means no line control)\n")
-{
- int lines;
- char *endptr = NULL;
-
- lines = strtol(argv[0], &endptr, 10);
- if (lines < 0 || lines > 512 || *endptr != '\0') {
- vty_out(vty, "length is malformed%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- host.lines = lines;
-
- return CMD_SUCCESS;
-}
-
-DEFUN(no_service_terminal_length, no_service_terminal_length_cmd,
- "no service terminal-length [<0-512>]",
- NO_STR
- "Set up miscellaneous service\n"
- "System wide terminal length configuration\n"
- "Number of lines of VTY (0 means no line control)\n")
-{
- host.lines = -1;
- return CMD_SUCCESS;
-}
-
-DEFUN_HIDDEN(do_echo,
- echo_cmd,
- "echo .MESSAGE",
- "Echo a message back to the vty\n" "The message to echo\n")
-{
- char *message;
-
- vty_out(vty, "%s%s",
- ((message =
- argv_concat(argv, argc, 0)) ? message : ""), VTY_NEWLINE);
- if (message)
- talloc_free(message);
- return CMD_SUCCESS;
-}
-
-#if 0
-DEFUN(config_logmsg,
- config_logmsg_cmd,
- "logmsg " LOG_LEVELS " .MESSAGE",
- "Send a message to enabled logging destinations\n"
- LOG_LEVEL_DESC "The message to send\n")
-{
- int level;
- char *message;
-
- if ((level = level_match(argv[0])) == ZLOG_DISABLED)
- return CMD_ERR_NO_MATCH;
-
- zlog(NULL, level,
- ((message = argv_concat(argv, argc, 1)) ? message : ""));
- if (message)
- talloc_free(message);
- return CMD_SUCCESS;
-}
-
-DEFUN(show_logging,
- show_logging_cmd,
- "show logging", SHOW_STR "Show current logging configuration\n")
-{
- struct zlog *zl = zlog_default;
-
- vty_out(vty, "Syslog logging: ");
- if (zl->maxlvl[ZLOG_DEST_SYSLOG] == ZLOG_DISABLED)
- vty_out(vty, "disabled");
- else
- vty_out(vty, "level %s, facility %s, ident %s",
- zlog_priority[zl->maxlvl[ZLOG_DEST_SYSLOG]],
- facility_name(zl->facility), zl->ident);
- vty_out(vty, "%s", VTY_NEWLINE);
-
- vty_out(vty, "Stdout logging: ");
- if (zl->maxlvl[ZLOG_DEST_STDOUT] == ZLOG_DISABLED)
- vty_out(vty, "disabled");
- else
- vty_out(vty, "level %s",
- zlog_priority[zl->maxlvl[ZLOG_DEST_STDOUT]]);
- vty_out(vty, "%s", VTY_NEWLINE);
-
- vty_out(vty, "Monitor logging: ");
- if (zl->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED)
- vty_out(vty, "disabled");
- else
- vty_out(vty, "level %s",
- zlog_priority[zl->maxlvl[ZLOG_DEST_MONITOR]]);
- vty_out(vty, "%s", VTY_NEWLINE);
-
- vty_out(vty, "File logging: ");
- if ((zl->maxlvl[ZLOG_DEST_FILE] == ZLOG_DISABLED) || !zl->fp)
- vty_out(vty, "disabled");
- else
- vty_out(vty, "level %s, filename %s",
- zlog_priority[zl->maxlvl[ZLOG_DEST_FILE]],
- zl->filename);
- vty_out(vty, "%s", VTY_NEWLINE);
-
- vty_out(vty, "Protocol name: %s%s",
- zlog_proto_names[zl->protocol], VTY_NEWLINE);
- vty_out(vty, "Record priority: %s%s",
- (zl->record_priority ? "enabled" : "disabled"), VTY_NEWLINE);
-
- return CMD_SUCCESS;
-}
-
-DEFUN(config_log_stdout,
- config_log_stdout_cmd,
- "log stdout", "Logging control\n" "Set stdout logging level\n")
-{
- zlog_set_level(NULL, ZLOG_DEST_STDOUT, zlog_default->default_lvl);
- return CMD_SUCCESS;
-}
-
-DEFUN(config_log_stdout_level,
- config_log_stdout_level_cmd,
- "log stdout " LOG_LEVELS,
- "Logging control\n" "Set stdout logging level\n" LOG_LEVEL_DESC)
-{
- int level;
-
- if ((level = level_match(argv[0])) == ZLOG_DISABLED)
- return CMD_ERR_NO_MATCH;
- zlog_set_level(NULL, ZLOG_DEST_STDOUT, level);
- return CMD_SUCCESS;
-}
-
-DEFUN(no_config_log_stdout,
- no_config_log_stdout_cmd,
- "no log stdout [LEVEL]",
- NO_STR "Logging control\n" "Cancel logging to stdout\n" "Logging level\n")
-{
- zlog_set_level(NULL, ZLOG_DEST_STDOUT, ZLOG_DISABLED);
- return CMD_SUCCESS;
-}
-
-DEFUN(config_log_monitor,
- config_log_monitor_cmd,
- "log monitor",
- "Logging control\n" "Set terminal line (monitor) logging level\n")
-{
- zlog_set_level(NULL, ZLOG_DEST_MONITOR, zlog_default->default_lvl);
- return CMD_SUCCESS;
-}
-
-DEFUN(config_log_monitor_level,
- config_log_monitor_level_cmd,
- "log monitor " LOG_LEVELS,
- "Logging control\n"
- "Set terminal line (monitor) logging level\n" LOG_LEVEL_DESC)
-{
- int level;
-
- if ((level = level_match(argv[0])) == ZLOG_DISABLED)
- return CMD_ERR_NO_MATCH;
- zlog_set_level(NULL, ZLOG_DEST_MONITOR, level);
- return CMD_SUCCESS;
-}
-
-DEFUN(no_config_log_monitor,
- no_config_log_monitor_cmd,
- "no log monitor [LEVEL]",
- NO_STR
- "Logging control\n"
- "Disable terminal line (monitor) logging\n" "Logging level\n")
-{
- zlog_set_level(NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED);
- return CMD_SUCCESS;
-}
-
-static int set_log_file(struct vty *vty, const char *fname, int loglevel)
-{
- int ret;
- char *p = NULL;
- const char *fullpath;
-
- /* Path detection. */
- if (!IS_DIRECTORY_SEP(*fname)) {
- char cwd[MAXPATHLEN + 1];
- cwd[MAXPATHLEN] = '\0';
-
- if (getcwd(cwd, MAXPATHLEN) == NULL) {
- zlog_err("config_log_file: Unable to alloc mem!");
- return CMD_WARNING;
- }
-
- if ((p = _talloc_zero(tall_vcmd_ctx,
- strlen(cwd) + strlen(fname) + 2),
- "set_log_file")
- == NULL) {
- zlog_err("config_log_file: Unable to alloc mem!");
- return CMD_WARNING;
- }
- sprintf(p, "%s/%s", cwd, fname);
- fullpath = p;
- } else
- fullpath = fname;
-
- ret = zlog_set_file(NULL, fullpath, loglevel);
-
- if (p)
- talloc_free(p);
-
- if (!ret) {
- vty_out(vty, "can't open logfile %s\n", fname);
- return CMD_WARNING;
- }
-
- if (host.logfile)
- talloc_free(host.logfile);
-
- host.logfile = talloc_strdup(tall_vty_cmd_ctx, fname);
-
- return CMD_SUCCESS;
-}
-
-DEFUN(config_log_file,
- config_log_file_cmd,
- "log file FILENAME",
- "Logging control\n" "Logging to file\n" "Logging filename\n")
-{
- return set_log_file(vty, argv[0], zlog_default->default_lvl);
-}
-
-DEFUN(config_log_file_level,
- config_log_file_level_cmd,
- "log file FILENAME " LOG_LEVELS,
- "Logging control\n"
- "Logging to file\n" "Logging filename\n" LOG_LEVEL_DESC)
-{
- int level;
-
- if ((level = level_match(argv[1])) == ZLOG_DISABLED)
- return CMD_ERR_NO_MATCH;
- return set_log_file(vty, argv[0], level);
-}
-
-DEFUN(no_config_log_file,
- no_config_log_file_cmd,
- "no log file [FILENAME]",
- NO_STR
- "Logging control\n" "Cancel logging to file\n" "Logging file name\n")
-{
- zlog_reset_file(NULL);
-
- if (host.logfile)
- talloc_free(host.logfile);
-
- host.logfile = NULL;
-
- return CMD_SUCCESS;
-}
-
-ALIAS(no_config_log_file,
- no_config_log_file_level_cmd,
- "no log file FILENAME LEVEL",
- NO_STR
- "Logging control\n"
- "Cancel logging to file\n" "Logging file name\n" "Logging level\n")
-
- DEFUN(config_log_syslog,
- config_log_syslog_cmd,
- "log syslog", "Logging control\n" "Set syslog logging level\n")
-{
- zlog_set_level(NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
- return CMD_SUCCESS;
-}
-
-DEFUN(config_log_syslog_level,
- config_log_syslog_level_cmd,
- "log syslog " LOG_LEVELS,
- "Logging control\n" "Set syslog logging level\n" LOG_LEVEL_DESC)
-{
- int level;
-
- if ((level = level_match(argv[0])) == ZLOG_DISABLED)
- return CMD_ERR_NO_MATCH;
- zlog_set_level(NULL, ZLOG_DEST_SYSLOG, level);
- return CMD_SUCCESS;
-}
-
-DEFUN_DEPRECATED(config_log_syslog_facility,
- config_log_syslog_facility_cmd,
- "log syslog facility " LOG_FACILITIES,
- "Logging control\n"
- "Logging goes to syslog\n"
- "(Deprecated) Facility parameter for syslog messages\n"
- LOG_FACILITY_DESC)
-{
- int facility;
-
- if ((facility = facility_match(argv[0])) < 0)
- return CMD_ERR_NO_MATCH;
-
- zlog_set_level(NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
- zlog_default->facility = facility;
- return CMD_SUCCESS;
-}
-
-DEFUN(no_config_log_syslog,
- no_config_log_syslog_cmd,
- "no log syslog [LEVEL]",
- NO_STR "Logging control\n" "Cancel logging to syslog\n" "Logging level\n")
-{
- zlog_set_level(NULL, ZLOG_DEST_SYSLOG, ZLOG_DISABLED);
- return CMD_SUCCESS;
-}
-
-ALIAS(no_config_log_syslog,
- no_config_log_syslog_facility_cmd,
- "no log syslog facility " LOG_FACILITIES,
- NO_STR
- "Logging control\n"
- "Logging goes to syslog\n"
- "Facility parameter for syslog messages\n" LOG_FACILITY_DESC)
-
- DEFUN(config_log_facility,
- config_log_facility_cmd,
- "log facility " LOG_FACILITIES,
- "Logging control\n"
- "Facility parameter for syslog messages\n" LOG_FACILITY_DESC)
-{
- int facility;
-
- if ((facility = facility_match(argv[0])) < 0)
- return CMD_ERR_NO_MATCH;
- zlog_default->facility = facility;
- return CMD_SUCCESS;
-}
-
-DEFUN(no_config_log_facility,
- no_config_log_facility_cmd,
- "no log facility [FACILITY]",
- NO_STR
- "Logging control\n"
- "Reset syslog facility to default (daemon)\n" "Syslog facility\n")
-{
- zlog_default->facility = LOG_DAEMON;
- return CMD_SUCCESS;
-}
-
-DEFUN_DEPRECATED(config_log_trap,
- config_log_trap_cmd,
- "log trap " LOG_LEVELS,
- "Logging control\n"
- "(Deprecated) Set logging level and default for all destinations\n"
- LOG_LEVEL_DESC)
-{
- int new_level;
- int i;
-
- if ((new_level = level_match(argv[0])) == ZLOG_DISABLED)
- return CMD_ERR_NO_MATCH;
-
- zlog_default->default_lvl = new_level;
- for (i = 0; i < ZLOG_NUM_DESTS; i++)
- if (zlog_default->maxlvl[i] != ZLOG_DISABLED)
- zlog_default->maxlvl[i] = new_level;
- return CMD_SUCCESS;
-}
-
-DEFUN_DEPRECATED(no_config_log_trap,
- no_config_log_trap_cmd,
- "no log trap [LEVEL]",
- NO_STR
- "Logging control\n"
- "Permit all logging information\n" "Logging level\n")
-{
- zlog_default->default_lvl = LOG_DEBUG;
- return CMD_SUCCESS;
-}
-
-DEFUN(config_log_record_priority,
- config_log_record_priority_cmd,
- "log record-priority",
- "Logging control\n"
- "Log the priority of the message within the message\n")
-{
- zlog_default->record_priority = 1;
- return CMD_SUCCESS;
-}
-
-DEFUN(no_config_log_record_priority,
- no_config_log_record_priority_cmd,
- "no log record-priority",
- NO_STR
- "Logging control\n"
- "Do not log the priority of the message within the message\n")
-{
- zlog_default->record_priority = 0;
- return CMD_SUCCESS;
-}
-#endif
-
-DEFUN(banner_motd_file,
- banner_motd_file_cmd,
- "banner motd file [FILE]",
- "Set banner\n" "Banner for motd\n" "Banner from a file\n" "Filename\n")
-{
- if (host.motdfile)
- talloc_free(host.motdfile);
- host.motdfile = talloc_strdup(tall_vty_cmd_ctx, argv[0]);
-
- return CMD_SUCCESS;
-}
-
-DEFUN(banner_motd_default,
- banner_motd_default_cmd,
- "banner motd default",
- "Set banner string\n" "Strings for motd\n" "Default string\n")
-{
- host.motd = default_motd;
- return CMD_SUCCESS;
-}
-
-DEFUN(no_banner_motd,
- no_banner_motd_cmd,
- "no banner motd", NO_STR "Set banner string\n" "Strings for motd\n")
-{
- host.motd = NULL;
- if (host.motdfile)
- talloc_free(host.motdfile);
- host.motdfile = NULL;
- return CMD_SUCCESS;
-}
-
-/* Set config filename. Called from vty.c */
-void host_config_set(const char *filename)
-{
- host.config = talloc_strdup(tall_vty_cmd_ctx, filename);
-}
-
-void install_default(enum node_type node)
-{
- install_element(node, &config_exit_cmd);
- install_element(node, &config_quit_cmd);
- install_element(node, &config_end_cmd);
- install_element(node, &config_help_cmd);
- install_element(node, &config_list_cmd);
-
- install_element(node, &config_write_terminal_cmd);
- install_element(node, &config_write_file_cmd);
- install_element(node, &config_write_memory_cmd);
- install_element(node, &config_write_cmd);
- install_element(node, &show_running_config_cmd);
-}
-
-/* Initialize command interface. Install basic nodes and commands. */
-void cmd_init(int terminal)
-{
- /* Allocate initial top vector of commands. */
- cmdvec = vector_init(VECTOR_MIN_SIZE);
-
- /* Default host value settings. */
- host.name = NULL;
- host.password = NULL;
- host.enable = NULL;
- host.logfile = NULL;
- host.config = NULL;
- host.lines = -1;
- host.motd = default_motd;
- host.motdfile = NULL;
-
- /* Install top nodes. */
- install_node(&view_node, NULL);
- install_node(&enable_node, NULL);
- install_node(&auth_node, NULL);
- install_node(&auth_enable_node, NULL);
- install_node(&config_node, config_write_host);
-
- /* Each node's basic commands. */
- install_element(VIEW_NODE, &show_version_cmd);
- if (terminal) {
- install_element(VIEW_NODE, &config_list_cmd);
- install_element(VIEW_NODE, &config_exit_cmd);
- install_element(VIEW_NODE, &config_quit_cmd);
- install_element(VIEW_NODE, &config_help_cmd);
- install_element(VIEW_NODE, &config_enable_cmd);
- install_element(VIEW_NODE, &config_terminal_length_cmd);
- install_element(VIEW_NODE, &config_terminal_no_length_cmd);
- install_element(VIEW_NODE, &echo_cmd);
- }
-
- if (terminal) {
- install_default(ENABLE_NODE);
- install_element(ENABLE_NODE, &config_disable_cmd);
- install_element(ENABLE_NODE, &config_terminal_cmd);
- install_element (ENABLE_NODE, ©_runningconfig_startupconfig_cmd);
- }
- install_element (ENABLE_NODE, &show_startup_config_cmd);
- install_element(ENABLE_NODE, &show_version_cmd);
-
- if (terminal) {
- install_element(ENABLE_NODE, &config_terminal_length_cmd);
- install_element(ENABLE_NODE, &config_terminal_no_length_cmd);
- install_element(ENABLE_NODE, &echo_cmd);
-
- install_default(CONFIG_NODE);
- }
-
- install_element(CONFIG_NODE, &hostname_cmd);
- install_element(CONFIG_NODE, &no_hostname_cmd);
-
- if (terminal) {
- install_element(CONFIG_NODE, &password_cmd);
- install_element(CONFIG_NODE, &password_text_cmd);
- install_element(CONFIG_NODE, &enable_password_cmd);
- install_element(CONFIG_NODE, &enable_password_text_cmd);
- install_element(CONFIG_NODE, &no_enable_password_cmd);
-
-#ifdef VTY_CRYPT_PW
- install_element(CONFIG_NODE, &service_password_encrypt_cmd);
- install_element(CONFIG_NODE, &no_service_password_encrypt_cmd);
-#endif
- install_element(CONFIG_NODE, &banner_motd_default_cmd);
- install_element(CONFIG_NODE, &banner_motd_file_cmd);
- install_element(CONFIG_NODE, &no_banner_motd_cmd);
- install_element(CONFIG_NODE, &service_terminal_length_cmd);
- install_element(CONFIG_NODE, &no_service_terminal_length_cmd);
-
- }
- srand(time(NULL));
-}
diff --git a/openbsc/src/vty/utils.c b/openbsc/src/vty/utils.c
deleted file mode 100644
index d8dfb8e..0000000
--- a/openbsc/src/vty/utils.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/* utility routines for printing common objects in the Osmocom world */
-
-/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <stdint.h>
-#include <inttypes.h>
-
-#include <osmocore/linuxlist.h>
-#include <osmocore/talloc.h>
-#include <osmocore/timer.h>
-#include <osmocore/rate_ctr.h>
-
-#include <vty/vty.h>
-
-void vty_out_rate_ctr_group(struct vty *vty, const char *prefix,
- struct rate_ctr_group *ctrg)
-{
- unsigned int i;
-
- vty_out(vty, "%s%s:%s", prefix, ctrg->desc->group_description, VTY_NEWLINE);
- for (i = 0; i < ctrg->desc->num_ctr; i++) {
- struct rate_ctr *ctr = &ctrg->ctr[i];
- vty_out(vty, " %s%s: %8" PRIu64 " "
- "(%" PRIu64 "/s %" PRIu64 "/m %" PRIu64 "/h %" PRIu64 "/d)%s",
- prefix, ctrg->desc->ctr_desc[i].description, ctr->current,
- ctr->intv[RATE_CTR_INTV_SEC].rate,
- ctr->intv[RATE_CTR_INTV_MIN].rate,
- ctr->intv[RATE_CTR_INTV_HOUR].rate,
- ctr->intv[RATE_CTR_INTV_DAY].rate,
- VTY_NEWLINE);
- };
-}
diff --git a/openbsc/src/vty/vector.c b/openbsc/src/vty/vector.c
deleted file mode 100644
index db47ae5..0000000
--- a/openbsc/src/vty/vector.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/* Generic vector interface routine
- * Copyright (C) 1997 Kunihiro Ishiguro
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <vty/vector.h>
-#include <vty/vty.h>
-#include <osmocore/talloc.h>
-#include <memory.h>
-
-void *tall_vty_vec_ctx;
-
-/* Initialize vector : allocate memory and return vector. */
-vector vector_init(unsigned int size)
-{
- vector v = talloc_zero(tall_vty_vec_ctx, struct _vector);
- if (!v)
- return NULL;
-
- /* allocate at least one slot */
- if (size == 0)
- size = 1;
-
- v->alloced = size;
- v->active = 0;
- v->index = _talloc_zero(tall_vty_vec_ctx, sizeof(void *) * size,
- "vector_init:index");
- if (!v->index) {
- talloc_free(v);
- return NULL;
- }
- return v;
-}
-
-void vector_only_wrapper_free(vector v)
-{
- talloc_free(v);
-}
-
-void vector_only_index_free(void *index)
-{
- talloc_free(index);
-}
-
-void vector_free(vector v)
-{
- talloc_free(v->index);
- talloc_free(v);
-}
-
-vector vector_copy(vector v)
-{
- unsigned int size;
- vector new = talloc_zero(tall_vty_vec_ctx, struct _vector);
- if (!new)
- return NULL;
-
- new->active = v->active;
- new->alloced = v->alloced;
-
- size = sizeof(void *) * (v->alloced);
- new->index = _talloc_zero(tall_vty_vec_ctx, size, "vector_copy:index");
- if (!new->index) {
- talloc_free(new);
- return NULL;
- }
- memcpy(new->index, v->index, size);
-
- return new;
-}
-
-/* Check assigned index, and if it runs short double index pointer */
-void vector_ensure(vector v, unsigned int num)
-{
- if (v->alloced > num)
- return;
-
- v->index = talloc_realloc_size(tall_vty_vec_ctx, v->index,
- sizeof(void *) * (v->alloced * 2));
- memset(&v->index[v->alloced], 0, sizeof(void *) * v->alloced);
- v->alloced *= 2;
-
- if (v->alloced <= num)
- vector_ensure(v, num);
-}
-
-/* This function only returns next empty slot index. It dose not mean
- the slot's index memory is assigned, please call vector_ensure()
- after calling this function. */
-int vector_empty_slot(vector v)
-{
- unsigned int i;
-
- if (v->active == 0)
- return 0;
-
- for (i = 0; i < v->active; i++)
- if (v->index[i] == 0)
- return i;
-
- return i;
-}
-
-/* Set value to the smallest empty slot. */
-int vector_set(vector v, void *val)
-{
- unsigned int i;
-
- i = vector_empty_slot(v);
- vector_ensure(v, i);
-
- v->index[i] = val;
-
- if (v->active <= i)
- v->active = i + 1;
-
- return i;
-}
-
-/* Set value to specified index slot. */
-int vector_set_index(vector v, unsigned int i, void *val)
-{
- vector_ensure(v, i);
-
- v->index[i] = val;
-
- if (v->active <= i)
- v->active = i + 1;
-
- return i;
-}
-
-/* Look up vector. */
-void *vector_lookup(vector v, unsigned int i)
-{
- if (i >= v->active)
- return NULL;
- return v->index[i];
-}
-
-/* Lookup vector, ensure it. */
-void *vector_lookup_ensure(vector v, unsigned int i)
-{
- vector_ensure(v, i);
- return v->index[i];
-}
-
-/* Unset value at specified index slot. */
-void vector_unset(vector v, unsigned int i)
-{
- if (i >= v->alloced)
- return;
-
- v->index[i] = NULL;
-
- if (i + 1 == v->active) {
- v->active--;
- while (i && v->index[--i] == NULL && v->active--) ; /* Is this ugly ? */
- }
-}
-
-/* Count the number of not emplty slot. */
-unsigned int vector_count(vector v)
-{
- unsigned int i;
- unsigned count = 0;
-
- for (i = 0; i < v->active; i++)
- if (v->index[i] != NULL)
- count++;
-
- return count;
-}
diff --git a/openbsc/src/vty/vty.c b/openbsc/src/vty/vty.c
deleted file mode 100644
index 0806856..0000000
--- a/openbsc/src/vty/vty.c
+++ /dev/null
@@ -1,1675 +0,0 @@
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <termios.h>
-
-#include <sys/utsname.h>
-#include <sys/param.h>
-
-#include <arpa/telnet.h>
-
-#include "cardshell.h"
-#include <vty/vty.h>
-#include <vty/command.h>
-#include <vty/buffer.h>
-#include <osmocore/talloc.h>
-
-/* our callback, located in telnet_interface.c */
-void vty_event(enum event event, int sock, struct vty *vty);
-
-extern struct host host;
-
-/* Vector which store each vty structure. */
-static vector vtyvec;
-
-vector Vvty_serv_thread;
-
-char *vty_cwd = NULL;
-
-/* Configure lock. */
-static int vty_config;
-
-static int no_password_check = 1;
-
-void *tall_vty_ctx;
-
-static void vty_clear_buf(struct vty *vty)
-{
- memset(vty->buf, 0, vty->max);
-}
-
-/* Allocate new vty struct. */
-struct vty *vty_new()
-{
- struct vty *new = talloc_zero(tall_vty_ctx, struct vty);
-
- if (!new)
- goto out;
-
- new->obuf = buffer_new(new, 0); /* Use default buffer size. */
- if (!new->obuf)
- goto out_new;
- new->buf = _talloc_zero(new, VTY_BUFSIZ, "vty_new->buf");
- if (!new->buf)
- goto out_obuf;
-
- new->max = VTY_BUFSIZ;
-
- return new;
-
-out_obuf:
- buffer_free(new->obuf);
-out_new:
- talloc_free(new);
- new = NULL;
-out:
- return new;
-}
-
-/* Authentication of vty */
-static void vty_auth(struct vty *vty, char *buf)
-{
- char *passwd = NULL;
- enum node_type next_node = 0;
- int fail;
- char *crypt(const char *, const char *);
-
- switch (vty->node) {
- case AUTH_NODE:
-#ifdef VTY_CRYPT_PW
- if (host.encrypt)
- passwd = host.password_encrypt;
- else
-#endif
- passwd = host.password;
- if (host.advanced)
- next_node = host.enable ? VIEW_NODE : ENABLE_NODE;
- else
- next_node = VIEW_NODE;
- break;
- case AUTH_ENABLE_NODE:
-#ifdef VTY_CRYPT_PW
- if (host.encrypt)
- passwd = host.enable_encrypt;
- else
-#endif
- passwd = host.enable;
- next_node = ENABLE_NODE;
- break;
- }
-
- if (passwd) {
-#ifdef VTY_CRYPT_PW
- if (host.encrypt)
- fail = strcmp(crypt(buf, passwd), passwd);
- else
-#endif
- fail = strcmp(buf, passwd);
- } else
- fail = 1;
-
- if (!fail) {
- vty->fail = 0;
- vty->node = next_node; /* Success ! */
- } else {
- vty->fail++;
- if (vty->fail >= 3) {
- if (vty->node == AUTH_NODE) {
- vty_out(vty,
- "%% Bad passwords, too many failures!%s",
- VTY_NEWLINE);
- vty->status = VTY_CLOSE;
- } else {
- /* AUTH_ENABLE_NODE */
- vty->fail = 0;
- vty_out(vty,
- "%% Bad enable passwords, too many failures!%s",
- VTY_NEWLINE);
- vty->node = VIEW_NODE;
- }
- }
- }
-}
-
-/* Close vty interface. */
-void vty_close(struct vty *vty)
-{
- int i;
-
- if (vty->obuf) {
- /* Flush buffer. */
- buffer_flush_all(vty->obuf, vty->fd);
-
- /* Free input buffer. */
- buffer_free(vty->obuf);
- vty->obuf = NULL;
- }
-
- /* Free command history. */
- for (i = 0; i < VTY_MAXHIST; i++)
- if (vty->hist[i])
- talloc_free(vty->hist[i]);
-
- /* Unset vector. */
- vector_unset(vtyvec, vty->fd);
-
- /* Close socket. */
- if (vty->fd > 0)
- close(vty->fd);
-
- if (vty->buf) {
- talloc_free(vty->buf);
- vty->buf = NULL;
- }
-
- /* Check configure. */
- vty_config_unlock(vty);
-
- /* VTY_CLOSED is handled by the telnet_interface */
- vty_event(VTY_CLOSED, vty->fd, vty);
-
- /* OK free vty. */
- talloc_free(vty);
-}
-
-int vty_shell(struct vty *vty)
-{
- return vty->type == VTY_SHELL ? 1 : 0;
-}
-
-
-/* VTY standard output function. */
-int vty_out(struct vty *vty, const char *format, ...)
-{
- va_list args;
- int len = 0;
- int size = 1024;
- char buf[1024];
- char *p = NULL;
-
- if (vty_shell(vty)) {
- va_start(args, format);
- vprintf(format, args);
- va_end(args);
- } else {
- /* Try to write to initial buffer. */
- va_start(args, format);
- len = vsnprintf(buf, sizeof buf, format, args);
- va_end(args);
-
- /* Initial buffer is not enough. */
- if (len < 0 || len >= size) {
- while (1) {
- if (len > -1)
- size = len + 1;
- else
- size = size * 2;
-
- p = talloc_realloc_size(vty, p, size);
- if (!p)
- return -1;
-
- va_start(args, format);
- len = vsnprintf(p, size, format, args);
- va_end(args);
-
- if (len > -1 && len < size)
- break;
- }
- }
-
- /* When initial buffer is enough to store all output. */
- if (!p)
- p = buf;
-
- /* Pointer p must point out buffer. */
- buffer_put(vty->obuf, (u_char *) p, len);
-
- /* If p is not different with buf, it is allocated buffer. */
- if (p != buf)
- talloc_free(p);
- }
-
- vty_event(VTY_WRITE, vty->fd, vty);
-
- return len;
-}
-
-int vty_out_newline(struct vty *vty)
-{
- char *p = vty_newline(vty);
- buffer_put(vty->obuf, p, strlen(p));
- return 0;
-}
-
-int vty_config_lock(struct vty *vty)
-{
- if (vty_config == 0) {
- vty->config = 1;
- vty_config = 1;
- }
- return vty->config;
-}
-
-int vty_config_unlock(struct vty *vty)
-{
- if (vty_config == 1 && vty->config == 1) {
- vty->config = 0;
- vty_config = 0;
- }
- return vty->config;
-}
-
-/* Say hello to vty interface. */
-void vty_hello(struct vty *vty)
-{
- if (host.motdfile) {
- FILE *f;
- char buf[4096];
-
- f = fopen(host.motdfile, "r");
- if (f) {
- while (fgets(buf, sizeof(buf), f)) {
- char *s;
- /* work backwards to ignore trailling isspace() */
- for (s = buf + strlen(buf);
- (s > buf) && isspace(*(s - 1)); s--) ;
- *s = '\0';
- vty_out(vty, "%s%s", buf, VTY_NEWLINE);
- }
- fclose(f);
- } else
- vty_out(vty, "MOTD file not found%s", VTY_NEWLINE);
- } else if (host.motd)
- vty_out(vty, "%s", host.motd);
-}
-
-/* Put out prompt and wait input from user. */
-static void vty_prompt(struct vty *vty)
-{
- struct utsname names;
- const char *hostname;
-
- if (vty->type == VTY_TERM) {
- hostname = host.name;
- if (!hostname) {
- uname(&names);
- hostname = names.nodename;
- }
- vty_out(vty, cmd_prompt(vty->node), hostname);
- }
-}
-
-/* Command execution over the vty interface. */
-static int vty_command(struct vty *vty, char *buf)
-{
- int ret;
- vector vline;
-
- /* Split readline string up into the vector */
- vline = cmd_make_strvec(buf);
-
- if (vline == NULL)
- return CMD_SUCCESS;
-
- ret = cmd_execute_command(vline, vty, NULL, 0);
- if (ret != CMD_SUCCESS)
- switch (ret) {
- case CMD_WARNING:
- if (vty->type == VTY_FILE)
- vty_out(vty, "Warning...%s", VTY_NEWLINE);
- break;
- case CMD_ERR_AMBIGUOUS:
- vty_out(vty, "%% Ambiguous command.%s", VTY_NEWLINE);
- break;
- case CMD_ERR_NO_MATCH:
- vty_out(vty, "%% Unknown command.%s", VTY_NEWLINE);
- break;
- case CMD_ERR_INCOMPLETE:
- vty_out(vty, "%% Command incomplete.%s", VTY_NEWLINE);
- break;
- }
- cmd_free_strvec(vline);
-
- return ret;
-}
-
-static const char telnet_backward_char = 0x08;
-static const char telnet_space_char = ' ';
-
-/* Basic function to write buffer to vty. */
-static void vty_write(struct vty *vty, const char *buf, size_t nbytes)
-{
- if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE))
- return;
-
- /* Should we do buffering here ? And make vty_flush (vty) ? */
- buffer_put(vty->obuf, buf, nbytes);
-}
-
-/* Ensure length of input buffer. Is buffer is short, double it. */
-static void vty_ensure(struct vty *vty, int length)
-{
- if (vty->max <= length) {
- vty->max *= 2;
- vty->buf = talloc_realloc_size(vty, vty->buf, vty->max);
- // FIXME: check return
- }
-}
-
-/* Basic function to insert character into vty. */
-static void vty_self_insert(struct vty *vty, char c)
-{
- int i;
- int length;
-
- vty_ensure(vty, vty->length + 1);
- length = vty->length - vty->cp;
- memmove(&vty->buf[vty->cp + 1], &vty->buf[vty->cp], length);
- vty->buf[vty->cp] = c;
-
- vty_write(vty, &vty->buf[vty->cp], length + 1);
- for (i = 0; i < length; i++)
- vty_write(vty, &telnet_backward_char, 1);
-
- vty->cp++;
- vty->length++;
-}
-
-/* Self insert character 'c' in overwrite mode. */
-static void vty_self_insert_overwrite(struct vty *vty, char c)
-{
- vty_ensure(vty, vty->length + 1);
- vty->buf[vty->cp++] = c;
-
- if (vty->cp > vty->length)
- vty->length++;
-
- if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE))
- return;
-
- vty_write(vty, &c, 1);
-}
-
-/* Insert a word into vty interface with overwrite mode. */
-static void vty_insert_word_overwrite(struct vty *vty, char *str)
-{
- int len = strlen(str);
- vty_write(vty, str, len);
- strcpy(&vty->buf[vty->cp], str);
- vty->cp += len;
- vty->length = vty->cp;
-}
-
-/* Forward character. */
-static void vty_forward_char(struct vty *vty)
-{
- if (vty->cp < vty->length) {
- vty_write(vty, &vty->buf[vty->cp], 1);
- vty->cp++;
- }
-}
-
-/* Backward character. */
-static void vty_backward_char(struct vty *vty)
-{
- if (vty->cp > 0) {
- vty->cp--;
- vty_write(vty, &telnet_backward_char, 1);
- }
-}
-
-/* Move to the beginning of the line. */
-static void vty_beginning_of_line(struct vty *vty)
-{
- while (vty->cp)
- vty_backward_char(vty);
-}
-
-/* Move to the end of the line. */
-static void vty_end_of_line(struct vty *vty)
-{
- while (vty->cp < vty->length)
- vty_forward_char(vty);
-}
-
-/* Add current command line to the history buffer. */
-static void vty_hist_add(struct vty *vty)
-{
- int index;
-
- if (vty->length == 0)
- return;
-
- index = vty->hindex ? vty->hindex - 1 : VTY_MAXHIST - 1;
-
- /* Ignore the same string as previous one. */
- if (vty->hist[index])
- if (strcmp(vty->buf, vty->hist[index]) == 0) {
- vty->hp = vty->hindex;
- return;
- }
-
- /* Insert history entry. */
- if (vty->hist[vty->hindex])
- talloc_free(vty->hist[vty->hindex]);
- vty->hist[vty->hindex] = talloc_strdup(vty, vty->buf);
-
- /* History index rotation. */
- vty->hindex++;
- if (vty->hindex == VTY_MAXHIST)
- vty->hindex = 0;
-
- vty->hp = vty->hindex;
-}
-
-/* Get telnet window size. */
-static int
-vty_telnet_option (struct vty *vty, unsigned char *buf, int nbytes)
-{
-#ifdef TELNET_OPTION_DEBUG
- int i;
-
- for (i = 0; i < nbytes; i++)
- {
- switch (buf[i])
- {
- case IAC:
- vty_out (vty, "IAC ");
- break;
- case WILL:
- vty_out (vty, "WILL ");
- break;
- case WONT:
- vty_out (vty, "WONT ");
- break;
- case DO:
- vty_out (vty, "DO ");
- break;
- case DONT:
- vty_out (vty, "DONT ");
- break;
- case SB:
- vty_out (vty, "SB ");
- break;
- case SE:
- vty_out (vty, "SE ");
- break;
- case TELOPT_ECHO:
- vty_out (vty, "TELOPT_ECHO %s", VTY_NEWLINE);
- break;
- case TELOPT_SGA:
- vty_out (vty, "TELOPT_SGA %s", VTY_NEWLINE);
- break;
- case TELOPT_NAWS:
- vty_out (vty, "TELOPT_NAWS %s", VTY_NEWLINE);
- break;
- default:
- vty_out (vty, "%x ", buf[i]);
- break;
- }
- }
- vty_out (vty, "%s", VTY_NEWLINE);
-
-#endif /* TELNET_OPTION_DEBUG */
-
- switch (buf[0])
- {
- case SB:
- vty->sb_len = 0;
- vty->iac_sb_in_progress = 1;
- return 0;
- break;
- case SE:
- {
- if (!vty->iac_sb_in_progress)
- return 0;
-
- if ((vty->sb_len == 0) || (vty->sb_buf[0] == '\0'))
- {
- vty->iac_sb_in_progress = 0;
- return 0;
- }
- switch (vty->sb_buf[0])
- {
- case TELOPT_NAWS:
- if (vty->sb_len != TELNET_NAWS_SB_LEN)
- vty_out(vty,"RFC 1073 violation detected: telnet NAWS option "
- "should send %d characters, but we received %lu",
- TELNET_NAWS_SB_LEN, (u_long)vty->sb_len);
- else if (sizeof(vty->sb_buf) < TELNET_NAWS_SB_LEN)
- vty_out(vty, "Bug detected: sizeof(vty->sb_buf) %lu < %d, "
- "too small to handle the telnet NAWS option",
- (u_long)sizeof(vty->sb_buf), TELNET_NAWS_SB_LEN);
- else
- {
- vty->width = ((vty->sb_buf[1] << 8)|vty->sb_buf[2]);
- vty->height = ((vty->sb_buf[3] << 8)|vty->sb_buf[4]);
-#ifdef TELNET_OPTION_DEBUG
- vty_out(vty, "TELNET NAWS window size negotiation completed: "
- "width %d, height %d%s",
- vty->width, vty->height, VTY_NEWLINE);
-#endif
- }
- break;
- }
- vty->iac_sb_in_progress = 0;
- return 0;
- break;
- }
- default:
- break;
- }
- return 1;
-}
-
-/* Execute current command line. */
-static int vty_execute(struct vty *vty)
-{
- int ret;
-
- ret = CMD_SUCCESS;
-
- switch (vty->node) {
- case AUTH_NODE:
- case AUTH_ENABLE_NODE:
- vty_auth(vty, vty->buf);
- break;
- default:
- ret = vty_command(vty, vty->buf);
- if (vty->type == VTY_TERM)
- vty_hist_add(vty);
- break;
- }
-
- /* Clear command line buffer. */
- vty->cp = vty->length = 0;
- vty_clear_buf(vty);
-
- if (vty->status != VTY_CLOSE)
- vty_prompt(vty);
-
- return ret;
-}
-
-/* Send WILL TELOPT_ECHO to remote server. */
-static void
-vty_will_echo (struct vty *vty)
-{
- unsigned char cmd[] = { IAC, WILL, TELOPT_ECHO, '\0' };
- vty_out (vty, "%s", cmd);
-}
-
-/* Make suppress Go-Ahead telnet option. */
-static void
-vty_will_suppress_go_ahead (struct vty *vty)
-{
- unsigned char cmd[] = { IAC, WILL, TELOPT_SGA, '\0' };
- vty_out (vty, "%s", cmd);
-}
-
-/* Make don't use linemode over telnet. */
-static void
-vty_dont_linemode (struct vty *vty)
-{
- unsigned char cmd[] = { IAC, DONT, TELOPT_LINEMODE, '\0' };
- vty_out (vty, "%s", cmd);
-}
-
-/* Use window size. */
-static void
-vty_do_window_size (struct vty *vty)
-{
- unsigned char cmd[] = { IAC, DO, TELOPT_NAWS, '\0' };
- vty_out (vty, "%s", cmd);
-}
-
-static void vty_kill_line_from_beginning(struct vty *);
-static void vty_redraw_line(struct vty *);
-
-/* Print command line history. This function is called from
- vty_next_line and vty_previous_line. */
-static void vty_history_print(struct vty *vty)
-{
- int length;
-
- vty_kill_line_from_beginning(vty);
-
- /* Get previous line from history buffer */
- length = strlen(vty->hist[vty->hp]);
- memcpy(vty->buf, vty->hist[vty->hp], length);
- vty->cp = vty->length = length;
-
- /* Redraw current line */
- vty_redraw_line(vty);
-}
-
-/* Show next command line history. */
-static void vty_next_line(struct vty *vty)
-{
- int try_index;
-
- if (vty->hp == vty->hindex)
- return;
-
- /* Try is there history exist or not. */
- try_index = vty->hp;
- if (try_index == (VTY_MAXHIST - 1))
- try_index = 0;
- else
- try_index++;
-
- /* If there is not history return. */
- if (vty->hist[try_index] == NULL)
- return;
- else
- vty->hp = try_index;
-
- vty_history_print(vty);
-}
-
-/* Show previous command line history. */
-static void vty_previous_line(struct vty *vty)
-{
- int try_index;
-
- try_index = vty->hp;
- if (try_index == 0)
- try_index = VTY_MAXHIST - 1;
- else
- try_index--;
-
- if (vty->hist[try_index] == NULL)
- return;
- else
- vty->hp = try_index;
-
- vty_history_print(vty);
-}
-
-/* This function redraw all of the command line character. */
-static void vty_redraw_line(struct vty *vty)
-{
- vty_write(vty, vty->buf, vty->length);
- vty->cp = vty->length;
-}
-
-/* Forward word. */
-static void vty_forward_word(struct vty *vty)
-{
- while (vty->cp != vty->length && vty->buf[vty->cp] != ' ')
- vty_forward_char(vty);
-
- while (vty->cp != vty->length && vty->buf[vty->cp] == ' ')
- vty_forward_char(vty);
-}
-
-/* Backward word without skipping training space. */
-static void vty_backward_pure_word(struct vty *vty)
-{
- while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ')
- vty_backward_char(vty);
-}
-
-/* Backward word. */
-static void vty_backward_word(struct vty *vty)
-{
- while (vty->cp > 0 && vty->buf[vty->cp - 1] == ' ')
- vty_backward_char(vty);
-
- while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ')
- vty_backward_char(vty);
-}
-
-/* When '^D' is typed at the beginning of the line we move to the down
- level. */
-static void vty_down_level(struct vty *vty)
-{
- vty_out(vty, "%s", VTY_NEWLINE);
- (*config_exit_cmd.func) (NULL, vty, 0, NULL);
- vty_prompt(vty);
- vty->cp = 0;
-}
-
-/* When '^Z' is received from vty, move down to the enable mode. */
-static void vty_end_config(struct vty *vty)
-{
- vty_out(vty, "%s", VTY_NEWLINE);
-
- switch (vty->node) {
- case VIEW_NODE:
- case ENABLE_NODE:
- /* Nothing to do. */
- break;
- case CONFIG_NODE:
- case VTY_NODE:
- vty_config_unlock(vty);
- vty->node = ENABLE_NODE;
- break;
- default:
- /* Unknown node, we have to ignore it. */
- break;
- }
-
- vty_prompt(vty);
- vty->cp = 0;
-}
-
-/* Delete a charcter at the current point. */
-static void vty_delete_char(struct vty *vty)
-{
- int i;
- int size;
-
- if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
- return;
-
- if (vty->length == 0) {
- vty_down_level(vty);
- return;
- }
-
- if (vty->cp == vty->length)
- return; /* completion need here? */
-
- size = vty->length - vty->cp;
-
- vty->length--;
- memmove(&vty->buf[vty->cp], &vty->buf[vty->cp + 1], size - 1);
- vty->buf[vty->length] = '\0';
-
- vty_write(vty, &vty->buf[vty->cp], size - 1);
- vty_write(vty, &telnet_space_char, 1);
-
- for (i = 0; i < size; i++)
- vty_write(vty, &telnet_backward_char, 1);
-}
-
-/* Delete a character before the point. */
-static void vty_delete_backward_char(struct vty *vty)
-{
- if (vty->cp == 0)
- return;
-
- vty_backward_char(vty);
- vty_delete_char(vty);
-}
-
-/* Kill rest of line from current point. */
-static void vty_kill_line(struct vty *vty)
-{
- int i;
- int size;
-
- size = vty->length - vty->cp;
-
- if (size == 0)
- return;
-
- for (i = 0; i < size; i++)
- vty_write(vty, &telnet_space_char, 1);
- for (i = 0; i < size; i++)
- vty_write(vty, &telnet_backward_char, 1);
-
- memset(&vty->buf[vty->cp], 0, size);
- vty->length = vty->cp;
-}
-
-/* Kill line from the beginning. */
-static void vty_kill_line_from_beginning(struct vty *vty)
-{
- vty_beginning_of_line(vty);
- vty_kill_line(vty);
-}
-
-/* Delete a word before the point. */
-static void vty_forward_kill_word(struct vty *vty)
-{
- while (vty->cp != vty->length && vty->buf[vty->cp] == ' ')
- vty_delete_char(vty);
- while (vty->cp != vty->length && vty->buf[vty->cp] != ' ')
- vty_delete_char(vty);
-}
-
-/* Delete a word before the point. */
-static void vty_backward_kill_word(struct vty *vty)
-{
- while (vty->cp > 0 && vty->buf[vty->cp - 1] == ' ')
- vty_delete_backward_char(vty);
- while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ')
- vty_delete_backward_char(vty);
-}
-
-/* Transpose chars before or at the point. */
-static void vty_transpose_chars(struct vty *vty)
-{
- char c1, c2;
-
- /* If length is short or point is near by the beginning of line then
- return. */
- if (vty->length < 2 || vty->cp < 1)
- return;
-
- /* In case of point is located at the end of the line. */
- if (vty->cp == vty->length) {
- c1 = vty->buf[vty->cp - 1];
- c2 = vty->buf[vty->cp - 2];
-
- vty_backward_char(vty);
- vty_backward_char(vty);
- vty_self_insert_overwrite(vty, c1);
- vty_self_insert_overwrite(vty, c2);
- } else {
- c1 = vty->buf[vty->cp];
- c2 = vty->buf[vty->cp - 1];
-
- vty_backward_char(vty);
- vty_self_insert_overwrite(vty, c1);
- vty_self_insert_overwrite(vty, c2);
- }
-}
-
-/* Do completion at vty interface. */
-static void vty_complete_command(struct vty *vty)
-{
- int i;
- int ret;
- char **matched = NULL;
- vector vline;
-
- if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
- return;
-
- vline = cmd_make_strvec(vty->buf);
- if (vline == NULL)
- return;
-
- /* In case of 'help \t'. */
- if (isspace((int)vty->buf[vty->length - 1]))
- vector_set(vline, '\0');
-
- matched = cmd_complete_command(vline, vty, &ret);
-
- cmd_free_strvec(vline);
-
- vty_out(vty, "%s", VTY_NEWLINE);
- switch (ret) {
- case CMD_ERR_AMBIGUOUS:
- vty_out(vty, "%% Ambiguous command.%s", VTY_NEWLINE);
- vty_prompt(vty);
- vty_redraw_line(vty);
- break;
- case CMD_ERR_NO_MATCH:
- /* vty_out (vty, "%% There is no matched command.%s", VTY_NEWLINE); */
- vty_prompt(vty);
- vty_redraw_line(vty);
- break;
- case CMD_COMPLETE_FULL_MATCH:
- vty_prompt(vty);
- vty_redraw_line(vty);
- vty_backward_pure_word(vty);
- vty_insert_word_overwrite(vty, matched[0]);
- vty_self_insert(vty, ' ');
- talloc_free(matched[0]);
- break;
- case CMD_COMPLETE_MATCH:
- vty_prompt(vty);
- vty_redraw_line(vty);
- vty_backward_pure_word(vty);
- vty_insert_word_overwrite(vty, matched[0]);
- talloc_free(matched[0]);
- break;
- case CMD_COMPLETE_LIST_MATCH:
- for (i = 0; matched[i] != NULL; i++) {
- if (i != 0 && ((i % 6) == 0))
- vty_out(vty, "%s", VTY_NEWLINE);
- vty_out(vty, "%-10s ", matched[i]);
- talloc_free(matched[i]);
- }
- vty_out(vty, "%s", VTY_NEWLINE);
-
- vty_prompt(vty);
- vty_redraw_line(vty);
- break;
- case CMD_ERR_NOTHING_TODO:
- vty_prompt(vty);
- vty_redraw_line(vty);
- break;
- default:
- break;
- }
- if (matched)
- vector_only_index_free(matched);
-}
-
-static void
-vty_describe_fold(struct vty *vty, int cmd_width,
- unsigned int desc_width, struct desc *desc)
-{
- char *buf;
- const char *cmd, *p;
- int pos;
-
- cmd = desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd;
-
- if (desc_width <= 0) {
- vty_out(vty, " %-*s %s%s", cmd_width, cmd, desc->str,
- VTY_NEWLINE);
- return;
- }
-
- buf = _talloc_zero(vty, strlen(desc->str) + 1, "describe_fold");
- if (!buf)
- return;
-
- for (p = desc->str; strlen(p) > desc_width; p += pos + 1) {
- for (pos = desc_width; pos > 0; pos--)
- if (*(p + pos) == ' ')
- break;
-
- if (pos == 0)
- break;
-
- strncpy(buf, p, pos);
- buf[pos] = '\0';
- vty_out(vty, " %-*s %s%s", cmd_width, cmd, buf, VTY_NEWLINE);
-
- cmd = "";
- }
-
- vty_out(vty, " %-*s %s%s", cmd_width, cmd, p, VTY_NEWLINE);
-
- talloc_free(buf);
-}
-
-/* Describe matched command function. */
-static void vty_describe_command(struct vty *vty)
-{
- int ret;
- vector vline;
- vector describe;
- unsigned int i, width, desc_width;
- struct desc *desc, *desc_cr = NULL;
-
- vline = cmd_make_strvec(vty->buf);
-
- /* In case of '> ?'. */
- if (vline == NULL) {
- vline = vector_init(1);
- vector_set(vline, '\0');
- } else if (isspace((int)vty->buf[vty->length - 1]))
- vector_set(vline, '\0');
-
- describe = cmd_describe_command(vline, vty, &ret);
-
- vty_out(vty, "%s", VTY_NEWLINE);
-
- /* Ambiguous error. */
- switch (ret) {
- case CMD_ERR_AMBIGUOUS:
- cmd_free_strvec(vline);
- vty_out(vty, "%% Ambiguous command.%s", VTY_NEWLINE);
- vty_prompt(vty);
- vty_redraw_line(vty);
- return;
- break;
- case CMD_ERR_NO_MATCH:
- cmd_free_strvec(vline);
- vty_out(vty, "%% There is no matched command.%s", VTY_NEWLINE);
- vty_prompt(vty);
- vty_redraw_line(vty);
- return;
- break;
- }
-
- /* Get width of command string. */
- width = 0;
- for (i = 0; i < vector_active(describe); i++)
- if ((desc = vector_slot(describe, i)) != NULL) {
- unsigned int len;
-
- if (desc->cmd[0] == '\0')
- continue;
-
- len = strlen(desc->cmd);
- if (desc->cmd[0] == '.')
- len--;
-
- if (width < len)
- width = len;
- }
-
- /* Get width of description string. */
- desc_width = vty->width - (width + 6);
-
- /* Print out description. */
- for (i = 0; i < vector_active(describe); i++)
- if ((desc = vector_slot(describe, i)) != NULL) {
- if (desc->cmd[0] == '\0')
- continue;
-
- if (strcmp(desc->cmd, "<cr>") == 0) {
- desc_cr = desc;
- continue;
- }
-
- if (!desc->str)
- vty_out(vty, " %-s%s",
- desc->cmd[0] ==
- '.' ? desc->cmd + 1 : desc->cmd,
- VTY_NEWLINE);
- else if (desc_width >= strlen(desc->str))
- vty_out(vty, " %-*s %s%s", width,
- desc->cmd[0] ==
- '.' ? desc->cmd + 1 : desc->cmd,
- desc->str, VTY_NEWLINE);
- else
- vty_describe_fold(vty, width, desc_width, desc);
-
-#if 0
- vty_out(vty, " %-*s %s%s", width
- desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
- desc->str ? desc->str : "", VTY_NEWLINE);
-#endif /* 0 */
- }
-
- if ((desc = desc_cr)) {
- if (!desc->str)
- vty_out(vty, " %-s%s",
- desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
- VTY_NEWLINE);
- else if (desc_width >= strlen(desc->str))
- vty_out(vty, " %-*s %s%s", width,
- desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
- desc->str, VTY_NEWLINE);
- else
- vty_describe_fold(vty, width, desc_width, desc);
- }
-
- cmd_free_strvec(vline);
- vector_free(describe);
-
- vty_prompt(vty);
- vty_redraw_line(vty);
-}
-
-/* ^C stop current input and do not add command line to the history. */
-static void vty_stop_input(struct vty *vty)
-{
- vty->cp = vty->length = 0;
- vty_clear_buf(vty);
- vty_out(vty, "%s", VTY_NEWLINE);
-
- switch (vty->node) {
- case VIEW_NODE:
- case ENABLE_NODE:
- /* Nothing to do. */
- break;
- case CONFIG_NODE:
- case VTY_NODE:
- vty_config_unlock(vty);
- vty->node = ENABLE_NODE;
- break;
- default:
- /* Unknown node, we have to ignore it. */
- break;
- }
- vty_prompt(vty);
-
- /* Set history pointer to the latest one. */
- vty->hp = vty->hindex;
-}
-
-#define CONTROL(X) ((X) - '@')
-#define VTY_NORMAL 0
-#define VTY_PRE_ESCAPE 1
-#define VTY_ESCAPE 2
-
-/* Escape character command map. */
-static void vty_escape_map(unsigned char c, struct vty *vty)
-{
- switch (c) {
- case ('A'):
- vty_previous_line(vty);
- break;
- case ('B'):
- vty_next_line(vty);
- break;
- case ('C'):
- vty_forward_char(vty);
- break;
- case ('D'):
- vty_backward_char(vty);
- break;
- default:
- break;
- }
-
- /* Go back to normal mode. */
- vty->escape = VTY_NORMAL;
-}
-
-/* Quit print out to the buffer. */
-static void vty_buffer_reset(struct vty *vty)
-{
- buffer_reset(vty->obuf);
- vty_prompt(vty);
- vty_redraw_line(vty);
-}
-
-/* Read data via vty socket. */
-int vty_read(struct vty *vty)
-{
- int i;
- int nbytes;
- unsigned char buf[VTY_READ_BUFSIZ];
-
- int vty_sock = vty->fd;
-
- /* Read raw data from socket */
- if ((nbytes = read(vty->fd, buf, VTY_READ_BUFSIZ)) <= 0) {
- if (nbytes < 0) {
- if (ERRNO_IO_RETRY(errno)) {
- vty_event(VTY_READ, vty_sock, vty);
- return 0;
- }
- }
- buffer_reset(vty->obuf);
- vty->status = VTY_CLOSE;
- }
-
- for (i = 0; i < nbytes; i++) {
- if (buf[i] == IAC) {
- if (!vty->iac) {
- vty->iac = 1;
- continue;
- } else {
- vty->iac = 0;
- }
- }
-
- if (vty->iac_sb_in_progress && !vty->iac) {
- if (vty->sb_len < sizeof(vty->sb_buf))
- vty->sb_buf[vty->sb_len] = buf[i];
- vty->sb_len++;
- continue;
- }
-
- if (vty->iac) {
- /* In case of telnet command */
- int ret = 0;
- ret = vty_telnet_option(vty, buf + i, nbytes - i);
- vty->iac = 0;
- i += ret;
- continue;
- }
-
- if (vty->status == VTY_MORE) {
- switch (buf[i]) {
- case CONTROL('C'):
- case 'q':
- case 'Q':
- vty_buffer_reset(vty);
- break;
-#if 0 /* More line does not work for "show ip bgp". */
- case '\n':
- case '\r':
- vty->status = VTY_MORELINE;
- break;
-#endif
- default:
- break;
- }
- continue;
- }
-
- /* Escape character. */
- if (vty->escape == VTY_ESCAPE) {
- vty_escape_map(buf[i], vty);
- continue;
- }
-
- /* Pre-escape status. */
- if (vty->escape == VTY_PRE_ESCAPE) {
- switch (buf[i]) {
- case '[':
- vty->escape = VTY_ESCAPE;
- break;
- case 'b':
- vty_backward_word(vty);
- vty->escape = VTY_NORMAL;
- break;
- case 'f':
- vty_forward_word(vty);
- vty->escape = VTY_NORMAL;
- break;
- case 'd':
- vty_forward_kill_word(vty);
- vty->escape = VTY_NORMAL;
- break;
- case CONTROL('H'):
- case 0x7f:
- vty_backward_kill_word(vty);
- vty->escape = VTY_NORMAL;
- break;
- default:
- vty->escape = VTY_NORMAL;
- break;
- }
- continue;
- }
-
- switch (buf[i]) {
- case CONTROL('A'):
- vty_beginning_of_line(vty);
- break;
- case CONTROL('B'):
- vty_backward_char(vty);
- break;
- case CONTROL('C'):
- vty_stop_input(vty);
- break;
- case CONTROL('D'):
- vty_delete_char(vty);
- break;
- case CONTROL('E'):
- vty_end_of_line(vty);
- break;
- case CONTROL('F'):
- vty_forward_char(vty);
- break;
- case CONTROL('H'):
- case 0x7f:
- vty_delete_backward_char(vty);
- break;
- case CONTROL('K'):
- vty_kill_line(vty);
- break;
- case CONTROL('N'):
- vty_next_line(vty);
- break;
- case CONTROL('P'):
- vty_previous_line(vty);
- break;
- case CONTROL('T'):
- vty_transpose_chars(vty);
- break;
- case CONTROL('U'):
- vty_kill_line_from_beginning(vty);
- break;
- case CONTROL('W'):
- vty_backward_kill_word(vty);
- break;
- case CONTROL('Z'):
- vty_end_config(vty);
- break;
- case '\n':
- case '\r':
- vty_out(vty, "%s", VTY_NEWLINE);
- vty_execute(vty);
- break;
- case '\t':
- vty_complete_command(vty);
- break;
- case '?':
- if (vty->node == AUTH_NODE
- || vty->node == AUTH_ENABLE_NODE)
- vty_self_insert(vty, buf[i]);
- else
- vty_describe_command(vty);
- break;
- case '\033':
- if (i + 1 < nbytes && buf[i + 1] == '[') {
- vty->escape = VTY_ESCAPE;
- i++;
- } else
- vty->escape = VTY_PRE_ESCAPE;
- break;
- default:
- if (buf[i] > 31 && buf[i] < 127)
- vty_self_insert(vty, buf[i]);
- break;
- }
- }
-
- /* Check status. */
- if (vty->status == VTY_CLOSE)
- vty_close(vty);
- else {
- vty_event(VTY_WRITE, vty_sock, vty);
- vty_event(VTY_READ, vty_sock, vty);
- }
- return 0;
-}
-
-/* Read up configuration file */
-static int
-vty_read_file(FILE *confp)
-{
- int ret;
- struct vty *vty;
-
- vty = vty_new();
- vty->fd = 0;
- vty->type = VTY_FILE;
- vty->node = CONFIG_NODE;
-
- ret = config_from_file(vty, confp);
-
- if (ret != CMD_SUCCESS) {
- switch (ret) {
- case CMD_ERR_AMBIGUOUS:
- fprintf(stderr, "Ambiguous command.\n");
- break;
- case CMD_ERR_NO_MATCH:
- fprintf(stderr, "There is no such command.\n");
- break;
- }
- fprintf(stderr, "Error occurred during reading below "
- "line:\n%s\n", vty->buf);
- vty_close(vty);
- return -EINVAL;
- }
-
- vty_close(vty);
- return 0;
-}
-
-/* Create new vty structure. */
-struct vty *
-vty_create (int vty_sock, void *priv)
-{
- struct vty *vty;
-
- struct termios t;
-
- tcgetattr(vty_sock, &t);
- cfmakeraw(&t);
- tcsetattr(vty_sock, TCSANOW, &t);
-
- /* Allocate new vty structure and set up default values. */
- vty = vty_new ();
- vty->fd = vty_sock;
- vty->priv = priv;
- vty->type = VTY_TERM;
- if (no_password_check)
- {
- if (host.advanced)
- vty->node = ENABLE_NODE;
- else
- vty->node = VIEW_NODE;
- }
- else
- vty->node = AUTH_NODE;
- vty->fail = 0;
- vty->cp = 0;
- vty_clear_buf (vty);
- vty->length = 0;
- memset (vty->hist, 0, sizeof (vty->hist));
- vty->hp = 0;
- vty->hindex = 0;
- vector_set_index (vtyvec, vty_sock, vty);
- vty->status = VTY_NORMAL;
- if (host.lines >= 0)
- vty->lines = host.lines;
- else
- vty->lines = -1;
-
- if (! no_password_check)
- {
- /* Vty is not available if password isn't set. */
- if (host.password == NULL && host.password_encrypt == NULL)
- {
- vty_out (vty, "Vty password is not set.%s", VTY_NEWLINE);
- vty->status = VTY_CLOSE;
- vty_close (vty);
- return NULL;
- }
- }
-
- /* Say hello to the world. */
- vty_hello (vty);
- if (! no_password_check)
- vty_out (vty, "%sUser Access Verification%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
-
- /* Setting up terminal. */
- vty_will_echo (vty);
- vty_will_suppress_go_ahead (vty);
-
- vty_dont_linemode (vty);
- vty_do_window_size (vty);
- /* vty_dont_lflow_ahead (vty); */
-
- vty_prompt (vty);
-
- /* Add read/write thread. */
- vty_event (VTY_WRITE, vty_sock, vty);
- vty_event (VTY_READ, vty_sock, vty);
-
- return vty;
-}
-
-DEFUN(config_who, config_who_cmd, "who", "Display who is on vty\n")
-{
- unsigned int i;
- struct vty *v;
-
- for (i = 0; i < vector_active(vtyvec); i++)
- if ((v = vector_slot(vtyvec, i)) != NULL)
- vty_out(vty, "%svty[%d] %s",
- v->config ? "*" : " ", i, VTY_NEWLINE);
- return CMD_SUCCESS;
-}
-
-/* Move to vty configuration mode. */
-DEFUN(line_vty,
- line_vty_cmd,
- "line vty", "Configure a terminal line\n" "Virtual terminal\n")
-{
- vty->node = VTY_NODE;
- return CMD_SUCCESS;
-}
-
-/* vty login. */
-DEFUN(vty_login, vty_login_cmd, "login", "Enable password checking\n")
-{
- no_password_check = 0;
- return CMD_SUCCESS;
-}
-
-DEFUN(no_vty_login,
- no_vty_login_cmd, "no login", NO_STR "Enable password checking\n")
-{
- no_password_check = 1;
- return CMD_SUCCESS;
-}
-
-DEFUN(service_advanced_vty,
- service_advanced_vty_cmd,
- "service advanced-vty",
- "Set up miscellaneous service\n" "Enable advanced mode vty interface\n")
-{
- host.advanced = 1;
- return CMD_SUCCESS;
-}
-
-DEFUN(no_service_advanced_vty,
- no_service_advanced_vty_cmd,
- "no service advanced-vty",
- NO_STR
- "Set up miscellaneous service\n" "Enable advanced mode vty interface\n")
-{
- host.advanced = 0;
- return CMD_SUCCESS;
-}
-
-DEFUN(terminal_monitor,
- terminal_monitor_cmd,
- "terminal monitor",
- "Set terminal line parameters\n"
- "Copy debug output to the current terminal line\n")
-{
- vty->monitor = 1;
- return CMD_SUCCESS;
-}
-
-DEFUN(terminal_no_monitor,
- terminal_no_monitor_cmd,
- "terminal no monitor",
- "Set terminal line parameters\n"
- NO_STR "Copy debug output to the current terminal line\n")
-{
- vty->monitor = 0;
- return CMD_SUCCESS;
-}
-
-DEFUN(show_history,
- show_history_cmd,
- "show history", SHOW_STR "Display the session command history\n")
-{
- int index;
-
- for (index = vty->hindex + 1; index != vty->hindex;) {
- if (index == VTY_MAXHIST) {
- index = 0;
- continue;
- }
-
- if (vty->hist[index] != NULL)
- vty_out(vty, " %s%s", vty->hist[index], VTY_NEWLINE);
-
- index++;
- }
-
- return CMD_SUCCESS;
-}
-
-/* Display current configuration. */
-static int vty_config_write(struct vty *vty)
-{
- vty_out(vty, "line vty%s", VTY_NEWLINE);
-
- /* login */
- if (no_password_check)
- vty_out(vty, " no login%s", VTY_NEWLINE);
-
- vty_out(vty, "!%s", VTY_NEWLINE);
-
- return CMD_SUCCESS;
-}
-
-struct cmd_node vty_node = {
- VTY_NODE,
- "%s(config-line)# ",
- 1,
-};
-
-/* Reset all VTY status. */
-void vty_reset()
-{
- unsigned int i;
- struct vty *vty;
- struct thread *vty_serv_thread;
-
- for (i = 0; i < vector_active(vtyvec); i++)
- if ((vty = vector_slot(vtyvec, i)) != NULL) {
- buffer_reset(vty->obuf);
- vty->status = VTY_CLOSE;
- vty_close(vty);
- }
-
- for (i = 0; i < vector_active(Vvty_serv_thread); i++)
- if ((vty_serv_thread =
- vector_slot(Vvty_serv_thread, i)) != NULL) {
- //thread_cancel (vty_serv_thread);
- vector_slot(Vvty_serv_thread, i) = NULL;
- close(i);
- }
-}
-
-static void vty_save_cwd(void)
-{
- char cwd[MAXPATHLEN];
- char *c ;
-
- c = getcwd(cwd, MAXPATHLEN);
-
- if (!c) {
- if (chdir(SYSCONFDIR) != 0)
- perror("chdir failed");
- if (getcwd(cwd, MAXPATHLEN) == NULL)
- perror("getcwd failed");
- }
-
- vty_cwd = _talloc_zero(tall_vty_ctx, strlen(cwd) + 1, "save_cwd");
- strcpy(vty_cwd, cwd);
-}
-
-char *vty_get_cwd()
-{
- return vty_cwd;
-}
-
-int vty_shell_serv(struct vty *vty)
-{
- return vty->type == VTY_SHELL_SERV ? 1 : 0;
-}
-
-void vty_init_vtysh()
-{
- vtyvec = vector_init(VECTOR_MIN_SIZE);
-}
-
-extern void *tall_bsc_ctx;
-/* Install vty's own commands like `who' command. */
-void vty_init()
-{
- tall_vty_ctx = talloc_named_const(NULL, 0, "vty");
- tall_vty_vec_ctx = talloc_named_const(tall_vty_ctx, 0, "vty_vector");
- tall_vty_cmd_ctx = talloc_named_const(tall_vty_ctx, 0, "vty_command");
-
- /* For further configuration read, preserve current directory. */
- vty_save_cwd();
-
- vtyvec = vector_init(VECTOR_MIN_SIZE);
-
- /* Install bgp top node. */
- install_node(&vty_node, vty_config_write);
-
- install_element(VIEW_NODE, &config_who_cmd);
- install_element(VIEW_NODE, &show_history_cmd);
- install_element(ENABLE_NODE, &config_who_cmd);
- install_element(CONFIG_NODE, &line_vty_cmd);
- install_element(CONFIG_NODE, &service_advanced_vty_cmd);
- install_element(CONFIG_NODE, &no_service_advanced_vty_cmd);
- install_element(CONFIG_NODE, &show_history_cmd);
- install_element(ENABLE_NODE, &terminal_monitor_cmd);
- install_element(ENABLE_NODE, &terminal_no_monitor_cmd);
- install_element(ENABLE_NODE, &show_history_cmd);
-
- install_default(VTY_NODE);
- install_element(VTY_NODE, &vty_login_cmd);
- install_element(VTY_NODE, &no_vty_login_cmd);
-}
-
-int vty_read_config_file(const char *file_name)
-{
- FILE *cfile;
- int rc;
-
- cfile = fopen(file_name, "r");
- if (!cfile)
- return -ENOENT;
-
- rc = vty_read_file(cfile);
- fclose(cfile);
-
- host_config_set(file_name);
-
- return rc;
-}
diff --git a/openbsc/src/vty_interface_cmds.c b/openbsc/src/vty_interface_cmds.c
deleted file mode 100644
index dd5e108..0000000
--- a/openbsc/src/vty_interface_cmds.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/* OpenBSC logging helper for the VTY */
-/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
- * (C) 2009-2010 by Holger Hans Peter Freyther
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <openbsc/vty.h>
-#include <openbsc/telnet_interface.h>
-
-#include <osmocore/talloc.h>
-
-#include <vty/command.h>
-#include <vty/buffer.h>
-#include <vty/vty.h>
-
-#include <stdlib.h>
-
-#define LOGGING_STR "Configure log message to this terminal\n"
-
-static void _vty_output(struct log_target *tgt, const char *line)
-{
- struct vty *vty = tgt->tgt_vty.vty;
- vty_out(vty, "%s", line);
- /* This is an ugly hack, but there is no easy way... */
- if (strchr(line, '\n'))
- vty_out(vty, "\r");
-}
-
-struct log_target *log_target_create_vty(struct vty *vty)
-{
- struct log_target *target;
-
- target = log_target_create();
- if (!target)
- return NULL;
-
- target->tgt_vty.vty = vty;
- target->output = _vty_output;
- return target;
-}
-
-DEFUN(enable_logging,
- enable_logging_cmd,
- "logging enable",
- LOGGING_STR
- "Enables logging to this vty\n")
-{
- struct telnet_connection *conn;
-
- conn = (struct telnet_connection *) vty->priv;
- if (conn->dbg) {
- vty_out(vty, "Logging already enabled.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- conn->dbg = log_target_create_vty(vty);
- if (!conn->dbg)
- return CMD_WARNING;
-
- log_add_target(conn->dbg);
- return CMD_SUCCESS;
-}
-
-DEFUN(logging_fltr_imsi,
- logging_fltr_imsi_cmd,
- "logging filter imsi IMSI",
- LOGGING_STR
- "Print all messages related to a IMSI\n")
-{
- struct telnet_connection *conn;
-
- conn = (struct telnet_connection *) vty->priv;
- if (!conn->dbg) {
- vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- log_set_imsi_filter(conn->dbg, argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(logging_fltr_all,
- logging_fltr_all_cmd,
- "logging filter all <0-1>",
- LOGGING_STR
- "Print all messages to the console\n")
-{
- struct telnet_connection *conn;
-
- conn = (struct telnet_connection *) vty->priv;
- if (!conn->dbg) {
- vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- log_set_all_filter(conn->dbg, atoi(argv[0]));
- return CMD_SUCCESS;
-}
-
-DEFUN(logging_use_clr,
- logging_use_clr_cmd,
- "logging color <0-1>",
- LOGGING_STR
- "Use color for printing messages\n")
-{
- struct telnet_connection *conn;
-
- conn = (struct telnet_connection *) vty->priv;
- if (!conn->dbg) {
- vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- log_set_use_color(conn->dbg, atoi(argv[0]));
- return CMD_SUCCESS;
-}
-
-DEFUN(logging_prnt_timestamp,
- logging_prnt_timestamp_cmd,
- "logging timestamp <0-1>",
- LOGGING_STR
- "Print the timestamp of each message\n")
-{
- struct telnet_connection *conn;
-
- conn = (struct telnet_connection *) vty->priv;
- if (!conn->dbg) {
- vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- log_set_print_timestamp(conn->dbg, atoi(argv[0]));
- return CMD_SUCCESS;
-}
-
-/* FIXME: those have to be kept in sync with the log levels and categories */
-#define VTY_DEBUG_CATEGORIES "(rll|cc|mm|rr|rsl|nm|sms|pag|mncc|inp|mi|mib|mux|meas|sccp|msc|mgcp|ho|db|ref|gprs|ns|bssgp|all)"
-#define CATEGORIES_HELP \
- "A-bis Radio Link Layer (RLL)\n" \
- "Layer3 Call Control (CC)\n" \
- "Layer3 Mobility Management (MM)\n" \
- "Layer3 Radio Resource (RR)\n" \
- "A-bis Radio Signalling Link (RSL)\n" \
- "A-bis Network Management / O&M (NM/OML)\n" \
- "Layer3 Short Messagaging Service (SMS)\n" \
- "Paging Subsystem\n" \
- "MNCC API for Call Control application\n" \
- "A-bis Input Subsystem\n" \
- "A-bis Input Driver for Signalling\n" \
- "A-bis Input Driver for B-Channel (voice data)\n" \
- "A-bis B-Channel / Sub-channel Multiplexer\n" \
- "Radio Measurements\n" \
- "SCCP\n" \
- "Mobile Switching Center\n" \
- "Media Gateway Control Protocol\n" \
- "Hand-over\n" \
- "Database Layer\n" \
- "Reference Counting\n" \
- "GPRS Core\n" \
- "GPRS Network Service (NS)\n" \
- "GPRS BSS Gateway Protocol (BSSGP)\n" \
- "Global setting for all subsytems\n"
-
-#define VTY_DEBUG_LEVELS "(everything|debug|info|notice|error|fatal)"
-#define LEVELS_HELP \
- "Log simply everything\n" \
- "Log debug messages and higher levels\n" \
- "Log informational messages and higher levels\n" \
- "Log noticable messages and higher levels\n" \
- "Log error messages and higher levels\n" \
- "Log only fatal messages\n"
-DEFUN(logging_level,
- logging_level_cmd,
- "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS,
- LOGGING_STR
- "Set the log level for a specified category\n"
- CATEGORIES_HELP
- LEVELS_HELP)
-{
- struct telnet_connection *conn;
- int category = log_parse_category(argv[0]);
- int level = log_parse_level(argv[1]);
-
- conn = (struct telnet_connection *) vty->priv;
- if (!conn->dbg) {
- vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- if (level < 0) {
- vty_out(vty, "Invalid level `%s'%s", argv[1], VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- /* Check for special case where we want to set global log level */
- if (!strcmp(argv[0], "all")) {
- log_set_log_level(conn->dbg, level);
- return CMD_SUCCESS;
- }
-
- if (category < 0) {
- vty_out(vty, "Invalid category `%s'%s", argv[0], VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- conn->dbg->categories[category].enabled = 1;
- conn->dbg->categories[category].loglevel = level;
-
- return CMD_SUCCESS;
-}
-
-DEFUN(logging_set_category_mask,
- logging_set_category_mask_cmd,
- "logging set log mask MASK",
- LOGGING_STR
- "Decide which categories to output.\n")
-{
- struct telnet_connection *conn;
-
- conn = (struct telnet_connection *) vty->priv;
- if (!conn->dbg) {
- vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- log_parse_category_mask(conn->dbg, argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(diable_logging,
- disable_logging_cmd,
- "logging disable",
- LOGGING_STR
- "Disables logging to this vty\n")
-{
- struct telnet_connection *conn;
-
- conn = (struct telnet_connection *) vty->priv;
- if (!conn->dbg) {
- vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- log_del_target(conn->dbg);
- talloc_free(conn->dbg);
- conn->dbg = NULL;
- return CMD_SUCCESS;
-}
-
-static void vty_print_logtarget(struct vty *vty, const struct log_info *info,
- const struct log_target *tgt)
-{
- unsigned int i;
-
- vty_out(vty, " Global Loglevel: %s%s",
- log_level_str(tgt->loglevel), VTY_NEWLINE);
- vty_out(vty, " Use color: %s, Print Timestamp: %s%s",
- tgt->use_color ? "On" : "Off",
- tgt->print_timestamp ? "On" : "Off", VTY_NEWLINE);
-
- vty_out(vty, " Log Level specific information:%s", VTY_NEWLINE);
-
- for (i = 0; i < info->num_cat; i++) {
- const struct log_category *cat = &tgt->categories[i];
- vty_out(vty, " %-10s %-10s %-8s %s%s",
- info->cat[i].name+1, log_level_str(cat->loglevel),
- cat->enabled ? "Enabled" : "Disabled",
- info->cat[i].description,
- VTY_NEWLINE);
- }
-}
-
-#define SHOW_LOG_STR "Show current logging configuration\n"
-
-DEFUN(show_logging_vty,
- show_logging_vty_cmd,
- "show logging vty",
- SHOW_STR SHOW_LOG_STR
- "Show current logging configuration for this vty\n")
-{
- struct telnet_connection *conn;
-
- conn = (struct telnet_connection *) vty->priv;
- if (!conn->dbg) {
- vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- vty_print_logtarget(vty, &log_info, conn->dbg);
-
- return CMD_SUCCESS;
-}
-
-void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *net)
-{
- vty_out(vty, "Channel Requests : %lu total, %lu no channel%s",
- counter_get(net->stats.chreq.total),
- counter_get(net->stats.chreq.no_channel), VTY_NEWLINE);
- vty_out(vty, "Channel Failures : %lu rf_failures, %lu rll failures%s",
- counter_get(net->stats.chan.rf_fail),
- counter_get(net->stats.chan.rll_err), VTY_NEWLINE);
- vty_out(vty, "Paging : %lu attempted, %lu complete, %lu expired%s",
- counter_get(net->stats.paging.attempted),
- counter_get(net->stats.paging.completed),
- counter_get(net->stats.paging.expired), VTY_NEWLINE);
- vty_out(vty, "BTS failures : %lu OML, %lu RSL%s",
- counter_get(net->stats.bts.oml_fail),
- counter_get(net->stats.bts.rsl_fail), VTY_NEWLINE);
-}
-
-void openbsc_vty_add_cmds()
-{
- install_element_ve(&enable_logging_cmd);
- install_element_ve(&disable_logging_cmd);
- install_element_ve(&logging_fltr_imsi_cmd);
- install_element_ve(&logging_fltr_all_cmd);
- install_element_ve(&logging_use_clr_cmd);
- install_element_ve(&logging_prnt_timestamp_cmd);
- install_element_ve(&logging_set_category_mask_cmd);
- install_element_ve(&logging_level_cmd);
- install_element_ve(&show_logging_vty_cmd);
-}
diff --git a/openbsc/src/vty_interface_layer3.c b/openbsc/src/vty_interface_layer3.c
index 1b2adbb..7c32c05 100644
--- a/openbsc/src/vty_interface_layer3.c
+++ b/openbsc/src/vty_interface_layer3.c
@@ -23,9 +23,9 @@
#include <unistd.h>
#include <sys/types.h>
-#include <vty/command.h>
-#include <vty/buffer.h>
-#include <vty/vty.h>
+#include <osmocom/vty/command.h>
+#include <osmocom/vty/buffer.h>
+#include <osmocom/vty/vty.h>
#include <arpa/inet.h>
@@ -43,35 +43,7 @@
#include <openbsc/debug.h>
#include <openbsc/vty.h>
-static struct gsm_network *gsmnet;
-
-struct cmd_node subscr_node = {
- SUBSCR_NODE,
- "%s(subscriber)#",
- 1,
-};
-
-static int dummy_config_write(struct vty *v)
-{
- return CMD_SUCCESS;
-}
-
-static struct buffer *argv_to_buffer(int argc, const char *argv[], int base)
-{
- struct buffer *b = buffer_new(NULL, 1024);
- int i;
-
- if (!b)
- return NULL;
-
- for (i = base; i < argc; i++) {
- buffer_putstr(b, argv[i]);
- buffer_putc(b, ' ');
- }
- buffer_putc(b, '\0');
-
- return b;
-}
+extern struct gsm_network *gsmnet_from_vty(struct vty *v);
static int hexparse(const char *str, u_int8_t *b, int max_len)
@@ -100,29 +72,6 @@
return i>>1;
}
-/* per-subscriber configuration */
-DEFUN(cfg_subscr,
- cfg_subscr_cmd,
- "subscriber IMSI",
- "Select a Subscriber to configure\n")
-{
- const char *imsi = argv[0];
- struct gsm_subscriber *subscr;
-
- subscr = subscr_get_by_imsi(gsmnet, imsi);
- if (!subscr) {
- vty_out(vty, "%% No subscriber for IMSI %s%s",
- imsi, VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- /* vty_go_parent should put this subscriber */
- vty->index = subscr;
- vty->node = SUBSCR_NODE;
-
- return CMD_SUCCESS;
-}
-
static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr)
{
int rc;
@@ -142,7 +91,7 @@
vty_out(vty, " TMSI: %08X%s", subscr->tmsi,
VTY_NEWLINE);
- rc = get_authinfo_by_subscr(&ainfo, subscr);
+ rc = db_get_authinfo_for_subscr(&ainfo, subscr);
if (!rc) {
vty_out(vty, " A3A8 algorithm id: %d%s",
ainfo.auth_algo, VTY_NEWLINE);
@@ -151,7 +100,7 @@
VTY_NEWLINE);
}
- rc = get_authtuple_by_subscr(&atuple, subscr);
+ rc = db_get_lastauthtuple_for_subscr(&atuple, subscr);
if (!rc) {
vty_out(vty, " A3A8 last tuple (used %d times):%s",
atuple.use_count, VTY_NEWLINE);
@@ -173,34 +122,6 @@
/* Subscriber */
-DEFUN(show_subscr,
- show_subscr_cmd,
- "show subscriber [IMSI]",
- SHOW_STR "Display information about a subscriber\n")
-{
- const char *imsi;
- struct gsm_subscriber *subscr;
-
- if (argc >= 1) {
- imsi = argv[0];
- subscr = subscr_get_by_imsi(gsmnet, imsi);
- if (!subscr) {
- vty_out(vty, "%% unknown subscriber%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- subscr_dump_full_vty(vty, subscr);
- subscr_put(subscr);
-
- return CMD_SUCCESS;
- }
-
- /* FIXME: iterate over all subscribers ? */
- return CMD_WARNING;
-
- return CMD_SUCCESS;
-}
-
DEFUN(show_subscr_cache,
show_subscr_cache_cmd,
"show subscriber cache",
@@ -221,6 +142,7 @@
"sms send pending",
"Send all pending SMS")
{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
struct gsm_sms *sms;
int id = 0;
@@ -253,7 +175,7 @@
strncpy(sms->text, text, sizeof(sms->text)-1);
/* FIXME: don't use ID 1 static */
- sms->sender = subscr_get_by_id(gsmnet, 1);
+ sms->sender = subscr_get_by_id(receiver->net, 1);
sms->reply_path_req = 0;
sms->status_rep_req = 0;
sms->ud_hdr_ind = 0;
@@ -266,19 +188,20 @@
return sms;
}
-static int _send_sms_buffer(struct gsm_subscriber *receiver,
- struct buffer *b, u_int8_t tp_pid)
+static int _send_sms_str(struct gsm_subscriber *receiver, char *str,
+ u_int8_t tp_pid)
{
struct gsm_sms *sms;
- sms = sms_from_text(receiver, buffer_getstr(b));
+ sms = sms_from_text(receiver, str);
sms->protocol_id = tp_pid;
gsm411_send_sms_subscr(receiver, sms);
return CMD_SUCCESS;
}
-static struct gsm_subscriber *get_subscr_by_argv(const char *type,
+static struct gsm_subscriber *get_subscr_by_argv(struct gsm_network *gsmnet,
+ const char *type,
const char *id)
{
if (!strcmp(type, "extension"))
@@ -293,14 +216,43 @@
return NULL;
}
#define SUBSCR_TYPES "(extension|imsi|tmsi|id)"
+#define SUBSCR_HELP "Operations on a Subscriber\n" \
+ "Identify subscriber by his extension (phone number)\n" \
+ "Identify subscriber by his IMSI\n" \
+ "Identify subscriber by his TMSI\n" \
+ "Identify subscriber by his database ID\n" \
+ "Identifier for the subscriber\n"
+
+DEFUN(show_subscr,
+ show_subscr_cmd,
+ "show subscriber " SUBSCR_TYPES " ID",
+ SHOW_STR SUBSCR_HELP)
+{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+ struct gsm_subscriber *subscr =
+ get_subscr_by_argv(gsmnet, argv[0], argv[1]);
+
+ if (!subscr) {
+ vty_out(vty, "%% No subscriber found for %s %s%s",
+ argv[0], argv[1], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ subscr_dump_full_vty(vty, subscr);
+
+ subscr_put(subscr);
+
+ return CMD_SUCCESS;
+}
DEFUN(subscriber_send_sms,
subscriber_send_sms_cmd,
- "subscriber " SUBSCR_TYPES " EXTEN sms send .LINE",
- "Select subscriber based on extension")
+ "subscriber " SUBSCR_TYPES " ID sms send .LINE",
+ SUBSCR_HELP "SMS Operations\n" "Send SMS\n" "Actual SMS Text")
{
- struct gsm_subscriber *subscr = get_subscr_by_argv(argv[0], argv[1]);
- struct buffer *b;
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+ struct gsm_subscriber *subscr = get_subscr_by_argv(gsmnet, argv[0], argv[1]);
+ char *str;
int rc;
if (!subscr) {
@@ -308,9 +260,9 @@
argv[0], argv[1], VTY_NEWLINE);
return CMD_WARNING;
}
- b = argv_to_buffer(argc, argv, 2);
- rc = _send_sms_buffer(subscr, b, 0);
- buffer_free(b);
+ str = argv_concat(argv, argc, 2);
+ rc = _send_sms_str(subscr, str, 0);
+ talloc_free(str);
subscr_put(subscr);
@@ -319,11 +271,13 @@
DEFUN(subscriber_silent_sms,
subscriber_silent_sms_cmd,
- "subscriber " SUBSCR_TYPES " EXTEN silent sms send .LINE",
- "Select subscriber based on extension")
+ "subscriber " SUBSCR_TYPES " ID silent-sms send .LINE",
+ SUBSCR_HELP
+ "Silent SMS Operation\n" "Send Silent SMS\n" "Actual SMS text\n")
{
- struct gsm_subscriber *subscr = get_subscr_by_argv(argv[0], argv[1]);
- struct buffer *b;
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+ struct gsm_subscriber *subscr = get_subscr_by_argv(gsmnet, argv[0], argv[1]);
+ char *str;
int rc;
if (!subscr) {
@@ -332,21 +286,30 @@
return CMD_WARNING;
}
- b = argv_to_buffer(argc, argv, 2);
- rc = _send_sms_buffer(subscr, b, 64);
- buffer_free(b);
+ str = argv_concat(argv, argc, 2);
+ rc = _send_sms_str(subscr, str, 0);
+ talloc_free(str);
subscr_put(subscr);
return rc;
}
+#define CHAN_TYPES "(any|tch/f|tch/any|sdcch)"
+#define CHAN_TYPE_HELP \
+ "Any channel\n" \
+ "TCH/F channel\n" \
+ "Any TCH channel\n" \
+ "SDCCH channel\n"
+
DEFUN(subscriber_silent_call_start,
subscriber_silent_call_start_cmd,
- "subscriber " SUBSCR_TYPES " EXTEN silent call start (any|tch/f|tch/any|sdcch)",
- "Start a silent call to a subscriber")
+ "subscriber " SUBSCR_TYPES " ID silent-call start (any|tch/f|tch/any|sdcch)",
+ SUBSCR_HELP "Silent call operation\n" "Start silent call\n"
+ CHAN_TYPE_HELP)
{
- struct gsm_subscriber *subscr = get_subscr_by_argv(argv[0], argv[1]);
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+ struct gsm_subscriber *subscr = get_subscr_by_argv(gsmnet, argv[0], argv[1]);
int rc, type;
if (!subscr) {
@@ -379,10 +342,12 @@
DEFUN(subscriber_silent_call_stop,
subscriber_silent_call_stop_cmd,
- "subscriber " SUBSCR_TYPES " EXTEN silent call stop",
- "Stop a silent call to a subscriber")
+ "subscriber " SUBSCR_TYPES " ID silent-call stop",
+ SUBSCR_HELP "Silent call operation\n" "Stop silent call\n"
+ CHAN_TYPE_HELP)
{
- struct gsm_subscriber *subscr = get_subscr_by_argv(argv[0], argv[1]);
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+ struct gsm_subscriber *subscr = get_subscr_by_argv(gsmnet, argv[0], argv[1]);
int rc;
if (!subscr) {
@@ -402,85 +367,140 @@
return CMD_SUCCESS;
}
-DEFUN(cfg_subscr_name,
- cfg_subscr_name_cmd,
- "name NAME",
- "Set the name of the subscriber")
+DEFUN(ena_subscr_authorizde,
+ ena_subscr_authorized_cmd,
+ "subscriber " SUBSCR_TYPES " ID authorized (0|1)",
+ SUBSCR_HELP "(De-)Authorize subscriber in HLR\n"
+ "Subscriber should NOT be authorized\n"
+ "Subscriber should be authorized\n")
{
- const char *name = argv[0];
- struct gsm_subscriber *subscr = vty->index;
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+ struct gsm_subscriber *subscr =
+ get_subscr_by_argv(gsmnet, argv[0], argv[1]);
+
+ if (!subscr) {
+ vty_out(vty, "%% No subscriber found for %s %s%s",
+ argv[0], argv[1], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ subscr->authorized = atoi(argv[2]);
+ db_sync_subscriber(subscr);
+
+ subscr_put(subscr);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(ena_subscr_name,
+ ena_subscr_name_cmd,
+ "subscriber " SUBSCR_TYPES " ID name NAME",
+ SUBSCR_HELP "Set the name of the subscriber\n"
+ "Name of the Subscriber\n")
+{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+ struct gsm_subscriber *subscr =
+ get_subscr_by_argv(gsmnet, argv[0], argv[1]);
+ const char *name = argv[2];
+
+ if (!subscr) {
+ vty_out(vty, "%% No subscriber found for %s %s%s",
+ argv[0], argv[1], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
strncpy(subscr->name, name, sizeof(subscr->name));
-
db_sync_subscriber(subscr);
+ subscr_put(subscr);
+
return CMD_SUCCESS;
}
-DEFUN(cfg_subscr_extension,
- cfg_subscr_extension_cmd,
- "extension EXTENSION",
- "Set the extension of the subscriber")
+DEFUN(ena_subscr_extension,
+ ena_subscr_extension_cmd,
+ "subscriber " SUBSCR_TYPES " ID extension EXTENSION",
+ SUBSCR_HELP "Set the extension (phone number) of the subscriber\n"
+ "Extension (phone number)\n")
{
- const char *name = argv[0];
- struct gsm_subscriber *subscr = vty->index;
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+ struct gsm_subscriber *subscr =
+ get_subscr_by_argv(gsmnet, argv[0], argv[1]);
+ const char *name = argv[2];
- strncpy(subscr->extension, name, sizeof(subscr->extension));
+ if (!subscr) {
+ vty_out(vty, "%% No subscriber found for %s %s%s",
+ argv[0], argv[1], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ strncpy(subscr->extension, name, sizeof(subscr->name));
db_sync_subscriber(subscr);
+ subscr_put(subscr);
+
return CMD_SUCCESS;
}
-DEFUN(cfg_subscr_authorized,
- cfg_subscr_authorized_cmd,
- "auth <0-1>",
- "Set the authorization status of the subscriber")
+#define A3A8_ALG_TYPES "(none|xor|comp128v1)"
+#define A3A8_ALG_HELP \
+ "Use No A3A8 algorithm\n" \
+ "Use XOR algorithm\n" \
+ "Use COMP128v1 algorithm\n"
+
+DEFUN(ena_subscr_a3a8,
+ ena_subscr_a3a8_cmd,
+ "subscriber " SUBSCR_TYPES " ID a3a8 " A3A8_ALG_TYPES " [KI]",
+ SUBSCR_HELP "Set a3a8 parameters for the subscriber\n"
+ A3A8_ALG_HELP "Encryption Key Ki\n")
{
- int auth = atoi(argv[0]);
- struct gsm_subscriber *subscr = vty->index;
-
- if (auth)
- subscr->authorized = 1;
- else
- subscr->authorized = 0;
-
- db_sync_subscriber(subscr);
-
- return CMD_SUCCESS;
-}
-
-#define A3A8_ALG_TYPES "(none|comp128v1)"
-
-DEFUN(cfg_subscr_a3a8,
- cfg_subscr_a3a8_cmd,
- "a3a8 " A3A8_ALG_TYPES " [KI]",
- "Set a3a8 parameters for the subscriber")
-{
- struct gsm_subscriber *subscr = vty->index;
- const char *alg_str = argv[0];
- const char *ki_str = argv[1];
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+ struct gsm_subscriber *subscr =
+ get_subscr_by_argv(gsmnet, argv[0], argv[1]);
+ const char *alg_str = argv[2];
+ const char *ki_str = argc == 4 ? argv[3] : NULL;
struct gsm_auth_info ainfo;
- int rc;
+ int rc, minlen, maxlen;
+
+ if (!subscr) {
+ vty_out(vty, "%% No subscriber found for %s %s%s",
+ argv[0], argv[1], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
if (!strcasecmp(alg_str, "none")) {
- /* Just erase */
- rc = set_authinfo_for_subscr(NULL, subscr);
+ ainfo.auth_algo = AUTH_ALGO_NONE;
+ minlen = maxlen = 0;
+ } else if (!strcasecmp(alg_str, "xor")) {
+ ainfo.auth_algo = AUTH_ALGO_XOR;
+ minlen = A38_XOR_MIN_KEY_LEN;
+ maxlen = A38_XOR_MAX_KEY_LEN;
} else if (!strcasecmp(alg_str, "comp128v1")) {
- /* Parse hex string Ki */
- rc = hexparse(ki_str, ainfo.a3a8_ki, sizeof(ainfo.a3a8_ki));
- if (rc != 16)
- return CMD_WARNING;
-
- /* Set the infos */
ainfo.auth_algo = AUTH_ALGO_COMP128v1;
- ainfo.a3a8_ki_len = rc;
- rc = set_authinfo_for_subscr(&ainfo, subscr);
+ minlen = maxlen = A38_COMP128_KEY_LEN;
} else {
/* Unknown method */
return CMD_WARNING;
}
+ if (ki_str) {
+ rc = hexparse(ki_str, ainfo.a3a8_ki, sizeof(ainfo.a3a8_ki));
+ if ((rc > maxlen) || (rc < minlen))
+ return CMD_WARNING;
+ ainfo.a3a8_ki_len = rc;
+ } else {
+ ainfo.a3a8_ki_len = 0;
+ if (minlen)
+ return CMD_WARNING;
+ }
+
+ rc = db_sync_authinfo_for_subscr(
+ ainfo.auth_algo == AUTH_ALGO_NONE ? NULL : &ainfo,
+ subscr);
+
+ /* the last tuple probably invalid with the new auth settings */
+ db_sync_lastauthtuple_for_subscr(NULL, subscr);
+
return rc ? CMD_WARNING : CMD_SUCCESS;
}
@@ -508,7 +528,7 @@
"show statistics",
SHOW_STR "Display network statistics\n")
{
- struct gsm_network *net = gsmnet;
+ struct gsm_network *net = gsmnet_from_vty(vty);
openbsc_vty_print_statistics(vty, net);
vty_out(vty, "Location Update : %lu attach, %lu normal, %lu periodic%s",
@@ -538,10 +558,8 @@
}
-int bsc_vty_init_extra(struct gsm_network *net)
+int bsc_vty_init_extra(void)
{
- gsmnet = net;
-
register_signal_handler(SS_SCALL, scall_cbfn, NULL);
install_element_ve(&show_subscr_cmd);
@@ -555,14 +573,10 @@
install_element_ve(&subscriber_silent_call_stop_cmd);
install_element_ve(&show_stats_cmd);
- install_element(CONFIG_NODE, &cfg_subscr_cmd);
- install_node(&subscr_node, dummy_config_write);
-
- install_default(SUBSCR_NODE);
- install_element(SUBSCR_NODE, &cfg_subscr_name_cmd);
- install_element(SUBSCR_NODE, &cfg_subscr_extension_cmd);
- install_element(SUBSCR_NODE, &cfg_subscr_authorized_cmd);
- install_element(SUBSCR_NODE, &cfg_subscr_a3a8_cmd);
+ install_element(ENABLE_NODE, &ena_subscr_name_cmd);
+ install_element(ENABLE_NODE, &ena_subscr_extension_cmd);
+ install_element(ENABLE_NODE, &ena_subscr_authorized_cmd);
+ install_element(ENABLE_NODE, &ena_subscr_a3a8_cmd);
return 0;
}
diff --git a/openbsc/tests/Makefile.am b/openbsc/tests/Makefile.am
index 3b1b931..b469832 100644
--- a/openbsc/tests/Makefile.am
+++ b/openbsc/tests/Makefile.am
@@ -1 +1 @@
-SUBDIRS = debug gsm0408 db channel sccp
+SUBDIRS = debug gsm0408 db channel sccp bsc-nat
diff --git a/openbsc/tests/bsc-nat/Makefile.am b/openbsc/tests/bsc-nat/Makefile.am
new file mode 100644
index 0000000..013a465
--- /dev/null
+++ b/openbsc/tests/bsc-nat/Makefile.am
@@ -0,0 +1,15 @@
+INCLUDES = $(all_includes) -I$(top_srcdir)/include
+AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS)
+
+EXTRA_DIST = bsc_data.c
+
+noinst_PROGRAMS = bsc_nat_test
+
+bsc_nat_test_SOURCES = bsc_nat_test.c \
+ $(top_srcdir)/src/nat/bsc_filter.c \
+ $(top_srcdir)/src/nat/bsc_sccp.c \
+ $(top_srcdir)/src/nat/bsc_nat_utils.c \
+ $(top_srcdir)/src/nat/bsc_mgcp_utils.c \
+ $(top_srcdir)/src/mgcp/mgcp_protocol.c \
+ $(top_srcdir)/src/mgcp/mgcp_network.c
+bsc_nat_test_LDADD = $(top_builddir)/src/libbsc.a $(top_builddir)/src/libsccp.a $(LIBOSMOCORE_LIBS) -lrt
diff --git a/openbsc/tests/bsc-nat/bsc_data.c b/openbsc/tests/bsc-nat/bsc_data.c
new file mode 100644
index 0000000..34242db
--- /dev/null
+++ b/openbsc/tests/bsc-nat/bsc_data.c
@@ -0,0 +1,154 @@
+/* test data */
+
+/* BSC -> MSC, CR */
+static const u_int8_t bsc_cr[] = {
+0x00, 0x2e, 0xfd,
+0x01, 0x00, 0x00, 0x15, 0x02, 0x02, 0x04, 0x02,
+0x42, 0xfe, 0x0f, 0x21, 0x00, 0x1f, 0x57, 0x05,
+0x08, 0x00, 0x72, 0xf4, 0x80, 0x20, 0x1c, 0xc3,
+0x51, 0x17, 0x12, 0x05, 0x08, 0x20, 0x72, 0xf4,
+0x90, 0x20, 0x1d, 0x50, 0x08, 0x29, 0x47, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00 };
+
+static const u_int8_t bsc_cr_patched[] = {
+0x00, 0x2e, 0xfd,
+0x01, 0x00, 0x00, 0x05, 0x02, 0x02, 0x04, 0x02,
+0x42, 0xfe, 0x0f, 0x21, 0x00, 0x1f, 0x57, 0x05,
+0x08, 0x00, 0x72, 0xf4, 0x80, 0x20, 0x1c, 0xc3,
+0x51, 0x17, 0x12, 0x05, 0x08, 0x20, 0x72, 0xf4,
+0x90, 0x20, 0x1d, 0x50, 0x08, 0x29, 0x47, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00 };
+
+/* CC, MSC -> BSC */
+static const u_int8_t msc_cc[] = {
+0x00, 0x0a, 0xfd,
+0x02, 0x00, 0x00, 0x05, 0x01, 0x1f, 0xe4, 0x02,
+0x01, 0x00 };
+static const u_int8_t msc_cc_patched[] = {
+0x00, 0x0a, 0xfd,
+0x02, 0x00, 0x00, 0x15, 0x01, 0x1f, 0xe4, 0x02,
+0x01, 0x00 };
+
+/* Classmark, BSC -> MSC */
+static const u_int8_t bsc_dtap[] = {
+0x00, 0x17, 0xfd,
+0x06, 0x01, 0x1f, 0xe4, 0x00, 0x01, 0x10, 0x00,
+0x0e, 0x54, 0x12, 0x03, 0x50, 0x18, 0x93, 0x13,
+0x06, 0x60, 0x14, 0x45, 0x00, 0x81, 0x00 };
+
+static const u_int8_t bsc_dtap_patched[] = {
+0x00, 0x17, 0xfd,
+0x06, 0x01, 0x1f, 0xe4, 0x00, 0x01, 0x10, 0x00,
+0x0e, 0x54, 0x12, 0x03, 0x50, 0x18, 0x93, 0x13,
+0x06, 0x60, 0x14, 0x45, 0x00, 0x81, 0x00 };
+
+/* Clear command, MSC -> BSC */
+static const u_int8_t msc_dtap[] = {
+0x00, 0x0d, 0xfd,
+0x06, 0x00, 0x00, 0x05, 0x00, 0x01, 0x06, 0x00,
+0x04, 0x20, 0x04, 0x01, 0x09 };
+static const u_int8_t msc_dtap_patched[] = {
+0x00, 0x0d, 0xfd,
+0x06, 0x00, 0x00, 0x15, 0x00, 0x01, 0x06, 0x00,
+0x04, 0x20, 0x04, 0x01, 0x09 };
+
+/*RLSD, MSC -> BSC */
+static const u_int8_t msc_rlsd[] = {
+0x00, 0x0a, 0xfd,
+0x04, 0x00, 0x00, 0x05, 0x01, 0x1f, 0xe4, 0x00,
+0x01, 0x00 };
+static const u_int8_t msc_rlsd_patched[] = {
+0x00, 0x0a, 0xfd,
+0x04, 0x00, 0x00, 0x15, 0x01, 0x1f, 0xe4, 0x00,
+0x01, 0x00 };
+
+/* RLC, BSC -> MSC */
+static const u_int8_t bsc_rlc[] = {
+0x00, 0x07, 0xfd,
+0x05, 0x01, 0x1f, 0xe4, 0x00, 0x00, 0x15 };
+
+static const u_int8_t bsc_rlc_patched[] = {
+0x00, 0x07, 0xfd,
+0x05, 0x01, 0x1f, 0xe4, 0x00, 0x00, 0x05 };
+
+
+/* a paging command */
+static const u_int8_t paging_by_lac_cmd[] = {
+0x00, 0x22, 0xfd, 0x09,
+0x00, 0x03, 0x07, 0x0b, 0x04, 0x43, 0x02, 0x00,
+0xfe, 0x04, 0x43, 0x5c, 0x00, 0xfe, 0x12, 0x00,
+0x10, 0x52, 0x08, 0x08, 0x29, 0x47, 0x10, 0x02,
+0x01, 0x50, 0x02, 0x30, 0x1a, 0x03, 0x05, 0x20,
+0x15 };
+
+/* an assignment command */
+static const u_int8_t ass_cmd[] = {
+0x00, 0x12, 0xfd, 0x06,
+0x00, 0x00, 0x49, 0x00, 0x01, 0x0b, 0x00, 0x09,
+0x01, 0x0b, 0x03, 0x01, 0x0a, 0x11, 0x01, 0x00,
+0x15 };
+
+/*
+ * MGCP messages
+ */
+
+/* nothing to patch */
+static const char crcx[] = "CRCX 23265295 8@mgw MGCP 1.0\r\nC: 394b0439fb\r\nL: p:20, a:AMR, nt:IN\r\nM: recvonly\r\n";
+static const char crcx_patched[] = "CRCX 23265295 8@mgw MGCP 1.0\r\nC: 394b0439fb\r\nL: p:20, a:AMR, nt:IN\r\nM: recvonly\r\n";
+
+
+/* patch the ip and port */
+static const char crcx_resp[] = "200 23265295\r\nI: 1\r\n\r\nv=0\r\nc=IN IP4 172.16.18.2\r\nm=audio 4002 RTP/AVP 98\r\na=rtpmap:98 AMR/8000\r\n";
+static const char crcx_resp_patched[] = "200 23265295\r\nI: 1\r\n\r\nv=0\r\nc=IN IP4 10.0.0.1\r\nm=audio 999 RTP/AVP 98\r\na=rtpmap:98 AMR/8000\r\n";
+
+/* patch the ip and port */
+static const char mdcx[] = " MDCX 23330829 8@mgw MGCP 1.0\r\nC: 394b0439fb\r\nI: 1\r\nL: p:20, a:AMR, nt:IN\r\nM: recvonly\r\n\r\nv=0\r\no=- 1049380491 0 IN IP4 172.16.18.2\r\ns=-\r\nc=IN IP4 172.16.18.2\r\nt=0 0\r\nm=audio 4410 RTP/AVP 126\r\na=rtpmap:126 AMR/8000/1\r\na=fmtp:126 mode-set=2;start-mode=0\r\na=ptime:20\r\na=recvonly\r\nm=image 4412 udptl t38\r\na=T38FaxVersion:0\r\na=T38MaxBitRate:14400\r\n";
+static const char mdcx_patched[] = " MDCX 23330829 8@mgw MGCP 1.0\r\nC: 394b0439fb\r\nI: 1\r\nL: p:20, a:AMR, nt:IN\r\nM: recvonly\r\n\r\nv=0\r\no=- 1049380491 0 IN IP4 172.16.18.2\r\ns=-\r\nc=IN IP4 10.0.0.23\r\nt=0 0\r\nm=audio 6666 RTP/AVP 126\r\na=rtpmap:126 AMR/8000/1\r\na=fmtp:126 mode-set=2;start-mode=0\r\na=ptime:20\r\na=recvonly\r\nm=image 4412 udptl t38\r\na=T38FaxVersion:0\r\na=T38MaxBitRate:14400\r\n";
+
+
+static const char mdcx_resp[] = "200 23330829\r\n\r\nv=0\r\nc=IN IP4 172.16.18.2\r\nm=audio 4002 RTP/AVP 98\r\na=rtpmap:98 AMR/8000\r\n";
+static const char mdcx_resp_patched[] = "200 23330829\r\n\r\nv=0\r\nc=IN IP4 10.0.0.23\r\nm=audio 5555 RTP/AVP 98\r\na=rtpmap:98 AMR/8000\r\n";
+
+/* different line ending */
+static const char mdcx_resp2[] = "200 33330829\n\nv=0\nc=IN IP4 172.16.18.2\nm=audio 4002 RTP/AVP 98\na=rtpmap:98 AMR/8000\n";
+static const char mdcx_resp_patched2[] = "200 33330829\n\nv=0\nc=IN IP4 10.0.0.23\nm=audio 5555 RTP/AVP 98\na=rtpmap:98 AMR/8000\n";
+
+struct mgcp_patch_test {
+ const char *orig;
+ const char *patch;
+ const char *ip;
+ const int port;
+};
+
+static const struct mgcp_patch_test mgcp_messages[] = {
+ {
+ .orig = crcx,
+ .patch = crcx_patched,
+ .ip = "0.0.0.0",
+ .port = 2323,
+ },
+ {
+ .orig = crcx_resp,
+ .patch = crcx_resp_patched,
+ .ip = "10.0.0.1",
+ .port = 999,
+ },
+ {
+ .orig = mdcx,
+ .patch = mdcx_patched,
+ .ip = "10.0.0.23",
+ .port = 6666,
+ },
+ {
+ .orig = mdcx_resp,
+ .patch = mdcx_resp_patched,
+ .ip = "10.0.0.23",
+ .port = 5555,
+ },
+ {
+ .orig = mdcx_resp2,
+ .patch = mdcx_resp_patched2,
+ .ip = "10.0.0.23",
+ .port = 5555,
+ },
+};
diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c
new file mode 100644
index 0000000..d1db2e4
--- /dev/null
+++ b/openbsc/tests/bsc-nat/bsc_nat_test.c
@@ -0,0 +1,727 @@
+/*
+ * BSC NAT Message filtering
+ *
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+
+#include <openbsc/debug.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/bsc_nat.h>
+
+#include <osmocore/talloc.h>
+
+#include <stdio.h>
+
+/* test messages for ipa */
+static u_int8_t ipa_id[] = {
+ 0x00, 0x01, 0xfe, 0x06,
+};
+
+/* SCCP messages are below */
+static u_int8_t gsm_reset[] = {
+ 0x00, 0x12, 0xfd,
+ 0x09, 0x00, 0x03, 0x05, 0x07, 0x02, 0x42, 0xfe,
+ 0x02, 0x42, 0xfe, 0x06, 0x00, 0x04, 0x30, 0x04,
+ 0x01, 0x20,
+};
+
+static const u_int8_t gsm_reset_ack[] = {
+ 0x00, 0x13, 0xfd,
+ 0x09, 0x00, 0x03, 0x07, 0x0b, 0x04, 0x43, 0x01,
+ 0x00, 0xfe, 0x04, 0x43, 0x5c, 0x00, 0xfe, 0x03,
+ 0x00, 0x01, 0x31,
+};
+
+static const u_int8_t gsm_paging[] = {
+ 0x00, 0x20, 0xfd,
+ 0x09, 0x00, 0x03, 0x07, 0x0b, 0x04, 0x43, 0x01,
+ 0x00, 0xfe, 0x04, 0x43, 0x5c, 0x00, 0xfe, 0x10,
+ 0x00, 0x0e, 0x52, 0x08, 0x08, 0x29, 0x47, 0x10,
+ 0x02, 0x01, 0x31, 0x97, 0x61, 0x1a, 0x01, 0x06,
+};
+
+/* BSC -> MSC connection open */
+static const u_int8_t bssmap_cr[] = {
+ 0x00, 0x2c, 0xfd,
+ 0x01, 0x01, 0x02, 0x03, 0x02, 0x02, 0x04, 0x02,
+ 0x42, 0xfe, 0x0f, 0x1f, 0x00, 0x1d, 0x57, 0x05,
+ 0x08, 0x00, 0x72, 0xf4, 0x80, 0x20, 0x12, 0xc3,
+ 0x50, 0x17, 0x10, 0x05, 0x24, 0x11, 0x03, 0x33,
+ 0x19, 0xa2, 0x08, 0x29, 0x47, 0x10, 0x02, 0x01,
+ 0x31, 0x97, 0x61, 0x00
+};
+
+/* MSC -> BSC connection confirm */
+static const u_int8_t bssmap_cc[] = {
+ 0x00, 0x0a, 0xfd,
+ 0x02, 0x01, 0x02, 0x03, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
+};
+
+/* MSC -> BSC released */
+static const u_int8_t bssmap_released[] = {
+ 0x00, 0x0e, 0xfd,
+ 0x04, 0x00, 0x00, 0x03, 0x01, 0x02, 0x03, 0x00, 0x01, 0x0f,
+ 0x02, 0x23, 0x42, 0x00,
+};
+
+/* BSC -> MSC released */
+static const u_int8_t bssmap_release_complete[] = {
+ 0x00, 0x07, 0xfd,
+ 0x05, 0x01, 0x02, 0x03, 0x00, 0x00, 0x03
+};
+
+/* both directions IT timer */
+static const u_int8_t connnection_it[] = {
+ 0x00, 0x0b, 0xfd,
+ 0x10, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03,
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+/* error in both directions */
+static const u_int8_t proto_error[] = {
+ 0x00, 0x05, 0xfd,
+ 0x0f, 0x22, 0x33, 0x44, 0x00,
+};
+
+/* MGCP wrap... */
+static const u_int8_t mgcp_msg[] = {
+ 0x00, 0x03, 0xfc,
+ 0x20, 0x20, 0x20,
+};
+
+/* location updating request */
+static const u_int8_t bss_lu[] = {
+ 0x00, 0x2e, 0xfd,
+ 0x01, 0x91, 0x45, 0x14, 0x02, 0x02, 0x04, 0x02,
+ 0x42, 0xfe, 0x0f, 0x21, 0x00, 0x1f, 0x57, 0x05,
+ 0x08, 0x00, 0x72, 0xf4, 0x80, 0x20, 0x14, 0xc3,
+ 0x50, 0x17, 0x12, 0x05, 0x08, 0x70, 0x72, 0xf4,
+ 0x80, 0xff, 0xfe, 0x30, 0x08, 0x29, 0x44, 0x50,
+ 0x12, 0x03, 0x24, 0x01, 0x95, 0x00
+};
+
+/* paging response */
+static const uint8_t pag_resp[] = {
+ 0x00, 0x2c, 0xfd, 0x01, 0xe5, 0x68,
+ 0x14, 0x02, 0x02, 0x04, 0x02, 0x42, 0xfe, 0x0f,
+ 0x1f, 0x00, 0x1d, 0x57, 0x05, 0x08, 0x00, 0x72,
+ 0xf4, 0x80, 0x20, 0x16, 0xc3, 0x50, 0x17, 0x10,
+ 0x06, 0x27, 0x01, 0x03, 0x30, 0x18, 0x96, 0x08,
+ 0x29, 0x26, 0x30, 0x32, 0x11, 0x42, 0x01, 0x19,
+ 0x00
+};
+
+struct filter_result {
+ const u_int8_t *data;
+ const u_int16_t length;
+ const int dir;
+ const int result;
+};
+
+static const struct filter_result results[] = {
+ {
+ .data = ipa_id,
+ .length = ARRAY_SIZE(ipa_id),
+ .dir = DIR_MSC,
+ .result = 1,
+ },
+ {
+ .data = gsm_reset,
+ .length = ARRAY_SIZE(gsm_reset),
+ .dir = DIR_MSC,
+ .result = 1,
+ },
+ {
+ .data = gsm_reset_ack,
+ .length = ARRAY_SIZE(gsm_reset_ack),
+ .dir = DIR_BSC,
+ .result = 1,
+ },
+ {
+ .data = gsm_paging,
+ .length = ARRAY_SIZE(gsm_paging),
+ .dir = DIR_BSC,
+ .result = 0,
+ },
+ {
+ .data = bssmap_cr,
+ .length = ARRAY_SIZE(bssmap_cr),
+ .dir = DIR_MSC,
+ .result = 0,
+ },
+ {
+ .data = bssmap_cc,
+ .length = ARRAY_SIZE(bssmap_cc),
+ .dir = DIR_BSC,
+ .result = 0,
+ },
+ {
+ .data = bssmap_released,
+ .length = ARRAY_SIZE(bssmap_released),
+ .dir = DIR_MSC,
+ .result = 0,
+ },
+ {
+ .data = bssmap_release_complete,
+ .length = ARRAY_SIZE(bssmap_release_complete),
+ .dir = DIR_BSC,
+ .result = 0,
+ },
+ {
+ .data = mgcp_msg,
+ .length = ARRAY_SIZE(mgcp_msg),
+ .dir = DIR_MSC,
+ .result = 0,
+ },
+ {
+ .data = connnection_it,
+ .length = ARRAY_SIZE(connnection_it),
+ .dir = DIR_BSC,
+ .result = 0,
+ },
+ {
+ .data = connnection_it,
+ .length = ARRAY_SIZE(connnection_it),
+ .dir = DIR_MSC,
+ .result = 0,
+ },
+ {
+ .data = proto_error,
+ .length = ARRAY_SIZE(proto_error),
+ .dir = DIR_BSC,
+ .result = 0,
+ },
+ {
+ .data = proto_error,
+ .length = ARRAY_SIZE(proto_error),
+ .dir = DIR_MSC,
+ .result = 0,
+ },
+
+};
+
+static void test_filter(void)
+{
+ int i;
+
+
+ /* start testinh with proper messages */
+ fprintf(stderr, "Testing BSS Filtering.\n");
+ for (i = 0; i < ARRAY_SIZE(results); ++i) {
+ int result;
+ struct bsc_nat_parsed *parsed;
+ struct msgb *msg = msgb_alloc(4096, "test-message");
+
+ fprintf(stderr, "Going to test item: %d\n", i);
+ memcpy(msg->data, results[i].data, results[i].length);
+ msg->l2h = msgb_put(msg, results[i].length);
+
+ parsed = bsc_nat_parse(msg);
+ if (!parsed) {
+ fprintf(stderr, "FAIL: Failed to parse the message\n");
+ continue;
+ }
+
+ result = bsc_nat_filter_ipa(results[i].dir, msg, parsed);
+ if (result != results[i].result) {
+ fprintf(stderr, "FAIL: Not the expected result got: %d wanted: %d\n",
+ result, results[i].result);
+ }
+
+ msgb_free(msg);
+ }
+}
+
+#include "bsc_data.c"
+
+static void copy_to_msg(struct msgb *msg, const u_int8_t *data, unsigned int length)
+{
+ msgb_reset(msg);
+ msg->l2h = msgb_put(msg, length);
+ memcpy(msg->l2h, data, msgb_l2len(msg));
+}
+
+#define VERIFY(con_found, con, msg, ver, str) \
+ if (!con_found || con_found->bsc != con) { \
+ fprintf(stderr, "Failed to find the con: %p\n", con_found); \
+ abort(); \
+ } \
+ if (memcmp(msg->data, ver, sizeof(ver)) != 0) { \
+ fprintf(stderr, "Failed to patch the %s msg.\n", str); \
+ abort(); \
+ }
+
+/* test conn tracking once */
+static void test_contrack()
+{
+ struct bsc_nat *nat;
+ struct bsc_connection *con;
+ struct sccp_connections *con_found;
+ struct sccp_connections *rc_con;
+ struct bsc_nat_parsed *parsed;
+ struct msgb *msg;
+
+ fprintf(stderr, "Testing connection tracking.\n");
+ nat = bsc_nat_alloc();
+ con = bsc_connection_alloc(nat);
+ con->cfg = bsc_config_alloc(nat, "foo", 23);
+ msg = msgb_alloc(4096, "test");
+
+ /* 1.) create a connection */
+ copy_to_msg(msg, bsc_cr, sizeof(bsc_cr));
+ parsed = bsc_nat_parse(msg);
+ con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
+ if (con_found != NULL) {
+ fprintf(stderr, "Con should not exist %p\n", con_found);
+ abort();
+ }
+ rc_con = create_sccp_src_ref(con, parsed);
+ if (!rc_con) {
+ fprintf(stderr, "Failed to create a ref\n");
+ abort();
+ }
+ con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
+ if (!con_found || con_found->bsc != con) {
+ fprintf(stderr, "Failed to find the con: %p\n", con_found);
+ abort();
+ }
+ if (con_found != rc_con) {
+ fprintf(stderr, "Failed to find the right connection.\n");
+ abort();
+ }
+ if (memcmp(msg->data, bsc_cr_patched, sizeof(bsc_cr_patched)) != 0) {
+ fprintf(stderr, "Failed to patch the BSC CR msg.\n");
+ abort();
+ }
+ talloc_free(parsed);
+
+ /* 2.) get the cc */
+ copy_to_msg(msg, msc_cc, sizeof(msc_cc));
+ parsed = bsc_nat_parse(msg);
+ con_found = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
+ VERIFY(con_found, con, msg, msc_cc_patched, "MSC CC");
+ if (update_sccp_src_ref(con_found, parsed) != 0) {
+ fprintf(stderr, "Failed to update the SCCP con.\n");
+ abort();
+ }
+
+ /* 3.) send some data */
+ copy_to_msg(msg, bsc_dtap, sizeof(bsc_dtap));
+ parsed = bsc_nat_parse(msg);
+ con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
+ VERIFY(con_found, con, msg, bsc_dtap_patched, "BSC DTAP");
+
+ /* 4.) receive some data */
+ copy_to_msg(msg, msc_dtap, sizeof(msc_dtap));
+ parsed = bsc_nat_parse(msg);
+ con_found = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
+ VERIFY(con_found, con, msg, msc_dtap_patched, "MSC DTAP");
+
+ /* 5.) close the connection */
+ copy_to_msg(msg, msc_rlsd, sizeof(msc_rlsd));
+ parsed = bsc_nat_parse(msg);
+ con_found = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
+ VERIFY(con_found, con, msg, msc_rlsd_patched, "MSC RLSD");
+
+ /* 6.) confirm the connection close */
+ copy_to_msg(msg, bsc_rlc, sizeof(bsc_rlc));
+ parsed = bsc_nat_parse(msg);
+ con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
+ if (!con_found || con_found->bsc != con) {
+ fprintf(stderr, "Failed to find the con: %p\n", con_found);
+ abort();
+ }
+ if (memcmp(msg->data, bsc_rlc_patched, sizeof(bsc_rlc_patched)) != 0) {
+ fprintf(stderr, "Failed to patch the BSC CR msg.\n");
+ abort();
+ }
+ remove_sccp_src_ref(con, msg, parsed);
+ talloc_free(parsed);
+
+ copy_to_msg(msg, bsc_rlc, sizeof(bsc_rlc));
+ parsed = bsc_nat_parse(msg);
+ con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
+
+ /* verify that it is gone */
+ if (con_found != NULL) {
+ fprintf(stderr, "Con should be gone. %p\n", con_found);
+ abort();
+ }
+ talloc_free(parsed);
+
+
+ talloc_free(nat);
+ msgb_free(msg);
+}
+
+static void test_paging(void)
+{
+ int lac;
+ struct bsc_nat *nat;
+ struct bsc_connection *con;
+ struct bsc_nat_parsed *parsed;
+ struct bsc_config cfg;
+ struct msgb *msg;
+
+ fprintf(stderr, "Testing paging by lac.\n");
+
+ nat = bsc_nat_alloc();
+ con = bsc_connection_alloc(nat);
+ con->cfg = &cfg;
+ cfg.lac = 23;
+ con->authenticated = 1;
+ llist_add(&con->list_entry, &nat->bsc_connections);
+ msg = msgb_alloc(4096, "test");
+
+ /* Test completely bad input */
+ copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
+ if (bsc_nat_find_bsc(nat, msg, &lac) != 0) {
+ fprintf(stderr, "Should have not found anything.\n");
+ abort();
+ }
+
+ /* Test it by not finding it */
+ copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
+ parsed = bsc_nat_parse(msg);
+ if (bsc_nat_find_bsc(nat, msg, &lac) != 0) {
+ fprintf(stderr, "Should have not found aynthing.\n");
+ abort();
+ }
+ talloc_free(parsed);
+
+ /* Test by finding it */
+ cfg.lac = 8213;
+ copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
+ parsed = bsc_nat_parse(msg);
+ if (bsc_nat_find_bsc(nat, msg, &lac) != con) {
+ fprintf(stderr, "Should have found it.\n");
+ abort();
+ }
+ talloc_free(parsed);
+}
+
+static void test_mgcp_ass_tracking(void)
+{
+ struct bsc_connection *bsc;
+ struct bsc_nat *nat;
+ struct sccp_connections con;
+ struct bsc_nat_parsed *parsed;
+ struct msgb *msg;
+
+ fprintf(stderr, "Testing MGCP.\n");
+ memset(&con, 0, sizeof(con));
+
+ nat = bsc_nat_alloc();
+ nat->bsc_endpoints = talloc_zero_array(nat,
+ struct bsc_endpoint,
+ 33);
+ bsc = bsc_connection_alloc(nat);
+ bsc->cfg = bsc_config_alloc(nat, "foo", 2323);
+ con.bsc = bsc;
+
+ msg = msgb_alloc(4096, "foo");
+ copy_to_msg(msg, ass_cmd, sizeof(ass_cmd));
+ parsed = bsc_nat_parse(msg);
+ if (bsc_mgcp_assign(&con, msg) != 0) {
+ fprintf(stderr, "Failed to handle assignment.\n");
+ abort();
+ }
+
+ if (con.msc_timeslot != 21) {
+ fprintf(stderr, "Timeslot should be 21.\n");
+ abort();
+ }
+
+ if (con.bsc_timeslot != 21) {
+ fprintf(stderr, "Assigned timeslot should have been 21.\n");
+ abort();
+ }
+ talloc_free(parsed);
+
+ bsc_mgcp_dlcx(&con);
+ if (con.bsc_timeslot != -1 || con.msc_timeslot != -1) {
+ fprintf(stderr, "Clearing should remove the mapping.\n");
+ abort();
+ }
+
+ talloc_free(nat);
+}
+
+/* test the code to find a given connection */
+static void test_mgcp_find(void)
+{
+ struct bsc_nat *nat;
+ struct bsc_connection *con;
+ struct sccp_connections *sccp_con;
+
+ fprintf(stderr, "Testing finding of a BSC Connection\n");
+
+ nat = bsc_nat_alloc();
+ con = bsc_connection_alloc(nat);
+ llist_add(&con->list_entry, &nat->bsc_connections);
+
+ sccp_con = talloc_zero(con, struct sccp_connections);
+ sccp_con->msc_timeslot = 12;
+ sccp_con->bsc_timeslot = 12;
+ sccp_con->bsc = con;
+ llist_add(&sccp_con->list_entry, &nat->sccp_connections);
+
+ if (bsc_mgcp_find_con(nat, 11) != NULL) {
+ fprintf(stderr, "Found the wrong connection.\n");
+ abort();
+ }
+
+ if (bsc_mgcp_find_con(nat, 12) != sccp_con) {
+ fprintf(stderr, "Didn't find the connection\n");
+ abort();
+ }
+
+ sccp_con->msc_timeslot = 0;
+ sccp_con->bsc_timeslot = 0;
+ if (bsc_mgcp_find_con(nat, 1) != sccp_con) {
+ fprintf(stderr, "Didn't find the connection\n");
+ abort();
+ }
+
+ /* free everything */
+ talloc_free(nat);
+}
+
+static void test_mgcp_rewrite(void)
+{
+ int i;
+ struct msgb *output;
+ fprintf(stderr, "Test rewriting MGCP messages.\n");
+
+ for (i = 0; i < ARRAY_SIZE(mgcp_messages); ++i) {
+ const char *orig = mgcp_messages[i].orig;
+ const char *patc = mgcp_messages[i].patch;
+ const char *ip = mgcp_messages[i].ip;
+ const int port = mgcp_messages[i].port;
+
+ char *input = strdup(orig);
+
+ output = bsc_mgcp_rewrite(input, strlen(input), ip, port);
+ if (msgb_l2len(output) != strlen(patc)) {
+ fprintf(stderr, "Wrong sizes for test: %d %d != %d != %d\n", i, msgb_l2len(output), strlen(patc), strlen(orig));
+ fprintf(stderr, "String '%s' vs '%s'\n", (const char *) output->l2h, patc);
+ abort();
+ }
+
+ if (memcmp(output->l2h, patc, msgb_l2len(output)) != 0) {
+ fprintf(stderr, "Broken on %d msg: '%s'\n", i, (const char *) output->l2h);
+ abort();
+ }
+
+ msgb_free(output);
+ free(input);
+ }
+}
+
+static void test_mgcp_parse(void)
+{
+ int code, ci;
+ char transaction[60];
+
+ fprintf(stderr, "Test MGCP response parsing.\n");
+
+ if (bsc_mgcp_parse_response(crcx_resp, &code, transaction) != 0) {
+ fprintf(stderr, "Failed to parse CRCX resp.\n");
+ abort();
+ }
+
+ if (code != 200) {
+ fprintf(stderr, "Failed to parse the CODE properly. Got: %d\n", code);
+ abort();
+ }
+
+ if (strcmp(transaction, "23265295") != 0) {
+ fprintf(stderr, "Failed to parse transaction id: '%s'\n", transaction);
+ abort();
+ }
+
+ ci = bsc_mgcp_extract_ci(crcx_resp);
+ if (ci != 1) {
+ fprintf(stderr, "Failed to parse the CI. Got: %d\n", ci);
+ abort();
+ }
+}
+
+struct cr_filter {
+ const u_int8_t *data;
+ int length;
+ int result;
+ int contype;
+
+ const char *bsc_imsi_allow;
+ const char *bsc_imsi_deny;
+ const char *nat_imsi_deny;
+};
+
+static struct cr_filter cr_filter[] = {
+ {
+ .data = bssmap_cr,
+ .length = sizeof(bssmap_cr),
+ .result = 0,
+ .contype = NAT_CON_TYPE_CM_SERV_REQ,
+ },
+ {
+ .data = bss_lu,
+ .length = sizeof(bss_lu),
+ .result = 0,
+ .contype = NAT_CON_TYPE_LU,
+ },
+ {
+ .data = pag_resp,
+ .length = sizeof(pag_resp),
+ .result = 0,
+ .contype = NAT_CON_TYPE_PAG_RESP,
+ },
+ {
+ /* nat deny is before blank/null BSC */
+ .data = bss_lu,
+ .length = sizeof(bss_lu),
+ .result = -3,
+ .nat_imsi_deny = "[0-9]*",
+ .contype = NAT_CON_TYPE_LU,
+ },
+ {
+ /* BSC allow is before NAT deny */
+ .data = bss_lu,
+ .length = sizeof(bss_lu),
+ .result = 0,
+ .nat_imsi_deny = "[0-9]*",
+ .bsc_imsi_allow = "2440[0-9]*",
+ .contype = NAT_CON_TYPE_LU,
+ },
+ {
+ /* BSC allow is before NAT deny */
+ .data = bss_lu,
+ .length = sizeof(bss_lu),
+ .result = 0,
+ .bsc_imsi_allow = "[0-9]*",
+ .nat_imsi_deny = "[0-9]*",
+ .contype = NAT_CON_TYPE_LU,
+ },
+ {
+ /* filter as deny is first */
+ .data = bss_lu,
+ .length = sizeof(bss_lu),
+ .result = -2,
+ .bsc_imsi_deny = "[0-9]*",
+ .bsc_imsi_allow = "[0-9]*",
+ .nat_imsi_deny = "[0-9]*",
+ .contype = NAT_CON_TYPE_LU,
+ },
+
+};
+
+static void test_cr_filter()
+{
+ int i, res, contype;
+ struct msgb *msg = msgb_alloc(4096, "test_cr_filter");
+ struct bsc_nat_parsed *parsed;
+ struct bsc_nat_acc_lst *nat_lst, *bsc_lst;
+ struct bsc_nat_acc_lst_entry *nat_entry, *bsc_entry;
+
+ struct bsc_nat *nat = bsc_nat_alloc();
+ struct bsc_connection *bsc = bsc_connection_alloc(nat);
+ bsc->cfg = bsc_config_alloc(nat, "foo", 1234);
+ bsc->cfg->acc_lst_name = "bsc";
+ nat->acc_lst_name = "nat";
+
+ nat_lst = bsc_nat_acc_lst_get(nat, "nat");
+ bsc_lst = bsc_nat_acc_lst_get(nat, "bsc");
+
+ bsc_entry = bsc_nat_acc_lst_entry_create(bsc_lst);
+ nat_entry = bsc_nat_acc_lst_entry_create(nat_lst);
+
+ for (i = 0; i < ARRAY_SIZE(cr_filter); ++i) {
+ msgb_reset(msg);
+ copy_to_msg(msg, cr_filter[i].data, cr_filter[i].length);
+
+ nat_lst = bsc_nat_acc_lst_get(nat, "nat");
+ bsc_lst = bsc_nat_acc_lst_get(nat, "bsc");
+
+ bsc_parse_reg(nat_entry, &nat_entry->imsi_deny_re, &nat_entry->imsi_deny,
+ cr_filter[i].nat_imsi_deny ? 1 : 0,
+ &cr_filter[i].nat_imsi_deny);
+ bsc_parse_reg(bsc_entry, &bsc_entry->imsi_allow_re, &bsc_entry->imsi_allow,
+ cr_filter[i].bsc_imsi_allow ? 1 : 0,
+ &cr_filter[i].bsc_imsi_allow);
+ bsc_parse_reg(bsc_entry, &bsc_entry->imsi_deny_re, &bsc_entry->imsi_deny,
+ cr_filter[i].bsc_imsi_deny ? 1 : 0,
+ &cr_filter[i].bsc_imsi_deny);
+
+ parsed = bsc_nat_parse(msg);
+ if (!parsed) {
+ fprintf(stderr, "FAIL: Failed to parse the message\n");
+ abort();
+ }
+
+ res = bsc_nat_filter_sccp_cr(bsc, msg, parsed, &contype);
+ if (res != cr_filter[i].result) {
+ fprintf(stderr, "FAIL: Wrong result %d for test %d.\n", res, i);
+ abort();
+ }
+
+ if (contype != cr_filter[i].contype) {
+ fprintf(stderr, "FAIL: Wrong contype %d for test %d.\n", res, contype);
+ abort();
+ }
+
+ talloc_free(parsed);
+ }
+
+ msgb_free(msg);
+}
+
+int main(int argc, char **argv)
+{
+ struct log_target *stderr_target;
+
+ stderr_target = log_target_create_stderr();
+ log_add_target(stderr_target);
+ log_set_all_filter(stderr_target, 1);
+
+ test_filter();
+ test_contrack();
+ test_paging();
+ test_mgcp_ass_tracking();
+ test_mgcp_find();
+ test_mgcp_rewrite();
+ test_mgcp_parse();
+ test_cr_filter();
+ return 0;
+}
+
+void input_event()
+{}
+int nm_state_event()
+{
+ return -1;
+}
+
+int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id)
+{
+ return -1;
+}
diff --git a/rrlp-ephemeris/.gitignore b/rrlp-ephemeris/.gitignore
deleted file mode 100644
index 88b45e4..0000000
--- a/rrlp-ephemeris/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-asn1_gen/*
-*.o
-*.a
-rrlp-test
diff --git a/rrlp-ephemeris/COPYING b/rrlp-ephemeris/COPYING
deleted file mode 100644
index 8d7088e..0000000
--- a/rrlp-ephemeris/COPYING
+++ /dev/null
@@ -1,2 +0,0 @@
-See the included gpl-2.0.txt or gpl-3.0.txt depending on your
-preferences.
diff --git a/rrlp-ephemeris/Makefile b/rrlp-ephemeris/Makefile
deleted file mode 100644
index 742cac7..0000000
--- a/rrlp-ephemeris/Makefile
+++ /dev/null
@@ -1,44 +0,0 @@
-
-ASN1C=../../../tmp/rrlp/asn1c/asn1c/asn1c
-ASN1_INCLUDE=/home/tnt/tmp/rrlp/asn1c/skeletons
-CC=gcc
-CFLAGS=-I$(ASN1_INCLUDE) -Iasn1_gen -O3 -Wall
-
-ASN1_FILES=$(wildcard asn1/*.asn)
-
-
-all: rrlp-test
-
-
-rrlp-test: libgsm-asn1.a gps.o ubx.o ubx-parse.o rrlp.o main.o
- $(CC) -o $@ gps.o ubx.o ubx-parse.o rrlp.o main.o -L. -lgsm-asn1 -lm
-
-
-#
-# ASN1 file autogeneration (need recursive makefile call)
-#
-
-ASN1_SOURCES = $(wildcard asn1_gen/*.c)
-ASN1_OBJECTS = $(ASN1_SOURCES:.c=.o)
-
-libgsm-asn1.a: $(ASN1_FILES)
- mkdir -p asn1_gen && \
- cd asn1_gen && \
- $(ASN1C) -fskeletons-copy -fnative-types -gen-PER $(addprefix ../,$^)
- @rm asn1_gen/converter-sample.c asn1_gen/Makefile.am.sample
- @$(MAKE) libgsm-asn1.a.submake
-
-libgsm-asn1.a.submake: $(ASN1_OBJECTS)
- $(AR) rcs libgsm-asn1.a $^
-
-.PHONY: libgsm-asn1.a.submake
-
-
-#
-# Clean
-#
-
-clean:
- rm -Rf asn1_gen
- rm -f libgsm-asn1.a *.o rrlp-test
-
diff --git a/rrlp-ephemeris/asn1/MAP-BS-Code.asn b/rrlp-ephemeris/asn1/MAP-BS-Code.asn
deleted file mode 100644
index 1d25366..0000000
--- a/rrlp-ephemeris/asn1/MAP-BS-Code.asn
+++ /dev/null
@@ -1,131 +0,0 @@
--- $Id: MAP-BS-Code.asn 28149 2009-04-25 17:45:34Z etxrab $
--- 3GPP TS 29.002 V8.9.0 (2009-04)
--- 17.7.10 Bearer Service Codes
-
-MAP-BS-Code {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-BS-Code (20) version11 (11)}
-
-DEFINITIONS
-
-::=
-
-BEGIN
-
-BearerServiceCode ::= OCTET STRING (SIZE (1))
- -- This type is used to represent the code identifying a single
- -- bearer service, a group of bearer services, or all bearer
- -- services. The services are defined in TS 3GPP TS 22.002 [3].
- -- The internal structure is defined as follows:
- --
- -- plmn-specific bearer services:
- -- bits 87654321: defined by the HPLMN operator
-
- -- rest of bearer services:
- -- bit 8: 0 (unused)
- -- bits 7654321: group (bits 7654), and rate, if applicable
- -- (bits 321)
-
-Ext-BearerServiceCode ::= OCTET STRING (SIZE (1..5))
- -- This type is used to represent the code identifying a single
- -- bearer service, a group of bearer services, or all bearer
- -- services. The services are defined in TS 3GPP TS 22.002 [3].
- -- The internal structure is defined as follows:
- --
- -- OCTET 1:
- -- plmn-specific bearer services:
- -- bits 87654321: defined by the HPLMN operator
- --
- -- rest of bearer services:
- -- bit 8: 0 (unused)
- -- bits 7654321: group (bits 7654), and rate, if applicable
- -- (bits 321)
-
- -- OCTETS 2-5: reserved for future use. If received the
- -- Ext-TeleserviceCode shall be
- -- treated according to the exception handling defined for the
- -- operation that uses this type.
-
-
- -- Ext-BearerServiceCode includes all values defined for BearerServiceCode.
-
-allBearerServices BearerServiceCode ::= '00000000'B
-
-allDataCDA-Services BearerServiceCode ::= '00010000'B
-dataCDA-300bps BearerServiceCode ::= '00010001'B
-dataCDA-1200bps BearerServiceCode ::= '00010010'B
-dataCDA-1200-75bps BearerServiceCode ::= '00010011'B
-dataCDA-2400bps BearerServiceCode ::= '00010100'B
-dataCDA-4800bps BearerServiceCode ::= '00010101'B
-dataCDA-9600bps BearerServiceCode ::= '00010110'B
-general-dataCDA BearerServiceCode ::= '00010111'B
-
-allDataCDS-Services BearerServiceCode ::= '00011000'B
-dataCDS-1200bps BearerServiceCode ::= '00011010'B
-dataCDS-2400bps BearerServiceCode ::= '00011100'B
-dataCDS-4800bps BearerServiceCode ::= '00011101'B
-dataCDS-9600bps BearerServiceCode ::= '00011110'B
-general-dataCDS BearerServiceCode ::= '00011111'B
-
-allPadAccessCA-Services BearerServiceCode ::= '00100000'B
-padAccessCA-300bps BearerServiceCode ::= '00100001'B
-padAccessCA-1200bps BearerServiceCode ::= '00100010'B
-padAccessCA-1200-75bps BearerServiceCode ::= '00100011'B
-padAccessCA-2400bps BearerServiceCode ::= '00100100'B
-padAccessCA-4800bps BearerServiceCode ::= '00100101'B
-padAccessCA-9600bps BearerServiceCode ::= '00100110'B
-general-padAccessCA BearerServiceCode ::= '00100111'B
-
-allDataPDS-Services BearerServiceCode ::= '00101000'B
-dataPDS-2400bps BearerServiceCode ::= '00101100'B
-dataPDS-4800bps BearerServiceCode ::= '00101101'B
-dataPDS-9600bps BearerServiceCode ::= '00101110'B
-general-dataPDS BearerServiceCode ::= '00101111'B
-
-allAlternateSpeech-DataCDA BearerServiceCode ::= '00110000'B
-
-allAlternateSpeech-DataCDS BearerServiceCode ::= '00111000'B
-
-allSpeechFollowedByDataCDA BearerServiceCode ::= '01000000'B
-
-allSpeechFollowedByDataCDS BearerServiceCode ::= '01001000'B
-
--- The following non-hierarchical Compound Bearer Service
--- Groups are defined in TS 3GPP TS 22.030:
-allDataCircuitAsynchronous BearerServiceCode ::= '01010000'B
- -- covers "allDataCDA-Services", "allAlternateSpeech-DataCDA" and
- -- "allSpeechFollowedByDataCDA"
-allAsynchronousServices BearerServiceCode ::= '01100000'B
- -- covers "allDataCDA-Services", "allAlternateSpeech-DataCDA",
- -- "allSpeechFollowedByDataCDA" and "allPadAccessCDA-Services"
-allDataCircuitSynchronous BearerServiceCode ::= '01011000'B
- -- covers "allDataCDS-Services", "allAlternateSpeech-DataCDS" and
- -- "allSpeechFollowedByDataCDS"
-allSynchronousServices BearerServiceCode ::= '01101000'B
- -- covers "allDataCDS-Services", "allAlternateSpeech-DataCDS",
- -- "allSpeechFollowedByDataCDS" and "allDataPDS-Services"
---
--- Compound Bearer Service Group Codes are only used in call
--- independent supplementary service operations, i.e. they
--- are not used in InsertSubscriberData or in
--- DeleteSubscriberData messages.
-
-allPLMN-specificBS BearerServiceCode ::= '11010000'B
-plmn-specificBS-1 BearerServiceCode ::= '11010001'B
-plmn-specificBS-2 BearerServiceCode ::= '11010010'B
-plmn-specificBS-3 BearerServiceCode ::= '11010011'B
-plmn-specificBS-4 BearerServiceCode ::= '11010100'B
-plmn-specificBS-5 BearerServiceCode ::= '11010101'B
-plmn-specificBS-6 BearerServiceCode ::= '11010110'B
-plmn-specificBS-7 BearerServiceCode ::= '11010111'B
-plmn-specificBS-8 BearerServiceCode ::= '11011000'B
-plmn-specificBS-9 BearerServiceCode ::= '11011001'B
-plmn-specificBS-A BearerServiceCode ::= '11011010'B
-plmn-specificBS-B BearerServiceCode ::= '11011011'B
-plmn-specificBS-C BearerServiceCode ::= '11011100'B
-plmn-specificBS-D BearerServiceCode ::= '11011101'B
-plmn-specificBS-E BearerServiceCode ::= '11011110'B
-plmn-specificBS-F BearerServiceCode ::= '11011111'B
-
-END
-
diff --git a/rrlp-ephemeris/asn1/MAP-CommonDataTypes.asn b/rrlp-ephemeris/asn1/MAP-CommonDataTypes.asn
deleted file mode 100644
index f3d202e..0000000
--- a/rrlp-ephemeris/asn1/MAP-CommonDataTypes.asn
+++ /dev/null
@@ -1,633 +0,0 @@
--- $Id: MAP-CommonDataTypes.asn 30470 2009-10-10 12:37:56Z krj $
--- 3GPP TS 29.002 V8.9.0 (2009-04)
--- 17.7.8 Common data types
-
-MAP-CommonDataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-CommonDataTypes (18) version11 (11)}
-
-DEFINITIONS
-
-IMPLICIT TAGS
-
-::=
-
-BEGIN
-
-EXPORTS
-
- -- general data types and values
- AddressString,
- ISDN-AddressString,
- maxISDN-AddressLength,
- FTN-AddressString,
- ISDN-SubaddressString,
- ExternalSignalInfo,
- Ext-ExternalSignalInfo,
-AccessNetworkSignalInfo,
- SignalInfo,
- maxSignalInfoLength,
- AlertingPattern,
- TBCD-STRING,
-
- -- data types for numbering and identification
- IMSI,
- TMSI,
- Identity,
- SubscriberId,
- IMEI,
- HLR-List,
- LMSI,
- GlobalCellId,
- NetworkResource,
- AdditionalNetworkResource,
- NAEA-PreferredCI,
- NAEA-CIC,
- ASCI-CallReference,
- SubscriberIdentity,
- PLMN-Id,
-
- -- data types for CAMEL
- CellGlobalIdOrServiceAreaIdOrLAI,
- CellGlobalIdOrServiceAreaIdFixedLength,
- LAIFixedLength,
-
- -- data types for subscriber management
- BasicServiceCode,
- Ext-BasicServiceCode,
- EMLPP-Info,
- EMLPP-Priority,
- MC-SS-Info,
- MaxMC-Bearers,
- MC-Bearers,
- Ext-SS-Status,
-
- -- data types for geographic location
- AgeOfLocationInformation,
- LCSClientExternalID,
- LCSClientInternalID,
- LCSServiceTypeID,
---- WS added exports needed by gsm_map.asn (extra asn1 file to handle older prot. ver.)
- ProtocolId,
- LCSServiceTypeID
-;
-
-IMPORTS
- TeleserviceCode,
- Ext-TeleserviceCode
-FROM MAP-TS-Code {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-TS-Code (19) version11 (11)}
-
- BearerServiceCode,
- Ext-BearerServiceCode
-FROM MAP-BS-Code {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-BS-Code (20) version11 (11)}
-
- SS-Code
-FROM MAP-SS-Code {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-SS-Code (15) version11 (11)}
-
- ExtensionContainer
-FROM MAP-ExtensionDataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
-;
-
-
--- general data types
-
-TBCD-STRING ::= OCTET STRING
- -- This type (Telephony Binary Coded Decimal String) is used to
- -- represent several digits from 0 through 9, *, #, a, b, c, two
- -- digits per octet, each digit encoded 0000 to 1001 (0 to 9),
- -- 1010 (*), 1011 (#), 1100 (a), 1101 (b) or 1110 (c); 1111 used
- -- as filler when there is an odd number of digits.
-
- -- bits 8765 of octet n encoding digit 2n
- -- bits 4321 of octet n encoding digit 2(n-1) +1
-
-AddressString ::= OCTET STRING (SIZE (1..maxAddressLength))
- -- This type is used to represent a number for addressing
- -- purposes. It is composed of
- -- a) one octet for nature of address, and numbering plan
- -- indicator.
- -- b) digits of an address encoded as TBCD-String.
-
- -- a) The first octet includes a one bit extension indicator, a
- -- 3 bits nature of address indicator and a 4 bits numbering
- -- plan indicator, encoded as follows:
-
- -- bit 8: 1 (no extension)
-
- -- bits 765: nature of address indicator
- -- 000 unknown
- -- 001 international number
- -- 010 national significant number
- -- 011 network specific number
- -- 100 subscriber number
- -- 101 reserved
- -- 110 abbreviated number
- -- 111 reserved for extension
-
- -- bits 4321: numbering plan indicator
- -- 0000 unknown
- -- 0001 ISDN/Telephony Numbering Plan (Rec ITU-T E.164)
- -- 0010 spare
- -- 0011 data numbering plan (ITU-T Rec X.121)
- -- 0100 telex numbering plan (ITU-T Rec F.69)
- -- 0101 spare
- -- 0110 land mobile numbering plan (ITU-T Rec E.212)
- -- 0111 spare
- -- 1000 national numbering plan
- -- 1001 private numbering plan
- -- 1111 reserved for extension
-
- -- all other values are reserved.
-
- -- b) The following octets representing digits of an address
- -- encoded as a TBCD-STRING.
-
-maxAddressLength INTEGER ::= 20
-
-ISDN-AddressString ::=
- AddressString (SIZE (1..maxISDN-AddressLength))
- -- This type is used to represent ISDN numbers.
-
-maxISDN-AddressLength INTEGER ::= 9
-
-FTN-AddressString ::=
- AddressString (SIZE (1..maxFTN-AddressLength))
- -- This type is used to represent forwarded-to numbers.
- -- If NAI = international the first digits represent the country code (CC)
- -- and the network destination code (NDC) as for E.164.
-
-maxFTN-AddressLength INTEGER ::= 15
-
-ISDN-SubaddressString ::=
- OCTET STRING (SIZE (1..maxISDN-SubaddressLength))
- -- This type is used to represent ISDN subaddresses.
- -- It is composed of
- -- a) one octet for type of subaddress and odd/even indicator.
- -- b) 20 octets for subaddress information.
-
- -- a) The first octet includes a one bit extension indicator, a
- -- 3 bits type of subaddress and a one bit odd/even indicator,
- -- encoded as follows:
-
- -- bit 8: 1 (no extension)
-
- -- bits 765: type of subaddress
- -- 000 NSAP (X.213/ISO 8348 AD2)
- -- 010 User Specified
- -- All other values are reserved
-
- -- bit 4: odd/even indicator
- -- 0 even number of address signals
- -- 1 odd number of address signals
- -- The odd/even indicator is used when the type of subaddress
- -- is "user specified" and the coding is BCD.
-
- -- bits 321: 000 (unused)
-
- -- b) Subaddress information.
- -- The NSAP X.213/ISO8348AD2 address shall be formatted as specified
- -- by octet 4 which contains the Authority and Format Identifier
- -- (AFI). The encoding is made according to the "preferred binary
- -- encoding" as defined in X.213/ISO834AD2. For the definition
- -- of this type of subaddress, see ITU-T Rec I.334.
-
- -- For User-specific subaddress, this field is encoded according
- -- to the user specification, subject to a maximum length of 20
- -- octets. When interworking with X.25 networks BCD coding should
- -- be applied.
-
-maxISDN-SubaddressLength INTEGER ::= 21
-
-ExternalSignalInfo ::= SEQUENCE {
- protocolId ProtocolId,
- signalInfo SignalInfo,
- -- Information about the internal structure is given in
- -- clause 7.6.9.
- extensionContainer ExtensionContainer OPTIONAL,
- -- extensionContainer must not be used in version 2
- ...}
-
-SignalInfo ::= OCTET STRING (SIZE (1..maxSignalInfoLength))
-
-maxSignalInfoLength INTEGER ::= 200
- -- This NamedValue represents the theoretical maximum number of octets which is
- -- available to carry a single instance of the SignalInfo data type,
- -- without requiring segmentation to cope with the network layer service.
- -- However, the actual maximum size available for an instance of the data
- -- type may be lower, especially when other information elements
- -- have to be included in the same component.
-
-ProtocolId ::= ENUMERATED {
- gsm-0408 (1),
- gsm-0806 (2),
- gsm-BSSMAP (3),
- -- Value 3 is reserved and must not be used
- ets-300102-1 (4)}
-
-Ext-ExternalSignalInfo ::= SEQUENCE {
- ext-ProtocolId Ext-ProtocolId,
- signalInfo SignalInfo,
- -- Information about the internal structure is given in
- -- clause 7.6.9.10
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-Ext-ProtocolId ::= ENUMERATED {
- ets-300356 (1),
- ...
- }
--- exception handling:
--- For Ext-ExternalSignalInfo sequences containing this parameter with any
--- other value than the ones listed the receiver shall ignore the whole
--- Ext-ExternalSignalInfo sequence.
-
-AccessNetworkSignalInfo ::= SEQUENCE {
- accessNetworkProtocolId AccessNetworkProtocolId,
- signalInfo LongSignalInfo,
- -- Information about the internal structure is given in clause 7.6.9.1
-
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-LongSignalInfo ::= OCTET STRING (SIZE (1..maxLongSignalInfoLength))
-
-maxLongSignalInfoLength INTEGER ::= 2560
- -- This Named Value represents the maximum number of octets which is available
- -- to carry a single instance of the LongSignalInfo data type using
- -- White Book SCCP with the maximum number of segments.
- -- It takes account of the octets used by the lower layers of the protocol, and
- -- other information elements which may be included in the same component.
-
-AccessNetworkProtocolId ::= ENUMERATED {
- ts3G-48006 (1),
- ts3G-25413 (2),
- ...}
- -- exception handling:
- -- For AccessNetworkSignalInfo sequences containing this parameter with any
- -- other value than the ones listed the receiver shall ignore the whole
- -- AccessNetworkSignalInfo sequence.
-
-AlertingPattern ::= OCTET STRING (SIZE (1) )
- -- This type is used to represent Alerting Pattern
-
- -- bits 8765 : 0000 (unused)
-
- -- bits 43 : type of Pattern
- -- 00 level
- -- 01 category
- -- 10 category
- -- all other values are reserved.
-
- -- bits 21 : type of alerting
-
-alertingLevel-0 AlertingPattern ::= '00000000'B
-alertingLevel-1 AlertingPattern ::= '00000001'B
-alertingLevel-2 AlertingPattern ::= '00000010'B
- -- all other values of Alerting level are reserved
- -- Alerting Levels are defined in GSM 02.07
-
-alertingCategory-1 AlertingPattern ::= '00000100'B
-alertingCategory-2 AlertingPattern ::= '00000101'B
-alertingCategory-3 AlertingPattern ::= '00000110'B
-alertingCategory-4 AlertingPattern ::= '00000111'B
-alertingCategory-5 AlertingPattern ::= '00001000'B
- -- all other values of Alerting Category are reserved
- -- Alerting categories are defined in GSM 02.07
-
--- data types for numbering and identification
-
-IMSI ::= TBCD-STRING (SIZE (3..8))
- -- digits of MCC, MNC, MSIN are concatenated in this order.
-
-Identity ::= CHOICE {
- imsi IMSI,
- imsi-WithLMSI IMSI-WithLMSI}
-
-IMSI-WithLMSI ::= SEQUENCE {
- imsi IMSI,
- lmsi LMSI,
- -- a special value 00000000 indicates that the LMSI is not in use
- ...}
-
-ASCI-CallReference ::= TBCD-STRING (SIZE (1..8))
- -- digits of VGCS/VBS-area,Group-ID are concatenated in this order if there is a
- -- VGCS/VBS-area.
-
-TMSI ::= OCTET STRING (SIZE (1..4))
-
-SubscriberId ::= CHOICE {
- imsi [0] IMSI,
- tmsi [1] TMSI}
-
-IMEI ::= TBCD-STRING (SIZE (8))
- -- Refers to International Mobile Station Equipment Identity
- -- and Software Version Number (SVN) defined in TS 3GPP TS 23.003 [17].
- -- If the SVN is not present the last octet shall contain the
- -- digit 0 and a filler.
- -- If present the SVN shall be included in the last octet.
-
-HLR-Id ::= IMSI
- -- leading digits of IMSI, i.e. (MCC, MNC, leading digits of
- -- MSIN) forming HLR Id defined in TS 3GPP TS 23.003 [17].
-
-HLR-List ::= SEQUENCE SIZE (1..maxNumOfHLR-Id) OF
- HLR-Id
-
-maxNumOfHLR-Id INTEGER ::= 50
-
-LMSI ::= OCTET STRING (SIZE (4))
-
-GlobalCellId ::= OCTET STRING (SIZE (5..7))
- -- Refers to Cell Global Identification defined in TS 3GPP TS 23.003 [17].
- -- The internal structure is defined as follows:
- -- octet 1 bits 4321 Mobile Country Code 1st digit
- -- bits 8765 Mobile Country Code 2nd digit
- -- octet 2 bits 4321 Mobile Country Code 3rd digit
- -- bits 8765 Mobile Network Code 3rd digit
- -- or filler (1111) for 2 digit MNCs
- -- octet 3 bits 4321 Mobile Network Code 1st digit
- -- bits 8765 Mobile Network Code 2nd digit
- -- octets 4 and 5 Location Area Code according to TS 3GPP TS 24.008 [35]
- -- octets 6 and 7 Cell Identity (CI) according to TS 3GPP TS 24.008 [35]
-
-NetworkResource ::= ENUMERATED {
- plmn (0),
- hlr (1),
- vlr (2),
- pvlr (3),
- controllingMSC (4),
- vmsc (5),
- eir (6),
- rss (7)}
-
-AdditionalNetworkResource ::= ENUMERATED {
- sgsn (0),
- ggsn (1),
- gmlc (2),
- gsmSCF (3),
- nplr (4),
- auc (5),
- ... ,
- ue (6),
- mme (7)}
- -- if unknown value is received in AdditionalNetworkResource
- -- it shall be ignored.
-
-
-NAEA-PreferredCI ::= SEQUENCE {
- naea-PreferredCIC [0] NAEA-CIC,
- extensionContainer [1] ExtensionContainer OPTIONAL,
- ...}
-
-NAEA-CIC ::= OCTET STRING (SIZE (3))
- -- The internal structure is defined by the Carrier Identification
- -- parameter in ANSI T1.113.3. Carrier codes between "000" and "999" may
- -- be encoded as 3 digits using "000" to "999" or as 4 digits using
- -- "0000" to "0999". Carrier codes between "1000" and "9999" are encoded
- -- using 4 digits.
-
-SubscriberIdentity ::= CHOICE {
- imsi [0] IMSI,
- msisdn [1] ISDN-AddressString
- }
-
-LCSClientExternalID ::= SEQUENCE {
- externalAddress [0] ISDN-AddressString OPTIONAL,
- extensionContainer [1] ExtensionContainer OPTIONAL,
- ... }
-
-LCSClientInternalID ::= ENUMERATED {
- broadcastService (0),
- o-andM-HPLMN (1),
- o-andM-VPLMN (2),
- anonymousLocation (3),
- targetMSsubscribedService (4),
- ... }
--- for a CAMEL phase 3 PLMN operator client, the value targetMSsubscribedService shall be used
-
-LCSServiceTypeID ::= INTEGER (0..127)
- -- the integer values 0-63 are reserved for Standard LCS service types
- -- the integer values 64-127 are reserved for Non Standard LCS service types
-
--- Standard LCS Service Types
-emergencyServices LCSServiceTypeID ::= 0
-emergencyAlertServices LCSServiceTypeID ::= 1
-personTracking LCSServiceTypeID ::= 2
-fleetManagement LCSServiceTypeID ::= 3
-assetManagement LCSServiceTypeID ::= 4
-trafficCongestionReporting LCSServiceTypeID ::= 5
-roadsideAssistance LCSServiceTypeID ::= 6
-routingToNearestCommercialEnterprise LCSServiceTypeID ::= 7
-navigation LCSServiceTypeID ::= 8
- --this service type is reserved for use in previous releases
-citySightseeing LCSServiceTypeID ::= 9
-localizedAdvertising LCSServiceTypeID ::= 10
-mobileYellowPages LCSServiceTypeID ::= 11
-trafficAndPublicTransportationInfo LCSServiceTypeID ::= 12
-weather LCSServiceTypeID ::= 13
-assetAndServiceFinding LCSServiceTypeID ::= 14
-gaming LCSServiceTypeID ::= 15
-findYourFriend LCSServiceTypeID ::= 16
-dating LCSServiceTypeID ::= 17
-chatting LCSServiceTypeID ::= 18
-routeFinding LCSServiceTypeID ::= 19
-whereAmI LCSServiceTypeID ::= 20
-
--- The values of LCSServiceTypeID are defined according to 3GPP TS 22.071.
-
--- Non Standard LCS Service Types
-serv64 LCSServiceTypeID ::= 64
-serv65 LCSServiceTypeID ::= 65
-serv66 LCSServiceTypeID ::= 66
-serv67 LCSServiceTypeID ::= 67
-serv68 LCSServiceTypeID ::= 68
-serv69 LCSServiceTypeID ::= 69
-serv70 LCSServiceTypeID ::= 70
-serv71 LCSServiceTypeID ::= 71
-serv72 LCSServiceTypeID ::= 72
-serv73 LCSServiceTypeID ::= 73
-serv74 LCSServiceTypeID ::= 74
-serv75 LCSServiceTypeID ::= 75
-serv76 LCSServiceTypeID ::= 76
-serv77 LCSServiceTypeID ::= 77
-serv78 LCSServiceTypeID ::= 78
-serv79 LCSServiceTypeID ::= 79
-serv80 LCSServiceTypeID ::= 80
-serv81 LCSServiceTypeID ::= 81
-serv82 LCSServiceTypeID ::= 82
-serv83 LCSServiceTypeID ::= 83
-serv84 LCSServiceTypeID ::= 84
-serv85 LCSServiceTypeID ::= 85
-serv86 LCSServiceTypeID ::= 86
-serv87 LCSServiceTypeID ::= 87
-serv88 LCSServiceTypeID ::= 88
-serv89 LCSServiceTypeID ::= 89
-serv90 LCSServiceTypeID ::= 90
-serv91 LCSServiceTypeID ::= 91
-serv92 LCSServiceTypeID ::= 92
-serv93 LCSServiceTypeID ::= 93
-serv94 LCSServiceTypeID ::= 94
-serv95 LCSServiceTypeID ::= 95
-serv96 LCSServiceTypeID ::= 96
-serv97 LCSServiceTypeID ::= 97
-serv98 LCSServiceTypeID ::= 98
-serv99 LCSServiceTypeID ::= 99
-serv100 LCSServiceTypeID ::= 100
-serv101 LCSServiceTypeID ::= 101
-serv102 LCSServiceTypeID ::= 102
-serv103 LCSServiceTypeID ::= 103
-serv104 LCSServiceTypeID ::= 104
-serv105 LCSServiceTypeID ::= 105
-serv106 LCSServiceTypeID ::= 106
-serv107 LCSServiceTypeID ::= 107
-serv108 LCSServiceTypeID ::= 108
-serv109 LCSServiceTypeID ::= 109
-serv110 LCSServiceTypeID ::= 110
-serv111 LCSServiceTypeID ::= 111
-serv112 LCSServiceTypeID ::= 112
-serv113 LCSServiceTypeID ::= 113
-serv114 LCSServiceTypeID ::= 114
-serv115 LCSServiceTypeID ::= 115
-serv116 LCSServiceTypeID ::= 116
-serv117 LCSServiceTypeID ::= 117
-serv118 LCSServiceTypeID ::= 118
-serv119 LCSServiceTypeID ::= 119
-serv120 LCSServiceTypeID ::= 120
-serv121 LCSServiceTypeID ::= 121
-serv122 LCSServiceTypeID ::= 122
-serv123 LCSServiceTypeID ::= 123
-serv124 LCSServiceTypeID ::= 124
-serv125 LCSServiceTypeID ::= 125
-serv126 LCSServiceTypeID ::= 126
-serv127 LCSServiceTypeID ::= 127
-
-PLMN-Id ::= OCTET STRING (SIZE (3))
- -- The internal structure is defined as follows:
- -- octet 1 bits 4321 Mobile Country Code 1st digit
- -- bits 8765 Mobile Country Code 2nd digit
- -- octet 2 bits 4321 Mobile Country Code 3rd digit
- -- bits 8765 Mobile Network Code 3rd digit
- -- or filler (1111) for 2 digit MNCs
- -- octet 3 bits 4321 Mobile Network Code 1st digit
- -- bits 8765 Mobile Network Code 2nd digit
-
--- data types for CAMEL
-
-CellGlobalIdOrServiceAreaIdOrLAI ::= CHOICE {
- cellGlobalIdOrServiceAreaIdFixedLength [0] CellGlobalIdOrServiceAreaIdFixedLength,
- laiFixedLength [1] LAIFixedLength}
-
-CellGlobalIdOrServiceAreaIdFixedLength ::= OCTET STRING (SIZE (7))
- -- Refers to Cell Global Identification or Service Are Identification
- -- defined in 3GPP TS 23.003.
- -- The internal structure is defined as follows:
- -- octet 1 bits 4321 Mobile Country Code 1st digit
- -- bits 8765 Mobile Country Code 2nd digit
- -- octet 2 bits 4321 Mobile Country Code 3rd digit
- -- bits 8765 Mobile Network Code 3rd digit
- -- or filler (1111) for 2 digit MNCs
- -- octet 3 bits 4321 Mobile Network Code 1st digit
- -- bits 8765 Mobile Network Code 2nd digit
- -- octets 4 and 5 Location Area Code according to 3GPP TS 24.008
- -- octets 6 and 7 Cell Identity (CI) value or
- -- Service Area Code (SAC) value
- -- according to 3GPP TS 23.003
-
-LAIFixedLength ::= OCTET STRING (SIZE (5))
- -- Refers to Location Area Identification defined in 3GPP TS 23.003 [17].
- -- The internal structure is defined as follows:
- -- octet 1 bits 4321 Mobile Country Code 1st digit
- -- bits 8765 Mobile Country Code 2nd digit
- -- octet 2 bits 4321 Mobile Country Code 3rd digit
- -- bits 8765 Mobile Network Code 3rd digit
- -- or filler (1111) for 2 digit MNCs
- -- octet 3 bits 4321 Mobile Network Code 1st digit
- -- bits 8765 Mobile Network Code 2nd digit
- -- octets 4 and 5 Location Area Code according to 3GPP TS 24.008 [35]
-
--- data types for subscriber management
-
-BasicServiceCode ::= CHOICE {
- bearerService [2] BearerServiceCode,
- teleservice [3] TeleserviceCode}
-
-Ext-BasicServiceCode ::= CHOICE {
- ext-BearerService [2] Ext-BearerServiceCode,
- ext-Teleservice [3] Ext-TeleserviceCode}
-
-EMLPP-Info ::= SEQUENCE {
- maximumentitledPriority EMLPP-Priority,
- defaultPriority EMLPP-Priority,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-EMLPP-Priority ::= INTEGER (0..15)
- -- The mapping from the values A,B,0,1,2,3,4 to the integer-value is
- -- specified as follows where A is the highest and 4 is the lowest
- -- priority level
- -- the integer values 7-15 are spare and shall be mapped to value 4
-
-priorityLevelA EMLPP-Priority ::= 6
-priorityLevelB EMLPP-Priority ::= 5
-priorityLevel0 EMLPP-Priority ::= 0
-priorityLevel1 EMLPP-Priority ::= 1
-priorityLevel2 EMLPP-Priority ::= 2
-priorityLevel3 EMLPP-Priority ::= 3
-priorityLevel4 EMLPP-Priority ::= 4
-
-MC-SS-Info ::= SEQUENCE {
- ss-Code [0] SS-Code,
- ss-Status [1] Ext-SS-Status,
- nbrSB [2] MaxMC-Bearers,
- nbrUser [3] MC-Bearers,
- extensionContainer [4] ExtensionContainer OPTIONAL,
- ...}
-
-MaxMC-Bearers ::= INTEGER (2..maxNumOfMC-Bearers)
-
-MC-Bearers ::= INTEGER (1..maxNumOfMC-Bearers)
-
-maxNumOfMC-Bearers INTEGER ::= 7
-
-Ext-SS-Status ::= OCTET STRING (SIZE (1..5))
-
- -- OCTET 1:
- --
- -- bits 8765: 0000 (unused)
- -- bits 4321: Used to convey the "P bit","R bit","A bit" and "Q bit",
- -- representing supplementary service state information
- -- as defined in TS 3GPP TS 23.011 [22]
-
- -- bit 4: "Q bit"
-
- -- bit 3: "P bit"
-
- -- bit 2: "R bit"
-
- -- bit 1: "A bit"
-
- -- OCTETS 2-5: reserved for future use. They shall be discarded if
- -- received and not understood.
-
-
- -- data types for geographic location
-
-AgeOfLocationInformation ::= INTEGER (0..32767)
--- the value represents the elapsed time in minutes since the last
--- network contact of the mobile station (i.e. the actuality of the
--- location information).
--- value "0" indicates that the MS is currently in contact with the
--- network
--- value "32767" indicates that the location information is at least
--- 32767 minutes old
-
-END
-
diff --git a/rrlp-ephemeris/asn1/MAP-ER-DataTypes.asn b/rrlp-ephemeris/asn1/MAP-ER-DataTypes.asn
deleted file mode 100644
index d0b90fc..0000000
--- a/rrlp-ephemeris/asn1/MAP-ER-DataTypes.asn
+++ /dev/null
@@ -1,415 +0,0 @@
--- $Id: MAP-ER-DataTypes.asn 28149 2009-04-25 17:45:34Z etxrab $
--- 3GPP TS 29.002 V8.9.0 (2009-04)
--- 17.7.7 Error data types
-
-MAP-ER-DataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-ER-DataTypes (17) version11 (11)}
-
-DEFINITIONS
-
-IMPLICIT TAGS
-
-::=
-
-BEGIN
-
-EXPORTS
- RoamingNotAllowedParam,
- CallBarredParam,
- CUG-RejectParam,
- SS-IncompatibilityCause,
- PW-RegistrationFailureCause,
- SM-DeliveryFailureCause,
- SystemFailureParam,
- DataMissingParam,
- UnexpectedDataParam,
- FacilityNotSupParam,
- OR-NotAllowedParam,
- UnknownSubscriberParam,
- NumberChangedParam,
- UnidentifiedSubParam,
- IllegalSubscriberParam,
- IllegalEquipmentParam,
- BearerServNotProvParam,
- TeleservNotProvParam,
- TracingBufferFullParam,
- NoRoamingNbParam,
- AbsentSubscriberParam,
- BusySubscriberParam,
- NoSubscriberReplyParam,
- ForwardingViolationParam,
- ForwardingFailedParam,
- ATI-NotAllowedParam,
- SubBusyForMT-SMS-Param,
- MessageWaitListFullParam,
- AbsentSubscriberSM-Param,
- AbsentSubscriberDiagnosticSM,
- ResourceLimitationParam,
- NoGroupCallNbParam,
- IncompatibleTerminalParam,
- ShortTermDenialParam,
- LongTermDenialParam,
- UnauthorizedRequestingNetwork-Param,
- UnauthorizedLCSClient-Param,
- PositionMethodFailure-Param,
-UnknownOrUnreachableLCSClient-Param,
- MM-EventNotSupported-Param,
-ATSI-NotAllowedParam,
-ATM-NotAllowedParam,
-IllegalSS-OperationParam,
-SS-NotAvailableParam,
-SS-SubscriptionViolationParam,
-InformationNotAvailableParam,
-TargetCellOutsideGCA-Param,
-OngoingGroupCallParam
-
-;
-
-IMPORTS
- SS-Status
-FROM MAP-SS-DataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-SS-DataTypes (14) version11 (11)}
-
- SignalInfo,
- BasicServiceCode,
- NetworkResource,
- AdditionalNetworkResource
-FROM MAP-CommonDataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-CommonDataTypes (18) version11 (11)}
-
-
- SS-Code
-FROM MAP-SS-Code {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-SS-Code (15) version11 (11)}
-
- ExtensionContainer
-FROM MAP-ExtensionDataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
-;
-
-RoamingNotAllowedParam ::= SEQUENCE {
- roamingNotAllowedCause RoamingNotAllowedCause,
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- additionalRoamingNotAllowedCause [0] AdditionalRoamingNotAllowedCause OPTIONAL }
-
--- if the additionalRoamingNotallowedCause is received by the MSC/VLR or SGSN then the
--- roamingNotAllowedCause shall be discarded.
-
-AdditionalRoamingNotAllowedCause ::= ENUMERATED {
- supportedRAT-TypesNotAllowed (0),
- ...}
-
-RoamingNotAllowedCause ::= ENUMERATED {
- plmnRoamingNotAllowed (0),
- operatorDeterminedBarring (3)}
-
-CallBarredParam ::= CHOICE {
- callBarringCause CallBarringCause,
- -- call BarringCause must not be used in version 3 and higher
- extensibleCallBarredParam ExtensibleCallBarredParam
- -- extensibleCallBarredParam must not be used in version <3
- }
-
-CallBarringCause ::= ENUMERATED {
- barringServiceActive (0),
- operatorBarring (1)}
-
-ExtensibleCallBarredParam ::= SEQUENCE {
- callBarringCause CallBarringCause OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ... ,
- unauthorisedMessageOriginator [1] NULL OPTIONAL }
-
-CUG-RejectParam ::= SEQUENCE {
- cug-RejectCause CUG-RejectCause OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-CUG-RejectCause ::= ENUMERATED {
- incomingCallsBarredWithinCUG (0),
- subscriberNotMemberOfCUG (1),
- requestedBasicServiceViolatesCUG-Constraints (5),
- calledPartySS-InteractionViolation (7)}
-
-SS-IncompatibilityCause ::= SEQUENCE {
- ss-Code [1] SS-Code OPTIONAL,
- basicService BasicServiceCode OPTIONAL,
- ss-Status [4] SS-Status OPTIONAL,
- ...}
-
-PW-RegistrationFailureCause ::= ENUMERATED {
- undetermined (0),
- invalidFormat (1),
- newPasswordsMismatch (2)}
-
-SM-EnumeratedDeliveryFailureCause ::= ENUMERATED {
- memoryCapacityExceeded (0),
- equipmentProtocolError (1),
- equipmentNotSM-Equipped (2),
- unknownServiceCentre (3),
- sc-Congestion (4),
- invalidSME-Address (5),
- subscriberNotSC-Subscriber (6)}
-
-SM-DeliveryFailureCause ::= SEQUENCE {
- sm-EnumeratedDeliveryFailureCause SM-EnumeratedDeliveryFailureCause,
- diagnosticInfo SignalInfo OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-AbsentSubscriberSM-Param ::= SEQUENCE {
- absentSubscriberDiagnosticSM AbsentSubscriberDiagnosticSM OPTIONAL,
- -- AbsentSubscriberDiagnosticSM can be either for non-GPRS
- -- or for GPRS
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- additionalAbsentSubscriberDiagnosticSM [0] AbsentSubscriberDiagnosticSM OPTIONAL }
- -- if received, additionalAbsentSubscriberDiagnosticSM
- -- is for GPRS and absentSubscriberDiagnosticSM is
- -- for non-GPRS
-
-AbsentSubscriberDiagnosticSM ::= INTEGER (0..255)
- -- AbsentSubscriberDiagnosticSM values are defined in 3GPP TS 23.040
-
-SystemFailureParam ::= CHOICE {
- networkResource NetworkResource,
- -- networkResource must not be used in version 3
- extensibleSystemFailureParam ExtensibleSystemFailureParam
- -- extensibleSystemFailureParam must not be used in version <3
- }
-
-ExtensibleSystemFailureParam ::= SEQUENCE {
- networkResource NetworkResource OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- additionalNetworkResource [0] AdditionalNetworkResource OPTIONAL,
- failureCauseParam [1] FailureCauseParam OPTIONAL }
-
-FailureCauseParam ::= ENUMERATED {
- limitReachedOnNumberOfConcurrentLocationRequests (0),
- ... }
- -- if unknown value is received in FailureCauseParam it shall be ignored
-
-
-DataMissingParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-UnexpectedDataParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-FacilityNotSupParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- shapeOfLocationEstimateNotSupported [0] NULL OPTIONAL,
- neededLcsCapabilityNotSupportedInServingNode [1] NULL OPTIONAL }
-
-OR-NotAllowedParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-UnknownSubscriberParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- unknownSubscriberDiagnostic UnknownSubscriberDiagnostic OPTIONAL}
-
-UnknownSubscriberDiagnostic ::= ENUMERATED {
- imsiUnknown (0),
- gprs-eps-SubscriptionUnknown (1),
- ...,
- npdbMismatch (2)}
- -- if unknown values are received in
- -- UnknownSubscriberDiagnostic they shall be discarded
-
-NumberChangedParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-UnidentifiedSubParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-IllegalSubscriberParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-IllegalEquipmentParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-BearerServNotProvParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-TeleservNotProvParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-TracingBufferFullParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-NoRoamingNbParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-AbsentSubscriberParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- absentSubscriberReason [0] AbsentSubscriberReason OPTIONAL}
-
-AbsentSubscriberReason ::= ENUMERATED {
- imsiDetach (0),
- restrictedArea (1),
- noPageResponse (2),
- ... ,
- purgedMS (3)}
--- exception handling: at reception of other values than the ones listed the
--- AbsentSubscriberReason shall be ignored.
--- The AbsentSubscriberReason: purgedMS is defined for the Super-Charger feature
--- (see TS 23.116). If this value is received in a Provide Roaming Number response
--- it shall be mapped to the AbsentSubscriberReason: imsiDetach in the Send Routeing
--- Information response
-
-BusySubscriberParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- ccbs-Possible [0] NULL OPTIONAL,
- ccbs-Busy [1] NULL OPTIONAL}
-
-NoSubscriberReplyParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-ForwardingViolationParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-ForwardingFailedParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-ATI-NotAllowedParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-ATSI-NotAllowedParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-ATM-NotAllowedParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-IllegalSS-OperationParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-SS-NotAvailableParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-SS-SubscriptionViolationParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-InformationNotAvailableParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-SubBusyForMT-SMS-Param ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ... ,
- gprsConnectionSuspended NULL OPTIONAL }
- -- If GprsConnectionSuspended is not understood it shall
- -- be discarded
-
-MessageWaitListFullParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-ResourceLimitationParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-NoGroupCallNbParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-IncompatibleTerminalParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-ShortTermDenialParam ::= SEQUENCE {
- ...}
-
-LongTermDenialParam ::= SEQUENCE {
- ...}
-
-UnauthorizedRequestingNetwork-Param ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-UnauthorizedLCSClient-Param ::= SEQUENCE {
- unauthorizedLCSClient-Diagnostic [0] UnauthorizedLCSClient-Diagnostic OPTIONAL,
- extensionContainer [1] ExtensionContainer OPTIONAL,
- ... }
-
-UnauthorizedLCSClient-Diagnostic ::= ENUMERATED {
- noAdditionalInformation (0),
- clientNotInMSPrivacyExceptionList (1),
- callToClientNotSetup (2),
- privacyOverrideNotApplicable (3),
- disallowedByLocalRegulatoryRequirements (4),
- ...,
- unauthorizedPrivacyClass (5),
- unauthorizedCallSessionUnrelatedExternalClient (6),
- unauthorizedCallSessionRelatedExternalClient (7) }
--- exception handling:
--- any unrecognized value shall be ignored
-
-PositionMethodFailure-Param ::= SEQUENCE {
- positionMethodFailure-Diagnostic [0] PositionMethodFailure-Diagnostic OPTIONAL,
- extensionContainer [1] ExtensionContainer OPTIONAL,
- ... }
-
-PositionMethodFailure-Diagnostic ::= ENUMERATED {
- congestion (0),
- insufficientResources (1),
- insufficientMeasurementData (2),
- inconsistentMeasurementData (3),
- locationProcedureNotCompleted (4),
- locationProcedureNotSupportedByTargetMS (5),
- qoSNotAttainable (6),
- positionMethodNotAvailableInNetwork (7),
- positionMethodNotAvailableInLocationArea (8),
- ... }
--- exception handling:
--- any unrecognized value shall be ignored
-
-UnknownOrUnreachableLCSClient-Param ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-MM-EventNotSupported-Param ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-TargetCellOutsideGCA-Param ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-OngoingGroupCallParam ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-
-END
-
diff --git a/rrlp-ephemeris/asn1/MAP-ExtensionDataTypes.asn b/rrlp-ephemeris/asn1/MAP-ExtensionDataTypes.asn
deleted file mode 100644
index d94c057..0000000
--- a/rrlp-ephemeris/asn1/MAP-ExtensionDataTypes.asn
+++ /dev/null
@@ -1,74 +0,0 @@
--- $Id: MAP-ExtensionDataTypes.asn 28149 2009-04-25 17:45:34Z etxrab $
--- MAP-ExtensionDataTypes.asn
---
--- Taken from 3GPP TS 29.002 V8.9.0 (2009-04)
---
--- 17.7.11 Extension data types
---
-
-MAP-ExtensionDataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
-
-DEFINITIONS
-
-IMPLICIT TAGS
-
-::=
-
-BEGIN
-
-EXPORTS
-
- PrivateExtension,
- ExtensionContainer,
- SLR-ArgExtensionContainer;
-
-
--- IOC for private MAP extensions
-
-
-MAP-EXTENSION ::= CLASS {
- &ExtensionType OPTIONAL,
- &extensionId OBJECT IDENTIFIER }
- -- The length of the Object Identifier shall not exceed 16 octets and the
- -- number of components of the Object Identifier shall not exceed 16
-
--- data types
-
-ExtensionContainer ::= SEQUENCE {
- privateExtensionList [0]PrivateExtensionList OPTIONAL,
- pcs-Extensions [1]PCS-Extensions OPTIONAL,
- ...}
-
-SLR-ArgExtensionContainer ::= SEQUENCE {
- privateExtensionList [0]PrivateExtensionList OPTIONAL,
- slr-Arg-PCS-Extensions [1]SLR-Arg-PCS-Extensions OPTIONAL,
- ...}
-
-PrivateExtensionList ::= SEQUENCE SIZE (1..maxNumOfPrivateExtensions) OF
- PrivateExtension
-
-PrivateExtension ::= SEQUENCE {
- extId MAP-EXTENSION.&extensionId
- ({ExtensionSet}),
- extType MAP-EXTENSION.&ExtensionType
- ({ExtensionSet}{@extId}) OPTIONAL}
-
-maxNumOfPrivateExtensions INTEGER ::= 10
-
-ExtensionSet MAP-EXTENSION ::=
- {...
- -- ExtensionSet is the set of all defined private extensions
- }
- -- Unsupported private extensions shall be discarded if received.
-
-PCS-Extensions ::= SEQUENCE {
- ...}
-
-SLR-Arg-PCS-Extensions ::= SEQUENCE {
- ...,
- na-ESRK-Request [0] NULL OPTIONAL }
-
-END
-
diff --git a/rrlp-ephemeris/asn1/MAP-LCS-DataTypes.asn b/rrlp-ephemeris/asn1/MAP-LCS-DataTypes.asn
deleted file mode 100644
index 2434b89..0000000
--- a/rrlp-ephemeris/asn1/MAP-LCS-DataTypes.asn
+++ /dev/null
@@ -1,657 +0,0 @@
--- $Id: MAP-LCS-DataTypes.asn 28149 2009-04-25 17:45:34Z etxrab $
--- MAP-LCS-DataTypes.asn
---
--- Taken from 3GPP TS 29.002 V8.9.0 (2009-04)
---
--- 17.7.13 Location service data types
---
-
-MAP-LCS-DataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-LCS-DataTypes (25) version11 (11)}
-
-DEFINITIONS
-IMPLICIT TAGS
-::=
-BEGIN
-
-EXPORTS
- RoutingInfoForLCS-Arg,
- RoutingInfoForLCS-Res,
- ProvideSubscriberLocation-Arg,
- ProvideSubscriberLocation-Res,
- SubscriberLocationReport-Arg,
- SubscriberLocationReport-Res,
-LocationType,
-DeferredLocationEventType,
-LCSClientName,
-LCS-QoS,
-Horizontal-Accuracy,
-ResponseTime,
-Ext-GeographicalInformation,
-VelocityEstimate,
-SupportedGADShapes,
-Add-GeographicalInformation,
-LCSRequestorID,
-LCS-ReferenceNumber,
-LCSCodeword,
-AreaEventInfo,
-ReportingPLMNList,
-PeriodicLDRInfo,
-SequenceNumber
-;
-
-IMPORTS
- AddressString,
- ISDN-AddressString,
- IMEI,
- IMSI,
- LMSI,
- SubscriberIdentity,
- AgeOfLocationInformation,
- LCSClientExternalID,
- LCSClientInternalID,
-LCSServiceTypeID,
-CellGlobalIdOrServiceAreaIdOrLAI,
-PLMN-Id
-FROM MAP-CommonDataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-CommonDataTypes (18) version11 (11)}
-
- ExtensionContainer,
- SLR-ArgExtensionContainer
-FROM MAP-ExtensionDataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
-
- USSD-DataCodingScheme,
-USSD-String
-FROM MAP-SS-DataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0) gsm-Network (1) modules (3)
- map-SS-DataTypes (14) version11 (11)}
-
- APN,
- GSN-Address,
- SupportedLCS-CapabilitySets
-FROM MAP-MS-DataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-MS-DataTypes (11) version11 (11)}
-
- Additional-Number
-FROM MAP-SM-DataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-SM-DataTypes (16) version11 (11)}
-;
-
-
-RoutingInfoForLCS-Arg ::= SEQUENCE {
- mlcNumber [0] ISDN-AddressString,
- targetMS [1] SubscriberIdentity,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ...}
-
-RoutingInfoForLCS-Res ::= SEQUENCE {
- targetMS [0] SubscriberIdentity,
- lcsLocationInfo [1] LCSLocationInfo,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ...,
- v-gmlc-Address [3] GSN-Address OPTIONAL,
- h-gmlc-Address [4] GSN-Address OPTIONAL,
- ppr-Address [5] GSN-Address OPTIONAL,
- additional-v-gmlc-Address [6] GSN-Address OPTIONAL }
-
-LCSLocationInfo ::= SEQUENCE {
- networkNode-Number ISDN-AddressString,
- -- NetworkNode-number can be either msc-number or sgsn-number
- lmsi [0] LMSI OPTIONAL,
- extensionContainer [1] ExtensionContainer OPTIONAL,
- ... ,
- gprsNodeIndicator [2] NULL OPTIONAL,
- -- gprsNodeIndicator is set only if the SGSN number is sent as the Network Node Number
- additional-Number [3] Additional-Number OPTIONAL,
- supportedLCS-CapabilitySets [4] SupportedLCS-CapabilitySets OPTIONAL,
- additional-LCS-CapabilitySets [5] SupportedLCS-CapabilitySets OPTIONAL
- }
-
-ProvideSubscriberLocation-Arg ::= SEQUENCE {
- locationType LocationType,
- mlc-Number ISDN-AddressString,
- lcs-ClientID [0] LCS-ClientID OPTIONAL,
- privacyOverride [1] NULL OPTIONAL,
- imsi [2] IMSI OPTIONAL,
- msisdn [3] ISDN-AddressString OPTIONAL,
- lmsi [4] LMSI OPTIONAL,
- imei [5] IMEI OPTIONAL,
- lcs-Priority [6] LCS-Priority OPTIONAL,
- lcs-QoS [7] LCS-QoS OPTIONAL,
- extensionContainer [8] ExtensionContainer OPTIONAL,
- ... ,
- supportedGADShapes [9] SupportedGADShapes OPTIONAL,
- lcs-ReferenceNumber [10] LCS-ReferenceNumber OPTIONAL,
- lcsServiceTypeID [11] LCSServiceTypeID OPTIONAL,
- lcsCodeword [12] LCSCodeword OPTIONAL,
- lcs-PrivacyCheck [13] LCS-PrivacyCheck OPTIONAL,
- areaEventInfo [14] AreaEventInfo OPTIONAL,
- h-gmlc-Address [15] GSN-Address OPTIONAL,
- mo-lrShortCircuitIndicator [16] NULL OPTIONAL,
- periodicLDRInfo [17] PeriodicLDRInfo OPTIONAL,
- reportingPLMNList [18] ReportingPLMNList OPTIONAL }
-
- -- one of imsi or msisdn is mandatory
- -- If a location estimate type indicates activate deferred location or cancel deferred
- -- location, a lcs-Reference number shall be included.
-
-LocationType ::= SEQUENCE {
- locationEstimateType [0] LocationEstimateType,
- ...,
- deferredLocationEventType [1] DeferredLocationEventType OPTIONAL }
-
-LocationEstimateType ::= ENUMERATED {
- currentLocation (0),
- currentOrLastKnownLocation (1),
- initialLocation (2),
- ...,
- activateDeferredLocation (3),
- cancelDeferredLocation (4) ,
- notificationVerificationOnly (5) }
--- exception handling:
--- a ProvideSubscriberLocation-Arg containing an unrecognized LocationEstimateType
--- shall be rejected by the receiver with a return error cause of unexpected data value
-
-DeferredLocationEventType ::= BIT STRING {
- msAvailable (0) ,
- enteringIntoArea (1),
- leavingFromArea (2),
- beingInsideArea (3) ,
- periodicLDR (4) } (SIZE (1..16))
--- beingInsideArea is always treated as oneTimeEvent regardless of the possible value
--- of occurrenceInfo inside areaEventInfo.
--- exception handling:
--- a ProvideSubscriberLocation-Arg containing other values than listed above in
--- DeferredLocationEventType shall be rejected by the receiver with a return error cause of
--- unexpected data value.
-
-LCS-ClientID ::= SEQUENCE {
- lcsClientType [0] LCSClientType,
- lcsClientExternalID [1] LCSClientExternalID OPTIONAL,
- lcsClientDialedByMS [2] AddressString OPTIONAL,
- lcsClientInternalID [3] LCSClientInternalID OPTIONAL,
- lcsClientName [4] LCSClientName OPTIONAL,
- ...,
- lcsAPN [5] APN OPTIONAL,
- lcsRequestorID [6] LCSRequestorID OPTIONAL }
-
-LCSClientType ::= ENUMERATED {
- emergencyServices (0),
- valueAddedServices (1),
- plmnOperatorServices (2),
- lawfulInterceptServices (3),
- ... }
- -- exception handling:
- -- unrecognized values may be ignored if the LCS client uses the privacy override
- -- otherwise, an unrecognized value shall be treated as unexpected data by a receiver
- -- a return error shall then be returned if received in a MAP invoke
-
-LCSClientName ::= SEQUENCE {
- dataCodingScheme [0] USSD-DataCodingScheme,
- nameString [2] NameString,
- ...,
- lcs-FormatIndicator [3] LCS-FormatIndicator OPTIONAL }
-
--- The USSD-DataCodingScheme shall indicate use of the default alphabet through the
--- following encoding
--- bit 7 6 5 4 3 2 1 0
--- 0 0 0 0 1 1 1 1
-
-NameString ::= USSD-String (SIZE (1..maxNameStringLength))
-
-maxNameStringLength INTEGER ::= 63
-
-LCSRequestorID ::= SEQUENCE {
- dataCodingScheme [0] USSD-DataCodingScheme,
- requestorIDString [1] RequestorIDString,
- ...,
- lcs-FormatIndicator [2] LCS-FormatIndicator OPTIONAL }
-
-RequestorIDString ::= USSD-String (SIZE (1..maxRequestorIDStringLength))
-
-maxRequestorIDStringLength INTEGER ::= 63
-
-LCS-FormatIndicator ::= ENUMERATED {
- logicalName (0),
- e-mailAddress (1),
- msisdn (2),
- url (3),
- sipUrl (4),
- ... }
-
-LCS-Priority ::= OCTET STRING (SIZE (1))
- -- 0 = highest priority
- -- 1 = normal priority
- -- all other values treated as 1
-
-LCS-QoS ::= SEQUENCE {
- horizontal-accuracy [0] Horizontal-Accuracy OPTIONAL,
- verticalCoordinateRequest [1] NULL OPTIONAL,
- vertical-accuracy [2] Vertical-Accuracy OPTIONAL, responseTime [3] ResponseTime OPTIONAL,
- extensionContainer [4] ExtensionContainer OPTIONAL,
- ...,
- velocityRequest [5] NULL OPTIONAL
-}
-
-Horizontal-Accuracy ::= OCTET STRING (SIZE (1))
- -- bit 8 = 0
- -- bits 7-1 = 7 bit Uncertainty Code defined in 3GPP TS 23.032. The horizontal location
- -- error should be less than the error indicated by the uncertainty code with 67%
- -- confidence.
-
-Vertical-Accuracy ::= OCTET STRING (SIZE (1))
- -- bit 8 = 0
- -- bits 7-1 = 7 bit Vertical Uncertainty Code defined in 3GPP TS 23.032.
- -- The vertical location error should be less than the error indicated
- -- by the uncertainty code with 67% confidence.
-
-ResponseTime ::= SEQUENCE {
- responseTimeCategory ResponseTimeCategory,
- ...}
--- note: an expandable SEQUENCE simplifies later addition of a numeric response time.
-
-ResponseTimeCategory ::= ENUMERATED {
- lowdelay (0),
- delaytolerant (1),
- ... }
--- exception handling:
--- an unrecognized value shall be treated the same as value 1 (delaytolerant)
-
-SupportedGADShapes ::= BIT STRING {
- ellipsoidPoint (0),
- ellipsoidPointWithUncertaintyCircle (1),
- ellipsoidPointWithUncertaintyEllipse (2),
- polygon (3),
- ellipsoidPointWithAltitude (4),
- ellipsoidPointWithAltitudeAndUncertaintyElipsoid (5),
- ellipsoidArc (6) } (SIZE (7..16))
--- A node shall mark in the BIT STRING all Shapes defined in 3GPP TS 23.032 it supports.
--- exception handling: bits 7 to 15 shall be ignored if received.
-
-LCS-ReferenceNumber::= OCTET STRING (SIZE(1))
-
-LCSCodeword ::= SEQUENCE {
- dataCodingScheme [0] USSD-DataCodingScheme,
- lcsCodewordString [1] LCSCodewordString,
- ...}
-
-LCSCodewordString ::= USSD-String (SIZE (1..maxLCSCodewordStringLength))
-
-maxLCSCodewordStringLength INTEGER ::= 20
-
-LCS-PrivacyCheck ::= SEQUENCE {
- callSessionUnrelated [0] PrivacyCheckRelatedAction,
- callSessionRelated [1] PrivacyCheckRelatedAction OPTIONAL,
- ...}
-
-PrivacyCheckRelatedAction ::= ENUMERATED {
- allowedWithoutNotification (0),
- allowedWithNotification (1),
- allowedIfNoResponse (2),
- restrictedIfNoResponse (3),
- notAllowed (4),
- ...}
--- exception handling:
--- a ProvideSubscriberLocation-Arg containing an unrecognized PrivacyCheckRelatedAction
--- shall be rejected by the receiver with a return error cause of unexpected data value
-
-AreaEventInfo ::= SEQUENCE {
- areaDefinition [0] AreaDefinition,
- occurrenceInfo [1] OccurrenceInfo OPTIONAL,
- intervalTime [2] IntervalTime OPTIONAL,
- ...}
-
-AreaDefinition ::= SEQUENCE {
- areaList [0] AreaList,
- ...}
-
-AreaList ::= SEQUENCE SIZE (1..maxNumOfAreas) OF Area
-
-maxNumOfAreas INTEGER ::= 10
-
-Area ::= SEQUENCE {
- areaType [0] AreaType,
- areaIdentification [1] AreaIdentification,
- ...}
-
-AreaType ::= ENUMERATED {
- countryCode (0),
- plmnId (1),
- locationAreaId (2),
- routingAreaId (3),
- cellGlobalId (4),
- ...,
- utranCellId (5) }
-
-AreaIdentification ::= OCTET STRING (SIZE (2..7))
- -- The internal structure is defined as follows:
- -- octet 1 bits 4321 Mobile Country Code 1st digit
- -- bits 8765 Mobile Country Code 2nd digit
- -- octet 2 bits 4321 Mobile Country Code 3rd digit
- -- bits 8765 Mobile Network Code 3rd digit if 3 digit MNC included
- -- or filler (1111)
- -- octet 3 bits 4321 Mobile Network Code 1st digit
- -- bits 8765 Mobile Network Code 2nd digit
- -- octets 4 and 5 Location Area Code (LAC) for Local Area Id,
- -- Routing Area Id and Cell Global Id
- -- octet 6 Routing Area Code (RAC) for Routing Area Id
- -- octets 6 and 7 Cell Identity (CI) for Cell Global Id
- -- octets 4 until 7 Utran Cell Identity (UC-Id) for Utran Cell Id
-
-OccurrenceInfo ::= ENUMERATED {
- oneTimeEvent (0),
- multipleTimeEvent (1),
- ...}
-
-IntervalTime ::= INTEGER (1..32767)
- -- minimum interval time between area reports in seconds
-
-PeriodicLDRInfo ::= SEQUENCE {
- reportingAmount ReportingAmount,
- reportingInterval ReportingInterval,
- ...}
--- reportingInterval x reportingAmount shall not exceed 8639999 (99 days, 23 hours,
--- 59 minutes and 59 seconds) for compatibility with OMA MLP and RLP
-
-ReportingAmount ::= INTEGER (1..maxReportingAmount)
-
-maxReportingAmount INTEGER ::= 8639999
-
-ReportingInterval ::= INTEGER (1..maxReportingInterval)
--- ReportingInterval is in seconds
-
-maxReportingInterval INTEGER ::= 8639999
-
-ReportingPLMNList::= SEQUENCE {
- plmn-ListPrioritized [0] NULL OPTIONAL,
- plmn-List [1] PLMNList,
- ...}
-
-PLMNList::= SEQUENCE SIZE (1..maxNumOfReportingPLMN) OF
- ReportingPLMN
-
-maxNumOfReportingPLMN INTEGER ::= 20
-
-ReportingPLMN::= SEQUENCE {
- plmn-Id [0] PLMN-Id,
- ran-Technology [1] RAN-Technology OPTIONAL,
- ran-PeriodicLocationSupport [2] NULL OPTIONAL,
- ...}
-
-RAN-Technology ::= ENUMERATED {
- gsm (0),
- umts (1),
- ...}
-
-ProvideSubscriberLocation-Res ::= SEQUENCE {
- locationEstimate Ext-GeographicalInformation,
- ageOfLocationEstimate [0] AgeOfLocationInformation OPTIONAL,
- extensionContainer [1] ExtensionContainer OPTIONAL,
- ... ,
- add-LocationEstimate [2] Add-GeographicalInformation OPTIONAL,
- deferredmt-lrResponseIndicator [3] NULL OPTIONAL,
- geranPositioningData [4] PositioningDataInformation OPTIONAL,
- utranPositioningData [5] UtranPositioningDataInfo OPTIONAL,
- cellIdOrSai [6] CellGlobalIdOrServiceAreaIdOrLAI OPTIONAL,
- sai-Present [7] NULL OPTIONAL,
- accuracyFulfilmentIndicator [8] AccuracyFulfilmentIndicator OPTIONAL,
- velocityEstimate [9] VelocityEstimate OPTIONAL,
- mo-lrShortCircuitIndicator [10] NULL OPTIONAL }
-
--- if deferredmt-lrResponseIndicator is set, locationEstimate is ignored.
-
--- the add-LocationEstimate parameter shall not be sent to a node that did not indicate the
--- geographic shapes supported in the ProvideSubscriberLocation-Arg
--- The locationEstimate and the add-locationEstimate parameters shall not be sent if
--- the supportedGADShapes parameter has been received in ProvideSubscriberLocation-Arg
--- and the shape encoded in locationEstimate or add-LocationEstimate is not marked
--- as supported in supportedGADShapes. In such a case ProvideSubscriberLocation
--- shall be rejected with error FacilityNotSupported with additional indication
--- shapeOfLocationEstimateNotSupported.
--- sai-Present indicates that the cellIdOrSai parameter contains a Service Area Identity.
-
-AccuracyFulfilmentIndicator ::= ENUMERATED {
- requestedAccuracyFulfilled (0),
- requestedAccuracyNotFulfilled (1),
- ... }
-
-Ext-GeographicalInformation ::= OCTET STRING (SIZE (1..maxExt-GeographicalInformation))
- -- Refers to geographical Information defined in 3GPP TS 23.032.
- -- This is composed of 1 or more octets with an internal structure according to
- -- 3GPP TS 23.032
- -- Octet 1: Type of shape, only the following shapes in 3GPP TS 23.032 are allowed:
- -- (a) Ellipsoid point with uncertainty circle
- -- (b) Ellipsoid point with uncertainty ellipse
- -- (c) Ellipsoid point with altitude and uncertainty ellipsoid
- -- (d) Ellipsoid Arc
- -- (e) Ellipsoid Point
- -- Any other value in octet 1 shall be treated as invalid
- -- Octets 2 to 8 for case (a) – Ellipsoid point with uncertainty circle
- -- Degrees of Latitude 3 octets
- -- Degrees of Longitude 3 octets
- -- Uncertainty code 1 octet
- -- Octets 2 to 11 for case (b) – Ellipsoid point with uncertainty ellipse:
- -- Degrees of Latitude 3 octets
- -- Degrees of Longitude 3 octets
- -- Uncertainty semi-major axis 1 octet
- -- Uncertainty semi-minor axis 1 octet
- -- Angle of major axis 1 octet
- -- Confidence 1 octet
- -- Octets 2 to 14 for case (c) – Ellipsoid point with altitude and uncertainty ellipsoid
- -- Degrees of Latitude 3 octets
- -- Degrees of Longitude 3 octets
- -- Altitude 2 octets
- -- Uncertainty semi-major axis 1 octet
- -- Uncertainty semi-minor axis 1 octet
- -- Angle of major axis 1 octet
- -- Uncertainty altitude 1 octet
- -- Confidence 1 octet
- -- Octets 2 to 13 for case (d) – Ellipsoid Arc
- -- Degrees of Latitude 3 octets
- -- Degrees of Longitude 3 octets
- -- Inner radius 2 octets
- -- Uncertainty radius 1 octet
- -- Offset angle 1 octet
- -- Included angle 1 octet
- -- Confidence 1 octet
- -- Octets 2 to 7 for case (e) – Ellipsoid Point
- -- Degrees of Latitude 3 octets
- -- Degrees of Longitude 3 octets
-
- --
- -- An Ext-GeographicalInformation parameter comprising more than one octet and
- -- containing any other shape or an incorrect number of octets or coding according
- -- to 3GPP TS 23.032 shall be treated as invalid data by a receiver.
- --
- -- An Ext-GeographicalInformation parameter comprising one octet shall be discarded
- -- by the receiver if an Add-GeographicalInformation parameter is received
- -- in the same message.
- --
- -- An Ext-GeographicalInformation parameter comprising one octet shall be treated as
- -- invalid data by the receiver if an Add-GeographicalInformation parameter is not
- -- received in the same message.
-
-maxExt-GeographicalInformation INTEGER ::= 20
- -- the maximum length allows for further shapes in 3GPP TS 23.032 to be included in later
- -- versions of 3GPP TS 29.002
-
-VelocityEstimate ::= OCTET STRING (SIZE (4..7))
- -- Refers to Velocity description defined in 3GPP TS 23.032.
- -- This is composed of 4 or more octets with an internal structure according to
- -- 3GPP TS 23.032
- -- Octet 1: Type of velocity, only the following types in 3GPP TS 23.032 are allowed:
- -- (a) Horizontal Velocity
- -- (b) Horizontal with Vertical Velocity
- -- (c) Horizontal Velocity with Uncertainty
- -- (d) Horizontal with Vertical Velocity and Uncertainty
- -- For types Horizontal with Vertical Velocity and Horizontal with Vertical Velocity
- -- and Uncertainty, the direction of the Vertical Speed is also included in Octet 1
- -- Any other value in octet 1 shall be treated as invalid
- -- Octets 2 to 4 for case (a) Horizontal velocity:
- -- Bearing 1 octet
- -- Horizontal Speed 2 octets
- -- Octets 2 to 5 for case (b) – Horizontal with Vertical Velocity:
- -- Bearing 1 octet
- -- Horizontal Speed 2 octets
- -- Vertical Speed 1 octet
- -- Octets 2 to 5 for case (c) – Horizontal velocity with Uncertainty:
- -- Bearing 1 octet
- -- Horizontal Speed 2 octets
- -- Uncertainty Speed 1 octet
- -- Octets 2 to 7 for case (d) – Horizontal with Vertical Velocity and Uncertainty:
- -- Bearing 1 octet
- -- Horizontal Speed 2 octets
- -- Vertical Speed 1 octet
- -- Horizontal Uncertainty Speed 1 octet
- -- Vertical Uncertainty Speed 1 octet
-
-PositioningDataInformation ::= OCTET STRING (SIZE (2..maxPositioningDataInformation))
- -- Refers to the Positioning Data defined in 3GPP TS 49.031.
- -- This is composed of 2 or more octets with an internal structure according to
- -- 3GPP TS 49.031.
-
-maxPositioningDataInformation INTEGER ::= 10
- --
-
-UtranPositioningDataInfo ::= OCTET STRING (SIZE (3..maxUtranPositioningDataInfo))
- -- Refers to the Position Data defined in 3GPP TS 25.413.
- -- This is composed of the positioningDataDiscriminator and the positioningDataSet
- -- included in positionData as defined in 3GPP TS 25.413.
-
-maxUtranPositioningDataInfo INTEGER ::= 11
- --
-
-Add-GeographicalInformation ::= OCTET STRING (SIZE (1..maxAdd-GeographicalInformation))
- -- Refers to geographical Information defined in 3GPP TS 23.032.
- -- This is composed of 1 or more octets with an internal structure according to
- -- 3GPP TS 23.032
- -- Octet 1: Type of shape, all the shapes defined in 3GPP TS 23.032 are allowed:
- -- Octets 2 to n (where n is the total number of octets necessary to encode the shape
- -- according to 3GPP TS 23.032) are used to encode the shape itself in accordance with the
- -- encoding defined in 3GPP TS 23.032
- --
- -- An Add-GeographicalInformation parameter, whether valid or invalid, received
- -- together with a valid Ext-GeographicalInformation parameter in the same message
- -- shall be discarded.
- --
- -- An Add-GeographicalInformation parameter containing any shape not defined in
- -- 3GPP TS 23.032 or an incorrect number of octets or coding according to
- -- 3GPP TS 23.032 shall be treated as invalid data by a receiver if not received
- -- together with a valid Ext-GeographicalInformation parameter in the same message.
-
-maxAdd-GeographicalInformation INTEGER ::= 91
- -- the maximum length allows support for all the shapes currently defined in 3GPP TS 23.032
-
-SubscriberLocationReport-Arg ::= SEQUENCE {
- lcs-Event LCS-Event,
- lcs-ClientID LCS-ClientID,
- lcsLocationInfo LCSLocationInfo,
- msisdn [0] ISDN-AddressString OPTIONAL,
- imsi [1] IMSI OPTIONAL,
- imei [2] IMEI OPTIONAL,
- na-ESRD [3] ISDN-AddressString OPTIONAL,
- na-ESRK [4] ISDN-AddressString OPTIONAL,
- locationEstimate [5] Ext-GeographicalInformation OPTIONAL,
- ageOfLocationEstimate [6] AgeOfLocationInformation OPTIONAL,
- slr-ArgExtensionContainer [7] SLR-ArgExtensionContainer OPTIONAL,
- ... ,
- add-LocationEstimate [8] Add-GeographicalInformation OPTIONAL,
- deferredmt-lrData [9] Deferredmt-lrData OPTIONAL,
- lcs-ReferenceNumber [10] LCS-ReferenceNumber OPTIONAL,
- geranPositioningData [11] PositioningDataInformation OPTIONAL,
- utranPositioningData [12] UtranPositioningDataInfo OPTIONAL,
- cellIdOrSai [13] CellGlobalIdOrServiceAreaIdOrLAI OPTIONAL,
- h-gmlc-Address [14] GSN-Address OPTIONAL,
- lcsServiceTypeID [15] LCSServiceTypeID OPTIONAL,
- sai-Present [17] NULL OPTIONAL,
- pseudonymIndicator [18] NULL OPTIONAL,
- accuracyFulfilmentIndicator [19] AccuracyFulfilmentIndicator OPTIONAL,
- velocityEstimate [20] VelocityEstimate OPTIONAL,
- sequenceNumber [21] SequenceNumber OPTIONAL,
- periodicLDRInfo [22] PeriodicLDRInfo OPTIONAL,
- mo-lrShortCircuitIndicator [23] NULL OPTIONAL }
-
- -- one of msisdn or imsi is mandatory
- -- a location estimate that is valid for the locationEstimate parameter should
- -- be transferred in this parameter in preference to the add-LocationEstimate.
- -- the deferredmt-lrData parameter shall be included if and only if the lcs-Event
- -- indicates a deferredmt-lrResponse.
- -- if the lcs-Event indicates a deferredmt-lrResponse then the locationEstimate
- -- and the add-locationEstimate parameters shall not be sent if the
- -- supportedGADShapes parameter had been received in ProvideSubscriberLocation-Arg
- -- and the shape encoded in locationEstimate or add-LocationEstimate was not marked
- -- as supported in supportedGADShapes. In such a case terminationCause
- -- in deferredmt-lrData shall be present with value
- -- shapeOfLocationEstimateNotSupported.
- -- If a lcs event indicates deferred mt-lr response, the lcs-Reference number shall be
- -- included.
- -- sai-Present indicates that the cellIdOrSai parameter contains a Service Area Identity.
-
-Deferredmt-lrData ::= SEQUENCE {
- deferredLocationEventType DeferredLocationEventType,
- terminationCause [0] TerminationCause OPTIONAL,
- lcsLocationInfo [1] LCSLocationInfo OPTIONAL,
- ...}
- -- lcsLocationInfo may be included only if a terminationCause is present
- -- indicating mt-lrRestart.
-
-LCS-Event ::= ENUMERATED {
- emergencyCallOrigination (0),
- emergencyCallRelease (1),
- mo-lr (2),
- ...,
- deferredmt-lrResponse (3) ,
- deferredmo-lrTTTPInitiation (4) }
- -- deferredmt-lrResponse is applicable to the delivery of a location estimate
- -- for an LDR initiated earlier by either the network (via an MT-LR activate deferred
- -- location) or the UE (via a deferred MO-LR TTTP initiation)
- -- exception handling:
- -- a SubscriberLocationReport-Arg containing an unrecognized LCS-Event
- -- shall be rejected by a receiver with a return error cause of unexpected data value
-
-TerminationCause ::= ENUMERATED {
- normal (0),
- errorundefined (1),
- internalTimeout (2),
- congestion (3),
- mt-lrRestart (4),
- privacyViolation (5),
- ...,
- shapeOfLocationEstimateNotSupported (6) ,
- subscriberTermination (7),
- uETermination (8),
- networkTermination (9) }
--- mt-lrRestart shall be used to trigger the GMLC to restart the location procedure,
--- either because the sending node knows that the terminal has moved under coverage
--- of another MSC or SGSN (e.g. Send Identification received), or because the subscriber
--- has been deregistered due to a Cancel Location received from HLR.
---
--- exception handling
--- an unrecognized value shall be treated the same as value 1 (errorundefined)
-
-SequenceNumber ::= INTEGER (1..maxReportingAmount)
-
-SubscriberLocationReport-Res ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- na-ESRK [0] ISDN-AddressString OPTIONAL,
- na-ESRD [1] ISDN-AddressString OPTIONAL,
- h-gmlc-Address [2] GSN-Address OPTIONAL,
- mo-lrShortCircuitIndicator [3] NULL OPTIONAL,
- reportingPLMNList [4] ReportingPLMNList OPTIONAL,
- lcs-ReferenceNumber [5] LCS-ReferenceNumber OPTIONAL }
-
--- na-ESRK and na-ESRD are mutually exclusive
---
--- exception handling
--- receipt of both na-ESRK and na-ESRD shall be treated the same as a return error
-
-
-END
-
diff --git a/rrlp-ephemeris/asn1/MAP-MS-DataTypes.asn b/rrlp-ephemeris/asn1/MAP-MS-DataTypes.asn
deleted file mode 100644
index 9c12a02..0000000
--- a/rrlp-ephemeris/asn1/MAP-MS-DataTypes.asn
+++ /dev/null
@@ -1,2780 +0,0 @@
--- $Id: MAP-MS-DataTypes.asn 28149 2009-04-25 17:45:34Z etxrab $
--- 3GPP TS 29.002 V8.9.0 (2009-04)
--- 17.7.1 Mobile Service data types
-
-MAP-MS-DataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-MS-DataTypes (11) version11 (11)}
-
-DEFINITIONS
-
-IMPLICIT TAGS
-
-::=
-
-BEGIN
-
-EXPORTS
-
- -- location registration types
- UpdateLocationArg,
- UpdateLocationRes,
- CancelLocationArg,
- CancelLocationRes,
- PurgeMS-Arg,
- PurgeMS-Res,
- SendIdentificationArg,
- SendIdentificationRes,
- UpdateGprsLocationArg,
- UpdateGprsLocationRes,
- IST-SupportIndicator,
- SupportedLCS-CapabilitySets,
-
- -- gprs location registration types
- GSN-Address,
-
- -- handover types
- ForwardAccessSignalling-Arg,
- PrepareHO-Arg,
- PrepareHO-Res,
- PrepareSubsequentHO-Arg,
- PrepareSubsequentHO-Res,
- ProcessAccessSignalling-Arg,
- SendEndSignal-Arg,
- SendEndSignal-Res,
-
- -- authentication management types
- SendAuthenticationInfoArg,
- SendAuthenticationInfoRes,
- AuthenticationFailureReportArg,
-AuthenticationFailureReportRes,
-
- -- security management types
- Kc,
- Cksn,
-
- -- equipment management types
- CheckIMEI-Arg,
- CheckIMEI-Res,
-
- -- subscriber management types
- InsertSubscriberDataArg,
- InsertSubscriberDataRes,
- LSAIdentity,
- DeleteSubscriberDataArg,
- DeleteSubscriberDataRes,
- Ext-QoS-Subscribed,
- Ext2-QoS-Subscribed,
- Ext3-QoS-Subscribed,
- SubscriberData,
- ODB-Data,
- SubscriberStatus,
- ZoneCodeList,
- maxNumOfZoneCodes,
- O-CSI,
-D-CSI,
- O-BcsmCamelTDPCriteriaList,
- T-BCSM-CAMEL-TDP-CriteriaList,
- SS-CSI,
- ServiceKey,
- DefaultCallHandling,
- CamelCapabilityHandling,
- BasicServiceCriteria,
- SupportedCamelPhases,
- OfferedCamel4CSIs,
- OfferedCamel4Functionalities,
- maxNumOfCamelTDPData,
- CUG-Index,
- CUG-Info,
- CUG-Interlock,
- InterCUG-Restrictions,
- IntraCUG-Options,
- NotificationToMSUser,
- QoS-Subscribed,
-IST-AlertTimerValue,
- T-CSI,
- T-BcsmTriggerDetectionPoint,
-APN,
-AdditionalInfo,
-
- -- fault recovery types
- ResetArg,
- RestoreDataArg,
- RestoreDataRes,
-
--- provide subscriber info types
-GeographicalInformation,
-MS-Classmark2,
-GPRSMSClass,
-
- -- subscriber information enquiry types
- ProvideSubscriberInfoArg,
- ProvideSubscriberInfoRes,
- SubscriberInfo,
- LocationInformation,
- LocationInformationGPRS,
- RAIdentity,
- SubscriberState,
- GPRSChargingID,
-MNPInfoRes,
- RouteingNumber,
-
- -- any time information enquiry types
- AnyTimeInterrogationArg,
- AnyTimeInterrogationRes,
-
- -- any time information handling types
- AnyTimeSubscriptionInterrogationArg,
- AnyTimeSubscriptionInterrogationRes,
- AnyTimeModificationArg,
- AnyTimeModificationRes,
-
- -- subscriber data modification notification types
- NoteSubscriberDataModifiedArg,
- NoteSubscriberDataModifiedRes,
-
- -- gprs location information retrieval types
- SendRoutingInfoForGprsArg,
- SendRoutingInfoForGprsRes,
-
- -- failure reporting types
- FailureReportArg,
- FailureReportRes,
-
- -- gprs notification types
- NoteMsPresentForGprsArg,
- NoteMsPresentForGprsRes,
-
- -- Mobility Management types
-NoteMM-EventArg,
- NoteMM-EventRes,
- NumberPortabilityStatus,
- PagingArea,
-
- -- VGCS / VBS types types
-GroupId,
-Long-GroupId,
-AdditionalSubscriptions
-
-;
-
-IMPORTS
- maxNumOfSS,
- SS-SubscriptionOption,
- SS-List,
- SS-ForBS-Code,
- Password
-FROM MAP-SS-DataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-SS-DataTypes (14) version11 (11)}
-
- SS-Code
-FROM MAP-SS-Code {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-SS-Code (15) version11 (11)}
-
- Ext-BearerServiceCode
-FROM MAP-BS-Code {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-BS-Code (20) version11 (11)}
-
- Ext-TeleserviceCode
-FROM MAP-TS-Code {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-TS-Code (19) version11 (11)}
-
- AddressString,
-ISDN-AddressString,
- ISDN-SubaddressString,
- FTN-AddressString,
- AccessNetworkSignalInfo,
- IMSI,
- IMEI,
- TMSI,
- HLR-List,
- LMSI,
- Identity,
- GlobalCellId,
- CellGlobalIdOrServiceAreaIdOrLAI,
- Ext-BasicServiceCode,
- NAEA-PreferredCI,
- EMLPP-Info,
- MC-SS-Info,
- SubscriberIdentity,
- AgeOfLocationInformation,
- LCSClientExternalID,
- LCSClientInternalID,
- Ext-SS-Status,
- LCSServiceTypeID,
- ASCI-CallReference,
- TBCD-STRING,
- LAIFixedLength,
- PLMN-Id,
-EMLPP-Priority
-FROM MAP-CommonDataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-CommonDataTypes (18) version11 (11)}
-
- ExtensionContainer
-FROM MAP-ExtensionDataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
-
- AbsentSubscriberDiagnosticSM
-FROM MAP-ER-DataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-ER-DataTypes (17) version11 (11)}
-
- TracePropagationList
-FROM MAP-OM-DataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-OM-DataTypes (12) version11 (11)}
-
-;
-
--- location registration types
-
-UpdateLocationArg ::= SEQUENCE {
- imsi IMSI,
- msc-Number [1] ISDN-AddressString,
- vlr-Number ISDN-AddressString,
- lmsi [10] LMSI OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ... ,
- vlr-Capability [6] VLR-Capability OPTIONAL,
- informPreviousNetworkEntity [11] NULL OPTIONAL,
- cs-LCS-NotSupportedByUE [12] NULL OPTIONAL,
- v-gmlc-Address [2] GSN-Address OPTIONAL,
- add-info [13] ADD-Info OPTIONAL,
- pagingArea [14] PagingArea OPTIONAL,
- skipSubscriberDataUpdate [15] NULL OPTIONAL
- -- The skipSubscriberDataUpdate parameter in the UpdateLocationArg and the ADD-Info
- -- structures carry the same semantic.
- }
-
-VLR-Capability ::= SEQUENCE{
- supportedCamelPhases [0] SupportedCamelPhases OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ... ,
- solsaSupportIndicator [2] NULL OPTIONAL,
- istSupportIndicator [1] IST-SupportIndicator OPTIONAL,
- superChargerSupportedInServingNetworkEntity [3] SuperChargerInfo OPTIONAL,
- longFTN-Supported [4] NULL OPTIONAL,
- supportedLCS-CapabilitySets [5] SupportedLCS-CapabilitySets OPTIONAL,
- offeredCamel4CSIs [6] OfferedCamel4CSIs OPTIONAL,
- supportedRAT-TypesIndicator [7] SupportedRAT-Types OPTIONAL,
- longGroupID-Supported [8] NULL OPTIONAL }
-
-SupportedRAT-Types::= BIT STRING {
- utran (0),
- geran (1),
- gan (2),
- i-hspa-evolution (3),
- e-utran (4)} (SIZE (2..8))
- -- exception handling: bits 5 to 7 shall be ignored if received and not understood
-
-
-
-SuperChargerInfo ::= CHOICE {
- sendSubscriberData [0] NULL,
- subscriberDataStored [1] AgeIndicator }
-
-AgeIndicator ::= OCTET STRING (SIZE (1..6))
- -- The internal structure of this parameter is implementation specific.
-
-IST-SupportIndicator ::= ENUMERATED {
- basicISTSupported (0),
- istCommandSupported (1),
- ...}
--- exception handling:
--- reception of values > 1 shall be mapped to ' istCommandSupported '
-
-SupportedLCS-CapabilitySets ::= BIT STRING {
- lcsCapabilitySet1 (0),
- lcsCapabilitySet2 (1),
- lcsCapabilitySet3 (2),
- lcsCapabilitySet4 (3) ,
- lcsCapabilitySet5 (4) } (SIZE (2..16))
--- Core network signalling capability set1 indicates LCS Release98 or Release99 version.
--- Core network signalling capability set2 indicates LCS Release4.
--- Core network signalling capability set3 indicates LCS Release5.
--- Core network signalling capability set4 indicates LCS Release6.
--- Core network signalling capability set5 indicates LCS Release7 or later version.
--- A node shall mark in the BIT STRING all LCS capability sets it supports.
--- If no bit is set then the sending node does not support LCS.
--- If the parameter is not sent by an VLR then the VLR may support at most capability set1.
--- If the parameter is not sent by an SGSN then no support for LCS is assumed.
--- An SGSN is not allowed to indicate support of capability set1.
--- Other bits than listed above shall be discarded.
-
-UpdateLocationRes ::= SEQUENCE {
- hlr-Number ISDN-AddressString,
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- add-Capability NULL OPTIONAL,
- pagingArea-Capability [0]NULL OPTIONAL }
-
-ADD-Info ::= SEQUENCE {
- imeisv [0] IMEI,
- skipSubscriberDataUpdate [1] NULL OPTIONAL,
- -- The skipSubscriberDataUpdate parameter in the UpdateLocationArg and the ADD-Info
- -- structures carry the same semantic.
- ...}
-
-
-PagingArea ::= SEQUENCE SIZE (1..5) OF LocationArea
-
-
-LocationArea ::= CHOICE {
- laiFixedLength [0] LAIFixedLength,
- lac [1] LAC}
-
-
-LAC ::= OCTET STRING (SIZE (2))
- -- Refers to Location Area Code of the Location Area Identification defined in
- -- 3GPP TS 23.003 [17].
- -- Location Area Code according to 3GPP TS 24.008 [35]
-
-CancelLocationArg ::= [3] SEQUENCE {
- identity Identity,
- cancellationType CancellationType OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- typeOfUpdate [0] TypeOfUpdate OPTIONAL }
-
-TypeOfUpdate ::= ENUMERATED {
- sgsn-change (0),
- mme-change (1),
- ...}
- -- TypeOfUpdate shall be absent if CancellationType is different from updateProcedure
-
-CancellationType ::= ENUMERATED {
- updateProcedure (0),
- subscriptionWithdraw (1),
- ...}
- -- The HLR shall not send values other than listed above
-
-CancelLocationRes ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-PurgeMS-Arg ::= [3] SEQUENCE {
- imsi IMSI,
- vlr-Number [0] ISDN-AddressString OPTIONAL,
- sgsn-Number [1] ISDN-AddressString OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-PurgeMS-Res ::= SEQUENCE {
- freezeTMSI [0] NULL OPTIONAL,
- freezeP-TMSI [1] NULL OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- freezeM-TMSI [2] NULL OPTIONAL }
-
-SendIdentificationArg ::= SEQUENCE {
- tmsi TMSI,
- numberOfRequestedVectors NumberOfRequestedVectors OPTIONAL,
- -- within a dialogue numberOfRequestedVectors shall be present in
- -- the first service request and shall not be present in subsequent service requests.
- -- If received in a subsequent service request it shall be discarded.
- segmentationProhibited NULL OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- msc-Number ISDN-AddressString OPTIONAL,
- previous-LAI [0] LAIFixedLength OPTIONAL,
- hopCounter [1] HopCounter OPTIONAL }
-
-HopCounter ::= INTEGER (0..3)
-
-SendIdentificationRes ::= [3] SEQUENCE {
- imsi IMSI OPTIONAL,
- -- IMSI shall be present in the first (or only) service response of a dialogue.
- -- If multiple service requests are present in a dialogue then IMSI
- -- shall not be present in any service response other than the first one.
- authenticationSetList AuthenticationSetList OPTIONAL,
- currentSecurityContext [2]CurrentSecurityContext OPTIONAL,
- extensionContainer [3] ExtensionContainer OPTIONAL,
- ...}
-
--- authentication management types
-
-AuthenticationSetList ::= CHOICE {
- tripletList [0] TripletList,
- quintupletList [1] QuintupletList }
-
-TripletList ::= SEQUENCE SIZE (1..5) OF
- AuthenticationTriplet
-
-QuintupletList ::= SEQUENCE SIZE (1..5) OF
- AuthenticationQuintuplet
-
-AuthenticationTriplet ::= SEQUENCE {
- rand RAND,
- sres SRES,
- kc Kc,
- ...}
-
-AuthenticationQuintuplet ::= SEQUENCE {
- rand RAND,
- xres XRES,
- ck CK,
- ik IK,
- autn AUTN,
- ...}
-
-CurrentSecurityContext ::= CHOICE {
- gsm-SecurityContextData [0] GSM-SecurityContextData,
- umts-SecurityContextData [1] UMTS-SecurityContextData }
-
-GSM-SecurityContextData ::= SEQUENCE {
- kc Kc,
- cksn Cksn,
- ... }
-
-UMTS-SecurityContextData ::= SEQUENCE {
- ck CK,
- ik IK,
- ksi KSI,
- ... }
-
-RAND ::= OCTET STRING (SIZE (16))
-
-SRES ::= OCTET STRING (SIZE (4))
-
-Kc ::= OCTET STRING (SIZE (8))
-
-XRES ::= OCTET STRING (SIZE (4..16))
-
-CK ::= OCTET STRING (SIZE (16))
-
-IK ::= OCTET STRING (SIZE (16))
-
-AUTN ::= OCTET STRING (SIZE (16))
-
-AUTS ::= OCTET STRING (SIZE (14))
-
-Cksn ::= OCTET STRING (SIZE (1))
- -- The internal structure is defined in 3GPP TS 24.008
-
-KSI ::= OCTET STRING (SIZE (1))
- -- The internal structure is defined in 3GPP TS 24.008
-
-AuthenticationFailureReportArg ::= SEQUENCE {
- imsi IMSI,
- failureCause FailureCause,
- extensionContainer ExtensionContainer OPTIONAL,
- ... ,
- re-attempt BOOLEAN OPTIONAL,
- accessType AccessType OPTIONAL,
- rand RAND OPTIONAL,
- vlr-Number [0] ISDN-AddressString OPTIONAL,
- sgsn-Number [1] ISDN-AddressString OPTIONAL }
-
-AccessType ::= ENUMERATED {
- call (0),
- emergencyCall (1),
- locationUpdating (2),
- supplementaryService (3),
- shortMessage (4),
- gprsAttach (5),
- routingAreaUpdating (6),
- serviceRequest (7),
- pdpContextActivation (8),
- pdpContextDeactivation (9),
- ...,
- gprsDetach (10)}
- -- exception handling:
- -- received values greater than 10 shall be ignored.
-
-AuthenticationFailureReportRes ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-FailureCause ::= ENUMERATED {
- wrongUserResponse (0),
- wrongNetworkSignature (1)}
-
--- gprs location registration types
-
-UpdateGprsLocationArg ::= SEQUENCE {
- imsi IMSI,
- sgsn-Number ISDN-AddressString,
- sgsn-Address GSN-Address,
- extensionContainer ExtensionContainer OPTIONAL,
- ... ,
- sgsn-Capability [0] SGSN-Capability OPTIONAL,
- informPreviousNetworkEntity [1] NULL OPTIONAL,
- ps-LCS-NotSupportedByUE [2] NULL OPTIONAL,
- v-gmlc-Address [3] GSN-Address OPTIONAL,
- add-info [4] ADD-Info OPTIONAL,
- eps-info [5] EPS-Info OPTIONAL,
- servingNodeTypeIndicator [6] NULL OPTIONAL,
- skipSubscriberDataUpdate [7] NULL OPTIONAL,
- usedRAT-Type [8] Used-RAT-Type OPTIONAL
- }
-
-Used-RAT-Type::= ENUMERATED {
- utran (0),
- geran (1),
- gan (2),
- i-hspa-evolution (3),
- e-utran (4),
- ...}
-
-EPS-Info ::= CHOICE{
- pdn-gw-update [0] PDN-GW-Update,
- isr-Information [1] ISR-Information }
-
-PDN-GW-Update ::= SEQUENCE{
- apn [0] APN OPTIONAL,
- pdn-gw-Identity [1] PDN-GW-Identity OPTIONAL,
- contextId [2] ContextId OPTIONAL,
- extensionContainer [3] ExtensionContainer OPTIONAL,
- ... }
-
-ISR-Information::= BIT STRING {
- updateMME (0),
- cancelSGSN (1)} (SIZE (2..8))
- -- exception handling: reception of unknown bit assignments in the
- -- ISR-Information data type shall be discarded by the receiver
-
-SGSN-Capability ::= SEQUENCE{
- solsaSupportIndicator NULL OPTIONAL,
- extensionContainer [1] ExtensionContainer OPTIONAL,
- ... ,
- superChargerSupportedInServingNetworkEntity [2] SuperChargerInfo OPTIONAL ,
- gprsEnhancementsSupportIndicator [3] NULL OPTIONAL,
- supportedCamelPhases [4] SupportedCamelPhases OPTIONAL,
- supportedLCS-CapabilitySets [5] SupportedLCS-CapabilitySets OPTIONAL,
- offeredCamel4CSIs [6] OfferedCamel4CSIs OPTIONAL,
- smsCallBarringSupportIndicator [7] NULL OPTIONAL, supportedRAT-TypesIndicator [8] SupportedRAT-Types OPTIONAL,
- supportedFeatures [9] SupportedFeatures OPTIONAL }
-
-SupportedFeatures::= BIT STRING {
- odb-all (0),
- odb-HPLMN-APN (1),
- odb-VPLMN-APN (2),
- regSub (3)} (SIZE (4..8))
-
-GSN-Address ::= OCTET STRING (SIZE (5..17))
- -- Octets are coded according to TS 3GPP TS 23.003 [17]
-
-UpdateGprsLocationRes ::= SEQUENCE {
- hlr-Number ISDN-AddressString,
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- add-Capability NULL OPTIONAL,
- sgsn-mmeSeparationSupported [0] NULL OPTIONAL }
-
--- handover types
-
-ForwardAccessSignalling-Arg ::= [3] SEQUENCE {
- an-APDU AccessNetworkSignalInfo,
- integrityProtectionInfo [0] IntegrityProtectionInformation OPTIONAL,
- encryptionInfo [1] EncryptionInformation OPTIONAL,
- keyStatus [2] KeyStatus OPTIONAL,
- allowedGSM-Algorithms [4] AllowedGSM-Algorithms OPTIONAL,
- allowedUMTS-Algorithms [5] AllowedUMTS-Algorithms OPTIONAL,
- radioResourceInformation [6] RadioResourceInformation OPTIONAL,
- extensionContainer [3] ExtensionContainer OPTIONAL,
- ...,
- radioResourceList [7] RadioResourceList OPTIONAL,
- bssmap-ServiceHandover [9] BSSMAP-ServiceHandover OPTIONAL,
- ranap-ServiceHandover [8] RANAP-ServiceHandover OPTIONAL,
- bssmap-ServiceHandoverList [10] BSSMAP-ServiceHandoverList OPTIONAL,
- currentlyUsedCodec [11] Codec OPTIONAL,
- iuSupportedCodecsList [12] SupportedCodecsList OPTIONAL,
- rab-ConfigurationIndicator [13] NULL OPTIONAL,
- iuSelectedCodec [14] Codec OPTIONAL,
- alternativeChannelType [15] RadioResourceInformation OPTIONAL,
- tracePropagationList [17] TracePropagationList OPTIONAL }
-
-AllowedGSM-Algorithms ::= OCTET STRING (SIZE (1))
- -- internal structure is coded as Algorithm identifier octet from
- -- Permitted Algorithms defined in 3GPP TS 48.008
- -- A node shall mark all GSM algorithms that are allowed in MSC-B
-
-AllowedUMTS-Algorithms ::= SEQUENCE {
- integrityProtectionAlgorithms [0] PermittedIntegrityProtectionAlgorithms OPTIONAL,
- encryptionAlgorithms [1] PermittedEncryptionAlgorithms OPTIONAL,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ...}
-
-PermittedIntegrityProtectionAlgorithms ::=
- OCTET STRING (SIZE (1..maxPermittedIntegrityProtectionAlgorithmsLength))
- -- Octets contain a complete PermittedIntegrityProtectionAlgorithms data type
- -- as defined in 3GPP TS 25.413, encoded according to the encoding scheme
- -- mandated by 3GPP TS 25.413.
- -- Padding bits are included, if needed, in the least significant bits of the
- -- last octet of the octet string.
-
-
-maxPermittedIntegrityProtectionAlgorithmsLength INTEGER ::= 9
-
-PermittedEncryptionAlgorithms ::=
- OCTET STRING (SIZE (1..maxPermittedEncryptionAlgorithmsLength))
- -- Octets contain a complete PermittedEncryptionAlgorithms data type
- -- as defined in 3GPP TS 25.413, encoded according to the encoding scheme
- -- mandated by 3GPP TS 25.413
- -- Padding bits are included, if needed, in the least significant bits of the
- -- last octet of the octet string.
-
-
-maxPermittedEncryptionAlgorithmsLength INTEGER ::= 9
-
-KeyStatus ::= ENUMERATED {
- old (0),
- new (1),
- ...}
- -- exception handling:
- -- received values in range 2-31 shall be treated as "old"
- -- received values greater than 31 shall be treated as "new"
-
-PrepareHO-Arg ::= [3] SEQUENCE {
- targetCellId [0] GlobalCellId OPTIONAL,
- ho-NumberNotRequired NULL OPTIONAL,
- targetRNCId [1] RNCId OPTIONAL,
- an-APDU [2] AccessNetworkSignalInfo OPTIONAL,
- multipleBearerRequested [3] NULL OPTIONAL,
- imsi [4] IMSI OPTIONAL,
- integrityProtectionInfo [5] IntegrityProtectionInformation OPTIONAL,
- encryptionInfo [6] EncryptionInformation OPTIONAL,
- radioResourceInformation [7] RadioResourceInformation OPTIONAL,
- allowedGSM-Algorithms [9] AllowedGSM-Algorithms OPTIONAL,
- allowedUMTS-Algorithms [10] AllowedUMTS-Algorithms OPTIONAL,
- radioResourceList [11] RadioResourceList OPTIONAL,
- extensionContainer [8] ExtensionContainer OPTIONAL,
- ... ,
- rab-Id [12] RAB-Id OPTIONAL,
- bssmap-ServiceHandover [13] BSSMAP-ServiceHandover OPTIONAL,
- ranap-ServiceHandover [14] RANAP-ServiceHandover OPTIONAL,
- bssmap-ServiceHandoverList [15] BSSMAP-ServiceHandoverList OPTIONAL,
- asciCallReference [20] ASCI-CallReference OPTIONAL,
- geran-classmark [16] GERAN-Classmark OPTIONAL,
- iuCurrentlyUsedCodec [17] Codec OPTIONAL,
- iuSupportedCodecsList [18] SupportedCodecsList OPTIONAL,
- rab-ConfigurationIndicator [19] NULL OPTIONAL,
- uesbi-Iu [21] UESBI-Iu OPTIONAL,
- imeisv [22] IMEI OPTIONAL,
- alternativeChannelType [23] RadioResourceInformation OPTIONAL,
- tracePropagationList [25] TracePropagationList OPTIONAL }
-
-BSSMAP-ServiceHandoverList ::= SEQUENCE SIZE (1.. maxNumOfServiceHandovers) OF
- BSSMAP-ServiceHandoverInfo
-
-BSSMAP-ServiceHandoverInfo ::= SEQUENCE {
- bssmap-ServiceHandover BSSMAP-ServiceHandover,
- rab-Id RAB-Id,
- -- RAB Identity is needed to relate the service handovers with the radio access bearers.
- ...}
-
-maxNumOfServiceHandovers INTEGER ::= 7
-
-BSSMAP-ServiceHandover ::= OCTET STRING (SIZE (1))
- -- Octets are coded according the Service Handover information element in
- -- 3GPP TS 48.008.
-
-RANAP-ServiceHandover ::= OCTET STRING (SIZE (1))
- -- Octet contains a complete Service-Handover data type
- -- as defined in 3GPP TS 25.413, encoded according to the encoding scheme
- -- mandated by 3GPP TS 25.413
- -- Padding bits are included in the least significant bits.
-
-
-RadioResourceList ::= SEQUENCE SIZE (1.. maxNumOfRadioResources) OF
- RadioResource
-
-RadioResource ::= SEQUENCE {
- radioResourceInformation RadioResourceInformation,
- rab-Id RAB-Id,
- -- RAB Identity is needed to relate the radio resources with the radio access bearers.
- ...}
-
-maxNumOfRadioResources INTEGER ::= 7
-
-PrepareHO-Res ::= [3] SEQUENCE {
- handoverNumber [0] ISDN-AddressString OPTIONAL,
- relocationNumberList [1] RelocationNumberList OPTIONAL,
- an-APDU [2] AccessNetworkSignalInfo OPTIONAL,
- multicallBearerInfo [3] MulticallBearerInfo OPTIONAL,
- multipleBearerNotSupported NULL OPTIONAL,
- selectedUMTS-Algorithms [5] SelectedUMTS-Algorithms OPTIONAL,
- chosenRadioResourceInformation [6] ChosenRadioResourceInformation OPTIONAL,
- extensionContainer [4] ExtensionContainer OPTIONAL,
- ...,
- iuSelectedCodec [7] Codec OPTIONAL,
- iuAvailableCodecsList [8] CodecList OPTIONAL }
-
-SelectedUMTS-Algorithms ::= SEQUENCE {
- integrityProtectionAlgorithm [0] ChosenIntegrityProtectionAlgorithm OPTIONAL,
- encryptionAlgorithm [1] ChosenEncryptionAlgorithm OPTIONAL,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ...}
-
-ChosenIntegrityProtectionAlgorithm ::= OCTET STRING (SIZE (1))
- -- Octet contains a complete IntegrityProtectionAlgorithm data type
- -- as defined in 3GPP TS 25.413, encoded according to the encoding scheme
- -- mandated by 3GPP TS 25.413
- -- Padding bits are included in the least significant bits.
-
-ChosenEncryptionAlgorithm ::= OCTET STRING (SIZE (1))
- -- Octet contains a complete EncryptionAlgorithm data type
- -- as defined in 3GPP TS 25.413, encoded according to the encoding scheme
- -- mandated by 3GPP TS 25.413
- -- Padding bits are included in the least significant bits.
-
-ChosenRadioResourceInformation ::= SEQUENCE {
- chosenChannelInfo [0] ChosenChannelInfo OPTIONAL,
- chosenSpeechVersion [1] ChosenSpeechVersion OPTIONAL,
- ...}
-
-ChosenChannelInfo ::= OCTET STRING (SIZE (1))
- -- Octets are coded according the Chosen Channel information element in 3GPP TS 48.008
-
-ChosenSpeechVersion ::= OCTET STRING (SIZE (1))
- -- Octets are coded according the Speech Version (chosen) information element in 3GPP TS
- -- 48.008
-
-PrepareSubsequentHO-Arg ::= [3] SEQUENCE {
- targetCellId [0] GlobalCellId OPTIONAL,
- targetMSC-Number [1] ISDN-AddressString,
- targetRNCId [2] RNCId OPTIONAL,
- an-APDU [3] AccessNetworkSignalInfo OPTIONAL,
- selectedRab-Id [4] RAB-Id OPTIONAL,
- extensionContainer [5] ExtensionContainer OPTIONAL,
- ...,
- geran-classmark [6] GERAN-Classmark OPTIONAL,
- rab-ConfigurationIndicator [7] NULL OPTIONAL }
-
-PrepareSubsequentHO-Res ::= [3] SEQUENCE {
- an-APDU AccessNetworkSignalInfo,
- extensionContainer [0] ExtensionContainer OPTIONAL,
- ...}
-
-ProcessAccessSignalling-Arg ::= [3] SEQUENCE {
- an-APDU AccessNetworkSignalInfo,
- selectedUMTS-Algorithms [1] SelectedUMTS-Algorithms OPTIONAL,
- selectedGSM-Algorithm [2] SelectedGSM-Algorithm OPTIONAL,
- chosenRadioResourceInformation [3] ChosenRadioResourceInformation OPTIONAL,
- selectedRab-Id [4] RAB-Id OPTIONAL,
- extensionContainer [0] ExtensionContainer OPTIONAL,
- ...,
- iUSelectedCodec [5] Codec OPTIONAL,
- iuAvailableCodecsList [6] CodecList OPTIONAL }
-
-SupportedCodecsList ::= SEQUENCE {
- utranCodecList [0] CodecList OPTIONAL,
- geranCodecList [1] CodecList OPTIONAL,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ...}
-
-CodecList ::= SEQUENCE {
- codec1 [1] Codec,
- codec2 [2] Codec OPTIONAL,
- codec3 [3] Codec OPTIONAL,
- codec4 [4] Codec OPTIONAL,
- codec5 [5] Codec OPTIONAL,
- codec6 [6] Codec OPTIONAL,
- codec7 [7] Codec OPTIONAL,
- codec8 [8] Codec OPTIONAL,
- extensionContainer [9] ExtensionContainer OPTIONAL,
- ...}
- -- Codecs are sent in priority order where codec1 has highest priority
-
-Codec ::= OCTET STRING (SIZE (1..4))
-
- -- The internal structure is defined as follows:
- -- octet 1 Coded as Codec Identification code in 3GPP TS 26.103
- -- octets 2,3,4 Parameters for the Codec as defined in 3GPP TS
- -- 26.103, if available, length depending on the codec
-
-GERAN-Classmark ::= OCTET STRING (SIZE (2..87))
- -- Octets are coded according the GERAN Classmark information element in 3GPP TS 48.008
-
-SelectedGSM-Algorithm ::= OCTET STRING (SIZE (1))
- -- internal structure is coded as Algorithm identifier octet from Chosen Encryption
- -- Algorithm defined in 3GPP TS 48.008
- -- A node shall mark only the selected GSM algorithm
-
-SendEndSignal-Arg ::= [3] SEQUENCE {
- an-APDU AccessNetworkSignalInfo,
- extensionContainer [0] ExtensionContainer OPTIONAL,
- ...}
-
-SendEndSignal-Res ::= SEQUENCE {
- extensionContainer [0] ExtensionContainer OPTIONAL,
- ...}
-
-RNCId ::= OCTET STRING (SIZE (7))
- -- The internal structure is defined as follows:
- -- octet 1 bits 4321 Mobile Country Code 1st digit
- -- bits 8765 Mobile Country Code 2nd digit
- -- octet 2 bits 4321 Mobile Country Code 3rd digit
- -- bits 8765 Mobile Network Code 3rd digit
- -- or filler (1111) for 2 digit MNCs
- -- octet 3 bits 4321 Mobile Network Code 1st digit
- -- bits 8765 Mobile Network Code 2nd digit
- -- octets 4 and 5 Location Area Code according to 3GPP TS 24.008
- -- octets 6 and 7 RNC Id value according to 3GPP TS 25.413
-
-RelocationNumberList ::= SEQUENCE SIZE (1..maxNumOfRelocationNumber) OF
- RelocationNumber
-
-MulticallBearerInfo ::= INTEGER (1..maxNumOfRelocationNumber)
-
-RelocationNumber ::= SEQUENCE {
- handoverNumber ISDN-AddressString,
- rab-Id RAB-Id,
- -- RAB Identity is needed to relate the calls with the radio access bearers.
- ...}
-
-RAB-Id ::= INTEGER (1..maxNrOfRABs)
-
-maxNrOfRABs INTEGER ::= 255
-
-maxNumOfRelocationNumber INTEGER ::= 7
-
-RadioResourceInformation ::= OCTET STRING (SIZE (3..13))
- -- Octets are coded according the Channel Type information element in 3GPP TS 48.008
-
-IntegrityProtectionInformation ::= OCTET STRING (SIZE (18..maxNumOfIntegrityInfo))
- -- Octets contain a complete IntegrityProtectionInformation data type
- -- as defined in 3GPP TS 25.413, encoded according to the encoding scheme
- -- mandated by 3GPP TS 25.413
- -- Padding bits are included, if needed, in the least significant bits of the
- -- last octet of the octet string.
-
-maxNumOfIntegrityInfo INTEGER ::= 100
-
-EncryptionInformation ::= OCTET STRING (SIZE (18..maxNumOfEncryptionInfo))
- -- Octets contain a complete EncryptionInformation data type
- -- as defined in 3GPP TS 25.413, encoded according to the encoding scheme
- -- mandated by 3GPP TS 25.413
- -- Padding bits are included, if needed, in the least significant bits of the
- -- last octet of the octet string.
-
-maxNumOfEncryptionInfo INTEGER ::= 100
-
--- authentication management types
-
-SendAuthenticationInfoArg ::= SEQUENCE {
- imsi [0] IMSI,
- numberOfRequestedVectors NumberOfRequestedVectors,
- segmentationProhibited NULL OPTIONAL,
- immediateResponsePreferred [1] NULL OPTIONAL,
- re-synchronisationInfo Re-synchronisationInfo OPTIONAL,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ...,
- requestingNodeType [3] RequestingNodeType OPTIONAL,
- requestingPLMN-Id [4] PLMN-Id OPTIONAL,
- numberOfRequestedAdditional-Vectors [5] NumberOfRequestedVectors OPTIONAL,
- additionalVectorsAreForEPS [6] NULL OPTIONAL }
-
-
-NumberOfRequestedVectors ::= INTEGER (1..5)
-
-Re-synchronisationInfo ::= SEQUENCE {
- rand RAND,
- auts AUTS,
- ...}
-
-SendAuthenticationInfoRes ::= [3] SEQUENCE {
- authenticationSetList AuthenticationSetList OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- eps-AuthenticationSetList [2] EPS-AuthenticationSetList OPTIONAL }
-
-EPS-AuthenticationSetList ::= SEQUENCE SIZE (1..5) OF
- EPC-AV
-
-EPC-AV ::= SEQUENCE {
- rand RAND,
- xres XRES,
- autn AUTN,
- kasme KASME,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-KASME ::= OCTET STRING (SIZE (16))
-
-RequestingNodeType ::= ENUMERATED {
- vlr (0),
- sgsn (1),
- ...,
- s-cscf (2),
- bsf (3),
- gan-aaa-server (4),
- wlan-aaa-server (5),
- mme (16),
- mme-sgsn (17)
- }
- -- the values 2, 3, 4 and 5 shall not be used on the MAP-D or Gr interfaces
- -- exception handling:
- -- received values in the range (6-15) shall be treated as "vlr"
- -- received values greater than 17 shall be treated as "sgsn"
-
--- equipment management types
-
-CheckIMEI-Arg ::= SEQUENCE {
- imei IMEI,
- requestedEquipmentInfo RequestedEquipmentInfo,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-CheckIMEI-Res ::= SEQUENCE {
- equipmentStatus EquipmentStatus OPTIONAL,
- bmuef UESBI-Iu OPTIONAL,
- extensionContainer [0] ExtensionContainer OPTIONAL,
- ...}
-
-RequestedEquipmentInfo::= BIT STRING {
- equipmentStatus (0),
- bmuef (1)} (SIZE (2..8))
- -- exception handling: reception of unknown bit assignments in the
- -- RequestedEquipmentInfo data type shall be discarded by the receiver
-
-UESBI-Iu ::= SEQUENCE {
- uesbi-IuA [0] UESBI-IuA OPTIONAL,
- uesbi-IuB [1] UESBI-IuB OPTIONAL,
- ...}
-
-UESBI-IuA ::= BIT STRING (SIZE(1..128))
--- See 3GPP TS 25.413
-
-UESBI-IuB ::= BIT STRING (SIZE(1..128))
--- See 3GPP TS 25.413
-
-EquipmentStatus ::= ENUMERATED {
- whiteListed (0),
- blackListed (1),
- greyListed (2)}
-
--- subscriber management types
-
-InsertSubscriberDataArg ::= SEQUENCE {
- imsi [0] IMSI OPTIONAL,
- COMPONENTS OF SubscriberData,
- extensionContainer [14] ExtensionContainer OPTIONAL,
- ... ,
- naea-PreferredCI [15] NAEA-PreferredCI OPTIONAL,
- -- naea-PreferredCI is included at the discretion of the HLR operator.
- gprsSubscriptionData [16] GPRSSubscriptionData OPTIONAL,
- roamingRestrictedInSgsnDueToUnsupportedFeature [23] NULL
- OPTIONAL,
- networkAccessMode [24] NetworkAccessMode OPTIONAL,
- lsaInformation [25] LSAInformation OPTIONAL,
- lmu-Indicator [21] NULL OPTIONAL,
- lcsInformation [22] LCSInformation OPTIONAL,
- istAlertTimer [26] IST-AlertTimerValue OPTIONAL,
- superChargerSupportedInHLR [27] AgeIndicator OPTIONAL,
- mc-SS-Info [28] MC-SS-Info OPTIONAL,
- cs-AllocationRetentionPriority [29] CS-AllocationRetentionPriority OPTIONAL,
- sgsn-CAMEL-SubscriptionInfo [17] SGSN-CAMEL-SubscriptionInfo OPTIONAL,
- chargingCharacteristics [18] ChargingCharacteristics OPTIONAL,
- accessRestrictionData [19] AccessRestrictionData OPTIONAL,
- ics-Indicator [20] BOOLEAN OPTIONAL,
- eps-SubscriptionData [31] EPS-SubscriptionData OPTIONAL,
- csg-SubscriptionDataList [32] CSG-SubscriptionDataList OPTIONAL }
- -- If the Network Access Mode parameter is sent, it shall be present only in
- -- the first sequence if seqmentation is used
-
-CSG-SubscriptionDataList ::= SEQUENCE SIZE (1..50) OF
- CSG-SubscriptionData
-
-CSG-SubscriptionData ::= SEQUENCE {
- csg-Id CSG-Id,
- expirationDate Time OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-CSG-Id ::= BIT STRING (SIZE (27))
- -- coded according to 3GPP TS 23.003 [17].
-
-Time ::= OCTET STRING (SIZE (4))
- -- Octets are coded according to IETF RFC 3588 [139]
-
-
-EPS-SubscriptionData ::= SEQUENCE {
- apn-oi-Replacement [0] APN-OI-Replacement OPTIONAL,
- rfsp-id [2] RFSP-ID OPTIONAL,
- ambr [3] AMBR OPTIONAL,
- apn-ConfigurationProfile [4] APN-ConfigurationProfile OPTIONAL,
- stn-sr [6] ISDN-AddressString OPTIONAL,
- extensionContainer [5] ExtensionContainer OPTIONAL,
- ... }
-
-APN-OI-Replacement ::= OCTET STRING (SIZE (9..100))
- -- Octets are coded as APN Operator Identifier according to TS 3GPP TS 23.003 [17]
-
-RFSP-ID ::= INTEGER (1..256)
-
-APN-ConfigurationProfile ::= SEQUENCE {
- defaultContext ContextId,
- completeDataListIncluded NULL OPTIONAL,
- -- If segmentation is used, completeDataListIncluded may only be present in the
- -- first segment of APN-ConfigurationProfile.
- epsDataList [1] EPS-DataList,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ... }
-
-EPS-DataList ::= SEQUENCE SIZE (1..maxNumOfAPN-Configurations) OF
- APN-Configuration
-
-
-maxNumOfAPN-Configurations INTEGER ::= 50
-
-
-APN-Configuration ::= SEQUENCE {
- contextId [0] ContextId,
- servedPartyIP-Address [1] PDP-Address OPTIONAL,
- apn [2] APN,
- eps-qos-Subscribed [3] EPS-QoS-Subscribed,
- pdn-gw-Identity [4] PDN-GW-Identity OPTIONAL,
- pdn-gw-AllocationType [5] PDN-GW-AllocationType OPTIONAL,
- vplmnAddressAllowed [6] NULL OPTIONAL,
- chargingCharacteristics [7] ChargingCharacteristics OPTIONAL,
- ambr [8] AMBR OPTIONAL,
- specificAPNInfoList [9] SpecificAPNInfoList OPTIONAL, extensionContainer [10] ExtensionContainer OPTIONAL,
- ... }
-
-EPS-QoS-Subscribed ::= SEQUENCE {
- qos-Class-Identifier [0] QoS-Class-Identifier,
- allocation-Retention-Priority [1] Allocation-Retention-Priority,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ... }
-
-AMBR ::= SEQUENCE {
- max-RequestedBandwidth-UL [0] Bandwidth,
- max-RequestedBandwidth-DL [1] Bandwidth,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ... }
-
-
-SpecificAPNInfoList ::= SEQUENCE SIZE (1..maxNumOfSpecificAPNInfos) OF
- SpecificAPNInfo
-
-maxNumOfSpecificAPNInfos INTEGER ::= 50
-
-SpecificAPNInfo ::= SEQUENCE {
- apn [0] APN,
- pdn-gw-Identity [1] PDN-GW-Identity,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ... }
-
-Bandwidth ::= INTEGER
- -- bits per second
-
-QoS-Class-Identifier ::= INTEGER (1..9)
- -- values are defined in 3GPP TS 29.212
-
-
-
-Allocation-Retention-Priority ::= SEQUENCE {
- priority-level [0] INTEGER,
- pre-emption-capability [1] BOOLEAN OPTIONAL,
- pre-emption-vulnerability [2] BOOLEAN OPTIONAL,
- extensionContainer [3] ExtensionContainer OPTIONAL,
- ... }
-
-PDN-GW-Identity ::= SEQUENCE {
- pdn-gw-ipv4-Address [0] PDP-Address OPTIONAL,
- pdn-gw-ipv6-Address [1] PDP-Address OPTIONAL,
- pdn-gw-name [2] FQDN OPTIONAL,
- extensionContainer [3] ExtensionContainer OPTIONAL,
- ... }
-
-FQDN ::= OCTET STRING (SIZE (9..100))
-
-
-PDN-GW-AllocationType ::= ENUMERATED {
- static (0),
- dynamic (1)}
-
-
-AccessRestrictionData ::= BIT STRING {
- utranNotAllowed (0),
- geranNotAllowed (1),
- ganNotAllowed (2),
- i-hspa-evolutionNotAllowed (3),
- e-utranNotAllowed (4),
- ho-toNon3GPP-AccessNotAllowed (5) } (SIZE (2..8))
- -- exception handling:
- -- access restriction data related to an access type not supported by a node
- -- shall be ignored
- -- bits 6 to 7 shall be ignored if received and not understood
-
-
-CS-AllocationRetentionPriority ::= OCTET STRING (SIZE (1))
- -- This data type encodes each priority level defined in TS 23.107 as the binary value
- -- of the priority level.
-
-IST-AlertTimerValue ::= INTEGER (15..255)
-
-LCSInformation ::= SEQUENCE {
- gmlc-List [0] GMLC-List OPTIONAL,
- lcs-PrivacyExceptionList [1] LCS-PrivacyExceptionList OPTIONAL,
- molr-List [2] MOLR-List OPTIONAL,
- ...,
- add-lcs-PrivacyExceptionList [3] LCS-PrivacyExceptionList OPTIONAL }
- -- add-lcs-PrivacyExceptionList may be sent only if lcs-PrivacyExceptionList is
- -- present and contains four instances of LCS-PrivacyClass. If the mentioned condition
- -- is not satisfied the receiving node shall discard add-lcs-PrivacyExceptionList.
- -- If an LCS-PrivacyClass is received both in lcs-PrivacyExceptionList and in
- -- add-lcs-PrivacyExceptionList with the same SS-Code, then the error unexpected
- -- data value shall be returned.
-
-GMLC-List ::= SEQUENCE SIZE (1..maxNumOfGMLC) OF
- ISDN-AddressString
- -- if segmentation is used, the complete GMLC-List shall be sent in one segment
-
-maxNumOfGMLC INTEGER ::= 5
-
-NetworkAccessMode ::= ENUMERATED {
- packetAndCircuit (0),
- onlyCircuit (1),
- onlyPacket (2),
- ...}
- -- if unknown values are received in NetworkAccessMode
- -- they shall be discarded.
-
-GPRSDataList ::= SEQUENCE SIZE (1..maxNumOfPDP-Contexts) OF
- PDP-Context
-
-maxNumOfPDP-Contexts INTEGER ::= 50
-
-PDP-Context ::= SEQUENCE {
- pdp-ContextId ContextId,
- pdp-Type [16] PDP-Type,
- pdp-Address [17] PDP-Address OPTIONAL,
- qos-Subscribed [18] QoS-Subscribed,
- vplmnAddressAllowed [19] NULL OPTIONAL,
- apn [20] APN,
- extensionContainer [21] ExtensionContainer OPTIONAL,
- ... ,
- ext-QoS-Subscribed [0] Ext-QoS-Subscribed OPTIONAL,
- pdp-ChargingCharacteristics [1] ChargingCharacteristics OPTIONAL,
- ext2-QoS-Subscribed [2] Ext2-QoS-Subscribed OPTIONAL,
- -- ext2-QoS-Subscribed may be present only if ext-QoS-Subscribed is present.
- ext3-QoS-Subscribed [3] Ext3-QoS-Subscribed OPTIONAL
- -- ext3-QoS-Subscribed may be present only if ext2-QoS-Subscribed is present.
- }
-
-ContextId ::= INTEGER (1..maxNumOfPDP-Contexts)
-
-GPRSSubscriptionData ::= SEQUENCE {
- completeDataListIncluded NULL OPTIONAL,
- -- If segmentation is used, completeDataListIncluded may only be present in the
- -- first segment of GPRSSubscriptionData.
- gprsDataList [1] GPRSDataList,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ... }
-
-SGSN-CAMEL-SubscriptionInfo ::= SEQUENCE {
- gprs-CSI [0] GPRS-CSI OPTIONAL,
- mo-sms-CSI [1] SMS-CSI OPTIONAL,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ...,
- mt-sms-CSI [3] SMS-CSI OPTIONAL,
- mt-smsCAMELTDP-CriteriaList [4] MT-smsCAMELTDP-CriteriaList OPTIONAL,
- mg-csi [5] MG-CSI OPTIONAL
- }
-
-GPRS-CSI ::= SEQUENCE {
- gprs-CamelTDPDataList [0] GPRS-CamelTDPDataList OPTIONAL,
- camelCapabilityHandling [1] CamelCapabilityHandling OPTIONAL,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- notificationToCSE [3] NULL OPTIONAL,
- csi-Active [4] NULL OPTIONAL,
- ...}
--- notificationToCSE and csi-Active shall not be present when GPRS-CSI is sent to SGSN.
--- They may only be included in ATSI/ATM ack/NSDC message.
--- GPRS-CamelTDPData and camelCapabilityHandling shall be present in
--- the GPRS-CSI sequence.
--- If GPRS-CSI is segmented, gprs-CamelTDPDataList and camelCapabilityHandling shall be
--- present in the first segment
-
-GPRS-CamelTDPDataList ::= SEQUENCE SIZE (1..maxNumOfCamelTDPData) OF
- GPRS-CamelTDPData
--- GPRS-CamelTDPDataList shall not contain more than one instance of
--- GPRS-CamelTDPData containing the same value for gprs-TriggerDetectionPoint.
-
-GPRS-CamelTDPData ::= SEQUENCE {
- gprs-TriggerDetectionPoint [0] GPRS-TriggerDetectionPoint,
- serviceKey [1] ServiceKey,
- gsmSCF-Address [2] ISDN-AddressString,
- defaultSessionHandling [3] DefaultGPRS-Handling,
- extensionContainer [4] ExtensionContainer OPTIONAL,
- ...
- }
-
-DefaultGPRS-Handling ::= ENUMERATED {
- continueTransaction (0) ,
- releaseTransaction (1) ,
- ...}
--- exception handling:
--- reception of values in range 2-31 shall be treated as "continueTransaction"
--- reception of values greater than 31 shall be treated as "releaseTransaction"
-
-GPRS-TriggerDetectionPoint ::= ENUMERATED {
- attach (1),
- attachChangeOfPosition (2),
- pdp-ContextEstablishment (11),
- pdp-ContextEstablishmentAcknowledgement (12),
- pdp-ContextChangeOfPosition (14),
- ... }
--- exception handling:
--- For GPRS-CamelTDPData sequences containing this parameter with any
--- other value than the ones listed the receiver shall ignore the whole
--- GPRS-CamelTDPDatasequence.
-
-APN ::= OCTET STRING (SIZE (2..63))
- -- Octets are coded according to TS 3GPP TS 23.003 [17]
-
-PDP-Type ::= OCTET STRING (SIZE (2))
- -- Octets are coded according to TS 3GPP TS 29.060 [105]
-
-PDP-Address ::= OCTET STRING (SIZE (1..16))
- -- Octets are coded according to TS 3GPP TS 29.060 [105]
-
- -- The possible size values are:
- -- 1-7 octets X.25 address type
- -- 4 octets IPv4 address type
- -- 16 octets Ipv6 address type
-
-QoS-Subscribed ::= OCTET STRING (SIZE (3))
- -- Octets are coded according to TS 3GPP TS 24.008 [35] Quality of Service Octets
- -- 3-5.
-
-Ext-QoS-Subscribed ::= OCTET STRING (SIZE (1..9))
- -- OCTET 1:
- -- Allocation/Retention Priority (This octet encodes each priority level defined in
- -- 23.107 as the binary value of the priority level, declaration in 29.060)
- -- Octets 2-9 are coded according to 3GPP TS 24.008 [35] Quality of Service Octets
- -- 6-13.
-
-Ext2-QoS-Subscribed ::= OCTET STRING (SIZE (1..3))
- -- Octets 1-3 are coded according to 3GPP TS 24.008 [35] Quality of Service Octets 14-16.
- -- If Quality of Service information is structured with 14 octet length, then
- -- Octet 1 is coded according to 3GPP TS 24.008 [35] Quality of Service Octet 14.
-
-Ext3-QoS-Subscribed ::= OCTET STRING (SIZE (1..2))
- -- Octets 1-2 are coded according to 3GPP TS 24.008 [35] Quality of Service Octets 17-18.
-
-ChargingCharacteristics ::= OCTET STRING (SIZE (2))
- -- Octets are coded according to 3GPP TS 32.215.
-
-LSAOnlyAccessIndicator ::= ENUMERATED {
- accessOutsideLSAsAllowed (0),
- accessOutsideLSAsRestricted (1)}
-
-LSADataList ::= SEQUENCE SIZE (1..maxNumOfLSAs) OF
- LSAData
-
-maxNumOfLSAs INTEGER ::= 20
-
-LSAData ::= SEQUENCE {
- lsaIdentity [0] LSAIdentity,
- lsaAttributes [1] LSAAttributes,
- lsaActiveModeIndicator [2] NULL OPTIONAL,
- extensionContainer [3] ExtensionContainer OPTIONAL,
- ...}
-
-LSAInformation ::= SEQUENCE {
- completeDataListIncluded NULL OPTIONAL,
-
- -- If segmentation is used, completeDataListIncluded may only be present in the
- -- first segment.
- lsaOnlyAccessIndicator [1] LSAOnlyAccessIndicator OPTIONAL,
- lsaDataList [2] LSADataList OPTIONAL,
- extensionContainer [3] ExtensionContainer OPTIONAL,
- ...}
-
-LSAIdentity ::= OCTET STRING (SIZE (3))
- -- Octets are coded according to TS 3GPP TS 23.003 [17]
-
-LSAAttributes ::= OCTET STRING (SIZE (1))
- -- Octets are coded according to TS 3GPP TS 48.008 [49]
-
-SubscriberData ::= SEQUENCE {
- msisdn [1] ISDN-AddressString OPTIONAL,
- category [2] Category OPTIONAL,
- subscriberStatus [3] SubscriberStatus OPTIONAL,
- bearerServiceList [4] BearerServiceList OPTIONAL,
- -- The exception handling for reception of unsupported / not allocated
- -- bearerServiceCodes is defined in section 8.8.1
- teleserviceList [6] TeleserviceList OPTIONAL,
- -- The exception handling for reception of unsupported / not allocated
- -- teleserviceCodes is defined in section 8.8.1
- provisionedSS [7] Ext-SS-InfoList OPTIONAL,
- odb-Data [8] ODB-Data OPTIONAL,
- roamingRestrictionDueToUnsupportedFeature [9] NULL OPTIONAL,
- regionalSubscriptionData [10] ZoneCodeList OPTIONAL,
- vbsSubscriptionData [11] VBSDataList OPTIONAL,
- vgcsSubscriptionData [12] VGCSDataList OPTIONAL,
- vlrCamelSubscriptionInfo [13] VlrCamelSubscriptionInfo OPTIONAL
- }
-
-Category ::= OCTET STRING (SIZE (1))
- -- The internal structure is defined in ITU-T Rec Q.763.
-
-SubscriberStatus ::= ENUMERATED {
- serviceGranted (0),
- operatorDeterminedBarring (1)}
-
-BearerServiceList ::= SEQUENCE SIZE (1..maxNumOfBearerServices) OF
- Ext-BearerServiceCode
-
-maxNumOfBearerServices INTEGER ::= 50
-
-TeleserviceList ::= SEQUENCE SIZE (1..maxNumOfTeleservices) OF
- Ext-TeleserviceCode
-
-maxNumOfTeleservices INTEGER ::= 20
-
-ODB-Data ::= SEQUENCE {
- odb-GeneralData ODB-GeneralData,
- odb-HPLMN-Data ODB-HPLMN-Data OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-ODB-GeneralData ::= BIT STRING {
- allOG-CallsBarred (0),
- internationalOGCallsBarred (1),
- internationalOGCallsNotToHPLMN-CountryBarred (2),
- interzonalOGCallsBarred (6),
- interzonalOGCallsNotToHPLMN-CountryBarred (7),
- interzonalOGCallsAndInternationalOGCallsNotToHPLMN-CountryBarred (8),
- premiumRateInformationOGCallsBarred (3),
- premiumRateEntertainementOGCallsBarred (4),
- ss-AccessBarred (5),
- allECT-Barred (9),
- chargeableECT-Barred (10),
- internationalECT-Barred (11),
- interzonalECT-Barred (12),
- doublyChargeableECT-Barred (13),
- multipleECT-Barred (14),
- allPacketOrientedServicesBarred (15),
- roamerAccessToHPLMN-AP-Barred (16),
- roamerAccessToVPLMN-AP-Barred (17),
- roamingOutsidePLMNOG-CallsBarred (18),
- allIC-CallsBarred (19),
- roamingOutsidePLMNIC-CallsBarred (20),
- roamingOutsidePLMNICountryIC-CallsBarred (21),
- roamingOutsidePLMN-Barred (22),
- roamingOutsidePLMN-CountryBarred (23),
- registrationAllCF-Barred (24),
- registrationCFNotToHPLMN-Barred (25),
- registrationInterzonalCF-Barred (26),
- registrationInterzonalCFNotToHPLMN-Barred (27),
- registrationInternationalCF-Barred (28)} (SIZE (15..32))
- -- exception handling: reception of unknown bit assignments in the
- -- ODB-GeneralData type shall be treated like unsupported ODB-GeneralData
- -- When the ODB-GeneralData type is removed from the HLR for a given subscriber,
- -- in NoteSubscriberDataModified operation sent toward the gsmSCF
- -- all bits shall be set to "O".
-
-ODB-HPLMN-Data ::= BIT STRING {
- plmn-SpecificBarringType1 (0),
- plmn-SpecificBarringType2 (1),
- plmn-SpecificBarringType3 (2),
- plmn-SpecificBarringType4 (3)} (SIZE (4..32))
- -- exception handling: reception of unknown bit assignments in the
- -- ODB-HPLMN-Data type shall be treated like unsupported ODB-HPLMN-Data
- -- When the ODB-HPLMN-Data type is removed from the HLR for a given subscriber,
- -- in NoteSubscriberDataModified operation sent toward the gsmSCF
- -- all bits shall be set to "O".
-
-Ext-SS-InfoList ::= SEQUENCE SIZE (1..maxNumOfSS) OF
- Ext-SS-Info
-
-Ext-SS-Info ::= CHOICE {
- forwardingInfo [0] Ext-ForwInfo,
- callBarringInfo [1] Ext-CallBarInfo,
- cug-Info [2] CUG-Info,
- ss-Data [3] Ext-SS-Data,
- emlpp-Info [4] EMLPP-Info}
-
-Ext-ForwInfo ::= SEQUENCE {
- ss-Code SS-Code,
- forwardingFeatureList Ext-ForwFeatureList,
- extensionContainer [0] ExtensionContainer OPTIONAL,
- ...}
-
-Ext-ForwFeatureList ::= SEQUENCE SIZE (1..maxNumOfExt-BasicServiceGroups) OF
- Ext-ForwFeature
-
-Ext-ForwFeature ::= SEQUENCE {
- basicService Ext-BasicServiceCode OPTIONAL,
- ss-Status [4] Ext-SS-Status,
- forwardedToNumber [5] ISDN-AddressString OPTIONAL,
- -- When this data type is sent from an HLR which supports CAMEL Phase 2
- -- to a VLR that supports CAMEL Phase 2 the VLR shall not check the
- -- format of the number
- forwardedToSubaddress [8] ISDN-SubaddressString OPTIONAL,
- forwardingOptions [6] Ext-ForwOptions OPTIONAL,
- noReplyConditionTime [7] Ext-NoRepCondTime OPTIONAL,
- extensionContainer [9] ExtensionContainer OPTIONAL,
- ...,
- longForwardedToNumber [10] FTN-AddressString OPTIONAL }
-
-Ext-ForwOptions ::= OCTET STRING (SIZE (1..5))
-
- -- OCTET 1:
-
- -- bit 8: notification to forwarding party
- -- 0 no notification
- -- 1 notification
-
- -- bit 7: redirecting presentation
- -- 0 no presentation
- -- 1 presentation
-
- -- bit 6: notification to calling party
- -- 0 no notification
- -- 1 notification
-
- -- bit 5: 0 (unused)
-
- -- bits 43: forwarding reason
- -- 00 ms not reachable
- -- 01 ms busy
- -- 10 no reply
- -- 11 unconditional
-
- -- bits 21: 00 (unused)
-
- -- OCTETS 2-5: reserved for future use. They shall be discarded if
- -- received and not understood.
-
-Ext-NoRepCondTime ::= INTEGER (1..100)
- -- Only values 5-30 are used.
- -- Values in the ranges 1-4 and 31-100 are reserved for future use
- -- If received:
- -- values 1-4 shall be mapped on to value 5
- -- values 31-100 shall be mapped on to value 30
-
-Ext-CallBarInfo ::= SEQUENCE {
- ss-Code SS-Code,
- callBarringFeatureList Ext-CallBarFeatureList,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-Ext-CallBarFeatureList ::= SEQUENCE SIZE (1..maxNumOfExt-BasicServiceGroups) OF
- Ext-CallBarringFeature
-
-Ext-CallBarringFeature ::= SEQUENCE {
- basicService Ext-BasicServiceCode OPTIONAL,
- ss-Status [4] Ext-SS-Status,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-CUG-Info ::= SEQUENCE {
- cug-SubscriptionList CUG-SubscriptionList,
- cug-FeatureList CUG-FeatureList OPTIONAL,
- extensionContainer [0] ExtensionContainer OPTIONAL,
- ...}
-
-CUG-SubscriptionList ::= SEQUENCE SIZE (0..maxNumOfCUG) OF
- CUG-Subscription
-
-CUG-Subscription ::= SEQUENCE {
- cug-Index CUG-Index,
- cug-Interlock CUG-Interlock,
- intraCUG-Options IntraCUG-Options,
- basicServiceGroupList Ext-BasicServiceGroupList OPTIONAL,
- extensionContainer [0] ExtensionContainer OPTIONAL,
- ...}
-
-CUG-Index ::= INTEGER (0..32767)
- -- The internal structure is defined in ETS 300 138.
-
-CUG-Interlock ::= OCTET STRING (SIZE (4))
-
-IntraCUG-Options ::= ENUMERATED {
- noCUG-Restrictions (0),
- cugIC-CallBarred (1),
- cugOG-CallBarred (2)}
-
-maxNumOfCUG INTEGER ::= 10
-
-CUG-FeatureList ::= SEQUENCE SIZE (1..maxNumOfExt-BasicServiceGroups) OF
- CUG-Feature
-
-Ext-BasicServiceGroupList ::= SEQUENCE SIZE (1..maxNumOfExt-BasicServiceGroups) OF
- Ext-BasicServiceCode
-
-maxNumOfExt-BasicServiceGroups INTEGER ::= 32
-
-CUG-Feature ::= SEQUENCE {
- basicService Ext-BasicServiceCode OPTIONAL,
- preferentialCUG-Indicator CUG-Index OPTIONAL,
- interCUG-Restrictions InterCUG-Restrictions,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-InterCUG-Restrictions ::= OCTET STRING (SIZE (1))
-
- -- bits 876543: 000000 (unused)
- -- Exception handling:
- -- bits 876543 shall be ignored if received and not understood
-
- -- bits 21
- -- 00 CUG only facilities
- -- 01 CUG with outgoing access
- -- 10 CUG with incoming access
- -- 11 CUG with both outgoing and incoming access
-
-Ext-SS-Data ::= SEQUENCE {
- ss-Code SS-Code,
- ss-Status [4] Ext-SS-Status,
- ss-SubscriptionOption SS-SubscriptionOption OPTIONAL,
- basicServiceGroupList Ext-BasicServiceGroupList OPTIONAL,
- extensionContainer [5] ExtensionContainer OPTIONAL,
- ...}
-
-LCS-PrivacyExceptionList ::= SEQUENCE SIZE (1..maxNumOfPrivacyClass) OF
- LCS-PrivacyClass
-
-maxNumOfPrivacyClass INTEGER ::= 4
-
-LCS-PrivacyClass ::= SEQUENCE {
- ss-Code SS-Code,
- ss-Status Ext-SS-Status,
- notificationToMSUser [0] NotificationToMSUser OPTIONAL,
- -- notificationToMSUser may be sent only for SS-codes callSessionRelated
- -- and callSessionUnrelated. If not received for SS-codes callSessionRelated
- -- and callSessionUnrelated,
- -- the default values according to 3GPP TS 23.271 shall be assumed.
- externalClientList [1] ExternalClientList OPTIONAL,
- -- externalClientList may be sent only for SS-code callSessionUnrelated to a
- -- visited node that does not support LCS Release 4 or later versions.
- -- externalClientList may be sent only for SS-codes callSessionUnrelated and
- -- callSessionRelated to a visited node that supports LCS Release 4 or later versions.
- plmnClientList [2] PLMNClientList OPTIONAL,
- -- plmnClientList may be sent only for SS-code plmnoperator.
- extensionContainer [3] ExtensionContainer OPTIONAL,
- ...,
- ext-externalClientList [4] Ext-ExternalClientList OPTIONAL,
- -- Ext-externalClientList may be sent only if the visited node supports LCS Release 4 or
- -- later versions, the user did specify more than 5 clients, and White Book SCCP is used.
- serviceTypeList [5] ServiceTypeList OPTIONAL
- -- serviceTypeList may be sent only for SS-code serviceType and if the visited node
- -- supports LCS Release 5 or later versions.
- --
- -- if segmentation is used, the complete LCS-PrivacyClass shall be sent in one segment
-}
-
-ExternalClientList ::= SEQUENCE SIZE (0..maxNumOfExternalClient) OF
- ExternalClient
-
-maxNumOfExternalClient INTEGER ::= 5
-
-PLMNClientList ::= SEQUENCE SIZE (1..maxNumOfPLMNClient) OF
- LCSClientInternalID
-
-maxNumOfPLMNClient INTEGER ::= 5
-
-Ext-ExternalClientList ::= SEQUENCE SIZE (1..maxNumOfExt-ExternalClient) OF
- ExternalClient
-
-maxNumOfExt-ExternalClient INTEGER ::= 35
-
-ExternalClient ::= SEQUENCE {
- clientIdentity LCSClientExternalID,
- gmlc-Restriction [0] GMLC-Restriction OPTIONAL,
- notificationToMSUser [1] NotificationToMSUser OPTIONAL,
- -- If notificationToMSUser is not received, the default value according to
- -- 3GPP TS 23.271 shall be assumed.
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ... }
-
-GMLC-Restriction ::= ENUMERATED {
- gmlc-List (0),
- home-Country (1) ,
- ... }
--- exception handling:
--- At reception of any other value than the ones listed the receiver shall ignore
--- GMLC-Restriction.
-
-NotificationToMSUser ::= ENUMERATED {
- notifyLocationAllowed (0),
- notifyAndVerify-LocationAllowedIfNoResponse (1),
- notifyAndVerify-LocationNotAllowedIfNoResponse (2),
- ...,
- locationNotAllowed (3) }
--- exception handling:
--- At reception of any other value than the ones listed the receiver shall ignore
--- NotificationToMSUser.
-
-ServiceTypeList ::= SEQUENCE SIZE (1..maxNumOfServiceType) OF
- ServiceType
-
-maxNumOfServiceType INTEGER ::= 32
-
-ServiceType ::= SEQUENCE {
- serviceTypeIdentity LCSServiceTypeID,
- gmlc-Restriction [0] GMLC-Restriction OPTIONAL,
- notificationToMSUser [1] NotificationToMSUser OPTIONAL,
- -- If notificationToMSUser is not received, the default value according to
- -- 3GPP TS 23.271 shall be assumed.
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ... }
-
-MOLR-List ::= SEQUENCE SIZE (1..maxNumOfMOLR-Class) OF
- MOLR-Class
-
-maxNumOfMOLR-Class INTEGER ::= 3
-
-MOLR-Class ::= SEQUENCE {
- ss-Code SS-Code,
- ss-Status Ext-SS-Status,
- extensionContainer [0] ExtensionContainer OPTIONAL,
- ...}
-
-ZoneCodeList ::= SEQUENCE SIZE (1..maxNumOfZoneCodes)
- OF ZoneCode
-
-ZoneCode ::= OCTET STRING (SIZE (2))
- -- internal structure is defined in TS 3GPP TS 23.003 [17]
-
-maxNumOfZoneCodes INTEGER ::= 10
-
-InsertSubscriberDataRes ::= SEQUENCE {
- teleserviceList [1] TeleserviceList OPTIONAL,
- bearerServiceList [2] BearerServiceList OPTIONAL,
- ss-List [3] SS-List OPTIONAL,
- odb-GeneralData [4] ODB-GeneralData OPTIONAL,
- regionalSubscriptionResponse [5] RegionalSubscriptionResponse OPTIONAL,
- supportedCamelPhases [6] SupportedCamelPhases OPTIONAL,
- extensionContainer [7] ExtensionContainer OPTIONAL,
- ... ,
- offeredCamel4CSIs [8] OfferedCamel4CSIs OPTIONAL,
- supportedFeatures [9] SupportedFeatures OPTIONAL }
-
-RegionalSubscriptionResponse ::= ENUMERATED {
- networkNode-AreaRestricted (0),
- tooManyZoneCodes (1),
- zoneCodesConflict (2),
- regionalSubscNotSupported (3)}
-
-DeleteSubscriberDataArg ::= SEQUENCE {
- imsi [0] IMSI,
- basicServiceList [1] BasicServiceList OPTIONAL,
- -- The exception handling for reception of unsupported/not allocated
- -- basicServiceCodes is defined in section 6.8.2
- ss-List [2] SS-List OPTIONAL,
- roamingRestrictionDueToUnsupportedFeature [4] NULL OPTIONAL,
- regionalSubscriptionIdentifier [5] ZoneCode OPTIONAL,
- vbsGroupIndication [7] NULL OPTIONAL,
- vgcsGroupIndication [8] NULL OPTIONAL,
- camelSubscriptionInfoWithdraw [9] NULL OPTIONAL,
- extensionContainer [6] ExtensionContainer OPTIONAL,
- ...,
- gprsSubscriptionDataWithdraw [10] GPRSSubscriptionDataWithdraw OPTIONAL,
- roamingRestrictedInSgsnDueToUnsuppportedFeature [11] NULL OPTIONAL,
- lsaInformationWithdraw [12] LSAInformationWithdraw OPTIONAL,
- gmlc-ListWithdraw [13] NULL OPTIONAL,
- istInformationWithdraw [14] NULL OPTIONAL,
- specificCSI-Withdraw [15] SpecificCSI-Withdraw OPTIONAL,
- chargingCharacteristicsWithdraw [16] NULL OPTIONAL,
- stn-srWithdraw [17] NULL OPTIONAL,
- epsSubscriptionDataWithdraw [18] EPS-SubscriptionDataWithdraw OPTIONAL,
- apn-oi-replacementWithdraw [19] NULL OPTIONAL,
- csg-SubscriptionDeleted [20] NULL OPTIONAL }
-
-SpecificCSI-Withdraw ::= BIT STRING {
- o-csi (0),
- ss-csi (1),
- tif-csi (2),
- d-csi (3),
- vt-csi (4),
- mo-sms-csi (5),
- m-csi (6),
- gprs-csi (7),
- t-csi (8),
- mt-sms-csi (9),
- mg-csi (10),
- o-IM-CSI (11),
- d-IM-CSI (12),
- vt-IM-CSI (13) } (SIZE(8..32))
--- exception handling:
--- bits 11 to 31 shall be ignored if received by a non-IP Multimedia Core Network entity.
--- bits 0-10 and 14-31 shall be ignored if received by an IP Multimedia Core Network entity.
--- bits 11-13 are only applicable in an IP Multimedia Core Network.
--- Bit 8 and bits 11-13 are only applicable for the NoteSubscriberDataModified operation.
-
-GPRSSubscriptionDataWithdraw ::= CHOICE {
- allGPRSData NULL,
- contextIdList ContextIdList}
-
-EPS-SubscriptionDataWithdraw ::= CHOICE {
- allEPS-Data NULL,
- contextIdList ContextIdList}
-
-ContextIdList ::= SEQUENCE SIZE (1..maxNumOfPDP-Contexts) OF
- ContextId
-
-LSAInformationWithdraw ::= CHOICE {
- allLSAData NULL,
- lsaIdentityList LSAIdentityList }
-
-LSAIdentityList ::= SEQUENCE SIZE (1..maxNumOfLSAs) OF
- LSAIdentity
-
-BasicServiceList ::= SEQUENCE SIZE (1..maxNumOfBasicServices) OF
- Ext-BasicServiceCode
-
-maxNumOfBasicServices INTEGER ::= 70
-
-DeleteSubscriberDataRes ::= SEQUENCE {
- regionalSubscriptionResponse [0] RegionalSubscriptionResponse OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-VlrCamelSubscriptionInfo ::= SEQUENCE {
- o-CSI [0] O-CSI OPTIONAL,
- extensionContainer [1] ExtensionContainer OPTIONAL,
- ...,
- ss-CSI [2] SS-CSI OPTIONAL,
- o-BcsmCamelTDP-CriteriaList [4] O-BcsmCamelTDPCriteriaList OPTIONAL,
- tif-CSI [3] NULL OPTIONAL,
- m-CSI [5] M-CSI OPTIONAL,
- mo-sms-CSI [6] SMS-CSI OPTIONAL,
- vt-CSI [7] T-CSI OPTIONAL,
- t-BCSM-CAMEL-TDP-CriteriaList [8] T-BCSM-CAMEL-TDP-CriteriaList OPTIONAL,
- d-CSI [9] D-CSI OPTIONAL,
- mt-sms-CSI [10] SMS-CSI OPTIONAL,
- mt-smsCAMELTDP-CriteriaList [11] MT-smsCAMELTDP-CriteriaList OPTIONAL
- }
-
-MT-smsCAMELTDP-CriteriaList ::= SEQUENCE SIZE (1.. maxNumOfCamelTDPData) OF
- MT-smsCAMELTDP-Criteria
-
-MT-smsCAMELTDP-Criteria ::= SEQUENCE {
- sms-TriggerDetectionPoint SMS-TriggerDetectionPoint,
- tpdu-TypeCriterion [0] TPDU-TypeCriterion OPTIONAL,
- ... }
-
-TPDU-TypeCriterion ::= SEQUENCE SIZE (1..maxNumOfTPDUTypes) OF
- MT-SMS-TPDU-Type
-
-
-maxNumOfTPDUTypes INTEGER ::= 5
-
-MT-SMS-TPDU-Type ::= ENUMERATED {
- sms-DELIVER (0),
- sms-SUBMIT-REPORT (1),
- sms-STATUS-REPORT (2),
- ... }
-
--- exception handling:
--- For TPDU-TypeCriterion sequences containing this parameter with any
--- other value than the ones listed above the receiver shall ignore
--- the whole TPDU-TypeCriterion sequence.
--- In CAMEL phase 4, sms-SUBMIT-REPORT shall not be used and a received TPDU-TypeCriterion
--- sequence containing sms-SUBMIT-REPORT shall be wholly ignored.
-
-D-CSI ::= SEQUENCE {
- dp-AnalysedInfoCriteriaList [0] DP-AnalysedInfoCriteriaList OPTIONAL,
- camelCapabilityHandling [1] CamelCapabilityHandling OPTIONAL,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- notificationToCSE [3] NULL OPTIONAL,
- csi-Active [4] NULL OPTIONAL,
- ...}
--- notificationToCSE and csi-Active shall not be present when D-CSI is sent to VLR/GMSC.
--- They may only be included in ATSI/ATM ack/NSDC message.
--- DP-AnalysedInfoCriteria and camelCapabilityHandling shall be present in
--- the D-CSI sequence.
--- If D-CSI is segmented, then the first segment shall contain dp-AnalysedInfoCriteriaList
--- and camelCapabilityHandling. Subsequent segments shall not contain
--- camelCapabilityHandling, but may contain dp-AnalysedInfoCriteriaList.
-
-DP-AnalysedInfoCriteriaList ::= SEQUENCE SIZE (1..maxNumOfDP-AnalysedInfoCriteria) OF
- DP-AnalysedInfoCriterium
-
-maxNumOfDP-AnalysedInfoCriteria INTEGER ::= 10
-
-DP-AnalysedInfoCriterium ::= SEQUENCE {
- dialledNumber ISDN-AddressString,
- serviceKey ServiceKey,
- gsmSCF-Address ISDN-AddressString,
- defaultCallHandling DefaultCallHandling,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-SS-CSI ::= SEQUENCE {
- ss-CamelData SS-CamelData,
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- notificationToCSE [0] NULL OPTIONAL,
- csi-Active [1] NULL OPTIONAL
--- notificationToCSE and csi-Active shall not be present when SS-CSI is sent to VLR.
--- They may only be included in ATSI/ATM ack/NSDC message.
-}
-
-SS-CamelData ::= SEQUENCE {
- ss-EventList SS-EventList,
- gsmSCF-Address ISDN-AddressString,
- extensionContainer [0] ExtensionContainer OPTIONAL,
- ...}
-
-SS-EventList ::= SEQUENCE SIZE (1..maxNumOfCamelSSEvents) OF SS-Code
- -- Actions for the following SS-Code values are defined in CAMEL Phase 3:
- -- ect SS-Code ::= '00110001'B
- -- multiPTY SS-Code ::= '01010001'B
- -- cd SS-Code ::= '00100100'B
- -- ccbs SS-Code ::= '01000100'B
- -- all other SS codes shall be ignored
- -- When SS-CSI is sent to the VLR, it shall not contain a marking for ccbs.
- -- If the VLR receives SS-CSI containing a marking for ccbs, the VLR shall discard the
- -- ccbs marking in SS-CSI.
-
-maxNumOfCamelSSEvents INTEGER ::= 10
-
-O-CSI ::= SEQUENCE {
- o-BcsmCamelTDPDataList O-BcsmCamelTDPDataList,
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- camelCapabilityHandling [0] CamelCapabilityHandling OPTIONAL,
- notificationToCSE [1] NULL OPTIONAL,
- csiActive [2] NULL OPTIONAL}
--- notificationtoCSE and csiActive shall not be present when O-CSI is sent to VLR/GMSC.
--- They may only be included in ATSI/ATM ack/NSDC message.
--- O-CSI shall not be segmented.
-
-O-BcsmCamelTDPDataList ::= SEQUENCE SIZE (1..maxNumOfCamelTDPData) OF
- O-BcsmCamelTDPData
- -- O-BcsmCamelTDPDataList shall not contain more than one instance of
- -- O-BcsmCamelTDPData containing the same value for o-BcsmTriggerDetectionPoint.
- -- For CAMEL Phase 2, this means that only one instance of O-BcsmCamelTDPData is allowed
- -- with o-BcsmTriggerDetectionPoint being equal to DP2.
-
-maxNumOfCamelTDPData INTEGER ::= 10
-
-O-BcsmCamelTDPData ::= SEQUENCE {
- o-BcsmTriggerDetectionPoint O-BcsmTriggerDetectionPoint,
- serviceKey ServiceKey,
- gsmSCF-Address [0] ISDN-AddressString,
- defaultCallHandling [1] DefaultCallHandling,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ...
- }
-
-ServiceKey ::= INTEGER (0..2147483647)
-
-O-BcsmTriggerDetectionPoint ::= ENUMERATED {
- collectedInfo (2),
- ...,
- routeSelectFailure (4) }
- -- exception handling:
- -- For O-BcsmCamelTDPData sequences containing this parameter with any
- -- other value than the ones listed the receiver shall ignore the whole
- -- O-BcsmCamelTDPDatasequence.
- -- For O-BcsmCamelTDP-Criteria sequences containing this parameter with any
- -- other value than the ones listed the receiver shall ignore the whole
- -- O-BcsmCamelTDP-Criteria sequence.
-
-O-BcsmCamelTDPCriteriaList ::= SEQUENCE SIZE (1..maxNumOfCamelTDPData) OF
- O-BcsmCamelTDP-Criteria
-
-T-BCSM-CAMEL-TDP-CriteriaList ::= SEQUENCE SIZE (1..maxNumOfCamelTDPData) OF
- T-BCSM-CAMEL-TDP-Criteria
-
-O-BcsmCamelTDP-Criteria ::= SEQUENCE {
- o-BcsmTriggerDetectionPoint O-BcsmTriggerDetectionPoint,
- destinationNumberCriteria [0] DestinationNumberCriteria OPTIONAL,
- basicServiceCriteria [1] BasicServiceCriteria OPTIONAL,
- callTypeCriteria [2] CallTypeCriteria OPTIONAL,
- ...,
- o-CauseValueCriteria [3] O-CauseValueCriteria OPTIONAL,
- extensionContainer [4] ExtensionContainer OPTIONAL }
-
-T-BCSM-CAMEL-TDP-Criteria ::= SEQUENCE {
- t-BCSM-TriggerDetectionPoint T-BcsmTriggerDetectionPoint,
- basicServiceCriteria [0] BasicServiceCriteria OPTIONAL,
- t-CauseValueCriteria [1] T-CauseValueCriteria OPTIONAL,
- ... }
-
-DestinationNumberCriteria ::= SEQUENCE {
- matchType [0] MatchType,
- destinationNumberList [1] DestinationNumberList OPTIONAL,
- destinationNumberLengthList [2] DestinationNumberLengthList OPTIONAL,
- -- one or both of destinationNumberList and destinationNumberLengthList
- -- shall be present
- ...}
-
-DestinationNumberList ::= SEQUENCE SIZE (1..maxNumOfCamelDestinationNumbers) OF
- ISDN-AddressString
- -- The receiving entity shall not check the format of a number in
- -- the dialled number list
-
-DestinationNumberLengthList ::= SEQUENCE SIZE (1..maxNumOfCamelDestinationNumberLengths) OF
- INTEGER(1..maxNumOfISDN-AddressDigits)
-
-BasicServiceCriteria ::= SEQUENCE SIZE(1..maxNumOfCamelBasicServiceCriteria) OF
- Ext-BasicServiceCode
-
-maxNumOfISDN-AddressDigits INTEGER ::= 15
-
-maxNumOfCamelDestinationNumbers INTEGER ::= 10
-
-maxNumOfCamelDestinationNumberLengths INTEGER ::= 3
-
-maxNumOfCamelBasicServiceCriteria INTEGER ::= 5
-
-CallTypeCriteria ::= ENUMERATED {
- forwarded (0),
- notForwarded (1)}
-
-MatchType ::= ENUMERATED {
- inhibiting (0),
- enabling (1)}
-
-O-CauseValueCriteria ::= SEQUENCE SIZE(1..maxNumOfCAMEL-O-CauseValueCriteria) OF
- CauseValue
-
-T-CauseValueCriteria ::= SEQUENCE SIZE(1..maxNumOfCAMEL-T-CauseValueCriteria) OF
- CauseValue
-
-maxNumOfCAMEL-O-CauseValueCriteria INTEGER ::= 5
-
-maxNumOfCAMEL-T-CauseValueCriteria INTEGER ::= 5
-
-CauseValue ::= OCTET STRING (SIZE(1))
--- Type extracted from Cause parameter in ITU-T Recommendation Q.763.
--- For the use of cause value refer to ITU-T Recommendation Q.850.
-
-DefaultCallHandling ::= ENUMERATED {
- continueCall (0) ,
- releaseCall (1) ,
- ...}
- -- exception handling:
- -- reception of values in range 2-31 shall be treated as "continueCall"
- -- reception of values greater than 31 shall be treated as "releaseCall"
-
-CamelCapabilityHandling ::= INTEGER(1..16)
- -- value 1 = CAMEL phase 1,
- -- value 2 = CAMEL phase 2,
- -- value 3 = CAMEL Phase 3,
- -- value 4 = CAMEL phase 4:
- -- reception of values greater than 4 shall be treated as CAMEL phase 4.
-
-SupportedCamelPhases ::= BIT STRING {
- phase1 (0),
- phase2 (1),
- phase3 (2),
- phase4 (3)} (SIZE (1..16))
--- A node shall mark in the BIT STRING all CAMEL Phases it supports.
--- Other values than listed above shall be discarded.
-
-OfferedCamel4CSIs ::= BIT STRING {
- o-csi (0),
- d-csi (1),
- vt-csi (2),
- t-csi (3),
- mt-sms-csi (4),
- mg-csi (5),
- psi-enhancements (6)
-} (SIZE (7..16))
--- A node supporting Camel phase 4 shall mark in the BIT STRING all Camel4 CSIs
--- it offers.
--- Other values than listed above shall be discarded.
-
-OfferedCamel4Functionalities ::= BIT STRING {
- initiateCallAttempt (0),
- splitLeg (1),
- moveLeg (2),
- disconnectLeg (3),
- entityReleased (4),
- dfc-WithArgument (5),
- playTone (6),
- dtmf-MidCall (7),
- chargingIndicator (8),
- alertingDP (9),
- locationAtAlerting (10),
- changeOfPositionDP (11),
- or-Interactions (12),
- warningToneEnhancements (13),
- cf-Enhancements (14),
- subscribedEnhancedDialledServices (15),
- servingNetworkEnhancedDialledServices (16),
- criteriaForChangeOfPositionDP (17),
- serviceChangeDP (18),
- collectInformation (19)
-} (SIZE (15..64))
--- A node supporting Camel phase 4 shall mark in the BIT STRING all CAMEL4
--- functionalities it offers.
--- Other values than listed above shall be discarded.
-
-SMS-CSI ::= SEQUENCE {
- sms-CAMEL-TDP-DataList [0] SMS-CAMEL-TDP-DataList OPTIONAL,
- camelCapabilityHandling [1] CamelCapabilityHandling OPTIONAL,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- notificationToCSE [3] NULL OPTIONAL,
- csi-Active [4] NULL OPTIONAL,
- ...}
--- notificationToCSE and csi-Active shall not be present
--- when MO-SMS-CSI or MT-SMS-CSI is sent to VLR or SGSN.
--- They may only be included in ATSI/ATM ack/NSDC message.
--- SMS-CAMEL-TDP-Data and camelCapabilityHandling shall be present in
--- the SMS-CSI sequence.
--- If SMS-CSI is segmented, sms-CAMEL-TDP-DataList and camelCapabilityHandling shall be
--- present in the first segment
-
-SMS-CAMEL-TDP-DataList ::= SEQUENCE SIZE (1..maxNumOfCamelTDPData) OF
- SMS-CAMEL-TDP-Data
--- SMS-CAMEL-TDP-DataList shall not contain more than one instance of
--- SMS-CAMEL-TDP-Data containing the same value for sms-TriggerDetectionPoint.
-
-SMS-CAMEL-TDP-Data ::= SEQUENCE {
- sms-TriggerDetectionPoint [0] SMS-TriggerDetectionPoint,
- serviceKey [1] ServiceKey,
- gsmSCF-Address [2] ISDN-AddressString,
- defaultSMS-Handling [3] DefaultSMS-Handling,
- extensionContainer [4] ExtensionContainer OPTIONAL,
- ...
- }
-
-SMS-TriggerDetectionPoint ::= ENUMERATED {
- sms-CollectedInfo (1),
- ...,
- sms-DeliveryRequest (2)
- }
--- exception handling:
--- For SMS-CAMEL-TDP-Data and MT-smsCAMELTDP-Criteria sequences containing this
--- parameter with any other value than the ones listed the receiver shall ignore
--- the whole sequence.
---
--- If this parameter is received with any other value than sms-CollectedInfo
--- in an SMS-CAMEL-TDP-Data sequence contained in mo-sms-CSI, then the receiver shall
--- ignore the whole SMS-CAMEL-TDP-Data sequence.
---
--- If this parameter is received with any other value than sms-DeliveryRequest
--- in an SMS-CAMEL-TDP-Data sequence contained in mt-sms-CSI then the receiver shall
--- ignore the whole SMS-CAMEL-TDP-Data sequence.
---
--- If this parameter is received with any other value than sms-DeliveryRequest
--- in an MT-smsCAMELTDP-Criteria sequence then the receiver shall
--- ignore the whole MT-smsCAMELTDP-Criteria sequence.
-
-DefaultSMS-Handling ::= ENUMERATED {
- continueTransaction (0) ,
- releaseTransaction (1) ,
- ...}
--- exception handling:
--- reception of values in range 2-31 shall be treated as "continueTransaction"
--- reception of values greater than 31 shall be treated as "releaseTransaction"
-
-M-CSI ::= SEQUENCE {
- mobilityTriggers MobilityTriggers,
- serviceKey ServiceKey,
- gsmSCF-Address [0] ISDN-AddressString,
- extensionContainer [1] ExtensionContainer OPTIONAL,
- notificationToCSE [2] NULL OPTIONAL,
- csi-Active [3] NULL OPTIONAL,
- ...}
--- notificationToCSE and csi-Active shall not be present when M-CSI is sent to VLR.
--- They may only be included in ATSI/ATM ack/NSDC message.
-
-MG-CSI ::= SEQUENCE {
- mobilityTriggers MobilityTriggers,
- serviceKey ServiceKey,
- gsmSCF-Address [0] ISDN-AddressString,
- extensionContainer [1] ExtensionContainer OPTIONAL,
- notificationToCSE [2] NULL OPTIONAL,
- csi-Active [3] NULL OPTIONAL,
- ...}
--- notificationToCSE and csi-Active shall not be present when MG-CSI is sent to SGSN.
--- They may only be included in ATSI/ATM ack/NSDC message.
-
-MobilityTriggers ::= SEQUENCE SIZE (1..maxNumOfMobilityTriggers) OF
- MM-Code
-
-maxNumOfMobilityTriggers INTEGER ::= 10
-
-MM-Code ::= OCTET STRING (SIZE (1))
--- This type is used to indicate a Mobility Management event.
--- Actions for the following MM-Code values are defined in CAMEL Phase 4:
---
--- CS domain MM events:
--- Location-update-in-same-VLR MM-Code ::= '00000000'B
--- Location-update-to-other-VLR MM-Code ::= '00000001'B
--- IMSI-Attach MM-Code ::= '00000010'B
--- MS-initiated-IMSI-Detach MM-Code ::= '00000011'B
--- Network-initiated-IMSI-Detach MM-Code ::= '00000100'B
---
--- PS domain MM events:
--- Routeing-Area-update-in-same-SGSN MM-Code ::= '10000000'B
--- Routeing-Area-update-to-other-SGSN-update-from-new-SGSN
--- MM-Code ::= '10000001'B
--- Routeing-Area-update-to-other-SGSN-disconnect-by-detach
--- MM-Code ::= '10000010'B
--- GPRS-Attach MM-Code ::= '10000011'B
--- MS-initiated-GPRS-Detach MM-Code ::= '10000100'B
--- Network-initiated-GPRS-Detach MM-Code ::= '10000101'B
--- Network-initiated-transfer-to-MS-not-reachable-for-paging
--- MM-Code ::= '10000110'B
---
--- If the MSC receives any other MM-code than the ones listed above for the
--- CS domain, then the MSC shall ignore that MM-code.
--- If the SGSN receives any other MM-code than the ones listed above for the
--- PS domain, then the SGSN shall ignore that MM-code.
-
-T-CSI ::= SEQUENCE {
- t-BcsmCamelTDPDataList T-BcsmCamelTDPDataList,
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- camelCapabilityHandling [0] CamelCapabilityHandling OPTIONAL,
- notificationToCSE [1] NULL OPTIONAL,
- csi-Active [2] NULL OPTIONAL}
--- notificationToCSE and csi-Active shall not be present when VT-CSI/T-CSI is sent
--- to VLR/GMSC.
--- They may only be included in ATSI/ATM ack/NSDC message.
--- T-CSI shall not be segmented.
-
-T-BcsmCamelTDPDataList ::= SEQUENCE SIZE (1..maxNumOfCamelTDPData) OF
- T-BcsmCamelTDPData
- --- T-BcsmCamelTDPDataList shall not contain more than one instance of
- --- T-BcsmCamelTDPData containing the same value for t-BcsmTriggerDetectionPoint.
- --- For CAMEL Phase 2, this means that only one instance of T-BcsmCamelTDPData is allowed
- --- with t-BcsmTriggerDetectionPoint being equal to DP12.
- --- For CAMEL Phase 3, more TDPÂ’s are allowed.
-
-T-BcsmCamelTDPData ::= SEQUENCE {
- t-BcsmTriggerDetectionPoint T-BcsmTriggerDetectionPoint,
- serviceKey ServiceKey,
- gsmSCF-Address [0] ISDN-AddressString,
- defaultCallHandling [1] DefaultCallHandling,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ...}
-
-T-BcsmTriggerDetectionPoint ::= ENUMERATED {
- termAttemptAuthorized (12),
- ... ,
- tBusy (13),
- tNoAnswer (14)}
- -- exception handling:
- -- For T-BcsmCamelTDPData sequences containing this parameter with any other
- -- value than the ones listed above, the receiver shall ignore the whole
- -- T-BcsmCamelTDPData sequence.
-
--- gprs location information retrieval types
-
-SendRoutingInfoForGprsArg ::= SEQUENCE {
- imsi [0] IMSI,
- ggsn-Address [1] GSN-Address OPTIONAL,
- ggsn-Number [2] ISDN-AddressString,
- extensionContainer [3] ExtensionContainer OPTIONAL,
- ...}
-
-SendRoutingInfoForGprsRes ::= SEQUENCE {
- sgsn-Address [0] GSN-Address,
- ggsn-Address [1] GSN-Address OPTIONAL,
- mobileNotReachableReason [2] AbsentSubscriberDiagnosticSM OPTIONAL,
- extensionContainer [3] ExtensionContainer OPTIONAL,
- ...}
-
--- failure report types
-
-FailureReportArg ::= SEQUENCE {
- imsi [0] IMSI,
- ggsn-Number [1] ISDN-AddressString ,
- ggsn-Address [2] GSN-Address OPTIONAL,
- extensionContainer [3] ExtensionContainer OPTIONAL,
- ...}
-
-FailureReportRes ::= SEQUENCE {
- ggsn-Address [0] GSN-Address OPTIONAL,
- extensionContainer [1] ExtensionContainer OPTIONAL,
- ...}
-
--- gprs notification types
-
-NoteMsPresentForGprsArg ::= SEQUENCE {
- imsi [0] IMSI,
- sgsn-Address [1] GSN-Address,
- ggsn-Address [2] GSN-Address OPTIONAL,
- extensionContainer [3] ExtensionContainer OPTIONAL,
- ...}
-
-NoteMsPresentForGprsRes ::= SEQUENCE {
- extensionContainer [0] ExtensionContainer OPTIONAL,
- ...}
-
--- fault recovery types
-
-ResetArg ::= SEQUENCE {
- hlr-Number ISDN-AddressString,
- hlr-List HLR-List OPTIONAL,
- ...}
-
-RestoreDataArg ::= SEQUENCE {
- imsi IMSI,
- lmsi LMSI OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ... ,
- vlr-Capability [6] VLR-Capability OPTIONAL }
-
-RestoreDataRes ::= SEQUENCE {
- hlr-Number ISDN-AddressString,
- msNotReachable NULL OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
--- VBS/VGCS types
-VBSDataList ::= SEQUENCE SIZE (1..maxNumOfVBSGroupIds) OF
- VoiceBroadcastData
-
-VGCSDataList ::= SEQUENCE SIZE (1..maxNumOfVGCSGroupIds) OF
- VoiceGroupCallData
-
-maxNumOfVBSGroupIds INTEGER ::= 50
-
-maxNumOfVGCSGroupIds INTEGER ::= 50
-
-VoiceGroupCallData ::= SEQUENCE {
- groupId GroupId,
- -- groupId shall be filled with six TBCD fillers (1111)if the longGroupId is present
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- additionalSubscriptions AdditionalSubscriptions OPTIONAL,
- additionalInfo [0] AdditionalInfo OPTIONAL,
- longGroupId [1] Long-GroupId OPTIONAL }
-
- -- VoiceGroupCallData containing a longGroupId shall not be sent to VLRs that did not
- -- indicate support of long Group IDs within the Update Location or Restore Data
- -- request message
-
-AdditionalInfo ::= BIT STRING (SIZE (1..136))
--- Refers to Additional Info as specified in 3GPP TS 43.068
-
-AdditionalSubscriptions ::= BIT STRING {
- privilegedUplinkRequest (0),
- emergencyUplinkRequest (1),
- emergencyReset (2)} (SIZE (3..8))
--- Other bits than listed above shall be discarded.
-
-VoiceBroadcastData ::= SEQUENCE {
- groupid GroupId,
- -- groupId shall be filled with six TBCD fillers (1111)if the longGroupId is present
- broadcastInitEntitlement NULL OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- longGroupId [0] Long-GroupId OPTIONAL }
-
--- VoiceBroadcastData containing a longGroupId shall not be sent to VLRs that did not
--- indicate support of long Group IDs within the Update Location or Restore Data
- -- request message
-
-GroupId ::= TBCD-STRING (SIZE (3))
- -- When Group-Id is less than six characters in length, the TBCD filler (1111)
- -- is used to fill unused half octets.
- -- Refers to the Group Identification as specified in 3GPP TS 23.003
- -- and 3GPP TS 43.068/ 43.069
-
-Long-GroupId ::= TBCD-STRING (SIZE (4))
- -- When Long-Group-Id is less than eight characters in length, the TBCD filler (1111)
- -- is used to fill unused half octets.
- -- Refers to the Group Identification as specified in 3GPP TS 23.003
- -- and 3GPP TS 43.068/ 43.069
-
-
--- provide subscriber info types
-
-ProvideSubscriberInfoArg ::= SEQUENCE {
- imsi [0] IMSI,
- lmsi [1] LMSI OPTIONAL,
- requestedInfo [2] RequestedInfo,
- extensionContainer [3] ExtensionContainer OPTIONAL,
- ...,
- callPriority [4] EMLPP-Priority OPTIONAL
- }
-
-ProvideSubscriberInfoRes ::= SEQUENCE {
- subscriberInfo SubscriberInfo,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-SubscriberInfo ::= SEQUENCE {
- locationInformation [0] LocationInformation OPTIONAL,
- subscriberState [1] SubscriberState OPTIONAL,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ... ,
- locationInformationGPRS [3] LocationInformationGPRS OPTIONAL,
- ps-SubscriberState [4] PS-SubscriberState OPTIONAL,
- imei [5] IMEI OPTIONAL,
- ms-Classmark2 [6] MS-Classmark2 OPTIONAL,
- gprs-MS-Class [7] GPRSMSClass OPTIONAL,
- mnpInfoRes [8] MNPInfoRes OPTIONAL }
-
--- If the HLR receives locationInformation, subscriberState or ms-Classmark2 from an SGSN
--- it shall discard them.
--- If the HLR receives locationInformationGPRS, ps-SubscriberState or gprs-MS-Class from
--- a VLR it shall discard them.
--- If the HLR receives parameters which it has not requested, it shall discard them.
-
-MNPInfoRes ::= SEQUENCE {
- routeingNumber [0] RouteingNumber OPTIONAL,
- imsi [1] IMSI OPTIONAL,
- msisdn [2] ISDN-AddressString OPTIONAL,
- numberPortabilityStatus [3] NumberPortabilityStatus OPTIONAL,
- extensionContainer [4] ExtensionContainer OPTIONAL,
- ... }
--- The IMSI parameter contains a generic IMSI, i.e. it is not tied necessarily to the
--- Subscriber. MCC and MNC values in this IMSI shall point to the Subscription Network of
--- the Subscriber. See 3GPP TS 23.066 [108].
-
-RouteingNumber ::= TBCD-STRING (SIZE (1..5))
-
-
-NumberPortabilityStatus ::= ENUMERATED {
- notKnownToBePorted (0),
- ownNumberPortedOut (1),
- foreignNumberPortedToForeignNetwork (2),
- ...,
- ownNumberNotPortedOut (4),
- foreignNumberPortedIn (5)
- }
- -- exception handling:
- -- reception of other values than the ones listed the receiver shall ignore the
- -- whole NumberPortabilityStatus;
- -- ownNumberNotPortedOut or foreignNumberPortedIn may only be included in Any Time
- -- Interrogation message.
-
-MS-Classmark2 ::= OCTET STRING (SIZE (3))
- -- This parameter carries the value part of the MS Classmark 2 IE defined in
- -- 3GPP TS 24.008 [35].
-
-GPRSMSClass ::= SEQUENCE {
- mSNetworkCapability [0] MSNetworkCapability,
- mSRadioAccessCapability [1] MSRadioAccessCapability OPTIONAL
- }
-
-MSNetworkCapability ::= OCTET STRING (SIZE (1..8))
- -- This parameter carries the value part of the MS Network Capability IE defined in
- -- 3GPP TS 24.008 [35].
-
-MSRadioAccessCapability ::= OCTET STRING (SIZE (1..50))
- -- This parameter carries the value part of the MS Radio Access Capability IE defined in
- -- 3GPP TS 24.008 [35].
-
-RequestedInfo ::= SEQUENCE {
- locationInformation [0] NULL OPTIONAL,
- subscriberState [1] NULL OPTIONAL,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ...,
- currentLocation [3] NULL OPTIONAL,
- requestedDomain [4] DomainType OPTIONAL,
- imei [6] NULL OPTIONAL,
- ms-classmark [5] NULL OPTIONAL,
- mnpRequestedInfo [7] NULL OPTIONAL }
-
--- currentLocation shall be absent if locationInformation is absent
-
-DomainType ::= ENUMERATED {
- cs-Domain (0),
- ps-Domain (1),
- ...}
--- exception handling:
--- reception of values > 1 shall be mapped to 'cs-Domain'
-
-LocationInformation ::= SEQUENCE {
- ageOfLocationInformation AgeOfLocationInformation OPTIONAL,
- geographicalInformation [0] GeographicalInformation OPTIONAL,
- vlr-number [1] ISDN-AddressString OPTIONAL,
- locationNumber [2] LocationNumber OPTIONAL,
- cellGlobalIdOrServiceAreaIdOrLAI [3] CellGlobalIdOrServiceAreaIdOrLAI OPTIONAL,
- extensionContainer [4] ExtensionContainer OPTIONAL,
- ... ,
- selectedLSA-Id [5] LSAIdentity OPTIONAL,
- msc-Number [6] ISDN-AddressString OPTIONAL,
- geodeticInformation [7] GeodeticInformation OPTIONAL,
- currentLocationRetrieved [8] NULL OPTIONAL,
- sai-Present [9] NULL OPTIONAL }
--- sai-Present indicates that the cellGlobalIdOrServiceAreaIdOrLAI parameter contains
--- a Service Area Identity.
--- currentLocationRetrieved shall be present
--- if the location information were retrieved after a successfull paging.
-
-LocationInformationGPRS ::= SEQUENCE {
- cellGlobalIdOrServiceAreaIdOrLAI [0] CellGlobalIdOrServiceAreaIdOrLAI OPTIONAL,
- routeingAreaIdentity [1] RAIdentity OPTIONAL,
- geographicalInformation [2] GeographicalInformation OPTIONAL,
- sgsn-Number [3] ISDN-AddressString OPTIONAL,
- selectedLSAIdentity [4] LSAIdentity OPTIONAL,
- extensionContainer [5] ExtensionContainer OPTIONAL,
- ...,
- sai-Present [6] NULL OPTIONAL,
- geodeticInformation [7] GeodeticInformation OPTIONAL,
- currentLocationRetrieved [8] NULL OPTIONAL,
- ageOfLocationInformation [9] AgeOfLocationInformation OPTIONAL }
--- sai-Present indicates that the cellGlobalIdOrServiceAreaIdOrLAI parameter contains
--- a Service Area Identity.
--- currentLocationRetrieved shall be present if the location information
--- was retrieved after successful paging.
-
-RAIdentity ::= OCTET STRING (SIZE (6))
--- Routing Area Identity is coded in accordance with 3GPP TS 29.060 [105].
--- It shall contain the value part defined in 3GPP TS 29.060 only. I.e. the 3GPP TS 29.060
--- type identifier octet shall not be included.
-
-
-GeographicalInformation ::= OCTET STRING (SIZE (8))
--- Refers to geographical Information defined in 3GPP TS 23.032.
--- Only the description of an ellipsoid point with uncertainty circle
--- as specified in 3GPP TS 23.032 is allowed to be used
--- The internal structure according to 3GPP TS 23.032 is as follows:
--- Type of shape (ellipsoid point with uncertainty circle) 1 octet
--- Degrees of Latitude 3 octets
--- Degrees of Longitude 3 octets
--- Uncertainty code 1 octet
-
-GeodeticInformation ::= OCTET STRING (SIZE (10))
--- Refers to Calling Geodetic Location defined in Q.763 (1999).
--- Only the description of an ellipsoid point with uncertainty circle
--- as specified in Q.763 (1999) is allowed to be used
--- The internal structure according to Q.763 (1999) is as follows:
--- Screening and presentation indicators 1 octet
--- Type of shape (ellipsoid point with uncertainty circle) 1 octet
--- Degrees of Latitude 3 octets
--- Degrees of Longitude 3 octets
--- Uncertainty code 1 octet
--- Confidence 1 octet
-
-LocationNumber ::= OCTET STRING (SIZE (2..10))
- -- the internal structure is defined in ITU-T Rec Q.763
-
-SubscriberState ::= CHOICE {
- assumedIdle [0] NULL,
- camelBusy [1] NULL,
- netDetNotReachable NotReachableReason,
- notProvidedFromVLR [2] NULL}
-
-PS-SubscriberState ::= CHOICE {
- notProvidedFromSGSN [0] NULL,
- ps-Detached [1] NULL,
- ps-AttachedNotReachableForPaging [2] NULL,
- ps-AttachedReachableForPaging [3] NULL,
- ps-PDP-ActiveNotReachableForPaging [4] PDP-ContextInfoList,
- ps-PDP-ActiveReachableForPaging [5] PDP-ContextInfoList,
- netDetNotReachable NotReachableReason }
-
-PDP-ContextInfoList ::= SEQUENCE SIZE (1..maxNumOfPDP-Contexts) OF
- PDP-ContextInfo
-
-PDP-ContextInfo ::= SEQUENCE {
- pdp-ContextIdentifier [0] ContextId,
- pdp-ContextActive [1] NULL OPTIONAL,
- pdp-Type [2] PDP-Type,
- pdp-Address [3] PDP-Address OPTIONAL,
- apn-Subscribed [4] APN OPTIONAL,
- apn-InUse [5] APN OPTIONAL,
- nsapi [6] NSAPI OPTIONAL,
- transactionId [7] TransactionId OPTIONAL,
- teid-ForGnAndGp [8] TEID OPTIONAL,
- teid-ForIu [9] TEID OPTIONAL,
- ggsn-Address [10] GSN-Address OPTIONAL,
- qos-Subscribed [11] Ext-QoS-Subscribed OPTIONAL,
- qos-Requested [12] Ext-QoS-Subscribed OPTIONAL,
- qos-Negotiated [13] Ext-QoS-Subscribed OPTIONAL,
- chargingId [14] GPRSChargingID OPTIONAL,
- chargingCharacteristics [15] ChargingCharacteristics OPTIONAL,
- rnc-Address [16] GSN-Address OPTIONAL,
- extensionContainer [17] ExtensionContainer OPTIONAL,
- ...,
- qos2-Subscribed [18] Ext2-QoS-Subscribed OPTIONAL,
- -- qos2-Subscribed may be present only if qos-Subscribed is present.
- qos2-Requested [19] Ext2-QoS-Subscribed OPTIONAL,
- -- qos2-Requested may be present only if qos-Requested is present.
- qos2-Negotiated [20] Ext2-QoS-Subscribed OPTIONAL,
- -- qos2-Negotiated may be present only if qos-Negotiated is present.
- qos3-Subscribed [21] Ext3-QoS-Subscribed OPTIONAL,
- -- qos3-Subscribed may be present only if qos2-Subscribed is present.
- qos3-Requested [22] Ext3-QoS-Subscribed OPTIONAL,
- -- qos3-Requested may be present only if qos2-Requested is present.
- qos3-Negotiated [23] Ext3-QoS-Subscribed OPTIONAL
- -- qos3-Negotiated may be present only if qos2-Negotiated is present.
-}
-
-NSAPI ::= INTEGER (0..15)
--- This type is used to indicate the Network layer Service Access Point
-
-TransactionId ::= OCTET STRING (SIZE (1..2))
--- This type carries the value part of the transaction identifier which is used in the
--- session management messages on the access interface. The encoding is defined in
--- 3GPP TS 24.008
-
-TEID ::= OCTET STRING (SIZE (4))
--- This type carries the value part of the Tunnel Endpoint Identifier which is used to
--- distinguish between different tunnels between the same pair of entities which communicate
--- using the GPRS Tunnelling Protocol The encoding is defined in 3GPP TS 29.060.
-
-GPRSChargingID ::= OCTET STRING (SIZE (4))
--- The Charging ID is a unique four octet value generated by the GGSN when
--- a PDP Context is activated. A Charging ID is generated for each activated context.
--- The encoding is defined in 3GPP TS 29.060.
-
-NotReachableReason ::= ENUMERATED {
- msPurged (0),
- imsiDetached (1),
- restrictedArea (2),
- notRegistered (3)}
-
--- any time interrogation info types
-
-AnyTimeInterrogationArg ::= SEQUENCE {
- subscriberIdentity [0] SubscriberIdentity,
- requestedInfo [1] RequestedInfo,
- gsmSCF-Address [3] ISDN-AddressString,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ...}
-
-AnyTimeInterrogationRes ::= SEQUENCE {
- subscriberInfo SubscriberInfo,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
--- any time information handling types
-
-AnyTimeSubscriptionInterrogationArg ::= SEQUENCE {
- subscriberIdentity [0] SubscriberIdentity,
- requestedSubscriptionInfo [1] RequestedSubscriptionInfo,
- gsmSCF-Address [2] ISDN-AddressString,
- extensionContainer [3] ExtensionContainer OPTIONAL,
- longFTN-Supported [4] NULL OPTIONAL,
- ...}
-
-AnyTimeSubscriptionInterrogationRes ::= SEQUENCE {
- callForwardingData [1] CallForwardingData OPTIONAL,
- callBarringData [2] CallBarringData OPTIONAL,
- odb-Info [3] ODB-Info OPTIONAL,
- camel-SubscriptionInfo [4] CAMEL-SubscriptionInfo OPTIONAL,
- supportedVLR-CAMEL-Phases [5] SupportedCamelPhases OPTIONAL,
- supportedSGSN-CAMEL-Phases [6] SupportedCamelPhases OPTIONAL,
- extensionContainer [7] ExtensionContainer OPTIONAL,
- ... ,
- offeredCamel4CSIsInVLR [8] OfferedCamel4CSIs OPTIONAL,
- offeredCamel4CSIsInSGSN [9] OfferedCamel4CSIs OPTIONAL,
- msisdn-BS-List [10] MSISDN-BS-List OPTIONAL }
-
-RequestedSubscriptionInfo ::= SEQUENCE {
- requestedSS-Info [1] SS-ForBS-Code OPTIONAL,
- odb [2] NULL OPTIONAL,
- requestedCAMEL-SubscriptionInfo [3] RequestedCAMEL-SubscriptionInfo OPTIONAL,
- supportedVLR-CAMEL-Phases [4] NULL OPTIONAL,
- supportedSGSN-CAMEL-Phases [5] NULL OPTIONAL,
- extensionContainer [6] ExtensionContainer OPTIONAL,
- ...,
- additionalRequestedCAMEL-SubscriptionInfo
- [7] AdditionalRequestedCAMEL-SubscriptionInfo
- OPTIONAL,
- msisdn-BS-List [8] NULL OPTIONAL }
-
-MSISDN-BS-List ::= SEQUENCE SIZE (1..maxNumOfMSISDN) OF
- MSISDN-BS
-
-maxNumOfMSISDN INTEGER ::= 50
-
-
-MSISDN-BS ::= SEQUENCE {
- msisdn ISDN-AddressString,
- basicServiceList [0] BasicServiceList OPTIONAL,
- extensionContainer [1] ExtensionContainer OPTIONAL,
- ...}
-
-RequestedCAMEL-SubscriptionInfo ::= ENUMERATED {
- o-CSI (0),
- t-CSI (1),
- vt-CSI (2),
- tif-CSI (3),
- gprs-CSI (4),
- mo-sms-CSI (5),
- ss-CSI (6),
- m-CSI (7),
- d-csi (8)}
-
-AdditionalRequestedCAMEL-SubscriptionInfo ::= ENUMERATED {
- mt-sms-CSI (0),
- mg-csi (1),
- o-IM-CSI (2),
- d-IM-CSI (3),
- vt-IM-CSI (4),
- ...}
--- exception handling: unknown values shall be discarded by the receiver.
-
-CallForwardingData ::= SEQUENCE {
- forwardingFeatureList Ext-ForwFeatureList,
- notificationToCSE NULL OPTIONAL,
- extensionContainer [0] ExtensionContainer OPTIONAL,
- ...}
-
-CallBarringData ::= SEQUENCE {
- callBarringFeatureList Ext-CallBarFeatureList,
- password Password OPTIONAL,
- wrongPasswordAttemptsCounter WrongPasswordAttemptsCounter OPTIONAL,
- notificationToCSE NULL OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-WrongPasswordAttemptsCounter ::= INTEGER (0..4)
-
-ODB-Info ::= SEQUENCE {
- odb-Data ODB-Data,
- notificationToCSE NULL OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-CAMEL-SubscriptionInfo ::= SEQUENCE {
- o-CSI [0] O-CSI OPTIONAL,
- o-BcsmCamelTDP-CriteriaList [1] O-BcsmCamelTDPCriteriaList OPTIONAL,
- d-CSI [2] D-CSI OPTIONAL,
- t-CSI [3] T-CSI OPTIONAL,
- t-BCSM-CAMEL-TDP-CriteriaList [4] T-BCSM-CAMEL-TDP-CriteriaList OPTIONAL,
- vt-CSI [5] T-CSI OPTIONAL,
- vt-BCSM-CAMEL-TDP-CriteriaList [6] T-BCSM-CAMEL-TDP-CriteriaList OPTIONAL,
- tif-CSI [7] NULL OPTIONAL,
- tif-CSI-NotificationToCSE [8] NULL OPTIONAL,
- gprs-CSI [9] GPRS-CSI OPTIONAL,
- mo-sms-CSI [10] SMS-CSI OPTIONAL,
- ss-CSI [11] SS-CSI OPTIONAL,
- m-CSI [12] M-CSI OPTIONAL,
- extensionContainer [13] ExtensionContainer OPTIONAL,
- ...,
- specificCSIDeletedList [14] SpecificCSI-Withdraw OPTIONAL,
- mt-sms-CSI [15] SMS-CSI OPTIONAL,
- mt-smsCAMELTDP-CriteriaList [16] MT-smsCAMELTDP-CriteriaList OPTIONAL,
- mg-csi [17] MG-CSI OPTIONAL,
- o-IM-CSI [18] O-CSI OPTIONAL,
- o-IM-BcsmCamelTDP-CriteriaList [19] O-BcsmCamelTDPCriteriaList OPTIONAL,
- d-IM-CSI [20] D-CSI OPTIONAL,
- vt-IM-CSI [21] T-CSI OPTIONAL,
- vt-IM-BCSM-CAMEL-TDP-CriteriaList [22] T-BCSM-CAMEL-TDP-CriteriaList OPTIONAL
- }
-
-AnyTimeModificationArg ::= SEQUENCE {
- subscriberIdentity [0] SubscriberIdentity,
- gsmSCF-Address [1] ISDN-AddressString,
- modificationRequestFor-CF-Info [2] ModificationRequestFor-CF-Info OPTIONAL,
- modificationRequestFor-CB-Info [3] ModificationRequestFor-CB-Info OPTIONAL,
- modificationRequestFor-CSI [4] ModificationRequestFor-CSI OPTIONAL,
- extensionContainer [5] ExtensionContainer OPTIONAL,
- longFTN-Supported [6] NULL OPTIONAL,
- ...,
- modificationRequestFor-ODB-data [7] ModificationRequestFor-ODB-data OPTIONAL,
- modificationRequestFor-IP-SM-GW-Data [8] ModificationRequestFor-IP-SM-GW-Data OPTIONAL }
-
-AnyTimeModificationRes ::= SEQUENCE {
- ss-InfoFor-CSE [0] Ext-SS-InfoFor-CSE OPTIONAL,
- camel-SubscriptionInfo [1] CAMEL-SubscriptionInfo OPTIONAL,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ...,
- odb-Info [3] ODB-Info OPTIONAL }
-
-ModificationRequestFor-CF-Info ::= SEQUENCE {
- ss-Code [0] SS-Code,
- basicService [1] Ext-BasicServiceCode OPTIONAL,
- ss-Status [2] Ext-SS-Status OPTIONAL,
- forwardedToNumber [3] AddressString OPTIONAL,
- forwardedToSubaddress [4] ISDN-SubaddressString OPTIONAL,
- noReplyConditionTime [5] Ext-NoRepCondTime OPTIONAL,
- modifyNotificationToCSE [6] ModificationInstruction OPTIONAL,
- extensionContainer [7] ExtensionContainer OPTIONAL,
- ...}
-
-ModificationRequestFor-CB-Info ::= SEQUENCE {
- ss-Code [0] SS-Code,
- basicService [1] Ext-BasicServiceCode OPTIONAL,
- ss-Status [2] Ext-SS-Status OPTIONAL,
- password [3] Password OPTIONAL,
- wrongPasswordAttemptsCounter [4] WrongPasswordAttemptsCounter OPTIONAL,
- modifyNotificationToCSE [5] ModificationInstruction OPTIONAL,
- extensionContainer [6] ExtensionContainer OPTIONAL,
- ...}
-
-ModificationRequestFor-ODB-data ::= SEQUENCE {
- odb-data [0] ODB-Data OPTIONAL,
- modifyNotificationToCSE [1] ModificationInstruction OPTIONAL,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ...}
-
-ModificationRequestFor-CSI ::= SEQUENCE {
- requestedCamel-SubscriptionInfo [0] RequestedCAMEL-SubscriptionInfo,
- modifyNotificationToCSE [1] ModificationInstruction OPTIONAL,
- modifyCSI-State [2] ModificationInstruction OPTIONAL,
- extensionContainer [3] ExtensionContainer OPTIONAL,
- ...,
- additionalRequestedCAMEL-SubscriptionInfo
- [4] AdditionalRequestedCAMEL-SubscriptionInfo
- OPTIONAL }
--- requestedCamel-SubscriptionInfo shall be discarded if
--- additionalRequestedCAMEL-SubscriptionInfo is received
-
-ModificationRequestFor-IP-SM-GW-Data ::= SEQUENCE {
- modifyRegistrationStatus [0] ModificationInstruction OPTIONAL,
- extensionContainer [1] ExtensionContainer OPTIONAL,
- ...}
-
-ModificationInstruction ::= ENUMERATED {
- deactivate (0),
- activate (1)}
-
--- subscriber data modification notification types
-
-NoteSubscriberDataModifiedArg ::= SEQUENCE {
- imsi IMSI,
- msisdn ISDN-AddressString,
- forwardingInfoFor-CSE [0] Ext-ForwardingInfoFor-CSE OPTIONAL,
- callBarringInfoFor-CSE [1] Ext-CallBarringInfoFor-CSE OPTIONAL,
- odb-Info [2] ODB-Info OPTIONAL,
- camel-SubscriptionInfo [3] CAMEL-SubscriptionInfo OPTIONAL,
- allInformationSent [4] NULL OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-NoteSubscriberDataModifiedRes ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
--- mobility management event notificatioon info types
-
-NoteMM-EventArg::= SEQUENCE {
- serviceKey ServiceKey,
- eventMet [0] MM-Code,
- imsi [1] IMSI,
- msisdn [2] ISDN-AddressString,
- locationInformation [3] LocationInformation OPTIONAL,
- supportedCAMELPhases [5] SupportedCamelPhases OPTIONAL,
- extensionContainer [6] ExtensionContainer OPTIONAL,
- ...,
- locationInformationGPRS [7] LocationInformationGPRS OPTIONAL,
- offeredCamel4Functionalities [8] OfferedCamel4Functionalities OPTIONAL
-}
-
-NoteMM-EventRes ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-Ext-SS-InfoFor-CSE ::= CHOICE {
- forwardingInfoFor-CSE [0] Ext-ForwardingInfoFor-CSE,
- callBarringInfoFor-CSE [1] Ext-CallBarringInfoFor-CSE
- }
-
-Ext-ForwardingInfoFor-CSE ::= SEQUENCE {
- ss-Code [0] SS-Code,
- forwardingFeatureList [1] Ext-ForwFeatureList,
- notificationToCSE [2] NULL OPTIONAL,
- extensionContainer [3] ExtensionContainer OPTIONAL,
- ...}
-
-Ext-CallBarringInfoFor-CSE ::= SEQUENCE {
- ss-Code [0] SS-Code,
- callBarringFeatureList [1] Ext-CallBarFeatureList,
- password [2] Password OPTIONAL,
- wrongPasswordAttemptsCounter [3] WrongPasswordAttemptsCounter OPTIONAL,
- notificationToCSE [4] NULL OPTIONAL,
- extensionContainer [5] ExtensionContainer OPTIONAL,
- ...}
-
-END
-
diff --git a/rrlp-ephemeris/asn1/MAP-OM-DataTypes.asn b/rrlp-ephemeris/asn1/MAP-OM-DataTypes.asn
deleted file mode 100644
index 024dd6f..0000000
--- a/rrlp-ephemeris/asn1/MAP-OM-DataTypes.asn
+++ /dev/null
@@ -1,216 +0,0 @@
--- $Id: MAP-OM-DataTypes.asn 28149 2009-04-25 17:45:34Z etxrab $
--- 17.7.2 Operation and maintenance data types
--- 3GPP TS 29.002 V8.9.0 (2009-04)
-
-MAP-OM-DataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-OM-DataTypes (12) version11 (11)}
-
-DEFINITIONS
-
-IMPLICIT TAGS
-
-::=
-
-BEGIN
-
-EXPORTS
- ActivateTraceModeArg,
- ActivateTraceModeRes,
- DeactivateTraceModeArg,
- DeactivateTraceModeRes,
- TracePropagationList
-;
-
-IMPORTS
- AddressString,
- IMSI
-FROM MAP-CommonDataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-CommonDataTypes (18) version11 (11)}
-
- ExtensionContainer
-FROM MAP-ExtensionDataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
-
-;
-
-ActivateTraceModeArg ::= SEQUENCE {
- imsi [0] IMSI OPTIONAL,
- traceReference [1] TraceReference,
- traceType [2] TraceType,
- omc-Id [3] AddressString OPTIONAL,
- extensionContainer [4] ExtensionContainer OPTIONAL,
- ...,
- traceReference2 [5] TraceReference2 OPTIONAL,
- traceDepthList [6] TraceDepthList OPTIONAL,
- traceNE-TypeList [7] TraceNE-TypeList OPTIONAL,
- traceInterfaceList [8] TraceInterfaceList OPTIONAL,
- traceEventList [9] TraceEventList OPTIONAL
- }
-
-TraceReference ::= OCTET STRING (SIZE (1..2))
-
-TraceReference2 ::= OCTET STRING (SIZE (3))
-
-TraceRecordingSessionReference ::= OCTET STRING (SIZE (2))
-
-TraceType ::= INTEGER
- (0..255)
- -- Trace types are fully defined in 3GPP TS 52.008. [61]
-
-TraceDepthList ::= SEQUENCE {
- msc-s-TraceDepth [0] TraceDepth OPTIONAL,
- mgw-TraceDepth [1] TraceDepth OPTIONAL,
- sgsn-TraceDepth [2] TraceDepth OPTIONAL,
- ggsn-TraceDepth [3] TraceDepth OPTIONAL,
- rnc-TraceDepth [4] TraceDepth OPTIONAL,
- bmsc-TraceDepth [5] TraceDepth OPTIONAL,
- ...}
-
-TraceDepth ::= ENUMERATED {
- minimum (0),
- medium (1),
- maximum (2),
- ...}
--- The value medium is applicable only for RNC. For other network elements, if value medium
--- is received, value minimum shall be applied.
-
-TraceNE-TypeList ::= BIT STRING {
- msc-s (0),
- mgw (1),
- sgsn (2),
- ggsn (3),
- rnc (4),
- bm-sc (5)} (SIZE (6..16))
--- Other bits than listed above shall be discarded.
-
-TraceInterfaceList ::= SEQUENCE {
- msc-s-List [0] MSC-S-InterfaceList OPTIONAL,
- mgw-List [1] MGW-InterfaceList OPTIONAL,
- sgsn-List [2] SGSN-InterfaceList OPTIONAL,
- ggsn-List [3] GGSN-InterfaceList OPTIONAL,
- rnc-List [4] RNC-InterfaceList OPTIONAL,
- bmsc-List [5] BMSC-InterfaceList OPTIONAL,
- ...}
-
-MSC-S-InterfaceList ::= BIT STRING {
- a (0),
- iu (1),
- mc (2),
- map-g (3),
- map-b (4),
- map-e (5),
- map-f (6),
- cap (7),
- map-d (8),
- map-c (9)} (SIZE (10..16))
--- Other bits than listed above shall be discarded.
-
-MGW-InterfaceList ::= BIT STRING {
- mc (0),
- nb-up (1),
- iu-up (2)} (SIZE (3..8))
--- Other bits than listed above shall be discarded.
-
-SGSN-InterfaceList ::= BIT STRING {
- gb (0),
- iu (1),
- gn (2),
- map-gr (3),
- map-gd (4),
- map-gf (5),
- gs (6),
- ge (7)} (SIZE (8..16))
--- Other bits than listed above shall be discarded.
-
-GGSN-InterfaceList ::= BIT STRING {
- gn (0),
- gi (1),
- gmb (2)} (SIZE (3..8))
--- Other bits than listed above shall be discarded.
-
-RNC-InterfaceList ::= BIT STRING {
- iu (0),
- iur (1),
- iub (2),
- uu (3)} (SIZE (4..8))
--- Other bits than listed above shall be discarded.
-
-BMSC-InterfaceList ::= BIT STRING {
- gmb (0)} (SIZE (1..8))
--- Other bits than listed above shall be discarded.
-
-TraceEventList ::= SEQUENCE {
- msc-s-List [0] MSC-S-EventList OPTIONAL,
- mgw-List [1] MGW-EventList OPTIONAL,
- sgsn-List [2] SGSN-EventList OPTIONAL,
- ggsn-List [3] GGSN-EventList OPTIONAL,
- bmsc-List [4] BMSC-EventList OPTIONAL,
- ...}
-
-MSC-S-EventList ::= BIT STRING {
- mo-mtCall (0),
- mo-mt-sms (1),
- lu-imsiAttach-imsiDetach (2),
- handovers (3),
- ss (4)} (SIZE (5..16))
--- Other bits than listed above shall be discarded.
-
-MGW-EventList ::= BIT STRING {
- context (0)} (SIZE (1..8))
--- Other bits than listed above shall be discarded.
-
-SGSN-EventList ::= BIT STRING {
- pdpContext (0),
- mo-mt-sms (1),
- rau-gprsAttach-gprsDetach (2),
- mbmsContext (3)} (SIZE (4..16))
--- Other bits than listed above shall be discarded.
-
-GGSN-EventList ::= BIT STRING {
- pdpContext (0),
- mbmsContext (1)} (SIZE (2..8))
--- Other bits than listed above shall be discarded.
-
-BMSC-EventList ::= BIT STRING {
- mbmsMulticastServiceActivation (0)} (SIZE (1..8))
--- Other bits than listed above shall be discarded.
-
-
-TracePropagationList ::= SEQUENCE {
- traceReference [0] TraceReference OPTIONAL,
- traceType [1] TraceType OPTIONAL,
- traceReference2 [2] TraceReference2 OPTIONAL,
- traceRecordingSessionReference [3] TraceRecordingSessionReference OPTIONAL,
- rnc-TraceDepth [4] TraceDepth OPTIONAL,
- rnc-InterfaceList [5] RNC-InterfaceList OPTIONAL,
- msc-s-TraceDepth [6] TraceDepth OPTIONAL,
- msc-s-InterfaceList [7] MSC-S-InterfaceList OPTIONAL,
- msc-s-EventList [8] MSC-S-EventList OPTIONAL,
- mgw-TraceDepth [9] TraceDepth OPTIONAL,
- mgw-InterfaceList [10] MGW-InterfaceList OPTIONAL,
- mgw-EventList [11] MGW-EventList OPTIONAL,
- ...}
-
-ActivateTraceModeRes ::= SEQUENCE {
- extensionContainer [0] ExtensionContainer OPTIONAL,
- ...,
- traceSupportIndicator [1] NULL OPTIONAL
- }
-
-DeactivateTraceModeArg ::= SEQUENCE {
- imsi [0] IMSI OPTIONAL,
- traceReference [1] TraceReference,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ...,
- traceReference2 [3] TraceReference2 OPTIONAL
- }
-
-DeactivateTraceModeRes ::= SEQUENCE {
- extensionContainer [0] ExtensionContainer OPTIONAL,
- ...}
-
-END
-
diff --git a/rrlp-ephemeris/asn1/MAP-SM-DataTypes.asn b/rrlp-ephemeris/asn1/MAP-SM-DataTypes.asn
deleted file mode 100644
index 0ef941f..0000000
--- a/rrlp-ephemeris/asn1/MAP-SM-DataTypes.asn
+++ /dev/null
@@ -1,270 +0,0 @@
--- $Id: MAP-SM-DataTypes.asn 28149 2009-04-25 17:45:34Z etxrab $
--- 3GPP TS 29.002 V8.9.0 (2009-04)
--- 17.7.6 Short message data types
-
-MAP-SM-DataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-SM-DataTypes (16) version11 (11)}
-
-DEFINITIONS
-
-IMPLICIT TAGS
-
-::=
-
-BEGIN
-
-EXPORTS
- RoutingInfoForSM-Arg,
- RoutingInfoForSM-Res,
- MO-ForwardSM-Arg,
- MO-ForwardSM-Res,
- MT-ForwardSM-Arg,
- MT-ForwardSM-Res,
- ReportSM-DeliveryStatusArg,
- ReportSM-DeliveryStatusRes,
- AlertServiceCentreArg,
- InformServiceCentreArg,
- ReadyForSM-Arg,
- ReadyForSM-Res,
- SM-DeliveryOutcome,
- AlertReason,
- Additional-Number,
- MT-ForwardSM-VGCS-Arg,
- MT-ForwardSM-VGCS-Res
-;
-
-IMPORTS
- AddressString,
- ISDN-AddressString,
- SignalInfo,
- IMSI,
- LMSI,
- ASCI-CallReference
-
-FROM MAP-CommonDataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-CommonDataTypes (18) version11 (11)}
-
- AbsentSubscriberDiagnosticSM
-FROM MAP-ER-DataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-ER-DataTypes (17) version11 (11)}
-
- ExtensionContainer
-FROM MAP-ExtensionDataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
-;
-
-
-RoutingInfoForSM-Arg ::= SEQUENCE {
- msisdn [0] ISDN-AddressString,
- sm-RP-PRI [1] BOOLEAN,
- serviceCentreAddress [2] AddressString,
- extensionContainer [6] ExtensionContainer OPTIONAL,
- ... ,
- gprsSupportIndicator [7] NULL OPTIONAL,
- -- gprsSupportIndicator is set only if the SMS-GMSC supports
- -- receiving of two numbers from the HLR
- sm-RP-MTI [8] SM-RP-MTI OPTIONAL,
- sm-RP-SMEA [9] SM-RP-SMEA OPTIONAL,
- sm-deliveryNotIntended [10] SM-DeliveryNotIntended OPTIONAL }
-
-SM-DeliveryNotIntended ::= ENUMERATED {
- onlyIMSI-requested (0),
- onlyMCC-MNC-requested (1),
- ...}
-
-SM-RP-MTI ::= INTEGER (0..10)
- -- 0 SMS Deliver
- -- 1 SMS Status Report
- -- other values are reserved for future use and shall be discarded if
- -- received
-
-SM-RP-SMEA ::= OCTET STRING (SIZE (1..12))
- -- this parameter contains an address field which is encoded
- -- as defined in 3GPP TS 23.040. An address field contains 3 elements :
- -- address-length
- -- type-of-address
- -- address-value
-
-RoutingInfoForSM-Res ::= SEQUENCE {
- imsi IMSI,
- locationInfoWithLMSI [0] LocationInfoWithLMSI,
- extensionContainer [4] ExtensionContainer OPTIONAL,
- ...}
-
-LocationInfoWithLMSI ::= SEQUENCE {
- networkNode-Number [1] ISDN-AddressString,
- lmsi LMSI OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- gprsNodeIndicator [5] NULL OPTIONAL,
- -- gprsNodeIndicator is set only if the SGSN number is sent as the
- -- Network Node Number
- additional-Number [6] Additional-Number OPTIONAL
- -- NetworkNode-number can be either msc-number or sgsn-number or IP-SM-GW
- -- number or SMS Router number
- }
-
-Additional-Number ::= CHOICE {
- msc-Number [0] ISDN-AddressString,
- sgsn-Number [1] ISDN-AddressString}
- -- additional-number can be either msc-number or sgsn-number
- -- if received networkNode-number is msc-number then the
- -- additional number is sgsn-number
- -- if received networkNode-number is sgsn-number then the
- -- additional number is msc-number
-
-MO-ForwardSM-Arg ::= SEQUENCE {
- sm-RP-DA SM-RP-DA,
- sm-RP-OA SM-RP-OA,
- sm-RP-UI SignalInfo,
- extensionContainer ExtensionContainer OPTIONAL,
- ... ,
- imsi IMSI OPTIONAL }
-
-MO-ForwardSM-Res ::= SEQUENCE {
- sm-RP-UI SignalInfo OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-MT-ForwardSM-Arg ::= SEQUENCE {
- sm-RP-DA SM-RP-DA,
- sm-RP-OA SM-RP-OA,
- sm-RP-UI SignalInfo,
- moreMessagesToSend NULL OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-MT-ForwardSM-Res ::= SEQUENCE {
- sm-RP-UI SignalInfo OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-SM-RP-DA ::= CHOICE {
- imsi [0] IMSI,
- lmsi [1] LMSI,
- serviceCentreAddressDA [4] AddressString,
- noSM-RP-DA [5] NULL}
-
-SM-RP-OA ::= CHOICE {
- msisdn [2] ISDN-AddressString,
- serviceCentreAddressOA [4] AddressString,
- noSM-RP-OA [5] NULL}
-
-ReportSM-DeliveryStatusArg ::= SEQUENCE {
- msisdn ISDN-AddressString,
- serviceCentreAddress AddressString,
- sm-DeliveryOutcome SM-DeliveryOutcome,
- absentSubscriberDiagnosticSM [0] AbsentSubscriberDiagnosticSM
- OPTIONAL,
- extensionContainer [1] ExtensionContainer OPTIONAL,
- ...,
- gprsSupportIndicator [2] NULL OPTIONAL,
- -- gprsSupportIndicator is set only if the SMS-GMSC supports
- -- handling of two delivery outcomes
- deliveryOutcomeIndicator [3] NULL OPTIONAL,
- -- DeliveryOutcomeIndicator is set when the SM-DeliveryOutcome
- -- is for GPRS
- additionalSM-DeliveryOutcome [4] SM-DeliveryOutcome OPTIONAL,
- -- If received, additionalSM-DeliveryOutcome is for GPRS
- -- If DeliveryOutcomeIndicator is set, then AdditionalSM-DeliveryOutcome shall be absent
- additionalAbsentSubscriberDiagnosticSM [5] AbsentSubscriberDiagnosticSM OPTIONAL,
- -- If received additionalAbsentSubscriberDiagnosticSM is for GPRS
- -- If DeliveryOutcomeIndicator is set, then AdditionalAbsentSubscriberDiagnosticSM
- -- shall be absent
- ip-sm-gw-Indicator [6] NULL OPTIONAL,
- -- the ip-sm-gw indicator indicates by its presence that sm-deliveryOutcome
- -- is for delivery via IMS
- -- If present, deliveryOutcomeIndicator shall be absent.
- ip-sm-gw-sm-deliveryOutcome [7] SM-DeliveryOutcome OPTIONAL,
- -- If received ip-sm-gw-sm-deliveryOutcome is for delivery via IMS
- -- If ip-sm-gw-Indicator is set, then ip-sm-gw-sm-deliveryOutcome shall be absent
- ip-sm-gw-absentSubscriberDiagnosticSM [8] AbsentSubscriberDiagnosticSM OPTIONAL
- -- If received ip-sm-gw-sm-absentSubscriberDiagnosticSM is for delivery via IMS
- -- If ip-sm-gw-Indicator is set, then ip-sm-gw-sm-absentSubscriberDiagnosticSM
- -- shall be absent
-}
-
-SM-DeliveryOutcome ::= ENUMERATED {
- memoryCapacityExceeded (0),
- absentSubscriber (1),
- successfulTransfer (2)}
-
-ReportSM-DeliveryStatusRes ::= SEQUENCE {
- storedMSISDN ISDN-AddressString OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-AlertServiceCentreArg ::= SEQUENCE {
- msisdn ISDN-AddressString,
- serviceCentreAddress AddressString,
- ...}
-
-InformServiceCentreArg ::= SEQUENCE {
- storedMSISDN ISDN-AddressString OPTIONAL,
- mw-Status MW-Status OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ... ,
- absentSubscriberDiagnosticSM AbsentSubscriberDiagnosticSM OPTIONAL,
- additionalAbsentSubscriberDiagnosticSM [0] AbsentSubscriberDiagnosticSM OPTIONAL }
- -- additionalAbsentSubscriberDiagnosticSM may be present only if
- -- absentSubscriberDiagnosticSM is present.
- -- if included, additionalAbsentSubscriberDiagnosticSM is for GPRS and
- -- absentSubscriberDiagnosticSM is for non-GPRS
-
-MW-Status ::= BIT STRING {
- sc-AddressNotIncluded (0),
- mnrf-Set (1),
- mcef-Set (2) ,
- mnrg-Set (3)} (SIZE (6..16))
- -- exception handling:
- -- bits 4 to 15 shall be ignored if received and not understood
-
-ReadyForSM-Arg ::= SEQUENCE {
- imsi [0] IMSI,
- alertReason AlertReason,
- alertReasonIndicator NULL OPTIONAL,
- -- alertReasonIndicator is set only when the alertReason
- -- sent to HLR is for GPRS
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- additionalAlertReasonIndicator [1] NULL OPTIONAL
- -- additionalAlertReasonIndicator is set only when the alertReason
- -- sent to HLR is for IP-SM-GW
- }
-
-ReadyForSM-Res ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-AlertReason ::= ENUMERATED {
- ms-Present (0),
- memoryAvailable (1)}
-
-MT-ForwardSM-VGCS-Arg ::= SEQUENCE {
- asciCallReference ASCI-CallReference,
- sm-RP-OA SM-RP-OA,
- sm-RP-UI SignalInfo,
- extensionContainer ExtensionContainer OPTIONAL,
- ...}
-
-MT-ForwardSM-VGCS-Res ::= SEQUENCE {
- sm-RP-UI [0] SignalInfo OPTIONAL,
- dispatcherList [1] DispatcherList OPTIONAL,
- ongoingCall NULL OPTIONAL,
- extensionContainer [2] ExtensionContainer OPTIONAL,
- ...}
-
-DispatcherList ::=
- SEQUENCE SIZE (1..maxNumOfDispatchers) OF
- ISDN-AddressString
-
-maxNumOfDispatchers INTEGER ::= 5
-
-
-
-END
-
diff --git a/rrlp-ephemeris/asn1/MAP-SS-Code.asn b/rrlp-ephemeris/asn1/MAP-SS-Code.asn
deleted file mode 100644
index 163f2dc..0000000
--- a/rrlp-ephemeris/asn1/MAP-SS-Code.asn
+++ /dev/null
@@ -1,190 +0,0 @@
--- $Id: MAP-SS-Code.asn 28149 2009-04-25 17:45:34Z etxrab $
--- 3GPP TS 29.002 V8.9.0 (2009-04)
--- 17.7.5 Supplementary service codes
-
-MAP-SS-Code {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-SS-Code (15) version11 (11)}
-
-DEFINITIONS
-
-::=
-
-BEGIN
-
-SS-Code ::= OCTET STRING (SIZE (1))
- -- This type is used to represent the code identifying a single
- -- supplementary service, a group of supplementary services, or
- -- all supplementary services. The services and abbreviations
- -- used are defined in TS 3GPP TS 22.004 [5]. The internal structure is
- -- defined as follows:
- --
- -- bits 87654321: group (bits 8765), and specific service
- -- (bits 4321)
-
-allSS SS-Code ::= '00000000'B
- -- reserved for possible future use
- -- all SS
-
-allLineIdentificationSS SS-Code ::= '00010000'B
- -- reserved for possible future use
- -- all line identification SS
-clip SS-Code ::= '00010001'B
- -- calling line identification presentation
-clir SS-Code ::= '00010010'B
- -- calling line identification restriction
-colp SS-Code ::= '00010011'B
- -- connected line identification presentation
-colr SS-Code ::= '00010100'B
- -- connected line identification restriction
-mci SS-Code ::= '00010101'B
- -- reserved for possible future use
- -- malicious call identification
-
-allNameIdentificationSS SS-Code ::= '00011000'B
- -- all name identification SS
-cnap SS-Code ::= '00011001'B
- -- calling name presentation
-
- -- SS-Codes '00011010'B to '00011111'B are reserved for future
- -- NameIdentification Supplementary Service use.
-
-allForwardingSS SS-Code ::= '00100000'B
- -- all forwarding SS
-cfu SS-Code ::= '00100001'B
- -- call forwarding unconditional
-allCondForwardingSS SS-Code ::= '00101000'B
- -- all conditional forwarding SS
-cfb SS-Code ::= '00101001'B
- -- call forwarding on mobile subscriber busy
-cfnry SS-Code ::= '00101010'B
- -- call forwarding on no reply
-cfnrc SS-Code ::= '00101011'B
- -- call forwarding on mobile subscriber not reachable
-cd SS-Code ::= '00100100'B
- -- call deflection
-
-allCallOfferingSS SS-Code ::= '00110000'B
- -- reserved for possible future use
- -- all call offering SS includes also all forwarding SS
-ect SS-Code ::= '00110001'B
- -- explicit call transfer
-mah SS-Code ::= '00110010'B
- -- reserved for possible future use
- -- mobile access hunting
-
-allCallCompletionSS SS-Code ::= '01000000'B
- -- reserved for possible future use
- -- all Call completion SS
-cw SS-Code ::= '01000001'B
- -- call waiting
-hold SS-Code ::= '01000010'B
- -- call hold
-ccbs-A SS-Code ::= '01000011'B
- -- completion of call to busy subscribers, originating side
- -- this SS-Code is used only in InsertSubscriberData, DeleteSubscriberData
- -- and InterrogateSS
-ccbs-B SS-Code ::= '01000100'B
- -- completion of call to busy subscribers, destination side
- -- this SS-Code is used only in InsertSubscriberData and DeleteSubscriberData
-mc SS-Code ::= '01000101'B
- -- multicall
-
-allMultiPartySS SS-Code ::= '01010000'B
- -- reserved for possible future use
- -- all multiparty SS
-multiPTY SS-Code ::= '01010001'B
- -- multiparty
-
-allCommunityOfInterest-SS SS-Code ::= '01100000'B
- -- reserved for possible future use
- -- all community of interest SS
-cug SS-Code ::= '01100001'B
- -- closed user group
-
-allChargingSS SS-Code ::= '01110000'B
- -- reserved for possible future use
- -- all charging SS
-aoci SS-Code ::= '01110001'B
- -- advice of charge information
-aocc SS-Code ::= '01110010'B
- -- advice of charge charging
-
-allAdditionalInfoTransferSS SS-Code ::= '10000000'B
- -- reserved for possible future use
- -- all additional information transfer SS
-uus1 SS-Code ::= '10000001'B
- -- UUS1 user-to-user signalling
-uus2 SS-Code ::= '10000010'B
- -- UUS2 user-to-user signalling
-uus3 SS-Code ::= '10000011'B
- -- UUS3 user-to-user signalling
-
-allBarringSS SS-Code ::= '10010000'B
- -- all barring SS
-barringOfOutgoingCalls SS-Code ::= '10010001'B
- -- barring of outgoing calls
-baoc SS-Code ::= '10010010'B
- -- barring of all outgoing calls
-boic SS-Code ::= '10010011'B
- -- barring of outgoing international calls
-boicExHC SS-Code ::= '10010100'B
- -- barring of outgoing international calls except those directed
- -- to the home PLMN Country
-barringOfIncomingCalls SS-Code ::= '10011001'B
- -- barring of incoming calls
-baic SS-Code ::= '10011010'B
- -- barring of all incoming calls
-bicRoam SS-Code ::= '10011011'B
- -- barring of incoming calls when roaming outside home PLMN
- -- Country
-
-allPLMN-specificSS SS-Code ::= '11110000'B
-plmn-specificSS-1 SS-Code ::= '11110001'B
-plmn-specificSS-2 SS-Code ::= '11110010'B
-plmn-specificSS-3 SS-Code ::= '11110011'B
-plmn-specificSS-4 SS-Code ::= '11110100'B
-plmn-specificSS-5 SS-Code ::= '11110101'B
-plmn-specificSS-6 SS-Code ::= '11110110'B
-plmn-specificSS-7 SS-Code ::= '11110111'B
-plmn-specificSS-8 SS-Code ::= '11111000'B
-plmn-specificSS-9 SS-Code ::= '11111001'B
-plmn-specificSS-A SS-Code ::= '11111010'B
-plmn-specificSS-B SS-Code ::= '11111011'B
-plmn-specificSS-C SS-Code ::= '11111100'B
-plmn-specificSS-D SS-Code ::= '11111101'B
-plmn-specificSS-E SS-Code ::= '11111110'B
-plmn-specificSS-F SS-Code ::= '11111111'B
-
-allCallPrioritySS SS-Code ::= '10100000'B
- -- reserved for possible future use
- -- all call priority SS
-emlpp SS-Code ::= '10100001'B
- -- enhanced Multilevel Precedence Pre-emption (EMLPP) service
-
-allLCSPrivacyException SS-Code ::= '10110000'B
- -- all LCS Privacy Exception Classes
-universal SS-Code ::= '10110001'B
- -- allow location by any LCS client
-callSessionRelated SS-Code ::= '10110010'B
- -- allow location by any value added LCS client to which a call/session
- -- is established from the target MS
-callSessionUnrelated SS-Code ::= '10110011'B
- -- allow location by designated external value added LCS clients
-plmnoperator SS-Code ::= '10110100'B
- -- allow location by designated PLMN operator LCS clients
-serviceType SS-Code ::= '10110101'B
- -- allow location by LCS clients of a designated LCS service type
-
-allMOLR-SS SS-Code ::= '11000000'B
- -- all Mobile Originating Location Request Classes
-basicSelfLocation SS-Code ::= '11000001'B
- -- allow an MS to request its own location
-autonomousSelfLocation SS-Code ::= '11000010'B
- -- allow an MS to perform self location without interaction
- -- with the PLMN for a predetermined period of time
-transferToThirdParty SS-Code ::= '11000011'B
- -- allow an MS to request transfer of its location to another LCS client
-
-END
-
diff --git a/rrlp-ephemeris/asn1/MAP-SS-DataTypes.asn b/rrlp-ephemeris/asn1/MAP-SS-DataTypes.asn
deleted file mode 100644
index 253f7f0..0000000
--- a/rrlp-ephemeris/asn1/MAP-SS-DataTypes.asn
+++ /dev/null
@@ -1,342 +0,0 @@
--- $Id: MAP-SS-DataTypes.asn 28149 2009-04-25 17:45:34Z etxrab $
--- 3GPP TS 29.002 V8.9.0 (2009-04)
--- 17.7.4 Supplementary service data types
-
-MAP-SS-DataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-SS-DataTypes (14) version11 (11)}
-
-DEFINITIONS
-
-IMPLICIT TAGS
-
-::=
-
-BEGIN
-
-EXPORTS
- RegisterSS-Arg,
- SS-Info,
- SS-Status,
- SS-SubscriptionOption,
- SS-ForBS-Code,
- InterrogateSS-Res,
- USSD-Arg,
- USSD-Res,
- USSD-DataCodingScheme,
- USSD-String,
- Password,
- GuidanceInfo,
- SS-List,
- SS-InfoList,
- OverrideCategory,
- CliRestrictionOption,
- NoReplyConditionTime,
- ForwardingOptions,
- maxNumOfSS,
- SS-Data,
- SS-InvocationNotificationArg,
- SS-InvocationNotificationRes,
- CCBS-Feature,
- RegisterCC-EntryArg,
- RegisterCC-EntryRes,
- EraseCC-EntryArg,
- EraseCC-EntryRes
-;
-
-IMPORTS
- AddressString,
- ISDN-AddressString,
- ISDN-SubaddressString,
- FTN-AddressString,
- IMSI,
- BasicServiceCode,
- AlertingPattern,
- EMLPP-Priority,
- MaxMC-Bearers,
- MC-Bearers,
- ExternalSignalInfo
-FROM MAP-CommonDataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-CommonDataTypes (18) version11 (11)}
-
- ExtensionContainer
-FROM MAP-ExtensionDataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
-
- SS-Code
-FROM MAP-SS-Code {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-SS-Code (15) version11 (11)}
-;
-
-
-RegisterSS-Arg ::= SEQUENCE {
- ss-Code SS-Code,
- basicService BasicServiceCode OPTIONAL,
- forwardedToNumber [4] AddressString OPTIONAL,
- forwardedToSubaddress [6] ISDN-SubaddressString OPTIONAL,
- noReplyConditionTime [5] NoReplyConditionTime OPTIONAL,
- ...,
- defaultPriority [7] EMLPP-Priority OPTIONAL,
- nbrUser [8] MC-Bearers OPTIONAL,
- longFTN-Supported [9] NULL OPTIONAL }
-
-NoReplyConditionTime ::= INTEGER (5..30)
-
-SS-Info ::= CHOICE {
- forwardingInfo [0] ForwardingInfo,
- callBarringInfo [1] CallBarringInfo,
- ss-Data [3] SS-Data}
-
-ForwardingInfo ::= SEQUENCE {
- ss-Code SS-Code OPTIONAL,
- forwardingFeatureList ForwardingFeatureList,
- ...}
-
-ForwardingFeatureList ::=
- SEQUENCE SIZE (1..maxNumOfBasicServiceGroups) OF
- ForwardingFeature
-
-ForwardingFeature ::= SEQUENCE {
- basicService BasicServiceCode OPTIONAL,
- ss-Status [4] SS-Status OPTIONAL,
- forwardedToNumber [5] ISDN-AddressString OPTIONAL,
- forwardedToSubaddress [8] ISDN-SubaddressString OPTIONAL,
- forwardingOptions [6] ForwardingOptions OPTIONAL,
- noReplyConditionTime [7] NoReplyConditionTime OPTIONAL,
- ...,
- longForwardedToNumber [9] FTN-AddressString OPTIONAL }
-
-SS-Status ::= OCTET STRING (SIZE (1))
-
- -- bits 8765: 0000 (unused)
- -- bits 4321: Used to convey the "P bit","R bit","A bit" and "Q bit",
- -- representing supplementary service state information
- -- as defined in TS 3GPP TS 23.011 [22]
-
- -- bit 4: "Q bit"
-
- -- bit 3: "P bit"
-
- -- bit 2: "R bit"
-
- -- bit 1: "A bit"
-
-ForwardingOptions ::= OCTET STRING (SIZE (1))
-
- -- bit 8: notification to forwarding party
- -- 0 no notification
- -- 1 notification
-
- -- bit 7: redirecting presentation
- -- 0 no presentation
- -- 1 presentation
-
- -- bit 6: notification to calling party
- -- 0 no notification
- -- 1 notification
-
- -- bit 5: 0 (unused)
-
- -- bits 43: forwarding reason
- -- 00 ms not reachable
- -- 01 ms busy
- -- 10 no reply
- -- 11 unconditional when used in a SRI Result,
- -- or call deflection when used in a RCH Argument
- -- bits 21: 00 (unused)
-
-CallBarringInfo ::= SEQUENCE {
- ss-Code SS-Code OPTIONAL,
- callBarringFeatureList CallBarringFeatureList,
- ...}
-
-CallBarringFeatureList ::= SEQUENCE SIZE (1..maxNumOfBasicServiceGroups) OF
- CallBarringFeature
-
-CallBarringFeature ::= SEQUENCE {
- basicService BasicServiceCode OPTIONAL,
- ss-Status [4] SS-Status OPTIONAL,
- ...}
-
-SS-Data ::= SEQUENCE {
- ss-Code SS-Code OPTIONAL,
- ss-Status [4] SS-Status OPTIONAL,
- ss-SubscriptionOption SS-SubscriptionOption OPTIONAL,
- basicServiceGroupList BasicServiceGroupList OPTIONAL,
- ...,
- defaultPriority EMLPP-Priority OPTIONAL,
- nbrUser [5] MC-Bearers OPTIONAL
- }
-
-SS-SubscriptionOption ::= CHOICE {
- cliRestrictionOption [2] CliRestrictionOption,
- overrideCategory [1] OverrideCategory}
-
-CliRestrictionOption ::= ENUMERATED {
- permanent (0),
- temporaryDefaultRestricted (1),
- temporaryDefaultAllowed (2)}
-
-OverrideCategory ::= ENUMERATED {
- overrideEnabled (0),
- overrideDisabled (1)}
-
-SS-ForBS-Code ::= SEQUENCE {
- ss-Code SS-Code,
- basicService BasicServiceCode OPTIONAL,
- ...,
- longFTN-Supported [4] NULL OPTIONAL }
-
-GenericServiceInfo ::= SEQUENCE {
- ss-Status SS-Status,
- cliRestrictionOption CliRestrictionOption OPTIONAL,
- ...,
- maximumEntitledPriority [0] EMLPP-Priority OPTIONAL,
- defaultPriority [1] EMLPP-Priority OPTIONAL,
- ccbs-FeatureList [2] CCBS-FeatureList OPTIONAL,
- nbrSB [3] MaxMC-Bearers OPTIONAL,
- nbrUser [4] MC-Bearers OPTIONAL,
- nbrSN [5] MC-Bearers OPTIONAL }
-
-CCBS-FeatureList ::= SEQUENCE SIZE (1..maxNumOfCCBS-Requests) OF
- CCBS-Feature
-
-maxNumOfCCBS-Requests INTEGER ::= 5
-
-CCBS-Feature ::= SEQUENCE {
- ccbs-Index [0] CCBS-Index OPTIONAL,
- b-subscriberNumber [1] ISDN-AddressString OPTIONAL,
- b-subscriberSubaddress [2] ISDN-SubaddressString OPTIONAL,
- basicServiceGroup [3] BasicServiceCode OPTIONAL,
- ...}
-
-CCBS-Index ::= INTEGER (1..maxNumOfCCBS-Requests)
-
-InterrogateSS-Res ::= CHOICE {
- ss-Status [0] SS-Status,
- basicServiceGroupList [2] BasicServiceGroupList,
- forwardingFeatureList [3] ForwardingFeatureList,
- genericServiceInfo [4] GenericServiceInfo }
-
-USSD-Arg ::= SEQUENCE {
- ussd-DataCodingScheme USSD-DataCodingScheme,
- ussd-String USSD-String,
- ... ,
- alertingPattern AlertingPattern OPTIONAL,
- msisdn [0] ISDN-AddressString OPTIONAL }
-
-USSD-Res ::= SEQUENCE {
- ussd-DataCodingScheme USSD-DataCodingScheme,
- ussd-String USSD-String,
- ...}
-
-USSD-DataCodingScheme ::= OCTET STRING (SIZE (1))
- -- The structure of the USSD-DataCodingScheme is defined by
- -- the Cell Broadcast Data Coding Scheme as described in
- -- TS 3GPP TS 23.038 [25]
-
-USSD-String ::= OCTET STRING (SIZE (1..maxUSSD-StringLength))
- -- The structure of the contents of the USSD-String is dependent
- -- on the USSD-DataCodingScheme as described in TS 3GPP TS 23.038 [25].
-
-maxUSSD-StringLength INTEGER ::= 160
-
-Password ::= NumericString
- (FROM ("0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"))
- (SIZE (4))
-
-GuidanceInfo ::= ENUMERATED {
- enterPW (0),
- enterNewPW (1),
- enterNewPW-Again (2)}
- -- How this information is really delivered to the subscriber
- -- (display, announcement, ...) is not part of this
- -- specification.
-
-SS-List ::= SEQUENCE SIZE (1..maxNumOfSS) OF
- SS-Code
-
-maxNumOfSS INTEGER ::= 30
-
-SS-InfoList ::= SEQUENCE SIZE (1..maxNumOfSS) OF
- SS-Info
-
-BasicServiceGroupList ::= SEQUENCE SIZE (1..maxNumOfBasicServiceGroups) OF
- BasicServiceCode
-
-maxNumOfBasicServiceGroups INTEGER ::= 13
-
-SS-InvocationNotificationArg ::= SEQUENCE {
- imsi [0] IMSI,
- msisdn [1] ISDN-AddressString,
- ss-Event [2] SS-Code,
- -- The following SS-Code values are allowed :
- -- ect SS-Code ::= '00110001'B
- -- multiPTY SS-Code ::= '01010001'B
- -- cd SS-Code ::= '00100100'B
- -- ccbs SS-Code ::= '01000100'B
- ss-EventSpecification [3] SS-EventSpecification OPTIONAL,
- extensionContainer [4] ExtensionContainer OPTIONAL,
- ...,
- b-subscriberNumber [5] ISDN-AddressString OPTIONAL,
- ccbs-RequestState [6] CCBS-RequestState OPTIONAL
- }
-
-CCBS-RequestState ::= ENUMERATED {
- request (0),
- recall (1),
- active (2),
- completed (3),
- suspended (4),
- frozen (5),
- deleted (6)
- }
-
-SS-InvocationNotificationRes ::= SEQUENCE {
- extensionContainer ExtensionContainer OPTIONAL,
- ...
- }
-
-SS-EventSpecification ::= SEQUENCE SIZE (1..maxEventSpecification) OF
- AddressString
-
-maxEventSpecification INTEGER ::= 2
-
-RegisterCC-EntryArg ::= SEQUENCE {
- ss-Code [0] SS-Code,
- ccbs-Data [1] CCBS-Data OPTIONAL,
- ...}
-
-CCBS-Data ::= SEQUENCE {
- ccbs-Feature [0] CCBS-Feature,
- translatedB-Number [1] ISDN-AddressString,
- serviceIndicator [2] ServiceIndicator OPTIONAL,
- callInfo [3] ExternalSignalInfo,
- networkSignalInfo [4] ExternalSignalInfo,
- ...}
-
-ServiceIndicator ::= BIT STRING {
- clir-invoked (0),
- camel-invoked (1)} (SIZE(2..32))
- -- exception handling:
- -- bits 2 to 31 shall be ignored if received and not understood
-
-RegisterCC-EntryRes ::= SEQUENCE {
- ccbs-Feature [0] CCBS-Feature OPTIONAL,
- ...}
-
-EraseCC-EntryArg ::= SEQUENCE {
- ss-Code [0] SS-Code,
- ccbs-Index [1] CCBS-Index OPTIONAL,
- ...}
-
-EraseCC-EntryRes ::= SEQUENCE {
- ss-Code [0] SS-Code,
- ss-Status [1] SS-Status OPTIONAL,
- ...}
-
-END
-
diff --git a/rrlp-ephemeris/asn1/MAP-TS-Code.asn b/rrlp-ephemeris/asn1/MAP-TS-Code.asn
deleted file mode 100644
index 5ac00bf..0000000
--- a/rrlp-ephemeris/asn1/MAP-TS-Code.asn
+++ /dev/null
@@ -1,92 +0,0 @@
--- $Id: MAP-TS-Code.asn 28149 2009-04-25 17:45:34Z etxrab $
--- 3GPP TS 29.002 V8.9.0 (2009-04)
--- 17.7.9 Teleservice Codes
-
-MAP-TS-Code {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-TS-Code (19) version11 (11)}
-
-DEFINITIONS
-
-::=
-
-BEGIN
-
-TeleserviceCode ::= OCTET STRING (SIZE (1))
- -- This type is used to represent the code identifying a single
- -- teleservice, a group of teleservices, or all teleservices. The
- -- services are defined in TS GSM 22.003 [4].
- -- The internal structure is defined as follows:
-
- -- bits 87654321: group (bits 8765) and specific service
- -- (bits 4321)
-
-Ext-TeleserviceCode ::= OCTET STRING (SIZE (1..5))
- -- This type is used to represent the code identifying a single
- -- teleservice, a group of teleservices, or all teleservices. The
- -- services are defined in TS GSM 22.003 [4].
- -- The internal structure is defined as follows:
-
- -- OCTET 1:
- -- bits 87654321: group (bits 8765) and specific service
- -- (bits 4321)
-
- -- OCTETS 2-5: reserved for future use. If received the
- -- Ext-TeleserviceCode shall be
- -- treated according to the exception handling defined for the
- -- operation that uses this type.
-
- -- Ext-TeleserviceCode includes all values defined for TeleserviceCode.
-
-allTeleservices TeleserviceCode ::= '00000000'B
-
-allSpeechTransmissionServices TeleserviceCode ::= '00010000'B
-telephony TeleserviceCode ::= '00010001'B
-emergencyCalls TeleserviceCode ::= '00010010'B
-
-allShortMessageServices TeleserviceCode ::= '00100000'B
-shortMessageMT-PP TeleserviceCode ::= '00100001'B
-shortMessageMO-PP TeleserviceCode ::= '00100010'B
-
-allFacsimileTransmissionServices TeleserviceCode ::= '01100000'B
-facsimileGroup3AndAlterSpeech TeleserviceCode ::= '01100001'B
-automaticFacsimileGroup3 TeleserviceCode ::= '01100010'B
-facsimileGroup4 TeleserviceCode ::= '01100011'B
-
--- The following non-hierarchical Compound Teleservice Groups
--- are defined in TS 3GPP TS 22.030:
-allDataTeleservices TeleserviceCode ::= '01110000'B
- -- covers Teleservice Groups 'allFacsimileTransmissionServices'
- -- and 'allShortMessageServices'
-allTeleservices-ExeptSMS TeleserviceCode ::= '10000000'B
- -- covers Teleservice Groups 'allSpeechTransmissionServices' and
- -- 'allFacsimileTransmissionServices'
---
--- Compound Teleservice Group Codes are only used in call
--- independent supplementary service operations, i.e. they
--- are not used in InsertSubscriberData or in
--- DeleteSubscriberData messages.
-
-allVoiceGroupCallServices TeleserviceCode ::= '10010000'B
-voiceGroupCall TeleserviceCode ::= '10010001'B
-voiceBroadcastCall TeleserviceCode ::= '10010010'B
-
-allPLMN-specificTS TeleserviceCode ::= '11010000'B
-plmn-specificTS-1 TeleserviceCode ::= '11010001'B
-plmn-specificTS-2 TeleserviceCode ::= '11010010'B
-plmn-specificTS-3 TeleserviceCode ::= '11010011'B
-plmn-specificTS-4 TeleserviceCode ::= '11010100'B
-plmn-specificTS-5 TeleserviceCode ::= '11010101'B
-plmn-specificTS-6 TeleserviceCode ::= '11010110'B
-plmn-specificTS-7 TeleserviceCode ::= '11010111'B
-plmn-specificTS-8 TeleserviceCode ::= '11011000'B
-plmn-specificTS-9 TeleserviceCode ::= '11011001'B
-plmn-specificTS-A TeleserviceCode ::= '11011010'B
-plmn-specificTS-B TeleserviceCode ::= '11011011'B
-plmn-specificTS-C TeleserviceCode ::= '11011100'B
-plmn-specificTS-D TeleserviceCode ::= '11011101'B
-plmn-specificTS-E TeleserviceCode ::= '11011110'B
-plmn-specificTS-F TeleserviceCode ::= '11011111'B
-
-END
-
diff --git a/rrlp-ephemeris/asn1/RRLP-Components.asn b/rrlp-ephemeris/asn1/RRLP-Components.asn
deleted file mode 100644
index 3bade6a..0000000
--- a/rrlp-ephemeris/asn1/RRLP-Components.asn
+++ /dev/null
@@ -1,1488 +0,0 @@
--- RRLP-Components.asn
--- $Id$
--- Taken from 3GPP TS 44.031 V7.4.0 (2007-03)
--- http://www.3gpp.org/ftp/Specs/archive/44_series/44.031/44031-740.zip/44031-740.doc
---
--- 4 Components
--- 5 Elements of Components
---
-
-RRLP-Components
--- { RRLP-Components }
-
-DEFINITIONS AUTOMATIC TAGS ::=
-
-BEGIN
-
-IMPORTS
- Ext-GeographicalInformation, VelocityEstimate
-FROM
- MAP-LCS-DataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-LCS-DataTypes (25) version11 (11)}
-
- ExtensionContainer
-FROM MAP-ExtensionDataTypes {
- itu-t identified-organization (4) etsi (0) mobileDomain (0)
- gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
-;
-
-
--- Add here other ASN.1 definitions presented below
--- in chapters 4 and 5.
-
--- Measurement Position request component
-MsrPosition-Req ::= SEQUENCE {
- positionInstruct PositionInstruct,
- referenceAssistData ReferenceAssistData OPTIONAL,
- msrAssistData MsrAssistData OPTIONAL,
- systemInfoAssistData SystemInfoAssistData OPTIONAL,
- gps-AssistData GPS-AssistData OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- -- Release 98 extension element
-rel98-MsrPosition-Req-extension Rel98-MsrPosition-Req-Extension OPTIONAL,
- -- Release 5 extension element
-rel5-MsrPosition-Req-extension Rel5-MsrPosition-Req-Extension OPTIONAL,
- -- Release 7 extension element
-rel7-MsrPosition-Req-extension Rel7-MsrPosition-Req-Extension OPTIONAL
-}
-
--- Measurement Position response component
-MsrPosition-Rsp ::= SEQUENCE {
- multipleSets MultipleSets OPTIONAL,
- referenceIdentity ReferenceIdentity OPTIONAL,
- otd-MeasureInfo OTD-MeasureInfo OPTIONAL,
- locationInfo LocationInfo OPTIONAL,
- gps-MeasureInfo GPS-MeasureInfo OPTIONAL,
- locationError LocationError OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- -- Release extension here
- rel-98-MsrPosition-Rsp-Extension
- Rel-98-MsrPosition-Rsp-Extension OPTIONAL,
- rel-5-MsrPosition-Rsp-Extension
- Rel-5-MsrPosition-Rsp-Extension OPTIONAL,
- -- rel-5-MsrPosition-Rsp-Extension and other possible future extensions
- -- are the only information elements that may be included in the 2nd
- -- MsrPosition-Rsp component when RRLP pseudo-segmentation is used
- rel-7-MsrPosition-Rsp-Extension
- Rel-7-MsrPosition-Rsp-Extension OPTIONAL
-}
-
--- Assistance Data component
-AssistanceData ::= SEQUENCE {
- referenceAssistData ReferenceAssistData OPTIONAL,
- msrAssistData MsrAssistData OPTIONAL,
- systemInfoAssistData SystemInfoAssistData OPTIONAL,
- gps-AssistData GPS-AssistData OPTIONAL,
- moreAssDataToBeSent MoreAssDataToBeSent OPTIONAL, -- If not present, interpret as only
- -- Assistance Data component used to
- -- deliver entire set of assistance
- -- data.
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- -- Release extension here
- rel98-AssistanceData-Extension Rel98-AssistanceData-Extension OPTIONAL,
- rel5-AssistanceData-Extension Rel5-AssistanceData-Extension OPTIONAL,
- rel7-AssistanceData-Extension Rel7-AssistanceData-Extension OPTIONAL
-}
-
--- Protocol Error component
-ProtocolError ::= SEQUENCE {
- errorCause ErrorCodes,
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- -- Release extensions here
- rel-5-ProtocolError-Extension Rel-5-ProtocolError-Extension OPTIONAL
-}
-
--- Position instructions
-PositionInstruct ::= SEQUENCE {
- -- Method type
- methodType MethodType,
- positionMethod PositionMethod,
- measureResponseTime MeasureResponseTime,
- useMultipleSets UseMultipleSets,
- environmentCharacter EnvironmentCharacter OPTIONAL
-}
-
---
-MethodType ::= CHOICE {
- msAssisted AccuracyOpt, -- accuracy is optional
- msBased Accuracy, -- accuracy is mandatory
- msBasedPref Accuracy, -- accuracy is mandatory
- msAssistedPref Accuracy -- accuracy is mandatory
-}
-
--- Accuracy of the location estimation
-AccuracyOpt ::= SEQUENCE {
- accuracy Accuracy OPTIONAL
-}
-
--- The values of this field are defined in 3GPP TS 23.032 (Uncertainty code)
-Accuracy ::= INTEGER (0..127)
-
-
--- Position Method
-PositionMethod ::= ENUMERATED {
- eotd (0),
- gps (1),
- gpsOrEOTD (2)
-}
-
--- Measurement request response time
-MeasureResponseTime ::= INTEGER (0..7)
-
--- useMultiple Sets, FFS!
-UseMultipleSets ::= ENUMERATED {
- multipleSets (0), -- multiple sets are allowed
- oneSet (1) -- sending of multiple is not allowed
-}
-
--- Environment characterization
-EnvironmentCharacter ::= ENUMERATED {
- badArea (0), -- bad urban or suburban, heavy multipath and NLOS
- notBadArea (1), -- light multipath and NLOS
- mixedArea (2), -- not defined or mixed environment
- ...
-}
-
--- E-OTD reference BTS for Assitance data IE
-ReferenceAssistData ::= SEQUENCE {
- bcchCarrier BCCHCarrier, -- BCCH carrier
- bsic BSIC, -- BSIC
- timeSlotScheme TimeSlotScheme, -- Timeslot scheme
- btsPosition BTSPosition OPTIONAL
-}
-
--- ellipsoid point and
--- ellipsoid point with altitude and uncertainty ellipsoid shapes are supported
-BTSPosition ::= Ext-GeographicalInformation
-
--- RF channel number of BCCH
-BCCHCarrier ::= INTEGER (0..1023)
-
--- Base station Identity Code
-BSIC ::= INTEGER (0..63)
-
--- Timeslot scheme
-TimeSlotScheme ::= ENUMERATED {
- equalLength (0),
- variousLength (1)
-}
-
--- Time slot (modulo)
-ModuloTimeSlot ::= INTEGER (0..3)
-
--- E-OTD measurement assistance data IE
--- The total number of neighbors in this element (MsrAssistData)
--- and in SystemInfoAssistData element (presented neighbors
--- can be at a maximum 15!)
-MsrAssistData ::= SEQUENCE {
- msrAssistList SeqOfMsrAssistBTS
-}
-SeqOfMsrAssistBTS ::= SEQUENCE (SIZE(1..15)) OF MsrAssistBTS
-
-MsrAssistBTS ::= SEQUENCE {
- bcchCarrier BCCHCarrier, -- BCCH carrier
- bsic BSIC, -- BSIC
- multiFrameOffset MultiFrameOffset, -- multiframe offset
- timeSlotScheme TimeSlotScheme, -- Timeslot scheme
- roughRTD RoughRTD, -- rough RTD value
-
- -- Location Calculation Assistance data is moved here
- calcAssistanceBTS CalcAssistanceBTS OPTIONAL
-}
-
--- Multiframe offset
-MultiFrameOffset ::= INTEGER (0..51)
--- The Multiframe Offset value 51 shall not be encoded by the transmitting entity and
--- shall be treated by the receiving entity as 0.
-
--- Rough RTD value between one base station and reference BTS
-RoughRTD ::= INTEGER (0..1250)
--- The RoughRTD value 1250 shall not be encoded by the transmitting entity and shall
--- be treated by the receiving entity as 0.
-
--- E-OTD Measurement assistance data for system information List IE
--- The total number of base stations in this element (SystemInfoAssistData
--- presented neighbors) and in MsrAssistData element can be at a maximum 15.
-SystemInfoAssistData ::= SEQUENCE {
- systemInfoAssistList SeqOfSystemInfoAssistBTS
-}
-SeqOfSystemInfoAssistBTS::= SEQUENCE (SIZE(1..32)) OF SystemInfoAssistBTS
-
--- whether n.th is present or not ?
-SystemInfoAssistBTS ::= CHOICE {
- notPresent NULL,
- present AssistBTSData
-}
-
--- Actual assistance data for system information base station
-AssistBTSData ::= SEQUENCE {
- bsic BSIC, -- BSIC
- multiFrameOffset MultiFrameOffset, -- multiframe offset
- timeSlotScheme TimeSlotScheme, -- Timeslot scheme
- roughRTD RoughRTD, -- rough RTD value
-
- -- Location Calculation Assistance data
- calcAssistanceBTS CalcAssistanceBTS OPTIONAL
-}
-
--- E-OTD Location calculation assistance data,
--- CalcAssistanceBTS element is optional not subfields
-CalcAssistanceBTS ::= SEQUENCE {
- fineRTD FineRTD, -- fine RTD value between base stations
- referenceWGS84 ReferenceWGS84 -- reference coordinates
-}
-
--- Coordinates of neighbour BTS, WGS-84 ellipsoid
-ReferenceWGS84 ::= SEQUENCE {
- relativeNorth RelDistance, -- relative distance (south negative)
- relativeEast RelDistance, -- relative distance (west negative)
- -- Relative Altitude is not always known
- relativeAlt RelativeAlt OPTIONAL -- relative altitude
-}
-
--- Fine RTD value between this BTS and the reference BTS
-FineRTD ::= INTEGER (0..255)
-
--- Relative north/east distance
-RelDistance ::= INTEGER (-200000..200000)
-
--- Relative altitude
-RelativeAlt ::= INTEGER (-4000..4000)
-
--- Measure position response IEs
--- Reference Identity
--- Multiple sets
-MultipleSets ::= SEQUENCE {
- -- number of reference sets
- nbrOfSets INTEGER (2..3),
-
- -- This field actually tells the number of reference BTSs
- nbrOfReferenceBTSs INTEGER (1..3),
-
- -- This field is conditional and included optionally only if
- -- nbrOfSets is 3 and number of reference BTSs is 2.
- referenceRelation ReferenceRelation OPTIONAL
-}
-
--- Relation between refence BTSs and sets
-ReferenceRelation ::= ENUMERATED {
- secondBTSThirdSet (0), -- 1st BTS related to 1st and 2nd sets
- secondBTSSecondSet (1), -- 1st BTS related to 1st and 3rd sets
- firstBTSFirstSet (2) -- 1st BTS related to 1st set
-}
-
--- Reference BTS Identity, this element contains number of
--- BTSs told nbrOfReferenceBTSs field in Multiple sets element)
-ReferenceIdentity ::= SEQUENCE {
- -- Reference BTS list
- refBTSList SeqOfReferenceIdentityType
-}
-SeqOfReferenceIdentityType ::= SEQUENCE (SIZE(1..3)) OF ReferenceIdentityType
-
--- Cell identity
-ReferenceIdentityType ::= CHOICE {
- bsicAndCarrier BSICAndCarrier, -- BSIC and Carrier
- ci CellID, -- Cell ID, LAC not needed
- requestIndex RequestIndex, -- Index to Requested Neighbor List
- systemInfoIndex SystemInfoIndex, -- Index to System info list, this type of ref. identity
- -- shall not be used by the MS unless it has received
- -- the SystemInfoAssistData from the SMLC for this cell.
- ciAndLAC CellIDAndLAC -- CI and LAC
-}
-
-BSICAndCarrier ::= SEQUENCE {
- carrier BCCHCarrier,
- bsic BSIC
-}
-
-RequestIndex ::= INTEGER (1..16)
-
-SystemInfoIndex ::= INTEGER (1..32)
-
-CellIDAndLAC ::= SEQUENCE {
- referenceLAC LACID, -- Location area code
- referenceCI CellID -- Cell identity
-}
-CellID ::= INTEGER (0..65535)
-LACID ::= INTEGER (0..65535)
-
--- OTD-MeasureInfo
-OTD-MeasureInfo ::= SEQUENCE {
- -- Measurement info elements, OTD-MsrElement is repeated number of times
- -- told in nbrOfReferenceBTSs in MultipleSets, default value is 1
- otdMsrFirstSets OTD-MsrElementFirst,
-
- -- if more than one sets are present this element is repeated
- -- NumberOfSets - 1 (-1 = first set)
- otdMsrRestSets SeqOfOTD-MsrElementRest OPTIONAL
-}
-
-SeqOfOTD-MsrElementRest ::= SEQUENCE (SIZE(1..2)) OF OTD-MsrElementRest
-
--- OTD measurent information for 1 set
-OTD-MsrElementFirst ::= SEQUENCE {
- refFrameNumber INTEGER (0..42431), -- Frame number modulo 42432
- referenceTimeSlot ModuloTimeSlot,
- toaMeasurementsOfRef TOA-MeasurementsOfRef OPTIONAL,
- stdResolution StdResolution,
- taCorrection INTEGER (0..960) OPTIONAL, -- TA correction
-
- -- measured neighbors in OTD measurements
- otd-FirstSetMsrs SeqOfOTD-FirstSetMsrs OPTIONAL
-}
-SeqOfOTD-FirstSetMsrs ::= SEQUENCE (SIZE(1..10)) OF OTD-FirstSetMsrs
-
--- OTD measurent information 2 and 3 sets if exist
-OTD-MsrElementRest ::= SEQUENCE {
- refFrameNumber INTEGER (0..42431), -- Frame number modulo 42432
- referenceTimeSlot ModuloTimeSlot,
- toaMeasurementsOfRef TOA-MeasurementsOfRef OPTIONAL,
- stdResolution StdResolution,
- taCorrection INTEGER (0..960) OPTIONAL, -- TA correction
-
- -- measured neighbors in OTD measurements
- otd-MsrsOfOtherSets SeqOfOTD-MsrsOfOtherSets OPTIONAL
-}
-SeqOfOTD-MsrsOfOtherSets ::= SEQUENCE (SIZE(1..10)) OF OTD-MsrsOfOtherSets
-
--- Standard deviation of the TOA measurements from the reference BTS
-TOA-MeasurementsOfRef ::= SEQUENCE {
- refQuality RefQuality,
- numOfMeasurements NumOfMeasurements
-}
-
-RefQuality ::= INTEGER (0..31) -- St Dev of TOA of reference as defined in annex
-NumOfMeasurements ::= INTEGER (0..7) -- No. of measurements for RefQuality as defined in annex
-StdResolution ::= INTEGER (0..3) -- Values of resolution are defined in annex
-
-OTD-FirstSetMsrs ::= OTD-MeasurementWithID
-
--- Neighbour info in OTD measurements 0-10 times in TD measurement info
-OTD-MsrsOfOtherSets ::= CHOICE {
- identityNotPresent OTD-Measurement,
- identityPresent OTD-MeasurementWithID
-}
-
--- For this OTD measurement identity is same as the identity of BTS
--- in the first set with same sequence number
-OTD-Measurement ::= SEQUENCE {
- nborTimeSlot ModuloTimeSlot,
- eotdQuality EOTDQuality,
- otdValue OTDValue
-}
-
--- This measurement contains the BTS identity and measurement
-OTD-MeasurementWithID ::=SEQUENCE {
- neighborIdentity NeighborIdentity,
- nborTimeSlot ModuloTimeSlot,
- eotdQuality EOTDQuality,
- otdValue OTDValue
-}
-
-EOTDQuality ::= SEQUENCE {
- nbrOfMeasurements INTEGER (0..7),
- stdOfEOTD INTEGER (0..31)
-}
-
-NeighborIdentity ::= CHOICE {
- bsicAndCarrier BSICAndCarrier, -- BSIC and Carrier
- ci CellID, -- Cell ID, LAC not needed
- multiFrameCarrier MultiFrameCarrier, -- MultiFrameOffest and BSIC
- requestIndex RequestIndex, -- Index to Requested Neighbor List
- systemInfoIndex SystemInfoIndex, -- Index to System info list, this type of neighbour
- -- identity shall not be used by the MS unless it has
- -- received the SystemInfoAssistData from the SMLC for
- -- this cell.
- ciAndLAC CellIDAndLAC -- CI and LAC
-}
-
--- Multiframe and carrier
-MultiFrameCarrier ::= SEQUENCE {
- bcchCarrier BCCHCarrier,
- multiFrameOffset MultiFrameOffset
-}
-
--- OTD measurement value for neighbour
-OTDValue ::= INTEGER (0..39999)
-
--- Location information IE
-LocationInfo ::= SEQUENCE {
- refFrame INTEGER (0..65535), -- Reference Frame number
- -- If refFrame is within (42432..65535), it shall be ignored by the receiver
- -- in that case the MS should provide GPS TOW if available
- gpsTOW INTEGER (0..14399999) OPTIONAL, -- GPS TOW
- fixType FixType,
- -- Note that applicable range for refFrame is 0 - 42431
- -- Possible shapes carried in posEstimate are
- -- ellipsoid point,
- -- ellipsoid point with uncertainty circle
- -- ellipsoid point with uncertainty ellipse
- -- ellipsoid point with altitude and uncertainty ellipsoid
- posEstimate Ext-GeographicalInformation
-}
-
-FixType ::= INTEGER {
- twoDFix (0),
- threeDFix (1)
-} (0..1)
-
--- GPS-Measurement information
-GPS-MeasureInfo ::= SEQUENCE {
- -- Measurement info elements
- -- user has to make sure that in this element is number of elements
- -- defined in reference BTS identity
- gpsMsrSetList SeqOfGPS-MsrSetElement
-}
-SeqOfGPS-MsrSetElement ::= SEQUENCE (SIZE(1..3)) OF GPS-MsrSetElement
-
--- OTD measurent information 1-3 times in message
-GPS-MsrSetElement ::= SEQUENCE {
- refFrame INTEGER (0..65535) OPTIONAL, -- Reference Frame number
- gpsTOW GPSTOW24b, -- GPS TOW
- -- Note that applicable range for refFrame is 0 - 42431
-
---N_SAT can be read from number of elements of gps-msrList
-
- gps-msrList SeqOfGPS-MsrElement
-}
-
--- 24 bit presentation for GPSTOW
-GPSTOW24b ::= INTEGER (0..14399999)
-
--- measured elements in measurement parameters field
-SeqOfGPS-MsrElement ::= SEQUENCE (SIZE(1..16)) OF GPS-MsrElement
-
-GPS-MsrElement ::= SEQUENCE {
- satelliteID SatelliteID, -- Satellite identifier
- cNo INTEGER (0..63), -- carrier noise ratio
- doppler INTEGER (-32768..32767), -- doppler, mulltiply by 0.2
- wholeChips INTEGER (0..1022), -- whole value of the code phase measurement
- fracChips INTEGER (0..1024), -- fractional value of the code phase measurement
- -- a value of 1024 shall not be encoded by the sender
- -- the receiver shall consider a value of 1024 to be
- -- invalid data
- mpathIndic MpathIndic, -- multipath indicator
- pseuRangeRMSErr INTEGER (0..63) -- index
-}
-
--- Multipath indicator
-MpathIndic ::= ENUMERATED {
- notMeasured (0),
- low (1),
- medium (2),
- high (3)
-}
-
--- Location error IE
-LocationError ::= SEQUENCE {
- locErrorReason LocErrorReason,
- additionalAssistanceData AdditionalAssistanceData OPTIONAL,
- ...
-}
-
-LocErrorReason ::= ENUMERATED {
- unDefined (0),
- notEnoughBTSs (1),
- notEnoughSats (2),
- eotdLocCalAssDataMissing (3),
- eotdAssDataMissing (4),
- gpsLocCalAssDataMissing (5),
- gpsAssDataMissing (6),
- methodNotSupported (7),
- notProcessed (8),
- refBTSForGPSNotServingBTS (9),
- refBTSForEOTDNotServingBTS (10),
- ...,
- notEnoughGANSSSats (11),
- ganssAssDataMissing (12),
- refBTSForGANSSNotServingBTS (13)
-}
-
--- exception handling:
--- an unrecognized value shall be treated the same as value 0
-
-
--- defines additional assistance data needed for any new location attempt
--- MS shall retain any assistance data already received
-AdditionalAssistanceData ::= SEQUENCE {
- gpsAssistanceData GPSAssistanceData OPTIONAL,
- extensionContainer ExtensionContainer OPTIONAL,
- ...,
- ganssAssistanceData GANSSAssistanceData OPTIONAL
-}
-
-GPSAssistanceData ::= OCTET STRING (SIZE (1..maxGPSAssistanceData))
--- GPSAssistanceData has identical structure and encoding to octets 3 to n of the
--- GPS Assistance Data IE in 3GPP TS 49.031
-
-maxGPSAssistanceData INTEGER ::= 40
-
-GANSSAssistanceData ::= OCTET STRING (SIZE (1..maxGANSSAssistanceData))
--- GANSSAssistanceData has identical structure and encoding to octets 3 to n of the
--- GANSS Assistance Data IE in 3GPP TS 49.031
-
-maxGANSSAssistanceData INTEGER ::= 40
-
-
--- Protocol Error Causes
-ErrorCodes ::= ENUMERATED {
- unDefined (0),
-missingComponet (1),
-incorrectData (2),
-missingIEorComponentElement (3),
-messageTooShort (4),
-unknowReferenceNumber (5),
-...
-}
-
--- exception handling:
--- an unrecognized value shall be treated the same as value 0
-
--- GPS assistance data IE
-GPS-AssistData ::= SEQUENCE {
- controlHeader ControlHeader
-}
-
--- More Assistance Data To Be Sent IE
--- More Assistance Data Components On the Way indication for delivery of an entire set of assistance
--- data in multiple Assistance Data components.
-
-MoreAssDataToBeSent ::= ENUMERATED {
- noMoreMessages (0), -- This is the only or last Assistance Data message used to deliver
- -- the entire set of assistance data.
- moreMessagesOnTheWay (1) -- The SMLC will send more Assistance Data messages or a final RRLP
- -- Measure Position Request message to deliver the
- -- the entire set of assistance data.
-}
-
--- Control header of the GPS assistance data
-ControlHeader ::= SEQUENCE {
-
- -- Field type Present information
- referenceTime ReferenceTime OPTIONAL,
- refLocation RefLocation OPTIONAL,
- dgpsCorrections DGPSCorrections OPTIONAL,
- navigationModel NavigationModel OPTIONAL,
- ionosphericModel IonosphericModel OPTIONAL,
- utcModel UTCModel OPTIONAL,
- almanac Almanac OPTIONAL,
- acquisAssist AcquisAssist OPTIONAL,
- realTimeIntegrity SeqOf-BadSatelliteSet OPTIONAL
-}
-
-ReferenceTime ::= SEQUENCE {
- gpsTime GPSTime,
- gsmTime GSMTime OPTIONAL,
- gpsTowAssist GPSTOWAssist OPTIONAL
-}
-
--- GPS Time includes week number and time-of-week (TOW)
-GPSTime ::= SEQUENCE {
- gpsTOW23b GPSTOW23b,
- gpsWeek GPSWeek
-}
-
--- GPSTOW, range 0-604799.92, resolution 0.08 sec, 23-bit presentation
-GPSTOW23b ::= INTEGER (0..7559999)
-
--- GPS week number
-GPSWeek ::= INTEGER (0..1023)
-
--- GPSTOWAssist consists of TLM message, Anti-spoof flag, Alert flag, and 2 reserved bits in TLM Word
--- for each visible satellite.
--- N_SAT can be read from number of elements in GPSTOWAssist
-GPSTOWAssist ::= SEQUENCE (SIZE(1..12)) OF GPSTOWAssistElement
-
-GPSTOWAssistElement ::= SEQUENCE {
- satelliteID SatelliteID,
- tlmWord TLMWord,
- antiSpoof AntiSpoofFlag,
- alert AlertFlag,
- tlmRsvdBits TLMReservedBits
-}
-
--- TLM Word, 14 bits
-TLMWord ::= INTEGER (0..16383)
-
--- Anti-Spoof flag
-AntiSpoofFlag ::= INTEGER (0..1)
-
--- Alert flag
-AlertFlag ::= INTEGER (0..1)
-
--- Reserved bits in TLM word, MSB occurs earlier in TLM Word transmitted by satellite
-TLMReservedBits ::= INTEGER (0..3)
-
-GSMTime ::= SEQUENCE {
- bcchCarrier BCCHCarrier, -- BCCH carrier
- bsic BSIC, -- BSIC
- frameNumber FrameNumber,
- timeSlot TimeSlot,
- bitNumber BitNumber
-}
-
--- Frame number
-FrameNumber ::= INTEGER (0..2097151)
-
--- Time slot number
-TimeSlot ::= INTEGER (0..7)
-
--- Bit number
-BitNumber ::= INTEGER (0..156)
-
-
--- Reference Location IE
-RefLocation ::= SEQUENCE {
- threeDLocation Ext-GeographicalInformation
-}
-
--- DGPS Corrections IE
-DGPSCorrections ::= SEQUENCE {
-
- gpsTOW INTEGER (0..604799), -- DGPS reference time
- status INTEGER (0..7),
- -- N_SAT can be read from number of elements of satList
- satList SeqOfSatElement
-}
-SeqOfSatElement ::= SEQUENCE (SIZE (1..16)) OF SatElement
-
--- number of correction for satellites
-SatElement ::= SEQUENCE {
- satelliteID SatelliteID,
-
-
---- Sequence number for ephemeris
- iode INTEGER (0..239),
- -- User Differential Range Error
- udre INTEGER (0..3),
-
- -- Pseudo Range Correction, range is
- -- -655.04 - +655.04,
- pseudoRangeCor INTEGER (-2047..2047),
-
- -- Pseudo Range Rate Correction, range is
- -- -4.064 - +4.064,
- rangeRateCor INTEGER (-127..127),
-
--- Delta Pseudo Range Correction 2
- deltaPseudoRangeCor2 INTEGER (-127..127), -- This IE shall be ignored by the receiver and
- -- set to zero by the sender
- -- Delta Pseudo Range Correction 2
- deltaRangeRateCor2 INTEGER (-7..7), -- This IE shall be ignored by the receiver and
- -- set to zero by the sender
- -- Delta Pseudo Range Correction 3
- deltaPseudoRangeCor3 INTEGER (-127..127), -- This IE shall be ignored by the receiver and
- -- set to zero by the sender
- -- Delta Pseudo Range Correction 3
- deltaRangeRateCor3 INTEGER (-7..7) -- This IE shall be ignored by the receiver and
- -- set to zero by the sender
-}
-
-SatelliteID ::= INTEGER (0..63) -- identifies satellite
-
--- Navigation Model IE
-NavigationModel ::= SEQUENCE {
- navModelList SeqOfNavModelElement
-}
-
--- navigation model satellite list
-SeqOfNavModelElement ::= SEQUENCE (SIZE(1..16)) OF NavModelElement
-
-NavModelElement ::= SEQUENCE {
- satelliteID SatelliteID,
- satStatus SatStatus -- satellite status
-}
-
--- the Status of the navigation model
-SatStatus ::= CHOICE {
- -- New satellite, new Navigation Model
- newSatelliteAndModelUC UncompressedEphemeris,
-
- -- Existing satellite, Existing Navigation Model
- oldSatelliteAndModel NULL,
-
- -- Existing satellite, new Navigation Model
- newNaviModelUC UncompressedEphemeris,
- ...
-}
-
--- Uncompressed satellite emhemeris and clock corrections
-UncompressedEphemeris ::= SEQUENCE {
- ephemCodeOnL2 INTEGER (0..3),
- ephemURA INTEGER (0..15),
- ephemSVhealth INTEGER (0..63),
- ephemIODC INTEGER (0..1023),
- ephemL2Pflag INTEGER (0..1),
- ephemSF1Rsvd EphemerisSubframe1Reserved,
- ephemTgd INTEGER (-128..127),
- ephemToc INTEGER (0..37799),
- ephemAF2 INTEGER (-128..127),
- ephemAF1 INTEGER (-32768..32767),
- ephemAF0 INTEGER (-2097152..2097151),
- ephemCrs INTEGER (-32768..32767),
- ephemDeltaN INTEGER (-32768..32767),
- ephemM0 INTEGER (-2147483648..2147483647),
- ephemCuc INTEGER (-32768..32767),
- ephemE INTEGER (0..4294967295),
- ephemCus INTEGER (-32768..32767),
- ephemAPowerHalf INTEGER (0..4294967295),
- ephemToe INTEGER (0..37799),
- ephemFitFlag INTEGER (0..1),
- ephemAODA INTEGER (0..31),
- ephemCic INTEGER (-32768..32767),
- ephemOmegaA0 INTEGER (-2147483648..2147483647),
- ephemCis INTEGER (-32768..32767),
- ephemI0 INTEGER (-2147483648..2147483647),
- ephemCrc INTEGER (-32768..32767),
- ephemW INTEGER (-2147483648..2147483647),
- ephemOmegaADot INTEGER (-8388608..8388607),
- ephemIDot INTEGER (-8192..8191)
-}
-
--- Reserved bits in subframe 1 of navigation message
-EphemerisSubframe1Reserved ::= SEQUENCE {
- reserved1 INTEGER (0..8388607), -- 23-bit field
- reserved2 INTEGER (0..16777215), -- 24-bit field
- reserved3 INTEGER (0..16777215), -- 24-bit field
- reserved4 INTEGER (0..65535) -- 16-bit field
-}
-
--- Ionospheric Model IE
-IonosphericModel ::= SEQUENCE {
- alfa0 INTEGER (-128..127),
- alfa1 INTEGER (-128..127),
- alfa2 INTEGER (-128..127),
- alfa3 INTEGER (-128..127),
- beta0 INTEGER (-128..127),
- beta1 INTEGER (-128..127),
- beta2 INTEGER (-128..127),
- beta3 INTEGER (-128..127)
-}
-
--- Universal Time Coordinate Model
-UTCModel ::= SEQUENCE {
- utcA1 INTEGER (-8388608..8388607),
- utcA0 INTEGER (-2147483648..2147483647),
- utcTot INTEGER (0..255),
- utcWNt INTEGER (0..255),
- utcDeltaTls INTEGER (-128..127),
- utcWNlsf INTEGER (0..255),
- utcDN INTEGER (-128..127),
- utcDeltaTlsf INTEGER (-128..127)
-}
-
--- Almanac, Long term model
--- NOTE: These are parameters are subset of the ephemeris
--- NOTE: But with reduced resolution and accuracy
-Almanac ::= SEQUENCE {
- alamanacWNa INTEGER (0..255), -- Once per message
-
- -- navigation model satellite list.
- -- The size of almanacList is actually Nums_Sats_Total field
- almanacList SeqOfAlmanacElement
-}
-SeqOfAlmanacElement ::= SEQUENCE (SIZE(1..64)) OF AlmanacElement
-
--- Almanac info once per satellite
-AlmanacElement ::= SEQUENCE {
- satelliteID SatelliteID,
- almanacE INTEGER (0..65535),
- alamanacToa INTEGER (0..255),
- almanacKsii INTEGER (-32768..32767),
- almanacOmegaDot INTEGER (-32768..32767),
- almanacSVhealth INTEGER (0..255),
- almanacAPowerHalf INTEGER (0..16777215),
- almanacOmega0 INTEGER (-8388608..8388607),
- almanacW INTEGER (-8388608..8388607),
- almanacM0 INTEGER (-8388608..8388607),
- almanacAF0 INTEGER (-1024..1023),
- almanacAF1 INTEGER (-1024..1023)
-}
-
--- Acquisition Assistance
-AcquisAssist ::= SEQUENCE {
-
- -- Number of Satellites can be read from acquistList
- timeRelation TimeRelation,
-
- -- Acquisition assistance list
- -- The size of Number of Satellites is actually Number of Satellites field
- acquisList SeqOfAcquisElement
-}
-SeqOfAcquisElement ::= SEQUENCE (SIZE(1..16)) OF AcquisElement
-
--- the relationship between GPS time and air-interface timing
-TimeRelation ::= SEQUENCE {
- --
- gpsTOW GPSTOW23b, -- 23b presentation
- gsmTime GSMTime OPTIONAL
-}
-
--- data occuring per number of satellites
-AcquisElement ::= SEQUENCE {
- svid SatelliteID,
-
- -- Doppler 0th order term,
- -- -5120.0 - 5117.5 Hz (= -2048 - 2047 with 2.5 Hz resolution)
- doppler0 INTEGER (-2048..2047),
- addionalDoppler AddionalDopplerFields OPTIONAL,
- codePhase INTEGER (0..1022), -- Code Phase
- intCodePhase INTEGER (0..19), -- Integer Code Phase
- gpsBitNumber INTEGER (0..3), -- GPS bit number
- codePhaseSearchWindow INTEGER (0..15), -- Code Phase Search Window
- addionalAngle AddionalAngleFields OPTIONAL
-}
-
-AddionalDopplerFields ::= SEQUENCE {
- -- Doppler 1st order term, -1.0 - +0.5 Hz/sec
- -- (= -42 + (0 to 63) with 1/42 Hz/sec. resolution)
- doppler1 INTEGER (0..63),
- dopplerUncertainty INTEGER (0..7)
- -- a sender shall not encode any DopplerUncertainty value in the range 5 to 7
- -- a receiver shall ignore any value between 5 and 7.
-}
-
-AddionalAngleFields ::= SEQUENCE {
- -- azimuth angle, 0 - 348.75 deg (= 0 - 31 with 11.25 deg resolution)
- azimuth INTEGER (0..31),
- -- elevation angle, 0 - 78.75 deg (= 0 - 7 with 11.25 deg resolution)
- elevation INTEGER (0..7)
-}
-
--- Real-Time Integrity
--- number of bad satellites can be read from this element
-SeqOf-BadSatelliteSet ::= SEQUENCE (SIZE(1..16)) OF SatelliteID
-
--- Extension Elements
-
--- Release 98 Extensions here
-Rel98-MsrPosition-Req-Extension ::= SEQUENCE {
- rel98-Ext-ExpOTD Rel98-Ext-ExpOTD OPTIONAL, -- ExpectedOTD extension
- ...,
- gpsTimeAssistanceMeasurementRequest NULL OPTIONAL,
- gpsReferenceTimeUncertainty GPSReferenceTimeUncertainty OPTIONAL
-
--- Further R98 extensions here
-}
-Rel98-AssistanceData-Extension ::= SEQUENCE {
- rel98-Ext-ExpOTD Rel98-Ext-ExpOTD OPTIONAL, -- ExpectedOTD extension
- ...,
- gpsTimeAssistanceMeasurementRequest NULL OPTIONAL,
- gpsReferenceTimeUncertainty GPSReferenceTimeUncertainty OPTIONAL
-
--- Further R98 extensions here
-}
-
--- Release 98 ExpOTD extension
-Rel98-Ext-ExpOTD ::= SEQUENCE {
--- If MsrAssistBTS is included in message, msrAssistData-R98-ExpOTD shall be included.
- msrAssistData-R98-ExpOTD MsrAssistData-R98-ExpOTD OPTIONAL,
-
--- If SystemInfoAssistaData is included in message, systemInfoAssistData-R98-ExpOTD shall be
--- included.
- systemInfoAssistData-R98-ExpOTD SystemInfoAssistData-R98-ExpOTD OPTIONAL
-}
-
--- MsrAssistData R98 extension
-MsrAssistData-R98-ExpOTD ::= SEQUENCE {
- msrAssistList-R98-ExpOTD SeqOfMsrAssistBTS-R98-ExpOTD
-}
-
--- Indexes in SeqOfMsrAssistBTS-R98-ExpOTD refer to SeqOfMsrAssistBTS
--- If the index exceeds the SegOfMsrAssistBTS range or if there is other
--- inconsistencies between the BTS indices, the MS shall apply protocol
--- error cause incorrectData
-SeqOfMsrAssistBTS-R98-ExpOTD ::= SEQUENCE (SIZE(1..15)) OF MsrAssistBTS-R98-ExpOTD
-
--- This element completes MsrAssistBTS IE
-MsrAssistBTS-R98-ExpOTD ::= SEQUENCE {
- expectedOTD ExpectedOTD,
- expOTDUncertainty ExpOTDUncertainty
-}
-
--- SystemInfoAssistData R98 extension
-SystemInfoAssistData-R98-ExpOTD ::= SEQUENCE {
- systemInfoAssistListR98-ExpOTD SeqOfSystemInfoAssistBTS-R98-ExpOTD
-}
-
--- SeqOfSystemInfoAssistBTS-R98-ExpOTD index refer to SeqOfSystemInfoAssistBTS
--- If the index exceeds the SegOfSystemInfoAssistBTS range or if there is other
--- inconsistencies between the BTS indices, the MS shall apply protocol
--- error cause incorrectData
-SeqOfSystemInfoAssistBTS-R98-ExpOTD ::= SEQUENCE (SIZE(1..32)) OF SystemInfoAssistBTS-R98-ExpOTD
-
--- whether n.th is present or not ?
-SystemInfoAssistBTS-R98-ExpOTD ::= CHOICE {
- notPresent NULL,
- present AssistBTSData-R98-ExpOTD
-}
-
--- This element completes AssistBTSData IE
-AssistBTSData-R98-ExpOTD ::= SEQUENCE {
- expectedOTD ExpectedOTD,
- expOTDuncertainty ExpOTDUncertainty -- Uncertainty of expected OTD
-}
-
--- Expected OTD value between nbor base station and reference BTS
--- at MS's current estimated location.
-ExpectedOTD ::= INTEGER (0..1250)
--- The ExpectedOTD value 1250 shall not be encoded by the transmitting entity and
--- shall be treated by the receiving entity as 0.
--- Uncertainty of Exptected OTD in bits
-ExpOTDUncertainty ::= INTEGER(0..7)
-
--- Release 98 extensions
-
-GPSReferenceTimeUncertainty ::= INTEGER (0 .. 127) -- Coding according to Annex
-
-GPSTimeAssistanceMeasurements ::= SEQUENCE {
- referenceFrameMSB INTEGER (0 .. 63), -- MSB of frame number
- gpsTowSubms INTEGER (0 .. 9999) OPTIONAL, -- in units of 100ns, for MS based AGPS
- deltaTow INTEGER (0 .. 127) OPTIONAL, -- for MS assisted AGPS
- gpsReferenceTimeUncertainty GPSReferenceTimeUncertainty OPTIONAL
-}
-
-Rel-98-MsrPosition-Rsp-Extension ::= SEQUENCE {
-
- -- First extension to Release 98
- rel-98-Ext-MeasureInfo SEQUENCE {
- otd-MeasureInfo-R98-Ext OTD-MeasureInfo-R98-Ext OPTIONAL
- },
- ...,
- timeAssistanceMeasurements GPSTimeAssistanceMeasurements OPTIONAL
- -- Further R98 extensions here
-}
-
--- This is an addition to OTD-MeasureInfo element defined in original message,
--- If OTD-MeasureInfo is absent, or if one or more OTD-MsrElementRest are present
--- OTD-MeasureInfo-R98-Ext shall be absent.
--- OTD-MeasureInfo-R98-Ext
-OTD-MeasureInfo-R98-Ext ::= SEQUENCE {
- -- Measurement info elements
- otdMsrFirstSets-R98-Ext OTD-MsrElementFirst-R98-Ext
-}
-
--- OTD measurement information Ext for the first set only
-OTD-MsrElementFirst-R98-Ext ::= SEQUENCE {
- -- additional measured neighbors in OTD measurements
- otd-FirstSetMsrs-R98-Ext SeqOfOTD-FirstSetMsrs-R98-Ext OPTIONAL
-}
-SeqOfOTD-FirstSetMsrs-R98-Ext ::= SEQUENCE (SIZE(1..5)) OF OTD-FirstSetMsrs
-
-Rel-5-MsrPosition-Rsp-Extension ::= SEQUENCE {
-
- extended-reference Extended-reference OPTIONAL,
- -- The extended-reference shall be included by the MS if and only if previously
- -- received from the SMLC in a Measure Position Request. When included, the value sent
- -- by the MS shall equal the value received from the SMLC.
-
- -- extension to Release 5, for RRLP pseudo-segmentation here
- otd-MeasureInfo-5-Ext OTD-MeasureInfo-5-Ext OPTIONAL,
- ulPseudoSegInd UlPseudoSegInd OPTIONAL, -- Included when uplink RRLP
- -- Pseudo-segmentation is used, not included when no uplink pseudo-segmentation is used
- ...
- -- Possibly more extensions for Release 5 here later
-}
-
-Extended-reference ::= SEQUENCE {
- smlc-code INTEGER (0..63),
- transaction-ID INTEGER (0..262143)
-}
-
-OTD-MeasureInfo-5-Ext ::= SeqOfOTD-MsrElementRest
- -- if more than one measurement sets are present this element is repeated
- -- NumberOfSets - 1 (-1 = first set) combined in OTD-MeasureInfo-5-Ext and
- -- OTD-MeasureInfo (e.g. if NumberOfSets is 3, then one otdMsrRestSets may
- -- be sent in OTD-MeasureInfo-5-Ext and one in OTD-MeasureInfo)
-
--- First part of Uplink RRLP Pseudo-segmentation indication, possibly more may be defined
--- in the future for segmentation with more than two segments.
-UlPseudoSegInd ::= ENUMERATED {
- firstOfMany (0),
- secondOfMany(1)
-}
-
-Rel5-MsrPosition-Req-Extension ::= SEQUENCE {
- extended-reference Extended-reference,
- ...
- -- Possibly more extensions for Release 5 here later
-}
-
-Rel5-AssistanceData-Extension ::= SEQUENCE {
- extended-reference Extended-reference,
- ...
-
--- Possibly more extensions for Release 5 here later
-}
-
-Rel-5-ProtocolError-Extension::= SEQUENCE {
- extended-reference Extended-reference OPTIONAL,
- -- The extended-reference shall be included by the MS if and only if previously
- -- received from the SMLC.
- -- When included, the value sent by the MS shall equal the value received from the SMLC.
- ...
-
- -- Possibly more extensions for Release 5 here later
-}
-
--- Release 7 Extensions here
-
-Rel7-MsrPosition-Req-Extension ::= SEQUENCE {
-velocityRequested NULL OPTIONAL,
- ganssPositionMethod GANSSPositioningMethod OPTIONAL,
- ganss-AssistData GANSS-AssistData OPTIONAL,
- ganssCarrierPhaseMeasurementRequest NULL OPTIONAL,
- ganssTODGSMTimeAssociationMeasurementRequest NULL OPTIONAL,
-requiredResponseTime RequiredResponseTime OPTIONAL,
- ...
- -- Further Release 7 extentions here
-}
-
--- additional satellite systems may be added in future versions of the protocol
-GANSSPositioningMethod ::= BIT STRING {
- gps (0),
- galileo (1)} (SIZE (2..16))
-
-GANSS-AssistData ::= SEQUENCE {
- ganss-controlHeader GANSS-ControlHeader
-}
-
-GANSS-ControlHeader ::= SEQUENCE {
- ganssCommonAssistData GANSSCommonAssistData OPTIONAL,
- ganssGenericAssistDataList SeqOfGANSSGenericAssistDataElement OPTIONAL
-}
-
--- GANSS Common Assistance Data Elements
-GANSSCommonAssistData ::= SEQUENCE {
- ganssReferenceTime GANSSReferenceTime OPTIONAL,
- ganssRefLocation GANSSRefLocation OPTIONAL,
- ganssIonosphericModel GANSSIonosphericModel OPTIONAL,
- ...
-}
-
--- List of GANSS Generic Assistance Data Elements, up to 8 GANSS
-SeqOfGANSSGenericAssistDataElement ::= SEQUENCE (SIZE (1..8)) OF GANSSGenericAssistDataElement
-
--- GANSS Generic Assistance Data Elements
-GANSSGenericAssistDataElement ::= SEQUENCE {
- ganssID INTEGER (0..7) OPTIONAL, -- Coding according to Annex
- ganssTimeModel SeqOfGANSSTimeModel OPTIONAL,
- ganssDiffCorrections GANSSDiffCorrections OPTIONAL,
- ganssNavigationModel GANSSNavModel OPTIONAL,
- ganssRealTimeIntegrity GANSSRealTimeIntegrity OPTIONAL,
- ganssDataBitAssist GANSSDataBitAssist OPTIONAL,
- ganssRefMeasurementAssist GANSSRefMeasurementAssist OPTIONAL,
- ganssAlmanacModel GANSSAlmanacModel OPTIONAL,
- ganssUTCModel GANSSUTCModel OPTIONAL,
- ...
-}
-
--- GANSS COMMON ASSISTANCE DATA ELEMENTS
-
--- GANSS Reference Time IE
-GANSSReferenceTime ::= SEQUENCE {
- ganssRefTimeInfo GANSSRefTimeInfo,
- ganssTOD-GSMTimeAssociation GANSSTOD-GSMTimeAssociation OPTIONAL
-}
-
--- GANSS Reference Time includes GANSS TOD, GANSS Day, uncertainty
-GANSSRefTimeInfo ::= SEQUENCE {
- ganssDay INTEGER(0 .. 8191) OPTIONAL,
- ganssTOD GANSSTOD,
- ganssTODUncertainty GANSSTODUncertainty OPTIONAL,
- ganssTimeID INTEGER (0 .. 7) OPTIONAL
-}
-
--- GANSS TOD integer seconds
-GANSSTOD ::= INTEGER (0 .. 86399)
-
--- GANSS TOD uncertainty
-GANSSTODUncertainty ::= INTEGER (0 .. 127) -- Coding according to Annex
-
--- GANSS TOD-GSM Time association
-GANSSTOD-GSMTimeAssociation ::= SEQUENCE {
- bcchCarrier BCCHCarrier, -- BCCH carrier
- bsic BSIC, -- BSIC
- frameNumber FrameNumber,
- timeSlot TimeSlot,
- bitNumber BitNumber,
- frameDrift FrameDrift OPTIONAL
-}
-
--- Frame drift
-FrameDrift ::= INTEGER(-64 .. 63)
-
--- GANSS Reference Location IE
-GANSSRefLocation ::= SEQUENCE {
- threeDLocation Ext-GeographicalInformation
-}
-
--- GANSS Ionospheric Model IE
--- GANSS Ionospheric Model consists of NeQuick model parameters and storm flags
-
-GANSSIonosphericModel ::= SEQUENCE {
- ganssIonoModel GANSSIonosphereModel,
- ganssIonoStormFlags GANSSIonoStormFlags OPTIONAL,
- ...
-}
-
--- GANSS ionosphere model. Coding according to Annex
-GANSSIonosphereModel ::= SEQUENCE {
- ai0 INTEGER (0 .. 4095),
- ai1 INTEGER (0 .. 4095),
- ai2 INTEGER (0 .. 4095)
-}
-
--- GANSS ionosphere storm flags
-GANSSIonoStormFlags ::= SEQUENCE {
- ionoStormFlag1 INTEGER (0 .. 1),
- ionoStormFlag2 INTEGER (0 .. 1),
- ionoStormFlag3 INTEGER (0 .. 1),
- ionoStormFlag4 INTEGER (0 .. 1),
- ionoStormFlag5 INTEGER (0 .. 1)
-}
-
--- GANSS GENERIC ASSISTANCE DATA ELEMENTS
-
--- GANSS Time Model IE consists of time offset and first and second order parameters to relate GNSS
--- specific system time to selected time reference
-SeqOfGANSSTimeModel ::= SEQUENCE (SIZE(1..7)) OF GANSSTimeModelElement
-
-GANSSTimeModelElement ::= SEQUENCE {
- ganssTimeModelRefTime INTEGER(0 .. 65535),
- tA0 TA0,
- tA1 TA1 OPTIONAL,
- tA2 TA2 OPTIONAL,
- gnssTOID INTEGER (0 .. 7),
- weekNumber INTEGER (0 .. 8191) OPTIONAL
-}
-
--- GANSS time model parameter A0
-TA0 ::= INTEGER (-2147483648 .. 2147483647)
-
--- GANSS time model parameter A1
-TA1 ::= INTEGER (-8388608 .. 8388607)
-
--- GANSS time model parameter A2
-TA2 ::= INTEGER (-64 .. 63)
-
--- DGANSS Corrections IE
-GANSSDiffCorrections ::= SEQUENCE {
- dganssRefTime INTEGER (0 .. 119), -- DGANSS reference time
-
- -- N_SGN_TYPE can be read from number of elements of sgnTypeList
- sgnTypeList SeqOfSgnTypeElement
-}
-
-SeqOfSgnTypeElement ::= SEQUENCE (SIZE (1..3)) OF SgnTypeElement -- max three signals per GNSS
-
--- DGANSS signal type element, once per GNSS signal type included in DGANSS
-SgnTypeElement ::= SEQUENCE {
- ganssSignalID GANSSSignalID OPTIONAL, -- signal type identity
- ganssStatusHealth INTEGER (0 .. 7),
- -- N_SGN can be read from number of elements of dganssSgnList
- dganssSgnList SeqOfDGANSSSgnElement
-}
-
-GANSSSignalID ::= INTEGER (0 .. 3) -- Coding according to Annex
-SeqOfDGANSSSgnElement ::= SEQUENCE (SIZE (1..16)) OF DGANSSSgnElement
-
--- number of correction for signals
-DGANSSSgnElement ::= SEQUENCE {
- svID SVID, -- Satellite identity
-
---- Sequence number for GANSS Navigation Model that matches the DGANSS correction set
- iod INTEGER (0 .. 1023),
-
- -- User Differential Range Error
- udre INTEGER (0..3),
-
- -- Pseudo Range Correction, range is
- -- -655.04 - +655.04,
- pseudoRangeCor INTEGER (-2047..2047),
-
- -- Pseudo Range Rate Correction, range is
- -- -4.064 - +4.064,
- rangeRateCor INTEGER (-127..127)
-}
-
-SVID ::= INTEGER (0 .. 63) -- Coding according to Annex
-
--- GANSS Navigation Model IE
-GANSSNavModel ::= SEQUENCE {
- nonBroadcastIndFlag INTEGER (0 .. 1),
- toeMSB INTEGER (0 .. 31) OPTIONAL, -- 5 MSB of toe and toc
- eMSB INTEGER (0 .. 127) OPTIONAL,
- sqrtAMBS INTEGER (0 .. 63) OPTIONAL,
- ganssSatelliteList SeqOfGANSSSatelliteElement
-}
-
-SeqOfGANSSSatelliteElement ::= SEQUENCE (SIZE(1..32)) OF GANSSSatelliteElement
-
-GANSSSatelliteElement ::= SEQUENCE {
- svID SVID,
- svHealth INTEGER (-7 .. 13), -- Coding according to Annex
- iod INTEGER (0 .. 1023), -- Coding according to Annex
- ganssClockModel GANSSClockModel,
- ganssOrbitModel GANSSOrbitModel,
- ...
-}
-
--- GANSS orbit model for the GNSS satellite according to the choice
-GANSSOrbitModel ::= CHOICE {
- keplerianSet NavModel-KeplerianSet,
- ...
-}
-
--- Navigation model in Keplerian parameters
-NavModel-KeplerianSet ::= SEQUENCE {
- keplerToeLSB INTEGER (0 .. 511), -- 9LSB are given in GANSSNavigationModel
- keplerW INTEGER (-2147483648..2147483647),
- keplerDeltaN INTEGER (-32768..32767),
- keplerM0 INTEGER (-2147483648..2147483647),
- keplerOmegaDot INTEGER (-8388608..8388607),
- keplerELSB INTEGER (0..33554431),
- keplerIDot INTEGER (-8192..8191),
- keplerAPowerHalfLSB INTEGER (0.. 67108863),
- keplerI0 INTEGER (-2147483648..2147483647),
- keplerOmega0 INTEGER (-2147483648..2147483647),
- keplerCrs INTEGER (-32768..32767),
- keplerCis INTEGER (-32768..32767),
- keplerCus INTEGER (-32768..32767),
- keplerCrc INTEGER (-32768..32767),
- keplerCic INTEGER (-32768..32767),
- keplerCuc INTEGER (-32768..32767)
-}
-
--- GANSS clock model for the GNSS satellite according to the choice
-GANSSClockModel ::= CHOICE {
- standardClockModelList SeqOfStandardClockModelElement,
- ...
-}
-
-SeqOfStandardClockModelElement ::= SEQUENCE (SIZE(1..2)) OF StandardClockModelElement
-
-StandardClockModelElement ::= SEQUENCE {
- stanClockTocLSB INTEGER (0 .. 511), -- 9LSB of time of clock
- stanClockAF2 INTEGER (-2048 .. 2047),
- stanClockAF1 INTEGER (-131072 .. 131071),
- stanClockAF0 INTEGER (-134217728 .. 134217727),
- stanClockTgd INTEGER (-512 .. 511) OPTIONAL,
- stanModelID INTEGER (0 .. 1) OPTIONAL,
- ...
-}
-
--- GANSS Real-Time Integrity IE
-GANSSRealTimeIntegrity ::= SEQUENCE {
- -- list of bad signals
- -- NBS can be read from number of elements in SeqOf-BadSignalSet
- ganssBadSignalList SeqOfBadSignalElement
-}
-
-SeqOfBadSignalElement ::= SEQUENCE (SIZE(1..16)) OF BadSignalElement
-
-BadSignalElement ::= SEQUENCE {
- badSVID SVID, -- Coding according to Annex
- badSignalID INTEGER (0 .. 3) OPTIONAL -- Coding according to Annex
-}
-
-
--- GANSS Data Bit Assistance IE
-GANSSDataBitAssist ::= SEQUENCE {
- ganssTOD INTEGER (0 .. 59),
- svID SVID,
- ganssDataTypeID INTEGER (0 .. 2), -- Coding according to Annex
- -- list of navigation data bits
- -- N_BIT can be read from number of elements in SeqOf-DataBits
- ganssDataBits SeqOf-GANSSDataBits
-}
-
-SeqOf-GANSSDataBits ::= SEQUENCE (SIZE(1 .. 1024)) OF GANSSDataBit
-GANSSDataBit ::= INTEGER(0 .. 1)
-
--- GANSS Reference Measurement Assistance IE
--- Code and Doppler assistance from the network.
-GANSSRefMeasurementAssist ::= SEQUENCE {
- ganssSignalID INTEGER (0 .. 3) OPTIONAL, -- Coding according to Annex
- ganssRefMeasAssitList SeqOfGANSSRefMeasurementElement
-}
-
-SeqOfGANSSRefMeasurementElement ::= SEQUENCE (SIZE(1 .. 16)) OF GANSSRefMeasurementElement
-
-GANSSRefMeasurementElement ::= SEQUENCE {
- svID SVID,
- -- Doppler 0th order term,
- -- -1024 m/s to 1023.5 m/s with 0.5 m/s resolution)
- doppler0 INTEGER (-2048 .. 2047), -- Coding according to Annex
- additionalDoppler AdditionalDopplerFields OPTIONAL,
- codePhase INTEGER (0 .. 1022), -- Code Phase in ms
- intCodePhase INTEGER (0 .. 127), -- Integer Code Phase in ms
- codePhaseSearchWindow INTEGER (0 .. 31), -- Code Phase Search Window, see Annex
- additionalAngle AddionalAngleFields OPTIONAL,
- ...
-}
-
-AdditionalDopplerFields ::= SEQUENCE {
- -- Doppler 1st order term, -0.2 - +0.1 m/s2
- doppler1 INTEGER (0..63),
- dopplerUncertainty INTEGER (0..4)
-}
-
--- GANSS Almanac Model IE
-GANSSAlmanacModel ::= SEQUENCE {
- weekNumber INTEGER (0 .. 255),
- svIDMask SVIDMASK,
- toa INTEGER (0 .. 255) OPTIONAL,
- ioda INTEGER (0 .. 3) OPTIONAL,
- ganssAlmanacList SeqOfGANSSAlmanacElement
-}
-
--- SV ID Mask, LSB for ID 1 and MSB for ID 36
-SVIDMASK ::= BIT STRING (SIZE (1..36))
-
-SeqOfGANSSAlmanacElement ::= SEQUENCE (SIZE(1 .. 36)) OF GANSSAlmanacElement
-
--- GANSS Almanac Model
-GANSSAlmanacElement ::= CHOICE {
- keplerianAlmanacSet Almanac-KeplerianSet,
- ...
-}
-
--- Almanac parameters according to Keplerian parameters
-Almanac-KeplerianSet ::= SEQUENCE {
- kepAlmanacE INTEGER (0 .. 2047),
- kepAlmanacDeltaI INTEGER (-1024 .. 1023),
- kepAlmanacOmegaDot INTEGER (-1024 .. 1023),
- kepSVHealth INTEGER (0 .. 15), -- Coding according to Annex
- kepAlmanacAPowerHalf INTEGER (-65536 .. 65535),
- kepAlmanacOmega0 INTEGER (-32768 .. 32767),
- kepAlmanacW INTEGER (-32768 .. 32767),
- kepAlmanacM0 INTEGER (-32768 .. 32767),
- kepAlmanacAF0 INTEGER (-8192 .. 8191),
- kepAlmanacAF1 INTEGER (-1024..1023)
-}
-
--- GANSS Universal Time Coordinate Model
-GANSSUTCModel ::= SEQUENCE {
- ganssUtcA1 INTEGER (-8388608..8388607),
- ganssUtcA0 INTEGER (-2147483648..2147483647),
- ganssUtcTot INTEGER (0..255),
- ganssUtcWNt INTEGER (0..255),
- ganssUtcDeltaTls INTEGER (-128..127),
- ganssUtcWNlsf INTEGER (0..255),
- ganssUtcDN INTEGER (-128..127),
- ganssUtcDeltaTlsf INTEGER (-128..127)
-}
-
---Required Measurement Request Response Time, range is 1 to 128 seconds.
-RequiredResponseTime ::= INTEGER (1..128)
-
-Rel-7-MsrPosition-Rsp-Extension ::= SEQUENCE {
-
- velEstimate VelocityEstimate OPTIONAL,
- -- Horizontal Velocity
- -- Horizontal with Vertical Velocity
- -- Horizontal Velocity with Uncertainty
- -- Horizontal with Vertical Velocity and Uncertainty
- ganssLocationInfo GANSSLocationInfo OPTIONAL,
- ganssMeasureInfo GANSSMeasureInfo OPTIONAL,
- ...
--- Further Release 7 extensions here
-}
-
--- GANSS Location Information contains location estimate, time stamp with uncertainty
--- and optionally Reference Frame field
-GANSSLocationInfo ::= SEQUENCE {
- referenceFrame ReferenceFrame OPTIONAL, -- Reference Frame Number
- ganssTODm GANSSTODm OPTIONAL, -- GNSS TOD modulo
- ganssTODFrac INTEGER (0 .. 16384) OPTIONAL, -- Coding according to Annex
- ganssTODUncertainty GANSSTODUncertainty OPTIONAL, -- Coding according to Annex
- ganssTimeID INTEGER (0 .. 3) OPTIONAL, -- Coding according to Annex
- fixType FixType,
- posData PositionData,
- stationaryIndication INTEGER(0 .. 1) OPTIONAL, -- '0' if moving or motion not known
- -- Possible shapes carried in posEstimate are
- -- ellipsoid point,
- -- ellipsoid point with uncertainty circle
- -- ellipsoid point with uncertainty ellipse
- -- ellipsoid point with altitude and uncertainty ellipsoid
- posEstimate Ext-GeographicalInformation,
- ...
-}
-
-PositionData ::= BIT STRING {
- e-otd(0),
- gps (1),
- galileo (2) } (SIZE (3..16))
-
-
--- GANSS TOD modulo 1 hour
-GANSSTODm ::= INTEGER (0 .. 3599999)
-
-ReferenceFrame ::= SEQUENCE {
- referenceFN INTEGER (0 .. 65535),
- -- Note that applicable range for referenceFN is 0 - 42431
- referenceFNMSB INTEGER (0 .. 63) OPTIONAL -- MSB of Reference Frame Number
-}
-
-
-
--- GANSS Measurement Information
-GANSSMeasureInfo ::= SEQUENCE {
- -- Measurement info elements
- -- user has to make sure that in this element is number of elements
- -- defined in reference BTS identity
- ganssMsrSetList SeqOfGANSS-MsrSetElement
-}
-SeqOfGANSS-MsrSetElement ::= SEQUENCE (SIZE(1..3)) OF GANSS-MsrSetElement
-
--- GANSS measurement information 1-3 times in a message
-GANSS-MsrSetElement ::= SEQUENCE {
- referenceFrame ReferenceFrame OPTIONAL, -- Reference Frame Number
- ganssTODm GANSSTODm OPTIONAL, -- GANSS TOD modulo
- deltaGNASSTOD INTEGER (0 .. 127) OPTIONAL,
- ganssTODUncertainty GANSSTODUncertainty OPTIONAL, -- Coding accoring to Annex
-
- --N_SGN_TYPE can be read from number of elements of SeqOfGANSS-SgnTypeElement
- ganss-SgnTypeList SeqOfGANSS-SgnTypeElement
-}
-
--- Measurements can be returned up to 6 different signal types
-SeqOfGANSS-SgnTypeElement ::= SEQUENCE (SIZE(1..6)) OF GANSS-SgnTypeElement
-
-GANSS-SgnTypeElement ::= SEQUENCE {
- ganssSignalID INTEGER (0 .. 15), -- Coding accroding to Annex
- --N_SGN can be read from number of elements of SeqOfGANSS-SgnElement
- ganss-SgnList SeqOfGANSS-SgnElement
-}
-
--- Measurements can be returned up to 16 per signal types
-SeqOfGANSS-SgnElement ::= SEQUENCE (SIZE(1..16)) OF GANSS-SgnElement
-
-
-GANSS-SgnElement ::= SEQUENCE {
- svID SVID,
- cNo INTEGER (0 .. 63),
- mpathDet MpathIndic, -- Coding according to Annex
- carrierQualityInd INTEGER (0 .. 3) OPTIONAL, -- Coding according to Annex
- codePhase INTEGER (0 .. 2097151),
- integerCodePhase INTEGER (0 .. 63) OPTIONAL,
- codePhaseRMSError INTEGER (0..63), -- Coding accoring to Annex
- doppler INTEGER (-32768 .. 32767) OPTIONAL,
- adr INTEGER (0 .. 33554431) OPTIONAL
-}
-
-Rel7-AssistanceData-Extension ::= SEQUENCE {
- ganss-AssistData GANSS-AssistData OPTIONAL,
- ganssCarrierPhaseMeasurementRequest NULL OPTIONAL,
- ganssTODGSMTimeAssociationMeasurementRequest NULL OPTIONAL,
- ...
--- Possibly more extensions for Release 7 here
-}
-
-END
diff --git a/rrlp-ephemeris/asn1/RRLP-Messages.asn b/rrlp-ephemeris/asn1/RRLP-Messages.asn
deleted file mode 100644
index 79140e2..0000000
--- a/rrlp-ephemeris/asn1/RRLP-Messages.asn
+++ /dev/null
@@ -1,38 +0,0 @@
--- RRLP-Messages.asn
--- $Id$
--- Taken from 3GPP TS 44.031 V7.4.0 (2007-03)
--- http://www.3gpp.org/ftp/Specs/archive/44_series/44.031/44031-740.zip/44031-740.doc
---
--- 3.1 General Format of RRLP Message
---
-
-RRLP-Messages
--- { RRLP-messages }
-
-DEFINITIONS AUTOMATIC TAGS ::=
-
-BEGIN
-
-IMPORTS
- MsrPosition-Req, MsrPosition-Rsp, AssistanceData,
- ProtocolError
-FROM
- RRLP-Components -- { RRLP-Components }
-;
-
-PDU ::= SEQUENCE {
- referenceNumber INTEGER (0..7),
- component RRLP-Component
-}
-
-RRLP-Component ::= CHOICE {
- msrPositionReq MsrPosition-Req,
- msrPositionRsp MsrPosition-Rsp,
- assistanceData AssistanceData,
- assistanceDataAck NULL,
- protocolError ProtocolError,
- ...
-
-}
-
-END
diff --git a/rrlp-ephemeris/asn1/patch-rrlp-components.diff b/rrlp-ephemeris/asn1/patch-rrlp-components.diff
deleted file mode 100644
index a5e55ae..0000000
--- a/rrlp-ephemeris/asn1/patch-rrlp-components.diff
+++ /dev/null
@@ -1,36 +0,0 @@
---- RRLP-Components.asn 2009-10-26 22:10:44.000000000 +0100
-+++ RRLP-Components.asn 2009-10-26 22:10:44.000000000 +0100
-@@ -18,16 +18,16 @@
- Ext-GeographicalInformation, VelocityEstimate
- FROM
- MAP-LCS-DataTypes {
-- ccitt identified-organization (4) etsi (0) mobileDomain (0)
-- gsm-Network (1) modules (3) map-LCS-DataTypes (25) version5 (5)}
-+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
-+ gsm-Network (1) modules (3) map-LCS-DataTypes (25) version11 (11)}
-
- ExtensionContainer
- FROM MAP-ExtensionDataTypes {
-- ccitt identified-organization (4) etsi (0) mobileDomain (0)
-- gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version4 (4)}
-+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
-+ gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
- ;
-
- -- Add here other ASN.1 definitions presented below
- -- in chapters 4 and 5.
-
-@@ -305,11 +305,11 @@
- SystemInfoIndex ::= INTEGER (1..32)
-
- CellIDAndLAC ::= SEQUENCE {
-- referenceLAC LAC, -- Location area code
-+ referenceLAC LACID, -- Location area code
- referenceCI CellID -- Cell identity
- }
- CellID ::= INTEGER (0..65535)
--LAC ::= INTEGER (0..65535)
-+LACID ::= INTEGER (0..65535)
-
- -- OTD-MeasureInfo
- OTD-MeasureInfo ::= SEQUENCE {
diff --git a/rrlp-ephemeris/asn1c_patches/00_add_enumerated_verbose.diff b/rrlp-ephemeris/asn1c_patches/00_add_enumerated_verbose.diff
deleted file mode 100644
index 64c22a3..0000000
--- a/rrlp-ephemeris/asn1c_patches/00_add_enumerated_verbose.diff
+++ /dev/null
@@ -1,56 +0,0 @@
-Index: skeletons/NativeEnumerated.c
-===================================================================
---- skeletons/NativeEnumerated.c (revision 1407)
-+++ skeletons/NativeEnumerated.c (working copy)
-@@ -22,7 +22,7 @@
- "ENUMERATED", /* The ASN.1 type is still ENUMERATED */
- "ENUMERATED",
- NativeInteger_free,
-- NativeInteger_print,
-+ NativeEnumerated_print,
- asn_generic_no_constraint,
- NativeInteger_decode_ber,
- NativeInteger_encode_der,
-@@ -205,3 +205,30 @@
- _ASN_ENCODED_OK(er);
- }
-
-+int
-+NativeEnumerated_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
-+ asn_app_consume_bytes_f *cb, void *app_key) {
-+ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
-+ const long *native = (const long *)sptr;
-+ char scratch[256];
-+ int ret;
-+
-+ (void)td; /* Unused argument */
-+ (void)ilevel; /* Unused argument */
-+
-+ if(native) {
-+ const asn_INTEGER_enum_map_t *map = INTEGER_map_value2enum(specs, *native);
-+ if (map && map->enum_len && map->enum_name) {
-+ ret = snprintf(scratch, sizeof(scratch),
-+ "%s", map->enum_name);
-+ } else {
-+ ret = snprintf(scratch, sizeof(scratch),
-+ (specs && specs->field_unsigned)
-+ ? "%lu" : "%ld", *native);
-+ }
-+ assert(ret > 0 && (size_t)ret < sizeof(scratch));
-+ return (cb(scratch, ret, app_key) < 0) ? -1 : 0;
-+ } else {
-+ return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
-+ }
-+}
-Index: skeletons/NativeEnumerated.h
-===================================================================
---- skeletons/NativeEnumerated.h (revision 1407)
-+++ skeletons/NativeEnumerated.h (working copy)
-@@ -24,6 +24,7 @@
- xer_type_encoder_f NativeEnumerated_encode_xer;
- per_type_decoder_f NativeEnumerated_decode_uper;
- per_type_encoder_f NativeEnumerated_encode_uper;
-+asn_struct_print_f NativeEnumerated_print;
-
- #ifdef __cplusplus
- }
diff --git a/rrlp-ephemeris/asn1c_patches/01_fix_per_encoding_dieter.diff b/rrlp-ephemeris/asn1c_patches/01_fix_per_encoding_dieter.diff
deleted file mode 100644
index a09c201..0000000
--- a/rrlp-ephemeris/asn1c_patches/01_fix_per_encoding_dieter.diff
+++ /dev/null
@@ -1,17 +0,0 @@
-Index: skeletons/per_support.c
-===================================================================
---- skeletons/per_support.c (revision 1407)
-+++ skeletons/per_support.c (working copy)
-@@ -336,7 +336,12 @@
- buf[3] = bits;
- else {
- ASN_DEBUG("->[PER out split %d]", obits);
-+#if 1 // Dieter
-+ po->nboff -= obits; // undo incrementation from a few lines above
-+ per_put_few_bits(po, bits >> (obits - 24), 24); // shift according to the rest of the bits
-+#else
- per_put_few_bits(po, bits >> 8, 24);
-+#endif
- per_put_few_bits(po, bits, obits - 24);
- ASN_DEBUG("<-[PER out split %d]", obits);
- }
diff --git a/rrlp-ephemeris/data.ubx b/rrlp-ephemeris/data.ubx
deleted file mode 100644
index 07cdddc..0000000
--- a/rrlp-ephemeris/data.ubx
+++ /dev/null
Binary files differ
diff --git a/rrlp-ephemeris/get-test-data.sh b/rrlp-ephemeris/get-test-data.sh
deleted file mode 100755
index 169f43c..0000000
--- a/rrlp-ephemeris/get-test-data.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/sh
-
-DEV=$1
-OUTF=$2
-
-# Change mode
-echo -en "\$PUBX,41,1,0001,0001,9600,0*14\r\n" > ${DEV}
-
-# Wait a little
-sleep 2
-
-# Start dump
-echo -en "\xb5\x62\x01\x02\x00\x00\x03\x0a" | \
- socat -t5 ${DEV},b9600,raw,clocal=1,echo=0 - > ${OUTF}
-echo -en "\xb5\x62\x0b\x10\x00\x00\x1b\x5c" | \
- socat -t10 ${DEV},b9600,raw,clocal=1,echo=0 - >> ${OUTF}
-
diff --git a/rrlp-ephemeris/gpl-2.0.txt b/rrlp-ephemeris/gpl-2.0.txt
deleted file mode 100644
index d511905..0000000
--- a/rrlp-ephemeris/gpl-2.0.txt
+++ /dev/null
@@ -1,339 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
diff --git a/rrlp-ephemeris/gpl-3.0.txt b/rrlp-ephemeris/gpl-3.0.txt
deleted file mode 100644
index 94a9ed0..0000000
--- a/rrlp-ephemeris/gpl-3.0.txt
+++ /dev/null
@@ -1,674 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
- If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
- <program> Copyright (C) <year> <name of author>
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<http://www.gnu.org/licenses/>.
-
- The GNU General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License. But first, please read
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/rrlp-ephemeris/gps.c b/rrlp-ephemeris/gps.c
deleted file mode 100644
index c235748..0000000
--- a/rrlp-ephemeris/gps.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * gps.c
- *
- * A few utility functions to deal with low level GPS data
- *
- *
- * Copyright (C) 2009 Sylvain Munaut <tnt@246tNt.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "gps.h"
-
-
-#define GET_FIELD_U(w, nb, pos) (((w) >> (pos)) & ((1<<(nb))-1))
-#define GET_FIELD_S(w, nb, pos) (((int)((w) << (32-(nb)-(pos)))) >> (32-(nb)))
-
-/*
- * Unpacks GPS Subframe 1,2,3 payloads (3 * 8 words)
- *
- * Note: eph->sv_id is not filled here since not present in those subframes
- *
- * (no parity bit checking is done, only the lower 24 bits of each word
- * are used)
- */
-int
-gps_unpack_sf123(uint32_t *sf, struct gps_ephemeris_sv *eph)
-{
- uint32_t *sf1 = &sf[0];
- uint32_t *sf2 = &sf[8];
- uint32_t *sf3 = &sf[16];
-
- int iode1, iode2;
-
- eph->week_no = GET_FIELD_U(sf1[0], 10, 14);
- eph->code_on_l2 = GET_FIELD_U(sf1[0], 2, 12);
- eph->sv_ura = GET_FIELD_U(sf1[0], 4, 8);
- eph->sv_health = GET_FIELD_U(sf1[0], 6, 2);
- eph->l2_p_flag = GET_FIELD_U(sf1[1], 1, 23);
- eph->t_gd = GET_FIELD_S(sf1[4], 8, 0);
- eph->iodc = (GET_FIELD_U(sf1[0], 2, 0) << 8) | \
- GET_FIELD_U(sf1[5], 8, 16);
- eph->t_oc = GET_FIELD_U(sf1[5], 16, 0);
- eph->a_f2 = GET_FIELD_S(sf1[6], 8, 16);
- eph->a_f1 = GET_FIELD_S(sf1[6], 16, 0);
- eph->a_f0 = GET_FIELD_S(sf1[7], 22, 2);
-
- iode1 = GET_FIELD_U(sf2[0], 8, 16);
- eph->c_rs = GET_FIELD_S(sf2[0], 16, 0);
- eph->delta_n = GET_FIELD_S(sf2[1], 16, 8);
- eph->m_0 = (GET_FIELD_S(sf2[1], 8, 0) << 24) | \
- GET_FIELD_U(sf2[2], 24, 0);
- eph->c_uc = GET_FIELD_S(sf2[3], 16, 8);
- eph->e = (GET_FIELD_U(sf2[3], 8, 0) << 24) | \
- GET_FIELD_U(sf2[4], 24, 0);
- eph->c_us = GET_FIELD_S(sf2[5], 16, 8);
- eph->a_powhalf = (GET_FIELD_U(sf2[5], 8, 0) << 24) | \
- GET_FIELD_U(sf2[6], 24, 0);
- eph->t_oe = GET_FIELD_U(sf2[7], 16, 8);
- eph->fit_flag = GET_FIELD_U(sf2[7], 1, 7);
-
- eph->c_ic = GET_FIELD_S(sf3[0], 16, 8);
- eph->omega_0 = (GET_FIELD_S(sf3[0], 8, 0) << 24) | \
- GET_FIELD_U(sf3[1], 24, 0);
- eph->c_is = GET_FIELD_S(sf3[2], 16, 8);
- eph->i_0 = (GET_FIELD_S(sf3[2], 8, 0) << 24) | \
- GET_FIELD_U(sf3[3], 24, 0);
- eph->c_rc = GET_FIELD_S(sf3[4], 16, 8);
- eph->w = (GET_FIELD_S(sf3[4], 8, 0) << 24) | \
- GET_FIELD_U(sf3[5], 24, 0);
- eph->omega_dot = GET_FIELD_S(sf3[6], 24, 0);
- iode2 = GET_FIELD_U(sf3[7], 8, 16);
- eph->idot = GET_FIELD_S(sf3[7], 14, 2);
-
- eph->_rsvd1 = GET_FIELD_U(sf1[1], 23, 0);
- eph->_rsvd2 = GET_FIELD_U(sf1[2], 24, 0);
- eph->_rsvd3 = GET_FIELD_U(sf1[3], 24, 0);
- eph->_rsvd4 = GET_FIELD_U(sf1[4], 16, 8);
- eph->aodo = GET_FIELD_U(sf2[7], 5, 2);
-
- /* Check & cross-validate iodc[7:0], iode1, iode2 */
- if ((iode1 != iode2) || (iode1 != (eph->iodc & 0xff)))
- return -1;
-
- return 0;
-}
-
-
-/*
- * Unpacks GPS Subframe 4 or 5 Almanac pages payload (8 words)
- *
- * (no parity bit checking is done, only the lower 24 bits of each word
- * are used)
- */
-int
-gps_unpack_sf45_almanac(uint32_t *sf, struct gps_almanac_sv *alm)
-{
- alm->sv_id = GET_FIELD_U(sf[0], 6, 16);
-
- alm->e = GET_FIELD_U(sf[0], 16, 0);
- alm->t_oa = GET_FIELD_U(sf[1], 8, 16);
- alm->ksii = GET_FIELD_S(sf[1], 16, 0);
- alm->omega_dot = GET_FIELD_S(sf[2], 16, 8);
- alm->sv_health = GET_FIELD_U(sf[2], 8, 0);
- alm->a_powhalf = GET_FIELD_U(sf[3], 24, 0);
- alm->omega_0 = GET_FIELD_S(sf[4], 24, 0);
- alm->w = GET_FIELD_S(sf[5], 24, 0);
- alm->m_0 = GET_FIELD_S(sf[6], 24, 0);
- alm->a_f0 = (GET_FIELD_S(sf[7], 8, 16) << 3) | \
- GET_FIELD_U(sf[7], 3, 2);
- alm->a_f1 = GET_FIELD_S(sf[7], 11, 5);
-
- return 0;
-}
-
diff --git a/rrlp-ephemeris/gps.h b/rrlp-ephemeris/gps.h
deleted file mode 100644
index 241b9d7..0000000
--- a/rrlp-ephemeris/gps.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * gps.h
- *
- * Header to deal with low level GPS data
- *
- *
- * Copyright (C) 2009 Sylvain Munaut <tnt@246tNt.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GPS_H__
-#define __GPS_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-
-#define MAX_SV 64
-
-
-/* Ionosperic model data */
-struct gps_ionosphere_model {
- /* #bits Scale factor Effective Units */
- /* (LSB) range */
-
- int alpha_0; /* s 8 2^-30 seconds */
- int alpha_1; /* s 8 2^-27 s / semi-circles */
- int alpha_2; /* s 8 2^-24 s / (semi-circles)^2 */
- int alpha_3; /* s 8 2^-24 s / (semi-circles)^3 */
- int beta_0; /* s 8 2^11 seconds */
- int beta_1; /* s 8 2^14 s / semi-circles */
- int beta_2; /* s 8 2^16 s / (semi-circles)^2 */
- int beta_3; /* s 8 2^16 s / (semi-circles)^3 */
-};
-
-
-/* UTC model data */
-struct gps_utc_model {
- /* #bits Scale factor Effective Units */
- /* (LSB) range */
-
- int a0; /* s 32 2^-30 seconds */
- int a1; /* s 24 2^-50 seconds / seconds */
- int delta_t_ls; /* s 8 1 seconds */
- int t_ot; /* u 8 2^12 602,112 seconds */
- int wn_t; /* u 8 1 weeks */
- int wn_lsf; /* u 8 1 weeks */
- int dn; /* u 8 1 7 days */
- int delta_t_lsf;/* s 8 1 seconds */
-};
-
-
-/* Almanach data */
-struct gps_almanac_sv {
- int sv_id;
- int sv_health;
-
- /* #bits Scale factor Effective Units */
- /* (LSB) range */
-
- int e; /* u 16 2^-21 */
- int t_oa; /* u 8 2^12 602,112 seconds */
- int ksii; /* s 16 2^-19 semi-circles */
- int omega_dot; /* s 16 2^-38 semi-circles / s */
- int a_powhalf; /* u 24 2^-11 meters */
- int omega_0; /* s 24 2^-23 semi-circles */
- int w; /* s 24 2^-23 semi-circles */
- int m_0; /* s 24 2^-23 semi-circles */
- int a_f0; /* s 11 2^-20 seconds */
- int a_f1; /* s 11 2^-38 seconds / seconds */
-};
-
-struct gps_almanac {
- int wna;
- int n_sv;
- struct gps_almanac_sv svs[MAX_SV];
-};
-
-
-/* Ephemeris data */
-struct gps_ephemeris_sv {
- int sv_id;
-
- /* #bits Scale factor Effective Units */
- /* (LSB) range */
-
- int code_on_l2; /* u 2 1 / */
- int week_no; /* u 10 1 week */
- int l2_p_flag; /* u 1 1 / */
- int sv_ura; /* u 4 / / */
- int sv_health; /* u 6 / / */
- int t_gd; /* s 8 2^-31 seconds */
- int iodc; /* u 10 / / */
- int t_oc; /* u 16 2^4 604,784 seconds */
- int a_f2; /* s 8 2^-55 sec / sec^2 */
- int a_f1; /* s 16 2^-43 sec / sec */
- int a_f0; /* s 22 2^-31 seconds */
-
- int c_rs; /* s 16 2^-5 meters */
- int delta_n; /* s 16 2^-43 semi-circles / s */
- int m_0; /* s 32 2^-31 semi-circles */
- int c_uc; /* s 16 2^-29 radians */
- unsigned int e; /* u 32 2^-33 0.03 / */
- int c_us; /* s 16 2^-29 radians */
- unsigned int a_powhalf; /* u 32 2^-19 meters^(1/2) */
- int t_oe; /* u 16 2^4 604,784 seconds */
- int fit_flag; /* u 1 / / */
-
- int c_ic; /* s 16 2^-29 radians */
- int omega_0; /* s 32 2^-31 semi-circles */
- int c_is; /* s 16 2^-29 radians */
- int i_0; /* s 32 2^-31 semi-circles */
- int c_rc; /* s 16 2^-5 meters */
- int w; /* s 32 2^-31 semi-circles */
- int omega_dot; /* s 24 2^-43 semi-circles / s */
- int idot; /* s 14 2^-43 semi-circles / s */
-
- int _rsvd1; /* 23 bits */
- int _rsvd2; /* 24 bits */
- int _rsvd3; /* 24 bits */
- int _rsvd4; /* 16 bits */
- int aodo; /* 8 bits Not sure it needs to be here ... */
-};
-
-struct gps_ephemeris {
- int n_sv;
- struct gps_ephemeris_sv svs[MAX_SV];
-};
-
-
-/* Reference position */
-struct gps_ref_pos { /* WSG84 ellipsoid */
- double latitude; /* deg */
- double longitude; /* deg */
- double altitude; /* m above ellipsoid */
-};
-
-
-/* Reference time */
-struct gps_ref_time {
- int wn; /* GPS week number */
- double tow; /* in seconds */
-};
-
-
-/* All assist data */
-#define GPS_FIELD_IONOSPHERE (1<<0)
-#define GPS_FIELD_UTC (1<<1)
-#define GPS_FIELD_ALMANAC (1<<2)
-#define GPS_FIELD_EPHEMERIS (1<<3)
-#define GPS_FIELD_REFPOS (1<<4)
-#define GPS_FIELD_REFTIME (1<<5)
-
-struct gps_assist_data {
- int fields;
- struct gps_ionosphere_model ionosphere;
- struct gps_utc_model utc;
- struct gps_almanac almanac;
- struct gps_ephemeris ephemeris;
- struct gps_ref_pos ref_pos;
- struct gps_ref_time ref_time;
-};
-
-
-/* GPS Subframe utility methods (see gps.c for details) */
-int gps_unpack_sf123(uint32_t *sf, struct gps_ephemeris_sv *eph);
-int gps_unpack_sf45_almanac(uint32_t *sf, struct gps_almanac_sv *alm);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __GPS_H__ */
-
diff --git a/rrlp-ephemeris/main.c b/rrlp-ephemeris/main.c
deleted file mode 100644
index bb025a2..0000000
--- a/rrlp-ephemeris/main.c
+++ /dev/null
@@ -1,99 +0,0 @@
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "gps.h"
-#include "ubx.h"
-#include "ubx-parse.h"
-#include "rrlp.h"
-
-static int
-do_ubx_read(struct gps_assist_data *gps, const char *filename)
-{
- int rv, fd, i;
- struct stat st;
- void *buf;
-
- /* Load file */
- fd = open(filename, O_RDONLY);
- if (fd < 0)
- return -1;
-
- rv = fstat(fd, &st);
- if (rv < 0) {
- close(fd);
- return -1;
- }
-
- buf = malloc(st.st_size);
- if (!buf) {
- close(fd);
- return -1;
- }
-
- rv = read(fd, buf, st.st_size);
- if (rv != st.st_size) {
- free(buf);
- close(fd);
- return -1;
- }
-
- /* Parse each message */
- for (i=0; i<st.st_size;) {
- int rv;
- rv = ubx_msg_dispatch(ubx_parse_dt, buf + i, st.st_size - i, gps);
- if (rv < 0)
- i++; /* Invalid message: try one byte later */
- else
- i += rv;
- }
-
- /* Done */
- free(buf);
- close(fd);
-
- return 0;
-}
-
-static int
-do_rrlp(struct gps_assist_data *gps)
-{
- struct rrlp_assist_req ar;
- void *pdus[64];
- int len[64];
- int i, rv;
-
- char *test = "\x28\x00\x80\x10\x01\x32\x00\x19\x4F\x07\x15\x04";
-
- rrlp_decode_assistance_request(&ar, test, 12);
- printf("%08x %016llx\n", ar.req_elems, (long long unsigned) ar.eph_svs);
-
- ar.req_elems = -1;
- ar.eph_svs = -1LL;
- rv = rrlp_gps_assist_pdus(gps, &ar, pdus, len, 64);
- printf("%d\n", rv);
- for (i=0; i<rv; i++) {
- printf("%p %d\n", pdus[i], len[i]);
- }
- return 0;
-}
-
-int main(int argc, char *argv[])
-{
- struct gps_assist_data gps;
- int rv;
-
- memset(&gps, 0x00, sizeof(gps));
-
- rv = do_ubx_read(&gps, "data.ubx");
-
- rv = do_rrlp(&gps);
-
- return 0;
-}
-
diff --git a/rrlp-ephemeris/rrlp.c b/rrlp-ephemeris/rrlp.c
deleted file mode 100644
index e60c3ab..0000000
--- a/rrlp-ephemeris/rrlp.c
+++ /dev/null
@@ -1,648 +0,0 @@
-/*
- * rrlp.c
- *
- * RRLP implementation
- *
- *
- * Copyright (C) 2009 Sylvain Munaut <tnt@246tNt.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include <errno.h>
-#include <math.h>
-
-#include "gps.h"
-#include "rrlp.h"
-
-#include <PDU.h>
-#include <GPS-AssistData.h>
-#include <NavigationModel.h>
-#include <IonosphericModel.h>
-#include <UTCModel.h>
-#include <Almanac.h>
-#include <RefLocation.h>
-#include <ReferenceTime.h>
-
-
-/* ------------------------------------------------------------------------ */
-/* RRLP Assistance request decoding */
-/* ---------------------------------------------------------------------{{{ */
-/* Decode and validate the assistance data request messages.
- * See section 10.10 of
- * . ETSI TS 149 031 V8.1.0 (2009-01)
- * . 3GPP TS 49.031 version 8.1.0 Release 8
- */
-
-/* Packed structure from 49.031 spec (RGA = Request GPS Assistance) */
-
-#define RRLP_RGA0_ALMANAC (1<<0)
-#define RRLP_RGA0_UTC_MODEL (1<<1)
-#define RRLP_RGA0_IONO_MODEL (1<<2)
-#define RRLP_RGA0_NAV_MODEL (1<<3)
-#define RRLP_RGA0_DGPS (1<<4)
-#define RRLP_RGA0_REF_LOC (1<<5)
-#define RRLP_RGA0_REF_TIME (1<<6)
-#define RRLP_RGA0_ACQ_ASSIST (1<<7)
-
-#define RRLP_RGA1_REALTIME_INT (1<<0)
-#define RRLP_RGA1_EPH_EXT (1<<1)
-#define RRLP_RGA1_EPH_EXT_CHECK (1<<2)
-
-struct rrlp_rga_hdr {
- uint8_t items0;
- uint8_t items1;
-} __attribute__((packed));
-
-struct rrlp_rga_eph_sv {
- uint8_t sv_id; /* [7:6] reserved, [5:0] sv_id */
- uint8_t iode; /* latest eph in the MS memory in hours */
-} __attribute__((packed));
-
-struct rrlp_rga_eph {
- uint8_t wn_hi; /* [7:6] = wn[9:8] */
- uint8_t wn_lo; /* wn[7:0] */
- uint8_t toe; /* latest eph in the MS memory in hours */
- uint8_t nsat_tmtoe; /* [7:4] nstat, [3:0] T-Toe limit */
- struct rrlp_rga_eph_sv svs[0];
-} __attribute__((packed));
-
-struct rrlp_rga_eph_ext {
- uint8_t validity; /* in 4 hours units */
-} __attribute__((packed));
-
-struct rrlp_rga_eph_ext_check {
- /* weeks are in gps week modulo 4 */
- uint8_t wn_begin_end; /* [7:4] begin, [3:0] end */
- uint8_t tow_begin;
- uint8_t tow_end;
-} __attribute__((packed));
-
-
-/* Parsing function */
-
-int
-rrlp_decode_assistance_request(
- struct rrlp_assist_req *ar,
- void *req, int req_len)
-{
- struct rrlp_rga_hdr *hdr = NULL;
- struct rrlp_rga_eph *eph = NULL;
- struct rrlp_rga_eph_ext *eph_ext = NULL;
- struct rrlp_rga_eph_ext_check *eph_ext_check = NULL;
- int p = 0;
-
- /* Reset */
- ar->req_elems = 0;
- ar->eph_svs = 0;
-
- /* Parse message */
- hdr = req;
- p += sizeof(struct rrlp_rga_hdr);
- if (p > req_len)
- return -1;
-
- if (hdr->items0 & RRLP_RGA0_NAV_MODEL) {
- eph = req + p;
- p += sizeof(struct rrlp_rga_eph);
- if (p > req_len)
- return -1;
- p += (eph->nsat_tmtoe >> 4) * sizeof(struct rrlp_rga_eph_sv);
- if (p > req_len)
- return -1;
- }
-
- if (hdr->items1 & RRLP_RGA1_EPH_EXT) {
- eph_ext = req + p;
- p += sizeof(struct rrlp_rga_eph_ext);
- if (p > req_len)
- return -1;
- }
-
- if (hdr->items1 & RRLP_RGA1_EPH_EXT_CHECK) {
- eph_ext_check = req + p;
- p += sizeof(struct rrlp_rga_eph_ext_check);
- if (p > req_len)
- return -1;
- }
-
- if (p != req_len)
- return -2; /* not all bytes consumed ??? */
-
- /* Print a warning for unsupported requests */
- if ((eph_ext != NULL) ||
- (eph_ext_check != NULL) ||
- (hdr->items0 & (RRLP_RGA0_DGPS | RRLP_RGA0_ACQ_ASSIST)) ||
- (hdr->items1 & RRLP_RGA1_REALTIME_INT)) {
- fprintf(stderr, "[w] Unsupported assistance data requested, ignored ...\n");
- }
-
- /* Copy the request */
- if (hdr->items0 & RRLP_RGA0_ALMANAC)
- ar->req_elems |= RRLP_AR_ALMANAC;
-
- if (hdr->items0 & RRLP_RGA0_UTC_MODEL)
- ar->req_elems |= RRLP_AR_UTC_MODEL;
-
- if (hdr->items0 & RRLP_RGA0_IONO_MODEL)
- ar->req_elems |= RRLP_AR_IONO_MODEL;
-
- if (hdr->items0 & RRLP_RGA0_REF_LOC)
- ar->req_elems |= RRLP_AR_REF_LOC;
-
- if (hdr->items0 & RRLP_RGA0_REF_TIME)
- ar->req_elems |= RRLP_AR_REF_TIME;
-
- if (hdr->items0 & RRLP_RGA0_NAV_MODEL) {
- int i, n_svs = eph->nsat_tmtoe >> 4;
- ar->req_elems |= RRLP_AR_EPHEMERIS;
- for (i=0; i<n_svs; i++)
- ar->eph_svs |= (1ULL << (eph->svs[i].sv_id - 1));
- }
-
- return 0;
-}
-
-/* }}} */
-
-
-/* ------------------------------------------------------------------------ */
-/* RRLP elements fill */
-/* ---------------------------------------------------------------------{{{ */
-
- /* Helpers */
-
-static void
-_ts_23_032_store_latitude(double lat, uint8_t *b)
-{
- uint32_t x;
- x = (uint32_t) floor(fabs(lat/90.0) * ((double)(1<<23)));
- if (x >= (1<<23))
- x = (1<<23) - 1;
- if (lat < 0.0)
- x |= (1<<23);
- b[0] = (x >> 16) & 0xff;
- b[1] = (x >> 8) & 0xff;
- b[2] = x & 0xff;
-}
-
-static void
-_ts_23_032_store_longitude(double lon, uint8_t *b)
-{
- int32_t x;
- x = floor((lon/360.0) * ((double)(1<<24)));
- if (x >= (1<<23))
- x = 0x007fffff;
- else if (x < -(1<<23))
- x = 0x00800000;
- b[0] = (x >> 16) & 0xff;
- b[1] = (x >> 8) & 0xff;
- b[2] = x & 0xff;
-}
-
-static void
-_ts_23_032_store_altitude(double alt, uint8_t *b)
-{
- int alt_i = (int)fabs(alt);
- b[0] = ((alt_i >> 8) & 0x7f) | (alt<0.0 ? 0x80 : 0x00);
- b[1] = alt_i & 0xff;
-}
-
-
- /* Fill methods */
-
-static void
-_rrlp_fill_navigation_model_element(
- struct NavModelElement *rrlp_nme,
- struct gps_ephemeris_sv *gps_eph_sv)
-{
- struct UncompressedEphemeris *rrlp_eph;
-
- rrlp_nme->satStatus.present = SatStatus_PR_newSatelliteAndModelUC;
- rrlp_nme->satelliteID = gps_eph_sv->sv_id;
-
- rrlp_eph = &rrlp_nme->satStatus.choice.newSatelliteAndModelUC;
-
- rrlp_eph->ephemCodeOnL2 = gps_eph_sv->code_on_l2;
- rrlp_eph->ephemURA = gps_eph_sv->sv_ura;
- rrlp_eph->ephemSVhealth = gps_eph_sv->sv_health;
- rrlp_eph->ephemIODC = gps_eph_sv->iodc;
- rrlp_eph->ephemL2Pflag = gps_eph_sv->l2_p_flag;
- rrlp_eph->ephemTgd = gps_eph_sv->t_gd;
- rrlp_eph->ephemToc = gps_eph_sv->t_oc;
- rrlp_eph->ephemAF2 = gps_eph_sv->a_f2;
- rrlp_eph->ephemAF1 = gps_eph_sv->a_f1;
- rrlp_eph->ephemAF0 = gps_eph_sv->a_f0;
- rrlp_eph->ephemCrs = gps_eph_sv->c_rs;
- rrlp_eph->ephemDeltaN = gps_eph_sv->delta_n;
- rrlp_eph->ephemM0 = gps_eph_sv->m_0;
- rrlp_eph->ephemCuc = gps_eph_sv->c_uc;
- rrlp_eph->ephemE = gps_eph_sv->e;
- rrlp_eph->ephemCus = gps_eph_sv->c_us;
- rrlp_eph->ephemAPowerHalf = gps_eph_sv->a_powhalf;
- rrlp_eph->ephemToe = gps_eph_sv->t_oe;
- rrlp_eph->ephemFitFlag = gps_eph_sv->fit_flag;
- rrlp_eph->ephemAODA = gps_eph_sv->aodo;
- rrlp_eph->ephemCic = gps_eph_sv->c_ic;
- rrlp_eph->ephemOmegaA0 = gps_eph_sv->omega_0;
- rrlp_eph->ephemCis = gps_eph_sv->c_is;
- rrlp_eph->ephemI0 = gps_eph_sv->i_0;
- rrlp_eph->ephemCrc = gps_eph_sv->c_rc;
- rrlp_eph->ephemW = gps_eph_sv->w;
- rrlp_eph->ephemOmegaADot = gps_eph_sv->omega_dot;
- rrlp_eph->ephemIDot = gps_eph_sv->idot;
-
- rrlp_eph->ephemSF1Rsvd.reserved1 = gps_eph_sv->_rsvd1;
- rrlp_eph->ephemSF1Rsvd.reserved2 = gps_eph_sv->_rsvd2;
- rrlp_eph->ephemSF1Rsvd.reserved3 = gps_eph_sv->_rsvd3;
- rrlp_eph->ephemSF1Rsvd.reserved4 = gps_eph_sv->_rsvd4;
-}
-
-static void
-_rrlp_fill_almanac_element(
- struct AlmanacElement *rrlp_ae,
- struct gps_almanac_sv *gps_alm_sv)
-{
- rrlp_ae->satelliteID = gps_alm_sv->sv_id;
-
- rrlp_ae->almanacE = gps_alm_sv->e;
- rrlp_ae->alamanacToa = gps_alm_sv->t_oa;
- rrlp_ae->almanacKsii = gps_alm_sv->ksii;
- rrlp_ae->almanacOmegaDot = gps_alm_sv->omega_dot;
- rrlp_ae->almanacSVhealth = gps_alm_sv->sv_health;
- rrlp_ae->almanacAPowerHalf = gps_alm_sv->a_powhalf;
- rrlp_ae->almanacOmega0 = gps_alm_sv->omega_0;
- rrlp_ae->almanacW = gps_alm_sv->w;
- rrlp_ae->almanacM0 = gps_alm_sv->m_0;
- rrlp_ae->almanacAF0 = gps_alm_sv->a_f0;
- rrlp_ae->almanacAF1 = gps_alm_sv->a_f1;
-
-}
-
-static void
-_rrlp_fill_ionospheric_model(
- struct IonosphericModel *rrlp_iono,
- struct gps_ionosphere_model *gps_iono)
-{
- rrlp_iono->alfa0 = gps_iono->alpha_0;
- rrlp_iono->alfa1 = gps_iono->alpha_1;
- rrlp_iono->alfa2 = gps_iono->alpha_2;
- rrlp_iono->alfa3 = gps_iono->alpha_3;
- rrlp_iono->beta0 = gps_iono->beta_0;
- rrlp_iono->beta1 = gps_iono->beta_1;
- rrlp_iono->beta2 = gps_iono->beta_2;
- rrlp_iono->beta3 = gps_iono->beta_3;
-}
-
-static void
-_rrlp_fill_utc_model(
- struct UTCModel *rrlp_utc,
- struct gps_utc_model *gps_utc)
-{
- rrlp_utc->utcA1 = gps_utc->a1;
- rrlp_utc->utcA0 = gps_utc->a0;
- rrlp_utc->utcTot = gps_utc->t_ot;
- rrlp_utc->utcWNt = gps_utc->wn_t & 0xff;
- rrlp_utc->utcDeltaTls = gps_utc->delta_t_ls;
- rrlp_utc->utcWNlsf = gps_utc->wn_lsf & 0xff;
- rrlp_utc->utcDN = gps_utc->dn;
- rrlp_utc->utcDeltaTlsf = gps_utc->delta_t_lsf;
-}
-
-/* }}} */
-
-
-/* ------------------------------------------------------------------------ */
-/* RRLP Assistance PDU Generation */
-/* ---------------------------------------------------------------------{{{ */
-
-struct PDU *
-_rrlp_create_gps_assist_pdu(int refnum, struct GPS_AssistData **o_gps_ad)
-{
- struct PDU *pdu;
- struct GPS_AssistData *gps_ad;
-
- pdu = calloc(1, sizeof(*pdu));
- if (!pdu)
- return NULL;
-
- gps_ad = calloc(1, sizeof(*gps_ad));
- if (!gps_ad) {
- free(pdu);
- return NULL;
- }
-
- if (o_gps_ad)
- *o_gps_ad = gps_ad;
-
- pdu->referenceNumber = refnum;
- pdu->component.present = RRLP_Component_PR_assistanceData;
- pdu->component.choice.assistanceData.gps_AssistData = gps_ad;
-
- return pdu;
-}
-
-static int
-_rrlp_add_ionospheric_model(
- struct GPS_AssistData *rrlp_gps_ad,
- struct gps_assist_data *gps_ad)
-{
- struct IonosphericModel *rrlp_iono;
-
- if (!(gps_ad->fields & GPS_FIELD_IONOSPHERE))
- return -EINVAL;
-
- rrlp_iono = calloc(1, sizeof(*rrlp_iono));
- if (!rrlp_iono)
- return -ENOMEM;
- rrlp_gps_ad->controlHeader.ionosphericModel = rrlp_iono;
-
- _rrlp_fill_ionospheric_model(rrlp_iono, &gps_ad->ionosphere);
-
- return 0;
-}
-
-static int
-_rrlp_add_utc_model(
- struct GPS_AssistData *rrlp_gps_ad,
- struct gps_assist_data *gps_ad)
-{
- struct UTCModel *rrlp_utc;
-
- if (!(gps_ad->fields & GPS_FIELD_UTC))
- return -EINVAL;
-
- rrlp_utc = calloc(1, sizeof(*rrlp_utc));
- if (!rrlp_utc)
- return -ENOMEM;
- rrlp_gps_ad->controlHeader.utcModel = rrlp_utc;
-
- _rrlp_fill_utc_model(rrlp_utc, &gps_ad->utc);
-
- return 0;
-}
-
-static int
-_rrlp_add_reference_location(
- struct GPS_AssistData *rrlp_gps_ad,
- struct gps_assist_data *gps_ad)
-{
- struct RefLocation *rrlp_refloc;
- uint8_t *b;
-
- if (!(gps_ad->fields & GPS_FIELD_REFPOS))
- return -EINVAL;
-
- rrlp_refloc = calloc(1, sizeof(*rrlp_refloc));
- if (!rrlp_refloc)
- return -ENOMEM;
- rrlp_gps_ad->controlHeader.refLocation = rrlp_refloc;
-
- b = malloc(9);
-
- b[0] = 0x80; /* Ellipsoid Point with altitude */
- _ts_23_032_store_latitude(gps_ad->ref_pos.latitude, &b[1]);
- _ts_23_032_store_longitude(gps_ad->ref_pos.longitude, &b[4]);
- _ts_23_032_store_altitude(gps_ad->ref_pos.altitude, &b[7]);
-
- rrlp_refloc->threeDLocation.buf = b;
- rrlp_refloc->threeDLocation.size = 9;
-
- return 0;
-}
-
-static int
-_rrlp_add_reference_time(
- struct GPS_AssistData *rrlp_gps_ad,
- struct gps_assist_data *gps_ad)
-{
- struct ReferenceTime *rrlp_reftime;
-
- if (!(gps_ad->fields & GPS_FIELD_REFTIME))
- return -EINVAL;
-
- rrlp_reftime = calloc(1, sizeof(*rrlp_reftime));
- if (!rrlp_reftime)
- return -ENOMEM;
- rrlp_gps_ad->controlHeader.referenceTime = rrlp_reftime;
-
- rrlp_reftime->gpsTime.gpsWeek = gps_ad->ref_time.wn & 0x3ff; /* 10b */
- rrlp_reftime->gpsTime.gpsTOW23b =
- ((int)floor(gps_ad->ref_time.tow / 0.08)) & 0x7fffff; /* 23b */
-
- return 0;
-}
-
-static int
-_rrlp_add_almanac(
- struct GPS_AssistData *rrlp_gps_ad,
- struct gps_assist_data *gps_ad, int *start, int count)
-{
- int i;
- struct Almanac *rrlp_alm;
- struct gps_almanac *gps_alm = &gps_ad->almanac;
-
- if (!(gps_ad->fields & GPS_FIELD_ALMANAC))
- return -EINVAL;
-
- rrlp_alm = calloc(1, sizeof(*rrlp_alm));
- if (!rrlp_alm)
- return -ENOMEM;
- rrlp_gps_ad->controlHeader.almanac = rrlp_alm;
-
- rrlp_alm->alamanacWNa = gps_alm->wna;
- if (count == -1)
- count = gps_alm->n_sv - *start;
- for (i=*start; (i<*start+count) && (i<gps_alm->n_sv); i++) {
- struct AlmanacElement *ae;
- ae = calloc(1, sizeof(*ae));
- if (!ae)
- return -ENOMEM;
- _rrlp_fill_almanac_element(ae, &gps_alm->svs[i]);
- ASN_SEQUENCE_ADD(&rrlp_alm->almanacList.list, ae);
- }
-
- *start = i;
-
- return i < gps_alm->n_sv;
-}
-
-static int
-_rrlp_add_ephemeris(
- struct GPS_AssistData *rrlp_gps_ad,
- struct gps_assist_data *gps_ad, int *start, int count, uint64_t mask)
-{
- int i, j;
- struct NavigationModel *rrlp_nav;
- struct gps_ephemeris *gps_eph = &gps_ad->ephemeris;
-
- if (!(gps_ad->fields & GPS_FIELD_EPHEMERIS))
- return -EINVAL;
-
- rrlp_nav = calloc(1, sizeof(*rrlp_nav));
- if (!rrlp_nav)
- return -ENOMEM;
- rrlp_gps_ad->controlHeader.navigationModel = rrlp_nav;
-
- if (count == -1)
- count = gps_eph->n_sv - *start;
- for (i=*start,j=0; (j<count) && (i<gps_eph->n_sv); i++) {
- if (!(mask & (1ULL<<(gps_eph->svs[i].sv_id-1))))
- continue;
- struct NavModelElement *nme;
- nme = calloc(1, sizeof(*nme));
- if (!nme)
- return -ENOMEM;
- _rrlp_fill_navigation_model_element(nme, &gps_eph->svs[i]);
- ASN_SEQUENCE_ADD(&rrlp_nav->navModelList.list, nme);
- j++;
- }
-
- *start = i;
-
- return i < gps_eph->n_sv;
-}
-
-
-#define MAX_PDUS 64
-
-int
-rrlp_gps_assist_pdus(
- struct gps_assist_data *gps_ad, struct rrlp_assist_req *req,
- void **o_pdu, int *o_len, int o_max_pdus)
-{
- struct PDU *lst_pdu[MAX_PDUS];
- int lst_cnt = 0;
-
- struct PDU *rrlp_pdu = NULL;
- struct GPS_AssistData *rrlp_gps_ad = NULL;
- uint32_t re = req->req_elems;
- int i, rv = 0;
-
- /* IonosphericModel, UTCModel, RefLocation, ReferenceTime */
- if (re & (RRLP_AR_IONO_MODEL |
- RRLP_AR_UTC_MODEL |
- RRLP_AR_REF_TIME |
- RRLP_AR_REF_LOC))
- {
- int pdu_has_data = 0;
-
- rrlp_pdu = _rrlp_create_gps_assist_pdu(1, &rrlp_gps_ad);
- if (!rrlp_pdu) {
- rv = -ENOMEM;
- goto error;
- }
-
- if (re & RRLP_AR_IONO_MODEL)
- if (!_rrlp_add_ionospheric_model(rrlp_gps_ad, gps_ad))
- pdu_has_data = 1;
-
- if (re & RRLP_AR_UTC_MODEL)
- if (!_rrlp_add_utc_model(rrlp_gps_ad, gps_ad))
- pdu_has_data = 1;
-
- if (re & RRLP_AR_REF_TIME)
- if (!_rrlp_add_reference_time(rrlp_gps_ad, gps_ad))
- pdu_has_data = 1;
-
- if (re & RRLP_AR_REF_LOC)
- if (!_rrlp_add_reference_location(rrlp_gps_ad, gps_ad))
- pdu_has_data = 1;
-
- if (pdu_has_data) {
- lst_pdu[lst_cnt++] = rrlp_pdu;
- rrlp_pdu = NULL;
- }
- }
-
- /* Almanac */
- if (re & RRLP_AR_ALMANAC) {
- i = 0;
- do {
- if (!(gps_ad->fields & GPS_FIELD_ALMANAC))
- break;
-
- if (!rrlp_pdu) {
- rrlp_pdu = _rrlp_create_gps_assist_pdu(1, &rrlp_gps_ad);
- if (!rrlp_pdu) {
- rv = -ENOMEM;
- goto error;
- }
- }
-
- rv = _rrlp_add_almanac(rrlp_gps_ad, gps_ad, &i, 10);
- if (rv < 0)
- goto error;
-
- lst_pdu[lst_cnt++] = rrlp_pdu;
- rrlp_pdu = NULL;
- } while (rv);
- }
-
- /* Ephemeris */
- if (re & RRLP_AR_EPHEMERIS) {
- i = 0;
- do {
- if (!(gps_ad->fields & GPS_FIELD_EPHEMERIS))
- break;
-
- if (!rrlp_pdu) {
- rrlp_pdu = _rrlp_create_gps_assist_pdu(1, &rrlp_gps_ad);
- if (!rrlp_pdu) {
- rv = -ENOMEM;
- goto error;
- }
- }
-
- rv = _rrlp_add_ephemeris(rrlp_gps_ad, gps_ad, &i, 2, req->eph_svs);
-
- lst_pdu[lst_cnt++] = rrlp_pdu;
- rrlp_pdu = NULL;
-
- } while (rv);
- }
-
- /* Serialize & Release all PDUs */
- for (i=0; i<lst_cnt && i<o_max_pdus; i++) {
- /* Pseudo segmentation flags */
- MoreAssDataToBeSent_t *mad = calloc(1, sizeof(*mad));
- *mad = (i == (lst_cnt-1)) ?
- MoreAssDataToBeSent_noMoreMessages :
- MoreAssDataToBeSent_moreMessagesOnTheWay;
- lst_pdu[i]->component.choice.assistanceData.moreAssDataToBeSent = mad;
-
- /* Serialization */
- // asn_fprint(stdout, &asn_DEF_PDU, lst_pdu[i]);
- rv = uper_encode_to_new_buffer(&asn_DEF_PDU, NULL, lst_pdu[i], &o_pdu[i]);
- if (rv < 0)
- goto error;
- o_len[i] = rv;
- }
-
- rv = lst_cnt;
-
- /* Release ASN.1 objects */
-error:
- if (rrlp_pdu)
- asn_DEF_PDU.free_struct(&asn_DEF_PDU, (void*)rrlp_pdu, 0);
-
- for (i=0; i<lst_cnt; i++)
- asn_DEF_PDU.free_struct(&asn_DEF_PDU, lst_pdu[i], 0);
-
- return rv;
-}
-
-/* }}} */
-
diff --git a/rrlp-ephemeris/rrlp.h b/rrlp-ephemeris/rrlp.h
deleted file mode 100644
index a5e4344..0000000
--- a/rrlp-ephemeris/rrlp.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * rrlp.h
- *
- * RRLP Header
- *
- *
- * Copyright (C) 2009 Sylvain Munaut <tnt@246tNt.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __RRLP_H__
-#define __RRLP_H__
-
-#include <stdint.h>
-
-#include "gps.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* Our internal simplified structure for requests */
-
-#define RRLP_AR_REF_LOC (1<<0)
-#define RRLP_AR_REF_TIME (1<<1)
-#define RRLP_AR_UTC_MODEL (1<<2)
-#define RRLP_AR_IONO_MODEL (1<<3)
-#define RRLP_AR_ALMANAC (1<<4)
-#define RRLP_AR_EPHEMERIS (1<<5)
-
-struct rrlp_assist_req {
- uint32_t req_elems;
- uint64_t eph_svs;
-};
-
-
-/* Methods */
-int rrlp_decode_assistance_request(struct rrlp_assist_req *ar,
- void *req, int req_len);
-
-int rrlp_gps_assist_pdus(
- struct gps_assist_data *gps_ad, struct rrlp_assist_req *req,
- void **o_pdu, int *o_len, int o_max_pdus);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __RRLP_H__ */
-
diff --git a/rrlp-ephemeris/ubx-parse.c b/rrlp-ephemeris/ubx-parse.c
deleted file mode 100644
index c3d0f70..0000000
--- a/rrlp-ephemeris/ubx-parse.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * ubx-parse.c
- *
- * Implementation of parsing code converting UBX messages to GPS assist
- * data
- *
- *
- * Copyright (C) 2009 Sylvain Munaut <tnt@246tNt.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-
-#include "gps.h"
-#include "ubx.h"
-#include "ubx-parse.h"
-
-
-/* Helpers */
-
-static int
-float_to_fixedpoint(float f, int sf)
-{
- if (sf < 0) {
- while (sf++ < 0)
- f *= 2.0f;
- } else {
- while (sf-- > 0)
- f *= 0.5f;
- }
-
- return (int)f;
-}
-
-static inline int
-double_to_fixedpoint(double d, int sf)
-{
- if (sf < 0) {
- while (sf++ < 0)
- d *= 2.0;
- } else {
- while (sf-- > 0)
- d *= 0.5;
- }
-
- return (int)d;
-}
-
-
-/* UBX message parsing to fill gps assist data */
-
-static void
-_ubx_msg_parse_nav_posllh(struct ubx_hdr *hdr, void *pl, int pl_len, void *ud)
-{
- struct ubx_nav_posllh *nav_posllh = pl;
- struct gps_assist_data *gps = ud;
-
- //printf("[.] NAV_POSLLH\n");
-
- gps->fields |= GPS_FIELD_REFPOS;
-
- gps->ref_pos.latitude = (double)(nav_posllh->lat) * 1e-7;
- gps->ref_pos.longitude = (double)(nav_posllh->lon) * 1e-7;
- gps->ref_pos.altitude = (double)(nav_posllh->height) * 1e-3;
-}
-
-static void
-_ubx_msg_parse_aid_ini(struct ubx_hdr *hdr, void *pl, int pl_len, void *ud)
-{
- struct ubx_aid_ini *aid_ini = pl;
- struct gps_assist_data *gps = ud;
-
- //printf("[.] AID_INI\n");
-
- /* Extract info for "Reference Time" */
- gps->fields |= GPS_FIELD_REFTIME;
-
- gps->ref_time.wn = aid_ini->wn;
- gps->ref_time.tow = (double)aid_ini->tow * 1e-3;
-
- // FIXME: We could extract ref position as well but we need it in
- // WGS84 geodetic coordinates and it's provided as ecef, so
- // we need a lot of math ...
-}
-
-static void
-_ubx_msg_parse_aid_hui(struct ubx_hdr *hdr, void *pl, int pl_len, void *ud)
-{
- struct ubx_aid_hui *aid_hui = pl;
- struct gps_assist_data *gps = ud;
-
- //printf("[.] AID_HUI\n");
-
- if (aid_hui->flags & 0x2) { /* UTC parameters valid */
- struct gps_utc_model *utc = &gps->utc;
-
- gps->fields |= GPS_FIELD_UTC;
-
- utc->a0 = double_to_fixedpoint(aid_hui->utc_a0, -30);
- utc->a1 = double_to_fixedpoint(aid_hui->utc_a1, -50);
- utc->delta_t_ls = aid_hui->utc_ls;
- utc->t_ot = aid_hui->utc_tot >> 12;
- utc->wn_t = aid_hui->utc_wnt;
- utc->wn_lsf = aid_hui->utc_wnf;
- utc->dn = aid_hui->utc_dn;
- utc->delta_t_lsf = aid_hui->utc_lsf;
- }
-
- if (aid_hui->flags & 0x04) { /* Klobuchar parameters valid */
- struct gps_ionosphere_model *iono = &gps->ionosphere;
-
- gps->fields |= GPS_FIELD_IONOSPHERE;
-
- iono->alpha_0 = float_to_fixedpoint(aid_hui->klob_a0, -30);
- iono->alpha_1 = float_to_fixedpoint(aid_hui->klob_a1, -27);
- iono->alpha_2 = float_to_fixedpoint(aid_hui->klob_a2, -24);
- iono->alpha_3 = float_to_fixedpoint(aid_hui->klob_a3, -24);
- iono->beta_0 = float_to_fixedpoint(aid_hui->klob_b0, 11);
- iono->beta_1 = float_to_fixedpoint(aid_hui->klob_b1, 14);
- iono->beta_2 = float_to_fixedpoint(aid_hui->klob_b2, 16);
- iono->beta_3 = float_to_fixedpoint(aid_hui->klob_b3, 16);
- }
-}
-
-static void
-_ubx_msg_parse_aid_alm(struct ubx_hdr *hdr, void *pl, int pl_len, void *ud)
-{
- struct ubx_aid_alm *aid_alm = pl;
- struct gps_assist_data *gps = ud;
-
- //printf("[.] AID_ALM %d - %d\n", aid_alm->sv_id, aid_alm->gps_week);
-
- if (aid_alm->gps_week) {
- gps->fields |= GPS_FIELD_ALMANAC;
- gps->almanac.wna = aid_alm->gps_week & 0xff;
- gps_unpack_sf45_almanac(aid_alm->alm_words, &gps->almanac.svs[gps->almanac.n_sv++]);
- }
-}
-
-static void
-_ubx_msg_parse_aid_eph(struct ubx_hdr *hdr, void *pl, int pl_len, void *ud)
-{
- struct ubx_aid_eph *aid_eph = pl;
- struct gps_assist_data *gps = ud;
-
- //printf("[.] AID_EPH %d - %s\n", aid_eph->sv_id, aid_eph->present ? "present" : "not present");
-
- if (aid_eph->present) {
- int i = gps->ephemeris.n_sv++;
- gps->fields |= GPS_FIELD_EPHEMERIS;
- gps->ephemeris.svs[i].sv_id = aid_eph->sv_id;
- gps_unpack_sf123(aid_eph->eph_words, &gps->ephemeris.svs[i]);
- }
-}
-
-
-/* Dispatch table */
-struct ubx_dispatch_entry ubx_parse_dt[] = {
- UBX_DISPATCH(NAV, POSLLH, _ubx_msg_parse_nav_posllh),
- UBX_DISPATCH(AID, INI, _ubx_msg_parse_aid_ini),
- UBX_DISPATCH(AID, HUI, _ubx_msg_parse_aid_hui),
- UBX_DISPATCH(AID, ALM, _ubx_msg_parse_aid_alm),
- UBX_DISPATCH(AID, EPH, _ubx_msg_parse_aid_eph),
-};
-
diff --git a/rrlp-ephemeris/ubx-parse.h b/rrlp-ephemeris/ubx-parse.h
deleted file mode 100644
index 621475d..0000000
--- a/rrlp-ephemeris/ubx-parse.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * ubx-parse.h
- *
- * Header for parsing code converting UBX messages to GPS assist data
- *
- *
- * Copyright (C) 2009 Sylvain Munaut <tnt@246tNt.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __UBX_PARSE_H__
-#define __UBX_PARSE_H__
-
-
-#include "gps.h"
-#include "ubx.h"
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* Dispatch table */
-extern struct ubx_dispatch_entry ubx_parse_dt[];
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __UBX_PARSE_H__ */
-
diff --git a/rrlp-ephemeris/ubx.c b/rrlp-ephemeris/ubx.c
deleted file mode 100644
index 83dd1f0..0000000
--- a/rrlp-ephemeris/ubx.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * ubx.c
- *
- * Implementation of generic UBX helpers
- *
- *
- * Copyright (C) 2009 Sylvain Munaut <tnt@246tNt.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-
-#include "ubx.h"
-
-
-static void
-ubx_checksum(uint8_t *data, int len, uint8_t *cksum)
-{
- int i;
- uint8_t ck0 = 0, ck1 = 0;
- for (i=0; i<len; i++) {
- ck0 += data[i];
- ck1 += ck0;
- }
- cksum[0] = ck0;
- cksum[1] = ck1;
-}
-
-
-static ubx_msg_handler_t
-ubx_find_handler(struct ubx_dispatch_entry *dt, uint8_t msg_class, uint8_t msg_id)
-{
- while (dt->handler) {
- if ((dt->msg_class == msg_class) && (dt->msg_id == msg_id))
- return dt->handler;
- dt++;
- }
- return NULL;
-}
-
-
-int
-ubx_msg_dispatch(struct ubx_dispatch_entry *dt,
- void *msg, int len, void *userdata)
-{
- struct ubx_hdr *hdr = msg;
- uint8_t cksum[2], *cksum_ptr;
- ubx_msg_handler_t h;
-
- if ((hdr->sync[0] != UBX_SYNC0) || (hdr->sync[1] != UBX_SYNC1)) {
- fprintf(stderr, "[!] Invalid sync bytes\n");
- return -1;
- }
-
- ubx_checksum(msg + 2, sizeof(struct ubx_hdr) + hdr->payload_len - 2, cksum);
- cksum_ptr = msg + (sizeof(struct ubx_hdr) + hdr->payload_len);
- if ((cksum_ptr[0] != cksum[0]) || (cksum_ptr[1] != cksum[1])) {
- fprintf(stderr, "[!] Invalid checksum\n");
- return -1;
- }
-
- h = ubx_find_handler(dt, hdr->msg_class, hdr->msg_id);
- if (h)
- h(hdr, msg + sizeof(struct ubx_hdr), hdr->payload_len, userdata);
-
- return sizeof(struct ubx_hdr) + hdr->payload_len + 2;
-}
-
diff --git a/rrlp-ephemeris/ubx.h b/rrlp-ephemeris/ubx.h
deleted file mode 100644
index 8264386..0000000
--- a/rrlp-ephemeris/ubx.h
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * ubx.h
- *
- * Header for UBX related stuff
- *
- *
- * Copyright (C) 2009 Sylvain Munaut <tnt@246tNt.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __UBX_H__
-#define __UBX_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-/* Constants used in UBX */
-
- /* Sync bytes (two first bytes of each message) */
-#define UBX_SYNC0 0xb5
-#define UBX_SYNC1 0x62
-
- /* UBX messages classes */
-#define UBX_CLASS_NAV 0x01
-#define UBX_CLASS_RXM 0x02
-#define UBX_CLASS_INF 0x04
-#define UBX_CLASS_ACK 0x05
-#define UBX_CLASS_CFG 0x06
-#define UBX_CLASS_UPD 0x09
-#define UBX_CLASS_MON 0x0a
-#define UBX_CLASS_AID 0x0b
-#define UBX_CLASS_TIM 0x0d
-
- /* UBX messages type ID (by class) */
-#define UBX_NAV_POSECEF 0x01
-#define UBX_NAV_POSLLH 0x02
-#define UBX_NAV_STATUS 0x03
-#define UBX_NAV_DOP 0x04
-#define UBX_NAV_SOL 0x06
-#define UBX_NAV_POSUTM 0x08
-#define UBX_NAV_VELECEF 0x11
-#define UBX_NAV_VELNED 0x12
-#define UBX_NAV_TIMEGPS 0x20
-#define UBX_NAV_TIMEUTC 0x21
-#define UBX_NAV_CLOCK 0x22
-#define UBX_NAV_SVINFO 0x30
-#define UBX_NAV_DGPS 0x31
-#define UBX_NAV_SBAS 0x32
-#define UBX_NAV_EKFSTATUS 0x40
-
-#define UBX_RXM_RAW 0x10
-#define UBX_RXM_SFRB 0x11
-#define UBX_RXM_SVSI 0x20
-#define UBX_RXM_SVSI_GPS 0x20
-#define UBX_RXM_ALM 0x30
-#define UBX_RXM_EPH 0x31
-#define UBX_RXM_POSREQ 0x40
-
-#define UBX_INF_ERROR 0x00
-#define UBX_INF_WARNING 0x01
-#define UBX_INF_NOTICE 0x02
-#define UBX_INF_TEST 0x03
-#define UBX_INF_DEBUG 0x04
-#define UBX_INF_USER 0x07
-
-#define UBX_ACK_NAK 0x00
-#define UBX_ACK_ACK 0x01
-
-#define UBX_CFG_PRT 0x00
-#define UBX_CFG_USB 0x1b
-#define UBX_CFG_MSG 0x01
-#define UBX_CFG_NMEA 0x17
-#define UBX_CFG_RATE 0x08
-#define UBX_CFG_CFG 0x09
-#define UBX_CFG_TP 0x07
-#define UBX_CFG_NAV2 0x1a
-#define UBX_CFG_DAT 0x06
-#define UBX_CFG_INF 0x02
-#define UBX_CFG_RST 0x04
-#define UBX_CFG_RXM 0x11
-#define UBX_CFG_ANT 0x13
-#define UBX_CFG_FXN 0x0e
-#define UBX_CFG_SBAS 0x16
-#define UBX_CFG_LIC 0x80
-#define UBX_CFG_TM 0x10
-#define UBX_CFG_TM2 0x19
-#define UBX_CFG_TMODE 0x1d
-#define UBX_CFG_EKF 0x12
-
-#define UBX_UPD_DOWNL 0x01
-#define UBX_UPD_UPLOAD 0x02
-#define UBX_UPD_EXEC 0x03
-#define UBX_UPD_MEMCPY 0x04
-
-#define UBX_MON_SCHD 0x01
-#define UBX_MON_IO 0x02
-#define UBX_MON_IPC 0x03
-#define UBX_MON_VER 0x04
-#define UBX_MON_EXCEPT 0x05
-#define UBX_MON_MSGPP 0x06
-#define UBX_MON_RXBUF 0x07
-#define UBX_MON_TXBUF 0x08
-#define UBX_MON_HW 0x09
-#define UBX_MON_USB 0x0a
-
-#define UBX_AID_REQ 0x00
-#define UBX_AID_INI 0x01
-#define UBX_AID_HUI 0x02
-#define UBX_AID_DATA 0x10
-#define UBX_AID_ALM 0x30
-#define UBX_AID_EPH 0x31
-
-#define UBX_TIM_TP 0x01
-#define UBX_TIM_TM 0x02
-#define UBX_TIM_TM2 0x03
-#define UBX_TIM_SVIN 0x04
-
-
-/* Header */
-struct ubx_hdr {
- uint8_t sync[2];
- uint8_t msg_class;
- uint8_t msg_id;
- uint16_t payload_len;
-} __attribute__((packed));
-
-
-/* Payload formats (some of them) */
-struct ubx_nav_posllh {
- uint32_t itow;
- int32_t lon; /* scaling 1e-7 */
- int32_t lat; /* scaling 1e-7 */
- int32_t height;/* mm */
- int32_t hsl; /* mm */
- uint32_t hacc; /* mm */
- uint32_t vacc; /* mm */
-} __attribute__((packed));
-
-struct ubx_aid_ini {
- int32_t x;
- int32_t y;
- int32_t z;
- uint32_t posacc;
- uint16_t tm_cfg;
- uint16_t wn;
- uint32_t tow;
- int32_t tow_ns;
- uint32_t tacc_ms;
- uint32_t tacc_ns;
- int32_t clkd;
- uint32_t clkdacc;
- uint32_t flags;
-} __attribute__((packed));
-
-struct ubx_aid_hui {
- uint32_t health;
- double utc_a1;
- double utc_a0;
- int32_t utc_tot;
- int16_t utc_wnt;
- int16_t utc_ls;
- int16_t utc_wnf;
- int16_t utc_dn;
- int16_t utc_lsf;
- int16_t utc_spare;
- float klob_a0;
- float klob_a1;
- float klob_a2;
- float klob_a3;
- float klob_b0;
- float klob_b1;
- float klob_b2;
- float klob_b3;
- uint32_t flags;
-} __attribute__((packed));
-
-struct ubx_aid_alm {
- uint32_t sv_id;
- uint32_t gps_week;
- uint32_t alm_words[8]; /* Present only if 'gps_week' != 0 */
-} __attribute__((packed));
-
-struct ubx_aid_eph {
- uint32_t sv_id;
- uint32_t present;
- uint32_t eph_words[24]; /* Present only if 'present' != 0 */
-} __attribute__((packed));
-
-
-/* Message handler */
-typedef void (*ubx_msg_handler_t)(
- struct ubx_hdr *hdr, void *payload, int payload_len, void *userdata);
-
-struct ubx_dispatch_entry {
- uint8_t msg_class;
- uint8_t msg_id;
- ubx_msg_handler_t handler;
-};
-
-#define UBX_DISPATCH(kls,id,hdl) { \
- .msg_class = UBX_CLASS_ ## kls , \
- .msg_id = UBX_ ## kls ## _ ## id, \
- .handler = (hdl), \
-}
-
-
-/* Methods */
-int ubx_msg_dispatch(struct ubx_dispatch_entry *dt,
- void *msg, int len, void *userdata);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __UBX_H__ */
-
diff --git a/wireshark/abis_oml.patch b/wireshark/abis_oml.patch
index 4013211..b9248dc 100644
--- a/wireshark/abis_oml.patch
+++ b/wireshark/abis_oml.patch
@@ -1,21 +1,21 @@
-From 5857518be87641fdab45e593bc9fd5ef5595e619 Mon Sep 17 00:00:00 2001
+From b659280ff645354bb55529b05114419b9f0efd6f Mon Sep 17 00:00:00 2001
From: Holger Hans Peter Freyther <zecke@selfish.org>
Date: Mon, 19 Apr 2010 13:23:51 +0800
Subject: [PATCH 1/2] Add the Abis OML patch.
---
epan/dissectors/Makefile.common | 1 +
- epan/dissectors/packet-gsm_abis_oml.c | 1382 +++++++++++++++++++++++++++++++++
- epan/dissectors/packet-gsm_abis_oml.h | 787 +++++++++++++++++++
- 3 files changed, 2170 insertions(+), 0 deletions(-)
+ epan/dissectors/packet-gsm_abis_oml.c | 1405 +++++++++++++++++++++++++++++++++
+ epan/dissectors/packet-gsm_abis_oml.h | 800 +++++++++++++++++++
+ 3 files changed, 2206 insertions(+), 0 deletions(-)
create mode 100644 epan/dissectors/packet-gsm_abis_oml.c
create mode 100644 epan/dissectors/packet-gsm_abis_oml.h
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common
-index dbc3726..98dcdc3 100644
+index b18f42e..115fa09 100644
--- a/epan/dissectors/Makefile.common
+++ b/epan/dissectors/Makefile.common
-@@ -481,6 +481,7 @@ DISSECTOR_SRC = \
+@@ -485,6 +485,7 @@ DISSECTOR_SRC = \
packet-gsm_a_gm.c \
packet-gsm_a_rp.c \
packet-gsm_a_rr.c \
@@ -25,10 +25,10 @@
packet-gsm_bssmap_le.c \
diff --git a/epan/dissectors/packet-gsm_abis_oml.c b/epan/dissectors/packet-gsm_abis_oml.c
new file mode 100644
-index 0000000..fa46ab5
+index 0000000..0f16f18
--- /dev/null
+++ b/epan/dissectors/packet-gsm_abis_oml.c
-@@ -0,0 +1,1382 @@
+@@ -0,0 +1,1405 @@
+/* packet-abis_oml.c
+ * Routines for packet dissection of GSM A-bis over IP (3GPP TS 12.21)
+ * Copyright 2009 by Harald Welte <laforge@gnumonks.org>
@@ -70,6 +70,8 @@
+#include "packet-gsm_abis_oml.h"
+#include "packet-gsm_a_common.h"
+
++#include <stdio.h>
++
+/* initialize the protocol and registered fields */
+static int proto_abis_oml = -1;
+
@@ -145,7 +147,7 @@
+static int ett_oml_fom_att = -1;
+
+/* Decode things as nanoBTS traces */
-+static gboolean global_oml_use_nano_bts = FALSE;
++static gboolean global_oml_use_nano_bts = TRUE;
+
+static proto_tree *top_tree;
+
@@ -611,6 +613,22 @@
+ { NM_IPACC_TR_IE_FREQ_ERR, "Frequency Error" },
+};
+
++static const struct tlv_def *
++find_tlv_tag(guint8 tag)
++{
++ const struct tlv_def *specific;
++
++ if (global_oml_use_nano_bts)
++ specific = &nm_att_tlvdef_ipa.def[tag];
++ else
++ specific = &nm_att_tlvdev_bs11.def[tag];
++
++ if (specific->type != TLV_TYPE_UNKNOWN)
++ return specific;
++
++ return &nm_att_tlvdef_base.def[tag];
++}
++
+/* Parse the ip.access specific BCCH Information IE embedded into the Test
+ * Report IE */
+static gint
@@ -695,7 +713,9 @@
+ipacc_tr_ie_chan_usage(tvbuff_t *tvb, proto_tree *att_tree, int offset)
+{
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
-+ guint16 result = tvb_get_ntohs(tvb, offset);
++ guint16 result;
++
++ result = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(att_tree, hf_attr_ipa_tr_arfcn,
+ tvb, offset, 2, result);
+ proto_tree_add_uint(att_tree, hf_attr_ipa_tr_rxlev,
@@ -715,11 +735,13 @@
+ 1, FALSE);
+
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
-+ guint8 ie = tvb_get_guint8(tvb, offset);
-+ guint16 len = tvb_get_ntohs(tvb, offset+1);
++ guint8 ie;
++ guint16 len;
+ proto_item *ti;
+ proto_tree *att_tree;
+
++ ie = tvb_get_guint8(tvb, offset);
++ len = tvb_get_ntohs(tvb, offset+1);
+ ti = proto_tree_add_item(tree, hf_oml_ipa_tres_attr_tag, tvb,
+ offset++, 1, FALSE);
+ att_tree = proto_item_add_subtree(ti, ett_oml_fom_att);
@@ -762,7 +784,7 @@
+ tvbuff_t *sub_tvb;
+
+ tag = tvb_get_guint8(tvb, offset);
-+ tdef = &nm_att_tlvdef.def[tag];
++ tdef = find_tlv_tag(tag);
+
+ switch (tdef->type) {
+ case TLV_TYPE_FIXED:
@@ -791,6 +813,7 @@
+ len = tvb_get_guint8(tvb, offset+1) << 8 |
+ tvb_get_guint8(tvb, offset+2);
+ break;
++ case TLV_TYPE_UNKNOWN: /* fall through */
+ default:
+ hlen = len_len = len = 0;
+ DISSECTOR_ASSERT_NOT_REACHED();
@@ -1413,10 +1436,10 @@
+}
diff --git a/epan/dissectors/packet-gsm_abis_oml.h b/epan/dissectors/packet-gsm_abis_oml.h
new file mode 100644
-index 0000000..d523e96
+index 0000000..bdc414d
--- /dev/null
+++ b/epan/dissectors/packet-gsm_abis_oml.h
-@@ -0,0 +1,787 @@
+@@ -0,0 +1,800 @@
+/* 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 */
+
@@ -2027,6 +2050,7 @@
+
+/* From openbsc/include/openbsc/tlv.h */
+enum tlv_type {
++ TLV_TYPE_UNKNOWN,
+ TLV_TYPE_FIXED,
+ TLV_TYPE_T,
+ TLV_TYPE_TV,
@@ -2075,7 +2099,7 @@
+};
+
+/* From openbsc/src/abis_nm.c */
-+static const struct tlv_definition nm_att_tlvdef = {
++static const struct tlv_definition nm_att_tlvdef_base = {
+ .def = {
+ [NM_ATT_ABIS_CHANNEL] = { TLV_TYPE_FIXED, 3 },
+ [NM_ATT_ADD_INFO] = { TLV_TYPE_TL16V, 0 },
@@ -2098,7 +2122,6 @@
+ [NM_ATT_GSM_TIME] = { TLV_TYPE_FIXED, 2 },
+ [NM_ATT_HSN] = { TLV_TYPE_TV, 0 },
+ [NM_ATT_HW_CONFIG] = { TLV_TYPE_TL16V, 0 },
-+ //BS11 [NM_ATT_HW_DESC] = { TLV_TYPE_TL16V, 0 },
+ [NM_ATT_HW_DESC] = { TLV_TYPE_TLV, 0 },
+ [NM_ATT_INTAVE_PARAM] = { TLV_TYPE_TV, 0 },
+ [NM_ATT_INTERF_BOUND] = { TLV_TYPE_FIXED, 6 },
@@ -2142,8 +2165,15 @@
+ [NM_ATT_OUTST_ALARM] = { TLV_TYPE_TV, 0 },
+ [NM_ATT_FILE_DATA] = { TLV_TYPE_TL16V, 0 },
+ [NM_ATT_MEAS_RES] = { TLV_TYPE_TL16V, 0 },
-+#if 0
-+ /* BS11 specifics */
++
++ },
++};
++
++/* BS11 specifics */
++static const struct tlv_definition nm_att_tlvdev_bs11 = {
++ .def = {
++ /* a difference.. */
++ [NM_ATT_HW_DESC] = { TLV_TYPE_TL16V, 0 },
+ [NM_ATT_BS11_ESN_FW_CODE_NO] = { TLV_TYPE_TLV, 0 },
+ [NM_ATT_BS11_ESN_HW_CODE_NO] = { TLV_TYPE_TLV, 0 },
+ [NM_ATT_BS11_ESN_PCB_SERIAL] = { TLV_TYPE_TLV, 0 },
@@ -2168,8 +2198,12 @@
+ [NM_ATT_BS11_CCLK_ACCURACY] = { TLV_TYPE_TV, 0 },
+ [NM_ATT_BS11_CCLK_TYPE] = { TLV_TYPE_TV, 0 },
+ [0x95] = { TLV_TYPE_FIXED, 2 },
-+#endif
-+ /* ip.access specifics */
++ },
++};
++
++/* ip.access specifics */
++static const struct tlv_definition nm_att_tlvdef_ipa = {
++ .def = {
+ [NM_ATT_IPACC_DST_IP] = { TLV_TYPE_FIXED, 4 },
+ [NM_ATT_IPACC_DST_IP_PORT] = { TLV_TYPE_FIXED, 2 },
+ [NM_ATT_IPACC_PRIM_OML_CFG] = { TLV_TYPE_TL16V, 0 },
@@ -2199,7 +2233,9 @@
+ [NM_ATT_IPACC_CODING_SCHEMES] = { TLV_TYPE_TL16V, 0 },
+ [NM_ATT_IPACC_RLC_CFG_2] = { TLV_TYPE_TL16V, 0 },
+ [NM_ATT_IPACC_RLC_CFG_3] = { TLV_TYPE_TL16V, 0 },
++ [NM_ATT_IPACC_PAGING_CFG] = { TLV_TYPE_FIXED, 2 },
+ [NM_ATT_IPACC_FILE_DATA] = { TLV_TYPE_TL16V, 0 },
++ [NM_ATT_IPACC_CGI] = { TLV_TYPE_TL16V, 0 },
+ },
+};
+