standards/188316: Visibility of ntohl etc. and POSIX 2008

Bruce Evans brde at
Sun Apr 6 17:43:57 UTC 2014

On Sun, 6 Apr 2014, Christian Neukirchen wrote:

>> Description:
> According to POSIX 2008, the functions ntohl etc. are defined in <arpa/inet.h> (, which works because they are defined unconditionally there.
> However, just including <netinet/in.h> should also define them (
>> The htonl(), htons(), ntohl(), and ntohs() functions shall be available
>> as described in <arpa/inet.h>. Inclusion of the <netinet/in.h> header may
>> also make visible all symbols from <arpa/inet.h>.

POSIX.1-2001 also says this.

> But ntohl etc are inside a "#if !defined(_KERNEL) && __BSD_VISIBLE" in <netinet/in.h>, violating the "shall be" requirement above.

The requirement was somehow missed before.  Probably due to its bad wording.
The bad wording "shall be available" is only used for namespaces twice in
POSIX.1-2001-draft7 (for {h_errno} in <netdb.h> and for {ntoh*} in
<netinet/in.h>.  The normal wording is "shall be defined as described in

>> How-To-Repeat:
> echo '#include <arpa/inet.h>\nint main(){htonl(1);}' | cc -D_XOPEN_SOURCE=700 -x c -
> (all good)
> echo '#include <netinet/in.h>\nint main(){htonl(1);}' | cc -D_XOPEN_SOURCE=700 -x c -
> <stdin>:2:12: warning: implicit declaration of function 'htonl' is invalid in C99 [-Wimplicit-function-declaration]
> int main(){htonl(1);}
>           ^
> 1 warning generated.
>> Fix:
> Guard the definition with __POSIX_VISIBLE >= 200112.

This is wrong too, and is inconsistent with <arpa/inet.h> where there
the symbols are defined unconditionally (if this wouldn't be redundant).
The correctness of this depends on the symbols being in a header that
doesn't exist in versions of POSIX that don't have the symbols.  I
think it is indeed correct, because POSIX started specifying both the
symbols and the headers in 2001.  Howver, the unconditional declarations
may be wrong for XSI, and aren't really right for BSD.  In 4.4BSD, they
were declared unconditionally in <sys/types.h> via nested pollution from
<machine/endian.h>, and were only declared in the POSIX headers as a
side effect of these headers being broken unless the application included
<sys/types.h>.  Similarly in FreeBSD-1 (and Net/2?).  Applications written
for this polluted API are no longer supported.  However, the documented
API (byteorder.3) was that these functions are declared in <sys/param.h>.
It is now that these functions are declared in the 2 POSIX headers.

In the kernel, the ntoh* family is still declared in <sys/param.h>, but
this is misdocumented in byteorder.9 which says that these functions
are declared in <sys/endian.h>.  <sys/endian.h> actually declares almost
all official endianness-related functions except these.  <sys/endian.h>
and presumably all the functions of it are not documented in any application
man page.

mips still has bogus ntoh* functions in libc in asm.


More information about the freebsd-standards mailing list