Subject: Re: CMSG_* problems
To: None <tech-userlevel@NetBSD.org, tech-kern@NetBSD.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: tech-userlevel
Date: 02/13/2007 02:43:32
>> This feels a lot like pushback against my proposal, but nobody has
>> actually come right out and said "no, I don't like this", much less
>> "...and here's why".
> Proposals to change RFC-defined interfaces rarely meet with immediate
> universal acclamation.  ;-)

True enough, but what I'm seeing feels very different to me from
something like "regardless of all this, I'm very hesitant to mess with
something already cast into an RFC".  (In which case I'd point out that
I'm not proposing to change anything specified in 2292; everything
specified there would, were I to get my way, work just as it always
did.  All I propose doing is adding two additional macros, to make it
possible to write in a coding style I find significantly cleaner than
the one the existing macros are designed for.)

> I think you'd agree, assuming it can be made to work, that iterating
> over a series of pointers is preferable to grabbing chunks of data at
> offsets.

Consider the example from 2292:

    for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
         cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
        if (cmsgptr->cmsg_level == ... && cmsgptr->cmsg_type == ... ) {
            u_char  *ptr;

            ptr = CMSG_DATA(cmsgptr);
            /* process data pointed to by ptr */
        }
    }

I would very much prefer to write this as something more like

	dp = mh.msg_control;
	o = 0;
	while (o < mh.msg_controllen)
	 { if (o+sizeof(struct cmsghdr) > mh.msg_controllen) { error }
	   bcopy(dp+o,&cmh,sizeof(struct cmsghdr));
	   if (o+cmh.cmsg_len > mh.msg_controllen) { error }
	   ...check cmh.cmsg_level and/or cmh.cmsg_type...
	   bcopy(dp+o+CMSG_DATASKIP(&cmh),...,
		cmh.cmsg_len-CMSG_DATASKIP(&cmh));
	   ...process the copied-out data...
	   o += CMSG_NXTSKIP(&cmh);
	 }

(or you can skip the error tests in the loop, since the suggested
implementation of CMSG_NXTHDR in 2292 effectively does).

Does this mean I agree?  I think "no", but I'm not sure.

Indeed, when I've had to manipulate control data buffers that's what
I've done, except that I've had to kludge around the lack of
CMSG_DATASKIP and CMSG_NXTSKIP.

In particular, this can be done in a library routine without having to
impose alignment restrictions on its client.  (And if it takes a
half-dozen go-rounds for *us* to figure out how to get alignment right,
how much chance does the typical app author have?  Especially since
"the typical app author" probably writes on the i386 port, on which you
*don't* have to get alignment right and the code will thus "work" even
if it's broken?)

> Do you think that assumption is acceptable?  Would documenting and
> relying on intmax_t alignment suffice?

Suffice for what?  It would certainly be better than what we have now,
but given the current lack of documentation that's not saying much.  It
would not suffice for my own use; if that's all that's done, I'll
continue kludging around the lack of the macros I want the ways I have
been.  They depend on a nonportability (pointers past the ends of
objects, usually), but I consider them preferable to - cleaner and far
less fragile than - overlaying the cmsghdr and data onto the
control-message buffer.

/~\ The ASCII				der Mouse
\ / Ribbon Campaign
 X  Against HTML	       mouse@rodents.montreal.qc.ca
/ \ Email!	     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B