ifconfig工具与驱动交互解析(ioctl)

Linux ifconfig(network interfaces configuring)

  • Linux ifconfig命令用于显示或设置网络设备。ifconfig可设置网络设备的状态,或是显示目前的设置。
  • 同netstat一样,ifconfig源码也位于net-tools中。
  • 源码位于net-tools工具包中,这是linux网络的基本工具包,此外还有arp,hostname,route等命令。

PS

此文章不考虑ifconfig的具体功能介绍,而是侧重与驱动和内核的交互,下面简单描述下该工具的使用实例,并且代码并不包含对于ifconfig的标准实现,仅是注重实现过程。

实例

$ ifconfig
eth0      Link encap:Ethernet  HWaddr 00:0c:29:e7:65:70
          inet addr:192.168.101.128  Bcast:192.168.101.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fee7:6570/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:17080658 errors:73 dropped:2 overruns:0 frame:0
          TX packets:17346739 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:4038046913 (4.0 GB)  TX bytes:2731849230 (2.7 GB)
          Interrupt:19 Base address:0x2000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:58049 errors:0 dropped:0 overruns:0 frame:0
          TX packets:58049 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:5540611 (5.5 MB)  TX bytes:5540611 (5.5 MB)

启动关闭指定网卡

# ifconfig eth0 down
# ifconfig eth0 up

用ifconfig修改MAC地址

# ifconfig eth0 down //关闭网卡
# ifconfig eth0 hw ether 00:AA:BB:CC:DD:EE //修改MAC地址
# ifconfig eth0 up //启动网卡

配置IP地址

# ifconfig eth0 192.168.1.56 
//给eth0网卡配置IP地址
# ifconfig eth0 192.168.1.56 netmask 255.255.255.0 
// 给eth0网卡配置IP地址,并加上子掩码
# ifconfig eth0 192.168.1.56 netmask 255.255.255.0 broadcast 192.168.1.255
// 给eth0网卡配置IP地址,加上子掩码,加上个广播地址

启用和关闭ARP协议

# ifconfig eth0 arp  //开启
# ifconfig eth0 -arp  //关闭

/proc/net/dev

$ cat /proc/net/dev
Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
    lo: 5558739   58239    0    0    0     0          0         0  5558739   58239    0    0    0     0       0          0
  eth0: 4038107838 17081103   73    2    0     0          0         0 2731895950 17347146    0    0    0     0       0          0
  • 这里列出了所有网络设备的其属性状态和收发包情况。ifconfig会open这个设备查找匹配信息。

那知道了如何使用该工具,那么具体是怎么实现的呢???
就到了下面的源码分析

代码分析

先来个简单的查看信息,如下是获取ip的流程

  1. 先通过ioctl获得本地所有接口的信息,并保存在ifconf中
  2. 再从ifconf中取出每一个ifreq中表示ip地址的信息

分析一:(获取ip地址)
接下来我们只需要从一个一个的接口信息获取ip地址信息即可。

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <linux/if.h>

 
int main()
{
    int i=0;
    int sockfd;
    struct ifconf ifconf;
    unsigned char buf[512];
    struct ifreq *ifreq;
    //初始化ifconf
    ifconf.ifc_len = 512;
    ifconf.ifc_buf = buf;
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0))<0)
    {
        exit(1);
    }
    ioctl(sockfd, SIOCGIFCONF, &ifconf); //获取所有接口信息
    //接下来一个一个的获取IP地址
    ifreq = (struct ifreq*)buf;
    for (i=(ifconf.ifc_len/sizeof (struct ifreq)); i>0; i--)
    {
        // if(ifreq->ifr_flags == AF_INET){ //for ipv4
        printf("name = [%s]\n" , ifreq->ifr_name);
        printf("local addr = [%s]\n" ,inet_ntoa(((struct sockaddr_in*)&(ifreq->ifr_addr))->sin_addr));
        ifreq++;
// }
    }
return 0;

执行结果

ifconfig_achieve$ ./ifconfig_wlan_ip.o
name = [lo]
local addr = [127.0.0.1]
name = [ens33]
local addr = [192.168.101.137]

解析:

  • ifc_len:表示用来存放所有接口信息的缓冲区长度
  • ifc_buf:表示存放接口信息的缓冲区
  • 用ioctl获得本地ip地址时要用到两个结构体ifconf和ifreq,我们需要在程序开始时对ifconf的ifc_len和ifc_buf进行初始化
  • 使用ioctl获取所有接口信息,完成后ifc_len内存放实际获得的接口信息总长度
    并且信息被存放在ifc_buf中。
  • struct ifconf:通常是用来保存所有接口信息的
  • struct ifreq:这个结构定义在include/net/if.h,用来配置ip地址,激活接口,配置MTU等接口信息的
  • 想要获取当前网口网线插入状态,需要用到ifreq结构体,获取网卡的信息,然后socket结合网卡驱动的ioctl,就可以得到与网线插入状态相关的数据。

简单部分罗列下上面的结构体:

//ifconf通常是用来保存所有接口信息的
struct ifconf
{
    int ifc_len; /* size of buffer */
    union
    {
        char *ifcu_buf; /* input from user->kernel*/
        struct ifreq *ifcu_req; /* return from kernel->user*/
    } ifc_ifcu;
};
#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
#define ifc_req ifc_ifcu.ifcu_req /* array of structures */
 
//ifreq用来保存某个接口的信息
struct ifreq 
{
    char ifr_name[IFNAMSIZ];
    union {
        struct sockaddr ifru_addr;
        struct sockaddr ifru_dstaddr;
        struct sockaddr ifru_broadaddr;
        short ifru_flags;
        int ifru_metric;
        caddr_t ifru_data;
    } ifr_ifru;
};
#define ifr_addr ifr_ifru.ifru_addr
#define ifr_dstaddr ifr_ifru.ifru_dstaddr
#define ifr_broadaddr ifr_ifru.ifru_broadaddr

分析二(获取基础信息,并更改设置ip)

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <linux/if.h>
#include <string.h>

#define INTERFACE "ens33"


void port_status(unsigned int flags)  
    { 
        if(flags & IFF_UP)    
        {  
            printf("is up\n");        
        }  
        if(flags & IFF_BROADCAST)     
        {  
            printf("is broadcast\n");     
        }  
        if(flags & IFF_LOOPBACK)      
        {  
            printf("is loop back\n");     
        }  
        if(flags & IFF_POINTOPOINT)   
        {  
            printf("is point to point\n");    
        }  
        if(flags & IFF_RUNNING)   
        {  
            printf("is running\n");   
        }  
        if(flags & IFF_PROMISC)   
        {  
            printf("is promisc\n");   
        }  
    }  

int main()
{
        int fd;
        struct ifreq buf[5];    //这个结构定义在/usr/include/net/if.h,用来配置和获取ip地址,掩码,MTU等接口信息的。 ifreq用来保存某个接口的信息 
        struct ifconf ifc;  //ifconf通常是用来保存所有接口信息的
        int ret = 0,i=0,j=0;      
        ifc.ifc_len = sizeof(buf);  
        ifc.ifc_buf = (caddr_t) buf;  
        uint32_t ip = 0x8165a8c0;//192.168.101.129
        struct sockaddr_in sin;
        if ((fd = socket(AF_INET, SOCK_DGRAM, 0))<0)
        {
        perror("socket" );
        exit(1);
        }
        else
        printf("----------fd:%d-----------\n",fd);
         
        ret = ioctl(fd, SIOCGIFCONF, (char*)&ifc);  
        if(ret)  
        {  
            printf("get if config info failed");  
            return -1;  
        }  
    for (i=(ifc.ifc_len/sizeof (struct ifreq)); i>0; i--)
    {
        printf("--------------name = [%s]------------\n" , buf[j].ifr_name);
        if(strcmp(buf[j].ifr_name,"ens33")==0)
        {
        printf("--------------ens33网卡---------------\n");
        strncpy(buf[j].ifr_name, INTERFACE, 5);
        memset(&sin, 0, sizeof(struct sockaddr));
        sin.sin_family = AF_INET;
        sin.sin_addr.s_addr = ip;
        memcpy(&buf[j].ifr_addr, &sin, sizeof(struct sockaddr));
        ret = ioctl(fd, SIOCSIFADDR, (char*)&buf[j]);
        if(ret)  
        continue;      
        }
        ret = ioctl(fd, SIOCGIFADDR, (char*)&buf[j]);  
            if(ret)  
                continue;
        printf("----------local addr = [%s]----------\n" ,inet_ntoa(((struct sockaddr_in*)&(buf[j].ifr_addr))->sin_addr));

        ret = ioctl(fd, SIOCGIFFLAGS, (char*)&buf[j]);  
            if(ret)  
                continue;  
        port_status(buf[j].ifr_flags);
        printf("--------------ifr_flags = [%d]------------\n" , buf[j].ifr_flags);

        ret = ioctl(fd, SIOCGIFMTU, (char*)&buf[j]);  
        if(ret)  
           continue;
        printf("-------mtu:%d----------\n",(unsigned int)(buf[j].ifr_ifru.ifru_mtu));
         /* 获取当前网卡的mac 命令cat /sys/class/net/eth0/address*/  
            ret = ioctl(fd, SIOCGIFHWADDR, (char*)&buf[j]);  
            if(ret)  
                continue;
        printf("%02x:%02x:%02x:%02x:%02x:%02x\n\n",  
                (unsigned char)buf[j].ifr_hwaddr.sa_data[0],  
                (unsigned char)buf[j].ifr_hwaddr.sa_data[1],  
                (unsigned char)buf[j].ifr_hwaddr.sa_data[2],  
                (unsigned char)buf[j].ifr_hwaddr.sa_data[3],  
                (unsigned char)buf[j].ifr_hwaddr.sa_data[4],  
                (unsigned char)buf[j].ifr_hwaddr.sa_data[5]  
                );
        j++;
        

    }
    close(fd);
return 0;
}

运行结果

./ifconfig_wlan.o
----------fd:3-----------
--------------name = [lo]------------
----------local addr = [127.0.0.1]----------
is up
is loop back
is running
--------------ifr_flags = [73]------------
-------mtu:65536----------
00:00:00:00:00:00

--------------name = [ens33]------------
--------------ens33网卡---------------
----------local addr = [192.168.101.129]----------
is up
is broadcast
is running
--------------ifr_flags = [4163]------------
-------mtu:1500----------
00:0c:29:24:11:8b

注意:
通过

gcc  ifconfig_wlan.c  -o ifconfig_wlan.o

命令编译出来的可执行文件本身是无法直接执行的,debug如下:

strace ./ifconfig_wlan.o

失败 log:
在这里插入图片描述
是由于编译的可执行文件权限不足导致ioctl设置失败,如下是解决流程:


 1. gcc ifconfig_wlan_information.c -o ifconfig_wlan_information.o
 2. sudo cp ifconfig_wlan_information.o ifconfig_wlan.o
 3. sudo chmod u+s ifconfig_wlan.o
 4. strace ./ifconfig_wlan.o

如下为再次执行后的结果:
在这里插入图片描述

结语

如上主要讲的是设置和获取,希望能够抛砖引玉,让大家学到更多

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/25958.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode】HOT 100(2)

题单介绍&#xff1a; 精选 100 道力扣&#xff08;LeetCode&#xff09;上最热门的题目&#xff0c;适合初识算法与数据结构的新手和想要在短时间内高效提升的人&#xff0c;熟练掌握这 100 道题&#xff0c;你就已经具备了在代码世界通行的基本能力。 目录 题单介绍&#…

软件测试测试环境搭建很难?一天学会这份测试环境搭建教程

如何搭建测试环境&#xff1f;这既是一道高频面试题&#xff0c;又是困扰很多小伙伴的难题。因为你在网上找到的大多数教程&#xff0c;乃至在一些培训机构的课程&#xff0c;都不会有详细的说明。 你能找到的大多数项目&#xff0c;是在本机电脑环境搭建环境&#xff0c;或是…

【单目标优化算法】孔雀优化算法(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

MySQL — 主从复制介绍

文章目录 主从复制一、概述二、原理三、 搭建主从复制结构3.1 服务器准备3.2 主库配置3.3 从库配置 主从复制 一、概述 ​ 主从复制是指将主数据库的DDL和DML操作通过二进制日志传到从库服务器中&#xff0c;然后在从库上对这些日志重新执行&#xff08;也叫重做&#xff09;…

1. TensorRT量化的定义及意义

前言 手写AI推出的全新TensorRT模型量化课程&#xff0c;链接&#xff1a;TensorRT下的模型量化。 课程大纲如下&#xff1a; 1. 量化的定义及意义 1.1 什么是量化&#xff1f; 定义 量化(Quantization)是指将高精度浮点数(如float32)表示为低精度整数(如int8)的过程&…

如何运用R语言进行Meta分析在【文献计量分析、贝叶斯、机器学习等】多技术的融合

Meta分析是针对某一科研问题&#xff0c;根据明确的搜索策略、选择筛选文献标准、采用严格的评价方法&#xff0c;对来源不同的研究成果进行收集、合并及定量统计分析的方法&#xff0c;最早出现于“循证医学”&#xff0c;现已广泛应用于农林生态&#xff0c;资源环境等方面。…

华为OD机试真题 Java 实现【高矮个子排队】【2023Q2 100分】,附详细解题思路

一、题目描述 现在有一队小朋友&#xff0c;他们高矮不同&#xff0c;我们以正整数数组表示这一队小朋友的身高&#xff0c;如数组{5,3,1,2,3}。 我们现在希望小朋友排队&#xff0c;以“高”“矮”“高”“矮”顺序排列&#xff0c;每一个“高”位置的小朋友要比相邻的位置高…

【配电网重构】基于改进二进制粒子群算法的配电网重构研究(Matlab代码实现

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

批量剪辑视频工具源码开发搭建分享

搭建步骤 1. 首先需要根据自身产品确定视频类型及需要实现的视频效果 2. 根据预期视频效果选择视频上传模式&#xff0c;并将视频素材进行上传 3. 添加音频、字幕&#xff0c;标题等与素材进行组合。 4. 设置投放计划&#xff0c;包括&#xff1a;视频标题、视频话题等 5.…

dom阶段实战内容

window定时器方法 ◼ 目前有两种方式可以实现&#xff1a;  setTimeout 允许我们将函数推迟到一段时间间隔之后再执行。  setInterval 允许我们重复运行一个函数&#xff0c;从一段时间间隔之后开始运行&#xff0c;之后以该时间间隔连续重复运行该函数。 ◼ 并且通常情况…

周赛347(模拟、思维题、动态规划+优化)

文章目录 周赛347[2710. 移除字符串中的尾随零](https://leetcode.cn/problems/remove-trailing-zeros-from-a-string/)模拟 [2711. 对角线上不同值的数量差](https://leetcode.cn/problems/difference-of-number-of-distinct-values-on-diagonals/)模拟 [2712. 使所有字符相等…

什么是分布式事务?

什么是分布式事务&#xff1f; 分布式对应的是单体架构&#xff0c;互联网早起单体架构是非常流行的&#xff0c;好像是一个家族企业&#xff0c;大家在一个家里劳作&#xff0c;单体架构如下图&#xff1a; 但是随着业务的复杂度提高&#xff0c;大家族人手不够&#xff0c;…

如何使用 Python Nornir 实现基于 CLI 的网络自动化?

在现代网络环境中&#xff0c;网络自动化已成为管理和配置网络设备的重要工具。Python Nornir 是一个强大的自动化框架&#xff0c;它提供了一个简单而灵活的方式来执行网络自动化任务。本文将详细介绍如何使用 Python Nornir 实现基于 CLI 的网络自动化。 1. Python Nornir 概…

view的常用属性和方法介绍(arcgis for javascript)

ArcGIS for JavaScript中的视图&#xff08;view&#xff09;是一个地图实例类&#xff0c;用于管理地图的显示区域、符号和标注等。通过视图类&#xff0c;可以实现以下功能&#xff1a; 显示地图&#xff1a;将地图显示在Web页面上。 缩放&#xff1a;缩放视图到指定的级别。…

SpringBoot 配置文件和日志文件

目录 一、SpringBoot配置文件 配置文件的格式 .properties配置文件格式 .yml配置文件格式 .properties 与 .yml的区别 配置文件的读取 .properties 与 .yml的区别 设置不同环境的配置⽂件 二、SpringBoot日志文件 日志打印的步骤 得到日志对象 方法一&#xff1a;使…

【网络】- 计算机网络体系结构 - OSI七层模型、TCP/IP四层(五层)协议

目录 一、概述 二、计算机网络体系结构的形成  &#x1f449;2.1 分层的网络体系结构  &#x1f449;2.2 OSI 参考模型  &#x1f449;2.3 TCP/IP - 事实的国际标准 三、OSI 参考模型 四、TCP/IP 协议 一、概述 但凡学习计算机网络知识&#xff0c;肯定绕不过网络协议的&…

SpringMVC拦截器

SpringMVC拦截器 介绍 拦截器&#xff08;interceptor&#xff09;的作用 SpringMVC的拦截器类似于Servlet开发中的过滤器Filter&#xff0c;用于对处理器 进行预处理和后处理 将拦截器按一定的顺序连接成一条链&#xff0c;这条链称为拦截器链&#xff08;Interception Ch…

hive中如何计算字符串中表达式

比如 select 1(2-3)(-4.1-3.1)-(4-3)-(-3.34.3)-1 col ,1(2-3)(-4.1-3.1)-(4-3)-(-3.34.3)-1 result \ 现在的需求式 给你一个字符串如上述col 你要算出result。 前提式 只有和-的运算&#xff0c;而且只有嵌套一次 -(4-3)没有 -(-4(3-(31)))嵌套多次。 第一步我们需要将运…

【学习笔记】Python核心技术与实战-基础篇-03列表和元组,到底用哪个?

目录 列表和元组基础概念区别列表和元组的基础操作和注意事项列表和元组存储方式的差异列表和元组的性能列表和元组的使用场景总结思考题 列表和元组基础 概念 列表和元组&#xff0c;都是一个可以放置任意数据类型的有序集合。 在绝大多数编程语言中&#xff0c;集合的数据类…

js数据类型和六种运算结果为false的情况

数据类型 number&#xff1a;数字&#xff08;整数、小数、NaN(Not a Number)&#xff09; string&#xff1a;字符串、单双引皆可 boolean&#xff1a;布尔。true、false null&#xff1a;对象为空 undefined&#xff1a;当声明的变量初始化时&#xff0c;该变量的默认值…