aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2019-10-30 04:30:29 +0100
committerNeels Hofmeyr <neels@hofmeyr.de>2019-11-11 05:31:59 +0100
commit774d114635d3e1ff47b8dfcb7681e2f2cb1180d3 (patch)
treec98f95061a67b8d1b0db5d655b741900d7e7b80f
parent40b52d9b58304d3e57b9ee716a61164f795f7210 (diff)
add osmo_gsup_conn_send_err_reply()
Remove hlr.c's static gsup_send_err_reply(), and create new osmo_gsup_conn_send_err_reply(), as used in osmo-msc. It includes more of the newer IEs in the response, like an SS/USSD session id. Prepares for adding D-GSM / MS lookup, which will need this function moved to a non-static context. Change-Id: I792fd9993ab2a323af58782a357d71205c43b72a
-rw-r--r--src/gsup_server.c50
-rw-r--r--src/gsup_server.h2
-rw-r--r--src/hlr.c29
3 files changed, 58 insertions, 23 deletions
diff --git a/src/gsup_server.c b/src/gsup_server.c
index 2870e9d..a22ee14 100644
--- a/src/gsup_server.c
+++ b/src/gsup_server.c
@@ -57,6 +57,56 @@ int osmo_gsup_conn_send(struct osmo_gsup_conn *conn, struct msgb *msg)
return 0;
}
+/* Encode an error reponse to the given GSUP message with the given cause.
+ * Determine the error message type via OSMO_GSUP_TO_MSGT_ERROR(gsup_orig->message_type).
+ * Only send an error response if the original message is a Request message.
+ * On failure, log an error, but don't return anything: if an error occurs while trying to report an earlier error,
+ * there is nothing we can do really except log the error (there are no callers that would use the return code).
+ */
+void osmo_gsup_conn_send_err_reply(struct osmo_gsup_conn *conn, const struct osmo_gsup_message *gsup_orig,
+ enum gsm48_gmm_cause cause)
+{
+ struct osmo_gsup_message gsup_reply;
+ struct msgb *msg_out;
+ int rc;
+
+ /* No need to answer if we couldn't parse an ERROR message type, only REQUESTs need an error reply. */
+ if (!OSMO_GSUP_IS_MSGT_REQUEST(gsup_orig->message_type))
+ return;
+
+ gsup_reply = (struct osmo_gsup_message){
+ .cause = cause,
+ .message_type = OSMO_GSUP_TO_MSGT_ERROR(gsup_orig->message_type),
+ .message_class = gsup_orig->message_class,
+
+ /* RP-Message-Reference is mandatory for SM Service */
+ .sm_rp_mr = gsup_orig->sm_rp_mr,
+ };
+
+ OSMO_STRLCPY_ARRAY(gsup_reply.imsi, gsup_orig->imsi);
+
+ /* For SS/USSD, it's important to keep both session state and ID IEs */
+ if (gsup_orig->session_state != OSMO_GSUP_SESSION_STATE_NONE) {
+ gsup_reply.session_state = OSMO_GSUP_SESSION_STATE_END;
+ gsup_reply.session_id = gsup_orig->session_id;
+ }
+
+ msg_out = osmo_gsup_msgb_alloc("GSUP ERR response");
+ rc = osmo_gsup_encode(msg_out, &gsup_reply);
+ if (rc) {
+ LOGP(DLGSUP, LOGL_ERROR, "%s: Unable to encode error response %s (rc=%d)\n",
+ osmo_quote_str(gsup_orig->imsi, -1), osmo_gsup_message_type_name(gsup_reply.message_type),
+ rc);
+ return;
+ }
+
+ rc = osmo_gsup_conn_send(conn, msg_out);
+ if (rc)
+ LOGP(DLGSUP, LOGL_ERROR, "%s: Unable to send error response %s (rc=%d)\n",
+ osmo_quote_str(gsup_orig->imsi, -1), osmo_gsup_message_type_name(gsup_reply.message_type),
+ rc);
+}
+
static int osmo_gsup_conn_oap_handle(struct osmo_gsup_conn *conn,
struct msgb *msg_rx)
{
diff --git a/src/gsup_server.h b/src/gsup_server.h
index 14f5013..6dae9bc 100644
--- a/src/gsup_server.h
+++ b/src/gsup_server.h
@@ -50,6 +50,8 @@ struct osmo_gsup_conn {
struct msgb *osmo_gsup_msgb_alloc(const char *label);
int osmo_gsup_conn_send(struct osmo_gsup_conn *conn, struct msgb *msg);
+void osmo_gsup_conn_send_err_reply(struct osmo_gsup_conn *conn, const struct osmo_gsup_message *gsup_orig,
+ enum gsm48_gmm_cause cause);
int osmo_gsup_conn_ccm_get(const struct osmo_gsup_conn *clnt, uint8_t **addr,
uint8_t tag);
diff --git a/src/hlr.c b/src/hlr.c
index aef890e..0cc0448 100644
--- a/src/hlr.c
+++ b/src/hlr.c
@@ -456,23 +456,6 @@ static int rx_purge_ms_req(struct osmo_gsup_conn *conn,
return osmo_gsup_conn_send(conn, msg_out);
}
-static int gsup_send_err_reply(struct osmo_gsup_conn *conn, const char *imsi,
- enum osmo_gsup_message_type type_in, uint8_t err_cause)
-{
- int type_err = OSMO_GSUP_TO_MSGT_ERROR(type_in);
- struct osmo_gsup_message gsup_reply = {0};
- struct msgb *msg_out;
-
- OSMO_STRLCPY_ARRAY(gsup_reply.imsi, imsi);
- gsup_reply.message_type = type_err;
- gsup_reply.cause = err_cause;
- msg_out = osmo_gsup_msgb_alloc("GSUP ERR response");
- OSMO_ASSERT(msg_out);
- osmo_gsup_encode(msg_out, &gsup_reply);
- LOGP(DMAIN, LOGL_NOTICE, "Tx %s\n", osmo_gsup_message_type_name(type_err));
- return osmo_gsup_conn_send(conn, msg_out);
-}
-
static int rx_check_imei_req(struct osmo_gsup_conn *conn, const struct osmo_gsup_message *gsup)
{
struct osmo_gsup_message gsup_reply = {0};
@@ -483,7 +466,7 @@ static int rx_check_imei_req(struct osmo_gsup_conn *conn, const struct osmo_gsup
/* Require IMEI */
if (!gsup->imei_enc) {
LOGP(DMAIN, LOGL_ERROR, "%s: missing IMEI\n", gsup->imsi);
- gsup_send_err_reply(conn, gsup->imsi, gsup->message_type, GMM_CAUSE_INV_MAND_INFO);
+ osmo_gsup_conn_send_err_reply(conn, gsup, GMM_CAUSE_INV_MAND_INFO);
return -1;
}
@@ -491,7 +474,7 @@ static int rx_check_imei_req(struct osmo_gsup_conn *conn, const struct osmo_gsup
rc = gsm48_decode_bcd_number2(imei, sizeof(imei), gsup->imei_enc, gsup->imei_enc_len, 0);
if (rc < 0) {
LOGP(DMAIN, LOGL_ERROR, "%s: failed to decode IMEI (rc: %i)\n", gsup->imsi, rc);
- gsup_send_err_reply(conn, gsup->imsi, gsup->message_type, GMM_CAUSE_INV_MAND_INFO);
+ osmo_gsup_conn_send_err_reply(conn, gsup, GMM_CAUSE_INV_MAND_INFO);
return -1;
}
@@ -499,7 +482,7 @@ static int rx_check_imei_req(struct osmo_gsup_conn *conn, const struct osmo_gsup
if (strlen(imei) != GSM23003_IMEI_NUM_DIGITS_NO_CHK) {
LOGP(DMAIN, LOGL_ERROR, "%s: wrong encoded IMEI length (IMEI: '%s', %lu, %i)\n", gsup->imsi, imei,
strlen(imei), GSM23003_IMEI_NUM_DIGITS_NO_CHK);
- gsup_send_err_reply(conn, gsup->imsi, gsup->message_type, GMM_CAUSE_INV_MAND_INFO);
+ osmo_gsup_conn_send_err_reply(conn, gsup, GMM_CAUSE_INV_MAND_INFO);
return -1;
}
@@ -509,7 +492,7 @@ static int rx_check_imei_req(struct osmo_gsup_conn *conn, const struct osmo_gsup
if (g_hlr->store_imei) {
LOGP(DAUC, LOGL_DEBUG, "IMSI='%s': storing IMEI = %s\n", gsup->imsi, imei);
if (db_subscr_update_imei_by_imsi(g_hlr->dbc, gsup->imsi, imei) < 0) {
- gsup_send_err_reply(conn, gsup->imsi, gsup->message_type, GMM_CAUSE_INV_MAND_INFO);
+ osmo_gsup_conn_send_err_reply(conn, gsup, GMM_CAUSE_INV_MAND_INFO);
return -1;
}
} else {
@@ -517,7 +500,7 @@ static int rx_check_imei_req(struct osmo_gsup_conn *conn, const struct osmo_gsup
LOGP(DMAIN, LOGL_INFO, "IMSI='%s': has IMEI = %s (consider setting 'store-imei')\n", gsup->imsi, imei);
struct hlr_subscriber subscr;
if (db_subscr_get_by_imsi(g_hlr->dbc, gsup->imsi, &subscr) < 0) {
- gsup_send_err_reply(conn, gsup->imsi, gsup->message_type, GMM_CAUSE_INV_MAND_INFO);
+ osmo_gsup_conn_send_err_reply(conn, gsup, GMM_CAUSE_INV_MAND_INFO);
return -1;
}
}
@@ -626,7 +609,7 @@ static int read_cb(struct osmo_gsup_conn *conn, struct msgb *msg)
* digits is impossible. Even 5 digits is a highly theoretical case */
if (strlen(gsup.imsi) < 5) { /* TODO: move this check to libosmogsm/gsup.c? */
LOGP(DMAIN, LOGL_ERROR, "IMSI too short: %s\n", osmo_quote_str(gsup.imsi, -1));
- gsup_send_err_reply(conn, gsup.imsi, gsup.message_type, GMM_CAUSE_INV_MAND_INFO);
+ osmo_gsup_conn_send_err_reply(conn, &gsup, GMM_CAUSE_INV_MAND_INFO);
msgb_free(msg);
return -EINVAL;
}