2010-06-15 10:45:26 +00:00
|
|
|
/* BSC Multiplexer/NAT */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
|
2010-06-15 10:46:56 +00:00
|
|
|
* (C) 2010 by On-Waves
|
2010-06-15 10:45:26 +00:00
|
|
|
* All Rights Reserved
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
2011-01-01 14:25:50 +00:00
|
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
2010-06-15 10:45:26 +00:00
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2011-01-01 14:25:50 +00:00
|
|
|
* GNU Affero General Public License for more details.
|
2010-06-15 10:45:26 +00:00
|
|
|
*
|
2011-01-01 14:25:50 +00:00
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2010-06-15 10:45:26 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <openbsc/bsc_nat.h>
|
2010-07-30 21:17:17 +00:00
|
|
|
#include <openbsc/bsc_nat_sccp.h>
|
2010-06-15 10:45:26 +00:00
|
|
|
#include <openbsc/ipaccess.h>
|
2010-06-15 10:45:38 +00:00
|
|
|
#include <openbsc/debug.h>
|
2010-06-15 10:45:26 +00:00
|
|
|
|
2011-03-22 15:47:59 +00:00
|
|
|
#include <osmocom/core/talloc.h>
|
2011-03-23 17:26:56 +00:00
|
|
|
#include <osmocom/gsm/protocol/gsm_08_08.h>
|
2010-06-15 11:06:18 +00:00
|
|
|
|
2010-08-03 13:11:51 +00:00
|
|
|
#include <osmocom/sccp/sccp.h>
|
2010-06-15 10:45:38 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The idea is to have a simple struct describing a IPA packet with
|
|
|
|
* SCCP SSN and the GSM 08.08 payload and decide. We will both have
|
|
|
|
* a white and a blacklist of packets we want to handle.
|
|
|
|
*
|
|
|
|
* TODO: Implement a "NOT" in the filter language.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define ALLOW_ANY -1
|
|
|
|
|
2010-01-30 10:53:30 +00:00
|
|
|
#define FILTER_TO_BSC 1
|
|
|
|
#define FILTER_TO_MSC 2
|
|
|
|
#define FILTER_TO_BOTH 3
|
|
|
|
|
|
|
|
|
2010-06-15 10:45:38 +00:00
|
|
|
struct bsc_pkt_filter {
|
|
|
|
int ipa_proto;
|
|
|
|
int dest_ssn;
|
|
|
|
int bssap;
|
|
|
|
int gsm;
|
|
|
|
int filter_dir;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct bsc_pkt_filter black_list[] = {
|
|
|
|
/* filter reset messages to the MSC */
|
|
|
|
{ IPAC_PROTO_SCCP, SCCP_SSN_BSSAP, 0, BSS_MAP_MSG_RESET, FILTER_TO_MSC },
|
|
|
|
|
|
|
|
/* filter reset ack messages to the BSC */
|
|
|
|
{ IPAC_PROTO_SCCP, SCCP_SSN_BSSAP, 0, BSS_MAP_MSG_RESET_ACKNOWLEDGE, FILTER_TO_BSC },
|
|
|
|
|
|
|
|
/* filter ip access */
|
|
|
|
{ IPAC_PROTO_IPACCESS, ALLOW_ANY, ALLOW_ANY, ALLOW_ANY, FILTER_TO_MSC },
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct bsc_pkt_filter white_list[] = {
|
|
|
|
/* allow IPAC_PROTO_SCCP messages to both sides */
|
2010-01-30 10:53:30 +00:00
|
|
|
{ IPAC_PROTO_SCCP, ALLOW_ANY, ALLOW_ANY, ALLOW_ANY, FILTER_TO_BOTH },
|
2010-04-01 06:47:12 +00:00
|
|
|
|
|
|
|
/* allow MGCP messages to both sides */
|
2011-01-07 15:54:46 +00:00
|
|
|
{ IPAC_PROTO_MGCP_OLD, ALLOW_ANY, ALLOW_ANY, ALLOW_ANY, FILTER_TO_BOTH },
|
2010-06-15 10:45:38 +00:00
|
|
|
};
|
|
|
|
|
2010-09-17 22:44:24 +00:00
|
|
|
struct bsc_nat_parsed *bsc_nat_parse(struct msgb *msg)
|
2010-06-15 10:45:26 +00:00
|
|
|
{
|
2010-06-15 10:45:38 +00:00
|
|
|
struct sccp_parse_result result;
|
|
|
|
struct bsc_nat_parsed *parsed;
|
2010-06-15 10:45:26 +00:00
|
|
|
struct ipaccess_head *hh;
|
|
|
|
|
2010-06-15 10:45:38 +00:00
|
|
|
/* quick fail */
|
|
|
|
if (msg->len < 4)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
parsed = talloc_zero(msg, struct bsc_nat_parsed);
|
|
|
|
if (!parsed)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* more init */
|
|
|
|
parsed->ipa_proto = parsed->called_ssn = parsed->calling_ssn = -1;
|
|
|
|
parsed->sccp_type = parsed->bssap = parsed->gsm_type = -1;
|
|
|
|
|
|
|
|
/* start parsing */
|
2010-06-15 10:45:26 +00:00
|
|
|
hh = (struct ipaccess_head *) msg->data;
|
2010-06-15 10:45:38 +00:00
|
|
|
parsed->ipa_proto = hh->proto;
|
|
|
|
|
|
|
|
msg->l2h = &hh->data[0];
|
|
|
|
|
2010-03-29 12:58:43 +00:00
|
|
|
/* do a size check on the input */
|
|
|
|
if (ntohs(hh->len) != msgb_l2len(msg)) {
|
src: port openBSC over libosmo-abis
This is a big patch that ports openBSC over libosmo-abis.
Sorry, the changes that are included here are all dependent
of libosmo-abis, splitting them into smaller pieces would
leave the repository in some intermediate state, which is
not desired.
The main changes are:
- The directory libabis/ has been removed as it now lives in
libosmo-abis.
- new configuration file format for nanoBTS and HSL femto, we
need to define the virtual e1_line and attach it to the OML
link.
- all the existing BTS drivers (nanoBTS, hsl femto, Nokia site,
BS11 and rbs2000) now use the new libosmo-abis framework.
- use r232 input driver available in libosmo-abis for bs11_config.
- use ipa_msg_recv instead of old ipaccess_read_msg function.
- delete definition of gsm_e1_subslot and input_signal_data.
These structures now lives in libosmo-abis.
Most of this patch are deletions of libabis/ which has been
moved to libosmo-abis.
This patch also modifies openBSC to use all the new definitions
available in libosmocore and libosmo-abis. In order to do that,
we have replaced the following:
- DINP, DMI, DMIB and DMUX by their respective DL* correspondences.
- SS_GLOBAL by SS_L_GLOBAL
- SS_INPUT by SS_L_INPUT
- S_GLOBAL_SHUTDOWN by S_L_GLOBAL_SHUTDOWN
- SS_INPUT by SS_L_INPUT
- S_INP_* by S_L_INP_* sub-signals
- E1INP_NODE by L_E1INP_NODE vty node
This patch has been tested with:
- one nanoBTS
- the HSL femto with the examples available under libosmo-abis
- BS11 with both dahdi and misdn drivers.
2011-08-17 20:44:07 +00:00
|
|
|
LOGP(DLINP, LOGL_ERROR, "Wrong input length?\n");
|
2010-03-29 12:58:43 +00:00
|
|
|
talloc_free(parsed);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-06-15 10:45:38 +00:00
|
|
|
/* analyze sccp down here */
|
|
|
|
if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
|
|
|
|
memset(&result, 0, sizeof(result));
|
|
|
|
if (sccp_parse_header(msg, &result) != 0) {
|
|
|
|
talloc_free(parsed);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg->l3h && msgb_l3len(msg) < 3) {
|
|
|
|
LOGP(DNAT, LOGL_ERROR, "Not enough space or GSM payload\n");
|
|
|
|
talloc_free(parsed);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
parsed->sccp_type = sccp_determine_msg_type(msg);
|
|
|
|
parsed->src_local_ref = result.source_local_reference;
|
|
|
|
parsed->dest_local_ref = result.destination_local_reference;
|
|
|
|
parsed->called_ssn = result.called.ssn;
|
|
|
|
parsed->calling_ssn = result.calling.ssn;
|
|
|
|
|
|
|
|
/* in case of connection confirm we have no payload */
|
|
|
|
if (msg->l3h) {
|
|
|
|
parsed->bssap = msg->l3h[0];
|
|
|
|
parsed->gsm_type = msg->l3h[2];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return parsed;
|
|
|
|
}
|
|
|
|
|
2010-01-30 10:53:30 +00:00
|
|
|
int bsc_nat_filter_ipa(int dir, struct msgb *msg, struct bsc_nat_parsed *parsed)
|
2010-06-15 10:45:38 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* go through the blacklist now */
|
|
|
|
for (i = 0; i < ARRAY_SIZE(black_list); ++i) {
|
2010-01-30 10:53:30 +00:00
|
|
|
/* ignore the rule? */
|
|
|
|
if (black_list[i].filter_dir != FILTER_TO_BOTH
|
|
|
|
&& black_list[i].filter_dir != dir)
|
|
|
|
continue;
|
|
|
|
|
2010-06-15 10:45:38 +00:00
|
|
|
/* the proto is not blacklisted */
|
|
|
|
if (black_list[i].ipa_proto != ALLOW_ANY
|
|
|
|
&& black_list[i].ipa_proto != parsed->ipa_proto)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
|
|
|
|
/* the SSN is not blacklisted */
|
|
|
|
if (black_list[i].dest_ssn != ALLOW_ANY
|
|
|
|
&& black_list[i].dest_ssn != parsed->called_ssn)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* bssap */
|
|
|
|
if (black_list[i].bssap != ALLOW_ANY
|
|
|
|
&& black_list[i].bssap != parsed->bssap)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* gsm */
|
|
|
|
if (black_list[i].gsm != ALLOW_ANY
|
|
|
|
&& black_list[i].gsm != parsed->gsm_type)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* blacklisted */
|
2010-03-29 12:59:59 +00:00
|
|
|
LOGP(DNAT, LOGL_INFO, "Blacklisted with rule %d\n", i);
|
2010-01-30 10:53:30 +00:00
|
|
|
return 1;
|
2010-06-15 10:45:38 +00:00
|
|
|
} else {
|
|
|
|
/* blacklisted, we have no content sniffing yet */
|
2010-03-29 12:59:59 +00:00
|
|
|
LOGP(DNAT, LOGL_INFO, "Blacklisted with rule %d\n", i);
|
2010-01-30 10:53:30 +00:00
|
|
|
return 1;
|
2010-06-15 10:45:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* go through the whitelust now */
|
|
|
|
for (i = 0; i < ARRAY_SIZE(white_list); ++i) {
|
2010-01-30 10:53:30 +00:00
|
|
|
/* ignore the rule? */
|
|
|
|
if (white_list[i].filter_dir != FILTER_TO_BOTH
|
|
|
|
&& white_list[i].filter_dir != dir)
|
|
|
|
continue;
|
|
|
|
|
2010-06-15 10:45:38 +00:00
|
|
|
/* the proto is not whitelisted */
|
|
|
|
if (white_list[i].ipa_proto != ALLOW_ANY
|
|
|
|
&& white_list[i].ipa_proto != parsed->ipa_proto)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
|
|
|
|
/* the SSN is not whitelisted */
|
|
|
|
if (white_list[i].dest_ssn != ALLOW_ANY
|
|
|
|
&& white_list[i].dest_ssn != parsed->called_ssn)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* bssap */
|
|
|
|
if (white_list[i].bssap != ALLOW_ANY
|
|
|
|
&& white_list[i].bssap != parsed->bssap)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* gsm */
|
|
|
|
if (white_list[i].gsm != ALLOW_ANY
|
|
|
|
&& white_list[i].gsm != parsed->gsm_type)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* whitelisted */
|
2010-03-29 12:59:59 +00:00
|
|
|
LOGP(DNAT, LOGL_INFO, "Whitelisted with rule %d\n", i);
|
2010-01-30 10:53:30 +00:00
|
|
|
return 0;
|
2010-06-15 10:45:38 +00:00
|
|
|
} else {
|
|
|
|
/* whitelisted */
|
2010-01-30 10:53:30 +00:00
|
|
|
return 0;
|
2010-06-15 10:45:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-30 10:53:30 +00:00
|
|
|
return 1;
|
2010-06-15 10:45:26 +00:00
|
|
|
}
|