blob: e3e5c349b62ac4e32bb72d80f469d75d15d79c1f [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 */
137
138 return 0;
139}
140
141static int listen_for_bsc(struct bsc_fd *bfd, struct in_addr *in_addr, int port)
142{
143 struct sockaddr_in addr;
144 int ret, on = 1;
145
146 bfd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
147 bfd->cb = ipaccess_listen_bsc_cb;
148 bfd->when = BSC_FD_READ;
149
150 memset(&addr, 0, sizeof(addr));
151 addr.sin_family = AF_INET;
152 addr.sin_port = htons(port);
153 addr.sin_addr.s_addr = in_addr->s_addr;
154
155 setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
156
157 ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
158 if (ret < 0) {
159 fprintf(stderr, "Could not bind the BSC socket %s\n",
160 strerror(errno));
161 return -EIO;
162 }
163
164 ret = listen(bfd->fd, 1);
165 if (ret < 0) {
166 perror("listen");
167 return ret;
168 }
169
170 ret = bsc_register_fd(bfd);
171 if (ret < 0) {
172 perror("register_listen_fd");
173 return ret;
174 }
175 return 0;
176}
177
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800178static void print_usage()
179{
180 printf("Usage: bsc_nat\n");
181}
182
183static void print_help()
184{
185 printf(" Some useful help...\n");
186 printf(" -h --help this text\n");
187 printf(" -d option --debug=DRLL:DCC:DMM:DRR:DRSL:DNM enable debugging\n");
188 printf(" -s --disable-color\n");
189 printf(" -c --config-file filename The config file to use.\n");
190 printf(" -m --msc=IP. The address of the MSC.\n");
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +0100191 printf(" -l --local=IP. The local address of this BSC.\n");
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800192}
193
194static void handle_options(int argc, char** argv)
195{
196 while (1) {
197 int option_index = 0, c;
198 static struct option long_options[] = {
199 {"help", 0, 0, 'h'},
200 {"debug", 1, 0, 'd'},
201 {"config-file", 1, 0, 'c'},
202 {"disable-color", 0, 0, 's'},
203 {"timestamp", 0, 0, 'T'},
204 {"msc", 1, 0, 'm'},
205 {"local", 1, 0, 'l'},
206 {0, 0, 0, 0}
207 };
208
209 c = getopt_long(argc, argv, "hd:sTPc:m:l:",
210 long_options, &option_index);
211 if (c == -1)
212 break;
213
214 switch (c) {
215 case 'h':
216 print_usage();
217 print_help();
218 exit(0);
219 case 's':
220 debug_use_color(0);
221 break;
222 case 'd':
223 debug_parse_category_mask(optarg);
224 break;
225 case 'c':
226 config_file = strdup(optarg);
227 break;
228 case 'T':
229 debug_timestamp(1);
230 break;
231 case 'm':
232 msc_address = strdup(optarg);
233 break;
234 case 'l':
235 inet_aton(optarg, &local_addr);
236 break;
237 default:
238 /* ignore */
239 break;
240 }
241 }
242}
243
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +0100244static void signal_handler(int signal)
245{
246 fprintf(stdout, "signal %u received\n", signal);
247
248 switch (signal) {
249 case SIGABRT:
250 /* in case of abort, we want to obtain a talloc report
251 * and then return to the caller, who will abort the process */
252 case SIGUSR1:
253 talloc_report_full(tall_bsc_ctx, stderr);
254 break;
255 default:
256 break;
257 }
258}
259
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800260int main(int argc, char** argv)
261{
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +0100262 int rc;
263
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800264 /* parse options */
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +0100265 local_addr.s_addr = INADDR_ANY;
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800266 handle_options(argc, argv);
267
268 /* seed the PRNG */
269 srand(time(NULL));
270
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +0100271 /* connect to the MSC */
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +0100272 msc_connection.cb = ipaccess_msc_cb;
273 rc = connect_to_msc(&msc_connection, msc_address, 5000);
274 if (rc < 0) {
275 fprintf(stderr, "Opening the MSC connection failed.\n");
276 exit(1);
277 }
278
Holger Hans Peter Freyther49d80682010-01-12 21:34:54 +0100279 /* wait for the BSC */
280 if (listen_for_bsc(&bsc_connection, &local_addr, 5000) < 0) {
281 fprintf(stderr, "Failed to listen for BSC.\n");
282 exit(1);
283 }
284
Holger Hans Peter Freyther6ace5222010-01-12 21:15:08 +0100285 signal(SIGINT, &signal_handler);
286 signal(SIGABRT, &signal_handler);
287 signal(SIGUSR1, &signal_handler);
288 signal(SIGPIPE, SIG_IGN);
289
290 while (1) {
291 bsc_select_main(0);
292 }
293
Holger Hans Peter Freyther9e2c5f52010-06-15 18:44:42 +0800294 return 0;
295}