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));
}
/* 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 */
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)");
}
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");
#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"))
{
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);
}
}
+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
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,
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,
}
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
* 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
}
}
* 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
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
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
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])