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.
This commit is contained in:
parent
adc2e87372
commit
bdf764a025
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue