tech-net archive

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

Re: struct sockaddr_storage issues



Sad Clouds <cryintothebluesky%gmail.com@localhost> writes:

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

Generally, sockaddr_storage is used to store sockaddrs, when you don't
know what kind you have.

> 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.

Is any of this specified by POSIX or RFC, and are you sure you are within
the standards?

Do other systems have a problem with using the right type and its
length?

> 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;
> }

I see why you ended up where you did, but it's easy to set a length in
the switch statement.

Attachment: signature.asc
Description: PGP signature



Home | Main Index | Thread Index | Old Index