blob: e0206334bc84da919d24139a7ab17717dfc9168b [file] [log] [blame]
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +08001/* BSC Multiplexer/NAT */
2
3/*
4 * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
5 * (C) 2010 by on-waves.com
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +01006 * (C) 2009 by Harald Welte <laforge@gnumonks.org>
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +08007 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 */
24#include <sys/socket.h>
25#include <netinet/in.h>
26#include <arpa/inet.h>
27
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +010028#include <errno.h>
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +010029#include <signal.h>
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +080030#include <stdio.h>
31#include <stdlib.h>
Holger Hans Peter Freyther5aa25ae2010-01-12 21:36:08 +010032#include <time.h>
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +080033#include <unistd.h>
34
35#define _GNU_SOURCE
36#include <getopt.h>
37
38#include <openbsc/debug.h>
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +010039#include <openbsc/msgb.h>
40#include <openbsc/bsc_msc.h>
41#include <openbsc/ipaccess.h>
42#include <openbsc/abis_nm.h>
43#include <openbsc/talloc.h>
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +080044
45static const char *config_file = "openbsc.cfg";
46static char *msc_address = "127.0.0.1";
47static struct in_addr local_addr;
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +010048static struct bsc_fd msc_connection;
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +010049static struct bsc_fd bsc_connection;
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +010050
51/*
52 * below are stubs we need to link
53 */
54int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
55 struct gsm_nm_state *old_state, struct gsm_nm_state *new_state)
56{
57 return -1;
58}
59
60void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
61{}
62
63int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id)
64{
65 return -1;
66}
67
68/*
69 * Below is the handling of messages coming
70 * from the MSC and need to be forwarded to
71 * a real BSC.
72 */
73static void initialize_msc_if_needed()
74{
75 static int init = 0;
76 init = 1;
77
78 /* do we need to send a GSM 08.08 message here? */
79}
80
81static void forward_sccp_to_bts(struct msgb *msg)
82{
83 /* filter, drop, patch the message? */
84}
85
86static int ipaccess_msc_cb(struct bsc_fd *bfd, unsigned int what)
87{
88 int error;
89 struct msgb *msg = ipaccess_read_msg(bfd, &error);
90 struct ipaccess_head *hh;
91
92 if (!msg) {
93 if (error == 0) {
94 fprintf(stderr, "The connection to the MSC was lost, exiting\n");
95 exit(-2);
96 }
97
98 fprintf(stderr, "Failed to parse ip access message: %d\n", error);
99 return -1;
100 }
101
102 DEBUGP(DMSC, "MSG from MSC: %s proto: %d\n", hexdump(msg->data, msg->len), msg->l2h[0]);
103
104 /* handle base message handling */
105 hh = (struct ipaccess_head *) msg->data;
106 ipaccess_rcvmsg_base(msg, bfd);
107
108 /* initialize the networking. This includes sending a GSM08.08 message */
109 if (hh->proto == IPAC_PROTO_IPACCESS && msg->l2h[0] == IPAC_MSGT_ID_ACK)
110 initialize_msc_if_needed();
111 else if (hh->proto == IPAC_PROTO_SCCP)
112 forward_sccp_to_bts(msg);
113
114 return 0;
115}
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800116
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +0100117/*
118 * Below is the handling of messages coming
119 * from the BSC and need to be forwarded to
120 * a real BSC.
121 */
122static int ipaccess_listen_bsc_cb(struct bsc_fd *bfd, unsigned int what)
123{
124 int ret;
125 struct sockaddr_in sa;
126 socklen_t sa_len = sizeof(sa);
127
128 if (!(what & BSC_FD_READ))
129 return 0;
130
131 ret = accept(bfd->fd, (struct sockaddr *) &sa, &sa_len);
132 if (ret < 0) {
133 perror("accept");
134 return ret;
135 }
136
137 /* todo... do something with the connection */
Holger Hans Peter Freytherda86c0a2010-01-12 21:35:32 +0100138 /* todo... use GNUtls to see if we want to trust this as a BTS */
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +0100139
140 return 0;
141}
142
143static int listen_for_bsc(struct bsc_fd *bfd, struct in_addr *in_addr, int port)
144{
145 struct sockaddr_in addr;
146 int ret, on = 1;
147
148 bfd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
149 bfd->cb = ipaccess_listen_bsc_cb;
150 bfd->when = BSC_FD_READ;
151
152 memset(&addr, 0, sizeof(addr));
153 addr.sin_family = AF_INET;
154 addr.sin_port = htons(port);
155 addr.sin_addr.s_addr = in_addr->s_addr;
156
157 setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
158
159 ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
160 if (ret < 0) {
161 fprintf(stderr, "Could not bind the BSC socket %s\n",
162 strerror(errno));
163 return -EIO;
164 }
165
166 ret = listen(bfd->fd, 1);
167 if (ret < 0) {
168 perror("listen");
169 return ret;
170 }
171
172 ret = bsc_register_fd(bfd);
173 if (ret < 0) {
174 perror("register_listen_fd");
175 return ret;
176 }
177 return 0;
178}
179
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800180static void print_usage()
181{
182 printf("Usage: bsc_nat\n");
183}
184
185static void print_help()
186{
187 printf(" Some useful help...\n");
188 printf(" -h --help this text\n");
189 printf(" -d option --debug=DRLL:DCC:DMM:DRR:DRSL:DNM enable debugging\n");
190 printf(" -s --disable-color\n");
191 printf(" -c --config-file filename The config file to use.\n");
192 printf(" -m --msc=IP. The address of the MSC.\n");
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +0100193 printf(" -l --local=IP. The local address of this BSC.\n");
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800194}
195
196static void handle_options(int argc, char** argv)
197{
198 while (1) {
199 int option_index = 0, c;
200 static struct option long_options[] = {
201 {"help", 0, 0, 'h'},
202 {"debug", 1, 0, 'd'},
203 {"config-file", 1, 0, 'c'},
204 {"disable-color", 0, 0, 's'},
205 {"timestamp", 0, 0, 'T'},
206 {"msc", 1, 0, 'm'},
207 {"local", 1, 0, 'l'},
208 {0, 0, 0, 0}
209 };
210
211 c = getopt_long(argc, argv, "hd:sTPc:m:l:",
212 long_options, &option_index);
213 if (c == -1)
214 break;
215
216 switch (c) {
217 case 'h':
218 print_usage();
219 print_help();
220 exit(0);
221 case 's':
222 debug_use_color(0);
223 break;
224 case 'd':
225 debug_parse_category_mask(optarg);
226 break;
227 case 'c':
228 config_file = strdup(optarg);
229 break;
230 case 'T':
231 debug_timestamp(1);
232 break;
233 case 'm':
234 msc_address = strdup(optarg);
235 break;
236 case 'l':
237 inet_aton(optarg, &local_addr);
238 break;
239 default:
240 /* ignore */
241 break;
242 }
243 }
244}
245
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +0100246static void signal_handler(int signal)
247{
248 fprintf(stdout, "signal %u received\n", signal);
249
250 switch (signal) {
251 case SIGABRT:
252 /* in case of abort, we want to obtain a talloc report
253 * and then return to the caller, who will abort the process */
254 case SIGUSR1:
255 talloc_report_full(tall_bsc_ctx, stderr);
256 break;
257 default:
258 break;
259 }
260}
261
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800262int main(int argc, char** argv)
263{
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +0100264 int rc;
265
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800266 /* parse options */
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +0100267 local_addr.s_addr = INADDR_ANY;
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800268 handle_options(argc, argv);
269
270 /* seed the PRNG */
271 srand(time(NULL));
272
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +0100273 /* connect to the MSC */
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +0100274 msc_connection.cb = ipaccess_msc_cb;
275 rc = connect_to_msc(&msc_connection, msc_address, 5000);
276 if (rc < 0) {
277 fprintf(stderr, "Opening the MSC connection failed.\n");
278 exit(1);
279 }
280
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +0100281 /* wait for the BSC */
282 if (listen_for_bsc(&bsc_connection, &local_addr, 5000) < 0) {
283 fprintf(stderr, "Failed to listen for BSC.\n");
284 exit(1);
285 }
286
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +0100287 signal(SIGINT, &signal_handler);
288 signal(SIGABRT, &signal_handler);
289 signal(SIGUSR1, &signal_handler);
290 signal(SIGPIPE, SIG_IGN);
291
292 while (1) {
293 bsc_select_main(0);
294 }
295
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800296 return 0;
297}