libhydra: Remove unused hydra->daemon
[strongswan.git] / src / charon-nm / charon-nm.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include <stdio.h>
17 #include <syslog.h>
18 #include <signal.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21
22 #include <hydra.h>
23 #include <daemon.h>
24
25 #include <library.h>
26 #include <utils/backtrace.h>
27 #include <threading/thread.h>
28
29 #include <nm/nm_backend.h>
30
31 /**
32 * Default user and group
33 */
34 #ifndef IPSEC_USER
35 #define IPSEC_USER NULL
36 #endif
37
38 #ifndef IPSEC_GROUP
39 #define IPSEC_GROUP NULL
40 #endif
41
42 /**
43 * Hook in library for debugging messages
44 */
45 extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
46
47 /**
48 * Simple logging hook for library logs, using syslog output
49 */
50 static void dbg_syslog(debug_t group, level_t level, char *fmt, ...)
51 {
52 if (level <= 1)
53 {
54 char buffer[8192], groupstr[4];
55 va_list args;
56
57 va_start(args, fmt);
58 /* write in memory buffer first */
59 vsnprintf(buffer, sizeof(buffer), fmt, args);
60 /* cache group name */
61 snprintf(groupstr, sizeof(groupstr), "%N", debug_names, group);
62 syslog(LOG_DAEMON|LOG_INFO, "00[%s] %s", groupstr, buffer);
63 va_end(args);
64 }
65 }
66
67 /**
68 * Run the daemon and handle unix signals
69 */
70 static void run()
71 {
72 sigset_t set;
73
74 /* handle SIGINT and SIGTERM in this handler */
75 sigemptyset(&set);
76 sigaddset(&set, SIGINT);
77 sigaddset(&set, SIGTERM);
78 sigprocmask(SIG_BLOCK, &set, NULL);
79
80 while (TRUE)
81 {
82 int sig;
83 int error;
84
85 error = sigwait(&set, &sig);
86 if (error)
87 {
88 DBG1(DBG_DMN, "error %d while waiting for a signal", error);
89 return;
90 }
91 switch (sig)
92 {
93 case SIGINT:
94 {
95 DBG1(DBG_DMN, "signal of type SIGINT received. Shutting down");
96 charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
97 return;
98 }
99 case SIGTERM:
100 {
101 DBG1(DBG_DMN, "signal of type SIGTERM received. Shutting down");
102 charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
103 return;
104 }
105 default:
106 {
107 DBG1(DBG_DMN, "unknown signal %d received. Ignored", sig);
108 break;
109 }
110 }
111 }
112 }
113
114 /**
115 * Handle SIGSEGV/SIGILL signals raised by threads
116 */
117 static void segv_handler(int signal)
118 {
119 backtrace_t *backtrace;
120
121 DBG1(DBG_DMN, "thread %u received %d", thread_current_id(), signal);
122 backtrace = backtrace_create(2);
123 backtrace->log(backtrace, stderr, TRUE);
124 backtrace->destroy(backtrace);
125
126 DBG1(DBG_DMN, "killing ourself, received critical signal");
127 abort();
128 }
129
130 /**
131 * Lookup UID and GID
132 */
133 static bool lookup_uid_gid()
134 {
135 char *name;
136
137 name = lib->settings->get_str(lib->settings, "charon-nm.user",
138 IPSEC_USER);
139 if (name && !lib->caps->resolve_uid(lib->caps, name))
140 {
141 return FALSE;
142 }
143 name = lib->settings->get_str(lib->settings, "charon-nm.group",
144 IPSEC_GROUP);
145 if (name && !lib->caps->resolve_gid(lib->caps, name))
146 {
147 return FALSE;
148 }
149 return TRUE;
150 }
151
152 /**
153 * Main function, starts NetworkManager backend.
154 */
155 int main(int argc, char *argv[])
156 {
157 struct sigaction action;
158 int status = SS_RC_INITIALIZATION_FAILED;
159
160 /* logging for library during initialization, as we have no bus yet */
161 dbg = dbg_syslog;
162
163 /* initialize library */
164 if (!library_init(NULL, "charon-nm"))
165 {
166 library_deinit();
167 exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
168 }
169
170 if (lib->integrity &&
171 !lib->integrity->check_file(lib->integrity, "charon-nm", argv[0]))
172 {
173 dbg_syslog(DBG_DMN, 1, "integrity check of charon-nm failed");
174 library_deinit();
175 exit(SS_RC_DAEMON_INTEGRITY);
176 }
177
178 if (!libhydra_init())
179 {
180 dbg_syslog(DBG_DMN, 1, "initialization failed - aborting charon-nm");
181 libhydra_deinit();
182 library_deinit();
183 exit(SS_RC_INITIALIZATION_FAILED);
184 }
185
186 if (!libcharon_init("charon-nm"))
187 {
188 dbg_syslog(DBG_DMN, 1, "initialization failed - aborting charon-nm");
189 goto deinit;
190 }
191
192 if (!lookup_uid_gid())
193 {
194 dbg_syslog(DBG_DMN, 1, "invalid uid/gid - aborting charon-nm");
195 goto deinit;
196 }
197
198 /* make sure we log to the DAEMON facility by default */
199 lib->settings->set_int(lib->settings, "charon-nm.syslog.daemon.default",
200 lib->settings->get_int(lib->settings,
201 "charon-nm.syslog.daemon.default", 1));
202 charon->load_loggers(charon, NULL, FALSE);
203
204 /* use random ports to avoid conflicts with regular charon */
205 lib->settings->set_int(lib->settings, "charon-nm.port", 0);
206 lib->settings->set_int(lib->settings, "charon-nm.port_natt_t", 0);
207
208 DBG1(DBG_DMN, "Starting charon NetworkManager backend (strongSwan "VERSION")");
209 if (lib->integrity)
210 {
211 DBG1(DBG_DMN, "integrity tests enabled:");
212 DBG1(DBG_DMN, "lib 'libstrongswan': passed file and segment integrity tests");
213 DBG1(DBG_DMN, "lib 'libhydra': passed file and segment integrity tests");
214 DBG1(DBG_DMN, "lib 'libcharon': passed file and segment integrity tests");
215 DBG1(DBG_DMN, "daemon 'charon-nm': passed file integrity test");
216 }
217
218 /* register NM backend to be loaded with plugins */
219 nm_backend_register();
220
221 /* initialize daemon */
222 if (!charon->initialize(charon,
223 lib->settings->get_str(lib->settings, "charon-nm.load", PLUGINS)))
224 {
225 DBG1(DBG_DMN, "initialization failed - aborting charon-nm");
226 goto deinit;
227 }
228 lib->plugins->status(lib->plugins, LEVEL_CTRL);
229
230 if (!lib->caps->drop(lib->caps))
231 {
232 DBG1(DBG_DMN, "capability dropping failed - aborting charon-nm");
233 goto deinit;
234 }
235
236 /* add handler for SEGV and ILL,
237 * INT and TERM are handled by sigwait() in run() */
238 action.sa_handler = segv_handler;
239 action.sa_flags = 0;
240 sigemptyset(&action.sa_mask);
241 sigaddset(&action.sa_mask, SIGINT);
242 sigaddset(&action.sa_mask, SIGTERM);
243 sigaction(SIGSEGV, &action, NULL);
244 sigaction(SIGILL, &action, NULL);
245 sigaction(SIGBUS, &action, NULL);
246 action.sa_handler = SIG_IGN;
247 sigaction(SIGPIPE, &action, NULL);
248
249 pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);
250
251 /* start daemon (i.e. the threads in the thread-pool) */
252 charon->start(charon);
253
254 /* main thread goes to run loop */
255 run();
256
257 status = 0;
258
259 deinit:
260 libcharon_deinit();
261 libhydra_deinit();
262 library_deinit();
263 return status;
264 }
265