Mercurial > hg > freeDiameter
comparison freeDiameterd/main.c @ 1339:e70ce64ce689
freeDiameterd: support syslog() logging.
Written for Effortel Technologies SA, published with their consent.
author | Thomas Klausner <tk@giga.or.at> |
---|---|
date | Tue, 09 Apr 2019 15:49:17 +0200 |
parents | 84a3c9c4b834 |
children | de90cf7f381e |
comparison
equal
deleted
inserted
replaced
1338:f1b65381c1e7 | 1339:e70ce64ce689 |
---|---|
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * | 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * |
32 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * | 32 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * |
33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * | 33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * |
34 *********************************************************************************************************/ | 34 *********************************************************************************************************/ |
35 | 35 |
36 #if defined(__GLIBC__) | |
37 #define _BSD_SOURCE /* for vsyslog */ | |
38 #endif | |
39 | |
36 #include <freeDiameter/freeDiameter-host.h> | 40 #include <freeDiameter/freeDiameter-host.h> |
37 #include <freeDiameter/libfdcore.h> | 41 #include <freeDiameter/libfdcore.h> |
38 | 42 |
39 #include <signal.h> | 43 #include <signal.h> |
40 #include <getopt.h> | 44 #include <getopt.h> |
41 #include <locale.h> | 45 #include <locale.h> |
42 | 46 #include <syslog.h> |
47 #include <stdarg.h> | |
43 | 48 |
44 /* forward declarations */ | 49 /* forward declarations */ |
45 static int main_cmdline(int argc, char *argv[]); | 50 static int main_cmdline(int argc, char *argv[]); |
46 static void * catch_signals(void * arg); | 51 static void * catch_signals(void * arg); |
47 static pthread_t signals_thr; | 52 static pthread_t signals_thr; |
53 static void fd_gnutls_debug(int level, const char * str) { | 58 static void fd_gnutls_debug(int level, const char * str) { |
54 fd_log_debug(" [gnutls:%d] %s", level, str); | 59 fd_log_debug(" [gnutls:%d] %s", level, str); |
55 } | 60 } |
56 | 61 |
57 | 62 |
63 static void syslog_logger(int loglevel, const char * format, va_list args) | |
64 { | |
65 int level; | |
66 | |
67 switch (loglevel) { | |
68 case FD_LOG_NOTICE: | |
69 level = LOG_NOTICE; | |
70 break; | |
71 case FD_LOG_ERROR: | |
72 level = LOG_ERR; | |
73 break; | |
74 case FD_LOG_FATAL: | |
75 level = LOG_CRIT; | |
76 break; | |
77 default: | |
78 /* fallthrough */ | |
79 case FD_LOG_DEBUG: | |
80 /* some systems log LOG_DEBUG to a file; but | |
81 * freeDiameter debug output is too verbose */ | |
82 return; | |
83 #if 0 | |
84 level = LOG_DEBUG; | |
85 break; | |
86 #endif | |
87 } | |
88 | |
89 vsyslog(level, format, args); | |
90 } | |
91 | |
92 | |
58 /* freeDiameter starting point */ | 93 /* freeDiameter starting point */ |
59 int main(int argc, char * argv[]) | 94 int main(int argc, char * argv[]) |
60 { | 95 { |
61 int ret; | 96 int ret; |
62 sigset_t sig_all; | 97 sigset_t sig_all; |
63 | 98 |
64 /* Block all signals from the current thread and all its future children -- we will catch everything in catch_signals */ | 99 /* Block all signals from the current thread and all its future children -- we will catch everything in catch_signals */ |
65 sigfillset(&sig_all); | 100 sigfillset(&sig_all); |
66 ret = pthread_sigmask(SIG_BLOCK, &sig_all, NULL); | 101 ret = pthread_sigmask(SIG_BLOCK, &sig_all, NULL); |
67 ASSERT(ret == 0); | 102 ASSERT(ret == 0); |
68 | 103 |
69 /* Parse the command-line */ | 104 /* Parse the command-line */ |
70 ret = main_cmdline(argc, argv); | 105 ret = main_cmdline(argc, argv); |
71 if (ret != 0) { | 106 if (ret != 0) { |
72 return ret; | 107 return ret; |
73 } | 108 } |
74 | 109 |
75 /* Initialize the core library */ | 110 /* Initialize the core library */ |
76 ret = fd_core_initialize(); | 111 ret = fd_core_initialize(); |
77 if (ret != 0) { | 112 if (ret != 0) { |
78 fprintf(stderr, "An error occurred during freeDiameter core library initialization.\n"); | 113 fprintf(stderr, "An error occurred during freeDiameter core library initialization.\n"); |
79 return ret; | 114 return ret; |
80 } | 115 } |
81 | 116 |
82 /* Set gnutls debug level ? */ | 117 /* Set gnutls debug level ? */ |
83 if (gnutls_debug) { | 118 if (gnutls_debug) { |
84 gnutls_global_set_log_function((gnutls_log_func)fd_gnutls_debug); | 119 gnutls_global_set_log_function((gnutls_log_func)fd_gnutls_debug); |
85 gnutls_global_set_log_level (gnutls_debug); | 120 gnutls_global_set_log_level (gnutls_debug); |
86 TRACE_DEBUG(INFO, "Enabled GNUTLS debug at level %d", gnutls_debug); | 121 TRACE_DEBUG(INFO, "Enabled GNUTLS debug at level %d", gnutls_debug); |
87 } | 122 } |
88 | 123 |
89 /* Parse the configuration file */ | 124 /* Parse the configuration file */ |
90 CHECK_FCT_DO( fd_core_parseconf(conffile), goto error ); | 125 CHECK_FCT_DO( fd_core_parseconf(conffile), goto error ); |
91 | 126 |
92 /* Start the servers */ | 127 /* Start the servers */ |
93 CHECK_FCT_DO( fd_core_start(), goto error ); | 128 CHECK_FCT_DO( fd_core_start(), goto error ); |
94 | 129 |
95 /* Allow SIGINT and SIGTERM from this point to terminate the application */ | 130 /* Allow SIGINT and SIGTERM from this point to terminate the application */ |
96 CHECK_POSIX_DO( pthread_create(&signals_thr, NULL, catch_signals, NULL), goto error ); | 131 CHECK_POSIX_DO( pthread_create(&signals_thr, NULL, catch_signals, NULL), goto error ); |
97 | 132 |
98 TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon initialized."); | 133 TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon initialized."); |
99 | 134 |
100 /* Now, just wait for termination */ | 135 /* Now, just wait for termination */ |
101 CHECK_FCT( fd_core_wait_shutdown_complete() ); | 136 CHECK_FCT( fd_core_wait_shutdown_complete() ); |
102 | 137 |
103 /* Just in case it was not the result of a signal, we cancel signals_thr */ | 138 /* Just in case it was not the result of a signal, we cancel signals_thr */ |
104 fd_thr_term(&signals_thr); | 139 fd_thr_term(&signals_thr); |
105 | 140 |
106 return 0; | 141 return 0; |
107 error: | 142 error: |
108 CHECK_FCT_DO( fd_core_shutdown(), ); | 143 CHECK_FCT_DO( fd_core_shutdown(), ); |
109 CHECK_FCT( fd_core_wait_shutdown_complete() ); | 144 CHECK_FCT( fd_core_wait_shutdown_complete() ); |
110 fd_thr_term(&signals_thr); | 145 fd_thr_term(&signals_thr); |
111 return -1; | 146 return -1; |
112 } | 147 } |
135 " used for Authentication, Authorization, and Accounting (AAA).\n"); | 170 " used for Authentication, Authorization, and Accounting (AAA).\n"); |
136 printf("\nUsage: " FD_PROJECT_BINARY " [OPTIONS]...\n"); | 171 printf("\nUsage: " FD_PROJECT_BINARY " [OPTIONS]...\n"); |
137 printf( " -h, --help Print help and exit\n" | 172 printf( " -h, --help Print help and exit\n" |
138 " -V, --version Print version and exit\n" | 173 " -V, --version Print version and exit\n" |
139 " -c, --config=filename Read configuration from this file instead of the \n" | 174 " -c, --config=filename Read configuration from this file instead of the \n" |
140 " default location (" DEFAULT_CONF_PATH "/" FD_DEFAULT_CONF_FILENAME ").\n"); | 175 " default location (" DEFAULT_CONF_PATH "/" FD_DEFAULT_CONF_FILENAME ").\n" |
176 " -s, --syslog Write log output to syslog (instead of stdout)\n"); | |
141 printf( "\nDebug:\n" | 177 printf( "\nDebug:\n" |
142 " These options are mostly useful for developers\n" | 178 " These options are mostly useful for developers\n" |
143 " -l, --dbglocale Set the locale for error messages\n" | 179 " -l, --dbglocale Set the locale for error messages\n" |
144 " -d, --debug Increase verbosity of debug messages if default logger is used\n" | 180 " -d, --debug Increase verbosity of debug messages if default logger is used\n" |
145 " -q, --quiet Decrease verbosity if default logger is used\n" | 181 " -q, --quiet Decrease verbosity if default logger is used\n" |
153 static int main_cmdline(int argc, char *argv[]) | 189 static int main_cmdline(int argc, char *argv[]) |
154 { | 190 { |
155 int c; | 191 int c; |
156 int option_index = 0; | 192 int option_index = 0; |
157 char * locale; | 193 char * locale; |
158 | 194 |
159 struct option long_options[] = { | 195 struct option long_options[] = { |
160 { "help", no_argument, NULL, 'h' }, | 196 { "help", no_argument, NULL, 'h' }, |
161 { "version", no_argument, NULL, 'V' }, | 197 { "version", no_argument, NULL, 'V' }, |
162 { "config", required_argument, NULL, 'c' }, | 198 { "config", required_argument, NULL, 'c' }, |
199 { "syslog", no_argument, NULL, 's' }, | |
163 { "debug", no_argument, NULL, 'd' }, | 200 { "debug", no_argument, NULL, 'd' }, |
164 { "quiet", no_argument, NULL, 'q' }, | 201 { "quiet", no_argument, NULL, 'q' }, |
165 { "dbglocale", optional_argument, NULL, 'l' }, | 202 { "dbglocale", optional_argument, NULL, 'l' }, |
166 { "dbg_func", required_argument, NULL, 'f' }, | 203 { "dbg_func", required_argument, NULL, 'f' }, |
167 { "dbg_file", required_argument, NULL, 'F' }, | 204 { "dbg_file", required_argument, NULL, 'F' }, |
168 { "dbg_gnutls", required_argument, NULL, 'g' }, | 205 { "dbg_gnutls", required_argument, NULL, 'g' }, |
169 { NULL, 0, NULL, 0 } | 206 { NULL, 0, NULL, 0 } |
170 }; | 207 }; |
171 | 208 |
172 /* Loop on arguments */ | 209 /* Loop on arguments */ |
173 while (1) { | 210 while (1) { |
174 c = getopt_long (argc, argv, "hVc:dql:f:F:g:", long_options, &option_index); | 211 c = getopt_long (argc, argv, "hVc:dql:f:F:g:s", long_options, &option_index); |
175 if (c == -1) | 212 if (c == -1) |
176 break; /* Exit from the loop. */ | 213 break; /* Exit from the loop. */ |
177 | 214 |
178 switch (c) { | 215 switch (c) { |
179 case 'h': /* Print help and exit. */ | 216 case 'h': /* Print help and exit. */ |
180 main_help(); | 217 main_help(); |
181 exit(0); | 218 exit(0); |
182 | 219 |
197 if (!locale) { | 234 if (!locale) { |
198 fprintf(stderr, "Unable to set locale (%s)\n", optarg); | 235 fprintf(stderr, "Unable to set locale (%s)\n", optarg); |
199 return EINVAL; | 236 return EINVAL; |
200 } | 237 } |
201 break; | 238 break; |
202 | 239 |
203 case 'd': /* Increase verbosity of debug messages. */ | 240 case 'd': /* Increase verbosity of debug messages. */ |
204 fd_g_debug_lvl--; | 241 fd_g_debug_lvl--; |
205 break; | 242 break; |
206 | 243 |
207 case 'f': /* Full debug for the function with this name. */ | 244 case 'f': /* Full debug for the function with this name. */ |
208 #ifdef DEBUG | 245 #ifdef DEBUG |
209 fd_debug_one_function = optarg; | 246 fd_debug_one_function = optarg; |
210 fd_g_debug_lvl = FD_LOG_DEBUG; | 247 fd_g_debug_lvl = FD_LOG_DEBUG; |
211 #else /* DEBUG */ | 248 #else /* DEBUG */ |
212 fprintf(stderr, "Error: must compile with DEBUG support to use --dbg_func feature!\n"); | 249 fprintf(stderr, "Error: must compile with DEBUG support to use --dbg_func feature!\n"); |
213 return EINVAL; | 250 return EINVAL; |
214 #endif /* DEBUG */ | 251 #endif /* DEBUG */ |
215 break; | 252 break; |
216 | 253 |
217 case 'F': /* Full debug for the file with this name. */ | 254 case 'F': /* Full debug for the file with this name. */ |
218 #ifdef DEBUG | 255 #ifdef DEBUG |
219 fd_debug_one_file = basename(optarg); | 256 fd_debug_one_file = basename(optarg); |
220 fd_g_debug_lvl = FD_LOG_DEBUG; | 257 fd_g_debug_lvl = FD_LOG_DEBUG; |
221 #else /* DEBUG */ | 258 #else /* DEBUG */ |
222 fprintf(stderr, "Error: must compile with DEBUG support to use --dbg_file feature!\n"); | 259 fprintf(stderr, "Error: must compile with DEBUG support to use --dbg_file feature!\n"); |
223 return EINVAL; | 260 return EINVAL; |
224 #endif /* DEBUG */ | 261 #endif /* DEBUG */ |
225 break; | 262 break; |
226 | 263 |
227 case 'g': /* Set a debug level and function for GNU TLS calls. */ | 264 case 'g': /* Set a debug level and function for GNU TLS calls. */ |
228 gnutls_debug = (int)atoi(optarg); | 265 gnutls_debug = (int)atoi(optarg); |
229 break; | 266 break; |
230 | 267 |
231 case 'q': /* Decrease verbosity then remove debug messages. */ | 268 case 'q': /* Decrease verbosity then remove debug messages. */ |
232 fd_g_debug_lvl++; | 269 fd_g_debug_lvl++; |
270 break; | |
271 | |
272 case 's': /* Write log data using syslog(3) */ | |
273 if (fd_log_handler_register(syslog_logger) != 0) { | |
274 fprintf(stderr, "Cannot initialize syslog logger\n"); | |
275 return EINVAL; | |
276 } | |
233 break; | 277 break; |
234 | 278 |
235 case '?': /* Invalid option. */ | 279 case '?': /* Invalid option. */ |
236 /* `getopt_long' already printed an error message. */ | 280 /* `getopt_long' already printed an error message. */ |
237 fprintf(stderr, "getopt_long found an invalid character\n"); | 281 fprintf(stderr, "getopt_long found an invalid character\n"); |
241 fprintf(stderr, "A command-line option is missing in parser: %c\n", c); | 285 fprintf(stderr, "A command-line option is missing in parser: %c\n", c); |
242 ASSERT(0); | 286 ASSERT(0); |
243 return EINVAL; | 287 return EINVAL; |
244 } | 288 } |
245 } | 289 } |
246 | 290 |
247 return 0; | 291 return 0; |
248 } | 292 } |
249 | 293 |
250 /* Handle some signals */ | 294 /* Handle some signals */ |
251 static void * catch_signals(void * arg) | 295 static void * catch_signals(void * arg) |
252 { | 296 { |
253 sigset_t ss; | 297 sigset_t ss; |
254 fd_log_threadname ( "signals catcher" ); | 298 fd_log_threadname ( "signals catcher" ); |
255 | 299 |
256 sigemptyset(&ss); | 300 sigemptyset(&ss); |
257 | 301 |
258 /* Signals that terminate the daemon */ | 302 /* Signals that terminate the daemon */ |
259 sigaddset(&ss, SIGTERM); | 303 sigaddset(&ss, SIGTERM); |
260 sigaddset(&ss, SIGINT); | 304 sigaddset(&ss, SIGINT); |
261 | 305 |
262 /* Signals that send an event */ | 306 /* Signals that send an event */ |
263 sigaddset(&ss, SIGUSR1); | 307 sigaddset(&ss, SIGUSR1); |
264 sigaddset(&ss, SIGUSR2); | 308 sigaddset(&ss, SIGUSR2); |
265 | 309 |
266 /* We unblock all other signals, so that their default handler is used (such as SIGTSTP) */ | 310 /* We unblock all other signals, so that their default handler is used (such as SIGTSTP) */ |
267 CHECK_SYS_DO( pthread_sigmask( SIG_SETMASK, &ss, NULL ), goto out ); | 311 CHECK_SYS_DO( pthread_sigmask( SIG_SETMASK, &ss, NULL ), goto out ); |
268 | 312 |
269 /* Now loop on the reception of the signal */ | 313 /* Now loop on the reception of the signal */ |
270 while (1) { | 314 while (1) { |
271 int sig, *ps; | 315 int sig, *ps; |
272 | 316 |
273 /* Wait to receive the next signal */ | 317 /* Wait to receive the next signal */ |
274 CHECK_POSIX_DO( sigwait(&ss, &sig), break ); | 318 CHECK_POSIX_DO( sigwait(&ss, &sig), break ); |
275 | 319 |
276 TRACE_DEBUG(FULL, "Signal %d caught", sig); | 320 TRACE_DEBUG(FULL, "Signal %d caught", sig); |
277 | 321 |
278 switch (sig) { | 322 switch (sig) { |
279 case SIGUSR1: | 323 case SIGUSR1: |
280 case SIGUSR2: | 324 case SIGUSR2: |
281 CHECK_MALLOC_DO( ps = malloc(sizeof(int)), goto out); | 325 CHECK_MALLOC_DO( ps = malloc(sizeof(int)), goto out); |
282 *ps = sig; | 326 *ps = sig; |
283 CHECK_FCT_DO( fd_event_send(fd_g_config->cnf_main_ev, FDEV_TRIGGER, sizeof(int), ps), goto out ); | 327 CHECK_FCT_DO( fd_event_send(fd_g_config->cnf_main_ev, FDEV_TRIGGER, sizeof(int), ps), goto out ); |
284 break; | 328 break; |
285 | 329 |
286 case SIGINT: | 330 case SIGINT: |
287 case SIGTERM: | 331 case SIGTERM: |
288 CHECK_FCT_DO( fd_core_shutdown(), goto out ); | 332 CHECK_FCT_DO( fd_core_shutdown(), goto out ); |
289 | 333 |
290 } | 334 } |
291 } | 335 } |
292 out: | 336 out: |
293 /* Better way to handle this ? */ | 337 /* Better way to handle this ? */ |
294 ASSERT(0); | 338 ASSERT(0); |
295 return NULL; | 339 return NULL; |
296 } | 340 } |