blob: 6eecf46e4abdf4a51c58238ae5bd53dd8de00d6f [file] [log] [blame]
Neels Hofmeyr84da6b12016-05-20 21:59:55 +02001/* OsmoMSC - Circuit-Switched Core Network (MSC+VLR+HLR+SMSC) implementation
2 */
3
4/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
5 * All Rights Reserved
6 *
7 * Based on OsmoNITB:
8 * (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
9 * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
10 * All Rights Reserved
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Affero General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Affero General Public License for more details.
21 *
22 * You should have received a copy of the GNU Affero General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 *
25 */
26
Stefan Sperling1051c422018-12-13 10:16:49 +010027#include <stdbool.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020028#include <unistd.h>
29#include <time.h>
30#include <errno.h>
31#include <signal.h>
32#include <fcntl.h>
33#include <sys/stat.h>
34
35#define _GNU_SOURCE
36#include <getopt.h>
37
38/* build switches from the configure script */
39#include "../../bscconfig.h"
40
Neels Hofmeyr90843962017-09-04 15:04:35 +020041#include <osmocom/msc/db.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020042#include <osmocom/core/application.h>
43#include <osmocom/core/select.h>
44#include <osmocom/core/stats.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020045#include <osmocom/msc/debug.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020046#include <osmocom/abis/abis.h>
47#include <osmocom/abis/e1_input.h>
48#include <osmocom/core/talloc.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020049#include <osmocom/msc/signal.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020050#include <osmocom/msc/sms_queue.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020051#include <osmocom/vty/telnet_interface.h>
52#include <osmocom/vty/ports.h>
53#include <osmocom/vty/logging.h>
Harald Welte3db47c42018-02-14 00:40:05 +010054#include <osmocom/vty/misc.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020055#include <osmocom/msc/vty.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020056#include <osmocom/msc/mncc.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020057#include <osmocom/msc/rrlp.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020058#include <osmocom/ctrl/control_if.h>
59#include <osmocom/ctrl/control_vty.h>
60#include <osmocom/ctrl/ports.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020061#include <osmocom/msc/smpp.h>
Philipp Maierfbf66102017-04-09 12:32:51 +020062#include <osmocom/sigtran/osmo_ss7.h>
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +020063#include <osmocom/mgcp_client/mgcp_client.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020064
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020065#ifdef BUILD_IU
66#include <osmocom/ranap/iu_client.h>
67#endif
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020068
Neels Hofmeyr90843962017-09-04 15:04:35 +020069#include <osmocom/msc/msc_ifaces.h>
70#include <osmocom/msc/iucs.h>
71#include <osmocom/msc/iucs_ranap.h>
72#include <osmocom/msc/a_iface.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020073
74static const char * const osmomsc_copyright =
75 "OsmoMSC - Osmocom Circuit-Switched Core Network implementation\r\n"
76 "Copyright (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>\r\n"
77 "Based on OsmoNITB:\r\n"
78 " (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>\r\n"
79 " (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>\r\n"
80 "Contributions by Daniel Willmann, Jan Lübbe, Stefan Schmidt\r\n"
81 "Dieter Spaar, Andreas Eversberg, Sylvain Munaut, Neels Hofmeyr\r\n\r\n"
82 "License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
83 "This is free software: you are free to change and redistribute it.\r\n"
84 "There is NO WARRANTY, to the extent permitted by law.\r\n";
85
86void *tall_msc_ctx = NULL;
87
88/* satisfy deps from libbsc legacy.
89 TODO double check these */
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020090void *tall_map_ctx = NULL;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020091/* end deps from libbsc legacy. */
92
93static struct {
94 const char *database_name;
95 const char *config_file;
96 int daemonize;
97 const char *mncc_sock_path;
98 int use_db_counter;
99} msc_cmdline_config = {
Neels Hofmeyra2ed9b52018-12-05 00:38:28 +0100100 .database_name = "sms.db",
101 .config_file = "osmo-msc.cfg",
102 .use_db_counter = 1,
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200103};
104
105/* timer to store statistics */
106#define DB_SYNC_INTERVAL 60, 0
107#define EXPIRE_INTERVAL 10, 0
108
109static struct osmo_timer_list db_sync_timer;
110
Pau Espin Pedrolb8744862018-08-13 16:29:50 +0200111static int quit = 0;
112
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200113static void print_usage()
114{
Neels Hofmeyre9495382018-03-09 15:00:24 +0100115 printf("Usage: osmo-msc\n");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200116}
117
118static void print_help()
119{
120 printf(" Some useful help...\n");
121 printf(" -h --help This text.\n");
Harald Welte703f2ec2018-01-25 00:36:42 +0100122 printf(" -d option --debug=DCC:DMM:DRR: Enable debugging.\n");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200123 printf(" -D --daemonize Fork the process into a background daemon.\n");
124 printf(" -c --config-file filename The config file to use.\n");
125 printf(" -s --disable-color\n");
126 printf(" -l --database db-name The database to use.\n");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200127 printf(" -T --timestamp Prefix every log line with a timestamp.\n");
Pau Espin Pedrola232eeb2018-06-15 14:58:33 +0200128 printf(" -V --version Print the version of OsmoMSC.\n");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200129 printf(" -e --log-level number Set a global loglevel.\n");
130 printf(" -M --mncc-sock-path PATH Disable built-in MNCC handler and offer socket.\n");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200131 printf(" -C --no-dbcounter Disable regular syncing of counters to database.\n");
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200132}
133
134static void handle_options(int argc, char **argv)
135{
136 while (1) {
137 int option_index = 0, c;
138 static struct option long_options[] = {
139 {"help", 0, 0, 'h'},
140 {"debug", 1, 0, 'd'},
141 {"daemonize", 0, 0, 'D'},
142 {"config-file", 1, 0, 'c'},
143 {"disable-color", 0, 0, 's'},
144 {"database", 1, 0, 'l'},
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200145 {"timestamp", 0, 0, 'T'},
146 {"version", 0, 0, 'V' },
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200147 {"log-level", 1, 0, 'e'},
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200148 {"mncc-sock-path", 1, 0, 'M'},
149 {"no-dbcounter", 0, 0, 'C'},
150 {0, 0, 0, 0}
151 };
152
Philipp Maierc4e7bd32017-12-05 12:14:47 +0100153 c = getopt_long(argc, argv, "hd:Dsl:TVc:e:CM:",
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200154 long_options, &option_index);
155 if (c == -1)
156 break;
157
158 switch (c) {
159 case 'h':
160 print_usage();
161 print_help();
162 exit(0);
163 case 's':
164 log_set_use_color(osmo_stderr_target, 0);
165 break;
166 case 'd':
167 log_parse_category_mask(osmo_stderr_target, optarg);
168 break;
169 case 'D':
170 msc_cmdline_config.daemonize = 1;
171 break;
172 case 'l':
173 msc_cmdline_config.database_name = optarg;
174 break;
175 case 'c':
176 msc_cmdline_config.config_file = optarg;
177 break;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200178 case 'T':
179 log_set_print_timestamp(osmo_stderr_target, 1);
180 break;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200181 case 'e':
182 log_set_log_level(osmo_stderr_target, atoi(optarg));
183 break;
184 case 'M':
185 msc_cmdline_config.mncc_sock_path = optarg;
186 break;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200187 case 'C':
188 msc_cmdline_config.use_db_counter = 0;
189 break;
190 case 'V':
191 print_version(1);
192 exit(0);
193 break;
194 default:
195 /* catch unknown options *as well as* missing arguments. */
196 fprintf(stderr, "Error in command line options. Exiting.\n");
197 exit(-1);
198 }
199 }
200}
201
202struct gsm_network *msc_network_alloc(void *ctx,
203 mncc_recv_cb_t mncc_recv)
204{
Neels Hofmeyr7f484202018-02-27 12:59:45 +0100205 struct gsm_network *net = gsm_network_init(ctx, mncc_recv);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200206 if (!net)
207 return NULL;
208
209 net->name_long = talloc_strdup(net, "OsmoMSC");
210 net->name_short = talloc_strdup(net, "OsmoMSC");
211
212 net->gsup_server_addr_str = talloc_strdup(net,
213 MSC_HLR_REMOTE_IP_DEFAULT);
214 net->gsup_server_port = MSC_HLR_REMOTE_PORT_DEFAULT;
215
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200216 mgcp_client_conf_init(&net->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200217
218 return net;
219}
220
221void msc_network_shutdown(struct gsm_network *net)
222{
223 /* nothing here yet */
224}
225
226static struct gsm_network *msc_network = NULL;
227
228extern void *tall_vty_ctx;
229static void signal_handler(int signal)
230{
231 fprintf(stdout, "signal %u received\n", signal);
232
233 switch (signal) {
234 case SIGINT:
Harald Welte28cd9442017-08-20 20:50:06 +0200235 case SIGTERM:
Pau Espin Pedrolb8744862018-08-13 16:29:50 +0200236 LOGP(DMSC, LOGL_NOTICE, "Terminating due to signal %d\n", signal);
237 quit++;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200238 break;
239 case SIGABRT:
240 osmo_generate_backtrace();
241 /* in case of abort, we want to obtain a talloc report
242 * and then return to the caller, who will abort the process */
243 case SIGUSR1:
244 talloc_report(tall_vty_ctx, stderr);
245 talloc_report_full(tall_msc_ctx, stderr);
246 break;
247 case SIGUSR2:
248 talloc_report_full(tall_vty_ctx, stderr);
249 break;
250 default:
251 break;
252 }
253}
254
255/* timer handling */
256static int _db_store_counter(struct osmo_counter *counter, void *data)
257{
258 return db_store_counter(counter);
259}
260
261static void db_sync_timer_cb(void *data)
262{
263 /* store counters to database and re-schedule */
264 osmo_counters_for_each(_db_store_counter, NULL);
265 osmo_timer_schedule(&db_sync_timer, DB_SYNC_INTERVAL);
266}
267
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100268static int msc_vty_go_parent(struct vty *vty)
269{
270 switch (vty->node) {
271 case GSMNET_NODE:
272 vty->node = CONFIG_NODE;
273 vty->index = NULL;
274 break;
275 case SMPP_ESME_NODE:
276 vty->node = SMPP_NODE;
277 vty->index = NULL;
278 break;
279 case SMPP_NODE:
280 case MSC_NODE:
281 case MNCC_INT_NODE:
282 vty->node = CONFIG_NODE;
283 vty->index = NULL;
284 break;
285 case SUBSCR_NODE:
286 vty->node = ENABLE_NODE;
287 vty->index = NULL;
288 break;
289 default:
290 osmo_ss7_vty_go_parent(vty);
291 }
292
293 return vty->node;
294}
295
296static int msc_vty_is_config_node(struct vty *vty, int node)
297{
298 /* Check if libosmo-sccp declares the node in
299 * question as config node */
300 if (osmo_ss7_is_config_node(vty, node))
301 return 1;
302
303 switch (node) {
304 /* add items that are not config */
305 case SUBSCR_NODE:
306 case CONFIG_NODE:
307 return 0;
308
309 default:
310 return 1;
311 }
312}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200313
314static struct vty_app_info msc_vty_info = {
315 .name = "OsmoMSC",
316 .version = PACKAGE_VERSION,
Neels Hofmeyr7c075a22018-03-22 14:50:20 +0100317 .go_parent_cb = msc_vty_go_parent,
318 .is_config_node = msc_vty_is_config_node,
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200319};
320
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200321#ifdef BUILD_IU
Philipp Maierfbf66102017-04-09 12:32:51 +0200322static int rcvmsg_iu_cs(struct msgb *msg, struct gprs_ra_id *ra_id, uint16_t *sai)
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200323{
Harald Weltea41b6302018-02-09 00:27:56 +0100324 DEBUGP(DIUCS, "got IuCS message %d bytes: %s\n", msg->len, msgb_hexdump(msg));
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200325 if (ra_id) {
Neels Hofmeyr379d5792018-02-22 04:04:54 +0100326 DEBUGP(DIUCS, "got IuCS message on %s\n", osmo_rai_name(ra_id));
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200327 }
328
329 return gsm0408_rcvmsg_iucs(msc_network, msg, ra_id? &ra_id->lac : NULL);
330}
331
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200332static int rx_iu_event(struct ranap_ue_conn_ctx *ctx, enum ranap_iu_event_type type,
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200333 void *data)
334{
335 DEBUGP(DIUCS, "got IuCS event %u: %s\n", type,
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200336 ranap_iu_event_type_str(type));
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200337
338 return iucs_rx_ranap_event(msc_network, ctx, type, data);
339}
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200340#endif
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200341
Philipp Maierfbf66102017-04-09 12:32:51 +0200342#define DEFAULT_M3UA_REMOTE_IP "127.0.0.1"
Neels Hofmeyrc875f842017-11-24 04:36:35 +0100343#define DEFAULT_PC "0.23.1"
Philipp Maierfbf66102017-04-09 12:32:51 +0200344
345static struct osmo_sccp_instance *sccp_setup(void *ctx, uint32_t cs7_instance,
346 const char *label, const char *default_pc_str)
347{
348 int default_pc = osmo_ss7_pointcode_parse(NULL, default_pc_str);
349 if (default_pc < 0)
350 return NULL;
351
352 return osmo_sccp_simple_client_on_ss7_id(ctx, cs7_instance, label, default_pc,
353 OSMO_SS7_ASP_PROT_M3UA,
354 0, NULL, /* local: use arbitrary port and 0.0.0.0. */
355 0, /* remote: use protocol default port */
356 DEFAULT_M3UA_REMOTE_IP);
357 /* Note: If a differing remote IP is to be used, it was already entered in the vty config at
358 * 'cs7' / 'asp' / 'remote-ip', and this default remote IP has no effect.
359 * Similarly, 'cs7' / 'listen' can specify the local IP address. */
360}
361
362static int ss7_setup(void *ctx)
363{
364 uint32_t cs7_instance_a = msc_network->a.cs7_instance;
365#if BUILD_IU
366 uint32_t cs7_instance_iu = msc_network->iu.cs7_instance;
367
368 if (cs7_instance_a == cs7_instance_iu) {
369 /* Create one single SCCP instance which will be used for both,
370 * Iu and A at the same time, under the same point-code */
371 LOGP(DMSC, LOGL_NOTICE, "CS7 Instance identifiers: A = Iu = %u\n", cs7_instance_a);
372
Neels Hofmeyrc875f842017-11-24 04:36:35 +0100373 msc_network->a.sccp = sccp_setup(ctx, cs7_instance_a, "OsmoMSC-A-Iu", DEFAULT_PC);
Philipp Maierfbf66102017-04-09 12:32:51 +0200374 if (!msc_network->a.sccp)
375 return -EINVAL;
376
377 msc_network->iu.sccp = msc_network->a.sccp;
378 } else {
379 /* Create two separate SCCP instances to run A and Iu independently on different
380 * pointcodes */
381 LOGP(DMSC, LOGL_NOTICE, "CS7 Instance identifiers: A = %u, Iu = %u\n",
382 cs7_instance_a, cs7_instance_iu);
383
Neels Hofmeyrc875f842017-11-24 04:36:35 +0100384 msc_network->a.sccp = sccp_setup(ctx, cs7_instance_a, "OsmoMSC-A", DEFAULT_PC);
Philipp Maierfbf66102017-04-09 12:32:51 +0200385 if (!msc_network->a.sccp)
386 return -EINVAL;
387
Neels Hofmeyrc875f842017-11-24 04:36:35 +0100388 msc_network->iu.sccp = sccp_setup(ctx, cs7_instance_iu, "OsmoMSC-Iu", DEFAULT_PC);
Philipp Maierfbf66102017-04-09 12:32:51 +0200389 if (!msc_network->iu.sccp)
390 return -EINVAL;
391 }
392#else
393 /* No Iu support, just open up an A instance */
Neels Hofmeyrc875f842017-11-24 04:36:35 +0100394 msc_network->a.sccp = sccp_setup(ctx, cs7_instance_a, "OsmoMSC-A", DEFAULT_PC);
Philipp Maierfbf66102017-04-09 12:32:51 +0200395 if (!msc_network->a.sccp)
396 return -EINVAL;
397#endif
398
399 return 0;
400}
401
Neels Hofmeyr6a8b9c72018-03-22 15:51:22 +0100402static const struct log_info_cat msc_default_categories[] = {
403 [DRLL] = {
404 .name = "DRLL",
405 .description = "A-bis Radio Link Layer (RLL)",
406 .color = "\033[1;31m",
407 .enabled = 1, .loglevel = LOGL_NOTICE,
408 },
409 [DCC] = {
410 .name = "DCC",
411 .description = "Layer3 Call Control (CC)",
412 .color = "\033[1;32m",
413 .enabled = 1, .loglevel = LOGL_NOTICE,
414 },
415 [DMM] = {
416 .name = "DMM",
417 .description = "Layer3 Mobility Management (MM)",
418 .color = "\033[1;33m",
419 .enabled = 1, .loglevel = LOGL_NOTICE,
420 },
421 [DRR] = {
422 .name = "DRR",
423 .description = "Layer3 Radio Resource (RR)",
424 .color = "\033[1;34m",
425 .enabled = 1, .loglevel = LOGL_NOTICE,
426 },
427 [DMNCC] = {
428 .name = "DMNCC",
429 .description = "MNCC API for Call Control application",
430 .color = "\033[1;39m",
431 .enabled = 1, .loglevel = LOGL_NOTICE,
432 },
433 [DPAG] = {
434 .name = "DPAG",
435 .description = "Paging Subsystem",
436 .color = "\033[1;38m",
437 .enabled = 1, .loglevel = LOGL_NOTICE,
438 },
439 [DMSC] = {
440 .name = "DMSC",
441 .description = "Mobile Switching Center",
442 .enabled = 1, .loglevel = LOGL_NOTICE,
443 },
444 [DMGCP] = {
445 .name = "DMGCP",
446 .description = "Media Gateway Control Protocol",
447 .enabled = 1, .loglevel = LOGL_NOTICE,
448 },
449 [DHO] = {
450 .name = "DHO",
451 .description = "Hand-Over",
452 .enabled = 1, .loglevel = LOGL_NOTICE,
453 },
454 [DDB] = {
455 .name = "DDB",
456 .description = "Database Layer",
457 .enabled = 1, .loglevel = LOGL_NOTICE,
458 },
459 [DREF] = {
460 .name = "DREF",
461 .description = "Reference Counting",
462 .enabled = 0, .loglevel = LOGL_NOTICE,
463 },
464 [DCTRL] = {
465 .name = "DCTRL",
466 .description = "Control interface",
467 .enabled = 1, .loglevel = LOGL_NOTICE,
468 },
469 [DSMPP] = {
470 .name = "DSMPP",
471 .description = "SMPP interface for external SMS apps",
Neels Hofmeyr88063dd2018-12-12 04:05:31 +0100472 .enabled = 1, .loglevel = LOGL_NOTICE,
Neels Hofmeyr6a8b9c72018-03-22 15:51:22 +0100473 },
474 [DRANAP] = {
475 .name = "DRANAP",
476 .description = "Radio Access Network Application Part Protocol",
Neels Hofmeyr88063dd2018-12-12 04:05:31 +0100477 .enabled = 1, .loglevel = LOGL_NOTICE,
Neels Hofmeyr6a8b9c72018-03-22 15:51:22 +0100478 },
479 [DVLR] = {
480 .name = "DVLR",
481 .description = "Visitor Location Register",
Neels Hofmeyr88063dd2018-12-12 04:05:31 +0100482 .enabled = 1, .loglevel = LOGL_NOTICE,
Neels Hofmeyr6a8b9c72018-03-22 15:51:22 +0100483 },
484 [DIUCS] = {
485 .name = "DIUCS",
486 .description = "Iu-CS Protocol",
Neels Hofmeyr88063dd2018-12-12 04:05:31 +0100487 .enabled = 1, .loglevel = LOGL_NOTICE,
Neels Hofmeyr6a8b9c72018-03-22 15:51:22 +0100488 },
489 [DBSSAP] = {
490 .name = "DBSSAP",
491 .description = "BSSAP Protocol (A Interface)",
492 .enabled = 1, .loglevel = LOGL_NOTICE,
493 },
494
495};
496
497static int filter_fn(const struct log_context *ctx, struct log_target *tar)
498{
499 const struct vlr_subscr *vsub = ctx->ctx[LOG_CTX_VLR_SUBSCR];
500
501 if ((tar->filter_map & (1 << LOG_FLT_VLR_SUBSCR)) != 0
502 && vsub && vsub == tar->filter_data[LOG_FLT_VLR_SUBSCR])
503 return 1;
504
505 return 0;
506}
507
508const struct log_info log_info = {
509 .filter_fn = filter_fn,
510 .cat = msc_default_categories,
511 .num_cat = ARRAY_SIZE(msc_default_categories),
512};
513
Neels Hofmeyrc01e9092018-03-22 15:56:49 +0100514extern void *tall_gsms_ctx;
515extern void *tall_call_ctx;
516extern void *tall_trans_ctx;
517
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200518int main(int argc, char **argv)
519{
520 int rc;
521
Vadim Yanitskiy381370b2018-08-14 18:57:53 +0700522 /* Track the use of talloc NULL memory contexts */
523 talloc_enable_null_tracking();
524
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200525 msc_vty_info.copyright = osmomsc_copyright;
526
527 tall_msc_ctx = talloc_named_const(NULL, 1, "osmo_msc");
Harald Welte3db47c42018-02-14 00:40:05 +0100528 msc_vty_info.tall_ctx = tall_msc_ctx;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200529
Neels Hofmeyrc01e9092018-03-22 15:56:49 +0100530 msgb_talloc_ctx_init(tall_msc_ctx, 0);
Pau Espin Pedrol060a6c42018-08-16 19:09:21 +0200531 osmo_signal_talloc_ctx_init(tall_msc_ctx);
Neels Hofmeyrc01e9092018-03-22 15:56:49 +0100532 tall_gsms_ctx = talloc_named_const(tall_msc_ctx, 0, "sms");
533 tall_call_ctx = talloc_named_const(tall_msc_ctx, 0, "gsm_call");
534 tall_trans_ctx = talloc_named_const(tall_msc_ctx, 0, "transaction");
535
Neels Hofmeyr08b38282018-03-30 23:04:04 +0200536 osmo_init_logging2(tall_msc_ctx, &log_info);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200537 osmo_stats_init(tall_msc_ctx);
538
539 /* For --version, vty_init() must be called before handling options */
540 vty_init(&msc_vty_info);
541
Philipp Maierfbf66102017-04-09 12:32:51 +0200542 osmo_ss7_init();
543 osmo_ss7_vty_init_asp(tall_msc_ctx);
Neels Hofmeyr86ed06c2018-09-27 01:54:32 +0200544 osmo_sccp_vty_init();
Philipp Maierfbf66102017-04-09 12:32:51 +0200545
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200546 /* Parse options */
547 handle_options(argc, argv);
548
Neels Hofmeyrfb153cb2018-12-05 00:47:31 +0100549 /* Allocate global gsm_network struct.
550 * At first set the internal MNCC as default, may be changed below according to cfg or cmdline option. */
551 msc_network = msc_network_alloc(tall_msc_ctx, int_mncc_recv);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200552 if (!msc_network)
553 return -ENOMEM;
554
555 if (msc_vlr_alloc(msc_network)) {
556 fprintf(stderr, "Failed to allocate VLR\n");
557 exit(1);
558 }
559
560 ctrl_vty_init(tall_msc_ctx);
561 logging_vty_add_cmds(&log_info);
Harald Welte3db47c42018-02-14 00:40:05 +0100562 osmo_talloc_vty_add_cmds();
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200563 msc_vty_init(msc_network);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200564
565#ifdef BUILD_SMPP
566 if (smpp_openbsc_alloc_init(tall_msc_ctx) < 0)
567 return -1;
568#endif
569
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200570 rc = vty_read_config_file(msc_cmdline_config.config_file, NULL);
571 if (rc < 0) {
Harald Welte703f2ec2018-01-25 00:36:42 +0100572 LOGP(DMSC, LOGL_FATAL, "Failed to parse the config file: '%s'\n",
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200573 msc_cmdline_config.config_file);
574 return 1;
575 }
576
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100577 /* Initialize MNCC socket if appropriate. If the cmdline option -M is present, it overrides the .cfg file
578 * setting 'msc' / 'mncc external MNCC_SOCKET_PATH'. Note that when -M is given, it "bleeds" back into the vty
579 * 'write' command and is reflected in the written out 'mncc external' cfg. */
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200580 if (msc_cmdline_config.mncc_sock_path) {
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100581 LOGP(DMNCC, LOGL_NOTICE,
582 "MNCC socket path is configured from commandline argument -M."
583 " This affects a written-back config file. Instead consider using the config file directly"
584 " ('msc' / 'mncc external MNCC_SOCKET_PATH').\n");
585 gsm_network_set_mncc_sock_path(msc_network, msc_cmdline_config.mncc_sock_path);
586 }
587 if (msc_network->mncc_sock_path) {
Neels Hofmeyrfb153cb2018-12-05 00:47:31 +0100588 msc_network->mncc_recv = mncc_sock_from_cc;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200589 rc = mncc_sock_init(msc_network,
Neels Hofmeyr80447eb2018-12-05 01:11:28 +0100590 msc_network->mncc_sock_path);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200591 if (rc) {
592 fprintf(stderr, "MNCC socket initialization failed. exiting.\n");
593 exit(1);
594 }
595 } else
596 DEBUGP(DMNCC, "Using internal MNCC handler.\n");
597
598 /* start telnet after reading config for vty_get_bind_addr() */
599 rc = telnet_init_dynif(tall_msc_ctx, &msc_network,
600 vty_get_bind_addr(), OSMO_VTY_PORT_MSC);
601 if (rc < 0)
602 return 2;
603
604 /* BSC stuff is to be split behind an A-interface to be used with
605 * OsmoBSC, but there is no need to remove it yet. Most of the
606 * following code until iu_init() is legacy. */
607
608#ifdef BUILD_SMPP
609 smpp_openbsc_start(msc_network);
610#endif
611
612 /* start control interface after reading config for
613 * ctrl_vty_get_bind_addr() */
614 msc_network->ctrl = ctrl_interface_setup_dynip(msc_network, ctrl_vty_get_bind_addr(),
615 OSMO_CTRL_PORT_MSC, NULL);
616 if (!msc_network->ctrl) {
617 printf("Failed to initialize control interface. Exiting.\n");
618 return -1;
619 }
620
621#if 0
622TODO: we probably want some of the _net_ ctrl commands from bsc_base_ctrl_cmds_install().
623 if (bsc_base_ctrl_cmds_install() != 0) {
624 printf("Failed to initialize the BSC control commands.\n");
625 return -1;
626 }
627#endif
628
629 if (msc_ctrl_cmds_install(msc_network) != 0) {
630 printf("Failed to initialize the MSC control commands.\n");
631 return -1;
632 }
633
634 /* seed the PRNG */
635 srand(time(NULL));
636 /* TODO: is this used for crypto?? Improve randomness, at least we
637 * should try to use the nanoseconds part of the current time. */
638
639 if (db_init(msc_cmdline_config.database_name)) {
640 printf("DB: Failed to init database: %s\n",
641 msc_cmdline_config.database_name);
642 return 4;
643 }
644
645 osmo_fsm_log_addr(true);
646 if (msc_vlr_start(msc_network)) {
647 fprintf(stderr, "Failed to start VLR\n");
648 exit(1);
649 }
650
Neels Hofmeyrc036b792018-11-29 22:37:51 +0100651 ran_conn_init();
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200652
653 if (db_prepare()) {
654 printf("DB: Failed to prepare database.\n");
655 return 5;
656 }
657
658 /* setup the timer */
659 osmo_timer_setup(&db_sync_timer, db_sync_timer_cb, NULL);
660 if (msc_cmdline_config.use_db_counter)
661 osmo_timer_schedule(&db_sync_timer, DB_SYNC_INTERVAL);
662
663 signal(SIGINT, &signal_handler);
Harald Welte28cd9442017-08-20 20:50:06 +0200664 signal(SIGTERM, &signal_handler);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200665 signal(SIGABRT, &signal_handler);
666 signal(SIGUSR1, &signal_handler);
667 signal(SIGUSR2, &signal_handler);
668 osmo_init_ignore_signals();
669
670 /* start the SMS queue */
671 if (sms_queue_start(msc_network, 20) != 0)
672 return -1;
673
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200674 msc_network->mgw.client = mgcp_client_init(
675 msc_network, &msc_network->mgw.conf);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200676
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200677 if (mgcp_client_connect(msc_network->mgw.client)) {
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200678 printf("MGCPGW connect failed\n");
679 return 7;
680 }
681
Philipp Maierfbf66102017-04-09 12:32:51 +0200682 if (ss7_setup(tall_msc_ctx)) {
683 printf("Setting up SCCP client failed.\n");
684 return 8;
685 }
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200686
687#ifdef BUILD_IU
688 /* Set up IuCS */
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200689 ranap_iu_init(tall_msc_ctx, DRANAP, "OsmoMSC-IuCS", msc_network->iu.sccp, rcvmsg_iu_cs, rx_iu_event);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200690#endif
691
Philipp Maierfbf66102017-04-09 12:32:51 +0200692 /* Set up A interface */
693 a_init(msc_network->a.sccp, msc_network);
694
Vadim Yanitskiy1f9b0862018-08-04 01:16:52 +0700695 /* Init RRLP handlers */
696 msc_rrlp_init();
697
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200698 if (msc_cmdline_config.daemonize) {
699 rc = osmo_daemonize();
700 if (rc < 0) {
701 perror("Error during daemonize");
702 return 6;
703 }
704 }
705
Pau Espin Pedrolb8744862018-08-13 16:29:50 +0200706 while (!quit) {
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200707 log_reset_context();
708 osmo_select_main(0);
709 }
Pau Espin Pedrolb8744862018-08-13 16:29:50 +0200710
711 msc_network_shutdown(msc_network);
712 osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL);
713 sleep(3);
714
715 log_fini();
716
717 /**
718 * Report the heap state of root context, then free,
719 * so both ASAN and Valgrind are happy...
720 */
721 talloc_report_full(tall_msc_ctx, stderr);
722 talloc_free(tall_msc_ctx);
723
Vadim Yanitskiyd8d4d8c2018-08-14 19:13:15 +0700724 /* FIXME: VTY code still uses NULL-context */
725 talloc_free(tall_vty_ctx);
726
Pau Espin Pedrolb8744862018-08-13 16:29:50 +0200727 /**
728 * Report the heap state of NULL context, then free,
729 * so both ASAN and Valgrind are happy...
730 */
731 talloc_report_full(NULL, stderr);
732 talloc_disable_null_tracking();
733 return 0;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200734}