本文介绍了一个C语言程序,用于获取Linux系统的网卡数量及其详细信息,包括网卡名称、MAC地址、IP地址、广播地址和子网掩码。通过`socket`、`ioctl`等系统调用遍历并打印所有接口信息,与`ifconfig`命令输出信息一致。
interface_info.c
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <errno.h>
-
- #include <net/if.h>
- #include <sys/ioctl.h>
- #include <arpa/inet.h>
-
- int sock_get_local_info(void)
- {
- int fd;
- int interfaceNum = 0;
- struct ifreq buf[16];
- struct ifconf ifc;
- struct ifreq ifrcopy;
- char mac[16] = {0};
- char ip[32] = {0};
- char broadAddr[32] = {0};
- char subnetMask[32] = {0};
-
- if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- perror("socket");
- close(fd);
- return -1;
- }
-
- ifc.ifc_len = sizeof(buf);
- ifc.ifc_buf = (caddr_t)buf;
- if (!ioctl(fd, SIOCGIFCONF, (char *)&ifc)) {
- interfaceNum = ifc.ifc_len / sizeof(struct ifreq);
- printf("interface num = %d\n", interfaceNum);
- while (interfaceNum-- > 0) {
- printf("\ndevice name: %s\n", buf[interfaceNum].ifr_name);
-
- //ignore the interface that not up or not runing
- ifrcopy = buf[interfaceNum];
- if (ioctl(fd, SIOCGIFFLAGS, &ifrcopy)) {
- printf("ioctl: %s [%s:%d]\n", strerror(errno), __FILE__, __LINE__);
- close(fd);
- return -1;
- }
-
- //get the mac of this interface
- if (!ioctl(fd, SIOCGIFHWADDR, (char *)(&buf[interfaceNum]))) {
- memset(mac, 0, sizeof(mac));
- snprintf(mac, sizeof(mac), "%02x%02x%02x%02x%02x%02x",
- (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[0],
- (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[1],
- (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[2],
- (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[3],
- (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[4],
- (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[5]);
- printf("device mac: %s\n", mac);
- } else {
- printf("ioctl: %s [%s:%d]\n", strerror(errno), __FILE__, __LINE__);
- close(fd);
- return -1;
- }
-
- //get the IP of this interface
- if (!ioctl(fd, SIOCGIFADDR, (char *)&buf[interfaceNum])) {
- snprintf(ip, sizeof(ip), "%s",
- (char *)inet_ntoa(((struct sockaddr_in *)&(buf[interfaceNum].ifr_addr))->sin_addr));
- printf("device ip: %s\n", ip);
- } else {
- printf("ioctl: %s [%s:%d]\n", strerror(errno), __FILE__, __LINE__);
- close(fd);
- return -1;
- }
-
- //get the broad address of this interface
- if (!ioctl(fd, SIOCGIFBRDADDR, &buf[interfaceNum])) {
- snprintf(broadAddr, sizeof(broadAddr), "%s",
- (char *)inet_ntoa(((struct sockaddr_in *)&(buf[interfaceNum].ifr_broadaddr))->sin_addr));
- printf("device broadAddr: %s\n", broadAddr);
- } else {
- printf("ioctl: %s [%s:%d]\n", strerror(errno), __FILE__, __LINE__);
- close(fd);
- return -1;
- }
-
- //get the subnet mask of this interface
- if (!ioctl(fd, SIOCGIFNETMASK, &buf[interfaceNum])) {
- snprintf(subnetMask, sizeof(subnetMask), "%s",
- (char *)inet_ntoa(((struct sockaddr_in *)&(buf[interfaceNum].ifr_netmask))->sin_addr));
- printf("device subnetMask: %s\n", subnetMask);
- } else {
- printf("ioctl: %s [%s:%d]\n", strerror(errno), __FILE__, __LINE__);
- close(fd);
- return -1;
- }
- }
- } else {
- printf("ioctl: %s [%s:%d]\n", strerror(errno), __FILE__, __LINE__);
- close(fd);
- return -1;
- }
- close(fd);
- return 0;
- }
-
- int main(int argc, char *argv[])
- {
- sock_get_local_info();
-
- return EXIT_SUCCESS;
- }
-
- gcc interface_info.c -o interface_info.out -Wall
-
- $ ./interface_info.out
- interface num = 2
-
- device name: enp0s3
- device mac: 08002738fcd0
- device ip: 192.168.31.223
- device broadAddr: 192.168.31.255
- device subnetMask: 255.255.255.0
-
- device name: lo
- device mac: 000000000000
- device ip: 127.0.0.1
- device broadAddr: 0.0.0.0
- device subnetMask: 255.0.0.0
-
和 ifconfig 命令显示的信息一致
- $ ifconfig
- enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
- inet 192.168.31.223 netmask 255.255.255.0 broadcast 192.168.31.255
- ether 08:00:27:38:fc:d0 txqueuelen 1000 (以太网)
- RX packets 183199 bytes 179974182 (179.9 MB)
- RX errors 0 dropped 193 overruns 0 frame 0
- TX packets 68178 bytes 7018396 (7.0 MB)
- TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
-
- lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
- inet 127.0.0.1 netmask 255.0.0.0
- inet6 ::1 prefixlen 128 scopeid 0x10<host>
- loop txqueuelen 1000 (本地环回)
- RX packets 4025 bytes 399305 (399.3 KB)
- RX errors 0 dropped 0 overruns 0 frame 0
- TX packets 4025 bytes 399305 (399.3 KB)
- TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
-