Linux下C语言操作网卡的几个代码实例?特别实用

news2024/11/30 5:00:24

前面写了一篇关于网络相关的文章:如何获取当前可用网口。

《简简单单教你如何用C语言列举当前所有网口!》

那么如何使用C语言直接操作网口?

比如读写IP地址、读写MAC地址等。

一、原理

主要通过系统用socket()、ioctl()、实现

int socket(int domain, int type, int protocol);
功能:
    创建套接字
参数:
	domain: 
		Name                Purpose                          Man page
		AF_UNIX, AF_LOCAL   Local communication              unix(7)
		AF_INET             IPv4 Internet protocols          ip(7)

	type:
		SOCK_STREAM     Provides sequenced, reliable, two-way, connection-based
	                     byte  streams.  An out-of-band data transmission mecha‐
	                     nism may be supported.
	     SOCK_DGRAM      Supports datagrams (connectionless, unreliable messages
	                     of a fixed maximum length).
	protocol:
		通常为0
返回值:
	成功:新的套接字的文件描述符
	失败:错误码,负值
int ioctl(int fd, unsigned long request, ...);
参数:
   fd :文件描述符
   request:命令
   ... :参数

其中网络用到的request定义头文件位于:

/usr/include/linux/sockios.h
/* Linux-specific socket ioctls */
#define SIOCINQ		FIONREAD
#define SIOCOUTQ	TIOCOUTQ        /* output queue size (not sent + not acked) */

/* Routing table calls. */
#define SIOCADDRT	0x890B		/* add routing table entry	*/
#define SIOCDELRT	0x890C		/* delete routing table entry	*/
#define SIOCRTMSG	0x890D		/* call to routing system	*/

/* Socket configuration controls. */
#define SIOCGIFNAME	0x8910		/* get iface name		*/
#define SIOCSIFLINK	0x8911		/* set iface channel		*/
#define SIOCGIFCONF	0x8912		/* get iface list		*/
#define SIOCGIFFLAGS	0x8913		/* get flags			*/
#define SIOCSIFFLAGS	0x8914		/* set flags			*/
#define SIOCGIFADDR	0x8915		/* get PA address		*/
#define SIOCSIFADDR	0x8916		/* set PA address		*/
#define SIOCGIFDSTADDR	0x8917		/* get remote PA address	*/
#define SIOCSIFDSTADDR	0x8918		/* set remote PA address	*/
#define SIOCGIFBRDADDR	0x8919		/* get broadcast PA address	*/
#define SIOCSIFBRDADDR	0x891a		/* set broadcast PA address	*/
#define SIOCGIFNETMASK	0x891b		/* get network PA mask		*/
#define SIOCSIFNETMASK	0x891c		/* set network PA mask		*/
#define SIOCGIFMETRIC	0x891d		/* get metric			*/
#define SIOCSIFMETRIC	0x891e		/* set metric			*/
#define SIOCGIFMEM	0x891f		/* get memory address (BSD)	*/
#define SIOCSIFMEM	0x8920		/* set memory address (BSD)	*/
#define SIOCGIFMTU	0x8921		/* get MTU size			*/
#define SIOCSIFMTU	0x8922		/* set MTU size			*/
#define SIOCSIFNAME	0x8923		/* set interface name */
#define	SIOCSIFHWADDR	0x8924		/* set hardware address 	*/
#define SIOCGIFENCAP	0x8925		/* get/set encapsulations       */
#define SIOCSIFENCAP	0x8926		
#define SIOCGIFHWADDR	0x8927		/* Get hardware address		*/
#define SIOCGIFSLAVE	0x8929		/* Driver slaving support	*/
#define SIOCSIFSLAVE	0x8930
#define SIOCADDMULTI	0x8931		/* Multicast address lists	*/
#define SIOCDELMULTI	0x8932
#define SIOCGIFINDEX	0x8933		/* name -> if_index mapping	*/
#define SIOGIFINDEX	SIOCGIFINDEX	/* misprint compatibility :-)	*/
#define SIOCSIFPFLAGS	0x8934		/* set/get extended flags set	*/
#define SIOCGIFPFLAGS	0x8935
#define SIOCDIFADDR	0x8936		/* delete PA address		*/
#define	SIOCSIFHWBROADCAST	0x8937	/* set hardware broadcast addr	*/
#define SIOCGIFCOUNT	0x8938		/* get number of devices */
……

其中ioctl的参数需要借助结构体struct ifreq
定义头文件:

/usr/include/linux/if.h
#if __UAPI_DEF_IF_IFREQ
struct ifreq {
#define IFHWADDRLEN	6
	union
	{
		char	ifrn_name[IFNAMSIZ];		/* if name, e.g. "en0" */
	} ifr_ifrn;
	
	union {
		struct	sockaddr ifru_addr;
		struct	sockaddr ifru_dstaddr;
		struct	sockaddr ifru_broadaddr;
		struct	sockaddr ifru_netmask;
		struct  sockaddr ifru_hwaddr;
		short	ifru_flags;
		int	ifru_ivalue;
		int	ifru_mtu;
		struct  ifmap ifru_map;
		char	ifru_slave[IFNAMSIZ];	/* Just fits the size */
		char	ifru_newname[IFNAMSIZ];
		void *	ifru_data;
		struct	if_settings ifru_settings;
	} ifr_ifru;
};
#endif /* __UAPI_DEF_IF_IFREQ */

#define ifr_name	ifr_ifrn.ifrn_name	/* interface name 	*/
#define ifr_hwaddr	ifr_ifru.ifru_hwaddr	/* MAC address 		*/
#define	ifr_addr	ifr_ifru.ifru_addr	/* address		*/
#define	ifr_dstaddr	ifr_ifru.ifru_dstaddr	/* other end of p-p lnk	*/
#define	ifr_broadaddr	ifr_ifru.ifru_broadaddr	/* broadcast address	*/
#define	ifr_netmask	ifr_ifru.ifru_netmask	/* interface net mask	*/
#define	ifr_flags	ifr_ifru.ifru_flags	/* flags		*/
#define	ifr_metric	ifr_ifru.ifru_ivalue	/* metric		*/
#define	ifr_mtu		ifr_ifru.ifru_mtu	/* mtu			*/
#define ifr_map		ifr_ifru.ifru_map	/* device map		*/
#define ifr_slave	ifr_ifru.ifru_slave	/* slave device		*/
#define	ifr_data	ifr_ifru.ifru_data	/* for use by interface	*/
#define ifr_ifindex	ifr_ifru.ifru_ivalue	/* interface index	*/
#define ifr_bandwidth	ifr_ifru.ifru_ivalue    /* link bandwidth	*/
#define ifr_qlen	ifr_ifru.ifru_ivalue	/* Queue length 	*/
#define ifr_newname	ifr_ifru.ifru_newname	/* New name		*/
#define ifr_settings	ifr_ifru.ifru_settings	/* Device/proto settings*/

二、函数实现

下面将实现不同功能的函数一一列举。

0. 列出所有可用网口

int list_all_port()
{
        struct ifconf ifconf;
        struct ifreq *ifr;
        int m, n, s, fd;

        if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
            return -11;
        }

        s = sizeof(struct ifreq)*5;
        for (;;) {
            ifr = malloc(s);

            ifconf.ifc_len = s;
            ifconf.ifc_req = ifr;
            
            if (ioctl(fd, SIOCGIFCONF, &ifconf) < 0) {
				perror("SIOCGIFCONF:");
                free(ifr);
                close(fd);
                return 1;
            }
                
            
            if (ifconf.ifc_len != s)
                break;
                
            free(ifr);
            s *= 2;
        }

        close(fd);
        
        m = ifconf.ifc_len/sizeof(struct ifreq);
        for (n = 0; n < m; n++)
		{
			printf("port:\t%s\n",ifconf.ifc_req[n].ifr_name);
		}
        free(ifr);
}

1. 获取指定网卡IP

int getLocalIp(const char *eth, char *ip) {
    struct ifreq ifr;
    struct sockaddr_in sin;
    int fd;
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);
    if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
        close(fd);
        return -1;
    }
    memcpy(&sin, &ifr.ifr_addr, sizeof(sin));
    snprintf(ip, IP_SIZE, "%s", inet_ntoa(sin.sin_addr));
    close(fd);
    return 0;
}

2. 设置本网卡IP地址

int setIpAddrManual(const char *eth, char *ipstr) {
    int fd;
    struct sockaddr_in sin;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);

	sin.sin_addr.s_addr = inet_addr(ipstr);
	
	sin.sin_family = AF_INET;
    memcpy(&ifr.ifr_addr, &sin, sizeof(sin));
	
    if (ioctl(fd, SIOCSIFADDR, &ifr) < 0)
    {
    	perror("");
        close(fd);
        return -1;
    }
    close(fd);
    return 0;
} 

3. 获取本机网卡Mac地址

int getLocalMac(const char *eth, char *mac) {


    int fd;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);
    if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0)
    {
        close(fd);
        return -1;
    }
   snprintf(mac,18, "%02x:%02x:%02x:%02x:%02x:%02x",
         (unsigned char) ifr.ifr_hwaddr.sa_data[0],
         (unsigned char) ifr.ifr_hwaddr.sa_data[1],
         (unsigned char) ifr.ifr_hwaddr.sa_data[2],
         (unsigned char) ifr.ifr_hwaddr.sa_data[3],
         (unsigned char) ifr.ifr_hwaddr.sa_data[4],
         (unsigned char) ifr.ifr_hwaddr.sa_data[5]);
    close(fd);
    return 0;

} 

4. 设置网卡mac地址

/*
support format [00:11:22:33:44:55]
*/
#define MAC_ARRAY(mac_array)  (unsigned int *)&mac_array[0],(unsigned int *)&mac_array[1],(unsigned int *)&mac_array[2],(unsigned int *)&mac_array[3],(unsigned int *)&mac_array[4],(unsigned int *)&mac_array[5] 
int setLocalMac(const char *eth, char *mac) {
    int fd;
    struct ifreq ifr;
	unsigned char mac_array[6] = {0};
	
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);
	ifr.ifr_hwaddr.sa_family = AF_LOCAL;
	
	sscanf(mac,"%02x:%02x:%02x:%02x:%02x:%02x",
		MAC_ARRAY(mac_array));

	memcpy(ifr.ifr_hwaddr.sa_data,mac_array,6);

    if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0)
    {
    	perror("SIOCSIFHWADDR:");
        close(fd);
        return -1;
    }

    close(fd);
    return 0;
} 

注意:

  • 网卡地址的第一字节必须是偶数
  • sa_family 值必须为:AF_LOCAL

5. 获取网卡mtu

int getMtu(const char *eth, char *mtu) {
    int fd;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);
    if (ioctl(fd, SIOCGIFMTU, &ifr) < 0)
    {
        close(fd);
        return -1;
    }	
   	snprintf(mtu,64, "%d", (unsigned char) ifr.ifr_mtu);
    close(fd);
    return 0;
} 

6. 获取广播地址

int getBroadAddr(const char *eth, char *ip) {
    int fd;
    struct sockaddr_in sin;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);
    if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
    {
    	perror("");
        close(fd);
        return -1;
    }
    memcpy(&sin, &ifr.ifr_broadaddr, sizeof(sin));
    snprintf(ip, IP_SIZE, "%s", inet_ntoa(sin.sin_addr));

    close(fd);
    return 0;
} 

7. 获取掩码

int getNetMask(const char *eth, char *mask) {
    int fd;
    struct sockaddr_in sin;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);
    if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
    {
    	perror("");
        close(fd);
        return -1;
    }
    memcpy(&sin, &ifr.ifr_netmask, sizeof(sin));
    snprintf(mask, IP_SIZE, "%s", inet_ntoa(sin.sin_addr));

    close(fd);
    return 0;
}

8. 获取网卡flag

int getFlags(const char *eth, char *fg) {
    int fd;
    struct sockaddr_in sin;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);
    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0)
    {
    	perror("");
        close(fd);
        return -1;
    }
	snprintf(fg, IP_SIZE, "%x", ifr.ifr_flags);

    close(fd);
    return 0;
} 

三、测试

1. 测试程序

int main(int argc, char **argv)
{
	int fg=0;
	char mac[32]={};
	char ip[IP_SIZE]={0};
	char buf[64];


	getBroadAddr(ethname,ip);
	printf("broad ip:\t%s\n",ip);

	getNetMask(ethname,ip);
	printf("mask:\t%s\n",ip);
	
	setIpAddrManual(ethname, "1.1.1.1");
	getLocalIp(ethname,ip);
	printf("ip:\t%s\n",ip);
	
	setLocalMac(ethname,"00:11:22:33:44:55");
	getLocalMac(ethname,mac);
	printf("mac:\t%s\n",mac);

	getMtu(ethname,buf);
	printf("mtu:\t%s\n",buf);	

	return 1;
}

2. 执行结果

执行后结果:

peng@ubuntu:~/work/test/ip$ ifconfig 
eth0      Link encap:Ethernet  HWaddr 00:11:22:33:44:55  
          inet addr:1.1.1.1  Bcast:1.255.255.255  Mask:255.0.0.0
          inet6 addr: fe80::d9d4:d42b:a04a:9d40/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:188577 errors:0 dropped:0 overruns:0 frame:0
          TX packets:208116 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:53762370 (53.7 MB)  TX bytes:172094089 (172.0 MB)

完整代码获取,请点赞转发,并后台留言:eth

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

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

相关文章

基于arduino的土壤湿度检测

1.总体设计框图 本浇花系统总体上分为硬件和软件两大组成部分。硬件部分包括Arduino UNO开发板、温湿度传感器、通信模块、浇水执行系统和液晶显示等。软件部分包括Android客户端。系统结构如图1所示 本浇花系统总体上分为硬件和软件两大组成部分。硬件部分包括Arduino UN…

LeetCode算法题---第2天

注:大佬解答来自LetCode官方题解 80.删除有序数组的重复项Ⅱ 1.题目 2.个人解答 var removeDuplicates function (nums) {let res [];for (let index 0; index < nums.length; index) {let num 0;if (res.includes(nums[index])) {for (let i 0; i < res.length; …

Python2020年06月Python二级 -- 编程题解析

题目一 数字转汉字 用户输入一个1~9&#xff08;包含1和9&#xff09;之间的任一数字&#xff0c;程序输出对应的汉字。 如输入2&#xff0c;程序输出“二”。可重复查询。 答案: 方法一 list1[一,二,三,四,五,六,七,八,九] while True:n int(input(请输入1~9之间任意一个数字…

Windows 安装CMake

CMake 简介 CMake是一个开源的、跨平台的自动化构建系統&#xff0c;用來管理软件构建的过程。 其用途主要包括&#xff1a; 1. 跨平台编译&#xff1a;CMake支援Windows&#xff0c;Mac OS&#xff0c;Linux等多种操作系統&#xff0c;且支援多数主流编译器如GCC&#xff0…

如何在 Elasticsearch 中使用 Openai Embedding 进行语义搜索

随着强大的 GPT 模型的出现&#xff0c;文本的语义提取得到了改进。 在本文中&#xff0c;我们将使用嵌入向量在文档中进行搜索&#xff0c;而不是使用关键字进行老式搜索。 什么是嵌入 - embedding&#xff1f; 在深度学习术语中&#xff0c;嵌入是文本或图像等内容的数字表示…

centos 7.9同时安装JDK1.8和openjdk11两个版本

1.使用的原因 在服务器上&#xff0c;有些情况因为有一些系统比较老&#xff0c;所以需要使用JDK8版本&#xff0c;但随着时间的发展&#xff0c;新的软件出来&#xff0c;一般都会使用比较新的JDK版本。所以就出现了我们标题的需求&#xff0c;一个系统内同时安装两个不同的版…

Bartende:Mac菜单栏图标管理软件

Bartender 是一款可以帮助用户更好地管理和组织菜单栏图标的 macOS 软件。它允许用户隐藏和重新排列菜单栏图标&#xff0c;从而减少混乱和杂乱。 以下是 Bartender 的主要特点&#xff1a; 菜单栏图标隐藏&#xff1a;Bartender 允许用户隐藏菜单栏图标&#xff0c;只在需要时…

【Vue】数据监视输入绑定

hello&#xff0c;我是小索奇&#xff0c;精心制作的Vue系列持续发放&#xff0c;涵盖大量的经验和示例&#xff0c;如有需要&#xff0c;可以收藏哈 本章给大家讲解的是数据监视&#xff0c;前面的章节已经更新完毕&#xff0c;后面的章节持续输出&#xff0c;有任何问题都可以…

孤举者难起,众行者易趋,openGauss 5.1.0版本正式发布!

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

基于SSM的教师办公管理的设计与实现(有报告)。Javaee项目。

演示视频&#xff1a; 基于SSM的教师办公管理的设计与实现&#xff08;有报告&#xff09;。Javaee项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring S…

Selenium Webdriver自动化测试框架

最近正在编写selenium webdriver自动化框架&#xff0c;经过几天的努力&#xff0c;目前基本已经实现了一套即能满足数据驱动、又能满足Web关键字驱动的自动化框架&#xff08;主要基于 antjenkinstestngselenium webdriverjxl实现&#xff09;。通过这次的自动化框架开发&…

[CISCN2019 华北赛区 Day2 Web1]Hack World 布尔注入

正确的值 错误的值 我们首先fuzz一下 发现空格被过滤了 我们首先测试 (1)(1) (1)(2) 确定了是布尔注入了 我们写一下查询语句 (select(ascii(mid(flag,1,1))>1)from(flag))(select(ascii(mid(flag,1,1))102)from(flag)) 确定了f 开头 我们开始写脚本 import string …

喜获殊荣!迅镭激光获评“2023年苏州市质量奖”!

近日&#xff0c;苏州市质量奖评定委员会公示2023年苏州市质量奖评定结果&#xff0c;经过层层严格评审&#xff0c;迅镭激光从众多企业中脱颖而出&#xff0c;成功获评“苏州市质量奖”称号! 苏州市质量奖是苏州市政府设立&#xff0c;授予在经营质量上表现优秀的苏州企业的专…

交换机之间配置手动|静态链路聚合

两台交换机&#xff0c;配置链路聚合&#xff1a; 1、禁止自动协商速率&#xff0c;配置固定速率 int G0/0/1 undo negotiation auto speed 100int G0/0/2 undo negotiation auto speed 100 2、配置eth-trunk int eth-trunk 1 mode manual | lacp-staticint G0/0/1 eth-trun…

notion + nextjs搭建博客

SaaS可以通过博客来获得SEO流量&#xff0c;之前我自己在nextjs上&#xff0c;基于MarkDown Cloudfare来构建博客&#xff0c;很快我就了解到更优雅的方案&#xff1a;notion nextjs搭建博客&#xff0c;之前搭建了过&#xff0c;没有记录&#xff0c;这次刚好又要弄&#xf…

Yolov8-pose关键点检测:模型轻量化创新 | OREPA结合c2f,节省70%的显存!训练速度提高2倍! | CVPR2022

💡💡💡本文解决什么问题:浙大&阿里提出在线卷积重新参数化OREPA,节省70%的显存!训练速度提高2倍! OREPA | GFLOPs从9.6降低至8.2, mAP50从0.921提升至0.931 Yolov8-Pose关键点检测专栏介绍:https://blog.csdn.net/m0_63774211/category_12398833.html ✨✨…

平台登录页面实现(一)

文章目录 一、实现用户名、密码、登录按钮、记住用户表单1、全局css代码定义在asserts/css/global.css 二、用户名、密码、记住用户的双向绑定三、没有用户&#xff0c;点击注册功能实现四、实现输入用户名、密码、点击登录按钮进行登录操作五、实现表单项校验六、提交表单预验…

[python 刷题] 153 Find Minimum in Rotated Sorted Array

[python 刷题] 153 Find Minimum in Rotated Sorted Array 题目&#xff1a; Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For example, the array nums [0,1,2,4,5,6,7] might become: [4,5,6,7,0,1,2] if it was rotated 4…

年度顶级赛事来袭:2023 CCF大数据与计算智能大赛首批赛题上线!

久等了&#xff01; 大数据与人工智能领域年度顶级盛事——2023 CCF大数据与计算智能大赛——首批赛题已上线&#xff0c;大赛火力全开&#xff0c;只等你来挑战&#xff01; 大赛介绍 CCF大数据与计算智能大赛&#xff08;CCF Big Data & Computing Intelligence Contes…

嵌入式Linux应用开发-第十二章设备树的改造

嵌入式Linux应用开发-第十二章设备树的改造 第十二章 LED模板驱动程序的改造&#xff1a;设备树12.1 总结3种写驱动程序的方法12.2 怎么使用设备树写驱动程序12.2.1 设备树节点要与platform_driver能匹配12.2.2 设备树节点指定资源&#xff0c;platform_driver获得资源 12.3 开…