Skip to content

Commit 4cb5b4f

Browse files
committed
Added a DNS script for linux and Mac OSX as an alternative to system calls (fixes #15)
1 parent 8095428 commit 4cb5b4f

File tree

13 files changed

+183
-6
lines changed

13 files changed

+183
-6
lines changed

apps/freelan/config/freelan.cfg

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,27 @@ ipv6_address_prefix_length=2aa1::1/8
722722
# Default: in_network
723723
#dns_servers_acceptance_policy=in_network
724724

725+
# The script to call when a DNS entry is to be added or removed.
726+
#
727+
# The script is called with the tap adapter's name as it's first argument.
728+
# The second argument is a verb which can be:
729+
# - add: A DNS entry must be added.
730+
# - remove: A DNS entry must be removed.
731+
# The third argument is the DNS server address to add or remove.
732+
#
733+
# If the script exits with a non-zero value, it is assumed that the addition or
734+
# removal of the DNS entry failed. If the addition fails for a given address,
735+
# the script won't be called for removal for this same address.
736+
#
737+
# On Windows, if no script is provided, FreeLAN will add/remove the DNS server
738+
# using system calls.
739+
#
740+
# On Mac OS X and Linux, there is sadly no reliable system call and you MUST
741+
# provide a script or DNS settings will simply be ignored.
742+
#
743+
# Default: <empty>
744+
#dns_script=
745+
725746
[security]
726747

727748
# The passphrase used to generate a pre-shared key to use for encryption.

apps/freelan/src/configuration_helper.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ po::options_description get_router_options()
372372
("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.")
373373
("router.maximum_routes_limit", po::value<unsigned int>()->default_value(1), "The maximum count of routes to accept for a given host.")
374374
("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.")
375+
("router.dns_script", po::value<fs::path>()->default_value(""), "The DNS script.")
375376
;
376377

377378
return result;
@@ -567,4 +568,5 @@ void setup_configuration(const fscp::logger& logger, fl::configuration& configur
567568
configuration.router.system_route_acceptance_policy = vm["router.system_route_acceptance_policy"].as<fl::router_configuration::system_route_scope_type>();
568569
configuration.router.maximum_routes_limit = vm["router.maximum_routes_limit"].as<unsigned int>();
569570
configuration.router.dns_servers_acceptance_policy = vm["router.dns_servers_acceptance_policy"].as<fl::router_configuration::dns_servers_scope_type>();
571+
configuration.router.dns_script = vm["router.dns_script"].as<fs::path>();
570572
}

apps/freelan/src/main.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,11 @@ void run(fscp::logger& logger, const cli_configuration& configuration, int& exit
478478
core.set_authentication_callback(boost::bind(&execute_authentication_script, configuration.fl_configuration.server.authentication_script, logger, _1, _2, _3, _4));
479479
}
480480

481+
if (!configuration.fl_configuration.router.dns_script.empty())
482+
{
483+
core.set_dns_callback(boost::bind(&execute_dns_script, configuration.fl_configuration.router.dns_script, logger, _1, _2, _3));
484+
}
485+
481486
core.open();
482487

483488
signals.async_wait(boost::bind(signal_handler, _1, _2, boost::ref(core), boost::ref(exit_signal)));

apps/freelan/src/tools.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,21 @@ bool execute_authentication_script(const boost::filesystem::path& script, const
227227

228228
return (exit_status == 0);
229229
}
230+
231+
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)
232+
{
233+
const std::string str_action = (action == freelan::core::DnsAction::Add) ? "add" : "remove";
234+
235+
#if defined(WINDOWS) && defined(UNICODE)
236+
int exit_status = execute(logger, script, { to_wstring(tap_adapter), to_wstring(str_action), to_wstring(dns_server.to_string()) });
237+
#else
238+
int exit_status = execute(logger, script, { tap_adapter, str_action, dns_server.to_string() });
239+
#endif
240+
241+
if (exit_status != 0)
242+
{
243+
logger(fscp::log_level::warning) << "DNS script exited with a non-zero exit status: " << exit_status;
244+
}
245+
246+
return (exit_status == 0);
247+
}

apps/freelan/src/tools.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,15 @@ bool execute_certificate_validation_script(const boost::filesystem::path& script
110110
*/
111111
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);
112112

113+
/**
114+
* \brief The DNS function.
115+
* \param script The script to call.
116+
* \param logger The logger instance.
117+
* \param tap_adapter The tap_adapter instance.
118+
* \param action A flag that indicates the action.
119+
* \param dns_server The DNS server address to add or remove.
120+
* \return The execution result of the specified script.
121+
*/
122+
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);
123+
113124
#endif /* TOOLS_HPP */

apps/freelan/src/windows/service.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,11 @@ namespace windows
515515
core.set_authentication_callback(boost::bind(&execute_authentication_script, fl_configuration.server.authentication_script, logger, _1, _2, _3, _4));
516516
}
517517

518+
if (!fl_configuration.router.dns_script.empty())
519+
{
520+
core.set_dns_callback(boost::bind(&execute_dns_script, fl_configuration.router.dns_script, logger, _1, _2, _3));
521+
}
522+
518523
core.open();
519524

520525
boost::unique_lock<boost::mutex> lock(ctx.stop_function_mutex);

libs/asiotap/include/asiotap/base_dns_servers_manager.hpp

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,16 @@ namespace asiotap
130130
*/
131131
typedef boost::shared_ptr<entry_type_impl> entry_type;
132132

133+
/**
134+
* \brief The add handler type.
135+
*/
136+
typedef boost::function<bool (const dns_server_type&)> dns_server_add_handler_type;
137+
138+
/**
139+
* \brief The remove handler type.
140+
*/
141+
typedef boost::function<bool (const dns_server_type&)> dns_server_remove_handler_type;
142+
133143
/**
134144
* \brief The registration success handler type.
135145
*/
@@ -151,7 +161,13 @@ namespace asiotap
151161
typedef boost::function<void(const dns_server_type&, const boost::system::system_error&)> dns_server_unregistration_failure_handler_type;
152162

153163
explicit base_dns_servers_manager(boost::asio::io_service& io_service_) :
154-
m_io_service(io_service_)
164+
m_io_service(io_service_),
165+
m_dns_server_add_handler(),
166+
m_dns_server_remove_handler(),
167+
m_dns_server_registration_success_handler(),
168+
m_dns_server_registration_failure_handler(),
169+
m_dns_server_unregistration_success_handler(),
170+
m_dns_server_unregistration_failure_handler()
155171
{
156172
}
157173

@@ -166,6 +182,16 @@ namespace asiotap
166182
return m_io_service;
167183
}
168184

185+
void set_dns_server_add_handler(dns_server_add_handler_type handler)
186+
{
187+
m_dns_server_add_handler = handler;
188+
}
189+
190+
void set_dns_server_remove_handler(dns_server_remove_handler_type handler)
191+
{
192+
m_dns_server_remove_handler = handler;
193+
}
194+
169195
void set_dns_server_registration_success_handler(dns_server_registration_success_handler_type handler)
170196
{
171197
m_dns_server_registration_success_handler = handler;
@@ -190,7 +216,15 @@ namespace asiotap
190216
{
191217
try
192218
{
193-
static_cast<DNSServersManagerType*>(this)->register_dns_server(dns_server);
219+
bool result = false;
220+
221+
if (m_dns_server_add_handler) {
222+
result = m_dns_server_add_handler(dns_server);
223+
}
224+
225+
if (!result) {
226+
static_cast<DNSServersManagerType*>(this)->register_dns_server(dns_server);
227+
}
194228

195229
if (m_dns_server_registration_success_handler)
196230
{
@@ -214,7 +248,15 @@ namespace asiotap
214248
{
215249
try
216250
{
217-
static_cast<DNSServersManagerType*>(this)->unregister_dns_server(dns_server);
251+
bool result = false;
252+
253+
if (m_dns_server_remove_handler) {
254+
result = m_dns_server_remove_handler(dns_server);
255+
}
256+
257+
if (!result) {
258+
static_cast<DNSServersManagerType*>(this)->unregister_dns_server(dns_server);
259+
}
218260

219261
if (m_dns_server_unregistration_success_handler)
220262
{
@@ -256,6 +298,8 @@ namespace asiotap
256298

257299
boost::asio::io_service& m_io_service;
258300
entry_table_type m_entry_table;
301+
dns_server_add_handler_type m_dns_server_add_handler;
302+
dns_server_remove_handler_type m_dns_server_remove_handler;
259303
dns_server_registration_success_handler_type m_dns_server_registration_success_handler;
260304
dns_server_registration_failure_handler_type m_dns_server_registration_failure_handler;
261305
dns_server_unregistration_success_handler_type m_dns_server_unregistration_success_handler;

libs/asiotap/include/asiotap/error.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ namespace asiotap
7272
process_handle_expected,
7373
external_process_output_parsing_error,
7474
no_such_tap_adapter,
75-
invalid_ip_configuration
75+
invalid_ip_configuration,
76+
external_process_execution_failed,
77+
no_dns_script_provided
7678
};
7779

7880
/**

libs/asiotap/src/error.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,14 @@ namespace asiotap
9494
{
9595
return "The specified IP configuration is invalid";
9696
}
97+
case asiotap_error::external_process_execution_failed:
98+
{
99+
return "The execution of the external process failed";
100+
}
101+
case asiotap_error::no_dns_script_provided:
102+
{
103+
return "No DNS script was provided";
104+
}
97105
default:
98106
{
99107
return "Unknown asiotap error";

libs/freelan/include/freelan/configuration.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,11 @@ namespace freelan
620620
* \brief The DNS servers acceptance policy.
621621
*/
622622
dns_servers_scope_type dns_servers_acceptance_policy;
623+
624+
/**
625+
* \brief The DNS script.
626+
*/
627+
boost::filesystem::path dns_script;
623628
};
624629

625630
/**

0 commit comments

Comments
 (0)