blob: 3f24a42b9d724a3f842f713f95f8bf92b617bf14 [file] [log] [blame]
Harald Welteb53e2bf2020-08-21 16:33:42 +02001/* (C) 2020 by Harald Welte <laforge@gnumonks.org>
2 * All Rights Reserved
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
13 *
14 * You should have received a copy of the GNU Affero General Public License
15 * along with this program. If not, see <http://www.gnu.org/lienses/>.
16 *
17 */
18
19#include <osmocom/ctrl/control_cmd.h>
20#include <osmocom/ctrl/control_if.h>
21#include <osmocom/ctrl/ports.h>
22#include <osmocom/ctrl/control_vty.h>
23
24#include <osmocom/core/application.h>
25#include <osmocom/core/linuxlist.h>
26#include <osmocom/core/talloc.h>
27#include <osmocom/core/signal.h>
28#include <osmocom/core/stats.h>
29#include <osmocom/core/rate_ctr.h>
30#include <osmocom/vty/telnet_interface.h>
31#include <osmocom/vty/ports.h>
32#include <osmocom/vty/logging.h>
33#include <osmocom/vty/command.h>
Neels Hofmeyr72992152020-09-19 02:36:08 +020034#include <osmocom/vty/misc.h>
Harald Welteb53e2bf2020-08-21 16:33:42 +020035
36#include <osmocom/sigtran/xua_msg.h>
37#include <osmocom/sigtran/sccp_sap.h>
38
Neels Hofmeyr72992152020-09-19 02:36:08 +020039#include <osmocom/smlc/debug.h>
Harald Welteb53e2bf2020-08-21 16:33:42 +020040#include <osmocom/smlc/smlc_data.h>
Neels Hofmeyr72992152020-09-19 02:36:08 +020041#include <osmocom/smlc/sccp_lb_inst.h>
42#include <osmocom/smlc/cell_locations.h>
Harald Welteb53e2bf2020-08-21 16:33:42 +020043
44#define _GNU_SOURCE
45#include <getopt.h>
46
47#include <signal.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <time.h>
51#include <unistd.h>
52
Harald Welteb53e2bf2020-08-21 16:33:42 +020053#include "../../config.h"
54
Neels Hofmeyr72992152020-09-19 02:36:08 +020055#define DEFAULT_M3UA_LOCAL_IP "localhost"
56#define DEFAULT_M3UA_REMOTE_IP "localhost"
57#define SMLC_DEFAULT_PC "0.23.6"
58
Harald Welteb53e2bf2020-08-21 16:33:42 +020059static const char *config_file = "osmo-smlc.cfg";
60static int daemonize = 0;
61static void *tall_smlc_ctx;
62struct smlc_state *g_smlc;
63
64static void print_usage()
65{
66 printf("Usage: osmo-smlc\n");
67}
68
69static void print_help()
70{
71 printf(" Some useful help...\n");
72 printf(" -h --help This text.\n");
73 printf(" -D --daemonize Fork the process into a background daemon.\n");
74 printf(" -d --debug option --debug=DRLL:DMM:DRR:DRSL:DNM enable debugging.\n");
75 printf(" -V --version Print the version of OsmoBSC.\n");
76 printf(" -c --config-file filename The config file to use.\n");
77 printf(" -e --log-level number Set a global loglevel.\n");
78 printf(" --vty-ref-xml Generate the VTY reference XML output and exit.\n");
79}
80
Pau Espin Pedrolb36a18f2021-02-24 14:26:30 +010081static void handle_long_options(const char *prog_name, const int long_option)
82{
83 static int vty_ref_mode = VTY_REF_GEN_MODE_DEFAULT;
84
85 switch (long_option) {
86 case 1:
87 vty_ref_mode = get_string_value(vty_ref_gen_mode_names, optarg);
88 if (vty_ref_mode < 0) {
89 fprintf(stderr, "%s: Unknown VTY reference generation "
90 "mode '%s'\n", prog_name, optarg);
91 exit(2);
92 }
93 break;
94 case 2:
95 fprintf(stderr, "Generating the VTY reference in mode '%s' (%s)\n",
96 get_value_string(vty_ref_gen_mode_names, vty_ref_mode),
97 get_value_string(vty_ref_gen_mode_desc, vty_ref_mode));
98 vty_dump_xml_ref_mode(stdout, (enum vty_ref_gen_mode) vty_ref_mode);
99 exit(0);
100 default:
101 fprintf(stderr, "%s: error parsing cmdline options\n", prog_name);
102 exit(2);
103 }
104}
105
Harald Welteb53e2bf2020-08-21 16:33:42 +0200106static void handle_options(int argc, char **argv)
107{
108 while (1) {
109 int option_index = 0, c;
110 static int long_option = 0;
111 static struct option long_options[] = {
112 {"help", 0, 0, 'h'},
113 {"debug", 1, 0, 'd'},
114 {"daemonize", 0, 0, 'D'},
115 {"config-file", 1, 0, 'c'},
116 {"version", 0, 0, 'V' },
117 {"log-level", 1, 0, 'e'},
Pau Espin Pedrolb36a18f2021-02-24 14:26:30 +0100118 {"vty-ref-mode", 1, &long_option, 1},
119 {"vty-ref-xml", 0, &long_option, 2},
Harald Welteb53e2bf2020-08-21 16:33:42 +0200120 {0, 0, 0, 0}
121 };
122
123 c = getopt_long(argc, argv, "hd:Dc:Ve:",
124 long_options, &option_index);
125 if (c == -1)
126 break;
127
128 switch (c) {
129 case 'h':
130 print_usage();
131 print_help();
132 exit(0);
133 case 0:
Pau Espin Pedrolb36a18f2021-02-24 14:26:30 +0100134 handle_long_options(argv[0], long_option);
135 break;
Harald Welteb53e2bf2020-08-21 16:33:42 +0200136 case 'd':
137 log_parse_category_mask(osmo_stderr_target, optarg);
138 break;
139 case 'D':
140 daemonize = 1;
141 break;
142 case 'c':
143 config_file = optarg;
144 break;
145 case 'V':
146 print_version(1);
147 exit(0);
148 break;
149 case 'e':
150 log_set_log_level(osmo_stderr_target, atoi(optarg));
151 break;
152 default:
153 /* catch unknown options *as well as* missing arguments. */
154 fprintf(stderr, "Error in command line options. Exiting.\n");
155 exit(-1);
156 }
157 }
158
159 if (argc > optind) {
160 fprintf(stderr, "Unsupported positional arguments on command line\n");
161 exit(2);
162 }
163}
164
165static struct vty_app_info vty_info = {
166 .name = "OsmoSMLC",
167 .copyright =
168 "Copyright (C) 2020 Harald Welte and sysmocom - s.f.m.c. GmbH\r\n\r\n"
169 "License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
170 "This is free software: you are free to change and redistribute it.\r\n"
171 "There is NO WARRANTY, to the extent permitted by law.\r\n",
172 .version = PACKAGE_VERSION,
173};
174
175static void signal_handler(int signal)
176{
177 fprintf(stdout, "signal %u received\n", signal);
178
179 switch (signal) {
180 case SIGINT:
181 case SIGTERM:
182 exit(0);
183 break;
184 case SIGABRT:
185 /* in case of abort, we want to obtain a talloc report
186 * and then return to the caller, who will abort the process */
187 case SIGUSR1:
188 talloc_report_full(tall_smlc_ctx, stderr);
189 break;
190 default:
191 break;
192 }
193}
194
195static const struct log_info_cat smlc_categories[] = {
Neels Hofmeyr72992152020-09-19 02:36:08 +0200196 [DSMLC] = {
197 .name = "DSMLC",
198 .description = "Serving Mobile Location Center",
199 .enabled = 1, .loglevel = LOGL_NOTICE,
200 },
201 [DREF] = {
202 .name = "DREF",
203 .description = "Reference Counting",
204 .enabled = 1, .loglevel = LOGL_NOTICE,
205 },
206 [DLB] = {
207 .name = "DLB",
208 .description = "Lb interface",
209 .enabled = 1, .loglevel = LOGL_NOTICE,
210 },
211 [DLCS] = {
212 .name = "DLCS",
213 .description = "Location Services",
214 .enabled = 1, .loglevel = LOGL_NOTICE,
215 },
Harald Welteb53e2bf2020-08-21 16:33:42 +0200216};
217
218const struct log_info log_info = {
219 .cat = smlc_categories,
220 .num_cat = ARRAY_SIZE(smlc_categories),
221};
222
223int main(int argc, char **argv)
224{
225 int rc;
Neels Hofmeyr72992152020-09-19 02:36:08 +0200226 int default_pc;
Harald Welteb53e2bf2020-08-21 16:33:42 +0200227
228 tall_smlc_ctx = talloc_named_const(NULL, 1, "osmo-smlc");
229 msgb_talloc_ctx_init(tall_smlc_ctx, 0);
230 osmo_signal_talloc_ctx_init(tall_smlc_ctx);
231 osmo_xua_msg_tall_ctx_init(tall_smlc_ctx);
232 vty_info.tall_ctx = tall_smlc_ctx;
233
234 osmo_init_logging2(tall_smlc_ctx, &log_info);
235 osmo_stats_init(tall_smlc_ctx);
236 rate_ctr_init(tall_smlc_ctx);
237
238 osmo_fsm_set_dealloc_ctx(OTC_SELECT);
239
Neels Hofmeyr72992152020-09-19 02:36:08 +0200240 g_smlc = smlc_state_alloc(tall_smlc_ctx);
Harald Welteb53e2bf2020-08-21 16:33:42 +0200241
242 /* This needs to precede handle_options() */
243 vty_init(&vty_info);
Neels Hofmeyr72992152020-09-19 02:36:08 +0200244 logging_vty_add_cmds();
245 osmo_talloc_vty_add_cmds();
Harald Welteb53e2bf2020-08-21 16:33:42 +0200246 ctrl_vty_init(tall_smlc_ctx);
Neels Hofmeyr72992152020-09-19 02:36:08 +0200247 cell_locations_vty_init();
Harald Welteb53e2bf2020-08-21 16:33:42 +0200248
249 /* Initialize SS7 */
250 OSMO_ASSERT(osmo_ss7_init() == 0);
251 osmo_ss7_vty_init_asp(tall_smlc_ctx);
252 osmo_sccp_vty_init();
253
254 /* parse options */
255 handle_options(argc, argv);
256
257 /* Read the config */
258 rc = vty_read_config_file(config_file, NULL);
259 if (rc < 0) {
260 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
261 exit(1);
262 }
263
264 /* Start telnet interface after reading config for vty_get_bind_addr() */
265 rc = telnet_init_dynif(tall_smlc_ctx, g_smlc, vty_get_bind_addr(), OSMO_VTY_PORT_SMLC);
266 if (rc < 0)
267 exit(1);
268
269 /* start control interface after reading config for
270 * ctrl_vty_get_bind_addr() */
271 g_smlc->ctrl = ctrl_interface_setup_dynip2(g_smlc, ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_SMLC,
272 smlc_ctrl_node_lookup, _LAST_CTRL_NODE_SMLC);
273 if (!g_smlc->ctrl) {
274 fprintf(stderr, "Failed to init the control interface. Exiting.\n");
275 exit(1);
276 }
277
278 /*
279 rc = smlc_ctrl_cmds_install(g_smlc);
280 if (rc < 0) {
281 fprintf(stderr, "Failed to install control commands. Exiting.\n");
282 exit(1);
283 }
284 */
285
Neels Hofmeyr72992152020-09-19 02:36:08 +0200286 default_pc = osmo_ss7_pointcode_parse(NULL, SMLC_DEFAULT_PC);
287 OSMO_ASSERT(default_pc);
288
289 g_smlc->sccp_inst = osmo_sccp_simple_client_on_ss7_id(g_smlc, 0, "Lb", default_pc, OSMO_SS7_ASP_PROT_M3UA,
290 0, DEFAULT_M3UA_LOCAL_IP, 0, DEFAULT_M3UA_REMOTE_IP);
291 if (!g_smlc->sccp_inst) {
292 fprintf(stderr, "Setting up SCCP failed\n");
293 return 1;
294 }
295
296 g_smlc->lb = sccp_lb_init(g_smlc, g_smlc->sccp_inst, OSMO_SCCP_SSN_SMLC_BSSAP_LE, "OsmoSMLC-Lb");
297 if (!g_smlc->lb) {
298 fprintf(stderr, "Setting up Lb receiver failed\n");
299 return 1;
Harald Welteb53e2bf2020-08-21 16:33:42 +0200300 }
301
302 signal(SIGINT, &signal_handler);
303 signal(SIGTERM, &signal_handler);
304 signal(SIGABRT, &signal_handler);
305 signal(SIGUSR1, &signal_handler);
306 signal(SIGUSR2, &signal_handler);
307 osmo_init_ignore_signals();
308
309 if (daemonize) {
310 rc = osmo_daemonize();
311 if (rc < 0) {
312 perror("Error during daemonize");
313 exit(1);
314 }
315 }
316
317 while (1) {
318 osmo_select_main_ctx(0);
319 }
320
321 return 0;
322}