tech-net archive

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

Re: struct sockaddr_storage issues



On Fri, 23 Dec 2022 13:15:34 -0500
Greg Troxel <gdt%lexort.com@localhost> wrote:

> You left out the likely important part, how you initialized the fields
> in the sockaddr, which needs to actually be of the type corresponding to
> the AF.
> 
> > Is this a NetBSD specific bug, or am I not using sockaddr_storage
> > correctly?
> 
> My guess is that you are doing something that leads to UB, said vaguely
> and broadly.

Hi,

I'm thinking this is either a NetBSD bug or a compatibility issue. I'm
testing this on NetBSD-9.3

The sockaddr_storage structure came after the socket APIs were created,
so may be different systems handle this in slightly different ways.

My thinking was that connect() really should not care about the
exact size of the socket structure, as long as it is greater or equal
to the size required for sa_family_t. So if it is AF_INET then size
has to be at least sizeof(struct sockaddr_in), if it is AF_INET6,
then size has to be at lease sizeof(struct sockaddr_in6), etc.

I try to write portable code for Linux, *BSD, Solaris, etc. I can't
think of a valid reason why connect() should fail for AF_INET with
larger socket structure, like sockaddr_storage, especially when it
is supported in NetBSD system headers.

Below is fragment of my code that initializes socket address before
calling connect(). Various error checking is omitted for readability.


sa_family_t             sa_family = 0;
struct in_addr          addr_ipv4;
struct in6_addr         addr_ipv6;
in_port_t               port = 0;
struct sockaddr_storage addr;

/* Specific IPv4 address */
else if ((int_val = inet_pton(AF_INET, val, &addr_ipv4)) == 1)
{
	sa_family = AF_INET;
}
/* Specific IPv6 address */
else if ((int_val = inet_pton(AF_INET6, val, &addr_ipv6)) == 1)
{
	sa_family = AF_INET6;
}

/* Set port number */
port = htons((uint16_t)u64);

/* Fill sockaddr_storage structure based on sa_family */
if (sa_family == AF_INET)
{
	((struct sockaddr_in *)&addr)->sin_family = sa_family;
	((struct sockaddr_in *)&addr)->sin_port = port;
	((struct sockaddr_in *)&addr)->sin_addr = addr_ipv4;
}
else if (sa_family == AF_INET6)
{
	((struct sockaddr_in6 *)&addr)->sin6_family = sa_family;
	((struct sockaddr_in6 *)&addr)->sin6_port = port;
	((struct sockaddr_in6 *)&addr)->sin6_addr = addr_ipv6;
}


Home | Main Index | Thread Index | Old Index