linux内核太构造数据包的第二种方式就是直接调用dev_queue_xmit函数,将构造完毕的数据包直接发送到网卡驱动。从NF框架来看,该函数的调用是在 POSTROUTING点之后了,也可以理解为直接通过调用二层的发送函数,将三层构造的数据包发送出去。该函数实际上会调用 skb->dev->hard_start_xmit,即对应网卡的驱动函数,将数据包直接发送的出去。
很显然,这个工作在二层的函数,发送数据包(数据包在二层的时候准确叫法应该是帧,我们这里是在三层直接调用的,权且还称作数据包)的方式是不需要再查路由了。
但是,二层发送的时候是需要根据目的MAC来进行的。在第一种方法构造的数据包中,仅仅交换了IP地址,而没有对MAC做任何修改。这样直接调用 dev_queue_xmit是会产生问题的,并且该函数发送的内容应该是从二层头部开始,到数据包的结束。因此,如果三层构造的数据包,想调用该函数直接发送数据包的话,则需要修改数据包的源和目的MAC,并将skb->data指针指向MAC头部,以及skb->len的值也要加上头部的长度方法。以下是可参考的示例代码:
unsigned char mac_temp[ETH_ALEN] = {0};
struct ethhdr *mach = NULL;
……
/*code…… 构造数据包的IP即上层协议及数据*/
……
/*交换源和目的MAC*/
mach = (struct ethhdr *)skb->mac.raw;
memcpy(mac_temp, (unsigned char *)mach->h_dest, ETH_ALEN);
memcpy(mach->h_dest, (unsigned char *)mach->h_source, ETH_ALEN);
memcpy(mach->h_source, mac_temp, ETH_ALEN);
/*修改skb->data指针,使其指向MAC头部,并且增加skb->len*/
skb_push(skb , ETH_HLEN);
/*直接调用该函数,将数据包从网卡上发送出去*/
ret = dev_queue_xmit(skb);
这里还要顺便说一下构造的数据包发送完毕之后,对于hook函数的返回值问题。
(1)第一种发送数据包的实现,对于send_reset函数的实现中,由于单独申请了nskb的内存,并构造的新的数据包。新数据包接着走NF的流程了。而对于原始的skb,就通过模块的返回值return NF_DROP做出了处理。
(2)第二种发送数据包的实现,若是基于已有数据包的基础上重新构造的数据包,那么实际上原始数据包的内容已经不复存在,而且调用完毕 dev_queue_xmit已将同一块缓冲区,只是填充了新数据的数据包发送出去,因此,这里已经没有原始数据包的存在了,需要返回 NF_STOLEN,告诉协议栈不用关心原始的包即可。否则,若是新数据包是单独申请的内存,那么对于原数据包还应该是返回NF_DROP.
分享到:
相关推荐
`dev_queue_xmit`和`dev_hard_start_xmit`是Linux内核网络栈中非常重要的两个函数,它们共同作用于数据包的发送过程。理解这两个函数的工作原理对于进行内核级网络编程至关重要。通过对`dev_queue_xmit`内部逻辑的...
ip_queue_xmit函数会对数据帧进行进一步完善,然后调用dev_queue_xmit函数将数据包送往链路层进行处理,并缓存数据包至sock结构之send_head队列,以保证可靠性传输。 在整个数据包发送过程中,数据包不会同时存在于...
7. 链路层由dev_queue_xmit函数处理,它将数据包传给网卡驱动。 8. 网卡驱动的hard_start_xmit函数最终将数据包通过DMA传输到网卡,并由网卡发送到物理媒介。 在整个流程中,数据包可能会经过分片、重组、拷贝等...
驱动程序通过`dev_queue_xmit()`函数发送数据包,并通过中断处理程序接收数据。 2. **网络设备结构体** (`struct net_device`):在内核中,每个网络设备都有一个`net_device`结构体,它包含了设备的配置信息、状态...
- **IP协议处理**:IP协议的发送和接收流程在`ip_input.c`和`ip_output.c`中,最后都会调用`dev_queue_xmit()`发送数据包。设备接收数据包后,会通过协议类型调用相应的处理函数,如`ip_rcv()`,并可能涉及VLAN处理...
Egress QoS则在设备启动时通过dev_activate函数配置默认的队列调度机制,如pfifo_fast,然后在dev_queue_xmit函数中执行实际的出口调度。 内核与用户空间的交互主要通过Netlink协议,这是一种用户空间与内核空间...
中的`netif_rx()`和`dev_queue_xmit()`函数进行。这两个函数分别处理从硬件接收到的数据包和向硬件发送的数据包。 6. **协议栈优化**: Linux内核的TCP/IP协议栈还包括了多种优化措施,如快速重传、快速恢复、延迟...
要从协议层向设备发送数据,需要使用dev_queue_xmit函数。这个函数对数据进行排队,并交由底层设备驱动程序发送数据包。报文的接收通常使用netif_rx执行。当底层设备驱动程序收到一个报文(包含在所分配的sk_buff中...
当数据包需要发送时,协议层会找到对应的网络接口,并调用`dev_queue_xmit`函数将其发送出去。网络接口的主要任务是确保数据包的有效传输,并且在必要时对其进行处理。 设计和实现网络虚接口涉及对Linux内核网络子...
例如,当需要发送数据包时,上层协议会调用`dev_queue_xmit()`函数;接收数据包时,则通过`netif_rx()`函数。`sk_buff`(套接字缓冲区)是网络子系统的核心数据结构,包含了关于数据包的所有关键信息,如设备指针、...
例如,dev_queue_xmit用于将数据包放入队列进行传输,netif_rx用于接收数据包。sk_buff(socket buffer)是Linux内核用于表示网络数据包的结构体,它是一个包含网络数据包缓冲区和相关描述信息的复杂结构,支持对...
最后,`dev_queue_xmit`函数将数据包放入网卡的发送队列,等待硬件进行实际的物理层传输。 在整个过程中,`skb`起到了承上启下的关键作用,它不仅保存了网络数据,还包含了一系列处理信息,如协议类型、数据长度、...
`dev_queue_xmit()`用于将数据包加入网络接口的发送队列。 ###### 5.3.2 DEVICE->hard_start_xmit()-devicedependent, drivers/net/DEVICE.c `hard_start_xmit()`是由具体的网络设备驱动提供的,用于真正发送数据包...
在数据传输阶段,网络设备驱动程序会将数据包发送到网络设备中,例如通过调用协议接口代码中的 deb_queue_xmit 函数来发送数据包。 2.3 数据接收 在数据接收阶段,网络设备驱动程序会从网络设备中接收数据包,例如...
Linux内核提供了丰富的系统函数来支持网络设备驱动的开发,如net_device结构体定义了设备的相关属性和操作,如dev_queue_xmit用于发送数据包,netif_rx接收并处理数据帧,hard_start_xmit用于实际的数据发送等。...
网络数据的出口函数为 dev_queue_xmit()。 Linux QoS 的输入流控 在数据接收流控时,数据只是刚从网卡设备中收到,还未交到网络上层处理。网卡的输入流控不是必须的,缺省情况下并不进行流控。输入流控入口函数为...