[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openvpn-devel
Subject:    Re: [Openvpn-devel] [PATCH v5 5/7] wintun: interactive service support
From:       Simon Rozman <simon () rozman ! si>
Date:       2019-12-17 13:17:37
Message-ID: 99D61A626FDA8A4B90A270669121BE10D05C945E () PLANJAVA ! amebis ! doma
[Download RAW message or body]

Definitely an ack. We need this for Wintun and to drop that SYSTEM token
hack.

Acked-by: Simon Rozman <simon@rozman.si> 

Best regards,
Simon

> -----Original Message-----
> From: Lev Stipakov <lstipakov@gmail.com>
> Sent: Tuesday, December 17, 2019 1:51 PM
> To: openvpn-devel@lists.sourceforge.net
> Cc: Lev Stipakov <lev@openvpn.net>
> Subject: [Openvpn-devel] [PATCH v5 5/7] wintun: interactive service
> support
> 
> From: Lev Stipakov <lev@openvpn.net>
> 
> Wintun requires ring buffers registration to be performed by privileged
> process. In order to use openvpn with wintun by non-Administrator, we
> need to use interactive service and shared memory to register buffers.
> 
> Openvpn process creates memory mapping object and event for send and
> receive ring and passes handles to interactive service. There handles
> are duplicated and memory mapped object is mapped into the address space
> of service process.
> Then address of mapped view and event handle is passed to wintun kernel
> driver.
> 
> After interactive service preformed registration, openvpn process maps
> memory mapped object into own address space. Thus mapped views in
> openvpn and service process represent the same memory region.
> 
> Signed-off-by: Lev Stipakov <lev@openvpn.net>
> ---
> 
>  While v2 has been ACKed, it had to be rebased on  top of previous patch
> in series, which required some  manual work.
> 
>  v5:
>   - rebased on top of [PATCH v8 4/7] wintun: ring buffers based I/O
>     (fixed struct tun_ring layout and made DeviceIoControl result check
> more robust)
> 
>  v4:
>   - rebased on top of [PATCH v5 4/7] "wintun: ring buffers based I/O"
> 
>  v3:
>   - rebased on top of [PATCH v4 4/7] "wintun: ring buffers based I/O"
>   - added doxygen comments to ring_buffer.h
> 
>  v2:
>   - rebased on top of master
> 
>  include/openvpn-msg.h                       |  10 ++
>  src/openvpn/Makefile.am                     |   2 +-
>  src/openvpn/openvpn.vcxproj                 |   2 +
>  src/openvpn/openvpn.vcxproj.filters         |   8 +-
>  src/openvpn/ring_buffer.c                   |  56 ++++++++
>  src/openvpn/ring_buffer.h                   | 104 +++++++++++++++
>  src/openvpn/tun.c                           |  82 ++++++++++--
>  src/openvpn/tun.h                           |   3 +
>  src/openvpn/win32.c                         |  27 ----
>  src/openvpn/win32.h                         |  46 -------
>  src/openvpnserv/Makefile.am                 |   3 +-
>  src/openvpnserv/interactive.c               | 141 +++++++++++++++++++-
>  src/openvpnserv/openvpnserv.vcxproj         |   2 +
>  src/openvpnserv/openvpnserv.vcxproj.filters |   6 +
>  14 files changed, 399 insertions(+), 93 deletions(-)  create mode
> 100644 src/openvpn/ring_buffer.c  create mode 100644
> src/openvpn/ring_buffer.h
> 
> diff --git a/include/openvpn-msg.h b/include/openvpn-msg.h index
> 66177a21..3ed62069 100644
> --- a/include/openvpn-msg.h
> +++ b/include/openvpn-msg.h
> @@ -39,6 +39,7 @@ typedef enum {
>      msg_del_block_dns,
>      msg_register_dns,
>      msg_enable_dhcp,
> +    msg_register_ring_buffers
>  } message_type_t;
> 
>  typedef struct {
> @@ -117,4 +118,13 @@ typedef struct {
>      interface_t iface;
>  } enable_dhcp_message_t;
> 
> +typedef struct {
> +    message_header_t header;
> +    HANDLE device;
> +    HANDLE send_ring_handle;
> +    HANDLE receive_ring_handle;
> +    HANDLE send_tail_moved;
> +    HANDLE receive_tail_moved;
> +} register_ring_buffers_message_t;
> +
>  #endif /* ifndef OPENVPN_MSG_H_ */
> diff --git a/src/openvpn/Makefile.am b/src/openvpn/Makefile.am index
> a091ffc2..d1bb99c2 100644
> --- a/src/openvpn/Makefile.am
> +++ b/src/openvpn/Makefile.am
> @@ -138,6 +138,6 @@ openvpn_LDADD = \
>  	$(OPTIONAL_SYSTEMD_LIBS) \
>  	$(OPTIONAL_DL_LIBS)
>  if WIN32
> -openvpn_SOURCES += openvpn_win32_resources.rc block_dns.c block_dns.h
> +openvpn_SOURCES += openvpn_win32_resources.rc block_dns.c block_dns.h
> +ring_buffer.c ring_buffer.h
>  openvpn_LDADD += -lgdi32 -lws2_32 -lwininet -lcrypt32 -liphlpapi -
> lwinmm -lfwpuclnt -lrpcrt4 -lncrypt -lsetupapi  endif diff --git
> a/src/openvpn/openvpn.vcxproj b/src/openvpn/openvpn.vcxproj index
> 7446d97d..614d720a 100644
> --- a/src/openvpn/openvpn.vcxproj
> +++ b/src/openvpn/openvpn.vcxproj
> @@ -181,6 +181,7 @@
>      <ClCompile Include="ps.c" />
>      <ClCompile Include="push.c" />
>      <ClCompile Include="reliable.c" />
> +    <ClCompile Include="ring_buffer.c" />
>      <ClCompile Include="route.c" />
>      <ClCompile Include="run_command.c" />
>      <ClCompile Include="schedule.c" />
> @@ -265,6 +266,7 @@
>      <ClInclude Include="push.h" />
>      <ClInclude Include="pushlist.h" />
>      <ClInclude Include="reliable.h" />
> +    <ClInclude Include="ring_buffer.h" />
>      <ClInclude Include="route.h" />
>      <ClInclude Include="run_command.h" />
>      <ClInclude Include="schedule.h" />
> diff --git a/src/openvpn/openvpn.vcxproj.filters
> b/src/openvpn/openvpn.vcxproj.filters
> index 653e892c..41e62d14 100644
> --- a/src/openvpn/openvpn.vcxproj.filters
> +++ b/src/openvpn/openvpn.vcxproj.filters
> @@ -240,6 +240,9 @@
>      <ClCompile Include="vlan.c">
>        <Filter>Source Files</Filter>
>      </ClCompile>
> +    <ClCompile Include="ring_buffer.c">
> +      <Filter>Source Files</Filter>
> +    </ClCompile>
>    </ItemGroup>
>    <ItemGroup>
>      <ClInclude Include="base64.h">
> @@ -500,10 +503,13 @@
>      <ClInclude Include="vlan.h">
>        <Filter>Header Files</Filter>
>      </ClInclude>
> +    <ClInclude Include="ring_buffer.h">
> +      <Filter>Header Files</Filter>
> +    </ClInclude>
>    </ItemGroup>
>    <ItemGroup>
>      <ResourceCompile Include="openvpn_win32_resources.rc">
>        <Filter>Resource Files</Filter>
>      </ResourceCompile>
>    </ItemGroup>
> -</Project>
> \ No newline at end of file
> +</Project>
> diff --git a/src/openvpn/ring_buffer.c b/src/openvpn/ring_buffer.c new
> file mode 100644 index 00000000..8c81dc46
> --- /dev/null
> +++ b/src/openvpn/ring_buffer.c
> @@ -0,0 +1,56 @@
> +/*
> + *  OpenVPN -- An application to securely tunnel IP networks
> + *             over a single UDP port, with support for SSL/TLS-based
> + *             session authentication and key exchange,
> + *             packet encryption, packet authentication, and
> + *             packet compression.
> + *
> + *  Copyright (C) 2002-2019 OpenVPN Inc <sales@openvpn.net>
> + *                2019 Lev Stipakov <lev@openvpn.net>
> + *
> + *  This program is free software; you can redistribute it and/or
> +modify
> + *  it under the terms of the GNU General Public License version 2
> + *  as published by the Free Software Foundation.
> + *
> + *  This program is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> +along
> + *  with this program; if not, write to the Free Software Foundation,
> +Inc.,
> + *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#include "ring_buffer.h"
> +
> +#ifdef _WIN32
> +
> +bool
> +register_ring_buffers(HANDLE device,
> +                      struct tun_ring *send_ring,
> +                      struct tun_ring *receive_ring,
> +                      HANDLE send_tail_moved,
> +                      HANDLE receive_tail_moved) {
> +    struct tun_register_rings rr;
> +    BOOL res;
> +    DWORD bytes_returned;
> +
> +    ZeroMemory(&rr, sizeof(rr));
> +
> +    rr.send.ring = send_ring;
> +    rr.send.ring_size = sizeof(struct tun_ring);
> +    rr.send.tail_moved = send_tail_moved;
> +
> +    rr.receive.ring = receive_ring;
> +    rr.receive.ring_size = sizeof(struct tun_ring);
> +    rr.receive.tail_moved = receive_tail_moved;
> +
> +    res = DeviceIoControl(device, TUN_IOCTL_REGISTER_RINGS, &rr,
> sizeof(rr),
> +                          NULL, 0, &bytes_returned, NULL);
> +
> +    return res != FALSE;
> +}
> +
> +#endif /* ifdef _WIN32 */
> \ No newline at end of file
> diff --git a/src/openvpn/ring_buffer.h b/src/openvpn/ring_buffer.h new
> file mode 100644 index 00000000..3522c984
> --- /dev/null
> +++ b/src/openvpn/ring_buffer.h
> @@ -0,0 +1,104 @@
> +/*
> + *  OpenVPN -- An application to securely tunnel IP networks
> + *             over a single UDP port, with support for SSL/TLS-based
> + *             session authentication and key exchange,
> + *             packet encryption, packet authentication, and
> + *             packet compression.
> + *
> + *  Copyright (C) 2002-2019 OpenVPN Inc <sales@openvpn.net>
> + *                2019 Lev Stipakov <lev@openvpn.net>
> + *
> + *  This program is free software; you can redistribute it and/or
> +modify
> + *  it under the terms of the GNU General Public License version 2
> + *  as published by the Free Software Foundation.
> + *
> + *  This program is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> +along
> + *  with this program; if not, write to the Free Software Foundation,
> +Inc.,
> + *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#ifdef _WIN32
> +#ifndef OPENVPN_RING_BUFFER_H
> +#define OPENVPN_RING_BUFFER_H
> +
> +#include <windows.h>
> +#include <winioctl.h>
> +
> +#include <stdint.h>
> +#include <stdbool.h>
> +
> +/*
> + * Values below are taken from Wireguard Windows client
> + *
> +https://github.com/WireGuard/wireguard-go/blob/master/tun/wintun/ring_w
> +indows.go#L14
> + */
> +#define WINTUN_RING_CAPACITY        0x800000
> +#define WINTUN_RING_TRAILING_BYTES  0x10000
> +#define WINTUN_MAX_PACKET_SIZE      0xffff
> +#define WINTUN_PACKET_ALIGN         4
> +
> +#define TUN_IOCTL_REGISTER_RINGS CTL_CODE(51820U, 0x970U,
> +METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
> +
> +/**
> + * Wintun ring buffer
> + * See https://github.com/WireGuard/wintun#ring-layout
> + */
> +struct tun_ring
> +{
> +    volatile ULONG head;
> +    volatile ULONG tail;
> +    volatile LONG alertable;
> +    UCHAR data[WINTUN_RING_CAPACITY + WINTUN_RING_TRAILING_BYTES]; };
> +
> +/**
> + * Struct for ring buffers registration
> + * See https://github.com/WireGuard/wintun#registering-rings
> + */
> +struct tun_register_rings
> +{
> +    struct
> +    {
> +        ULONG ring_size;
> +        struct tun_ring *ring;
> +        HANDLE tail_moved;
> +    } send, receive;
> +};
> +
> +struct TUN_PACKET_HEADER
> +{
> +    uint32_t size;
> +};
> +
> +struct TUN_PACKET
> +{
> +    uint32_t size;
> +    UCHAR data[WINTUN_MAX_PACKET_SIZE]; };
> +
> +/**
> + * Registers ring buffers used to exchange data between
> + * userspace openvpn process and wintun kernel driver,
> + * see https://github.com/WireGuard/wintun#registering-rings
> + *
> + * @param device              handle to opened wintun device
> + * @param send_ring           pointer to send ring
> + * @param receive_ring        pointer to receive ring
> + * @param send_tail_moved     event set by wintun to signal openvpn
> + *                            that data is available for reading in
> send ring
> + * @param receive_tail_moved  event set by openvpn to signal wintun
> + *                            that data has been written to receive
> ring
> + * @return                    true if registration is successful, false
> otherwise
> + */
> +bool register_ring_buffers(HANDLE device,
> +                           struct tun_ring *send_ring,
> +                           struct tun_ring *receive_ring,
> +                           HANDLE send_tail_moved,
> +                           HANDLE receive_tail_moved);
> +
> +#endif /* ifndef OPENVPN_RING_BUFFER_H */ #endif /* ifdef _WIN32 */
> diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c index
> 3f66b216..77d84fb2 100644
> --- a/src/openvpn/tun.c
> +++ b/src/openvpn/tun.c
> @@ -779,17 +779,29 @@ init_tun_post(struct tuntap *tt,
> 
>      if (tt->wintun)
>      {
> -        tt->wintun_send_ring = malloc(sizeof(struct tun_ring));
> -        tt->wintun_receive_ring = malloc(sizeof(struct tun_ring));
> -        if ((tt->wintun_send_ring == NULL) || (tt->wintun_receive_ring
> == NULL))
> +        tt->wintun_send_ring_handle =
> CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
> +                                                        PAGE_READWRITE,
> +                                                        0,
> +                                                        sizeof(struct
> tun_ring),
> +                                                        NULL);
> +        tt->wintun_receive_ring_handle =
> CreateFileMapping(INVALID_HANDLE_VALUE,
> +                                                           NULL,
> +
> PAGE_READWRITE,
> +                                                           0,
> +
> sizeof(struct tun_ring),
> +                                                           NULL);
> +        if ((tt->wintun_send_ring_handle == NULL) ||
> + (tt->wintun_receive_ring_handle == NULL))
>          {
>              msg(M_FATAL, "Cannot allocate memory for ring buffer");
>          }
> -        ZeroMemory(tt->wintun_send_ring, sizeof(struct tun_ring));
> -        ZeroMemory(tt->wintun_receive_ring, sizeof(struct tun_ring));
> 
>          tt->rw_handle.read = CreateEvent(NULL, FALSE, FALSE, NULL);
>          tt->rw_handle.write = CreateEvent(NULL, FALSE, FALSE, NULL);
> +
> +        if ((tt->rw_handle.read == NULL) || (tt->rw_handle.write ==
> NULL))
> +        {
> +            msg(M_FATAL, "Cannot create events for ring buffer");
> +        }
>      }
>      else
>      {
> @@ -5604,6 +5616,44 @@ register_dns_service(const struct tuntap *tt)
>      gc_free(&gc);
>  }
> 
> +static void
> +service_register_ring_buffers(const struct tuntap *tt) {
> +    HANDLE msg_channel = tt->options.msg_channel;
> +    ack_message_t ack;
> +    struct gc_arena gc = gc_new();
> +
> +    register_ring_buffers_message_t msg = {
> +        .header = {
> +            msg_register_ring_buffers,
> +            sizeof(register_ring_buffers_message_t),
> +            0
> +        },
> +        .device = tt->hand,
> +        .send_ring_handle = tt->wintun_send_ring_handle,
> +        .receive_ring_handle = tt->wintun_receive_ring_handle,
> +        .send_tail_moved = tt->rw_handle.read,
> +        .receive_tail_moved = tt->rw_handle.write
> +    };
> +
> +    if (!send_msg_iservice(msg_channel, &msg, sizeof(msg), &ack,
> "Register ring buffers"))
> +    {
> +        gc_free(&gc);
> +        return;
> +    }
> +    else if (ack.error_number != NO_ERROR)
> +    {
> +        msg(M_FATAL, "Register ring buffers failed using service: %s
> [status=0x%x]",
> +            strerror_win32(ack.error_number, &gc), ack.error_number);
> +    }
> +    else
> +    {
> +        msg(M_INFO, "Ring buffers registered via service");
> +    }
> +
> +    gc_free(&gc);
> +}
> +
>  void
>  fork_register_dns_action(struct tuntap *tt)  { @@ -6198,9 +6248,20 @@
> open_tun(const char *dev, const char *dev_type, const char *dev_node,
> struct tun
> 
>      if (tt->wintun)
>      {
> +        tt->wintun_send_ring = (struct tun_ring *)MapViewOfFile(tt-
> >wintun_send_ring_handle,
> +
> FILE_MAP_ALL_ACCESS,
> +                                                                0,
> +                                                                0,
> +
> sizeof(struct tun_ring));
> +        tt->wintun_receive_ring = (struct tun_ring *)MapViewOfFile(tt-
> >wintun_receive_ring_handle,
> +
> FILE_MAP_ALL_ACCESS,
> +                                                                   0,
> +                                                                   0,
> +
> + sizeof(struct tun_ring));
> +
>          if (tt->options.msg_channel)
>          {
> -            /* TODO */
> +            service_register_ring_buffers(tt);
>          }
>          else
>          {
> @@ -6365,13 +6426,12 @@ close_tun(struct tuntap *tt, openvpn_net_ctx_t
> *ctx)
>      {
>          CloseHandle(tt->rw_handle.read);
>          CloseHandle(tt->rw_handle.write);
> +        UnmapViewOfFile(tt->wintun_send_ring);
> +        UnmapViewOfFile(tt->wintun_receive_ring);
> +        CloseHandle(tt->wintun_send_ring_handle);
> +        CloseHandle(tt->wintun_receive_ring_handle);
>      }
> 
> -    free(tt->wintun_receive_ring);
> -    free(tt->wintun_send_ring);
> -
> -    tt->wintun_receive_ring = NULL;
> -    tt->wintun_send_ring = NULL;
> 
>      clear_tuntap(tt);
>      free(tt);
> diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h index
> 10f687c5..b0b80d1a 100644
> --- a/src/openvpn/tun.h
> +++ b/src/openvpn/tun.h
> @@ -39,6 +39,7 @@
>  #include "proto.h"
>  #include "misc.h"
>  #include "networking.h"
> +#include "ring_buffer.h"
> 
>  #ifdef _WIN32
>  #define WINTUN_COMPONENT_ID "wintun"
> @@ -183,6 +184,8 @@ struct tuntap
>      bool wintun; /* true if wintun is used instead of tap-windows6 */
>      int standby_iter;
> 
> +    HANDLE wintun_send_ring_handle;
> +    HANDLE wintun_receive_ring_handle;
>      struct tun_ring *wintun_send_ring;
>      struct tun_ring *wintun_receive_ring;  #else  /* ifdef _WIN32 */
> diff --git a/src/openvpn/win32.c b/src/openvpn/win32.c index
> 24dae7d6..b2f2a19f 100644
> --- a/src/openvpn/win32.c
> +++ b/src/openvpn/win32.c
> @@ -1588,31 +1588,4 @@ impersonate_as_system()
>      return true;
>  }
> 
> -bool
> -register_ring_buffers(HANDLE device,
> -                      struct tun_ring* send_ring,
> -                      struct tun_ring* receive_ring,
> -                      HANDLE send_tail_moved,
> -                      HANDLE receive_tail_moved)
> -{
> -    struct tun_register_rings rr;
> -    BOOL res;
> -    DWORD bytes_returned;
> -
> -    ZeroMemory(&rr, sizeof(rr));
> -
> -    rr.send.ring = send_ring;
> -    rr.send.ring_size = sizeof(struct tun_ring);
> -    rr.send.tail_moved = send_tail_moved;
> -
> -    rr.receive.ring = receive_ring;
> -    rr.receive.ring_size = sizeof(struct tun_ring);
> -    rr.receive.tail_moved = receive_tail_moved;
> -
> -    res = DeviceIoControl(device, TUN_IOCTL_REGISTER_RINGS, &rr,
> sizeof(rr),
> -                          NULL, 0, &bytes_returned, NULL);
> -
> -    return res != FALSE;
> -}
> -
>  #endif /* ifdef _WIN32 */
> diff --git a/src/openvpn/win32.h b/src/openvpn/win32.h index
> 5fe95f47..4b508c56 100644
> --- a/src/openvpn/win32.h
> +++ b/src/openvpn/win32.h
> @@ -325,53 +325,7 @@ bool send_msg_iservice(HANDLE pipe, const void
> *data, size_t size,  int  openvpn_execve(const struct argv *a, const
> struct env_set *es, const unsigned int flags);
> 
> -/*
> - * Values below are taken from Wireguard Windows client
> - * https://github.com/WireGuard/wireguard-
> go/blob/master/tun/wintun/ring_windows.go#L14
> - */
> -#define WINTUN_RING_CAPACITY 0x800000
> -#define WINTUN_RING_TRAILING_BYTES 0x10000 -#define
> WINTUN_MAX_PACKET_SIZE 0xffff -#define WINTUN_PACKET_ALIGN 4
> -
> -struct tun_ring
> -{
> -    volatile ULONG head;
> -    volatile ULONG tail;
> -    volatile LONG alertable;
> -    UCHAR data[WINTUN_RING_CAPACITY + WINTUN_RING_TRAILING_BYTES];
> -};
> -
> -struct tun_register_rings
> -{
> -    struct
> -    {
> -        ULONG ring_size;
> -        struct tun_ring *ring;
> -        HANDLE tail_moved;
> -    } send, receive;
> -};
> -
> -struct TUN_PACKET_HEADER
> -{
> -    uint32_t size;
> -};
> -
> -struct TUN_PACKET
> -{
> -    uint32_t size;
> -    UCHAR data[WINTUN_MAX_PACKET_SIZE];
> -};
> -
> -#define TUN_IOCTL_REGISTER_RINGS CTL_CODE(51820U, 0x970U,
> METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
> -
>  bool impersonate_as_system();
> 
> -bool register_ring_buffers(HANDLE device,
> -                           struct tun_ring *send_ring,
> -                           struct tun_ring *receive_ring,
> -                           HANDLE send_tail_moved,
> -                           HANDLE receive_tail_moved);
> -
>  #endif /* ifndef OPENVPN_WIN32_H */
>  #endif /* ifdef _WIN32 */
> diff --git a/src/openvpnserv/Makefile.am b/src/openvpnserv/Makefile.am
> index bc65070b..f8d3319c 100644
> --- a/src/openvpnserv/Makefile.am
> +++ b/src/openvpnserv/Makefile.am
> @@ -36,4 +36,5 @@ openvpnserv_SOURCES = \
>  	service.c service.h \
>  	validate.c validate.h \
>  	$(top_srcdir)/src/openvpn/block_dns.c
> $(top_srcdir)/src/openvpn/block_dns.h \
> -	openvpnserv_resources.rc
> +	openvpnserv_resources.rc \
> +	$(top_srcdir)/src/openvpn/ring_buffer.c
> +$(top_srcdir)/src/openvpn/ring_buffer.h
> diff --git a/src/openvpnserv/interactive.c
> b/src/openvpnserv/interactive.c index 623c3ff7..6e72a141 100644
> --- a/src/openvpnserv/interactive.c
> +++ b/src/openvpnserv/interactive.c
> @@ -43,13 +43,15 @@
>  #include "openvpn-msg.h"
>  #include "validate.h"
>  #include "block_dns.h"
> +#include "ring_buffer.h"
> 
>  #define IO_TIMEOUT  2000 /*ms*/
> 
> -#define ERROR_OPENVPN_STARTUP  0x20000000
> -#define ERROR_STARTUP_DATA     0x20000001
> -#define ERROR_MESSAGE_DATA     0x20000002
> -#define ERROR_MESSAGE_TYPE     0x20000003
> +#define ERROR_OPENVPN_STARTUP        0x20000000
> +#define ERROR_STARTUP_DATA           0x20000001
> +#define ERROR_MESSAGE_DATA           0x20000002
> +#define ERROR_MESSAGE_TYPE           0x20000003
> +#define ERROR_REGISTER_RING_BUFFERS  0x20000004
> 
>  static SERVICE_STATUS_HANDLE service;
>  static SERVICE_STATUS status = { .dwServiceType =
> SERVICE_WIN32_SHARE_PROCESS }; @@ -58,6 +60,7 @@ static settings_t
> settings;  static HANDLE rdns_semaphore = NULL;  #define RDNS_TIMEOUT
> 600  /* seconds to wait for the semaphore */
> 
> +#define TUN_IOCTL_REGISTER_RINGS CTL_CODE(51820U, 0x970U,
> +METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
> 
>  openvpn_service_t interactive_service = {
>      interactive,
> @@ -100,6 +103,14 @@ typedef struct {
>      int metric_v6;
>  } block_dns_data_t;
> 
> +typedef struct {
> +    HANDLE send_ring_handle;
> +    HANDLE receive_ring_handle;
> +    HANDLE send_tail_moved;
> +    HANDLE receive_tail_moved;
> +    HANDLE device;
> +} ring_buffer_handles_t;
> +
> 
>  static DWORD
>  AddListItem(list_item_t **pfirst, LPVOID data) @@ -154,6 +165,26 @@
> CloseHandleEx(LPHANDLE handle)
>      return INVALID_HANDLE_VALUE;
>  }
> 
> +static HANDLE
> +OvpnUnmapViewOfFile(LPHANDLE handle)
> +{
> +    if (handle && *handle && *handle != INVALID_HANDLE_VALUE)
> +    {
> +        UnmapViewOfFile(*handle);
> +        *handle = INVALID_HANDLE_VALUE;
> +    }
> +    return INVALID_HANDLE_VALUE;
> +}
> +
> +static void
> +CloseRingBufferHandles(ring_buffer_handles_t *ring_buffer_handles) {
> +    CloseHandleEx(&ring_buffer_handles->device);
> +    CloseHandleEx(&ring_buffer_handles->receive_tail_moved);
> +    CloseHandleEx(&ring_buffer_handles->send_tail_moved);
> +    OvpnUnmapViewOfFile(&ring_buffer_handles->send_ring_handle);
> +    OvpnUnmapViewOfFile(&ring_buffer_handles->receive_ring_handle);
> +}
> 
>  static HANDLE
>  InitOverlapped(LPOVERLAPPED overlapped) @@ -1198,8 +1229,95 @@
> HandleEnableDHCPMessage(const enable_dhcp_message_t *dhcp)
>      return err;
>  }
> 
> +static DWORD
> +OvpnDuplicateHandle(HANDLE ovpn_proc, HANDLE orig_handle, HANDLE*
> +new_handle) {
> +    DWORD err = ERROR_SUCCESS;
> +
> +    if (!DuplicateHandle(ovpn_proc, orig_handle, GetCurrentProcess(),
> new_handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
> +    {
> +        err = GetLastError();
> +        MsgToEventLog(M_SYSERR, TEXT("Could not duplicate handle"));
> +        return err;
> +    }
> +
> +    return err;
> +}
> +
> +static DWORD
> +DuplicateAndMapRing(HANDLE ovpn_proc, HANDLE orig_handle, HANDLE
> +*new_handle, struct tun_ring **ring) {
> +    DWORD err = ERROR_SUCCESS;
> +
> +    err = OvpnDuplicateHandle(ovpn_proc, orig_handle, new_handle);
> +    if (err != ERROR_SUCCESS)
> +    {
> +        return err;
> +    }
> +    *ring = (struct tun_ring *)MapViewOfFile(*new_handle,
> FILE_MAP_ALL_ACCESS, 0, 0, sizeof(struct tun_ring));
> +    if (*ring == NULL)
> +    {
> +        err = GetLastError();
> +        MsgToEventLog(M_SYSERR, TEXT("Could not map shared memory"));
> +        return err;
> +    }
> +
> +    return err;
> +}
> +
> +static DWORD
> +HandleRegisterRingBuffers(const register_ring_buffers_message_t *rrb,
> HANDLE ovpn_proc,
> +                          ring_buffer_handles_t *ring_buffer_handles) {
> +    DWORD err = 0;
> +    struct tun_ring *send_ring;
> +    struct tun_ring *receive_ring;
> +
> +    CloseRingBufferHandles(ring_buffer_handles);
> +
> +    err = OvpnDuplicateHandle(ovpn_proc, rrb->device,
> &ring_buffer_handles->device);
> +    if (err != ERROR_SUCCESS)
> +    {
> +        return err;
> +    }
> +
> +    err = DuplicateAndMapRing(ovpn_proc, rrb->send_ring_handle,
> &ring_buffer_handles->send_ring_handle, &send_ring);
> +    if (err != ERROR_SUCCESS)
> +    {
> +        return err;
> +    }
> +
> +    err = DuplicateAndMapRing(ovpn_proc, rrb->receive_ring_handle,
> &ring_buffer_handles->receive_ring_handle, &receive_ring);
> +    if (err != ERROR_SUCCESS)
> +    {
> +        return err;
> +    }
> +
> +    err = OvpnDuplicateHandle(ovpn_proc, rrb->send_tail_moved,
> &ring_buffer_handles->send_tail_moved);
> +    if (err != ERROR_SUCCESS)
> +    {
> +        return err;
> +    }
> +
> +    err = OvpnDuplicateHandle(ovpn_proc, rrb->receive_tail_moved,
> &ring_buffer_handles->receive_tail_moved);
> +    if (err != ERROR_SUCCESS)
> +    {
> +        return err;
> +    }
> +
> +    if (!register_ring_buffers(ring_buffer_handles->device, send_ring,
> receive_ring,
> +                               ring_buffer_handles->send_tail_moved,
> ring_buffer_handles->receive_tail_moved))
> +    {
> +        MsgToEventLog(M_SYSERR, TEXT("Could not register ring
> buffers"));
> +        err = ERROR_REGISTER_RING_BUFFERS;
> +    }
> +
> +    return err;
> +}
> +
>  static VOID
> -HandleMessage(HANDLE pipe, DWORD bytes, DWORD count, LPHANDLE events,
> undo_lists_t *lists)
> +HandleMessage(HANDLE pipe, HANDLE ovpn_proc, ring_buffer_handles_t
> *ring_buffer_handles,
> +              DWORD bytes, DWORD count, LPHANDLE events, undo_lists_t
> +*lists)
>  {
>      DWORD read;
>      union {
> @@ -1210,6 +1328,7 @@ HandleMessage(HANDLE pipe, DWORD bytes, DWORD
> count, LPHANDLE events, undo_lists
>          block_dns_message_t block_dns;
>          dns_cfg_message_t dns;
>          enable_dhcp_message_t dhcp;
> +        register_ring_buffers_message_t rrb;
>      } msg;
>      ack_message_t ack = {
>          .header = {
> @@ -1277,6 +1396,13 @@ HandleMessage(HANDLE pipe, DWORD bytes, DWORD
> count, LPHANDLE events, undo_lists
>              }
>              break;
> 
> +        case msg_register_ring_buffers:
> +            if (msg.header.size == sizeof(msg.rrb))
> +            {
> +                ack.error_number = HandleRegisterRingBuffers(&msg.rrb,
> ovpn_proc, ring_buffer_handles);
> +            }
> +            break;
> +
>          default:
>              ack.error_number = ERROR_MESSAGE_TYPE;
>              MsgToEventLog(MSG_FLAGS_ERROR, TEXT("Unknown message type
> %d"), msg.header.type); @@ -1360,6 +1486,7 @@ RunOpenvpn(LPVOID p)
>      WCHAR *cmdline = NULL;
>      size_t cmdline_size;
>      undo_lists_t undo_lists;
> +    ring_buffer_handles_t ring_buffer_handles;
> 
>      SECURITY_ATTRIBUTES inheritable = {
>          .nLength = sizeof(inheritable), @@ -1380,6 +1507,7 @@
> RunOpenvpn(LPVOID p)
>      ZeroMemory(&startup_info, sizeof(startup_info));
>      ZeroMemory(&undo_lists, sizeof(undo_lists));
>      ZeroMemory(&proc_info, sizeof(proc_info));
> +    ZeroMemory(&ring_buffer_handles, sizeof(ring_buffer_handles));
> 
>      if (!GetStartupData(pipe, &sud))
>      {
> @@ -1611,7 +1739,7 @@ RunOpenvpn(LPVOID p)
>              break;
>          }
> 
> -        HandleMessage(ovpn_pipe, bytes, 1, &exit_event, &undo_lists);
> +        HandleMessage(ovpn_pipe, proc_info.hProcess,
> + &ring_buffer_handles, bytes, 1, &exit_event, &undo_lists);
>      }
> 
>      WaitForSingleObject(proc_info.hProcess, IO_TIMEOUT); @@ -1638,6
> +1766,7 @@ out:
>      free(cmdline);
>      DestroyEnvironmentBlock(user_env);
>      FreeStartupData(&sud);
> +    CloseRingBufferHandles(&ring_buffer_handles);
>      CloseHandleEx(&proc_info.hProcess);
>      CloseHandleEx(&proc_info.hThread);
>      CloseHandleEx(&stdin_read);
> diff --git a/src/openvpnserv/openvpnserv.vcxproj
> b/src/openvpnserv/openvpnserv.vcxproj
> index 7061b7b1..c5a34b87 100644
> --- a/src/openvpnserv/openvpnserv.vcxproj
> +++ b/src/openvpnserv/openvpnserv.vcxproj
> @@ -115,6 +115,7 @@
>      </Link>
>    </ItemDefinitionGroup>
>    <ItemGroup>
> +    <ClCompile Include="..\openvpn\ring_buffer.c" />
>      <ClCompile Include="automatic.c" />
>      <ClCompile Include="common.c" />
>      <ClCompile Include="interactive.c" /> @@ -123,6 +124,7 @@
>      <ClCompile Include="..\openvpn\block_dns.c" />
>    </ItemGroup>
>    <ItemGroup>
> +    <ClInclude Include="..\openvpn\ring_buffer.h" />
>      <ClInclude Include="service.h" />
>      <ClInclude Include="validate.h" />
>      <ClInclude Include="..\openvpn\block_dns.h" /> diff --git
> a/src/openvpnserv/openvpnserv.vcxproj.filters
> b/src/openvpnserv/openvpnserv.vcxproj.filters
> index 3ce9bb24..3cb14ef6 100644
> --- a/src/openvpnserv/openvpnserv.vcxproj.filters
> +++ b/src/openvpnserv/openvpnserv.vcxproj.filters
> @@ -33,6 +33,9 @@
>      <ClCompile Include="..\openvpn\block_dns.c">
>        <Filter>Source Files</Filter>
>      </ClCompile>
> +    <ClCompile Include="..\openvpn\ring_buffer.c">
> +      <Filter>Source Files</Filter>
> +    </ClCompile>
>    </ItemGroup>
>    <ItemGroup>
>      <ClInclude Include="service.h">
> @@ -44,6 +47,9 @@
>      <ClInclude Include="..\openvpn\block_dns.h">
>        <Filter>Header Files</Filter>
>      </ClInclude>
> +    <ClInclude Include="..\openvpn\ring_buffer.h">
> +      <Filter>Header Files</Filter>
> +    </ClInclude>
>    </ItemGroup>
>    <ItemGroup>
>      <ResourceCompile Include="openvpnserv_resources.rc">
> --
> 2.17.1
> 
> 
> 
> _______________________________________________
> Openvpn-devel mailing list
> Openvpn-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/openvpn-devel

["smime.p7s" (application/pkcs7-signature)]
[Attachment #4 (--===============7461155979468251849==)]


_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic