patch attached, of course. Even in UNIX County, ioctl(FIONBIO) isn't everywhere. Let alone abroad.
Since the days of yore OpenSSL has implicitly known this as there exists a BIO_socket_nbio() but since it was far from complete the more or less complete #ifdef portability hacks litter the codebase. This patch ensures toggling the socket nonblocking option works on all platforms which are supported by OpenSSL -- in fact, the edits are a mix of those hacks mentioned above and checking them against the man pages or other documentation available for various platforms. I'm not entirely sure about the VMS tweak, but it's in the OpenSSL codebase elsewhere, so it is included here as well. The patch/diff files for the various apps/*, etc. spots will follow later with this PR. This one can be done without fixing those yet, so we can 'upgrade' in two easy stages in this PR. (Or do you prefer multiple PRs for this? It's a basic change, so from that perspective doesn't merit multiple PR#s IMO.) One note: - BIO_F_BIO_SOCKET_NBIO is new so the mkerr.pl perl script must be run to update the error section(s) in the header file(s). - ERR_R_PASSED_INVALID_ARGUMENT is a new code; its usefulness reaches beyond this simple patch as there are several places in OpenSSL where the various subsystems (BIO, EVP, ENGINE) use their own equivalent code; using this 'global spanning' ERR_-based error code cuts down on error code duplication; besides that, it's not a BIO specific error, so making it BIO_R_PASSED_INVALID_ARGUMENT is nonsense; this kind of error is 'generic' in that it is due to the caller, i.e. user of the subsystem and not dependent on the subsystem per se. The relevant edit for err/err.h is shown at the bottom of this message (included as separate attachment for your convenience). --- h:\prj\1original\openssl\openssl\crypto\bio\b_sock.c 2010-05-14 15:18:09.000000000 +-0200 +++ h:\prj\3actual\openssl\crypto\bio\b_sock.c 2010-05-20 00:03:33.000000000 +-0200 @@ -927,15 +1007,57 @@ return(ret == 0); } #endif int BIO_socket_nbio(int s, int mode) { - int ret= -1; + int ret = -1; int l; - l=mode; +#if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000) +/* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */ +#undef FIONBIO +#endif + #ifdef FIONBIO - ret=BIO_socket_ioctl(s,FIONBIO,&l); + l = mode; + + ret = BIO_socket_ioctl(s, FIONBIO, &l); +#elif defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(FNDELAY)) + /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */ + + l = fcntl(s, F_GETFL, 0); + if (l == -1) + { + SYSerr(SYS_F_FCNTL, get_last_rtl_error()); + ret = -1; + } + else + { +#if defined(O_NONBLOCK) + l &= ~O_NONBLOCK; +#else + l &= ~FNDELAY; /* BSD4.x */ #endif + if (mode) + { +#if defined(O_NONBLOCK) + l |= O_NONBLOCK; +#else + l |= FNDELAY; /* BSD4.x */ +#endif + } + ret = fcntl(s, F_SETFL, l); + if (ret < 0) + { + SYSerr(SYS_F_FCNTL, get_last_rtl_error()); + } + } +#else + /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */ + + BIOerr(BIO_F_BIO_SOCKET_NBIO, ERR_R_PASSED_INVALID_ARGUMENT); +#endif + return(ret == 0); } ======================================================================= --- h:\prj\1original\openssl\openssl\crypto\err\err.h 2010-05-14 15:32:28.000000000 +-0200 +++ h:\prj\3actual\openssl\crypto\err\err.h 2010-05-01 23:57:30.000000000 +-0200 @@ -306,8 +383,9 @@ -#define ERR_R_INTERNAL_ERROR (4|ERR_R_FATAL) -#define ERR_R_DISABLED (5|ERR_R_FATAL) +#define ERR_R_INTERNAL_ERROR (4 | ERR_R_FATAL) +#define ERR_R_DISABLED (5 | ERR_R_FATAL) +#define ERR_R_PASSED_INVALID_ARGUMENT (6) /* [i_a] this happens everywhere; make one error code for this */ /* 99 is the maximum possible ERR_R_... code, higher values * are reserved for the individual libraries */ typedef struct ERR_string_data_st -- Met vriendelijke groeten / Best regards, Ger Hobbelt -------------------------------------------------- web: http://www.hobbelt.com/ http://www.hebbut.net/ mail: g...@hobbelt.com mobile: +31-6-11 120 978 --------------------------------------------------patch attached, of course.
Even in UNIX County, ioctl(FIONBIO) isn't everywhere. Let alone abroad.
Since the days of yore OpenSSL has implicitly known this as there exists a BIO_socket_nbio() but since it was far from complete the more or less complete #ifdef portability hacks litter the codebase.
This patch ensures toggling the socket nonblocking option works on all platforms which are supported by OpenSSL -- in fact, the edits are a mix of those hacks mentioned above and checking them against the man pages or other documentation available for various platforms. I'm not entirely sure about the VMS tweak, but it's in the OpenSSL codebase elsewhere, so it is included here as well.
The patch/diff files for the various apps/*, etc. spots will follow later with this PR. This one can be done without fixing those yet, so we can 'upgrade' in two easy stages in this PR. (Or do you prefer multiple PRs for this? It's a basic change, so from that perspective doesn't merit multiple PR#s IMO.)
One note:
- BIO_F_BIO_SOCKET_NBIO is new so the mkerr.pl perl script must be run to update the error section(s) in the header file(s).
- ERR_R_PASSED_INVALID_ARGUMENT is a new code; its usefulness reaches beyond this simple patch as there are several places in OpenSSL where the various subsystems (BIO, EVP, ENGINE) use their own equivalent code; using this 'global spanning' ERR_-based error code cuts down on error code duplication; besides that, it's not a BIO specific error, so making it BIO_R_PASSED_INVALID_ARGUMENT is nonsense; this kind of error is 'generic' in that it is due to the caller, i.e. user of the subsystem and not dependent on the subsystem per se.
The relevant edit for err/err.h is shown at the bottom of this message (included as separate attachment for your convenience).
--- h:\prj\1original\openssl\openssl\crypto\bio\b_sock.c 2010-05-14 15:18:09.000000000 +-0200
+++ h:\prj\3actual\openssl\crypto\bio\b_sock.c 2010-05-20 00:03:33.000000000 +-0200
@@ -927,15 +1007,57 @@
return(ret == 0);
}
#endif
int BIO_socket_nbio(int s, int mode)
{
- int ret= -1;
+ int ret = -1;
int l;
- l=mode;
+#if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000)
+/* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */
+#undef FIONBIO
+#endif
+
#ifdef FIONBIO
- ret=BIO_socket_ioctl(s,FIONBIO,&l);
+ l = mode;
+
+ ret = BIO_socket_ioctl(s, FIONBIO, &l);
+#elif defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(FNDELAY))
+ /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
+
+ l = fcntl(s, F_GETFL, 0);
+ if (l == -1)
+ {
+ SYSerr(SYS_F_FCNTL, get_last_rtl_error());
+ ret = -1;
+ }
+ else
+ {
+#if defined(O_NONBLOCK)
+ l &= ~O_NONBLOCK;
+#else
+ l &= ~FNDELAY; /* BSD4.x */
#endif
+ if (mode)
+ {
+#if defined(O_NONBLOCK)
+ l |= O_NONBLOCK;
+#else
+ l |= FNDELAY; /* BSD4.x */
+#endif
+ }
+ ret = fcntl(s, F_SETFL, l);
+ if (ret < 0)
+ {
+ SYSerr(SYS_F_FCNTL, get_last_rtl_error());
+ }
+ }
+#else
+ /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
+
+ BIOerr(BIO_F_BIO_SOCKET_NBIO, ERR_R_PASSED_INVALID_ARGUMENT);
+#endif
+
return(ret == 0);
}
=======================================================================
--- h:\prj\1original\openssl\openssl\crypto\err\err.h 2010-05-14 15:32:28.000000000 +-0200
+++ h:\prj\3actual\openssl\crypto\err\err.h 2010-05-01 23:57:30.000000000 +-0200
@@ -306,8 +383,9 @@
-#define ERR_R_INTERNAL_ERROR (4|ERR_R_FATAL)
-#define ERR_R_DISABLED (5|ERR_R_FATAL)
+#define ERR_R_INTERNAL_ERROR (4 | ERR_R_FATAL)
+#define ERR_R_DISABLED (5 | ERR_R_FATAL)
+#define ERR_R_PASSED_INVALID_ARGUMENT (6) /* [i_a] this happens everywhere; make one error code for this */
/* 99 is the maximum possible ERR_R_... code, higher values
* are reserved for the individual libraries */
typedef struct ERR_string_data_st
--
Met vriendelijke groeten / Best regards,
Ger Hobbelt
--------------------------------------------------
web: http://www.hobbelt.com/
http://www.hebbut.net/
mail: g...@hobbelt.com
mobile: +31-6-11 120 978
--------------------------------------------------
openssl_bio_b_sock.diff
Description: Binary data
openssl_err_err_h_generic_6.diff
Description: Binary data