C代码来获取Linux中IP地址的接口名称

我如何从C代码获取Linux中IP地址的接口名称?

例如,我想获取分配给IP地址192.168.0.1的接口名称(如etho,eth1,l0)

Solutions Collecting From Web of "C代码来获取Linux中IP地址的接口名称"

你可以使用getifaddrs 。 有关使用信息,请参阅man 3 getifaddrs 。 这只适用于类Unix系统。

使用/ proc / net / arp你可以匹配它。 这是一个命令行工具的例子。

用法:getdevicebyip 192.168.0.1

 #include <stdio.h> #include <fcntl.h> int main(int argc, char **argv){ if (argc < 2) return 1; FILE *fp = fopen("/proc/net/arp", "r"); char ip[99], hw[99], flags[99], mac[99], mask[99], dev[99], dummy[99]; fgets(dummy, 99, fp); //header line while (fscanf(fp, "%s %s %s %s %s %s\n", ip, hw, flags, mac, mask, dev) != EOF) if (!strcmp(argv[1],ip)) printf("%s\n",dev); return 0; } 

netlink是在Linux上执行此操作的一种方法。 我认为这甚至可能是在Linux上正确的方式(即使它不是可移植的)。

策略是:

  1. 通过发送一个netlink消息从内核获取接口上的地址列表。
  2. 找到你想要的地址(我已经硬编码一个我想要的address_dq ),并记录它的接口(在这个阶段的数字)
  3. 通过发送另一个netlink消息获取接口列表,
  4. 找到与步骤(2)中记录的号码相匹配的接口号码。
  5. 获取界面的名称。

下面的代码并不漂亮,但我相信你可以做得更好。 由于不检查多部分消息(检查NLM_F_MULTI标志,并且NLM_F_MULTI的消息类型是NLMSG_DONE操作的方式),所以我特别NLMSG_DONE 。 相反,我只是假定第一条消息的响应是多部分的 – 它在我的机器上 – 并且咀嚼了NLMSG_DONE消息。

码…

 #include <asm/types.h> #include <linux/netlink.h> #include <linux/rtnetlink.h> #include <sys/socket.h> #include <string.h> #include <stdio.h> #include <stdlib.h> int main(int argc, void ** argv) { // This is the address we want the interface name for, // expressed in dotted-quad format char * address_dq = "127.0.0.1"; // Convert it to decimal format unsigned int address; inet_pton(AF_INET, address_dq, &address); char buf[16384]; // Our first message will be a header followed by an address payload struct { struct nlmsghdr nlhdr; struct ifaddrmsg addrmsg; } msg; // Our second message will be a header followed by a link payload struct { struct nlmsghdr nlhdr; struct ifinfomsg infomsg; } msg2; struct nlmsghdr *retmsg; // Set up the netlink socket int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); // Fill in the message // NLM_F_REQUEST means we are asking the kernel for data // NLM_F_ROOT means provide all the addresses // RTM_GETADDR means we want address information // AF_INET means limit the response to ipv4 addresses memset(&msg, 0, sizeof(msg)); msg.nlhdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); msg.nlhdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; msg.nlhdr.nlmsg_type = RTM_GETADDR; msg.addrmsg.ifa_family = AF_INET; // As above, but RTM_GETLINK means we want link information memset(&msg2, 0, sizeof(msg2)); msg2.nlhdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); msg2.nlhdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; msg2.nlhdr.nlmsg_type = RTM_GETLINK; msg2.infomsg.ifi_family = AF_UNSPEC; // Send the first netlink message send(sock, &msg, msg.nlhdr.nlmsg_len, 0); int len; // Get the netlink reply len = recv(sock, buf, sizeof(buf), 0); retmsg = (struct nlmsghdr *)buf; // Loop through the reply messages (one for each address) // Each message has a ifaddrmsg structure in it, which // contains the prefix length as a member. The ifaddrmsg // structure is followed by one or more rtattr structures, // some of which (should) contain raw addresses. while NLMSG_OK(retmsg, len) { struct ifaddrmsg *retaddr; retaddr = (struct ifaddrmsg *)NLMSG_DATA(retmsg); int iface_idx = retaddr->ifa_index; struct rtattr *retrta; retrta = (struct rtattr *)IFA_RTA(retaddr); int attlen; attlen = IFA_PAYLOAD(retmsg); char pradd[128]; // Loop through the routing information to look for the // raw address. while RTA_OK(retrta, attlen) { if (retrta->rta_type == IFA_ADDRESS) { // Found one -- is it the one we want? unsigned int * tmp = RTA_DATA(retrta); if (address == *tmp) { // Yes! inet_ntop(AF_INET, RTA_DATA(retrta), pradd, sizeof(pradd)); printf("Address %s ", pradd); // Now we need to get the interface information // First eat up the "DONE" message waiting for us len = recv(sock, buf, sizeof(buf), 0); // Send the second netlink message and get the reply send(sock, &msg2, msg2.nlhdr.nlmsg_len, 0); len = recv(sock, buf, sizeof(buf), 0); retmsg = (struct nlmsghdr *)buf; while NLMSG_OK(retmsg, len) { struct ifinfomsg *retinfo; retinfo = NLMSG_DATA(retmsg); if (retinfo->ifi_index == iface_idx) { retrta = IFLA_RTA(retinfo); attlen = IFLA_PAYLOAD(retmsg); char prname[128]; // Loop through the routing information // to look for the interface name. while RTA_OK(retrta, attlen) { if (retrta->rta_type == IFLA_IFNAME) { strcpy(prname, RTA_DATA(retrta)); printf("on %s\n", prname); exit(EXIT_SUCCESS); } retrta = RTA_NEXT(retrta, attlen); } } retmsg = NLMSG_NEXT(retmsg, len); } } } retrta = RTA_NEXT(retrta, attlen); } retmsg = NLMSG_NEXT(retmsg, len); } } 

如上所述运行时,返回Address 127.0.0.1 on lo

使用"192.168.1.x"而不是"127.0.0.1" ,而是Address 192.168.1.x on eth0返回Address 192.168.1.x on eth0