diff options
author | Neels Hofmeyr <nhofmeyr@sysmocom.de> | 2017-07-13 02:03:50 +0200 |
---|---|---|
committer | Neels Hofmeyr <neels@hofmeyr.de> | 2017-08-30 14:14:58 +0200 |
commit | ee6cfdc0d9710e3a69c8e1939eb21c8f2b759885 (patch) | |
tree | ed5aeb0979a1838778649078847a1ed6caa6b1a4 | |
parent | 6c809185ee86d318d10205756bb6d91914d11fdf (diff) |
split off osmo-sgsn: remove files, apply build1.1.0
Change-Id: I5d27ff93e56cd13e0e70edd15e2080201e35e91f
318 files changed, 795 insertions, 97309 deletions
diff --git a/configure.ac b/configure.ac index e97198528..a90a6cafc 100644 --- a/configure.ac +++ b/configure.ac @@ -48,51 +48,6 @@ PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 0.6.4) PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 0.0.1) PKG_CHECK_MODULES(LIBOSMOSIGTRAN, libosmo-sigtran) # TODO version? PKG_CHECK_MODULES(LIBCRYPTO, libcrypto >= 0.9.5) -PKG_CHECK_MODULES(LIBOSMOLEGACYMGCP, libosmo-legacy-mgcp >= 0.0.1) - -# Enabke/disable the NAT? -AC_ARG_ENABLE([nat], [AS_HELP_STRING([--enable-nat], [Build the BSC NAT. Requires SCCP])], - [osmo_ac_build_nat="$enableval"],[osmo_ac_build_nat="no"]) -if test "$osmo_ac_build_nat" = "yes" ; then - PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 0.0.2) -fi -AM_CONDITIONAL(BUILD_NAT, test "x$osmo_ac_build_nat" = "xyes") -AC_SUBST(osmo_ac_build_nat) - -# Enable/disable the BSC? -AC_ARG_ENABLE([osmo-bsc], [AS_HELP_STRING([--enable-osmo-bsc], [Build the Osmo BSC])], - [osmo_ac_build_bsc="$enableval"],[osmo_ac_build_bsc="no"]) -if test "$osmo_ac_build_bsc" = "yes" ; then - PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 0.0.6) -fi -AM_CONDITIONAL(BUILD_BSC, test "x$osmo_ac_build_bsc" = "xyes") -AC_SUBST(osmo_ac_build_bsc) - -# Enable/disable smpp support in the msc? -AC_ARG_ENABLE([smpp], [AS_HELP_STRING([--enable-smpp], [Build the SMPP interface])], - [osmo_ac_build_smpp="$enableval"],[osmo_ac_build_smpp="no"]) -if test "$osmo_ac_build_smpp" = "yes" ; then - PKG_CHECK_MODULES(LIBSMPP34, libsmpp34 >= 1.12) - AC_DEFINE(BUILD_SMPP, 1, [Define if we want to build SMPP]) -fi -AM_CONDITIONAL(BUILD_SMPP, test "x$osmo_ac_build_smpp" = "xyes") -AC_SUBST(osmo_ac_build_smpp) - -# Enable/disable transcoding within osmo-bsc_mgcp? -AC_ARG_ENABLE([mgcp-transcoding], [AS_HELP_STRING([--enable-mgcp-transcoding], [Build the MGCP gateway with internal transcoding enabled.])], - [osmo_ac_mgcp_transcoding="$enableval"],[osmo_ac_mgcp_transcoding="no"]) -AC_ARG_WITH([g729], [AS_HELP_STRING([--with-g729], [Enable G.729 encoding/decoding.])], [osmo_ac_with_g729="$withval"],[osmo_ac_with_g729="no"]) - -if test "$osmo_ac_mgcp_transcoding" = "yes" ; then - AC_SEARCH_LIBS([gsm_create], [gsm], [LIBRARY_GSM="$LIBS";LIBS=""], [AC_MSG_ERROR([--enable-mgcp-transcoding: cannot find usable libgsm])]) - AC_SUBST(LIBRARY_GSM) - if test "$osmo_ac_with_g729" = "yes" ; then - PKG_CHECK_MODULES(LIBBCG729, libbcg729 >= 0.1, [AC_DEFINE([HAVE_BCG729], [1], [Use bgc729 decoder/encoder])]) - fi - AC_DEFINE(BUILD_MGCP_TRANSCODING, 1, [Define if we want to build the MGCP gateway with transcoding support]) -fi -AM_CONDITIONAL(BUILD_MGCP_TRANSCODING, test "x$osmo_ac_mgcp_transcoding" = "xyes") -AC_SUBST(osmo_ac_mgcp_transcoding) # Enable/disable 3G aka IuPS + IuCS support? AC_ARG_ENABLE([iu], [AS_HELP_STRING([--enable-iu], [Build 3G support, aka IuPS and IuCS interfaces])], @@ -227,42 +182,18 @@ AC_OUTPUT( include/openbsc/Makefile include/Makefile src/Makefile - src/libtrau/Makefile - src/libbsc/Makefile - src/libmsc/Makefile - src/libvlr/Makefile - src/libcommon/Makefile - src/libfilter/Makefile - src/libcommon-cs/Makefile - src/osmo-msc/Makefile - src/osmo-bsc/Makefile - src/osmo-bsc_nat/Makefile - src/ipaccess/Makefile - src/utils/Makefile src/gprs/Makefile tests/Makefile tests/atlocal - tests/gsm0408/Makefile - tests/channel/Makefile - tests/bsc/Makefile - tests/bsc-nat/Makefile - tests/bsc-nat-trie/Makefile tests/gprs/Makefile tests/gbproxy/Makefile - tests/abis/Makefile - tests/smpp/Makefile - tests/trau/Makefile tests/sgsn/Makefile - tests/subscr/Makefile tests/oap/Makefile tests/gtphub/Makefile tests/xid/Makefile tests/sndcp_xid/Makefile tests/slhc/Makefile tests/v42bis/Makefile - tests/nanobts_omlattr/Makefile - tests/sms_queue/Makefile - tests/msc_vlr/Makefile doc/Makefile doc/examples/Makefile contrib/Makefile diff --git a/include/openbsc/Makefile.am b/include/openbsc/Makefile.am index c1cb6a3fb..031ef79c2 100644 --- a/include/openbsc/Makefile.am +++ b/include/openbsc/Makefile.am @@ -1,106 +1,29 @@ 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_nat.h \ - bsc_nat_callstats.h \ - bsc_nat_sccp.h \ - bsc_rll.h \ - bsc_subscriber.h \ - bss.h \ - bts_ipaccess_nanobts_omlattr.h \ - chan_alloc.h \ + a_reset.h \ common.h \ - common_bsc.h \ - common_cs.h \ crc24.h \ - ctrl.h \ - db.h \ debug.h \ - e1_config.h \ gb_proxy.h \ gprs_gb_parse.h \ gprs_gmm.h \ gprs_llc.h \ gprs_llc_xid.h \ gprs_sgsn.h \ - gprs_sndcp.h \ gprs_sndcp_comp.h \ gprs_sndcp_dcomp.h \ + gprs_sndcp.h \ gprs_sndcp_pcomp.h \ gprs_sndcp_xid.h \ gprs_subscriber.h \ gprs_utils.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 \ gtphub.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 \ - nat_rewrite_trie.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 \ - pcu_if.h \ - pcuif_proto.h \ rest_octets.h \ - rrlp.h \ - rs232.h \ - rtp_proxy.h \ sgsn.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 \ v42bis.h \ v42bis_private.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/openbsc/a_iface.h b/include/openbsc/a_iface.h deleted file mode 100644 index 149f1c71e..000000000 --- a/include/openbsc/a_iface.h +++ /dev/null @@ -1,76 +0,0 @@ -/* (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 <http://www.gnu.org/licenses/>. - * - */ - -#pragma once - -#include <openbsc/a_reset.h> - -/* 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/openbsc/a_iface_bssap.h b/include/openbsc/a_iface_bssap.h deleted file mode 100644 index 237c618fd..000000000 --- a/include/openbsc/a_iface_bssap.h +++ /dev/null @@ -1,41 +0,0 @@ -/* (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 <http://www.gnu.org/licenses/>. - * - */ - -#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/openbsc/abis_nm.h b/include/openbsc/abis_nm.h deleted file mode 100644 index db2a659e4..000000000 --- a/include/openbsc/abis_nm.h +++ /dev/null @@ -1,180 +0,0 @@ -/* 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 <laforge@gnumonks.org> - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef _NM_H -#define _NM_H - -#include <osmocom/gsm/tlv.h> -#include <osmocom/gsm/abis_nm.h> -#include <osmocom/gsm/protocol/gsm_12_21.h> - -#include <openbsc/gsm_data.h> - -/* 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/openbsc/abis_om2000.h b/include/openbsc/abis_om2000.h deleted file mode 100644 index b093a0350..000000000 --- a/include/openbsc/abis_om2000.h +++ /dev/null @@ -1,129 +0,0 @@ -#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 <laforge@gnumonks.org> - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -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/openbsc/abis_rsl.h b/include/openbsc/abis_rsl.h deleted file mode 100644 index f983fceec..000000000 --- a/include/openbsc/abis_rsl.h +++ /dev/null @@ -1,117 +0,0 @@ -/* 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 <laforge@gnumonks.org> - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef _RSL_H -#define _RSL_H - -#include <stdbool.h> -#include <osmocom/gsm/protocol/gsm_08_58.h> -#include <osmocom/gsm/gsm_utils.h> -#include <osmocom/gsm/sysinfo.h> -#include <osmocom/core/msgb.h> - -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/openbsc/arfcn_range_encode.h b/include/openbsc/arfcn_range_encode.h deleted file mode 100644 index 7ec710c33..000000000 --- a/include/openbsc/arfcn_range_encode.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef ARFCN_RANGE_ENCODE_H -#define ARFCN_RANGE_ENCODE_H - -#include <stdint.h> - -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/openbsc/auth.h b/include/openbsc/auth.h deleted file mode 100644 index b314bbf19..000000000 --- a/include/openbsc/auth.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _AUTH_H -#define _AUTH_H - -#include <osmocom/core/utils.h> - -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/openbsc/bsc_api.h b/include/openbsc/bsc_api.h deleted file mode 100644 index 40068d6ef..000000000 --- a/include/openbsc/bsc_api.h +++ /dev/null @@ -1,58 +0,0 @@ -/* 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/openbsc/bsc_msc.h b/include/openbsc/bsc_msc.h deleted file mode 100644 index 380eb17c1..000000000 --- a/include/openbsc/bsc_msc.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Routines to talk to the MSC using the IPA Protocol */ -/* - * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org> - * (C) 2010 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef BSC_MSC_H -#define BSC_MSC_H - -#include <osmocom/core/write_queue.h> -#include <osmocom/core/timer.h> -#include <osmocom/sigtran/sccp_sap.h> -#include <openbsc/a_reset.h> - -#include <netinet/in.h> - -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/openbsc/bsc_msc_data.h b/include/openbsc/bsc_msc_data.h deleted file mode 100644 index 4a283d165..000000000 --- a/include/openbsc/bsc_msc_data.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Data for the true BSC - * - * (C) 2010-2015 by Holger Hans Peter Freyther <zecke@selfish.org> - * (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 <http://www.gnu.org/licenses/>. - * - */ - -/* - * 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 <osmocom/core/timer.h> -#include <osmocom/gsm/protocol/gsm_04_08.h> - - -#include <osmocom/sigtran/osmo_ss7.h> -#include <osmocom/sigtran/sccp_sap.h> -#include <osmocom/sigtran/sccp_helpers.h> -#include <osmocom/sigtran/protocol/sua.h> -#include <osmocom/sigtran/protocol/m3ua.h> -#include <osmocom/core/fsm.h> - -#include <regex.h> - -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/openbsc/bsc_msg_filter.h b/include/openbsc/bsc_msg_filter.h deleted file mode 100644 index a9dedf43c..000000000 --- a/include/openbsc/bsc_msg_filter.h +++ /dev/null @@ -1,107 +0,0 @@ -#pragma once - -#include <osmocom/core/msgb.h> -#include <osmocom/core/msgfile.h> -#include <osmocom/core/linuxrbtree.h> -#include <osmocom/core/linuxlist.h> - -#include <regex.h> - -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/openbsc/bsc_nat.h b/include/openbsc/bsc_nat.h deleted file mode 100644 index 452daf2ab..000000000 --- a/include/openbsc/bsc_nat.h +++ /dev/null @@ -1,462 +0,0 @@ -/* - * (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org> - * (C) 2010-2012 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef BSC_NAT_H -#define BSC_NAT_H - -#include <osmocom/legacy_mgcp/mgcp.h> - -#include "bsc_msg_filter.h" - -#include <osmocom/core/select.h> -#include <osmocom/core/msgb.h> -#include <osmocom/core/msgfile.h> -#include <osmocom/core/timer.h> -#include <osmocom/core/write_queue.h> -#include <osmocom/core/rate_ctr.h> -#include <osmocom/core/statistics.h> -#include <osmocom/gsm/protocol/gsm_04_08.h> - -#include <regex.h> -#include <stdbool.h> - -#define DIR_BSC 1 -#define DIR_MSC 2 - -#define PAGIN_GROUP_UNASSIGNED -1 - -struct sccp_source_reference; -struct nat_sccp_connection; -struct bsc_nat_parsed; -struct bsc_nat; -struct bsc_nat_ussd_con; -struct nat_rewrite_rule; - -/* - * Is this terminated to the MSC, to the local machine (release - * handling for IMSI filtering) or to a USSD provider? - */ -enum { - NAT_CON_END_MSC, - NAT_CON_END_LOCAL, - NAT_CON_END_USSD, -}; - -/* - * Pending command entry - */ -struct bsc_cmd_list { - struct llist_head list_entry; - - struct osmo_timer_list timeout; - - /* The NATed ID used on the bsc_con*/ - int nat_id; - - /* The control connection from which the command originated */ - struct ctrl_connection *ccon; - - /* The command from the control connection */ - struct ctrl_cmd *cmd; -}; - -/* - * Per BSC data structure - */ -struct bsc_connection { - struct llist_head list_entry; - - /* do we know anything about this BSC? */ - int authenticated; - uint8_t last_rand[16]; - - /* the fd we use to communicate */ - struct osmo_wqueue write_queue; - - /* incoming message buffer */ - struct msgb *pending_msg; - - /* the BSS associated */ - struct bsc_config *cfg; - - /* a timeout node */ - struct osmo_timer_list id_timeout; - - /* pong timeout */ - struct osmo_timer_list ping_timeout; - struct osmo_timer_list pong_timeout; - - /* mgcp related code */ - char *_endpoint_status; - int number_multiplexes; - int max_endpoints; - int last_endpoint; - int next_transaction; - uint32_t pending_dlcx_count; - struct llist_head pending_dlcx; - - /* track the pending commands for this BSC */ - struct llist_head cmd_pending; - int last_id; - - /* a back pointer */ - struct bsc_nat *nat; -}; - -/** - * Stats per BSC - */ -struct bsc_config_stats { - struct rate_ctr_group *ctrg; -}; - -enum bsc_cfg_ctr { - BCFG_CTR_SCCP_CONN, - BCFG_CTR_SCCP_CALLS, - BCFG_CTR_NET_RECONN, - BCFG_CTR_DROPPED_SCCP, - BCFG_CTR_DROPPED_CALLS, - BCFG_CTR_REJECTED_CR, - BCFG_CTR_REJECTED_MSG, - BCFG_CTR_ILL_PACKET, - BCFG_CTR_CON_TYPE_LU, - BCFG_CTR_CON_CMSERV_RQ, - BCFG_CTR_CON_PAG_RESP, - BCFG_CTR_CON_SSA, - BCFG_CTR_CON_OTHER, -}; - -/** - * One BSC entry in the config - */ -struct bsc_config { - struct llist_head entry; - - uint8_t key[16]; - uint8_t key_present; - char *token; - int nr; - - char *description; - - /* imsi white and blacklist */ - char *acc_lst_name; - - int forbid_paging; - int paging_group; - - /* audio handling */ - int max_endpoints; - - /* used internally for reload handling */ - bool remove; - bool token_updated; - - /* backpointer */ - struct bsc_nat *nat; - - struct bsc_config_stats stats; - - struct llist_head lac_list; - - /* Osmux is enabled/disabled per BSC */ - int osmux; -}; - -struct bsc_lac_entry { - struct llist_head entry; - uint16_t lac; -}; - -struct bsc_nat_paging_group { - struct llist_head entry; - - /* list of lac entries */ - struct llist_head lists; - int nr; -}; - -/** - * BSCs point of view of endpoints - */ -struct bsc_endpoint { - /* the operation that is carried out */ - int transaction_state; - /* the pending transaction id */ - char *transaction_id; - /* the bsc we are talking to */ - struct bsc_connection *bsc; -}; - -/** - * Statistic for the nat. - */ -struct bsc_nat_statistics { - struct { - struct osmo_counter *conn; - struct osmo_counter *calls; - } sccp; - - struct { - struct osmo_counter *reconn; - struct osmo_counter *auth_fail; - } bsc; - - struct { - struct osmo_counter *reconn; - } msc; - - struct { - struct osmo_counter *reconn; - } ussd; -}; - -/** - * the structure of the "nat" network - */ -struct bsc_nat { - /* active SCCP connections that need patching */ - struct llist_head sccp_connections; - - /* active BSC connections that need patching */ - struct llist_head bsc_connections; - - /* access lists */ - struct llist_head access_lists; - - /* paging groups */ - struct llist_head paging_groups; - - /* known BSC's */ - struct llist_head bsc_configs; - int num_bsc; - int bsc_ip_dscp; - - /* MGCP config */ - struct mgcp_config *mgcp_cfg; - uint8_t mgcp_msg[4096]; - int mgcp_length; - int mgcp_ipa; - int sdp_ensure_amr_mode_set; - - /* msc things */ - struct llist_head dests; - struct bsc_msc_dest *main_dest; - struct bsc_msc_connection *msc_con; - char *token; - - /* timeouts */ - int auth_timeout; - int ping_timeout; - int pong_timeout; - - struct bsc_endpoint *bsc_endpoints; - - /* path to file with BSC config */ - char *include_file; - char *include_base; - char *resolved_path; - - /* filter */ - char *acc_lst_name; - - /* Barring of subscribers with a rb tree */ - struct rb_root imsi_black_list; - char *imsi_black_list_fn; - - /* number rewriting */ - char *num_rewr_name; - struct llist_head num_rewr; - char *num_rewr_post_name; - struct llist_head num_rewr_post; - - char *smsc_rewr_name; - struct llist_head smsc_rewr; - char *tpdest_match_name; - struct llist_head tpdest_match; - char *sms_clear_tp_srr_name; - struct llist_head sms_clear_tp_srr; - char *sms_num_rewr_name; - struct llist_head sms_num_rewr; - - /* more rewriting */ - char *num_rewr_trie_name; - struct nat_rewrite *num_rewr_trie; - - /* USSD messages we want to match */ - char *ussd_lst_name; - char *ussd_query; - regex_t ussd_query_re; - char *ussd_token; - char *ussd_local; - struct osmo_fd ussd_listen; - struct bsc_nat_ussd_con *ussd_con; - - /* for maintainenance */ - int blocked; - - /* statistics */ - struct bsc_nat_statistics stats; - - /* control interface */ - struct ctrl_handle *ctrl; -}; - -struct bsc_nat_ussd_con { - struct osmo_wqueue queue; - struct bsc_nat *nat; - int authorized; - - struct msgb *pending_msg; - - struct osmo_timer_list auth_timeout; -}; - -/* create and init the structures */ -struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, - unsigned int number); -struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num); -struct bsc_config *bsc_config_by_token(struct bsc_nat *nat, const char *token, int len); -void bsc_config_free(struct bsc_config *); -void bsc_config_add_lac(struct bsc_config *cfg, int lac); -void bsc_config_del_lac(struct bsc_config *cfg, int lac); -int bsc_config_handles_lac(struct bsc_config *cfg, int lac); - -struct bsc_nat *bsc_nat_alloc(void); -struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat); -void bsc_nat_set_msc_ip(struct bsc_nat *bsc, const char *ip); - -void sccp_connection_destroy(struct nat_sccp_connection *); -void bsc_close_connection(struct bsc_connection *); - -const char *bsc_con_type_to_string(int type); - -/** - * parse the given message into the above structure - */ -struct bsc_nat_parsed *bsc_nat_parse(struct msgb *msg); - -/** - * filter based on IP Access header in both directions - */ -int bsc_nat_filter_ipa(int direction, struct msgb *msg, struct bsc_nat_parsed *parsed); -int bsc_nat_vty_init(struct bsc_nat *nat); -int bsc_nat_find_paging(struct msgb *msg, const uint8_t **,int *len); - -/** - * SCCP patching and handling - */ -struct nat_sccp_connection *create_sccp_src_ref(struct bsc_connection *bsc, struct bsc_nat_parsed *parsed); -int update_sccp_src_ref(struct nat_sccp_connection *sccp, struct bsc_nat_parsed *parsed); -void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed); -struct nat_sccp_connection *patch_sccp_src_ref_to_bsc(struct msgb *, struct bsc_nat_parsed *, struct bsc_nat *); -struct nat_sccp_connection *patch_sccp_src_ref_to_msc(struct msgb *, struct bsc_nat_parsed *, struct bsc_connection *); -struct nat_sccp_connection *bsc_nat_find_con_by_bsc(struct bsc_nat *, struct sccp_source_reference *); - -/** - * MGCP/Audio handling - */ -int bsc_mgcp_nr_multiplexes(int max_endpoints); -int bsc_write_mgcp(struct bsc_connection *bsc, const uint8_t *data, unsigned int length); -int bsc_mgcp_assign_patch(struct nat_sccp_connection *, struct msgb *msg); -void bsc_mgcp_init(struct nat_sccp_connection *); -void bsc_mgcp_dlcx(struct nat_sccp_connection *); -void bsc_mgcp_free_endpoints(struct bsc_nat *nat); -int bsc_mgcp_nat_init(struct bsc_nat *nat); - -struct nat_sccp_connection *bsc_mgcp_find_con(struct bsc_nat *, int endpoint_number); -struct msgb *bsc_mgcp_rewrite(char *input, int length, int endp, const char *ip, - int port, int osmux, int *first_payload_type, int mode_set); -void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg); - -void bsc_mgcp_clear_endpoints_for(struct bsc_connection *bsc); -int bsc_mgcp_parse_response(const char *str, int *code, char transaction[60]); -uint32_t bsc_mgcp_extract_ci(const char *resp); - - -int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int id); -int bsc_do_write(struct osmo_wqueue *queue, struct msgb *msg, int id); -int bsc_write_msg(struct osmo_wqueue *queue, struct msgb *msg); -int bsc_write_cb(struct osmo_fd *bfd, struct msgb *msg); - -int bsc_nat_msc_is_connected(struct bsc_nat *nat); - -int bsc_conn_type_to_ctr(struct nat_sccp_connection *conn); - -struct gsm48_hdr *bsc_unpack_dtap(struct bsc_nat_parsed *parsed, struct msgb *msg, uint32_t *len); - -/** USSD filtering */ -int bsc_ussd_init(struct bsc_nat *nat); -int bsc_ussd_check(struct nat_sccp_connection *con, struct bsc_nat_parsed *parsed, struct msgb *msg); -int bsc_ussd_close_connections(struct bsc_nat *nat); - -struct msgb *bsc_nat_rewrite_msg(struct bsc_nat *nat, struct msgb *msg, struct bsc_nat_parsed *, const char *imsi); - -/** paging group handling */ -struct bsc_nat_paging_group *bsc_nat_paging_group_num(struct bsc_nat *nat, int group); -struct bsc_nat_paging_group *bsc_nat_paging_group_create(struct bsc_nat *nat, int group); -void bsc_nat_paging_group_delete(struct bsc_nat_paging_group *); -void bsc_nat_paging_group_add_lac(struct bsc_nat_paging_group *grp, int lac); -void bsc_nat_paging_group_del_lac(struct bsc_nat_paging_group *grp, int lac); - -/** - * Number rewriting support below - */ -struct bsc_nat_num_rewr_entry { - struct llist_head list; - - regex_t msisdn_reg; - regex_t num_reg; - - char *replace; - uint8_t is_prefix_lookup; -}; - -void bsc_nat_num_rewr_entry_adapt(void *ctx, struct llist_head *head, const struct osmo_config_list *); - -void bsc_nat_send_mgcp_to_msc(struct bsc_nat *bsc_nat, struct msgb *msg); -void bsc_nat_handle_mgcp(struct bsc_nat *bsc, struct msgb *msg); - -struct ctrl_handle *bsc_nat_controlif_setup(struct bsc_nat *nat, - const char *bind_addr, int port); -void bsc_nat_ctrl_del_pending(struct bsc_cmd_list *pending); -int bsc_nat_handle_ctrlif_msg(struct bsc_connection *bsc, struct msgb *msg); - -int bsc_nat_extract_lac(struct bsc_connection *bsc, struct nat_sccp_connection *con, - struct bsc_nat_parsed *parsed, struct msgb *msg); - -int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg, - struct bsc_nat_parsed *, int *con_type, char **imsi, - struct bsc_filter_reject_cause *cause); -int bsc_nat_filter_dt(struct bsc_connection *bsc, struct msgb *msg, - struct nat_sccp_connection *con, struct bsc_nat_parsed *parsed, - struct bsc_filter_reject_cause *cause); - -/** - * CTRL interface helper - */ -void bsc_nat_inform_reject(struct bsc_connection *bsc, const char *imsi); - -/* - * Use for testing - */ -void bsc_nat_free(struct bsc_nat *nat); - -#endif diff --git a/include/openbsc/bsc_nat_callstats.h b/include/openbsc/bsc_nat_callstats.h deleted file mode 100644 index 64f9bfc0a..000000000 --- a/include/openbsc/bsc_nat_callstats.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org> - * (C) 2010-2012 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef BSC_NAT_CALLSTATS_H -#define BSC_NAT_CALLSTATS_H - -#include <osmocom/core/linuxlist.h> - -#include <osmocom/sccp/sccp_types.h> - -struct bsc_nat_call_stats { - struct llist_head entry; - - struct sccp_source_reference remote_ref; - struct sccp_source_reference src_ref; /* as seen by the MSC */ - - /* mgcp options */ - uint32_t ci; - int bts_rtp_port; - int net_rtp_port; - struct in_addr bts_addr; - struct in_addr net_addr; - - - /* as witnessed by the NAT */ - uint32_t net_ps; - uint32_t net_os; - uint32_t bts_pr; - uint32_t bts_or; - uint32_t bts_expected; - uint32_t bts_jitter; - int bts_loss; - - uint32_t trans_id; - int msc_endpoint; -}; - -#endif diff --git a/include/openbsc/bsc_nat_sccp.h b/include/openbsc/bsc_nat_sccp.h deleted file mode 100644 index 082466408..000000000 --- a/include/openbsc/bsc_nat_sccp.h +++ /dev/null @@ -1,105 +0,0 @@ -/* NAT utilities using SCCP types */ -/* - * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org> - * (C) 2010 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef BSC_NAT_SCCP_H -#define BSC_NAT_SCCP_H - -#include "bsc_msg_filter.h" - -#include <osmocom/sccp/sccp_types.h> - -/* - * For the NAT we will need to analyze and later patch - * the received message. This would require us to parse - * the IPA and SCCP header twice. Instead of doing this - * we will have one analyze structure and have the patching - * and filter operate on the same structure. - */ -struct bsc_nat_parsed { - /* ip access prototype */ - int ipa_proto; - - /* source local reference */ - struct sccp_source_reference *src_local_ref; - - /* destination local reference */ - struct sccp_source_reference *dest_local_ref; - - /* original value */ - struct sccp_source_reference original_dest_ref; - - /* called ssn number */ - int called_ssn; - - /* calling ssn number */ - int calling_ssn; - - /* sccp message type */ - int sccp_type; - - /* bssap type, e.g. 0 for BSS Management */ - int bssap; - - /* the gsm0808 message type */ - int gsm_type; -}; - -/* - * Per SCCP source local reference patch table. It needs to - * be updated on new SCCP connections, connection confirm and reject, - * and on the loss of the BSC connection. - */ -struct nat_sccp_connection { - struct llist_head list_entry; - - struct bsc_connection *bsc; - struct bsc_msc_connection *msc_con; - - struct sccp_source_reference real_ref; - struct sccp_source_reference patched_ref; - struct sccp_source_reference remote_ref; - int has_remote_ref; - - /* status */ - int con_local; - int authorized; - - struct bsc_filter_state filter_state; - - uint16_t lac; - uint16_t ci; - - /* remember which Transactions we run over the bypass */ - char ussd_ti[8]; - - /* - * audio handling. Remember if we have ever send a CRCX, - * remember the endpoint used by the MSC and BSC. - */ - int msc_endp; - int bsc_endp; - - /* timeout handling */ - struct timespec creation_time; -}; - - -#endif diff --git a/include/openbsc/bsc_rll.h b/include/openbsc/bsc_rll.h deleted file mode 100644 index 729ba6037..000000000 --- a/include/openbsc/bsc_rll.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _BSC_RLL_H -#define _BSC_RLL_H - -#include <openbsc/gsm_data.h> - -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/openbsc/bsc_subscriber.h b/include/openbsc/bsc_subscriber.h deleted file mode 100644 index 324734f9a..000000000 --- a/include/openbsc/bsc_subscriber.h +++ /dev/null @@ -1,43 +0,0 @@ -/* GSM subscriber details for use in BSC land */ - -#pragma once - -#include <stdint.h> - -#include <osmocom/core/linuxlist.h> -#include <osmocom/gsm/protocol/gsm_23_003.h> - -struct log_target; - -struct bsc_subscr { - struct llist_head entry; - int use_count; - - char imsi[GSM23003_IMSI_MAX_DIGITS+1]; - uint32_t tmsi; - uint16_t lac; -}; - -const char *bsc_subscr_name(struct bsc_subscr *bsub); - -struct bsc_subscr *bsc_subscr_find_or_create_by_imsi(struct llist_head *list, - const char *imsi); -struct bsc_subscr *bsc_subscr_find_or_create_by_tmsi(struct llist_head *list, - uint32_t tmsi); - -struct bsc_subscr *bsc_subscr_find_by_imsi(struct llist_head *list, - const char *imsi); -struct bsc_subscr *bsc_subscr_find_by_tmsi(struct llist_head *list, - uint32_t tmsi); - -void bsc_subscr_set_imsi(struct bsc_subscr *bsub, const char *imsi); - -struct bsc_subscr *_bsc_subscr_get(struct bsc_subscr *bsub, - const char *file, int line); -struct bsc_subscr *_bsc_subscr_put(struct bsc_subscr *bsub, - const char *file, int line); -#define bsc_subscr_get(bsub) _bsc_subscr_get(bsub, __BASE_FILE__, __LINE__) -#define bsc_subscr_put(bsub) _bsc_subscr_put(bsub, __BASE_FILE__, __LINE__) - -void log_set_filter_bsc_subscr(struct log_target *target, - struct bsc_subscr *bsub); diff --git a/include/openbsc/bss.h b/include/openbsc/bss.h deleted file mode 100644 index 9f16bf7d7..000000000 --- a/include/openbsc/bss.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _BSS_H_ -#define _BSS_H_ - -#include <openbsc/gsm_data.h> - -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/openbsc/bts_ipaccess_nanobts_omlattr.h b/include/openbsc/bts_ipaccess_nanobts_omlattr.h deleted file mode 100644 index bc7860b2d..000000000 --- a/include/openbsc/bts_ipaccess_nanobts_omlattr.h +++ /dev/null @@ -1,32 +0,0 @@ -/* OML attribute table generator for ipaccess nanobts */ - -/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> - * 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 <http://www.gnu.org/licenses/>. - */ - -#pragma once - -#include <stdint.h> -#include <osmocom/core/msgb.h> - -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/openbsc/chan_alloc.h b/include/openbsc/chan_alloc.h deleted file mode 100644 index 7388e14c5..000000000 --- a/include/openbsc/chan_alloc.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Management functions to allocate/release struct gsm_lchan */ -/* (C) 2008 by Harald Welte <laforge@gnumonks.org> - * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org> - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ -#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/openbsc/common_bsc.h b/include/openbsc/common_bsc.h deleted file mode 100644 index 796038323..000000000 --- a/include/openbsc/common_bsc.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include <stdint.h> -#include <openbsc/common_cs.h> - -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/openbsc/common_cs.h b/include/openbsc/common_cs.h deleted file mode 100644 index 6dc956f80..000000000 --- a/include/openbsc/common_cs.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include <stdint.h> - -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/openbsc/ctrl.h b/include/openbsc/ctrl.h deleted file mode 100644 index c5ac21092..000000000 --- a/include/openbsc/ctrl.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -struct ctrl_handle *bsc_controlif_setup(struct gsm_network *net, - const char *bind_addr, uint16_t port); diff --git a/include/openbsc/db.h b/include/openbsc/db.h deleted file mode 100644 index 988c9bd6e..000000000 --- a/include/openbsc/db.h +++ /dev/null @@ -1,59 +0,0 @@ -/* (C) 2008 by Jan Luebbe <jluebbe@debian.org> - * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org> - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef _DB_H -#define _DB_H - -#include <stdbool.h> - -#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/openbsc/e1_config.h b/include/openbsc/e1_config.h deleted file mode 100644 index 538c0b09d..000000000 --- a/include/openbsc/e1_config.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _E1_CONFIG_H -#define _E1_CONFIG_H - -#include <openbsc/gsm_data_shared.h> - -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/openbsc/gprs_sgsn.h b/include/openbsc/gprs_sgsn.h index 57995e018..c47fb0905 100644 --- a/include/openbsc/gprs_sgsn.h +++ b/include/openbsc/gprs_sgsn.h @@ -10,8 +10,7 @@ #include <osmocom/crypt/gprs_cipher.h> #include <osmocom/gsm/protocol/gsm_23_003.h> - -#include <openbsc/gsm_data.h> +#include <osmocom/crypt/auth.h> #define GSM_EXTENSION_LENGTH 15 #define GSM_APN_LENGTH 102 @@ -119,6 +118,13 @@ struct service_info { struct ranap_ue_conn_ctx; +struct gsm_auth_tuple { + int use_count; + int key_seq; + struct osmo_auth_vector vec; +}; +#define GSM_KEY_SEQ_INVAL 7 /* GSM 04.08 - 10.5.1.2 */ + /* According to TS 03.60, Table 5: SGSN MM and PDP Contexts */ /* Extended by 3GPP TS 23.060, Table 6: SGSN MM and PDP Contexts */ struct sgsn_mm_ctx { diff --git a/include/openbsc/gprs_utils.h b/include/openbsc/gprs_utils.h index 574f5c50c..e06364dad 100644 --- a/include/openbsc/gprs_utils.h +++ b/include/openbsc/gprs_utils.h @@ -24,6 +24,8 @@ #include <stdint.h> #include <sys/types.h> +#include <osmocom/core/msgb.h> + struct msgb; struct gprs_ra_id; @@ -42,3 +44,12 @@ int gprs_parse_mi_tmsi(const uint8_t *value, size_t value_len, uint32_t *tmsi); void gprs_parse_tmsi(const uint8_t *value, uint32_t *tmsi); int gprs_ra_id_equals(const struct gprs_ra_id *id1, const struct gprs_ra_id *id2); + +#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); +} diff --git a/include/openbsc/gsm_04_08.h b/include/openbsc/gsm_04_08.h deleted file mode 100644 index ca251b00b..000000000 --- a/include/openbsc/gsm_04_08.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef _GSM_04_08_H -#define _GSM_04_08_H - -#include <osmocom/gsm/gsm48.h> -#include <osmocom/gsm/gsm_utils.h> -#include <osmocom/gsm/protocol/gsm_04_08.h> - -#include <openbsc/meas_rep.h> - -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/openbsc/gsm_04_11.h b/include/openbsc/gsm_04_11.h deleted file mode 100644 index 3305e3e61..000000000 --- a/include/openbsc/gsm_04_11.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _GSM_04_11_H -#define _GSM_04_11_H - -#include <osmocom/gsm/protocol/gsm_04_11.h> - -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/openbsc/gsm_04_80.h b/include/openbsc/gsm_04_80.h deleted file mode 100644 index d65f640bc..000000000 --- a/include/openbsc/gsm_04_80.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _GSM_04_80_H -#define _GSM_04_80_H - -#include <osmocom/core/msgb.h> -#include <osmocom/gsm/protocol/gsm_04_80.h> -#include <osmocom/gsm/gsm0480.h> - -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/openbsc/gsm_data.h b/include/openbsc/gsm_data.h deleted file mode 100644 index 88a4f1067..000000000 --- a/include/openbsc/gsm_data.h +++ /dev/null @@ -1,691 +0,0 @@ -#ifndef _GSM_DATA_H -#define _GSM_DATA_H - -#include <stdint.h> -#include <regex.h> -#include <sys/types.h> -#include <stdbool.h> - -#include <osmocom/core/timer.h> -#include <osmocom/core/rate_ctr.h> -#include <osmocom/core/select.h> -#include <osmocom/core/stats.h> - -#include <osmocom/crypt/auth.h> -#include <osmocom/sigtran/sccp_sap.h> - -#include <openbsc/common.h> -#include <openbsc/rest_octets.h> -#include <openbsc/common_cs.h> -#include <osmocom/legacy_mgcp/mgcpgw_client.h> - - -/** 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/openbsc/gsm_data_shared.h b/include/openbsc/gsm_data_shared.h deleted file mode 100644 index bed46d254..000000000 --- a/include/openbsc/gsm_data_shared.h +++ /dev/null @@ -1,1003 +0,0 @@ -#ifndef _GSM_DATA_SHAREDH -#define _GSM_DATA_SHAREDH - -#include <regex.h> -#include <stdbool.h> -#include <stdint.h> - -#include <osmocom/core/timer.h> -#include <osmocom/core/bitvec.h> -#include <osmocom/core/statistics.h> -#include <osmocom/core/utils.h> -#include <osmocom/gsm/gsm_utils.h> -#include <osmocom/gsm/tlv.h> -#include <osmocom/gsm/rxlev_stat.h> -#include <osmocom/gsm/sysinfo.h> -#include <osmocom/gsm/meas_rep.h> -#include <osmocom/gsm/protocol/gsm_04_08.h> -#include <osmocom/gsm/protocol/gsm_08_58.h> -#include <osmocom/gsm/protocol/gsm_12_21.h> - -#include <osmocom/abis/e1_input.h> - -#ifndef ROLE_BSC -#include <osmocom/gsm/lapdm.h> -#endif - -#include <openbsc/common_cs.h> - -/* 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/openbsc/gsm_subscriber.h b/include/openbsc/gsm_subscriber.h deleted file mode 100644 index d88e32aa7..000000000 --- a/include/openbsc/gsm_subscriber.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef _GSM_SUBSCR_H -#define _GSM_SUBSCR_H - -#include <stdbool.h> - -#include <osmocom/core/linuxlist.h> -#include <osmocom/gsm/protocol/gsm_23_003.h> - -#include <openbsc/gsm_data.h> - -#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/openbsc/handover.h b/include/openbsc/handover.h deleted file mode 100644 index 3fe71a28b..000000000 --- a/include/openbsc/handover.h +++ /dev/null @@ -1,14 +0,0 @@ -#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/openbsc/handover_decision.h b/include/openbsc/handover_decision.h deleted file mode 100644 index 81078b05d..000000000 --- a/include/openbsc/handover_decision.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _HANDOVER_DECISION_H -#define _HANDOVER_DECISION_H - -void on_dso_load_ho_dec(void); - -#endif /* _HANDOVER_DECISION_H */ - diff --git a/include/openbsc/ipaccess.h b/include/openbsc/ipaccess.h deleted file mode 100644 index 82e89c27d..000000000 --- a/include/openbsc/ipaccess.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _IPACCESS_H -#define _IPACCESS_H - -#include <osmocom/abis/e1_input.h> -#include "gsm_subscriber.h" -#include <osmocom/core/linuxlist.h> -#include <osmocom/gsm/protocol/ipaccess.h> -#include <osmocom/gsm/protocol/gsm_23_003.h> - -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/openbsc/iucs.h b/include/openbsc/iucs.h deleted file mode 100644 index b7d60645d..000000000 --- a/include/openbsc/iucs.h +++ /dev/null @@ -1,7 +0,0 @@ -#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/openbsc/iucs_ranap.h b/include/openbsc/iucs_ranap.h deleted file mode 100644 index c2ff5f90e..000000000 --- a/include/openbsc/iucs_ranap.h +++ /dev/null @@ -1,7 +0,0 @@ -#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/openbsc/meas_feed.h b/include/openbsc/meas_feed.h deleted file mode 100644 index f77ee075f..000000000 --- a/include/openbsc/meas_feed.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _OPENBSC_MEAS_FEED_H -#define _OPENBSC_MEAS_FEED_H - -#include <stdint.h> - -#include <openbsc/meas_rep.h> - -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/openbsc/meas_rep.h b/include/openbsc/meas_rep.h deleted file mode 100644 index b0c03f0bb..000000000 --- a/include/openbsc/meas_rep.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef _MEAS_REP_H -#define _MEAS_REP_H - -#include <stdint.h> - -#include <osmocom/gsm/meas_rep.h> - -#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/openbsc/misdn.h b/include/openbsc/misdn.h deleted file mode 100644 index 9851ad32c..000000000 --- a/include/openbsc/misdn.h +++ /dev/null @@ -1,27 +0,0 @@ -/* (C) 2008 by Harald Welte <laforge@gnumonks.org> - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef MISDN_H -#define MISDN_H - -#include <osmocom/abis/e1_input.h> - -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/openbsc/mncc.h b/include/openbsc/mncc.h deleted file mode 100644 index 881e0418e..000000000 --- a/include/openbsc/mncc.h +++ /dev/null @@ -1,215 +0,0 @@ -/* 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 <laforge@gnumonks.org> - * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org> - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef _MNCC_H -#define _MNCC_H - -#include <osmocom/core/linuxlist.h> -#include <osmocom/gsm/mncc.h> - -#include <stdint.h> - -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/openbsc/mncc_int.h b/include/openbsc/mncc_int.h deleted file mode 100644 index 213ce1414..000000000 --- a/include/openbsc/mncc_int.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _MNCC_INT_H -#define _MNCC_INT_H - -#include <stdint.h> - -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/openbsc/msc_ifaces.h b/include/openbsc/msc_ifaces.h deleted file mode 100644 index a1071ae9b..000000000 --- a/include/openbsc/msc_ifaces.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include <osmocom/core/msgb.h> -#include <openbsc/gsm_data.h> - -/* 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/openbsc/nat_rewrite_trie.h b/include/openbsc/nat_rewrite_trie.h deleted file mode 100644 index 0571099c6..000000000 --- a/include/openbsc/nat_rewrite_trie.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * (C) 2013 by On-Waves - * (C) 2013 by Holger Hans Peter Freyther <zecke@selfish.org> - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ -#ifndef NAT_REWRITE_FILE_H -#define NAT_REWRITE_FILE_H - -#include <osmocom/core/linuxrbtree.h> - -struct vty; - -struct nat_rewrite_rule { - /* For digits 0-9 and + */ - struct nat_rewrite_rule *rules[11]; - - char empty; - char prefix[14]; - char rewrite[6]; -}; - -struct nat_rewrite { - struct nat_rewrite_rule rule; - size_t prefixes; -}; - - -struct nat_rewrite *nat_rewrite_parse(void *ctx, const char *filename); -struct nat_rewrite_rule *nat_rewrite_lookup(struct nat_rewrite *, const char *prefix); -void nat_rewrite_dump(struct nat_rewrite *rewr); -void nat_rewrite_dump_vty(struct vty *vty, struct nat_rewrite *rewr); - -#endif diff --git a/include/openbsc/network_listen.h b/include/openbsc/network_listen.h deleted file mode 100644 index 67d1f4ef7..000000000 --- a/include/openbsc/network_listen.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _OPENBSC_NWL_H -#define _OPENBSC_NWL_H - -#include <stdint.h> -#include <openbsc/gsm_data.h> - -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/openbsc/openbscdefines.h b/include/openbsc/openbscdefines.h deleted file mode 100644 index c6ac153b8..000000000 --- a/include/openbsc/openbscdefines.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org> - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#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/openbsc/osmo_bsc.h b/include/openbsc/osmo_bsc.h deleted file mode 100644 index 5ebea5079..000000000 --- a/include/openbsc/osmo_bsc.h +++ /dev/null @@ -1,75 +0,0 @@ -/* 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/openbsc/osmo_bsc_grace.h b/include/openbsc/osmo_bsc_grace.h deleted file mode 100644 index 5a81cd137..000000000 --- a/include/openbsc/osmo_bsc_grace.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * (C) 2010-2013 by Holger Hans Peter Freyther <zecke@selfish.org> - * (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 <http://www.gnu.org/licenses/>. - * - */ - -#ifndef OSMO_BSC_GRACE_H -#define OSMO_BSC_GRACE_H - -#include <openbsc/gsm_data.h> -#include <openbsc/signal.h> - -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/openbsc/osmo_bsc_reset.h b/include/openbsc/osmo_bsc_reset.h deleted file mode 100644 index 578f763e6..000000000 --- a/include/openbsc/osmo_bsc_reset.h +++ /dev/null @@ -1,34 +0,0 @@ -/* (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 <http://www.gnu.org/licenses/>. - * - */ - -/* 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/openbsc/osmo_bsc_rf.h b/include/openbsc/osmo_bsc_rf.h deleted file mode 100644 index 19ccd080d..000000000 --- a/include/openbsc/osmo_bsc_rf.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef OSMO_BSC_RF -#define OSMO_BSC_RF - -#include <openbsc/gsm_data.h> -#include <osmocom/core/write_queue.h> -#include <osmocom/core/timer.h> - -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/openbsc/osmo_bsc_sigtran.h b/include/openbsc/osmo_bsc_sigtran.h deleted file mode 100644 index fbcfcb3fc..000000000 --- a/include/openbsc/osmo_bsc_sigtran.h +++ /dev/null @@ -1,48 +0,0 @@ -/* (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 <http://www.gnu.org/licenses/>. - * - */ - -#pragma once - -#include <openbsc/gsm_data.h> -#include <openbsc/bsc_msc_data.h> - -/* 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/openbsc/osmo_msc.h b/include/openbsc/osmo_msc.h deleted file mode 100644 index cdfd27f11..000000000 --- a/include/openbsc/osmo_msc.h +++ /dev/null @@ -1,99 +0,0 @@ -/* Routines for the MSC handling */ - -#ifndef OSMO_MSC_H -#define OSMO_MSC_H - -#include <osmocom/core/fsm.h> -#include <osmocom/gsm/gsup.h> - -#include <openbsc/gsm_data.h> - -#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/openbsc/osmux.h b/include/openbsc/osmux.h deleted file mode 100644 index f3ea72a85..000000000 --- a/include/openbsc/osmux.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _OPENBSC_OSMUX_H_ -#define _OPENBSC_OSMUX_H_ - -#include <osmocom/netif/osmux.h> - -#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/openbsc/paging.h b/include/openbsc/paging.h deleted file mode 100644 index 7dd8500ac..000000000 --- a/include/openbsc/paging.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Paging helper and manager.... */ -/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org> - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef PAGING_H -#define PAGING_H - -#include <stdlib.h> -#include <string.h> - -#include <osmocom/core/linuxlist.h> -#include <osmocom/core/timer.h> - -#include <openbsc/gsm_data.h> -#include <openbsc/bsc_subscriber.h> - -/** - * 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/openbsc/pcu_if.h b/include/openbsc/pcu_if.h deleted file mode 100644 index 1f398b4aa..000000000 --- a/include/openbsc/pcu_if.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _PCU_IF_H -#define _PCU_IF_H - -#include <osmocom/gsm/l1sap.h> - -extern int pcu_direct; - -struct pcu_sock_state { - struct gsm_network *net; - struct osmo_fd listen_bfd; /* fd for listen socket */ - struct osmo_fd conn_bfd; /* fd for connection to lcr */ - struct llist_head upqueue; /* queue for sending messages */ -}; - -/* PCU relevant information has changed; Inform PCU (if connected) */ -void pcu_info_update(struct gsm_bts *bts); - -/* Forward rach indication to PCU */ -int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint16_t ra, uint32_t fn, - uint8_t is_11bit, enum ph_burst_type burst_type); - -/* Confirm the sending of an immediate assignment to the pcu */ -int pcu_tx_imm_ass_sent(struct gsm_bts *bts, uint32_t tlli); - - -/* Confirm the sending of an immediate assignment to the pcu */ -int pcu_tx_imm_ass_sent(struct gsm_bts *bts, uint32_t tlli); - -/* Open connection to PCU */ -int pcu_sock_init(const char *path, struct gsm_bts *bts); - -/* Close connection to PCU */ -void pcu_sock_exit(struct gsm_bts *bts); - -#endif /* _PCU_IF_H */ diff --git a/include/openbsc/pcuif_proto.h b/include/openbsc/pcuif_proto.h deleted file mode 100644 index eb28d66bc..000000000 --- a/include/openbsc/pcuif_proto.h +++ /dev/null @@ -1,176 +0,0 @@ -#ifndef _PCUIF_PROTO_H -#define _PCUIF_PROTO_H - -#define PCU_IF_VERSION 0x08 - -/* msg_type */ -#define PCU_IF_MSG_DATA_REQ 0x00 /* send data to given channel */ -#define PCU_IF_MSG_DATA_CNF 0x01 /* confirm (e.g. transmission on PCH) */ -#define PCU_IF_MSG_DATA_IND 0x02 /* receive data from given channel */ -#define PCU_IF_MSG_DATA_CNF_DT 0x11 /* confirm (with direct tlli) */ -#define PCU_IF_MSG_RTS_REQ 0x10 /* ready to send request */ -#define PCU_IF_MSG_RACH_IND 0x22 /* receive RACH */ -#define PCU_IF_MSG_INFO_IND 0x32 /* retrieve BTS info */ -#define PCU_IF_MSG_ACT_REQ 0x40 /* activate/deactivate PDCH */ -#define PCU_IF_MSG_TIME_IND 0x52 /* GSM time indication */ -#define PCU_IF_MSG_PAG_REQ 0x60 /* paging request */ - -/* sapi */ -#define PCU_IF_SAPI_RACH 0x01 /* channel request on CCCH */ -#define PCU_IF_SAPI_AGCH 0x02 /* assignment on AGCH */ -#define PCU_IF_SAPI_PCH 0x03 /* paging/assignment on PCH */ -#define PCU_IF_SAPI_BCCH 0x04 /* SI on BCCH */ -#define PCU_IF_SAPI_PDTCH 0x05 /* packet data/control/ccch block */ -#define PCU_IF_SAPI_PRACH 0x06 /* packet random access channel */ -#define PCU_IF_SAPI_PTCCH 0x07 /* packet TA control channel */ -#define PCU_IF_SAPI_AGCH_DT 0x08 /* assignment on AGCH but with additional TLLI */ - -/* flags */ -#define PCU_IF_FLAG_ACTIVE (1 << 0)/* BTS is active */ -#define PCU_IF_FLAG_SYSMO (1 << 1)/* access PDCH of sysmoBTS directly */ -#define PCU_IF_FLAG_CS1 (1 << 16) -#define PCU_IF_FLAG_CS2 (1 << 17) -#define PCU_IF_FLAG_CS3 (1 << 18) -#define PCU_IF_FLAG_CS4 (1 << 19) -#define PCU_IF_FLAG_MCS1 (1 << 20) -#define PCU_IF_FLAG_MCS2 (1 << 21) -#define PCU_IF_FLAG_MCS3 (1 << 22) -#define PCU_IF_FLAG_MCS4 (1 << 23) -#define PCU_IF_FLAG_MCS5 (1 << 24) -#define PCU_IF_FLAG_MCS6 (1 << 25) -#define PCU_IF_FLAG_MCS7 (1 << 26) -#define PCU_IF_FLAG_MCS8 (1 << 27) -#define PCU_IF_FLAG_MCS9 (1 << 28) - -struct gsm_pcu_if_data { - uint8_t sapi; - uint8_t len; - uint8_t data[162]; - uint32_t fn; - uint16_t arfcn; - uint8_t trx_nr; - uint8_t ts_nr; - uint8_t block_nr; - int8_t rssi; - uint16_t ber10k; /*!< \brief BER in units of 0.01% */ - int16_t ta_offs_qbits; /* !< \brief Burst TA Offset in quarter bits */ - int16_t lqual_cb; /* !< \brief Link quality in centiBel */ -} __attribute__ ((packed)); - -/* data confirmation with direct tlli (instead of raw mac block with tlli) */ -struct gsm_pcu_if_data_cnf_dt { - uint8_t sapi; - uint32_t tlli; - uint32_t fn; - uint16_t arfcn; - uint8_t trx_nr; - uint8_t ts_nr; - uint8_t block_nr; - int8_t rssi; - uint16_t ber10k; /*!< \brief BER in units of 0.01% */ - int16_t ta_offs_qbits; /* !< \brief Burst TA Offset in quarter bits */ - int16_t lqual_cb; /* !< \brief Link quality in centiBel */ -} __attribute__ ((packed)); - -struct gsm_pcu_if_rts_req { - uint8_t sapi; - uint8_t spare[3]; - uint32_t fn; - uint16_t arfcn; - uint8_t trx_nr; - uint8_t ts_nr; - uint8_t block_nr; -} __attribute__ ((packed)); - -struct gsm_pcu_if_rach_ind { - uint8_t sapi; - uint16_t ra; - int16_t qta; - uint32_t fn; - uint16_t arfcn; - uint8_t is_11bit; - uint8_t burst_type; -} __attribute__ ((packed)); - -struct gsm_pcu_if_info_trx { - uint16_t arfcn; - uint8_t pdch_mask; /* PDCH channels per TS */ - uint8_t spare; - uint8_t tsc[8]; /* TSC per channel */ - uint32_t hlayer1; -} __attribute__ ((packed)); - -struct gsm_pcu_if_info_ind { - uint32_t version; - uint32_t flags; - struct gsm_pcu_if_info_trx trx[8]; /* TRX infos per BTS */ - uint8_t bsic; - /* RAI */ - uint16_t mcc, mnc, lac, rac; - /* NSE */ - uint16_t nsei; - uint8_t nse_timer[7]; - uint8_t cell_timer[11]; - /* cell */ - uint16_t cell_id; - uint16_t repeat_time; - uint8_t repeat_count; - uint16_t bvci; - uint8_t t3142; - uint8_t t3169; - uint8_t t3191; - uint8_t t3193_10ms; - uint8_t t3195; - uint8_t n3101; - uint8_t n3103; - uint8_t n3105; - uint8_t cv_countdown; - uint16_t dl_tbf_ext; - uint16_t ul_tbf_ext; - uint8_t initial_cs; - uint8_t initial_mcs; - /* NSVC */ - uint16_t nsvci[2]; - uint16_t local_port[2]; - uint16_t remote_port[2]; - uint32_t remote_ip[2]; -} __attribute__ ((packed)); - -struct gsm_pcu_if_act_req { - uint8_t activate; - uint8_t trx_nr; - uint8_t ts_nr; - uint8_t spare; -} __attribute__ ((packed)); - -struct gsm_pcu_if_time_ind { - uint32_t fn; -} __attribute__ ((packed)); - -struct gsm_pcu_if_pag_req { - uint8_t sapi; - uint8_t chan_needed; - uint8_t identity_lv[9]; -} __attribute__ ((packed)); - -struct gsm_pcu_if { - /* context based information */ - uint8_t msg_type; /* message type */ - uint8_t bts_nr; /* bts number */ - uint8_t spare[2]; - - union { - struct gsm_pcu_if_data data_req; - struct gsm_pcu_if_data data_cnf; - struct gsm_pcu_if_data_cnf_dt data_cnf_dt; - struct gsm_pcu_if_data data_ind; - struct gsm_pcu_if_rts_req rts_req; - struct gsm_pcu_if_rach_ind rach_ind; - struct gsm_pcu_if_info_ind info_ind; - struct gsm_pcu_if_act_req act_req; - struct gsm_pcu_if_time_ind time_ind; - struct gsm_pcu_if_pag_req pag_req; - } u; -} __attribute__ ((packed)); - -#endif /* _PCUIF_PROTO_H */ diff --git a/include/openbsc/rrlp.h b/include/openbsc/rrlp.h deleted file mode 100644 index c89402a2d..000000000 --- a/include/openbsc/rrlp.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _RRLP_H -#define _RRLP_H - -void on_dso_load_rrlp(void); - -#endif /* _RRLP_H */ - diff --git a/include/openbsc/rs232.h b/include/openbsc/rs232.h deleted file mode 100644 index 61187ca62..000000000 --- a/include/openbsc/rs232.h +++ /dev/null @@ -1,9 +0,0 @@ -#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/openbsc/rtp_proxy.h b/include/openbsc/rtp_proxy.h deleted file mode 100644 index 52ffefd27..000000000 --- a/include/openbsc/rtp_proxy.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef _RTP_PROXY_H -#define _RTP_PROXY_H - -/* RTP proxy handling for ip.access nanoBTS */ - -/* (C) 2009 by Harald Welte <laforge@gnumonks.org> - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - - -#include <netinet/in.h> - -#include <osmocom/core/linuxlist.h> -#include <osmocom/core/select.h> - -#include <openbsc/mncc.h> - -#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/openbsc/signal.h b/include/openbsc/signal.h index 49f86d612..4b6ba56f6 100644 --- a/include/openbsc/signal.h +++ b/include/openbsc/signal.h @@ -25,220 +25,12 @@ #include <stdlib.h> #include <errno.h> -#include <openbsc/gsm_data.h> - #include <osmocom/core/signal.h> -/* - * 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, diff --git a/include/openbsc/silent_call.h b/include/openbsc/silent_call.h deleted file mode 100644 index 5fec77b73..000000000 --- a/include/openbsc/silent_call.h +++ /dev/null @@ -1,15 +0,0 @@ -#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/openbsc/smpp.h b/include/openbsc/smpp.h deleted file mode 100644 index bcdac8f0b..000000000 --- a/include/openbsc/smpp.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -int smpp_openbsc_alloc_init(void *ctx); -int smpp_openbsc_start(struct gsm_network *net); diff --git a/include/openbsc/sms_queue.h b/include/openbsc/sms_queue.h deleted file mode 100644 index 2a8bd5850..000000000 --- a/include/openbsc/sms_queue.h +++ /dev/null @@ -1,17 +0,0 @@ -#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/openbsc/socket.h b/include/openbsc/socket.h deleted file mode 100644 index 0fd85f104..000000000 --- a/include/openbsc/socket.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _BSC_SOCKET_H -#define _BSC_SOCKET_H - -#include <osmocom/core/select.h> - -#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/openbsc/system_information.h b/include/openbsc/system_information.h deleted file mode 100644 index 71bea2660..000000000 --- a/include/openbsc/system_information.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _SYSTEM_INFO_H -#define _SYSTEM_INFO_H - -#include <osmocom/gsm/sysinfo.h> - -#include <openbsc/arfcn_range_encode.h> - -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/openbsc/transaction.h b/include/openbsc/transaction.h deleted file mode 100644 index 4930fbd32..000000000 --- a/include/openbsc/transaction.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef _TRANSACT_H -#define _TRANSACT_H - -#include <openbsc/gsm_data.h> -#include <openbsc/gsm_subscriber.h> -#include <osmocom/core/linuxlist.h> -#include <openbsc/gsm_04_11.h> -#include <openbsc/mncc.h> -#include <osmocom/gsm/gsm0411_smc.h> -#include <osmocom/gsm/gsm0411_smr.h> - -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/openbsc/trau_mux.h b/include/openbsc/trau_mux.h deleted file mode 100644 index 75c359b56..000000000 --- a/include/openbsc/trau_mux.h +++ /dev/null @@ -1,70 +0,0 @@ -/* Simple TRAU frame reflector to route voice calls */ - -/* (C) 2009 by Harald Welte <laforge@gnumonks.org> - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -/* 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 <stdint.h> -#include <openbsc/gsm_data.h> -#include <openbsc/mncc.h> - -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/openbsc/trau_upqueue.h b/include/openbsc/trau_upqueue.h deleted file mode 100644 index ecc765843..000000000 --- a/include/openbsc/trau_upqueue.h +++ /dev/null @@ -1,7 +0,0 @@ -#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/openbsc/ussd.h b/include/openbsc/ussd.h deleted file mode 100644 index 266546811..000000000 --- a/include/openbsc/ussd.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _USSD_H -#define _USSD_H - -/* Handler function for mobile-originated USSD messages */ - -#include <osmocom/core/msgb.h> - -int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg); - -#endif diff --git a/include/openbsc/vlr.h b/include/openbsc/vlr.h deleted file mode 100644 index 619971a52..000000000 --- a/include/openbsc/vlr.h +++ /dev/null @@ -1,422 +0,0 @@ -#pragma once - -#include <stdint.h> -#include <osmocom/core/linuxlist.h> -#include <osmocom/core/fsm.h> -#include <osmocom/core/logging.h> -#include <osmocom/gsm/protocol/gsm_23_003.h> -#include <osmocom/gsm/protocol/gsm_04_08_gprs.h> -#include <osmocom/gsm/gsm23003.h> -#include <openbsc/gsm_data.h> -// for GSM_NAME_LENGTH -#include <openbsc/gsm_subscriber.h> - -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/openbsc/vty.h b/include/openbsc/vty.h index f7056016c..d2e3d9a73 100644 --- a/include/openbsc/vty.h +++ b/include/openbsc/vty.h @@ -1,54 +1,9 @@ -#ifndef OPENBSC_VTY_H -#define OPENBSC_VTY_H +#pragma once -#include <osmocom/vty/vty.h> -#include <osmocom/vty/buffer.h> #include <osmocom/vty/command.h> -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, + GBPROXY_NODE = _LAST_OSMOVTY_NODE + 1, 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 diff --git a/osmoappdesc.py b/osmoappdesc.py index 22210d5bf..f610e77b3 100644 --- a/osmoappdesc.py +++ b/osmoappdesc.py @@ -15,38 +15,20 @@ # along with this program. If not, see <http://www.gnu.org/licenses/> -# Most systems won't be able to use these, so they're separated out -nitb_e1_configs = [ - "doc/examples/osmo-nitb/bs11/openbsc-2bts-2trx.cfg", - "doc/examples/osmo-nitb/bs11/openbsc-1bts-2trx-hopping.cfg", - "doc/examples/osmo-nitb/bs11/openbsc-1bts-2trx.cfg", - "doc/examples/osmo-nitb/bs11/openbsc.cfg", - "doc/examples/osmo-nitb/nokia/openbsc_nokia_3trx.cfg", - "doc/examples/osmo-nitb/nanobts/openbsc-multitrx.cfg", - "doc/examples/osmo-nitb/rbs2308/openbsc.cfg" -] - - app_configs = { - "osmo-bsc": ["doc/examples/osmo-bsc/osmo-bsc.cfg"], - "nat": ["doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg"], "gbproxy": ["doc/examples/osmo-gbproxy/osmo-gbproxy.cfg", "doc/examples/osmo-gbproxy/osmo-gbproxy-legacy.cfg"], "sgsn": ["doc/examples/osmo-sgsn/osmo-sgsn.cfg"], - "msc": ["doc/examples/osmo-msc/osmo-msc.cfg"], "gtphub": ["doc/examples/osmo-gtphub/osmo-gtphub-1iface.cfg"] } -apps = [(4242, "src/osmo-bsc/osmo-bsc", "OsmoBSC", "osmo-bsc"), - (4244, "src/osmo-bsc_nat/osmo-bsc_nat", "OsmoBSCNAT", "nat"), - (4246, "src/gprs/osmo-gbproxy", "OsmoGbProxy", "gbproxy"), +apps = [(4246, "src/gprs/osmo-gbproxy", "OsmoGbProxy", "gbproxy"), (4245, "src/gprs/osmo-sgsn", "OsmoSGSN", "sgsn"), - (4254, "src/osmo-msc/osmo-msc", "OsmoMSC", "msc"), (4253, "src/gprs/osmo-gtphub", "OsmoGTPhub", "gtphub") ] -vty_command = ["./src/osmo-msc/osmo-msc", "-c", - "doc/examples/osmo-msc/osmo-msc.cfg"] +vty_command = ["./src/gprs/osmo-sgsn", "-c", + "doc/examples/osmo-sgsn/osmo-sgsn.cfg"] -vty_app = apps[4] # reference apps[] entry for osmo-msc +vty_app = apps[1] diff --git a/src/Makefile.am b/src/Makefile.am index 70e53ac3e..4d1bba47a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,34 +19,7 @@ AM_LDFLAGS = \ $(COVERAGE_LDFLAGS) \ $(NULL) -# Libraries -SUBDIRS = \ - libcommon \ - libvlr \ - libbsc \ - libmsc \ - libtrau \ - libfilter \ - libcommon-cs \ - $(NULL) - # Programs -SUBDIRS += \ - osmo-msc \ - utils \ - ipaccess \ +SUBDIRS = \ gprs \ $(NULL) - -# Conditional Programs -if BUILD_NAT -SUBDIRS += \ - osmo-bsc_nat \ - $(NULL) -endif - -if BUILD_BSC -SUBDIRS += \ - osmo-bsc \ - $(NULL) -endif diff --git a/src/gprs/Makefile.am b/src/gprs/Makefile.am index 39a4c12a7..654604b80 100644 --- a/src/gprs/Makefile.am +++ b/src/gprs/Makefile.am @@ -62,7 +62,6 @@ osmo_gbproxy_SOURCES = \ gprs_utils.c \ $(NULL) osmo_gbproxy_LDADD = \ - $(top_builddir)/src/libcommon/libcommon.a \ $(OSMO_LIBS) \ $(LIBCRYPTO_LIBS) \ -lrt \ @@ -93,9 +92,10 @@ osmo_sgsn_SOURCES = \ slhc.c \ gprs_llc_xid.c \ v42bis.c \ + gsup_client.c \ + oap_client.c \ $(NULL) osmo_sgsn_LDADD = \ - $(top_builddir)/src/libcommon/libcommon.a \ $(OSMO_LIBS) \ $(LIBOSMOABIS_LIBS) \ $(LIBCARES_LIBS) \ @@ -122,7 +122,6 @@ osmo_gtphub_SOURCES = \ gprs_utils.c \ $(NULL) osmo_gtphub_LDADD = \ - $(top_builddir)/src/libcommon/libcommon.a \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(LIBOSMOVTY_LIBS) \ diff --git a/src/gprs/gb_proxy.c b/src/gprs/gb_proxy.c index cd38d23bf..d288cb314 100644 --- a/src/gprs/gb_proxy.c +++ b/src/gprs/gb_proxy.c @@ -47,12 +47,13 @@ #include <openbsc/gb_proxy.h> #include <openbsc/gprs_llc.h> -#include <openbsc/gsm_04_08.h> #include <osmocom/gsm/protocol/gsm_04_08_gprs.h> #include <openbsc/gprs_utils.h> #include <openssl/rand.h> +extern void *tall_bsc_ctx; + static const struct rate_ctr_desc global_ctr_description[] = { { "inv-bvci", "Invalid BVC Identifier " }, { "inv-lai", "Invalid Location Area Identifier" }, diff --git a/src/gprs/gb_proxy_main.c b/src/gprs/gb_proxy_main.c index caff27f6f..853a763a2 100644 --- a/src/gprs/gb_proxy_main.c +++ b/src/gprs/gb_proxy_main.c @@ -190,13 +190,39 @@ static void handle_options(int argc, char **argv) } } -extern int bsc_vty_go_parent(struct vty *vty); +int gbproxy_vty_is_config_node(struct vty *vty, int node) +{ + switch (node) { + /* add items that are not config */ + case CONFIG_NODE: + return 0; + + default: + return 1; + } +} + +int gbproxy_vty_go_parent(struct vty *vty) +{ + switch (vty->node) { + case GBPROXY_NODE: + default: + if (gbproxy_vty_is_config_node(vty, vty->node)) + vty->node = CONFIG_NODE; + else + vty->node = ENABLE_NODE; + + vty->index = NULL; + } + + return vty->node; +} static struct vty_app_info vty_info = { .name = "OsmoGbProxy", .version = PACKAGE_VERSION, - .go_parent_cb = bsc_vty_go_parent, - .is_config_node = bsc_vty_is_config_node, + .go_parent_cb = gbproxy_vty_go_parent, + .is_config_node = gbproxy_vty_is_config_node, }; /* default categories */ @@ -226,7 +252,6 @@ static const struct log_info gprs_log_info = { int main(int argc, char **argv) { - struct gsm_network dummy_network; int rc; tall_bsc_ctx = talloc_named_const(NULL, 0, "nsip_proxy"); @@ -271,7 +296,7 @@ int main(int argc, char **argv) } /* start telnet after reading config for vty_get_bind_addr() */ - rc = telnet_init_dynif(tall_bsc_ctx, &dummy_network, + rc = telnet_init_dynif(tall_bsc_ctx, NULL, vty_get_bind_addr(), OSMO_VTY_PORT_GBPROXY); if (rc < 0) exit(1); diff --git a/src/gprs/gb_proxy_patch.c b/src/gprs/gb_proxy_patch.c index 210fb2b96..bee315036 100644 --- a/src/gprs/gb_proxy_patch.c +++ b/src/gprs/gb_proxy_patch.c @@ -23,13 +23,14 @@ #include <openbsc/gprs_utils.h> #include <openbsc/gprs_gb_parse.h> -#include <openbsc/gsm_data.h> #include <openbsc/debug.h> #include <osmocom/gprs/protocol/gsm_08_18.h> #include <osmocom/core/rate_ctr.h> #include <osmocom/gsm/apn.h> +extern void *tall_bsc_ctx; + /* patch RA identifier in place */ static void gbproxy_patch_raid(uint8_t *raid_enc, struct gbproxy_peer *peer, int to_bss, const char *log_text) diff --git a/src/gprs/gb_proxy_peer.c b/src/gprs/gb_proxy_peer.c index 890968717..a83630bc1 100644 --- a/src/gprs/gb_proxy_peer.c +++ b/src/gprs/gb_proxy_peer.c @@ -22,17 +22,18 @@ #include <openbsc/gb_proxy.h> -#include <openbsc/gsm_data.h> -#include <openbsc/gsm_data_shared.h> #include <openbsc/debug.h> #include <osmocom/gprs/protocol/gsm_08_18.h> #include <osmocom/core/rate_ctr.h> #include <osmocom/core/stats.h> #include <osmocom/core/talloc.h> +#include <osmocom/gsm/tlv.h> #include <string.h> +extern void *tall_bsc_ctx; + static const struct rate_ctr_desc peer_ctr_description[] = { { "blocked", "BVC Block " }, { "unblocked", "BVC Unblock " }, diff --git a/src/gprs/gb_proxy_vty.c b/src/gprs/gb_proxy_vty.c index 86d65a8e3..bd5bb1b5b 100644 --- a/src/gprs/gb_proxy_vty.c +++ b/src/gprs/gb_proxy_vty.c @@ -26,8 +26,8 @@ #include <osmocom/core/talloc.h> #include <osmocom/core/rate_ctr.h> +#include <osmocom/gsm/gsm48.h> -#include <openbsc/gsm_04_08.h> #include <osmocom/gprs/gprs_ns.h> #include <osmocom/gsm/apn.h> diff --git a/src/gprs/gprs_gmm.c b/src/gprs/gprs_gmm.c index 032137f0b..7301bf1c2 100644 --- a/src/gprs/gprs_gmm.c +++ b/src/gprs/gprs_gmm.c @@ -35,7 +35,6 @@ #include "bscconfig.h" -#include <openbsc/db.h> #include <osmocom/core/msgb.h> #include <osmocom/gsm/tlv.h> #include <osmocom/gsm/gsm_utils.h> @@ -56,11 +55,6 @@ #endif #include <openbsc/debug.h> -#include <openbsc/gsm_data.h> -#include <openbsc/gsm_subscriber.h> -#include <openbsc/gsm_04_08.h> -#include <openbsc/paging.h> -#include <openbsc/transaction.h> #include <openbsc/gprs_llc.h> #include <openbsc/gprs_sgsn.h> #include <openbsc/gprs_gmm.h> @@ -75,6 +69,7 @@ #define PTMSI_ALLOC extern struct sgsn_instance *sgsn; +extern void *tall_bsc_ctx; static const struct tlv_definition gsm48_gmm_att_tlvdef = { .def = { diff --git a/src/gprs/gprs_llc.c b/src/gprs/gprs_llc.c index 2be663f98..904ec7e07 100644 --- a/src/gprs/gprs_llc.c +++ b/src/gprs/gprs_llc.c @@ -31,15 +31,14 @@ #include <osmocom/core/talloc.h> #include <osmocom/core/rate_ctr.h> #include <osmocom/gprs/gprs_bssgp.h> +#include <osmocom/gsm/gsm_utils.h> -#include <openbsc/gsm_data.h> #include <openbsc/debug.h> #include <openbsc/gprs_sgsn.h> #include <openbsc/gprs_gmm.h> #include <openbsc/gprs_llc.h> #include <openbsc/crc24.h> #include <openbsc/sgsn.h> -#include <openbsc/gsm_subscriber.h> #include <openbsc/gprs_llc_xid.h> #include <openbsc/gprs_sndcp_comp.h> #include <openbsc/gprs_sndcp.h> diff --git a/src/gprs/gprs_llc_parse.c b/src/gprs/gprs_llc_parse.c index a5a7a7122..be634974a 100644 --- a/src/gprs/gprs_llc_parse.c +++ b/src/gprs/gprs_llc_parse.c @@ -28,7 +28,6 @@ #include <osmocom/core/talloc.h> #include <osmocom/gprs/gprs_bssgp.h> -#include <openbsc/gsm_data.h> #include <openbsc/debug.h> #include <openbsc/gprs_sgsn.h> #include <openbsc/gprs_gmm.h> diff --git a/src/gprs/gprs_llc_vty.c b/src/gprs/gprs_llc_vty.c index bf34e9782..626d6ef1b 100644 --- a/src/gprs/gprs_llc_vty.c +++ b/src/gprs/gprs_llc_vty.c @@ -27,7 +27,6 @@ #include <arpa/inet.h> -#include <openbsc/gsm_data.h> #include <osmocom/core/msgb.h> #include <osmocom/gsm/tlv.h> #include <osmocom/core/talloc.h> diff --git a/src/gprs/gprs_sgsn.c b/src/gprs/gprs_sgsn.c index de79afb1a..560485de5 100644 --- a/src/gprs/gprs_sgsn.c +++ b/src/gprs/gprs_sgsn.c @@ -31,6 +31,7 @@ #include <osmocom/gprs/gprs_bssgp.h> #include <osmocom/gsm/protocol/gsm_04_08_gprs.h> #include <osmocom/gsm/apn.h> +#include <osmocom/gsm/gsm_utils.h> #include <openbsc/gprs_subscriber.h> #include <openbsc/debug.h> @@ -56,6 +57,7 @@ #define GPRS_LLME_CHECK_TICK 30 extern struct sgsn_instance *sgsn; +extern void *tall_bsc_ctx; LLIST_HEAD(sgsn_mm_ctxts); LLIST_HEAD(sgsn_ggsn_ctxts); diff --git a/src/gprs/gprs_sndcp.c b/src/gprs/gprs_sndcp.c index a18998f9e..05dad6603 100644 --- a/src/gprs/gprs_sndcp.c +++ b/src/gprs/gprs_sndcp.c @@ -30,7 +30,6 @@ #include <osmocom/core/talloc.h> #include <osmocom/gprs/gprs_bssgp.h> -#include <openbsc/gsm_data.h> #include <openbsc/debug.h> #include <openbsc/gprs_llc.h> #include <openbsc/sgsn.h> diff --git a/src/gprs/gprs_sndcp_vty.c b/src/gprs/gprs_sndcp_vty.c index 430881fc8..4bad8b040 100644 --- a/src/gprs/gprs_sndcp_vty.c +++ b/src/gprs/gprs_sndcp_vty.c @@ -26,7 +26,6 @@ #include <arpa/inet.h> -#include <openbsc/gsm_data.h> #include <osmocom/core/msgb.h> #include <osmocom/gsm/tlv.h> #include <osmocom/core/talloc.h> diff --git a/src/gprs/gsup_client.c b/src/gprs/gsup_client.c new file mode 100644 index 000000000..258f230cb --- /dev/null +++ b/src/gprs/gsup_client.c @@ -0,0 +1,355 @@ +/* Generic Subscriber Update Protocol client */ + +/* (C) 2014-2016 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Jacob Erlbeck + * 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 <http://www.gnu.org/licenses/>. + * + */ + +#include <openbsc/gsup_client.h> + +#include <osmocom/abis/ipa.h> +#include <osmocom/gsm/protocol/ipaccess.h> +#include <osmocom/core/msgb.h> +#include <osmocom/core/logging.h> + +#include <openbsc/debug.h> + +#include <errno.h> +#include <string.h> + +extern void *tall_bsc_ctx; + +static void start_test_procedure(struct gsup_client *gsupc); + +static void gsup_client_send_ping(struct gsup_client *gsupc) +{ + struct msgb *msg = gsup_client_msgb_alloc(); + + msg->l2h = msgb_put(msg, 1); + msg->l2h[0] = IPAC_MSGT_PING; + ipa_msg_push_header(msg, IPAC_PROTO_IPACCESS); + ipa_client_conn_send(gsupc->link, msg); +} + +static int gsup_client_connect(struct gsup_client *gsupc) +{ + int rc; + + if (gsupc->is_connected) + return 0; + + if (osmo_timer_pending(&gsupc->connect_timer)) { + LOGP(DLGSUP, LOGL_DEBUG, + "GSUP connect: connect timer already running\n"); + osmo_timer_del(&gsupc->connect_timer); + } + + if (osmo_timer_pending(&gsupc->ping_timer)) { + LOGP(DLGSUP, LOGL_DEBUG, + "GSUP connect: ping timer already running\n"); + osmo_timer_del(&gsupc->ping_timer); + } + + if (ipa_client_conn_clear_queue(gsupc->link) > 0) + LOGP(DLGSUP, LOGL_DEBUG, "GSUP connect: discarded stored messages\n"); + + rc = ipa_client_conn_open(gsupc->link); + + if (rc >= 0) { + LOGP(DLGSUP, LOGL_NOTICE, "GSUP connecting to %s:%d\n", + gsupc->link->addr, gsupc->link->port); + return 0; + } + + LOGP(DLGSUP, LOGL_ERROR, "GSUP failed to connect to %s:%d: %s\n", + gsupc->link->addr, gsupc->link->port, strerror(-rc)); + + if (rc == -EBADF || rc == -ENOTSOCK || rc == -EAFNOSUPPORT || + rc == -EINVAL) + return rc; + + osmo_timer_schedule(&gsupc->connect_timer, + GSUP_CLIENT_RECONNECT_INTERVAL, 0); + + LOGP(DLGSUP, LOGL_INFO, "Scheduled timer to retry GSUP connect to %s:%d\n", + gsupc->link->addr, gsupc->link->port); + + return 0; +} + +static void connect_timer_cb(void *gsupc_) +{ + struct gsup_client *gsupc = gsupc_; + + if (gsupc->is_connected) + return; + + gsup_client_connect(gsupc); +} + +static void client_send(struct gsup_client *gsupc, int proto_ext, + struct msgb *msg_tx) +{ + ipa_prepend_header_ext(msg_tx, proto_ext); + ipa_msg_push_header(msg_tx, IPAC_PROTO_OSMO); + ipa_client_conn_send(gsupc->link, msg_tx); + /* msg_tx is now queued and will be freed. */ +} + +static void gsup_client_oap_register(struct gsup_client *gsupc) +{ + struct msgb *msg_tx; + int rc; + rc = oap_client_register(&gsupc->oap_state, &msg_tx); + + if ((rc < 0) || (!msg_tx)) { + LOGP(DLGSUP, LOGL_ERROR, "GSUP OAP set up, but cannot register.\n"); + return; + } + + client_send(gsupc, IPAC_PROTO_EXT_OAP, msg_tx); +} + +static void gsup_client_updown_cb(struct ipa_client_conn *link, int up) +{ + struct gsup_client *gsupc = link->data; + + LOGP(DLGSUP, LOGL_INFO, "GSUP link to %s:%d %s\n", + link->addr, link->port, up ? "UP" : "DOWN"); + + gsupc->is_connected = up; + + if (up) { + start_test_procedure(gsupc); + + if (gsupc->oap_state.state == OAP_INITIALIZED) + gsup_client_oap_register(gsupc); + + osmo_timer_del(&gsupc->connect_timer); + } else { + osmo_timer_del(&gsupc->ping_timer); + + osmo_timer_schedule(&gsupc->connect_timer, + GSUP_CLIENT_RECONNECT_INTERVAL, 0); + } +} + +static int gsup_client_oap_handle(struct gsup_client *gsupc, struct msgb *msg_rx) +{ + int rc; + struct msgb *msg_tx; + + /* If the oap_state is disabled, this will reject the messages. */ + rc = oap_client_handle(&gsupc->oap_state, msg_rx, &msg_tx); + msgb_free(msg_rx); + if (rc < 0) + return rc; + + if (msg_tx) + client_send(gsupc, IPAC_PROTO_EXT_OAP, msg_tx); + + return 0; +} + +static int gsup_client_read_cb(struct ipa_client_conn *link, struct msgb *msg) +{ + struct ipaccess_head *hh = (struct ipaccess_head *) msg->data; + struct ipaccess_head_ext *he = (struct ipaccess_head_ext *) msgb_l2(msg); + struct gsup_client *gsupc = (struct gsup_client *)link->data; + int rc; + struct ipaccess_unit ipa_dev = { + /* see gsup_client_create() on const vs non-const */ + .unit_name = (char*)gsupc->unit_name, + }; + + OSMO_ASSERT(ipa_dev.unit_name); + + msg->l2h = &hh->data[0]; + + rc = ipaccess_bts_handle_ccm(link, &ipa_dev, msg); + + if (rc < 0) { + LOGP(DLGSUP, LOGL_NOTICE, + "GSUP received an invalid IPA/CCM message from %s:%d\n", + link->addr, link->port); + /* Link has been closed */ + gsupc->is_connected = 0; + msgb_free(msg); + return -1; + } + + if (rc == 1) { + uint8_t msg_type = *(msg->l2h); + /* CCM message */ + if (msg_type == IPAC_MSGT_PONG) { + LOGP(DLGSUP, LOGL_DEBUG, "GSUP receiving PONG\n"); + gsupc->got_ipa_pong = 1; + } + + msgb_free(msg); + return 0; + } + + if (hh->proto != IPAC_PROTO_OSMO) + goto invalid; + + if (!he || msgb_l2len(msg) < sizeof(*he)) + goto invalid; + + msg->l2h = &he->data[0]; + + if (he->proto == IPAC_PROTO_EXT_GSUP) { + OSMO_ASSERT(gsupc->read_cb != NULL); + gsupc->read_cb(gsupc, msg); + /* expecting read_cb() to free msg */ + } else if (he->proto == IPAC_PROTO_EXT_OAP) { + return gsup_client_oap_handle(gsupc, msg); + /* gsup_client_oap_handle frees msg */ + } else + goto invalid; + + return 0; + +invalid: + LOGP(DLGSUP, LOGL_NOTICE, + "GSUP received an invalid IPA message from %s:%d, size = %d\n", + link->addr, link->port, msgb_length(msg)); + + msgb_free(msg); + return -1; +} + +static void ping_timer_cb(void *gsupc_) +{ + struct gsup_client *gsupc = gsupc_; + + LOGP(DLGSUP, LOGL_INFO, "GSUP ping callback (%s, %s PONG)\n", + gsupc->is_connected ? "connected" : "not connected", + gsupc->got_ipa_pong ? "got" : "didn't get"); + + if (gsupc->got_ipa_pong) { + start_test_procedure(gsupc); + return; + } + + LOGP(DLGSUP, LOGL_NOTICE, "GSUP ping timed out, reconnecting\n"); + ipa_client_conn_close(gsupc->link); + gsupc->is_connected = 0; + + gsup_client_connect(gsupc); +} + +static void start_test_procedure(struct gsup_client *gsupc) +{ + osmo_timer_setup(&gsupc->ping_timer, ping_timer_cb, gsupc); + + gsupc->got_ipa_pong = 0; + osmo_timer_schedule(&gsupc->ping_timer, GSUP_CLIENT_PING_INTERVAL, 0); + LOGP(DLGSUP, LOGL_DEBUG, "GSUP sending PING\n"); + gsup_client_send_ping(gsupc); +} + +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) +{ + struct gsup_client *gsupc; + int rc; + + gsupc = talloc_zero(tall_bsc_ctx, struct gsup_client); + OSMO_ASSERT(gsupc); + + /* struct ipaccess_unit has a non-const unit_name, so let's copy to be + * able to have a non-const unit_name here as well. To not taint the + * public gsup_client API, let's store it in a const char* anyway. */ + gsupc->unit_name = talloc_strdup(gsupc, unit_name); + OSMO_ASSERT(gsupc->unit_name); + + /* a NULL oapc_config will mark oap_state disabled. */ + rc = oap_client_init(oapc_config, &gsupc->oap_state); + if (rc != 0) + goto failed; + + gsupc->link = ipa_client_conn_create(gsupc, + /* no e1inp */ NULL, + 0, + ip_addr, tcp_port, + gsup_client_updown_cb, + gsup_client_read_cb, + /* default write_cb */ NULL, + gsupc); + if (!gsupc->link) + goto failed; + + osmo_timer_setup(&gsupc->connect_timer, connect_timer_cb, gsupc); + + rc = gsup_client_connect(gsupc); + + if (rc < 0) + goto failed; + + gsupc->read_cb = read_cb; + + return gsupc; + +failed: + gsup_client_destroy(gsupc); + return NULL; +} + +void gsup_client_destroy(struct gsup_client *gsupc) +{ + osmo_timer_del(&gsupc->connect_timer); + osmo_timer_del(&gsupc->ping_timer); + + if (gsupc->link) { + ipa_client_conn_close(gsupc->link); + ipa_client_conn_destroy(gsupc->link); + gsupc->link = NULL; + } + talloc_free(gsupc); +} + +int gsup_client_send(struct gsup_client *gsupc, struct msgb *msg) +{ + if (!gsupc) { + LOGP(DGPRS, LOGL_NOTICE, "No GSUP client, unable to " + "send %s\n", msgb_hexdump(msg)); + msgb_free(msg); + return -ENOTCONN; + } + + if (!gsupc->is_connected) { + LOGP(DGPRS, LOGL_NOTICE, "GSUP not connected, unable to " + "send %s\n", msgb_hexdump(msg)); + msgb_free(msg); + return -EAGAIN; + } + + client_send(gsupc, IPAC_PROTO_EXT_GSUP, msg); + + return 0; +} + +struct msgb *gsup_client_msgb_alloc(void) +{ + return msgb_alloc_headroom(4000, 64, __func__); +} diff --git a/src/gprs/gtphub_main.c b/src/gprs/gtphub_main.c index 2b87d19ef..d7b3ba74b 100644 --- a/src/gprs/gtphub_main.c +++ b/src/gprs/gtphub_main.c @@ -39,6 +39,8 @@ #include <osmocom/vty/telnet_interface.h> #include <osmocom/vty/ports.h> +#include <osmocom/sigtran/osmo_ss7.h> + #include <openbsc/debug.h> #include <openbsc/gtphub.h> #include <openbsc/vty.h> @@ -46,7 +48,7 @@ #include "../../bscconfig.h" extern void *osmo_gtphub_ctx; - +void *tall_bsc_ctx; const char *gtphub_copyright = "Copyright (C) 2015 sysmocom s.f.m.c GmbH <info@sysmocom.de>\r\n" @@ -113,13 +115,38 @@ static void signal_handler(int signal) } } -extern int bsc_vty_go_parent(struct vty *vty); +int gtphub_vty_go_parent(struct vty *vty) +{ + switch (vty->node) { + default: + osmo_ss7_vty_go_parent(vty); + } + + return vty->node; +} + +int gtphub_vty_is_config_node(struct vty *vty, int node) +{ + /* Check if libosmo-sccp declares the node in + * question as config node */ + if (osmo_ss7_is_config_node(vty, node)) + return 1; + + switch (node) { + /* add items that are not config */ + case CONFIG_NODE: + return 0; + + default: + return 1; + } +} static struct vty_app_info vty_info = { .name = "OsmoGTPhub", .version = PACKAGE_VERSION, - .go_parent_cb = bsc_vty_go_parent, - .is_config_node = bsc_vty_is_config_node, + .go_parent_cb = gtphub_vty_go_parent, + .is_config_node = gtphub_vty_is_config_node, }; struct cmdline_cfg { diff --git a/src/gprs/gtphub_vty.c b/src/gprs/gtphub_vty.c index a30ad2a54..d611b1f9a 100644 --- a/src/gprs/gtphub_vty.c +++ b/src/gprs/gtphub_vty.c @@ -37,6 +37,7 @@ * globals. */ #include <openbsc/sgsn.h> extern struct sgsn_instance *sgsn; +extern void *tall_bsc_ctx; static struct gtphub *g_hub = 0; static struct gtphub_cfg *g_cfg = 0; diff --git a/src/gprs/oap_client.c b/src/gprs/oap_client.c new file mode 100644 index 000000000..5128ac119 --- /dev/null +++ b/src/gprs/oap_client.c @@ -0,0 +1,280 @@ +/* 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 <http://www.gnu.org/licenses/>. + * + */ + +#include <string.h> +#include <errno.h> + +#include <osmocom/core/utils.h> +#include <osmocom/crypt/auth.h> +#include <osmocom/gsm/oap.h> + +#include <openbsc/oap_client.h> +#include <openbsc/debug.h> + +int oap_client_init(struct oap_client_config *config, + struct oap_client_state *state) +{ + OSMO_ASSERT(state->state == OAP_UNINITIALIZED); + + if (!config) + goto disable; + + if (config->client_id == 0) + goto disable; + + if (config->secret_k_present == 0) { + LOGP(DLOAP, LOGL_NOTICE, "OAP: client ID set, but secret K missing.\n"); + goto disable; + } + + if (config->secret_opc_present == 0) { + LOGP(DLOAP, LOGL_NOTICE, "OAP: client ID set, but secret OPC missing.\n"); + goto disable; + } + + state->client_id = config->client_id; + memcpy(state->secret_k, config->secret_k, sizeof(state->secret_k)); + memcpy(state->secret_opc, config->secret_opc, sizeof(state->secret_opc)); + state->state = OAP_INITIALIZED; + return 0; + +disable: + state->state = OAP_DISABLED; + return 0; +} + +/* From the given state and received RAND and AUTN octets, validate the + * server's authenticity and formulate the matching milenage reply octets in + * *tx_xres. The state is not modified. + * On success, and if tx_res is not NULL, exactly 8 octets will be written to + * *tx_res. If not NULL, tx_res must point at allocated memory of at least 8 + * octets. The caller will want to send XRES back to the server in a challenge + * response message and update the state. + * Return 0 on success; -1 if OAP is disabled; -2 if rx_random and rx_autn fail + * the authentication check; -3 for any other errors. */ +static int oap_evaluate_challenge(const struct oap_client_state *state, + const uint8_t *rx_random, + const uint8_t *rx_autn, + uint8_t *tx_xres) +{ + struct osmo_auth_vector vec; + + struct osmo_sub_auth_data auth = { + .type = OSMO_AUTH_TYPE_UMTS, + .algo = OSMO_AUTH_ALG_MILENAGE, + }; + + osmo_static_assert(sizeof(((struct osmo_sub_auth_data*)0)->u.umts.k) + == sizeof(state->secret_k), _secret_k_size_match); + osmo_static_assert(sizeof(((struct osmo_sub_auth_data*)0)->u.umts.opc) + == sizeof(state->secret_opc), _secret_opc_size_match); + + switch (state->state) { + case OAP_UNINITIALIZED: + case OAP_DISABLED: + return -1; + default: + break; + } + + memcpy(auth.u.umts.k, state->secret_k, sizeof(auth.u.umts.k)); + memcpy(auth.u.umts.opc, state->secret_opc, sizeof(auth.u.umts.opc)); + memset(auth.u.umts.amf, '\0', sizeof(auth.u.umts.amf)); + auth.u.umts.sqn = 41; /* TODO use incrementing sequence nr */ + + memset(&vec, 0, sizeof(vec)); + osmo_auth_gen_vec(&vec, &auth, rx_random); + + if (vec.res_len != 8) { + LOGP(DLOAP, LOGL_ERROR, "OAP: Expected XRES to be 8 octets, got %d\n", + vec.res_len); + return -3; + } + + if (osmo_constant_time_cmp(vec.autn, rx_autn, sizeof(vec.autn)) != 0) { + LOGP(DLOAP, LOGL_ERROR, "OAP: AUTN mismatch!\n"); + LOGP(DLOAP, LOGL_INFO, "OAP: AUTN from server: %s\n", + osmo_hexdump_nospc(rx_autn, sizeof(vec.autn))); + LOGP(DLOAP, LOGL_INFO, "OAP: AUTN expected: %s\n", + osmo_hexdump_nospc(vec.autn, sizeof(vec.autn))); + return -2; + } + + if (tx_xres != NULL) + memcpy(tx_xres, vec.res, 8); + return 0; +} + +struct msgb *oap_client_encoded(const struct osmo_oap_message *oap_msg) +{ + struct msgb *msg = msgb_alloc_headroom(1000, 64, __func__); + OSMO_ASSERT(msg); + osmo_oap_encode(msg, oap_msg); + return msg; +} + +/* Create a new msgb containing an OAP registration message. + * On error, return NULL. */ +static struct msgb* oap_msg_register(uint16_t client_id) +{ + struct osmo_oap_message oap_msg = {0}; + + if (client_id < 1) { + LOGP(DLOAP, LOGL_ERROR, "OAP: Invalid client ID: %d\n", client_id); + return NULL; + } + + oap_msg.message_type = OAP_MSGT_REGISTER_REQUEST; + oap_msg.client_id = client_id; + return oap_client_encoded(&oap_msg); +} + +int oap_client_register(struct oap_client_state *state, struct msgb **msg_tx) +{ + *msg_tx = oap_msg_register(state->client_id); + if (!(*msg_tx)) + return -1; + + state->state = OAP_REQUESTED_CHALLENGE; + return 0; +} + +/* Create a new msgb containing an OAP challenge response message. + * xres must point at 8 octets to return as challenge response. + * On error, return NULL. */ +static struct msgb* oap_msg_challenge_response(uint8_t *xres) +{ + struct osmo_oap_message oap_reply = {0}; + + oap_reply.message_type = OAP_MSGT_CHALLENGE_RESULT; + memcpy(oap_reply.xres, xres, sizeof(oap_reply.xres)); + oap_reply.xres_present = 1; + return oap_client_encoded(&oap_reply); +} + +static int handle_challenge(struct oap_client_state *state, + struct osmo_oap_message *oap_rx, + struct msgb **msg_tx) +{ + int rc; + uint8_t xres[8]; + + if (!(oap_rx->rand_present && oap_rx->autn_present)) { + LOGP(DLOAP, LOGL_ERROR, + "OAP challenge incomplete (rand_present: %d, autn_present: %d)\n", + oap_rx->rand_present, oap_rx->autn_present); + rc = -2; + goto failure; + } + + rc = oap_evaluate_challenge(state, + oap_rx->rand, + oap_rx->autn, + xres); + if (rc < 0) + goto failure; + + *msg_tx = oap_msg_challenge_response(xres); + if ((*msg_tx) == NULL) { + rc = -1; + goto failure; + } + + state->state = OAP_SENT_CHALLENGE_RESULT; + return 0; + +failure: + OSMO_ASSERT(rc < 0); + state->state = OAP_INITIALIZED; + return rc; +} + +int oap_client_handle(struct oap_client_state *state, + const struct msgb *msg_rx, struct msgb **msg_tx) +{ + uint8_t *data = msgb_l2(msg_rx); + size_t data_len = msgb_l2len(msg_rx); + struct osmo_oap_message oap_msg = {0}; + int rc = 0; + + *msg_tx = NULL; + + OSMO_ASSERT(data); + + rc = osmo_oap_decode(&oap_msg, data, data_len); + if (rc < 0) { + LOGP(DLOAP, LOGL_ERROR, + "Decoding OAP message failed with error '%s' (%d)\n", + get_value_string(gsm48_gmm_cause_names, -rc), -rc); + return -10; + } + + switch (state->state) { + case OAP_UNINITIALIZED: + LOGP(DLOAP, LOGL_ERROR, + "Received OAP message %d, but the OAP client is" + " not initialized\n", oap_msg.message_type); + return -ENOTCONN; + case OAP_DISABLED: + LOGP(DLOAP, LOGL_ERROR, + "Received OAP message %d, but the OAP client is" + " disabled\n", oap_msg.message_type); + return -ENOTCONN; + default: + break; + } + + switch (oap_msg.message_type) { + case OAP_MSGT_CHALLENGE_REQUEST: + return handle_challenge(state, &oap_msg, msg_tx); + + case OAP_MSGT_REGISTER_RESULT: + /* successfully registered */ + state->state = OAP_REGISTERED; + break; + + case OAP_MSGT_REGISTER_ERROR: + LOGP(DLOAP, LOGL_ERROR, + "OAP registration failed\n"); + state->state = OAP_INITIALIZED; + if (state->registration_failures < 3) { + state->registration_failures ++; + return oap_client_register(state, msg_tx); + } + return -11; + + case OAP_MSGT_REGISTER_REQUEST: + case OAP_MSGT_CHALLENGE_RESULT: + LOGP(DLOAP, LOGL_ERROR, + "Received invalid OAP message type for OAP client side: %d\n", + (int)oap_msg.message_type); + return -12; + + default: + LOGP(DLOAP, LOGL_ERROR, + "Unknown OAP message type: %d\n", + (int)oap_msg.message_type); + return -13; + } + + return 0; +} diff --git a/src/gprs/sgsn_ares.c b/src/gprs/sgsn_ares.c index d94d184a3..623809911 100644 --- a/src/gprs/sgsn_ares.c +++ b/src/gprs/sgsn_ares.c @@ -24,6 +24,8 @@ #include <netdb.h> +extern void *tall_bsc_ctx; + struct cares_event_fd { struct llist_head head; struct osmo_fd fd; diff --git a/src/gprs/sgsn_ctrl.c b/src/gprs/sgsn_ctrl.c index 31ac74f1f..f7b1180be 100644 --- a/src/gprs/sgsn_ctrl.c +++ b/src/gprs/sgsn_ctrl.c @@ -21,7 +21,6 @@ #include <osmocom/ctrl/control_if.h> #include <osmocom/ctrl/control_cmd.h> -#include <openbsc/gsm_data.h> #include <openbsc/gprs_sgsn.h> #include <openbsc/sgsn.h> #include <openbsc/debug.h> diff --git a/src/gprs/sgsn_main.c b/src/gprs/sgsn_main.c index 25ee632cc..e24a57ba2 100644 --- a/src/gprs/sgsn_main.c +++ b/src/gprs/sgsn_main.c @@ -62,13 +62,13 @@ #include <osmocom/ctrl/control_if.h> #include <osmocom/ctrl/ports.h> -#include <osmocom/sigtran/protocol/m3ua.h> - #include <gtp.h> #include "../../bscconfig.h" #if BUILD_IU +#include <osmocom/sigtran/osmo_ss7.h> +#include <osmocom/sigtran/protocol/m3ua.h> #include <osmocom/ranap/iu_client.h> #endif @@ -173,13 +173,40 @@ static void signal_handler(int signal) /* NSI that BSSGP uses when transmitting on NS */ extern struct gprs_ns_inst *bssgp_nsi; -extern int bsc_vty_go_parent(struct vty *vty); +int sgsn_vty_is_config_node(struct vty *vty, int node) +{ + /* So far the SGSN has no nested nodes that need parent node + * declaration, except for the ss7 vty nodes. */ + switch (node) { + case SGSN_NODE: + return 1; + default: +#if BUILD_IU + return osmo_ss7_is_config_node(vty, node); +#else + return 0; +#endif + } +} + +int sgsn_vty_go_parent(struct vty *vty) +{ + /* So far the SGSN has no nested nodes that need parent node + * declaration, except for the ss7 vty nodes. */ +#if BUILD_IU + return osmo_ss7_vty_go_parent(vty); +#else + vty->node = CONFIG_NODE; + vty->index = NULL; + return 0; +#endif +} static struct vty_app_info vty_info = { .name = "OsmoSGSN", .version = PACKAGE_VERSION, - .go_parent_cb = bsc_vty_go_parent, - .is_config_node = bsc_vty_is_config_node, + .go_parent_cb = sgsn_vty_go_parent, + .is_config_node = sgsn_vty_is_config_node, }; static void print_help(void) @@ -325,14 +352,17 @@ static const struct log_info gprs_log_info = { .num_cat = ARRAY_SIZE(gprs_categories), }; -int sgsn_ranap_iu_event(struct ue_conn_ctx *ctx, enum ranap_iu_event_type type, void *data); +#if BUILD_IU +int sgsn_ranap_iu_event(struct ranap_ue_conn_ctx *ctx, enum ranap_iu_event_type type, void *data); +#endif int main(int argc, char **argv) { struct ctrl_handle *ctrl; - struct gsm_network dummy_network; - struct osmo_sccp_instance *sccp; int rc; +#if BUILD_IU + struct osmo_sccp_instance *sccp; +#endif srand(time(NULL)); tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn"); @@ -354,7 +384,11 @@ int main(int argc, char **argv) osmo_stats_vty_add_cmds(&gprs_log_info); sgsn_vty_init(&sgsn_inst.cfg); ctrl_vty_init(tall_bsc_ctx); + +#if BUILD_IU osmo_ss7_init(); + osmo_ss7_vty_init_asp(tall_bsc_ctx); +#endif handle_options(argc, argv); @@ -389,7 +423,7 @@ int main(int argc, char **argv) } /* start telnet after reading config for vty_get_bind_addr() */ - rc = telnet_init_dynif(tall_bsc_ctx, &dummy_network, + rc = telnet_init_dynif(tall_bsc_ctx, NULL, vty_get_bind_addr(), OSMO_VTY_PORT_SGSN); if (rc < 0) exit(1); @@ -442,7 +476,7 @@ int main(int argc, char **argv) } } -#ifdef BUILD_IU +#if BUILD_IU sccp = osmo_sccp_simple_client(tall_bsc_ctx, "OsmoSGSN", 2 /* FIXME: configurable */, OSMO_SS7_ASP_PROT_M3UA, 0, diff --git a/src/gprs/sgsn_vty.c b/src/gprs/sgsn_vty.c index 3a5b2ca64..fce251885 100644 --- a/src/gprs/sgsn_vty.c +++ b/src/gprs/sgsn_vty.c @@ -51,6 +51,8 @@ #include <osmocom/ranap/iu_client.h> #endif +extern void *tall_bsc_ctx; + static struct sgsn_config *g_cfg = NULL; const struct value_string sgsn_auth_pol_strs[] = { diff --git a/src/ipaccess/Makefile.am b/src/ipaccess/Makefile.am deleted file mode 100644 index 4dfe24738..000000000 --- a/src/ipaccess/Makefile.am +++ /dev/null @@ -1,66 +0,0 @@ -AM_CPPFLAGS = \ - $(all_includes) \ - -I$(top_srcdir)/include \ - -I$(top_builddir) \ - $(NULL) - -AM_CFLAGS = \ - -Wall \ - $(LIBOSMOCORE_CFLAGS) \ - $(LIBOSMOGSM_CFLAGS) \ - $(LIBOSMOABIS_CFLAGS) \ - $(COVERAGE_CFLAGS) \ - $(NULL) - -AM_LDFLAGS = \ - $(COVERAGE_LDFLAGS) \ - $(NULL) - -OSMO_LIBS = \ - $(LIBOSMOCORE_LIBS) \ - $(LIBOSMOGSM_LIBS) \ - $(LIBOSMOABIS_LIBS) \ - $(NULL) - -bin_PROGRAMS = \ - abisip-find \ - ipaccess-config \ - ipaccess-proxy \ - $(NULL) - -abisip_find_LDADD = \ - $(top_builddir)/src/libbsc/libbsc.a \ - $(top_builddir)/src/libtrau/libtrau.a \ - $(top_builddir)/src/libcommon/libcommon.a \ - $(OSMO_LIBS) \ - $(NULL) - -abisip_find_SOURCES = \ - abisip-find.c \ - $(NULL) - -ipaccess_config_SOURCES = \ - ipaccess-config.c \ - ipaccess-firmware.c \ - network_listen.c \ - $(NULL) - -# FIXME: resolve the bogus dependencies patched around here: -ipaccess_config_LDADD = \ - $(top_builddir)/src/libbsc/libbsc.a \ - $(top_builddir)/src/libcommon-cs/libcommon-cs.a \ - $(top_builddir)/src/libtrau/libtrau.a \ - $(top_builddir)/src/libcommon/libcommon.a \ - $(OSMO_LIBS) \ - $(NULL) - -ipaccess_proxy_SOURCES = \ - ipaccess-proxy.c \ - $(NULL) - -ipaccess_proxy_LDADD = \ - $(top_builddir)/src/libbsc/libbsc.a \ - $(top_builddir)/src/libtrau/libtrau.a \ - $(top_builddir)/src/libcommon/libcommon.a \ - $(OSMO_LIBS) \ - $(NULL) diff --git a/src/ipaccess/abisip-find.c b/src/ipaccess/abisip-find.c deleted file mode 100644 index 21d9f2290..000000000 --- a/src/ipaccess/abisip-find.c +++ /dev/null @@ -1,216 +0,0 @@ -/* ip.access nanoBTS configuration tool */ - -/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org> - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - - -#include <osmocom/core/select.h> -#include <osmocom/core/timer.h> -#include <osmocom/gsm/protocol/ipaccess.h> -#include <osmocom/gsm/ipa.h> -#include <openbsc/gsm_data.h> - -static int udp_sock(const char *ifname) -{ - int fd, rc, bc = 1; - struct sockaddr_in sa; - - fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (fd < 0) - return fd; - - if (ifname) { -#ifdef __FreeBSD__ - rc = setsockopt(fd, SOL_SOCKET, IP_RECVIF, ifname, - strlen(ifname)); -#else - rc = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname, - strlen(ifname)); -#endif - if (rc < 0) - goto err; - } - - memset(&sa, 0, sizeof(sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons(3006); - sa.sin_addr.s_addr = INADDR_ANY; - - rc = bind(fd, (struct sockaddr *)&sa, sizeof(sa)); - if (rc < 0) - goto err; - - rc = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &bc, sizeof(bc)); - if (rc < 0) - goto err; - -#if 0 - /* we cannot bind, since the response packets don't come from - * the broadcast address */ - sa.sin_family = AF_INET; - sa.sin_port = htons(3006); - inet_aton("255.255.255.255", &sa.sin_addr); - - rc = connect(fd, (struct sockaddr *)&sa, sizeof(sa)); - if (rc < 0) - goto err; -#endif - return fd; - -err: - close(fd); - return rc; -} - -const unsigned char find_pkt[] = { 0x00, 0x0b+8, IPAC_PROTO_IPACCESS, 0x00, - IPAC_MSGT_ID_GET, - 0x01, IPAC_IDTAG_MACADDR, - 0x01, IPAC_IDTAG_IPADDR, - 0x01, IPAC_IDTAG_UNIT, - 0x01, IPAC_IDTAG_LOCATION1, - 0x01, IPAC_IDTAG_LOCATION2, - 0x01, IPAC_IDTAG_EQUIPVERS, - 0x01, IPAC_IDTAG_SWVERSION, - 0x01, IPAC_IDTAG_UNITNAME, - 0x01, IPAC_IDTAG_SERNR, - }; - - -static int bcast_find(int fd) -{ - struct sockaddr_in sa; - - sa.sin_family = AF_INET; - sa.sin_port = htons(3006); - inet_aton("255.255.255.255", &sa.sin_addr); - - return sendto(fd, find_pkt, sizeof(find_pkt), 0, (struct sockaddr *) &sa, sizeof(sa)); -} - -static int parse_response(unsigned char *buf, int len) -{ - uint8_t t_len; - uint8_t t_tag; - uint8_t *cur = buf; - - while (cur < buf + len) { - t_len = *cur++; - t_tag = *cur++; - - printf("%s='%s' ", ipa_ccm_idtag_name(t_tag), cur); - - cur += t_len; - } - printf("\n"); - return 0; -} - -static int read_response(int fd) -{ - unsigned char buf[255]; - struct sockaddr_in sa; - int len; - socklen_t sa_len = sizeof(sa); - - len = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sa, &sa_len); - if (len < 0) - return len; - - /* 2 bytes length, 1 byte protocol */ - if (buf[2] != IPAC_PROTO_IPACCESS) - return 0; - - if (buf[4] != IPAC_MSGT_ID_RESP) - return 0; - - return parse_response(buf+6, len-6); -} - -static int bfd_cb(struct osmo_fd *bfd, unsigned int flags) -{ - if (flags & BSC_FD_READ) - return read_response(bfd->fd); - if (flags & BSC_FD_WRITE) { - bfd->when &= ~BSC_FD_WRITE; - return bcast_find(bfd->fd); - } - return 0; -} - -static struct osmo_timer_list timer; - -static void timer_cb(void *_data) -{ - struct osmo_fd *bfd = _data; - - bfd->when |= BSC_FD_WRITE; - - osmo_timer_schedule(&timer, 5, 0); -} - -int main(int argc, char **argv) -{ - struct osmo_fd bfd; - char *ifname = NULL; - int rc; - - printf("abisip-find (C) 2009 by Harald Welte\n"); - printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n"); - - if (argc < 2) { - fprintf(stdout, "you might need to specify the outgoing\n" - " network interface, e.g. ``%s eth0''\n", argv[0]); - } else { - ifname = argv[1]; - } - - bfd.cb = bfd_cb; - bfd.when = BSC_FD_READ | BSC_FD_WRITE; - bfd.fd = udp_sock(ifname); - if (bfd.fd < 0) { - perror("Cannot create local socket for broadcast udp"); - exit(1); - } - - rc = osmo_fd_register(&bfd); - if (rc < 0) { - fprintf(stderr, "Cannot register FD\n"); - exit(1); - } - - osmo_timer_setup(&timer, timer_cb, &bfd); - osmo_timer_schedule(&timer, 5, 0); - - printf("Trying to find ip.access BTS by broadcast UDP...\n"); - - while (1) { - rc = osmo_select_main(0); - if (rc < 0) - exit(3); - } - - exit(0); -} - diff --git a/src/ipaccess/ipaccess-config.c b/src/ipaccess/ipaccess-config.c deleted file mode 100644 index 6822c06a6..000000000 --- a/src/ipaccess/ipaccess-config.c +++ /dev/null @@ -1,1019 +0,0 @@ -/* ip.access nanoBTS configuration tool */ - -/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org> - * (C) 2009-2011 by Holger Hans Peter Freyther - * (C) 2009-2010 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <getopt.h> -#include <errno.h> -#include <sys/fcntl.h> -#include <sys/stat.h> - -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - - -#include <osmocom/core/application.h> -#include <osmocom/core/select.h> -#include <osmocom/core/timer.h> -#include <openbsc/ipaccess.h> -#include <openbsc/common_bsc.h> -#include <osmocom/abis/e1_input.h> -#include <openbsc/abis_nm.h> -#include <openbsc/signal.h> -#include <openbsc/debug.h> -#include <openbsc/network_listen.h> -#include <osmocom/abis/ipaccess.h> -#include <openbsc/gsm_data.h> -#include <openbsc/abis_nm.h> -#include <openbsc/signal.h> -#include <openbsc/debug.h> -#include <openbsc/network_listen.h> -#include <osmocom/core/talloc.h> -#include <osmocom/abis/abis.h> -#include <osmocom/gsm/protocol/gsm_12_21.h> - -struct gsm_network *bsc_gsmnet; - -static int net_listen_testnr; -static int restart; -static char *prim_oml_ip; -static char *bts_ip_addr, *bts_ip_mask, *bts_ip_gw; -static char *unit_id; -static uint16_t nv_flags; -static uint16_t nv_mask; -static char *software = NULL; -static int sw_load_state = 0; -static int oml_state = 0; -static int dump_files = 0; -static char *firmware_analysis = NULL; -static int found_trx = 0; -static int loop_tests = 0; - -static void *tall_ctx_config = NULL; -static struct abis_nm_sw_desc *sw_load1 = NULL; -static struct abis_nm_sw_desc *sw_load2 = NULL; - -/* -static uint8_t prim_oml_attr[] = { 0x95, 0x00, 7, 0x88, 192, 168, 100, 11, 0x00, 0x00 }; -static uint8_t unit_id_attr[] = { 0x91, 0x00, 9, '2', '3', '4', '2', '/' , '0', '/', '0', 0x00 }; -*/ - -extern int ipaccess_fd_cb(struct osmo_fd *bfd, unsigned int what); -extern struct e1inp_line_ops ipaccess_e1inp_line_ops; - -/* Actively connect to a BTS. Currently used by ipaccess-config.c */ -static int ipaccess_connect(struct e1inp_line *line, struct sockaddr_in *sa) -{ - struct e1inp_ts *e1i_ts = &line->ts[0]; - struct osmo_fd *bfd = &e1i_ts->driver.ipaccess.fd; - int ret, on = 1; - - bfd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - bfd->cb = ipaccess_fd_cb; - bfd->when = BSC_FD_READ | BSC_FD_WRITE; - bfd->data = line; - bfd->priv_nr = E1INP_SIGN_OML; - - if (bfd->fd < 0) { - LOGP(DLINP, LOGL_ERROR, "could not create TCP socket.\n"); - return -EIO; - } - - ret = setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); - if (ret < 0) { - LOGP(DLINP, LOGL_ERROR, "could not set socket option\n"); - close(bfd->fd); - return -EIO; - } - - ret = connect(bfd->fd, (struct sockaddr *) sa, sizeof(*sa)); - if (ret < 0) { - LOGP(DLINP, LOGL_ERROR, "could not connect socket\n"); - close(bfd->fd); - return ret; - } - - ret = osmo_fd_register(bfd); - if (ret < 0) { - close(bfd->fd); - return ret; - } - return ret; - //return e1inp_line_register(line); -} - -/* configure pseudo E1 line in ip.access style and connect to BTS */ -static int ia_config_connect(struct gsm_bts *bts, struct sockaddr_in *sin) -{ - struct e1inp_line *line; - struct e1inp_ts *sign_ts, *rsl_ts; - struct e1inp_sign_link *oml_link, *rsl_link; - - line = talloc_zero(tall_bsc_ctx, struct e1inp_line); - if (!line) - return -ENOMEM; - - line->driver = e1inp_driver_find("ipa"); - if (!line->driver) { - fprintf(stderr, "cannot `ipa' driver, giving up.\n"); - return -EINVAL; - } - line->ops = &ipaccess_e1inp_line_ops; - - /* create E1 timeslots for signalling and TRAU frames */ - e1inp_ts_config_sign(&line->ts[1-1], line); - e1inp_ts_config_sign(&line->ts[2-1], line); - - /* create signalling links for TS1 */ - sign_ts = &line->ts[1-1]; - rsl_ts = &line->ts[2-1]; - oml_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OML, - bts->c0, 0xff, 0); - rsl_link = e1inp_sign_link_create(rsl_ts, E1INP_SIGN_RSL, - bts->c0, 0, 0); - - /* create back-links from bts/trx */ - bts->oml_link = oml_link; - bts->c0->rsl_link = rsl_link; - - /* default port at BTS for incoming connections is 3006 */ - if (sin->sin_port == 0) - sin->sin_port = htons(3006); - - return ipaccess_connect(line, sin); -} - -/* - * Callback function for NACK on the OML NM - * - * Currently we send the config requests but don't check the - * result. The nanoBTS will send us a NACK when we did something the - * BTS didn't like. - */ -static int ipacc_msg_nack(uint8_t mt) -{ - fprintf(stderr, "Failure to set attribute. This seems fatal\n"); - exit(-1); - return 0; -} - -static void check_restart_or_exit(struct gsm_bts_trx *trx) -{ - if (restart) { - abis_nm_ipaccess_restart(trx); - } else { - exit(0); - } -} - -static int ipacc_msg_ack(uint8_t mt, struct gsm_bts_trx *trx) -{ - if (sw_load_state == 1) { - fprintf(stderr, "The new software is activaed.\n"); - check_restart_or_exit(trx); - } else if (oml_state == 1) { - fprintf(stderr, "Set the NV Attributes.\n"); - check_restart_or_exit(trx); - } - - return 0; -} - -static const uint8_t phys_conf_min[] = { 0x02 }; - -static uint16_t build_physconf(uint8_t *physconf_buf, const struct rxlev_stats *st) -{ - uint16_t *whitelist = (uint16_t *) (physconf_buf + 4); - int num_arfcn; - unsigned int arfcnlist_size; - - /* Create whitelist from rxlevels */ - physconf_buf[0] = phys_conf_min[0]; - physconf_buf[1] = NM_IPAC_EIE_ARFCN_WHITE; - num_arfcn = ipac_rxlevstat2whitelist(whitelist, st, 0, 100); - arfcnlist_size = num_arfcn * 2; - *((uint16_t *) (physconf_buf+2)) = htons(arfcnlist_size); - DEBUGP(DNM, "physconf_buf (%s)\n", osmo_hexdump(physconf_buf, arfcnlist_size+4)); - return arfcnlist_size+4; -} - -static int nwl_sig_cb(unsigned int subsys, unsigned int signal, - void *handler_data, void *signal_data) -{ - struct gsm_bts_trx *trx; - uint8_t physconf_buf[2*NUM_ARFCNS+16]; - uint16_t physconf_len; - - switch (signal) { - case S_IPAC_NWL_COMPLETE: - trx = signal_data; - DEBUGP(DNM, "received S_IPAC_NWL_COMPLETE signal\n"); - switch (trx->ipaccess.test_nr) { - case NM_IPACC_TESTNO_CHAN_USAGE: - /* Dump RxLev results */ - //rxlev_stat_dump(&trx->ipaccess.rxlev_stat); - /* Create whitelist from results */ - physconf_len = build_physconf(physconf_buf, - &trx->ipaccess.rxlev_stat); - /* Start next test abbout BCCH channel usage */ - ipac_nwl_test_start(trx, NM_IPACC_TESTNO_BCCH_CHAN_USAGE, - physconf_buf, physconf_len); - break; - case NM_IPACC_TESTNO_BCCH_CHAN_USAGE: - /* Dump BCCH RxLev results */ - //rxlev_stat_dump(&trx->ipaccess.rxlev_stat); - /* Create whitelist from results */ - physconf_len = build_physconf(physconf_buf, - &trx->ipaccess.rxlev_stat); - /* Start next test about BCCH info */ - ipac_nwl_test_start(trx, NM_IPACC_TESTNO_BCCH_INFO, - physconf_buf, physconf_len); - break; - case NM_IPACC_TESTNO_BCCH_INFO: - /* re-start full process with CHAN_USAGE */ - if (loop_tests) { - DEBUGP(DNM, "starting next test cycle\n"); - ipac_nwl_test_start(trx, net_listen_testnr, phys_conf_min, - sizeof(phys_conf_min)); - } else { - exit(0); - } - break; - } - break; - } - return 0; -} - -static int nm_state_event(int evt, uint8_t obj_class, void *obj, - struct gsm_nm_state *old_state, struct gsm_nm_state *new_state, - struct abis_om_obj_inst *obj_inst); - -static int nm_sig_cb(unsigned int subsys, unsigned int signal, - void *handler_data, void *signal_data) -{ - struct ipacc_ack_signal_data *ipacc_data; - struct nm_statechg_signal_data *nsd; - - switch (signal) { - case S_NM_IPACC_NACK: - ipacc_data = signal_data; - return ipacc_msg_nack(ipacc_data->msg_type); - case S_NM_IPACC_ACK: - ipacc_data = signal_data; - return ipacc_msg_ack(ipacc_data->msg_type, ipacc_data->trx); - case S_NM_IPACC_RESTART_ACK: - printf("The BTS has acked the restart. Exiting.\n"); - exit(0); - break; - case S_NM_IPACC_RESTART_NACK: - printf("The BTS has nacked the restart. Exiting.\n"); - exit(0); - break; - case S_NM_STATECHG_OPER: - case S_NM_STATECHG_ADM: - nsd = signal_data; - nm_state_event(signal, nsd->obj_class, nsd->obj, nsd->old_state, - nsd->new_state, nsd->obj_inst); - break; - default: - break; - } - - return 0; -} - -/* callback function passed to the ABIS OML code */ -static int percent; -static int percent_old; -static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *_msg, - void *data, void *param) -{ - struct msgb *msg; - struct gsm_bts_trx *trx; - - if (hook != GSM_HOOK_NM_SWLOAD) - return 0; - - trx = (struct gsm_bts_trx *) data; - - switch (event) { - case NM_MT_LOAD_INIT_ACK: - fprintf(stdout, "Software Load Initiate ACK\n"); - break; - case NM_MT_LOAD_INIT_NACK: - fprintf(stderr, "ERROR: Software Load Initiate NACK\n"); - exit(5); - break; - case NM_MT_LOAD_END_ACK: - fprintf(stderr, "LOAD END ACK..."); - /* now make it the default */ - sw_load_state = 1; - - msg = msgb_alloc(1024, "sw: nvattr"); - msg->l2h = msgb_put(msg, 3); - msg->l3h = &msg->l2h[3]; - - /* activate software */ - if (sw_load1) - abis_nm_put_sw_desc(msg, sw_load1, true); - - if (sw_load2) - abis_nm_put_sw_desc(msg, sw_load2, true); - - /* fill in the data */ - msg->l2h[0] = NM_ATT_IPACC_CUR_SW_CFG; - msg->l2h[1] = msgb_l3len(msg) >> 8; - msg->l2h[2] = msgb_l3len(msg) & 0xff; - printf("Foo l2h: %p l3h: %p... length l2: %u l3: %u\n", msg->l2h, msg->l3h, msgb_l2len(msg), msgb_l3len(msg)); - abis_nm_ipaccess_set_nvattr(trx, msg->l2h, msgb_l2len(msg)); - msgb_free(msg); - break; - case NM_MT_LOAD_END_NACK: - fprintf(stderr, "ERROR: Software Load End NACK\n"); - exit(3); - break; - case NM_MT_ACTIVATE_SW_NACK: - fprintf(stderr, "ERROR: Activate Software NACK\n"); - exit(4); - break; - case NM_MT_ACTIVATE_SW_ACK: - break; - case NM_MT_LOAD_SEG_ACK: - percent = abis_nm_software_load_status(trx->bts); - if (percent > percent_old) - printf("Software Download Progress: %d%%\n", percent); - percent_old = percent; - break; - case NM_MT_LOAD_ABORT: - fprintf(stderr, "ERROR: Load aborted by the BTS.\n"); - exit(6); - break; - } - return 0; -} - -static void nv_put_ip_if_cfg(struct msgb *nmsg, uint32_t ip, uint32_t mask) -{ - msgb_put_u8(nmsg, NM_ATT_IPACC_IP_IF_CFG); - - msgb_put_u32(nmsg, ip); - msgb_put_u32(nmsg, mask); -} - -static void nv_put_gw_cfg(struct msgb *nmsg, uint32_t addr, uint32_t mask, uint32_t gw) -{ - msgb_put_u8(nmsg, NM_ATT_IPACC_IP_GW_CFG); - msgb_put_u32(nmsg, addr); - msgb_put_u32(nmsg, mask); - msgb_put_u32(nmsg, gw); -} - -static void nv_put_unit_id(struct msgb *nmsg, const char *unit_id) -{ - msgb_tl16v_put(nmsg, NM_ATT_IPACC_UNIT_ID, strlen(unit_id)+1, - (const uint8_t *)unit_id); -} - -static void nv_put_prim_oml(struct msgb *nmsg, uint32_t ip, uint16_t port) -{ - int len; - - /* 0x88 + IP + port */ - len = 1 + sizeof(ip) + sizeof(port); - - msgb_put_u8(nmsg, NM_ATT_IPACC_PRIM_OML_CFG_LIST); - msgb_put_u16(nmsg, len); - - msgb_put_u8(nmsg, 0x88); - - /* IP address */ - msgb_put_u32(nmsg, ip); - - /* port number */ - msgb_put_u16(nmsg, port); -} - -static void nv_put_flags(struct msgb *nmsg, uint16_t nv_flags, uint16_t nv_mask) -{ - msgb_put_u8(nmsg, NM_ATT_IPACC_NV_FLAGS); - msgb_put_u16(nmsg, sizeof(nv_flags) + sizeof(nv_mask)); - msgb_put_u8(nmsg, nv_flags & 0xff); - msgb_put_u8(nmsg, nv_mask & 0xff); - msgb_put_u8(nmsg, nv_flags >> 8); - msgb_put_u8(nmsg, nv_mask >> 8); -} - -/* human-readable test names for the ip.access tests */ -static const struct value_string ipa_test_strs[] = { - { 64, "ccch-usage" }, - { 65, "bcch-usage" }, - { 66, "freq-sync" }, - { 67, "rtp-usage" }, - { 68, "rtp-perf" }, - { 69, "gprs-ccch" }, - { 70, "pccch-usage" }, - { 71, "gprs-usage" }, - { 72, "esta-mf" }, - { 73, "uplink-mf" }, - { 74, "dolink-mf" }, - { 75, "tbf-details" }, - { 76, "tbf-usage" }, - { 77, "llc-data" }, - { 78, "pdch-usage" }, - { 79, "power-control" }, - { 80, "link-adaption" }, - { 81, "tch-usage" }, - { 82, "amr-mf" }, - { 83, "rtp-multiplex-perf" }, - { 84, "rtp-multiplex-usage" }, - { 85, "srtp-multiplex-usage" }, - { 86, "abis-traffic" }, - { 89, "gprs-multiplex-perf" }, - { 90, "gprs-multiplex-usage" }, - { 0, NULL }, -}; - -/* human-readable names for the ip.access nanoBTS NVRAM Flags */ -static const struct value_string ipa_nvflag_strs[] = { - { 0x0001, "static-ip" }, - { 0x0002, "static-gw" }, - { 0x0004, "no-dhcp-vsi" }, - { 0x0008, "dhcp-enabled" }, - { 0x0040, "led-disabled" }, - { 0x0100, "secondary-oml-enabled" }, - { 0x0200, "diag-enabled" }, - { 0x0400, "cli-enabled" }, - { 0x0800, "http-enabled" }, - { 0x1000, "post-enabled" }, - { 0x2000, "snmp-enabled" }, - { 0, NULL } -}; - -/* set the flags in flags/mask according to a string-identified flag and 'enable' */ -static int ipa_nvflag_set(uint16_t *flags, uint16_t *mask, const char *name, int en) -{ - int rc; - rc = get_string_value(ipa_nvflag_strs, name); - if (rc < 0) - return rc; - - *mask |= rc; - if (en) - *flags |= rc; - else - *flags &= ~rc; - - return 0; -} - -static void bootstrap_om(struct gsm_bts_trx *trx) -{ - struct msgb *nmsg = msgb_alloc(1024, "nested msgb"); - int need_to_set_attr = 0; - int len; - - printf("OML link established using TRX %d\n", trx->nr); - - if (unit_id) { - len = strlen(unit_id); - if (len > nmsg->data_len-10) - goto out_err; - printf("setting Unit ID to '%s'\n", unit_id); - nv_put_unit_id(nmsg, unit_id); - need_to_set_attr = 1; - } - if (prim_oml_ip) { - struct in_addr ia; - - if (!inet_aton(prim_oml_ip, &ia)) { - fprintf(stderr, "invalid IP address: %s\n", - prim_oml_ip); - goto out_err; - } - - printf("setting primary OML link IP to '%s'\n", inet_ntoa(ia)); - nv_put_prim_oml(nmsg, ntohl(ia.s_addr), 0); - need_to_set_attr = 1; - } - if (nv_mask) { - printf("setting NV Flags/Mask to 0x%04x/0x%04x\n", - nv_flags, nv_mask); - nv_put_flags(nmsg, nv_flags, nv_mask); - need_to_set_attr = 1; - } - if (bts_ip_addr && bts_ip_mask) { - struct in_addr ia_addr, ia_mask; - - if (!inet_aton(bts_ip_addr, &ia_addr)) { - fprintf(stderr, "invalid IP address: %s\n", - bts_ip_addr); - goto out_err; - } - - if (!inet_aton(bts_ip_mask, &ia_mask)) { - fprintf(stderr, "invalid IP address: %s\n", - bts_ip_mask); - goto out_err; - } - - printf("setting static IP Address/Mask\n"); - nv_put_ip_if_cfg(nmsg, ntohl(ia_addr.s_addr), ntohl(ia_mask.s_addr)); - need_to_set_attr = 1; - } - if (bts_ip_gw) { - struct in_addr ia_gw; - - if (!inet_aton(bts_ip_gw, &ia_gw)) { - fprintf(stderr, "invalid IP address: %s\n", - bts_ip_gw); - goto out_err; - } - - printf("setting static IP Gateway\n"); - /* we only set the default gateway with zero addr/mask */ - nv_put_gw_cfg(nmsg, 0, 0, ntohl(ia_gw.s_addr)); - need_to_set_attr = 1; - } - - if (need_to_set_attr) { - abis_nm_ipaccess_set_nvattr(trx, nmsg->head, nmsg->len); - oml_state = 1; - } - - if (restart && !prim_oml_ip && !software) { - printf("restarting BTS\n"); - abis_nm_ipaccess_restart(trx); - } - -out_err: - msgb_free(nmsg); -} - -static int nm_state_event(int evt, uint8_t obj_class, void *obj, - struct gsm_nm_state *old_state, struct gsm_nm_state *new_state, - struct abis_om_obj_inst *obj_inst) -{ - if (obj_class == NM_OC_BASEB_TRANSC) { - if (!found_trx && obj_inst->trx_nr != 0xff) { - struct gsm_bts_trx *trx = container_of(obj, struct gsm_bts_trx, bb_transc); - bootstrap_om(trx); - found_trx = 1; - } - } else if (evt == S_NM_STATECHG_OPER && - obj_class == NM_OC_RADIO_CARRIER && - new_state->availability == 3) { - struct gsm_bts_trx *trx = obj; - - if (net_listen_testnr) - ipac_nwl_test_start(trx, net_listen_testnr, - phys_conf_min, sizeof(phys_conf_min)); - else if (software) { - int rc; - printf("Attempting software upload with '%s'\n", software); - rc = abis_nm_software_load(trx->bts, trx->nr, software, 19, 0, swload_cbfn, trx); - if (rc < 0) { - fprintf(stderr, "Failed to start software load\n"); - exit(-3); - } - } - } - return 0; -} - -static struct abis_nm_sw_desc *create_swload(struct sdp_header *header) -{ - struct abis_nm_sw_desc *load; - - load = talloc_zero(tall_ctx_config, struct abis_nm_sw_desc); - - osmo_strlcpy((char *)load->file_id, header->firmware_info.sw_part, - sizeof(load->file_id)); - load->file_id_len = strlen((char*)load->file_id) + 1; - - osmo_strlcpy((char *)load->file_version, header->firmware_info.version, - sizeof(load->file_version)); - load->file_version_len = strlen((char*)load->file_version) + 1; - - return load; -} - -static int find_sw_load_params(const char *filename) -{ - struct stat stat; - struct sdp_header *header; - struct llist_head *entry; - int fd; - void *tall_firm_ctx = 0; - - entry = talloc_zero(tall_firm_ctx, struct llist_head); - INIT_LLIST_HEAD(entry); - - fd = open(filename, O_RDONLY); - if (!fd) { - perror("nada"); - return -1; - } - - /* verify the file */ - if (fstat(fd, &stat) == -1) { - perror("Can not stat the file"); - close(fd); - return -1; - } - - ipaccess_analyze_file(fd, stat.st_size, 0, entry); - if (close(fd) != 0) { - perror("Close failed.\n"); - return -1; - } - - /* try to find what we are looking for */ - llist_for_each_entry(header, entry, entry) { - if (ntohs(header->firmware_info.more_more_magic) == 0x1000) { - sw_load1 = create_swload(header); - } else if (ntohs(header->firmware_info.more_more_magic) == 0x2001) { - sw_load2 = create_swload(header); - } - } - - if (!sw_load1 || !sw_load2) { - fprintf(stderr, "Did not find data.\n"); - talloc_free(tall_firm_ctx); - return -1; - } - - talloc_free(tall_firm_ctx); - return 0; -} - -static void dump_entry(struct sdp_header_item *sub_entry, int part, int fd) -{ - int out_fd; - int copied; - char filename[4096]; - off_t target; - - if (!dump_files) - return; - - if (sub_entry->header_entry.something1 == 0) - return; - - snprintf(filename, sizeof(filename), "part.%d", part++); - out_fd = open(filename, O_WRONLY | O_CREAT, 0660); - if (out_fd < 0) { - perror("Can not dump firmware"); - return; - } - - target = sub_entry->absolute_offset + ntohl(sub_entry->header_entry.start) + 4; - if (lseek(fd, target, SEEK_SET) != target) { - perror("seek failed"); - close(out_fd); - return; - } - - for (copied = 0; copied < ntohl(sub_entry->header_entry.length); ++copied) { - char c; - if (read(fd, &c, sizeof(c)) != sizeof(c)) { - perror("copy failed"); - break; - } - - if (write(out_fd, &c, sizeof(c)) != sizeof(c)) { - perror("write failed"); - break; - } - } - - close(out_fd); -} - -static void analyze_firmware(const char *filename) -{ - struct stat stat; - struct sdp_header *header; - struct sdp_header_item *sub_entry; - struct llist_head *entry; - int fd; - void *tall_firm_ctx = 0; - int part = 0; - - entry = talloc_zero(tall_firm_ctx, struct llist_head); - INIT_LLIST_HEAD(entry); - - printf("Opening possible firmware '%s'\n", filename); - fd = open(filename, O_RDONLY); - if (!fd) { - perror("nada"); - return; - } - - /* verify the file */ - if (fstat(fd, &stat) == -1) { - perror("Can not stat the file"); - close(fd); - return; - } - - ipaccess_analyze_file(fd, stat.st_size, 0, entry); - - llist_for_each_entry(header, entry, entry) { - printf("Printing header information:\n"); - printf("more_more_magic: 0x%x\n", ntohs(header->firmware_info.more_more_magic)); - printf("header_length: %u\n", ntohl(header->firmware_info.header_length)); - printf("file_length: %u\n", ntohl(header->firmware_info.file_length)); - printf("sw_part: %.20s\n", header->firmware_info.sw_part); - printf("text1: %.64s\n", header->firmware_info.text1); - printf("time: %.12s\n", header->firmware_info.time); - printf("date: %.14s\n", header->firmware_info.date); - printf("text2: %.10s\n", header->firmware_info.text2); - printf("version: %.20s\n", header->firmware_info.version); - printf("subitems...\n"); - - llist_for_each_entry(sub_entry, &header->header_list, entry) { - printf("\tsomething1: %u\n", sub_entry->header_entry.something1); - printf("\ttext1: %.64s\n", sub_entry->header_entry.text1); - printf("\ttime: %.12s\n", sub_entry->header_entry.time); - printf("\tdate: %.14s\n", sub_entry->header_entry.date); - printf("\ttext2: %.10s\n", sub_entry->header_entry.text2); - printf("\tversion: %.20s\n", sub_entry->header_entry.version); - printf("\tlength: %u\n", ntohl(sub_entry->header_entry.length)); - printf("\taddr1: 0x%x\n", ntohl(sub_entry->header_entry.addr1)); - printf("\taddr2: 0x%x\n", ntohl(sub_entry->header_entry.addr2)); - printf("\tstart: 0x%x\n", ntohl(sub_entry->header_entry.start)); - printf("\tabs. offset: 0x%lx\n", sub_entry->absolute_offset); - printf("\n\n"); - - dump_entry(sub_entry, part++, fd); - } - printf("\n\n"); - } - - if (close(fd) != 0) { - perror("Close failed.\n"); - return; - } - - talloc_free(tall_firm_ctx); -} - -static void print_usage(void) -{ - printf("Usage: ipaccess-config IP_OF_BTS\n"); -} - -static void print_help(void) -{ -#if 0 - printf("Commands for reading from the BTS:\n"); - printf(" -D --dump\t\t\tDump the BTS configuration\n"); - printf("\n"); -#endif - printf("Commands for writing to the BTS:\n"); - printf(" -u --unit-id UNIT_ID\t\tSet the Unit ID of the BTS\n"); - printf(" -o --oml-ip IP\t\tSet primary OML IP (IP of your BSC)\n"); - printf(" -i --ip-address IP/MASK\tSet static IP address + netmask of BTS\n"); - printf(" -g --ip-gateway IP\t\tSet static IP gateway of BTS\n"); - printf(" -r --restart\t\t\tRestart the BTS (after other operations)\n"); - printf(" -n --nvram-flags FLAGS/MASK\tSet NVRAM attributes\n"); - printf(" -S --nvattr-set FLAG\tSet one additional NVRAM attribute\n"); - printf(" -U --nvattr-unset FLAG\tSet one additional NVRAM attribute\n"); - printf(" -l --listen TESTNR\t\tPerform specified test number\n"); - printf(" -L --Listen TEST_NAME\t\tPerform specified test\n"); - printf(" -s --stream-id ID\t\tSet the IPA Stream Identifier for OML\n"); - printf(" -d --software FIRMWARE\tDownload firmware into BTS\n"); - printf("\n"); - printf("Miscellaneous commands:\n"); - printf(" -h --help\t\t\tthis text\n"); - printf(" -H --HELP\t\t\tPrint parameter details.\n"); - printf(" -f --firmware FIRMWARE\tProvide firmware information\n"); - printf(" -w --write-firmware\t\tThis will dump the firmware parts to the filesystem. Use with -f.\n"); - printf(" -p --loop\t\t\tLoop the tests executed with the --listen command.\n"); -} - -static void print_value_string(const struct value_string *val, int size) -{ - int i; - - for (i = 0; i < size - 1; ++i) { - char sep = val[i + 1].str == NULL ? '.' : ','; - printf("%s%c ", val[i].str, sep); - } - printf("\n"); -} - -static void print_options(void) -{ - - printf("Options for NVRAM (-S,-U):\n "); - print_value_string(&ipa_nvflag_strs[0], ARRAY_SIZE(ipa_nvflag_strs)); - - printf("Options for Tests (-L):\n "); - print_value_string(&ipa_test_strs[0], ARRAY_SIZE(ipa_test_strs)); -} - -extern void bts_model_nanobts_init(); - -int main(int argc, char **argv) -{ - struct gsm_bts *bts; - struct sockaddr_in sin; - int rc, option_index = 0, stream_id = 0xff; - - tall_ctx_config = talloc_named_const(NULL, 0, "ipaccess-config"); - msgb_talloc_ctx_init(tall_ctx_config, 0); - - osmo_init_logging(&log_info); - log_parse_category_mask(osmo_stderr_target, "DNM,0"); - bts_model_nanobts_init(); - - printf("ipaccess-config (C) 2009-2010 by Harald Welte and others\n"); - printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n"); - - while (1) { - int c; - unsigned long ul; - char *slash; - static struct option long_options[] = { - { "unit-id", 1, 0, 'u' }, - { "oml-ip", 1, 0, 'o' }, - { "ip-address", 1, 0, 'i' }, - { "ip-gateway", 1, 0, 'g' }, - { "restart", 0, 0, 'r' }, - { "nvram-flags", 1, 0, 'n' }, - { "nvattr-set", 1, 0, 'S' }, - { "nvattr-unset", 1, 0, 'U' }, - { "help", 0, 0, 'h' }, - { "HELP", 0, 0, 'H' }, - { "listen", 1, 0, 'l' }, - { "Listen", 1, 0, 'L' }, - { "stream-id", 1, 0, 's' }, - { "software", 1, 0, 'd' }, - { "firmware", 1, 0, 'f' }, - { "write-firmware", 0, 0, 'w' }, - { "disable-color", 0, 0, 'c'}, - { "loop", 0, 0, 'p' }, - { 0, 0, 0, 0 }, - }; - - c = getopt_long(argc, argv, "u:o:i:g:rn:S:U:l:L:hs:d:f:wcpH", long_options, - &option_index); - - if (c == -1) - break; - - switch (c) { - case 'u': - unit_id = optarg; - break; - case 'o': - prim_oml_ip = optarg; - break; - case 'i': - slash = strchr(optarg, '/'); - if (!slash) - exit(2); - bts_ip_addr = optarg; - *slash = 0; - bts_ip_mask = slash+1; - break; - case 'g': - bts_ip_gw = optarg; - break; - case 'r': - restart = 1; - break; - case 'n': - slash = strchr(optarg, '/'); - if (!slash) - exit(2); - ul = strtoul(optarg, NULL, 16); - nv_flags = ul & 0xffff; - ul = strtoul(slash+1, NULL, 16); - nv_mask = ul & 0xffff; - break; - case 'S': - if (ipa_nvflag_set(&nv_flags, &nv_mask, optarg, 1) < 0) - exit(2); - break; - case 'U': - if (ipa_nvflag_set(&nv_flags, &nv_mask, optarg, 0) < 0) - exit(2); - break; - case 'l': - net_listen_testnr = atoi(optarg); - break; - case 'L': - net_listen_testnr = get_string_value(ipa_test_strs, - optarg); - if (net_listen_testnr < 0) { - fprintf(stderr, - "The test '%s' is not known. Use -H to" - " see available tests.\n", optarg); - exit(2); - } - break; - case 's': - stream_id = atoi(optarg); - break; - case 'd': - software = strdup(optarg); - if (find_sw_load_params(optarg) != 0) - exit(0); - break; - case 'f': - firmware_analysis = optarg; - break; - case 'w': - dump_files = 1; - break; - case 'c': - log_set_use_color(osmo_stderr_target, 0); - break; - case 'p': - loop_tests = 1; - break; - case 'h': - print_usage(); - print_help(); - exit(0); - case 'H': - print_options(); - exit(0); - } - }; - - if (firmware_analysis) - analyze_firmware(firmware_analysis); - - if (optind >= argc) { - /* only warn if we have not done anything else */ - if (!firmware_analysis) - fprintf(stderr, "you have to specify the IP address of the BTS. Use --help for more information\n"); - exit(2); - } - libosmo_abis_init(tall_ctx_config); - - bsc_gsmnet = bsc_network_init(tall_bsc_ctx, 1, 1, NULL); - if (!bsc_gsmnet) - exit(1); - - bts = gsm_bts_alloc_register(bsc_gsmnet, GSM_BTS_TYPE_NANOBTS, - HARDCODED_BSIC); - /* ip.access supports up to 4 chained TRX */ - gsm_bts_trx_alloc(bts); - gsm_bts_trx_alloc(bts); - gsm_bts_trx_alloc(bts); - bts->oml_tei = stream_id; - - osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL); - osmo_signal_register_handler(SS_IPAC_NWL, nwl_sig_cb, NULL); - - ipac_nwl_init(); - - printf("Trying to connect to ip.access BTS ...\n"); - - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - inet_aton(argv[optind], &sin.sin_addr); - rc = ia_config_connect(bts, &sin); - if (rc < 0) { - perror("Error connecting to the BTS"); - exit(1); - } - - bts->oml_link->ts->sign.delay = 10; - bts->c0->rsl_link->ts->sign.delay = 10; - while (1) { - rc = osmo_select_main(0); - if (rc < 0) - exit(3); - } - - exit(0); -} - diff --git a/src/ipaccess/ipaccess-firmware.c b/src/ipaccess/ipaccess-firmware.c deleted file mode 100644 index 5f55bb526..000000000 --- a/src/ipaccess/ipaccess-firmware.c +++ /dev/null @@ -1,135 +0,0 @@ -/* Routines for parsing an ipacces SDP firmware file */ - -/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org> - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#include <openbsc/debug.h> -#include <openbsc/ipaccess.h> -#include <osmocom/core/talloc.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#define PART_LENGTH 138 - -osmo_static_assert(sizeof(struct sdp_header_entry) == 138, right_entry); -osmo_static_assert(sizeof(struct sdp_firmware) == 158, _right_header_length); - -/* more magic, the second "int" in the header */ -static char more_magic[] = { 0x10, 0x02 }; - -int ipaccess_analyze_file(int fd, const unsigned int st_size, const unsigned int base_offset, struct llist_head *list) -{ - struct sdp_firmware *firmware_header = 0; - struct sdp_header *header; - char buf[4096]; - int rc, i; - uint16_t table_size; - uint16_t table_offset; - off_t table_start; - - - rc = read(fd, buf, sizeof(*firmware_header)); - if (rc < 0) { - perror("Can not read header start."); - return -1; - } - - firmware_header = (struct sdp_firmware *) &buf[0]; - if (strncmp(firmware_header->magic, " SDP", 4) != 0) { - fprintf(stderr, "Wrong magic.\n"); - return -1; - } - - if (memcmp(firmware_header->more_magic, more_magic, 2) != 0) { - fprintf(stderr, "Wrong more magic. Got: 0x%x 0x%x vs. 0x%x 0x%x\n", - firmware_header->more_magic[0] & 0xff, firmware_header->more_magic[1] & 0xff, - more_magic[0], more_magic[1]); - return -1; - } - - - if (ntohl(firmware_header->file_length) != st_size) { - fprintf(stderr, "The filesize and the header do not match.\n"); - return -1; - } - - /* add the firmware */ - header = talloc_zero(list, struct sdp_header); - header->firmware_info = *firmware_header; - INIT_LLIST_HEAD(&header->header_list); - llist_add(&header->entry, list); - - table_offset = ntohs(firmware_header->table_offset); - table_start = lseek(fd, table_offset, SEEK_CUR); - if (table_start == -1) { - fprintf(stderr, "Failed to seek to the rel position: 0x%x\n", table_offset); - return -1; - } - - if (read(fd, &table_size, sizeof(table_size)) != sizeof(table_size)) { - fprintf(stderr, "The table size could not be read.\n"); - return -1; - } - - table_size = ntohs(table_size); - - if (table_size % PART_LENGTH != 0) { - fprintf(stderr, "The part length seems to be wrong: 0x%x\n", table_size); - return -1; - } - - /* look into each firmware now */ - for (i = 0; i < table_size / PART_LENGTH; ++i) { - struct sdp_header_entry entry; - struct sdp_header_item *header_entry; - unsigned int offset = table_start + 2; - offset += i * 138; - - if (lseek(fd, offset, SEEK_SET) != offset) { - fprintf(stderr, "Can not seek to the offset: %u.\n", offset); - return -1; - } - - rc = read(fd, &entry, sizeof(entry)); - if (rc != sizeof(entry)) { - fprintf(stderr, "Can not read the header entry.\n"); - return -1; - } - - header_entry = talloc_zero(header, struct sdp_header_item); - header_entry->header_entry = entry; - header_entry->absolute_offset = base_offset; - llist_add(&header_entry->entry, &header->header_list); - - /* now we need to find the SDP file... */ - offset = ntohl(entry.start) + 4 + base_offset; - if (lseek(fd, offset, SEEK_SET) != offset) { - perror("can't seek to sdp"); - return -1; - } - - - ipaccess_analyze_file(fd, ntohl(entry.length), offset, list); - } - - return 0; -} - diff --git a/src/ipaccess/ipaccess-proxy.c b/src/ipaccess/ipaccess-proxy.c deleted file mode 100644 index d3674426c..000000000 --- a/src/ipaccess/ipaccess-proxy.c +++ /dev/null @@ -1,1226 +0,0 @@ -/* OpenBSC Abis/IP proxy ip.access nanoBTS */ - -/* (C) 2009 by Harald Welte <laforge@gnumonks.org> - * (C) 2010 by On-Waves - * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org> - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <errno.h> -#include <string.h> -#include <signal.h> -#include <time.h> -#include <sys/fcntl.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <arpa/inet.h> -#include <netinet/in.h> - -#define _GNU_SOURCE -#include <getopt.h> - -#include <openbsc/gsm_data.h> -#include <osmocom/core/application.h> -#include <osmocom/core/select.h> -#include <osmocom/gsm/tlv.h> -#include <osmocom/core/msgb.h> -#include <osmocom/gsm/ipa.h> -#include <osmocom/abis/ipa.h> -#include <osmocom/abis/ipaccess.h> -#include <openbsc/debug.h> -#include <openbsc/ipaccess.h> -#include <openbsc/socket.h> -#include <osmocom/core/talloc.h> - -/* one instance of an ip.access protocol proxy */ -struct ipa_proxy { - /* socket where we listen for incoming OML from BTS */ - struct osmo_fd oml_listen_fd; - /* socket where we listen for incoming RSL from BTS */ - struct osmo_fd rsl_listen_fd; - /* list of BTS's (struct ipa_bts_conn */ - struct llist_head bts_list; - /* the BSC reconnect timer */ - struct osmo_timer_list reconn_timer; - /* global GPRS NS data */ - struct in_addr gprs_addr; - struct in_addr listen_addr; -}; - -/* global pointer to the proxy structure */ -static struct ipa_proxy *ipp; - -struct ipa_proxy_conn { - struct osmo_fd fd; - struct llist_head tx_queue; - struct ipa_bts_conn *bts_conn; -}; -#define MAX_TRX 4 - -/* represents a particular BTS in our proxy */ -struct ipa_bts_conn { - /* list of BTS's (ipa_proxy->bts_list) */ - struct llist_head list; - /* back pointer to the proxy which we belong to */ - struct ipa_proxy *ipp; - /* the unit ID as determined by CCM */ - struct { - uint16_t site_id; - uint16_t bts_id; - } unit_id; - - /* incoming connections from BTS */ - struct ipa_proxy_conn *oml_conn; - struct ipa_proxy_conn *rsl_conn[MAX_TRX]; - - /* outgoing connections to BSC */ - struct ipa_proxy_conn *bsc_oml_conn; - struct ipa_proxy_conn *bsc_rsl_conn[MAX_TRX]; - - /* UDP sockets for BTS and BSC injection */ - struct osmo_fd udp_bts_fd; - struct osmo_fd udp_bsc_fd; - - /* NS data */ - struct in_addr bts_addr; - struct osmo_fd gprs_ns_fd; - int gprs_local_port; - uint16_t gprs_orig_port; - uint32_t gprs_orig_ip; - - char *id_tags[256]; - uint8_t *id_resp; - unsigned int id_resp_len; -}; - -enum ipp_fd_type { - OML_FROM_BTS = 1, - RSL_FROM_BTS = 2, - OML_TO_BSC = 3, - RSL_TO_BSC = 4, - UDP_TO_BTS = 5, - UDP_TO_BSC = 6, -}; - -/* some of the code against we link from OpenBSC needs this */ -void *tall_bsc_ctx; - -static char *listen_ipaddr; -static char *bsc_ipaddr; -static char *gprs_ns_ipaddr; - -static int gprs_ns_cb(struct osmo_fd *bfd, unsigned int what); - -#define PROXY_ALLOC_SIZE 1200 - -static struct ipa_bts_conn *find_bts_by_unitid(struct ipa_proxy *ipp, - uint16_t site_id, - uint16_t bts_id) -{ - struct ipa_bts_conn *ipbc; - - llist_for_each_entry(ipbc, &ipp->bts_list, list) { - if (ipbc->unit_id.site_id == site_id && - ipbc->unit_id.bts_id == bts_id) - return ipbc; - } - - return NULL; -} - -struct ipa_proxy_conn *alloc_conn(void) -{ - struct ipa_proxy_conn *ipc; - - ipc = talloc_zero(tall_bsc_ctx, struct ipa_proxy_conn); - if (!ipc) - return NULL; - - INIT_LLIST_HEAD(&ipc->tx_queue); - - return ipc; -} - -static int store_idtags(struct ipa_bts_conn *ipbc, struct tlv_parsed *tlvp) -{ - unsigned int i, len; - - for (i = 0; i <= 0xff; i++) { - if (!TLVP_PRESENT(tlvp, i)) - continue; - - len = TLVP_LEN(tlvp, i); -#if 0 - if (!ipbc->id_tags[i]) - ipbc->id_tags[i] = talloc_size(tall_bsc_ctx, len); - else -#endif - ipbc->id_tags[i] = talloc_realloc_size(ipbc, - ipbc->id_tags[i], len); - if (!ipbc->id_tags[i]) - return -ENOMEM; - - memset(ipbc->id_tags[i], 0, len); - //memcpy(ipbc->id_tags[i], TLVP_VAL(tlvp, i), len); - } - return 0; -} - - -static struct ipa_proxy_conn *connect_bsc(struct sockaddr_in *sa, int priv_nr, void *data); - -#define logp_ipbc_uid(ss, lvl, ipbc, trx_id) _logp_ipbc_uid(ss, lvl, __FILE__, __LINE__, ipbc, trx_id) - -static void _logp_ipbc_uid(unsigned int ss, unsigned int lvl, char *file, int line, - struct ipa_bts_conn *ipbc, uint8_t trx_id) -{ - if (ipbc) - logp2(ss, lvl, file, line, 0, "(%u/%u/%u) ", ipbc->unit_id.site_id, - ipbc->unit_id.bts_id, trx_id); - else - logp2(ss, lvl, file, line, 0, "unknown "); -} - -static int handle_udp_read(struct osmo_fd *bfd) -{ - struct ipa_bts_conn *ipbc = bfd->data; - struct ipa_proxy_conn *other_conn = NULL; - struct msgb *msg = msgb_alloc(PROXY_ALLOC_SIZE, "Abis/IP UDP"); - struct ipaccess_head *hh; - int ret; - - /* with UDP sockets, we cannot read partial packets but have to read - * all of it in one go */ - hh = (struct ipaccess_head *) msg->data; - ret = recv(bfd->fd, msg->data, msg->data_len, 0); - if (ret < 0) { - if (errno != EAGAIN) - LOGP(DLINP, LOGL_ERROR, "recv error %s\n", strerror(errno)); - msgb_free(msg); - return ret; - } - if (ret == 0) { - DEBUGP(DLINP, "UDP peer disappeared, dead socket\n"); - osmo_fd_unregister(bfd); - close(bfd->fd); - bfd->fd = -1; - msgb_free(msg); - return -EIO; - } - if (ret < sizeof(*hh)) { - DEBUGP(DLINP, "could not even read header!?!\n"); - msgb_free(msg); - return -EIO; - } - msgb_put(msg, ret); - msg->l2h = msg->data + sizeof(*hh); - DEBUGP(DLMI, "UDP RX: %s\n", osmo_hexdump(msg->data, msg->len)); - - if (hh->len != msg->len - sizeof(*hh)) { - DEBUGP(DLINP, "length (%u/%u) disagrees with header(%u)\n", - msg->len, msg->len - 3, hh->len); - msgb_free(msg); - return -EIO; - } - - switch (bfd->priv_nr & 0xff) { - case UDP_TO_BTS: - /* injection towards BTS */ - switch (hh->proto) { - case IPAC_PROTO_RSL: - /* FIXME: what to do about TRX > 0 */ - other_conn = ipbc->rsl_conn[0]; - break; - default: - DEBUGP(DLINP, "Unknown protocol 0x%02x, sending to " - "OML FD\n", hh->proto); - /* fall through */ - case IPAC_PROTO_IPACCESS: - case IPAC_PROTO_OML: - other_conn = ipbc->oml_conn; - break; - } - break; - case UDP_TO_BSC: - /* injection towards BSC */ - switch (hh->proto) { - case IPAC_PROTO_RSL: - /* FIXME: what to do about TRX > 0 */ - other_conn = ipbc->bsc_rsl_conn[0]; - break; - default: - DEBUGP(DLINP, "Unknown protocol 0x%02x, sending to " - "OML FD\n", hh->proto); - /* fall through */ - case IPAC_PROTO_IPACCESS: - case IPAC_PROTO_OML: - other_conn = ipbc->bsc_oml_conn; - break; - } - break; - default: - DEBUGP(DLINP, "Unknown filedescriptor priv_nr=%04x\n", bfd->priv_nr); - break; - } - - if (other_conn) { - /* enqueue the message for TX on the respective FD */ - msgb_enqueue(&other_conn->tx_queue, msg); - other_conn->fd.when |= BSC_FD_WRITE; - } else - msgb_free(msg); - - return 0; -} - -static int handle_udp_write(struct osmo_fd *bfd) -{ - /* not implemented yet */ - bfd->when &= ~BSC_FD_WRITE; - - return -EIO; -} - -/* callback from select.c in case one of the fd's can be read/written */ -static int udp_fd_cb(struct osmo_fd *bfd, unsigned int what) -{ - int rc = 0; - - if (what & BSC_FD_READ) - rc = handle_udp_read(bfd); - if (what & BSC_FD_WRITE) - rc = handle_udp_write(bfd); - - return rc; -} - - -static int ipbc_alloc_connect(struct ipa_proxy_conn *ipc, struct osmo_fd *bfd, - uint16_t site_id, uint16_t bts_id, - uint16_t trx_id, struct tlv_parsed *tlvp, - struct msgb *msg) -{ - struct ipa_bts_conn *ipbc; - uint16_t udp_port; - int ret = 0; - struct sockaddr_in sin; - - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - inet_aton(bsc_ipaddr, &sin.sin_addr); - - DEBUGP(DLINP, "(%u/%u/%u) New BTS connection: ", - site_id, bts_id, trx_id); - - /* OML needs to be established before RSL */ - if ((bfd->priv_nr & 0xff) != OML_FROM_BTS) { - DEBUGPC(DLINP, "Not a OML connection ?!?\n"); - return -EIO; - } - - /* allocate new BTS connection data structure */ - ipbc = talloc_zero(tall_bsc_ctx, struct ipa_bts_conn); - if (!ipbc) { - ret = -ENOMEM; - goto err_out; - } - - DEBUGPC(DLINP, "Created BTS Conn data structure\n"); - ipbc->ipp = ipp; - ipbc->unit_id.site_id = site_id; - ipbc->unit_id.bts_id = bts_id; - ipbc->oml_conn = ipc; - ipc->bts_conn = ipbc; - - /* store the content of the ID TAGS for later reference */ - store_idtags(ipbc, tlvp); - ipbc->id_resp_len = msg->len; - ipbc->id_resp = talloc_size(tall_bsc_ctx, ipbc->id_resp_len); - memcpy(ipbc->id_resp, msg->data, ipbc->id_resp_len); - - /* Create OML TCP connection towards BSC */ - sin.sin_port = htons(IPA_TCP_PORT_OML); - ipbc->bsc_oml_conn = connect_bsc(&sin, OML_TO_BSC, ipbc); - if (!ipbc->bsc_oml_conn) { - ret = -EIO; - goto err_bsc_conn; - } - - DEBUGP(DLINP, "(%u/%u/%u) OML Connected to BSC\n", - site_id, bts_id, trx_id); - - /* Create UDP socket for BTS packet injection */ - udp_port = 10000 + (site_id % 1000)*100 + (bts_id % 100); - ret = make_sock(&ipbc->udp_bts_fd, IPPROTO_UDP, INADDR_ANY, udp_port, - UDP_TO_BTS, udp_fd_cb, ipbc); - if (ret < 0) - goto err_udp_bts; - DEBUGP(DLINP, "(%u/%u/%u) Created UDP socket for injection " - "towards BTS at port %u\n", site_id, bts_id, trx_id, udp_port); - - /* Create UDP socket for BSC packet injection */ - udp_port = 20000 + (site_id % 1000)*100 + (bts_id % 100); - ret = make_sock(&ipbc->udp_bsc_fd, IPPROTO_UDP, INADDR_ANY, udp_port, - UDP_TO_BSC, udp_fd_cb, ipbc); - if (ret < 0) - goto err_udp_bsc; - DEBUGP(DLINP, "(%u/%u/%u) Created UDP socket for injection " - "towards BSC at port %u\n", site_id, bts_id, trx_id, udp_port); - - - /* GPRS NS related code */ - if (gprs_ns_ipaddr) { - struct sockaddr_in sock; - socklen_t len = sizeof(sock); - struct in_addr addr; - uint32_t ip; - - inet_aton(listen_ipaddr, &addr); - ip = ntohl(addr.s_addr); /* make_sock() needs host byte order */ - ret = make_sock(&ipbc->gprs_ns_fd, IPPROTO_UDP, ip, 0, 0, - gprs_ns_cb, ipbc); - if (ret < 0) { - LOGP(DLINP, LOGL_ERROR, "Creating the GPRS socket failed.\n"); - goto err_udp_bsc; - } - - ret = getsockname(ipbc->gprs_ns_fd.fd, (struct sockaddr* ) &sock, &len); - ipbc->gprs_local_port = ntohs(sock.sin_port); - LOGP(DLINP, LOGL_NOTICE, - "Created GPRS NS Socket. Listening on: %s:%d\n", - inet_ntoa(sock.sin_addr), ipbc->gprs_local_port); - - ret = getpeername(bfd->fd, (struct sockaddr* ) &sock, &len); - ipbc->bts_addr = sock.sin_addr; - } - - llist_add(&ipbc->list, &ipp->bts_list); - - return 0; - -err_udp_bsc: - osmo_fd_unregister(&ipbc->udp_bts_fd); -err_udp_bts: - osmo_fd_unregister(&ipbc->bsc_oml_conn->fd); - close(ipbc->bsc_oml_conn->fd.fd); - talloc_free(ipbc->bsc_oml_conn); - ipbc->bsc_oml_conn = NULL; -err_bsc_conn: - talloc_free(ipbc->id_resp); - talloc_free(ipbc); -#if 0 - osmo_fd_unregister(bfd); - close(bfd->fd); - talloc_free(bfd); -#endif -err_out: - return ret; -} - -static int ipaccess_rcvmsg(struct ipa_proxy_conn *ipc, struct msgb *msg, - struct osmo_fd *bfd) -{ - struct tlv_parsed tlvp; - uint8_t msg_type = *(msg->l2h); - struct ipaccess_unit unit_data; - struct ipa_bts_conn *ipbc; - int ret = 0; - - switch (msg_type) { - case IPAC_MSGT_PING: - ret = ipa_ccm_send_pong(bfd->fd); - break; - case IPAC_MSGT_PONG: - DEBUGP(DLMI, "PONG!\n"); - break; - case IPAC_MSGT_ID_RESP: - DEBUGP(DLMI, "ID_RESP "); - /* parse tags, search for Unit ID */ - ipa_ccm_idtag_parse(&tlvp, (uint8_t *)msg->l2h + 2, - msgb_l2len(msg)-2); - DEBUGP(DLMI, "\n"); - - if (!TLVP_PRESENT(&tlvp, IPAC_IDTAG_UNIT)) { - LOGP(DLINP, LOGL_ERROR, "No Unit ID in ID RESPONSE !?!\n"); - return -EIO; - } - - /* lookup BTS, create sign_link, ... */ - memset(&unit_data, 0, sizeof(unit_data)); - ipa_parse_unitid((char *)TLVP_VAL(&tlvp, IPAC_IDTAG_UNIT), - &unit_data); - ipbc = find_bts_by_unitid(ipp, unit_data.site_id, unit_data.bts_id); - if (!ipbc) { - /* We have not found an ipbc (per-bts proxy instance) - * for this BTS yet. The first connection of a new BTS must - * be a OML connection. We allocate the associated data structures, - * and try to connect to the remote end */ - - return ipbc_alloc_connect(ipc, bfd, unit_data.site_id, - unit_data.bts_id, - unit_data.trx_id, &tlvp, msg); - /* if this fails, the caller will clean up bfd */ - } else { - struct sockaddr_in sin; - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - inet_aton(bsc_ipaddr, &sin.sin_addr); - - DEBUGP(DLINP, "Identified BTS %u/%u/%u\n", - unit_data.site_id, unit_data.bts_id, unit_data.trx_id); - - if ((bfd->priv_nr & 0xff) != RSL_FROM_BTS) { - LOGP(DLINP, LOGL_ERROR, "Second OML connection from " - "same BTS ?!?\n"); - return 0; - } - - if (unit_data.trx_id >= MAX_TRX) { - LOGP(DLINP, LOGL_ERROR, "We don't support more " - "than %u TRX\n", MAX_TRX); - return -EINVAL; - } - - ipc->bts_conn = ipbc; - /* store TRX number in higher 8 bit of the bfd private number */ - bfd->priv_nr |= unit_data.trx_id << 8; - ipbc->rsl_conn[unit_data.trx_id] = ipc; - - /* Create RSL TCP connection towards BSC */ - sin.sin_port = htons(IPA_TCP_PORT_RSL); - ipbc->bsc_rsl_conn[unit_data.trx_id] = - connect_bsc(&sin, RSL_TO_BSC | (unit_data.trx_id << 8), ipbc); - if (!ipbc->bsc_oml_conn) - return -EIO; - DEBUGP(DLINP, "(%u/%u/%u) Connected RSL to BSC\n", - unit_data.site_id, unit_data.bts_id, unit_data.trx_id); - } - break; - case IPAC_MSGT_ID_GET: - DEBUGP(DLMI, "ID_GET\n"); - if ((bfd->priv_nr & 0xff) != OML_TO_BSC && - (bfd->priv_nr & 0xff) != RSL_TO_BSC) { - DEBUGP(DLINP, "IDentity REQuest from BTS ?!?\n"); - return -EIO; - } - ipbc = ipc->bts_conn; - if (!ipbc) { - DEBUGP(DLINP, "ID_GET from BSC before we have ID_RESP from BTS\n"); - return -EIO; - } - ret = write(bfd->fd, ipbc->id_resp, ipbc->id_resp_len); - if (ret != ipbc->id_resp_len) { - LOGP(DLINP, LOGL_ERROR, "Partial write: %d of %d\n", - ret, ipbc->id_resp_len); - return -EIO; - } - ret = 0; - break; - case IPAC_MSGT_ID_ACK: - DEBUGP(DLMI, "ID_ACK? -> ACK!\n"); - ret = ipa_ccm_send_id_ack(bfd->fd); - break; - default: - LOGP(DLMI, LOGL_ERROR, "Unhandled IPA type; %d\n", msg_type); - return 1; - break; - } - return ret; -} - -struct msgb *ipaccess_proxy_read_msg(struct osmo_fd *bfd, int *error) -{ - struct msgb *msg = msgb_alloc(PROXY_ALLOC_SIZE, "Abis/IP"); - struct ipaccess_head *hh; - int len, ret = 0; - - if (!msg) { - *error = -ENOMEM; - return NULL; - } - - /* first read our 3-byte header */ - hh = (struct ipaccess_head *) msg->data; - ret = recv(bfd->fd, msg->data, 3, 0); - if (ret < 0) { - if (errno != EAGAIN) - LOGP(DLINP, LOGL_ERROR, "recv error: %s\n", strerror(errno)); - msgb_free(msg); - *error = ret; - return NULL; - } else if (ret == 0) { - msgb_free(msg); - *error = ret; - return NULL; - } - - msgb_put(msg, ret); - - /* then read te length as specified in header */ - msg->l2h = msg->data + sizeof(*hh); - len = ntohs(hh->len); - ret = recv(bfd->fd, msg->l2h, len, 0); - if (ret < len) { - LOGP(DLINP, LOGL_ERROR, "short read!\n"); - msgb_free(msg); - *error = -EIO; - return NULL; - } - msgb_put(msg, ret); - - return msg; -} - -static struct ipa_proxy_conn *ipc_by_priv_nr(struct ipa_bts_conn *ipbc, - unsigned int priv_nr) -{ - struct ipa_proxy_conn *bsc_conn; - unsigned int trx_id = priv_nr >> 8; - - switch (priv_nr & 0xff) { - case OML_FROM_BTS: /* incoming OML data from BTS, forward to BSC OML */ - bsc_conn = ipbc->bsc_oml_conn; - break; - case RSL_FROM_BTS: /* incoming RSL data from BTS, forward to BSC RSL */ - bsc_conn = ipbc->bsc_rsl_conn[trx_id]; - break; - case OML_TO_BSC: /* incoming OML data from BSC, forward to BTS OML */ - bsc_conn = ipbc->oml_conn; - break; - case RSL_TO_BSC: /* incoming RSL data from BSC, forward to BTS RSL */ - bsc_conn = ipbc->rsl_conn[trx_id]; - break; - default: - bsc_conn = NULL; - break; - } - return bsc_conn; -} - -static void reconn_tmr_cb(void *data) -{ - struct ipa_proxy *ipp = data; - struct ipa_bts_conn *ipbc; - struct sockaddr_in sin; - int i; - - DEBUGP(DLINP, "Running reconnect timer\n"); - - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - inet_aton(bsc_ipaddr, &sin.sin_addr); - - llist_for_each_entry(ipbc, &ipp->bts_list, list) { - /* if OML to BSC is dead, try to restore it */ - if (ipbc->oml_conn && !ipbc->bsc_oml_conn) { - sin.sin_port = htons(IPA_TCP_PORT_OML); - logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, 0); - LOGPC(DLINP, LOGL_NOTICE, "OML Trying to reconnect\n"); - ipbc->bsc_oml_conn = connect_bsc(&sin, OML_TO_BSC, ipbc); - if (!ipbc->bsc_oml_conn) - goto reschedule; - logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, 0); - LOGPC(DLINP, LOGL_NOTICE, "OML Reconnected\n"); - } - /* if we (still) don't have a OML connection, skip RSL */ - if (!ipbc->oml_conn || !ipbc->bsc_oml_conn) - continue; - - for (i = 0; i < ARRAY_SIZE(ipbc->rsl_conn); i++) { - unsigned int priv_nr; - /* don't establish RSL links which we don't have */ - if (!ipbc->rsl_conn[i]) - continue; - if (ipbc->bsc_rsl_conn[i]) - continue; - priv_nr = ipbc->rsl_conn[i]->fd.priv_nr; - priv_nr &= ~0xff; - priv_nr |= RSL_TO_BSC; - sin.sin_port = htons(IPA_TCP_PORT_RSL); - logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, priv_nr >> 8); - LOGPC(DLINP, LOGL_NOTICE, "RSL Trying to reconnect\n"); - ipbc->bsc_rsl_conn[i] = connect_bsc(&sin, priv_nr, ipbc); - if (!ipbc->bsc_rsl_conn[i]) - goto reschedule; - logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, priv_nr >> 8); - LOGPC(DLINP, LOGL_NOTICE, "RSL Reconnected\n"); - } - } - return; - -reschedule: - osmo_timer_schedule(&ipp->reconn_timer, 5, 0); -} - -static void handle_dead_socket(struct osmo_fd *bfd) -{ - struct ipa_proxy_conn *ipc = bfd->data; /* local conn */ - struct ipa_proxy_conn *bsc_conn; /* remote conn */ - struct ipa_bts_conn *ipbc = ipc->bts_conn; - unsigned int trx_id = bfd->priv_nr >> 8; - struct msgb *msg, *msg2; - - osmo_fd_unregister(bfd); - close(bfd->fd); - bfd->fd = -1; - - /* FIXME: clear tx_queue, remove all references, etc. */ - llist_for_each_entry_safe(msg, msg2, &ipc->tx_queue, list) - msgb_free(msg); - - switch (bfd->priv_nr & 0xff) { - case OML_FROM_BTS: /* incoming OML data from BTS, forward to BSC OML */ - /* The BTS started a connection with us but we got no - * IPAC_MSGT_ID_RESP message yet, in that scenario we did not - * allocate the ipa_bts_conn structure. */ - if (ipbc == NULL) - break; - ipbc->oml_conn = NULL; - bsc_conn = ipbc->bsc_oml_conn; - /* close the connection to the BSC */ - osmo_fd_unregister(&bsc_conn->fd); - close(bsc_conn->fd.fd); - llist_for_each_entry_safe(msg, msg2, &bsc_conn->tx_queue, list) - msgb_free(msg); - talloc_free(bsc_conn); - ipbc->bsc_oml_conn = NULL; - /* FIXME: do we need to delete the entire ipbc ? */ - break; - case RSL_FROM_BTS: /* incoming RSL data from BTS, forward to BSC RSL */ - ipbc->rsl_conn[trx_id] = NULL; - bsc_conn = ipbc->bsc_rsl_conn[trx_id]; - /* close the connection to the BSC */ - osmo_fd_unregister(&bsc_conn->fd); - close(bsc_conn->fd.fd); - llist_for_each_entry_safe(msg, msg2, &bsc_conn->tx_queue, list) - msgb_free(msg); - talloc_free(bsc_conn); - ipbc->bsc_rsl_conn[trx_id] = NULL; - break; - case OML_TO_BSC: /* incoming OML data from BSC, forward to BTS OML */ - ipbc->bsc_oml_conn = NULL; - bsc_conn = ipbc->oml_conn; - /* start reconnect timer */ - osmo_timer_schedule(&ipp->reconn_timer, 5, 0); - break; - case RSL_TO_BSC: /* incoming RSL data from BSC, forward to BTS RSL */ - ipbc->bsc_rsl_conn[trx_id] = NULL; - bsc_conn = ipbc->rsl_conn[trx_id]; - /* start reconnect timer */ - osmo_timer_schedule(&ipp->reconn_timer, 5, 0); - break; - default: - bsc_conn = NULL; - break; - } - - talloc_free(ipc); -} - -static void patch_gprs_msg(struct ipa_bts_conn *ipbc, int priv_nr, struct msgb *msg) -{ - uint8_t *nsvci; - - if ((priv_nr & 0xff) != OML_FROM_BTS && (priv_nr & 0xff) != OML_TO_BSC) - return; - - if (msgb_l2len(msg) != 39) - return; - - /* - * Check if this is a IPA Set Attribute or IPA Set Attribute ACK - * and if the FOM Class is GPRS NSVC0 and then we will patch it. - * - * The patch assumes the message looks like the one from the trace - * but we only match messages with a specific size anyway... So - * this hack should work just fine. - */ - - if (msg->l2h[0] == 0x10 && msg->l2h[1] == 0x80 && - msg->l2h[2] == 0x00 && msg->l2h[3] == 0x15 && - msg->l2h[18] == 0xf5 && msg->l2h[19] == 0xf2) { - nsvci = &msg->l2h[23]; - ipbc->gprs_orig_port = *(uint16_t *)(nsvci+8); - ipbc->gprs_orig_ip = *(uint32_t *)(nsvci+10); - *(uint16_t *)(nsvci+8) = htons(ipbc->gprs_local_port); - *(uint32_t *)(nsvci+10) = ipbc->ipp->listen_addr.s_addr; - } else if (msg->l2h[0] == 0x10 && msg->l2h[1] == 0x80 && - msg->l2h[2] == 0x00 && msg->l2h[3] == 0x15 && - msg->l2h[18] == 0xf6 && msg->l2h[19] == 0xf2) { - nsvci = &msg->l2h[23]; - *(uint16_t *)(nsvci+8) = ipbc->gprs_orig_port; - *(uint32_t *)(nsvci+10) = ipbc->gprs_orig_ip; - } -} - -static int handle_tcp_read(struct osmo_fd *bfd) -{ - struct ipa_proxy_conn *ipc = bfd->data; - struct ipa_bts_conn *ipbc = ipc->bts_conn; - struct ipa_proxy_conn *bsc_conn; - struct msgb *msg; - struct ipaccess_head *hh; - int ret = 0; - char *btsbsc; - - if ((bfd->priv_nr & 0xff) <= 2) - btsbsc = "BTS"; - else - btsbsc = "BSC"; - - msg = ipaccess_proxy_read_msg(bfd, &ret); - if (!msg) { - if (ret == 0) { - logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, bfd->priv_nr >> 8); - LOGPC(DLINP, LOGL_NOTICE, "%s disappeared, " - "dead socket\n", btsbsc); - handle_dead_socket(bfd); - } - return ret; - } - - msgb_put(msg, ret); - logp_ipbc_uid(DLMI, LOGL_DEBUG, ipbc, bfd->priv_nr >> 8); - DEBUGPC(DLMI, "RX<-%s: %s\n", btsbsc, osmo_hexdump(msg->data, msg->len)); - - hh = (struct ipaccess_head *) msg->data; - if (hh->proto == IPAC_PROTO_IPACCESS) { - ret = ipaccess_rcvmsg(ipc, msg, bfd); - if (ret < 0) { - osmo_fd_unregister(bfd); - close(bfd->fd); - bfd->fd = -1; - talloc_free(bfd); - msgb_free(msg); - return ret; - } else if (ret == 0) { - /* we do not forward parts of the CCM protocol - * through the proxy but rather terminate it ourselves. */ - msgb_free(msg); - return ret; - } - } - - if (!ipbc) { - LOGP(DLINP, LOGL_ERROR, - "received %s packet but no ipc->bts_conn?!?\n", btsbsc); - msgb_free(msg); - return -EIO; - } - - bsc_conn = ipc_by_priv_nr(ipbc, bfd->priv_nr); - if (bsc_conn) { - if (gprs_ns_ipaddr) - patch_gprs_msg(ipbc, bfd->priv_nr, msg); - /* enqueue packet towards BSC */ - msgb_enqueue(&bsc_conn->tx_queue, msg); - /* mark respective filedescriptor as 'we want to write' */ - bsc_conn->fd.when |= BSC_FD_WRITE; - } else { - logp_ipbc_uid(DLINP, LOGL_INFO, ipbc, bfd->priv_nr >> 8); - LOGPC(DLINP, LOGL_INFO, "Dropping packet from %s, " - "since remote connection is dead\n", btsbsc); - msgb_free(msg); - } - - return ret; -} - -/* a TCP socket is ready to be written to */ -static int handle_tcp_write(struct osmo_fd *bfd) -{ - struct ipa_proxy_conn *ipc = bfd->data; - struct ipa_bts_conn *ipbc = ipc->bts_conn; - struct llist_head *lh; - struct msgb *msg; - char *btsbsc; - int ret; - - if ((bfd->priv_nr & 0xff) <= 2) - btsbsc = "BTS"; - else - btsbsc = "BSC"; - - - /* get the next msg for this timeslot */ - if (llist_empty(&ipc->tx_queue)) { - bfd->when &= ~BSC_FD_WRITE; - return 0; - } - lh = ipc->tx_queue.next; - llist_del(lh); - msg = llist_entry(lh, struct msgb, list); - - logp_ipbc_uid(DLMI, LOGL_DEBUG, ipbc, bfd->priv_nr >> 8); - DEBUGPC(DLMI, "TX %04x: %s\n", bfd->priv_nr, - osmo_hexdump(msg->data, msg->len)); - - ret = send(bfd->fd, msg->data, msg->len, 0); - msgb_free(msg); - - if (ret == 0) { - logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, bfd->priv_nr >> 8); - LOGP(DLINP, LOGL_NOTICE, "%s disappeared, dead socket\n", btsbsc); - handle_dead_socket(bfd); - } - - return ret; -} - -/* callback from select.c in case one of the fd's can be read/written */ -static int proxy_ipaccess_fd_cb(struct osmo_fd *bfd, unsigned int what) -{ - int rc = 0; - - if (what & BSC_FD_READ) { - rc = handle_tcp_read(bfd); - if (rc < 0) - return rc; - } - if (what & BSC_FD_WRITE) - rc = handle_tcp_write(bfd); - - return rc; -} - -/* callback of the listening filedescriptor */ -static int listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what) -{ - int ret; - struct ipa_proxy_conn *ipc; - struct osmo_fd *bfd; - struct sockaddr_in sa; - socklen_t sa_len = sizeof(sa); - - if (!(what & BSC_FD_READ)) - return 0; - - ret = accept(listen_bfd->fd, (struct sockaddr *) &sa, &sa_len); - if (ret < 0) { - perror("accept"); - return ret; - } - DEBUGP(DLINP, "accept()ed new %s link from %s\n", - (listen_bfd->priv_nr & 0xff) == OML_FROM_BTS ? "OML" : "RSL", - inet_ntoa(sa.sin_addr)); - - ipc = alloc_conn(); - if (!ipc) { - close(ret); - return -ENOMEM; - } - - bfd = &ipc->fd; - bfd->fd = ret; - bfd->data = ipc; - bfd->priv_nr = listen_bfd->priv_nr; - bfd->cb = proxy_ipaccess_fd_cb; - bfd->when = BSC_FD_READ; - ret = osmo_fd_register(bfd); - if (ret < 0) { - LOGP(DLINP, LOGL_ERROR, "could not register FD\n"); - close(bfd->fd); - talloc_free(ipc); - return ret; - } - - /* Request ID. FIXME: request LOCATION, HW/SW VErsion, Unit Name, Serno */ - ret = ipa_ccm_send_id_req(bfd->fd); - - return 0; -} - -static void send_ns(int fd, const char *buf, int size, struct in_addr ip, int port) -{ - int ret; - struct sockaddr_in addr; - socklen_t len = sizeof(addr); - memset(&addr, 0, sizeof(addr)); - - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr = ip; - - ret = sendto(fd, buf, size, 0, (struct sockaddr *) &addr, len); - if (ret < 0) { - LOGP(DLINP, LOGL_ERROR, "Failed to forward GPRS message.\n"); - } -} - -static int gprs_ns_cb(struct osmo_fd *bfd, unsigned int what) -{ - struct ipa_bts_conn *bts; - char buf[4096]; - int ret; - struct sockaddr_in sock; - socklen_t len = sizeof(sock); - - /* 1. get the data... */ - ret = recvfrom(bfd->fd, buf, sizeof(buf), 0, (struct sockaddr *) &sock, &len); - if (ret < 0) { - LOGP(DLINP, LOGL_ERROR, "Failed to recv GPRS NS msg: %s.\n", strerror(errno)); - return -1; - } - - bts = bfd->data; - - /* 2. figure out where to send it to */ - if (memcmp(&sock.sin_addr, &ipp->gprs_addr, sizeof(sock.sin_addr)) == 0) { - LOGP(DLINP, LOGL_DEBUG, "GPRS NS msg from network.\n"); - send_ns(bfd->fd, buf, ret, bts->bts_addr, 23000); - } else if (memcmp(&sock.sin_addr, &bts->bts_addr, sizeof(sock.sin_addr)) == 0) { - LOGP(DLINP, LOGL_DEBUG, "GPRS NS msg from BTS.\n"); - send_ns(bfd->fd, buf, ret, ipp->gprs_addr, 23000); - } else { - LOGP(DLINP, LOGL_ERROR, "Unknown GPRS source: %s\n", inet_ntoa(sock.sin_addr)); - } - - return 0; -} - -/* Actively connect to a BSC. */ -static struct ipa_proxy_conn *connect_bsc(struct sockaddr_in *sa, int priv_nr, void *data) -{ - struct ipa_proxy_conn *ipc; - struct osmo_fd *bfd; - int ret, on = 1; - - ipc = alloc_conn(); - if (!ipc) - return NULL; - - ipc->bts_conn = data; - - bfd = &ipc->fd; - bfd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - bfd->cb = ipaccess_fd_cb; - bfd->when = BSC_FD_READ | BSC_FD_WRITE; - bfd->data = ipc; - bfd->priv_nr = priv_nr; - - if (bfd->fd < 0) { - LOGP(DLINP, LOGL_ERROR, "Could not create socket: %s\n", - strerror(errno)); - talloc_free(ipc); - return NULL; - } - - ret = setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); - if (ret < 0) { - LOGP(DLINP, LOGL_ERROR, "Could not set socket option\n"); - close(bfd->fd); - talloc_free(ipc); - return NULL; - } - - ret = connect(bfd->fd, (struct sockaddr *) sa, sizeof(*sa)); - if (ret < 0) { - LOGP(DLINP, LOGL_ERROR, "Could not connect socket: %s\n", - inet_ntoa(sa->sin_addr)); - close(bfd->fd); - talloc_free(ipc); - return NULL; - } - - /* pre-fill tx_queue with identity request */ - ret = osmo_fd_register(bfd); - if (ret < 0) { - close(bfd->fd); - talloc_free(ipc); - return NULL; - } - - return ipc; -} - -static int ipaccess_proxy_setup(void) -{ - int ret; - - ipp = talloc_zero(tall_bsc_ctx, struct ipa_proxy); - if (!ipp) - return -ENOMEM; - INIT_LLIST_HEAD(&ipp->bts_list); - osmo_timer_setup(&ipp->reconn_timer, reconn_tmr_cb, ipp); - - /* Listen for OML connections */ - ret = make_sock(&ipp->oml_listen_fd, IPPROTO_TCP, INADDR_ANY, - IPA_TCP_PORT_OML, OML_FROM_BTS, listen_fd_cb, NULL); - if (ret < 0) - return ret; - - /* Listen for RSL connections */ - ret = make_sock(&ipp->rsl_listen_fd, IPPROTO_TCP, INADDR_ANY, - IPA_TCP_PORT_RSL, RSL_FROM_BTS, listen_fd_cb, NULL); - - if (ret < 0) - return ret; - - /* Connect the GPRS NS Socket */ - if (gprs_ns_ipaddr) { - inet_aton(gprs_ns_ipaddr, &ipp->gprs_addr); - inet_aton(listen_ipaddr, &ipp->listen_addr); - } - - return ret; -} - -static void signal_handler(int signal) -{ - fprintf(stdout, "signal %u received\n", signal); - - switch (signal) { - case SIGABRT: - /* in case of abort, we want to obtain a talloc report - * and then return to the caller, who will abort the process */ - case SIGUSR1: - talloc_report_full(tall_bsc_ctx, stderr); - break; - default: - break; - } -} - -static void print_help(void) -{ - printf(" ipaccess-proxy is a proxy BTS.\n"); - printf(" -h --help. This help text.\n"); - printf(" -l --listen IP. The ip to listen to.\n"); - printf(" -b --bsc IP. The BSC IP address.\n"); - printf(" -g --gprs IP. Take GPRS NS from that IP.\n"); - printf("\n"); - printf(" -s --disable-color. Disable the color inside the logging message.\n"); - printf(" -e --log-level number. Set the global loglevel.\n"); - printf(" -T --timestamp. Prefix every log message with a timestamp.\n"); - printf(" -V --version. Print the version of OpenBSC.\n"); -} - -static void print_usage(void) -{ - printf("Usage: ipaccess-proxy [options]\n"); -} - -enum { - IPA_PROXY_OPT_LISTEN_NONE = 0, - IPA_PROXY_OPT_LISTEN_IP = (1 << 0), - IPA_PROXY_OPT_BSC_IP = (1 << 1), -}; - -static void handle_options(int argc, char** argv) -{ - int options_mask = 0; - - /* disable explicit missing arguments error output from getopt_long */ - opterr = 0; - - while (1) { - int option_index = 0, c; - static struct option long_options[] = { - {"help", 0, 0, 'h'}, - {"disable-color", 0, 0, 's'}, - {"timestamp", 0, 0, 'T'}, - {"log-level", 1, 0, 'e'}, - {"listen", 1, 0, 'l'}, - {"bsc", 1, 0, 'b'}, - {0, 0, 0, 0} - }; - - c = getopt_long(argc, argv, "hsTe:l:b:g:", - long_options, &option_index); - if (c == -1) - break; - - switch (c) { - case 'h': - print_usage(); - print_help(); - exit(0); - case 'l': - listen_ipaddr = optarg; - options_mask |= IPA_PROXY_OPT_LISTEN_IP; - break; - case 'b': - bsc_ipaddr = optarg; - options_mask |= IPA_PROXY_OPT_BSC_IP; - break; - case 'g': - gprs_ns_ipaddr = optarg; - break; - case 's': - log_set_use_color(osmo_stderr_target, 0); - break; - case 'T': - log_set_print_timestamp(osmo_stderr_target, 1); - break; - case 'e': - log_set_log_level(osmo_stderr_target, atoi(optarg)); - break; - case '?': - if (optopt) { - printf("ERROR: missing mandatory argument " - "for `%s' option\n", argv[optind-1]); - } else { - printf("ERROR: unknown option `%s'\n", - argv[optind-1]); - } - print_usage(); - print_help(); - exit(EXIT_FAILURE); - break; - default: - /* ignore */ - break; - } - } - if ((options_mask & (IPA_PROXY_OPT_LISTEN_IP | IPA_PROXY_OPT_BSC_IP)) - != (IPA_PROXY_OPT_LISTEN_IP | IPA_PROXY_OPT_BSC_IP)) { - printf("ERROR: You have to specify `--listen' and `--bsc' " - "options at least.\n"); - print_usage(); - print_help(); - exit(EXIT_FAILURE); - } -} - -int main(int argc, char **argv) -{ - int rc; - - tall_bsc_ctx = talloc_named_const(NULL, 1, "ipaccess-proxy"); - msgb_talloc_ctx_init(tall_bsc_ctx, 0); - - osmo_init_logging(&log_info); - log_parse_category_mask(osmo_stderr_target, "DLINP:DLMI"); - - handle_options(argc, argv); - - rc = ipaccess_proxy_setup(); - if (rc < 0) - exit(1); - - signal(SIGUSR1, &signal_handler); - signal(SIGABRT, &signal_handler); - osmo_init_ignore_signals(); - - while (1) { - osmo_select_main(0); - } -} diff --git a/src/ipaccess/network_listen.c b/src/ipaccess/network_listen.c deleted file mode 100644 index 3b44ceb74..000000000 --- a/src/ipaccess/network_listen.c +++ /dev/null @@ -1,257 +0,0 @@ -/* ip.access nanoBTS network listen mode */ - -/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org> - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <stdint.h> - -#include <arpa/inet.h> - -#include <osmocom/core/talloc.h> -#include <osmocom/core/timer.h> -#include <osmocom/gsm/rxlev_stat.h> -#include <osmocom/gsm/gsm48_ie.h> - -#include <openbsc/gsm_data.h> -#include <openbsc/abis_nm.h> -#include <openbsc/signal.h> -#include <openbsc/debug.h> -#include <osmocom/abis/e1_input.h> - -#define WHITELIST_MAX_SIZE ((NUM_ARFCNS*2)+2+1) - -int ipac_rxlevstat2whitelist(uint16_t *buf, const struct rxlev_stats *st, uint8_t min_rxlev, - uint16_t max_num_arfcns) -{ - int i; - unsigned int num_arfcn = 0; - - for (i = NUM_RXLEVS-1; i >= min_rxlev; i--) { - int16_t arfcn = -1; - - while ((arfcn = rxlev_stat_get_next(st, i, arfcn)) >= 0) { - *buf++ = htons(arfcn); - num_arfcn++; - - } - - if (num_arfcn > max_num_arfcns) - break; - } - - return num_arfcn; -} - -enum ipac_test_state { - IPAC_TEST_S_IDLE, - IPAC_TEST_S_RQD, - IPAC_TEST_S_EXEC, - IPAC_TEST_S_PARTIAL, -}; - -int ipac_nwl_test_start(struct gsm_bts_trx *trx, uint8_t testnr, - const uint8_t *phys_conf, unsigned int phys_conf_len) -{ - struct msgb *msg; - - if (trx->ipaccess.test_state != IPAC_TEST_S_IDLE) { - fprintf(stderr, "Cannot start test in state %u\n", trx->ipaccess.test_state); - return -EINVAL; - } - - switch (testnr) { - case NM_IPACC_TESTNO_CHAN_USAGE: - case NM_IPACC_TESTNO_BCCH_CHAN_USAGE: - rxlev_stat_reset(&trx->ipaccess.rxlev_stat); - break; - } - - msg = msgb_alloc_headroom(phys_conf_len+256, 128, "OML"); - - if (phys_conf && phys_conf_len) { - uint8_t *payload; - /* first put the phys conf header */ - msgb_tv16_put(msg, NM_ATT_PHYS_CONF, phys_conf_len); - payload = msgb_put(msg, phys_conf_len); - memcpy(payload, phys_conf, phys_conf_len); - } - - abis_nm_perform_test(trx->bts, NM_OC_RADIO_CARRIER, 0, trx->nr, 0xff, - testnr, 1, msg); - trx->ipaccess.test_nr = testnr; - - /* FIXME: start safety timer until when test is supposed to complete */ - - return 0; -} - -static uint16_t last_arfcn; -static struct gsm_sysinfo_freq nwl_si_freq[1024]; -#define FREQ_TYPE_NCELL_2 0x04 /* sub channel of SI 2 */ -#define FREQ_TYPE_NCELL_2bis 0x08 /* sub channel of SI 2bis */ -#define FREQ_TYPE_NCELL_2ter 0x10 /* sub channel of SI 2ter */ - -struct ipacc_ferr_elem { - int16_t freq_err; - uint8_t freq_qual; - uint8_t arfcn; -} __attribute__((packed)); - -struct ipacc_cusage_elem { - uint16_t arfcn:10, - rxlev:6; -} __attribute__ ((packed)); - -static int test_rep(void *_msg) -{ - struct msgb *msg = _msg; - struct abis_om_fom_hdr *foh = msgb_l3(msg); - uint16_t test_rep_len, ferr_list_len; - struct ipacc_ferr_elem *ife; - struct ipac_bcch_info binfo; - struct e1inp_sign_link *sign_link = (struct e1inp_sign_link *)msg->dst; - int i, rc; - - DEBUGP(DNM, "TEST REPORT: "); - - if (foh->data[0] != NM_ATT_TEST_NO || - foh->data[2] != NM_ATT_TEST_REPORT) - return -EINVAL; - - DEBUGPC(DNM, "test_no=0x%02x ", foh->data[1]); - /* data[2] == NM_ATT_TEST_REPORT */ - /* data[3..4]: test_rep_len */ - memcpy(&test_rep_len, &foh->data[3], sizeof(uint16_t)); - test_rep_len = ntohs(test_rep_len); - /* data[5]: ip.access test result */ - DEBUGPC(DNM, "tst_res=%s\n", ipacc_testres_name(foh->data[5])); - - /* data[6]: ip.access nested IE. 3 == freq_err_list */ - switch (foh->data[6]) { - case NM_IPAC_EIE_FREQ_ERR_LIST: - /* data[7..8]: length of ferr_list */ - memcpy(&ferr_list_len, &foh->data[7], sizeof(uint16_t)); - ferr_list_len = ntohs(ferr_list_len); - - /* data[9...]: frequency error list elements */ - for (i = 0; i < ferr_list_len; i+= sizeof(*ife)) { - ife = (struct ipacc_ferr_elem *) (foh->data + 9 + i); - DEBUGP(DNM, "==> ARFCN %4u, Frequency Error %6hd\n", - ife->arfcn, ntohs(ife->freq_err)); - } - break; - case NM_IPAC_EIE_CHAN_USE_LIST: - /* data[7..8]: length of ferr_list */ - memcpy(&ferr_list_len, &foh->data[7], sizeof(uint16_t)); - ferr_list_len = ntohs(ferr_list_len); - - /* data[9...]: channel usage list elements */ - for (i = 0; i < ferr_list_len; i+= 2) { - uint16_t *cu_ptr = (uint16_t *)(foh->data + 9 + i); - uint16_t cu = ntohs(*cu_ptr); - uint16_t arfcn = cu & 0x3ff; - uint8_t rxlev = cu >> 10; - DEBUGP(DNM, "==> ARFCN %4u, RxLev %2u\n", arfcn, rxlev); - rxlev_stat_input(&sign_link->trx->ipaccess.rxlev_stat, - arfcn, rxlev); - } - break; - case NM_IPAC_EIE_BCCH_INFO_TYPE: - break; - case NM_IPAC_EIE_BCCH_INFO: - rc = ipac_parse_bcch_info(&binfo, foh->data+6); - if (rc < 0) { - DEBUGP(DNM, "BCCH Info parsing failed\n"); - break; - } - DEBUGP(DNM, "==> ARFCN %u, RxLev %2u, RxQual %2u: %3d-%d, LAC %d CI %d BSIC %u\n", - binfo.arfcn, binfo.rx_lev, binfo.rx_qual, - binfo.cgi.mcc, binfo.cgi.mnc, - binfo.cgi.lac, binfo.cgi.ci, binfo.bsic); - - if (binfo.arfcn != last_arfcn) { - /* report is on a new arfcn, need to clear channel list */ - memset(nwl_si_freq, 0, sizeof(nwl_si_freq)); - last_arfcn = binfo.arfcn; - } - if (binfo.info_type & IPAC_BINF_NEIGH_BA_SI2) { - DEBUGP(DNM, "BA SI2: %s\n", osmo_hexdump(binfo.ba_list_si2, sizeof(binfo.ba_list_si2))); - gsm48_decode_freq_list(nwl_si_freq, binfo.ba_list_si2, sizeof(binfo.ba_list_si2), - 0x8c, FREQ_TYPE_NCELL_2); - } - if (binfo.info_type & IPAC_BINF_NEIGH_BA_SI2bis) { - DEBUGP(DNM, "BA SI2bis: %s\n", osmo_hexdump(binfo.ba_list_si2bis, sizeof(binfo.ba_list_si2bis))); - gsm48_decode_freq_list(nwl_si_freq, binfo.ba_list_si2bis, sizeof(binfo.ba_list_si2bis), - 0x8e, FREQ_TYPE_NCELL_2bis); - } - if (binfo.info_type & IPAC_BINF_NEIGH_BA_SI2ter) { - DEBUGP(DNM, "BA SI2ter: %s\n", osmo_hexdump(binfo.ba_list_si2ter, sizeof(binfo.ba_list_si2ter))); - gsm48_decode_freq_list(nwl_si_freq, binfo.ba_list_si2ter, sizeof(binfo.ba_list_si2ter), - 0x8e, FREQ_TYPE_NCELL_2ter); - } - for (i = 0; i < ARRAY_SIZE(nwl_si_freq); i++) { - if (nwl_si_freq[i].mask) - DEBUGP(DNM, "Neighbor Cell on ARFCN %u\n", i); - } - break; - default: - break; - } - - switch (foh->data[5]) { - case NM_IPACC_TESTRES_SUCCESS: - case NM_IPACC_TESTRES_STOPPED: - case NM_IPACC_TESTRES_TIMEOUT: - case NM_IPACC_TESTRES_NO_CHANS: - sign_link->trx->ipaccess.test_state = IPAC_TEST_S_IDLE; - /* Send signal to notify higher layers of test completion */ - DEBUGP(DNM, "dispatching S_IPAC_NWL_COMPLETE signal\n"); - osmo_signal_dispatch(SS_IPAC_NWL, S_IPAC_NWL_COMPLETE, - sign_link->trx); - break; - case NM_IPACC_TESTRES_PARTIAL: - sign_link->trx->ipaccess.test_state = IPAC_TEST_S_PARTIAL; - break; - } - - return 0; -} - -static int nwl_sig_cb(unsigned int subsys, unsigned int signal, - void *handler_data, void *signal_data) -{ - switch (signal) { - case S_NM_TEST_REP: - return test_rep(signal_data); - default: - break; - } - - return 0; -} - -void ipac_nwl_init(void) -{ - osmo_signal_register_handler(SS_NM, nwl_sig_cb, NULL); -} diff --git a/src/libbsc/Makefile.am b/src/libbsc/Makefile.am deleted file mode 100644 index e78bde624..000000000 --- a/src/libbsc/Makefile.am +++ /dev/null @@ -1,57 +0,0 @@ -AM_CPPFLAGS = \ - $(all_includes) \ - -I$(top_srcdir)/include \ - -I$(top_builddir) \ - $(NULL) - -AM_CFLAGS = \ - -Wall \ - $(LIBOSMOCORE_CFLAGS) \ - $(LIBOSMOGSM_CFLAGS) \ - $(LIBOSMOVTY_CFLAGS) \ - $(LIBOSMOABIS_CFLAGS) \ - $(COVERAGE_CFLAGS) \ - $(NULL) - -noinst_LIBRARIES = \ - libbsc.a \ - $(NULL) - -libbsc_a_SOURCES = \ - abis_nm.c \ - abis_nm_vty.c \ - abis_om2000.c \ - abis_om2000_vty.c \ - abis_rsl.c \ - bsc_rll.c \ - bsc_subscriber.c \ - paging.c \ - bts_ericsson_rbs2000.c \ - bts_ipaccess_nanobts.c \ - bts_siemens_bs11.c \ - bts_nokia_site.c \ - bts_unknown.c \ - bts_sysmobts.c \ - chan_alloc.c \ - handover_decision.c \ - handover_logic.c \ - meas_rep.c \ - pcu_sock.c \ - rest_octets.c \ - system_information.c \ - e1_config.c \ - bsc_api.c \ - bsc_msc.c bsc_vty.c \ - gsm_04_08_utils.c \ - gsm_04_80_utils.c \ - bsc_init.c \ - bts_init.c \ - bsc_rf_ctrl.c \ - arfcn_range_encode.c \ - bsc_ctrl_commands.c \ - bsc_ctrl_lookup.c \ - net_init.c \ - bsc_dyn_ts.c \ - bts_ipaccess_nanobts_omlattr.c \ - $(NULL) - diff --git a/src/libbsc/abis_nm.c b/src/libbsc/abis_nm.c deleted file mode 100644 index cf20d7c49..000000000 --- a/src/libbsc/abis_nm.c +++ /dev/null @@ -1,2924 +0,0 @@ -/* GSM Network Management (OML) 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 <laforge@gnumonks.org> - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - - -#include <errno.h> -#include <unistd.h> -#include <stdio.h> -#include <fcntl.h> -#include <stdlib.h> -#include <libgen.h> -#include <time.h> -#include <limits.h> - -#include <sys/stat.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <openbsc/gsm_data.h> -#include <openbsc/debug.h> -#include <osmocom/core/msgb.h> -#include <osmocom/gsm/protocol/gsm_12_21.h> -#include <osmocom/gsm/tlv.h> -#include <osmocom/gsm/abis_nm.h> -#include <osmocom/core/talloc.h> -#include <osmocom/core/utils.h> -#include <openbsc/abis_nm.h> -#include <openbsc/misdn.h> -#include <openbsc/signal.h> -#include <osmocom/abis/e1_input.h> - -#define OM_ALLOC_SIZE 1024 -#define OM_HEADROOM_SIZE 128 -#define IPACC_SEGMENT_SIZE 245 - -int abis_nm_tlv_parse(struct tlv_parsed *tp, struct gsm_bts *bts, const uint8_t *buf, int len) -{ - if (!bts->model) - return -EIO; - return tlv_parse(tp, &bts->model->nm_att_tlvdef, buf, len, 0, 0); -} - -static int is_in_arr(enum abis_nm_msgtype mt, const enum abis_nm_msgtype *arr, int size) -{ - int i; - - for (i = 0; i < size; i++) { - if (arr[i] == mt) - return 1; - } - - return 0; -} - -#if 0 -/* is this msgtype the usual ACK/NACK type ? */ -static int is_ack_nack(enum abis_nm_msgtype mt) -{ - return !is_in_arr(mt, no_ack_nack, ARRAY_SIZE(no_ack_nack)); -} -#endif - -/* is this msgtype a report ? */ -static int is_report(enum abis_nm_msgtype mt) -{ - return is_in_arr(mt, abis_nm_reports, ARRAY_SIZE(abis_nm_reports)); -} - -#define MT_ACK(x) (x+1) -#define MT_NACK(x) (x+2) - -static void fill_om_hdr(struct abis_om_hdr *oh, uint8_t len) -{ - oh->mdisc = ABIS_OM_MDISC_FOM; - oh->placement = ABIS_OM_PLACEMENT_ONLY; - oh->sequence = 0; - oh->length = len; -} - -static struct abis_om_fom_hdr *fill_om_fom_hdr(struct abis_om_hdr *oh, uint8_t len, - uint8_t msg_type, uint8_t obj_class, - uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr) -{ - struct abis_om_fom_hdr *foh = - (struct abis_om_fom_hdr *) oh->data; - - fill_om_hdr(oh, len+sizeof(*foh)); - foh->msg_type = msg_type; - foh->obj_class = obj_class; - foh->obj_inst.bts_nr = bts_nr; - foh->obj_inst.trx_nr = trx_nr; - foh->obj_inst.ts_nr = ts_nr; - return foh; -} - -static struct msgb *nm_msgb_alloc(void) -{ - return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, - "OML"); -} - -int _abis_nm_sendmsg(struct msgb *msg) -{ - msg->l2h = msg->data; - - if (!msg->dst) { - LOGP(DNM, LOGL_ERROR, "%s: msg->dst == NULL\n", __func__); - return -EINVAL; - } - - return abis_sendmsg(msg); -} - -/* Send a OML NM Message from BSC to BTS */ -static int abis_nm_queue_msg(struct gsm_bts *bts, struct msgb *msg) -{ - msg->dst = bts->oml_link; - - /* queue OML messages */ - if (llist_empty(&bts->abis_queue) && !bts->abis_nm_pend) { - bts->abis_nm_pend = OBSC_NM_W_ACK_CB(msg); - return _abis_nm_sendmsg(msg); - } else { - msgb_enqueue(&bts->abis_queue, msg); - return 0; - } - -} - -int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg) -{ - OBSC_NM_W_ACK_CB(msg) = 1; - return abis_nm_queue_msg(bts, msg); -} - -static int abis_nm_sendmsg_direct(struct gsm_bts *bts, struct msgb *msg) -{ - OBSC_NM_W_ACK_CB(msg) = 0; - return abis_nm_queue_msg(bts, msg); -} - -static int abis_nm_rcvmsg_sw(struct msgb *mb); - -int nm_is_running(struct gsm_nm_state *s) { - return (s->operational == NM_OPSTATE_ENABLED) && ( - (s->availability == NM_AVSTATE_OK) || - (s->availability == 0xff) - ); -} - -/* Update the administrative state of a given object in our in-memory data - * structures and send an event to the higher layer */ -static int update_admstate(struct gsm_bts *bts, uint8_t obj_class, - struct abis_om_obj_inst *obj_inst, uint8_t adm_state) -{ - struct gsm_nm_state *nm_state, new_state; - struct nm_statechg_signal_data nsd; - - memset(&nsd, 0, sizeof(nsd)); - - nsd.obj = gsm_objclass2obj(bts, obj_class, obj_inst); - if (!nsd.obj) - return -EINVAL; - nm_state = gsm_objclass2nmstate(bts, obj_class, obj_inst); - if (!nm_state) - return -1; - - new_state = *nm_state; - new_state.administrative = adm_state; - - nsd.bts = bts; - nsd.obj_class = obj_class; - nsd.old_state = nm_state; - nsd.new_state = &new_state; - nsd.obj_inst = obj_inst; - osmo_signal_dispatch(SS_NM, S_NM_STATECHG_ADM, &nsd); - - nm_state->administrative = adm_state; - - return 0; -} - -static int abis_nm_rx_statechg_rep(struct msgb *mb) -{ - struct abis_om_hdr *oh = msgb_l2(mb); - struct abis_om_fom_hdr *foh = msgb_l3(mb); - struct e1inp_sign_link *sign_link = mb->dst; - struct gsm_bts *bts = sign_link->trx->bts; - struct tlv_parsed tp; - struct gsm_nm_state *nm_state, new_state; - - DEBUGPC(DNM, "STATE CHG: "); - - memset(&new_state, 0, sizeof(new_state)); - - nm_state = gsm_objclass2nmstate(bts, foh->obj_class, &foh->obj_inst); - if (!nm_state) { - DEBUGPC(DNM, "unknown object class\n"); - return -EINVAL; - } - - new_state = *nm_state; - - abis_nm_tlv_parse(&tp, bts, foh->data, oh->length-sizeof(*foh)); - if (TLVP_PRESENT(&tp, NM_ATT_OPER_STATE)) { - new_state.operational = *TLVP_VAL(&tp, NM_ATT_OPER_STATE); - DEBUGPC(DNM, "OP_STATE=%s ", - abis_nm_opstate_name(new_state.operational)); - } - if (TLVP_PRESENT(&tp, NM_ATT_AVAIL_STATUS)) { - if (TLVP_LEN(&tp, NM_ATT_AVAIL_STATUS) == 0) - new_state.availability = 0xff; - else - new_state.availability = *TLVP_VAL(&tp, NM_ATT_AVAIL_STATUS); - DEBUGPC(DNM, "AVAIL=%s(%02x) ", - abis_nm_avail_name(new_state.availability), - new_state.availability); - } else - new_state.availability = 0xff; - if (TLVP_PRESENT(&tp, NM_ATT_ADM_STATE)) { - new_state.administrative = *TLVP_VAL(&tp, NM_ATT_ADM_STATE); - DEBUGPC(DNM, "ADM=%2s ", - get_value_string(abis_nm_adm_state_names, - new_state.administrative)); - } - DEBUGPC(DNM, "\n"); - - if ((new_state.administrative != 0 && nm_state->administrative == 0) || - new_state.operational != nm_state->operational || - new_state.availability != nm_state->availability) { - /* Update the operational state of a given object in our in-memory data - * structures and send an event to the higher layer */ - struct nm_statechg_signal_data nsd; - nsd.obj = gsm_objclass2obj(bts, foh->obj_class, &foh->obj_inst); - nsd.obj_class = foh->obj_class; - nsd.old_state = nm_state; - nsd.new_state = &new_state; - nsd.obj_inst = &foh->obj_inst; - nsd.bts = bts; - osmo_signal_dispatch(SS_NM, S_NM_STATECHG_OPER, &nsd); - nm_state->operational = new_state.operational; - nm_state->availability = new_state.availability; - if (nm_state->administrative == 0) - nm_state->administrative = new_state.administrative; - } -#if 0 - if (op_state == 1) { - /* try to enable objects that are disabled */ - abis_nm_opstart(bts, foh->obj_class, - foh->obj_inst.bts_nr, - foh->obj_inst.trx_nr, - foh->obj_inst.ts_nr); - } -#endif - return 0; -} - -static inline void log_oml_fail_rep(const struct gsm_bts *bts, const char *type, - const char *severity, const uint8_t *p_val, - const char *text) -{ - enum abis_nm_pcause_type pcause = p_val[0]; - enum abis_mm_event_causes cause = osmo_load16be(p_val + 1); - - LOGPC(DNM, LOGL_ERROR, "BTS %u: Failure Event Report: ", bts->nr); - if (type) - LOGPC(DNM, LOGL_ERROR, "Type=%s, ", type); - if (severity) - LOGPC(DNM, LOGL_ERROR, "Severity=%s, ", severity); - - LOGPC(DNM, LOGL_ERROR, "Probable cause=%s: ", - get_value_string(abis_nm_pcause_type_names, pcause)); - - if (pcause == NM_PCAUSE_T_MANUF) - LOGPC(DNM, LOGL_ERROR, "%s, ", - get_value_string(abis_mm_event_cause_names, cause)); - else - LOGPC(DNM, LOGL_ERROR, "%02X %02X ", p_val[1], p_val[2]); - - if (text) { - LOGPC(DNM, LOGL_ERROR, "Additional Text=%s. ", text); - } - - LOGPC(DNM, LOGL_ERROR, "\n"); -} - -static inline void handle_manufact_report(struct gsm_bts *bts, const uint8_t *p_val, const char *type, - const char *severity, const char *text) -{ - enum abis_mm_event_causes cause = osmo_load16be(p_val + 1); - - switch (cause) { - case OSMO_EVT_PCU_VERS: - if (text) { - LOGPC(DNM, LOGL_NOTICE, "BTS %u reported connected PCU version %s\n", bts->nr, text); - osmo_strlcpy(bts->pcu_version, text, sizeof(bts->pcu_version)); - } else { - LOGPC(DNM, LOGL_ERROR, "BTS %u reported PCU disconnection.\n", bts->nr); - bts->pcu_version[0] = '\0'; - } - break; - default: - log_oml_fail_rep(bts, type, severity, p_val, text); - }; -} - -static int rx_fail_evt_rep(struct msgb *mb, struct gsm_bts *bts) -{ - struct abis_om_hdr *oh = msgb_l2(mb); - struct abis_om_fom_hdr *foh = msgb_l3(mb); - struct e1inp_sign_link *sign_link = mb->dst; - struct tlv_parsed tp; - int rc = 0; - const uint8_t *p_val = NULL; - char *p_text = NULL; - const char *e_type = NULL, *severity = NULL; - - abis_nm_tlv_parse(&tp, sign_link->trx->bts, foh->data, - oh->length-sizeof(*foh)); - - if (TLVP_PRESENT(&tp, NM_ATT_ADD_TEXT)) { - p_val = TLVP_VAL(&tp, NM_ATT_ADD_TEXT); - p_text = talloc_strndup(tall_bsc_ctx, (const char *) p_val, - TLVP_LEN(&tp, NM_ATT_ADD_TEXT)); - } - - if (TLVP_PRESENT(&tp, NM_ATT_EVENT_TYPE)) - e_type = abis_nm_event_type_name(*TLVP_VAL(&tp, - NM_ATT_EVENT_TYPE)); - - if (TLVP_PRESENT(&tp, NM_ATT_SEVERITY)) - severity = abis_nm_severity_name(*TLVP_VAL(&tp, - NM_ATT_SEVERITY)); - - if (TLVP_PRESENT(&tp, NM_ATT_PROB_CAUSE)) { - p_val = TLVP_VAL(&tp, NM_ATT_PROB_CAUSE); - - switch (p_val[0]) { - case NM_PCAUSE_T_MANUF: - handle_manufact_report(bts, p_val, e_type, severity, - p_text); - break; - default: - log_oml_fail_rep(bts, e_type, severity, p_val, p_text); - }; - } else { - LOGPC(DNM, LOGL_ERROR, "BTS%u: Failure Event Report without " - "Probable Cause?!\n", bts->nr); - rc = -EINVAL; - } - - if (p_text) - talloc_free(p_text); - - return rc; -} - -static int abis_nm_rcvmsg_report(struct msgb *mb, struct gsm_bts *bts) -{ - struct abis_om_fom_hdr *foh = msgb_l3(mb); - uint8_t mt = foh->msg_type; - - abis_nm_debugp_foh(DNM, foh); - - //nmh->cfg->report_cb(mb, foh); - - switch (mt) { - case NM_MT_STATECHG_EVENT_REP: - return abis_nm_rx_statechg_rep(mb); - break; - case NM_MT_SW_ACTIVATED_REP: - DEBUGPC(DNM, "Software Activated Report\n"); - osmo_signal_dispatch(SS_NM, S_NM_SW_ACTIV_REP, mb); - break; - case NM_MT_FAILURE_EVENT_REP: - rx_fail_evt_rep(mb, bts); - osmo_signal_dispatch(SS_NM, S_NM_FAIL_REP, mb); - break; - case NM_MT_TEST_REP: - DEBUGPC(DNM, "Test Report\n"); - osmo_signal_dispatch(SS_NM, S_NM_TEST_REP, mb); - break; - default: - DEBUGPC(DNM, "reporting NM MT 0x%02x\n", mt); - break; - - }; - - return 0; -} - -/* Activate the specified software into the BTS */ -static int ipacc_sw_activate(struct gsm_bts *bts, uint8_t obj_class, uint8_t i0, uint8_t i1, - uint8_t i2, const struct abis_nm_sw_desc *sw_desc) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - uint16_t len = abis_nm_sw_desc_len(sw_desc, true); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, len, NM_MT_ACTIVATE_SW, obj_class, i0, i1, i2); - abis_nm_put_sw_desc(msg, sw_desc, true); - - return abis_nm_sendmsg(bts, msg); -} - -int abis_nm_select_newest_sw(const struct abis_nm_sw_desc *sw_descr, - const size_t size) -{ - int res = 0; - int i; - - for (i = 1; i < size; ++i) { - if (memcmp(sw_descr[res].file_version, sw_descr[i].file_version, - OSMO_MIN(sw_descr[i].file_version_len, - sw_descr[res].file_version_len)) < 0) { - res = i; - } - } - - return res; -} - -static inline bool handle_attr(const struct gsm_bts *bts, enum bts_attribute id, uint8_t *val, uint8_t len) -{ - switch (id) { - case BTS_TYPE_VARIANT: - LOGP(DNM, LOGL_NOTICE, "BTS%u reported variant: %s\n", bts->nr, val); - break; - case BTS_SUB_MODEL: - LOGP(DNM, LOGL_NOTICE, "BTS%u reported submodel: %s\n", bts->nr, val); - break; - default: - return false; - } - return true; -} - -/* Parse Attribute Response Info - return pointer to the actual content */ -static inline uint8_t *parse_attr_resp_info_unreported(uint8_t bts_nr, uint8_t *ari, uint16_t ari_len, uint16_t *out_len) -{ - uint8_t num_unreported = ari[0], i; - - DEBUGP(DNM, "BTS%u Get Attributes Response Info: %u bytes total with %u unreported attributes\n", - bts_nr, ari_len, num_unreported); - - /* +1 because we have to account for number of unreported attributes, prefixing the list: */ - for (i = 0; i < num_unreported; i++) - LOGP(DNM, LOGL_ERROR, "BTS%u Attribute %s is unreported\n", - bts_nr, get_value_string(abis_nm_att_names, ari[i + 1])); - - /* the data starts right after the list of unreported attributes + space for length of that list */ - *out_len = ari_len - (num_unreported + 2); - - return ari + num_unreported + 1; /* we have to account for 1st byte with number of unreported attributes */ -} - -/* Parse Attribute Response Info content for 3GPP TS 52.021 §9.4.30 Manufacturer Id */ -static inline uint8_t *parse_attr_resp_info_manuf_id(struct gsm_bts *bts, uint8_t *data, uint16_t *data_len) -{ - struct tlv_parsed tp; - uint16_t m_id_len = 0; - uint8_t adjust = 0, i; - - abis_nm_tlv_parse(&tp, bts, data, *data_len); - if (TLVP_PRES_LEN(&tp, NM_ATT_MANUF_ID, 2)) { - m_id_len = TLVP_LEN(&tp, NM_ATT_MANUF_ID); - - /* log potential BTS feature vector overflow */ - if (m_id_len > sizeof(bts->_features_data)) - LOGP(DNM, LOGL_NOTICE, "BTS%u Get Attributes Response: feature vector is truncated to %u bytes\n", - bts->nr, MAX_BTS_FEATURES/8); - - /* check that max. expected BTS attribute is above given feature vector length */ - if (m_id_len > OSMO_BYTES_FOR_BITS(_NUM_BTS_FEAT)) - LOGP(DNM, LOGL_NOTICE, "BTS%u Get Attributes Response: reported unexpectedly long (%u bytes) " - "feature vector - most likely it was compiled against newer BSC headers. " - "Consider upgrading your BSC to later version.\n", - bts->nr, m_id_len); - - memcpy(bts->_features_data, TLVP_VAL(&tp, NM_ATT_MANUF_ID), sizeof(bts->_features_data)); - adjust = m_id_len + 3; /* adjust for parsed TL16V struct */ - - for (i = 0; i < _NUM_BTS_FEAT; i++) - if (gsm_bts_has_feature(bts, i) != gsm_btsmodel_has_feature(bts->model, i)) - LOGP(DNM, LOGL_NOTICE, "BTS%u feature '%s' reported via OML does not match statically " - "set feature: %u != %u. Please fix.\n", bts->nr, - get_value_string(gsm_bts_features_descs, i), - gsm_bts_has_feature(bts, i), gsm_btsmodel_has_feature(bts->model, i)); - } - - *data_len -= adjust; - - return data + adjust; -} - -/* Parse Attribute Response Info content for 3GPP TS 52.021 §9.4.28 Manufacturer Dependent State */ -static inline uint8_t *parse_attr_resp_info_manuf_state(const struct gsm_bts_trx *trx, uint8_t *data, uint16_t *data_len) -{ - struct tlv_parsed tp; - const uint8_t *power; - uint8_t adjust = 0; - - if (!trx) /* this attribute does not make sense on BTS level, only on TRX level */ - return data; - - abis_nm_tlv_parse(&tp, trx->bts, data, *data_len); - if (TLVP_PRES_LEN(&tp, NM_ATT_MANUF_STATE, 1)) { - power = TLVP_VAL(&tp, NM_ATT_MANUF_STATE); - LOGP(DNM, LOGL_NOTICE, "%s Get Attributes Response: nominal power is %u\n", gsm_trx_name(trx), *power); - adjust = 2; /* adjust for parsed TV struct */ - } - - *data_len -= adjust; - - return data + adjust; -} - -/* Handle 3GPP TS 52.021 §9.4.64 Get Attribute Response Info */ -static int abis_nm_rx_get_attr_resp(struct msgb *mb, const struct gsm_bts_trx *trx) -{ - struct abis_om_hdr *oh = msgb_l2(mb); - struct abis_om_fom_hdr *foh = msgb_l3(mb); - struct e1inp_sign_link *sign_link = mb->dst; - struct gsm_bts *bts = trx ? trx->bts : sign_link->trx->bts; - struct tlv_parsed tp; - uint8_t *data, i; - uint16_t data_len; - int rc; - struct abis_nm_sw_desc sw_descr[MAX_BTS_ATTR]; - - abis_nm_debugp_foh(DNM, foh); - - DEBUGPC(DNM, "Get Attributes Response for BTS%u\n", bts->nr); - - abis_nm_tlv_parse(&tp, bts, foh->data, oh->length-sizeof(*foh)); - if (!TLVP_PRES_LEN(&tp, NM_ATT_GET_ARI, 1)) { - LOGP(DNM, LOGL_ERROR, "BTS%u: Get Attributes Response without Response Info?!\n", bts->nr); - return -EINVAL; - } - - data = parse_attr_resp_info_unreported(bts->nr, TLVP_VAL(&tp, NM_ATT_GET_ARI), TLVP_LEN(&tp, NM_ATT_GET_ARI), - &data_len); - - data = parse_attr_resp_info_manuf_state(trx, data, &data_len); - data = parse_attr_resp_info_manuf_id(bts, data, &data_len); - - /* after parsing manufacturer-specific attributes there's list of replies in form of sw-conf structure: */ - rc = abis_nm_get_sw_conf(data, data_len, &sw_descr[0], ARRAY_SIZE(sw_descr)); - if (rc > 0) { - for (i = 0; i < rc; i++) { - if (!handle_attr(bts, str2btsattr((const char *)sw_descr[i].file_id), - sw_descr[i].file_version, sw_descr[i].file_version_len)) - LOGP(DNM, LOGL_NOTICE, "BTS%u: ARI reported sw[%d/%d]: %s is %s\n", - bts->nr, i, rc, sw_descr[i].file_id, sw_descr[i].file_version); - } - } else - LOGP(DNM, LOGL_ERROR, "BTS%u: failed to parse SW-Config part of Get Attribute Response Info: %s\n", - bts->nr, strerror(-rc)); - - return 0; -} - -/* 3GPP TS 52.021 §6.2.5 */ -static int abis_nm_rx_sw_act_req(struct msgb *mb) -{ - struct abis_om_hdr *oh = msgb_l2(mb); - struct abis_om_fom_hdr *foh = msgb_l3(mb); - struct e1inp_sign_link *sign_link = mb->dst; - struct tlv_parsed tp; - const uint8_t *sw_config; - int ret, sw_config_len, len; - struct abis_nm_sw_desc sw_descr[MAX_BTS_ATTR]; - - abis_nm_debugp_foh(DNM, foh); - - DEBUGPC(DNM, "SW Activate Request: "); - - DEBUGP(DNM, "Software Activate Request, ACKing and Activating\n"); - - ret = abis_nm_sw_act_req_ack(sign_link->trx->bts, foh->obj_class, - foh->obj_inst.bts_nr, - foh->obj_inst.trx_nr, - foh->obj_inst.ts_nr, 0, - foh->data, oh->length-sizeof(*foh)); - if (ret != 0) { - LOGP(DNM, LOGL_ERROR, - "Sending SW ActReq ACK failed: %d\n", ret); - return ret; - } - - abis_nm_tlv_parse(&tp, sign_link->trx->bts, foh->data, oh->length-sizeof(*foh)); - sw_config = TLVP_VAL(&tp, NM_ATT_SW_CONFIG); - sw_config_len = TLVP_LEN(&tp, NM_ATT_SW_CONFIG); - if (!TLVP_PRESENT(&tp, NM_ATT_SW_CONFIG)) { - LOGP(DNM, LOGL_ERROR, - "SW config not found! Can't continue.\n"); - return -EINVAL; - } else { - DEBUGP(DNM, "Found SW config: %s\n", osmo_hexdump(sw_config, sw_config_len)); - } - - /* Parse up to two sw descriptions from the data */ - len = abis_nm_get_sw_conf(sw_config, sw_config_len, &sw_descr[0], - ARRAY_SIZE(sw_descr)); - if (len <= 0) { - LOGP(DNM, LOGL_ERROR, "Failed to parse SW Config.\n"); - return -EINVAL; - } - - ret = abis_nm_select_newest_sw(&sw_descr[0], len); - DEBUGP(DNM, "Selected sw description %d of %d\n", ret, len); - - return ipacc_sw_activate(sign_link->trx->bts, foh->obj_class, - foh->obj_inst.bts_nr, - foh->obj_inst.trx_nr, - foh->obj_inst.ts_nr, - &sw_descr[ret]); -} - -/* Receive a CHANGE_ADM_STATE_ACK, parse the TLV and update local state */ -static int abis_nm_rx_chg_adm_state_ack(struct msgb *mb) -{ - struct abis_om_hdr *oh = msgb_l2(mb); - struct abis_om_fom_hdr *foh = msgb_l3(mb); - struct e1inp_sign_link *sign_link = mb->dst; - struct tlv_parsed tp; - uint8_t adm_state; - - abis_nm_tlv_parse(&tp, sign_link->trx->bts, foh->data, oh->length-sizeof(*foh)); - if (!TLVP_PRESENT(&tp, NM_ATT_ADM_STATE)) - return -EINVAL; - - adm_state = *TLVP_VAL(&tp, NM_ATT_ADM_STATE); - - return update_admstate(sign_link->trx->bts, foh->obj_class, &foh->obj_inst, adm_state); -} - -static int abis_nm_rx_lmt_event(struct msgb *mb) -{ - struct abis_om_hdr *oh = msgb_l2(mb); - struct abis_om_fom_hdr *foh = msgb_l3(mb); - struct e1inp_sign_link *sign_link = mb->dst; - struct tlv_parsed tp; - - DEBUGP(DNM, "LMT Event "); - abis_nm_tlv_parse(&tp, sign_link->trx->bts, foh->data, oh->length-sizeof(*foh)); - if (TLVP_PRESENT(&tp, NM_ATT_BS11_LMT_LOGON_SESSION) && - TLVP_LEN(&tp, NM_ATT_BS11_LMT_LOGON_SESSION) >= 1) { - uint8_t onoff = *TLVP_VAL(&tp, NM_ATT_BS11_LMT_LOGON_SESSION); - DEBUGPC(DNM, "LOG%s ", onoff ? "ON" : "OFF"); - } - if (TLVP_PRESENT(&tp, NM_ATT_BS11_LMT_USER_ACC_LEV) && - TLVP_LEN(&tp, NM_ATT_BS11_LMT_USER_ACC_LEV) >= 1) { - uint8_t level = *TLVP_VAL(&tp, NM_ATT_BS11_LMT_USER_ACC_LEV); - DEBUGPC(DNM, "Level=%u ", level); - } - if (TLVP_PRESENT(&tp, NM_ATT_BS11_LMT_USER_NAME) && - TLVP_LEN(&tp, NM_ATT_BS11_LMT_USER_NAME) >= 1) { - char *name = (char *) TLVP_VAL(&tp, NM_ATT_BS11_LMT_USER_NAME); - DEBUGPC(DNM, "Username=%s ", name); - } - DEBUGPC(DNM, "\n"); - /* FIXME: parse LMT LOGON TIME */ - return 0; -} - -void abis_nm_queue_send_next(struct gsm_bts *bts) -{ - int wait = 0; - struct msgb *msg; - /* the queue is empty */ - while (!llist_empty(&bts->abis_queue)) { - msg = msgb_dequeue(&bts->abis_queue); - wait = OBSC_NM_W_ACK_CB(msg); - _abis_nm_sendmsg(msg); - - if (wait) - break; - } - - bts->abis_nm_pend = wait; -} - -/* Receive a OML NM Message from BTS */ -static int abis_nm_rcvmsg_fom(struct msgb *mb) -{ - struct abis_om_hdr *oh = msgb_l2(mb); - struct abis_om_fom_hdr *foh = msgb_l3(mb); - struct e1inp_sign_link *sign_link = mb->dst; - uint8_t mt = foh->msg_type; - /* sign_link might get deleted via osmo_signal_dispatch -> save bts */ - struct gsm_bts *bts = sign_link->trx->bts; - int ret = 0; - - /* check for unsolicited message */ - if (is_report(mt)) - return abis_nm_rcvmsg_report(mb, bts); - - if (is_in_arr(mt, abis_nm_sw_load_msgs, ARRAY_SIZE(abis_nm_sw_load_msgs))) - return abis_nm_rcvmsg_sw(mb); - - if (is_in_arr(mt, abis_nm_nacks, ARRAY_SIZE(abis_nm_nacks))) { - struct nm_nack_signal_data nack_data; - struct tlv_parsed tp; - - abis_nm_debugp_foh(DNM, foh); - - DEBUGPC(DNM, "%s NACK ", abis_nm_nack_name(mt)); - - abis_nm_tlv_parse(&tp, bts, foh->data, oh->length-sizeof(*foh)); - if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES)) - DEBUGPC(DNM, "CAUSE=%s\n", - abis_nm_nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES))); - else - DEBUGPC(DNM, "\n"); - - nack_data.msg = mb; - nack_data.mt = mt; - nack_data.bts = bts; - osmo_signal_dispatch(SS_NM, S_NM_NACK, &nack_data); - abis_nm_queue_send_next(bts); - return 0; - } -#if 0 - /* check if last message is to be acked */ - if (is_ack_nack(nmh->last_msgtype)) { - if (mt == MT_ACK(nmh->last_msgtype)) { - DEBUGP(DNM, "received ACK (0x%x)\n", foh->msg_type); - /* we got our ACK, continue sending the next msg */ - } else if (mt == MT_NACK(nmh->last_msgtype)) { - /* we got a NACK, signal this to the caller */ - DEBUGP(DNM, "received NACK (0x%x)\n", foh->msg_type); - /* FIXME: somehow signal this to the caller */ - } else { - /* really strange things happen */ - return -EINVAL; - } - } -#endif - - switch (mt) { - case NM_MT_CHG_ADM_STATE_ACK: - ret = abis_nm_rx_chg_adm_state_ack(mb); - break; - case NM_MT_SW_ACT_REQ: - ret = abis_nm_rx_sw_act_req(mb); - break; - case NM_MT_BS11_LMT_SESSION: - ret = abis_nm_rx_lmt_event(mb); - break; - case NM_MT_OPSTART_ACK: - abis_nm_debugp_foh(DNM, foh); - DEBUGPC(DNM, "Opstart ACK\n"); - break; - case NM_MT_SET_CHAN_ATTR_ACK: - abis_nm_debugp_foh(DNM, foh); - DEBUGPC(DNM, "Set Channel Attributes ACK\n"); - break; - case NM_MT_SET_RADIO_ATTR_ACK: - abis_nm_debugp_foh(DNM, foh); - DEBUGPC(DNM, "Set Radio Carrier Attributes ACK\n"); - break; - case NM_MT_CONN_MDROP_LINK_ACK: - abis_nm_debugp_foh(DNM, foh); - DEBUGPC(DNM, "CONN MDROP LINK ACK\n"); - break; - case NM_MT_IPACC_RESTART_ACK: - osmo_signal_dispatch(SS_NM, S_NM_IPACC_RESTART_ACK, NULL); - break; - case NM_MT_IPACC_RESTART_NACK: - osmo_signal_dispatch(SS_NM, S_NM_IPACC_RESTART_NACK, NULL); - break; - case NM_MT_SET_BTS_ATTR_ACK: - break; - case NM_MT_GET_ATTR_RESP: - ret = abis_nm_rx_get_attr_resp(mb, gsm_bts_trx_num(bts, (foh)->obj_inst.trx_nr)); - break; - default: - abis_nm_debugp_foh(DNM, foh); - LOGPC(DNM, LOGL_ERROR, "Unhandled message %s\n", - get_value_string(abis_nm_msgtype_names, mt)); - } - - abis_nm_queue_send_next(bts); - return ret; -} - -static int abis_nm_rx_ipacc(struct msgb *mb); - -static int abis_nm_rcvmsg_manuf(struct msgb *mb) -{ - int rc; - struct e1inp_sign_link *sign_link = mb->dst; - int bts_type = sign_link->trx->bts->type; - - switch (bts_type) { - case GSM_BTS_TYPE_NANOBTS: - case GSM_BTS_TYPE_OSMOBTS: - rc = abis_nm_rx_ipacc(mb); - abis_nm_queue_send_next(sign_link->trx->bts); - break; - default: - LOGP(DNM, LOGL_ERROR, "don't know how to parse OML for this " - "BTS type (%u)\n", bts_type); - rc = 0; - break; - } - - return rc; -} - -/* High-Level API */ -/* Entry-point where L2 OML from BTS enters the NM code */ -int abis_nm_rcvmsg(struct msgb *msg) -{ - struct abis_om_hdr *oh = msgb_l2(msg); - int rc = 0; - - /* Various consistency checks */ - if (oh->placement != ABIS_OM_PLACEMENT_ONLY) { - LOGP(DNM, LOGL_ERROR, "ABIS OML placement 0x%x not supported\n", - oh->placement); - if (oh->placement != ABIS_OM_PLACEMENT_FIRST) { - rc = -EINVAL; - goto err; - } - } - if (oh->sequence != 0) { - LOGP(DNM, LOGL_ERROR, "ABIS OML sequence 0x%x != 0x00\n", - oh->sequence); - rc = -EINVAL; - goto err; - } -#if 0 - unsigned int l2_len = msg->tail - (uint8_t *)msgb_l2(msg); - unsigned int hlen = sizeof(*oh) + sizeof(struct abis_om_fom_hdr); - if (oh->length + hlen > l2_len) { - LOGP(DNM, LOGL_ERROR, "ABIS OML truncated message (%u > %u)\n", - oh->length + sizeof(*oh), l2_len); - return -EINVAL; - } - if (oh->length + hlen < l2_len) - LOGP(DNM, LOGL_ERROR, "ABIS OML message with extra trailer?!? (oh->len=%d, sizeof_oh=%d l2_len=%d\n", oh->length, sizeof(*oh), l2_len); -#endif - msg->l3h = (unsigned char *)oh + sizeof(*oh); - - switch (oh->mdisc) { - case ABIS_OM_MDISC_FOM: - rc = abis_nm_rcvmsg_fom(msg); - break; - case ABIS_OM_MDISC_MANUF: - rc = abis_nm_rcvmsg_manuf(msg); - break; - case ABIS_OM_MDISC_MMI: - case ABIS_OM_MDISC_TRAU: - LOGP(DNM, LOGL_ERROR, "unimplemented ABIS OML message discriminator 0x%x\n", - oh->mdisc); - break; - default: - LOGP(DNM, LOGL_ERROR, "unknown ABIS OML message discriminator 0x%x\n", - oh->mdisc); - rc = -EINVAL; - break; - } -err: - msgb_free(msg); - return rc; -} - -#if 0 -/* initialized all resources */ -struct abis_nm_h *abis_nm_init(struct abis_nm_cfg *cfg) -{ - struct abis_nm_h *nmh; - - nmh = malloc(sizeof(*nmh)); - if (!nmh) - return NULL; - - nmh->cfg = cfg; - - return nmh; -} - -/* free all resources */ -void abis_nm_fini(struct abis_nm_h *nmh) -{ - free(nmh); -} -#endif - -/* Here we are trying to define a high-level API that can be used by - * the actual BSC implementation. However, the architecture is currently - * still under design. Ideally the calls to this API would be synchronous, - * while the underlying stack behind the APi runs in a traditional select - * based state machine. - */ - -/* 6.2 Software Load: */ -enum sw_state { - SW_STATE_NONE, - SW_STATE_WAIT_INITACK, - SW_STATE_WAIT_SEGACK, - SW_STATE_WAIT_ENDACK, - SW_STATE_WAIT_ACTACK, - SW_STATE_ERROR, -}; - -struct abis_nm_sw { - struct gsm_bts *bts; - int trx_nr; - gsm_cbfn *cbfn; - void *cb_data; - int forced; - - /* this will become part of the SW LOAD INITIATE */ - uint8_t obj_class; - uint8_t obj_instance[3]; - - uint8_t file_id[255]; - uint8_t file_id_len; - - uint8_t file_version[255]; - uint8_t file_version_len; - - uint8_t window_size; - uint8_t seg_in_window; - - int fd; - FILE *stream; - enum sw_state state; - int last_seg; -}; - -static struct abis_nm_sw g_sw; - -static void sw_add_file_id_and_ver(struct abis_nm_sw *sw, struct msgb *msg) -{ - if (sw->bts->type == GSM_BTS_TYPE_NANOBTS) { - msgb_v_put(msg, NM_ATT_SW_DESCR); - msgb_tl16v_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id); - msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len, - sw->file_version); - } else if (sw->bts->type == GSM_BTS_TYPE_BS11) { - msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id); - msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len, - sw->file_version); - } else { - LOGP(DNM, LOGL_ERROR, "Please implement this for the BTS.\n"); - } -} - -/* 6.2.1 / 8.3.1: Load Data Initiate */ -static int sw_load_init(struct abis_nm_sw *sw) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - uint8_t len = 3*2 + sw->file_id_len + sw->file_version_len; - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, len, NM_MT_LOAD_INIT, sw->obj_class, - sw->obj_instance[0], sw->obj_instance[1], - sw->obj_instance[2]); - - sw_add_file_id_and_ver(sw, msg); - msgb_tv_put(msg, NM_ATT_WINDOW_SIZE, sw->window_size); - - return abis_nm_sendmsg(sw->bts, msg); -} - -static int is_last_line(FILE *stream) -{ - char next_seg_buf[256]; - long pos; - - /* check if we're sending the last line */ - pos = ftell(stream); - - /* Did ftell fail? Then we are at the end for sure */ - if (pos < 0) - return 1; - - if (!fgets(next_seg_buf, sizeof(next_seg_buf)-2, stream)) { - int rc = fseek(stream, pos, SEEK_SET); - if (rc < 0) - return rc; - return 1; - } - - fseek(stream, pos, SEEK_SET); - return 0; -} - -/* 6.2.2 / 8.3.2 Load Data Segment */ -static int sw_load_segment(struct abis_nm_sw *sw) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - char seg_buf[256]; - char *line_buf = seg_buf+2; - unsigned char *tlv; - int len; - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - - switch (sw->bts->type) { - case GSM_BTS_TYPE_BS11: - if (fgets(line_buf, sizeof(seg_buf)-2, sw->stream) == NULL) { - perror("fgets reading segment"); - return -EINVAL; - } - seg_buf[0] = 0x00; - - /* check if we're sending the last line */ - sw->last_seg = is_last_line(sw->stream); - if (sw->last_seg) - seg_buf[1] = 0; - else - seg_buf[1] = 1 + sw->seg_in_window++; - - len = strlen(line_buf) + 2; - tlv = msgb_put(msg, TLV_GROSS_LEN(len)); - tlv_put(tlv, NM_ATT_BS11_FILE_DATA, len, (uint8_t *)seg_buf); - /* BS11 wants CR + LF in excess of the TLV length !?! */ - tlv[1] -= 2; - - /* we only now know the exact length for the OM hdr */ - len = strlen(line_buf)+2; - break; - case GSM_BTS_TYPE_NANOBTS: { - osmo_static_assert(sizeof(seg_buf) >= IPACC_SEGMENT_SIZE, buffer_big_enough); - len = read(sw->fd, &seg_buf, IPACC_SEGMENT_SIZE); - if (len < 0) { - perror("read failed"); - return -EINVAL; - } - - if (len != IPACC_SEGMENT_SIZE) - sw->last_seg = 1; - - ++sw->seg_in_window; - msgb_tl16v_put(msg, NM_ATT_IPACC_FILE_DATA, len, (const uint8_t *) seg_buf); - len += 3; - break; - } - default: - LOGP(DNM, LOGL_ERROR, "sw_load_segment needs implementation for the BTS.\n"); - /* FIXME: Other BTS types */ - return -1; - } - - fill_om_fom_hdr(oh, len, NM_MT_LOAD_SEG, sw->obj_class, - sw->obj_instance[0], sw->obj_instance[1], - sw->obj_instance[2]); - - return abis_nm_sendmsg_direct(sw->bts, msg); -} - -/* 6.2.4 / 8.3.4 Load Data End */ -static int sw_load_end(struct abis_nm_sw *sw) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - uint8_t len = 2*2 + sw->file_id_len + sw->file_version_len; - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, len, NM_MT_LOAD_END, sw->obj_class, - sw->obj_instance[0], sw->obj_instance[1], - sw->obj_instance[2]); - - sw_add_file_id_and_ver(sw, msg); - return abis_nm_sendmsg(sw->bts, msg); -} - -/* Activate the specified software into the BTS */ -static int sw_activate(struct abis_nm_sw *sw) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - uint8_t len = 2*2 + sw->file_id_len + sw->file_version_len; - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, len, NM_MT_ACTIVATE_SW, sw->obj_class, - sw->obj_instance[0], sw->obj_instance[1], - sw->obj_instance[2]); - - /* FIXME: this is BS11 specific format */ - msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id); - msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len, - sw->file_version); - - return abis_nm_sendmsg(sw->bts, msg); -} - -struct sdp_firmware { - char magic[4]; - char more_magic[4]; - unsigned int header_length; - unsigned int file_length; -} __attribute__ ((packed)); - -static int parse_sdp_header(struct abis_nm_sw *sw) -{ - struct sdp_firmware firmware_header; - int rc; - struct stat stat; - - rc = read(sw->fd, &firmware_header, sizeof(firmware_header)); - if (rc != sizeof(firmware_header)) { - LOGP(DNM, LOGL_ERROR, "Could not read SDP file header.\n"); - return -1; - } - - if (strncmp(firmware_header.magic, " SDP", 4) != 0) { - LOGP(DNM, LOGL_ERROR, "The magic number1 is wrong.\n"); - return -1; - } - - if (firmware_header.more_magic[0] != 0x10 || - firmware_header.more_magic[1] != 0x02 || - firmware_header.more_magic[2] != 0x00 || - firmware_header.more_magic[3] != 0x00) { - LOGP(DNM, LOGL_ERROR, "The more magic number is wrong.\n"); - return -1; - } - - - if (fstat(sw->fd, &stat) == -1) { - LOGP(DNM, LOGL_ERROR, "Could not stat the file.\n"); - return -1; - } - - if (ntohl(firmware_header.file_length) != stat.st_size) { - LOGP(DNM, LOGL_ERROR, "The filesizes do not match.\n"); - return -1; - } - - /* go back to the start as we checked the whole filesize.. */ - lseek(sw->fd, 0l, SEEK_SET); - LOGP(DNM, LOGL_NOTICE, "The ipaccess SDP header is not fully understood.\n" - "There might be checksums in the file that are not\n" - "verified and incomplete firmware might be flashed.\n" - "There is absolutely no WARRANTY that flashing will\n" - "work.\n"); - return 0; -} - -static int sw_open_file(struct abis_nm_sw *sw, const char *fname) -{ - char file_id[12+1]; - char file_version[80+1]; - int rc; - - sw->fd = open(fname, O_RDONLY); - if (sw->fd < 0) - return sw->fd; - - switch (sw->bts->type) { - case GSM_BTS_TYPE_BS11: - sw->stream = fdopen(sw->fd, "r"); - if (!sw->stream) { - perror("fdopen"); - return -1; - } - /* read first line and parse file ID and VERSION */ - rc = fscanf(sw->stream, "@(#)%12s:%80s\r\n", - file_id, file_version); - if (rc != 2) { - perror("parsing header line of software file"); - return -1; - } - strcpy((char *)sw->file_id, file_id); - sw->file_id_len = strlen(file_id); - strcpy((char *)sw->file_version, file_version); - sw->file_version_len = strlen(file_version); - /* rewind to start of file */ - rewind(sw->stream); - break; - case GSM_BTS_TYPE_NANOBTS: - /* TODO: extract that from the filename or content */ - rc = parse_sdp_header(sw); - if (rc < 0) { - fprintf(stderr, "Could not parse the ipaccess SDP header\n"); - return -1; - } - - strcpy((char *)sw->file_id, "id"); - sw->file_id_len = 3; - strcpy((char *)sw->file_version, "version"); - sw->file_version_len = 8; - break; - default: - /* We don't know how to treat them yet */ - close(sw->fd); - return -EINVAL; - } - - return 0; -} - -static void sw_close_file(struct abis_nm_sw *sw) -{ - switch (sw->bts->type) { - case GSM_BTS_TYPE_BS11: - fclose(sw->stream); - break; - default: - close(sw->fd); - break; - } -} - -/* Fill the window */ -static int sw_fill_window(struct abis_nm_sw *sw) -{ - int rc; - - while (sw->seg_in_window < sw->window_size) { - rc = sw_load_segment(sw); - if (rc < 0) - return rc; - if (sw->last_seg) - break; - } - return 0; -} - -/* callback function from abis_nm_rcvmsg() handler */ -static int abis_nm_rcvmsg_sw(struct msgb *mb) -{ - struct abis_om_fom_hdr *foh = msgb_l3(mb); - struct e1inp_sign_link *sign_link = mb->dst; - int rc = -1; - struct abis_nm_sw *sw = &g_sw; - enum sw_state old_state = sw->state; - - //DEBUGP(DNM, "state %u, NM MT 0x%02x\n", sw->state, foh->msg_type); - - switch (sw->state) { - case SW_STATE_WAIT_INITACK: - switch (foh->msg_type) { - case NM_MT_LOAD_INIT_ACK: - /* fill window with segments */ - if (sw->cbfn) - sw->cbfn(GSM_HOOK_NM_SWLOAD, - NM_MT_LOAD_INIT_ACK, mb, - sw->cb_data, NULL); - rc = sw_fill_window(sw); - sw->state = SW_STATE_WAIT_SEGACK; - abis_nm_queue_send_next(sign_link->trx->bts); - break; - case NM_MT_LOAD_INIT_NACK: - if (sw->forced) { - DEBUGP(DNM, "FORCED: Ignoring Software Load " - "Init NACK\n"); - if (sw->cbfn) - sw->cbfn(GSM_HOOK_NM_SWLOAD, - NM_MT_LOAD_INIT_ACK, mb, - sw->cb_data, NULL); - rc = sw_fill_window(sw); - sw->state = SW_STATE_WAIT_SEGACK; - } else { - DEBUGP(DNM, "Software Load Init NACK\n"); - /* FIXME: cause */ - if (sw->cbfn) - sw->cbfn(GSM_HOOK_NM_SWLOAD, - NM_MT_LOAD_INIT_NACK, mb, - sw->cb_data, NULL); - sw->state = SW_STATE_ERROR; - } - abis_nm_queue_send_next(sign_link->trx->bts); - break; - } - break; - case SW_STATE_WAIT_SEGACK: - switch (foh->msg_type) { - case NM_MT_LOAD_SEG_ACK: - if (sw->cbfn) - sw->cbfn(GSM_HOOK_NM_SWLOAD, - NM_MT_LOAD_SEG_ACK, mb, - sw->cb_data, NULL); - sw->seg_in_window = 0; - if (!sw->last_seg) { - /* fill window with more segments */ - rc = sw_fill_window(sw); - sw->state = SW_STATE_WAIT_SEGACK; - } else { - /* end the transfer */ - sw->state = SW_STATE_WAIT_ENDACK; - rc = sw_load_end(sw); - } - abis_nm_queue_send_next(sign_link->trx->bts); - break; - case NM_MT_LOAD_ABORT: - if (sw->cbfn) - sw->cbfn(GSM_HOOK_NM_SWLOAD, - NM_MT_LOAD_ABORT, mb, - sw->cb_data, NULL); - break; - } - break; - case SW_STATE_WAIT_ENDACK: - switch (foh->msg_type) { - case NM_MT_LOAD_END_ACK: - sw_close_file(sw); - DEBUGP(DNM, "Software Load End (BTS %u)\n", - sw->bts->nr); - sw->state = SW_STATE_NONE; - if (sw->cbfn) - sw->cbfn(GSM_HOOK_NM_SWLOAD, - NM_MT_LOAD_END_ACK, mb, - sw->cb_data, NULL); - rc = 0; - abis_nm_queue_send_next(sign_link->trx->bts); - break; - case NM_MT_LOAD_END_NACK: - if (sw->forced) { - DEBUGP(DNM, "FORCED: Ignoring Software Load" - "End NACK\n"); - sw->state = SW_STATE_NONE; - if (sw->cbfn) - sw->cbfn(GSM_HOOK_NM_SWLOAD, - NM_MT_LOAD_END_ACK, mb, - sw->cb_data, NULL); - } else { - DEBUGP(DNM, "Software Load End NACK\n"); - /* FIXME: cause */ - sw->state = SW_STATE_ERROR; - if (sw->cbfn) - sw->cbfn(GSM_HOOK_NM_SWLOAD, - NM_MT_LOAD_END_NACK, mb, - sw->cb_data, NULL); - } - abis_nm_queue_send_next(sign_link->trx->bts); - break; - } - case SW_STATE_WAIT_ACTACK: - switch (foh->msg_type) { - case NM_MT_ACTIVATE_SW_ACK: - /* we're done */ - DEBUGP(DNM, "Activate Software DONE!\n"); - sw->state = SW_STATE_NONE; - rc = 0; - if (sw->cbfn) - sw->cbfn(GSM_HOOK_NM_SWLOAD, - NM_MT_ACTIVATE_SW_ACK, mb, - sw->cb_data, NULL); - abis_nm_queue_send_next(sign_link->trx->bts); - break; - case NM_MT_ACTIVATE_SW_NACK: - DEBUGP(DNM, "Activate Software NACK\n"); - /* FIXME: cause */ - sw->state = SW_STATE_ERROR; - if (sw->cbfn) - sw->cbfn(GSM_HOOK_NM_SWLOAD, - NM_MT_ACTIVATE_SW_NACK, mb, - sw->cb_data, NULL); - abis_nm_queue_send_next(sign_link->trx->bts); - break; - } - case SW_STATE_NONE: - switch (foh->msg_type) { - case NM_MT_ACTIVATE_SW_ACK: - rc = 0; - break; - } - break; - case SW_STATE_ERROR: - break; - } - - if (rc) - DEBUGP(DNM, "unexpected NM MT 0x%02x in state %u -> %u\n", - foh->msg_type, old_state, sw->state); - - return rc; -} - -/* Load the specified software into the 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) -{ - struct abis_nm_sw *sw = &g_sw; - int rc; - - DEBUGP(DNM, "Software Load (BTS %u, File \"%s\")\n", - bts->nr, fname); - - if (sw->state != SW_STATE_NONE) - return -EBUSY; - - sw->bts = bts; - sw->trx_nr = trx_nr; - - switch (bts->type) { - case GSM_BTS_TYPE_BS11: - sw->obj_class = NM_OC_SITE_MANAGER; - sw->obj_instance[0] = 0xff; - sw->obj_instance[1] = 0xff; - sw->obj_instance[2] = 0xff; - break; - case GSM_BTS_TYPE_NANOBTS: - sw->obj_class = NM_OC_BASEB_TRANSC; - sw->obj_instance[0] = sw->bts->nr; - sw->obj_instance[1] = sw->trx_nr; - sw->obj_instance[2] = 0xff; - break; - case GSM_BTS_TYPE_UNKNOWN: - default: - LOGPC(DNM, LOGL_ERROR, "Software Load not properly implemented.\n"); - return -1; - break; - } - sw->window_size = win_size; - sw->state = SW_STATE_WAIT_INITACK; - sw->cbfn = cbfn; - sw->cb_data = cb_data; - sw->forced = forced; - - rc = sw_open_file(sw, fname); - if (rc < 0) { - sw->state = SW_STATE_NONE; - return rc; - } - - return sw_load_init(sw); -} - -int abis_nm_software_load_status(struct gsm_bts *bts) -{ - struct abis_nm_sw *sw = &g_sw; - struct stat st; - int rc, percent; - - rc = fstat(sw->fd, &st); - if (rc < 0) { - perror("ERROR during stat"); - return rc; - } - - if (sw->stream) - percent = (ftell(sw->stream) * 100) / st.st_size; - else - percent = (lseek(sw->fd, 0, SEEK_CUR) * 100) / st.st_size; - return percent; -} - -/* Activate the specified software into the BTS */ -int abis_nm_software_activate(struct gsm_bts *bts, const char *fname, - gsm_cbfn *cbfn, void *cb_data) -{ - struct abis_nm_sw *sw = &g_sw; - int rc; - - DEBUGP(DNM, "Activating Software (BTS %u, File \"%s\")\n", - bts->nr, fname); - - if (sw->state != SW_STATE_NONE) - return -EBUSY; - - sw->bts = bts; - sw->obj_class = NM_OC_SITE_MANAGER; - sw->obj_instance[0] = 0xff; - sw->obj_instance[1] = 0xff; - sw->obj_instance[2] = 0xff; - sw->state = SW_STATE_WAIT_ACTACK; - sw->cbfn = cbfn; - sw->cb_data = cb_data; - - /* Open the file in order to fill some sw struct members */ - rc = sw_open_file(sw, fname); - if (rc < 0) { - sw->state = SW_STATE_NONE; - return rc; - } - sw_close_file(sw); - - return sw_activate(sw); -} - -static void fill_nm_channel(struct abis_nm_channel *ch, uint8_t bts_port, - uint8_t ts_nr, uint8_t subslot_nr) -{ - ch->attrib = NM_ATT_ABIS_CHANNEL; - ch->bts_port = bts_port; - ch->timeslot = ts_nr; - ch->subslot = subslot_nr; -} - -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) -{ - struct abis_om_hdr *oh; - struct abis_nm_channel *ch; - uint8_t len = sizeof(*ch) + 2; - struct msgb *msg = nm_msgb_alloc(); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, len, NM_MT_ESTABLISH_TEI, NM_OC_RADIO_CARRIER, - bts->bts_nr, trx_nr, 0xff); - - msgb_tv_put(msg, NM_ATT_TEI, tei); - - ch = (struct abis_nm_channel *) msgb_put(msg, sizeof(*ch)); - fill_nm_channel(ch, e1_port, e1_timeslot, e1_subslot); - - return abis_nm_sendmsg(bts, msg); -} - -/* connect signalling of one (BTS,TRX) to a particular timeslot on the E1 */ -int abis_nm_conn_terr_sign(struct gsm_bts_trx *trx, - uint8_t e1_port, uint8_t e1_timeslot, uint8_t e1_subslot) -{ - struct gsm_bts *bts = trx->bts; - struct abis_om_hdr *oh; - struct abis_nm_channel *ch; - struct msgb *msg = nm_msgb_alloc(); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, sizeof(*ch), NM_MT_CONN_TERR_SIGN, - NM_OC_RADIO_CARRIER, bts->bts_nr, trx->nr, 0xff); - - ch = (struct abis_nm_channel *) msgb_put(msg, sizeof(*ch)); - fill_nm_channel(ch, e1_port, e1_timeslot, e1_subslot); - - return abis_nm_sendmsg(bts, msg); -} - -#if 0 -int abis_nm_disc_terr_sign(struct abis_nm_h *h, struct abis_om_obj_inst *inst, - struct abis_nm_abis_channel *chan) -{ -} -#endif - -int abis_nm_conn_terr_traf(struct gsm_bts_trx_ts *ts, - uint8_t e1_port, uint8_t e1_timeslot, - uint8_t e1_subslot) -{ - struct gsm_bts *bts = ts->trx->bts; - struct abis_om_hdr *oh; - struct abis_nm_channel *ch; - struct msgb *msg = nm_msgb_alloc(); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, sizeof(*ch), NM_MT_CONN_TERR_TRAF, - NM_OC_CHANNEL, bts->bts_nr, ts->trx->nr, ts->nr); - - ch = (struct abis_nm_channel *) msgb_put(msg, sizeof(*ch)); - fill_nm_channel(ch, e1_port, e1_timeslot, e1_subslot); - - DEBUGP(DNM, "CONNECT TERR TRAF Um=%s E1=(%u,%u,%u)\n", - gsm_ts_name(ts), - e1_port, e1_timeslot, e1_subslot); - - return abis_nm_sendmsg(bts, msg); -} - -#if 0 -int abis_nm_disc_terr_traf(struct abis_nm_h *h, struct abis_om_obj_inst *inst, - struct abis_nm_abis_channel *chan, - uint8_t subchan) -{ -} -#endif - -/* 3GPP TS 52.021 § 8.11.1 */ -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) -{ - struct abis_om_hdr *oh; - struct msgb *msg; - - if (bts->type != GSM_BTS_TYPE_OSMOBTS) { - LOGPC(DNM, LOGL_NOTICE, "Getting attributes from BTS%d type %s is not supported.\n", - bts->nr, btstype2str(bts->type)); - return -EINVAL; - } - - DEBUGP(DNM, "Get Attr (bts=%d)\n", bts->nr); - - msg = nm_msgb_alloc(); - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, attr_len, NM_MT_GET_ATTR, obj_class, - bts_nr, trx_nr, ts_nr); - msgb_tl16v_put(msg, NM_ATT_LIST_REQ_ATTR, attr_len, attr); - - return abis_nm_sendmsg(bts, msg); -} - -/* Chapter 8.6.1 */ -int abis_nm_set_bts_attr(struct gsm_bts *bts, uint8_t *attr, int attr_len) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - uint8_t *cur; - - DEBUGP(DNM, "Set BTS Attr (bts=%d)\n", bts->nr); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, attr_len, NM_MT_SET_BTS_ATTR, NM_OC_BTS, bts->bts_nr, 0xff, 0xff); - cur = msgb_put(msg, attr_len); - memcpy(cur, attr, attr_len); - - return abis_nm_sendmsg(bts, msg); -} - -/* Chapter 8.6.2 */ -int abis_nm_set_radio_attr(struct gsm_bts_trx *trx, uint8_t *attr, int attr_len) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - uint8_t *cur; - - DEBUGP(DNM, "Set TRX Attr (bts=%d,trx=%d)\n", trx->bts->nr, trx->nr); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, attr_len, NM_MT_SET_RADIO_ATTR, NM_OC_RADIO_CARRIER, - trx->bts->bts_nr, trx->nr, 0xff); - cur = msgb_put(msg, attr_len); - memcpy(cur, attr, attr_len); - - return abis_nm_sendmsg(trx->bts, msg); -} - -int abis_nm_update_max_power_red(struct gsm_bts_trx *trx) -{ - uint8_t attr[] = { NM_ATT_RF_MAXPOWR_R, trx->max_power_red / 2 }; - return abis_nm_set_radio_attr(trx, attr, ARRAY_SIZE(attr)); -} - -static int verify_chan_comb(struct gsm_bts_trx_ts *ts, uint8_t chan_comb, - const char **reason) -{ - int i; - - *reason = "Reason unknown"; - - /* As it turns out, the BS-11 has some very peculiar restrictions - * on the channel combinations it allows */ - switch (ts->trx->bts->type) { - case GSM_BTS_TYPE_BS11: - switch (chan_comb) { - case NM_CHANC_TCHHalf: - case NM_CHANC_TCHHalf2: - case NM_CHANC_OSMO_TCHFull_TCHHalf_PDCH: - /* not supported */ - *reason = "TCH/H is not supported."; - return -EINVAL; - case NM_CHANC_SDCCH: - /* only one SDCCH/8 per TRX */ - for (i = 0; i < TRX_NR_TS; i++) { - if (i == ts->nr) - continue; - if (ts->trx->ts[i].nm_chan_comb == - NM_CHANC_SDCCH) { - *reason = "Only one SDCCH/8 per TRX allowed."; - return -EINVAL; - } - } - /* not allowed for TS0 of BCCH-TRX */ - if (ts->trx == ts->trx->bts->c0 && - ts->nr == 0) { - *reason = "SDCCH/8 must be on TS0."; - return -EINVAL; - } - - /* not on the same TRX that has a BCCH+SDCCH4 - * combination */ - if (ts->trx != ts->trx->bts->c0 && - (ts->trx->ts[0].nm_chan_comb == 5 || - ts->trx->ts[0].nm_chan_comb == 8)) { - *reason = "SDCCH/8 and BCCH must be on the same TRX."; - return -EINVAL; - } - break; - case NM_CHANC_mainBCCH: - case NM_CHANC_BCCHComb: - /* allowed only for TS0 of C0 */ - if (ts->trx != ts->trx->bts->c0 || ts->nr != 0) { - *reason = "Main BCCH must be on TS0."; - return -EINVAL; - } - break; - case NM_CHANC_BCCH: - /* allowed only for TS 2/4/6 of C0 */ - if (ts->trx != ts->trx->bts->c0) { - *reason = "BCCH must be on C0."; - return -EINVAL; - } - if (ts->nr != 2 && ts->nr != 4 && ts->nr != 6) { - *reason = "BCCH must be on TS 2/4/6."; - return -EINVAL; - } - break; - case 8: /* this is not like 08.58, but in fact - * FCCH+SCH+BCCH+CCCH+SDCCH/4+SACCH/C4+CBCH */ - /* FIXME: only one CBCH allowed per cell */ - break; - } - break; - case GSM_BTS_TYPE_NANOBTS: - switch (ts->nr) { - case 0: - if (ts->trx->nr == 0) { - /* only on TRX0 */ - switch (chan_comb) { - case NM_CHANC_BCCH: - case NM_CHANC_mainBCCH: - case NM_CHANC_BCCHComb: - return 0; - break; - default: - *reason = "TS0 of TRX0 must carry a BCCH."; - return -EINVAL; - } - } else { - switch (chan_comb) { - case NM_CHANC_TCHFull: - case NM_CHANC_TCHHalf: - case NM_CHANC_IPAC_TCHFull_TCHHalf: - return 0; - default: - *reason = "TS0 must carry a TCH/F or TCH/H."; - return -EINVAL; - } - } - break; - case 1: - if (ts->trx->nr == 0) { - switch (chan_comb) { - case NM_CHANC_SDCCH_CBCH: - if (ts->trx->ts[0].nm_chan_comb == - NM_CHANC_mainBCCH) - return 0; - *reason = "TS0 must be the main BCCH for CBCH."; - return -EINVAL; - case NM_CHANC_SDCCH: - case NM_CHANC_TCHFull: - case NM_CHANC_TCHHalf: - case NM_CHANC_IPAC_TCHFull_TCHHalf: - case NM_CHANC_IPAC_TCHFull_PDCH: - case NM_CHANC_OSMO_TCHFull_TCHHalf_PDCH: - return 0; - default: - *reason = "TS1 must carry a CBCH, SDCCH or TCH."; - return -EINVAL; - } - } else { - switch (chan_comb) { - case NM_CHANC_SDCCH: - case NM_CHANC_TCHFull: - case NM_CHANC_TCHHalf: - case NM_CHANC_IPAC_TCHFull_TCHHalf: - return 0; - default: - *reason = "TS1 must carry a SDCCH or TCH."; - return -EINVAL; - } - } - break; - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - switch (chan_comb) { - case NM_CHANC_TCHFull: - case NM_CHANC_TCHHalf: - case NM_CHANC_IPAC_TCHFull_TCHHalf: - return 0; - case NM_CHANC_IPAC_PDCH: - case NM_CHANC_IPAC_TCHFull_PDCH: - case NM_CHANC_OSMO_TCHFull_TCHHalf_PDCH: - if (ts->trx->nr == 0) - return 0; - else { - *reason = "PDCH must be on TRX0."; - return -EINVAL; - } - } - break; - } - *reason = "Unknown combination"; - return -EINVAL; - case GSM_BTS_TYPE_OSMOBTS: - /* no known restrictions */ - return 0; - default: - /* unknown BTS type */ - return 0; - } - return 0; -} - -/* Chapter 8.6.3 */ -int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, uint8_t chan_comb) -{ - struct gsm_bts *bts = ts->trx->bts; - struct abis_om_hdr *oh; - uint8_t zero = 0x00; - struct msgb *msg = nm_msgb_alloc(); - uint8_t len = 2 + 2; - const char *reason = NULL; - - if (bts->type == GSM_BTS_TYPE_BS11) - len += 4 + 2 + 2 + 3; - - DEBUGP(DNM, "Set Chan Attr %s\n", gsm_ts_name(ts)); - if (verify_chan_comb(ts, chan_comb, &reason) < 0) { - msgb_free(msg); - LOGP(DNM, LOGL_ERROR, - "Invalid Channel Combination %d on %s. Reason: %s\n", - chan_comb, gsm_ts_name(ts), reason); - return -EINVAL; - } - ts->nm_chan_comb = chan_comb; - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, len, NM_MT_SET_CHAN_ATTR, - NM_OC_CHANNEL, bts->bts_nr, - ts->trx->nr, ts->nr); - msgb_tv_put(msg, NM_ATT_CHAN_COMB, chan_comb); - if (ts->hopping.enabled) { - unsigned int i; - uint8_t *len; - - msgb_tv_put(msg, NM_ATT_HSN, ts->hopping.hsn); - msgb_tv_put(msg, NM_ATT_MAIO, ts->hopping.maio); - - /* build the ARFCN list */ - msgb_put_u8(msg, NM_ATT_ARFCN_LIST); - len = msgb_put(msg, 1); - *len = 0; - for (i = 0; i < ts->hopping.arfcns.data_len*8; i++) { - if (bitvec_get_bit_pos(&ts->hopping.arfcns, i)) { - msgb_put_u16(msg, i); - /* At least BS-11 wants a TLV16 here */ - if (bts->type == GSM_BTS_TYPE_BS11) - *len += 1; - else - *len += sizeof(uint16_t); - } - } - } - msgb_tv_put(msg, NM_ATT_TSC, gsm_ts_tsc(ts)); /* training sequence */ - if (bts->type == GSM_BTS_TYPE_BS11) - msgb_tlv_put(msg, 0x59, 1, &zero); - - return abis_nm_sendmsg(bts, msg); -} - -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) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - uint8_t msgtype = NM_MT_SW_ACT_REQ_ACK; - uint8_t len = att_len; - - if (nack) { - len += 2; - msgtype = NM_MT_SW_ACT_REQ_NACK; - } - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, att_len, msgtype, obj_class, i1, i2, i3); - - if (attr) { - uint8_t *ptr = msgb_put(msg, att_len); - memcpy(ptr, attr, att_len); - } - if (nack) - msgb_tv_put(msg, NM_ATT_NACK_CAUSES, NM_NACK_OBJCLASS_NOTSUPP); - - return abis_nm_sendmsg_direct(bts, msg); -} - -int abis_nm_raw_msg(struct gsm_bts *bts, int len, uint8_t *rawmsg) -{ - struct msgb *msg = nm_msgb_alloc(); - struct abis_om_hdr *oh; - uint8_t *data; - - oh = (struct abis_om_hdr *) msgb_put(msg, sizeof(*oh)); - fill_om_hdr(oh, len); - data = msgb_put(msg, len); - memcpy(data, rawmsg, len); - - return abis_nm_sendmsg(bts, msg); -} - -/* Siemens specific commands */ -static int __simple_cmd(struct gsm_bts *bts, uint8_t msg_type) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 0, msg_type, NM_OC_SITE_MANAGER, - 0xff, 0xff, 0xff); - - return abis_nm_sendmsg(bts, msg); -} - -/* Chapter 8.9.2 */ -int abis_nm_opstart(struct gsm_bts *bts, uint8_t obj_class, uint8_t i0, uint8_t i1, uint8_t i2) -{ - struct abis_om_hdr *oh; - struct abis_om_fom_hdr *foh; - struct msgb *msg = nm_msgb_alloc(); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - foh = fill_om_fom_hdr(oh, 0, NM_MT_OPSTART, obj_class, i0, i1, i2); - - abis_nm_debugp_foh(DNM, foh); - DEBUGPC(DNM, "Sending OPSTART\n"); - - return abis_nm_sendmsg(bts, msg); -} - -/* Chapter 8.8.5 */ -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) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 2, NM_MT_CHG_ADM_STATE, obj_class, i0, i1, i2); - msgb_tv_put(msg, NM_ATT_ADM_STATE, adm_state); - - return abis_nm_sendmsg(bts, msg); -} - -int abis_nm_conn_mdrop_link(struct gsm_bts *bts, uint8_t e1_port0, uint8_t ts0, - uint8_t e1_port1, uint8_t ts1) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - uint8_t *attr; - - DEBUGP(DNM, "CONNECT MDROP LINK E1=(%u,%u) -> E1=(%u, %u)\n", - e1_port0, ts0, e1_port1, ts1); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 6, NM_MT_CONN_MDROP_LINK, - NM_OC_SITE_MANAGER, 0x00, 0x00, 0x00); - - attr = msgb_put(msg, 3); - attr[0] = NM_ATT_MDROP_LINK; - attr[1] = e1_port0; - attr[2] = ts0; - - attr = msgb_put(msg, 3); - attr[0] = NM_ATT_MDROP_NEXT; - attr[1] = e1_port1; - attr[2] = ts1; - - return abis_nm_sendmsg(bts, msg); -} - -/* Chapter 8.7.1 */ -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) -{ - struct abis_om_hdr *oh; - - DEBUGP(DNM, "PEFORM TEST %s\n", abis_nm_test_name(test_nr)); - - if (!msg) - msg = nm_msgb_alloc(); - - msgb_tv_push(msg, NM_ATT_AUTON_REPORT, auton_report); - msgb_tv_push(msg, NM_ATT_TEST_NO, test_nr); - oh = (struct abis_om_hdr *) msgb_push(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, msgb_l3len(msg), NM_MT_PERF_TEST, - obj_class, bts_nr, trx_nr, ts_nr); - - return abis_nm_sendmsg(bts, msg); -} - -int abis_nm_event_reports(struct gsm_bts *bts, int on) -{ - if (on == 0) - return __simple_cmd(bts, NM_MT_STOP_EVENT_REP); - else - return __simple_cmd(bts, NM_MT_REST_EVENT_REP); -} - -/* Siemens (or BS-11) specific commands */ - -int abis_nm_bs11_bsc_disconnect(struct gsm_bts *bts, int reconnect) -{ - if (reconnect == 0) - return __simple_cmd(bts, NM_MT_BS11_DISCONNECT); - else - return __simple_cmd(bts, NM_MT_BS11_RECONNECT); -} - -int abis_nm_bs11_restart(struct gsm_bts *bts) -{ - return __simple_cmd(bts, NM_MT_BS11_RESTART); -} - - -struct bs11_date_time { - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t min; - uint8_t sec; -} __attribute__((packed)); - - -void get_bs11_date_time(struct bs11_date_time *aet) -{ - time_t t; - struct tm *tm; - - t = time(NULL); - tm = localtime(&t); - aet->sec = tm->tm_sec; - aet->min = tm->tm_min; - aet->hour = tm->tm_hour; - aet->day = tm->tm_mday; - aet->month = tm->tm_mon; - aet->year = htons(1900 + tm->tm_year); -} - -int abis_nm_bs11_reset_resource(struct gsm_bts *bts) -{ - return __simple_cmd(bts, NM_MT_BS11_RESET_RESOURCE); -} - -int abis_nm_bs11_db_transmission(struct gsm_bts *bts, int begin) -{ - if (begin) - return __simple_cmd(bts, NM_MT_BS11_BEGIN_DB_TX); - else - return __simple_cmd(bts, NM_MT_BS11_END_DB_TX); -} - -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) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - uint8_t *cur; - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, attr_len, NM_MT_BS11_CREATE_OBJ, - NM_OC_BS11, type, 0, idx); - cur = msgb_put(msg, attr_len); - memcpy(cur, attr, attr_len); - - return abis_nm_sendmsg(bts, msg); -} - -int abis_nm_bs11_delete_object(struct gsm_bts *bts, - enum abis_bs11_objtype type, uint8_t idx) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 0, NM_MT_BS11_DELETE_OBJ, - NM_OC_BS11, type, 0, idx); - - return abis_nm_sendmsg(bts, msg); -} - -int abis_nm_bs11_create_envaBTSE(struct gsm_bts *bts, uint8_t idx) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - uint8_t zero = 0x00; - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 3, NM_MT_BS11_CREATE_OBJ, - NM_OC_BS11_ENVABTSE, 0, idx, 0xff); - msgb_tlv_put(msg, 0x99, 1, &zero); - - return abis_nm_sendmsg(bts, msg); -} - -int abis_nm_bs11_create_bport(struct gsm_bts *bts, uint8_t idx) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 0, NM_MT_BS11_CREATE_OBJ, NM_OC_BS11_BPORT, - idx, 0xff, 0xff); - - return abis_nm_sendmsg(bts, msg); -} - -int abis_nm_bs11_delete_bport(struct gsm_bts *bts, uint8_t idx) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 0, NM_MT_BS11_DELETE_OBJ, NM_OC_BS11_BPORT, - idx, 0xff, 0xff); - - return abis_nm_sendmsg(bts, msg); -} - -static const uint8_t sm_attr[] = { NM_ATT_TEI, NM_ATT_ABIS_CHANNEL }; -int abis_nm_bs11_get_oml_tei_ts(struct gsm_bts *bts) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 2+sizeof(sm_attr), NM_MT_GET_ATTR, NM_OC_SITE_MANAGER, - 0xff, 0xff, 0xff); - msgb_tlv_put(msg, NM_ATT_LIST_REQ_ATTR, sizeof(sm_attr), sm_attr); - - return abis_nm_sendmsg(bts, msg); -} - -/* like abis_nm_conn_terr_traf + set_tei */ -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) -{ - struct abis_om_hdr *oh; - struct abis_nm_channel *ch; - struct msgb *msg = nm_msgb_alloc(); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, sizeof(*ch)+2, NM_MT_BS11_SET_ATTR, - NM_OC_SITE_MANAGER, 0xff, 0xff, 0xff); - - ch = (struct abis_nm_channel *) msgb_put(msg, sizeof(*ch)); - fill_nm_channel(ch, e1_port, e1_timeslot, e1_subslot); - msgb_tv_put(msg, NM_ATT_TEI, tei); - - return abis_nm_sendmsg(bts, msg); -} - -int abis_nm_bs11_set_trx_power(struct gsm_bts_trx *trx, uint8_t level) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 3, NM_MT_BS11_SET_ATTR, - NM_OC_BS11, BS11_OBJ_PA, 0x00, trx->nr); - msgb_tlv_put(msg, NM_ATT_BS11_TXPWR, 1, &level); - - return abis_nm_sendmsg(trx->bts, msg); -} - -int abis_nm_bs11_get_trx_power(struct gsm_bts_trx *trx) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - uint8_t attr = NM_ATT_BS11_TXPWR; - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 2+sizeof(attr), NM_MT_GET_ATTR, - NM_OC_BS11, BS11_OBJ_PA, 0x00, trx->nr); - msgb_tlv_put(msg, NM_ATT_LIST_REQ_ATTR, sizeof(attr), &attr); - - return abis_nm_sendmsg(trx->bts, msg); -} - -int abis_nm_bs11_get_pll_mode(struct gsm_bts *bts) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - uint8_t attr[] = { NM_ATT_BS11_PLL_MODE }; - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 2+sizeof(attr), NM_MT_GET_ATTR, - NM_OC_BS11, BS11_OBJ_LI, 0x00, 0x00); - msgb_tlv_put(msg, NM_ATT_LIST_REQ_ATTR, sizeof(attr), attr); - - return abis_nm_sendmsg(bts, msg); -} - -int abis_nm_bs11_get_cclk(struct gsm_bts *bts) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - uint8_t attr[] = { NM_ATT_BS11_CCLK_ACCURACY, - NM_ATT_BS11_CCLK_TYPE }; - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 2+sizeof(attr), NM_MT_GET_ATTR, - NM_OC_BS11, BS11_OBJ_CCLK, 0x00, 0x00); - msgb_tlv_put(msg, NM_ATT_LIST_REQ_ATTR, sizeof(attr), attr); - - return abis_nm_sendmsg(bts, msg); - -} - -//static const uint8_t bs11_logon_c7[] = { 0x07, 0xd9, 0x01, 0x11, 0x0d, 0x10, 0x20 }; - -int abis_nm_bs11_factory_logon(struct gsm_bts *bts, int on) -{ - return abis_nm_bs11_logon(bts, 0x02, "FACTORY", on); -} - -int abis_nm_bs11_infield_logon(struct gsm_bts *bts, int on) -{ - return abis_nm_bs11_logon(bts, 0x03, "FIELD ", on); -} - -int abis_nm_bs11_logon(struct gsm_bts *bts, uint8_t level, const char *name, int on) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - struct bs11_date_time bdt; - - get_bs11_date_time(&bdt); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - if (on) { - uint8_t len = 3*2 + sizeof(bdt) - + 1 + strlen(name); - fill_om_fom_hdr(oh, len, NM_MT_BS11_LMT_LOGON, - NM_OC_BS11_BTSE, 0xff, 0xff, 0xff); - msgb_tlv_put(msg, NM_ATT_BS11_LMT_LOGIN_TIME, - sizeof(bdt), (uint8_t *) &bdt); - msgb_tlv_put(msg, NM_ATT_BS11_LMT_USER_ACC_LEV, - 1, &level); - msgb_tlv_put(msg, NM_ATT_BS11_LMT_USER_NAME, - strlen(name), (uint8_t *)name); - } else { - fill_om_fom_hdr(oh, 0, NM_MT_BS11_LMT_LOGOFF, - NM_OC_BS11_BTSE, 0xff, 0xff, 0xff); - } - - return abis_nm_sendmsg(bts, msg); -} - -int abis_nm_bs11_set_trx1_pw(struct gsm_bts *bts, const char *password) -{ - struct abis_om_hdr *oh; - struct msgb *msg; - - if (strlen(password) != 10) - return -EINVAL; - - msg = nm_msgb_alloc(); - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 2+strlen(password), NM_MT_BS11_SET_ATTR, - NM_OC_BS11, BS11_OBJ_TRX1, 0x00, 0x00); - msgb_tlv_put(msg, NM_ATT_BS11_PASSWORD, 10, (const uint8_t *)password); - - return abis_nm_sendmsg(bts, msg); -} - -/* change the BS-11 PLL Mode to either locked (E1 derived) or standalone */ -int abis_nm_bs11_set_pll_locked(struct gsm_bts *bts, int locked) -{ - struct abis_om_hdr *oh; - struct msgb *msg; - uint8_t tlv_value; - - msg = nm_msgb_alloc(); - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 3, NM_MT_BS11_SET_ATTR, NM_OC_BS11, - BS11_OBJ_LI, 0x00, 0x00); - - if (locked) - tlv_value = BS11_LI_PLL_LOCKED; - else - tlv_value = BS11_LI_PLL_STANDALONE; - - msgb_tlv_put(msg, NM_ATT_BS11_PLL_MODE, 1, &tlv_value); - - return abis_nm_sendmsg(bts, msg); -} - -/* Set the calibration value of the PLL (work value/set value) - * It depends on the login which one is changed */ -int abis_nm_bs11_set_pll(struct gsm_bts *bts, int value) -{ - struct abis_om_hdr *oh; - struct msgb *msg; - uint8_t tlv_value[2]; - - msg = nm_msgb_alloc(); - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 3, NM_MT_BS11_SET_ATTR, NM_OC_BS11, - BS11_OBJ_TRX1, 0x00, 0x00); - - tlv_value[0] = value>>8; - tlv_value[1] = value&0xff; - - msgb_tlv_put(msg, NM_ATT_BS11_PLL, 2, tlv_value); - - return abis_nm_sendmsg(bts, msg); -} - -int abis_nm_bs11_get_state(struct gsm_bts *bts) -{ - return __simple_cmd(bts, NM_MT_BS11_GET_STATE); -} - -/* BS11 SWL */ - -void *tall_fle_ctx; - -struct abis_nm_bs11_sw { - struct gsm_bts *bts; - char swl_fname[PATH_MAX]; - uint8_t win_size; - int forced; - struct llist_head file_list; - gsm_cbfn *user_cb; /* specified by the user */ -}; -static struct abis_nm_bs11_sw _g_bs11_sw, *g_bs11_sw = &_g_bs11_sw; - -struct file_list_entry { - struct llist_head list; - char fname[PATH_MAX]; -}; - -struct file_list_entry *fl_dequeue(struct llist_head *queue) -{ - struct llist_head *lh; - - if (llist_empty(queue)) - return NULL; - - lh = queue->next; - llist_del(lh); - - return llist_entry(lh, struct file_list_entry, list); -} - -static int bs11_read_swl_file(struct abis_nm_bs11_sw *bs11_sw) -{ - char linebuf[255]; - struct llist_head *lh, *lh2; - FILE *swl; - int rc = 0; - - swl = fopen(bs11_sw->swl_fname, "r"); - if (!swl) - return -ENODEV; - - /* zero the stale file list, if any */ - llist_for_each_safe(lh, lh2, &bs11_sw->file_list) { - llist_del(lh); - talloc_free(lh); - } - - while (fgets(linebuf, sizeof(linebuf), swl)) { - char file_id[12+1]; - char file_version[80+1]; - struct file_list_entry *fle; - static char dir[PATH_MAX]; - - if (strlen(linebuf) < 4) - continue; - - rc = sscanf(linebuf+4, "%12s:%80s\r\n", file_id, file_version); - if (rc < 0) { - perror("ERR parsing SWL file"); - rc = -EINVAL; - goto out; - } - if (rc < 2) - continue; - - fle = talloc_zero(tall_fle_ctx, struct file_list_entry); - if (!fle) { - rc = -ENOMEM; - goto out; - } - - /* construct new filename */ - osmo_strlcpy(dir, bs11_sw->swl_fname, sizeof(dir)); - strncat(fle->fname, dirname(dir), sizeof(fle->fname) - 1); - strcat(fle->fname, "/"); - strncat(fle->fname, file_id, sizeof(fle->fname) - 1 -strlen(fle->fname)); - - llist_add_tail(&fle->list, &bs11_sw->file_list); - } - -out: - fclose(swl); - return rc; -} - -/* bs11 swload specific callback, passed to abis_nm core swload */ -static int bs11_swload_cbfn(unsigned int hook, unsigned int event, - struct msgb *msg, void *data, void *param) -{ - struct abis_nm_bs11_sw *bs11_sw = data; - struct file_list_entry *fle; - int rc = 0; - - switch (event) { - case NM_MT_LOAD_END_ACK: - fle = fl_dequeue(&bs11_sw->file_list); - if (fle) { - /* start download the next file of our file list */ - rc = abis_nm_software_load(bs11_sw->bts, 0xff, fle->fname, - bs11_sw->win_size, - bs11_sw->forced, - &bs11_swload_cbfn, bs11_sw); - talloc_free(fle); - } else { - /* activate the SWL */ - rc = abis_nm_software_activate(bs11_sw->bts, - bs11_sw->swl_fname, - bs11_swload_cbfn, - bs11_sw); - } - break; - case NM_MT_LOAD_SEG_ACK: - case NM_MT_LOAD_END_NACK: - case NM_MT_LOAD_INIT_ACK: - case NM_MT_LOAD_INIT_NACK: - case NM_MT_ACTIVATE_SW_NACK: - case NM_MT_ACTIVATE_SW_ACK: - default: - /* fallthrough to the user callback */ - if (bs11_sw->user_cb) - rc = bs11_sw->user_cb(hook, event, msg, NULL, NULL); - break; - } - - return rc; -} - -/* Siemens provides a SWL file that is a mere listing of all the other - * files that are part of a software release. We need to upload first - * the list file, and then each file that is listed in the list file */ -int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname, - uint8_t win_size, int forced, gsm_cbfn *cbfn) -{ - struct abis_nm_bs11_sw *bs11_sw = g_bs11_sw; - struct file_list_entry *fle; - int rc = 0; - - INIT_LLIST_HEAD(&bs11_sw->file_list); - bs11_sw->bts = bts; - bs11_sw->win_size = win_size; - bs11_sw->user_cb = cbfn; - bs11_sw->forced = forced; - - osmo_strlcpy(bs11_sw->swl_fname, fname, sizeof(bs11_sw->swl_fname)); - rc = bs11_read_swl_file(bs11_sw); - if (rc < 0) - return rc; - - /* dequeue next item in file list */ - fle = fl_dequeue(&bs11_sw->file_list); - if (!fle) - return -EINVAL; - - /* start download the next file of our file list */ - rc = abis_nm_software_load(bts, 0xff, fle->fname, win_size, forced, - bs11_swload_cbfn, bs11_sw); - talloc_free(fle); - return rc; -} - -#if 0 -static uint8_t req_attr_btse[] = { - NM_ATT_ADM_STATE, NM_ATT_BS11_LMT_LOGON_SESSION, - NM_ATT_BS11_LMT_LOGIN_TIME, NM_ATT_BS11_LMT_USER_ACC_LEV, - NM_ATT_BS11_LMT_USER_NAME, - - 0xaf, NM_ATT_BS11_RX_OFFSET, NM_ATT_BS11_VENDOR_NAME, - - NM_ATT_BS11_SW_LOAD_INTENDED, NM_ATT_BS11_SW_LOAD_SAFETY, - - NM_ATT_BS11_SW_LOAD_STORED }; - -static uint8_t req_attr_btsm[] = { - NM_ATT_ABIS_CHANNEL, NM_ATT_TEI, NM_ATT_BS11_ABIS_EXT_TIME, - NM_ATT_ADM_STATE, NM_ATT_AVAIL_STATUS, 0xce, NM_ATT_FILE_ID, - NM_ATT_FILE_VERSION, NM_ATT_OPER_STATE, 0xe8, NM_ATT_BS11_ALL_TEST_CATG, - NM_ATT_SW_DESCR, NM_ATT_GET_ARI }; -#endif - -static uint8_t req_attr[] = { - NM_ATT_ADM_STATE, NM_ATT_AVAIL_STATUS, 0xa8, NM_ATT_OPER_STATE, - 0xd5, 0xa1, NM_ATT_BS11_ESN_FW_CODE_NO, NM_ATT_BS11_ESN_HW_CODE_NO, - 0x42, NM_ATT_BS11_ESN_PCB_SERIAL, NM_ATT_BS11_PLL }; - -int abis_nm_bs11_get_serno(struct gsm_bts *bts) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - /* SiemensHW CCTRL object */ - fill_om_fom_hdr(oh, 2+sizeof(req_attr), NM_MT_GET_ATTR, NM_OC_BS11, - 0x03, 0x00, 0x00); - msgb_tlv_put(msg, NM_ATT_LIST_REQ_ATTR, sizeof(req_attr), req_attr); - - return abis_nm_sendmsg(bts, msg); -} - -int abis_nm_bs11_set_ext_time(struct gsm_bts *bts) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - struct bs11_date_time aet; - - get_bs11_date_time(&aet); - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - /* SiemensHW CCTRL object */ - fill_om_fom_hdr(oh, 2+sizeof(aet), NM_MT_BS11_SET_ATTR, NM_OC_SITE_MANAGER, - 0xff, 0xff, 0xff); - msgb_tlv_put(msg, NM_ATT_BS11_ABIS_EXT_TIME, sizeof(aet), (uint8_t *) &aet); - - return abis_nm_sendmsg(bts, msg); -} - -int abis_nm_bs11_get_bport_line_cfg(struct gsm_bts *bts, uint8_t bport) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - uint8_t attr = NM_ATT_BS11_LINE_CFG; - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 2+sizeof(attr), NM_MT_GET_ATTR, - NM_OC_BS11_BPORT, bport, 0xff, 0x02); - msgb_tlv_put(msg, NM_ATT_LIST_REQ_ATTR, sizeof(attr), &attr); - - return abis_nm_sendmsg(bts, msg); -} - -int abis_nm_bs11_set_bport_line_cfg(struct gsm_bts *bts, uint8_t bport, enum abis_bs11_line_cfg line_cfg) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - struct bs11_date_time aet; - - get_bs11_date_time(&aet); - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 2, NM_MT_BS11_SET_ATTR, NM_OC_BS11_BPORT, - bport, 0xff, 0x02); - msgb_tv_put(msg, NM_ATT_BS11_LINE_CFG, line_cfg); - - return abis_nm_sendmsg(bts, msg); -} - -/* ip.access nanoBTS specific commands */ -static const char ipaccess_magic[] = "com.ipaccess"; - - -static int abis_nm_rx_ipacc(struct msgb *msg) -{ - struct in_addr addr; - struct abis_om_hdr *oh = msgb_l2(msg); - struct abis_om_fom_hdr *foh; - uint8_t idstrlen = oh->data[0]; - struct tlv_parsed tp; - struct ipacc_ack_signal_data signal; - struct e1inp_sign_link *sign_link = msg->dst; - - if (strncmp((char *)&oh->data[1], ipaccess_magic, idstrlen)) { - LOGP(DNM, LOGL_ERROR, "id string is not com.ipaccess !?!\n"); - return -EINVAL; - } - - foh = (struct abis_om_fom_hdr *) (oh->data + 1 + idstrlen); - abis_nm_tlv_parse(&tp, sign_link->trx->bts, foh->data, oh->length-sizeof(*foh)); - - abis_nm_debugp_foh(DNM, foh); - - DEBUGPC(DNM, "IPACCESS(0x%02x): ", foh->msg_type); - - switch (foh->msg_type) { - case NM_MT_IPACC_RSL_CONNECT_ACK: - DEBUGPC(DNM, "RSL CONNECT ACK "); - if (TLVP_PRESENT(&tp, NM_ATT_IPACC_DST_IP)) { - memcpy(&addr, - TLVP_VAL(&tp, NM_ATT_IPACC_DST_IP), sizeof(addr)); - - DEBUGPC(DNM, "IP=%s ", inet_ntoa(addr)); - } - if (TLVP_PRESENT(&tp, NM_ATT_IPACC_DST_IP_PORT)) - DEBUGPC(DNM, "PORT=%u ", - ntohs(*((uint16_t *) - TLVP_VAL(&tp, NM_ATT_IPACC_DST_IP_PORT)))); - if (TLVP_PRESENT(&tp, NM_ATT_IPACC_STREAM_ID)) - DEBUGPC(DNM, "STREAM=0x%02x ", - *TLVP_VAL(&tp, NM_ATT_IPACC_STREAM_ID)); - DEBUGPC(DNM, "\n"); - break; - case NM_MT_IPACC_RSL_CONNECT_NACK: - LOGP(DNM, LOGL_ERROR, "RSL CONNECT NACK "); - if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES)) - LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n", - abis_nm_nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES))); - else - LOGPC(DNM, LOGL_ERROR, "\n"); - break; - case NM_MT_IPACC_SET_NVATTR_ACK: - DEBUGPC(DNM, "SET NVATTR ACK\n"); - /* FIXME: decode and show the actual attributes */ - break; - case NM_MT_IPACC_SET_NVATTR_NACK: - LOGP(DNM, LOGL_ERROR, "SET NVATTR NACK "); - if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES)) - LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n", - abis_nm_nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES))); - else - LOGPC(DNM, LOGL_ERROR, "\n"); - break; - case NM_MT_IPACC_GET_NVATTR_ACK: - DEBUGPC(DNM, "GET NVATTR ACK\n"); - /* FIXME: decode and show the actual attributes */ - break; - case NM_MT_IPACC_GET_NVATTR_NACK: - LOGPC(DNM, LOGL_ERROR, "GET NVATTR NACK "); - if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES)) - LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n", - abis_nm_nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES))); - else - LOGPC(DNM, LOGL_ERROR, "\n"); - break; - case NM_MT_IPACC_SET_ATTR_ACK: - DEBUGPC(DNM, "SET ATTR ACK\n"); - break; - case NM_MT_IPACC_SET_ATTR_NACK: - LOGPC(DNM, LOGL_ERROR, "SET ATTR NACK "); - if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES)) - LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n", - abis_nm_nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES))); - else - LOGPC(DNM, LOGL_ERROR, "\n"); - break; - default: - DEBUGPC(DNM, "unknown\n"); - break; - } - - /* signal handling */ - switch (foh->msg_type) { - case NM_MT_IPACC_RSL_CONNECT_NACK: - case NM_MT_IPACC_SET_NVATTR_NACK: - case NM_MT_IPACC_GET_NVATTR_NACK: - signal.trx = gsm_bts_trx_by_nr(sign_link->trx->bts, foh->obj_inst.trx_nr); - signal.msg_type = foh->msg_type; - osmo_signal_dispatch(SS_NM, S_NM_IPACC_NACK, &signal); - break; - case NM_MT_IPACC_SET_NVATTR_ACK: - signal.trx = gsm_bts_trx_by_nr(sign_link->trx->bts, foh->obj_inst.trx_nr); - signal.msg_type = foh->msg_type; - osmo_signal_dispatch(SS_NM, S_NM_IPACC_ACK, &signal); - break; - default: - break; - } - - return 0; -} - -/* send an ip-access manufacturer specific message */ -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) -{ - struct msgb *msg = nm_msgb_alloc(); - struct abis_om_hdr *oh; - struct abis_om_fom_hdr *foh; - uint8_t *data; - - /* construct the 12.21 OM header, observe the erroneous length */ - oh = (struct abis_om_hdr *) msgb_put(msg, sizeof(*oh)); - fill_om_hdr(oh, sizeof(*foh) + attr_len); - oh->mdisc = ABIS_OM_MDISC_MANUF; - - /* add the ip.access magic */ - data = msgb_put(msg, sizeof(ipaccess_magic)+1); - *data++ = sizeof(ipaccess_magic); - memcpy(data, ipaccess_magic, sizeof(ipaccess_magic)); - - /* fill the 12.21 FOM header */ - foh = (struct abis_om_fom_hdr *) msgb_put(msg, sizeof(*foh)); - foh->msg_type = msg_type; - foh->obj_class = obj_class; - foh->obj_inst.bts_nr = bts_nr; - foh->obj_inst.trx_nr = trx_nr; - foh->obj_inst.ts_nr = ts_nr; - - if (attr && attr_len) { - data = msgb_put(msg, attr_len); - memcpy(data, attr, attr_len); - } - - return abis_nm_sendmsg(bts, msg); -} - -/* set some attributes in NVRAM */ -int abis_nm_ipaccess_set_nvattr(struct gsm_bts_trx *trx, uint8_t *attr, - int attr_len) -{ - return abis_nm_ipaccess_msg(trx->bts, NM_MT_IPACC_SET_NVATTR, - NM_OC_BASEB_TRANSC, 0, trx->nr, 0xff, attr, - attr_len); -} - -int abis_nm_ipaccess_rsl_connect(struct gsm_bts_trx *trx, - uint32_t ip, uint16_t port, uint8_t stream) -{ - struct in_addr ia; - uint8_t attr[] = { NM_ATT_IPACC_STREAM_ID, 0, - NM_ATT_IPACC_DST_IP_PORT, 0, 0, - NM_ATT_IPACC_DST_IP, 0, 0, 0, 0 }; - - int attr_len = sizeof(attr); - - ia.s_addr = htonl(ip); - attr[1] = stream; - attr[3] = port >> 8; - attr[4] = port & 0xff; - *(uint32_t *)(attr+6) = ia.s_addr; - - /* if ip == 0, we use the default IP */ - if (ip == 0) - attr_len -= 5; - - DEBUGP(DNM, "ip.access RSL CONNECT IP=%s PORT=%u STREAM=0x%02x\n", - inet_ntoa(ia), port, stream); - - return abis_nm_ipaccess_msg(trx->bts, NM_MT_IPACC_RSL_CONNECT, - NM_OC_BASEB_TRANSC, trx->bts->bts_nr, - trx->nr, 0xff, attr, attr_len); -} - -/* restart / reboot an ip.access nanoBTS */ -int abis_nm_ipaccess_restart(struct gsm_bts_trx *trx) -{ - struct abis_om_hdr *oh; - struct msgb *msg = nm_msgb_alloc(); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); - fill_om_fom_hdr(oh, 0, NM_MT_IPACC_RESTART, NM_OC_BASEB_TRANSC, - trx->bts->nr, trx->nr, 0xff); - - return abis_nm_sendmsg_direct(trx->bts, msg); -} - -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) -{ - return abis_nm_ipaccess_msg(bts, NM_MT_IPACC_SET_ATTR, - obj_class, bts_nr, trx_nr, ts_nr, - attr, attr_len); -} - -void abis_nm_ipaccess_cgi(uint8_t *buf, struct gsm_bts *bts) -{ - /* we simply reuse the GSM48 function and overwrite the RAC - * with the Cell ID */ - gsm48_ra_id_by_bts(buf, bts); - *((uint16_t *)(buf + 5)) = htons(bts->cell_identity); -} - -void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked) -{ - int new_state = locked ? NM_STATE_LOCKED : NM_STATE_UNLOCKED; - - trx->mo.nm_state.administrative = new_state; - if (!trx->bts || !trx->bts->oml_link) - return; - - abis_nm_chg_adm_state(trx->bts, NM_OC_RADIO_CARRIER, - trx->bts->bts_nr, trx->nr, 0xff, - new_state); -} - -static const struct value_string ipacc_testres_names[] = { - { NM_IPACC_TESTRES_SUCCESS, "SUCCESS" }, - { NM_IPACC_TESTRES_TIMEOUT, "TIMEOUT" }, - { NM_IPACC_TESTRES_NO_CHANS, "NO CHANNELS" }, - { NM_IPACC_TESTRES_PARTIAL, "PARTIAL" }, - { NM_IPACC_TESTRES_STOPPED, "STOPPED" }, - { 0, NULL } -}; - -const char *ipacc_testres_name(uint8_t res) -{ - return get_value_string(ipacc_testres_names, res); -} - -void ipac_parse_cgi(struct cell_global_id *cid, const uint8_t *buf) -{ - cid->mcc = (buf[0] & 0xf) * 100; - cid->mcc += (buf[0] >> 4) * 10; - cid->mcc += (buf[1] & 0xf) * 1; - - if (buf[1] >> 4 == 0xf) { - cid->mnc = (buf[2] & 0xf) * 10; - cid->mnc += (buf[2] >> 4) * 1; - } else { - cid->mnc = (buf[2] & 0xf) * 100; - cid->mnc += (buf[2] >> 4) * 10; - cid->mnc += (buf[1] >> 4) * 1; - } - - cid->lac = ntohs(*((uint16_t *)&buf[3])); - cid->ci = ntohs(*((uint16_t *)&buf[5])); -} - -/* parse BCCH information IEI from wire format to struct ipac_bcch_info */ -int ipac_parse_bcch_info(struct ipac_bcch_info *binf, uint8_t *buf) -{ - uint8_t *cur = buf; - uint16_t len __attribute__((unused)); - - memset(binf, 0, sizeof(*binf)); - - if (cur[0] != NM_IPAC_EIE_BCCH_INFO) - return -EINVAL; - cur++; - - len = ntohs(*(uint16_t *)cur); - cur += 2; - - binf->info_type = ntohs(*(uint16_t *)cur); - cur += 2; - - if (binf->info_type & IPAC_BINF_FREQ_ERR_QUAL) - binf->freq_qual = *cur >> 2; - - binf->arfcn = (*cur++ & 3) << 8; - binf->arfcn |= *cur++; - - if (binf->info_type & IPAC_BINF_RXLEV) - binf->rx_lev = *cur & 0x3f; - cur++; - - if (binf->info_type & IPAC_BINF_RXQUAL) - binf->rx_qual = *cur & 0x7; - cur++; - - if (binf->info_type & IPAC_BINF_FREQ_ERR_QUAL) - binf->freq_err = ntohs(*(uint16_t *)cur); - cur += 2; - - if (binf->info_type & IPAC_BINF_FRAME_OFFSET) - binf->frame_offset = ntohs(*(uint16_t *)cur); - cur += 2; - - if (binf->info_type & IPAC_BINF_FRAME_NR_OFFSET) - binf->frame_nr_offset = ntohl(*(uint32_t *)cur); - cur += 4; - -#if 0 - /* Somehow this is not set correctly */ - if (binf->info_type & IPAC_BINF_BSIC) -#endif - binf->bsic = *cur & 0x3f; - cur++; - - ipac_parse_cgi(&binf->cgi, cur); - cur += 7; - - if (binf->info_type & IPAC_BINF_NEIGH_BA_SI2) { - memcpy(binf->ba_list_si2, cur, sizeof(binf->ba_list_si2)); - cur += sizeof(binf->ba_list_si2); - } - - if (binf->info_type & IPAC_BINF_NEIGH_BA_SI2bis) { - memcpy(binf->ba_list_si2bis, cur, - sizeof(binf->ba_list_si2bis)); - cur += sizeof(binf->ba_list_si2bis); - } - - if (binf->info_type & IPAC_BINF_NEIGH_BA_SI2ter) { - memcpy(binf->ba_list_si2ter, cur, - sizeof(binf->ba_list_si2ter)); - cur += sizeof(binf->ba_list_si2ter); - } - - return 0; -} - -void abis_nm_clear_queue(struct gsm_bts *bts) -{ - struct msgb *msg; - - while (!llist_empty(&bts->abis_queue)) { - msg = msgb_dequeue(&bts->abis_queue); - msgb_free(msg); - } - - bts->abis_nm_pend = 0; -} diff --git a/src/libbsc/abis_nm_ipaccess.c b/src/libbsc/abis_nm_ipaccess.c deleted file mode 100644 index b8225383a..000000000 --- a/src/libbsc/abis_nm_ipaccess.c +++ /dev/null @@ -1,87 +0,0 @@ -/* GSM Network Management (OML) messages on the A-bis interface - * Extensions for the ip.access A-bis over IP protocol*/ - -/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org> - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -/* A list of all the 'embedded' attributes of ip.access */ -enum ipa_embedded_att { - IPA_ATT_ARFCN_WHITELIST = 0x01, - IPA_ATT_ARFCN_BLACKLIST = 0x02, - IPA_ATT_FREQ_ERR_LIST = 0x03, - IPA_ATT_CHAN_USAGE_LIST = 0x04, - IPA_ATT_BCCH_INF_TYPE = 0x05, - IPA_ATT_BCCH_INF = 0x06, - IPA_ATT_CONFIG = 0x07, - IPA_ATT_RESULT_DETAILS = 0x08, - IPA_ATT_RXLEV_THRESH = 0x09, - IPA_ATT_FREQ_SYNC_OPT = 0x0a, - IPA_ATT_MAC_ADDR = 0x0b, - IPA_ATT_HW_SW_COMPAT_NR = 0x0c, - IPA_ATT_MANUF_SER_NR = 0x0d, - IPA_ATT_OEM_ID = 0x0e, - IPA_ATT_DATETIME_MANUF = 0x0f, - IPA_ATT_DATETIME_CALIB = 0x10, - IPA_ATT_BEACON_INF = 0x11, - IPA_ATT_FREQ_ERR = 0x12, - IPA_ATT_SNMP_COMM_STRING = 0x13, - IPA_ATT_SNMP_TRAP_ADDR = 0x14, - IPA_ATT_SNMP_TRAP_PORT = 0x15, - IPA_ATT_SNMP_MAN_ADDR = 0x16, - IPA_ATT_SNMP_SYS_CONTACT = 0x17, - IPA_ATT_FACTORY_ID = 0x18, - IPA_ATT_FACTORY_SERIAL = 0x19, - IPA_ATT_LOGGED_EVT_IND = 0x1a, - IPA_ATT_LOCAL_ADD_TEXT = 0x1b, - IPA_ATT_FREQ_BANDS = 0x1c, - IPA_ATT_MAX_TA = 0x1d, - IPA_ATT_CIPH_ALG = 0x1e, - IPA_ATT_CHAN_TYPES = 0x1f, - IPA_ATT_CHAN_MODES = 0x20, - IPA_ATT_GPRS_CODING_SCHEMES = 0x21, - IPA_ATT_RTP_FEATURES = 0x22, - IPA_ATT_RSL_FEATURES = 0x23, - IPA_ATT_BTS_HW_CLASS = 0x24, - IPA_ATT_BTS_ID = 0x25, - IPA_ATT_BCAST_L2_MSG = 0x26, -}; - -/* append an ip.access channel list to the given msgb */ -static int ipa_chan_list_append(struct msgb *msg, uint8_t ie, - uint16_t *arfcns, int arfcn_count) -{ - int i; - uint8_t *u8; - uint16_t *u16; - - /* tag */ - u8 = msgb_push(msg, 1); - *u8 = ie; - - /* length in octets */ - u16 = msgb_push(msg, 2); - *u16 = htons(arfcn_count * 2); - - for (i = 0; i < arfcn_count; i++) { - u16 = msgb_push(msg, 2); - *u16 = htons(arfcns[i]); - } - - return 0; -} diff --git a/src/libbsc/abis_nm_vty.c b/src/libbsc/abis_nm_vty.c deleted file mode 100644 index 6ec0a4a21..000000000 --- a/src/libbsc/abis_nm_vty.c +++ /dev/null @@ -1,191 +0,0 @@ -/* VTY interface for A-bis OML (Netowrk Management) */ - -/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org> - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <stdint.h> - -#include <arpa/inet.h> - -#include <osmocom/gsm/abis_nm.h> - -#include <openbsc/gsm_data.h> -#include <osmocom/core/msgb.h> -#include <osmocom/gsm/tlv.h> -#include <osmocom/core/talloc.h> -#include <openbsc/debug.h> -#include <openbsc/signal.h> -#include <openbsc/abis_nm.h> -#include <openbsc/vty.h> - -#include <osmocom/vty/vty.h> -#include <osmocom/vty/command.h> -#include <osmocom/vty/logging.h> -#include <osmocom/vty/telnet_interface.h> - -extern struct gsm_network *bsc_gsmnet; - -static struct cmd_node oml_node = { - OML_NODE, - "%s(oml)# ", - 1, -}; - -struct oml_node_state { - struct gsm_bts *bts; - uint8_t obj_class; - uint8_t obj_inst[3]; -}; - -static int dummy_config_write(struct vty *v) -{ - return CMD_SUCCESS; -} - -/* FIXME: auto-generate those strings from the value_string lists */ -#define NM_OBJCLASS_VTY "(site-manager|bts|radio-carrier|baseband-transceiver|channel|adjc|handover|power-contorl|btse|rack|test|envabtse|bport|gprs-nse|gprs-cell|gprs-nsvc|siemenshw)" -#define NM_OBJCLASS_VTY_HELP "Site Manager Object\n" \ - "BTS Object\n" \ - "Radio Carrier Object\n" \ - "Baseband Transceiver Object\n" \ - "Channel (Timeslot) Object\n" \ - "Adjacent Object (Siemens)\n" \ - "Handover Object (Siemens)\n" \ - "Power Control Object (Siemens)\n" \ - "BTSE Object (Siemens)\n" \ - "Rack Object (Siemens)\n" \ - "Test Object (Siemens)\n" \ - "ENVABTSE Object (Siemens)\n" \ - "BPORT Object (Siemens)\n" \ - "GPRS NSE Object (ip.access/osmo-bts)\n" \ - "GPRS Cell Object (ip.acecss/osmo-bts)\n" \ - "GPRS NSVC Object (ip.acecss/osmo-bts)\n" \ - "SIEMENSHW Object (Siemens)\n" - - -DEFUN(oml_class_inst, oml_class_inst_cmd, - "bts <0-255> oml class " NM_OBJCLASS_VTY - " instance <0-255> <0-255> <0-255>", - "BTS related commands\n" "BTS Number\n" - "Manipulate the OML managed objects\n" - "Object Class\n" NM_OBJCLASS_VTY_HELP - "Object Instance\n" "BTS Number\n" "TRX Number\n" "TS Number\n") -{ - struct gsm_bts *bts; - struct oml_node_state *oms; - int bts_nr = atoi(argv[0]); - - bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr); - if (!bts) { - vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE); - return CMD_WARNING; - } - - oms = talloc_zero(tall_bsc_ctx, struct oml_node_state); - if (!oms) - return CMD_WARNING; - - oms->bts = bts; - oms->obj_class = get_string_value(abis_nm_obj_class_names, argv[1]); - oms->obj_inst[0] = atoi(argv[2]); - oms->obj_inst[1] = atoi(argv[3]); - oms->obj_inst[2] = atoi(argv[4]); - - vty->index = oms; - vty->node = OML_NODE; - - return CMD_SUCCESS; - -} - -DEFUN(oml_classnum_inst, oml_classnum_inst_cmd, - "bts <0-255> oml class <0-255> instance <0-255> <0-255> <0-255>", - "BTS related commands\n" "BTS Number\n" - "Manipulate the OML managed objects\n" - "Object Class\n" "Object Class\n" - "Object Instance\n" "BTS Number\n" "TRX Number\n" "TS Number\n") -{ - struct gsm_bts *bts; - struct oml_node_state *oms; - int bts_nr = atoi(argv[0]); - - bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr); - if (!bts) { - vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE); - return CMD_WARNING; - } - - oms = talloc_zero(tall_bsc_ctx, struct oml_node_state); - if (!oms) - return CMD_WARNING; - - oms->bts = bts; - oms->obj_class = atoi(argv[1]); - oms->obj_inst[0] = atoi(argv[2]); - oms->obj_inst[1] = atoi(argv[3]); - oms->obj_inst[2] = atoi(argv[4]); - - vty->index = oms; - vty->node = OML_NODE; - - return CMD_SUCCESS; -} - -DEFUN(oml_chg_adm_state, oml_chg_adm_state_cmd, - "change-adm-state (locked|unlocked|shutdown|null)", - "Change the Administrative State\n" - "Locked\n" "Unlocked\n" "Shutdown\n" "NULL\n") -{ - struct oml_node_state *oms = vty->index; - enum abis_nm_adm_state state; - - state = get_string_value(abis_nm_adm_state_names, argv[0]); - - abis_nm_chg_adm_state(oms->bts, oms->obj_class, oms->obj_inst[0], - oms->obj_inst[1], oms->obj_inst[2], state); - - return CMD_SUCCESS; -} - -DEFUN(oml_opstart, oml_opstart_cmd, - "opstart", "Send an OPSTART message to the object") -{ - struct oml_node_state *oms = vty->index; - - abis_nm_opstart(oms->bts, oms->obj_class, oms->obj_inst[0], - oms->obj_inst[1], oms->obj_inst[2]); - - return CMD_SUCCESS; -} - -int abis_nm_vty_init(void) -{ - install_element(ENABLE_NODE, &oml_class_inst_cmd); - install_element(ENABLE_NODE, &oml_classnum_inst_cmd); - install_node(&oml_node, dummy_config_write); - - vty_install_default(OML_NODE); - install_element(OML_NODE, &oml_chg_adm_state_cmd); - install_element(OML_NODE, &oml_opstart_cmd); - - return 0; -} diff --git a/src/libbsc/abis_om2000.c b/src/libbsc/abis_om2000.c deleted file mode 100644 index 82a14b269..000000000 --- a/src/libbsc/abis_om2000.c +++ /dev/null @@ -1,2776 +0,0 @@ -/* 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,2016 by Harald Welte <laforge@gnumonks.org> - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - - -#include <errno.h> -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <time.h> -#include <stdint.h> - -#include <arpa/inet.h> - -#include <osmocom/core/msgb.h> -#include <osmocom/gsm/tlv.h> -#include <osmocom/core/talloc.h> -#include <osmocom/core/utils.h> -#include <osmocom/core/fsm.h> - -#include <openbsc/gsm_data.h> -#include <openbsc/debug.h> -#include <openbsc/abis_nm.h> -#include <openbsc/abis_rsl.h> -#include <openbsc/abis_om2000.h> -#include <openbsc/signal.h> -#include <osmocom/abis/e1_input.h> - -/* FIXME: move to libosmocore */ -struct osmo_fsm_inst *osmo_fsm_inst_alloc_child_id(struct osmo_fsm *fsm, - struct osmo_fsm_inst *parent, - uint32_t parent_term_event, - const char *id) -{ - struct osmo_fsm_inst *fi; - - fi = osmo_fsm_inst_alloc(fsm, parent, NULL, parent->log_level, - id ? id : parent->id); - if (!fi) { - /* indicate immediate termination to caller */ - osmo_fsm_inst_dispatch(parent, parent_term_event, NULL); - return NULL; - } - - LOGPFSM(fi, "is child of %s\n", osmo_fsm_inst_name(parent)); - - fi->proc.parent = parent; - fi->proc.parent_term_event = parent_term_event; - llist_add(&fi->proc.child, &parent->proc.children); - - return fi; -} - - -#define OM_ALLOC_SIZE 1024 -#define OM_HEADROOM_SIZE 128 - -#define OM2K_TIMEOUT 10 -#define TRX_FSM_TIMEOUT 60 -#define BTS_FSM_TIMEOUT 60 - -/* use following functions from abis_nm.c: - * om2k_msgb_alloc() - * abis_om2k_sendmsg() - */ - -struct abis_om2k_hdr { - struct abis_om_hdr om; - uint16_t msg_type; - struct abis_om2k_mo mo; - uint8_t data[0]; -} __attribute__ ((packed)); - -enum abis_om2k_msgtype { - OM2K_MSGT_ABORT_SP_CMD = 0x0000, - OM2K_MSGT_ABORT_SP_COMPL = 0x0002, - OM2K_MSGT_ALARM_REP_ACK = 0x0004, - OM2K_MSGT_ALARM_REP_NACK = 0x0005, - OM2K_MSGT_ALARM_REP = 0x0006, - OM2K_MSGT_ALARM_STATUS_REQ = 0x0008, - OM2K_MSGT_ALARM_STATUS_REQ_ACK = 0x000a, - OM2K_MSGT_ALARM_STATUS_REQ_REJ = 0x000b, - OM2K_MSGT_ALARM_STATUS_RES_ACK = 0x000c, - OM2K_MSGT_ALARM_STATUS_RES_NACK = 0x000d, - OM2K_MSGT_ALARM_STATUS_RES = 0x000e, - OM2K_MSGT_CAL_TIME_RESP = 0x0010, - OM2K_MSGT_CAL_TIME_REJ = 0x0011, - OM2K_MSGT_CAL_TIME_REQ = 0x0012, - - OM2K_MSGT_CON_CONF_REQ = 0x0014, - OM2K_MSGT_CON_CONF_REQ_ACK = 0x0016, - OM2K_MSGT_CON_CONF_REQ_REJ = 0x0017, - OM2K_MSGT_CON_CONF_RES_ACK = 0x0018, - OM2K_MSGT_CON_CONF_RES_NACK = 0x0019, - OM2K_MSGT_CON_CONF_RES = 0x001a, - - OM2K_MSGT_CONNECT_CMD = 0x001c, - OM2K_MSGT_CONNECT_COMPL = 0x001e, - OM2K_MSGT_CONNECT_REJ = 0x001f, - - OM2K_MSGT_DISABLE_REQ = 0x0028, - OM2K_MSGT_DISABLE_REQ_ACK = 0x002a, - OM2K_MSGT_DISABLE_REQ_REJ = 0x002b, - OM2K_MSGT_DISABLE_RES_ACK = 0x002c, - OM2K_MSGT_DISABLE_RES_NACK = 0x002d, - OM2K_MSGT_DISABLE_RES = 0x002e, - OM2K_MSGT_DISCONNECT_CMD = 0x0030, - OM2K_MSGT_DISCONNECT_COMPL = 0x0032, - OM2K_MSGT_DISCONNECT_REJ = 0x0033, - OM2K_MSGT_ENABLE_REQ = 0x0034, - OM2K_MSGT_ENABLE_REQ_ACK = 0x0036, - OM2K_MSGT_ENABLE_REQ_REJ = 0x0037, - OM2K_MSGT_ENABLE_RES_ACK = 0x0038, - OM2K_MSGT_ENABLE_RES_NACK = 0x0039, - OM2K_MSGT_ENABLE_RES = 0x003a, - - OM2K_MSGT_FAULT_REP_ACK = 0x0040, - OM2K_MSGT_FAULT_REP_NACK = 0x0041, - OM2K_MSGT_FAULT_REP = 0x0042, - - OM2K_MSGT_IS_CONF_REQ = 0x0060, - OM2K_MSGT_IS_CONF_REQ_ACK = 0x0062, - OM2K_MSGT_IS_CONF_REQ_REJ = 0x0063, - OM2K_MSGT_IS_CONF_RES_ACK = 0x0064, - OM2K_MSGT_IS_CONF_RES_NACK = 0x0065, - OM2K_MSGT_IS_CONF_RES = 0x0066, - - OM2K_MSGT_OP_INFO = 0x0074, - OM2K_MSGT_OP_INFO_ACK = 0x0076, - OM2K_MSGT_OP_INFO_REJ = 0x0077, - OM2K_MSGT_RESET_CMD = 0x0078, - OM2K_MSGT_RESET_COMPL = 0x007a, - OM2K_MSGT_RESET_REJ = 0x007b, - OM2K_MSGT_RX_CONF_REQ = 0x007c, - OM2K_MSGT_RX_CONF_REQ_ACK = 0x007e, - OM2K_MSGT_RX_CONF_REQ_REJ = 0x007f, - OM2K_MSGT_RX_CONF_RES_ACK = 0x0080, - OM2K_MSGT_RX_CONF_RES_NACK = 0x0081, - OM2K_MSGT_RX_CONF_RES = 0x0082, - OM2K_MSGT_START_REQ = 0x0084, - OM2K_MSGT_START_REQ_ACK = 0x0086, - OM2K_MSGT_START_REQ_REJ = 0x0087, - OM2K_MSGT_START_RES_ACK = 0x0088, - OM2K_MSGT_START_RES_NACK = 0x0089, - OM2K_MSGT_START_RES = 0x008a, - OM2K_MSGT_STATUS_REQ = 0x008c, - OM2K_MSGT_STATUS_RESP = 0x008e, - OM2K_MSGT_STATUS_REJ = 0x008f, - - OM2K_MSGT_TEST_REQ = 0x0094, - OM2K_MSGT_TEST_REQ_ACK = 0x0096, - OM2K_MSGT_TEST_REQ_REJ = 0x0097, - OM2K_MSGT_TEST_RES_ACK = 0x0098, - OM2K_MSGT_TEST_RES_NACK = 0x0099, - OM2K_MSGT_TEST_RES = 0x009a, - - OM2K_MSGT_TF_CONF_REQ = 0x00a0, - OM2K_MSGT_TF_CONF_REQ_ACK = 0x00a2, - OM2K_MSGT_TF_CONF_REQ_REJ = 0x00a3, - OM2K_MSGT_TF_CONF_RES_ACK = 0x00a4, - OM2K_MSGT_TF_CONF_RES_NACK = 0x00a5, - OM2K_MSGT_TF_CONF_RES = 0x00a6, - OM2K_MSGT_TS_CONF_REQ = 0x00a8, - OM2K_MSGT_TS_CONF_REQ_ACK = 0x00aa, - OM2K_MSGT_TS_CONF_REQ_REJ = 0x00ab, - OM2K_MSGT_TS_CONF_RES_ACK = 0x00ac, - OM2K_MSGT_TS_CONF_RES_NACK = 0x00ad, - OM2K_MSGT_TS_CONF_RES = 0x00ae, - OM2K_MSGT_TX_CONF_REQ = 0x00b0, - OM2K_MSGT_TX_CONF_REQ_ACK = 0x00b2, - OM2K_MSGT_TX_CONF_REQ_REJ = 0x00b3, - OM2K_MSGT_TX_CONF_RES_ACK = 0x00b4, - OM2K_MSGT_TX_CONF_RES_NACK = 0x00b5, - OM2K_MSGT_TX_CONF_RES = 0x00b6, - - OM2K_MSGT_CAPA_REQ = 0x00e8, - OM2K_MSGT_CAPA_REQ_ACK = 0x00ea, - OM2K_MSGT_CAPA_REQ_REJ = 0x00eb, - OM2K_MSGT_CAPA_RES = 0x00ee, - OM2K_MSGT_CAPA_RES_ACK = 0x00ec, - OM2K_MSGT_CAPA_RES_NACK = 0x00ed, - - OM2K_MSGT_NEGOT_REQ_ACK = 0x0104, - OM2K_MSGT_NEGOT_REQ_NACK = 0x0105, - OM2K_MSGT_NEGOT_REQ = 0x0106, -}; - -enum abis_om2k_dei { - OM2K_DEI_ACCORDANCE_IND = 0x00, - OM2K_DEI_BCC = 0x06, - OM2K_DEI_BS_AG_BKS_RES = 0x07, - OM2K_DEI_BSIC = 0x09, - OM2K_DEI_BA_PA_MFRMS = 0x0a, - OM2K_DEI_CBCH_INDICATOR = 0x0b, - OM2K_DEI_CCCH_OPTIONS = 0x0c, - OM2K_DEI_CAL_TIME = 0x0d, - OM2K_DEI_COMBINATION = 0x0f, - OM2K_DEI_CON_CONN_LIST = 0x10, - OM2K_DEI_DRX_DEV_MAX = 0x12, - OM2K_DEI_END_LIST_NR = 0x13, - OM2K_DEI_EXT_COND_MAP_1 = 0x14, - OM2K_DEI_EXT_COND_MAP_2 = 0x15, - OM2K_DEI_FILLING_MARKER = 0x1c, - OM2K_DEI_FN_OFFSET = 0x1d, - OM2K_DEI_FREQ_LIST = 0x1e, - OM2K_DEI_FREQ_SPEC_RX = 0x1f, - OM2K_DEI_FREQ_SPEC_TX = 0x20, - OM2K_DEI_HSN = 0x21, - OM2K_DEI_ICM_INDICATOR = 0x22, - OM2K_DEI_INT_FAULT_MAP_1A = 0x23, - OM2K_DEI_INT_FAULT_MAP_1B = 0x24, - OM2K_DEI_INT_FAULT_MAP_2A = 0x25, - OM2K_DEI_INT_FAULT_MAP_2A_EXT = 0x26, - OM2K_DEI_IS_CONN_LIST = 0x27, - OM2K_DEI_LIST_NR = 0x28, - OM2K_DEI_LOCAL_ACCESS = 0x2a, - OM2K_DEI_MAIO = 0x2b, - OM2K_DEI_MO_STATE = 0x2c, - OM2K_DEI_NY1 = 0x2d, - OM2K_DEI_OP_INFO = 0x2e, - OM2K_DEI_POWER = 0x2f, - OM2K_DEI_REASON_CODE = 0x32, - OM2K_DEI_RX_DIVERSITY = 0x33, - OM2K_DEI_REPL_UNIT_MAP = 0x34, - OM2K_DEI_RESULT_CODE = 0x35, - OM2K_DEI_T3105 = 0x38, - OM2K_DEI_TF_MODE = 0x3a, - OM2K_DEI_TS_NR = 0x3c, - OM2K_DEI_TSC = 0x3d, - OM2K_DEI_BTS_VERSION = 0x40, - OM2K_DEI_OML_IWD_VERSION = 0x41, - OM2K_DEI_RSL_IWD_VERSION = 0x42, - OM2K_DEI_OML_FUNC_MAP_1 = 0x43, - OM2K_DEI_OML_FUNC_MAP_2 = 0x44, - OM2K_DEI_RSL_FUNC_MAP_1 = 0x45, - OM2K_DEI_RSL_FUNC_MAP_2 = 0x46, - OM2K_DEI_EXT_RANGE = 0x47, - OM2K_DEI_REQ_IND = 0x48, - OM2K_DEI_REPL_UNIT_MAP_EXT = 0x50, - OM2K_DEI_ICM_BOUND_PARAMS = 0x74, - OM2K_DEI_LSC = 0x79, - OM2K_DEI_LSC_FILT_TIME = 0x7a, - OM2K_DEI_CALL_SUPV_TIME = 0x7b, - OM2K_DEI_ICM_CHAN_RATE = 0x7e, - OM2K_DEI_HW_INFO_SIG = 0x84, - OM2K_DEI_TF_SYNC_SRC = 0x86, - OM2K_DEI_TTA = 0x87, - OM2K_DEI_CAPA_SIG = 0x8a, - OM2K_DEI_NEGOT_REC1 = 0x90, - OM2K_DEI_NEGOT_REC2 = 0x91, - OM2K_DEI_ENCR_ALG = 0x92, - OM2K_DEI_INTERF_REJ_COMB = 0x94, - OM2K_DEI_FS_OFFSET = 0x98, - OM2K_DEI_EXT_COND_MAP_2_EXT = 0x9c, - OM2K_DEI_TSS_MO_STATE = 0x9d, -}; - -const struct tlv_definition om2k_att_tlvdef = { - .def = { - [OM2K_DEI_ACCORDANCE_IND] = { TLV_TYPE_TV }, - [OM2K_DEI_BCC] = { TLV_TYPE_TV }, - [OM2K_DEI_BS_AG_BKS_RES] = { TLV_TYPE_TV }, - [OM2K_DEI_BSIC] = { TLV_TYPE_TV }, - [OM2K_DEI_BA_PA_MFRMS] = { TLV_TYPE_TV }, - [OM2K_DEI_CBCH_INDICATOR] = { TLV_TYPE_TV }, - [OM2K_DEI_INT_FAULT_MAP_1A] = { TLV_TYPE_FIXED, 6 }, - [OM2K_DEI_INT_FAULT_MAP_1B] = { TLV_TYPE_FIXED, 6 }, - [OM2K_DEI_INT_FAULT_MAP_2A] = { TLV_TYPE_FIXED, 6 }, - [OM2K_DEI_INT_FAULT_MAP_2A_EXT]={ TLV_TYPE_FIXED, 6 }, - [OM2K_DEI_CCCH_OPTIONS] = { TLV_TYPE_TV }, - [OM2K_DEI_CAL_TIME] = { TLV_TYPE_FIXED, 6 }, - [OM2K_DEI_COMBINATION] = { TLV_TYPE_TV }, - [OM2K_DEI_CON_CONN_LIST] = { TLV_TYPE_TLV }, - [OM2K_DEI_DRX_DEV_MAX] = { TLV_TYPE_TV }, - [OM2K_DEI_END_LIST_NR] = { TLV_TYPE_TV }, - [OM2K_DEI_EXT_COND_MAP_1] = { TLV_TYPE_FIXED, 2 }, - [OM2K_DEI_EXT_COND_MAP_2] = { TLV_TYPE_FIXED, 2 }, - [OM2K_DEI_FILLING_MARKER] = { TLV_TYPE_TV }, - [OM2K_DEI_FN_OFFSET] = { TLV_TYPE_FIXED, 2 }, - [OM2K_DEI_FREQ_LIST] = { TLV_TYPE_TLV }, - [OM2K_DEI_FREQ_SPEC_RX] = { TLV_TYPE_FIXED, 2 }, - [OM2K_DEI_FREQ_SPEC_TX] = { TLV_TYPE_FIXED, 2 }, - [OM2K_DEI_HSN] = { TLV_TYPE_TV }, - [OM2K_DEI_ICM_INDICATOR] = { TLV_TYPE_TV }, - [OM2K_DEI_IS_CONN_LIST] = { TLV_TYPE_TLV }, - [OM2K_DEI_LIST_NR] = { TLV_TYPE_TV }, - [OM2K_DEI_LOCAL_ACCESS] = { TLV_TYPE_TV }, - [OM2K_DEI_MAIO] = { TLV_TYPE_TV }, - [OM2K_DEI_MO_STATE] = { TLV_TYPE_TV }, - [OM2K_DEI_NY1] = { TLV_TYPE_TV }, - [OM2K_DEI_OP_INFO] = { TLV_TYPE_TV }, - [OM2K_DEI_POWER] = { TLV_TYPE_TV }, - [OM2K_DEI_REASON_CODE] = { TLV_TYPE_TV }, - [OM2K_DEI_RX_DIVERSITY] = { TLV_TYPE_TV }, - [OM2K_DEI_RESULT_CODE] = { TLV_TYPE_TV }, - [OM2K_DEI_T3105] = { TLV_TYPE_TV }, - [OM2K_DEI_TF_MODE] = { TLV_TYPE_TV }, - [OM2K_DEI_TS_NR] = { TLV_TYPE_TV }, - [OM2K_DEI_TSC] = { TLV_TYPE_TV }, - [OM2K_DEI_BTS_VERSION] = { TLV_TYPE_FIXED, 12 }, - [OM2K_DEI_OML_IWD_VERSION] = { TLV_TYPE_FIXED, 6 }, - [OM2K_DEI_RSL_IWD_VERSION] = { TLV_TYPE_FIXED, 6 }, - [OM2K_DEI_OML_FUNC_MAP_1] = { TLV_TYPE_TLV }, - [OM2K_DEI_OML_FUNC_MAP_2] = { TLV_TYPE_TLV }, - [OM2K_DEI_RSL_FUNC_MAP_1] = { TLV_TYPE_TLV }, - [OM2K_DEI_RSL_FUNC_MAP_2] = { TLV_TYPE_TLV }, - [OM2K_DEI_EXT_RANGE] = { TLV_TYPE_TV }, - [OM2K_DEI_REQ_IND] = { TLV_TYPE_TV }, - [OM2K_DEI_REPL_UNIT_MAP] = { TLV_TYPE_FIXED, 6 }, - [OM2K_DEI_REPL_UNIT_MAP_EXT] = {TLV_TYPE_FIXED, 6}, - [OM2K_DEI_ICM_BOUND_PARAMS] = { TLV_TYPE_FIXED, 5 }, - [OM2K_DEI_LSC] = { TLV_TYPE_TV }, - [OM2K_DEI_LSC_FILT_TIME] = { TLV_TYPE_TV }, - [OM2K_DEI_CALL_SUPV_TIME] = { TLV_TYPE_TV }, - [OM2K_DEI_ICM_CHAN_RATE] = { TLV_TYPE_TV }, - [OM2K_DEI_HW_INFO_SIG] = { TLV_TYPE_FIXED, 2 }, - [OM2K_DEI_TF_SYNC_SRC] = { TLV_TYPE_TV }, - [OM2K_DEI_TTA] = { TLV_TYPE_TV }, - [OM2K_DEI_CAPA_SIG] = { TLV_TYPE_FIXED, 2 }, - [OM2K_DEI_NEGOT_REC1] = { TLV_TYPE_TLV }, - [OM2K_DEI_NEGOT_REC2] = { TLV_TYPE_TLV }, - [OM2K_DEI_ENCR_ALG] = { TLV_TYPE_TV }, - [OM2K_DEI_INTERF_REJ_COMB] = { TLV_TYPE_TV }, - [OM2K_DEI_FS_OFFSET] = { TLV_TYPE_FIXED, 5 }, - [OM2K_DEI_EXT_COND_MAP_2_EXT] = { TLV_TYPE_FIXED, 4 }, - [OM2K_DEI_TSS_MO_STATE] = { TLV_TYPE_FIXED, 4 }, - }, -}; - -static const struct value_string om2k_msgcode_vals[] = { - { 0x0000, "Abort SP Command" }, - { 0x0002, "Abort SP Complete" }, - { 0x0004, "Alarm Report ACK" }, - { 0x0005, "Alarm Report NACK" }, - { 0x0006, "Alarm Report" }, - { 0x0008, "Alarm Status Request" }, - { 0x000a, "Alarm Status Request Accept" }, - { 0x000b, "Alarm Status Request Reject" }, - { 0x000c, "Alarm Status Result ACK" }, - { 0x000d, "Alarm Status Result NACK" }, - { 0x000e, "Alarm Status Result" }, - { 0x0010, "Calendar Time Response" }, - { 0x0011, "Calendar Time Reject" }, - { 0x0012, "Calendar Time Request" }, - { 0x0014, "CON Configuration Request" }, - { 0x0016, "CON Configuration Request Accept" }, - { 0x0017, "CON Configuration Request Reject" }, - { 0x0018, "CON Configuration Result ACK" }, - { 0x0019, "CON Configuration Result NACK" }, - { 0x001a, "CON Configuration Result" }, - { 0x001c, "Connect Command" }, - { 0x001e, "Connect Complete" }, - { 0x001f, "Connect Reject" }, - { 0x0028, "Disable Request" }, - { 0x002a, "Disable Request Accept" }, - { 0x002b, "Disable Request Reject" }, - { 0x002c, "Disable Result ACK" }, - { 0x002d, "Disable Result NACK" }, - { 0x002e, "Disable Result" }, - { 0x0030, "Disconnect Command" }, - { 0x0032, "Disconnect Complete" }, - { 0x0033, "Disconnect Reject" }, - { 0x0034, "Enable Request" }, - { 0x0036, "Enable Request Accept" }, - { 0x0037, "Enable Request Reject" }, - { 0x0038, "Enable Result ACK" }, - { 0x0039, "Enable Result NACK" }, - { 0x003a, "Enable Result" }, - { 0x003c, "Escape Downlink Normal" }, - { 0x003d, "Escape Downlink NACK" }, - { 0x003e, "Escape Uplink Normal" }, - { 0x003f, "Escape Uplink NACK" }, - { 0x0040, "Fault Report ACK" }, - { 0x0041, "Fault Report NACK" }, - { 0x0042, "Fault Report" }, - { 0x0044, "File Package End Command" }, - { 0x0046, "File Package End Result" }, - { 0x0047, "File Package End Reject" }, - { 0x0048, "File Relation Request" }, - { 0x004a, "File Relation Response" }, - { 0x004b, "File Relation Request Reject" }, - { 0x004c, "File Segment Transfer" }, - { 0x004e, "File Segment Transfer Complete" }, - { 0x004f, "File Segment Transfer Reject" }, - { 0x0050, "HW Information Request" }, - { 0x0052, "HW Information Request Accept" }, - { 0x0053, "HW Information Request Reject" }, - { 0x0054, "HW Information Result ACK" }, - { 0x0055, "HW Information Result NACK" }, - { 0x0056, "HW Information Result" }, - { 0x0060, "IS Configuration Request" }, - { 0x0062, "IS Configuration Request Accept" }, - { 0x0063, "IS Configuration Request Reject" }, - { 0x0064, "IS Configuration Result ACK" }, - { 0x0065, "IS Configuration Result NACK" }, - { 0x0066, "IS Configuration Result" }, - { 0x0068, "Load Data End" }, - { 0x006a, "Load Data End Result" }, - { 0x006b, "Load Data End Reject" }, - { 0x006c, "Load Data Init" }, - { 0x006e, "Load Data Init Accept" }, - { 0x006f, "Load Data Init Reject" }, - { 0x0070, "Loop Control Command" }, - { 0x0072, "Loop Control Complete" }, - { 0x0073, "Loop Control Reject" }, - { 0x0074, "Operational Information" }, - { 0x0076, "Operational Information Accept" }, - { 0x0077, "Operational Information Reject" }, - { 0x0078, "Reset Command" }, - { 0x007a, "Reset Complete" }, - { 0x007b, "Reset Reject" }, - { 0x007c, "RX Configuration Request" }, - { 0x007e, "RX Configuration Request Accept" }, - { 0x007f, "RX Configuration Request Reject" }, - { 0x0080, "RX Configuration Result ACK" }, - { 0x0081, "RX Configuration Result NACK" }, - { 0x0082, "RX Configuration Result" }, - { 0x0084, "Start Request" }, - { 0x0086, "Start Request Accept" }, - { 0x0087, "Start Request Reject" }, - { 0x0088, "Start Result ACK" }, - { 0x0089, "Start Result NACK" }, - { 0x008a, "Start Result" }, - { 0x008c, "Status Request" }, - { 0x008e, "Status Response" }, - { 0x008f, "Status Reject" }, - { 0x0094, "Test Request" }, - { 0x0096, "Test Request Accept" }, - { 0x0097, "Test Request Reject" }, - { 0x0098, "Test Result ACK" }, - { 0x0099, "Test Result NACK" }, - { 0x009a, "Test Result" }, - { 0x00a0, "TF Configuration Request" }, - { 0x00a2, "TF Configuration Request Accept" }, - { 0x00a3, "TF Configuration Request Reject" }, - { 0x00a4, "TF Configuration Result ACK" }, - { 0x00a5, "TF Configuration Result NACK" }, - { 0x00a6, "TF Configuration Result" }, - { 0x00a8, "TS Configuration Request" }, - { 0x00aa, "TS Configuration Request Accept" }, - { 0x00ab, "TS Configuration Request Reject" }, - { 0x00ac, "TS Configuration Result ACK" }, - { 0x00ad, "TS Configuration Result NACK" }, - { 0x00ae, "TS Configuration Result" }, - { 0x00b0, "TX Configuration Request" }, - { 0x00b2, "TX Configuration Request Accept" }, - { 0x00b3, "TX Configuration Request Reject" }, - { 0x00b4, "TX Configuration Result ACK" }, - { 0x00b5, "TX Configuration Result NACK" }, - { 0x00b6, "TX Configuration Result" }, - { 0x00bc, "DIP Alarm Report ACK" }, - { 0x00bd, "DIP Alarm Report NACK" }, - { 0x00be, "DIP Alarm Report" }, - { 0x00c0, "DIP Alarm Status Request" }, - { 0x00c2, "DIP Alarm Status Response" }, - { 0x00c3, "DIP Alarm Status Reject" }, - { 0x00c4, "DIP Quality Report I ACK" }, - { 0x00c5, "DIP Quality Report I NACK" }, - { 0x00c6, "DIP Quality Report I" }, - { 0x00c8, "DIP Quality Report II ACK" }, - { 0x00c9, "DIP Quality Report II NACK" }, - { 0x00ca, "DIP Quality Report II" }, - { 0x00dc, "DP Configuration Request" }, - { 0x00de, "DP Configuration Request Accept" }, - { 0x00df, "DP Configuration Request Reject" }, - { 0x00e0, "DP Configuration Result ACK" }, - { 0x00e1, "DP Configuration Result NACK" }, - { 0x00e2, "DP Configuration Result" }, - { 0x00e4, "Capabilities HW Info Report ACK" }, - { 0x00e5, "Capabilities HW Info Report NACK" }, - { 0x00e6, "Capabilities HW Info Report" }, - { 0x00e8, "Capabilities Request" }, - { 0x00ea, "Capabilities Request Accept" }, - { 0x00eb, "Capabilities Request Reject" }, - { 0x00ec, "Capabilities Result ACK" }, - { 0x00ed, "Capabilities Result NACK" }, - { 0x00ee, "Capabilities Result" }, - { 0x00f0, "FM Configuration Request" }, - { 0x00f2, "FM Configuration Request Accept" }, - { 0x00f3, "FM Configuration Request Reject" }, - { 0x00f4, "FM Configuration Result ACK" }, - { 0x00f5, "FM Configuration Result NACK" }, - { 0x00f6, "FM Configuration Result" }, - { 0x00f8, "FM Report Request" }, - { 0x00fa, "FM Report Response" }, - { 0x00fb, "FM Report Reject" }, - { 0x00fc, "FM Start Command" }, - { 0x00fe, "FM Start Complete" }, - { 0x00ff, "FM Start Reject" }, - { 0x0100, "FM Stop Command" }, - { 0x0102, "FM Stop Complete" }, - { 0x0103, "FM Stop Reject" }, - { 0x0104, "Negotiation Request ACK" }, - { 0x0105, "Negotiation Request NACK" }, - { 0x0106, "Negotiation Request" }, - { 0x0108, "BTS Initiated Request ACK" }, - { 0x0109, "BTS Initiated Request NACK" }, - { 0x010a, "BTS Initiated Request" }, - { 0x010c, "Radio Channels Release Command" }, - { 0x010e, "Radio Channels Release Complete" }, - { 0x010f, "Radio Channels Release Reject" }, - { 0x0118, "Feature Control Command" }, - { 0x011a, "Feature Control Complete" }, - { 0x011b, "Feature Control Reject" }, - - { 0, NULL } -}; - -/* TS 12.21 Section 9.4: Attributes */ -static const struct value_string om2k_attr_vals[] = { - { 0x00, "Accordance indication" }, - { 0x01, "Alarm Id" }, - { 0x02, "Alarm Data" }, - { 0x03, "Alarm Severity" }, - { 0x04, "Alarm Status" }, - { 0x05, "Alarm Status Type" }, - { 0x06, "BCC" }, - { 0x07, "BS_AG_BKS_RES" }, - { 0x09, "BSIC" }, - { 0x0a, "BA_PA_MFRMS" }, - { 0x0b, "CBCH Indicator" }, - { 0x0c, "CCCH Options" }, - { 0x0d, "Calendar Time" }, - { 0x0f, "Channel Combination" }, - { 0x10, "CON Connection List" }, - { 0x11, "Data End Indication" }, - { 0x12, "DRX_DEV_MAX" }, - { 0x13, "End List Number" }, - { 0x14, "External Condition Map Class 1" }, - { 0x15, "External Condition Map Class 2" }, - { 0x16, "File Relation Indication" }, - { 0x17, "File Revision" }, - { 0x18, "File Segment Data" }, - { 0x19, "File Segment Length" }, - { 0x1a, "File Segment Sequence Number" }, - { 0x1b, "File Size" }, - { 0x1c, "Filling Marker" }, - { 0x1d, "FN Offset" }, - { 0x1e, "Frequency List" }, - { 0x1f, "Frequency Specifier RX" }, - { 0x20, "Frequency Specifier TX" }, - { 0x21, "HSN" }, - { 0x22, "ICM Indicator" }, - { 0x23, "Internal Fault Map Class 1A" }, - { 0x24, "Internal Fault Map Class 1B" }, - { 0x25, "Internal Fault Map Class 2A" }, - { 0x26, "Internal Fault Map Class 2A Extension" }, - { 0x27, "IS Connection List" }, - { 0x28, "List Number" }, - { 0x29, "File Package State Indication" }, - { 0x2a, "Local Access State" }, - { 0x2b, "MAIO" }, - { 0x2c, "MO State" }, - { 0x2d, "Ny1" }, - { 0x2e, "Operational Information" }, - { 0x2f, "Power" }, - { 0x30, "RU Position Data" }, - { 0x31, "Protocol Error" }, - { 0x32, "Reason Code" }, - { 0x33, "Receiver Diversity" }, - { 0x34, "Replacement Unit Map" }, - { 0x35, "Result Code" }, - { 0x36, "RU Revision Data" }, - { 0x38, "T3105" }, - { 0x39, "Test Loop Setting" }, - { 0x3a, "TF Mode" }, - { 0x3b, "TF Compensation Value" }, - { 0x3c, "Time Slot Number" }, - { 0x3d, "TSC" }, - { 0x3e, "RU Logical Id" }, - { 0x3f, "RU Serial Number Data" }, - { 0x40, "BTS Version" }, - { 0x41, "OML IWD Version" }, - { 0x42, "RWL IWD Version" }, - { 0x43, "OML Function Map 1" }, - { 0x44, "OML Function Map 2" }, - { 0x45, "RSL Function Map 1" }, - { 0x46, "RSL Function Map 2" }, - { 0x47, "Extended Range Indicator" }, - { 0x48, "Request Indicators" }, - { 0x49, "DIP Alarm Condition Map" }, - { 0x4a, "ES Incoming" }, - { 0x4b, "ES Outgoing" }, - { 0x4e, "SES Incoming" }, - { 0x4f, "SES Outgoing" }, - { 0x50, "Replacement Unit Map Extension" }, - { 0x52, "UAS Incoming" }, - { 0x53, "UAS Outgoing" }, - { 0x58, "DF Incoming" }, - { 0x5a, "DF Outgoing" }, - { 0x5c, "SF" }, - { 0x60, "S Bits Setting" }, - { 0x61, "CRC-4 Use Option" }, - { 0x62, "T Parameter" }, - { 0x63, "N Parameter" }, - { 0x64, "N1 Parameter" }, - { 0x65, "N3 Parameter" }, - { 0x66, "N4 Parameter" }, - { 0x67, "P Parameter" }, - { 0x68, "Q Parameter" }, - { 0x69, "BI_Q1" }, - { 0x6a, "BI_Q2" }, - { 0x74, "ICM Boundary Parameters" }, - { 0x77, "AFT" }, - { 0x78, "AFT RAI" }, - { 0x79, "Link Supervision Control" }, - { 0x7a, "Link Supervision Filtering Time" }, - { 0x7b, "Call Supervision Time" }, - { 0x7c, "Interval Length UAS Incoming" }, - { 0x7d, "Interval Length UAS Outgoing" }, - { 0x7e, "ICM Channel Rate" }, - { 0x7f, "Attribute Identifier" }, - { 0x80, "FM Frequency List" }, - { 0x81, "FM Frequency Report" }, - { 0x82, "FM Percentile" }, - { 0x83, "FM Clear Indication" }, - { 0x84, "HW Info Signature" }, - { 0x85, "MO Record" }, - { 0x86, "TF Synchronisation Source" }, - { 0x87, "TTA" }, - { 0x88, "End Segment Number" }, - { 0x89, "Segment Number" }, - { 0x8a, "Capabilities Signature" }, - { 0x8c, "File Relation List" }, - { 0x90, "Negotiation Record I" }, - { 0x91, "Negotiation Record II" }, - { 0x92, "Encryption Algorithm" }, - { 0x94, "Interference Rejection Combining" }, - { 0x95, "Dedication Information" }, - { 0x97, "Feature Code" }, - { 0x98, "FS Offset" }, - { 0x99, "ESB Timeslot" }, - { 0x9a, "Master TG Instance" }, - { 0x9b, "Master TX Chain Delay" }, - { 0x9c, "External Condition Class 2 Extension" }, - { 0x9d, "TSs MO State" }, - { 0, NULL } -}; - -const struct value_string om2k_mo_class_short_vals[] = { - { 0x01, "TRXC" }, - { 0x03, "TS" }, - { 0x04, "TF" }, - { 0x05, "IS" }, - { 0x06, "CON" }, - { 0x07, "DP" }, - { 0x0a, "CF" }, - { 0x0b, "TX" }, - { 0x0c, "RX" }, - { 0, NULL } -}; - -const struct value_string om2k_result_strings[] = { - { 0x02, "Wrong state or out of sequence" }, - { 0x03, "File error" }, - { 0x04, "Fault, unspecified" }, - { 0x05, "Tuning fault" }, - { 0x06, "Protocol error" }, - { 0x07, "MO not connected" }, - { 0x08, "Parameter error" }, - { 0x09, "Optional function not supported" }, - { 0x0a, "Local access state LOCALLY DISCONNECTED" }, - { 0, NULL } -}; - -const struct value_string om2k_accordance_strings[] = { - { 0x00, "Data according to request" }, - { 0x01, "Data not according to request" }, - { 0x02, "Inconsistent MO data" }, - { 0x03, "Capability constraint violation" }, - { 0, NULL } -}; - -const struct value_string om2k_mostate_vals[] = { - { 0x00, "RESET" }, - { 0x01, "STARTED" }, - { 0x02, "ENABLED" }, - { 0x03, "DISABLED" }, - { 0, NULL } -}; - -/* entire decoded OM2K message (header + parsed TLV) */ -struct om2k_decoded_msg { - struct abis_om2k_hdr o2h; - uint16_t msg_type; - struct tlv_parsed tp; -}; - -/* resolve the OM2000 Managed Object by BTS + MO Address */ -static struct om2k_mo * -get_om2k_mo(struct gsm_bts *bts, const struct abis_om2k_mo *abis_mo) -{ - struct om2k_mo *mo = NULL; - struct gsm_bts_trx *trx; - - switch (abis_mo->class) { - case OM2K_MO_CLS_CF: - mo = &bts->rbs2000.cf.om2k_mo; - break; - case OM2K_MO_CLS_CON: - mo = &bts->rbs2000.con.om2k_mo; - break; - case OM2K_MO_CLS_IS: - mo = &bts->rbs2000.is.om2k_mo; - break; - case OM2K_MO_CLS_TF: - mo = &bts->rbs2000.tf.om2k_mo; - break; - - case OM2K_MO_CLS_TRXC: - trx = gsm_bts_trx_num(bts, abis_mo->inst); - if (!trx) - return NULL; - mo = &trx->rbs2000.trxc.om2k_mo; - break; - case OM2K_MO_CLS_TX: - trx = gsm_bts_trx_num(bts, abis_mo->inst); - if (!trx) - return NULL; - mo = &trx->rbs2000.tx.om2k_mo; - break; - case OM2K_MO_CLS_RX: - trx = gsm_bts_trx_num(bts, abis_mo->inst); - if (!trx) - return NULL; - mo = &trx->rbs2000.rx.om2k_mo; - break; - case OM2K_MO_CLS_TS: - trx = gsm_bts_trx_num(bts, abis_mo->assoc_so); - if (!trx) - return NULL; - if (abis_mo->inst >= ARRAY_SIZE(trx->ts)) - return NULL; - mo = &trx->ts[abis_mo->inst].rbs2000.om2k_mo; - break; - default: - return NULL; - }; - - return mo; -} - -static struct msgb *om2k_msgb_alloc(void) -{ - return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, - "OM2000"); -} - -static int abis_om2k_tlv_parse(struct tlv_parsed *tp, const uint8_t *buf, int len) -{ - return tlv_parse(tp, &om2k_att_tlvdef, buf, len, 0, 0); -} - -static int abis_om2k_msg_tlv_parse(struct tlv_parsed *tp, struct abis_om2k_hdr *oh) -{ - return abis_om2k_tlv_parse(tp, oh->data, oh->om.length - 6); -} - -/* decode/parse the message */ -static int om2k_decode_msg(struct om2k_decoded_msg *odm, struct msgb *msg) -{ - struct abis_om2k_hdr *o2h = msgb_l2(msg); - odm->msg_type = ntohs(o2h->msg_type); - odm->o2h = *o2h; - return abis_om2k_msg_tlv_parse(&odm->tp, o2h); -} - -static char *om2k_mo_name(const struct abis_om2k_mo *mo) -{ - static char mo_buf[64]; - - memset(mo_buf, 0, sizeof(mo_buf)); - snprintf(mo_buf, sizeof(mo_buf), "%s/%02x/%02x/%02x", - get_value_string(om2k_mo_class_short_vals, mo->class), - mo->bts, mo->assoc_so, mo->inst); - return mo_buf; -} - -/* resolve the gsm_nm_state data structure for a given MO */ -static struct gsm_nm_state * -mo2nm_state(struct gsm_bts *bts, const struct abis_om2k_mo *mo) -{ - struct gsm_bts_trx *trx; - struct gsm_nm_state *nm_state = NULL; - - switch (mo->class) { - case OM2K_MO_CLS_TRXC: - trx = gsm_bts_trx_num(bts, mo->inst); - if (!trx) - return NULL; - nm_state = &trx->mo.nm_state; - break; - case OM2K_MO_CLS_TS: - trx = gsm_bts_trx_num(bts, mo->assoc_so); - if (!trx) - return NULL; - if (mo->inst >= ARRAY_SIZE(trx->ts)) - return NULL; - nm_state = &trx->ts[mo->inst].mo.nm_state; - break; - case OM2K_MO_CLS_TF: - nm_state = &bts->rbs2000.tf.mo.nm_state; - break; - case OM2K_MO_CLS_IS: - nm_state = &bts->rbs2000.is.mo.nm_state; - break; - case OM2K_MO_CLS_CON: - nm_state = &bts->rbs2000.con.mo.nm_state; - break; - case OM2K_MO_CLS_DP: - nm_state = &bts->rbs2000.con.mo.nm_state; - break; - case OM2K_MO_CLS_CF: - nm_state = &bts->mo.nm_state; - break; - case OM2K_MO_CLS_TX: - trx = gsm_bts_trx_num(bts, mo->inst); - if (!trx) - return NULL; - /* FIXME */ - break; - case OM2K_MO_CLS_RX: - trx = gsm_bts_trx_num(bts, mo->inst); - if (!trx) - return NULL; - /* FIXME */ - break; - } - - return nm_state; -} - -static void *mo2obj(struct gsm_bts *bts, struct abis_om2k_mo *mo) -{ - struct gsm_bts_trx *trx; - - switch (mo->class) { - case OM2K_MO_CLS_TX: - case OM2K_MO_CLS_RX: - case OM2K_MO_CLS_TRXC: - return gsm_bts_trx_num(bts, mo->inst); - case OM2K_MO_CLS_TS: - trx = gsm_bts_trx_num(bts, mo->assoc_so); - if (!trx) - return NULL; - if (mo->inst >= ARRAY_SIZE(trx->ts)) - return NULL; - return &trx->ts[mo->inst]; - case OM2K_MO_CLS_TF: - case OM2K_MO_CLS_IS: - case OM2K_MO_CLS_CON: - case OM2K_MO_CLS_DP: - case OM2K_MO_CLS_CF: - return bts; - } - - return NULL; -} - -static void update_mo_state(struct gsm_bts *bts, struct abis_om2k_mo *mo, - uint8_t mo_state) -{ - struct gsm_nm_state *nm_state = mo2nm_state(bts, mo); - struct gsm_nm_state new_state; - struct nm_statechg_signal_data nsd; - - if (!nm_state) - return; - - new_state = *nm_state; - /* NOTICE: 12.21 Availability state values != OM2000 */ - new_state.availability = mo_state; - - memset(&nsd, 0, sizeof(nsd)); - - nsd.bts = bts; - nsd.obj = mo2obj(bts, mo); - nsd.old_state = nm_state; - nsd.new_state = &new_state; - nsd.om2k_mo = mo; - - osmo_signal_dispatch(SS_NM, S_NM_STATECHG_ADM, &nsd); - - nm_state->availability = new_state.availability; -} - -static void update_op_state(struct gsm_bts *bts, const struct abis_om2k_mo *mo, - uint8_t op_state) -{ - struct gsm_nm_state *nm_state = mo2nm_state(bts, mo); - struct gsm_nm_state new_state; - - if (!nm_state) - return; - - new_state = *nm_state; - switch (op_state) { - case 1: - new_state.operational = NM_OPSTATE_ENABLED; - break; - case 0: - new_state.operational = NM_OPSTATE_DISABLED; - break; - default: - new_state.operational = NM_OPSTATE_NULL; - break; - } - - nm_state->operational = new_state.operational; -} - -static int abis_om2k_sendmsg(struct gsm_bts *bts, struct msgb *msg) -{ - struct abis_om2k_hdr *o2h; - struct gsm_bts_trx *trx; - - msg->l2h = msg->data; - o2h = (struct abis_om2k_hdr *) msg->l2h; - - /* Compute the length in the OML header */ - o2h->om.length = 6 + msgb_l2len(msg)-sizeof(*o2h); - - switch (o2h->mo.class) { - case OM2K_MO_CLS_TRXC: - case OM2K_MO_CLS_TX: - case OM2K_MO_CLS_RX: - /* Route through per-TRX OML Link to the appropriate TRX */ - trx = gsm_bts_trx_by_nr(bts, o2h->mo.inst); - if (!trx) { - LOGP(DNM, LOGL_ERROR, "MO=%s Tx Dropping msg to " - "non-existing TRX\n", om2k_mo_name(&o2h->mo)); - return -ENODEV; - } - msg->dst = trx->oml_link; - break; - case OM2K_MO_CLS_TS: - /* Route through per-TRX OML Link to the appropriate TRX */ - trx = gsm_bts_trx_by_nr(bts, o2h->mo.assoc_so); - if (!trx) { - LOGP(DNM, LOGL_ERROR, "MO=%s Tx Dropping msg to " - "non-existing TRX\n", om2k_mo_name(&o2h->mo)); - return -ENODEV; - } - msg->dst = trx->oml_link; - break; - default: - /* Route through the IXU/DXU OML Link */ - msg->dst = bts->oml_link; - break; - } - - return _abis_nm_sendmsg(msg); -} - -static void fill_om2k_hdr(struct abis_om2k_hdr *o2h, const struct abis_om2k_mo *mo, - uint16_t msg_type) -{ - o2h->om.mdisc = ABIS_OM_MDISC_FOM; - o2h->om.placement = ABIS_OM_PLACEMENT_ONLY; - o2h->om.sequence = 0; - /* We fill o2h->om.length later during om2k_sendmsg() */ - o2h->msg_type = htons(msg_type); - memcpy(&o2h->mo, mo, sizeof(o2h->mo)); -} - -static int abis_om2k_cal_time_resp(struct gsm_bts *bts) -{ - struct msgb *msg = om2k_msgb_alloc(); - struct abis_om2k_hdr *o2k; - time_t tm_t; - struct tm *tm; - - o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k)); - fill_om2k_hdr(o2k, &bts->rbs2000.cf.om2k_mo.addr, - OM2K_MSGT_CAL_TIME_RESP); - - tm_t = time(NULL); - tm = localtime(&tm_t); - - msgb_put_u8(msg, OM2K_DEI_CAL_TIME); - msgb_put_u8(msg, tm->tm_year % 100); - msgb_put_u8(msg, tm->tm_mon + 1); - msgb_put_u8(msg, tm->tm_mday); - msgb_put_u8(msg, tm->tm_hour); - msgb_put_u8(msg, tm->tm_min); - msgb_put_u8(msg, tm->tm_sec); - - return abis_om2k_sendmsg(bts, msg); -} - -static int abis_om2k_tx_simple(struct gsm_bts *bts, const struct abis_om2k_mo *mo, - uint8_t msg_type) -{ - struct msgb *msg = om2k_msgb_alloc(); - struct abis_om2k_hdr *o2k; - - o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k)); - fill_om2k_hdr(o2k, mo, msg_type); - - DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(mo), - get_value_string(om2k_msgcode_vals, msg_type)); - - return abis_om2k_sendmsg(bts, msg); -} - -int abis_om2k_tx_reset_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo) -{ - return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_RESET_CMD); -} - -int abis_om2k_tx_start_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo) -{ - return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_START_REQ); -} - -int abis_om2k_tx_status_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo) -{ - return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_STATUS_REQ); -} - -int abis_om2k_tx_connect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo) -{ - return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_CONNECT_CMD); -} - -int abis_om2k_tx_disconnect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo) -{ - return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_DISCONNECT_CMD); -} - -int abis_om2k_tx_test_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo) -{ - return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_TEST_REQ); -} - -int abis_om2k_tx_enable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo) -{ - return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_ENABLE_REQ); -} - -int abis_om2k_tx_disable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo) -{ - return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_DISABLE_REQ); -} - -int abis_om2k_tx_op_info(struct gsm_bts *bts, const struct abis_om2k_mo *mo, - uint8_t operational) -{ - struct msgb *msg = om2k_msgb_alloc(); - struct abis_om2k_hdr *o2k; - - o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k)); - fill_om2k_hdr(o2k, mo, OM2K_MSGT_OP_INFO); - - msgb_tv_put(msg, OM2K_DEI_OP_INFO, operational); - - DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(mo), - get_value_string(om2k_msgcode_vals, OM2K_MSGT_OP_INFO)); - - /* we update the state here... and send the signal at ACK */ - update_op_state(bts, mo, operational); - - return abis_om2k_sendmsg(bts, msg); -} - -int abis_om2k_tx_cap_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo) -{ - return abis_om2k_tx_simple(bts, mo, OM2K_MSGT_CAPA_REQ); -} - -static void om2k_fill_is_conn_grp(struct om2k_is_conn_grp *grp, uint16_t icp1, - uint16_t icp2, uint8_t cont_idx) -{ - grp->icp1 = htons(icp1); - grp->icp2 = htons(icp2); - grp->cont_idx = cont_idx; -} - -int abis_om2k_tx_is_conf_req(struct gsm_bts *bts) -{ - struct msgb *msg = om2k_msgb_alloc(); - struct abis_om2k_hdr *o2k; - struct is_conn_group *grp; - unsigned int num_grps = 0, i = 0; - struct om2k_is_conn_grp *cg; - - /* count number of groups in linked list */ - llist_for_each_entry(grp, &bts->rbs2000.is.conn_groups, list) - num_grps++; - - if (!num_grps) - return -EINVAL; - - /* allocate buffer for oml group array */ - cg = talloc_zero_array(bts, struct om2k_is_conn_grp, num_grps); - - /* fill array with data from linked list */ - llist_for_each_entry(grp, &bts->rbs2000.is.conn_groups, list) - om2k_fill_is_conn_grp(&cg[i++], grp->icp1, grp->icp2, grp->ci); - - o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k)); - fill_om2k_hdr(o2k, &bts->rbs2000.is.om2k_mo.addr, - OM2K_MSGT_IS_CONF_REQ); - - msgb_tv_put(msg, OM2K_DEI_LIST_NR, 1); - msgb_tv_put(msg, OM2K_DEI_END_LIST_NR, 1); - - msgb_tlv_put(msg, OM2K_DEI_IS_CONN_LIST, - num_grps * sizeof(*cg), (uint8_t *)cg); - - talloc_free(cg); - - DEBUGP(DNM, "Tx MO=%s %s\n", - om2k_mo_name(&bts->rbs2000.is.om2k_mo.addr), - get_value_string(om2k_msgcode_vals, OM2K_MSGT_IS_CONF_REQ)); - - return abis_om2k_sendmsg(bts, msg); -} - -int abis_om2k_tx_con_conf_req(struct gsm_bts *bts) -{ - struct msgb *msg = om2k_msgb_alloc(); - struct abis_om2k_hdr *o2k; - struct con_group *grp; - unsigned int num_grps = 0; - - /* count number of groups in linked list */ - llist_for_each_entry(grp, &bts->rbs2000.con.conn_groups, list) - num_grps++; - - if (!num_grps) - return -EINVAL; - - /* first build the value part of the OM2K_DEI_CON_CONN_LIST DEI */ - msgb_put_u8(msg, num_grps); - llist_for_each_entry(grp, &bts->rbs2000.con.conn_groups, list) { - struct con_path *cp; - unsigned int num_paths = 0; - llist_for_each_entry(cp, &grp->paths, list) - num_paths++; - msgb_put_u8(msg, num_paths); - llist_for_each_entry(cp, &grp->paths, list) { - struct om2k_con_path *om2k_cp; - om2k_cp = (struct om2k_con_path *) msgb_put(msg, sizeof(*om2k_cp)); - om2k_cp->ccp = htons(cp->ccp); - om2k_cp->ci = cp->ci; - om2k_cp->tag = cp->tag; - om2k_cp->tei = cp->tei; - } - } - msgb_push_u8(msg, msgb_length(msg)); - msgb_push_u8(msg, OM2K_DEI_CON_CONN_LIST); - - /* pre-pend the list number DEIs */ - msgb_tv_push(msg, OM2K_DEI_END_LIST_NR, 1); - msgb_tv_push(msg, OM2K_DEI_LIST_NR, 1); - - /* pre-pend the OM2K header */ - o2k = (struct abis_om2k_hdr *) msgb_push(msg, sizeof(*o2k)); - fill_om2k_hdr(o2k, &bts->rbs2000.con.om2k_mo.addr, - OM2K_MSGT_CON_CONF_REQ); - - DEBUGP(DNM, "Tx MO=%s %s\n", - om2k_mo_name(&bts->rbs2000.con.om2k_mo.addr), - get_value_string(om2k_msgcode_vals, OM2K_MSGT_CON_CONF_REQ)); - - return abis_om2k_sendmsg(bts, msg); -} - -static void om2k_trx_to_mo(struct abis_om2k_mo *mo, - const struct gsm_bts_trx *trx, - enum abis_om2k_mo_cls cls) -{ - mo->class = cls; - mo->bts = 0; - mo->inst = trx->nr; - mo->assoc_so = 255; -} - -static void om2k_ts_to_mo(struct abis_om2k_mo *mo, - const struct gsm_bts_trx_ts *ts) -{ - mo->class = OM2K_MO_CLS_TS; - mo->bts = 0; - mo->inst = ts->nr; - mo->assoc_so = ts->trx->nr; -} - -/* Configure a Receiver MO */ -int abis_om2k_tx_rx_conf_req(struct gsm_bts_trx *trx) -{ - struct msgb *msg = om2k_msgb_alloc(); - struct abis_om2k_hdr *o2k; - struct abis_om2k_mo mo; - - om2k_trx_to_mo(&mo, trx, OM2K_MO_CLS_RX); - - o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k)); - fill_om2k_hdr(o2k, &mo, OM2K_MSGT_RX_CONF_REQ); - - msgb_tv16_put(msg, OM2K_DEI_FREQ_SPEC_RX, trx->arfcn); - msgb_tv_put(msg, OM2K_DEI_RX_DIVERSITY, 0x02); /* A */ - - return abis_om2k_sendmsg(trx->bts, msg); -} - -/* Configure a Transmitter MO */ -int abis_om2k_tx_tx_conf_req(struct gsm_bts_trx *trx) -{ - struct msgb *msg = om2k_msgb_alloc(); - struct abis_om2k_hdr *o2k; - struct abis_om2k_mo mo; - - om2k_trx_to_mo(&mo, trx, OM2K_MO_CLS_TX); - - o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k)); - fill_om2k_hdr(o2k, &mo, OM2K_MSGT_TX_CONF_REQ); - - msgb_tv16_put(msg, OM2K_DEI_FREQ_SPEC_TX, trx->arfcn); - msgb_tv_put(msg, OM2K_DEI_POWER, trx->nominal_power-trx->max_power_red); - msgb_tv_put(msg, OM2K_DEI_FILLING_MARKER, 0); /* Filling enabled */ - msgb_tv_put(msg, OM2K_DEI_BCC, trx->bts->bsic & 0x7); - /* Dedication Information is optional */ - - return abis_om2k_sendmsg(trx->bts, msg); -} - -enum abis_om2k_tf_mode { - OM2K_TF_MODE_MASTER = 0x00, - OM2K_TF_MODE_STANDALONE = 0x01, - OM2K_TF_MODE_SLAVE = 0x02, - OM2K_TF_MODE_UNDEFINED = 0xff, -}; - -static const uint8_t fs_offset_undef[5] = { 0xff, 0xff, 0xff, 0xff, 0xff }; - -int abis_om2k_tx_tf_conf_req(struct gsm_bts *bts) -{ - struct msgb *msg = om2k_msgb_alloc(); - struct abis_om2k_hdr *o2k; - - o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k)); - fill_om2k_hdr(o2k, &bts->rbs2000.tf.om2k_mo.addr, - OM2K_MSGT_TF_CONF_REQ); - - msgb_tv_put(msg, OM2K_DEI_TF_MODE, OM2K_TF_MODE_STANDALONE); - msgb_tv_put(msg, OM2K_DEI_TF_SYNC_SRC, 0x00); - msgb_tv_fixed_put(msg, OM2K_DEI_FS_OFFSET, - sizeof(fs_offset_undef), fs_offset_undef); - - DEBUGP(DNM, "Tx MO=%s %s\n", - om2k_mo_name(&bts->rbs2000.tf.om2k_mo.addr), - get_value_string(om2k_msgcode_vals, OM2K_MSGT_TF_CONF_REQ)); - - return abis_om2k_sendmsg(bts, msg); -} - -static uint8_t pchan2comb(enum gsm_phys_chan_config pchan) -{ - switch (pchan) { - case GSM_PCHAN_CCCH: - return 4; - case GSM_PCHAN_CCCH_SDCCH4: - return 5; - case GSM_PCHAN_SDCCH8_SACCH8C: - return 3; - case GSM_PCHAN_TCH_F: - case GSM_PCHAN_TCH_H: - case GSM_PCHAN_PDCH: - case GSM_PCHAN_TCH_F_PDCH: - case GSM_PCHAN_TCH_F_TCH_H_PDCH: - return 8; - default: - return 0; - } -} - -static uint8_t ts2comb(struct gsm_bts_trx_ts *ts) -{ - switch (ts->pchan) { - case GSM_PCHAN_TCH_F_PDCH: - LOGP(DNM, LOGL_ERROR, "%s pchan %s not intended for use" - " with OM2000, use %s instead\n", - gsm_ts_and_pchan_name(ts), - gsm_pchan_name(GSM_PCHAN_TCH_F_PDCH), - gsm_pchan_name(GSM_PCHAN_TCH_F_TCH_H_PDCH)); - /* If we allowed initialization of TCH/F_PDCH, it would fail - * when we try to send the ip.access specific RSL PDCH Act - * message for it. Rather fail completely right now: */ - return 0; - case GSM_PCHAN_TCH_F_TCH_H_PDCH: - return pchan2comb(GSM_PCHAN_TCH_F); - default: - return pchan2comb(ts->pchan); - } -} - -static int put_freq_list(uint8_t *buf, uint16_t arfcn) -{ - buf[0] = 0x00; /* TX/RX address */ - buf[1] = (arfcn >> 8); - buf[2] = (arfcn & 0xff); - - return 3; -} - -/* Compute a frequency list in OM2000 fomrmat */ -static int om2k_gen_freq_list(uint8_t *list, struct gsm_bts_trx_ts *ts) -{ - uint8_t *cur = list; - int len; - - if (ts->hopping.enabled) { - unsigned int i; - for (i = 0; i < ts->hopping.arfcns.data_len*8; i++) { - if (bitvec_get_bit_pos(&ts->hopping.arfcns, i)) - cur += put_freq_list(cur, i); - } - } else - cur += put_freq_list(cur, ts->trx->arfcn); - - len = cur - list; - - return len; -} - -const uint8_t icm_bound_params[] = { 0x02, 0x06, 0x0c, 0x16, 0x06 }; - -int abis_om2k_tx_ts_conf_req(struct gsm_bts_trx_ts *ts) -{ - struct msgb *msg = om2k_msgb_alloc(); - struct abis_om2k_hdr *o2k; - struct abis_om2k_mo mo; - uint8_t freq_list[64*3]; /* BA max size: 64 ARFCN */ - int freq_list_len; - - om2k_ts_to_mo(&mo, ts); - - memset(freq_list, 0, sizeof(freq_list)); - freq_list_len = om2k_gen_freq_list(freq_list, ts); - if (freq_list_len < 0) - return freq_list_len; - - o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k)); - fill_om2k_hdr(o2k, &mo, OM2K_MSGT_TS_CONF_REQ); - - msgb_tv_put(msg, OM2K_DEI_COMBINATION, ts2comb(ts)); - msgb_tv_put(msg, OM2K_DEI_TS_NR, ts->nr); - msgb_tlv_put(msg, OM2K_DEI_FREQ_LIST, freq_list_len, freq_list); - msgb_tv_put(msg, OM2K_DEI_HSN, ts->hopping.hsn); - msgb_tv_put(msg, OM2K_DEI_MAIO, ts->hopping.maio); - msgb_tv_put(msg, OM2K_DEI_BSIC, ts->trx->bts->bsic); - msgb_tv_put(msg, OM2K_DEI_RX_DIVERSITY, 0x02); /* A */ - msgb_tv16_put(msg, OM2K_DEI_FN_OFFSET, 0); - msgb_tv_put(msg, OM2K_DEI_EXT_RANGE, 0); /* Off */ - /* Optional: Interference Rejection Combining */ - msgb_tv_put(msg, OM2K_DEI_INTERF_REJ_COMB, 0x00); - switch (ts->pchan) { - case GSM_PCHAN_CCCH: - msgb_tv_put(msg, OM2K_DEI_BA_PA_MFRMS, 0x06); - msgb_tv_put(msg, OM2K_DEI_BS_AG_BKS_RES, 0x01); - msgb_tv_put(msg, OM2K_DEI_DRX_DEV_MAX, 0x05); - /* Repeat Paging/IMM.ASS: True, Allow Paging Type 3: Yes, Page for 5 seconds (default) */ - msgb_tv_put(msg, OM2K_DEI_CCCH_OPTIONS, 0x01); - break; - case GSM_PCHAN_CCCH_SDCCH4: - msgb_tv_put(msg, OM2K_DEI_T3105, ts->trx->bts->network->T3105 / 10); - msgb_tv_put(msg, OM2K_DEI_NY1, 35); - msgb_tv_put(msg, OM2K_DEI_BA_PA_MFRMS, 0x06); - msgb_tv_put(msg, OM2K_DEI_CBCH_INDICATOR, 0); - msgb_tv_put(msg, OM2K_DEI_TSC, gsm_ts_tsc(ts)); - msgb_tv_put(msg, OM2K_DEI_BS_AG_BKS_RES, 0x01); - msgb_tv_put(msg, OM2K_DEI_ICM_INDICATOR, 0); - msgb_tv_put(msg, OM2K_DEI_DRX_DEV_MAX, 0x05); - /* Repeat Paging/IMM.ASS: True, Allow Paging Type 3: Yes, Page for 5 seconds (default) */ - msgb_tv_put(msg, OM2K_DEI_CCCH_OPTIONS, 0x01); - msgb_tv_fixed_put(msg, OM2K_DEI_ICM_BOUND_PARAMS, - sizeof(icm_bound_params), icm_bound_params); - break; - case GSM_PCHAN_SDCCH8_SACCH8C: - msgb_tv_put(msg, OM2K_DEI_T3105, ts->trx->bts->network->T3105 / 10); - msgb_tv_put(msg, OM2K_DEI_NY1, 35); - msgb_tv_put(msg, OM2K_DEI_CBCH_INDICATOR, 0); - msgb_tv_put(msg, OM2K_DEI_TSC, gsm_ts_tsc(ts)); - /* Disable RF RESOURCE INDICATION on idle channels */ - msgb_tv_put(msg, OM2K_DEI_ICM_INDICATOR, 0); - msgb_tv_fixed_put(msg, OM2K_DEI_ICM_BOUND_PARAMS, - sizeof(icm_bound_params), icm_bound_params); - break; - default: - msgb_tv_put(msg, OM2K_DEI_T3105, ts->trx->bts->network->T3105 / 10); - msgb_tv_put(msg, OM2K_DEI_NY1, 35); - msgb_tv_put(msg, OM2K_DEI_TSC, gsm_ts_tsc(ts)); - /* Disable RF RESOURCE INDICATION on idle channels */ - msgb_tv_put(msg, OM2K_DEI_ICM_INDICATOR, 0); - msgb_tv_fixed_put(msg, OM2K_DEI_ICM_BOUND_PARAMS, - sizeof(icm_bound_params), icm_bound_params); - msgb_tv_put(msg, OM2K_DEI_TTA, 10); /* Timer for Time Alignment */ - if (ts->pchan == GSM_PCHAN_TCH_H) - msgb_tv_put(msg, OM2K_DEI_ICM_CHAN_RATE, 1); /* TCH/H */ - else - msgb_tv_put(msg, OM2K_DEI_ICM_CHAN_RATE, 0); /* TCH/F */ - msgb_tv_put(msg, OM2K_DEI_LSC, 1); /* enabled */ - msgb_tv_put(msg, OM2K_DEI_LSC_FILT_TIME, 10); /* units of 100ms */ - msgb_tv_put(msg, OM2K_DEI_CALL_SUPV_TIME, 8); - msgb_tv_put(msg, OM2K_DEI_ENCR_ALG, 0x00); - /* Not sure what those below mean */ - msgb_tv_put(msg, 0x9e, 0x00); - msgb_tv_put(msg, 0x9f, 0x37); - msgb_tv_put(msg, 0xa0, 0x01); - break; - } - - DEBUGP(DNM, "Tx MO=%s %s\n", - om2k_mo_name(&mo), - get_value_string(om2k_msgcode_vals, OM2K_MSGT_TS_CONF_REQ)); - - return abis_om2k_sendmsg(ts->trx->bts, msg); -} - - -/*********************************************************************** - * OM2000 Managed Object (MO) FSM - ***********************************************************************/ - -#define S(x) (1 << (x)) - -enum om2k_event_name { - OM2K_MO_EVT_START, - OM2K_MO_EVT_RX_CONN_COMPL, - OM2K_MO_EVT_RX_RESET_COMPL, - OM2K_MO_EVT_RX_START_REQ_ACCEPT, - OM2K_MO_EVT_RX_START_RES, - OM2K_MO_EVT_RX_CFG_REQ_ACCEPT, - OM2K_MO_EVT_RX_CFG_RES, - OM2K_MO_EVT_RX_ENA_REQ_ACCEPT, - OM2K_MO_EVT_RX_ENA_RES, - OM2K_MO_EVT_RX_OPINFO_ACC, -}; - -static const struct value_string om2k_event_names[] = { - { OM2K_MO_EVT_START, "START" }, - { OM2K_MO_EVT_RX_CONN_COMPL, "RX-CONN-COMPL" }, - { OM2K_MO_EVT_RX_RESET_COMPL, "RX-RESET-COMPL" }, - { OM2K_MO_EVT_RX_START_REQ_ACCEPT, "RX-RESET-REQ-ACCEPT" }, - { OM2K_MO_EVT_RX_START_RES, "RX-START-RESULT" }, - { OM2K_MO_EVT_RX_CFG_REQ_ACCEPT, "RX-CFG-REQ-ACCEPT" }, - { OM2K_MO_EVT_RX_CFG_RES, "RX-CFG-RESULT" }, - { OM2K_MO_EVT_RX_ENA_REQ_ACCEPT, "RX-ENABLE-REQ-ACCEPT" }, - { OM2K_MO_EVT_RX_ENA_RES, "RX-ENABLE-RESULT" }, - { OM2K_MO_EVT_RX_OPINFO_ACC, "RX-OPINFO-ACCEPT" }, - { 0, NULL } -}; - -enum om2k_mo_fsm_state { - OM2K_ST_INIT, - OM2K_ST_WAIT_CONN_COMPL, - OM2K_ST_WAIT_RES_COMPL, - OM2K_ST_WAIT_START_ACCEPT, - OM2K_ST_WAIT_START_RES, - OM2K_ST_WAIT_CFG_ACCEPT, - OM2K_ST_WAIT_CFG_RES, - OM2K_ST_WAIT_ENABLE_ACCEPT, - OM2K_ST_WAIT_ENABLE_RES, - OM2K_ST_WAIT_OPINFO_ACCEPT, - OM2K_ST_DONE, - OM2K_ST_ERROR, -}; - -struct om2k_mo_fsm_priv { - struct gsm_bts_trx *trx; - struct om2k_mo *mo; - uint8_t ts_nr; -}; - -static void om2k_mo_st_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_mo_fsm_priv *omfp = fi->priv; - - OSMO_ASSERT(event == OM2K_MO_EVT_START); - - switch (omfp->mo->addr.class) { - case OM2K_MO_CLS_CF: - /* no Connect required, is always connected */ - osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_START_ACCEPT, - OM2K_TIMEOUT, 0); - abis_om2k_tx_start_req(omfp->trx->bts, &omfp->mo->addr); - break; - case OM2K_MO_CLS_TRXC: - /* no Connect required, start with Reset */ - osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_RES_COMPL, - OM2K_TIMEOUT, 0); - abis_om2k_tx_reset_cmd(omfp->trx->bts, &omfp->mo->addr); - break; - default: - /* start with Connect */ - osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_CONN_COMPL, - OM2K_TIMEOUT, 0); - abis_om2k_tx_connect_cmd(omfp->trx->bts, &omfp->mo->addr); - break; - } -} - -static void om2k_mo_st_wait_conn_compl(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_mo_fsm_priv *omfp = fi->priv; - - switch (omfp->mo->addr.class) { -#if 0 - case OM2K_MO_CLS_TF: - /* skip the reset, hope that helps */ - osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_START_ACCEPT, - OM2K_TIMEOUT, 0); - abis_om2k_tx_start_req(omfp->trx->bts, &omfp->mo->addr); - break; -#endif - default: - osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_RES_COMPL, - OM2K_TIMEOUT, 0); - abis_om2k_tx_reset_cmd(omfp->trx->bts, &omfp->mo->addr); - break; - } -} - -static void om2k_mo_st_wait_res_compl(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_mo_fsm_priv *omfp = fi->priv; - - osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_START_ACCEPT, - OM2K_TIMEOUT, 0); - abis_om2k_tx_start_req(omfp->trx->bts, &omfp->mo->addr); -} - -static void om2k_mo_st_wait_start_accept(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_decoded_msg *omd = data; - - switch (omd->msg_type) { - case OM2K_MSGT_START_REQ_ACK: - osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_START_RES, - OM2K_TIMEOUT, 0); - break; - case OM2K_MSGT_START_REQ_REJ: - osmo_fsm_inst_state_chg(fi, OM2K_ST_ERROR, 0, 0); - break; - } -} - -static void om2k_mo_st_wait_start_res(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_mo_fsm_priv *omfp = fi->priv; - struct gsm_bts_trx_ts *ts; - - switch (omfp->mo->addr.class) { - case OM2K_MO_CLS_CF: - case OM2K_MO_CLS_TRXC: - /* Transition directly to Operational Info */ - osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_OPINFO_ACCEPT, - OM2K_TIMEOUT, 0); - abis_om2k_tx_op_info(omfp->trx->bts, &omfp->mo->addr, 1); - return; - case OM2K_MO_CLS_DP: - /* Transition directoy to WAIT_ENABLE_ACCEPT */ - osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_ENABLE_ACCEPT, - OM2K_TIMEOUT, 0); - abis_om2k_tx_enable_req(omfp->trx->bts, &omfp->mo->addr); - return; -#if 0 - case OM2K_MO_CLS_TF: - /* skip the config, hope that helps speeding things up */ - osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_ENABLE_ACCEPT, - OM2K_TIMEOUT, 0); - abis_om2k_tx_enable_req(omfp->trx->bts, &omfp->mo->addr); - return; -#endif - } - - osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_CFG_ACCEPT, - OM2K_TIMEOUT, 0); - switch (omfp->mo->addr.class) { - case OM2K_MO_CLS_TF: - abis_om2k_tx_tf_conf_req(omfp->trx->bts); - break; - case OM2K_MO_CLS_IS: - abis_om2k_tx_is_conf_req(omfp->trx->bts); - break; - case OM2K_MO_CLS_CON: - abis_om2k_tx_con_conf_req(omfp->trx->bts); - break; - case OM2K_MO_CLS_TX: - abis_om2k_tx_tx_conf_req(omfp->trx); - break; - case OM2K_MO_CLS_RX: - abis_om2k_tx_rx_conf_req(omfp->trx); - break; - case OM2K_MO_CLS_TS: - ts = mo2obj(omfp->trx->bts, &omfp->mo->addr); - abis_om2k_tx_ts_conf_req(ts); - break; - } -} - -static void om2k_mo_st_wait_cfg_accept(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_mo_fsm_priv *omfp = fi->priv; - uint32_t timeout = OM2K_TIMEOUT; - - if (omfp->mo->addr.class == OM2K_MO_CLS_TF) - timeout = 600; - - osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_CFG_RES, timeout, 0); -} - -static void om2k_mo_st_wait_cfg_res(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_mo_fsm_priv *omfp = fi->priv; - struct om2k_decoded_msg *omd = data; - uint8_t accordance; - - if (!TLVP_PRESENT(&omd->tp, OM2K_DEI_ACCORDANCE_IND)) { - osmo_fsm_inst_state_chg(fi, OM2K_ST_ERROR, 0, 0); - return; - } - accordance = *TLVP_VAL(&omd->tp, OM2K_DEI_ACCORDANCE_IND); - - if (accordance != 0) { - /* accordance not OK */ - osmo_fsm_inst_state_chg(fi, OM2K_ST_ERROR, 0, 0); - return; - } - - osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_ENABLE_ACCEPT, - OM2K_TIMEOUT, 0); - abis_om2k_tx_enable_req(omfp->trx->bts, &omfp->mo->addr); -} - -static void om2k_mo_st_wait_enable_accept(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_mo_fsm_priv *omfp = fi->priv; - struct om2k_decoded_msg *omd = data; - - switch (omd->msg_type) { - case OM2K_MSGT_ENABLE_REQ_REJ: - osmo_fsm_inst_state_chg(fi, OM2K_ST_ERROR, 0, 0); - break; - case OM2K_MSGT_ENABLE_REQ_ACK: - if (omfp->mo->addr.class == OM2K_MO_CLS_IS && - omfp->trx->bts->rbs2000.use_superchannel) - e1inp_ericsson_set_altc(omfp->trx->bts->oml_link->ts->line, 1); - osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_ENABLE_RES, - OM2K_TIMEOUT, 0); - } -} - -static void om2k_mo_st_wait_enable_res(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_mo_fsm_priv *omfp = fi->priv; - //struct om2k_decoded_msg *omd = data; - /* TODO: check if state is actually enabled now? */ - - osmo_fsm_inst_state_chg(fi, OM2K_ST_WAIT_OPINFO_ACCEPT, - OM2K_TIMEOUT, 0); - abis_om2k_tx_op_info(omfp->trx->bts, &omfp->mo->addr, 1); -} - -static void om2k_mo_st_wait_opinfo_accept(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_mo_fsm_priv *omfp = fi->priv; - - /* if we have just received opinfo accept for the timeslot, - * start dynamic TCH switching procedures */ - if (omfp->mo->addr.class == OM2K_MO_CLS_TS) { - struct gsm_bts_trx_ts *ts; - ts = mo2obj(omfp->trx->bts, &omfp->mo->addr); - dyn_ts_init(ts); - } - osmo_fsm_inst_state_chg(fi, OM2K_ST_DONE, 0, 0); -} - -static void om2k_mo_s_done_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) -{ - struct om2k_mo_fsm_priv *omfp = fi->priv; - omfp->mo->fsm = NULL; - osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL); -} - -static void om2k_mo_s_error_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) -{ - struct om2k_mo_fsm_priv *omfp = fi->priv; - - omfp->mo->fsm = NULL; - osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL); -} - -static const struct osmo_fsm_state om2k_is_states[] = { - [OM2K_ST_INIT] = { - .name = "INIT", - .in_event_mask = S(OM2K_MO_EVT_START), - .out_state_mask = S(OM2K_ST_DONE) | - S(OM2K_ST_ERROR) | - S(OM2K_ST_WAIT_CONN_COMPL) | - S(OM2K_ST_WAIT_START_ACCEPT) | - S(OM2K_ST_WAIT_RES_COMPL), - .action = om2k_mo_st_init, - }, - [OM2K_ST_WAIT_CONN_COMPL] = { - .name = "WAIT-CONN-COMPL", - .in_event_mask = S(OM2K_MO_EVT_RX_CONN_COMPL), - .out_state_mask = S(OM2K_ST_DONE) | - S(OM2K_ST_ERROR) | - S(OM2K_ST_WAIT_START_ACCEPT) | - S(OM2K_ST_WAIT_RES_COMPL), - .action = om2k_mo_st_wait_conn_compl, - }, - [OM2K_ST_WAIT_RES_COMPL] = { - .name = "WAIT-RES-COMPL", - .in_event_mask = S(OM2K_MO_EVT_RX_RESET_COMPL), - .out_state_mask = S(OM2K_ST_DONE) | - S(OM2K_ST_ERROR) | - S(OM2K_ST_WAIT_START_ACCEPT), - .action = om2k_mo_st_wait_res_compl, - }, - [OM2K_ST_WAIT_START_ACCEPT] = { - .name = "WAIT-START-ACCEPT", - .in_event_mask = S(OM2K_MO_EVT_RX_START_REQ_ACCEPT), - .out_state_mask = S(OM2K_ST_DONE) | - S(OM2K_ST_ERROR) | - S(OM2K_ST_WAIT_START_RES), - .action =om2k_mo_st_wait_start_accept, - }, - [OM2K_ST_WAIT_START_RES] = { - .name = "WAIT-START-RES", - .in_event_mask = S(OM2K_MO_EVT_RX_START_RES), - .out_state_mask = S(OM2K_ST_DONE) | - S(OM2K_ST_ERROR) | - S(OM2K_ST_WAIT_CFG_ACCEPT) | - S(OM2K_ST_WAIT_OPINFO_ACCEPT), - .action = om2k_mo_st_wait_start_res, - }, - [OM2K_ST_WAIT_CFG_ACCEPT] = { - .name = "WAIT-CFG-ACCEPT", - .in_event_mask = S(OM2K_MO_EVT_RX_CFG_REQ_ACCEPT), - .out_state_mask = S(OM2K_ST_DONE) | - S(OM2K_ST_ERROR) | - S(OM2K_ST_WAIT_CFG_RES), - .action = om2k_mo_st_wait_cfg_accept, - }, - [OM2K_ST_WAIT_CFG_RES] = { - .name = "WAIT-CFG-RES", - .in_event_mask = S(OM2K_MO_EVT_RX_CFG_RES), - .out_state_mask = S(OM2K_ST_DONE) | - S(OM2K_ST_ERROR) | - S(OM2K_ST_WAIT_ENABLE_ACCEPT), - .action = om2k_mo_st_wait_cfg_res, - }, - [OM2K_ST_WAIT_ENABLE_ACCEPT] = { - .name = "WAIT-ENABLE-ACCEPT", - .in_event_mask = S(OM2K_MO_EVT_RX_ENA_REQ_ACCEPT), - .out_state_mask = S(OM2K_ST_DONE) | - S(OM2K_ST_ERROR) | - S(OM2K_ST_WAIT_ENABLE_RES), - .action = om2k_mo_st_wait_enable_accept, - }, - [OM2K_ST_WAIT_ENABLE_RES] = { - .name = "WAIT-ENABLE-RES", - .in_event_mask = S(OM2K_MO_EVT_RX_ENA_RES), - .out_state_mask = S(OM2K_ST_DONE) | - S(OM2K_ST_ERROR) | - S(OM2K_ST_WAIT_OPINFO_ACCEPT), - .action = om2k_mo_st_wait_enable_res, - }, - [OM2K_ST_WAIT_OPINFO_ACCEPT] = { - .name = "WAIT-OPINFO-ACCEPT", - .in_event_mask = S(OM2K_MO_EVT_RX_OPINFO_ACC), - .out_state_mask = S(OM2K_ST_DONE) | - S(OM2K_ST_ERROR), - .action = om2k_mo_st_wait_opinfo_accept, - }, - [OM2K_ST_DONE] = { - .name = "DONE", - .in_event_mask = 0, - .out_state_mask = 0, - .onenter = om2k_mo_s_done_onenter, - }, - [OM2K_ST_ERROR] = { - .name = "ERROR", - .in_event_mask = 0, - .out_state_mask = 0, - .onenter = om2k_mo_s_error_onenter, - }, - -}; - -static int om2k_mo_timer_cb(struct osmo_fsm_inst *fi) -{ - osmo_fsm_inst_state_chg(fi, OM2K_ST_ERROR, 0, 0); - return 0; -} - -static struct osmo_fsm om2k_mo_fsm = { - .name = "OM2000-MO", - .states = om2k_is_states, - .num_states = ARRAY_SIZE(om2k_is_states), - .log_subsys = DNM, - .event_names = om2k_event_names, - .timer_cb = om2k_mo_timer_cb, -}; - -struct osmo_fsm_inst *om2k_mo_fsm_start(struct osmo_fsm_inst *parent, - uint32_t term_event, - struct gsm_bts_trx *trx, struct om2k_mo *mo) -{ - struct osmo_fsm_inst *fi; - struct om2k_mo_fsm_priv *omfp; - char idbuf[64]; - - snprintf(idbuf, sizeof(idbuf), "%s-%s", parent->id, - om2k_mo_name(&mo->addr)); - - fi = osmo_fsm_inst_alloc_child_id(&om2k_mo_fsm, parent, - term_event, idbuf); - if (!fi) - return NULL; - - mo->fsm = fi; - omfp = talloc_zero(fi, struct om2k_mo_fsm_priv); - omfp->mo = mo; - omfp->trx = trx; - fi->priv = omfp; - - osmo_fsm_inst_dispatch(fi, OM2K_MO_EVT_START, NULL); - - return fi; -} - -int om2k_mo_fsm_recvmsg(struct gsm_bts *bts, struct om2k_mo *mo, - struct om2k_decoded_msg *odm) -{ - switch (odm->msg_type) { - case OM2K_MSGT_CONNECT_COMPL: - case OM2K_MSGT_CONNECT_REJ: - osmo_fsm_inst_dispatch(mo->fsm, - OM2K_MO_EVT_RX_CONN_COMPL, odm); - break; - - case OM2K_MSGT_RESET_COMPL: - case OM2K_MSGT_RESET_REJ: - osmo_fsm_inst_dispatch(mo->fsm, - OM2K_MO_EVT_RX_RESET_COMPL, odm); - break; - - case OM2K_MSGT_START_REQ_ACK: - case OM2K_MSGT_START_REQ_REJ: - osmo_fsm_inst_dispatch(mo->fsm, - OM2K_MO_EVT_RX_START_REQ_ACCEPT, odm); - break; - - case OM2K_MSGT_START_RES: - osmo_fsm_inst_dispatch(mo->fsm, - OM2K_MO_EVT_RX_START_RES, odm); - break; - - case OM2K_MSGT_CON_CONF_REQ_ACK: - case OM2K_MSGT_IS_CONF_REQ_ACK: - case OM2K_MSGT_RX_CONF_REQ_ACK: - case OM2K_MSGT_TF_CONF_REQ_ACK: - case OM2K_MSGT_TS_CONF_REQ_ACK: - case OM2K_MSGT_TX_CONF_REQ_ACK: - osmo_fsm_inst_dispatch(mo->fsm, - OM2K_MO_EVT_RX_CFG_REQ_ACCEPT, odm); - break; - - case OM2K_MSGT_CON_CONF_RES: - case OM2K_MSGT_IS_CONF_RES: - case OM2K_MSGT_RX_CONF_RES: - case OM2K_MSGT_TF_CONF_RES: - case OM2K_MSGT_TS_CONF_RES: - case OM2K_MSGT_TX_CONF_RES: - osmo_fsm_inst_dispatch(mo->fsm, - OM2K_MO_EVT_RX_CFG_RES, odm); - break; - - case OM2K_MSGT_ENABLE_REQ_ACK: - case OM2K_MSGT_ENABLE_REQ_REJ: - osmo_fsm_inst_dispatch(mo->fsm, - OM2K_MO_EVT_RX_ENA_REQ_ACCEPT, odm); - break; - case OM2K_MSGT_ENABLE_RES: - osmo_fsm_inst_dispatch(mo->fsm, - OM2K_MO_EVT_RX_ENA_RES, odm); - break; - - case OM2K_MSGT_OP_INFO_ACK: - case OM2K_MSGT_OP_INFO_REJ: - osmo_fsm_inst_dispatch(mo->fsm, - OM2K_MO_EVT_RX_OPINFO_ACC, odm); - break; - default: - return -1; - } - - return 0; -} - -/*********************************************************************** - * OM2000 TRX Finite State Machine, initializes TRXC and all siblings - ***********************************************************************/ - -enum om2k_trx_event { - OM2K_TRX_EVT_START, - OM2K_TRX_EVT_TRXC_DONE, - OM2K_TRX_EVT_TX_DONE, - OM2K_TRX_EVT_RX_DONE, - OM2K_TRX_EVT_TS_DONE, - OM2K_TRX_EVT_STOP, -}; - -static struct value_string om2k_trx_events[] = { - { OM2K_TRX_EVT_START, "START" }, - { OM2K_TRX_EVT_TRXC_DONE, "TRXC-DONE" }, - { OM2K_TRX_EVT_TX_DONE, "TX-DONE" }, - { OM2K_TRX_EVT_RX_DONE, "RX-DONE" }, - { OM2K_TRX_EVT_TS_DONE, "TS-DONE" }, - { OM2K_TRX_EVT_STOP, "STOP" }, - { 0, NULL } -}; - -enum om2k_trx_state { - OM2K_TRX_S_INIT, - OM2K_TRX_S_WAIT_TRXC, - OM2K_TRX_S_WAIT_TX, - OM2K_TRX_S_WAIT_RX, - OM2K_TRX_S_WAIT_TS, - OM2K_TRX_S_DONE, - OM2K_TRX_S_ERROR -}; - -struct om2k_trx_fsm_priv { - struct gsm_bts_trx *trx; - uint8_t next_ts_nr; -}; - -static void om2k_trx_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_trx_fsm_priv *otfp = fi->priv; - - /* First initialize TRXC */ - osmo_fsm_inst_state_chg(fi, OM2K_TRX_S_WAIT_TRXC, - TRX_FSM_TIMEOUT, 0); - om2k_mo_fsm_start(fi, OM2K_TRX_EVT_TRXC_DONE, otfp->trx, - &otfp->trx->rbs2000.trxc.om2k_mo); -} - -static void om2k_trx_s_wait_trxc(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_trx_fsm_priv *otfp = fi->priv; - - /* Initialize TX after TRXC */ - osmo_fsm_inst_state_chg(fi, OM2K_TRX_S_WAIT_TX, - TRX_FSM_TIMEOUT, 0); - om2k_mo_fsm_start(fi, OM2K_TRX_EVT_TX_DONE, otfp->trx, - &otfp->trx->rbs2000.tx.om2k_mo); -} - -static void om2k_trx_s_wait_tx(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_trx_fsm_priv *otfp = fi->priv; - - /* Initialize RX after TX */ - osmo_fsm_inst_state_chg(fi, OM2K_TRX_S_WAIT_RX, - TRX_FSM_TIMEOUT, 0); - om2k_mo_fsm_start(fi, OM2K_TRX_EVT_RX_DONE, otfp->trx, - &otfp->trx->rbs2000.rx.om2k_mo); -} - -static void om2k_trx_s_wait_rx(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_trx_fsm_priv *otfp = fi->priv; - struct gsm_bts_trx_ts *ts; - - /* Initialize Timeslots after TX */ - osmo_fsm_inst_state_chg(fi, OM2K_TRX_S_WAIT_TS, - TRX_FSM_TIMEOUT, 0); - otfp->next_ts_nr = 0; - ts = &otfp->trx->ts[otfp->next_ts_nr++]; - om2k_mo_fsm_start(fi, OM2K_TRX_EVT_TS_DONE, otfp->trx, - &ts->rbs2000.om2k_mo); -} - -static void om2k_trx_s_wait_ts(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_trx_fsm_priv *otfp = fi->priv; - struct gsm_bts_trx_ts *ts; - - if (otfp->next_ts_nr < 8) { - /* iterate to the next timeslot */ - ts = &otfp->trx->ts[otfp->next_ts_nr++]; - om2k_mo_fsm_start(fi, OM2K_TRX_EVT_TS_DONE, otfp->trx, - &ts->rbs2000.om2k_mo); - } else { - /* only after all 8 TS */ - osmo_fsm_inst_state_chg(fi, OM2K_TRX_S_DONE, 0, 0); - } -} - -static void om2k_trx_s_done_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) -{ - struct om2k_trx_fsm_priv *otfp = fi->priv; - gsm_bts_trx_set_system_infos(otfp->trx); - osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL); -} - -static const struct osmo_fsm_state om2k_trx_states[] = { - [OM2K_TRX_S_INIT] = { - .in_event_mask = S(OM2K_TRX_EVT_START), - .out_state_mask = S(OM2K_TRX_S_WAIT_TRXC), - .name = "INIT", - .action = om2k_trx_s_init, - }, - [OM2K_TRX_S_WAIT_TRXC] = { - .in_event_mask = S(OM2K_TRX_EVT_TRXC_DONE), - .out_state_mask = S(OM2K_TRX_S_ERROR) | - S(OM2K_TRX_S_WAIT_TX), - .name = "WAIT-TRXC", - .action = om2k_trx_s_wait_trxc, - }, - [OM2K_TRX_S_WAIT_TX] = { - .in_event_mask = S(OM2K_TRX_EVT_TX_DONE), - .out_state_mask = S(OM2K_TRX_S_ERROR) | - S(OM2K_TRX_S_WAIT_RX), - .name = "WAIT-TX", - .action = om2k_trx_s_wait_tx, - }, - [OM2K_TRX_S_WAIT_RX] = { - .in_event_mask = S(OM2K_TRX_EVT_RX_DONE), - .out_state_mask = S(OM2K_TRX_S_ERROR) | - S(OM2K_TRX_S_WAIT_TS), - .name = "WAIT-RX", - .action = om2k_trx_s_wait_rx, - }, - [OM2K_TRX_S_WAIT_TS] = { - .in_event_mask = S(OM2K_TRX_EVT_TS_DONE), - .out_state_mask = S(OM2K_TRX_S_ERROR) | - S(OM2K_TRX_S_DONE), - .name = "WAIT-TS", - .action = om2k_trx_s_wait_ts, - }, - [OM2K_TRX_S_DONE] = { - .name = "DONE", - .onenter = om2k_trx_s_done_onenter, - }, - [OM2K_TRX_S_ERROR] = { - .name = "ERROR", - }, -}; - -static int om2k_trx_timer_cb(struct osmo_fsm_inst *fi) -{ - osmo_fsm_inst_state_chg(fi, OM2K_TRX_S_ERROR, 0, 0); - return 0; -} - -static struct osmo_fsm om2k_trx_fsm = { - .name = "OM2000-TRX", - .states = om2k_trx_states, - .num_states = ARRAY_SIZE(om2k_trx_states), - .log_subsys = DNM, - .event_names = om2k_trx_events, - .timer_cb = om2k_trx_timer_cb, -}; - -struct osmo_fsm_inst *om2k_trx_fsm_start(struct osmo_fsm_inst *parent, - struct gsm_bts_trx *trx, - uint32_t term_event) -{ - struct osmo_fsm_inst *fi; - struct om2k_trx_fsm_priv *otfp; - char idbuf[32]; - - snprintf(idbuf, sizeof(idbuf), "%u/%u", trx->bts->nr, trx->nr); - - fi = osmo_fsm_inst_alloc_child_id(&om2k_trx_fsm, parent, term_event, - idbuf); - if (!fi) - return NULL; - - otfp = talloc_zero(fi, struct om2k_trx_fsm_priv); - otfp->trx = trx; - fi->priv = otfp; - - osmo_fsm_inst_dispatch(fi, OM2K_TRX_EVT_START, NULL); - - return fi; -} - - -/*********************************************************************** - * OM2000 BTS Finite State Machine, initializes CF and all siblings - ***********************************************************************/ - -enum om2k_bts_event { - OM2K_BTS_EVT_START, - OM2K_BTS_EVT_CF_DONE, - OM2K_BTS_EVT_IS_DONE, - OM2K_BTS_EVT_CON_DONE, - OM2K_BTS_EVT_TF_DONE, - OM2K_BTS_EVT_TRX_DONE, - OM2K_BTS_EVT_STOP, -}; - -static const struct value_string om2k_bts_events[] = { - { OM2K_BTS_EVT_START, "START" }, - { OM2K_BTS_EVT_CF_DONE, "CF-DONE" }, - { OM2K_BTS_EVT_IS_DONE, "IS-DONE" }, - { OM2K_BTS_EVT_CON_DONE, "CON-DONE" }, - { OM2K_BTS_EVT_TF_DONE, "TF-DONE" }, - { OM2K_BTS_EVT_TRX_DONE, "TRX-DONE" }, - { OM2K_BTS_EVT_STOP, "STOP" }, - { 0, NULL } -}; - -enum om2k_bts_state { - OM2K_BTS_S_INIT, - OM2K_BTS_S_WAIT_CF, - OM2K_BTS_S_WAIT_IS, - OM2K_BTS_S_WAIT_CON, - OM2K_BTS_S_WAIT_TF, - OM2K_BTS_S_WAIT_TRX, - OM2K_BTS_S_DONE, - OM2K_BTS_S_ERROR, -}; - -struct om2k_bts_fsm_priv { - struct gsm_bts *bts; - uint8_t next_trx_nr; -}; - -static void om2k_bts_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_bts_fsm_priv *obfp = fi->priv; - struct gsm_bts *bts = obfp->bts; - - OSMO_ASSERT(event == OM2K_BTS_EVT_START); - osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_CF, - BTS_FSM_TIMEOUT, 0); - om2k_mo_fsm_start(fi, OM2K_BTS_EVT_CF_DONE, bts->c0, - &bts->rbs2000.cf.om2k_mo); -} - -static void om2k_bts_s_wait_cf(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_bts_fsm_priv *obfp = fi->priv; - struct gsm_bts *bts = obfp->bts; - - OSMO_ASSERT(event == OM2K_BTS_EVT_CF_DONE); - /* TF can take a long time to initialize, wait for 10min */ - osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_TF, 600, 0); - om2k_mo_fsm_start(fi, OM2K_BTS_EVT_TF_DONE, bts->c0, - &bts->rbs2000.tf.om2k_mo); -} - -static void om2k_bts_s_wait_tf(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_bts_fsm_priv *obfp = fi->priv; - struct gsm_bts *bts = obfp->bts; - - OSMO_ASSERT(event == OM2K_BTS_EVT_TF_DONE); - - osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_CON, - BTS_FSM_TIMEOUT, 0); - om2k_mo_fsm_start(fi, OM2K_BTS_EVT_CON_DONE, bts->c0, - &bts->rbs2000.con.om2k_mo); -} - -static void om2k_bts_s_wait_con(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_bts_fsm_priv *obfp = fi->priv; - struct gsm_bts *bts = obfp->bts; - - OSMO_ASSERT(event == OM2K_BTS_EVT_CON_DONE); - - osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_IS, - BTS_FSM_TIMEOUT, 0); - om2k_mo_fsm_start(fi, OM2K_BTS_EVT_IS_DONE, bts->c0, - &bts->rbs2000.is.om2k_mo); -} - -static void om2k_bts_s_wait_is(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_bts_fsm_priv *obfp = fi->priv; - struct gsm_bts_trx *trx; - - OSMO_ASSERT(event == OM2K_BTS_EVT_IS_DONE); - - osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_TRX, - BTS_FSM_TIMEOUT, 0); - obfp->next_trx_nr = 0; - trx = gsm_bts_trx_num(obfp->bts, obfp->next_trx_nr++); - om2k_trx_fsm_start(fi, trx, OM2K_BTS_EVT_TRX_DONE); -} - -static void om2k_bts_s_wait_trx(struct osmo_fsm_inst *fi, uint32_t event, void *data) -{ - struct om2k_bts_fsm_priv *obfp = fi->priv; - - OSMO_ASSERT(event == OM2K_BTS_EVT_TRX_DONE); - - if (obfp->next_trx_nr < obfp->bts->num_trx) { - struct gsm_bts_trx *trx; - trx = gsm_bts_trx_num(obfp->bts, obfp->next_trx_nr++); - om2k_trx_fsm_start(fi, trx, OM2K_BTS_EVT_TRX_DONE); - } else { - osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_DONE, 0, 0); - } -} - -static void om2k_bts_s_done_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) -{ - osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL); -} - -static const struct osmo_fsm_state om2k_bts_states[] = { - [OM2K_BTS_S_INIT] = { - .in_event_mask = S(OM2K_BTS_EVT_START), - .out_state_mask = S(OM2K_BTS_S_WAIT_CF), - .name = "INIT", - .action = om2k_bts_s_init, - }, - [OM2K_BTS_S_WAIT_CF] = { - .in_event_mask = S(OM2K_BTS_EVT_CF_DONE), - .out_state_mask = S(OM2K_BTS_S_ERROR) | - S(OM2K_BTS_S_WAIT_TF), - .name = "WAIT-CF", - .action = om2k_bts_s_wait_cf, - }, - [OM2K_BTS_S_WAIT_TF] = { - .in_event_mask = S(OM2K_BTS_EVT_TF_DONE), - .out_state_mask = S(OM2K_BTS_S_ERROR) | - S(OM2K_BTS_S_WAIT_CON), - .name = "WAIT-TF", - .action = om2k_bts_s_wait_tf, - }, - [OM2K_BTS_S_WAIT_CON] = { - .in_event_mask = S(OM2K_BTS_EVT_CON_DONE), - .out_state_mask = S(OM2K_BTS_S_ERROR) | - S(OM2K_BTS_S_WAIT_IS), - .name = "WAIT-CON", - .action = om2k_bts_s_wait_con, - }, - [OM2K_BTS_S_WAIT_IS] = { - .in_event_mask = S(OM2K_BTS_EVT_IS_DONE), - .out_state_mask = S(OM2K_BTS_S_ERROR) | - S(OM2K_BTS_S_WAIT_TRX), - .name = "WAIT-IS", - .action = om2k_bts_s_wait_is, - }, - [OM2K_BTS_S_WAIT_TRX] = { - .in_event_mask = S(OM2K_BTS_EVT_TRX_DONE), - .out_state_mask = S(OM2K_BTS_S_ERROR) | - S(OM2K_BTS_S_DONE), - .name = "WAIT-TRX", - .action = om2k_bts_s_wait_trx, - }, - [OM2K_BTS_S_DONE] = { - .name = "DONE", - .onenter = om2k_bts_s_done_onenter, - }, - [OM2K_BTS_S_ERROR] = { - .name = "ERROR", - }, -}; - -static int om2k_bts_timer_cb(struct osmo_fsm_inst *fi) -{ - osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_ERROR, 0, 0); - return 0; -} - -static struct osmo_fsm om2k_bts_fsm = { - .name = "OM2000-BTS", - .states = om2k_bts_states, - .num_states = ARRAY_SIZE(om2k_bts_states), - .log_subsys = DNM, - .event_names = om2k_bts_events, - .timer_cb = om2k_bts_timer_cb, -}; - -struct osmo_fsm_inst * -om2k_bts_fsm_start(struct gsm_bts *bts) -{ - struct osmo_fsm_inst *fi; - struct om2k_bts_fsm_priv *obfp; - char idbuf[16]; - - snprintf(idbuf, sizeof(idbuf), "%u", bts->nr); - - fi = osmo_fsm_inst_alloc(&om2k_bts_fsm, bts, NULL, - LOGL_DEBUG, idbuf); - if (!fi) - return NULL; - fi->priv = obfp = talloc_zero(fi, struct om2k_bts_fsm_priv); - obfp->bts = bts; - - osmo_fsm_inst_dispatch(fi, OM2K_BTS_EVT_START, NULL); - - return fi; -} - - -/*********************************************************************** - * OM2000 Negotiation - ***********************************************************************/ - -static int abis_om2k_tx_negot_req_ack(struct gsm_bts *bts, const struct abis_om2k_mo *mo, - uint8_t *data, unsigned int len) -{ - struct msgb *msg = om2k_msgb_alloc(); - struct abis_om2k_hdr *o2k; - - o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k)); - fill_om2k_hdr(o2k, mo, OM2K_MSGT_NEGOT_REQ_ACK); - - msgb_tlv_put(msg, OM2K_DEI_NEGOT_REC2, len, data); - - DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(mo), - get_value_string(om2k_msgcode_vals, OM2K_MSGT_NEGOT_REQ_ACK)); - - return abis_om2k_sendmsg(bts, msg); -} - -struct iwd_version { - uint8_t gen_char[3+1]; - uint8_t rev_char[3+1]; -}; - -struct iwd_type { - uint8_t num_vers; - struct iwd_version v[8]; -}; - -static int om2k_rx_negot_req(struct msgb *msg) -{ - struct e1inp_sign_link *sign_link = (struct e1inp_sign_link *)msg->dst; - struct abis_om2k_hdr *o2h = msgb_l2(msg); - struct iwd_type iwd_types[16]; - uint8_t num_iwd_types = o2h->data[2]; - uint8_t *cur = o2h->data+3; - unsigned int i, v; - - uint8_t out_buf[1024]; - uint8_t *out_cur = out_buf+1; - uint8_t out_num_types = 0; - - memset(iwd_types, 0, sizeof(iwd_types)); - - /* Parse the RBS-supported IWD versions into iwd_types array */ - for (i = 0; i < num_iwd_types; i++) { - uint8_t num_versions = *cur++; - uint8_t iwd_type = *cur++; - - iwd_types[iwd_type].num_vers = num_versions; - - for (v = 0; v < num_versions; v++) { - struct iwd_version *iwd_v = &iwd_types[iwd_type].v[v]; - - memcpy(iwd_v->gen_char, cur, 3); - cur += 3; - memcpy(iwd_v->rev_char, cur, 3); - cur += 3; - - DEBUGP(DNM, "\tIWD Type %u Gen %s Rev %s\n", iwd_type, - iwd_v->gen_char, iwd_v->rev_char); - } - } - - /* Select the last version for each IWD type */ - for (i = 0; i < ARRAY_SIZE(iwd_types); i++) { - struct iwd_type *type = &iwd_types[i]; - struct iwd_version *last_v; - - if (type->num_vers == 0) - continue; - - out_num_types++; - - last_v = &type->v[type->num_vers-1]; - - *out_cur++ = i; - memcpy(out_cur, last_v->gen_char, 3); - out_cur += 3; - memcpy(out_cur, last_v->rev_char, 3); - out_cur += 3; - } - - out_buf[0] = out_num_types; - - return abis_om2k_tx_negot_req_ack(sign_link->trx->bts, &o2h->mo, out_buf, out_cur - out_buf); -} - - -/*********************************************************************** - * OM2000 Receive Message Handler - ***********************************************************************/ - -static int om2k_rx_nack(struct msgb *msg) -{ - struct abis_om2k_hdr *o2h = msgb_l2(msg); - uint16_t msg_type = ntohs(o2h->msg_type); - struct tlv_parsed tp; - - LOGP(DNM, LOGL_ERROR, "Rx MO=%s %s", om2k_mo_name(&o2h->mo), - get_value_string(om2k_msgcode_vals, msg_type)); - - abis_om2k_msg_tlv_parse(&tp, o2h); - if (TLVP_PRESENT(&tp, OM2K_DEI_REASON_CODE)) - LOGPC(DNM, LOGL_ERROR, ", Reason 0x%02x", - *TLVP_VAL(&tp, OM2K_DEI_REASON_CODE)); - - if (TLVP_PRESENT(&tp, OM2K_DEI_RESULT_CODE)) - LOGPC(DNM, LOGL_ERROR, ", Result %s", - get_value_string(om2k_result_strings, - *TLVP_VAL(&tp, OM2K_DEI_RESULT_CODE))); - LOGPC(DNM, LOGL_ERROR, "\n"); - - return 0; -} - -static int process_mo_state(struct gsm_bts *bts, struct om2k_decoded_msg *odm) -{ - uint8_t mo_state; - - if (!TLVP_PRESENT(&odm->tp, OM2K_DEI_MO_STATE)) - return -EIO; - mo_state = *TLVP_VAL(&odm->tp, OM2K_DEI_MO_STATE); - - LOGP(DNM, LOGL_DEBUG, "Rx MO=%s %s, MO State: %s\n", - om2k_mo_name(&odm->o2h.mo), - get_value_string(om2k_msgcode_vals, odm->msg_type), - get_value_string(om2k_mostate_vals, mo_state)); - - /* Throw error message in case we see an enable rsponse that does - * not yield an enabled mo-state */ - if (odm->msg_type == OM2K_MSGT_ENABLE_RES - && mo_state != OM2K_MO_S_ENABLED) { - LOGP(DNM, LOGL_ERROR, - "Rx MO=%s %s Failed to enable MO State!\n", - om2k_mo_name(&odm->o2h.mo), - get_value_string(om2k_msgcode_vals, odm->msg_type)); - } - - update_mo_state(bts, &odm->o2h.mo, mo_state); - - return 0; -} - -/* Display fault report bits (helper function of display_fault_maps()) */ -static bool display_fault_bits(const uint8_t *vect, uint16_t len, - uint8_t dei, const struct abis_om2k_mo *mo) -{ - uint16_t i; - int k; - bool faults_present = false; - int first = 1; - char string[255]; - - /* Check if errors are present at all */ - for (i = 0; i < len; i++) - if (vect[i]) - faults_present = true; - if (!faults_present) - return false; - - sprintf(string, "Fault Report: %s (", - get_value_string(om2k_attr_vals, dei)); - - for (i = 0; i < len; i++) { - for (k = 0; k < 8; k++) { - if ((vect[i] >> k) & 1) { - if (!first) - sprintf(string + strlen(string), ","); - sprintf(string + strlen(string), "%d", k + i*8); - first = 0; - } - } - } - - sprintf(string + strlen(string), ")\n"); - DEBUGP(DNM, "Rx MO=%s %s", om2k_mo_name(mo), string); - - return true; -} - -/* Display fault report maps */ -static void display_fault_maps(const uint8_t *src, unsigned int src_len, - const struct abis_om2k_mo *mo) -{ - uint8_t tag; - uint16_t tag_len; - const uint8_t *val; - int src_pos = 0; - int rc; - int tlv_count = 0; - uint16_t msg_code; - bool faults_present = false; - - /* Chop off header */ - src+=4; - src_len-=4; - - /* Check message type */ - msg_code = (*src & 0xff) << 8; - src++; - src_len--; - msg_code |= (*src & 0xff); - src++; - src_len--; - if (msg_code != OM2K_MSGT_FAULT_REP) { - LOGP(DNM, LOGL_ERROR, "Rx MO=%s Fault report: invalid message code!\n", - om2k_mo_name(mo)); - return; - } - - /* Chop off mo-interface */ - src += 4; - src_len -= 4; - - /* Iterate over each TLV element */ - while (1) { - - /* Bail if an the maximum number of TLV fields - * have been parsed */ - if (tlv_count >= 11) { - LOGP(DNM, LOGL_ERROR, - "Rx MO=%s Fault Report: too many tlv elements!\n", - om2k_mo_name(mo)); - return; - } - - /* Parse TLV field */ - rc = tlv_parse_one(&tag, &tag_len, &val, &om2k_att_tlvdef, - src + src_pos, src_len - src_pos); - if (rc > 0) - src_pos += rc; - else { - LOGP(DNM, LOGL_ERROR, - "Rx MO=%s Fault Report: invalid tlv element!\n", - om2k_mo_name(mo)); - return; - } - - switch (tag) { - case OM2K_DEI_INT_FAULT_MAP_1A: - case OM2K_DEI_INT_FAULT_MAP_1B: - case OM2K_DEI_INT_FAULT_MAP_2A: - case OM2K_DEI_EXT_COND_MAP_1: - case OM2K_DEI_EXT_COND_MAP_2: - case OM2K_DEI_REPL_UNIT_MAP: - case OM2K_DEI_INT_FAULT_MAP_2A_EXT: - case OM2K_DEI_EXT_COND_MAP_2_EXT: - case OM2K_DEI_REPL_UNIT_MAP_EXT: - faults_present |= display_fault_bits(val, tag_len, - tag, mo); - break; - } - - /* Stop when no further TLV elements can be expected */ - if (src_len - src_pos < 2) - break; - - tlv_count++; - } - - if (!faults_present) { - DEBUGP(DNM, "Rx MO=%s Fault Report: All faults ceased!\n", - om2k_mo_name(mo)); - } -} - -int abis_om2k_rcvmsg(struct msgb *msg) -{ - struct e1inp_sign_link *sign_link = (struct e1inp_sign_link *)msg->dst; - struct gsm_bts *bts = sign_link->trx->bts; - struct abis_om2k_hdr *o2h = msgb_l2(msg); - struct abis_om_hdr *oh = &o2h->om; - uint16_t msg_type = ntohs(o2h->msg_type); - struct om2k_decoded_msg odm; - struct om2k_mo *mo; - int rc = 0; - - /* Various consistency checks */ - if (oh->placement != ABIS_OM_PLACEMENT_ONLY) { - LOGP(DNM, LOGL_ERROR, "ABIS OML placement 0x%x not supported\n", - oh->placement); - if (oh->placement != ABIS_OM_PLACEMENT_FIRST) - return -EINVAL; - } - if (oh->sequence != 0) { - LOGP(DNM, LOGL_ERROR, "ABIS OML sequence 0x%x != 0x00\n", - oh->sequence); - return -EINVAL; - } - - msg->l3h = (unsigned char *)o2h + sizeof(*o2h); - - if (oh->mdisc != ABIS_OM_MDISC_FOM) { - LOGP(DNM, LOGL_ERROR, "unknown ABIS OM2000 message discriminator 0x%x\n", - oh->mdisc); - return -EINVAL; - } - - DEBUGP(DNM, "Rx MO=%s %s (%s)\n", om2k_mo_name(&o2h->mo), - get_value_string(om2k_msgcode_vals, msg_type), - osmo_hexdump(msg->l2h, msgb_l2len(msg))); - - om2k_decode_msg(&odm, msg); - - process_mo_state(bts, &odm); - - switch (msg_type) { - case OM2K_MSGT_CAL_TIME_REQ: - rc = abis_om2k_cal_time_resp(bts); - break; - case OM2K_MSGT_FAULT_REP: - display_fault_maps(msg->l2h, msgb_l2len(msg), &o2h->mo); - rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_FAULT_REP_ACK); - break; - case OM2K_MSGT_NEGOT_REQ: - rc = om2k_rx_negot_req(msg); - break; - case OM2K_MSGT_START_RES: - /* common processing here */ - rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_START_RES_ACK); - /* below we dispatch into MO */ - break; - case OM2K_MSGT_IS_CONF_RES: - rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_IS_CONF_RES_ACK); - break; - case OM2K_MSGT_CON_CONF_RES: - rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_CON_CONF_RES_ACK); - break; - case OM2K_MSGT_TX_CONF_RES: - rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TX_CONF_RES_ACK); - break; - case OM2K_MSGT_RX_CONF_RES: - rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_RX_CONF_RES_ACK); - break; - case OM2K_MSGT_TS_CONF_RES: - rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TS_CONF_RES_ACK); - break; - case OM2K_MSGT_TF_CONF_RES: - rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TF_CONF_RES_ACK); - break; - case OM2K_MSGT_ENABLE_RES: - rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_ENABLE_RES_ACK); - break; - case OM2K_MSGT_DISABLE_RES: - rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_DISABLE_RES_ACK); - break; - case OM2K_MSGT_TEST_RES: - rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TEST_RES_ACK); - break; - case OM2K_MSGT_CAPA_RES: - rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_CAPA_RES_ACK); - break; - /* ERrors */ - case OM2K_MSGT_START_REQ_REJ: - case OM2K_MSGT_CONNECT_REJ: - case OM2K_MSGT_OP_INFO_REJ: - case OM2K_MSGT_DISCONNECT_REJ: - case OM2K_MSGT_TEST_REQ_REJ: - case OM2K_MSGT_CON_CONF_REQ_REJ: - case OM2K_MSGT_IS_CONF_REQ_REJ: - case OM2K_MSGT_TX_CONF_REQ_REJ: - case OM2K_MSGT_RX_CONF_REQ_REJ: - case OM2K_MSGT_TS_CONF_REQ_REJ: - case OM2K_MSGT_TF_CONF_REQ_REJ: - case OM2K_MSGT_ENABLE_REQ_REJ: - case OM2K_MSGT_ALARM_STATUS_REQ_REJ: - case OM2K_MSGT_DISABLE_REQ_REJ: - rc = om2k_rx_nack(msg); - break; - } - - /* Resolve the MO for this message */ - mo = get_om2k_mo(bts, &o2h->mo); - if (!mo) { - LOGP(DNM, LOGL_ERROR, "Couldn't resolve MO for OM2K msg " - "%s: %s\n", get_value_string(om2k_msgcode_vals, msg_type), - msgb_hexdump(msg)); - return 0; - } - if (!mo->fsm) { - LOGP(DNM, LOGL_ERROR, "MO object should not generate any message. fsm == NULL " - "%s: %s\n", get_value_string(om2k_msgcode_vals, msg_type), - msgb_hexdump(msg)); - return 0; - } - - /* Dispatch message to that MO */ - om2k_mo_fsm_recvmsg(bts, mo, &odm); - - msgb_free(msg); - return rc; -} - -static void om2k_mo_init(struct om2k_mo *mo, uint8_t class, - uint8_t bts_nr, uint8_t assoc_so, uint8_t inst) -{ - mo->addr.class = class; - mo->addr.bts = bts_nr; - mo->addr.assoc_so = assoc_so; - mo->addr.inst = inst; -} - -/* initialize the OM2K_MO members of gsm_bts_trx and its timeslots */ -void abis_om2k_trx_init(struct gsm_bts_trx *trx) -{ - struct gsm_bts *bts = trx->bts; - unsigned int i; - - OSMO_ASSERT(bts->type == GSM_BTS_TYPE_RBS2000); - - om2k_mo_init(&trx->rbs2000.trxc.om2k_mo, OM2K_MO_CLS_TRXC, - bts->nr, 255, trx->nr); - om2k_mo_init(&trx->rbs2000.tx.om2k_mo, OM2K_MO_CLS_TX, - bts->nr, 255, trx->nr); - om2k_mo_init(&trx->rbs2000.rx.om2k_mo, OM2K_MO_CLS_RX, - bts->nr, 255, trx->nr); - - for (i = 0; i < ARRAY_SIZE(trx->ts); i++) { - om2k_mo_init(&trx->ts[i].rbs2000.om2k_mo, OM2K_MO_CLS_TS, - bts->nr, trx->nr, i); - } -} - -/* initialize the OM2K_MO members of gsm_bts */ -void abis_om2k_bts_init(struct gsm_bts *bts) -{ - OSMO_ASSERT(bts->type == GSM_BTS_TYPE_RBS2000); - - om2k_mo_init(&bts->rbs2000.cf.om2k_mo, OM2K_MO_CLS_CF, - bts->nr, 0xFF, 0); - om2k_mo_init(&bts->rbs2000.is.om2k_mo, OM2K_MO_CLS_IS, - bts->nr, 0xFF, 0); - om2k_mo_init(&bts->rbs2000.con.om2k_mo, OM2K_MO_CLS_CON, - bts->nr, 0xFF, 0); - om2k_mo_init(&bts->rbs2000.dp.om2k_mo, OM2K_MO_CLS_DP, - bts->nr, 0xFF, 0); - om2k_mo_init(&bts->rbs2000.tf.om2k_mo, OM2K_MO_CLS_TF, - bts->nr, 0xFF, 0); -} - -static __attribute__((constructor)) void abis_om2k_init(void) -{ - osmo_fsm_register(&om2k_mo_fsm); - osmo_fsm_register(&om2k_bts_fsm); - osmo_fsm_register(&om2k_trx_fsm); -} diff --git a/src/libbsc/abis_om2000_vty.c b/src/libbsc/abis_om2000_vty.c deleted file mode 100644 index a6bc4c78c..000000000 --- a/src/libbsc/abis_om2000_vty.c +++ /dev/null @@ -1,609 +0,0 @@ -/* VTY interface for A-bis OM2000 */ - -/* (C) 2010-2011 by Harald Welte <laforge@gnumonks.org> - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <stdint.h> - -#include <arpa/inet.h> - -#include <openbsc/gsm_data.h> -#include <osmocom/core/msgb.h> -#include <osmocom/gsm/tlv.h> -#include <osmocom/core/talloc.h> -#include <openbsc/debug.h> -#include <openbsc/signal.h> -#include <openbsc/abis_om2000.h> -#include <openbsc/vty.h> - -#include <osmocom/vty/vty.h> -#include <osmocom/vty/command.h> -#include <osmocom/vty/logging.h> -#include <osmocom/vty/telnet_interface.h> - -extern struct gsm_network *bsc_gsmnet; - -static struct cmd_node om2k_node = { - OM2K_NODE, - "%s(om2k)# ", - 1, -}; - -static struct cmd_node om2k_con_group_node = { - OM2K_CON_GROUP_NODE, - "%s(om2k-con-group)# ", - 1, -}; - -struct con_group; - -struct oml_node_state { - struct gsm_bts *bts; - struct abis_om2k_mo mo; - struct con_group *cg; -}; - -static int dummy_config_write(struct vty *v) -{ - return CMD_SUCCESS; -} - -/* FIXME: auto-generate those strings from the value_string lists */ -#define OM2K_OBJCLASS_VTY "(trxc|ts|tf|is|con|dp|cf|tx|rx)" -#define OM2K_OBJCLASS_VTY_HELP "TRX Controller\n" \ - "Timeslot\n" \ - "Timing Function\n" \ - "Interface Switch\n" \ - "Abis Concentrator\n" \ - "Digital Path\n" \ - "Central Function\n" \ - "Transmitter\n" \ - "Receiver\n" - -DEFUN(om2k_class_inst, om2k_class_inst_cmd, - "bts <0-255> om2000 class " OM2K_OBJCLASS_VTY - " <0-255> <0-255> <0-255>", - "BTS related commands\n" "BTS Number\n" - "Manipulate the OM2000 managed objects\n" - "Object Class\n" OM2K_OBJCLASS_VTY_HELP - "BTS Number\n" "Associated SO Instance\n" "Instance Number\n") -{ - struct gsm_bts *bts; - struct oml_node_state *oms; - int bts_nr = atoi(argv[0]); - - bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr); - if (!bts) { - vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE); - return CMD_WARNING; - } - - if (bts->type != GSM_BTS_TYPE_RBS2000) { - vty_out(vty, "%% BTS %d not an Ericsson RBS%s", - bts_nr, VTY_NEWLINE); - return CMD_WARNING; - } - - oms = talloc_zero(tall_bsc_ctx, struct oml_node_state); - if (!oms) - return CMD_WARNING; - - oms->bts = bts; - oms->mo.class = get_string_value(om2k_mo_class_short_vals, argv[1]); - oms->mo.bts = atoi(argv[2]); - oms->mo.assoc_so = atoi(argv[3]); - oms->mo.inst = atoi(argv[4]); - - vty->index = oms; - vty->node = OM2K_NODE; - - return CMD_SUCCESS; - -} - -DEFUN(om2k_classnum_inst, om2k_classnum_inst_cmd, - "bts <0-255> om2000 class <0-255> <0-255> <0-255> <0-255>", - "BTS related commands\n" "BTS Number\n" - "Manipulate the OML managed objects\n" - "Object Class\n" "Object Class\n" - "BTS Number\n" "Associated SO Instance\n" "Instance Number\n") -{ - struct gsm_bts *bts; - struct oml_node_state *oms; - int bts_nr = atoi(argv[0]); - - bts = gsm_bts_num(gsmnet_from_vty(vty), bts_nr); - if (!bts) { - vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE); - return CMD_WARNING; - } - - oms = talloc_zero(tall_bsc_ctx, struct oml_node_state); - if (!oms) - return CMD_WARNING; - - oms->bts = bts; - oms->mo.class = atoi(argv[1]); - oms->mo.bts = atoi(argv[2]); - oms->mo.assoc_so = atoi(argv[3]); - oms->mo.inst = atoi(argv[4]); - - vty->index = oms; - vty->node = OM2K_NODE; - - return CMD_SUCCESS; -} - -DEFUN(om2k_reset, om2k_reset_cmd, - "reset-command", - "Reset the MO\n") -{ - struct oml_node_state *oms = vty->index;< |