summaryrefslogtreecommitdiffstats
path: root/src/gsm/gsm0480.c
diff options
context:
space:
mode:
authorVadim Yanitskiy <axilirator@gmail.com>2017-07-29 05:05:54 +0600
committerHarald Welte <laforge@gnumonks.org>2018-01-17 10:45:39 +0000
commit7f16c443bcffc0b50684df5c9ec52734cd34fe38 (patch)
tree40a2d2fb9a13d7c782d8c8e9e0f02c0394133693 /src/gsm/gsm0480.c
parentc30431ffc73669c89f15de998c82fd1df42bafcb (diff)
gsm0480: handle GSM0480_CTYPE_RETURN_RESULT
Change-Id: I8fb2856acbbf4c53e7d53200a37bc8f79e763bcf
Diffstat (limited to 'src/gsm/gsm0480.c')
-rw-r--r--src/gsm/gsm0480.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c
index 17657c78..fdec3d26 100644
--- a/src/gsm/gsm0480.c
+++ b/src/gsm/gsm0480.c
@@ -204,6 +204,10 @@ static int parse_facility_ie(const uint8_t *facility_ie, uint16_t length,
struct ss_request *req);
static int parse_ss_invoke(const uint8_t *invoke_data, uint16_t length,
struct ss_request *req);
+static int parse_ss_return_result(const uint8_t *rr_data, uint16_t length,
+ struct ss_request *req);
+static int parse_process_uss_data(const uint8_t *uss_req_data, uint16_t length,
+ struct ss_request *req);
static int parse_process_uss_req(const uint8_t *uss_req_data, uint16_t length,
struct ss_request *req);
static int parse_ss_for_bs_req(const uint8_t *ss_req_data,
@@ -372,6 +376,9 @@ static int parse_facility_ie(const uint8_t *facility_ie, uint16_t length,
req);
break;
case GSM0480_CTYPE_RETURN_RESULT:
+ rc &= parse_ss_return_result(facility_ie+2,
+ component_length,
+ req);
break;
case GSM0480_CTYPE_RETURN_ERROR:
break;
@@ -451,6 +458,81 @@ static int parse_ss_invoke(const uint8_t *invoke_data, uint16_t length,
return rc;
}
+/* Parse a Return Result component - see table 3.4 */
+static int parse_ss_return_result(const uint8_t *rr_data, uint16_t length,
+ struct ss_request *req)
+{
+ uint8_t operation_code;
+ uint8_t offset;
+
+ if (length < 3)
+ return 0;
+
+ /* Mandatory part */
+ if (rr_data[0] != GSM0480_COMPIDTAG_INVOKE_ID) {
+ LOGP(0, LOGL_DEBUG, "Unexpected GSM 04.80 Component-ID tag "
+ "0x%02x (expecting Invoke ID tag)\n", rr_data[0]);
+ return 0;
+ }
+
+ offset = rr_data[1] + 2;
+ req->invoke_id = rr_data[2];
+
+ if (offset >= length)
+ return 0;
+
+ if (rr_data[offset] != GSM_0480_SEQUENCE_TAG)
+ return 0;
+
+ if (offset + 2 > length)
+ return 0;
+
+ offset += 2;
+ operation_code = rr_data[offset + 2];
+ req->opcode = operation_code;
+
+ switch (operation_code) {
+ case GSM0480_OP_CODE_USS_NOTIFY:
+ case GSM0480_OP_CODE_USS_REQUEST:
+ case GSM0480_OP_CODE_PROCESS_USS_REQ:
+ return parse_process_uss_req(rr_data + offset + 3,
+ length - offset - 3, req);
+ case GSM0480_OP_CODE_PROCESS_USS_DATA:
+ return parse_process_uss_data(rr_data + offset + 3,
+ length - offset - 3, req);
+ default:
+ LOGP(0, LOGL_DEBUG, "GSM 04.80 operation code 0x%02x "
+ "is not yet handled\n", operation_code);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int parse_process_uss_data(const uint8_t *uss_req_data, uint16_t length,
+ struct ss_request *req)
+{
+ uint8_t num_chars;
+
+ /* we need at least that much */
+ if (length < 3)
+ return 0;
+
+ if (uss_req_data[0] != ASN1_IA5_STRING_TAG)
+ return 0;
+
+ num_chars = uss_req_data[1];
+ if (num_chars > length - 2)
+ return 0;
+
+ if (num_chars > GSM0480_USSD_OCTET_STRING_LEN)
+ num_chars = GSM0480_USSD_OCTET_STRING_LEN;
+
+ memcpy(req->ussd_text, uss_req_data + 2, num_chars);
+
+ return 1;
+}
+
/* Parse the parameters of a Process UnstructuredSS Request */
static int parse_process_uss_req(const uint8_t *uss_req_data, uint16_t length,
struct ss_request *req)