内容简介:我想获得连接到我的计算机的所有NIC的以下详细信息:1)接口名称(例如eth0)2)如果Linux中存在这样的东西,则接口号(如
我想获得连接到我的计算机的所有NIC的以下详细信息:
1)接口名称(例如eth0)
2)如果 Linux 中存在这样的东西,则接口号(如 Windows )
3)NIC带宽容量和模式(例如1Gb / s全双工)
getifaddrs()
/ freeifaddrs()
获取所有接口的链接列表,然后使用ioctl(fd,SIOCGIFINDEX,struct ifreq *)获取每个接口的接口索引.由于接口是连续的并且总是列出(无论它们是否为(活动)),我选择使用ioctl(fd,SIOCGIFNAME,struct ifreq *)来循环枚举它们.在所有情况下,fd都是AF_INET套接字.
要获得接口的双工和速度,需要使用ioctl(fd,SIOCETHTOOL,struct ifreq *),ifr_data指向具有cmd = ETHTOOL_GSET的struct ethtool_cmd.
如果失败则ioctls应该返回-1,如果成功则返回非负值(零,我相信).
这是一个示例程序:
#include <unistd.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <netinet/ip.h> #include <net/if.h> #include <linux/ethtool.h> #include <linux/sockios.h> #include <string.h> #include <errno.h> #include <stdio.h> struct interface { int index; int flags; /* IFF_UP etc. */ long speed; /* Mbps; -1 is unknown */ int duplex; /* DUPLEX_FULL, DUPLEX_HALF, or unknown */ char name[IF_NAMESIZE + 1]; }; static int get_interface_common(const int fd, struct ifreq *const ifr, struct interface *const info) { struct ethtool_cmd cmd; int result; /* Interface flags. */ if (ioctl(fd, SIOCGIFFLAGS, ifr) == -1) info->flags = 0; else info->flags = ifr->ifr_flags; ifr->ifr_data = (void *)&cmd; cmd.cmd = ETHTOOL_GSET; /* "Get settings" */ if (ioctl(fd, SIOCETHTOOL, ifr) == -1) { /* Unknown */ info->speed = -1L; info->duplex = DUPLEX_UNKNOWN; } else { info->speed = ethtool_cmd_speed(&cmd); info->duplex = cmd.duplex; } do { result = close(fd); } while (result == -1 && errno == EINTR); if (result == -1) return errno; return 0; } int get_interface_by_index(const int index, struct interface *const info) { int socketfd, result; struct ifreq ifr; if (index < 1 || !info) return errno = EINVAL; socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (socketfd == -1) return errno; ifr.ifr_ifindex = index; if (ioctl(socketfd, SIOCGIFNAME, &ifr) == -1) { do { result = close(socketfd); } while (result == -1 && errno == EINTR); return errno = ENOENT; } info->index = index; strncpy(info->name, ifr.ifr_name, IF_NAMESIZE); info->name[IF_NAMESIZE] = '\0'; return get_interface_common(socketfd, &ifr, info); } int get_interface_by_name(const char *const name, struct interface *const info) { int socketfd, result; struct ifreq ifr; if (!name || !*name || !info) return errno = EINVAL; socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (socketfd == -1) return errno; strncpy(ifr.ifr_name, name, IF_NAMESIZE); if (ioctl(socketfd, SIOCGIFINDEX, &ifr) == -1) { do { result = close(socketfd); } while (result == -1 && errno == EINTR); return errno = ENOENT; } info->index = ifr.ifr_ifindex; strncpy(info->name, name, IF_NAMESIZE); info->name[IF_NAMESIZE] = '\0'; return get_interface_common(socketfd, &ifr, info); } int main(int argc, char *argv[]) { struct interface iface; int arg; int status = 0; if (argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) { fprintf(stderr, "\n"); fprintf(stderr, "Usage: %s { -h | --help }\n", argv[0]); fprintf(stderr, " %s\n", argv[0]); fprintf(stderr, " %s INTERFACE ...\n", argv[0]); fprintf(stderr, "\n"); return 1; } if (argc > 1) { for (arg = 1; arg < argc; arg++) { if (get_interface_by_name(argv[arg], &iface) != 0) { fprintf(stderr, "%s: No such interface.\n", argv[arg]); status = 1; continue; } printf("%s: Interface %d", iface.name, iface.index); if (iface.flags & IFF_UP) printf(", up"); if (iface.duplex == DUPLEX_FULL) printf(", full duplex"); else if (iface.duplex == DUPLEX_HALF) printf(", half duplex"); if (iface.speed > 0) printf(", %ld Mbps", iface.speed); printf("\n"); } } else { for (arg = 1; ; arg++) { if (get_interface_by_index(arg, &iface) != 0) break; printf("%s: Interface %d", iface.name, iface.index); if (iface.flags & IFF_UP) printf(", up"); if (iface.duplex == DUPLEX_FULL) printf(", full duplex"); else if (iface.duplex == DUPLEX_HALF) printf(", half duplex"); if (iface.speed > 0) printf(", %ld Mbps", iface.speed); printf("\n"); } } return status; }
如果将上面保存为iflist.c,则可以使用它进行编译
gcc -W -Wall -O3 iflist.c -o iflist
要查看用法,请运行iflist -h.要列出所有接口,请运行它而不带参数:
./iflist
以上将使用我描述的枚举方法.要仅列出特定接口,请运行命名接口:
./iflist eth0 lo
当然,仅为以太网接口列出双工和速度.
编辑添加:
如果上述程序没有为接口提供带宽和模式,这里有一个简化版本,它报告确切原因(错误).这个接口名称作为命令行参数;它没有枚举接口.
#include <unistd.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <netinet/ip.h> #include <net/if.h> #include <linux/ethtool.h> #include <linux/sockios.h> #include <string.h> #include <errno.h> #include <stdio.h> int ethernet_interface(const char *const name, int *const index, int *const speed, int *const duplex) { struct ifreq ifr; struct ethtool_cmd cmd; int fd, result; if (!name || !*name) { fprintf(stderr, "Error: NULL interface name.\n"); fflush(stderr); return errno = EINVAL; } if (index) *index = -1; if (speed) *speed = -1; if (duplex) *duplex = -1; fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) { const int err = errno; fprintf(stderr, "%s: Cannot create AF_INET socket: %s.\n", name, strerror(err)); fflush(stderr); return errno = err; } strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); ifr.ifr_data = (void *)&cmd; cmd.cmd = ETHTOOL_GSET; if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) { const int err = errno; do { result = close(fd); } while (result == -1 && errno == EINTR); fprintf(stderr, "%s: SIOCETHTOOL ioctl: %s.\n", name, strerror(err)); return errno = err; } if (speed) *speed = ethtool_cmd_speed(&cmd); if (duplex) switch (cmd.duplex) { case DUPLEX_HALF: *duplex = 0; break; case DUPLEX_FULL: *duplex = 1; break; default: fprintf(stderr, "%s: Unknown mode (0x%x).\n", name, cmd.duplex); fflush(stderr); *duplex = -1; } if (index && ioctl(fd, SIOCGIFINDEX, &ifr) >= 0) *index = ifr.ifr_ifindex; do { result = close(fd); } while (result == -1 && errno == EINTR); if (result == -1) { const int err = errno; fprintf(stderr, "%s: Error closing socket: %s.\n", name, strerror(err)); return errno = err; } return 0; } int main(int argc, char *argv[]) { int arg, speed, index, duplex; if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { fprintf(stderr, "\n"); fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]); fprintf(stderr, " %s INTERFACE ...\n", argv[0]); fprintf(stderr, "\n"); return 0; } for (arg = 1; arg < argc; arg++) { if (ethernet_interface(argv[arg], &index, &speed, &duplex)) return 1; if (index == -1) printf("%s: (no interface index)", argv[arg]); else printf("%s: interface %d", argv[arg], index); if (speed == -1) printf(", unknown bandwidth"); else printf(", %d Mbps bandwidth", speed); if (duplex == 0) printf(", half duplex.\n"); else if (duplex == 1) printf(", full duplex.\n"); else printf(", unknown mode.\n"); } return 0; }
有问题吗?
翻译自:https://stackoverflow.com/questions/14264371/how-to-get-nic-details-from-a-c-program
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- dotnet 获取程序所在路径的方法
- Golang:通过小程序获取微信 openid
- 微信小程序与公众号获取openId的不同
- 微信小程序获取用户的 OpenId (附前端代码)
- express获取微信小程序二维码小记
- 小程序登录及用户信息和手机号的获取
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python Algorithms
Magnus Lie Hetland / Apress / 2010-11-24 / USD 49.99
Python Algorithms explains the Python approach to algorithm analysis and design. Written by Magnus Lie Hetland, author of Beginning Python, this book is sharply focused on classical algorithms, but it......一起来看看 《Python Algorithms》 这本书的介绍吧!