From 90843964679f35ef4d11c2788debcba976f500bc Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Mon, 4 Sep 2017 15:04:35 +0200 Subject: rename include/openbsc to include/osmocom/msc Change-Id: I1f96a1285bbd1b4607614856bca935d5c26e2da9 --- include/osmocom/msc/Makefile.am | 82 ++ include/osmocom/msc/a_iface.h | 76 ++ include/osmocom/msc/a_iface_bssap.h | 41 + include/osmocom/msc/a_reset.h | 63 ++ include/osmocom/msc/abis_nm.h | 180 ++++ include/osmocom/msc/abis_om2000.h | 129 +++ include/osmocom/msc/abis_rsl.h | 117 +++ include/osmocom/msc/arfcn_range_encode.h | 26 + include/osmocom/msc/auth.h | 22 + include/osmocom/msc/bsc_api.h | 58 ++ include/osmocom/msc/bsc_msc.h | 77 ++ include/osmocom/msc/bsc_msc_data.h | 174 ++++ include/osmocom/msc/bsc_msg_filter.h | 107 +++ include/osmocom/msc/bsc_rll.h | 19 + include/osmocom/msc/bss.h | 20 + include/osmocom/msc/bts_ipaccess_nanobts_omlattr.h | 32 + include/osmocom/msc/chan_alloc.h | 54 ++ include/osmocom/msc/common.h | 6 + include/osmocom/msc/common_bsc.h | 9 + include/osmocom/msc/common_cs.h | 27 + include/osmocom/msc/crc24.h | 10 + include/osmocom/msc/ctrl.h | 4 + include/osmocom/msc/db.h | 59 ++ include/osmocom/msc/debug.h | 47 + include/osmocom/msc/e1_config.h | 11 + include/osmocom/msc/gsm_04_08.h | 85 ++ include/osmocom/msc/gsm_04_11.h | 53 ++ include/osmocom/msc/gsm_04_14.h | 15 + include/osmocom/msc/gsm_04_80.h | 25 + include/osmocom/msc/gsm_data.h | 691 ++++++++++++++ include/osmocom/msc/gsm_data_shared.h | 1003 ++++++++++++++++++++ include/osmocom/msc/gsm_subscriber.h | 68 ++ include/osmocom/msc/gsup_client.h | 63 ++ include/osmocom/msc/gtphub.h | 523 ++++++++++ include/osmocom/msc/handover.h | 14 + include/osmocom/msc/handover_decision.h | 7 + include/osmocom/msc/ipaccess.h | 52 + include/osmocom/msc/iu_dummy.h | 51 + include/osmocom/msc/iucs.h | 7 + include/osmocom/msc/iucs_ranap.h | 7 + include/osmocom/msc/meas_feed.h | 41 + include/osmocom/msc/meas_rep.h | 67 ++ include/osmocom/msc/misdn.h | 27 + include/osmocom/msc/mncc.h | 215 +++++ include/osmocom/msc/mncc_int.h | 14 + include/osmocom/msc/msc_ifaces.h | 42 + include/osmocom/msc/network_listen.h | 16 + include/osmocom/msc/oap_client.h | 82 ++ include/osmocom/msc/openbscdefines.h | 34 + include/osmocom/msc/osmo_bsc.h | 75 ++ include/osmocom/msc/osmo_bsc_grace.h | 35 + include/osmocom/msc/osmo_bsc_reset.h | 34 + include/osmocom/msc/osmo_bsc_rf.h | 66 ++ include/osmocom/msc/osmo_bsc_sigtran.h | 48 + include/osmocom/msc/osmo_msc.h | 99 ++ include/osmocom/msc/osmux.h | 41 + include/osmocom/msc/paging.h | 76 ++ include/osmocom/msc/rest_octets.h | 139 +++ include/osmocom/msc/rrlp.h | 7 + include/osmocom/msc/rs232.h | 9 + include/osmocom/msc/rtp_proxy.h | 95 ++ include/osmocom/msc/signal.h | 260 +++++ include/osmocom/msc/silent_call.h | 15 + include/osmocom/msc/slhc.h | 187 ++++ include/osmocom/msc/smpp.h | 4 + include/osmocom/msc/sms_queue.h | 17 + include/osmocom/msc/socket.h | 14 + include/osmocom/msc/system_information.h | 22 + include/osmocom/msc/transaction.h | 103 ++ include/osmocom/msc/trau_mux.h | 70 ++ include/osmocom/msc/trau_upqueue.h | 7 + include/osmocom/msc/ussd.h | 10 + include/osmocom/msc/vlr.h | 422 ++++++++ include/osmocom/msc/vty.h | 54 ++ 74 files changed, 6561 insertions(+) create mode 100644 include/osmocom/msc/Makefile.am create mode 100644 include/osmocom/msc/a_iface.h create mode 100644 include/osmocom/msc/a_iface_bssap.h create mode 100644 include/osmocom/msc/a_reset.h create mode 100644 include/osmocom/msc/abis_nm.h create mode 100644 include/osmocom/msc/abis_om2000.h create mode 100644 include/osmocom/msc/abis_rsl.h create mode 100644 include/osmocom/msc/arfcn_range_encode.h create mode 100644 include/osmocom/msc/auth.h create mode 100644 include/osmocom/msc/bsc_api.h create mode 100644 include/osmocom/msc/bsc_msc.h create mode 100644 include/osmocom/msc/bsc_msc_data.h create mode 100644 include/osmocom/msc/bsc_msg_filter.h create mode 100644 include/osmocom/msc/bsc_rll.h create mode 100644 include/osmocom/msc/bss.h create mode 100644 include/osmocom/msc/bts_ipaccess_nanobts_omlattr.h create mode 100644 include/osmocom/msc/chan_alloc.h create mode 100644 include/osmocom/msc/common.h create mode 100644 include/osmocom/msc/common_bsc.h create mode 100644 include/osmocom/msc/common_cs.h create mode 100644 include/osmocom/msc/crc24.h create mode 100644 include/osmocom/msc/ctrl.h create mode 100644 include/osmocom/msc/db.h create mode 100644 include/osmocom/msc/debug.h create mode 100644 include/osmocom/msc/e1_config.h create mode 100644 include/osmocom/msc/gsm_04_08.h create mode 100644 include/osmocom/msc/gsm_04_11.h create mode 100644 include/osmocom/msc/gsm_04_14.h create mode 100644 include/osmocom/msc/gsm_04_80.h create mode 100644 include/osmocom/msc/gsm_data.h create mode 100644 include/osmocom/msc/gsm_data_shared.h create mode 100644 include/osmocom/msc/gsm_subscriber.h create mode 100644 include/osmocom/msc/gsup_client.h create mode 100644 include/osmocom/msc/gtphub.h create mode 100644 include/osmocom/msc/handover.h create mode 100644 include/osmocom/msc/handover_decision.h create mode 100644 include/osmocom/msc/ipaccess.h create mode 100644 include/osmocom/msc/iu_dummy.h create mode 100644 include/osmocom/msc/iucs.h create mode 100644 include/osmocom/msc/iucs_ranap.h create mode 100644 include/osmocom/msc/meas_feed.h create mode 100644 include/osmocom/msc/meas_rep.h create mode 100644 include/osmocom/msc/misdn.h create mode 100644 include/osmocom/msc/mncc.h create mode 100644 include/osmocom/msc/mncc_int.h create mode 100644 include/osmocom/msc/msc_ifaces.h create mode 100644 include/osmocom/msc/network_listen.h create mode 100644 include/osmocom/msc/oap_client.h create mode 100644 include/osmocom/msc/openbscdefines.h create mode 100644 include/osmocom/msc/osmo_bsc.h create mode 100644 include/osmocom/msc/osmo_bsc_grace.h create mode 100644 include/osmocom/msc/osmo_bsc_reset.h create mode 100644 include/osmocom/msc/osmo_bsc_rf.h create mode 100644 include/osmocom/msc/osmo_bsc_sigtran.h create mode 100644 include/osmocom/msc/osmo_msc.h create mode 100644 include/osmocom/msc/osmux.h create mode 100644 include/osmocom/msc/paging.h create mode 100644 include/osmocom/msc/rest_octets.h create mode 100644 include/osmocom/msc/rrlp.h create mode 100644 include/osmocom/msc/rs232.h create mode 100644 include/osmocom/msc/rtp_proxy.h create mode 100644 include/osmocom/msc/signal.h create mode 100644 include/osmocom/msc/silent_call.h create mode 100644 include/osmocom/msc/slhc.h create mode 100644 include/osmocom/msc/smpp.h create mode 100644 include/osmocom/msc/sms_queue.h create mode 100644 include/osmocom/msc/socket.h create mode 100644 include/osmocom/msc/system_information.h create mode 100644 include/osmocom/msc/transaction.h create mode 100644 include/osmocom/msc/trau_mux.h create mode 100644 include/osmocom/msc/trau_upqueue.h create mode 100644 include/osmocom/msc/ussd.h create mode 100644 include/osmocom/msc/vlr.h create mode 100644 include/osmocom/msc/vty.h (limited to 'include/osmocom/msc') diff --git a/include/osmocom/msc/Makefile.am b/include/osmocom/msc/Makefile.am new file mode 100644 index 000000000..6e7aa384b --- /dev/null +++ b/include/osmocom/msc/Makefile.am @@ -0,0 +1,82 @@ +noinst_HEADERS = \ + abis_nm.h \ + abis_om2000.h \ + abis_rsl.h \ + a_iface.h \ + a_iface_bssap.h \ + arfcn_range_encode.h \ + auth.h \ + bsc_msc.h \ + bsc_msg_filter.h \ + bsc_rll.h \ + bss.h \ + bts_ipaccess_nanobts_omlattr.h \ + chan_alloc.h \ + common.h \ + common_bsc.h \ + common_cs.h \ + crc24.h \ + ctrl.h \ + db.h \ + debug.h \ + e1_config.h \ + gsm_04_08.h \ + gsm_04_11.h \ + gsm_04_14.h \ + gsm_04_80.h \ + gsm_data.h \ + gsm_data_shared.h \ + gsm_subscriber.h \ + gsup_client.h \ + handover.h \ + handover_decision.h \ + ipaccess.h \ + iucs.h \ + iucs_ranap.h \ + iu_dummy.h \ + meas_feed.h \ + meas_rep.h \ + misdn.h \ + mncc.h \ + mncc_int.h \ + msc_ifaces.h \ + network_listen.h \ + oap_client.h \ + openbscdefines.h \ + osmo_bsc.h \ + osmo_bsc_grace.h \ + a_reset.h \ + osmo_bsc_rf.h \ + osmo_msc.h \ + osmo_bsc_sigtran.h \ + bsc_msc_data.h \ + osmux.h \ + paging.h \ + rest_octets.h \ + rrlp.h \ + rs232.h \ + rtp_proxy.h \ + signal.h \ + silent_call.h \ + slhc.h \ + smpp.h \ + sms_queue.h \ + socket.h \ + system_information.h \ + transaction.h \ + trau_mux.h \ + trau_upqueue.h \ + ussd.h \ + vlr.h \ + vty.h \ + $(NULL) + +openbsc_HEADERS = \ + bsc_api.h \ + gsm_04_08.h \ + meas_rep.h \ + $(NULL) + +# DO NOT add a newline and '$(NULL)' to this line. That would add a trailing +# space to the directory installed: $prefix/include/'openbsc ' +openbscdir = $(includedir)/openbsc diff --git a/include/osmocom/msc/a_iface.h b/include/osmocom/msc/a_iface.h new file mode 100644 index 000000000..a49ede25e --- /dev/null +++ b/include/osmocom/msc/a_iface.h @@ -0,0 +1,76 @@ +/* (C) 2017 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Philipp Maier + * + * 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 . + * + */ + +#pragma once + +#include + +/* A struct to keep a context information about the BSCs we are associated with */ +struct bsc_context { + struct llist_head list; + + /* Holds a copy of the sccp address of the BSC, + * this address will become known as soon as + * a remote BSC tries to make a connection or + * sends a RESET request via UNIDATA */ + struct osmo_sccp_addr bsc_addr; + + /* Holds a copy of the our local MSC address, + * this will be the sccp-address that is associated + * with the A interface */ + struct osmo_sccp_addr msc_addr; + + /* A pointer to the reset handler FSM, the + * state machine is allocated when the BSC + * is registerd. */ + struct a_reset_ctx *reset; + + /* A pointer to the sccp_user that is associated + * with the A interface. We need this information + * to send the resets and to send paging requests */ + struct osmo_sccp_user *sccp_user; +}; + +/* Initalize A interface connection between to MSC and BSC */ +int a_init(struct osmo_sccp_instance *sccp, struct gsm_network *network); + +/* Send DTAP message via A-interface */ +int a_iface_tx_dtap(struct msgb *msg); + +/* Send Cipher mode command via A-interface */ +int a_iface_tx_cipher_mode(const struct gsm_subscriber_connection *conn, + int cipher, const const uint8_t *key, int len, int include_imeisv); + +/* Page a subscriber via A-interface */ +int a_iface_tx_paging(const char *imsi, uint32_t tmsi, uint16_t lac); + +/* Send assignment request via A-interface */ +int a_iface_tx_assignment(const struct gsm_trans *trans); + +/* Send clear command via A-interface */ +int a_iface_tx_clear_cmd(struct gsm_subscriber_connection *conn); + +/* Clear all subscriber connections on a specified BSC + * (Helper function for a_iface_bssap.c) */ +void a_clear_all(struct osmo_sccp_user *scu, const struct osmo_sccp_addr *bsc_addr); + +/* Delete info of a closed connection from the active connection list + * (Helper function for a_iface_bssap.c) */ +void a_delete_bsc_con(uint32_t conn_id); diff --git a/include/osmocom/msc/a_iface_bssap.h b/include/osmocom/msc/a_iface_bssap.h new file mode 100644 index 000000000..237c618fd --- /dev/null +++ b/include/osmocom/msc/a_iface_bssap.h @@ -0,0 +1,41 @@ +/* (C) 2017 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Philipp Maier + * + * 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 . + * + */ + +#pragma once + +/* Note: The structs and functions presented in this header file are intended + * to be used only by a_iface.c. */ + +/* A structure to hold tha most basic information about a sigtran connection + * we use this struct internally here to pass connection data around */ +struct a_conn_info { + struct osmo_sccp_addr *msc_addr; + struct osmo_sccp_addr *bsc_addr; + uint32_t conn_id; + struct gsm_network *network; + struct a_reset_ctx *reset; +}; + +/* Receive incoming connection less data messages via sccp */ +void sccp_rx_udt(struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg); + +/* Receive incoming connection oriented data messages via sccp */ +int sccp_rx_dt(struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg); + diff --git a/include/osmocom/msc/a_reset.h b/include/osmocom/msc/a_reset.h new file mode 100644 index 000000000..7aaab0620 --- /dev/null +++ b/include/osmocom/msc/a_reset.h @@ -0,0 +1,63 @@ +/* (C) 2017 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Philipp Maier + * + * 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 . + * + */ + +#pragma once + + + +/* Reset context data (callbacks, state machine etc...) */ +struct a_reset_ctx { + + /* FSM instance, which handles the reset procedure */ + struct osmo_fsm_inst *fsm; + + /* Connection failure counter. When this counter + * reaches a certain threshold, the reset procedure + * will be triggered */ + int conn_loss_counter; + + /* A human readable name to display in the logs */ + char name[256]; + + /* Callback function to be called when a connection + * failure is detected and a rest must occur */ + void (*cb)(void *priv); + + /* Privated data for the callback function */ + void *priv; +}; + +/* Create and start state machine which handles the reset/reset-ack procedure */ +struct a_reset_ctx *a_reset_alloc(const void *ctx, const char *name, void *cb, void *priv); + +/* Tear down state machine */ +void a_reset_free(struct a_reset_ctx *reset); + +/* Confirm that we sucessfully received a reset acknowlege message */ +void a_reset_ack_confirm(struct a_reset_ctx *reset); + +/* Report a failed connection */ +void a_reset_conn_fail(struct a_reset_ctx *reset); + +/* Report a successful connection */ +void a_reset_conn_success(struct a_reset_ctx *reset); + +/* Check if we have a connection to a specified msc */ +bool a_reset_conn_ready(struct a_reset_ctx *reset); diff --git a/include/osmocom/msc/abis_nm.h b/include/osmocom/msc/abis_nm.h new file mode 100644 index 000000000..25819626e --- /dev/null +++ b/include/osmocom/msc/abis_nm.h @@ -0,0 +1,180 @@ +/* GSM Network Management messages on the A-bis interface + * 3GPP TS 12.21 version 8.0.0 Release 1999 / ETSI TS 100 623 V8.0.0 */ + +/* (C) 2008-2009 by Harald Welte + * 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 . + * + */ + +#ifndef _NM_H +#define _NM_H + +#include +#include +#include + +#include + +/* max number of attributes represented as 3GPP TS 52.021 ยง9.4.62 SW Description array */ +#define MAX_BTS_ATTR 5 + +struct cell_global_id { + uint16_t mcc; + uint16_t mnc; + uint16_t lac; + uint16_t ci; +}; + +/* The BCCH info from an ip.access test, in host byte order + * and already parsed... */ +struct ipac_bcch_info { + struct llist_head list; + + uint16_t info_type; + uint8_t freq_qual; + uint16_t arfcn; + uint8_t rx_lev; + uint8_t rx_qual; + int16_t freq_err; + uint16_t frame_offset; + uint32_t frame_nr_offset; + uint8_t bsic; + struct cell_global_id cgi; + uint8_t ba_list_si2[16]; + uint8_t ba_list_si2bis[16]; + uint8_t ba_list_si2ter[16]; + uint8_t ca_list_si1[16]; +}; + +/* PUBLIC */ + +struct msgb; + +struct abis_nm_cfg { + /* callback for unidirectional reports */ + int (*report_cb)(struct msgb *, + struct abis_om_fom_hdr *); + /* callback for software activate requests from BTS */ + int (*sw_act_req)(struct msgb *); +}; + +extern int abis_nm_rcvmsg(struct msgb *msg); + +int abis_nm_tlv_parse(struct tlv_parsed *tp, struct gsm_bts *bts, const uint8_t *buf, int len); +int abis_nm_rx(struct msgb *msg); +int abis_nm_opstart(struct gsm_bts *bts, uint8_t obj_class, uint8_t i0, uint8_t i1, uint8_t i2); +int abis_nm_chg_adm_state(struct gsm_bts *bts, uint8_t obj_class, uint8_t i0, + uint8_t i1, uint8_t i2, enum abis_nm_adm_state adm_state); +int abis_nm_establish_tei(struct gsm_bts *bts, uint8_t trx_nr, + uint8_t e1_port, uint8_t e1_timeslot, uint8_t e1_subslot, + uint8_t tei); +int abis_nm_conn_terr_sign(struct gsm_bts_trx *trx, + uint8_t e1_port, uint8_t e1_timeslot, uint8_t e1_subslot); +int abis_nm_conn_terr_traf(struct gsm_bts_trx_ts *ts, + uint8_t e1_port, uint8_t e1_timeslot, + uint8_t e1_subslot); +int abis_nm_get_attr(struct gsm_bts *bts, uint8_t obj_class, + uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr, + const uint8_t *attr, uint8_t attr_len); +int abis_nm_set_bts_attr(struct gsm_bts *bts, uint8_t *attr, int attr_len); +int abis_nm_set_radio_attr(struct gsm_bts_trx *trx, uint8_t *attr, int attr_len); +int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, uint8_t chan_comb); +int abis_nm_sw_act_req_ack(struct gsm_bts *bts, uint8_t obj_class, uint8_t i1, + uint8_t i2, uint8_t i3, int nack, uint8_t *attr, int att_len); +int abis_nm_raw_msg(struct gsm_bts *bts, int len, uint8_t *msg); +int abis_nm_event_reports(struct gsm_bts *bts, int on); +int abis_nm_reset_resource(struct gsm_bts *bts); +int abis_nm_software_load(struct gsm_bts *bts, int trx_nr, const char *fname, + uint8_t win_size, int forced, + gsm_cbfn *cbfn, void *cb_data); +int abis_nm_software_load_status(struct gsm_bts *bts); +int abis_nm_software_activate(struct gsm_bts *bts, const char *fname, + gsm_cbfn *cbfn, void *cb_data); + +int abis_nm_conn_mdrop_link(struct gsm_bts *bts, uint8_t e1_port0, uint8_t ts0, + uint8_t e1_port1, uint8_t ts1); + +int abis_nm_perform_test(struct gsm_bts *bts, uint8_t obj_class, + uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr, + uint8_t test_nr, uint8_t auton_report, struct msgb *msg); + +/* Siemens / BS-11 specific */ +int abis_nm_bs11_reset_resource(struct gsm_bts *bts); +int abis_nm_bs11_db_transmission(struct gsm_bts *bts, int begin); +int abis_nm_bs11_create_object(struct gsm_bts *bts, enum abis_bs11_objtype type, + uint8_t idx, uint8_t attr_len, const uint8_t *attr); +int abis_nm_bs11_create_envaBTSE(struct gsm_bts *bts, uint8_t idx); +int abis_nm_bs11_create_bport(struct gsm_bts *bts, uint8_t idx); +int abis_nm_bs11_delete_object(struct gsm_bts *bts, + enum abis_bs11_objtype type, uint8_t idx); +int abis_nm_bs11_delete_bport(struct gsm_bts *bts, uint8_t idx); +int abis_nm_bs11_conn_oml_tei(struct gsm_bts *bts, uint8_t e1_port, + uint8_t e1_timeslot, uint8_t e1_subslot, uint8_t tei); +int abis_nm_bs11_get_oml_tei_ts(struct gsm_bts *bts); +int abis_nm_bs11_get_serno(struct gsm_bts *bts); +int abis_nm_bs11_set_trx_power(struct gsm_bts_trx *trx, uint8_t level); +int abis_nm_bs11_get_trx_power(struct gsm_bts_trx *trx); +int abis_nm_bs11_logon(struct gsm_bts *bts, uint8_t level, const char *name, int on); +int abis_nm_bs11_factory_logon(struct gsm_bts *bts, int on); +int abis_nm_bs11_infield_logon(struct gsm_bts *bts, int on); +int abis_nm_bs11_set_trx1_pw(struct gsm_bts *bts, const char *password); +int abis_nm_bs11_set_pll_locked(struct gsm_bts *bts, int locked); +int abis_nm_bs11_get_pll_mode(struct gsm_bts *bts); +int abis_nm_bs11_set_pll(struct gsm_bts *bts, int value); +int abis_nm_bs11_get_cclk(struct gsm_bts *bts); +int abis_nm_bs11_get_state(struct gsm_bts *bts); +int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname, + uint8_t win_size, int forced, gsm_cbfn *cbfn); +int abis_nm_bs11_set_ext_time(struct gsm_bts *bts); +int abis_nm_bs11_get_bport_line_cfg(struct gsm_bts *bts, uint8_t bport); +int abis_nm_bs11_set_bport_line_cfg(struct gsm_bts *bts, uint8_t bport, enum abis_bs11_line_cfg line_cfg); +int abis_nm_bs11_bsc_disconnect(struct gsm_bts *bts, int reconnect); +int abis_nm_bs11_restart(struct gsm_bts *bts); + +/* ip.access nanoBTS specific commands */ +int abis_nm_ipaccess_msg(struct gsm_bts *bts, uint8_t msg_type, + uint8_t obj_class, uint8_t bts_nr, + uint8_t trx_nr, uint8_t ts_nr, + uint8_t *attr, int attr_len); +int abis_nm_ipaccess_set_nvattr(struct gsm_bts_trx *trx, uint8_t *attr, + int attr_len); +int abis_nm_ipaccess_restart(struct gsm_bts_trx *trx); +int abis_nm_ipaccess_set_attr(struct gsm_bts *bts, uint8_t obj_class, + uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr, + uint8_t *attr, uint8_t attr_len); +int abis_nm_ipaccess_rsl_connect(struct gsm_bts_trx *trx, + uint32_t ip, uint16_t port, uint8_t stream); +void abis_nm_ipaccess_cgi(uint8_t *buf, struct gsm_bts *bts); +int ipac_parse_bcch_info(struct ipac_bcch_info *binf, uint8_t *buf); +const char *ipacc_testres_name(uint8_t res); + +/* Functions calling into other code parts */ +int nm_is_running(struct gsm_nm_state *s); + +int abis_nm_vty_init(void); + +void abis_nm_clear_queue(struct gsm_bts *bts); + +int _abis_nm_sendmsg(struct msgb *msg); + +void abis_nm_queue_send_next(struct gsm_bts *bts); /* for bs11_config. */ + +int abis_nm_select_newest_sw(const struct abis_nm_sw_desc *sw, const size_t len); + +/* Helper functions for updating attributes */ +int abis_nm_update_max_power_red(struct gsm_bts_trx *trx); + +#endif /* _NM_H */ diff --git a/include/osmocom/msc/abis_om2000.h b/include/osmocom/msc/abis_om2000.h new file mode 100644 index 000000000..b093a0350 --- /dev/null +++ b/include/osmocom/msc/abis_om2000.h @@ -0,0 +1,129 @@ +#ifndef OPENBSC_ABIS_OM2K_H +#define OPENBSC_ABIS_OM2K_H +/* Ericsson RBS 2xxx GSM O&M (OM2000) messages on the A-bis interface + * implemented based on protocol trace analysis, no formal documentation */ + +/* (C) 2010-2011 by Harald Welte + * + * 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 . + * + */ + +enum abis_om2k_mo_cls { + OM2K_MO_CLS_TRXC = 0x01, + OM2K_MO_CLS_TS = 0x03, + OM2K_MO_CLS_TF = 0x04, + OM2K_MO_CLS_IS = 0x05, + OM2K_MO_CLS_CON = 0x06, + OM2K_MO_CLS_DP = 0x07, + OM2K_MO_CLS_CF = 0x0a, + OM2K_MO_CLS_TX = 0x0b, + OM2K_MO_CLS_RX = 0x0c, +}; + +enum om2k_mo_state { + OM2K_MO_S_RESET = 0, + OM2K_MO_S_STARTED, + OM2K_MO_S_ENABLED, + OM2K_MO_S_DISABLED, +}; + +/* on-wire format for IS conn group */ +struct om2k_is_conn_grp { + uint16_t icp1; + uint16_t icp2; + uint8_t cont_idx; +} __attribute__ ((packed)); + +/* internal data formant for IS conn group */ +struct is_conn_group { + struct llist_head list; + uint16_t icp1; + uint16_t icp2; + uint8_t ci; +}; + +/* on-wire format for CON Path */ +struct om2k_con_path { + uint16_t ccp; + uint8_t ci; + uint8_t tag; + uint8_t tei; +} __attribute__ ((packed)); + +/* internal data format for CON group */ +struct con_group { + /* links list of CON groups in BTS */ + struct llist_head list; + struct gsm_bts *bts; + /* CON Group ID */ + uint8_t cg; + /* list of CON paths in this group */ + struct llist_head paths; +}; + +/* internal data format for CON path */ +struct con_path { + /* links with con_group.paths */ + struct llist_head list; + /* CON Connection Point */ + uint16_t ccp; + /* Contiguity Index */ + uint8_t ci; + /* Tag */ + uint8_t tag; + /* TEI */ + uint8_t tei; +}; + +extern const struct abis_om2k_mo om2k_mo_cf; +extern const struct abis_om2k_mo om2k_mo_is; +extern const struct abis_om2k_mo om2k_mo_con; +extern const struct abis_om2k_mo om2k_mo_tf; + +extern const struct value_string om2k_mo_class_short_vals[]; + +int abis_om2k_rcvmsg(struct msgb *msg); + +extern const struct abis_om2k_mo om2k_mo_cf; + +int abis_om2k_tx_reset_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo); +int abis_om2k_tx_start_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo); +int abis_om2k_tx_status_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo); +int abis_om2k_tx_connect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo); +int abis_om2k_tx_disconnect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo); +int abis_om2k_tx_enable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo); +int abis_om2k_tx_disable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo); +int abis_om2k_tx_test_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo); +int abis_om2k_tx_op_info(struct gsm_bts *bts, const struct abis_om2k_mo *mo, + uint8_t operational); +int abis_om2k_tx_cap_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo); +int abis_om2k_tx_is_conf_req(struct gsm_bts *bts); +int abis_om2k_tx_tf_conf_req(struct gsm_bts *bts); +int abis_om2k_tx_rx_conf_req(struct gsm_bts_trx *trx); +int abis_om2k_tx_tx_conf_req(struct gsm_bts_trx *trx); +int abis_om2k_tx_ts_conf_req(struct gsm_bts_trx_ts *ts); + +struct osmo_fsm_inst *om2k_bts_fsm_start(struct gsm_bts *bts); +void abis_om2k_bts_init(struct gsm_bts *bts); +void abis_om2k_trx_init(struct gsm_bts_trx *trx); + +int abis_om2k_vty_init(void); + +struct vty; +void abis_om2k_config_write_bts(struct vty *vty, struct gsm_bts *bts); + +#endif /* OPENBCS_ABIS_OM2K_H */ diff --git a/include/osmocom/msc/abis_rsl.h b/include/osmocom/msc/abis_rsl.h new file mode 100644 index 000000000..f983fceec --- /dev/null +++ b/include/osmocom/msc/abis_rsl.h @@ -0,0 +1,117 @@ +/* GSM Radio Signalling Link messages on the A-bis interface + * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */ + +/* (C) 2008 by Harald Welte + * 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 . + * + */ + +#ifndef _RSL_H +#define _RSL_H + +#include +#include +#include +#include +#include + +struct gsm_bts; +struct gsm_lchan; +struct gsm_bts_trx_ts; + +#define GSM48_LEN2PLEN(a) (((a) << 2) | 1) + +int rsl_bcch_info(const struct gsm_bts_trx *trx, enum osmo_sysinfo_type si_type, const uint8_t *data, int len); +int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type, + const uint8_t *data, int len); +int rsl_chan_activate(struct gsm_bts_trx *trx, uint8_t chan_nr, + uint8_t act_type, + struct rsl_ie_chan_mode *chan_mode, + struct rsl_ie_chan_ident *chan_ident, + uint8_t bs_power, uint8_t ms_power, + uint8_t ta); +int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type, + uint8_t ho_ref); +int rsl_chan_mode_modify_req(struct gsm_lchan *ts); +int rsl_encryption_cmd(struct msgb *msg); +int rsl_paging_cmd(struct gsm_bts *bts, uint8_t paging_group, uint8_t len, + uint8_t *ms_ident, uint8_t chan_needed, bool is_gprs); +int rsl_imm_assign_cmd(struct gsm_bts *bts, uint8_t len, uint8_t *val); + +int rsl_data_request(struct msgb *msg, uint8_t link_id); +int rsl_establish_request(struct gsm_lchan *lchan, uint8_t link_id); +int rsl_relase_request(struct gsm_lchan *lchan, uint8_t link_id); + +/* Ericcson vendor specific RSL extensions */ +int rsl_ericsson_imm_assign_cmd(struct gsm_bts *bts, uint32_t tlli, uint8_t len, uint8_t *val); + +/* Siemens vendor-specific RSL extensions */ +int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci); + +/* ip.access specfic RSL extensions */ +int rsl_ipacc_crcx(struct gsm_lchan *lchan); +int rsl_ipacc_mdcx(struct gsm_lchan *lchan, uint32_t ip, + uint16_t port, uint8_t rtp_payload2); +int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan); +int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act); + +int abis_rsl_rcvmsg(struct msgb *msg); + +uint64_t str_to_imsi(const char *imsi_str); +int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id, + enum rsl_rel_mode release_mode); + +int rsl_lchan_set_state(struct gsm_lchan *lchan, int); +int rsl_lchan_mark_broken(struct gsm_lchan *lchan, const char *broken); + +/* to be provided by external code */ +int rsl_deact_sacch(struct gsm_lchan *lchan); + +/* BCCH related code */ +int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf); +int rsl_ccch_conf_to_bs_ccch_sdcch_comb(int ccch_conf); + +int rsl_sacch_info_modify(struct gsm_lchan *lchan, uint8_t type, + const uint8_t *data, int len); + +int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db); +int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm); + +/* SMSCB functionality */ +int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number, + struct rsl_ie_cb_cmd_type cb_command, + const uint8_t *data, int len); + +/* some Nokia specific stuff */ +int rsl_nokia_si_begin(struct gsm_bts_trx *trx); +int rsl_nokia_si_end(struct gsm_bts_trx *trx); + +/* required for Nokia BTS power control */ +int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction); + + +int rsl_release_sapis_from(struct gsm_lchan *lchan, int start, + enum rsl_rel_mode release_mode); +int rsl_start_t3109(struct gsm_lchan *lchan); + +int rsl_direct_rf_release(struct gsm_lchan *lchan); + +void dyn_ts_init(struct gsm_bts_trx_ts *ts); +int dyn_ts_switchover_start(struct gsm_bts_trx_ts *ts, + enum gsm_phys_chan_config to_pchan); + +#endif /* RSL_MT_H */ + diff --git a/include/osmocom/msc/arfcn_range_encode.h b/include/osmocom/msc/arfcn_range_encode.h new file mode 100644 index 000000000..7ec710c33 --- /dev/null +++ b/include/osmocom/msc/arfcn_range_encode.h @@ -0,0 +1,26 @@ +#ifndef ARFCN_RANGE_ENCODE_H +#define ARFCN_RANGE_ENCODE_H + +#include + +enum gsm48_range { + ARFCN_RANGE_INVALID = -1, + ARFCN_RANGE_128 = 127, + ARFCN_RANGE_256 = 255, + ARFCN_RANGE_512 = 511, + ARFCN_RANGE_1024 = 1023, +}; + +#define RANGE_ENC_MAX_ARFCNS 29 + +int range_enc_determine_range(const int *arfcns, int size, int *f0_out); +int range_enc_arfcns(enum gsm48_range rng, const int *arfcns, int sze, int *out, int idx); +int range_enc_find_index(enum gsm48_range rng, const int *arfcns, int size); +int range_enc_filter_arfcns(int *arfcns, const int sze, const int f0, int *f0_included); + +int range_enc_range128(uint8_t *chan_list, int f0, int *w); +int range_enc_range256(uint8_t *chan_list, int f0, int *w); +int range_enc_range512(uint8_t *chan_list, int f0, int *w); +int range_enc_range1024(uint8_t *chan_list, int f0, int f0_incl, int *w); + +#endif diff --git a/include/osmocom/msc/auth.h b/include/osmocom/msc/auth.h new file mode 100644 index 000000000..b314bbf19 --- /dev/null +++ b/include/osmocom/msc/auth.h @@ -0,0 +1,22 @@ +#ifndef _AUTH_H +#define _AUTH_H + +#include + +struct gsm_auth_tuple; + +enum auth_action { + AUTH_ERROR = -1, /* Internal error */ + AUTH_NOT_AVAIL = 0, /* No auth tuple available */ + AUTH_DO_AUTH_THEN_CIPH = 1, /* Firsth authenticate, then cipher */ + AUTH_DO_CIPH = 2, /* Only ciphering */ + AUTH_DO_AUTH = 3, /* Only authentication, no ciphering */ +}; + +extern const struct value_string auth_action_names[]; +static inline const char *auth_action_str(enum auth_action a) +{ + return get_value_string(auth_action_names, a); +} + +#endif /* _AUTH_H */ diff --git a/include/osmocom/msc/bsc_api.h b/include/osmocom/msc/bsc_api.h new file mode 100644 index 000000000..40068d6ef --- /dev/null +++ b/include/osmocom/msc/bsc_api.h @@ -0,0 +1,58 @@ +/* GSM 08.08 like API for OpenBSC */ + +#ifndef OPENBSC_BSC_API_H +#define OPENBSC_BSC_API_H + +#include "gsm_data.h" + +#define BSC_API_CONN_POL_ACCEPT 0 +#define BSC_API_CONN_POL_REJECT 1 + +struct bsc_api { + /*! \brief BTS->MSC: tell MSC a SAPI was not established */ + void (*sapi_n_reject)(struct gsm_subscriber_connection *conn, int dlci); + /*! \brief MS->MSC: Tell MSC that ciphering has been enabled */ + void (*cipher_mode_compl)(struct gsm_subscriber_connection *conn, + struct msgb *msg, uint8_t chosen_encr); + /*! \brief MS->MSC: New MM context with L3 payload */ + int (*compl_l3)(struct gsm_subscriber_connection *conn, + struct msgb *msg, uint16_t chosen_channel); + /*! \brief MS->BSC/MSC: Um L3 message */ + void (*dtap)(struct gsm_subscriber_connection *conn, uint8_t link_id, + struct msgb *msg); + /*! \brief BSC->MSC: Assignment of lchan successful */ + void (*assign_compl)(struct gsm_subscriber_connection *conn, + uint8_t rr_cause, uint8_t chosen_channel, + uint8_t encr_alg_id, uint8_t speech_mode); + /*! \brief BSC->MSC: Assignment of lchan failed */ + void (*assign_fail)(struct gsm_subscriber_connection *conn, + uint8_t cause, uint8_t *rr_cause); + /*! \brief BSC->MSC: RR conn has been cleared */ + int (*clear_request)(struct gsm_subscriber_connection *conn, + uint32_t cause); + /*! \brief BSC->MSC: Classmark Update */ + void (*classmark_chg)(struct gsm_subscriber_connection *conn, + const uint8_t *cm2, uint8_t cm2_len, + const uint8_t *cm3, uint8_t cm3_len); + + /** + * Configure the multirate setting on this channel. If it is + * not implemented AMR5.9 will be used. + */ + void (*mr_config)(struct gsm_subscriber_connection *conn, + struct gsm_lchan *lchan, int full_rate); + + /** Callback for additional actions during conn cleanup */ + void (*conn_cleanup)(struct gsm_subscriber_connection *conn); +}; + +int bsc_api_init(struct gsm_network *network, struct bsc_api *api); +int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, int link_id, int allow_sacch); +int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, int full_rate); +int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher, + const uint8_t *key, int len, int include_imeisv); +int gsm0808_page(struct gsm_bts *bts, unsigned int page_group, + unsigned int mi_len, uint8_t *mi, int chan_type); +int gsm0808_clear(struct gsm_subscriber_connection *conn); + +#endif diff --git a/include/osmocom/msc/bsc_msc.h b/include/osmocom/msc/bsc_msc.h new file mode 100644 index 000000000..d649f76cd --- /dev/null +++ b/include/osmocom/msc/bsc_msc.h @@ -0,0 +1,77 @@ +/* Routines to talk to the MSC using the IPA Protocol */ +/* + * (C) 2010 by Holger Hans Peter Freyther + * (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 . + * + */ + +#ifndef BSC_MSC_H +#define BSC_MSC_H + +#include +#include +#include +#include + +#include + +struct bsc_msc_dest { + struct llist_head list; + + char *ip; + int port; + int dscp; +}; + + +struct bsc_msc_connection { + /* FIXME: Remove stuff that is no longer needed! */ + struct osmo_wqueue write_queue; + int is_connected; + int is_authenticated; + int first_contact; + + struct llist_head *dests; + + const char *name; + + void (*connection_loss) (struct bsc_msc_connection *); + void (*connected) (struct bsc_msc_connection *); + struct osmo_timer_list reconnect_timer; + struct osmo_timer_list timeout_timer; + + struct msgb *pending_msg; + + /* Sigtran connection data */ + struct osmo_sccp_instance *sccp; + struct osmo_sccp_user *sccp_user; + struct osmo_sccp_addr g_calling_addr; + struct osmo_sccp_addr g_called_addr; + struct a_reset_ctx *reset; + + int conn_id_counter; +}; + +struct bsc_msc_connection *bsc_msc_create(void *ctx, struct llist_head *dest); +int bsc_msc_connect(struct bsc_msc_connection *); +void bsc_msc_schedule_connect(struct bsc_msc_connection *); + +void bsc_msc_lost(struct bsc_msc_connection *); + +struct msgb *bsc_msc_id_get_resp(int fixed, const char *token, const uint8_t *res, int len); + +#endif diff --git a/include/osmocom/msc/bsc_msc_data.h b/include/osmocom/msc/bsc_msc_data.h new file mode 100644 index 000000000..4a283d165 --- /dev/null +++ b/include/osmocom/msc/bsc_msc_data.h @@ -0,0 +1,174 @@ +/* + * Data for the true BSC + * + * (C) 2010-2015 by Holger Hans Peter Freyther + * (C) 2010-2015 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 . + * + */ + +/* + * NOTE: This is about a *remote* MSC for OsmoBSC and is not part of libmsc. + */ + +#ifndef _OSMO_MSC_DATA_H +#define _OSMO_MSC_DATA_H + +#include "bsc_msc.h" + +#include +#include + + +#include +#include +#include +#include +#include +#include + +#include + +struct osmo_bsc_rf; +struct gsm_network; + +struct gsm_audio_support { + uint8_t hr : 1, + ver : 7; +}; + +enum { + MSC_CON_TYPE_NORMAL, + MSC_CON_TYPE_LOCAL, +}; + +/*! /brief Information on a remote MSC for libbsc. + */ +struct bsc_msc_data { + struct llist_head entry; + + /* Back pointer */ + struct gsm_network *network; + + int allow_emerg; + int type; + + /* local call routing */ + char *local_pref; + regex_t local_pref_reg; + + + /* Connection data */ + char *bsc_token; + uint8_t bsc_key[16]; + uint8_t bsc_key_present; + + int ping_timeout; + int pong_timeout; + struct osmo_timer_list ping_timer; + struct osmo_timer_list pong_timer; + int advanced_ping; + struct bsc_msc_connection *msc_con; + int core_mnc; + int core_mcc; + int core_lac; + int core_ci; + int rtp_base; + + /* audio codecs */ + struct gsm48_multi_rate_conf amr_conf; + struct gsm_audio_support **audio_support; + int audio_length; + + /* destinations */ + struct llist_head dests; + + /* ussd welcome text */ + char *ussd_welcome_txt; + + /* mgcp agent */ + struct osmo_wqueue mgcp_agent; + + int nr; + + /* ussd msc connection lost text */ + char *ussd_msc_lost_txt; + + /* ussd text when MSC has entered the grace period */ + char *ussd_grace_txt; + + char *acc_lst_name; + + /* Sigtran connection data */ + struct { + uint32_t cs7_instance; + bool cs7_instance_valid; + struct osmo_sccp_instance *sccp; + struct osmo_sccp_user *sccp_user; + + /* Holds a copy of the our local MSC address, + * this will be the sccp-address that is associated + * with the A interface of this particular BSC, + * this address is filled up by the VTY interface */ + struct osmo_sccp_addr bsc_addr; + char *bsc_addr_name; + + /* Holds a copy of the MSC address. This is the + * address of the MSC that handles the calls of + * this BSC. The address is configured via the + * VTY interface */ + struct osmo_sccp_addr msc_addr; + char *msc_addr_name; + + struct a_reset_ctx *reset; + } a; +}; + +/* + * Per BSC data. + */ +struct osmo_bsc_data { + struct gsm_network *network; + + /* msc configuration */ + struct llist_head mscs; + + /* rf ctl related bits */ + char *mid_call_txt; + int mid_call_timeout; + char *rf_ctrl_name; + struct osmo_bsc_rf *rf_ctrl; + int auto_off_timeout; + + /* ussd text when there is no MSC available */ + char *ussd_no_msc_txt; + + char *acc_lst_name; +}; + + +int osmo_bsc_msc_init(struct bsc_msc_data *msc); +int osmo_bsc_sccp_init(struct gsm_network *gsmnet); +int msc_queue_write(struct bsc_msc_connection *conn, struct msgb *msg, int proto); +int msc_queue_write_with_ping(struct bsc_msc_connection *, struct msgb *msg, int proto); + +int osmo_bsc_audio_init(struct gsm_network *network); + +struct bsc_msc_data *osmo_msc_data_find(struct gsm_network *, int); +struct bsc_msc_data *osmo_msc_data_alloc(struct gsm_network *, int); + + +#endif diff --git a/include/osmocom/msc/bsc_msg_filter.h b/include/osmocom/msc/bsc_msg_filter.h new file mode 100644 index 000000000..a9dedf43c --- /dev/null +++ b/include/osmocom/msc/bsc_msg_filter.h @@ -0,0 +1,107 @@ +#pragma once + +#include +#include +#include +#include + +#include + +struct vty; +struct gsm48_hdr; + +struct bsc_filter_reject_cause { + int lu_reject_cause; + int cm_reject_cause; +}; + +struct bsc_filter_barr_entry { + struct rb_node node; + + char *imsi; + int cm_reject_cause; + int lu_reject_cause; +}; + +enum bsc_filter_acc_ctr { + ACC_LIST_LOCAL_FILTER, + ACC_LIST_GLOBAL_FILTER, +}; + +struct bsc_msg_acc_lst { + struct llist_head list; + + /* counter */ + struct rate_ctr_group *stats; + + /* the name of the list */ + const char *name; + struct llist_head fltr_list; +}; + +struct bsc_msg_acc_lst_entry { + struct llist_head list; + + /* the filter */ + char *imsi_allow; + regex_t imsi_allow_re; + char *imsi_deny; + regex_t imsi_deny_re; + + /* reject reasons for the access lists */ + int cm_reject_cause; + int lu_reject_cause; +}; + +enum { + FLT_CON_TYPE_NONE, + FLT_CON_TYPE_LU, + FLT_CON_TYPE_CM_SERV_REQ, + FLT_CON_TYPE_PAG_RESP, + FLT_CON_TYPE_SSA, + FLT_CON_TYPE_LOCAL_REJECT, + FLT_CON_TYPE_OTHER, +}; + + +struct bsc_filter_state { + char *imsi; + int imsi_checked; + int con_type; +}; + +struct bsc_filter_request { + void *ctx; + struct rb_root *black_list; + struct llist_head *access_lists; + const char *local_lst_name; + const char *global_lst_name; + int bsc_nr; +}; + + +int bsc_filter_barr_adapt(void *ctx, struct rb_root *rbtree, const struct osmo_config_list *); +int bsc_filter_barr_find(struct rb_root *root, const char *imsi, int *cm, int *lu); + +/** + * Content filtering. + */ +int bsc_msg_filter_initial(struct gsm48_hdr *hdr, size_t size, + struct bsc_filter_request *req, + int *con_type, char **imsi, + struct bsc_filter_reject_cause *cause); +int bsc_msg_filter_data(struct gsm48_hdr *hdr, size_t size, + struct bsc_filter_request *req, + struct bsc_filter_state *state, + struct bsc_filter_reject_cause *cause); + +/* IMSI allow/deny handling */ +struct bsc_msg_acc_lst *bsc_msg_acc_lst_find(struct llist_head *lst, const char *name); +struct bsc_msg_acc_lst *bsc_msg_acc_lst_get(void *ctx, struct llist_head *lst, const char *name); +void bsc_msg_acc_lst_delete(struct bsc_msg_acc_lst *lst); + +struct bsc_msg_acc_lst_entry *bsc_msg_acc_lst_entry_create(struct bsc_msg_acc_lst *); +int bsc_msg_acc_lst_check_allow(struct bsc_msg_acc_lst *lst, const char *imsi); + +void bsc_msg_lst_vty_init(void *ctx, struct llist_head *lst, int node); +void bsc_msg_acc_lst_write(struct vty *vty, struct bsc_msg_acc_lst *lst); diff --git a/include/osmocom/msc/bsc_rll.h b/include/osmocom/msc/bsc_rll.h new file mode 100644 index 000000000..93c80e7a9 --- /dev/null +++ b/include/osmocom/msc/bsc_rll.h @@ -0,0 +1,19 @@ +#ifndef _BSC_RLL_H +#define _BSC_RLL_H + +#include + +enum bsc_rllr_ind { + BSC_RLLR_IND_EST_CONF, + BSC_RLLR_IND_REL_IND, + BSC_RLLR_IND_ERR_IND, + BSC_RLLR_IND_TIMEOUT, +}; + +int rll_establish(struct gsm_lchan *lchan, uint8_t link_id, + void (*cb)(struct gsm_lchan *, uint8_t, void *, + enum bsc_rllr_ind), + void *data); +void rll_indication(struct gsm_lchan *lchan, uint8_t link_id, uint8_t type); + +#endif /* _BSC_RLL_H */ diff --git a/include/osmocom/msc/bss.h b/include/osmocom/msc/bss.h new file mode 100644 index 000000000..090433420 --- /dev/null +++ b/include/osmocom/msc/bss.h @@ -0,0 +1,20 @@ +#ifndef _BSS_H_ +#define _BSS_H_ + +#include + +struct msgb; + +/* start and stop network */ +extern int bsc_network_alloc(mncc_recv_cb_t mncc_recv); +extern int bsc_network_configure(const char *cfg_file); +extern int bsc_shutdown_net(struct gsm_network *net); + +/* register all supported BTS */ +extern int bts_init(void); +extern int bts_model_bs11_init(void); +extern int bts_model_rbs2k_init(void); +extern int bts_model_nanobts_init(void); +extern int bts_model_nokia_site_init(void); +extern int bts_model_sysmobts_init(void); +#endif diff --git a/include/osmocom/msc/bts_ipaccess_nanobts_omlattr.h b/include/osmocom/msc/bts_ipaccess_nanobts_omlattr.h new file mode 100644 index 000000000..bc7860b2d --- /dev/null +++ b/include/osmocom/msc/bts_ipaccess_nanobts_omlattr.h @@ -0,0 +1,32 @@ +/* OML attribute table generator for ipaccess nanobts */ + +/* (C) 2016 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Philipp Maier + * + * 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 . + */ + +#pragma once + +#include +#include + +struct msgb *nanobts_attr_bts_get(struct gsm_bts *bts); +struct msgb *nanobts_attr_nse_get(struct gsm_bts *bts); +struct msgb *nanobts_attr_cell_get(struct gsm_bts *bts); +struct msgb *nanobts_attr_nscv_get(struct gsm_bts *bts); +struct msgb *nanobts_attr_radio_get(struct gsm_bts *bts, + struct gsm_bts_trx *trx); diff --git a/include/osmocom/msc/chan_alloc.h b/include/osmocom/msc/chan_alloc.h new file mode 100644 index 000000000..7388e14c5 --- /dev/null +++ b/include/osmocom/msc/chan_alloc.h @@ -0,0 +1,54 @@ +/* Management functions to allocate/release struct gsm_lchan */ +/* (C) 2008 by Harald Welte + * (C) 2009 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 . + * + */ +#ifndef _CHAN_ALLOC_H +#define _CHAN_ALLOC_H + +#include "gsm_data.h" + +struct gsm_subscriber_connection; + +/* Find an allocated channel for a specified subscriber */ +struct gsm_subscriber_connection *connection_for_subscr(struct vlr_subscr *vsub); + +/* Allocate a logical channel (SDCCH, TCH, ...) */ +struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type, int allow_bigger); + +/* Free a logical channel (SDCCH, TCH, ...) */ +void lchan_free(struct gsm_lchan *lchan); +void lchan_reset(struct gsm_lchan *lchan); + +/* Release the given lchan */ +int lchan_release(struct gsm_lchan *lchan, int sacch_deact, enum rsl_rel_mode release_mode); + +struct load_counter { + unsigned int total; + unsigned int used; +}; + +struct pchan_load { + struct load_counter pchan[_GSM_PCHAN_MAX]; +}; + +void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts); +void network_chan_load(struct pchan_load *pl, struct gsm_network *net); + +int trx_is_usable(struct gsm_bts_trx *trx); + +#endif /* _CHAN_ALLOC_H */ diff --git a/include/osmocom/msc/common.h b/include/osmocom/msc/common.h new file mode 100644 index 000000000..d91b3d39e --- /dev/null +++ b/include/osmocom/msc/common.h @@ -0,0 +1,6 @@ +#pragma once + +enum nsap_addr_enc { + NSAP_ADDR_ENC_X213, + NSAP_ADDR_ENC_V4RAW, +}; diff --git a/include/osmocom/msc/common_bsc.h b/include/osmocom/msc/common_bsc.h new file mode 100644 index 000000000..821298cbf --- /dev/null +++ b/include/osmocom/msc/common_bsc.h @@ -0,0 +1,9 @@ +#pragma once + +#include +#include + +struct gsm_network *bsc_network_init(void *ctx, + uint16_t country_code, + uint16_t network_code, + mncc_recv_cb_t mncc_recv); diff --git a/include/osmocom/msc/common_cs.h b/include/osmocom/msc/common_cs.h new file mode 100644 index 000000000..6dc956f80 --- /dev/null +++ b/include/osmocom/msc/common_cs.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +struct msgb; +struct gsm_network; + +typedef int (*mncc_recv_cb_t)(struct gsm_network *, struct msgb *); + +struct vty; + +#define MAX_A5_KEY_LEN (128/8) + +struct gsm_encr { + uint8_t alg_id; + uint8_t key_len; + uint8_t key[MAX_A5_KEY_LEN]; +}; + +struct gsm_network *gsm_network_init(void *ctx, + uint16_t country_code, + uint16_t network_code, + mncc_recv_cb_t mncc_recv); + +int common_cs_vty_init(struct gsm_network *network, + int (* config_write_net )(struct vty *)); +struct gsm_network *gsmnet_from_vty(struct vty *v); diff --git a/include/osmocom/msc/crc24.h b/include/osmocom/msc/crc24.h new file mode 100644 index 000000000..756638c03 --- /dev/null +++ b/include/osmocom/msc/crc24.h @@ -0,0 +1,10 @@ +#ifndef _CRC24_H +#define _CRC24_H + +#include + +#define INIT_CRC24 0xffffff + +uint32_t crc24_calc(uint32_t fcs, uint8_t *cp, unsigned int len); + +#endif diff --git a/include/osmocom/msc/ctrl.h b/include/osmocom/msc/ctrl.h new file mode 100644 index 000000000..c5ac21092 --- /dev/null +++ b/include/osmocom/msc/ctrl.h @@ -0,0 +1,4 @@ +#pragma once + +struct ctrl_handle *bsc_controlif_setup(struct gsm_network *net, + const char *bind_addr, uint16_t port); diff --git a/include/osmocom/msc/db.h b/include/osmocom/msc/db.h new file mode 100644 index 000000000..988c9bd6e --- /dev/null +++ b/include/osmocom/msc/db.h @@ -0,0 +1,59 @@ +/* (C) 2008 by Jan Luebbe + * (C) 2009 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 . + * + */ + +#ifndef _DB_H +#define _DB_H + +#include + +#include "gsm_subscriber.h" + +struct gsm_equipment; +struct gsm_network; +struct gsm_auth_info; +struct gsm_auth_tuple; +struct gsm_sms; + +/* one time initialisation */ +int db_init(const char *name); +int db_prepare(void); +int db_fini(void); + +/* SMS store-and-forward */ +int db_sms_store(struct gsm_sms *sms); +struct gsm_sms *db_sms_get(struct gsm_network *net, unsigned long long id); +struct gsm_sms *db_sms_get_next_unsent(struct gsm_network *net, + unsigned long long min_sms_id, + unsigned int max_failed); +struct gsm_sms *db_sms_get_next_unsent_rr_msisdn(struct gsm_network *net, + const char *last_msisdn, + unsigned int max_failed); +struct gsm_sms *db_sms_get_unsent_for_subscr(struct vlr_subscr *vsub, + unsigned int max_failed); +int db_sms_mark_delivered(struct gsm_sms *sms); +int db_sms_inc_deliver_attempts(struct gsm_sms *sms); +int db_sms_delete_by_msisdn(const char *msisdn); + +/* Statistics counter storage */ +struct osmo_counter; +int db_store_counter(struct osmo_counter *ctr); +struct rate_ctr_group; +int db_store_rate_ctr_group(struct rate_ctr_group *ctrg); + +#endif /* _DB_H */ diff --git a/include/osmocom/msc/debug.h b/include/osmocom/msc/debug.h new file mode 100644 index 000000000..65e197d52 --- /dev/null +++ b/include/osmocom/msc/debug.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include + +#define DEBUG +#include + +/* Debug Areas of the code */ +enum { + DRLL, + DCC, + DMM, + DRR, + DRSL, + DNM, + DMNCC, + DPAG, + DMEAS, + DSCCP, + DMSC, + DMGCP, + DHO, + DDB, + DREF, + DGPRS, + DNS, + DBSSGP, + DLLC, + DSNDCP, + DSLHC, + DNAT, + DCTRL, + DSMPP, + DFILTER, + DGTPHUB, + DRANAP, + DSUA, + DV42BIS, + DPCU, + DVLR, + DIUCS, + DSIGTRAN, + Debug_LastEntry, +}; + +extern const struct log_info log_info; diff --git a/include/osmocom/msc/e1_config.h b/include/osmocom/msc/e1_config.h new file mode 100644 index 000000000..ac5fbb1e4 --- /dev/null +++ b/include/osmocom/msc/e1_config.h @@ -0,0 +1,11 @@ +#ifndef _E1_CONFIG_H +#define _E1_CONFIG_H + +#include + +int e1_reconfig_ts(struct gsm_bts_trx_ts *ts); +int e1_reconfig_trx(struct gsm_bts_trx *trx); +int e1_reconfig_bts(struct gsm_bts *bts); + +#endif /* _E1_CONFIG_H */ + diff --git a/include/osmocom/msc/gsm_04_08.h b/include/osmocom/msc/gsm_04_08.h new file mode 100644 index 000000000..c99fc86aa --- /dev/null +++ b/include/osmocom/msc/gsm_04_08.h @@ -0,0 +1,85 @@ +#ifndef _GSM_04_08_H +#define _GSM_04_08_H + +#include +#include +#include + +#include + +struct msgb; +struct gsm_bts; +struct gsm_network; +struct gsm_trans; +struct gsm_subscriber_connection; +struct amr_multirate_conf; +struct amr_mode; +struct bsc_subscr; + +#define GSM48_ALLOC_SIZE 2048 +#define GSM48_ALLOC_HEADROOM 256 + +static inline struct msgb *gsm48_msgb_alloc_name(const char *name) +{ + return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM, + name); +} + +void cm_service_request_concludes(struct gsm_subscriber_connection *conn, + struct msgb *msg); + +/* config options controlling the behaviour of the lower leves */ +void gsm0408_allow_everyone(int allow); +void gsm0408_clear_all_trans(struct gsm_network *net, int protocol); +int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg); + +int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id); +enum gsm_chan_t get_ctype_by_chreq(struct gsm_network *bts, uint8_t ra); +/* don't use "enum gsm_chreq_reason_t" to avoid circular dependency */ +int get_reason_by_chreq(uint8_t ra, int neci); +void gsm_net_update_ctype(struct gsm_network *net); + +int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn); +int gsm48_tx_mm_auth_req(struct gsm_subscriber_connection *conn, uint8_t *rand, + uint8_t *autn, int key_seq); +int gsm48_tx_mm_auth_rej(struct gsm_subscriber_connection *conn); +int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn); +int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn, + enum gsm48_reject_value value); +int gsm48_send_rr_release(struct gsm_lchan *lchan); +int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv); +int gsm48_send_rr_app_info(struct gsm_subscriber_connection *conn, uint8_t apdu_id, + uint8_t apdu_len, const uint8_t *apdu); +int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, uint8_t power_class); +int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan, + uint8_t power_command, uint8_t ho_ref); + +int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg); + +/* convert a ASCII phone number to call-control BCD */ +int encode_bcd_number(uint8_t *bcd_lv, uint8_t max_len, + int h_len, const char *input); +int decode_bcd_number(char *output, int output_len, const uint8_t *bcd_lv, + int h_len); + +int send_siemens_mrpci(struct gsm_lchan *lchan, uint8_t *classmark2_lv); +int gsm48_extract_mi(uint8_t *classmark2, int length, char *mi_string, uint8_t *mi_type); +int gsm48_paging_extract_mi(struct gsm48_pag_resp *pag, int length, char *mi_string, uint8_t *mi_type); + +int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t lchan_mode); +int gsm48_rx_rr_modif_ack(struct msgb *msg); +int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg); + +struct msgb *gsm48_create_mm_serv_rej(enum gsm48_reject_value value); +struct msgb *gsm48_create_loc_upd_rej(uint8_t cause); +void gsm48_lchan2chan_desc(struct gsm48_chan_desc *cd, + const struct gsm_lchan *lchan); + +void release_security_operation(struct gsm_subscriber_connection *conn); +void allocate_security_operation(struct gsm_subscriber_connection *conn); + +int gsm48_multirate_config(uint8_t *lv, const struct amr_multirate_conf *mr, const struct amr_mode *modes); + +int gsm48_tch_rtp_create(struct gsm_trans *trans); + +#endif diff --git a/include/osmocom/msc/gsm_04_11.h b/include/osmocom/msc/gsm_04_11.h new file mode 100644 index 000000000..3305e3e61 --- /dev/null +++ b/include/osmocom/msc/gsm_04_11.h @@ -0,0 +1,53 @@ +#ifndef _GSM_04_11_H +#define _GSM_04_11_H + +#include + +struct vlr_subscr; +struct gsm_subscriber_connection; +struct gsm_trans; + +#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */ + +/* SMS deliver PDU */ +struct sms_deliver { + uint8_t mti:2; /* message type indicator */ + uint8_t mms:1; /* more messages to send */ + uint8_t rp:1; /* reply path */ + uint8_t udhi:1; /* user data header indicator */ + uint8_t sri:1; /* status report indication */ + uint8_t *orig_addr; /* originating address */ + uint8_t pid; /* protocol identifier */ + uint8_t dcs; /* data coding scheme */ + /* service centre time stamp */ + uint8_t ud_len; /* user data length */ + uint8_t *user_data; /* user data */ + + uint8_t msg_ref; /* message reference */ + uint8_t *smsc; +}; + +struct msgb; + +int gsm0411_rcv_sms(struct gsm_subscriber_connection *conn, struct msgb *msg); + +struct gsm_sms *sms_alloc(void); +void sms_free(struct gsm_sms *sms); +struct gsm_sms *sms_from_text(struct vlr_subscr *receiver, + struct vlr_subscr *sender, + int dcs, const char *text); + +void _gsm411_sms_trans_free(struct gsm_trans *trans); +int gsm411_send_sms_subscr(struct vlr_subscr *vsub, + struct gsm_sms *sms); +int gsm411_send_sms(struct gsm_subscriber_connection *conn, + struct gsm_sms *sms); +void gsm411_sapi_n_reject(struct gsm_subscriber_connection *conn); + +uint8_t sms_next_rp_msg_ref(uint8_t *next_rp_ref); + +int gsm411_send_rp_ack(struct gsm_trans *trans, uint8_t msg_ref); +int gsm411_send_rp_error(struct gsm_trans *trans, uint8_t msg_ref, + uint8_t cause); + +#endif diff --git a/include/osmocom/msc/gsm_04_14.h b/include/osmocom/msc/gsm_04_14.h new file mode 100644 index 000000000..3cdbe0469 --- /dev/null +++ b/include/osmocom/msc/gsm_04_14.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +int gsm0414_tx_close_tch_loop_cmd(struct gsm_subscriber_connection *conn, + enum gsm414_tch_loop_mode loop_mode); +int gsm0414_tx_open_loop_cmd(struct gsm_subscriber_connection *conn); +int gsm0414_tx_act_emmi_cmd(struct gsm_subscriber_connection *conn); +int gsm0414_tx_test_interface(struct gsm_subscriber_connection *conn, + uint8_t tested_devs); +int gsm0414_tx_reset_ms_pos_store(struct gsm_subscriber_connection *conn, + uint8_t technology); + +int gsm0414_rcv_test(struct gsm_subscriber_connection *conn, + struct msgb *msg); diff --git a/include/osmocom/msc/gsm_04_80.h b/include/osmocom/msc/gsm_04_80.h new file mode 100644 index 000000000..d65f640bc --- /dev/null +++ b/include/osmocom/msc/gsm_04_80.h @@ -0,0 +1,25 @@ +#ifndef _GSM_04_80_H +#define _GSM_04_80_H + +#include +#include +#include + +struct gsm_subscriber_connection; + +int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn, + const struct msgb *in_msg, const char* response_text, + const struct ss_request *req); +int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn, + const struct msgb *msg, + const struct ss_request *request); + +int msc_send_ussd_notify(struct gsm_subscriber_connection *conn, int level, + const char *text); +int msc_send_ussd_release_complete(struct gsm_subscriber_connection *conn); + +int bsc_send_ussd_notify(struct gsm_subscriber_connection *conn, int level, + const char *text); +int bsc_send_ussd_release_complete(struct gsm_subscriber_connection *conn); + +#endif diff --git a/include/osmocom/msc/gsm_data.h b/include/osmocom/msc/gsm_data.h new file mode 100644 index 000000000..9343c3195 --- /dev/null +++ b/include/osmocom/msc/gsm_data.h @@ -0,0 +1,691 @@ +#ifndef _GSM_DATA_H +#define _GSM_DATA_H + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + + +/** annotations for msgb ownership */ +#define __uses + +#define OBSC_NM_W_ACK_CB(__msgb) (__msgb)->cb[3] + +struct mncc_sock_state; +struct gsm_subscriber_group; +struct bsc_subscr; +struct vlr_instance; +struct vlr_subscr; +struct ranap_ue_conn_ctx; + +#define OBSC_LINKID_CB(__msgb) (__msgb)->cb[3] + +#define tmsi_from_string(str) strtoul(str, NULL, 10) + +/* 3-bit long values */ +#define EARFCN_PRIO_INVALID 8 +#define EARFCN_MEAS_BW_INVALID 8 +/* 5-bit long values */ +#define EARFCN_QRXLV_INVALID 32 +#define EARFCN_THRESH_LOW_INVALID 32 + +enum gsm_security_event { + GSM_SECURITY_NOAVAIL, + GSM_SECURITY_AUTH_FAILED, + GSM_SECURITY_SUCCEEDED, + GSM_SECURITY_ALREADY, +}; + +struct msgb; +typedef int gsm_cbfn(unsigned int hooknum, + unsigned int event, + struct msgb *msg, + void *data, void *param); + +/* Real authentication information containing Ki */ +enum gsm_auth_algo { + AUTH_ALGO_NONE, + AUTH_ALGO_XOR, + AUTH_ALGO_COMP128v1, +}; + +struct gsm_auth_info { + enum gsm_auth_algo auth_algo; + unsigned int a3a8_ki_len; + uint8_t a3a8_ki[16]; +}; + +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 */ + +/* + * AUTHENTICATION/CIPHERING state + */ +struct gsm_security_operation { + struct gsm_auth_tuple atuple; + gsm_cbfn *cb; + void *cb_data; +}; + +/* + * A dummy to keep a connection up for at least + * a couple of seconds to work around MSC issues. + */ +struct gsm_anchor_operation { + struct osmo_timer_list timeout; +}; + +/* Maximum number of neighbor cells whose average we track */ +#define MAX_NEIGH_MEAS 10 +/* Maximum size of the averaging window for neighbor cells */ +#define MAX_WIN_NEIGH_AVG 10 + +/* processed neighbor measurements for one cell */ +struct neigh_meas_proc { + uint16_t arfcn; + uint8_t bsic; + uint8_t rxlev[MAX_WIN_NEIGH_AVG]; + unsigned int rxlev_cnt; + uint8_t last_seen_nr; +}; + +enum ran_type { + RAN_UNKNOWN, + RAN_GERAN_A, /* 2G / A-interface */ + RAN_UTRAN_IU, /* 3G / Iu-interface (IuCS or IuPS) */ +}; + +extern const struct value_string ran_type_names[]; +static inline const char *ran_type_name(enum ran_type val) +{ return get_value_string(ran_type_names, val); } + +struct gsm_classmark { + bool classmark1_set; + struct gsm48_classmark1 classmark1; + uint8_t classmark2_len; + uint8_t classmark2[3]; + uint8_t classmark3_len; + uint8_t classmark3[14]; /* if cm3 gets extended by spec, it will be truncated */ +}; + +enum integrity_protection_state { + INTEGRITY_PROTECTION_NONE = 0, + INTEGRITY_PROTECTION_IK = 1, + INTEGRITY_PROTECTION_IK_CK = 2, +}; + +/* active radio connection of a mobile subscriber */ +struct gsm_subscriber_connection { + /* global linked list of subscriber_connections */ + struct llist_head entry; + + /* usage count. If this drops to zero, we start the release + * towards A/Iu */ + uint32_t use_count; + + /* The MS has opened the conn with a CM Service Request, and we shall + * keep it open for an actual request (or until timeout). */ + bool received_cm_service_request; + + /* libbsc subscriber information (if available) */ + struct bsc_subscr *bsub; + + /* libmsc/libvlr subscriber information (if available) */ + struct vlr_subscr *vsub; + + /* LU expiration handling */ + uint8_t expire_timer_stopped; + /* SMS helpers for libmsc */ + uint8_t next_rp_ref; + + /* + * Operations that have a state and might be pending + */ + struct gsm_security_operation *sec_operation; + struct gsm_anchor_operation *anch_operation; + + struct osmo_fsm_inst *conn_fsm; + + /* Are we part of a special "silent" call */ + int silent_call; + + /* MNCC rtp bridge markers */ + int mncc_rtp_bridge; + int mncc_rtp_create_pending; + int mncc_rtp_connect_pending; + + /* bsc structures */ + struct osmo_bsc_sccp_con *sccp_con; /* BSC */ + + /* back pointers */ + struct gsm_network *network; + + bool in_release; + struct gsm_lchan *lchan; /* BSC */ + struct gsm_lchan *ho_lchan; /* BSC */ + struct gsm_bts *bts; /* BSC */ + + /* for assignment handling */ + struct osmo_timer_list T10; /* BSC */ + struct gsm_lchan *secondary_lchan; /* BSC */ + + /* connected via 2G or 3G? */ + enum ran_type via_ran; + + struct gsm_classmark classmark; + + uint16_t lac; + struct gsm_encr encr; + + struct { + unsigned int mgcp_rtp_endpoint; + uint16_t port_subscr; + uint16_t port_cn; + } rtp; + + /* which Iu-CS connection, if any. */ + struct { + struct ranap_ue_conn_ctx *ue_ctx; + uint8_t rab_id; + } iu; + + struct { + /* A pointer to the SCCP user that handles + * the SCCP connections for this subscriber + * connection */ + struct osmo_sccp_user *scu; + + /* The address of the BSC that is associated + * with this subscriber connection */ + struct osmo_sccp_addr bsc_addr; + + /* The connection identifier that is used + * to reference the SCCP connection that is + * associated with this subscriber connection */ + int conn_id; + } a; +}; + + +#define ROLE_BSC +#include "gsm_data_shared.h" + + +enum { + BSC_CTR_CHREQ_TOTAL, + BSC_CTR_CHREQ_NO_CHANNEL, + BSC_CTR_HANDOVER_ATTEMPTED, + BSC_CTR_HANDOVER_NO_CHANNEL, + BSC_CTR_HANDOVER_TIMEOUT, + BSC_CTR_HANDOVER_COMPLETED, + BSC_CTR_HANDOVER_FAILED, + BSC_CTR_PAGING_ATTEMPTED, + BSC_CTR_PAGING_DETACHED, + BSC_CTR_PAGING_COMPLETED, + BSC_CTR_PAGING_EXPIRED, + BSC_CTR_CHAN_RF_FAIL, + BSC_CTR_CHAN_RLL_ERR, + BSC_CTR_BTS_OML_FAIL, + BSC_CTR_BTS_RSL_FAIL, + BSC_CTR_CODEC_AMR_F, + BSC_CTR_CODEC_AMR_H, + BSC_CTR_CODEC_EFR, + BSC_CTR_CODEC_V1_FR, + BSC_CTR_CODEC_V1_HR, +}; + +static const struct rate_ctr_desc bsc_ctr_description[] = { + [BSC_CTR_CHREQ_TOTAL] = {"chreq.total", "Received channel requests."}, + [BSC_CTR_CHREQ_NO_CHANNEL] = {"chreq.no_channel", "Sent to MS no channel available."}, + [BSC_CTR_HANDOVER_ATTEMPTED] = {"handover.attempted", "Received handover attempts."}, + [BSC_CTR_HANDOVER_NO_CHANNEL] = {"handover.no_channel", "Sent no channel available responses."}, + [BSC_CTR_HANDOVER_TIMEOUT] = {"handover.timeout", "Count the amount of timeouts of timer T3103."}, + [BSC_CTR_HANDOVER_COMPLETED] = {"handover.completed", "Received handover completed."}, + [BSC_CTR_HANDOVER_FAILED] = {"handover.failed", "Receive HO FAIL messages."}, + [BSC_CTR_PAGING_ATTEMPTED] = {"paging.attempted", "Paging attempts for a MS."}, + [BSC_CTR_PAGING_DETACHED] = {"paging.detached", "Counts the amount of paging attempts which couldn't sent out any paging request because no responsible bts found."}, + [BSC_CTR_PAGING_COMPLETED] = {"paging.completed", "Paging successful completed."}, + [BSC_CTR_PAGING_EXPIRED] = {"paging.expired", "Paging Request expired because of timeout T3113."}, + [BSC_CTR_CHAN_RF_FAIL] = {"chan.rf_fail", "Received a RF failure indication from BTS."}, + [BSC_CTR_CHAN_RLL_ERR] = {"chan.rll_err", "Received a RLL failure with T200 cause from BTS."}, + [BSC_CTR_BTS_OML_FAIL] = {"bts.oml_fail", "Received a TEI down on a OML link."}, + [BSC_CTR_BTS_RSL_FAIL] = {"bts.rsl_fail", "Received a TEI down on a OML link."}, + [BSC_CTR_CODEC_AMR_F] = {"bts.codec_amr_f", "Count the usage of AMR/F codec by channel mode requested."}, + [BSC_CTR_CODEC_AMR_H] = {"bts.codec_amr_h", "Count the usage of AMR/H codec by channel mode requested."}, + [BSC_CTR_CODEC_EFR] = {"bts.codec_efr", "Count the usage of EFR codec by channel mode requested."}, + [BSC_CTR_CODEC_V1_FR] = {"bts.codec_fr", "Count the usage of FR codec by channel mode requested."}, + [BSC_CTR_CODEC_V1_HR] = {"bts.codec_hr", "Count the usage of HR codec by channel mode requested."}, +}; + +enum { + MSC_CTR_LOC_UPDATE_TYPE_ATTACH, + MSC_CTR_LOC_UPDATE_TYPE_NORMAL, + MSC_CTR_LOC_UPDATE_TYPE_PERIODIC, + MSC_CTR_LOC_UPDATE_TYPE_DETACH, + MSC_CTR_LOC_UPDATE_FAILED, + MSC_CTR_LOC_UPDATE_COMPLETED, + MSC_CTR_SMS_SUBMITTED, + MSC_CTR_SMS_NO_RECEIVER, + MSC_CTR_SMS_DELIVERED, + MSC_CTR_SMS_RP_ERR_MEM, + MSC_CTR_SMS_RP_ERR_OTHER, + MSC_CTR_SMS_DELIVER_UNKNOWN_ERROR, + MSC_CTR_CALL_MO_SETUP, + MSC_CTR_CALL_MO_CONNECT_ACK, + MSC_CTR_CALL_MT_SETUP, + MSC_CTR_CALL_MT_CONNECT, + MSC_CTR_CALL_ACTIVE, + MSC_CTR_CALL_COMPLETE, + MSC_CTR_CALL_INCOMPLETE, +}; + +static const struct rate_ctr_desc msc_ctr_description[] = { + [MSC_CTR_LOC_UPDATE_TYPE_ATTACH] = {"loc_update_type.attach", "Received location update imsi attach requests."}, + [MSC_CTR_LOC_UPDATE_TYPE_NORMAL] = {"loc_update_type.normal", "Received location update normal requests."}, + [MSC_CTR_LOC_UPDATE_TYPE_PERIODIC] = {"loc_update_type.periodic", "Received location update periodic requests."}, + [MSC_CTR_LOC_UPDATE_TYPE_DETACH] = {"loc_update_type.detach", "Received location update detach indication."}, + [MSC_CTR_LOC_UPDATE_FAILED] = {"loc_update_resp.failed", "Rejected location updates."}, + [MSC_CTR_LOC_UPDATE_COMPLETED] = {"loc_update_resp.completed", "Successful location updates."}, + [MSC_CTR_SMS_SUBMITTED] = {"sms.submitted", "Received a RPDU from a MS (MO)."}, + [MSC_CTR_SMS_NO_RECEIVER] = {"sms.no_receiver", "Counts SMS which couldn't routed because no receiver found."}, + [MSC_CTR_SMS_DELIVERED] = {"sms.delivered", "Global SMS Deliver attempts."}, + [MSC_CTR_SMS_RP_ERR_MEM] = {"sms.rp_err_mem", "CAUSE_MT_MEM_EXCEEDED errors of MS responses on a sms deliver attempt."}, + [MSC_CTR_SMS_RP_ERR_OTHER] = {"sms.rp_err_other", "Other error of MS responses on a sms delive attempt."}, + [MSC_CTR_SMS_DELIVER_UNKNOWN_ERROR] = {"sms.deliver_unknown_error", "Unknown error occured during sms delivery."}, + /* FIXME: count also sms delivered */ + [MSC_CTR_CALL_MO_SETUP] = {"call.mo_setup", "Received setup requests from a MS to init a MO call."}, + [MSC_CTR_CALL_MO_CONNECT_ACK] = {"call.mo_connect_ack", "Received a connect ack from MS of a MO call. Call is now succesful connected up."}, + [MSC_CTR_CALL_MT_SETUP] = {"call.mt_setup", "Sent setup requests to the MS (MT)."}, + [MSC_CTR_CALL_MT_CONNECT] = {"call.mt_connect", "Sent a connect to the MS (MT)."}, + [MSC_CTR_CALL_ACTIVE] = {"call.active", "Count total amount of calls that ever reached active state."}, + [MSC_CTR_CALL_COMPLETE] = {"call.complete", "Count total amount of calls which got terminated by disconnect req or ind after reaching active state."}, + [MSC_CTR_CALL_INCOMPLETE] = {"call.incomplete", "Count total amount of call which got terminated by any other reason after reaching active state."}, +}; + + +static const struct rate_ctr_group_desc bsc_ctrg_desc = { + "bsc", + "base station controller", + OSMO_STATS_CLASS_GLOBAL, + ARRAY_SIZE(bsc_ctr_description), + bsc_ctr_description, +}; + +static const struct rate_ctr_group_desc msc_ctrg_desc = { + "msc", + "mobile switching center", + OSMO_STATS_CLASS_GLOBAL, + ARRAY_SIZE(msc_ctr_description), + msc_ctr_description, +}; + +enum gsm_auth_policy { + GSM_AUTH_POLICY_CLOSED, /* only subscribers authorized in DB */ + GSM_AUTH_POLICY_ACCEPT_ALL, /* accept everyone, even if not authorized in DB */ + GSM_AUTH_POLICY_TOKEN, /* accept first, send token per sms, then revoke authorization */ + GSM_AUTH_POLICY_REGEXP, /* accept IMSIs matching given regexp */ +}; + +#define GSM_T3101_DEFAULT 10 /* s */ +#define GSM_T3103_DEFAULT 5 /* s */ +#define GSM_T3105_DEFAULT 100 /* ms */ +#define GSM_T3107_DEFAULT 5 /* s */ +#define GSM_T3109_DEFAULT 19 /* s, must be 2s + radio_link_timeout*0.48 */ +#define GSM_T3111_DEFAULT 2 /* s */ +#define GSM_T3113_DEFAULT 60 +#define GSM_T3115_DEFAULT 10 +#define GSM_T3117_DEFAULT 10 +#define GSM_T3119_DEFAULT 10 +#define GSM_T3122_DEFAULT 10 +#define GSM_T3141_DEFAULT 10 + +struct gsm_tz { + int override; /* if 0, use system's time zone instead. */ + int hr; /* hour */ + int mn; /* minute */ + int dst; /* daylight savings */ +}; + +struct gsm_network { + /* TODO MSCSPLIT the gsm_network struct is basically a kitchen sink for + * global settings and variables, "madly" mixing BSC and MSC stuff. Split + * this in e.g. struct osmo_bsc and struct osmo_msc, with the things + * these have in common, like country and network code, put in yet + * separate structs and placed as members in osmo_bsc and osmo_msc. */ + + /* global parameters */ + uint16_t country_code; + uint16_t network_code; + char *name_long; + char *name_short; + enum gsm_auth_policy auth_policy; + regex_t authorized_regexp; + char *authorized_reg_str; + enum gsm48_reject_value reject_cause; + int a5_encryption; + bool authentication_required; + int neci; + int send_mm_info; + struct { + int active; + /* Window RXLEV averaging */ + unsigned int win_rxlev_avg; /* number of SACCH frames */ + /* Window RXQUAL averaging */ + unsigned int win_rxqual_avg; /* number of SACCH frames */ + /* Window RXLEV neighbouring cells averaging */ + unsigned int win_rxlev_avg_neigh; /* number of SACCH frames */ + + /* how often should we check for power budget HO */ + unsigned int pwr_interval; /* SACCH frames */ + /* how much better does a neighbor cell have to be ? */ + unsigned int pwr_hysteresis; /* dBm */ + /* maximum distacne before we try a handover */ + unsigned int max_distance; /* TA values */ + } handover; + + struct rate_ctr_group *bsc_ctrs; + struct rate_ctr_group *msc_ctrs; + struct osmo_counter *active_calls; + + /* layer 4 */ + struct mncc_sock_state *mncc_state; + mncc_recv_cb_t mncc_recv; + struct llist_head upqueue; + /* + * TODO: Move the trans_list into the subscriber connection and + * create a pending list for MT transactions. These exist before + * we have a subscriber connection. + */ + struct llist_head trans_list; + struct bsc_api *bsc_api; + + unsigned int num_bts; + struct llist_head bts_list; + + /* timer values */ + int T3101; + int T3103; + int T3105; + int T3107; + int T3109; + int T3111; + int T3113; + int T3115; + int T3117; + int T3119; + int T3122; + int T3141; + + /* timer to expire old location updates */ + struct osmo_timer_list subscr_expire_timer; + + /* Radio Resource Location Protocol (TS 04.31) */ + struct { + enum rrlp_mode mode; + } rrlp; + + enum gsm_chan_t ctype_by_chreq[18]; + + /* Use a TCH for handling requests of type paging any */ + int pag_any_tch; + + /* MSC data in case we are a true BSC */ + struct osmo_bsc_data *bsc_data; + + struct gsm_sms_queue *sms_queue; + + /* control interface */ + struct ctrl_handle *ctrl; + + /* Allow or disallow TCH/F on dynamic TCH/F_TCH/H_PDCH; OS#1778 */ + bool dyn_ts_allow_tch_f; + + /* all active subscriber connections. */ + struct llist_head subscr_conns; + + /* if override is nonzero, this timezone data is used for all MM + * contexts. */ + /* TODO: in OsmoNITB, tz-override used to be BTS-specific. To enable + * BTS|RNC specific timezone overrides for multi-tz networks in + * OsmoMSC, this should be tied to the location area code (LAC). */ + struct gsm_tz tz; + + /* List of all struct bsc_subscr used in libbsc. This llist_head is + * allocated so that the llist_head pointer itself can serve as a + * talloc context (useful to not have to pass the entire gsm_network + * struct to the bsc_subscr_* API, and for bsc_susbscr unit tests to + * not require gsm_data.h). In an MSC-without-BSC environment, this + * pointer is NULL to indicate absence of a bsc_subscribers list. */ + struct llist_head *bsc_subscribers; + + /* MSC: GSUP server address of the HLR */ + const char *gsup_server_addr_str; + uint16_t gsup_server_port; + + struct vlr_instance *vlr; + + /* Periodic location update default value */ + uint8_t t3212; + + struct { + struct mgcpgw_client_conf conf; + struct mgcpgw_client *client; + } mgcpgw; + + struct { + /* CS7 instance id number (set via VTY) */ + uint32_t cs7_instance; + int rab_assign_addr_enc; + struct osmo_sccp_instance *sccp; + } iu; + + struct { + /* CS7 instance id number (set via VTY) */ + uint32_t cs7_instance; + /* A list with the context information about + * all BSCs we have connections with */ + struct llist_head bscs; + struct osmo_sccp_instance *sccp; + } a; +}; + +struct osmo_esme; + +enum gsm_sms_source_id { + SMS_SOURCE_UNKNOWN = 0, + SMS_SOURCE_MS, /* received from MS */ + SMS_SOURCE_VTY, /* received from VTY */ + SMS_SOURCE_SMPP, /* received via SMPP */ +}; + +#define SMS_HDR_SIZE 128 +#define SMS_TEXT_SIZE 256 + +struct gsm_sms_addr { + uint8_t ton; + uint8_t npi; + char addr[21+1]; +}; + +struct gsm_sms { + unsigned long long id; + struct vlr_subscr *receiver; + struct gsm_sms_addr src, dst; + enum gsm_sms_source_id source; + + struct { + uint8_t transaction_id; + uint32_t msg_ref; + } gsm411; + + struct { + struct osmo_esme *esme; + uint32_t sequence_nr; + int transaction_mode; + char msg_id[16]; + } smpp; + + unsigned long validity_minutes; + time_t created; + bool is_report; + uint8_t reply_path_req; + uint8_t status_rep_req; + uint8_t ud_hdr_ind; + uint8_t protocol_id; + uint8_t data_coding_scheme; + uint8_t msg_ref; + uint8_t user_data_len; + uint8_t user_data[SMS_TEXT_SIZE]; + + char text[SMS_TEXT_SIZE]; +}; + +extern void talloc_ctx_init(void *ctx_root); + +int gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type); + +enum gsm_bts_type parse_btstype(const char *arg); +const char *btstype2str(enum gsm_bts_type type); +struct gsm_bts *gsm_bts_by_lac(struct gsm_network *net, unsigned int lac, + struct gsm_bts *start_bts); + +extern void *tall_bsc_ctx; +extern int ipacc_rtp_direct; + +/* this actaully refers to the IPA transport, not the BTS model */ +static inline int is_ipaccess_bts(struct gsm_bts *bts) +{ + switch (bts->type) { + case GSM_BTS_TYPE_NANOBTS: + case GSM_BTS_TYPE_OSMOBTS: + return 1; + default: + break; + } + return 0; +} + +static inline int is_sysmobts_v2(struct gsm_bts *bts) +{ + switch (bts->type) { + case GSM_BTS_TYPE_OSMOBTS: + return 1; + default: + break; + } + return 0; +} + +static inline int is_siemens_bts(struct gsm_bts *bts) +{ + switch (bts->type) { + case GSM_BTS_TYPE_BS11: + return 1; + default: + break; + } + + return 0; +} + +static inline int is_nokia_bts(struct gsm_bts *bts) +{ + switch (bts->type) { + case GSM_BTS_TYPE_NOKIA_SITE: + return 1; + default: + break; + } + + return 0; +} + +static inline int is_e1_bts(struct gsm_bts *bts) +{ + switch (bts->type) { + case GSM_BTS_TYPE_BS11: + case GSM_BTS_TYPE_RBS2000: + case GSM_BTS_TYPE_NOKIA_SITE: + return 1; + default: + break; + } + + return 0; +} + +enum gsm_auth_policy gsm_auth_policy_parse(const char *arg); +const char *gsm_auth_policy_name(enum gsm_auth_policy policy); + +enum rrlp_mode rrlp_mode_parse(const char *arg); +const char *rrlp_mode_name(enum rrlp_mode mode); + +enum bts_gprs_mode bts_gprs_mode_parse(const char *arg, int *valid); +const char *bts_gprs_mode_name(enum bts_gprs_mode mode); +int bts_gprs_mode_is_compat(struct gsm_bts *bts, enum bts_gprs_mode mode); + +int gsm48_ra_id_by_bts(uint8_t *buf, struct gsm_bts *bts); +void gprs_ra_id_by_bts(struct gprs_ra_id *raid, struct gsm_bts *bts); + +int gsm_btsmodel_set_feature(struct gsm_bts_model *model, enum gsm_bts_features feat); +int gsm_bts_model_register(struct gsm_bts_model *model); + +struct gsm_subscriber_connection *bsc_subscr_con_allocate(struct gsm_lchan *lchan); +void bsc_subscr_con_free(struct gsm_subscriber_connection *conn); + +struct gsm_subscriber_connection *msc_subscr_con_allocate(struct gsm_network *network); +void msc_subscr_con_free(struct gsm_subscriber_connection *conn); + +struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net, + enum gsm_bts_type type, + uint8_t bsic); + +void set_ts_e1link(struct gsm_bts_trx_ts *ts, uint8_t e1_nr, + uint8_t e1_ts, uint8_t e1_ts_ss); + +void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked); +bool gsm_btsmodel_has_feature(struct gsm_bts_model *model, enum gsm_bts_features feat); +struct gsm_bts_trx *gsm_bts_trx_by_nr(struct gsm_bts *bts, int nr); +int gsm_bts_trx_set_system_infos(struct gsm_bts_trx *trx); +int gsm_bts_set_system_infos(struct gsm_bts *bts); + +/* generic E1 line operations for all ISDN-based BTS. */ +extern struct e1inp_line_ops bts_isdn_e1inp_line_ops; + +extern const struct value_string bts_type_names[_NUM_GSM_BTS_TYPE+1]; +extern const struct value_string bts_type_descs[_NUM_GSM_BTS_TYPE+1]; + +/* control interface handling */ +int bsc_base_ctrl_cmds_install(void); +int msc_ctrl_cmds_install(struct gsm_network *net); + +/* dependency handling */ +void bts_depend_mark(struct gsm_bts *bts, int dep); +void bts_depend_clear(struct gsm_bts *bts, int dep); +int bts_depend_check(struct gsm_bts *bts); +int bts_depend_is_depedency(struct gsm_bts *base, struct gsm_bts *other); + +int gsm_bts_get_radio_link_timeout(const struct gsm_bts *bts); +void gsm_bts_set_radio_link_timeout(struct gsm_bts *bts, int value); + +bool classmark_is_r99(struct gsm_classmark *cm); + +#endif /* _GSM_DATA_H */ diff --git a/include/osmocom/msc/gsm_data_shared.h b/include/osmocom/msc/gsm_data_shared.h new file mode 100644 index 000000000..5028a269d --- /dev/null +++ b/include/osmocom/msc/gsm_data_shared.h @@ -0,0 +1,1003 @@ +#ifndef _GSM_DATA_SHAREDH +#define _GSM_DATA_SHAREDH + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifndef ROLE_BSC +#include +#endif + +#include + +/* 16 is the max. number of SI2quater messages according to 3GPP TS 44.018 Table 10.5.2.33b.1: + 4-bit index is used (2#1111 = 10#15) */ +#define SI2Q_MAX_NUM 16 +/* length in bits (for single SI2quater message) */ +#define SI2Q_MAX_LEN 160 +#define SI2Q_MIN_LEN 18 + +struct osmo_bsc_data; + +struct osmo_bsc_sccp_con; +struct gsm_sms_queue; + +/* RRLP mode of operation */ +enum rrlp_mode { + RRLP_MODE_NONE, + RRLP_MODE_MS_BASED, + RRLP_MODE_MS_PREF, + RRLP_MODE_ASS_PREF, +}; + +/* Channel Request reason */ +enum gsm_chreq_reason_t { + GSM_CHREQ_REASON_EMERG, + GSM_CHREQ_REASON_PAG, + GSM_CHREQ_REASON_CALL, + GSM_CHREQ_REASON_LOCATION_UPD, + GSM_CHREQ_REASON_OTHER, + GSM_CHREQ_REASON_PDCH, +}; + +/* lchans 0..3 are SDCCH in combined channel configuration, + use 4 as magic number for BCCH hack - see osmo-bts-../oml.c:opstart_compl() */ +#define CCCH_LCHAN 4 + +#define TRX_NR_TS 8 +#define TS_MAX_LCHAN 8 + +#define HARDCODED_ARFCN 123 +#define HARDCODED_BSIC 0x3f /* NCC = 7 / BCC = 7 */ + +/* for multi-drop config */ +#define HARDCODED_BTS0_TS 1 +#define HARDCODED_BTS1_TS 6 +#define HARDCODED_BTS2_TS 11 + +#define MAX_VERSION_LENGTH 64 + +#define MAX_BTS_FEATURES 128 + +enum gsm_hooks { + GSM_HOOK_NM_SWLOAD, + GSM_HOOK_RR_PAGING, + GSM_HOOK_RR_SECURITY, +}; + +enum gsm_paging_event { + GSM_PAGING_SUCCEEDED, + GSM_PAGING_EXPIRED, + GSM_PAGING_OOM, + GSM_PAGING_BUSY, +}; + +enum bts_gprs_mode { + BTS_GPRS_NONE = 0, + BTS_GPRS_GPRS = 1, + BTS_GPRS_EGPRS = 2, +}; + +struct gsm_lchan; +struct gsm_mncc; +struct osmo_rtp_socket; +struct rtp_socket; +struct bsc_api; + +/* Network Management State */ +struct gsm_nm_state { + uint8_t operational; + uint8_t administrative; + uint8_t availability; +}; + +struct gsm_abis_mo { + uint8_t obj_class; + uint8_t procedure_pending; + struct abis_om_obj_inst obj_inst; + const char *name; + struct gsm_nm_state nm_state; + struct tlv_parsed *nm_attr; + struct gsm_bts *bts; +}; + +/* Ericsson OM2000 Managed Object */ +struct abis_om2k_mo { + uint8_t class; + uint8_t bts; + uint8_t assoc_so; + uint8_t inst; +} __attribute__ ((packed)); + +struct om2k_mo { + struct abis_om2k_mo addr; + struct osmo_fsm_inst *fsm; +}; + +#define A38_XOR_MIN_KEY_LEN 12 +#define A38_XOR_MAX_KEY_LEN 16 +#define A38_COMP128_KEY_LEN 16 +#define RSL_ENC_ALG_A5(x) (x+1) +#define MAX_EARFCN_LIST 32 + +/* is the data link established? who established it? */ +#define LCHAN_SAPI_UNUSED 0 +#define LCHAN_SAPI_MS 1 +#define LCHAN_SAPI_NET 2 +#define LCHAN_SAPI_REL 3 + +/* state of a logical channel */ +enum gsm_lchan_state { + LCHAN_S_NONE, /* channel is not active */ + LCHAN_S_ACT_REQ, /* channel activation requested */ + LCHAN_S_ACTIVE, /* channel is active and operational */ + LCHAN_S_REL_REQ, /* channel release has been requested */ + LCHAN_S_REL_ERR, /* channel is in an error state */ + LCHAN_S_BROKEN, /* channel is somehow unusable */ + LCHAN_S_INACTIVE, /* channel is set inactive */ +}; + +/* BTS ONLY */ +#define MAX_NUM_UL_MEAS 104 +#define LC_UL_M_F_L1_VALID (1 << 0) +#define LC_UL_M_F_RES_VALID (1 << 1) + +struct bts_ul_meas { + /* BER in units of 0.01%: 10.000 == 100% ber, 0 == 0% ber */ + uint16_t ber10k; + /* timing advance offset (in quarter bits) */ + int16_t ta_offs_qbits; + /* C/I ratio in dB */ + float c_i; + /* flags */ + uint8_t is_sub:1; + /* RSSI in dBm * -1 */ + uint8_t inv_rssi; +}; + +struct bts_codec_conf { + uint8_t hr; + uint8_t efr; + uint8_t amr; +}; + +struct amr_mode { + uint8_t mode; + uint8_t threshold; + uint8_t hysteresis; +}; + +struct amr_multirate_conf { + uint8_t gsm48_ie[2]; + struct amr_mode ms_mode[4]; + struct amr_mode bts_mode[4]; + uint8_t num_modes; +}; +/* /BTS ONLY */ + +enum lchan_csd_mode { + LCHAN_CSD_M_NT, + LCHAN_CSD_M_T_1200_75, + LCHAN_CSD_M_T_600, + LCHAN_CSD_M_T_1200, + LCHAN_CSD_M_T_2400, + LCHAN_CSD_M_T_9600, + LCHAN_CSD_M_T_14400, + LCHAN_CSD_M_T_29000, + LCHAN_CSD_M_T_32000, +}; + +/* State of the SAPIs in the lchan */ +enum lchan_sapi_state { + LCHAN_SAPI_S_NONE, + LCHAN_SAPI_S_REQ, + LCHAN_SAPI_S_ASSIGNED, + LCHAN_SAPI_S_REL, + LCHAN_SAPI_S_ERROR, +}; + +struct gsm_lchan { + /* The TS that we're part of */ + struct gsm_bts_trx_ts *ts; + /* The logical subslot number in the TS */ + uint8_t nr; + /* The logical channel type */ + enum gsm_chan_t type; + /* RSL channel mode */ + enum rsl_cmod_spd rsl_cmode; + /* If TCH, traffic channel mode */ + enum gsm48_chan_mode tch_mode; + enum lchan_csd_mode csd_mode; + /* State */ + enum gsm_lchan_state state; + const char *broken_reason; + /* Power levels for MS and BTS */ + uint8_t bs_power; + uint8_t ms_power; + /* Encryption information */ + struct gsm_encr encr; + + /* AMR bits */ + uint8_t mr_ms_lv[7]; + uint8_t mr_bts_lv[7]; + + /* Established data link layer services */ + uint8_t sapis[8]; + int sacch_deact; + + struct { + uint32_t bound_ip; + uint32_t connect_ip; + uint16_t bound_port; + uint16_t connect_port; + uint16_t conn_id; + uint8_t rtp_payload; + uint8_t rtp_payload2; + uint8_t speech_mode; +#ifdef ROLE_BSC + struct rtp_socket *rtp_socket; + + /* info we need to postpone the AoIP + * assignment completed message */ + struct { + uint8_t rr_cause; + uint8_t chosen_channel; + uint8_t encr_alg_id; + uint8_t speech_mode; + bool valid; + } ass_compl; +#else + struct osmo_rtp_socket *rtp_socket; +#endif + } abis_ip; + + uint8_t rqd_ta; + + char *name; + +#ifdef ROLE_BSC + struct osmo_timer_list T3101; + struct osmo_timer_list T3109; + struct osmo_timer_list T3111; + struct osmo_timer_list error_timer; + struct osmo_timer_list act_timer; + struct osmo_timer_list rel_work; + uint8_t error_cause; + + /* table of neighbor cell measurements */ + struct neigh_meas_proc neigh_meas[MAX_NEIGH_MEAS]; + + /* cache of last measurement reports on this lchan */ + struct gsm_meas_rep meas_rep[6]; + int meas_rep_idx; + + /* GSM Random Access data */ + struct gsm48_req_ref *rqd_ref; + + struct gsm_subscriber_connection *conn; + + struct { + /* channel activation type and handover ref */ + uint8_t act_type; + uint8_t ho_ref; + struct gsm48_req_ref *rqd_ref; + uint8_t rqd_ta; + } dyn; +#else + /* Number of different GsmL1_Sapi_t used in osmo_bts_sysmo is 23. + * Currently we don't share these headers so this is a magic number. */ + struct llist_head sapi_cmds; + uint8_t sapis_dl[23]; + uint8_t sapis_ul[23]; + struct lapdm_channel lapdm_ch; + struct llist_head dl_tch_queue; + struct { + /* bitmask of all SI that are present/valid in si_buf */ + uint32_t valid; + uint32_t last; + /* buffers where we put the pre-computed SI: + SI2Q_MAX_NUM is the max number of SI2quater messages (see 3GPP TS 44.018) */ + sysinfo_buf_t buf[_MAX_SYSINFO_TYPE][SI2Q_MAX_NUM]; + } si; + struct { + uint8_t flags; + /* RSL measurment result number, 0 at lchan_act */ + uint8_t res_nr; + /* current Tx power level of the BTS */ + uint8_t bts_tx_pwr; + /* number of measurements stored in array below */ + uint8_t num_ul_meas; + struct bts_ul_meas uplink[MAX_NUM_UL_MEAS]; + /* last L1 header from the MS */ + uint8_t l1_info[2]; + struct gsm_meas_rep_unidir ul_res; + } meas; + struct { + struct amr_multirate_conf amr_mr; + struct { + struct osmo_fsm_inst *dl_amr_fsm; + /* TCH cache */ + uint8_t cache[20]; + /* FACCH cache */ + uint8_t facch[GSM_MACBLOCK_LEN]; + uint8_t len; + uint32_t fn; + bool is_update; + /* set for each SID frame to detect talkspurt for codecs + without explicit ONSET event */ + bool ul_sid; + /* indicates if DTXd was active during DL measurement + period */ + bool dl_active; + } dtx; + uint8_t last_cmr; + uint32_t last_fn; + } tch; + + /* 3GPP TS 48.058 ยง 9.3.37: [0; 255] ok, -1 means invalid*/ + int16_t ms_t_offs; + /* 3GPP TS 45.010 ยง 1.2 round trip propagation delay (in symbols) or -1 */ + int16_t p_offs; + + /* BTS-side ciphering state (rx only, bi-directional, ...) */ + uint8_t ciph_state; + uint8_t ciph_ns; + uint8_t loopback; + struct { + uint8_t active; + uint8_t ref; + /* T3105: PHYS INF retransmission */ + struct osmo_timer_list t3105; + /* counts up to Ny1 */ + unsigned int phys_info_count; + } ho; + /* S counter for link loss */ + int s; + /* Kind of the release/activation. E.g. RSL or PCU */ + int rel_act_kind; + /* RTP header Marker bit to indicate beginning of speech after pause */ + bool rtp_tx_marker; + /* power handling */ + struct { + uint8_t current; + uint8_t fixed; + } ms_power_ctrl; + + struct msgb *pending_rel_ind_msg; +#endif +}; + +enum { + TS_F_PDCH_ACTIVE = 0x1000, + TS_F_PDCH_ACT_PENDING = 0x2000, + TS_F_PDCH_DEACT_PENDING = 0x4000, + TS_F_PDCH_PENDING_MASK = 0x6000 /*< + TS_F_PDCH_ACT_PENDING | TS_F_PDCH_DEACT_PENDING */ +} gsm_bts_trx_ts_flags; + +/* One Timeslot in a TRX */ +struct gsm_bts_trx_ts { + struct gsm_bts_trx *trx; + /* number of this timeslot at the TRX */ + uint8_t nr; + + enum gsm_phys_chan_config pchan; + + struct { + enum gsm_phys_chan_config pchan_is; + enum gsm_phys_chan_config pchan_want; + struct msgb *pending_chan_activ; + } dyn; + + unsigned int flags; + struct gsm_abis_mo mo; + struct tlv_parsed nm_attr; + uint8_t nm_chan_comb; + int tsc; /* -1 == use BTS TSC */ + + struct { + /* Parameters below are configured by VTY */ + int enabled; + uint8_t maio; + uint8_t hsn; + struct bitvec arfcns; + uint8_t arfcns_data[1024/8]; + /* This is the pre-computed MA for channel assignments */ + struct bitvec ma; + uint8_t ma_len; /* part of ma_data that is used */ + uint8_t ma_data[8]; /* 10.5.2.21: max 8 bytes value part */ + } hopping; + + /* To which E1 subslot are we connected */ + struct gsm_e1_subslot e1_link; + + union { + struct { + struct om2k_mo om2k_mo; + } rbs2000; + }; + + struct gsm_lchan lchan[TS_MAX_LCHAN]; +}; + +/* One TRX in a BTS */ +struct gsm_bts_trx { + /* list header in bts->trx_list */ + struct llist_head list; + + struct gsm_bts *bts; + /* number of this TRX in the BTS */ + uint8_t nr; + /* human readable name / description */ + char *description; + /* how do we talk RSL with this TRX? */ + struct gsm_e1_subslot rsl_e1_link; + uint8_t rsl_tei; + struct e1inp_sign_link *rsl_link; + + /* Some BTS (specifically Ericsson RBS) have a per-TRX OML Link */ + struct e1inp_sign_link *oml_link; + + struct gsm_abis_mo mo; + struct tlv_parsed nm_attr; + struct { + struct gsm_abis_mo mo; + } bb_transc; + + uint16_t arfcn; + int nominal_power; /* in dBm */ + unsigned int max_power_red; /* in actual dB */ + +#ifndef ROLE_BSC + struct trx_power_params power_params; + int ms_power_control; + + struct { + void *l1h; + } role_bts; +#endif + + union { + struct { + struct { + struct gsm_abis_mo mo; + } bbsig; + struct { + struct gsm_abis_mo mo; + } pa; + } bs11; + struct { + unsigned int test_state; + uint8_t test_nr; + struct rxlev_stats rxlev_stat; + } ipaccess; + struct { + struct { + struct om2k_mo om2k_mo; + } trxc; + struct { + struct om2k_mo om2k_mo; + } rx; + struct { + struct om2k_mo om2k_mo; + } tx; + } rbs2000; + }; + struct gsm_bts_trx_ts ts[TRX_NR_TS]; +}; + +#define GSM_BTS_SI2Q(bts, i) (struct gsm48_system_information_type_2quater *)((bts)->si_buf[SYSINFO_TYPE_2quater][i]) +#define GSM_BTS_HAS_SI(bts, i) ((bts)->si_valid & (1 << i)) +#define GSM_BTS_SI(bts, i) (void *)((bts)->si_buf[i][0]) +#define GSM_LCHAN_SI(lchan, i) (void *)((lchan)->si.buf[i][0]) + +enum gsm_bts_type { + GSM_BTS_TYPE_UNKNOWN, + GSM_BTS_TYPE_BS11, + GSM_BTS_TYPE_NANOBTS, + GSM_BTS_TYPE_RBS2000, + GSM_BTS_TYPE_NOKIA_SITE, + GSM_BTS_TYPE_OSMOBTS, + _NUM_GSM_BTS_TYPE +}; + +enum gsm_bts_type_variant { + BTS_UNKNOWN, + BTS_OSMO_LITECELL15, + BTS_OSMO_OCTPHY, + BTS_OSMO_SYSMO, + BTS_OSMO_TRX, + _NUM_BTS_VARIANT +}; + +/* Used by OML layer for BTS Attribute reporting */ +enum bts_attribute { + BTS_TYPE_VARIANT, + BTS_SUB_MODEL, + TRX_PHY_VERSION, +}; + +struct vty; + +struct gsm_bts_model { + struct llist_head list; + + enum gsm_bts_type type; + enum gsm_bts_type_variant variant; + const char *name; + + bool started; + int (*start)(struct gsm_network *net); + int (*oml_rcvmsg)(struct msgb *msg); + + void (*e1line_bind_ops)(struct e1inp_line *line); + + void (*config_write_bts)(struct vty *vty, struct gsm_bts *bts); + void (*config_write_trx)(struct vty *vty, struct gsm_bts_trx *trx); + void (*config_write_ts)(struct vty *vty, struct gsm_bts_trx_ts *ts); + + struct tlv_definition nm_att_tlvdef; + + /* features of a given BTS model set via gsm_bts_model_register() locally */ + struct bitvec features; + uint8_t _features_data[MAX_BTS_FEATURES/8]; +}; + +/* N. B: always add new features to the end of the list (right before _NUM_BTS_FEAT) to avoid breaking compatibility + with BTS compiled against earlier version of this header */ +enum gsm_bts_features { + BTS_FEAT_HSCSD, + BTS_FEAT_GPRS, + BTS_FEAT_EGPRS, + BTS_FEAT_ECSD, + BTS_FEAT_HOPPING, + BTS_FEAT_MULTI_TSC, + BTS_FEAT_OML_ALERTS, + BTS_FEAT_AGCH_PCH_PROP, + BTS_FEAT_CBCH, + _NUM_BTS_FEAT +}; + +extern const struct value_string gsm_bts_features_descs[]; + +/* + * This keeps track of the paging status of one BTS. It + * includes a number of pending requests, a back pointer + * to the gsm_bts, a timer and some more state. + */ +struct gsm_bts_paging_state { + /* pending requests */ + struct llist_head pending_requests; + struct gsm_bts *bts; + + struct osmo_timer_list work_timer; + struct osmo_timer_list credit_timer; + + /* free chans needed */ + int free_chans_need; + + /* load */ + uint16_t available_slots; +}; + +struct gsm_envabtse { + struct gsm_abis_mo mo; +}; + +struct gsm_bts_gprs_nsvc { + struct gsm_bts *bts; + /* data read via VTY config file, to configure the BTS + * via OML from BSC */ + int id; + uint16_t nsvci; + uint16_t local_port; /* on the BTS */ + uint16_t remote_port; /* on the SGSN */ + uint32_t remote_ip; /* on the SGSN */ + + struct gsm_abis_mo mo; +}; + +enum gprs_rlc_par { + RLC_T3142, + RLC_T3169, + RLC_T3191, + RLC_T3193, + RLC_T3195, + RLC_N3101, + RLC_N3103, + RLC_N3105, + CV_COUNTDOWN, + T_DL_TBF_EXT, /* ms */ + T_UL_TBF_EXT, /* ms */ + _NUM_RLC_PAR +}; + +enum gprs_cs { + GPRS_CS1, + GPRS_CS2, + GPRS_CS3, + GPRS_CS4, + GPRS_MCS1, + GPRS_MCS2, + GPRS_MCS3, + GPRS_MCS4, + GPRS_MCS5, + GPRS_MCS6, + GPRS_MCS7, + GPRS_MCS8, + GPRS_MCS9, + _NUM_GRPS_CS +}; + +struct gprs_rlc_cfg { + uint16_t parameter[_NUM_RLC_PAR]; + struct { + uint16_t repeat_time; /* ms */ + uint8_t repeat_count; + } paging; + uint32_t cs_mask; /* bitmask of gprs_cs */ + uint8_t initial_cs; + uint8_t initial_mcs; +}; + + +enum neigh_list_manual_mode { + NL_MODE_AUTOMATIC = 0, + NL_MODE_MANUAL = 1, + NL_MODE_MANUAL_SI5SEP = 2, /* SI2 and SI5 have separate neighbor lists */ +}; + +enum bts_loc_fix { + BTS_LOC_FIX_INVALID = 0, + BTS_LOC_FIX_2D = 1, + BTS_LOC_FIX_3D = 2, +}; + +extern const struct value_string bts_loc_fix_names[]; + +struct bts_location { + struct llist_head list; + time_t tstamp; + enum bts_loc_fix valid; + double lat; + double lon; + double height; +}; + +/* One BTS */ +struct gsm_bts { + /* list header in net->bts_list */ + struct llist_head list; + + /* Geographical location of the BTS */ + struct llist_head loc_list; + + /* number of ths BTS in network */ + uint8_t nr; + /* human readable name / description */ + char *description; + /* Cell Identity */ + uint16_t cell_identity; + /* location area code of this BTS */ + uint16_t location_area_code; + /* Base Station Identification Code (BSIC), lower 3 bits is BCC, + * which is used as TSC for the CCCH */ + uint8_t bsic; + /* type of BTS */ + enum gsm_bts_type type; + enum gsm_bts_type_variant variant; + struct gsm_bts_model *model; + enum gsm_band band; + char version[MAX_VERSION_LENGTH]; + char sub_model[MAX_VERSION_LENGTH]; + + /* features of a given BTS set/reported via OML */ + struct bitvec features; + uint8_t _features_data[MAX_BTS_FEATURES/8]; + + /* Connected PCU version (if any) */ + char pcu_version[MAX_VERSION_LENGTH]; + + /* maximum Tx power that the MS is permitted to use in this cell */ + int ms_max_power; + + /* how do we talk OML with this TRX? */ + struct gsm_e1_subslot oml_e1_link; + uint8_t oml_tei; + struct e1inp_sign_link *oml_link; + + /* Abis network management O&M handle */ + struct abis_nm_h *nmh; + + struct gsm_abis_mo mo; + + /* number of this BTS on given E1 link */ + uint8_t bts_nr; + + /* DTX features of this BTS */ + enum gsm48_dtx_mode dtxu; + bool dtxd; + + /* paging state and control */ + struct gsm_bts_paging_state paging; + + /* CCCH is on C0 */ + struct gsm_bts_trx *c0; + + struct { + struct gsm_abis_mo mo; + } site_mgr; + + /* bitmask of all SI that are present/valid in si_buf */ + uint32_t si_valid; + /* 3GPP TS 44.018 Table 10.5.2.33b.1 INDEX and COUNT for SI2quater */ + uint8_t si2q_index; /* distinguish individual SI2quater messages */ + uint8_t si2q_count; /* si2q_index for the last (highest indexed) individual SI2quater message */ + /* buffers where we put the pre-computed SI */ + sysinfo_buf_t si_buf[_MAX_SYSINFO_TYPE][SI2Q_MAX_NUM]; + /* offsets used while generating SI2quater */ + size_t e_offset; + size_t u_offset; + + /* ip.accesss Unit ID's have Site/BTS/TRX layout */ + union { + struct { + uint16_t site_id; + uint16_t bts_id; + uint32_t flags; + uint32_t rsl_ip; + } ip_access; + struct { + struct { + struct gsm_abis_mo mo; + } cclk; + struct { + struct gsm_abis_mo mo; + } rack; + struct gsm_envabtse envabtse[4]; + } bs11; + struct { + struct { + struct om2k_mo om2k_mo; + struct gsm_abis_mo mo; + struct llist_head conn_groups; + } cf; + struct { + struct om2k_mo om2k_mo; + struct gsm_abis_mo mo; + struct llist_head conn_groups; + } is; + struct { + struct om2k_mo om2k_mo; + struct gsm_abis_mo mo; + struct llist_head conn_groups; + } con; + struct { + struct om2k_mo om2k_mo; + struct gsm_abis_mo mo; + } dp; + struct { + struct om2k_mo om2k_mo; + struct gsm_abis_mo mo; + } tf; + uint32_t use_superchannel:1; + } rbs2000; + struct { + uint8_t bts_type; + unsigned int configured:1, + skip_reset:1, + no_loc_rel_cnf:1, + bts_reset_timer_cnf, + did_reset:1, + wait_reset:1; + struct osmo_timer_list reset_timer; + } nokia; + }; + + /* Not entirely sure how ip.access specific this is */ + struct { + uint8_t supports_egprs_11bit_rach; + enum bts_gprs_mode mode; + struct { + struct gsm_abis_mo mo; + uint16_t nsei; + uint8_t timer[7]; + } nse; + struct { + struct gsm_abis_mo mo; + uint16_t bvci; + uint8_t timer[11]; + struct gprs_rlc_cfg rlc_cfg; + } cell; + struct gsm_bts_gprs_nsvc nsvc[2]; + uint8_t rac; + uint8_t net_ctrl_ord; + bool ctrl_ack_type_use_block; + } gprs; + + /* RACH NM values */ + int rach_b_thresh; + int rach_ldavg_slots; + + /* transceivers */ + int num_trx; + struct llist_head trx_list; + + /* SI related items */ + int force_combined_si; + int bcch_change_mark; + +#ifdef ROLE_BSC + /* Abis NM queue */ + struct llist_head abis_queue; + int abis_nm_pend; + + struct gsm_network *network; + + /* should the channel allocator allocate channels from high TRX to TRX0, + * rather than starting from TRX0 and go upwards? */ + int chan_alloc_reverse; + + enum neigh_list_manual_mode neigh_list_manual_mode; + /* parameters from which we build SYSTEM INFORMATION */ + struct { + struct gsm48_rach_control rach_control; + uint8_t ncc_permitted; + struct gsm48_cell_sel_par cell_sel_par; + struct gsm48_si_selection_params cell_ro_sel_par; /* rest octet */ + struct gsm48_cell_options cell_options; + struct gsm48_control_channel_descr chan_desc; + struct bitvec neigh_list; + struct bitvec cell_alloc; + struct bitvec si5_neigh_list; + struct osmo_earfcn_si2q si2quater_neigh_list; + size_t uarfcn_length; /* index for uarfcn and scramble lists */ + struct { + /* bitmask large enough for all possible ARFCN's */ + uint8_t neigh_list[1024/8]; + uint8_t cell_alloc[1024/8]; + /* If the user wants a different neighbor list in SI5 than in SI2 */ + uint8_t si5_neigh_list[1024/8]; + uint8_t meas_bw_list[MAX_EARFCN_LIST]; + uint16_t earfcn_list[MAX_EARFCN_LIST]; + uint16_t uarfcn_list[MAX_EARFCN_LIST]; + uint16_t scramble_list[MAX_EARFCN_LIST]; + } data; + } si_common; + bool early_classmark_allowed; + /* for testing only: Have an infinitely long radio link timeout */ + bool infinite_radio_link_timeout; + + /* do we use static (user-defined) system information messages? (bitmask) */ + uint32_t si_mode_static; + + /* exclude the BTS from the global RF Lock handling */ + int excl_from_rf_lock; + + /* supported codecs beside FR */ + struct bts_codec_conf codec; + + /* BTS dependencies bit field */ + uint32_t depends_on[256/(8*4)]; + + /* full and half rate multirate config */ + struct amr_multirate_conf mr_full; + struct amr_multirate_conf mr_half; + + /* PCU socket state */ + char *pcu_sock_path; + struct pcu_sock_state *pcu_state; + +#endif /* ROLE_BSC */ + void *role; +}; + + +struct gsm_bts *gsm_bts_alloc(void *talloc_ctx, uint8_t bts_num); +struct gsm_bts *gsm_bts_num(struct gsm_network *net, int num); + +struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts); +struct gsm_bts_trx *gsm_bts_trx_num(const struct gsm_bts *bts, int num); + +enum gsm_bts_type str2btstype(const char *arg); +const char *btstype2str(enum gsm_bts_type type); + +enum bts_attribute str2btsattr(const char *s); +const char *btsatttr2str(enum bts_attribute v); + +enum gsm_bts_type_variant str2btsvariant(const char *arg); +const char *btsvariant2str(enum gsm_bts_type_variant v); + +extern const struct value_string gsm_chreq_descs[]; +const struct value_string gsm_pchant_names[13]; +const struct value_string gsm_pchant_descs[13]; +const char *gsm_pchan_name(enum gsm_phys_chan_config c); +enum gsm_phys_chan_config gsm_pchan_parse(const char *name); +const char *gsm_lchant_name(enum gsm_chan_t c); +const char *gsm_chreq_name(enum gsm_chreq_reason_t c); +char *gsm_trx_name(const struct gsm_bts_trx *trx); +char *gsm_ts_name(const struct gsm_bts_trx_ts *ts); +char *gsm_ts_and_pchan_name(const struct gsm_bts_trx_ts *ts); +char *gsm_lchan_name_compute(const struct gsm_lchan *lchan); +const char *gsm_lchans_name(enum gsm_lchan_state s); + +static inline char *gsm_lchan_name(const struct gsm_lchan *lchan) +{ + return lchan->name; +} + +static inline int gsm_bts_set_feature(struct gsm_bts *bts, enum gsm_bts_features feat) +{ + OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES); + return bitvec_set_bit_pos(&bts->features, feat, 1); +} + +static inline bool gsm_bts_has_feature(const struct gsm_bts *bts, enum gsm_bts_features feat) +{ + OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES); + return bitvec_get_bit_pos(&bts->features, feat); +} + +void gsm_abis_mo_reset(struct gsm_abis_mo *mo); + +struct gsm_abis_mo * +gsm_objclass2mo(struct gsm_bts *bts, uint8_t obj_class, + const struct abis_om_obj_inst *obj_inst); + +struct gsm_nm_state * +gsm_objclass2nmstate(struct gsm_bts *bts, uint8_t obj_class, + const struct abis_om_obj_inst *obj_inst); +void * +gsm_objclass2obj(struct gsm_bts *bts, uint8_t obj_class, + const struct abis_om_obj_inst *obj_inst); + +/* reset the state of all MO in the BTS */ +void gsm_bts_mo_reset(struct gsm_bts *bts); + +uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan, + uint8_t ts_nr, uint8_t lchan_nr); +uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan); +uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan, + enum gsm_phys_chan_config as_pchan); + +/* return the gsm_lchan for the CBCH (if it exists at all) */ +struct gsm_lchan *gsm_bts_get_cbch(struct gsm_bts *bts); + +/* + * help with parsing regexps + */ +int gsm_parse_reg(void *ctx, regex_t *reg, char **str, + int argc, const char **argv) __attribute__ ((warn_unused_result)); + +static inline uint8_t gsm_ts_tsc(const struct gsm_bts_trx_ts *ts) +{ + if (ts->tsc != -1) + return ts->tsc; + else + return ts->trx->bts->bsic & 7; +} + +struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr, + int *rc); + +enum gsm_phys_chan_config ts_pchan(struct gsm_bts_trx_ts *ts); +uint8_t ts_subslots(struct gsm_bts_trx_ts *ts); +bool ts_is_tch(struct gsm_bts_trx_ts *ts); + +#endif diff --git a/include/osmocom/msc/gsm_subscriber.h b/include/osmocom/msc/gsm_subscriber.h new file mode 100644 index 000000000..6b0e3da42 --- /dev/null +++ b/include/osmocom/msc/gsm_subscriber.h @@ -0,0 +1,68 @@ +#ifndef _GSM_SUBSCR_H +#define _GSM_SUBSCR_H + +#include + +#include +#include + +#include + +#define GSM_NAME_LENGTH 160 + +#define GSM_EXTENSION_LENGTH 15 /* MSISDN can only be 15 digits length */ +#define GSM_MIN_EXTEN 20000 +#define GSM_MAX_EXTEN 49999 + +#define GSM_SUBSCRIBER_FIRST_CONTACT 0x00000001 +/* gprs_sgsn.h defines additional flags including and above bit 16 (0x10000) */ + +#define GSM_SUBSCRIBER_NO_EXPIRATION 0x0 + +enum gsm_subscriber_field { + GSM_SUBSCRIBER_IMSI, + GSM_SUBSCRIBER_TMSI, + GSM_SUBSCRIBER_EXTENSION, + GSM_SUBSCRIBER_ID, +}; + +enum gsm_subscriber_update_reason { + GSM_SUBSCRIBER_UPDATE_ATTACHED, + GSM_SUBSCRIBER_UPDATE_DETACHED, + GSM_SUBSCRIBER_UPDATE_EQUIPMENT, +}; + +/* + * Struct for pending channel requests. This is managed in the + * llist_head requests of each subscriber. The reference counting + * should work in such a way that a subscriber with a pending request + * remains in memory. + */ +struct subscr_request { + struct llist_head entry; + + /* human readable label to be able to log pending request kinds */ + const char *label; + + /* the callback data */ + gsm_cbfn *cbfn; + void *param; +}; + +int subscr_update(struct vlr_subscr *vsub, int reason); + +/* + * Paging handling with authentication + */ +struct subscr_request *subscr_request_conn(struct vlr_subscr *vsub, + gsm_cbfn *cbfn, void *param, + const char *label); + +void subscr_remove_request(struct subscr_request *req); +int subscr_rx_paging_response(struct msgb *msg, + struct gsm_subscriber_connection *conn); + +int subscr_paging_dispatch(unsigned int hooknum, unsigned int event, + struct msgb *msg, void *data, void *param); + +#endif /* _GSM_SUBSCR_H */ diff --git a/include/osmocom/msc/gsup_client.h b/include/osmocom/msc/gsup_client.h new file mode 100644 index 000000000..3d1dce078 --- /dev/null +++ b/include/osmocom/msc/gsup_client.h @@ -0,0 +1,63 @@ +/* GPRS Subscriber Update Protocol client */ + +/* (C) 2014 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Jacob Erlbeck + * + * 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 . + * + */ +#pragma once + +#include + +#include + +#define GSUP_CLIENT_RECONNECT_INTERVAL 10 +#define GSUP_CLIENT_PING_INTERVAL 20 + +struct msgb; +struct ipa_client_conn; +struct gsup_client; + +/* Expects message in msg->l2h */ +typedef int (*gsup_client_read_cb_t)(struct gsup_client *gsupc, + struct msgb *msg); + +struct gsup_client { + const char *unit_name; + + struct ipa_client_conn *link; + gsup_client_read_cb_t read_cb; + void *data; + + struct oap_client_state oap_state; + + struct osmo_timer_list ping_timer; + struct osmo_timer_list connect_timer; + int is_connected; + int got_ipa_pong; +}; + +struct gsup_client *gsup_client_create(const char *unit_name, + const char *ip_addr, + unsigned int tcp_port, + gsup_client_read_cb_t read_cb, + struct oap_client_config *oapc_config); + +void gsup_client_destroy(struct gsup_client *gsupc); +int gsup_client_send(struct gsup_client *gsupc, struct msgb *msg); +struct msgb *gsup_client_msgb_alloc(void); + diff --git a/include/osmocom/msc/gtphub.h b/include/osmocom/msc/gtphub.h new file mode 100644 index 000000000..d7b6f1b9e --- /dev/null +++ b/include/osmocom/msc/gtphub.h @@ -0,0 +1,523 @@ +/* GTP Hub Implementation */ + +/* (C) 2015 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * 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 . + */ + +#pragma once + +#include +#include + +#include +#include +#include + +#include + + +/* support */ + +/* TODO move to osmocom/core/socket.c ? */ +#include /* for IPPROTO_* etc */ +struct osmo_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[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 + * \param[in] host Remote host name or IP address in string form + * \param[in] port Remote port number in host byte order + * \returns 0 on success, otherwise an error code (from getaddrinfo()). + * + * 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, + 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, + const char *host, uint16_t port) +{ + return osmo_sockaddr_init(addr, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, + host, port); +} + +/*! \brief convert sockaddr to human readable string. + * \param[out] addr_str Valid pointer to a buffer of length addr_str_len. + * \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] 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 + * 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, + char *port_str, size_t port_str_len, + const struct osmo_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(). + * \param[in] buf A buffer to use for string operations. + * \param[in] buf_len Length of the buffer. + * \returns Address string (in buffer). + * + * Compose a string of the numeric IP-address and port represented by *addr of + * the form " port ". The returned string is valid until the + * next invocation of this function. + */ +const char *osmo_sockaddr_to_strb(const struct osmo_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(). + * \returns Address string in static buffer. + * + * See osmo_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 + * buffer each. + */ +const char *osmo_sockaddr_to_str(const struct osmo_sockaddr *addr); + +/*! \brief compare two osmo_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); + +/*! \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); + + +/* general */ + +enum gtphub_plane_idx { + GTPH_PLANE_CTRL = 0, + GTPH_PLANE_USER = 1, + GTPH_PLANE_N +}; + +enum gtphub_side_idx { + GTPH_SIDE_SGSN = 0, + GTPH_SIDE_GGSN = 1, + GTPH_SIDE_N +}; + +#define for_each_side(I) for (I = 0; I < GTPH_SIDE_N; I++) +#define for_each_plane(I) for (I = 0; I < GTPH_PLANE_N; I++) +#define for_each_side_and_plane(I,J) for_each_side(I) for_each_plane(J) + +static inline int other_side_idx(int side_idx) +{ + return (side_idx + 1) & 1; +} + +extern const char* const gtphub_plane_idx_names[GTPH_PLANE_N]; +extern const uint16_t gtphub_plane_idx_default_port[GTPH_PLANE_N]; + +extern const char* const gtphub_side_idx_names[GTPH_SIDE_N]; + +/* A host address in the form that is expected in the 7.7.32 GSN Address IE. + * len is either 4 (IPv4) or 16 (IPv6), any other value is invalid. If no + * address is set, len shall be 0. */ +struct gsn_addr { + uint16_t len; + uint8_t buf[16]; +}; + +void gsn_addr_copy(struct gsn_addr *gsna, const struct gsn_addr *src); +int gsn_addr_from_str(struct gsn_addr *gsna, const char *numeric_addr_str); + +/* Return gsna in numeric string form, in a static buffer. */ +const char *gsn_addr_to_str(const struct gsn_addr *gsna); + +/* note: strbuf_len doesn't need to be larger than INET6_ADDRSTRLEN + 1. */ +const char *gsn_addr_to_strb(const struct gsn_addr *gsna, + char *strbuf, int strbuf_len); + +/* Return 1 on match, zero otherwise. */ +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); + +/* expiry */ + +struct expiring_item; +typedef void (*del_cb_t)(struct expiring_item *); + +struct expiring_item { + struct llist_head entry; + time_t expiry; + del_cb_t del_cb; +}; + +struct expiry { + int expiry_in_seconds; + struct llist_head items; +}; + +/* Initialize an expiry queue. */ +void expiry_init(struct expiry *exq, int expiry_in_seconds); + +/* Add a new mapping, or restart the expiry timeout for an already listed + * mapping. */ +void expiry_add(struct expiry *exq, struct expiring_item *item, time_t now); + +/* Initialize to all-empty; must be called before using the item in any way. */ +void expiring_item_init(struct expiring_item *item); + +/* Remove the given item from its expiry queue, and call item->del_cb, if set. + * This sets item->del_cb to NULL and is harmless when run a second time on the + * same item, so the del_cb may choose to call this function, too, to allow + * deleting items from several code paths. */ +void expiring_item_del(struct expiring_item *item); + +/* Carry out due expiry of mappings. Must be invoked regularly. + * 'now' is the current clock count in seconds and must correspond to the clock + * count passed to nr_map_add(). A monotonous clock counter should be used. */ +int expiry_tick(struct expiry *exq, time_t now); + +/* Expire all items. */ +void expiry_clear(struct expiry *exq); + + +/* number map */ + +/* A number map assigns a "random" mapped number to each user provided number. + * If the same number is requested multiple times, the same mapped number is + * returned. + * + * Number maps plug into possibly shared pools and expiry queues, for example: + * + * mapA -----------+-> pool1 <-+-- mapB + * {10->1, 11->5} | {1, 2, 3, ...} | {10->2, 11->3} + * | | + * | | + * /-> \-> expiry1 <-/ + * | (30 seconds) + * | + * mapC -------+-----> pool2 <-+-- mapD + * {10->1, 11->3} {1, 2, 3, ...} | {10->2, 11->5} + * | + * expiry2 <-/ + * (60 seconds) + * + * A map contains mappings ("10->1"). Each map needs a number pool, which can + * be shared with other maps. Each new mapping receives a number from the pool, + * which is then unavailable to any other map using the same pool. + * + * A map may point at an expiry queue, in which case all mappings added to it + * are also appended to the expiry queue (using a separate llist entry in the + * mapping). Any number of maps may submit to the same expiry queue, if they + * desire the same expiry timeout. An expiry queue stores the mappings in + * chronological order, so that expiry checking is needed only from the start + * of the queue; hence only mappings with identical expiry timeout can be added + * to the same expiry queue. Upon expiry, a mapping is dropped from the map it + * was submitted at. expiry_tick() needs to be called regularly for each expiry + * queue. + * + * A nr_mapping can be embedded in a larger struct: each mapping can have a + * distinct destructor (del_cb), and each del_cb can figure out the container + * struct's address and free that upon expiry or manual deletion. So in expiry + * queues (and even maps), mappings of different container types can be mixed. + * This can help to drastically reduce the amount of unnecessary visits during + * expiry checking, for the case that no expiry is pending. An expiry queue + * always knows which mappings to expire next, because they are right at the + * start of its list. + * + * Mapping allocation and a del_cb are provided by the caller. If del_cb is + * NULL, no deallocation will be done (allowing statically allocated entries). + */ + +typedef unsigned int nr_t; + +/* Generator for unused numbers. So far this counts upwards from zero, but the + * implementation may change in the future. Treat this like an opaque struct. + * If this becomes random, the tests need to be fixed. */ +struct nr_pool { + nr_t last_nr; + nr_t nr_min; + nr_t nr_max; +}; + +struct nr_mapping { + struct llist_head entry; + struct expiring_item expiry_entry; + + void *origin; + nr_t orig; + nr_t repl; +}; + +struct nr_map { + struct nr_pool *pool; /* multiple nr_maps can share a nr_pool. */ + struct expiry *add_items_to_expiry; + struct llist_head mappings; +}; + + +void nr_pool_init(struct nr_pool *pool, nr_t nr_min, nr_t nr_max); + +/* Return the next unused number from the nr_pool. */ +nr_t nr_pool_next(struct nr_pool *pool); + +/* Initialize the nr_mapping to zero/empty values. */ +void nr_mapping_init(struct nr_mapping *mapping); + +/* Remove the given mapping from its parent map and expiry queue, and call + * mapping->del_cb, if set. */ +void nr_mapping_del(struct nr_mapping *mapping); + +/* Initialize an (already allocated) nr_map, and set the map's number pool. + * Multiple nr_map instances may use the same nr_pool. Set the nr_map's expiry + * queue to exq, so that all added mappings are automatically expired after the + * time configured in exq. exq may be NULL to disable automatic expiry. */ +void nr_map_init(struct nr_map *map, struct nr_pool *pool, + struct expiry *exq); + +/* Add a new entry to the map. mapping->orig, mapping->origin and + * mapping->del_cb must be set before calling this function. The remaining + * fields of *mapping will be overwritten. mapping->repl is set to the next + * available mapped number from map->pool. 'now' is the current clock count in + * seconds; if no map->expiry is used, just pass 0 for 'now'. */ +void nr_map_add(struct nr_map *map, struct nr_mapping *mapping, + time_t now); + +/* Restart the timeout for the given mapping. mapping must be a member of map. + */ +void nr_map_refresh(struct nr_map *map, struct nr_mapping *mapping, + time_t now); + +/* Return a known mapping from nr_orig and the given origin. If nr_orig is + * unknown, return NULL. */ +struct nr_mapping *nr_map_get(const struct nr_map *map, + void *origin, nr_t nr_orig); + +/* Return a known mapping to nr_repl. If nr_repl is unknown, return NULL. */ +struct nr_mapping *nr_map_get_inv(const struct nr_map *map, nr_t nr_repl); + +/* Remove all mappings from map. */ +void nr_map_clear(struct nr_map *map); + +/* Return 1 if map has no entries, 0 otherwise. */ +int nr_map_empty(const struct nr_map *map); + + +/* config */ + +static const int GTPH_EXPIRE_QUICKLY_SECS = 30; /* TODO is there a spec for this? */ +static const int GTPH_EXPIRE_SLOWLY_MINUTES = 6 * 60; /* TODO is there a spec for this? */ + +struct gtphub_cfg_addr { + const char *addr_str; + uint16_t port; +}; + +struct gtphub_cfg_bind { + struct gtphub_cfg_addr bind; +}; + +struct gtphub_cfg { + struct gtphub_cfg_bind to_gsns[GTPH_SIDE_N][GTPH_PLANE_N]; + struct gtphub_cfg_addr proxy[GTPH_SIDE_N][GTPH_PLANE_N]; + int sgsn_use_sender; /* Use sender, not GSN addr IE with std ports */ +}; + + +/* state */ + +struct gtphub_peer { + struct llist_head entry; + + struct llist_head addresses; /* Alternatives, not load balancing. */ + struct nr_pool seq_pool; + struct nr_map seq_map; +}; + +struct gtphub_peer_addr { + struct llist_head entry; + + struct gtphub_peer *peer; + struct gsn_addr addr; + struct llist_head ports; +}; + +struct gtphub_peer_port { + struct llist_head entry; + + 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) */ + int last_restart_count; /* 0..255 = valid, all else means unknown */ + + struct rate_ctr_group *counters_io; +}; + +struct gtphub_tunnel_endpoint { + struct gtphub_peer_port *peer; + uint32_t tei_orig; /* from/to peer */ + + struct rate_ctr_group *counters_io; +}; + +struct gtphub_tunnel { + struct llist_head entry; + struct expiring_item expiry_entry; + + uint32_t tei_repl; /* unique TEI to replace peers' TEIs */ + struct gtphub_tunnel_endpoint endpoint[GTPH_SIDE_N][GTPH_PLANE_N]; +}; + +struct gtphub_bind { + struct gsn_addr local_addr; + uint16_t local_port; + struct osmo_fd ofd; + + /* list of struct gtphub_peer */ + struct llist_head peers; + + const char *label; /* For logging */ + struct rate_ctr_group *counters_io; +}; + +struct gtphub_resolved_ggsn { + struct llist_head entry; + struct expiring_item expiry_entry; + + /* 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]; + + /* Which address and port we resolved that to. */ + struct gtphub_peer_port *peer; +}; + +struct gtphub { + struct gtphub_bind to_gsns[GTPH_SIDE_N][GTPH_PLANE_N]; + + /* pointers to an entry of to_gsns[s][p].peers */ + struct gtphub_peer_port *proxy[GTPH_SIDE_N][GTPH_PLANE_N]; + + /* The TEI numbers will simply wrap and be reused, which will work out + * in practice. Problems would arise if one given peer maintained the + * same TEI for a time long enough for the TEI nr map to wrap an entire + * uint32_t; if a new TEI were mapped every second, this would take + * more than 100 years (in which a single given TEI must not time out) + * to cause a problem. */ + struct nr_pool tei_pool; + + struct llist_head tunnels; /* struct gtphub_tunnel */ + struct llist_head pending_deletes; /* opaque (gtphub.c) */ + + struct llist_head ggsn_lookups; /* opaque (gtphub_ares.c) */ + struct llist_head resolved_ggsns; /* struct gtphub_resolved_ggsn */ + + struct osmo_timer_list gc_timer; + struct expiry expire_quickly; + struct expiry expire_slowly; + + uint8_t restart_counter; + + int sgsn_use_sender; +}; + +struct gtp_packet_desc; + + +/* api */ + +int gtphub_vty_init(struct gtphub *global_hub, struct gtphub_cfg *global_cfg); +int gtphub_cfg_read(struct gtphub_cfg *cfg, const char *config_file); + +/* Initialize and start gtphub: bind to ports, run expiry timers. */ +int gtphub_start(struct gtphub *hub, struct gtphub_cfg *cfg, + uint8_t restart_counter); + +/* Close all sockets, expire all maps and peers and free all allocations. The + * struct is then unusable, unless gtphub_start() is run on it again. */ +void gtphub_stop(struct gtphub *hub); + +time_t gtphub_now(void); + +/* Remove expired items, empty peers, ... */ +void gtphub_gc(struct gtphub *hub, time_t now); + +/* Return the string of the first address for this peer. */ +const char *gtphub_peer_str(struct gtphub_peer *peer); + +/* Return a human readable description of tun in a static buffer. */ +const char *gtphub_tunnel_str(struct gtphub_tunnel *tun); + +/* Return 1 if all of tun's endpoints are fully established, 0 otherwise. */ +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, + uint8_t *buf, + size_t received, + time_t now, + uint8_t **reply_buf, + struct osmo_fd **to_ofd, + struct osmo_sockaddr *to_addr); + +struct gtphub_peer_port *gtphub_port_have(struct gtphub *hub, + struct gtphub_bind *bind, + const struct gsn_addr *addr, + uint16_t port); + +struct gtphub_peer_port *gtphub_port_find_sa(const struct gtphub_bind *bind, + const struct osmo_sockaddr *addr); + +void gtphub_resolved_ggsn(struct gtphub *hub, const char *apn_oi_str, + struct gsn_addr *resolved_addr, + time_t now); + +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 uint8_t *buf, size_t buf_len); diff --git a/include/osmocom/msc/handover.h b/include/osmocom/msc/handover.h new file mode 100644 index 000000000..3fe71a28b --- /dev/null +++ b/include/osmocom/msc/handover.h @@ -0,0 +1,14 @@ +#ifndef _HANDOVER_H +#define _HANDOVER_H + +struct gsm_subscriber_connection; + +int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts); + +/* clear any operation for this connection */ +void bsc_clear_handover(struct gsm_subscriber_connection *conn, int free_lchan); + +/* Return the old lchan or NULL. This is meant for audio handling */ +struct gsm_lchan *bsc_handover_pending(struct gsm_lchan *new_lchan); + +#endif /* _HANDOVER_H */ diff --git a/include/osmocom/msc/handover_decision.h b/include/osmocom/msc/handover_decision.h new file mode 100644 index 000000000..81078b05d --- /dev/null +++ b/include/osmocom/msc/handover_decision.h @@ -0,0 +1,7 @@ +#ifndef _HANDOVER_DECISION_H +#define _HANDOVER_DECISION_H + +void on_dso_load_ho_dec(void); + +#endif /* _HANDOVER_DECISION_H */ + diff --git a/include/osmocom/msc/ipaccess.h b/include/osmocom/msc/ipaccess.h new file mode 100644 index 000000000..82e89c27d --- /dev/null +++ b/include/osmocom/msc/ipaccess.h @@ -0,0 +1,52 @@ +#ifndef _IPACCESS_H +#define _IPACCESS_H + +#include +#include "gsm_subscriber.h" +#include +#include +#include + +struct ipac_msgt_sccp_state { + uint8_t src_ref[3]; + uint8_t dst_ref[3]; + uint8_t trans_id; + uint8_t invoke_id; + char imsi[GSM23003_IMSI_MAX_DIGITS+1]; + uint8_t data[0]; +} __attribute__((packed)); + +/* + * @add_remove 0 for remove, 1 for add, 3 to asK + * @nr_lacs Number of extra lacs inside this package + * @lac One lac entry + */ +struct ipac_ext_lac_cmd { + uint8_t add_remove; + uint8_t nr_extra_lacs; + uint16_t lac; + uint8_t data[0]; +} __attribute__((packed)); + +void ipaccess_drop_oml(struct gsm_bts *bts); +void ipaccess_drop_rsl(struct gsm_bts_trx *trx); + +struct sdp_header_item { + struct sdp_header_entry header_entry; + struct llist_head entry; + off_t absolute_offset; +}; + +struct sdp_header { + struct sdp_firmware firmware_info; + + /* for more_magic a list of sdp_header_entry_list */ + struct llist_head header_list; + + /* the entry of the sdp_header */ + struct llist_head entry; +}; + +int ipaccess_analyze_file(int fd, const unsigned int st_size, const unsigned base_offset, struct llist_head *list); + +#endif /* _IPACCESS_H */ diff --git a/include/osmocom/msc/iu_dummy.h b/include/osmocom/msc/iu_dummy.h new file mode 100644 index 000000000..d5e142801 --- /dev/null +++ b/include/osmocom/msc/iu_dummy.h @@ -0,0 +1,51 @@ +/* Trivial switch-off of external Iu dependencies, + * allowing to run full unit tests even when built without Iu support. */ + +/* + * (C) 2016,2017 by sysmocom s.f.m.c. GmbH + * + * Author: Neels Hofmeyr + * + * 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 . + * + */ + +#include +#include + +#include + +struct msgb; +struct gsm_auth_tuple; +struct RANAP_Cause; +struct osmo_auth_vector; + +struct ranap_ue_conn_ctx { + struct llist_head list; + uint32_t conn_id; +}; + +int ranap_iu_tx(struct msgb *msg, uint8_t sapi); +int ranap_iu_tx_sec_mode_cmd(struct ranap_ue_conn_ctx *uectx, struct osmo_auth_vector *vec, + int send_ck); +int ranap_iu_page_cs(const char *imsi, const uint32_t *tmsi, uint16_t lac); +int ranap_iu_page_ps(const char *imsi, const uint32_t *ptmsi, uint16_t lac, uint8_t rac); +struct msgb *ranap_new_msg_rab_assign_voice(uint8_t rab_id, uint32_t rtp_ip, + uint16_t rtp_port, + bool use_x213_nsap); +int ranap_iu_rab_act(struct ranap_ue_conn_ctx *ue_ctx, struct msgb *msg); +int ranap_iu_tx_common_id(struct ranap_ue_conn_ctx *uectx, const char *imsi); +int ranap_iu_tx_release(struct ranap_ue_conn_ctx *ctx, const struct RANAP_Cause *cause); diff --git a/include/osmocom/msc/iucs.h b/include/osmocom/msc/iucs.h new file mode 100644 index 000000000..b7d60645d --- /dev/null +++ b/include/osmocom/msc/iucs.h @@ -0,0 +1,7 @@ +#pragma once + +int gsm0408_rcvmsg_iucs(struct gsm_network *network, struct msgb *msg, + uint16_t *lac); + +struct gsm_subscriber_connection *subscr_conn_lookup_iu(struct gsm_network *network, + struct ranap_ue_conn_ctx *ue); diff --git a/include/osmocom/msc/iucs_ranap.h b/include/osmocom/msc/iucs_ranap.h new file mode 100644 index 000000000..c2ff5f90e --- /dev/null +++ b/include/osmocom/msc/iucs_ranap.h @@ -0,0 +1,7 @@ +#pragma once + +struct gsm_network; +struct ranap_ue_conn_ctx; + +int iucs_rx_ranap_event(struct gsm_network *network, + struct ranap_ue_conn_ctx *ue_ctx, int type, void *data); diff --git a/include/osmocom/msc/meas_feed.h b/include/osmocom/msc/meas_feed.h new file mode 100644 index 000000000..02b7d95b4 --- /dev/null +++ b/include/osmocom/msc/meas_feed.h @@ -0,0 +1,41 @@ +#ifndef _OPENBSC_MEAS_FEED_H +#define _OPENBSC_MEAS_FEED_H + +#include + +#include + +struct meas_feed_hdr { + uint8_t msg_type; + uint8_t reserved; + uint16_t version; +}; + +struct meas_feed_meas { + struct meas_feed_hdr hdr; + char imsi[15+1]; + char name[31+1]; + char scenario[31+1]; + struct gsm_meas_rep mr; + /* The logical channel type, enum gsm_chan_t */ + uint8_t lchan_type; + /* The physical channel type, enum gsm_phys_chan_config */ + uint8_t pchan_type; + /* number of ths BTS in network */ + uint8_t bts_nr; + /* number of this TRX in the BTS */ + uint8_t trx_nr; + /* number of this timeslot at the TRX */ + uint8_t ts_nr; + /* The logical subslot number in the TS */ + uint8_t ss_nr; +}; + +enum meas_feed_msgtype { + MEAS_FEED_MEAS = 0, +}; + +#define MEAS_FEED_VERSION 1 + + +#endif diff --git a/include/osmocom/msc/meas_rep.h b/include/osmocom/msc/meas_rep.h new file mode 100644 index 000000000..b0c03f0bb --- /dev/null +++ b/include/osmocom/msc/meas_rep.h @@ -0,0 +1,67 @@ +#ifndef _MEAS_REP_H +#define _MEAS_REP_H + +#include + +#include + +#define MRC_F_PROCESSED 0x0001 + +/* extracted from a L3 measurement report IE */ +struct gsm_meas_rep_cell { + uint8_t rxlev; + uint8_t bsic; + uint8_t neigh_idx; + uint16_t arfcn; + unsigned int flags; +}; + +#define MEAS_REP_F_UL_DTX 0x01 +#define MEAS_REP_F_DL_VALID 0x02 +#define MEAS_REP_F_BA1 0x04 +#define MEAS_REP_F_DL_DTX 0x08 +#define MEAS_REP_F_MS_TO 0x10 +#define MEAS_REP_F_MS_L1 0x20 +#define MEAS_REP_F_FPC 0x40 + +/* parsed uplink and downlink measurement result */ +struct gsm_meas_rep { + /* back-pointer to the logical channel */ + struct gsm_lchan *lchan; + + /* number of the measurement report */ + uint8_t nr; + /* flags, see MEAS_REP_F_* */ + unsigned int flags; + + /* uplink and downlink rxlev, rxqual; full and sub */ + struct gsm_meas_rep_unidir ul; + struct gsm_meas_rep_unidir dl; + + uint8_t bs_power; + /* according to 3GPP TS 48.058 ยง MS Timing Offset [-63; 192] */ + int16_t ms_timing_offset; + struct { + int8_t pwr; /* MS power in dBm */ + uint8_t ta; /* MS timing advance */ + } ms_l1; + + /* neighbor measurement reports for up to 6 cells */ + int num_cell; + struct gsm_meas_rep_cell cell[6]; +}; + +/* obtain an average over the last 'num' fields in the meas reps */ +int get_meas_rep_avg(const struct gsm_lchan *lchan, + enum meas_rep_field field, unsigned int num); + +/* Check if N out of M last values for FIELD are >= bd */ +int meas_rep_n_out_of_m_be(const struct gsm_lchan *lchan, + enum meas_rep_field field, + unsigned int n, unsigned int m, int be); + +unsigned int calc_initial_idx(unsigned int array_size, + unsigned int meas_rep_idx, + unsigned int num_values); + +#endif /* _MEAS_REP_H */ diff --git a/include/osmocom/msc/misdn.h b/include/osmocom/msc/misdn.h new file mode 100644 index 000000000..9851ad32c --- /dev/null +++ b/include/osmocom/msc/misdn.h @@ -0,0 +1,27 @@ +/* (C) 2008 by Harald Welte + * 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 . + * + */ + +#ifndef MISDN_H +#define MISDN_H + +#include + +int mi_setup(int cardnr, struct e1inp_line *line, int release_l2); +int mi_e1_line_update(struct e1inp_line *line); + +#endif diff --git a/include/osmocom/msc/mncc.h b/include/osmocom/msc/mncc.h new file mode 100644 index 000000000..881e0418e --- /dev/null +++ b/include/osmocom/msc/mncc.h @@ -0,0 +1,215 @@ +/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface + * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */ + +/* (C) 2008-2009 by Harald Welte + * (C) 2008, 2009 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 . + * + */ + +#ifndef _MNCC_H +#define _MNCC_H + +#include +#include + +#include + +struct gsm_network; +struct msgb; + + +/* One end of a call */ +struct gsm_call { + struct llist_head entry; + + /* network handle */ + void *net; + + /* the 'local' transaction */ + uint32_t callref; + /* the 'remote' transaction */ + uint32_t remote_ref; +}; + +#define MNCC_SETUP_REQ 0x0101 +#define MNCC_SETUP_IND 0x0102 +#define MNCC_SETUP_RSP 0x0103 +#define MNCC_SETUP_CNF 0x0104 +#define MNCC_SETUP_COMPL_REQ 0x0105 +#define MNCC_SETUP_COMPL_IND 0x0106 +/* MNCC_REJ_* is perfomed via MNCC_REL_* */ +#define MNCC_CALL_CONF_IND 0x0107 +#define MNCC_CALL_PROC_REQ 0x0108 +#define MNCC_PROGRESS_REQ 0x0109 +#define MNCC_ALERT_REQ 0x010a +#define MNCC_ALERT_IND 0x010b +#define MNCC_NOTIFY_REQ 0x010c +#define MNCC_NOTIFY_IND 0x010d +#define MNCC_DISC_REQ 0x010e +#define MNCC_DISC_IND 0x010f +#define MNCC_REL_REQ 0x0110 +#define MNCC_REL_IND 0x0111 +#define MNCC_REL_CNF 0x0112 +#define MNCC_FACILITY_REQ 0x0113 +#define MNCC_FACILITY_IND 0x0114 +#define MNCC_START_DTMF_IND 0x0115 +#define MNCC_START_DTMF_RSP 0x0116 +#define MNCC_START_DTMF_REJ 0x0117 +#define MNCC_STOP_DTMF_IND 0x0118 +#define MNCC_STOP_DTMF_RSP 0x0119 +#define MNCC_MODIFY_REQ 0x011a +#define MNCC_MODIFY_IND 0x011b +#define MNCC_MODIFY_RSP 0x011c +#define MNCC_MODIFY_CNF 0x011d +#define MNCC_MODIFY_REJ 0x011e +#define MNCC_HOLD_IND 0x011f +#define MNCC_HOLD_CNF 0x0120 +#define MNCC_HOLD_REJ 0x0121 +#define MNCC_RETRIEVE_IND 0x0122 +#define MNCC_RETRIEVE_CNF 0x0123 +#define MNCC_RETRIEVE_REJ 0x0124 +#define MNCC_USERINFO_REQ 0x0125 +#define MNCC_USERINFO_IND 0x0126 +#define MNCC_REJ_REQ 0x0127 +#define MNCC_REJ_IND 0x0128 + +#define MNCC_BRIDGE 0x0200 +#define MNCC_FRAME_RECV 0x0201 +#define MNCC_FRAME_DROP 0x0202 +#define MNCC_LCHAN_MODIFY 0x0203 +#define MNCC_RTP_CREATE 0x0204 +#define MNCC_RTP_CONNECT 0x0205 +#define MNCC_RTP_FREE 0x0206 + +#define GSM_TCHF_FRAME 0x0300 +#define GSM_TCHF_FRAME_EFR 0x0301 +#define GSM_TCHH_FRAME 0x0302 +#define GSM_TCH_FRAME_AMR 0x0303 +#define GSM_BAD_FRAME 0x03ff + +#define MNCC_SOCKET_HELLO 0x0400 + +#define GSM_MAX_FACILITY 128 +#define GSM_MAX_SSVERSION 128 +#define GSM_MAX_USERUSER 128 + +#define MNCC_F_BEARER_CAP 0x0001 +#define MNCC_F_CALLED 0x0002 +#define MNCC_F_CALLING 0x0004 +#define MNCC_F_REDIRECTING 0x0008 +#define MNCC_F_CONNECTED 0x0010 +#define MNCC_F_CAUSE 0x0020 +#define MNCC_F_USERUSER 0x0040 +#define MNCC_F_PROGRESS 0x0080 +#define MNCC_F_EMERGENCY 0x0100 +#define MNCC_F_FACILITY 0x0200 +#define MNCC_F_SSVERSION 0x0400 +#define MNCC_F_CCCAP 0x0800 +#define MNCC_F_KEYPAD 0x1000 +#define MNCC_F_SIGNAL 0x2000 + +struct gsm_mncc { + /* context based information */ + uint32_t msg_type; + uint32_t callref; + + /* which fields are present */ + uint32_t fields; + + /* data derived informations (MNCC_F_ based) */ + struct gsm_mncc_bearer_cap bearer_cap; + struct gsm_mncc_number called; + struct gsm_mncc_number calling; + struct gsm_mncc_number redirecting; + struct gsm_mncc_number connected; + struct gsm_mncc_cause cause; + struct gsm_mncc_progress progress; + struct gsm_mncc_useruser useruser; + struct gsm_mncc_facility facility; + struct gsm_mncc_cccap cccap; + struct gsm_mncc_ssversion ssversion; + struct { + int sup; + int inv; + } clir; + int signal; + + /* data derived information, not MNCC_F based */ + int keypad; + int more; + int notify; /* 0..127 */ + int emergency; + char imsi[16]; +}; + +struct gsm_data_frame { + uint32_t msg_type; + uint32_t callref; + unsigned char data[0]; +}; + +#define MNCC_SOCK_VERSION 5 +struct gsm_mncc_hello { + uint32_t msg_type; + uint32_t version; + + /* send the sizes of the structs */ + uint32_t mncc_size; + uint32_t data_frame_size; + + /* send some offsets */ + uint32_t called_offset; + uint32_t signal_offset; + uint32_t emergency_offset; +}; + +struct gsm_mncc_rtp { + uint32_t msg_type; + uint32_t callref; + uint32_t ip; + uint16_t port; + uint32_t payload_type; + uint32_t payload_msg_type; +}; + +struct gsm_mncc_bridge { + uint32_t msg_type; + uint32_t callref[2]; +}; + +const char *get_mncc_name(int value); +void mncc_set_cause(struct gsm_mncc *data, int loc, int val); +void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg); + +/* input from CC code into mncc_builtin */ +int int_mncc_recv(struct gsm_network *net, struct msgb *msg); + +/* input from CC code into mncc_sock */ +int mncc_sock_from_cc(struct gsm_network *net, struct msgb *msg); + +int mncc_sock_init(struct gsm_network *net, const char *sock_path); + +#define mncc_is_data_frame(msg_type) \ + (msg_type == GSM_TCHF_FRAME \ + || msg_type == GSM_TCHF_FRAME_EFR \ + || msg_type == GSM_TCHH_FRAME \ + || msg_type == GSM_TCH_FRAME_AMR \ + || msg_type == GSM_BAD_FRAME) + + +#endif diff --git a/include/osmocom/msc/mncc_int.h b/include/osmocom/msc/mncc_int.h new file mode 100644 index 000000000..213ce1414 --- /dev/null +++ b/include/osmocom/msc/mncc_int.h @@ -0,0 +1,14 @@ +#ifndef _MNCC_INT_H +#define _MNCC_INT_H + +#include + +struct mncc_int { + uint8_t def_codec[2]; +}; + +extern struct mncc_int mncc_int; + +uint8_t mncc_codec_for_mode(int lchan_type); + +#endif diff --git a/include/osmocom/msc/msc_ifaces.h b/include/osmocom/msc/msc_ifaces.h new file mode 100644 index 000000000..d46dfe9b3 --- /dev/null +++ b/include/osmocom/msc/msc_ifaces.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include + +/* These are the interfaces of the MSC layer towards (from?) the BSC and RNC, + * i.e. in the direction towards the mobile device (MS aka UE). + * + * 2G will use the A-interface, + * 3G aka UMTS will use the Iu-interface (for the MSC, it's IuCS). + * + * To allow linking parts of the MSC code without having to include entire + * infrastructures of external libraries, the core transmitting and receiving + * functions are left unimplemented. For example, a unit test does not need to + * link against external ASN1 libraries if it is never going to encode actual + * outgoing messages. It is up to each building scope to implement real world + * functions or to plug mere dummy implementations. + * + * For example, msc_tx_dtap(conn, msg), depending on conn->via_iface, will call + * either iu_tx() or a_tx() [note: at time of writing, the A-interface is not + * yet implemented]. When you try to link against libmsc, you will find that + * the compiler complains about an undefined reference to iu_tx(). If you, + * however, link against libiu as well as the osmo-iuh libs (etc.), iu_tx() is + * available. A unit test may instead simply implement a dummy iu_tx() function + * and not link against osmo-iuh, see tests/libiudummy/. + */ + +/* Each main linkage must implement this function (see comment above). */ +extern int iu_tx(struct msgb *msg, uint8_t sapi); + +int msc_tx_dtap(struct gsm_subscriber_connection *conn, + struct msgb *msg); + +int msc_gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn); +int msc_gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn, + enum gsm48_reject_value value); + +int msc_tx_common_id(struct gsm_subscriber_connection *conn); +int msc_call_assignment(struct gsm_trans *trans); +int msc_call_bridge(struct gsm_trans *trans1, struct gsm_trans *trans2); +void msc_call_release(struct gsm_trans *trans); +int msc_call_connect(struct gsm_trans *trans, uint16_t port, uint32_t ip); diff --git a/include/osmocom/msc/network_listen.h b/include/osmocom/msc/network_listen.h new file mode 100644 index 000000000..05fbb2fec --- /dev/null +++ b/include/osmocom/msc/network_listen.h @@ -0,0 +1,16 @@ +#ifndef _OPENBSC_NWL_H +#define _OPENBSC_NWL_H + +#include +#include + +void ipac_nwl_init(void); + +/* Start a NWL test. It will raise the S_IPAC_TEST_COMPLETE signal. */ +int ipac_nwl_test_start(struct gsm_bts_trx *trx, uint8_t testnr, + const uint8_t *phys_conf, unsigned int phys_conf_len); + +int ipac_rxlevstat2whitelist(uint16_t *buf, const struct rxlev_stats *st, uint8_t min_rxlev, + uint16_t max_num_arfcns); + +#endif /* _OPENBSC_NWL_H */ diff --git a/include/osmocom/msc/oap_client.h b/include/osmocom/msc/oap_client.h new file mode 100644 index 000000000..80c86d5d6 --- /dev/null +++ b/include/osmocom/msc/oap_client.h @@ -0,0 +1,82 @@ +/* Osmocom Authentication Protocol API */ + +/* (C) 2015 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * 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 . + * + */ + +#pragma once + +#include + +struct msgb; +struct osmo_oap_message; + +/* This is the config part for vty. It is essentially copied in + * oap_client_state, where values are copied over once the config is + * considered valid. */ +struct oap_client_config { + uint16_t client_id; + int secret_k_present; + uint8_t secret_k[16]; + int secret_opc_present; + uint8_t secret_opc[16]; +}; + +/* The runtime state of the OAP client. client_id and the secrets are in fact + * duplicated from oap_client_config, so that a separate validation of the + * config data is possible, and so that only a struct oap_client_state* is + * passed around. */ +struct oap_client_state { + enum { + OAP_UNINITIALIZED = 0, /* just allocated. */ + OAP_DISABLED, /* disabled by config. */ + OAP_INITIALIZED, /* enabled, config is valid. */ + OAP_REQUESTED_CHALLENGE, + OAP_SENT_CHALLENGE_RESULT, + OAP_REGISTERED + } state; + uint16_t client_id; + uint8_t secret_k[16]; + uint8_t secret_opc[16]; + int registration_failures; +}; + +/* From config, initialize state. Return 0 on success. */ +int oap_client_init(struct oap_client_config *config, + struct oap_client_state *state); + +/* Construct an OAP registration message and return in *msg_tx. Use + * state->client_id and update state->state. + * Return 0 on success, or a negative value on error. + * If an error is returned, *msg_tx is guaranteed to be NULL. */ +int oap_client_register(struct oap_client_state *state, struct msgb **msg_tx); + +/* Decode and act on a received OAP message msg_rx. Update state->state. If a + * non-NULL pointer is returned in *msg_tx, that msgb should be sent to the OAP + * server (and freed) by the caller. The received msg_rx is not freed. + * Return 0 on success, or a negative value on error. + * If an error is returned, *msg_tx is guaranteed to be NULL. */ +int oap_client_handle(struct oap_client_state *state, + const struct msgb *msg_rx, struct msgb **msg_tx); + +/* Allocate a msgb and in it, return the encoded oap_client_msg. Return + * NULL on error. (Like oap_client_encode(), but also allocates a msgb.) + * About the name: the idea is do_something(oap_client_encoded(my_struct)) + */ +struct msgb *oap_client_encoded(const struct osmo_oap_message *oap_client_msg); diff --git a/include/osmocom/msc/openbscdefines.h b/include/osmocom/msc/openbscdefines.h new file mode 100644 index 000000000..c6ac153b8 --- /dev/null +++ b/include/osmocom/msc/openbscdefines.h @@ -0,0 +1,34 @@ +/* + * (C) 2009 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 . + * + */ + +#ifndef OPENBSCDEFINES_H +#define OPENBSCDEFINES_H + +#ifdef BUILDING_ON_WINDOWS + #ifdef BUILDING_OPENBSC + #define BSC_API __declspec(dllexport) + #else + #define BSC_API __declspec(dllimport) + #endif +#else + #define BSC_API __attribute__((visibility("default"))) +#endif + +#endif diff --git a/include/osmocom/msc/osmo_bsc.h b/include/osmocom/msc/osmo_bsc.h new file mode 100644 index 000000000..5ebea5079 --- /dev/null +++ b/include/osmocom/msc/osmo_bsc.h @@ -0,0 +1,75 @@ +/* OpenBSC BSC code */ + +#ifndef OSMO_BSC_H +#define OSMO_BSC_H + +#include "bsc_api.h" +#include "bsc_msg_filter.h" + +#define BSS_SEND_USSD 1 + +enum bsc_con { + BSC_CON_SUCCESS, + BSC_CON_REJECT_NO_LINK, + BSC_CON_REJECT_RF_GRACE, + BSC_CON_NO_MEM, +}; + +struct sccp_connection; +struct bsc_msc_data; +struct bsc_msc_connection; + +struct osmo_bsc_sccp_con { + struct llist_head entry; + + int ciphering_handled; + + /* for audio handling */ + uint16_t cic; + uint32_t rtp_ip; + int rtp_port; + + /* for advanced ping/pong */ + int send_ping; + + /* SCCP connection realted */ + struct sccp_connection *sccp; + struct bsc_msc_data *msc; + struct osmo_timer_list sccp_it_timeout; + struct osmo_timer_list sccp_cc_timeout; + + struct llist_head sccp_queue; + unsigned int sccp_queue_size; + + struct gsm_subscriber_connection *conn; + uint8_t new_subscriber; + + struct bsc_filter_state filter_state; + + /* Sigtran connection ID */ + int conn_id; +}; + +struct bsc_api *osmo_bsc_api(); + +int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg); +int bsc_open_connection(struct osmo_bsc_sccp_con *sccp, struct msgb *msg); +enum bsc_con bsc_create_new_connection(struct gsm_subscriber_connection *conn, + struct bsc_msc_data *msc, int send_ping); +int bsc_delete_connection(struct osmo_bsc_sccp_con *sccp); + +struct bsc_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn, struct msgb *); +int bsc_scan_bts_msg(struct gsm_subscriber_connection *conn, struct msgb *msg); +int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg); +int bsc_send_welcome_ussd(struct gsm_subscriber_connection *conn); + +int bsc_handle_udt(struct bsc_msc_data *msc, struct msgb *msg, unsigned int length); +int bsc_handle_dt(struct osmo_bsc_sccp_con *conn, struct msgb *msg, unsigned int len); + +int bsc_ctrl_cmds_install(); + +void bsc_gen_location_state_trap(struct gsm_bts *bts); + +struct llist_head *bsc_access_lists(void); + +#endif diff --git a/include/osmocom/msc/osmo_bsc_grace.h b/include/osmocom/msc/osmo_bsc_grace.h new file mode 100644 index 000000000..6232ffda1 --- /dev/null +++ b/include/osmocom/msc/osmo_bsc_grace.h @@ -0,0 +1,35 @@ +/* + * (C) 2010-2013 by Holger Hans Peter Freyther + * (C) 2010-2013 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 . + * + */ + +#ifndef OSMO_BSC_GRACE_H +#define OSMO_BSC_GRACE_H + +#include +#include + +struct bsc_msc_data; + +int bsc_grace_allow_new_connection(struct gsm_network *net, struct gsm_bts *bts); +int bsc_grace_paging_request(enum signal_rf rf_policy, + struct bsc_subscr *subscr, + int chan_needed, + struct bsc_msc_data *msc); + +#endif diff --git a/include/osmocom/msc/osmo_bsc_reset.h b/include/osmocom/msc/osmo_bsc_reset.h new file mode 100644 index 000000000..578f763e6 --- /dev/null +++ b/include/osmocom/msc/osmo_bsc_reset.h @@ -0,0 +1,34 @@ +/* (C) 2017 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Philipp Maier + * + * 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 . + * + */ + +/* Create and start state machine which handles the reset/reset-ack procedure */ +void start_reset_fsm(struct bsc_msc_data *msc); + +/* Confirm that we sucessfully received a reset acknowlege message */ +void reset_ack_confirm(struct bsc_msc_data *msc); + +/* Report a failed connection */ +void report_conn_fail(struct bsc_msc_data *msc); + +/* Report a successful connection */ +void report_conn_success(struct bsc_msc_data *msc); + +/* Check if we have a connection to a specified msc */ +bool sccp_conn_ready(struct bsc_msc_data *msc); diff --git a/include/osmocom/msc/osmo_bsc_rf.h b/include/osmocom/msc/osmo_bsc_rf.h new file mode 100644 index 000000000..a81ebd710 --- /dev/null +++ b/include/osmocom/msc/osmo_bsc_rf.h @@ -0,0 +1,66 @@ +#ifndef OSMO_BSC_RF +#define OSMO_BSC_RF + +#include +#include +#include + +enum osmo_bsc_rf_opstate { + OSMO_BSC_RF_OPSTATE_INOPERATIONAL, + OSMO_BSC_RF_OPSTATE_OPERATIONAL, +}; + +enum osmo_bsc_rf_adminstate { + OSMO_BSC_RF_ADMINSTATE_UNLOCKED, + OSMO_BSC_RF_ADMINSTATE_LOCKED, +}; + +enum osmo_bsc_rf_policy { + OSMO_BSC_RF_POLICY_OFF, + OSMO_BSC_RF_POLICY_ON, + OSMO_BSC_RF_POLICY_GRACE, + OSMO_BSC_RF_POLICY_UNKNOWN, +}; + + +struct gsm_network; + +struct osmo_bsc_rf { + /* the value of signal.h */ + int policy; + struct osmo_fd listen; + struct gsm_network *gsm_network; + + const char *last_state_command; + + char *last_rf_lock_ctrl_command; + + /* delay the command */ + char last_request; + struct osmo_timer_list delay_cmd; + + /* verify that RF is up as it should be */ + struct osmo_timer_list rf_check; + + /* some handling for the automatic grace switch */ + struct osmo_timer_list grace_timeout; + + /* auto RF switch-off due lack of MSC connection */ + struct osmo_timer_list auto_off_timer; +}; + +struct osmo_bsc_rf_conn { + struct osmo_wqueue queue; + struct osmo_bsc_rf *rf; +}; + +const char *osmo_bsc_rf_get_opstate_name(enum osmo_bsc_rf_opstate opstate); +const char *osmo_bsc_rf_get_adminstate_name(enum osmo_bsc_rf_adminstate adminstate); +const char *osmo_bsc_rf_get_policy_name(enum osmo_bsc_rf_policy policy); +enum osmo_bsc_rf_opstate osmo_bsc_rf_get_opstate_by_bts(struct gsm_bts *bts); +enum osmo_bsc_rf_adminstate osmo_bsc_rf_get_adminstate_by_bts(struct gsm_bts *bts); +enum osmo_bsc_rf_policy osmo_bsc_rf_get_policy_by_bts(struct gsm_bts *bts); +struct osmo_bsc_rf *osmo_bsc_rf_create(const char *path, struct gsm_network *net); +void osmo_bsc_rf_schedule_lock(struct osmo_bsc_rf *rf, char cmd); + +#endif diff --git a/include/osmocom/msc/osmo_bsc_sigtran.h b/include/osmocom/msc/osmo_bsc_sigtran.h new file mode 100644 index 000000000..7015edbc4 --- /dev/null +++ b/include/osmocom/msc/osmo_bsc_sigtran.h @@ -0,0 +1,48 @@ +/* (C) 2017 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Philipp Maier + * + * 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 . + * + */ + +#pragma once + +#include +#include + +/* Allocate resources to make a new connection oriented sigtran connection + * (not the connection ittself!) */ +enum bsc_con osmo_bsc_sigtran_new_conn(struct gsm_subscriber_connection *conn, struct bsc_msc_data *msc); + +/* Open a new connection oriented sigtran connection */ +int osmo_bsc_sigtran_open_conn(const struct osmo_bsc_sccp_con *conn, struct msgb *msg); + +/* Send data to MSC */ +int osmo_bsc_sigtran_send(const struct osmo_bsc_sccp_con *conn, struct msgb *msg); + +/* Delete a connection from the list with open connections + * (called by osmo_bsc_api.c on failing open connections and + * locally, when a connection is closed by the MSC */ +int osmo_bsc_sigtran_del_conn(struct osmo_bsc_sccp_con *sccp); + +/* Initalize osmo sigtran backhaul */ +int osmo_bsc_sigtran_init(struct llist_head *mscs); + +/* Close all open sigtran connections and channels */ +void osmo_bsc_sigtran_reset(const struct bsc_msc_data *msc); + +/* Send reset-ack to MSC */ +void osmo_bsc_sigtran_tx_reset_ack(const struct bsc_msc_data *msc); diff --git a/include/osmocom/msc/osmo_msc.h b/include/osmocom/msc/osmo_msc.h new file mode 100644 index 000000000..5f4713ee8 --- /dev/null +++ b/include/osmocom/msc/osmo_msc.h @@ -0,0 +1,99 @@ +/* Routines for the MSC handling */ + +#ifndef OSMO_MSC_H +#define OSMO_MSC_H + +#include +#include + +#include + +#include "bsc_api.h" + +#define MSC_HLR_REMOTE_IP_DEFAULT "127.0.0.1" +#define MSC_HLR_REMOTE_PORT_DEFAULT OSMO_GSUP_PORT + +enum subscr_conn_fsm_event { + /* Mark 0 as invalid to catch uninitialized vars */ + SUBSCR_CONN_E_INVALID = 0, + /* Timeout on connection establishment starts */ + SUBSCR_CONN_E_START, + /* LU or Process Access FSM has determined that this conn is good */ + SUBSCR_CONN_E_ACCEPTED, + /* received first reply from MS in "real" CC, SMS, USSD communication */ + SUBSCR_CONN_E_COMMUNICATING, + /* Some async action has completed, check again whether all is done */ + SUBSCR_CONN_E_BUMP, + /* MS/BTS/BSC originated close request */ + SUBSCR_CONN_E_MO_CLOSE, + /* MSC originated close request, e.g. failed authentication */ + SUBSCR_CONN_E_CN_CLOSE, +}; + +enum subscr_conn_fsm_state { + SUBSCR_CONN_S_INIT, + SUBSCR_CONN_S_NEW, + SUBSCR_CONN_S_ACCEPTED, + SUBSCR_CONN_S_COMMUNICATING, + SUBSCR_CONN_S_RELEASED, +}; + +enum subscr_conn_from { + SUBSCR_CONN_FROM_INVALID, + SUBSCR_CONN_FROM_LU, + SUBSCR_CONN_FROM_CM_SERVICE_REQ, + SUBSCR_CONN_FROM_PAGING_RESP, +}; + +extern const struct value_string subscr_conn_from_names[]; +static inline const char *subscr_conn_from_name(enum subscr_conn_from val) +{ + return get_value_string(subscr_conn_from_names, val); +} + +enum msc_compl_l3_rc { + MSC_CONN_ACCEPT = 0, + MSC_CONN_REJECT = 1, +}; + +struct bsc_api *msc_bsc_api(); + +int msc_create_conn_fsm(struct gsm_subscriber_connection *conn, const char *id); + +int msc_vlr_alloc(struct gsm_network *net); +int msc_vlr_start(struct gsm_network *net); + +void msc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci); +int msc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause); +int msc_compl_l3(struct gsm_subscriber_connection *conn, + struct msgb *msg, uint16_t chosen_channel); +void msc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, + struct msgb *msg); +void msc_cipher_mode_compl(struct gsm_subscriber_connection *conn, + struct msgb *msg, uint8_t alg_id); +void msc_rx_sec_mode_compl(struct gsm_subscriber_connection *conn); +void msc_classmark_chg(struct gsm_subscriber_connection *conn, + const uint8_t *cm2, uint8_t cm2_len, + const uint8_t *cm3, uint8_t cm3_len); +void msc_assign_fail(struct gsm_subscriber_connection *conn, + uint8_t cause, uint8_t *rr_cause); + +void msc_subscr_conn_init(void); +bool msc_subscr_conn_is_accepted(struct gsm_subscriber_connection *conn); +void msc_subscr_conn_communicating(struct gsm_subscriber_connection *conn); +void msc_subscr_conn_close(struct gsm_subscriber_connection *conn, + uint32_t cause); + +#define msc_subscr_conn_get(conn) \ + _msc_subscr_conn_get(conn, __BASE_FILE__, __LINE__) +#define msc_subscr_conn_put(conn) \ + _msc_subscr_conn_put(conn, __BASE_FILE__, __LINE__) +struct gsm_subscriber_connection * +_msc_subscr_conn_get(struct gsm_subscriber_connection *conn, + const char *file, int line); +void _msc_subscr_conn_put(struct gsm_subscriber_connection *conn, + const char *file, int line); + +void msc_stop_paging(struct vlr_subscr *vsub); + +#endif diff --git a/include/osmocom/msc/osmux.h b/include/osmocom/msc/osmux.h new file mode 100644 index 000000000..f3ea72a85 --- /dev/null +++ b/include/osmocom/msc/osmux.h @@ -0,0 +1,41 @@ +#ifndef _OPENBSC_OSMUX_H_ +#define _OPENBSC_OSMUX_H_ + +#include + +#define OSMUX_PORT 1984 + +enum { + OSMUX_ROLE_BSC = 0, + OSMUX_ROLE_BSC_NAT, +}; + +int osmux_init(int role, struct mgcp_config *cfg); +int osmux_enable_endpoint(struct mgcp_endpoint *endp, struct in_addr *addr, uint16_t port); +void osmux_disable_endpoint(struct mgcp_endpoint *endp); +void osmux_allocate_cid(struct mgcp_endpoint *endp); +void osmux_release_cid(struct mgcp_endpoint *endp); + +int osmux_xfrm_to_rtp(struct mgcp_endpoint *endp, int type, char *buf, int rc); +int osmux_xfrm_to_osmux(int type, char *buf, int rc, struct mgcp_endpoint *endp); + +int osmux_send_dummy(struct mgcp_endpoint *endp); + +int osmux_get_cid(void); +void osmux_put_cid(uint8_t osmux_cid); +int osmux_used_cid(void); + +enum osmux_state { + OSMUX_STATE_DISABLED = 0, + OSMUX_STATE_NEGOTIATING, + OSMUX_STATE_ACTIVATING, + OSMUX_STATE_ENABLED, +}; + +enum osmux_usage { + OSMUX_USAGE_OFF = 0, + OSMUX_USAGE_ON = 1, + OSMUX_USAGE_ONLY = 2, +}; + +#endif diff --git a/include/osmocom/msc/paging.h b/include/osmocom/msc/paging.h new file mode 100644 index 000000000..b856dcd2e --- /dev/null +++ b/include/osmocom/msc/paging.h @@ -0,0 +1,76 @@ +/* Paging helper and manager.... */ +/* (C) 2009 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 . + * + */ + +#ifndef PAGING_H +#define PAGING_H + +#include +#include + +#include +#include + +#include + +/** + * A pending paging request + */ +struct gsm_paging_request { + /* list_head for list of all paging requests */ + struct llist_head entry; + /* the subscriber which we're paging. Later gsm_paging_request + * should probably become a part of the bsc_subsrc struct? */ + struct bsc_subscr *bsub; + /* back-pointer to the BTS on which we are paging */ + struct gsm_bts *bts; + /* what kind of channel type do we ask the MS to establish */ + int chan_type; + + /* Timer 3113: how long do we try to page? */ + struct osmo_timer_list T3113; + + /* How often did we ask the BTS to page? */ + int attempts; + + /* callback to be called in case paging completes */ + gsm_cbfn *cbfn; + void *cbfn_param; +}; + +/* schedule paging request */ +int paging_request(struct gsm_network *network, struct bsc_subscr *bsub, + int type, gsm_cbfn *cbfn, void *data); +int paging_request_bts(struct gsm_bts *bts, struct bsc_subscr *bsub, + int type, gsm_cbfn *cbfn, void *data); + +/* stop paging requests */ +void paging_request_stop(struct llist_head *bts_list, + struct gsm_bts *_bts, struct bsc_subscr *bsub, + struct gsm_subscriber_connection *conn, + struct msgb *msg); + +/* update paging load */ +void paging_update_buffer_space(struct gsm_bts *bts, uint16_t); + +/* pending paging requests */ +unsigned int paging_pending_requests_nr(struct gsm_bts *bts); + +void *paging_get_data(struct gsm_bts *bts, struct bsc_subscr *bsub); + +#endif diff --git a/include/osmocom/msc/rest_octets.h b/include/osmocom/msc/rest_octets.h new file mode 100644 index 000000000..49857b7c5 --- /dev/null +++ b/include/osmocom/msc/rest_octets.h @@ -0,0 +1,139 @@ +#ifndef _REST_OCTETS_H +#define _REST_OCTETS_H + +#include +#include +#include + +/* generate SI1 rest octets */ +int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net); +int rest_octets_si2quater(uint8_t *data, struct gsm_bts *bts); +int rest_octets_si6(uint8_t *data, bool is1800_net); + +struct gsm48_si_selection_params { + uint16_t penalty_time:5, + temp_offs:3, + cell_resel_off:6, + cbq:1, + present:1; +}; + +struct gsm48_si_power_offset { + uint8_t power_offset:2, + present:1; +}; + +struct gsm48_si3_gprs_ind { + uint8_t si13_position:1, + ra_colour:3, + present:1; +}; + +struct gsm48_lsa_params { + uint32_t prio_thr:3, + lsa_offset:3, + mcc:12, + mnc:12; + unsigned int present; +}; + +struct gsm48_si_ro_info { + struct gsm48_si_selection_params selection_params; + struct gsm48_si_power_offset power_offset; + uint8_t si2ter_indicator; + uint8_t early_cm_ctrl; + struct { + uint8_t where:3, + present:1; + } scheduling; + struct gsm48_si3_gprs_ind gprs_ind; + /* SI 3 specific */ + uint8_t si2quater_indicator; + /* SI 4 specific */ + struct gsm48_lsa_params lsa_params; + uint16_t cell_id; + uint8_t break_ind; /* do we have SI7 + SI8 ? */ +}; + + +/* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */ +int rest_octets_si3(uint8_t *data, const struct gsm48_si_ro_info *si3); + +/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */ +int rest_octets_si4(uint8_t *data, const struct gsm48_si_ro_info *si4, int len); + +enum pbcch_carrier_type { + PBCCH_BCCH, + PBCCH_ARFCN, + PBCCH_MAIO +}; + +/* TS 03.60 Chapter 6.3.3.1: Network Mode of Operation */ +enum gprs_nmo { + GPRS_NMO_I = 0, /* CS pagin on GPRS paging or traffic channel */ + GPRS_NMO_II = 1, /* all paging on CCCH */ + GPRS_NMO_III = 2, /* no paging coordination */ +}; + +/* TS 04.60 12.24 */ +struct gprs_cell_options { + enum gprs_nmo nmo; + /* T3168: wait for packet uplink assignment message */ + uint32_t t3168; /* in milliseconds */ + /* T3192: wait for release of the TBF after reception of the final block */ + uint32_t t3192; /* in milliseconds */ + uint32_t drx_timer_max;/* in seconds */ + uint32_t bs_cv_max; + uint8_t supports_egprs_11bit_rach; + bool ctrl_ack_type_use_block; /* use PACKET CONTROL ACKNOWLEDGMENT */ + + uint8_t ext_info_present; + struct { + uint8_t egprs_supported; + uint8_t use_egprs_p_ch_req; + uint8_t bep_period; + uint8_t pfc_supported; + uint8_t dtm_supported; + uint8_t bss_paging_coordination; + } ext_info; +}; + +/* TS 04.60 Table 12.9.2 */ +struct gprs_power_ctrl_pars { + uint8_t alpha; + uint8_t t_avg_w; + uint8_t t_avg_t; + uint8_t pc_meas_chan; + uint8_t n_avg_i; +}; + +struct gsm48_si13_info { + struct gprs_cell_options cell_opts; + struct gprs_power_ctrl_pars pwr_ctrl_pars; + uint8_t bcch_change_mark; + uint8_t si_change_field; + uint8_t pbcch_present; + + union { + struct { + uint8_t rac; + uint8_t spgc_ccch_sup; + uint8_t net_ctrl_ord; + uint8_t prio_acc_thr; + } no_pbcch; + struct { + uint8_t psi1_rep_per; + uint8_t pb; + uint8_t tsc; + uint8_t tn; + enum pbcch_carrier_type carrier_type; + uint16_t arfcn; + uint8_t maio; + } pbcch; + }; +}; + +/* Generate SI13 Rest Octests (Chapter 10.5.2.37b) */ +int rest_octets_si13(uint8_t *data, const struct gsm48_si13_info *si13); + +#endif /* _REST_OCTETS_H */ diff --git a/include/osmocom/msc/rrlp.h b/include/osmocom/msc/rrlp.h new file mode 100644 index 000000000..c89402a2d --- /dev/null +++ b/include/osmocom/msc/rrlp.h @@ -0,0 +1,7 @@ +#ifndef _RRLP_H +#define _RRLP_H + +void on_dso_load_rrlp(void); + +#endif /* _RRLP_H */ + diff --git a/include/osmocom/msc/rs232.h b/include/osmocom/msc/rs232.h new file mode 100644 index 000000000..61187ca62 --- /dev/null +++ b/include/osmocom/msc/rs232.h @@ -0,0 +1,9 @@ +#ifndef _RS232_H +#define _RS232_H + +int rs232_setup(const char *serial_port, unsigned int delay_ms, + struct gsm_bts *bts); + +int handle_serial_msg(struct msgb *msg); + +#endif /* _RS232_H */ diff --git a/include/osmocom/msc/rtp_proxy.h b/include/osmocom/msc/rtp_proxy.h new file mode 100644 index 000000000..3cd8cac24 --- /dev/null +++ b/include/osmocom/msc/rtp_proxy.h @@ -0,0 +1,95 @@ +#ifndef _RTP_PROXY_H +#define _RTP_PROXY_H + +/* RTP proxy handling for ip.access nanoBTS */ + +/* (C) 2009 by Harald Welte + * 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 . + * + */ + + +#include + +#include +#include + +#include + +#define RTP_PT_GSM_FULL 3 +#define RTP_PT_GSM_HALF 96 +#define RTP_PT_GSM_EFR 97 +#define RTP_PT_AMR 98 +#define RTP_LEN_GSM_FULL 33 +#define RTP_LEN_GSM_HALF 15 +#define RTP_LEN_GSM_EFR 31 +#define RTP_GSM_DURATION 160 + +enum rtp_rx_action { + RTP_NONE, + RTP_PROXY, + RTP_RECV_UPSTREAM, +}; + +enum rtp_tx_action { + RTP_SEND_NONE, + RTP_SEND_DOWNSTREAM, +}; + +struct rtp_sub_socket { + struct sockaddr_in sin_local; + struct sockaddr_in sin_remote; + + struct osmo_fd bfd; + /* linked list of to-be-transmitted msgb's */ + struct llist_head tx_queue; +}; + +struct rtp_socket { + struct llist_head list; + + struct rtp_sub_socket rtp; + struct rtp_sub_socket rtcp; + + /* what should we do on receive? */ + enum rtp_rx_action rx_action; + union { + struct { + struct rtp_socket *other_sock; + } proxy; + struct { + struct gsm_network *net; + uint32_t callref; + } receive; + }; + enum rtp_tx_action tx_action; + struct { + uint16_t sequence; + uint32_t timestamp; + uint32_t ssrc; + struct timeval last_tv; + } transmit; +}; + +struct rtp_socket *rtp_socket_create(void); +int rtp_socket_bind(struct rtp_socket *rs, uint32_t ip); +int rtp_socket_connect(struct rtp_socket *rs, uint32_t ip, uint16_t port); +int rtp_socket_proxy(struct rtp_socket *this, struct rtp_socket *other); +int rtp_socket_upstream(struct rtp_socket *this, struct gsm_network *net, uint32_t callref); +int rtp_socket_free(struct rtp_socket *rs); +int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame); + +#endif /* _RTP_PROXY_H */ diff --git a/include/osmocom/msc/signal.h b/include/osmocom/msc/signal.h new file mode 100644 index 000000000..14c76f828 --- /dev/null +++ b/include/osmocom/msc/signal.h @@ -0,0 +1,260 @@ +/* Generic signalling/notification infrastructure */ +/* (C) 2009-2010, 2015 by Holger Hans Peter Freyther + * (C) 2009 by Harald Welte + * (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 . + * + */ + +#ifndef OPENBSC_SIGNAL_H +#define OPENBSC_SIGNAL_H + +#include +#include + +#include + +#include + +/* + * Signalling subsystems + */ +enum signal_subsystems { + SS_PAGING, + SS_SMS, + SS_ABISIP, + SS_NM, + SS_LCHAN, + SS_SUBSCR, + SS_SCALL, + SS_CHALLOC, + SS_IPAC_NWL, + SS_RF, + SS_MSC, + SS_HO, + SS_CCCH, + SS_SGSN, +}; + +/* SS_PAGING signals */ +enum signal_paging { + S_PAGING_SUCCEEDED, + S_PAGING_EXPIRED, +}; + +/* SS_SMS signals */ +enum signal_sms { + S_SMS_SUBMITTED, /* A SMS has been successfully submitted to us */ + S_SMS_DELIVERED, /* A SMS has been successfully delivered to a MS */ + S_SMS_SMMA, /* A MS tells us it has more space available */ + S_SMS_MEM_EXCEEDED, /* A MS tells us it has no more space available */ + S_SMS_UNKNOWN_ERROR, /* A MS tells us it has an error */ +}; + +/* SS_ABISIP signals */ +enum signal_abisip { + S_ABISIP_CRCX_ACK, + S_ABISIP_MDCX_ACK, + S_ABISIP_DLCX_IND, +}; + +/* SS_NM signals */ +enum signal_nm { + S_NM_SW_ACTIV_REP, /* GSM 12.21 software activated report */ + S_NM_FAIL_REP, /* GSM 12.21 failure event report */ + S_NM_NACK, /* GSM 12.21 various NM_MT_*_NACK happened */ + S_NM_IPACC_NACK, /* GSM 12.21 nanoBTS extensions NM_MT_IPACC_*_*_NACK happened */ + S_NM_IPACC_ACK, /* GSM 12.21 nanoBTS extensions NM_MT_IPACC_*_*_ACK happened */ + S_NM_IPACC_RESTART_ACK, /* nanoBTS has send a restart ack */ + S_NM_IPACC_RESTART_NACK,/* nanoBTS has send a restart ack */ + S_NM_TEST_REP, /* GSM 12.21 Test Report */ + S_NM_STATECHG_OPER, /* Operational State changed*/ + S_NM_STATECHG_ADM, /* Administrative State changed */ + S_NM_OM2K_CONF_RES, /* OM2K Configuration Result */ +}; + +/* SS_LCHAN signals */ +enum signal_lchan { + /* + * The lchan got freed with an use_count != 0 and error + * recovery needs to be carried out from within the + * signal handler. + */ + S_LCHAN_UNEXPECTED_RELEASE, + S_LCHAN_ACTIVATE_ACK, /* 08.58 Channel Activate ACK */ + S_LCHAN_ACTIVATE_NACK, /* 08.58 Channel Activate NACK */ + S_LCHAN_HANDOVER_COMPL, /* 04.08 Handover Completed */ + S_LCHAN_HANDOVER_FAIL, /* 04.08 Handover Failed */ + S_LCHAN_HANDOVER_DETECT, /* 08.58 Handover Detect */ + S_LCHAN_MEAS_REP, /* 08.58 Measurement Report */ +}; + +/* SS_CHALLOC signals */ +enum signal_challoc { + S_CHALLOC_ALLOC_FAIL, /* allocation of lchan has failed */ + S_CHALLOC_FREED, /* lchan has been successfully freed */ +}; + +/* SS_SUBSCR signals */ +enum signal_subscr { + S_SUBSCR_ATTACHED, + S_SUBSCR_DETACHED, + S_SUBSCR_IDENTITY, /* we've received some identity information */ +}; + +/* SS_SCALL signals */ +enum signal_scall { + S_SCALL_SUCCESS, + S_SCALL_EXPIRED, + S_SCALL_DETACHED, +}; + +/* SS_IPAC_NWL signals */ +enum signal_ipaccess { + S_IPAC_NWL_COMPLETE, +}; + +enum signal_global { + S_GLOBAL_BTS_CLOSE_OM, +}; + +/* SS_RF signals */ +enum signal_rf { + S_RF_OFF, + S_RF_ON, + S_RF_GRACE, +}; + +struct paging_signal_data { + struct vlr_subscr *vsub; + struct gsm_bts *bts; + + int paging_result; + + /* NULL in case the paging didn't work */ + struct gsm_subscriber_connection *conn; +}; + +struct scall_signal_data { + struct gsm_subscriber_connection *conn; + void *data; +}; + +struct ipacc_ack_signal_data { + struct gsm_bts_trx *trx; + uint8_t msg_type; +}; + +struct abis_om2k_mo; + +struct nm_statechg_signal_data { + struct gsm_bts *bts; + uint8_t obj_class; + void *obj; + struct gsm_nm_state *old_state; + struct gsm_nm_state *new_state; + + /* This pointer is vaold for TS 12.21 MO */ + struct abis_om_obj_inst *obj_inst; + /* This pointer is vaold for RBS2000 MO */ + struct abis_om2k_mo *om2k_mo; +}; + +struct nm_om2k_signal_data { + struct gsm_bts *bts; + void *obj; + struct abis_om2k_mo *om2k_mo; + + uint8_t accordance_ind; +}; + +struct nm_nack_signal_data { + struct msgb *msg; + struct gsm_bts *bts; + uint8_t mt; +}; + +struct challoc_signal_data { + struct gsm_bts *bts; + struct gsm_lchan *lchan; + enum gsm_chan_t type; +}; + +struct rf_signal_data { + struct gsm_network *net; +}; + +struct sms_signal_data { + /* The transaction where this occured */ + struct gsm_trans *trans; + /* Can be NULL for SMMA */ + struct gsm_sms *sms; + /* int paging result. Only the ones with > 0 */ + int paging_result; +}; + +struct lchan_signal_data { + /* The lchan the signal happened on */ + struct gsm_lchan *lchan; + /* Measurement reports on this lchan */ + struct gsm_meas_rep *mr; +}; + +/* MSC signals */ +enum signal_msc { + S_MSC_LOST, + S_MSC_CONNECTED, + S_MSC_AUTHENTICATED, +}; + +struct bsc_msc_data; +struct msc_signal_data { + struct bsc_msc_data *data; +}; + +/* SS_CCCH signals */ +enum signal_ccch { + S_CCCH_PAGING_LOAD, + S_CCCH_RACH_LOAD, +}; + +struct ccch_signal_data { + struct gsm_bts *bts; + uint16_t pg_buf_space; + uint16_t rach_slot_count; + uint16_t rach_busy_count; + uint16_t rach_access_count; +}; + +/* GPRS SGSN signals SS_SGSN */ +enum signal_sgsn { + S_SGSN_ATTACH, + S_SGSN_DETACH, + S_SGSN_UPDATE, + S_SGSN_PDP_ACT, + S_SGSN_PDP_DEACT, + S_SGSN_PDP_TERMINATE, + S_SGSN_PDP_FREE, + S_SGSN_MM_FREE, +}; + +struct sgsn_mm_ctx; +struct sgsn_signal_data { + struct sgsn_mm_ctx *mm; + struct sgsn_pdp_ctx *pdp; /* non-NULL for PDP_ACT, PDP_DEACT, PDP_FREE */ +}; + +#endif diff --git a/include/osmocom/msc/silent_call.h b/include/osmocom/msc/silent_call.h new file mode 100644 index 000000000..5fec77b73 --- /dev/null +++ b/include/osmocom/msc/silent_call.h @@ -0,0 +1,15 @@ +#ifndef _SILENT_CALL_H +#define _SILENT_CALL_H + +struct gsm_subscriber_connection; + +extern int gsm_silent_call_start(struct vlr_subscr *vsub, + void *data, int type); +extern int gsm_silent_call_stop(struct vlr_subscr *vsub); + +#if 0 +extern int silent_call_rx(struct gsm_subscriber_connection *conn, struct msgb *msg); +extern int silent_call_reroute(struct gsm_subscriber_connection *conn, struct msgb *msg); +#endif + +#endif /* _SILENT_CALL_H */ diff --git a/include/osmocom/msc/slhc.h b/include/osmocom/msc/slhc.h new file mode 100644 index 000000000..cd5a47cf4 --- /dev/null +++ b/include/osmocom/msc/slhc.h @@ -0,0 +1,187 @@ +#ifndef _SLHC_H +#define _SLHC_H +/* + * Definitions for tcp compression routines. + * + * $Header: slcompress.h,v 1.10 89/12/31 08:53:02 van Exp $ + * + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: + * - Initial distribution. + * + * + * modified for KA9Q Internet Software Package by + * Katie Stevens (dkstevens@ucdavis.edu) + * University of California, Davis + * Computing Services + * - 01-31-90 initial adaptation + * + * - Feb 1991 Bill_Simpson@um.cc.umich.edu + * variable number of conversation slots + * allow zero or one slots + * separate routines + * status display + */ + +/* + * Compressed packet format: + * + * The first octet contains the packet type (top 3 bits), TCP + * 'push' bit, and flags that indicate which of the 4 TCP sequence + * numbers have changed (bottom 5 bits). The next octet is a + * conversation number that associates a saved IP/TCP header with + * the compressed packet. The next two octets are the TCP checksum + * from the original datagram. The next 0 to 15 octets are + * sequence number changes, one change per bit set in the header + * (there may be no changes and there are two special cases where + * the receiver implicitly knows what changed -- see below). + * + * There are 5 numbers which can change (they are always inserted + * in the following order): TCP urgent pointer, window, + * acknowledgment, sequence number and IP ID. (The urgent pointer + * is different from the others in that its value is sent, not the + * change in value.) Since typical use of SLIP links is biased + * toward small packets (see comments on MTU/MSS below), changes + * use a variable length coding with one octet for numbers in the + * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the + * range 256 - 65535 or 0. (If the change in sequence number or + * ack is more than 65535, an uncompressed packet is sent.) + */ + +/* + * Packet types (must not conflict with IP protocol version) + * + * The top nibble of the first octet is the packet type. There are + * three possible types: IP (not proto TCP or tcp with one of the + * control flags set); uncompressed TCP (a normal IP/TCP packet but + * with the 8-bit protocol field replaced by an 8-bit connection id -- + * this type of packet syncs the sender & receiver); and compressed + * TCP (described above). + * + * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and + * is logically part of the 4-bit "changes" field that follows. Top + * three bits are actual packet type. For backward compatibility + * and in the interest of conserving bits, numbers are chosen so the + * IP protocol version number (4) which normally appears in this nibble + * means "IP packet". + */ + + +#include +#include + +/* SLIP compression masks for len/vers byte */ +#define SL_TYPE_IP 0x40 +#define SL_TYPE_UNCOMPRESSED_TCP 0x70 +#define SL_TYPE_COMPRESSED_TCP 0x80 +#define SL_TYPE_ERROR 0x00 + +/* Bits in first octet of compressed packet */ +#define NEW_C 0x40 /* flag bits for what changed in a packet */ +#define NEW_I 0x20 +#define NEW_S 0x08 +#define NEW_A 0x04 +#define NEW_W 0x02 +#define NEW_U 0x01 + +/* reserved, special-case values of above */ +#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */ +#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */ +#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U) + +#define TCP_PUSH_BIT 0x10 + +/* + * data type and sizes conversion assumptions: + * + * VJ code KA9Q style generic + * u_char byte_t unsigned char 8 bits + * u_short int16 unsigned short 16 bits + * u_int int16 unsigned short 16 bits + * u_long unsigned long unsigned long 32 bits + * int int32 long 32 bits + */ + +typedef __u8 byte_t; +typedef __u32 int32; + +/* + * "state" data for each active tcp conversation on the wire. This is + * basically a copy of the entire IP/TCP header from the last packet + * we saw from the conversation together with a small identifier + * the transmit & receive ends of the line use to locate saved header. + */ +struct cstate { + byte_t cs_this; /* connection id number (xmit) */ + struct cstate *next; /* next in ring (xmit) */ + struct iphdr cs_ip; /* ip/tcp hdr from most recent packet */ + struct tcphdr cs_tcp; + unsigned char cs_ipopt[64]; + unsigned char cs_tcpopt[64]; + int cs_hsize; +}; +#define NULLSLSTATE (struct cstate *)0 + +/* + * all the state data for one serial line (we need one of these per line). + */ +struct slcompress { + struct cstate *tstate; /* transmit connection states (array)*/ + struct cstate *rstate; /* receive connection states (array)*/ + + byte_t tslot_limit; /* highest transmit slot id (0-l)*/ + byte_t rslot_limit; /* highest receive slot id (0-l)*/ + + byte_t xmit_oldest; /* oldest xmit in ring */ + byte_t xmit_current; /* most recent xmit id */ + byte_t recv_current; /* most recent rcvd id */ + + byte_t flags; +#define SLF_TOSS 0x01 /* tossing rcvd frames until id received */ + + int32 sls_o_nontcp; /* outbound non-TCP packets */ + int32 sls_o_tcp; /* outbound TCP packets */ + int32 sls_o_uncompressed; /* outbound uncompressed packets */ + int32 sls_o_compressed; /* outbound compressed packets */ + int32 sls_o_searches; /* searches for connection state */ + int32 sls_o_misses; /* times couldn't find conn. state */ + + int32 sls_i_uncompressed; /* inbound uncompressed packets */ + int32 sls_i_compressed; /* inbound compressed packets */ + int32 sls_i_error; /* inbound error packets */ + int32 sls_i_tossed; /* inbound packets tossed because of error */ + + int32 sls_i_runt; + int32 sls_i_badcheck; +}; +#define NULLSLCOMPR (struct slcompress *)0 + +/* In slhc.c: */ +struct slcompress *slhc_init(const void *ctx, int rslots, int tslots); + +void slhc_free(struct slcompress *comp); + +int slhc_compress(struct slcompress *comp, unsigned char *icp, int isize, + unsigned char *ocp, unsigned char **cpp, int compress_cid); +int slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize); +int slhc_remember(struct slcompress *comp, unsigned char *icp, int isize); +int slhc_toss(struct slcompress *comp); + +void slhc_i_status(struct slcompress *comp); +void slhc_o_status(struct slcompress *comp); + +#endif /* _SLHC_H */ diff --git a/include/osmocom/msc/smpp.h b/include/osmocom/msc/smpp.h new file mode 100644 index 000000000..bcdac8f0b --- /dev/null +++ b/include/osmocom/msc/smpp.h @@ -0,0 +1,4 @@ +#pragma once + +int smpp_openbsc_alloc_init(void *ctx); +int smpp_openbsc_start(struct gsm_network *net); diff --git a/include/osmocom/msc/sms_queue.h b/include/osmocom/msc/sms_queue.h new file mode 100644 index 000000000..2a8bd5850 --- /dev/null +++ b/include/osmocom/msc/sms_queue.h @@ -0,0 +1,17 @@ +#ifndef SMS_QUEUE_H +#define SMS_QUEUE_H + +struct gsm_network; +struct gsm_sms_queue; +struct vty; + +int sms_queue_start(struct gsm_network *, int in_flight); +int sms_queue_trigger(struct gsm_sms_queue *); + +/* vty helper functions */ +int sms_queue_stats(struct gsm_sms_queue *, struct vty* vty); +int sms_queue_set_max_pending(struct gsm_sms_queue *, int max); +int sms_queue_set_max_failure(struct gsm_sms_queue *, int fail); +int sms_queue_clear(struct gsm_sms_queue *); + +#endif diff --git a/include/osmocom/msc/socket.h b/include/osmocom/msc/socket.h new file mode 100644 index 000000000..0fd85f104 --- /dev/null +++ b/include/osmocom/msc/socket.h @@ -0,0 +1,14 @@ +#ifndef _BSC_SOCKET_H +#define _BSC_SOCKET_H + +#include + +#ifndef IPPROTO_GRE +#define IPPROTO_GRE 47 +#endif + +int make_sock(struct osmo_fd *bfd, int proto, + uint32_t ip, uint16_t port, int priv_nr, + int (*cb)(struct osmo_fd *fd, unsigned int what), void *data); + +#endif /* _BSC_SOCKET_H */ diff --git a/include/osmocom/msc/system_information.h b/include/osmocom/msc/system_information.h new file mode 100644 index 000000000..854b7e3ce --- /dev/null +++ b/include/osmocom/msc/system_information.h @@ -0,0 +1,22 @@ +#ifndef _SYSTEM_INFO_H +#define _SYSTEM_INFO_H + +#include + +#include + +struct gsm_bts; + +int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type type); +size_t si2q_earfcn_count(const struct osmo_earfcn_si2q *e); +unsigned range1024_p(unsigned n); +unsigned range512_q(unsigned m); +int range_encode(enum gsm48_range r, int *arfcns, int arfcns_used, int *w, + int f0, uint8_t *chan_list); +uint8_t si2q_num(struct gsm_bts *bts); +int bts_earfcn_add(struct gsm_bts *bts, uint16_t earfcn, uint8_t thresh_hi, uint8_t thresh_lo, uint8_t prio, + uint8_t qrx, uint8_t meas_bw); +int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble); +int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, + bool diversity); +#endif diff --git a/include/osmocom/msc/transaction.h b/include/osmocom/msc/transaction.h new file mode 100644 index 000000000..272fb3b2e --- /dev/null +++ b/include/osmocom/msc/transaction.h @@ -0,0 +1,103 @@ +#ifndef _TRANSACT_H +#define _TRANSACT_H + +#include +#include +#include +#include +#include +#include +#include + +enum bridge_state { + BRIDGE_STATE_NONE, + BRIDGE_STATE_LOOPBACK_PENDING, + BRIDGE_STATE_LOOPBACK_ESTABLISHED, + BRIDGE_STATE_BRIDGE_PENDING, + BRIDGE_STATE_BRIDGE_ESTABLISHED, +}; + +/* One transaction */ +struct gsm_trans { + /* Entry in list of all transactions */ + struct llist_head entry; + + /* Back pointer to the network struct */ + struct gsm_network *net; + + /* The protocol within which we live */ + uint8_t protocol; + + /* The current transaction ID */ + uint8_t transaction_id; + + /* To whom we belong, unique identifier of remote MM entity */ + struct vlr_subscr *vsub; + + /* The associated connection we are using to transmit messages */ + struct gsm_subscriber_connection *conn; + + /* reference from MNCC or other application */ + uint32_t callref; + + /* if traffic channel receive was requested */ + int tch_recv; + + /* is thats one paging? */ + struct subscr_request *paging_request; + + /* bearer capabilities (rate and codec) */ + struct gsm_mncc_bearer_cap bearer_cap; + + /* status of the assignment, true when done */ + bool assignment_done; + + /* if true, TCH_RTP_CREATE is sent after the + * assignment is done */ + bool tch_rtp_create; + + union { + struct { + + /* current call state */ + int state; + + /* current timer and message queue */ + int Tcurrent; /* current CC timer */ + int T308_second; /* used to send release again */ + struct osmo_timer_list timer; + struct gsm_mncc msg; /* stores setup/disconnect/release message */ + } cc; + struct { + struct gsm411_smc_inst smc_inst; + struct gsm411_smr_inst smr_inst; + + struct gsm_sms *sms; + } sms; + }; + + struct { + struct gsm_trans *peer; + enum bridge_state state; + } bridge; +}; + + + +struct gsm_trans *trans_find_by_id(struct gsm_subscriber_connection *conn, + uint8_t proto, uint8_t trans_id); +struct gsm_trans *trans_find_by_callref(struct gsm_network *net, + uint32_t callref); + +struct gsm_trans *trans_alloc(struct gsm_network *net, + struct vlr_subscr *vsub, + uint8_t protocol, uint8_t trans_id, + uint32_t callref); +void trans_free(struct gsm_trans *trans); + +int trans_assign_trans_id(struct gsm_network *net, struct vlr_subscr *vsub, + uint8_t protocol, uint8_t ti_flag); +struct gsm_trans *trans_has_conn(const struct gsm_subscriber_connection *conn); +void trans_conn_closed(struct gsm_subscriber_connection *conn); + +#endif diff --git a/include/osmocom/msc/trau_mux.h b/include/osmocom/msc/trau_mux.h new file mode 100644 index 000000000..08863bfea --- /dev/null +++ b/include/osmocom/msc/trau_mux.h @@ -0,0 +1,70 @@ +/* Simple TRAU frame reflector to route voice calls */ + +/* (C) 2009 by Harald Welte + * 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 . + * + */ + +/* The "TRAU mux map" defines which particular 16kbit sub-slot (in which E1 + * timeslot on which E1 interface) should be directly muxed to which other + * sub-slot. Entries in the mux map are always bi-directional. + * + * The idea of all this is to directly switch voice channels in the BSC + * from one phone to another. We do this right now since we don't support + * any external interface for voice channels, and in the future as an + * optimization to routing them externally. + */ + +#include +#include +#include + +struct decoded_trau_frame; + +/* map a TRAU mux map entry */ +int trau_mux_map(const struct gsm_e1_subslot *src, + const struct gsm_e1_subslot *dst); +int trau_mux_map_lchan(const struct gsm_lchan *src, + const struct gsm_lchan *dst); + +/* unmap a TRAU mux map entry */ +int trau_mux_unmap(const struct gsm_e1_subslot *ss, uint32_t callref); + +/* we get called by subchan_demux */ +int trau_mux_input(struct gsm_e1_subslot *src_e1_ss, + const uint8_t *trau_bits, int num_bits); + +/* add a trau receiver */ +int trau_recv_lchan(struct gsm_lchan *lchan, uint32_t callref); + +/* send trau from application */ +int trau_send_frame(struct gsm_lchan *lchan, struct gsm_data_frame *frame); + +/* switch trau muxer to new lchan */ +int switch_trau_mux(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan); + +/* callback invoked if we receive TRAU frames */ +int subch_cb(struct subch_demux *dmx, int ch, uint8_t *data, int len, void *_priv); + +/* TRAU frame transcoding */ +struct msgb *trau_decode_fr(uint32_t callref, + const struct decoded_trau_frame *tf); +struct msgb *trau_decode_efr(uint32_t callref, + const struct decoded_trau_frame *tf); +void trau_encode_fr(struct decoded_trau_frame *tf, + const unsigned char *data); +void trau_encode_efr(struct decoded_trau_frame *tf, + const unsigned char *data); diff --git a/include/osmocom/msc/trau_upqueue.h b/include/osmocom/msc/trau_upqueue.h new file mode 100644 index 000000000..ecc765843 --- /dev/null +++ b/include/osmocom/msc/trau_upqueue.h @@ -0,0 +1,7 @@ +#ifndef _TRAU_UPQUEUE_H +#define _TRAU_UPQUEUE_H + +void trau_tx_to_mncc(struct gsm_network *net, struct msgb *msg); + +#endif /* _TRAU_UPQUEUE_H */ + diff --git a/include/osmocom/msc/ussd.h b/include/osmocom/msc/ussd.h new file mode 100644 index 000000000..266546811 --- /dev/null +++ b/include/osmocom/msc/ussd.h @@ -0,0 +1,10 @@ +#ifndef _USSD_H +#define _USSD_H + +/* Handler function for mobile-originated USSD messages */ + +#include + +int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg); + +#endif diff --git a/include/osmocom/msc/vlr.h b/include/osmocom/msc/vlr.h new file mode 100644 index 000000000..e9afde33d --- /dev/null +++ b/include/osmocom/msc/vlr.h @@ -0,0 +1,422 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +// for GSM_NAME_LENGTH +#include + +struct log_target; + +/* from 3s to 10s */ +#define GSM_29002_TIMER_S 10 +/* from 15s to 30s */ +#define GSM_29002_TIMER_M 30 +/* from 1min to 10min */ +#define GSM_29002_TIMER_ML (10*60) +/* from 28h to 38h */ +#define GSM_29002_TIMER_L (32*60*60) + +/* VLR subscriber authentication state */ +enum vlr_subscr_auth_state { + /* subscriber needs to be autenticated */ + VLR_SUB_AS_NEEDS_AUTH, + /* waiting for AuthInfo from HLR/AUC */ + VLR_SUB_AS_NEEDS_AUTH_WAIT_AI, + /* waiting for response from subscriber */ + VLR_SUB_AS_WAIT_RESP, + /* successfully authenticated */ + VLR_SUB_AS_AUTHENTICATED, + /* subscriber needs re-sync */ + VLR_SUB_AS_NEEDS_RESYNC, + /* waiting for AuthInfo with ReSync */ + VLR_SUB_AS_NEEDS_AUTH_WAIT_SAI_RESYNC, + /* waiting for response from subscr, resync case */ + VLR_SUB_AS_WAIT_RESP_RESYNC, + /* waiting for IMSI from subscriber */ + VLR_SUB_AS_WAIT_ID_IMSI, + /* authentication has failed */ + VLR_SUB_AS_AUTH_FAILED, +}; + +enum vlr_lu_event { + VLR_ULA_E_UPDATE_LA, /* Initial trigger (LU from MS) */ + VLR_ULA_E_SEND_ID_ACK, /* Result of Send-ID from PVLR */ + VLR_ULA_E_SEND_ID_NACK, /* Result of Send-ID from PVLR */ + VLR_ULA_E_AUTH_RES, /* Result of auth procedure */ + VLR_ULA_E_CIPH_RES, /* Result of Ciphering Mode Command */ + VLR_ULA_E_ID_IMSI, /* IMSI recieved from MS */ + VLR_ULA_E_ID_IMEI, /* IMEI received from MS */ + VLR_ULA_E_ID_IMEISV, /* IMEISV received from MS */ + VLR_ULA_E_HLR_LU_RES, /* HLR UpdateLocation result */ + VLR_ULA_E_UPD_HLR_COMPL,/* UpdatE_HLR_VLR result */ + VLR_ULA_E_LU_COMPL_SUCCESS,/* Location_Update_Completion_VLR result */ + VLR_ULA_E_LU_COMPL_FAILURE,/* Location_Update_Completion_VLR result */ + VLR_ULA_E_NEW_TMSI_ACK, /* TMSI Reallocation Complete */ +}; + +enum vlr_ciph_result_cause { + VLR_CIPH_REJECT, /* ? */ + VLR_CIPH_COMPL, +}; + +struct vlr_ciph_result { + enum vlr_ciph_result_cause cause; + const char *imeisv; +}; + +enum vlr_subscr_security_context { + VLR_SEC_CTX_NONE, + VLR_SEC_CTX_GSM, + VLR_SEC_CTX_UMTS, +}; + +enum vlr_lu_type { + VLR_LU_TYPE_PERIODIC, + VLR_LU_TYPE_IMSI_ATTACH, + VLR_LU_TYPE_REGULAR, +}; + +#define OSMO_LBUF_DECL(name, xlen) \ + struct { \ + uint8_t buf[xlen]; \ + size_t len; \ + } name + +struct sgsn_mm_ctx; +struct vlr_instance; + +/* The VLR subscriber is the part of the GSM subscriber state in VLR (CS) or + * SGSN (PS), particularly while interacting with the HLR via GSUP */ +struct vlr_subscr { + struct llist_head list; + struct vlr_instance *vlr; + + /* TODO either populate from HLR or drop this completely? */ + long long unsigned int id; + + /* Data from HLR */ /* 3GPP TS 23.008 */ + /* Always use vlr_subscr_set_imsi() to write to imsi[] */ + char imsi[GSM23003_IMSI_MAX_DIGITS+1]; /* 2.1.1.1 */ + char msisdn[GSM_EXTENSION_LENGTH+1]; /* 2.1.2 */ + char name[GSM_NAME_LENGTH+1]; /* proprietary */ + OSMO_LBUF_DECL(hlr, 16); /* 2.4.7 */ + uint32_t periodic_lu_timer; /* 2.4.24 */ + uint32_t age_indicator; /* 2.17.1 */ + + /* Authentication Data */ + struct gsm_auth_tuple auth_tuples[5]; /* 2.3.1-2.3.4 */ + struct gsm_auth_tuple *last_tuple; + enum vlr_subscr_security_context sec_ctx; + + /* Data local to VLR is below */ + uint32_t tmsi; /* 2.1.4 */ + /* Newly allocated TMSI that was not yet acked by MS */ + uint32_t tmsi_new; + + /* some redundancy in information below? */ + struct osmo_cell_global_id cgi; /* 2.4.16 */ + uint16_t lac; /* 2.4.2 */ + + char imeisv[GSM23003_IMEISV_NUM_DIGITS+1]; /* 2.2.3 */ + char imei[GSM23003_IMEISV_NUM_DIGITS+1]; /* 2.1.9 */ + bool imsi_detached_flag; /* 2.7.1 */ + bool conf_by_radio_contact_ind; /* 2.7.4.1 */ + bool sub_dataconf_by_hlr_ind; /* 2.7.4.2 */ + bool loc_conf_in_hlr_ind; /* 2.7.4.3 */ + bool dormant_ind; /* 2.7.8 */ + bool cancel_loc_rx; /* 2.7.8A */ + bool ms_not_reachable_flag; /* 2.10.2 (MNRF) */ + bool la_allowed; + + int use_count; + time_t expire_lu; /* FIXME: overlap with periodic_lu_timer/age_indicator */ + + struct osmo_fsm_inst *lu_fsm; + struct osmo_fsm_inst *auth_fsm; + struct osmo_fsm_inst *proc_arq_fsm; + + bool lu_complete; + + void *msc_conn_ref; + + /* PS (SGSN) specific parts */ + struct { + struct llist_head pdp_list; + uint8_t rac; + uint8_t sac; + struct gprs_mm_ctx *mmctx; + } ps; + /* CS (NITB/CSCN) specific parts */ + struct { + /* pending requests */ + bool is_paging; + /* list of struct subscr_request */ + struct llist_head requests; + uint8_t lac; + enum ran_type attached_via_ran; + } cs; +}; + +enum vlr_proc_arq_result; + +enum vlr_ciph { + VLR_CIPH_NONE, /*< A5/0, no encryption */ + VLR_CIPH_A5_1, /*< A5/1, encryption */ + VLR_CIPH_A5_2, /*< A5/2, deprecated export-grade encryption */ + VLR_CIPH_A5_3, /*< A5/3, 'new secure' encryption */ +}; + +struct vlr_ops { + /* encode + transmit an AUTH REQ towards the MS. + * \param[in] at auth tuple providing rand, key_seq and autn. + * \param[in] send_autn True to send AUTN, for r99 UMTS auth. + */ + int (*tx_auth_req)(void *msc_conn_ref, struct gsm_auth_tuple *at, + bool send_autn); + /* encode + transmit an AUTH REJECT towards the MS */ + int (*tx_auth_rej)(void *msc_conn_ref); + + /* encode + transmit an IDENTITY REQUEST towards the MS */ + int (*tx_id_req)(void *msc_conn_ref, uint8_t mi_type); + + int (*tx_lu_acc)(void *msc_conn_ref, uint32_t send_tmsi); + int (*tx_lu_rej)(void *msc_conn_ref, uint8_t cause); + int (*tx_cm_serv_acc)(void *msc_conn_ref); + int (*tx_cm_serv_rej)(void *msc_conn_ref, enum vlr_proc_arq_result result); + + int (*set_ciph_mode)(void *msc_conn_ref, enum vlr_ciph ciph_mode, + bool retrieve_imeisv); + + /* UTRAN: send Common Id (when auth+ciph are complete) */ + int (*tx_common_id)(void *msc_conn_ref); + + + /* notify MSC/SGSN that the subscriber data in VLR has been updated */ + void (*subscr_update)(struct vlr_subscr *vsub); + /* notify MSC/SGSN that the given subscriber has been associated + * with this msc_conn_ref */ + void (*subscr_assoc)(void *msc_conn_ref, struct vlr_subscr *vsub); +}; + +enum vlr_timer { + VLR_T_3250, + VLR_T_3260, + VLR_T_3270, + _NUM_VLR_TIMERS +}; + +/* An instance of the VLR codebase */ +struct vlr_instance { + struct llist_head subscribers; + struct llist_head operations; + struct gsup_client *gsup_client; + struct vlr_ops ops; + struct { + bool retrieve_imeisv_early; + bool retrieve_imeisv_ciphered; + bool assign_tmsi; + bool check_imei_rqd; + int auth_tuple_max_use_count; + bool auth_reuse_old_sets_on_error; + bool parq_retrieve_imsi; + bool is_ps; + uint32_t timer[_NUM_VLR_TIMERS]; + } cfg; + /* A free-form pointer for use by the caller */ + void *user_ctx; +}; + +extern const struct value_string vlr_ciph_names[]; +static inline const char *vlr_ciph_name(enum vlr_ciph val) +{ + return get_value_string(vlr_ciph_names, val); +} + +/* Location Updating request */ +struct osmo_fsm_inst * +vlr_loc_update(struct osmo_fsm_inst *parent, + uint32_t parent_event_success, + uint32_t parent_event_failure, + void *parent_event_data, + struct vlr_instance *vlr, void *msc_conn_ref, + enum vlr_lu_type type, uint32_t tmsi, const char *imsi, + const struct osmo_location_area_id *old_lai, + const struct osmo_location_area_id *new_lai, + bool authentication_required, + enum vlr_ciph ciphering_required, + bool is_r99, bool is_utran, + bool assign_tmsi); + +void vlr_loc_update_conn_timeout(struct osmo_fsm_inst *fi); + +/* tell the VLR that the subscriber connection is gone */ +int vlr_subscr_disconnected(struct vlr_subscr *vsub); + +int vlr_subscr_rx_id_resp(struct vlr_subscr *vsub, const uint8_t *mi, size_t mi_len); +int vlr_subscr_rx_auth_resp(struct vlr_subscr *vsub, bool is_r99, bool is_utran, + const uint8_t *res, uint8_t res_len); +int vlr_subscr_rx_auth_fail(struct vlr_subscr *vsub, const uint8_t *auts); +int vlr_subscr_tx_auth_fail_rep(struct vlr_subscr *vsub); +void vlr_subscr_rx_ciph_res(struct vlr_subscr *vsub, struct vlr_ciph_result *res); +int vlr_subscr_rx_tmsi_reall_compl(struct vlr_subscr *vsub); +int vlr_subscr_rx_imsi_detach(struct vlr_subscr *vsub); +void vlr_subscr_conn_timeout(struct vlr_subscr *vsub); + +struct vlr_instance *vlr_alloc(void *ctx, const struct vlr_ops *ops); +int vlr_start(const char *gsup_unit_name, struct vlr_instance *vlr, + const char *gsup_server_addr_str, uint16_t gsup_server_port); + +/* internal use only */ + +struct osmo_fsm_inst *sub_pres_vlr_fsm_start(struct osmo_fsm_inst *parent, + struct vlr_subscr *vsub, + uint32_t term_event); +struct osmo_fsm_inst * +upd_hlr_vlr_proc_start(struct osmo_fsm_inst *parent, + struct vlr_subscr *vsub, + uint32_t parent_event); + +struct osmo_fsm_inst * +lu_compl_vlr_proc_start(struct osmo_fsm_inst *parent, + struct vlr_subscr *vsub, + void *msc_conn_ref, + uint32_t parent_event_success, + uint32_t parent_event_failure); + + +const char *vlr_subscr_name(struct vlr_subscr *vsub); +const char *vlr_subscr_msisdn_or_name(struct vlr_subscr *vsub); + +#define vlr_subscr_find_by_imsi(vlr, imsi) \ + _vlr_subscr_find_by_imsi(vlr, imsi, __BASE_FILE__, __LINE__) +#define vlr_subscr_find_or_create_by_imsi(vlr, imsi, created) \ + _vlr_subscr_find_or_create_by_imsi(vlr, imsi, created, \ + __BASE_FILE__, __LINE__) + +#define vlr_subscr_find_by_tmsi(vlr, tmsi) \ + _vlr_subscr_find_by_tmsi(vlr, tmsi, __BASE_FILE__, __LINE__) +#define vlr_subscr_find_or_create_by_tmsi(vlr, tmsi, created) \ + _vlr_subscr_find_or_create_by_tmsi(vlr, tmsi, created, \ + __BASE_FILE__, __LINE__) + +#define vlr_subscr_find_by_msisdn(vlr, msisdn) \ + _vlr_subscr_find_by_msisdn(vlr, msisdn, __BASE_FILE__, __LINE__) + +struct vlr_subscr *_vlr_subscr_find_by_imsi(struct vlr_instance *vlr, + const char *imsi, + const char *file, int line); +struct vlr_subscr *_vlr_subscr_find_or_create_by_imsi(struct vlr_instance *vlr, + const char *imsi, + bool *created, + const char *file, + int line); + +struct vlr_subscr *_vlr_subscr_find_by_tmsi(struct vlr_instance *vlr, + uint32_t tmsi, + const char *file, int line); +struct vlr_subscr *_vlr_subscr_find_or_create_by_tmsi(struct vlr_instance *vlr, + uint32_t tmsi, + bool *created, + const char *file, + int line); + +struct vlr_subscr *_vlr_subscr_find_by_msisdn(struct vlr_instance *vlr, + const char *msisdn, + const char *file, int line); + +#define vlr_subscr_get(sub) _vlr_subscr_get(sub, __BASE_FILE__, __LINE__) +#define vlr_subscr_put(sub) _vlr_subscr_put(sub, __BASE_FILE__, __LINE__) +struct vlr_subscr *_vlr_subscr_get(struct vlr_subscr *sub, const char *file, int line); +struct vlr_subscr *_vlr_subscr_put(struct vlr_subscr *sub, const char *file, int line); + +struct vlr_subscr *vlr_subscr_alloc(struct vlr_instance *vlr); +void vlr_subscr_free(struct vlr_subscr *vsub); +int vlr_subscr_alloc_tmsi(struct vlr_subscr *vsub); + +void vlr_subscr_set_imsi(struct vlr_subscr *vsub, const char *imsi); +void vlr_subscr_set_imei(struct vlr_subscr *vsub, const char *imei); +void vlr_subscr_set_imeisv(struct vlr_subscr *vsub, const char *imeisv); +void vlr_subscr_set_msisdn(struct vlr_subscr *vsub, const char *msisdn); + +bool vlr_subscr_matches_imsi(struct vlr_subscr *vsub, const char *imsi); +bool vlr_subscr_matches_tmsi(struct vlr_subscr *vsub, uint32_t tmsi); +bool vlr_subscr_matches_msisdn(struct vlr_subscr *vsub, const char *msisdn); +bool vlr_subscr_matches_imei(struct vlr_subscr *vsub, const char *imei); + +uint32_t vlr_timer(struct vlr_instance *vlr, uint32_t timer); + +int vlr_subscr_changed(struct vlr_subscr *vsub); +int vlr_subscr_purge(struct vlr_subscr *vsub); +void vlr_subscr_cancel(struct vlr_subscr *vsub, enum gsm48_gmm_cause cause); + + +/* Process Acccess Request FSM */ + +enum vlr_proc_arq_result { + VLR_PR_ARQ_RES_NONE, + VLR_PR_ARQ_RES_SYSTEM_FAILURE, + VLR_PR_ARQ_RES_ILLEGAL_SUBSCR, + VLR_PR_ARQ_RES_UNIDENT_SUBSCR, + VLR_PR_ARQ_RES_ROAMING_NOTALLOWED, + VLR_PR_ARQ_RES_ILLEGAL_EQUIP, + VLR_PR_ARQ_RES_UNKNOWN_ERROR, + VLR_PR_ARQ_RES_TIMEOUT, + VLR_PR_ARQ_RES_PASSED, +}; + +extern const struct value_string vlr_proc_arq_result_names[]; +static inline const char *vlr_proc_arq_result_name(enum vlr_proc_arq_result res) +{ + return get_value_string(vlr_proc_arq_result_names, res); +} + +enum proc_arq_vlr_event { + PR_ARQ_E_START, + PR_ARQ_E_ID_IMSI, + PR_ARQ_E_AUTH_RES, + PR_ARQ_E_CIPH_RES, + PR_ARQ_E_UPD_LOC_RES, + PR_ARQ_E_TRACE_RES, + PR_ARQ_E_IMEI_RES, + PR_ARQ_E_PRES_RES, + PR_ARQ_E_TMSI_ACK, +}; + +enum vlr_parq_type { + VLR_PR_ARQ_T_INVALID = 0, /* to guard against unset vars */ + VLR_PR_ARQ_T_CM_SERV_REQ, + VLR_PR_ARQ_T_PAGING_RESP, + /* FIXME: differentiate between services of 24.008 10.5.3.3 */ +}; + +/* Process Access Request (CM SERV REQ / PAGING RESP) */ +void +vlr_proc_acc_req(struct osmo_fsm_inst *parent, + uint32_t parent_event_success, + uint32_t parent_event_failure, + void *parent_event_data, + struct vlr_instance *vlr, void *msc_conn_ref, + enum vlr_parq_type type, const uint8_t *mi_lv, + const struct osmo_location_area_id *lai, + bool authentication_required, + enum vlr_ciph ciphering_required, + bool is_r99, bool is_utran); + +void vlr_parq_conn_timeout(struct osmo_fsm_inst *fi); + +void vlr_parq_fsm_init(void); + +int vlr_set_ciph_mode(struct vlr_instance *vlr, + struct osmo_fsm_inst *fi, + void *msc_conn_ref, + enum vlr_ciph ciph_mode, + bool retrieve_imeisv); + +void log_set_filter_vlr_subscr(struct log_target *target, + struct vlr_subscr *vlr_subscr); diff --git a/include/osmocom/msc/vty.h b/include/osmocom/msc/vty.h new file mode 100644 index 000000000..f7056016c --- /dev/null +++ b/include/osmocom/msc/vty.h @@ -0,0 +1,54 @@ +#ifndef OPENBSC_VTY_H +#define OPENBSC_VTY_H + +#include +#include +#include + +struct gsm_network; +struct vty; + +void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *); + +struct buffer *vty_argv_to_buffer(int argc, const char *argv[], int base); + +extern struct cmd_element cfg_description_cmd; +extern struct cmd_element cfg_no_description_cmd; + +enum bsc_vty_node { + GSMNET_NODE = _LAST_OSMOVTY_NODE + 1, + BTS_NODE, + TRX_NODE, + TS_NODE, + SUBSCR_NODE, + MGCP_NODE, + GBPROXY_NODE, + SGSN_NODE, + OML_NODE, + NAT_NODE, + NAT_BSC_NODE, + MSC_NODE, + OM2K_NODE, + OM2K_CON_GROUP_NODE, + TRUNK_NODE, + PGROUP_NODE, + MNCC_INT_NODE, + NITB_NODE, + BSC_NODE, + SMPP_NODE, + SMPP_ESME_NODE, + GTPHUB_NODE, + HLR_NODE, +}; + +extern int bsc_vty_is_config_node(struct vty *vty, int node); + +struct log_info; +int bsc_vty_init(struct gsm_network *network); +int bsc_vty_init_extra(void); + +void msc_vty_init(struct gsm_network *msc_network); + +struct gsm_network *gsmnet_from_vty(struct vty *vty); + +#endif -- cgit v1.2.3