aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <axilirator@gmail.com>2018-06-12 08:03:53 +0700
committerVadim Yanitskiy <axilirator@gmail.com>2018-06-12 23:31:34 +0700
commit5df4e4ddde86c1ca2528a6749c071d24925e9136 (patch)
tree4e979dd00b9cac8abe2fd459fd11deb6f35a0c60
parent9aec25e464865573acc7ccde92f471a1af799cd6 (diff)
libmsc/gsm_04_80.c: make the API abstract from ss_request struct
There is no need to pass a pointer to a ss_request struct when calling the gsm0480_send_ussd_* functions, because they only use both transaction ID and InvokeID from there, which may be passed directly. This change allows one to use this API without parsing the whole GSM 04.80 message, or when parsing is failed. Moreover, if InvokeID is not available, one can pass any incorrect, (e.g. negative) value, so the universal NULL tag will be used. Finally, setting a TI flag is also up to the caller. Change-Id: I13d5abbfdcf8238ebaf0566c420f09cd9255b648
-rw-r--r--include/osmocom/msc/gsm_04_80.h10
-rw-r--r--src/libmsc/gsm_04_80.c79
-rw-r--r--src/libmsc/gsm_09_11.c16
3 files changed, 77 insertions, 28 deletions
diff --git a/include/osmocom/msc/gsm_04_80.h b/include/osmocom/msc/gsm_04_80.h
index fb057c8db..7d630888f 100644
--- a/include/osmocom/msc/gsm_04_80.h
+++ b/include/osmocom/msc/gsm_04_80.h
@@ -7,14 +7,14 @@
struct gsm_subscriber_connection;
int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn,
- const char* response_text,
- const struct ss_request *req);
+ uint8_t transaction_id, uint8_t invoke_id,
+ const char *response_text);
int gsm0480_send_ussd_return_error(struct gsm_subscriber_connection *conn,
- const struct ss_request *req,
+ uint8_t transaction_id, uint8_t invoke_id,
uint8_t error_code);
int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn,
- const struct ss_request *req,
- uint8_t error_tag, uint8_t error_code);
+ uint8_t transaction_id, int invoke_id,
+ uint8_t problem_tag, uint8_t problem_code);
int msc_send_ussd_notify(struct gsm_subscriber_connection *conn, int level,
const char *text);
diff --git a/src/libmsc/gsm_04_80.c b/src/libmsc/gsm_04_80.c
index 8799fcbdc..32e8e23e0 100644
--- a/src/libmsc/gsm_04_80.c
+++ b/src/libmsc/gsm_04_80.c
@@ -59,10 +59,28 @@ static inline unsigned char *msgb_push_TLV1(struct msgb *msgb, uint8_t tag,
return data;
}
+static inline unsigned char *msgb_push_NULL(struct msgb *msgb)
+{
+ uint8_t *data = msgb_push(msgb, 2);
-/* Send response to a mobile-originated ProcessUnstructuredSS-Request */
+ data[0] = ASN1_NULL_TYPE_TAG;
+ data[1] = 0;
+ return data;
+}
+
+
+/*! Send a MT RELEASE COMPLETE message with USSD-response,
+ * wrapped into the ReturnResult component (see section 3.6.1).
+ *
+ * \param[in] conn Active subscriber connection
+ * \param[in] transaction_id Transaction ID with TI flag set
+ * \param[in] invoke_id InvokeID of the request
+ * \param[in] response_text The response text
+ * \return result of \ref msc_tx_dtap
+ */
int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn,
- const char *response_text, const struct ss_request *req)
+ uint8_t transaction_id, uint8_t invoke_id,
+ const char *response_text)
{
struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 USSD RSP");
struct gsm48_hdr *gh;
@@ -91,7 +109,7 @@ int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn,
msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG);
/* Pre-pend the invoke ID */
- msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id);
+ msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id);
/* Wrap this up as a Return Result component */
msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_RESULT);
@@ -101,15 +119,24 @@ int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn,
/* And finally pre-pend the L3 header */
gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_NC_SS | req->transaction_id
- | (1<<7); /* TI direction = 1 */
+ gh->proto_discr = GSM48_PDISC_NC_SS;
+ gh->proto_discr |= transaction_id << 4;
gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE;
return msc_tx_dtap(conn, msg);
}
+/*! Send a MT RELEASE COMPLETE message with ReturnError component
+ * (see section 3.6.1) and given error code (see section 3.6.6).
+ *
+ * \param[in] conn Active subscriber connection
+ * \param[in] transaction_id Transaction ID with TI flag set
+ * \param[in] invoke_id InvokeID of the request
+ * \param[in] error_code Error code (section 4.5)
+ * \return result of \ref msc_tx_dtap
+ */
int gsm0480_send_ussd_return_error(struct gsm_subscriber_connection *conn,
- const struct ss_request *req, uint8_t error_code)
+ uint8_t transaction_id, uint8_t invoke_id, uint8_t error_code)
{
struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 USSD ERR");
struct gsm48_hdr *gh;
@@ -118,7 +145,7 @@ int gsm0480_send_ussd_return_error(struct gsm_subscriber_connection *conn,
msgb_push_TLV1(msg, GSM_0480_ERROR_CODE_TAG, error_code);
/* Before it insert the invoke ID */
- msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id);
+ msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id);
/* Wrap this up as a Reject component */
msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_ERROR);
@@ -128,25 +155,45 @@ int gsm0480_send_ussd_return_error(struct gsm_subscriber_connection *conn,
/* And finally pre-pend the L3 header */
gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_NC_SS;
- gh->proto_discr |= req->transaction_id | (1<<7); /* TI direction = 1 */
+ gh->proto_discr = GSM48_PDISC_NC_SS;
+ gh->proto_discr |= transaction_id << 4;
gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE;
return msc_tx_dtap(conn, msg);
}
+/*! Send a MT RELEASE COMPLETE message with Reject component
+ * (see section 3.6.1) and given error code (see section 3.6.7).
+ *
+ * \param[in] conn Active subscriber connection
+ * \param[in] transaction_id Transaction ID with TI flag set
+ * \param[in] invoke_id InvokeID of the request
+ * \param[in] problem_tag Problem code tag (table 3.13)
+ * \param[in] problem_code Problem code (tables 3.14-17)
+ * \return result of \ref msc_tx_dtap
+ *
+ * Note: if InvokeID is not available, e.g. when message parsing
+ * failed, any incorrect value can be passed (0x00 > x > 0xff), so
+ * the universal NULL-tag (see table 3.6) will be used instead.
+ */
int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn,
- const struct ss_request *req,
- uint8_t error_tag, uint8_t error_code)
+ uint8_t transaction_id, int invoke_id,
+ uint8_t problem_tag, uint8_t problem_code)
{
struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 USSD REJ");
struct gsm48_hdr *gh;
/* First insert the problem code */
- msgb_push_TLV1(msg, error_tag, error_code);
+ msgb_push_TLV1(msg, problem_tag, problem_code);
- /* Before it insert the invoke ID */
- msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id);
+ /**
+ * If the Invoke ID is not available, Universal Null
+ * (table 3.9) with length = 0 shall be used.
+ */
+ if (invoke_id < 0 || invoke_id > 255)
+ msgb_push_NULL(msg);
+ else
+ msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id);
/* Wrap this up as a Reject component */
msgb_wrap_with_TL(msg, GSM0480_CTYPE_REJECT);
@@ -156,8 +203,8 @@ int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn,
/* And finally pre-pend the L3 header */
gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_NC_SS;
- gh->proto_discr |= req->transaction_id | (1<<7); /* TI direction = 1 */
+ gh->proto_discr = GSM48_PDISC_NC_SS;
+ gh->proto_discr |= transaction_id << 4;
gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE;
return msc_tx_dtap(conn, msg);
diff --git a/src/libmsc/gsm_09_11.c b/src/libmsc/gsm_09_11.c
index fc588f5c2..799dfaa63 100644
--- a/src/libmsc/gsm_09_11.c
+++ b/src/libmsc/gsm_09_11.c
@@ -46,7 +46,7 @@ const char USSD_TEXT_OWN_NUMBER[] = "*#100#";
/* A network-specific handler function */
static int send_own_number(struct gsm_subscriber_connection *conn,
- const struct ss_request *req)
+ uint8_t tid, uint8_t invoke_id)
{
char *own_number = conn->vsub->msisdn;
char response_string[GSM_EXTENSION_LENGTH + 20];
@@ -56,7 +56,7 @@ static int send_own_number(struct gsm_subscriber_connection *conn,
/* Need trailing CR as EOT character */
snprintf(response_string, sizeof(response_string), "Your extension is %s\r", own_number);
- return gsm0480_send_ussd_response(conn, response_string, req);
+ return gsm0480_send_ussd_response(conn, tid, invoke_id, response_string);
}
/* Entry point for call independent MO SS messages */
@@ -121,7 +121,8 @@ int gsm0911_rcv_nc_ss(struct gsm_subscriber_connection *conn, struct msgb *msg)
if (!rc) {
LOGP(DMM, LOGL_ERROR, "SS/USSD message parsing error, "
"rejecting request...\n");
- gsm0480_send_ussd_reject(conn, &req, GSM_0480_PROBLEM_CODE_TAG_GENERAL,
+ gsm0480_send_ussd_reject(conn, tid, -1,
+ GSM_0480_PROBLEM_CODE_TAG_GENERAL,
GSM_0480_GEN_PROB_CODE_UNRECOGNISED);
/* The GSM 04.80 API uses inverted codes (0 means error) */
return -EPROTO;
@@ -131,8 +132,8 @@ int gsm0911_rcv_nc_ss(struct gsm_subscriber_connection *conn, struct msgb *msg)
if (req.ussd_text[0] == '\0' || req.ussd_text[0] == 0xFF) {
if (req.ss_code > 0) {
/* Assume interrogateSS or modification of it and reject */
- return gsm0480_send_ussd_return_error(conn, &req,
- GSM0480_ERR_CODE_ILLEGAL_SS_OPERATION);
+ return gsm0480_send_ussd_return_error(conn, tid,
+ req.invoke_id, GSM0480_ERR_CODE_ILLEGAL_SS_OPERATION);
}
/* Still assuming a Release-Complete and returning */
return 0;
@@ -141,10 +142,11 @@ int gsm0911_rcv_nc_ss(struct gsm_subscriber_connection *conn, struct msgb *msg)
msc_subscr_conn_communicating(conn);
if (!strcmp(USSD_TEXT_OWN_NUMBER, (const char *)req.ussd_text)) {
DEBUGP(DMM, "USSD: Own number requested\n");
- rc = send_own_number(conn, &req);
+ rc = send_own_number(conn, tid, req.invoke_id);
} else {
DEBUGP(DMM, "Unhandled USSD %s\n", req.ussd_text);
- rc = gsm0480_send_ussd_return_error(conn, &req,
+ rc = gsm0480_send_ussd_return_error(conn,
+ tid, req.invoke_id,
GSM0480_ERR_CODE_UNEXPECTED_DATA_VALUE);
}