[Openvpn-devel,v1] dco_win: report per-peer ioctl failures instead of exiting

Message ID 20260918180507.26425-1-gert@greenie.muc.de
State New
Headers
Series [Openvpn-devel,v1] dco_win: report per-peer ioctl failures instead of exiting |

Commit Message

Gert Doering Sept. 18, 2026, 6:05 p.m. UTC
  From: Lev Stipakov <lev@openvpn.net>

Three per-peer operations end the process when their ioctl fails: MP_NEW_PEER,
NEW_KEY and SWAP_KEYS all report with M_ERR, which is M_FATAL. On a server that
means one client's failure disconnects every other client.

The shared code above them already recovers per instance: a failed MP_NEW_PEER
drops that client in multi.c, a failed SWAP_KEYS raises SIGUSR1 for that
instance in forward.c, and change 1835 restarts the instance on a failed
NEW_KEY. None of it runs on Windows, because the process is gone before the
error can be returned.

Report and return, which is what DEL_PEER, MP_SET_PEER and the iroute calls in
this same file already do. The remaining M_ERR uses here are interface-wide
setup, where failing hard is still right.

NEW_KEY failing is not hypothetical: the driver owns the keepalive timer and
expires peers itself, so a key install can arrive for a peer it has just
removed. Measured on a Windows DCO server under peer churn: 15 refused installs
across four runs, no process exit.

Signed-off-by: Lev Stipakov <lev@openvpn.net>
Acked-by: Gert Doering <gert@greenie.muc.de>
Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1920
Change-Id: Ie46934c0a8f04908cc277114ae491c100d368cb2
---

This change was reviewed on Gerrit and approved by at least one
developer. I request to merge it to master.

Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1920
This mail reflects revision 1 of this Change.

Acked-by according to Gerrit (reflected above):
Gert Doering <gert@greenie.muc.de>
  

Patch

diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c
index b3268bc..90cff8c 100644
--- a/src/openvpn/dco_win.c
+++ b/src/openvpn/dco_win.c
@@ -460,7 +460,8 @@ 
     if (!DeviceIoControl(dco->tt->hand, OVPN_IOCTL_MP_NEW_PEER, &newPeer, sizeof(newPeer), NULL, 0,
                          &bytesReturned, NULL))
     {
-        msg(M_ERR, "DeviceIoControl(OVPN_IOCTL_MP_NEW_PEER) failed");
+        msg(M_WARN | M_ERRNO, "DeviceIoControl(OVPN_IOCTL_MP_NEW_PEER) failed");
+        return -1;
     }
 
     return 0;
@@ -575,7 +576,7 @@ 
 
     if (!DeviceIoControl(dco->tt->hand, ioctl, buf, bufSize, NULL, 0, &bytes_returned, NULL))
     {
-        msg(M_ERR, "DeviceIoControl(OVPN_IOCTL_NEW_KEY) failed");
+        msg(M_WARN | M_ERRNO, "DeviceIoControl(OVPN_IOCTL_NEW_KEY) failed");
         return -1;
     }
     return 0;
@@ -609,7 +610,7 @@ 
     DWORD bytes_returned = 0;
     if (!DeviceIoControl(dco->tt->hand, ioctl, buf, len, NULL, 0, &bytes_returned, NULL))
     {
-        msg(M_ERR, "DeviceIoControl(OVPN_IOCTL_SWAP_KEYS) failed");
+        msg(M_WARN | M_ERRNO, "DeviceIoControl(OVPN_IOCTL_SWAP_KEYS) failed");
         return -1;
     }
     return 0;