New upstream version 0.3.7
[anytun.git] / src / options.cpp
1 /*
2  *  anytun
3  *
4  *  The secure anycast tunneling protocol (satp) defines a protocol used
5  *  for communication between any combination of unicast and anycast
6  *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
7  *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
8  *  ethernet, ip, arp ...). satp directly includes cryptography and
9  *  message authentication based on the methods used by SRTP.  It is
10  *  intended to deliver a generic, scaleable and secure solution for
11  *  tunneling and relaying of packets of any protocol.
12  *
13  *
14  *  Copyright (C) 2007-2014 Markus Grüneis, Othmar Gsenger, Erwin Nindl,
15  *                          Christian Pointner <satp@wirdorange.org>
16  *
17  *  This file is part of Anytun.
18  *
19  *  Anytun is free software: you can redistribute it and/or modify
20  *  it under the terms of the GNU General Public License as published by
21  *  the Free Software Foundation, either version 3 of the License, or
22  *  any later version.
23  *
24  *  Anytun is distributed in the hope that it will be useful,
25  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
26  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  *  GNU General Public License for more details.
28  *
29  *  You should have received a copy of the GNU General Public License
30  *  along with Anytun.  If not, see <http://www.gnu.org/licenses/>.
31  *
32  *  In addition, as a special exception, the copyright holders give
33  *  permission to link the code of portions of this program with the
34  *  OpenSSL library under certain conditions as described in each
35  *  individual source file, and distribute linked combinations
36  *  including the two.
37  *  You must obey the GNU General Public License in all respects
38  *  for all of the code used other than OpenSSL.  If you modify
39  *  file(s) with this exception, you may extend this exception to your
40  *  version of the file(s), but you are not obligated to do so.  If you
41  *  do not wish to do so, delete this exception statement from your
42  *  version.  If you delete this exception statement from all source
43  *  files in the program, then also delete it here.
44  */
45
46 #include <cstring>
47 #include <iostream>
48 #include <queue>
49 #include <string>
50 #include <sstream>
51
52 #include "datatypes.h"
53 #include "version.h"
54
55 #include "options.h"
56 #include "log.h"
57 #include "authAlgoFactory.h"
58
59 std::ostream& operator<<(std::ostream& stream, syntax_error const& error)
60 {
61   stream << "syntax error: " << error.what() << std::endl;
62   if(error.pos >= 0) {
63     stream << "              ";
64     for(int32_t i = 0; i < error.pos; ++i) { stream << " "; }
65     return stream << "^";
66   }
67   return stream;
68 }
69
70 std::ostream& operator<<(std::ostream& stream, role_t const& role)
71 {
72   switch(role) {
73   case ROLE_LEFT:
74     stream << "left";
75     break;
76   case ROLE_RIGHT:
77     stream << "right";
78     break;
79   default:
80     stream << "unknown";
81     break;
82   }
83   return stream;
84 }
85
86 void OptionHost::init(std::string addrPort)
87 {
88   std::string origAddrPort(addrPort);
89   size_t pos = addrPort.find_first_of("[");
90
91   if(pos != std::string::npos && pos != 0) {
92     throw syntax_error(origAddrPort, pos);  // an [ was found but not at the beginning;
93   }
94
95   bool hasPort = false;
96   if(pos != std::string::npos) {
97     addrPort.erase(pos, 1);
98     pos = addrPort.find_first_of("]");
99
100     if(pos == std::string::npos) {
101       throw syntax_error(origAddrPort, origAddrPort.length());  //no trailing ] although an leading [ was found
102     }
103
104     if(pos < addrPort.length()-2) {
105       if(addrPort[pos+1] != ':') {
106         throw syntax_error(origAddrPort, pos+2);  // wrong port delimieter
107       }
108
109       addrPort[pos+1] = '/';
110       hasPort = true;
111     } else if(pos != addrPort.length()-1) {
112       throw syntax_error(origAddrPort, pos+2);  // too few characters left
113     }
114
115     addrPort.erase(pos, 1);
116   } else {
117     pos = addrPort.find_first_of(":");
118     if(pos != std::string::npos && pos == addrPort.find_last_of(":")) {
119       // an ':' has been found and it is the only one -> assuming port present
120       hasPort = true;
121       addrPort[pos] = '/';
122     }
123   }
124
125   if(hasPort) {
126     std::stringstream tmp_stream(addrPort);
127
128     getline(tmp_stream, addr, '/');
129     if(!tmp_stream.good()) {
130       throw syntax_error(origAddrPort, addr.length());
131     }
132
133     tmp_stream >> port;
134   } else {
135     addr = addrPort;
136     port = "2323"; // default sync port
137   }
138 }
139
140 std::istream& operator>>(std::istream& stream, OptionHost& host)
141 {
142   std::string tmp;
143   stream >> tmp;
144   host.init(tmp);
145   return stream;
146 }
147
148 void OptionNetwork::init(std::string network)
149 {
150   std::stringstream tmp_stream(network);
151   getline(tmp_stream, net_addr, '/');
152   if(!tmp_stream.good()) {
153     throw syntax_error(network, net_addr.length());
154   }
155   tmp_stream >> prefix_length;
156 }
157
158 std::istream& operator>>(std::istream& stream, OptionNetwork& network)
159 {
160   std::string tmp;
161   stream >> tmp;
162   network.init(tmp);
163   return stream;
164 }
165
166 Options& gOpt = Options::instance();
167
168 Options& Options::instance()
169 {
170   static Options instance;
171   return instance;
172 }
173
174 Options::Options() : key_(uint32_t(0)), salt_(uint32_t(0))
175 {
176 #if defined(ANYCTR_OPTIONS)
177   progname_ = "anytun-controld";
178 #elif defined(ANYCONF_OPTIONS)
179   progname_ = "anytun-config";
180 #else
181   progname_ = "anytun";
182 #endif
183
184   cluster_opts = false;
185   connection_opts = false;
186
187   daemonize_ = true;
188   username_ = "";
189   groupname_ = "";
190   chroot_dir_ = "";
191   pid_file_ = "";
192
193   debug_ = false;
194
195   file_name_ = "";
196   bind_to_.addr = "127.0.0.1";
197   bind_to_.port = "2323";
198
199   resolv_addr_type_ = ANY;
200
201   local_.addr = "";
202   local_.port = "4444";
203   remote_.addr = "";
204   remote_.port = "4444";
205   local_sync_.addr = "";
206   local_sync_.port = "";
207
208   dev_name_ = "";
209   dev_type_ = "";
210   post_up_script_ = "";
211
212   sender_id_ = 0;
213   mux_ = 0;
214   seq_window_size_ = 0;
215
216 #if !defined(ANYCONF_OPTIONS)
217 #ifndef NO_CRYPT
218   cipher_ = "aes-ctr";
219   auth_algo_ = "sha1";
220   auth_tag_length_ = 10;
221   kd_prf_ = "aes-ctr";
222 #else
223   cipher_ = "null";
224   auth_algo_ = "null";
225   auth_tag_length_ = 0;
226   kd_prf_ = "null";
227 #endif
228 #else
229   cipher_ = "null";
230   auth_algo_ = "null";
231   auth_tag_length_ = 0;
232   kd_prf_ = "aes-ctr";
233 #endif
234   role_ = ROLE_LEFT;
235 }
236
237 Options::~Options()
238 {
239 }
240
241 #define NOTHING
242
243 #define PARSE_BOOL_PARAM(SHORT, LONG, VALUE, DO_POST)                           \
244     else if(str == SHORT || str == LONG) {                                      \
245       VALUE = true;                                                             \
246       DO_POST;                                                                  \
247     }
248
249 #define PARSE_INVERSE_BOOL_PARAM(SHORT, LONG, VALUE, DO_POST)                   \
250     else if(str == SHORT || str == LONG) {                                      \
251       VALUE = false;                                                            \
252       DO_POST;                                                                  \
253     }
254
255 #define PARSE_SIGNED_INT_PARAM(SHORT, LONG, VALUE, DO_POST)                     \
256     else if(str == SHORT || str == LONG)                                        \
257     {                                                                           \
258       if(argc < 1)                                                              \
259         throw syntax_error(str, str.length());                                  \
260       std::stringstream tmp;                                                    \
261       tmp << argv[i+1];                                                         \
262       tmp >> VALUE;                                                             \
263       argc--;                                                                   \
264       i++;                                                                      \
265       DO_POST;                                                                  \
266     }
267
268 #define PARSE_SCALAR_PARAM(SHORT, LONG, VALUE, DO_POST)                         \
269     else if(str == SHORT || str == LONG)                                        \
270     {                                                                           \
271       if(argc < 1)                                                              \
272         throw syntax_error(str, str.length());                                  \
273       if(argv[i+1][0] == '-') {                                                 \
274         uint32_t pos = str.length() + 1;                                       \
275         throw syntax_error(str.append(" ").append(argv[i+1]), pos);             \
276       }                                                                         \
277       std::stringstream tmp;                                                    \
278       tmp << argv[i+1];                                                         \
279       tmp >> VALUE;                                                             \
280       argc--;                                                                   \
281       i++;                                                                      \
282       DO_POST;                                                                  \
283     }
284
285 #define PARSE_SCALAR_PARAM2(SHORT, LONG, VALUE1, VALUE2, DO_POST)               \
286     else if(str == SHORT || str == LONG)                                        \
287     {                                                                           \
288       if(argc < 1)                                                              \
289         throw syntax_error(str, str.length());                                  \
290       if(argc < 2)                                                              \
291         throw syntax_error(str.append(" ").append(argv[i+1]), str.length());    \
292       if(argv[i+1][0] == '-') {                                                 \
293         uint32_t pos = str.length() + 1;                                       \
294         throw syntax_error(str.append(" ").append(argv[i+1]), pos);             \
295       }                                                                         \
296       if(argv[i+2][0] == '-') {                                                 \
297         uint32_t pos = str.length() + 1 + strlen(argv[i+1]) + 1;               \
298         throw syntax_error(str.append(" ").append(argv[i+1]).append(" ").append(argv[i+2]), pos); \
299       }                                                                         \
300       std::stringstream tmp;                                                    \
301       tmp << argv[i+1] << " " << argv[i+2];                                     \
302       tmp >> VALUE1;                                                            \
303       tmp >> VALUE2;                                                            \
304       argc-=2;                                                                  \
305       i+=2;                                                                     \
306       DO_POST;                                                                  \
307     }
308
309 #define PARSE_CSLIST_PARAM(SHORT, LONG, LIST, TYPE, DO_POST)                    \
310     else if(str == SHORT || str == LONG)                                        \
311     {                                                                           \
312       if(argc < 1)                                                              \
313         throw syntax_error(str, str.length());                                  \
314       if(argv[i+1][0] == '-') {                                                 \
315         uint32_t pos = str.length() + 1;                                       \
316         throw syntax_error(str.append(" ").append(argv[i+1]), pos);             \
317       }                                                                         \
318       std::stringstream tmp(argv[i+1]);                                         \
319       while (tmp.good())                                                        \
320       {                                                                         \
321         std::string tmp_line;                                                   \
322         getline(tmp,tmp_line,',');                                              \
323         LIST.push_back(TYPE(tmp_line));                                         \
324       }                                                                         \
325       argc--;                                                                   \
326       i++;                                                                      \
327       DO_POST;                                                                  \
328     }
329
330 #define PARSE_HEXSTRING_PARAM_SEC(SHORT, LONG, VALUE, DO_POST)                  \
331     else if(str == SHORT || str == LONG)                                        \
332     {                                                                           \
333       if(argc < 1)                                                              \
334         throw syntax_error(str, str.length());                                  \
335       if(argv[i+1][0] == '-') {                                                 \
336         uint32_t pos = str.length() + 1;                                       \
337         throw syntax_error(str.append(" ").append(argv[i+1]), pos);             \
338       }                                                                         \
339       VALUE = Buffer(std::string(argv[i+1]));                                   \
340       for(size_t j=0; j < strlen(argv[i+1]); ++j)                               \
341         argv[i+1][j] = '#';                                                     \
342       argc--;                                                                   \
343       i++;                                                                      \
344       DO_POST;                                                                  \
345     }
346
347 #define PARSE_PHRASE_PARAM_SEC(SHORT, LONG, VALUE, DO_POST)                     \
348     else if(str == SHORT || str == LONG)                                        \
349     {                                                                           \
350       if(argc < 1)                                                              \
351         throw syntax_error(str, str.length());                                  \
352       if(argv[i+1][0] == '-') {                                                 \
353         uint32_t pos = str.length() + 1;                                       \
354         throw syntax_error(str.append(" ").append(argv[i+1]), pos);             \
355       }                                                                         \
356       VALUE = argv[i+1];                                                        \
357       for(size_t j=0; j < strlen(argv[i+1]); ++j)                               \
358         argv[i+1][j] = '#';                                                     \
359       argc--;                                                                   \
360       i++;                                                                      \
361       DO_POST;                                                                  \
362     }
363
364 #define PARSE_STRING_LIST(SHORT, LONG, LIST, DO_POST)                           \
365     else if(str == SHORT || str == LONG)                                        \
366     {                                                                           \
367       if(argc < 1)                                                              \
368         throw syntax_error(str, str.length());                                  \
369       if(argv[i+1][0] == '-') {                                                 \
370         uint32_t pos = str.length() + 1;                                       \
371         throw syntax_error(str.append(" ").append(argv[i+1]), pos);             \
372       }                                                                         \
373       LIST.push_back(argv[i+1]);                                                \
374       argc--;                                                                   \
375       i++;                                                                      \
376       DO_POST;                                                                  \
377     }
378
379 bool Options::parse(int argc, char* argv[])
380 {
381   WritersLock lock(mutex);
382
383   progname_ = argv[0];
384   argc--;
385   bool ipv4_only = false, ipv6_only = false;
386   std::string role = "";
387   for(int i=1; argc > 0; ++i) {
388     std::string str(argv[i]);
389     argc--;
390
391     if(str == "-h" || str == "--help") {
392       printUsage();
393       return false;
394     } else if(str == "-v" || str == "--version") {
395       printVersion();
396       return false;
397     }
398
399 #if defined(ANYTUN_OPTIONS) || defined(ANYCTR_OPTIONS)
400
401 #if !defined(_MSC_VER) && !defined(MINGW)
402     PARSE_INVERSE_BOOL_PARAM("-D","--nodaemonize", daemonize_, NOTHING)
403     PARSE_SCALAR_PARAM("-u","--username", username_, NOTHING)
404     PARSE_SCALAR_PARAM("-g","--groupname", groupname_, NOTHING)
405     PARSE_SCALAR_PARAM("-C","--chroot", chroot_dir_, NOTHING)
406     PARSE_SCALAR_PARAM("-P","--write-pid", pid_file_, NOTHING)
407 #endif
408
409 #endif
410
411     PARSE_STRING_LIST("-L","--log", log_targets_, NOTHING)
412     PARSE_BOOL_PARAM("-U","--debug", debug_, NOTHING)
413
414 #if defined(ANYCTR_OPTIONS)
415
416     PARSE_SCALAR_PARAM("-f","--file", file_name_, NOTHING)
417     PARSE_SCALAR_PARAM("-X","--control-host", bind_to_, NOTHING)
418
419 #endif
420 #if defined(ANYTUN_OPTIONS)
421
422     PARSE_SCALAR_PARAM("-i","--interface", local_.addr, NOTHING)
423     PARSE_SCALAR_PARAM("-p","--port", local_.port, NOTHING)
424     PARSE_SCALAR_PARAM("-s","--sender-id", sender_id_, NOTHING)
425
426 #endif
427 #if defined(ANYTUN_OPTIONS) || defined(ANYCONF_OPTIONS)
428
429     PARSE_SCALAR_PARAM("-r","--remote-host", remote_.addr, connection_opts = true)
430     PARSE_SCALAR_PARAM("-o","--remote-port", remote_.port, connection_opts = true)
431     PARSE_BOOL_PARAM("-4","--ipv4-only", ipv4_only, connection_opts = true)
432     PARSE_BOOL_PARAM("-6","--ipv6-only", ipv6_only, connection_opts = true)
433
434 #endif
435 #if defined(ANYTUN_OPTIONS)
436
437     PARSE_SCALAR_PARAM("-I","--sync-interface", local_sync_.addr, cluster_opts = true)
438     PARSE_SCALAR_PARAM("-S","--sync-port", local_sync_.port, cluster_opts = true)
439     PARSE_CSLIST_PARAM("-M","--sync-hosts", remote_sync_hosts_, OptionHost, cluster_opts = true)
440     PARSE_CSLIST_PARAM("-X","--control-host", remote_sync_hosts_, OptionHost, cluster_opts = true)
441
442     PARSE_SCALAR_PARAM("-d","--dev", dev_name_, NOTHING)
443     PARSE_SCALAR_PARAM("-t","--type", dev_type_, NOTHING)
444     PARSE_SCALAR_PARAM("-n","--ifconfig", ifconfig_param_, NOTHING)
445     PARSE_SCALAR_PARAM("-x","--post-up-script", post_up_script_, NOTHING)
446
447 #endif
448 #if defined(ANYTUN_OPTIONS) || defined(ANYCONF_OPTIONS)
449
450 #ifndef NO_ROUTING
451     PARSE_CSLIST_PARAM("-R","--route", routes_, OptionNetwork, connection_opts = true)
452 #endif
453
454     PARSE_SCALAR_PARAM("-m","--mux", mux_, connection_opts = true)
455     PARSE_SCALAR_PARAM("-w","--window-size", seq_window_size_, connection_opts = true)
456
457 #ifndef NO_CRYPT
458     PARSE_SCALAR_PARAM("-k","--kd-prf", kd_prf_, connection_opts = true)
459     PARSE_SCALAR_PARAM("-e","--role", role, connection_opts = true)
460 #ifndef NO_PASSPHRASE
461     PARSE_PHRASE_PARAM_SEC("-E","--passphrase", passphrase_, connection_opts = true)
462 #endif
463     PARSE_HEXSTRING_PARAM_SEC("-K","--key", key_, connection_opts = true)
464     PARSE_HEXSTRING_PARAM_SEC("-A","--salt", salt_, connection_opts = true)
465 #endif
466
467 #endif
468 #if defined(ANYTUN_OPTIONS)
469
470 #ifndef NO_CRYPT
471     PARSE_SCALAR_PARAM("-c","--cipher", cipher_, NOTHING)
472     PARSE_SCALAR_PARAM("-a","--auth-algo", auth_algo_, NOTHING)
473     PARSE_SCALAR_PARAM("-b","--auth-tag-length", auth_tag_length_, NOTHING)
474 #endif
475
476 #endif
477     else {
478       throw syntax_error(str, 0);
479     }
480   }
481   if(ipv4_only && ipv6_only) {
482     throw syntax_error("-4 and -6 are mutual exclusive", -1);
483   }
484   if(ipv4_only) {
485     resolv_addr_type_ = IPV4_ONLY;
486   }
487   if(ipv6_only) {
488     resolv_addr_type_ = IPV6_ONLY;
489   }
490
491   if(role != "") {
492     if(role == "alice" || role == "server" || role == "left") {
493       role_ = ROLE_LEFT;
494     } else if(role == "bob" || role == "client" || role == "right") {
495       role_ = ROLE_RIGHT;
496     } else {
497       throw syntax_error("unknown role name: " + role, -1);
498     }
499   }
500
501   if(debug_) {
502     log_targets_.push_back("stdout:5");
503     daemonize_ = false;
504   }
505
506   if(log_targets_.empty()) {
507 #if !defined(_MSC_VER) && !defined(MINGW)
508 #if !defined(ANYCONF_OPTIONS)
509     log_targets_.push_back(std::string("syslog:3,").append(progname_).append(",daemon"));
510 #else
511     log_targets_.push_back("stderr:2");
512 #endif
513 #else
514 #ifdef WIN_SERVICE
515     log_targets_.push_back(std::string("eventlog:3,").append(progname_));
516 #else
517     log_targets_.push_back("stdout:3");
518 #endif
519 #endif
520   }
521
522   return true;
523 }
524
525 void Options::parse_post()
526 {
527 #if defined(ANYTUN_OPTIONS)
528   if(cluster_opts && connection_opts) {
529     cLog.msg(Log::PRIO_WARNING) << "you have provided options for cluster support as well as connection oriented options, we strongly recommend to use anytun-config and anytun-controld when building a cluster";
530   }
531
532   if(cipher_ == "null" && auth_algo_ == "null") {
533     kd_prf_ = "null";
534   }
535   if((cipher_ != "null" || auth_algo_ != "null") && kd_prf_ == "null") {
536     cLog.msg(Log::PRIO_WARNING) << "using NULL key derivation with encryption and or authentication enabled!";
537   }
538
539   uint32_t tag_len_max = AuthAlgoFactory::getDigestLength(auth_algo_);
540   if(!tag_len_max) { auth_tag_length_ = 0; }
541   else if(tag_len_max < auth_tag_length_) {
542     cLog.msg(Log::PRIO_WARNING) << auth_algo_ << " auth algo can't generate tags of length " << auth_tag_length_ << ", using maximum tag length(" << tag_len_max << ")";
543     auth_tag_length_ = tag_len_max;
544   }
545 #endif
546
547   if(dev_name_ == "" && dev_type_ == "") {
548     dev_type_ = "tun";
549   }
550 }
551
552 void Options::printVersion()
553 {
554 #if defined(ANYCTR_OPTIONS)
555   std::cout << "anytun-controld";
556 #elif defined(ANYCONF_OPTIONS)
557   std::cout << "anytun-config";
558 #else
559   std::cout << "anytun";
560 #endif
561   std::cout << VERSION_STRING << std::endl;
562
563 #if defined(__clang__)
564   std::cout << "built using CLANG " << __clang_version__ << " with " << CRYPTO_LIB_NAME << " crypto library." << std::endl;
565 #elif defined(__GNUC__)
566   std::cout << "built using GCC " << __GNUC__ << '.' << __GNUC_MINOR__ << '.' << __GNUC_PATCHLEVEL__
567             << " with " << CRYPTO_LIB_NAME << " crypto library." << std::endl;
568 #else
569   std::cout << "built using an unknown compiler " << CRYPTO_LIB_NAME << " crypto library." << std::endl;
570 #endif
571 }
572
573 void Options::printUsage()
574 {
575   std::cout << "USAGE:" << std::endl;
576
577 #if defined(ANYCTR_OPTIONS)
578   std::cout << "anytun-controld " << std::endl;
579 #elif defined(ANYCONF_OPTIONS)
580   std::cout << "anytun-config " << std::endl;
581 #else
582   std::cout << "anytun " << std::endl;
583 #endif
584
585   std::cout << "   [-h|--help]                         prints this..." << std::endl;
586   std::cout << "   [-v|--version]                      print version info and exit" << std::endl;
587
588 #if defined(ANYTUN_OPTIONS) || defined(ANYCTR_OPTIONS)
589
590 #if !defined(_MSC_VER) && !defined(MINGW)
591   std::cout << "   [-D|--nodaemonize]                  don't run in background" << std::endl;
592   std::cout << "   [-u|--username] <username>          change to this user" << std::endl;
593   std::cout << "   [-g|--groupname] <groupname>        change to this group" << std::endl;
594   std::cout << "   [-C|--chroot] <path>                chroot to this directory" << std::endl;
595   std::cout << "   [-P|--write-pid] <path>             write pid to this file" << std::endl;
596 #endif
597
598 #endif
599
600   std::cout << "   [-L|--log] <target>:<level>[,<param1>[,<param2>..]]" << std::endl;
601   std::cout << "                                       add a log target, can be invoked several times" << std::endl;
602   std::cout << "                                       i.e.: stdout:5" << std::endl;
603   std::cout << "   [-U|--debug]                        don't daemonize and log to stdout with maximum log level" << std::endl;
604
605 #if defined(ANYCTR_OPTIONS)
606
607   std::cout << "   [-f|--file] <path>                  path to input file" << std::endl;
608   std::cout << "   [-X|--control-host] < <hostname|ip>[:<port>] | :<port> >" << std::endl;
609   std::cout << "                                       local tcp port and or ip address to bind to" << std::endl;
610
611 #endif
612 #if defined(ANYTUN_OPTIONS)
613
614   std::cout << "   [-i|--interface] <hostname|ip>      local anycast ip address to bind to" << std::endl;
615   std::cout << "   [-p|--port] <port>                  local anycast(data) port to bind to" << std::endl;
616   std::cout << "   [-s|--sender-id ] <sender id>       the sender id to use" << std::endl;
617
618 #endif
619 #if defined(ANYTUN_OPTIONS) || defined(ANYCONF_OPTIONS)
620
621   std::cout << "   [-r|--remote-host] <hostname|ip>    remote host" << std::endl;
622   std::cout << "   [-o|--remote-port] <port>           remote port" << std::endl;
623   std::cout << "   [-4|--ipv4-only]                    always resolv IPv4 addresses" << std::endl;
624   std::cout << "   [-6|--ipv6-only]                    always resolv IPv6 addresses" << std::endl;
625
626 #endif
627 #if defined(ANYTUN_OPTIONS)
628
629   std::cout << "   [-I|--sync-interface] <ip-address>  local unicast(sync) ip address to bind to" << std::endl;
630   std::cout << "   [-S|--sync-port] <port>             local unicast(sync) port to bind to" << std::endl;
631   std::cout << "   [-M|--sync-hosts] <hostname|ip>[:<port>][,<hostname|ip>[:<port>][...]]"<< std::endl;
632   std::cout << "                                       remote hosts to sync with" << std::endl;
633   std::cout << "   [-X|--control-host] <hostname|ip>[:<port>]"<< std::endl;
634   std::cout << "                                       fetch the config from this host" << std::endl;
635
636   std::cout << "   [-d|--dev] <name>                   device name" << std::endl;
637   std::cout << "   [-t|--type] <tun|tap>               device type" << std::endl;
638   std::cout << "   [-n|--ifconfig] <local>/<prefix>    the local address for the tun/tap device and the used prefix length" << std::endl;
639   std::cout << "   [-x|--post-up-script] <script>      script gets called after interface is created" << std::endl;
640
641 #endif
642 #if defined(ANYTUN_OPTIONS) || defined(ANYCONF_OPTIONS)
643
644 #ifndef NO_ROUTING
645   std::cout << "   [-R|--route] <net>/<prefix length>  add a route to connection, can be invoked several times" << std::endl;
646 #endif
647
648   std::cout << "   [-m|--mux] <mux-id>                 the multiplex id to use" << std::endl;
649   std::cout << "   [-w|--window-size] <window size>    seqence number window size" << std::endl;
650
651 #ifndef NO_CRYPT
652   std::cout << "   [-k|--kd-prf] <kd-prf type>         key derivation pseudo random function" << std::endl;
653   std::cout << "   [-e|--role] <role>                  left (alice) or right (bob)" << std::endl;
654 #ifndef NO_PASSPHRASE
655   std::cout << "   [-E|--passphrase] <pass phrase>     a passprhase to generate master key and salt from" << std::endl;
656 #endif
657   std::cout << "   [-K|--key] <master key>             master key to use for encryption" << std::endl;
658   std::cout << "   [-A|--salt] <master salt>           master salt to use for encryption" << std::endl;
659 #endif
660
661 #endif
662 #if defined(ANYTUN_OPTIONS)
663
664 #ifndef NO_CRYPT
665   std::cout << "   [-c|--cipher] <cipher type>         payload encryption algorithm" << std::endl;
666   std::cout << "   [-a|--auth-algo] <algo type>        message authentication algorithm" << std::endl;
667   std::cout << "   [-b|--auth-tag-length]              length of the auth tag" << std::endl;
668 #endif
669
670 #endif
671 }
672
673 void Options::printOptions()
674 {
675   ReadersLock lock(mutex);
676
677   std::cout << "Options:" << std::endl;
678   std::cout << std::endl;
679   std::cout << "daemonize = " << daemonize_ << std::endl;
680   std::cout << "username = '" << username_ << "'" << std::endl;
681   std::cout << "groupname = '" << groupname_ << "'" << std::endl;
682   std::cout << "chroot_dir = '" << chroot_dir_ << "'" << std::endl;
683   std::cout << "pid_file = '" << pid_file_ << "'" << std::endl;
684   std::cout << std::endl;
685   std::cout << "log_targets:";
686   StringList::const_iterator lit = log_targets_.begin();
687   for(; lit != log_targets_.end(); ++lit) {
688     std::cout << " '" << *lit << "',";
689   }
690   std::cout << std::endl;
691   std::cout << "debug = " << debug_ << std::endl;
692   std::cout << std::endl;
693   std::cout << "file_name = '" << file_name_ << "'" << std::endl;
694   std::cout << "bind_to.addr = '" << bind_to_.addr << "'" << std::endl;
695   std::cout << "bind_to.port = '" << bind_to_.port << "'" << std::endl;
696   std::cout << std::endl;
697   std::cout << "resolv_addr_type = ";
698   switch(resolv_addr_type_) {
699   case ANY:
700     std::cout <<  "any" << std::endl;
701     break;
702   case IPV4_ONLY:
703     std::cout <<  "ipv4-only" << std::endl;
704     break;
705   case IPV6_ONLY:
706     std::cout <<  "ipv6-only" << std::endl;
707     break;
708   default:
709     std::cout <<  "?" << std::endl;
710     break;
711   }
712   std::cout << std::endl;
713   std::cout << "local.addr = '" << local_.addr << "'" << std::endl;
714   std::cout << "local.port = '" << local_.port << "'" << std::endl;
715   std::cout << "remote.addr = '" << remote_.addr << "'" << std::endl;
716   std::cout << "remote.port = '" << remote_.port << "'" << std::endl;
717   std::cout << "local_sync.addr = '" << local_sync_.addr << "'" << std::endl;
718   std::cout << "local_sync.port = '" << local_sync_.port << "'" << std::endl;
719   std::cout << "remote_sync_hosts:" << std::endl;
720   HostList::const_iterator hit = remote_sync_hosts_.begin();
721   for(; hit != remote_sync_hosts_.end(); ++hit) {
722     std::cout << "  '" << hit->addr << "','" << hit->port << "'" << std::endl;
723   }
724   std::cout << std::endl;
725   std::cout << "dev_name = '" << dev_name_ << "'" << std::endl;
726   std::cout << "dev_type = '" << dev_type_ << "'" << std::endl;
727   std::cout << "ifconfig_param_local = '" << ifconfig_param_.net_addr << "/" << ifconfig_param_.prefix_length << "'" << std::endl;
728   std::cout << "post_up_script = '" << post_up_script_ << "'" << std::endl;
729   std::cout << "routes:" << std::endl;
730   NetworkList::const_iterator rit;
731   for(rit = routes_.begin(); rit != routes_.end(); ++rit) {
732     std::cout << "  " << rit->net_addr << "/" << rit->prefix_length << std::endl;
733   }
734   std::cout << std::endl;
735   std::cout << "sender_id = '" << sender_id_ << "'" << std::endl;
736   std::cout << "mux_id = " << mux_ << std::endl;
737   std::cout << "seq_window_size = '" << seq_window_size_ << "'" << std::endl;
738   std::cout << std::endl;
739   std::cout << "cipher = '" << cipher_ << "'" << std::endl;
740   std::cout << "auth_algo = '" << auth_algo_ << "'" << std::endl;
741   std::cout << "auth_tag_length = " << auth_tag_length_ << std::endl;
742   std::cout << "kd_prf = '" << kd_prf_ << "'" << std::endl;
743   std::cout << "role = ";
744   switch(role_) {
745   case ROLE_LEFT:
746     std::cout << "left" << std::endl;
747     break;
748   case ROLE_RIGHT:
749     std::cout << "right" << std::endl;
750     break;
751   default:
752     std::cout << "??" << std::endl;
753     break;
754   }
755   std::cout << "passphrase = '" << passphrase_ << "'" << std::endl;
756   std::cout << "key = " << key_.getHexDumpOneLine() << std::endl;
757   std::cout << "salt = " << salt_.getHexDumpOneLine() << std::endl;
758 }
759
760
761
762 std::string Options::getProgname()
763 {
764   ReadersLock lock(mutex);
765   return progname_;
766 }
767
768 Options& Options::setProgname(std::string p)
769 {
770   WritersLock lock(mutex);
771   progname_ = p;
772   return *this;
773 }
774
775 bool Options::getDaemonize()
776 {
777   ReadersLock lock(mutex);
778   return daemonize_;
779 }
780
781 Options& Options::setDaemonize(bool d)
782 {
783   WritersLock lock(mutex);
784   daemonize_ = d;
785   return *this;
786 }
787
788 std::string Options::getUsername()
789 {
790   ReadersLock lock(mutex);
791   return username_;
792 }
793
794 Options& Options::setUsername(std::string u)
795 {
796   WritersLock lock(mutex);
797   username_ = u;
798   return *this;
799 }
800
801 std::string Options::getGroupname()
802 {
803   ReadersLock lock(mutex);
804   return groupname_;
805 }
806
807 Options& Options::setGroupname(std::string g)
808 {
809   WritersLock lock(mutex);
810   groupname_ = g;
811   return *this;
812 }
813
814 std::string Options::getChrootDir()
815 {
816   ReadersLock lock(mutex);
817   return chroot_dir_;
818 }
819
820 Options& Options::setChrootDir(std::string c)
821 {
822   WritersLock lock(mutex);
823   chroot_dir_ = c;
824   return *this;
825 }
826
827 std::string Options::getPidFile()
828 {
829   ReadersLock lock(mutex);
830   return pid_file_;
831 }
832
833 Options& Options::setPidFile(std::string p)
834 {
835   WritersLock lock(mutex);
836   pid_file_ = p;
837   return *this;
838 }
839
840
841 StringList Options::getLogTargets()
842 {
843   ReadersLock lock(mutex);
844   return log_targets_;
845 }
846
847 bool Options::getDebug()
848 {
849   ReadersLock lock(mutex);
850   return debug_;
851 }
852
853 Options& Options::setDebug(bool d)
854 {
855   WritersLock lock(mutex);
856   debug_ = d;
857   return *this;
858 }
859
860
861 std::string Options::getFileName()
862 {
863   ReadersLock lock(mutex);
864   return file_name_;
865 }
866
867 Options& Options::setFileName(std::string f)
868 {
869   WritersLock lock(mutex);
870   file_name_ = f;
871   return *this;
872 }
873
874 std::string Options::getBindToAddr()
875 {
876   ReadersLock lock(mutex);
877   return bind_to_.addr;
878 }
879
880 Options& Options::setBindToAddr(std::string b)
881 {
882   WritersLock lock(mutex);
883   bind_to_.addr = b;
884   return *this;
885 }
886
887 std::string Options::getBindToPort()
888 {
889   ReadersLock lock(mutex);
890   return bind_to_.port;
891 }
892
893 Options& Options::setBindToPort(std::string b)
894 {
895   WritersLock lock(mutex);
896   bind_to_.port = b;
897   return *this;
898 }
899
900
901 ResolvAddrType Options::getResolvAddrType()
902 {
903   ReadersLock lock(mutex);
904   return resolv_addr_type_;
905 }
906
907 Options& Options::setResolvAddrType(ResolvAddrType r)
908 {
909   WritersLock lock(mutex);
910   resolv_addr_type_ = r;
911   return *this;
912 }
913
914 std::string Options::getLocalAddr()
915 {
916   ReadersLock lock(mutex);
917   return local_.addr;
918 }
919
920 Options& Options::setLocalAddr(std::string l)
921 {
922   WritersLock lock(mutex);
923   local_.addr = l;
924   return *this;
925 }
926
927 std::string Options::getLocalPort()
928 {
929   ReadersLock lock(mutex);
930   return local_.port;
931 }
932
933 Options& Options::setLocalPort(std::string l)
934 {
935   WritersLock lock(mutex);
936   local_.port = l;
937   return *this;
938 }
939
940 std::string Options::getRemoteAddr()
941 {
942   ReadersLock lock(mutex);
943   return remote_.addr;
944 }
945
946 Options& Options::setRemoteAddr(std::string r)
947 {
948   WritersLock lock(mutex);
949   remote_.addr = r;
950   return *this;
951 }
952
953 std::string Options::getRemotePort()
954 {
955   ReadersLock lock(mutex);
956   return remote_.port;
957 }
958
959 Options& Options::setRemotePort(std::string r)
960 {
961   WritersLock lock(mutex);
962   remote_.port = r;
963   return *this;
964 }
965
966 std::string Options::getLocalSyncAddr()
967 {
968   ReadersLock lock(mutex);
969   return local_sync_.addr;
970 }
971
972 Options& Options::setLocalSyncAddr(std::string l)
973 {
974   WritersLock lock(mutex);
975   local_sync_.addr = l;
976   return *this;
977 }
978
979 std::string Options::getLocalSyncPort()
980 {
981   ReadersLock lock(mutex);
982   return local_sync_.port;
983 }
984
985 Options& Options::setLocalSyncPort(std::string l)
986 {
987   WritersLock lock(mutex);
988   local_sync_.port = l;
989   return *this;
990 }
991
992 HostList Options::getRemoteSyncHosts()
993 {
994   ReadersLock lock(mutex);
995   return remote_sync_hosts_;
996 }
997
998
999
1000 std::string Options::getDevName()
1001 {
1002   ReadersLock lock(mutex);
1003   return dev_name_;
1004 }
1005
1006 Options& Options::setDevName(std::string d)
1007 {
1008   WritersLock lock(mutex);
1009   dev_name_ = d;
1010   return *this;
1011 }
1012
1013 std::string Options::getDevType()
1014 {
1015   ReadersLock lock(mutex);
1016   return dev_type_;
1017 }
1018
1019 Options& Options::setDevType(std::string d)
1020 {
1021   WritersLock lock(mutex);
1022   dev_type_ = d;
1023   return *this;
1024 }
1025
1026 OptionNetwork Options::getIfconfigParam()
1027 {
1028   ReadersLock lock(mutex);
1029   return ifconfig_param_;
1030 }
1031
1032 Options& Options::setIfconfigParam(OptionNetwork i)
1033 {
1034   WritersLock lock(mutex);
1035   ifconfig_param_ = i;
1036   return *this;
1037 }
1038
1039 std::string Options::getPostUpScript()
1040 {
1041   ReadersLock lock(mutex);
1042   return post_up_script_;
1043 }
1044
1045 Options& Options::setPostUpScript(std::string p)
1046 {
1047   WritersLock lock(mutex);
1048   post_up_script_ = p;
1049   return *this;
1050 }
1051
1052 NetworkList Options::getRoutes()
1053 {
1054   ReadersLock lock(mutex);
1055   return routes_;
1056 }
1057
1058
1059
1060 sender_id_t Options::getSenderId()
1061 {
1062   ReadersLock lock(mutex);
1063   return sender_id_;
1064 }
1065
1066 Options& Options::setSenderId(sender_id_t s)
1067 {
1068   WritersLock lock(mutex);
1069   sender_id_ = s;
1070   return *this;
1071 }
1072
1073 mux_t Options::getMux()
1074 {
1075   ReadersLock lock(mutex);
1076   return mux_;
1077 }
1078
1079 Options& Options::setMux(mux_t m)
1080 {
1081   WritersLock lock(mutex);
1082   mux_ = m;
1083   return *this;
1084 }
1085
1086 window_size_t Options::getSeqWindowSize()
1087 {
1088   ReadersLock lock(mutex);
1089   return seq_window_size_;
1090 }
1091
1092 Options& Options::setSeqWindowSize(window_size_t s)
1093 {
1094   WritersLock lock(mutex);
1095   seq_window_size_ = s;
1096   return *this;
1097 }
1098
1099
1100
1101 std::string Options::getCipher()
1102 {
1103   ReadersLock lock(mutex);
1104   return cipher_;
1105 }
1106
1107 Options& Options::setCipher(std::string c)
1108 {
1109   WritersLock lock(mutex);
1110   cipher_ = c;
1111   return *this;
1112 }
1113
1114 std::string Options::getAuthAlgo()
1115 {
1116   ReadersLock lock(mutex);
1117   return auth_algo_;
1118 }
1119
1120 Options& Options::setAuthAlgo(std::string a)
1121 {
1122   WritersLock lock(mutex);
1123   auth_algo_ = a;
1124   return *this;
1125 }
1126
1127 uint32_t Options::getAuthTagLength()
1128 {
1129   ReadersLock lock(mutex);
1130   return auth_tag_length_;
1131 }
1132
1133 Options& Options::setAuthTagLength(uint32_t a)
1134 {
1135   WritersLock lock(mutex);
1136   auth_tag_length_ = a;
1137   return *this;
1138 }
1139
1140
1141 std::string Options::getKdPrf()
1142 {
1143   ReadersLock lock(mutex);
1144   return kd_prf_;
1145 }
1146
1147 Options& Options::setKdPrf(std::string k)
1148 {
1149   WritersLock lock(mutex);
1150   kd_prf_ = k;
1151   return *this;
1152 }
1153
1154 role_t Options::getRole()
1155 {
1156   ReadersLock lock(mutex);
1157   return role_;
1158 }
1159
1160 Options& Options::setRole(role_t r)
1161 {
1162   WritersLock lock(mutex);
1163   role_ = r;
1164   return *this;
1165 }
1166
1167 std::string Options::getPassphrase()
1168 {
1169   ReadersLock lock(mutex);
1170   return passphrase_;
1171 }
1172
1173 Options& Options::setPassphrase(std::string p)
1174 {
1175   WritersLock lock(mutex);
1176   passphrase_ = p;
1177   return *this;
1178 }
1179
1180 Buffer Options::getKey()
1181 {
1182   ReadersLock lock(mutex);
1183   return key_;
1184 }
1185
1186 Options& Options::setKey(std::string k)
1187 {
1188   WritersLock lock(mutex);
1189   key_ = k;
1190   return *this;
1191 }
1192
1193 Buffer Options::getSalt()
1194 {
1195   ReadersLock lock(mutex);
1196   return salt_;
1197 }
1198
1199 Options& Options::setSalt(std::string s)
1200 {
1201   WritersLock lock(mutex);
1202   salt_ = s;
1203   return *this;
1204 }