Hi, On Tue, Apr 4, 2023 at 4:01 AM Lev Stipakov <lstipa...@gmail.com> wrote:
> From: Lev Stipakov <l...@openvpn.net> > > We set DNS domain either via interactve service or DHCP. > When interactive service is not used, for example, > when profiles are started by OpenVPNService, this option > is not working for DCO and wintun. > > This implements setting DNS domain via WMIC command, > similar to implementation in interactive service. > This is done when: > > - interactive service is not used > - ip_win32_type is either METSH or IPAPI, which is > the case for DCO and wintun. > > Fixes https://github.com/OpenVPN/openvpn/issues/306 > > Change-Id: I9ab51bf1c0774564204c75ecce9ebfb818db2f5b > --- > src/openvpn/options.c | 8 ++--- > src/openvpn/tun.c | 72 ++++++++++++++++++++++++++++++++++--------- > src/openvpn/tun.h | 6 ++++ > src/openvpn/win32.h | 1 + > 4 files changed, 67 insertions(+), 20 deletions(-) > > diff --git a/src/openvpn/options.c b/src/openvpn/options.c > index 2680f268..36d54ceb 100644 > --- a/src/openvpn/options.c > +++ b/src/openvpn/options.c > @@ -3396,11 +3396,11 @@ options_postprocess_mutate_invariant(struct > options *options) > #ifdef _WIN32 > const int dev = dev_type_enum(options->dev, options->dev_type); > > + const bool dhcp = tuntap_maybe_dhcp(&options->tuntap_options); > + > /* when using wintun/ovpn-dco, kernel doesn't send DHCP requests, so > don't use it */ > if ((options->windows_driver == WINDOWS_DRIVER_WINTUN > - || options->windows_driver == WINDOWS_DRIVER_DCO) > - && (options->tuntap_options.ip_win32_type == IPW32_SET_DHCP_MASQ > - || options->tuntap_options.ip_win32_type == > IPW32_SET_ADAPTIVE)) > + || options->windows_driver == WINDOWS_DRIVER_DCO) && dhcp) > { > options->tuntap_options.ip_win32_type = IPW32_SET_NETSH; > } > @@ -3408,8 +3408,6 @@ options_postprocess_mutate_invariant(struct options > *options) > if ((dev == DEV_TYPE_TUN || dev == DEV_TYPE_TAP) && > !options->route_delay_defined) > { > /* delay may only be necessary when we perform DHCP handshake */ > - const bool dhcp = (options->tuntap_options.ip_win32_type == > IPW32_SET_DHCP_MASQ) > - || (options->tuntap_options.ip_win32_type == > IPW32_SET_ADAPTIVE); > if ((options->mode == MODE_POINT_TO_POINT) && dhcp) > { > options->route_delay_defined = true; > diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c > index 2ebe4809..c2cc7e26 100644 > --- a/src/openvpn/tun.c > +++ b/src/openvpn/tun.c > @@ -84,6 +84,8 @@ static void netsh_set_dns6_servers(const struct in6_addr > *addr_list, > > static void netsh_command(const struct argv *a, int n, int msglevel); > > +static void exec_command(const char *prefix, const struct argv *a, int n, > int msglevel); > + > static const char *netsh_get_id(const char *dev_node, struct gc_arena > *gc); > > static bool > @@ -324,6 +326,22 @@ out: > return ret; > } > > +static void > +wmic_do_dns_domain(bool add, const struct tuntap *tt) > +{ > + if (!tt->options.domain) > + { > + return; > + } > + > + struct argv argv = argv_new(); > + argv_printf(&argv, "%s%s nicconfig where (InterfaceIndex=%ld) call > SetDNSDomain %s", > + get_win_sys_path(), WMIC_PATH_SUFFIX, tt->adapter_index, > add ? tt->options.domain : ""); > + exec_command("WMIC", &argv, 1, M_WARN); > + > + argv_free(&argv); > +} > + > #endif /* ifdef _WIN32 */ > > #ifdef TARGET_SOLARIS > @@ -1190,6 +1208,11 @@ do_ifconfig_ipv6(struct tuntap *tt, const char > *ifname, int tun_mtu, > /* set ipv6 dns servers if any are specified */ > netsh_set_dns6_servers(tt->options.dns6, tt->options.dns6_len, > tt->adapter_index); > windows_set_mtu(tt->adapter_index, AF_INET6, tun_mtu); > + > + if (!tt->did_ifconfig_setup && !tuntap_maybe_dhcp(&tt->options)) > Adding "!tuntap_maybe_dhcp()" here looks wrong. We must set the domain if not set during IPv4 processing and that is indicated by did_ifconfig_setup. Just as done in the case handled by interactive-service above. For example: in case there is no IPv4 address, the domain will not be set at this point but tuntap_may_dhcp() could still be true if the driver is tap-windows6. And the above will wrongly skip the wmic call. Even otherwise, adding a seemingly dhcp-related check in IPv6 case will only confuse us in future. Same in close_tun() to match. Once that check is removed there is no need to introduce tuntap_maybe_dhcp() in this patch at all. This can be kept simple by just adding wmic_do_dns_domain() and calling it in two places under the same conditions as done using service. Plus the netsh_command() to exec_command() generalization. That makes it easier to review as well. As for refactoring/cleaning up, we can address it separately as the whole ip-win32 thing is a mess that could benefit from a thorough cleanup. + { > + wmic_do_dns_domain(true, tt); > + } > } > #else /* platforms we have no IPv6 code for */ > msg(M_FATAL, "Sorry, but I don't know how to do IPv6 'ifconfig' > commands on this operating system. You should ifconfig your TUN/TAP device > manually or use an --up script."); > @@ -1525,7 +1548,7 @@ do_ifconfig_ipv4(struct tuntap *tt, const char > *ifname, int tun_mtu, > ifname, ifconfig_local, > ifconfig_remote_netmask); > } > - else if (tt->options.ip_win32_type == IPW32_SET_DHCP_MASQ || > tt->options.ip_win32_type == IPW32_SET_ADAPTIVE) > + else if (tuntap_maybe_dhcp(&tt->options)) > { > /* Let the DHCP configure the interface. */ > } > @@ -1535,11 +1558,18 @@ do_ifconfig_ipv4(struct tuntap *tt, const char > *ifname, int tun_mtu, > do_dns_service(true, AF_INET, tt); > do_dns_domain_service(true, tt); > } > - else if (tt->options.ip_win32_type == IPW32_SET_NETSH) > + else > { > - netsh_ifconfig(&tt->options, tt->adapter_index, tt->local, > - tt->adapter_netmask, NI_IP_NETMASK|NI_OPTIONS); > + if (tt->options.ip_win32_type == IPW32_SET_NETSH) > + { > + netsh_ifconfig(&tt->options, tt->adapter_index, tt->local, > + tt->adapter_netmask, NI_IP_NETMASK | > NI_OPTIONS); > + } > + > + wmic_do_dns_domain(true, tt); > } > + > + > if (tt->options.msg_channel) > { > do_set_mtu_service(tt, AF_INET, tun_mtu); > @@ -5238,12 +5268,8 @@ dhcp_renew(const struct tuntap *tt) > } > } > > -/* > - * netsh functions > - */ > - > static void > -netsh_command(const struct argv *a, int n, int msglevel) > +exec_command(const char *prefix, const struct argv *a, int n, int > msglevel) > { > int i; > for (i = 0; i < n; ++i) > @@ -5251,8 +5277,8 @@ netsh_command(const struct argv *a, int n, int > msglevel) > bool status; > management_sleep(0); > netcmd_semaphore_lock(); > - argv_msg_prefix(M_INFO, a, "NETSH"); > - status = openvpn_execve_check(a, NULL, 0, "ERROR: netsh command > failed"); > + argv_msg_prefix(M_INFO, a, prefix); > + status = openvpn_execve_check(a, NULL, 0, "ERROR: command > failed"); > netcmd_semaphore_release(); > if (status) > { > @@ -5260,7 +5286,13 @@ netsh_command(const struct argv *a, int n, int > msglevel) > } > management_sleep(4); > } > - msg(msglevel, "NETSH: command failed"); > + msg(msglevel, "%s: command failed", prefix); > +} > + > +static void > +netsh_command(const struct argv *a, int n, int msglevel) > +{ > + exec_command("NETSH", a, n, msglevel); > } > > void > @@ -6927,6 +6959,11 @@ close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx) > } > else > { > + if (!tt->did_ifconfig_setup && > !tuntap_maybe_dhcp(&tt->options)) > same here > + { > + wmic_do_dns_domain(false, tt); > + } > + > netsh_delete_address_dns(tt, true, &gc); > } > } > @@ -6937,7 +6974,7 @@ close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx) > { > /* We didn't do ifconfig. */ > } > - else if (tt->options.ip_win32_type == IPW32_SET_DHCP_MASQ || > tt->options.ip_win32_type == IPW32_SET_ADAPTIVE) > + else if (tuntap_maybe_dhcp(&tt->options)) > { > /* We don't have to clean the configuration with DHCP. */ > } > @@ -6947,9 +6984,14 @@ close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx) > do_dns_service(false, AF_INET, tt); > do_address_service(false, AF_INET, tt); > } > - else if (tt->options.ip_win32_type == IPW32_SET_NETSH) > + else > { > - netsh_delete_address_dns(tt, false, &gc); > + wmic_do_dns_domain(false, tt); > + > + if (tt->options.ip_win32_type == IPW32_SET_NETSH) > + { > + netsh_delete_address_dns(tt, false, &gc); > + } > } > } > > diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h > index e19e1a2e..0d8e2307 100644 > --- a/src/openvpn/tun.h > +++ b/src/openvpn/tun.h > @@ -668,6 +668,12 @@ tuntap_is_dco_win_timeout(struct tuntap *tt, int > status) > const char * > print_windows_driver(enum windows_driver_type windows_driver); > > +static inline bool > +tuntap_maybe_dhcp(struct tuntap_options *o) > +{ > + return o->ip_win32_type == IPW32_SET_DHCP_MASQ || o->ip_win32_type == > IPW32_SET_ADAPTIVE; > +} > + > #else /* ifdef _WIN32 */ > > static inline bool > diff --git a/src/openvpn/win32.h b/src/openvpn/win32.h > index 72ffb012..36059662 100644 > --- a/src/openvpn/win32.h > +++ b/src/openvpn/win32.h > @@ -38,6 +38,7 @@ > #define WIN_ROUTE_PATH_SUFFIX "\\system32\\route.exe" > #define WIN_IPCONFIG_PATH_SUFFIX "\\system32\\ipconfig.exe" > #define WIN_NET_PATH_SUFFIX "\\system32\\net.exe" > +#define WMIC_PATH_SUFFIX "\\system32\\wbem\\wmic.exe" > > /* > * Win32-specific OpenVPN code, targeted at the mingw > -- > 2.23.0.windows.1 Selva
_______________________________________________ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel