aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/osmo-bsc_nat
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2011-04-16 14:06:18 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2011-04-19 13:06:47 +0200
commit123bc3283460ef24f054abef756ba6fcbd4188cc (patch)
treedab9bb0f918903666d908dde1bc1d53561b23a04 /openbsc/src/osmo-bsc_nat
parent91b9a45be42202738d3435425f97887d320f88a7 (diff)
ussd: Keep track of used TIs for USSD and forward messages
Keep track of the used transaction identifier and always forward messages to the USSD provider. E.g. this can be used to have a dialogue going. Right now it is still possible that the MSC will close down the connection.
Diffstat (limited to 'openbsc/src/osmo-bsc_nat')
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat.c2
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_ussd.c86
2 files changed, 65 insertions, 23 deletions
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c
index c9c9b7bfe..4a6e36d91 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c
@@ -981,6 +981,8 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
msg = bsc_nat_rewrite_setup(bsc->nat, msg, parsed, con->imsi);
talloc_free(parsed);
parsed = NULL;
+ } else if (con->con_local == NAT_CON_END_USSD) {
+ bsc_check_ussd(con, parsed, msg);
}
con_bsc = con->bsc;
diff --git a/openbsc/src/osmo-bsc_nat/bsc_ussd.c b/openbsc/src/osmo-bsc_nat/bsc_ussd.c
index 8c8963e47..0392e9b10 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_ussd.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_ussd.c
@@ -252,6 +252,30 @@ int bsc_ussd_init(struct bsc_nat *nat)
ntohl(addr.s_addr), 5001, 0, ussd_listen_cb, nat);
}
+static int forward_ussd_simple(struct sccp_connections *con, struct msgb *input)
+{
+ struct msgb *copy;
+ struct bsc_nat_ussd_con *ussd;
+
+ if (!con->bsc->nat->ussd_con)
+ return -1;
+
+ copy = msgb_alloc_headroom(4096, 128, "forward bts");
+ if (!copy) {
+ LOGP(DNAT, LOGL_ERROR, "Allocation failed, not forwarding.\n");
+ return -1;
+ }
+
+ /* copy the data into the copy */
+ copy->l2h = msgb_put(copy, msgb_l2len(input));
+ memcpy(copy->l2h, input->l2h, msgb_l2len(input));
+
+ /* send it out */
+ ussd = con->bsc->nat->ussd_con;
+ bsc_do_write(&ussd->queue, copy, IPAC_PROTO_SCCP);
+ return 0;
+}
+
static int forward_ussd(struct sccp_connections *con, const struct ussd_request *req,
struct msgb *input)
{
@@ -302,6 +326,7 @@ int bsc_check_ussd(struct sccp_connections *con, struct bsc_nat_parsed *parsed,
uint32_t len;
uint8_t msg_type;
uint8_t proto;
+ uint8_t ti;
struct gsm48_hdr *hdr48;
struct bsc_nat_acc_lst *lst;
struct ussd_request req;
@@ -338,30 +363,45 @@ int bsc_check_ussd(struct sccp_connections *con, struct bsc_nat_parsed *parsed,
proto = hdr48->proto_discr & 0x0f;
msg_type = hdr48->msg_type & 0xbf;
- if (proto != GSM48_PDISC_NC_SS || msg_type != GSM0480_MTYPE_REGISTER)
- return 0;
-
- /* now check if it is a IMSI we care about */
- lst = bsc_nat_acc_lst_find(con->bsc->nat, con->bsc->nat->ussd_lst_name);
- if (!lst)
- return 0;
-
- if (bsc_nat_lst_check_allow(lst, con->imsi) != 0)
+ ti = (hdr48->proto_discr & 0x70) >> 4;
+ if (proto != GSM48_PDISC_NC_SS)
return 0;
- /* now decode the message and see if we really want to handle it */
- memset(&req, 0, sizeof(req));
- if (gsm0480_decode_ussd_request(hdr48, len, &req) != 1)
- return 0;
- if (req.text[0] == 0xff)
- return 0;
-
- if (regexec(&con->bsc->nat->ussd_query_re, req.text, 0, NULL, 0) == REG_NOMATCH)
- return 0;
+ if (msg_type == GSM0480_MTYPE_REGISTER) {
+
+ /* now check if it is a IMSI we care about */
+ lst = bsc_nat_acc_lst_find(con->bsc->nat,
+ con->bsc->nat->ussd_lst_name);
+ if (!lst)
+ return 0;
+
+ if (bsc_nat_lst_check_allow(lst, con->imsi) != 0)
+ return 0;
+
+ /* now decode the message and see if we really want to handle it */
+ memset(&req, 0, sizeof(req));
+ if (gsm0480_decode_ussd_request(hdr48, len, &req) != 1)
+ return 0;
+ if (req.text[0] == 0xff)
+ return 0;
+
+ if (regexec(&con->bsc->nat->ussd_query_re,
+ req.text, 0, NULL, 0) == REG_NOMATCH)
+ return 0;
+
+ /* found a USSD query for our subscriber */
+ LOGP(DNAT, LOGL_NOTICE, "Found USSD query for %s\n", con->imsi);
+ con->ussd_ti[ti] = 1;
+ if (forward_ussd(con, &req, msg) != 0)
+ return 0;
+ return 1;
+ } else if (msg_type == GSM0480_MTYPE_FACILITY && con->ussd_ti[ti]) {
+ LOGP(DNAT, LOGL_NOTICE, "Forwarding message part of TI: %d %s\n",
+ ti, con->imsi);
+ if (forward_ussd_simple(con, msg) != 0)
+ return 0;
+ return 1;
+ }
- /* found a USSD query for our subscriber */
- LOGP(DNAT, LOGL_NOTICE, "Found USSD query for %s\n", con->imsi);
- if (forward_ussd(con, &req, msg) != 0)
- return 0;
- return 1;
+ return 0;
}