vpninfo->progress(vpninfo, PRG_ERR, "Error fetching HTTPS response\n");
if (!retried) {
retried = 1;
- SSL_free(vpninfo->https_ssl);
- close(vpninfo->ssl_fd);
+ openconnect_close_https(vpninfo);
if (openconnect_open_https(vpninfo)) {
vpninfo->progress(vpninfo, PRG_ERR,
BIO_set_nbio(SSL_get_wbio(vpninfo->https_ssl),1);
fcntl(vpninfo->ssl_fd, F_SETFL, fcntl(vpninfo->ssl_fd, F_GETFL) | O_NONBLOCK);
- vpninfo->ssl_pfd = vpn_add_pollfd(vpninfo, vpninfo->ssl_fd, POLLIN|POLLHUP|POLLERR);
+ if (vpninfo->select_nfds <= vpninfo->ssl_fd)
+ vpninfo->select_nfds = vpninfo->ssl_fd + 1;
+
+ FD_SET(vpninfo->ssl_fd, &vpninfo->select_rfds);
+ FD_SET(vpninfo->ssl_fd, &vpninfo->select_efds);
vpninfo->ssl_times.last_rx = vpninfo->ssl_times.last_tx = time(NULL);
return 0;
if (vpninfo->current_ssl_pkt) {
handle_outgoing:
vpninfo->ssl_times.last_tx = time(NULL);
- vpninfo->pfds[vpninfo->ssl_pfd].events &= ~POLLOUT;
+ FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
ret = SSL_write(vpninfo->https_ssl,
vpninfo->current_ssl_pkt->hdr,
vpninfo->current_ssl_pkt->len + 8);
case SSL_ERROR_WANT_WRITE:
/* Waiting for the socket to become writable -- it's
probably stalled, and/or the buffers are full */
- vpninfo->pfds[vpninfo->ssl_pfd].events |= POLLOUT;
+ FD_SET(vpninfo->ssl_fd, &vpninfo->select_wfds);
+
case SSL_ERROR_WANT_READ:
if (ka_stalled_dpd_time(&vpninfo->ssl_times, timeout))
goto peer_dead;
case KA_DPD_DEAD:
peer_dead:
vpninfo->progress(vpninfo, PRG_ERR, "CSTP Dead Peer Detection detected dead peer!\n");
- SSL_free(vpninfo->https_ssl);
- vpninfo->https_ssl = NULL;
- close(vpninfo->ssl_fd);
+ openconnect_close_https(vpninfo);
/* It's already deflated in the old stream. Extremely
non-trivial to reconstitute it; just throw it away */
vpninfo->new_dtls_fd = dtls_fd;
vpninfo->new_dtls_ssl = dtls_ssl;
- vpninfo->pfds[vpninfo->new_dtls_pfd].fd = vpninfo->new_dtls_fd;
+
+ if (vpninfo->select_nfds <= dtls_fd)
+ vpninfo->select_nfds = dtls_fd + 1;
+
+ FD_SET(dtls_fd, &vpninfo->select_rfds);
+ FD_SET(dtls_fd, &vpninfo->select_efds);
time(&vpninfo->new_dtls_started);
return dtls_try_handshake(vpninfo);
/* We are replacing an old connection */
SSL_free(vpninfo->dtls_ssl);
close(vpninfo->dtls_fd);
+ FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
+ FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
+ FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
}
- vpninfo->pfds[vpninfo->dtls_pfd].fd = vpninfo->new_dtls_fd;
vpninfo->dtls_ssl = vpninfo->new_dtls_ssl;
vpninfo->dtls_fd = vpninfo->new_dtls_fd;
- vpninfo->pfds[vpninfo->new_dtls_pfd].fd = -1;
vpninfo->new_dtls_ssl = NULL;
vpninfo->new_dtls_fd = -1;
/* Kill the new (failed) connection... */
SSL_free(vpninfo->new_dtls_ssl);
- vpninfo->pfds[vpninfo->new_dtls_pfd].fd = -1;
+ FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_rfds);
+ FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_efds);
close(vpninfo->new_dtls_fd);
vpninfo->new_dtls_ssl = NULL;
vpninfo->new_dtls_fd = -1;
if (vpninfo->dtls_ssl) {
SSL_free(vpninfo->dtls_ssl);
close(vpninfo->dtls_fd);
- vpninfo->pfds[vpninfo->dtls_pfd].fd = -1;
+ FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
+ FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
+ FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
vpninfo->dtls_ssl = NULL;
vpninfo->dtls_fd = -1;
}
if (vpninfo->dtls_ssl) {
SSL_free(vpninfo->dtls_ssl);
close(vpninfo->dtls_fd);
- vpninfo->pfds[vpninfo->dtls_pfd].fd = -1;
+ FD_CLR(vpninfo->dtls_fd, &vpninfo->select_rfds);
+ FD_CLR(vpninfo->dtls_fd, &vpninfo->select_wfds);
+ FD_CLR(vpninfo->dtls_fd, &vpninfo->select_efds);
vpninfo->dtls_ssl = NULL;
vpninfo->dtls_fd = -1;
}
return -EINVAL;
}
- vpninfo->dtls_pfd = vpn_add_pollfd(vpninfo, -1,
- POLLIN|POLLHUP|POLLERR);
- vpninfo->new_dtls_pfd = vpn_add_pollfd(vpninfo, -1,
- POLLIN|POLLHUP|POLLERR);
-
+
if (connect_dtls_socket(vpninfo))
return -EINVAL;
return 0;
}
-int vpn_add_pollfd(struct openconnect_info *vpninfo, int fd, short events)
-{
- vpninfo->nfds++;
- vpninfo->pfds = realloc(vpninfo->pfds, sizeof(struct pollfd) * vpninfo->nfds);
- if (!vpninfo->pfds) {
- vpninfo->progress(vpninfo, PRG_ERR, "Failed to reallocate pfds\n");
- exit(1);
- }
- vpninfo->pfds[vpninfo->nfds - 1].fd = fd;
- vpninfo->pfds[vpninfo->nfds - 1].events = events;
-
- return vpninfo->nfds - 1;
-}
-
static int killed;
static void handle_sigint(int sig)
while (!vpninfo->quit_reason) {
int did_work = 0;
int timeout = INT_MAX;
+ struct timeval tv;
+ fd_set rfds, wfds, efds;
if (vpninfo->new_dtls_ssl)
dtls_try_handshake(vpninfo);
vpninfo->progress(vpninfo, PRG_TRACE,
"Did no work; sleeping for %d ms...\n", timeout);
-
- poll(vpninfo->pfds, vpninfo->nfds, timeout);
- if (vpninfo->pfds[vpninfo->ssl_pfd].revents & POLL_HUP) {
+ memcpy(&rfds, &vpninfo->select_rfds, sizeof(rfds));
+ memcpy(&wfds, &vpninfo->select_wfds, sizeof(wfds));
+ memcpy(&efds, &vpninfo->select_efds, sizeof(efds));
+
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout * 1000) % 1000000;
+ select(vpninfo->select_nfds, &rfds, &wfds, &efds, &tv);
+ if (FD_ISSET(vpninfo->ssl_fd, &efds)) {
vpninfo->progress(vpninfo, PRG_ERR, "Server closed connection!\n");
/* OpenSSL doesn't seem to cope properly with this... */
exit(1);
#define __OPENCONNECT_ANYCONNECT_H
#include <openssl/ssl.h>
-#include <poll.h>
#include <zlib.h>
#include <stdint.h>
#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
struct pkt {
int type;
const char *vpn_nbns[3];
const char *vpn_domain;
- struct pollfd *pfds;
- int nfds;
+ int select_nfds;
+ fd_set select_rfds;
+ fd_set select_wfds;
+ fd_set select_efds;
+
int tun_fd;
int ssl_fd;
int dtls_fd;
int new_dtls_fd;
- int ssl_pfd;
- int dtls_pfd;
- int new_dtls_pfd;
struct pkt *incoming_queue;
struct pkt *outgoing_queue;
openconnect_SSL_printf(SSL *ssl, const char *fmt, ...);
int openconnect_SSL_gets(SSL *ssl, char *buf, size_t len);
int openconnect_open_https(struct openconnect_info *vpninfo);
+void openconnect_close_https(struct openconnect_info *vpninfo);
/* main.c */
extern int verbose;
return 0;
}
+void openconnect_close_https(struct openconnect_info *vpninfo)
+{
+ SSL_free(vpninfo->https_ssl);
+ vpninfo->https_ssl = NULL;
+ close(vpninfo->ssl_fd);
+ FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
+ FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
+ FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
+ vpninfo->ssl_fd = -1;
+}
+
void openconnect_init_openssl(void)
{
SSL_library_init ();
{
struct ifreq ifr;
int tun_fd;
- int pfd;
if (vpninfo->script_tun) {
pid_t child;
fcntl(tun_fd, F_SETFD, FD_CLOEXEC);
vpninfo->tun_fd = tun_fd;
- pfd = vpn_add_pollfd(vpninfo, vpninfo->tun_fd, POLLIN);
+
+ if (vpninfo->select_nfds <= tun_fd)
+ vpninfo->select_nfds = tun_fd + 1;
+
+ FD_SET(tun_fd, &vpninfo->select_rfds);
fcntl(vpninfo->tun_fd, F_SETFL, fcntl(vpninfo->tun_fd, F_GETFL) | O_NONBLOCK);