Subject: Re: SUN_LEN() definition change
To: None <tech-kern@NetBSD.ORG>
From: Mike Long <mike.long@analog.com>
List: tech-kern
Date: 02/25/1997 18:39:32
>From: "Chris G. Demetriou" <cgd@CS.cmu.edu>
>Date: Mon, 24 Feb 1997 13:52:46 -0500
>
>> > mikel
>> > Wed Feb 19 22:43:49 PST 1997
>> > Update of /cvsroot/src/sys/sys
>> > In directory netbsd1:/var/slash-tmp/cvs-serv29427/src/sys/sys
>> 
>> > Modified Files:
>> >         un.h 
>> > Log Message:
>> > include terminating null in count returned by SUN_LEN macro; from
>> >   Enami Tsugutomo in PR kern/3035.
>> 
>> Is this really necessary ?
>> 
>> SUN_LEN() definition change implies system call interface change.
>> IMHO, the problem should be fixed on netstat program side, not system
>> call interface side. Please re-think about the fix.
>
>I think that I agree that this should be fixed in netstat.  something
>like "%.*s" should be used to print these, if that's true.

The problem is bigger than that.  To show why, I will have to go into
the history of the sockaddr_un structure.

In older (pre-4.4?) versions of BSD, the sockaddr_un structure looked
like:

struct	sockaddr_un {
	short	sun_family;		/* AF_UNIX */
	char	sun_path[108];		/* path name (gag) */
};

At some point in the development of 4.4BSD it became:

struct	sockaddr_un {
	u_char	sun_len;		/* sockaddr len including null */
	u_char	sun_family;		/* AF_UNIX */
	char	sun_path[104];		/* path name (gag) */
};

(note that all of the sockaddr* structures changed similarly)

First of all, there is a bit of big-endian bias here.  Someone noticed
that the upper half of the *_family member in the sockaddr structures
was unused, and decided to recycle it to store the length.  Old
binaries will still work (implicitly setting *_len to zero), but
*only* on big-endian machines.

The real issue is that since the sun_len member is unique to 4.4BSD-
based systems, very little source code uses it.  I took a quick look
around my system and found quite a few instances of this sort of
thing:

int s;
struct sockaddr_un sun;
...
s = socket(PF_UNIX, ...);
bind(s, &sun, strlen(sun.sun_path) + 2);

Also, third-party code (and even some code in our tree) ignores
sun_len.  Since very little userland code bothers to fill it in, it
cannot be assumed to be valid.  The only reason netstat(8) ever worked
at all is that code inside the kernel appends a null to sun_path.  The
reason you see garbage when you run 'netstat | cat -v' is that (as of
now) the null is stuffed into the wrong location in sun_path.

I'm still unsure what the best solution is.  I think cgd was within
his rights to back out my change to <sys/un.h>, but either SUN_LEN
must be modified, or (more likely) the 'including null' part of that
comment has to go.  I will continue to look into this.
-- 
Mike Long <mike.long@analog.com>     <URL:http://www.shore.net/~mikel>
VLSI Design Engineer         finger mikel@shore.net for PGP public key
Analog Devices, CPD Division          CCBF225E7D3F7ECB2C8F7ABB15D9BE7B
Norwood, MA 02062 USA       (eq (opinion 'ADI) (opinion 'mike)) -> nil