]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Attempt at rational signal handling when in the
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Mon, 13 Nov 2006 09:31:40 +0000 (09:31 +0000)
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Mon, 13 Nov 2006 09:31:40 +0000 (09:31 +0000)
management hold state.

During management hold, ignore SIGUSR1/SIGHUP signals
thrown with the "signal" command.

Also, "signal" command will now apply remapping as
specified with the --remap-usr1 option.

When a signal entered using the "signal" command from a management
hold is ignored, output:

>HOLD:Waiting for hold release

git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@1458 e7ae566f-a301-0410-adde-c780ea21d3b5

init.c
manage.c
manage.h
openvpn.c

diff --git a/init.c b/init.c
index 2eb18962a4be0fa81ee14c894c78cf273be14263..244f03cfa7f7f4cc5c13cf1e9622ba6098edd9c3 100644 (file)
--- a/init.c
+++ b/init.c
@@ -1225,6 +1225,7 @@ socket_restart_pause (struct context *c)
     sec = c->persist.restart_sleep_seconds;
   c->persist.restart_sleep_seconds = 0;
 
+  /* do managment hold on context restart, i.e. second, third, fourth, etc. initialization */
   if (do_hold (NULL))
     sec = 0;
 
@@ -1244,7 +1245,7 @@ do_startup_pause (struct context *c)
   if (!c->first_time)
     socket_restart_pause (c);
   else
-    do_hold (NULL);
+    do_hold (NULL); /* do management hold on first context initialization */
 }
 
 /*
@@ -2456,7 +2457,8 @@ open_management (struct context *c)
                               c->options.management_state_buffer_size,
                               c->options.management_hold,
                               c->options.management_client,
-                              c->options.management_write_peer_info_file))
+                              c->options.management_write_peer_info_file,
+                              c->options.remap_sigusr1))
            {
              management_set_state (management,
                                    OPENVPN_STATE_CONNECTING,
@@ -2465,7 +2467,7 @@ open_management (struct context *c)
                                    (in_addr_t)0);
            }
 
-         /* possible wait */
+         /* initial management hold, called early, before first context initialization */
          do_hold (c);
          if (IS_SIG (c))
            {
index 1c28485c2eb6b46e0714863029b6c566c81e2387..993afa220906b94debf7a2d437f3acf6f7071efb 100644 (file)
--- a/manage.c
+++ b/manage.c
@@ -277,14 +277,49 @@ virtual_output_callback_func (void *arg, const unsigned int flags, const char *s
     }
 }
 
+/*
+ * Given a signal, return the signal with possible remapping applied,
+ * or -1 if the signal should be ignored.
+ */
+static int
+man_mod_signal (const struct management *man, const int signum)
+{
+  const unsigned int flags = man->settings.mansig;
+  int s = signum;
+  if (s == SIGUSR1)
+    {
+      if (flags & MANSIG_MAP_USR1_TO_HUP)
+       s = SIGHUP;
+      if (flags & MANSIG_MAP_USR1_TO_TERM)
+       s = SIGTERM;
+    }
+  if (flags & MANSIG_IGNORE_USR1_HUP)
+    {
+      if (s == SIGHUP || s == SIGUSR1)
+       s = -1;
+    }
+  return s;
+}
+
 static void
 man_signal (struct management *man, const char *name)
 {
   const int sig = parse_signal (name);
   if (sig >= 0)
     {
-      throw_signal (sig);
-      msg (M_CLIENT, "SUCCESS: signal %s thrown", signal_name (sig, true));
+      const int sig_mod = man_mod_signal (man, sig);
+      if (sig_mod >= 0)
+       {
+         throw_signal (sig_mod);
+         msg (M_CLIENT, "SUCCESS: signal %s thrown", signal_name (sig_mod, true));
+       }
+      else
+       {
+         if (man->persist.special_state_msg)
+           msg (M_CLIENT, "%s", man->persist.special_state_msg);
+         else
+           msg (M_CLIENT, "ERROR: signal '%s' is currently ignored", name);
+       }
     }
   else
     {
@@ -1276,7 +1311,8 @@ man_settings_init (struct man_settings *ms,
                   const int state_buffer_size,
                   const bool hold,
                   const bool connect_as_client,
-                  const char *write_peer_info_file)
+                  const char *write_peer_info_file,
+                  const int remap_sigusr1)
 {
   if (!ms->defined)
     {
@@ -1340,6 +1376,14 @@ man_settings_init (struct man_settings *ms,
       ms->echo_buffer_size = echo_buffer_size;
       ms->state_buffer_size = state_buffer_size;
 
+      /*
+       * Set remap sigusr1 flags
+       */
+      if (remap_sigusr1 == SIGHUP)
+       ms->mansig |= MANSIG_MAP_USR1_TO_HUP;
+      else if (remap_sigusr1 == SIGTERM)
+       ms->mansig |= MANSIG_MAP_USR1_TO_TERM;
+
       ms->defined = true;
     }
 }
@@ -1440,7 +1484,8 @@ management_open (struct management *man,
                 const int state_buffer_size,
                 const bool hold,
                 const bool connect_as_client,
-                const char *write_peer_info_file)
+                const char *write_peer_info_file,
+                const int remap_sigusr1)
 {
   bool ret = false;
 
@@ -1459,7 +1504,8 @@ management_open (struct management *man,
                     state_buffer_size,
                     hold,
                     connect_as_client,
-                    write_peer_info_file);
+                    write_peer_info_file,
+                    remap_sigusr1);
 
   /*
    * The log is initially sized to MANAGEMENT_LOG_HISTORY_INITIAL_SIZE,
@@ -2052,6 +2098,7 @@ management_hold (struct management *man)
 
       man->persist.standalone_disabled = false; /* This is so M_CLIENT messages will be correctly passed through msg() */
       man->persist.special_state_msg = NULL;
+      man->settings.mansig |= MANSIG_IGNORE_USR1_HUP;
 
       man_wait_for_client_connection (man, &signal_received, 0, MWCC_HOLD_WAIT);
 
@@ -2072,6 +2119,7 @@ management_hold (struct management *man)
       /* revert state */
       man->persist.standalone_disabled = standalone_disabled_save;
       man->persist.special_state_msg = NULL;
+      man->settings.mansig &= ~MANSIG_IGNORE_USR1_HUP;
 
       return true;
     }
index c7cce0736733b6cf94d3b36093bb639affbcc6c4..445f710283f74c49463fa75ffab8070ad86e5a66 100644 (file)
--- a/manage.h
+++ b/manage.h
@@ -207,6 +207,12 @@ struct man_settings {
   bool hold;
   bool connect_as_client;
   char *write_peer_info_file;
+
+/* flags for handling the management interface "signal" command */
+# define MANSIG_IGNORE_USR1_HUP  (1<<0)
+# define MANSIG_MAP_USR1_TO_HUP  (1<<1)
+# define MANSIG_MAP_USR1_TO_TERM (1<<2)
+  unsigned int mansig;
 };
 
 /* up_query modes */
@@ -276,7 +282,8 @@ bool management_open (struct management *man,
                      const int state_buffer_size,
                      const bool hold,
                      const bool connect_as_client,
-                     const char *write_peer_info_file);
+                     const char *write_peer_info_file,
+                     const int remap_sigusr1);
 
 void management_close (struct management *man);
 
index cb6af50440652b704df1647c3cc29ea93d134b19..66ade224cfea3c30e394ae424ee5fc919a1567f7 100644 (file)
--- a/openvpn.c
+++ b/openvpn.c
@@ -107,8 +107,6 @@ main (int argc, char *argv[])
   return 1;
 #endif
 
-  pre_init_signal_catch ();
-
   CLEAR (c);
 
   /* signify first time for components which can
@@ -124,6 +122,9 @@ main (int argc, char *argv[])
        */
       do
        {
+         /* enter pre-initialization mode with regard to signal handling */
+         pre_init_signal_catch ();
+
          /* zero context struct but leave first_time member alone */
          context_clear_all_except_first_time (&c);