a06f3fe37fbddad06c53269b854e356e3d637d79
[tinc] / src / tincd.c
1 /*
2     tincd.c -- the main file for tincd
3     Copyright (C) 1998,1999,2000 Ivo Timmermans <itimmermans@bigfoot.com>
4                             2000 Guus Sliepen <guus@sliepen.warande.net>
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
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20     $Id: tincd.c,v 1.10.4.15 2000/10/21 11:52:08 guus Exp $
21 */
22
23 #include "config.h"
24
25 #include <errno.h>
26 #include <fcntl.h> 
27 #include <getopt.h>
28 #include <signal.h>
29 #include <stdio.h>
30 #include <sys/types.h>
31 #include <syslog.h>
32 #include <unistd.h>
33 #include <signal.h>
34 #include <openssl/rand.h>
35 #include <openssl/rsa.h>
36
37 #ifdef HAVE_SYS_IOCTL_H
38 # include <sys/ioctl.h>
39 #endif
40
41 #include <pidfile.h>
42 #include <utils.h>
43 #include <xalloc.h>
44
45 #include "conf.h"
46 #include "encr.h"
47 #include "net.h"
48 #include "netutl.h"
49 #include "protocol.h"
50
51 #include "system.h"
52
53 /* The name this program was run with. */
54 char *program_name;
55
56 /* If nonzero, display usage information and exit. */
57 static int show_help;
58
59 /* If nonzero, print the version on standard output and exit.  */
60 static int show_version;
61
62 /* If nonzero, it will attempt to kill a running tincd and exit. */
63 static int kill_tincd = 0;
64
65 /* If zero, don't detach from the terminal. */
66 static int do_detach = 1;
67
68 /* If nonzero, generate public/private keypair for this host/net. */
69 static int generate_keys = 0;
70
71 char *identname;                 /* program name for syslog */
72 char *pidfilename;               /* pid file location */
73 static pid_t ppid;               /* pid of non-detached part */
74 char **g_argv;                   /* a copy of the cmdline arguments */
75
76 void cleanup_and_exit(int);
77 int detach(void);
78 int kill_other(void);
79 void make_names(void);
80 RETSIGTYPE parent_exit(int a);
81 void setup_signals(void);
82 int write_pidfile(void);
83
84 static struct option const long_options[] =
85 {
86   { "kill", no_argument, NULL, 'k' },
87   { "net", required_argument, NULL, 'n' },
88   { "help", no_argument, &show_help, 1 },
89   { "version", no_argument, &show_version, 1 },
90   { "no-detach", no_argument, &do_detach, 0 },
91   { "keygen", optional_argument, NULL, 'K'},
92   { NULL, 0, NULL, 0 }
93 };
94
95 static void
96 usage(int status)
97 {
98   if(status != 0)
99     fprintf(stderr, _("Try `%s --help\' for more information.\n"), program_name);
100   else
101     {
102       printf(_("Usage: %s [option]...\n\n"), program_name);
103       printf(_("  -c, --config=DIR      Read configuration options from DIR.\n"
104                "  -D, --no-detach       Don't fork and detach.\n"
105                "  -d                    Increase debug level.\n"
106                "  -k, --kill            Attempt to kill a running tincd and exit.\n"
107                "  -n, --net=NETNAME     Connect to net NETNAME.\n"));
108       printf(_("  -K, --keygen[=BITS]   Generate public/private RSA keypair.\n"
109                "      --help            Display this help and exit.\n"
110                "      --version         Output version information and exit.\n\n"));
111       printf(_("Report bugs to tinc@nl.linux.org.\n"));
112     }
113   exit(status);
114 }
115
116 void
117 parse_options(int argc, char **argv, char **envp)
118 {
119   int r;
120   int option_index = 0;
121   config_t *p;
122
123   while((r = getopt_long(argc, argv, "c:Ddkn:K::", long_options, &option_index)) != EOF)
124     {
125       switch(r)
126         {
127         case 0: /* long option */
128           break;
129         case 'c': /* config file */
130           confbase = xmalloc(strlen(optarg)+1);
131           strcpy(confbase, optarg);
132           break;
133         case 'D': /* no detach */
134           do_detach = 0;
135           break;
136         case 'd': /* inc debug level */
137           debug_lvl++;
138           break;
139         case 'k': /* kill old tincds */
140           kill_tincd = 1;
141           break;
142         case 'n': /* net name given */
143           netname = xmalloc(strlen(optarg)+1);
144           strcpy(netname, optarg);
145           break;
146         case 'K': /* generate public/private keypair */
147           if(optarg)
148             {
149               generate_keys = atoi(optarg);
150               if(generate_keys < 512)
151                 {
152                   fprintf(stderr, _("Invalid argument! BITS must be a number equal to or greater than 512.\n"));
153                   usage(1);
154                 }
155               generate_keys &= ~7;      /* Round it to bytes */
156             }
157           else
158             generate_keys = 1024;
159           break;
160         case '?':
161           usage(1);
162         default:
163           break;
164         }
165     }
166 }
167
168 /* This function prettyprints the key generation process */
169
170 void indicator(int a, int b, void *p)
171 {
172   switch(a)
173   {
174     case 0:
175       fprintf(stderr, ".");
176       break;
177     case 1:
178       fprintf(stderr, "+");
179       break;
180     case 2:
181       fprintf(stderr, "-");
182       break;
183     case 3:
184       switch(b)
185         {
186           case 0:
187             fprintf(stderr, " p\n");      
188             break;
189           case 1:
190             fprintf(stderr, " q\n");
191             break;
192           default:
193             fprintf(stderr, "?");
194          }
195        break;
196     default:
197       fprintf(stderr, "?");
198   }
199 }
200
201 /* Generate a public/private RSA keypair, and possibly store it into the configuration file. */
202
203 int keygen(int bits)
204 {
205   RSA *rsa_key;
206
207   fprintf(stderr, _("Seeding the PRNG: please press some keys or move\nthe mouse if this program seems to have halted...\n"));
208   RAND_load_file("/dev/random", 1024);  /* OpenSSL PRNG state apparently uses 1024 bytes, but it seems pretty sufficient anyway :) */
209
210   fprintf(stderr, _("Generating %d bits keys:\n"), bits);
211   rsa_key = RSA_generate_key(bits, 0xFFFF, indicator, NULL);
212   if(!rsa_key)
213     {
214       fprintf(stderr, _("Error during key generation!"));
215       return -1;
216      }
217   else
218     fprintf(stderr, _("Done.\n"));
219
220   fprintf(stderr, _("Please copy the private key to tinc.conf and the\npublic key to your host configuration file:\n\n"));
221   printf("PublicKey = %s\n", BN_bn2hex(rsa_key->n));
222   printf("PrivateKey = %s\n", BN_bn2hex(rsa_key->d));
223   
224   fflush(stdin);
225   return 0;
226 }
227
228 void memory_full(int size)
229 {
230   syslog(LOG_ERR, _("Memory exhausted (last is %s:%d) (couldn't allocate %d bytes), exiting."), cp_file, cp_line, size);
231   exit(1);
232 }
233
234 /*
235   Detach from current terminal, write pidfile, kill parent
236 */
237 int detach(void)
238 {
239   int fd;
240   pid_t pid;
241
242   if(do_detach)
243     {
244       ppid = getpid();
245
246       if((pid = fork()) < 0)
247         {
248           perror("fork");
249           return -1;
250         }
251       if(pid) /* parent process */
252         {
253           signal(SIGTERM, parent_exit);
254 //        sleep(600); /* wait 10 minutes */
255           exit(1);
256         }
257     }
258   
259   if(write_pidfile())
260     return -1;
261
262   if(do_detach)
263     {
264       if((fd = open("/dev/tty", O_RDWR)) >= 0)
265         {
266           if(ioctl(fd, TIOCNOTTY, NULL))
267             {
268               perror("ioctl");
269               return -1;
270             }
271           close(fd);
272         }
273
274       if(setsid() < 0)
275         return -1;
276
277       kill(ppid, SIGTERM);
278     }
279   
280   chdir("/"); /* avoid keeping a mointpoint busy */
281
282   openlog(identname, LOG_CONS | LOG_PID, LOG_DAEMON);
283
284   if(debug_lvl > DEBUG_NOTHING)
285     syslog(LOG_NOTICE, _("tincd %s (%s %s) starting, debug level %d"),
286            VERSION, __DATE__, __TIME__, debug_lvl);
287   else
288     syslog(LOG_NOTICE, _("tincd %s starting"), VERSION);
289
290   xalloc_fail_func = memory_full;
291
292   return 0;
293 }
294
295 /*
296   Close network connections, and terminate neatly
297 */
298 void cleanup_and_exit(int c)
299 {
300   close_network_connections();
301
302   if(debug_lvl > DEBUG_NOTHING)
303     syslog(LOG_INFO, _("Total bytes written: tap %d, socket %d; bytes read: tap %d, socket %d"),
304            total_tap_out, total_socket_out, total_tap_in, total_socket_in);
305
306   closelog();
307   kill(ppid, SIGTERM);
308   exit(c);
309 }
310
311 /*
312   check for an existing tinc for this net, and write pid to pidfile
313 */
314 int write_pidfile(void)
315 {
316   int pid;
317
318   if((pid = check_pid(pidfilename)))
319     {
320       if(netname)
321         fprintf(stderr, _("A tincd is already running for net `%s' with pid %d.\n"),
322                 netname, pid);
323       else
324         fprintf(stderr, _("A tincd is already running with pid %d.\n"), pid);
325       return 1;
326     }
327
328   /* if it's locked, write-protected, or whatever */
329   if(!write_pid(pidfilename))
330     return 1;
331
332   return 0;
333 }
334
335 /*
336   kill older tincd for this net
337 */
338 int kill_other(void)
339 {
340   int pid;
341
342   if(!(pid = read_pid(pidfilename)))
343     {
344       if(netname)
345         fprintf(stderr, _("No other tincd is running for net `%s'.\n"), netname);
346       else
347         fprintf(stderr, _("No other tincd is running.\n"));
348       return 1;
349     }
350
351   errno = 0;    /* No error, sometimes errno is only changed on error */
352   /* ESRCH is returned when no process with that pid is found */
353   if(kill(pid, SIGTERM) && errno == ESRCH)
354     fprintf(stderr, _("Removing stale lock file.\n"));
355   remove_pid(pidfilename);
356
357   return 0;
358 }
359
360 /*
361   Set all files and paths according to netname
362 */
363 void make_names(void)
364 {
365   if(netname)
366     {
367       if(!pidfilename)
368         asprintf(&pidfilename, "/var/run/tinc.%s.pid", netname);
369       if(!confbase)
370         asprintf(&confbase, "%s/tinc/%s", CONFDIR, netname);
371       if(!identname)
372         asprintf(&identname, "tinc.%s", netname);
373     }
374   else
375     {
376       if(!pidfilename)
377         pidfilename = "/var/run/tinc.pid";
378       if(!confbase)
379         asprintf(&confbase, "%s/tinc", CONFDIR);
380       if(!identname)
381         identname = "tinc";
382     }
383 }
384
385 int
386 main(int argc, char **argv, char **envp)
387 {
388   program_name = argv[0];
389
390   setlocale (LC_ALL, "");
391   bindtextdomain (PACKAGE, LOCALEDIR);
392   textdomain (PACKAGE);
393
394   /* Do some intl stuff right now */
395   
396   unknown = _("unknown");
397
398   parse_options(argc, argv, envp);
399
400   if(show_version)
401     {
402       printf(_("%s version %s (built %s %s, protocol %d)\n"), PACKAGE, VERSION, __DATE__, __TIME__, PROT_CURRENT);
403       printf(_("Copyright (C) 1998,1999,2000 Ivo Timmermans, Guus Sliepen and others.\n"
404                "See the AUTHORS file for a complete list.\n\n"
405                "tinc comes with ABSOLUTELY NO WARRANTY.  This is free software,\n"
406                "and you are welcome to redistribute it under certain conditions;\n"
407                "see the file COPYING for details.\n"));
408
409       return 0;
410     }
411
412   if(show_help)
413     usage(0);
414
415   if(geteuid())
416     {
417       fprintf(stderr, _("You must be root to run this program. Sorry.\n"));
418       return 1;
419     }
420
421   g_argv = argv;
422
423   make_names();
424
425   if(generate_keys)
426     exit(keygen(generate_keys));
427
428   if(kill_tincd)
429     exit(kill_other());
430
431   if(read_server_config())
432     return 1;
433
434   setup_signals();
435
436   if(detach())
437     exit(0);
438
439 /* FIXME: wt* is this suppose to do?
440   if(security_init())
441     return 1;
442 */
443   for(;;)
444     {
445       if(!setup_network_connections())
446         {
447           main_loop();
448           cleanup_and_exit(1);
449          }
450       
451       syslog(LOG_ERR, _("Unrecoverable error"));
452       cp_trace();
453
454       if(do_detach)
455         {
456           syslog(LOG_NOTICE, _("Restarting in %d seconds!"), MAXTIMEOUT);
457           sleep(MAXTIMEOUT);
458         }
459       else
460         {
461           syslog(LOG_ERR, _("Aieee! Not restarting."));
462           exit(0);
463         }
464     }
465 }
466
467 RETSIGTYPE
468 sigterm_handler(int a)
469 {
470   if(debug_lvl > DEBUG_NOTHING)
471     syslog(LOG_NOTICE, _("Got TERM signal"));
472   cleanup_and_exit(0);
473 }
474
475 RETSIGTYPE
476 sigquit_handler(int a)
477 {
478   if(debug_lvl > DEBUG_NOTHING)
479     syslog(LOG_NOTICE, _("Got QUIT signal"));
480   cleanup_and_exit(0);
481 }
482
483 RETSIGTYPE
484 sigsegv_square(int a)
485 {
486   syslog(LOG_ERR, _("Got another SEGV signal: not restarting"));
487   exit(0);
488 }
489
490 RETSIGTYPE
491 sigsegv_handler(int a)
492 {
493   syslog(LOG_ERR, _("Got SEGV signal"));
494   cp_trace();
495
496   if(do_detach)
497     {
498       syslog(LOG_NOTICE, _("Trying to re-execute in 5 seconds..."));
499       signal(SIGSEGV, sigsegv_square);
500       close_network_connections();
501       sleep(5);
502       remove_pid(pidfilename);
503       execvp(g_argv[0], g_argv);
504     }
505   else
506     {
507       syslog(LOG_NOTICE, _("Aieee! Not restarting."));
508       exit(0);
509     }
510 }
511
512 RETSIGTYPE
513 sighup_handler(int a)
514 {
515   if(debug_lvl > DEBUG_NOTHING)
516     syslog(LOG_NOTICE, _("Got HUP signal, rereading configuration and restarting"));
517   sighup = 1;
518 }
519
520 RETSIGTYPE
521 sigint_handler(int a)
522 {
523   if(debug_lvl > DEBUG_NOTHING)
524     syslog(LOG_NOTICE, _("Got INT signal, exiting"));
525   cleanup_and_exit(0);
526 }
527
528 RETSIGTYPE
529 sigusr1_handler(int a)
530 {
531   dump_conn_list();
532 }
533
534 RETSIGTYPE
535 sigusr2_handler(int a)
536 {
537   if(debug_lvl > DEBUG_NOTHING)
538     syslog(LOG_NOTICE, _("Got USR2 signal, forcing new key generation"));
539 /* FIXME: reprogram this.
540   regenerate_keys();
541 */
542 }
543
544 RETSIGTYPE
545 sighuh(int a)
546 {
547   syslog(LOG_WARNING, _("Got unexpected signal %d (%s)"), a, strsignal(a));
548   cp_trace();
549 }
550
551 void
552 setup_signals(void)
553 {
554   int i;
555
556   for(i=0;i<32;i++)
557     signal(i,sighuh);
558
559   if(signal(SIGTERM, SIG_IGN) != SIG_ERR)
560     signal(SIGTERM, sigterm_handler);
561   if(signal(SIGQUIT, SIG_IGN) != SIG_ERR)
562     signal(SIGQUIT, sigquit_handler);
563   if(signal(SIGSEGV, SIG_IGN) != SIG_ERR)
564     signal(SIGSEGV, sigsegv_handler);
565   if(signal(SIGHUP, SIG_IGN) != SIG_ERR)
566     signal(SIGHUP, sighup_handler);
567   signal(SIGPIPE, SIG_IGN);
568   if(signal(SIGINT, SIG_IGN) != SIG_ERR)
569     signal(SIGINT, sigint_handler);
570   signal(SIGUSR1, sigusr1_handler);
571   signal(SIGUSR2, sigusr2_handler);
572   signal(SIGCHLD, SIG_IGN);
573 }
574
575 RETSIGTYPE parent_exit(int a)
576 {
577   exit(0);
578 }