Move the call to send_gsmtap() before the call to decode_gsm_rlcmac_uplink() as if
the latter returns error we return and never get to see the packet on the GSMTAP.
Change-Id: Ia6af9f40590f28fcae3fef50d9c601d8435412cd
The main idea of this change is to demonstrate a weakness of the
CSN.1 codec that most likely causes a unit test breakage in [1].
The problem seems to be that the transitional structures, where
the CSN.1 decoder stores the results, do not contain any details
about presence of the optional fields (such as M_UINT_OR_NULL).
In other words, it's impossible to know whether some optional
field is omitted in the encoded message (NULL), or is it just
set to 0. This means that the encoder will always include all
optional fields, even if they're not present in the original
message.
[1] Ibb4cbd3f5865415fd547e95fc24ff31df1aed4c0
Change-Id: Ic46d6e56768f516203d27d8e7a5adb77afdf32b7
As seen in OS#4420, setting the MetaInfo.recv_time outside of
llc_queue before calling llc_queue::enqueue() and later on using that
value in llc_queue itself at dequeue time is not a good idea, since it
can provoke errors if the recv_time was not set correctly.
For instance, LlcTest was not setting the value for recv_time on some
test, which ended up with a huge millisec value when substracting now()
from it:
"""
llc.cpp:215:29: runtime error: signed integer overflow: 1582738663 * 1000 cannot be represented in type 'long int'
"""
This issue only appeared when started building on a raspberrypi4.
Let's better set/store the MetaInfo.recv_time internally during
llc_queue::enqueue(). Then, enqueue() only needs the
MetaInfo.expire_time, so let's change its arg list to only receive that
to avoid confusions.
Take the chance to move the llc_queue APIs to use osmo_gettimeofday,
since we need to fake the time now that the API itself sets that time.
Also take the chance during this refactor to disallow passing null
pointer by default since no user needs that.
Finally, update the LlcTest accordingly with all API/behavior changes.
Related: OS#4420
Change-Id: Ief6b1464dc779ff22adc2b02da7a006cd772ebce
Long story short: as it turns out the test vector '12a5146200'O
has been generated by TITAN, and it's malformed. The length
indicator it contains must be at least 29 bits, not 21. This
field is calculated by TITAN automatically, so I guess there
is a bug somewhere in its RAW encoder implementation.
It's funny that Wireshark decodes the old malformed vector without
any problems if it's encapsulated into the BSSGP DL-UNITDATA. The
reason for that is because BSSGP dissector does not actually use
the CSN.1 codec and relies on its own hand-written parser [1],
which does not respect the length constraints.
Furthermore, table 10.5.146/3GPP TS 24.008, describing the format
of MS Radio Access Capability IE, has the following comment:
< Multislot capability struct > ::=
{ 0 | 1 < HSCSD multislot class : bit (5) > }
...
-- error: struct too short, assume features do not exist
so ideally our CSN.1 decoder should be more tolerant to the old
malformed vector, but unfortunately error handling is not implemented.
[1] See de_gmm_ms_radio_acc_cap() in epan/dissectors/packet-gsm_a_gm.c.
Change-Id: I5f810397b8d09c18e069168023429f6a4d899c86
Found while doing differential analysis (comparison against the
original implementation from Wireshark).
Change-Id: Ibd0b7400d78f7873c2a8d45267332f511b5c6fbb
Found while doing differential analysis (comparison against the
original implementation from Wireshark).
Change-Id: I9f7fa9c3f2f4ff5213dded930cee7ec509b9d799
Found while doing differential analysis (comparison against the
original implementation from Wireshark).
Change-Id: Id2a4f03035cd8354d3fba0ad37571453d3986d21
The implementation of CSN.1 codec was taken from Wireshark, where
it's implemented in pure C. For some reason it was mixed with C++
specific features, mostly using references in parameter
declaration. Not sure what are the benefits.
Change-Id: I56d8b7fbd2f9f4e0bdd6b09d0366fe7eb7aa327a
This would allow us to catch more bugs. Note that I had to remove
printing of pointer address to make the output deterministic.
Change-Id: I1a77441eb957353c919bc73f8e3a2e38f4a383a9
As was discovered recently (see OS#4388), bitvec_read_field()
would never return a negative value because its return type
is unsigned (uint64_t).
We don't really need to get more than one bit, so let's just
use the bitvec_get_bit_pos() instead.
Change-Id: I763a295cd955cd33f542292c85d97ff82f6b49bc
Related: OS#4388
It contails no valid identity, and thus violates the specs.
Let's keep it 'as-is' to check that decoder actually fails.
Change-Id: I663edfdaac0c065e08ab7b6dc50d2f18e433433c
Related: OS#4392
After the recent changes [1], it was noticed that one of the unit
tests fails. In particular, a decode-encode cycle of Packet
Polling Request produces a different vector:
vector1 = 49 13 e0 08 50 88 40 13 a8 04 8b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
vector2 = 49 13 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
vector1 == vector2 : FALSE
As it turns out, the original (input) vector itself is malformed
because it contails no valid identity, and thus violates the
specs. The CSN.1 decoder from Pycrate [2] throws an exception
while trying to decode it. I believe we should do the same.
Let's stop decoding the bit stream and return an error in case
if neither of a given list of the choice items matched.
[1] Ia0f8cc224a4c38e80699f834fd83d4c0d99322ea
[2] https://github.com/P1sec/pycrate
Change-Id: I420144773ed5e80372534e0f18db5e74cdb2999d
Fixes: OS#4392
The problem is that bitvec_free() is not NULL-safe. Ideally we
need to fix it in libosmocore [1], but let's also fix it here,
so OsmoPCU can be safely used with older libosmocore versions.
[1] https://gerrit.osmocom.org/c/libosmocore/+/17114
Change-Id: I7647d17b3d03f8e193ef6e793a2d3c1967744eef
Fixes: CID#208181, CID#208179
Output was incorrect before this patch. LOPC was being called without
having any initial LOGP, and trailing newline was usually missing at the
end.
Since csnDecoder/encoder functions are recursive, it's difficult to
handle logging state in a coherent way inside them. Let's better simply
control start/end of logging related topics in the callers of those
functions, and simply use LOGPC everywhere in csn1.cpp.
Change-Id: I50da7560939fac360b7545e2a6bfaf45ed0c4832
It was noticed that OsmoPCU leaks memory when trying to reconnect
to the BTS. It could be easily fixed, but we don't really need to
allocate the PCU socket state on heap as we never have more than
one connection.
Change-Id: Iea8930f443caa16f522f7c5375e0004e4e2315cb
Since I2b32b4fe20732728db6e9cdac7e484d96ab86dc5, go_parent_cb()
is completely optional. It no longer has the task to determine
the correct parent node. The is_config_node() callback is no
longer needed too. Get rid of them.
Since Ic5e69a396df659933fd4d50298b9925e837a6861 we depend on 1.3.0.
Change-Id: Id7ce8c4e1ac43747ad40a06d01433c366da07b42
As was discovered by pespin, changing logging level of DCSN1 makes
the CSN.1 decoder behave differently (see OS#4375). In particular,
this makes RLCMACTest (encode / decode test) fail.
I did a quick investigation and noticed that some of the logging
statements call bitvec_read_field(). By definition this function
moves the internal pointer (current bit position) of a given
vector and increments readIndex by a given amount of bits.
The problem is that LOGPC would not evaluate its format string if
the logging message is not going to be printed, e.g. if a given
logging level is lower than the current one, or in case if
logging is not enabled at all.
The first two conditional calls to bitvec_read_field() are related
to CSN_PADDING_BITS, so that's not critical because padding is
always in the end of messages. The later two are related to
CSN_RECURSIVE_ARRAY and CSN_RECURSIVE_TARRAY respectively.
Let's use bitvec_get_uint() instead to keep readIndex unchanged.
Change-Id: Ia331048db9f790ca407fd341ced01df12d10a233
Fixes: OS#4375
Same API is kept to more easily keep code compatibility with wireshark's
packet-csn1.c implementation.
Change-Id: I1ce2c52e2357841aa1f31babfdce9011435f866b
The 'gprs_llc' is defined as a pure C structure with C++ specific
extensions (methods), so it's rather a class. Accessing its field
'frame' statically causes Clang to throw a compilation error:
gprs_bssgp_pcu.cpp:111:29: error: invalid use of non-static data member 'frame'
if (len > sizeof(gprs_llc::frame))
Let's avoid this and use LLC_MAX_LEN as the size limitation.
God knows what to expect from such a mix of C++ and C...
Change-Id: I7f84bd776cc780a45880f136107f6e0bc56241d1
Looks pretty much like a typo. Both '-1' and '.' symbols are
neighbours in QWERTZ keyboard layout, so it must be -1.
Found by Clang [-Wliteral-conversion].
Change-Id: Id4eb2dcc3b44e18096c7b94efb7260e2400c596b
This is rather a cosmetic change aimed to make ASAN / Coverity happy.
In general, we never pass any input from an untrusted source.
Change-Id: I26d654da4c3bf5fd86a298c3027fd9820c932308
It does not make sense since INT_MAX is always less than LONG_MAX.
Found by Clang [-Wtautological-constant-out-of-range-compare].
Change-Id: I9934e05aa050bf93b3c795376f5dca3a848a7e11
(as they are part of the RlcMacUplink_t structure that is also used to call csnStreamDissector function).
Port from wireshark.git commit 9f8b638cfa8a660fb64c54dcadb83e6747db0a15.
Ported-by: Pau Espin Pedrol <pespin@sysmocom.de>
Change-Id: If46f8cc3f21f527f911dcac6ff1b78f182104a00
Port of wireshark.git 8626bb4cbb4d9926f7b56663585d9ef66252f93f.
We don't really need the other fields added there, let's keep only the
value out of the union.
Change-Id: Ia8889252ee7518a919a15d749815c2803b4b23cd