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.
This commit is contained in:
Holger Hans Peter Freyther 2011-04-16 14:06:18 +02:00
parent 91b9a45be4
commit 123bc32834
3 changed files with 65 additions and 20 deletions

View File

@ -80,6 +80,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.

View File

@ -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;

View File

@ -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)
ti = (hdr48->proto_discr & 0x70) >> 4;
if (proto != GSM48_PDISC_NC_SS)
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 (msg_type == GSM0480_MTYPE_REGISTER) {
if (bsc_nat_lst_check_allow(lst, con->imsi) != 0)
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;
/* 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 (bsc_nat_lst_check_allow(lst, con->imsi) != 0)
return 0;
if (regexec(&con->bsc->nat->ussd_query_re, req.text, 0, NULL, 0) == REG_NOMATCH)
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;
/* 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;
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;
}
return 0;
}