Skip to content

Commit

Permalink
Added a DNS script for linux and Mac OSX as an alternative to system …
Browse files Browse the repository at this point in the history
…calls (fixes #15)
  • Loading branch information
ereOn committed May 5, 2015
1 parent 8095428 commit 4cb5b4f
Show file tree
Hide file tree
Showing 13 changed files with 183 additions and 6 deletions.
21 changes: 21 additions & 0 deletions apps/freelan/config/freelan.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,27 @@ ipv6_address_prefix_length=2aa1::1/8
# Default: in_network
#dns_servers_acceptance_policy=in_network

# The script to call when a DNS entry is to be added or removed.
#
# The script is called with the tap adapter's name as it's first argument.
# The second argument is a verb which can be:
# - add: A DNS entry must be added.
# - remove: A DNS entry must be removed.
# The third argument is the DNS server address to add or remove.
#
# If the script exits with a non-zero value, it is assumed that the addition or
# removal of the DNS entry failed. If the addition fails for a given address,
# the script won't be called for removal for this same address.
#
# On Windows, if no script is provided, FreeLAN will add/remove the DNS server
# using system calls.
#
# On Mac OS X and Linux, there is sadly no reliable system call and you MUST
# provide a script or DNS settings will simply be ignored.
#
# Default: <empty>
#dns_script=

[security]

# The passphrase used to generate a pre-shared key to use for encryption.
Expand Down
2 changes: 2 additions & 0 deletions apps/freelan/src/configuration_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ po::options_description get_router_options()
("router.system_route_acceptance_policy", po::value<fl::router_configuration::system_route_scope_type>()->default_value(fl::router_configuration::system_route_scope_type::none), "The system route acceptance policy.")
("router.maximum_routes_limit", po::value<unsigned int>()->default_value(1), "The maximum count of routes to accept for a given host.")
("router.dns_servers_acceptance_policy", po::value<fl::router_configuration::dns_servers_scope_type>()->default_value(fl::router_configuration::dns_servers_scope_type::in_network), "The DNS servers acceptance policy.")
("router.dns_script", po::value<fs::path>()->default_value(""), "The DNS script.")
;

return result;
Expand Down Expand Up @@ -567,4 +568,5 @@ void setup_configuration(const fscp::logger& logger, fl::configuration& configur
configuration.router.system_route_acceptance_policy = vm["router.system_route_acceptance_policy"].as<fl::router_configuration::system_route_scope_type>();
configuration.router.maximum_routes_limit = vm["router.maximum_routes_limit"].as<unsigned int>();
configuration.router.dns_servers_acceptance_policy = vm["router.dns_servers_acceptance_policy"].as<fl::router_configuration::dns_servers_scope_type>();
configuration.router.dns_script = vm["router.dns_script"].as<fs::path>();
}
5 changes: 5 additions & 0 deletions apps/freelan/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,11 @@ void run(fscp::logger& logger, const cli_configuration& configuration, int& exit
core.set_authentication_callback(boost::bind(&execute_authentication_script, configuration.fl_configuration.server.authentication_script, logger, _1, _2, _3, _4));
}

if (!configuration.fl_configuration.router.dns_script.empty())
{
core.set_dns_callback(boost::bind(&execute_dns_script, configuration.fl_configuration.router.dns_script, logger, _1, _2, _3));
}

core.open();

signals.async_wait(boost::bind(signal_handler, _1, _2, boost::ref(core), boost::ref(exit_signal)));
Expand Down
18 changes: 18 additions & 0 deletions apps/freelan/src/tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,21 @@ bool execute_authentication_script(const boost::filesystem::path& script, const

return (exit_status == 0);
}

bool execute_dns_script(const boost::filesystem::path& script, const fscp::logger& logger, const std::string& tap_adapter, freelan::core::DnsAction action, const boost::asio::ip::address& dns_server)
{
const std::string str_action = (action == freelan::core::DnsAction::Add) ? "add" : "remove";

#if defined(WINDOWS) && defined(UNICODE)
int exit_status = execute(logger, script, { to_wstring(tap_adapter), to_wstring(str_action), to_wstring(dns_server.to_string()) });
#else
int exit_status = execute(logger, script, { tap_adapter, str_action, dns_server.to_string() });
#endif

if (exit_status != 0)
{
logger(fscp::log_level::warning) << "DNS script exited with a non-zero exit status: " << exit_status;
}

return (exit_status == 0);
}
11 changes: 11 additions & 0 deletions apps/freelan/src/tools.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,15 @@ bool execute_certificate_validation_script(const boost::filesystem::path& script
*/
bool execute_authentication_script(const boost::filesystem::path& script, const fscp::logger& logger, const std::string& username, const std::string& password, const std::string& remote_host, uint16_t remote_port);

/**
* \brief The DNS function.
* \param script The script to call.
* \param logger The logger instance.
* \param tap_adapter The tap_adapter instance.
* \param action A flag that indicates the action.
* \param dns_server The DNS server address to add or remove.
* \return The execution result of the specified script.
*/
bool execute_dns_script(const boost::filesystem::path& script, const fscp::logger& logger, const std::string& tap_adapter, freelan::core::DnsAction action, const boost::asio::ip::address& dns_server);

#endif /* TOOLS_HPP */
5 changes: 5 additions & 0 deletions apps/freelan/src/windows/service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,11 @@ namespace windows
core.set_authentication_callback(boost::bind(&execute_authentication_script, fl_configuration.server.authentication_script, logger, _1, _2, _3, _4));
}

if (!fl_configuration.router.dns_script.empty())
{
core.set_dns_callback(boost::bind(&execute_dns_script, fl_configuration.router.dns_script, logger, _1, _2, _3));
}

core.open();

boost::unique_lock<boost::mutex> lock(ctx.stop_function_mutex);
Expand Down
50 changes: 47 additions & 3 deletions libs/asiotap/include/asiotap/base_dns_servers_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ namespace asiotap
*/
typedef boost::shared_ptr<entry_type_impl> entry_type;

/**
* \brief The add handler type.
*/
typedef boost::function<bool (const dns_server_type&)> dns_server_add_handler_type;

/**
* \brief The remove handler type.
*/
typedef boost::function<bool (const dns_server_type&)> dns_server_remove_handler_type;

/**
* \brief The registration success handler type.
*/
Expand All @@ -151,7 +161,13 @@ namespace asiotap
typedef boost::function<void(const dns_server_type&, const boost::system::system_error&)> dns_server_unregistration_failure_handler_type;

explicit base_dns_servers_manager(boost::asio::io_service& io_service_) :
m_io_service(io_service_)
m_io_service(io_service_),
m_dns_server_add_handler(),
m_dns_server_remove_handler(),
m_dns_server_registration_success_handler(),
m_dns_server_registration_failure_handler(),
m_dns_server_unregistration_success_handler(),
m_dns_server_unregistration_failure_handler()
{
}

Expand All @@ -166,6 +182,16 @@ namespace asiotap
return m_io_service;
}

void set_dns_server_add_handler(dns_server_add_handler_type handler)
{
m_dns_server_add_handler = handler;
}

void set_dns_server_remove_handler(dns_server_remove_handler_type handler)
{
m_dns_server_remove_handler = handler;
}

void set_dns_server_registration_success_handler(dns_server_registration_success_handler_type handler)
{
m_dns_server_registration_success_handler = handler;
Expand All @@ -190,7 +216,15 @@ namespace asiotap
{
try
{
static_cast<DNSServersManagerType*>(this)->register_dns_server(dns_server);
bool result = false;

if (m_dns_server_add_handler) {
result = m_dns_server_add_handler(dns_server);
}

if (!result) {
static_cast<DNSServersManagerType*>(this)->register_dns_server(dns_server);
}

if (m_dns_server_registration_success_handler)
{
Expand All @@ -214,7 +248,15 @@ namespace asiotap
{
try
{
static_cast<DNSServersManagerType*>(this)->unregister_dns_server(dns_server);
bool result = false;

if (m_dns_server_remove_handler) {
result = m_dns_server_remove_handler(dns_server);
}

if (!result) {
static_cast<DNSServersManagerType*>(this)->unregister_dns_server(dns_server);
}

if (m_dns_server_unregistration_success_handler)
{
Expand Down Expand Up @@ -256,6 +298,8 @@ namespace asiotap

boost::asio::io_service& m_io_service;
entry_table_type m_entry_table;
dns_server_add_handler_type m_dns_server_add_handler;
dns_server_remove_handler_type m_dns_server_remove_handler;
dns_server_registration_success_handler_type m_dns_server_registration_success_handler;
dns_server_registration_failure_handler_type m_dns_server_registration_failure_handler;
dns_server_unregistration_success_handler_type m_dns_server_unregistration_success_handler;
Expand Down
4 changes: 3 additions & 1 deletion libs/asiotap/include/asiotap/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ namespace asiotap
process_handle_expected,
external_process_output_parsing_error,
no_such_tap_adapter,
invalid_ip_configuration
invalid_ip_configuration,
external_process_execution_failed,
no_dns_script_provided
};

/**
Expand Down
8 changes: 8 additions & 0 deletions libs/asiotap/src/error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,14 @@ namespace asiotap
{
return "The specified IP configuration is invalid";
}
case asiotap_error::external_process_execution_failed:
{
return "The execution of the external process failed";
}
case asiotap_error::no_dns_script_provided:
{
return "No DNS script was provided";
}
default:
{
return "Unknown asiotap error";
Expand Down
5 changes: 5 additions & 0 deletions libs/freelan/include/freelan/configuration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,11 @@ namespace freelan
* \brief The DNS servers acceptance policy.
*/
dns_servers_scope_type dns_servers_acceptance_policy;

/**
* \brief The DNS script.
*/
boost::filesystem::path dns_script;
};

/**
Expand Down
21 changes: 21 additions & 0 deletions libs/freelan/include/freelan/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,16 @@ namespace freelan
*/
typedef boost::function<void (const asiotap::tap_adapter&)> tap_adapter_handler_type;

enum class DnsAction {
Add,
Remove
};

/**
* \brief The up callback type.
*/
typedef boost::function<bool (const std::string&, DnsAction, const boost::asio::ip::address&)> dns_handler_type;

// Public constants

/**
Expand Down Expand Up @@ -408,6 +418,16 @@ namespace freelan
m_tap_adapter_down_callback = callback;
}

/**
* \brief Set the DNS callback.
* \param callback The callback.
* \warning This method can only be called when the core is NOT running.
*/
void set_dns_callback(dns_handler_type callback)
{
m_dns_callback = callback;
}

/**
* \brief Open the core.
* \see close
Expand Down Expand Up @@ -441,6 +461,7 @@ namespace freelan
certificate_validation_handler_type m_certificate_validation_callback;
tap_adapter_handler_type m_tap_adapter_up_callback;
tap_adapter_handler_type m_tap_adapter_down_callback;
dns_handler_type m_dns_callback;

private: /* General purpose */

Expand Down
4 changes: 3 additions & 1 deletion libs/freelan/src/configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ namespace freelan
accept_routes_requests(true),
internal_route_acceptance_policy(internal_route_scope_type::unicast_in_network),
system_route_acceptance_policy(system_route_scope_type::none),
maximum_routes_limit(1)
maximum_routes_limit(1),
dns_servers_acceptance_policy(dns_servers_scope_type::in_network),
dns_script()
{
}

Expand Down
35 changes: 34 additions & 1 deletion libs/freelan/src/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ namespace freelan
m_certificate_validation_callback(),
m_tap_adapter_up_callback(),
m_tap_adapter_down_callback(),
m_dns_callback(),
m_fscp_server(),
m_contact_timer(m_io_service, CONTACT_PERIOD),
m_dynamic_contact_timer(m_io_service, DYNAMIC_CONTACT_PERIOD),
Expand Down Expand Up @@ -502,8 +503,40 @@ namespace freelan
m_route_manager.set_route_unregistration_failure_handler([this](const asiotap::route_manager::route_type& route, const boost::system::system_error& ex){
m_logger(fscp::log_level::warning) << "Unable to remove system route (" << route << "): " << ex.what();
});

// Setup the DNS servers manager.
m_dns_servers_manager.set_dns_server_add_handler([this](const asiotap::dns_servers_manager::dns_server_type& dns_server) -> bool {
if (m_dns_callback) {
if (!m_dns_callback(dns_server.interface_name, DnsAction::Add, dns_server.dns_server_address.value())) {
throw boost::system::system_error(make_error_code(asiotap::asiotap_error::external_process_execution_failed));
}

return true;
} else {
#ifndef WINDOWS
throw boost::system::system_error(make_error_code(asiotap::asiotap_error::no_dns_script_provided));
#endif
}

return false;
});
m_dns_servers_manager.set_dns_server_remove_handler([this](const asiotap::dns_servers_manager::dns_server_type& dns_server) -> bool {
if (m_dns_callback) {
if (!m_dns_callback(dns_server.interface_name, DnsAction::Remove, dns_server.dns_server_address.value())) {
throw boost::system::system_error(make_error_code(asiotap::asiotap_error::external_process_execution_failed));
}

return true;
}
else {
#ifndef WINDOWS
m_logger(fscp::log_level::warning) << "Should have added a DNS server but no DNS script was configured.";
throw boost::system::system_error(make_error_code(asiotap::asiotap_error::no_dns_script_provided));
#endif
}

return false;
});
m_dns_servers_manager.set_dns_server_registration_success_handler([this](const asiotap::dns_servers_manager::dns_server_type& dns_server){
m_logger(fscp::log_level::information) << "Added DNS server: " << dns_server;
});
Expand Down

0 comments on commit 4cb5b4f

Please sign in to comment.