]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Extended "client-kill" management interface command (server-side)
authorJames Yonan <james@openvpn.net>
Sun, 20 Mar 2011 04:12:26 +0000 (04:12 +0000)
committerDavid Sommerseth <dazo@users.sourceforge.net>
Tue, 26 Apr 2011 20:29:11 +0000 (22:29 +0200)
to accept an optional message string.  The message string format is:

  RESTART|HALT,<human-readable-message>

RESTART will tell the client to restart (i.e. SIGUSR1).

HALT will tell the client to exit (i.e. SIGTERM).

On the client, human-readable-message will be communicated via
management interface:

  >NOTIFY,<severity>,<type>,<human-readable-message>"

Version 2.1.3m

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

forward.c
manage.c
manage.h
multi.c
push.c
push.h
version.m4

index ce0a7c4c2fb2bc8b3dbfb2a0fade5bc0006b3bf7..65b8f0c8c3d45d7e46fe0613eb09c4aad4f2413c 100644 (file)
--- a/forward.c
+++ b/forward.c
@@ -155,7 +155,9 @@ check_incoming_control_channel_dowork (struct context *c)
          else if (buf_string_match_head_str (&buf, "PUSH_"))
            incoming_push_message (c, &buf);
          else if (buf_string_match_head_str (&buf, "RESTART"))
-           server_pushed_restart (c, &buf);
+           server_pushed_signal (c, &buf, true, 7);
+         else if (buf_string_match_head_str (&buf, "HALT"))
+           server_pushed_signal (c, &buf, false, 4);
          else
            msg (D_PUSH_ERRORS, "WARNING: Received unknown control message: %s", BSTR (&buf));
        }
@@ -237,7 +239,12 @@ send_control_channel_string (struct context *c, const char *str, int msglevel)
     /* buffered cleartext write onto TLS control channel */
     stat = tls_send_payload (c->c2.tls_multi, (uint8_t*) str, strlen (str) + 1);
 
-    /* reschedule tls_multi_process */
+    /*
+     * Reschedule tls_multi_process.
+     * NOTE: in multi-client mode, usually the below two statements are
+     * insufficient to reschedule the client instance object unless
+     * multi_schedule_context_wakeup(m, mi) is also called.
+     */
     interval_action (&c->c2.tmp_int);
     context_immediate_reschedule (c); /* ZERO-TIMEOUT */
 
index 0939105ac57d4ea7e5b4f36cd49453383f281b44..67f87d67e7169667700a898ea9092787717c5487 100644 (file)
--- a/manage.c
+++ b/manage.c
@@ -96,7 +96,7 @@ man_help ()
   msg (M_CLIENT, "client-auth-nt CID KID : Authenticate client-id/key-id CID/KID");
   msg (M_CLIENT, "client-deny CID KID R [CR] : Deny auth client-id/key-id CID/KID with log reason");
   msg (M_CLIENT, "                             text R and optional client reason text CR");
-  msg (M_CLIENT, "client-kill CID        : Kill client instance CID");
+  msg (M_CLIENT, "client-kill CID [M]    : Kill client instance CID with message M (def=RESTART)");
   msg (M_CLIENT, "env-filter [level]     : Set env-var filter level");
 #ifdef MANAGEMENT_PF
   msg (M_CLIENT, "client-pf CID          : Define packet filter for client CID (MULTILINE)");
@@ -947,14 +947,14 @@ man_client_deny (struct management *man, const char *cid_str, const char *kid_st
 }
 
 static void
-man_client_kill (struct management *man, const char *cid_str)
+man_client_kill (struct management *man, const char *cid_str, const char *kill_msg)
 {
   unsigned long cid = 0;
   if (parse_cid (cid_str, &cid))
     {
       if (man->persist.callback.kill_by_cid)
        {
-         const bool status = (*man->persist.callback.kill_by_cid) (man->persist.callback.arg, cid);
+         const bool status = (*man->persist.callback.kill_by_cid) (man->persist.callback.arg, cid, kill_msg);
          if (status)
            {
              msg (M_CLIENT, "SUCCESS: client-kill command succeeded");
@@ -1265,8 +1265,8 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
 #ifdef MANAGEMENT_DEF_AUTH
   else if (streq (p[0], "client-kill"))
     {
-      if (man_need (man, p, 1, 0))
-       man_client_kill (man, p[1]);
+      if (man_need (man, p, 1, MN_AT_LEAST))
+       man_client_kill (man, p[1], p[2]);
     }
   else if (streq (p[0], "client-deny"))
     {
@@ -2190,6 +2190,7 @@ management_open (struct management *man,
 void
 management_close (struct management *man)
 {
+  man_output_list_push_finalize (man);  /* flush output queue */
   man_connection_close (man);
   man_settings_close (&man->settings);
   man_persist_close (&man->persist);
@@ -2332,6 +2333,12 @@ management_up_down(struct management *man, const char *updown, const struct env_
     }
 }
 
+void
+management_notify(struct management *man, const char *severity, const char *type, const char *text)
+{
+  msg (M_CLIENT, ">NOTIFY:%s,%s,%s", severity, type, text);
+}
+
 #ifdef MANAGEMENT_DEF_AUTH
 
 static bool
index 18b1564411dde51a7ecb590472e5371760be6671..5e0696b8a69fdf60f59f739f0428ec84fac31d91 100644 (file)
--- a/manage.h
+++ b/manage.h
@@ -156,7 +156,7 @@ struct management_callback
   void (*delete_event) (void *arg, event_t event);
   int (*n_clients) (void *arg);
 #ifdef MANAGEMENT_DEF_AUTH
-  bool (*kill_by_cid) (void *arg, const unsigned long cid);
+  bool (*kill_by_cid) (void *arg, const unsigned long cid, const char *kill_msg);
   bool (*client_auth) (void *arg,
                       const unsigned long cid,
                       const unsigned int mda_key_id,
@@ -375,6 +375,8 @@ void management_event_loop_n_seconds (struct management *man, int sec);
 
 void management_up_down(struct management *man, const char *updown, const struct env_set *es);
 
+void management_notify(struct management *man, const char *severity, const char *type, const char *text);
+
 #ifdef MANAGEMENT_DEF_AUTH
 void management_notify_client_needing_auth (struct management *management,
                                            const unsigned int auth_id,
diff --git a/multi.c b/multi.c
index df96ba5303c07038f72ef17fbf853e66623f0554..4ab1e723aa63d72d5d9e0cd8f03181d18ed6b1d4 100644 (file)
--- a/multi.c
+++ b/multi.c
@@ -2544,13 +2544,14 @@ lookup_by_cid (struct multi_context *m, const unsigned long cid)
 }
 
 static bool
-management_kill_by_cid (void *arg, const unsigned long cid)
+management_kill_by_cid (void *arg, const unsigned long cid, const char *kill_msg)
 {
   struct multi_context *m = (struct multi_context *) arg;
   struct multi_instance *mi = lookup_by_cid (m, cid);
   if (mi)
     {
-      send_restart (&mi->context); /* was: multi_signal_instance (m, mi, SIGTERM); */
+      send_restart (&mi->context, kill_msg); /* was: multi_signal_instance (m, mi, SIGTERM); */
+      multi_schedule_context_wakeup(m, mi);
       return true;
     }
   else
diff --git a/push.c b/push.c
index f7b7d17b927830fb9139762c8031c706e35db2d2..2e8aa55f2a4f18ff3ee734fe4bb74ce0cfc8c427 100644 (file)
--- a/push.c
+++ b/push.c
@@ -87,13 +87,30 @@ receive_auth_failed (struct context *c, const struct buffer *buffer)
  * Act on received restart message from server
  */
 void
-server_pushed_restart (struct context *c, const struct buffer *buffer)
+server_pushed_signal (struct context *c, const struct buffer *buffer, const bool restart, const int adv)
 {
   if (c->options.pull)
     {
-      msg (D_STREAM_ERRORS, "Connection reset command was pushed by server");
-      c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- server-pushed connection reset */
-      c->sig->signal_text = "server-pushed-connection-reset";
+      struct buffer buf = *buffer;
+      const char *m = "";
+      if (buf_advance (&buf, adv) && buf_read_u8 (&buf) == ',' && BLEN (&buf))
+       m = BSTR (&buf);
+      if (restart)
+       {
+         msg (D_STREAM_ERRORS, "Connection reset command was pushed by server ('%s')", m);
+         c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- server-pushed connection reset */
+         c->sig->signal_text = "server-pushed-connection-reset";
+       }
+      else
+       {
+         msg (D_STREAM_ERRORS, "Halt command was pushed by server ('%s')", m);
+         c->sig->signal_received = SIGTERM; /* SOFT-SIGTERM -- server-pushed halt */
+         c->sig->signal_text = "server-pushed-halt";
+       }
+#ifdef ENABLE_MANAGEMENT
+      if (management)
+       management_notify (management, "info", c->sig->signal_text, m);
+#endif
     }
 }
 
@@ -130,10 +147,10 @@ send_auth_failed (struct context *c, const char *client_reason)
  * Send restart message from server to client.
  */
 void
-send_restart (struct context *c)
+send_restart (struct context *c, const char *kill_msg)
 {
   schedule_exit (c, c->options.scheduled_exit_interval, SIGTERM);
-  send_control_channel_string (c, "RESTART", D_PUSH);
+  send_control_channel_string (c, kill_msg ? kill_msg : "RESTART", D_PUSH);
 }
 
 #endif
diff --git a/push.h b/push.h
index b5d1fbf3d209fc71c91cdb57f7a0e4cc37a5de4b..8c3f1575baab4c0d09022340193bc8569e004a4f 100644 (file)
--- a/push.h
+++ b/push.h
@@ -50,7 +50,7 @@ bool send_push_request (struct context *c);
 
 void receive_auth_failed (struct context *c, const struct buffer *buffer);
 
-void server_pushed_restart (struct context *c, const struct buffer *buffer);
+void server_pushed_signal (struct context *c, const struct buffer *buffer, const bool restart, const int adv);
 
 #if P2MP_SERVER
 
@@ -67,7 +67,7 @@ void remove_iroutes_from_push_route_list (struct options *o);
 
 void send_auth_failed (struct context *c, const char *client_reason);
 
-void send_restart (struct context *c);
+void send_restart (struct context *c, const char *kill_msg);
 
 #endif
 #endif
index e3825f2df252f15392ad4090eda908b538830dd7..f3e7a8d1514dc8df0420216e485883a5fa35e4ca 100644 (file)
@@ -1,5 +1,5 @@
 dnl define the OpenVPN version
-define(PRODUCT_VERSION,[2.1.3k])
+define(PRODUCT_VERSION,[2.1.3m])
 dnl define the TAP version
 define(PRODUCT_TAP_ID,[tap0901])
 define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])