diff options
author | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2013-08-26 17:07:12 +0200 |
---|---|---|
committer | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2013-09-03 16:15:02 +0200 |
commit | 81a625cbe5d094452bd0150df9d29f3e00a407c8 (patch) | |
tree | 5481e1f5cf243eba3fef786ed787e62a22fc3232 | |
parent | 7e5cdb1da017feee6222a33760ad92fae932c453 (diff) |
nat: Detect a CC Setup and filter it for local call handling
-rw-r--r-- | openbsc/include/openbsc/bsc_nat_sccp.h | 4 | ||||
-rw-r--r-- | openbsc/src/osmo-bsc_nat/bsc_nat_call_control.c | 89 |
2 files changed, 92 insertions, 1 deletions
diff --git a/openbsc/include/openbsc/bsc_nat_sccp.h b/openbsc/include/openbsc/bsc_nat_sccp.h index 0561df1f4..40e04a027 100644 --- a/openbsc/include/openbsc/bsc_nat_sccp.h +++ b/openbsc/include/openbsc/bsc_nat_sccp.h @@ -83,6 +83,10 @@ struct nat_sccp_connection { int imsi_checked; char *imsi; + /* status for local call handling */ + int has_cc_ti; + int cc_ti; + uint16_t lac; uint16_t ci; diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_call_control.c b/openbsc/src/osmo-bsc_nat/bsc_nat_call_control.c index 0328380bb..00b306490 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_call_control.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_call_control.c @@ -25,10 +25,14 @@ #include <openbsc/ipaccess.h> #include <openbsc/vty.h> +#include <osmocom/gsm/tlv.h> +#include <osmocom/gsm/gsm48.h> #include <osmocom/gsm/protocol/gsm_08_08.h> #include <osmocom/core/talloc.h> +#include <string.h> + void bsc_cc_update_msc_ip(struct bsc_nat *nat, const char *ip) { if (ip) { @@ -173,8 +177,91 @@ int bsc_cc_initialize(struct bsc_nat *nat) return 0; } +static int cc_new_connection(struct nat_sccp_connection *con, struct msgb *msg) +{ + return 0; +} + +static int cc_forward(struct nat_sccp_connection *con, struct msgb *msg) +{ + return 0; +} + int bsc_cc_check(struct nat_sccp_connection *con, struct bsc_nat_parsed *parsed, struct msgb *msg) { - return 0; + uint32_t len; + uint8_t msg_type; + uint8_t proto; + uint8_t ti; + struct gsm48_hdr *hdr48; + struct gsm_mncc_number called; + struct tlv_parsed tp; + unsigned payload_len; + + char _dest_nr[35]; + + /* no local number prefix */ + if (!con->bsc->nat->local_prefix) + return 0; + + /* We have not verified the IMSI yet */ + if (!con->authorized) + return 0; + + if (parsed->bssap != BSSAP_MSG_DTAP) + return 0; + + hdr48 = bsc_unpack_dtap(parsed, msg, &len); + if (!hdr48) + return 0; + + proto = hdr48->proto_discr & 0x0f; + msg_type = hdr48->msg_type & 0xbf; + ti = (hdr48->proto_discr & 0x70) >> 4; + + /* ignore everything not call related */ + if (proto != GSM48_PDISC_CC) + return 0; + + /* if we know this connection, return quickly */ + if (con->has_cc_ti && con->cc_ti == ti) { + cc_forward(con, msg); + return 1; + } + + /* right now we identify a CC setup and remember things */ + if (msg_type != GSM48_MT_CC_SETUP) + return 0; + + /* now look into it */ + payload_len = msgb_l3len(msg) - sizeof(*hdr48); + + tlv_parse(&tp, &gsm48_att_tlvdef, hdr48->data, payload_len, 0, 0); + if (!TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) { + LOGP(DMSC, LOGL_ERROR, "Called BCD not present in setup.\n"); + return 0; + } + + memset(&called, 0, sizeof(called)); + gsm48_decode_called(&called, + TLVP_VAL(&tp, GSM48_IE_CALLED_BCD) - 1); + + if (called.plan != 1 && called.plan != 0) + return 0; + + if (called.plan == 1 && called.type == 1) { + _dest_nr[0] = _dest_nr[1] = '0'; + memcpy(_dest_nr + 2, called.number, sizeof(called.number)); + } else + memcpy(_dest_nr, called.number, sizeof(called.number)); + + /* now we can compare the number... */ + if (regexec(&con->bsc->nat->local_prefix_regexp, _dest_nr, 0, NULL, 0) != 0) + return 0; + + con->has_cc_ti = 1; + con->cc_ti = ti; + cc_new_connection(con, msg); + return 1; } |