Beispiel #1
0
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);
}
Beispiel #2
0
    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;
  }
}
Beispiel #6
0
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);
}
Beispiel #7
0
	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;
  }
}
Beispiel #9
0
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);
}
Beispiel #10
0
 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());
     }
 }
Beispiel #11
0
 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");
}
Beispiel #13
0
 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;
         }
     }
 }
Beispiel #14
0
 // 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();
 };
Beispiel #15
0
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);
}
Beispiel #16
0
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);

}
Beispiel #17
0
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;
}
Beispiel #19
0
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());
}