406661031628f55e2ef56f51e345fe2a43b2c892
[tinc] / src / process.c
1 /*
2     process.c -- process management functions
3     Copyright (C) 1999-2005 Ivo Timmermans,
4                   2000-2009 Guus Sliepen <guus@tinc-vpn.org>
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License along
17     with this program; if not, write to the Free Software Foundation, Inc.,
18     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include "system.h"
22
23 #include "conf.h"
24 #include "connection.h"
25 #include "device.h"
26 #include "edge.h"
27 #include "logger.h"
28 #include "node.h"
29 #include "pidfile.h"
30 #include "process.h"
31 #include "subnet.h"
32 #include "utils.h"
33 #include "xalloc.h"
34
35 /* If zero, don't detach from the terminal. */
36 bool do_detach = true;
37 bool sighup = false;
38 bool sigalrm = false;
39
40 extern char *identname;
41 extern char *pidfilename;
42 extern char **g_argv;
43 extern bool use_logfile;
44 extern volatile bool running;
45
46 sigset_t emptysigset;
47
48 static int saved_debug_level = -1;
49
50 static void memory_full(int size) {
51         logger(LOG_ERR, _("Memory exhausted (couldn't allocate %d bytes), exitting."), size);
52         cp_trace();
53         exit(1);
54 }
55
56 /* Some functions the less gifted operating systems might lack... */
57
58 #ifdef HAVE_MINGW
59 extern char *identname;
60 extern char *program_name;
61 extern char **g_argv;
62
63 static SC_HANDLE manager = NULL;
64 static SC_HANDLE service = NULL;
65 static SERVICE_STATUS status = {0};
66 static SERVICE_STATUS_HANDLE statushandle = 0;
67
68 bool install_service(void) {
69         char command[4096] = "\"";
70         char **argp;
71         bool space;
72         SERVICE_DESCRIPTION description = {"Virtual Private Network daemon"};
73
74         manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
75         if(!manager) {
76                 logger(LOG_ERR, _("Could not open service manager: %s"), winerror(GetLastError()));
77                 return false;
78         }
79
80         if(!strchr(program_name, '\\')) {
81                 GetCurrentDirectory(sizeof command - 1, command + 1);
82                 strncat(command, "\\", sizeof command - strlen(command));
83         }
84
85         strncat(command, program_name, sizeof command - strlen(command));
86
87         strncat(command, "\"", sizeof command - strlen(command));
88
89         for(argp = g_argv + 1; *argp; argp++) {
90                 space = strchr(*argp, ' ');
91                 strncat(command, " ", sizeof command - strlen(command));
92                 
93                 if(space)
94                         strncat(command, "\"", sizeof command - strlen(command));
95                 
96                 strncat(command, *argp, sizeof command - strlen(command));
97
98                 if(space)
99                         strncat(command, "\"", sizeof command - strlen(command));
100         }
101
102         service = CreateService(manager, identname, identname,
103                         SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
104                         command, NULL, NULL, NULL, NULL, NULL);
105         
106         if(!service) {
107                 logger(LOG_ERR, _("Could not create %s service: %s"), identname, winerror(GetLastError()));
108                 return false;
109         }
110
111         ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &description);
112
113         logger(LOG_INFO, _("%s service installed"), identname);
114
115         if(!StartService(service, 0, NULL))
116                 logger(LOG_WARNING, _("Could not start %s service: %s"), identname, winerror(GetLastError()));
117         else
118                 logger(LOG_INFO, _("%s service started"), identname);
119
120         return true;
121 }
122
123 bool remove_service(void) {
124         manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
125         if(!manager) {
126                 logger(LOG_ERR, _("Could not open service manager: %s"), winerror(GetLastError()));
127                 return false;
128         }
129
130         service = OpenService(manager, identname, SERVICE_ALL_ACCESS);
131
132         if(!service) {
133                 logger(LOG_ERR, _("Could not open %s service: %s"), identname, winerror(GetLastError()));
134                 return false;
135         }
136
137         if(!ControlService(service, SERVICE_CONTROL_STOP, &status))
138                 logger(LOG_ERR, _("Could not stop %s service: %s"), identname, winerror(GetLastError()));
139         else
140                 logger(LOG_INFO, _("%s service stopped"), identname);
141
142         if(!DeleteService(service)) {
143                 logger(LOG_ERR, _("Could not remove %s service: %s"), identname, winerror(GetLastError()));
144                 return false;
145         }
146
147         logger(LOG_INFO, _("%s service removed"), identname);
148
149         return true;
150 }
151
152 DWORD WINAPI controlhandler(DWORD request, DWORD type, LPVOID boe, LPVOID bah) {
153         switch(request) {
154                 case SERVICE_CONTROL_INTERROGATE:
155                         SetServiceStatus(statushandle, &status);
156                         return NO_ERROR;
157                 case SERVICE_CONTROL_STOP:
158                         logger(LOG_NOTICE, _("Got %s request"), "SERVICE_CONTROL_STOP");
159                         break;
160                 case SERVICE_CONTROL_SHUTDOWN:
161                         logger(LOG_NOTICE, _("Got %s request"), "SERVICE_CONTROL_SHUTDOWN");
162                         break;
163                 default:
164                         logger(LOG_WARNING, _("Got unexpected request %d"), request);
165                         return ERROR_CALL_NOT_IMPLEMENTED;
166         }
167
168         if(running) {
169                 running = false;
170                 status.dwWaitHint = 30000; 
171                 status.dwCurrentState = SERVICE_STOP_PENDING; 
172                 SetServiceStatus(statushandle, &status);
173                 return NO_ERROR;
174         } else {
175                 status.dwWaitHint = 0; 
176                 status.dwCurrentState = SERVICE_STOPPED; 
177                 SetServiceStatus(statushandle, &status);
178                 exit(1);
179         }
180
181 }
182
183 VOID WINAPI run_service(DWORD argc, LPTSTR* argv) {
184         int err = 1;
185         extern int main2(int argc, char **argv);
186
187
188         status.dwServiceType = SERVICE_WIN32; 
189         status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
190         status.dwWin32ExitCode = 0; 
191         status.dwServiceSpecificExitCode = 0; 
192         status.dwCheckPoint = 0; 
193
194         statushandle = RegisterServiceCtrlHandlerEx(identname, controlhandler, NULL); 
195
196         if (!statushandle) {
197                 logger(LOG_ERR, _("System call `%s' failed: %s"), "RegisterServiceCtrlHandlerEx", winerror(GetLastError()));
198                 err = 1;
199         } else {
200                 status.dwWaitHint = 30000; 
201                 status.dwCurrentState = SERVICE_START_PENDING; 
202                 SetServiceStatus(statushandle, &status);
203
204                 status.dwWaitHint = 0; 
205                 status.dwCurrentState = SERVICE_RUNNING;
206                 SetServiceStatus(statushandle, &status);
207
208                 err = main2(argc, argv);
209
210                 status.dwWaitHint = 0;
211                 status.dwCurrentState = SERVICE_STOPPED; 
212                 //status.dwWin32ExitCode = err; 
213                 SetServiceStatus(statushandle, &status);
214         }
215
216         return;
217 }
218
219 bool init_service(void) {
220         SERVICE_TABLE_ENTRY services[] = {
221                 {identname, run_service},
222                 {NULL, NULL}
223         };
224
225         if(!StartServiceCtrlDispatcher(services)) {
226                 if(GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
227                         return false;
228                 }
229                 else
230                         logger(LOG_ERR, _("System call `%s' failed: %s"), "StartServiceCtrlDispatcher", winerror(GetLastError()));
231         }
232
233         return true;
234 }
235 #endif
236
237 #ifndef HAVE_MINGW
238 /*
239   check for an existing tinc for this net, and write pid to pidfile
240 */
241 static bool write_pidfile(void) {
242         pid_t pid;
243
244         cp();
245
246         pid = check_pid(pidfilename);
247
248         if(pid) {
249                 if(netname)
250                         fprintf(stderr, _("A tincd is already running for net `%s' with pid %ld.\n"),
251                                         netname, (long)pid);
252                 else
253                         fprintf(stderr, _("A tincd is already running with pid %ld.\n"), (long)pid);
254                 return false;
255         }
256
257         /* if it's locked, write-protected, or whatever */
258         if(!write_pid(pidfilename)) {
259                 fprintf(stderr, _("Could write pid file %s: %s\n"), pidfilename, strerror(errno));
260                 return false;
261         }
262
263         return true;
264 }
265 #endif
266
267 /*
268   kill older tincd for this net
269 */
270 bool kill_other(int signal) {
271 #ifndef HAVE_MINGW
272         pid_t pid;
273
274         cp();
275
276         pid = read_pid(pidfilename);
277
278         if(!pid) {
279                 if(netname)
280                         fprintf(stderr, _("No other tincd is running for net `%s'.\n"),
281                                         netname);
282                 else
283                         fprintf(stderr, _("No other tincd is running.\n"));
284                 return false;
285         }
286
287         errno = 0;                                      /* No error, sometimes errno is only changed on error */
288
289         /* ESRCH is returned when no process with that pid is found */
290         if(kill(pid, signal) && errno == ESRCH) {
291                 if(netname)
292                         fprintf(stderr, _("The tincd for net `%s' is no longer running. "),
293                                         netname);
294                 else
295                         fprintf(stderr, _("The tincd is no longer running. "));
296
297                 fprintf(stderr, _("Removing stale lock file.\n"));
298                 remove_pid(pidfilename);
299         }
300
301         return true;
302 #else
303         return remove_service();
304 #endif
305 }
306
307 /*
308   Detach from current terminal, write pidfile, kill parent
309 */
310 bool detach(void) {
311         cp();
312
313         setup_signals();
314
315         /* First check if we can open a fresh new pidfile */
316
317 #ifndef HAVE_MINGW
318         if(!write_pidfile())
319                 return false;
320
321         /* If we succeeded in doing that, detach */
322
323         closelogger();
324 #endif
325
326         if(do_detach) {
327 #ifndef HAVE_MINGW
328                 if(daemon(0, 0)) {
329                         fprintf(stderr, _("Couldn't detach from terminal: %s"),
330                                         strerror(errno));
331                         return false;
332                 }
333
334                 /* Now UPDATE the pid in the pidfile, because we changed it... */
335
336                 if(!write_pid(pidfilename)) {
337                         fprintf(stderr, _("Could not write pid file %s: %s\n"), pidfilename, strerror(errno));
338                         return false;
339                 }
340 #else
341                 if(!statushandle)
342                         exit(install_service());
343 #endif
344         }
345
346         openlogger(identname, use_logfile?LOGMODE_FILE:(do_detach?LOGMODE_SYSLOG:LOGMODE_STDERR));
347
348         logger(LOG_NOTICE, _("tincd %s (%s %s) starting, debug level %d"),
349                            VERSION, __DATE__, __TIME__, debug_level);
350
351         xalloc_fail_func = memory_full;
352
353         return true;
354 }
355
356 bool execute_script(const char *name, char **envp) {
357 #ifdef HAVE_SYSTEM
358         int status, len;
359         char *scriptname, *p;
360         int i;
361
362         cp();
363
364 #ifndef HAVE_MINGW
365         len = xasprintf(&scriptname, "\"%s/%s\"", confbase, name);
366 #else
367         len = xasprintf(&scriptname, "\"%s/%s.bat\"", confbase, name);
368 #endif
369         if(len < 0)
370                 return false;
371
372         scriptname[len - 1] = '\0';
373
374 #ifndef HAVE_TUNEMU
375         /* First check if there is a script */
376
377         if(access(scriptname + 1, F_OK)) {
378                 free(scriptname);
379                 return true;
380         }
381 #endif
382
383         ifdebug(STATUS) logger(LOG_INFO, _("Executing script %s"), name);
384
385 #ifdef HAVE_PUTENV
386         /* Set environment */
387         
388         for(i = 0; envp[i]; i++)
389                 putenv(envp[i]);
390 #endif
391
392         scriptname[len - 1] = '\"';
393         status = system(scriptname);
394
395         free(scriptname);
396
397         /* Unset environment */
398
399         for(i = 0; envp[i]; i++) {
400                 char *e = strchr(envp[i], '=');
401                 if(e) {
402                         p = alloca(e - envp[i] + 1);
403                         strncpy(p, envp[i], e - envp[i]);
404                         p[e - envp[i]] = '\0';
405                         putenv(p);
406                 }
407         }
408
409 #ifdef WEXITSTATUS
410         if(status != -1) {
411                 if(WIFEXITED(status)) { /* Child exited by itself */
412                         if(WEXITSTATUS(status)) {
413                                 logger(LOG_ERR, _("Script %s exited with non-zero status %d"),
414                                            name, WEXITSTATUS(status));
415                                 return false;
416                         }
417                 } else if(WIFSIGNALED(status)) {        /* Child was killed by a signal */
418                         logger(LOG_ERR, _("Script %s was killed by signal %d (%s)"),
419                                    name, WTERMSIG(status), strsignal(WTERMSIG(status)));
420                         return false;
421                 } else {                        /* Something strange happened */
422                         logger(LOG_ERR, _("Script %s terminated abnormally"), name);
423                         return false;
424                 }
425         } else {
426                 logger(LOG_ERR, _("System call `%s' failed: %s"), "system", strerror(errno));
427                 return false;
428         }
429 #endif
430 #endif
431         return true;
432 }
433
434
435 /*
436   Signal handlers.
437 */
438
439 #ifndef HAVE_MINGW
440 static RETSIGTYPE sigterm_handler(int a) {
441         logger(LOG_NOTICE, _("Got %s signal"), "TERM");
442         if(running)
443                 running = false;
444         else
445                 exit(1);
446 }
447
448 static RETSIGTYPE sigquit_handler(int a) {
449         logger(LOG_NOTICE, _("Got %s signal"), "QUIT");
450         if(running)
451                 running = false;
452         else
453                 exit(1);
454 }
455
456 static RETSIGTYPE fatal_signal_square(int a) {
457         logger(LOG_ERR, _("Got another fatal signal %d (%s): not restarting."), a,
458                    strsignal(a));
459         cp_trace();
460         exit(1);
461 }
462
463 static RETSIGTYPE fatal_signal_handler(int a) {
464         struct sigaction act;
465         logger(LOG_ERR, _("Got fatal signal %d (%s)"), a, strsignal(a));
466         cp_trace();
467
468         if(do_detach) {
469                 logger(LOG_NOTICE, _("Trying to re-execute in 5 seconds..."));
470
471                 act.sa_handler = fatal_signal_square;
472                 act.sa_mask = emptysigset;
473                 act.sa_flags = 0;
474                 sigaction(SIGSEGV, &act, NULL);
475
476                 close_network_connections();
477                 sleep(5);
478                 remove_pid(pidfilename);
479                 execvp(g_argv[0], g_argv);
480         } else {
481                 logger(LOG_NOTICE, _("Not restarting."));
482                 exit(1);
483         }
484 }
485
486 static RETSIGTYPE sighup_handler(int a) {
487         logger(LOG_NOTICE, _("Got %s signal"), "HUP");
488         sighup = true;
489 }
490
491 static RETSIGTYPE sigint_handler(int a) {
492         logger(LOG_NOTICE, _("Got %s signal"), "INT");
493
494         if(saved_debug_level != -1) {
495                 logger(LOG_NOTICE, _("Reverting to old debug level (%d)"),
496                         saved_debug_level);
497                 debug_level = saved_debug_level;
498                 saved_debug_level = -1;
499         } else {
500                 logger(LOG_NOTICE,
501                         _("Temporarily setting debug level to 5.  Kill me with SIGINT again to go back to level %d."),
502                         debug_level);
503                 saved_debug_level = debug_level;
504                 debug_level = 5;
505         }
506 }
507
508 static RETSIGTYPE sigalrm_handler(int a) {
509         logger(LOG_NOTICE, _("Got %s signal"), "ALRM");
510         sigalrm = true;
511 }
512
513 static RETSIGTYPE sigusr1_handler(int a) {
514         dump_connections();
515 }
516
517 static RETSIGTYPE sigusr2_handler(int a) {
518         dump_device_stats();
519         dump_nodes();
520         dump_edges();
521         dump_subnets();
522 }
523
524 static RETSIGTYPE sigwinch_handler(int a) {
525         do_purge = true;
526 }
527
528 static RETSIGTYPE unexpected_signal_handler(int a) {
529         logger(LOG_WARNING, _("Got unexpected signal %d (%s)"), a, strsignal(a));
530         cp_trace();
531 }
532
533 static RETSIGTYPE ignore_signal_handler(int a) {
534         ifdebug(SCARY_THINGS) logger(LOG_DEBUG, _("Ignored signal %d (%s)"), a, strsignal(a));
535 }
536
537 static struct {
538         int signal;
539         void (*handler)(int);
540 } sighandlers[] = {
541         {SIGHUP, sighup_handler},
542         {SIGTERM, sigterm_handler},
543         {SIGQUIT, sigquit_handler},
544         {SIGSEGV, fatal_signal_handler},
545         {SIGBUS, fatal_signal_handler},
546         {SIGILL, fatal_signal_handler},
547         {SIGPIPE, ignore_signal_handler},
548         {SIGINT, sigint_handler},
549         {SIGUSR1, sigusr1_handler},
550         {SIGUSR2, sigusr2_handler},
551         {SIGCHLD, ignore_signal_handler},
552         {SIGALRM, sigalrm_handler},
553         {SIGWINCH, sigwinch_handler},
554         {0, NULL}
555 };
556 #endif
557
558 void setup_signals(void) {
559 #ifndef HAVE_MINGW
560         int i;
561         struct sigaction act;
562
563         sigemptyset(&emptysigset);
564         act.sa_handler = NULL;
565         act.sa_mask = emptysigset;
566         act.sa_flags = 0;
567
568         /* Set a default signal handler for every signal, errors will be
569            ignored. */
570         for(i = 1; i < NSIG; i++) {
571                 if(!do_detach)
572                         act.sa_handler = SIG_DFL;
573                 else
574                         act.sa_handler = unexpected_signal_handler;
575                 sigaction(i, &act, NULL);
576         }
577
578         /* If we didn't detach, allow coredumps */
579         if(!do_detach)
580                 sighandlers[3].handler = SIG_DFL;
581
582         /* Then, for each known signal that we want to catch, assign a
583            handler to the signal, with error checking this time. */
584         for(i = 0; sighandlers[i].signal; i++) {
585                 act.sa_handler = sighandlers[i].handler;
586                 if(sigaction(sighandlers[i].signal, &act, NULL) < 0)
587                         fprintf(stderr, _("Installing signal handler for signal %d (%s) failed: %s\n"),
588                                         sighandlers[i].signal, strsignal(sighandlers[i].signal),
589                                         strerror(errno));
590         }
591 #endif
592 }