I've a sockaddr_storage object and I need to fill it with values provided by the user. Note that user can provide either of AF_INET
or AF_INET6
as domain for filling up the struct.
void fill(sockaddr_storage &addrStruct, int domain,
const char addr[], const int port)
{
std::memset(&addrStruct, 0, sizeof(addrStruct));
switch(domain) {
case AF_INET: addrStruct.sin_family = AF_INET;
addrStruct.sin_port= htons(port);
inet_pton(AF_INET, addr, addrStruct.sin_addr);
case AF_INET6: ....
....
....
default: ....
}
}
Pretty sure this doesn't works since addrStruct
is of type struct sockaddr_storage
and these members are present in struct sockaddr_in
. I also tried static_cast<sockaddr_in>(addrStruct).sin_port
and similar but that again doesn't works. So how should I be filling up this struct so that it holds valid values while respecting alignment of casted structs.
You have to do reinterpret cast of
addrStruct
tosockaddr_in
. In your case the code will look as following:But I recommend you to use
getaddrinfo(3)
instead your approach.It is almost always better to use getaddrinfo than the
inet_*
family of address conversion functions. It does all of the allocation and initialization ofsockaddr
objects for you—you don't have to mess withsockaddr_storage
yourself. It handles IPv4 and IPv6 seamlessly, it handles "multihomed" hosts with more than one address, and it can (optionally) do DNS lookups.To use
getaddrinfo
, you completely throw away thefill
function that you showed. The code that usesfill
probably looks something like this:You replace that with
That looks more complicated, but remember that it totally replaces the
fill
function you didn't know how to write, and also remember that it will seamlessly handle DNS for you. (If you have a concrete reason to want to process numeric addresses only, you can set flags inhints
for that.)For more detailed example usage see the manpage I linked to.
You need to use the appropriate address structure first, and fill it out:
Then, after you're done,
memcpy()
it into thesockaddr_storage
:Note that you should still zero out the full
sockaddr_storage
buffer beforehand, as you did.Another way to do it is to define your own
union
of all the address structures, includingsockaddr_storage
, then initialize the appropriateunion
member.