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
--------------------------------------------------

Attachment: openssl_bio_b_sock.diff
Description: Binary data

Attachment: openssl_err_err_h_generic_6.diff
Description: Binary data

Reply via email to