aboutsummaryrefslogtreecommitdiffstats
path: root/src/libmsc/a_iface_bssap.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2018-02-09 01:23:25 +0100
committerHarald Welte <laforge@gnumonks.org>2018-02-09 02:22:22 +0100
commitc27ef657968dc3c842ac8338c75912430723d1e2 (patch)
treee5d9b2e9737aa89b822bec38fc50a53307484242 /src/libmsc/a_iface_bssap.c
parentc65d324ea68b2954887ad381c9379d2e6d78c6d9 (diff)
a_iface: centralize lookup of subscriber_conn
There's little point in resolving the gsm_subscriber_connection in each and every function handling connection-oriented messages. We can resolve it once and dispatch the already-resolved conn into the function, instead of passing the raw sccp_user and a_conn_info. Change-Id: Iea85527ea4d4cde7b36cc28a8027362c1570518f
Diffstat (limited to 'src/libmsc/a_iface_bssap.c')
-rw-r--r--src/libmsc/a_iface_bssap.c115
1 files changed, 42 insertions, 73 deletions
diff --git a/src/libmsc/a_iface_bssap.c b/src/libmsc/a_iface_bssap.c
index 809cb3a2f..ad10a8c81 100644
--- a/src/libmsc/a_iface_bssap.c
+++ b/src/libmsc/a_iface_bssap.c
@@ -223,16 +223,14 @@ void a_sccp_rx_udt(struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_
*/
/* Endpoint to handle BSSMAP clear request */
-static int bssmap_rx_clear_rqst(struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg)
+static int bssmap_rx_clear_rqst(struct gsm_subscriber_connection *conn, struct msgb *msg)
{
- struct gsm_network *network = a_conn_info->network;
struct tlv_parsed tp;
int rc;
struct msgb *msg_resp;
uint8_t cause;
- struct gsm_subscriber_connection *conn;
- LOGP(DMSC, LOGL_INFO, "BSC requested to clear connection (conn_id=%i)\n", a_conn_info->conn_id);
+ LOGPCONN(conn, LOGL_INFO, "BSC requested to clear connection\n");
tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, msgb_l3len(msg) - 1, 0, 0);
if (!TLVP_PRESENT(&tp, GSM0808_IE_CAUSE)) {
@@ -243,28 +241,24 @@ static int bssmap_rx_clear_rqst(struct osmo_sccp_user *scu, const struct a_conn_
/* Respond with clear command */
msg_resp = gsm0808_create_clear_command(GSM0808_CAUSE_CALL_CONTROL);
- rc = osmo_sccp_tx_data_msg(scu, a_conn_info->conn_id, msg_resp);
+ rc = osmo_sccp_tx_data_msg(conn->a.scu, conn->a.conn_id, msg_resp);
- /* If possible, inform the MSC about the clear request */
- conn = subscr_conn_lookup_a(network, a_conn_info->conn_id);
- if (!conn)
- goto fail;
msc_clear_request(conn, cause);
msgb_free(msg);
return rc;
-
fail:
msgb_free(msg);
return -EINVAL;
}
/* Endpoint to handle BSSMAP clear complete */
-static int bssmap_rx_clear_complete(struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg)
+static int bssmap_rx_clear_complete(struct osmo_sccp_user *scu,
+ const struct a_conn_info *a_conn_info, struct msgb *msg)
{
int rc;
- LOGP(DMSC, LOGL_INFO, "Releasing connection (conn_id=%i)\n", a_conn_info->conn_id);
+ LOGP(DMSC, LOGL_INFO, "Rx BSSMAP CLEAR COMPPLETE, releasing SCCP connection\n");
rc = osmo_sccp_tx_disconn(scu, a_conn_info->conn_id,
NULL, SCCP_RELEASE_CAUSE_END_USER_ORIGINATED);
@@ -357,20 +351,14 @@ fail:
}
/* Endpoint to handle BSSMAP classmark update */
-static int bssmap_rx_classmark_upd(struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg)
+static int bssmap_rx_classmark_upd(struct gsm_subscriber_connection *conn, struct msgb *msg)
{
- struct gsm_network *network = a_conn_info->network;
- struct gsm_subscriber_connection *conn;
struct tlv_parsed tp;
const uint8_t *cm2 = NULL;
const uint8_t *cm3 = NULL;
uint8_t cm2_len = 0;
uint8_t cm3_len = 0;
- conn = subscr_conn_lookup_a(network, a_conn_info->conn_id);
- if (!conn)
- goto fail;
-
LOGPCONN(conn, LOGL_DEBUG, "Rx BSSMAP CLASSMARK UPDATE\n");
tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, msgb_l3len(msg) - 1, 0, 0);
@@ -399,8 +387,7 @@ fail:
}
/* Endpoint to handle BSSMAP cipher mode complete */
-static int bssmap_rx_ciph_compl(const struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info,
- struct msgb *msg)
+static int bssmap_rx_ciph_compl(struct gsm_subscriber_connection *conn, struct msgb *msg)
{
/* FIXME: The field GSM0808_IE_LAYER_3_MESSAGE_CONTENTS is optional by
* means of the specification. So there can be messages without L3 info.
@@ -409,15 +396,9 @@ static int bssmap_rx_ciph_compl(const struct osmo_sccp_user *scu, const struct a
* msc_cipher_mode_compl() was never meant to be used without L3 data.
* This needs to be discussed further! */
- struct gsm_network *network = a_conn_info->network;
- struct gsm_subscriber_connection *conn;
struct tlv_parsed tp;
uint8_t alg_id = 1;
- conn = subscr_conn_lookup_a(network, a_conn_info->conn_id);
- if (!conn)
- goto fail;
-
LOGPCONN(conn, LOGL_DEBUG, "Rx BSSMAP CIPHER MODE COMPLETE\n");
tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, msgb_l3len(msg) - 1, 0, 0);
@@ -439,23 +420,14 @@ static int bssmap_rx_ciph_compl(const struct osmo_sccp_user *scu, const struct a
msgb_free(msg);
return 0;
-fail:
- msgb_free(msg);
- return -EINVAL;
}
/* Endpoint to handle BSSMAP cipher mode reject */
-static int bssmap_rx_ciph_rej(const struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg)
+static int bssmap_rx_ciph_rej(struct gsm_subscriber_connection *conn, struct msgb *msg)
{
- struct gsm_network *network = a_conn_info->network;
- struct gsm_subscriber_connection *conn;
struct tlv_parsed tp;
uint8_t cause;
- conn = subscr_conn_lookup_a(network, a_conn_info->conn_id);
- if (!conn)
- goto fail;
-
LOGPCONN(conn, LOGL_NOTICE, "RX BSSMAP CIPHER MODE REJECT\n");
tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, msgb_l3len(msg) - 1, 0, 0);
@@ -478,19 +450,13 @@ fail:
}
/* Endpoint to handle BSSMAP assignment failure */
-static int bssmap_rx_ass_fail(const struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg)
+static int bssmap_rx_ass_fail(struct gsm_subscriber_connection *conn, struct msgb *msg)
{
- struct gsm_network *network = a_conn_info->network;
- struct gsm_subscriber_connection *conn;
struct tlv_parsed tp;
uint8_t cause;
uint8_t *rr_cause_ptr = NULL;
uint8_t rr_cause;
- conn = subscr_conn_lookup_a(network, a_conn_info->conn_id);
- if (!conn)
- goto fail;
-
LOGPCONN(conn, LOGL_NOTICE, "Rx BSSMAP ASSIGNMENT FAILURE message\n");
tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 1, msgb_l3len(msg) - 1, 0, 0);
@@ -516,24 +482,18 @@ static int bssmap_rx_ass_fail(const struct osmo_sccp_user *scu, const struct a_c
msgb_free(msg);
return 0;
+
fail:
msgb_free(msg);
return -EINVAL;
}
/* Endpoint to handle sapi "n" reject */
-static int bssmap_rx_sapi_n_rej(const struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info,
- struct msgb *msg)
+static int bssmap_rx_sapi_n_rej(struct gsm_subscriber_connection *conn, struct msgb *msg)
{
- struct gsm_network *network = a_conn_info->network;
- struct gsm_subscriber_connection *conn;
struct tlv_parsed tp;
uint8_t dlci;
- conn = subscr_conn_lookup_a(network, a_conn_info->conn_id);
- if (!conn)
- goto fail;
-
LOGPCONN(conn, LOGL_NOTICE, "BSC sends sapi \"n\" reject message\n");
/* Note: The MSC code seems not to care about the cause code, but by
@@ -557,27 +517,21 @@ static int bssmap_rx_sapi_n_rej(const struct osmo_sccp_user *scu, const struct a
msgb_free(msg);
return 0;
+
fail:
msgb_free(msg);
return -EINVAL;
}
/* Endpoint to handle assignment complete */
-static int bssmap_rx_ass_compl(const struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info,
- struct msgb *msg)
+static int bssmap_rx_ass_compl(struct gsm_subscriber_connection *conn, struct msgb *msg)
{
- struct gsm_network *network = a_conn_info->network;
- struct gsm_subscriber_connection *conn;
struct mgcp_client *mgcp;
struct tlv_parsed tp;
struct sockaddr_storage rtp_addr;
struct sockaddr_in *rtp_addr_in;
int rc;
- conn = subscr_conn_lookup_a(network, a_conn_info->conn_id);
- if (!conn)
- goto fail;
-
mgcp = conn->network->mgw.client;
OSMO_ASSERT(mgcp);
@@ -622,35 +576,50 @@ fail:
/* Handle incoming connection oriented BSSMAP messages */
static int rx_bssmap(struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg)
{
+ struct gsm_subscriber_connection *conn;
+
if (msgb_l3len(msg) < 1) {
LOGP(DMSC, LOGL_NOTICE, "Error: No data received -- discarding message!\n");
msgb_free(msg);
return -1;
}
- LOGP(DMSC, LOGL_DEBUG, "Rx BSSMAP DT1 %s\n", gsm0808_bssmap_name(msg->l3h[0]));
-
+ /* Only message types allowed without a 'conn' */
switch (msg->l3h[0]) {
- case BSS_MAP_MSG_CLEAR_RQST:
- return bssmap_rx_clear_rqst(scu, a_conn_info, msg);
- case BSS_MAP_MSG_CLEAR_COMPLETE:
- return bssmap_rx_clear_complete(scu, a_conn_info, msg);
case BSS_MAP_MSG_COMPLETE_LAYER_3:
return bssmap_rx_l3_compl(scu, a_conn_info, msg);
+ case BSS_MAP_MSG_CLEAR_COMPLETE:
+ return bssmap_rx_clear_complete(scu, a_conn_info, msg);
+ default:
+ break;
+ }
+
+ conn = subscr_conn_lookup_a(a_conn_info->network, a_conn_info->conn_id);
+ if (!conn) {
+ LOGP(DMSC, LOGL_ERROR, "Couldn't find subscr_conn for conn_id=%d\n", a_conn_info->conn_id);
+ msgb_free(msg);
+ return -EINVAL;
+ }
+
+ LOGPCONN(conn, LOGL_DEBUG, "Rx BSSMAP DT1 %s\n", gsm0808_bssmap_name(msg->l3h[0]));
+
+ switch (msg->l3h[0]) {
+ case BSS_MAP_MSG_CLEAR_RQST:
+ return bssmap_rx_clear_rqst(conn, msg);
case BSS_MAP_MSG_CLASSMARK_UPDATE:
- return bssmap_rx_classmark_upd(scu, a_conn_info, msg);
+ return bssmap_rx_classmark_upd(conn, msg);
case BSS_MAP_MSG_CIPHER_MODE_COMPLETE:
- return bssmap_rx_ciph_compl(scu, a_conn_info, msg);
+ return bssmap_rx_ciph_compl(conn, msg);
case BSS_MAP_MSG_CIPHER_MODE_REJECT:
- return bssmap_rx_ciph_rej(scu, a_conn_info, msg);
+ return bssmap_rx_ciph_rej(conn, msg);
case BSS_MAP_MSG_ASSIGMENT_FAILURE:
- return bssmap_rx_ass_fail(scu, a_conn_info, msg);
+ return bssmap_rx_ass_fail(conn, msg);
case BSS_MAP_MSG_SAPI_N_REJECT:
- return bssmap_rx_sapi_n_rej(scu, a_conn_info, msg);
+ return bssmap_rx_sapi_n_rej(conn, msg);
case BSS_MAP_MSG_ASSIGMENT_COMPLETE:
- return bssmap_rx_ass_compl(scu, a_conn_info, msg);
+ return bssmap_rx_ass_compl(conn, msg);
default:
- LOGP(DMSC, LOGL_ERROR, "Unimplemented msg type: %s\n", gsm0808_bssmap_name(msg->l3h[0]));
+ LOGPCONN(conn, LOGL_ERROR, "Unimplemented msg type: %s\n", gsm0808_bssmap_name(msg->l3h[0]));
msgb_free(msg);
return -EINVAL;
}