Attention is currently required from: flichtenheld, plaisthos. Hello plaisthos, flichtenheld,
I'd like you to do a code review. Please visit http://gerrit.openvpn.net/c/openvpn/+/943?usp=email to review the following change. Change subject: win: create adapter on demand ...................................................................... win: create adapter on demand The installer currently creates one adapter per driver. When a user tries to start a second VPN connection while another is active, the client fails with an unclear error message: "All ovpn-dco adapters on this system are currently in use or disabled." This message does not guide the user toward resolving the issue, such as by running the shortcut "Add a new dco-win virtual network adapter." To improve user experience, the client will now create an adapter on demand when no available adapters exist. The client sends a command specifying the adapter type to the interactive service, which then executes tapctl.exe to create a new adapter. This feature requires the interactive service, but this should not pose a problem since even our automatic service has recently started relying on the interactive service. GitHub: #728 Change-Id: I621d44ec6b0facc524875c15ddfd11ec47b06c15 Signed-off-by: Lev Stipakov <l...@openvpn.net> --- M include/openvpn-msg.h M src/openvpn/socket.c M src/openvpn/tun.c M src/openvpnserv/common.c M src/openvpnserv/interactive.c M src/openvpnserv/service.h 6 files changed, 154 insertions(+), 10 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/43/943/1 diff --git a/include/openvpn-msg.h b/include/openvpn-msg.h index 8b48053..2cf8d40 100644 --- a/include/openvpn-msg.h +++ b/include/openvpn-msg.h @@ -47,7 +47,8 @@ msg_register_ring_buffers, msg_set_mtu, msg_add_wins_cfg, - msg_del_wins_cfg + msg_del_wins_cfg, + msg_create_adapter } message_type_t; typedef struct { @@ -172,4 +173,15 @@ int mtu; } set_mtu_message_t; +typedef enum { + ADAPTER_TYPE_DCO, + ADAPTER_TYPE_TAP, + ADAPTER_TYPE_WINTUN +} adapter_type_t; + +typedef struct { + message_header_t header; + adapter_type_t adapter_type; +} create_adapter_message_t; + #endif /* ifndef OPENVPN_MSG_H_ */ diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index a0c22b1..34a049e 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -2231,6 +2231,7 @@ ALLOC_OBJ_CLEAR(tt, struct tuntap); tt->backend_driver = DRIVER_DCO; + tt->options.msg_channel = c->options.msg_channel; const char *device_guid = NULL; /* not used */ tun_open_device(tt, c->options.dev_node, &device_guid, &c->gc); diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c index 4f7de6c..7532c9c 100644 --- a/src/openvpn/tun.c +++ b/src/openvpn/tun.c @@ -451,6 +451,63 @@ argv_free(&argv); } +static bool +do_create_adapter_service(HANDLE msg_channel, enum tun_driver_type driver_type) +{ + bool ret = false; + ack_message_t ack; + struct gc_arena gc = gc_new(); + + adapter_type_t t; + switch (driver_type) + { + case WINDOWS_DRIVER_TAP_WINDOWS6: + t = ADAPTER_TYPE_TAP; + break; + + case WINDOWS_DRIVER_WINTUN: + t = ADAPTER_TYPE_WINTUN; + break; + + case DRIVER_DCO: + t = ADAPTER_TYPE_DCO; + break; + + default: + msg(M_NONFATAL, "Invalid backend driver %s", print_tun_backend_driver(driver_type)); + goto out; + } + + create_adapter_message_t msg = { + .header = { + msg_create_adapter, + sizeof(create_adapter_message_t), + 0 + }, + .adapter_type = t + }; + + if (!send_msg_iservice(msg_channel, &msg, sizeof(msg), &ack, "create_adapter")) + { + goto out; + } + + if (ack.error_number != NO_ERROR) + { + msg(M_NONFATAL, "TUN: creating %s adapter using service failed: %s [status=%u]", + print_tun_backend_driver(driver_type), strerror_win32(ack.error_number, &gc), ack.error_number); + } + else + { + msg(M_INFO, "%s adapter created using service", print_tun_backend_driver(driver_type)); + ret = true; + } + +out: + gc_free(&gc); + return ret; +} + #endif /* ifdef _WIN32 */ #ifdef TARGET_SOLARIS @@ -3713,7 +3770,7 @@ } } -static const struct device_instance_id_interface * +static struct device_instance_id_interface * get_device_instance_id_interface(struct gc_arena *gc) { HDEVINFO dev_info_set; @@ -3841,7 +3898,7 @@ return first; } -static const struct tap_reg * +static struct tap_reg * get_tap_reg(struct gc_arena *gc) { HKEY adapter_key; @@ -3986,7 +4043,7 @@ return first; } -static const struct panel_reg * +static struct panel_reg * get_panel_reg(struct gc_arena *gc) { LONG status; @@ -6586,12 +6643,11 @@ void tun_open_device(struct tuntap *tt, const char *dev_node, const char **device_guid, struct gc_arena *gc) { - const struct tap_reg *tap_reg = get_tap_reg(gc); - const struct panel_reg *panel_reg = get_panel_reg(gc); - const struct device_instance_id_interface *device_instance_id_interface = get_device_instance_id_interface(gc); - uint8_t actual_buffer[256]; + struct tap_reg *tap_reg = get_tap_reg(gc); + struct panel_reg *panel_reg = get_panel_reg(gc); + struct device_instance_id_interface *device_instance_id_interface = get_device_instance_id_interface(gc); - at_least_one_tap_win(tap_reg); + uint8_t actual_buffer[256]; /* * Lookup the device name in the registry, using the --dev-node high level name. @@ -6622,6 +6678,7 @@ else { int device_number = 0; + bool adapter_created = false; /* Try opening all TAP devices until we find one available */ while (true) @@ -6637,7 +6694,24 @@ if (!*device_guid) { - msg(M_FATAL, "All %s adapters on this system are currently in use or disabled.", print_tun_backend_driver(tt->backend_driver)); + HANDLE h = tt->options.msg_channel; + if (adapter_created || (h && !do_create_adapter_service(h, tt->backend_driver))) + { + msg(M_FATAL, "All %s adapters on this system are currently in use or disabled.", print_tun_backend_driver(tt->backend_driver)); + } + else + { + adapter_created = true; + + /* we have created a new adapter so we must reinitialize adapters structs */ + tap_reg = get_tap_reg(gc); + panel_reg = get_panel_reg(gc); + device_instance_id_interface = get_device_instance_id_interface(gc); + + device_number = 0; + + continue; + } } if (tt->backend_driver != windows_driver) diff --git a/src/openvpnserv/common.c b/src/openvpnserv/common.c index 4a11e6c..198835e 100644 --- a/src/openvpnserv/common.c +++ b/src/openvpnserv/common.c @@ -96,6 +96,14 @@ goto out; } + swprintf(default_value, _countof(default_value), L"%ls\\bin", install_path); + error = GetRegString(key, L"bin_dir", s->bin_dir, sizeof(s->bin_dir), + default_value); + if (error != ERROR_SUCCESS) + { + goto out; + } + error = GetRegString(key, L"config_ext", s->ext_string, sizeof(s->ext_string), L".ovpn"); if (error != ERROR_SUCCESS) diff --git a/src/openvpnserv/interactive.c b/src/openvpnserv/interactive.c index f06d386..b1d71d4 100644 --- a/src/openvpnserv/interactive.c +++ b/src/openvpnserv/interactive.c @@ -125,6 +125,7 @@ register_ring_buffers_message_t rrb; set_mtu_message_t mtu; wins_cfg_message_t wins; + create_adapter_message_t create_adapter; } pipe_message_t; typedef struct { @@ -3107,6 +3108,45 @@ return err; } +static DWORD +HandleCreateAdapterMessage(const create_adapter_message_t *msg) +{ + const WCHAR *hwid; + + switch (msg->adapter_type) + { + case ADAPTER_TYPE_DCO: + hwid = L"ovpn-dco"; + break; + + case ADAPTER_TYPE_TAP: + hwid = L"root\\tap0901"; + break; + + case ADAPTER_TYPE_WINTUN: + hwid = L"wintun"; + break; + + default: + return ERROR_INVALID_PARAMETER; + } + + WCHAR cmd[MAX_PATH]; + WCHAR args[MAX_PATH]; + + if (swprintf_s(cmd, _countof(cmd), L"%s\\tapctl.exe", settings.bin_dir) < 0) + { + return ERROR_BUFFER_OVERFLOW; + } + + if (swprintf_s(args, _countof(args), L"tapctl create --hwid %s", hwid) < 0) + { + return ERROR_BUFFER_OVERFLOW; + } + + return ExecCommand(cmd, args, 10000); +} + static VOID HandleMessage(HANDLE pipe, PPROCESS_INFORMATION proc_info, DWORD bytes, DWORD count, LPHANDLE events, undo_lists_t *lists) @@ -3206,6 +3246,14 @@ } break; + case msg_create_adapter: + if (msg.header.size == sizeof(msg.create_adapter)) + { + ack.error_number = HandleCreateAdapterMessage(&msg.create_adapter); + } + break; + + default: ack.error_number = ERROR_MESSAGE_TYPE; MsgToEventLog(MSG_FLAGS_ERROR, L"Unknown message type %d", msg.header.type); diff --git a/src/openvpnserv/service.h b/src/openvpnserv/service.h index cbe213b..cebc67f 100644 --- a/src/openvpnserv/service.h +++ b/src/openvpnserv/service.h @@ -63,6 +63,7 @@ typedef struct { WCHAR exe_path[MAX_PATH]; WCHAR config_dir[MAX_PATH]; + WCHAR bin_dir[MAX_PATH]; WCHAR ext_string[16]; WCHAR log_dir[MAX_PATH]; WCHAR ovpn_admin_group[MAX_NAME]; -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/943?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I621d44ec6b0facc524875c15ddfd11ec47b06c15 Gerrit-Change-Number: 943 Gerrit-PatchSet: 1 Gerrit-Owner: stipa <lstipa...@gmail.com> Gerrit-Reviewer: flichtenheld <fr...@lichtenheld.com> Gerrit-Reviewer: plaisthos <arne-open...@rfc2549.org> Gerrit-CC: openvpn-devel <openvpn-devel@lists.sourceforge.net> Gerrit-Attention: plaisthos <arne-open...@rfc2549.org> Gerrit-Attention: flichtenheld <fr...@lichtenheld.com> Gerrit-MessageType: newchange
_______________________________________________ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel