mirror of https://gerrit.osmocom.org/libosmocore
gsm/gsm0480: refactor and expose gsm0480_parse_facility_ie()
This function can be used when there is only a part of GSM 04.80 message available - Facility IE, e.g. when a message is carried over GSUP/MAP. Let's expose it. Refactoring includes the following: - adding the 'gsm0480_' prefix; - correcting inverted return value; - cosmetic code style changes. Change-Id: I623c39ffbe6cdee65eade8435a2faa04d0da193e
This commit is contained in:
parent
52e44121db
commit
5a09f75c1e
|
@ -93,6 +93,8 @@ struct ss_request {
|
|||
|
||||
int gsm0480_extract_ie_by_tag(const struct gsm48_hdr *hdr, uint16_t msg_len,
|
||||
uint8_t **ie, uint16_t *ie_len, uint8_t ie_tag);
|
||||
int gsm0480_parse_facility_ie(const uint8_t *facility_ie, uint16_t length,
|
||||
struct ss_request *req);
|
||||
int gsm0480_decode_ss_request(const struct gsm48_hdr *hdr, uint16_t len,
|
||||
struct ss_request *request);
|
||||
|
||||
|
|
|
@ -201,8 +201,6 @@ static int parse_ss_facility(const uint8_t *ss_facility, uint16_t len,
|
|||
struct ss_request *req);
|
||||
static int parse_ss_info_elements(const uint8_t *ss_ie, uint16_t len,
|
||||
struct ss_request *req);
|
||||
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,
|
||||
|
@ -419,7 +417,7 @@ static int parse_ss_facility(const uint8_t *ss_facility, uint16_t len,
|
|||
if (len - 1 < facility_length)
|
||||
return 0;
|
||||
|
||||
return parse_facility_ie(ss_facility + 1, facility_length, req);
|
||||
return !gsm0480_parse_facility_ie(ss_facility + 1, facility_length, req);
|
||||
}
|
||||
|
||||
static int parse_ss_info_elements(const uint8_t *ss_ie, uint16_t len,
|
||||
|
@ -445,7 +443,7 @@ static int parse_ss_info_elements(const uint8_t *ss_ie, uint16_t len,
|
|||
case GSM48_IE_CAUSE:
|
||||
break;
|
||||
case GSM0480_IE_FACILITY:
|
||||
rc = parse_facility_ie(ss_ie + 2, iei_length, req);
|
||||
rc = !gsm0480_parse_facility_ie(ss_ie + 2, iei_length, req);
|
||||
break;
|
||||
case GSM0480_IE_SS_VERSION:
|
||||
break;
|
||||
|
@ -464,31 +462,40 @@ static int parse_ss_info_elements(const uint8_t *ss_ie, uint16_t len,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int parse_facility_ie(const uint8_t *facility_ie, uint16_t length,
|
||||
struct ss_request *req)
|
||||
/*! Parse the components of a given Facility IE
|
||||
* \param[in] facility_ie The Facility IE
|
||||
* \param[in] length The length of Facility IE
|
||||
* \param[out] req Abstract representation of SS message
|
||||
* \return 0 in case of success, otherwise -ERRNO
|
||||
*/
|
||||
int gsm0480_parse_facility_ie(const uint8_t *facility_ie, uint16_t length,
|
||||
struct ss_request *req)
|
||||
{
|
||||
int rc = 1;
|
||||
uint8_t component_length;
|
||||
uint8_t component_type;
|
||||
uint8_t offset = 0;
|
||||
int rc = 1;
|
||||
|
||||
/* Iterate over components within IE */
|
||||
while (offset + 2 <= length) {
|
||||
/* Component Type tag - table 3.7 */
|
||||
uint8_t component_type = facility_ie[offset];
|
||||
uint8_t component_length = facility_ie[offset+1];
|
||||
component_type = facility_ie[offset];
|
||||
component_length = facility_ie[offset + 1];
|
||||
|
||||
/* size check */
|
||||
/* Make sure that there is no overflow */
|
||||
if (offset + 2 + component_length > length) {
|
||||
LOGP(0, LOGL_ERROR, "Component does not fit.\n");
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (component_type) {
|
||||
case GSM0480_CTYPE_INVOKE:
|
||||
rc &= parse_ss_invoke(facility_ie+2,
|
||||
rc &= parse_ss_invoke(facility_ie + 2,
|
||||
component_length,
|
||||
req);
|
||||
break;
|
||||
case GSM0480_CTYPE_RETURN_RESULT:
|
||||
rc &= parse_ss_return_result(facility_ie+2,
|
||||
rc &= parse_ss_return_result(facility_ie + 2,
|
||||
component_length,
|
||||
req);
|
||||
break;
|
||||
|
@ -502,10 +509,17 @@ static int parse_facility_ie(const uint8_t *facility_ie, uint16_t length,
|
|||
rc = 0;
|
||||
break;
|
||||
}
|
||||
offset += (component_length+2);
|
||||
};
|
||||
|
||||
return rc;
|
||||
offset += (component_length + 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* The internal functions are using inverted return
|
||||
* codes, where '0' means error/failure. While a
|
||||
* common approach is to return negative errno in
|
||||
* case of any failure, and '0' if all is ok.
|
||||
*/
|
||||
return (rc == 0) ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
/* Parse an Invoke component - see table 3.3 */
|
||||
|
|
|
@ -90,6 +90,7 @@ gsm0480_create_ussd_resp;
|
|||
gsm0480_create_ussd_notify;
|
||||
gsm0480_create_ussd_release_complete;
|
||||
gsm0480_extract_ie_by_tag;
|
||||
gsm0480_parse_facility_ie;
|
||||
gsm0480_decode_ussd_request;
|
||||
gsm0480_decode_ss_request;
|
||||
gsm0480_wrap_facility;
|
||||
|
|
|
@ -188,6 +188,43 @@ static void test_extract_ie_by_tag(void)
|
|||
printf("\n");
|
||||
}
|
||||
|
||||
static void test_parse_facility_ie(void)
|
||||
{
|
||||
struct ss_request req;
|
||||
uint16_t ie_len;
|
||||
uint8_t *ie;
|
||||
int rc;
|
||||
|
||||
printf("[i] Testing gsm0480_parse_facility_ie()\n");
|
||||
|
||||
/* Extract Facility IE from FACILITY message */
|
||||
rc = gsm0480_extract_ie_by_tag((struct gsm48_hdr *) ussd_facility,
|
||||
sizeof(ussd_facility), &ie, &ie_len, GSM0480_IE_FACILITY);
|
||||
OSMO_ASSERT(rc == 0);
|
||||
OSMO_ASSERT(ie != NULL && ie_len > 0);
|
||||
printf("[?] FACILITY message with Facility IE "
|
||||
"(len=%u): %s\n", ie_len, osmo_hexdump(ie, ie_len));
|
||||
|
||||
/* Attempt to decode */
|
||||
memset(&req, 0x00, sizeof(req));
|
||||
rc = gsm0480_parse_facility_ie(ie, ie_len, &req);
|
||||
OSMO_ASSERT(rc == 0);
|
||||
|
||||
/* Verify expected vs decoded data */
|
||||
printf("[?] InvokeID: expected 0x%02x, decoded 0x%02x\n",
|
||||
0x01, req.invoke_id);
|
||||
printf("[?] Operation code: expected 0x%02x, decoded 0x%02x\n",
|
||||
0x3c, req.opcode);
|
||||
printf("[?] Data Coding Scheme: expected 0x%02x, decoded 0x%02x\n",
|
||||
0x0f, req.ussd_data_dcs);
|
||||
printf("[?] Data length: expected 0x%02x, decoded 0x%02x\n",
|
||||
0x01, req.ussd_data_len);
|
||||
printf("[?] Data: expected %s, decoded %s\n", "32",
|
||||
osmo_hexdump_nospc(req.ussd_data, req.ussd_data_len));
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct ss_request req;
|
||||
|
@ -201,6 +238,9 @@ int main(int argc, char **argv)
|
|||
/* Test gsm0480_extract_ie_by_tag() */
|
||||
test_extract_ie_by_tag();
|
||||
|
||||
/* Test gsm0480_parse_facility_ie() */
|
||||
test_parse_facility_ie();
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
gsm0480_decode_ss_request((struct gsm48_hdr *) ussd_request,
|
||||
sizeof(ussd_request), &req);
|
||||
|
|
|
@ -4,6 +4,14 @@
|
|||
[?] FACILITY message with Facility IE (len=18): a2 10 02 01 01 30 0b 02 01 3c 30 06 04 01 0f 04 01 32
|
||||
[?] RELEASE COMPLETE message with Facility IE (len=8): a3 06 02 01 05 02 01 24
|
||||
|
||||
[i] Testing gsm0480_parse_facility_ie()
|
||||
[?] FACILITY message with Facility IE (len=18): a2 10 02 01 01 30 0b 02 01 3c 30 06 04 01 0f 04 01 32
|
||||
[?] InvokeID: expected 0x01, decoded 0x01
|
||||
[?] Operation code: expected 0x3c, decoded 0x3c
|
||||
[?] Data Coding Scheme: expected 0x0f, decoded 0x0f
|
||||
[?] Data length: expected 0x01, decoded 0x01
|
||||
[?] Data: expected 32, decoded 32
|
||||
|
||||
Tested if it still works. Text was: **321#
|
||||
interrogateSS CFU text..'' code 33
|
||||
Testing parsing a USSD request and truncated versions
|
||||
|
|
Loading…
Reference in New Issue