configure: Fix typo when enabling CPAN modules as dependency
[strongswan.git] / src / starter / invokecharon.c
1 /* strongSwan charon launcher
2 * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
3 * Copyright (C) 2006 Martin Willi - Hochschule fuer Technik Rapperswil
4 *
5 * Ported from invokepluto.c to fit charons needs.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <signal.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <errno.h>
25
26 #include <library.h>
27 #include <utils/debug.h>
28
29 #include "confread.h"
30 #include "invokecharon.h"
31 #include "files.h"
32
33 static int _charon_pid = 0;
34 static int _stop_requested;
35
36 pid_t starter_charon_pid(void)
37 {
38 return _charon_pid;
39 }
40
41 void starter_charon_sigchild(pid_t pid, int status)
42 {
43 if (pid == _charon_pid)
44 {
45 _charon_pid = 0;
46 if (status == SS_RC_LIBSTRONGSWAN_INTEGRITY ||
47 status == SS_RC_DAEMON_INTEGRITY)
48 {
49 DBG1(DBG_APP, "%s has quit: integrity test of %s failed",
50 daemon_name, (status == 64) ? "libstrongswan" : daemon_name);
51 _stop_requested = 1;
52 }
53 else if (status == SS_RC_INITIALIZATION_FAILED)
54 {
55 DBG1(DBG_APP, "%s has quit: initialization failed", daemon_name);
56 _stop_requested = 1;
57 }
58 if (!_stop_requested)
59 {
60 DBG1(DBG_APP, "%s has died -- restart scheduled (%dsec)",
61 daemon_name, CHARON_RESTART_DELAY);
62 alarm(CHARON_RESTART_DELAY); // restart in 5 sec
63 }
64 unlink(pid_file);
65 }
66 }
67
68 int starter_stop_charon (void)
69 {
70 int i;
71 pid_t pid = _charon_pid;
72
73 if (pid)
74 {
75 _stop_requested = 1;
76
77 /* be more and more aggressive */
78 for (i = 0; i < 50 && (pid = _charon_pid) != 0; i++)
79 {
80 if (i == 0)
81 {
82 kill(pid, SIGINT);
83 }
84 else if (i < 40)
85 {
86 kill(pid, SIGTERM);
87 }
88 else if (i == 40)
89 {
90 kill(pid, SIGKILL);
91 DBG1(DBG_APP, "starter_stop_charon(): %s does not respond, sending KILL",
92 daemon_name);
93 }
94 else
95 {
96 kill(pid, SIGKILL);
97 }
98 usleep(200000); /* sleep for 200 ms */
99 }
100 if (_charon_pid == 0)
101 {
102 DBG1(DBG_APP, "%s stopped after %d ms", daemon_name, 200*i);
103 return 0;
104 }
105 DBG1(DBG_APP, "starter_stop_charon(): can't stop %s !!!", daemon_name);
106 return -1;
107 }
108 else
109 {
110 DBG1(DBG_APP, "stater_stop_charon(): %s was not started...", daemon_name);
111 }
112 return -1;
113 }
114
115
116 int starter_start_charon (starter_config_t *cfg, bool no_fork, bool attach_gdb)
117 {
118 struct stat stb;
119 int pid, i;
120 char buffer[BUF_LEN];
121 int argc = 1;
122 char *arg[] = {
123 cmd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
124 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
125 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
126 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
127 };
128
129 if (attach_gdb)
130 {
131 argc = 0;
132 arg[argc++] = "/usr/bin/gdb";
133 arg[argc++] = "--args";
134 arg[argc++] = cmd;
135 }
136 if (!no_fork)
137 {
138 arg[argc++] = "--use-syslog";
139 }
140
141 /* parse debug string */
142 {
143 int level;
144 char type[4];
145 char *pos = cfg->setup.charondebug;
146 char *buf_pos = buffer;
147
148 while (pos && sscanf(pos, "%3s %d,", type, &level) == 2)
149 {
150 snprintf(buf_pos, buffer + sizeof(buffer) - buf_pos, "--debug-%s", type);
151 arg[argc++] = buf_pos;
152 buf_pos += strlen(buf_pos) + 1;
153 if (buf_pos >= buffer + sizeof(buffer))
154 {
155 break;
156 }
157 snprintf(buf_pos, buffer + sizeof(buffer) - buf_pos, "%d", level);
158 arg[argc++] = buf_pos;
159 buf_pos += strlen(buf_pos) + 1;
160 if (buf_pos >= buffer + sizeof(buffer))
161 {
162 break;
163 }
164
165 /* get next */
166 pos = strchr(pos, ',');
167 if (pos)
168 {
169 pos++;
170 }
171 }
172 }
173
174 if (_charon_pid)
175 {
176 DBG1(DBG_APP, "starter_start_charon(): %s already started...",
177 daemon_name);
178 return -1;
179 }
180 else
181 {
182 unlink(CHARON_CTL_FILE);
183 _stop_requested = 0;
184
185 pid = fork();
186 switch (pid)
187 {
188 case -1:
189 DBG1(DBG_APP, "can't fork(): %s", strerror(errno));
190 return -1;
191 case 0:
192 /* child */
193 setsid();
194 closefrom(3);
195 sigprocmask(SIG_SETMASK, 0, NULL);
196 /* disable glibc's malloc checker, conflicts with leak detective */
197 setenv("MALLOC_CHECK_", "0", 1);
198 execv(arg[0], arg);
199 DBG1(DBG_APP, "can't execv(%s,...): %s", arg[0], strerror(errno));
200 exit(1);
201 default:
202 /* father */
203 _charon_pid = pid;
204 while (attach_gdb)
205 {
206 /* wait indefinitely if gdb is attached */
207 usleep(10000);
208 if (stat(pid_file, &stb) == 0)
209 {
210 return 0;
211 }
212 }
213 for (i = 0; i < 500 && _charon_pid; i++)
214 {
215 /* wait for charon for a maximum of 500 x 20 ms = 10 s */
216 usleep(20000);
217 if (stat(pid_file, &stb) == 0)
218 {
219 DBG1(DBG_APP, "%s (%d) started after %d ms", daemon_name,
220 _charon_pid, 20*(i+1));
221 return 0;
222 }
223 }
224 if (_charon_pid)
225 {
226 /* If charon is started but with no ctl file, stop it */
227 DBG1(DBG_APP, "%s too long to start... - kill kill",
228 daemon_name);
229 for (i = 0; i < 20 && (pid = _charon_pid) != 0; i++)
230 {
231 if (i == 0)
232 {
233 kill(pid, SIGINT);
234 }
235 else if (i < 10)
236 {
237 kill(pid, SIGTERM);
238 }
239 else
240 {
241 kill(pid, SIGKILL);
242 }
243 usleep(20000); /* sleep for 20 ms */
244 }
245 }
246 else
247 {
248 DBG1(DBG_APP, "%s refused to be started", daemon_name);
249 }
250 return -1;
251 }
252 }
253 return -1;
254 }