blob: 099b07a5cd46d56131fd1b0641c13256a603bffc [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
Holger Hans Peter Freytherea8cbd52010-03-29 14:58:43 +020096 /* do a size check on the input */
97 if (ntohs(hh->len) != msgb_l2len(msg)) {
98 LOGP(DINP, LOGL_ERROR, "Wrong input length?\n");
99 talloc_free(parsed);
100 return NULL;
101 }
102
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800103 /* analyze sccp down here */
104 if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
105 memset(&result, 0, sizeof(result));
106 if (sccp_parse_header(msg, &result) != 0) {
107 talloc_free(parsed);
108 return 0;
109 }
110
111 if (msg->l3h && msgb_l3len(msg) < 3) {
112 LOGP(DNAT, LOGL_ERROR, "Not enough space or GSM payload\n");
113 talloc_free(parsed);
114 return 0;
115 }
116
117 parsed->sccp_type = sccp_determine_msg_type(msg);
118 parsed->src_local_ref = result.source_local_reference;
119 parsed->dest_local_ref = result.destination_local_reference;
120 parsed->called_ssn = result.called.ssn;
121 parsed->calling_ssn = result.calling.ssn;
122
123 /* in case of connection confirm we have no payload */
124 if (msg->l3h) {
125 parsed->bssap = msg->l3h[0];
126 parsed->gsm_type = msg->l3h[2];
127 }
128 }
129
130 return parsed;
131}
132
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100133int bsc_nat_filter_ipa(int dir, struct msgb *msg, struct bsc_nat_parsed *parsed)
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800134{
135 int i;
136
137 /* go through the blacklist now */
138 for (i = 0; i < ARRAY_SIZE(black_list); ++i) {
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100139 /* ignore the rule? */
140 if (black_list[i].filter_dir != FILTER_TO_BOTH
141 && black_list[i].filter_dir != dir)
142 continue;
143
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800144 /* the proto is not blacklisted */
145 if (black_list[i].ipa_proto != ALLOW_ANY
146 && black_list[i].ipa_proto != parsed->ipa_proto)
147 continue;
148
149 if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
150 /* the SSN is not blacklisted */
151 if (black_list[i].dest_ssn != ALLOW_ANY
152 && black_list[i].dest_ssn != parsed->called_ssn)
153 continue;
154
155 /* bssap */
156 if (black_list[i].bssap != ALLOW_ANY
157 && black_list[i].bssap != parsed->bssap)
158 continue;
159
160 /* gsm */
161 if (black_list[i].gsm != ALLOW_ANY
162 && black_list[i].gsm != parsed->gsm_type)
163 continue;
164
165 /* blacklisted */
166 LOGP(DNAT, LOGL_NOTICE, "Blacklisted with rule %d\n", i);
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100167 return 1;
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800168 } else {
169 /* blacklisted, we have no content sniffing yet */
170 LOGP(DNAT, LOGL_NOTICE, "Blacklisted with rule %d\n", i);
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100171 return 1;
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800172 }
173 }
174
175 /* go through the whitelust now */
176 for (i = 0; i < ARRAY_SIZE(white_list); ++i) {
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100177 /* ignore the rule? */
178 if (white_list[i].filter_dir != FILTER_TO_BOTH
179 && white_list[i].filter_dir != dir)
180 continue;
181
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800182 /* the proto is not whitelisted */
183 if (white_list[i].ipa_proto != ALLOW_ANY
184 && white_list[i].ipa_proto != parsed->ipa_proto)
185 continue;
186
187 if (parsed->ipa_proto == IPAC_PROTO_SCCP) {
188 /* the SSN is not whitelisted */
189 if (white_list[i].dest_ssn != ALLOW_ANY
190 && white_list[i].dest_ssn != parsed->called_ssn)
191 continue;
192
193 /* bssap */
194 if (white_list[i].bssap != ALLOW_ANY
195 && white_list[i].bssap != parsed->bssap)
196 continue;
197
198 /* gsm */
199 if (white_list[i].gsm != ALLOW_ANY
200 && white_list[i].gsm != parsed->gsm_type)
201 continue;
202
203 /* whitelisted */
204 LOGP(DNAT, LOGL_NOTICE, "Whitelisted with rule %d\n", i);
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100205 return 0;
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800206 } else {
207 /* whitelisted */
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100208 return 0;
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800209 }
210 }
211
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100212 return 1;
Holger Hans Peter Freyther6a97b8d2010-06-15 18:45:26 +0800213}