A dummy client to do integration tests of the ns2 layer.
It drop all unit data. But allows vty tests.
Change-Id: I127c178426bc1a3da8de251740eda93853030d6d
The RIM Routing Information IE (see also 3GPP TS 48.018, section
11.3.70) is used to control the flow of BSSGP rim messages at the SGSN.
Change-Id: I6f88a9aeeb50a612d32e9efd23040c9740bc4f11
Related: SYS#5103
Historically, BSSGP uses a non-constant, user-configurable integer
varieable for the logging sub-system. Let's replace this with a
statically-allocated library logging constant.
This is required if we want to use the subsystem number in e.g.
static initialized for osmo_fsm.log_subsys.
Change-Id: I506190aae9217c0956e4b5764d1a0c0772268e93
100 minutes = 6000000000 microseconds was too big to be stored in an
unsigned long in a 32bit platform, making the test print 4294967295
instead. Let's set a smaller value to have the test happy on 32 bits.
Change-Id: Ic0d009f00a69cee59f2d3fc0b40ecdc97d81c75c
3GPP TS 24.008 section 10.5.1.7 describes a Mobile Station Classmark 3
IE, which is encoded as CSN.1 struct. This means that it can not be
parsed by just casting a memory location to a struct pointer, so lets
add a parser to parse the CM3 IE.
This is fixed version of Ic8b2bfd00330235f5bed00771e421588abfaac1f,
which got reverted because it used the keyword "class" as struct member,
which lead into problems with c++ builds. This is now fixed.
Change-Id: Id8732551b33616227609cd6fcf6c3133751a89eb
Related: OS#4796 SYS#5114
60 seconds = 6000000000 microseconds was too big to be stored in an
unsigned long in a 32bit platform, making the test print 4294967295
instead. Let's set a smaller value to have the test happy on 32 bits.
Change-Id: I97d53f6b7b410cef4b3f3fbe3162626fcdd7b05a
This reverts commit a4939dc846,
which caused massive build failures in C++ programs like osmo-pcu
- unsurprisingly, as it calls a struct member "class", which is a
reserved keyword in C++.
Change-Id: Ia43e56385e7b580f492c560aee8ff8b1e8a0e1d8
Some applications may need submillisecond timers, such as those
interacting with modbus serial lines (RS-485, RTU), which require
timers of values around 1.5 char-time (T1.5), where a data char is
composed of 11 bits sent on the line: 1 start bit, 8 data bits,
1 stop bit, and and parity bit (or 2nd stop bits if no parity).
For instance, for a baudrate of 9600:
1.5 * 11 / 9600 = 1.718 ms = 1718 us
So having a granularity of MS is not enough here.
Change-Id: I71848d7c1ee0649929ce07680ee7320bb2a42f0e
3GPP TS 24.008 section 10.5.1.7 describes a Mobile Station Classmark 3
IE, which is encoded as CSN.1 struct. This means that it can not be
parsed by just casting a memory location to a struct pointer, so lets
add a parser to parse the CM3 IE.
Change-Id: Ic8b2bfd00330235f5bed00771e421588abfaac1f
Related: OS#4796 SYS#5114
Some VTY commands are intentionally hidden, e.g. because they might
by relatively dangerous if used in production operation. We equip
such commands with a special attribute - CMD_ATTR_HIDDEN.
The problem is that neiter they appear in the XML VTY reference,
nor in the online VTY help, so it's a bit tricky to invoke them.
This change introduces so-called 'expert' mode, in which hidden
(but not deprecated) commands are getting visible.
In the (telnet) VTY session, this mode can be activated by passing
an additional argument to well-known 'enable' command:
OsmoApp> enable ?
[expert-mode] Enable the expert mode (show hidden commands)
OsmoApp> enable expert-mode
OsmoApp#
so then hidden commands will appear together with all the other
commands. They will be marked with a special '^' flag:
OsmoApp# list with-flags
^ ... foo-hidden [expert-mode]
. ... foo-regular-one
! ... foo-immediate
^ u.. app-hidden-unbelievable
For the XML reference generation, additional API needs to be
introduced. This will be implemented in subsequent patches.
Change-Id: Ie69c2a19b22fb31d7bd7f6412f0aeac86ea5048f
Related: SYS#4910
Otherwise we get (valid!) format string warnings like these on 32bit
targets:
[ 372s] bssmap_le/bssmap_le_test.c: In function 'test_bssmap_le_enc_dec':
[ 372s] bssmap_le/bssmap_le_test.c:141:15: warning: format '%ld' expects argument of type 'long int', but argument 2 has type 'int' [-Wformat=]
[ 372s] printf("[%ld] %s: ERROR: failed to encode pdu\n", (pdu - bssmap_le_test_pdus),
[ 372s] ^
Closes: OS#4786
Change-Id: Ib1c16b8adc5c8c0a2b418db51d12089f9b49a844
BSSLAP: there are APDUs transferred in BSSMAP-LE Connection Oriented
Information messages on Lb between BSC and SMLC.
Add BSSLAP coding for these APDU messages:
- TA Layer3
- TA Request
- TA Response, possibly containing Location Estimate coded in GAD
- Reject
- Reset (for intra-BSS handover during TA Request)
- Abort (for inter-BSS handover)
Add encoding and decoding tests.
Change-Id: I6409c4bcac402dc7626a3afce9081c59cd715fe8
GAD, Universal Geographical Area Description:
- raw coding for all GAD elements.
- SI-units encoding and decoding for Ellipsoid point with uncertainty circle,
which I presume is the typical "at most N meters away from cell tower located
at X,Y", which corresponds to the TA positioning currently being implemented.
- other SI-units GAD element encodings are so far not implemented.
Add encoding and decoding tests.
In gsm/protocol/gsm_23_032.h are the raw coding structs as defined in 3GPP TS
23.032.
In gsm/gad.h are structs carrying consistent units based on meters and degrees,
for convenient / less error prone handling of GAD data, and for human readable
representations of the GAD data.
The separation of the two is desirable because OsmoBSC will receive GAD data
from OsmoSMLC on the Lb interface, and pass on this data to the MSC via the A
interface. It is better to pass the GAD data as-is without de/encoding.
Change-Id: I7a9dd805a91b1ebb6353bde0cd169218acbf223c
This will be useful to handle latitude and longitude numbers for GAD, which is
the location estimate representation used for LCS (Location Services).
The OsmoSMLC VTY user interface will provide floating-point strings like
"23.456" while GAD stores them as micro-degress 23456000. The osmo_gad_to_str*
will also convert latitude and longitude to floating-point string.
There was code review concerns against adding this API, upon which I tried to
use floating point string formats. But I encountered various problems with
accuracy and trailing zeros. For global positioning data (latitude and
longitude), even inaccuracy on the sixth significant decimal digit causes
noticeable positional shift. To achieve sufficient accuracy on the least
significant end, I need to use double instead of float. To remove trailing
zeros, the idea was to use '%.6g' format, but that can cause rounding. '%.6f'
on a double looks ok, but always includes trailing zeros. A test program shows:
%.6g of ((double)(int32_t)23230100)/1e6 = "23.2301" <-- good
%.6g of ((double)(int32_t)42419993)/1e6 = "42.42" <-- bad rounding
%.6g of ((double)(int32_t)23230199)/1e6 = "23.2302" <-- bad rounding
%.6f of ((double)(int32_t)23230100)/1e6 = "23.230100" <-- trailing zeros
%.6f of ((double)(int32_t)42419993)/1e6 = "42.419993" <-- good
%.6f of ((double)(int32_t)23230199)/1e6 = "23.230199" <-- good
It looks like when accepting that there will be trailing zeros, using double
with '%.6f' would work out, but in the end I am not certain enough that there
aren't more hidden rounding / precision glitches. Hence I decided to reinforce
the need to add this API: it is glitch free in sufficient precision for
latitude and longitude data, because it is based on integer arithmetic.
The need for this precision is particular to the (new) OsmoSMLC vty
configuration, where reading and writing back user config must not modify the
values the user entered. Considering to add these functions to osmo-smlc.git,
we might as well add them here to libosmocore utils, and also use them in
osmo_gad_to_str_*() functions.
Change-Id: Ib9aee749cd331712a4dcdadfb6a2dfa4c26da957
As shown in the recently added bitgen_test.c, using osmo_loadXXbe_ext() with a
smaller n produces results aligned on the most significant bytes, which is
cumbersome, since it does not return a previously stored value. This problem
exists only for the big-endian functions, the little-endian osmo_loadXXle_ext()
properly return values adjusted on the least significant octets.
Add osmo_loadXXbe_ext_2() variants that properly right-adjust the returned
value. Prominently highlight this behavior in API doc. Test the new functions
in bitgen_test.c.
For example, this eases handling of 24bit integers (e.g. loaded from buffer to
uint32_t, and stored into buffer from uint32_t). Also explicitly show this 24
bit case in bitgen_test.c
Change-Id: I2806df6f0f7bf1ad705d52fa386d4525b892b928
The autogenerated bitXXgen.h headers for osmo_load16le_ext() thru
osmo_store64_be() are not actually tested at all. Add a test.
The test output shows that the osmo_load*be_ext for a shorter len do not return
nicely matching results. A practical example showing the difficulty in storing
and loading 24bit integer values as/from big-endian:
uint8_t buf[4];
memset(buf, 0, sizeof(buf));
osmo_store32be_ext(0x00112233, buf, 3); // stores 11 22 33
printf("%s\n", osmo_hexdump(buf, 4));
uint32_t r = osmo_load32be_ext(buf, 3); // returns 0x11223300, not 0x00112233
printf("0x%x\n", r);
output is:
11 22 33 00
0x11223300
In contrast, the little-endian variant properly aligns the loaded bytes on the
least significant octet:
uint8_t buf[4];
memset(buf, 0, sizeof(buf));
osmo_store32le_ext(0x00112233, buf, 3); // stores 33 22 11
printf("%s\n", osmo_hexdump(buf, 4));
uint32_t r = osmo_load32le_ext(buf, 3); // returns 0x00112233 as expected
printf("0x%x\n", r);
output for le is:
33 22 11 00
0x112233
Change-Id: I5542ace54376a206aa8574812d4c742c86c293b4
The function is checking for IP version matching between local and
remote addresses even if only one is needed based on flags. For example,
if user only desired to bind, the remote address should not be
used nor checked.
Bug was introduced here: 2c962f5de1
Change-Id: I87afd1db9bd017426abcc959fa515d15784cdf1c
According to 3GPP TS 44.005, section 4.2.2 "Priority":
a) on DCCH, a SAPI=0 frame always has higher priority than SAPI=3;
b) on ACCH, the priority arrangement is more complex:
b1) if a SAPI = 3 frame is awaiting transmission, two SAPI=0
frames shall not be sent in consecutive SACCH frames;
b2) on the network side (LAPDM_MODE_BTS), it must also be ensured
that any SAPI=3 frame is followed by at least one SAPI=0 frame;
b3) a SAPI = 0 frame may be repeated in the next SACCH period
if the Repeated SACCH is supported (see 3GPP TS 44.006, section 11).
We definitely need to extend our testing coverage to ensure that
we implement b) correctly, but for now let's focus on DCCH:
a) for DCCH, ensure that SAPI=0 frames preceed SAPI=3 ones;
b) for ACCH, re-use the existing round-robin implementation.
Change-Id: Ia3780bce1222b312ae2fd2d21496a4d6c5ccb6e0
Related: SYS#5047, OS#4731
Recently we've encountered a situation where during MT SMS delivery,
the func=SABM for SAPI=3 was sent on Downlink *before* the BTS
replied with the func=UA for SAPI=0 (contetion resolution procedure,
where we echo the (RR) Paging Response back to the MS).
This change adds a unit test reprodicing the problem.
Change-Id: Ied0f8bb683de8e37bcfa984c2877aa1cec1c0b4b
Related: SYS#5047, OS#4731
We intentionally do not match stderr output because it contains
non-deterministic messages (e.g. pointer addresses), so let's
make sure that all test specific messages go to stdout.
Change-Id: Ia52f8e811cee9d3e1cd5fcda49a9134ccaa31f7f
This is basically an ACKnowledgement for (RR) CM Service Request,
thus it contains a copy of the original Uplink message (cm).
Let's rename it to reflect this explicitly.
Change-Id: Id497ff4b688528916495387d64915b14396a68f1
This is basically a successor of gsm0808_create_sapi_reject(), but
instead of hard-coding GSM0808_CAUSE_BSS_NOT_EQUIPPED, it allows
the caller to specify a cause value to be used. The old function
is now deprecated and should not be used.
Change-Id: Iefe5484d0fa02d5722b628b1dc237d51d3fb1a9b
Related: OS#4728
Some systmes (like the ones available in OBS) don't support creating
SCTP sockets, so we need to skip those tests there.
Change-Id: I1d16280674625877ec22cc60cbc5deb67868a656
Drop one of the two log lines since it would be a duplicated and anyway
it misses context (return code).
Change-Id: I4620bf86f4bcda58ae85209278ac9ae9a0f3012a
The function is improved to support AF_INET:v4->v4, AF_INET6:v6->v6 and
AF_UNSPEC:v4+v6->v4+v6.
Unit tests for the function are added to make sure function behaves
correctly in several scenarios.
Change-Id: I36d8ab85d92bba4d6adb83bc1875eb61094ed2ef
osmo_sock_init2 abstract two calls of getaddrinfo into one.
While there aren't problems with AF_INET or AF_INET6. When using
AF_UNSPEC there are corner cases when this fails. E.g. calling
local_host with "" and remote_host with an IPv6 only address results in
setting up a local socket with AF_INET while trying to connect from there towards
AF_INET6 will most likely fail.
To prevent such cases with AF_UNSPEC, search prio calling any syscalls if local and remote site
supports AF_INET or AF_INET6. In case both supported, prefer AF_INET6
Change-Id: I397c633931fd00d4f083955a3c49a40fb002d766
When I wrote the new I.460 mux + demux code, I failed to realize that
* bit numbers in relevant ITU specs start with 1 as MSB ... 8 as LSB
* sub-slot 0 is bits 1+2, i.e. the two MSBs of a byte
* bit-ordering within each sub-slot is also MSB first
As a result, the code and test data was broken.
Change-Id: I6df7dbf411efbdeaf516e72ac552432bf5a569d0
When calling a user-provided call-back function for the i460 mux
or demux, always pass a pointer to the osmo_i460_subchan the callback
relates to. This way, the user can walk the i460 data structures
to obtain information about which mux/demux instances is calling.
Change-Id: Id842c72ce371a67fe5df6694e195c281aaf607ab
Without this patch, for instance having a range 0-ULONG_MAX would match
if someones types value -3, which would be converted to unsigned but
that's clearly what is expected here from user point of view.
Change-Id: Ia95f6314a2dd3f94d21fc219cf69bb8d39b8e7f0
This fixes commands not being matched due to providing a range with more
than 10 digits.
The last case (passing -4000 matching 0-ULONG_MAX) shows a different bug
which will be fixed in next commit.
Change-Id: I0afa0caabffe36083c36b92ba90696ded00bb7be
As per current status, the numeric tests are expected to fail due to a
couple bugs which will be fixed in next commits.
Change-Id: Id5b17bd96d7af4ed9a77ebbea0e6be4b0fcbde6c
This test knowingly calls deprecated functions -- allow that to squelch these
warnings:
warning: ‘gsm48_generate_lai’ is deprecated: Use gsm48_generate_lai2() instead, to not lose leading zeros in the MNC [-Wdeprecated-declarations]
warning: ‘gsm48_decode_lai’ is deprecated: Use gsm48_decode_lai2() instead, to not lose leading zeros in the MNC [-Wdeprecated-declarations]
Change-Id: Ifd618c1b9befa9c9ef0a338ab4aae2b0f796f4c2
Implement better API around 3GPP TS 24.008 Mobile Identity coding.
struct osmo_mobile_identity is a decoded representation of the raw Mobile
Identity, with a string representation as well as dedicated raw uint32_t TMSI.
The aim is to remove all uncertainty about decoded buffer sizes / data types.
I have patches ready for current osmo CNI programs, replacing the Mobile
Identity coding with this new API. Deprecate the old MI API.
osmo-bsc: I71c3b4c65dbfdfa51409e09d4868aea83225338a
osmo-msc: Ic3f969e739654c1e8c387aedeeba5cce07fe2307
osmo-sgsn: I4cacb10bac419633ca0c14f244f9903f7f517b49
Note that some GPRS and SGs related coding is done here in libosmocore and
hence currently remains using the old implementation (see previous version of
this patch: Ic3f969e739654c1e8c387aedeeba5cce07fe2307).
New API functions provide properly size-checking implementations of:
- decoding a raw MI from a bunch of MI octets;
- locating and decoding MI from a full 3GPP TS 24.008 Complete Layer 3 msgb;
- encoding to a buffer;
- encoding to the end of a msgb.
Other than the old gsm48_generate_mid(), omit a TLV tag and length from
encoding. Many callers manually stripped the tag and value after calling
gsm48_generate_mid(). The aim is to leave writing a TL to the caller entirely,
especially since some callers need to use a TvL, i.e. support a variable-size
length of 8 or 16 bit.
New validity checks so far not implemented anywhere else:
- stricter validation of number of digits of IMSI, IMEI, IMEI-SV MI.
- stricter on filler nibbles to be 0xf.
As a result, applications using osmo_mobile_identity will be stricter in
rejecting coding mistakes (some of which we currently have in our test suites,
and which we'll need to fix).
Rationale:
While implementing osmo-bsc's MSC pooling feature in osmo-bsc, this API will be
used to reduce the number of times a Mobile Identity is extracted from a raw
RSL message.
Extracting the Mobile Identity from messages has numerous duplicate
implementations across our code with various levels of specialization.
https://xkcd.com/927/
To name a few:
- libosmocore: gsm48_mi_to_string(), osmo_mi_name_buf()
- osmo-bsc: extract_sub()
- osmo-msc: mm_rx_loc_upd_req(), cm_serv_reuse_conn(), gsm48_rx_mm_serv_req(),
vlr_proc_acc_req()
We have existing functions to produce a human readable string from a Mobile
Identity, more or less awkward:
- gsm48_mi_to_string() decodes a TMSI as a decimal number. These days we use
hexadecimal TMSI everywhere.
- osmo_mi_name_buf() decodes the BCD digits from a raw MI every time, so we'd
need to pass around the raw message bytes. Also, osmo_mi_name_buf() has the
wrong signature, it should return a length like snprintf().
- osmo-bsc's extract_sub() first uses gsm48_mi_to_string() which encodes the
raw uint32_t TMSI to a string, and then calls strtoul() via
tmsi_from_string() to code those back to a raw uint32_t.
Each of the above implementations employ their own size overflow checks, each
invoke osmo_bcd2str() and implement their own TMSI osmo_load32be() handling.
Too much code dup, let's hope that each and every one is correct.
In osmo-bsc, I am now implementing MSC pooling, and need to extract NRI bits
from a TMSI Mobile Identity. Since none of the above functions are general
enough to be re-used, I found myself again copy-pasting Mobile Identity code:
locating the MI in a 24.008 message with proper size checks, decoding MI
octets.
This time I would like it to become a generally re-usable API.
This patch was first merged as Ic3f969e739654c1e8c387aedeeba5cce07fe2307 and
caused test fallout, because it re-implemented old API with the new stricter
decoding. In this patch version, old API remains 1:1 unchanged to avoid such
fallout. Applications will soon switch to the new osmo_mobile_identity API and
become stricter on MI coding when that happens, not implicitly by a new
libosmocore version.
Change-Id: If4f7be606e54cfa1c59084cf169785b1cbda5cf5
This reverts commit d1ceca9d48, as it
introduces regressions in both osmo-msc and osmo-nitb which have been
causing failing builds for several days now.
Change-Id: I4bd958d0cd2ab4b0c4725e6d114f4404d725fcf7
Implement better API around 3GPP TS 24.008 Mobile Identity coding.
struct osmo_mobile_identity is a decoded representation of the raw Mobile
Identity, with a string representation as well as dedicated raw uint32_t TMSI.
The aim is to remove all uncertainty about decoded buffer sizes / data types.
I have patches ready for all osmo programs, completely replacing the Mobile
Identity coding with this new API. Hence deprecate the old MI API.
New API functions provide properly size-checking implementations of:
- decoding a raw MI from a bunch of MI octets;
- locating and decoding MI from a full 3GPP TS 24.008 Complete Layer 3 msgb;
- encoding to a buffer;
- encoding to the end of a msgb.
Other than the old gsm48_generate_mid(), omit a TLV tag and length from
encoding. Many callers manually stripped the tag and value after calling
gsm48_generate_mid(). The aim is to leave writing a TL to the caller entirely,
especially since some callers need to use a TvL, i.e. support a variable-size
length of 8 or 16 bit.
New validity checks so far not implemented anywhere else:
- stricter validation of number of digits of IMSI, IMEI, IMEI-SV MI.
- stricter on filler nibbles to be 0xf.
Rationale:
While implementing osmo-bsc's MSC pooling feature in osmo-bsc, this API will be
used to reduce the number of times a Mobile Identity is extracted from a raw
RSL message.
Extracting the Mobile Identity from messages has numerous duplicate
implementations across our code with various levels of specialization.
https://xkcd.com/927/
To name a few:
- libosmocore: gsm48_mi_to_string(), osmo_mi_name_buf()
- osmo-bsc: extract_sub()
- osmo-msc: mm_rx_loc_upd_req(), cm_serv_reuse_conn(), gsm48_rx_mm_serv_req(),
vlr_proc_acc_req()
We have existing functions to produce a human readable string from a Mobile
Identity, more or less awkward:
- gsm48_mi_to_string() decodes a TMSI as a decimal number. These days we use
hexadecimal TMSI everywhere.
- osmo_mi_name_buf() decodes the BCD digits from a raw MI every time, so we'd
need to pass around the raw message bytes. Also, osmo_mi_name_buf() has the
wrong signature, it should return a length like snprintf().
- osmo-bsc's extract_sub() first uses gsm48_mi_to_string() which encodes the
raw uint32_t TMSI to a string, and then calls strtoul() via
tmsi_from_string() to code those back to a raw uint32_t.
Each of the above implementations employ their own size overflow checks, each
invoke osmo_bcd2str() and implement their own TMSI osmo_load32be() handling.
Too much code dup, let's hope that each and every one is correct.
In osmo-bsc, I am now implementing MSC pooling, and need to extract NRI bits
from a TMSI Mobile Identity. Since none of the above functions are general
enough to be re-used, I found myself again copy-pasting Mobile Identity code:
locating the MI in a 24.008 message with proper size checks, decoding MI
octets.
This time I would like it to become a generally re-usable API.
Change-Id: Ic3f969e739654c1e8c387aedeeba5cce07fe2307
These utilities will be used by osmo-bsc to determine the Network Resource
Indicator seen in the TMSI, and (potentially) by osmo-msc to compose a TMSI
with a specific NRI, for osmo-bsc's load balancing between several MSCs.
Add utility functions to:
- extract an NRI value from a TMSI.
- overwrite the NRI value in a TMSI.
- limit an NRI in a (random) TMSI to a given list of ranges.
- add NRI value ranges to a list.
- remove them from a list.
- match NRI value (range) to a list.
- parse NRI values from string, for VTY.
- common VTY functionality of adding/removing NRI values from argv.
Add C tests for the above.
Why we need public API for NRI ranges: In osmo-bsc alone, we need the same NRI
API twice, 1: to manage/list NRI value ranges per-MSC, and 2: to manage/list
NULL-NRI values. If we also consider (potentially) adding NRI support to
osmo-msc, we need the same API twice again there. Hence it is useful to define
re-used API up here in libosmocore.
Related: OS#3682
Change-Id: Icb57a2dd9323c7ea11b34003eccc7e68a0247bf5
The call identifier in the ASSIGNMENT COMMAND is encoded in the wrong
endieness. 3GPP TS 48.008, section 3.2.2.105 specifies that the least
significant byte should be transmitted first, which means that the
endieness here is little endian. Lets make sure that the endieness is
correctly transmitted, regardless of the host byte order.
Change-Id: I6468e502f552f99ab54aec9d4b1c169fdc0adfb8
Related: OS#4582
This implements a multiplexer and de-multiplexer for the ITU-T I.460
standard. The latter covers the transmission of sub-slots of 32/16/8k
inside 64k timeslots.
Change-Id: Id522f06e73b77332b437b7a27e4966872da70eda
These functions implement re-ordering of bits as per TS 06.90 / 26.101
based on the already existing tables we've had in libosmocoding.
Change-Id: Ia4ac2aea2e96f9185f082a07ca64dfc5276efb46
Function gsm0808_get_cipher_reject_cause() was previously available
in private gsm0808_utils.h. In practice, the exact same code is useful
to extract Cause IE value from any of the many other BSSMAP messages
which use it.
So let's rename it to gsm0808_get_cause() and make it avilable
to everyone to use.
Change-Id: Idf2b99e9ef014eba26e3d4f0f38c2714d3a0520a
The value string array that explain the type of the AMR DTX / SID
frames is incomplete, lets add the missing strings.
Change-Id: If9e80b4bd8bdc31323c7c276155b2538e20a99be
Related: OS#2978
See TS 08.08 section 3.2.1.34 SAPI "n" REJECT:
1) DLCI is a TV element, not V.
2) Cause is a TLV element and we have a special function to encode it.
Change-Id: I033afe556c06427d06ac55c4f78854a45e41aae6
When switching the l2 structures passes to test_pdtch() to be constant,
it was noted that output of the test changes. This happens because same
array is tested several times with different length, incrementing each
time. Since the test was modifying the input array directly, it means
each new run of test_pdtch() the array was further modified.
Upon constifying the structures, we copy the array and hence only modify
the required bits each time.
Change-Id: Iffd0ca3669eb8d0d2e80d754fc8acbf72f1bebe8
gsm0503_coding contains AMR decoder functions for HR and FR. Those can
only decode AMR payload frames but not amr DTX frames. Lets add
functionality to detect DTX frames. Also lets add decoding for SID_UPDATE
frames as well as error checking for the SID frame recognition patterns.
Related: OS#2978
Change-Id: I2bbdb39ea20461ca08b2e6f1a33532cb55cd5195
According to 3GPP TS 44.004, figure 7.4a.b, the format of 11-bit
RACH uplink / Uplink access burst block is as defined follows:
<---------------------------------------------------
8 7 6 5 4 3 2 1
+--------------------------------------------------+
| 11 bit RACH uplink / Uplink access burst block | OCT1
+--------------------------------------------------+
| | OCT2
+-------------------+
As was (correctly) assumed in [1], the bit ordering in 11-bit RACH
coding functions is wrong. The problem is that neither of generic
functions from bit16gen.h can be used to load / store the RA11
value (regardless of the endianness), because they assume that
the payload is 16 bit long.
With this patch applied, RA11 values from [1] look correct:
< EGPRS Packet channel request message content > ::=
< Signalling : 110011 < RandomBits : 00111 > > |
< Signalling : 110011 < RandomBits : 00110 > > |
< Signalling : 110011 < RandomBits : 01111 > > |
< Signalling : 110011 < RandomBits : 01100 > > |
< Signalling : 110011 < RandomBits : 00111 > > |
< Signalling : 110011 < RandomBits : 10110 > > ;
[1] Id80e471d252b9416217b56f4c8c0a8f5f1289fee
Change-Id: I43d30611dd69f77f2b3b46f4b56056a8891d3c24
Related: OS#1548
This change adds several soft-bit (-127 .. 127) sequences containing
EGPRS Packet Channel Request message (11-bit, payload only) sent by
an EGPRS capable phone, and captured on the BTS/PCU side using a
tool from the TRX Toolkit - trx_sniff.py.
As can be seen from the test output, none of decoded RA11 values
looks like a valid EGPRS Packet Channel Request message (see
table 11.2.5a.2 of 3GPP TS 44.060). All test sequences contain
the same message with several random bits:
< EGPRS Packet channel request message content > ::=
< Signalling : 110011 < RandomBits : bit (5) > >;
since the phone was trying to perform Attach Request. It seems
the bit order of decoded messages is somehow wrong.
Change-Id: Id80e471d252b9416217b56f4c8c0a8f5f1289fee
Related: OS#1548
We don't really need additional 1.4M of debug output, given that
we test every possible 8-bit and 11-bit RA value. It's enough
to print error message if the resulting value does not match.
Otherwise it's hard to read the expected output without commenting
the related log statements out. Note that it's still possible to
re-enable verbose debug output by defining DEBUG.
Change-Id: I0d5ed90cb0a2b3007d665520a73b0fa0b86a4099
The table amr_len_by_ft represents the length of the raw AMR speech bits
in bytes. The table is based on the Table found in RFC 4867 §3.6, Table 1,
Column "Total speech bits". The number of bits is divided by 8 and then
rounded up to get the number of consumed octets.
An AMR SID frame (including STI and MI) takes up 39 bits, this will
result in 5 octets, not in 7. Lets correct this.
Related: OS#2978
Change-Id: Icf330450981b32be5d1cee5b10aa92bac4cb72f5
AMR SID update frames are protected using an 1/4 convolutional coder,
wich is similar to the one used with 6,7 kbit voice frames. Except that
there is no puncturing and the length is different.
Change-Id: Ia35ed4178a7f0d816052b7e5d6478b93a1d9744f
Related: OS#2978
This function is supposed to return 0 on success or 1 in case of
error. However, it used to return 1 even in case of success. The
reason is that length of the input string was not taken into
account and sscanf() was failing on '\0'.
Let's use osmo_hexparse() and rely on its return value.
P.S. Funny that the unit test expectations were wrong too.
Change-Id: I441a22c7964bb31688071d8bcf6a282d8c0187ff
The aim of this unit test is to demonstrate the problem described
in OS#4388: bitvec_read_field() can never return negative value
on error (e.g. out of bounds access).
Change-Id: I340ab5799fa53d5345edb02f3e2a3655527705c0
Related: OS#4388
In some situations, we want to execute an external shell command
in a non-blocking way. Similar to 'system', but without waiting for
the child to complete. We also want to close all file descriptors
ahead of the exec() and filter + modify the environment.
Change-Id: Ib24ac8a083db32e55402ce496a5eabd8749cc888
Related: OS#4332
Make build and external tests work with python3, so we can drop
the python2 dependency.
This should be merged shortly after osmo-python-tests was migrated to
python3, and the jenkins build slaves were (automatically) updated to
have the new osmo-python-tests installed.
Related: OS#2819
Depends: osmo-python-tests I3ffc3519bf6c22536a49dad7a966188ddad351a7
Change-Id: I84ef43f700e125c7a65f92347f12844e07e65655
This is a bit of a hack, as we want to maintain binary compatibility
without breaking existing users of libosmocore. To do so, we use the
'num_auth_vectors' field in two ways now:
* In the existing use case as part of SEND_AUTH_INFO_RESPONSE, it
indicates the number of vectors stored in the 'auth_vectors' field
* In the new use case as part of SEND_AUTH_INFO_REQUEST, it indicates
the number of vectors actually requested by the MSC/SGSN/MME.
Change-Id: Iaecc47280f8ce54f3e3a888c1cfc160735483d0f
Provide string escaping that
- returns the required buffer size, so it can be used with OSMO_STRBUF_APPEND().
- uses C compatible string constant escaping sequences.
This is intended as a replacement for all previous osmo_escape_str* and
osmo_quote_str* API. It pains me that I didn't get them right the first nor the
second time:
- The buffer functions do not return the chars needed, which is required for
allocating sufficient memory in the *_c versions of the functions.
- Because of that, these functions are accurately usable for
OSMO_STRBUF_APPEND(), producing truncated strings, for example when dumping a
GSUP message.
- They do not use the C equivalent string constant escaping: for some reason I
thought "\15" would be valid, but it should be "\x0f".
If I could, I would completely drop those mislead implementations ... but
backwards compat prohibits that.
A previous patch already provided internal static functions that accurately
return the required buffer size. Enhance these to also support C compatible
string escaping, and use them as implementation of the new functions:
osmo_escape_cstr_buf()
osmo_escape_cstr_c()
osmo_quote_cstr_buf()
osmo_quote_cstr_c()
In the tests for these, also test C string equivalence.
Naming: from API versions, it would be kind of logical to call them
osmo_escape_str_buf3() and osmo_escape_str_c2(). Since these anyway return a
different escaping, it makes sense to me to have distinct names instead.
Quasi missing are variants of the non-C-compatible weird legacy escaping that
return the required buffer size, but I refrain from adding those, because we
have enough API cruft as it is. Just always use these new cstr variants.
Change-Id: I3dfb892036e01000033dd8e7e4a6a0c32a3caa9b
Keep track of parent nodes and go back hierarchically, not only for .cfg file
reading, but also for telnet VTY sessions.
A long time ago cfg file parsing was made strictly hierarchical: node exits go
back to parent nodes exactly as they were entered. However, live telnet VTY
sessions still lacked this and depended on the go_parent_cb().
From this commit on, implementing a go_parent_cb() is completely optional. The
go_parent_cb() no longer has the task to determine the correct parent node,
neither for cfg files (as already the case before this patch) nor for telnet
VTY sessions (added by this patch). Instead, a go_parent_cb() implementation
can merely take actions it requires on node exits, for example applying some
config when leaving a specific node.
The node value that is returned by the go_parent_cb() and the vty->node and
vty->index values that might be set are completely ignored; instead the
implicit parent node tracking determines the parent and node object.
As a side effect, the is_config_node() callback is no longer needed, since the
VTY now always implicitly knows when to exit back to the CONFIG_NODE.
For example, osmo_ss7_is_config_node() could now be dropped, and the
osmo_ss7_vty_go_parent() could be shortened by five switch cases, does no
longer need to set vty->node nor vty->index and could thus be shortened to:
int osmo_ss7_vty_go_parent(struct vty *vty)
{
struct osmo_ss7_asp *asp;
struct osmo_xua_server *oxs;
switch (vty->node) {
case L_CS7_ASP_NODE:
asp = vty->index;
/* If no local addr was set */
if (!asp->cfg.local.host_cnt) {
asp->cfg.local.host[0] = NULL;
asp->cfg.local.host_cnt = 1;
}
osmo_ss7_asp_restart(asp);
break;
case L_CS7_XUA_NODE:
oxs = vty->index;
/* If no local addr was set, or erased after _create(): */
if (!oxs->cfg.local.host_cnt)
osmo_ss7_xua_server_set_local_host(oxs, NULL);
if (osmo_ss7_xua_server_bind(oxs) < 0)
vty_out(vty, "%% Unable to bind xUA server to IP(s)%s", VTY_NEWLINE);
break;
}
return 0;
}
Before parent tracking, every program was required to write a go_parent_cb()
which has to return every node's parent node, basically a switch() statement
that manually traces the way back out of child nodes. If the go_parent_cb() has
errors, we may wildly jump around the node tree: a common error is to jump
right out to the top config node with one exit, even though we were N levels
deep. This kind of error has been eliminated for cfg files long ago, but still
exists for telnet VTY sessions, which this patch fixes.
This came up when I was adding multi-level config nodes to osmo-hlr to support
Distributed GSM / remote MS lookup: the config file worked fine, while vty node
tests failed to exit to the correct nodes.
Change-Id: I2b32b4fe20732728db6e9cdac7e484d96ab86dc5
Follow up for patch I3cf150cc0cc06dd36039fbde091bc71b01697322
osmo_sockaddr_str_{from,to}_32n actually use host byte order. Deprecate these
and introduce a more accurately named version ending in h.
Change-Id: Ic7fc279bf3c741811cfc002538e28e8f8560e338
When finding a char in a string, I want to be able to limit the search area by
size, not only by nul terminator.
Change-Id: I48f8ace9f51f8a06796648883afcabe3b4e8b537
A couple of times recently I've needed to copy out a substring to a buffer with
limited size. Use of strncpy() or osmo_strlcpy() are nontrivial here.
I wanted to have a dedicated function.
After I wrote that function with a test, I noticed that I had already
implemented the same thing a while ago, as osmo_print_n() :P
So here is just the test.
Change-Id: Ia716abdc1f58af6065b84f4f567388a32a7b39fc
Provide a common implementation for foo_name_c() functions that base on
foo_name_buf() functions.
char *foo_name_c(void *ctx, example_t arg)
{
OSMO_NAME_C_IMPL(ctx, 64, "ERROR", foo_name_buf, arg)
}
Rationale: the most efficient way of composing strings that have optional parts
or require loops for composition is by writing to a ready char[], and this in
turn is easiest done by using OSMO_STRBUF_* API. Using such a basic name string
implementation which typically returns a length, I often want a more convenient
version that returns a char*, which can just be inlined in a "%s" string format
-- crucially: skipping string composition when inlined in a LOGP(). This common
implementation allows saving code dup, only the function signature is needed.
Why not include the function signature in the macro? The two sets of varargs
(1: signature args, 2: function call args) are hard to do. Also, having an
explicit signature is good for readability and code grepping / ctags.
Upcoming uses: in libosmocore in the mslookup (D-GSM) implementation
(osmo_mslookup_result_name_c()), and in osmo_msc's codec negotiation
implementation (sdp_audio_codecs_name_c(), sdp_msg_name_c(), ...).
I54b6c0810f181259da307078977d9ef3d90458c9 (libosmocore)
If3ce23cd5bab15e2ab4c52ef3e4c75979dffe931 (osmo-msc)
Change-Id: Ida5ba8d9640ea641aafef0236800f6d489d3d322
Of course both v4 and v6 addresses are kept in network byte order when
represented in bytes, but when writing, I somehow must have assumed that
inet_pton() returns host byte order. Fix that mixup in the API docs:
osmo_sockaddr_str_from_32() and osmo_sockaddr_str_to_32() actually use network
byte order.
osmo_sockaddr_str_from_32n() and osmo_sockaddr_str_to_32n() actually use host
byte order, though reflecting 'n' in their name.
sockaddr_str_test: use hexdump instead of %x to show the
osmo_sockaddr_str_to_32*() conversions so that the error becomes obvious.
(Printing %x reverses the bytes again and made it look correct.)
Change-Id: I3cf150cc0cc06dd36039fbde091bc71b01697322
It's hard to figure out what color logging categories have with those ANSI
color code strings. Instead, define these OSMO_LOGCOLOR_* constants.
Naming: commonly, the logging.h header has the "LOG" prefix in the name, but it
seems saner to include the OSMO_ prefix: it seems too likely that some
libosmocore user somewhere already has defined "LOGCOLOR_RED" somewhere.
Change-Id: I03b6b1f73ae7ee61d37ff921e071a3d0881d3e9a
Currently planned user: for Distributed GSM in osmo-hlr: setting per-MSC
service addresses in VTY: replace/remove existing entries.
osmo_sockaddr_str_cmp() is useful to catch identical resulting IP addresses,
regardless of differing strings (e.g. '0::' and '::' are equal but differ in
strings).
Change-Id: I0dbc1cf707098dcda75f8e07c1b936951f9f9501
Setting vty->fd to 0 is a bad idea, which may cause the process
to write() warnings to its own _stdin_ (yes, it's possible).
For example, when a configuration file contains deprecated
logging commands. Let's use stderr by default.
Change-Id: Icdeaea67a06da3a2f07b252e455629559ecc1829
We shall not prevent programs from starting if their configuration
files contain deprecated 'logging level ...' commands. Just print
a warning and return CMD_SUCCESS instead of CMD_WARNING.
While writing a unit test, another funny bug has been uncovered.
Parsing of a deprecated command indeed triggers a deprecation
warning, originated from libosmovty's log_deprecated_func().
This function simply calls vty_out(), but...
Since the invocation of the vty_out() happens _before_ the VTY
is initialized, the process is actually writing that warning
to its own stdin! Most likely, because we use talloc_zero()
to allocate a new instance of struct 'vty'.
As a side effect, the evil warning magically appears in the output
of 'make check', breaking the test statistics. Let's work around
this bug for now by redirecting stdin to /dev/null.
Change-Id: Ia934581410cd41594791d4e14ee74c16abe1009a
Fixes: Ic9c1b566ec4a459f03e6319cf369691903cf9d00
The format prints IP:port separated by a colon, which of course is confusing
when the IPv6 address itself contains mostly colons. The new format adds square
braces.
cafe:face::1:42 -> [cafe:face::1]:42
The IPv4 format remains unchanged:
1.2.3.4:42
Change-Id: I161f8427729ae31be0eac719b7a4a9290715e37f
Often, an IP address of 0.0.0.0 is considered an unset value (for clients
requiring a server address; not for listening on "any").
osmo_sockaddr_str_is_set() does return false when the port is 0, but there is
no simple way to tell whether the IP address is actually set to a server
address.
Add osmo_sockaddr_str_is_nonzero() to return false if:
- the port is zero, or
- the IP address is zero (0.0.0.0 or ::0), or
- the IP address cannot be parsed.
A practical use example: osmo-msc so far accepts an RTP IP address of 0.0.0.0
as valid. I noticed when trying to trigger error handling from a ttcn3 test.
osmo-msc can use this function to reject invalid addresses from MGCP messages.
Related: I53ddb19a70fda3deb906464e1b89c12d9b4c7cbd (osmo-msc)
Change-Id: I73cbcab90cffcdc9a5f8d5281c57c1f87b2c3550
Refuse state changes and event dispatch for FSM instances that are already
terminating.
It is assumed that refusing state changes and events after FSM termination is
seen as the sane expected behavior, hence this change in behavior is merged
without being configurable.
There is no fallout in current Osmocom code trees. fsm_dealloc_test needs a
changed expected output, since it is explicitly creating complex FSM structures
that terminate. Currently no other C test in Osmocom code needs adjusting.
Rationale:
Where multiple FSM instances are collaborating (like in osmo-bsc or osmo-msc),
a terminating FSM instance often causes events to be dispatched back to itself,
or causes state changes in FSM instances that are already terminating. That is
hard to avoid, since each FSM instance could be a cause of failure, and wants
to notify all the others of that, which in turn often choose to terminate.
Another use case: any function that dispatches events or state changes to more
than one FSM instance must be sure that after the first event dispatch, the
second FSM instance is in fact still allocated. Furthermore, if the second FSM
instance *has* terminated from the first dispatch, this often means that no
more actions should be taken. That could be done by an explicit check for
fsm->proc.terminating, but a more general solution is to do this check
internally in fsm.c.
In practice, I need this to avoid a crash in libosmo-mgcp-client, when an
on_success() event dispatch causes the MGCP endpoint FSM to deallocate. The
earlier dealloc-in-main-loop patch fixed part of it, but not all.
Change-Id: Ia81a0892f710db86bd977462730b69f0dcc78f8c
This is a simpler and more general solution to the problem so far solved by
osmo_fsm_term_safely(true). This extends use-after-free fixes to arbitrary
functions, not only FSM instances during termination.
The aim is to defer talloc_free() until back in the main loop.
Rationale: I discovered an osmo-msc use-after-free crash from an invalid
message, caused by this pattern:
void event_action()
{
osmo_fsm_inst_dispatch(foo, FOO_EVENT, NULL);
osmo_fsm_inst_dispatch(bar, BAR_EVENT, NULL);
}
Usually, FOO_EVENT takes successful action, and afterwards we also notify bar.
However, in this particular case, FOO_EVENT caused failure, and the immediate
error handling directly terminated and deallocated bar. In such a case,
dispatching BAR_EVENT causes a use-after-free; this constituted a DoS vector
just from sending messages that cause *any* failure during the first event
dispatch.
Instead, when this is enabled, we do not deallocate 'foo' until event_action()
has returned back to the main loop.
Test: duplicate fsm_dealloc_test.c using this, and print the number of items
deallocated in each test loop, to ensure the feature works. We also verify that
the deallocation safety works simply by fsm_dealloc_test.c not crashing.
We should probably follow up by refusing event dispatch and state transitions
for FSM instances that are terminating or already terminated:
see I0adc13a1a998e953b6c850efa2761350dd07e03a.
Change-Id: Ief4dba9ea587c9b4aea69993e965fbb20fb80e78
The calculation of the beginning of a block for TCH/F, TCH/H and FACCH
can be challenging since those channels are affected by the diagonal
interleaving of the TCH channels. However, GSM 05.02 Section 7 Table 1
of 5 specifies how the blocks are distributed over the TDMA frame
interval. Lets add a mapping function that is based on that table
Related: OS#3803
Change-Id: I3d71c66f8c401f5afbad9b1c86c24580dab9e0ce
log_enable_multithread() enables use of locks inside the
implementation. Lock use is disabled by default, this way only
multi-thread processes need to enable it and suffer related
complexity/performance penalties.
Locks are required around osmo_log_target_list and items inside it,
since targets can be used, modified and deleted by different threads
concurrently (for instance, user writing "logging disable" in VTY while
another thread is willing to write into that target).
Multithread apps and libraries aiming at being used in multithread apps
should update their code to use the locks introduced here when
containing code iterating over osmo_log_target_list explictly or
implicitly by obtaining a log_target (eg. osmo_log_vty2tgt()).
Related: OS#4088
Change-Id: Id7711893b34263baacac6caf4d489467053131bb
This is useful for timers expected to have a range of valid or expected
values.
Validation is done at runtime when timer values are set by the app or by
the user through the VTY.
Related: OS#4190
Change-Id: I4661ac41c29a009a1d5fc57d87aaee6041c7d1b2
OSMO_GSUP_SUPPORTED_RAT_TYPES_IE corresponds to the Supported RAT Types
Indicator from 3GPP TS 29.002. See 8.1.2 MAP_UPDATE_LOCATION service,
which indicates the capabilities of the MSC/VLR to the HLR.
So far, have room for eight RAT types in the gsup_msg. That is an arbitrary
random choice without any rationale.
OSMO_GSUP_CURRENT_RAT_TYPE_IE is useful to communicate the currently
used RAN / RAT type of the current subscriber during Location Updating Request.
Change-Id: I93850710ab55a605bf61b95063a69682a2899bb1
Since structure 'osmo_gcr_parsed' does contain arrays, GCC is not
happy about the way we initialize it. Let's do it explicitly.
Change-Id: Ia814b4a4ed5bec84ff1f69232f7f7d5ca0d19794
The ECU implementation for FR is currently tested by calling the related
functions directly and by using the generic ECU abstraction layer. However,
the test "test_fr_concealment" only tests directly. Lets add a version
that uses the generic ECU abstraction layer as well.
The generic ECU abstraction layer obsolets the public API functions
osmo_ecu_fr_reset() and osmo_ecu_fr_conceal(), lets tag those functions
as dprecated.
Change-Id: Ib0c8a9b164f14ea4fa00688f760a76cdb4890af4
We don't want to expose the details of a given ECU implementation to
the user (e.g. osmo-bts), but have a generic abstraction layer where
an ECU implementation can simply register a few call-back functions
with the generic core.
As the developer and copyright holder of the related code, I hereby
state that any ECU implementation using 'struct osmo_ecu_ops' and
registering with the 'osmo_ecu_register()' function shall not be
considered as a derivative work under any applicable copyright law;
the copyleft terms of GPLv2 shall hence not apply to any such ECU
implementation.
The intent of the above exception is to allow anyone to combine
third party Error Concealment Unit implementations with libosmocore,
including but not limited to such published by ETSI.
Change-Id: I4d33c9c7c2d4c7462ff38a49c178b65accae1915
Rather than having applications maintain their own talloc cotexts,
let's offer some root talloc contexts in libosmocore. Let's also
make them per thread right from the beginning. This will help
some multi-threaded applications to use talloc in a thread-safe
way.
Change-Id: Iae39cd57274bf6753ecaf186f229e582b42662e3
When reading SUT logs resulting from TTCN3 runs, it can be hard to figure out
which log section corresponds to which test code. Add a 'logp' command on VIEW
and ENABLE nodes that simply echos an arbitrary message on log output, useful
to set markers / explanations from the TTCN3 code, which then appear in all log
outputs and can make it trivial to figure out which log section is interesting.
logging_vty_test# logp lglobal notice This is the log message
DLGLOBAL NOTICE This is the log message
From TTCN3, could be used like this, e.g. in BSC_Tests.ttcn:
private function f_logp(charstring log_msg) runs on MSC_ConnHdlr
{
// log on TTCN3 log output
log(log_msg);
// log in stderr log
f_vty_transceive(BSCVTY, "logp lglobal notice " & log_msg);
}
...
f_logp("f_probe_for_handover(" & log_label & "): Ending the test: Handover Failure stops the procedure.");
Change-Id: Ife5dc8999174c74e0d133729284fe526d6eaf8d9
Since March 15th 2017, libosmocore API logging_vty_add_cmds() had its
parameter removed (c65c5b4ea0). However,
definition in C file doesn't contain "(void)", which means number of
parameters is undefined and thus compiler doesn't complain. Let's remove
parameters from all callers before enforcing "(void)" on it.
Related: OS#4138
Change-Id: Iaea795521361a8e5b3b45eaeb35e6eda69163af3
After recent system upgrade, gcc 9.1.0, I started getting gsm0808_test
failing locally:
Assert failed memcmp(&enc_ct, &dec_ct, sizeof(enc_ct)) == 0 libosmocore/tests/gsm0808/gsm0808_test.c:992
During investigation with gdb, fields of both structures seem to contain
same values. However, closer lookup gives some hints on why it fails:
(gdb) print memcmp(&enc_ct, &dec_ct, sizeof(enc_ct))
$1 = 85
(gdb) print memcmp(&enc_ct, &dec_ct, 12)
$14 = 85
(gdb) print ((uint8_t*)&enc_ct)[11]
$15 = 85 'U'
(gdb) print ((uint8_t*)&dec_ct)[11]
$16 = 0 '\000'
So the 12th byte in struct gsm0808_channel_type is basically an
alignment padding byte added by the compiler (to align perm_spch_len to
4-byte alignment). Since both compared structs are initialized without
memset(0) but using compiler's designated initializers, it seems the compiler
decided it's no longer needed to zero the padding byte, making memcp fail in
this case.
In order to avoid the failure, let's properly check every field instead
of using memcp here.
Change-Id: I17fe7a0a5dc650f050bba1f47d071be749550729
When using `OSMO_ASSERT(exp);` clang will warn about
an empty expression because the semi colon was superflous.
Use do {} while (0) to enfore the need of a semi colon.
This might break other test.
Change-Id: I2272d29a81496164bebd1696a694383a28a86434
For instance, take command "single0 [one]":
If user executes "single0 on", VTY func will receive argv[0]="one"
instead of argv[0]="on".
Related: OS#4045
Change-Id: I5f4e2d16c62a2d22717989c6acc77450957168cb
For instance, take command "multi0 (one|two|three)":
If user executes "multi0 tw", VTY func will receive argv[0]="two"
instead of argv[0]="tw".
Fixes: OS#4045
Change-Id: I91b6621ac3d87fda5412a9b415e7bfb4736c8a9a
The test shows that in the case were "single0 on" is executed, VTY
function should return complete "single0 one" but it doesn't.
Related: OS#4045
Change-Id: Ib5b9dc07e2b280dc95011b3926afb1d490cadd81
inner block defined variable "enum match_type ret" was being masking
outter block variable "int ret = 0". The ret variable was being given
non zero values only inside the inner block, so that change was done on
the inner variable and not the outer one, which is returned.
Fixes: 5314c513f2
Change-Id: Iec87d7db49a096d07e38ff8a060b923a52bfd6ba
Return ENOSPC if the decoding buffer is one byte too small, instead of
returning 0 and silently truncating the string. Add a new "truncated"
variable to detect if the loop breaks in the final iteration.
The string is not truncated if there is exactly one 0xf ('\0') higher
nibble remaining. This is covered by the existing test case "long
15-digit (maximum) MSISDN, limited buffer".
Related: OS#4049
Change-Id: Ie05900aca50cc7fe8a45d17844dbfcd905fd82fe
This patch is a result of discussion we had in [1]. The key idea
is that libosmovty should properly auto-complete the commands
containing choice, such as the following one:
multi0 (one|two|three)
[1] If9b0c0d031477ca87786aab5c269d00748e896c8
Right now, sending the following command:
(osmo-foo-bar)# multi0 th
would basically match the following vector:
multi0 three
however the resulting argv would be:
["multi0", "th"]
Moreover, sending the following command:
(osmo-foo-bar)# multi0 t
would basically match the following vectors:
multi0 two
multi0 three
because both start from 't', so the resulting argv would be:
["multi0", "t"]
which is ambiguous!
The expected output is:
(osmo-foo-bar)# multi0 th
ok argc=1 three
(osmo-foo-bar)# multi0 t
% Ambiguous command.
This is going to be fixed in the follow up patches.
Change-Id: I83c3aef813173952641035862c534ef16384780e
The documentation of gsm48_decode_bcd_number2() clearly states that
the output truncation is a erroneous case, so it should actually
return negative in such cases. Let's return -ENOSPC.
Change-Id: I75680f232001ba419a587fed4c24f32c70c3ad2b
Thanks to the new unit test for BCD number encoding / decoding, it was
discovered that gsm48_decode_bcd_number2() does not properly handle
encoded LV if the output buffer size is equal to the original MSISDN
length + 1 (\0-terminator): one digit is lost.
For example, decoding of 15-digit long MSISDN to a buffer of size
16 (15 digits + 1 for \0) would give us only 14 digits.
The problem was that 'output_len' was being decremented before
checking the remaining buffer length and writing a digit to it.
As a result, the maximum length was always one byte shorter.
Change-Id: I61d49387fedbf7b238e21540a5eff22f6861e27a
Fixes: OS#4025
So far, both gsm48_encode_bcd_number() and gsm48_decode_bcd_number2()
did not have any unit test coverage. Let's fill this gap by testing
the following scenarios:
- encoding / decoding of a regular 9-digit MSISDN;
- encoding / decoding of a MSISDN with optional LHV;
- encoding / decoding of a long 15-digit MSISDN;
- encoding / decoding of a MSISDN to a buffer:
- with exactly matching size,
- with lower size (truncation);
- decoding LV buffer with incorrect length,
- encoding / decoding an empty input buffer.
As it turns out, gsm48_decode_bcd_number2() does not properly
handle encoded LV if the output buffer size is equal to the
original MSISDN length + 1 (\0-terminator): one digit is lost.
For example, decoding of 15-digit long MSISDN to a buffer of size
16 (15 digits + 1 for \0) would give us only 14 digits. This is
reflected in the unit test output:
Decoding HEX (buffer limit=16) '0821436587092143f5'...
Expected: (rc=0) '123456789012345'
Actual: (rc=0) '12345678901234'
Moreover, if the output buffer is shorter than decoded number,
gsm48_decode_bcd_number2() silently truncates it and returns 0,
while its description states, that the rc should reflect this.
To be fixed in the follow-up patches.
Change-Id: I4b2c330cf8ffe4427c0bee7d5f3b74be56ecd85d
Related: OS#4025
libosmo{core,gsm,vty} code is GPLv2+. The OAP code originated in
osmo-msc.git and was moved here without changing the license. That
was a mistake, it always was meant to be under GPLv2-or-later after
moving to libosmocore.git.
Copyright is with sysmocom, so I as the managing director can
approve the license change.
Change-Id: I08311fa8214c15f8df8945b9894226608cf96f15
So far, the TLV code contained two types of functions
* tlp_parse() to parse all TLVs according to definition into tlvp_parsed
* various helper functions to encode individual TLVs during message
generation
This patch implements the inverse of tlv_parse(): tlv_encode(), which
takes a full 'struct tlv_pared' and encodes all IEs found in it. The
order of IEs is in numerically ascending order of the tag.
As many protocols have different IE/TLV ordering requirements, let's add
a tlv_encode_ordered() function where the caller can specify the TLV
ordering during the one-shot encode.
Change-Id: I761a30bf20355a9f80a4a8e0c60b0b0f78515efe
Based on a draft created by Neels, which is the result of reading a MAP
trace of two MSCs negotiating inter-MSC handovers, and of reading the
TS 29.002, TS 29.010 and related specs:
https://lists.osmocom.org/pipermail/openbsc/2019-January/012653.html
I figured out that the "Handover Number" mentioned in the specifications
is the same as the MSISDN IE that we already have, so we can use that
instead of creating a new IE (example usage in tests/gsup/gsup_test.c).
Create a new OSMO_GSUP_MSGT_E_ROUTING_ERROR message type, which the GSUP
server uses to tell a client that its message could not be forwarded to
the destination (see [1]). MAP has no related message.
[1]: Change-Id: Ia4f345abc877baaf0a8f73b8988e6514d9589bf5 (osmo-hlr.git)
Related: OS#3774
Change-Id: Ic00b0601eacff6d72927cea51767801142ee75db
osmo-msc and osmo-hlr have distinct subsystems handling incoming GSUP messages.
So far we decide entirely by message type which code path should handle a GSUP
message. Thus no GSUP message type may be re-used across subsystems.
If we add a GSUP message to indicate a routing error, it would have to be a
distinct message type for subscriber management, another one for SMS, another
one for USSD...
To allow introducing common message types, introduce a GSUP Message Class IE.
In the presence of this IE, GSUP handlers can trivially direct a received
message to the right code path. If it is missing, handlers can fall back to the
previous switch(message_type) method.
Change-Id: Ic397a9f2c4a7224e47cab944c72e75ca5592efef
To be able to append an escaped or quoted string using
OSMO_STRBUF_APPEND_NOLEN(), the function signature must have the buf and len as
first args, like most other *_buf() functions.
Add osmo_escape_str_buf2() and osmo_quote_str_buf2() to match this signature.
A recent patch [1] has changed the return value of osmo_escape_str_buf() to
char*, removing the const. However, the functions may return const strings,
hence re-add the const. The new signatures always return the non-const buffer.
To avoid code duplication, implement osmo_quote_str_buf() and
osmo_escape_str_buf() by calling the new functions.
I decided to allow slight changes to the behavior for current osmo_escape_str()
and osmo_escape_str_buf(), because impact on callers is minimal:
(1) The new implementation uses OSMO_STRBUF_*, and in consequence
osmo_quote_str() no longer prints an ending double quote after truncated
strings; Before, a truncated output was, sic:
"this string is trunca"
and now this becomes, sic:
"this string is truncat
I decided to not keep the old behavior because it is questionable to begin
with. It looks like the string actually ended at the truncation boundary
instead of the reason being not enough space in the output buffer.
(2) The new osmo_escape_str_buf2() function obviously cannot pass-thru an
unchanged char* if no escaping was needed. Sacrifice this tiny optimization
feature to avoid code duplication:
- it is an unnoticeable optimization,
- the caller anyway always passes a string buffer,
- the feature caused handling strings and buffers differently depending on
their content (i.e. code that usually writes out strings in full length
"suddenly" truncates because a non-printable character is contained, etc.)
I considered adding a skip_if_unescaped flag to the osmo_quote_str_buf2()
function signature, but in the end decided that the API clutter is not worth
having for all the above reasons.
Adjust tests to accomodate above changes.
[1] 4a62eda225
Ibf85f79e93244f53b2684ff6f1095c5b41203e05
Change-Id: Id748b906b0083b1f1887f2be7a53cae705a8a9ae
In OSMO_STRBUF_APPEND, use local variable names that are less likely to shadow
other local variables: prefix with _sb_.
In OSMO_STRBUF_APPEND, add a check to add to .pos only if it is not NULL.
Add OSMO_STRBUF_APPEND_NOLEN(), which works for function signatures that don't
return a length. This is useful for any osmo_*_buf() string writing functions,
so that these write directly to the strbuf.
Change-Id: I108cadf72deb3a3bcab9a07e50572d9da1ab0359
Move from a static implementation in tdef_vty.c to utils.c, I also want to use
this in osmo-msc.
The point is that the telnet VTY allows unambiguous partly matches of keyword
args. For example, if I have a command definition of:
compare (apples|oranges)
then it is perfectly legal as for the vty parser to write only
compare app
One could expect the VTY to then pass the unambiguous match of "apples" to the
parsing function, but that is not the case.
Hence a VTY function implementation is faced with parsing a keyword of "app"
instead of the expected "apples".
This is actually a very widespread bug in our VTY implementations, which assume
that exactly one full keyword will always be found. I am now writing new
commands in a way that are able to manage only the starts of keywords.
Arguably, strstr(a, b) == a does the same thing, but it searches the entire
string unnecessarily.
Change-Id: Ib2ffb0e9a870dd52e081c7e66d8818057d159513
A separate ST_DESTROYING state originally helped with certain deallocation
scenarios. But now that fsm.c avoids re-entering osmo_fsm_inst_term() twice and
gracefully handles FSM instance deallocations for termination cascades, it is
actually just as safe without a separate ST_DESTROYING state. ST_DESTROYING was
used to flag deallocation and prevent entering osmo_fsm_inst_term() twice,
which works only in a very limited range of scenarios.
Remove ST_DESTROYING from fsm_dealloc_test.c to show that all tested scenarios
still clean up gracefully.
Change-Id: I05354e6cad9b82ba474fa50ffd41d481b3c697b4
Add global flag osmo_fsm_term_safely() -- if set to true, enable the following
behavior:
Detect osmo_fsm_inst_term() occuring within osmo_fsm_inst_term():
- collect deallocations until the outermost osmo_fsm_inst_term() is done.
- call osmo_fsm_inst_free() *after* dispatching the parent event.
If a struct osmo_fsm_inst enters osmo_fsm_inst_term() while another is already
within osmo_fsm_inst_term(), do not directly deallocate it, but talloc-reparent
it to a separate talloc context, to be deallocated with the outermost FSM inst.
The effect is that all osmo_fsm_inst freed within an osmo_fsm_inst_term()
cascade will stay allocated until all osmo_fsm_inst_term() are complete and all
of them will be deallocated at the same time.
Mark the deferred deallocation state as __thread in an attempt to make cascaded
deallocation handling threadsafe. Keep the enable/disable flag separate, so
that it is global and not per-thread.
The feature is showcased by fsm_dealloc_test.c: with this feature, all of those
wild deallocation scenarios succeed.
Make fsm_dealloc_test a normal regression test in testsuite.at.
Rationale:
It is difficult to gracefully handle deallocations of groups of FSM instances
that reference each other. As soon as one child dispatching a cleanup event
causes its parent to deallocate before fsm.c was ready for it, deallocation
will hit a use-after-free. Before this patch, by using parent_term events and
distinct "terminating" FSM states, parent/child FSMs can be taught to wait for
all children to deallocate before deallocating the parent. But as soon as a
non-child / non-parent FSM instance is involved, or actually any other
cleanup() action that triggers parent FSMs or parent talloc contexts to become
unused, it is near impossible to think of all possible deallocation events
ricocheting, and to avoid running into freeing FSM instances that were still in
the middle of osmo_fsm_inst_term(), or FSM instances to enter
osmo_fsm_inst_term() more than once. This patch makes deallocation of "all
possible" setups of complex cross referencing FSM instances easy to handle
correctly, without running into use-after-free or double free situations, and,
notably, without changing calling code.
Change-Id: I8eda67540a1cd444491beb7856b9fcd0a3143b18
To prevent re-entering osmo_fsm_inst_term() twice for the same osmo_fsm_inst,
add flag osmo_fsm_inst.proc.terminating. osmo_fsm_inst_term() sets this to
true, or exits if it already is true.
Update fsm_dealloc_test.err for illustration. It is not relevant for unit
testing yet, just showing the difference.
Change-Id: I0c02d76a86f90c49e0eae2f85db64704c96a7674
Despite efforts to properly handle "GONE" events and entering a ST_DESTROYING
only once, so far this test runs straight into a heap use-after-free. With
current fsm.c, it is hard to resolve the situation with the objects named
"other" also causing deallocations besides the FSM instance parent/child
relations.
For illustration, add an "expected" test output file fsm_dealloc_test.err,
making this pass will follow in a subsequent patch.
Change-Id: If801907c541bca9f524c9e5fd22ac280ca16979a
Provide a common implementation of use counting that supports naming each user
as well as counting more than just one use per user, depending on the rules the
caller implies.
In osmo-msc, we were originally using a simple int counter to see whether a
connection is still in use or should be discarded. For clarity, we later added
names to each user in the form of a bitmask of flags, to figure out exactly
which users are still active: for logging and to debug double get / double put
bugs. This however is still not adequate, since there may be more than one CM
Service Request pending. Also, it is a specialized implementation that is not
re-usable.
With this generalized implementation, we can:
- fix the problem of inadequate counting of multiple concurrent CM Service
Requests (more than one use count per user category),
- directly use arbitrary names for uses like __func__ or "foo" (no need to
define enums and value_string[]s),
- re-use the same code for e.g. vlr_subscr and get fairly detailed VLR
susbscriber usage logging for free.
Change-Id: Ife31e6798b4e728a23913179e346552a7dd338c0
For handling RTP IP addresses and ports, osmo-mgw, osmo-bsc and osmo-msc
so far have their own separate shims and code duplication around
inet_ntoa(), htons(), sockaddr conversions etc. Unify and standardize
with this common API.
In the MGW endpoint FSM that was introduced in osmo-bsc and which I
would like to re-use for osmo-msc (upcoming patch moving that to
osmo-mgw), it has turned out that using char* IP address and uint16_t
port number types are a convenient common denominator for logging,
MGCP message composition and GSM48. Ongoing osmo-msc work also uses this
for MNCC.
This is of course potentially useful for any other IP+port combinations
besides RTP stream handling.
Needless to say that most current implementations will probably stay
with their current own conversion code for a long time; for current
osmo-{bsc,msc,mgw} work (MGW endpoint FSM) though, I would like to move
to this API here.
Change-Id: Id617265337f09dfb6ddfe111ef5e578cd3dc9f63
osmo_escape_str_buf() used to have the somewhat odd semantics that
if no escaping was needed, it would return the original pointer without
making any copy to the output buffer. While this seems like an elegant
optimization, it is a very strange behavior and it works differently
than all of our other *_buf() functions. Let's unify the API and
turn osmo_escape_str_buf() into a strlcpy() if no escaping is needed.
Change-Id: I3a02bdb27008a73101c2db41ac04248960ed4064
This ensures that the rpath of the generated binaries is set to
use only the just-compiled libosmo{core,gsm,vty}.so and not any
system-wide installed libraries while avoiding the ugly shell script
wrapper.
Change-Id: I9b9ae0ed277ba71519661a66a70b7f86971e4511
The function gsm0808_sc_cfg_from_gsm48_mr_cfg() is used to convert a
gsm48 multirate struct into a set of S-bits (S0 to S15). However, the
conversion function currently does not take into account that bit S1
actually stands for four rates at once (Config-NB-Code = 1). Lets make
sure that S1 is only set when the multirate configuration permits all
four required rates.
Change-Id: I6ad531d4e70c2252e32e2bbaca8e14a7ec6d9840
Related: SYS#4470
The function gsm0808_sc_cfg_from_gsm48_mr_cfg() takes an S15 to S0
bitmask and converts that bitmask into an AMR multirate configuration
struct.
Unfortunately the current implementation implements 3GPP TS 28.062,
Table 7.11.3.1.3-2 wrongly in some aspects. Lets fix this.
- Fix wrong interpretation of the bitpatterns
- 5,15K is invalid and must never be selected
- Make sure that no more than 4 rates are selected in the active set
- Extend unit-test
Change-Id: I6fd7f4073b84093742c322752f2fd878d1071e15
Related: SYS#4470
CGI to Cell ID: for example, for Paging, osmo-msc has a CGI for a subscriber
and needs to send out a Cell Identifier IE. Makes sense to add this conversion
here.
Cell ID to CGI: for a Layer 3 Complete, a subscriber sends the current cell in
the form of a Cell Identifier, which we store as a CGI, if necessary enriched
with the local PLMN.
Add enum with bitmask values to identify parts of a CGI, for the return value
of gsm0808_cell_id_to_cgi(). Can't use enum CELL_IDENT for that, because it
doesn't have a value for just a PLMN (and is not a bitmask).
Change-Id: Ib9af67b100c4583342a2103669732dab2e577b04
During FSM design for osmo-msc, I noticed that the current behavior that
keep_timer=true doesn't guarantee a running timer can make FSM design a bit
complex, especially when using osmo_tdef for timeout definitions.
A desirable keep_timer=true behavior is one that keeps the previous timer
running, but starts a timer if no timer is running yet.
The simplest example is: a given state repeatedly transitions back to itself,
but wants to set a timeout only on first entering, avoiding to restart the
timeout on re-entering.
Another example is a repeated transition between two or more states, where the
first time we enter this group a timeout should start, but it should not
restart from scratch on every transition.
When using osmo_tdef timeout definitions for this, so far separate meaningless
states have to be introduced that merely set a fixed timeout.
To simplify, add osmo_fsm_inst_state_chg_keep_or_start_timer(), and use this in
osmo_tdef_fsm_inst_state_chg() when both keep_timer == true *and* T != 0.
In tdef_test.ok, the changes show that on first entering state L, the previous
T=1 is now kept with a large remaining timeout. When entering state L from O,
where no timer was running, this time L's T123 is started.
Change-Id: Id647511a4b18e0c4de0e66fb1f35dc9adb9177db
Always call osmo_tdef_fsm_inst_state_chg(), also when no timeout is defined.
When there is no timeout defined for a state, tdef_test.c tries to be smart and
print different output. In that mess, I missed the fact that
osmo_tdef_fsm_inst_state_chg() isn't always called as it should. In the same
mess, the resulting state was never printed until the preceding patch, which
helped to hide this bug.
Change-Id: I1d953d99854422bff8eb32f051e9c6147bc836b6
- Always print the state after a state transition.
This shows that actually state transitions are missing for states that have
no timer defined. This is a bug in tdef_test.c, to be fixed subsequently.
- Instead of total time passed since start, print the individual fake time
intervals. Omit initial useless zero fake time advance.
- Add two more state transitions, back out from and into a state that has no
timeout set.
Change-Id: Icb31af96d37741e256ff07868f3d4f5c48cdda74
fi->T values are int, i.e. can be negative. Do not log them as unsigned, but
define a distinct timer class "Xnnnn" for negative T values: i.e. for T == -1,
print "Timeout of X1" instead of "Timeout of T4294967295".
The negative T timer number space is useful to distinguish freely invented
timers from proper 3GPP defined T numbers. So far I was using numbers like
T993210 or T9999 for invented T, but X1, X2 etc. is a better solution. This way
we can make sure to not accidentally define an invented timer number that
actually collides with a proper 3GPP specified timer number that the author was
not aware of at the time of writing.
Add OSMO_T_FMT and OSMO_T_FMT_ARGS() macros as standardized timer number print
format. Use that in fsm.c, tdef_vty.c, and adjust vty tests accordingly.
Mention the two timer classes in various API docs and VTY online-docs.
Change-Id: I3a59457623da9309fbbda235fe18fadd1636bff6
Check return value of RACH encode/decode functions and fail test on
unexpected results.
Change-Id: I41bfa808e3c064a11152e7ce8ee77a01d38a0744
Related: OS#1854
Add a flag that adds timeout info to osmo_fsm_inst state change logging.
To not affect unit testing, make this an opt-in feature that is disabled by
default -- mostly because osmo_fsm_inst_state_chg_keep_timer() will produce
non-deterministic logging depending on timing (logs remaining time).
Unit tests that don't verify log output and those that use fake time may also
enable this feature. Do so in fsm_test.c.
The idea is that in due course we will add osmo_fsm_log_timeouts(true) calls to
all of our production applications' main() initialization.
Change-Id: I089b81021a1a4ada1205261470da032b82d57872
This function performs sending a NS-ALIVE PDU and starting Tns-Test,
let's use it in all places where we used to do that.
As part of this, also fix a bug where the sendto() return value (number
of bytes sent) would actually propagate up all the way to
gprs_ns_rx_reset() return value, which in turn affects the test results
on stdout.
Change-Id: I4d303117f77fabb74bbb91887b9914a81c2a084a
Add functions to dump LCLS (without GCR) and GCR. Dumping entire struct
results in inconveniently long string hence the separate functions. Both
use talloc functions so they expect caller to take care of providing
proper allocation context and freeing memory.
Change-Id: Ic3609224c8f3282d667e75f68bc20327e36eb9e6