From: David Woodhouse Date: Thu, 1 Jul 2021 15:30:27 +0000 (+0100) Subject: Fix epoll support for connection pause/restart X-Git-Tag: v8.20~110 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=dc86e96ee2a6da6f59e1903946fe097e6cbd4250;p=users%2Fdwmw2%2Fopenconnect.git Fix epoll support for connection pause/restart We need to actually remove the file descriptors from the epoll set. Otherwise we get -EEXIST when adding them again (in the case of the cmd_fd as we re-enter the main loop). Signed-off-by: David Woodhouse --- diff --git a/dtls.c b/dtls.c index 894a9687..ca8ad551 100644 --- a/dtls.c +++ b/dtls.c @@ -154,9 +154,7 @@ void dtls_close(struct openconnect_info *vpninfo) { if (vpninfo->dtls_ssl) { dtls_ssl_free(vpninfo); - unmonitor_read_fd(vpninfo, dtls); - unmonitor_write_fd(vpninfo, dtls); - unmonitor_except_fd(vpninfo, dtls); + unmonitor_fd(vpninfo, dtls); closesocket(vpninfo->dtls_fd); vpninfo->dtls_ssl = NULL; vpninfo->dtls_fd = -1; diff --git a/esp.c b/esp.c index 56190b17..cc423a58 100644 --- a/esp.c +++ b/esp.c @@ -392,9 +392,7 @@ void esp_close(struct openconnect_info *vpninfo) /* We close and reopen the socket in case we roamed and our local IP address has changed. */ if (vpninfo->dtls_fd != -1) { - unmonitor_read_fd(vpninfo, dtls); - unmonitor_write_fd(vpninfo, dtls); - unmonitor_except_fd(vpninfo, dtls); + unmonitor_fd(vpninfo, dtls); closesocket(vpninfo->dtls_fd); vpninfo->dtls_fd = -1; } diff --git a/gnutls.c b/gnutls.c index afa5d917..12147ab5 100644 --- a/gnutls.c +++ b/gnutls.c @@ -2473,9 +2473,7 @@ void openconnect_close_https(struct openconnect_info *vpninfo, int final) vpninfo->https_sess = NULL; } if (vpninfo->ssl_fd != -1) { - unmonitor_read_fd(vpninfo, ssl); - unmonitor_write_fd(vpninfo, ssl); - unmonitor_except_fd(vpninfo, ssl); + unmonitor_fd(vpninfo, ssl); closesocket(vpninfo->ssl_fd); vpninfo->ssl_fd = -1; } diff --git a/mainloop.c b/mainloop.c index 0d57db26..848049fa 100644 --- a/mainloop.c +++ b/mainloop.c @@ -285,6 +285,10 @@ int openconnect_mainloop(struct openconnect_info *vpninfo, vpninfo->got_pause_cmd = 0; vpn_progress(vpninfo, PRG_INFO, _("Caller paused the connection\n")); + + if (vpninfo->cmd_fd >= 0) + unmonitor_fd(vpninfo, cmd); + return 0; } } @@ -390,6 +394,10 @@ int openconnect_mainloop(struct openconnect_info *vpninfo, if (tun_is_up(vpninfo)) os_shutdown_tun(vpninfo); + + if (vpninfo->cmd_fd >= 0) + unmonitor_fd(vpninfo, cmd); + return ret < 0 ? ret : -EIO; } diff --git a/openconnect-internal.h b/openconnect-internal.h index e4ac5419..023b14be 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -856,8 +856,11 @@ static inline void free_pkt(struct openconnect_info *vpninfo, struct pkt *pkt) #define monitor_fd_new(_v, _n) do { if (!_v->_n##_event) _v->_n##_event = CreateEvent(NULL, FALSE, FALSE, NULL); } while (0) #define read_fd_monitored(_v, _n) (_v->_n##_monitored & FD_READ) -#else +#define __unmonitor_fd(_v, _n) do { CloseHandle(_v->_n##_event); \ + _v->_n##_event = (HANDLE)0; \ + } while(0) +#else #ifdef HAVE_EPOLL static inline void __sync_epoll_fd(struct openconnect_info *vpninfo, int fd, uint32_t *fd_evts) @@ -880,10 +883,27 @@ static inline void __sync_epoll_fd(struct openconnect_info *vpninfo, int fd, uin } } #define update_epoll_fd(_v, _n) __sync_epoll_fd(_v, _v->_n##_fd, &_v->_n##_epoll) + +static inline void __remove_epoll_fd(struct openconnect_info *vpninfo, int fd) +{ + struct epoll_event ev = { 0 }; + if (vpninfo->epoll_fd >= 0 && + epoll_ctl(vpninfo->epoll_fd, EPOLL_CTL_DEL, fd, &ev) < 0) + vpn_perror(vpninfo, "EPOLL_CTL_DEL"); + /* No other action on error; if it truly matters we'll bail + * later and fall back to select() */ +} + +#define __unmonitor_fd(_v, _n) do { \ + __remove_epoll_fd(_v, _v->_n##_fd); \ + _v->_n##_epoll = 0; } while(0) + +#else /* !HAVE_POLL */ +#define __unmonitor_fd(_v, _n) do { } while(0) #endif -static inline void __monitor_fd(struct openconnect_info *vpninfo, - int fd, fd_set *set) +static inline void __monitor_fd_event(struct openconnect_info *vpninfo, + int fd, fd_set *set) { if (fd < 0 || FD_ISSET(fd, set)) return; @@ -894,8 +914,8 @@ static inline void __monitor_fd(struct openconnect_info *vpninfo, #endif } -static inline void __unmonitor_fd(struct openconnect_info *vpninfo, - int fd, fd_set *set) +static inline void __unmonitor_fd_event(struct openconnect_info *vpninfo, + int fd, fd_set *set) { if (fd < 0 || !FD_ISSET(fd, set)) return; @@ -906,12 +926,12 @@ static inline void __unmonitor_fd(struct openconnect_info *vpninfo, #endif } -#define monitor_read_fd(_v, _n) __monitor_fd(_v, _v->_n##_fd, &_v->_select_rfds) -#define unmonitor_read_fd(_v, _n) __unmonitor_fd(_v, _v->_n##_fd, &_v->_select_rfds) -#define monitor_write_fd(_v, _n) __monitor_fd(_v, _v->_n##_fd, &_v->_select_wfds) -#define unmonitor_write_fd(_v, _n) __unmonitor_fd(_v, _v->_n##_fd, &_v->_select_wfds) -#define monitor_except_fd(_v, _n) __monitor_fd(_v, _v->_n##_fd, &_v->_select_efds) -#define unmonitor_except_fd(_v, _n) __unmonitor_fd(_v, _v->_n##_fd, &_v->_select_efds) +#define monitor_read_fd(_v, _n) __monitor_fd_event(_v, _v->_n##_fd, &_v->_select_rfds) +#define unmonitor_read_fd(_v, _n) __unmonitor_fd_event(_v, _v->_n##_fd, &_v->_select_rfds) +#define monitor_write_fd(_v, _n) __monitor_fd_event(_v, _v->_n##_fd, &_v->_select_wfds) +#define unmonitor_write_fd(_v, _n) __unmonitor_fd_event(_v, _v->_n##_fd, &_v->_select_wfds) +#define monitor_except_fd(_v, _n) __monitor_fd_event(_v, _v->_n##_fd, &_v->_select_efds) +#define unmonitor_except_fd(_v, _n) __unmonitor_fd_event(_v, _v->_n##_fd, &_v->_select_efds) static inline void __monitor_fd_new(struct openconnect_info *vpninfo, int fd) @@ -931,11 +951,17 @@ static inline void __monitor_fd_new(struct openconnect_info *vpninfo, #endif } - #define monitor_fd_new(_v, _n) __monitor_fd_new(_v, _v->_n##_fd) - #define read_fd_monitored(_v, _n) FD_ISSET(_v->_n##_fd, &_v->_select_rfds) -#endif +#endif /* !WIN32 */ + +/* This is for all platforms */ +#define unmonitor_fd(_v, _n) do { \ + unmonitor_read_fd(_v, _n); \ + unmonitor_write_fd(_v, _n); \ + unmonitor_except_fd(_v, _n); \ + __unmonitor_fd(_v, _n); \ + } while(0) /* Key material for DTLS-PSK */ #define PSK_LABEL "EXPORTER-openconnect-psk" diff --git a/openssl.c b/openssl.c index 095e29f3..8d8e81f5 100644 --- a/openssl.c +++ b/openssl.c @@ -1999,9 +1999,7 @@ void openconnect_close_https(struct openconnect_info *vpninfo, int final) vpninfo->https_ssl = NULL; } if (vpninfo->ssl_fd != -1) { - unmonitor_read_fd(vpninfo, ssl); - unmonitor_write_fd(vpninfo, ssl); - unmonitor_except_fd(vpninfo, ssl); + unmonitor_fd(vpninfo, ssl); closesocket(vpninfo->ssl_fd); vpninfo->ssl_fd = -1; } diff --git a/tun.c b/tun.c index e5b8a49d..eba766d8 100644 --- a/tun.c +++ b/tun.c @@ -453,7 +453,7 @@ int openconnect_setup_tun_fd(struct openconnect_info *vpninfo, int tun_fd) set_fd_cloexec(tun_fd); if (vpninfo->tun_fd != -1) - unmonitor_read_fd(vpninfo, tun); + unmonitor_fd(vpninfo, tun); vpninfo->tun_fd = tun_fd;