Get IP address of an interface on Linux

CLinuxSockets

C Problem Overview


How can I get the IPv4 address of an interface on Linux from C code?

For example, I'd like to get the IP address (if any) assigned to eth0.

C Solutions


Solution 1 - C

Try this:

#include <stdio.h>
#include <unistd.h>
#include <string.h> /* for strncpy */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>

int
main()
{
 int fd;
 struct ifreq ifr;

 fd = socket(AF_INET, SOCK_DGRAM, 0);

 /* I want to get an IPv4 IP address */
 ifr.ifr_addr.sa_family = AF_INET;

 /* I want IP address attached to "eth0" */
 strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1);

 ioctl(fd, SIOCGIFADDR, &ifr);

 close(fd);

 /* display result */
 printf("%s\n", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));

 return 0;
}

The code sample is taken from here.

Solution 2 - C

In addition to the ioctl() method Filip demonstrated you can use getifaddrs(). There is an example program at the bottom of the man page.

Solution 3 - C

If you're looking for an address (IPv4) of the specific interface say wlan0 then try this code which uses getifaddrs():

#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
    struct ifaddrs *ifaddr, *ifa;
    int family, s;
    char host[NI_MAXHOST];

    if (getifaddrs(&ifaddr) == -1) 
    {
        perror("getifaddrs");
        exit(EXIT_FAILURE);
    }

        
    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) 
    {
        if (ifa->ifa_addr == NULL)
            continue;  

        s=getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in),host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);

        if((strcmp(ifa->ifa_name,"wlan0")==0)&&(ifa->ifa_addr->sa_family==AF_INET))
        {
            if (s != 0)
            {
                printf("getnameinfo() failed: %s\n", gai_strerror(s));
                exit(EXIT_FAILURE);
            }
            printf("\tInterface : <%s>\n",ifa->ifa_name );
            printf("\t  Address : <%s>\n", host); 
        }
    }
   
    freeifaddrs(ifaddr);
    exit(EXIT_SUCCESS);
}

You can replace wlan0 with eth0 for ethernet and lo for local loopback.

The structure and detailed explanations of the data structures used could be found here.

To know more about linked list in C this page will be a good starting point.

Solution 4 - C

My 2 cents: the same code works even if iOS:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>



#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
	[super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
	showIP();
}



void showIP()
{
	struct ifaddrs *ifaddr, *ifa;
	int family, s;
	char host[NI_MAXHOST];
	
	if (getifaddrs(&ifaddr) == -1)
	{
		perror("getifaddrs");
		exit(EXIT_FAILURE);
	}
	
	
	for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
	{
		if (ifa->ifa_addr == NULL)
			continue;
		
		s=getnameinfo(ifa->ifa_addr,sizeof(struct sockaddr_in),host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
		
		if( /*(strcmp(ifa->ifa_name,"wlan0")==0)&&( */ ifa->ifa_addr->sa_family==AF_INET) // )
		{
			if (s != 0)
			{
				printf("getnameinfo() failed: %s\n", gai_strerror(s));
				exit(EXIT_FAILURE);
			}
			printf("\tInterface : <%s>\n",ifa->ifa_name );
			printf("\t  Address : <%s>\n", host);
		}
	}
	
	freeifaddrs(ifaddr);
}


@end

I simply removed the test against wlan0 to see data. ps You can remove "family"

Solution 5 - C

I have been in the same issue recently, and this is the code I made up and it works. Make sure to use the name of the network interface, exactly as you have it (could be "eth0" or else).

gotta check if ifconfigcommand beforehand to get the interface name and use it in C.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <unistd.h>
#include <linux/if.h>
#include <errno.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <arpa/inet.h>
    

void extract_ipaddress()
    {
    	//create an ifreq struct for passing data in and out of ioctl
    	struct ifreq my_struct;
     
    	//declare and define the variable containing the name of the interface
    	char *interface_name="enp0s3";   //a very frequent interface name is "eth0";
     
    	//the ifreq structure should initially contains the name of the interface to be queried. Which should be copied into the ifr_name field.
    	//Since this is a fixed length buffer, one should ensure that the name does not cause an overrun
    	size_t interface_name_len=strlen(interface_name);
     
    	if(interface_name_len<sizeof(my_struct.ifr_name))
    	{
    		memcpy(my_struct.ifr_name,interface_name,interface_name_len);
    		my_struct.ifr_name[interface_name_len]=0;
    	}
    	else
    	{
    		perror("Copy name of interface to ifreq struct");
    		printf("The name you provided for the interface is too long...\n");
    	}
     
    	//provide an open socket descriptor with the address family AF_INET
    	/* ***************************************************************
    	 * All ioctl call needs a file descriptor to act on. In the case of SIOCGIFADDR this must refer to a socket file descriptor. This socket must be in the address family that you wish to obtain (AF_INET for IPv4)
    	 * ***************************************************************
    	 */
     
    	int file_descriptor=socket(AF_INET, SOCK_DGRAM,0);
     
    	if(file_descriptor==-1)
    	{
    		perror("Socket file descriptor");
    		printf("The construction of the socket file descriptor was unsuccessful.\n");
    	    return -1;
    	}
     
    	//invoke ioctl() because the socket file descriptor exists and also the struct 'ifreq' exists
    	int myioctl_call=ioctl(file_descriptor,SIOCGIFADDR,&my_struct);
     
    	if (myioctl_call==-1)
    	{
    	    perror("ioctl");
    	    printf("Ooops, error when invoking ioctl() system call.\n");
    	    close(file_descriptor);
    	    return -1;
    	}
     
    	close(file_descriptor);
     
    	/* **********************************************************************
    	 * If this completes without error , then the hardware address of the interface should have been returned in the  'my_struct.ifr_addr' which is types as struct sockaddr_in.
    	 * ***********************************************************************/
     
      //extract the IP Address (IPv4) from the my_struct.ifr_addr which has the type 'ifreq'
     
    	/* *** Cast the returned address to a struct 'sockaddr_in' *** */
    	struct sockaddr_in * ipaddress= (struct sockaddr_in *)&my_struct.ifr_addr;
       /* *** Extract the 'sin_addr' field from the data type (struct) to obtain a struct 'in_addr' *** */
      printf("IP Address is %s.\n", inet_ntoa(ipaddress->sin_addr));

    }

Solution 6 - C

If you don't mind the binary size, you can use iproute2 as library.

iproute2-as-lib

Pros:

  • No need to write the socket layer code.
  • More or even more information about network interfaces can be got. Same functionality with the iproute2 tools.
  • Simple API interface.

Cons:

  • iproute2-as-lib library size is big. ~500kb.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionleeeroyView Question on Stackoverflow
Solution 1 - CFilip EkbergView Answer on Stackoverflow
Solution 2 - CDuckView Answer on Stackoverflow
Solution 3 - CsjsamView Answer on Stackoverflow
Solution 4 - CingcontiView Answer on Stackoverflow
Solution 5 - CGeorgeView Answer on Stackoverflow
Solution 6 - CeshenhuView Answer on Stackoverflow