Linux内核构造数据包并发送(二)(dev_queue_xmit方式)

2024-02-05 20:38

本文主要是介绍Linux内核构造数据包并发送(二)(dev_queue_xmit方式),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

linux内核太构造数据包的第二种方式就是直接调用dev_queue_xmit函数,将构造完毕的数据包直接发送到网卡驱动。从NF框架来看,该函数的调用是在 POSTROUTING点之后了,也可以理解为直接通过调用二层的发送函数,将三层构造的数据包发送出去。该函数实际上会调用 skb->dev->hard_start_xmit,即对应网卡的驱动函数,将数据包直接发送的出去。 

       很显然,这个工作在二层的函数,发送数据包(数据包在二层的时候准确叫法应该是帧,我们这里是在三层直接调用的,权且还称作数据包)的方式是不需要再查路由了。 

但是,二层发送的时候是需要根据目的MAC来进行的。在第一种方法构造的数据包中,仅仅交换了IP地址,而没有对MAC做任何修改。这样直接调用 dev_queue_xmit是会产生问题的,并且该函数发送的内容应该是从二层头部开始,到数据包的结束。因此,如果三层构造的数据包,想调用该函数直接发送数据包的话,则需要修改数据包的源和目的MAC,并将skb->data指针指向MAC头部,以及skb->len的值也要加上头部的长度方法。以下是可参考的示例代码: 

 

C代码
  1. unsigned char mac_temp[ETH_ALEN] = {0};     
  2.      
  3.  struct ethhdr *mach = NULL;     
  4.      
  5.  ……     
  6.      
  7.  /*code…… 构造数据包的IP即上层协议及数据*/     
  8.      
  9.  ……     
  10.      
  11. /*交换源和目的MAC*/     
  12.      
  13.   mach = (struct ethhdr *)skb->mac.raw;     
  14.      
  15.    memcpy(mac_temp, (unsigned char *)mach->h_dest, ETH_ALEN);     
  16.      
  17.    memcpy(mach->h_dest, (unsigned char *)mach->h_source, ETH_ALEN);     
  18.      
  19.    memcpy(mach->h_source, mac_temp, ETH_ALEN);     
  20.      
  21. /*修改skb->data指针,使其指向MAC头部,并且增加skb->len*/     
  22.      
  23. skb_push(skb , ETH_HLEN);     
  24.      
  25. /*直接调用该函数,将数据包从网卡上发送出去*/     
  26.      
  27. ret = dev_queue_xmit(skb);    
[c] view plain copy print ?
  1. unsigned char mac_temp[ETH_ALEN] = {0};    
  2.     
  3.  struct ethhdr *mach = NULL;    
  4.     
  5.  ……    
  6.     
  7.  /*code…… 构造数据包的IP即上层协议及数据*/    
  8.     
  9.  ……    
  10.     
  11. /*交换源和目的MAC*/    
  12.     
  13.   mach = (struct ethhdr *)skb->mac.raw;    
  14.     
  15.    memcpy(mac_temp, (unsigned char *)mach->h_dest, ETH_ALEN);    
  16.     
  17.    memcpy(mach->h_dest, (unsigned char *)mach->h_source, ETH_ALEN);    
  18.     
  19.    memcpy(mach->h_source, mac_temp, ETH_ALEN);    
  20.     
  21. /*修改skb->data指针,使其指向MAC头部,并且增加skb->len*/    
  22.     
  23. skb_push(skb , ETH_HLEN);    
  24.     
  25. /*直接调用该函数,将数据包从网卡上发送出去*/    
  26.     
  27. ret = dev_queue_xmit(skb);    
  这里还要顺便说一下构造的数据包发送完毕之后,对于hook函数的返回值问题。 

   (1)第一种发送数据包的实现,对于send_reset函数的实现中,由于单独申请了nskb的内存,并构造的新的数据包。新数据包接着走NF的流程了。而对于原始的skb,就通过模块的返回值return NF_DROP做出了处理。 
   (2)第二种发送数据包的实现,若是基于已有数据包的基础上重新构造的数据包,那么实际上原始数据包的内容已经不复存在,而且调用完毕 dev_queue_xmit已将同一块缓冲区,只是填充了新数据的数据包发送出去,因此,这里已经没有原始数据包的存在了,需要返回 NF_STOLEN,告诉协议栈不用关心原始的包即可。否则,若是新数据包是单独申请的内存,那么对于原数据包还应该是返回NF_DROP.

这篇关于Linux内核构造数据包并发送(二)(dev_queue_xmit方式)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/682096

相关文章

Linux搭建单机MySQL8.0.26版本的操作方法

《Linux搭建单机MySQL8.0.26版本的操作方法》:本文主要介绍Linux搭建单机MySQL8.0.26版本的操作方法,本文通过图文并茂的形式给大家讲解的非常详细,感兴趣的朋友一起看看吧... 目录概述环境信息数据库服务安装步骤下载前置依赖服务下载方式一:进入官网下载,并上传到宿主机中,适合离线环境

Android实现定时任务的几种方式汇总(附源码)

《Android实现定时任务的几种方式汇总(附源码)》在Android应用中,定时任务(ScheduledTask)的需求几乎无处不在:从定时刷新数据、定时备份、定时推送通知,到夜间静默下载、循环执行... 目录一、项目介绍1. 背景与意义二、相关基础知识与系统约束三、方案一:Handler.postDel

windows和Linux使用命令行计算文件的MD5值

《windows和Linux使用命令行计算文件的MD5值》在Windows和Linux系统中,您可以使用命令行(终端或命令提示符)来计算文件的MD5值,文章介绍了在Windows和Linux/macO... 目录在Windows上:在linux或MACOS上:总结在Windows上:可以使用certuti

gradle第三方Jar包依赖统一管理方式

《gradle第三方Jar包依赖统一管理方式》:本文主要介绍gradle第三方Jar包依赖统一管理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录背景实现1.顶层模块build.gradle添加依赖管理插件2.顶层模块build.gradle添加所有管理依赖包

Linux之systemV共享内存方式

《Linux之systemV共享内存方式》:本文主要介绍Linux之systemV共享内存方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、工作原理二、系统调用接口1、申请共享内存(一)key的获取(二)共享内存的申请2、将共享内存段连接到进程地址空间3、将

Maven中引入 springboot 相关依赖的方式(最新推荐)

《Maven中引入springboot相关依赖的方式(最新推荐)》:本文主要介绍Maven中引入springboot相关依赖的方式(最新推荐),本文给大家介绍的非常详细,对大家的学习或工作具有... 目录Maven中引入 springboot 相关依赖的方式1. 不使用版本管理(不推荐)2、使用版本管理(推

C#使用StackExchange.Redis实现分布式锁的两种方式介绍

《C#使用StackExchange.Redis实现分布式锁的两种方式介绍》分布式锁在集群的架构中发挥着重要的作用,:本文主要介绍C#使用StackExchange.Redis实现分布式锁的... 目录自定义分布式锁获取锁释放锁自动续期StackExchange.Redis分布式锁获取锁释放锁自动续期分布式

快速修复一个Panic的Linux内核的技巧

《快速修复一个Panic的Linux内核的技巧》Linux系统中运行了不当的mkinitcpio操作导致内核文件不能正常工作,重启的时候,内核启动中止于Panic状态,该怎么解决这个问题呢?下面我们就... 感谢China编程(www.chinasem.cn)网友 鸢一雨音 的投稿写这篇文章是有原因的。为了配置完

Java对象转换的实现方式汇总

《Java对象转换的实现方式汇总》:本文主要介绍Java对象转换的多种实现方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java对象转换的多种实现方式1. 手动映射(Manual Mapping)2. Builder模式3. 工具类辅助映

Spring Boot读取配置文件的五种方式小结

《SpringBoot读取配置文件的五种方式小结》SpringBoot提供了灵活多样的方式来读取配置文件,这篇文章为大家介绍了5种常见的读取方式,文中的示例代码简洁易懂,大家可以根据自己的需要进... 目录1. 配置文件位置与加载顺序2. 读取配置文件的方式汇总方式一:使用 @Value 注解读取配置方式二