Discussion:
fix malfunction of socket functions on HP-UX in 64-bit mode
Bruno Haible
2018-01-27 10:17:49 UTC
Permalink
On 64-bit HP-UX, socklen_t is defined as the 64-bit type 'size_t';
however the system calls getsockname() etc. read only the first 32 bits
from &addr_len. Because the endianness is BIG_ENDIAN, this reads as 0,
and thus these system calls don't fill in an address in the supplied
buffer (but nevertheless return 0). This problem is known to HP for
15 years [1]. Their response is described in "man xopen_networking" [2].

Namely, they first provided a fix that consists in linking with -lxnet.
Then they realized that this approach breaks all code (e.g. in libraries)
that assumes that the functions take an 'int *' (old BSD convention)
rather than a 'socklen_t *'.

So they now provide a different fix, namely wrappers called _xpg_getsockname
etc., which is enabled by defining the macro _HPUX_ALT_XOPEN_SOCKET_API.

But they don't enable this second fix by default!!

This fix works only when the appropriate feature macros are defined, but this
is not a problem in practice:
- If you use CC="cc +DD64 -AC99", the compiler will add -D_HPUX_SOURCE=1
by default.
- If you use CC="cc +DD64 -AC99 -D_XOPEN_SOURCE=500", the compiler will
automatically add -D_HPUX_SOURCE=1 -D_XOPEN_SOURCE_EXTENDED

Here's what I'm committing for gnulib:
1) A test case for getsockname() that highlights the problem: It fails
on HP-UX in 64-bit mode (but succeeds in 32-bit mode).
2) A modification of the 'extensions' module to define the
_HPUX_ALT_XOPEN_SOCKET_API macro.

With this fix, the getsockname test now works also in 64-bit mode.

[1] https://marc.info/?l=hpux-devtools&m=106742181731126&w=2
[2] https://support.hpe.com/hpsc/doc/public/display?docId=emr_na-c02281864
Tom G. Christensen
2018-04-24 16:40:01 UTC
Permalink
Post by Bruno Haible
1) A test case for getsockname() that highlights the problem: It fails
on HP-UX in 64-bit mode (but succeeds in 32-bit mode).
This testcase uses SO_REUSEPORT which is not available everywhere.

From Solaris 9:
test-getsockname.c: In function 'open_server_socket':
test-getsockname.c:43:30: error: 'SO_REUSEPORT' undeclared (first use in
this function)
setsockopt (s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof (x));
^
test-getsockname.c:43:30: note: each undeclared identifier is reported
only once for each function it appears in


Perhaps it could use SO_REUSEADDR on systems lacking SO_REUSEPORT?

-tgc
Bruno Haible
2018-04-24 18:08:45 UTC
Permalink
Post by Tom G. Christensen
This testcase uses SO_REUSEPORT which is not available everywhere.
test-getsockname.c:43:30: error: 'SO_REUSEPORT' undeclared (first use in
this function)
setsockopt (s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof (x));
^
test-getsockname.c:43:30: note: each undeclared identifier is reported
only once for each function it appears in
Thanks for the report. This should fix it:


2018-04-24 Bruno Haible <***@clisp.org>

sys_socket: Make SO_REUSEPORT available across platforms.
Reported by Tom G. Christensen <***@jupiterrise.com>.
* lib/sys_socket.in.h (SO_REUSEPORT): New macro.
* doc/posix-headers/sys_socket.texi: Mention the issue.
* tests/test-poll.c (SO_REUSEPORT): Remove.
* tests/test-select.h: Include <sys/socket.h>.
(SO_REUSEPORT): Remove.
* modules/select-tests (Depends-on): Add 'sys_socket'.

diff --git a/lib/sys_socket.in.h b/lib/sys_socket.in.h
index 7102588..cbaf5cf 100644
--- a/lib/sys_socket.in.h
+++ b/lib/sys_socket.in.h
@@ -215,6 +215,15 @@ struct msghdr {

#endif

+/* Ensure SO_REUSEPORT is defined. */
+/* For the subtle differences between SO_REUSEPORT and SO_REUSEADDR, see
+ https://stackoverflow.com/questions/14388706/socket-options-so-reuseaddr-and-so-reuseport-how-do-they-differ-do-they-mean-t
+ and https://lwn.net/Articles/542629/
+ */
+#ifndef SO_REUSEPORT
+# define SO_REUSEPORT SO_REUSEADDR
+#endif
+
/* Fix some definitions from <winsock2.h>. */

#if @HAVE_WINSOCK2_H@
diff --git a/doc/posix-headers/sys_socket.texi b/doc/posix-headers/sys_socket.texi
index 380a0ae..3144ae2 100644
--- a/doc/posix-headers/sys_socket.texi
+++ b/doc/posix-headers/sys_socket.texi
@@ -32,6 +32,9 @@
The @code{CMSG_SPACE} and @code{CMSG_LEN} macros are not provided on some
platforms:
OpenVMS.
+@item
+This header file does not define the @code{SO_REUSEPORT} macro on some platforms:
+Minix 3.1.8, Solaris 10, Cygwin, mingw, MSVC 14.
@end itemize

Portability problems not fixed by Gnulib:
diff --git a/tests/test-poll.c b/tests/test-poll.c
index c5e0a92..ebace0f 100644
--- a/tests/test-poll.c
+++ b/tests/test-poll.c
@@ -52,10 +52,6 @@ SIGNATURE_CHECK (poll, int, (struct pollfd[], nfds_t, int));
#include <sys/wait.h>
#endif

-#ifndef SO_REUSEPORT
-#define SO_REUSEPORT SO_REUSEADDR
-#endif
-
#define TEST_PORT 12345


diff --git a/tests/test-select.h b/tests/test-select.h
index d751e42..364687b 100644
--- a/tests/test-select.h
+++ b/tests/test-select.h
@@ -18,6 +18,7 @@

#include <stdio.h>
#include <string.h>
+#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
@@ -37,10 +38,6 @@
# include <sys/wait.h>
#endif

-#ifndef SO_REUSEPORT
-# define SO_REUSEPORT SO_REUSEADDR
-#endif
-
#define TEST_PORT 12345


diff --git a/modules/select-tests b/modules/select-tests
index bd7b731..899b50c 100644
--- a/modules/select-tests
+++ b/modules/select-tests
@@ -10,6 +10,7 @@ tests/test-select-stdin.c

Depends-on:
stdbool
+sys_socket
netinet_in
arpa_inet
unistd
Tom G. Christensen
2018-04-25 16:21:54 UTC
Permalink
Post by Tom G. Christensen
This testcase uses SO_REUSEPORT which is not available everywhere.
test-getsockname.c:43:30: error: 'SO_REUSEPORT' undeclared (first use in
this function)
setsockopt (s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof (x));
^
test-getsockname.c:43:30: note: each undeclared identifier is reported
only once for each function it appears in
<snip>

Confirmed, thanks!

-tgc

Loading...