Commit Graph

23 Commits

Author SHA1 Message Date
Harald Welte 544a32f271 Send "BSSMAP CommonID" to tell BSC about the IMSI
We're already sending the RANAP CommonID message to the RNC,
let's do the same using BSSMAP CommonId towards the BSC.  This
way the BSC knows about the IMSI of the served subscriber, which
is very useful for logging/debugging.

Change-Id: I2552736477663adb250c55728093500e8ae83ebb
Closes: OS#2969
Depends: libosmocore.git I353adc1aa72377f7d4b3336d2ff47791fb73d62c
2020-08-17 11:17:41 +00:00
Neels Hofmeyr 46d526a3df use new osmo_mobile_identity API everywhere
Depends: Ic3f969e739654c1e8c387aedeeba5cce07fe2307 (libosmocore)
Change-Id: Idfc8e576e10756aeaacf5569f6178068313eb7ea
2020-06-19 03:58:13 +02:00
Vadim Yanitskiy 3daf0c2786 vlr: remove unused parameter 'log_level' of auth_fsm_start()
We unconditionally use logging level of the parent FSM anyway.
All callers of auth_fsm_start() always pass fi->log_level.

Change-Id: If2fdf2564eb56d3d94ec3800bdcb0aabcad4e48d
2020-01-27 18:21:08 +00:00
Neels Hofmeyr c4628a3ad4 large refactoring: support inter-BSC and inter-MSC Handover
3GPP TS 49.008 '4.3 Roles of MSC-A, MSC-I and MSC-T' defines distinct roles:
- MSC-A is responsible for managing subscribers,
- MSC-I is the gateway to the RAN.
- MSC-T is a second transitory gateway to another RAN during Handover.

After inter-MSC Handover, the MSC-I is handled by a remote MSC instance, while
the original MSC-A retains the responsibility of subscriber management.

MSC-T exists in this patch but is not yet used, since Handover is only prepared
for, not yet implemented.

Facilitate Inter-MSC and inter-BSC Handover by the same internal split of MSC
roles.

Compared to inter-MSC Handover, mere inter-BSC has the obvious simplifications:
- all of MSC-A, MSC-I and MSC-T roles will be served by the same osmo-msc
  instance,
- messages between MSC-A and MSC-{I,T} don't need to be routed via E-interface
  (GSUP),
- no call routing between MSC-A and -I via MNCC necessary.

This is the largest code bomb I have submitted, ever. Out of principle, I
apologize to everyone trying to read this as a whole. Unfortunately, I see no
sense in trying to split this patch into smaller bits. It would be a huge
amount of work to introduce these changes in separate chunks, especially if
each should in turn be useful and pass all test suites. So, unfortunately, we
are stuck with this code bomb.

The following are some details and rationale for this rather huge refactoring:

* separate MSC subscriber management from ran_conn

struct ran_conn is reduced from the pivotal subscriber management entity it has
been so far to a mere storage for an SCCP connection ID and an MSC subscriber
reference.

The new pivotal subscriber management entity is struct msc_a -- struct msub
lists the msc_a, msc_i, msc_t roles, the vast majority of code paths however
use msc_a, since MSC-A is where all the interesting stuff happens.

Before handover, msc_i is an FSM implementation that encodes to the local
ran_conn. After inter-MSC Handover, msc_i is a compatible but different FSM
implementation that instead forwards via/from GSUP. Same goes for the msc_a
struct: if osmo-msc is the MSC-I "RAN proxy" for a remote MSC-A role, the
msc_a->fi is an FSM implementation that merely forwards via/from GSUP.

* New SCCP implementation for RAN access

To be able to forward BSSAP and RANAP messages via the GSUP interface, the
individual message layers need to be cleanly separated. The IuCS implementation
used until now (iu_client from libosmo-ranap) did not provide this level of
separation, and needed a complete rewrite. It was trivial to implement this in
such a way that both BSSAP and RANAP can be handled by the same SCCP code,
hence the new SCCP-RAN layer also replaces BSSAP handling.

sccp_ran.h: struct sccp_ran_inst provides an abstract handler for incoming RAN
connections. A set of callback functions provides implementation specific
details.

* RAN Abstraction (BSSAP vs. RANAP)

The common SCCP implementation did set the theme for the remaining refactoring:
make all other MSC code paths entirely RAN-implementation-agnostic.

ran_infra.c provides data structures that list RAN implementation specifics,
from logging to RAN de-/encoding to SCCP callbacks and timers. A ran_infra
pointer hence allows complete abstraction of RAN implementations:

- managing connected RAN peers (BSC, RNC) in ran_peer.c,
- classifying and de-/encoding RAN PDUs,
- recording connected LACs and cell IDs and sending out Paging requests to
  matching RAN peers.

* RAN RESET now also for RANAP

ran_peer.c absorbs the reset_fsm from a_reset.c; in consequence, RANAP also
supports proper RESET semantics now. Hence osmo-hnbgw now also needs to provide
proper RESET handling, which it so far duly ignores. (TODO)

* RAN de-/encoding abstraction

The RAN abstraction mentioned above serves not only to separate RANAP and BSSAP
implementations transparently, but also to be able to optionally handle RAN on
distinct levels. Before Handover, all RAN messages are handled by the MSC-A
role.  However, after an inter-MSC Handover, a standalone MSC-I will need to
decode RAN PDUs, at least in order to manage Assignment of RTP streams between
BSS/RNC and MNCC call forwarding.

ran_msg.h provides a common API with abstraction for:

- receiving events from RAN, i.e. passing RAN decode from the BSC/RNC and
  MS/UE: struct ran_dec_msg represents RAN messages decoded from either BSSMAP
  or RANAP;
- sending RAN events: ran_enc_msg is the counterpart to compose RAN messages
  that should be encoded to either BSSMAP or RANAP and passed down to the
  BSC/RNC and MS/UE.

The RAN-specific implementations are completely contained by ran_msg_a.c and
ran_msg_iu.c.

In particular, Assignment and Ciphering have so far been distinct code paths
for BSSAP and RANAP, with switch(via_ran){...} statements all over the place.
Using RAN_DEC_* and RAN_ENC_* abstractions, these are now completely unified.

Note that SGs does not qualify for RAN abstraction: the SGs interface always
remains with the MSC-A role, and SGs messages follow quite distinct semantics
from the fairly similar GERAN and UTRAN.

* MGW and RTP stream management

So far, managing MGW endpoints via MGCP was tightly glued in-between
GSM-04.08-CC on the one and MNCC on the other side. Prepare for switching RTP
streams between different RAN peers by moving to object-oriented
implementations: implement struct call_leg and struct rtp_stream with distinct
FSMs each. For MGW communication, use the osmo_mgcpc_ep API that has originated
from osmo-bsc and recently moved to libosmo-mgcp-client for this purpose.
Instead of implementing a sequence of events with code duplication for the RAN
and CN sides, the idea is to manage each RTP stream separately by firing and
receiving events as soon as codecs and RTP ports are negotiated, and letting
the individual FSMs take care of the MGW management "asynchronously". The
caller provides event IDs and an FSM instance that should be notified of RTP
stream setup progress. Hence it becomes possible to reconnect RTP streams from
one GSM-04.08-CC to another (inter-BSC Handover) or between CC and MNCC RTP
peers (inter-MSC Handover) without duplicating the MGCP code for each
transition.

The number of FSM implementations used for MGCP handling may seem a bit of an
overkill. But in fact, the number of perspectives on RTP forwarding are far
from trivial:
- an MGW endpoint is an entity with N connections, and MGCP "sessions" for
  configuring them by talking to the MGW;
- an RTP stream is a remote peer connected to one of the endpoint's
  connections, which is asynchronously notified of codec and RTP port choices;
- a call leg is the higher level view on either an MT or MO side of a voice
  call, a combination of two RTP streams to forward between two remote peers.

  BSC                 MGW                PBX
                CI          CI
                [MGW-endpoint]
  [--rtp_stream--]          [--rtp_stream--]
  [----------------call_leg----------------]

* Use counts

Introduce using the new osmo_use_count API added to libosmocore for this
purpose. Each use token has a distinct name in the logging, which can be a
globally constant name or ad-hoc, like the local __func__ string constant.  Use
in the new struct msc_a, as well as change vlr_subscr to the new osmo_use_count
API.

* FSM Timeouts

Introduce using the new osmo_tdef API, which provides a common VTY
implementation for all timer numbers, and FSM state transitions with the
correct timeout. Originated in osmo-bsc, recently moved to libosmocore.

Depends: Ife31e6798b4e728a23913179e346552a7dd338c0 (libosmocore)
         Ib9af67b100c4583342a2103669732dab2e577b04 (libosmocore)
	 Id617265337f09dfb6ddfe111ef5e578cd3dc9f63 (libosmocore)
	 Ie9e2add7bbfae651c04e230d62e37cebeb91b0f5 (libosmo-sccp)
	 I26be5c4b06a680f25f19797407ab56a5a4880ddc (osmo-mgw)
	 Ida0e59f9a1f2dd18efea0a51680a67b69f141efa (osmo-mgw)
	 I9a3effd38e72841529df6c135c077116981dea36 (osmo-mgw)
Change-Id: I27e4988e0371808b512c757d2b52ada1615067bd
2019-05-08 17:02:32 +02:00
Neels Hofmeyr 5b1e0309b5 fix various missing line endings in logging
Change-Id: I013eb0eeb5673c06034465020e5dc5230f45ddf5
2019-05-06 23:45:28 +02:00
Neels Hofmeyr 7c5346cd70 vlr_subscr: use osmo_use_count
Depends: Ife31e6798b4e728a23913179e346552a7dd338c0 (libosmocore)
Change-Id: Ib06d030e8464abe415ff597d462ed40eeddef475
2019-04-12 02:15:25 +02:00
Sylvain Munaut da9f37ed20 libvlr: Allow 2G auth tuples to be re-used without going through AUTH
If the key_seq we get in the first messages matches the last_tuple, then
both we and the MS already know the key to use and we don't need the
AUTH REQUEST/RESPONSE cycle.

Security wise ... not so good, and so IMHO the 'auth required' option
in the MSC should always be set. But this allows to turn on ciphering on
a channel without doing any MM transaction, and so the MS doesn't turn
on the T3240 timer which allows to have a ciphered silent-call channel
that won't timeout.

Change-Id: Ief840a2ae7a0ffd2bf0bf726f209a79e3f787646
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2019-03-19 15:24:01 +00:00
Neels Hofmeyr 1035d90c17 fix vlr ops.subscr_assoc re-association
In rare cases, a conn is already associated with a subscriber. So far, we
abort()ed on that, bringing the entire osmo-msc down. Rather log an error and
keep the service running.

In vlr.ops.subscr_assoc, add success/failure return value, and abort the
LU/PARQ on error.

I haven't figured out in detail yet why/how a subscriber would re-launch a
LU/PARQ on a conn that is already associated, so far it is merely clear that we
do not want to crash the MSC if that happens. A log is in OS#3742.

Related: OS#3742, OS#3743
Change-Id: Ic0d54644bc735700220b1ef3a4384c217d57d20f
2019-01-04 01:46:46 +00:00
Neels Hofmeyr fa391ee86c vlr_access_req_fsm.c: use osmo_strlcpy and avoid compiler error
gcc 8.1.0:
../../../../src/osmo-msc/src/libvlr/vlr_access_req_fsm.c:679:3: error: ‘strncpy’ output may be truncated copying 15 bytes from a string of length 31 [-Werror=stringop-truncation]
   strncpy(par->imsi, mi_string, sizeof(par->imsi)-1);
   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The Mobile Identity is a union of various kinds, but the IMSI is at most 15
digits, so truncation is "intended". I hope other layers validate the correct
length of an IMSI MI.

Change-Id: I0a17a188fc91e42e252ae4bf1d6cd0bf0e5eb077
2018-07-26 20:31:55 +02:00
Philipp Maier 6f4752e00c vlr_access_req_fsm: use correct cause codes
The FSM that controls the VLR ACCESS uses cause code 9
(GSM48_REJECT_MS_IDENTITY_NOT_DERVIVABLE) to signal that the
identity of the MS is currently not known in VLR (MSC-Reboot)
However, this cause code is from the GMM domain and is interpreted
as GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER by the MS, which cauese
the MS not to make a new LOCATION UPDATE on CM SERVICE REQUEST

- use GSM48_REJECT_IMSI_UNKNOWN_IN_VLR and
  GSM48_REJECT_IMSI_UNKNOWN_IN_VLR instead of
  GSM48_REJECT_IMSI_UNKNOWN_IN_VLR

Change-Id: Ic058c93387f9be9af4940f8961839c02b93ee370
Closes: OS#3266
2018-05-16 10:34:16 +02:00
Neels Hofmeyr 158095960b refactor VLR FSM result handling
Instead of keeping separate enums for FSM results and translating between those
and the actual 04.08 reject causes that will ultimately reach the MS, just pass
enum gsm48_reject_value cause codes around everywhere.

Collapse some VLR *_timeout() and *_cancel() api to just *_cancel() with a
gsm48 cause arg.

(Hopefully) improve a few reject causes, but otherwise just aim for more
transparent decisions on which cause value is used, for future fixes of
returned causes.

Depends: I6661f139e68a498fb1bef10c266c2f064b72774a (libosmocore)
Change-Id: I27bf8d68737ff1f8dc6d11fb1eac3d391aab0cb1
2018-04-12 19:40:00 +00:00
Neels Hofmeyr fa10eda6d7 vlr_ciph_result: fix use after free of imeisv
Define the struct vlr_ciph_result member .imeisv not as a char* but a char[] of
appropriate length, to avoid the need to point to external memory.

Thus fix a use-after-free in msc_cipher_mode_compl(), which defined the
imeisv[] buffer in a sub-scope within that function, so that the .imeisv
pointer was already invalid when fed to vlr_subscr_rx_ciph_res().

Did you notice that the commit summary rhymes?

Closes: OS#3053
Change-Id: I90cfb952a7dec6d104200872164ebadb25d0260d
2018-03-13 01:29:04 +01:00
Neels Hofmeyr 7795a19ced vlr: fix GSM AKA in a UMTS AKA capable environment
Switch by vsub->sec_ctx to use the proper Kc for ciphering.

Even on an R99 capable MS with a UMTS AKA capable USIM, the MS may still choose
to only perform GSM AKA, as long as the bearer is GERAN. The VLR already stores
whether the MS replied with a GSM AKA SRES or a UMTS AKA RES in vsub->sec_ctx.
So far, though, we were always using the UMTS AKA Kc just because the USIM and
core net are capable of it, ignoring the choice the MS might have made in the
Authentication Response.

In msc_vlr_test_gsm_ciph, fix the test expectations to the correct GSM AKA Kc
keys, showing that all of LU, CM Service Request and Paging Response now
support MS choosing GSM AKA in a UMTS capable environment.

Related: OS#2793
Change-Id: I42ce51ae979f42d173a45ae69273071c426bf97c
2018-03-10 20:58:24 +00:00
Harald Welte 71c51df07d Shift ciphering algorithm selection from VLR to MSC
The VLR code seems to have the assumption that there is one particular
algorithm to be used, as opposed to one of a set of algorithms.

What's missing is basically to decide when/where to pick the best
algorithm within the capabilities of the phone (classmark) and the
network configuration (net->a5_encryption_mask).  So far, libvlr has no
notion of classmark.  Rather, libmsc has.

Why does the VLR care about the particular algorithm at all?  The VLR
should probably simply decide if it should use encryption or not, and if
so, the MSC will figure which algorithm to use.

Change-Id: I5ed80ca2086560a5975a758ec568a034a9a8ab89
2018-01-28 00:09:41 +00:00
Neels Hofmeyr 2ef2da54ab cosmetic prep: tell vlr_ops.set_ciph_mode() whether UMTS AKA is used
In case of UMTS AKA, the Kc for ciphering must be derived from the 3G auth
tokens. tuple->vec.kc was calculated from the GSM algorithm and is not
necessarily a match for the UMTS AKA tokens.

To decide (in an upcoming patch) whether to use UMTS AKA derived Kc or the Kc
from the auth vector, the set_ciph_mode() from vlr_ops needs to know whether
UMTS AKA is being used. This could possibly derived from the msc_conn_ref, but
all flags are already available in the vlr_lu_fsm and vlr_access_req_fsm. Hence
add a umts_aka flag to the set_ciph_mode() callback invocation. The VLR FSMs
thus decide whether UMTS AKA or GSM AKA is to be used during Ciphering Mode
Command, which makes more sense than re-implementing the same decision process
in the MSC.

I considered placing the Kc derivation in vlr_set_ciph_mode() and only tell the
MSC's set_ciph_mode() implementation the precise keys it should use, but the
RAN particulars, and whether a Kc is used at all, rather belong with the MSC.

Related: OS#2745
Prepares: If04e405426c55a81341747a9b450a69188525d5c
Change-Id: I983c48347faf4ee1b405d8174b4e006c904157cf
2017-12-18 05:18:11 +01:00
Neels Hofmeyr 1a5bcd5c3b sub_pres_vlr_fsm_start: fix heap use after free
When sub_pres_vlr_fsm_start() is called, it dispatches an event which may in
some cases already cause tear down and free of the parent FSM instance, after
which storing the returned instance pointer in that parent's metadata will use
freed memory. Instead, pass the target pointer to remember the instance at to
sub_pres_vlr_fsm_start() and assign the pointer *before* firing the event.

Explain so in a new comment.

I haven't checked whether that pointer is actually used at all -- this is the
easiest way to fix the use-after-free without getting sucked into semantic
questions.

Change-Id: Ibdc0b64cd12ba3e2b9737e3517d8484e67abcf04
2017-11-20 13:49:32 +00:00
Max 43b01b0514 Remove rest_octets.h
The MSC should not fiddle with low-level SI details like rest octets
anyway. Unfortunately simply removing the header is impossible as it
causes massive fallout due to missing includes. Fixed it as well.

The only other parameter which required removal is cell_ro_sel_par which
is not referenced anywhere in the code anyway.

Change-Id: Ibff77330de056fad4288cd4c48d016aad8105354
2017-09-15 11:31:03 +02:00
Neels Hofmeyr 9084396467 rename include/openbsc to include/osmocom/msc
Change-Id: I1f96a1285bbd1b4607614856bca935d5c26e2da9
2017-09-06 16:41:25 +02:00
Neels Hofmeyr 84da6b1edb Implement IuCS (large refactoring and addition)
osmo-nitb becomes osmo-msc
add DIUCS debug log constant
add iucs.[hc]
add msc vty, remove nitb vty
add libiudummy, to avoid linking Iu deps in tests
Use new msc_tx_dtap() instead of gsm0808_submit_dtap()
libmgcp: add mgcpgw client API
bridge calls via mgcpgw

Enable MSC specific CTRL commands, bsc_base_ctrl_cmds_install() still needs to
be split up.

Change-Id: I5b5b6a9678b458affa86800afb1ec726e66eed88
2017-08-08 19:17:53 +02:00
Neels Hofmeyr 54a706cf92 vlr: LU FSM: enable Retrieve_IMEISV_If_Required
Change-Id: I121b95ad6d5ecb7603815eece2b43008de487a8a
2017-08-07 16:52:25 +02:00
Neels Hofmeyr ef9126c4dc vlr: place comments on if (0) cases
Change-Id: I56c1e61dedeac01a4e24452feee6616782783d8f
2017-08-07 16:52:23 +02:00
Harald Welte 2483f1b050 Use libvlr in libmsc (large refactoring)
Original libvlr code is by Harald Welte <laforge@gnumonks.org>,
polished and tweaked by Neels Hofmeyr <nhofmeyr@sysmocom.de>.

This is a long series of trial-and-error development collapsed in one patch.
This may be split in smaller commits if reviewers prefer that. If we can keep
it as one, we have saved ourselves the additional separation work.

SMS:

The SQL based lookup of SMS for attached subscribers no longer works since the
SQL database no longer has the subscriber data. Replace with a round-robin on
the SMS recipient MSISDNs paired with a VLR subscriber RAM lookup whether the
subscriber is currently attached.

If there are many SMS for not-attached subscribers in the SMS database, this
will become inefficient: a DB hit returns a pending SMS, the RAM lookup will
reveal that the subscriber is not attached, after which the DB is hit for the
next SMS. It would become more efficient e.g. by having an MSISDN based hash
list for the VLR subscribers and by marking non-attached SMS recipients in the
SMS database so that they can be excluded with the SQL query already.

There is a sanity limit to do at most 100 db hits per attempt to find a pending
SMS. So if there are more than 100 stored SMS waiting for their recipients to
actually attach to the MSC, it may take more than one SMS queue trigger to
deliver SMS for subscribers that are actually attached.

This is not very beautiful, but is merely intended to carry us over to a time
when we have a proper separate SMSC entity.

Introduce gsm_subscriber_connection ref-counting in libmsc.

Remove/Disable VTY and CTRL commands to create subscribers, which is now a task
of the OsmoHLR. Adjust the python tests accordingly.

Remove VTY cmd subscriber-keep-in-ram.

Use OSMO_GSUP_PORT = 4222 instead of 2222. See
I4222e21686c823985be8ff1f16b1182be8ad6175.

So far use the LAC from conn->bts, will be replaced by conn->lac in
Id3705236350d5f69e447046b0a764bbabc3d493c.

Related: OS#1592 OS#1974
Change-Id: I639544a6cdda77a3aafc4e3446a55393f60e4050
2017-07-23 04:08:43 +02:00
Harald Welte b8b85a1b2e Add libvlr implementation
Original libvlr code is by Harald Welte <laforge@gnumonks.org>,
polished and tweaked by Neels Hofmeyr <nhofmeyr@sysmocom.de>.

This is a long series of trial-and-error development collapsed in one patch.
This may be split in smaller commits if reviewers prefer that. If we can keep
it as one, we have saved ourselves the additional separation work.

Related: OS#1592
Change-Id: Ie303c98f8c18e40c87c1b68474b35de332033622
2017-07-21 18:32:03 +02:00