According to POSIX 2008, the functions ntohl etc. are defined in <arpa/inet.h> (http://pubs.opengroup.org/onlinepubs/9699919799/functions/htonl.html), which works because they are defined unconditionally there. However, just including <netinet/in.h> should also define them (http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html): > 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>. But ntohl etc are inside a "#if !defined(_KERNEL) && __BSD_VISIBLE" in <netinet/in.h>, violating the "shall be" requirement above. Fix: Guard the definition with __POSIX_VISIBLE >= 200112. 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.
On Sun, 6 Apr 2014, Christian Neukirchen wrote: >> Description: > According to POSIX 2008, the functions ntohl etc. are defined in <arpa/inet.h> (http://pubs.opengroup.org/onlinepubs/9699919799/functions/htonl.html), which works because they are defined unconditionally there. > > However, just including <netinet/in.h> should also define them (http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html): > >> 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 <otherheader.h>"). >> 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. Bruce
On Mon, Apr 07, 2014 at 03:43:44AM +1000, Bruce Evans wrote: > On Sun, 6 Apr 2014, Christian Neukirchen wrote: > >> Description: > > According to POSIX 2008, the functions ntohl etc. are defined in > > <arpa/inet.h> > > (http://pubs.opengroup.org/onlinepubs/9699919799/functions/htonl.html), > > which works because they are defined unconditionally there. > > However, just including <netinet/in.h> should also define them > > (http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html): > >> 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 > <otherheader.h>"). > >> 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. So you propose to change the "#if !defined(_KERNEL) && __BSD_VISIBLE" conditional to "#ifndef _KERNEL"? This affects only old versions of POSIX (where <netinet/in.h> may not be included anyway) and non-POSIX standard C (which does not define <netinet/in.h> either). Note that there are other __POSIX_VISIBLE >= 200112 conditionals in <netinet/in.h>, so the submitter's change may be more consistent, even if it is somehow wrong. -- Jilles Tjoelker
State Changed From-To: open->patched Committed to 11-current, thanks!
Responsible Changed From-To: freebsd-standards->jilles I committed the change. http://www.freebsd.org/cgi/query-pr.cgi?pr=188316 Date: Thu, 29 May 2014 15:23:44 +0000 (UTC)
A commit references this bug: Author: jilles Date: Wed Oct 29 23:10:49 UTC 2014 New revision: 273841 URL: https://svnweb.freebsd.org/changeset/base/273841 Log: MFC r266842: netinet/in.h: Expose htonl(), htons(), ntohl() and ntohs() in strict POSIX mode. Put the htonl(), htons(), ntohl() and ntohs() declarations under __POSIX_VISIBLE >= 200112. POSIX.1-2001 and newer require these to be exposed from <netinet/in.h> (as well as <arpa/inet.h>). Note that it may be unnecessary to check __POSIX_VISIBLE >= 200112 because older versions of POSIX and the C standard do not define this header. However, other places in the same file already perform the check. PR: 188316 Submitted by: Christian Neukirchen Changes: _U stable/10/ stable/10/sys/netinet/in.h