Darren Reed wrote:
> On 28/07/10 05:09 AM, James Carlson wrote:
>> Darren Reed wrote:
>>   
>>> On 27/07/10 01:47 PM, James Carlson wrote:
>>>     
>>>> ...
>>>> BSD has for decades provided sa_len, so you don't have to guess at how
>>>> long your sockaddrs really are.  Solaris does not, and there's weird
>>>> (and fragile) switch (sa.sa_family) in every application that has to
>>>> deal with routing socket messages.
>>>>
>>>>        
>>> Something that has been floated about, from time to time,
>>> is making sa_family_t an 8bit type rather than the current
>>> 16bit type and using the other 8 bits for sa_len. If done
>>> such that the ordering of the fields is different for x86 and
>>> sparc then there should be few (if any) binary compatibility
>>> issues.
>>>      
>> That's (unfortunately) not really true.  If you receive a routing socket
>> message with flags in rtm_addrs, you need to look at the sockaddrs that
>> follow for each flag set.  One of the first things an application will
>> do with that message will be to read sa_family from those sockaddrs that
>> follow the rt_msghdr, which means dereferencing and switching on the
>> first *two* bytes of the structure.
>>    Those existing applications are already compiled using the old
>> sockaddr
>> definition, and they will always read the first two bytes as being the
>> family.  They can't be told not to read both bytes without a recompile.
>>   If you redefine one of those bytes to be the length value, then the
>> family number that the application sees will be bogus (e.g., AF 0x1002
>> rather than 2), and the application will fail.
>>    
> 
> I think this is just a case of being strict with what you send
> (i.e. solaris only generates messages with sa_len==0) and
> liberal with what you receive.

I still don't believe that works.

The only place where sa_len is interesting for applications is with the
sockaddrs that follow rt_msghdr, because it's a list with
variable-length elements generated by the kernel, and there's no a
priori way to know how to find the next entry in the list.  The way it's
done today is a mess: applications have to switch on sa_family, then use
sizeof (sockaddr_XXX) to advance the pointer to the next element in the
list.  If you leave out one of the possible sa_family cases from your
switch statement -- or if we add a new one that can be reported -- then
you lose.  You'll have no way to find the next element.  Which means we
can never add a new address family -- or, at least, if we do, we can't
allow it to be leaked into routing socket messages, because it'll break
existing applications.

The other interfaces using sockaddr are boring for applications.
They're either cases where we're sending a sockaddr to the kernel, and
the kernel had darn well better know how big the structure is (e.g.,
connect(3SOCKET)), or we're not going anywhere anyway, or cases where
the kernel is passing back a single buffer, and we have no use at all
for the information (if the kernel copied out something too big for our
buffer, then we're already dead in the water).

So, you can implement this "feature" as you've suggested, but only in
the places where it's uninteresting to do so.  Why bother?  I don't
believe it's really helpful.

BSD bit the bullet back in the 4.2/4.3 time when they just made a binary
incompatible change and went on with it.  At least historically, we've
been unwilling to do the same for Solaris, no matter how broken the old
interface really is.

Again, the reason I mentioned this particular case is that -- like
rtm_flags and rtm_index, and perhaps the long-obsolete rmx_pksent --
there's not much that can be done feasibly to "improve" the interface
without creating a new binary compatible update path or somehow deciding
that incompatibility is "ok."

The long-known work-around for these sorts of problems is quite simple.
 The application just uses the routing socket message as a "hint" that
it should use ioctl() to get the real information.  The message is only
a notification that something has changed.  It's not pretty -- it'd be
nice if the message itself had everything you needed to know -- but it
works reliably.

And, in fact, this usage is _assumed_.  That's why you'll see interface
updates even when it looks like nothing has changed, because it's some
other (possibly invisible) attribute that has actually been changed, and
we're using the dummy routing socket message as a notification to the
application.

-- 
James Carlson         42.703N 71.076W         <carls...@workingcode.com>
_______________________________________________
networking-discuss mailing list
networking-discuss@opensolaris.org

Reply via email to