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.
is that possible to print interface if i give IP address with subnet mask . Ex 192.168.0.1/24 should print interface
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
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.
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] = ”;).