Hi,

I'm not sure I must post this patch here. It corrects a strange behavior of openvpn and its plugin openvpn-down-root upon some restart occasion :

On the client side, openvpn fails and quit after failure of its plugin when the server is restarted. This is quite annoying in large VPN, requiring to "start" again the openvpn process on all clients everytime you do a "restart" of the vpn server node.

These are the logs (in verbose level 7):

...
PLUGIN_CALL: POST /usr/lib/openvpn/openvpn-down-root.so/PLUGIN_UP status=1
PLUGIN_CALL: plugin function PLUGIN_UP failed with status 1: /usr/lib/openvpn/openvpn-down-root.so
ERROR: up/down plugin call failed
Exiting
DOWN-ROOT: BACKGROUND: received command code: 1
DOWN-ROOT: BACKGROUND: EXIT


I tracked down the problem in the plugin, right in the function openvpn_plugin_func_v1, it seemed to me that the case

(type == OPENVPN_PLUGIN_UP && context->foreground_fd >= 0)

wasn't handled and thus, at the end of this function, this special case triggers OPENVPN_PLUGIN_FUNC_ERROR which in turn will end up exiting openvpn.

This special case is only triggered on restart : the condition
(type == OPENVPN_PLUGIN_UP) is true at start and is used to fork a process (with root perms) that will wait for openvpn signal to launch it's command.

context->foreground_fd is set to the communication socket between the forked process and openvpn. This is "-1" when no process have been created BUT is >= 0 when it has been created.

My patch handles the special case : (type == OPENVPN_PLUGIN_UP && context->foreground_fd >= 0) which occurs at restart condition : forked process and communication socket are already present, but PLUGIN_UP is called.

My patch will test that the process is still valid by sending a "ping command", and return that all is ok if process answered correctly to the ping.

I'm not a confirmed developper, so this patch needs review.

Hope this will help...

(The patch is the result of a "svn diff" from the openvpn root directory)

Valentin LAB

Index: plugin/down-root/down-root.c
===================================================================
--- plugin/down-root/down-root.c	(revision 1820)
+++ plugin/down-root/down-root.c	(working copy)
@@ -44,12 +44,14 @@
 /* Command codes for foreground -> background communication */
 #define COMMAND_RUN_SCRIPT 0
 #define COMMAND_EXIT       1
+#define COMMAND_PING       2

 /* Response codes for background -> foreground communication */
 #define RESPONSE_INIT_SUCCEEDED   10
 #define RESPONSE_INIT_FAILED      11
 #define RESPONSE_SCRIPT_SUCCEEDED 12
 #define RESPONSE_SCRIPT_FAILED    13
+#define RESPONSE_PING_REQUEST     14

 /* Background process function */
 static void down_root_server (const int fd, char *command, const char *argv[], const char *envp[], const int verb);
@@ -386,6 +388,28 @@
 	  return 0; /* NOTREACHED */
 	}
     }
+  else if (type == OPENVPN_PLUGIN_UP && context->foreground_fd >= 0) /* no need to fork a second process */
+    {
+
+      /* Check process communication */      
+
+      if (send_control (context->foreground_fd, COMMAND_PING) == -1)
+	{
+	  fprintf (stderr, "DOWN-ROOT: Error sending ping request signal to background process\n");
+	}
+      else
+	{
+	  const int status = recv_control (context->foreground_fd);
+	  if (status == RESPONSE_PING_REQUEST) 
+	    {
+	      return OPENVPN_PLUGIN_FUNC_SUCCESS;
+	    }
+	  else
+	    {
+	      fprintf (stderr, "DOWN-ROOT: Error receiving ping reception confirmation from background process\n");
+	    }
+	}
+    }
   else if (type == OPENVPN_PLUGIN_DOWN && context->foreground_fd >= 0)
     {
       if (send_control (context->foreground_fd, COMMAND_RUN_SCRIPT) == -1)
@@ -401,6 +425,7 @@
 	    fprintf (stderr, "DOWN-ROOT: Error receiving script execution confirmation from background process\n");
 	}
     }
+  
   return OPENVPN_PLUGIN_FUNC_ERROR;
 }

@@ -525,6 +550,17 @@
 	    }
 	  break;

+	case COMMAND_PING: /* allows to check if process is listening */
+
+	  if (send_control (fd, RESPONSE_PING_REQUEST) == -1)
+	    {
+	      fprintf (stderr, "DOWN-ROOT: BACKGROUND: write error on response socket [4]\n");
+	      goto done;
+	    }
+
+	  break;
+
+
 	case COMMAND_EXIT:
 	  goto done;

Reply via email to