Navigation


source: freeDiameter/freeDiameter/main.c @ 25:67ca08d5bc48

Last change on this file since 25:67ca08d5bc48 was 25:67ca08d5bc48, checked in by Sebastien Decugis <sdecugis@nict.go.jp>, 11 years ago

Completed connection context files

File size: 10.4 KB
Line 
1/*********************************************************************************************************
2* Software License Agreement (BSD License)                                                               *
3* Author: Sebastien Decugis <sdecugis@nict.go.jp>                                                        *
4*                                                                                                        *
5* Copyright (c) 2009, WIDE Project and NICT                                                              *
6* All rights reserved.                                                                                   *
7*                                                                                                        *
8* Redistribution and use of this software in source and binary forms, with or without modification, are  *
9* permitted provided that the following conditions are met:                                              *
10*                                                                                                        *
11* * Redistributions of source code must retain the above                                                 *
12*   copyright notice, this list of conditions and the                                                    *
13*   following disclaimer.                                                                                *
14*                                                                                                        *
15* * Redistributions in binary form must reproduce the above                                              *
16*   copyright notice, this list of conditions and the                                                    *
17*   following disclaimer in the documentation and/or other                                               *
18*   materials provided with the distribution.                                                            *
19*                                                                                                        *
20* * Neither the name of the WIDE Project or NICT nor the                                                 *
21*   names of its contributors may be used to endorse or                                                  *
22*   promote products derived from this software without                                                  *
23*   specific prior written permission of WIDE Project and                                                *
24*   NICT.                                                                                                *
25*                                                                                                        *
26* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
27* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
28* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
29* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT     *
30* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS    *
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   *
33* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                                             *
34*********************************************************************************************************/
35
36#include "fD.h"
37
38#include <signal.h>
39#include <getopt.h>
40#include <locale.h>
41#include <gcrypt.h>
42
43/* forward declarations */
44static void * sig_hdl(void * arg);
45static int main_cmdline(int argc, char *argv[]);
46static void main_version(void);
47static void main_help( void );
48
49/* The static configuration structure */
50static struct fd_config conf;
51struct fd_config * fd_g_config = &conf;
52
53/* gcrypt functions to support posix threads */
54GCRY_THREAD_OPTION_PTHREAD_IMPL;
55
56/* freeDiameter starting point */
57int main(int argc, char * argv[])
58{
59        int ret;
60        pthread_t sig_th;
61        sigset_t sig_all;
62       
63        memset(fd_g_config, 0, sizeof(struct fd_config));
64        sigfillset(&sig_all);
65        CHECK_POSIX(  pthread_sigmask(SIG_BLOCK, &sig_all, NULL)  );
66       
67        /* Initialize the library */
68        CHECK_FCT( fd_lib_init() );
69        TRACE_DEBUG(INFO, "libfreeDiameter initialized.");
70       
71        /* Name this thread */
72        fd_log_threadname("Main");
73       
74        /* Initialize the config */
75        CHECK_FCT( fd_conf_init() );
76
77        /* Parse the command-line */
78        CHECK_FCT(  main_cmdline(argc, argv)  );
79       
80        /* Initialize gcrypt and gnutls */
81        (void) gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
82        (void) gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
83        CHECK_GNUTLS_DO( gnutls_global_init(), return EINVAL );
84        if ( ! gnutls_check_version(GNUTLS_VERSION) ) {
85                fprintf(stderr, "The GNUTLS library is too old; found '%s', need '" GNUTLS_VERSION "'\n", gnutls_check_version(NULL));
86                return EINVAL;
87        } else {
88                TRACE_DEBUG(INFO, "GNUTLS library '%s' initialized.", gnutls_check_version(NULL));
89        }
90       
91        /* Allow SIGINT and SIGTERM from this point */
92        CHECK_POSIX(  pthread_create(&sig_th, NULL, sig_hdl, NULL)  );
93       
94        /* Add definitions of the base protocol */
95        CHECK_FCT( fd_dict_base_protocol(fd_g_config->cnf_dict) );
96       
97        /* Initialize other modules */
98        CHECK_FCT(  fd_queues_init()  );
99        CHECK_FCT(  fd_msg_init()  );
100        CHECK_FCT(  fd_p_expi_init()  );
101       
102        /* Parse the configuration file */
103        CHECK_FCT( fd_conf_parse() );
104       
105        /* Load the dynamic extensions */
106        CHECK_FCT(  fd_ext_load()  );
107       
108        fd_conf_dump();
109       
110        /* Start the servers */
111        CHECK_FCT( fd_servers_start() );
112       
113        /* Start the peer state machines */
114        CHECK_FCT( fd_psm_start() );
115       
116        /* Now, just wait for events */
117        TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon initialized.");
118        while (1) {
119                int code; size_t sz; void * data;
120                CHECK_FCT_DO(  fd_event_get(fd_g_config->cnf_main_ev, &code, &sz, &data),  break  );
121                switch (code) {
122                        case FDEV_DUMP_DICT:
123                                fd_dict_dump(fd_g_config->cnf_dict);
124                                break;
125                       
126                        case FDEV_DUMP_EXT:
127                                fd_ext_dump();
128                                break;
129                       
130                        case FDEV_DUMP_SERV:
131                                fd_servers_dump();
132                                break;
133                       
134                        case FDEV_DUMP_QUEUES:
135                                fd_fifo_dump(0, "Incoming messages", fd_g_incoming, fd_msg_dump_walk);
136                                fd_fifo_dump(0, "Outgoing messages", fd_g_outgoing, fd_msg_dump_walk);
137                                fd_fifo_dump(0, "Local messages",    fd_g_local,    fd_msg_dump_walk);
138                                break;
139                       
140                        case FDEV_DUMP_CONFIG:
141                                fd_conf_dump();
142                                break;
143                       
144                        case FDEV_DUMP_PEERS:
145                                fd_peer_dump_list(FULL);
146                                break;
147                       
148                        case FDEV_TERMINATE:
149                                ret = 0;
150                                goto end;
151                       
152                        default:
153                                TRACE_DEBUG(INFO, "Unexpected event in the daemon (%d), ignored.\n", code);
154                }
155        }
156       
157end:
158        TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon is stopping...");
159       
160        /* cleanups */
161        CHECK_FCT_DO( fd_servers_stop(), /* Stop accepting new connections */ );
162        TODO("Stop dispatch thread(s) properly (no cancel yet)");
163        CHECK_FCT_DO( fd_peer_fini(), /* Stop all connections */ );
164        TODO("Stop dispatch & routing threads");
165        CHECK_FCT_DO( fd_ext_fini(), /* Cleaup all extensions */ );
166        TODO("Cleanup queues (dump all remaining messages ?)");
167       
168        CHECK_FCT_DO( fd_thr_term(&sig_th), /* continue */ );
169       
170        gnutls_global_deinit();
171       
172        return ret;
173}
174
175const char * fd_ev_str(int event)
176{
177        switch (event) {
178        #define case_str( _val )\
179                case _val : return #_val
180                case_str(FDEV_TERMINATE);
181                case_str(FDEV_DUMP_DICT);
182                case_str(FDEV_DUMP_EXT);
183                case_str(FDEV_DUMP_SERV);
184                case_str(FDEV_DUMP_QUEUES);
185                case_str(FDEV_DUMP_CONFIG);
186                case_str(FDEV_DUMP_PEERS);
187               
188                default:
189                        TRACE_DEBUG(FULL, "Unknown event : %d", event);
190                        return "Unknown event";
191        }
192}
193
194/* Parse the command-line */
195static int main_cmdline(int argc, char *argv[])
196{
197        int c;
198        int option_index = 0;
199        char * locale;
200       
201        struct option long_options[] = {
202                { "help",       no_argument,            NULL, 'h' },
203                { "version",    no_argument,            NULL, 'V' },
204                { "config",     required_argument,      NULL, 'c' },
205                { "debug",      no_argument,            NULL, 'd' },
206                { "quiet",      no_argument,            NULL, 'q' },
207                { "dbglocale",  optional_argument,      NULL, 'l' },
208                { NULL,         0,                      NULL, 0 }
209        };
210       
211        TRACE_ENTRY("%d %p", argc, argv);
212       
213        /* Loop on arguments */
214        while (1) {
215                c = getopt_long (argc, argv, "hVc:dql:", long_options, &option_index);
216                if (c == -1) 
217                        break;  /* Exit from the loop.  */
218               
219                switch (c) {
220                        case 'h':       /* Print help and exit.  */
221                                main_help();
222                                exit(0);
223
224                        case 'V':       /* Print version and exit.  */
225                                main_version();
226                                exit(0);
227
228                        case 'c':       /* Read configuration from this file instead of the default location..  */
229                                CHECK_PARAMS( optarg );
230                                fd_g_config->cnf_file = optarg;
231                                break;
232
233                        case 'l':       /* Change the locale.  */
234                                locale = setlocale(LC_ALL, optarg?:"");
235                                if (locale) {
236                                        TRACE_DEBUG(INFO, "Locale set to: %s", optarg ?: locale);
237                                } else {
238                                        TRACE_DEBUG(INFO, "Unable to set locale (%s)", optarg);
239                                        return EINVAL;
240                                }
241                                break;
242
243                        case 'd':       /* Increase verbosity of debug messages.  */
244                                fd_g_debug_lvl++;
245                                break;
246                               
247                        case 'q':       /* Decrease verbosity then remove debug messages.  */
248                                fd_g_debug_lvl--;
249                                break;
250
251                        case '?':       /* Invalid option.  */
252                                /* `getopt_long' already printed an error message.  */
253                                TRACE_DEBUG(INFO, "getopt_long found an invalid character");
254                                return EINVAL;
255
256                        default:        /* bug: option not considered.  */
257                                TRACE_DEBUG(INFO, "A command-line option is missing in parser: %c", c);
258                                ASSERT(0);
259                                return EINVAL;
260                }
261        }
262               
263        return 0;
264}
265
266/* Display package version */
267static void main_version_core(void)
268{
269        printf("%s, version %d.%d.%d"
270#ifdef HG_VERSION
271                " (r%s"
272# ifdef PACKAGE_HG_REVISION
273                "/%s"
274# endif /* PACKAGE_HG_VERSION */
275                ")"
276#endif /* HG_VERSION */
277                "\n", 
278                FD_PROJECT_NAME, FD_PROJECT_VERSION_MAJOR, FD_PROJECT_VERSION_MINOR, FD_PROJECT_VERSION_REV
279#ifdef HG_VERSION
280                , HG_VERSION
281# ifdef PACKAGE_HG_REVISION
282                , PACKAGE_HG_REVISION
283# endif /* PACKAGE_HG_VERSION */
284#endif /* HG_VERSION */
285                );
286}
287
288/* Display package version and general info */
289static void main_version(void)
290{
291        main_version_core();
292        printf( "%s\n", FD_PROJECT_COPYRIGHT);
293        printf( "\nSee " FD_PROJECT_NAME " homepage at http://aaa.koganei.wide.ad.jp/\n"
294                " for information, updates and bug reports on this software.\n");
295}
296
297/* Print command-line options */
298static void main_help( void )
299{
300        main_version_core();
301        printf( "  This daemon is an implementation of the Diameter protocol\n"
302                "  used for Authentication, Authorization, and Accounting (AAA).\n");
303        printf("\nUsage:  " FD_PROJECT_BINARY " [OPTIONS]...\n");
304        printf( "  -h, --help             Print help and exit\n"
305                "  -V, --version          Print version and exit\n"
306                "  -c, --config=filename  Read configuration from this file instead of the \n"
307                "                           default location (%s).\n", DEFAULT_CONF_FILE);
308        printf( "\nDebug:\n"
309                "  These options are mostly useful for developers\n"
310                "  -l, --dbglocale        Set the locale for error messages\n"
311                "  -d, --debug            Increase verbosity of debug messages\n"
312                "  -q, --quiet            Decrease verbosity then remove debug messages\n");
313}
314
315#ifdef HAVE_SIGNALENT_H
316const char *const signalstr[] = {
317# include "signalent.h"
318};
319const int nsignalstr = sizeof signalstr / sizeof signalstr[0];
320# define SIGNALSTR(sig) (((sig) < nsignalstr) ? signalstr[(sig)] : "unknown")
321#else /* HAVE_SIGNALENT_H */
322# define SIGNALSTR(sig) ("")
323#endif /* HAVE_SIGNALENT_H */
324
325/* signal handler */
326static void * sig_hdl(void * arg)
327{
328        sigset_t sig_main;
329        int sig = 0;
330       
331        TRACE_ENTRY();
332        fd_log_threadname("Main signal handler");
333       
334        sigemptyset(&sig_main);
335        sigaddset(&sig_main, SIGINT);
336        sigaddset(&sig_main, SIGTERM);
337       
338        CHECK_SYS_DO(  sigwait(&sig_main, &sig), TRACE_DEBUG(INFO, "Error in sigwait function") );
339       
340        TRACE_DEBUG(INFO, "Received signal %s (%d), exiting", SIGNALSTR(sig), sig);
341        CHECK_FCT_DO( fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), exit(2) );
342        return NULL;
343}
344       
Note: See TracBrowser for help on using the repository browser.