osmo-bsc/src/osmo-bsc/osmo_bsc_msc.c

495 lines
17 KiB
C
Raw Permalink Normal View History

/*
* Handle the connection to the MSC. This include ping/timeout/reconnect
* (C) 2008-2018 by Harald Welte <laforge@gnumonks.org>
* (C) 2009-2015 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009-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/>.
*
*/
#include <osmocom/ctrl/control_cmd.h>
#include <osmocom/ctrl/control_if.h>
#include <osmocom/crypt/auth.h>
#include <osmocom/bsc/debug.h>
#include <osmocom/bsc/gsm_data.h>
#include <osmocom/bsc/ipaccess.h>
#include <osmocom/bsc/bsc_msc_data.h>
#include <osmocom/bsc/osmo_bsc_sigtran.h>
#include <osmocom/bsc/signal.h>
#include <osmocom/bsc/bts.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/socket.h>
#include <osmocom/gsm/gsm0808.h>
#include <osmocom/gsm/gsm23236.h>
src: port openBSC over libosmo-abis This is a big patch that ports openBSC over libosmo-abis. Sorry, the changes that are included here are all dependent of libosmo-abis, splitting them into smaller pieces would leave the repository in some intermediate state, which is not desired. The main changes are: - The directory libabis/ has been removed as it now lives in libosmo-abis. - new configuration file format for nanoBTS and HSL femto, we need to define the virtual e1_line and attach it to the OML link. - all the existing BTS drivers (nanoBTS, hsl femto, Nokia site, BS11 and rbs2000) now use the new libosmo-abis framework. - use r232 input driver available in libosmo-abis for bs11_config. - use ipa_msg_recv instead of old ipaccess_read_msg function. - delete definition of gsm_e1_subslot and input_signal_data. These structures now lives in libosmo-abis. Most of this patch are deletions of libabis/ which has been moved to libosmo-abis. This patch also modifies openBSC to use all the new definitions available in libosmocore and libosmo-abis. In order to do that, we have replaced the following: - DINP, DMI, DMIB and DMUX by their respective DL* correspondences. - SS_GLOBAL by SS_L_GLOBAL - SS_INPUT by SS_L_INPUT - S_GLOBAL_SHUTDOWN by S_L_GLOBAL_SHUTDOWN - SS_INPUT by SS_L_INPUT - S_INP_* by S_L_INP_* sub-signals - E1INP_NODE by L_E1INP_NODE vty node This patch has been tested with: - one nanoBTS - the HSL femto with the examples available under libosmo-abis - BS11 with both dahdi and misdn drivers.
2011-08-17 20:44:07 +00:00
#include <osmocom/abis/ipa.h>
#include <osmocom/mgcp_client/mgcp_client.h>
sccplite: Use mgwpool config to set up socket forwarding IPA-MGCP from MSC to MGW In SCCPlite, the BSC receives the CN-side MGCP from the MSC through an IPA conn, and it then forwards those messages to its co-located MGW through a rawUDP socket created at startup. This forwarding UDP socket still relied exclusively on the "mgw.conf" struct which was filled only by the old VTY interface which was been deprecated lately. This patch moves the mgw-pool setup before the msc setup so that if the VTY config file still uses the old VTY, the single MGW is added to the MGW pool through mgcp_client_pool_register_single(). It then simply picks the first available MGW from the pool when creating the raw UDP MGCP-forwarding socket. This means SCCPLite is still left with supporting only 1 MGW. If more than one MGW is defined in the pool, then when the call is being set up a different MGW could be picked from the pool while the CN-side MGCP would still be sent to the MGW pool selected at osm-bsc startup. This limitation coul be removed later on by adding a new VTY command under the "msc" to pin calls for an MSC to an MGW with a given "mgw_nr" from the pool, and that same MGW be looked for in the pool every time a new call is being established. Another possibility would be to avoid creating the "connected" UDP socket at osmo-bsc startup, and rather use it in non-connected mode and transmit (sendto) using the mgcp_client remote address during call establishment. In any case, this is left as future excercise since so far there hasn't been any need for multiple MGWs in SCCPLite setups. Related: SYS#5987 Change-Id: If105dee52b8d36161c759f979eaef4579b47d365
2022-10-26 09:18:23 +00:00
#include <osmocom/mgcp_client/mgcp_client_pool.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <unistd.h>
static const struct rate_ctr_desc msc_ctr_description[] = {
/* Rx message counters (per specific message) */
[MSC_CTR_BSSMAP_RX_UDT_RESET_ACKNOWLEDGE] = {
"bssmap:rx:udt:reset:ack",
"Number of received BSSMAP UDT RESET ACKNOWLEDGE messages"
},
[MSC_CTR_BSSMAP_RX_UDT_RESET] = {
"bssmap:rx:udt:reset:request",
"Number of received BSSMAP UDT RESET messages"
},
[MSC_CTR_BSSMAP_RX_UDT_PAGING] = {
"bssmap:rx:udt:paging",
"Number of received BSSMAP UDT PAGING messages"
},
[MSC_CTR_BSSMAP_RX_UDT_UNKNOWN] = {
"bssmap:rx:udt:err_unknown",
"Number of received BSSMAP unknown UDT messages"
},
[MSC_CTR_BSSMAP_RX_DT1_CLEAR_CMD] = {
"bssmap:rx:dt1:clear:cmd",
"Number of received BSSMAP DT1 CLEAR CMD messages"
},
[MSC_CTR_BSSMAP_RX_DT1_CIPHER_MODE_CMD] = {
"bssmap:rx:dt1:cipher_mode:cmd",
"Number of received BSSMAP DT1 CIPHER MODE CMD messages"
},
[MSC_CTR_BSSMAP_RX_DT1_ASSIGNMENT_RQST] = {
"bssmap:rx:dt1:assignment:rqst",
"Number of received BSSMAP DT1 ASSIGNMENT RQST messages"
},
[MSC_CTR_BSSMAP_RX_DT1_LCLS_CONNECT_CTRL] = {
"bssmap:rx:dt1:lcls_connect_ctrl:cmd",
"Number of received BSSMAP DT1 LCLS CONNECT CTRL messages"
},
[MSC_CTR_BSSMAP_RX_DT1_HANDOVER_RQST] = {
"bssmap:rx:dt1:handover:rqst",
"Number of received BSSMAP DT1 HANDOVER RQST messages"
},
[MSC_CTR_BSSMAP_RX_DT1_HANDOVER_CMD] = {
"bssmap:rx:dt1:handover:cmd",
"Number of received BSSMAP DT1 HANDOVER CMD messages"
},
[MSC_CTR_BSSMAP_RX_DT1_CLASSMARK_RQST] = {
"bssmap:rx:dt1:classmark:rqst",
"Number of received BSSMAP DT1 CLASSMARK RQST messages"
},
[MSC_CTR_BSSMAP_RX_DT1_CONFUSION] = {
"bssmap:rx:dt1:confusion",
"Number of received BSSMAP DT1 CONFUSION messages"
},
[MSC_CTR_BSSMAP_RX_DT1_COMMON_ID] = {
"bssmap:rx:dt1:common_id",
"Number of received BSSMAP DT1 COMMON ID messages"
},
[MSC_CTR_BSSMAP_RX_DT1_UNKNOWN] = {
"bssmap:rx:dt1:err_unknown",
"Number of received BSSMAP unknown DT1 messages"
},
[MSC_CTR_BSSMAP_RX_DT1_DTAP] = {
"bssmap:rx:dt1:dtap:good",
"Number of received BSSMAP DTAP messages"
},
[MSC_CTR_BSSMAP_RX_DT1_DTAP_ERROR] = {
"bssmap:rx:dt1:dtap:error",
"Number of received BSSMAP DTAP messages with errors"
},
[MSC_CTR_BSSMAP_RX_DT1_PERFORM_LOCATION_REQUEST] = {
"bssmap:rx:dt1:location:request",
"Number of received BSSMAP Perform Location Request messages"
},
[MSC_CTR_BSSMAP_RX_DT1_PERFORM_LOCATION_ABORT] = {
"bssmap:tx:dt1:location:abort",
"Number of received BSSMAP Perform Location Abort messages"
},
[MSC_CTR_BSSMAP_RX_DT1_VGCS_VBS_SETUP] = {
"bssmap:rx:dt1:vgcs_vbs_setup",
"Number of received BSSMAP DT1 VGCS/VBS SETUP messages"
},
[MSC_CTR_BSSMAP_RX_DT1_VGCS_VBS_ASSIGN_RQST] = {
"bssmap:rx:dt1:vgcs_vbs_assignment:req",
"Number of received BSSMAP DT1 VGCS/VBS ASSIGNMENT messages"
},
[MSC_CTR_BSSMAP_RX_DT1_UPLINK_RQST_ACKNOWLEDGE] = {
"bssmap:rx:dt1:uplink_rqst:ack",
"Number of received BSSMAP DT1 UPLINK REQUEST ACKNOWLEDGE messages"
},
[MSC_CTR_BSSMAP_RX_DT1_UPLINK_REJECT_CMD] = {
"bssmap:rx:dt1:uplink_reject:cmd",
"Number of received BSSMAP DT1 UPLINK REJECT COMMAND messages"
},
[MSC_CTR_BSSMAP_RX_DT1_UPLINK_RELEASE_CMD] = {
"bssmap:rx:dt1:uplink_release:cmd",
"Number of received BSSMAP DT1 UPLINK RELEASE COMMAND messages"
},
[MSC_CTR_BSSMAP_RX_DT1_UPLINK_SEIZED_CMD] = {
"bssmap:rx:dt1:uplink_seized:cmd",
"Number of received BSSMAP DT1 UPLINK SEIZED COMMAND messages"
},
[MSC_CTR_BSSMAP_RX_DT1_VGCS_ADDL_INFO] = {
"bssmap:rx:dt1:vgcs_addl_info",
"Number of received BSSMAP DT1 VGCS/VBS ASSITIONAL INFORMATION messages"
},
[MSC_CTR_BSSMAP_RX_DT1_VGCS_SMS] = {
"bssmap:rx:dt1:vgcs_sms",
"Number of received BSSMAP DT1 VGCS SMS messages"
},
[MSC_CTR_BSSMAP_RX_DT1_NOTIFICATION_DATA] = {
"bssmap:rx:dt1:notification_data",
"Number of received BSSMAP DT1 NOTIFICATION DATA messages"
},
/* Tx message counters (per message type)
*
* The counters here follow the logic of the osmo_bsc_sigtran_send() function
* which receives DT1 messages from the upper layers and actually sends them to the MSC.
* These counters cover all messages passed to the function by the upper layers: */
[MSC_CTR_BSSMAP_TX_BSS_MANAGEMENT] = {
"bssmap:tx:type:bss_management",
"Number of transmitted BSS MANAGEMENT messages"
},
[MSC_CTR_BSSMAP_TX_DTAP] = {
"bssmap:tx:type:dtap",
"Number of transmitted DTAP messages"
},
[MSC_CTR_BSSMAP_TX_UNKNOWN] = {
"bssmap:tx:type:err_unknown",
"Number of transmitted messages with unknown type (an error in our code?)"
},
[MSC_CTR_BSSMAP_TX_SHORT] = {
"bssmap:tx:type:err_short",
"Number of transmitted messages which are too short (an error in our code?)"
},
/* The next counters are also counted in the osmo_bsc_sigtran_send() function and
* sum up to the exactly same number as the counters above but instead of message
* classes they split by the result of the sending attempt: */
[MSC_CTR_BSSMAP_TX_ERR_CONN_NOT_READY] = {
"bssmap:tx:result:err_conn_not_ready",
"Number of BSSMAP messages we tried to send when the connection was not ready yet"
},
[MSC_CTR_BSSMAP_TX_ERR_SEND] = {
"bssmap:tx:result:err_send",
"Number of socket errors while sending BSSMAP messages"
},
[MSC_CTR_BSSMAP_TX_SUCCESS] = {
"bssmap:tx:result:success",
"Number of successfully sent BSSMAP messages"
},
/* Tx message counters (per specific message)
*
* Theoretically, the DT1 counters should sum up to the same number as the Tx counters
* above but since these counters are coming from the upper layers, there might be
* some difference if we forget some code path. */
[MSC_CTR_BSSMAP_TX_UDT_RESET] = {
"bssmap:tx:udt:reset:request",
"Number of transmitted BSSMAP UDT RESET messages"
},
[MSC_CTR_BSSMAP_TX_UDT_RESET_ACK] = {
"bssmap:tx:udt:reset:ack",
"Number of transmitted BSSMAP UDT RESET ACK messages"
},
[MSC_CTR_BSSMAP_TX_DT1_CLEAR_RQST] = {
"bssmap:tx:dt1:clear:rqst",
"Number of transmitted BSSMAP DT1 CLEAR RQSTtx messages"
},
[MSC_CTR_BSSMAP_TX_DT1_CLEAR_COMPLETE] = {
"bssmap:tx:dt1:clear:complete",
"Number of transmitted BSSMAP DT1 CLEAR COMPLETE messages"
},
[MSC_CTR_BSSMAP_TX_DT1_ASSIGNMENT_FAILURE] = {
"bssmap:tx:dt1:assignment:failure",
"Number of transmitted BSSMAP DT1 ASSIGNMENT FAILURE messages"
},
[MSC_CTR_BSSMAP_TX_DT1_ASSIGNMENT_COMPLETE] = {
"bssmap:tx:dt1:assignment:complete",
"Number of transmitted BSSMAP DT1 ASSIGNMENT COMPLETE messages"
},
[MSC_CTR_BSSMAP_TX_DT1_SAPI_N_REJECT] = {
"bssmap:tx:dt1:sapi_n:reject",
"Number of transmitted BSSMAP DT1 SAPI N REJECT messages"
},
[MSC_CTR_BSSMAP_TX_DT1_CIPHER_COMPLETE] = {
"bssmap:tx:dt1:cipher_mode:complete",
"Number of transmitted BSSMAP DT1 CIPHER COMPLETE messages"
},
[MSC_CTR_BSSMAP_TX_DT1_CIPHER_REJECT] = {
"bssmap:tx:dt1:cipher_mode:reject",
"Number of transmitted BSSMAP DT1 CIPHER REJECT messages"
},
[MSC_CTR_BSSMAP_TX_DT1_CLASSMARK_UPDATE] = {
"bssmap:tx:dt1:classmark:update",
"Number of transmitted BSSMAP DT1 CLASSMARK UPDATE messages"
},
[MSC_CTR_BSSMAP_TX_DT1_LCLS_CONNECT_CTRL_ACK] = {
"bssmap:tx:dt1:lcls_connect_ctrl:ack",
"Number of transmitted BSSMAP DT1 LCLS CONNECT CTRL ACK messages"
},
[MSC_CTR_BSSMAP_TX_DT1_HANDOVER_REQUIRED] = {
"bssmap:tx:dt1:handover:required",
"Number of transmitted BSSMAP DT1 HANDOVER REQUIRED messages"
},
[MSC_CTR_BSSMAP_TX_DT1_HANDOVER_PERFORMED] = {
"bssmap:tx:dt1:handover:performed",
"Number of transmitted BSSMAP DT1 HANDOVER PERFORMED messages"
},
[MSC_CTR_BSSMAP_TX_DT1_HANDOVER_RQST_ACKNOWLEDGE] = {
"bssmap:tx:dt1:handover:rqst_acknowledge",
"Number of transmitted BSSMAP DT1 HANDOVER RQST ACKNOWLEDGE messages"
},
[MSC_CTR_BSSMAP_TX_DT1_HANDOVER_DETECT] = {
"bssmap:tx:dt1:handover:detect",
"Number of transmitted BSSMAP DT1 HANDOVER DETECT messages"
},
[MSC_CTR_BSSMAP_TX_DT1_HANDOVER_COMPLETE] = {
"bssmap:tx:dt1:handover:complete",
"Number of transmitted BSSMAP DT1 HANDOVER COMPLETE messages"
},
[MSC_CTR_BSSMAP_TX_DT1_HANDOVER_FAILURE] = {
"bssmap:tx:dt1:handover:failure",
"Number of transmitted BSSMAP DT1 HANDOVER FAILURE messages"
},
[MSC_CTR_BSSMAP_TX_DT1_DTAP] = {
"bssmap:tx:dt1:dtap",
"Number of transmitted BSSMAP DT1 DTAP messages"
},
[MSC_CTR_BSSMAP_TX_DT1_PERFORM_LOCATION_RESPONSE_SUCCESS] = {
"bssmap:tx:dt1:location:response_success",
"Number of transmitted BSSMAP Perform Location Response messages containing a location estimate"
},
[MSC_CTR_BSSMAP_TX_DT1_PERFORM_LOCATION_RESPONSE_FAILURE] = {
"bssmap:tx:dt1:location:response_failure",
"Number of transmitted BSSMAP Perform Location Response messages containing a failure cause"
},
[MSC_CTR_BSSMAP_TX_DT1_VGCS_VBS_SETUP_ACK] = {
"bssmap:tx:dt1:vgcs_vbs_setup:ack",
"Number of transmitted BSSMAP DT1 VGCS/VBS SETUP ACK messages"
},
[MSC_CTR_BSSMAP_TX_DT1_VGCS_VBS_SETUP_REFUSE] = {
"bssmap:tx:dt1:vgcs_vbs_setup:refuse",
"Number of transmitted BSSMAP DT1 VGCS/VBS SETUP REFUSE messages"
},
[MSC_CTR_BSSMAP_TX_DT1_VGCS_VBS_ASSIGN_RESULT] = {
"bssmap:tx:dt1:vgcs_vbs_assignment:res",
"Number of transmitted BSSMAP DT1 VGCS/VBS ASSIGNMENT RESULT messages"
},
[MSC_CTR_BSSMAP_TX_DT1_VGCS_VBS_ASSIGN_FAIL] = {
"bssmap:tx:dt1:vgcs_vbs_assignment:fail",
"Number of transmitted BSSMAP DT1 VGCS/VBS ASSIGNMENT FAILURE messages"
},
[MSC_CTR_BSSMAP_TX_DT1_VGCS_VBS_QUEUING_INDICATION] = {
"bssmap:tx:dt1:vgcs_vbs_queuing:ind",
"Number of transmitted BSSMAP DT1 VGCS/VBS QUEUING INDICATION messages"
},
[MSC_CTR_BSSMAP_TX_DT1_UPLINK_RQST] = {
"bssmap:tx:dt1:uplink_rqst",
"Number of transmitted BSSMAP DT1 UPLINK REQUEST messages"
},
[MSC_CTR_BSSMAP_TX_DT1_VGCS_VBS_ASSIGNMENT_STATUS] = {
"bssmap:tx:dt1:vgcs_vbs_assignment:status",
"Number of transmitted BSSMAP DT1 VGCS/VBS ASSIGNMENT STATUS messages"
},
[MSC_CTR_BSSMAP_TX_DT1_VGCS_VBS_AREA_CELL_INFO] = {
"bssmap:tx:dt1:vgcs_vbs_area_cell:info",
"Number of transmitted BSSMAP DT1 VGCS/VBS AREA CELL INFO messages"
},
[MSC_CTR_BSSMAP_TX_DT1_UPLINK_RQST_CONFIRMATION] = {
"bssmap:tx:dt1:uplink_rqst:cnf",
"Number of transmitted BSSMAP DT1 UPLINK REQUEST CONFIRMATION messages"
},
[MSC_CTR_BSSMAP_TX_DT1_UPLINK_RELEASE_INDICATION] = {
"bssmap:tx:dt1:uplink_release:ind",
"Number of transmitted BSSMAP DT1 UPLINK RELEASE INDICATION messages"
},
[MSC_CTR_BSSMAP_TX_DT1_UPLINK_APP_DATA] = {
"bssmap:tx:dt1:uplink_app_data",
"Number of transmitted BSSMAP DT1 UPLINK APPLICATION DATA messages"
},
/* Indicators for MSC pool usage */
[MSC_CTR_MSCPOOL_SUBSCR_NEW] = {
"mscpool:subscr:new",
"Complete Layer 3 requests assigned to this MSC by round-robin (no NRI was assigned yet).",
},
[MSC_CTR_MSCPOOL_SUBSCR_REATTACH] = {
"mscpool:subscr:reattach",
"Complete Layer 3 requests assigned to this MSC by round-robin because the subscriber indicates a"
" NULL-NRI (previously assigned by another MSC).",
},
[MSC_CTR_MSCPOOL_SUBSCR_KNOWN] = {
"mscpool:subscr:known",
"Complete Layer 3 requests directed to this MSC because the subscriber indicates an NRI of this MSC.",
},
[MSC_CTR_MSCPOOL_SUBSCR_PAGED] = {
"mscpool:subscr:paged",
"Paging Response directed to this MSC because the subscriber was recently paged by this MSC.",
},
[MSC_CTR_MSCPOOL_SUBSCR_ATTACH_LOST] = {
"mscpool:subscr:attach_lost",
"A subscriber indicates an NRI value matching this MSC, but the MSC is not connected:"
" a re-attach to another MSC (if available) was forced, with possible service failure.",
},
[MSC_CTR_MSCPOOL_EMERG_FORWARDED] = {
"mscpool:emerg:forwarded",
"Emergency call requests forwarded to this MSC.",
},
};
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,
};
static const struct osmo_stat_item_desc msc_stat_desc[] = {
[MSC_STAT_MSC_LINKS_ACTIVE] = { "msc_links:active", "Number of active MSC links", "", 16, 0 },
[MSC_STAT_MSC_LINKS_TOTAL] = { "msc_links:total", "Number of configured MSC links", "", 16, 0 },
};
static const struct osmo_stat_item_group_desc msc_statg_desc = {
.group_name_prefix = "msc",
.group_description = "mobile switching center",
.class_id = OSMO_STATS_CLASS_GLOBAL,
.num_items = ARRAY_SIZE(msc_stat_desc),
.item_desc = msc_stat_desc,
};
int osmo_bsc_msc_init(struct bsc_msc_data *msc)
{
int rc;
/* Everything below refers to SCCP-Lite MSC connections only. */
if (msc_is_aoip(msc))
return 0;
rc = osmo_sock_init2_ofd(&msc->mgcp_ipa.ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP,
msc->mgcp_ipa.local_addr, msc->mgcp_ipa.local_port,
NULL, 0, OSMO_SOCK_F_BIND);
if (rc < 0) {
LOGP(DMSC, LOGL_ERROR, "msc %u: Could not create/connect/bind MGCP proxy socket: %d\n",
msc->nr, rc);
return rc;
}
sccplite: Use mgwpool config to set up socket forwarding IPA-MGCP from MSC to MGW In SCCPlite, the BSC receives the CN-side MGCP from the MSC through an IPA conn, and it then forwards those messages to its co-located MGW through a rawUDP socket created at startup. This forwarding UDP socket still relied exclusively on the "mgw.conf" struct which was filled only by the old VTY interface which was been deprecated lately. This patch moves the mgw-pool setup before the msc setup so that if the VTY config file still uses the old VTY, the single MGW is added to the MGW pool through mgcp_client_pool_register_single(). It then simply picks the first available MGW from the pool when creating the raw UDP MGCP-forwarding socket. This means SCCPLite is still left with supporting only 1 MGW. If more than one MGW is defined in the pool, then when the call is being set up a different MGW could be picked from the pool while the CN-side MGCP would still be sent to the MGW pool selected at osm-bsc startup. This limitation coul be removed later on by adding a new VTY command under the "msc" to pin calls for an MSC to an MGW with a given "mgw_nr" from the pool, and that same MGW be looked for in the pool every time a new call is being established. Another possibility would be to avoid creating the "connected" UDP socket at osmo-bsc startup, and rather use it in non-connected mode and transmit (sendto) using the mgcp_client remote address during call establishment. In any case, this is left as future excercise since so far there hasn't been any need for multiple MGWs in SCCPLite setups. Related: SYS#5987 Change-Id: If105dee52b8d36161c759f979eaef4579b47d365
2022-10-26 09:18:23 +00:00
LOGP(DMSC, LOGL_INFO, "msc %u: Socket forwarding IPA-encapsulated MGCP messages towards MGW: %s\n",
msc->nr, osmo_sock_get_name2(msc->mgcp_ipa.ofd.fd));
return 0;
}
struct bsc_msc_data *osmo_msc_data_find(struct gsm_network *net, int nr)
{
struct bsc_msc_data *msc_data;
llist_for_each_entry(msc_data, &net->mscs, entry)
if (msc_data->nr == nr)
return msc_data;
return NULL;
}
struct bsc_msc_data *osmo_msc_data_alloc(struct gsm_network *net, int nr)
{
struct bsc_msc_data *msc_data;
/* check if there is already one */
msc_data = osmo_msc_data_find(net, nr);
if (msc_data)
return msc_data;
msc_data = talloc_zero(net, struct bsc_msc_data);
if (!msc_data)
return NULL;
/* init statistics */
msc_data->msc_ctrs = rate_ctr_group_alloc(net, &msc_ctrg_desc, nr);
if (!msc_data->msc_ctrs) {
talloc_free(msc_data);
return NULL;
}
msc_data->msc_statg = osmo_stat_item_group_alloc(net, &msc_statg_desc, nr);
if (!msc_data->msc_statg) {
rate_ctr_group_free(msc_data->msc_ctrs);
talloc_free(msc_data);
return NULL;
}
llist_add_tail(&msc_data->entry, &net->mscs);
/* Init back pointer */
msc_data->network = net;
msc_data->core_plmn = (struct osmo_plmn_id){
.mcc = GSM_MCC_MNC_INVALID,
.mnc = GSM_MCC_MNC_INVALID,
};
msc_data->nr = nr;
msc_data->allow_emerg = 1;
msc_data->a.asp_proto = OSMO_SS7_ASP_PROT_M3UA;
/* Defaults for the audio setup */
msc_data->amr_conf.m5_90 = 1;
msc_data->amr_octet_aligned = true;
/* Allow the full set of possible codecs by default */
msc_data->audio_length = 5;
msc_data->audio_support[0].ver = 1;
msc_data->audio_support[0].hr = 0;
msc_data->audio_support[1].ver = 1;
msc_data->audio_support[1].hr = 1;
msc_data->audio_support[2].ver = 2;
msc_data->audio_support[2].hr = 0;
msc_data->audio_support[3].ver = 3;
msc_data->audio_support[3].hr = 0;
msc_data->audio_support[4].ver = 3;
msc_data->audio_support[4].hr = 1;
osmo_fd_setup(&msc_data->mgcp_ipa.ofd, -1, OSMO_FD_READ, &bsc_sccplite_mgcp_proxy_cb, msc_data, 0);
msc_data->mgcp_ipa.local_addr = NULL; /* = INADDR(6)_ANY */
msc_data->mgcp_ipa.local_port = 0; /* dynamic */
msc_data->nri_ranges = osmo_nri_ranges_alloc(msc_data);
msc_data->allow_attach = true;
return msc_data;
}
struct osmo_cell_global_id *cgi_for_msc(struct bsc_msc_data *msc, struct gsm_bts *bts)
{
static struct osmo_cell_global_id cgi;
fix crashes due to OSMO_ASSERT(conn->lchan) Starting from ttcn3-bsc-test-sccplite build #777, it was noticed that osmo-bsc crashes with the following message: Assert failed conn->lchan include/osmocom/bsc/gsm_data.h:1376 The cause of this is a recently merged patch that calls conn_get_bts() during assignment_fsm rate counter dispatch: "Count assignment rates per BTS as well" commit b5ccf09fc4042c7fb1fdaaa6263961c40b32564e Change-Id I0009e51d4caf68e762138d98e2e23d49acc3cc1a The root cause being that the assignment_fsm attempts to count an Assignment event for a BTS after the lchan has already been released and disassociated from the conn. The assertion is found in conn_get_bts(), which is used in various places. In fact, each caller is a potential DoS risk -- though most are in code paths that are guaranteed to have an lchan and bts present, having an OSMO_ASSERT() on the relatively volatile presence of an lchan is not a good idea for osmo-bsc's stability and error resilience. - Change conn_get_bts() to return NULL in the lack of an lchan. - Adjust all callers of conn_get_bts() to gracefully handle a NULL return val. - Same for cgi_for_msc() and callers, closely related. Here is a backtrace: Program received signal SIGABRT pwndbg> bt 0x0000555555be6e52 in conn_get_bts (conn=0x622000057160) at include/osmocom/bsc/gsm_data.h:1376 0x0000555555c1edc8 in assignment_fsm_timer_cb (fi=0x612000060220) at assignment_fsm.c:758 0x00007ffff72b1104 in fsm_tmr_cb (data=0x612000060220) at libosmocore/src/fsm.c:325 0x00007ffff72ab062 in osmo_timers_update () at libosmocore/src/timer.c:257 0x00007ffff72ab5d2 in _osmo_select_main (polling=0) at libosmocore/src/select.c:260 0x00007ffff72abd2f in osmo_select_main_ctx (polling=<optimized out>) at libosmocore/src/select.c:291 0x0000555555e1b81b in main (argc=3, argv=0x7fffffffe1b8) at osmo_bsc_main.c:953 0x00007ffff6752002 in __libc_start_main () from /usr/lib/libc.so.6 0x0000555555b61bbe in _start () In the case of the assignment_fsm counter, we now miss a chance to increase a BTS counter for a failed Assignment, but this is a separate problem. The main point of this patch is that osmo-bsc must not crash. Related: OS#4620, OS#4619 Patch-by: fixeria Tweaked-by: neels Fixes: I0009e51d4caf68e762138d98e2e23d49acc3cc1a Change-Id: Id681dfb0ad654bdb4b71805d1ad4f39a8bf6bbd1
2020-06-18 15:29:56 +00:00
if (!bts)
return NULL;
cgi.lai.plmn = msc->network->plmn;
if (msc->core_plmn.mcc != GSM_MCC_MNC_INVALID)
cgi.lai.plmn.mcc = msc->core_plmn.mcc;
if (msc->core_plmn.mnc != GSM_MCC_MNC_INVALID) {
cgi.lai.plmn.mnc = msc->core_plmn.mnc;
cgi.lai.plmn.mnc_3_digits = msc->core_plmn.mnc_3_digits;
}
cgi.lai.lac = bts->location_area_code;
cgi.cell_identity = bts->cell_identity;
return &cgi;
}