C Program to Get IP Address from Interface Name on Linux

By | August 10, 2020

On a Linux system, all network interfaces have a unique name that is shows up when you run the ifconfig command for example.

The main network adapter often has the name eth0 or enp1s0 on linux systems. The ip address is configured using desktop gui tools, or through commands like ifconfig.

If you are writing some socket program, that needs to get the ip address of a given interface like eth0, then use the ioctl function.

In this tutorial, we shall see how to fetch the ip address and netmask of a given interface.

Code

Here is a simple piece of code that demonstrates how. Note that you have to change the value of iface to the name of the interface present on your system.

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

int main()
{
	int fd;
	struct ifreq ifr;
	
    // replace with your interface name
    // or ask user to input
    
	char iface[] = "enp1s0";
	
	fd = socket(AF_INET, SOCK_DGRAM, 0);

	//Type of address to retrieve - IPv4 IP address
	ifr.ifr_addr.sa_family = AF_INET;

	//Copy the interface name in the ifreq structure
	strncpy(ifr.ifr_name , iface , IFNAMSIZ-1);

	ioctl(fd, SIOCGIFADDR, &ifr);

	close(fd);

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

	return 0;
}

The above example uses a UDP socket (SOCK_DGRAM). We can use a TCP socket (SOCK_STREAM) as well.

Output

Now compile and run the program and it should show the ip address of the given interface.

$ gcc interface_ip.c && ./a.out 
enp1s0 - 192.168.1.207

Get Netmask with IP

If you also need the netmask then use the SIOCGIFNETMASK value in ioctl like this :

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <unistd.h>
#include <arpa/inet.h>

int main()
{
	int fd;
	struct ifreq ifr;
	
	char iface[] = "enp1s0";
	
	fd = socket(AF_INET, SOCK_DGRAM, 0);

	//Type of address to retrieve - IPv4 IP address
	ifr.ifr_addr.sa_family = AF_INET;

	//Copy the interface name in the ifreq structure
	strncpy(ifr.ifr_name , iface , IFNAMSIZ-1);
	
	//get the ip address
	ioctl(fd, SIOCGIFADDR, &ifr);
	
	//display ip
	printf("IP address of %s - %s\n" , iface , inet_ntoa(( (struct sockaddr_in *)&ifr.ifr_addr )->sin_addr) );
	
	//get the netmask ip
	ioctl(fd, SIOCGIFNETMASK, &ifr);
	
	//display netmask
	printf("Netmask of %s - %s\n" , iface , inet_ntoa(( (struct sockaddr_in *)&ifr.ifr_addr )->sin_addr) );
	
	close(fd);
	
	return 0;
}

Output

This time it will also show the netmask configured on the interface along with the ip address:

$ gcc interface_ip.c && ./a.out 
IP address of enp1s0 - 192.168.1.207
Netmask of enp1s0 - 255.255.0.0

Conclusion

If you need to get the MAC address of a given interface, then use the code shown in this post
C Program to get MAC Address from Interface Name on Linux

Hope that helps. If you have any feedback or questions, let us know in the comments below.

About Silver Moon

A Tech Enthusiast, Blogger, Linux Fan and a Software Developer. Writes about Computer hardware, Linux and Open Source software and coding in Python, Php and Javascript. He can be reached at [email protected].

4 Comments

C Program to Get IP Address from Interface Name on Linux
  1. Dmitry Saychenko

    In Ubuntu 18.04 i get strange results:
    dmitry@dmitry-lenovo:~/test/c$ uname -a
    Linux dmitry-lenovo 5.4.0-58-generic #64~18.04.1-Ubuntu SMP Wed Dec 9 17:11:11 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
    Random results:
    dmitry@dmitry-lenovo:~/test/c$ gcc getipaddr.c
    dmitry@dmitry-lenovo:~/test/c$ ./a.out
    180.85.0.0
    dmitry@dmitry-lenovo:~/test/c$ ./a.out
    3.86.0.0
    dmitry@dmitry-lenovo:~/test/c$ ./a.out
    205.85.0.0
    If fill if_req structure with zeroes:

    fd = socket(AF_INET, SOCK_DGRAM, 0);

    memset(&ifr, 0, sizeof(struct ifreq));

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

    I get:
    dmitry@dmitry-lenovo:~/test/c$ ./a.out
    0.0.0.0

  2. Allen Edwards

    Finally someone posted some code that actually works. Thank you so much. This is such a straightforward question that receives such complicated gobbledegook on Stackoverflow. I have been looking for this for a long time. Great job.

    I don’t understand the comment above about strcpy(). Hope it isn’t a problem.

  3. cordeg

    This code makes a common mistake in assuming that strncpy() guarantees that the resulting string is null-terminated. In fact, it only does so if the string is shorter than the length specified (i.e., IFNAMSIZ-1); otherwise, it simply copies up to the last character position that fits (i.e., ifr.ifr_name[IFNAMSIZ-2]) and stops — no ” is inserted. (This may seem stupid to the younger readers, but the purpose of the strncpy() function was to support an erstwhile popular use of fixed-length “string buffer” storage where null terminators were considered a waste of a perfectly good space in a message, for example. In any case, the C standard never required the guarantee of a null-terminator on truncated strings as a result, though some compiler vendors implemented it that way by choice, leading some to believe the behavior was part of the function definition.) Of course, in this example, the string is a fixed “eth0”, so the code works just fine, but obviously the code uses strncpy() rather than strcpy() to cover the general case where the ifname string length is unknown and could exceed the IFNAMSIZ limit. As long as this is theoretically possible, the code should ensure null-termination by following up the strncpy() with a manual termination (e.g., “ifr.ifr_name[IFNAMSIZ-1] = ”;).

Leave a Reply

Your email address will not be published. Required fields are marked *