The good news about the BSOD is that according to dump, it doesn't
seem to be related to the recent changes to the driver. The bad news
is that while I got dump, I don't quite understand yet what has
happened there, looks like the internal state somehow got corrupted
(I posted question to
https://community.osr.com/discussion/293594/bug-check-at-wdfobjectgettypedcontextworker/).
I was unable to reproduce it after that.

So I think we could proceed with --persist-tun support patch and
meanwhile I'll be hunting for that (and possible others) bug check.
While testing it yesterday, I found the case with --persist-tun and
TCP when the patch wasn't working, so there is V2.

ma 29. elok. 2022 klo 16.35 lstipa...@gmail.com kirjoitti:
>
> Let’s not merge it yet. I managed to get a BSOD with the new driver version, 
> which this patch is supposed to use. I haven’t seen those for a while, which 
> means that the previous driver version (0.7.6) is stable and new one (with 
> persist tun support) is not.
>
> We’ll get back to this patch when I’ll fix the driver.
>
> Lähetetty iPhonesta
>
> > Lev Stipakov <lstipa...@gmail.com> kirjoitti 29.8.2022 kello 14.51:
> >
> > From: Lev Stipakov <l...@openvpn.net>
> >
> > Since version 0.8.0, dco-win driver added support for
> > DEL_PEER command, which enabled --persist-tun
> > implementation on client side.
> >
> > Add real implementation for dco_del_peer on Windows,
> > which calls DEL_PEER, which clears peer state
> > on the driver without tearing tunnel down.
> >
> > When pulled options are changed on restart,
> > we need to close and reopen tun device. This
> > is not yes supported for dco-win, so we close
> > tun and trigger reconnect.
> >
> > Signed-off-by: Lev Stipakov <l...@openvpn.net>
> > ---
> > src/openvpn/dco.c          |  5 -----
> > src/openvpn/dco_win.c      | 29 ++++++++++++++----------
> > src/openvpn/dco_win.h      |  8 ++++---
> > src/openvpn/init.c         | 19 +++++++++++++---
> > src/openvpn/ovpn_dco_win.h |  1 +
> > src/openvpn/socket.c       | 45 ++++++++++++++++++++------------------
> > 6 files changed, 63 insertions(+), 44 deletions(-)
> >
> > diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c
> > index 78023eea..075820c3 100644
> > --- a/src/openvpn/dco.c
> > +++ b/src/openvpn/dco.c
> > @@ -233,11 +233,6 @@ dco_check_startup_option_conflict(int msglevel, const 
> > struct options *o)
> >         return false;
> >     }
> >
> > -    if (o->persist_tun)
> > -    {
> > -        msg(msglevel, "--persist-tun is not supported with ovpn-dco.");
> > -        return false;
> > -    }
> > #elif defined(TARGET_LINUX)
> >     /* if the device name is fixed, we need to check if an interface with 
> > this
> >      * name already exists. IF it does, it must be a DCO interface, 
> > otherwise
> > diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c
> > index a2030866..a7d6b55d 100644
> > --- a/src/openvpn/dco_win.c
> > +++ b/src/openvpn/dco_win.c
> > @@ -42,7 +42,7 @@
> > const IN_ADDR in4addr_any = { 0 };
> > #endif
> >
> > -static struct tuntap
> > +struct tuntap
> > create_dco_handle(const char *devname, struct gc_arena *gc)
> > {
> >     struct tuntap tt = { .windows_driver = WINDOWS_DRIVER_DCO };
> > @@ -157,10 +157,9 @@ dco_connect_wait(HANDLE handle, OVERLAPPED *ov, int 
> > timeout, volatile int *signa
> >     return -1;
> > }
> >
> > -struct tuntap
> > -dco_create_socket(struct addrinfo *remoteaddr, bool bind_local,
> > -                  struct addrinfo *bind, const char *devname,
> > -                  struct gc_arena *gc, int timeout,
> > +bool
> > +dco_create_socket(HANDLE handle, struct addrinfo *remoteaddr, bool 
> > bind_local,
> > +                  struct addrinfo *bind, int timeout,
> >                   volatile int *signal_received)
> > {
> >     msg(D_DCO_DEBUG, "%s", __func__);
> > @@ -232,10 +231,8 @@ dco_create_socket(struct addrinfo *remoteaddr, bool 
> > bind_local,
> >         ASSERT(0);
> >     }
> >
> > -    struct tuntap tt = create_dco_handle(devname, gc);
> > -
> >     OVERLAPPED ov = { 0 };
> > -    if (!DeviceIoControl(tt.hand, OVPN_IOCTL_NEW_PEER, &peer, 
> > sizeof(peer), NULL, 0, NULL, &ov))
> > +    if (!DeviceIoControl(handle, OVPN_IOCTL_NEW_PEER, &peer, sizeof(peer), 
> > NULL, 0, NULL, &ov))
> >     {
> >         DWORD err = GetLastError();
> >         if (err != ERROR_IO_PENDING)
> > @@ -244,13 +241,13 @@ dco_create_socket(struct addrinfo *remoteaddr, bool 
> > bind_local,
> >         }
> >         else
> >         {
> > -            if (dco_connect_wait(tt.hand, &ov, timeout, signal_received) < 
> > 0)
> > +            if (dco_connect_wait(handle, &ov, timeout, signal_received) < 
> > 0)
> >             {
> > -                close_tun_handle(&tt);
> > +                return false;
> >             }
> >         }
> >     }
> > -    return tt;
> > +    return true;
> > }
> >
> > int
> > @@ -265,7 +262,15 @@ dco_new_peer(dco_context_t *dco, unsigned int peerid, 
> > int sd,
> > int
> > dco_del_peer(dco_context_t *dco, unsigned int peerid)
> > {
> > -    msg(D_DCO_DEBUG, "%s: peer-id %d - not implemented", __func__, peerid);
> > +    msg(D_DCO_DEBUG, "%s: peer-id %d", __func__, peerid);
> > +
> > +    DWORD bytes_returned = 0;
> > +    if (!DeviceIoControl(dco->tt->hand, OVPN_IOCTL_DEL_PEER, NULL,
> > +                         0, NULL, 0, &bytes_returned, NULL))
> > +    {
> > +        msg(M_WARN | M_ERRNO, "DeviceIoControl(OVPN_IOCTL_DEL_PEER) 
> > failed");
> > +        return -1;
> > +    }
> >     return 0;
> > }
> >
> > diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h
> > index 348fc568..3a04e4f3 100644
> > --- a/src/openvpn/dco_win.h
> > +++ b/src/openvpn/dco_win.h
> > @@ -37,9 +37,11 @@ struct dco_context {
> > typedef struct dco_context dco_context_t;
> >
> > struct tuntap
> > -dco_create_socket(struct addrinfo *remoteaddr, bool bind_local,
> > -                  struct addrinfo *bind, const char *devname,
> > -                  struct gc_arena *gc, int timeout,
> > +create_dco_handle(const char *devname, struct gc_arena *gc);
> > +
> > +bool
> > +dco_create_socket(HANDLE handle, struct addrinfo *remoteaddr, bool 
> > bind_local,
> > +                  struct addrinfo *bind, int timeout,
> >                   volatile int *signal_received);
> >
> > void
> > diff --git a/src/openvpn/init.c b/src/openvpn/init.c
> > index 9917cefe..84d95c21 100644
> > --- a/src/openvpn/init.c
> > +++ b/src/openvpn/init.c
> > @@ -2183,10 +2183,23 @@ do_up(struct context *c, bool pulled_options, 
> > unsigned int option_types_found)
> >             {
> >                 /* if so, close tun, delete routes, then reinitialize tun 
> > and add routes */
> >                 msg(M_INFO, "NOTE: Pulled options changed on restart, will 
> > need to close and reopen TUN/TAP device.");
> > +
> > +                bool tt_dco_win = tuntap_is_dco_win(c->c1.tuntap);
> >                 do_close_tun(c, true);
> > -                management_sleep(1);
> > -                c->c2.did_open_tun = do_open_tun(c);
> > -                update_time();
> > +
> > +                if (tt_dco_win)
> > +                {
> > +                    msg(M_NONFATAL, "dco-win doesn't yet support reopening 
> > TUN device");
> > +                    /* prevent link_socket_close() from closing handle 
> > with WinSock API */
> > +                    c->c2.link_socket->sd = SOCKET_UNDEFINED;
> > +                    return false;
> > +                }
> > +                else
> > +                {
> > +                    management_sleep(1);
> > +                    c->c2.did_open_tun = do_open_tun(c);
> > +                    update_time();
> > +                }
> >             }
> >         }
> >
> > diff --git a/src/openvpn/ovpn_dco_win.h b/src/openvpn/ovpn_dco_win.h
> > index 1ebd51a7..cbbdf92e 100644
> > --- a/src/openvpn/ovpn_dco_win.h
> > +++ b/src/openvpn/ovpn_dco_win.h
> > @@ -106,3 +106,4 @@ typedef struct _OVPN_SET_PEER {
> > #define OVPN_IOCTL_SWAP_KEYS    CTL_CODE(FILE_DEVICE_UNKNOWN, 4, 
> > METHOD_BUFFERED, FILE_ANY_ACCESS)
> > #define OVPN_IOCTL_SET_PEER     CTL_CODE(FILE_DEVICE_UNKNOWN, 5, 
> > METHOD_BUFFERED, FILE_ANY_ACCESS)
> > #define OVPN_IOCTL_START_VPN    CTL_CODE(FILE_DEVICE_UNKNOWN, 6, 
> > METHOD_BUFFERED, FILE_ANY_ACCESS)
> > +#define OVPN_IOCTL_DEL_PEER     CTL_CODE(FILE_DEVICE_UNKNOWN, 7, 
> > METHOD_BUFFERED, FILE_ANY_ACCESS)
> > diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c
> > index 4e29327b..f2bb3d69 100644
> > --- a/src/openvpn/socket.c
> > +++ b/src/openvpn/socket.c
> > @@ -2128,23 +2128,29 @@ static void
> > create_socket_dco_win(struct context *c, struct link_socket *sock,
> >                       volatile int *signal_received)
> > {
> > -    struct tuntap *tt;
> > -    /* In this case persist-tun is enabled, which we don't support yet */
> > -    ASSERT(!c->c1.tuntap);
> > -
> > -    ALLOC_OBJ(tt, struct tuntap);
> > -
> > -    *tt = dco_create_socket(sock->info.lsa->current_remote,
> > -                            sock->bind_local,
> > -                            sock->info.lsa->bind_local,
> > -                            c->options.dev_node,
> > -                            &c->gc,
> > -                            
> > get_server_poll_remaining_time(sock->server_poll_timeout),
> > -                            signal_received);
> > -
> > -    /* This state is used by signal handler which does teardown,
> > -     * so it has to be set before return */
> > -    c->c1.tuntap = tt;
> > +    if (!c->c1.tuntap)
> > +    {
> > +        struct tuntap *tt;
> > +        ALLOC_OBJ(tt, struct tuntap);
> > +
> > +        *tt = create_dco_handle(c->options.dev_node, &c->gc);
> > +
> > +        /* Ensure we can "safely" cast the handle to a socket */
> > +        static_assert(sizeof(sock->sd) == sizeof(tt->hand), "HANDLE and 
> > SOCKET size differs");
> > +
> > +        c->c1.tuntap = tt;
> > +    }
> > +
> > +    bool res = dco_create_socket(c->c1.tuntap->hand,
> > +                                 sock->info.lsa->current_remote,
> > +                                 sock->bind_local, 
> > sock->info.lsa->bind_local,
> > +                                 
> > get_server_poll_remaining_time(sock->server_poll_timeout),
> > +                                 signal_received);
> > +    if (!res)
> > +    {
> > +        close_tun_handle(c->c1.tuntap);
> > +    }
> > +
> >     sock->info.dco_installed = true;
> >
> >     if (*signal_received)
> > @@ -2152,10 +2158,7 @@ create_socket_dco_win(struct context *c, struct 
> > link_socket *sock,
> >         return;
> >     }
> >
> > -    /* Ensure we can "safely" cast the handle to a socket */
> > -    static_assert(sizeof(sock->sd) == sizeof(tt->hand), "HANDLE and SOCKET 
> > size differs");
> > -    sock->sd = (SOCKET)tt->hand;
> > -
> > +    sock->sd = (SOCKET)c->c1.tuntap->hand;
> >     linksock_print_addr(sock);
> > }
> > #endif /* if defined(_WIN32) */
> > --
> > 2.23.0.windows.1
> >



-- 
-Lev


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

Reply via email to