aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-02-09 17:35:09 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-02-09 17:35:09 +0100
commit061947807313551d3255de4604c731cb757bb2a8 (patch)
treee042f2bacfb52b770541d0724b8b42735c0c54a5 /openbsc
parentf8f184edab18b033eb8a63282477d737e41c145d (diff)
[nat] Intercept the PAGING message and then forward it to the BSCs with that LAC
* Provide access to the GSM0808 TLV attributes so we can use it in the nat code. * Read the PAGING message, if it is paged by LAC we go through each LAC and then attempt to find the proper BSC connection and then send the message to that BSC.
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/include/openbsc/bssap.h2
-rw-r--r--openbsc/src/Makefile.am2
-rw-r--r--openbsc/src/bssap.c5
-rw-r--r--openbsc/src/nat/bsc_nat.c42
4 files changed, 49 insertions, 2 deletions
diff --git a/openbsc/include/openbsc/bssap.h b/openbsc/include/openbsc/bssap.h
index a46e0a9cd..e873dfad1 100644
--- a/openbsc/include/openbsc/bssap.h
+++ b/openbsc/include/openbsc/bssap.h
@@ -331,4 +331,6 @@ void bts_send_queued(struct bss_sccp_connection_data*);
void bts_free_queued(struct bss_sccp_connection_data*);
void bts_unblock_queue(struct bss_sccp_connection_data*);
+const struct tlv_definition *gsm0808_att_tlvdef();
+
#endif
diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am
index 0e411775e..615884a38 100644
--- a/openbsc/src/Makefile.am
+++ b/openbsc/src/Makefile.am
@@ -43,5 +43,5 @@ isdnsync_SOURCES = isdnsync.c
bsc_mgcp_SOURCES = bsc_mgcp.c msgb.c talloc.c debug.c select.c timer.c telnet_interface.c
bsc_mgcp_LDADD = libvty.a
-bsc_nat_SOURCES = nat/bsc_nat.c nat/bsc_filter.c nat/bsc_nat_vty.c bsc_msc.c
+bsc_nat_SOURCES = nat/bsc_nat.c nat/bsc_filter.c nat/bsc_nat_vty.c bsc_msc.c bssap.c
bsc_nat_LDADD = libvty.a libbsc.a libsccp.a
diff --git a/openbsc/src/bssap.c b/openbsc/src/bssap.c
index 3a283666c..002e7ce21 100644
--- a/openbsc/src/bssap.c
+++ b/openbsc/src/bssap.c
@@ -63,6 +63,11 @@ static const struct tlv_definition bss_att_tlvdef = {
},
};
+const struct tlv_definition *gsm0808_att_tlvdef()
+{
+ return &bss_att_tlvdef;
+}
+
static u_int16_t get_network_code_for_msc(struct gsm_network *net)
{
if (net->core_network_code > 0)
diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c
index 588a9e247..e4db47f0b 100644
--- a/openbsc/src/nat/bsc_nat.c
+++ b/openbsc/src/nat/bsc_nat.c
@@ -270,7 +270,7 @@ static void initialize_msc_if_needed()
static int forward_sccp_to_bts(struct msgb *msg)
{
- struct bsc_connection *bsc;
+ struct bsc_connection *bsc = NULL;
struct bsc_nat_parsed *parsed;
int rc;
@@ -316,6 +316,46 @@ static int forward_sccp_to_bts(struct msgb *msg)
return write(bsc->bsc_fd.fd, msg->data, msg->len);
send_to_all:
+ /*
+ * Filter Paging from the network. We do not want to send a PAGING
+ * Command to every BSC in our network. We will analys the PAGING
+ * message and then send it to the authenticated messages...
+ */
+ if (parsed->ipa_proto == IPAC_PROTO_SCCP && parsed->gsm_type == BSS_MAP_MSG_PAGING) {
+ int data_length;
+ const u_int8_t *data;
+ struct tlv_parsed tp;
+ int i = 0;
+
+ tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l3h + 3, msgb_l3len(msg) - 3, 0, 0);
+ if (!TLVP_PRESENT(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST)) {
+ LOGP(DNAT, LOGL_ERROR, "No CellIdentifier List inside paging msg.\n");
+ goto exit;
+ }
+
+ data_length = TLVP_LEN(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
+ data = TLVP_VAL(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
+ if (data[0] != CELL_IDENT_LAC) {
+ LOGP(DNAT, LOGL_ERROR, "Unhandled cell ident discrminator: %c\n", data[0]);
+ goto exit;
+ }
+
+ /* go through each LAC and forward the message */
+ for (i = 1; i < data_length - 1; i += 2) {
+ unsigned int _lac = ntohs(*(unsigned int *) &data[i]);
+ llist_for_each_entry(bsc, &nat->bsc_connections, list_entry) {
+ if (!bsc->authenticated || _lac != bsc->lac)
+ continue;
+
+ rc = write(bsc->bsc_fd.fd, msg->data, msg->len);
+ if (rc < msg->len)
+ LOGP(DNAT, LOGL_ERROR,
+ "Failed to write message to BTS: %d\n", rc);
+ }
+ }
+
+ goto exit;
+ }
/* currently send this to every BSC connected */
llist_for_each_entry(bsc, &nat->bsc_connections, list_entry) {
if (!bsc->authenticated)