blob: 88c3f689c7a1be86a6052e3ceb5e5da0499dcaff [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>
37#include <osmocom/core/utils.h>
38#include <osmocom/ctrl/control_if.h>
39#include <osmocom/ctrl/control_cmd.h>
40#include <osmocom/ctrl/control_vty.h>
41#include <osmocom/ctrl/ports.h>
42#include <osmocom/vty/telnet_interface.h>
43#include <osmocom/vty/logging.h>
44#include <osmocom/vty/stats.h>
45#include <osmocom/vty/ports.h>
46#include <osmocom/vty/command.h>
47#include <osmocom/vty/misc.h>
Pau Espin Pedrolaedae4c2020-08-18 12:44:54 +020048#include <osmocom/vty/cpu_sched_vty.h>
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +020049
50#include "ggsn.h"
51
52void *tall_ggsn_ctx;
53
54static int end = 0;
55static int daemonize = 0;
56struct ctrl_handle *g_ctrlh;
57
58struct ul255_t qos;
59struct ul255_t apn;
60
61static char *config_file = "osmo-ggsn.cfg";
62
63/* To exit gracefully. Used with GCC compilation flag -pg and gprof */
64static void signal_handler(int s)
65{
66 LOGP(DGGSN, LOGL_NOTICE, "signal %d received\n", s);
67 switch (s) {
68 case SIGINT:
69 case SIGTERM:
70 LOGP(DGGSN, LOGL_NOTICE, "SIGINT received, shutting down\n");
71 end = 1;
72 break;
73 case SIGABRT:
Pau Espin Pedrol12304c02020-11-25 18:49:16 +010074 /* in case of abort, we want to obtain a talloc report and
75 * then run default SIGABRT handler, who will generate coredump
76 * and abort the process. abort() should do this for us after we
77 * return, but program wouldn't exit if an external SIGABRT is
78 * received.
79 */
80 talloc_report(tall_vty_ctx, stderr);
81 talloc_report_full(tall_ggsn_ctx, stderr);
82 signal(SIGABRT, SIG_DFL);
83 raise(SIGABRT);
84 break;
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +020085 case SIGUSR1:
86 talloc_report(tall_vty_ctx, stderr);
87 talloc_report_full(tall_ggsn_ctx, stderr);
88 break;
89 case SIGUSR2:
90 talloc_report_full(tall_vty_ctx, stderr);
91 break;
92 default:
93 break;
94 }
95}
96
97static void print_usage()
98{
99 printf("Usage: osmo-ggsn [-h] [-D] [-c configfile] [-V]\n");
100}
101
102static void print_help()
103{
104 printf( " Some useful help...\n"
105 " -h --help This help text\n"
106 " -D --daemonize Fork the process into a background daemon\n"
107 " -c --config-file filename The config file to use\n"
108 " -V --version Print the version of OsmoGGSN\n"
109 );
Harald Welte67a3c832021-02-23 17:07:03 +0100110
111 printf("\nVTY reference generation:\n");
112 printf(" --vty-ref-mode MODE VTY reference generation mode (e.g. 'expert').\n");
113 printf(" --vty-ref-xml Generate the VTY reference XML output and exit.\n");
114}
115
116static void handle_long_options(const char *prog_name, const int long_option)
117{
118 static int vty_ref_mode = VTY_REF_GEN_MODE_DEFAULT;
119
120 switch (long_option) {
121 case 1:
122 vty_ref_mode = get_string_value(vty_ref_gen_mode_names, optarg);
123 if (vty_ref_mode < 0) {
124 fprintf(stderr, "%s: Unknown VTY reference generation "
125 "mode '%s'\n", prog_name, optarg);
126 exit(2);
127 }
128 break;
129 case 2:
130 fprintf(stderr, "Generating the VTY reference in mode '%s' (%s)\n",
131 get_value_string(vty_ref_gen_mode_names, vty_ref_mode),
132 get_value_string(vty_ref_gen_mode_desc, vty_ref_mode));
133 vty_dump_xml_ref_mode(stdout, (enum vty_ref_gen_mode) vty_ref_mode);
134 exit(0);
135 default:
136 fprintf(stderr, "%s: error parsing cmdline options\n", prog_name);
137 exit(2);
138 }
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +0200139}
140
141static void handle_options(int argc, char **argv)
142{
143 while (1) {
144 int option_index = 0, c;
Harald Welte67a3c832021-02-23 17:07:03 +0100145 static int long_option = 0;
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +0200146 static struct option long_options[] = {
147 { "help", 0, 0, 'h' },
148 { "daemonize", 0, 0, 'D' },
149 { "config-file", 1, 0, 'c' },
150 { "version", 0, 0, 'V' },
Harald Welte67a3c832021-02-23 17:07:03 +0100151 { "vty-ref-mode", 1, &long_option, 1 },
152 { "vty-ref-xml", 0, &long_option, 2 },
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +0200153 { 0, 0, 0, 0 }
154 };
155
156 c = getopt_long(argc, argv, "hdc:V", long_options, &option_index);
157 if (c == -1)
158 break;
159
160 switch (c) {
Harald Welte67a3c832021-02-23 17:07:03 +0100161 case 0:
162 handle_long_options(argv[0], long_option);
163 break;
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +0200164 case 'h':
165 print_usage();
166 print_help();
167 exit(0);
168 case 'D':
169 daemonize = 1;
170 break;
171 case 'c':
172 config_file = optarg;
173 break;
174 case 'V':
175 print_version(1);
176 exit(0);
177 break;
178 }
179 }
180}
181
182int main(int argc, char **argv)
183{
184 struct ggsn_ctx *ggsn;
185 int rc;
186
187 tall_ggsn_ctx = talloc_named_const(NULL, 0, "OsmoGGSN");
188 msgb_talloc_ctx_init(tall_ggsn_ctx, 0);
189 g_vty_info.tall_ctx = tall_ggsn_ctx;
190
191 /* Handle keyboard interrupt SIGINT */
192 signal(SIGINT, &signal_handler);
193 signal(SIGTERM, &signal_handler);
194 signal(SIGABRT, &signal_handler);
195 signal(SIGUSR1, &signal_handler);
196 signal(SIGUSR2, &signal_handler);
197
198 osmo_init_ignore_signals();
199 osmo_init_logging2(tall_ggsn_ctx, &log_info);
200 osmo_stats_init(tall_ggsn_ctx);
201
202 vty_init(&g_vty_info);
203 logging_vty_add_cmds();
204 osmo_talloc_vty_add_cmds();
205 osmo_stats_vty_add_cmds();
206 ggsn_vty_init();
207 ctrl_vty_init(tall_ggsn_ctx);
Pau Espin Pedrolaedae4c2020-08-18 12:44:54 +0200208 osmo_cpu_sched_vty_init(tall_ggsn_ctx);
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +0200209
210 handle_options(argc, argv);
211
212 rate_ctr_init(tall_ggsn_ctx);
213
214 rc = vty_read_config_file(config_file, NULL);
215 if (rc < 0) {
216 fprintf(stderr, "Failed to open config file: '%s'\n", config_file);
217 exit(2);
218 }
219
220 rc = telnet_init_dynif(tall_ggsn_ctx, NULL, vty_get_bind_addr(), OSMO_VTY_PORT_GGSN);
221 if (rc < 0)
222 exit(1);
223
224 g_ctrlh = ctrl_interface_setup_dynip(NULL, ctrl_vty_get_bind_addr(),
225 OSMO_CTRL_PORT_GGSN, NULL);
226 if (!g_ctrlh) {
227 LOGP(DGGSN, LOGL_ERROR, "Failed to create CTRL interface.\n");
228 exit(1);
229 }
230
231 if (daemonize) {
232 rc = osmo_daemonize();
233 if (rc < 0) {
234 perror("Error during daemonize");
235 exit(1);
236 }
237 }
238
239#if 0
240 /* qos */
241 qos.l = 3;
242 qos.v[2] = (args_info.qos_arg) & 0xff;
243 qos.v[1] = ((args_info.qos_arg) >> 8) & 0xff;
244 qos.v[0] = ((args_info.qos_arg) >> 16) & 0xff;
245#endif
246
247 /* Main select loop */
248 while (!end) {
249 osmo_select_main(0);
250 }
251
252 llist_for_each_entry(ggsn, &g_ggsn_list, list)
253 ggsn_stop(ggsn);
254
255 return 0;
256}