casting sockaddr_storage as sockaddr_in for inet_ntop
Solution 1
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);
Solution 2
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 astruct sockaddr_storage
somewhere) - or it is really a pointer, and you should pass
(struct sockaddr *) peer_addr
- without the&
- togetnameinfo()
.
Another point: The second parameter for getnameinfo()
is supposed to be the "real" size of the address struct you are inputting.
Related videos on Youtube
Comments
-
Babbleshack over 1 year
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.
-
Babbleshack over 10 yearsi thought getnameinfo() returned the hostname of the address?
-
Martin R over 10 years@Babbleshack: See "man getnameinfo" for the NI_NUMERICHOST flag: Return the address in numeric form, as if calling inet_ntop(3), instead of a host name.
-
glglgl over 10 yearsThe portable way is not to use
peer_addr->ss_family
(which isn't even known at least on my system), but to use the real size of the allocated structure. -
Babbleshack over 10 yearswhen i try to do that i get a compilation error, when i use my original code, my program works as expected. does this mean i have 'undefined behaviour'
-
glglgl over 10 years@Babbleshack I don't know what that meas as I don't know which compilation error you get. But it is very likely that you get UB, as a cast might hide and shadow problems.
-
Babbleshack over 10 yearsWhen i remove the dereferance from sockaddr, i get 'conversion to non scaler type' error
-
Martin R over 10 years@Babbleshack: May I ask why you "unaccepted" the answer? Does it not work anymore? - Of course glglgl is right that using the actual sockaddr length (e.g. as returned by recvfrom()) is the more portable way, but that should not make my answer completely wrong. - And it confusing if you change the question. Originally, peer_addr was a pointer to a struct sockaddr_storage, therefore my answer assumed that.
-
Babbleshack over 10 years@MartinR Thanks your answer reflects my working code. I have reaccepted your answer.