Remove the paragraph about writing to the Free Software Foundation's
mailing address. The FSF has changed addresses in the past, and may do
so again. In 2021 this is not useful, let's rather have a bit less
boilerplate at the start of source files.
Change-Id: I5050285e75cf120407a1d883e99b3c4bcae8ffd7
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
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
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
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
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
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
The IMEI-SV is speified as a 16 digit number: 14 digits of IMEI plus
two digits of software version. Let's not try to feed 18 digit long
numbers into our functions, as the resulting behavior is unspecified.
Change-Id: I6fb85a0516dc387902ad9de4fe8c1ba82d68cae6
As part of fixing issue OS#3075, we want to migrate support
for encoding system information from osmo-bsc to libosmocore.
This change ports one of the prerequisites for doing so:
osmo-bsc code for range-encoding ARFCNs, including tests.
An osmo_gsm48_ prefix has been prepended to public symbols in
order to avoid clashes with existing symbols in osmo-bsc code.
Change-Id: Ia220764fba451be5e975ae7c5eefb1a25ac2bf2c
Related: OS#3075
We have gsm48_mi_to_string() and osmo_bcd2str(), but still lack a function that
conveniently prints both MI type and value in one function call.
Related: http://people.osmocom.org/neels/mi_mi_mi.jpg
Change-Id: I7798c3ef983c2e333b2b9cbffef6f366f370bd81
All successful cases already return from the switch(), so simply handle all
errors below it by returning an empty string (if there is enough string
buffer).
Change-Id: I709ac3b9efb7b4258d8660715b10312e11b9b571
For MI encoding, see 3GPP TS 24.008, 10.5.1.4 Mobile Identity. The 'odd' flag
indicates whether the last BCD nibble is used. Of course that flag should be
made sure to reflect the actual length.
Change-Id: Id6e695ebf9f86b295eaa7e2c6228989256f37e68
By using osmo_bcd2str(), ensure that the resulting string is always nul
terminated, and always return strlen()+1 whether truncated or not.
Still keep up the previous return value style, even if that isn't consistent at
all.
The difference between IMSI/IMEI and TMSI return values remains and is not part
of this patch.
Change-Id: I1b51b72a721e1cc9d69796b804ebda741ff0f36b
One would think by now we would solidly encode and decode Mobile Identities.
Well, guess again.
- rc is sometimes the amount of bytes written, sometimes actual strlen().
- on string truncation, rc is sometimes strlen() (assuming nul terminated), and
sometimes snprintf()-style would-be strlen().
- returned string, when truncated by not enough buffer size, is sometimes nul
terminated, sometimes not.
- gsm48_mi_to_string() happily reads a byte from zero-length input buffer.
- gsm48_mi_to_string() happily writes to zero length output buffer.
- gsm48_mi_to_string() returns nonempty string for empty input.
- encoding a MI type that still has the GSM_MI_ODD flag set results in encoding
an even-length MI as odd-length (hence appending a stray 'F').
I am going to tweak the implementation of gsm48 mobile identity encoding /
decoding, so first pinpoint the current behavior in a unit test, and show how
perforated even such a seemingly trivial API can be.
Change-Id: Iaae3af87f82f1a8f2e6273984c011b2813038cf7
Note that on the input side, the 3-digits flag may be left false when the MNC
is >99 anyway. On the decoded side, the flag is set accurately.
Change-Id: I89765613d8c5bd939a6957f7443ac88475f1b93c
Add gsm48_encode_ra() which takes appropriate struct as [out] parameter
instead of generic buffer. Using uint8_t buffer instead of proper struct
type prooved to be error-prone - see Coverity CID57877, CID57876.
Old gsm48_construct_ra() is made into tiny wrapper around new
function. The test output is adjusted because of the change in function
return value which was constant and hence ignored anyway.
Related: OS#1640
Change-Id: I31f9605277f4945f207c2c44ff82e62399f8db74
Remove initial msgb talloc context creation: if we create a root ctx for msgb
that all msgb are allocated in, we would in a final cleanup discard all msgbs,
i.e. we would not verify that all msgb are cleaned up properly.
If we create the msgb context and *don't* clean it up in the end, the sanitizer
build fails because the context root is not cleaned up.
Easiest is to actually allocate all msgb at NULL ctx, because then any msgb
that aren't cleaned up properly would still linger, while we don't leave a root
ctx that we need to clean up either.
Helps fix sanitizer build on debian 9.
Change-Id: I1f2d1d05c75bbf4d92787f9735083f18cdc90f6f
The &buf[3] is unlikely to be aligned properly. Use memcpy instead
of an assignment. Add a small testcase that verifies that I didn't
mess up the conversion.
Alignment trap: osmo-nitb (3293) PC=0x492b7094 Instr=0xe5803003 Address=0xbeb259db FSR 0x801