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