From 30b6f8c2d9c653304cb7e8738ee4529120f9bd90 Mon Sep 17 00:00:00 2001 From: Sebastien Vincent Date: Wed, 19 Dec 2018 21:36:23 +0100 Subject: [PATCH] [libasiotap/libfreelan] Adds an option to set DHCP for interface (Windows only). --- apps/freelan/config/freelan.cfg | 8 ++++++ apps/freelan/src/configuration_helper.cpp | 6 +++++ .../asiotap/tap_adapter_configuration.hpp | 1 + .../asiotap/windows/windows_route_manager.hpp | 1 + .../src/windows/windows_route_manager.cpp | 26 +++++++++++++++++++ .../src/windows/windows_tap_adapter.cpp | 19 ++++++++++++-- .../freelan/include/freelan/configuration.hpp | 5 ++++ libs/freelan/src/core.cpp | 3 +++ 8 files changed, 67 insertions(+), 2 deletions(-) diff --git a/apps/freelan/config/freelan.cfg b/apps/freelan/config/freelan.cfg index 80b80fd8..6996e384 100644 --- a/apps/freelan/config/freelan.cfg +++ b/apps/freelan/config/freelan.cfg @@ -465,6 +465,14 @@ public_endpoint=0.0.0.0 # ipv4_address_prefix_length=9.0.0.1/24 +# The tap adapter interface DHCP status. +# +# If it is on the interface will send DHCP request to obtain IPv4 address from +# DHCP server (which must be installed on the FreeLAN overlay network). +# +# Note: this is only available for Windows! +ipv4_dhcp=false + # The tap adapter IPv6 address and prefix length to use. # # The network address must be in numeric format with a netmask suffix. diff --git a/apps/freelan/src/configuration_helper.cpp b/apps/freelan/src/configuration_helper.cpp index 0592c43c..66d71882 100644 --- a/apps/freelan/src/configuration_helper.cpp +++ b/apps/freelan/src/configuration_helper.cpp @@ -335,6 +335,7 @@ po::options_description get_tap_adapter_options() ("tap_adapter.mss_override", po::value()->default_value(fl::mss_type()), "The MSS override.") ("tap_adapter.metric", po::value()->default_value(fl::auto_metric_type()), "The metric of the tap adapter.") ("tap_adapter.ipv4_address_prefix_length", po::value(), "The tap adapter IPv4 address and prefix length.") + ("tap_adapter.ipv4_dhcp", po::value()->default_value(false), "The tap adapter IPv4 DHCP status.") ("tap_adapter.ipv6_address_prefix_length", po::value(), "The tap adapter IPv6 address and prefix length.") ("tap_adapter.remote_ipv4_address", po::value(), "The tap adapter IPv4 remote address.") ("tap_adapter.arp_proxy_enabled", po::value()->default_value(false), "Whether to enable the ARP proxy.") @@ -538,6 +539,11 @@ void setup_configuration(const fscp::logger& logger, fl::configuration& configur configuration.tap_adapter.ipv4_address_prefix_length = vm["tap_adapter.ipv4_address_prefix_length"].as(); } + if (vm.count("tap_adapter.ipv4_dhcp")) + { + configuration.tap_adapter.ipv4_dhcp = vm["tap_adapter.ipv4_dhcp"].as(); + } + if (vm.count("tap_adapter.ipv6_address_prefix_length")) { configuration.tap_adapter.ipv6_address_prefix_length = vm["tap_adapter.ipv6_address_prefix_length"].as(); diff --git a/libs/asiotap/include/asiotap/tap_adapter_configuration.hpp b/libs/asiotap/include/asiotap/tap_adapter_configuration.hpp index 313fcbed..2d7eef06 100644 --- a/libs/asiotap/include/asiotap/tap_adapter_configuration.hpp +++ b/libs/asiotap/include/asiotap/tap_adapter_configuration.hpp @@ -58,6 +58,7 @@ namespace asiotap { boost::optional network_address; boost::optional remote_address; + bool dhcp; }; struct ipv6_configuration diff --git a/libs/asiotap/include/asiotap/windows/windows_route_manager.hpp b/libs/asiotap/include/asiotap/windows/windows_route_manager.hpp index e7a19f45..b9be9ee3 100644 --- a/libs/asiotap/include/asiotap/windows/windows_route_manager.hpp +++ b/libs/asiotap/include/asiotap/windows/windows_route_manager.hpp @@ -84,6 +84,7 @@ namespace asiotap { } + void netsh_interface_ip_set_dhcp(const std::string& interface_name, bool persistent = false); void netsh_interface_ip_set_address(const std::string& interface_name, const ip_network_address& address, bool persistent = false); windows_route_manager::route_type get_route_for(const boost::asio::ip::address& host); diff --git a/libs/asiotap/src/windows/windows_route_manager.cpp b/libs/asiotap/src/windows/windows_route_manager.cpp index 65e1844b..04fa8c8e 100644 --- a/libs/asiotap/src/windows/windows_route_manager.cpp +++ b/libs/asiotap/src/windows/windows_route_manager.cpp @@ -170,6 +170,32 @@ namespace asiotap unregister_route(route_entry.interface, route_entry.route, route_entry.metric); } + void windows_route_manager::netsh_interface_ip_set_dhcp(const std::string& interface_name, bool persistent) + { + std::vector args { + "interface", + "ip", + "set", + "address", + "dhcp", + "name=" + interface_name, + persistent ? "store=persistent" : "store=active" + }; + +#ifdef UNICODE + std::vector wargs; + + for (auto&& arg : args) + { + wargs.push_back(multi_byte_to_wide_char(arg)); + } + + netsh(wargs); +#else + netsh(args); +#endif + } + void windows_route_manager::netsh_interface_ip_set_address(const std::string& interface_name, const ip_network_address& address, bool persistent) { std::vector args; diff --git a/libs/asiotap/src/windows/windows_tap_adapter.cpp b/libs/asiotap/src/windows/windows_tap_adapter.cpp index d4d104a3..e9b79198 100644 --- a/libs/asiotap/src/windows/windows_tap_adapter.cpp +++ b/libs/asiotap/src/windows/windows_tap_adapter.cpp @@ -335,8 +335,8 @@ namespace asiotap DWORD len; if (!::DeviceIoControl(descriptor().native_handle(), TAP_WIN_IOCTL_SET_MEDIA_STATUS, - &status, sizeof(status), - &status, sizeof(status), &len, NULL)) + &status, sizeof(status), + &status, sizeof(status), &len, NULL)) { throw boost::system::system_error(::GetLastError(), boost::system::system_category()); } @@ -488,6 +488,21 @@ namespace asiotap } } + if (configuration.ipv4.dhcp) + { + try + { + m_route_manager.netsh_interface_ip_set_dhcp(display_name()); + } + catch (const boost::system::system_error& ex) + { + if (ex.code() != executeplus::executeplus_error::external_process_failed) + { + throw; + } + } + } + if (configuration.ipv6.network_address) { try diff --git a/libs/freelan/include/freelan/configuration.hpp b/libs/freelan/include/freelan/configuration.hpp index 341c6727..631ebd72 100644 --- a/libs/freelan/include/freelan/configuration.hpp +++ b/libs/freelan/include/freelan/configuration.hpp @@ -467,6 +467,11 @@ namespace freelan */ asiotap::ipv4_network_address ipv4_address_prefix_length; + /** + * \brief The IPv4 tap adapter DHCP status. + */ + bool ipv4_dhcp; + /** * \brief The IPv6 tap adapter address. */ diff --git a/libs/freelan/src/core.cpp b/libs/freelan/src/core.cpp index ce8aa110..8fd87285 100644 --- a/libs/freelan/src/core.cpp +++ b/libs/freelan/src/core.cpp @@ -1787,6 +1787,9 @@ namespace freelan m_logger(fscp::log_level::information) << "No IPv4 address configured."; } + // IPv4 DHCP (for Windows) + tap_config.ipv4.dhcp = m_configuration.tap_adapter.ipv4_dhcp; + // IPv6 address if (!m_configuration.tap_adapter.ipv6_address_prefix_length.is_null()) {