mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-cbc.git
				synced 2025-11-03 21:53:37 +00:00 
			
		
		
		
	Compare commits
	
		
			79 Commits
		
	
	
		
			pespin/fix
			...
			master
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					91ea92868a | ||
| 
						 | 
					1b402db278 | ||
| 
						 | 
					c5afbd3336 | ||
| 
						 | 
					da85d1f75a | ||
| 
						 | 
					2c34f95a04 | ||
| 
						 | 
					1a454c9174 | ||
| 
						 | 
					f25277e872 | ||
| 
						 | 
					28d66aa8ec | ||
| 
						 | 
					80184a4e41 | ||
| 
						 | 
					cc02c15505 | ||
| 
						 | 
					f4fa15cb0e | ||
| 
						 | 
					16daffdc52 | ||
| 
						 | 
					3bb05bafce | ||
| 
						 | 
					637874eaf9 | ||
| 
						 | 
					f6a2a6ba4f | ||
| 
						 | 
					bd50b41eeb | ||
| 
						 | 
					f18c9d6f9c | ||
| 
						 | 
					9fad2713c3 | ||
| 
						 | 
					b3743e9603 | ||
| 
						 | 
					538bc4c699 | ||
| 
						 | 
					da8b98cf88 | ||
| 
						 | 
					36a7759e39 | ||
| 
						 | 
					7ae4b6d61f | ||
| 
						 | 
					311673c365 | ||
| 
						 | 
					7fbd6aa472 | ||
| 
						 | 
					66221e60d6 | ||
| 
						 | 
					0422a10253 | ||
| 
						 | 
					292b2e895b | ||
| 
						 | 
					a7aca0333b | ||
| 
						 | 
					d04fe38e73 | ||
| 
						 | 
					eb82cbc249 | ||
| 
						 | 
					43439c785f | ||
| 
						 | 
					1d9d13ce6b | ||
| 
						 | 
					6e64d1079f | ||
| 
						 | 
					d5ea7f765e | ||
| 
						 | 
					8d70759ab7 | ||
| 
						 | 
					8f15c2c23d | ||
| 
						 | 
					d5c0b73f00 | ||
| 
						 | 
					65d3c505b7 | ||
| 
						 | 
					13152304f7 | ||
| 
						 | 
					40a6158e41 | ||
| 
						 | 
					d78f13c89a | ||
| 
						 | 
					28d3a53dc5 | ||
| 
						 | 
					caba7fc493 | ||
| 
						 | 
					cb4e11f984 | ||
| 
						 | 
					a76d15048d | ||
| 
						 | 
					20705a0877 | ||
| 
						 | 
					041ae3246d | ||
| 
						 | 
					e86af042fd | ||
| 
						 | 
					0b8a08b698 | ||
| 
						 | 
					d24c3dfba0 | ||
| 
						 | 
					c190939f0c | ||
| 
						 | 
					cb99991127 | ||
| 
						 | 
					e6e878a2fc | ||
| 
						 | 
					d8a537aca8 | ||
| 
						 | 
					4a9d22e5a0 | ||
| 
						 | 
					1429377005 | ||
| 
						 | 
					bc21b3ae81 | ||
| 
						 | 
					ab8b8402a4 | ||
| 
						 | 
					e416069cf6 | ||
| 
						 | 
					e67faef4ec | ||
| 
						 | 
					745a2d6600 | ||
| 
						 | 
					b093e6708d | ||
| 
						 | 
					66625de21c | ||
| 
						 | 
					6db8c13fea | ||
| 
						 | 
					3f9d78e2a3 | ||
| 
						 | 
					692243baf5 | ||
| 
						 | 
					9ce5d4bad7 | ||
| 
						 | 
					7beca6fda0 | ||
| 
						 | 
					4dd20eec56 | ||
| 
						 | 
					9144fd1fd8 | ||
| 
						 | 
					3c804efcc6 | ||
| 
						 | 
					5ae411980b | ||
| 
						 | 
					93a588ba60 | ||
| 
						 | 
					56d1ef3b52 | ||
| 
						 | 
					3ef5020007 | ||
| 
						 | 
					5044524f01 | ||
| 
						 | 
					3468e90ab3 | ||
| 
						 | 
					028b48b967 | 
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -2,6 +2,7 @@
 | 
			
		||||
*.a
 | 
			
		||||
*.lo
 | 
			
		||||
*.la
 | 
			
		||||
*~
 | 
			
		||||
.deps
 | 
			
		||||
Makefile
 | 
			
		||||
Makefile.in
 | 
			
		||||
@@ -20,7 +21,6 @@ depcomp
 | 
			
		||||
install-sh
 | 
			
		||||
missing
 | 
			
		||||
stamp-h1
 | 
			
		||||
configure~
 | 
			
		||||
 | 
			
		||||
# libtool
 | 
			
		||||
ltmain.sh
 | 
			
		||||
@@ -62,3 +62,4 @@ doc/manuals/vty/cbc_vty_reference.xml
 | 
			
		||||
 | 
			
		||||
contrib/osmo-cbc.spec
 | 
			
		||||
libosmo-sbcap.pc
 | 
			
		||||
include/osmocom/sbcap/version.h
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ pkgconfig_DATA = \
 | 
			
		||||
EXTRA_DIST = .version \
 | 
			
		||||
	README.md \
 | 
			
		||||
	git-version-gen \
 | 
			
		||||
	contrib/osmo-cbc.spec.in \
 | 
			
		||||
	debian \
 | 
			
		||||
	cbc.schema.json \
 | 
			
		||||
	smscb.schema.json \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										29
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								README.md
									
									
									
									
									
								
							@@ -60,10 +60,37 @@ Contributing
 | 
			
		||||
Our coding standards are described at
 | 
			
		||||
https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards
 | 
			
		||||
 | 
			
		||||
We us a gerrit based patch submission/review process for managing
 | 
			
		||||
We use a Gerrit based patch submission/review process for managing
 | 
			
		||||
contributions.  Please see
 | 
			
		||||
https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit for
 | 
			
		||||
more details
 | 
			
		||||
 | 
			
		||||
The current patch queue for osmo-cbc can be seen at
 | 
			
		||||
https://gerrit.osmocom.org/#/q/project:osmo-cbc+status:open
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Generating asn1c code
 | 
			
		||||
---------------------
 | 
			
		||||
 | 
			
		||||
Upstream master as1nc from [vlm](https://github.com/vlm/asn1c) [doesn't support
 | 
			
		||||
APER encoding](https://github.com/vlm/asn1c/issues/452). Nevertheless, the
 | 
			
		||||
upstream fork maintained by a big contributor
 | 
			
		||||
[mouse07410](https://github.com/mouse07410/asn1c) does support it, and it is
 | 
			
		||||
used in osmo-cbc to generate the SBc-AP code from ASN.1 files present in
 | 
			
		||||
src/sbcap/asn1/.
 | 
			
		||||
 | 
			
		||||
In order to regenerate the code, one shall adjust the ASN1C_SKELETON_PATH and
 | 
			
		||||
ASN1C_BIN_PATH in configure.ac to point to the built & installed asn1c from
 | 
			
		||||
mouse07410 (usually `vlm_master` branch). Last generated code was built using
 | 
			
		||||
commit hash 08b293e8aa342d465d26805d1d66f3595b2ce261.
 | 
			
		||||
 | 
			
		||||
Then, do the usual `autoreconf -fi && ./configure`, using a buildir != srcdir
 | 
			
		||||
(important, in order to avoid ending up with tempotary files in srcdir and
 | 
			
		||||
making it difficult to stash the relevant changes).
 | 
			
		||||
 | 
			
		||||
Finally, run `make -C src/ regen`, which will regenerate the files and copy over
 | 
			
		||||
the skeletons, with git possibily showing changes in the following paths:
 | 
			
		||||
- include/osmocom/sbcap/
 | 
			
		||||
- src/sbcap/gen/
 | 
			
		||||
- src/sbcap/skel/
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								TODO-RELEASE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								TODO-RELEASE
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
# When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install
 | 
			
		||||
# according to https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release
 | 
			
		||||
# In short: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
 | 
			
		||||
# LIBVERSION=c:r:a
 | 
			
		||||
# If the library source code has changed at all since the last update, then increment revision: c:r + 1:a.
 | 
			
		||||
# If any interfaces have been added, removed, or changed since the last update: c + 1:0:a.
 | 
			
		||||
# If any interfaces have been added since the last public release: c:r:a + 1.
 | 
			
		||||
# If any interfaces have been removed or changed since the last public release: c:r:0.
 | 
			
		||||
#library	what			description / commit summary line
 | 
			
		||||
@@ -31,10 +31,10 @@ if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
 | 
			
		||||
fi
 | 
			
		||||
PKG_PROG_PKG_CONFIG([0.20])
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.7.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.7.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.7.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 1.2.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.10.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.10.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.10.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 1.5.0)
 | 
			
		||||
PKG_CHECK_MODULES(ULFIUS, libulfius)
 | 
			
		||||
PKG_CHECK_MODULES(JANSSON, jansson)
 | 
			
		||||
PKG_CHECK_MODULES(ORCANIA, liborcania)
 | 
			
		||||
@@ -196,7 +196,6 @@ AC_OUTPUT(
 | 
			
		||||
    include/osmocom/cbc/Makefile
 | 
			
		||||
    include/osmocom/sbcap/Makefile
 | 
			
		||||
    contrib/Makefile
 | 
			
		||||
    contrib/osmo-cbc.spec
 | 
			
		||||
    tests/Makefile
 | 
			
		||||
    tests/sbcap/Makefile
 | 
			
		||||
    doc/Makefile
 | 
			
		||||
 
 | 
			
		||||
@@ -63,7 +63,7 @@ def do_create_cbs(args):
 | 
			
		||||
            },
 | 
			
		||||
            'payload': {
 | 
			
		||||
                'payload_decoded': {
 | 
			
		||||
                    'character_set': "gsm",
 | 
			
		||||
                    'character_set': args.character_set,
 | 
			
		||||
                    #'language': 'en',
 | 
			
		||||
                    'data_utf8': args.payload_data_utf8,
 | 
			
		||||
                    #'data_utf8': "Mahlzeit1 Mahlzeit2 Mahlzeit3 Mahlzeit4 Mahlzeit5 Mahlzeit6 Mahlzeit7 Mahlzeit8"
 | 
			
		||||
@@ -117,7 +117,7 @@ def main(argv):
 | 
			
		||||
    parser.add_argument("-p", "--port", help="TCP port to connect to", type=int, default=12345)
 | 
			
		||||
    parser.add_argument("-v", "--verbose", help="increase output verbosity", action='count', default=0)
 | 
			
		||||
 | 
			
		||||
    subparsers = parser.add_subparsers()
 | 
			
		||||
    subparsers = parser.add_subparsers(required=True)
 | 
			
		||||
 | 
			
		||||
    parser_c_cbs = subparsers.add_parser('create-cbs', help='Create a new CBS message')
 | 
			
		||||
    parser_c_cbs.add_argument("--msg-id", type=int, help='Message Identifier', required=True)
 | 
			
		||||
@@ -126,6 +126,7 @@ def main(argv):
 | 
			
		||||
    parser_c_cbs.add_argument("--repetition-period", type=int, help='Repetition Period', default=5)
 | 
			
		||||
    parser_c_cbs.add_argument("--num-of-bcast", type=int, help='Number of Broadcasts', default=999)
 | 
			
		||||
    parser_c_cbs.add_argument("--payload-data-utf8", type=str, help='Payload Data in UTF8', required=True)
 | 
			
		||||
    parser_c_cbs.add_argument("--character-set", type=str, help='Character Set', default="gsm", choices=["gsm","ucs2","8bit"])
 | 
			
		||||
    parser_c_cbs.set_defaults(func=do_create_cbs)
 | 
			
		||||
 | 
			
		||||
    parser_c_etws = subparsers.add_parser('create-etws', help='Create a new ETWS message')
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,6 @@ export LD_LIBRARY_PATH="$inst/lib"
 | 
			
		||||
export PATH="$inst/bin:$PATH"
 | 
			
		||||
 | 
			
		||||
osmo-build-dep.sh libosmocore "" --disable-doxygen
 | 
			
		||||
osmo-build-dep.sh libosmo-abis
 | 
			
		||||
osmo-build-dep.sh libosmo-netif "" --disable-doxygen
 | 
			
		||||
 | 
			
		||||
# Additional configure options and depends
 | 
			
		||||
@@ -51,11 +50,12 @@ autoreconf --install --force
 | 
			
		||||
./configure --enable-sanitize --enable-werror --enable-external-tests $CONFIG
 | 
			
		||||
$MAKE $PARALLEL_MAKE
 | 
			
		||||
DISTCHECK_CONFIGURE_FLAGS="--enable-external-tests $CONFIG" \
 | 
			
		||||
  $MAKE distcheck \
 | 
			
		||||
  $MAKE $PARALLEL_MAKE distcheck \
 | 
			
		||||
  || cat-testlogs.sh
 | 
			
		||||
 | 
			
		||||
if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
 | 
			
		||||
	make -C "$base/doc/manuals" publish
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
$MAKE $PARALLEL_MAKE maintainer-clean
 | 
			
		||||
osmo-clean-workspace.sh
 | 
			
		||||
 
 | 
			
		||||
@@ -1,128 +0,0 @@
 | 
			
		||||
#
 | 
			
		||||
# spec file for package osmo-cbc
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c) 2021, Harald Welte <laforge@gnumonks.org>
 | 
			
		||||
#
 | 
			
		||||
# All modifications and additions to the file contributed by third parties
 | 
			
		||||
# remain the property of their copyright owners, unless otherwise agreed
 | 
			
		||||
# upon. The license for this file, and modifications and additions to the
 | 
			
		||||
# file, is the same license as for the pristine package itself (unless the
 | 
			
		||||
# license for the pristine package is not an Open Source License, in which
 | 
			
		||||
# case the license is the MIT License). An "Open Source License" is a
 | 
			
		||||
# license that conforms to the Open Source Definition (Version 1.9)
 | 
			
		||||
# published by the Open Source Initiative.
 | 
			
		||||
 | 
			
		||||
## Disable LTO for now since it breaks compilation of the tests
 | 
			
		||||
## https://osmocom.org/issues/4113
 | 
			
		||||
%define _lto_cflags %{nil}
 | 
			
		||||
 | 
			
		||||
Name:           osmo-cbc
 | 
			
		||||
Version:        @VERSION@
 | 
			
		||||
Release:        0
 | 
			
		||||
Summary:        OsmoCBC: Osmocom's Cell Broadcast Centre for 3GPP mobile networks
 | 
			
		||||
License:        AGPL-3.0-or-later
 | 
			
		||||
Group:          Hardware/Mobile
 | 
			
		||||
URL:            https://osmocom.org/projects/osmo-cbc
 | 
			
		||||
Source:         %{name}-%{version}.tar.xz
 | 
			
		||||
BuildRequires:  automake >= 1.9
 | 
			
		||||
BuildRequires:  libtool >= 2
 | 
			
		||||
BuildRequires:  pkgconfig >= 0.20
 | 
			
		||||
%if 0%{?suse_version}
 | 
			
		||||
BuildRequires:  systemd-rpm-macros
 | 
			
		||||
%endif
 | 
			
		||||
BuildRequires:  pkgconfig(libsctp)
 | 
			
		||||
BuildRequires:  pkgconfig(libosmocore) >= 1.7.0
 | 
			
		||||
BuildRequires:  pkgconfig(libosmogsm) >= 1.7.0
 | 
			
		||||
BuildRequires:  pkgconfig(libosmovty) >= 1.7.0
 | 
			
		||||
BuildRequires:  pkgconfig(libosmo-netif) >= 1.2.0
 | 
			
		||||
BuildRequires:  pkgconfig(talloc)
 | 
			
		||||
BuildRequires:  pkgconfig(libulfius)
 | 
			
		||||
%{?systemd_requires}
 | 
			
		||||
 | 
			
		||||
%description
 | 
			
		||||
OsmoCBC: Osmocom's Cell Broadcast Centre for 3GPP mobile networks.
 | 
			
		||||
 | 
			
		||||
%package utils
 | 
			
		||||
Summary:	CLI utility to interface osmo-cbc REST interface
 | 
			
		||||
License:	MIT
 | 
			
		||||
Group:		Productivity/Telephony/Utilities
 | 
			
		||||
 | 
			
		||||
%description utils
 | 
			
		||||
CLI utility to interface with the osmo-cbc REST interface (ECBE).
 | 
			
		||||
 | 
			
		||||
%package -n libosmo-sbcap0
 | 
			
		||||
Summary:	Osmocom's library to encode/decode SBc-AP messages
 | 
			
		||||
Group:          System/Libraries
 | 
			
		||||
 | 
			
		||||
%description -n libosmo-sbcap0
 | 
			
		||||
Osmocom's library to encode/decode SBc-AP messages.
 | 
			
		||||
 | 
			
		||||
%package -n libosmo-sbcap-devel
 | 
			
		||||
Summary:        Development files for libosmo-sbcap
 | 
			
		||||
Group:          Development/Libraries/C and C++
 | 
			
		||||
Requires:       libosmo-sbcap0 = %{version}
 | 
			
		||||
 | 
			
		||||
%description -n libosmo-sbcap-devel
 | 
			
		||||
Osmocom's library to encode/decode SBc-AP messages.
 | 
			
		||||
 | 
			
		||||
This subpackage contains libraries and header files for developing
 | 
			
		||||
applications that want to make use of libosmo-sbcap.
 | 
			
		||||
 | 
			
		||||
%prep
 | 
			
		||||
%setup -q
 | 
			
		||||
 | 
			
		||||
%build
 | 
			
		||||
echo "%{version}" >.tarball-version
 | 
			
		||||
autoreconf -fi
 | 
			
		||||
%configure \
 | 
			
		||||
  --docdir=%{_docdir}/%{name} \
 | 
			
		||||
  --with-systemdsystemunitdir=%{_unitdir}
 | 
			
		||||
make %{?_smp_mflags}
 | 
			
		||||
 | 
			
		||||
%install
 | 
			
		||||
%make_install
 | 
			
		||||
install -m 755 contrib/cbc-apitool.py %{buildroot}/usr/bin/cbc-apitool.py
 | 
			
		||||
find %{buildroot} \( -name '*.la' -o -name '*.a' \) -delete -print
 | 
			
		||||
 | 
			
		||||
%if 0%{?suse_version}
 | 
			
		||||
%preun
 | 
			
		||||
%service_del_preun %{name}.service
 | 
			
		||||
 | 
			
		||||
%postun
 | 
			
		||||
%service_del_postun %{name}.service
 | 
			
		||||
 | 
			
		||||
%pre
 | 
			
		||||
%service_add_pre %{name}.service
 | 
			
		||||
 | 
			
		||||
%post
 | 
			
		||||
%service_add_post %{name}.service
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
%check
 | 
			
		||||
make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
 | 
			
		||||
 | 
			
		||||
%files
 | 
			
		||||
%license COPYING
 | 
			
		||||
%doc README.md
 | 
			
		||||
%{_bindir}/osmo-cbc
 | 
			
		||||
%dir %{_docdir}/%{name}/examples
 | 
			
		||||
%dir %{_docdir}/%{name}/examples/osmo-cbc
 | 
			
		||||
%{_docdir}/%{name}/examples/osmo-cbc/osmo-cbc*.cfg
 | 
			
		||||
%dir %{_sysconfdir}/osmocom
 | 
			
		||||
%config(noreplace) %{_sysconfdir}/osmocom/osmo-cbc.cfg
 | 
			
		||||
%{_unitdir}/%{name}.service
 | 
			
		||||
 | 
			
		||||
%files utils
 | 
			
		||||
%{_bindir}/cbc-apitool.py
 | 
			
		||||
 | 
			
		||||
%files -n libosmo-sbcap0
 | 
			
		||||
%{_libdir}/libosmo-sbcap.so.0*
 | 
			
		||||
 | 
			
		||||
%files -n libosmo-sbcap-devel
 | 
			
		||||
%{_libdir}/libosmo-sbcap.so
 | 
			
		||||
%{_libdir}/pkgconfig/libosmo-sbcap.pc
 | 
			
		||||
%dir %{_includedir}/osmocom
 | 
			
		||||
%dir %{_includedir}/osmocom/sbcap
 | 
			
		||||
%{_includedir}/osmocom/sbcap/*.h
 | 
			
		||||
 | 
			
		||||
%changelog
 | 
			
		||||
@@ -1,9 +1,15 @@
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=Osmocom CBC (Cell Broadcasting Centre)
 | 
			
		||||
After=network-online.target
 | 
			
		||||
Wants=network-online.target
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
Type=simple
 | 
			
		||||
StateDirectory=osmocom
 | 
			
		||||
WorkingDirectory=%S/osmocom
 | 
			
		||||
Restart=always
 | 
			
		||||
User=osmocom
 | 
			
		||||
Group=osmocom
 | 
			
		||||
ExecStart=/usr/bin/osmo-cbc -c /etc/osmocom/osmo-cbc.cfg
 | 
			
		||||
RestartSec=2
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										173
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										173
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,176 @@
 | 
			
		||||
osmo-cbc (0.5.1) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Oliver Smith ]
 | 
			
		||||
  * contrib/jenkins: libosmo-abis after libosmo-netif
 | 
			
		||||
 | 
			
		||||
  [ Pau Espin Pedrol ]
 | 
			
		||||
  * .gitignore: Add *~
 | 
			
		||||
  * cbsp_link: Log unexpected return error codes
 | 
			
		||||
  * abis: Fix reusing link->conn while it is being destroyed
 | 
			
		||||
  * jenkins.sh: Skip building unneeded libosmo-abis
 | 
			
		||||
 | 
			
		||||
 -- Oliver Smith <osmith@sysmocom.de>  Wed, 12 Feb 2025 14:30:50 +0100
 | 
			
		||||
 | 
			
		||||
osmo-cbc (0.5.0) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Harald Welte ]
 | 
			
		||||
  * cbc-apitool: Make character set configurable
 | 
			
		||||
 | 
			
		||||
  [ Andreas Eversberg ]
 | 
			
		||||
  * Use uniform log format for default config files
 | 
			
		||||
 | 
			
		||||
  [ Vadim Yanitskiy ]
 | 
			
		||||
  * build: include debian/ into the release tarball
 | 
			
		||||
  * README.md: cosmetic: fix a typo
 | 
			
		||||
 | 
			
		||||
  [ Pau Espin Pedrol ]
 | 
			
		||||
  * SBcAP: Update as1nc skeleton and generated code
 | 
			
		||||
 | 
			
		||||
  [ Max ]
 | 
			
		||||
  * .deb/.rpm: add osmocom user during package install
 | 
			
		||||
 | 
			
		||||
  [ Oliver Smith ]
 | 
			
		||||
  * .deb/.rpm: various fixes related to non-root
 | 
			
		||||
  * contrib: remove rpm spec file
 | 
			
		||||
  * debian/postinst: add checks, be verbose
 | 
			
		||||
 | 
			
		||||
 -- Oliver Smith <osmith@sysmocom.de>  Thu, 25 Jul 2024 09:46:02 +0200
 | 
			
		||||
 | 
			
		||||
osmo-cbc (0.4.2) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Vadim Yanitskiy ]
 | 
			
		||||
  * {src,tests/sbcap}/Makefile.am: reorder libraries in LDADD
 | 
			
		||||
  * tests: use -no-install libtool flag to avoid ./lt-* scripts
 | 
			
		||||
 | 
			
		||||
  [ Oliver Smith ]
 | 
			
		||||
  * debian: set compat level to 10
 | 
			
		||||
  * systemd: depend on networking-online.target
 | 
			
		||||
 | 
			
		||||
  [ Pau Espin Pedrol ]
 | 
			
		||||
  * sbcap: Update asn1c skeleton files
 | 
			
		||||
  * README.md: Document generation of SBcAP code from ASN.1 files
 | 
			
		||||
  * Catch and forbid configuring peers before configuring main protocol node
 | 
			
		||||
 | 
			
		||||
 -- Pau Espin Pedrol <pespin@sysmocom.de>  Tue, 12 Sep 2023 17:08:37 +0200
 | 
			
		||||
 | 
			
		||||
osmo-cbc (0.4.1) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Vadim Yanitskiy ]
 | 
			
		||||
  * contrib/jenkins.sh: also execute maintainer-clean target
 | 
			
		||||
  * contrib/jenkins.sh: execute 'distcheck' with $PARALLEL_MAKE
 | 
			
		||||
  * contrib/jenkins.sh: fix 'publish' target
 | 
			
		||||
 | 
			
		||||
  [ Max ]
 | 
			
		||||
  * Set working directory in systemd service file
 | 
			
		||||
 | 
			
		||||
  [ arehbein ]
 | 
			
		||||
  * osmo-cbc: Transition to use of 'telnet_init_default'
 | 
			
		||||
 | 
			
		||||
 -- Pau Espin Pedrol <pespin@sysmocom.de>  Tue, 07 Feb 2023 17:39:54 +0100
 | 
			
		||||
 | 
			
		||||
osmo-cbc (0.4.0) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Pau Espin Pedrol ]
 | 
			
		||||
  * Configure libosmocore logging system as multithread
 | 
			
		||||
  * Move peer to DELETED state before signalling parent FSM with DELETE_(N)ACK
 | 
			
		||||
  * Fix typos in error messages
 | 
			
		||||
  * main: remove newline char in perror() call
 | 
			
		||||
  * cbsp_server: Exit process gracefully if binding socket fails
 | 
			
		||||
  * Move header files to include/osmocom/cbc/ dir
 | 
			
		||||
  * Improve error handling when forwarding ECBE msg to CBSP
 | 
			
		||||
  * cbsp: Clean up conn closed paths
 | 
			
		||||
  * rest_api: Fix cbs.data_user_len not set in 'payload_encoded'
 | 
			
		||||
  * Add sbcap library
 | 
			
		||||
  * Add unit tests for sbcap
 | 
			
		||||
  * sbcap: Update asn1c skeleton files
 | 
			
		||||
  * Add initial SBc-AP support to osmo-cbc
 | 
			
		||||
  * doc: user manual: fix typo
 | 
			
		||||
  * doc: Document SBc-AP support and config
 | 
			
		||||
  * Fix printf format in 32bit arch
 | 
			
		||||
  * vty: Fix call to OSMO_STRBUF_PRINTF
 | 
			
		||||
  * sbcap: Update asn1c skeleton files
 | 
			
		||||
  * Improve example osmo-cbc.cfg file
 | 
			
		||||
  * sbcap_server.c: Remove unneeded goto
 | 
			
		||||
  * sbcap_server: Log all sctp notif
 | 
			
		||||
  * sbcap_server: Fix double-free of rx msg if conn is destroyed
 | 
			
		||||
  * Split cbc_peer to its own .c and .h files
 | 
			
		||||
  * cbc_peer: Close SBcAP conn when removing active peer
 | 
			
		||||
  * Move function defined in rest_it_op.c to rest_it_op.h
 | 
			
		||||
  * Move vty stuff to its own header cbc_vty.h
 | 
			
		||||
  * Split cbc_message related code to its own .c and .h file
 | 
			
		||||
  * Get rid of internal.h
 | 
			
		||||
  * sbcap_server.h: Remove unused fields
 | 
			
		||||
  * cbsp_server.c: Drop unused code
 | 
			
		||||
  * Rename CBSP,SABP,SBcAP structs and APIs
 | 
			
		||||
  * Rename {cbsp,sbcap}_server(_fsm).h s/server/link/
 | 
			
		||||
  * Rename fields in cbc_{cbsp,sbcap}_mgr
 | 
			
		||||
  * Use cbc_{cbsp,sbcap}_link_close when possible
 | 
			
		||||
  * cbc_vty: Use value_string to define proto names used in vty
 | 
			
		||||
  * cbc_vty: print correct protocol when writing config
 | 
			
		||||
  * Refactor {cbsp,sbcap}_cbc_accept_cb
 | 
			
		||||
  * cbc_vty: write peer config nodes at the end
 | 
			
		||||
  * Make cbsp,sbcap mgr available in data model
 | 
			
		||||
  * Fix cbc_vty_go_parent() not being called
 | 
			
		||||
  * cbc_main: Fix setting default SBc-AP local address
 | 
			
		||||
  * vty: Define peer proto during 'peer' node cmd
 | 
			
		||||
  * Move struct cbc bring up code to its own file and functions
 | 
			
		||||
  * Split cbsp/sbcap server socket creation from struct allocation
 | 
			
		||||
  * cbc-apitool: Fix port stored in var as a string
 | 
			
		||||
  * cbc-apitool: print usage instead of crashing if no subcmd passed
 | 
			
		||||
  * sbcap: Fix encoding of Warning-Type
 | 
			
		||||
  * cosmetic: smscb_message_fsm.c: Fix typo in comment
 | 
			
		||||
  * Support CBSP/TCP and SBc-AP/SCTP client mode
 | 
			
		||||
  * cbc_vty: Fix missing indent char in dump_one_etws_msg
 | 
			
		||||
  * vty: Fix 'show message' not finding expired messages
 | 
			
		||||
  * vty: Add command to delete expired messages
 | 
			
		||||
  * vty: Print created and expired times for each message
 | 
			
		||||
  * sbcap_msg: Improve spec references for used IEs
 | 
			
		||||
  * vty: Fix typo in vty output
 | 
			
		||||
  * Rearrange cbc_message and cbsp message code
 | 
			
		||||
  * Rename functions generating CBSP/SBc-AP Write-Replace request
 | 
			
		||||
  * sbcap: Fix typo in sbcap_cause_vals
 | 
			
		||||
  * sbcap: Send Error Indication if decoding rx msg fails
 | 
			
		||||
  * sbcap: Drop unused events
 | 
			
		||||
  * sbcap: Improve logging of rx Error Indication
 | 
			
		||||
  * sbcap: Improve logging on non-implemented PWS Restart/Failure Ind
 | 
			
		||||
  * sbcap: Tx Error ind if Rx ProcedureCode is unknown
 | 
			
		||||
  * Move sbcap_as_find_ie() to libsbcap
 | 
			
		||||
  * sbcap: Fix typo in comment
 | 
			
		||||
  * sbcap: Log info about messages received and trasmitted
 | 
			
		||||
  * Move cbc_cell_id2str() and make it public
 | 
			
		||||
  * Move ASN1C enc/dec logging to its own category
 | 
			
		||||
  * sbcap: Request and handle Write Replace Warning Indication
 | 
			
		||||
  * sbcap: Store reported failed TAIs from WriteReplaceResponse in cbc_message_peer
 | 
			
		||||
  * sbcap: Improve handling of WriteReplaceWarnResponse
 | 
			
		||||
  * Introduce logging category smscb
 | 
			
		||||
  * Split event list for smscb_message_fsm and smscb_peer_fsm
 | 
			
		||||
  * Split smscb_peer_fsm into CBSP and SBcAP specific FSMs
 | 
			
		||||
  * cbc_main: Enable logging of fsm timeouts
 | 
			
		||||
  * Propagate error to caller when tx cbsp/sbcap Write-Replace-Req fails
 | 
			
		||||
  * sbcap: Fix NULL pointer dereference
 | 
			
		||||
  * cbsp/sbcap: Fix memleak in error condition (tx without link)
 | 
			
		||||
  * *_smscb_peer_fsm: Immediately NACK if Tx of msg failed
 | 
			
		||||
  * cbsp: Fix heap-use-after-free closing cli conn in connecting state
 | 
			
		||||
  * cbsp/sbcap: Set link fsm id with peer's name
 | 
			
		||||
  * cbsp/sbcap: Fail if trying to Tx on non-connected (connecting) link
 | 
			
		||||
  * sbcap: Add Concurrent-Warning-Message-Indicator IE to Write-Replace-Req
 | 
			
		||||
  * cbsp: Log storing of CellId info received from peers
 | 
			
		||||
  * cbsp: Store content of received Cell Id from Failed List
 | 
			
		||||
 | 
			
		||||
  [ Oliver Smith ]
 | 
			
		||||
  * gitreview: add new file
 | 
			
		||||
  * checkpatch.conf: ignore sbcap generated files
 | 
			
		||||
  * contrib/osmo-cbc.spec: add libosmo-sbcap0/-dev
 | 
			
		||||
  * debian: add subpackages libosmo-sbcap0/-dev
 | 
			
		||||
  * libosmo-sbcap.pc.in: new file
 | 
			
		||||
 | 
			
		||||
  [ Vadim Yanitskiy ]
 | 
			
		||||
  * tests/sbcap: fix wrong operator used in OSMO_ASSERT statement
 | 
			
		||||
  * cbc_vty: use install_element[_ve](), not install_lib_element[_ve]()
 | 
			
		||||
  * libosmo-sbcap: add -no-undefined to libosmo_sbcap_la_LDFLAGS
 | 
			
		||||
 | 
			
		||||
 -- Pau Espin Pedrol <pespin@sysmocom.de>  Mon, 08 Aug 2022 11:42:56 +0200
 | 
			
		||||
 | 
			
		||||
osmo-cbc (0.3.0) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Vadim Yanitskiy ]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								debian/compat
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								debian/compat
									
									
									
									
										vendored
									
									
								
							@@ -1 +1 @@
 | 
			
		||||
9
 | 
			
		||||
10
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							@@ -2,7 +2,7 @@ Source: osmo-cbc
 | 
			
		||||
Section: net
 | 
			
		||||
Priority: extra
 | 
			
		||||
Maintainer: Osmocom team <openbsc@lists.osmocom.org>
 | 
			
		||||
Build-Depends: debhelper (>=9),
 | 
			
		||||
Build-Depends: debhelper (>= 10),
 | 
			
		||||
               dh-autoreconf,
 | 
			
		||||
               autotools-dev,
 | 
			
		||||
               autoconf,
 | 
			
		||||
@@ -11,12 +11,12 @@ Build-Depends: debhelper (>=9),
 | 
			
		||||
               pkg-config,
 | 
			
		||||
               python3-minimal,
 | 
			
		||||
               libtalloc-dev,
 | 
			
		||||
               libosmocore-dev (>= 1.7.0),
 | 
			
		||||
               libosmo-netif-dev (>= 1.2.0),
 | 
			
		||||
               libosmocore-dev (>= 1.10.0),
 | 
			
		||||
               libosmo-netif-dev (>= 1.5.0),
 | 
			
		||||
               libulfius-dev,
 | 
			
		||||
               libjansson-dev,
 | 
			
		||||
               libsctp-dev,
 | 
			
		||||
               osmo-gsm-manuals-dev
 | 
			
		||||
               osmo-gsm-manuals-dev (>= 1.6.0)
 | 
			
		||||
Standards-Version: 3.9.8
 | 
			
		||||
Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-cbc
 | 
			
		||||
Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-cbc
 | 
			
		||||
@@ -50,7 +50,7 @@ Description: ${misc:Package} PDF documentation
 | 
			
		||||
 Various manuals: user manual, VTY reference manual and/or
 | 
			
		||||
 protocol/interface manuals.
 | 
			
		||||
 | 
			
		||||
Package: libosmo-sbcap0
 | 
			
		||||
Package: libosmo-sbcap2
 | 
			
		||||
Section: libs
 | 
			
		||||
Architecture: any
 | 
			
		||||
Multi-Arch: same
 | 
			
		||||
@@ -62,5 +62,5 @@ Package: libosmo-sbcap-dev
 | 
			
		||||
Section: libdevel
 | 
			
		||||
Architecture: any
 | 
			
		||||
Multi-Arch: same
 | 
			
		||||
Depends: libosmo-sbcap0 (= ${binary:Version}), ${misc:Depends}
 | 
			
		||||
Depends: libosmo-sbcap2 (= ${binary:Version}), ${misc:Depends}
 | 
			
		||||
Description: libosmo-sbcap: Osmocom's library to encode/decode SBc-AP messages
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								debian/osmo-cbc.install
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								debian/osmo-cbc.install
									
									
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
/etc/osmocom/osmo-cbc.cfg
 | 
			
		||||
lib/systemd/system/osmo-cbc.service
 | 
			
		||||
usr/bin/osmo-cbc
 | 
			
		||||
usr/share/doc/osmo-cbc/examples/osmo-cbc/*.cfg usr/share/doc/osmo-bsc/examples
 | 
			
		||||
usr/share/doc/osmo-cbc/examples/osmo-cbc/*.cfg usr/share/doc/osmo-cbc/examples
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										38
									
								
								debian/postinst
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										38
									
								
								debian/postinst
									
									
									
									
										vendored
									
									
										Executable file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
#!/bin/sh -e
 | 
			
		||||
case "$1" in
 | 
			
		||||
	configure)
 | 
			
		||||
		# Create the osmocom group and user (if it doesn't exist yet)
 | 
			
		||||
		if ! getent group osmocom >/dev/null; then
 | 
			
		||||
			groupadd --system osmocom
 | 
			
		||||
		fi
 | 
			
		||||
		if ! getent passwd osmocom >/dev/null; then
 | 
			
		||||
			useradd \
 | 
			
		||||
				--system \
 | 
			
		||||
				--gid osmocom \
 | 
			
		||||
				--home-dir /var/lib/osmocom \
 | 
			
		||||
				--shell /sbin/nologin \
 | 
			
		||||
				--comment "Open Source Mobile Communications" \
 | 
			
		||||
				osmocom
 | 
			
		||||
		fi
 | 
			
		||||
 | 
			
		||||
		# Fix permissions of previous (root-owned) install (OS#4107)
 | 
			
		||||
		if dpkg --compare-versions "$2" le "0.5.0"; then
 | 
			
		||||
			if [ -e /etc/osmocom/osmo-cbc.cfg ]; then
 | 
			
		||||
				chown -v osmocom:osmocom /etc/osmocom/osmo-cbc.cfg
 | 
			
		||||
				chmod -v 0660 /etc/osmocom/osmo-cbc.cfg
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
			if [ -d /etc/osmocom ]; then
 | 
			
		||||
				chown -v root:osmocom /etc/osmocom
 | 
			
		||||
				chmod -v 2775 /etc/osmocom
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
			mkdir -p /var/lib/osmocom
 | 
			
		||||
			chown -R -v osmocom:osmocom /var/lib/osmocom
 | 
			
		||||
		fi
 | 
			
		||||
		;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
# dh_installdeb(1) will replace this with shell code automatically
 | 
			
		||||
# generated by other debhelper scripts.
 | 
			
		||||
#DEBHELPER#
 | 
			
		||||
@@ -1,8 +1,16 @@
 | 
			
		||||
log stderr
 | 
			
		||||
 logging color 1
 | 
			
		||||
 logging print category-hex 0
 | 
			
		||||
 logging print category 1
 | 
			
		||||
 logging timestamp 0
 | 
			
		||||
 logging print file basename last
 | 
			
		||||
 logging print level 1
 | 
			
		||||
 logging level main notice
 | 
			
		||||
 logging level rest notice
 | 
			
		||||
 logging level smscb notice
 | 
			
		||||
 logging level cbsp notice
 | 
			
		||||
 logging level sbcap notice
 | 
			
		||||
 logging level asn1c notice
 | 
			
		||||
 logging level rest notice
 | 
			
		||||
cbc
 | 
			
		||||
 unknown-peers reject
 | 
			
		||||
 ecbe
 | 
			
		||||
@@ -16,9 +24,11 @@ cbc
 | 
			
		||||
  local-ip ::1
 | 
			
		||||
  local-port 29168
 | 
			
		||||
 peer cbsp example-bsc
 | 
			
		||||
  mode server
 | 
			
		||||
  remote-ip 127.0.0.2
 | 
			
		||||
  remote-port 48049
 | 
			
		||||
 peer sbcap example-mme
 | 
			
		||||
  mode client
 | 
			
		||||
  remote-ip 127.0.0.2
 | 
			
		||||
  remote-ip ::2
 | 
			
		||||
  remote-port 29168
 | 
			
		||||
 
 | 
			
		||||
@@ -50,6 +50,8 @@ You can create a new CBS message using `cbc-apitool create-cbs`.
 | 
			
		||||
*--payload-data-utf8 PAYLOAD_DATA_UTF8*::
 | 
			
		||||
        Payload data (typically text message) in UTF8 encoding.  Will be
 | 
			
		||||
        transcoded to 7bit GSM alphabet internally.
 | 
			
		||||
*--character-set {gsm,8bit,ucs2}*::
 | 
			
		||||
        Character set to be used for the message.  Default: gsm
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
==== `create-etws` Options
 | 
			
		||||
 
 | 
			
		||||
@@ -17,5 +17,5 @@ arguments:
 | 
			
		||||
	Fork the process as a daemon into background.
 | 
			
		||||
*-c, --config-file 'CONFIGFILE'*::
 | 
			
		||||
	Specify the file and path name of the configuration file to be
 | 
			
		||||
	used. If none is specified, use `osmo-bsc.cfg` in the current
 | 
			
		||||
	used. If none is specified, use `osmo-cbc.cfg` in the current
 | 
			
		||||
	working directory.
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ noinst_HEADERS = \
 | 
			
		||||
	cbc_vty.h \
 | 
			
		||||
	cbsp_link.h \
 | 
			
		||||
	cbsp_link_fsm.h \
 | 
			
		||||
	cbsp_msg.h \
 | 
			
		||||
	charset.h \
 | 
			
		||||
	debug.h \
 | 
			
		||||
	sbcap_msg.h \
 | 
			
		||||
@@ -12,4 +13,5 @@ noinst_HEADERS = \
 | 
			
		||||
	sbcap_link_fsm.h \
 | 
			
		||||
	rest_it_op.h \
 | 
			
		||||
	smscb_message_fsm.h \
 | 
			
		||||
	smscb_peer_fsm.h \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,8 @@ enum cbc_cell_id_type {
 | 
			
		||||
	CBC_CELL_ID_LAI,
 | 
			
		||||
	CBC_CELL_ID_LAC,
 | 
			
		||||
	CBC_CELL_ID_CI,
 | 
			
		||||
	CBC_CELL_ID_ECGI,
 | 
			
		||||
	CBC_CELL_ID_TAI,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cbc_cell_id {
 | 
			
		||||
@@ -27,6 +29,8 @@ struct cbc_cell_id {
 | 
			
		||||
		struct osmo_location_area_id lai;
 | 
			
		||||
		uint16_t lac;
 | 
			
		||||
		uint16_t ci;
 | 
			
		||||
		struct osmo_eutran_cell_global_id ecgi;
 | 
			
		||||
		struct osmo_tracking_area_id tai;
 | 
			
		||||
	} u;
 | 
			
		||||
	/* only in failure list */
 | 
			
		||||
	struct {
 | 
			
		||||
@@ -39,6 +43,8 @@ struct cbc_cell_id {
 | 
			
		||||
	} num_compl;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const char *cbc_cell_id2str(const struct cbc_cell_id *cid);
 | 
			
		||||
 | 
			
		||||
/*********************************************************************************
 | 
			
		||||
 * CBC itself
 | 
			
		||||
 *********************************************************************************/
 | 
			
		||||
@@ -51,11 +57,13 @@ struct cbc {
 | 
			
		||||
		struct {
 | 
			
		||||
			char *local_host;
 | 
			
		||||
			int local_port;
 | 
			
		||||
			bool configured;
 | 
			
		||||
		} cbsp;
 | 
			
		||||
		struct {
 | 
			
		||||
			char *local_host[CBC_MAX_LOC_ADDRS];
 | 
			
		||||
			unsigned int num_local_host;
 | 
			
		||||
			int local_port;
 | 
			
		||||
			bool configured;
 | 
			
		||||
		} sbcap;
 | 
			
		||||
		struct {
 | 
			
		||||
			char *local_host;
 | 
			
		||||
@@ -81,6 +89,7 @@ struct cbc {
 | 
			
		||||
extern struct cbc *g_cbc;
 | 
			
		||||
struct cbc *cbc_alloc(void *ctx);
 | 
			
		||||
int cbc_start(struct cbc *cbc);
 | 
			
		||||
void cbc_add_sbcap_default_local_host_if_needed(struct cbc *cbc);
 | 
			
		||||
 | 
			
		||||
/* rest_api.c */
 | 
			
		||||
int rest_api_init(void *ctx, const char *bind_addr, uint16_t port);
 | 
			
		||||
 
 | 
			
		||||
@@ -99,9 +99,11 @@ struct cbc_message {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cbc_message *cbc_message_alloc(void *ctx, const struct cbc_message *cbcmsg);
 | 
			
		||||
void cbc_message_free(struct cbc_message *cbcmsg);
 | 
			
		||||
int cbc_message_new(const struct cbc_message *cbcmsg, struct rest_it_op *op);
 | 
			
		||||
void cbc_message_delete(struct cbc_message *cbcmsg, struct rest_it_op *op);
 | 
			
		||||
struct cbc_message *cbc_message_by_id(uint16_t message_id);
 | 
			
		||||
struct cbc_message *cbc_message_expired_by_id(uint16_t message_id);
 | 
			
		||||
int peer_new_cbc_message(struct cbc_peer *peer, struct cbc_message *cbcmsg);
 | 
			
		||||
 | 
			
		||||
int cbc_message_del_peer(struct cbc_message *cbcmsg, struct cbc_peer *peer);
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,16 @@ enum cbc_peer_protocol {
 | 
			
		||||
	CBC_PEER_PROTO_SBcAP
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum cbc_peer_link_mode {
 | 
			
		||||
	CBC_PEER_LINK_MODE_DISABLED = 0,
 | 
			
		||||
	CBC_PEER_LINK_MODE_SERVER,
 | 
			
		||||
	CBC_PEER_LINK_MODE_CLIENT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern const struct value_string cbc_peer_link_mode_names[];
 | 
			
		||||
static inline const char *cbc_peer_link_mode_name(enum cbc_peer_link_mode val)
 | 
			
		||||
{ return get_value_string(cbc_peer_link_mode_names, val); }
 | 
			
		||||
 | 
			
		||||
struct cbc_peer {
 | 
			
		||||
	struct llist_head list;		/* linked to cbc.peers */
 | 
			
		||||
	const char *name;
 | 
			
		||||
@@ -34,6 +44,7 @@ struct cbc_peer {
 | 
			
		||||
		struct cbc_sabp_link *sabp;
 | 
			
		||||
		struct cbc_sbcap_link *sbcap;
 | 
			
		||||
	} link;
 | 
			
		||||
	enum cbc_peer_link_mode link_mode;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern const struct value_string cbc_peer_proto_name[];
 | 
			
		||||
@@ -44,3 +55,4 @@ void cbc_peer_remove(struct cbc_peer *peer);
 | 
			
		||||
struct cbc_peer *cbc_peer_by_name(const char *name);
 | 
			
		||||
struct cbc_peer *cbc_peer_by_addr_proto(const char *remote_host, uint16_t remote_port,
 | 
			
		||||
					enum cbc_peer_protocol proto);
 | 
			
		||||
int cbc_peer_apply_cfg_chg(struct cbc_peer *peer);
 | 
			
		||||
 
 | 
			
		||||
@@ -31,19 +31,22 @@ int cbc_cbsp_mgr_open_srv(struct cbc_cbsp_mgr *mgr);
 | 
			
		||||
struct cbc_cbsp_link {
 | 
			
		||||
	/* entry in osmo_cbsp_cbc.links */
 | 
			
		||||
	struct llist_head list;
 | 
			
		||||
	/* stream server connection for this link */
 | 
			
		||||
	struct osmo_stream_srv *conn;
 | 
			
		||||
	/* partially received CBSP message (rx completion pending) */
 | 
			
		||||
	struct msgb *rx_msg;
 | 
			
		||||
 | 
			
		||||
	struct osmo_fsm_inst *fi;
 | 
			
		||||
 | 
			
		||||
	struct cbc_peer *peer;
 | 
			
		||||
	bool is_client;
 | 
			
		||||
	union {
 | 
			
		||||
		struct osmo_stream_srv *srv_conn;
 | 
			
		||||
		struct osmo_stream_cli *cli_conn;
 | 
			
		||||
		void *conn; /* used when we just care about the pointer */
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cbc_cbsp_link *cbc_cbsp_link_alloc(struct cbc_cbsp_mgr *cbc, struct cbc_peer *peer);
 | 
			
		||||
void cbc_cbsp_link_free(struct cbc_cbsp_link *link);
 | 
			
		||||
const char *cbc_cbsp_link_name(const struct cbc_cbsp_link *link);
 | 
			
		||||
void cbc_cbsp_link_tx(struct cbc_cbsp_link *link, struct osmo_cbsp_decoded *cbsp);
 | 
			
		||||
int cbc_cbsp_link_open_cli(struct cbc_cbsp_link *link);
 | 
			
		||||
int cbc_cbsp_link_tx(struct cbc_cbsp_link *link, struct osmo_cbsp_decoded *cbsp);
 | 
			
		||||
void cbc_cbsp_link_close(struct cbc_cbsp_link *link);
 | 
			
		||||
int cbc_cbsp_link_rx_cb(struct cbc_cbsp_link *link, struct osmo_cbsp_decoded *dec);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								include/osmocom/cbc/cbsp_msg.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								include/osmocom/cbc/cbsp_msg.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <osmocom/gsm/cbsp.h>
 | 
			
		||||
 | 
			
		||||
struct cbc_message;
 | 
			
		||||
struct osmo_cbsp_decoded *cbsp_gen_write_replace_req(void *ctx, const struct cbc_message *cbcmsg);
 | 
			
		||||
@@ -2,7 +2,9 @@
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	DMAIN,
 | 
			
		||||
	DSMSCB,
 | 
			
		||||
	DCBSP,
 | 
			
		||||
	DSBcAP,
 | 
			
		||||
	DASN1C,
 | 
			
		||||
	DREST,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -33,15 +33,20 @@ int cbc_sbcap_mgr_open_srv(struct cbc_sbcap_mgr *mgr);
 | 
			
		||||
struct cbc_sbcap_link {
 | 
			
		||||
	/* entry in osmo_sbcap_cbc.links */
 | 
			
		||||
	struct llist_head list;
 | 
			
		||||
	/* stream server connection for this link */
 | 
			
		||||
	struct osmo_stream_srv *conn;
 | 
			
		||||
	struct osmo_fsm_inst *fi;
 | 
			
		||||
	struct cbc_peer *peer;
 | 
			
		||||
	bool is_client;
 | 
			
		||||
	union {
 | 
			
		||||
		struct osmo_stream_srv *srv_conn;
 | 
			
		||||
		struct osmo_stream_cli *cli_conn;
 | 
			
		||||
		void *conn; /* used when we just care about the pointer */
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cbc_sbcap_link *cbc_sbcap_link_alloc(struct cbc_sbcap_mgr *cbc, struct cbc_peer *peer);
 | 
			
		||||
void cbc_sbcap_link_free(struct cbc_sbcap_link *link);
 | 
			
		||||
const char *cbc_sbcap_link_name(const struct cbc_sbcap_link *link);
 | 
			
		||||
void cbc_sbcap_link_tx(struct cbc_sbcap_link *link, SBcAP_SBC_AP_PDU_t *pdu);
 | 
			
		||||
int cbc_sbcap_link_open_cli(struct cbc_sbcap_link *link);
 | 
			
		||||
int cbc_sbcap_link_tx(struct cbc_sbcap_link *link, SBcAP_SBC_AP_PDU_t *pdu);
 | 
			
		||||
void cbc_sbcap_link_close(struct cbc_sbcap_link *link);
 | 
			
		||||
int cbc_sbcap_link_rx_cb(struct cbc_sbcap_link *link, SBcAP_SBC_AP_PDU_t *pdu);
 | 
			
		||||
 
 | 
			
		||||
@@ -6,10 +6,7 @@
 | 
			
		||||
extern struct osmo_fsm sbcap_link_fsm;
 | 
			
		||||
 | 
			
		||||
enum sbcap_link_event {
 | 
			
		||||
	SBcAP_LINK_E_RX_RST_COMPL,	/* reset complete received */
 | 
			
		||||
	SBcAP_LINK_E_RX_RST_FAIL,		/* reset failure received */
 | 
			
		||||
	SBcAP_LINK_E_RX_KA_COMPL,		/* keep-alive complete received */
 | 
			
		||||
	SBcAP_LINK_E_RX_RESTART,		/* restart received */
 | 
			
		||||
	SBcAP_LINK_E_RX_RESTART,	/* SBc-AP PWS Restart Ind received */
 | 
			
		||||
	SBcAP_LINK_E_CMD_RESET,		/* RESET command from CBC */
 | 
			
		||||
	SBcAP_LINK_E_CMD_CLOSE,		/* CLOSE command from CBC */
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,17 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <osmocom/core/linuxlist.h>
 | 
			
		||||
#include <osmocom/netif/stream.h>
 | 
			
		||||
#include <osmocom/sbcap/sbcap_common.h>
 | 
			
		||||
 | 
			
		||||
#include "cbc_data.h"
 | 
			
		||||
 | 
			
		||||
struct cbc_message;
 | 
			
		||||
typedef struct SBcAP_SBC_AP_PDU SBcAP_SBC_AP_PDU_t;
 | 
			
		||||
 | 
			
		||||
SBcAP_SBC_AP_PDU_t *cbcmsg_to_sbcap(void *ctx, const struct cbc_message *cbcmsg);
 | 
			
		||||
SBcAP_SBC_AP_PDU_t *sbcap_gen_write_replace_warning_req(void *ctx, const struct cbc_message *cbcmsg);
 | 
			
		||||
SBcAP_SBC_AP_PDU_t *sbcap_gen_stop_warning_req(void *ctx, const struct cbc_message *cbcmsg);
 | 
			
		||||
SBcAP_SBC_AP_PDU_t *sbcap_gen_error_ind(void *ctx, SBcAP_Cause_t cause, SBcAP_SBC_AP_PDU_t *rx_pdu);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void cci_from_sbcap_bcast_cell_id(struct cbc_cell_id *cci, const SBcAP_CellId_Broadcast_List_Item_t *it);
 | 
			
		||||
void cci_from_sbcap_tai(struct cbc_cell_id *cci, const SBcAP_TAI_t *tai);
 | 
			
		||||
 
 | 
			
		||||
@@ -3,34 +3,28 @@
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <osmocom/core/fsm.h>
 | 
			
		||||
 | 
			
		||||
enum smscb_fsm_event {
 | 
			
		||||
	SMSCB_E_CHILD_DIED,
 | 
			
		||||
enum smscb_message_fsm_event {
 | 
			
		||||
	SMSCB_MSG_E_CHILD_DIED,
 | 
			
		||||
	/* create a message (from REST) */
 | 
			
		||||
	SMSCB_E_CREATE,
 | 
			
		||||
	SMSCB_MSG_E_CREATE,
 | 
			
		||||
	/* replace a message (from REST) */
 | 
			
		||||
	SMSCB_E_REPLACE,
 | 
			
		||||
	SMSCB_MSG_E_REPLACE,
 | 
			
		||||
	/* get status of a message (from REST) */
 | 
			
		||||
	SMSCB_E_STATUS,
 | 
			
		||||
	SMSCB_MSG_E_STATUS,
 | 
			
		||||
	/* delete a message (from REST) */
 | 
			
		||||
	SMSCB_E_DELETE,
 | 
			
		||||
	/* CBSP peer confirms write */
 | 
			
		||||
	SMSCB_E_CBSP_WRITE_ACK,
 | 
			
		||||
	SMSCB_E_CBSP_WRITE_NACK,
 | 
			
		||||
	/* CBSP peer confirms replace */
 | 
			
		||||
	SMSCB_E_CBSP_REPLACE_ACK,
 | 
			
		||||
	SMSCB_E_CBSP_REPLACE_NACK,
 | 
			
		||||
	/* CBSP peer confirms delete */
 | 
			
		||||
	SMSCB_E_CBSP_DELETE_ACK,
 | 
			
		||||
	SMSCB_E_CBSP_DELETE_NACK,
 | 
			
		||||
	/* CBSP peer confirms status query */
 | 
			
		||||
	SMSCB_E_CBSP_STATUS_ACK,
 | 
			
		||||
	SMSCB_E_CBSP_STATUS_NACK,
 | 
			
		||||
	/* SBc-AP peer confirms write */
 | 
			
		||||
	SMSCB_E_SBCAP_WRITE_ACK,
 | 
			
		||||
	SMSCB_E_SBCAP_WRITE_NACK,
 | 
			
		||||
	/* SBc-AP peer confirms delete */
 | 
			
		||||
	SMSCB_E_SBCAP_DELETE_ACK,
 | 
			
		||||
	SMSCB_E_SBCAP_DELETE_NACK,
 | 
			
		||||
	SMSCB_MSG_E_DELETE,
 | 
			
		||||
	/* peer confirms write */
 | 
			
		||||
	SMSCB_MSG_E_WRITE_ACK,
 | 
			
		||||
	SMSCB_MSG_E_WRITE_NACK,
 | 
			
		||||
	/* peer confirms replace */
 | 
			
		||||
	SMSCB_MSG_E_REPLACE_ACK,
 | 
			
		||||
	SMSCB_MSG_E_REPLACE_NACK,
 | 
			
		||||
	/* peer confirms delete */
 | 
			
		||||
	SMSCB_MSG_E_DELETE_ACK,
 | 
			
		||||
	SMSCB_MSG_E_DELETE_NACK,
 | 
			
		||||
	/* peer confirms status query */
 | 
			
		||||
	SMSCB_MSG_E_STATUS_ACK,
 | 
			
		||||
	SMSCB_MSG_E_STATUS_NACK
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum smscb_fsm_state {
 | 
			
		||||
@@ -56,4 +50,4 @@ enum smscb_p_fsm_timer {
 | 
			
		||||
	T_WAIT_DELETE_ACK,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern const struct value_string smscb_fsm_event_names[];
 | 
			
		||||
extern const struct value_string smscb_message_fsm_event_names[];
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								include/osmocom/cbc/smscb_peer_fsm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								include/osmocom/cbc/smscb_peer_fsm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <osmocom/core/fsm.h>
 | 
			
		||||
 | 
			
		||||
enum smscb_peer_fsm_event {
 | 
			
		||||
	/* create a message (from REST) */
 | 
			
		||||
	SMSCB_PEER_E_CREATE,
 | 
			
		||||
	/* replace a message (from REST) */
 | 
			
		||||
	SMSCB_PEER_E_REPLACE,
 | 
			
		||||
	/* get status of a message (from REST) */
 | 
			
		||||
	SMSCB_PEER_E_STATUS,
 | 
			
		||||
	/* delete a message (from REST) */
 | 
			
		||||
	SMSCB_PEER_E_DELETE,
 | 
			
		||||
	/* CBSP peer confirms write */
 | 
			
		||||
	SMSCB_PEER_E_CBSP_WRITE_ACK,
 | 
			
		||||
	SMSCB_PEER_E_CBSP_WRITE_NACK,
 | 
			
		||||
	/* CBSP peer confirms replace */
 | 
			
		||||
	SMSCB_PEER_E_CBSP_REPLACE_ACK,
 | 
			
		||||
	SMSCB_PEER_E_CBSP_REPLACE_NACK,
 | 
			
		||||
	/* CBSP peer confirms delete */
 | 
			
		||||
	SMSCB_PEER_E_CBSP_DELETE_ACK,
 | 
			
		||||
	SMSCB_PEER_E_CBSP_DELETE_NACK,
 | 
			
		||||
	/* CBSP peer confirms status query */
 | 
			
		||||
	SMSCB_PEER_E_CBSP_STATUS_ACK,
 | 
			
		||||
	SMSCB_PEER_E_CBSP_STATUS_NACK,
 | 
			
		||||
	/* SBc-AP peer confirms write */
 | 
			
		||||
	SMSCB_PEER_E_SBCAP_WRITE_ACK,
 | 
			
		||||
	SMSCB_PEER_E_SBCAP_WRITE_NACK,
 | 
			
		||||
	/* SBc-AP peer confirms delete */
 | 
			
		||||
	SMSCB_PEER_E_SBCAP_DELETE_ACK,
 | 
			
		||||
	SMSCB_PEER_E_SBCAP_DELETE_NACK,
 | 
			
		||||
	/* SBc-AP peer sends Write Replace Warning Indication to us */
 | 
			
		||||
	SMSCB_PEER_E_SBCAP_WRITE_IND,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern const struct value_string smscb_peer_fsm_event_names[];
 | 
			
		||||
 | 
			
		||||
extern struct osmo_fsm cbsp_smscb_peer_fsm;
 | 
			
		||||
extern struct osmo_fsm sbcap_smscb_peer_fsm;
 | 
			
		||||
@@ -1,3 +1,16 @@
 | 
			
		||||
version.h: version.h.tpl
 | 
			
		||||
	$(AM_V_GEN)$(MKDIR_P) $(dir $@)
 | 
			
		||||
	$(AM_V_GEN)sed \
 | 
			
		||||
		-e "s/{{VERSION}}/$$(echo '@VERSION@' | cut -d. -f1-3)/g" \
 | 
			
		||||
		-e "s/{{VERSION_MAJOR}}/$$(echo '@VERSION@' | cut -d. -f1)/g" \
 | 
			
		||||
		-e "s/{{VERSION_MINOR}}/$$(echo '@VERSION@' | cut -d. -f2)/g" \
 | 
			
		||||
		-e "s/{{VERSION_PATCH}}/$$(echo '@VERSION@' | cut -d. -f3)/g" \
 | 
			
		||||
		$< > $@
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST = \
 | 
			
		||||
	version.h.tpl \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
sbcap_HEADERS = \
 | 
			
		||||
	sbcap_common.h \
 | 
			
		||||
	sbcap_internal.h \
 | 
			
		||||
@@ -115,6 +128,7 @@ sbcap_HEADERS = \
 | 
			
		||||
	SBcAP_Write-Replace-Warning-Indication.h \
 | 
			
		||||
	SBcAP_Write-Replace-Warning-Request.h \
 | 
			
		||||
	SBcAP_Write-Replace-Warning-Response.h \
 | 
			
		||||
	version.h \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
sbcapdir = $(includedir)/osmocom/sbcap
 | 
			
		||||
 
 | 
			
		||||
@@ -29,12 +29,12 @@ typedef long	 SBcAP_Concurrent_Warning_Message_Indicator_t;
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_per_constraints_t asn_PER_type_SBcAP_Concurrent_Warning_Message_Indicator_constr_1;
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_Concurrent_Warning_Message_Indicator;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_Concurrent_Warning_Message_Indicator_specs_1;
 | 
			
		||||
asn_struct_free_f Concurrent_Warning_Message_Indicator_free;
 | 
			
		||||
asn_struct_print_f Concurrent_Warning_Message_Indicator_print;
 | 
			
		||||
asn_constr_check_f Concurrent_Warning_Message_Indicator_constraint;
 | 
			
		||||
per_type_decoder_f Concurrent_Warning_Message_Indicator_decode_aper;
 | 
			
		||||
per_type_encoder_f Concurrent_Warning_Message_Indicator_encode_aper;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_SBcAP_Concurrent_Warning_Message_Indicator_specs_1;
 | 
			
		||||
asn_struct_free_f SBcAP_Concurrent_Warning_Message_Indicator_free;
 | 
			
		||||
asn_struct_print_f SBcAP_Concurrent_Warning_Message_Indicator_print;
 | 
			
		||||
asn_constr_check_f SBcAP_Concurrent_Warning_Message_Indicator_constraint;
 | 
			
		||||
per_type_decoder_f SBcAP_Concurrent_Warning_Message_Indicator_decode_aper;
 | 
			
		||||
per_type_encoder_f SBcAP_Concurrent_Warning_Message_Indicator_encode_aper;
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -31,12 +31,12 @@ typedef long	 SBcAP_Criticality_t;
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_per_constraints_t asn_PER_type_SBcAP_Criticality_constr_1;
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_Criticality;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_Criticality_specs_1;
 | 
			
		||||
asn_struct_free_f Criticality_free;
 | 
			
		||||
asn_struct_print_f Criticality_print;
 | 
			
		||||
asn_constr_check_f Criticality_constraint;
 | 
			
		||||
per_type_decoder_f Criticality_decode_aper;
 | 
			
		||||
per_type_encoder_f Criticality_encode_aper;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_SBcAP_Criticality_specs_1;
 | 
			
		||||
asn_struct_free_f SBcAP_Criticality_free;
 | 
			
		||||
asn_struct_print_f SBcAP_Criticality_print;
 | 
			
		||||
asn_constr_check_f SBcAP_Criticality_constraint;
 | 
			
		||||
per_type_decoder_f SBcAP_Criticality_decode_aper;
 | 
			
		||||
per_type_encoder_f SBcAP_Criticality_encode_aper;
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,8 @@ typedef struct SBcAP_Error_Indication {
 | 
			
		||||
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_Error_Indication;
 | 
			
		||||
extern asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Error_Indication_specs_1;
 | 
			
		||||
extern asn_TYPE_member_t asn_MBR_SBcAP_Error_Indication_1[1];
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,8 @@ typedef struct SBcAP_PWS_Failure_Indication {
 | 
			
		||||
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_PWS_Failure_Indication;
 | 
			
		||||
extern asn_SEQUENCE_specifics_t asn_SPC_SBcAP_PWS_Failure_Indication_specs_1;
 | 
			
		||||
extern asn_TYPE_member_t asn_MBR_SBcAP_PWS_Failure_Indication_1[2];
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,8 @@ typedef struct SBcAP_PWS_Restart_Indication {
 | 
			
		||||
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_PWS_Restart_Indication;
 | 
			
		||||
extern asn_SEQUENCE_specifics_t asn_SPC_SBcAP_PWS_Restart_Indication_specs_1;
 | 
			
		||||
extern asn_TYPE_member_t asn_MBR_SBcAP_PWS_Restart_Indication_1[2];
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -31,12 +31,12 @@ typedef long	 SBcAP_Presence_t;
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_per_constraints_t asn_PER_type_SBcAP_Presence_constr_1;
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_Presence;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_Presence_specs_1;
 | 
			
		||||
asn_struct_free_f Presence_free;
 | 
			
		||||
asn_struct_print_f Presence_print;
 | 
			
		||||
asn_constr_check_f Presence_constraint;
 | 
			
		||||
per_type_decoder_f Presence_decode_aper;
 | 
			
		||||
per_type_encoder_f Presence_encode_aper;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_SBcAP_Presence_specs_1;
 | 
			
		||||
asn_struct_free_f SBcAP_Presence_free;
 | 
			
		||||
asn_struct_print_f SBcAP_Presence_print;
 | 
			
		||||
asn_constr_check_f SBcAP_Presence_constraint;
 | 
			
		||||
per_type_decoder_f SBcAP_Presence_decode_aper;
 | 
			
		||||
per_type_encoder_f SBcAP_Presence_encode_aper;
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,12 +29,12 @@ typedef long	 SBcAP_RAT_Selector_5GS_t;
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_per_constraints_t asn_PER_type_SBcAP_RAT_Selector_5GS_constr_1;
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_RAT_Selector_5GS;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_RAT_Selector_5GS_specs_1;
 | 
			
		||||
asn_struct_free_f RAT_Selector_5GS_free;
 | 
			
		||||
asn_struct_print_f RAT_Selector_5GS_print;
 | 
			
		||||
asn_constr_check_f RAT_Selector_5GS_constraint;
 | 
			
		||||
per_type_decoder_f RAT_Selector_5GS_decode_aper;
 | 
			
		||||
per_type_encoder_f RAT_Selector_5GS_encode_aper;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_SBcAP_RAT_Selector_5GS_specs_1;
 | 
			
		||||
asn_struct_free_f SBcAP_RAT_Selector_5GS_free;
 | 
			
		||||
asn_struct_print_f SBcAP_RAT_Selector_5GS_print;
 | 
			
		||||
asn_constr_check_f SBcAP_RAT_Selector_5GS_constraint;
 | 
			
		||||
per_type_decoder_f SBcAP_RAT_Selector_5GS_decode_aper;
 | 
			
		||||
per_type_encoder_f SBcAP_RAT_Selector_5GS_encode_aper;
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,12 +29,12 @@ typedef long	 SBcAP_Send_Stop_Warning_Indication_t;
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_per_constraints_t asn_PER_type_SBcAP_Send_Stop_Warning_Indication_constr_1;
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_Send_Stop_Warning_Indication;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_Send_Stop_Warning_Indication_specs_1;
 | 
			
		||||
asn_struct_free_f Send_Stop_Warning_Indication_free;
 | 
			
		||||
asn_struct_print_f Send_Stop_Warning_Indication_print;
 | 
			
		||||
asn_constr_check_f Send_Stop_Warning_Indication_constraint;
 | 
			
		||||
per_type_decoder_f Send_Stop_Warning_Indication_decode_aper;
 | 
			
		||||
per_type_encoder_f Send_Stop_Warning_Indication_encode_aper;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_SBcAP_Send_Stop_Warning_Indication_specs_1;
 | 
			
		||||
asn_struct_free_f SBcAP_Send_Stop_Warning_Indication_free;
 | 
			
		||||
asn_struct_print_f SBcAP_Send_Stop_Warning_Indication_print;
 | 
			
		||||
asn_constr_check_f SBcAP_Send_Stop_Warning_Indication_constraint;
 | 
			
		||||
per_type_decoder_f SBcAP_Send_Stop_Warning_Indication_decode_aper;
 | 
			
		||||
per_type_encoder_f SBcAP_Send_Stop_Warning_Indication_encode_aper;
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,12 +29,12 @@ typedef long	 SBcAP_Send_Write_Replace_Warning_Indication_t;
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_per_constraints_t asn_PER_type_SBcAP_Send_Write_Replace_Warning_Indication_constr_1;
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_Send_Write_Replace_Warning_Indication;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_Send_Write_Replace_Warning_Indication_specs_1;
 | 
			
		||||
asn_struct_free_f Send_Write_Replace_Warning_Indication_free;
 | 
			
		||||
asn_struct_print_f Send_Write_Replace_Warning_Indication_print;
 | 
			
		||||
asn_constr_check_f Send_Write_Replace_Warning_Indication_constraint;
 | 
			
		||||
per_type_decoder_f Send_Write_Replace_Warning_Indication_decode_aper;
 | 
			
		||||
per_type_encoder_f Send_Write_Replace_Warning_Indication_encode_aper;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_SBcAP_Send_Write_Replace_Warning_Indication_specs_1;
 | 
			
		||||
asn_struct_free_f SBcAP_Send_Write_Replace_Warning_Indication_free;
 | 
			
		||||
asn_struct_print_f SBcAP_Send_Write_Replace_Warning_Indication_print;
 | 
			
		||||
asn_constr_check_f SBcAP_Send_Write_Replace_Warning_Indication_constraint;
 | 
			
		||||
per_type_decoder_f SBcAP_Send_Write_Replace_Warning_Indication_decode_aper;
 | 
			
		||||
per_type_encoder_f SBcAP_Send_Write_Replace_Warning_Indication_encode_aper;
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,12 +29,12 @@ typedef long	 SBcAP_Stop_All_Indicator_t;
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_per_constraints_t asn_PER_type_SBcAP_Stop_All_Indicator_constr_1;
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_Stop_All_Indicator;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_Stop_All_Indicator_specs_1;
 | 
			
		||||
asn_struct_free_f Stop_All_Indicator_free;
 | 
			
		||||
asn_struct_print_f Stop_All_Indicator_print;
 | 
			
		||||
asn_constr_check_f Stop_All_Indicator_constraint;
 | 
			
		||||
per_type_decoder_f Stop_All_Indicator_decode_aper;
 | 
			
		||||
per_type_encoder_f Stop_All_Indicator_encode_aper;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_SBcAP_Stop_All_Indicator_specs_1;
 | 
			
		||||
asn_struct_free_f SBcAP_Stop_All_Indicator_free;
 | 
			
		||||
asn_struct_print_f SBcAP_Stop_All_Indicator_print;
 | 
			
		||||
asn_constr_check_f SBcAP_Stop_All_Indicator_constraint;
 | 
			
		||||
per_type_decoder_f SBcAP_Stop_All_Indicator_decode_aper;
 | 
			
		||||
per_type_encoder_f SBcAP_Stop_All_Indicator_encode_aper;
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,8 @@ typedef struct SBcAP_Stop_Warning_Indication {
 | 
			
		||||
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_Stop_Warning_Indication;
 | 
			
		||||
extern asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Stop_Warning_Indication_specs_1;
 | 
			
		||||
extern asn_TYPE_member_t asn_MBR_SBcAP_Stop_Warning_Indication_1[2];
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,8 @@ typedef struct SBcAP_Stop_Warning_Request {
 | 
			
		||||
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_Stop_Warning_Request;
 | 
			
		||||
extern asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Stop_Warning_Request_specs_1;
 | 
			
		||||
extern asn_TYPE_member_t asn_MBR_SBcAP_Stop_Warning_Request_1[2];
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,8 @@ typedef struct SBcAP_Stop_Warning_Response {
 | 
			
		||||
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_Stop_Warning_Response;
 | 
			
		||||
extern asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Stop_Warning_Response_specs_1;
 | 
			
		||||
extern asn_TYPE_member_t asn_MBR_SBcAP_Stop_Warning_Response_1[2];
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -32,12 +32,12 @@ typedef long	 SBcAP_TriggeringMessage_t;
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_per_constraints_t asn_PER_type_SBcAP_TriggeringMessage_constr_1;
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_TriggeringMessage;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_TriggeringMessage_specs_1;
 | 
			
		||||
asn_struct_free_f TriggeringMessage_free;
 | 
			
		||||
asn_struct_print_f TriggeringMessage_print;
 | 
			
		||||
asn_constr_check_f TriggeringMessage_constraint;
 | 
			
		||||
per_type_decoder_f TriggeringMessage_decode_aper;
 | 
			
		||||
per_type_encoder_f TriggeringMessage_encode_aper;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_SBcAP_TriggeringMessage_specs_1;
 | 
			
		||||
asn_struct_free_f SBcAP_TriggeringMessage_free;
 | 
			
		||||
asn_struct_print_f SBcAP_TriggeringMessage_print;
 | 
			
		||||
asn_constr_check_f SBcAP_TriggeringMessage_constraint;
 | 
			
		||||
per_type_decoder_f SBcAP_TriggeringMessage_decode_aper;
 | 
			
		||||
per_type_encoder_f SBcAP_TriggeringMessage_encode_aper;
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -33,12 +33,12 @@ typedef long	 SBcAP_TypeOfError_t;
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_per_constraints_t asn_PER_type_SBcAP_TypeOfError_constr_1;
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_TypeOfError;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_TypeOfError_specs_1;
 | 
			
		||||
asn_struct_free_f TypeOfError_free;
 | 
			
		||||
asn_struct_print_f TypeOfError_print;
 | 
			
		||||
asn_constr_check_f TypeOfError_constraint;
 | 
			
		||||
per_type_decoder_f TypeOfError_decode_aper;
 | 
			
		||||
per_type_encoder_f TypeOfError_encode_aper;
 | 
			
		||||
extern const asn_INTEGER_specifics_t asn_SPC_SBcAP_TypeOfError_specs_1;
 | 
			
		||||
asn_struct_free_f SBcAP_TypeOfError_free;
 | 
			
		||||
asn_struct_print_f SBcAP_TypeOfError_print;
 | 
			
		||||
asn_constr_check_f SBcAP_TypeOfError_constraint;
 | 
			
		||||
per_type_decoder_f SBcAP_TypeOfError_decode_aper;
 | 
			
		||||
per_type_encoder_f SBcAP_TypeOfError_encode_aper;
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,8 @@ typedef struct SBcAP_Write_Replace_Warning_Indication {
 | 
			
		||||
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_Write_Replace_Warning_Indication;
 | 
			
		||||
extern asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Write_Replace_Warning_Indication_specs_1;
 | 
			
		||||
extern asn_TYPE_member_t asn_MBR_SBcAP_Write_Replace_Warning_Indication_1[2];
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,8 @@ typedef struct SBcAP_Write_Replace_Warning_Request {
 | 
			
		||||
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_Write_Replace_Warning_Request;
 | 
			
		||||
extern asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Write_Replace_Warning_Request_specs_1;
 | 
			
		||||
extern asn_TYPE_member_t asn_MBR_SBcAP_Write_Replace_Warning_Request_1[2];
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,8 @@ typedef struct SBcAP_Write_Replace_Warning_Response {
 | 
			
		||||
 | 
			
		||||
/* Implementation */
 | 
			
		||||
extern asn_TYPE_descriptor_t asn_DEF_SBcAP_Write_Replace_Warning_Response;
 | 
			
		||||
extern asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Write_Replace_Warning_Response_specs_1;
 | 
			
		||||
extern asn_TYPE_member_t asn_MBR_SBcAP_Write_Replace_Warning_Response_1[2];
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -118,8 +118,8 @@
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/logging.h>
 | 
			
		||||
 | 
			
		||||
extern int _sbcap_DSBCAP;
 | 
			
		||||
#define SBC_AP_DEBUG(x, args ...) DEBUGP(_sbcap_DSBCAP, x, ## args)
 | 
			
		||||
extern int _sbcap_DASN1C;
 | 
			
		||||
#define SBC_AP_DEBUG(x, args ...) DEBUGP(_sbcap_DASN1C, x, ## args)
 | 
			
		||||
 | 
			
		||||
extern int asn1_xer_print;
 | 
			
		||||
 | 
			
		||||
@@ -137,12 +137,22 @@ void sbcap_pdu_free(SBcAP_SBC_AP_PDU_t *pdu);
 | 
			
		||||
struct msgb *sbcap_encode(SBcAP_SBC_AP_PDU_t *pdu);
 | 
			
		||||
SBcAP_SBC_AP_PDU_t *sbcap_decode(const struct msgb *msg);
 | 
			
		||||
 | 
			
		||||
const char *sbcap_procedure_code_str(SBcAP_ProcedureCode_t pc);
 | 
			
		||||
const char *sbcap_cause_str(SBcAP_Cause_t cause);
 | 
			
		||||
 | 
			
		||||
void sbcap_set_log_area(int log_area);
 | 
			
		||||
void sbcap_set_log_area(int log_area_sbcap, int log_area_asn1c);
 | 
			
		||||
 | 
			
		||||
SBcAP_ProcedureCode_t sbcap_pdu_get_procedure_code(const SBcAP_SBC_AP_PDU_t *pdu);
 | 
			
		||||
SBcAP_Criticality_t sbcap_pdu_get_criticality(const SBcAP_SBC_AP_PDU_t *pdu);
 | 
			
		||||
const char *sbcap_pdu_get_name(const SBcAP_SBC_AP_PDU_t *pdu);
 | 
			
		||||
 | 
			
		||||
void *sbcap_as_find_ie(void *void_list, SBcAP_ProtocolIE_ID_t ie_id);
 | 
			
		||||
 | 
			
		||||
SBcAP_Write_Replace_Warning_Request_IEs_t *sbcap_alloc_Write_Replace_Warning_Request_IE(
 | 
			
		||||
	long id, SBcAP_Criticality_t criticality, SBcAP_Write_Replace_Warning_Request_IEs__value_PR present);
 | 
			
		||||
 | 
			
		||||
SBcAP_Stop_Warning_Request_IEs_t *sbcap_alloc_Stop_Warning_Request_IE(
 | 
			
		||||
	long id, SBcAP_Criticality_t criticality, SBcAP_Stop_Warning_Request_IEs__value_PR present);
 | 
			
		||||
 | 
			
		||||
SBcAP_ErrorIndicationIEs_t *sbcap_alloc_Error_Indication_IE(
 | 
			
		||||
	long id, SBcAP_Criticality_t criticality, SBcAP_Stop_Warning_Request_IEs__value_PR present);
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/logging.h>
 | 
			
		||||
 | 
			
		||||
extern int _sbcap_DSBCAP;
 | 
			
		||||
#define SBC_AP_ASN_DEBUG(x, args ...) DEBUGP(_sbcap_DSBCAP, x "\n", ## args)
 | 
			
		||||
extern int _sbcap_DASN1C;
 | 
			
		||||
#define SBC_AP_ASN_DEBUG(x, args ...) DEBUGP(_sbcap_DASN1C, x "\n", ## args)
 | 
			
		||||
 | 
			
		||||
#define	ASN_DEBUG	SBC_AP_ASN_DEBUG
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								include/osmocom/sbcap/version.h.tpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								include/osmocom/sbcap/version.h.tpl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#define LIBOSMO_SBCAP_VERSION {{VERSION}}
 | 
			
		||||
#define LIBOSMO_SBCAP_VERSION_STR "{{VERSION}}"
 | 
			
		||||
 | 
			
		||||
#define LIBOSMO_SBCAP_VERSION_MAJOR {{VERSION_MAJOR}}
 | 
			
		||||
#define LIBOSMO_SBCAP_VERSION_MINOR {{VERSION_MINOR}}
 | 
			
		||||
#define LIBOSMO_SBCAP_VERSION_PATCH {{VERSION_PATCH}}
 | 
			
		||||
 | 
			
		||||
#define LIBOSMO_SBCAP_VERSION_GREATER_EQUAL(major, minor, patch) \
 | 
			
		||||
	(LIBOSMO_SBCAP_VERSION_MAJOR > (major) || \
 | 
			
		||||
	 (LIBOSMO_SBCAP_VERSION_MAJOR == (major) && \
 | 
			
		||||
	  LIBOSMO_SBCAP_VERSION_MINOR > (minor)) || \
 | 
			
		||||
	 (LIBOSMO_SBCAP_VERSION_MAJOR == (major) && \
 | 
			
		||||
	  LIBOSMO_SBCAP_VERSION_MINOR == (minor) && \
 | 
			
		||||
	  LIBOSMO_SBCAP_VERSION_PATCH >= (patch)))
 | 
			
		||||
@@ -17,21 +17,30 @@ osmo_cbc_SOURCES = \
 | 
			
		||||
	cbc_vty.c \
 | 
			
		||||
	cbsp_link.c \
 | 
			
		||||
	cbsp_link_fsm.c \
 | 
			
		||||
	cbsp_msg.c \
 | 
			
		||||
	cbsp_smscb_peer_fsm.c \
 | 
			
		||||
	rest_api.c \
 | 
			
		||||
	charset.c \
 | 
			
		||||
	message_handling.c \
 | 
			
		||||
	rest_it_op.c \
 | 
			
		||||
	sbcap_msg.c \
 | 
			
		||||
	sbcap_link.c \
 | 
			
		||||
	sbcap_link_fsm.c \
 | 
			
		||||
	smscb_peer_fsm.c \
 | 
			
		||||
	sbcap_smscb_peer_fsm.c \
 | 
			
		||||
	smscb_message_fsm.c \
 | 
			
		||||
	smscb_peer_fsm.c \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
osmo_cbc_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) \
 | 
			
		||||
		 $(LIBOSMONETIF_LIBS) \
 | 
			
		||||
		 $(ULFIUS_LIBS) $(JANSSON_LIBS) $(ORCANIA_LIBS) $(LIBSCTP_LIBS) \
 | 
			
		||||
		 sbcap/libosmo-sbcap.la
 | 
			
		||||
osmo_cbc_LDADD = \
 | 
			
		||||
	sbcap/libosmo-sbcap.la \
 | 
			
		||||
	$(LIBOSMOCORE_LIBS) \
 | 
			
		||||
	$(LIBOSMOGSM_LIBS) \
 | 
			
		||||
	$(LIBOSMOVTY_LIBS) \
 | 
			
		||||
	$(LIBOSMONETIF_LIBS) \
 | 
			
		||||
	$(ULFIUS_LIBS) \
 | 
			
		||||
	$(JANSSON_LIBS) \
 | 
			
		||||
	$(ORCANIA_LIBS) \
 | 
			
		||||
	$(LIBSCTP_LIBS) \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
regen:
 | 
			
		||||
	$(MAKE) -C sbcap regen
 | 
			
		||||
 
 | 
			
		||||
@@ -35,6 +35,46 @@
 | 
			
		||||
#include <osmocom/cbc/rest_it_op.h>
 | 
			
		||||
#include <osmocom/cbc/debug.h>
 | 
			
		||||
 | 
			
		||||
const char *cbc_cell_id2str(const struct cbc_cell_id *cid)
 | 
			
		||||
{
 | 
			
		||||
	static char buf[256];
 | 
			
		||||
 | 
			
		||||
	switch (cid->id_discr) {
 | 
			
		||||
	case CBC_CELL_ID_NONE:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "NONE");
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_BSS:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "BSS");
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_CGI:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "CGI %s", osmo_cgi_name(&cid->u.cgi));
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_LAC_CI:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "LAC %u CI %u", cid->u.lac_and_ci.lac, cid->u.lac_and_ci.ci);
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_LAI:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "LAI %s", osmo_lai_name(&cid->u.lai));
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_LAC:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "LAC %u", cid->u.lac);
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_CI:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "CI %u", cid->u.ci);
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_ECGI:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "ECGI %s-%05X-%02X", osmo_plmn_name(&cid->u.ecgi.plmn),
 | 
			
		||||
			 cid->u.ecgi.eci >> 8, cid->u.ecgi.eci & 0xff);
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_TAI:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "TAI %s-%u", osmo_plmn_name(&cid->u.tai.plmn), cid->u.tai.tac);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "<invalid>");
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct cbc *cbc_alloc(void *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc *cbc;
 | 
			
		||||
@@ -45,7 +85,9 @@ struct cbc *cbc_alloc(void *ctx)
 | 
			
		||||
	INIT_LLIST_HEAD(&cbc->expired_messages);
 | 
			
		||||
	cbc->config.cbsp.local_host = talloc_strdup(cbc, "127.0.0.1");
 | 
			
		||||
	cbc->config.cbsp.local_port = CBSP_TCP_PORT;
 | 
			
		||||
	/* cbc->config.sbcap local_host set up during VTY (and vty_go_parent) */
 | 
			
		||||
	/* Due to SCTP multi-home support, cbc->config.sbcap.local_host is not set here,
 | 
			
		||||
	 * but through VTY (user or vty_go_parent()), or if not set default is set after
 | 
			
		||||
	 * VTY cfg read, during cbc_start(). */
 | 
			
		||||
	cbc->config.sbcap.local_port = SBcAP_SCTP_PORT;
 | 
			
		||||
	cbc->config.ecbe.local_host = talloc_strdup(cbc, "127.0.0.1");
 | 
			
		||||
	cbc->config.ecbe.local_port = 12345;
 | 
			
		||||
@@ -63,6 +105,17 @@ struct cbc *cbc_alloc(void *ctx)
 | 
			
		||||
	return cbc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* If no local addr set, add a default one: */
 | 
			
		||||
void cbc_add_sbcap_default_local_host_if_needed(struct cbc *cbc)
 | 
			
		||||
{
 | 
			
		||||
	if (g_cbc->config.sbcap.num_local_host > 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	g_cbc->config.sbcap.local_host[0] = talloc_strdup(g_cbc, "127.0.0.1");
 | 
			
		||||
	g_cbc->config.sbcap.local_host[1] = talloc_strdup(g_cbc, "::1");
 | 
			
		||||
	g_cbc->config.sbcap.num_local_host = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cbc_start(struct cbc *cbc)
 | 
			
		||||
{
 | 
			
		||||
	void *tall_rest_ctx;
 | 
			
		||||
@@ -75,6 +128,12 @@ int cbc_start(struct cbc *cbc)
 | 
			
		||||
		return rc;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* User didn't configure an SBcAP node with a local address, use default: */
 | 
			
		||||
	if (!cbc->config.sbcap.configured) {
 | 
			
		||||
		cbc_add_sbcap_default_local_host_if_needed(cbc);
 | 
			
		||||
		cbc->config.sbcap.configured = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((rc = cbc_sbcap_mgr_open_srv(cbc->sbcap.mgr)) < 0) {
 | 
			
		||||
		LOGP(DMAIN, LOGL_ERROR, "Error binding SBc-AP port\n");
 | 
			
		||||
		return rc;
 | 
			
		||||
 
 | 
			
		||||
@@ -35,6 +35,7 @@
 | 
			
		||||
#include <osmocom/core/utils.h>
 | 
			
		||||
#include <osmocom/core/logging.h>
 | 
			
		||||
#include <osmocom/core/application.h>
 | 
			
		||||
#include <osmocom/core/fsm.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/vty/vty.h>
 | 
			
		||||
#include <osmocom/vty/stats.h>
 | 
			
		||||
@@ -44,9 +45,12 @@
 | 
			
		||||
#include <osmocom/vty/logging.h>
 | 
			
		||||
#include <osmocom/vty/misc.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sbcap/sbcap_common.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/cbc/debug.h>
 | 
			
		||||
#include <osmocom/cbc/cbc_data.h>
 | 
			
		||||
#include <osmocom/cbc/cbc_vty.h>
 | 
			
		||||
#include <osmocom/cbc/cbc_peer.h>
 | 
			
		||||
 | 
			
		||||
static void *tall_cbc_ctx;
 | 
			
		||||
struct cbc *g_cbc;
 | 
			
		||||
@@ -59,6 +63,13 @@ static const struct log_info_cat log_info_cat[] = {
 | 
			
		||||
		.enabled = 1,
 | 
			
		||||
		.loglevel = LOGL_NOTICE,
 | 
			
		||||
	},
 | 
			
		||||
	[DSMSCB] = {
 | 
			
		||||
		.name = "DSMSCB",
 | 
			
		||||
		.description = "SMS Cell Broadcast handling",
 | 
			
		||||
		.color = "\033[1;35m",
 | 
			
		||||
		.enabled = 1,
 | 
			
		||||
		.loglevel = LOGL_NOTICE,
 | 
			
		||||
	},
 | 
			
		||||
	[DCBSP] = {
 | 
			
		||||
		.name = "DCBSP",
 | 
			
		||||
		.description = "Cell Broadcast Service Protocol (CBC-BSC)",
 | 
			
		||||
@@ -73,6 +84,13 @@ static const struct log_info_cat log_info_cat[] = {
 | 
			
		||||
		.enabled = 1,
 | 
			
		||||
		.loglevel = LOGL_NOTICE,
 | 
			
		||||
	},
 | 
			
		||||
	[DASN1C] = {
 | 
			
		||||
		.name = "DASN1C",
 | 
			
		||||
		.description = "SBc-AP ASN1C enc/dec",
 | 
			
		||||
		.color = "\033[1;34m",
 | 
			
		||||
		.enabled = 1,
 | 
			
		||||
		.loglevel = LOGL_NOTICE,
 | 
			
		||||
	},
 | 
			
		||||
	[DREST] = {
 | 
			
		||||
		.name = "DREST",
 | 
			
		||||
		.description = "REST interface",
 | 
			
		||||
@@ -90,12 +108,18 @@ static const struct log_info log_info = {
 | 
			
		||||
static int cbc_vty_go_parent(struct vty *vty)
 | 
			
		||||
{
 | 
			
		||||
	switch (vty->node) {
 | 
			
		||||
	case CBSP_NODE:
 | 
			
		||||
		g_cbc->config.cbsp.configured = true;
 | 
			
		||||
		break;
 | 
			
		||||
	case SBcAP_NODE:
 | 
			
		||||
		/* If no local addr set, add a default one: */
 | 
			
		||||
		if (g_cbc->config.sbcap.num_local_host == 0) {
 | 
			
		||||
			g_cbc->config.sbcap.local_host[0] = talloc_strdup(g_cbc, "127.0.0.1");
 | 
			
		||||
				g_cbc->config.sbcap.num_local_host = 1;
 | 
			
		||||
		}
 | 
			
		||||
		cbc_add_sbcap_default_local_host_if_needed(g_cbc);
 | 
			
		||||
		g_cbc->config.sbcap.configured = true;
 | 
			
		||||
		vty->node = CONFIG_NODE;
 | 
			
		||||
		vty->index = NULL;
 | 
			
		||||
		break;
 | 
			
		||||
	case PEER_NODE:
 | 
			
		||||
		cbc_peer_apply_cfg_chg((struct cbc_peer *)vty->index);
 | 
			
		||||
		vty->node = CONFIG_NODE;
 | 
			
		||||
		vty->index = NULL;
 | 
			
		||||
		break;
 | 
			
		||||
@@ -120,7 +144,6 @@ static struct vty_app_info vty_info = {
 | 
			
		||||
	.copyright = cbc_copyright,
 | 
			
		||||
	.go_parent_cb	= cbc_vty_go_parent,
 | 
			
		||||
	.version = PACKAGE_VERSION,
 | 
			
		||||
	.is_config_node = NULL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct {
 | 
			
		||||
@@ -244,7 +267,11 @@ int main(int argc, char **argv)
 | 
			
		||||
	msgb_talloc_ctx_init(tall_cbc_ctx, 0);
 | 
			
		||||
	osmo_init_logging2(tall_cbc_ctx, &log_info);
 | 
			
		||||
	log_enable_multithread();
 | 
			
		||||
	sbcap_set_log_area(DSBcAP, DASN1C);
 | 
			
		||||
	osmo_stats_init(tall_cbc_ctx);
 | 
			
		||||
	osmo_fsm_log_timeouts(true);
 | 
			
		||||
 | 
			
		||||
	vty_info.tall_ctx = tall_cbc_ctx;
 | 
			
		||||
	vty_init(&vty_info);
 | 
			
		||||
 | 
			
		||||
	g_cbc = cbc_alloc(tall_cbc_ctx);
 | 
			
		||||
@@ -255,6 +282,8 @@ int main(int argc, char **argv)
 | 
			
		||||
 | 
			
		||||
	logging_vty_add_cmds();
 | 
			
		||||
	osmo_fsm_vty_add_cmds();
 | 
			
		||||
	osmo_stats_vty_add_cmds();
 | 
			
		||||
	osmo_talloc_vty_add_cmds();
 | 
			
		||||
 | 
			
		||||
	rc = vty_read_config_file(cmdline_config.config_file, NULL);
 | 
			
		||||
	if (rc < 0) {
 | 
			
		||||
@@ -263,7 +292,7 @@ int main(int argc, char **argv)
 | 
			
		||||
		exit(1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rc = telnet_init_dynif(tall_cbc_ctx, NULL, vty_get_bind_addr(), OSMO_VTY_PORT_CBC);
 | 
			
		||||
	rc = telnet_init_default(tall_cbc_ctx, NULL, OSMO_VTY_PORT_CBC);
 | 
			
		||||
	if (rc < 0) {
 | 
			
		||||
		perror("Error binding VTY port");
 | 
			
		||||
		exit(1);
 | 
			
		||||
 
 | 
			
		||||
@@ -27,8 +27,146 @@
 | 
			
		||||
#include <osmocom/core/linuxlist.h>
 | 
			
		||||
#include <osmocom/core/talloc.h>
 | 
			
		||||
#include <osmocom/core/utils.h>
 | 
			
		||||
#include <osmocom/core/logging.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/cbc/cbsp_msg.h>
 | 
			
		||||
#include <osmocom/cbc/cbsp_link.h>
 | 
			
		||||
#include <osmocom/cbc/sbcap_msg.h>
 | 
			
		||||
#include <osmocom/cbc/sbcap_link.h>
 | 
			
		||||
#include <osmocom/cbc/cbc_message.h>
 | 
			
		||||
#include <osmocom/cbc/cbc_peer.h>
 | 
			
		||||
#include <osmocom/cbc/debug.h>
 | 
			
		||||
#include <osmocom/cbc/rest_it_op.h>
 | 
			
		||||
#include <osmocom/cbc/smscb_message_fsm.h>
 | 
			
		||||
 | 
			
		||||
/* determine if peer is within scope of cbc_msg */
 | 
			
		||||
static bool is_peer_in_scope(const struct cbc_peer *peer, const struct cbc_message *cbcmsg)
 | 
			
		||||
{
 | 
			
		||||
	switch (cbcmsg->scope) {
 | 
			
		||||
	case CBC_MSG_SCOPE_PLMN:
 | 
			
		||||
		return true;
 | 
			
		||||
	/* FIXME: differnt scopes */
 | 
			
		||||
	default:
 | 
			
		||||
		OSMO_ASSERT(0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* send given new message to given peer */
 | 
			
		||||
int peer_new_cbc_message(struct cbc_peer *peer, struct cbc_message *cbcmsg)
 | 
			
		||||
{
 | 
			
		||||
	struct osmo_cbsp_decoded *cbsp;
 | 
			
		||||
	SBcAP_SBC_AP_PDU_t *sbcap;
 | 
			
		||||
 | 
			
		||||
	switch (peer->proto) {
 | 
			
		||||
	case CBC_PEER_PROTO_CBSP:
 | 
			
		||||
		/* skip peers without any current CBSP connection */
 | 
			
		||||
		if (!peer->link.cbsp) {
 | 
			
		||||
			LOGP(DCBSP, LOGL_NOTICE, "[%s] Tx CBSP: not connected\n",
 | 
			
		||||
			     peer->name);
 | 
			
		||||
			return -ENOTCONN;
 | 
			
		||||
		}
 | 
			
		||||
		if (!(cbsp = cbsp_gen_write_replace_req(peer, cbcmsg))) {
 | 
			
		||||
			LOGP(DCBSP, LOGL_ERROR, "[%s] Tx CBSP: msg gen failed\n",
 | 
			
		||||
			     peer->name);
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		return cbc_cbsp_link_tx(peer->link.cbsp, cbsp);
 | 
			
		||||
 | 
			
		||||
	case CBC_PEER_PROTO_SBcAP:
 | 
			
		||||
		/* skip peers without any current SBc-AP connection */
 | 
			
		||||
		if (!peer->link.sbcap) {
 | 
			
		||||
			LOGP(DSBcAP, LOGL_NOTICE, "[%s] Tx SBc-AP: not connected\n",
 | 
			
		||||
			     peer->name);
 | 
			
		||||
			return -ENOTCONN;
 | 
			
		||||
		}
 | 
			
		||||
		if (!(sbcap = sbcap_gen_write_replace_warning_req(peer, cbcmsg))) {
 | 
			
		||||
			LOGP(DSBcAP, LOGL_ERROR, "[%s] Tx SBc-AP: msg gen failed\n",
 | 
			
		||||
			     peer->name);
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		return cbc_sbcap_link_tx(peer->link.sbcap, sbcap);
 | 
			
		||||
 | 
			
		||||
	case CBC_PEER_PROTO_SABP:
 | 
			
		||||
		LOGP(DLGLOBAL, LOGL_ERROR, "Sending message to peer proto %s not implemented!\n",
 | 
			
		||||
		     get_value_string(cbc_peer_proto_name, peer->proto));
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		OSMO_ASSERT(0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* receive a new CBC message from the user (REST). Allocates new memory,
 | 
			
		||||
 * a FSM, copies data from 'orig', routes to all peers and starts FSMs.
 | 
			
		||||
 * Once the operation is complete (success, error, timeout) we must
 | 
			
		||||
 * notify osmo_it_q of the completion */
 | 
			
		||||
int cbc_message_new(const struct cbc_message *orig, struct rest_it_op *op)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_message *cbcmsg = cbc_message_alloc(g_cbc, orig);
 | 
			
		||||
	struct cbc_peer *peer;
 | 
			
		||||
 | 
			
		||||
	if (!cbcmsg) {
 | 
			
		||||
		rest_it_op_set_http_result(op, 409, "Could not allocate");
 | 
			
		||||
		rest_it_op_complete(op);
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	OSMO_ASSERT(llist_empty(&cbcmsg->peers));
 | 
			
		||||
 | 
			
		||||
	/* iterate over all peers */
 | 
			
		||||
	llist_for_each_entry(peer, &g_cbc->peers, list) {
 | 
			
		||||
		struct cbc_message_peer *mp;
 | 
			
		||||
 | 
			
		||||
		if (!is_peer_in_scope(peer, cbcmsg))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		/* allocate new cbc_mesage_peer + related FSM */
 | 
			
		||||
		mp = smscb_peer_fsm_alloc(peer, cbcmsg);
 | 
			
		||||
		if (!mp) {
 | 
			
		||||
			LOGP(DCBSP, LOGL_ERROR, "Cannot allocate cbc_message_peer\n");
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* kick off the state machine[s] */
 | 
			
		||||
	if (osmo_fsm_inst_dispatch(cbcmsg->fi, SMSCB_MSG_E_CREATE, op) < 0) {
 | 
			
		||||
		rest_it_op_set_http_result(op, 500, "Illegal FSM event");
 | 
			
		||||
		rest_it_op_complete(op);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* we continue in the FSM after the WRITE_ACK event was received */
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cbc_message_delete(struct cbc_message *cbcmsg, struct rest_it_op *op)
 | 
			
		||||
{
 | 
			
		||||
	if (osmo_fsm_inst_dispatch(cbcmsg->fi, SMSCB_MSG_E_DELETE, op) < 0) {
 | 
			
		||||
		rest_it_op_set_http_result(op, 500, "Illegal FSM event");
 | 
			
		||||
		rest_it_op_complete(op);
 | 
			
		||||
	}
 | 
			
		||||
	/* we continue in the FSM after the DELETE_ACK event was received */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct cbc_message *cbc_message_by_id(uint16_t message_id)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_message *cbc_msg;
 | 
			
		||||
	llist_for_each_entry(cbc_msg, &g_cbc->messages, list) {
 | 
			
		||||
		if (cbc_msg->msg.message_id == message_id)
 | 
			
		||||
			return cbc_msg;
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct cbc_message *cbc_message_expired_by_id(uint16_t message_id)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_message *cbc_msg;
 | 
			
		||||
	llist_for_each_entry(cbc_msg, &g_cbc->expired_messages, list) {
 | 
			
		||||
		if (cbc_msg->msg.message_id == message_id)
 | 
			
		||||
			return cbc_msg;
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* remove a peer from the message */
 | 
			
		||||
int cbc_message_del_peer(struct cbc_message *cbcmsg, struct cbc_peer *peer)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										116
									
								
								src/cbc_peer.c
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								src/cbc_peer.c
									
									
									
									
									
								
							@@ -32,6 +32,7 @@
 | 
			
		||||
#include <osmocom/cbc/cbc_peer.h>
 | 
			
		||||
#include <osmocom/cbc/cbsp_link.h>
 | 
			
		||||
#include <osmocom/cbc/sbcap_link.h>
 | 
			
		||||
#include <osmocom/cbc/debug.h>
 | 
			
		||||
 | 
			
		||||
const struct value_string cbc_peer_proto_name[] = {
 | 
			
		||||
	{ CBC_PEER_PROTO_CBSP, "CBSP" },
 | 
			
		||||
@@ -40,6 +41,14 @@ const struct value_string cbc_peer_proto_name[] = {
 | 
			
		||||
	{ 0, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const struct value_string cbc_peer_link_mode_names[] = {
 | 
			
		||||
	{ CBC_PEER_LINK_MODE_DISABLED, "disabled" },
 | 
			
		||||
	{ CBC_PEER_LINK_MODE_SERVER, "server" },
 | 
			
		||||
	{ CBC_PEER_LINK_MODE_CLIENT, "client" },
 | 
			
		||||
	{}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* create a new cbc_peer */
 | 
			
		||||
struct cbc_peer *cbc_peer_create(const char *name, enum cbc_peer_protocol proto)
 | 
			
		||||
{
 | 
			
		||||
@@ -120,3 +129,110 @@ struct cbc_peer *cbc_peer_by_addr_proto(const char *remote_host, uint16_t remote
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int cbc_peer_apply_cfg_chg_cbsp(struct cbc_peer *peer)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_cbsp_link *link = peer->link.cbsp;
 | 
			
		||||
	int rc = 0;
 | 
			
		||||
 | 
			
		||||
	switch (peer->link_mode) {
 | 
			
		||||
	case CBC_PEER_LINK_MODE_DISABLED:
 | 
			
		||||
		if (link) {
 | 
			
		||||
			LOGPCC(link, LOGL_NOTICE,
 | 
			
		||||
			       "link mode changed to 'disabled', closing active link\n");
 | 
			
		||||
			cbc_cbsp_link_close(link);
 | 
			
		||||
		}
 | 
			
		||||
		/* Nothing to be done, cbc_cbsp_mgr->srv_link will refuse
 | 
			
		||||
		 * accepting() disabled peers. */
 | 
			
		||||
		OSMO_ASSERT(!peer->link.cbsp);
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_PEER_LINK_MODE_SERVER:
 | 
			
		||||
		if (link && link->is_client) {
 | 
			
		||||
			LOGPCC(link, LOGL_NOTICE,
 | 
			
		||||
			       "link mode changed 'client' -> 'server', closing active link\n");
 | 
			
		||||
			cbc_cbsp_link_close(link);
 | 
			
		||||
		}
 | 
			
		||||
		/* Nothing to be done, cbc_cbsp_mgr->srv_link will accept() and
 | 
			
		||||
		 * recreate the link */
 | 
			
		||||
		OSMO_ASSERT(!peer->link.cbsp);
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_PEER_LINK_MODE_CLIENT:
 | 
			
		||||
		if (link) {
 | 
			
		||||
			if (link->is_client) {
 | 
			
		||||
				/* nothing to be done, cli link already created */
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			LOGPCC(link, LOGL_NOTICE,
 | 
			
		||||
			       "link mode changed 'server' -> 'client', closing active link\n");
 | 
			
		||||
			cbc_cbsp_link_close(link);
 | 
			
		||||
		}
 | 
			
		||||
		OSMO_ASSERT(!peer->link.cbsp);
 | 
			
		||||
		link = cbc_cbsp_link_alloc(g_cbc->cbsp.mgr, peer);
 | 
			
		||||
		peer->link.cbsp = link;
 | 
			
		||||
		rc = cbc_cbsp_link_open_cli(link);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int cbc_peer_apply_cfg_chg_sbcap(struct cbc_peer *peer)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_sbcap_link *link = peer->link.sbcap;
 | 
			
		||||
	int rc = 0;
 | 
			
		||||
 | 
			
		||||
	switch (peer->link_mode) {
 | 
			
		||||
	case CBC_PEER_LINK_MODE_DISABLED:
 | 
			
		||||
		if (link) {
 | 
			
		||||
			LOGPSBCAPC(link, LOGL_NOTICE,
 | 
			
		||||
				   "link mode changed to 'disabled', closing active link\n");
 | 
			
		||||
			cbc_sbcap_link_close(link);
 | 
			
		||||
		}
 | 
			
		||||
		/* Nothing to be done, cbc_sbcap_mgr->srv_link will refuse
 | 
			
		||||
		 * accepting() disabled peers. */
 | 
			
		||||
		OSMO_ASSERT(!peer->link.sbcap);
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_PEER_LINK_MODE_SERVER:
 | 
			
		||||
		if (link && link->is_client) {
 | 
			
		||||
			LOGPSBCAPC(link, LOGL_NOTICE,
 | 
			
		||||
				   "link mode changed 'client' -> 'server', closing active link\n");
 | 
			
		||||
			cbc_sbcap_link_close(link);
 | 
			
		||||
		}
 | 
			
		||||
		/* Nothing to be done, cbc_sbcap_mgr->srv_link will accept() and
 | 
			
		||||
		 * recreate the link */
 | 
			
		||||
		OSMO_ASSERT(!peer->link.sbcap);
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_PEER_LINK_MODE_CLIENT:
 | 
			
		||||
		if (link) {
 | 
			
		||||
			if (link->is_client) {
 | 
			
		||||
				/* nothing to be done, cli link already created */
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			LOGPSBCAPC(link, LOGL_NOTICE,
 | 
			
		||||
				   "link mode changed 'server' -> 'client', closing active link\n");
 | 
			
		||||
			cbc_sbcap_link_close(link);
 | 
			
		||||
		}
 | 
			
		||||
		OSMO_ASSERT(!peer->link.sbcap);
 | 
			
		||||
		link = cbc_sbcap_link_alloc(g_cbc->sbcap.mgr, peer);
 | 
			
		||||
		peer->link.sbcap = link;
 | 
			
		||||
		rc = cbc_sbcap_link_open_cli(link);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cbc_peer_apply_cfg_chg(struct cbc_peer *peer)
 | 
			
		||||
{
 | 
			
		||||
	int rc = -ENOTSUP;
 | 
			
		||||
 | 
			
		||||
	switch (peer->proto) {
 | 
			
		||||
	case CBC_PEER_PROTO_CBSP:
 | 
			
		||||
		rc = cbc_peer_apply_cfg_chg_cbsp(peer);
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_PEER_PROTO_SBcAP:
 | 
			
		||||
		rc = cbc_peer_apply_cfg_chg_sbcap(peer);
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_PEER_PROTO_SABP:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										141
									
								
								src/cbc_vty.c
									
									
									
									
									
								
							
							
						
						
									
										141
									
								
								src/cbc_vty.c
									
									
									
									
									
								
							@@ -102,13 +102,26 @@ DEFUN(show_peers, show_peers_cmd,
 | 
			
		||||
static void dump_one_cbc_msg(struct vty *vty, const struct cbc_message *cbc_msg)
 | 
			
		||||
{
 | 
			
		||||
	const struct smscb_message *smscb = &cbc_msg->msg;
 | 
			
		||||
	char str_created[32], str_expired[32];
 | 
			
		||||
	struct tm tm_created = {0};
 | 
			
		||||
	struct tm tm_expired = {0};
 | 
			
		||||
 | 
			
		||||
	OSMO_ASSERT(!smscb->is_etws);
 | 
			
		||||
 | 
			
		||||
	vty_out(vty, "| %04X| %04X|%-20s|%-13s|  %-4u|%c| %02x|%s",
 | 
			
		||||
	localtime_r(&cbc_msg->time.created, &tm_created);
 | 
			
		||||
	strftime(str_created, sizeof(str_created), "%Y-%m-%dT%H:%M:%SZ", &tm_created);
 | 
			
		||||
	if (cbc_msg->time.expired > 0) {
 | 
			
		||||
		localtime_r(&cbc_msg->time.expired, &tm_expired);
 | 
			
		||||
		strftime(str_expired, sizeof(str_expired), "%Y-%m-%dT%H:%M:%SZ", &tm_expired);
 | 
			
		||||
	} else {
 | 
			
		||||
		OSMO_STRLCPY_ARRAY(str_expired, "active");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vty_out(vty, "| %04X| %04X|%-20s|%-13s|  %-4u|%c| %02x|%-20s|%-20s|%s",
 | 
			
		||||
		smscb->message_id, smscb->serial_nr, cbc_msg->cbe_name,
 | 
			
		||||
		get_value_string(cbsp_category_names, cbc_msg->priority), cbc_msg->rep_period,
 | 
			
		||||
		cbc_msg->extended_cbch ? 'E' : 'N', smscb->cbs.dcs,
 | 
			
		||||
		str_created, str_expired,
 | 
			
		||||
		VTY_NEWLINE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -119,9 +132,11 @@ DEFUN(show_messages_cbs, show_messages_cbs_cmd,
 | 
			
		||||
	struct cbc_message *cbc_msg;
 | 
			
		||||
 | 
			
		||||
	vty_out(vty,
 | 
			
		||||
"|MsgId|SerNo|      CBE Name      |  Category   |Period|E|DCS|%s", VTY_NEWLINE);
 | 
			
		||||
"|MsgId|SerNo|      CBE Name      |  Category   |Period|E|DCS|       Created      |       Expired      |%s",
 | 
			
		||||
	VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty,
 | 
			
		||||
"|-----|-----|--------------------|-------------|------|-|---|%s", VTY_NEWLINE);
 | 
			
		||||
"|-----|-----|--------------------|-------------|------|-|---|--------------------|--------------------|%s",
 | 
			
		||||
	VTY_NEWLINE);
 | 
			
		||||
 | 
			
		||||
	llist_for_each_entry(cbc_msg, &g_cbc->messages, list) {
 | 
			
		||||
		if (cbc_msg->msg.is_etws)
 | 
			
		||||
@@ -138,37 +153,25 @@ DEFUN(show_messages_cbs, show_messages_cbs_cmd,
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *cbc_cell_id2str(const struct cbc_cell_id *cid)
 | 
			
		||||
DEFUN(delete_message_expired, delete_message_expired_cmd,
 | 
			
		||||
	"delete message expired id <0-65535>",
 | 
			
		||||
	"Delete message from the local expired list\n"
 | 
			
		||||
	"Delete message from the local expired list\n"
 | 
			
		||||
	"Delete message from the local expired list\n"
 | 
			
		||||
	"Message ID\n" "Message ID\n")
 | 
			
		||||
{
 | 
			
		||||
	static char buf[256];
 | 
			
		||||
 | 
			
		||||
	switch (cid->id_discr) {
 | 
			
		||||
	case CBC_CELL_ID_NONE:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "NONE");
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_BSS:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "BSS");
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_CGI:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "CGI %s", osmo_cgi_name(&cid->u.cgi));
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_LAC_CI:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "LAC %u CI %u", cid->u.lac_and_ci.lac, cid->u.lac_and_ci.ci);
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_LAI:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "LAI %s", osmo_lai_name(&cid->u.lai));
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_LAC:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "LAC %u", cid->u.lac);
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_CI:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "CI %u", cid->u.ci);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "<invalid>");
 | 
			
		||||
		break;
 | 
			
		||||
	struct cbc_message *cbc_msg;
 | 
			
		||||
	uint16_t msgid = atoi(argv[0]);
 | 
			
		||||
	cbc_msg = cbc_message_expired_by_id(msgid);
 | 
			
		||||
	if (!cbc_msg) {
 | 
			
		||||
		if (cbc_message_by_id(msgid))
 | 
			
		||||
			vty_out(vty, "Message ID %s has not yet expired!%s", argv[0], VTY_NEWLINE);
 | 
			
		||||
		else
 | 
			
		||||
			vty_out(vty, "Unknown expired Message ID %s%s", argv[0], VTY_NEWLINE);
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
	}
 | 
			
		||||
	return buf;
 | 
			
		||||
	cbc_message_free(cbc_msg);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dump_one_msg_peer(struct vty *vty, const struct cbc_message_peer *msg_peer, const char *pfx)
 | 
			
		||||
@@ -205,10 +208,13 @@ DEFUN(show_message_cbs, show_message_cbs_cmd,
 | 
			
		||||
	const struct smscb_message *smscb;
 | 
			
		||||
	struct cbc_message_peer *msg_peer;
 | 
			
		||||
	char *timestr;
 | 
			
		||||
	uint16_t msgid = atoi(argv[0]);
 | 
			
		||||
 | 
			
		||||
	cbc_msg = cbc_message_by_id(atoi(argv[0]));
 | 
			
		||||
	cbc_msg = cbc_message_by_id(msgid);
 | 
			
		||||
	if (!cbc_msg)
 | 
			
		||||
		cbc_msg = cbc_message_expired_by_id(msgid);
 | 
			
		||||
	if (!cbc_msg) {
 | 
			
		||||
		vty_out(vty, "Unknown Messsage ID %s%s", argv[0], VTY_NEWLINE);
 | 
			
		||||
		vty_out(vty, "Unknown Message ID %s%s", argv[0], VTY_NEWLINE);
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
	}
 | 
			
		||||
	smscb = &cbc_msg->msg;
 | 
			
		||||
@@ -251,13 +257,26 @@ DEFUN(show_message_cbs, show_message_cbs_cmd,
 | 
			
		||||
static void dump_one_etws_msg(struct vty *vty, const struct cbc_message *cbc_msg)
 | 
			
		||||
{
 | 
			
		||||
	const struct smscb_message *smscb = &cbc_msg->msg;
 | 
			
		||||
	char str_created[32], str_expired[32];
 | 
			
		||||
	struct tm tm_created = {0};
 | 
			
		||||
	struct tm tm_expired = {0};
 | 
			
		||||
 | 
			
		||||
	OSMO_ASSERT(smscb->is_etws);
 | 
			
		||||
 | 
			
		||||
	vty_out(vty, "| %04X| %04X|%-20s|%-13s|  %-4u|%c|      %04d|%s",
 | 
			
		||||
	localtime_r(&cbc_msg->time.created, &tm_created);
 | 
			
		||||
	strftime(str_created, sizeof(str_created), "%Y-%m-%dT%H:%M:%SZ", &tm_created);
 | 
			
		||||
	if (cbc_msg->time.expired > 0) {
 | 
			
		||||
		localtime_r(&cbc_msg->time.expired, &tm_expired);
 | 
			
		||||
		strftime(str_expired, sizeof(str_expired), "%Y-%m-%dT%H:%M:%SZ", &tm_expired);
 | 
			
		||||
	} else {
 | 
			
		||||
		OSMO_STRLCPY_ARRAY(str_expired, "active");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vty_out(vty, "| %04X| %04X|%-20s|%-13s|  %-4u|%c|        %04d|%-20s|%-20s|%s",
 | 
			
		||||
		smscb->message_id, smscb->serial_nr, cbc_msg->cbe_name,
 | 
			
		||||
		get_value_string(cbsp_category_names, cbc_msg->priority), cbc_msg->rep_period,
 | 
			
		||||
		cbc_msg->extended_cbch ? 'E' : 'N', smscb->etws.warning_type,
 | 
			
		||||
		str_created, str_expired,
 | 
			
		||||
		VTY_NEWLINE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -268,9 +287,11 @@ DEFUN(show_messages_etws, show_messages_etws_cmd,
 | 
			
		||||
	struct cbc_message *cbc_msg;
 | 
			
		||||
 | 
			
		||||
	vty_out(vty,
 | 
			
		||||
"|MsgId|SerNo|      CBE Name      |  Category   |Period|E|Warning Type|%s", VTY_NEWLINE);
 | 
			
		||||
"|MsgId|SerNo|      CBE Name      |  Category   |Period|E|Warning Type|       Created      |       Expired      |%s",
 | 
			
		||||
	VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty,
 | 
			
		||||
"|-----|-----|--------------------|-------------|------|-|------------|%s", VTY_NEWLINE);
 | 
			
		||||
"|-----|-----|--------------------|-------------|------|-|------------|--------------------|--------------------|%s",
 | 
			
		||||
	VTY_NEWLINE);
 | 
			
		||||
 | 
			
		||||
	llist_for_each_entry(cbc_msg, &g_cbc->messages, list) {
 | 
			
		||||
		if (!cbc_msg->msg.is_etws)
 | 
			
		||||
@@ -530,9 +551,10 @@ DEFUN_DEPRECATED(cfg_cbc_peer_old, cfg_cbc_peer_old_cmd,
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_peer *peer;
 | 
			
		||||
 | 
			
		||||
	vty_out(vty, "%% This function is deprecated, use "
 | 
			
		||||
	vty_out(vty, "%% '%s' is deprecated, use "
 | 
			
		||||
		"'peer " CBC_PEER_PROTO_NAME_VTY_CMD " NAME' instead. "
 | 
			
		||||
		"Assuming 'cbsp' for peers being created%s", VTY_NEWLINE);
 | 
			
		||||
		"Assuming 'cbsp' for peers being created%s",
 | 
			
		||||
		self->string, VTY_NEWLINE);
 | 
			
		||||
 | 
			
		||||
	peer = cbc_peer_by_name(argv[0]);
 | 
			
		||||
	if (!peer)
 | 
			
		||||
@@ -555,6 +577,26 @@ DEFUN(cfg_cbc_peer, cfg_cbc_peer_cmd,
 | 
			
		||||
	enum cbc_peer_protocol proto;
 | 
			
		||||
 | 
			
		||||
	proto = get_string_value(cbc_peer_proto_name_vty, argv[0]);
 | 
			
		||||
	switch (proto) {
 | 
			
		||||
	case CBC_PEER_PROTO_CBSP:
 | 
			
		||||
		if (!g_cbc->config.cbsp.configured) {
 | 
			
		||||
			vty_out(vty, "%% Node '%s' must be configured before configuring node 'peer'!%s",
 | 
			
		||||
				argv[0], VTY_NEWLINE);
 | 
			
		||||
			return CMD_WARNING;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_PEER_PROTO_SBcAP:
 | 
			
		||||
		if (!g_cbc->config.sbcap.configured) {
 | 
			
		||||
			vty_out(vty, "%% Node '%s' must be configured before configuring node 'peer'!%s",
 | 
			
		||||
				argv[0], VTY_NEWLINE);
 | 
			
		||||
			return CMD_WARNING;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_PEER_PROTO_SABP:
 | 
			
		||||
	default:
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	peer = cbc_peer_by_name(argv[1]);
 | 
			
		||||
	if (!peer)
 | 
			
		||||
		peer = cbc_peer_create(argv[1], proto);
 | 
			
		||||
@@ -588,8 +630,22 @@ DEFUN_DEPRECATED(cfg_peer_proto, cfg_peer_proto_cmd,
 | 
			
		||||
	"Configure Protocol of Peer\n"
 | 
			
		||||
	CBC_PEER_PROTO_NAME_VTY_STR)
 | 
			
		||||
{
 | 
			
		||||
	vty_out(vty, "%% This function is deprecated and does nothing, use "
 | 
			
		||||
		"'peer " CBC_PEER_PROTO_NAME_VTY_CMD " NAME' instead%s", VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, "%% '%s' is deprecated and does nothing, use "
 | 
			
		||||
		"'peer " CBC_PEER_PROTO_NAME_VTY_CMD " NAME' instead%s",
 | 
			
		||||
		self->string, VTY_NEWLINE);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN_ATTR(cfg_peer_mode, cfg_peer_mode_cmd,
 | 
			
		||||
	"mode (server|client|disabled)",
 | 
			
		||||
	"Connect to peer as TCP(CBSP)/SCTP(SBc-AP) server or client\n"
 | 
			
		||||
	"server: listen for inbound TCP (CBSP) / SCTP (SBc-AP) connections from a remote peer\n"
 | 
			
		||||
	"client: establish outbound TCP (CBSP) / SCTP (SBc-AP) connection to a remote peer\n"
 | 
			
		||||
	"Disable CBSP link\n",
 | 
			
		||||
	CMD_ATTR_NODE_EXIT)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_peer *peer = (struct cbc_peer *) vty->index;
 | 
			
		||||
	peer->link_mode = get_string_value(cbc_peer_link_mode_names, argv[0]);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -677,6 +733,7 @@ static void write_one_peer(struct vty *vty, struct cbc_peer *peer)
 | 
			
		||||
	unsigned int i;
 | 
			
		||||
	vty_out(vty, " peer %s %s%s", get_value_string(cbc_peer_proto_name_vty, peer->proto),
 | 
			
		||||
		peer->name, VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, "  mode %s%s", cbc_peer_link_mode_name(peer->link_mode), VTY_NEWLINE);
 | 
			
		||||
	if (peer->remote_port == -1)
 | 
			
		||||
		vty_out(vty, "  no remote-port%s", VTY_NEWLINE);
 | 
			
		||||
	else
 | 
			
		||||
@@ -703,6 +760,7 @@ void cbc_vty_init(void)
 | 
			
		||||
	install_element_ve(&show_message_cbs_cmd);
 | 
			
		||||
	install_element_ve(&show_messages_cbs_cmd);
 | 
			
		||||
	install_element_ve(&show_messages_etws_cmd);
 | 
			
		||||
	install_element_ve(&delete_message_expired_cmd);
 | 
			
		||||
 | 
			
		||||
	install_element(CONFIG_NODE, &cfg_cbc_cmd);
 | 
			
		||||
	install_node(&cbc_node, config_write_cbc);
 | 
			
		||||
@@ -729,6 +787,7 @@ void cbc_vty_init(void)
 | 
			
		||||
	install_element(CBC_NODE, &cfg_cbc_no_peer_cmd);
 | 
			
		||||
	install_node(&peer_node, NULL);
 | 
			
		||||
	install_element(PEER_NODE, &cfg_peer_proto_cmd);
 | 
			
		||||
	install_element(PEER_NODE, &cfg_peer_mode_cmd);
 | 
			
		||||
	install_element(PEER_NODE, &cfg_peer_remote_port_cmd);
 | 
			
		||||
	install_element(PEER_NODE, &cfg_peer_no_remote_port_cmd);
 | 
			
		||||
	install_element(PEER_NODE, &cfg_peer_remote_ip_cmd);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										190
									
								
								src/cbsp_link.c
									
									
									
									
									
								
							
							
						
						
									
										190
									
								
								src/cbsp_link.c
									
									
									
									
									
								
							@@ -41,18 +41,23 @@
 | 
			
		||||
struct cbc_cbsp_link *cbc_cbsp_link_alloc(struct cbc_cbsp_mgr *cbc, struct cbc_peer *peer)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_cbsp_link *link;
 | 
			
		||||
	char *name;
 | 
			
		||||
 | 
			
		||||
	link = talloc_zero(cbc, struct cbc_cbsp_link);
 | 
			
		||||
	OSMO_ASSERT(link);
 | 
			
		||||
 | 
			
		||||
	link->peer = peer;
 | 
			
		||||
	link->is_client = (peer->link_mode == CBC_PEER_LINK_MODE_CLIENT);
 | 
			
		||||
 | 
			
		||||
	link->fi = osmo_fsm_inst_alloc(&cbsp_link_fsm, link, link, LOGL_DEBUG, NULL);
 | 
			
		||||
	name = talloc_strdup(link, peer->name);
 | 
			
		||||
	osmo_identifier_sanitize_buf(name, NULL, '_');
 | 
			
		||||
	link->fi = osmo_fsm_inst_alloc(&cbsp_link_fsm, link, link, LOGL_DEBUG, name);
 | 
			
		||||
	if (!link->fi) {
 | 
			
		||||
		LOGPCC(link, LOGL_ERROR, "Unable to allocate FSM\n");
 | 
			
		||||
		talloc_free(link);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	talloc_free(name);
 | 
			
		||||
 | 
			
		||||
	llist_add_tail(&link->list, &cbc->links);
 | 
			
		||||
	return link;
 | 
			
		||||
@@ -70,18 +75,125 @@ void cbc_cbsp_link_free(struct cbc_cbsp_link *link)
 | 
			
		||||
 | 
			
		||||
const char *cbc_cbsp_link_name(const struct cbc_cbsp_link *link)
 | 
			
		||||
{
 | 
			
		||||
	struct osmo_fd *ofd;
 | 
			
		||||
	OSMO_ASSERT(link);
 | 
			
		||||
 | 
			
		||||
	if (link->peer && link->peer->name) {
 | 
			
		||||
	if (link->peer && link->peer->name)
 | 
			
		||||
		return link->peer->name;
 | 
			
		||||
	} else {
 | 
			
		||||
		struct osmo_fd *ofd = osmo_stream_srv_get_ofd(link->conn);
 | 
			
		||||
		return osmo_sock_get_name2(ofd->fd);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (link->is_client)
 | 
			
		||||
		ofd = osmo_stream_cli_get_ofd(link->cli_conn);
 | 
			
		||||
	else
 | 
			
		||||
		ofd = osmo_stream_srv_get_ofd(link->srv_conn);
 | 
			
		||||
	return osmo_sock_get_name2(ofd->fd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * TCP client
 | 
			
		||||
 */
 | 
			
		||||
static int cbc_cbsp_link_cli_connect_cb(struct osmo_stream_cli *conn)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_cbsp_link *link = osmo_stream_cli_get_data(conn);
 | 
			
		||||
	LOGPCC(link, LOGL_NOTICE, "Connected\n");
 | 
			
		||||
	osmo_fsm_inst_dispatch(link->fi, CBSP_LINK_E_CMD_RESET, NULL);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int cbc_cbsp_link_cli_disconnect_cb(struct osmo_stream_cli *conn)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_cbsp_link *link = osmo_stream_cli_get_data(conn);
 | 
			
		||||
	if (!link->conn) /* conn is being destroyed by us, we called osmo_stream_cli_destroy() */
 | 
			
		||||
		return 0;
 | 
			
		||||
	LOGPCC(link, LOGL_NOTICE, "Disconnected.\n");
 | 
			
		||||
	LOGPCC(link, LOGL_NOTICE, "Reconnecting...\n");
 | 
			
		||||
	osmo_stream_cli_reconnect(conn);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int cbc_cbsp_link_cli_read_cb(struct osmo_stream_cli *conn)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_cbsp_link *link = osmo_stream_cli_get_data(conn);
 | 
			
		||||
	struct osmo_fd *ofd = osmo_stream_cli_get_ofd(conn);
 | 
			
		||||
	struct osmo_cbsp_decoded *decoded;
 | 
			
		||||
	struct msgb *msg = NULL;
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
	LOGPCC(link, LOGL_DEBUG, "read_cb rx_msg=%p\n", link->rx_msg);
 | 
			
		||||
 | 
			
		||||
	/* message de-segmentation */
 | 
			
		||||
	rc = osmo_cbsp_recv_buffered(conn, ofd->fd, &msg, &link->rx_msg);
 | 
			
		||||
	if (rc <= 0) {
 | 
			
		||||
		LOGPCC(link, LOGL_NOTICE, "osmo_cbsp_recv_buffered() ret %d\n", rc);
 | 
			
		||||
		if (rc == -EAGAIN || rc == -EINTR) {
 | 
			
		||||
			/* more data needs to be read */
 | 
			
		||||
			return 0;
 | 
			
		||||
		} else if (rc == -EPIPE || rc == -ECONNRESET) {
 | 
			
		||||
			/* lost connection with server */
 | 
			
		||||
		} else if (rc == 0) {
 | 
			
		||||
			/* connection closed with server */
 | 
			
		||||
		}
 | 
			
		||||
		/* destroy connection */
 | 
			
		||||
		cbc_cbsp_link_close(link);
 | 
			
		||||
		return -EBADF;
 | 
			
		||||
	}
 | 
			
		||||
	OSMO_ASSERT(msg);
 | 
			
		||||
	LOGPCC(link, LOGL_DEBUG, "Received CBSP %s\n", msgb_hexdump(msg));
 | 
			
		||||
	/* decode + dispatch message */
 | 
			
		||||
	decoded = osmo_cbsp_decode(link, msg);
 | 
			
		||||
	if (decoded) {
 | 
			
		||||
		LOGPCC(link, LOGL_INFO, "Received CBSP %s\n",
 | 
			
		||||
			get_value_string(cbsp_msg_type_names, decoded->msg_type));
 | 
			
		||||
		g_cbc->cbsp.mgr->rx_cb(link, decoded);
 | 
			
		||||
	} else {
 | 
			
		||||
		LOGPCC(link, LOGL_ERROR, "Unable to decode %s\n", msgb_hexdump(msg));
 | 
			
		||||
	}
 | 
			
		||||
	msgb_free(msg);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cbc_cbsp_link_open_cli(struct cbc_cbsp_link *link)
 | 
			
		||||
{
 | 
			
		||||
	struct osmo_stream_cli *conn;
 | 
			
		||||
	struct cbc_peer *peer = link->peer;
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
	OSMO_ASSERT(link->is_client);
 | 
			
		||||
	OSMO_ASSERT(peer->link_mode == CBC_PEER_LINK_MODE_CLIENT);
 | 
			
		||||
 | 
			
		||||
	conn = osmo_stream_cli_create(link);
 | 
			
		||||
	osmo_stream_cli_set_data(conn, link);
 | 
			
		||||
	osmo_stream_cli_set_nodelay(conn, true);
 | 
			
		||||
	osmo_stream_cli_set_reconnect_timeout(conn, 5);
 | 
			
		||||
	osmo_stream_cli_set_proto(conn, IPPROTO_TCP);
 | 
			
		||||
	osmo_stream_cli_set_connect_cb(conn, cbc_cbsp_link_cli_connect_cb);
 | 
			
		||||
	osmo_stream_cli_set_disconnect_cb(conn, cbc_cbsp_link_cli_disconnect_cb);
 | 
			
		||||
	osmo_stream_cli_set_read_cb(conn, cbc_cbsp_link_cli_read_cb);
 | 
			
		||||
	rc = osmo_stream_cli_set_local_addrs(conn, (const char **)&g_cbc->config.cbsp.local_host, 1);
 | 
			
		||||
	if (rc < 0)
 | 
			
		||||
		goto free_ret;
 | 
			
		||||
	/* We assign free local port for client links:
 | 
			
		||||
	 * osmo_stream_cli_set_local_port(conn, g_cbc->cbsp.local_port);
 | 
			
		||||
	 */
 | 
			
		||||
	OSMO_ASSERT(peer->num_remote_host > 0);
 | 
			
		||||
	rc = osmo_stream_cli_set_addrs(conn, (const char **)peer->remote_host, peer->num_remote_host);
 | 
			
		||||
	if (rc < 0)
 | 
			
		||||
		goto free_ret;
 | 
			
		||||
	osmo_stream_cli_set_port(conn, peer->remote_port);
 | 
			
		||||
	rc = osmo_stream_cli_open(conn);
 | 
			
		||||
	if (rc < 0)
 | 
			
		||||
		goto free_ret;
 | 
			
		||||
	link->cli_conn = conn;
 | 
			
		||||
	return 0;
 | 
			
		||||
free_ret:
 | 
			
		||||
	osmo_stream_cli_destroy(conn);
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * TCP server
 | 
			
		||||
 */
 | 
			
		||||
/* data from BSC has arrived at CBC */
 | 
			
		||||
static int cbsp_cbc_read_cb(struct osmo_stream_srv *conn)
 | 
			
		||||
static int cbsp_cbc_srv_read_cb(struct osmo_stream_srv *conn)
 | 
			
		||||
{
 | 
			
		||||
	struct osmo_stream_srv_link *srv_link = osmo_stream_srv_get_master(conn);
 | 
			
		||||
	struct cbc_cbsp_link *link = osmo_stream_srv_get_data(conn);
 | 
			
		||||
@@ -96,6 +208,7 @@ static int cbsp_cbc_read_cb(struct osmo_stream_srv *conn)
 | 
			
		||||
	/* message de-segmentation */
 | 
			
		||||
	rc = osmo_cbsp_recv_buffered(conn, ofd->fd, &msg, &link->rx_msg);
 | 
			
		||||
	if (rc <= 0) {
 | 
			
		||||
		LOGPCC(link, LOGL_NOTICE, "osmo_cbsp_recv_buffered() ret %d\n", rc);
 | 
			
		||||
		if (rc == -EAGAIN || rc == -EINTR) {
 | 
			
		||||
			/* more data needs to be read */
 | 
			
		||||
			return 0;
 | 
			
		||||
@@ -125,7 +238,7 @@ static int cbsp_cbc_read_cb(struct osmo_stream_srv *conn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* connection from BSC to CBC has been closed */
 | 
			
		||||
static int cbsp_cbc_closed_cb(struct osmo_stream_srv *conn)
 | 
			
		||||
static int cbsp_cbc_srv_closed_cb(struct osmo_stream_srv *conn)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_cbsp_link *link = osmo_stream_srv_get_data(conn);
 | 
			
		||||
	LOGPCC(link, LOGL_NOTICE, "connection closed\n");
 | 
			
		||||
@@ -170,6 +283,23 @@ static int cbsp_cbc_accept_cb(struct osmo_stream_srv_link *srv_link, int fd)
 | 
			
		||||
		peer = cbc_peer_create(NULL, CBC_PEER_PROTO_CBSP);
 | 
			
		||||
		OSMO_ASSERT(peer);
 | 
			
		||||
		peer->unknown_dynamic_peer = true;
 | 
			
		||||
	} else { /* peer is known */
 | 
			
		||||
		switch (peer->link_mode) {
 | 
			
		||||
		case CBC_PEER_LINK_MODE_DISABLED:
 | 
			
		||||
			LOGP(DCBSP, LOGL_NOTICE,
 | 
			
		||||
			     "Rejecting conn for disabled CBSP peer %s:%d\n",
 | 
			
		||||
			     remote_ip, remote_port);
 | 
			
		||||
			close(fd);
 | 
			
		||||
			return -1;
 | 
			
		||||
		case CBC_PEER_LINK_MODE_CLIENT:
 | 
			
		||||
			LOGP(DCBSP, LOGL_NOTICE,
 | 
			
		||||
			     "Rejecting conn for CBSP peer %s:%d configured as 'client'\n",
 | 
			
		||||
			     remote_ip, remote_port);
 | 
			
		||||
			close(fd);
 | 
			
		||||
			return -1;
 | 
			
		||||
		default: /* MODE_SERVER */
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (peer->link.cbsp) {
 | 
			
		||||
		LOGPCC(peer->link.cbsp, LOGL_ERROR,
 | 
			
		||||
@@ -179,10 +309,11 @@ static int cbsp_cbc_accept_cb(struct osmo_stream_srv_link *srv_link, int fd)
 | 
			
		||||
	}
 | 
			
		||||
	link = cbc_cbsp_link_alloc(cbc, peer);
 | 
			
		||||
	OSMO_ASSERT(link);
 | 
			
		||||
	link->conn = osmo_stream_srv_create(srv_link, srv_link, fd,
 | 
			
		||||
					    cbsp_cbc_read_cb, cbsp_cbc_closed_cb,
 | 
			
		||||
					    link);
 | 
			
		||||
	if (!link->conn) {
 | 
			
		||||
 | 
			
		||||
	link->srv_conn = osmo_stream_srv_create(srv_link, srv_link, fd,
 | 
			
		||||
						cbsp_cbc_srv_read_cb, cbsp_cbc_srv_closed_cb,
 | 
			
		||||
						link);
 | 
			
		||||
	if (!link->srv_conn) {
 | 
			
		||||
		LOGPCC(link, LOGL_ERROR,
 | 
			
		||||
		       "Unable to create stream server for %s:%u\n",
 | 
			
		||||
		       remote_ip, remote_port);
 | 
			
		||||
@@ -195,14 +326,20 @@ static int cbsp_cbc_accept_cb(struct osmo_stream_srv_link *srv_link, int fd)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cbc_cbsp_link_tx(struct cbc_cbsp_link *link, struct osmo_cbsp_decoded *cbsp)
 | 
			
		||||
int cbc_cbsp_link_tx(struct cbc_cbsp_link *link, struct osmo_cbsp_decoded *cbsp)
 | 
			
		||||
{
 | 
			
		||||
	struct msgb *msg;
 | 
			
		||||
 | 
			
		||||
	if (!link) {
 | 
			
		||||
		LOGP(DCBSP, LOGL_NOTICE, "Cannot transmit %s: no connection\n",
 | 
			
		||||
			get_value_string(cbsp_msg_type_names, cbsp->msg_type));
 | 
			
		||||
		return ;
 | 
			
		||||
		talloc_free(cbsp);
 | 
			
		||||
		return -ENOLINK;
 | 
			
		||||
	} else if (link->is_client && !osmo_stream_cli_is_connected(link->cli_conn)) {
 | 
			
		||||
		LOGPCC(link, LOGL_NOTICE, "Cannot transmit %s: reconnecting\n",
 | 
			
		||||
		     get_value_string(cbsp_msg_type_names, cbsp->msg_type));
 | 
			
		||||
		talloc_free(cbsp);
 | 
			
		||||
		return -ENOTCONN;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	LOGPCC(link, LOGL_INFO, "Transmitting %s\n",
 | 
			
		||||
@@ -213,16 +350,33 @@ void cbc_cbsp_link_tx(struct cbc_cbsp_link *link, struct osmo_cbsp_decoded *cbsp
 | 
			
		||||
		LOGPCC(link, LOGL_ERROR, "Failed to encode CBSP %s: %s\n",
 | 
			
		||||
			get_value_string(cbsp_msg_type_names, cbsp->msg_type), osmo_cbsp_errstr);
 | 
			
		||||
		talloc_free(cbsp);
 | 
			
		||||
		return;
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	talloc_free(cbsp);
 | 
			
		||||
	osmo_stream_srv_send(link->conn, msg);
 | 
			
		||||
	if (link->is_client)
 | 
			
		||||
		osmo_stream_cli_send(link->cli_conn, msg);
 | 
			
		||||
	else
 | 
			
		||||
		osmo_stream_srv_send(link->srv_conn, msg);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cbc_cbsp_link_close(struct cbc_cbsp_link *link)
 | 
			
		||||
{
 | 
			
		||||
	if (link->conn)
 | 
			
		||||
		osmo_stream_srv_destroy(link->conn);
 | 
			
		||||
	if (!link->conn)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (link->is_client) {
 | 
			
		||||
		struct osmo_stream_cli *cli_conn = link->cli_conn;
 | 
			
		||||
		link->cli_conn = NULL;
 | 
			
		||||
		osmo_stream_cli_destroy(cli_conn);
 | 
			
		||||
		if (link->peer)
 | 
			
		||||
			link->peer->link.cbsp = NULL;
 | 
			
		||||
		if (link->fi)
 | 
			
		||||
			osmo_fsm_inst_dispatch(link->fi, CBSP_LINK_E_CMD_CLOSE, NULL);
 | 
			
		||||
	} else {
 | 
			
		||||
		osmo_stream_srv_destroy(link->srv_conn);
 | 
			
		||||
		/* Same as waht's done for cli is done for srv in closed_cb() */
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@
 | 
			
		||||
#include <osmocom/cbc/cbsp_link.h>
 | 
			
		||||
#include <osmocom/cbc/cbsp_link_fsm.h>
 | 
			
		||||
#include <osmocom/cbc/debug.h>
 | 
			
		||||
#include <osmocom/cbc/smscb_message_fsm.h>
 | 
			
		||||
#include <osmocom/cbc/smscb_peer_fsm.h>
 | 
			
		||||
 | 
			
		||||
#define S(x)	(1 << (x))
 | 
			
		||||
 | 
			
		||||
@@ -339,22 +339,22 @@ int cbc_cbsp_link_rx_cb(struct cbc_cbsp_link *link, struct osmo_cbsp_decoded *de
 | 
			
		||||
	switch (dec->msg_type) {
 | 
			
		||||
	case CBSP_MSGT_WRITE_REPLACE_COMPL:
 | 
			
		||||
		if (dec->u.write_replace_compl.old_serial_nr)
 | 
			
		||||
			return osmo_fsm_inst_dispatch(mp->fi, SMSCB_E_CBSP_REPLACE_ACK, dec);
 | 
			
		||||
			return osmo_fsm_inst_dispatch(mp->fi, SMSCB_PEER_E_CBSP_REPLACE_ACK, dec);
 | 
			
		||||
		else
 | 
			
		||||
			return osmo_fsm_inst_dispatch(mp->fi, SMSCB_E_CBSP_WRITE_ACK, dec);
 | 
			
		||||
			return osmo_fsm_inst_dispatch(mp->fi, SMSCB_PEER_E_CBSP_WRITE_ACK, dec);
 | 
			
		||||
	case CBSP_MSGT_WRITE_REPLACE_FAIL:
 | 
			
		||||
		if (dec->u.write_replace_fail.old_serial_nr)
 | 
			
		||||
			return osmo_fsm_inst_dispatch(mp->fi, SMSCB_E_CBSP_REPLACE_NACK, dec);
 | 
			
		||||
			return osmo_fsm_inst_dispatch(mp->fi, SMSCB_PEER_E_CBSP_REPLACE_NACK, dec);
 | 
			
		||||
		else
 | 
			
		||||
			return osmo_fsm_inst_dispatch(mp->fi, SMSCB_E_CBSP_WRITE_NACK, dec);
 | 
			
		||||
			return osmo_fsm_inst_dispatch(mp->fi, SMSCB_PEER_E_CBSP_WRITE_NACK, dec);
 | 
			
		||||
	case CBSP_MSGT_KILL_COMPL:
 | 
			
		||||
		return osmo_fsm_inst_dispatch(mp->fi, SMSCB_E_CBSP_DELETE_ACK, dec);
 | 
			
		||||
		return osmo_fsm_inst_dispatch(mp->fi, SMSCB_PEER_E_CBSP_DELETE_ACK, dec);
 | 
			
		||||
	case CBSP_MSGT_KILL_FAIL:
 | 
			
		||||
		return osmo_fsm_inst_dispatch(mp->fi, SMSCB_E_CBSP_DELETE_NACK, dec);
 | 
			
		||||
		return osmo_fsm_inst_dispatch(mp->fi, SMSCB_PEER_E_CBSP_DELETE_NACK, dec);
 | 
			
		||||
	case CBSP_MSGT_MSG_STATUS_QUERY_COMPL:
 | 
			
		||||
		return osmo_fsm_inst_dispatch(mp->fi, SMSCB_E_CBSP_STATUS_ACK, dec);
 | 
			
		||||
		return osmo_fsm_inst_dispatch(mp->fi, SMSCB_PEER_E_CBSP_STATUS_ACK, dec);
 | 
			
		||||
	case CBSP_MSGT_MSG_STATUS_QUERY_FAIL:
 | 
			
		||||
		return osmo_fsm_inst_dispatch(mp->fi, SMSCB_E_CBSP_STATUS_NACK, dec);
 | 
			
		||||
		return osmo_fsm_inst_dispatch(mp->fi, SMSCB_PEER_E_CBSP_STATUS_NACK, dec);
 | 
			
		||||
	default:
 | 
			
		||||
		LOGPCC(link, LOGL_ERROR, "unknown message %s\n",
 | 
			
		||||
			get_value_string(cbsp_msg_type_names, dec->msg_type));
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										110
									
								
								src/cbsp_msg.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								src/cbsp_msg.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,110 @@
 | 
			
		||||
/* Osmocom CBC (Cell Broacast Centre) */
 | 
			
		||||
 | 
			
		||||
/* (C) 2019 by Harald Welte <laforge@gnumonks.org>
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0+
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Affero General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/linuxlist.h>
 | 
			
		||||
#include <osmocom/core/utils.h>
 | 
			
		||||
#include <osmocom/gsm/cbsp.h>
 | 
			
		||||
#include <osmocom/cbc/cbsp_msg.h>
 | 
			
		||||
#include <osmocom/cbc/cbc_message.h>
 | 
			
		||||
 | 
			
		||||
/* convert cbc_message to osmo_cbsp_cell_list */
 | 
			
		||||
static int cbcmsg_to_cbsp_cell_list(const void *ctx, struct osmo_cbsp_cell_list *list,
 | 
			
		||||
				    const struct cbc_message *cbcmsg)
 | 
			
		||||
{
 | 
			
		||||
	struct osmo_cbsp_cell_ent *ent;
 | 
			
		||||
 | 
			
		||||
	switch (cbcmsg->scope) {
 | 
			
		||||
	case CBC_MSG_SCOPE_PLMN:
 | 
			
		||||
		list->id_discr = CELL_IDENT_BSS;
 | 
			
		||||
		ent = talloc_zero(ctx, struct osmo_cbsp_cell_ent);
 | 
			
		||||
		if (!ent)
 | 
			
		||||
			return -ENOMEM;
 | 
			
		||||
		//ent->cell_id = ?
 | 
			
		||||
		llist_add_tail(&ent->list, &list->list);
 | 
			
		||||
		return 0;
 | 
			
		||||
	default:
 | 
			
		||||
		OSMO_ASSERT(0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* generate a CBSP WRITE-REPLACE from our internal representation */
 | 
			
		||||
struct osmo_cbsp_decoded *cbsp_gen_write_replace_req(void *ctx, const struct cbc_message *cbcmsg)
 | 
			
		||||
{
 | 
			
		||||
	struct osmo_cbsp_write_replace *wrepl;
 | 
			
		||||
	const struct smscb_message *smscb = &cbcmsg->msg;
 | 
			
		||||
	struct osmo_cbsp_decoded *cbsp = osmo_cbsp_decoded_alloc(ctx, CBSP_MSGT_WRITE_REPLACE);
 | 
			
		||||
	unsigned int i;
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
	if (!cbsp)
 | 
			
		||||
		return NULL;
 | 
			
		||||
	wrepl = &cbsp->u.write_replace;
 | 
			
		||||
 | 
			
		||||
	wrepl->msg_id = smscb->message_id;
 | 
			
		||||
	wrepl->new_serial_nr = smscb->serial_nr;
 | 
			
		||||
	/* FIXME: old? */
 | 
			
		||||
	/* Cell list */
 | 
			
		||||
	rc = cbcmsg_to_cbsp_cell_list(cbcmsg, &wrepl->cell_list, cbcmsg);
 | 
			
		||||
	if (rc < 0) {
 | 
			
		||||
		talloc_free(cbsp);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	if (!smscb->is_etws)
 | 
			
		||||
		wrepl->is_cbs = true;
 | 
			
		||||
	if (wrepl->is_cbs) {
 | 
			
		||||
		if (cbcmsg->extended_cbch)
 | 
			
		||||
			wrepl->u.cbs.channel_ind = CBSP_CHAN_IND_EXTENDED;
 | 
			
		||||
		else
 | 
			
		||||
			wrepl->u.cbs.channel_ind = CBSP_CHAN_IND_BASIC;
 | 
			
		||||
		wrepl->u.cbs.category = cbcmsg->priority;
 | 
			
		||||
		wrepl->u.cbs.rep_period = cbcmsg->rep_period;
 | 
			
		||||
		wrepl->u.cbs.num_bcast_req = cbcmsg->num_bcast;
 | 
			
		||||
		wrepl->u.cbs.dcs = smscb->cbs.dcs;
 | 
			
		||||
		INIT_LLIST_HEAD(&wrepl->u.cbs.msg_content);
 | 
			
		||||
		for (i = 0; i < smscb->cbs.num_pages; i++) {
 | 
			
		||||
			struct osmo_cbsp_content *ce = talloc_zero(cbsp, struct osmo_cbsp_content);
 | 
			
		||||
			if (i == smscb->cbs.num_pages - 1)
 | 
			
		||||
				ce->user_len = smscb->cbs.data_user_len - (i * SMSCB_RAW_PAGE_LEN);
 | 
			
		||||
			else
 | 
			
		||||
				ce->user_len = SMSCB_RAW_PAGE_LEN;
 | 
			
		||||
			memcpy(ce->data, smscb->cbs.data[i], SMSCB_RAW_PAGE_LEN);
 | 
			
		||||
			llist_add_tail(&ce->list, &wrepl->u.cbs.msg_content);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		wrepl->u.emergency.indicator = 1;
 | 
			
		||||
		wrepl->u.emergency.warning_type = (smscb->etws.warning_type & 0x7f) << 9;
 | 
			
		||||
		if (smscb->etws.user_alert)
 | 
			
		||||
			wrepl->u.emergency.warning_type |= 0x0100;
 | 
			
		||||
		if (smscb->etws.popup_on_display)
 | 
			
		||||
			wrepl->u.emergency.warning_type |= 0x0080;
 | 
			
		||||
		memcpy(wrepl->u.emergency.warning_sec_info, smscb->etws.warning_sec_info,
 | 
			
		||||
			sizeof(wrepl->u.emergency.warning_sec_info));
 | 
			
		||||
		if (cbcmsg->warning_period_sec == 0xffffffff)
 | 
			
		||||
			wrepl->u.emergency.warning_period = 0;
 | 
			
		||||
		else
 | 
			
		||||
			wrepl->u.emergency.warning_period = cbcmsg->warning_period_sec;
 | 
			
		||||
	}
 | 
			
		||||
	return cbsp;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										574
									
								
								src/cbsp_smscb_peer_fsm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										574
									
								
								src/cbsp_smscb_peer_fsm.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,574 @@
 | 
			
		||||
/* SMSCB Peer FSM: Represents state of one SMSCB for one peer (BSC) */
 | 
			
		||||
 | 
			
		||||
/* This FSM exists per tuple of (message, bsc peer) */
 | 
			
		||||
 | 
			
		||||
/* (C) 2019 by Harald Welte <laforge@gnumonks.org>
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0+
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Affero General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/utils.h>
 | 
			
		||||
#include <osmocom/core/linuxlist.h>
 | 
			
		||||
#include <osmocom/core/talloc.h>
 | 
			
		||||
#include <osmocom/core/fsm.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/gsm/gsm23003.h>
 | 
			
		||||
#include <osmocom/gsm/protocol/gsm_08_08.h>
 | 
			
		||||
#include <osmocom/gsm/gsm0808_utils.h>
 | 
			
		||||
#include <osmocom/gsm/cbsp.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sbcap/sbcap_common.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/cbc/cbc_message.h>
 | 
			
		||||
#include <osmocom/cbc/cbc_peer.h>
 | 
			
		||||
#include <osmocom/cbc/cbsp_link.h>
 | 
			
		||||
#include <osmocom/cbc/sbcap_link.h>
 | 
			
		||||
#include <osmocom/cbc/sbcap_msg.h>
 | 
			
		||||
#include <osmocom/cbc/debug.h>
 | 
			
		||||
#include <osmocom/cbc/smscb_peer_fsm.h>
 | 
			
		||||
#include <osmocom/cbc/smscb_message_fsm.h>
 | 
			
		||||
 | 
			
		||||
#define S(x)	(1 << (x))
 | 
			
		||||
 | 
			
		||||
/***********************************************************************
 | 
			
		||||
 * Helper functions
 | 
			
		||||
 ***********************************************************************/
 | 
			
		||||
 | 
			
		||||
/* covert TS 08.08 Cell Identity value to CBC internal type */
 | 
			
		||||
static enum cbc_cell_id_type cci_discr_from_cell_id(enum CELL_IDENT id_discr)
 | 
			
		||||
{
 | 
			
		||||
	switch (id_discr) {
 | 
			
		||||
	case CELL_IDENT_NO_CELL:
 | 
			
		||||
		return CBC_CELL_ID_NONE;
 | 
			
		||||
	case CELL_IDENT_WHOLE_GLOBAL:
 | 
			
		||||
		return CBC_CELL_ID_CGI;
 | 
			
		||||
	case CELL_IDENT_LAC_AND_CI:
 | 
			
		||||
		return CBC_CELL_ID_LAC_CI;
 | 
			
		||||
	case CELL_IDENT_CI:
 | 
			
		||||
		return CBC_CELL_ID_CI;
 | 
			
		||||
	case CELL_IDENT_LAI:
 | 
			
		||||
		return CBC_CELL_ID_LAI;
 | 
			
		||||
	case CELL_IDENT_LAC:
 | 
			
		||||
		return CBC_CELL_ID_LAC;
 | 
			
		||||
	case CELL_IDENT_BSS:
 | 
			
		||||
		return CBC_CELL_ID_BSS;
 | 
			
		||||
	default:
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* covert CBC internal type to TS 08.08 Cell Identity */
 | 
			
		||||
static enum CELL_IDENT cell_id_from_ccid_discr(enum cbc_cell_id_type in)
 | 
			
		||||
{
 | 
			
		||||
	switch (in) {
 | 
			
		||||
	case CBC_CELL_ID_NONE:
 | 
			
		||||
		return CELL_IDENT_NO_CELL;
 | 
			
		||||
	case CBC_CELL_ID_CGI:
 | 
			
		||||
		return CELL_IDENT_WHOLE_GLOBAL;
 | 
			
		||||
	case CBC_CELL_ID_LAC_CI:
 | 
			
		||||
		return CELL_IDENT_LAC_AND_CI;
 | 
			
		||||
	case CBC_CELL_ID_CI:
 | 
			
		||||
		return CELL_IDENT_CI;
 | 
			
		||||
	case CBC_CELL_ID_LAI:
 | 
			
		||||
		return CELL_IDENT_LAI;
 | 
			
		||||
	case CBC_CELL_ID_LAC:
 | 
			
		||||
		return CELL_IDENT_LAC;
 | 
			
		||||
	case CBC_CELL_ID_BSS:
 | 
			
		||||
		return CELL_IDENT_BSS;
 | 
			
		||||
	default:
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* convert TS 08.08 Cell Identifier Union to CBC internal type */
 | 
			
		||||
static void cci_from_cbsp(struct cbc_cell_id *cci, enum CELL_IDENT id_discr,
 | 
			
		||||
			  const union gsm0808_cell_id_u *u)
 | 
			
		||||
{
 | 
			
		||||
	cci->id_discr = cci_discr_from_cell_id(id_discr);
 | 
			
		||||
 | 
			
		||||
	switch (id_discr) {
 | 
			
		||||
	case CELL_IDENT_NO_CELL:
 | 
			
		||||
		break;
 | 
			
		||||
	case CELL_IDENT_WHOLE_GLOBAL:
 | 
			
		||||
		cci->u.cgi = u->global;
 | 
			
		||||
		break;
 | 
			
		||||
	case CELL_IDENT_LAC_AND_CI:
 | 
			
		||||
		cci->u.lac_and_ci = u->lac_and_ci;
 | 
			
		||||
		break;
 | 
			
		||||
	case CELL_IDENT_CI:
 | 
			
		||||
		cci->u.ci = u->ci;
 | 
			
		||||
		break;
 | 
			
		||||
	case CELL_IDENT_LAI:
 | 
			
		||||
		cci->u.lai = u->lai_and_lac;
 | 
			
		||||
		break;
 | 
			
		||||
	case CELL_IDENT_LAC:
 | 
			
		||||
		cci->u.lac = u->lac;
 | 
			
		||||
		break;
 | 
			
		||||
	case CELL_IDENT_BSS:
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* convert TS 08.08 Cell Identifier Union to CBC internal type */
 | 
			
		||||
static void cbsp_from_cci(union gsm0808_cell_id_u *u, const struct cbc_cell_id *cci)
 | 
			
		||||
{
 | 
			
		||||
	switch (cci->id_discr) {
 | 
			
		||||
	case CBC_CELL_ID_NONE:
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_CGI:
 | 
			
		||||
		u->global = cci->u.cgi;
 | 
			
		||||
		printf("u->gobal: %s\n", osmo_hexdump((uint8_t *) &u->global, sizeof(u->global)));
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_LAC_CI:
 | 
			
		||||
		u->lac_and_ci = cci->u.lac_and_ci;
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_CI:
 | 
			
		||||
		u->ci = cci->u.ci;
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_LAI:
 | 
			
		||||
		u->lai_and_lac = cci->u.lai;
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_LAC:
 | 
			
		||||
		u->lac = cci->u.lac;
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_CELL_ID_BSS:
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		OSMO_ASSERT(0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* read a single osmo_cbsp_num_compl_ent and add it to cbc_message_peer */
 | 
			
		||||
static void cci_from_cbsp_compl_ent(struct cbc_message_peer *mp,
 | 
			
		||||
				    struct osmo_cbsp_num_compl_ent *ce, enum CELL_IDENT id_discr)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_cell_id *cci;
 | 
			
		||||
 | 
			
		||||
	cci = NULL; // FIXME: lookup
 | 
			
		||||
	if (!cci) {
 | 
			
		||||
		cci = talloc_zero(mp, struct cbc_cell_id);
 | 
			
		||||
		if (!cci)
 | 
			
		||||
			return;
 | 
			
		||||
		llist_add_tail(&cci->list, &mp->num_compl_list);
 | 
			
		||||
	}
 | 
			
		||||
	cci_from_cbsp(cci, id_discr, &ce->cell_id);
 | 
			
		||||
	cci->num_compl.num_compl += ce->num_compl;
 | 
			
		||||
	cci->num_compl.num_bcast_info += ce->num_bcast_info;
 | 
			
		||||
	LOGPFSML(mp->fi, LOGL_DEBUG, "Appending CellId %s to Broadcast Completed list\n",
 | 
			
		||||
		 cbc_cell_id2str(cci));
 | 
			
		||||
}
 | 
			
		||||
static void msg_peer_append_cbsp_compl(struct cbc_message_peer *mp,
 | 
			
		||||
					struct osmo_cbsp_num_compl_list *nclist)
 | 
			
		||||
{
 | 
			
		||||
	struct osmo_cbsp_num_compl_ent *ce;
 | 
			
		||||
 | 
			
		||||
	llist_for_each_entry(ce, &nclist->list, list)
 | 
			
		||||
		cci_from_cbsp_compl_ent(mp, ce, nclist->id_discr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* read a single osmo_cbsp_cell_ent and add it to cbc_message_peer */
 | 
			
		||||
static void cci_from_cbsp_cell_ent(struct cbc_message_peer *mp,
 | 
			
		||||
				   struct osmo_cbsp_cell_ent *ce, enum CELL_IDENT id_discr)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_cell_id *cci;
 | 
			
		||||
 | 
			
		||||
	cci = NULL; // FIXME: lookup
 | 
			
		||||
	if (!cci) {
 | 
			
		||||
		cci = talloc_zero(mp, struct cbc_cell_id);
 | 
			
		||||
		if (!cci)
 | 
			
		||||
			return;
 | 
			
		||||
		llist_add_tail(&cci->list, &mp->cell_list);
 | 
			
		||||
	}
 | 
			
		||||
	cci_from_cbsp(cci, id_discr, &ce->cell_id);
 | 
			
		||||
	LOGPFSML(mp->fi, LOGL_DEBUG, "Appending CellId %s to Cell list\n",
 | 
			
		||||
		 cbc_cell_id2str(cci));
 | 
			
		||||
}
 | 
			
		||||
static void msg_peer_append_cbsp_cell(struct cbc_message_peer *mp,
 | 
			
		||||
					struct osmo_cbsp_cell_list *clist)
 | 
			
		||||
{
 | 
			
		||||
	struct osmo_cbsp_cell_ent *ce;
 | 
			
		||||
 | 
			
		||||
	llist_for_each_entry(ce, &clist->list, list)
 | 
			
		||||
		cci_from_cbsp_cell_ent(mp, ce, clist->id_discr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* read a single osmo_cbsp_fail_ent and add it to cbc_message_peer */
 | 
			
		||||
static void cci_from_cbsp_fail_ent(struct cbc_message_peer *mp,
 | 
			
		||||
				   struct osmo_cbsp_fail_ent *fe)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_cell_id *cci;
 | 
			
		||||
	cci = NULL; // lookup */
 | 
			
		||||
	if (!cci) {
 | 
			
		||||
		cci = talloc_zero(mp, struct cbc_cell_id);
 | 
			
		||||
		if (!cci)
 | 
			
		||||
			return;
 | 
			
		||||
		llist_add_tail(&cci->list, &mp->fail_list);
 | 
			
		||||
	}
 | 
			
		||||
	cci_from_cbsp(cci, fe->id_discr, &fe->cell_id);
 | 
			
		||||
	cci->fail.cause = fe->cause;
 | 
			
		||||
	LOGPFSML(mp->fi, LOGL_DEBUG, "Appending CellId %s (cause: %u) to Failed list\n",
 | 
			
		||||
		 cbc_cell_id2str(cci), cci->fail.cause);
 | 
			
		||||
}
 | 
			
		||||
static void msg_peer_append_cbsp_fail(struct cbc_message_peer *mp, struct llist_head *flist)
 | 
			
		||||
{
 | 
			
		||||
	struct osmo_cbsp_fail_ent *fe;
 | 
			
		||||
 | 
			
		||||
	llist_for_each_entry(fe, flist, list)
 | 
			
		||||
		cci_from_cbsp_fail_ent(mp, fe);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* append all cells from cbc_message_peer to given CBSP cell_list */
 | 
			
		||||
static void cbsp_append_cell_list(struct osmo_cbsp_cell_list *out, void *ctx,
 | 
			
		||||
				  const struct cbc_message_peer *mp)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_cell_id *cci;
 | 
			
		||||
	enum cbc_cell_id_type id_discr = CBC_CELL_ID_NONE;
 | 
			
		||||
 | 
			
		||||
	llist_for_each_entry(cci, &mp->cell_list, list) {
 | 
			
		||||
		struct osmo_cbsp_cell_ent *ent;
 | 
			
		||||
 | 
			
		||||
		if (id_discr == CBC_CELL_ID_NONE)
 | 
			
		||||
			id_discr = cci->id_discr;
 | 
			
		||||
		else if (id_discr != cci->id_discr) {
 | 
			
		||||
			LOGPFSML(mp->fi, LOGL_ERROR, "Cannot encode CBSP cell_list as not all "
 | 
			
		||||
				 "entries are of same type (%u != %u)\n", id_discr, cci->id_discr);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		ent = talloc_zero(ctx, struct osmo_cbsp_cell_ent);
 | 
			
		||||
		OSMO_ASSERT(ent);
 | 
			
		||||
		cbsp_from_cci(&ent->cell_id, cci);
 | 
			
		||||
		llist_add_tail(&ent->list, &out->list);
 | 
			
		||||
	}
 | 
			
		||||
	out->id_discr = cell_id_from_ccid_discr(id_discr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/***********************************************************************
 | 
			
		||||
 * actual FSM
 | 
			
		||||
 ***********************************************************************/
 | 
			
		||||
 | 
			
		||||
static void smscb_p_fsm_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_message_peer *mp = (struct cbc_message_peer *) fi->priv;
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
	switch (event) {
 | 
			
		||||
	case SMSCB_PEER_E_CREATE:
 | 
			
		||||
		/* send it to peer */
 | 
			
		||||
		rc = peer_new_cbc_message(mp->peer, mp->cbcmsg);
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, SMSCB_S_WAIT_WRITE_ACK, 10, T_WAIT_WRITE_ACK);
 | 
			
		||||
		if (rc != 0) /* Immediately timeout the message */
 | 
			
		||||
			fi->fsm->timer_cb(fi);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		OSMO_ASSERT(0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void smscb_p_fsm_wait_write_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_message_peer *mp = (struct cbc_message_peer *) fi->priv;
 | 
			
		||||
	struct osmo_cbsp_decoded *dec = NULL;
 | 
			
		||||
 | 
			
		||||
	switch (event) {
 | 
			
		||||
	case SMSCB_PEER_E_CBSP_WRITE_ACK:
 | 
			
		||||
		dec = data;
 | 
			
		||||
		msg_peer_append_cbsp_compl(mp, &dec->u.write_replace_compl.num_compl_list);
 | 
			
		||||
		msg_peer_append_cbsp_cell(mp, &dec->u.write_replace_compl.cell_list);
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, SMSCB_S_ACTIVE, 0, 0);
 | 
			
		||||
		/* Signal parent fsm about completion */
 | 
			
		||||
		osmo_fsm_inst_dispatch(fi->proc.parent, SMSCB_MSG_E_WRITE_ACK, mp);
 | 
			
		||||
		break;
 | 
			
		||||
	case SMSCB_PEER_E_CBSP_WRITE_NACK:
 | 
			
		||||
		dec = data;
 | 
			
		||||
		msg_peer_append_cbsp_compl(mp, &dec->u.write_replace_fail.num_compl_list);
 | 
			
		||||
		msg_peer_append_cbsp_cell(mp, &dec->u.write_replace_fail.cell_list);
 | 
			
		||||
		msg_peer_append_cbsp_fail(mp, &dec->u.write_replace_fail.fail_list);
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, SMSCB_S_ACTIVE, 0, 0);
 | 
			
		||||
		/* Signal parent fsm about completion */
 | 
			
		||||
		osmo_fsm_inst_dispatch(fi->proc.parent, SMSCB_MSG_E_WRITE_NACK, mp);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		OSMO_ASSERT(0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void smscb_p_fsm_active(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_message_peer *mp = (struct cbc_message_peer *) fi->priv;
 | 
			
		||||
	struct osmo_cbsp_decoded *cbsp;
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
	switch (event) {
 | 
			
		||||
	case SMSCB_PEER_E_REPLACE: /* send WRITE-REPLACE to BSC */
 | 
			
		||||
		cbsp = osmo_cbsp_decoded_alloc(mp->peer, CBSP_MSGT_WRITE_REPLACE);
 | 
			
		||||
		OSMO_ASSERT(cbsp);
 | 
			
		||||
		cbsp->u.write_replace.msg_id = mp->cbcmsg->msg.message_id;
 | 
			
		||||
		cbsp->u.write_replace.old_serial_nr = &mp->cbcmsg->msg.serial_nr;
 | 
			
		||||
		//cbsp->u.write_replace.new_serial_nr
 | 
			
		||||
		/* TODO: we assume that the replace will always affect all original cells */
 | 
			
		||||
		cbsp_append_cell_list(&cbsp->u.write_replace.cell_list, cbsp, mp);
 | 
			
		||||
		// TODO: ALL OTHER DATA
 | 
			
		||||
		rc = cbc_cbsp_link_tx(mp->peer->link.cbsp, cbsp);
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, SMSCB_S_WAIT_REPLACE_ACK, 10, T_WAIT_REPLACE_ACK);
 | 
			
		||||
		if (rc != 0) /* Immediately timeout the message */
 | 
			
		||||
			fi->fsm->timer_cb(fi);
 | 
			
		||||
		break;
 | 
			
		||||
	case SMSCB_PEER_E_STATUS: /* send MSG-STATUS-QUERY to BSC */
 | 
			
		||||
		cbsp = osmo_cbsp_decoded_alloc(mp->peer, CBSP_MSGT_MSG_STATUS_QUERY);
 | 
			
		||||
		OSMO_ASSERT(cbsp);
 | 
			
		||||
		cbsp->u.msg_status_query.msg_id = mp->cbcmsg->msg.message_id;
 | 
			
		||||
		cbsp->u.msg_status_query.old_serial_nr = mp->cbcmsg->msg.serial_nr;
 | 
			
		||||
		cbsp_append_cell_list(&cbsp->u.msg_status_query.cell_list, cbsp, mp);
 | 
			
		||||
		cbsp->u.msg_status_query.channel_ind = CBSP_CHAN_IND_BASIC;
 | 
			
		||||
		rc = cbc_cbsp_link_tx(mp->peer->link.cbsp, cbsp);
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, SMSCB_S_WAIT_STATUS_ACK, 10, T_WAIT_STATUS_ACK);
 | 
			
		||||
		if (rc != 0) /* Immediately timeout the message */
 | 
			
		||||
			fi->fsm->timer_cb(fi);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		OSMO_ASSERT(0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void smscb_p_fsm_wait_status_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_message_peer *mp = (struct cbc_message_peer *) fi->priv;
 | 
			
		||||
	struct osmo_cbsp_decoded *dec = NULL;
 | 
			
		||||
 | 
			
		||||
	switch (event) {
 | 
			
		||||
	case SMSCB_PEER_E_CBSP_STATUS_ACK:
 | 
			
		||||
		dec = data;
 | 
			
		||||
		msg_peer_append_cbsp_compl(mp, &dec->u.msg_status_query_compl.num_compl_list);
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, SMSCB_S_ACTIVE, 0, 0);
 | 
			
		||||
		/* Signal parent fsm about completion */
 | 
			
		||||
		osmo_fsm_inst_dispatch(fi->proc.parent, SMSCB_MSG_E_STATUS_ACK, mp);
 | 
			
		||||
		break;
 | 
			
		||||
	case SMSCB_PEER_E_CBSP_STATUS_NACK:
 | 
			
		||||
		dec = data;
 | 
			
		||||
		msg_peer_append_cbsp_compl(mp, &dec->u.msg_status_query_fail.num_compl_list);
 | 
			
		||||
		msg_peer_append_cbsp_fail(mp, &dec->u.msg_status_query_fail.fail_list);
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, SMSCB_S_ACTIVE, 0, 0);
 | 
			
		||||
		/* Signal parent fsm about completion */
 | 
			
		||||
		osmo_fsm_inst_dispatch(fi->proc.parent, SMSCB_MSG_E_STATUS_NACK, mp);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		OSMO_ASSERT(0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void smscb_p_fsm_wait_replace_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_message_peer *mp = (struct cbc_message_peer *) fi->priv;
 | 
			
		||||
	struct osmo_cbsp_decoded *dec = NULL;
 | 
			
		||||
 | 
			
		||||
	switch (event) {
 | 
			
		||||
	case SMSCB_PEER_E_CBSP_REPLACE_ACK:
 | 
			
		||||
		dec = data;
 | 
			
		||||
		msg_peer_append_cbsp_compl(mp, &dec->u.write_replace_compl.num_compl_list);
 | 
			
		||||
		msg_peer_append_cbsp_cell(mp, &dec->u.write_replace_compl.cell_list);
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, SMSCB_S_ACTIVE, 0, 0);
 | 
			
		||||
		/* Signal parent fsm about completion */
 | 
			
		||||
		osmo_fsm_inst_dispatch(fi->proc.parent, SMSCB_MSG_E_REPLACE_ACK, mp);
 | 
			
		||||
		break;
 | 
			
		||||
	case SMSCB_PEER_E_CBSP_REPLACE_NACK:
 | 
			
		||||
		dec = data;
 | 
			
		||||
		msg_peer_append_cbsp_compl(mp, &dec->u.write_replace_fail.num_compl_list);
 | 
			
		||||
		msg_peer_append_cbsp_cell(mp, &dec->u.write_replace_fail.cell_list);
 | 
			
		||||
		msg_peer_append_cbsp_fail(mp, &dec->u.write_replace_fail.fail_list);
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, SMSCB_S_ACTIVE, 0, 0);
 | 
			
		||||
		/* Signal parent fsm about completion */
 | 
			
		||||
		osmo_fsm_inst_dispatch(fi->proc.parent, SMSCB_MSG_E_REPLACE_NACK, mp);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		OSMO_ASSERT(0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void smscb_p_fsm_wait_delete_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_message_peer *mp = (struct cbc_message_peer *) fi->priv;
 | 
			
		||||
	struct osmo_cbsp_decoded *dec = NULL;
 | 
			
		||||
 | 
			
		||||
	switch (event) {
 | 
			
		||||
	case SMSCB_PEER_E_CBSP_DELETE_ACK:
 | 
			
		||||
		dec = data;
 | 
			
		||||
		/* append results */
 | 
			
		||||
		msg_peer_append_cbsp_compl(mp, &dec->u.kill_compl.num_compl_list);
 | 
			
		||||
		msg_peer_append_cbsp_cell(mp, &dec->u.kill_compl.cell_list);
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, SMSCB_S_DELETED, 0, 0);
 | 
			
		||||
		/* Signal parent fsm about completion */
 | 
			
		||||
		osmo_fsm_inst_dispatch(fi->proc.parent, SMSCB_MSG_E_DELETE_ACK, mp);
 | 
			
		||||
		break;
 | 
			
		||||
	case SMSCB_PEER_E_CBSP_DELETE_NACK:
 | 
			
		||||
		dec = data;
 | 
			
		||||
		/* append results */
 | 
			
		||||
		msg_peer_append_cbsp_compl(mp, &dec->u.kill_fail.num_compl_list);
 | 
			
		||||
		msg_peer_append_cbsp_cell(mp, &dec->u.kill_fail.cell_list);
 | 
			
		||||
		msg_peer_append_cbsp_fail(mp, &dec->u.kill_fail.fail_list);
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, SMSCB_S_DELETED, 0, 0);
 | 
			
		||||
		/* Signal parent fsm about completion */
 | 
			
		||||
		osmo_fsm_inst_dispatch(fi->proc.parent, SMSCB_MSG_E_DELETE_NACK, mp);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		OSMO_ASSERT(0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int smscb_p_fsm_timer_cb(struct osmo_fsm_inst *fi)
 | 
			
		||||
{
 | 
			
		||||
	switch (fi->T) {
 | 
			
		||||
	case T_WAIT_WRITE_ACK:
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, SMSCB_S_ACTIVE, 0, 0);
 | 
			
		||||
		osmo_fsm_inst_dispatch(fi->proc.parent, SMSCB_PEER_E_CBSP_WRITE_NACK, NULL);
 | 
			
		||||
		break;
 | 
			
		||||
	case T_WAIT_REPLACE_ACK:
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, SMSCB_S_ACTIVE, 0, 0);
 | 
			
		||||
		osmo_fsm_inst_dispatch(fi->proc.parent, SMSCB_MSG_E_REPLACE_NACK, NULL);
 | 
			
		||||
		break;
 | 
			
		||||
	case T_WAIT_STATUS_ACK:
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, SMSCB_S_ACTIVE, 0, 0);
 | 
			
		||||
		osmo_fsm_inst_dispatch(fi->proc.parent, SMSCB_MSG_E_STATUS_NACK, NULL);
 | 
			
		||||
		break;
 | 
			
		||||
	case T_WAIT_DELETE_ACK:
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, SMSCB_S_DELETED, 0, 0);
 | 
			
		||||
		osmo_fsm_inst_dispatch(fi->proc.parent, SMSCB_PEER_E_CBSP_DELETE_NACK, NULL);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		OSMO_ASSERT(0);
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void smscb_p_fsm_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_message_peer *mp = (struct cbc_message_peer *) fi->priv;
 | 
			
		||||
	struct osmo_cbsp_decoded *cbsp;
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
	switch (event) {
 | 
			
		||||
	case SMSCB_PEER_E_DELETE: /* send KILL to BSC */
 | 
			
		||||
		switch (fi->state) {
 | 
			
		||||
		case SMSCB_S_DELETED:
 | 
			
		||||
		case SMSCB_S_INIT:
 | 
			
		||||
			LOGPFSML(fi, LOGL_ERROR, "Event %s not permitted\n",
 | 
			
		||||
				 osmo_fsm_event_name(fi->fsm, event));
 | 
			
		||||
			return;
 | 
			
		||||
		default:
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		cbsp = osmo_cbsp_decoded_alloc(mp->peer, CBSP_MSGT_KILL);
 | 
			
		||||
		OSMO_ASSERT(cbsp);
 | 
			
		||||
		cbsp->u.kill.msg_id = mp->cbcmsg->msg.message_id;
 | 
			
		||||
		cbsp->u.kill.old_serial_nr = mp->cbcmsg->msg.serial_nr;
 | 
			
		||||
		/* TODO: we assume that the delete will always affect all original cells */
 | 
			
		||||
		cbsp_append_cell_list(&cbsp->u.kill.cell_list, cbsp, mp);
 | 
			
		||||
		if (!mp->cbcmsg->msg.is_etws) {
 | 
			
		||||
			/* Channel Indication IE is only present in CBS, not in ETWS! */
 | 
			
		||||
			cbsp->u.kill.channel_ind = talloc_zero(cbsp, enum cbsp_channel_ind);
 | 
			
		||||
			OSMO_ASSERT(cbsp->u.kill.channel_ind);
 | 
			
		||||
			*(cbsp->u.kill.channel_ind) = CBSP_CHAN_IND_BASIC;
 | 
			
		||||
		}
 | 
			
		||||
		rc = cbc_cbsp_link_tx(mp->peer->link.cbsp, cbsp);
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, SMSCB_S_WAIT_DELETE_ACK, 10, T_WAIT_DELETE_ACK);
 | 
			
		||||
		if (rc != 0) /* Immediately timeout the message */
 | 
			
		||||
			fi->fsm->timer_cb(fi);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		OSMO_ASSERT(0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void smscb_p_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_message_peer *mp = (struct cbc_message_peer *) fi->priv;
 | 
			
		||||
	llist_del(&mp->list);
 | 
			
		||||
	/* memory of mp is child of fi and hence automatically free'd */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct osmo_fsm_state smscb_p_fsm_states[] = {
 | 
			
		||||
	[SMSCB_S_INIT] = {
 | 
			
		||||
		.name = "INIT",
 | 
			
		||||
		.in_event_mask = S(SMSCB_PEER_E_CREATE),
 | 
			
		||||
		.out_state_mask = S(SMSCB_S_WAIT_WRITE_ACK) |
 | 
			
		||||
				  S(SMSCB_S_ACTIVE),
 | 
			
		||||
		.action = smscb_p_fsm_init,
 | 
			
		||||
	},
 | 
			
		||||
	[SMSCB_S_WAIT_WRITE_ACK] = {
 | 
			
		||||
		.name = "WAIT_WRITE_ACK",
 | 
			
		||||
		.in_event_mask = S(SMSCB_PEER_E_CBSP_WRITE_ACK) |
 | 
			
		||||
				 S(SMSCB_PEER_E_CBSP_WRITE_NACK),
 | 
			
		||||
		.out_state_mask = S(SMSCB_S_ACTIVE) |
 | 
			
		||||
				  S(SMSCB_S_WAIT_DELETE_ACK),
 | 
			
		||||
		.action = smscb_p_fsm_wait_write_ack,
 | 
			
		||||
	},
 | 
			
		||||
	[SMSCB_S_ACTIVE] = {
 | 
			
		||||
		.name = "ACTIVE",
 | 
			
		||||
		.in_event_mask = S(SMSCB_PEER_E_REPLACE) |
 | 
			
		||||
				 S(SMSCB_PEER_E_STATUS),
 | 
			
		||||
		.out_state_mask = S(SMSCB_S_WAIT_REPLACE_ACK) |
 | 
			
		||||
				  S(SMSCB_S_WAIT_STATUS_ACK) |
 | 
			
		||||
				  S(SMSCB_S_WAIT_DELETE_ACK),
 | 
			
		||||
		.action = smscb_p_fsm_active,
 | 
			
		||||
	},
 | 
			
		||||
	[SMSCB_S_WAIT_STATUS_ACK] = {
 | 
			
		||||
		.name = "WAIT_STATUS_ACK",
 | 
			
		||||
		.in_event_mask = S(SMSCB_PEER_E_CBSP_STATUS_ACK) |
 | 
			
		||||
				 S(SMSCB_PEER_E_CBSP_STATUS_NACK),
 | 
			
		||||
		.out_state_mask = S(SMSCB_S_ACTIVE) |
 | 
			
		||||
				 S(SMSCB_S_WAIT_DELETE_ACK),
 | 
			
		||||
		.action = smscb_p_fsm_wait_status_ack,
 | 
			
		||||
	},
 | 
			
		||||
	[SMSCB_S_WAIT_REPLACE_ACK] = {
 | 
			
		||||
		.name = "WAIT_REPLACE_ACK",
 | 
			
		||||
		.in_event_mask = S(SMSCB_PEER_E_CBSP_REPLACE_ACK) |
 | 
			
		||||
				 S(SMSCB_PEER_E_CBSP_REPLACE_NACK),
 | 
			
		||||
		.out_state_mask = S(SMSCB_S_ACTIVE) |
 | 
			
		||||
				  S(SMSCB_S_WAIT_DELETE_ACK),
 | 
			
		||||
		.action = smscb_p_fsm_wait_replace_ack,
 | 
			
		||||
	},
 | 
			
		||||
	[SMSCB_S_WAIT_DELETE_ACK] = {
 | 
			
		||||
		.name = "WAIT_DELETE_ACK",
 | 
			
		||||
		.in_event_mask = S(SMSCB_PEER_E_CBSP_DELETE_ACK) |
 | 
			
		||||
				 S(SMSCB_PEER_E_CBSP_DELETE_NACK),
 | 
			
		||||
		.out_state_mask = S(SMSCB_S_DELETED),
 | 
			
		||||
		.action = smscb_p_fsm_wait_delete_ack,
 | 
			
		||||
	},
 | 
			
		||||
	[SMSCB_S_DELETED] = {
 | 
			
		||||
		.name = "DELETED",
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct osmo_fsm cbsp_smscb_peer_fsm = {
 | 
			
		||||
	.name = "SMSCB-PEER-CBSP",
 | 
			
		||||
	.states = smscb_p_fsm_states,
 | 
			
		||||
	.num_states = ARRAY_SIZE(smscb_p_fsm_states),
 | 
			
		||||
	.allstate_event_mask = S(SMSCB_PEER_E_DELETE),
 | 
			
		||||
	.allstate_action = smscb_p_fsm_allstate,
 | 
			
		||||
	.timer_cb = smscb_p_fsm_timer_cb,
 | 
			
		||||
	.log_subsys = DCBSP,
 | 
			
		||||
	.event_names = smscb_peer_fsm_event_names,
 | 
			
		||||
	.cleanup = smscb_p_fsm_cleanup,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static __attribute__((constructor)) void on_dso_load_smscb_p_fsm(void)
 | 
			
		||||
{
 | 
			
		||||
	OSMO_ASSERT(osmo_fsm_register(&cbsp_smscb_peer_fsm) == 0);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,237 +0,0 @@
 | 
			
		||||
/* Osmocom CBC (Cell Broacast Centre) */
 | 
			
		||||
 | 
			
		||||
/* (C) 2019 by Harald Welte <laforge@gnumonks.org>
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: AGPL-3.0+
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Affero General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/linuxlist.h>
 | 
			
		||||
#include <osmocom/core/utils.h>
 | 
			
		||||
#include <osmocom/gsm/cbsp.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/cbc/cbc_data.h>
 | 
			
		||||
#include <osmocom/cbc/cbsp_link.h>
 | 
			
		||||
#include <osmocom/cbc/sbcap_link.h>
 | 
			
		||||
#include <osmocom/cbc/sbcap_msg.h>
 | 
			
		||||
#include <osmocom/cbc/rest_it_op.h>
 | 
			
		||||
#include <osmocom/cbc/debug.h>
 | 
			
		||||
#include <osmocom/cbc/cbc_peer.h>
 | 
			
		||||
#include <osmocom/cbc/smscb_message_fsm.h>
 | 
			
		||||
 | 
			
		||||
/* convert cbc_message to osmo_cbsp_cell_list */
 | 
			
		||||
static int cbcmsg_to_cbsp_cell_list(const void *ctx, struct osmo_cbsp_cell_list *list,
 | 
			
		||||
				    const struct cbc_message *cbcmsg)
 | 
			
		||||
{
 | 
			
		||||
	struct osmo_cbsp_cell_ent *ent;
 | 
			
		||||
 | 
			
		||||
	switch (cbcmsg->scope) {
 | 
			
		||||
	case CBC_MSG_SCOPE_PLMN:
 | 
			
		||||
		list->id_discr = CELL_IDENT_BSS;
 | 
			
		||||
		ent = talloc_zero(ctx, struct osmo_cbsp_cell_ent);
 | 
			
		||||
		if (!ent)
 | 
			
		||||
			return -ENOMEM;
 | 
			
		||||
		//ent->cell_id = ?
 | 
			
		||||
		llist_add_tail(&ent->list, &list->list);
 | 
			
		||||
		return 0;
 | 
			
		||||
	default:
 | 
			
		||||
		OSMO_ASSERT(0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* generate a CBSP WRITE-REPLACE from our internal representation */
 | 
			
		||||
struct osmo_cbsp_decoded *cbcmsg_to_cbsp(void *ctx, const struct cbc_message *cbcmsg)
 | 
			
		||||
{
 | 
			
		||||
	struct osmo_cbsp_write_replace *wrepl;
 | 
			
		||||
	const struct smscb_message *smscb = &cbcmsg->msg;
 | 
			
		||||
	struct osmo_cbsp_decoded *cbsp = osmo_cbsp_decoded_alloc(ctx, CBSP_MSGT_WRITE_REPLACE);
 | 
			
		||||
	unsigned int i;
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
	if (!cbsp)
 | 
			
		||||
		return NULL;
 | 
			
		||||
	wrepl = &cbsp->u.write_replace;
 | 
			
		||||
 | 
			
		||||
	wrepl->msg_id = smscb->message_id;
 | 
			
		||||
	wrepl->new_serial_nr = smscb->serial_nr;
 | 
			
		||||
	/* FIXME: old? */
 | 
			
		||||
	/* Cell list */
 | 
			
		||||
	rc = cbcmsg_to_cbsp_cell_list(cbcmsg, &wrepl->cell_list, cbcmsg);
 | 
			
		||||
	if (rc < 0) {
 | 
			
		||||
		talloc_free(cbsp);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	if (!smscb->is_etws)
 | 
			
		||||
		wrepl->is_cbs = true;
 | 
			
		||||
	if (wrepl->is_cbs) {
 | 
			
		||||
		if (cbcmsg->extended_cbch)
 | 
			
		||||
			wrepl->u.cbs.channel_ind = CBSP_CHAN_IND_EXTENDED;
 | 
			
		||||
		else
 | 
			
		||||
			wrepl->u.cbs.channel_ind = CBSP_CHAN_IND_BASIC;
 | 
			
		||||
		wrepl->u.cbs.category = cbcmsg->priority;
 | 
			
		||||
		wrepl->u.cbs.rep_period = cbcmsg->rep_period;
 | 
			
		||||
		wrepl->u.cbs.num_bcast_req = cbcmsg->num_bcast;
 | 
			
		||||
		wrepl->u.cbs.dcs = smscb->cbs.dcs;
 | 
			
		||||
		INIT_LLIST_HEAD(&wrepl->u.cbs.msg_content);
 | 
			
		||||
		for (i = 0; i < smscb->cbs.num_pages; i++) {
 | 
			
		||||
			struct osmo_cbsp_content *ce = talloc_zero(cbsp, struct osmo_cbsp_content);
 | 
			
		||||
			if (i == smscb->cbs.num_pages - 1)
 | 
			
		||||
				ce->user_len = smscb->cbs.data_user_len - (i * SMSCB_RAW_PAGE_LEN);
 | 
			
		||||
			else
 | 
			
		||||
				ce->user_len = SMSCB_RAW_PAGE_LEN;
 | 
			
		||||
			memcpy(ce->data, smscb->cbs.data[i], SMSCB_RAW_PAGE_LEN);
 | 
			
		||||
			llist_add_tail(&ce->list, &wrepl->u.cbs.msg_content);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		wrepl->u.emergency.indicator = 1;
 | 
			
		||||
		wrepl->u.emergency.warning_type = (smscb->etws.warning_type & 0x7f) << 9;
 | 
			
		||||
		if (smscb->etws.user_alert)
 | 
			
		||||
			wrepl->u.emergency.warning_type |= 0x0100;
 | 
			
		||||
		if (smscb->etws.popup_on_display)
 | 
			
		||||
			wrepl->u.emergency.warning_type |= 0x0080;
 | 
			
		||||
		memcpy(wrepl->u.emergency.warning_sec_info, smscb->etws.warning_sec_info,
 | 
			
		||||
			sizeof(wrepl->u.emergency.warning_sec_info));
 | 
			
		||||
		if (cbcmsg->warning_period_sec == 0xffffffff)
 | 
			
		||||
			wrepl->u.emergency.warning_period = 0;
 | 
			
		||||
		else
 | 
			
		||||
			wrepl->u.emergency.warning_period = cbcmsg->warning_period_sec;
 | 
			
		||||
	}
 | 
			
		||||
	return cbsp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* determine if peer is within scope of cbc_msg */
 | 
			
		||||
static bool is_peer_in_scope(const struct cbc_peer *peer, const struct cbc_message *cbcmsg)
 | 
			
		||||
{
 | 
			
		||||
	switch (cbcmsg->scope) {
 | 
			
		||||
	case CBC_MSG_SCOPE_PLMN:
 | 
			
		||||
		return true;
 | 
			
		||||
	/* FIXME: differnt scopes */
 | 
			
		||||
	default:
 | 
			
		||||
		OSMO_ASSERT(0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* send given new message to given peer */
 | 
			
		||||
int peer_new_cbc_message(struct cbc_peer *peer, struct cbc_message *cbcmsg)
 | 
			
		||||
{
 | 
			
		||||
	struct osmo_cbsp_decoded *cbsp;
 | 
			
		||||
	SBcAP_SBC_AP_PDU_t *sbcap;
 | 
			
		||||
 | 
			
		||||
	switch (peer->proto) {
 | 
			
		||||
	case CBC_PEER_PROTO_CBSP:
 | 
			
		||||
		/* skip peers without any current CBSP connection */
 | 
			
		||||
		if (!peer->link.cbsp) {
 | 
			
		||||
			LOGP(DCBSP, LOGL_NOTICE, "[%s] Tx CBSP: not connected\n",
 | 
			
		||||
			     peer->name);
 | 
			
		||||
			return -ENOTCONN;
 | 
			
		||||
		}
 | 
			
		||||
		if (!(cbsp = cbcmsg_to_cbsp(peer, cbcmsg))) {
 | 
			
		||||
			LOGP(DCBSP, LOGL_ERROR, "[%s] Tx CBSP: msg gen failed\n",
 | 
			
		||||
			     peer->name);
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		cbc_cbsp_link_tx(peer->link.cbsp, cbsp);
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_PEER_PROTO_SBcAP:
 | 
			
		||||
		/* skip peers without any current SBc-AP connection */
 | 
			
		||||
		if (!peer->link.sbcap) {
 | 
			
		||||
			LOGP(DSBcAP, LOGL_NOTICE, "[%s] Tx SBc-AP: not connected\n",
 | 
			
		||||
			     peer->name);
 | 
			
		||||
			return -ENOTCONN;
 | 
			
		||||
		}
 | 
			
		||||
		if (!(sbcap = cbcmsg_to_sbcap(peer, cbcmsg))) {
 | 
			
		||||
			LOGP(DSBcAP, LOGL_ERROR, "[%s] Tx SBc-AP: msg gen failed\n",
 | 
			
		||||
			     peer->name);
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
		cbc_sbcap_link_tx(peer->link.sbcap, sbcap);
 | 
			
		||||
		break;
 | 
			
		||||
	case CBC_PEER_PROTO_SABP:
 | 
			
		||||
		LOGP(DLGLOBAL, LOGL_ERROR, "Sending message to peer proto %s not implemented!\n",
 | 
			
		||||
		     get_value_string(cbc_peer_proto_name, peer->proto));
 | 
			
		||||
		return -1;
 | 
			
		||||
	default:
 | 
			
		||||
		OSMO_ASSERT(0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* receive a new CBC message from the user (REST). Allocates new memory,
 | 
			
		||||
 * a FSM, copies data from 'orig', routes to all peers and starts FSMs.
 | 
			
		||||
 * Once the operation is complete (success, error, timeout) we must
 | 
			
		||||
 * notify osmo_it_q of the completion */
 | 
			
		||||
int cbc_message_new(const struct cbc_message *orig, struct rest_it_op *op)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_message *cbcmsg = cbc_message_alloc(g_cbc, orig);
 | 
			
		||||
	struct cbc_peer *peer;
 | 
			
		||||
 | 
			
		||||
	if (!cbcmsg) {
 | 
			
		||||
		rest_it_op_set_http_result(op, 409, "Could not allocate");
 | 
			
		||||
		rest_it_op_complete(op);
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	OSMO_ASSERT(llist_empty(&cbcmsg->peers));
 | 
			
		||||
 | 
			
		||||
	/* iterate over all peers */
 | 
			
		||||
	llist_for_each_entry(peer, &g_cbc->peers, list) {
 | 
			
		||||
		struct cbc_message_peer *mp;
 | 
			
		||||
 | 
			
		||||
		if (!is_peer_in_scope(peer, cbcmsg))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		/* allocate new cbc_mesage_peer + related FSM */
 | 
			
		||||
		mp = smscb_peer_fsm_alloc(peer, cbcmsg);
 | 
			
		||||
		if (!mp) {
 | 
			
		||||
			LOGP(DCBSP, LOGL_ERROR, "Cannot allocate cbc_message_peer\n");
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* kick off the state machine[s] */
 | 
			
		||||
	if (osmo_fsm_inst_dispatch(cbcmsg->fi, SMSCB_E_CREATE, op) < 0) {
 | 
			
		||||
		rest_it_op_set_http_result(op, 500, "Illegal FSM event");
 | 
			
		||||
		rest_it_op_complete(op);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* we continue in the FSM after the WRITE_ACK event was received */
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cbc_message_delete(struct cbc_message *cbcmsg, struct rest_it_op *op)
 | 
			
		||||
{
 | 
			
		||||
	if (osmo_fsm_inst_dispatch(cbcmsg->fi, SMSCB_E_DELETE, op) < 0) {
 | 
			
		||||
		rest_it_op_set_http_result(op, 500, "Illegal FSM event");
 | 
			
		||||
		rest_it_op_complete(op);
 | 
			
		||||
	}
 | 
			
		||||
	/* we continue in the FSM after the DELETE_ACK event was received */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct cbc_message *cbc_message_by_id(uint16_t message_id)
 | 
			
		||||
{
 | 
			
		||||
	struct cbc_message *cbc_msg;
 | 
			
		||||
	llist_for_each_entry(cbc_msg, &g_cbc->messages, list) {
 | 
			
		||||
		if (cbc_msg->msg.message_id == message_id)
 | 
			
		||||
			return cbc_msg;
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
@@ -33,6 +33,8 @@ ASN_MODULE_SRC = \
 | 
			
		||||
	gen/constr_SET_OF_print.c \
 | 
			
		||||
	gen/constr_SET_OF_rfill.c \
 | 
			
		||||
	gen/constr_TYPE.c \
 | 
			
		||||
	gen/ENUMERATED.c \
 | 
			
		||||
	gen/ENUMERATED_aper.c \
 | 
			
		||||
	gen/GraphicString.c \
 | 
			
		||||
	gen/INTEGER_aper.c \
 | 
			
		||||
	gen/INTEGER.c \
 | 
			
		||||
@@ -348,7 +350,9 @@ SKEL_HEADER_FILES = \
 | 
			
		||||
	skel/constr_TYPE.h \
 | 
			
		||||
	skel/constraints.h \
 | 
			
		||||
	skel/der_encoder.h \
 | 
			
		||||
	skel/jer_decoder.h \
 | 
			
		||||
	skel/jer_encoder.h \
 | 
			
		||||
	skel/jer_support.h \
 | 
			
		||||
	skel/oer_decoder.h \
 | 
			
		||||
	skel/oer_encoder.h \
 | 
			
		||||
	skel/oer_support.h \
 | 
			
		||||
@@ -374,9 +378,9 @@ noinst_LTLIBRARIES=libosmo-asn1-sbcap.la
 | 
			
		||||
libosmo_asn1_sbcap_la_SOURCES=$(ASN_MODULE_SRC)
 | 
			
		||||
libosmo_asn1_sbcap_la_LIBADD=$(ASN1C_LDADD)
 | 
			
		||||
 | 
			
		||||
sbcap_LIBVERSION=0:0:0
 | 
			
		||||
sbcap_LIBVERSION=2:0:0
 | 
			
		||||
lib_LTLIBRARIES = libosmo-sbcap.la
 | 
			
		||||
libosmo_sbcap_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(sbcap_LIBVERSION)
 | 
			
		||||
libosmo_sbcap_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(sbcap_LIBVERSION) -no-undefined
 | 
			
		||||
libosmo_sbcap_la_LIBADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) \
 | 
			
		||||
		                  $(ASN1C_LIBS) libosmo-asn1-sbcap.la
 | 
			
		||||
libosmo_sbcap_la_SOURCES = sbcap_common.c
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ asn_TYPE_operation_t asn_OP_ANY = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
 | 
			
		||||
    OCTET_STRING_compare,
 | 
			
		||||
    OCTET_STRING_copy,
 | 
			
		||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
 | 
			
		||||
    OCTET_STRING_decode_ber,
 | 
			
		||||
    OCTET_STRING_encode_der,
 | 
			
		||||
@@ -33,9 +34,11 @@ asn_TYPE_operation_t asn_OP_ANY = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
    OCTET_STRING_decode_jer_hex,
 | 
			
		||||
    ANY_encode_jer,
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
 | 
			
		||||
    0,
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@ asn_TYPE_operation_t asn_OP_BIT_STRING = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
 | 
			
		||||
    BIT_STRING_compare,
 | 
			
		||||
    BIT_STRING_copy,
 | 
			
		||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
 | 
			
		||||
    OCTET_STRING_decode_ber,   /* Implemented in terms of OCTET STRING */
 | 
			
		||||
    OCTET_STRING_encode_der,   /* Implemented in terms of OCTET STRING */
 | 
			
		||||
@@ -39,9 +40,11 @@ asn_TYPE_operation_t asn_OP_BIT_STRING = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
    OCTET_STRING_decode_jer_hex,
 | 
			
		||||
    BIT_STRING_encode_jer,
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
 | 
			
		||||
    BIT_STRING_decode_oer,
 | 
			
		||||
@@ -211,3 +214,37 @@ BIT_STRING_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
BIT_STRING_copy(const asn_TYPE_descriptor_t *td, void **aptr,
 | 
			
		||||
                const void *bptr) {
 | 
			
		||||
    const asn_OCTET_STRING_specifics_t *specs = td->specifics;
 | 
			
		||||
    BIT_STRING_t *a = (BIT_STRING_t *)*aptr;
 | 
			
		||||
    const BIT_STRING_t *b = (const BIT_STRING_t *)bptr;
 | 
			
		||||
 | 
			
		||||
    if(!b) {
 | 
			
		||||
        if(a) {
 | 
			
		||||
            FREEMEM(a->buf);
 | 
			
		||||
            FREEMEM(a);
 | 
			
		||||
            *aptr = 0;
 | 
			
		||||
        }
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(!a) {
 | 
			
		||||
        a = *aptr = CALLOC(1, specs->struct_size);
 | 
			
		||||
        if(!a) return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint8_t* buf = MALLOC(b->size + 1);
 | 
			
		||||
    if(!buf) return -1;
 | 
			
		||||
    memcpy(buf, b->buf, b->size);
 | 
			
		||||
    buf[b->size] = 0;
 | 
			
		||||
 | 
			
		||||
    FREEMEM(a->buf);
 | 
			
		||||
    a->buf = buf;
 | 
			
		||||
    a->size = b->size;
 | 
			
		||||
    a->bits_unused = b->bits_unused;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										92
									
								
								src/sbcap/gen/ENUMERATED.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/sbcap/gen/ENUMERATED.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,92 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright (c) 2003, 2005, 2006 Lev Walkin <vlm@lionet.info>.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 * Redistribution and modifications are permitted subject to BSD license.
 | 
			
		||||
 */
 | 
			
		||||
#include <asn_internal.h>
 | 
			
		||||
#include <ENUMERATED.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * ENUMERATED basic type description.
 | 
			
		||||
 */
 | 
			
		||||
static const ber_tlv_tag_t asn_DEF_ENUMERATED_tags[] = {
 | 
			
		||||
    (ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
 | 
			
		||||
};
 | 
			
		||||
asn_TYPE_operation_t asn_OP_ENUMERATED = {
 | 
			
		||||
    ASN__PRIMITIVE_TYPE_free,
 | 
			
		||||
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
 | 
			
		||||
    INTEGER_print,  /* Implemented in terms of INTEGER */
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
 | 
			
		||||
    INTEGER_compare,  /* Implemented in terms of INTEGER */
 | 
			
		||||
    INTEGER_copy,  /* Implemented in terms of INTEGER */
 | 
			
		||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
 | 
			
		||||
    ber_decode_primitive,
 | 
			
		||||
    INTEGER_encode_der,  /* Implemented in terms of INTEGER */
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_BER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
 | 
			
		||||
    INTEGER_decode_xer,  /* This is temporary! */
 | 
			
		||||
    INTEGER_encode_xer,
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
    ENUMERATED_decode_jer,
 | 
			
		||||
    INTEGER_encode_jer,
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
 | 
			
		||||
    ENUMERATED_decode_oer,
 | 
			
		||||
    ENUMERATED_encode_oer,
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_OER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_UPER_SUPPORT)
 | 
			
		||||
    ENUMERATED_decode_uper,  /* Unaligned PER decoder */
 | 
			
		||||
    ENUMERATED_encode_uper,  /* Unaligned PER encoder */
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_APER_SUPPORT)
 | 
			
		||||
    ENUMERATED_decode_aper,  /* Aligned PER decoder */
 | 
			
		||||
    ENUMERATED_encode_aper,  /* Aligned PER encoder */
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_APER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
 | 
			
		||||
    ENUMERATED_random_fill,
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
 | 
			
		||||
    0  /* Use generic outmost tag fetcher */
 | 
			
		||||
};
 | 
			
		||||
asn_TYPE_descriptor_t asn_DEF_ENUMERATED = {
 | 
			
		||||
    "ENUMERATED",
 | 
			
		||||
    "ENUMERATED",
 | 
			
		||||
    &asn_OP_ENUMERATED,
 | 
			
		||||
    asn_DEF_ENUMERATED_tags,
 | 
			
		||||
    sizeof(asn_DEF_ENUMERATED_tags) / sizeof(asn_DEF_ENUMERATED_tags[0]),
 | 
			
		||||
    asn_DEF_ENUMERATED_tags,	/* Same as above */
 | 
			
		||||
    sizeof(asn_DEF_ENUMERATED_tags) / sizeof(asn_DEF_ENUMERATED_tags[0]),
 | 
			
		||||
    {
 | 
			
		||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
 | 
			
		||||
        0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_OER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
 | 
			
		||||
        0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
 | 
			
		||||
        asn_generic_no_constraint
 | 
			
		||||
    },
 | 
			
		||||
    0, 0,  /* No members */
 | 
			
		||||
    0  /* No specifics */
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										43
									
								
								src/sbcap/gen/ENUMERATED_aper.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/sbcap/gen/ENUMERATED_aper.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 * Redistribution and modifications are permitted subject to BSD license.
 | 
			
		||||
 */
 | 
			
		||||
#include <asn_internal.h>
 | 
			
		||||
#include <ENUMERATED.h>
 | 
			
		||||
#include <NativeEnumerated.h>
 | 
			
		||||
 | 
			
		||||
asn_dec_rval_t
 | 
			
		||||
ENUMERATED_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
 | 
			
		||||
                       const asn_TYPE_descriptor_t *td,
 | 
			
		||||
                       const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
 | 
			
		||||
    asn_dec_rval_t rval;
 | 
			
		||||
    ENUMERATED_t *st = (ENUMERATED_t *)*sptr;
 | 
			
		||||
    long value;
 | 
			
		||||
    void *vptr = &value;
 | 
			
		||||
 | 
			
		||||
    if(!st) {
 | 
			
		||||
        st = (ENUMERATED_t *)(*sptr = CALLOC(1, sizeof(*st)));
 | 
			
		||||
        if(!st) ASN__DECODE_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rval = NativeEnumerated_decode_aper(opt_codec_ctx, td, constraints,
 | 
			
		||||
                                        (void **)&vptr, pd);
 | 
			
		||||
    if(rval.code == RC_OK)
 | 
			
		||||
        if(asn_long2INTEGER(st, value))
 | 
			
		||||
            rval.code = RC_FAIL;
 | 
			
		||||
    return rval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
asn_enc_rval_t
 | 
			
		||||
ENUMERATED_encode_aper(const asn_TYPE_descriptor_t *td,
 | 
			
		||||
                       const asn_per_constraints_t *constraints,
 | 
			
		||||
                       const void *sptr, asn_per_outp_t *po) {
 | 
			
		||||
    const ENUMERATED_t *st = (const ENUMERATED_t *)sptr;
 | 
			
		||||
    long value;
 | 
			
		||||
 | 
			
		||||
    if(asn_INTEGER2long(st, &value))
 | 
			
		||||
        ASN__ENCODE_FAILED;
 | 
			
		||||
 | 
			
		||||
    return NativeEnumerated_encode_aper(td, constraints, &value, po);
 | 
			
		||||
}
 | 
			
		||||
@@ -20,6 +20,7 @@ asn_TYPE_operation_t asn_OP_GraphicString = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
 | 
			
		||||
    OCTET_STRING_compare,
 | 
			
		||||
    OCTET_STRING_copy,
 | 
			
		||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
 | 
			
		||||
    OCTET_STRING_decode_ber,  /* Implemented in terms of OCTET STRING */
 | 
			
		||||
    OCTET_STRING_encode_der,
 | 
			
		||||
@@ -35,9 +36,11 @@ asn_TYPE_operation_t asn_OP_GraphicString = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
    OCTET_STRING_decode_jer_hex,
 | 
			
		||||
    OCTET_STRING_encode_jer,  /* Can't expect it to be ASCII/UTF8 */
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
 | 
			
		||||
    OCTET_STRING_decode_oer,
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@ asn_TYPE_operation_t asn_OP_INTEGER = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
 | 
			
		||||
    INTEGER_compare,
 | 
			
		||||
    INTEGER_copy,
 | 
			
		||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
 | 
			
		||||
    ber_decode_primitive,
 | 
			
		||||
    INTEGER_encode_der,
 | 
			
		||||
@@ -37,9 +38,11 @@ asn_TYPE_operation_t asn_OP_INTEGER = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
    INTEGER_decode_jer,
 | 
			
		||||
    INTEGER_encode_jer,
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
 | 
			
		||||
    INTEGER_decode_oer,  /* OER decoder */
 | 
			
		||||
@@ -361,7 +364,8 @@ asn_imax2INTEGER(INTEGER_t *st, intmax_t value) {
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	/* Copy the integer body */
 | 
			
		||||
	for(bp = buf, pend1 += add; p != pend1; p += add)
 | 
			
		||||
	pend1 += add;
 | 
			
		||||
	for(bp = buf; p != pend1; p += add)
 | 
			
		||||
		*bp++ = *p;
 | 
			
		||||
 | 
			
		||||
	if(st->buf) FREEMEM(st->buf);
 | 
			
		||||
@@ -411,6 +415,33 @@ asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
 | 
			
		||||
    return asn_imax2INTEGER(st, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int asn_INTEGER2int64(const INTEGER_t *st, int64_t *value) {
 | 
			
		||||
    intmax_t v;
 | 
			
		||||
    if(asn_INTEGER2imax(st, &v) == 0) {
 | 
			
		||||
        if(v < INT64_MIN || v > INT64_MAX) {
 | 
			
		||||
            errno = ERANGE;
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        *value = v;
 | 
			
		||||
        return 0;
 | 
			
		||||
    } else {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int asn_INTEGER2uint64(const INTEGER_t *st, uint64_t *value) {
 | 
			
		||||
    uintmax_t v;
 | 
			
		||||
    if(asn_INTEGER2umax(st, &v) == 0) {
 | 
			
		||||
        if(v > UINT64_MAX) {
 | 
			
		||||
            errno = ERANGE;
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        *value = v;
 | 
			
		||||
        return 0;
 | 
			
		||||
    } else {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
asn_uint642INTEGER(INTEGER_t *st, uint64_t value) {
 | 
			
		||||
@@ -736,3 +767,40 @@ INTEGER_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
INTEGER_copy(const asn_TYPE_descriptor_t *td, void **aptr,
 | 
			
		||||
                     const void *bptr) {
 | 
			
		||||
    (void)td;
 | 
			
		||||
    INTEGER_t *a = *aptr;
 | 
			
		||||
    const INTEGER_t *b = bptr;
 | 
			
		||||
 | 
			
		||||
    if(!b) {
 | 
			
		||||
        if(a) {
 | 
			
		||||
            FREEMEM(a->buf);
 | 
			
		||||
            FREEMEM(a);
 | 
			
		||||
            *aptr = 0;
 | 
			
		||||
        }
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(!a) {
 | 
			
		||||
        a = *aptr = CALLOC(1, sizeof(*a));
 | 
			
		||||
        if(!a) return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(b->size) {
 | 
			
		||||
        uint8_t* buf = MALLOC(b->size);
 | 
			
		||||
        if(!buf) return -1;
 | 
			
		||||
        memcpy(buf, b->buf, b->size);
 | 
			
		||||
        FREEMEM(a->buf);
 | 
			
		||||
        a->buf = buf;
 | 
			
		||||
        a->size = b->size;
 | 
			
		||||
    } else {
 | 
			
		||||
        FREEMEM(a->buf);
 | 
			
		||||
        a->buf = 0;
 | 
			
		||||
        a->size = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -57,7 +57,7 @@ INTEGER_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
 | 
			
		||||
                int max_range_bytes = (ct->range_bits >> 3) +
 | 
			
		||||
                                      (((ct->range_bits % 8) > 0) ? 1 : 0);
 | 
			
		||||
                int length = 0, i;
 | 
			
		||||
                long value = 0;
 | 
			
		||||
                intmax_t value = 0;
 | 
			
		||||
 | 
			
		||||
                for (i = 1; ; i++) {
 | 
			
		||||
                    int upper = 1 << i;
 | 
			
		||||
@@ -79,18 +79,18 @@ INTEGER_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
 | 
			
		||||
                    int buf = per_get_few_bits(pd, 8);
 | 
			
		||||
                    if (buf < 0)
 | 
			
		||||
                        ASN__DECODE_FAILED;
 | 
			
		||||
                    value += (((long)buf) << (8 * length));
 | 
			
		||||
                    value += (((intmax_t)buf) << (8 * length));
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                value += ct->lower_bound;
 | 
			
		||||
                if((specs && specs->field_unsigned)
 | 
			
		||||
                        ? asn_uint642INTEGER(st, (unsigned long)value)
 | 
			
		||||
                        : asn_int642INTEGER(st, value))
 | 
			
		||||
                        ? asn_umax2INTEGER(st, (uintmax_t)value)
 | 
			
		||||
                        : asn_imax2INTEGER(st, value))
 | 
			
		||||
                    ASN__DECODE_FAILED;
 | 
			
		||||
                ASN_DEBUG("Got value %ld + low %lld",
 | 
			
		||||
                          value, (long long int)ct->lower_bound);
 | 
			
		||||
                ASN_DEBUG("Got value %"ASN_PRIdMAX" + low %"ASN_PRIdMAX"",
 | 
			
		||||
                          value, (intmax_t)ct->lower_bound);
 | 
			
		||||
            } else {
 | 
			
		||||
                long value = 0;
 | 
			
		||||
                intmax_t value = 0;
 | 
			
		||||
                if (ct->range_bits < 8) {
 | 
			
		||||
                    value = per_get_few_bits(pd, ct->range_bits);
 | 
			
		||||
                    if(value < 0) ASN__DECODE_STARVED;
 | 
			
		||||
@@ -108,11 +108,11 @@ INTEGER_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
 | 
			
		||||
                }
 | 
			
		||||
                value += ct->lower_bound;
 | 
			
		||||
                if((specs && specs->field_unsigned)
 | 
			
		||||
                        ? asn_ulong2INTEGER(st, value)
 | 
			
		||||
                        : asn_long2INTEGER(st, value))
 | 
			
		||||
                        ? asn_umax2INTEGER(st, (uintmax_t)value)
 | 
			
		||||
                        : asn_imax2INTEGER(st, value))
 | 
			
		||||
                    ASN__DECODE_FAILED;
 | 
			
		||||
                ASN_DEBUG("Got value %ld + low %lld",
 | 
			
		||||
                          value, (long long int)ct->lower_bound);
 | 
			
		||||
                ASN_DEBUG("Got value %"ASN_PRIdMAX" + low %"ASN_PRIdMAX"",
 | 
			
		||||
                          value, (intmax_t)ct->lower_bound);
 | 
			
		||||
            }
 | 
			
		||||
            return rval;
 | 
			
		||||
        } else {
 | 
			
		||||
@@ -167,7 +167,7 @@ INTEGER_encode_aper(const asn_TYPE_descriptor_t *td,
 | 
			
		||||
    const uint8_t *buf;
 | 
			
		||||
    const uint8_t *end;
 | 
			
		||||
    const asn_per_constraint_t *ct;
 | 
			
		||||
    long value = 0;
 | 
			
		||||
    intmax_t value = 0;
 | 
			
		||||
 | 
			
		||||
    if(!st || st->size == 0) ASN__ENCODE_FAILED;
 | 
			
		||||
 | 
			
		||||
@@ -179,26 +179,26 @@ INTEGER_encode_aper(const asn_TYPE_descriptor_t *td,
 | 
			
		||||
    if(ct) {
 | 
			
		||||
        int inext = 0;
 | 
			
		||||
        if(specs && specs->field_unsigned) {
 | 
			
		||||
            unsigned long uval;
 | 
			
		||||
            if(asn_INTEGER2ulong(st, &uval))
 | 
			
		||||
            uintmax_t uval;
 | 
			
		||||
            if(asn_INTEGER2umax(st, &uval))
 | 
			
		||||
                ASN__ENCODE_FAILED;
 | 
			
		||||
            /* Check proper range */
 | 
			
		||||
            if(ct->flags & APC_SEMI_CONSTRAINED) {
 | 
			
		||||
                if(uval < (unsigned long)ct->lower_bound)
 | 
			
		||||
                if(uval < (uintmax_t)ct->lower_bound)
 | 
			
		||||
                    inext = 1;
 | 
			
		||||
            } else if(ct->range_bits >= 0) {
 | 
			
		||||
                if(uval < (unsigned long)ct->lower_bound
 | 
			
		||||
                        || uval > (unsigned long)ct->upper_bound)
 | 
			
		||||
                if(uval < (uintmax_t)ct->lower_bound
 | 
			
		||||
                        || uval > (uintmax_t)ct->upper_bound)
 | 
			
		||||
                    inext = 1;
 | 
			
		||||
            }
 | 
			
		||||
            ASN_DEBUG("Value %lu (%02x/%zu) lb %lld ub %lld %s",
 | 
			
		||||
            ASN_DEBUG("Value %"ASN_PRIdMAX" (%02x/%"ASN_PRI_SIZE") lb %"ASN_PRIdMAX" ub %"ASN_PRIdMAX" %s",
 | 
			
		||||
                      uval, st->buf[0], st->size,
 | 
			
		||||
                      (long long int)ct->lower_bound,
 | 
			
		||||
                      (long long int)ct->upper_bound,
 | 
			
		||||
                      (intmax_t)ct->lower_bound,
 | 
			
		||||
                      (intmax_t)ct->upper_bound,
 | 
			
		||||
                      inext ? "ext" : "fix");
 | 
			
		||||
            value = uval;
 | 
			
		||||
        } else {
 | 
			
		||||
            if(asn_INTEGER2long(st, &value)) ASN__ENCODE_FAILED;
 | 
			
		||||
            if(asn_INTEGER2imax(st, &value)) ASN__ENCODE_FAILED;
 | 
			
		||||
            /* Check proper range */
 | 
			
		||||
            if(ct->flags & APC_SEMI_CONSTRAINED) {
 | 
			
		||||
                if(value < ct->lower_bound)
 | 
			
		||||
@@ -208,10 +208,10 @@ INTEGER_encode_aper(const asn_TYPE_descriptor_t *td,
 | 
			
		||||
                        || value > ct->upper_bound)
 | 
			
		||||
                    inext = 1;
 | 
			
		||||
            }
 | 
			
		||||
            ASN_DEBUG("Value %lu (%02x/%zu) lb %lld ub %lld %s",
 | 
			
		||||
            ASN_DEBUG("Value %"ASN_PRIdMAX" (%02x/%"ASN_PRI_SIZE") lb %"ASN_PRIdMAX" ub %"ASN_PRIdMAX" %s",
 | 
			
		||||
                      value, st->buf[0], st->size,
 | 
			
		||||
                      (long long int)ct->lower_bound,
 | 
			
		||||
                      (long long int)ct->upper_bound,
 | 
			
		||||
                      (intmax_t)ct->lower_bound,
 | 
			
		||||
                      (intmax_t)ct->upper_bound,
 | 
			
		||||
                      inext ? "ext" : "fix");
 | 
			
		||||
        }
 | 
			
		||||
        if(ct->flags & APC_EXTENSIBLE) {
 | 
			
		||||
@@ -225,11 +225,11 @@ INTEGER_encode_aper(const asn_TYPE_descriptor_t *td,
 | 
			
		||||
 | 
			
		||||
    /* X.691, #12.2.2 */
 | 
			
		||||
    if(ct && ct->range_bits >= 0) {
 | 
			
		||||
        unsigned long v;
 | 
			
		||||
        uintmax_t v;
 | 
			
		||||
 | 
			
		||||
        /* #10.5.6 */
 | 
			
		||||
        ASN_DEBUG("Encoding integer %ld (%lld) with range %d bits",
 | 
			
		||||
                  value, (long long int)(value - ct->lower_bound),
 | 
			
		||||
        ASN_DEBUG("Encoding integer %"ASN_PRIdMAX" (%"ASN_PRIdMAX") with range %d bits",
 | 
			
		||||
                  value, (intmax_t)(value - ct->lower_bound),
 | 
			
		||||
                  ct->range_bits);
 | 
			
		||||
 | 
			
		||||
        v = value - ct->lower_bound;
 | 
			
		||||
@@ -287,7 +287,7 @@ INTEGER_encode_aper(const asn_TYPE_descriptor_t *td,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(ct && ct->lower_bound) {
 | 
			
		||||
        ASN_DEBUG("Adjust lower bound to %lld", (long long int)ct->lower_bound);
 | 
			
		||||
        ASN_DEBUG("Adjust lower bound to %"ASN_PRIdMAX"", (intmax_t)ct->lower_bound);
 | 
			
		||||
        /* TODO: adjust lower bound */
 | 
			
		||||
        ASN__ENCODE_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ asn_TYPE_operation_t asn_OP_NativeEnumerated = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
 | 
			
		||||
    NativeInteger_compare,
 | 
			
		||||
    NativeInteger_copy,
 | 
			
		||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
 | 
			
		||||
    NativeInteger_decode_ber,
 | 
			
		||||
    NativeInteger_encode_der,
 | 
			
		||||
@@ -41,9 +42,11 @@ asn_TYPE_operation_t asn_OP_NativeEnumerated = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
    NativeEnumerated_decode_jer,
 | 
			
		||||
    NativeEnumerated_encode_jer,
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
 | 
			
		||||
    NativeEnumerated_decode_oer,
 | 
			
		||||
 
 | 
			
		||||
@@ -64,7 +64,7 @@ NativeEnumerated_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        /* XXX handle indefinite index length > 64k */
 | 
			
		||||
        value = aper_get_nsnnwn(pd, 65537);
 | 
			
		||||
        value = aper_get_nsnnwn(pd);
 | 
			
		||||
        if(value < 0) ASN__DECODE_STARVED;
 | 
			
		||||
        value += specs->extension - 1;
 | 
			
		||||
        //if(value >= specs->map_count)
 | 
			
		||||
@@ -148,9 +148,7 @@ NativeEnumerated_encode_aper(const asn_TYPE_descriptor_t *td,
 | 
			
		||||
    ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
 | 
			
		||||
              value, specs->extension, inext,
 | 
			
		||||
              value - (inext ? (specs->extension - 1) : 0));
 | 
			
		||||
    if(aper_put_nsnnwn(po,
 | 
			
		||||
                       ct->upper_bound - ct->lower_bound + 1,
 | 
			
		||||
                       value - (inext ? (specs->extension - 1) : 0)))
 | 
			
		||||
    if(aper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
 | 
			
		||||
        ASN__ENCODE_FAILED;
 | 
			
		||||
 | 
			
		||||
    ASN__ENCODED_OK(er);
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@ asn_TYPE_operation_t asn_OP_NativeInteger = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
 | 
			
		||||
    NativeInteger_compare,
 | 
			
		||||
    NativeInteger_copy,
 | 
			
		||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
 | 
			
		||||
    NativeInteger_decode_ber,
 | 
			
		||||
    NativeInteger_encode_der,
 | 
			
		||||
@@ -42,9 +43,11 @@ asn_TYPE_operation_t asn_OP_NativeInteger = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
    NativeInteger_decode_jer,
 | 
			
		||||
    NativeInteger_encode_jer,
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
 | 
			
		||||
    NativeInteger_decode_oer,  /* OER decoder */
 | 
			
		||||
@@ -150,3 +153,30 @@ NativeInteger_compare(const asn_TYPE_descriptor_t *td, const void *aptr, const v
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
NativeInteger_copy(const asn_TYPE_descriptor_t *td, void **aptr, const void *bptr) {
 | 
			
		||||
    unsigned long *a = *aptr;
 | 
			
		||||
    const unsigned long *b = bptr;
 | 
			
		||||
 | 
			
		||||
    (void)td;
 | 
			
		||||
 | 
			
		||||
    /* Check if source has data */
 | 
			
		||||
    if(!b) {
 | 
			
		||||
        /* Clear destination */
 | 
			
		||||
        if(a) {
 | 
			
		||||
            FREEMEM(a);
 | 
			
		||||
            *aptr = 0;
 | 
			
		||||
        }
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(!a) {
 | 
			
		||||
        a = *aptr = MALLOC(sizeof(*a));
 | 
			
		||||
        if(!a) return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *a = *b;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -63,8 +63,10 @@ NativeInteger_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
 | 
			
		||||
                0, sizeof(variants) / sizeof(variants[0]) - 1)];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(!constraints) constraints = &td->encoding_constraints;
 | 
			
		||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
 | 
			
		||||
        if(!constraints || !constraints->per_constraints) 
 | 
			
		||||
            constraints = &td->encoding_constraints;
 | 
			
		||||
      
 | 
			
		||||
        const asn_per_constraints_t *ct;
 | 
			
		||||
 | 
			
		||||
        ct = constraints ? constraints->per_constraints : 0;
 | 
			
		||||
@@ -74,6 +76,8 @@ NativeInteger_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
 | 
			
		||||
                                           ct->value.upper_bound);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
#else
 | 
			
		||||
      if(!constraints) constraints = &td->encoding_constraints;
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@ asn_TYPE_operation_t asn_OP_OBJECT_IDENTIFIER = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
 | 
			
		||||
    OCTET_STRING_compare,   /* Implemented in terms of a string comparison */
 | 
			
		||||
    OCTET_STRING_copy,      /* Implemented in terms of a string copy */
 | 
			
		||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
 | 
			
		||||
    ber_decode_primitive,
 | 
			
		||||
    der_encode_primitive,
 | 
			
		||||
@@ -39,9 +40,11 @@ asn_TYPE_operation_t asn_OP_OBJECT_IDENTIFIER = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
    OBJECT_IDENTIFIER_decode_jer,
 | 
			
		||||
    OBJECT_IDENTIFIER_encode_jer,
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
 | 
			
		||||
    OBJECT_IDENTIFIER_decode_oer,
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ asn_TYPE_operation_t asn_OP_OCTET_STRING = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
 | 
			
		||||
    OCTET_STRING_compare,
 | 
			
		||||
    OCTET_STRING_copy,
 | 
			
		||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
 | 
			
		||||
    OCTET_STRING_decode_ber,
 | 
			
		||||
    OCTET_STRING_encode_der,
 | 
			
		||||
@@ -41,9 +42,11 @@ asn_TYPE_operation_t asn_OP_OCTET_STRING = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
    OCTET_STRING_decode_jer_hex,
 | 
			
		||||
    OCTET_STRING_encode_jer,
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
 | 
			
		||||
    OCTET_STRING_decode_oer,
 | 
			
		||||
@@ -247,6 +250,43 @@ OCTET_STRING_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
OCTET_STRING_copy(const asn_TYPE_descriptor_t *td, void **aptr,
 | 
			
		||||
                     const void *bptr) {
 | 
			
		||||
    const asn_OCTET_STRING_specifics_t *specs = 
 | 
			
		||||
        td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
 | 
			
		||||
                      : &asn_SPC_OCTET_STRING_specs;
 | 
			
		||||
    OCTET_STRING_t *a = *aptr;
 | 
			
		||||
    const OCTET_STRING_t *b = bptr;
 | 
			
		||||
 | 
			
		||||
    if(!b) {
 | 
			
		||||
        if(a) {
 | 
			
		||||
            FREEMEM(a->buf);
 | 
			
		||||
            a->buf = 0;
 | 
			
		||||
            a->size = 0;
 | 
			
		||||
            FREEMEM(a);
 | 
			
		||||
        }
 | 
			
		||||
        *aptr = 0;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(!a) {
 | 
			
		||||
        a = *aptr = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
 | 
			
		||||
        if(!a) return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void *buf = MALLOC(b->size + 1);
 | 
			
		||||
    if(!buf) return -1;
 | 
			
		||||
    memcpy(buf, b->buf, b->size);
 | 
			
		||||
    ((uint8_t *)buf)[b->size] = '\0';
 | 
			
		||||
 | 
			
		||||
    FREEMEM(a->buf);
 | 
			
		||||
    a->buf = (uint8_t *)buf;
 | 
			
		||||
    a->size = b->size;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
 | 
			
		||||
int
 | 
			
		||||
OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf,
 | 
			
		||||
 
 | 
			
		||||
@@ -179,7 +179,6 @@ OCTET_STRING_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
 | 
			
		||||
            raw_len = aper_get_length(pd, csiz->lower_bound, csiz->upper_bound,
 | 
			
		||||
                                      csiz->effective_bits, &repeat);
 | 
			
		||||
        if(raw_len < 0) RETURN(RC_WMORE);
 | 
			
		||||
        raw_len += csiz->lower_bound;
 | 
			
		||||
 | 
			
		||||
        ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
 | 
			
		||||
                  (long)csiz->effective_bits, (long)raw_len,
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ asn_TYPE_operation_t asn_OP_OPEN_TYPE = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
 | 
			
		||||
    OPEN_TYPE_compare,
 | 
			
		||||
    OPEN_TYPE_copy,
 | 
			
		||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
 | 
			
		||||
    OPEN_TYPE_decode_ber,
 | 
			
		||||
    OPEN_TYPE_encode_der,
 | 
			
		||||
@@ -29,9 +30,11 @@ asn_TYPE_operation_t asn_OP_OPEN_TYPE = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
    OPEN_TYPE_decode_jer,
 | 
			
		||||
    OPEN_TYPE_encode_jer,
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
 | 
			
		||||
    OPEN_TYPE_decode_oer,
 | 
			
		||||
 
 | 
			
		||||
@@ -53,7 +53,8 @@ OPEN_TYPE_aper_get(const asn_codec_ctx_t *opt_codec_ctx,
 | 
			
		||||
        (char *)*memb_ptr2
 | 
			
		||||
        + elm->type->elements[selected.presence_index - 1].memb_offset;
 | 
			
		||||
 | 
			
		||||
    rv = aper_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL,
 | 
			
		||||
    rv = aper_open_type_get(opt_codec_ctx, selected.type_descriptor,
 | 
			
		||||
                            elm->type->elements[selected.presence_index - 1].encoding_constraints.per_constraints,
 | 
			
		||||
                            &inner_value, pd);
 | 
			
		||||
    switch(rv.code) {
 | 
			
		||||
    case RC_OK:
 | 
			
		||||
@@ -110,7 +111,7 @@ OPEN_TYPE_encode_aper(const asn_TYPE_descriptor_t *td,
 | 
			
		||||
        memb_ptr = (const char *)sptr + elm->memb_offset;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(aper_open_type_put(elm->type, NULL, memb_ptr, po) < 0) {
 | 
			
		||||
    if(aper_open_type_put(elm->type, elm->encoding_constraints.per_constraints, memb_ptr, po) < 0) {
 | 
			
		||||
        ASN__ENCODE_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@ asn_TYPE_operation_t asn_OP_ObjectDescriptor = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
 | 
			
		||||
    OCTET_STRING_compare,
 | 
			
		||||
    OCTET_STRING_copy,
 | 
			
		||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
 | 
			
		||||
    OCTET_STRING_decode_ber,  /* Implemented in terms of OCTET STRING */
 | 
			
		||||
    OCTET_STRING_encode_der,
 | 
			
		||||
@@ -35,9 +36,11 @@ asn_TYPE_operation_t asn_OP_ObjectDescriptor = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
    OCTET_STRING_decode_jer_utf8,
 | 
			
		||||
    OCTET_STRING_encode_jer_utf8,
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
 | 
			
		||||
    0,
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sbcap/SBcAP_Error-Indication.h>
 | 
			
		||||
 | 
			
		||||
static asn_TYPE_member_t asn_MBR_SBcAP_Error_Indication_1[] = {
 | 
			
		||||
asn_TYPE_member_t asn_MBR_SBcAP_Error_Indication_1[] = {
 | 
			
		||||
	{ ATF_NOFLAGS, 0, offsetof(struct SBcAP_Error_Indication, protocolIEs),
 | 
			
		||||
		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
 | 
			
		||||
		-1,	/* IMPLICIT tag at current level */
 | 
			
		||||
@@ -32,7 +32,7 @@ static const ber_tlv_tag_t asn_DEF_SBcAP_Error_Indication_tags_1[] = {
 | 
			
		||||
static const asn_TYPE_tag2member_t asn_MAP_SBcAP_Error_Indication_tag2el_1[] = {
 | 
			
		||||
    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 } /* protocolIEs */
 | 
			
		||||
};
 | 
			
		||||
static asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Error_Indication_specs_1 = {
 | 
			
		||||
asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Error_Indication_specs_1 = {
 | 
			
		||||
	sizeof(struct SBcAP_Error_Indication),
 | 
			
		||||
	offsetof(struct SBcAP_Error_Indication, _asn_ctx),
 | 
			
		||||
	asn_MAP_SBcAP_Error_Indication_tag2el_1,
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sbcap/SBcAP_PWS-Failure-Indication.h>
 | 
			
		||||
 | 
			
		||||
static asn_TYPE_member_t asn_MBR_SBcAP_PWS_Failure_Indication_1[] = {
 | 
			
		||||
asn_TYPE_member_t asn_MBR_SBcAP_PWS_Failure_Indication_1[] = {
 | 
			
		||||
	{ ATF_NOFLAGS, 0, offsetof(struct SBcAP_PWS_Failure_Indication, protocolIEs),
 | 
			
		||||
		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
 | 
			
		||||
		-1,	/* IMPLICIT tag at current level */
 | 
			
		||||
@@ -51,7 +51,7 @@ static const asn_TYPE_tag2member_t asn_MAP_SBcAP_PWS_Failure_Indication_tag2el_1
 | 
			
		||||
    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* protocolIEs */
 | 
			
		||||
    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* protocolExtensions */
 | 
			
		||||
};
 | 
			
		||||
static asn_SEQUENCE_specifics_t asn_SPC_SBcAP_PWS_Failure_Indication_specs_1 = {
 | 
			
		||||
asn_SEQUENCE_specifics_t asn_SPC_SBcAP_PWS_Failure_Indication_specs_1 = {
 | 
			
		||||
	sizeof(struct SBcAP_PWS_Failure_Indication),
 | 
			
		||||
	offsetof(struct SBcAP_PWS_Failure_Indication, _asn_ctx),
 | 
			
		||||
	asn_MAP_SBcAP_PWS_Failure_Indication_tag2el_1,
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sbcap/SBcAP_PWS-Restart-Indication.h>
 | 
			
		||||
 | 
			
		||||
static asn_TYPE_member_t asn_MBR_SBcAP_PWS_Restart_Indication_1[] = {
 | 
			
		||||
asn_TYPE_member_t asn_MBR_SBcAP_PWS_Restart_Indication_1[] = {
 | 
			
		||||
	{ ATF_NOFLAGS, 0, offsetof(struct SBcAP_PWS_Restart_Indication, protocolIEs),
 | 
			
		||||
		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
 | 
			
		||||
		-1,	/* IMPLICIT tag at current level */
 | 
			
		||||
@@ -51,7 +51,7 @@ static const asn_TYPE_tag2member_t asn_MAP_SBcAP_PWS_Restart_Indication_tag2el_1
 | 
			
		||||
    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* protocolIEs */
 | 
			
		||||
    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* protocolExtensions */
 | 
			
		||||
};
 | 
			
		||||
static asn_SEQUENCE_specifics_t asn_SPC_SBcAP_PWS_Restart_Indication_specs_1 = {
 | 
			
		||||
asn_SEQUENCE_specifics_t asn_SPC_SBcAP_PWS_Restart_Indication_specs_1 = {
 | 
			
		||||
	sizeof(struct SBcAP_PWS_Restart_Indication),
 | 
			
		||||
	offsetof(struct SBcAP_PWS_Restart_Indication, _asn_ctx),
 | 
			
		||||
	asn_MAP_SBcAP_PWS_Restart_Indication_tag2el_1,
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sbcap/SBcAP_Stop-Warning-Indication.h>
 | 
			
		||||
 | 
			
		||||
static asn_TYPE_member_t asn_MBR_SBcAP_Stop_Warning_Indication_1[] = {
 | 
			
		||||
asn_TYPE_member_t asn_MBR_SBcAP_Stop_Warning_Indication_1[] = {
 | 
			
		||||
	{ ATF_NOFLAGS, 0, offsetof(struct SBcAP_Stop_Warning_Indication, protocolIEs),
 | 
			
		||||
		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
 | 
			
		||||
		-1,	/* IMPLICIT tag at current level */
 | 
			
		||||
@@ -51,7 +51,7 @@ static const asn_TYPE_tag2member_t asn_MAP_SBcAP_Stop_Warning_Indication_tag2el_
 | 
			
		||||
    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* protocolIEs */
 | 
			
		||||
    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* protocolExtensions */
 | 
			
		||||
};
 | 
			
		||||
static asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Stop_Warning_Indication_specs_1 = {
 | 
			
		||||
asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Stop_Warning_Indication_specs_1 = {
 | 
			
		||||
	sizeof(struct SBcAP_Stop_Warning_Indication),
 | 
			
		||||
	offsetof(struct SBcAP_Stop_Warning_Indication, _asn_ctx),
 | 
			
		||||
	asn_MAP_SBcAP_Stop_Warning_Indication_tag2el_1,
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sbcap/SBcAP_Stop-Warning-Request.h>
 | 
			
		||||
 | 
			
		||||
static asn_TYPE_member_t asn_MBR_SBcAP_Stop_Warning_Request_1[] = {
 | 
			
		||||
asn_TYPE_member_t asn_MBR_SBcAP_Stop_Warning_Request_1[] = {
 | 
			
		||||
	{ ATF_NOFLAGS, 0, offsetof(struct SBcAP_Stop_Warning_Request, protocolIEs),
 | 
			
		||||
		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
 | 
			
		||||
		-1,	/* IMPLICIT tag at current level */
 | 
			
		||||
@@ -51,7 +51,7 @@ static const asn_TYPE_tag2member_t asn_MAP_SBcAP_Stop_Warning_Request_tag2el_1[]
 | 
			
		||||
    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* protocolIEs */
 | 
			
		||||
    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* protocolExtensions */
 | 
			
		||||
};
 | 
			
		||||
static asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Stop_Warning_Request_specs_1 = {
 | 
			
		||||
asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Stop_Warning_Request_specs_1 = {
 | 
			
		||||
	sizeof(struct SBcAP_Stop_Warning_Request),
 | 
			
		||||
	offsetof(struct SBcAP_Stop_Warning_Request, _asn_ctx),
 | 
			
		||||
	asn_MAP_SBcAP_Stop_Warning_Request_tag2el_1,
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sbcap/SBcAP_Stop-Warning-Response.h>
 | 
			
		||||
 | 
			
		||||
static asn_TYPE_member_t asn_MBR_SBcAP_Stop_Warning_Response_1[] = {
 | 
			
		||||
asn_TYPE_member_t asn_MBR_SBcAP_Stop_Warning_Response_1[] = {
 | 
			
		||||
	{ ATF_NOFLAGS, 0, offsetof(struct SBcAP_Stop_Warning_Response, protocolIEs),
 | 
			
		||||
		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
 | 
			
		||||
		-1,	/* IMPLICIT tag at current level */
 | 
			
		||||
@@ -51,7 +51,7 @@ static const asn_TYPE_tag2member_t asn_MAP_SBcAP_Stop_Warning_Response_tag2el_1[
 | 
			
		||||
    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* protocolIEs */
 | 
			
		||||
    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* protocolExtensions */
 | 
			
		||||
};
 | 
			
		||||
static asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Stop_Warning_Response_specs_1 = {
 | 
			
		||||
asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Stop_Warning_Response_specs_1 = {
 | 
			
		||||
	sizeof(struct SBcAP_Stop_Warning_Response),
 | 
			
		||||
	offsetof(struct SBcAP_Stop_Warning_Response, _asn_ctx),
 | 
			
		||||
	asn_MAP_SBcAP_Stop_Warning_Response_tag2el_1,
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sbcap/SBcAP_Write-Replace-Warning-Indication.h>
 | 
			
		||||
 | 
			
		||||
static asn_TYPE_member_t asn_MBR_SBcAP_Write_Replace_Warning_Indication_1[] = {
 | 
			
		||||
asn_TYPE_member_t asn_MBR_SBcAP_Write_Replace_Warning_Indication_1[] = {
 | 
			
		||||
	{ ATF_NOFLAGS, 0, offsetof(struct SBcAP_Write_Replace_Warning_Indication, protocolIEs),
 | 
			
		||||
		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
 | 
			
		||||
		-1,	/* IMPLICIT tag at current level */
 | 
			
		||||
@@ -51,7 +51,7 @@ static const asn_TYPE_tag2member_t asn_MAP_SBcAP_Write_Replace_Warning_Indicatio
 | 
			
		||||
    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* protocolIEs */
 | 
			
		||||
    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* protocolExtensions */
 | 
			
		||||
};
 | 
			
		||||
static asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Write_Replace_Warning_Indication_specs_1 = {
 | 
			
		||||
asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Write_Replace_Warning_Indication_specs_1 = {
 | 
			
		||||
	sizeof(struct SBcAP_Write_Replace_Warning_Indication),
 | 
			
		||||
	offsetof(struct SBcAP_Write_Replace_Warning_Indication, _asn_ctx),
 | 
			
		||||
	asn_MAP_SBcAP_Write_Replace_Warning_Indication_tag2el_1,
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sbcap/SBcAP_Write-Replace-Warning-Request.h>
 | 
			
		||||
 | 
			
		||||
static asn_TYPE_member_t asn_MBR_SBcAP_Write_Replace_Warning_Request_1[] = {
 | 
			
		||||
asn_TYPE_member_t asn_MBR_SBcAP_Write_Replace_Warning_Request_1[] = {
 | 
			
		||||
	{ ATF_NOFLAGS, 0, offsetof(struct SBcAP_Write_Replace_Warning_Request, protocolIEs),
 | 
			
		||||
		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
 | 
			
		||||
		-1,	/* IMPLICIT tag at current level */
 | 
			
		||||
@@ -51,7 +51,7 @@ static const asn_TYPE_tag2member_t asn_MAP_SBcAP_Write_Replace_Warning_Request_t
 | 
			
		||||
    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* protocolIEs */
 | 
			
		||||
    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* protocolExtensions */
 | 
			
		||||
};
 | 
			
		||||
static asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Write_Replace_Warning_Request_specs_1 = {
 | 
			
		||||
asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Write_Replace_Warning_Request_specs_1 = {
 | 
			
		||||
	sizeof(struct SBcAP_Write_Replace_Warning_Request),
 | 
			
		||||
	offsetof(struct SBcAP_Write_Replace_Warning_Request, _asn_ctx),
 | 
			
		||||
	asn_MAP_SBcAP_Write_Replace_Warning_Request_tag2el_1,
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sbcap/SBcAP_Write-Replace-Warning-Response.h>
 | 
			
		||||
 | 
			
		||||
static asn_TYPE_member_t asn_MBR_SBcAP_Write_Replace_Warning_Response_1[] = {
 | 
			
		||||
asn_TYPE_member_t asn_MBR_SBcAP_Write_Replace_Warning_Response_1[] = {
 | 
			
		||||
	{ ATF_NOFLAGS, 0, offsetof(struct SBcAP_Write_Replace_Warning_Response, protocolIEs),
 | 
			
		||||
		(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
 | 
			
		||||
		-1,	/* IMPLICIT tag at current level */
 | 
			
		||||
@@ -51,7 +51,7 @@ static const asn_TYPE_tag2member_t asn_MAP_SBcAP_Write_Replace_Warning_Response_
 | 
			
		||||
    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* protocolIEs */
 | 
			
		||||
    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* protocolExtensions */
 | 
			
		||||
};
 | 
			
		||||
static asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Write_Replace_Warning_Response_specs_1 = {
 | 
			
		||||
asn_SEQUENCE_specifics_t asn_SPC_SBcAP_Write_Replace_Warning_Response_specs_1 = {
 | 
			
		||||
	sizeof(struct SBcAP_Write_Replace_Warning_Response),
 | 
			
		||||
	offsetof(struct SBcAP_Write_Replace_Warning_Response, _asn_ctx),
 | 
			
		||||
	asn_MAP_SBcAP_Write_Replace_Warning_Response_tag2el_1,
 | 
			
		||||
 
 | 
			
		||||
@@ -25,8 +25,7 @@ aper_get_length(asn_per_data_t *pd, ssize_t lb, ssize_t ub,
 | 
			
		||||
	*repeat = 0;
 | 
			
		||||
 | 
			
		||||
	if (constrained && ub < 65536) {
 | 
			
		||||
		int range = ub - lb + 1;
 | 
			
		||||
		return aper_get_nsnnwn(pd, range);
 | 
			
		||||
		return aper_get_constrained_whole_number(pd, lb, ub);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (aper_get_align(pd) < 0)
 | 
			
		||||
@@ -70,55 +69,117 @@ aper_get_nslength(asn_per_data_t *pd) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ssize_t
 | 
			
		||||
aper_get_nsnnwn(asn_per_data_t *pd, int range) {
 | 
			
		||||
	ssize_t value;
 | 
			
		||||
	int bytes = 0;
 | 
			
		||||
aper_get_nsnnwn(asn_per_data_t *pd) {
 | 
			
		||||
	int b;
 | 
			
		||||
	int length;
 | 
			
		||||
 | 
			
		||||
	ASN_DEBUG("getting nsnnwn with range %d", range);
 | 
			
		||||
	ASN_DEBUG("getting nsnnwn");
 | 
			
		||||
 | 
			
		||||
	if(range <= 255) {
 | 
			
		||||
		int i;
 | 
			
		||||
	b = per_get_few_bits(pd, 1);
 | 
			
		||||
	if (b == -1)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
		if (range < 0) return -1;
 | 
			
		||||
		/* 1 -> 8 bits */
 | 
			
		||||
		for (i = 1; i <= 8; i++) {
 | 
			
		||||
			int upper = 1 << i;
 | 
			
		||||
			if (upper >= range)
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		value = per_get_few_bits(pd, i);
 | 
			
		||||
		return value;
 | 
			
		||||
	} else if (range == 256){
 | 
			
		||||
		/* 1 byte */
 | 
			
		||||
		bytes = 1;
 | 
			
		||||
	} else if (range <= 65536) {
 | 
			
		||||
		/* 2 bytes */
 | 
			
		||||
		bytes = 2;
 | 
			
		||||
	} else {
 | 
			
		||||
		//return -1;
 | 
			
		||||
		int length;
 | 
			
		||||
	/* X.691 2002 10.6.1 */
 | 
			
		||||
	if (b == 0)
 | 
			
		||||
		return per_get_few_bits(pd, 6);
 | 
			
		||||
 | 
			
		||||
		/* handle indefinite range */
 | 
			
		||||
		length = per_get_few_bits(pd, 1);
 | 
			
		||||
		if (length == 0)
 | 
			
		||||
			return per_get_few_bits(pd, 6);
 | 
			
		||||
 | 
			
		||||
		if (aper_get_align(pd) < 0)
 | 
			
		||||
			return -1;
 | 
			
		||||
 | 
			
		||||
		length = per_get_few_bits(pd, 8);
 | 
			
		||||
		/* the length is not likely to be that big */
 | 
			
		||||
		if (length > 4)
 | 
			
		||||
			return -1;
 | 
			
		||||
		value = 0;
 | 
			
		||||
		if (per_get_many_bits(pd, (uint8_t *)&value, 0, length * 8) < 0)
 | 
			
		||||
			return -1;
 | 
			
		||||
		return value;
 | 
			
		||||
	}
 | 
			
		||||
	if (aper_get_align(pd) < 0)
 | 
			
		||||
		return -1;
 | 
			
		||||
	value = per_get_few_bits(pd, 8 * bytes);
 | 
			
		||||
	return value;
 | 
			
		||||
 | 
			
		||||
	/* X.691 2002 10.6.2 */
 | 
			
		||||
	/* X.691 2002 10.9.3.5 */
 | 
			
		||||
	b = per_get_few_bits(pd, 1);
 | 
			
		||||
	if (b == -1)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	if (b == 1) {
 | 
			
		||||
		/* other 10.9.3.x cases not handled, it's doubtful we reach them in practice */
 | 
			
		||||
		ASN_DEBUG("todo: X.691 2002 10.9.3.x");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* X.691 2002 10.9.3.6 */
 | 
			
		||||
	length = per_get_few_bits(pd, 7);
 | 
			
		||||
	if (length > 4) {
 | 
			
		||||
		/* todo */
 | 
			
		||||
		ASN_DEBUG("todo: X.691 2002 10.9.3.6 for length > 4");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	ASN_DEBUG("length %d\n", length);
 | 
			
		||||
 | 
			
		||||
	/* todo: 0xffffffff will be seen as -1 and will lead to decoding failure */
 | 
			
		||||
	return per_get_few_bits(pd, length * 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* X.691 2002 10.5 - Decoding of a constrained whole number */
 | 
			
		||||
long
 | 
			
		||||
aper_get_constrained_whole_number(asn_per_data_t *pd, long lb, long ub) {
 | 
			
		||||
	assert(ub >= lb);
 | 
			
		||||
	long range = ub - lb + 1;
 | 
			
		||||
	int range_len;
 | 
			
		||||
	int value_len;
 | 
			
		||||
	long value;
 | 
			
		||||
 | 
			
		||||
	ASN_DEBUG("aper get constrained_whole_number with lb %ld and ub %ld", lb, ub);
 | 
			
		||||
 | 
			
		||||
	/* X.691 2002 10.5.4 */
 | 
			
		||||
	if (range == 1)
 | 
			
		||||
		return lb;
 | 
			
		||||
 | 
			
		||||
	/* X.691 2002 10.5.7.1 - The bit-field case. */
 | 
			
		||||
	if (range <= 255) {
 | 
			
		||||
		int bitfield_size = 8;
 | 
			
		||||
		for (bitfield_size = 8; bitfield_size >= 2; bitfield_size--)
 | 
			
		||||
			if ((range - 1) & (1 << (bitfield_size-1)))
 | 
			
		||||
				break;
 | 
			
		||||
		value = per_get_few_bits(pd, bitfield_size);
 | 
			
		||||
		if (value < 0 || value >= range)
 | 
			
		||||
			return -1;
 | 
			
		||||
		return value + lb;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* X.691 2002 10.5.7.2 - The one-octet case. */
 | 
			
		||||
	if (range == 256) {
 | 
			
		||||
		if (aper_get_align(pd))
 | 
			
		||||
			return -1;
 | 
			
		||||
		value = per_get_few_bits(pd, 8);
 | 
			
		||||
		if (value < 0 || value >= range)
 | 
			
		||||
			return -1;
 | 
			
		||||
		return value + lb;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* X.691 2002 10.5.7.3 - The two-octet case. */
 | 
			
		||||
	if (range <= 65536) {
 | 
			
		||||
		if (aper_get_align(pd))
 | 
			
		||||
			return -1;
 | 
			
		||||
		value = per_get_few_bits(pd, 16);
 | 
			
		||||
		if (value < 0 || value >= range)
 | 
			
		||||
			return -1;
 | 
			
		||||
		return value + lb;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* X.691 2002 10.5.7.4 - The indefinite length case. */
 | 
			
		||||
	/* since we limit input to be 'long' we don't handle all numbers */
 | 
			
		||||
	/* and so length determinant is retrieved as X.691 2002 10.9.3.3 */
 | 
			
		||||
	/* number of bytes to store the range */
 | 
			
		||||
	for (range_len = 3; ; range_len++) {
 | 
			
		||||
		long bits = ((long)1) << (8 * range_len);
 | 
			
		||||
		if (range - 1 < bits)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	value_len = aper_get_constrained_whole_number(pd, 1, range_len);
 | 
			
		||||
	if (value_len == -1)
 | 
			
		||||
		return -1;
 | 
			
		||||
	if (value_len > 4) {
 | 
			
		||||
		ASN_DEBUG("todo: aper_get_constrained_whole_number: value_len > 4");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	if (aper_get_align(pd))
 | 
			
		||||
		return -1;
 | 
			
		||||
	value = per_get_few_bits(pd, value_len * 8);
 | 
			
		||||
	if (value < 0 || value >= range)
 | 
			
		||||
		return -1;
 | 
			
		||||
	return value + lb;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int aper_put_align(asn_per_outp_t *po) {
 | 
			
		||||
@@ -142,11 +203,9 @@ aper_put_length(asn_per_outp_t *po, ssize_t lb, ssize_t ub, size_t n, int *need_
 | 
			
		||||
 | 
			
		||||
	ASN_DEBUG("APER put length %zu with range (%zd..%zd)", n, lb, ub);
 | 
			
		||||
 | 
			
		||||
	/* 11.9 X.691 Note 2 */
 | 
			
		||||
	if (constrained && ub < 65536) {
 | 
			
		||||
		int range = ub - lb + 1;
 | 
			
		||||
		return aper_put_nsnnwn(po, range, n) ? -1 : (ssize_t)n;
 | 
			
		||||
	}
 | 
			
		||||
	/* X.691 2002 10.9.3.3 */
 | 
			
		||||
	if (constrained && ub < 65536)
 | 
			
		||||
		return aper_put_constrained_whole_number(po, lb, ub, n + lb) ? -1 : (ssize_t)n;
 | 
			
		||||
 | 
			
		||||
	if (aper_put_align(po) < 0)
 | 
			
		||||
		return -1;
 | 
			
		||||
@@ -189,51 +248,113 @@ aper_put_nslength(asn_per_outp_t *po, size_t length) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
aper_put_nsnnwn(asn_per_outp_t *po, int range, int number) {
 | 
			
		||||
	int bytes;
 | 
			
		||||
aper_put_nsnnwn(asn_per_outp_t *po, int number) {
 | 
			
		||||
	int len;
 | 
			
		||||
 | 
			
		||||
	ASN_DEBUG("aper put nsnnwn %d with range %d", number, range);
 | 
			
		||||
	/* 10.5.7.1 X.691 */
 | 
			
		||||
	if(range < 0) {
 | 
			
		||||
		int i;
 | 
			
		||||
		for (i = 1; ; i++) {
 | 
			
		||||
			int bits = 1 << (8 * i);
 | 
			
		||||
			if (number <= bits)
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		bytes = i;
 | 
			
		||||
		assert(i <= 4);
 | 
			
		||||
	ASN_DEBUG("aper put nsnnwn %d", number);
 | 
			
		||||
 | 
			
		||||
	if (number <= 63) {
 | 
			
		||||
		if (per_put_few_bits(po, 0, 1))
 | 
			
		||||
			return -1;
 | 
			
		||||
		return per_put_few_bits(po, number, 6);
 | 
			
		||||
	}
 | 
			
		||||
	if(range <= 255) {
 | 
			
		||||
 | 
			
		||||
	if (per_put_few_bits(po, 1, 1))
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	if (number < 256) {
 | 
			
		||||
		len = 1;
 | 
			
		||||
	} else if (number < 65536) {
 | 
			
		||||
		len = 2;
 | 
			
		||||
	} else { /* number > 64K */
 | 
			
		||||
		int i;
 | 
			
		||||
		for (i = 1; i <= 8; i++) {
 | 
			
		||||
			int bits = 1 << i;
 | 
			
		||||
			if (range <= bits)
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		return per_put_few_bits(po, number, i);
 | 
			
		||||
	} else if(range == 256) {
 | 
			
		||||
		if (number >= range)
 | 
			
		||||
			return -1;
 | 
			
		||||
		bytes = 1;
 | 
			
		||||
	} else if(range <= 65536) {
 | 
			
		||||
		if (number >= range)
 | 
			
		||||
			return -1;
 | 
			
		||||
		bytes = 2;
 | 
			
		||||
	} else { /* Ranges > 64K */
 | 
			
		||||
		int i;
 | 
			
		||||
		for (i = 1; ; i++) {
 | 
			
		||||
		for (i = 3; ; i++) {
 | 
			
		||||
			int bits = 1 << (8 * i);
 | 
			
		||||
			if (range <= bits)
 | 
			
		||||
			if (number < bits)
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		assert(i <= 4);
 | 
			
		||||
		bytes = i;
 | 
			
		||||
		len = i;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (aper_put_align(po) < 0)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	/* put the length which is a non-constrained whole number */
 | 
			
		||||
	if (len <= 127) {
 | 
			
		||||
		if(per_put_few_bits(po, 0, 1))
 | 
			
		||||
			return -1;
 | 
			
		||||
		if(per_put_few_bits(po, len, 7))
 | 
			
		||||
			return -1;
 | 
			
		||||
	} else {
 | 
			
		||||
		/* todo but not big problem, it's very doubtful that the
 | 
			
		||||
		 * number of bytes to encode 'number' will be > 127
 | 
			
		||||
		 */
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	if(aper_put_align(po) < 0) /* Aligning on octet */
 | 
			
		||||
		return -1;
 | 
			
		||||
/* 	if(per_put_few_bits(po, bytes, 8))
 | 
			
		||||
		return -1;
 | 
			
		||||
*/
 | 
			
		||||
	return per_put_few_bits(po, number, 8 * bytes);
 | 
			
		||||
	return per_put_few_bits(po, number, 8 * len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* X.691 2002 10.5 - Encoding of a constrained whole number */
 | 
			
		||||
int
 | 
			
		||||
aper_put_constrained_whole_number(asn_per_outp_t *po, long lb, long ub, long number) {
 | 
			
		||||
	assert(ub >= lb);
 | 
			
		||||
	long range = ub - lb + 1;
 | 
			
		||||
	long value = number - lb;
 | 
			
		||||
	int range_len;
 | 
			
		||||
	int value_len;
 | 
			
		||||
 | 
			
		||||
	ASN_DEBUG("aper put constrained_whole_number %ld with lb %ld and ub %ld", number, lb, ub);
 | 
			
		||||
 | 
			
		||||
	if (number < lb || number > ub)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	/* X.691 2002 10.5.4 */
 | 
			
		||||
	if (range == 1)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/* X.691 2002 10.5.7.1 - The bit-field case. */
 | 
			
		||||
	if (range <= 255) {
 | 
			
		||||
		int bitfield_size = 8;
 | 
			
		||||
		for (bitfield_size = 8; bitfield_size >= 2; bitfield_size--)
 | 
			
		||||
			if ((range - 1) & (1 << (bitfield_size-1)))
 | 
			
		||||
				break;
 | 
			
		||||
		return per_put_few_bits(po, value, bitfield_size);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* X.691 2002 10.5.7.2 - The one-octet case. */
 | 
			
		||||
	if (range == 256) {
 | 
			
		||||
		if (aper_put_align(po))
 | 
			
		||||
			return -1;
 | 
			
		||||
		return per_put_few_bits(po, value, 8);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* X.691 2002 10.5.7.3 - The two-octet case. */
 | 
			
		||||
	if (range <= 65536) {
 | 
			
		||||
		if (aper_put_align(po))
 | 
			
		||||
			return -1;
 | 
			
		||||
		return per_put_few_bits(po, value, 16);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* X.691 2002 10.5.7.4 - The indefinite length case. */
 | 
			
		||||
	/* since we limit input to be 'long' we don't handle all numbers */
 | 
			
		||||
	/* and so length determinant is stored as X.691 2002 10.9.3.3 */
 | 
			
		||||
	/* number of bytes to store the range */
 | 
			
		||||
	for (range_len = 3; ; range_len++) {
 | 
			
		||||
		int bits = 1 << (8 * range_len);
 | 
			
		||||
		if (range - 1 < bits)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	/* number of bytes to store the value */
 | 
			
		||||
	for (value_len = 1; ; value_len++) {
 | 
			
		||||
		long bits = ((long)1) << (8 * value_len);
 | 
			
		||||
		if (value < bits)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	if (aper_put_constrained_whole_number(po, 1, range_len, value_len))
 | 
			
		||||
		return -1;
 | 
			
		||||
	if (aper_put_align(po))
 | 
			
		||||
		return -1;
 | 
			
		||||
	return per_put_few_bits(po, value, value_len * 8);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -229,6 +229,9 @@ asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
 | 
			
		||||
#if !defined(ASN_DISABLE_XER_SUPPORT)
 | 
			
		||||
    enum xer_encoder_flags_e xer_flags = XER_F_CANONICAL;
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
    enum jer_encoder_flags_e jer_flags = JER_F;
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
 | 
			
		||||
 | 
			
		||||
    (void)opt_codec_ctx; /* Parameters are not checked on encode yet. */
 | 
			
		||||
 | 
			
		||||
@@ -432,9 +435,15 @@ asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
    case ATS_BASIC_JER:
 | 
			
		||||
    case ATS_JER_MINIFIED:
 | 
			
		||||
        /* Currently JER_F and JER_F_MINIFIED have opposite purposes
 | 
			
		||||
        *  so we just flip the flag. */
 | 
			
		||||
        jer_flags &= ~JER_F;
 | 
			
		||||
        jer_flags |= JER_F_MINIFIED;
 | 
			
		||||
        /* Fall through. */
 | 
			
		||||
    case ATS_JER:
 | 
			
		||||
        if(td->op->jer_encoder) {
 | 
			
		||||
            er = jer_encode(td, sptr, callback, callback_key);
 | 
			
		||||
            er = jer_encode(td, sptr, jer_flags, callback, callback_key);
 | 
			
		||||
            if(er.encoded == -1) {
 | 
			
		||||
                if(er.failed_type && er.failed_type->op->jer_encoder) {
 | 
			
		||||
                    errno = EBADF;   /* Structure has incorrect form. */
 | 
			
		||||
@@ -533,6 +542,15 @@ asn_decode(const asn_codec_ctx_t *opt_codec_ctx,
 | 
			
		||||
        errno = ENOENT;
 | 
			
		||||
        ASN__DECODE_FAILED;
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
 | 
			
		||||
    case ATS_JER:
 | 
			
		||||
    case ATS_JER_MINIFIED:
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
        return jer_decode(opt_codec_ctx, td, sptr, buffer, size);
 | 
			
		||||
#else
 | 
			
		||||
        errno = ENOENT;
 | 
			
		||||
        ASN__DECODE_FAILED;
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,9 @@ asn__format_to_callback(int (*cb)(const void *, size_t, void *key), void *key,
 | 
			
		||||
        buf_size <<= 1;
 | 
			
		||||
        if(buf == scratch) {
 | 
			
		||||
            buf = MALLOC(buf_size);
 | 
			
		||||
            if(!buf) return -1;
 | 
			
		||||
            if(!buf) {
 | 
			
		||||
              return -1;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            void *p = REALLOC(buf, buf_size);
 | 
			
		||||
            if(!p) {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@
 | 
			
		||||
#include <asn_internal.h>
 | 
			
		||||
#include <asn_random_fill.h>
 | 
			
		||||
#include <constr_TYPE.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
asn_random_fill(const struct asn_TYPE_descriptor_s *td, void **struct_ptr,
 | 
			
		||||
@@ -42,17 +43,22 @@ asn_random_between(intmax_t lb, intmax_t rb) {
 | 
			
		||||
        uintmax_t range = asn__intmax_range(lb, rb);
 | 
			
		||||
        uintmax_t value = 0;
 | 
			
		||||
        uintmax_t got_entropy = 0;
 | 
			
		||||
 | 
			
		||||
        (void)intmax_max;
 | 
			
		||||
        assert(RAND_MAX > 0xffffff);    /* Seen 7ffffffd! */
 | 
			
		||||
        int max = 0xffffff;
 | 
			
		||||
 | 
			
		||||
#ifdef __WIN32__
 | 
			
		||||
        max = RAND_MAX-1;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        assert(RAND_MAX > max);    /* Seen 7ffffffd! */
 | 
			
		||||
        assert(range < intmax_max);
 | 
			
		||||
 | 
			
		||||
        for(; got_entropy < range;) {
 | 
			
		||||
            got_entropy = (got_entropy << 24) | 0xffffff;
 | 
			
		||||
            got_entropy = (got_entropy << 24) | max;
 | 
			
		||||
#ifdef HAVE_RANDOM
 | 
			
		||||
            value = (value << 24) | (random() % 0xffffff);
 | 
			
		||||
            value = (value << 24) | (random() % max);
 | 
			
		||||
#else
 | 
			
		||||
            value = (value << 24) | (rand() % 0xffffff);
 | 
			
		||||
            value = (value << 24) | (rand() % max);
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ asn_TYPE_operation_t asn_OP_CHOICE = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
 | 
			
		||||
    CHOICE_compare,
 | 
			
		||||
    CHOICE_copy,
 | 
			
		||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
 | 
			
		||||
    CHOICE_decode_ber,
 | 
			
		||||
    CHOICE_encode_der,
 | 
			
		||||
@@ -28,9 +29,11 @@ asn_TYPE_operation_t asn_OP_CHOICE = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
    CHOICE_decode_jer,
 | 
			
		||||
    CHOICE_encode_jer,
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
 | 
			
		||||
    CHOICE_decode_oer,
 | 
			
		||||
@@ -154,13 +157,14 @@ CHOICE_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
 | 
			
		||||
void
 | 
			
		||||
CHOICE_free(const asn_TYPE_descriptor_t *td, void *ptr,
 | 
			
		||||
            enum asn_struct_free_method method) {
 | 
			
		||||
    const asn_CHOICE_specifics_t *specs =
 | 
			
		||||
        (const asn_CHOICE_specifics_t *)td->specifics;
 | 
			
		||||
    const asn_CHOICE_specifics_t *specs;
 | 
			
		||||
    unsigned present;
 | 
			
		||||
 | 
			
		||||
	if(!td || !ptr)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
    specs = (const asn_CHOICE_specifics_t *)td->specifics;
 | 
			
		||||
 | 
			
		||||
	ASN_DEBUG("Freeing %s as CHOICE", td->name);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
@@ -311,6 +315,59 @@ CHOICE_compare(const asn_TYPE_descriptor_t *td, const void *aptr, const void *bp
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
CHOICE_copy(const asn_TYPE_descriptor_t *td, void **aptr, const void *bptr) {
 | 
			
		||||
    if(!td) return -1;
 | 
			
		||||
 | 
			
		||||
    void *st = *aptr;
 | 
			
		||||
    const asn_CHOICE_specifics_t *specs =
 | 
			
		||||
        (const asn_CHOICE_specifics_t *)td->specifics;
 | 
			
		||||
    const asn_TYPE_member_t *elm;  /* CHOICE's element */
 | 
			
		||||
    int present;
 | 
			
		||||
    int ret;
 | 
			
		||||
	void *amemb;
 | 
			
		||||
    void **amembp;
 | 
			
		||||
    const void *bmemb;
 | 
			
		||||
 | 
			
		||||
    if(!bptr) {
 | 
			
		||||
        if(st) {
 | 
			
		||||
            ASN_STRUCT_FREE(*td, st);
 | 
			
		||||
            *aptr = NULL;
 | 
			
		||||
        }
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(!st) {
 | 
			
		||||
        st = *aptr = CALLOC(1, specs->struct_size);
 | 
			
		||||
        if(!st) return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    present = _fetch_present_idx(bptr,
 | 
			
		||||
                                 specs->pres_offset, specs->pres_size);
 | 
			
		||||
 | 
			
		||||
    if(present <= 0 && (unsigned)present > td->elements_count) return -1;
 | 
			
		||||
    --present;
 | 
			
		||||
 | 
			
		||||
    elm = &td->elements[present];
 | 
			
		||||
    if(elm->flags & ATF_POINTER) {
 | 
			
		||||
        /* Member is a pointer to another structure */
 | 
			
		||||
        amembp = (void **)((char *)st + elm->memb_offset);
 | 
			
		||||
        bmemb = *(const void* const*)((const char*)bptr + elm->memb_offset);
 | 
			
		||||
    } else {
 | 
			
		||||
        amemb = (char *)st + elm->memb_offset;
 | 
			
		||||
        amembp = &amemb;
 | 
			
		||||
        bmemb = (const void*)((const char*)bptr + elm->memb_offset);
 | 
			
		||||
    }
 | 
			
		||||
    ret = elm->type->op->copy_struct(elm->type, amembp, bmemb);
 | 
			
		||||
    if (ret != 0) return ret;
 | 
			
		||||
 | 
			
		||||
    _set_present_idx(st,
 | 
			
		||||
            specs->pres_offset,
 | 
			
		||||
            specs->pres_size, present + 1);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Return the 1-based choice variant presence index.
 | 
			
		||||
 * Returns 0 in case of error.
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,8 @@ CHOICE_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
 | 
			
		||||
        value = per_get_few_bits(pd, 1);
 | 
			
		||||
        if(value < 0) ASN__DECODE_STARVED;
 | 
			
		||||
        if(value) ct = 0;  /* Not restricted */
 | 
			
		||||
        if((unsigned)value >= td->elements_count)
 | 
			
		||||
            ASN__DECODE_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(ct && ct->range_bits >= 0) {
 | 
			
		||||
@@ -53,8 +55,8 @@ CHOICE_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
 | 
			
		||||
        if(specs->ext_start == -1)
 | 
			
		||||
            ASN__DECODE_FAILED;
 | 
			
		||||
 | 
			
		||||
        if (ct && ct->upper_bound >= ct->lower_bound) {
 | 
			
		||||
            value = aper_get_nsnnwn(pd, ct->upper_bound - ct->lower_bound + 1);
 | 
			
		||||
        if(specs && specs->tag2el_count > (unsigned)specs->ext_start) {
 | 
			
		||||
            value = aper_get_nsnnwn(pd); /* extension elements range */
 | 
			
		||||
            if(value < 0) ASN__DECODE_STARVED;
 | 
			
		||||
            value += specs->ext_start;
 | 
			
		||||
            if((unsigned)value >= td->elements_count)
 | 
			
		||||
@@ -166,11 +168,7 @@ CHOICE_encode_aper(const asn_TYPE_descriptor_t *td,
 | 
			
		||||
        asn_enc_rval_t rval = {0,0,0};
 | 
			
		||||
        if(specs->ext_start == -1)
 | 
			
		||||
            ASN__ENCODE_FAILED;
 | 
			
		||||
        int n = present - specs->ext_start;
 | 
			
		||||
        if(n <= 63) {
 | 
			
		||||
            if(n < 0) ASN__ENCODE_FAILED;
 | 
			
		||||
            if(per_put_few_bits(po, n, 7)) ASN__ENCODE_FAILED;
 | 
			
		||||
        } else
 | 
			
		||||
        if(aper_put_nsnnwn(po, present - specs->ext_start))
 | 
			
		||||
            ASN__ENCODE_FAILED;
 | 
			
		||||
        if(aper_open_type_put(elm->type, elm->encoding_constraints.per_constraints,
 | 
			
		||||
                              memb_ptr, po))
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ asn_TYPE_operation_t asn_OP_SEQUENCE = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
 | 
			
		||||
    SEQUENCE_compare,
 | 
			
		||||
    SEQUENCE_copy,
 | 
			
		||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
 | 
			
		||||
    SEQUENCE_decode_ber,
 | 
			
		||||
    SEQUENCE_encode_der,
 | 
			
		||||
@@ -29,9 +30,11 @@ asn_TYPE_operation_t asn_OP_SEQUENCE = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
    SEQUENCE_decode_jer,
 | 
			
		||||
    SEQUENCE_encode_jer,
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
 | 
			
		||||
    SEQUENCE_decode_oer,
 | 
			
		||||
@@ -66,13 +69,14 @@ void
 | 
			
		||||
SEQUENCE_free(const asn_TYPE_descriptor_t *td, void *sptr,
 | 
			
		||||
              enum asn_struct_free_method method) {
 | 
			
		||||
    size_t edx;
 | 
			
		||||
    const asn_SEQUENCE_specifics_t *specs =
 | 
			
		||||
        (const asn_SEQUENCE_specifics_t *)td->specifics;
 | 
			
		||||
    const asn_SEQUENCE_specifics_t *specs; 
 | 
			
		||||
    asn_struct_ctx_t *ctx; /* Decoder context */
 | 
			
		||||
 | 
			
		||||
	if(!td || !sptr)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
    specs = (const asn_SEQUENCE_specifics_t *)td->specifics;
 | 
			
		||||
 | 
			
		||||
	ASN_DEBUG("Freeing %s as SEQUENCE", td->name);
 | 
			
		||||
 | 
			
		||||
	for(edx = 0; edx < td->elements_count; edx++) {
 | 
			
		||||
@@ -124,6 +128,8 @@ SEQUENCE_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
 | 
			
		||||
	for(edx = 0; edx < td->elements_count; edx++) {
 | 
			
		||||
		asn_TYPE_member_t *elm = &td->elements[edx];
 | 
			
		||||
		const void *memb_ptr;
 | 
			
		||||
		asn_constr_check_f *constr;
 | 
			
		||||
		int ret;
 | 
			
		||||
 | 
			
		||||
		if(elm->flags & ATF_POINTER) {
 | 
			
		||||
			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
 | 
			
		||||
@@ -139,14 +145,12 @@ SEQUENCE_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
 | 
			
		||||
			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if(elm->encoding_constraints.general_constraints) {
 | 
			
		||||
			int ret = elm->encoding_constraints.general_constraints(elm->type, memb_ptr,
 | 
			
		||||
				ctfailcb, app_key);
 | 
			
		||||
			if(ret) return ret;
 | 
			
		||||
		} else {
 | 
			
		||||
			return elm->type->encoding_constraints.general_constraints(elm->type,
 | 
			
		||||
				memb_ptr, ctfailcb, app_key);
 | 
			
		||||
		}
 | 
			
		||||
		constr = elm->encoding_constraints.general_constraints;
 | 
			
		||||
		if(!constr)
 | 
			
		||||
			constr = elm->type->encoding_constraints.general_constraints;
 | 
			
		||||
 | 
			
		||||
		ret = constr(elm->type, memb_ptr, ctfailcb, app_key);
 | 
			
		||||
		if(ret) return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
@@ -195,3 +199,53 @@ SEQUENCE_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
SEQUENCE_copy(const asn_TYPE_descriptor_t *td, void **aptr,
 | 
			
		||||
                 const void *bptr) {
 | 
			
		||||
    if(!td) return -1;
 | 
			
		||||
 | 
			
		||||
    const asn_SEQUENCE_specifics_t *specs = 
 | 
			
		||||
        (const asn_SEQUENCE_specifics_t *)td->specifics;
 | 
			
		||||
    size_t edx;
 | 
			
		||||
    void *st = *aptr;        /* Target structure */
 | 
			
		||||
 | 
			
		||||
    if(!bptr) {
 | 
			
		||||
        if(st) {
 | 
			
		||||
            SEQUENCE_free(td, st, 0);
 | 
			
		||||
            *aptr = 0;
 | 
			
		||||
        }
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Create the target structure if it is not present already.
 | 
			
		||||
     */
 | 
			
		||||
    if(st == 0) {
 | 
			
		||||
        st = *aptr = CALLOC(1, specs->struct_size);
 | 
			
		||||
        if(st == 0) return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	for(edx = 0; edx < td->elements_count; edx++) {
 | 
			
		||||
		asn_TYPE_member_t *elm = &td->elements[edx];
 | 
			
		||||
		void *amemb;
 | 
			
		||||
		void **amembp;
 | 
			
		||||
		const void *bmemb;
 | 
			
		||||
        int ret;
 | 
			
		||||
 | 
			
		||||
        if(elm->flags & ATF_POINTER) {
 | 
			
		||||
            /* Member is a pointer to another structure */
 | 
			
		||||
            amembp = (void **)((char *)st + elm->memb_offset);
 | 
			
		||||
            bmemb = *(const void* const*)((const char*)bptr + elm->memb_offset);
 | 
			
		||||
        } else {
 | 
			
		||||
            amemb = (char *)st + elm->memb_offset;
 | 
			
		||||
            amembp = &amemb;
 | 
			
		||||
            bmemb = (const void*)((const char*)bptr + elm->memb_offset);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ret = elm->type->op->copy_struct(elm->type, amembp, bmemb);
 | 
			
		||||
        if(ret != 0) return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ asn_TYPE_operation_t asn_OP_SEQUENCE_OF = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
 | 
			
		||||
    SEQUENCE_OF_compare,
 | 
			
		||||
    SEQUENCE_OF_copy,
 | 
			
		||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
 | 
			
		||||
    SEQUENCE_OF_decode_ber,
 | 
			
		||||
    SEQUENCE_OF_encode_der,
 | 
			
		||||
@@ -30,9 +31,11 @@ asn_TYPE_operation_t asn_OP_SEQUENCE_OF = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
    SEQUENCE_OF_decode_jer,
 | 
			
		||||
    SEQUENCE_OF_encode_jer,
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
 | 
			
		||||
    SEQUENCE_OF_decode_oer,  /* Same as SET OF decoder. */
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ asn_TYPE_operation_t asn_OP_SET_OF = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
 | 
			
		||||
    SET_OF_compare,
 | 
			
		||||
    SET_OF_copy,
 | 
			
		||||
#if !defined(ASN_DISABLE_BER_SUPPORT)
 | 
			
		||||
    SET_OF_decode_ber,
 | 
			
		||||
    SET_OF_encode_der,
 | 
			
		||||
@@ -29,9 +30,11 @@ asn_TYPE_operation_t asn_OP_SET_OF = {
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_JER_SUPPORT)
 | 
			
		||||
    SET_OF_decode_jer,
 | 
			
		||||
    SET_OF_encode_jer,
 | 
			
		||||
#else
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
#endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
 | 
			
		||||
#if !defined(ASN_DISABLE_OER_SUPPORT)
 | 
			
		||||
    SET_OF_decode_oer,
 | 
			
		||||
@@ -369,3 +372,58 @@ SET_OF_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
SET_OF_copy(const asn_TYPE_descriptor_t *td, void **aptr,
 | 
			
		||||
            const void *bptr) {
 | 
			
		||||
    if(!td) return -1;
 | 
			
		||||
 | 
			
		||||
    const asn_SET_OF_specifics_t *specs = 
 | 
			
		||||
        (const asn_SET_OF_specifics_t *)td->specifics;
 | 
			
		||||
    void *st = *aptr;
 | 
			
		||||
 | 
			
		||||
    if(!bptr) {
 | 
			
		||||
        if(*aptr) {
 | 
			
		||||
            asn_set_empty(_A_SET_FROM_VOID(*aptr));
 | 
			
		||||
            *aptr = 0;
 | 
			
		||||
        }
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(st == 0) {
 | 
			
		||||
        st = *aptr = CALLOC(1, specs->struct_size);
 | 
			
		||||
        if(st == 0) return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    asn_anonymous_set_ *a = _A_SET_FROM_VOID(*aptr);
 | 
			
		||||
    const asn_anonymous_set_ *b = _A_CSET_FROM_VOID(bptr);
 | 
			
		||||
 | 
			
		||||
    if(b->size) {
 | 
			
		||||
		void *_new_arr;
 | 
			
		||||
		_new_arr = REALLOC(a->array, b->size * sizeof(b->array[0]));
 | 
			
		||||
		if(_new_arr) {
 | 
			
		||||
			a->array = (void **)_new_arr;
 | 
			
		||||
			a->size = b->size;
 | 
			
		||||
		} else {
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        a->count = b->count;
 | 
			
		||||
 | 
			
		||||
        for(int i = 0; i < b->count; i++) {
 | 
			
		||||
            void *bmemb = b->array[i];
 | 
			
		||||
            if(bmemb) {
 | 
			
		||||
                void *amemb = 0;
 | 
			
		||||
                int ret;
 | 
			
		||||
                ret = td->elements->type->op->copy_struct(
 | 
			
		||||
                                                    td->elements->type,
 | 
			
		||||
                                                    &amemb, bmemb);
 | 
			
		||||
                if(ret != 0) return ret;
 | 
			
		||||
                a->array[i] = amemb;
 | 
			
		||||
            } else {
 | 
			
		||||
                a->array[i] = 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -129,13 +129,12 @@ SET_OF_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
 | 
			
		||||
        if(value) ct = 0;  /* Not restricted! */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(ct && ct->effective_bits >= 0) {
 | 
			
		||||
    if(ct && ct->upper_bound >= 1 && ct->upper_bound <= 65535
 | 
			
		||||
       && ct->upper_bound == ct->lower_bound) {
 | 
			
		||||
        /* X.691, #19.5: No length determinant */
 | 
			
		||||
        nelems = aper_get_nsnnwn(pd, ct->upper_bound - ct->lower_bound + 1);
 | 
			
		||||
        ASN_DEBUG("Preparing to fetch %ld+%lld elements from %s",
 | 
			
		||||
                  (long)nelems, (long long int)ct->lower_bound, td->name);
 | 
			
		||||
        if(nelems < 0)  ASN__DECODE_STARVED;
 | 
			
		||||
        nelems += ct->lower_bound;
 | 
			
		||||
        nelems = ct->upper_bound;
 | 
			
		||||
        ASN_DEBUG("Preparing to fetch %ld elements from %s",
 | 
			
		||||
                  (long)nelems, td->name);
 | 
			
		||||
    } else {
 | 
			
		||||
        nelems = -1;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user