C++ - How to get IP and port from struct sockaddr
Solution 1
non-compile tested example for IPv4. IPv6 is almost the same, just adjust the constant-defintions used (read the inet_ntop man page)
#include <arpa/inet.h>
void print_ipv4(struct sockaddr *s)
{
struct sockaddr_in *sin = (struct sockaddr_in *)s;
char ip[INET_ADDRSTRLEN];
uint16_t port;
inet_pton (AF_INET, sin->sin_addr, ip, sizeof (ip));
port = htons (sin->sin_port);
printf ("host %s:%d\n", ip, port);
}
Solution 2
inet_ntop
is needed to convert from binary to string, not inet_pton
.
$ man inet_ntop
...
This function converts the network address structure src in the af address family into a character string. The
resulting string is copied to the buffer pointed to by dst, which must be a non-null pointer. The caller specifies
the number of bytes available in this buffer in the argument size.
Example:
#include <arpa/inet.h>
...
char address[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &my_sockaddr_in.sin_addr, address, sizeof(address));
Related videos on Youtube
Christian Rößner
Updated on September 15, 2022Comments
-
Christian Rößner over 1 year
I am trying to develop a mail milter with libmilter. Therefor I have to define some callback functions. Currently I struggle with the connect() function. The declaration looks like this:
sfsistat mlfi_connect(SMFICTX *ctx, char *hostname, struct sockaddr *hostaddr);
When a client connects to the milter, this callback is called. Now I would like to log the hostname, IP and port. For the hostname this is easy. But I can not get it to work with the hostaddr.
I found some similar articles here on StackOverflow, but none worked for me. It looks like I have to convert the structure to either sockaddr_in or sockaddr_in6, but I get compiler problems like "member access into incomplete type 'struct sockaddr_in'"
This is what I tried:
struct sockaddr_in *sin; struct sockaddr_in6 *sin6; string ipandport; switch (hostaddr->sa_family) { case AF_INET: sin = (struct sockaddr_in *) hostaddr; unsigned char *ip = (unsigned char *)&sin->sin_addr.s_addr; break; case AF_INET6: // TODO break; default: ipandport = "unknown"; }
I never thought that it could be so hard to get such trivial information :-)
-
Christian Rößner almost 8 yearsThank you. While I was waiting for answers, I found a different solution.
-
sorush-r over 6 yearsShouldn't it be
ntohs
instead ofhtons
? -
Stian Skjelstad over 5 yearsntohs() and htons() does exactly the same. Either they do nothing, or they swap upper and lower byte. Most socket implementations, use macro to alias one to the other.
-
i336_ over 4 yearsOddly, my prototype of
inet_pton
(as listed in man-pages 5.02, 2019-03-06) doesn't include the 4th argument you're using for thesizeof
there. -
fadedbee over 4 yearsThis is the wrong way around.
inet_pton
converts from string tostruct sockaddr_in
,inet_ntop
is needed to convert fromstruct sockaddr_in
to string. (See my answer.)