I need to convert socket address that is placed in structure sockaddr
to structure in_addr
. I was trying to understand how IP is stored in these structures:
struct sockaddr
{
u_short sa_family; /* address family */
char sa_data[14]; /* up to 14 bytes of direct address */
};
struct in_addr
{
union
{
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
}
S_un;
};
I got stuck with question how 127.0.0.1
is stored in 14 characters of sa_data
.
What is the best way to convert sockaddr to in_addr?
sockaddr
is a generic struct, which is shared by different types of sockets. For TCP/IP sockets this struct becomes sockaddr_in
(IPv4) or sockaddr_in6
(IPv6). For unix sockets it becomes sockaddr_un
.
Ideally you would use sockaddr_in
instead of sockaddr
.
But given sockaddr
, you could do this to extract IP address from it:
sockaddr foo;
in_addr ip_address = ((sockaddr_in)foo).sin_addr;
or
in_addr_t ip_address = ((sockaddr_in)foo).sin_addr.s_addr;
If you look inside sockaddr_in
you will see that the first 2 bytes of sa_data
are the port number. And the next 4 bytes are the IP address.
PS: Please note that the IP address is stored in network byte order, so you will probably need to use ntohl
(network-to-host) and htonl
(host-to-network) to convert to/from host byte order.
UPDATE
For IPv6 things are similar:
sockaddr foo;
in_addr6 ip_address = ((sockaddr_in6)foo).sin6_addr;
To access individual bytes, use ip_address[0]
... ip_address[15]
.
Inside the sockaddr_in6
struct the first 2 bytes of sa_data
are the port number, next 4 bytes are flow info and after that the next 16 bytes are the IPv6 address.
Bewares, however, that sockaddr_in6
is larger than sockaddr
, so when casting from sockaddr
to sockaddr_in6
, make sure that the address is indeed an IPv6 address by checking the address family foo.sa_family == AF_INET6
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With