tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: struct sockaddr_storage issues



> I'm seeing issues on NetBSD where connect() returns error and sets
> errno to "Invalid argument".  [...]

> struct sockaddr_storage addr

> connect(fd, (struct sockaddr *)&addr, sizeof(addr))

> If I replace the above connect() with

> connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr))

> then connect() succeeds.

That last is almost certainly spurious.  Your address family is
probably AF_INET; at least on my systems, sizeof(struct sockaddr)
equals sizeof(struct sockaddr_in).  You really should be using the
correct size for the address family you're using.

On NetBSD, the various sockaddr structs know their sizes; you could use
addr.ss_len.  If, as your remark below implies may be the case, you're
coming from a Linux background, you probably are not aware of this, as
Linux does not have most (all?) of those length fields - it's one of
the more annoying Linuxisms I run into semi-routinely.

> Looks like NetBSD is not happy about the size of struct
> sockaddr_storage.

There's nothing wrong with it, except that it's not correct for the
address family you're using.

> On Linux this works correctly.

It "works", maybe, in that the connection is established.  I would not
say it works correctly; I would say it works incorrectly, that it
connects when it shouldn't.  (I would also say that sin_zero should not
exist in sockaddr_in, but that's a separate rant.)

> sizeof(struct sockaddr)=16
> sizeof(struct sockaddr_storage)=128

> Is this a NetBSD specific bug, or am I not using sockaddr_storage
> correctly?

Closer to the latter, I would say.

I am hardly authoritative on the subject, but my understanding is that
sockaddr_storage exists as an "enough space for any protocol" sockaddr.
(Which it only sort-of is - AF_LOCAL is a semi-exception.)
sizeof(struct sockaddr_storage) is relevant to...just about nothing,
actually, except that it's no smaller than sizeof any of the
AF-specific structs sockaddr (sockaddr_in, sockaddr_in6, sockaddr_iso,
etc).

I do not really understand why the socket calls (bind, accept, etc)
were designed to take length values when the sockaddrs themselves
contain lengths (Linux does not explain; I'm talking about the
pre-Linux days here, when UCB first created sockets).  Perhaps the
*_len fields postdate the API design or something?  Maybe someone who
was involved at the time can speak up on this.

But the upshot is that you really should be using not sizeof(struct
sockaddr_storage) but the AF-specific size value (which in at least one
case - AF_LOCAL - depends on not just the AF but the details of the
address).  That Linux lets you get away with a too-large value is a
Linux bug (or at best misfeature).

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


Home | Main Index | Thread Index | Old Index