当前位置: 首页 > news >正文

【C语言】linux内核packet_setsockopt

一、中文注释

// 发送数据包函数。它尝试通过特定的网络设备队列直接传输一个skb(socket缓冲区)。
static int packet_direct_xmit(struct sk_buff *skb)
{return dev_direct_xmit(skb, packet_pick_tx_queue(skb)); // 调用dev_direct_xmit函数,并传入skb和通过packet_pick_tx_queue选择的发送队列。
}// 设置socket选项的函数。这个函数负责处理网络层的各种选项设置。
static int
packet_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
{struct sock *sk = sock->sk; // 从socket结构中获取sock结构。struct packet_sock *po = pkt_sk(sk); // 将sock结构转换为packet_sock结构体。int ret;if (level != SOL_PACKET)return -ENOPROTOOPT; // 如果层级不是SOL_PACKET,返回错误。// 根据选项名称执行相应的操作。switch (optname) {case PACKET_ADD_MEMBERSHIP:case PACKET_DROP_MEMBERSHIP:{struct packet_mreq_max mreq; // 定义多播请求结构。int len = optlen; // 获取选项长度。memset(&mreq, 0, sizeof(mreq)); // 初始化多播请求结构。if (len < sizeof(struct packet_mreq))return -EINVAL; // 如果传入的长度小于packet_mreq结构大小,返回无效参数错误。if (len > sizeof(mreq))len = sizeof(mreq); // 如果传入的长度大于packet_mreq_max结构大小,调整为packet_mreq_max结构大小。if (copy_from_user(&mreq, optval, len))return -EFAULT; // 从用户空间拷贝数据失败,则返回错误。if (len < (mreq.mr_alen + offsetof(struct packet_mreq, mr_address)))return -EINVAL; // 如果长度小于mreq结构中mr_address成员起始位置加上地址长度,则返回无效参数错误。if (optname == PACKET_ADD_MEMBERSHIP)ret = packet_mc_add(sk, &mreq); // 添加多播组成员。elseret = packet_mc_drop(sk, &mreq); // 删除多播组成员。return ret; // 返回操作结果。}case PACKET_RX_RING:case PACKET_TX_RING:{union tpacket_req_u req_u;int len;lock_sock(sk); // 锁定sock结构。switch (po->tp_version) {case TPACKET_V1:case TPACKET_V2:len = sizeof(req_u.req); // 设置请求结构大小。break;case TPACKET_V3:default:len = sizeof(req_u.req3); // 设置请求结构大小。break;}if (optlen < len) {ret = -EINVAL; // 如果传入长度小于请求结构大小,返回无效参数错误。} else {if (copy_from_user(&req_u.req, optval, len))ret = -EFAULT; // 从用户空间拷贝数据失败,则返回错误。elseret = packet_set_ring(sk, &req_u, 0, optname == PACKET_TX_RING); // 设置环形缓冲区。}release_sock(sk); // 释放sock结构锁。return ret; // 返回操作结果。}// 设置数据包复制阈值,当skb长度小于此值时复制数据。
case PACKET_COPY_THRESH:
{int val;if (optlen != sizeof(val))return -EINVAL; // 如果选项长度不合法,返回错误。if (copy_from_user(&val, optval, sizeof(val)))return -EFAULT; // 如果用户空间数据拷贝失败,返回错误。pkt_sk(sk)->copy_thresh = val; // 设置数据包复制阈值。return 0;
}
// ...
// 设置packet socket的版本号。
case PACKET_VERSION:
{int val;if (optlen != sizeof(val))return -EINVAL; // 如果选项长度不合法,返回错误。if (copy_from_user(&val, optval, sizeof(val)))return -EFAULT; // 如果用户空间数据拷贝失败,返回错误。switch (val) {case TPACKET_V1:case TPACKET_V2:case TPACKET_V3:break; // 如果为有效版本,继续执行。default:return -EINVAL; // 如果为无效版本,返回错误。}lock_sock(sk); // 锁定sock结构。if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) {ret = -EBUSY; // 如果已经设置了环形缓冲区,则返回忙。} else {po->tp_version = val; // 设置协议版本。ret = 0;}release_sock(sk); // 释放sock结构锁。return ret; // 返回操作结果。
}
// ...
// 设置packet socket是否绕过队列规则处理。
case PACKET_QDISC_BYPASS:
{int val;if (optlen != sizeof(val))return -EINVAL; // 如果选项长度不合法,返回错误。if (copy_from_user(&val, optval, sizeof(val)))return -EFAULT; // 如果用户空间数据拷贝失败,返回错误。po->xmit = val ? packet_direct_xmit : dev_queue_xmit; // 根据val的值选择是直接传输还是进入队列规则处理。return 0;
}
// ...
// 默认case,如果没有匹配到任何选项,代表不支持该协议选项。
default:return -ENOPROTOOPT; // 返回不支持的协议选项错误。
// 所有case分支的目的都是处理socket层的不同选项设置,如添加/删除多播组,设置缓冲区大小和环形配置,调整性能选项等。
// 每个case分支以处理特定选项名(optname)为基础,对socket结构的特定成员进行赋值或执行相关操作函数。}
}

这段代码是Linux内核网络栈中的一部分,提供对原始套接字层的操作。`packet_direct_xmit` 函数用于直接通过指定的网络队列发送数据包。`packet_setsockopt` 函数是一个针对`SOL_PACKET`套接字层级的设置选项的函数,可以添加或删除多播组成员,设置缓冲区环区域,修改某些性能参数等。这些操作通常是由网络程序进行socket编程时所使用。

每个 case 分支处理一个特定的套接字选项,例如 PACKET_RX_RING 或 PACKET_TX_RING 用于分配或释放环形缓冲区,而 PACKET_COPY_THRESH 用于设置包拷贝阈值等。每个分支内部通常会首先验证用户提供的参数长度是否合法,然后从用户空间拷贝数据到内核空间,接着进行相应的设置修改,某些情况下还需要在操作前后获取和释放锁,以保护数据结构的一致性。如果选项设置成功,通常会返回 0,否则返回错误码。

二、中文讲解

第一个函数 packet_direct_xmit:

static int packet_direct_xmit(struct sk_buff *skb)
{return dev_direct_xmit(skb, packet_pick_tx_queue(skb));
}

packet_direct_xmit 函数是一个非常简单的函数,它接收一个 sk_buff 结构体指针 skb(代表网络数据包),调用 dev_direct_xmit 函数直接将这个数据包发送出去。发送的队列是由 packet_pick_tx_queue(skb) 函数返回的。通常这个函数被用作数据包的直接传输,规避了一些队列管理机制。

第二个函数 packet_setsockopt:

static int packet_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
{// ...
}

packet_setsockopt 函数用于设置给定套接字 sock 的某些选项。函数参数 level 表示选项的级别,这里必须是 SOL_PACKET,否则返回 -ENOPROTOOPT 错误。`optname` 指定了要设置的选项的名称,`optval` 是指向包含选项值的用户空间缓冲区的指针,而 optlen 表示缓冲区的长度。
函数体内是一个 switch 语句,根据 optname 的不同,执行不同的操作:
1. PACKET_ADD_MEMBERSHIP 和 PACKET_DROP_MEMBERSHIP:用于管理数据包多播成员资格。
2. PACKET_RX_RING 和 PACKET_TX_RING:设置接收和发送环形缓冲区,这些操作涉及到性能优化,以高效处理网络数据包。
3. PACKET_COPY_THRESH:设置数据包复制阈值。
4. PACKET_VERSION:指定环形缓冲区版本(TPACKET_V1, TPACKET_V2, 或 TPACKET_V3)。
5. PACKET_RESERVE:为环形缓冲区中每个帧预留空间。
6. PACKET_LOSS:设置丢包选项,以模拟网络丢包情况。
7. PACKET_AUXDATA:启用或禁用附加数据。
8. PACKET_ORIGDEV:路由过程中获取原始设备信息的选项。
9. PACKET_VNET_HDR:用于虚拟网络设备头部的选项。
10. PACKET_TIMESTAMP:设置数据包的时间戳类型。
11. PACKET_FANOUT 和 PACKET_FANOUT_DATA:用于将数据包分发到多个程序。
12. PACKET_TX_HAS_OFF:设置是否启用硬件校验和。
13. PACKET_QDISC_BYPASS:设置是否绕过队列规则直接发送数据包。
对于每种情况,在设置选项前都有一些校验逻辑来保证输入参数的有效性。如果输入参数无效,函数会返回相应的错误代码(例如 -EINVAL 表示无效参数)。各种选项设置可能涉及到从用户空间复制数据到内核空间(使用 copy_from_user),也可能对套接字状态加锁来确保线程安全。成功执行操作后,函数通常返回 0 表示成功。

相关文章:

【C语言】linux内核packet_setsockopt

一、中文注释 // 发送数据包函数。它尝试通过特定的网络设备队列直接传输一个skb&#xff08;socket缓冲区&#xff09;。 static int packet_direct_xmit(struct sk_buff *skb) {return dev_direct_xmit(skb, packet_pick_tx_queue(skb)); // 调用dev_direct_xmit函数&#x…...

LeetCode的使用方法

LeetCode的使用方法 一、LeetCode是什么&#xff1f;1.LeetCode简介2.LeetCode官网 二、LeetCode的使用方法1.注册账号2.力扣社区力扣编辑器 2.1 讨论发起讨论参与讨论关注讨论 2.2 文章撰写文章关注文章 3.力扣面试官版测评面试招聘竞赛 4.力扣学习LeetBook 书架我的阅读猜您喜…...

Vue事件处理:.passive修饰符与应用场景

.passive修饰符 passive这个修饰符会执行默认方法。你们可能会问&#xff0c;明明默认执行为什么会设置这样一个修饰符。这就要说一下这个修饰符的本意了。 浏览器只有等内核线程执行到事件监听器对应的JavaScript代码时&#xff0c;才能知道内部是否会调用preventDefa…...

智慧城市中的数字孪生:构建城市管理的未来框架

目录 一、引言 二、数字孪生技术概述 三、数字孪生技术在智慧城市中的应用 1、实时监测与预警 2、模拟与优化 3、智能化决策 4、协同与共享 四、数字孪生技术构建城市管理的未来框架的价值 1、提高管理效率 2、优化资源配置 3、提升公共服务水平 4、增强应对突发事…...

强引用、软引用、弱引用、幻象引用 —— Java的四种引用类型解析

强引用、软引用、弱引用、幻象引用 —— Java的四种引用类型解析 在Java中&#xff0c;对象的生命周期并不总是由我们直接控制。除了我们常见的强引用外&#xff0c;Java还提供了软引用、弱引用和幻象引用这三种引用类型&#xff0c;它们对对象生命周期的影响各不相同。理解这…...

基于禁忌搜索算法(TS)的TSP(Python实现)

本篇文章是博主在最化优学习、人工智能等领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对相关等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在最优化算…...

Linux shell 网络掩码地址转CIDR

例子&#xff1a; ./1.sh 255.255.255.0 ./1.sh 255.255.255.128 ./1.sh 255.255.0.0 源实现&#xff1a; #!/bin/bashnetmask_to_cidr() {local IFSlocal -a octetslocal i0local cidr0IFS. read -r -a octets <<< "$1"for octet in "${octets[]}…...

C#,煎饼排序问题(Pancake Sorting Problem)算法与源代码

1 煎饼排序问题 给定一个未排序的数组&#xff0c;任务是对给定数组进行排序。您只能在阵列上执行以下操作。 翻转&#xff08;arr&#xff0c;i&#xff09;&#xff1a;将数组从0反转为i 示例&#xff1a; 输入&#xff1a;arr[]{23、10、20、11、12、6、7} 输出&#xff1a…...

13.西瓜书——半监督学习

1.概述 &#xff08;1&#xff09; 纯半监督学习 (Pure Semi-Supervised Learning) 纯半监督学习是一种典型的半监督学习方法&#xff0c;它的主要特点是同时利用有标签数据和无标签数据进行模型训练。目标是通过整合这两种类型的数据来提高模型的泛化性能。在这个过程中&#…...

C++进阶之路---继承(二)

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、继承与友元 友元关系不能继承&#xff0c;也就是说基类友元不能访问子类私有和保护成员。 class Student; class Per…...

C及C++每日练习(3)

选择题&#xff1a; 1.以下程序的输出结果是&#xff08;&#xff09; #include <stdio.h> main() { char a[10] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, *p; int i; i 8; p a i; printf("%s\n", p - 3); } A.6 B. 6789 C. 6 D.789 对于本题&#xff0…...

黑马点评-附近商户实现

GEO数据结构 Redis在3.2版本中加入了对GEO的支持&#xff0c;允许存储地理坐标信息&#xff0c;根据经纬度来检索数据。 GEO本质上是基于sortedSet实现的&#xff0c;在Sorted Set中&#xff0c;每个成员都是与一个分数(score)相关联的&#xff0c;这个分数用于对成员进行排序…...

安装nginx:手动安装和yum安装

本文在centos7.9下分别尝试了yum安装和手动安装&#xff0c;记录一下试验过程。为后来者少踩点坑。 下载 下载地址&#xff1a;链接 。建议下载稳定版本&#xff0c;也就是Stable Version&#xff0c;这里下载的是 nginx-1.24.0 # 我下载在如下文件夹 mkdir/opt/apps cd /op…...

【C++ STL详解】——string类

目录 前言 一、string类对象的常见构造 二、string类对象的访问及遍历 1.下标【】&#xff08;底层operator【】函数&#xff09; ​编辑 2.迭代器 3.范围for 4.at 5.back和front 三、string类对象的容量操作 1.size 和 length 2.capacity 3.empty 4.clear 5.res…...

MatplotlibPython 1 3.7

放大数据&#xff0c;如果想仔细看某一行的数据的时候 可以调不同的颜色&#xff0c;图片的长宽高&#xff0c;以及线的种类 plt.figure 这个命令下的所有东西都在这个figure里面 plt.xlim 改变坐标轴的范围 plt.xlabel 改变坐标轴的总名称 plt.xticks 换单位 plt.yt…...

深入理解 Dubbo:构建分布式服务治理体系

目录 1. 介绍 2. Dubbo 的核心概念 2.1 服务提供者&#xff08;Provider&#xff09;与服务消费者&#xff08;Consumer&#xff09; 2.2 注册中心&#xff08;Registry&#xff09; 2.3 监控中心&#xff08;Monitor&#xff09; 3. Dubbo 的功能特性 3.1 远程调用&…...

唤起原生IOS和安卓Android app的方法

大家好我是咕噜美乐蒂&#xff0c;很高兴又和大家见面了&#xff01; 要唤起原生 iOS 或 Android 应用程序&#xff0c;你可以使用以下方法&#xff1a; 唤起原生 iOS 应用程序 在 iOS 上&#xff0c;你可以使用自定义 URL 方案或 Universal Links 来唤起原生应用程序。以下…...

RabbitMQ的web控制端介绍

2.1 web管理界面介绍 connections&#xff1a;无论生产者还是消费者&#xff0c;都需要与RabbitMQ建立连接后才可以完成消息的生产和消费&#xff0c;在这里可以查看连接情况channels&#xff1a;通道&#xff0c;建立连接后&#xff0c;会形成通道&#xff0c;消息的投递、获取…...

GitHub登不上:修改hosts文件来解决(GitHub520,window)

参考链接&#xff1a;GitHub520: 本项目无需安装任何程序&#xff0c;通过修改本地 hosts 文件&#xff0c;试图解决&#xff1a; GitHub 访问速度慢的问题 GitHub 项目中的图片显示不出的问题 花 5 分钟时间&#xff0c;让你"爱"上 GitHub。 (gitee.com) GitHub网站…...

01-DevOps代码上线-git入门及gitlab远程仓库

一、准备学习环境 10.0.0.71-gitlab 2c2g-20GB 10.0.0.72-jenkins 2c2g-20GB 10.0.0.73-sonarqube 1c1g-20GB 10.0.0.74-nexus 1c1g-20GB 10.0.0.75-dm 1c1g-20GB &#xff08;模拟写代码服务器&#xff09; 在centos系统中&…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...