Anonymous | Login | 2024-09-07 15:01 UTC |
Main | My View | View Issues | Change Log | Docs |
Viewing Issue Simple Details [ Jump to Notes ] | [ Issue History ] [ Print ] | ||||||
ID | Category | Severity | Type | Date Submitted | Last Update | ||
0000978 | [1003.1(2008)/Issue 7] Base Definitions and Headers | Editorial | Enhancement Request | 2015-08-21 20:54 | 2024-06-11 08:52 | ||
Reporter | EdSchouten | View Status | public | ||||
Assigned To | ajosey | ||||||
Priority | normal | Resolution | Accepted As Marked | ||||
Status | Closed | ||||||
Name | Ed Schouten | ||||||
Organization | Nuxi | ||||||
User Reference | |||||||
Section | <sys/socket.h> | ||||||
Page Number | n/a | ||||||
Line Number | n/a | ||||||
Interp Status | --- | ||||||
Final Accepted Text | Note: 0003242 | ||||||
Summary | 0000978: Please add CMSG_LEN() and CMSG_SPACE(). | ||||||
Description |
Most implementations provide the macros CMSG_LEN() and CMSG_SPACE(). These are quite important when constructing space to store control messages. This is why they are part of RFC 2292: https://tools.ietf.org/html/rfc2292#section-4.3 [^] POSIX issue 7 only seems to standardize CMSG_DATA(), CMSG_NXTHDR() and CMSG_FIRSTHDR(). Would it make sense to sync up with RFC 2292? |
||||||
Desired Action | Add CMSG_LEN() and CMSG_SPACE(). This will allow programmers to finally construct buffers for control messages in a portable way. | ||||||
Tags | issue8 | ||||||
Attached Files | |||||||
|
Relationships | ||||||
|
Notes | |
(0002805) wahern (reporter) 2015-09-01 18:09 |
My porting notes show that CMSG_SPACE expanded to a non-constant expression on NetBSD 5.1.2 and OS X 10.7. But, notably, in the latest NetBSD and OS X releases it now expands to a constant expression. I ran into this issue because I was originally using CMSG_SPACE to define a C99 compound literal. It would be useful if these were defined to expand to constant expressions. Another interesting issue I have documented is the type of .msg_iovlen in struct msghdr. It's defined as size_t in glibc and RFC2292, unsigned on OpenBSD, and int everywhere else I checked. The POSIX standard defines it as int, although I guess it's not entirely clear that the language mandates the type as well as the member. I mention this because it might be worthwhile to consider specifying the type of the CMSG_SPACE and CMSG_LEN expressions (e.g. socklen_t to match .msg_controllen and .cmsg_len), especially if they're not required to expand to constant expressions. Otherwise compilers might emit conversion warnings, as the obvious implementations will result in a type of size_t. |
(0002807) shware_systems (reporter) 2015-09-03 07:11 |
For msg_iovlen, I read it as the count of members in the array msg_iov points to, so int is appropriate. The description is missing "count of", though, so some implementers may construe it being the total size of the array, with count being derived via msg_iovlen/sizeof(struct iovec), and would be consistent with the definition of the iovec structure. The use of size_t as the type of iovec.iovlen in <uio.h> is appropriate as it references the size allocated to the buffer pointed to by each entry. The use of signed int is normative, however, so bug reports should be filed with glibc and OpenBSD alerting them to it, imo. - As I read the RFC and C99TC3, CMSG_LEN is superfluous. The C standard explicitly requires sizeof() to account for any implicit tail padding of structures the compiler may generate, so CMSG_LEN() and CMSG_SPACE() should return equal values when based on sizeof(struct cmsg_hdr). CMSG_SPACE is not, to account for the different methods a conforming compiler may use to allocate a char array without attempting an allocation of the array as an automatic variable. I can see them evaluating to a compile time constant expression only if cmsg_data is declared a static array size, not a variable sized one or left undefined. I concur with it be explicit socklen_t is used as return type, similar to CMSG_DATA requiring (unsigned char*). |
(0002808) philip-guenther (reporter) 2015-09-03 08:38 |
> As I read the RFC and C99TC3, CMSG_LEN is superfluous. The C standard explicitly requires > sizeof() to account for any implicit tail padding of structures the compiler may generate, > so CMSG_LEN() and CMSG_SPACE() should return equal values when based on sizeof(struct cmsg_hdr). At least on traditional BSD implementations, if the buffer holding the control msg is allocated with, e.g., malloc(), then the pointer returned by CMSG_DATA() will be sufficiently aligned for any control data passed by the system. This matters when the alignment required by cmsghdr is less than the system's maximum alignment. For example, consider a system where * cmsghdr only requires 4 byte alignment, * sizeof(struct cmsghdr) == 12, * long long objects require 8 byte alignment, and * there's a control message containing a long long. In order for CMSG_DATA() to return a pointer that is aligned for accessing a long long, there must be 4 bytes of padding between the cmsghdr and the actual data, and CMSG_DATA() and CMSG_ALIGN() must round up sizeof(struct cmsgmdr) to a multiple of the max alignment required by a control message. This exact situation occurs on OpenBSD on most archs with the SCM_TIMESTAMP cmsg which passes a struct timeval, since time_t is long long on OpenBSD. If the spec doesn't currently require the pointer returned by CMSG_DATA() to be aligned sufficiently for all the cmsg structures supported by the system, then I would argue that's a defect in the standard: the code I've seen seems to assume that and does *not* copy the CMSG_DATA() to an aligned buffer before accessing it. e.g, ntp.org's ntpd, ISC bind |
(0003241) shware_systems (reporter) 2016-06-02 15:48 |
Re: 2808 Alignment issues with casting to another structure the unsigned char array CMSG_DATA() points to, it is up to the implementation to prefix a dummy field to that structure, nominally via an #ifdef that references the compilation environment #defines, that would force the alignment. It is not the compiler's job, or the standard's imo, to require a larger alignment than char as a result. |
(0003242) geoffclare (manager) 2016-06-02 16:40 edited on: 2016-06-09 15:07 |
On page 386 line 12945 section <sys/socket.h> add to CMSG_NXTHDR:If the first argument is a pointer to a msghdr structure and the second argument is a null pointer, this macro shall be equivalent to CMSG_FIRSTHDR(mhdr). On page 386 line 12949 section <sys/socket.h> add to the list of macros: CMSG_SPACE(length) If the argument has a type such that its value can be assigned to an object of type socklen_t, this macro shall return the space required by an ancillary data object of the specified length and its cmsghdr structure, including any padding needed to satisfy alignment requirements. This macro can be used, for example, to allocate space dynamically for the ancillary data. This macro should not be used to initialize the cmsg_len member of a cmsghdr structure. If the argument is an integer constant expression, this macro shall expand to an integer constant expression.CMSG_LEN(length) If the argument has a type such that its value can be assigned to an object of type socklen_t, this macro shall return the value to store in the cmsg_len member of the cmsghdr structure for an ancillary data object of the specified length, taking into account any padding needed to satisfy alignment requirements. If the argument is an integer constant expression, this macro shall expand to an integer constant expression. |
(0003243) EdSchouten (updater) 2016-06-03 08:04 |
In response to comment 2808: An in my opinion elegant way of solving that problem would be to declare struct cmsghdr as follows: struct cmsghdr { socklen_t cmsg_len; int cmsg_level; int cmsg_type; _Alignas(max_align_t) unsigned char __cmsg_data[]; }; That way you can be certain that any properly aligned cmsghdr is also capable of storing any piece of data with the correct alignment. |
(0003244) EdSchouten (updater) 2016-06-03 09:08 |
Quick question in response comment 3242: I can understand why CMSG_LEN() should return a socklen_t, as it needs to be assignable to cmsg_len. For CMSG_SPACE(), however, wouldn't it make more sense to return size_t? That's a value that is typically used for array sizes, or to be passed to malloc(). |
(0003245) shware_systems (reporter) 2016-06-03 13:10 |
It's for consistency, and the range of socklen_t can be less than that of size_t. It avoids potential overflow casting a size_t set arbitrarily large to other socklen_t parameters, iow. |
(0004884) eblake (manager) 2020-06-04 12:38 |
This is an interesting thread on a portability pitfall between Linux and OmniOS handling message length differently: https://gitlab.freedesktop.org/dbus/dbus/-/issues/304 [^] Among other things, the thread suggests that perhaps we need to change wording along the lines: CMSG_DATA(cmsg): If the argument is a pointer to a cmsghdr structure, this macro shall return an unsigned character pointer to the data array associated with the cmsghdr structure. The data array has length cmsg->cmsg_len - CMSG_LEN (0). |
(0004885) geoffclare (manager) 2020-06-04 13:45 |
Re: Note: 0004884, since this bug has already been applied, any additional changes will need to be done via a separate bug (either against the current standard or against Issue 8 draft 1 once it is out). |
Issue History | |||
Date Modified | Username | Field | Change |
2015-08-21 20:54 | EdSchouten | New Issue | |
2015-08-21 20:54 | EdSchouten | Status | New => Under Review |
2015-08-21 20:54 | EdSchouten | Assigned To | => ajosey |
2015-08-21 20:54 | EdSchouten | Name | => Ed Schouten |
2015-08-21 20:54 | EdSchouten | Organization | => Nuxi |
2015-08-21 20:54 | EdSchouten | Section | => <sys/socket.h> |
2015-08-21 20:54 | EdSchouten | Page Number | => n/a |
2015-08-21 20:54 | EdSchouten | Line Number | => n/a |
2015-08-25 22:01 | shware_systems | Issue Monitored: shware_systems | |
2015-08-25 22:06 | shware_systems | Issue End Monitor: shware_systems | |
2015-09-01 18:09 | wahern | Note Added: 0002805 | |
2015-09-03 07:11 | shware_systems | Note Added: 0002807 | |
2015-09-03 08:38 | philip-guenther | Note Added: 0002808 | |
2016-06-02 15:48 | shware_systems | Note Added: 0003241 | |
2016-06-02 16:40 | geoffclare | Note Added: 0003242 | |
2016-06-03 08:04 | EdSchouten | Note Added: 0003243 | |
2016-06-03 09:08 | EdSchouten | Note Added: 0003244 | |
2016-06-03 13:10 | shware_systems | Note Added: 0003245 | |
2016-06-09 15:07 | nick | Interp Status | => --- |
2016-06-09 15:07 | nick | Final Accepted Text | => bugnote: 3242 |
2016-06-09 15:07 | nick | Status | Under Review => Resolved |
2016-06-09 15:07 | nick | Resolution | Open => Accepted As Marked |
2016-06-09 15:07 | geoffclare | Note Edited: 0003242 | |
2016-06-09 15:08 | nick | Final Accepted Text | bugnote: 3242 => Note: 0003242 |
2016-06-09 15:08 | nick | Tag Attached: issue8 | |
2020-04-08 15:35 | geoffclare | Status | Resolved => Applied |
2020-04-16 09:04 | geoffclare | Relationship added | related to 0001056 |
2020-06-04 12:38 | eblake | Note Added: 0004884 | |
2020-06-04 13:45 | geoffclare | Note Added: 0004885 | |
2024-06-11 08:52 | agadmin | Status | Applied => Closed |
Mantis 1.1.6[^] Copyright © 2000 - 2008 Mantis Group |