blob: 81a8ab19c0c28bfc63d109fd474d4788d4ee9eec [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>
48
49#include "ggsn.h"
50
51void *tall_ggsn_ctx;
52
53static int end = 0;
54static int daemonize = 0;
55struct ctrl_handle *g_ctrlh;
56
57struct ul255_t qos;
58struct ul255_t apn;
59
60static char *config_file = "osmo-ggsn.cfg";
61
62/* To exit gracefully. Used with GCC compilation flag -pg and gprof */
63static void signal_handler(int s)
64{
65 LOGP(DGGSN, LOGL_NOTICE, "signal %d received\n", s);
66 switch (s) {
67 case SIGINT:
68 case SIGTERM:
69 LOGP(DGGSN, LOGL_NOTICE, "SIGINT received, shutting down\n");
70 end = 1;
71 break;
72 case SIGABRT:
73 case SIGUSR1:
74 talloc_report(tall_vty_ctx, stderr);
75 talloc_report_full(tall_ggsn_ctx, stderr);
76 break;
77 case SIGUSR2:
78 talloc_report_full(tall_vty_ctx, stderr);
79 break;
80 default:
81 break;
82 }
83}
84
85static void print_usage()
86{
87 printf("Usage: osmo-ggsn [-h] [-D] [-c configfile] [-V]\n");
88}
89
90static void print_help()
91{
92 printf( " Some useful help...\n"
93 " -h --help This help text\n"
94 " -D --daemonize Fork the process into a background daemon\n"
95 " -c --config-file filename The config file to use\n"
96 " -V --version Print the version of OsmoGGSN\n"
97 );
98}
99
100static void handle_options(int argc, char **argv)
101{
102 while (1) {
103 int option_index = 0, c;
104 static struct option long_options[] = {
105 { "help", 0, 0, 'h' },
106 { "daemonize", 0, 0, 'D' },
107 { "config-file", 1, 0, 'c' },
108 { "version", 0, 0, 'V' },
109 { 0, 0, 0, 0 }
110 };
111
112 c = getopt_long(argc, argv, "hdc:V", long_options, &option_index);
113 if (c == -1)
114 break;
115
116 switch (c) {
117 case 'h':
118 print_usage();
119 print_help();
120 exit(0);
121 case 'D':
122 daemonize = 1;
123 break;
124 case 'c':
125 config_file = optarg;
126 break;
127 case 'V':
128 print_version(1);
129 exit(0);
130 break;
131 }
132 }
133}
134
135int main(int argc, char **argv)
136{
137 struct ggsn_ctx *ggsn;
138 int rc;
139
140 tall_ggsn_ctx = talloc_named_const(NULL, 0, "OsmoGGSN");
141 msgb_talloc_ctx_init(tall_ggsn_ctx, 0);
142 g_vty_info.tall_ctx = tall_ggsn_ctx;
143
144 /* Handle keyboard interrupt SIGINT */
145 signal(SIGINT, &signal_handler);
146 signal(SIGTERM, &signal_handler);
147 signal(SIGABRT, &signal_handler);
148 signal(SIGUSR1, &signal_handler);
149 signal(SIGUSR2, &signal_handler);
150
151 osmo_init_ignore_signals();
152 osmo_init_logging2(tall_ggsn_ctx, &log_info);
153 osmo_stats_init(tall_ggsn_ctx);
154
155 vty_init(&g_vty_info);
156 logging_vty_add_cmds();
157 osmo_talloc_vty_add_cmds();
158 osmo_stats_vty_add_cmds();
159 ggsn_vty_init();
160 ctrl_vty_init(tall_ggsn_ctx);
161
162 handle_options(argc, argv);
163
164 rate_ctr_init(tall_ggsn_ctx);
165
166 rc = vty_read_config_file(config_file, NULL);
167 if (rc < 0) {
168 fprintf(stderr, "Failed to open config file: '%s'\n", config_file);
169 exit(2);
170 }
171
172 rc = telnet_init_dynif(tall_ggsn_ctx, NULL, vty_get_bind_addr(), OSMO_VTY_PORT_GGSN);
173 if (rc < 0)
174 exit(1);
175
176 g_ctrlh = ctrl_interface_setup_dynip(NULL, ctrl_vty_get_bind_addr(),
177 OSMO_CTRL_PORT_GGSN, NULL);
178 if (!g_ctrlh) {
179 LOGP(DGGSN, LOGL_ERROR, "Failed to create CTRL interface.\n");
180 exit(1);
181 }
182
183 if (daemonize) {
184 rc = osmo_daemonize();
185 if (rc < 0) {
186 perror("Error during daemonize");
187 exit(1);
188 }
189 }
190
191#if 0
192 /* qos */
193 qos.l = 3;
194 qos.v[2] = (args_info.qos_arg) & 0xff;
195 qos.v[1] = ((args_info.qos_arg) >> 8) & 0xff;
196 qos.v[0] = ((args_info.qos_arg) >> 16) & 0xff;
197#endif
198
199 /* Main select loop */
200 while (!end) {
201 osmo_select_main(0);
202 }
203
204 llist_for_each_entry(ggsn, &g_ggsn_list, list)
205 ggsn_stop(ggsn);
206
207 return 0;
208}