首页 > 其他分享 >C语言getifaddrs()通过网口IP获取网口名

C语言getifaddrs()通过网口IP获取网口名

时间:2023-05-15 18:11:55浏览次数:55  
标签:forever 00 IP getifaddrs lft 网口 ifa ff include

原文地址:https://www.cnblogs.com/liqinglucky/p/getifaddrs.html

用C语言实现通过ip地址获取到本地网口名。比如我知道网口IP是173.1.4.53,怎么通过这个IP匹配出网口是ens9?

# ip addr
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: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:f2:d2:cc brd ff:ff:ff:ff:ff:ff
    inet 193.9.3.23/24 brd 193.9.3.255 scope global ens3
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:fef2:d2cc/64 scope link
       valid_lft forever preferred_lft forever
3: ens9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:6f:83:74 brd ff:ff:ff:ff:ff:ff
    inet 173.1.4.53/24 brd 173.1.4.255 scope global ens9
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:fe6f:8374/64 scope link
       valid_lft forever preferred_lft forever

初步思路是利用linux命令:ip addr获取接口和ip的方式遍历所有linux的ip和网口名。然后C语言去匹配过滤ip就能拿到对应的网口名。

调查发现linux命令:ip addr不是读文件的,直接调的接口getifaddrs[1]

遍历所有网口[2]

方案1:

代码iface.c

#include <net/if.h>
#include <stdio.h>

int main (void)
{
    struct if_nameindex *if_nidxs, *intf;

    if_nidxs = if_nameindex();
    if ( if_nidxs != NULL )
    {
        for (intf = if_nidxs; intf->if_index != 0 || intf->if_name != NULL; intf++)
        {
            printf("%s\n", intf->if_name);
        }

        if_freenameindex(if_nidxs);
    }

    return 0;
}

测试

# gcc iface.c -o iface
# ./iface
lo
ens3
ens9

方案2:

代码ifaddr.c

#include <stdio.h>
#include <net/if.h>
#include <ifaddrs.h>

int main (void)
{
    struct ifaddrs *addrs,*tmp;

    getifaddrs(&addrs);
    tmp = addrs;

    while (tmp)
    {
        if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_PACKET)
            printf("%s '%s'\n", tmp->ifa_name,tmp->ifa_addr->sa_data);

        tmp = tmp->ifa_next;
    }

    freeifaddrs(addrs);

    return 0;
}

测试:

# gcc ifaddr.c -o ifaddr
# ./ifaddr
lo ''
ens3 ''
ens9 ''

通过网口IP获取网口名[3]

这里代码参考[4]getifaddrs()官方例子。

官方代码运行:

# ./main
lo       AF_PACKET (17)
                tx_packets =   13989603; rx_packets =   13989603
                tx_bytes   = 1126608262; rx_bytes   = 1126608262
ens3     AF_PACKET (17)
                tx_packets =    4187731; rx_packets =    8975400
                tx_bytes   = 3827704908; rx_bytes   =  807683670
ens9     AF_PACKET (17)
                tx_packets =    1219601; rx_packets =    7449959
                tx_bytes   =  110307334; rx_bytes   =  696553525
lo       AF_INET (2)
                address: <127.0.0.1>
ens3     AF_INET (2)
                address: <193.9.3.23>
ens9     AF_INET (2)
                address: <173.1.4.53>

根据getifaddrs()官方示例代码,匹配ifa->ifa_addr后,ifa->ifa_name就是网卡名。
代码:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/if_link.h>
#include <string.h>

int main(int argc, char *argv[])
{
    struct ifaddrs *ifaddr;
    int family, s;
    char host[NI_MAXHOST];

    if (getifaddrs(&ifaddr) == -1) {
        perror("getifaddrs");
        exit(EXIT_FAILURE);
    }

    for (struct ifaddrs *ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr == NULL)
            continue;

        family = ifa->ifa_addr->sa_family;

        if (family == AF_INET || family == AF_INET6) {
            s = getnameinfo(ifa->ifa_addr,
                    (family == AF_INET) ? sizeof(struct sockaddr_in) :
                                          sizeof(struct sockaddr_in6),
                    host, NI_MAXHOST,
                    NULL, 0, NI_NUMERICHOST);
            if (s != 0) {
                printf("getnameinfo() failed: %s\n", gai_strerror(s));
                exit(EXIT_FAILURE);
            }
            if( !strcmp(host, "173.1.4.53")){
                printf("%-8s ",ifa->ifa_name);
                printf("address: <%s>\n", host);
            }

        } 
    }

    freeifaddrs(ifaddr);
    exit(EXIT_SUCCESS);
}

测试:

# gcc main.c -o main
# ./main
ens9     address: <173.1.4.53>

参考:


  1. Linxu的struct ifaddrs 与getifaddrs()函数 - 月未央 - 博客园 (cnblogs.com) ↩︎

  2. c - Linux getting all network interface names - Stack Overflow ↩︎

  3. C code to get the interface name for the IP address in Linux - Stack Overflow ↩︎

  4. getifaddrs(3) - Linux manual page (man7.org) ↩︎

标签:forever,00,IP,getifaddrs,lft,网口,ifa,ff,include
From: https://www.cnblogs.com/liqinglucky/p/getifaddrs.html

相关文章

  • 使用Eclipse JEE+Mtj+Nokia S60 V3SDK开发J2ME应用的环境搭建
    使用EclipseJEE+Mtj+NokiaS60V3SDK开发J2ME应用的环境搭建2010-04-0716:53   在NokiaS60V3下进行J2ME应用程序开发,需要搭建Nokia官方提供的SDK环境。一般的J2ME应用开发使用Sun公司的J2MESDK就可以了,如果需要开发基于NokiaS60手机应用,就需要Noki......
  • fMRIPrep
    Step1InstallDocker apt-getinstalldocker.io-yAdduserwhichcanexecutedocker sudousermod-aGdocker${USER}PullDockerimagesdockerpullnipreps/fmriprep:20.2.2dockerpullnipreps/fmriprep:latest Refer: https://www.nipreps.org/apps/......
  • bash: pip: command not found...
     001、[root@PC1test]#pipbash:pip:commandnotfound...  002、[root@PC1test]#cat/etc/redhat-release 003、[root@PC1software]#curlhttps://bootstrap.pypa.io/pip/2.7/get-pip.py-oget-pip.py[root@PC1software]#pythonget-pip.py ......
  • 40+JavaScript进阶单行代码
    数组//生成数组0-99的数组//方案1constcreateArr=(n)=>Array.from(newArray(n),(v,i)=>i);letarr=createArr(100);console.log(arr);//方案2constcreateArr=(n)=>newArray(n).fill(0).map((v,i)=>i)......
  • MATLAB用yalmip+cplex解决电动汽车有序充放电问题,目标函数为总负荷峰谷差最小,代码可运
    MATLAB用yalmip+cplex解决电动汽车有序充放电问题,目标函数为总负荷峰谷差最小,代码可运行且有注释。YID:5335653801669338......
  • Linux下基于iptables的hashlimit模块限速
    记录一下:【对目标IP限制下载速率】出站包,目标IP为x.x.x.x,限速200KBytes/s:iptables-AOUTPUT-dx.x.x.x-mhashlimit--hashlimit-above200kb/s--hashlimit-modedstip--hashlimit-nameout-jDROP 【对自身tcp/12345提供的服务限制下载速率】出站包,源端口是tcp/12......
  • UIpath Orchestrator 环境与安装
    前言之前曾经参与过几个uipath的项目,都有用到Orchestrator(下面简称OC),直到去年出了最新的正式版OC,由于项目的特殊性,也遇到了一些之前未遇到过的问题,借此机会想把一些安装过程以及期间遇到的问题都罗列出来,希望各位可以少走一点弯路。所谓的特殊性完全是一部空的机器,就只有一个干......
  • eclipse插件WindowBuilder安装方式
    用在线安装,先启动eclipse,点菜单栏里帮助,再点里面的INSTALLNEWSOFTWARE,http://code.google.com/intl/zh-CN/javadevtools/download-wbpro.html 这网址里有3个版本,看你的是什么版本,直接把网址复制到WORKWITH里面去,等一下在下面的框里就会出现WINDOWBUILDER,全选,然后下一步···......
  • 基于matlab的yalmip+cplex的两阶段鲁棒微电网two_stage robust optimization
    基于matlab的yalmip+cplex的两阶段鲁棒微电网two_stagerobustoptimization微电网双层场景两阶段鲁棒规划方法,目标函数包含投资成本和运行成本,其中,投资成本主要为储能的等年值投资成本,运行成本则包括配电网交互成本(购售电成本)、各单元运维成本以及微型燃气轮机的燃料成本。包含储......
  • vue3+ swiper8
    swiper是一个非常好用的图片切换组件,但是vue3+swiper8版本的文档看上去会有点懵逼(一部分是因为版本太多了,一部分是因为很少用)此处记录下我的使用方法:安装:npmiswiper按照官网来使用:html部分:(基本上常用的也就这些啦,在复杂的就真的要去啃书啦)<swiper//在swiper......