aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2012-12-17 14:35:03 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2013-01-07 15:02:34 +0100
commitbdf764a0255ebef0593b5c39a5118278d1a17d50 (patch)
tree2d50cd15795fe5b0bf81078c12efa85d1137b610
parentadc2e8737235fd5f1655ba1a319d3aab76f16d91 (diff)
nat: Allow the filter to select the reject cause
In preparation for another kind of black-list allow the filter code to decide how the connection should be rejected. Introduce a new struct that will carry the reject causes for certain operations.
-rw-r--r--openbsc/include/openbsc/bsc_nat.h11
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat.c30
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat_filter.c16
-rw-r--r--openbsc/tests/bsc-nat/bsc_nat_test.c15
4 files changed, 49 insertions, 23 deletions
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index 7e59c6318..71cd121f4 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -327,6 +327,11 @@ struct bsc_nat_ussd_con {
struct osmo_timer_list auth_timeout;
};
+struct bsc_nat_reject_cause {
+ int lu_reject_cause;
+ int cm_reject_cause;
+};
+
/* create and init the structures */
struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token);
struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num);
@@ -360,9 +365,11 @@ int bsc_nat_find_paging(struct msgb *msg, const uint8_t **,int *len);
* Content filtering.
*/
int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg,
- struct bsc_nat_parsed *, int *con_type, char **imsi);
+ struct bsc_nat_parsed *, int *con_type, char **imsi,
+ struct bsc_nat_reject_cause *cause);
int bsc_nat_filter_dt(struct bsc_connection *bsc, struct msgb *msg,
- struct sccp_connections *con, struct bsc_nat_parsed *parsed);
+ struct sccp_connections *con, struct bsc_nat_parsed *parsed,
+ struct bsc_nat_reject_cause *cause);
/**
* SCCP patching and handling
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c
index 466dc72dc..edf8b1763 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c
@@ -1,8 +1,8 @@
/* BSC Multiplexer/NAT */
/*
- * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2011 by On-Waves
+ * (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2012 by On-Waves
* (C) 2009 by Harald Welte <laforge@gnumonks.org>
* All Rights Reserved
*
@@ -416,7 +416,9 @@ static void bsc_stat_reject(int filter, struct bsc_connection *bsc, int normal)
* 2.) Give up on the BSC side
* 2.1) Depending on the con type reject the service, or just close it
*/
-static void bsc_send_con_release(struct bsc_connection *bsc, struct sccp_connections *con)
+static void bsc_send_con_release(struct bsc_connection *bsc,
+ struct sccp_connections *con,
+ struct bsc_nat_reject_cause *cause)
{
struct msgb *rlsd;
/* 1. release the network */
@@ -434,7 +436,7 @@ static void bsc_send_con_release(struct bsc_connection *bsc, struct sccp_connect
/* 2. release the BSC side */
if (con->con_type == NAT_CON_TYPE_LU) {
struct msgb *payload, *udt;
- payload = gsm48_create_loc_upd_rej(GSM48_REJECT_PLMN_NOT_ALLOWED);
+ payload = gsm48_create_loc_upd_rej(cause->lu_reject_cause);
if (payload) {
gsm0808_prepend_dtap_header(payload, 0);
@@ -465,15 +467,16 @@ static void bsc_send_con_release(struct bsc_connection *bsc, struct sccp_connect
}
static void bsc_send_con_refuse(struct bsc_connection *bsc,
- struct bsc_nat_parsed *parsed, int con_type)
+ struct bsc_nat_parsed *parsed, int con_type,
+ struct bsc_nat_reject_cause *cause)
{
struct msgb *payload;
struct msgb *refuse;
if (con_type == NAT_CON_TYPE_LU)
- payload = gsm48_create_loc_upd_rej(GSM48_REJECT_PLMN_NOT_ALLOWED);
+ payload = gsm48_create_loc_upd_rej(cause->lu_reject_cause);
else if (con_type == NAT_CON_TYPE_CM_SERV_REQ)
- payload = gsm48_create_mm_serv_rej(GSM48_REJECT_PLMN_NOT_ALLOWED);
+ payload = gsm48_create_mm_serv_rej(cause->cm_reject_cause);
else {
LOGP(DNAT, LOGL_ERROR, "Unknown connection type: %d\n", con_type);
payload = NULL;
@@ -980,6 +983,7 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
struct bsc_connection *con_bsc = NULL;
int con_type;
struct bsc_nat_parsed *parsed;
+ struct bsc_nat_reject_cause cause;
/* Parse and filter messages */
parsed = bsc_nat_parse(msg);
@@ -1010,7 +1014,9 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
struct sccp_connections *con;
switch (parsed->sccp_type) {
case SCCP_MSG_TYPE_CR:
- filter = bsc_nat_filter_sccp_cr(bsc, msg, parsed, &con_type, &imsi);
+ memset(&cause, 0, sizeof(cause));
+ filter = bsc_nat_filter_sccp_cr(bsc, msg, parsed,
+ &con_type, &imsi, &cause);
if (filter < 0) {
bsc_stat_reject(filter, bsc, 0);
goto exit3;
@@ -1038,10 +1044,12 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
if (con) {
/* only filter non local connections */
if (!con->con_local) {
- filter = bsc_nat_filter_dt(bsc, msg, con, parsed);
+ memset(&cause, 0, sizeof(cause));
+ filter = bsc_nat_filter_dt(bsc, msg,
+ con, parsed, &cause);
if (filter < 0) {
bsc_stat_reject(filter, bsc, 1);
- bsc_send_con_release(bsc, con);
+ bsc_send_con_release(bsc, con, &cause);
con = NULL;
goto exit2;
}
@@ -1156,7 +1164,7 @@ exit3:
/* send a SCCP Connection Refused */
if (imsi)
talloc_free(imsi);
- bsc_send_con_refuse(bsc, parsed, con_type);
+ bsc_send_con_refuse(bsc, parsed, con_type, &cause);
talloc_free(parsed);
msgb_free(msg);
return -1;
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_filter.c b/openbsc/src/osmo-bsc_nat/bsc_nat_filter.c
index 42cfb9e74..15afb9a4a 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat_filter.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat_filter.c
@@ -2,8 +2,8 @@
* Access filtering
*/
/*
- * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010-2011 by On-Waves
+ * (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2012 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
@@ -223,8 +223,8 @@ static int _dt_check_id_resp(struct bsc_connection *bsc,
/* Filter out CR data... */
int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg,
- struct bsc_nat_parsed *parsed, int *con_type,
- char **imsi)
+ struct bsc_nat_parsed *parsed, int *con_type,
+ char **imsi, struct bsc_nat_reject_cause *cause)
{
struct tlv_parsed tp;
struct gsm48_hdr *hdr48;
@@ -233,6 +233,8 @@ int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg,
uint8_t msg_type, proto;
*con_type = NAT_CON_TYPE_NONE;
+ cause->cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
+ cause->lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
*imsi = NULL;
if (parsed->gsm_type != BSS_MAP_MSG_COMPLETE_LAYER_3) {
@@ -292,12 +294,16 @@ int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg,
}
int bsc_nat_filter_dt(struct bsc_connection *bsc, struct msgb *msg,
- struct sccp_connections *con, struct bsc_nat_parsed *parsed)
+ struct sccp_connections *con, struct bsc_nat_parsed *parsed,
+ struct bsc_nat_reject_cause *cause)
{
uint32_t len;
uint8_t msg_type, proto;
struct gsm48_hdr *hdr48;
+ cause->cm_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
+ cause->lu_reject_cause = GSM48_REJECT_PLMN_NOT_ALLOWED;
+
if (con->imsi_checked)
return 0;
diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c
index f8ba57b8a..59d92bd07 100644
--- a/openbsc/tests/bsc-nat/bsc_nat_test.c
+++ b/openbsc/tests/bsc-nat/bsc_nat_test.c
@@ -1,8 +1,8 @@
/*
* BSC NAT Message filtering
*
- * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2010 by On-Waves
+ * (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2012 by On-Waves
*
* All Rights Reserved
*
@@ -761,6 +761,7 @@ static void test_cr_filter()
struct bsc_nat_parsed *parsed;
struct bsc_nat_acc_lst *nat_lst, *bsc_lst;
struct bsc_nat_acc_lst_entry *nat_entry, *bsc_entry;
+ struct bsc_nat_reject_cause cause;
struct bsc_nat *nat = bsc_nat_alloc();
struct bsc_connection *bsc = bsc_connection_alloc(nat);
@@ -802,7 +803,8 @@ static void test_cr_filter()
abort();
}
- res = bsc_nat_filter_sccp_cr(bsc, msg, parsed, &contype, &imsi);
+ memset(&cause, 0, sizeof(cause));
+ res = bsc_nat_filter_sccp_cr(bsc, msg, parsed, &contype, &imsi, &cause);
if (res != cr_filter[i].result) {
printf("FAIL: Wrong result %d for test %d.\n", res, i);
abort();
@@ -825,6 +827,7 @@ static void test_dt_filter()
int i;
struct msgb *msg = msgb_alloc(4096, "test_dt_filter");
struct bsc_nat_parsed *parsed;
+ struct bsc_nat_reject_cause cause;
struct bsc_nat *nat = bsc_nat_alloc();
struct bsc_connection *bsc = bsc_connection_alloc(nat);
@@ -854,7 +857,8 @@ static void test_dt_filter()
abort();
}
- if (bsc_nat_filter_dt(bsc, msg, con, parsed) != 1) {
+ memset(&cause, 0, sizeof(cause));
+ if (bsc_nat_filter_dt(bsc, msg, con, parsed, &cause) != 1) {
printf("FAIL: Should have passed..\n");
abort();
}
@@ -869,7 +873,8 @@ static void test_dt_filter()
continue;
con->imsi_checked = 0;
- bsc_nat_filter_dt(bsc, msg, con, parsed);
+ memset(&cause, 0, sizeof(cause));
+ bsc_nat_filter_dt(bsc, msg, con, parsed, &cause);
}
}