Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can we cast sockaddr to sockaddr_in

I can see why it is useful to cast sockaddr to sockaddr_in, but I don't understand how this is possible. From what I've read, they're the same size and sockaddr_in is added with sin_zero to make it the same size. I would like to know how the compiler knows where to get the information from sockaddr_in if it is layed out differently to sockaddr.

like image 622
Jean-Luc Avatar asked Feb 16 '12 13:02

Jean-Luc


People also ask

What is the use of Sockaddr_in?

The SOCKADDR_IN structure specifies a transport address and port for the AF_INET address family.

What is a Sockaddr?

sockaddr is used as the base of a set of address structures that act like a discriminated union, see the Beej guide to networking. You generally look at the sa_family and then cast to the appropriate address family's specific address structure.


1 Answers

It is possible because you normally cast pointers, not the structures themselves. You do what in natural language means "please treat this pointer to a socket structure as a pointer to an internet socket structure instead". Compiler has no problems to re-interpret the pointer.

Here is more detailed description taken up from comments:

A sockaddr is 16 bytes in size - the first two bytes are the sa_family, and the remaining 14 bytes are the sa_data which is arbitrary data. A sockaddr_in is also 16 bytes in size - the first 2 bytes are the sin_family (always AF_INET), the next 2 bytes are the sin_port, the next 4 bytes are the sin_addr (IP address), and the last 8 bytes are the sin_zero which is unused in IPv4 and provided only to ensure 16 bytes. This way, you can look at sockaddr.sa_family first, and if it is AF_INET then interpret the entire sockaddr as a sockaddr_in.

A sockaddr_in is not stored inside of sockaddr.sa_data field. The entire sockaddr is the entire sockaddr_in (when sockaddr.sa_family is AF_INET, that is). If you take a sockaddr* pointer and cast it to a sockaddr_in* pointer, then:

  • sockaddr.sa_family is sockaddr_in.sin_family
  • bytes 0-1 of sockaddr.sa_data are sockaddr_in.sin_port
  • bytes 2-5 are sockaddr_in.sin_addr
  • bytes 6-13 are sockaddr_in.sin_zero.
like image 148
Roman R. Avatar answered Oct 08 '22 14:10

Roman R.