请问如何从接口IP地址获取接口索引? 例如,如果接口IP地址为192.168.23.25,则它的接口索引是什么。
我想补充一点,我需要在C语言编写的代码中使用它,所以如果有任何带有某些选项的函数可以根据接口IP地址给我接口索引号。
请问如何从接口IP地址获取接口索引? 例如,如果接口IP地址为192.168.23.25,则它的接口索引是什么。
我想补充一点,我需要在C语言编写的代码中使用它,所以如果有任何带有某些选项的函数可以根据接口IP地址给我接口索引号。
ip addr add 192.168.25.23/24 dev eth0
lo address family: 17 (AF_PACKET)
eth0 address family: 17 (AF_PACKET)
lo address family: 2 (AF_INET)
address: <127.0.0.1>
eth0 address family: 2 (AF_INET)
address: <192.168.1.105>
eth0 address family: 2 (AF_INET)
address: <192.168.25.23>
lo address family: 10 (AF_INET6)
address: <::1>
eth0 address family: 10 (AF_INET6)
address: <fe84::82d6:baaf:fe14:4c22%eth0>
#include <net/if.h>
#include <stdio.h>
#include <errno.h>
int main(int argc, char *argv[])
{
for (int ix=1; ix<argc; ix++)
{
unsigned int rc = if_nametoindex(argv[ix]);
if (rc) {
printf("interface [%s] has index : %d\n", argv[ix], rc);
}
else {
perror("if_nametoindex");
}
}
}
使用示例:
$ ./if_index eth0
interface [eth0] has index : 2
$ cat /proc/net/if_inet6
00000000000000000000000000000001 01 80 10 80 lo
fe800000000000000a0027fffe1a2a32 03 40 20 80 eth1
fe800000000000000a0027fffe08b9ca 02 40 20 80 eth0
# ip a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
...
使用正确的参数:
# ip -json a s lo | jq '.[] | .ifindex'
1
# ip -json a s enp2s0 | jq '.[] | .ifindex'
2
ip -json a s lo
表示 ip -json address show lo
,而 ip -json a s enp2s0
表示 ip -json address show enp2s0
。 - chris你不能这样做,你需要查看所有接口,然后循环遍历所有IP地址,直到找到你想要的那一个。我认为这段代码可以实现你的需求。
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
in_addr_t ia;
int id;
ia = inet_addr(argv[1]);
id = do_lookup(ia);
}
int do_lookup(in_addr_t ia) {
char buf[1024];
struct ifconf ifc;
struct ifreq *ifr;
int sck;
int nInterfaces;
int i;
/* Get a socket handle. */
sck = socket(AF_INET, SOCK_DGRAM, 0);
if(sck < 0)
{
perror("socket");
return -1;
}
/* Query available interfaces. */
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
if(ioctl(sck, SIOCGIFCONF, &ifc) < 0)
{
perror("ioctl(SIOCGIFCONF)");
return -1;
}
/* Iterate through the list of interfaces. */
ifr = ifc.ifc_req;
nInterfaces = ifc.ifc_len / sizeof(struct ifreq);
for(i = 0; i < nInterfaces; i++)
{
struct ifreq *item = &ifr[i];
if(((struct sockaddr_in *)&item->ifr_addr)->sin_addr.s_addr == ia) {
return i;
}
}
return -1;
}
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <arpa/inet.h>
int main(void)
{
char buf[1024];
struct ifconf ifc;
struct ifreq *ifr;
int sck;
int nInterfaces;
int i;
/* Get a socket handle. */
sck = socket(AF_INET, SOCK_DGRAM, 0);
if(sck < 0)
{
perror("socket");
return 1;
}
/* Query available interfaces. */
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
if(ioctl(sck, SIOCGIFCONF, &ifc) < 0)
{
perror("ioctl(SIOCGIFCONF)");
return 1;
}
/* Iterate through the list of interfaces. */
ifr = ifc.ifc_req;
nInterfaces = ifc.ifc_len / sizeof(struct ifreq);
for(i = 0; i < nInterfaces; i++)
{
struct ifreq *item = &ifr[i];
/* Show the device name and IP address */
printf("%s: IP %s",
item->ifr_name,
inet_ntoa(((struct sockaddr_in *)&item->ifr_addr)->sin_addr));
/* Get the MAC address */
if(ioctl(sck, SIOCGIFHWADDR, item) < 0)
{
perror("ioctl(SIOCGIFHWADDR)");
return 1;
}
/* Get the broadcast address (added by Eric) */
if(ioctl(sck, SIOCGIFBRDADDR, item) >= 0)
printf(", BROADCAST %s", inet_ntoa(((struct sockaddr_in *)&item->ifr_broadaddr)->sin_addr));
printf("\n");
}
return 0;
}
我从这里得到了它。
ip addr add 192.168.25.23/24 dev eth1
注意:我刚刚注意到原帖要求使用C
语言解决。非常抱歉。然而,由于搜索引擎将我明确包含bash的搜索短语带到了这里(而且我已经输入了所有这些内容),希望大家不介意我在这里留下它。如果有时间,我会稍后将其转换为gist,并尝试在此处删除它。
我有一个相对简单的解决方案,适用于shell脚本。我喜欢@Oliver的建议,但它没有达到获取给定IP地址接口索引的原始目标。我稍微调整了他的答案。假设我想知道当前绑定到192.168.1.96的接口索引是哪个。这种方法可以工作:
chris@anglesey:~$ ip -json address show \
| jq '.[] | select(.addr_info[].local == "192.168.1.96") | .ifindex'
输出:
60
.ifindex
元素来检查它是否正确,从而获取网卡的所有 JSON 数据。chris@anglesey:~$ ip -json address show | jq '.[] | select(.addr_info[].local == "192.168.1.96") '
{
"ifindex": 60,
"ifname": "enx808abdbef5eb",
"flags": [
"BROADCAST",
"MULTICAST",
"UP",
"LOWER_UP"
],
"mtu": 1500,
"qdisc": "fq_codel",
"operstate": "UP",
"group": "default",
"txqlen": 1000,
"link_type": "ether",
"address": "80:8a:bd:be:f5:eb",
"broadcast": "ff:ff:ff:ff:ff:ff",
"addr_info": [
{
"family": "inet",
"local": "192.168.1.96",
"prefixlen": 24,
"broadcast": "192.168.1.255",
"scope": "global",
"dynamic": true,
"noprefixroute": true,
"label": "enx808abdbef5eb",
"valid_life_time": 71302,
"preferred_life_time": 71302
},
{
"family": "inet6",
"local": "fe80::767a:4f36:1fb0:cd0b",
"prefixlen": 64,
"scope": "link",
"noprefixroute": true,
"valid_life_time": 4294967295,
"preferred_life_time": 4294967295
}
]
}
通过更改命令中给定的IP地址,此方法将自动处理辅助地址和IPv6地址。
此外,如果您只知道要查找的地址的子字符串,则可以进行微小调整以查找该地址。虽然不能像按子网过滤那样有用,但有时可能会有所帮助。
chris@anglesey:~$ ip -json addr show | jq '.[] | select(.addr_info[].local | contains("192.168.1")) | .ifindex'
输出:
60