aboutsummaryrefslogtreecommitdiffstats
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-16 15:22:26 +0200
commit6ae9a9322b526c7ca85bb2cf4133908c885540fa (patch)
treef92c8bff5f907f2cd87f3cb6ecbef9f54ae43c16
parentffa58ba5441b2d64e873f825c0769a0895e415e3 (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.
-rw-r--r--openbsc/include/openbsc/bsc_nat_sccp.h3
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat.c2
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_ussd.c86
3 files changed, 68 insertions, 23 deletions
diff --git a/openbsc/include/openbsc/bsc_nat_sccp.h b/openbsc/include/openbsc/bsc_nat_sccp.h
index 4ae640e7f..293ec96f6 100644
--- a/openbsc/include/openbsc/bsc_nat_sccp.h
+++ b/openbsc/include/openbsc/bsc_nat_sccp.h
@@ -81,6 +81,9 @@ struct sccp_connections {
int imsi_checked;
char *imsi;
+ /* remember which Transactions we run over the bypass */
+ char ussd_ti[8];
+
/*
* audio handling. Remember if we have ever send a CRCX,
* remember the endpoint used by the MSC and BSC.
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c
index d38256587..c7d75e571 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c
@@ -952,6 +952,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 == 2) {
+ 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 48ecad57f..8f0d5721d 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_ussd.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_ussd.c
@@ -260,6 +260,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)
{
@@ -310,6 +334,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;
@@ -346,30 +371,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;
}