Bug 188316 - [headers] Visibility of ntohl etc. and POSIX 2008
Summary: [headers] Visibility of ntohl etc. and POSIX 2008
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: standards (show other bugs)
Version: 10.0-RELEASE
Hardware: Any Any
: Normal Affects Only Me
Assignee: Jilles Tjoelker
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-04-06 15:40 UTC by chneukirchen
Modified: 2014-11-02 14:26 UTC (History)
0 users

See Also:
jilles: mfc-stable10+
jilles: mfc-stable9-
jilles: mfc-stable8-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description chneukirchen 2014-04-06 15:40:00 UTC
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.
Comment 1 Bruce Evans freebsd_committer freebsd_triage 2014-04-06 18:43:44 UTC
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
Comment 2 Jilles Tjoelker freebsd_committer freebsd_triage 2014-05-18 22:50:50 UTC
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
Comment 3 Jilles Tjoelker freebsd_committer freebsd_triage 2014-05-29 16:26:56 UTC
State Changed
From-To: open->patched

Committed to 11-current, thanks! 


Comment 4 Jilles Tjoelker freebsd_committer freebsd_triage 2014-05-29 16:26:56 UTC
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)
Comment 5 commit-hook freebsd_committer freebsd_triage 2014-10-29 23:11:18 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