diff options
author | Vadim Yanitskiy <vyanitskiy@sysmocom.de> | 2023-06-28 19:07:49 +0700 |
---|---|---|
committer | fixeria <vyanitskiy@sysmocom.de> | 2023-07-21 12:49:20 +0000 |
commit | 5800f3add5d158be31017233ba286f3ca148f743 (patch) | |
tree | 395f7e8d01011c5c4384b852a7da067c1e9b824b | |
parent | f8b73f06827b00cc9b49a0edc5e550e22ffce474 (diff) |
USSD: fix handling of ussd-DataCodingScheme != 0x0f
The usual Data Coding Scheme value in the mobile-originated USSD
request (processUnstructuredSS-Request) is 0x0f, which means:
0000 .... = Coding Group: Coding Group 0 (Language using the GSM 7 bit default alphabet)
.... 1111 = Language: unspecified
However some modems are known to use a different default value, if
not specified explicitly (AT+CUSD has optional DCS parameter):
0000 .... = Coding Group: Coding Group 0 (Language using the GSM 7 bit default alphabet)
.... 0000 = Language: German (0)
In function rx_proc_ss_req(), we should not be using req.ussd_text,
because this field has been deprecated and may contain unexpected
data. For example, in the abovementioned case it would contain the
7 bit encoded ussd-String 'aa510c061b01'O and osmo-hlr would indeed
fail to find a matching route for a non-ASCII string.
Instead of relaying on gsm0480_parse_facility_ie(), let's check the
Data Coding Scheme value and decode the request string ourselves.
Expect the Coding Group 0, but be more tolerant to the indicated
language: print a warning and treat it as '1111'B (unspecified).
Change-Id: Ib7bac660b1a7942adcfbe7b14f162c95061a25db
Related: OS#6075
-rw-r--r-- | src/hlr_ussd.c | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/src/hlr_ussd.c b/src/hlr_ussd.c index 8d5237f..1c0107b 100644 --- a/src/hlr_ussd.c +++ b/src/hlr_ussd.c @@ -122,9 +122,40 @@ void ussd_route_del(struct hlr_ussd_route *rt) talloc_free(rt); } -static struct hlr_ussd_route *ussd_route_lookup_7bit(struct hlr *hlr, const char *ussd_code) +static struct hlr_ussd_route *ussd_route_lookup_for_req(struct hlr *hlr, const struct ss_request *req) { + const uint8_t cgroup = req->ussd_data_dcs >> 4; + const uint8_t lang = req->ussd_data_dcs & 0x0f; + char ussd_code[GSM0480_USSD_7BIT_STRING_LEN]; struct hlr_ussd_route *rt; + + ussd_code[0] = '\0'; + + /* We support only the Coding Group 0 (GSM 7-bit default alphabeet). In fact, + * the USSD request is usually limited to [*#0-9], so we don't really need to + * support other coding groups and languages. */ + switch (cgroup) { + case 0: + /* The Language is usually set to '1111'B (unspecified), but some UEs + * are known to indicate '0000'B (German). */ + if (lang != 0x0f) { + LOGP(DSS, LOGL_NOTICE, "USSD DataCodingScheme (0x%02x): " + "the Language is usually set to 15 (unspecified), " + "but the request indicates %u - ignoring this\n", + req->ussd_data_dcs, lang); + /* do not abort, attempt to decode as if it was '1111'B */ + } + + gsm_7bit_decode_n_ussd(&ussd_code[0], sizeof(ussd_code), + req->ussd_data, (req->ussd_data_len * 8) / 7); + break; + default: + LOGP(DSS, LOGL_ERROR, "USSD DataCodingScheme (0x%02x): " + "Coding Group %u is not supported, expecting Coding Group 0\n", + req->ussd_data_dcs, cgroup); + return NULL; + } + llist_for_each_entry(rt, &hlr->ussd_routes, list) { if (!strncmp(ussd_code, rt->prefix, strlen(rt->prefix))) { LOGP(DSS, LOGL_DEBUG, "Found %s '%s' (prefix '%s') for USSD " @@ -603,7 +634,7 @@ void rx_proc_ss_req(struct osmo_gsup_req *gsup_req) } else { /* VLR->EUSE: MO USSD. VLR is known ('conn'), EUSE is to be resolved */ struct hlr_ussd_route *rt; - rt = ussd_route_lookup_7bit(hlr, (const char *) req.ussd_text); + rt = ussd_route_lookup_for_req(hlr, &req); if (rt) { if (rt->is_external) { ss->is_external = true; |