blob: a7c96a71c4c245ba908cec5a7dd89a95133fbe03 [file] [log] [blame]
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +02001/*
2 * OsmoGGSN - Gateway GPRS Support Node
3 * Copyright (C) 2002, 2003, 2004 Mondru AB.
4 * Copyright (C) 2017-2019 by Harald Welte <laforge@gnumonks.org>
5 * Copyright (C) 2019 sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
6 *
7 * The contents of this file may be used under the terms of the GNU
8 * General Public License Version 2, provided that the above copyright
9 * notice and this permission notice is included in all copies or
10 * substantial portions of the software.
11 *
12 */
13
14#include "../config.h"
15
16#ifdef HAVE_STDINT_H
17#include <stdint.h>
18#endif
19
20#include <getopt.h>
21#include <ctype.h>
22#include <signal.h>
23#include <stdio.h>
24#include <string.h>
25#include <stdlib.h>
26#include <unistd.h>
27#include <inttypes.h>
28#include <errno.h>
29#include <sys/types.h>
30#include <sys/ioctl.h>
31
32#include <osmocom/core/application.h>
33#include <osmocom/core/select.h>
34#include <osmocom/core/stats.h>
35#include <osmocom/core/rate_ctr.h>
36#include <osmocom/core/timer.h>
Pau Espin Pedrol9f1f7472022-11-02 19:52:19 +010037#include <osmocom/core/tdef.h>
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +020038#include <osmocom/core/utils.h>
39#include <osmocom/ctrl/control_if.h>
40#include <osmocom/ctrl/control_cmd.h>
41#include <osmocom/ctrl/control_vty.h>
42#include <osmocom/ctrl/ports.h>
43#include <osmocom/vty/telnet_interface.h>
44#include <osmocom/vty/logging.h>
45#include <osmocom/vty/stats.h>
46#include <osmocom/vty/ports.h>
47#include <osmocom/vty/command.h>
48#include <osmocom/vty/misc.h>
Pau Espin Pedrolaedae4c2020-08-18 12:44:54 +020049#include <osmocom/vty/cpu_sched_vty.h>
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +020050
51#include "ggsn.h"
52
53void *tall_ggsn_ctx;
54
55static int end = 0;
56static int daemonize = 0;
57struct ctrl_handle *g_ctrlh;
58
59struct ul255_t qos;
60struct ul255_t apn;
61
62static char *config_file = "osmo-ggsn.cfg";
63
Pau Espin Pedrol9f1f7472022-11-02 19:52:19 +010064struct osmo_tdef_group ggsn_tdef_group[] = {
65 {.name = "gtp", .tdefs = gtp_T_defs, .desc = "GTP (libgtp) timers" },
66 { }
67};
68
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +020069/* To exit gracefully. Used with GCC compilation flag -pg and gprof */
70static void signal_handler(int s)
71{
72 LOGP(DGGSN, LOGL_NOTICE, "signal %d received\n", s);
73 switch (s) {
74 case SIGINT:
75 case SIGTERM:
76 LOGP(DGGSN, LOGL_NOTICE, "SIGINT received, shutting down\n");
77 end = 1;
78 break;
79 case SIGABRT:
Pau Espin Pedrol12304c02020-11-25 18:49:16 +010080 /* in case of abort, we want to obtain a talloc report and
81 * then run default SIGABRT handler, who will generate coredump
82 * and abort the process. abort() should do this for us after we
83 * return, but program wouldn't exit if an external SIGABRT is
84 * received.
85 */
86 talloc_report(tall_vty_ctx, stderr);
87 talloc_report_full(tall_ggsn_ctx, stderr);
88 signal(SIGABRT, SIG_DFL);
89 raise(SIGABRT);
90 break;
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +020091 case SIGUSR1:
92 talloc_report(tall_vty_ctx, stderr);
93 talloc_report_full(tall_ggsn_ctx, stderr);
94 break;
95 case SIGUSR2:
96 talloc_report_full(tall_vty_ctx, stderr);
97 break;
98 default:
99 break;
100 }
101}
102
103static void print_usage()
104{
105 printf("Usage: osmo-ggsn [-h] [-D] [-c configfile] [-V]\n");
106}
107
108static void print_help()
109{
110 printf( " Some useful help...\n"
111 " -h --help This help text\n"
112 " -D --daemonize Fork the process into a background daemon\n"
113 " -c --config-file filename The config file to use\n"
114 " -V --version Print the version of OsmoGGSN\n"
115 );
Harald Welte67a3c832021-02-23 17:07:03 +0100116
117 printf("\nVTY reference generation:\n");
118 printf(" --vty-ref-mode MODE VTY reference generation mode (e.g. 'expert').\n");
119 printf(" --vty-ref-xml Generate the VTY reference XML output and exit.\n");
120}
121
122static void handle_long_options(const char *prog_name, const int long_option)
123{
124 static int vty_ref_mode = VTY_REF_GEN_MODE_DEFAULT;
125
126 switch (long_option) {
127 case 1:
128 vty_ref_mode = get_string_value(vty_ref_gen_mode_names, optarg);
129 if (vty_ref_mode < 0) {
130 fprintf(stderr, "%s: Unknown VTY reference generation "
131 "mode '%s'\n", prog_name, optarg);
132 exit(2);
133 }
134 break;
135 case 2:
136 fprintf(stderr, "Generating the VTY reference in mode '%s' (%s)\n",
137 get_value_string(vty_ref_gen_mode_names, vty_ref_mode),
138 get_value_string(vty_ref_gen_mode_desc, vty_ref_mode));
139 vty_dump_xml_ref_mode(stdout, (enum vty_ref_gen_mode) vty_ref_mode);
140 exit(0);
141 default:
142 fprintf(stderr, "%s: error parsing cmdline options\n", prog_name);
143 exit(2);
144 }
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +0200145}
146
147static void handle_options(int argc, char **argv)
148{
149 while (1) {
150 int option_index = 0, c;
Harald Welte67a3c832021-02-23 17:07:03 +0100151 static int long_option = 0;
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +0200152 static struct option long_options[] = {
153 { "help", 0, 0, 'h' },
154 { "daemonize", 0, 0, 'D' },
155 { "config-file", 1, 0, 'c' },
156 { "version", 0, 0, 'V' },
Harald Welte67a3c832021-02-23 17:07:03 +0100157 { "vty-ref-mode", 1, &long_option, 1 },
158 { "vty-ref-xml", 0, &long_option, 2 },
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +0200159 { 0, 0, 0, 0 }
160 };
161
162 c = getopt_long(argc, argv, "hdc:V", long_options, &option_index);
163 if (c == -1)
164 break;
165
166 switch (c) {
Harald Welte67a3c832021-02-23 17:07:03 +0100167 case 0:
168 handle_long_options(argv[0], long_option);
169 break;
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +0200170 case 'h':
171 print_usage();
172 print_help();
173 exit(0);
174 case 'D':
175 daemonize = 1;
176 break;
177 case 'c':
178 config_file = optarg;
179 break;
180 case 'V':
181 print_version(1);
182 exit(0);
183 break;
184 }
185 }
186}
187
188int main(int argc, char **argv)
189{
190 struct ggsn_ctx *ggsn;
191 int rc;
192
193 tall_ggsn_ctx = talloc_named_const(NULL, 0, "OsmoGGSN");
194 msgb_talloc_ctx_init(tall_ggsn_ctx, 0);
195 g_vty_info.tall_ctx = tall_ggsn_ctx;
196
197 /* Handle keyboard interrupt SIGINT */
198 signal(SIGINT, &signal_handler);
199 signal(SIGTERM, &signal_handler);
200 signal(SIGABRT, &signal_handler);
201 signal(SIGUSR1, &signal_handler);
202 signal(SIGUSR2, &signal_handler);
203
204 osmo_init_ignore_signals();
205 osmo_init_logging2(tall_ggsn_ctx, &log_info);
206 osmo_stats_init(tall_ggsn_ctx);
207
208 vty_init(&g_vty_info);
209 logging_vty_add_cmds();
210 osmo_talloc_vty_add_cmds();
211 osmo_stats_vty_add_cmds();
212 ggsn_vty_init();
213 ctrl_vty_init(tall_ggsn_ctx);
Pau Espin Pedrolaedae4c2020-08-18 12:44:54 +0200214 osmo_cpu_sched_vty_init(tall_ggsn_ctx);
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +0200215
216 handle_options(argc, argv);
217
218 rate_ctr_init(tall_ggsn_ctx);
219
220 rc = vty_read_config_file(config_file, NULL);
221 if (rc < 0) {
222 fprintf(stderr, "Failed to open config file: '%s'\n", config_file);
223 exit(2);
224 }
225
arehbein97f60e32022-12-19 21:28:50 +0100226 rc = telnet_init_default(tall_ggsn_ctx, NULL, OSMO_VTY_PORT_GGSN);
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +0200227 if (rc < 0)
228 exit(1);
229
Maxa727e6e2022-12-17 21:14:57 +0300230 g_ctrlh = ctrl_interface_setup(NULL, OSMO_CTRL_PORT_GGSN, NULL);
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +0200231 if (!g_ctrlh) {
232 LOGP(DGGSN, LOGL_ERROR, "Failed to create CTRL interface.\n");
233 exit(1);
234 }
235
236 if (daemonize) {
237 rc = osmo_daemonize();
238 if (rc < 0) {
239 perror("Error during daemonize");
240 exit(1);
241 }
242 }
243
244#if 0
245 /* qos */
246 qos.l = 3;
247 qos.v[2] = (args_info.qos_arg) & 0xff;
248 qos.v[1] = ((args_info.qos_arg) >> 8) & 0xff;
249 qos.v[0] = ((args_info.qos_arg) >> 16) & 0xff;
250#endif
251
252 /* Main select loop */
253 while (!end) {
254 osmo_select_main(0);
255 }
256
257 llist_for_each_entry(ggsn, &g_ggsn_list, list)
258 ggsn_stop(ggsn);
259
260 return 0;
261}