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

news2024/9/29 1:26:28

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

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

结语

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《消息队列高手课》课程笔记(七)

如何使用异步设计提升系统性能&#xff1f; 异步设计如何提升系统性能&#xff1f; 假设我们要实现一个转账的微服务 Transfer(accountFrom, accountTo, amount)&#xff0c;这个服务有三个参数&#xff1a;分别是转出账户、转入账户和转账金额。 这个例子的实现过程中&…

chatgpt赋能python:Python中如何反转字符串:三种简单方法

Python中如何反转字符串&#xff1a;三种简单方法 当我们在处理字符串时&#xff0c;有时需要将其反向排列。在Python中&#xff0c;这可以通过以下三种简单方法实现&#xff1a; 1. 使用内置的切片方法 在Python中&#xff0c;可以使用字符串的切片方法将其反转。这种方法非…

(浙大陈越版)数据结构 第三章 树(上) 3.4 小白专场:树的同构(PTA编程题讲解)

题意理解和二叉树表示 给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换变成T2&#xff0c;则称两棵树是“同构”的。 eg1&#xff1a;现请你判断如下两棵树&#xff08;左侧为T1&#xff0c;右侧为T2&#xff09;是否为同构树&#xff1f; 显然T1可以通过有限次左右孩子…

REST风格 -- SpringMVC入门保姆级教程(四)

文章目录 前言四、REST风格1.了解REST风格2.REST风格写法一般步骤3.REST风格快速开发4.REST风格中的注解5. 案例&#xff1a;基于REST风格页面数据交互 总结 前言 为了巩固所学的知识&#xff0c;作者尝试着开始发布一些学习笔记类的博客&#xff0c;方便日后回顾。当然&#…

Redis高级篇 - 分布式缓存

分布式缓存 基于Redis集群解决单机Redis存在的问题 单机的Redis存在四大问题&#xff1a; 1.Redis持久化 Redis有两种持久化方案&#xff1a; RDB持久化AOF持久化 1.1.RDB持久化 RDB全称Redis Database Backup file&#xff08;Redis数据备份文件&#xff09;&#xff0c…

iPad触屏笔哪个牌子好用?Apple Pencil的平替笔

从无纸化的广泛使用&#xff0c;电容笔成为无纸化中不可替代的一部分。但由于原装电容笔的昂贵&#xff0c;市面上的电容笔品牌众多&#xff0c;不知如何下手&#xff0c;今天给大家推荐几款好用又平价的Apple Pencil平替笔。顺便给不知道如何挑选电容笔的小伙伴科普一下电容笔…

车载网络测试 - CANCANFD - 基础篇_02

目录 七、与CAN总线相关的标准 1、ISO 11898,ISO16845 2、SAE J1939,ISO 11783,NMEA 2000,CANopen 3、ISO15765/ISO14229 4、ISO 17356/OSEK 5、CCP(CAN Calibration Protocol) 6、GMLAN,VWTP,FNOS,DCNet,MCNet 八、CAN总线的特点 九、CAN总线基本概念 七、与CAN总线相…

机器学习-4 决策树算法

决策树算法 算法概述分类算法与分类器决策树算法树模型决策树的原理决策树算法的关键决策树构造的基本思路 算法基本思想决策树的训练与测试三种经典的决策树生成算法基于信息增益的ID3算法基于信息增益率的C4.5算法C4.5算法C5.0算法 基于基尼系数的CART算法 算法流程算法关键问…

chatgpt赋能python:Python中的包

Python中的包 对于使用Python进行编程的开发者来说&#xff0c;包是一个非常重要的概念。包可以看作是一个包含了多个模块的文件夹&#xff0c;这些模块可以在代码中使用。通过使用Python中的包&#xff0c;开发者可以使代码更加模块化&#xff0c;提高代码的可维护性和可读性…

Emacs之git操作(一百零五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

Apache Impala(1):Impala简介

1 Impala 基本介绍 impala 是 cloudera 提供的一款高效率的 sql 查询工具&#xff0c;提供实时的查询效果&#xff0c;官方测试性能比 hive 快 10 到 100 倍&#xff0c;其 sql 查询比 sparkSQL 还要更加快速&#xff0c;号称是当前大数据领域最快的查询 sql 工具&#xff0c…

小主机折腾记13

这个月折腾的事比较多&#xff0c;记个流水账 1.600g2mt加装wifi模块&#xff1b; 买了ngff转pcie的转接卡&#xff0c;发现竟然不能原生支持蓝牙&#xff0c;需要额外接一个4pin转9针usb的线&#xff0c;600g2mt是没有那种通用的usb9针口的…… 而内建蓝牙的转接卡网上也有卖&…

【项目】ROS下使用N100模块

本文主要记录如何使用WHEELTEC N100 模块。 之前的版本是CP2102串口芯片&#xff0c;而2022年5月之后的N100采用的是CH9102串口芯片。 一、修改串口号&#xff1a; 工具&#xff1a;链接&#xff1a;https://pan.baidu.com/s/13Pdq45_Z0ZRwuaNN0I84Cg 提取码&#xff1a;i6j…

《深入理解计算机系统(CSAPP)》第6章 存储器层次结构 - 学习笔记

写在前面的话&#xff1a;此系列文章为笔者学习CSAPP时的个人笔记&#xff0c;分享出来与大家学习交流&#xff0c;目录大体与《深入理解计算机系统》书本一致。因是初次预习时写的笔记&#xff0c;在复习回看时发现部分内容存在一些小问题&#xff0c;因时间紧张来不及再次整理…

【计算机网络详解】——应用层(学习笔记)

&#x1f4d6; 前言&#xff1a;应用层是计算机网络体系结构的最顶层&#xff0c;是设计和建立计算机网络的最终目的&#xff0c;也是计算机网络中发展最快的部分。在本文中&#xff0c;我们以一些经典的网络应用为例来学习有关网络应用的原理、协议和实现方面的知识。 目录 &a…

华为OD机试真题B卷 Java 实现【快速寻找某字符】,附详细解题思路

一、题目描述 给定一个一个目标值 target和一个 元素升序的无重复数字字符串 &#xff0c;写一个函数搜索 字符串 中的 target&#xff0c;如果目标值存在返回下标&#xff08;下标从 0 开始&#xff09;&#xff0c;否则返回 -1。 二、输入描述 第一行输入一个目标值target…

在Centos Stream 9上Docker的实操教程(三) - Docker容器数据卷

在Centos Stream 9上Docker的实操教程 - Docker容器数据卷 问题场景Docker容器数据卷简单介绍数据卷使用操作实例安装redis验证配置文件生效验证数据是否丢失 结语 问题场景 Docker容器我们可以理解就是微型的linux系统&#xff0c;在使用容器的时候自然会产生一系列数据文件&…

基于SpringBoot+Vue的儿童书法机构管理系统

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 儿童书法机构的管理是…

代码随想录算法训练营第四十二天 | 二维dp数组01背包, 力扣 416. 分割等和子集

背包 解析 1.确定dp数组以及下标的含义 对于背包问题&#xff0c;有一种写法&#xff0c; 是使用二维数组&#xff0c;即dp[i][j] 表示从下标为[0-i]的物品里任意取&#xff0c;放进容量为j的背包&#xff0c;价值总和最大是多少。 2.确定递推公式 有两个方向推出来dp[i][…

跨境电商app开发搭建多语言商城后的运营技巧,一件了解电子商城及运营

跨境电商APP包含&#xff1a;买家端手机H5版本, 电脑Pc网页版本, 安卓苹果App。 一、模式介绍 如需要探讨&#xff0c;请kan 名片。 无货源模式&#xff1a;电商平台上的卖家不需要自己拥有实体的库存&#xff0c;而是通过与供应链服务提供商合作&#xff0c;将订单和支付…