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