blob: 06260bf9380bee36b190ac8393c88829cc3c167d [file] [log] [blame]
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +02001/* GTP Hub main program */
2
3/* (C) 2015 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
4 * All Rights Reserved
5 *
6 * Author: Neels Hofmeyr
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <unistd.h>
23#include <signal.h>
24#include <string.h>
25#include <errno.h>
26
27#define _GNU_SOURCE
28#include <getopt.h>
29
30#include <osmocom/core/signal.h>
31#include <osmocom/core/application.h>
32#include <osmocom/core/logging.h>
33#include <osmocom/core/utils.h>
34#include <osmocom/core/rate_ctr.h>
35
36#include <osmocom/vty/logging.h>
37#include <osmocom/vty/telnet_interface.h>
38
39#include <openbsc/debug.h>
40#include <openbsc/gtphub.h>
41#include <openbsc/vty.h>
42
43#include "../../bscconfig.h"
44
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020045#ifndef OSMO_VTY_PORT_GTPHUB
46/* should come from libosmocore */
47#define OSMO_VTY_PORT_GTPHUB 4253
48#endif
49
50extern void *osmo_gtphub_ctx;
51
52
53const char *gtphub_copyright =
54 "Copyright (C) 2015 sysmocom s.f.m.c GmbH <info@sysmocom.de>\r\n"
55 "License AGPLv3+: GNU AGPL version 2 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
56 "This is free software: you are free to change and redistribute it.\r\n"
57 "There is NO WARRANTY, to the extent permitted by law.\r\n";
58
59static struct log_info_cat gtphub_categories[] = {
60 [DGTPHUB] = {
61 .name = "DGTPHUB",
62 .description = "GTP Hub",
63 .color = "\033[1;33m",
Neels Hofmeyrd9b1d492015-11-18 18:11:09 +010064 .enabled = 1,
65 .loglevel = LOGL_NOTICE,
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020066 },
67};
68
69int gtphub_log_filter_fn(const struct log_context *ctx,
70 struct log_target *tar)
71{
72 return 0;
73}
74
75static const struct log_info gtphub_log_info = {
76 .filter_fn = gtphub_log_filter_fn,
77 .cat = gtphub_categories,
78 .num_cat = ARRAY_SIZE(gtphub_categories),
79};
80
81void log_cfg(struct gtphub_cfg *cfg)
82{
83 struct gtphub_cfg_addr *a;
84 a = &cfg->to_sgsns[GTPH_PLANE_CTRL].bind;
Neels Hofmeyrd9b1d492015-11-18 18:11:09 +010085 LOGP(DGTPHUB, LOGL_NOTICE,
86 "to-SGSNs bind, Control: %s port %d\n",
87 a->addr_str, a->port);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020088 a = &cfg->to_sgsns[GTPH_PLANE_USER].bind;
Neels Hofmeyrd9b1d492015-11-18 18:11:09 +010089 LOGP(DGTPHUB, LOGL_NOTICE,
90 "to-SGSNs bind, User: %s port %d\n",
91 a->addr_str, a->port);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020092 a = &cfg->to_ggsns[GTPH_PLANE_CTRL].bind;
Neels Hofmeyrd9b1d492015-11-18 18:11:09 +010093 LOGP(DGTPHUB, LOGL_NOTICE,
94 "to-GGSNs bind, Control: %s port %d\n",
95 a->addr_str, a->port);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020096 a = &cfg->to_ggsns[GTPH_PLANE_USER].bind;
Neels Hofmeyrd9b1d492015-11-18 18:11:09 +010097 LOGP(DGTPHUB, LOGL_NOTICE,
98 "to-GGSNs bind, User: %s port %d\n",
99 a->addr_str, a->port);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200100}
101
102static void signal_handler(int signal)
103{
104 fprintf(stdout, "signal %u received\n", signal);
105
106 switch (signal) {
107 case SIGINT:
108 osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL);
109 sleep(1);
110 exit(0);
111 break;
112 case SIGABRT:
113 /* in case of abort, we want to obtain a talloc report
114 * and then return to the caller, who will abort the process */
115 case SIGUSR1:
116 case SIGUSR2:
117 talloc_report_full(osmo_gtphub_ctx, stderr);
118 break;
119 default:
120 break;
121 }
122}
123
124extern int bsc_vty_go_parent(struct vty *vty);
125
126static struct vty_app_info vty_info = {
127 .name = "OsmoGTPhub",
128 .version = PACKAGE_VERSION,
129 .go_parent_cb = bsc_vty_go_parent,
130 .is_config_node = bsc_vty_is_config_node,
131};
132
133struct cmdline_cfg {
134 const char *config_file;
135 int daemonize;
136};
137
138static void print_help(struct cmdline_cfg *ccfg)
139{
140 printf("gtphub commandline options\n");
141 printf(" -h --help This text.\n");
142 printf(" -D --daemonize Fork the process into a background daemon.\n");
143 printf(" -d,--debug <cat> Enable Debugging for this category.\n");
144 printf(" Pass '-d list' to get a category listing.\n");
145 printf(" -s --disable-color");
146 printf(" -c --config-file The config file to use [%s].\n", ccfg->config_file);
147 printf(" -e,--log-level <nr> Set a global log level.\n");
148}
149
150static void list_categories(void)
151{
152 printf("Avaliable debug categories:\n");
153 int i;
154 for (i = 0; i < gtphub_log_info.num_cat; ++i) {
155 if (!gtphub_log_info.cat[i].name)
156 continue;
157
158 printf("%s\n", gtphub_log_info.cat[i].name);
159 }
160}
161
162static void handle_options(struct cmdline_cfg *ccfg, int argc, char **argv)
163{
164 while (1) {
165 int option_index = 0, c;
166 static struct option long_options[] = {
167 {"help", 0, 0, 'h'},
168 {"debug", 1, 0, 'd'},
169 {"daemonize", 0, 0, 'D'},
170 {"config-file", 1, 0, 'c'},
171 {"disable-color", 0, 0, 's'},
172 {"timestamp", 0, 0, 'T'},
173 {"log-level", 1, 0, 'e'},
174 {NULL, 0, 0, 0}
175 };
176
177 c = getopt_long(argc, argv, "hd:Dc:sTe:",
178 long_options, &option_index);
179 if (c == -1)
180 break;
181
182 switch (c) {
183 case 'h':
184 //print_usage();
185 print_help(ccfg);
186 exit(0);
187 case 's':
188 log_set_use_color(osmo_stderr_target, 0);
189 break;
190 case 'd':
191 if (strcmp("list", optarg) == 0) {
192 list_categories();
193 exit(0);
194 } else
195 log_parse_category_mask(osmo_stderr_target, optarg);
196 break;
197 case 'D':
198 ccfg->daemonize = 1;
199 break;
200 case 'c':
201 ccfg->config_file = optarg;
202 break;
203 case 'T':
204 log_set_print_timestamp(osmo_stderr_target, 1);
205 break;
206 case 'e':
207 log_set_log_level(osmo_stderr_target, atoi(optarg));
208 break;
209 default:
210 /* ignore */
211 break;
212 }
213 }
214}
215
216int main(int argc, char **argv)
217{
218 int rc;
219
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100220 struct cmdline_cfg _ccfg;
221 struct cmdline_cfg *ccfg = &_ccfg;
222 memset(ccfg, '\0', sizeof(*ccfg));
223 ccfg->config_file = "./gtphub.conf";
224
225 struct gtphub_cfg _cfg;
226 struct gtphub_cfg *cfg = &_cfg;
227 memset(cfg, '\0', sizeof(*cfg));
228
229 struct gtphub _hub;
230 struct gtphub *hub = &_hub;
231
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200232 osmo_gtphub_ctx = talloc_named_const(NULL, 0, "osmo_gtphub");
233
234 signal(SIGINT, &signal_handler);
235 signal(SIGABRT, &signal_handler);
236 signal(SIGUSR1, &signal_handler);
237 signal(SIGUSR2, &signal_handler);
238 osmo_init_ignore_signals();
239
240 osmo_init_logging(&gtphub_log_info);
241
242 vty_info.copyright = gtphub_copyright;
243 vty_init(&vty_info);
244 logging_vty_add_cmds(&gtphub_log_info);
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100245 gtphub_vty_init(hub, cfg);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200246
247 rate_ctr_init(osmo_gtphub_ctx);
248 rc = telnet_init(osmo_gtphub_ctx, 0, OSMO_VTY_PORT_GTPHUB);
249 if (rc < 0)
250 exit(1);
251
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200252 handle_options(ccfg, argc, argv);
253
254 rc = gtphub_cfg_read(cfg, ccfg->config_file);
255 if (rc < 0) {
Neels Hofmeyrd9b1d492015-11-18 18:11:09 +0100256 LOGP(DGTPHUB, LOGL_FATAL, "Cannot parse config file '%s'\n",
257 ccfg->config_file);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200258 exit(2);
259 }
260
261 if (gtphub_start(hub, cfg) != 0)
262 return -1;
263
264 log_cfg(cfg);
265
266 if (ccfg->daemonize) {
267 rc = osmo_daemonize();
268 if (rc < 0) {
Neels Hofmeyrd9b1d492015-11-18 18:11:09 +0100269 LOGP(DGTPHUB, LOGL_FATAL, "Error during daemonize");
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200270 exit(1);
271 }
272 }
273
274 while (1) {
275 rc = osmo_select_main(0);
276 if (rc < 0)
277 exit(3);
278 }
279
280 /* not reached */
281 exit(0);
282}