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
>From 46e7ff4afee45c1b2b52849bd36b3b258417ec51 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Sat, 27 Jan 2018 08:52:31 +0100 Subject: [PATCH 1/2] getsockname tests: More tests. * tests/test-getsockname.c (open_server_socket): New function, mostly copied from test-poll.c. (main): Check that getsockname fills in addr. * modules/getsockname-tests (Depends-on): Add the necessary dependencies. (test_getsockname_LDADD): Link with $(INET_PTON_LIB). --- ChangeLog | 10 ++++++++++ modules/getsockname-tests | 10 +++++++++- tests/test-getsockname.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4994460..70d4219 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2018-01-27 Bruno Haible <br...@clisp.org> + + getsockname tests: More tests. + * tests/test-getsockname.c (open_server_socket): New function, mostly + copied from test-poll.c. + (main): Check that getsockname fills in addr. + * modules/getsockname-tests (Depends-on): Add the necessary + dependencies. + (test_getsockname_LDADD): Link with $(INET_PTON_LIB). + 2018-01-26 Paul Eggert <egg...@cs.ucla.edu> manywarnings: fix maintainer comment diff --git a/modules/getsockname-tests b/modules/getsockname-tests index 0134e4c..9141254 100644 --- a/modules/getsockname-tests +++ b/modules/getsockname-tests @@ -5,11 +5,19 @@ tests/macros.h Depends-on: netinet_in +arpa_inet +inet_pton +errno +perror sockets +socket +setsockopt +bind +listen configure.ac: Makefile.am: TESTS += test-getsockname check_PROGRAMS += test-getsockname -test_getsockname_LDADD = $(LDADD) @LIBSOCKET@ +test_getsockname_LDADD = $(LDADD) @LIBSOCKET@ $(INET_PTON_LIB) diff --git a/tests/test-getsockname.c b/tests/test-getsockname.c index 95f2217..2c951fb 100644 --- a/tests/test-getsockname.c +++ b/tests/test-getsockname.c @@ -21,13 +21,47 @@ #include "signature.h" SIGNATURE_CHECK (getsockname, int, (int, struct sockaddr *, socklen_t *)); -#include <errno.h> +#include <stdio.h> +#include <string.h> #include <netinet/in.h> +#include <arpa/inet.h> #include <unistd.h> +#include <errno.h> #include "sockets.h" #include "macros.h" +static int +open_server_socket (void) +{ + int s, x; + struct sockaddr_in ia; + + s = socket (AF_INET, SOCK_STREAM, 0); + + x = 1; + setsockopt (s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof (x)); + + memset (&ia, 0, sizeof (ia)); + ia.sin_family = AF_INET; + inet_pton (AF_INET, "0.0.0.0", &ia.sin_addr); + /* Port 0 means that the system should assign a port. */ + ia.sin_port = htons (0); + if (bind (s, (struct sockaddr *) &ia, sizeof (ia)) < 0) + { + perror ("bind"); + exit (77); + } + + if (listen (s, 1) < 0) + { + perror ("listen"); + exit (77); + } + + return s; +} + int main (void) { @@ -52,5 +86,17 @@ main (void) ASSERT (errno == EBADF); } + /* Test behaviour for a server socket. */ + { + int s = open_server_socket (); + struct sockaddr_in addr; + socklen_t addrlen = sizeof (addr); + + memset (&addr, 0, sizeof (addr)); + ASSERT (getsockname (s, (struct sockaddr *) &addr, &addrlen) == 0); + ASSERT (addr.sin_family == AF_INET); + ASSERT (ntohs (addr.sin_port) != 0); + } + return 0; } -- 2.7.4
>From d4f6a210f44a2bbfedfc60353758c39fb86f8d7a Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Sat, 27 Jan 2018 10:57:59 +0100 Subject: [PATCH 2/2] Fix malfunction of socket functions on HP-UX in 64-bit mode. * m4/socketlib.m4 (gl_SOCKETLIB): Add comment. * m4/extensions.m4 (AC_USE_SYSTEM_EXTENSIONS): Define _HPUX_ALT_XOPEN_SOCKET_API. * modules/accept (Depends-on): Add 'extensions'. * modules/getpeername (Depends-on): Likewise. * modules/getsockname (Depends-on): Likewise. * modules/getsockopt (Depends-on): Likewise. * modules/recvfrom (Depends-on): Likewise. * doc/posix-functions/accept.texi: Mention the HP-UX socklen_t problem. * doc/posix-functions/getpeername.texi: Likewise. * doc/posix-functions/getsockname.texi: Likewise. * doc/posix-functions/getsockopt.texi: Likewise. * doc/posix-functions/recvfrom.texi: Likewise. --- ChangeLog | 17 +++++++++++++++++ doc/posix-functions/accept.texi | 5 +++++ doc/posix-functions/getpeername.texi | 5 +++++ doc/posix-functions/getsockname.texi | 5 +++++ doc/posix-functions/getsockopt.texi | 5 +++++ doc/posix-functions/recvfrom.texi | 5 +++++ m4/extensions.m4 | 8 +++++++- m4/socketlib.m4 | 6 +++++- modules/accept | 1 + modules/getpeername | 1 + modules/getsockname | 1 + modules/getsockopt | 1 + modules/recvfrom | 1 + 13 files changed, 59 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 70d4219..e4e24f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,22 @@ 2018-01-27 Bruno Haible <br...@clisp.org> + Fix malfunction of socket functions on HP-UX in 64-bit mode. + * m4/socketlib.m4 (gl_SOCKETLIB): Add comment. + * m4/extensions.m4 (AC_USE_SYSTEM_EXTENSIONS): Define + _HPUX_ALT_XOPEN_SOCKET_API. + * modules/accept (Depends-on): Add 'extensions'. + * modules/getpeername (Depends-on): Likewise. + * modules/getsockname (Depends-on): Likewise. + * modules/getsockopt (Depends-on): Likewise. + * modules/recvfrom (Depends-on): Likewise. + * doc/posix-functions/accept.texi: Mention the HP-UX socklen_t problem. + * doc/posix-functions/getpeername.texi: Likewise. + * doc/posix-functions/getsockname.texi: Likewise. + * doc/posix-functions/getsockopt.texi: Likewise. + * doc/posix-functions/recvfrom.texi: Likewise. + +2018-01-27 Bruno Haible <br...@clisp.org> + getsockname tests: More tests. * tests/test-getsockname.c (open_server_socket): New function, mostly copied from test-poll.c. diff --git a/doc/posix-functions/accept.texi b/doc/posix-functions/accept.texi index a92ea3f..b1216ee 100644 --- a/doc/posix-functions/accept.texi +++ b/doc/posix-functions/accept.texi @@ -17,6 +17,11 @@ the @code{accept} function cannot be used in calls to @code{read}, On Windows platforms (excluding Cygwin), error codes from this function are not placed in @code{errno}, and @code{WSAGetLastError} must be used instead. +@item +On HP-UX 11, in 64-bit mode, when the macro @code{_HPUX_ALT_XOPEN_SOCKET_API} +is not defined, this function behaves incorrectly because it is declared +to take a pointer to a 64-bit wide @code{socklen_t} entity but in fact +considers it as a pointer to a 32-bit wide @code{unsigned int} entity. @end itemize Portability problems not fixed by Gnulib: diff --git a/doc/posix-functions/getpeername.texi b/doc/posix-functions/getpeername.texi index 5b2776e..8476e0a 100644 --- a/doc/posix-functions/getpeername.texi +++ b/doc/posix-functions/getpeername.texi @@ -12,6 +12,11 @@ Portability problems fixed by Gnulib: On Windows platforms (excluding Cygwin), error codes from this function are not placed in @code{errno}, and @code{WSAGetLastError} must be used instead. +@item +On HP-UX 11, in 64-bit mode, when the macro @code{_HPUX_ALT_XOPEN_SOCKET_API} +is not defined, this function behaves incorrectly because it is declared +to take a pointer to a 64-bit wide @code{socklen_t} entity but in fact +considers it as a pointer to a 32-bit wide @code{unsigned int} entity. @end itemize Portability problems not fixed by Gnulib: diff --git a/doc/posix-functions/getsockname.texi b/doc/posix-functions/getsockname.texi index 7d462a7..714565d 100644 --- a/doc/posix-functions/getsockname.texi +++ b/doc/posix-functions/getsockname.texi @@ -12,6 +12,11 @@ Portability problems fixed by Gnulib: On Windows platforms (excluding Cygwin), error codes from this function are not placed in @code{errno}, and @code{WSAGetLastError} must be used instead. +@item +On HP-UX 11, in 64-bit mode, when the macro @code{_HPUX_ALT_XOPEN_SOCKET_API} +is not defined, this function behaves incorrectly because it is declared +to take a pointer to a 64-bit wide @code{socklen_t} entity but in fact +considers it as a pointer to a 32-bit wide @code{unsigned int} entity. @end itemize Portability problems not fixed by Gnulib: diff --git a/doc/posix-functions/getsockopt.texi b/doc/posix-functions/getsockopt.texi index 9e7d26e..f15c934 100644 --- a/doc/posix-functions/getsockopt.texi +++ b/doc/posix-functions/getsockopt.texi @@ -12,6 +12,11 @@ Portability problems fixed by Gnulib: On Windows platforms (excluding Cygwin), error codes from this function are not placed in @code{errno}, and @code{WSAGetLastError} must be used instead. +@item +On HP-UX 11, in 64-bit mode, when the macro @code{_HPUX_ALT_XOPEN_SOCKET_API} +is not defined, this function behaves incorrectly because it is declared +to take a pointer to a 64-bit wide @code{socklen_t} entity but in fact +considers it as a pointer to a 32-bit wide @code{unsigned int} entity. @end itemize Portability problems not fixed by Gnulib: diff --git a/doc/posix-functions/recvfrom.texi b/doc/posix-functions/recvfrom.texi index f591d0c..251ed5c 100644 --- a/doc/posix-functions/recvfrom.texi +++ b/doc/posix-functions/recvfrom.texi @@ -16,6 +16,11 @@ OSF/1 5.1. On Windows platforms (excluding Cygwin), error codes from this function are not placed in @code{errno}, and @code{WSAGetLastError} must be used instead. +@item +On HP-UX 11, in 64-bit mode, when the macro @code{_HPUX_ALT_XOPEN_SOCKET_API} +is not defined, this function behaves incorrectly because it is declared +to take a pointer to a 64-bit wide @code{socklen_t} entity but in fact +considers it as a pointer to a 32-bit wide @code{unsigned int} entity. @end itemize Portability problems not fixed by Gnulib: diff --git a/m4/extensions.m4 b/m4/extensions.m4 index d1b2321..71a854f 100644 --- a/m4/extensions.m4 +++ b/m4/extensions.m4 @@ -1,4 +1,4 @@ -# serial 17 -*- Autoconf -*- +# serial 18 -*- Autoconf -*- # Enable extensions on systems that normally disable them. # Copyright (C) 2003, 2006-2018 Free Software Foundation, Inc. @@ -118,6 +118,11 @@ dnl configure.ac when using autoheader 2.62. #ifndef _XOPEN_SOURCE # undef _XOPEN_SOURCE #endif +/* Enable X/Open compliant socket functions that do not require linking + with -lxnet on HP-UX 11.11. */ +#ifndef _HPUX_ALT_XOPEN_SOCKET_API +# undef _HPUX_ALT_XOPEN_SOCKET_API +#endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # undef __EXTENSIONS__ @@ -163,6 +168,7 @@ dnl configure.ac when using autoheader 2.62. [ac_cv_should_define__xopen_source=yes])])]) test $ac_cv_should_define__xopen_source = yes && AC_DEFINE([_XOPEN_SOURCE], [500]) + AC_DEFINE([_HPUX_ALT_XOPEN_SOCKET_API]) ])# AC_USE_SYSTEM_EXTENSIONS # gl_USE_SYSTEM_EXTENSIONS diff --git a/m4/socketlib.m4 b/m4/socketlib.m4 index ca240b1..a725d3c 100644 --- a/m4/socketlib.m4 +++ b/m4/socketlib.m4 @@ -1,4 +1,4 @@ -# socketlib.m4 serial 1 +# socketlib.m4 serial 2 dnl Copyright (C) 2008-2018 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -38,6 +38,10 @@ AC_DEFUN([gl_SOCKETLIB], dnl Solaris has most socket functions in libsocket. dnl Haiku has most socket functions in libnetwork. dnl BeOS has most socket functions in libnet. + dnl On HP-UX, do NOT link with libxnet, because in 64-bit mode this would + dnl break code (e.g. in libraries) that invokes accept(), getpeername(), + dnl getsockname(), getsockopt(), or recvfrom() with a 32-bit addrlen. See + dnl "man xopen_networking" for details. AC_CACHE_CHECK([for library containing setsockopt], [gl_cv_lib_socket], [ gl_cv_lib_socket= AC_LINK_IFELSE([AC_LANG_PROGRAM([[extern diff --git a/modules/accept b/modules/accept index 059a56d..b997566 100644 --- a/modules/accept +++ b/modules/accept @@ -6,6 +6,7 @@ lib/accept.c lib/w32sock.h Depends-on: +extensions sys_socket socketlib errno [test "$ac_cv_header_winsock2_h" = yes] diff --git a/modules/getpeername b/modules/getpeername index d1ef822..53f077b 100644 --- a/modules/getpeername +++ b/modules/getpeername @@ -7,6 +7,7 @@ lib/getpeername.c lib/w32sock.h Depends-on: +extensions sys_socket socketlib errno [test "$ac_cv_header_winsock2_h" = yes] diff --git a/modules/getsockname b/modules/getsockname index 15cf490..8a8ffe0 100644 --- a/modules/getsockname +++ b/modules/getsockname @@ -7,6 +7,7 @@ lib/getsockname.c lib/w32sock.h Depends-on: +extensions sys_socket socketlib errno [test "$ac_cv_header_winsock2_h" = yes] diff --git a/modules/getsockopt b/modules/getsockopt index 1cd1f2e..adb4b87 100644 --- a/modules/getsockopt +++ b/modules/getsockopt @@ -6,6 +6,7 @@ lib/getsockopt.c lib/w32sock.h Depends-on: +extensions sys_socket socketlib sys_time [test "$ac_cv_header_winsock2_h" = yes] diff --git a/modules/recvfrom b/modules/recvfrom index 2b051b4..590f6fe 100644 --- a/modules/recvfrom +++ b/modules/recvfrom @@ -6,6 +6,7 @@ lib/recvfrom.c lib/w32sock.h Depends-on: +extensions sys_socket socketlib errno [test "$ac_cv_header_winsock2_h" = yes] -- 2.7.4