diff --git a/cstp.c b/cstp.c index c59398b5..5397f68d 100644 --- a/cstp.c +++ b/cstp.c @@ -569,6 +569,8 @@ int cstp_reconnect(struct openconnect_info *vpninfo) poll_cmd_fd(vpninfo, interval); if (vpninfo->got_cancel_cmd) return -EINTR; + if (vpninfo->got_pause_cmd) + return 0; timeout -= interval; interval += vpninfo->reconnect_interval; if (interval > RECONNECT_INTERVAL_MAX) @@ -709,6 +711,9 @@ int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout) int len, ret; int work_done = 0; + if (vpninfo->ssl_fd == -1) + goto do_reconnect; + /* FIXME: The poll() handling here is fairly simplistic. Actually, if the SSL connection stalls it could return a WANT_WRITE error on _either_ of the SSL_read() or SSL_write() calls. In that case, diff --git a/mainloop.c b/mainloop.c index b56e34ea..053c81bd 100644 --- a/mainloop.c +++ b/mainloop.c @@ -55,6 +55,7 @@ int queue_new_packet(struct pkt **q, void *buf, int len) } /* Return value: + * = 0, when successfully paused (may call again) * = -EINTR, if aborted locally via cmd_fd * = -EPIPE, if the remote end explicitly terminated the session * = -EPERM, if the gateway sent 401 Unauthorized (cookie expired) @@ -86,7 +87,8 @@ int openconnect_mainloop(struct openconnect_info *vpninfo, dtls_try_handshake(vpninfo); if (vpninfo->dtls_attempt_period && !vpninfo->dtls_ssl && !vpninfo->new_dtls_ssl && - vpninfo->new_dtls_started + vpninfo->dtls_attempt_period < time(NULL)) { + vpninfo->new_dtls_started + vpninfo->dtls_attempt_period < time(NULL) && + vpninfo->ssl_fd != -1) { vpn_progress(vpninfo, PRG_TRACE, _("Attempt new DTLS connection\n")); connect_dtls_socket(vpninfo); } @@ -115,6 +117,17 @@ int openconnect_mainloop(struct openconnect_info *vpninfo, ret = -EINTR; break; } + if (vpninfo->got_pause_cmd) { + /* close all connections and wait for the user to call + openconnect_mainloop() again */ + openconnect_close_https(vpninfo, 0); + dtls_close(vpninfo, 1); + vpninfo->new_dtls_started = 0; + + vpninfo->got_pause_cmd = 0; + vpn_progress(vpninfo, PRG_INFO, _("Caller paused the connection\n")); + return 0; + } if (did_work) continue; diff --git a/openconnect-internal.h b/openconnect-internal.h index 76db5d45..574894e1 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -299,6 +299,7 @@ struct openconnect_info { int cmd_fd; int cmd_fd_write; int got_cancel_cmd; + int got_pause_cmd; struct pkt *incoming_queue; struct pkt *outgoing_queue; diff --git a/openconnect.h b/openconnect.h index f0bece75..a30ca056 100644 --- a/openconnect.h +++ b/openconnect.h @@ -168,7 +168,8 @@ struct oc_auth_form { #define PRG_TRACE 3 /* byte commands to write into the cmd_fd */ -#define OC_CMD_CANCEL 'x' +#define OC_CMD_CANCEL 'x' +#define OC_CMD_PAUSE 'p' #define RECONNECT_INTERVAL_MIN 10 #define RECONNECT_INTERVAL_MAX 100 diff --git a/ssl.c b/ssl.c index b9fef08a..4a0210ab 100644 --- a/ssl.c +++ b/ssl.c @@ -549,6 +549,9 @@ void check_cmd_fd(struct openconnect_info *vpninfo, fd_set *fds) case OC_CMD_CANCEL: vpninfo->got_cancel_cmd = 1; break; + case OC_CMD_PAUSE: + vpninfo->got_pause_cmd = 1; + break; } }