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