c79696c079b624c377a7e379d7dd8ac466d216b7
[strongswan.git] / Source / charon / daemon.c
1 /**
2 * @file daemon.c
3 *
4 * @brief Main of IKEv2-Daemon
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include <stdio.h>
24 #include <signal.h>
25 #include <pthread.h>
26
27 #include "daemon.h"
28
29
30 #include "types.h"
31 #include "socket.h"
32 #include "ike_sa_manager.h"
33 #include "sender.h"
34 #include "receiver.h"
35 #include "scheduler.h"
36 #include "thread_pool.h"
37 #include "utils/allocator.h"
38 #include "utils/logger_manager.h"
39 #include "queues/event_queue.h"
40 #include "queues/job_queue.h"
41 #include "queues/send_queue.h"
42
43
44 /* function declaration (defined and described after main function) */
45
46 static status_t initialize_globals();
47 static void destroy_globals();
48 static status_t start_threads();
49 static void end_threads();
50 static void main_loop();
51 static void register_signals();
52 static void destroy_and_exit(int);
53
54 /** Global job-queue */
55 job_queue_t *global_job_queue = NULL;
56 /** Global event-queue */
57 event_queue_t *global_event_queue = NULL;
58 /** Global send-queue */
59 send_queue_t *global_send_queue = NULL;
60 /** Global socket */
61 socket_t *global_socket = NULL;
62 /** Global logger manager */
63 logger_manager_t *global_logger_manager = NULL;
64 /** Global ike_sa-manager */
65 ike_sa_manager_t *global_ike_sa_manager = NULL;
66 /** Global configuration-manager */
67 configuration_manager_t *global_configuration_manager = NULL;
68
69 /**
70 * logger_t object assigned for daemon things
71 */
72 static logger_t *logger = NULL;
73
74 /**
75 * Sender-Thread
76 */
77 static sender_t *sender_thread = NULL;
78 /**
79 * Receiver-Thread
80 */
81 static receiver_t *receiver_thread = NULL;
82 /**
83 * Scheduler-Thread
84 */
85 static scheduler_t *scheduler_thread = NULL;
86 /**
87 * Thread pool holding the worker threads
88 */
89 static thread_pool_t *thread_pool = NULL;
90
91 /**
92 * Signal set used for signal handling
93 */
94 sigset_t signal_set;
95
96
97 int main()
98 {
99 /* set signal handler */
100 register_signals();
101
102 /* logger_manager is created first */
103 global_logger_manager = logger_manager_create(ALL);
104 if (global_logger_manager == NULL)
105 {
106 printf("could not create logger manager");
107 return -1;
108 }
109
110 /* a own logger for the daemon is created */
111 logger = global_logger_manager->create_logger(global_logger_manager,DAEMON,NULL);
112 if (logger == NULL)
113 {
114 printf("could not create logger object");
115 destroy_globals();
116 return -1;
117 }
118
119 /* initialize all global objects */
120 if (initialize_globals() != SUCCESS)
121 {
122 destroy_globals();
123 return -1;
124 }
125 /* a own logger for the daemon is created */
126 logger = global_logger_manager->create_logger(global_logger_manager,DAEMON,NULL);
127 if (logger == NULL)
128 {
129 printf("could not create logger object");
130 destroy_globals();
131 return -1;
132 }
133
134 logger->log(logger,CONTROL,"start daemon %s", DAEMON_NAME);
135 /* now its time to create all the different threads :-) */
136 if (start_threads() != SUCCESS)
137 {
138 /* ugh, not good */
139 logger->log(logger,CONTROL,"Fatal error: Needed Threads could not be started");
140 destroy_and_exit(-1);
141 }
142
143 int i;
144 for(i = 0; i<10; i++)
145 {
146 initiate_ike_sa_job_t *initiate_job;
147
148 initiate_job = initiate_ike_sa_job_create("pinflb31");
149 global_event_queue->add_relative(global_event_queue, (job_t*)initiate_job, i * 1000);
150
151 }
152
153 logger->log(logger,CONTROL_MORE,"going to wait for exit signal");
154 /* go and handle signals*/
155 main_loop();
156
157 destroy_and_exit(0);
158
159 /* never reached */
160 return -1;
161 }
162
163 /**
164 * Main Loop.
165 * Waits for registered signals and acts dependently
166 */
167 static void main_loop()
168 {
169 while(1)
170 {
171 int signal_number;
172 int error;
173
174 error = sigwait(&signal_set, &signal_number);
175
176 if(error)
177 {
178 /* do error code */
179 logger->log(logger,CONTROL,"Error %d when waiting for signal",error);
180 return;
181 }
182 switch (signal_number)
183 {
184 case SIGHUP:
185 {
186 logger->log(logger,CONTROL,"Signal of type SIGHUP received. Do nothing");
187 break;
188 }
189 case SIGINT:
190 {
191 logger->log(logger,CONTROL,"Signal of type SIGINT received. Exit main loop.");
192 return;
193 }
194 case SIGTERM:
195 {
196 logger->log(logger,CONTROL,"Signal of type SIGTERM received. Exit main loop.");
197 return;
198 }
199 default:
200 {
201 logger->log(logger,CONTROL,"Unknown signal %d received. Do nothing",signal_number);
202 break;
203 }
204 }
205 }
206 }
207
208 /**
209 * Registers signals SIGINT, SIGHUP and SIGTERM.
210 * Signals are handled in main_loop()
211 */
212 static void register_signals()
213 {
214 sigemptyset(&signal_set);
215 sigaddset(&signal_set, SIGINT);
216 sigaddset(&signal_set, SIGHUP);
217 sigaddset(&signal_set, SIGTERM);
218 pthread_sigmask(SIG_BLOCK, &signal_set, 0);
219
220 }
221
222 /**
223 * Initializes global objects
224 *
225 * @return
226 * - SUCCESS
227 * - FAILED
228 */
229 static status_t initialize_globals()
230 {
231 /* initialize global object */
232 global_socket = socket_create(IKEV2_UDP_PORT);
233 global_ike_sa_manager = ike_sa_manager_create();
234 global_job_queue = job_queue_create();
235 global_event_queue = event_queue_create();
236 global_send_queue = send_queue_create();
237 global_configuration_manager = configuration_manager_create();
238
239 if ( (global_socket == NULL) ||
240 (global_job_queue == NULL) ||
241 (global_event_queue == NULL) ||
242 (global_send_queue == NULL) ||
243 (global_configuration_manager == NULL) ||
244 (global_ike_sa_manager == NULL))
245 {
246 return FAILED;
247 }
248
249 return SUCCESS;
250 }
251
252 /**
253 * Destroy global objects
254 */
255 static void destroy_globals()
256 {
257 if (global_ike_sa_manager != NULL)
258 {
259 global_job_queue->destroy(global_job_queue);
260 }
261 if (global_event_queue != NULL)
262 {
263 global_event_queue->destroy(global_event_queue);
264 }
265 if (global_send_queue != NULL)
266 {
267 global_send_queue->destroy(global_send_queue);
268 }
269 if (global_socket != NULL)
270 {
271 global_socket->destroy(global_socket);
272 }
273 if (global_ike_sa_manager != NULL)
274 {
275 global_ike_sa_manager->destroy(global_ike_sa_manager);
276 }
277 if (global_ike_sa_manager != NULL)
278 {
279 global_configuration_manager->destroy(global_configuration_manager);
280 }
281 }
282
283 /**
284 * Creates all needed Threads
285 *
286 * @return
287 * - SUCCESS
288 * - FAILED
289 */
290 static status_t start_threads()
291 {
292 sender_thread = sender_create();
293 if (sender_thread == NULL)
294 {
295 return FAILED;
296 }
297 scheduler_thread = scheduler_create();
298 if (scheduler_thread == NULL)
299 {
300 return FAILED;
301 }
302 thread_pool = thread_pool_create(NUMBER_OF_WORKING_THREADS);
303 if (thread_pool == NULL)
304 {
305 return FAILED;
306 }
307 receiver_thread = receiver_create();
308 if (receiver_thread == NULL)
309 {
310 return FAILED;
311 }
312
313 return SUCCESS;
314 }
315
316
317 /**
318 * Ends all Threads
319 *
320 */
321 static void end_threads()
322 {
323 if (receiver_thread != NULL)
324 {
325 receiver_thread->destroy(receiver_thread);
326 }
327 if (scheduler_thread != NULL)
328 {
329 scheduler_thread->destroy(scheduler_thread);
330 }
331 if (sender_thread != NULL)
332 {
333 sender_thread->destroy(sender_thread);
334 }
335 if (thread_pool != NULL)
336 {
337 thread_pool->destroy(thread_pool);
338 }
339
340 }
341
342 /**
343 * Destroys initialized objects, kills all threads and exits
344 *
345 * @param exit_code Code to exit with
346 */
347 static void destroy_and_exit(int exit_code)
348 {
349 logger->log(logger,CONTROL,"going to exit daemon");
350
351 end_threads();
352
353 /* all globals can be destroyed now */
354 destroy_globals();
355
356 /* logger is destroyed */
357 logger->log(logger,CONTROL_MORE,"destroy logger");
358 global_logger_manager->destroy_logger(global_logger_manager,logger);
359 logger->log(logger,CONTROL_MORE,"destroy logger_manager");
360 logger->log(logger,CONTROL_MORE,"------------------------------------");
361 if (global_logger_manager != NULL)
362 {
363 global_logger_manager->destroy(global_logger_manager);
364 }
365
366 #ifdef LEAK_DETECTIVE
367 /* Leaks are reported in log file */
368 report_memory_leaks(void);
369 #endif
370
371 exit(exit_code);
372 }