added a workaround for strerror_r problem
[anytun.git] / src / options.cpp
blob868c0bb356f80fa3008379f123853660fa14816c
1 /*
2 * anytun
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.
14 * Copyright (C) 2007-2008 Othmar Gsenger, Erwin Nindl,
15 * Christian Pointner <satp@wirdorange.org>
17 * This file is part of Anytun.
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.
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.
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/>.
32 #include <iostream>
33 #include <queue>
34 #include <string>
35 #include <sstream>
36 #include <cstring>
38 #include "datatypes.h"
39 #include "options.h"
41 Options* Options::inst = NULL;
42 Mutex Options::instMutex;
43 Options& gOpt = Options::instance();
45 Options& Options::instance()
47 Lock lock(instMutex);
48 static instanceCleaner c;
49 if(!inst)
50 inst = new Options();
52 return *inst;
55 Options::Options() : key_(u_int32_t(0)), salt_(u_int32_t(0))
57 progname_ = "anytun";
58 daemonize_ = true;
59 chroot_ = false;
60 username_ = "nobody";
61 chroot_dir_ = "/var/run/anytun";
62 pid_file_ = "";
63 sender_id_ = 0;
64 local_addr_ = "";
65 local_port_ = "4444";
66 local_sync_port_ = "";
67 remote_sync_port_ = "";
68 remote_sync_addr_ = "";
69 remote_addr_ = "";
70 remote_port_ = "4444";
71 dev_name_ = "";
72 dev_type_ = "";
73 ifconfig_param_local_ = "";
74 ifconfig_param_remote_netmask_ = "";
75 post_up_script_ = "";
76 seq_window_size_ = 100;
77 cipher_ = "aes-ctr";
78 kd_prf_ = "aes-ctr";
79 auth_algo_ = "sha1";
80 mux_ = 0;
83 Options::~Options()
87 #define PARSE_BOOL_PARAM(SHORT, LONG, VALUE) \
88 else if(str == SHORT || str == LONG) \
89 VALUE = true;
91 #define PARSE_INVERSE_BOOL_PARAM(SHORT, LONG, VALUE) \
92 else if(str == SHORT || str == LONG) \
93 VALUE = false;
95 #define PARSE_SCALAR_PARAM(SHORT, LONG, VALUE) \
96 else if(str == SHORT || str == LONG) \
97 { \
98 if(argc < 1 || argv[i+1][0] == '-') \
99 return false; \
100 std::stringstream tmp; \
101 tmp << argv[i+1]; \
102 tmp >> VALUE; \
103 argc--; \
104 i++; \
107 #define PARSE_SCALAR_PARAM2(SHORT, LONG, VALUE1, VALUE2) \
108 else if(str == SHORT || str == LONG) \
110 if(argc < 2 || \
111 argv[i+1][0] == '-' || argv[i+2][0] == '-') \
112 return false; \
113 std::stringstream tmp; \
114 tmp << argv[i+1] << " " << argv[i+2]; \
115 tmp >> VALUE1; \
116 tmp >> VALUE2; \
117 argc-=2; \
118 i+=2; \
121 #define PARSE_HEXSTRING_PARAM_SEC(SHORT, LONG, VALUE) \
122 else if(str == SHORT || str == LONG) \
124 if(argc < 1 || argv[i+1][0] == '-') \
125 return false; \
126 VALUE = Buffer(std::string(argv[i+1])); \
127 for(size_t j=0; j < strlen(argv[i+1]); ++j) \
128 argv[i+1][j] = '#'; \
129 argc--; \
130 i++; \
133 #define PARSE_CSLIST_PARAM(SHORT, LONG, LIST) \
134 else if(str == SHORT || str == LONG) \
136 if(argc < 1 || argv[i+1][0] == '-') \
137 return false; \
138 std::stringstream tmp(argv[i+1]); \
139 while (tmp.good()) \
141 std::string tmp_line; \
142 getline(tmp,tmp_line,','); \
143 LIST.push(tmp_line); \
145 argc--; \
146 i++; \
149 bool Options::parse(int argc, char* argv[])
151 Lock lock(mutex);
153 progname_ = argv[0];
154 argc--;
155 std::queue<std::string> route_queue;
156 std::queue<std::string> host_port_queue;
157 for(int i=1; argc > 0; ++i)
159 std::string str(argv[i]);
160 argc--;
162 if(str == "-h" || str == "--help")
163 return false;
164 PARSE_INVERSE_BOOL_PARAM("-D","--nodaemonize", daemonize_)
165 PARSE_BOOL_PARAM("-C","--chroot", chroot_)
166 PARSE_SCALAR_PARAM("-u","--username", username_)
167 PARSE_SCALAR_PARAM("-H","--chroot-dir", chroot_dir_)
168 PARSE_SCALAR_PARAM("-P","--write-pid", pid_file_)
169 PARSE_SCALAR_PARAM("-s","--sender-id", sender_id_)
170 PARSE_SCALAR_PARAM("-i","--interface", local_addr_)
171 PARSE_SCALAR_PARAM("-p","--port", local_port_)
172 PARSE_SCALAR_PARAM("-S","--sync-port", local_sync_port_)
173 PARSE_SCALAR_PARAM("-I","--sync-interface", local_sync_addr_)
174 PARSE_SCALAR_PARAM("-R","--remote-sync-host", remote_sync_addr_)
175 PARSE_SCALAR_PARAM("-O","--remote-sync-port", remote_sync_port_)
176 PARSE_SCALAR_PARAM("-r","--remote-host", remote_addr_)
177 PARSE_SCALAR_PARAM("-o","--remote-port", remote_port_)
178 PARSE_SCALAR_PARAM("-d","--dev", dev_name_)
179 PARSE_SCALAR_PARAM("-t","--type", dev_type_)
180 PARSE_SCALAR_PARAM2("-n","--ifconfig", ifconfig_param_local_, ifconfig_param_remote_netmask_)
181 PARSE_SCALAR_PARAM("-x","--post-up-script", post_up_script_)
182 PARSE_SCALAR_PARAM("-w","--window-size", seq_window_size_)
183 PARSE_SCALAR_PARAM("-m","--mux", mux_)
184 PARSE_SCALAR_PARAM("-c","--cipher", cipher_)
185 PARSE_HEXSTRING_PARAM_SEC("-K","--key", key_)
186 PARSE_HEXSTRING_PARAM_SEC("-A","--salt", salt_)
187 PARSE_SCALAR_PARAM("-k","--kd-prf", kd_prf_)
188 PARSE_SCALAR_PARAM("-a","--auth-algo", auth_algo_)
189 PARSE_CSLIST_PARAM("-M","--sync-hosts", host_port_queue)
190 PARSE_CSLIST_PARAM("-X","--control-host", host_port_queue)
191 PARSE_CSLIST_PARAM("-T","--route", route_queue)
192 else
193 return false;
196 if(cipher_ == "null" && auth_algo_ == "null")
197 kd_prf_ = "null";
198 if((cipher_ != "null" || auth_algo_ != "null") && kd_prf_ == "null")
199 kd_prf_ = "aes-ctr";
201 if(dev_name_ == "" && dev_type_ == "")
202 dev_type_ = "tun";
204 while(!host_port_queue.empty())
206 bool ret = splitAndAddHostPort(host_port_queue.front(), connect_to_);
207 if(!ret) return false;
208 host_port_queue.pop();
210 while(!route_queue.empty())
212 std::stringstream tmp_stream(route_queue.front());
213 OptionRoute rt;
214 getline(tmp_stream,rt.net_addr,'/');
215 if(!tmp_stream.good())
216 return false;
217 tmp_stream >> rt.prefix_length;
218 route_queue.pop();
219 routes_.push_back(rt);
221 return true;
224 bool Options::splitAndAddHostPort(std::string hostPort, ConnectToList& list)
226 OptionConnectTo oct;
227 size_t pos = hostPort.find_first_of("[");
229 if(pos != std::string::npos && pos != 0)
230 return false; // an [ was found but not at the beginning
232 bool hasPort = false;
233 if(pos != std::string::npos) {
234 hostPort.erase(pos, 1);
235 pos = hostPort.find_first_of("]");
237 if(pos == std::string::npos)
238 return false; // no trailing ] although an leading [ was found
240 if(pos < hostPort.length()-2) {
242 if(hostPort[pos+1] != ':')
243 return false; // wrong port delimieter
245 hostPort[pos+1] = '/';
246 hasPort = true;
248 else if(pos != hostPort.length()-1)
249 return false; // to few characters left
251 hostPort.erase(pos, 1);
253 else {
254 pos = hostPort.find_first_of(":");
255 if(pos != std::string::npos && pos == hostPort.find_last_of(":")) {
256 // an ':' has been found and it is the only one -> assuming port present
257 hasPort = true;
258 hostPort[pos] = '/';
262 if(hasPort) {
263 std::stringstream tmp_stream(hostPort);
264 getline(tmp_stream,oct.host,'/');
265 if(!tmp_stream.good())
266 return false;
268 tmp_stream >> oct.port;
270 else {
271 oct.host = hostPort;
272 oct.port = "2323"; // default sync port
275 list.push_back(oct);
276 return true;
279 void Options::printUsage()
281 std::cout << "USAGE:" << std::endl;
282 std::cout << "anytun [-h|--help] prints this..." << std::endl;
283 // std::cout << " [-f|--config] <file> the config file" << std::endl;
284 std::cout << " [-D|--nodaemonize] don't run in background" << std::endl;
285 std::cout << " [-C|--chroot] chroot and drop privileges" << std::endl;
286 std::cout << " [-u|--username] <username> if chroot change to this user" << std::endl;
287 std::cout << " [-H|--chroot-dir] <path> chroot to this directory" << std::endl;
288 std::cout << " [-P|--write-pid] <path> write pid to this file" << std::endl;
289 std::cout << " [-s|--sender-id ] <sender id> the sender id to use" << std::endl;
290 std::cout << " [-i|--interface] <ip-address> local anycast ip address to bind to" << std::endl;
291 std::cout << " [-p|--port] <port> local anycast(data) port to bind to" << std::endl;
292 std::cout << " [-I|--sync-interface] <ip-address> local unicast(sync) ip address to bind to" << std::endl;
293 std::cout << " [-S|--sync-port] <port> local unicast(sync) port to bind to" << std::endl;
294 std::cout << " [-M|--sync-hosts] <hostname|ip>[:<port>][,<hostname|ip>[:<port>][...]]"<< std::endl;
295 std::cout << " remote hosts to sync with" << std::endl;
296 std::cout << " [-X|--control-host] <hostname|ip>[:<port>]"<< std::endl;
297 std::cout << " fetch the config from this host" << std::endl;
298 std::cout << " [-r|--remote-host] <hostname|ip> remote host" << std::endl;
299 std::cout << " [-o|--remote-port] <port> remote port" << std::endl;
300 std::cout << " [-d|--dev] <name> device name" << std::endl;
301 std::cout << " [-t|--type] <tun|tap> device type" << std::endl;
302 std::cout << " [-n|--ifconfig] <local> the local address for the tun/tap device" << std::endl
303 << " <remote|netmask> the remote address(tun) or netmask(tap)" << std::endl;
304 std::cout << " [-x|--post-up-script] <script> script gets called after interface is created" << std::endl;
305 std::cout << " [-w|--window-size] <window size> seqence number window size" << std::endl;
306 std::cout << " [-m|--mux] <mux-id> the multiplex id to use" << std::endl;
307 std::cout << " [-c|--cipher] <cipher type> payload encryption algorithm" << std::endl;
308 std::cout << " [-K|--key] <master key> master key to use for encryption" << std::endl;
309 std::cout << " [-A|--salt] <master salt> master salt to use for encryption" << std::endl;
310 // std::cout << " [-k|--kd-prf] <kd-prf type> key derivation pseudo random function" << std::endl;
311 std::cout << " [-a|--auth-algo] <algo type> message authentication algorithm" << std::endl;
312 std::cout << " [-T|--route] <net>/<prefix length> add a route to connection, can be invoked several times" << std::endl;
315 void Options::printOptions()
317 Lock lock(mutex);
318 std::cout << "Options:" << std::endl;
319 std::cout << "daemonize=" << daemonize_ << std::endl;
320 std::cout << "chroot=" << chroot_ << std::endl;
321 std::cout << "username='" << username_ << "'" << std::endl;
322 std::cout << "chroot_dir='" << chroot_dir_ << "'" << std::endl;
323 std::cout << "pid_file='" << pid_file_ << "'" << std::endl;
324 std::cout << "sender_id='" << sender_id_ << "'" << std::endl;
325 std::cout << "local_addr='" << local_addr_ << "'" << std::endl;
326 std::cout << "local_port='" << local_port_ << "'" << std::endl;
327 std::cout << "local_sync_addr='" << local_sync_addr_ << "'" << std::endl;
328 std::cout << "local_sync_port='" << local_sync_port_ << "'" << std::endl;
329 std::cout << "remote_addr='" << remote_addr_ << "'" << std::endl;
330 std::cout << "remote_port='" << remote_port_ << "'" << std::endl;
331 std::cout << "dev_name='" << dev_name_ << "'" << std::endl;
332 std::cout << "dev_type='" << dev_type_ << "'" << std::endl;
333 std::cout << "ifconfig_param_local='" << ifconfig_param_local_ << "'" << std::endl;
334 std::cout << "ifconfig_param_remote_netmask='" << ifconfig_param_remote_netmask_ << "'" << std::endl;
335 std::cout << "post_up_script='" << post_up_script_ << "'" << std::endl;
336 std::cout << "seq_window_size='" << seq_window_size_ << "'" << std::endl;
337 std::cout << "mux_id='" << mux_ << "'" << std::endl;
338 std::cout << "cipher='" << cipher_ << "'" << std::endl;
339 std::cout << "key=" << key_.getHexDumpOneLine() << std::endl;
340 std::cout << "salt=" << salt_.getHexDumpOneLine() << std::endl;
341 std::cout << "kd_prf='" << kd_prf_ << "'" << std::endl;
342 std::cout << "auth_algo='" << auth_algo_ << "'" << std::endl;
344 std::cout << "connect_to=";
345 ConnectToList::const_iterator it = connect_to_.begin();
346 for(; it != connect_to_.end(); ++it)
347 std::cout << "'" << it->host << "','" << it->port << "';";
348 std::cout << std::endl;
349 std::cout << "routes:" << std::endl;
350 RouteList::const_iterator rit;
351 for(rit = routes_.begin(); rit != routes_.end(); ++rit)
352 std::cout << " " << rit->net_addr << "/" << rit->prefix_length << std::endl;
355 std::string Options::getProgname()
357 Lock lock(mutex);
358 return progname_;
362 Options& Options::setProgname(std::string p)
364 Lock lock(mutex);
365 progname_ = p;
366 return *this;
369 bool Options::getDaemonize()
371 return daemonize_;
374 Options& Options::setDaemonize(bool d)
376 daemonize_ = d;
377 return *this;
380 bool Options::getChroot()
382 return chroot_;
385 Options& Options::setChroot(bool c)
387 chroot_ = c;
388 return *this;
391 std::string Options::getUsername()
393 Lock lock(mutex);
394 return username_;
397 Options& Options::setUsername(std::string u)
399 Lock lock(mutex);
400 username_ = u;
401 return *this;
404 std::string Options::getChrootDir()
406 Lock lock(mutex);
407 return chroot_dir_;
410 Options& Options::setChrootDir(std::string c)
412 Lock lock(mutex);
413 chroot_dir_ = c;
414 return *this;
417 std::string Options::getPidFile()
419 Lock lock(mutex);
420 return pid_file_;
423 Options& Options::setPidFile(std::string p)
425 Lock lock(mutex);
426 pid_file_ = p;
427 return *this;
430 ConnectToList Options::getConnectTo()
432 Lock lock(mutex);
433 return connect_to_;
436 sender_id_t Options::getSenderId()
438 return sender_id_;
441 Options& Options::setSenderId(sender_id_t s)
443 sender_id_ = s;
444 return *this;
447 std::string Options::getLocalAddr()
449 Lock lock(mutex);
450 return local_addr_;
453 Options& Options::setLocalAddr(std::string l)
455 Lock lock(mutex);
456 local_addr_ = l;
457 return *this;
460 std::string Options::getLocalSyncAddr()
462 Lock lock(mutex);
463 return local_sync_addr_;
466 Options& Options::setLocalSyncAddr(std::string l)
468 Lock lock(mutex);
469 local_sync_addr_ = l;
470 return *this;
473 std::string Options::getLocalPort()
475 return local_port_;
478 Options& Options::setLocalPort(std::string l)
480 local_port_ = l;
481 return *this;
484 std::string Options::getLocalSyncPort()
486 return local_sync_port_;
489 Options& Options::setLocalSyncPort(std::string l)
491 local_sync_port_ = l;
492 return *this;
495 std::string Options::getRemoteSyncPort()
497 return remote_sync_port_;
500 Options& Options::setRemoteSyncPort(std::string l)
502 remote_sync_port_ = l;
503 return *this;
506 std::string Options::getRemoteSyncAddr()
508 Lock lock(mutex);
509 return remote_sync_addr_;
512 Options& Options::setRemoteSyncAddr(std::string r)
514 Lock lock(mutex);
515 remote_sync_addr_ = r;
516 return *this;
519 std::string Options::getRemoteAddr()
521 Lock lock(mutex);
522 return remote_addr_;
525 Options& Options::setRemoteAddr(std::string r)
527 Lock lock(mutex);
528 remote_addr_ = r;
529 return *this;
532 std::string Options::getRemotePort()
534 return remote_port_;
537 Options& Options::setRemotePort(std::string r)
539 remote_port_ = r;
540 return *this;
543 Options& Options::setRemoteAddrPort(std::string addr, std::string port)
545 Lock lock(mutex);
546 remote_addr_ = addr;
547 remote_port_ = port;
548 return *this;
551 std::string Options::getDevName()
553 Lock lock(mutex);
554 return dev_name_;
557 std::string Options::getDevType()
559 Lock lock(mutex);
560 return dev_type_;
563 Options& Options::setDevName(std::string d)
565 Lock lock(mutex);
566 dev_name_ = d;
567 return *this;
570 Options& Options::setDevType(std::string d)
572 Lock lock(mutex);
573 dev_type_ = d;
574 return *this;
577 std::string Options::getIfconfigParamLocal()
579 Lock lock(mutex);
580 return ifconfig_param_local_;
583 Options& Options::setIfconfigParamLocal(std::string i)
585 Lock lock(mutex);
586 ifconfig_param_local_ = i;
587 return *this;
590 std::string Options::getIfconfigParamRemoteNetmask()
592 Lock lock(mutex);
593 return ifconfig_param_remote_netmask_;
596 Options& Options::setIfconfigParamRemoteNetmask(std::string i)
598 Lock lock(mutex);
599 ifconfig_param_remote_netmask_ = i;
600 return *this;
603 std::string Options::getPostUpScript()
605 Lock lock(mutex);
606 return post_up_script_;
609 Options& Options::setPostUpScript(std::string p)
611 Lock lock(mutex);
612 post_up_script_ = p;
613 return *this;
616 window_size_t Options::getSeqWindowSize()
618 return seq_window_size_;
621 Options& Options::setSeqWindowSize(window_size_t s)
623 seq_window_size_ = s;
624 return *this;
627 std::string Options::getCipher()
629 Lock lock(mutex);
630 return cipher_;
633 Options& Options::setCipher(std::string c)
635 Lock lock(mutex);
636 cipher_ = c;
637 return *this;
640 std::string Options::getKdPrf()
642 Lock lock(mutex);
643 return kd_prf_;
646 Options& Options::setKdPrf(std::string k)
648 Lock lock(mutex);
649 kd_prf_ = k;
650 return *this;
653 std::string Options::getAuthAlgo()
655 Lock lock(mutex);
656 return auth_algo_;
659 Options& Options::setAuthAlgo(std::string a)
661 Lock lock(mutex);
662 auth_algo_ = a;
663 return *this;
666 mux_t Options::getMux()
668 Lock lock(mutex);
669 return mux_;
672 Options& Options::setMux(mux_t m)
674 Lock lock(mutex);
675 mux_ = m;
676 return *this;
679 Buffer Options::getKey()
681 Lock lock(mutex);
682 return key_;
685 Options& Options::setKey(std::string k)
687 Lock lock(mutex);
688 key_ = k;
689 return *this;
692 Buffer Options::getSalt()
694 Lock lock(mutex);
695 return salt_;
698 Options& Options::setSalt(std::string s)
700 Lock lock(mutex);
701 salt_ = s;
702 return *this;
705 RouteList Options::getRoutes()
707 Lock lock(mutex);
708 return routes_;