From d7e3f4ed178b3599ffa15d4633a418d1662471a2 Mon Sep 17 00:00:00 2001 From: equinox Date: Tue, 25 Nov 2008 04:13:55 +0000 Subject: [PATCH] options parser support ipv6 now fixed anytun-controld - fixed log issues - added better error output - some cleanups git-svn-id: https://anytun.org/svn/anytun@605 2edecd69-f0ce-4815-94af-351a89d40aaa --- src/anyCtrOptions.cpp | 69 +++++++++++++++++++--- src/anyCtrOptions.h | 8 ++- src/anytun-controld.cpp | 150 +++++++++++++++++++++++++++++------------------- src/anytun.cpp | 10 ++-- src/options.cpp | 64 ++++++++++++++++++--- src/options.h | 2 + 6 files changed, 218 insertions(+), 85 deletions(-) diff --git a/src/anyCtrOptions.cpp b/src/anyCtrOptions.cpp index 7543206..2256677 100644 --- a/src/anyCtrOptions.cpp +++ b/src/anyCtrOptions.cpp @@ -61,7 +61,7 @@ Options::Options() chroot_dir_ = "/var/run/anytun-controld"; pid_file_ = ""; bind_to_addr_ = "127.0.0.1"; - bind_to_port_ = 4445; + bind_to_port_ = "4445"; } Options::~Options() @@ -156,12 +156,61 @@ bool Options::parse(int argc, char* argv[]) return false; } - if(control_host != "") { - std::stringstream tmp_stream(control_host); - getline(tmp_stream,bind_to_addr_,':'); - if(!tmp_stream.good()) - return false; - tmp_stream >> bind_to_port_; + if(control_host != "") + return splitAndSetHostPort(control_host); + + return true; +} + +bool Options::splitAndSetHostPort(std::string hostPort) +{ + if(hostPort.length() >= 2 && hostPort[0] == ':' && hostPort[1] != ':') { + bind_to_addr_ = ""; + hostPort.erase(0,1); + std::stringstream tmp_stream(hostPort); + tmp_stream >> bind_to_port_; + return true; + } + + size_t pos = hostPort.find_first_of("["); + + if(pos != std::string::npos && pos != 0) + return false; // an [ was found but not at the beginning + + bool hasPort = false; + if(pos != std::string::npos) { + hostPort.erase(pos, 1); + pos = hostPort.find_first_of("]"); + + if(pos == std::string::npos) + return false; // no trailing ] although an leading [ was found + + if(pos < hostPort.length()-2) { + + if(hostPort[pos+1] != ':') + return false; // wrong port delimieter + + hostPort[pos+1] = '/'; + hasPort = true; + } + else if(pos != hostPort.length()-1) + return false; // to few characters left + + hostPort.erase(pos, 1); + } + + if(hasPort) { + std::stringstream tmp_stream(hostPort); + + getline(tmp_stream, bind_to_addr_, '/'); + if(!tmp_stream.good()) + return false; + + tmp_stream >> bind_to_port_; + } + else { + bind_to_addr_ = hostPort; + bind_to_port_ = "2323"; // default sync port } return true; @@ -190,6 +239,8 @@ void Options::printOptions() std::cout << "username='" << username_ << "'" << std::endl; std::cout << "chroot_dir='" << chroot_dir_ << "'" << std::endl; std::cout << "pid_file='" << pid_file_ << "'" << std::endl; + std::cout << "bind_to_addr_='" << bind_to_addr_ << "'" << std::endl; + std::cout << "bind_to_port_='" << bind_to_port_ << "'" << std::endl; } std::string Options::getProgname() @@ -293,12 +344,12 @@ Options& Options::setBindToAddr(std::string b) return *this; } -uint16_t Options::getBindToPort() +std::string Options::getBindToPort() { return bind_to_port_; } -Options& Options::setBindToPort(uint16_t b) +Options& Options::setBindToPort(std::string b) { bind_to_port_ = b; return *this; diff --git a/src/anyCtrOptions.h b/src/anyCtrOptions.h index 1a9e8b3..d4789c3 100644 --- a/src/anyCtrOptions.h +++ b/src/anyCtrOptions.h @@ -62,8 +62,8 @@ public: Options& setFileName(std::string f); std::string getBindToAddr(); Options& setBindToAddr(std::string b); - uint16_t getBindToPort(); - Options& setBindToPort(uint16_t b); + std::string getBindToPort(); + Options& setBindToPort(std::string b); private: @@ -82,10 +82,12 @@ private: }; friend class instanceCleaner; + bool splitAndSetHostPort(std::string hostPort); + Mutex mutex; std::string bind_to_addr_; - uint16_t bind_to_port_; + std::string bind_to_port_; std::string progname_; bool daemonize_; bool chroot_; diff --git a/src/anytun-controld.cpp b/src/anytun-controld.cpp index f869553..24a6634 100644 --- a/src/anytun-controld.cpp +++ b/src/anytun-controld.cpp @@ -46,19 +46,9 @@ #include "syncServer.h" #include "daemon.hpp" -std::string filename; - -class ThreadParam -{ -public: - ThreadParam() : addr(""), port(0) {}; - std::string addr; - u_int16_t port; -}; - void syncOnConnect(SyncTcpConnection * connptr) { - std::ifstream file( filename.c_str() ); + std::ifstream file( gOpt.getFileName().c_str() ); if( file.is_open() ) { std::string line; @@ -71,72 +61,112 @@ void syncOnConnect(SyncTcpConnection * connptr) } } -void syncListener(void* p ) +bool syncListenerInit(boost::asio::io_service& io_service) { - ThreadParam* param = reinterpret_cast(p); - try { - boost::asio::io_service io_service; - SyncServer server(io_service, SyncTcpConnection::proto::endpoint(SyncTcpConnection::proto::v6(), param->port)); + SyncTcpConnection::proto::resolver resolver(io_service); + SyncTcpConnection::proto::endpoint e; + if(gOpt.getBindToAddr()!="") + { + SyncTcpConnection::proto::resolver::query query(gOpt.getBindToAddr(), gOpt.getBindToPort()); + e = *resolver.resolve(query); + } else { + SyncTcpConnection::proto::resolver::query query(gOpt.getBindToPort()); + e = *resolver.resolve(query); + } + + + SyncServer server(io_service,e); server.onConnect=boost::bind(syncOnConnect,_1); - io_service.run(); } catch (std::exception& e) { - std::cerr << e.what() << std::endl; + std::string addr = gOpt.getBindToAddr() == "" ? "*" : gOpt.getBindToAddr(); + cLog.msg(Log::PRIO_ERR) << "cannot bind to " << addr << ":" << gOpt.getBindToPort() + << " (" << e.what() << ")" << std::endl; + return false; } + return true; +} +void syncListener(boost::asio::io_service* io_service) +{ + io_service->run(); } int main(int argc, char* argv[]) { - if(!gOpt.parse(argc, argv)) - { - gOpt.printUsage(); - exit(-1); - } - - std::ifstream file( gOpt.getFileName().c_str() ); - if( file.is_open() ) - file.close(); - else + bool daemonized=false; + try { - std::cout << "ERROR: unable to open file!" << std::endl; - exit(-1); - } + + if(!gOpt.parse(argc, argv)) + { + gOpt.printUsage(); + exit(-1); + } + + cLog.setLogName("anytun-controld"); + cLog.msg(Log::PRIO_NOTICE) << "anytun-controld started..."; + + std::ifstream file( gOpt.getFileName().c_str() ); + if( file.is_open() ) + file.close(); + else + { + std::cout << "ERROR: unable to open file!" << std::endl; + exit(-1); + } + + std::ofstream pidFile; + if(gOpt.getPidFile() != "") { + pidFile.open(gOpt.getPidFile().c_str()); + if(!pidFile.is_open()) { + std::cout << "can't open pid file" << std::endl; + } + } + + if(gOpt.getChroot()) + chrootAndDrop(gOpt.getChrootDir(), gOpt.getUsername()); + if(gOpt.getDaemonize()) + { + daemonize(); + daemonized = true; + } - std::ofstream pidFile; - if(gOpt.getPidFile() != "") { - pidFile.open(gOpt.getPidFile().c_str()); - if(!pidFile.is_open()) { - std::cout << "can't open pid file" << std::endl; + if(pidFile.is_open()) { + pid_t pid = getpid(); + pidFile << pid; + pidFile.close(); } + + SignalController sig; + sig.init(); + + boost::asio::io_service io_service; + if(!syncListenerInit(io_service)) + return -1; + boost::thread * syncListenerThread; + syncListenerThread = new boost::thread(boost::bind(syncListener, &io_service)); + + int ret = sig.run(); + + return ret; } - - if(gOpt.getChroot()) - chrootAndDrop(gOpt.getChrootDir(), gOpt.getUsername()); - if(gOpt.getDaemonize()) - daemonize(); - - if(pidFile.is_open()) { - pid_t pid = getpid(); - pidFile << pid; - pidFile.close(); + catch(std::runtime_error& e) + { + if(daemonized) + cLog.msg(Log::PRIO_ERR) << "uncaught runtime error, exiting: " << e.what(); + else + std::cout << "uncaught runtime error, exiting: " << e.what() << std::endl; + } + catch(std::exception& e) + { + if(daemonized) + cLog.msg(Log::PRIO_ERR) << "uncaught exception, exiting: " << e.what(); + else + std::cout << "uncaught exception, exiting: " << e.what() << std::endl; } - - SignalController sig; - sig.init(); - - ThreadParam p; - p.addr = gOpt.getBindToAddr(); - p.port = gOpt.getBindToPort(); - filename = gOpt.getFileName(); - boost::thread * syncListenerThread; - syncListenerThread = new boost::thread(boost::bind(syncListener,&p)); - - int ret = sig.run(); - - return ret; } diff --git a/src/anytun.cpp b/src/anytun.cpp index a5ea52f..258d98a 100644 --- a/src/anytun.cpp +++ b/src/anytun.cpp @@ -214,10 +214,8 @@ void syncConnector(void* p ) sc.run(); } -void syncListener(SyncQueue * queue ) +void syncListener(SyncQueue * queue) { -// ThreadParam* param = reinterpret_cast(p); - try { boost::asio::io_service io_service; @@ -240,7 +238,9 @@ void syncListener(SyncQueue * queue ) } catch (std::exception& e) { - std::cerr << e.what() << std::endl; + std::string addr = gOpt.getLocalSyncAddr() == "" ? "*" : gOpt.getLocalSyncAddr(); + cLog.msg(Log::PRIO_ERR) << "sync: cannot bind to " << addr << ":" << gOpt.getLocalSyncPort() + << " (" << e.what() << ")" << std::endl; } } @@ -498,7 +498,7 @@ int main(int argc, char* argv[]) gOpt.printUsage(); exit(-1); } - + cLog.msg(Log::PRIO_NOTICE) << "anytun started..."; std::ofstream pidFile; diff --git a/src/options.cpp b/src/options.cpp index 806c7c8..1a40f59 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -201,18 +201,60 @@ bool Options::parse(int argc, char* argv[]) while(!host_port_queue.empty()) { - std::stringstream tmp_stream(host_port_queue.front()); - OptionConnectTo oct; - getline(tmp_stream,oct.host,':'); - if(!tmp_stream.good()) - return false; - tmp_stream >> oct.port; - host_port_queue.pop(); - connect_to_.push_back(oct); + bool ret = splitAndAddHostPort(host_port_queue.front(), connect_to_); + if(!ret) return false; + host_port_queue.pop(); } return true; } +bool Options::splitAndAddHostPort(std::string hostPort, ConnectToList& list) +{ + OptionConnectTo oct; + size_t pos = hostPort.find_first_of("["); + + if(pos != std::string::npos && pos != 0) + return false; // an [ was found but not at the beginning + + bool hasPort = false; + if(pos != std::string::npos) { + hostPort.erase(pos, 1); + pos = hostPort.find_first_of("]"); + + if(pos == std::string::npos) + return false; // no trailing ] although an leading [ was found + + if(pos < hostPort.length()-2) { + + if(hostPort[pos+1] != ':') + return false; // wrong port delimieter + + hostPort[pos+1] = '/'; + hasPort = true; + } + else if(pos != hostPort.length()-1) + return false; // to few characters left + + hostPort.erase(pos, 1); + } + + if(hasPort) { + std::stringstream tmp_stream(hostPort); + getline(tmp_stream,oct.host,'/'); + if(!tmp_stream.good()) + return false; + + tmp_stream >> oct.port; + } + else { + oct.host = hostPort; + oct.port = "2323"; // default sync port + } + + list.push_back(oct); + return true; +} + void Options::printUsage() { std::cout << "USAGE:" << std::endl; @@ -276,6 +318,12 @@ void Options::printOptions() std::cout << "salt=" << salt_.getHexDumpOneLine() << std::endl; std::cout << "kd_prf='" << kd_prf_ << "'" << std::endl; std::cout << "auth_algo='" << auth_algo_ << "'" << std::endl; + + std::cout << "connect_to="; + ConnectToList::const_iterator it = connect_to_.begin(); + for(; it != connect_to_.end(); ++it) + std::cout << "'" << it->host << "','" << it->port << "';"; + std::cout << std::endl; } std::string Options::getProgname() diff --git a/src/options.h b/src/options.h index 4224640..f0054b2 100644 --- a/src/options.h +++ b/src/options.h @@ -127,6 +127,8 @@ private: }; friend class instanceCleaner; + static bool splitAndAddHostPort(std::string hostPort, ConnectToList& list); + ::Mutex mutex; ConnectToList connect_to_; -- 2.11.4.GIT