Skip to content

Commit

Permalink
Use closesocket() and fix errno handling for MinGW
Browse files Browse the repository at this point in the history
Based on a patch from Nikos Mavrogiannopoulos.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
  • Loading branch information
David Woodhouse authored and David Woodhouse committed Feb 6, 2014
1 parent 76df598 commit bd7ae7e
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 28 deletions.
41 changes: 41 additions & 0 deletions compat.c
Expand Up @@ -198,3 +198,44 @@ int openconnect__inet_aton(const char *cp, struct in_addr *addr)
return (addr->s_addr == 0xffffffff) ? 0 : 1;
}
#endif

#ifdef _WIN32
int openconnect__win32_neterrno()
{
switch (WSAGetLastError()) {
case WSAEINTR: return EINTR;
case WSAEWOULDBLOCK: return EWOULDBLOCK;
case WSAEINPROGRESS: return EINPROGRESS;
case WSAEALREADY: return EALREADY;
case WSAENOTSOCK: return ENOTSOCK;
case WSAEDESTADDRREQ: return EDESTADDRREQ;
case WSAEMSGSIZE: return EMSGSIZE;
case WSAEPROTOTYPE: return EPROTOTYPE;
case WSAENOPROTOOPT: return ENOPROTOOPT;
case WSAEPROTONOSUPPORT:return EPROTONOSUPPORT;
case WSAEOPNOTSUPP: return EOPNOTSUPP;
case WSAEPFNOSUPPORT: return EAFNOSUPPORT;
case WSAEAFNOSUPPORT: return EAFNOSUPPORT;
case WSAEADDRINUSE: return EADDRINUSE;
case WSAEADDRNOTAVAIL: return EADDRNOTAVAIL;
case WSAENETDOWN: return ENETDOWN;
case WSAENETUNREACH: return ENETUNREACH;
case WSAENETRESET: return ENETRESET;
case WSAECONNABORTED: return ECONNABORTED;
case WSAECONNRESET: return ECONNRESET;
case WSAENOBUFS: return ENOBUFS;
case WSAEISCONN: return EISCONN;
case WSAENOTCONN: return ENOTCONN;
case WSAETIMEDOUT: return ETIMEDOUT;
case WSAECONNREFUSED: return ECONNREFUSED;
case WSAELOOP: return ELOOP;
case WSAENAMETOOLONG: return ENAMETOOLONG;
case WSAEHOSTUNREACH: return EHOSTUNREACH;
case WSAENOTEMPTY: return ENOTEMPTY;
case WSAEINVAL: return EINVAL;
case WSAEFAULT: return EFAULT;
case 0: return 0;
default: return EIO;
}
}
#endif /* _WIN32 */
11 changes: 10 additions & 1 deletion configure.ac
Expand Up @@ -83,6 +83,10 @@ case $host_os in
AC_DEFINE(HAVE_SUNOS_BROKEN_TIME)
symver_time="openconnect__time;"
;;
*mingw32*|*mingw64*)
AC_MSG_NOTICE([Applying feature macros for MinGW/Windows build])
have_win=yes
;;
*)
# On FreeBSD the only way to get vsyslog() visible is to define
# *nothing*, which makes absolutely everything visible.
Expand Down Expand Up @@ -140,7 +144,12 @@ AS_COMPILER_FLAGS(WFLAGS,
-Wwrite-strings")
AC_SUBST(WFLAGS, [$WFLAGS])

AC_CHECK_FUNC(socket, [], AC_CHECK_LIB(socket, socket, [], AC_ERROR(Cannot find socket() function)))
if test "$have_win" = yes; then
# Checking "properly" for __attribute__((dllimport,stdcall)) functions is non-trivial
LIBS="$LIBS -lws2_32"
else
AC_CHECK_FUNC(socket, [], AC_CHECK_LIB(socket, socket, [], AC_ERROR(Cannot find socket() function)))
fi

have_inet_aton=yes
AC_CHECK_FUNC(inet_aton, [], AC_CHECK_LIB(nsl, inet_aton, [], have_inet_aton=no))
Expand Down
12 changes: 6 additions & 6 deletions dtls.c
Expand Up @@ -524,20 +524,20 @@ int connect_dtls_socket(struct openconnect_info *vpninfo)
_("Unknown protocol family %d. Cannot do DTLS\n"),
vpninfo->peer_addr->sa_family);
vpninfo->dtls_attempt_period = 0;
close(dtls_fd);
closesocket(dtls_fd);
return -EINVAL;
}

if (bind(dtls_fd, (struct sockaddr *)&dtls_bind_addr, dtls_bind_addrlen)) {
perror(_("Bind UDP socket for DTLS"));
close(dtls_fd);
closesocket(dtls_fd);
return -EINVAL;
}
}

if (connect(dtls_fd, vpninfo->dtls_addr, vpninfo->peer_addrlen)) {
perror(_("UDP (DTLS) connect:\n"));
close(dtls_fd);
closesocket(dtls_fd);
return -EINVAL;
}

Expand All @@ -546,7 +546,7 @@ int connect_dtls_socket(struct openconnect_info *vpninfo)

ret = start_dtls_handshake(vpninfo, dtls_fd);
if (ret) {
close(dtls_fd);
closesocket(dtls_fd);
return ret;
}

Expand All @@ -566,7 +566,7 @@ void dtls_close(struct openconnect_info *vpninfo, int kill_handshake_too)
{
if (vpninfo->dtls_ssl) {
DTLS_FREE(vpninfo->dtls_ssl);
close(vpninfo->dtls_fd);
closesocket(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);
Expand All @@ -575,7 +575,7 @@ void dtls_close(struct openconnect_info *vpninfo, int kill_handshake_too)
}
if (kill_handshake_too && vpninfo->new_dtls_ssl) {
DTLS_FREE(vpninfo->new_dtls_ssl);
close(vpninfo->new_dtls_fd);
closesocket(vpninfo->new_dtls_fd);
FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_rfds);
FD_CLR(vpninfo->new_dtls_fd, &vpninfo->select_efds);
vpninfo->new_dtls_ssl = NULL;
Expand Down
16 changes: 8 additions & 8 deletions gnutls.c
Expand Up @@ -1862,7 +1862,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
gnutls_free(datum.data);
gnutls_certificate_free_credentials(vpninfo->https_cred);
vpninfo->https_cred = NULL;
close(ssl_sock);
closesocket(ssl_sock);
return -ENOMEM;
}
err = gnutls_x509_crt_list_import(certs, &nr_certs, &datum,
Expand All @@ -1883,7 +1883,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
gnutls_strerror(err));
gnutls_certificate_free_credentials(vpninfo->https_cred);
vpninfo->https_cred = NULL;
close(ssl_sock);
closesocket(ssl_sock);
return -EINVAL;
}
}
Expand All @@ -1899,7 +1899,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
vpninfo->cafile, gnutls_strerror(err));
gnutls_certificate_free_credentials(vpninfo->https_cred);
vpninfo->https_cred = NULL;
close(ssl_sock);
closesocket(ssl_sock);
return -EINVAL;
}
}
Expand All @@ -1911,7 +1911,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
_("Loading certificate failed. Aborting.\n"));
gnutls_certificate_free_credentials(vpninfo->https_cred);
vpninfo->https_cred = NULL;
close(ssl_sock);
closesocket(ssl_sock);
return err;
}
}
Expand All @@ -1937,7 +1937,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
gnutls_strerror(err));
gnutls_deinit(vpninfo->https_sess);
vpninfo->https_sess = NULL;
close(ssl_sock);
closesocket(ssl_sock);
return -EIO;
}

Expand Down Expand Up @@ -1967,15 +1967,15 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
gnutls_deinit(vpninfo->https_sess);
vpninfo->https_sess = NULL;
close(ssl_sock);
closesocket(ssl_sock);
return -EINTR;
}
} else if (err == GNUTLS_E_INTERRUPTED || gnutls_error_is_fatal(err)) {
vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure: %s\n"),
gnutls_strerror(err));
gnutls_deinit(vpninfo->https_sess);
vpninfo->https_sess = NULL;
close(ssl_sock);
closesocket(ssl_sock);
return -EIO;
} else {
/* non-fatal error or warning. Ignore it and continue */
Expand Down Expand Up @@ -2004,7 +2004,7 @@ void openconnect_close_https(struct openconnect_info *vpninfo, int final)
vpninfo->https_sess = NULL;
}
if (vpninfo->ssl_fd != -1) {
close(vpninfo->ssl_fd);
closesocket(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);
Expand Down
8 changes: 8 additions & 0 deletions openconnect-internal.h
Expand Up @@ -369,6 +369,14 @@ void openconnect__unsetenv(const char *name);
int openconnect__inet_aton(const char *cp, struct in_addr *addr);
#endif

#ifdef _WIN32
#define neterrno openconnect__win32_neterrno
int openconnect__win32_neterrno();
#else
#define neterrno() errno
#define closesocket close
#endif

/* I always coded as if it worked like this. Now it does. */
#define realloc_inplace(p, size) do { \
void *__realloc_old = p; \
Expand Down
16 changes: 8 additions & 8 deletions openssl.c
Expand Up @@ -1283,7 +1283,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
_("Loading certificate failed. Aborting.\n"));
SSL_CTX_free(vpninfo->https_ctx);
vpninfo->https_ctx = NULL;
close(ssl_sock);
closesocket(ssl_sock);
return err;
}
check_certificate_expiry(vpninfo);
Expand Down Expand Up @@ -1316,7 +1316,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
if (!b) {
SSL_CTX_free(vpninfo->https_ctx);
vpninfo->https_ctx = NULL;
close(ssl_sock);
closesocket(ssl_sock);
return -EINVAL;
}

Expand All @@ -1330,7 +1330,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
openconnect_report_ssl_errors(vpninfo);
SSL_CTX_free(vpninfo->https_ctx);
vpninfo->https_ctx = NULL;
close(ssl_sock);
closesocket(ssl_sock);
return -ENOENT;
}

Expand All @@ -1354,7 +1354,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
openconnect_report_ssl_errors(vpninfo);
SSL_CTX_free(vpninfo->https_ctx);
vpninfo->https_ctx = NULL;
close(ssl_sock);
closesocket(ssl_sock);
return -EINVAL;
}
}
Expand Down Expand Up @@ -1386,7 +1386,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure\n"));
openconnect_report_ssl_errors(vpninfo);
SSL_free(https_ssl);
close(ssl_sock);
closesocket(ssl_sock);
return -EINVAL;
}

Expand All @@ -1395,14 +1395,14 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
if (is_cancel_pending(vpninfo, &rd_set)) {
vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
SSL_free(https_ssl);
close(ssl_sock);
closesocket(ssl_sock);
return -EINVAL;
}
}

if (verify_peer(vpninfo, https_ssl)) {
SSL_free(https_ssl);
close(ssl_sock);
closesocket(ssl_sock);
return -EINVAL;
}

Expand Down Expand Up @@ -1430,7 +1430,7 @@ void openconnect_close_https(struct openconnect_info *vpninfo, int final)
vpninfo->https_ssl = NULL;
}
if (vpninfo->ssl_fd != -1) {
close(vpninfo->ssl_fd);
closesocket(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);
Expand Down
10 changes: 5 additions & 5 deletions ssl.c
Expand Up @@ -66,7 +66,7 @@ static int cancellable_connect(struct openconnect_info *vpninfo, int sockfd,
if (vpninfo->protect_socket)
vpninfo->protect_socket(vpninfo->cbdata, sockfd);

if (connect(sockfd, addr, addrlen) < 0 && errno != EINPROGRESS)
if (connect(sockfd, addr, addrlen) < 0 && neterrno() != EINPROGRESS)
return -1;

do {
Expand Down Expand Up @@ -119,7 +119,7 @@ int connect_https_socket(struct openconnect_info *vpninfo)
vpninfo->hostname);
}
if (ssl_sock >= 0)
close(ssl_sock);
closesocket(ssl_sock);
return -EINVAL;
}
} else {
Expand Down Expand Up @@ -242,7 +242,7 @@ int connect_https_socket(struct openconnect_info *vpninfo)
if (!vpninfo->peer_addr) {
vpn_progress(vpninfo, PRG_ERR,
_("Failed to allocate sockaddr storage\n"));
close(ssl_sock);
closesocket(ssl_sock);
return -ENOMEM;
}
vpninfo->peer_addrlen = rp->ai_addrlen;
Expand All @@ -266,7 +266,7 @@ int connect_https_socket(struct openconnect_info *vpninfo)
}
break;
}
close(ssl_sock);
closesocket(ssl_sock);
ssl_sock = -1;
}
freeaddrinfo(result);
Expand All @@ -282,7 +282,7 @@ int connect_https_socket(struct openconnect_info *vpninfo)
if (vpninfo->proxy) {
err = process_proxy(vpninfo, ssl_sock);
if (err) {
close(ssl_sock);
closesocket(ssl_sock);
return err;
}
}
Expand Down

0 comments on commit bd7ae7e

Please sign in to comment.