blob: 6e8752e48027ef18931acd17ff6d9977c295d453 [file] [log] [blame]
Holger Hans Peter Freythera93b83b2011-01-17 15:21:06 +01001/* Relay UDT/all SCCP messages */
2/*
3 * (C) 2010-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
4 * (C) 2010-2011 by On-Waves
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
23#include <mtp_data.h>
24#include <mtp_level3.h>
25#include <mtp_pcap.h>
26#include <thread.h>
27#include <bsc_data.h>
28#include <snmp_mtp.h>
29#include <cellmgr_debug.h>
Holger Hans Peter Freyther9cf11bc2011-01-17 15:53:06 +010030#include <sctp_m2ua.h>
Holger Hans Peter Freythera93b83b2011-01-17 15:21:06 +010031
Holger Hans Peter Freyther02921272011-01-22 23:05:03 +010032#include <osmocom/m2ua/m2ua_msg.h>
33
Holger Hans Peter Freythera93b83b2011-01-17 15:21:06 +010034#include <osmocore/talloc.h>
35
36#include <osmocom/vty/vty.h>
37#include <osmocom/vty/telnet_interface.h>
38
39#include <sys/stat.h>
40#include <sys/types.h>
41
42#include <fcntl.h>
43#include <signal.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <assert.h>
48#include <unistd.h>
49
50#ifndef _GNU_SOURCE
51#define _GNU_SOURCE
52#endif
53#include <getopt.h>
54
55#undef PACKAGE_NAME
56#undef PACKAGE_VERSION
57#undef PACKAGE_BUGREPORT
58#undef PACKAGE_TARNAME
59#undef PACKAGE_STRING
60#include <cellmgr_config.h>
61
62static struct log_target *stderr_target;
63
64static char *config = "osmo_stp.cfg";
65
66struct bsc_data bsc;
67extern void cell_vty_init(void);
68
69/*
70 * methods called from the MTP Level3 part
71 */
72void mtp_link_set_forward_sccp(struct mtp_link_set *link, struct msgb *_msg, int sls)
73{
Holger Hans Peter Freyther9cf11bc2011-01-17 15:53:06 +010074 struct mtp_link_set *target;
75
76 target = bsc.m2ua_set == link ? bsc.link_set : bsc.m2ua_set;
77 mtp_link_set_submit_sccp_data(target, sls, _msg->l2h, msgb_l2len(_msg));
Holger Hans Peter Freythera93b83b2011-01-17 15:21:06 +010078}
79
Holger Hans Peter Freyther1b6901e2011-01-17 16:13:28 +010080void mtp_link_set_forward_isup(struct mtp_link_set *set, struct msgb *msg, int sls)
81{
82 struct mtp_link_set *target;
83
84 target = bsc.m2ua_set == set ? bsc.link_set : bsc.m2ua_set;
85 mtp_link_set_submit_isup_data(target, sls, msg->l3h, msgb_l3len(msg));
86}
87
Holger Hans Peter Freythera93b83b2011-01-17 15:21:06 +010088void mtp_linkset_down(struct mtp_link_set *set)
89{
90 set->available = 0;
91 mtp_link_set_stop(set);
92}
93
94void mtp_linkset_up(struct mtp_link_set *set)
95{
96 set->available = 1;
97 mtp_link_set_reset(set);
98}
99
100static void print_usage()
101{
102 printf("Usage: osmo-stp\n");
103}
104
105static void sigint()
106{
107 static pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER;
108 static int handled = 0;
109
110 /* failed to lock */
111 if (pthread_mutex_trylock(&exit_mutex) != 0)
112 return;
113 if (handled)
114 goto out;
115
116 printf("Terminating.\n");
117 handled = 1;
118 if (bsc.setup)
119 link_shutdown_all(bsc.link_set);
120 exit(0);
121
122out:
123 pthread_mutex_unlock(&exit_mutex);
124}
125
126static void print_help()
127{
128 printf(" Some useful help...\n");
129 printf(" -h --help this text\n");
130 printf(" -c --config=CFG The config file to use.\n");
131 printf(" -p --pcap=FILE. Write MSUs to the PCAP file.\n");
132 printf(" -c --once. Send the SLTM msg only once.\n");
133 printf(" -v --version. Print the version number\n");
134}
135
136static void handle_options(int argc, char **argv)
137{
138 while (1) {
139 int option_index = 0, c;
140 static struct option long_options[] = {
141 {"help", 0, 0, 'h'},
142 {"config", 1, 0, 'c'},
143 {"pcap", 1, 0, 'p'},
144 {"version", 0, 0, 0},
145 {0, 0, 0, 0},
146 };
147
148 c = getopt_long(argc, argv, "hc:p:v",
149 long_options, &option_index);
150 if (c == -1)
151 break;
152
153 switch (c) {
154 case 'h':
155 print_usage();
156 print_help();
157 exit(0);
158 case 'p':
159 if (bsc.pcap_fd >= 0)
160 close(bsc.pcap_fd);
161 bsc.pcap_fd = open(optarg, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP| S_IROTH);
162 if (bsc.pcap_fd < 0) {
163 fprintf(stderr, "Failed to open PCAP file.\n");
164 exit(0);
165 }
166 mtp_pcap_write_header(bsc.pcap_fd);
167 break;
168 case 'c':
169 config = optarg;
170 break;
171 case 'v':
172 printf("This is %s version %s.\n", PACKAGE, VERSION);
173 exit(0);
174 break;
175 default:
176 fprintf(stderr, "Unknown option.\n");
177 break;
178 }
179 }
180}
181
Holger Hans Peter Freyther0452f222011-02-03 13:35:42 +0100182static struct mtp_link_set *find_link_set(struct bsc_data *bsc,
183 int len, const char *buf)
184{
185 if (strncmp(buf, "mtp", len) == 0)
186 return bsc->link_set;
187 else if (strncmp(buf, "m2ua", len) == 0)
188 return bsc->m2ua_set;
189 return NULL;
190}
191
192static int inject_read_cb(struct bsc_fd *fd, unsigned int what)
193{
194 struct msgb *msg;
195 struct m2ua_msg_part *data, *link;
196 struct bsc_data *bsc;
197 struct m2ua_msg *m2ua;
198 struct mtp_link_set *out_set;
199 uint8_t buf[4096];
200
201 bsc = fd->data;
202
203 int rc = read(fd->fd, buf, sizeof(buf));
204 if (rc <= 0) {
205 LOGP(DINP, LOGL_ERROR, "Failed to read from the console.\n");
206 return -1;
207 }
208
Holger Hans Peter Freytheree63d7d2011-02-10 12:39:05 +0100209 if (!bsc->allow_inject) {
210 LOGP(DINP, LOGL_ERROR, "Injecting messages is not allowed.\n");
211 return -1;
212 }
213
Holger Hans Peter Freyther0452f222011-02-03 13:35:42 +0100214 m2ua = m2ua_from_msg(rc, buf);
215 if (!m2ua) {
216 LOGP(DINP, LOGL_ERROR, "Failed to parse M2UA.\n");
217 return -1;
218 }
219
220 if (m2ua->hdr.msg_class == M2UA_CLS_MAUP && m2ua->hdr.msg_type == M2UA_MAUP_DATA) {
221 data = m2ua_msg_find_tag(m2ua, M2UA_TAG_DATA);
222 if (!data) {
223 LOGP(DINP, LOGL_ERROR, "MAUP Data without data.\n");
224 goto exit;
225 }
226
227 if (data->len > 2048) {
228 LOGP(DINP, LOGL_ERROR, "Data is too big for this configuration.\n");
229 goto exit;
230 }
231
232 link = m2ua_msg_find_tag(m2ua, MUA_TAG_IDENT_TEXT);
233 if (!link) {
234 LOGP(DINP, LOGL_ERROR, "Interface Identifier Text is mandantory.\n");
235 goto exit;
236 }
237
238 if (link->len > 255) {
239 LOGP(DINP, LOGL_ERROR, "Spec violation. Ident text should be shorter than 255.\n");
240 goto exit;
241 }
242
243 out_set = find_link_set(bsc, link->len, (const char *) link->dat);
244 if (!out_set) {
245 LOGP(DINP, LOGL_ERROR, "Identified linkset does not exist.\n");
246 goto exit;
247 }
248
249 msg = msgb_alloc(2048, "inject-data");
250 if (!msg) {
251 LOGP(DINP, LOGL_ERROR, "Failed to allocate storage.\n");
252 goto exit;
253 }
254
255 msg->l2h = msgb_put(msg, data->len);
256 memcpy(msg->l2h, data->dat, data->len);
257
258 /* we are diretcly going to the output. no checking of anything */
259 if (mtp_link_set_send(out_set, msg) != 0) {
260 LOGP(DINP, LOGL_ERROR, "Failed to send message.\n");
261 msgb_free(msg);
262 }
263 }
264
265exit:
266 m2ua_msg_free(m2ua);
267 return 0;
268}
269
270static int inject_init(struct bsc_data *bsc)
271{
272 int fd;
273 struct sockaddr_in addr;
274
275 fd = socket(PF_INET, SOCK_DGRAM, 0);
276 if (fd < 0)
277 return -1;
278
279 memset(&addr, 0, sizeof(addr));
280 addr.sin_family = AF_INET;
281 addr.sin_port = htons(5001);
282
283 if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) != 0) {
284 LOGP(DINP, LOGL_ERROR, "Failed to bind to port 5001.\n");
285 close(fd);
286 return -1;
287 }
288
289 bsc->inject_fd.fd = fd;
290 bsc->inject_fd.when = BSC_FD_READ;
291 bsc->inject_fd.cb = inject_read_cb;
292 bsc->inject_fd.data = bsc;
293
294 if (bsc_register_fd(&bsc->inject_fd) != 0) {
295 LOGP(DINP, LOGL_ERROR, "Failed to register.\n");
296 close(fd);
297 return -1;
298 }
299
300 return 0;
301}
302
Holger Hans Peter Freythera93b83b2011-01-17 15:21:06 +0100303int main(int argc, char **argv)
304{
305 int rc;
Holger Hans Peter Freyther9cf11bc2011-01-17 15:53:06 +0100306 struct mtp_link *data;
307 struct mtp_m2ua_link *lnk;
Holger Hans Peter Freythera93b83b2011-01-17 15:21:06 +0100308 INIT_LLIST_HEAD(&bsc.sccp_connections);
309
Holger Hans Peter Freythera310e532011-01-22 16:34:16 +0100310 bsc.app = APP_STP;
Holger Hans Peter Freythera93b83b2011-01-17 15:21:06 +0100311 bsc.dpc = 1;
312 bsc.opc = 0;
313 bsc.sccp_opc = -1;
Holger Hans Peter Freytherd8a73e22011-01-17 22:37:11 +0100314 bsc.isup_opc = -1;
Holger Hans Peter Freythera93b83b2011-01-17 15:21:06 +0100315 bsc.udp_port = 3456;
316 bsc.udp_ip = NULL;
317 bsc.src_port = 1313;
318 bsc.ni_ni = MTP_NI_NATION_NET;
319 bsc.ni_spare = 0;
Holger Hans Peter Freytherc6bfa272011-01-22 17:06:34 +0100320 bsc.udp_nr_links = 1;
Holger Hans Peter Freythera93b83b2011-01-17 15:21:06 +0100321
322 mtp_link_set_init();
323 thread_init();
324
325 log_init(&log_info);
326 stderr_target = log_target_create_stderr();
327 log_add_target(stderr_target);
328
329 /* enable filters */
330 log_set_all_filter(stderr_target, 1);
331 log_set_category_filter(stderr_target, DINP, 1, LOGL_INFO);
332 log_set_category_filter(stderr_target, DSCCP, 1, LOGL_INFO);
333 log_set_category_filter(stderr_target, DMSC, 1, LOGL_INFO);
334 log_set_category_filter(stderr_target, DMGCP, 1, LOGL_INFO);
335 log_set_print_timestamp(stderr_target, 1);
336 log_set_use_color(stderr_target, 0);
337
338 sccp_set_log_area(DSCCP);
Holger Hans Peter Freyther02921272011-01-22 23:05:03 +0100339 m2ua_set_log_area(DM2UA);
Holger Hans Peter Freythera93b83b2011-01-17 15:21:06 +0100340
341 bsc.setup = 0;
342 bsc.msc_address = "127.0.0.1";
343 bsc.pcap_fd = -1;
344 bsc.udp_reset_timeout = 180;
345 bsc.ping_time = 20;
346 bsc.pong_time = 5;
347 bsc.msc_time = 20;
348 bsc.forward_only = 1;
349
350 handle_options(argc, argv);
351
352 signal(SIGPIPE, SIG_IGN);
353 signal(SIGINT, sigint);
354 srand(time(NULL));
355
356 cell_vty_init();
357 if (vty_read_config_file(config, NULL) < 0) {
358 fprintf(stderr, "Failed to read the VTY config.\n");
359 return -1;
360 }
361
362 rc = telnet_init(NULL, NULL, 4242);
363 if (rc < 0)
364 return rc;
365
Holger Hans Peter Freyther0452f222011-02-03 13:35:42 +0100366 if (inject_init(&bsc) != 0) {
367 LOGP(DINP, LOGL_NOTICE, "Failed to initialize inject interface.\n");
368 return -1;
369 }
370
Holger Hans Peter Freythera93b83b2011-01-17 15:21:06 +0100371 if (link_init(&bsc) != 0)
372 return -1;
373
Holger Hans Peter Freyther9cf11bc2011-01-17 15:53:06 +0100374 bsc.m2ua_set = mtp_link_set_alloc();
375 bsc.m2ua_set->dpc = 92;
376 bsc.m2ua_set->opc = 9;
377 bsc.m2ua_set->sccp_opc = 9;
Holger Hans Peter Freytherd8a73e22011-01-17 22:37:11 +0100378 bsc.m2ua_set->isup_opc = 9;
Holger Hans Peter Freyther9cf11bc2011-01-17 15:53:06 +0100379 bsc.m2ua_set->ni = 3;
380 bsc.m2ua_set->bsc = &bsc;
Holger Hans Peter Freytherf6375b42011-01-22 21:01:23 +0100381 bsc.m2ua_set->pcap_fd = bsc.pcap_fd;
Holger Hans Peter Freyther38d936a2011-01-26 12:41:42 +0100382 bsc.m2ua_set->name = talloc_strdup(bsc.m2ua_set, "M2UA");
Holger Hans Peter Freyther9cf11bc2011-01-17 15:53:06 +0100383
Holger Hans Peter Freytherefbd8c22011-01-17 20:21:45 +0100384 /* for both links we want to have all isup messages */
Holger Hans Peter Freytherf603f282011-01-30 00:24:15 +0100385 if (bsc.isup_pass) {
386 LOGP(DINP, LOGL_NOTICE, "Going to pass through all ISUP messages.\n");
387 bsc.m2ua_set->pass_all_isup = 1;
388 bsc.link_set->pass_all_isup = 1;
389 }
Holger Hans Peter Freytherefbd8c22011-01-17 20:21:45 +0100390
Holger Hans Peter Freyther9cf11bc2011-01-17 15:53:06 +0100391 lnk = sctp_m2ua_transp_create("0.0.0.0", 2904);
Holger Hans Peter Freytherf6375b42011-01-22 21:01:23 +0100392 lnk->base.pcap_fd = -1;
Holger Hans Peter Freyther9cf11bc2011-01-17 15:53:06 +0100393 mtp_link_set_add_link(bsc.m2ua_set, (struct mtp_link *) lnk);
394
395 llist_for_each_entry(data, &bsc.m2ua_set->links, entry)
396 data->start(data);
397
Holger Hans Peter Freythera93b83b2011-01-17 15:21:06 +0100398 while (1) {
399 bsc_select_main(0);
400 }
401
402 return 0;
403}
404
405/* dummy for links */
406int msc_init(struct bsc_data *data, int dummy)
407{
408 return 0;
409}
410