blob: 35c4817c192e8c8a4a83ea132df2c1bd1441ccd6 [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>
32#include <unistd.h>
33
34#define _GNU_SOURCE
35#include <getopt.h>
36
37#include <openbsc/debug.h>
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +010038#include <openbsc/msgb.h>
39#include <openbsc/bsc_msc.h>
40#include <openbsc/ipaccess.h>
41#include <openbsc/abis_nm.h>
42#include <openbsc/talloc.h>
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +080043
44static const char *config_file = "openbsc.cfg";
45static char *msc_address = "127.0.0.1";
46static struct in_addr local_addr;
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +010047static struct bsc_fd msc_connection;
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +010048static struct bsc_fd bsc_connection;
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +010049
50/*
51 * below are stubs we need to link
52 */
53int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
54 struct gsm_nm_state *old_state, struct gsm_nm_state *new_state)
55{
56 return -1;
57}
58
59void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
60{}
61
62int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id)
63{
64 return -1;
65}
66
67/*
68 * Below is the handling of messages coming
69 * from the MSC and need to be forwarded to
70 * a real BSC.
71 */
72static void initialize_msc_if_needed()
73{
74 static int init = 0;
75 init = 1;
76
77 /* do we need to send a GSM 08.08 message here? */
78}
79
80static void forward_sccp_to_bts(struct msgb *msg)
81{
82 /* filter, drop, patch the message? */
83}
84
85static int ipaccess_msc_cb(struct bsc_fd *bfd, unsigned int what)
86{
87 int error;
88 struct msgb *msg = ipaccess_read_msg(bfd, &error);
89 struct ipaccess_head *hh;
90
91 if (!msg) {
92 if (error == 0) {
93 fprintf(stderr, "The connection to the MSC was lost, exiting\n");
94 exit(-2);
95 }
96
97 fprintf(stderr, "Failed to parse ip access message: %d\n", error);
98 return -1;
99 }
100
101 DEBUGP(DMSC, "MSG from MSC: %s proto: %d\n", hexdump(msg->data, msg->len), msg->l2h[0]);
102
103 /* handle base message handling */
104 hh = (struct ipaccess_head *) msg->data;
105 ipaccess_rcvmsg_base(msg, bfd);
106
107 /* initialize the networking. This includes sending a GSM08.08 message */
108 if (hh->proto == IPAC_PROTO_IPACCESS && msg->l2h[0] == IPAC_MSGT_ID_ACK)
109 initialize_msc_if_needed();
110 else if (hh->proto == IPAC_PROTO_SCCP)
111 forward_sccp_to_bts(msg);
112
113 return 0;
114}
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800115
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +0100116/*
117 * Below is the handling of messages coming
118 * from the BSC and need to be forwarded to
119 * a real BSC.
120 */
121static int ipaccess_listen_bsc_cb(struct bsc_fd *bfd, unsigned int what)
122{
123 int ret;
124 struct sockaddr_in sa;
125 socklen_t sa_len = sizeof(sa);
126
127 if (!(what & BSC_FD_READ))
128 return 0;
129
130 ret = accept(bfd->fd, (struct sockaddr *) &sa, &sa_len);
131 if (ret < 0) {
132 perror("accept");
133 return ret;
134 }
135
136 /* todo... do something with the connection */
Holger Hans Peter Freytherda86c0a2010-01-12 21:35:32 +0100137 /* todo... use GNUtls to see if we want to trust this as a BTS */
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +0100138
139 return 0;
140}
141
142static int listen_for_bsc(struct bsc_fd *bfd, struct in_addr *in_addr, int port)
143{
144 struct sockaddr_in addr;
145 int ret, on = 1;
146
147 bfd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
148 bfd->cb = ipaccess_listen_bsc_cb;
149 bfd->when = BSC_FD_READ;
150
151 memset(&addr, 0, sizeof(addr));
152 addr.sin_family = AF_INET;
153 addr.sin_port = htons(port);
154 addr.sin_addr.s_addr = in_addr->s_addr;
155
156 setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
157
158 ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
159 if (ret < 0) {
160 fprintf(stderr, "Could not bind the BSC socket %s\n",
161 strerror(errno));
162 return -EIO;
163 }
164
165 ret = listen(bfd->fd, 1);
166 if (ret < 0) {
167 perror("listen");
168 return ret;
169 }
170
171 ret = bsc_register_fd(bfd);
172 if (ret < 0) {
173 perror("register_listen_fd");
174 return ret;
175 }
176 return 0;
177}
178
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800179static void print_usage()
180{
181 printf("Usage: bsc_nat\n");
182}
183
184static void print_help()
185{
186 printf(" Some useful help...\n");
187 printf(" -h --help this text\n");
188 printf(" -d option --debug=DRLL:DCC:DMM:DRR:DRSL:DNM enable debugging\n");
189 printf(" -s --disable-color\n");
190 printf(" -c --config-file filename The config file to use.\n");
191 printf(" -m --msc=IP. The address of the MSC.\n");
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +0100192 printf(" -l --local=IP. The local address of this BSC.\n");
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800193}
194
195static void handle_options(int argc, char** argv)
196{
197 while (1) {
198 int option_index = 0, c;
199 static struct option long_options[] = {
200 {"help", 0, 0, 'h'},
201 {"debug", 1, 0, 'd'},
202 {"config-file", 1, 0, 'c'},
203 {"disable-color", 0, 0, 's'},
204 {"timestamp", 0, 0, 'T'},
205 {"msc", 1, 0, 'm'},
206 {"local", 1, 0, 'l'},
207 {0, 0, 0, 0}
208 };
209
210 c = getopt_long(argc, argv, "hd:sTPc:m:l:",
211 long_options, &option_index);
212 if (c == -1)
213 break;
214
215 switch (c) {
216 case 'h':
217 print_usage();
218 print_help();
219 exit(0);
220 case 's':
221 debug_use_color(0);
222 break;
223 case 'd':
224 debug_parse_category_mask(optarg);
225 break;
226 case 'c':
227 config_file = strdup(optarg);
228 break;
229 case 'T':
230 debug_timestamp(1);
231 break;
232 case 'm':
233 msc_address = strdup(optarg);
234 break;
235 case 'l':
236 inet_aton(optarg, &local_addr);
237 break;
238 default:
239 /* ignore */
240 break;
241 }
242 }
243}
244
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +0100245static void signal_handler(int signal)
246{
247 fprintf(stdout, "signal %u received\n", signal);
248
249 switch (signal) {
250 case SIGABRT:
251 /* in case of abort, we want to obtain a talloc report
252 * and then return to the caller, who will abort the process */
253 case SIGUSR1:
254 talloc_report_full(tall_bsc_ctx, stderr);
255 break;
256 default:
257 break;
258 }
259}
260
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800261int main(int argc, char** argv)
262{
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +0100263 int rc;
264
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800265 /* parse options */
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +0100266 local_addr.s_addr = INADDR_ANY;
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800267 handle_options(argc, argv);
268
269 /* seed the PRNG */
270 srand(time(NULL));
271
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +0100272 /* connect to the MSC */
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +0100273 msc_connection.cb = ipaccess_msc_cb;
274 rc = connect_to_msc(&msc_connection, msc_address, 5000);
275 if (rc < 0) {
276 fprintf(stderr, "Opening the MSC connection failed.\n");
277 exit(1);
278 }
279
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +0100280 /* wait for the BSC */
281 if (listen_for_bsc(&bsc_connection, &local_addr, 5000) < 0) {
282 fprintf(stderr, "Failed to listen for BSC.\n");
283 exit(1);
284 }
285
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +0100286 signal(SIGINT, &signal_handler);
287 signal(SIGABRT, &signal_handler);
288 signal(SIGUSR1, &signal_handler);
289 signal(SIGPIPE, SIG_IGN);
290
291 while (1) {
292 bsc_select_main(0);
293 }
294
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800295 return 0;
296}