0b02aad4daef42e92bd62bee3a44f739b96f10d6
[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.30 2000/11/16 22:12:23 zarq 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 <string.h>
35 #include <termios.h>
36
37 #ifdef HAVE_SYS_IOCTL_H
38 # include <sys/ioctl.h>
39 #endif
40
41 #ifdef HAVE_OPENSSL_RAND_H
42 # include <openssl/rand.h>
43 #else
44 # include <rand.h>
45 #endif
46
47 #ifdef HAVE_OPENSSL_RSA_H
48 # include <openssl/rsa.h>
49 #else
50 # include <rsa.h>
51 #endif
52
53 #ifdef HAVE_OPENSSL_ERR_H
54 # include <openssl/err.h>
55 #else
56 # include <err.h>
57 #endif
58
59
60
61 #include <utils.h>
62 #include <xalloc.h>
63
64 #include "conf.h"
65 #include "net.h"
66 #include "netutl.h"
67 #include "protocol.h"
68 #include "subnet.h"
69
70 #include "system.h"
71
72 /* The name this program was run with. */
73 char *program_name;
74
75 /* If nonzero, display usage information and exit. */
76 static int show_help;
77
78 /* If nonzero, print the version on standard output and exit.  */
79 static int show_version;
80
81 /* If nonzero, it will attempt to kill a running tincd and exit. */
82 static int kill_tincd = 0;
83
84 /* If zero, don't detach from the terminal. */
85 extern int do_detach;
86
87 /* If nonzero, generate public/private keypair for this host/net. */
88 static int generate_keys = 0;
89
90 char *identname;                 /* program name for syslog */
91 char *pidfilename;               /* pid file location */
92 char **g_argv;                   /* a copy of the cmdline arguments */
93 char **environment;              /* A pointer to the environment on
94                                     startup */
95
96 void cleanup_and_exit(int);
97 int kill_other(void);
98 void make_names(void);
99 int write_pidfile(void);
100
101 static struct option const long_options[] =
102 {
103   { "config", required_argument, NULL, 'c' },
104   { "kill", no_argument, NULL, 'k' },
105   { "net", required_argument, NULL, 'n' },
106   { "help", no_argument, &show_help, 1 },
107   { "version", no_argument, &show_version, 1 },
108   { "no-detach", no_argument, &do_detach, 0 },
109   { "generate-keys", optional_argument, NULL, 'K'},
110   { NULL, 0, NULL, 0 }
111 };
112
113 static void
114 usage(int status)
115 {
116   if(status != 0)
117     fprintf(stderr, _("Try `%s --help\' for more information.\n"), program_name);
118   else
119     {
120       printf(_("Usage: %s [option]...\n\n"), program_name);
121       printf(_("  -c, --config=DIR           Read configuration options from DIR.\n"
122                "  -D, --no-detach            Don't fork and detach.\n"
123                "  -d                         Increase debug level.\n"
124                "  -k, --kill                 Attempt to kill a running tincd and exit.\n"
125                "  -n, --net=NETNAME          Connect to net NETNAME.\n"));
126       printf(_("  -K, --generate-keys[=BITS] Generate public/private RSA keypair.\n"
127                "      --help                 Display this help and exit.\n"
128                "      --version              Output version information and exit.\n\n"));
129       printf(_("Report bugs to tinc@nl.linux.org.\n"));
130     }
131   exit(status);
132 }
133
134 void
135 parse_options(int argc, char **argv, char **envp)
136 {
137   int r;
138   int option_index = 0;
139   
140   while((r = getopt_long(argc, argv, "c:Ddkn:K::", long_options, &option_index)) != EOF)
141     {
142       switch(r)
143         {
144         case 0: /* long option */
145           break;
146         case 'c': /* config file */
147           confbase = xmalloc(strlen(optarg)+1);
148           strcpy(confbase, optarg);
149           break;
150         case 'D': /* no detach */
151           do_detach = 0;
152           break;
153         case 'd': /* inc debug level */
154           debug_lvl++;
155           break;
156         case 'k': /* kill old tincds */
157           kill_tincd = 1;
158           break;
159         case 'n': /* net name given */
160           netname = xmalloc(strlen(optarg)+1);
161           strcpy(netname, optarg);
162           break;
163         case 'K': /* generate public/private keypair */
164           if(optarg)
165             {
166               generate_keys = atoi(optarg);
167               if(generate_keys < 512)
168                 {
169                   fprintf(stderr, _("Invalid argument! BITS must be a number equal to or greater than 512.\n"));
170                   usage(1);
171                 }
172               generate_keys &= ~7;      /* Round it to bytes */
173             }
174           else
175             generate_keys = 1024;
176           break;
177         case '?':
178           usage(1);
179         default:
180           break;
181         }
182     }
183 }
184
185 /* This function prettyprints the key generation process */
186
187 void indicator(int a, int b, void *p)
188 {
189   switch(a)
190   {
191     case 0:
192       fprintf(stderr, ".");
193       break;
194     case 1:
195       fprintf(stderr, "+");
196       break;
197     case 2:
198       fprintf(stderr, "-");
199       break;
200     case 3:
201       switch(b)
202         {
203           case 0:
204             fprintf(stderr, " p\n");      
205             break;
206           case 1:
207             fprintf(stderr, " q\n");
208             break;
209           default:
210             fprintf(stderr, "?");
211          }
212        break;
213     default:
214       fprintf(stderr, "?");
215   }
216 }
217
218 /* Generate a public/private RSA keypair, and possibly store it into the configuration file. */
219
220 int keygen(int bits)
221 {
222   RSA *rsa_key;
223
224   fprintf(stderr, _("Generating %d bits keys:\n"), bits);
225   rsa_key = RSA_generate_key(bits, 0xFFFF, indicator, NULL);
226   if(!rsa_key)
227     {
228       fprintf(stderr, _("Error during key generation!"));
229       return -1;
230      }
231   else
232     fprintf(stderr, _("Done.\n"));
233
234   fprintf(stderr, _("Please copy the private key to tinc.conf and the\npublic key to your host configuration file:\n\n"));
235   printf("PublicKey = %s\n", BN_bn2hex(rsa_key->n));
236   printf("PrivateKey = %s\n", BN_bn2hex(rsa_key->d));
237   
238   fflush(stdin);
239   return 0;
240 }
241
242 /*
243   Set all files and paths according to netname
244 */
245 void make_names(void)
246 {
247   if(netname)
248     {
249       if(!pidfilename)
250         asprintf(&pidfilename, "/var/run/tinc.%s.pid", netname);
251       if(!confbase)
252         asprintf(&confbase, "%s/tinc/%s", CONFDIR, netname);
253       else
254         fprintf(stderr, _("Both netname and configuration directory given, using the latter...\n"));
255       if(!identname)
256         asprintf(&identname, "tinc.%s", netname);
257     }
258   else
259     {
260       if(!pidfilename)
261         pidfilename = "/var/run/tinc.pid";
262       if(!confbase)
263         asprintf(&confbase, "%s/tinc", CONFDIR);
264       if(!identname)
265         identname = "tinc";
266     }
267 }
268
269 int
270 main(int argc, char **argv, char **envp)
271 {
272   program_name = argv[0];
273
274   setlocale (LC_ALL, "");
275   bindtextdomain (PACKAGE, LOCALEDIR);
276   textdomain (PACKAGE);
277
278   /* Do some intl stuff right now */
279   
280   unknown = _("unknown");
281
282   environment = envp;
283   parse_options(argc, argv, envp);
284
285   if(show_version)
286     {
287       printf(_("%s version %s (built %s %s, protocol %d)\n"), PACKAGE, VERSION, __DATE__, __TIME__, PROT_CURRENT);
288       printf(_("Copyright (C) 1998,1999,2000 Ivo Timmermans, Guus Sliepen and others.\n"
289                "See the AUTHORS file for a complete list.\n\n"
290                "tinc comes with ABSOLUTELY NO WARRANTY.  This is free software,\n"
291                "and you are welcome to redistribute it under certain conditions;\n"
292                "see the file COPYING for details.\n"));
293
294       return 0;
295     }
296
297   if(show_help)
298     usage(0);
299
300   if(geteuid())
301     {
302       fprintf(stderr, _("You must be root to run this program. Sorry.\n"));
303       return 1;
304     }
305
306   g_argv = argv;
307
308   make_names();
309
310   /* Slllluuuuuuurrrrp! */
311
312   RAND_load_file("/dev/urandom", 1024);
313
314   if(generate_keys)
315     exit(keygen(generate_keys));
316
317   if(kill_tincd)
318     exit(kill_other());
319
320   if(read_server_config())
321     return 1;
322
323   if(detach())
324     exit(0);
325
326   if(debug_lvl >= DEBUG_ERROR)
327     ERR_load_crypto_strings();
328     
329   for(;;)
330     {
331       if(!setup_network_connections())
332         {
333           main_loop();
334           cleanup_and_exit(1);
335         }
336       
337       syslog(LOG_ERR, _("Unrecoverable error"));
338       cp_trace();
339
340       if(do_detach)
341         {
342           syslog(LOG_NOTICE, _("Restarting in %d seconds!"), MAXTIMEOUT);
343           sleep(MAXTIMEOUT);
344         }
345       else
346         {
347           syslog(LOG_ERR, _("Not restarting."));
348           exit(0);
349         }
350     }
351 }
352