blob: d3de5f70b09be34275166e918a92c2699de6560a [file] [log] [blame]
Holger Hans Peter Freyther6a97b8d2010-06-15 18:45:26 +08001/* BSC Multiplexer/NAT */
2
3/*
4 * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
Holger Hans Peter Freytherdf6143a2010-06-15 18:46:56 +08005 * (C) 2010 by On-Waves
Holger Hans Peter Freyther6a97b8d2010-06-15 18:45:26 +08006 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23
24#include <openbsc/bsc_nat.h>
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +080025#include <openbsc/bssap.h>
Holger Hans Peter Freyther6a97b8d2010-06-15 18:45:26 +080026#include <openbsc/ipaccess.h>
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +080027#include <openbsc/debug.h>
Holger Hans Peter Freyther6a97b8d2010-06-15 18:45:26 +080028
Holger Hans Peter Freyther6c45f2e2010-06-15 19:06:18 +080029#include <osmocore/talloc.h>
30
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +080031#include <sccp/sccp.h>
32
33/*
34 * The idea is to have a simple struct describing a IPA packet with
35 * SCCP SSN and the GSM 08.08 payload and decide. We will both have
36 * a white and a blacklist of packets we want to handle.
37 *
38 * TODO: Implement a "NOT" in the filter language.
39 */
40
41#define ALLOW_ANY -1
42
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +010043#define FILTER_TO_BSC 1
44#define FILTER_TO_MSC 2
45#define FILTER_TO_BOTH 3
46
47
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +080048struct bsc_pkt_filter {
49 int ipa_proto;
50 int dest_ssn;
51 int bssap;
52 int gsm;
53 int filter_dir;
54};
55
56static struct bsc_pkt_filter black_list[] = {
57 /* filter reset messages to the MSC */
58 { IPAC_PROTO_SCCP, SCCP_SSN_BSSAP, 0, BSS_MAP_MSG_RESET, FILTER_TO_MSC },
59
60 /* filter reset ack messages to the BSC */
61 { IPAC_PROTO_SCCP, SCCP_SSN_BSSAP, 0, BSS_MAP_MSG_RESET_ACKNOWLEDGE, FILTER_TO_BSC },
62
63 /* filter ip access */
64 { IPAC_PROTO_IPACCESS, ALLOW_ANY, ALLOW_ANY, ALLOW_ANY, FILTER_TO_MSC },
65};
66
67static struct bsc_pkt_filter white_list[] = {
68 /* allow IPAC_PROTO_SCCP messages to both sides */
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +010069 { IPAC_PROTO_SCCP, ALLOW_ANY, ALLOW_ANY, ALLOW_ANY, FILTER_TO_BOTH },
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +080070};
71
72struct bsc_nat_parsed* bsc_nat_parse(struct msgb *msg)
Holger Hans Peter Freyther6a97b8d2010-06-15 18:45:26 +080073{
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +080074 struct sccp_parse_result result;
75 struct bsc_nat_parsed *parsed;
Holger Hans Peter Freyther6a97b8d2010-06-15 18:45:26 +080076 struct ipaccess_head *hh;
77
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +080078 /* quick fail */
79 if (msg->len < 4)
80 return NULL;
81
82 parsed = talloc_zero(msg, struct bsc_nat_parsed);
83 if (!parsed)
84 return NULL;
85
86 /* more init */
87 parsed->ipa_proto = parsed->called_ssn = parsed->calling_ssn = -1;
88 parsed->sccp_type = parsed->bssap = parsed->gsm_type = -1;
89
90 /* start parsing */
Holger Hans Peter Freyther6a97b8d2010-06-15 18:45:26 +080091 hh = (struct ipaccess_head *) msg->data;
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +080092 parsed->ipa_proto = hh->proto;
93
94 msg->l2h = &hh->data[0];
95
96 /* analyze sccp down here */
97 if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
98 memset(&result, 0, sizeof(result));
99 if (sccp_parse_header(msg, &result) != 0) {
100 talloc_free(parsed);
101 return 0;
102 }
103
104 if (msg->l3h && msgb_l3len(msg) < 3) {
105 LOGP(DNAT, LOGL_ERROR, "Not enough space or GSM payload\n");
106 talloc_free(parsed);
107 return 0;
108 }
109
110 parsed->sccp_type = sccp_determine_msg_type(msg);
111 parsed->src_local_ref = result.source_local_reference;
112 parsed->dest_local_ref = result.destination_local_reference;
113 parsed->called_ssn = result.called.ssn;
114 parsed->calling_ssn = result.calling.ssn;
115
116 /* in case of connection confirm we have no payload */
117 if (msg->l3h) {
118 parsed->bssap = msg->l3h[0];
119 parsed->gsm_type = msg->l3h[2];
120 }
121 }
122
123 return parsed;
124}
125
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100126int bsc_nat_filter_ipa(int dir, struct msgb *msg, struct bsc_nat_parsed *parsed)
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800127{
128 int i;
129
130 /* go through the blacklist now */
131 for (i = 0; i < ARRAY_SIZE(black_list); ++i) {
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100132 /* ignore the rule? */
133 if (black_list[i].filter_dir != FILTER_TO_BOTH
134 && black_list[i].filter_dir != dir)
135 continue;
136
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800137 /* the proto is not blacklisted */
138 if (black_list[i].ipa_proto != ALLOW_ANY
139 && black_list[i].ipa_proto != parsed->ipa_proto)
140 continue;
141
142 if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
143 /* the SSN is not blacklisted */
144 if (black_list[i].dest_ssn != ALLOW_ANY
145 && black_list[i].dest_ssn != parsed->called_ssn)
146 continue;
147
148 /* bssap */
149 if (black_list[i].bssap != ALLOW_ANY
150 && black_list[i].bssap != parsed->bssap)
151 continue;
152
153 /* gsm */
154 if (black_list[i].gsm != ALLOW_ANY
155 && black_list[i].gsm != parsed->gsm_type)
156 continue;
157
158 /* blacklisted */
159 LOGP(DNAT, LOGL_NOTICE, "Blacklisted with rule %d\n", i);
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100160 return 1;
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800161 } else {
162 /* blacklisted, we have no content sniffing yet */
163 LOGP(DNAT, LOGL_NOTICE, "Blacklisted with rule %d\n", i);
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100164 return 1;
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800165 }
166 }
167
168 /* go through the whitelust now */
169 for (i = 0; i < ARRAY_SIZE(white_list); ++i) {
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100170 /* ignore the rule? */
171 if (white_list[i].filter_dir != FILTER_TO_BOTH
172 && white_list[i].filter_dir != dir)
173 continue;
174
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800175 /* the proto is not whitelisted */
176 if (white_list[i].ipa_proto != ALLOW_ANY
177 && white_list[i].ipa_proto != parsed->ipa_proto)
178 continue;
179
180 if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
181 /* the SSN is not whitelisted */
182 if (white_list[i].dest_ssn != ALLOW_ANY
183 && white_list[i].dest_ssn != parsed->called_ssn)
184 continue;
185
186 /* bssap */
187 if (white_list[i].bssap != ALLOW_ANY
188 && white_list[i].bssap != parsed->bssap)
189 continue;
190
191 /* gsm */
192 if (white_list[i].gsm != ALLOW_ANY
193 && white_list[i].gsm != parsed->gsm_type)
194 continue;
195
196 /* whitelisted */
197 LOGP(DNAT, LOGL_NOTICE, "Whitelisted with rule %d\n", i);
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100198 return 0;
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800199 } else {
200 /* whitelisted */
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100201 return 0;
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800202 }
203 }
204
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100205 return 1;
Holger Hans Peter Freyther6a97b8d2010-06-15 18:45:26 +0800206}