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?

+3


source to share


1 answer


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

.

+5


source







All Articles