Compare commits

...

413 Commits

Author SHA1 Message Date
Pau Espin Pedrol
1fd205f0b8 ranap: Take into account RNC availability during paging
Avoid transmitting a RANAP paging message to an RNC if we already know
it's not currently available over SCCP.
Take into account that information when deciding/printing whether the
paging could be sent or not.

Take the chance to clean up the iu paging function helpers inherited
from osmo-iuh iu_client.c to better fit the data domain in osmo-sgsn
(iu_rnc).

Change-Id: I24e5446bcf4c958028577230b231960acea9e5b9
2025-09-02 18:55:03 +02:00
Pau Espin Pedrol
b062c3647e stats: Introduce stats sgsn.iu_peers.{total,active}
Change-Id: I51b5227d92027f1251dc4debbbf59737e7c1a9ba
2025-09-02 18:55:03 +02:00
Pau Espin Pedrol
d6c29beaf3 Introduce iu_rnc FSM
This FSM is similar to the already existing ran_peer_fsm in osmo-msc,
which already had better logic around SCCP and RANAP state handling.
Similarly, osmo-sgsn's struct ranap_iu_rnc maps to osmo-msc's struct ran_peer.

With this FSM we can currently track the RANAP link state towards a given
RNC peer:
* Reject (RANAP Error Indication) all UE-related messages until a RANAP
  RESET from RNC is received first.
* Tear down all subsriber connections whenever the RANAP peer sends us a
  RESET message.
* Tear down all subscriber connections whenever the SCCP link towards
  RNC becomes unavailable.
* Send a RESET towards RNC peer once the SCCP link towrdards it becomes
  available again.

This commit only implements so far the Rx path of the FSM, ie. when
receiving events/messages from a peer over SCCP and pushing them locally
up the stack (RANAP). The Tx side will be implemented in a follow-up
commit, which will allow discarding messages if the lower layers towards
a given RNC are known to be down.

Related: OS#3403
Change-Id: I18b7803500163e78ff6a684095194174b0fb6ee1
2025-09-02 18:55:03 +02:00
Pau Espin Pedrol
a24ebc7051 iu_rnc: Introduce helper API iu_rnc_discard_all_ue_ctx()
This is a preparation commit to introduce iu_rnc_fsm in follow-up patch.
The helper API will be used whenever the entire RNC is considered reset.

* Code inside handle_notice_ind() is moved to its own function
  iu_rnc_discard_all_ue_ctx().
* Dependent helper ue_ctx_link_invalidated_free() API is properly
  prefixed/renamed to ue_conn_ctx_link_invalidated_free(), where methods
  for ue_conn_ctx object are placed.
* ue_conn_ctx_find() is properly prefixed/renamed to
  sgsn_scu_iups_ue_conn_ctx_find() and made available to functions in
  other files.

Change-Id: Ie3a4732a85a69d115dd5756bfa64b296e9e5edd2
2025-09-02 18:55:02 +02:00
Pau Espin Pedrol
611b32811e Store scu_iups in iu_rnc instead of ue_ctx
All the ue_ctx belong to a given peer RNC, which holds the SCCP User to
talk to it.

Change-Id: I3969af765b7b0d1375b5e6ad8f3f2e9845f939ef
2025-09-02 18:53:17 +02:00
Pau Espin Pedrol
7673bbd7ad ranap: Create iu_rnc upon rx RESET
RANAP RESET, the first message an SGSN usually receives from an RNC,
contain the GlobalRNC-ID we can already use to register the iu_rnc
object.
This allows keeping track of peers since first message, before first
InitialUE message is received.
Once we start tracking peer RNC state within osmo-sgsn (as we already do
in other osmo-* programs), this will be needed.

Change-Id: Iaf31271feb4d88881382ed8594d0d8e20e22b194
2025-09-02 18:51:43 +02:00
Pau Espin Pedrol
b9c9271a1f ranap: Improve error handling in Rx RESET
* Verify the CN Indicator is set to PS to avoid reacting on content from
  unexpected peers (eg. IuCS). If none is set, be permissive on rx and
  assume PS.

* If GlobalRNC-ID IE is missing, reject the RESET with an Error
  Indication towards the peer to notify about the rejection.
  Same if we couldn't decode properly it.

* Introduce Tx helpers for generic SCCP UNITDATA.req and RANAP Error
  Indication helpers to simplify code and avoid duplication.

Depends: osmo-iuh.git Change-Id I58c75b3e0e0f33f48d077385ffac820a6b2be59e
Change-Id: I2a53e10c3903992a42d081e3ec300fbdb9b3c34c
2025-09-02 18:51:43 +02:00
Pau Espin Pedrol
dfcb514076 iu_rnc: Split iu_rnc_register API into 2 steps
Split lookup+allocation from RAI updating.
This will be needed once we start creating iu_rnc objects upon SCCP
rx RANAP RESET messages, which hold Global RNC-ID but no RAI
information.

Change-Id: I3761cc539c63a7ed680b04bb8136a43d397c10aa
2025-09-02 18:51:43 +02:00
Pau Espin Pedrol
009c25f968 ranap: Reject InitialUE without RAC IE
According to 3GPP TS 25.413 clauses 8.22.2 and 9.1.33,
RAC IE is mandatory in PS domain.

Change-Id: I7d6b996ddf1c5a7cde1bf06b500d3ed19c6090c6
2025-09-02 18:51:43 +02:00
Pau Espin Pedrol
202039ed02 iu_rnc: Use API osmo_sccp_addr_ri_cmp() to compare addresses
Change-Id: I04fb37f28b52da9eecb1f8ea40c38ee3eced1c29
2025-09-02 18:51:43 +02:00
Pau Espin Pedrol
ecaa198fa0 Apply uniform prefix to remaining APIs in gprs_ranap.h
Change-Id: I4f253f35013085bdebf80e94ab0d2f771e40dba6
2025-09-02 18:51:43 +02:00
Pau Espin Pedrol
eb5959f6b9 Split Iu RANAP conn release over different layers
Move and rename functions acting on mmctx to mmctx.{c,h}.
From there, call functions acting on ranap ue_ctx.

Change-Id: I4acdbc857df36b7409c8210d364758192dfdb0bb
2025-09-02 18:51:43 +02:00
Pau Espin Pedrol
c1f2de5790 Split Iu RANAP RAB PS act/deact over different layers
Properly separate logic acting on objects vs logic building and
generating RANAP msg on the wire.

Change-Id: I98788468b7e50619cfd99b3aef2311bb601fb6be
2025-09-02 18:51:43 +02:00
Pau Espin Pedrol
a0203ce7ff ranap: Clean up RANAP rx path param passing
Use the osmo-iuh ranap_cn_rx_*_decode2() APIs directly. This
allows getting rid of extra "ctx" temporary structs and another level of
cb indirection.

Take the chance to update most pointers consitfying them.

Depends: osmo-iuh.git Change-Id I667dc2ef377c1ceb5b11315458f00b282c143c81
Change-Id: Ib3c00b5105b7ba4bb1a2dad1a14bea233a03c358
2025-09-02 18:51:43 +02:00
Pau Espin Pedrol
20d032bdd2 iu_rnc: Constify function params
Change-Id: I288bc21d24aa5abd3d9bd97e796ac9f8590290bd
2025-09-02 18:51:43 +02:00
Pau Espin Pedrol
203676d047 sccp: Introduce helper func sgsn_scu_iups_tx_data_req()
This avoid code deduplication plus moving SCCP SAP logic into sccp.c.

Change-Id: Id34f86b4f5e40ddceac4066ec18ebc60529cafab
2025-09-02 18:51:43 +02:00
Pau Espin Pedrol
265bc33b05 Split most of iu_client.{c,h} into sccp.{c,h} and iu_rnc.{c,h}
* iu_rnc is easily spotted as an object class in the data domain which
  can be put into its own file, handling its specific logic and data.

* SCCP code can also be moved into own specific file, which eases
  self-containment of the layer logic and data.

* As a result, lots of RANAP Rx/Tx code in iu_client.{c,h} can also be
  moved to the already existing gprs_ranap.{c,h}.

All these changes improve a lot readibility of code and makes it a lot
easier to improve/extend the different layers/objects in future patches.

Change-Id: I4c792ae665720460b5a954b5c7cbfe5acbc37473
2025-09-02 18:51:08 +02:00
Pau Espin Pedrol
77cf72ea91 Move gsm0408_gprs_rcvmsg_iu to gprs_gmm.{c,h}
It belongs to that layer, same as existing gsm0408_gprs_rcvmsg_gb()
counterpart.

Change-Id: I09c19689fd7016b76ebeee821b551427965b7cf1
2025-08-27 14:44:34 +02:00
Pau Espin Pedrol
ad61ccd07b debug.h: Remove unused log category DIUCS
It's used nowhere, not even defined in the initialization array of
categories, because IuCS has no place in SGSN.

Change-Id: I0f7c6bedaf3b7f909c3e27175ca99967492ab7c3
2025-08-26 17:51:43 +02:00
Alexander Couzens
02fbdb59c2 Re-introduce Iu/UTRAN support
Add support for UTRAN routing areas.

Change-Id: I1b1aedd2a7c358bd388aa3d8a9f3c6a0011b4889
2025-08-21 23:08:52 +02:00
Alexander Couzens
b1444a6c11 [4/4] iu_client: start using adopted iu_client
Use internal headers.
Use renamed event names/types.

Change-Id: I7c99ad0498c6f885361562c54fcf0ebdc086616b
2025-08-21 18:40:49 +02:00
Alexander Couzens
6043666db5 [3/4] iu_client: hide symbols to prevent clashes
Change-Id: Ide2f7767b90501790a5d609222185918da66336b
2025-08-21 18:40:43 +02:00
Alexander Couzens
6534fdbf27 [2/4] iu_client: rename symbols to prevent clashes with libosmo-ranap
While moving the iu_client into osmoSGSN, it's not allowed to have
the same global symbols in the library as in osmoSGSN.

Change-Id: I2af29b38f110b80f69ef598c8e2700ff323a9d7c
2025-08-21 18:10:25 +02:00
Alexander Couzens
2d4fe639cc [1/4] Adopt iu_client from osmo-iuh
iu_client was original written to have an abstraction
for Iu. However the MSC stopped using iu_client a long
time ago because the abstraption didn't fit well.
There was never time to rewrite SGSN to direct talk RANAP
using the primitives.
Adopt iu_client for now, but with the plan to rewrite
it in a similar way as osmo-msc is doing IuCS.

Adopted from osmo-iuh:
1631c8ac5a2f ("iu_client: fix linter issues")
Related: OS#5487

Change-Id: I9c0d9667ddcb57b52eae34da942acfc1688c1418
2025-08-21 18:10:21 +02:00
Alexander Couzens
4ba6638840 routing area: prefix GERAN functions with geran
Make it easier to understand the purpose
of the functions.

Change-Id: Ic616bd8f9afe6cd3702cd4af08706b7b36987f42
2025-08-06 15:00:40 +02:00
Alexander Couzens
bae75b9a60 BSSGP: reset cells when receiving a Reset on Signal BVC
When a PCU sends a BVC Reset over BSSGP on the Signal BVC,
all cells which has been set up previously via PtP BVCs
has to be removed.

They might be introduced after the Signal BVC reset procedure
has finished.

Change-Id: I380c8f9ef90d8c7face5c380d923ab5168f5b484
2025-08-06 14:46:34 +02:00
Alexander Couzens
c156925405 tests: RA: add test for a GERAN cell to change its BVCI
Change-Id: Idcada8364bf62aae2244b92e0d7a43c120c9c0ad
2025-08-01 17:44:33 +02:00
Alexander Couzens
2422c0375b routing area: sgsn_ra_geran_page_ra: make argument rai const
The second argument mmctx can't made const because of the paging info,
which uses non-const fields.

Change-Id: I21d7e66e433f2b891c94bae91697aa46198fb20c
2025-08-01 17:44:33 +02:00
Alexander Couzens
fec2e5884a routing area: add LOGRA() logging macro
Prepend the routing area in the log message.

Change-Id: Ib287b70c34b21ce64bc864f69fcf6af5fa0698b9
2025-08-01 17:44:33 +02:00
Alexander Couzens
4b894f1a85 routing area: introduce sgsn_ra_find_or_create()
If the RA is the same, return the RA, but if the ran type is different,
return NULL instead of allocating a second RA in the other
RAT.

Change-Id: I6955a09d9d8f3ba4dc3a14d7ed5cd9798d929c61
2025-08-01 17:43:57 +02:00
Alexander Couzens
328edfd6f8 routing area: move cell.cell_id behind a geran union
To prepare for Iu support, use the SGSN RA cell for both,
a GERAN Cell and a UTRAN Service Area.

Change-Id: I0c24d98dd699748842dca271b93e58d27cf02285
2025-08-01 14:27:43 +02:00
Alexander Couzens
9eb1f7e006 use variable name rai for struct osmo_routing_area_id
Be consistent with variable naming if a single
`struct osmo_routing_area_id *` area id is used.

Change-Id: I946983d4857035e06c68af378654466b35025014
2025-08-01 14:25:48 +02:00
Alexander Couzens
f34503289e routing area: introduce ran_type on the RA
A Routing Area should be uniquely identified by the RAI.
Following this, it is forbidden to have a RAI which is valid
in both, GERAN and UTRAN.

Change-Id: I59c35f1a4912ff11574bb31e4fe424816993548c
2025-08-01 14:25:16 +02:00
Alexander Couzens
dda9c6780b ranap: split mmctx related iu events into own function
In preparation of Routing Areas for Iu, split
off mmctx related events into an own function.
All mmctx related events must contain a valid ctx or are
otherwise invalid.

Change-Id: Ie6f131d29da299f09e897240ec5c39a395ce6f1b
2025-07-17 11:42:24 +02:00
Alexander Couzens
234da0eed4 mmctx: LOGIUP: allow ue to be NULL
In certain cases, the ue can be NULL.
E.g. when receiving a new Iu event without a context.

Change-Id: Ie569fa100abe518cb63c1b918ad7748a7ea3bb99
2025-07-17 11:41:35 +02:00
Alexander Couzens
b79797d056 gprs_gmm: fix endianess of GSM48_IE_GMM_PDP_CTX_STATUS
The pdp_status is actually encoded as little endian,
but there is no tlvp_val16le yet.

Change-Id: Ib9bee2f8d0b1f89986d15cf3ce6404ad76378c8c
2025-07-14 17:39:22 +02:00
Alexander Couzens
34182d28a4 GMM: implement IMEI SV on auth/ciph response
The SGSN is requesting the IMEI SV on an auth/ciphering response.
Parse the answer of the MS/UE.

Change-Id: Ia8b428967a4ce3132a4a63ae10fe610de81c3a29
2025-02-17 23:13:43 +01:00
Alexander Couzens
901ca02e0e Assign MME GroupId/Code to remote MMEs
In preparation to route SGSN Context Req/Resp/Ack the SGSN
need to route GTP messages based on the MME GroupId and MME Code.

Change-Id: I881aeba904fb6ca815842d36e466a2459ad81913
2025-02-17 23:13:42 +01:00
Alexander Couzens
944b6dfb8d gprs_gmm_util: use a RAU specific TLV dictionary
Limit the known and allowed TLVs according to the spec.

Change-Id: I460971deeebc9977a984937c542b263d941e78df
2025-01-31 16:44:58 +01:00
Alexander Couzens
27dd6d84ec gprs_gmm_util: add parsing of GMM Attach Requests
This will be used in the following commit.

Change-Id: I4a82e0c4070da982efd6c2f15fd145393423772b
2025-01-31 16:43:43 +01:00
Alexander Couzens
028c299bb2 Add include prefix for all libgtp related includes
The libgtp includes contain all the prefix osmocom/gtp.
The old non-prefix was used in the old OpenGGSN code base.

Change-Id: I5ea50c9766f719e1eea89cbf6783fafc2093773d
2025-01-28 00:17:16 +01:00
Alexander Couzens
d3b037ccfa gprs_ms_net_cap_gea_mask(): protect against empty MS Network Capabilities
When the MS Network Capability is empty, expect to support at least
unencrypted communications.
This shouldn't be empty at all, as the minimum length of it is 2 when
the MS/UE is doing an Attach Request.
But when receiving a MS/UE SGSN Context via Gn, the field
is optional.
The MS/UE shall include it into the Routing Area Request,
but not must.

Change-Id: Ieef2e3eeaaadc90c35fff6f20d47bd36aaa4b9e6
2025-01-28 00:17:15 +01:00
Alexander Couzens
921af3d428 Refactor mmctx_is_r99 into mmctx.c
It is related to the mmctx and should be in mmctx.c instead
of the GMM message parsing or handling.

Change-Id: I198a3c9d49667c70e8995808b3fcb5ea26e8f17a
2025-01-28 00:17:15 +01:00
Alexander Couzens
0e8f055631 GMM: rework PDP context status
Use an uint16 instead of an pointer with an unknown length.
Also encode the current active PDP context (e.g. on 2G/4G
mobilty this could change). It resynchronizes the UE with the SGSN
state.

Change-Id: I12d3110c9365132f96ef7ff8a1be22a431682c81
2025-01-28 00:16:53 +01:00
Pau Espin Pedrol
df44350b4b jenkins.sh: No need to build libosmo-sigtran with doxygen
Change-Id: Iab3d1b2e1591e66702a01def6c322f4a11970ead
2024-12-10 16:52:17 +01:00
Pau Espin Pedrol
7a45b57485 sgsn_vty: Drop unneeded use of abis/ipa.h header
The header is not needed and will eventually be deprecated.

Change-Id: I48a513b8ea63dadbc6d6d571380980f55ff04a06
2024-12-10 14:37:31 +01:00
Alexander Couzens
7d94476bde GTP: CreatePDPContext: only use IMEISV IE when IMEISV is known
The IE is optional, but if it is present, it must be 11 byte long
containing a 8 byte IMEISV. If IMEI is unknown the SGSN
would add an empty IMEISV IE which is invalid.

Change-Id: I812af1e702e77214244f32ae65663c1a03b23962
2024-12-05 12:28:05 +00:00
Pau Espin Pedrol
6668b2b29a vty: Avoid accessing gsupclient object fields directly
Use new APIs recently added.

Depends: osmo-hlr.git Change-Id I401af83232022f1c141eef1f428cbe206a8aaaa2
Change-Id: Ie443ef0bd983635a5b29e434d79b93ef3f7ce370
2024-12-03 14:32:57 +01:00
Pau Espin Pedrol
b69e326e69 gmm: Fix reject small size RAU request
A RAU Request can actually be 14 bytes long:
"""
GSM A-I/F DTAP - Routing Area Update Request
    Protocol Discriminator: GPRS mobility management messages (8)
        .... 1000 = Protocol discriminator: GPRS mobility management messages (0x8)
        0000 .... = Skip Indicator: No indication of selected PLMN (0)
    DTAP GPRS Mobility Management Message Type: Routing Area Update Request (0x08)
    Update Type
        .... 0... = Follow-on request pending: False
        .... .000 = Update type: RA updating (0)
    Ciphering Key Sequence Number
        0... .... = Spare bit(s): 0
        .111 .... = key sequence: No key is available (MS to network) (7)
    Routing Area Identification - Old routing area identification - RAI: 262-42-13135-0
        Routing area identification: 262-42-13135-0
            Mobile Country Code (MCC): Germany (262)
            Mobile Network Code (MNC): Vodafone GmbH (42)
            Location Area Code (LAC): 0x334f (13135)
            Routing Area Code (RAC): 0x00 (0)
    MS Radio Access Capability
        Length: 4
        MS RA capability 1
            0001 .... = Access Technology Type: GSM E --note that GSM E covers GSM P (1)
            .... 0001  111. .... = Length in bits: 0x0f (15)
            ...0 01.. RF Power Capability, GMSK Power Class: Not specified (1)
            A5 Bits: Same values apply for parameters as in the immediately preceding Access capabilities field within this IE (0)
            .... ...1 = Controlled early Classmark Sending: Implemented
            0... .... = Pseudo Synchronisation: Not Present
            .0.. .... = Voice Group Call Service: no VGCS capability or no notifications wanted
            ..0. .... = Voice Broadcast Service: no VBS capability or no notifications wanted
            ...1 .... = Multislot capability struct: Present
                HSCSD multislot class: Bits are not available (0)
                GPRS multislot class: Bits are not available (0)
                SMS_VALUE (Switch-Measure-Switch): Bits are not available (0)
                ECSD multislot class: Bits are not available (0)
                EGPRS multislot class: Bits are not available (0)
                DTM GPRS Multi Slot Class: Bits are not available (0)
"""

Change-Id: I49210a04b16e6e2fc9d799b99c2fa415f28ddbba
2024-11-25 19:10:12 +00:00
Pau Espin Pedrol
11854f52ac jenkins.sh: libosmo-netif no longer depends on libosmo-abis
Change-Id: Id62040f41e9a5c233cc42eedb0bd5df9f62df418
Depends: libosmo-abis.git Change-Id I079dc3999de508301dd37ed03e399356a58d3cab
Depends: libosmo-netif.git Change-Id I13d6e88158f6d9ce017986283183ee9c2cc68cae
2024-11-21 14:54:24 +01:00
Pau Espin Pedrol
61d3e3a377 gsm48_gmm_ie_tlvdef: Add newer definitions from current enum gsm48_gprs_ie_mm
Depends: libosmocore.git a28ae056435b0de575441f7608101117d1beda0c
Change-Id: I38dc87bcaa23a5c4ec36ae4ab082b150dad93840
2024-11-19 19:30:01 +01:00
Pau Espin Pedrol
d4bded987b gsm48_gmm_ie_tlvdef: Add missing definitions from current enum gsm48_gprs_ie_mm
Fill in defintions for all enum fields defined as of libosmocore.git
51bbb34a16359941f17a0b80d8fe9b6d73d12307.

Change-Id: I2648fbfb0f133069470a829d80fdbe80b7e6e1ef
2024-11-19 18:59:19 +01:00
Pau Espin Pedrol
99bc975225 gsm48_gmm_ie_tlvdef: Sort based on enum gsm48_gprs_ie_mm order
Change-Id: Icb943e06b7ee7bd7f2def30c9b5ec5d24123cd94
2024-11-19 18:56:48 +01:00
Alexander Couzens
7138f8eb93 Use %d instead of %i
%d and %i has the same meaning when used in format string for printf.
The linter will warn when using %i. %i was only added to provide
symmetry between scanf() and printf().

Change-Id: Icd5f5f9b0d2ed8fd82afa406787acb4bd95358bf
2024-10-22 10:25:51 +02:00
Alexander Couzens
5b289e83cf GMM: split parsing of a RA Update Request in a separate file
gprs_gmm.c is huge. Further split the general validation
and parsing of the message into an own function.

Change-Id: I413da1b6b4b7c0c4781393acd8564661bc74ce2d
2024-10-22 10:25:51 +02:00
Alexander Couzens
8a2ed97336 move gsm48_gmm_att_tlvdef into gprs_gmm_util
The gprs_gmm.c is huge. Move message parsing into gprs_gmm_util.c.

Change-Id: I67dcdb986fd01dc093501d324b5c376246a5d30d
2024-10-22 10:25:49 +02:00
Alexander Couzens
72283a1686 Refactor diffing same GMM messages
gprs_gmm_attach_req_ies() isn't specific for the attach request.
It also did not cover the full message because of a fixed message length
when comparing both messages.

A diff of the old and new GMM message is required to figure out
if the MS/UE is retransmitting an old message or starting
a new procedure.

Change-Id: Ie698d3a6894a5796663c22c8bfd12b47acda57e6
2024-10-21 20:53:52 +02:00
Alexander Couzens
e7303adc8d Implement correct Routing Area based paging
Previous the SGSN would not support multiple BSS within the
same routing area.
Add support paging of a whole routing area.

Change-Id: I181da9f656e394ccfcb8999021a5b7e13ca0419f
2024-10-21 20:53:52 +02:00
Alexander Couzens
e8c82d9cd1 Add Routing Areas
Add a routing area layer which tracks routing area and
cells within a routing area.

Change-Id: I2474b19a7471a1dea3c863ddf8372b16180211aa
2024-10-21 20:53:52 +02:00
Pau Espin Pedrol
6213201b95 ranap: Reject ActivatePDPCtx from UE if RABAssResp parsing fails
Before this patch, if Rx path at RAB Ass Req failed, the PDP ctx in the
middle of being activated was left untouched.
Explicitly communicate the failure to both sides (UE and GGSN).

Related: OS#6508
Related: SYS#7119
Change-Id: I111cc4b17100d2e1ef756b654dc9e98415b3a8bb
2024-10-16 17:22:35 +02:00
Pau Espin Pedrol
3087322c3e ranap: Fix decoding of padded ITU X.213 IPv4 TLA in Rab Ass Resp
Simply use the existing omos-iuh library helper to decode the IP
address, which is more robust than existing adhoc code in osmo-sgsn.
The library version already supports decoding ITU X.213 IANA binary IPv4
addresses padded to 20 bytes.

Related: OS#6508
Related: SYS#7119
Change-Id: I9c48b676068574338f60b6ed7ad8b61ba748b52e
2024-10-16 17:22:09 +02:00
Oliver Smith
b12c892a42 contrib/jenkins: libosmo-sccp -> libosmo-sigtran
Change-Id: Id587ed1a8604c4881fd82784ad400c91d9125e32
2024-09-16 12:29:43 +02:00
Oliver Smith
a39a564906 debian/control: remove build-dep: libosmo-sccp-dev
This follows the removal of the libsccp.a and the pkg-config
libosmo-sccp.pc from libosmo-sccp.git

Related: libosmo-sccp I299a32a2f8f61477cf49c8126567fef2092d5407
Change-Id: I2fc827cf15b7f78173e5ee489abe2c6d12b82c2f
2024-09-10 09:54:58 +02:00
Vadim Yanitskiy
13592d2fa5 sm: pdpctx_timer_stop(): warn about timer not running
Similarly to 282de031, this commit turns errors like:

  DGPRS ERROR PDP(---/0) Stopping PDP timer 3395 but 0 is running

into warnings with a more accurate reason:

  DGPRS ERROR PDP(---/0) Stopping *inactive* PDP timer 3395

Change-Id: I64932d1cbd93667ab2e94e04691d6601435dba81
Related: 282de031 "gmm: mmctx_timer_stop(): warn about timer not running"
2024-08-30 05:21:41 +00:00
Alexander Couzens
12ed86d17a Replace gprs_ra_id with modern osmo_routing_area_id
The new modern osmo_routing_area_id is more flexible
and allow to access PLMN, LAC more convient.

Depends: Iaef54cac541913534af00f40483723e9952a6807 (libosmocore)
Change-Id: Ia41eb8f51d3836b1bc65325ff1ec6bdb16e20c7e
2024-08-20 14:08:14 +02:00
Pau Espin Pedrol
35c178e84d llc: Mark old/current tlli as all 1's when unassigning LLME
TS 44.064 section 8.3.3 (and other sections) talk about special
unassigned value of "all 1's", but I couldn't find any reference to a
"all 0's" specific value/meaning.
In practice in the code this may not be super important since those
values may not ve checked due to the FSM state, but in any case they are
initially set to all 1's, so it makes total sense to re-set them to the
same unassigned value instead of a randomly chosen all 0's value.

Change-Id: I660c8d0ef08b34f8cb74fd51b5c59e5628d687ae
2024-08-19 18:26:31 +02:00
Pau Espin Pedrol
868d818e6e Fix double free during RAU with unexpected Old RAI
If an MS which had an MMCTX at the SGSN sent RAU update with an
unexpected Old RA field, the RAU was rejected and LLME (LLC layer)
unassigned (freed), because no MMCTX was found matching the wrong old
RA.
However, an MMCTX may actually exist pointing to that LLME, and hence
when the LLME is freed, it stayed unnoticed with a dangling pointer to
the freed LLME in ctx->gb.llme.
Let's try to harder to avoid this kind of bugs which make osmo-sgsn
crash.

Once we properly split the code into separate independent layers (LLC,
MMCTX, etc.) each holding their own structs, this kind of bugs shouldn't
happen anymore.

Related: OS#6441
Change-Id: I5a4328c6e945b85dd815215724feecadba59c435
2024-08-19 18:20:53 +02:00
Vadim Yanitskiy
140017e0ed build: do not link against libosmo-abis
We use 'struct ipa_client_conn' from libosmo-abis:

  src/sgsn/sgsn_vty.c:56:#include <osmocom/abis/ipa.h>

but do not call any of its API directly, so linking against it
is not necessary.  Remove it from $LDADD, but keep in $CFLAGS.

Change-Id: I11168a7b25942d6c70566441fb0a1d26c3ae5c43
Related: OS#6535
2024-08-09 17:57:31 +07:00
Vadim Yanitskiy
c239545936 build: remove indirect libosmo-netif dependency
Neither we include its headers nor call any of its functions.
It's actually a dependency of libosmo-sccp, which is required
for '--enable-iu', so keep it in contrib/jenkins.sh.

Change-Id: Ia3395fd335d3a693c314b29b8e92968eef55da9a
Related: OS#6535
2024-08-09 17:57:22 +07:00
Alexander Couzens
9650961c4b includes: add forward declartion of external types
Change-Id: Ifbf0a045a6391694155f6627967f2d92b930d765
2024-08-04 19:52:35 +02:00
Alexander Couzens
c05dad1035 includes: sgsn.h: use full path include for gtp.h
The gtp header of ggsn have been moved to osmocom/gtp/gtp.h for a while.
Use the full path to prevent clashs with older versions

Change-Id: I764644110c0f332b18117e1e8311ddc55eafd5fa
2024-08-04 17:44:37 +02:00
Pau Espin Pedrol
7d5337fe80 Handle rx UpdatePDPCtxReq with Tunnel Direct Flags EI=1
GGSN informed us that it received an Error Indication when sending DL data to the RNC.
This probably means the RNC lost its state, aka crashed or was rebooted.
Mark the subscriber as PMM-IDLE, release Iu and point GTPU back to SGSN.
Then page the UE so it hopefully re-creates the state at the RNC.

Related: OS#6512
Related: OS#6519
Related: SYS#5435
Depends: osmo-ggsn.git Change-Id Ic80a9a928c55b6ff85be96014920bb42793cb943
Change-Id: I76d4c387730fdbfb9e7e0dd23a5afb9e762228b1
2024-08-01 11:39:00 +02:00
Pau Espin Pedrol
2cd06e28f4 Announce SGSN own TEID during UpdatePDPCtxReq after UE goes PMM-IDLE
When the UE/RNC closes the Iu conn (while keeping the PDP Context
activated), the SGSN updates the GGSN to point the GTPU tunnel to
itself. Unfortunately, only the IP address was being updated while the
TEID was kept the same (the one from the RNC).

As a result, when new MT data arrived at the GGSN, it would forward it
over GTPU to the SGSN using the incorrect RNC TEID, which the libgtp
stack at osmo-sgsn would silently drop due to not being known (because
it was >PDP_MAX=1024).

The issue can be triggered in test SGSN_Tests_Iu.TC_pmm_idle_rx_mt_data.

Related: OS#5773
Related: SYS#5435
Change-Id: I782aa43c71569922a945bd44544bb1388bf8c878
2024-07-30 21:38:41 +02:00
Pau Espin Pedrol
0bab0007c7 gtp: Set Direct Tunnel Flags DTI during UpdatePDPCtx
This is required as per TS 28.060 to tell the GGSN that the remote
Address/TEID it is receiving it's the one of the RNC.
Upon receiving a GTPU Error Indication, the GGSN knowing it's using
DirectTunnel, can then update the SGSN with UpdatePDPContextReq with
Direct Tunnel Flags DTI=1 EI=1 and then the SGSN can decide whether
reconfigure the Direct Tunnel or switch to 2-leg tunnel until the
connection with RNC/UE can be reestablished.

Depends: osmo-ggsn.git Change-Id Ia3e360a35d30858eab1e438dc2508fd756c2e22e
Related: SYS#5435
Change-Id: Iefe73eeea41df0c55db673194c9e9547504cbf0d
2024-07-30 21:38:37 +02:00
Pau Espin Pedrol
4ced617eb6 Fix DeactPDPCtxAcc when UE goes PMM ENABLED but lost its PDP context
Scenario: UE activates a PDP context, then after a while goes PMM IDLE
(Iu conn is destroyed but PDP is kept).
When UE connects through Iu again, it sends eg. RAU or ServiceRequest
with pdp_status bitmask statis the active NSAPIs.
If some NSAPI (PDP context) is enabled at SGSN but doesn't show up in
the bitmask, SGSN will destroy the PDP context with GGSN
(DeletePDPContextReq) towards GGSN prior to re-creating it.
When SGSN receives the DeletePDPContextResp, it would forward a
DeactivatePDPContextReq to the UE for a PDP context which was not known
by the UE anymore, this is wrong.

With this patch, the state of the NSAPI/PDP at the UE side is tracked,
and used to know whether when the PDP gets deleted on the GGSN side then
it needs to also be deleted on the Iu side.

Change-Id: I0ccd9228d71c29248b5f510356dbfdb09565dc30
2024-07-30 21:36:01 +02:00
Oliver Smith
f8d248e2d1 Bump version: 1.11.1.22-bea6a-dirty → 1.12.0
Change-Id: I9331fb5c69c5d00d419e859f1fa81d6e231b0318
2024-07-24 17:31:38 +02:00
Vadim Yanitskiy
bea6a0ffb5 README.md: cosmetic: fix a typo
Change-Id: Ia23fdbde29691c7af3834effee3d03ab866ca809
2024-06-05 18:34:07 +07:00
Oliver Smith
a13cc20c98 doc: set state-dir to /var/lib/osmocom/osmo-sgsn
Be consistent with osmo-ggsn, and set the state dir to
/var/lib/osmocom/osmo-sgsn. Without this patch, it defaults to the
current directory, which means in case of running with the systemd
service, /var/lib/osmocom.

Copy osmo-sgsn.cfg and osmo-sgsn-accept-all.cfg to the tests dir and do
not set the state-dir there. Usually the user that runs the VTY and CTRL
tests is not allowed to write to /var/lib/osmocom. (I've also tried
generating these on the fly, but that breaks in 'make distcheck', as I
would need to write to the source dir or would need to change
osmo-python-tests etc. to read the config file from another directory.)

Related: osmo-ggsn I5b51529b4f8bd2462e54f58a1ce2e2d7c76ff46a
Depends: osmo-python-tests Ic312d546da1c21f68a80b6a188616ef9bc84f4c6
Change-Id: I309807ff0bc125d4653222b2b4ba69ded3bbff70
2024-05-27 14:36:01 +02:00
Oliver Smith
1fd4a4c135 debian/osmo-gtphub.init: delete
Remove SysV init scripts. These are not really maintained anymore and
this makes it consistent with other Osmocom projects.

Avoids synchronizing with SysV scripts on debian:
  # systemctl enable osmo-gtphub
  Synchronizing state of osmo-gtphub.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
  Executing: /usr/lib/systemd/systemd-sysv-install enable osmo-gtphub

Change-Id: I9008944369314a4cbb345bfbf01bdb57aa7590fb
2024-05-22 13:33:52 +02:00
Oliver Smith
b3ce06058c sgsn/sgsn_vty: create state-dir
Prepare to change the state-dir in the default config in a follow-up
commit. Create the directory if it does not exist.

Change-Id: I8db4898cdaa2fcbd6bbf7c543764b9cdf828de83
2024-05-16 10:50:56 +02:00
Oliver Smith
0a6fe9727f debian/postinst: add checks, be verbose
Do not attempt to change permissions/ownership if the package gets
upgraded from a version higher than the next release.

Do not fail if the user deleted the config file.

Be verbose when changing permissions.

Related: OS#4107
Change-Id: I2b01a7625cf66fbb7d203f939ddcc1cbab43cf33
2024-05-14 15:21:06 +02:00
Oliver Smith
7ba62d3061 contrib: remove rpm spec file
Related: https://osmocom.org/news/255
Related: OS#6446
Change-Id: I9e7a3beb861faab1b6852aa5b57847c590986976
2024-05-13 08:39:35 +00:00
Vadim Yanitskiy
62b28ffe1b VTY: sync default UMTS UEA config with osmo-msc
As was reported in OS#6442, nano3g S16 is unhappy when CS and PS
domains use different UEA configuration for simultaneous RANAP
connections.  Bring osmo-sgsn in sync with osmo-msc to avoid this.

Change-Id: I4eb9451b4267fc1436ed90a55ff200cf36f16bf6
Related: OS#6442
2024-05-09 10:50:08 +02:00
Vadim Yanitskiy
cdf716cf9a VTY: move default settings to sgsn_instance_alloc()
It's cleaner to have all configuration defaults in one place.

Change-Id: I1a439dcc76272a181986b6ec9368ef16441dc098
Related: OS#6442
2024-05-09 10:48:29 +02:00
Oliver Smith
a9c39c04de .deb/.rpm: various fixes related to non-root
* Explicitly chown /var/lib/osmocom to osmocom:osmocom, instead of
  relying on systemd to do it when the service starts up. This does not
  work with the systemd versions in debian 10 and almalinux 8.
* deb: Use "useradd" instead of the interactive "adduser" perl script
  from Debian. This makes it consistent with how we do it in rpm, and
  avoids the dependency on "adduser".
* deb: Consistently use tabs through the file, instead of mixing tabs
  and spaces.
* deb: Remove support for the "dpkg-statoverride --list" logic. This
  seems to be a rather obscure feature to override permissions for
  certain files or directories, for which it does not seem to be a good
  idea to make the postinst script less maintainable. Something similar
  can be achieved by using your own Osmocom config file in a different
  path with different permissions.

Related: OS#4107
Change-Id: I406ff0d625b02991d580c8382aa4be04dba45a00
2024-05-08 06:46:32 +00:00
Vadim Yanitskiy
282de031f1 gmm: mmctx_timer_stop(): warn about timer not running
This turns errors like:

  DMM ERROR MM(262420000000038/e2ff704e) Stopping MM timer 3350 but 0 is running

into warnings with a more accurate reason:

  DMM NOTICE MM(262420000000037/e2ff704e) Stopping *inactive* MM timer 3350

Change-Id: I56ecad9d8f1049974b0896f6d0e7fc61580155ec
2024-05-01 10:44:27 +02:00
Vadim Yanitskiy
c3156193da gmm: cosmetic: fix preprocessor macro formatting
Change-Id: I77171d65db23794d8fd9872e0cc4d6f3b50dda0d
2024-05-01 10:44:27 +02:00
Alexander Couzens
cd3a8cfad6 docs: front page: use https:// instead of http://
Change-Id: If3c3b8e79f94da7a3bcc9262808da09f6a5a601c
2024-04-28 12:17:10 +00:00
Alexander Couzens
e51b3be379 docs: update year to 2024
Change-Id: I85a987eee470d2040c91289d33c5d97c3e90674d
2024-04-28 12:17:10 +00:00
Alexander Couzens
b34e0a5720 docs: replace legacy NS with new NS2 chapters
osmo-sgsn already switched to the new NS2 code. Use the correct
NS2 chapter

Change-Id: I9cc86d234e029b5192e36aeb14b0e39d1496842d
2024-04-28 12:17:10 +00:00
Oliver Smith
05363e0a32 contrib/osmo-sgsn.spec: fix build for almalinux:8
Add the missing "%if 0%{?suse_version}" around %service_del/add
commands, as these are only available on opensuse.

Fix for:
  error: line 106: Too many names: %preun  -n osmo-gtphub %service_del_preun   osmo-gtphub.service

Fixes: a07e6d9c (".deb/.rpm: add osmocom user during package install")
Change-Id: I89802f926bfccc0f7b4bb1ff64115b232b1db022
2024-04-26 09:58:51 +02:00
Max
a07e6d9c58 .deb/.rpm: add osmocom user during package install
Create osmocom user & group during package installation.
Fix the configuration dir/files permission to match.

Related: OS#4107
Tweaked-By: Oliver Smith <osmith@sysmocom.de>
Change-Id: I55ce205d4b314d01b2641c8f3d52455c051d6282
2024-04-24 11:52:50 +02:00
Harald Welte
1ede89a35a README.md: Add Forum and Issue Tracker sections
Change-Id: I69dfe4124c2a2be30c9ef04e70e3f15d10a2305c
2024-03-23 17:15:07 +01:00
Harald Welte
647304fbe5 README.md: Overhaul (more links; improved formatting)
Change-Id: I0cf9898877aab2f834c886491f4d203d55a8b4b9
2024-03-23 17:07:07 +01:00
Harald Welte
370d6e8b59 Add funding link to github mirror
see https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/displaying-a-sponsor-button-in-your-repository

Change-Id: Icf0fd068742eba60c23f0e567e6e72b42063f2c0
2024-03-23 17:03:36 +01:00
Pau Espin Pedrol
dc4c294f94 gsup: Use new libosmogsm struct osmo_gsup_pdp_info fields
This also makes sure it doesn't compile against older libosmogsm gsup
versions which would break ABI.

Change-Id: I0d03d368e73ab62ec631420769f6af91f2ff9987
Related: OS#6091
Depends: libosmocore.git Change-Id 70be3560659c58f24b8db529c4fc85da4bb0ec04
2024-01-29 11:07:03 +01:00
Vadim Yanitskiy
f2545b1b8f build: include README.md into the release tarball
Change-Id: Ia467ae8cc6eec0dc9fb36d4c159d2762e965c4f8
2024-01-26 23:37:30 +07:00
Andreas Eversberg
1f1d90f175 Use uniform log format for default config files
Related: OS#6272
Change-Id: I6b6aa5a5100cf0045dcba1b062acc9376d34b0ae
2023-12-01 12:40:54 +01:00
Oliver Smith
2a89bbf66f Bump version: 1.11.0.5-67677-dirty → 1.11.1
Depends: osmo-ggsn I1f116e1cded135f231f22ebc9b817aebf3736fc2
Change-Id: I869eef2032d6025c8ed59a1b25192c6c5c08977e
2023-11-28 13:43:15 +01:00
Daniel Willmann
676777c5f9 libgtp: Check for all successful create_pdp_conf causes
Related: OS#6268
Change-Id: I11ce72908c2dfb983887e6c1db316fd7de42f027
2023-11-23 18:00:07 +01:00
Daniel Willmann
ff9c46cc61 vty-tests: Test encryption options
Change-Id: I471c04602dedfb2a80d4408c09125e51c465a8b8
2023-11-22 16:06:43 +01:00
Daniel Willmann
75a0aa78a3 sgsn_vty: Correctly indent encryption cipher-plugin-path
Change-Id: I16b3450c3919bebbceb8d27f73d7c6dde102d0f7
2023-11-22 16:06:43 +01:00
Daniel Willmann
20aef4de28 sgsn_vty: Fix output in config_write_sgsn
The encryption uea option was missing

Change-Id: I2c81ced87c53d69a94b3894441323201f81f1a76
2023-11-22 13:14:25 +01:00
Philipp Maier
e746b0bef6 sgsn_rim: forward message based on RIM ROUTING ADDRESS
At the moment we parse the RAN TRANSPARENT CONTAINER to look at the
destination RIM ROUTING INFORMATION. This is not correct. The SGSN
should not decode the RAN TRANSPARENT CONTAINER and use the RIM ROUTING
ADDRESS / RIM ROUTING ADDRESS DISCRIMINATOR IE to make the routing
decision.

Related: OS#6095
Depends: libosmocore.git Ibca1f08906c4ffeecdae80d4e91c6c7b05fe4f8a
Change-Id: Ifd2b915ed2f05130cff8ee77714b82005c17de3d
2023-09-18 21:53:39 +02:00
Pau Espin Pedrol
57567968ea Bump version: 1.10.0.16-7e4d-dirty → 1.11.0
Change-Id: Ia56d2e1c4247396522f02df2c95b842db655e171
2023-09-12 16:57:03 +02:00
Philipp Maier
7e4dbb4b34 sgsn_rim: do not check the origin of a RIM message
When we forward RIM messages from GTP to BSSGP, we do not have to check
the origin of the message since it does not matter from which origin the
message came when we are forwarding it.

Related: OS#6095
Change-Id: Iea8176dcfe64c25d207bafc0ef61ca9d9ad415be
2023-08-10 10:24:23 +02:00
Philipp Maier
7840375d51 sgsn_rim: get rid of MME check in sgsn_rim_rx_from_gtp:
There is no point in checking the MME any further. When the message has
reached this code path it is about to be forwarded to BSSGP, so the MME
does not play a role in the following code pathes.

The check also relys on the source RIM ROUTING INFORMATION IE inside the
RAN TRANSPARENT CONTAINER, which we are not supposed to decode.

Change-Id: I97c89aeb11537ae54d1fbea48c75619d8a92af61
Related: OS#6095
2023-08-10 10:23:06 +02:00
Philipp Maier
429d332ece sgsn_rim: cosmetic: improve comment
Let's describe more clear what we do in sgsn_bssgp_fwd_rim_to_geran

Related: OS#6095
Change-Id: I54aa82845515bcaa6badc9e0e87fa6248333430e
2023-08-10 10:19:37 +02:00
Philipp Maier
f24970a7ca sgsn_rim: fix typo
Related: OS#6095
Change-Id: I86f70ea9a1a3e43523ec327165bfeb1737ad300a
2023-07-28 13:23:49 +02:00
Pau Espin Pedrol
2365fec0fb gmm: Add missing GSM48_IE_GMM_RX_NPDU_NUM_LIST IE in gsm48_gmm_att_tlvdef
Depends: libosmocore.git Change-Id Ifac09653141758af345efe2eb9cef25ebf4dcff9
Change-Id: I5b43384407b1c9c33790cae9c48c2816213578e6
2023-07-18 17:41:09 +02:00
Pau Espin Pedrol
5df65b6c30 gmm: Update DRX params during rx RAU REQ
The DRX params where already parsed in GMM Attached Req and transmitted
to PCU over BSSGP DL UD packets, but it was not being updated if the MS
changed it during RAU Req.

TS 24.008 9.4.14.3 DRX parameter:
"This IE shall be included if the MS changes the access network
from GSM to UMTS, or the MS wants to indicate new DRX parameters
to the network."

Change-Id: I1dd7f8f161280dd017c337eacc3aa2be4ccd65ea
2023-07-14 18:11:31 +02:00
Pau Espin Pedrol
5f1020b963 Write explicit role & sctp-role fields in ASP configurations
Change-Id: I44e251ca2df02e4f1fdfc1492306ec25d0653ef6
2023-06-08 19:34:21 +02:00
Oliver Smith
eda1b83f75 systemd: depend on networking-online.target
Related: SYS#6400
Change-Id: Idadcbbf55e976ae035cfac4b85ccd870e0f27b82
2023-05-26 14:10:48 +02:00
Vadim Yanitskiy
b83aabaa95 copyright: fix typo: sysmocom s/s.m.f.c./s.f.m.c./ GmbH
Change-Id: Ie2d864d5171e0da2e8a6c8551d151fd14f89bf05
2023-05-18 17:22:26 +07:00
Pau Espin Pedrol
1bebd08a4b gprs_sm.c: Fix load of misaligned ptr address
Got this Asan runtime error in osmo-sgsn while implementing the MS side of SM:
"""
DMM gprs_sm.c:427 MM(901700000015254/c655d609) -> ACTIVATE PDP CONTEXT REQ: SAPI=3 NSAPI=6 IETF IPv4 /osmo-sgsn/src/sgsn/gprs_sm.c:453:16: runtime error: load of misaligned address 0x61f000064ba3 for type 'uint32_t', which requires 4 byte alignment
0x61f000064ba3: note: pointer points here
 00  06 01 21 00 00 00 00 28  09 27 01 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00
              ^
"""

Change-Id: I8069e3457120b22bb6514fd5d192bff486d7d87f
2023-05-03 11:35:24 +02:00
Oliver Smith
a86056fdf3 debian: set compat level to 10
Related: OS#5958
Change-Id: Ib45ad7c44cdefa4c5acab2da09f24796253a133d
2023-04-25 16:48:32 +02:00
Vadim Yanitskiy
99ec755643 tests: $(BUILT_SOURCES) is not defined, depend on osmo-sgsn
Change-Id: I4f9e99ed3673bb51fa5f7d374c35c3c92735eacb
2023-03-30 02:11:21 +07:00
Pau Espin Pedrol
d5dca3a67f gmm: Ciphering Key Sequence Number IE has half octet tag
As per 3GPP TS 24.008:
* 10.5.1.2 Ciphering Key Sequence Number
* Table 9.4.9/TS 24.00

The IE is so far being encoded manually, hence why it worked fine until
now.

Change-Id: Ic220113f30377a14cbe3550a04cd04f3caef49cf
2023-03-22 13:36:35 +01:00
Vadim Yanitskiy
3c26a1dc3c tests: use -no-install libtool flag to avoid ./lt-* scripts
This option should be used for any executables which are used only
for testing, or for generating other files and are consequently never
installed.  By specifying this option, we are telling Libtool that
the executable it links will only ever be executed from where it is
built in the build tree.  Libtool is usually able to considerably
speed up the link process for such executables.

Change-Id: I8af6a38d7abbf06aa8268981c80c3bfda2f80a27
2023-03-11 05:02:17 +07:00
arehbein
642019f288 Transition to use of 'telnet_init_default'
Related: OS#5809
Change-Id: Icc57c68337d55c6594c1c36e9bf41624d11dab0a
2023-02-26 21:16:12 +01:00
Oliver Smith
f8a5066ad0 Run struct_endianness.py
Ensure there is no diff to prepare to run this in CI.

Related: OS#5884
Change-Id: I808afd0e9833e6e99d30a37675cbd200ced027e4
2023-02-20 10:51:48 +01:00
Pau Espin Pedrol
8c42673eba Bump version: 1.9.0.56-07fe-dirty → 1.10.0
Change-Id: I89eb79ffeb28b8dae5b4a5c3cc1142d07052692c
2023-02-07 17:34:27 +01:00
Pau Espin Pedrol
07feb06d54 Fix extra whitespace in pdpctx_ctr_description
Change-Id: I4d9145c681e725b709fde38f6e9b4516d37b4d8c
2023-01-11 12:58:23 +01:00
Pau Espin Pedrol
86b630cfe1 vty: Introduce encryption cipher-plugin-path command
The load of plugins will eventually be moved to libosmo-gprs
implementation, and path will be passed as a parameter. Once it's moved
inside libosmo-gprs, it will be more strict on load failures, which can
cause internally if the path doesn't exist (unless NULL is passed).
Hence, add a VTY config to allow configuring the right path, and have it
disabled by default.

Change-Id: I4f965c7afafa193f4d7486750dd3e43cca22bb65
2023-01-11 12:58:23 +01:00
Pau Espin Pedrol
93bc518b53 Move global mmctx list into struct sgsn_instance
Change-Id: Idf8458902321da03b9b0831dad3ad383a9c7afa1
2023-01-11 12:58:23 +01:00
Pau Espin Pedrol
58101ea587 Split gprs_sgsn.{c,h} -> {auth,mmctx,sgsn}.{c,h}
Some level of split already existed, like sgsn_auth.c, but headers were
entangled together.
Let's clearly separate application centric code (sgsn.c/h), auth related
code (auth.c/h) and mmctx related code (mmctx.c/h).

Change-Id: I048a082851c1275c959649942904205b02acce2a
2023-01-11 12:58:15 +01:00
Pau Espin Pedrol
6aad14c3fa gtphub.h: Remove dependency on sgsn/gprs_sgsn.h
It is only really needed to import define GSM_APN_LENGTH, which is
actually also available in libosmogsm. Hence simply use the one from
libosmogsm.

Change-Id: I4c6110feeeaa1adfb6b1f0147eeb56dfe34636ec
2023-01-11 12:51:38 +01:00
Pau Espin Pedrol
f44dfa8a0e Rename bscconfig.h -> config.h
Change-Id: I007103be34c1aaab7a9375c44b226d4590fe5b24
2023-01-11 12:51:38 +01:00
Pau Espin Pedrol
e931b39b3c Move LOGGSUBSCRP to gprs_subscriber.h
The define belongs to gprs_subscriber.h header.

Change-Id: Icdb7e55ca8e90dd2ba79ccdb1a8ba650a3942ab3
2023-01-11 12:51:38 +01:00
Pau Espin Pedrol
fd9e82da31 Move sgsn_ctrl_cmds_install() declaration to sgsn.h
sgsn.h is the main header containing all misc app related contents.
This is another step towards shrinking gprs_sgsn.h mess.

Change-Id: I80e3a68e2e368d8c73135c850e4728bdf6cf5f09
2023-01-11 12:51:38 +01:00
Pau Espin Pedrol
f2307c483f Move gtphub header to include/osmocom/gtphub/
Change-Id: I82e1f2a3bc8e22b28747a540879bd661f1704cde
2023-01-11 12:51:38 +01:00
Pau Espin Pedrol
15a52d92c4 Move global pdp_list inside struct sgsn_instance
This way pdp contexts are managed by the lifcycle of the main global struct
sgsn_instance automatically.

Change-Id: I725218fd54adcc68dceded5eb43675f25771bb96
2023-01-11 12:51:38 +01:00
Pau Espin Pedrol
05190c36bb Move sgsn_pdp_ctx to its own file pdpctx.{c,h}
This further shrinks the mess in gprs_sgsn.h, and allows to easily see
layer violations (like pdpctx.c requiring llc.h)

Change-Id: Iad4da06efee7d8514ff48423bdaebc0f26413cc1
2023-01-11 12:51:34 +01:00
Pau Espin Pedrol
3d3c8c55f0 Drop extern declarations of global sgsn_instance in source files
There's an extern declaration already in sgsn.h.

Change-Id: I2375e13c8436a069e8fe60136c8e1759a9adc2d1
2023-01-11 12:46:34 +01:00
Pau Espin Pedrol
164a1eeb8a Move extern declarations of tall_sgsn_ctx to sgsn.h
Change-Id: Ifbd54b2e92db8d4a0e0cd1c569cfd83dd85165b8
2023-01-11 12:43:18 +01:00
Pau Espin Pedrol
69569879ae gtp_{ggsn,mme}: Allocate contexts under struct sgsn_instance
This way apns are managed by the lifcycle of the main global struct
sgsn_instance automatically.

Change-Id: Ie65d59632a368c6957c33dca64e856ace792b2c6
2023-01-11 12:31:23 +01:00
Pau Espin Pedrol
fd4d435442 Move global apn_list inside struct sgsn_instance
This way apns are managed by the lifcycle of the main global struct
sgsn_instance automatically.

Change-Id: I8cc8e540cfb64d0f130e9c0aaedf7b0835f8fe16
2023-01-05 19:37:07 +01:00
Pau Espin Pedrol
8ec269a0e0 Move gtp related functions to gtp.h
The functions are implemented in sgsn_libgtp.c and hence belong to
header file gtp.h

Change-Id: I7f5cf2895b05e03435769548b61051e6284ccb3c
2023-01-05 19:20:43 +01:00
Pau Espin Pedrol
4bd6f663a7 sndcp: Standarize unitdata function naming
Use sndcp_<sap>_type>_<op> so that it's easier to distinguish and
identify them.

Change-Id: Ib8825570a8f61d0a28d631f86f5244e70d3194aa
2023-01-05 19:00:56 +01:00
Pau Espin Pedrol
52c9b8e593 Move func defintions of funcs implemented in gprs_sndcp.c to gprs_sndcp.h
Move them to the correct header where they belong, so that the all the
related protocol stuff is placed together.

Change-Id: I9052f48a0af125bb445194f4ae94ebbe49508fda
2023-01-05 18:57:39 +01:00
Pau Espin Pedrol
51028e2c16 Properly split llc->sndcp->gtp unitdata pathi through extra func call
Beforehand the function handling the LL-UNITDATA primitive from LLC was
already submitting the packet to GTP code which had an SNDCP related
name, so everything was really confusing and layer separation was not
clean.

Change-Id: Ia544a9dd4c0c7647b0c1b64ca110351f40820618
2023-01-05 18:46:23 +01:00
Pau Espin Pedrol
e69f460ae7 sgsn.h: Drop declaration of non existing function
Change-Id: Idabea56d1ff89e51b517b15771a5a1ed3b050ec9
2023-01-05 18:23:03 +01:00
Pau Espin Pedrol
0e707fc83a Move struct sgsn_subscriber_pdp_data to gprs_subscriber.h
The functions driving its lifcyecles are already in gprs_subscriber.c,
and are used mainly by functions in the same file, hence move it to the
related header to further shrink gprs_sgsn.h.

Change-Id: Iff7be91af130a3317d57d3649c17e3d5d2540e7a
2023-01-05 17:48:17 +01:00
Pau Espin Pedrol
ffd6e37eb5 Move struct apn_ctx and APN related definitions to its own file
This allows further shrinking of gprs_sgsn.{c,h} and also being able to
use GSM_APN_LENGTH on different headers easily (needed by follow-up
patch).

Change-Id: Id225ed8b84e1376f4a30f17dd4b153b6b1a6efa8
2023-01-05 17:45:28 +01:00
Pau Espin Pedrol
44bde6b85a Move global ggsn_list into struct sgsn_instance
Change-Id: I9d4c74476b777a866af2796dd376ed50da7b5d01
2023-01-05 17:23:43 +01:00
Pau Espin Pedrol
e659f75cf1 Keep sgsn subsystems under struct sgsn_instance lifecycle
Rework initialization and destruction of several sgsn subsystems to be
allocated & released together with the struct sgsn_instance.

This makes it easier to destroy and recreate the entire context and
allows us to start moving global variables scattered around to be under
struct sgsn_instance.

Change-Id: Idf60519b8e475b94d38bbb69e737132a5afaefab
2023-01-05 17:23:43 +01:00
Pau Espin Pedrol
67e71eac1c Remove unneeded extern declaration from libosmocotrl
Change-Id: I464df2d03538c71f6666046c67170746690e723d
2023-01-05 17:23:43 +01:00
Pau Espin Pedrol
c1cf4af11b Move related structs to gprs_subscriber.h
This allows shrinking a bit more gprs_sgsn.h and and in turn have
everything much more tidy.

Change-Id: Ie39b48a0d612aa632327cc5a21c833b05f5bf297
2023-01-05 15:43:29 +01:00
Pau Espin Pedrol
f37aedbf76 Fix -Werror=old-style-definition
Change-Id: I119d4ba58d9c68df12b433b0cee924468a1473d8
2023-01-05 14:25:47 +01:00
Pau Espin Pedrol
920c6c8c81 Introduce new header file sgsn/gtp.h
It will be used to store all stuff relatd to libgtp use and GTP
protocol, similar to what we already do for other protocols.

Change-Id: I4aae35cd0ea401856cd822cb507d668350d07a89
2023-01-05 14:15:52 +01:00
Pau Espin Pedrol
df203361e8 Move gprs_sndcp_vty_init() declaration to gprs_sndcp.h
Change-Id: Iea9692e7ef9bd017d89ef654d2f2ae5b30cc4550
2023-01-05 14:15:52 +01:00
Pau Espin Pedrol
b61ab9b9ac gprs_subscriber: Move API declarations to correct header
Change-Id: Iaa1032c38fa54ad57c472d9120cfbb34b2ae90e9
2023-01-05 14:15:50 +01:00
Pau Espin Pedrol
5f4736aa85 Move struct sgsn_ggsn_ctx to its own file gtp_ggsn.{c,h}
Similar to what we already have for struct sgsn_mme_ctx in
gtp_mme.{c,h}.

This is just the nth step of properly splitting different
protocol layers, data model, etc.

Change-Id: Iad1895f09e43e299df7bb126bf52fdb98268392e
2023-01-05 00:11:57 +01:00
Pau Espin Pedrol
fc1a5538d0 Replace gprs_str_to_apn() with libosmocore API osmo_apn_from_str()
The exact same function exists in libosmocore with a different naming.

Change-Id: Ibef55a648f2d58f4fdd24fa553efde530982af2d
2023-01-04 19:56:39 +01:00
Pau Espin Pedrol
eb967fccb2 Remove unused function gprs_parse_mi_tmsi()
Change-Id: I6fb7688bf54c7ae3ca3e06bf3a1b729fa62d82f9
2023-01-04 16:29:43 +01:00
Pau Espin Pedrol
13c00008b4 Standarize lle and llme state enum & value_string
Change-Id: Iaf102ce5ca60854fe7eb1af17c73a80e7c76181b
2023-01-04 13:57:52 +01:00
Pau Espin Pedrol
e5614e434f vty: Fix wrong value_string used to print llme state
Change-Id: Id3eec91b47029964092087858e4ae3a824929ce3
2023-01-04 13:53:57 +01:00
Pau Espin Pedrol
b0b582bff8 cosmetic: gprs_llc_vty.c: Fix trailing whitespace
Change-Id: I543fd784f7e1a0f7c82bd7c79e073104becc88da
2023-01-04 13:49:22 +01:00
Pau Espin Pedrol
bc46812bd7 Move gprs_tmr_to_secs() to tests/gprs/gprs_test.c
That function is only used in the test. Let's hence move the function to
the same test file in order to simplify osmo-sgsn code.

Change-Id: I69d80810362d75eb93974af34f61639514f99f8a
2023-01-02 13:38:01 +01:00
Pau Espin Pedrol
4398ac073b Rename gprs_gb.[c,h] -> gprs_ns.[c,h]
All remaining code in that file is NS protocol related, hence let's
rename it so that we end up with one file per protocol in the Gb stack.

Change-Id: I8312c8a70d60cab48764950c5b57ca02964e9db2
2022-12-28 23:14:20 +01:00
Pau Espin Pedrol
05d5f28e93 Move some functions gprs_gb.[c,h] -> gprs_gmm.[c,h]
This leaves only NS protocol related code in gprs_gb.[c,h], which will
be renamed to gprs_ns.[c,h] in a follow up patch.

Change-Id: I3dcbe1d0f75cb91ec8b700e239e2ba16fff030a2
2022-12-28 23:12:47 +01:00
Pau Espin Pedrol
7a74ae492e Create new specific file for BSSGP code
Right now there's no much code there since the related code is totally
entangled with the LLC one.
This will eventually change in the future when we switch to use
libosmo-gprs.
Hence, this commit is a preparation to have already some place to put
new BSSGP specific code in the future.

Change-Id: I816396ab5ccb86032bbc21b41a959934a7768780
2022-12-28 23:11:49 +01:00
Pau Espin Pedrol
749ca7c850 Move gprs_gb_parse.[c,h] to tests/sgsn/
That big file is really only used by tests/sgsn/sgsn_test nowadays, so
let's keep it out of osmo-sgsn app code base.

Change-Id: Ia5a639832f52b2f015a2800bd0d94a28d7bc689b
2022-12-22 19:49:39 +01:00
Max
e7ccfdb4aa ctrl: take both address and port from vty config
Change-Id: Ie1330b152a2e5cdcdb80a1c958e7c1d784b78eab
2022-12-17 21:16:58 +03:00
Oliver Smith
e39ff86dd9 osmo-gtphub.cfg: fix conflict with osmo-ggsn.cfg
Change bind-to-ggsns from 127.0.0.2 to 127.0.0.20, so osmo-gtphub's
default config does not confligt with the osmo-ggsn default config. This
change is for the effort of making the configs of all Osmocom programs
not conflict with each other.

A similar change was made in Id892e1f4ab2daabbe9824b819b5fed985373b97a
with bind-to-sgsns.

Related: OS#5817
Change-Id: I57ee457b62139d831707b6ebd6baaea8d33c2d9c
2022-12-08 16:28:32 +01:00
Pau Espin Pedrol
57b63875c7 sndcp: Put decompress handling code into helper function
This further simplifies code and avoids duplicating it.

Change-Id: Id83f9e4a87139de2b2f64c8523460c186d5b5649
2022-12-06 12:06:26 +01:00
Oliver Smith
55e3dc8ec8 sgsn_libgtp: cb_data_ind: remove mm_idle assert
Log an error message and drop the packet instead of asserting if
mm state fsm is in ST_MM_IDLE while the gmm fsm is in
ST_GMM_REGISTERED_NORMAL.

Fixes: OS#5725
Change-Id: I9dab98917c622b36dae22399bb359d747a598208
2022-11-17 14:08:30 +01:00
Oliver Smith
acd967a177 contrib/jenkins.sh: use enable-werror with IU too
Now that the warnings in osmo-iuh have been fixed, we should be able to
build the IU version of OsmoSGSN with --enable-werror too.

Related: OS#4462
Change-Id: I8cc4e209e21acfe513bef72927499f1ccdead783
2022-11-15 13:01:25 +01:00
Pau Espin Pedrol
8501126031 vty: Make new libgtp tdefs configurable through VTY
Related: OS#5485
Depends: osmo-ggsn.git Change-Id I10bc8e2e197c0e8753b23b684b5ae41025672bf7
Change-Id: I46e9cd158a9f2f721c69f807beb7bb67a459f4a4
2022-11-04 14:27:30 +01:00
Max
b43496a60d GMM: permit E_GMM_COMMON_PROC_SUCCESS in normal state
The FSM might be moved out of ST_GMM_COMMON_PROC_INIT state either
by E_GMM_ATTACH_SUCCESS or by E_GMM_COMMON_PROC_SUCCESS events
which are not mutually exclusive. Hence the later event will arrive when we're already in
the ST_GMM_REGISTERED_NORMAL state.

Let's have both events permitted to keep the logs clean from useless error.

Related: OS#5349
Change-Id: Ia97b50aac6c665812ddca9010de7f97b17b78bd5
2022-10-14 15:04:36 +03:00
Max
caff83e702 Constify LLC/SNDCP parameters
That makes it easier to track side-effects while reading the code.

Related: OS#5349
Change-Id: I903f8a747a8d3b7f734dac7b0c12373ecbb90b11
2022-10-11 10:54:39 +03:00
Max
61f2186592 GTP: migrate from deprecated function
The gtp_set_cb_recovery3() is similar to gtp_set_cb_recovery2()
with extra parameter representing GSN.

Change-Id: I8b46cf8c52e36b0312eddf37f3e136662b95732e
2022-10-11 10:54:39 +03:00
Max
559636a4a2 SNDCP: log more details on failure
Related: OS#5349
Change-Id: Iad3ebbc28909a827db7b3a0ae2d3e1de7991210f
2022-10-08 20:24:22 +03:00
Vadim Yanitskiy
13ccbc1e61 llc: gprs_llc_fcs(): make the input data pointer const
Change-Id: If95210fe69f915ab1010fe5916cb6bee3faeb7b9
2022-09-08 12:51:54 +00:00
Vadim Yanitskiy
d32852664d gprs_llc.h: use '#pragma once'
Change-Id: Iff748fe68dbef83589bfb5e3bea5183deb365fa6
2022-09-08 12:51:43 +00:00
Max
77cdc424cb Set working directory in systemd service file
By default systemd will execute service with root directory (or home directory for user instance) which might result in
attempts to create files in unexpected place. Let's set it to 'osmocom' subdir of state directory (/var/lib for system instance) instead.

Related: OS#4821
Change-Id: I950d84853c6737276d02b3275127b499ae567c38
2022-08-30 19:42:59 +07:00
Vadim Yanitskiy
fb6cf3221e gprs_llc: fix misleading spacing in gprs_llc_rcvmsg()
Change-Id: I7ec97a7d9b37f0541887bc13e31f547613f8945e
2022-08-26 05:38:33 +07:00
Vadim Yanitskiy
c63a8381e5 configure.ac: do not require unused dlsym/dlopen
Change-Id: I90b383ed45b27d8b59272116dd81acb72912349d
2022-08-16 23:31:22 +07:00
Pau Espin Pedrol
328ed94040 Bump version: 1.8.0.9-c230-dirty → 1.9.0
Change-Id: If8d3bad88dbd57b620e3aca61d99073e178c2fb6
2022-06-29 11:45:09 +02:00
Harald Welte
c230f0c283 README: Major update
* convert to markdown syntax
* bring in-line with other osmo-* README.md files, in terms of
  links to git, mailing list, manuals, etc.

Change-Id: Ia4a4329c6ef6b8c833aa26832776dad662cdc7e9
2022-06-20 10:16:56 +00:00
Harald Welte
e2b9b7ee57 update git URLs (git -> https; gitea)
Change-Id: Ib8d2953a6c3f1e65b7c638feea4d8a97ee02e443
2022-06-20 10:15:50 +00:00
Vadim Yanitskiy
199f295d36 tests: use 'check_PROGRAMS' instead of 'noinst_PROGRAMS'
When using 'check_PROGRAMS', autoconf/automake generates smarter
Makefiles, so that the test programs are not being compiled during
the normal 'make all', but only during 'make check'.

Change-Id: I8118ee3d3da9bdcd0c691471ef91b95dba21004a
2022-04-13 19:55:36 +03:00
Neels Hofmeyr
3c7656a481 Iu: add UEA encryption
Add vty 'encryption uea 0 1 2', defaults to 'encryption uea 0' to yield
previous behavior.

If any UEA above 0 is enabled, include the UEA key in the Iu Security
Mode Command.

I noticed that only the code bit in st_iu_security_cmd_on_enter()
affects the test. The same code in gsm48_gmm_authorize() seems to be
dead code? But applying the patch there as well just to be safe.

We cannot yet verify the chosen UEA to match a configured UEA level,
because the iu_client.c does not send us message details with the
RANAP_IU_EVENT_SECURITY_MODE_COMPLETE.
Also we cannot yet send the set of configured UEA to the hNodeB, since,
again, iu_client.c does not provide the proper API for it.
The proper solution here is to completely dissolve iu_client.c and do
all Iu handling in osmo-sgsn itself -- see OS#5487.

Related: SYS#5516
Related: I1a7c3b156830058c43f15f55883ea301d2d01d5f (osmo-ttcn3-hacks)
Change-Id: I27e8e0078c45426bf227bb44aac82a4875d18d0f
2022-03-10 19:07:38 +01:00
Neels Hofmeyr
340a7e9339 s/cipher_support_mask/gea_encryption_mask
will add uea_encryption_mask, and find that the name
'cipher_support_mask' is not concise enough.

Related: SYS#5516
Change-Id: Ie8d4a0534c5b751f698bce425427bb1d28ddea31
2022-03-07 15:37:26 +01:00
Pau Espin Pedrol
938ebfb129 Revert "sgsn: Handle different levels of QoS"
This reverts commit 4bd931f96d.

The commit was wrong, and previous code is correct.
Relevant specs:
* TS 29.060 7.7.34 Quality of Service (QoS) Profile
* TS 24.008 10.5.6.5 Quality of service

As can be seen in TS 24.008 10.5.6.5, OSMO_IE_GSM_REQ_QOS never comes
with the the ARP byte prepended. This is actually always prepended when
sending the GTP message, as explained in TS 29.060 7.7.34.

As a result, the Qos Service sent in Create PDP Context Request sent to
the GGSN contained wrongly formatted Qos Profile IE, which was observed
checking wireshark with a real phone. This was found due to open5gs-smfd
being more strict about the possible lengths of the IE, since the
wrongly formatted IE send in GTP had length=14, which is incorrect due
to folllowing TS 24.008 10.5.6.5 wording:
"Octets 15-22 are optional. If octet 15 is included, then octet 16 shall also be included, and octets 17-22may be
included."
In this case, due to the wrong format it was seen as including octet 15
but not 16.

Change-Id: I4fc5ab823a27d27482858a7459337a2f8ae593c3
Related: SYS#5793
2022-02-18 17:26:14 +01:00
Pau Espin Pedrol
d06c717e30 Drop unneeded ax_check_compile_flag.m4
The macro is no longer used since 2d0e22960c.

Change-Id: I230005acc27e29c679a4ddbb2b316a3aae70874e
2022-01-11 18:13:46 +01:00
Oliver Smith
57425a3805 treewide: remove FSF address
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: I9bc57a7152015e0f37e3d1573921d6d5d3c0449b
2021-12-14 12:21:06 +01:00
Oliver Smith
f76428500a llme_free: clean up related sndcp
Fix crash in vty_dump_sne when sndcp->lle has already been deallocated.

Context:
* sndcp->lle is set only once in gprs_sndcp_entity_alloc()
* sndcp->lle is a struct gprs_llc_lle, which gets allocated and
  deallocated together with struct gprs_llc_llme. From gprs_llc.h:

    struct gprs_llc_llme {
            ...
            struct gprs_llc_lle lle[NUM_SAPIS];

Fixes: OS#4824
Change-Id: I707029f78222bc6335837241e5a08c54c5ae6eb3
2021-12-07 17:13:12 +01:00
Pau Espin Pedrol
0f9966e307 Bump version: 1.7.0.28-245ac-dirty → 1.8.0
Change-Id: I62daba59b9dd1a0cade5292c8705ee5ec5b103c2
2021-11-16 17:57:50 +01:00
Vadim Yanitskiy
245ac9501b tests/Makefile.am: do not try removing non-existing files
Change-Id: Ie9f4a9aa4061e4e4c659b1ad71596846ce75df7b
2021-11-15 04:39:57 +03:00
Oliver Smith
2d0e22960c Revert "Turn some compiler warnings into errors"
Do not turn some compiler warnings into errors by default. This patch
was added before --enable-werror was available.

We build with --enable-werror during development and in CI. If the code
is built with a different compiler that throws additional warnings, it
should not stop the build.

This reverts commit 34f012639d.

Related: OS#5289
Change-Id: I24e0a0d7f93f196dc642e37b03f68464024c09d4
2021-11-04 10:55:57 +01:00
Keith
6cee1a1ded VTY: Don't display 'PDP Address: invalid' for IPv4v6
We were not handling the case of PDP_TYPE_N_IETF_IPv4v6
in gprs_pdpaddr2str() and showed "invalid" for these addresses.

Depends: libosmocore Change-Id: I1f82f9d8fc13dcc4474760329bd74ae9685b9031
Change-Id: Id36b7520677e4a0af40d05dc503b26d1b0b74a26
2021-09-30 20:45:19 +02:00
Oliver Smith
c0e146467a debian/control: remove dh-systemd build-depend
Related: OS#5223
Change-Id: I769bf61a2f3a97d55c65999436d2cb079c9170a0
2021-09-01 16:07:07 +02:00
Oliver Smith
ab39b622cc vty: add "page imsi"
Make it easy to manually test pagings from SGSN to the PCU.

Related: SYS#4878
Change-Id: I8a73caa234f6b841e641be866e22e7fa03152eb7
2021-08-06 22:25:10 +02:00
Oliver Smith
3aba7ad2ae gtphub: remove llist_first, llist_last macros
Use list_first_entry_or_null instead of llist_first, which has been
present in libosmocore since the 0.10.0 release.

Use llist_last_entry instead of llist_last (also present since
libosmocore 0.10.0). This macro does not have a check for an empty
list, however the only user is already checking for an empty list
before using the macro.

This solves a build error, as llist_last was defined in libosmocore
Icf455bf6ba9d60bd311af17c9e80febaa42cacc9 (should probably be reverted
for backwards compatibility with previous osmo-sgsn versions?):

gtphub.c:68:0: error: "llist_last" redefined [-Werror]
 #define llist_last(head, type, entry) \

In file included from /build/deps/install/stow/libosmocore/include/osmocom/core/timer.h:46:0,
                 from /build/deps/install/stow/osmo-ggsn/include/gtp.h:17,
                 from gtphub.c:32:
/build/deps/install/stow/libosmocore/include/osmocom/core/linuxlist.h:245:0: note: this is the location of the previous definition
 #define llist_last(head) (head)->prev

Change-Id: Ia0496c24386cd13b1e9e604aa2d425d3fa28d352
2021-07-12 12:20:52 +02:00
Vadim Yanitskiy
e9336a72a0 doc/manuals: update configuration.adoc to use new command syntax
The old command is deprecated since [1] has been merged.

Change-Id: Iac985f373de98206fdfb3196295ebec160189780
Related: [1] Ie6700c4e9d2df1eb5fde1b971e287b62668cc2de
Related: SYS#5324
2021-07-03 21:07:43 +02:00
Eric
2f898265d0 add support for multiple encryption algorithms and a5/4
Change-Id: Ie6700c4e9d2df1eb5fde1b971e287b62668cc2de
Related: SYS#5324
2021-06-16 16:43:23 +02:00
Pau Espin Pedrol
a33f00637e Use new stat item/ctr getter APIs
Generated with spatch:
"""
@@
expression E1, E2;
@@
- &E2->ctr[E1]
+ rate_ctr_group_get_ctr(E2, E1)
"""

Change-Id: I2e064883ac6dafa89e41a297a886a9ebd26ce925
2021-06-04 17:27:05 +02:00
Keith
c12c1a6b0c vty: Fix optional display of pdp with mm-context
The vty is randomly including the pdp context when the vty
command 'show mm-context all' is issued without the pdp
parameter.
I do not know why, but I assume that relying on a true/false
test of argv[0] has unpredictable results.

Change-Id: Idcde4dd30a39625b24a1c3a38901349875e0949a
2021-05-20 04:41:22 +02:00
Pau Espin Pedrol
e5c8998f9c Support forwarding RIM messages over GTPCv1 EUTRAN<->GERAN
MMEs connect over Gn interface using GTPCv1 towards the SGSN in order to
exchange RIM PDUs by using "RAN Information Relay" GTPCv1 message type.
For more info, see 3GPP TS 29.060 sec 7.5.14.1 "RAN Information Relay"

In order to support it, this commit does the following:

* Uses new libgtp APIs to rx and tx RAN Information Relay messages. The
  same "gsn" object is reused, ie. the local GTPCv1 socket address used
  for exchanging messages against GGSN is reused.
* Adds a new "sgsn_mme_ctx" struct holding information about MMEs
  allowed by the SGSN, each one containing information about the GTP
  address it uses, the in/out routing based on TAI requests, etc. The
  set of MMEs and their config can be set up using new VTY node introduced
  in this commit.
* The RIM related code in SGSN is refactored to allow forwarding from
  and to several types of addresses/interfaces.

Depends: osmo-ggsn.git Change-Id Iea3eb032ccd4aed5187baca7f7719349d76039d4
Depends: libosmocore.git Change-Id I534db7d8bc5ceb19a2a6866f07d5f5c70e456c5c
Related: SYS#5314
Change-Id: I396450b8d8b66595dab8ff7bf41cbf964bb40d93
2021-05-19 11:45:05 +02:00
Pau Espin Pedrol
8969db7a49 gtp: Delete ctx upon receive UpdateCtxResp with cause Non-existent
Related: SYS#5435
Change-Id: Ic5f682a79663acc65fd364dd7a3a7cc554534414
2021-05-08 09:00:45 +00:00
Pau Espin Pedrol
0b0b59a8ff Drop unused GBRPOXY enum field
Change-Id: I85dbc65addfbb072a75b6f62fcc4306b7fbb6a91
2021-05-03 18:19:23 +02:00
Pau Espin Pedrol
888052e71c mm_state_{gb,iu}_fsm: Improve naming for detach event
The E_(P)MM_IMPLICIT_DETACH event was actually sent and handled when the
UE was considered to be detached, no matter the reason, be it due to
implicit detach, or Detach Request received, etc.
So, let's properly name the event to avoid confusions in the code.

Related: SYS#5389
Change-Id: I224ea9db80b4d96696934cea06349dab036f919b
2021-04-14 13:27:36 +02:00
Pau Espin Pedrol
913dbcd552 mm_state_{gb,iu}_fsm: Add missing license block, improve spec references
Change-Id: Ifcfd9c11005a388220c599e7b2f6901175141f1c
2021-04-14 13:18:31 +02:00
Pau Espin Pedrol
922684f318 gprs_ranap.c: Clean up code path releasing IU conn
Let's always send the event to the FSM and keep logic of whether it's a
good event to sent or not inside the FSM, not in the caller.
The logic is kept the same: if the event is not expected (not handled),
keep forcing free of the IU connection.
In theory this should never happen since only a PMM in Connected state
should have a established connection (hence only a PMM in Connected
state can have it released). In any case let's keep the safety check,
but let the FSM receive the event and log an error about unexpected
event, which is more interesting from debug point of view.

While at it, clean up the related logging line: There's no need to print
the imsi explicitly, since LOGMMCTXP already does it. Furthermore, print
the exact low level event which triggered the code path.

Related: SYS#5389
Change-Id: I45017562ea7f27c2248b7de56f99ce7ca88e89b2
2021-04-14 12:42:02 +02:00
Pau Espin Pedrol
3caa7f6d97 Iu: Drop timer X3314
This Iu timer is Osmocom specific, but is made to resemble T3314
timer from GERAN (also named READY timer).

The idea of this activity timer was to arm it whenever PMM state
transitions to CONNECTED, and then rearm it every time there's some
sort of activity, until there's none for some time, then we send a
Release Command to close the conn with the HNGBW/RNC. That's the
same principle as per spec-defined READY timer T3314.

However, there's still a fundamental problem with it: GTP-U in
GERAN passes through the SGSN, but in UTRAN, the GTP-U stream
goes directly from the HnodeB to the GGSN. Hence, there's no proper
way to re-arm this timer upon activity in UTRAN, basically because
the SGSN will never see (userplane data) activity. That explains why
the E_MM_PDU_RECEPTION event exists for mm_state_gb_fsm, but doesn't
exist for mm_state_iu_fsm.
As a result, the timer is currently never rearmed, which means it
will transition to IDLE always after 44 seconds (default value) once
it went into CONNECTED state.

In UTRAN, there is a SCCP connection for each subscriber between
RNC/hNB and SGSN. If the subscriber is no longer in the respective
state, the RNC/hNB should release that IuPS SCCP connection, whcih
in turn means the SGSN cleans up its state.
Furthermore, SCCP has a built-in IT (inactivity timer). So should
the RNC/hNB die, that timer would time out, and the SGSN-side local
SCCP stack (provider) wold send a RELEASE.ind for that connection
to the user (SGSN).

TLDR; this timer is not really needed and cannot be implemented
properly in UTRAN, so let's remove it.

Related: OS#5116
Change-Id: Ibc71829e417bf2dd0c27deb842369dd4f17010d6
2021-04-14 12:14:52 +02:00
Pau Espin Pedrol
223754fde5 mm_state_iu_fsm: T3314 expiry must lead to PMM IDLE, not PMM DETACHED
This Iu timer is Osmocom specific, but is made to resemble T3314 timer
from GERAN (also named READY timer). The READY timer mission is to make
the MM state transition from READY to STANDBY, which in PMM (UTRAN)
matches the transition from CONNECTED to IDLE.
Instead, the patch introducing the timer was making it transition to
DETACHED directly, but this was clearly not the intention:
* Detaching a UE after 44 seconds (default value for T3314) is overkill.
* The comment describing it says: "Iu User inactivity timer. On expiry
  release Iu connection". The release of Iu connection happens during
  the CONNECTED->IDLE transition (that's basically the difference between
  both states).

The transition CONNECTED->IDLE is done by means of calling
sgsn_ranap_iu_release_free(), which will eventually answer with a event
RANAP_IU_EVENT_IU_RELEASE from lower layers when the Release Complete is
received. At that point, osmo-sgsn code frees the connection and
transitions to IDLE state. This way we maintain the state according to
the connection existance.

Related: SYS#5389
Related: osmo-iuh.git Change-Id Iac822c74e56750dc40e94573eae0e20853ff68c0
Fixes: 3bad31bcb4
Change-Id: I7279102ad51b0c39eb6d04c129986984112d15cc
2021-04-13 20:36:06 +02:00
Pau Espin Pedrol
f025e582bb gprs_gmm.c: State proper GMM prefix logging rx/tx of GMM messages
Change-Id: I58af41acdc4a04870b4cf2ea34a272d46d896254
2021-04-13 11:58:59 +02:00
Pau Espin Pedrol
e8cd6856a5 mm_iu: Expect E_PMM_PS_ATTACH when in ST_PMM_IDLE
It can happen that the MS tries to attach while SGSN's MM Iu state is
ST_PMM_IDLE (eg because UE was hard rebooted). Since Attach is a
specific case of getting a Connection Established, also allow it as a
trigger to transit to state ST_PMM_CONNECTED.

Related: SYS#5389
Change-Id: Ia74a062ddc3052faad569f1428f0ddd02e5b188d
2021-03-25 17:58:07 +01:00
Pau Espin Pedrol
c67c90b47e mm_iu: Send event E_PMM_PS_CONN_ESTABLISH upon rx GMM SERVICE REQUEST
Attach event should only be triggered by rx Attach Request, not other
messages. Furthermore, currently E_PMM_PS_CONN_ESTABLISH is defined and
expected in FSM but not sent by anyone.
Also, The opposite transition is done by E_PMM_PS_CONN_RELEASE:

"""
MM_STATE_Iu(0)[0x81379b0]{Connected}: Received Event E_PMM_PS_CONN_RELEASE
MM_STATE_Iu(0)[0x81379b0]{Connected}: state_chg to Idle
...
MM(001010123456063/c8b8bd08) -> GMM SERVICE REQUEST MI(3367550216) type="signalling"
MM_STATE_Iu(0)[0x81379b0]{Idle}: Received Event E_PMM_PS_ATTACH
MM_STATE_Iu(0)[0x81379b0]{Idle}: Event E_PMM_PS_ATTACH not permitted
"""

Related: SYS#5389
Change-Id: Ica00891f91834522f4dea2508b62af34e4c4eca7
2021-03-25 17:58:03 +01:00
Pau Espin Pedrol
c26072a77f gmm_fsm: Expect E_GMM_COMMON_PROC_INIT_REQ when in ST_GMM_COMMON_PROC_INIT
Due to whatever errors, the MS may re-init the Common Procedure by
retransmitting a GPRS Attach Request while we are for instance aiting
for Identity to be resolved.

See this log:
MM(---/ffffffff) -> GMM ATTACH REQUEST MI(3903513414) type="GPRS attach"
GMM(gmm_fsm)[0x8136110]{Deregistered}: Allocated
GMM_ATTACH_REQ_FSM(gb_gmm_req)[0x81383c0]{Init}: Allocated
MM_STATE_Gb[0x8138ac0]{Idle}: Allocated
MM_STATE_Iu[0x8138bb0]{Detached}: Allocated
GMM(gmm_fsm)[0x8136110]{Deregistered}: Received Event E_GMM_COMMON_PROC_INIT_REQ
GMM(gmm_fsm)[0x8136110]{Deregistered}: state_chg to CommonProcedureInitiated
GMM_ATTACH_REQ_FSM(gb_gmm_req)[0x81383c0]{Init}: Received Event E_ATTACH_REQ_RECV
GMM_ATTACH_REQ_FSM(gb_gmm_req)[0x81383c0]{Init}: state_chg to CheckIdentity
MM(/fba673a2) <- GPRS IDENTITY REQUEST: mi_type=IMEI
UE(0x2){001-01-10422-99} Received GSM 04.08 message type 0x16, but no MM context available
GMM_ATTACH_REQ_FSM(gb_gmm_req)[0x81383c0]{CheckIdentity}: Timeout of T3370
MM(/fba673a2) <- GPRS IDENTITY REQUEST: mi_type=IMEI
[Failure to handle GSM48_MT_GMM_ID_RESP and subsequent retransmission of GPRS IDENTITY REQUEST happens a couple times here]
MM(---/ffffffff) -> GMM ATTACH REQUEST MI(3903513414) type="GPRS attach"
GMM(gmm_fsm)[0x8136110]{CommonProcedureInitiated}: Received Event E_GMM_COMMON_PROC_INIT_REQ
GMM(gmm_fsm)[0x8136110]{CommonProcedureInitiated}: Event E_GMM_COMMON_PROC_INIT_REQ not permitted
GMM_ATTACH_REQ_FSM(gb_gmm_req)[0x81383c0]{CheckIdentity}: Received Event E_ATTACH_REQ_RECV
[Here IDENTITY REQUEST is sent again, and this time MS answers ID RESPONSE back and goes forward]

Related: SYS#5389
Change-Id: I93d7d6bc694c84223a11d075d24c234b82b73389
2021-03-25 16:57:24 +01:00
Pau Espin Pedrol
ce0a0e9beb gmm: Expect E_VLR_ANSWERED when in ST_IU_SECURITY_CMD
GSUP message is sent immediately before moving onto state
ST_IU_SECURITY_CMD, so it's expected to receive a response for it, which
will trigger event E_VLR_ANSWERED being sent.
See following log showing the scenario:

"""
GMM_ATTACH_REQ_FSM(gb_gmm_req)[0x8137b88]{Authenticate}: Received Event E_AUTH_RESP_RECV_SUCCESS
MM(001010123456789/f8bab3dc) Requesting authorization
MM(001010123456789/f8bab3dc) Missing information, requesting subscriber data
MM(001010123456789/f8bab3dc) Requesting subscriber data update
SUBSCR(001010123456789) subscriber data is not available
SUBSCR(001010123456789) Sending GSUP, will send: 04 01 08 00 01 01 21 43 65 60 f3 28 01 01
GMM_ATTACH_REQ_FSM(gb_gmm_req)[0x8137b88]{Authenticate}: state_chg to IuSecurityCommand
SUBSCR(001010123456789) Received GSUP message OSMO_GSUP_MSGT_INSERT_DATA_REQUEST
SUBSCR(001010123456789) Will set PDP info, context id = 1, APN = 01 2a
SUBSCR(001010123456789) Updating subscriber data
MM(001010123456789/f8bab3dc) Subscriber data update
MM(001010123456789/f8bab3dc) Updating authorization (authenticate -> accepted)
MM(001010123456789/f8bab3dc) Got authorization update: state authenticate -> accepted
MM(001010123456789/f8bab3dc) Authorized, continuing procedure, IMSI=001010123456789
GMM_ATTACH_REQ_FSM(gb_gmm_req)[0x8137b88]{IuSecurityCommand}: Received Event E_VLR_ANSWERED
GMM_ATTACH_REQ_FSM(gb_gmm_req)[0x8137b88]{IuSecurityCommand}: Event E_VLR_ANSWERED not permitted
SUBSCR(001010123456789) Sending GSUP, will send: 12 01 08 00 01 01 21 43 65 60 f3 28 01 01
SUBSCR(001010123456789) Received GSUP message OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT
SUBSCR(001010123456789) Updating subscriber data
MM(001010123456789/f8bab3dc) Subscriber data update
MM(001010123456789/f8bab3dc) Updating authorization (accepted -> accepted)
sccp_sap_up(N-DATA.indication)
N-DATA.ind(2, 20 06 00 08 00 00 01 00 06 00 01 00 )
handle_co(dir=2, proc=6)
Transmitting RANAP CommonID (SCCP conn_id 2)
GMM_ATTACH_REQ_FSM(gb_gmm_req)[0x8137b88]{IuSecurityCommand}: Received Event E_IU_SECURITY_CMD_COMPLETE
GMM_ATTACH_REQ_FSM(gb_gmm_req)[0x8137b88]{IuSecurityCommand}: state_chg to WaitAttachComplete
"""

Related: SYS#5389
Change-Id: If348ff32faa4a709b59ee1b9b043883a7d46cf93
2021-03-25 16:35:07 +01:00
Pau Espin Pedrol
c8ace5a03c gmm: log GMM msg type name instead of number
Change-Id: I2dc6eb5bfb0f44caf2687e582d660f71fdd647a2
2021-03-25 16:03:05 +01:00
Pau Espin Pedrol
183e6c3367 ranap: log ranap iu event type name instead of number
Change-Id: If66e9d5989b46abe01855a5c1183d567d358abeb
2021-03-25 15:54:45 +01:00
Vadim Yanitskiy
8de4be261d main: resurrect removed 'ns' logging category as deprecated
This logging category has been removed completely in [1], and now
osmo-sgsn fails to start with old configuration files:

  There is no such command.
  Error occurred during reading the below line:
   logging level ns info

Let's accept it and print a deprecation warning.

Change-Id: I2036170af41db89484c299e18e0b703c97427dc1
Fixes: [1] Ia4723ab344ad6a1927029a2d5d0dda020266b39d
2021-03-14 20:59:08 +01:00
Daniel Willmann
6fd19da165 manuals: Regenerate counters/VTY through docker
Change-Id: I09b01d2e4bc7b1c17588100b16ac9f04cf72cf99
2021-03-12 07:27:24 +00:00
Harald Welte
adcf97d095 Remove bogus DNS log category
When we switched to the libosmogb NS2 implementation, we should have
removed the DNS category, as NS2 uses DLNS internally and hence DNS
is unused.

Change-Id: Ia4723ab344ad6a1927029a2d5d0dda020266b39d
Closes: OS#5058
2021-03-10 12:30:05 +00:00
Pau Espin Pedrol
80adb30e93 Bump version: 1.6.0.157-b05c1-dirty → 1.7.0
Change-Id: Ifa861bb0109f433b103a75d5140425bf19c66943
2021-02-23 19:39:45 +00:00
Harald Welte
ebd39830cb main: change initialization order
We must have initialized e.g. the NS protocol stack before calling
handle_options(), as that might want to dumpy the VTY XML, and it
can obviously only dump those nodes that are registered at that
point.

Change-Id: Icd1b8fb3f466cdace67ff0d4f7c85183d8266c41
2021-02-23 16:43:37 +01:00
Harald Welte
b05c1d0ce4 manuals: generate vty reference xml at build time
Move 'doc' subdir further down to "make sure" the osmo-bsc binary is built
before the docs

Rremove sgsn_vty_reference from the source tree.

In manuals//Makefile.am use the new BUILT_REFERENCE_XML feature recently added
to osmo-gsm-manuals, and add a build target to generate the XML using the new
osmo-sgsn --vty-ref-xml cmdline switch.

Change-Id: Ied75fdd13283aa592350994fb4febce06c213d3a
Depends: I613d692328050a036d05b49a436ab495fc2087ba
2021-02-23 15:52:54 +01:00
Harald Welte
999a776b70 main: add --vty-ref-mode, use vty_dump_xml_ref_mode()
Change-Id: I893fc869d5900eff8395bfded0c2fa3883c5a1e7
Depends: Ie2022a7f9e167e5ceacf15350c037dd43768ff40
Related: SYS#5359
2021-02-23 15:52:54 +01:00
Pau Espin Pedrol
11ccc4305d Fix nsei+bvci not updated on rx UL SNDCP data
msgid2mmctx() was already being called for signalling messages in
gsm0408_gprs_rcvmsg_gb() before calling gprs_gb_recv_pdu(), but it was
not called in sndcp_llunitdata_ind().

Let's move msgid2mmctx() inside gprs_gb_recv_pdu() since we want to
always update the nsei+bvci, regardless of message containing data or
control content.

This commit fixes the scenario where an MS changes to a new cell (PCU)
and then continues transmitting UL data. Prior to this patch, the SGSN
kept sending DL content to the old cell (PCU nsei+bvci) instead of the
new one even after the MS transmitted Ul content fro mthe new cell.

Related: SYS#4909
Change-Id: I2c14e1d65575f54212924f7c5f0a2f4c1b76ec81
2021-02-16 13:59:07 +01:00
Oliver Smith
901ed14c89 gbproxy: remove (moved to own repository)
New repository:
https://git.osmocom.org/osmo-gbproxy/

Related: OS#4992
Change-Id: I37f7cebaf2a06bd93627a452f5df44edcfc0f87a
2021-02-08 11:52:53 +00:00
Pau Espin Pedrol
4be5ab3707 sndcp: Fix struct bit fields on big endian
Change-Id: I30014bf84e7a69fa3d85d542d03e41d56506beb7
2021-02-04 12:49:40 +01:00
Pau Espin Pedrol
c999c223ae .gitignore: Ignore new autofoo tmp files
Change-Id: I20b03d40214fe1822aab8df01e3c79404a795f01
2021-02-04 12:48:17 +01:00
Philipp Maier
2ce050ba46 sgsn_rim: Add routing for (GERAN) BSSGP RIM messages
The SGSN currently does not forward BSSGP RIM messages.

Related: SYS#5103
Depends: libosmocore Icd667f41d5735de56cd9fb257670337c679dd258
Change-Id: I6fde8ab8955660b48000ca1b650cfc7c7b2e24ba
2021-01-28 23:20:31 +01:00
Alexander Couzens
43e5f8a2c6 follow libosmocore/gprs_ns2 API changes (gprs_ns2_dynamic_create_nse)
The call gprs_ns2_dynamic_create_nse has been removed because it
was a workaround for the old/dropped vty api.

Depends-on: Ie924ead6da17657f3da334068c8ada82c8845495 (libosmocore)
Change-Id: Ie636cfd18d6d43da0e42f2c2de68dfa5c571d55c
2021-01-28 21:19:59 +00:00
Alexander Couzens
caf73b803c sgsn: migrate to the new gprs_ns2_vty configuration
Change the whole vty configuration for NS to be more flexible
and support more setups. Old configurations are invalid.

API change which must be synchronized with libosmocore

For further information see:
https://osmocom.org/projects/libosmocore/wiki/Network_service_(NS)

Depends-on: I8c3f2afecc74b78f7f914f7dce166cbcb63444eb (libosmocore)
Change-Id: Ie9306ab4d4738c2c57a69987086e22771b30657e
2021-01-28 21:19:59 +00:00
Alexander Couzens
0018d3e0ec gbproxy: follow gprs_ns2 API vty changes
The gprs_ns2_vty2 has been renamed to gprs_ns2_vty. The old
vty has been complete dropped.

API change which must be synchronized with libosmocore.

Depends-on: I8c3f2afecc74b78f7f914f7dce166cbcb63444eb (libosmocore)
Change-Id: If5bd6b86e130772e6c93d640b0c637985416136d
2021-01-28 21:19:59 +00:00
Daniel Willmann
f955d078ed manuals/gbproxy: Move pooling to separate chapter
Change-Id: Ie2ad652c8261ce56cb2ed1a6f16a81486ccdf063
Related: SYS#5115, SYS#5005
2021-01-28 20:57:16 +01:00
Daniel Willmann
93ccc3cf5d manuals/gbproxy: MSC -> SGSN for pooling chapter
Mostly just change the chapter so it makes sense for gbproxy. Some todos
are still left

Change-Id: I905835c2be7be43fe376fbc9d743107948c7e6d4
Related: SYS#5115, SYS#5005
2021-01-28 20:57:16 +01:00
Daniel Willmann
10e0fcaae2 manuals/gbproxy: Add osmo-bsc MSC pooling chapter from Neels as a base
Related: SYS#5115, SYS#5005
Change-Id: I930f5df847ea6f40d0ee0c75dd25b6dd20e00839
2021-01-28 20:57:16 +01:00
Daniel Willmann
592eb140f0 manuals/gbproxy: Update configuration chapter
Change-Id: I01f8d47f9fa384a2528ddf2e6c936ff28d11409e
Related: SYS#5115, SYS#5005
2021-01-28 20:57:16 +01:00
Daniel Willmann
c7b6aabac1 Rename OsmoGbPROXY -> *Proxy
Change-Id: I7542ac1d5242f1784146de2df7cecaf70fe93c6c
Related: SYS#5115, SYS#5005
2021-01-28 20:57:16 +01:00
Daniel Willmann
873c8a55e7 manual/gbproxy: Update overview chapter
* Remove mention of features that are no longer supported
* Update the data model

Related: SYS#5115, SYS#5005
Change-Id: Icb9095f4002f2a0a4562fccecae109075cb93c7b
2021-01-28 20:57:16 +01:00
Harald Welte
e0876bda26 gbproxy: Avoid depending on any of the SGSN code
The last remaining functin of the SGSN code base we used was
gprs_gb_parse_tlli().

Let's simply copy this function over and become  self-contained.

This would allow migrating osmo-gbproxy to a separate repository.

Change-Id: I6f3f86581b47ad71a3d97f07611a2e2709876d69
2021-01-28 19:14:32 +01:00
Alexander Couzens
21afdf9a32 follow libosmocore/gprs_ns2 API changes of GPRS enums
All gprs_ns2 enums have now GPRS_NS2 as prefix.

API change which must be synchronized with libosmocore

Depends-on: I548ff12f7277cbb7e1a630a3dc02b738ce89be72 (libosmocore)
Change-Id: I1af704cdd62ddaff4304479b837dc185b80d7dd6
2021-01-27 21:07:01 +01:00
Daniel Willmann
c09cb29d78 gbproxy: Fix radio status routing by TMSI
If a radio status message contains a TMSI it should be routed as if it
was a TLLI. Convert the TMSI to (foreign) TLLI so NRI-routing works.

Both foreign and local TLLIs are routed the same.

Fixes: OS#4954
Change-Id: Ifd64f02fa16b44f8e2e19eb8ba973f50a829ead5
2021-01-22 12:42:14 +01:00
Daniel Willmann
6ad4040f55 gbproxy: Improve log messages in gbproxy_select_sgsn
Change-Id: Id7bc755b90c35ed7c8cfa8408073e2866d639f2d
Related: OS#4954
2021-01-22 12:36:13 +01:00
Daniel Willmann
45bf92feb4 gbproxy: Print the correct message type for dummy paging/paging reject
Change-Id: I5337abb27587fa2e8320b5bfc3765c9de5c57f6c
2021-01-19 11:37:55 +01:00
Daniel Willmann
d367b8bc78 gbproxy: Use IMSI cache for PTP paging and implement DUMMY_PAGING_PS
Some code was missing to support PAGING_REJECT and DUMMY_PAGING_PS over both PTP
and signalling. This commit adds the missing pieces, notably:

* Use and route according to the IMSI cache for paging on PTP
* Ensure DUMMY_PAGING_PS is broadcast if no routing area is included

Change-Id: I7243e0d4470cb62fa6db36d26002ccd6542b5147
Related: OS#4951, OS#4472
2021-01-19 09:59:01 +01:00
Harald Welte
5037b6817f gb_proxy: Don't use orphan log subsystem DPCU
DPCU is defined in debug.h, but never registered as log subsystem,
so we shall not use it.  Also remove other similar "orphan" log
subsystems from debug.h

Change-Id: I8be54ee49e10d4004128352613923c4700063aa3
2021-01-18 20:32:25 +00:00
Daniel Willmann
d245c0e542 gbproxy: Add VTY commands to query the TLLI/IMSI cache
OsmoGbProxy# show gbproxy tlli-cache
TLLI cache timeout 10s
 TLLI c2200024 -> NSE(02001/BSS) valid 10s
TLLI cache contains 1 entries

OsmoGbProxy# show gbproxy imsi-cache
IMSI cache timeout 10s
 IMSI 262420000001000 -> NSE(00102/SGSN): valid 5s
 IMSI 262420000000000 -> NSE(00101/SGSN): valid 3s
IMSI cache contains 2 entries

Change-Id: I03f1050573de9b241eb4fa82460c434155c15c6a
Related: OS#4951, OS#4472
2021-01-18 18:47:41 +01:00
Daniel Willmann
4380f94cf2 gbproxy: Define and use help string for gbproxy
Change-Id: Ic9336c83147903e5af6622179f9394130f969a77
2021-01-18 18:46:32 +01:00
Daniel Willmann
0d170d61aa gbproxy: Fix VTY cmd name
Change-Id: I5bb5f7cf93779a7a07965f2f35fdb59a7a2b731b
2021-01-18 18:46:32 +01:00
Daniel Willmann
fb5ccb468a gbproxy: Remove unused variable assignment
Change-Id: I79684e0b27211d756912a63be5cae890ea44be82
2021-01-17 13:51:57 +01:00
Daniel Willmann
b96d5a6ead gbproxy: Move helper function to a more logical place
Change-Id: I3b39991fe2441334aaa9dda6c33c0b7b4484e455
2021-01-17 13:51:57 +01:00
Daniel Willmann
6ff8d21fed gbproxy: Use C-style comments
Change-Id: Ia3d27ef79a3370147395e7441149fd1231a760d5
2021-01-17 13:51:57 +01:00
Daniel Willmann
5b1122f717 gbproxy: Use IMSI cache to handle PAGING_PS_REJECT
Change-Id: I7d91d9ecfba757dc81edcf05efb7a2158348099d
Related: OS#4472, OS#4951
2021-01-17 13:51:57 +01:00
Daniel Willmann
914484d561 gbproxy: Implement IMSI cache
When SGSN pooling is enabled we need to route some responses based on
IMSI back to the correct SGSN, e.g. PAGING_PS_REJECT.

The IMSI cache keeps track of this IMSI <-> NSE(SGSN) mapping.

Change-Id: If0a8d6cc1d63f2fb2c395cc5d4373a915bc2cb87
Related: OS#4951, OS#4472
2021-01-17 13:51:57 +01:00
Oliver Smith
b6343a72d8 contrib/jenkins: don't build osmo-gsm-manuals
Related: OS#4912
Change-Id: I3fc43b1afb7cdfd2b78c062e36ccf2491700f988
2021-01-14 14:58:41 +00:00
Daniel Willmann
ef0c2a4b85 gbproxy: Increase TLLI cache timeout to 10s
The range of SUSPEND/RESUME timers T3/T4 is up to 10s so we should keep
the cache entries valid for this time.

Fixes: OS#4895
Change-Id: I9e88e49981098831f3255938deb868f4503f650f
Related: SYS#5235
2021-01-13 18:21:48 +01:00
Daniel Willmann
02b24c5a44 gbproxy: Implement TLLI cache and use it for SUSPEND/RESUME
When routing a SUSPEND/RESUME we need to keep track of where it came
from so we can send the (N)ACK back to the correct BSS. Use the TLLI
which is present in both messages to cache and retrieve the correct BSS.

A timer runs every two seconds and expires entries that are older than
the timeout (hardcoded to 5 seconds for now).

Related: SYS#4865, OS#4472
Change-Id: I42adf70f560d2bb358a9e1c7614281e8d2967568
2021-01-11 15:09:05 +01:00
Alexander Couzens
cd7c7a74b7 configure.ac: define a c standard instead of using the compilers default
Change-Id: I9867adbed211db0a7b42ac3557f56c3042a67936
2021-01-08 02:32:33 +00:00
Daniel Willmann
ddb3fbb0f2 Fix gbproxy_sgsn_by_tlli wraparound
Change-Id: I74ecb655f4d433f7ac14d00d934d237325aab606
Related: SYS#4865, OS#4472
2021-01-05 18:29:39 +01:00
Vadim Yanitskiy
e245677cdd gb_proxy_peer: fix NULL pointer dereference in gbproxy_sgsn_alloc()
LOGPSGSN_CAT() dereferences sgsn->nse in order to get NSEI.

Change-Id: I1c592dd6f0da5f167290f38de3b30a1a04c4313d
Fixes: CID#215868
2021-01-05 15:26:30 +01:00
Vadim Yanitskiy
1c33e4af05 gb_proxy_peer: sgsn can never be NULL in gbproxy_sgsn_by_nri()
Redundant check makes Coverity think that sgsn can be NULL...

Change-Id: Iffdeb18e0a5575a2a09129eed9b8a41c3340dcbf
Fixes: CID#215870
2021-01-05 14:38:05 +01:00
Daniel Willmann
3844da98f8 gbproxy: Add VTY command to override the node selection function
This is mainly useful when testing SGSN pooling

Change-Id: I2894320413dbd0b9aec9a9bc9b88ce7cdeed206b
Related: SYS#5115, OS#4472
2021-01-04 18:33:52 +01:00
Daniel Willmann
dee0bcc8e9 gbproxy: Add config option to name an SGSN
This is useful for logging and configuration to identify an SGSN by name

Change-Id: I2a3410dd9bebb242957e13a63ed70e447204203c
Related: SYS#5115, OS#4472
2021-01-04 18:33:52 +01:00
Alexander Couzens
51730f7a8c gbproxy: use ns2 vty2
The new gprs_ns2 vty2 support ip-sns and reorganize the
network service configuration

Depends: I163279cf57e84198dc8c53e1c109f5a9474670e9 (libosmocore)
Change-Id: I2a18dcf035f1fc7304a0c7c7c83b5e8e15429d2b
2021-01-04 16:27:41 +00:00
Alexander Couzens
f23e2db752 sgsn: Use the new NS2 api
The new NS2 api supports NSE with multiple NS-VC and contains a NS-VC
fsm. FR/GRE support is not working.
The configuration is compatible except for FR/GRE.

Relates: OS#4629
Depends-on: Iaad7b53d44338e5dd81dc2202f23bdcb715af804 (libosmocore)
Depends-on: I6cef42749555e577d5573f2ed8b8bce4cf842a98 (libosmocore)
Change-Id: I92a3bcaf166b091a22d74c7c1586964d33d7cc9d
2021-01-04 16:06:13 +00:00
Harald Welte
8a33528854 gbproxy: Fix build on Deiban 8
[  258s]   CC       gb_proxy.o
[  258s] gb_proxy.c: In function 'gbproxy_select_sgsn_bvc':
[  258s] gb_proxy.c:293:2: error: 'for' loop initial declarations are only allowed in C99 or C11 mode
[  258s]   for (int i = 0; i < ARRAY_SIZE(cell->sgsn_bvc); i++) {
[  258s]   ^
[  258s] gb_proxy.c:293:2: note: use option -std=c99, -std=gnu99, -std=c11 or -std=gnu11 to compile your
code

Change-Id: I717410b11f1ee38d49e9ca5af593cb59a244ae0a
2020-12-30 12:13:56 +01:00
Daniel Willmann
00c1f91ed7 gbproxy: Add comments to sgsn functions
Change-Id: I8c96308045112f25292b0e57c306d8486a2524cc
2020-12-29 16:41:43 +01:00
Daniel Willmann
8d382c5337 gbproxy: Add SGSN pooling support
Change-Id: I58b9f55065f6bd43450e4b07cffe7ba132b1fd9b
Related: OS#4472
2020-12-29 16:41:29 +01:00
Daniel Willmann
ef3c9af0f9 gbproxy: Add SGSN NRI configuration
In order to support SGSN pooling we need to configure the various NRI
parameters such as the bitlen, NULL NRI, and which NRIs are assigned to
which SGSN.

Related: OS#4890, OS#4472
Change-Id: Id67592aa7712e5e04e7264b2fb8f26d57eb7e69e
2020-12-29 16:38:49 +01:00
Harald Welte
5a21f07dff gbproxy: Add "show gbproxy cell ..." VTY command
This allows the user to inspect CELL related gb-proxy state.

Change-Id: Iad1e8bbc358df9a3b3392404a70445a169dfebd5
2020-12-22 19:33:34 +00:00
Daniel Willmann
ea0b5d0df6 gbproxy: Fix confusing log message in gbprox_relay2nse
This function is now used to transmit messages in both directions,
BSS->SGSN and SGSN->BSS.
Print the actual direction in the logs

Change-Id: I31682156dfe88f7ca121a711968e625caed8bd5e
Related: OS#4472
2020-12-22 12:32:16 +01:00
Daniel Willmann
3054213e87 osmo-gbproxy: Initialize all hash_maps
Change-Id: I9578af77a7b2f61b57c918a703768ca20221c294
Related: OS#4472
2020-12-21 18:44:08 +01:00
Alexander Couzens
3326ba7d4c sgsn: check for NULL of gprs_subscr_get_or_create()
gprs_subscr_get_or_create() can return NULL if no memory can
be allocated. Detected by the compiler on Ubuntu s390x.

Signed-off-by: Steve Langasek <steve.langasek@ubuntu.com>
Signed-off-by: Alexander Couzens <lynxis@fe80.eu>

Change-Id: I86b3652d46bdd581fe6cbab16b52395a0daaa082
2020-12-15 11:57:16 +01:00
Harald Welte
b6b2f14197 gbproxy: rename vty command "show gbproxy ..." to "show gbproxy bvc ..."
we have other objects to show, and the orthogoanl way to do this is
to rename the existing one.

Change-Id: I7836a37533a2de81720acedda712d61f429df12c
2020-12-14 12:21:17 +01:00
Harald Welte
959f77e34b gbproxy: Improve VTY state introspection
* allow to print not only BSS-side BVCs, but also SGSN-side
* differentiate between SIG and PTP BVC
* print the actual BVC FSM state name instead of just UNBLOCKED/nothing

Change-Id: I8e09a9dc296b15094d191b0451d04457c815d116
2020-12-12 19:12:52 +01:00
Harald Welte
9e917647ae gbproxy: Implement scaling of BVC flow control in SGSN pool
When there are multiple SGSNs inside a pool, we need to decide
how much of the per-BVC capacity advertised by the BSS in its
BVC-FLOW-CONTROL we should announce to each of the pool members.

A conservative approach would be to advertise 1/num_sgsn, but
there may also be use case where over-provisioning (announcing more
than an equal share of the capacity) is useful.

Hence, let's introduce "pool bvc-flow-control-ratio <1-100>" in order
to allow the administrator to decide.

Related: OS#4891
Change-Id: Ibe5addf657e7237499ca0205bacfe999ecd1e771
2020-12-12 19:12:18 +01:00
Harald Welte
784c59f87e gbproxy: Add FSM related VTY commands
Change-Id: Id84ce52722d705eb25a12ee6f108ad3107a9f8d2
2020-12-12 17:33:49 +01:00
Harald Welte
1aa0ae9db1 gbproxy: Fix segfault when receiving PAGING for unknown destination
The 'nse' variable had been used both as the input argument of the
SGSN-side NSE, as well as a loop iteration variable.  Let's separate
this clearly.

Closes: OS#4904
Change-Id: I375a219cd72eb11a9a0cb7d55a3efb7b83b771ac
2020-12-12 16:16:57 +01:00
Harald Welte
cab8588242 gbproxy: (Re)allocate SGSN-side PTP BVC even if CELL already exists
After a SGSN-side RESET of the SIG-BVC, all PTP BVC on the SGSN side
are gone.  However, the CELLs and the BSS side BVCs continue to exist
(as there may be other SGSNs).

So if a PTP-BVC RESET from the BSS side arrives in such a situation,
and we can find a matching CELL, we still need to check if we need
to create any SGSN-side PTP BVCs instead of simply being happy with
the CELLs already existing.

Change-Id: I1d1562e421082fa4399c73ac31290e4c95718e49
Closes: OS#4903
2020-12-12 15:18:05 +01:00
Harald Welte
4b4c997dc5 gbproxy: Copy RA-ID from BSS side BVC to CELL and SGSN-side BVC
Change-Id: I18669f269c4a959fcfa51885aafb719b662a7f8a
Related: OS#4894
2020-12-12 15:17:33 +01:00
Daniel Willmann
c4c1db9e78 gbproxy: Fix bvci check in gbprox_rx_ptp_from_*
The check for bvci in _rx_ptp_from_* was always false.

Change-Id: I16a0284ba3201c146c307db6997a416589d7e693
Related: OS#4472
2020-12-10 18:11:47 +01:00
Harald Welte
61ff273365 gbproxy: Implement handling of BVC Flow Control
We must locally terminate + acknowledge any inbound BSSGP-FC-BVC,
and ourselves trigger the transmission of BSSGP-FC-BVC to each
SGSN in the pool.

Related: OS#4891
Depends: libosmcoore.git Ie59be6761177c43456898be9148727f15861a622
Change-Id: Ib6495e5de4bfcf748a98e08743d1a8f2565f8b69
2020-12-10 18:09:21 +01:00
Harald Welte
bf69833b6d gbproxy: Don't create an extra msgb copy for SGSN DL SIG
That copy may have made sense while we were doing patching/buffering,
but we're not doing any of that anymore.

Related: OS#4472
Change-Id: I207a869ffac8bf60104f80f9ed58faf0021e5e95
2020-12-10 18:08:58 +01:00
Harald Welte
7cb76a4321 gbproxy: Introduce new DOBJ log category; log object allocation/release
Related: OS#4472
Change-Id: I43bcbcda8667d193e7a17fd8e8e9109597b01484
2020-12-10 18:06:34 +01:00
Harald Welte
c91f53ca0a gbproxy: Use "(nsei << 16) | bvci" as rate_ctr_group index
As we now have gbproxy_bvc on both the SGSN and the BSS side
with the same BVCI, using the BVCI alone will no longer render
unique indexes.

Related: OS#4472
Change-Id: I13f3c9e69562a56ad7d3742fdeb2ba48f134fdaa
2020-12-10 18:06:06 +01:00
Harald Welte
5687ae65fa gbproxy major rewrite for SGSN pool support
Rewrite of a large part of osmo-gbproxy in order to prepare
for SGSN pool support.  The amount of changes are of such fundamental
nature that it doesn't make sense to try to split this into hundreds
of individual changesets.

Related: OS#4472
Change-Id: Ie0746f17927a9509c3806cc80dc1a31d25df7937
2020-12-10 18:05:52 +01:00
Daniel Willmann
7c86a1efce mm_state_gb_fsm: Handle implicit detach from mm_standby
Change-Id: I63d04a2dcdc17b4df6616c515641c435d919c787
Related: OS#2737
2020-12-10 15:25:51 +00:00
Harald Welte
453a51d1a1 migrate to DLBSSGP as log sub-system for BSSGP
Change-Id: I69ee10b6fad1da2053cf6f3ae99d3ecf62a144ce
Depends: libosmocore.git Change-Id I506190aae9217c0956e4b5764d1a0c0772268e93
2020-12-10 15:42:15 +01:00
Harald Welte
a54ed46bac gbproxy: Log FSM timeouts
Change-Id: I5c48e42083ab6f8622808457ca3f017adf35cdff
2020-12-07 18:30:01 +01:00
Harald Welte
052d855449 gb_proxy: Use osmo_tlv_prot_parse() to validate mandatory IEs
We recently introduced code to libosmocore which allows us to validate
the mandatory IE presence (and length) in a generic way.  Let's use it.

Change-Id: I0ea3f5f9566d9bf5a8429c3ee748e3e90cda6cd7
Depends: libosmocore.git I7e4226463f3c935134b5c2c737696fbfd1dd5815
2020-12-07 18:22:20 +01:00
Harald Welte
11ad5713f2 gbproxy: use gbprox_relay2peer() whenever possible
gbprox_relay2peer() is a small wrapper around gbprox_relay2nse(),
but as it manages the transmit error counter, we should use it whenever
possible.

Change-Id: I85ab49ca0a25dd7c54b88c4fdc8838843e6d2209
2020-12-07 18:22:20 +01:00
Harald Welte
d651edcce0 gb_proxy: Introduce more validation / constraint checks
* ensure the BSSGP PDU header length before reading pdu_type field
* ensure we never process uplink PDUs in downlink and vice-versa
* ensure we never proceses PTP PDUs on SIGNALING BVCI and vice-versa

Change-Id: I6e40aed0283f1a0860ab273606605f7fb28717cf
Depends: libosmocore.git I7e4226463f3c935134b5c2c737696fbfd1dd5815
2020-12-07 18:22:20 +01:00
Harald Welte
56f5e74d7d gbproxy: Delete gbproxy_test
The test is actually performing invalid operations such as
sending empty NS packets without even a BSSGP header - and assumes
that gbproxy should route those.

Given that we have a much more comprehensive tset suite in
GBProxy_Tests.ttcn in osmo-ttch3-hacks.git, it makes sense to remove
the testsuite.  It may contain many more wrong assumptions, or
assumptions that no longer hold true with the "gbproxy 2020".

Change-Id: I053aebab6bf5d0ee955f2221bf27925b36140cf3
2020-12-07 18:22:20 +01:00
Harald Welte
4bf53ef19a gb_proxy: cosmetic: Use function rather than open-coding is_sgsn
Change-Id: Id41d74ebd41e5084377a986f4a1acd53cae12bc1
2020-12-05 17:50:50 +01:00
Harald Welte
91bb720449 gbproxy: Remove patching, TLLI-tracking and SGSN2 support
Those features were introduced a long time ago for one specific use
case at one specific user, and they are not needed anymore.  They
complicate the code base significantly and are hard to maintain with
all the upcoming modifications regarding SGSN pool supoprt.

Change-Id: Id9cc2e1c63486491ac5bb68876088a615075fde6
2020-12-05 14:05:36 +01:00
Harald Welte
993d3f4d9a gbproxy: convert nse->bvcs from llist_head to hashtable
For the common lookup-by-bvci, this should reduce the computational
complexity significantly.

Depends: libosmocore.git I8ef73a62fe9846ce45058eb21cf999dd3eed5741
Change-Id: Ic8e9279fd61a3c514fc3203429f36a468f0e81d3
2020-12-05 13:55:06 +01:00
Harald Welte
78db244b42 gbproxy: convert bss_nses from llist_head to hashtable
For the common lookup-by-nsei, this should reduce the computational
complexity significantly.

Depends: libosmocore.git I8ef73a62fe9846ce45058eb21cf999dd3eed5741
Change-Id: Idbb6a362332bb6e3ce22102e7409ae80d0980f44
2020-12-05 13:49:37 +01:00
Harald Welte
0e1b791c81 gbproxy: Rename gbproxy_cfg.nses to gbproxy_cfg.bss_nses
We will soon also have a list of sgsn-side NSEs, and we need to
differentiate those.

Change-Id: If5accec0c70c01b88927ea07beba6f6488bd9d5a
Related: OS#4472
2020-12-05 12:08:10 +01:00
Harald Welte
8cd74407ab gb_proxy: Rename gbproxy_peer to gbproxy_bvc
I cannot really read the code while it contains its historical weird
naming.  A "peer" used to be a strange amalgamation of NSE + BVC,
while in reality we can have any number of BVC on top of each NSE.

We recently started to split the peer into a gbproxy_nse_peer + gbproxy_peer.
This takes it one step further and renames gbproxy_peer to gbproxy_bvc,
as that's really what it is.

Change-Id: Iae01067282a6401f6af4cab731202872d2cdb080
2020-12-05 12:06:42 +01:00
Harald Welte
6c4c6f08ae gb_proxy: Use TLVP_PRES_LEN instead of TLVP_PRESENT
With TLVP_PRESENT we only check if a tiven TLV/IE is present,
but don't verify that it's length matches our expectation.  This can
lead to out-of-bounds reads, so let's always use TLVP_PRES_LEN.

Change-Id: I1519cff0f6b2fe77f9a91eee17e0055d9df1bce6
2020-12-05 11:44:39 +01:00
Harald Welte
fb7f8c5f07 gbproxy: Send BVC-STATUS if BSS sends us BVC-RESET without mandatory IEs
Change-Id: I198ca70f5e0947735f76d32cd9d3eed159349a94
2020-12-05 11:44:38 +01:00
Daniel Willmann
9a2fc908df gbproxy: Delete gbproxy_nse in delete-gbproxy-peer VTY command
The gbproxy_nse is created when the signalling BVC is resetted. When
we delete all bvcs of an nsei we need to remove it as well.

Change-Id: I997b29fef93188565f81bd403bc68840473958c3
Related: SYS#5002
2020-12-04 17:49:19 +01:00
Daniel Willmann
e794c1f00b gbproxy: Allow gbproxy_nse_free(NULL)
Calling free() with a null-pointer is usually supported and does
nothing. Change gbproxy_{peer,nse}_free() to reflect that behaviour.

Change-Id: Ia32084f81ca8f8cb9ddea3adabd4b44fd766f1c7
2020-12-04 17:49:19 +01:00
Daniel Willmann
bd356a6d84 gbproxy: Add newline to log message
Change-Id: I91a076872b5d744a237f6d325857b95362455e8d
2020-12-04 01:31:05 +01:00
Daniel Willmann
e8c8ec9683 gbproxy: Add BVC log filters
Since gbproxy doesn't use bssgp_rcvmsg from libosmocore we need to
implement our own filtering.

Change-Id: I4d1b57b89990945d307f27a58a7f630be0253d5b
Related: SYS#5232
2020-12-04 01:31:05 +01:00
Harald Welte
55253716d2 gbproxy: Cosmetics: use longer lines
Change-Id: I9426bf4be2faa0da7848cb102b20cc539948b3f5
2020-12-02 23:06:37 +01:00
Harald Welte
1239cf457e gb_proxy: Slightly restructure processing of BSS-originated BVC-RESET
* explicit else clause rather than implicit
* don't continue processing if mandatory BVCI missing from message

Change-Id: I038576b91ae1ece149149d8663de7b8495d24e06
2020-12-02 23:03:22 +01:00
Harald Welte
ac44d6b2a2 gbproxy: Move BSS-side BVC-RESET processing to its own function
The switch clause was getting a bit too long/nested, let's add
a separate gbprox_rx_bvc_reset_from_bss() function.

Change-Id: If262566e275cca96035045d1194ce102c0942eb6
2020-12-02 23:01:47 +01:00
Harald Welte
c8d98ac8f9 gb_proxy: Broadcast SGSN-INVOKE-TRACE and OVERLOAD
Both BSSGP messages appear from the SGSN in downlink on BVCI=0.

We must send a copy of this message to each of the BSS side NSEs.

Change-Id: Ia19791b143989eb1490f461d88b9edbd8e3b82be
Closes: OS#4875
2020-12-02 22:45:42 +01:00
Daniel Willmann
6626bbc215 gbproxy: Add todos encountered while going through the code
Change-Id: I8c3a788f008d3cb2d067d974c2b1b9ca45185d8d
2020-12-02 22:42:48 +01:00
Daniel Willmann
103a7ec033 gbproxy: Change generic LOG messages so BVCI/NSEI fmt is consistent
We actually need to alter our compiler flags to avoid -Werror=trigraphs
creating trouble:

gb_proxy.c: In function ‘block_unblock_peer’:
gb_proxy.c:875:37: error: trigraph ??) ignored, use -trigraphs to enable [-Werror=trigraphs]
  875 |   LOGP(DGPRS, LOGL_ERROR, "BVC(%05u/??) Cannot find BSS\n",
      |

Fixes: SYS#5233
Change-Id: I93296353dd964602699480faae1248096e331c6a
2020-12-02 22:42:42 +01:00
Daniel Willmann
6e8ed2784e gbproxy: Use LOG macros for NSE/BVC
Change-Id: If445f18bc8390c338b5aeb9085951ea392e68b3a
Related: SYS#5233
2020-12-02 17:47:49 +01:00
Daniel Willmann
7418797027 gbproxy: Add logging macros for NSE and BVC
Change-Id: Ibb2bcf3344bdc750869223b4c4861b4bbc6f417c
Related: SYS#5233
2020-12-02 17:17:17 +01:00
Harald Welte
d97ff681c3 gb_proxy: More precise + readable log messages
* use string representations instead of magic numbers whenever possible
* make text actually describe the specific case, rather than copy+paste
* proper order (foobar indication) not (indication ..... foobar)

Change-Id: I232038da26a9963763c5fc9051b87c9182b27d94
2020-12-01 11:56:57 +00:00
Pau Espin Pedrol
83142beca2 gmm: Introduce comment to ease addition of Network feature support IE later
Change-Id: I131cba3de3c80c61d5549e7c31b4eacaaeddb040
2020-12-01 11:47:58 +00:00
Pau Espin Pedrol
8c3d7fd263 gmm: fix build without define PTMSI_ALLOC
Change-Id: Idcac01c4634af81ef884dc2b1b20dec3f8d12236
2020-12-01 11:47:58 +00:00
Daniel Willmann
9e583c8d89 gbproxy: Separate function to move gbproxy_peer to different nse
Change-Id: I0a8b1e4b78384ea99d50109f050ca501b18ba5d9
Related: SYS#5226
2020-11-30 18:30:35 +01:00
Daniel Willmann
5937dfd39f gbproxy: Only send paging to each matching NSE once
Fixes: SYS#5226
Change-Id: Ia33e7816b354266b9d2659ef96b798db60c134f3
2020-11-30 18:30:35 +01:00
Daniel Willmann
cafa3881ad gbproxy: Ensure BVC0 is reset before handling PtP BVCs
Change-Id: I9c67f973f7bca00e8eb22a024ef2282c007dd84b
Related: SYS#5226
2020-11-30 18:30:35 +01:00
Daniel Willmann
447ad441e6 gbproxy: Add NSE peer that can have multiple gbproxy_peers
We want this level of indirection to support multiple BVCs per NSE. The
current code assumes that an NSE only has one BVC which breaks messages
on the signalling BVC which should only be sent once to an NSE
regardless of the number of BVCs it contains.

Change-Id: I97cc6c8f8c0f1b91577ab8f679c4ae217cc88076
Related: SYS#5226
2020-11-30 18:30:35 +01:00
Daniel Willmann
f7a1aed0e6 gbproxy: Remove test testing NSVCI change
This was overlooked in commit 82182d which already removed lots of
NS-specific code in gbproxy_test.c

From that commit message:
"""
Since NS2 has a different abstraction we mock up the prim send/recv
functions and don't test NS like the old tests did.
"""

Change-Id: Ic1d7e646e633c9fa62812f5005ed10c0108a06f2
Related: SYS#5226
2020-11-30 18:26:38 +01:00
Harald Welte
eb4233e505 gb_proxy_peer: Add some FIXMEs regarding invalid assumptions
Change-Id: Ibf3d4a3bd58e706dfa44e8cc9ff4823a7759dea5
2020-11-27 23:15:18 +01:00
Harald Welte
2636e89ff0 gbproxy: Pass TLLI as LSP towards NS to facilitate load sharing
Change-Id: I6aef26c126b330a393fc2be5f558b6d5f1d9f7f4
2020-11-27 23:15:18 +01:00
Pau Espin Pedrol
bcd7709452 sgsn: generate coredump and exit upon SIGABRT received
Previous code relied on abort() switching sigaction to SIG_FDL +
retriggering SIGABRT in case the signal handler returns, which would
then generate the coredump + terminate the process.
However, if a SIGABRT is received from somewhere else (kill -SIGABRT),
then the process would print the talloc report and continue running,
which is not desired.

Change-Id: I65f70a53b6982bff9ea4bd6ff786d8a2f8181eac
Fixes: OS#4865
2020-11-25 18:28:55 +01:00
Pau Espin Pedrol
7ffc6603e2 gtphub: generate coredump and exit upon SIGABRT received
Previous code relied on abort() switching sigaction to SIG_FDL +
retriggering SIGABRT in case the signal handler returns, which would
then generate the coredump + terminate the process.
However, if a SIGABRT is received from somewhere else (kill -SIGABRT),
then the process would print the talloc report and continue running,
which is not desired.

Change-Id: I1cab4a716cf2fda6353f698888edbcec6228d78b
Fixes: OS#4865
2020-11-25 18:22:21 +01:00
Pau Espin Pedrol
826eaa327b gbproxy: generate coredump and exit upon SIGABRT received
Previous code relied on abort() switching sigaction to SIG_FDL +
retriggering SIGABRT in case the signal handler returns, which would
then generate the coredump + terminate the process.
However, if a SIGABRT is received from somewhere else (kill -SIGABRT),
then the process would print the talloc report and continue running,
which is not desired.

Change-Id: I97559b29328101c7cf340aaf1052c0c406634065
Fixes: OS#4865
2020-11-25 18:22:12 +01:00
Harald Welte
952fbf20c9 gprs_gb_parse: Add function to determine TLLI from encoded BSSGP
This will be needed to use the TLLI as link selector parameter
in osmo-gbproxy in an upcoming patch.

Depends: libosmocore.git I397b32a6e6ea3e9d218446138cceafa9b27685dd
Change-Id: Ia6d5300e63ad23987cbdca824db620305bd583d7
2020-11-24 11:33:16 +01:00
Harald Welte
8553f5532a gbproxy: Implement paging to entire BSS area
When we receive a PAGING for PS or CS with destination to the entire
BSS area, we need to iterate over all peers and send one copy of the
paging to each of them.

Change-Id: Iecf244238500a354d5a5b40c76f0c0bb8f8c2511
2020-11-24 11:33:16 +01:00
Harald Welte
3375fa4d64 gbproxy: Properly implement paging to LAC/RAC
There may very well be many PCUs connected within the same RAC or LAC.

This means we'll need to iterate the list of peers and dispatch it to
each matching peer.

Change-Id: I2c44959661fb53730586f4347cbfbbcece065e13
2020-11-24 11:33:12 +01:00
Harald Welte
e1ba4239b4 Use osmo_fd_*_{disable,enable}
Change-Id: Ia207cd2ee68d657ee88cb0152a5b1faa4161c967
Depends: libosmocore.git Idb89ba7bc7c129a6304a76900d17f47daf54d17d
2020-11-11 20:15:09 +00:00
Daniel Willmann
638cddd8f1 osmo-gbproxy: Implement nsvc-state ctrl command
Change-Id: I0beb572103803f3ee4ecb28d9bf2e3139e0f8aa4
2020-11-11 20:11:50 +00:00
Daniel Willmann
58937ce333 configure.ac: Require python3 for ext_tests
The python scripts already use #!/usr/bin/env python3 so it was pure
coincidence that the tests are working.

Change-Id: I96ac31e7862fe102e5baee0c2e25458ff0451a50
2020-11-09 10:54:14 +00:00
Daniel Willmann
02f2c34f8a osmo-gbproxy: Free msgb in ns2 prim callback
Commit cce88282388f in libosmocore changed the msg ownership model - the
callback that the user registers is now responsible for freeing the msg.

Change-Id: Iee940aba7d94afefb5957dbe5f0b04dcf951b31c
Related: SYS#4998
2020-11-09 10:54:09 +00:00
Daniel Willmann
62fa6198ae Let libosmocore handle VTY parent node tracking
* is_config_node is deprecated, so don't set it
* go_parent_cb is only used if we want to do special stuff upon exiting
  a node, in osmo-sgsn and gtphub only osmo_ss7_vty_go_parent() needs to
  be called

Change-Id: I2008dd9026922d29ee703c59e70d3fecced0ee18
2020-11-06 22:21:21 +01:00
Daniel Willmann
c42331f359 gbproxy: Get the peer if paging by BVCI on SIG_BVC
Currently the code reports routing the message to a BVCI but never even
tries to get the peer for it.

Change-Id: Ic72f0f03e5886ab76404915fc60a2796e6881a7a
Related: SYS#4998
2020-11-06 22:21:21 +01:00
Daniel Willmann
15c9da226b gbproxy: Add todo for BVC RESET logic
When we receive a signalling BVC RESET from the SGSN we want to reset
the signalling BVCs for every peer.

Change-Id: I98c1a53d0e4b9a988e9ddec97ce0c67ded6f6326
Related: SYS#4998
2020-11-06 22:21:16 +01:00
Daniel Willmann
8bca8de5cb gbproxy: Whitespace fixes
Change-Id: Id70c15050b6314fdcd452e89e358d657e1f86e57
2020-11-06 18:45:05 +01:00
Alexander Couzens
82182d09c7 Port gbproxy to NS2
Since NS2 has a different abstraction we mock up the prim send/recv
functions and don't test NS like the old tests did.

Related: SYS#4998
Change-Id: Iecfd0408a35a11638d254c1db3c1d477b1a11524
2020-11-06 18:45:05 +01:00
Pau Espin Pedrol
08395b3369 process_ms_ctx_status: Fix crash deleting PDP Ctx if GTP side was already released
sgsn_delete_pdp_ctx() should never be called without checking if the GTP
side is available, since it may happen that it has already been released
by the time the mmctx tells us the pdp ctx is gone on the MS side.

Fixes: OS#4817
Change-Id: Ie618874545172ec98355174a2ee041fc4a8bec16
2020-10-23 13:25:13 +02:00
Pau Espin Pedrol
25998ddcc5 process_ms_ctx_status: refactor to avoid code duplication
Change-Id: I1d1a1284c1563b3a5598e79d8ffd544288de4d62
2020-10-23 13:23:18 +02:00
Pau Espin Pedrol
60581ae7c9 sgsn_delete_pdp_ctx: Add documentation and assert assumptions
This function is only expected to be called if the GTP side of the PDP
ctx is still alive, since it will tear down the GTP side and then finish
the pending MS side if needed.

The asserts are added to ease debugging since it was noted that a few
callers were using this function without properly checking the status of
the pdp ctx.

Related: OS#4817
Change-Id: I4248e2e9846fec5ae2c8557384da2deb86668c50
2020-10-23 13:04:48 +02:00
Keith
c70e8388c7 VTY: Add gtp state-dir command
The SGSN initialises GTP with gtp_statedir of "./" which may
not be the desired path for writing the gsn_restart file.
When starting from systemd for example, we might write
to the system root.

This patch allows override via the config file.

Closes: OS#4820
Change-Id: Ib3ffb7fd6ea1d9b0286111d8c2cba9da5394ca58
2020-10-20 13:21:37 +00:00
Pau Espin Pedrol
5ce54ba1e6 Fix crash rx DeactPdpReq while waiting for DeactPdpAck after gtp side is freed
Scenario:
1- For an unknwon reason, sgsn sends DeletePdpCtxReq on GTP towards GGSN.
2- GGSN answers with Error Indication to that pdp ctx which calls
   gtp_freepdp()
3- gtp_freepdp() calls libgtp callback cb_delete_context() before freeing the
   pointer, in osmo-sgsn callback points to cb_delete_context(), which
   removes pctx->ggsn and tries to drop the pdp on the NS side by sending a
   DeactPdpReq.
4- While waiting for DeactPdpAck, the MS/PCU sends a DeactPdpReq, and
   code was unconditionalyl trying to release the gtp side without checking
   if it was alreay released, using pctx->ggsn==NULL and crashing.

This is basically the same logic already in place in regular path
gsm48_rx_gsm_deact_pdp_ack.

Related: OS#4817
Change-Id: I02587a3dc812823d893fc00b904142b75fd190b9
2020-10-19 15:06:55 +00:00
Pau Espin Pedrol
ff5b59a821 Log error if pdp ctx is freed while holding an active timer
Change-Id: Iae520be36377b27a12441defa722fd41a3cdba0a
2020-10-19 15:06:55 +00:00
Harald Welte
be2330fde4 Use osmo_fd_setup() whenever applicable
Change-Id: I68d14b1c19dd8f1764fdf65afe1a957278255e40
2020-10-19 10:50:45 +00:00
Pau Espin Pedrol
8d2d7db818 contrib/jenkins: Enable parallel make in make distcheck
Change-Id: I423c4b1d854fa6ec7df504353ce666766ba0c787
Related: OS#4421
2020-10-12 19:34:04 +02:00
Alexander Couzens
92ef0c8675 gtphub: fix compilation with gcc 10.2.0
gtphub.c:2915:2: error: ‘snprintf’ argument 4 may overlap destination object ‘buf’ [-Werror=restrict]
 2915 |  snprintf(pos, len, " port %s", portbuf);
      |  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Be better safe and use the stack instead of byte counting in the buffer.

Change-Id: Ied9665ce6bd2633797bbc3a2171e911ada357a22
2020-10-03 20:37:15 +02:00
Alexander Couzens
68d9c5a468 gtphub_test: fix compilation error on gcc 10.2.0
Ensure dump && hex can't be zero.

gtphub_test.c: In function ‘_reply_is.constprop’:
gtphub_test.c:535:3: error: ‘%s’ directive argument is null [-Werror=format-overflow=]

Change-Id: Id27bf46855a228935fe706584f9b27cf3facf623
2020-10-02 20:44:34 +00:00
Philipp Maier
ef6205ba00 gprs_sndcp: fix use after free
When compression is turned on, an extra buffer "expnd" is allocated in
the context of msg. This means that when msg is freed, expnd is freed as
well and there is no need for freein it explcicitly, which, when it is
done after freeng msg, causes talloc to abort.

Change-Id: I8959b75e241ffabf9fa34c4cf014721584372b26
2020-10-02 17:38:12 +02:00
Daniel Willmann
86336af2a3 gbproxy-usermanual: Explain BSSGP/BVC handling
Related: SYS#5005
Change-Id: I383fcd3864a94177f13909c6b8c15648900d3201
2020-09-25 09:54:26 +02:00
Keith
6d92f148aa Fix Radio Priority in MM Attach and PDP Context Activation
3GPP TS 24.008 Section 10.5.7.2 Radio Priority states that the Radio Priority IE is
3 bits as follows:

--------------------------------------------
0 0 1   priority level 1 (highest)
0 1 0   priority level 2
0 1 1   priority level 3
1 0 0   priority level 4 (lowest)

All other values are interpreted as priority
 level 4 by this version of the protocol.
--------------------------------------------

However at least the MediaTek MT6753 and MT6592 have been
observed to interpret a value of 0 0 0 in an undetermined way
resulting in lack of access to RACH in the cell.

Fixes: OS#4506
Change-Id: I810cd541eb5764ee3f2c238bcd3a10836228d0b5
2020-09-21 00:18:48 +02:00
Alexander Couzens
27a0bf70e7 gmm: on invalid RA id reject the MS with an implicit detach
As long the SGSN doesn't support PS handover treat unknown RA as invalid
and do an implicit detach.

Fixes ttcn3 crash when an RAU happen within an Attach Request

Change-Id: I6a0b335d51f58c26349f7e0a62b2107d7d351d07
2020-09-20 09:52:24 +00:00
Alexander Couzens
d3c3ddeb51 gprs_llc: _bssgp_tx_dl_ud: ensure the LLME is valid before using it
In rare cases the LLME is NULL even when the mmctx is valid.
Ensure not accessing a NULL pointer.

Change-Id: Id9fdfb0d88264671546f8dfc4655032ff27bf43e
2020-09-18 18:32:04 +02:00
Pau Espin Pedrol
e6c5b4a970 Change default SCTP conn NULL->127.0.0.1 to localhost->localhost
"127.0.0.1" is changed to "localhost" to let local NSS decide whether to
use IPv4 or IPv6. In newish systems, IPv6 ::1 will be selected since
IPv6 takes precedence over IPv4.

Similarly, the default source addr needs to be changed from NULL to "localhost"
since for some yet unknwon reason, getaddrinfo(AF_UNSPEC, NULL) returns
first IPv4 "0.0.0.0" and later "::", which is inconsistent with
getaddrinfo("localhost") result, resulting in src=IPv4(0.0.0.0) and
dst=IPv6(::1), which is incompatible and will fail. In any case, since
the default remote address is a local one and it's the client side,
there's no real logical change since the kernel would anyway should have
taken a local address anyway.

Change-Id: I2f599e1aa449d44136ef20ba5f516ca9b61f3223
2020-08-21 18:07:11 +02:00
Pau Espin Pedrol
aae7daff81 Support setting rt-prio and cpu-affinity mask through VTY
Change-Id: I1af1b154d14de6d6d6fba08f15f167f4b2ed9aa2
Depends: libosmocore.git Change-Id If76a4bd2cc7b3c7adf5d84790a944d78be70e10a
Depends: osmo-gsm-masnuals.git Change-Id Icd75769ef630c3fa985fc5e2154d5521689cdd3c
Related: SYS#4986
2020-08-18 13:50:00 +02:00
Pau Espin Pedrol
b32936d823 doc: Update VTY reference xml file
Change-Id: I787bbc254ef10766fe8d480ffd93a16d9926a50e
2020-08-18 13:46:17 +02:00
Pau Espin Pedrol
d5dc143001 configure.ac: Fix trailing whitespace
Change-Id: I5abdce5daef43dad772bf52576b47c0867d65c98
2020-08-18 13:45:09 +02:00
Vadim Yanitskiy
65a5a0a27b debian/control: change maintainer to the Osmocom team / mailing list
Change-Id: Ic6956c4d5cc9913c06b9e293dc5bb156f6510285
2020-08-13 16:09:03 +07:00
Harald Welte
9d16b14345 Send a BVC-RESET to all persistent Gb interfaces at start-up
3GPP TS 48.018 Section 8.4:

> After any failure affecting the NSE, the party (BSS or SGSN) where
> the failure resided shall reset the signalling BVC. After sending or
> receiving a BVC-RESET PDU for the signalling BVC, the BSS shall stop all
> traffic and initiate the BVC-RESET procedure for all BVCs corresponding
> to PTP functional entities of the underlying network service entity. The
> BSS must complete the BVC-RESET procedure for signalling BVC before
> starting PTP BVC-RESET procedures.

TODO: We should not just trigger a single outbound BVC-RESET message,
but we should re-transmit them until we get a response.   This would
likely entail adding FSMs to libosmogb, which we will leave for a later
point - it's anticipated that the NS + BSSGP code is undergoing quite
some changes in the coming months anyway, so leave it for then.

Change-Id: I0b46035b40709c38bb9ab9493c11031a577e3ee0
Closes: OS#4629
Depends: libosmocore.git I353adc1aa72377f7d4b3336d2ff47791fb73d62c
2020-07-27 14:43:36 +00:00
Alexander Couzens
dd930a25ad gtphub: rename sgsn's oww osmo_sockaddr into sgsn_sockaddr
The osmo_ prefix should be only used for official struct/apis of libosmocore.
This commit was done via `sed -i 's/osmo_sockaddr/sgsn_sockaddr/g'`.

In prepartion of introducing a different api of osmo_sockaddr to
libosmocore.

Change-Id: Ibb1ddce9ff1ffe7494de5cdb8ea1843c45fe4566
2020-07-18 21:43:49 +00:00
Pau Espin Pedrol
b3e10aa8eb sgsn_libgtp: Avoid ps-paging MS on GMM Suspended state
The MS notifies movement to GMM SUSPEND state because it is for instance
handling a call and cannot use PDCH anymore. Once it releases the TCH it
will ASAP move to either dedicated mode or trigger RAU, which means it
will get out of SUSPEND state. So it doesn't make sense to try paging
the MS when in that state.

This change makes test TC_suspend_nopaging pass.

Related: OS#4616
Change-Id: Ia245899eb9f16c7f839785def4ceb721a1c3a11b
2020-06-26 12:20:57 +02:00
Pau Espin Pedrol
36ecddb705 gprs_gmm_fsm.c: Add missing license header
The file was created by myself on September 2019,
31c4657c97.

Change-Id: I94299b9ccf760ad13429e149067f06ed60d37de3
2020-06-26 12:07:12 +02:00
Harald Welte
90dedcb2e7 *.spec.in: Use %config(noreplace) to retain current config file
Change-Id: I4e7f0a44d5e2d132b24ca0f38dc6f520b59112da
2020-06-22 15:20:33 +02:00
Pau Espin Pedrol
cfd307b4e8 sgsn_libgtp: Improve ps-paging logging
Change-Id: I0c3d48d54295824c3ba5b0fa9e3c035983556326
2020-06-18 11:39:13 +00:00
Neels Hofmeyr
b26a5a82db use new osmo_mobile_identity API everywhere
Depends: If4f7be606e54cfa1c59084cf169785b1cbda5cf5 (libosmocore)
Change-Id: I4cacb10bac419633ca0c14f244f9903f7f517b49
2020-06-18 11:23:35 +00:00
Neels Hofmeyr
7369d449f1 gbproxy_test.c: fix mobile identity test data
Fix the final nibble of all IMSI BCD digits to 0xf, since it is a filler digit.

The encoded IMSI has an even amount of digits (14) and must contain a 0xf
filler nibble at the end. The test data looked correct due to repeated '1'
digits.

wrong hex: 11 12 13 14 15 16 17 18
correct:   11 12 13 14 15 16 17 f8
order:     1T 32 54 76 98 ba dc Xe  T = type, X = filler, 1..e = 14 digits

This error was found when applying the new osmo_mobile_identity API.

Change-Id: Ia006a3da6779ad1984f642e8ea29790a4daeb8b9
2020-06-18 11:23:35 +00:00
Harald Welte
5e1a486a72 Treat RAU as implicit RESUME if GMM is suspended
We so far only resumed from suspend upon receiving an explicit BSSGP
RESUME message from the BSS.  The latter is only possible in
BSC-colocated PCU, where the BSC can trigger the message when releasing
the dedicated channel.  In BTS-colocated PCUs, this is not possible,
and we have to rely on the MS resuming by RAU.

See 3GPP TS 23.060 section 16.2.1.1.1 clause 6:

The MS shall resume GPRS services by sending a Routeing Area Update Request message to the SGSN:
* if the BSS did not successfully request the SGSN to resume GPRS services,
* if the RR Channel Release message was not received before the MS left dedicated mode,
* if the MS locally determines that the conditions for the GPRS suspension have disappeared

Without this patch, the GMM state would forever be stuck in SUSPEND,
which in turn causes the SGSN to page the MS all the time.

Change-Id: I3c09187a27483d95fa0070bbb467f94a2ea3978f
Related: OS4616
2020-06-17 21:09:03 +00:00
Harald Welte
627e285fd0 Fix memory leak when SNDCP de-fragmentation is used
As msgb ownership is not passed along, we need to free the message
buffer memory we allocate in defrag_segments() after calling
sgsn_rx_sndcp_ud_ind().

Change-Id: I1185b1aa99bb167d616eb469e5445e4ed5ad949d
Closes: OS#4603
2020-06-08 20:46:53 +02:00
Oliver Smith
5e0b829884 Makefile.am: EXTRA_DIST: debian, contrib/*.spec.in
Change-Id: I15d4c9ca2c7ed0467b44f57bbaa1a2177feff154
2020-05-22 13:45:48 +02:00
Oliver Smith
bd6d677179 contrib: integrate RPM spec
Remove OpenSUSE bug report link, set version to @VERSION@, make it build
with CentOS 8 etc.

Related: OS#4550
Change-Id: I824b67f2d590ac2aa9f2e4fa4387a5283cf22521
2020-05-19 16:49:33 +02:00
Oliver Smith
482bb07301 contrib: import RPM spec
Copy the RPM spec file from:
https://build.opensuse.org/project/show/home:mnhauke:osmocom:nightly

Related: OS#4550
Change-Id: Ia18f44f1b6dc259c3d0474b88b33f4657d96fd7a
2020-05-14 11:52:28 +02:00
Neels Hofmeyr
b63e19d7d2 gsup: send RAT type on LU
At 36c3, osmo-hlr was run with a patch that records the RAN type of attached
subscribers. Even though this is not in osmo-hlr master, it is nice information
to send along.

Change-Id: I5dbe610738aed7ea1edf6b33543b1c03818cc274
2020-05-12 13:52:24 +02:00
Neels Hofmeyr
c6548bbaab fix nullpointer: in gsm48_rx_gmm_ra_upd_req()
This caused frequent crashes at 36c3. The "proper" fix is probably elsewhere
(lynxis mentions an unfinished patch), but at least this prevented some crashes
during active operation.

Once this is merged, we can (re)enable SGSN_Tests_Iu.TC_geran_attach_iu_rau,
which tests exactly for this scenario:  A Subscriber / MM context that is so
far attached via GERAN, but now receives a RAU via UTRAN/Iu.

Closes: OS#4339
Change-Id: Ifde15dc4151d84748f0e67b32c9c260cb2d9d8fc
2020-05-10 22:33:27 +00:00
Pau Espin Pedrol
b2ebc59f30 Use OSMO_FD_* instead of deprecated BSC_FD_*
New define is available since libosmocore 1.1.0, and we already require
1.2.0, so no need to update dependenices.
Let's change it to avoid people re-using old BSC_FD_* symbols when
copy-pasting somewhere else.

Change-Id: Iaebd049e383b02204a12f39cc6c932a53d25fd72
2020-05-09 19:21:15 +02:00
Harald Welte
9d550cb369 gtphub_test: Fix compilation with gcc-10
/usr/bin/ld: ../../src/gtphub/gtphub.o:/home/laforge/projects/git/osmo-sgsn/src/gtphub/gtphub.c:50: multiple definition of `osmo_gtphub_ctx'; gtphub_test.o:/home/laforge/projects/git/osmo-sgsn/tests/gtphub/gtphub_test.c:57: first defined here
collect2: error: ld returned 1 exit status

See also https://alioth-lists.debian.net/pipermail/debian-mobcom-maintainers/Week-of-Mon-20200413/000653.html

Change-Id: I19c1eef6649d2747f0b624f5292d7ae47c4ca839
2020-04-20 19:47:19 +02:00
Eric
e6b2883f10 configure.ac: fix libtool issue with clang and sanitizer
As pointed out at https://github.com/libexpat/libexpat/issues/312
libtool does not play nice with clang sanitizer builds at all.
For those builds LD shoud be set to clang too (and LDFLAGS needs the
sanitizer flags as well), because the clang compiler driver knows how
linking to the sanitizer libs works, but then at a later stage libtool
fails to actually produce the shared libraries and the build fails. This
is fixed by this patch.

Addtionally LD_LIBRARY_PATH has no effect on conftest runs during
configure time, so the rpath needs to be set to the asan library path to
ensure the configure run does not fail due to a missing asan library,
i.e.:

SANS='-fsanitize=memory -fsanitize-recover=all -shared-libsan'
export CC=clang-10
ASANPATH=$(dirname `$CC -print-file-name=libclang_rt.asan-x86_64.so`)
export LDFLAGS="-Wl,-rpath,$ASANPATH $SANS $LDFLAGS"

Change-Id: I7402b019c191304f639806a3c29e6bb698b398ed
2020-04-11 01:04:28 +02:00
Eric
6528e8c1cb tests: dlopen does not imply availability of dlsym..
Check for both.

Change-Id: If41a20bf499f791432f5f207e40688e97fb6e9f7
2020-04-11 01:04:08 +02:00
Neels Hofmeyr
6e4cd085b5 manual: explain IuPS, add SCCP/M3UA section from common chapters
Add 'cs7' default configuration, link to the
osmo-gsm-manuals/common/cs7-config.adoc chapter to fully explain the 'cs7'
client configuration.

Related: OS#2767
Depends: Ia2508d4c7b0fef9cdc57e7e122799a480e340bf7 (osmo-gsm-manuals)
Change-Id: If0f7c8fc4b94eb40b62570cf90999d5074dc00ee
2020-03-23 20:06:12 +01:00
Alexander Couzens
91a8bbd5db gprs_gmm_fsm.c: Implement RAT change between 2g and 3g
Related: OS#2737
Change-Id: I3fc614da6ba137e871ee0fe86ca22b6a4a354dd2
2020-02-04 10:21:12 +01:00
Daniel Willmann
d999e54aa2 gprs_gmm: Check for RAT change and ensure this only happens for RAU/ATT
Change-Id: I38cb31907eddeade5350cdb648df179408d908d2
Related: OS#3727
2020-02-04 09:27:20 +01:00
Pau Espin Pedrol
394aa533e9 Bump version: 1.5.0.91-5997-dirty → 1.6.0
Change-Id: I99e6950db3f54c6291dd259bed9b5c46cc26c465
2020-01-03 19:17:56 +01:00
Oliver Smith
5997357c69 osmoappdesc.py, tests: switch to python 3
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: I8c07d99c1bc9f0383e4bce17544e0998998cc54d
2019-12-11 09:41:27 +01:00
Harald Welte
de67c001b7 exit(2) on unsupported positional arguments on command line
Change-Id: I4f2d70d0b0f1b7bdb8604c930aba8fbb53d8bd54
2019-12-03 22:28:19 +01:00
Oliver Smith
ad08d17e07 regen_doc.sh: support gbproxy, run without docker
Do not only update the VTY reference and counters of osmo-sgsn, but also
the VTY reference of gbproxy.

This was not possible with the old code path of calling "regen_doc.sh"
inside docker-playground.git, as it expects the program to be updated to
have the same name as the docker image. Using the docker-playground
script also has the disadvantage, that one must push the development
branch to git.osmocom.org before updating the VTY reference/counters,
because that script would build a new docker container with a freshly
cloned repository, check out the same commit that we have already
locally, build that and then finally regenerate the docs.

So instead of adding another parameter for the docker image to the
script in docker-playground.git and calling it twice, simplify the
process by rewriting the regen_doc.sh script in osmo-sgsn.git. Make it
start the locally installed osmo-sgsn and osmo-gbproxy binaries and
call osmo_interact_vty.py on them.

Related: OS#4292
Change-Id: I8b5bd5347ea34266ad650383372630f2a84d5cce
2019-12-03 11:41:21 +01:00
Oliver Smith
118c411e81 doc: add OsmoGbProxy VTY reference
Depends: (osmo-gsm-manuals) I4dea3e07b88175b2a88e577129360af7ec5f87e1
Related: OS#4292
Change-Id: I24c3ca2fc2446673edceefb797c7d800c3a1a5d2
2019-12-03 11:39:26 +01:00
Oliver Smith
fa2656d14e gitignore: fix paths to binaries
Change-Id: Ia968bbc5de34e9068d4b414e5a701b958ae517e5
2019-12-02 14:40:31 +01:00
Harald Welte
6e6347613d manual: Fix copy+paste error
Change-Id: I5753ded676951998a1fd76e4d2c2bf3311213f53
2019-12-01 14:31:16 +01:00
Harald Welte
61557f42c1 check for osmo_ss7_init() error return value
Change-Id: Ic228273aa6fb197b78c70c467a4a99af317e8098
2019-12-01 12:43:17 +00:00
Harald Welte
a868e17c5e check for osmo_fsm_register() error return values
Change-Id: I2028c82ac1b0421101c3f5d04fd999b65abdbf08
2019-12-01 12:43:17 +00:00
Harald Welte
1fd50d9abe Initial OsmoGbPROXY user manual
This adds a very basic manual consisting of nothing more than
the common chapters and a high-level description of what it is
all about.

Change-Id: I80d4ea016376c59995ccfcd8685c7c0e86745bd2
2019-12-01 12:42:58 +00:00
Harald Welte
4146121cc9 LLC: Don't use hard-coded N201-U / N201-I values in XID
The N201 values are negotiated per SAPI, and there are default values
per each SAPI.  Let's use those rather than hard-coded values.

Closes: OS#3954
Change-Id: I447a3c6dd85311772a6e219c62dc820d2726857f
2019-11-30 18:50:50 +00:00
Max
85386dcfad Use libosmocore constant for IMSI length in ACL entry
Presumably the length is chosen to match that of imsi in
osmo_gsup_message.

Change-Id: I138aea409aab0c748c75546e628797fc7498bf40
2019-11-23 19:12:45 +07:00
Pau Espin Pedrol
9203da58e2 gprs_gmm.c: Send XID reset with received TLLI
Otherwise lower layers will end up using a TLLI from PTMSI which was not
yet announced to the MS if it is still not in GMM attached state, as
showcased by SGSN_Tests.TC_attach_req_id_req_ra_update.

Related: OS#3957, OS#4245
Change-Id: Ide51726abb82f5784eca4ab8d62b2ad8512be843
2019-11-21 16:39:23 +01:00
Pau Espin Pedrol
b71d2c5ddd gprs_llc.c: Use enum instead of hardcoded value
Change-Id: I89815f44f615a188f46a13f3785b3f7484f73bb3
2019-11-21 16:15:52 +01:00
Pau Espin Pedrol
029a70e493 Improve logging in gprs_llc.c code
Change-Id: Id89cc6760179fb9b1709a30b5d1af41d466b280b
2019-11-21 14:15:10 +01:00
Pau Espin Pedrol
de80976d94 gmm: Fix assertion hit during RA UPD REQ before completting gmm attach
Output:
20191107021548500 DMM <0002> gprs_gb.c:40 MM_STATE_Gb(2596296189)[0x6120000084a0]{Idle}: Received Event E_MM_PDU_RECEPTION
20191107021548500 DMM <0002> gprs_gmm.c:1531 MM(/d4b6d7af) -> GMM RA UPDATE REQUEST type="RA updating"
20191107021548501 DMM <0002> gprs_gmm.c:1615 MM(/d4b6d7af) The MM context cannot be used, RA: 901-70-2758-208
Assert failed mmctx->gb.llme == NULL gprs_gmm.c:1620

Scenario reproducing the crash can be triggered with TTCN3
SGSN_Tests.TC_attach_req_id_req_ra_update.

Basically, SGSN first receives an ATTACH REQ with a given RA ID, then
SGSN switches to state CommonProcedureInitiated and sends GMM ID REQ,
and MS/PCU answers immediatelly with a RA Update instead with a new RA
ID.

Related: OS#3957, OS#4245
Change-Id: I64fa5cf1b427d3abb99e553e584897261a827ce6
2019-11-08 18:50:29 +01:00
Pau Espin Pedrol
284314ab0a sgsn_libgtp.c: Drop use of deprecated libgtp APIs gtp_retrans*()
Since osmo-ggsn.git c94837c6a401bf0f80791b619a9b4cfbe9160afd, those
APIs are a no-op since timers are tracked internally through osmocom
APIs (and at the same time, new implementation fixes some timing related
bugs).

As a result, osmo-sgsn depends now on at least that libgtp commit. Since
it's not yet avaiable on latest libgtp release, let's track it down in
TODO-RELESE to not forget to update libgtp requirements during osmo-sgsn
release.

Related: OS#4178
Change-Id: Ia9a93d4a6ed63cd0c736f9a99d81d730b958d82e
2019-10-21 08:31:31 +00:00
Alexander Couzens
4d1d2e78b1 sgsn: Gb: implementing PS Paging when MS is MM_STANDBY
When the MS is in MM_STANDBY, the Routing Area is known,
but not the exact cell.
Start the paging procedure. (Even this is only supported
for the last known cell, not the Routing Area. Routing Area
paging is not yet supported.)

Change-Id: Icc2c6ba70f8f74054546a1e31741fc90b232a23c
2019-10-17 08:01:16 +00:00
Alexander Couzens
030824e172 sgsn_libgtp: refactor ps paging into gprs_gb
Paging should be done in gprs_gb
Change-Id: I3020020f52005aa460ca6b245ee2297aec9821b3
2019-10-17 08:01:10 +00:00
Vadim Yanitskiy
0e124d3131 gprs_mm_state_iu_fsm.c: fix: assign timer_cb to mm_state_iu_fsm
GCC warns us that 'pmm_state_fsm_timer_cb' is defined but not used.
This function was introduced in [1], but was not assigned to the FSM.

[1] I66c2ac0350cb074aefd9a22c5121acf723f239d3

Change-Id: Ib040befc87b2676aad2b8fe3671404fb3f5b030b
2019-10-09 18:32:55 +07:00
Alexander Couzens
865bf6f1bf sgsn_mm_ctx_alloc(): check for unallocated fsms
Change-Id: I867612a60236eaf7009400c92f5d871006aaf008
2019-10-08 23:13:10 +00:00
Alexander Couzens
10af11dacc gprs_gmm: release Iu connection on RAU failures
When a RAU fails without an a GMM context, release the Iu
connection after sending a response.

Change-Id: I05a9200f55d608ccfb3f86184c324a2b428da76b
2019-10-08 20:31:56 +00:00
Alexander Couzens
afadd102bf ranap: add non-spec X1001
When the SGSN releases a RANAP connection, it sends a Release Command
and waits for a Release Complete. Use X1001 to release the Iu connection
when the Release Complete is lost/never received.

Change-Id: I39a0169c22a4ac430b3d6f3c281d1f381eaa4756
2019-10-08 20:31:25 +00:00
Alexander Couzens
12235310af sgsn: MM Gb Fsm: fix event handling for implicit detach
Implicit detach means there won't be any Gb state afterwards.

Change-Id: Iececb730e7135e14ebd94f82edb79b03ced1f9e3
2019-10-08 12:38:35 +00:00
Alexander Couzens
d597ee260a gprs_sgsn: always allocate Gb/Iu mm fsm
When moving between RANs we need them at a later point.
Allocate them always to not make the code (more) complex.

Change-Id: I1724790335b0820f153a0cbdb5cfd1cfea36d1e9
2019-10-08 12:38:14 +00:00
Alexander Couzens
743e687496 gprs_ranap: add missing rc = 0
After processing the event, set the return code to success.
Thanks to manatails (redmine).

Change-Id: I73b3b3c3dd330bc953835737758854cf68539495
Fixes: #3969
2019-10-08 12:02:19 +00:00
Alexander Couzens
4c7609a508 gprs_mm_state_gb_fsm: ensure T3350 is not running when entering IDLE
In IDLE there is not further context with the MS. Prevents the Timer from sending
packages to a MS which can not respond

Change-Id: Ibdd913173af11d0e6d04aa392e047d5d9aee1243
2019-10-08 10:34:57 +00:00
Alexander Couzens
62f6f9aebf gprs_ranap: on Iu release, stop the attach fsm if running
A Iu release should stop any active procedure.

Change-Id: I78c6c0c4024657212d6abef51e226ce233018fee
2019-10-08 10:34:28 +00:00
Alexander Couzens
3bad31bcb4 Iu: implement a user inactivity timer
The user inactivity timer is similiar to the Gb READY timer and reduces
the resources taken by an idle UE.

Change-Id: I66c2ac0350cb074aefd9a22c5121acf723f239d3
2019-10-08 10:34:09 +00:00
Alexander Couzens
eb5aee580d gprs_ranap: release Iu UE Context when exiting PMM Connected
PMM Connected defines a Iu signaling connection. The 2 other
PMM states do not have an active Iu signaling connection.

Change-Id: Ie05d2bdf8dfb593b4c7e837107a3a06f22e90119
2019-10-03 20:29:37 +00:00
Alexander Couzens
e30f19542b Avoid compiling unneeded files when building without Iu
Remove gprs_ranap.c and gprs_mm_state_iu_fsm.c
from the Makefile when building without IU.

Change-Id: I2386f8e86bbf0b87eedce9f57eb86b1b64998a69
2019-10-03 19:51:03 +00:00
Alexander Couzens
a8f782502b sgsn: when receiving data PDU notify the Gb GMM fsm
When receiving a PDU, the GMM fsm will change to state MM_READY
and will re-arm the T3314

Relates: OS#1941
Change-Id: I78f40762fb17bbd4a6f35608a793f8e5271e9b86
2019-09-28 17:55:19 +00:00
Pau Espin Pedrol
324bb5a11e Introduce TODO-RELEASE file
It's going to be useful to track new dependency APIs being used which
require dependency version release and version bump during release of
osmo-sgsn.

Change-Id: Ia495a8577001c6a223c31f4ddd7eee289e3523c7
2019-09-19 16:15:32 +02:00
Alexander Couzens
1cb4be9db0 gprs_ranap: refactor REQUIRE_MM define
All branches need a MM context. Exit early if no MM context
present.

Change-Id: Ifa4c55f1f2c199fa63bd755311026b8586a65f3f
2019-09-12 01:43:16 +02:00
Alexander Couzens
6888021bf2 mm_gb_fsm: unassign the llme when entering MM_IDLE
MM_IDLE means there is no known state to this MM.

Change-Id: Ieb0d6cea828842763c13942fe1a63dd89399f799
2019-09-12 01:43:16 +02:00
Alexander Couzens
10b3d70fea gprs_ranap: send CommonId after receiving Security Mode Complete
After Security Mode Complete, the sender has been authenticated.
Send a CommonId to enable paging coordination between CS and PS.

Change-Id: If195c26e87ba3054e159746671babf93a12e7013
2019-09-12 01:43:16 +02:00
Alexander Couzens
8e3766cd38 sgsn_pdp_ctx_terminate: check llme before accessing
Change-Id: Ib4361cdc12f9c1674c89c6fafeeb52a3f42abe1d
2019-09-10 16:01:46 +02:00
163 changed files with 9957 additions and 23262 deletions

1
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1 @@
open_collective: osmocom

12
.gitignore vendored
View File

@@ -6,14 +6,15 @@ debian/*.log
.deps
Makefile
Makefile.in
bscconfig.h
bscconfig.h.in
config.h
config.h.in
*.*~
*.sw?
.libs
*.pyc
*.gcda
*.gcno
*~
#configure
aclocal.m4
@@ -39,9 +40,8 @@ ltmain.sh
# apps and app data
src/gprs/osmo-sgsn
src/gprs/osmo-gbproxy
src/gprs/osmo-gtphub
src/sgsn/osmo-sgsn
src/gtphub/osmo-gtphub
src/libcommon/gsup_test_client
#tests
@@ -69,3 +69,5 @@ doc/manuals/generated/
doc/manuals/osmomsc-usermanual.xml
doc/manuals/common
doc/manuals/build
contrib/osmo-sgsn.spec

View File

@@ -9,15 +9,21 @@ AM_CPPFLAGS = \
$(NULL)
SUBDIRS = \
doc \
include \
src \
contrib \
tests \
doc \
$(NULL)
BUILT_SOURCES = $(top_srcdir)/.version
EXTRA_DIST = git-version-gen osmoappdesc.py .version
EXTRA_DIST = \
.version \
README.md \
debian \
git-version-gen \
osmoappdesc.py \
$(NULL)
AM_DISTCHECK_CONFIGURE_FLAGS = \
--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)

17
README
View File

@@ -1,17 +0,0 @@
About OsmoSGSN
==============
OsmoSGSN originated from the OpenBSC project, as a separate program within
openbsc.git. In 2017, OpenBSC was split in separate repositories, and hence
OsmoSGSN was given its own separate git repository.
OsmoSGSN exposes
- GSUP towards OsmoHLR (or a MAP proxy);
- GTP towards a GGSN (e.g. OsmoGGSN);
- Gb towards a BSS (e.g. OsmoPCU);
- IuPS towards an RNC or HNB-GW (e.g. OsmoHNBGW) for 3G data;
- The Osmocom typical telnet VTY and CTRL interfaces.
Find OsmoSGSN issue tracker and wiki online at
https://osmocom.org/projects/osmosgsn
https://osmocom.org/projects/osmosgsn/wiki

100
README.md Normal file
View File

@@ -0,0 +1,100 @@
osmo-sgsn - Osmocom SGSN Implementation
=======================================
This repository contains a C-language implementation of a *Serving GPRS
Support Node (SGSN)* for 2.5/2.75G (GPRS/EDGE) and 3G (UMTS). It is part of the
[Osmocom](https://osmocom.org/) Open Source Mobile Communications
project.
OsmoSGSN exposes
* *Gb* towards PCUs (e.g. [OsmoPCU](https://osmocom.org/projects/osmopcu/wiki/OsmoPCU)): Various GbIP flavors + Gb/FR/E1
* *GTP* towards a GGSN (e.g. [OsmoGGSN](https://osmocom.org/projects/openggsn/wiki))
* IuPS over IP towards RNCs / HNBGW (e.g. [osmo-hnbgw](https://osmocom.org/projects/osmohnbgw/wiki))
* The Osmocom typical telnet *VTY* and *CTRL* interfaces.
* The Osmocom typical *statsd* exporter.
* GSUP (custom MAP-like protocol) towards [osmo-hlr](https://osmocom.org/projects/osmo-hlr/wiki/OsmoHLR)
OsmoSGSN implements
* GPRS mobility management
* GPRS session management
Homepage
--------
You can find the OsmoSGSN homepage online at <https://osmocom.org/projects/osmosgsn/wiki>.
GIT Repository
--------------
You can clone from the official osmo-sgsn.git repository using
git clone https://gitea.osmocom.org/cellular-infrastructure/osmo-sgsn
There is a web interface at <https://gitea.osmocom.org/cellular-infrastructure/osmo-sgsn>
Documentation
-------------
User Manuals and VTY reference manuals are [optionally] built in PDF form
as part of the build process.
Pre-rendered PDF version of the current "master" can be found at
[User Manual](https://ftp.osmocom.org/docs/latest/osmosgsn-usermanual.pdf)
as well as the [VTY Reference Manual](https://ftp.osmocom.org/docs/latest/osmosgsn-vty-reference.pdf)
Forum
-----
We welcome any osmo-sgsn related discussions in the
[Cellular Network Infratructure -> 2G/3G Core Network](https://discourse.osmocom.org/c/cni/2g-3g-cn).
section of the osmocom discourse (web based Forum).
Mailing List
------------
Discussions related to osmo-sgsn are happening on the
osmocom-net-gprs@lists.osmocom.org mailing list, please see
<https://lists.osmocom.org/postorius/lists/osmocom-net-gprs.lists.osmocom.org/> for subscription
options and the list archive.
Please observe the [Osmocom Mailing List
Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
when posting.
Issue Tracker
-------------
We use the [issue tracker of the osmo-sgsn project on osmocom.org](https://osmocom.org/projects/osmosgsn/issues) for
tracking the state of bug reports and feature requests. Feel free to submit any issues you may find, or help
us out by resolving existing issues.
Contributing
------------
Our coding standards are described at
<https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards>
We use a Gerrit based patch submission/review process for managing
contributions. Please see
<https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit> for
more details
The current patch queue for osmo-sgsn can be seen at
<https://gerrit.osmocom.org/#/q/project:osmo-sgsn+status:open>
History
-------
OsmoSGSN originated from the OpenBSC project, as a separate program within
openbsc.git. In 2017, OpenBSC was split in separate repositories, and hence
OsmoSGSN was given its own separate git repository.

View File

@@ -1,6 +1,6 @@
To run the configuration parsing and output (VTY) test suite, first install
git://git.osmocom.org/python/osmo-python-tests
https://gitea.osmocom.org/cellular-infrastructure/osmo-python-tests
and pass the following configure options here:

15
TODO-RELEASE Normal file
View File

@@ -0,0 +1,15 @@
# When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install
# according to https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release
# In short: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
# LIBVERSION=c:r:a
# If the library source code has changed at all since the last update, then increment revision: c:r + 1:a.
# If any interfaces have been added, removed, or changed since the last update: c + 1:0:a.
# If any interfaces have been added since the last public release: c:r:a + 1.
# If any interfaces have been removed or changed since the last public release: c:r:0.
#library what description / commit summary line
libgtp >1.12.0 new field dir_tun_flags in struct pdp_t
libgtp >1.12.0 gtp_set_cb_update_context_ind(), gtp_update_context_resp()
libosmocore >1.10.0 enum gsm48_gprs_ie_mm: GSM48_IE_GMM_UE_NET_CAP, GSM48_IE_GMM_VD_PREF_UE_USAGE
libosmo-gsup-client >1.8.0 osmo_gsup_client_is_connected(), osmo_gsup_client_get_rem_addr(), osmo_gsup_client_get_rem_port()
osmo-iuh >1.7.0 ranap multiple params are constified, see osmo-iuh Change-Id I667dc2ef377c1ceb5b11315458f00b282c143c81
osmo-iuh >1.7.0 ranap_new_msg_error_ind()

View File

@@ -22,6 +22,11 @@ AC_PROG_CC
AC_PROG_INSTALL
LT_INIT
dnl patching ${archive_cmds} to affect generation of file "libtool" to fix linking with clang
AS_CASE(["$LD"],[*clang*],
[AS_CASE(["${host_os}"],
[*linux*],[archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'])])
dnl check for pkg-config (explained in detail in libosmocore/configure.ac)
AC_PATH_PROG(PKG_CONFIG_INSTALLED, pkg-config, no)
if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
@@ -29,39 +34,31 @@ if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
fi
PKG_PROG_PKG_CONFIG([0.20])
dnl check for AX_CHECK_COMPILE_FLAG
m4_ifdef([AX_CHECK_COMPILE_FLAG], [], [
AC_MSG_ERROR([Please install autoconf-archive; re-run 'autoreconf -fi' for it to take effect.])
])
dnl use a defined standard across all builds and don't depend on compiler default
CFLAGS="$CFLAGS -std=gnu11"
dnl checks for libraries
AC_SEARCH_LIBS([dlopen], [dl dld], [LIBRARY_DL="$LIBS";LIBS=""])
AC_SUBST(LIBRARY_DL)
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.2.0)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.2.0)
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.2.0)
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.2.0)
PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 1.2.0)
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.6.0)
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 0.4.0)
PKG_CHECK_MODULES(LIBOSMOGSUPCLIENT, libosmo-gsup-client >= 1.0.0)
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.10.0)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.10.0)
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.10.0)
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.10.0)
PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 1.10.0)
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.6.0)
PKG_CHECK_MODULES(LIBOSMOGSUPCLIENT, libosmo-gsup-client >= 1.8.0)
PKG_CHECK_MODULES(LIBGTP, libgtp >= 1.12.0)
# Enable/disable 3G aka IuPS + IuCS support?
AC_ARG_ENABLE([iu], [AS_HELP_STRING([--enable-iu], [Build 3G support, aka IuPS and IuCS interfaces])],
[osmo_ac_iu="$enableval"],[osmo_ac_iu="no"])
if test "x$osmo_ac_iu" = "xyes" ; then
PKG_CHECK_MODULES(LIBOSMOSIGTRAN, libosmo-sigtran >= 1.0.0)
PKG_CHECK_MODULES(LIBOSMOSIGTRAN, libosmo-sigtran >= 1.9.0)
PKG_CHECK_MODULES(LIBASN1C, libasn1c >= 0.9.30)
PKG_CHECK_MODULES(LIBOSMORANAP, libosmo-ranap >= 0.4.0)
PKG_CHECK_MODULES(LIBOSMORANAP, libosmo-ranap >= 1.6.0)
AC_DEFINE(BUILD_IU, 1, [Define if we want to build IuPS and IuCS interfaces support])
fi
AM_CONDITIONAL(BUILD_IU, test "x$osmo_ac_iu" = "xyes")
AC_SUBST(osmo_ac_iu)
PKG_CHECK_MODULES(LIBGTP, libgtp >= 1.4.0)
PKG_CHECK_MODULES(LIBCARES, libcares)
dnl checks for header files
@@ -110,15 +107,8 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([char foo;])],
CFLAGS="$saved_CFLAGS"
AC_SUBST(SYMBOL_VISIBILITY)
CPPFLAGS="$CPPFLAGS -Wall"
CFLAGS="$CFLAGS -Wall"
AX_CHECK_COMPILE_FLAG([-Werror=implicit], [CFLAGS="$CFLAGS -Werror=implicit"])
AX_CHECK_COMPILE_FLAG([-Werror=maybe-uninitialized], [CFLAGS="$CFLAGS -Werror=maybe-uninitialized"])
AX_CHECK_COMPILE_FLAG([-Werror=memset-transposed-args], [CFLAGS="$CFLAGS -Werror=memset-transposed-args"])
AX_CHECK_COMPILE_FLAG([-Wnull-dereference], [CFLAGS="$CFLAGS -Wnull-dereference"])
AX_CHECK_COMPILE_FLAG([-Werror=sizeof-array-argument], [CFLAGS="$CFLAGS -Werror=sizeof-array-argument"])
AX_CHECK_COMPILE_FLAG([-Werror=sizeof-pointer-memaccess], [CFLAGS="$CFLAGS -Werror=sizeof-pointer-memaccess"])
CPPFLAGS="$CPPFLAGS -Wall -Wno-trigraphs"
CFLAGS="$CFLAGS -Wall -Wno-trigraphs"
# Coverage build taken from WebKit's configure.in
AC_MSG_CHECKING([whether to enable code coverage support])
@@ -164,13 +154,13 @@ AC_ARG_ENABLE([external_tests],
[Include the VTY/CTRL tests in make check [default=no]]),
[enable_ext_tests="$enableval"],[enable_ext_tests="no"])
if test "x$enable_ext_tests" = "xyes" ; then
AC_CHECK_PROG(PYTHON2_AVAIL,python2,yes)
if test "x$PYTHON2_AVAIL" != "xyes" ; then
AC_MSG_ERROR([Please install python2 to run the VTY/CTRL tests.])
AC_CHECK_PROG(PYTHON3_AVAIL,python3,yes)
if test "x$PYTHON3_AVAIL" != "xyes" ; then
AC_MSG_ERROR([Please install python3 to run the VTY/CTRL tests.])
fi
AC_CHECK_PROG(OSMOTESTEXT_CHECK,osmotestvty.py,yes)
if test "x$OSMOTESTEXT_CHECK" != "xyes" ; then
AC_MSG_ERROR([Please install git://osmocom.org/python/osmo-python-tests to run the VTY/CTRL tests.])
AC_MSG_ERROR([Please install https://gitea.osmocom.org/cellular-infrastructure/osmo-python-tests to run the VTY/CTRL tests.])
fi
fi
AC_MSG_CHECKING([whether to enable VTY/CTRL tests])
@@ -239,21 +229,21 @@ AC_MSG_RESULT([CFLAGS="$CFLAGS"])
AC_MSG_RESULT([CPPFLAGS="$CPPFLAGS"])
dnl Generate the output
AM_CONFIG_HEADER(bscconfig.h)
AM_CONFIG_HEADER(config.h)
AC_OUTPUT(
include/Makefile
include/osmocom/Makefile
include/osmocom/gtphub/Makefile
include/osmocom/sgsn/Makefile
src/Makefile
src/gprs/Makefile
src/sgsn/Makefile
src/gbproxy/Makefile
src/gtphub/Makefile
tests/Makefile
tests/atlocal
tests/gprs/Makefile
tests/gbproxy/Makefile
tests/gprs_routing_area/Makefile
tests/sgsn/Makefile
tests/gtphub/Makefile
tests/xid/Makefile

View File

@@ -1,58 +0,0 @@
#!/usr/bin/env python
"""
demonstrate a unblock bug on the GB Proxy..
"""
bts_ns_reset = "\x02\x00\x81\x01\x01\x82\x1f\xe7\x04\x82\x1f\xe7"
ns_reset_ack = "\x03\x01\x82\x1f\xe7\x04\x82\x1f\xe7"
bts_ns_unblock = "\x06"
ns_unblock_ack = "\x07"
bts_bvc_reset_0 = "\x00\x00\x00\x00\x22\x04\x82\x00\x00\x07\x81\x03\x3b\x81\x02"
ns_bvc_reset_0_ack = "\x00\x00\x00\x00\x23\x04\x82\x00\x00"
bts_bvc_reset_8167 = "\x00\x00\x00\x00\x22\x04\x82\x1f\xe7\x07\x81\x08\x08\x88\x72\xf4\x80\x10\x1c\x00\x9c\x40"
import socket
socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
socket.bind(("0.0.0.0", 0))
socket.setblocking(1)
import sys
port = int(sys.argv[1])
print "Sending data to port: %d" % port
def send_and_receive(packet):
socket.sendto(packet, ("127.0.0.1", port))
try:
data, addr = socket.recvfrom(4096)
except socket.error, e:
print "ERROR", e
import sys
sys.exit(0)
return data
#send stuff once
to_send = [
(bts_ns_reset, ns_reset_ack, "reset ack"),
(bts_ns_unblock, ns_unblock_ack, "unblock ack"),
(bts_bvc_reset_0, ns_bvc_reset_0_ack, "BVCI=0 reset ack"),
]
for (out, inp, type) in to_send:
res = send_and_receive(out)
if res != inp:
print "Failed to get the %s" % type
sys.exit(-1)
import time
time.sleep(3)
res = send_and_receive(bts_bvc_reset_8167)
print "Sent all messages... check wireshark for the last response"

View File

@@ -32,25 +32,21 @@ export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
export LD_LIBRARY_PATH="$inst/lib"
export PATH="$inst/bin:$PATH"
osmo-build-dep.sh libosmo-netif "" --disable-doxygen
osmo-build-dep.sh libosmo-abis
osmo-build-dep.sh libosmo-netif
osmo-build-dep.sh osmo-ggsn
osmo-build-dep.sh osmo-hlr
enable_werror=""
if [ "x$IU" = "x--enable-iu" ]; then
osmo-build-dep.sh libosmo-sccp
osmo-build-dep.sh libosmo-sigtran "" --disable-doxygen
osmo-build-dep.sh libasn1c
#osmo-build-dep.sh asn1c aper-prefix # only needed for make regen in osmo-iuh
osmo-build-dep.sh osmo-iuh
else
enable_werror="--enable-werror"
fi
# Additional configure options and depends
CONFIG=""
if [ "$WITH_MANUALS" = "1" ]; then
osmo-build-dep.sh osmo-gsm-manuals
CONFIG="--enable-manuals"
fi
@@ -64,18 +60,18 @@ set -x
cd "$base"
autoreconf --install --force
./configure --enable-sanitize $enable_werror $IU --enable-external-tests $CONFIG
./configure --enable-sanitize --enable-werror $IU --enable-external-tests $CONFIG
$MAKE $PARALLEL_MAKE
LD_LIBRARY_PATH="$inst/lib" $MAKE check \
|| cat-testlogs.sh
LD_LIBRARY_PATH="$inst/lib" \
DISTCHECK_CONFIGURE_FLAGS="$enable_werror $IU --enable-external-tests $CONFIG" \
$MAKE distcheck \
DISTCHECK_CONFIGURE_FLAGS="--enable-werror $IU --enable-external-tests $CONFIG" \
$MAKE $PARALLEL_MAKE distcheck \
|| cat-testlogs.sh
if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
make -C "$base/doc/manuals" publish
fi
$MAKE maintainer-clean
$MAKE $PARALLEL_MAKE maintainer-clean
osmo-clean-workspace.sh

View File

@@ -1,11 +1,9 @@
EXTRA_DIST = \
osmo-gbproxy.service \
osmo-gtphub.service \
osmo-sgsn.service
if HAVE_SYSTEMD
SYSTEMD_SERVICES = \
osmo-gbproxy.service \
osmo-gtphub.service \
osmo-sgsn.service

View File

@@ -1,12 +0,0 @@
[Unit]
Description=Osmocom Gb proxy
[Service]
Type=simple
ExecStart=/usr/bin/osmo-gbproxy -c /etc/osmocom/osmo-gbproxy.cfg
Restart=always
RestartSec=2
RestartPreventExitStatus=1
[Install]
WantedBy=multi-user.target

View File

@@ -1,9 +1,15 @@
[Unit]
Description=Osmocom GTP Hub
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=osmocom
Group=osmocom
ExecStart=/usr/bin/osmo-gtphub -c /etc/osmocom/osmo-gtphub.cfg
StateDirectory=osmocom
WorkingDirectory=%S/osmocom
Restart=always
RestartSec=2
RestartPreventExitStatus=1

View File

@@ -3,10 +3,16 @@ Description=Osmocom SGSN (Serving GPRS Support Node)
Wants=osmo-hlr.service
After=osmo-hlr.service
After=osmo-hnbgw.service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
StateDirectory=osmocom
WorkingDirectory=%S/osmocom
Restart=always
User=osmocom
Group=osmocom
ExecStart=/usr/bin/osmo-sgsn -c /etc/osmocom/osmo-sgsn.cfg
RestartSec=2

508
debian/changelog vendored
View File

@@ -1,3 +1,511 @@
osmo-sgsn (1.12.0) unstable; urgency=medium
[ Andreas Eversberg ]
* Use uniform log format for default config files
[ Vadim Yanitskiy ]
* build: include README.md into the release tarball
* gmm: cosmetic: fix preprocessor macro formatting
* gmm: mmctx_timer_stop(): warn about timer not running
* VTY: move default settings to sgsn_instance_alloc()
* VTY: sync default UMTS UEA config with osmo-msc
* README.md: cosmetic: fix a typo
[ Pau Espin Pedrol ]
* gsup: Use new libosmogsm struct osmo_gsup_pdp_info fields
[ Harald Welte ]
* Add funding link to github mirror
* README.md: Overhaul (more links; improved formatting)
* README.md: Add Forum and Issue Tracker sections
[ Max ]
* .deb/.rpm: add osmocom user during package install
[ Oliver Smith ]
* contrib/osmo-sgsn.spec: fix build for almalinux:8
* .deb/.rpm: various fixes related to non-root
* contrib: remove rpm spec file
* debian/postinst: add checks, be verbose
* sgsn/sgsn_vty: create state-dir
* debian/osmo-gtphub.init: delete
* doc: set state-dir to /var/lib/osmocom/osmo-sgsn
[ Alexander Couzens ]
* docs: replace legacy NS with new NS2 chapters
* docs: update year to 2024
* docs: front page: use https:// instead of http://
-- Oliver Smith <osmith@sysmocom.de> Wed, 24 Jul 2024 17:31:38 +0200
osmo-sgsn (1.11.1) unstable; urgency=medium
[ Philipp Maier ]
* sgsn_rim: forward message based on RIM ROUTING ADDRESS
[ Daniel Willmann ]
* sgsn_vty: Fix output in config_write_sgsn
* sgsn_vty: Correctly indent encryption cipher-plugin-path
* vty-tests: Test encryption options
* libgtp: Check for all successful create_pdp_conf causes
-- Oliver Smith <osmith@sysmocom.de> Tue, 28 Nov 2023 13:32:46 +0100
osmo-sgsn (1.11.0) unstable; urgency=medium
[ Oliver Smith ]
* Run struct_endianness.py
* debian: set compat level to 10
* systemd: depend on networking-online.target
[ arehbein ]
* Transition to use of 'telnet_init_default'
[ Vadim Yanitskiy ]
* tests: use -no-install libtool flag to avoid ./lt-* scripts
* tests: $(BUILT_SOURCES) is not defined, depend on osmo-sgsn
* copyright: fix typo: sysmocom s/s.m.f.c./s.f.m.c./ GmbH
[ Pau Espin Pedrol ]
* gmm: Ciphering Key Sequence Number IE has half octet tag
* gprs_sm.c: Fix load of misaligned ptr address
* Write explicit role & sctp-role fields in ASP configurations
* gmm: Update DRX params during rx RAU REQ
* gmm: Add missing GSM48_IE_GMM_RX_NPDU_NUM_LIST IE in gsm48_gmm_att_tlvdef
[ Philipp Maier ]
* sgsn_rim: fix typo
* sgsn_rim: cosmetic: improve comment
* sgsn_rim: get rid of MME check in sgsn_rim_rx_from_gtp:
* sgsn_rim: do not check the origin of a RIM message
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 12 Sep 2023 16:57:02 +0200
osmo-sgsn (1.10.0) unstable; urgency=medium
[ Vadim Yanitskiy ]
* configure.ac: do not require unused dlsym/dlopen
* gprs_llc: fix misleading spacing in gprs_llc_rcvmsg()
* gprs_llc.h: use '#pragma once'
* llc: gprs_llc_fcs(): make the input data pointer const
[ Max ]
* Set working directory in systemd service file
* SNDCP: log more details on failure
* GTP: migrate from deprecated function
* Constify LLC/SNDCP parameters
* GMM: permit E_GMM_COMMON_PROC_SUCCESS in normal state
* ctrl: take both address and port from vty config
[ Pau Espin Pedrol ]
* vty: Make new libgtp tdefs configurable through VTY
* sndcp: Put decompress handling code into helper function
* Move gprs_gb_parse.[c,h] to tests/sgsn/
* Create new specific file for BSSGP code
* Move some functions gprs_gb.[c,h] -> gprs_gmm.[c,h]
* Rename gprs_gb.[c,h] -> gprs_ns.[c,h]
* Move gprs_tmr_to_secs() to tests/gprs/gprs_test.c
* cosmetic: gprs_llc_vty.c: Fix trailing whitespace
* vty: Fix wrong value_string used to print llme state
* Standarize lle and llme state enum & value_string
* Remove unused function gprs_parse_mi_tmsi()
* Replace gprs_str_to_apn() with libosmocore API osmo_apn_from_str()
* Move struct sgsn_ggsn_ctx to its own file gtp_ggsn.{c,h}
* gprs_subscriber: Move API declarations to correct header
* Move gprs_sndcp_vty_init() declaration to gprs_sndcp.h
* Introduce new header file sgsn/gtp.h
* Fix -Werror=old-style-definition
* Move related structs to gprs_subscriber.h
* Remove unneeded extern declaration from libosmocotrl
* Keep sgsn subsystems under struct sgsn_instance lifecycle
* Move global ggsn_list into struct sgsn_instance
* Move struct apn_ctx and APN related definitions to its own file
* Move struct sgsn_subscriber_pdp_data to gprs_subscriber.h
* sgsn.h: Drop declaration of non existing function
* Properly split llc->sndcp->gtp unitdata pathi through extra func call
* Move func defintions of funcs implemented in gprs_sndcp.c to gprs_sndcp.h
* sndcp: Standarize unitdata function naming
* Move gtp related functions to gtp.h
* Move global apn_list inside struct sgsn_instance
* gtp_{ggsn,mme}: Allocate contexts under struct sgsn_instance
* Move extern declarations of tall_sgsn_ctx to sgsn.h
* Drop extern declarations of global sgsn_instance in source files
* Move sgsn_pdp_ctx to its own file pdpctx.{c,h}
* Move global pdp_list inside struct sgsn_instance
* Move gtphub header to include/osmocom/gtphub/
* Move sgsn_ctrl_cmds_install() declaration to sgsn.h
* Move LOGGSUBSCRP to gprs_subscriber.h
* Rename bscconfig.h -> config.h
* gtphub.h: Remove dependency on sgsn/gprs_sgsn.h
* Split gprs_sgsn.{c,h} -> {auth,mmctx,sgsn}.{c,h}
* Move global mmctx list into struct sgsn_instance
* vty: Introduce encryption cipher-plugin-path command
* Fix extra whitespace in pdpctx_ctr_description
[ Oliver Smith ]
* contrib/jenkins.sh: use enable-werror with IU too
* sgsn_libgtp: cb_data_ind: remove mm_idle assert
* osmo-gtphub.cfg: fix conflict with osmo-ggsn.cfg
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 07 Feb 2023 17:34:26 +0100
osmo-sgsn (1.9.0) unstable; urgency=medium
[ Oliver Smith ]
* llme_free: clean up related sndcp
* treewide: remove FSF address
[ Pau Espin Pedrol ]
* Drop unneeded ax_check_compile_flag.m4
* Revert "sgsn: Handle different levels of QoS"
[ Neels Hofmeyr ]
* s/cipher_support_mask/gea_encryption_mask
* Iu: add UEA encryption
[ Vadim Yanitskiy ]
* tests: use 'check_PROGRAMS' instead of 'noinst_PROGRAMS'
[ Harald Welte ]
* update git URLs (git -> https; gitea)
* README: Major update
-- Pau Espin Pedrol <pespin@sysmocom.de> Wed, 29 Jun 2022 11:45:08 +0200
osmo-sgsn (1.8.0) unstable; urgency=medium
[ Harald Welte ]
* Remove bogus DNS log category
[ Daniel Willmann ]
* manuals: Regenerate counters/VTY through docker
[ Vadim Yanitskiy ]
* main: resurrect removed 'ns' logging category as deprecated
* doc/manuals: update configuration.adoc to use new command syntax
* tests/Makefile.am: do not try removing non-existing files
[ Pau Espin Pedrol ]
* ranap: log ranap iu event type name instead of number
* gmm: log GMM msg type name instead of number
* gmm: Expect E_VLR_ANSWERED when in ST_IU_SECURITY_CMD
* gmm_fsm: Expect E_GMM_COMMON_PROC_INIT_REQ when in ST_GMM_COMMON_PROC_INIT
* mm_iu: Send event E_PMM_PS_CONN_ESTABLISH upon rx GMM SERVICE REQUEST
* mm_iu: Expect E_PMM_PS_ATTACH when in ST_PMM_IDLE
* gprs_gmm.c: State proper GMM prefix logging rx/tx of GMM messages
* mm_state_iu_fsm: T3314 expiry must lead to PMM IDLE, not PMM DETACHED
* Iu: Drop timer X3314
* gprs_ranap.c: Clean up code path releasing IU conn
* mm_state_{gb,iu}_fsm: Add missing license block, improve spec references
* mm_state_{gb,iu}_fsm: Improve naming for detach event
* Drop unused GBRPOXY enum field
* gtp: Delete ctx upon receive UpdateCtxResp with cause Non-existent
* Support forwarding RIM messages over GTPCv1 EUTRAN<->GERAN
* Use new stat item/ctr getter APIs
[ Keith ]
* vty: Fix optional display of pdp with mm-context
* VTY: Don't display 'PDP Address: invalid' for IPv4v6
[ Eric ]
* add support for multiple encryption algorithms and a5/4
[ Oliver Smith ]
* gtphub: remove llist_first, llist_last macros
* vty: add "page imsi"
* debian/control: remove dh-systemd build-depend
* Revert "Turn some compiler warnings into errors"
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 16 Nov 2021 17:57:50 +0100
osmo-sgsn (1.7.0) unstable; urgency=medium
[ Daniel Willmann ]
* gprs_gmm: Check for RAT change and ensure this only happens for RAU/ATT
* gbproxy-usermanual: Explain BSSGP/BVC handling
* gbproxy: Whitespace fixes
* gbproxy: Add todo for BVC RESET logic
* gbproxy: Get the peer if paging by BVCI on SIG_BVC
* Let libosmocore handle VTY parent node tracking
* osmo-gbproxy: Free msgb in ns2 prim callback
* configure.ac: Require python3 for ext_tests
* osmo-gbproxy: Implement nsvc-state ctrl command
* gbproxy: Remove test testing NSVCI change
* gbproxy: Add NSE peer that can have multiple gbproxy_peers
* gbproxy: Ensure BVC0 is reset before handling PtP BVCs
* gbproxy: Only send paging to each matching NSE once
* gbproxy: Separate function to move gbproxy_peer to different nse
* gbproxy: Add logging macros for NSE and BVC
* gbproxy: Use LOG macros for NSE/BVC
* gbproxy: Change generic LOG messages so BVCI/NSEI fmt is consistent
* gbproxy: Add todos encountered while going through the code
* gbproxy: Add BVC log filters
* gbproxy: Add newline to log message
* gbproxy: Allow gbproxy_nse_free(NULL)
* gbproxy: Delete gbproxy_nse in delete-gbproxy-peer VTY command
* mm_state_gb_fsm: Handle implicit detach from mm_standby
* gbproxy: Fix bvci check in gbprox_rx_ptp_from_*
* osmo-gbproxy: Initialize all hash_maps
* gbproxy: Fix confusing log message in gbprox_relay2nse
* gbproxy: Add SGSN NRI configuration
* gbproxy: Add SGSN pooling support
* gbproxy: Add comments to sgsn functions
* gbproxy: Add config option to name an SGSN
* gbproxy: Add VTY command to override the node selection function
* Fix gbproxy_sgsn_by_tlli wraparound
* gbproxy: Implement TLLI cache and use it for SUSPEND/RESUME
* gbproxy: Increase TLLI cache timeout to 10s
* gbproxy: Implement IMSI cache
* gbproxy: Use IMSI cache to handle PAGING_PS_REJECT
* gbproxy: Use C-style comments
* gbproxy: Move helper function to a more logical place
* gbproxy: Remove unused variable assignment
* gbproxy: Fix VTY cmd name
* gbproxy: Define and use help string for gbproxy
* gbproxy: Add VTY commands to query the TLLI/IMSI cache
* gbproxy: Use IMSI cache for PTP paging and implement DUMMY_PAGING_PS
* gbproxy: Print the correct message type for dummy paging/paging reject
* gbproxy: Improve log messages in gbproxy_select_sgsn
* gbproxy: Fix radio status routing by TMSI
* manual/gbproxy: Update overview chapter
* Rename OsmoGbPROXY -> *Proxy
* manuals/gbproxy: Update configuration chapter
* manuals/gbproxy: Add osmo-bsc MSC pooling chapter from Neels as a base
* manuals/gbproxy: MSC -> SGSN for pooling chapter
* manuals/gbproxy: Move pooling to separate chapter
[ Alexander Couzens ]
* gprs_gmm_fsm.c: Implement RAT change between 2g and 3g
* gtphub: rename sgsn's oww osmo_sockaddr into sgsn_sockaddr
* gprs_llc: _bssgp_tx_dl_ud: ensure the LLME is valid before using it
* gmm: on invalid RA id reject the MS with an implicit detach
* gtphub_test: fix compilation error on gcc 10.2.0
* gtphub: fix compilation with gcc 10.2.0
* Port gbproxy to NS2
* sgsn: check for NULL of gprs_subscr_get_or_create()
* sgsn: Use the new NS2 api
* gbproxy: use ns2 vty2
* configure.ac: define a c standard instead of using the compilers default
* follow libosmocore/gprs_ns2 API changes of GPRS enums
* gbproxy: follow gprs_ns2 API vty changes
* sgsn: migrate to the new gprs_ns2_vty configuration
* follow libosmocore/gprs_ns2 API changes (gprs_ns2_dynamic_create_nse)
[ Neels Hofmeyr ]
* manual: explain IuPS, add SCCP/M3UA section from common chapters
* fix nullpointer: in gsm48_rx_gmm_ra_upd_req()
* gsup: send RAT type on LU
* gbproxy_test.c: fix mobile identity test data
* use new osmo_mobile_identity API everywhere
[ Eric ]
* tests: dlopen does not imply availability of dlsym..
* configure.ac: fix libtool issue with clang and sanitizer
[ Harald Welte ]
* gtphub_test: Fix compilation with gcc-10
* Fix memory leak when SNDCP de-fragmentation is used
* Treat RAU as implicit RESUME if GMM is suspended
* *.spec.in: Use %config(noreplace) to retain current config file
* Send a BVC-RESET to all persistent Gb interfaces at start-up
* Use osmo_fd_setup() whenever applicable
* Use osmo_fd_*_{disable,enable}
* gbproxy: Properly implement paging to LAC/RAC
* gbproxy: Implement paging to entire BSS area
* gprs_gb_parse: Add function to determine TLLI from encoded BSSGP
* gbproxy: Pass TLLI as LSP towards NS to facilitate load sharing
* gb_proxy_peer: Add some FIXMEs regarding invalid assumptions
* gb_proxy: More precise + readable log messages
* gb_proxy: Broadcast SGSN-INVOKE-TRACE and OVERLOAD
* gbproxy: Move BSS-side BVC-RESET processing to its own function
* gb_proxy: Slightly restructure processing of BSS-originated BVC-RESET
* gbproxy: Cosmetics: use longer lines
* gbproxy: Send BVC-STATUS if BSS sends us BVC-RESET without mandatory IEs
* gb_proxy: Use TLVP_PRES_LEN instead of TLVP_PRESENT
* gb_proxy: Rename gbproxy_peer to gbproxy_bvc
* gbproxy: Rename gbproxy_cfg.nses to gbproxy_cfg.bss_nses
* gbproxy: convert bss_nses from llist_head to hashtable
* gbproxy: convert nse->bvcs from llist_head to hashtable
* gbproxy: Remove patching, TLLI-tracking and SGSN2 support
* gb_proxy: cosmetic: Use function rather than open-coding is_sgsn
* gbproxy: Delete gbproxy_test
* gb_proxy: Introduce more validation / constraint checks
* gbproxy: use gbprox_relay2peer() whenever possible
* gb_proxy: Use osmo_tlv_prot_parse() to validate mandatory IEs
* gbproxy: Log FSM timeouts
* migrate to DLBSSGP as log sub-system for BSSGP
* gbproxy major rewrite for SGSN pool support
* gbproxy: Use "(nsei << 16) | bvci" as rate_ctr_group index
* gbproxy: Introduce new DOBJ log category; log object allocation/release
* gbproxy: Don't create an extra msgb copy for SGSN DL SIG
* gbproxy: Implement handling of BVC Flow Control
* gbproxy: Copy RA-ID from BSS side BVC to CELL and SGSN-side BVC
* gbproxy: (Re)allocate SGSN-side PTP BVC even if CELL already exists
* gbproxy: Fix segfault when receiving PAGING for unknown destination
* gbproxy: Add FSM related VTY commands
* gbproxy: Implement scaling of BVC flow control in SGSN pool
* gbproxy: Improve VTY state introspection
* gbproxy: rename vty command "show gbproxy ..." to "show gbproxy bvc ..."
* gbproxy: Add "show gbproxy cell ..." VTY command
* gbproxy: Fix build on Deiban 8
* gb_proxy: Don't use orphan log subsystem DPCU
* gbproxy: Avoid depending on any of the SGSN code
* main: add --vty-ref-mode, use vty_dump_xml_ref_mode()
* manuals: generate vty reference xml at build time
[ Pau Espin Pedrol ]
* Use OSMO_FD_* instead of deprecated BSC_FD_*
* sgsn_libgtp: Improve ps-paging logging
* gprs_gmm_fsm.c: Add missing license header
* sgsn_libgtp: Avoid ps-paging MS on GMM Suspended state
* configure.ac: Fix trailing whitespace
* doc: Update VTY reference xml file
* Support setting rt-prio and cpu-affinity mask through VTY
* Change default SCTP conn NULL->127.0.0.1 to localhost->localhost
* contrib/jenkins: Enable parallel make in make distcheck
* Log error if pdp ctx is freed while holding an active timer
* Fix crash rx DeactPdpReq while waiting for DeactPdpAck after gtp side is freed
* sgsn_delete_pdp_ctx: Add documentation and assert assumptions
* process_ms_ctx_status: refactor to avoid code duplication
* process_ms_ctx_status: Fix crash deleting PDP Ctx if GTP side was already released
* gbproxy: generate coredump and exit upon SIGABRT received
* gtphub: generate coredump and exit upon SIGABRT received
* sgsn: generate coredump and exit upon SIGABRT received
* gmm: fix build without define PTMSI_ALLOC
* gmm: Introduce comment to ease addition of Network feature support IE later
* .gitignore: Ignore new autofoo tmp files
* sndcp: Fix struct bit fields on big endian
* Fix nsei+bvci not updated on rx UL SNDCP data
[ Oliver Smith ]
* contrib: import RPM spec
* contrib: integrate RPM spec
* Makefile.am: EXTRA_DIST: debian, contrib/*.spec.in
* contrib/jenkins: don't build osmo-gsm-manuals
* gbproxy: remove (moved to own repository)
[ Vadim Yanitskiy ]
* debian/control: change maintainer to the Osmocom team / mailing list
* gb_proxy_peer: sgsn can never be NULL in gbproxy_sgsn_by_nri()
* gb_proxy_peer: fix NULL pointer dereference in gbproxy_sgsn_alloc()
[ Keith ]
* Fix Radio Priority in MM Attach and PDP Context Activation
* VTY: Add gtp state-dir command
[ Philipp Maier ]
* gprs_sndcp: fix use after free
* sgsn_rim: Add routing for (GERAN) BSSGP RIM messages
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 23 Feb 2021 20:29:33 +0100
osmo-sgsn (1.6.0) unstable; urgency=medium
[ Pau Espin Pedrol ]
* gprs_gmm: Introduce macros to access msgb's associated IU UE ctx
* gprs_llc.h: Improve documentation of some structs
* gprs_gmm.c: Improve doc on nullable parameters
* gprs_gmm.c: Drop unneeded brackets
* Introduce define TLLI_UNASSIGNED
* gprs_sgsn.c: Warn upon llme free unexpected scenarios
* gprs_gmm: Clarify comment during TLLI assignment
* gprs_sgsn.c: Remove recently introduced assert
* gprs_gmm: Introduce assert to guard against unexpected condition
* gprs_gmm.c: Use correct function to set MM_IDLE state during cleanup
* gprs_sgsn.h: Flag MM_CTX_T_GERAN_Iu as not supported
* gprs_gmm.c: Flag mmctx_set_(p)mm_state() functions static
* sgsn: use sccp_simple_client API to setup ss7 id 0 instead of 1
* gprs_gmm.c: Fix typo in log message
* gprs_gmm.c: Call mmctx_set_(p)mm_state only on related ran_type
* Introduce and use log macros when no mm ctx available
* gprs_gmm: Avoid spaces in fsm events and enum strings
* tests: Verify that timers can be set over VTY
* Replace own timer infra with libosmocore osmo_tdef
* tests: Introduce vty-transcript-test tests
* gprs_gmm.c: Use osmo_rai_name() in log line
* examples: Add osmo-sgsn_custom-sccp.cfg
* vty: Introduce cs7-instance-iu
* gprs_gmm.c: Print value_string of reject cause
* gprs_gmm.c: Add spec document to function documentation
* gtp: make echo_interval unsigned
* gtp: cb_delete_context(): Clarify why pdp->lib is set to NULL
* Introduce log helper LOGGGSN and log category DGTP
* sgsn: gtp: Drop related pdp contexts on echo timeout against GGSN
* Move lots of Iu/ranap specific code into its own file
* Move llc->MM/SM Gb specific glue code to its own file
* Split enum gprs_pmm_state into Iu and Gb counterparts
* Merge common allocation steps for Gb and Iu ctx
* gprs_gmm.c: Replace inet_ntoa with inet_ntop
* sgsn_cdr.c: Fix ip addr string buffer size
* sgsn_vty: Fix mmctx rate_ctr output indentation
* sgsn_vty: Print correct Iu mmctx id in 'show mm-context'
* Introduce FSM mm_state_gb_fsm
* Introduce FSM mm_state_iu_fsm
* vty: Print MM state and RAN type in show mm-context
* src/gprs/Makefile.am: Move build of shared .c files to an internal lib
* Move out gbproxy to its own subdir
* Move out gtphub to its own subdir
* Move out sgsn to its own subdir
* gmm: Move code handling GMM Attach Complete to its own function
* gmm: Move code handling GMM Routing Area Update Complete to its own function
* gmm: Move code handling GMM PTMSI Realloc Complete to its own function
* enum gprs_gmm_state: Fix spec reference
* Implement GMM State using osmocom FSM
* Split out GPRS SM layer into its own file
* sgsn: Reject PdpActReq if no GTP pdp ctx exists
* Introduce TODO-RELEASE file
* sgsn_libgtp.c: Drop use of deprecated libgtp APIs gtp_retrans*()
* gmm: Fix assertion hit during RA UPD REQ before completting gmm attach
* Improve logging in gprs_llc.c code
* gprs_llc.c: Use enum instead of hardcoded value
* gprs_gmm.c: Send XID reset with received TLLI
[ Alexander Couzens ]
* gprs/gprs_gmm: implement T3314. Timeout to reset MM state READY->STANDBY
* gprs_gmm: only update gb/iu cell information when Iu/Gb present
* gprs_gmm: clarify comment of Iu follow-on request
* gprs_gmm: gsm48_rx_gmm_att_req(): refactor duplicated code
* sgsn_pdp_ctx_terminate: check llme before accessing
* gprs_ranap: send CommonId after receiving Security Mode Complete
* mm_gb_fsm: unassign the llme when entering MM_IDLE
* gprs_ranap: refactor REQUIRE_MM define
* sgsn: when receiving data PDU notify the Gb GMM fsm
* Avoid compiling unneeded files when building without Iu
* gprs_ranap: release Iu UE Context when exiting PMM Connected
* Iu: implement a user inactivity timer
* gprs_ranap: on Iu release, stop the attach fsm if running
* gprs_mm_state_gb_fsm: ensure T3350 is not running when entering IDLE
* gprs_ranap: add missing rc = 0
* gprs_sgsn: always allocate Gb/Iu mm fsm
* sgsn: MM Gb Fsm: fix event handling for implicit detach
* ranap: add non-spec X1001
* gprs_gmm: release Iu connection on RAU failures
* sgsn_mm_ctx_alloc(): check for unallocated fsms
* sgsn_libgtp: refactor ps paging into gprs_gb
* sgsn: Gb: implementing PS Paging when MS is MM_STANDBY
[ Vadim Yanitskiy ]
* gprs_mm_state_iu_fsm.c: fix: assign timer_cb to mm_state_iu_fsm
[ Max ]
* Use libosmocore constant for IMSI length in ACL entry
[ Harald Welte ]
* LLC: Don't use hard-coded N201-U / N201-I values in XID
* Initial OsmoGbPROXY user manual
* check for osmo_fsm_register() error return values
* check for osmo_ss7_init() error return value
* manual: Fix copy+paste error
* exit(2) on unsupported positional arguments on command line
[ Oliver Smith ]
* gitignore: fix paths to binaries
* doc: add OsmoGbProxy VTY reference
* regen_doc.sh: support gbproxy, run without docker
* osmoappdesc.py, tests: switch to python 3
-- Pau Espin Pedrol <pespin@sysmocom.de> Fri, 03 Jan 2020 19:17:56 +0100
osmo-sgsn (1.5.0) unstable; urgency=medium
[ Max ]

2
debian/compat vendored
View File

@@ -1 +1 @@
9
10

41
debian/control vendored
View File

@@ -1,10 +1,9 @@
Source: osmo-sgsn
Section: net
Priority: extra
Maintainer: Alexander Couzens <lynxis@fe80.eu>
Build-Depends: debhelper (>=9),
Maintainer: Osmocom team <openbsc@lists.osmocom.org>
Build-Depends: debhelper (>= 10),
dh-autoreconf,
dh-systemd (>= 1.5),
autotools-dev,
autoconf,
automake,
@@ -12,19 +11,17 @@ Build-Depends: debhelper (>=9),
pkg-config,
libtalloc-dev,
libc-ares-dev,
libgtp-dev (>= 1.4.0),
libosmocore-dev (>= 1.2.0),
libosmo-abis-dev (>= 0.6.0),
libosmo-netif-dev (>= 0.4.0),
libosmo-gsup-client-dev (>= 1.0.0),
libgtp-dev (>= 1.12.0),
libosmocore-dev (>= 1.10.0),
libosmo-abis-dev (>= 1.6.0),
libosmo-gsup-client-dev (>= 1.8.0),
libasn1c-dev (>= 0.9.30),
libosmo-ranap-dev (>= 0.4.0),
libosmo-sigtran-dev (>= 1.0.0),
libosmo-sccp-dev (>= 1.0.0),
osmo-gsm-manuals-dev
libosmo-ranap-dev (>= 1.6.0),
libosmo-sigtran-dev (>= 1.9.0),
osmo-gsm-manuals-dev (>= 1.6.0)
Standards-Version: 3.9.8
Vcs-Git: git://git.osmocom.org/osmo-sgsn.git
Vcs-Browser: https://git.osmocom.org/osmo-sgsn
Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-sgsn
Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-sgsn
Homepage: https://projects.osmocom.org/projects/osmo-sgsn
@@ -53,22 +50,6 @@ Priority: extra
Depends: osmo-gtphub (= ${binary:Version}), ${misc:Depends}
Description: Debug symbols for Osmocom GTP Hub
Package: osmo-gbproxy
Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends}
Recommends: osmo-sgsn
Description: Osmocom GPRS Gb Interface Proxy
The purpose of the Gb proxy is to aggregate the Gb links of multiple
BSS's and present them in one Gb link to the SGSN.
Package: osmo-gbproxy-dbg
Architecture: any
Section: debug
Priority: extra
Depends: osmo-gbproxy (= ${binary:Version}), ${misc:Depends}
Description: Debug symbols for Osmocom GPRS Gb Interface Proxy
Package: osmo-sgsn-doc
Architecture: all
Section: doc

20
debian/copyright vendored
View File

@@ -1,6 +1,6 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: osmo-sgsn
Source: git://git.osmocom.org/osmo-sgsn
Source: https://gitea.osmocom.org/cellular-infrastructure/osmo-sgsn
Files: .gitignore
.gitreview
@@ -19,13 +19,10 @@ Files: .gitignore
contrib/ipa.py
contrib/jenkins.sh
contrib/soap.py
contrib/systemd/osmo-gbproxy.service
contrib/systemd/osmo-sgsn.service
contrib/twisted_ipa.py
doc/Makefile.am
doc/examples/Makefile.am
doc/examples/osmo-gbproxy/osmo-gbproxy-legacy.cfg
doc/examples/osmo-gbproxy/osmo-gbproxy.cfg
doc/examples/osmo-gtphub/gtphub-example.txt
doc/examples/osmo-gtphub/osmo-gtphub-1iface.cfg
doc/examples/osmo-gtphub/osmo-gtphub.cfg
@@ -36,7 +33,6 @@ Files: .gitignore
include/osmocom/sgsn/crc24.h
include/osmocom/sgsn/debug.h
include/osmocom/sgsn/gb_proxy.h
include/osmocom/sgsn/gprs_gb_parse.h
include/osmocom/sgsn/gprs_gmm.h
include/osmocom/sgsn/gprs_llc.h
include/osmocom/sgsn/gprs_sgsn.h
@@ -51,13 +47,12 @@ Files: .gitignore
src/gprs/osmo_sgsn.cfg
tests/Makefile.am
tests/atlocal.in
tests/gbproxy/Makefile.am
tests/gbproxy/gbproxy_test.ok
tests/gprs/Makefile.am
tests/gprs/gprs_test.c
tests/gprs/gprs_test.ok
tests/gtphub/Makefile.am
tests/gtphub/gtphub_test.ok
tests/sgsn/gprs_gb_parse.h
tests/sgsn/Makefile.am
tests/sgsn/sgsn_test.ok
tests/slhc/Makefile.am
@@ -79,19 +74,12 @@ Files: include/osmocom/sgsn/a_reset.h
include/osmocom/sgsn/gprs_sndcp_pcomp.h
include/osmocom/sgsn/gprs_sndcp_xid.h
include/osmocom/sgsn/gprs_utils.h
include/osmocom/sgsn/gtphub.h
include/osmocom/gtphub/gtphub.h
include/osmocom/sgsn/signal.h
src/gprs/gprs_llc_parse.c
src/gprs/crc24.c
src/gprs/gprs_gb_parse.c
src/gprs/gprs_utils.c
src/gprs/sgsn_ares.c
src/gbproxy/gb_proxy.c
src/gbproxy/gb_proxy_main.c
src/gbproxy/gb_proxy_patch.c
src/gbproxy/gb_proxy_peer.c
src/gbproxy/gb_proxy_tlli.c
src/gbproxy/gb_proxy_vty.c
src/gtphub/gtphub.c
src/gtphub/gtphub_main.c
src/gtphub/gtphub_vty.c
@@ -114,6 +102,7 @@ Files: include/osmocom/sgsn/a_reset.h
src/sgsn/sgsn_main.c
src/sgsn/sgsn_vty.c
tests/gtphub/gtphub_test.c
tests/sgsn/gprs_gb_parse.c
tests/sgsn/sgsn_test.c
tests/slhc/slhc_test.c
tests/sndcp_xid/sndcp_xid_test.c
@@ -142,7 +131,6 @@ License: AGPL-3.0+
Files: src/gtphub/gtphub_ares.c
src/gtphub/gtphub_sock.c
tests/gbproxy/gbproxy_test.c
Copyright: 2013 Jacob Erlbeck <jerlbeck@sysmocom.de>
2013 sysmocom s.f.m.c. GmbH
2014 Holger Hans Peter Freyther

View File

@@ -1,151 +0,0 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: osmo-gbproxy
# Required-Start: $network $local_fs
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Osmocom GBproxy
# Description: A tool to proxy the GPRS Gb interface.
### END INIT INFO
# Author: Harald Welte <laforge@gnumonks.org>
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
NAME=osmo-gbproxy # Introduce the short server's name here
DESC="Osmocom GBProxy" # Introduce a short description here
DAEMON=/usr/bin/osmo-gbproxy # Introduce the server's location here
SCRIPTNAME=/etc/init.d/osmocom-gbproxy
CONFIG_FILE=/etc/osmocom/osmocom-gbproxy.cfg
# Exit if the package is not installed
[ -x $DAEMON ] || exit 0
# Read configuration variable file if it is present
[ -r /etc/default/osmocom-gbproxy ] && . /etc/default/osmocom-gbproxy
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions
DAEMON_ARGS="-D -c $CONFIG_FILE"
#
# Function that starts the daemon/service
#
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
start-stop-daemon --start --quiet --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --exec $DAEMON -- \
$DAEMON_ARGS \
|| return 2
# Add code here, if necessary, that waits for the process to be ready
# to handle requests from services started subsequently which depend
# on this one. As a last resort, sleep for some time.
}
#
# Function that stops the daemon/service
#
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --name $NAME
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
# Wait for children to finish too if this is a daemon that forks
# and if the daemon is only ever run from this initscript.
# If the above conditions are not satisfied then add some other code
# that waits for the process to drop all resources that could be
# needed by services started subsequently. A last resort is to
# sleep for some time.
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
[ "$?" = 2 ] && return 2
return "$RETVAL"
}
#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
#
# If the daemon can reload its configuration without
# restarting (for example, when it is sent a SIGHUP),
# then implement that here.
#
start-stop-daemon --stop --signal 1 --quiet $PIDFILE --name $NAME
return 0
}
case "$1" in
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME"
do_start
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
status)
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
;;
#reload|force-reload)
#
# If do_reload() is not implemented then leave this commented out
# and leave 'force-reload' as an alias for 'restart'.
#
#log_daemon_msg "Reloading $DESC" "$NAME"
#do_reload
#log_end_msg $?
#;;
restart|force-reload)
#
# If the "reload" option is implemented then remove the
# 'force-reload' alias
#
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
exit 3
;;
esac
:

View File

@@ -1,5 +0,0 @@
etc/osmocom/osmo-gbproxy.cfg
lib/systemd/system/osmo-gbproxy.service
usr/bin/osmo-gbproxy
usr/share/doc/osmo-sgsn/examples/osmo-gbproxy/osmo-gbproxy-legacy.cfg usr/share/doc/osmo-gbproxy/examples
usr/share/doc/osmo-sgsn/examples/osmo-gbproxy/osmo-gbproxy.cfg usr/share/doc/osmo-gbproxy/examples

View File

@@ -1,150 +0,0 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: osmo-gtphub
# Required-Start: $network $local_fs
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Osmocom GTP hub
# Description: Osmocom GTP hub
### END INIT INFO
# Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
NAME=osmo-gtphub # Introduce the short server's name here
DESC="Osmocom GTP hub" # Introduce a short description here
DAEMON=/usr/bin/osmo-gtphub # Introduce the server's location here
SCRIPTNAME=/etc/init.d/osmo-gtphub
# Exit if the package is not installed
[ -x $DAEMON ] || exit 0
# Read configuration variable file if it is present
[ -r /etc/default/osmo-gtphub ] && . /etc/default/osmo-gtphub
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions
DAEMON_ARGS="$DAEMON_ARGS -D -c $CONFIG_FILE"
#
# Function that starts the daemon/service
#
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
start-stop-daemon --start --quiet --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --exec $DAEMON -- \
$DAEMON_ARGS \
|| return 2
# Add code here, if necessary, that waits for the process to be ready
# to handle requests from services started subsequently which depend
# on this one. As a last resort, sleep for some time.
}
#
# Function that stops the daemon/service
#
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --name $NAME
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
# Wait for children to finish too if this is a daemon that forks
# and if the daemon is only ever run from this initscript.
# If the above conditions are not satisfied then add some other code
# that waits for the process to drop all resources that could be
# needed by services started subsequently. A last resort is to
# sleep for some time.
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
[ "$?" = 2 ] && return 2
return "$RETVAL"
}
#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
#
# If the daemon can reload its configuration without
# restarting (for example, when it is sent a SIGHUP),
# then implement that here.
#
start-stop-daemon --stop --signal 1 --quiet $PIDFILE --name $NAME
return 0
}
case "$1" in
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME"
do_start
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
status)
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
;;
#reload|force-reload)
#
# If do_reload() is not implemented then leave this commented out
# and leave 'force-reload' as an alias for 'restart'.
#
#log_daemon_msg "Reloading $DESC" "$NAME"
#do_reload
#log_end_msg $?
#;;
restart|force-reload)
#
# If the "reload" option is implemented then remove the
# 'force-reload' alias
#
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
exit 3
;;
esac
:

38
debian/postinst vendored Executable file
View File

@@ -0,0 +1,38 @@
#!/bin/sh -e
case "$1" in
configure)
# Create the osmocom group and user (if it doesn't exist yet)
if ! getent group osmocom >/dev/null; then
groupadd --system osmocom
fi
if ! getent passwd osmocom >/dev/null; then
useradd \
--system \
--gid osmocom \
--home-dir /var/lib/osmocom \
--shell /sbin/nologin \
--comment "Open Source Mobile Communications" \
osmocom
fi
# Fix permissions of previous (root-owned) install (OS#4107)
if dpkg --compare-versions "$2" le "1.12.0"; then
if [ -e /etc/osmocom/osmo-sgsn.cfg ]; then
chown -v osmocom:osmocom /etc/osmocom/osmo-sgsn.cfg
chmod -v 0660 /etc/osmocom/osmo-sgsn.cfg
fi
if [ -d /etc/osmocom ]; then
chown -v root:osmocom /etc/osmocom
chmod -v 2775 /etc/osmocom
fi
mkdir -p /var/lib/osmocom
chown -R -v osmocom:osmocom /var/lib/osmocom
fi
;;
esac
# dh_installdeb(1) will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#

1
debian/rules vendored
View File

@@ -58,7 +58,6 @@ override_dh_auto_configure:
override_dh_strip:
dh_strip -posmo-sgsn --dbg-package=osmo-sgsn-dbg
dh_strip -posmo-gtphub --dbg-package=osmo-gtphub-dbg
dh_strip -posmo-gbproxy --dbg-package=osmo-gbproxy-dbg
# Print test results in case of a failure
override_dh_auto_test:

View File

@@ -1,7 +1,7 @@
OSMOCONF_FILES = \
osmo-gtphub/osmo-gtphub.cfg \
osmo-sgsn/osmo-sgsn.cfg \
osmo-gbproxy/osmo-gbproxy.cfg
$(NULL)
osmoconfdir = $(sysconfdir)/osmocom
osmoconf_DATA = $(OSMOCONF_FILES)

View File

@@ -1,44 +0,0 @@
!
! OsmoGbProxy (UNKNOWN) configuration saved from vty
!!
!
log stderr
logging filter all 1
logging color 1
logging timestamp 0
logging level all debug
logging level gprs debug
logging level ns info
logging level bssgp debug
logging level lglobal notice
logging level llapd notice
logging level linp notice
logging level lmux notice
logging level lmi notice
logging level lmib notice
logging level lsms notice
!
line vty
no login
!
ns
nse 666 nsvci 666
nse 666 remote-role sgsn
! nse 666 encapsulation framerelay-gre
! nse 666 remote-ip 172.16.1.70
! nse 666 fr-dlci 666
timer tns-block 3
timer tns-block-retries 3
timer tns-reset 3
timer tns-reset-retries 3
timer tns-test 30
timer tns-alive 3
timer tns-alive-retries 10
encapsulation udp local-port 23000
! encapsulation framerelay-gre enabled 1
gbproxy
sgsn nsei 666
core-mobile-country-code 666
core-mobile-network-code 6
core-access-point-name none match-imsi ^666066|^66607
tlli-list max-length 200

View File

@@ -1,26 +0,0 @@
!
! Osmocom Gb Proxy (0.9.0.404-6463) configuration saved from vty
!!
!
line vty
no login
!
gbproxy
sgsn nsei 101
ns
nse 101 nsvci 101
nse 101 remote-role sgsn
nse 101 encapsulation udp
nse 101 remote-ip 192.168.100.239
nse 101 remote-port 7777
timer tns-block 3
timer tns-block-retries 3
timer tns-reset 3
timer tns-reset-retries 3
timer tns-test 30
timer tns-alive 3
timer tns-alive-retries 10
encapsulation framerelay-gre enabled 0
encapsulation framerelay-gre local-ip 0.0.0.0
encapsulation udp local-ip 127.0.0.100
encapsulation udp local-port 23000

View File

@@ -5,6 +5,14 @@
! For the test, try to use most config commands.
!
log stderr
logging color 1
logging print category-hex 0
logging print category 1
logging timestamp 0
logging print file basename last
logging print level 1
line vty
no login

View File

@@ -2,6 +2,14 @@
! Osmocom gtphub configuration
!
log stderr
logging color 1
logging print category-hex 0
logging print category 1
logging timestamp 0
logging print file basename last
logging print level 1
line vty
no login
@@ -9,7 +17,7 @@ gtphub
! Local addresses to listen on and send from, each on standard ports
! 2123 and 2152. Setting these addresses is mandatory.
bind-to-sgsns 127.0.0.10
bind-to-ggsns 127.0.0.2
bind-to-ggsns 127.0.0.20
! Local nonstandard ports or separate IPs:
!bind-to-sgsns ctrl 127.0.0.1 2342 user 127.0.0.1 4223

View File

@@ -2,10 +2,19 @@
! Osmocom SGSN configuration
!
!
log stderr
logging color 1
logging print category-hex 0
logging print category 1
logging timestamp 0
logging print file basename last
logging print level 1
line vty
no login
!
sgsn
gtp state-dir /var/lib/osmocom/osmo-sgsn
gtp local-ip 127.0.0.1
ggsn 0 remote-ip 127.0.0.2
ggsn 0 gtp-version 1
@@ -21,9 +30,9 @@ ns
timer tns-test 30
timer tns-alive 3
timer tns-alive-retries 10
encapsulation udp local-ip 127.0.0.1
encapsulation udp local-port 23000
encapsulation framerelay-gre enabled 0
bind udp local
listen 127.0.0.1 23000
accept-ipaccess
!
bssgp
!

View File

@@ -2,10 +2,19 @@
! Osmocom SGSN configuration
!
!
log stderr
logging color 1
logging print category-hex 0
logging print category 1
logging timestamp 0
logging print file basename last
logging print level 1
line vty
no login
!
sgsn
gtp state-dir /var/lib/osmocom/osmo-sgsn
gtp local-ip 127.0.0.1
ggsn 0 remote-ip 127.0.0.2
ggsn 0 gtp-version 1
@@ -23,9 +32,9 @@ ns
timer tns-test 30
timer tns-alive 3
timer tns-alive-retries 10
encapsulation udp local-ip 127.0.0.1
encapsulation udp local-port 23000
encapsulation framerelay-gre enabled 0
bind udp local
listen 127.0.0.1 23000
accept-ipaccess
!
bssgp
!

View File

@@ -2,6 +2,14 @@
! Osmocom SGSN configuration
!
!
log stderr
logging color 1
logging print category-hex 0
logging print category 1
logging timestamp 0
logging print file basename last
logging print level 1
line vty
no login
!
@@ -9,10 +17,13 @@ cs7 instance 0
point-code 0.23.4
asp asp-clnt-OsmoSGSN-A 2905 0 m3ua
remote-ip 172.18.8.200 ! where to reach the STP
role asp
sctp-role client
as as-clnt-OsmoSGSN-A m3ua
asp asp-clnt-OsmoSGSN-A
routing-key 3 0.23.4
sgsn
gtp state-dir /var/lib/osmocom/osmo-sgsn
gtp local-ip 127.0.0.1
ggsn 0 remote-ip 127.0.0.2
ggsn 0 gtp-version 1
@@ -31,9 +42,9 @@ ns
timer tns-test 30
timer tns-alive 3
timer tns-alive-retries 10
encapsulation udp local-ip 127.0.0.1
encapsulation udp local-port 23000
encapsulation framerelay-gre enabled 0
bind udp local
listen 127.0.0.1 23000
accept-ipaccess
!
bssgp
!

View File

@@ -3,7 +3,8 @@ EXTRA_DIST = osmosgsn-usermanual.adoc \
osmosgsn-vty-reference.xml \
regen_doc.sh \
chapters \
vty
vty \
$(NULL)
if BUILD_MANUALS
ASCIIDOC = osmosgsn-usermanual.adoc
@@ -11,6 +12,12 @@ if BUILD_MANUALS
include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.asciidoc.inc
VTY_REFERENCE = osmosgsn-vty-reference.xml
BUILT_REFERENCE_XML = $(builddir)/vty/sgsn_vty_reference.xml
$(builddir)/vty/sgsn_vty_reference.xml: $(top_builddir)/src/sgsn/osmo-sgsn
mkdir -p $(builddir)/vty
$(top_builddir)/src/sgsn/osmo-sgsn --vty-ref-xml > $@
include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.vty-reference.inc
OSMO_REPOSITORY = osmo-sgsn

View File

@@ -11,7 +11,8 @@ explicit configuration of each PCU connecting to the SGSN. The
administrator only has to ensure that the NS and BSSGP layer identities
(NSEI, NSVCI, BVCI) are unique for each PCU connecting to the SGSN.
=== Configuring the Gp interface
[[gp-if-ggsn]]
=== Configuring the Gp interface (towards GGSN)
The Gp interface is the GTP-C and GTP-U based interface between the SGSN
and the GGSNs. It is implemented via UDP on well-known source and
@@ -67,6 +68,58 @@ OsmoSGSN(config-sgsn)# grx-dns-add 1.2.3.4 <3>
<2> Enable the dynamic GGSN resolving mode
<3> Specify the IP address of a DNS server for APN resolution
[[gp-if-mme]]
=== Configuring the Gp interface (towards MME)
The Gp interface also contains the GTP-C v1 based interface between the SGSN
and the MMEs. This interface between SGSN and MMEs is used to transfer _RAN
Information Relay_ GTP-C messages between them, which are used as containers to
allow PCUs under the SGSN and eNodeBs under MMEs to exchange cell information
(RIM).
In the SGSN, this interface re-uses the same socket local configuration as per
the GGSN connections (see _gtp local-ip_ VTY command in <<gp-if-ggsn>>).
Similarly as with GGSNs, (again see <<gp-if-ggsn>>), selection of destination
peers for the _RAN Information Relay_ message can be configured statically or
dynamically over GRX.
==== Static MME/TAI configuration
In this mode, there is a static list of MMEs and TAIs configured in
OsmoSGSN via the VTY / config file. One MME in the list can be configured as the
_default route_, where all unspecified TAIs are routed too.
This is a non-standard method outside of the 3GPP specifications for the
SGSN, and is typically only used in private/small GPRS networks without
any access to a GRX.
.Example: Static MME/TAI configuration (single catch-all GGSN)
----
sgsn
...
gtp local-ip 192.168.0.10 <1>
mme test-mme0 <2>
gtp remote-ip 192.168.0.20 <3>
gtp ran-info-relay 262 42 3 <4>
gtp ran-info-relay 262 42 4
mme test-mme1 <5>
gtp remote-ip 192.168.0.30
gtp ran-info-relay default <6>
----
<1> Configure the local IP address at the SGSN used for Gp/GTP
<2> Configure an MME named "test-mme0"
<3> Specify the remote IP address of the MME (for MME "test-mme0")
<4> Route specified TAIs towards this MME
<5> Configure an MME named "test-mme1"
<6> Route all TAIs with an unspecified MME towards MM "test-mme1"
==== Dynamic MME/TAI configuration
Dynamic MME/TAI peer look up over GRX is not yet supported by OsmoSGSN.
[[auth-pol]]
=== Authorization Policy
@@ -345,14 +398,35 @@ Encryption can be enabled if the auth-policy is set to remote and the
HLR subscriber entries contain the keys of the SIM card. See
<<sgsn-ex-gsup>> on how to connect to an external HLR.
.Example: Turn on encryption (GEA3)
.Example: Turn on encryption (GEA3 and GEA4)
----
sgsn
encryption GEA3
encryption gea 3 4
----
.Example: Turn off encryption (GEA0)
----
sgsn
encryption GEA0
encryption gea 0
----
=== Configure SCCP/M3UA to accept _IuPS_ links
OsmoSGSN acts as client to contact an STP instance and establish an SCCP/M3UA
link.
An example configuration of OsmoSGSN's SCCP link:
----
cs7 instance 0
point-code 0.23.4
asp asp-clnt-OsmoSGSN 2905 0 m3ua
remote-ip 127.0.0.1
role asp
sctp-role client
as as-clnt-OsmoSGSN m3ua
asp asp-clnt-OsmoSGSN
routing-key 0 0.23.4
----
This configuration is explained in detail in <<cs7_config>>.

View File

@@ -15,6 +15,14 @@
Conversion to asciidoc, removal of sysmoBTS specific parts.
</revremark>
</revision>
<revision>
<revnumber>3</revnumber>
<date>April 2024</date>
<authorinitials>AC</authorinitials>
<revremark>
Replace NS chapter with new NS2 chapter to match the code.
</revremark>
</revision>
</revhistory>
<authorgroup>
@@ -29,10 +37,21 @@
<jobtitle>Managing Director</jobtitle>
</affiliation>
</author>
<author>
<firstname>Alexander</firstname>
<surname>Couzens</surname>
<email>acouzens@sysmocom.de</email>
<authorinitials>AC</authorinitials>
<affiliation>
<shortaffil>sysmocom</shortaffil>
<orgname>sysmocom - s.f.m.c. GmbH</orgname>
<jobtitle>Developer</jobtitle>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2013-2016</year>
<year>2013-2024</year>
<holder>sysmocom - s.f.m.c. GmbH</holder>
</copyright>
@@ -47,8 +66,8 @@
</para>
<para>
The Asciidoc source code of this manual can be found at
<ulink url="http://git.osmocom.org/osmo-gsm-manuals/">
http://git.osmocom.org/osmo-gsm-manuals/
<ulink url="https://git.osmocom.org/osmo-gsm-manuals/">
https://git.osmocom.org/osmo-gsm-manuals/
</ulink>
</para>
</legalnotice>

View File

@@ -19,7 +19,9 @@ include::./common/chapters/logging.adoc[]
include::{srcdir}/chapters/configuration.adoc[]
include::./common/chapters/gb.adoc[]
include::./common/chapters/cs7-config.adoc[]
include::./common/chapters/gb-ns2.adoc[]
include::./common/chapters/control_if.adoc[]

View File

@@ -12,6 +12,6 @@ COMMIT=${COMMIT:-$(git log -1 --format=format:%H)}
cd "$DOCKER_PLAYGROUND/scripts" || exit 1
OSMO_SGSN_BRANCH=$COMMIT ./regen_doc.sh osmo-sgsn 4245 \
OSMO_BSC_BRANCH=$COMMIT ./regen_doc.sh osmo-sgsn 4245 \
"$MANUAL_DIR/chapters/counters_generated.adoc" \
"$MANUAL_DIR/vty/sgsn_vty_reference.xml"

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,4 @@
SUBDIRS = \
gtphub \
sgsn \
$(NULL)

View File

@@ -0,0 +1,3 @@
noinst_HEADERS = \
gtphub.h \
$(NULL)

View File

@@ -27,22 +27,20 @@
#include <osmocom/core/select.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/gsm/apn.h>
/* support */
/* TODO move to osmocom/core/socket.c ? */
#include <netdb.h> /* for IPPROTO_* etc */
struct osmo_sockaddr {
struct sgsn_sockaddr {
struct sockaddr_storage a;
socklen_t l;
};
/* TODO move to osmocom/core/socket.c ? */
/*! \brief Initialize a sockaddr
* \param[out] addr Valid osmo_sockaddr pointer to write result to
* \param[out] addr Valid sgsn_sockaddr pointer to write result to
* \param[in] family Address Family like AF_INET, AF_INET6, AF_UNSPEC
* \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM
* \param[in] proto Protocol like IPPROTO_TCP, IPPROTO_UDP
@@ -53,16 +51,16 @@ struct osmo_sockaddr {
* Copy the first result from a getaddrinfo() call with the given parameters to
* *addr and *addr_len. On error, do not change *addr and return nonzero.
*/
int osmo_sockaddr_init(struct osmo_sockaddr *addr,
int sgsn_sockaddr_init(struct sgsn_sockaddr *addr,
uint16_t family, uint16_t type, uint8_t proto,
const char *host, uint16_t port);
/* Conveniently pass AF_UNSPEC, SOCK_DGRAM and IPPROTO_UDP to
* osmo_sockaddr_init(). */
static inline int osmo_sockaddr_init_udp(struct osmo_sockaddr *addr,
* sgsn_sockaddr_init(). */
static inline int sgsn_sockaddr_init_udp(struct sgsn_sockaddr *addr,
const char *host, uint16_t port)
{
return osmo_sockaddr_init(addr, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP,
return sgsn_sockaddr_init(addr, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP,
host, port);
}
@@ -71,25 +69,25 @@ static inline int osmo_sockaddr_init_udp(struct osmo_sockaddr *addr,
* \param[in] addr_str_len Size of buffer addr_str points at.
* \param[out] port_str Valid pointer to a buffer of length port_str_len.
* \param[in] port_str_len Size of buffer port_str points at.
* \param[in] addr Binary representation as returned by osmo_sockaddr_init().
* \param[in] addr Binary representation as returned by sgsn_sockaddr_init().
* \param[in] flags flags as passed to getnameinfo().
* \returns 0 on success, an error code on error.
*
* Return the IPv4 or IPv6 address string and the port (a.k.a. service) string
* representations of the given struct osmo_sockaddr in two caller provided
* representations of the given struct sgsn_sockaddr in two caller provided
* char buffers. Flags of (NI_NUMERICHOST | NI_NUMERICSERV) return numeric
* address and port. Either one of addr_str or port_str may be NULL, in which
* case nothing is returned there.
*
* See also osmo_sockaddr_to_str() (less flexible, but much more convenient). */
int osmo_sockaddr_to_strs(char *addr_str, size_t addr_str_len,
* See also sgsn_sockaddr_to_str() (less flexible, but much more convenient). */
int sgsn_sockaddr_to_strs(char *addr_str, size_t addr_str_len,
char *port_str, size_t port_str_len,
const struct osmo_sockaddr *addr,
const struct sgsn_sockaddr *addr,
int flags);
/*! \brief concatenate the parts returned by osmo_sockaddr_to_strs().
* \param[in] addr Binary representation as returned by osmo_sockaddr_init().
/*! \brief concatenate the parts returned by sgsn_sockaddr_to_strs().
* \param[in] addr Binary representation as returned by sgsn_sockaddr_init().
* \param[in] buf A buffer to use for string operations.
* \param[in] buf_len Length of the buffer.
* \returns Address string (in buffer).
@@ -98,33 +96,33 @@ int osmo_sockaddr_to_strs(char *addr_str, size_t addr_str_len,
* the form "<ip-addr> port <port>". The returned string is valid until the
* next invocation of this function.
*/
const char *osmo_sockaddr_to_strb(const struct osmo_sockaddr *addr,
const char *sgsn_sockaddr_to_strb(const struct sgsn_sockaddr *addr,
char *buf, size_t buf_len);
/*! \brief conveniently return osmo_sockaddr_to_strb() in a static buffer.
* \param[in] addr Binary representation as returned by osmo_sockaddr_init().
/*! \brief conveniently return sgsn_sockaddr_to_strb() in a static buffer.
* \param[in] addr Binary representation as returned by sgsn_sockaddr_init().
* \returns Address string in static buffer.
*
* See osmo_sockaddr_to_strb().
* See sgsn_sockaddr_to_strb().
*
* Note: only one osmo_sockaddr_to_str() call will work per print/log
* statement. For two or more, use osmo_sockaddr_to_strb() with a separate
* Note: only one sgsn_sockaddr_to_str() call will work per print/log
* statement. For two or more, use sgsn_sockaddr_to_strb() with a separate
* buffer each.
*/
const char *osmo_sockaddr_to_str(const struct osmo_sockaddr *addr);
const char *sgsn_sockaddr_to_str(const struct sgsn_sockaddr *addr);
/*! \brief compare two osmo_sockaddr.
/*! \brief compare two sgsn_sockaddr.
* \param[in] a The first address to compare.
* \param[in] b The other address to compare.
* \returns 0 if equal, otherwise -1 or 1.
*/
int osmo_sockaddr_cmp(const struct osmo_sockaddr *a,
const struct osmo_sockaddr *b);
int sgsn_sockaddr_cmp(const struct sgsn_sockaddr *a,
const struct sgsn_sockaddr *b);
/*! \brief Overwrite *dst with *src.
* Like memcpy(), but copy only the valid bytes. */
void osmo_sockaddr_copy(struct osmo_sockaddr *dst,
const struct osmo_sockaddr *src);
void sgsn_sockaddr_copy(struct sgsn_sockaddr *dst,
const struct sgsn_sockaddr *src);
/* general */
@@ -179,7 +177,7 @@ int gsn_addr_same(const struct gsn_addr *a, const struct gsn_addr *b);
/* Decode sa to gsna. Return 0 on success. If port is non-NULL, the port number
* from sa is also returned. */
int gsn_addr_from_sockaddr(struct gsn_addr *gsna, uint16_t *port,
const struct osmo_sockaddr *sa);
const struct sgsn_sockaddr *sa);
/* expiry */
@@ -389,7 +387,7 @@ struct gtphub_peer_port {
struct gtphub_peer_addr *peer_addr;
uint16_t port;
unsigned int ref_count; /* references from other peers' seq_maps */
struct osmo_sockaddr sa; /* a "cache" for (peer_addr->addr, port) */
struct sgsn_sockaddr sa; /* a "cache" for (peer_addr->addr, port) */
int last_restart_count; /* 0..255 = valid, all else means unknown */
struct rate_ctr_group *counters_io;
@@ -428,7 +426,7 @@ struct gtphub_resolved_ggsn {
/* The APN OI, the Operator Identifier, is the combined address,
* including parts of the IMSI and APN NI, and ending with ".gprs". */
char apn_oi_str[GSM_APN_LENGTH];
char apn_oi_str[APN_MAXLEN+1];
/* Which address and port we resolved that to. */
struct gtphub_peer_port *peer;
@@ -496,13 +494,13 @@ int gtphub_tunnel_complete(struct gtphub_tunnel *tun);
int gtphub_handle_buf(struct gtphub *hub,
unsigned int side_idx,
unsigned int port_idx,
const struct osmo_sockaddr *from_addr,
const struct sgsn_sockaddr *from_addr,
uint8_t *buf,
size_t received,
time_t now,
uint8_t **reply_buf,
struct osmo_fd **to_ofd,
struct osmo_sockaddr *to_addr);
struct sgsn_sockaddr *to_addr);
struct gtphub_peer_port *gtphub_port_have(struct gtphub *hub,
struct gtphub_bind *bind,
@@ -510,7 +508,7 @@ struct gtphub_peer_port *gtphub_port_have(struct gtphub *hub,
uint16_t port);
struct gtphub_peer_port *gtphub_port_find_sa(const struct gtphub_bind *bind,
const struct osmo_sockaddr *addr);
const struct sgsn_sockaddr *addr);
void gtphub_resolved_ggsn(struct gtphub *hub, const char *apn_oi_str,
struct gsn_addr *resolved_addr,
@@ -519,5 +517,5 @@ void gtphub_resolved_ggsn(struct gtphub *hub, const char *apn_oi_str,
const char *gtphub_port_str(struct gtphub_peer_port *port);
int gtphub_write(const struct osmo_fd *to,
const struct osmo_sockaddr *to_addr,
const struct sgsn_sockaddr *to_addr,
const uint8_t *buf, size_t buf_len);

View File

@@ -1,19 +1,21 @@
noinst_HEADERS = \
apn.h \
auth.h \
common.h \
crc24.h \
debug.h \
gb_proxy.h \
gprs_gb.h \
gprs_gb_parse.h \
gprs_bssgp.h \
gprs_gmm.h \
gprs_gmm_fsm.h \
gprs_gmm_attach.h \
gprs_gmm_util.h \
gprs_mm_state_gb_fsm.h \
gprs_mm_state_iu_fsm.h \
gprs_ns.h \
gprs_llc.h \
gprs_llc_xid.h \
gprs_ranap.h \
gprs_sgsn.h \
gprs_routing_area.h \
gprs_sm.h \
gprs_sndcp_comp.h \
gprs_sndcp_dcomp.h \
@@ -22,8 +24,17 @@ noinst_HEADERS = \
gprs_sndcp_xid.h \
gprs_subscriber.h \
gprs_utils.h \
gtphub.h \
gtp.h \
gtp_ggsn.h \
gtp_mme.h \
iu_client.h \
iu_rnc.h \
iu_rnc_fsm.h \
mmctx.h \
pdpctx.h \
sccp.h \
sgsn.h \
sgsn_rim.h \
signal.h \
slhc.h \
v42bis.h \

View File

@@ -0,0 +1,20 @@
#pragma once
#include <osmocom/core/linuxlist.h>
struct sgsn_ggsn_ctx;
#define GSM_APN_LENGTH 102
struct apn_ctx {
struct llist_head list;
struct sgsn_ggsn_ctx *ggsn;
char *name;
char *imsi_prefix;
char *description;
};
struct apn_ctx *sgsn_apn_ctx_find_alloc(const char *name, const char *imsi_prefix);
void sgsn_apn_ctx_free(struct apn_ctx *actx);
struct apn_ctx *sgsn_apn_ctx_by_name(const char *name, const char *imsi_prefix);
struct apn_ctx *sgsn_apn_ctx_match(const char *name, const char *imsi_prefix);

View File

@@ -0,0 +1,39 @@
/* MS authorization and subscriber data handling */
#pragma once
#include <osmocom/core/linuxlist.h>
struct sgsn_config;
struct sgsn_instance;
struct sgsn_mm_ctx;
struct gsm_auth_tuple;
/* Authorization/ACL handling */
enum sgsn_auth_state {
SGSN_AUTH_UNKNOWN,
SGSN_AUTH_AUTHENTICATE,
SGSN_AUTH_UMTS_RESYNC,
SGSN_AUTH_ACCEPTED,
SGSN_AUTH_REJECTED
};
extern const struct value_string *sgsn_auth_state_names;
void sgsn_auth_init(struct sgsn_instance *sgsn);
/* Request authorization */
enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mm);
int sgsn_auth_request(struct sgsn_mm_ctx *mm);
void sgsn_auth_update(struct sgsn_mm_ctx *mm);
struct gsm_auth_tuple *sgsn_auth_get_tuple(struct sgsn_mm_ctx *mmctx,
unsigned key_seq);
/*
* Authorization/ACL handling
*/
struct imsi_acl_entry {
struct llist_head list;
char imsi[OSMO_IMSI_BUF_SIZE];
};
struct imsi_acl_entry *sgsn_acl_lookup(const char *imsi, const struct sgsn_config *cfg);
int sgsn_acl_add(const char *imsi, struct sgsn_config *cfg);
int sgsn_acl_del(const char *imsi, struct sgsn_config *cfg);

View File

@@ -5,6 +5,6 @@
#define INIT_CRC24 0xffffff
uint32_t crc24_calc(uint32_t fcs, uint8_t *cp, unsigned int len);
uint32_t crc24_calc(uint32_t fcs, const uint8_t *cp, unsigned int len);
#endif

View File

@@ -8,38 +8,25 @@
/* Debug Areas of the code */
enum {
DRLL,
DCC,
DMM,
DRR,
DRSL,
DNM,
DMNCC,
DPAG,
DMEAS,
DSCCP,
DMSC,
DHO,
DDB,
DREF,
DGPRS,
DNS,
DBSSGP,
DLLC,
DSNDCP,
DSLHC,
DNAT,
DCTRL,
DFILTER,
DGTPHUB,
DRANAP,
DSUA,
DV42BIS,
DPCU,
DVLR,
DIUCS,
DSIGTRAN,
DGTP,
DOBJ,
DRIM,
DRA, /* Routing Area handling */
Debug_LastEntry,
};

View File

@@ -1,334 +0,0 @@
#ifndef _GB_PROXY_H
#define _GB_PROXY_H
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/gsm23003.h>
#include <osmocom/gprs/gprs_ns.h>
#include <osmocom/vty/command.h>
#include <sys/types.h>
#include <regex.h>
#include <stdbool.h>
#define GBPROXY_INIT_VU_GEN_TX 256
struct rate_ctr_group;
struct gprs_gb_parse_context;
struct tlv_parsed;
enum gbproxy_global_ctr {
GBPROX_GLOB_CTR_INV_BVCI,
GBPROX_GLOB_CTR_INV_LAI,
GBPROX_GLOB_CTR_INV_RAI,
GBPROX_GLOB_CTR_INV_NSEI,
GBPROX_GLOB_CTR_PROTO_ERR_BSS,
GBPROX_GLOB_CTR_PROTO_ERR_SGSN,
GBPROX_GLOB_CTR_NOT_SUPPORTED_BSS,
GBPROX_GLOB_CTR_NOT_SUPPORTED_SGSN,
GBPROX_GLOB_CTR_RESTART_RESET_SGSN,
GBPROX_GLOB_CTR_TX_ERR_SGSN,
GBPROX_GLOB_CTR_OTHER_ERR,
GBPROX_GLOB_CTR_PATCH_PEER_ERR,
};
enum gbproxy_peer_ctr {
GBPROX_PEER_CTR_BLOCKED,
GBPROX_PEER_CTR_UNBLOCKED,
GBPROX_PEER_CTR_DROPPED,
GBPROX_PEER_CTR_INV_NSEI,
GBPROX_PEER_CTR_TX_ERR,
GBPROX_PEER_CTR_RAID_PATCHED_BSS,
GBPROX_PEER_CTR_RAID_PATCHED_SGSN,
GBPROX_PEER_CTR_APN_PATCHED,
GBPROX_PEER_CTR_TLLI_PATCHED_BSS,
GBPROX_PEER_CTR_TLLI_PATCHED_SGSN,
GBPROX_PEER_CTR_PTMSI_PATCHED_BSS,
GBPROX_PEER_CTR_PTMSI_PATCHED_SGSN,
GBPROX_PEER_CTR_PATCH_CRYPT_ERR,
GBPROX_PEER_CTR_PATCH_ERR,
GBPROX_PEER_CTR_ATTACH_REQS,
GBPROX_PEER_CTR_ATTACH_REJS,
GBPROX_PEER_CTR_ATTACH_ACKS,
GBPROX_PEER_CTR_ATTACH_COMPLS,
GBPROX_PEER_CTR_RA_UPD_REQS,
GBPROX_PEER_CTR_RA_UPD_REJS,
GBPROX_PEER_CTR_RA_UPD_ACKS,
GBPROX_PEER_CTR_RA_UPD_COMPLS,
GBPROX_PEER_CTR_GMM_STATUS_BSS,
GBPROX_PEER_CTR_GMM_STATUS_SGSN,
GBPROX_PEER_CTR_DETACH_REQS,
GBPROX_PEER_CTR_DETACH_ACKS,
GBPROX_PEER_CTR_PDP_ACT_REQS,
GBPROX_PEER_CTR_PDP_ACT_REJS,
GBPROX_PEER_CTR_PDP_ACT_ACKS,
GBPROX_PEER_CTR_PDP_DEACT_REQS,
GBPROX_PEER_CTR_PDP_DEACT_ACKS,
GBPROX_PEER_CTR_TLLI_UNKNOWN,
GBPROX_PEER_CTR_TLLI_CACHE_SIZE,
GBPROX_PEER_CTR_LAST,
};
enum gbproxy_keep_mode {
GBPROX_KEEP_NEVER, /* don't ever keep TLLI/IMSI state of de-registered subscribers */
GBPROX_KEEP_REATTACH, /* keep if re-attach has been requested by SGSN */
GBPROX_KEEP_IDENTIFIED, /* keep if we had resolved an IMSI */
GBPROX_KEEP_ALWAYS, /* always keep */
};
enum gbproxy_match_id {
GBPROX_MATCH_PATCHING, /* match rule on whether or not we should patch */
GBPROX_MATCH_ROUTING, /* match rule on whether or not we should route (2-SGSN) */
GBPROX_MATCH_LAST
};
struct gbproxy_match {
bool enable; /* is this match enabled? */
char *re_str; /* regular expression (for IMSI) in string format */
regex_t re_comp; /* compiled regular expression (for IMSI) */
};
/* global gb-proxy configuration */
struct gbproxy_config {
/* parsed from config file */
uint16_t nsip_sgsn_nsei;
/* NS instance of libosmogb */
struct gprs_ns_inst *nsi;
/* Linked list of all Gb peers (except SGSN) */
struct llist_head bts_peers;
/* Counter */
struct rate_ctr_group *ctrg;
/* MCC/MNC to be patched into RA-ID on the way from BSS to SGSN? */
struct osmo_plmn_id core_plmn;
/* APN to be patched into PDP CTX ACT REQ on the way from BSS to SGSN */
uint8_t* core_apn;
size_t core_apn_size;
/* Frequency (sec) at which timer to clean stale links is fired (0 disabled) */
unsigned int clean_stale_timer_freq;
/* If !0, Max age to consider a struct gbproxy_link_info as stale */
int tlli_max_age;
/* If !0, Max len of gbproxy_peer->list (list of struct gbproxy_link_info) */
int tlli_max_len;
/* If !0, Max len of gbproxy_link_info->stored_msgs (list of msgb) */
uint32_t stored_msgs_max_len;
/* Should the P-TMSI be patched on the fly (required for 2-SGSN config) */
bool patch_ptmsi;
/* Should the IMSI be acquired by the proxy (required for 2-SGSN config) */
bool acquire_imsi;
/* Should we route subscribers to two different SGSNs? */
bool route_to_sgsn2;
/* NSEI of the second SGSN */
uint16_t nsip_sgsn2_nsei;
/* should we keep a cache of per-subscriber state even after de-registration? */
enum gbproxy_keep_mode keep_link_infos;
/* IMSI checking/matching for 2-SGSN routing and patching */
struct gbproxy_match matches[GBPROX_MATCH_LAST];
};
struct gbproxy_patch_state {
struct osmo_plmn_id local_plmn;
/* List of TLLIs for which patching is enabled */
struct llist_head logical_links;
int logical_link_count;
};
/* one peer at NS level that we interact with (BSS/PCU) */
struct gbproxy_peer {
/* linked to gbproxy_config.bts_peers */
struct llist_head list;
/* point back to the config */
struct gbproxy_config *cfg;
/* NSEI of the peer entity */
uint16_t nsei;
/* BVCI used for Point-to-Point to this peer */
uint16_t bvci;
bool blocked;
/* Routeing Area that this peer is part of (raw 04.08 encoding) */
uint8_t ra[6];
/* Counter */
struct rate_ctr_group *ctrg;
/* State related to on-the-fly patching of certain messages */
struct gbproxy_patch_state patch_state;
/* Fired periodically to clean up stale links from list */
struct osmo_timer_list clean_stale_timer;
};
struct gbproxy_tlli_state {
/* currently active TLLI */
uint32_t current;
/* newly-assigned TLLI (e.g. during P-TMSI allocation procedure) */
uint32_t assigned;
/* has the BSS side validated (confirmed) the new TLLI? */
bool bss_validated;
/* has the SGSN side validated (confirmed) the new TLLI? */
bool net_validated;
/* NOTE: once both are validated, we set current = assigned and assigned = 0 */
/* The P-TMSI for this subscriber */
uint32_t ptmsi;
};
/* One TLLI (= UE, = Subscriber) served via this proxy */
struct gbproxy_link_info {
/* link to gbproxy_peer.patch_state.logical_links */
struct llist_head list;
/* TLLI on the BSS/PCU side */
struct gbproxy_tlli_state tlli;
/* TLLI on the SGSN side (can be different in case of P-TMSI patching) */
struct gbproxy_tlli_state sgsn_tlli;
/* NSEI of the SGSN serving this link */
uint32_t sgsn_nsei;
/* timestamp when we last had any contact with this UE */
time_t timestamp;
/* IMSI of the subscriber (if/once known) */
uint8_t *imsi;
size_t imsi_len;
/* is the IMSI acquisition still pending? */
bool imsi_acq_pending;
/* queue of stored UL messages (until IMSI acquisition completes and we can
* determine which of the SGSNs we should route this to */
struct llist_head stored_msgs;
uint32_t stored_msgs_len;
/* generated N(U) we use (required due to IMSI acquisition */
unsigned vu_gen_tx_bss;
/* is this subscriber deregistered (TLLI invalidated)? */
bool is_deregistered;
/* does this link match either the (2-SGSN) routing or the patching rule? */
bool is_matching[GBPROX_MATCH_LAST];
};
/* gb_proxy_vty .c */
int gbproxy_vty_init(void);
int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg);
/* gb_proxy_ctrl.c */
int gb_ctrl_cmds_install(void);
/* gb_proxy.c */
int gbproxy_init_config(struct gbproxy_config *cfg);
/* Main input function for Gb proxy */
int gbprox_rcvmsg(struct gbproxy_config *cfg, struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t nsvci);
int gbprox_signal(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data);
/* Reset all persistent NS-VC's */
int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi);
void gbprox_reset(struct gbproxy_config *cfg);
/* TLLI info handling */
void gbproxy_delete_link_infos(struct gbproxy_peer *peer);
struct gbproxy_link_info *gbproxy_update_link_state_ul(
struct gbproxy_peer *peer, time_t now,
struct gprs_gb_parse_context *parse_ctx);
struct gbproxy_link_info *gbproxy_update_link_state_dl(
struct gbproxy_peer *peer, time_t now,
struct gprs_gb_parse_context *parse_ctx);
int gbproxy_update_link_state_after(
struct gbproxy_peer *peer, struct gbproxy_link_info *link_info,
time_t now, struct gprs_gb_parse_context *parse_ctx);
int gbproxy_remove_stale_link_infos(struct gbproxy_peer *peer, time_t now);
void gbproxy_delete_link_info(struct gbproxy_peer *peer,
struct gbproxy_link_info *link_info);
void gbproxy_link_info_discard_messages(struct gbproxy_link_info *link_info);
void gbproxy_attach_link_info(struct gbproxy_peer *peer, time_t now,
struct gbproxy_link_info *link_info);
void gbproxy_update_link_info(struct gbproxy_link_info *link_info,
const uint8_t *imsi, size_t imsi_len);
void gbproxy_detach_link_info(struct gbproxy_peer *peer,
struct gbproxy_link_info *link_info);
struct gbproxy_link_info *gbproxy_link_info_alloc( struct gbproxy_peer *peer);
struct gbproxy_link_info *gbproxy_link_info_by_tlli(
struct gbproxy_peer *peer, uint32_t tlli);
struct gbproxy_link_info *gbproxy_link_info_by_imsi(
struct gbproxy_peer *peer, const uint8_t *imsi, size_t imsi_len);
struct gbproxy_link_info *gbproxy_link_info_by_any_sgsn_tlli(
struct gbproxy_peer *peer, uint32_t tlli);
struct gbproxy_link_info *gbproxy_link_info_by_sgsn_tlli(
struct gbproxy_peer *peer,
uint32_t tlli, uint32_t sgsn_nsei);
struct gbproxy_link_info *gbproxy_link_info_by_ptmsi(
struct gbproxy_peer *peer,
uint32_t ptmsi);
int gbproxy_imsi_matches(
struct gbproxy_config *cfg,
enum gbproxy_match_id match_id,
struct gbproxy_link_info *link_info);
uint32_t gbproxy_map_tlli(
uint32_t other_tlli, struct gbproxy_link_info *link_info, int to_bss);
/* needed by gb_proxy_tlli.h */
uint32_t gbproxy_make_bss_ptmsi(struct gbproxy_peer *peer, uint32_t sgsn_ptmsi);
uint32_t gbproxy_make_sgsn_tlli(
struct gbproxy_peer *peer, struct gbproxy_link_info *link_info,
uint32_t bss_tlli);
void gbproxy_reset_link(struct gbproxy_link_info *link_info);
int gbproxy_check_imsi(
struct gbproxy_match *match, const uint8_t *imsi, size_t imsi_len);
/* Message patching */
void gbproxy_patch_bssgp(
struct msgb *msg, uint8_t *bssgp, size_t bssgp_len,
struct gbproxy_peer *peer, struct gbproxy_link_info *link_info,
int *len_change, struct gprs_gb_parse_context *parse_ctx);
int gbproxy_patch_llc(
struct msgb *msg, uint8_t *llc, size_t llc_len,
struct gbproxy_peer *peer, struct gbproxy_link_info *link_info,
int *len_change, struct gprs_gb_parse_context *parse_ctx);
int gbproxy_set_patch_filter(
struct gbproxy_match *match, const char *filter, const char **err_msg);
void gbproxy_clear_patch_filter(struct gbproxy_match *match);
/* Peer handling */
struct gbproxy_peer *gbproxy_peer_by_bvci(
struct gbproxy_config *cfg, uint16_t bvci);
struct gbproxy_peer *gbproxy_peer_by_nsei(
struct gbproxy_config *cfg, uint16_t nsei);
struct gbproxy_peer *gbproxy_peer_by_rai(
struct gbproxy_config *cfg, const uint8_t *ra);
struct gbproxy_peer *gbproxy_peer_by_lai(
struct gbproxy_config *cfg, const uint8_t *la);
struct gbproxy_peer *gbproxy_peer_by_lac(
struct gbproxy_config *cfg, const uint8_t *la);
struct gbproxy_peer *gbproxy_peer_by_bssgp_tlv(
struct gbproxy_config *cfg, struct tlv_parsed *tp);
struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_config *cfg, uint16_t bvci);
void gbproxy_peer_free(struct gbproxy_peer *peer);
int gbproxy_cleanup_peers(struct gbproxy_config *cfg, uint16_t nsei, uint16_t bvci);
#endif

View File

@@ -0,0 +1,15 @@
#pragma once
#include <osmocom/core/msgb.h>
struct osmo_prim_hdr;
struct sgsn_mm_ctx;
/* Called by bssgp layer when a prim is received from lower layers. */
int sgsn_bssgp_rx_prim(struct osmo_prim_hdr *oph);
/* called by the bssgp layer to send NS PDUs */
int sgsn_bssgp_dispatch_ns_unitdata_req_cb(void *ctx, struct msgb *msg);
/* page a MS in a single cell */
int sgsn_bssgp_page_ps_bvci(struct sgsn_mm_ctx *mmctx, uint16_t nsei, uint16_t bvci);

View File

@@ -1,9 +0,0 @@
#pragma once
#include <stdbool.h>
#include <osmocom/core/msgb.h>
#include <osmocom/sgsn/gprs_rllc.h>
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
bool drop_cipherable);

View File

@@ -1,10 +1,16 @@
#ifndef _GPRS_GMM_H
#define _GPRS_GMM_H
#include <osmocom/core/msgb.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <stdbool.h>
#include <stdint.h>
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/crypt/auth.h>
struct sgsn_mm_ctx;
struct gprs_llc_llme;
struct osmo_routing_area_id;
int gsm48_tx_gmm_auth_ciph_req(struct sgsn_mm_ctx *mm,
const struct osmo_auth_vector *vec,
@@ -24,10 +30,19 @@ void gsm0408_gprs_access_denied(struct sgsn_mm_ctx *mmctx, int gmm_cause);
void gsm0408_gprs_access_cancelled(struct sgsn_mm_ctx *mmctx, int gmm_cause);
void gsm0408_gprs_authenticate(struct sgsn_mm_ctx *mmctx);
int gprs_gmm_rx_suspend(struct gprs_ra_id *raid, uint32_t tlli);
int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli,
int gprs_gmm_rx_suspend(struct osmo_routing_area_id *raid, uint32_t tlli);
int gprs_gmm_rx_resume(struct osmo_routing_area_id *raid, uint32_t tlli,
uint8_t suspend_ref);
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
bool drop_cipherable);
#ifdef BUILD_IU
int gsm0408_gprs_rcvmsg_iu(struct msgb *msg, struct gprs_ra_id *ra_id, uint16_t *sai);
#endif /* ifdef BUILD_IU */
/* Has to be called whenever any PDU (signaling, data, ...) has been received */
void gprs_gb_recv_pdu(struct sgsn_mm_ctx *mmctx, const struct msgb *msg);
time_t gprs_max_time_to_idle(void);
int gsm48_tx_gmm_id_req(struct sgsn_mm_ctx *mm, uint8_t id_type);
@@ -35,7 +50,7 @@ int gsm48_tx_gmm_att_rej(struct sgsn_mm_ctx *mm,
uint8_t gmm_cause);
int gsm48_tx_gmm_att_ack(struct sgsn_mm_ctx *mm);
int gprs_gmm_attach_req_ies(struct msgb *a, struct msgb *b);
int gprs_gmm_msg_cmp(struct msgb *a, struct msgb *b);
int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx);
/* TODO: move extract_subscr_* when gsm48_gmm_authorize() got removed */

View File

@@ -2,6 +2,10 @@
#include <osmocom/core/fsm.h>
#include <osmocom/sgsn/mmctx.h>
struct gprs_llc_llme;
/* 3GPP TS 24.008 § 4.1.3.3 GMM mobility management states on the network side */
enum gmm_fsm_states {
ST_GMM_DEREGISTERED, /* 4.1.3.3.1.1 */
@@ -23,6 +27,12 @@ enum gmm_fsm_events {
E_GMM_SUSPEND,
E_GMM_RESUME,
E_GMM_CLEANUP,
E_GMM_RAT_CHANGE,
};
struct gmm_rat_change_data {
enum sgsn_ran_type new_ran_type;
struct gprs_llc_llme *llme;
};
static inline bool gmm_fsm_is_registered(struct osmo_fsm_inst *fi)

View File

@@ -0,0 +1,42 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <osmocom/gsm/gsm23003.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/gsm/tlv.h>
struct msgb;
extern const struct tlv_definition gsm48_gmm_ie_tlvdef;
/* 9.4.14 RAU Request */
struct gprs_gmm_ra_upd_req {
uint8_t skip_ind; /* 10.3.1 */
uint8_t update_type; /* 10.5.5.18 */
bool follow_up_req; /* 10.5.5.18 */
uint8_t cksq; /* 10.5.1.2 */
struct osmo_routing_area_id old_rai; /* 10.5.5.15 */
uint8_t *ms_radio_cap; /* 10.5.5.12a */
uint8_t ms_radio_cap_len;
struct tlv_parsed tlv;
};
struct gprs_gmm_att_req {
uint8_t skip_ind; /* 10.3.1 */
uint8_t attach_type; /* 10.5.5.2 */
bool follow_up_req; /* 10.5.5.2 */
uint8_t cksq; /* 10.5.1.2 */
uint16_t drx_parms; /* 10.5.5.6 */
struct osmo_mobile_identity mi; /* 10.5.1.4 */
struct osmo_routing_area_id old_rai; /* 10.5.5.15 */
uint8_t *ms_network_cap; /* 10.5.5.12 */
uint8_t ms_network_cap_len;
uint8_t *ms_radio_cap; /* 10.5.5.12a */
uint8_t ms_radio_cap_len;
struct tlv_parsed tlv;
};
int gprs_gmm_parse_ra_upd_req(const struct msgb *msg, struct gprs_gmm_ra_upd_req *rau_req);
int gprs_gmm_parse_att_req(const struct msgb *msg, struct gprs_gmm_att_req *att_req);

View File

@@ -1,11 +1,16 @@
#ifndef _GPRS_LLC_H
#define _GPRS_LLC_H
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/core/timer.h>
#include <osmocom/gsm/tlv.h>
#include <osmocom/crypt/gprs_cipher.h>
#include <osmocom/sgsn/gprs_llc_xid.h>
struct sgsn_mm_ctx;
/* Section 4.7 LLC Layer Structure */
enum gprs_llc_sapi {
GPRS_SAPI_GMM = 1,
@@ -91,6 +96,7 @@ enum gprs_llc_lle_state {
GPRS_LLES_LOCAL_REL = 6, /* Local Release */
GPRS_LLES_TIMER_REC = 7, /* Timer Recovery */
};
extern const struct value_string gprs_llc_lle_state_names[];
enum gprs_llc_llme_state {
GPRS_LLMS_UNASSIGNED = 1, /* No TLLI yet */
@@ -272,18 +278,15 @@ static inline int gprs_llc_is_retransmit(uint16_t nu, uint16_t vur)
}
/* LLC low level functions */
void gprs_llme_copy_key(struct sgsn_mm_ctx *mm, struct gprs_llc_llme *llme);
void gprs_llme_copy_key(const struct sgsn_mm_ctx *mm, struct gprs_llc_llme *llme);
/* parse a GPRS LLC header, also check for invalid frames */
int gprs_llc_hdr_parse(struct gprs_llc_hdr_parsed *ghp,
uint8_t *llc_hdr, int len);
void gprs_llc_hdr_dump(struct gprs_llc_hdr_parsed *gph, struct gprs_llc_lle *lle);
int gprs_llc_fcs(uint8_t *data, unsigned int len);
int gprs_llc_fcs(const uint8_t *data, unsigned int len);
/* LLME handling routines */
struct llist_head *gprs_llme_list(void);
struct gprs_llc_lle *gprs_lle_get_or_create(const uint32_t tlli, uint8_t sapi);
#endif

View File

@@ -5,7 +5,7 @@
struct sgsn_mm_ctx;
/* TS 23.060 6.1.1 Mobility Management States (A/Gb mode) */
/* TS 23.060 § 6.1.1 Mobility Management States (A/Gb mode) */
enum mm_state_gb_fsm_states {
ST_MM_IDLE,
ST_MM_READY,
@@ -14,9 +14,8 @@ enum mm_state_gb_fsm_states {
enum mm_state_gb_fsm_events {
E_MM_GPRS_ATTACH,
/* E_GPRS_DETACH, TODO: not used */
E_MM_GPRS_DETACH, /* MS becomes detached: due to Detach Req, RAU reject, implicit detach, etc. */
E_MM_PDU_RECEPTION,
E_MM_IMPLICIT_DETACH, /* = E_MM_CANCEL_LOCATION */
E_MM_READY_TIMER_EXPIRY,
/* E_FORCE_TO_STANDBY, TODO: not used */
/* E_ABNSORMAL_RLC_CONDITION, TODO: not used */

View File

@@ -4,8 +4,7 @@
struct sgsn_mm_ctx;
/* TS 23.060 6.1.1 Mobility Management States (A/Gb mode) */
/* TS 23.060 § 6.1.2 Mobility Management States (Iu mode) */
enum mm_state_iu_fsm_states {
ST_PMM_DETACHED,
ST_PMM_CONNECTED,
@@ -14,11 +13,11 @@ enum mm_state_iu_fsm_states {
enum mm_state_iu_fsm_events {
E_PMM_PS_ATTACH,
/* E_PS_DETACH, TODO: not used */
E_PMM_PS_DETACH, /* UE becomes detached: due to Detach Req, RAU reject, implicit detach, etc. */
E_PMM_PS_CONN_RELEASE,
E_PMM_PS_CONN_ESTABLISH,
E_PMM_IMPLICIT_DETACH, /* = E_PS_ATTACH_REJECT, E_RAU_REJECT */
E_PMM_RA_UPDATE, /* = Serving RNC relocation */
E_PMM_RX_GGSN_GTPU_DT_EI, /* param: struct sgsn_pdp_ctx *pctx */
};
extern struct osmo_fsm mm_state_iu_fsm;

View File

@@ -0,0 +1,9 @@
#pragma once
#include <stdbool.h>
#include <osmocom/core/msgb.h>
#include <osmocom/sgsn/gprs_llc.h>
/* called by the ns layer */
int gprs_ns_prim_cb(struct osmo_prim_hdr *oph, void *ctx);

View File

@@ -1,19 +1,67 @@
#pragma once
#include "config.h"
#include <osmocom/core/msgb.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#ifdef BUILD_IU
#include <osmocom/ranap/ranap_ies_defs.h>
#include <osmocom/ranap/ranap_msg_factory.h>
#include <osmocom/ranap/iu_client.h>
#include <osmocom/sgsn/iu_client.h>
#include <osmocom/sgsn/sccp.h>
struct sgsn_mm_ctx;
struct sgsn_pdp_ctx;
/* struct RANAP_GlobalRNC_ID with a coupled buffer where .buf points to.
* Used to easily generate a struct RANAP_GlobalRNC_ID to encode,
* see sgsn_ranap_iu_grnc_id_compose(). */
struct iu_grnc_id {
uint8_t plmn_buf[3];
struct RANAP_GlobalRNC_ID grnc_id;
};
int sgsn_ranap_iu_grnc_id_compose(struct iu_grnc_id *dst, const struct osmo_rnc_id *src);
void activate_pdp_rabs(struct sgsn_mm_ctx *ctx);
int sgsn_ranap_iu_event(struct ranap_ue_conn_ctx *ctx, enum ranap_iu_event_type type, void *data);
int iu_rab_act_ps(uint8_t rab_id, struct sgsn_pdp_ctx *pdp);
int gsm0408_gprs_rcvmsg_iu(struct msgb *msg, struct gprs_ra_id *ra_id, uint16_t *sai);
#endif
int sgsn_ranap_iu_tx(struct msgb *msg, uint8_t sapi);
int sgsn_ranap_iu_tx_rab_ps_ass_req(struct ranap_ue_conn_ctx *ue_ctx,
uint8_t rab_id, uint32_t gtp_ip, uint32_t gtp_tei);
int sgsn_ranap_iu_tx_sec_mode_cmd(struct ranap_ue_conn_ctx *uectx, struct osmo_auth_vector *vec,
int send_ck, int new_key);
int sgsn_ranap_iu_tx_common_id(struct ranap_ue_conn_ctx *ue_ctx, const char *imsi);
int sgsn_ranap_iu_tx_release(struct ranap_ue_conn_ctx *ctx, const struct RANAP_Cause *cause);
/* Transmit a Iu Release Command and submit event RANAP_IU_EVENT_IU_RELEASE upon
* Release Complete or timeout. Caller is responsible to free the context and
* closing the SCCP connection (sgsn_ranap_iu_free_ue) upon recieval of the event. */
void sgsn_ranap_iu_tx_release_free(struct ranap_ue_conn_ctx *ctx,
const struct RANAP_Cause *cause,
int timeout);
int sgsn_ranap_iu_tx_cl(struct sgsn_sccp_user_iups *scu_iups,
const struct osmo_sccp_addr *dst_addr,
struct msgb *msg);
int sgsn_ranap_iu_tx_error_ind(struct sgsn_sccp_user_iups *scu_iups,
const struct osmo_sccp_addr *dst_addr,
const RANAP_Cause_t *cause);
void sgsn_ranap_iu_handle_co_initial(struct ranap_iu_rnc *iu_rnc,
uint32_t conn_id,
const ranap_message *message);
void sgsn_ranap_iu_handle_co(struct ranap_ue_conn_ctx *ue_ctx, const ranap_message *message);
/* Entry points from rx SCCP: */
int sgsn_ranap_iu_rx_cl_msg(struct sgsn_sccp_user_iups *scu_iups,
const struct osmo_scu_unitdata_param *ud_prim,
const uint8_t *data, size_t len);
int sgsn_ranap_iu_rx_co_initial_msg(struct sgsn_sccp_user_iups *scu_iups,
const struct osmo_sccp_addr *rem_sccp_addr,
uint32_t conn_id,
const uint8_t *data, size_t len);
int sgsn_ranap_iu_rx_co_msg(struct ranap_ue_conn_ctx *ue_ctx, const uint8_t *data, size_t len);
#endif /* ifdef BUILD_IU */
struct ranap_ue_conn_ctx;
/* On RANAP, Returns pointer to he associated ranap_ue_conn_ctx in msg, filled

View File

@@ -0,0 +1,140 @@
/*! \file gprs_routing_area.h */
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/utils.h>
#include <osmocom/gsm/gsm23003.h>
/* rai -> struct osmo_routing_area_id * */
#define LOGRAI(level, rai, fmt, args...) \
do {\
char __log_rai_buf[32]; \
LOGP(DRA, level, "RA(%s) " fmt, \
osmo_rai_name2_buf(__log_rai_buf, sizeof(__log_rai_buf), rai), \
## args); \
} while (0)
/* ra -> struct sgsn_ra * */
#define LOGRA(level, ra, fmt, args...) \
LOGRAI(level, (&(ra)->rai), fmt, ## args)
struct sgsn_instance;
struct sgsn_mm_ctx;
struct sgsn_ra_global {
/* list of struct sgsn_ra */
struct llist_head ra_list;
};
enum sgsn_ra_ran_type {
RA_TYPE_GERAN_Gb,
RA_TYPE_UTRAN_Iu,
};
extern const struct value_string sgsn_ra_ran_type_names[];
struct sgsn_ra {
/* Entry in sgsn_ra_global->ra_list */
struct llist_head list;
struct osmo_routing_area_id rai;
/* For GERAN: every PCU is connected to the SGSN. It allows the SGSN to know every single cell.
* For routing, the SGSN must know to which PCU a given cell is connected.
* It is possible that more than one PCU serves the same Routing Area.
*
* For UTRAN: only the RNC (HNB via HNBGW) is communicating with the SGSN.
* The SGSN doesn't know every cell, because they aren't accepted individually by the SGSN.
* The SGSN only "knows" RAI/SAI if they have been used. In the future it would be a good idea to
* allow configuring RA in the vty/config as well.
* Similar to the GERAN Cell, but iu_client doesn't notify us for every given SAI, only for RAC.
* Further the SGSN doesn't get informed about Service Area and can't relate the SAI to a given UE.
* For UTRAN only do a LAC/RAC <> RNC relation and don't have a specific cell relation.
*/
enum sgsn_ra_ran_type ran_type;
union {
struct {
/* the RNC id must be the same for a given Routing Area */
struct osmo_rnc_id rnc_id;
} utran;
} u;
/* GERAN/UTRAN: cells contains a list of sgsn_ra_cells which are alive */
struct llist_head cells_alive_list;
};
struct sgsn_ra_cell {
/* Entry in sgsn_ra->cells */
struct llist_head list;
/*! link back to the parent */
struct sgsn_ra *ra;
enum sgsn_ra_ran_type ran_type;
union {
struct {
uint16_t nsei;
uint16_t bvci;
uint16_t cell_id;
} geran;
struct {
/* the RNC id must be the same for a given Routing Area */
uint16_t sac;
} utran;
} u;
};
void sgsn_ra_init(struct sgsn_instance *inst);
struct sgsn_ra *sgsn_ra_alloc(const struct osmo_routing_area_id *rai, enum sgsn_ra_ran_type ran_type);
struct sgsn_ra *sgsn_ra_find_or_create(const struct osmo_routing_area_id *rai, enum sgsn_ra_ran_type ran_type);
struct sgsn_ra *sgsn_ra_get_ra(const struct osmo_routing_area_id *rai);
void sgsn_ra_free(struct sgsn_ra *ra);
struct sgsn_ra_cell *sgsn_ra_cell_alloc_geran(struct sgsn_ra *ra, uint16_t cell_id, uint16_t nsei, uint16_t bvci);
void sgsn_ra_cell_free(struct sgsn_ra_cell *cell);
/* GERAN */
/* Called by BSSGP layer to inform about a reset on a PtP BVCI */
int sgsn_ra_geran_bvc_cell_reset_ind(uint16_t nsei, uint16_t bvci, struct osmo_cell_global_id_ps *cgi_ps);
/* Called by BSSGP layer to inform about a reset on a Signal BVCI */
void sgsn_ra_geran_bvc_sign_reset_ind(uint16_t nsei);
/* FIXME: handle BVC BLOCK/UNBLOCK/UNAVAILABLE */
/* Called by NS-VC layer to inform about an unavailable NSEI (and all BVCI on them) */
int sgsn_ra_geran_nsei_failure_ind(uint16_t nsei);
struct sgsn_ra_cell *sgsn_ra_geran_get_cell_by_cgi_ps(const struct osmo_cell_global_id_ps *cgi_ps);
struct sgsn_ra_cell *sgsn_ra_geran_get_cell_by_lai(const struct osmo_location_area_id *lai, uint16_t cell_id);
struct sgsn_ra_cell *sgsn_ra_geran_get_cell_by_cgi(const struct osmo_cell_global_id *cgi);
struct sgsn_ra_cell *sgsn_ra_geran_get_cell_by_ra(const struct sgsn_ra *ra, uint16_t cell_id);
struct sgsn_ra_cell *sgsn_ra_geran_get_cell_by_gb(uint16_t nsei, uint16_t bvci);
/* UTRAN */
int sgsn_ra_utran_register(const struct osmo_routing_area_id *rai, const struct osmo_rnc_id *rnc_id);
struct sgsn_ra *sgsn_ra_geran_get_ra(const struct osmo_routing_area_id *rai);
/* Page the whole routing area for this mmctx */
int sgsn_ra_geran_page_ra(const struct osmo_routing_area_id *rai, struct sgsn_mm_ctx *mmctx);
struct sgsn_ra *sgsn_ra_utran_get_ra(const struct osmo_routing_area_id *rai);
/*
* return value for callbacks.
* STOP: stop calling the callback for the remaining cells, sgsn_ra_foreach_ra() returns 0
* CONT: continue to call the callback for remaining cells
* ABORT: stop calling the callback for the remaining cells, sgsn_ra_foreach_ra() returns -1
*/
#define SGSN_RA_CB_STOP 1
#define SGSN_RA_CB_CONT 0
#define SGSN_RA_CB_ERROR -1
typedef int (sgsn_ra_cb_t)(struct sgsn_ra_cell *ra_cell, void *cb_data);
int sgsn_ra_foreach_cell(struct sgsn_ra *ra, sgsn_ra_cb_t *cb, void *cb_data);
int sgsn_ra_foreach_cell2(struct osmo_routing_area_id *rai, sgsn_ra_cb_t *cb, void *cb_data);
/* Page the whole routing area for this mmctx */
int sgsn_ra_utran_page_ra(const struct osmo_routing_area_id *rai, const struct sgsn_mm_ctx *mmctx);

View File

@@ -1,526 +0,0 @@
#ifndef _GPRS_SGSN_H
#define _GPRS_SGSN_H
#include <stdint.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <osmocom/core/fsm.h>
#include <osmocom/core/timer.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/crypt/gprs_cipher.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/crypt/auth.h>
#define GSM_EXTENSION_LENGTH 15
#define GSM_APN_LENGTH 102
struct gprs_llc_lle;
struct ctrl_handle;
struct gprs_subscr;
enum gsm48_gsm_cause;
enum gprs_mm_ctr {
GMM_CTR_PKTS_SIG_IN,
GMM_CTR_PKTS_SIG_OUT,
GMM_CTR_PKTS_UDATA_IN,
GMM_CTR_PKTS_UDATA_OUT,
GMM_CTR_BYTES_UDATA_IN,
GMM_CTR_BYTES_UDATA_OUT,
GMM_CTR_PDP_CTX_ACT,
GMM_CTR_SUSPEND,
GMM_CTR_PAGING_PS,
GMM_CTR_PAGING_CS,
GMM_CTR_RA_UPDATE,
};
enum gprs_pdp_ctx {
PDP_CTR_PKTS_UDATA_IN,
PDP_CTR_PKTS_UDATA_OUT,
PDP_CTR_BYTES_UDATA_IN,
PDP_CTR_BYTES_UDATA_OUT,
};
enum gprs_t3350_mode {
GMM_T3350_MODE_NONE,
GMM_T3350_MODE_ATT,
GMM_T3350_MODE_RAU,
GMM_T3350_MODE_PTMSI_REALL,
};
/* Authorization/ACL handling */
enum sgsn_auth_state {
SGSN_AUTH_UNKNOWN,
SGSN_AUTH_AUTHENTICATE,
SGSN_AUTH_UMTS_RESYNC,
SGSN_AUTH_ACCEPTED,
SGSN_AUTH_REJECTED
};
#define MS_RADIO_ACCESS_CAPA
enum sgsn_ggsn_lookup_state {
SGSN_GGSN_2DIGIT,
SGSN_GGSN_3DIGIT,
};
struct sgsn_ggsn_lookup {
int state;
struct sgsn_mm_ctx *mmctx;
/* APN string */
char apn_str[GSM_APN_LENGTH];
/* the original data */
struct msgb *orig_msg;
struct tlv_parsed tp;
/* for dealing with re-transmissions */
uint8_t nsapi;
uint8_t sapi;
uint8_t ti;
};
enum sgsn_ran_type {
/* GPRS/EDGE via Gb */
MM_CTX_T_GERAN_Gb,
/* UMTS via Iu */
MM_CTX_T_UTRAN_Iu,
#if 0
/* GPRS/EDGE via Iu, not supported */
MM_CTX_T_GERAN_Iu,
#endif
};
extern const struct value_string sgsn_ran_type_names[];
struct service_info {
uint8_t type;
uint16_t pdp_status;
};
struct ranap_ue_conn_ctx;
struct gsm_auth_tuple {
int use_count;
int key_seq;
struct osmo_auth_vector vec;
};
#define GSM_KEY_SEQ_INVAL 7 /* GSM 04.08 - 10.5.1.2 */
/* According to TS 03.60, Table 5: SGSN MM and PDP Contexts */
/* Extended by 3GPP TS 23.060, Table 6: SGSN MM and PDP Contexts */
struct sgsn_mm_ctx {
struct llist_head list;
enum sgsn_ran_type ran_type;
char imsi[GSM23003_IMSI_MAX_DIGITS+1];
struct osmo_fsm_inst *gmm_fsm;
uint32_t p_tmsi;
uint32_t p_tmsi_old; /* old P-TMSI before new is confirmed */
uint32_t p_tmsi_sig;
char imei[GSM23003_IMEISV_NUM_DIGITS+1];
/* Opt: Software Version Numbber / TS 23.195 */
char msisdn[GSM_EXTENSION_LENGTH];
struct gprs_ra_id ra;
struct {
uint16_t cell_id; /* Gb only */
uint32_t cell_id_age; /* Gb only */
uint8_t radio_prio_sms;
/* Additional bits not present in the GSM TS */
uint16_t nsei;
uint16_t bvci;
struct gprs_llc_llme *llme;
uint32_t tlli;
uint32_t tlli_new;
/* TS 23.060 6.1.1 Mobility Management States (A/Gb mode) */
struct osmo_fsm_inst *mm_state_fsm;
} gb;
struct {
int new_key;
uint16_t sac; /* Iu: Service Area Code */
uint32_t sac_age; /* Iu: Service Area Code age */
/* CSG ID */
/* CSG Membership */
/* Access Mode */
/* Seelected CN Operator ID (TS 23.251) */
/* CSG Subscription Data */
/* LIPA Allowed */
/* Voice Support Match Indicator */
struct ranap_ue_conn_ctx *ue_ctx;
struct service_info service;
/* TS 23.060 6.1.2 Mobility Management States (Iu mode) */
struct osmo_fsm_inst *mm_state_fsm;
} iu;
struct {
struct osmo_fsm_inst *fsm;
/* when a second attach req arrives while in this procedure,
* the fsm needs to compare it against old to decide what to do */
struct msgb *attach_req;
uint32_t id_type;
unsigned int auth_reattempt; /* tracking UMTS resync auth attempts */
} gmm_att_req;
/* VLR number */
uint32_t new_sgsn_addr;
/* Authentication Triplet */
struct gsm_auth_tuple auth_triplet;
/* Kc */
/* Iu: CK, IK, KSI */
/* CKSN */
enum gprs_ciph_algo ciph_algo;
/* Auth & Ciphering Request reference from 3GPP TS 24.008 § 10.5.5.19: */
uint8_t ac_ref_nr_used;
struct {
uint8_t len;
uint8_t buf[50]; /* GSM 04.08 10.5.5.12a, extended in TS 24.008 */
} ms_radio_access_capa;
/* Supported Codecs (SRVCC) */
struct {
uint8_t len;
uint8_t buf[8]; /* GSM 04.08 10.5.5.12, extended in TS 24.008 */
} ms_network_capa;
/* UE Netowrk Capability (E-UTRAN) */
uint16_t drx_parms;
/* Active Time value for PSM */
int mnrg; /* MS reported to HLR? */
int ngaf; /* MS reported to MSC/VLR? */
int ppf; /* paging for GPRS + non-GPRS? */
/* Subscribed Charging Characteristics */
/* Trace Reference */
/* Trace Type */
/* Trigger ID */
/* OMC Identity */
/* SMS Parameters */
int recovery;
/* Access Restriction */
/* GPRS CSI (CAMEL) */
/* MG-CSI (CAMEL) */
/* Subscribed UE-AMBR */
/* UE-AMBR */
/* APN Subscribed */
struct llist_head pdp_list;
struct rate_ctr_group *ctrg;
struct osmo_timer_list timer;
unsigned int T; /* Txxxx number */
unsigned int num_T_exp; /* number of consecutive T expirations */
enum gprs_t3350_mode t3350_mode;
uint8_t t3370_id_type;
uint8_t pending_req; /* the request's message type */
/* TODO: There isn't much semantic difference between t3350_mode
* (refers to the timer) and pending_req (refers to the procedure),
* where mm->T == 3350 => mm->t3350_mode == f(mm->pending_req). Check
* whether one of them can be dropped. */
enum sgsn_auth_state auth_state;
enum osmo_sub_auth_type sec_ctx;
/* the string representation of the current hlr */
char hlr[GSM_EXTENSION_LENGTH];
/* the current GGSN look-up operation */
struct sgsn_ggsn_lookup *ggsn_lookup;
struct gprs_subscr *subscr;
};
static inline bool sgsn_mm_ctx_is_authenticated(struct sgsn_mm_ctx *ctx)
{
switch (ctx->sec_ctx) {
case OSMO_AUTH_TYPE_GSM:
case OSMO_AUTH_TYPE_UMTS:
return true;
default:
return false;
}
}
#define LOGMMCTXP(level, mm, fmt, args...) \
LOGP(DMM, level, "MM(%s/%08x) " fmt, (mm) ? (mm)->imsi : "---", \
(mm) ? (mm)->p_tmsi : GSM_RESERVED_TMSI, ## args)
#ifdef BUILD_IU
#define LOGIUP(ue, level, fmt, args...) \
LOGP(DMM, level, "UE(0x%x){%s} " fmt, ue->conn_id, osmo_rai_name(&(ue)->ra_id), ## args)
#else
#define LOGIUP(ue, level, fmt, args...) \
LOGP(DMM, level, "UE(%p){NOTSUPPORTED} " fmt, ue, ## args)
#endif
#define LOGGBP(llme, level, fmt, args...) \
LOGP(DMM, level, "LLME(%08x/%08x){%s} " fmt, (llme)->old_tlli, \
(llme)->tlli, get_value_string_or_null(gprs_llc_llme_state_names, (llme)->state), ## args);
#define LOGGBIUP(llme, msg, level, fmt, args...) \
do { \
struct ranap_ue_conn_ctx * _ue; \
if (llme) { \
LOGGBP(llme, level, fmt, ## args); \
} else if ((msg) && (_ue = MSG_IU_UE_CTX(msg))) { \
LOGIUP(_ue, level, fmt, ## args); \
} else { OSMO_ASSERT(0); } \
} while (0)
/* look-up a SGSN MM context based on TLLI + RAI */
struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
const struct gprs_ra_id *raid);
struct sgsn_mm_ctx *sgsn_mm_ctx_by_ptmsi(uint32_t tmsi);
struct sgsn_mm_ctx *sgsn_mm_ctx_by_imsi(const char *imsi);
struct sgsn_mm_ctx *sgsn_mm_ctx_by_ue_ctx(const void *uectx);
/* look-up by matching TLLI and P-TMSI (think twice before using this) */
struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli_and_ptmsi(uint32_t tlli,
const struct gprs_ra_id *raid);
/* Allocate a new SGSN MM context */
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_gb(uint32_t tlli,
const struct gprs_ra_id *raid);
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_iu(void *uectx);
void sgsn_mm_ctx_cleanup_free(struct sgsn_mm_ctx *ctx);
struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,
struct tlv_parsed *tp,
enum gsm48_gsm_cause *gsm_cause,
char *apn_str);
enum pdp_ctx_state {
PDP_STATE_NONE,
PDP_STATE_CR_REQ,
PDP_STATE_CR_CONF,
/* 04.08 / Figure 6.2 / 6.1.2.2 */
PDP_STATE_INACT_PEND,
PDP_STATE_INACTIVE = PDP_STATE_NONE,
};
enum pdp_type {
PDP_TYPE_NONE,
PDP_TYPE_ETSI_PPP,
PDP_TYPE_IANA_IPv4,
PDP_TYPE_IANA_IPv6,
};
struct sgsn_pdp_ctx {
struct llist_head list; /* list_head for mmctx->pdp_list */
struct llist_head g_list; /* list_head for global list */
struct sgsn_mm_ctx *mm; /* back pointer to MM CTX */
int destroy_ggsn; /* destroy it on destruction */
struct sgsn_ggsn_ctx *ggsn; /* which GGSN serves this PDP */
struct llist_head ggsn_list; /* list_head for ggsn->pdp_list */
struct rate_ctr_group *ctrg;
//unsigned int id;
struct pdp_t *lib; /* pointer to libgtp PDP ctx */
enum pdp_ctx_state state;
enum pdp_type type;
uint32_t address;
char *apn_subscribed;
//char *apn_used;
uint16_t nsapi; /* SNDCP */
uint16_t sapi; /* LLC */
uint8_t ti; /* transaction identifier */
int vplmn_allowed;
uint32_t qos_profile_subscr;
//uint32_t qos_profile_req;
//uint32_t qos_profile_neg;
uint8_t radio_prio;
//uint32_t charging_id;
struct osmo_timer_list timer;
unsigned int T; /* Txxxx number */
unsigned int num_T_exp; /* number of consecutive T expirations */
struct osmo_timer_list cdr_timer; /* CDR record wird timer */
struct timespec cdr_start; /* The start of the CDR */
uint64_t cdr_bytes_in;
uint64_t cdr_bytes_out;
uint32_t cdr_charging_id;
};
#define LOGPDPCTXP(level, pdp, fmt, args...) \
LOGP(DGPRS, level, "PDP(%s/%u) " \
fmt, (pdp)->mm ? (pdp)->mm->imsi : "---", (pdp)->ti, ## args)
/* look up PDP context by MM context and NSAPI */
struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_nsapi(const struct sgsn_mm_ctx *mm,
uint8_t nsapi);
/* look up PDP context by MM context and transaction ID */
struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm,
uint8_t tid);
struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
struct sgsn_ggsn_ctx *ggsn,
uint8_t nsapi);
void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp);
void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp);
struct sgsn_ggsn_ctx {
struct llist_head list;
uint32_t id;
unsigned int gtp_version;
struct in_addr remote_addr;
int remote_restart_ctr;
struct gsn_t *gsn;
struct llist_head pdp_list; /* list of associated pdp ctx (struct sgsn_pdp_ctx*) */
struct osmo_timer_list echo_timer;
unsigned int echo_interval;
};
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id);
void sgsn_ggsn_ctx_free(struct sgsn_ggsn_ctx *ggc);
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(uint32_t id);
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct in_addr *addr);
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(uint32_t id);
void sgsn_ggsn_ctx_drop_pdp(struct sgsn_pdp_ctx *pctx);
int sgsn_ggsn_ctx_drop_all_pdp_except(struct sgsn_ggsn_ctx *ggsn, struct sgsn_pdp_ctx *except);
int sgsn_ggsn_ctx_drop_all_pdp(struct sgsn_ggsn_ctx *ggsn);
void sgsn_ggsn_ctx_add_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp);
void sgsn_ggsn_ctx_remove_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp);
void sgsn_ggsn_ctx_check_echo_timer(struct sgsn_ggsn_ctx *ggc);
#define LOGGGSN(ggc, level, fmt, args...) { \
char _buf[INET_ADDRSTRLEN]; \
LOGP(DGTP, level, "GGSN(%" PRIu32 ":%s): " fmt, (ggc)->id, inet_ntop(AF_INET, &(ggc)->remote_addr, _buf, sizeof(_buf)), ## args); \
} while (0)
struct apn_ctx {
struct llist_head list;
struct sgsn_ggsn_ctx *ggsn;
char *name;
char *imsi_prefix;
char *description;
};
struct apn_ctx *sgsn_apn_ctx_find_alloc(const char *name, const char *imsi_prefix);
void sgsn_apn_ctx_free(struct apn_ctx *actx);
struct apn_ctx *sgsn_apn_ctx_by_name(const char *name, const char *imsi_prefix);
struct apn_ctx *sgsn_apn_ctx_match(const char *name, const char *imsi_prefix);
extern struct llist_head sgsn_mm_ctxts;
extern struct llist_head sgsn_ggsn_ctxts;
extern struct llist_head sgsn_apn_ctxts;
extern struct llist_head sgsn_pdp_ctxts;
uint32_t sgsn_alloc_ptmsi(void);
struct sgsn_instance *sgsn_instance_alloc(void *talloc_ctx);
void sgsn_inst_init(struct sgsn_instance *sgsn);
char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len);
/*
* ctrl interface related work
*/
int sgsn_ctrl_cmds_install(void);
/*
* Authorization/ACL handling
*/
struct imsi_acl_entry {
struct llist_head list;
char imsi[16+1];
};
/* see GSM 09.02, 17.7.1, PDP-Context and GPRSSubscriptionData */
/* see GSM 09.02, B.1, gprsSubscriptionData */
struct sgsn_subscriber_pdp_data {
struct llist_head list;
unsigned int context_id;
uint16_t pdp_type;
char apn_str[GSM_APN_LENGTH];
uint8_t qos_subscribed[20];
size_t qos_subscribed_len;
uint8_t pdp_charg[2];
bool has_pdp_charg;
};
struct sgsn_subscriber_data {
struct sgsn_mm_ctx *mm;
struct gsm_auth_tuple auth_triplets[5];
int auth_triplets_updated;
struct llist_head pdp_list;
int error_cause;
uint8_t msisdn[9];
size_t msisdn_len;
uint8_t hlr[9];
size_t hlr_len;
uint8_t pdp_charg[2];
bool has_pdp_charg;
};
#define SGSN_ERROR_CAUSE_NONE (-1)
#define LOGGSUBSCRP(level, subscr, fmt, args...) \
LOGP(DGPRS, level, "SUBSCR(%s) " fmt, \
(subscr) ? (subscr)->imsi : "---", \
## args)
struct sgsn_config;
struct sgsn_instance;
extern const struct value_string *sgsn_auth_state_names;
void sgsn_auth_init(struct sgsn_instance *sgsn);
struct imsi_acl_entry *sgsn_acl_lookup(const char *imsi, const struct sgsn_config *cfg);
int sgsn_acl_add(const char *imsi, struct sgsn_config *cfg);
int sgsn_acl_del(const char *imsi, struct sgsn_config *cfg);
/* Request authorization */
int sgsn_auth_request(struct sgsn_mm_ctx *mm);
enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mm);
void sgsn_auth_update(struct sgsn_mm_ctx *mm);
struct gsm_auth_tuple *sgsn_auth_get_tuple(struct sgsn_mm_ctx *mmctx,
unsigned key_seq);
/*
* GPRS subscriber data
*/
#define GPRS_SUBSCRIBER_FIRST_CONTACT 0x00000001
#define GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING (1 << 16)
#define GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING (1 << 17)
#define GPRS_SUBSCRIBER_CANCELLED (1 << 18)
#define GPRS_SUBSCRIBER_ENABLE_PURGE (1 << 19)
#define GPRS_SUBSCRIBER_UPDATE_PENDING_MASK ( \
GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING | \
GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING \
)
int gprs_subscr_init(struct sgsn_instance *sgi);
int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx,
const uint8_t *auts,
const uint8_t *auts_rand);
int gprs_subscr_auth_sync(struct gprs_subscr *subscr,
const uint8_t *auts, const uint8_t *auts_rand);
void gprs_subscr_cleanup(struct gprs_subscr *subscr);
struct gprs_subscr *gprs_subscr_get_or_create(const char *imsi);
struct gprs_subscr *gprs_subscr_get_or_create_by_mmctx( struct sgsn_mm_ctx *mmctx);
struct gprs_subscr *gprs_subscr_get_by_imsi(const char *imsi);
void gprs_subscr_cancel(struct gprs_subscr *subscr);
void gprs_subscr_update(struct gprs_subscr *subscr);
void gprs_subscr_update_auth_info(struct gprs_subscr *subscr);
int gprs_subscr_rx_gsup_message(struct msgb *msg);
/* Called on subscriber data updates */
void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx);
int gprs_sndcp_vty_init(void);
struct sgsn_instance;
int sgsn_gtp_init(struct sgsn_instance *sgi);
void sgsn_rate_ctr_init();
#endif /* _GPRS_SGSN_H */

View File

@@ -1,7 +1,10 @@
#pragma once
#include <osmocom/core/msgb.h>
#include <osmocom/sgsn/gprs_sgsn.h>
struct sgsn_mm_ctx;
struct sgsn_pdp_ctx;
struct gprs_llc_llme;
int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause, bool teardown);
int gsm48_tx_gsm_act_pdp_rej(struct sgsn_mm_ctx *mm, uint8_t tid,

View File

@@ -3,6 +3,9 @@
#include <stdint.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/gsm/gsm48.h>
struct gprs_llc_lle;
/* A fragment queue header, maintaining list of fragments for one N-PDU */
struct defrag_state {
@@ -44,7 +47,7 @@ struct gprs_sndcp_entity {
struct llist_head list;
/* FIXME: move this RA_ID up to the LLME or even higher */
struct gprs_ra_id ra_id;
struct osmo_routing_area_id rai;
/* reference to the LLC Entity below this SNDCP entity */
struct gprs_llc_lle *lle;
/* The NSAPI we shall use on top of LLC */
@@ -60,6 +63,8 @@ struct gprs_sndcp_entity {
extern struct llist_head gprs_sndcp_entities;
int gprs_sndcp_vty_init(void);
/* Set of SNDCP-XID negotiation (See also: TS 144 065,
* Section 6.8 XID parameter negotiation) */
int sndcp_sn_xid_req(struct gprs_llc_lle *lle, uint8_t nsapi);
@@ -68,7 +73,7 @@ int sndcp_sn_xid_req(struct gprs_llc_lle *lle, uint8_t nsapi);
* Section 6.8 XID parameter negotiation) */
int sndcp_sn_xid_ind(struct gprs_llc_xid_field *xid_field_indication,
struct gprs_llc_xid_field *xid_field_response,
struct gprs_llc_lle *lle);
const struct gprs_llc_lle *lle);
/* Process SNDCP-XID indication
* (See also: TS 144 065, Section 6.8 XID parameter negotiation) */
@@ -76,4 +81,21 @@ int sndcp_sn_xid_conf(struct gprs_llc_xid_field *xid_field_conf,
struct gprs_llc_xid_field *xid_field_request,
struct gprs_llc_lle *lle);
/* Clean up all gprs_sndcp_entities related to llme (OS#4824) */
void gprs_sndcp_sm_deactivate_ind_by_llme(const struct gprs_llc_llme *llme);
/* Called by SNDCP when it has received/re-assembled a N-PDU */
int sndcp_sn_unitdata_ind(struct gprs_sndcp_entity *sne, struct msgb *msg,
uint32_t npdu_len, uint8_t *npdu);
int sndcp_sn_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi,
void *mmcontext);
/* Entry point for the SNSM-ACTIVATE.indication */
int sndcp_sm_activate_ind(struct gprs_llc_lle *lle, uint8_t nsapi);
/* Entry point for the SNSM-DEACTIVATE.indication */
int sndcp_sm_deactivate_ind(const struct gprs_llc_lle *lle, uint8_t nsapi);
int sndcp_ll_unitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
uint8_t *hdr, uint16_t len);
#endif /* INT_SNDCP_H */

View File

@@ -4,10 +4,70 @@
#include <stdint.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/socket.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/sgsn/apn.h>
struct sgsn_instance;
struct sgsn_mm_ctx;
extern struct llist_head * const gprs_subscribers;
#define GPRS_SUBSCRIBER_FIRST_CONTACT 0x00000001
#define GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING (1 << 16)
#define GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING (1 << 17)
#define GPRS_SUBSCRIBER_CANCELLED (1 << 18)
#define GPRS_SUBSCRIBER_ENABLE_PURGE (1 << 19)
#define GPRS_SUBSCRIBER_UPDATE_PENDING_MASK ( \
GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING | \
GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING \
)
struct gsm_auth_tuple {
int use_count;
int key_seq;
struct osmo_auth_vector vec;
};
#define GSM_KEY_SEQ_INVAL 7 /* GSM 04.08 - 10.5.1.2 */
struct sgsn_subscriber_data {
struct sgsn_mm_ctx *mm;
struct gsm_auth_tuple auth_triplets[5];
int auth_triplets_updated;
struct llist_head pdp_list;
int error_cause;
uint8_t msisdn[9];
size_t msisdn_len;
uint8_t hlr[9];
size_t hlr_len;
uint8_t pdp_charg[2];
bool has_pdp_charg;
};
/* see GSM 09.02, 17.7.1, PDP-Context and GPRSSubscriptionData */
/* see GSM 09.02, B.1, gprsSubscriptionData */
struct sgsn_subscriber_pdp_data {
struct llist_head list;
unsigned int context_id;
enum gsm48_pdp_type_org pdp_type_org;
enum gsm48_pdp_type_nr pdp_type_nr;
struct osmo_sockaddr pdp_address[2];
char apn_str[GSM_APN_LENGTH];
uint8_t qos_subscribed[20];
size_t qos_subscribed_len;
uint8_t pdp_charg[2];
bool has_pdp_charg;
};
struct sgsn_subscriber_pdp_data *sgsn_subscriber_pdp_data_alloc(struct sgsn_subscriber_data *sdata);
struct gprs_subscr {
struct llist_head entry;
int use_count;
@@ -29,3 +89,22 @@ struct gprs_subscr *_gprs_subscr_put(struct gprs_subscr *gsub,
const char *file, int line);
#define gprs_subscr_get(gsub) _gprs_subscr_get(gsub, __FILE__, __LINE__)
#define gprs_subscr_put(gsub) _gprs_subscr_put(gsub, __FILE__, __LINE__)
int gprs_subscr_init(struct sgsn_instance *sgi);
int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx,
const uint8_t *auts,
const uint8_t *auts_rand);
void gprs_subscr_cleanup(struct gprs_subscr *subscr);
struct gprs_subscr *gprs_subscr_get_or_create(const char *imsi);
struct gprs_subscr *gprs_subscr_get_or_create_by_mmctx(struct sgsn_mm_ctx *mmctx);
struct gprs_subscr *gprs_subscr_get_by_imsi(const char *imsi);
void gprs_subscr_cancel(struct gprs_subscr *subscr);
void gprs_subscr_update(struct gprs_subscr *subscr);
void gprs_subscr_update_auth_info(struct gprs_subscr *subscr);
int gprs_subscr_rx_gsup_message(struct msgb *msg);
#define LOGGSUBSCRP(level, subscr, fmt, args...) \
LOGP(DGPRS, level, "SUBSCR(%s) " fmt, \
(subscr) ? (subscr)->imsi : "---", \
## args)

View File

@@ -29,15 +29,11 @@
struct msgb;
struct gprs_ra_id;
int gprs_str_to_apn(uint8_t *apn_enc, size_t max_len, const char *str);
/* GSM 04.08, 10.5.7.3 GPRS Timer */
int gprs_tmr_to_secs(uint8_t tmr);
uint8_t gprs_secs_to_tmr_floor(int secs);
int gprs_is_mi_tmsi(const uint8_t *value, size_t value_len);
int gprs_is_mi_imsi(const uint8_t *value, size_t value_len);
int gprs_parse_mi_tmsi(const uint8_t *value, size_t value_len, uint32_t *tmsi);
void gprs_parse_tmsi(const uint8_t *value, uint32_t *tmsi);
int gprs_ra_id_equals(const struct gprs_ra_id *id1, const struct gprs_ra_id *id2);

View File

@@ -0,0 +1,29 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <osmocom/gsm/tlv.h>
#include <osmocom/gprs/gprs_bssgp_rim.h>
struct gprs_ra_id;
struct sgsn_instance;
struct sgsn_ggsn_ctx;
struct sgsn_pdp_ctx;
struct sgsn_mm_ctx;
struct sgsn_mme_ctx;
int sgsn_gtp_init(struct sgsn_instance *sgi);
int sgsn_mme_ran_info_req(struct sgsn_mme_ctx *mme, const struct bssgp_ran_information_pdu *pdu);
void sgsn_ggsn_echo_req(struct sgsn_ggsn_ctx *ggc);
struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
struct sgsn_mm_ctx *mmctx,
uint16_t nsapi,
struct tlv_parsed *tp);
int sgsn_gtp_data_req(struct osmo_routing_area_id *rai, int32_t tlli, uint8_t nsapi,
struct msgb *msg, uint32_t npdu_len, uint8_t *npdu);
int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx);
int send_act_pdp_cont_acc(struct sgsn_pdp_ctx *pctx);

View File

@@ -0,0 +1,41 @@
#pragma once
#include <stdint.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/timer.h>
#include <osmocom/gprs/protocol/gsm_24_301.h>
struct gsn_t;
struct sgsn_pdp_ctx;
struct sgsn_instance;
struct sgsn_ggsn_ctx {
struct llist_head list;
uint32_t id;
unsigned int gtp_version;
struct in_addr remote_addr;
int remote_restart_ctr;
struct gsn_t *gsn;
struct llist_head pdp_list; /* list of associated pdp ctx (struct sgsn_pdp_ctx*) */
struct osmo_timer_list echo_timer;
unsigned int echo_interval;
};
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(struct sgsn_instance *sgsn, uint32_t id);
void sgsn_ggsn_ctx_free(struct sgsn_ggsn_ctx *ggc);
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(struct sgsn_instance *sgsn, uint32_t id);
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct sgsn_instance *sgsn, struct in_addr *addr);
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(struct sgsn_instance *sgsn, uint32_t id);
void sgsn_ggsn_ctx_drop_pdp(struct sgsn_pdp_ctx *pctx);
int sgsn_ggsn_ctx_drop_all_pdp_except(struct sgsn_ggsn_ctx *ggsn, struct sgsn_pdp_ctx *except);
int sgsn_ggsn_ctx_drop_all_pdp(struct sgsn_ggsn_ctx *ggsn);
void sgsn_ggsn_ctx_add_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp);
void sgsn_ggsn_ctx_remove_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp);
void sgsn_ggsn_ctx_check_echo_timer(struct sgsn_ggsn_ctx *ggc);
#define LOGGGSN(ggc, level, fmt, args...) { \
char _buf[INET_ADDRSTRLEN]; \
LOGP(DGTP, level, "GGSN(%" PRIu32 ":%s): " fmt, (ggc)->id, inet_ntop(AF_INET, &(ggc)->remote_addr, _buf, sizeof(_buf)), ## args); \
} while (0)

View File

@@ -0,0 +1,46 @@
#pragma once
#include <netinet/in.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/timer.h>
#include <osmocom/gprs/protocol/gsm_24_301.h>
#include <osmocom/gsm/gsm23003.h>
struct gsn_t;
struct mme_rim_route {
struct llist_head list; /* item in struct sgsn_mme_ctx */
struct osmo_eutran_tai tai;
};
struct sgsn_mme_ctx {
struct llist_head list; /* item in sgsn_mme_ctxts */
struct llist_head routes; /* list of struct mme_rim_route */
struct sgsn_instance *sgsn; /* backpointer */
char *name;
struct in_addr remote_addr;
struct osmo_gummei gummei;
bool gummei_valid;
/* is it the default route for outgoing message? are all incoming messages accepted? */
bool default_route;
};
struct sgsn_mme_ctx *sgsn_mme_ctx_alloc(struct sgsn_instance *sgsn, const char *name);
struct sgsn_mme_ctx *sgsn_mme_ctx_find_alloc(struct sgsn_instance *sgsn, const char *name);
void sgsn_mme_ctx_free(struct sgsn_mme_ctx *mme);
struct sgsn_mme_ctx *sgsn_mme_ctx_by_name(const struct sgsn_instance *sgsn, const char *name);
struct sgsn_mme_ctx *sgsn_mme_ctx_by_addr(const struct sgsn_instance *sgsn, const struct in_addr *addr);
struct sgsn_mme_ctx *sgsn_mme_ctx_by_route(const struct sgsn_instance *sgsn, const struct osmo_eutran_tai *tai);
struct sgsn_mme_ctx *sgsn_mme_ctx_by_gummei(const struct sgsn_instance *sgsn, const struct osmo_gummei *gummei);
struct sgsn_mme_ctx *sgsn_mme_ctx_by_default_route(const struct sgsn_instance *sgsn);
void sgsn_mme_ctx_route_add(struct sgsn_mme_ctx *mme, const struct osmo_eutran_tai *tai);
void sgsn_mme_ctx_route_del(struct sgsn_mme_ctx *mme, const struct osmo_eutran_tai *tai);
#define LOGMME(mme, cat, level, fmt, args...) { \
char _buf[INET_ADDRSTRLEN]; \
LOGP(cat, level, "MME(%s:%s): " fmt, (mme)->name, inet_ntop(AF_INET, &(mme)->remote_addr, _buf, sizeof(_buf)), ## args); \
} while (0)

View File

@@ -0,0 +1,95 @@
#pragma once
#include <stdbool.h>
#include <osmocom/core/defs.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/iuh/common.h>
#include <osmocom/ranap/ranap_common.h>
#include <osmocom/ranap/vty.h>
#include <osmocom/sigtran/sccp_sap.h>
struct msgb;
struct osmo_auth_vector;
struct RANAP_RAB_SetupOrModifiedItemIEs_s;
struct ranap_iu_rnc;
struct ranap_ue_conn_ctx {
struct llist_head list; /* item in sgsn_sccp->ue_conn_ctx_list */
struct ranap_iu_rnc *rnc;
uint32_t conn_id;
int integrity_active;
struct gprs_ra_id ra_id;
enum ranap_nsap_addr_enc rab_assign_addr_enc;
bool notification; /* send notification to the upstream user */
/* if true the ue_ctx will be free on Iu release complete */
bool free_on_release;
/* Will be set when the Iu Release Command has been sent */
struct osmo_timer_list release_timeout;
};
enum ranap_iu_event_new_area_type {
RANAP_IU_NEW_LAC,
RANAP_IU_NEW_RAC,
};
struct ranap_iu_event_new_area {
const struct osmo_rnc_id *rnc_id;
enum ranap_iu_event_new_area_type cell_type;
union {
const struct osmo_location_area_id *lai;
const struct osmo_routing_area_id *rai;
} u;
};
enum ranap_iu_event_type {
RANAP_IU_EVENT_RAB_ASSIGN,
RANAP_IU_EVENT_SECURITY_MODE_COMPLETE,
RANAP_IU_EVENT_IU_RELEASE, /* An actual Iu Release message was received */
RANAP_IU_EVENT_LINK_INVALIDATED, /* A SUA link was lost or closed down */
RANAP_IU_EVENT_NEW_AREA, /* Either a new LAC/RAC has been detected */
};
extern const struct value_string iu_client_event_type_names[];
static inline const char *iu_client_event_type_str(enum ranap_iu_event_type e)
{
return get_value_string(iu_client_event_type_names, e);
}
/* Implementations of iu_recv_cb_t shall find the ranap_ue_conn_ctx in msg->dst. */
typedef int (*ranap_iu_recv_cb_t)(struct msgb *msg, struct gprs_ra_id *ra_id,
uint16_t *sai);
typedef int (*ranap_iu_event_cb_t)(struct ranap_ue_conn_ctx *ue_ctx,
enum ranap_iu_event_type type, void *data);
typedef int (*ranap_iu_rab_ass_resp_cb_t)(struct ranap_ue_conn_ctx *ue_ctx, uint8_t rab_id,
struct RANAP_RAB_SetupOrModifiedItemIEs_s *setup_ies);
int global_iu_event(struct ranap_ue_conn_ctx *ue_ctx,
enum ranap_iu_event_type type,
void *data);
int ranap_iu_init(void *ctx);
int ranap_iu_page_cs(const char *imsi, const uint32_t *tmsi, uint16_t lac)
OSMO_DEPRECATED("Use ranap_iu_page_cs2 instead");
int ranap_iu_page_ps(const char *imsi, const uint32_t *ptmsi, uint16_t lac, uint8_t rac)
OSMO_DEPRECATED("Use ranap_iu_page_ps2 instead");
int ranap_iu_page_cs2(const char *imsi, const uint32_t *tmsi, const struct osmo_location_area_id *lai);
int ranap_iu_page_ps2(const char *imsi, const uint32_t *ptmsi, const struct osmo_routing_area_id *rai);
struct ranap_ue_conn_ctx *ue_conn_ctx_alloc(struct ranap_iu_rnc *rnc, uint32_t conn_id);
void ue_conn_ctx_link_invalidated_free(struct ranap_ue_conn_ctx *ue);
/* freeing the UE will release all resources
* This will close the SCCP connection connected to the UE */
void sgsn_ranap_iu_free_ue(struct ranap_ue_conn_ctx *ue_ctx);

View File

@@ -0,0 +1,57 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <osmocom/core/defs.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/fsm.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/iuh/common.h>
#include <osmocom/sigtran/sccp_sap.h>
struct iu_lac_rac_entry {
struct llist_head entry;
struct osmo_routing_area_id rai;
};
/* A remote RNC (Radio Network Controller, like BSC but for UMTS) that has
* called us and is currently reachable at the given osmo_sccp_addr. So, when we
* know a LAC for a subscriber, we can page it at the RNC matching that LAC or
* RAC. An HNB-GW typically presents itself as if it were a single RNC, even
* though it may have several RNCs in hNodeBs connected to it. Those will then
* share the same RNC id, which they actually receive and adopt from the HNB-GW
* in the HNBAP HNB REGISTER ACCEPT message. */
struct ranap_iu_rnc {
struct llist_head entry;
struct osmo_rnc_id rnc_id;
struct sgsn_sccp_user_iups *scu_iups;
struct osmo_sccp_addr sccp_addr;
struct osmo_fsm_inst *fi;
/* A list of struct iu_lac_rac_entry */
struct llist_head lac_rac_list;
};
struct ranap_iu_rnc *iu_rnc_find_or_create(const struct osmo_rnc_id *rnc_id,
struct sgsn_sccp_user_iups *scu_iups,
const struct osmo_sccp_addr *addr);
struct ranap_iu_rnc *iu_rnc_find_by_addr(const struct osmo_sccp_addr *rnc_sccp_addr);
void iu_rnc_update_rai_seen(struct ranap_iu_rnc *rnc, const struct osmo_routing_area_id *rai);
void iu_rnc_discard_all_ue_ctx(struct ranap_iu_rnc *rnc);
int iu_rnc_tx_paging_cmd(struct ranap_iu_rnc *rnc,
const char *imsi,
const uint32_t *tmsi,
bool is_ps,
uint32_t paging_cause);
#define LOG_RNC_CAT(IU_RNC, subsys, loglevel, fmt, args ...) \
LOGPFSMSL((IU_RNC)->fi, subsys, loglevel, fmt, ## args)
#define LOG_RNC(IU_RNC, loglevel, fmt, args ...) \
LOG_RNC_CAT(IU_RNC, DRANAP, loglevel, fmt, ## args)

View File

@@ -0,0 +1,37 @@
#include <stdint.h>
#include <osmocom/core/fsm.h>
#include <osmocom/ranap/ranap_ies_defs.h>
struct ranap_iu_rnc;
enum iu_rnc_state {
IU_RNC_ST_WAIT_RX_RESET = 0,
IU_RNC_ST_WAIT_RX_RESET_ACK,
IU_RNC_ST_READY,
IU_RNC_ST_DISCARDING,
};
struct iu_rnc_ev_msg_up_co_initial_ctx {
struct ranap_iu_rnc *rnc;
uint32_t conn_id;
ranap_message message;
};
struct iu_rnc_ev_msg_up_co_ctx {
struct ranap_ue_conn_ctx *ue_ctx;
ranap_message message;
};
enum iu_rnc_event {
IU_RNC_EV_MSG_UP_CO_INITIAL, /* struct iu_rnc_ev_msg_up_co_initial_ctx* */
IU_RNC_EV_MSG_UP_CO, /* struct iu_rnc_ev_msg_up_co_ctx* */
IU_RNC_EV_RX_RESET, /* no param */
IU_RNC_EV_RX_RESET_ACK, /* no param */
IU_RNC_EV_MSG_DOWN_CL, /* struct msgb* */
IU_RNC_EV_AVAILABLE,
IU_RNC_EV_UNAVAILABLE
};
extern struct osmo_fsm iu_rnc_fsm;

View File

@@ -0,0 +1,301 @@
#pragma once
#include "config.h"
#include <stdint.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <osmocom/core/fsm.h>
#include <osmocom/core/timer.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/crypt/gprs_cipher.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/crypt/auth.h>
#include <osmocom/sgsn/apn.h>
#include <osmocom/sgsn/auth.h>
#include <osmocom/sgsn/gprs_subscriber.h>
#define GSM_EXTENSION_LENGTH 15
struct gprs_llc_lle;
struct ctrl_handle;
struct gprs_subscr;
struct sgsn_ggsn_ctx;
struct sgsn_pdp_ctx;
enum gsm48_gsm_cause;
enum gprs_mm_ctr {
GMM_CTR_PKTS_SIG_IN,
GMM_CTR_PKTS_SIG_OUT,
GMM_CTR_PKTS_UDATA_IN,
GMM_CTR_PKTS_UDATA_OUT,
GMM_CTR_BYTES_UDATA_IN,
GMM_CTR_BYTES_UDATA_OUT,
GMM_CTR_PDP_CTX_ACT,
GMM_CTR_SUSPEND,
GMM_CTR_PAGING_PS,
GMM_CTR_PAGING_CS,
GMM_CTR_RA_UPDATE,
};
enum gprs_t3350_mode {
GMM_T3350_MODE_NONE,
GMM_T3350_MODE_ATT,
GMM_T3350_MODE_RAU,
GMM_T3350_MODE_PTMSI_REALL,
};
enum sgsn_ggsn_lookup_state {
SGSN_GGSN_2DIGIT,
SGSN_GGSN_3DIGIT,
};
struct sgsn_ggsn_lookup {
int state;
struct sgsn_mm_ctx *mmctx;
/* APN string */
char apn_str[GSM_APN_LENGTH];
/* the original data */
struct msgb *orig_msg;
struct tlv_parsed tp;
/* for dealing with re-transmissions */
uint8_t nsapi;
uint8_t sapi;
uint8_t ti;
};
enum sgsn_ran_type {
/* GPRS/EDGE via Gb */
MM_CTX_T_GERAN_Gb,
/* UMTS via Iu */
MM_CTX_T_UTRAN_Iu,
#if 0
/* GPRS/EDGE via Iu, not supported */
MM_CTX_T_GERAN_Iu,
#endif
};
extern const struct value_string sgsn_ran_type_names[];
struct service_info {
uint8_t type;
uint16_t pdp_status;
};
struct ranap_ue_conn_ctx;
/* According to TS 03.60, Table 5: SGSN MM and PDP Contexts */
/* Extended by 3GPP TS 23.060, Table 6: SGSN MM and PDP Contexts */
struct sgsn_mm_ctx {
struct llist_head list;
enum sgsn_ran_type ran_type;
char imsi[GSM23003_IMSI_MAX_DIGITS+1];
struct osmo_fsm_inst *gmm_fsm;
uint32_t p_tmsi;
uint32_t p_tmsi_old; /* old P-TMSI before new is confirmed */
uint32_t p_tmsi_sig;
char imei[GSM23003_IMEISV_NUM_DIGITS+1];
/* Opt: Software Version Numbber / TS 23.195 */
char msisdn[GSM_EXTENSION_LENGTH];
struct osmo_routing_area_id ra;
struct {
uint16_t cell_id; /* Gb only */
uint32_t cell_id_age; /* Gb only */
uint8_t radio_prio_sms;
/* Additional bits not present in the GSM TS */
uint16_t nsei;
uint16_t bvci;
struct gprs_llc_llme *llme;
uint32_t tlli;
uint32_t tlli_new;
/* TS 23.060 6.1.1 Mobility Management States (A/Gb mode) */
struct osmo_fsm_inst *mm_state_fsm;
} gb;
struct {
int new_key;
uint16_t sac; /* Iu: Service Area Code */
uint32_t sac_age; /* Iu: Service Area Code age */
/* CSG ID */
/* CSG Membership */
/* Access Mode */
/* Seelected CN Operator ID (TS 23.251) */
/* CSG Subscription Data */
/* LIPA Allowed */
/* Voice Support Match Indicator */
struct ranap_ue_conn_ctx *ue_ctx;
struct service_info service;
/* TS 23.060 6.1.2 Mobility Management States (Iu mode) */
struct osmo_fsm_inst *mm_state_fsm;
} iu;
struct {
struct osmo_fsm_inst *fsm;
/* when a second attach req arrives while in this procedure,
* the fsm needs to compare it against old to decide what to do */
struct msgb *attach_req;
uint32_t id_type;
unsigned int auth_reattempt; /* tracking UMTS resync auth attempts */
} gmm_att_req;
/* VLR number */
uint32_t new_sgsn_addr;
/* Authentication Triplet */
struct gsm_auth_tuple auth_triplet;
/* Kc */
/* Iu: CK, IK, KSI */
/* CKSN */
enum gprs_ciph_algo ciph_algo;
uint8_t ue_cipher_mask;
/* Auth & Ciphering Request reference from 3GPP TS 24.008 § 10.5.5.19: */
uint8_t ac_ref_nr_used;
struct {
uint8_t len;
uint8_t buf[50]; /* GSM 04.08 10.5.5.12a, extended in TS 24.008 */
} ms_radio_access_capa;
/* Supported Codecs (SRVCC) */
struct {
uint8_t len;
uint8_t buf[8]; /* GSM 04.08 10.5.5.12, extended in TS 24.008 */
} ms_network_capa;
/* UE Netowrk Capability (E-UTRAN) */
uint16_t drx_parms;
/* Active Time value for PSM */
int mnrg; /* MS reported to HLR? */
int ngaf; /* MS reported to MSC/VLR? */
int ppf; /* paging for GPRS + non-GPRS? */
/* Subscribed Charging Characteristics */
/* Trace Reference */
/* Trace Type */
/* Trigger ID */
/* OMC Identity */
/* SMS Parameters */
int recovery;
/* Access Restriction */
/* GPRS CSI (CAMEL) */
/* MG-CSI (CAMEL) */
/* Subscribed UE-AMBR */
/* UE-AMBR */
/* APN Subscribed */
struct llist_head pdp_list;
struct rate_ctr_group *ctrg;
struct osmo_timer_list timer;
unsigned int T; /* Txxxx number */
unsigned int num_T_exp; /* number of consecutive T expirations */
enum gprs_t3350_mode t3350_mode;
uint8_t t3370_id_type;
uint8_t pending_req; /* the request's message type */
/* TODO: There isn't much semantic difference between t3350_mode
* (refers to the timer) and pending_req (refers to the procedure),
* where mm->T == 3350 => mm->t3350_mode == f(mm->pending_req). Check
* whether one of them can be dropped. */
enum sgsn_auth_state auth_state;
enum osmo_sub_auth_type sec_ctx;
/* the string representation of the current hlr */
char hlr[GSM_EXTENSION_LENGTH];
/* the current GGSN look-up operation */
struct sgsn_ggsn_lookup *ggsn_lookup;
struct gprs_subscr *subscr;
};
static inline bool sgsn_mm_ctx_is_authenticated(struct sgsn_mm_ctx *ctx)
{
switch (ctx->sec_ctx) {
case OSMO_AUTH_TYPE_GSM:
case OSMO_AUTH_TYPE_UMTS:
return true;
default:
return false;
}
}
#define LOGMMCTXP(level, mm, fmt, args...) \
LOGP(DMM, level, "MM(%s/%08x) " fmt, (mm) ? (mm)->imsi : "---", \
(mm) ? (mm)->p_tmsi : GSM_RESERVED_TMSI, ## args)
#ifdef BUILD_IU
#define LOGIUP(ue, level, fmt, args...) \
LOGP(DMM, level, "UE(0x%x){%s} " fmt, (ue) ? (ue)->conn_id : 0xffffffff, \
(ue) ? osmo_rai_name(&(ue)->ra_id) : "", ## args)
#else
#define LOGIUP(ue, level, fmt, args...) \
LOGP(DMM, level, "UE(%p){NOTSUPPORTED} " fmt, ue, ## args)
#endif
#define LOGGBP(llme, category, level, fmt, args...) \
LOGP(category, level, "LLME(%08x/%08x){%s} " fmt, (llme)->old_tlli, \
(llme)->tlli, get_value_string_or_null(gprs_llc_llme_state_names, (llme)->state), ## args);
#define LOGGBIUP(llme, msg, level, fmt, args...) \
do { \
struct ranap_ue_conn_ctx * _ue; \
if (llme) { \
LOGGBP(llme, DMM, level, fmt, ## args); \
} else if ((msg) && (_ue = MSG_IU_UE_CTX(msg))) { \
LOGIUP(_ue, level, fmt, ## args); \
} else { OSMO_ASSERT(0); } \
} while (0)
/* look-up a SGSN MM context based on TLLI + RAI */
struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
const struct osmo_routing_area_id *raid);
struct sgsn_mm_ctx *sgsn_mm_ctx_by_ptmsi(uint32_t tmsi);
struct sgsn_mm_ctx *sgsn_mm_ctx_by_imsi(const char *imsi);
struct sgsn_mm_ctx *sgsn_mm_ctx_by_ue_ctx(const void *uectx);
struct sgsn_mm_ctx *sgsn_mm_ctx_by_llme(const struct gprs_llc_llme *llme);
/* look-up by matching TLLI and P-TMSI (think twice before using this) */
struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli_and_ptmsi(uint32_t tlli,
const struct osmo_routing_area_id *raid);
/* Allocate a new SGSN MM context */
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_gb(uint32_t tlli,
const struct osmo_routing_area_id *raid);
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_iu(void *uectx);
void sgsn_mm_ctx_cleanup_free(struct sgsn_mm_ctx *ctx);
struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,
struct tlv_parsed *tp,
enum gsm48_gsm_cause *gsm_cause,
char *apn_str);
/* look up PDP context by MM context and NSAPI */
struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_nsapi(const struct sgsn_mm_ctx *mm,
uint8_t nsapi);
/* look up PDP context by MM context and transaction ID */
struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm,
uint8_t tid);
bool sgsn_mm_ctx_is_r99(const struct sgsn_mm_ctx *mm);
uint32_t sgsn_alloc_ptmsi(void);
/* Called on subscriber data updates */
void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx);
#ifdef BUILD_IU
struct RANAP_Cause;
void sgsn_mm_ctx_iu_activate_rabs(struct sgsn_mm_ctx *ctx);
void sgsn_mm_ctx_iu_ranap_release_free(struct sgsn_mm_ctx *ctx,
const struct RANAP_Cause *cause);
void sgsn_mm_ctx_iu_ranap_free(struct sgsn_mm_ctx *ctx);
#endif /* ifdef BUILD_IU */

View File

@@ -0,0 +1,105 @@
#pragma once
#include "config.h"
#include <stdint.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/crypt/gprs_cipher.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/crypt/auth.h>
#include <osmocom/sgsn/apn.h>
#include <osmocom/sgsn/gprs_subscriber.h>
struct sgsn_mm_ctx;
struct sgsn_ggsn_ctx;
enum gprs_pdp_ctx {
PDP_CTR_PKTS_UDATA_IN,
PDP_CTR_PKTS_UDATA_OUT,
PDP_CTR_BYTES_UDATA_IN,
PDP_CTR_BYTES_UDATA_OUT,
};
enum pdp_ctx_state {
PDP_STATE_NONE,
PDP_STATE_CR_REQ,
PDP_STATE_CR_CONF,
/* 04.08 / Figure 6.2 / 6.1.2.2 */
PDP_STATE_INACT_PEND,
PDP_STATE_INACTIVE = PDP_STATE_NONE,
};
enum pdp_type {
PDP_TYPE_NONE,
PDP_TYPE_ETSI_PPP,
PDP_TYPE_IANA_IPv4,
PDP_TYPE_IANA_IPv6,
};
struct sgsn_pdp_ctx {
struct llist_head list; /* list_head for mmctx->pdp_list */
struct llist_head g_list; /* list_head for global list */
struct sgsn_mm_ctx *mm; /* back pointer to MM CTX */
int destroy_ggsn; /* destroy it on destruction */
struct sgsn_ggsn_ctx *ggsn; /* which GGSN serves this PDP */
struct llist_head ggsn_list; /* list_head for ggsn->pdp_list */
struct rate_ctr_group *ctrg;
//unsigned int id;
struct pdp_t *lib; /* pointer to libgtp PDP ctx */
enum pdp_ctx_state state;
enum pdp_type type;
uint32_t address;
char *apn_subscribed;
//char *apn_used;
uint16_t nsapi; /* SNDCP */
uint16_t sapi; /* LLC */
uint8_t ti; /* transaction identifier */
int vplmn_allowed;
uint32_t qos_profile_subscr;
//uint32_t qos_profile_req;
//uint32_t qos_profile_neg;
uint8_t radio_prio;
//uint32_t charging_id;
bool ue_pdp_active; /* PDP Context is active for this NSAPI? */
/* Keeps original SGSN local TEID when lib->teid_own is updated with
* RNC's TEID upon use of Direct Tunnel feature: */
uint32_t sgsn_teid_own;
struct osmo_timer_list timer;
unsigned int T; /* Txxxx number */
unsigned int num_T_exp; /* number of consecutive T expirations */
struct osmo_timer_list cdr_timer; /* CDR record wird timer */
struct timespec cdr_start; /* The start of the CDR */
uint64_t cdr_bytes_in;
uint64_t cdr_bytes_out;
uint32_t cdr_charging_id;
};
#define LOGPDPCTXP(level, pdp, fmt, args...) \
LOGP(DGPRS, level, "PDP(%s/%u) " \
fmt, (pdp)->mm ? (pdp)->mm->imsi : "---", (pdp)->ti, ## args)
struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
struct sgsn_ggsn_ctx *ggsn,
uint8_t nsapi);
void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp);
void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp);
#ifdef BUILD_IU
int sgsn_pdp_ctx_iu_rab_activate(struct sgsn_pdp_ctx *pdp, uint8_t rab_id);
int sgsn_pdp_ctx_iu_rab_deactivate(struct sgsn_pdp_ctx *pdp, uint8_t rab_id);
#endif /* ifdef BUILD_IU */
char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len, bool return_ipv6);

View File

@@ -0,0 +1,46 @@
/* SCCP Handling */
/* (C) 2025 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#pragma once
#include <stdint.h>
#include <osmocom/sigtran/sccp_sap.h>
struct sgsn_instance;
struct ranap_ue_conn_ctx;
struct sgsn_sccp_user_iups {
struct sgsn_instance *sgsn; /* backpointer */
struct osmo_sccp_instance *sccp; /* backpointer */
struct osmo_sccp_user *scu; /* IuPS */
struct osmo_sccp_addr local_sccp_addr;
struct llist_head ue_conn_ctx_list; /* list of "struct ranap_ue_conn_ctx" */
struct llist_head ue_conn_sccp_addr_list; /* list of "struct iu_new_ctx_entry" */
};
struct sgsn_sccp_user_iups *sgsn_scu_iups_inst_alloc(struct sgsn_instance *sgsn, struct osmo_sccp_instance *sccp);
void sgsn_scu_iups_free(struct sgsn_sccp_user_iups *scu_iups);
int sgsn_scu_iups_tx_data_req(struct sgsn_sccp_user_iups *scu_iups, uint32_t conn_id, struct msgb *ranap_msg);
struct ranap_ue_conn_ctx *sgsn_scu_iups_ue_conn_ctx_find(struct sgsn_sccp_user_iups *scu_iups, uint32_t conn_id);
int sgsn_sccp_init(struct sgsn_instance *sgsn);
void sgsn_sccp_release(struct sgsn_instance *sgsn);

View File

@@ -1,26 +1,36 @@
#ifndef _SGSN_H
#define _SGSN_H
#include "config.h"
#include <osmocom/core/msgb.h>
#include <osmocom/core/select.h>
#include <osmocom/core/stat_item.h>
#include <osmocom/crypt/gprs_cipher.h>
#include <osmocom/gprs/gprs_ns.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/gprs/gprs_ns2.h>
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/sgsn/auth.h>
#include <osmocom/sgsn/gtp_mme.h>
#include <osmocom/gsm/oap_client.h>
#include <osmocom/gsupclient/gsup_client.h>
#include <osmocom/sgsn/common.h>
#include "../../bscconfig.h"
#if BUILD_IU
#include <osmocom/ranap/iu_client.h>
#include <osmocom/sigtran/sccp_sap.h>
#include <osmocom/sgsn/iu_client.h>
#endif
#include <ares.h>
#include <gtp.h>
#include <osmocom/gtp/gtp.h>
struct hostent;
#define SGSN_ERROR_CAUSE_NONE (-1)
/* This rac will be used internally. RAC with 0xff will be rejected */
#define OSMO_RESERVED_RAC 0xff
enum sgsn_auth_policy {
SGSN_AUTH_POLICY_OPEN,
SGSN_AUTH_POLICY_CLOSED,
@@ -69,10 +79,12 @@ struct sgsn_config {
struct sockaddr_in gtp_listenaddr;
/* misc */
struct gprs_ns_inst *nsi;
struct gprs_ns2_inst *nsi;
char *crypt_cipher_plugin_path;
enum sgsn_auth_policy auth_policy;
enum gprs_ciph_algo cipher;
uint8_t gea_encryption_mask;
uint8_t uea_encryption_mask;
struct llist_head imsi_acl;
struct sockaddr_in gsup_server_addr;
@@ -88,6 +100,7 @@ struct sgsn_config {
/* Timer defintions */
struct osmo_tdef *T_defs;
struct osmo_tdef *T_defs_gtp;
int dynamic_lookup;
@@ -130,8 +143,6 @@ struct sgsn_instance {
struct osmo_fd gtp_fd0;
struct osmo_fd gtp_fd1c;
struct osmo_fd gtp_fd1u;
/* Timer for libGTP */
struct osmo_timer_list gtp_timer;
/* GSN instance for libgtp */
struct gsn_t *gsn;
/* Subscriber */
@@ -145,10 +156,55 @@ struct sgsn_instance {
ares_channel ares_channel;
struct ares_addr_node *ares_servers;
/* Routing areas */
struct sgsn_ra_global *routing_area;
struct rate_ctr_group *rate_ctrs;
struct osmo_stat_item_group *statg;
struct llist_head apn_list; /* list of struct sgsn_apn_ctx */
struct llist_head ggsn_list; /* list of struct sgsn_ggsn_ctx */
struct llist_head mme_list; /* list of struct sgsn_mme_ctx */
struct llist_head mm_list; /* list of struct sgsn_mm_ctx */
struct llist_head pdp_list; /* list of struct sgsn_pdp_ctx */
#if BUILD_IU
struct llist_head rnc_list; /* list of struct ranap_iu_rnc */
#endif /* if BUILD_IU */
struct ctrl_handle *ctrlh;
#if BUILD_IU
/* SCCP (Iu) */
struct {
struct osmo_sccp_instance *sccp;
struct sgsn_sccp_user_iups *scu_iups;
} sccp;
#endif /* if BUILD_IU */
};
extern struct osmo_tdef sgsn_T_defs[];
extern struct sgsn_instance *sgsn;
extern void *tall_sgsn_ctx;
enum {
SGSN_STAT_IU_PEERS_TOTAL,
SGSN_STAT_IU_PEERS_ACTIVE,
};
static inline void sgsn_stat_inc(unsigned int idx, int32_t value)
{
osmo_stat_item_inc(osmo_stat_item_group_get_item(sgsn->statg, idx), value);
}
static inline void sgsn_stat_dec(unsigned int idx, int32_t value)
{
osmo_stat_item_dec(osmo_stat_item_group_get_item(sgsn->statg, idx), value);
}
/*
* ctrl interface related work (sgsn_ctrl.c)
*/
int sgsn_ctrl_cmds_install(void);
/* sgsn_vty.c */
@@ -157,39 +213,13 @@ int sgsn_parse_config(const char *config_file);
char *sgsn_gtp_ntoa(struct ul16_t *ul);
/* sgsn.c */
/* Main input function for Gb proxy */
int sgsn_rcvmsg(struct msgb *msg, struct gprs_nsvc *nsvc, uint16_t ns_bvci);
/* sgsn_libgtp.c */
struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
struct sgsn_mm_ctx *mmctx,
uint16_t nsapi,
struct tlv_parsed *tp);
int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx);
void sgsn_pdp_upd_gtp_u(struct sgsn_pdp_ctx *pdp, void *addr, size_t alen);
void sgsn_ggsn_echo_req(struct sgsn_ggsn_ctx *ggc);
int send_act_pdp_cont_acc(struct sgsn_pdp_ctx *pctx);
/* gprs_sndcp.c */
/* Entry point for the SNSM-ACTIVATE.indication */
int sndcp_sm_activate_ind(struct gprs_llc_lle *lle, uint8_t nsapi);
/* Entry point for the SNSM-DEACTIVATE.indication */
int sndcp_sm_deactivate_ind(struct gprs_llc_lle *lle, uint8_t nsapi);
/* Called by SNDCP when it has received/re-assembled a N-PDU */
int sgsn_rx_sndcp_ud_ind(struct gprs_ra_id *ra_id, int32_t tlli, uint8_t nsapi,
struct msgb *msg, uint32_t npdu_len, uint8_t *npdu);
int sndcp_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi,
void *mmcontext);
int sndcp_llunitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
uint8_t *hdr, uint16_t len);
struct sgsn_instance *sgsn_instance_alloc(void *talloc_ctx);
int sgsn_inst_init(struct sgsn_instance *sgsn);
/*
* CDR related functionality
*/
int sgsn_cdr_init(struct sgsn_instance *sgsn);
void sgsn_cdr_release(struct sgsn_instance *sgsn);
/*

View File

@@ -0,0 +1,6 @@
#pragma once
struct sgsn_mme_ctx;
int sgsn_rim_rx_from_gb(struct osmo_bssgp_prim *bp, struct msgb *msg);
int sgsn_rim_rx_from_gtp(struct msgb *msg, struct bssgp_rim_routing_info *rim_routing_address);

View File

@@ -17,10 +17,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*! \page v42bis_page V.42bis modem data compression

View File

@@ -17,10 +17,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#if !defined(_SPANDSP_PRIVATE_V42BIS_H_)

View File

@@ -3,7 +3,7 @@
#include <osmocom/vty/command.h>
enum bsc_vty_node {
GBPROXY_NODE = _LAST_OSMOVTY_NODE + 1,
SGSN_NODE,
SGSN_NODE = _LAST_OSMOVTY_NODE + 1,
GTPHUB_NODE,
MME_NODE,
};

View File

@@ -1,74 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
#
# DESCRIPTION
#
# Check whether the given FLAG works with the current language's compiler
# or gives an error. (Warnings, however, are ignored)
#
# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
# success/failure.
#
# If EXTRA-FLAGS is defined, it is added to the current language's default
# flags (e.g. CFLAGS) when the check is done. The check is thus made with
# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
# force the compiler to issue an error when a bad flag is given.
#
# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
#
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
#
# LICENSE
#
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 4
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
[AS_VAR_SET(CACHEVAR,[yes])],
[AS_VAR_SET(CACHEVAR,[no])])
_AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
AS_VAR_IF(CACHEVAR,yes,
[m4_default([$2], :)],
[m4_default([$3], :)])
AS_VAR_POPDEF([CACHEVAR])dnl
])dnl AX_CHECK_COMPILE_FLAGS

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# (C) 2013 by Katerina Barone-Adesi <kat.obsc@gmail.com>
# This program is free software: you can redistribute it and/or modify
@@ -16,19 +16,15 @@
app_configs = {
"gbproxy": ["doc/examples/osmo-gbproxy/osmo-gbproxy.cfg",
"doc/examples/osmo-gbproxy/osmo-gbproxy-legacy.cfg"],
"sgsn": ["doc/examples/osmo-sgsn/osmo-sgsn.cfg"],
"sgsn": ["tests/osmo-sgsn.cfg"],
"gtphub": ["doc/examples/osmo-gtphub/osmo-gtphub-1iface.cfg"]
}
apps = [(4246, "src/gbproxy/osmo-gbproxy", "OsmoGbProxy", "gbproxy"),
(4245, "src/sgsn/osmo-sgsn", "OsmoSGSN", "sgsn"),
apps = [(4245, "src/sgsn/osmo-sgsn", "OsmoSGSN", "sgsn"),
(4253, "src/gtphub/osmo-gtphub", "OsmoGTPhub", "gtphub")
]
vty_command = ["./src/sgsn/osmo-sgsn", "-c",
"doc/examples/osmo-sgsn/osmo-sgsn.cfg"]
vty_command = ["./src/sgsn/osmo-sgsn", "-c", "tests/osmo-sgsn.cfg"]
vty_app = apps[1]
vty_app = apps[0]

View File

@@ -1,6 +1,5 @@
SUBDIRS = \
gprs \
sgsn \
gbproxy \
gtphub \
$(NULL)

View File

@@ -1,46 +0,0 @@
AM_CPPFLAGS = \
$(all_includes) \
-I$(top_srcdir)/include \
-I$(top_builddir) \
$(NULL)
AM_CFLAGS = \
-Wall \
-fno-strict-aliasing \
$(LIBOSMOCORE_CFLAGS) \
$(LIBOSMOGSM_CFLAGS) \
$(LIBOSMOVTY_CFLAGS) \
$(LIBOSMOCTRL_CFLAGS) \
$(LIBOSMOABIS_CFLAGS) \
$(LIBOSMOGB_CFLAGS) \
$(LIBOSMOGSUPCLIENT_CFLAGS) \
$(COVERAGE_CFLAGS) \
$(LIBGTP_CFLAGS) \
$(NULL)
bin_PROGRAMS = \
osmo-gbproxy \
$(NULL)
osmo_gbproxy_SOURCES = \
gb_proxy.c \
gb_proxy_main.c \
gb_proxy_vty.c \
gb_proxy_ctrl.c \
gb_proxy_patch.c \
gb_proxy_tlli.c \
gb_proxy_peer.c \
$(NULL)
osmo_gbproxy_LDADD = \
$(top_builddir)/src/gprs/gprs_gb_parse.o \
$(top_builddir)/src/gprs/gprs_llc_parse.o \
$(top_builddir)/src/gprs/crc24.o \
$(top_builddir)/src/gprs/gprs_utils.o \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOGSM_LIBS) \
$(LIBOSMOVTY_LIBS) \
$(LIBOSMOCTRL_LIBS) \
$(LIBOSMOGB_LIBS) \
$(LIBGTP_LIBS) \
-lrt \
$(NULL)

File diff suppressed because it is too large Load Diff

View File

@@ -1,98 +0,0 @@
/* Control Interface Implementation for the Gb-proxy */
/*
* (C) 2018 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
* All Rights Reserved
*
* Author: Daniel Willmann
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <osmocom/core/talloc.h>
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/gprs/gprs_ns.h>
#include <osmocom/ctrl/control_if.h>
#include <osmocom/ctrl/control_cmd.h>
#include <osmocom/sgsn/gb_proxy.h>
#include <osmocom/sgsn/debug.h>
extern vector ctrl_node_vec;
static int get_nsvc_state(struct ctrl_cmd *cmd, void *data)
{
struct gbproxy_config *cfg = data;
struct gprs_ns_inst *nsi = cfg->nsi;
struct gprs_nsvc *nsvc;
cmd->reply = talloc_strdup(cmd, "");
llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
if (nsvc == nsi->unknown_nsvc)
continue;
cmd->reply = gprs_nsvc_state_append(cmd->reply, nsvc);
}
return CTRL_CMD_REPLY;
}
CTRL_CMD_DEFINE_RO(nsvc_state, "nsvc-state");
static int get_gbproxy_state(struct ctrl_cmd *cmd, void *data)
{
struct gbproxy_config *cfg = data;
struct gbproxy_peer *peer;
cmd->reply = talloc_strdup(cmd, "");
llist_for_each_entry(peer, &cfg->bts_peers, list) {
struct gprs_ra_id raid;
gsm48_parse_ra(&raid, peer->ra);
cmd->reply = talloc_asprintf_append(cmd->reply, "%u,%u,%u,%u,%u,%u,%s\n",
peer->nsei, peer->bvci,
raid.mcc, raid.mnc,
raid.lac, raid.rac,
peer->blocked ? "BLOCKED" : "UNBLOCKED");
}
return CTRL_CMD_REPLY;
}
CTRL_CMD_DEFINE_RO(gbproxy_state, "gbproxy-state");
static int get_num_peers(struct ctrl_cmd *cmd, void *data)
{
struct gbproxy_config *cfg = data;
cmd->reply = talloc_strdup(cmd, "");
cmd->reply = talloc_asprintf_append(cmd->reply, "%u", llist_count(&cfg->bts_peers));
return CTRL_CMD_REPLY;
}
CTRL_CMD_DEFINE_RO(num_peers, "number-of-peers");
int gb_ctrl_cmds_install(void)
{
int rc = 0;
rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_nsvc_state);
rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_gbproxy_state);
rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_num_peers);
return rc;
}

View File

@@ -1,393 +0,0 @@
/* NS-over-IP proxy */
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
* (C) 2010 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
#include <signal.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <osmocom/core/application.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/select.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/stats.h>
#include <osmocom/gprs/gprs_ns.h>
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/sgsn/signal.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/vty.h>
#include <osmocom/sgsn/gb_proxy.h>
#include <osmocom/ctrl/control_vty.h>
#include <osmocom/ctrl/control_if.h>
#include <osmocom/ctrl/ports.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/telnet_interface.h>
#include <osmocom/vty/logging.h>
#include <osmocom/vty/stats.h>
#include <osmocom/vty/ports.h>
#include <osmocom/vty/misc.h>
#include "../../bscconfig.h"
#define _GNU_SOURCE
#include <getopt.h>
void *tall_sgsn_ctx;
const char *openbsc_copyright =
"Copyright (C) 2010 Harald Welte and On-Waves\r\n"
"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
"This is free software: you are free to change and redistribute it.\r\n"
"There is NO WARRANTY, to the extent permitted by law.\r\n";
#define CONFIG_FILE_DEFAULT "osmo-gbproxy.cfg"
#define CONFIG_FILE_LEGACY "osmo_gbproxy.cfg"
static char *config_file = NULL;
struct gbproxy_config *gbcfg;
static int daemonize = 0;
/* Pointer to the SGSN peer */
extern struct gbprox_peer *gbprox_peer_sgsn;
/* call-back function for the NS protocol */
static int proxy_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
struct msgb *msg, uint16_t bvci)
{
int rc = 0;
switch (event) {
case GPRS_NS_EVT_UNIT_DATA:
rc = gbprox_rcvmsg(gbcfg, msg, nsvc->nsei, bvci, nsvc->nsvci);
break;
default:
LOGP(DGPRS, LOGL_ERROR, "SGSN: Unknown event %u from NS\n", event);
if (msg)
msgb_free(msg);
rc = -EIO;
break;
}
return rc;
}
static void signal_handler(int signal)
{
fprintf(stdout, "signal %u received\n", signal);
switch (signal) {
case SIGINT:
case SIGTERM:
osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL);
sleep(1);
exit(0);
break;
case SIGABRT:
/* in case of abort, we want to obtain a talloc report
* and then return to the caller, who will abort the process */
case SIGUSR1:
talloc_report(tall_vty_ctx, stderr);
talloc_report_full(tall_sgsn_ctx, stderr);
break;
case SIGUSR2:
talloc_report_full(tall_vty_ctx, stderr);
break;
default:
break;
}
}
static void print_usage()
{
printf("Usage: bsc_hack\n");
}
static void print_help()
{
printf(" Some useful help...\n");
printf(" -h --help this text\n");
printf(" -d option --debug=DNS:DGPRS,0:0 enable debugging\n");
printf(" -D --daemonize Fork the process into a background daemon\n");
printf(" -c --config-file filename The config file to use [%s]\n", CONFIG_FILE_DEFAULT);
printf(" -s --disable-color\n");
printf(" -T --timestamp Prefix every log line with a timestamp\n");
printf(" -V --version. Print the version.\n");
printf(" -e --log-level number. Set a global loglevel.\n");
}
static void handle_options(int argc, char **argv)
{
while (1) {
int option_index = 0, c;
static struct option long_options[] = {
{ "help", 0, 0, 'h' },
{ "debug", 1, 0, 'd' },
{ "daemonize", 0, 0, 'D' },
{ "config-file", 1, 0, 'c' },
{ "disable-color", 0, 0, 's' },
{ "timestamp", 0, 0, 'T' },
{ "version", 0, 0, 'V' },
{ "log-level", 1, 0, 'e' },
{ 0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "hd:Dc:sTVe:",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'h':
print_usage();
print_help();
exit(0);
case 's':
log_set_use_color(osmo_stderr_target, 0);
break;
case 'd':
log_parse_category_mask(osmo_stderr_target, optarg);
break;
case 'D':
daemonize = 1;
break;
case 'c':
config_file = optarg;
break;
case 'T':
log_set_print_timestamp(osmo_stderr_target, 1);
break;
case 'e':
log_set_log_level(osmo_stderr_target, atoi(optarg));
break;
case 'V':
print_version(1);
exit(0);
break;
default:
break;
}
}
}
int gbproxy_vty_is_config_node(struct vty *vty, int node)
{
switch (node) {
/* add items that are not config */
case CONFIG_NODE:
return 0;
default:
return 1;
}
}
int gbproxy_vty_go_parent(struct vty *vty)
{
switch (vty->node) {
case GBPROXY_NODE:
default:
if (gbproxy_vty_is_config_node(vty, vty->node))
vty->node = CONFIG_NODE;
else
vty->node = ENABLE_NODE;
vty->index = NULL;
}
return vty->node;
}
static struct vty_app_info vty_info = {
.name = "OsmoGbProxy",
.version = PACKAGE_VERSION,
.go_parent_cb = gbproxy_vty_go_parent,
.is_config_node = gbproxy_vty_is_config_node,
};
/* default categories */
static struct log_info_cat gprs_categories[] = {
[DGPRS] = {
.name = "DGPRS",
.description = "GPRS Packet Service",
.enabled = 1, .loglevel = LOGL_DEBUG,
},
[DNS] = {
.name = "DNS",
.description = "GPRS Network Service (NS)",
.enabled = 1, .loglevel = LOGL_INFO,
},
[DBSSGP] = {
.name = "DBSSGP",
.description = "GPRS BSS Gateway Protocol (BSSGP)",
.enabled = 1, .loglevel = LOGL_DEBUG,
},
};
static const struct log_info gprs_log_info = {
.filter_fn = gprs_log_filter_fn,
.cat = gprs_categories,
.num_cat = ARRAY_SIZE(gprs_categories),
};
static bool file_exists(const char *path)
{
struct stat sb;
return stat(path, &sb) ? false : true;
}
int main(int argc, char **argv)
{
int rc;
struct ctrl_handle *ctrl;
tall_sgsn_ctx = talloc_named_const(NULL, 0, "nsip_proxy");
msgb_talloc_ctx_init(tall_sgsn_ctx, 0);
vty_info.tall_ctx = tall_sgsn_ctx;
signal(SIGINT, &signal_handler);
signal(SIGTERM, &signal_handler);
signal(SIGABRT, &signal_handler);
signal(SIGUSR1, &signal_handler);
signal(SIGUSR2, &signal_handler);
osmo_init_ignore_signals();
osmo_init_logging2(tall_sgsn_ctx, &gprs_log_info);
vty_info.copyright = openbsc_copyright;
vty_init(&vty_info);
logging_vty_add_cmds();
osmo_talloc_vty_add_cmds();
osmo_stats_vty_add_cmds();
gbproxy_vty_init();
handle_options(argc, argv);
/* Backwards compatibility: for years, the default config file name was
* osmo_gbproxy.cfg. All other Osmocom programs use osmo-*.cfg with a
* dash. To be able to use the new config file name without breaking
* previous setups that might rely on the legacy default config file
* name, we need to look for the old config file if no -c option was
* passed AND no file exists with the new default file name. */
if (!config_file) {
/* No -c option was passed */
if (file_exists(CONFIG_FILE_LEGACY)
&& !file_exists(CONFIG_FILE_DEFAULT))
config_file = CONFIG_FILE_LEGACY;
else
config_file = CONFIG_FILE_DEFAULT;
}
rate_ctr_init(tall_sgsn_ctx);
osmo_stats_init(tall_sgsn_ctx);
bssgp_nsi = gprs_ns_instantiate(&proxy_ns_cb, tall_sgsn_ctx);
if (!bssgp_nsi) {
LOGP(DGPRS, LOGL_ERROR, "Unable to instantiate NS\n");
exit(1);
}
gbcfg = talloc_zero(tall_sgsn_ctx, struct gbproxy_config);
if (!gbcfg) {
LOGP(DGPRS, LOGL_FATAL, "Unable to allocate config\n");
exit(1);
}
gbproxy_init_config(gbcfg);
gbcfg->nsi = bssgp_nsi;
gprs_ns_vty_init(bssgp_nsi);
gprs_ns_set_log_ss(DNS);
bssgp_set_log_ss(DBSSGP);
osmo_signal_register_handler(SS_L_NS, &gbprox_signal, gbcfg);
rc = gbproxy_parse_config(config_file, gbcfg);
if (rc < 0) {
LOGP(DGPRS, LOGL_FATAL, "Cannot parse config file '%s'\n", config_file);
exit(2);
}
/* start telnet after reading config for vty_get_bind_addr() */
rc = telnet_init_dynif(tall_sgsn_ctx, NULL,
vty_get_bind_addr(), OSMO_VTY_PORT_GBPROXY);
if (rc < 0)
exit(1);
/* Start control interface after getting config for
* ctrl_vty_get_bind_addr() */
ctrl = ctrl_interface_setup_dynip(gbcfg, ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_GBPROXY, NULL);
if (!ctrl) {
LOGP(DGPRS, LOGL_FATAL, "Failed to create CTRL interface.\n");
exit(1);
}
if (gb_ctrl_cmds_install() != 0) {
LOGP(DGPRS, LOGL_FATAL, "Failed to install CTRL commands.\n");
exit(1);
}
if (!gprs_nsvc_by_nsei(gbcfg->nsi, gbcfg->nsip_sgsn_nsei)) {
LOGP(DGPRS, LOGL_FATAL, "You cannot proxy to NSEI %u "
"without creating that NSEI before\n",
gbcfg->nsip_sgsn_nsei);
exit(2);
}
rc = gprs_ns_nsip_listen(bssgp_nsi);
if (rc < 0) {
LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen on NSIP socket\n");
exit(2);
}
rc = gprs_ns_frgre_listen(bssgp_nsi);
if (rc < 0) {
LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen GRE "
"socket. Do you have CAP_NET_RAW?\n");
exit(2);
}
if (daemonize) {
rc = osmo_daemonize();
if (rc < 0) {
perror("Error during daemonize");
exit(1);
}
}
/* Reset all the persistent NS-VCs that we've read from the config */
gbprox_reset_persistent_nsvcs(bssgp_nsi);
while (1) {
rc = osmo_select_main(0);
if (rc < 0)
exit(3);
}
exit(0);
}

View File

@@ -1,465 +0,0 @@
/* Gb-proxy message patching */
/* (C) 2014 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <osmocom/sgsn/gb_proxy.h>
#include <osmocom/sgsn/gprs_utils.h>
#include <osmocom/sgsn/gprs_gb_parse.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/gprs/protocol/gsm_08_18.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/gsm/apn.h>
extern void *tall_sgsn_ctx;
/* patch RA identifier in place */
static void gbproxy_patch_raid(struct gsm48_ra_id *raid_enc, struct gbproxy_peer *peer,
int to_bss, const char *log_text)
{
struct gbproxy_patch_state *state = &peer->patch_state;
struct osmo_plmn_id old_plmn;
struct gprs_ra_id raid;
enum gbproxy_peer_ctr counter =
to_bss ?
GBPROX_PEER_CTR_RAID_PATCHED_SGSN :
GBPROX_PEER_CTR_RAID_PATCHED_BSS;
if (!state->local_plmn.mcc || !state->local_plmn.mnc)
return;
gsm48_parse_ra(&raid, (uint8_t *)raid_enc);
old_plmn = (struct osmo_plmn_id){
.mcc = raid.mcc,
.mnc = raid.mnc,
.mnc_3_digits = raid.mnc_3_digits,
};
if (!to_bss) {
/* BSS -> SGSN */
if (state->local_plmn.mcc)
raid.mcc = peer->cfg->core_plmn.mcc;
if (state->local_plmn.mnc) {
raid.mnc = peer->cfg->core_plmn.mnc;
raid.mnc_3_digits = peer->cfg->core_plmn.mnc_3_digits;
}
} else {
/* SGSN -> BSS */
if (state->local_plmn.mcc)
raid.mcc = state->local_plmn.mcc;
if (state->local_plmn.mnc) {
raid.mnc = state->local_plmn.mnc;
raid.mnc_3_digits = state->local_plmn.mnc_3_digits;
}
}
LOGP(DGPRS, LOGL_DEBUG,
"Patching %s to %s: "
"%s-%d-%d -> %s\n",
log_text,
to_bss ? "BSS" : "SGSN",
osmo_plmn_name(&old_plmn), raid.lac, raid.rac,
osmo_rai_name(&raid));
gsm48_encode_ra(raid_enc, &raid);
rate_ctr_inc(&peer->ctrg->ctr[counter]);
}
static void gbproxy_patch_apn_ie(struct msgb *msg,
uint8_t *apn_ie, size_t apn_ie_len,
struct gbproxy_peer *peer,
size_t *new_apn_ie_len, const char *log_text)
{
struct apn_ie_hdr {
uint8_t iei;
uint8_t apn_len;
uint8_t apn[0];
} *hdr = (void *)apn_ie;
size_t apn_len = hdr->apn_len;
uint8_t *apn = hdr->apn;
OSMO_ASSERT(apn_ie_len == apn_len + sizeof(struct apn_ie_hdr));
OSMO_ASSERT(apn_ie_len > 2 && apn_ie_len <= 102);
if (peer->cfg->core_apn_size == 0) {
char str1[110];
/* Remove the IE */
LOGP(DGPRS, LOGL_DEBUG,
"Patching %s to SGSN: Removing APN '%s'\n",
log_text,
osmo_apn_to_str(str1, apn, apn_len));
*new_apn_ie_len = 0;
msgb_resize_area(msg, apn_ie, apn_ie_len, 0);
} else {
/* Resize the IE */
char str1[110];
char str2[110];
OSMO_ASSERT(peer->cfg->core_apn_size <= 100);
LOGP(DGPRS, LOGL_DEBUG,
"Patching %s to SGSN: "
"Replacing APN '%s' -> '%s'\n",
log_text,
osmo_apn_to_str(str1, apn, apn_len),
osmo_apn_to_str(str2, peer->cfg->core_apn,
peer->cfg->core_apn_size));
*new_apn_ie_len = peer->cfg->core_apn_size + 2;
msgb_resize_area(msg, apn, apn_len, peer->cfg->core_apn_size);
memcpy(apn, peer->cfg->core_apn, peer->cfg->core_apn_size);
hdr->apn_len = peer->cfg->core_apn_size;
}
rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_APN_PATCHED]);
}
static int gbproxy_patch_tlli(uint8_t *tlli_enc,
struct gbproxy_peer *peer,
uint32_t new_tlli,
int to_bss, const char *log_text)
{
uint32_t tlli_be;
uint32_t tlli;
enum gbproxy_peer_ctr counter =
to_bss ?
GBPROX_PEER_CTR_TLLI_PATCHED_SGSN :
GBPROX_PEER_CTR_TLLI_PATCHED_BSS;
memcpy(&tlli_be, tlli_enc, sizeof(tlli_be));
tlli = ntohl(tlli_be);
if (tlli == new_tlli)
return 0;
LOGP(DGPRS, LOGL_DEBUG,
"Patching %ss: "
"Replacing %08x -> %08x\n",
log_text, tlli, new_tlli);
tlli_be = htonl(new_tlli);
memcpy(tlli_enc, &tlli_be, sizeof(tlli_be));
rate_ctr_inc(&peer->ctrg->ctr[counter]);
return 1;
}
static int gbproxy_patch_ptmsi(uint8_t *ptmsi_enc,
struct gbproxy_peer *peer,
uint32_t new_ptmsi,
int to_bss, const char *log_text)
{
uint32_t ptmsi_be;
uint32_t ptmsi;
enum gbproxy_peer_ctr counter =
to_bss ?
GBPROX_PEER_CTR_PTMSI_PATCHED_SGSN :
GBPROX_PEER_CTR_PTMSI_PATCHED_BSS;
memcpy(&ptmsi_be, ptmsi_enc, sizeof(ptmsi_be));
ptmsi = ntohl(ptmsi_be);
if (ptmsi == new_ptmsi)
return 0;
LOGP(DGPRS, LOGL_DEBUG,
"Patching %ss: "
"Replacing %08x -> %08x\n",
log_text, ptmsi, new_ptmsi);
ptmsi_be = htonl(new_ptmsi);
memcpy(ptmsi_enc, &ptmsi_be, sizeof(ptmsi_be));
rate_ctr_inc(&peer->ctrg->ctr[counter]);
return 1;
}
int gbproxy_patch_llc(struct msgb *msg, uint8_t *llc, size_t llc_len,
struct gbproxy_peer *peer,
struct gbproxy_link_info *link_info, int *len_change,
struct gprs_gb_parse_context *parse_ctx)
{
struct gprs_llc_hdr_parsed *ghp = &parse_ctx->llc_hdr_parsed;
int have_patched = 0;
int fcs;
struct gbproxy_config *cfg = peer->cfg;
if (parse_ctx->ptmsi_enc && link_info &&
!parse_ctx->old_raid_is_foreign && peer->cfg->patch_ptmsi) {
uint32_t ptmsi;
if (parse_ctx->to_bss)
ptmsi = link_info->tlli.ptmsi;
else
ptmsi = link_info->sgsn_tlli.ptmsi;
if (ptmsi != GSM_RESERVED_TMSI) {
if (gbproxy_patch_ptmsi(parse_ctx->ptmsi_enc, peer,
ptmsi, parse_ctx->to_bss, "P-TMSI"))
have_patched = 1;
} else {
/* TODO: invalidate old RAI if present (see below) */
}
}
if (parse_ctx->new_ptmsi_enc && link_info && cfg->patch_ptmsi) {
uint32_t ptmsi;
if (parse_ctx->to_bss)
ptmsi = link_info->tlli.ptmsi;
else
ptmsi = link_info->sgsn_tlli.ptmsi;
OSMO_ASSERT(ptmsi);
if (gbproxy_patch_ptmsi(parse_ctx->new_ptmsi_enc, peer,
ptmsi, parse_ctx->to_bss, "new P-TMSI"))
have_patched = 1;
}
if (parse_ctx->raid_enc) {
gbproxy_patch_raid((struct gsm48_ra_id *)parse_ctx->raid_enc, peer, parse_ctx->to_bss,
parse_ctx->llc_msg_name);
have_patched = 1;
}
if (parse_ctx->old_raid_enc && !parse_ctx->old_raid_is_foreign) {
/* TODO: Patch to invalid if P-TMSI unknown. */
gbproxy_patch_raid((struct gsm48_ra_id *)parse_ctx->old_raid_enc, peer, parse_ctx->to_bss,
parse_ctx->llc_msg_name);
have_patched = 1;
}
if (parse_ctx->apn_ie &&
cfg->core_apn &&
!parse_ctx->to_bss &&
gbproxy_imsi_matches(cfg, GBPROX_MATCH_PATCHING, link_info) &&
cfg->core_apn) {
size_t new_len;
gbproxy_patch_apn_ie(msg,
parse_ctx->apn_ie, parse_ctx->apn_ie_len,
peer, &new_len, parse_ctx->llc_msg_name);
*len_change += (int)new_len - (int)parse_ctx->apn_ie_len;
have_patched = 1;
}
if (have_patched) {
llc_len += *len_change;
ghp->crc_length += *len_change;
/* Fix FCS */
fcs = gprs_llc_fcs(llc, ghp->crc_length);
LOGP(DLLC, LOGL_DEBUG, "Updated LLC message, CRC: %06x -> %06x\n",
ghp->fcs, fcs);
llc[llc_len - 3] = fcs & 0xff;
llc[llc_len - 2] = (fcs >> 8) & 0xff;
llc[llc_len - 1] = (fcs >> 16) & 0xff;
}
return have_patched;
}
/* patch BSSGP message to use core_plmn.mcc/mnc on the SGSN side */
void gbproxy_patch_bssgp(struct msgb *msg, uint8_t *bssgp, size_t bssgp_len,
struct gbproxy_peer *peer,
struct gbproxy_link_info *link_info, int *len_change,
struct gprs_gb_parse_context *parse_ctx)
{
const char *err_info = NULL;
int err_ctr = -1;
if (parse_ctx->bssgp_raid_enc)
gbproxy_patch_raid((struct gsm48_ra_id *)parse_ctx->bssgp_raid_enc, peer,
parse_ctx->to_bss, "BSSGP");
if (parse_ctx->need_decryption &&
(peer->cfg->patch_ptmsi || peer->cfg->core_apn)) {
/* Patching LLC messages has been requested
* explicitly, but the message (including the
* type) is encrypted, so we possibly fail to
* patch the LLC part of the message. */
err_ctr = GBPROX_PEER_CTR_PATCH_CRYPT_ERR;
err_info = "GMM message is encrypted";
goto patch_error;
}
if (!link_info && parse_ctx->tlli_enc && parse_ctx->to_bss) {
/* Happens with unknown (not cached) TLLI coming from
* the SGSN */
/* TODO: What shall be done with the message in this case? */
err_ctr = GBPROX_PEER_CTR_TLLI_UNKNOWN;
err_info = "TLLI sent by the SGSN is unknown";
goto patch_error;
}
if (!link_info)
return;
if (parse_ctx->tlli_enc && peer->cfg->patch_ptmsi) {
uint32_t tlli = gbproxy_map_tlli(parse_ctx->tlli,
link_info, parse_ctx->to_bss);
if (tlli) {
gbproxy_patch_tlli(parse_ctx->tlli_enc, peer, tlli,
parse_ctx->to_bss, "TLLI");
parse_ctx->tlli = tlli;
} else {
/* Internal error */
err_ctr = GBPROX_PEER_CTR_PATCH_ERR;
err_info = "Replacement TLLI is 0";
goto patch_error;
}
}
if (parse_ctx->bssgp_ptmsi_enc && peer->cfg->patch_ptmsi) {
uint32_t ptmsi;
if (parse_ctx->to_bss)
ptmsi = link_info->tlli.ptmsi;
else
ptmsi = link_info->sgsn_tlli.ptmsi;
if (ptmsi != GSM_RESERVED_TMSI)
gbproxy_patch_ptmsi(
parse_ctx->bssgp_ptmsi_enc, peer,
ptmsi, parse_ctx->to_bss, "BSSGP P-TMSI");
}
if (parse_ctx->llc) {
uint8_t *llc = parse_ctx->llc;
size_t llc_len = parse_ctx->llc_len;
int llc_len_change = 0;
gbproxy_patch_llc(msg, llc, llc_len, peer, link_info,
&llc_len_change, parse_ctx);
/* Note that the APN might have been resized here, but no
* pointer int the parse_ctx will refer to an adress after the
* APN. So it's possible to patch first and do the TLLI
* handling afterwards. */
if (llc_len_change) {
llc_len += llc_len_change;
/* Fix LLC IE len */
/* TODO: This is a kludge, but the a pointer to the
* start of the IE is not available here */
if (llc[-2] == BSSGP_IE_LLC_PDU && llc[-1] & 0x80) {
/* most probably a one byte length */
if (llc_len > 127) {
err_info = "Cannot increase size";
err_ctr = GBPROX_PEER_CTR_PATCH_ERR;
goto patch_error;
}
llc[-1] = llc_len | 0x80;
} else {
llc[-2] = (llc_len >> 8) & 0x7f;
llc[-1] = llc_len & 0xff;
}
*len_change += llc_len_change;
}
/* Note that the tp struct might contain invalid pointers here
* if the LLC field has changed its size */
parse_ctx->llc_len = llc_len;
}
return;
patch_error:
OSMO_ASSERT(err_ctr >= 0);
rate_ctr_inc(&peer->ctrg->ctr[err_ctr]);
LOGP(DGPRS, LOGL_ERROR,
"NSEI=%u(%s) failed to patch BSSGP message as requested: %s.\n",
msgb_nsei(msg), parse_ctx->to_bss ? "SGSN" : "BSS",
err_info);
}
void gbproxy_clear_patch_filter(struct gbproxy_match *match)
{
if (match->enable) {
regfree(&match->re_comp);
match->enable = false;
}
talloc_free(match->re_str);
match->re_str = NULL;
}
int gbproxy_set_patch_filter(struct gbproxy_match *match, const char *filter,
const char **err_msg)
{
static char err_buf[300];
int rc;
gbproxy_clear_patch_filter(match);
if (!filter)
return 0;
rc = regcomp(&match->re_comp, filter,
REG_EXTENDED | REG_NOSUB | REG_ICASE);
if (rc == 0) {
match->enable = true;
match->re_str = talloc_strdup(tall_sgsn_ctx, filter);
return 0;
}
if (err_msg) {
regerror(rc, &match->re_comp,
err_buf, sizeof(err_buf));
*err_msg = err_buf;
}
return -1;
}
int gbproxy_check_imsi(struct gbproxy_match *match,
const uint8_t *imsi, size_t imsi_len)
{
char mi_buf[200];
int rc;
if (!match->enable)
return 1;
rc = gprs_is_mi_imsi(imsi, imsi_len);
if (rc > 0)
rc = gsm48_mi_to_string(mi_buf, sizeof(mi_buf), imsi, imsi_len);
if (rc <= 0) {
LOGP(DGPRS, LOGL_NOTICE, "Invalid IMSI %s\n",
osmo_hexdump(imsi, imsi_len));
return -1;
}
LOGP(DGPRS, LOGL_DEBUG, "Checking IMSI '%s' (%d)\n", mi_buf, rc);
rc = regexec(&match->re_comp, mi_buf, 0, NULL, 0);
if (rc == REG_NOMATCH) {
LOGP(DGPRS, LOGL_INFO,
"IMSI '%s' doesn't match pattern '%s'\n",
mi_buf, match->re_str);
return 0;
}
return 1;
}

View File

@@ -1,240 +0,0 @@
/* Gb proxy peer handling */
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
* (C) 2010-2013 by On-Waves
* (C) 2013 by Holger Hans Peter Freyther
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <osmocom/sgsn/gb_proxy.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/gprs/protocol/gsm_08_18.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/stats.h>
#include <osmocom/core/talloc.h>
#include <osmocom/gsm/tlv.h>
#include <string.h>
extern void *tall_sgsn_ctx;
static const struct rate_ctr_desc peer_ctr_description[] = {
{ "blocked", "BVC Block " },
{ "unblocked", "BVC Unblock " },
{ "dropped", "BVC blocked, dropped packet " },
{ "inv-nsei", "NSEI mismatch " },
{ "tx-err", "NS Transmission error " },
{ "raid-mod:bss", "RAID patched (BSS )" },
{ "raid-mod:sgsn", "RAID patched (SGSN)" },
{ "apn-mod:sgsn", "APN patched " },
{ "tlli-mod:bss", "TLLI patched (BSS )" },
{ "tlli-mod:sgsn", "TLLI patched (SGSN)" },
{ "ptmsi-mod:bss", "P-TMSI patched (BSS )" },
{ "ptmsi-mod:sgsn","P-TMSI patched (SGSN)" },
{ "mod-crypt-err", "Patch error: encrypted " },
{ "mod-err", "Patch error: other " },
{ "attach-reqs", "Attach Request count " },
{ "attach-rejs", "Attach Reject count " },
{ "attach-acks", "Attach Accept count " },
{ "attach-cpls", "Attach Completed count " },
{ "ra-upd-reqs", "RoutingArea Update Request count" },
{ "ra-upd-rejs", "RoutingArea Update Reject count " },
{ "ra-upd-acks", "RoutingArea Update Accept count " },
{ "ra-upd-cpls", "RoutingArea Update Compltd count" },
{ "gmm-status", "GMM Status count (BSS)" },
{ "gmm-status", "GMM Status count (SGSN)" },
{ "detach-reqs", "Detach Request count " },
{ "detach-acks", "Detach Accept count " },
{ "pdp-act-reqs", "PDP Activation Request count " },
{ "pdp-act-rejs", "PDP Activation Reject count " },
{ "pdp-act-acks", "PDP Activation Accept count " },
{ "pdp-deact-reqs","PDP Deactivation Request count " },
{ "pdp-deact-acks","PDP Deactivation Accept count " },
{ "tlli-unknown", "TLLI from SGSN unknown " },
{ "tlli-cache", "TLLI cache size " },
};
osmo_static_assert(ARRAY_SIZE(peer_ctr_description) == GBPROX_PEER_CTR_LAST, everything_described);
static const struct rate_ctr_group_desc peer_ctrg_desc = {
.group_name_prefix = "gbproxy:peer",
.group_description = "GBProxy Peer Statistics",
.num_ctr = ARRAY_SIZE(peer_ctr_description),
.ctr_desc = peer_ctr_description,
.class_id = OSMO_STATS_CLASS_PEER,
};
/* Find the gbprox_peer by its BVCI */
struct gbproxy_peer *gbproxy_peer_by_bvci(struct gbproxy_config *cfg, uint16_t bvci)
{
struct gbproxy_peer *peer;
llist_for_each_entry(peer, &cfg->bts_peers, list) {
if (peer->bvci == bvci)
return peer;
}
return NULL;
}
/* Find the gbprox_peer by its NSEI */
struct gbproxy_peer *gbproxy_peer_by_nsei(struct gbproxy_config *cfg,
uint16_t nsei)
{
struct gbproxy_peer *peer;
llist_for_each_entry(peer, &cfg->bts_peers, list) {
if (peer->nsei == nsei)
return peer;
}
return NULL;
}
/* look-up a peer by its Routeing Area Identification (RAI) */
struct gbproxy_peer *gbproxy_peer_by_rai(struct gbproxy_config *cfg,
const uint8_t *ra)
{
struct gbproxy_peer *peer;
llist_for_each_entry(peer, &cfg->bts_peers, list) {
if (!memcmp(peer->ra, ra, 6))
return peer;
}
return NULL;
}
/* look-up a peer by its Location Area Identification (LAI) */
struct gbproxy_peer *gbproxy_peer_by_lai(struct gbproxy_config *cfg,
const uint8_t *la)
{
struct gbproxy_peer *peer;
llist_for_each_entry(peer, &cfg->bts_peers, list) {
if (!memcmp(peer->ra, la, 5))
return peer;
}
return NULL;
}
/* look-up a peer by its Location Area Code (LAC) */
struct gbproxy_peer *gbproxy_peer_by_lac(struct gbproxy_config *cfg,
const uint8_t *la)
{
struct gbproxy_peer *peer;
llist_for_each_entry(peer, &cfg->bts_peers, list) {
if (!memcmp(peer->ra + 3, la + 3, 2))
return peer;
}
return NULL;
}
struct gbproxy_peer *gbproxy_peer_by_bssgp_tlv(struct gbproxy_config *cfg,
struct tlv_parsed *tp)
{
if (TLVP_PRESENT(tp, BSSGP_IE_BVCI)) {
uint16_t bvci;
bvci = ntohs(tlvp_val16_unal(tp, BSSGP_IE_BVCI));
if (bvci >= 2)
return gbproxy_peer_by_bvci(cfg, bvci);
}
if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA)) {
uint8_t *rai = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA);
/* Only compare LAC part, since MCC/MNC are possibly patched.
* Since the LAC of different BSS must be different when
* MCC/MNC are patched, collisions shouldn't happen. */
return gbproxy_peer_by_lac(cfg, rai);
}
if (TLVP_PRESENT(tp, BSSGP_IE_LOCATION_AREA)) {
uint8_t *lai = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_LOCATION_AREA);
return gbproxy_peer_by_lac(cfg, lai);
}
return NULL;
}
static void clean_stale_timer_cb(void *data)
{
time_t now;
struct timespec ts = {0,};
struct gbproxy_peer *peer = (struct gbproxy_peer *) data;
osmo_clock_gettime(CLOCK_MONOTONIC, &ts);
now = ts.tv_sec;
gbproxy_remove_stale_link_infos(peer, now);
if (peer->cfg->clean_stale_timer_freq != 0)
osmo_timer_schedule(&peer->clean_stale_timer,
peer->cfg->clean_stale_timer_freq, 0);
}
struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_config *cfg, uint16_t bvci)
{
struct gbproxy_peer *peer;
peer = talloc_zero(tall_sgsn_ctx, struct gbproxy_peer);
if (!peer)
return NULL;
peer->bvci = bvci;
peer->ctrg = rate_ctr_group_alloc(peer, &peer_ctrg_desc, bvci);
if (!peer->ctrg) {
talloc_free(peer);
return NULL;
}
peer->cfg = cfg;
llist_add(&peer->list, &cfg->bts_peers);
INIT_LLIST_HEAD(&peer->patch_state.logical_links);
osmo_timer_setup(&peer->clean_stale_timer, clean_stale_timer_cb, peer);
if (peer->cfg->clean_stale_timer_freq != 0)
osmo_timer_schedule(&peer->clean_stale_timer,
peer->cfg->clean_stale_timer_freq, 0);
return peer;
}
void gbproxy_peer_free(struct gbproxy_peer *peer)
{
llist_del(&peer->list);
osmo_timer_del(&peer->clean_stale_timer);
gbproxy_delete_link_infos(peer);
rate_ctr_group_free(peer->ctrg);
peer->ctrg = NULL;
talloc_free(peer);
}
int gbproxy_cleanup_peers(struct gbproxy_config *cfg, uint16_t nsei, uint16_t bvci)
{
int counter = 0;
struct gbproxy_peer *peer, *tmp;
llist_for_each_entry_safe(peer, tmp, &cfg->bts_peers, list) {
if (peer->nsei != nsei)
continue;
if (bvci && peer->bvci != bvci)
continue;
gbproxy_peer_free(peer);
counter += 1;
}
return counter;
}

View File

@@ -1,723 +0,0 @@
/* Gb-proxy TLLI state handling */
/* (C) 2014 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <osmocom/gsm/gsm48.h>
#include <osmocom/sgsn/gb_proxy.h>
#include <osmocom/sgsn/gprs_utils.h>
#include <osmocom/sgsn/gprs_gb_parse.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/talloc.h>
struct gbproxy_link_info *gbproxy_link_info_by_tlli(struct gbproxy_peer *peer,
uint32_t tlli)
{
struct gbproxy_link_info *link_info;
struct gbproxy_patch_state *state = &peer->patch_state;
if (!tlli)
return NULL;
llist_for_each_entry(link_info, &state->logical_links, list)
if (link_info->tlli.current == tlli ||
link_info->tlli.assigned == tlli)
return link_info;
return NULL;
}
struct gbproxy_link_info *gbproxy_link_info_by_ptmsi(
struct gbproxy_peer *peer,
uint32_t ptmsi)
{
struct gbproxy_link_info *link_info;
struct gbproxy_patch_state *state = &peer->patch_state;
if (ptmsi == GSM_RESERVED_TMSI)
return NULL;
llist_for_each_entry(link_info, &state->logical_links, list)
if (link_info->tlli.ptmsi == ptmsi)
return link_info;
return NULL;
}
struct gbproxy_link_info *gbproxy_link_info_by_any_sgsn_tlli(
struct gbproxy_peer *peer,
uint32_t tlli)
{
struct gbproxy_link_info *link_info;
struct gbproxy_patch_state *state = &peer->patch_state;
if (!tlli)
return NULL;
/* Don't care about the NSEI */
llist_for_each_entry(link_info, &state->logical_links, list)
if (link_info->sgsn_tlli.current == tlli ||
link_info->sgsn_tlli.assigned == tlli)
return link_info;
return NULL;
}
struct gbproxy_link_info *gbproxy_link_info_by_sgsn_tlli(
struct gbproxy_peer *peer,
uint32_t tlli, uint32_t sgsn_nsei)
{
struct gbproxy_link_info *link_info;
struct gbproxy_patch_state *state = &peer->patch_state;
if (!tlli)
return NULL;
llist_for_each_entry(link_info, &state->logical_links, list)
if ((link_info->sgsn_tlli.current == tlli ||
link_info->sgsn_tlli.assigned == tlli) &&
link_info->sgsn_nsei == sgsn_nsei)
return link_info;
return NULL;
}
struct gbproxy_link_info *gbproxy_link_info_by_imsi(
struct gbproxy_peer *peer,
const uint8_t *imsi,
size_t imsi_len)
{
struct gbproxy_link_info *link_info;
struct gbproxy_patch_state *state = &peer->patch_state;
if (!gprs_is_mi_imsi(imsi, imsi_len))
return NULL;
llist_for_each_entry(link_info, &state->logical_links, list) {
if (link_info->imsi_len != imsi_len)
continue;
if (memcmp(link_info->imsi, imsi, imsi_len) != 0)
continue;
return link_info;
}
return NULL;
}
void gbproxy_link_info_discard_messages(struct gbproxy_link_info *link_info)
{
struct msgb *msg, *nxt;
llist_for_each_entry_safe(msg, nxt, &link_info->stored_msgs, list) {
llist_del(&msg->list);
msgb_free(msg);
}
}
void gbproxy_delete_link_info(struct gbproxy_peer *peer,
struct gbproxy_link_info *link_info)
{
struct gbproxy_patch_state *state = &peer->patch_state;
gbproxy_link_info_discard_messages(link_info);
llist_del(&link_info->list);
talloc_free(link_info);
state->logical_link_count -= 1;
peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
state->logical_link_count;
}
void gbproxy_delete_link_infos(struct gbproxy_peer *peer)
{
struct gbproxy_link_info *link_info, *nxt;
struct gbproxy_patch_state *state = &peer->patch_state;
llist_for_each_entry_safe(link_info, nxt, &state->logical_links, list)
gbproxy_delete_link_info(peer, link_info);
OSMO_ASSERT(state->logical_link_count == 0);
OSMO_ASSERT(llist_empty(&state->logical_links));
}
void gbproxy_attach_link_info(struct gbproxy_peer *peer, time_t now,
struct gbproxy_link_info *link_info)
{
struct gbproxy_patch_state *state = &peer->patch_state;
link_info->timestamp = now;
llist_add(&link_info->list, &state->logical_links);
state->logical_link_count += 1;
peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
state->logical_link_count;
}
int gbproxy_remove_stale_link_infos(struct gbproxy_peer *peer, time_t now)
{
struct gbproxy_patch_state *state = &peer->patch_state;
int exceeded_max_len = 0;
int deleted_count = 0;
int check_for_age;
if (peer->cfg->tlli_max_len > 0)
exceeded_max_len =
state->logical_link_count - peer->cfg->tlli_max_len;
check_for_age = peer->cfg->tlli_max_age > 0;
for (; exceeded_max_len > 0; exceeded_max_len--) {
struct gbproxy_link_info *link_info;
OSMO_ASSERT(!llist_empty(&state->logical_links));
link_info = llist_entry(state->logical_links.prev,
struct gbproxy_link_info,
list);
LOGP(DGPRS, LOGL_INFO,
"Removing TLLI %08x from list "
"(stale, length %d, max_len exceeded)\n",
link_info->tlli.current, state->logical_link_count);
gbproxy_delete_link_info(peer, link_info);
deleted_count += 1;
}
while (check_for_age && !llist_empty(&state->logical_links)) {
time_t age;
struct gbproxy_link_info *link_info;
link_info = llist_entry(state->logical_links.prev,
struct gbproxy_link_info,
list);
age = now - link_info->timestamp;
/* age < 0 only happens after system time jumps, discard entry */
if (age <= peer->cfg->tlli_max_age && age >= 0) {
check_for_age = 0;
continue;
}
LOGP(DGPRS, LOGL_INFO,
"Removing TLLI %08x from list "
"(stale, age %d, max_age exceeded)\n",
link_info->tlli.current, (int)age);
gbproxy_delete_link_info(peer, link_info);
deleted_count += 1;
}
return deleted_count;
}
struct gbproxy_link_info *gbproxy_link_info_alloc( struct gbproxy_peer *peer)
{
struct gbproxy_link_info *link_info;
link_info = talloc_zero(peer, struct gbproxy_link_info);
link_info->tlli.ptmsi = GSM_RESERVED_TMSI;
link_info->sgsn_tlli.ptmsi = GSM_RESERVED_TMSI;
link_info->vu_gen_tx_bss = GBPROXY_INIT_VU_GEN_TX;
INIT_LLIST_HEAD(&link_info->stored_msgs);
return link_info;
}
void gbproxy_detach_link_info(
struct gbproxy_peer *peer,
struct gbproxy_link_info *link_info)
{
struct gbproxy_patch_state *state = &peer->patch_state;
llist_del(&link_info->list);
OSMO_ASSERT(state->logical_link_count > 0);
state->logical_link_count -= 1;
peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
state->logical_link_count;
}
void gbproxy_update_link_info(struct gbproxy_link_info *link_info,
const uint8_t *imsi, size_t imsi_len)
{
if (!gprs_is_mi_imsi(imsi, imsi_len))
return;
link_info->imsi_len = imsi_len;
link_info->imsi =
talloc_realloc_size(link_info, link_info->imsi, imsi_len);
OSMO_ASSERT(link_info->imsi != NULL);
memcpy(link_info->imsi, imsi, imsi_len);
}
void gbproxy_reassign_tlli(struct gbproxy_tlli_state *tlli_state,
struct gbproxy_peer *peer, uint32_t new_tlli)
{
if (new_tlli == tlli_state->current)
return;
LOGP(DGPRS, LOGL_INFO,
"The TLLI has been reassigned from %08x to %08x\n",
tlli_state->current, new_tlli);
/* Remember assigned TLLI */
tlli_state->assigned = new_tlli;
tlli_state->bss_validated = false;
tlli_state->net_validated = false;
}
uint32_t gbproxy_map_tlli(uint32_t other_tlli,
struct gbproxy_link_info *link_info, int to_bss)
{
uint32_t tlli = 0;
struct gbproxy_tlli_state *src, *dst;
if (to_bss) {
src = &link_info->sgsn_tlli;
dst = &link_info->tlli;
} else {
src = &link_info->tlli;
dst = &link_info->sgsn_tlli;
}
if (src->current == other_tlli)
tlli = dst->current;
else if (src->assigned == other_tlli)
tlli = dst->assigned;
return tlli;
}
static void gbproxy_validate_tlli(struct gbproxy_tlli_state *tlli_state,
uint32_t tlli, int to_bss)
{
LOGP(DGPRS, LOGL_DEBUG,
"%s({current = %08x, assigned = %08x, net_vld = %d, bss_vld = %d}, %08x)\n",
__func__, tlli_state->current, tlli_state->assigned,
tlli_state->net_validated, tlli_state->bss_validated, tlli);
if (!tlli_state->assigned || tlli_state->assigned != tlli)
return;
/* TODO: Is this ok? Check spec */
if (gprs_tlli_type(tlli) != TLLI_LOCAL)
return;
/* See GSM 04.08, 4.7.1.5 */
if (to_bss)
tlli_state->net_validated = true;
else
tlli_state->bss_validated = true;
if (!tlli_state->bss_validated || !tlli_state->net_validated)
return;
LOGP(DGPRS, LOGL_INFO,
"The TLLI %08x has been validated (was %08x)\n",
tlli_state->assigned, tlli_state->current);
tlli_state->current = tlli;
tlli_state->assigned = 0;
}
static void gbproxy_touch_link_info(struct gbproxy_peer *peer,
struct gbproxy_link_info *link_info,
time_t now)
{
gbproxy_detach_link_info(peer, link_info);
gbproxy_attach_link_info(peer, now, link_info);
}
static int gbproxy_unregister_link_info(struct gbproxy_peer *peer,
struct gbproxy_link_info *link_info)
{
if (!link_info)
return 1;
if (link_info->tlli.ptmsi == GSM_RESERVED_TMSI && !link_info->imsi_len) {
LOGP(DGPRS, LOGL_INFO,
"Removing TLLI %08x from list (P-TMSI or IMSI are not set)\n",
link_info->tlli.current);
gbproxy_delete_link_info(peer, link_info);
return 1;
}
link_info->tlli.current = 0;
link_info->tlli.assigned = 0;
link_info->sgsn_tlli.current = 0;
link_info->sgsn_tlli.assigned = 0;
link_info->is_deregistered = true;
gbproxy_reset_link(link_info);
return 0;
}
int gbproxy_imsi_matches(struct gbproxy_config *cfg,
enum gbproxy_match_id match_id,
struct gbproxy_link_info *link_info)
{
struct gbproxy_match *match;
OSMO_ASSERT(match_id >= 0 && match_id < ARRAY_SIZE(cfg->matches));
match = &cfg->matches[match_id];
if (!match->enable)
return 1;
return link_info != NULL && link_info->is_matching[match_id];
}
static void gbproxy_assign_imsi(struct gbproxy_peer *peer,
struct gbproxy_link_info *link_info,
struct gprs_gb_parse_context *parse_ctx)
{
int imsi_matches;
struct gbproxy_link_info *other_link_info;
enum gbproxy_match_id match_id;
/* Make sure that there is a second entry with the same IMSI */
other_link_info = gbproxy_link_info_by_imsi(
peer, parse_ctx->imsi, parse_ctx->imsi_len);
if (other_link_info && other_link_info != link_info) {
char mi_buf[200];
mi_buf[0] = '\0';
gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
parse_ctx->imsi, parse_ctx->imsi_len);
LOGP(DGPRS, LOGL_INFO,
"Removing TLLI %08x from list (IMSI %s re-used)\n",
other_link_info->tlli.current, mi_buf);
gbproxy_delete_link_info(peer, other_link_info);
}
/* Update the IMSI field */
gbproxy_update_link_info(link_info,
parse_ctx->imsi, parse_ctx->imsi_len);
/* Check, whether the IMSI matches */
OSMO_ASSERT(ARRAY_SIZE(link_info->is_matching) ==
ARRAY_SIZE(peer->cfg->matches));
for (match_id = 0; match_id < ARRAY_SIZE(link_info->is_matching);
++match_id) {
imsi_matches = gbproxy_check_imsi(
&peer->cfg->matches[match_id],
parse_ctx->imsi, parse_ctx->imsi_len);
if (imsi_matches >= 0)
link_info->is_matching[match_id] = imsi_matches ? true : false;
}
}
static int gbproxy_tlli_match(const struct gbproxy_tlli_state *a,
const struct gbproxy_tlli_state *b)
{
if (a->current && a->current == b->current)
return 1;
if (a->assigned && a->assigned == b->assigned)
return 1;
if (a->ptmsi != GSM_RESERVED_TMSI && a->ptmsi == b->ptmsi)
return 1;
return 0;
}
static void gbproxy_remove_matching_link_infos(
struct gbproxy_peer *peer, struct gbproxy_link_info *link_info)
{
struct gbproxy_link_info *info, *nxt;
struct gbproxy_patch_state *state = &peer->patch_state;
/* Make sure that there is no second entry with the same P-TMSI or TLLI */
llist_for_each_entry_safe(info, nxt, &state->logical_links, list) {
if (info == link_info)
continue;
if (!gbproxy_tlli_match(&link_info->tlli, &info->tlli) &&
(link_info->sgsn_nsei != info->sgsn_nsei ||
!gbproxy_tlli_match(&link_info->sgsn_tlli, &info->sgsn_tlli)))
continue;
LOGP(DGPRS, LOGL_INFO,
"Removing TLLI %08x from list (P-TMSI/TLLI re-used)\n",
info->tlli.current);
gbproxy_delete_link_info(peer, info);
}
}
static struct gbproxy_link_info *gbproxy_get_link_info_ul(
struct gbproxy_peer *peer,
int *tlli_is_valid,
struct gprs_gb_parse_context *parse_ctx)
{
struct gbproxy_link_info *link_info = NULL;
if (parse_ctx->tlli_enc) {
link_info = gbproxy_link_info_by_tlli(peer, parse_ctx->tlli);
if (link_info) {
*tlli_is_valid = 1;
return link_info;
}
}
*tlli_is_valid = 0;
if (!link_info && parse_ctx->imsi) {
link_info = gbproxy_link_info_by_imsi(
peer, parse_ctx->imsi, parse_ctx->imsi_len);
}
if (!link_info && parse_ctx->ptmsi_enc && !parse_ctx->old_raid_is_foreign) {
uint32_t bss_ptmsi;
gprs_parse_tmsi(parse_ctx->ptmsi_enc, &bss_ptmsi);
link_info = gbproxy_link_info_by_ptmsi(peer, bss_ptmsi);
}
if (!link_info)
return NULL;
link_info->is_deregistered = false;
return link_info;
}
struct gbproxy_link_info *gbproxy_update_link_state_ul(
struct gbproxy_peer *peer,
time_t now,
struct gprs_gb_parse_context *parse_ctx)
{
struct gbproxy_link_info *link_info;
int tlli_is_valid;
link_info = gbproxy_get_link_info_ul(peer, &tlli_is_valid, parse_ctx);
if (parse_ctx->tlli_enc && parse_ctx->llc) {
uint32_t sgsn_tlli;
if (!link_info) {
LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list\n",
parse_ctx->tlli);
link_info = gbproxy_link_info_alloc(peer);
gbproxy_attach_link_info(peer, now, link_info);
/* Setup TLLIs */
sgsn_tlli = gbproxy_make_sgsn_tlli(peer, link_info,
parse_ctx->tlli);
link_info->sgsn_tlli.current = sgsn_tlli;
link_info->tlli.current = parse_ctx->tlli;
} else if (!tlli_is_valid) {
/* New TLLI (info found by IMSI or P-TMSI) */
link_info->tlli.current = parse_ctx->tlli;
link_info->tlli.assigned = 0;
link_info->sgsn_tlli.current =
gbproxy_make_sgsn_tlli(peer, link_info,
parse_ctx->tlli);
link_info->sgsn_tlli.assigned = 0;
gbproxy_touch_link_info(peer, link_info, now);
} else {
sgsn_tlli = gbproxy_map_tlli(parse_ctx->tlli, link_info, 0);
if (!sgsn_tlli)
sgsn_tlli = gbproxy_make_sgsn_tlli(peer, link_info,
parse_ctx->tlli);
gbproxy_validate_tlli(&link_info->tlli,
parse_ctx->tlli, 0);
gbproxy_validate_tlli(&link_info->sgsn_tlli,
sgsn_tlli, 0);
gbproxy_touch_link_info(peer, link_info, now);
}
} else if (link_info) {
gbproxy_touch_link_info(peer, link_info, now);
}
if (parse_ctx->imsi && link_info && link_info->imsi_len == 0)
gbproxy_assign_imsi(peer, link_info, parse_ctx);
return link_info;
}
static struct gbproxy_link_info *gbproxy_get_link_info_dl(
struct gbproxy_peer *peer,
struct gprs_gb_parse_context *parse_ctx)
{
struct gbproxy_link_info *link_info = NULL;
/* Which key to use depends on its availability only, if that fails, do
* not retry it with another key (e.g. IMSI). */
if (parse_ctx->tlli_enc)
link_info = gbproxy_link_info_by_sgsn_tlli(peer, parse_ctx->tlli,
parse_ctx->peer_nsei);
/* TODO: Get link_info by (SGSN) P-TMSI if that is available (see
* GSM 08.18, 7.2) instead of using the IMSI as key. */
else if (parse_ctx->imsi)
link_info = gbproxy_link_info_by_imsi(
peer, parse_ctx->imsi, parse_ctx->imsi_len);
if (link_info)
link_info->is_deregistered = false;
return link_info;
}
struct gbproxy_link_info *gbproxy_update_link_state_dl(
struct gbproxy_peer *peer,
time_t now,
struct gprs_gb_parse_context *parse_ctx)
{
struct gbproxy_link_info *link_info = NULL;
link_info = gbproxy_get_link_info_dl(peer, parse_ctx);
if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && link_info) {
/* A new P-TMSI has been signalled in the message,
* register new TLLI */
uint32_t new_sgsn_ptmsi;
uint32_t new_bss_ptmsi = GSM_RESERVED_TMSI;
gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_sgsn_ptmsi);
if (link_info->sgsn_tlli.ptmsi == new_sgsn_ptmsi)
new_bss_ptmsi = link_info->tlli.ptmsi;
if (new_bss_ptmsi == GSM_RESERVED_TMSI)
new_bss_ptmsi = gbproxy_make_bss_ptmsi(peer, new_sgsn_ptmsi);
LOGP(DGPRS, LOGL_INFO,
"Got new PTMSI %08x from SGSN, using %08x for BSS\n",
new_sgsn_ptmsi, new_bss_ptmsi);
/* Setup PTMSIs */
link_info->sgsn_tlli.ptmsi = new_sgsn_ptmsi;
link_info->tlli.ptmsi = new_bss_ptmsi;
} else if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && !link_info &&
!peer->cfg->patch_ptmsi) {
/* A new P-TMSI has been signalled in the message with an unknown
* TLLI, create a new link_info */
/* TODO: Add a test case for this branch */
uint32_t new_ptmsi;
gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
LOGP(DGPRS, LOGL_INFO,
"Adding TLLI %08x to list (SGSN, new P-TMSI is %08x)\n",
parse_ctx->tlli, new_ptmsi);
link_info = gbproxy_link_info_alloc(peer);
link_info->sgsn_tlli.current = parse_ctx->tlli;
link_info->tlli.current = parse_ctx->tlli;
link_info->sgsn_tlli.ptmsi = new_ptmsi;
link_info->tlli.ptmsi = new_ptmsi;
gbproxy_attach_link_info(peer, now, link_info);
} else if (parse_ctx->tlli_enc && parse_ctx->llc && !link_info &&
!peer->cfg->patch_ptmsi) {
/* Unknown SGSN TLLI, create a new link_info */
uint32_t new_ptmsi;
link_info = gbproxy_link_info_alloc(peer);
LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list (SGSN)\n",
parse_ctx->tlli);
gbproxy_attach_link_info(peer, now, link_info);
/* Setup TLLIs */
link_info->sgsn_tlli.current = parse_ctx->tlli;
link_info->tlli.current = parse_ctx->tlli;
if (!parse_ctx->new_ptmsi_enc)
return link_info;
/* A new P-TMSI has been signalled in the message */
gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
LOGP(DGPRS, LOGL_INFO,
"Assigning new P-TMSI %08x\n", new_ptmsi);
/* Setup P-TMSIs */
link_info->sgsn_tlli.ptmsi = new_ptmsi;
link_info->tlli.ptmsi = new_ptmsi;
} else if (parse_ctx->tlli_enc && parse_ctx->llc && link_info) {
uint32_t bss_tlli = gbproxy_map_tlli(parse_ctx->tlli,
link_info, 1);
gbproxy_validate_tlli(&link_info->sgsn_tlli, parse_ctx->tlli, 1);
gbproxy_validate_tlli(&link_info->tlli, bss_tlli, 1);
gbproxy_touch_link_info(peer, link_info, now);
} else if (link_info) {
gbproxy_touch_link_info(peer, link_info, now);
}
if (parse_ctx->imsi && link_info && link_info->imsi_len == 0)
gbproxy_assign_imsi(peer, link_info, parse_ctx);
return link_info;
}
int gbproxy_update_link_state_after(
struct gbproxy_peer *peer,
struct gbproxy_link_info *link_info,
time_t now,
struct gprs_gb_parse_context *parse_ctx)
{
int rc = 0;
if (parse_ctx->invalidate_tlli && link_info) {
int keep_info =
peer->cfg->keep_link_infos == GBPROX_KEEP_ALWAYS ||
(peer->cfg->keep_link_infos == GBPROX_KEEP_REATTACH &&
parse_ctx->await_reattach) ||
(peer->cfg->keep_link_infos == GBPROX_KEEP_IDENTIFIED &&
link_info->imsi_len > 0);
if (keep_info) {
LOGP(DGPRS, LOGL_INFO, "Unregistering TLLI %08x\n",
link_info->tlli.current);
rc = gbproxy_unregister_link_info(peer, link_info);
} else {
LOGP(DGPRS, LOGL_INFO, "Removing TLLI %08x from list\n",
link_info->tlli.current);
gbproxy_delete_link_info(peer, link_info);
rc = 1;
}
} else if (parse_ctx->to_bss && parse_ctx->tlli_enc &&
parse_ctx->new_ptmsi_enc && link_info) {
/* A new PTMSI has been signaled in the message,
* register new TLLI */
uint32_t new_sgsn_ptmsi = link_info->sgsn_tlli.ptmsi;
uint32_t new_bss_ptmsi = link_info->tlli.ptmsi;
uint32_t new_sgsn_tlli;
uint32_t new_bss_tlli = 0;
new_sgsn_tlli = gprs_tmsi2tlli(new_sgsn_ptmsi, TLLI_LOCAL);
if (new_bss_ptmsi != GSM_RESERVED_TMSI)
new_bss_tlli = gprs_tmsi2tlli(new_bss_ptmsi, TLLI_LOCAL);
LOGP(DGPRS, LOGL_INFO,
"Assigning new TLLI %08x to SGSN, %08x to BSS\n",
new_sgsn_tlli, new_bss_tlli);
gbproxy_reassign_tlli(&link_info->sgsn_tlli,
peer, new_sgsn_tlli);
gbproxy_reassign_tlli(&link_info->tlli,
peer, new_bss_tlli);
gbproxy_remove_matching_link_infos(peer, link_info);
}
gbproxy_remove_stale_link_infos(peer, now);
return rc;
}

View File

@@ -1,926 +0,0 @@
/*
* (C) 2010 by Harald Welte <laforge@gnumonks.org>
* (C) 2010 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <time.h>
#include <inttypes.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/gprs/gprs_ns.h>
#include <osmocom/gsm/apn.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gb_proxy.h>
#include <osmocom/sgsn/gprs_utils.h>
#include <osmocom/sgsn/vty.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/vty.h>
#include <osmocom/vty/misc.h>
static struct gbproxy_config *g_cfg = NULL;
/*
* vty code for gbproxy below
*/
static struct cmd_node gbproxy_node = {
GBPROXY_NODE,
"%s(config-gbproxy)# ",
1,
};
static const struct value_string keep_modes[] = {
{GBPROX_KEEP_NEVER, "never"},
{GBPROX_KEEP_REATTACH, "re-attach"},
{GBPROX_KEEP_IDENTIFIED, "identified"},
{GBPROX_KEEP_ALWAYS, "always"},
{0, NULL}
};
static const struct value_string match_ids[] = {
{GBPROX_MATCH_PATCHING, "patching"},
{GBPROX_MATCH_ROUTING, "routing"},
{0, NULL}
};
static void gbprox_vty_print_peer(struct vty *vty, struct gbproxy_peer *peer)
{
struct gprs_ra_id raid;
gsm48_parse_ra(&raid, peer->ra);
vty_out(vty, "NSEI %5u, PTP-BVCI %5u, "
"RAI %s", peer->nsei, peer->bvci, osmo_rai_name(&raid));
if (peer->blocked)
vty_out(vty, " [BVC-BLOCKED]");
vty_out(vty, "%s", VTY_NEWLINE);
}
static int config_write_gbproxy(struct vty *vty)
{
enum gbproxy_match_id match_id;
vty_out(vty, "gbproxy%s", VTY_NEWLINE);
vty_out(vty, " sgsn nsei %u%s", g_cfg->nsip_sgsn_nsei,
VTY_NEWLINE);
if (g_cfg->core_plmn.mcc > 0)
vty_out(vty, " core-mobile-country-code %s%s",
osmo_mcc_name(g_cfg->core_plmn.mcc), VTY_NEWLINE);
if (g_cfg->core_plmn.mnc > 0)
vty_out(vty, " core-mobile-network-code %s%s",
osmo_mnc_name(g_cfg->core_plmn.mnc, g_cfg->core_plmn.mnc_3_digits), VTY_NEWLINE);
for (match_id = 0; match_id < ARRAY_SIZE(g_cfg->matches); ++match_id) {
struct gbproxy_match *match = &g_cfg->matches[match_id];
if (match->re_str)
vty_out(vty, " match-imsi %s %s%s",
get_value_string(match_ids, match_id),
match->re_str, VTY_NEWLINE);
}
if (g_cfg->core_apn != NULL) {
if (g_cfg->core_apn_size > 0) {
char str[500] = {0};
vty_out(vty, " core-access-point-name %s%s",
osmo_apn_to_str(str, g_cfg->core_apn,
g_cfg->core_apn_size),
VTY_NEWLINE);
} else {
vty_out(vty, " core-access-point-name none%s",
VTY_NEWLINE);
}
}
if (g_cfg->route_to_sgsn2)
vty_out(vty, " secondary-sgsn nsei %u%s", g_cfg->nsip_sgsn2_nsei,
VTY_NEWLINE);
if (g_cfg->clean_stale_timer_freq > 0)
vty_out(vty, " link-list clean-stale-timer %u%s",
g_cfg->clean_stale_timer_freq, VTY_NEWLINE);
if (g_cfg->tlli_max_age > 0)
vty_out(vty, " link-list max-age %d%s",
g_cfg->tlli_max_age, VTY_NEWLINE);
if (g_cfg->tlli_max_len > 0)
vty_out(vty, " link-list max-length %d%s",
g_cfg->tlli_max_len, VTY_NEWLINE);
vty_out(vty, " link-list keep-mode %s%s",
get_value_string(keep_modes, g_cfg->keep_link_infos),
VTY_NEWLINE);
if (g_cfg->stored_msgs_max_len > 0)
vty_out(vty, " link stored-msgs-max-length %"PRIu32"%s",
g_cfg->stored_msgs_max_len, VTY_NEWLINE);
return CMD_SUCCESS;
}
DEFUN(cfg_gbproxy,
cfg_gbproxy_cmd,
"gbproxy",
"Configure the Gb proxy")
{
vty->node = GBPROXY_NODE;
return CMD_SUCCESS;
}
DEFUN(cfg_nsip_sgsn_nsei,
cfg_nsip_sgsn_nsei_cmd,
"sgsn nsei <0-65534>",
"SGSN information\n"
"NSEI to be used in the connection with the SGSN\n"
"The NSEI\n")
{
unsigned int nsei = atoi(argv[0]);
if (g_cfg->route_to_sgsn2 && g_cfg->nsip_sgsn2_nsei == nsei) {
vty_out(vty, "SGSN NSEI %d conflicts with secondary SGSN NSEI%s",
nsei, VTY_NEWLINE);
return CMD_WARNING;
}
g_cfg->nsip_sgsn_nsei = nsei;
return CMD_SUCCESS;
}
#define GBPROXY_CORE_MNC_STR "Use this network code for the core network\n"
DEFUN(cfg_gbproxy_core_mnc,
cfg_gbproxy_core_mnc_cmd,
"core-mobile-network-code <1-999>",
GBPROXY_CORE_MNC_STR "NCC value\n")
{
uint16_t mnc;
bool mnc_3_digits;
if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
vty_out(vty, "%% Invalid MNC: %s%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
g_cfg->core_plmn.mnc = mnc;
g_cfg->core_plmn.mnc_3_digits = mnc_3_digits;
return CMD_SUCCESS;
}
DEFUN(cfg_gbproxy_no_core_mnc,
cfg_gbproxy_no_core_mnc_cmd,
"no core-mobile-network-code",
NO_STR GBPROXY_CORE_MNC_STR)
{
g_cfg->core_plmn.mnc = 0;
g_cfg->core_plmn.mnc_3_digits = false;
return CMD_SUCCESS;
}
#define GBPROXY_CORE_MCC_STR "Use this country code for the core network\n"
DEFUN(cfg_gbproxy_core_mcc,
cfg_gbproxy_core_mcc_cmd,
"core-mobile-country-code <1-999>",
GBPROXY_CORE_MCC_STR "MCC value\n")
{
g_cfg->core_plmn.mcc = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_gbproxy_no_core_mcc,
cfg_gbproxy_no_core_mcc_cmd,
"no core-mobile-country-code",
NO_STR GBPROXY_CORE_MCC_STR)
{
g_cfg->core_plmn.mcc = 0;
return CMD_SUCCESS;
}
#define GBPROXY_MATCH_IMSI_STR "Restrict actions to certain IMSIs\n"
DEFUN(cfg_gbproxy_match_imsi,
cfg_gbproxy_match_imsi_cmd,
"match-imsi (patching|routing) .REGEXP",
GBPROXY_MATCH_IMSI_STR
"Patch MS related information elements on match only\n"
"Route to the secondary SGSN on match only\n"
"Regular expression for the IMSI match\n")
{
const char *filter = argv[1];
const char *err_msg = NULL;
struct gbproxy_match *match;
enum gbproxy_match_id match_id = get_string_value(match_ids, argv[0]);
OSMO_ASSERT(match_id >= GBPROX_MATCH_PATCHING &&
match_id < GBPROX_MATCH_LAST);
match = &g_cfg->matches[match_id];
if (gbproxy_set_patch_filter(match, filter, &err_msg) != 0) {
vty_out(vty, "Match expression invalid: %s%s",
err_msg, VTY_NEWLINE);
return CMD_WARNING;
}
g_cfg->acquire_imsi = true;
return CMD_SUCCESS;
}
DEFUN(cfg_gbproxy_no_match_imsi,
cfg_gbproxy_no_match_imsi_cmd,
"no match-imsi",
NO_STR GBPROXY_MATCH_IMSI_STR)
{
enum gbproxy_match_id match_id;
for (match_id = 0; match_id < ARRAY_SIZE(g_cfg->matches); ++match_id)
gbproxy_clear_patch_filter(&g_cfg->matches[match_id]);
g_cfg->acquire_imsi = false;
return CMD_SUCCESS;
}
#define GBPROXY_CORE_APN_STR "Use this access point name (APN) for the backbone\n"
#define GBPROXY_CORE_APN_ARG_STR "Replace APN by this string\n" "Remove APN\n"
static int set_core_apn(struct vty *vty, const char *apn)
{
int apn_len;
if (!apn) {
talloc_free(g_cfg->core_apn);
g_cfg->core_apn = NULL;
g_cfg->core_apn_size = 0;
return CMD_SUCCESS;
}
apn_len = strlen(apn);
if (apn_len >= 100) {
vty_out(vty, "APN string too long (max 99 chars)%s",
VTY_NEWLINE);
return CMD_WARNING;
}
if (apn_len == 0) {
talloc_free(g_cfg->core_apn);
/* TODO: replace NULL */
g_cfg->core_apn = talloc_zero_size(NULL, 2);
g_cfg->core_apn_size = 0;
} else {
/* TODO: replace NULL */
g_cfg->core_apn =
talloc_realloc_size(NULL, g_cfg->core_apn, apn_len + 1);
g_cfg->core_apn_size =
gprs_str_to_apn(g_cfg->core_apn, apn_len + 1, apn);
}
return CMD_SUCCESS;
}
DEFUN(cfg_gbproxy_core_apn,
cfg_gbproxy_core_apn_cmd,
"core-access-point-name (APN|none)",
GBPROXY_CORE_APN_STR GBPROXY_CORE_APN_ARG_STR)
{
if (strcmp(argv[0], "none") == 0)
return set_core_apn(vty, "");
else
return set_core_apn(vty, argv[0]);
}
DEFUN(cfg_gbproxy_no_core_apn,
cfg_gbproxy_no_core_apn_cmd,
"no core-access-point-name",
NO_STR GBPROXY_CORE_APN_STR)
{
return set_core_apn(vty, NULL);
}
/* TODO: Remove the patch-ptmsi command, since P-TMSI patching is enabled
* automatically when needed. This command is only left for manual testing
* (e.g. doing P-TMSI patching without using a secondary SGSN)
*/
#define GBPROXY_PATCH_PTMSI_STR "Patch P-TMSI/TLLI\n"
DEFUN(cfg_gbproxy_patch_ptmsi,
cfg_gbproxy_patch_ptmsi_cmd,
"patch-ptmsi",
GBPROXY_PATCH_PTMSI_STR)
{
g_cfg->patch_ptmsi = true;
return CMD_SUCCESS;
}
DEFUN(cfg_gbproxy_no_patch_ptmsi,
cfg_gbproxy_no_patch_ptmsi_cmd,
"no patch-ptmsi",
NO_STR GBPROXY_PATCH_PTMSI_STR)
{
g_cfg->patch_ptmsi = false;
return CMD_SUCCESS;
}
/* TODO: Remove the acquire-imsi command, since that feature is enabled
* automatically when IMSI matching is enabled. This command is only left for
* manual testing (e.g. doing IMSI acquisition without IMSI based patching)
*/
#define GBPROXY_ACQUIRE_IMSI_STR "Acquire the IMSI before establishing a LLC connection (Experimental)\n"
DEFUN(cfg_gbproxy_acquire_imsi,
cfg_gbproxy_acquire_imsi_cmd,
"acquire-imsi",
GBPROXY_ACQUIRE_IMSI_STR)
{
g_cfg->acquire_imsi = true;
return CMD_SUCCESS;
}
DEFUN(cfg_gbproxy_no_acquire_imsi,
cfg_gbproxy_no_acquire_imsi_cmd,
"no acquire-imsi",
NO_STR GBPROXY_ACQUIRE_IMSI_STR)
{
g_cfg->acquire_imsi = false;
return CMD_SUCCESS;
}
#define GBPROXY_SECOND_SGSN_STR "Route matching LLC connections to a second SGSN (Experimental)\n"
DEFUN(cfg_gbproxy_secondary_sgsn,
cfg_gbproxy_secondary_sgsn_cmd,
"secondary-sgsn nsei <0-65534>",
GBPROXY_SECOND_SGSN_STR
"NSEI to be used in the connection with the SGSN\n"
"The NSEI\n")
{
unsigned int nsei = atoi(argv[0]);
if (g_cfg->nsip_sgsn_nsei == nsei) {
vty_out(vty, "Secondary SGSN NSEI %d conflicts with primary SGSN NSEI%s",
nsei, VTY_NEWLINE);
return CMD_WARNING;
}
g_cfg->route_to_sgsn2 = true;
g_cfg->nsip_sgsn2_nsei = nsei;
g_cfg->patch_ptmsi = true;
return CMD_SUCCESS;
}
DEFUN(cfg_gbproxy_no_secondary_sgsn,
cfg_gbproxy_no_secondary_sgsn_cmd,
"no secondary-sgsn",
NO_STR GBPROXY_SECOND_SGSN_STR)
{
g_cfg->route_to_sgsn2 = false;
g_cfg->nsip_sgsn2_nsei = 0xFFFF;
g_cfg->patch_ptmsi = false;
return CMD_SUCCESS;
}
#define GBPROXY_LINK_LIST_STR "Set TLLI list parameters\n"
#define GBPROXY_LINK_STR "Set TLLI parameters\n"
#define GBPROXY_CLEAN_STALE_TIMER_STR "Periodic timer to clean stale links\n"
DEFUN(cfg_gbproxy_link_list_clean_stale_timer,
cfg_gbproxy_link_list_clean_stale_timer_cmd,
"link-list clean-stale-timer <1-999999>",
GBPROXY_LINK_LIST_STR GBPROXY_CLEAN_STALE_TIMER_STR
"Frequency at which the periodic timer is fired (in seconds)\n")
{
struct gbproxy_peer *peer;
g_cfg->clean_stale_timer_freq = (unsigned int) atoi(argv[0]);
/* Re-schedule running timers soon in case prev frequency was really big
and new frequency is desired to be lower. After initial run, periodic
time is used. Use random() to avoid firing timers for all peers at
the same time */
llist_for_each_entry(peer, &g_cfg->bts_peers, list)
osmo_timer_schedule(&peer->clean_stale_timer,
random() % 5, random() % 1000000);
return CMD_SUCCESS;
}
DEFUN(cfg_gbproxy_link_list_no_clean_stale_timer,
cfg_gbproxy_link_list_no_clean_stale_timer_cmd,
"no link-list clean-stale-timer",
NO_STR GBPROXY_LINK_LIST_STR GBPROXY_CLEAN_STALE_TIMER_STR)
{
struct gbproxy_peer *peer;
g_cfg->clean_stale_timer_freq = 0;
llist_for_each_entry(peer, &g_cfg->bts_peers, list)
osmo_timer_del(&peer->clean_stale_timer);
return CMD_SUCCESS;
}
#define GBPROXY_MAX_AGE_STR "Limit maximum age\n"
DEFUN(cfg_gbproxy_link_list_max_age,
cfg_gbproxy_link_list_max_age_cmd,
"link-list max-age <1-999999>",
GBPROXY_LINK_LIST_STR GBPROXY_MAX_AGE_STR
"Maximum age in seconds\n")
{
g_cfg->tlli_max_age = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_gbproxy_link_list_no_max_age,
cfg_gbproxy_link_list_no_max_age_cmd,
"no link-list max-age",
NO_STR GBPROXY_LINK_LIST_STR GBPROXY_MAX_AGE_STR)
{
g_cfg->tlli_max_age = 0;
return CMD_SUCCESS;
}
#define GBPROXY_MAX_LEN_STR "Limit list length\n"
DEFUN(cfg_gbproxy_link_list_max_len,
cfg_gbproxy_link_list_max_len_cmd,
"link-list max-length <1-99999>",
GBPROXY_LINK_LIST_STR GBPROXY_MAX_LEN_STR
"Maximum number of logical links in the list\n")
{
g_cfg->tlli_max_len = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_gbproxy_link_list_no_max_len,
cfg_gbproxy_link_list_no_max_len_cmd,
"no link-list max-length",
NO_STR GBPROXY_LINK_LIST_STR GBPROXY_MAX_LEN_STR)
{
g_cfg->tlli_max_len = 0;
return CMD_SUCCESS;
}
DEFUN(cfg_gbproxy_link_list_keep_mode,
cfg_gbproxy_link_list_keep_mode_cmd,
"link-list keep-mode (never|re-attach|identified|always)",
GBPROXY_LINK_LIST_STR "How to keep entries for detached logical links\n"
"Discard entry immediately after detachment\n"
"Keep entry if a re-attachment has be requested\n"
"Keep entry if it associated with an IMSI\n"
"Don't discard entries after detachment\n")
{
int val = get_string_value(keep_modes, argv[0]);
OSMO_ASSERT(val >= GBPROX_KEEP_NEVER && val <= GBPROX_KEEP_ALWAYS);
g_cfg->keep_link_infos = val;
return CMD_SUCCESS;
}
DEFUN(cfg_gbproxy_link_stored_msgs_max_len,
cfg_gbproxy_link_stored_msgs_max_len_cmd,
"link stored-msgs-max-length <1-99999>",
GBPROXY_LINK_STR GBPROXY_MAX_LEN_STR
"Maximum number of msgb stored in the logical link waiting to acquire its IMSI\n")
{
g_cfg->stored_msgs_max_len = (uint32_t) atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_gbproxy_link_no_stored_msgs_max_len,
cfg_gbproxy_link_no_stored_msgs_max_len_cmd,
"no link stored-msgs-max-length",
NO_STR GBPROXY_LINK_STR GBPROXY_MAX_LEN_STR)
{
g_cfg->stored_msgs_max_len = 0;
return CMD_SUCCESS;
}
DEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]",
SHOW_STR "Display information about the Gb proxy\n" "Show statistics\n")
{
struct gbproxy_peer *peer;
int show_stats = argc >= 1;
if (show_stats)
vty_out_rate_ctr_group(vty, "", g_cfg->ctrg);
llist_for_each_entry(peer, &g_cfg->bts_peers, list) {
gbprox_vty_print_peer(vty, peer);
if (show_stats)
vty_out_rate_ctr_group(vty, " ", peer->ctrg);
}
return CMD_SUCCESS;
}
DEFUN(show_gbproxy_links, show_gbproxy_links_cmd, "show gbproxy links",
SHOW_STR "Display information about the Gb proxy\n" "Show logical links\n")
{
struct gbproxy_peer *peer;
char mi_buf[200];
time_t now;
struct timespec ts = {0,};
osmo_clock_gettime(CLOCK_MONOTONIC, &ts);
now = ts.tv_sec;
llist_for_each_entry(peer, &g_cfg->bts_peers, list) {
struct gbproxy_link_info *link_info;
struct gbproxy_patch_state *state = &peer->patch_state;
gbprox_vty_print_peer(vty, peer);
llist_for_each_entry(link_info, &state->logical_links, list) {
time_t age = now - link_info->timestamp;
if (link_info->imsi > 0) {
snprintf(mi_buf, sizeof(mi_buf), "(invalid)");
gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
link_info->imsi,
link_info->imsi_len);
} else {
snprintf(mi_buf, sizeof(mi_buf), "(none)");
}
vty_out(vty, " TLLI %08x, IMSI %s, AGE %d",
link_info->tlli.current, mi_buf, (int)age);
if (link_info->stored_msgs_len)
vty_out(vty, ", STORED %"PRIu32"/%"PRIu32,
link_info->stored_msgs_len,
g_cfg->stored_msgs_max_len);
if (g_cfg->route_to_sgsn2)
vty_out(vty, ", SGSN NSEI %d",
link_info->sgsn_nsei);
if (link_info->is_deregistered)
vty_out(vty, ", DE-REGISTERED");
vty_out(vty, "%s", VTY_NEWLINE);
}
}
return CMD_SUCCESS;
}
DEFUN(delete_gb_bvci, delete_gb_bvci_cmd,
"delete-gbproxy-peer <0-65534> bvci <2-65534>",
"Delete a GBProxy peer by NSEI and optionally BVCI\n"
"NSEI number\n"
"Only delete peer with a matching BVCI\n"
"BVCI number\n")
{
const uint16_t nsei = atoi(argv[0]);
const uint16_t bvci = atoi(argv[1]);
int counter;
counter = gbproxy_cleanup_peers(g_cfg, nsei, bvci);
if (counter == 0) {
vty_out(vty, "BVC not found%s", VTY_NEWLINE);
return CMD_WARNING;
}
return CMD_SUCCESS;
}
DEFUN(delete_gb_nsei, delete_gb_nsei_cmd,
"delete-gbproxy-peer <0-65534> (only-bvc|only-nsvc|all) [dry-run]",
"Delete a GBProxy peer by NSEI and optionally BVCI\n"
"NSEI number\n"
"Only delete BSSGP connections (BVC)\n"
"Only delete dynamic NS connections (NS-VC)\n"
"Delete BVC and dynamic NS connections\n"
"Show what would be deleted instead of actually deleting\n"
)
{
const uint16_t nsei = atoi(argv[0]);
const char *mode = argv[1];
int dry_run = argc > 2;
int delete_bvc = 0;
int delete_nsvc = 0;
int counter;
if (strcmp(mode, "only-bvc") == 0)
delete_bvc = 1;
else if (strcmp(mode, "only-nsvc") == 0)
delete_nsvc = 1;
else
delete_bvc = delete_nsvc = 1;
if (delete_bvc) {
if (!dry_run)
counter = gbproxy_cleanup_peers(g_cfg, nsei, 0);
else {
struct gbproxy_peer *peer;
counter = 0;
llist_for_each_entry(peer, &g_cfg->bts_peers, list) {
if (peer->nsei != nsei)
continue;
vty_out(vty, "BVC: ");
gbprox_vty_print_peer(vty, peer);
counter += 1;
}
}
vty_out(vty, "%sDeleted %d BVC%s",
dry_run ? "Not " : "", counter, VTY_NEWLINE);
}
if (delete_nsvc) {
struct gprs_ns_inst *nsi = g_cfg->nsi;
struct gprs_nsvc *nsvc, *nsvc2;
counter = 0;
llist_for_each_entry_safe(nsvc, nsvc2, &nsi->gprs_nsvcs, list) {
if (nsvc->nsei != nsei)
continue;
if (nsvc->persistent)
continue;
if (!dry_run)
gprs_nsvc_delete(nsvc);
else
vty_out(vty, "NS-VC: NSEI %5u, NS-VCI %5u, "
"remote %s%s",
nsvc->nsei, nsvc->nsvci,
gprs_ns_ll_str(nsvc), VTY_NEWLINE);
counter += 1;
}
vty_out(vty, "%sDeleted %d NS-VC%s",
dry_run ? "Not " : "", counter, VTY_NEWLINE);
}
return CMD_SUCCESS;
}
#define GBPROXY_DELETE_LINK_STR \
"Delete a GBProxy logical link entry by NSEI and identification\nNSEI number\n"
DEFUN(delete_gb_link_by_id, delete_gb_link_by_id_cmd,
"delete-gbproxy-link <0-65534> (tlli|imsi|sgsn-nsei) IDENT",
GBPROXY_DELETE_LINK_STR
"Delete entries with a matching TLLI (hex)\n"
"Delete entries with a matching IMSI\n"
"Delete entries with a matching SGSN NSEI\n"
"Identification to match\n")
{
const uint16_t nsei = atoi(argv[0]);
enum {MATCH_TLLI = 't', MATCH_IMSI = 'i', MATCH_SGSN = 's'} match;
uint32_t ident = 0;
const char *imsi = NULL;
struct gbproxy_peer *peer = 0;
struct gbproxy_link_info *link_info, *nxt;
struct gbproxy_patch_state *state;
char mi_buf[200];
int found = 0;
match = argv[1][0];
switch (match) {
case MATCH_TLLI: ident = strtoll(argv[2], NULL, 16); break;
case MATCH_IMSI: imsi = argv[2]; break;
case MATCH_SGSN: ident = strtoll(argv[2], NULL, 0); break;
};
peer = gbproxy_peer_by_nsei(g_cfg, nsei);
if (!peer) {
vty_out(vty, "Didn't find peer with NSEI %d%s",
nsei, VTY_NEWLINE);
return CMD_WARNING;
}
state = &peer->patch_state;
llist_for_each_entry_safe(link_info, nxt, &state->logical_links, list) {
switch (match) {
case MATCH_TLLI:
if (link_info->tlli.current != ident)
continue;
break;
case MATCH_SGSN:
if (link_info->sgsn_nsei != ident)
continue;
break;
case MATCH_IMSI:
if (!link_info->imsi)
continue;
mi_buf[0] = '\0';
gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
link_info->imsi,
link_info->imsi_len);
if (strcmp(mi_buf, imsi) != 0)
continue;
break;
}
vty_out(vty, "Deleting link with TLLI %08x%s", link_info->tlli.current,
VTY_NEWLINE);
gbproxy_delete_link_info(peer, link_info);
found += 1;
}
if (!found && argc >= 2) {
vty_out(vty, "Didn't find link entry with %s %s%s",
argv[1], argv[2], VTY_NEWLINE);
}
return CMD_SUCCESS;
}
DEFUN(delete_gb_link, delete_gb_link_cmd,
"delete-gbproxy-link <0-65534> (stale|de-registered)",
GBPROXY_DELETE_LINK_STR
"Delete stale entries\n"
"Delete de-registered entries\n")
{
const uint16_t nsei = atoi(argv[0]);
enum {MATCH_STALE = 's', MATCH_DEREGISTERED = 'd'} match;
struct gbproxy_peer *peer = 0;
struct gbproxy_link_info *link_info, *nxt;
struct gbproxy_patch_state *state;
time_t now;
struct timespec ts = {0,};
int found = 0;
match = argv[1][0];
peer = gbproxy_peer_by_nsei(g_cfg, nsei);
if (!peer) {
vty_out(vty, "Didn't find peer with NSEI %d%s",
nsei, VTY_NEWLINE);
return CMD_WARNING;
}
state = &peer->patch_state;
osmo_clock_gettime(CLOCK_MONOTONIC, &ts);
now = ts.tv_sec;
if (match == MATCH_STALE) {
found = gbproxy_remove_stale_link_infos(peer, now);
if (found)
vty_out(vty, "Deleted %d stale logical link%s%s",
found, found == 1 ? "" : "s", VTY_NEWLINE);
} else {
llist_for_each_entry_safe(link_info, nxt,
&state->logical_links, list) {
if (!link_info->is_deregistered)
continue;
gbproxy_delete_link_info(peer, link_info);
found += 1;
}
}
if (found)
vty_out(vty, "Deleted %d %s logical link%s%s",
found, argv[1], found == 1 ? "" : "s", VTY_NEWLINE);
return CMD_SUCCESS;
}
/*
* legacy commands to provide an upgrade path from "broken" releases
* or pre-releases
*/
DEFUN_DEPRECATED(cfg_gbproxy_broken_apn_match,
cfg_gbproxy_broken_apn_match_cmd,
"core-access-point-name none match-imsi .REGEXP",
GBPROXY_CORE_APN_STR GBPROXY_MATCH_IMSI_STR "Remove APN\n"
"Patch MS related information elements on match only\n"
"Route to the secondary SGSN on match only\n"
"Regular expression for the IMSI match\n")
{
const char *filter = argv[0];
const char *err_msg = NULL;
struct gbproxy_match *match;
enum gbproxy_match_id match_id = get_string_value(match_ids, "patching");
/* apply APN none */
set_core_apn(vty, "");
/* do the matching... with copy and paste */
OSMO_ASSERT(match_id >= GBPROX_MATCH_PATCHING &&
match_id < GBPROX_MATCH_LAST);
match = &g_cfg->matches[match_id];
if (gbproxy_set_patch_filter(match, filter, &err_msg) != 0) {
vty_out(vty, "Match expression invalid: %s%s",
err_msg, VTY_NEWLINE);
return CMD_WARNING;
}
g_cfg->acquire_imsi = true;
return CMD_SUCCESS;
}
#define GBPROXY_TLLI_LIST_STR "Set TLLI list parameters\n"
#define GBPROXY_MAX_LEN_STR "Limit list length\n"
DEFUN_DEPRECATED(cfg_gbproxy_depr_tlli_list_max_len,
cfg_gbproxy_depr_tlli_list_max_len_cmd,
"tlli-list max-length <1-99999>",
GBPROXY_TLLI_LIST_STR GBPROXY_MAX_LEN_STR
"Maximum number of TLLIs in the list\n")
{
g_cfg->tlli_max_len = atoi(argv[0]);
return CMD_SUCCESS;
}
int gbproxy_vty_init(void)
{
install_element_ve(&show_gbproxy_cmd);
install_element_ve(&show_gbproxy_links_cmd);
install_element(ENABLE_NODE, &delete_gb_bvci_cmd);
install_element(ENABLE_NODE, &delete_gb_nsei_cmd);
install_element(ENABLE_NODE, &delete_gb_link_by_id_cmd);
install_element(ENABLE_NODE, &delete_gb_link_cmd);
install_element(CONFIG_NODE, &cfg_gbproxy_cmd);
install_node(&gbproxy_node, config_write_gbproxy);
install_element(GBPROXY_NODE, &cfg_nsip_sgsn_nsei_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_core_mcc_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_core_mnc_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_match_imsi_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_core_apn_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_secondary_sgsn_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_patch_ptmsi_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_acquire_imsi_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_clean_stale_timer_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_max_age_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_max_len_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_keep_mode_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_link_stored_msgs_max_len_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mcc_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mnc_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_no_match_imsi_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_apn_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_no_secondary_sgsn_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_no_patch_ptmsi_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_no_acquire_imsi_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_clean_stale_timer_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_max_age_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_max_len_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_link_no_stored_msgs_max_len_cmd);
/* broken or deprecated to allow an upgrade path */
install_element(GBPROXY_NODE, &cfg_gbproxy_broken_apn_match_cmd);
install_element(GBPROXY_NODE, &cfg_gbproxy_depr_tlli_list_max_len_cmd);
return 0;
}
int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg)
{
int rc;
g_cfg = cfg;
rc = vty_read_config_file(config_file, NULL);
if (rc < 0) {
fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
return rc;
}
return 0;
}

View File

@@ -29,7 +29,6 @@ endif
noinst_LTLIBRARIES = libcommon.la
libcommon_la_SOURCES = \
gprs_gb_parse.c \
gprs_llc_parse.c \
crc24.c \
gprs_utils.c \

View File

@@ -59,7 +59,7 @@ static const uint32_t tbl_crc24[256] = {
#define INIT_CRC24 0xffffff
uint32_t crc24_calc(uint32_t fcs, uint8_t *cp, unsigned int len)
uint32_t crc24_calc(uint32_t fcs, const uint8_t *cp, unsigned int len)
{
while (len--)
fcs = (fcs >> 8) ^ tbl_crc24[(fcs ^ *cp++) & 0xff];

View File

@@ -29,7 +29,7 @@
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/sgsn/mmctx.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/gprs_llc.h>
#include <osmocom/sgsn/crc24.h>
@@ -55,7 +55,7 @@ static const struct value_string llc_cmd_strs[] = {
#define N202 4
#define CRC24_LENGTH 3
int gprs_llc_fcs(uint8_t *data, unsigned int len)
int gprs_llc_fcs(const uint8_t *data, unsigned int len)
{
uint32_t fcs_calc;

View File

@@ -22,7 +22,7 @@
#include <osmocom/sgsn/gprs_utils.h>
#include <osmocom/core/msgb.h>
#include <osmocom/gprs/gprs_ns.h>
#include <osmocom/gprs/gprs_ns2.h>
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/gsm/protocol/gsm_04_08.h>
@@ -30,56 +30,6 @@
#include <string.h>
int gprs_str_to_apn(uint8_t *apn_enc, size_t max_len, const char *str)
{
uint8_t *last_len_field;
int len;
/* Can we even write the length field to the output? */
if (max_len == 0)
return -1;
/* Remember where we need to put the length once we know it */
last_len_field = apn_enc;
len = 1;
apn_enc += 1;
while (str[0]) {
if (len >= max_len)
return -1;
if (str[0] == '.') {
*last_len_field = (apn_enc - last_len_field) - 1;
last_len_field = apn_enc;
} else {
*apn_enc = str[0];
}
apn_enc += 1;
str += 1;
len += 1;
}
*last_len_field = (apn_enc - last_len_field) - 1;
return len;
}
/* GSM 04.08, 10.5.7.3 GPRS Timer */
int gprs_tmr_to_secs(uint8_t tmr)
{
switch (tmr & GPRS_TMR_UNIT_MASK) {
case GPRS_TMR_2SECONDS:
return 2 * (tmr & GPRS_TMR_FACT_MASK);
default:
case GPRS_TMR_MINUTE:
return 60 * (tmr & GPRS_TMR_FACT_MASK);
case GPRS_TMR_6MINUTE:
return 360 * (tmr & GPRS_TMR_FACT_MASK);
case GPRS_TMR_DEACTIVATED:
return -1;
}
}
/* This functions returns a tmr value such that
* - f is monotonic
* - f(s) <= s
@@ -132,19 +82,6 @@ int gprs_is_mi_imsi(const uint8_t *value, size_t value_len)
return 1;
}
int gprs_parse_mi_tmsi(const uint8_t *value, size_t value_len, uint32_t *tmsi)
{
uint32_t tmsi_be;
if (!gprs_is_mi_tmsi(value, value_len))
return 0;
memcpy(&tmsi_be, value + 1, sizeof(tmsi_be));
*tmsi = ntohl(tmsi_be);
return 1;
}
void gprs_parse_tmsi(const uint8_t *value, uint32_t *tmsi)
{
uint32_t tmsi_be;

View File

@@ -24,8 +24,6 @@
#include <netdb.h>
extern void *tall_sgsn_ctx;
struct cares_event_fd {
struct llist_head head;
struct osmo_fd fd;
@@ -51,8 +49,8 @@ static int ares_osmo_fd_cb(struct osmo_fd *fd, unsigned int what)
LOGP(DGPRS, LOGL_DEBUG, "C-ares fd(%d) ready(%d)\n", fd->fd, what);
ares_process_fd(sgsn->ares_channel,
(what & BSC_FD_READ) ? fd->fd : ARES_SOCKET_BAD,
(what & BSC_FD_WRITE) ? fd->fd : ARES_SOCKET_BAD);
(what & OSMO_FD_READ) ? fd->fd : ARES_SOCKET_BAD,
(what & OSMO_FD_WRITE) ? fd->fd : ARES_SOCKET_BAD);
osmo_ares_reschedule(sgsn);
return 0;
}
@@ -120,14 +118,14 @@ static void setup_ares_osmo_fd(void *data, int fd, int read, int write)
update_fd:
if (read)
ufd->fd.when |= BSC_FD_READ;
osmo_fd_read_enable(&ufd->fd);
else
ufd->fd.when &= ~BSC_FD_READ;
osmo_fd_read_disable(&ufd->fd);
if (write)
ufd->fd.when |= BSC_FD_WRITE;
osmo_fd_write_enable(&ufd->fd);
else
ufd->fd.when &= ~BSC_FD_WRITE;
osmo_fd_write_disable(&ufd->fd);
osmo_ares_reschedule(sgsn);
}

View File

@@ -29,10 +29,10 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <gtp.h>
#include <gtpie.h>
#include <osmocom/gtp/gtp.h>
#include <osmocom/gtp/gtpie.h>
#include <osmocom/sgsn/gtphub.h>
#include <osmocom/gtphub/gtphub.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gprs_utils.h>
@@ -59,15 +59,6 @@ void *osmo_gtphub_ctx;
/* TODO move this to osmocom/core/select.h ? */
typedef int (*osmo_fd_cb_t)(struct osmo_fd *fd, unsigned int what);
/* TODO move this to osmocom/core/linuxlist.h ? */
#define __llist_first(head) (((head)->next == (head)) ? NULL : (head)->next)
#define llist_first(head, type, entry) \
llist_entry(__llist_first(head), type, entry)
#define __llist_last(head) (((head)->next == (head)) ? NULL : (head)->prev)
#define llist_last(head, type, entry) \
llist_entry(__llist_last(head), type, entry)
/* TODO move GTP header stuff to openggsn/gtp/ ? See gtp_decaps*() */
enum gtp_rc {
@@ -167,12 +158,12 @@ void gsn_addr_copy(struct gsn_addr *gsna, const struct gsn_addr *src)
}
int gsn_addr_from_sockaddr(struct gsn_addr *gsna, uint16_t *port,
const struct osmo_sockaddr *sa)
const struct sgsn_sockaddr *sa)
{
char addr_str[256];
char port_str[6];
if (osmo_sockaddr_to_strs(addr_str, sizeof(addr_str),
if (sgsn_sockaddr_to_strs(addr_str, sizeof(addr_str),
port_str, sizeof(port_str),
sa, (NI_NUMERICHOST | NI_NUMERICSERV))
!= 0) {
@@ -484,7 +475,7 @@ static int get_ie_imsi_str(union gtpie_member *ie[], int i,
* present but cannot be decoded. */
static int get_ie_apn_str(union gtpie_member *ie[], const char **apn_str)
{
static char apn_buf[GSM_APN_LENGTH];
static char apn_buf[APN_MAXLEN+1];
unsigned int len;
if (gtpie_gettlv(ie, GTPIE_APN, 0,
&len, apn_buf, sizeof(apn_buf)) != 0)
@@ -613,7 +604,7 @@ void expiry_add(struct expiry *exq, struct expiring_item *item, time_t now)
OSMO_ASSERT(llist_empty(&exq->items)
|| (item->expiry
>= llist_last(&exq->items, struct expiring_item, entry)->expiry));
>= llist_last_entry(&exq->items, struct expiring_item, entry)->expiry));
/* Add/move to the tail to always sort by expiry, ascending. */
llist_del(&item->entry);
@@ -853,10 +844,7 @@ static int gtphub_sock_init(struct osmo_fd *ofd,
return -1;
}
ofd->when = BSC_FD_READ;
ofd->cb = cb;
ofd->data = data;
ofd->priv_nr = ofd_id;
osmo_fd_setup(ofd, -1, OSMO_FD_READ, cb, data, ofd_id);
int rc;
rc = osmo_sock_init_ofd(ofd,
@@ -925,7 +913,7 @@ static void gtphub_bind_stop(struct gtphub_bind *b) {
/* Recv datagram from from->fd, write sender's address to *from_addr.
* Return the number of bytes read, zero on error. */
static int gtphub_read(const struct osmo_fd *from,
struct osmo_sockaddr *from_addr,
struct sgsn_sockaddr *from_addr,
uint8_t *buf, size_t buf_len)
{
OSMO_ASSERT(from_addr);
@@ -946,7 +934,7 @@ static int gtphub_read(const struct osmo_fd *from,
}
LOG(LOGL_DEBUG, "Received %d bytes from %s: %s%s\n",
(int)received, osmo_sockaddr_to_str(from_addr),
(int)received, sgsn_sockaddr_to_str(from_addr),
osmo_hexdump(buf, received > 1000? 1000 : received),
received > 1000 ? "..." : "");
@@ -983,7 +971,7 @@ static inline void set_tei(struct gtp_packet_desc *p, uint32_t tei)
static void gtphub_mapping_del_cb(struct expiring_item *expi);
static struct nr_mapping *gtphub_mapping_new()
static struct nr_mapping *gtphub_mapping_new(void)
{
struct nr_mapping *nrm;
nrm = talloc_zero(osmo_gtphub_ctx, struct nr_mapping);
@@ -1007,7 +995,7 @@ static const char *gtphub_tunnel_side_str(struct gtphub_tunnel *tun,
char *pos = buf;
int left = sizeof(buf);
int l;
struct gtphub_tunnel_endpoint *c, *u;
c = &tun->endpoint[side_idx][GTPH_PLANE_CTRL];
u = &tun->endpoint[side_idx][GTPH_PLANE_USER];
@@ -1116,7 +1104,7 @@ static void gtphub_tunnel_del_cb(struct expiring_item *expi)
/* rate counter index for hubs: [7; 10] */
#define CTR_IDX_HUB(s, p) CTR_IDX(s, p, 3, 2)
static struct gtphub_tunnel *gtphub_tunnel_new()
static struct gtphub_tunnel *gtphub_tunnel_new(void)
{
struct gtphub_tunnel *tun;
tun = talloc_zero(osmo_gtphub_ctx, struct gtphub_tunnel);
@@ -1145,9 +1133,7 @@ static const char *gtphub_peer_strb(struct gtphub_peer *peer, char *buf,
if (llist_empty(&peer->addresses))
return "(addressless)";
struct gtphub_peer_addr *a = llist_first(&peer->addresses,
struct gtphub_peer_addr,
entry);
struct gtphub_peer_addr *a = llist_first_entry_or_null(&peer->addresses, struct gtphub_peer_addr, entry);
return gsn_addr_to_strb(&a->addr, buf, buflen);
}
@@ -1948,14 +1934,14 @@ static int from_sgsns_read_cb(struct osmo_fd *from_sgsns_ofd, unsigned int what)
LOG(LOGL_DEBUG, "=== reading from SGSN (%s)\n",
gtphub_plane_idx_names[plane_idx]);
if (!(what & BSC_FD_READ))
if (!(what & OSMO_FD_READ))
return 0;
struct gtphub *hub = from_sgsns_ofd->data;
static uint8_t buf[4096];
struct osmo_sockaddr from_addr;
struct osmo_sockaddr to_addr;
struct sgsn_sockaddr from_addr;
struct sgsn_sockaddr to_addr;
struct osmo_fd *to_ofd;
int len;
uint8_t *reply_buf;
@@ -1979,14 +1965,14 @@ static int from_ggsns_read_cb(struct osmo_fd *from_ggsns_ofd, unsigned int what)
OSMO_ASSERT(plane_idx < GTPH_PLANE_N);
LOG(LOGL_DEBUG, "=== reading from GGSN (%s)\n",
gtphub_plane_idx_names[plane_idx]);
if (!(what & BSC_FD_READ))
if (!(what & OSMO_FD_READ))
return 0;
struct gtphub *hub = from_ggsns_ofd->data;
static uint8_t buf[4096];
struct osmo_sockaddr from_addr;
struct osmo_sockaddr to_addr;
struct sgsn_sockaddr from_addr;
struct sgsn_sockaddr to_addr;
struct osmo_fd *to_ofd;
int len;
uint8_t *reply_buf;
@@ -2071,9 +2057,9 @@ static int gtphub_unmap(struct gtphub *hub,
static int gsn_addr_to_sockaddr(struct gsn_addr *src,
uint16_t port,
struct osmo_sockaddr *dst)
struct sgsn_sockaddr *dst)
{
return osmo_sockaddr_init_udp(dst, gsn_addr_to_str(src), port);
return sgsn_sockaddr_init_udp(dst, gsn_addr_to_str(src), port);
}
/* If p is an Echo request, replace p's data with the matching response and
@@ -2107,7 +2093,7 @@ static int gtphub_handle_echo_req(struct gtphub *hub, struct gtp_packet_desc *p,
}
struct gtphub_peer_port *gtphub_known_addr_have_port(const struct gtphub_bind *bind,
const struct osmo_sockaddr *addr);
const struct sgsn_sockaddr *addr);
/* Parse buffer as GTP packet, replace elements in-place and return the ofd and
* address to forward to. Return a pointer to the osmo_fd, but copy the
@@ -2117,18 +2103,18 @@ struct gtphub_peer_port *gtphub_known_addr_have_port(const struct gtphub_bind *b
int gtphub_handle_buf(struct gtphub *hub,
unsigned int side_idx,
unsigned int plane_idx,
const struct osmo_sockaddr *from_addr,
const struct sgsn_sockaddr *from_addr,
uint8_t *buf,
size_t received,
time_t now,
uint8_t **reply_buf,
struct osmo_fd **to_ofd,
struct osmo_sockaddr *to_addr)
struct sgsn_sockaddr *to_addr)
{
struct gtphub_bind *from_bind = &hub->to_gsns[side_idx][plane_idx];
struct gtphub_bind *to_bind = &hub->to_gsns[other_side_idx(side_idx)][plane_idx];
rate_ctr_add(&from_bind->counters_io->ctr[GTPH_CTR_BYTES_IN],
rate_ctr_add(rate_ctr_group_get_ctr(from_bind->counters_io, GTPH_CTR_BYTES_IN),
received);
struct gtp_packet_desc p;
@@ -2138,7 +2124,7 @@ int gtphub_handle_buf(struct gtphub *hub,
(side_idx == GTPH_SIDE_GGSN)? "<-" : "->",
gtphub_plane_idx_names[plane_idx],
gtphub_side_idx_names[side_idx],
osmo_sockaddr_to_str(from_addr),
sgsn_sockaddr_to_str(from_addr),
gtp_type_str(p.type));
if (p.rc <= 0) {
@@ -2146,26 +2132,26 @@ int gtphub_handle_buf(struct gtphub *hub,
gtp_type_str(p.type),
gtphub_side_idx_names[side_idx],
gtphub_plane_idx_names[plane_idx],
osmo_sockaddr_to_str(from_addr));
sgsn_sockaddr_to_str(from_addr));
return -1;
}
rate_ctr_inc(&from_bind->counters_io->ctr[GTPH_CTR_PKTS_IN]);
rate_ctr_inc(rate_ctr_group_get_ctr(from_bind->counters_io, GTPH_CTR_PKTS_IN));
int reply_len;
reply_len = gtphub_handle_echo_req(hub, &p, reply_buf);
if (reply_len > 0) {
/* It was an echo. Nothing left to do. */
osmo_sockaddr_copy(to_addr, from_addr);
sgsn_sockaddr_copy(to_addr, from_addr);
*to_ofd = &from_bind->ofd;
rate_ctr_inc(&from_bind->counters_io->ctr[GTPH_CTR_PKTS_OUT]);
rate_ctr_add(&from_bind->counters_io->ctr[GTPH_CTR_BYTES_OUT],
rate_ctr_inc(rate_ctr_group_get_ctr(from_bind->counters_io, GTPH_CTR_PKTS_OUT));
rate_ctr_add(rate_ctr_group_get_ctr(from_bind->counters_io, GTPH_CTR_BYTES_OUT),
reply_len);
LOG(LOGL_DEBUG, "%s Echo response to %s: %d bytes to %s\n",
(side_idx == GTPH_SIDE_GGSN)? "-->" : "<--",
gtphub_side_idx_names[side_idx],
(int)reply_len, osmo_sockaddr_to_str(to_addr));
(int)reply_len, sgsn_sockaddr_to_str(to_addr));
return reply_len;
}
if (reply_len < 0)
@@ -2178,7 +2164,7 @@ int gtphub_handle_buf(struct gtphub *hub,
* so no-one else is allowed to talk to us from that side. */
struct gtphub_peer_port *from_peer = hub->proxy[side_idx][plane_idx];
if (from_peer) {
if (osmo_sockaddr_cmp(&from_peer->sa, from_addr) != 0) {
if (sgsn_sockaddr_cmp(&from_peer->sa, from_addr) != 0) {
LOG(LOGL_ERROR,
"Rejecting: %s proxy configured, but GTP packet"
" received on %s bind is from another sender:"
@@ -2186,7 +2172,7 @@ int gtphub_handle_buf(struct gtphub *hub,
gtphub_side_idx_names[side_idx],
gtphub_side_idx_names[side_idx],
gtphub_port_str(from_peer),
osmo_sockaddr_to_str(from_addr));
sgsn_sockaddr_to_str(from_addr));
return -1;
}
}
@@ -2204,7 +2190,7 @@ int gtphub_handle_buf(struct gtphub *hub,
if (side_idx == GTPH_SIDE_GGSN) {
LOG(LOGL_ERROR, "Dropping packet%s: unknown GGSN peer: %s\n",
gtp_type_str(p.type),
osmo_sockaddr_to_str(from_addr));
sgsn_sockaddr_to_str(from_addr));
return -1;
} else {
/* SGSN */
@@ -2216,7 +2202,7 @@ int gtphub_handle_buf(struct gtphub *hub,
"Dropping packet%s: User plane peer was not"
"announced by PDP Context: %s\n",
gtp_type_str(p.type),
osmo_sockaddr_to_str(from_addr));
sgsn_sockaddr_to_str(from_addr));
return -1;
}
@@ -2235,13 +2221,13 @@ int gtphub_handle_buf(struct gtphub *hub,
LOG(LOGL_ERROR, "Dropping packet%s: invalid %s peer: %s\n",
gtp_type_str(p.type),
gtphub_side_idx_names[side_idx],
osmo_sockaddr_to_str(from_addr));
sgsn_sockaddr_to_str(from_addr));
return -1;
}
rate_ctr_add(&from_peer->counters_io->ctr[GTPH_CTR_BYTES_IN],
rate_ctr_add(rate_ctr_group_get_ctr(from_peer->counters_io, GTPH_CTR_BYTES_IN),
received);
rate_ctr_inc(&from_peer->counters_io->ctr[GTPH_CTR_PKTS_IN]);
rate_ctr_inc(rate_ctr_group_get_ctr(from_peer->counters_io, GTPH_CTR_PKTS_IN));
LOG(LOGL_DEBUG, "from %s peer: %s\n", gtphub_side_idx_names[side_idx],
gtphub_port_str(from_peer));
@@ -2260,9 +2246,9 @@ int gtphub_handle_buf(struct gtphub *hub,
if (p.tun) {
struct gtphub_tunnel_endpoint *te = &p.tun->endpoint[p.side_idx][p.plane_idx];
rate_ctr_add(&te->counters_io->ctr[GTPH_CTR_BYTES_IN],
rate_ctr_add(rate_ctr_group_get_ctr(te->counters_io, GTPH_CTR_BYTES_IN),
received);
rate_ctr_inc(&te->counters_io->ctr[GTPH_CTR_PKTS_IN]);
rate_ctr_inc(rate_ctr_group_get_ctr(te->counters_io, GTPH_CTR_PKTS_IN));
}
if ((!to_peer) && (side_idx == GTPH_SIDE_SGSN)) {
@@ -2297,7 +2283,7 @@ int gtphub_handle_buf(struct gtphub *hub,
!= 0)
return -1;
}
/* Either to_peer was resolved from an existing tunnel,
* or a PDP Ctx and thus a tunnel has just been created,
* or the tunnel has been deleted due to this message. */
@@ -2309,24 +2295,24 @@ int gtphub_handle_buf(struct gtphub *hub,
if (!to_peer_from_seq)
gtphub_map_seq(&p, from_peer, to_peer);
osmo_sockaddr_copy(to_addr, &to_peer->sa);
sgsn_sockaddr_copy(to_addr, &to_peer->sa);
*reply_buf = (uint8_t*)p.data;
if (received) {
rate_ctr_inc(&to_bind->counters_io->ctr[GTPH_CTR_PKTS_OUT]);
rate_ctr_add(&to_bind->counters_io->ctr[GTPH_CTR_BYTES_OUT],
rate_ctr_inc(rate_ctr_group_get_ctr(to_bind->counters_io, GTPH_CTR_PKTS_OUT));
rate_ctr_add(rate_ctr_group_get_ctr(to_bind->counters_io, GTPH_CTR_BYTES_OUT),
received);
rate_ctr_inc(&to_peer->counters_io->ctr[GTPH_CTR_PKTS_OUT]);
rate_ctr_add(&to_peer->counters_io->ctr[GTPH_CTR_BYTES_OUT],
rate_ctr_inc(rate_ctr_group_get_ctr(to_peer->counters_io, GTPH_CTR_PKTS_OUT));
rate_ctr_add(rate_ctr_group_get_ctr(to_peer->counters_io, GTPH_CTR_BYTES_OUT),
received);
}
if (p.tun) {
struct gtphub_tunnel_endpoint *te = &p.tun->endpoint[other_side_idx(p.side_idx)][p.plane_idx];
rate_ctr_inc(&te->counters_io->ctr[GTPH_CTR_PKTS_OUT]);
rate_ctr_add(&te->counters_io->ctr[GTPH_CTR_BYTES_OUT],
rate_ctr_inc(rate_ctr_group_get_ctr(te->counters_io, GTPH_CTR_PKTS_OUT));
rate_ctr_add(rate_ctr_group_get_ctr(te->counters_io, GTPH_CTR_BYTES_OUT),
received);
}
@@ -2335,7 +2321,7 @@ int gtphub_handle_buf(struct gtphub *hub,
(side_idx == GTPH_SIDE_SGSN)? "-->" : "<--",
gtphub_side_idx_names[other_side_idx(side_idx)],
p.header_tei, p.seq,
(int)received, osmo_sockaddr_to_str(to_addr));
(int)received, sgsn_sockaddr_to_str(to_addr));
return received;
}
@@ -2645,7 +2631,7 @@ static struct gtphub_peer_port *gtphub_port_find(const struct gtphub_bind *bind,
}
struct gtphub_peer_port *gtphub_port_find_sa(const struct gtphub_bind *bind,
const struct osmo_sockaddr *addr)
const struct sgsn_sockaddr *addr)
{
struct gsn_addr gsna;
uint16_t port;
@@ -2704,7 +2690,7 @@ static struct gtphub_peer_addr *gtphub_addr_have(struct gtphub *hub,
struct gtphub_peer *peer = gtphub_peer_new(hub, bind);
a = gtphub_peer_add_addr(peer, addr);
LOG(LOGL_DEBUG, "New peer address: %s %s\n",
bind->label,
gsn_addr_to_str(&a->addr));
@@ -2762,7 +2748,7 @@ struct gtphub_peer_port *gtphub_port_have(struct gtphub *hub,
/* Find a GGSN peer with a matching address. If the address is known but the
* port not, create a new port for that peer address. */
struct gtphub_peer_port *gtphub_known_addr_have_port(const struct gtphub_bind *bind,
const struct osmo_sockaddr *addr)
const struct sgsn_sockaddr *addr)
{
struct gtphub_peer_addr *pa;
struct gtphub_peer_port *pp;
@@ -2817,7 +2803,7 @@ static int gtphub_resolve_ggsn(struct gtphub *hub,
/* TODO move to osmocom/core/socket.c ? */
/* use this in osmo_sock_init() to remove dup. */
/* Internal: call getaddrinfo for osmo_sockaddr_init(). The caller is required
/* Internal: call getaddrinfo for sgsn_sockaddr_init(). The caller is required
to call freeaddrinfo(*result), iff zero is returned. */
static int _osmo_getaddrinfo(struct addrinfo **result,
uint16_t family, uint16_t type, uint8_t proto,
@@ -2844,7 +2830,7 @@ static int _osmo_getaddrinfo(struct addrinfo **result,
}
/* TODO move to osmocom/core/socket.c ? */
int osmo_sockaddr_init(struct osmo_sockaddr *addr,
int sgsn_sockaddr_init(struct sgsn_sockaddr *addr,
uint16_t family, uint16_t type, uint8_t proto,
const char *host, uint16_t port)
{
@@ -2865,9 +2851,9 @@ int osmo_sockaddr_init(struct osmo_sockaddr *addr,
return 0;
}
int osmo_sockaddr_to_strs(char *addr_str, size_t addr_str_len,
int sgsn_sockaddr_to_strs(char *addr_str, size_t addr_str_len,
char *port_str, size_t port_str_len,
const struct osmo_sockaddr *addr,
const struct sgsn_sockaddr *addr,
int flags)
{
int rc;
@@ -2896,14 +2882,14 @@ int osmo_sockaddr_to_strs(char *addr_str, size_t addr_str_len,
return rc;
}
const char *osmo_sockaddr_to_strb(const struct osmo_sockaddr *addr,
const char *sgsn_sockaddr_to_strb(const struct sgsn_sockaddr *addr,
char *buf, size_t buf_len)
{
char portbuf[6];
const int portbuf_len = 6;
OSMO_ASSERT(buf_len > portbuf_len);
char *portbuf = buf + buf_len - portbuf_len;
buf_len -= portbuf_len;
if (osmo_sockaddr_to_strs(buf, buf_len,
if (sgsn_sockaddr_to_strs(buf, buf_len,
portbuf, portbuf_len,
addr,
NI_NUMERICHOST | NI_NUMERICSERV))
@@ -2918,17 +2904,17 @@ const char *osmo_sockaddr_to_strb(const struct osmo_sockaddr *addr,
return buf;
}
const char *osmo_sockaddr_to_str(const struct osmo_sockaddr *addr)
const char *sgsn_sockaddr_to_str(const struct sgsn_sockaddr *addr)
{
static char buf[256];
const char *result = osmo_sockaddr_to_strb(addr, buf, sizeof(buf));
const char *result = sgsn_sockaddr_to_strb(addr, buf, sizeof(buf));
if (! result)
return "(invalid)";
return result;
}
int osmo_sockaddr_cmp(const struct osmo_sockaddr *a,
const struct osmo_sockaddr *b)
int sgsn_sockaddr_cmp(const struct sgsn_sockaddr *a,
const struct sgsn_sockaddr *b)
{
if (a == b)
return 0;
@@ -2938,7 +2924,7 @@ int osmo_sockaddr_cmp(const struct osmo_sockaddr *a,
return 1;
if (a->l != b->l) {
/* Lengths are not the same, but determine the order. Will
* anyone ever sort a list by osmo_sockaddr though...? */
* anyone ever sort a list by sgsn_sockaddr though...? */
int cmp = memcmp(&a->a, &b->a, (a->l < b->l)? a->l : b->l);
if (cmp == 0) {
if (a->l < b->l)
@@ -2951,8 +2937,8 @@ int osmo_sockaddr_cmp(const struct osmo_sockaddr *a,
return memcmp(&a->a, &b->a, a->l);
}
void osmo_sockaddr_copy(struct osmo_sockaddr *dst,
const struct osmo_sockaddr *src)
void sgsn_sockaddr_copy(struct sgsn_sockaddr *dst,
const struct sgsn_sockaddr *src)
{
OSMO_ASSERT(src->l <= sizeof(dst->a));
memcpy(&dst->a, &src->a, src->l);

View File

@@ -28,11 +28,12 @@
#include <string.h>
#include <unistd.h>
#include <osmocom/sgsn/gtphub.h>
#include <osmocom/gtphub/gtphub.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/core/utils.h>
#include <osmocom/gsm/apn.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
/* TODO split GRX ares from sgsn into a separate struct and allow use without
* globals. */
@@ -56,8 +57,8 @@ struct ggsn_lookup {
struct gtphub *hub;
char imsi_str[GSM23003_IMSI_MAX_DIGITS+1];
char apn_ni_str[GSM_APN_LENGTH];
char apn_oi_str[GSM_APN_LENGTH];
char apn_ni_str[APN_MAXLEN+1];
char apn_oi_str[APN_MAXLEN+1];
int have_3dig_mnc;
};

View File

@@ -34,6 +34,7 @@
#include <osmocom/core/logging.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/msgb.h>
#include <osmocom/vty/logging.h>
#include <osmocom/vty/telnet_interface.h>
@@ -41,10 +42,10 @@
#include <osmocom/vty/misc.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gtphub.h>
#include <osmocom/gtphub/gtphub.h>
#include <osmocom/sgsn/vty.h>
#include "../../bscconfig.h"
#include "../../config.h"
#if BUILD_IU
#include <osmocom/sigtran/osmo_ss7.h>
@@ -95,11 +96,11 @@ void log_cfg(struct gtphub_cfg *cfg)
}
}
static void signal_handler(int signal)
static void signal_handler(int signum)
{
fprintf(stdout, "signal %d received\n", signal);
fprintf(stdout, "signal %d received\n", signum);
switch (signal) {
switch (signum) {
case SIGINT:
case SIGTERM:
osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL);
@@ -107,8 +108,16 @@ static void signal_handler(int signal)
exit(0);
break;
case SIGABRT:
/* in case of abort, we want to obtain a talloc report
* and then return to the caller, who will abort the process */
/* in case of abort, we want to obtain a talloc report and
* then run default SIGABRT handler, who will generate coredump
* and abort the process. abort() should do this for us after we
* return, but program wouldn't exit if an external SIGABRT is
* received.
*/
talloc_report_full(osmo_gtphub_ctx, stderr);
signal(SIGABRT, SIG_DFL);
raise(SIGABRT);
break;
case SIGUSR1:
case SIGUSR2:
talloc_report_full(osmo_gtphub_ctx, stderr);
@@ -118,44 +127,12 @@ static void signal_handler(int signal)
}
}
#if BUILD_IU
int gtphub_vty_go_parent(struct vty *vty)
{
switch (vty->node) {
default:
osmo_ss7_vty_go_parent(vty);
}
return vty->node;
}
#endif
int gtphub_vty_is_config_node(struct vty *vty, int node)
{
/* Check if libosmo-sccp declares the node in
* question as config node */
#if BUILD_IU
if (osmo_ss7_is_config_node(vty, node))
return 1;
#endif
switch (node) {
/* add items that are not config */
case CONFIG_NODE:
return 0;
default:
return 1;
}
}
static struct vty_app_info vty_info = {
.name = "OsmoGTPhub",
.version = PACKAGE_VERSION,
#if BUILD_IU
.go_parent_cb = gtphub_vty_go_parent,
.go_parent_cb = osmo_ss7_vty_go_parent,
#endif
.is_config_node = gtphub_vty_is_config_node,
};
struct cmdline_cfg {
@@ -322,6 +299,11 @@ static void handle_options(struct cmdline_cfg *ccfg, int argc, char **argv)
break;
}
}
if (argc > optind) {
fprintf(stderr, "Unsupported positional arguments on command line\n");
exit(2);
}
}
int main(int argc, char **argv)
@@ -372,8 +354,7 @@ int main(int argc, char **argv)
}
/* start telnet after reading config for vty_get_bind_addr() */
rc = telnet_init_dynif(osmo_gtphub_ctx, 0, vty_get_bind_addr(),
OSMO_VTY_PORT_GTPHUB);
rc = telnet_init_default(osmo_gtphub_ctx, NULL, OSMO_VTY_PORT_GTPHUB);
if (rc < 0)
exit(1);

View File

@@ -25,7 +25,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <osmocom/sgsn/gtphub.h>
#include <errno.h>
#include <string.h>
#include <osmocom/core/utils.h>
#include <osmocom/gtphub/gtphub.h>
#include <osmocom/sgsn/debug.h>
/* Convenience makro, note: only within this C file. */
@@ -33,13 +38,13 @@
LOGP(DGTPHUB, level, fmt, ##args)
int gtphub_write(const struct osmo_fd *to,
const struct osmo_sockaddr *to_addr,
const struct sgsn_sockaddr *to_addr,
const uint8_t *buf, size_t buf_len)
{
errno = 0;
ssize_t sent = sendto(to->fd, buf, buf_len, 0,
(struct sockaddr*)&to_addr->a, to_addr->l);
LOG(LOGL_DEBUG, "to %s\n", osmo_sockaddr_to_str(to_addr));
LOG(LOGL_DEBUG, "to %s\n", sgsn_sockaddr_to_str(to_addr));
if (sent == -1) {
LOG(LOGL_ERROR, "error: %s\n", strerror(errno));

View File

@@ -31,7 +31,7 @@
#include <osmocom/vty/misc.h>
#include <osmocom/sgsn/vty.h>
#include <osmocom/sgsn/gtphub.h>
#include <osmocom/gtphub/gtphub.h>
/* TODO split GRX ares from sgsn into a separate struct and allow use without
* globals. */

View File

@@ -40,14 +40,15 @@ bin_PROGRAMS = \
$(NULL)
osmo_sgsn_SOURCES = \
gprs_gb.c \
apn.c \
gprs_bssgp.c \
gprs_gmm_attach.c \
gprs_gmm.c \
gprs_gmm_fsm.c \
gprs_gmm_util.c \
gprs_mm_state_gb_fsm.c \
gprs_mm_state_iu_fsm.c \
gprs_ranap.c \
gprs_sgsn.c \
gprs_ns.c \
gprs_routing_area.c \
gprs_sm.c \
gprs_sndcp.c \
gprs_sndcp_comp.c \
@@ -55,15 +56,21 @@ osmo_sgsn_SOURCES = \
gprs_sndcp_pcomp.c \
gprs_sndcp_vty.c \
gprs_sndcp_xid.c \
gtp_ggsn.c \
gtp_mme.c \
sgsn.c \
sgsn_main.c \
sgsn_vty.c \
sgsn_libgtp.c \
gprs_llc.c \
gprs_llc_vty.c \
mmctx.c \
pdpctx.c \
sgsn_ctrl.c \
sgsn_auth.c \
gprs_subscriber.c \
sgsn_cdr.c \
sgsn_rim.c \
slhc.c \
gprs_llc_xid.c \
v42bis.c \
@@ -74,7 +81,6 @@ osmo_sgsn_LDADD = \
$(top_builddir)/src/gprs/gprs_utils.o \
$(top_builddir)/src/gprs/sgsn_ares.o \
$(OSMO_LIBS) \
$(LIBOSMOABIS_LIBS) \
$(LIBOSMOGSUPCLIENT_LIBS) \
$(LIBCARES_LIBS) \
$(LIBGTP_LIBS) \
@@ -87,4 +93,14 @@ osmo_sgsn_LDADD += \
$(LIBOSMORANAP_LIBS) \
$(LIBASN1C_LIBS) \
$(NULL)
osmo_sgsn_SOURCES += \
gprs_mm_state_iu_fsm.c \
gprs_ranap.c \
iu_client.c \
iu_rnc.c \
iu_rnc_fsm.c \
sccp.c \
$(NULL)
endif

123
src/sgsn/apn.c Normal file
View File

@@ -0,0 +1,123 @@
/* APN contexts */
/* (C) 2009-2015 by Harald Welte <laforge@gnumonks.org>
* (C) 2010 by On-Waves
* (C) 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <string.h>
#include <talloc.h>
#include <osmocom/sgsn/apn.h>
#include <osmocom/sgsn/sgsn.h>
static struct apn_ctx *sgsn_apn_ctx_alloc(const char *ap_name, const char *imsi_prefix)
{
struct apn_ctx *actx;
actx = talloc_zero(sgsn, struct apn_ctx);
if (!actx)
return NULL;
actx->name = talloc_strdup(actx, ap_name);
actx->imsi_prefix = talloc_strdup(actx, imsi_prefix);
llist_add_tail(&actx->list, &sgsn->apn_list);
return actx;
}
void sgsn_apn_ctx_free(struct apn_ctx *actx)
{
llist_del(&actx->list);
talloc_free(actx);
}
struct apn_ctx *sgsn_apn_ctx_match(const char *name, const char *imsi)
{
struct apn_ctx *actx;
struct apn_ctx *found_actx = NULL;
size_t imsi_prio = 0;
size_t name_prio = 0;
size_t name_req_len = strlen(name);
llist_for_each_entry(actx, &sgsn->apn_list, list) {
size_t name_ref_len, imsi_ref_len;
const char *name_ref_start, *name_match_start;
imsi_ref_len = strlen(actx->imsi_prefix);
if (strncmp(actx->imsi_prefix, imsi, imsi_ref_len) != 0)
continue;
if (imsi_ref_len < imsi_prio)
continue;
/* IMSI matches */
name_ref_start = &actx->name[0];
if (name_ref_start[0] == '*') {
/* Suffix match */
name_ref_start += 1;
name_ref_len = strlen(name_ref_start);
if (name_ref_len > name_req_len)
continue;
} else {
name_ref_len = strlen(name_ref_start);
if (name_ref_len != name_req_len)
continue;
}
name_match_start = name + (name_req_len - name_ref_len);
if (strcasecmp(name_match_start, name_ref_start) != 0)
continue;
/* IMSI and name match */
if (imsi_ref_len == imsi_prio && name_ref_len < name_prio)
/* Lower priority, skip */
continue;
imsi_prio = imsi_ref_len;
name_prio = name_ref_len;
found_actx = actx;
}
return found_actx;
}
struct apn_ctx *sgsn_apn_ctx_by_name(const char *name, const char *imsi_prefix)
{
struct apn_ctx *actx;
llist_for_each_entry(actx, &sgsn->apn_list, list) {
if (strcasecmp(name, actx->name) == 0 &&
strcasecmp(imsi_prefix, actx->imsi_prefix) == 0)
return actx;
}
return NULL;
}
struct apn_ctx *sgsn_apn_ctx_find_alloc(const char *name, const char *imsi_prefix)
{
struct apn_ctx *actx;
actx = sgsn_apn_ctx_by_name(name, imsi_prefix);
if (!actx)
actx = sgsn_apn_ctx_alloc(name, imsi_prefix);
return actx;
}

130
src/sgsn/gprs_bssgp.c Normal file
View File

@@ -0,0 +1,130 @@
/* GPRS BSSGP protocol implementation as per 3GPP TS 08.18 */
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
* (C) 2010 by On-Waves
* (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <osmocom/core/prim.h>
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/gprs/gprs_ns2.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/sgsn/gprs_llc.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/gprs_routing_area.h>
#include <osmocom/sgsn/sgsn_rim.h>
#include <osmocom/sgsn/mmctx.h>
#include <osmocom/sgsn/debug.h>
static int bssgp_nm_bvc_reset_ind(struct osmo_bssgp_prim *bp)
{
struct osmo_cell_global_id_ps cgi_ps = {};
/* Signalling: BVCI == 0, no CGI-PS
* PtP BVCI: BVCI != 0, CGI-PS */
if (bp->bvci == 0) {
sgsn_ra_geran_bvc_sign_reset_ind(bp->nsei);
return 0;
}
if (!bp->tp)
return -EINVAL;
if (!TLVP_PRES_LEN(bp->tp, BSSGP_IE_CELL_ID, 8))
return -EINVAL;
bssgp_parse_cell_id2(&cgi_ps.rai, &cgi_ps.cell_identity, TLVP_VAL(bp->tp, BSSGP_IE_CELL_ID), 8);
return sgsn_ra_geran_bvc_cell_reset_ind(bp->nsei, bp->bvci, &cgi_ps);
}
/* call-back function for the BSSGP protocol */
int sgsn_bssgp_rx_prim(struct osmo_prim_hdr *oph)
{
struct osmo_bssgp_prim *bp;
struct osmo_routing_area_id rai = {};
bp = container_of(oph, struct osmo_bssgp_prim, oph);
switch (oph->sap) {
case SAP_BSSGP_LL:
switch (oph->primitive) {
case PRIM_BSSGP_UL_UD:
return gprs_llc_rcvmsg(oph->msg, bp->tp);
}
break;
case SAP_BSSGP_GMM:
gprs_rai_to_osmo(&rai, bp->ra_id);
switch (oph->primitive) {
case PRIM_BSSGP_GMM_SUSPEND:
return gprs_gmm_rx_suspend(&rai, bp->tlli);
case PRIM_BSSGP_GMM_RESUME:
return gprs_gmm_rx_resume(&rai, bp->tlli,
bp->u.resume.suspend_ref);
}
break;
case SAP_BSSGP_NM:
switch (oph->primitive) {
case PRIM_NM_BVC_RESET:
if (oph->operation == PRIM_OP_INDICATION)
bssgp_nm_bvc_reset_ind(bp);
break;
case PRIM_NM_BVC_BLOCK:
case PRIM_NM_BVC_UNBLOCK:
case PRIM_NM_STATUS:
case PRIM_NM_LLC_DISCARDED:
break;
}
break;
case SAP_BSSGP_RIM:
return sgsn_rim_rx_from_gb(bp, oph->msg);
}
return 0;
}
int sgsn_bssgp_page_ps_bvci(struct sgsn_mm_ctx *mmctx, uint16_t nsei, uint16_t bvci)
{
struct bssgp_paging_info pinfo;
/* initiate PS PAGING procedure */
memset(&pinfo, 0, sizeof(pinfo));
pinfo.mode = BSSGP_PAGING_PS;
pinfo.scope = BSSGP_PAGING_BVCI;
pinfo.bvci = bvci;
pinfo.imsi = mmctx->imsi;
pinfo.ptmsi = &mmctx->p_tmsi;
pinfo.drx_params = mmctx->drx_parms;
pinfo.qos[0] = 0; // FIXME
return bssgp_tx_paging(nsei, 0, &pinfo);
}
/* called by the bssgp layer to send NS PDUs */
int sgsn_bssgp_dispatch_ns_unitdata_req_cb(void *ctx, struct msgb *msg)
{
struct gprs_ns2_inst *nsi = (struct gprs_ns2_inst *) ctx;
struct osmo_gprs_ns2_prim nsp = {};
nsp.nsei = msgb_nsei(msg);
nsp.bvci = msgb_bvci(msg);
osmo_prim_init(&nsp.oph, SAP_NS, GPRS_NS2_PRIM_UNIT_DATA, PRIM_OP_REQUEST, msg);
return gprs_ns2_recv_prim(nsi, &nsp.oph);
}

Some files were not shown because too many files have changed in this diff Show More