Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

casting sockaddr_storage as sockaddr_in for inet_ntop

Tags:

c

sockets

I am trying to cast a sockaddr_storage to a sockadd_in, so that i can print out the source ip address of a datagram packet, i do not seem to be able to get the cast correct,

struct sockaddr_storage  peer_addr;


getnameinfo((struct sockaddr *) &peer_add
                peer_addrlen,
                hostbuff, sizeof(hostbuff),
                NULL, 0, NI_NAMEREQD);


inet_ntop(AF_INET, (((struct sockaddr_in *)peer_addr).sin_addr), ipbuff, INET_ADDRSTRLEN);

when i try to cast the structure to a sockaddr_in, i either get 'cannot convert to pointer', or when i remove the dereferance i get 'conversion to non scaler type requested'.

I have tried alot of combinations and simply don't understand where i am going wrong.

like image 832
Babbleshack Avatar asked Dec 16 '22 04:12

Babbleshack


2 Answers

inet_ntop(peer_addr->ss_family, &(((struct sockaddr_in *)peer_addr)->sin_addr), ipbuff, INET_ADDRSTRLEN);

should work. But consider to use getnameinfo() instead, which is the more modern interface:

char host[NI_MAXHOST];
getnameinfo((struct sockaddr *)peer_addr, peer_addr->ss_len, host, sizeof(host), NULL, 0, NI_NUMERICHOST);

works for both IPv4 and IPv6 addresses.


Update according to the changed types in the question: This is a complete example that should compile without warnings:

int socket = ...;

struct sockaddr_storage peer_addr;
socklen_t peer_addrlen;
char host[NI_MAXHOST];

ssize_t amount;
char buffer[1000];
amount = recvfrom(socket, buffer, sizeof(buffer), 0, (struct sockaddr *)&peer_addr, &peer_addrlen);
getnameinfo((struct sockaddr *)&peer_addr, peer_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST);

Or, using inet_ntop():

char ipbuff[INET_ADDRSTRLEN];
inet_ntop(peer_addr.ss_family, &(((struct sockaddr_in *)&peer_addr)->sin_addr), ipbuff, INET_ADDRSTRLEN);
like image 107
Martin R Avatar answered Jan 26 '23 00:01

Martin R


struct sockaddr_storage  *  peer_addr;


getnameinfo((struct sockaddr *) &peer_add
                peer_addrlen,
                hostbuff, sizeof(hostbuff),
                NULL, 0, NI_NAMEREQD);

Here you are mixing up stuff.

getnameinfo() indeed takes a struct sockaddr* as its first parameter, but what you try to do here won't work: peer_addr is a struct sockaddr_storage *, you take its address - which is a struct sockaddr_storage **, and try to cast this. That won't work.

I don't know where your peer_addr comes from, but

  • either it should be a struct sockaddr_storage (I don't think there is a need to have a pointer to a struct sockaddr_storage somewhere)
  • or it is really a pointer, and you should pass (struct sockaddr *) peer_addr - without the & - to getnameinfo().

Another point: The second parameter for getnameinfo() is supposed to be the "real" size of the address struct you are inputting.

like image 25
glglgl Avatar answered Jan 25 '23 23:01

glglgl