Skip to content

Commit

Permalink
Enable dhcp on tap adapter using interactive service
Browse files Browse the repository at this point in the history
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 <[email protected]>
Acked-by: Lev Stipakov <[email protected]>
Acked-by: Gert Doering <[email protected]>
Message-Id: <[email protected]>
URL: https://www.mail-archive.com/[email protected]/msg17517.html
Signed-off-by: Gert Doering <[email protected]>
  • Loading branch information
selvanair authored and cron2 committed Oct 5, 2018
1 parent a29b60c commit b4fc8bb
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 2 deletions.
8 changes: 7 additions & 1 deletion include/openvpn-msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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_ */
53 changes: 52 additions & 1 deletion src/openvpn/tun.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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;
Expand Down
47 changes: 47 additions & 0 deletions src/openvpnserv/interactive.c
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,45 @@ HandleDNSConfigMessage(const dns_cfg_message_t *msg, undo_lists_t *lists)
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)
{
Expand All @@ -1175,6 +1214,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 = {
Expand Down Expand Up @@ -1235,6 +1275,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);
Expand Down

0 comments on commit b4fc8bb

Please sign in to comment.