C++ - How to get IP and port from struct sockaddr

12,466

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));
Share:
12,466

Related videos on Youtube

Christian Rößner
Author by

Christian Rößner

Updated on September 15, 2022

Comments

  • Christian Rößner
    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
    Christian Rößner almost 8 years
    Thank you. While I was waiting for answers, I found a different solution.
  • sorush-r
    sorush-r over 6 years
    Shouldn't it be ntohs instead of htons ?
  • Stian Skjelstad
    Stian Skjelstad over 5 years
    ntohs() 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_
    i336_ over 4 years
    Oddly, 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 the sizeof there.
  • fadedbee
    fadedbee over 4 years
    This is the wrong way around. inet_pton converts from string to struct sockaddr_in, inet_ntop is needed to convert from struct sockaddr_in to string. (See my answer.)