main.c 10.1 KB
Newer Older
Sebastien Decugis's avatar
Sebastien Decugis committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*********************************************************************************************************
* Software License Agreement (BSD License)                                                               *
* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
*													 *
* Copyright (c) 2009, WIDE Project and NICT								 *
* All rights reserved.											 *
* 													 *
* Redistribution and use of this software in source and binary forms, with or without modification, are  *
* permitted provided that the following conditions are met:						 *
* 													 *
* * Redistributions of source code must retain the above 						 *
*   copyright notice, this list of conditions and the 							 *
*   following disclaimer.										 *
*    													 *
* * Redistributions in binary form must reproduce the above 						 *
*   copyright notice, this list of conditions and the 							 *
*   following disclaimer in the documentation and/or other						 *
*   materials provided with the distribution.								 *
* 													 *
* * Neither the name of the WIDE Project or NICT nor the 						 *
*   names of its contributors may be used to endorse or 						 *
*   promote products derived from this software without 						 *
*   specific prior written permission of WIDE Project and 						 *
*   NICT.												 *
* 													 *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
*********************************************************************************************************/

36
#include "fD.h"
Sebastien Decugis's avatar
Sebastien Decugis committed
37

Sebastien Decugis's avatar
Sebastien Decugis committed
38
39
#include <signal.h>
#include <getopt.h>
Sebastien Decugis's avatar
Sebastien Decugis committed
40
#include <locale.h>
41
#include <gcrypt.h>
Sebastien Decugis's avatar
Sebastien Decugis committed
42

43
44
45
/* forward declarations */
static void * sig_hdl(void * arg);
static int main_cmdline(int argc, char *argv[]);
46
47
static void main_version(void);
static void main_help( void );
48
49
50
51
52

/* The static configuration structure */
static struct fd_config conf;
struct fd_config * fd_g_config = &conf;

Sebastien Decugis's avatar
Sebastien Decugis committed
53
54
GCRY_THREAD_OPTION_PTHREAD_IMPL;

55
56
57
58
59
60
61
62
63
64
65
66
67
/* freeDiameter starting point */
int main(int argc, char * argv[])
{
	int ret;
	pthread_t sig_th;
	sigset_t sig_all;
	
	memset(fd_g_config, 0, sizeof(struct fd_config));
	sigfillset(&sig_all);
	CHECK_POSIX(  pthread_sigmask(SIG_BLOCK, &sig_all, NULL)  );
	
	/* Initialize the library */
	CHECK_FCT( fd_lib_init() );
Sebastien Decugis's avatar
Sebastien Decugis committed
68
	TRACE_DEBUG(INFO, "libfreeDiameter initialized.");
69
70
71
72
73
74
75
76
77
78
	
	/* Name this thread */
	fd_log_threadname("Main");
	
	/* Initialize the config */
	CHECK_FCT( fd_conf_init() );

	/* Parse the command-line */
	CHECK_FCT(  main_cmdline(argc, argv)  );
	
Sebastien Decugis's avatar
Sebastien Decugis committed
79
	/* Initialize gcrypt and gnutls */
80
	(void) gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
Sebastien Decugis's avatar
Sebastien Decugis committed
81
	(void) gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
Sebastien Decugis's avatar
Sebastien Decugis committed
82
83
84
85
86
87
88
89
	CHECK_GNUTLS_DO( gnutls_global_init(), return EINVAL );
	if ( ! gnutls_check_version(GNUTLS_VERSION) ) {
		fprintf(stderr, "The GNUTLS library is too old; found '%s', need '" GNUTLS_VERSION "'\n", gnutls_check_version(NULL));
		return EINVAL;
	} else {
		TRACE_DEBUG(INFO, "GNUTLS library '%s' initialized.", gnutls_check_version(NULL));
	}
	
90
91
92
93
94
95
96
97
98
	/* Allow SIGINT and SIGTERM from this point */
	CHECK_POSIX(  pthread_create(&sig_th, NULL, sig_hdl, NULL)  );
	
	/* Add definitions of the base protocol */
	CHECK_FCT( fd_dict_base_protocol(fd_g_config->cnf_dict) );
	
	/* Initialize other modules */
	CHECK_FCT(  fd_queues_init()  );
	CHECK_FCT(  fd_msg_init()  );
99
	CHECK_FCT(  fd_p_expi_init()  );
100
101
102
103
104
105
106
107
	
	/* Parse the configuration file */
	CHECK_FCT( fd_conf_parse() );
	
	/* Load the dynamic extensions */
	CHECK_FCT(  fd_ext_load()  );
	
	/* Start the peer state machines */
108
	CHECK_FCT( fd_psm_start() );
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
	
	/* Now, just wait for events */
	TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon initialized.");
	fd_conf_dump();
	while (1) {
		int code;
		CHECK_FCT_DO(  fd_event_get(fd_g_config->cnf_main_ev, &code, NULL),  break  );
		switch (code) {
			case FDEV_DUMP_DICT:
				fd_dict_dump(fd_g_config->cnf_dict);
				break;
			
			case FDEV_DUMP_EXT:
				fd_ext_dump();
				break;
			
			case FDEV_DUMP_QUEUES:
				fd_fifo_dump(0, "Incoming messages", fd_g_incoming, fd_msg_dump_walk);
				fd_fifo_dump(0, "Outgoing messages", fd_g_outgoing, fd_msg_dump_walk);
				fd_fifo_dump(0, "Local messages",    fd_g_local,    fd_msg_dump_walk);
				break;
			
			case FDEV_DUMP_CONFIG:
				fd_conf_dump();
				break;
			
135
			case FDEV_DUMP_PEERS:
136
				fd_peer_dump_list(FULL);
137
				break;
138
139
140
141
142
143
144
145
146
147
148
149
150
151
			
			case FDEV_TERMINATE:
				ret = 0;
				goto end;
			
			default:
				TRACE_DEBUG(INFO, "Unexpected event in the daemon (%d), ignored.\n", code);
		}
	}
	
end:
	TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon is stopping...");
	
	/* cleanups */
152
153
154
155
156
157
	TODO("Stop dispatch thread(s) properly (no cancel yet)");
	CHECK_FCT_DO( fd_peer_fini(), /* Stop all connections */ );
	TODO("Stop dispatch & routing threads");
	CHECK_FCT_DO( fd_ext_fini(), /* Cleaup all extensions */ );
	TODO("Cleanup queues (dump all remaining messages ?)");
	
158
159
	CHECK_FCT_DO( fd_thr_term(&sig_th), /* continue */ );
	
Sebastien Decugis's avatar
Sebastien Decugis committed
160
161
	gnutls_global_deinit();
	
162
163
	return ret;
}
Sebastien Decugis's avatar
Sebastien Decugis committed
164

165
const char * fd_ev_str(int event)
Sebastien Decugis's avatar
Sebastien Decugis committed
166
{
167
168
169
170
171
172
173
174
175
176
177
178
179
180
	switch (event) {
	#define case_str( _val )\
		case _val : return #_val
		case_str(FDEV_TERMINATE);
		case_str(FDEV_DUMP_DICT);
		case_str(FDEV_DUMP_EXT);
		case_str(FDEV_DUMP_QUEUES);
		case_str(FDEV_DUMP_CONFIG);
		case_str(FDEV_DUMP_PEERS);
		
		default:
			TRACE_DEBUG(FULL, "Unknown event : %d", event);
			return "Unknown event";
	}
Sebastien Decugis's avatar
Sebastien Decugis committed
181
182
183
184
185
186
187
}

/* Parse the command-line */
static int main_cmdline(int argc, char *argv[])
{
	int c;
	int option_index = 0;
Sebastien Decugis's avatar
Sebastien Decugis committed
188
	char * locale;
Sebastien Decugis's avatar
Sebastien Decugis committed
189
190
	
      	struct option long_options[] = {
Sebastien Decugis's avatar
Sebastien Decugis committed
191
192
193
194
195
196
197
		{ "help",	no_argument, 		NULL, 'h' },
		{ "version",	no_argument, 		NULL, 'V' },
		{ "config",	required_argument, 	NULL, 'c' },
		{ "debug",	no_argument, 		NULL, 'd' },
		{ "quiet",	no_argument, 		NULL, 'q' },
		{ "dbglocale",	optional_argument, 	NULL, 'l' },
		{ NULL,		0, 			NULL, 0 }
Sebastien Decugis's avatar
Sebastien Decugis committed
198
199
200
201
202
203
	};
	
	TRACE_ENTRY("%d %p", argc, argv);
	
	/* Loop on arguments */
	while (1) {
Sebastien Decugis's avatar
Sebastien Decugis committed
204
		c = getopt_long (argc, argv, "hVc:dql:", long_options, &option_index);
Sebastien Decugis's avatar
Sebastien Decugis committed
205
206
207
208
209
210
211
212
213
214
215
216
217
218
		if (c == -1) 
			break;	/* Exit from the loop.  */
		
		switch (c) {
			case 'h':	/* Print help and exit.  */
				main_help();
				exit(0);

			case 'V':	/* Print version and exit.  */
				main_version();
				exit(0);

			case 'c':	/* Read configuration from this file instead of the default location..  */
				CHECK_PARAMS( optarg );
219
				fd_g_config->cnf_file = optarg;
Sebastien Decugis's avatar
Sebastien Decugis committed
220
221
				break;

Sebastien Decugis's avatar
Sebastien Decugis committed
222
223
224
225
226
227
228
229
230
231
			case 'l':	/* Change the locale.  */
				locale = setlocale(LC_ALL, optarg?:"");
				if (locale) {
					TRACE_DEBUG(INFO, "Locale set to: %s", optarg ?: locale);
				} else {
					TRACE_DEBUG(INFO, "Unable to set locale (%s)", optarg);
					return EINVAL;
				}
				break;

Sebastien Decugis's avatar
Sebastien Decugis committed
232
233
234
235
236
237
238
239
240
241
			case 'd':	/* Increase verbosity of debug messages.  */
				fd_g_debug_lvl++;
				break;
				
			case 'q':	/* Decrease verbosity then remove debug messages.  */
				fd_g_debug_lvl--;
				break;

			case '?':	/* Invalid option.  */
				/* `getopt_long' already printed an error message.  */
Sebastien Decugis's avatar
Sebastien Decugis committed
242
				TRACE_DEBUG(INFO, "getopt_long found an invalid character");
Sebastien Decugis's avatar
Sebastien Decugis committed
243
244
245
				return EINVAL;

			default:	/* bug: option not considered.  */
Sebastien Decugis's avatar
Sebastien Decugis committed
246
				TRACE_DEBUG(INFO, "A command-line option is missing in parser: %c", c);
Sebastien Decugis's avatar
Sebastien Decugis committed
247
248
249
250
251
252
				ASSERT(0);
				return EINVAL;
		}
	}
		
	return 0;
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
}

/* Display package version */
static void main_version_core(void)
{
	printf("%s, version %d.%d.%d"
#ifdef HG_VERSION
		" (r%s"
# ifdef PACKAGE_HG_REVISION
		"/%s"
# endif /* PACKAGE_HG_VERSION */
		")"
#endif /* HG_VERSION */
		"\n", 
		FD_PROJECT_NAME, FD_PROJECT_VERSION_MAJOR, FD_PROJECT_VERSION_MINOR, FD_PROJECT_VERSION_REV
#ifdef HG_VERSION
		, HG_VERSION
# ifdef PACKAGE_HG_REVISION
		, PACKAGE_HG_REVISION
# endif /* PACKAGE_HG_VERSION */
#endif /* HG_VERSION */
		);
}

/* Display package version and general info */
static void main_version(void)
{
	main_version_core();
	printf( "%s\n", FD_PROJECT_COPYRIGHT);
	printf( "\nSee " FD_PROJECT_NAME " homepage at http://aaa.koganei.wide.ad.jp/\n"
		" for information, updates and bug reports on this software.\n");
}

/* Print command-line options */
static void main_help( void )
{
	main_version_core();
	printf(	"  This daemon is an implementation of the Diameter protocol\n"
		"  used for Authentication, Authorization, and Accounting (AAA).\n");
	printf("\nUsage:  " FD_PROJECT_BINARY " [OPTIONS]...\n");
	printf( "  -h, --help             Print help and exit\n"
  		"  -V, --version          Print version and exit\n"
  		"  -c, --config=filename  Read configuration from this file instead of the \n"
		"                           default location (%s).\n", DEFAULT_CONF_FILE);
 	printf( "\nDebug:\n"
  		"  These options are mostly useful for developers\n"
Sebastien Decugis's avatar
Sebastien Decugis committed
299
  		"  -l, --dbglocale        Set the locale for error messages\n"
300
301
  		"  -d, --debug            Increase verbosity of debug messages\n"
  		"  -q, --quiet            Decrease verbosity then remove debug messages\n");
Sebastien Decugis's avatar
Sebastien Decugis committed
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
}

#ifdef HAVE_SIGNALENT_H
const char *const signalstr[] = {
# include "signalent.h"
};
const int nsignalstr = sizeof signalstr / sizeof signalstr[0];
# define SIGNALSTR(sig) (((sig) < nsignalstr) ? signalstr[(sig)] : "unknown")
#else /* HAVE_SIGNALENT_H */
# define SIGNALSTR(sig) ("")
#endif /* HAVE_SIGNALENT_H */

/* signal handler */
static void * sig_hdl(void * arg)
{
	sigset_t sig_main;
	int sig = 0;
	
	TRACE_ENTRY();
	fd_log_threadname("Main signal handler");
	
	sigemptyset(&sig_main);
	sigaddset(&sig_main, SIGINT);
	sigaddset(&sig_main, SIGTERM);
	
	CHECK_SYS_DO(  sigwait(&sig_main, &sig), TRACE_DEBUG(INFO, "Error in sigwait function") );
	
	TRACE_DEBUG(INFO, "Received signal %s (%d), exiting", SIGNALSTR(sig), sig);
330
	CHECK_FCT_DO( fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, NULL), exit(2) );
Sebastien Decugis's avatar
Sebastien Decugis committed
331
332
333
	return NULL;
}