diff options
author | Oliver Smith <osmith@sysmocom.de> | 2019-04-04 12:00:24 +0200 |
---|---|---|
committer | Oliver Smith <osmith@sysmocom.de> | 2019-04-09 13:42:26 +0200 |
commit | 95abc2be17f06b28225e19c198340d14d7848c47 (patch) | |
tree | 806d821bd90dea8bcf1fd3e7610687bd8e964e97 /src | |
parent | f1fe94c8cae5591dff4dd77e74c4c2f09638d6a1 (diff) |
USSD: save MO USSD's originating MSC's vlr_number
Save the source IPA name in ss_session, so we can send "invalid IMSI"
messages to the originating MSC.
Remove the fixed size from ss->vlr_number (we don't know the size of the
IPA name when it does not come from the database). Add
ss->vlr_number_len to give osmo_gsup_addr_send() the format it expects,
and to have one less place in the code where the IPA names are not
stored as blob.
Looking up the IPA name from struct osmo_gsup_conn could either be done
like in osmo_gsup_server_ccm_cb() by reading the IPA IEs (which has a
FIXME comment), or by finding the route associated with conn. I went
with the latter approach, because it seems cleaner to me.
Related: OS#3710
Change-Id: If5a65f471672949192061c5fe396603611123bc1
Diffstat (limited to 'src')
-rw-r--r-- | src/gsup_router.c | 24 | ||||
-rw-r--r-- | src/gsup_router.h | 9 | ||||
-rw-r--r-- | src/hlr_ussd.c | 34 |
3 files changed, 53 insertions, 14 deletions
diff --git a/src/gsup_router.c b/src/gsup_router.c index 4fedd38..df978ba 100644 --- a/src/gsup_router.c +++ b/src/gsup_router.c @@ -25,13 +25,7 @@ #include "logging.h" #include "gsup_server.h" - -struct gsup_route { - struct llist_head list; - - uint8_t *addr; - struct osmo_gsup_conn *conn; -}; +#include "gsup_router.h" /*! Find a route for the given address. * \param[in] gs gsup server @@ -53,6 +47,22 @@ struct osmo_gsup_conn *gsup_route_find(struct osmo_gsup_server *gs, return NULL; } +/*! Find a GSUP connection's route (to read the IPA address from the route). + * \param[in] conn GSUP connection + * \return GSUP route + */ +struct gsup_route *gsup_route_find_by_conn(const struct osmo_gsup_conn *conn) +{ + struct gsup_route *gr; + + llist_for_each_entry(gr, &conn->server->routes, list) { + if (gr->conn == conn) + return gr; + } + + return NULL; +} + /* add a new route for the given address to the given conn */ int gsup_route_add(struct osmo_gsup_conn *conn, const uint8_t *addr, size_t addrlen) { diff --git a/src/gsup_router.h b/src/gsup_router.h index 282531d..bff484e 100644 --- a/src/gsup_router.h +++ b/src/gsup_router.h @@ -3,9 +3,18 @@ #include <stdint.h> #include "gsup_server.h" +struct gsup_route { + struct llist_head list; + + uint8_t *addr; + struct osmo_gsup_conn *conn; +}; + struct osmo_gsup_conn *gsup_route_find(struct osmo_gsup_server *gs, const uint8_t *addr, size_t addrlen); +struct gsup_route *gsup_route_find_by_conn(const struct osmo_gsup_conn *conn); + /* add a new route for the given address to the given conn */ int gsup_route_add(struct osmo_gsup_conn *conn, const uint8_t *addr, size_t addrlen); diff --git a/src/hlr_ussd.c b/src/hlr_ussd.c index ea69cd9..56a5a95 100644 --- a/src/hlr_ussd.c +++ b/src/hlr_ussd.c @@ -167,8 +167,11 @@ struct ss_session { const struct hlr_iuse *iuse; } u; - /* subscriber's vlr_number, will be looked up once per session and cached here */ - char vlr_number[32]; + /* subscriber's vlr_number + * MO USSD: originating MSC's vlr_number + * MT USSD: looked up once per session and cached here */ + uint8_t *vlr_number; + size_t vlr_number_len; /* we don't keep a pointer to the osmo_gsup_{route,conn} towards the MSC/VLR here, * as this might change during inter-VLR hand-over, and we simply look-up the serving MSC/VLR @@ -233,24 +236,26 @@ static int ss_gsup_send(struct ss_session *ss, struct osmo_gsup_server *gs, stru int rc; /* Use vlr_number as looked up by the caller, or look up now. */ - if (!ss->vlr_number[0]) { + if (!ss->vlr_number) { rc = db_subscr_get_by_imsi(g_hlr->dbc, ss->imsi, &subscr); if (rc < 0) { LOGPSS(ss, LOGL_ERROR, "Cannot find subscriber, cannot route GSUP message\n"); msgb_free(msg); return -EINVAL; } - osmo_strlcpy(ss->vlr_number, subscr.vlr_number, sizeof(ss->vlr_number)); + ss->vlr_number = (uint8_t *)talloc_strdup(ss, subscr.vlr_number); + ss->vlr_number_len = strlen(subscr.vlr_number) + 1; } - if (!ss->vlr_number[0]) { + /* Check for empty string (all vlr_number strings end in "\0", because otherwise gsup_route_find() fails) */ + if (ss->vlr_number_len == 1) { LOGPSS(ss, LOGL_ERROR, "Cannot send GSUP message, no VLR number stored for subscriber\n"); msgb_free(msg); return -EINVAL; } - LOGPSS(ss, LOGL_DEBUG, "Tx SS/USSD to VLR '%s'\n", ss->vlr_number); - return osmo_gsup_addr_send(gs, (uint8_t *)ss->vlr_number, strlen(ss->vlr_number) + 1, msg); + LOGPSS(ss, LOGL_DEBUG, "Tx SS/USSD to VLR %s\n", osmo_quote_str((char *)ss->vlr_number, ss->vlr_number_len)); + return osmo_gsup_addr_send(gs, ss->vlr_number, ss->vlr_number_len, msg); } static int ss_tx_to_ms(struct ss_session *ss, enum osmo_gsup_message_type gsup_msg_type, @@ -500,6 +505,7 @@ int rx_proc_ss_req(struct osmo_gsup_conn *conn, const struct osmo_gsup_message * struct hlr *hlr = conn->server->priv; struct ss_session *ss; struct ss_request req = {0}; + struct gsup_route *gsup_rt; LOGP(DSS, LOGL_DEBUG, "%s/0x%08x: Process SS (%s)\n", gsup->imsi, gsup->session_id, osmo_gsup_session_state_name(gsup->session_state)); @@ -529,6 +535,20 @@ int rx_proc_ss_req(struct osmo_gsup_conn *conn, const struct osmo_gsup_message * gsup->imsi, gsup->session_id); goto out_err; } + /* Get IPA name from VLR conn and save as ss->vlr_number */ + if (!conn_is_euse(conn)) { + gsup_rt = gsup_route_find_by_conn(conn); + if (gsup_rt) { + ss->vlr_number = (uint8_t *)talloc_strdup(ss, (const char *)gsup_rt->addr); + ss->vlr_number_len = strlen((const char *)gsup_rt->addr) + 1; + LOGPSS(ss, LOGL_DEBUG, "Destination IPA name retrieved from GSUP route: %s\n", + osmo_quote_str((const char *)ss->vlr_number, ss->vlr_number_len)); + } else { + LOGPSS(ss, LOGL_NOTICE, "Could not find GSUP route, therefore can't set the destination" + " IPA name. We'll try to look it up later, but this should not" + " have happened.\n"); + } + } if (ss_op_is_ussd(req.opcode)) { if (conn_is_euse(conn)) { /* EUSE->VLR: MT USSD. EUSE is known ('conn'), VLR is to be resolved */ |