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 }
"Welcome to our mercurial repository"