Convert IP address from sockaddr to in_addr
I need to convert a socket address that is being put in a struct sockaddr
into a struct in_addr
. I was trying to figure out how the 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 have a question about how is 127.0.0.1
stored in 14 characters sa_data
. What's the best way to convert sockaddr to in_addr?
source to share
sockaddr
is a generic structure that is shared by different socket types. For TCP / IP sockets, this structure becomes sockaddr_in
. For unix sockets, it becomes sockaddr_un
.
Ideally, you would use sockaddr_in
instead sockaddr
.
But given sockaddr
, to extract the IP address from it, you can do this:
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 can see that the first 2 bytes 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 probably need to use ntohl
(network-to-host) and htonl
(host-to-network) to convert to / from host byte order.
UPDATE
For IPv6, everything is similar:
sockaddr foo;
in_addr6 ip_address = ((sockaddr_in6)foo).sin6_addr;
To access the individual bytes, use ip_address[0]
... ip_address[15]
.
Within the structure, the sockaddr_in6
first 2 bytes sa_data
are the port number, the next 4 bytes are the stream information, and after that the next 16 bytes are the IPv6 address.
Bewares is, however, which is sockaddr_in6
greater than sockaddr
, so when dropping from sockaddr
to, sockaddr_in6
verify that the address is indeed an IPv6 address by checking the address family foo.sa_family == AF_INET6
.
source to share