ACK ti 2. lokak. 2018 klo 23.02 selva.n...@gmail.com kirjoitti:
> From: Selva Nair <selva.n...@gmail.com> > > Currently, if dhcp on the TAP interface is disabled, OpenVPN > on Windows tries to enable it using netsh but that succeeds only when > run with admin privileges. > > When interactive service is available, delegate this task to the > service. > > Trac #1111 > Tested on Windows 7 > > Signed-off-by: Selva Nair <selva.n...@gmail.com> > --- > v2 changes: As suggested by Lev > - In comment, clarify the 10 chars room is for printing 32 bit int > - Use get_win_sys_path() added in the accompanying patch (1 of 3) > > Refactoring of writing to the message channel is in the > following patch. > > include/openvpn-msg.h | 8 ++++++- > src/openvpn/tun.c | 53 > ++++++++++++++++++++++++++++++++++++++++++- > src/openvpnserv/interactive.c | 47 ++++++++++++++++++++++++++++++++++++++ > 3 files changed, 106 insertions(+), 2 deletions(-) > > diff --git a/include/openvpn-msg.h b/include/openvpn-msg.h > index 82ecfe8..66177a2 100644 > --- a/include/openvpn-msg.h > +++ b/include/openvpn-msg.h > @@ -37,7 +37,8 @@ typedef enum { > msg_flush_neighbors, > msg_add_block_dns, > msg_del_block_dns, > - msg_register_dns > + msg_register_dns, > + msg_enable_dhcp, > } message_type_t; > > typedef struct { > @@ -111,4 +112,9 @@ typedef struct { > interface_t iface; > } block_dns_message_t; > > +typedef struct { > + message_header_t header; > + interface_t iface; > +} enable_dhcp_message_t; > + > #endif /* ifndef OPENVPN_MSG_H_ */ > diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c > index 50f158c..a2d5315 100644 > --- a/src/openvpn/tun.c > +++ b/src/openvpn/tun.c > @@ -5203,6 +5203,49 @@ netsh_enable_dhcp(const struct tuntap_options *to, > argv_reset(&argv); > } > > +/* Enable dhcp on tap adapter using iservice */ > +static bool > +service_enable_dhcp(const struct tuntap *tt) > +{ > + DWORD len; > + bool ret = false; > + ack_message_t ack; > + struct gc_arena gc = gc_new(); > + HANDLE pipe = tt->options.msg_channel; > + > + enable_dhcp_message_t dhcp = { > + .header = { > + msg_enable_dhcp, > + sizeof(enable_dhcp_message_t), > + 0 > + }, > + .iface = { .index = tt->adapter_index, .name = "" } > + }; > + > + if (!WriteFile(pipe, &dhcp, sizeof(dhcp), &len, NULL) > + || !ReadFile(pipe, &ack, sizeof(ack), &len, NULL)) > + { > + msg(M_WARN, "Enable_dhcp: could not talk to service: %s [%lu]", > + strerror_win32(GetLastError(), &gc), GetLastError()); > + goto out; > + } > + > + if (ack.error_number != NO_ERROR) > + { > + msg(M_NONFATAL, "TUN: enabling dhcp using service failed: %s > [status=%u if_index=%d]", > + strerror_win32(ack.error_number, &gc), ack.error_number, > dhcp.iface.index); > + } > + else > + { > + msg(M_INFO, "DHCP enabled on interface %d using service", > dhcp.iface.index); > + ret = true; > + } > + > +out: > + gc_free(&gc); > + return ret; > +} > + > /* > * Return a TAP name for netsh commands. > */ > @@ -5683,7 +5726,15 @@ open_tun(const char *dev, const char *dev_type, > const char *dev_node, struct tun > */ > if (dhcp_status(tt->adapter_index) == DHCP_STATUS_DISABLED) > { > - netsh_enable_dhcp(&tt->options, tt->actual_name); > + /* try using the service if available, else directly > execute netsh */ > + if (tt->options.msg_channel) > + { > + service_enable_dhcp(tt); > + } > + else > + { > + netsh_enable_dhcp(&tt->options, tt->actual_name); > + } > } > dhcp_masq = true; > dhcp_masq_post = true; > diff --git a/src/openvpnserv/interactive.c b/src/openvpnserv/interactive.c > index 0489684..c0fdc19 100644 > --- a/src/openvpnserv/interactive.c > +++ b/src/openvpnserv/interactive.c > @@ -1165,6 +1165,45 @@ out: > return err; > } > > +static DWORD > +HandleEnableDHCPMessage(const enable_dhcp_message_t *dhcp) > +{ > + DWORD err = 0; > + DWORD timeout = 5000; /* in milli seconds */ > + wchar_t argv0[MAX_PATH]; > + > + /* Path of netsh */ > + swprintf(argv0, _countof(argv0), L"%s\\%s", get_win_sys_path(), > L"netsh.exe"); > + argv0[_countof(argv0) - 1] = L'\0'; > + > + /* cmd template: > + * netsh interface ipv4 set address name=$if_index source=dhcp > + */ > + const wchar_t *fmt = L"netsh interface ipv4 set address name=\"%d\" > source=dhcp"; > + > + /* max cmdline length in wchars -- include room for if index: > + * 10 chars for 32 bit int in decimal and +1 for NUL > + */ > + size_t ncmdline = wcslen(fmt) + 10 + 1; > + wchar_t *cmdline = malloc(ncmdline*sizeof(wchar_t)); > + if (!cmdline) > + { > + err = ERROR_OUTOFMEMORY; > + return err; > + } > + > + openvpn_sntprintf(cmdline, ncmdline, fmt, dhcp->iface.index); > + > + err = ExecCommand(argv0, cmdline, timeout); > + > + /* Note: This could fail if dhcp is already enabled, so the caller > + * may not want to treat errors as FATAL. > + */ > + > + free(cmdline); > + return err; > +} > + > static VOID > HandleMessage(HANDLE pipe, DWORD bytes, DWORD count, LPHANDLE events, > undo_lists_t *lists) > { > @@ -1176,6 +1215,7 @@ HandleMessage(HANDLE pipe, DWORD bytes, DWORD count, > LPHANDLE events, undo_lists > flush_neighbors_message_t flush_neighbors; > block_dns_message_t block_dns; > dns_cfg_message_t dns; > + enable_dhcp_message_t dhcp; > } msg; > ack_message_t ack = { > .header = { > @@ -1236,6 +1276,13 @@ HandleMessage(HANDLE pipe, DWORD bytes, DWORD > count, LPHANDLE events, undo_lists > ack.error_number = HandleDNSConfigMessage(&msg.dns, lists); > break; > > + case msg_enable_dhcp: > + if (msg.header.size == sizeof(msg.dhcp)) > + { > + ack.error_number = HandleEnableDHCPMessage(&msg.dhcp); > + } > + break; > + > default: > ack.error_number = ERROR_MESSAGE_TYPE; > MsgToEventLog(MSG_FLAGS_ERROR, TEXT("Unknown message type > %d"), msg.header.type); > -- > 2.1.4 > > > > _______________________________________________ > Openvpn-devel mailing list > Openvpn-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/openvpn-devel > -- -Lev
_______________________________________________ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel