diff --git a/mainloop.c b/mainloop.c index cac7b2dc..e5c19732 100644 --- a/mainloop.c +++ b/mainloop.c @@ -105,7 +105,8 @@ int tun_mainloop(struct openconnect_info *vpninfo, int *timeout) /* Return value: * = 0, when successfully paused (may call again) - * = -EINTR, if aborted locally via cmd_fd + * = -EINTR, if aborted locally via OC_CMD_CANCEL + * = -ECONNABORTED, if aborted locally via OC_CMD_DETACH * = -EPIPE, if the remote end explicitly terminated the session * = -EPERM, if the gateway sent 401 Unauthorized (cookie expired) * < 0, for any other error @@ -157,8 +158,12 @@ int openconnect_mainloop(struct openconnect_info *vpninfo, poll_cmd_fd(vpninfo, 0); if (vpninfo->got_cancel_cmd) { - vpninfo->quit_reason = "Aborted by caller"; - ret = -EINTR; + if (vpninfo->cancel_type == OC_CMD_CANCEL) { + vpninfo->quit_reason = "Aborted by caller"; + ret = -EINTR; + } else { + ret = -ECONNABORTED; + } break; } if (vpninfo->got_pause_cmd) { @@ -215,7 +220,8 @@ int openconnect_mainloop(struct openconnect_info *vpninfo, #endif } - cstp_bye(vpninfo, vpninfo->quit_reason); + if (vpninfo->quit_reason) + cstp_bye(vpninfo, vpninfo->quit_reason); os_shutdown_tun(vpninfo); return ret < 0 ? ret : -EIO; diff --git a/openconnect-internal.h b/openconnect-internal.h index dbe1feeb..c7c13d79 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -305,6 +305,7 @@ struct openconnect_info { int cmd_fd_write; int got_cancel_cmd; int got_pause_cmd; + char cancel_type; struct pkt *incoming_queue; struct pkt *outgoing_queue; diff --git a/openconnect.h b/openconnect.h index 88588f29..6c2ac1be 100644 --- a/openconnect.h +++ b/openconnect.h @@ -225,9 +225,21 @@ struct oc_stats { #define PRG_DEBUG 2 #define PRG_TRACE 3 -/* byte commands to write into the cmd_fd */ +/* Byte commands to write into the cmd_fd: + * + * CANCEL closes network connections, logs off the session (cookie) + * and shuts down the tun device. + * PAUSE closes network connections and returns. The caller is expected + * to call openconnect_mainloop() again soon. + * DETACH closes network connections and shuts down the tun device. + * It is not legal to call openconnect_mainloop() again after this, + * but a new instance of openconnect can be started using the same + * cookie. + * STATS calls the stats_handler. + */ #define OC_CMD_CANCEL 'x' #define OC_CMD_PAUSE 'p' +#define OC_CMD_DETACH 'd' #define OC_CMD_STATS 's' #define RECONNECT_INTERVAL_MIN 10 diff --git a/ssl.c b/ssl.c index 80ab9f89..6be3d6ac 100644 --- a/ssl.c +++ b/ssl.c @@ -587,7 +587,9 @@ void check_cmd_fd(struct openconnect_info *vpninfo, fd_set *fds) switch (cmd) { case OC_CMD_CANCEL: + case OC_CMD_DETACH: vpninfo->got_cancel_cmd = 1; + vpninfo->cancel_type = cmd; break; case OC_CMD_PAUSE: vpninfo->got_pause_cmd = 1;