pki: Add pki --signcrl man page
[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 for (i = 0; i < 500 && _charon_pid; i++)
205 {
206 /* wait for charon for a maximum of 500 x 20 ms = 10 s */
207 usleep(20000);
208 if (stat(pid_file, &stb) == 0)
209 {
210 DBG1(DBG_APP, "%s (%d) started after %d ms", daemon_name,
211 _charon_pid, 20*(i+1));
212 return 0;
213 }
214 }
215 if (_charon_pid)
216 {
217 /* If charon is started but with no ctl file, stop it */
218 DBG1(DBG_APP, "%s too long to start... - kill kill",
219 daemon_name);
220 for (i = 0; i < 20 && (pid = _charon_pid) != 0; i++)
221 {
222 if (i == 0)
223 {
224 kill(pid, SIGINT);
225 }
226 else if (i < 10)
227 {
228 kill(pid, SIGTERM);
229 }
230 else
231 {
232 kill(pid, SIGKILL);
233 }
234 usleep(20000); /* sleep for 20 ms */
235 }
236 }
237 else
238 {
239 DBG1(DBG_APP, "%s refused to be started", daemon_name);
240 }
241 return -1;
242 }
243 }
244 return -1;
245 }