void GetExePath(int argc, char *argv[], boost::filesystem::path & path, boost::system::error_code & ec) { struct pst_status pst; std::memset(&pst, 0, sizeof(pst)); int res, pid = ::getpid(); // Acquire proc info, it contains file id of text file(executable) res = ::pstat_getproc(&pst, sizeof(pst), 0, pid); if (res < 0) { ec.assign(errno, boost::system::generic_category()); return; } pst_fid * fid_text = &pst.pst_fid_text; char buffer[PATH_MAX]; // Now get pathname. According to man pstat_getpathname returns name from system cache, // and it actually can be missing this information. // In this case function will return 0, errno will be unchanged res = ::pstat_getpathname(buffer, PATH_MAX, fid_text); if (res < 0) { ec.assign(errno, boost::system::generic_category()); return; } path.assign(buffer, buffer + res); }
void setup(char const * ifname, boost::system::error_code & ec) noexcept { std::memset(&sll_, 0, sizeof(sll_)); sll_.sll_family = static_cast<std::uint16_t>(protocol().family()); sll_.sll_protocol = static_cast<std::uint16_t>(protocol().protocol()); if ((sll_.sll_ifindex = static_cast<int>(::if_nametoindex(ifname))) == 0) { ec.assign(errno, boost::system::generic_category()); return; } struct ::ifreq ifr; std::memset(&ifr, 0, sizeof(ifr)); std::strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)-1); int fd; if ((fd = ::socket(AF_INET, SOCK_DGRAM, 0)) < 0) { ec.assign(errno, boost::system::generic_category()); return; } if (::ioctl(fd, SIOCGIFHWADDR, &ifr) != 0) { ec.assign(errno, boost::system::generic_category()); } ::close(fd); std::memcpy(sll_.sll_addr, &ifr.ifr_hwaddr, 6); }
void Socks4Strategy::ProcessResponse(const Buffer& response, boost::system::error_code& ec) { if (state() != State::kConnecting) { ec.assign(ssf::error::broken_pipe, ssf::error::get_ssf_category()); return; } Reply socks_reply; boost::asio::buffer_copy(socks_reply.MutBuffer(), boost::asio::buffer(response)); if (socks_reply.null_byte() != 0) { SSF_LOG("network_proxy", error, "SOCKSv4 connection failed (invalid socks reply)"); set_state(State::kError); ec.assign(ssf::error::connection_refused, ssf::error::get_ssf_category()); return; } if (socks_reply.status() != Reply::Status::kGranted) { SSF_LOG("network_proxy", error, "SOCKSv4 connection failed (status {})", static_cast<uint32_t>(socks_reply.status())); set_state(State::kError); ec.assign(ssf::error::connection_refused, ssf::error::get_ssf_category()); return; } set_state(State::kConnected); ec.assign(ssf::error::success, ssf::error::get_ssf_category()); }
void CopyCommandLine::ExtractHostPattern(const std::string& string, std::string* p_host, std::string* p_pattern, boost::system::error_code& ec) const { std::size_t found = string.find_first_of(kHostDirectorySeparator); if (found == std::string::npos || string.empty()) { ec.assign(::error::invalid_argument, ::error::get_ssf_category()); return; } *p_host = string.substr(0, found); *p_pattern = string.substr(found + 1); ec.assign(::error::success, ::error::get_ssf_category()); }
void CopyCommandLine::ParseSecondArgument(const std::string& second_arg, boost::system::error_code& parse_ec) { if (stdin_input_) { // No second arg should be provided with stdin option SSF_LOG( "cli", error, "parsing failed: two args provided with stdin option, one expected"); parse_ec.assign(::error::invalid_argument, ::error::get_ssf_category()); return; } // Expecting host:filepath or filepath syntax if (from_client_to_server_) { // Expecting host:dirpath ExtractHostPattern(second_arg, &host_, &output_pattern_, parse_ec); if (parse_ec) { return; } } else { // Expecting dirpath output_pattern_ = second_arg; } }
void GetExePath(int argc, char *argv[], boost::filesystem::path & path, boost::system::error_code & ec) { char buffer[PATH_MAX]; if (::realpath(getexecname(), buffer) == NULL) ec.assign(errno, boost::system::generic_category()); else path.assign(buffer); }
std::string FormatError(boost::system::error_code err) { #if BOOST_OS_WINDOWS if (err.category() == boost::system::system_category()) err.assign(err.value(), ext::boost_system_utf8_category()); #endif return FormatErrorImpl(err); }
void CopyCommandLine::ParseOptions(const Options& opts, boost::system::error_code& ec) { stdin_input_ = opts.count("stdin-input"); if (!stdin_input_) { resume_ = opts.count("resume"); recursive_ = opts.count("recursive"); check_file_integrity_ = opts.count("check-integrity"); max_parallel_copies_ = opts["max-transfers"].as<uint32_t>(); if (max_parallel_copies_ == 0) { SSF_LOG("cli", error, "max-transfers must be > 0"); ec.assign(::error::invalid_argument, ::error::get_ssf_category()); return; } } auto& args = opts["args"].as<std::vector<std::string>>(); switch (args.size()) { case 0: SSF_LOG("cli", error, "missing arguments"); ec.assign(::error::invalid_argument, ::error::get_ssf_category()); return; case 1: ParseFirstArgument(args[0], ec); if (ec) { return; } break; case 2: ParseFirstArgument(args[0], ec); if (ec) { return; } ParseSecondArgument(args[1], ec); if (ec) return; break; default: SSF_LOG("cli", error, "too many arguments"); ec.assign(::error::invalid_argument, ::error::get_ssf_category()); return; } }
void GetExePath(int argc, char *argv[], boost::filesystem::path & path, boost::system::error_code & ec) { char buffer[PATH_MAX]; ssize_t len = ::readlink("/proc/self/exe", buffer, sizeof(buffer)); if (len == -1 || len == sizeof(buffer)) ec.assign(errno, boost::system::generic_category()); else path.assign(buffer, buffer + len); }
void add(std::string const & path, int flags, boost::system::error_code & ec) { int wd = ::inotify_add_watch(fd_.native_handle(), path.c_str(), static_cast<std::uint32_t>(flags) | IN_MASK_ADD); if (wd >= 0) { std::lock_guard<decltype(mutex_)> lock(mutex_); files_.emplace(wd, path); } else { ec.assign(errno, boost::system::generic_category()); } }
void open(boost::system::error_code & ec) { if (fd_.is_open()) { ec = make_error_code(boost::asio::error::already_open); } else { int fd = ::inotify_init1(IN_NONBLOCK | IN_CLOEXEC); if (fd >= 0) fd_.assign(fd, ec); else ec.assign(errno, boost::system::generic_category()); } }
void StandardCommandLine::ParseOptions(const Options& opts, boost::system::error_code& ec) { if (IsServerCli()) { try { host_ = opts["bind-address"].as<std::string>(); } catch (cxxopts::option_not_present_exception) { host_ = ""; } } else { auto& server_address = opts["server-address"].as<std::vector<std::string>>(); if (server_address.size() > 1) { SSF_LOG("cli", error, "too many arguments"); ec.assign(::error::invalid_argument, ::error::get_ssf_category()); } else if (!server_address.size()) { SSF_LOG("cli", error, "missing arguments"); ec.assign(::error::invalid_argument, ::error::get_ssf_category()); } else host_ = server_address[0]; } show_status_ = opts.count("status"); if (IsServerCli()) { relay_only_ = opts.count("relay-only"); } else { uint32_t max_attempts = opts["max-connect-attempts"].as<uint32_t>(); if (max_attempts == 0) { SSF_LOG("cli", error, "option max-connect-attempts must be > 0"); ec.assign(::error::invalid_argument, ::error::get_ssf_category()); } else { max_connection_attempts_ = max_attempts; } reconnection_timeout_ = opts["reconnect-delay"].as<uint32_t>(); no_reconnection_ = opts.count("no-reconnect"); } gateway_ports_ = opts.count("gateway-ports"); }
void remove(std::string const & path, boost::system::error_code & ec) { std::lock_guard<decltype(mutex_)> lock(mutex_); for(auto it = files_.begin(); it != files_.end(); ++it) { if (it->second == path) { if (::inotify_rm_watch(fd_.native_handle(), it->first) == 0) files_.erase(it); else ec.assign(errno, boost::system::generic_category()); return; } } }
// never throws and set ec static time_point now(boost::system::error_code & ec) { if (BOOST_CHRONO_IS_THROWS(ec)) { boost::throw_exception( boost::system::system_error( errno_, BOOST_CHRONO_SYSTEM_CATEGORY, "errored_clock" ) ); } ec.assign( errno_, BOOST_CHRONO_SYSTEM_CATEGORY ); return time_point(); };
void GetExePath(int argc, char *argv[], boost::filesystem::path & path, boost::system::error_code & ec) { int mib[4]; mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PATHNAME; mib[3] = -1; char buffer[2048]; size_t len = sizeof(buffer); if (sysctl(mib, 4, buffer, &len, NULL, 0) != 0) ec.assign(errno, boost::system::generic_category()); else path.assign(buffer, buffer + len); }
void GetExePath(int argc, char *argv[], boost::filesystem::path & path, boost::system::error_code & ec) { std::vector<wchar_t> buffer(MAX_PATH); DWORD sz = ::GetModuleFileNameW(nullptr, buffer.data(), static_cast<DWORD>(buffer.size())); while (buffer.size() == sz) // if buffer size is not enough, increase by 2 { buffer.resize(buffer.size() * 2); sz = ::GetModuleFileNameW(nullptr, buffer.data(), static_cast<DWORD>(buffer.size())); } if (!sz) ec.assign(::GetLastError(), boost::system::system_category()); else path.assign(buffer.data(), buffer.data() + sz); }
void GetExePath(int argc, char *argv[], boost::filesystem::path & path, boost::system::error_code & ec) { char buffer[PATH_MAX]; uint32_t len = sizeof(buffer); if (_NSGetExecutablePath(buffer, &len) != 0) { ec.assign(errno, boost::system::system_category()); } else { // resolve symlinks, ., .. if possible auto * canonicalPath = ::realpath(buffer, NULL); if (canonicalPath != NULL) { strncpy(buffer, canonicalPath, len); free(canonicalPath); path.assign(buffer, buffer + len); } } }
void Socks4Strategy::PopulateRequest(const std::string& target_host, uint16_t target_port, Buffer* p_request, uint32_t* p_expected_response_size, boost::system::error_code& ec) { using namespace ssf::network::socks; if (state() != State::kConnecting) { ec.assign(ssf::error::broken_pipe, ssf::error::get_ssf_category()); return; } v4::Request socks_req; socks_req.Init(Request::Command::kConnect, target_host, target_port, ec); if (ec) { set_state(State::kError); return; } auto buffer_seq = socks_req.ConstBuffer(); p_request->resize(boost::asio::buffer_size(buffer_seq)); boost::asio::buffer_copy(boost::asio::buffer(*p_request), buffer_seq); *p_expected_response_size = 8; }
pid_t spawn (boost::asio::io_service& io_service, const child_options& opt, std::map<stream_id, boost::shared_ptr<stream_descriptor> >& streams, boost::system::error_code& ec) { typedef std::map<stream_id, child_options::stream_behaviour> beh_t; posix_spawn_file_actions_t file_actions; posix_spawn_file_actions_init(&file_actions); streams.clear(); std::vector<int> close_later; const beh_t& behaviours = opt.get_stream_behaviours(); for (beh_t::const_iterator iter = behaviours.begin(); iter != behaviours.end(); ++iter) { switch (iter->second) { case child_options::close: { posix_spawn_file_actions_addclose(&file_actions, iter->first.native()); break; } case child_options::inherit: { posix_spawn_file_actions_addinherit_np(&file_actions, iter->first.native()); break; } case child_options::pipe_read: { posix::pipe p; close_later.push_back(p.read_end()); posix_spawn_file_actions_adddup2(&file_actions, p.steal_read_end(), iter->first.native()); streams.insert( std::make_pair( iter->first, boost::shared_ptr<stream_descriptor>( new stream_descriptor(io_service, p.steal_write_end())) ) ); break; } case child_options::pipe_write: { posix::pipe p; close_later.push_back(p.write_end()); posix_spawn_file_actions_adddup2(&file_actions, p.steal_write_end(), iter->first.native()); streams.insert( std::make_pair( iter->first, boost::shared_ptr<stream_descriptor>( new stream_descriptor(io_service, p.steal_read_end())) ) ); break; } } } zero_terminated_list_of_strings argv; argv.add(opt.get_command()); argv.add(opt.get_args()); pid_t child_pid = -1; const char* _path = opt.get_command().c_str(); char* const* _argv = argv.data(); int result = posix_spawn(&child_pid, _path, &file_actions, NULL, _argv, NULL); posix_spawn_file_actions_destroy(&file_actions); std::for_each(close_later.begin(), close_later.end(), ::close); ec.assign(result, boost::system::generic_category()); return child_pid; }
uint32_t SystemRouters::AsyncConfig( const std::string& interfaces_config_filepath, const std::string& routers_config_filepath, boost::system::error_code& ec, SystemRouters::AllRoutersUpHandler all_up_handler) { PropertyTree pt; try { boost::property_tree::read_json(routers_config_filepath, pt); } catch (const std::exception&) { ec.assign(ssf::error::bad_file_descriptor, ssf::error::get_ssf_category()); io_service_.post(boost::asio::detail::binder1<AllRoutersUpHandler, boost::system::error_code>( all_up_handler, ec)); return 0; } std::unordered_set<std::string> added_routers; for (auto& config_router : pt) { auto given_router_name = config_router.second.get_child_optional("router"); if (!given_router_name) { ec.assign(ssf::error::missing_config_parameters, ssf::error::get_ssf_category()); break; } std::string router_name = given_router_name->data().c_str(); auto p_router = RoutedProtocol::get_router(router_name); // A router already exists with this name, stop if (p_router) { ec.assign(ssf::error::device_or_resource_busy, ssf::error::get_ssf_category()); break; } RoutedProtocol::StartRouter(router_name, io_service_); added_routers.insert(router_name); p_router = RoutedProtocol::get_router(router_name); p_routers_[router_name] = p_router; const auto& given_networks = config_router.second.get_child_optional("networks"); const auto& given_routes = config_router.second.get_child_optional("routes"); if (!given_networks && !given_routes) { ec.assign(ssf::error::missing_config_parameters, ssf::error::get_ssf_category()); break; } if (given_networks) { AddNetworksFromPropertyTree(router_name, *given_networks, ec); } if (!ec) { if (given_routes) { AddRoutesFromPropertyTree(p_router.get(), *given_routes, ec); } } if (ec) { break; } } // If an error occured, stop all previous routers configured if (ec) { BOOST_LOG_TRIVIAL(error) << "Error when configuring router"; for (auto& router_name : added_routers) { BOOST_LOG_TRIVIAL(error) << " * Remove router " << router_name; StopRouter(router_name); } added_routers.clear(); io_service_.post(boost::asio::detail::binder1<AllRoutersUpHandler, boost::system::error_code>( all_up_handler, ec)); } system_interfaces_.AsyncMount(interfaces_config_filepath, boost::bind(&SystemRouters::InterfaceUpHandler, this, _1, _2, all_up_handler)); return static_cast<uint32_t>(added_routers.size()); }