How to get my IP address without loopback in C?

For communication between two hosts, I need to send the IP address of my host to another site. The problem is that if I ask for my IP address, maybe I will return my local loopback IP address (127.xxx) and not the network (ethernet) IP address.

I am using the following code:

char myhostname[32];


gethostname(myhostname, 32);
hp = gethostbyname(myhostname);
unsigned my_ip = *(unsigned*)(hp->h_addr);

if( (my_ip % 256) == 127) {
  /* Wrong IP adress as it 127.x.x.x */
  printf("Error, local IP address!");
  return;
}

The only way to solve this is to make sure that my hostname in / etc / hosts is behind the real network address and not the local loopback (by default, for example, Ubuntu).

Is there a way to solve this without relying on the contents of / etc / hosts?

Edit: I changed the code above, so it uses getaddrinfo, but I still return the loopback device number (127.0,0,1) instead of the real IP address:

struct addrinfo hint = {0};
struct addrinfo *aip = NULL;
unsigned ip = 0;
struct sockaddr_in *sinp = NULL;

hint.ai_family = AF_INET; /* IPv4 */
hint.ai_socktype = SOCK_STREAM;

if(getaddrinfo(hostname, NULL, &hint, &aip) != 0) {
    return 0;
}
sinp = (struct sockaddr_in *) aip->ai_addr;
ip   = *(unsigned *) &sinp->sin_addr;

( 3 addrinfo SOCK_STREAM, SOCK_DGRAM SOCK_RAW, )

, ...

+3
10

POSIX getaddrinfo(), , .

. man getaddrinfo.

+9

, : , , NAT: ing / .

IP-, , , , .

, , , .

+4

... . (. beej , , accept())

+4

, /etc/hosts , getaddrinfo IP-, 127.0.0.1 . , localhost... - . :

/etc/hosts:
127.0.0.1 localhost.localdomain localhost foo
:: 1 localhost6.localdomain6 localhost6
172.16.1.248 foo
172.16.1.249 bie
172.16.1.250 bletch

, , getaddrinfo host = "foo", 127.0.0.1 3 . , foo "127.0.0.1" "172.16.1.248". foo "127.0.0.1", .

, -.

+3

: IP-

, IP- , , , .

+1

(, , - ethernet WLAN), VPN IP-. , IP- , .

0
0

. , my_ip hp.

gethostbyname() hostent, h_addr_list.

h_addr_list - IP-, , .

, loopback, h_addr_list.

EDIT: it should work something like this:

gethostname(myhostname, 32);
hp = gethostbyname(myhostname);
unsigned my_ip = *(unsigned*)(hp->h_addr);

for (int i = 0; hp->h_addr_list[i] != 0; ++i) {
  if (hp->h_addr_list[i] != INADDR_LOOPBACK) {
    // hp->addr_list[i] is a non-loopback address
  }
}
// no address found
0
source

If / etc / hosts still exists and still the same, finding all the h_addr_list entries will not help.

0
source

Your new code protects the use of IPv4 (in the hint.ai_family field), which is a terrible idea.

Also, you are close, you just need to go through getaddrinfo results. Your code just gets the first IP address, but there is aip-> ai_next field that follows ...

struct addrinfo {
       ...
       struct addrinfo *ai_next;       /* next structure in linked list */
};
0
source

Source: https://habr.com/ru/post/1704428/


All Articles