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 - * (C) 2010-2011 by On-Waves + * (C) 2010-2012 by Holger Hans Peter Freyther + * (C) 2010-2012 by On-Waves * (C) 2009 by Harald Welte * 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 - * (C) 2010-2011 by On-Waves + * (C) 2010-2012 by Holger Hans Peter Freyther + * (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 - * (C) 2010 by On-Waves + * (C) 2010-2012 by Holger Hans Peter Freyther + * (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); } }