Linux内核发送构造数据包的方式
- 格式:docx
- 大小:20.34 KB
- 文档页数:7
linux 开发板之间数据传输方式
Linux开发板之间的数据传输方式有多种,以下是一些常见的方式:1.网络传输:通过网线或Wi-Fi连接,使用TCP/IP协议栈进行数据传
输。
这种方式适合大量数据的快速传输,但需要稳定的网络环境。
2.串口传输:通过串口连接,使用串口通信协议(如RS-232、RS-485
等)进行数据传输。
这种方式适合短距离、低速的数据传输,常用于设备之间的调试和通信。
B传输:通过USB接口连接,使用USB协议进行数据传输。
这种
方式速度较快,适用于大量数据的传输,但需要开发板支持USB接口。
4.SD卡/eMMC传输:将数据存储到SD卡或eMMC等存储介质中,
然后通过插槽或接口连接到另一块开发板进行数据传输。
这种方式适合大量数据的存储和传输,但需要开发板支持相应的存储接口。
5.I2C/SPI传输:通过I2C或SPI等总线协议进行数据传输。
这种方式
适用于短距离、低速的数据传输,常用于设备之间的通信和控制。
具体选择哪种传输方式,需要根据应用场景、传输距离、传输速率、设备接口等因素综合考虑。
Linux终端命令的文件传输方法Linux终端命令提供了多种文件传输方法,方便用户在终端中进行文件传输和共享。
本文将介绍几种常用的Linux终端命令的文件传输方法,包括scp、rsync和sftp。
1. scp命令scp(Secure Copy)是一种基于SSH协议的文件传输工具,用于在不同的主机之间进行文件拷贝。
它支持将本地文件拷贝到远程主机,也可以从远程主机拷贝文件到本地。
使用scp命令进行文件传输的基本语法如下:```scp [选项] [源文件] [目标文件]```其中,选项可以指定加密算法、端口号等参数,源文件指定要传输的文件路径,目标文件指定传输后的目标路径。
示例:将本地文件`example.txt`拷贝到远程主机`user@remote:/path/to/destination/`:```scp example.txt user@remote:/path/to/destination/将远程主机`user@remote:/path/to/source/example.txt`拷贝到本地当前目录:```scp user@remote:/path/to/source/example.txt .```2. rsync命令rsync是一个快速、多功能的文件复制和同步工具,它通过差异化算法来进行增量更新,有效减少数据传输量。
rsync可以在本地主机之间进行文件传输,也可以在本地和远程主机之间进行文件传输。
使用rsync命令进行文件传输的基本语法如下:```rsync [选项] [源文件/目录] [目标文件/目录]```其中,选项可以指定连接方式、忽略文件等参数,源文件/目录指定要传输的文件或目录路径,目标文件/目录指定传输后的目标路径。
示例:将本地目录`/path/to/source/`下的所有文件同步到远程主机`user@remote:/path/to/destination/`:rsync -avz /path/to/source/ user@remote:/path/to/destination/```从远程主机`user@remote:/path/to/source/`同步所有文件到本地目录`/path/to/destination/`:```rsync -avz user@remote:/path/to/source/ /path/to/destination/```3. sftp命令sftp(Secure File Transfer Protocol)是基于SSH协议的一种安全文件传输协议,用于在本地和远程主机之间进行文件传输。
Linux 服务器传输大文件的方法本文介绍在 Linux 服务器上传输大文件的几种方法,以帮助用户更有效地处理大型文件。
在 Linux 服务器上,传输大文件时可能会遇到一些挑战,如网络速度慢、传输时间过长等问题。
本文将介绍几种有效的方法来帮助您在 Linux 服务器上传输大文件。
1. 使用 SFTP 协议SFTP(Secure File Transfer Protocol)是一种安全且高效的文件传输协议,适用于在 Linux 服务器之间传输大文件。
与 FTP 协议相比,SFTP 提供了更强的安全性,可通过加密数据传输来保护文件隐私。
在使用 SFTP 时,请确保已安装 OpenSSH,以便在 Linux 服务器间进行安全传输。
2. 使用 rsync 同步工具rsync 是一种用于数据同步和备份的工具,可大大提高在 Linux 服务器上传输大文件的速度。
rsync 通过仅传输已更改的数据块来实现数据同步,从而减少数据传输量。
在使用 rsync 时,请确保目标服务器已安装 rsync,并使用以下命令进行同步:```rsync -avz -e ssh /path/to/source /path/to/destination ```其中,`-a`表示复制整个目录,`-v`表示显示传输进度,`-z`表示压缩数据以提高传输速度,`-e`表示使用 SSH 协议进行加密传输。
3. 使用 NFS 共享文件系统NFS(Network File System)是一种允许在不同 Linux 服务器之间共享文件系统的协议。
通过在源服务器和目标服务器之间设置NFS 共享,可以实现大文件的快速传输。
在使用 NFS 共享时,请确保已配置好 NFS 服务器,并在目标服务器上安装 NFS 客户端。
4. 分割文件并传输对于非常大的文件,可以将其分割成多个小文件,然后逐个传输。
这种方法可以提高传输速度,并降低网络拥堵。
使用`split`命令可以将文件分割成多个小文件,然后使用`xfer`命令逐个传输这些小文件。
两台linux主机传送大文件的方法-概述说明以及解释1.引言1.1 概述概述:在进行文件传输时,Linux主机之间有多种方法可供选择。
本文将介绍三种常用的方法:使用SCP命令进行文件传输、使用rsync命令进行文件传输,以及使用FTP服务器进行文件传输。
这些方法各有优缺点,我们将对它们进行详细的比较和总结。
同时,我们也会给出我们的最佳推荐方法,并展望未来的发展方向。
文件传输在日常工作和生活中非常常见,特别是在Linux环境下。
无论是在服务器之间进行文件备份、数据同步,还是在不同的开发环境中共享文件,选择合适的文件传输方法能够提高效率、节省时间。
在接下来的章节中,我们将详细介绍每种方法的基本用法和高级用法,并分析它们的优缺点。
首先,我们将介绍SCP命令,它是一种简单直观的文件传输方式。
然后,我们将介绍rsync命令,它提供了更为灵活和高效的文件传输选项。
最后,我们将介绍FTP服务器的搭建和使用方法,探讨它的优势和不足。
通过对这些方法的比较和分析,我们将总结出每种方法的适用场景,并给出我们的最佳推荐方法。
此外,我们也会对未来的文件传输技术发展进行展望,以期提升文件传输的速度、安全性和便利性。
通过本文的阅读,读者将能够了解到不同的文件传输方法之间的差异,为自己的工作环境选择合适的传输方式提供参考和指导。
接下来,让我们开始介绍第一种传输方法:使用SCP命令进行文件传输。
1.2文章结构文章结构部分内容如下:2. 正文2.1 方法一:使用SCP命令进行文件传输2.1.1 SCP命令的基本用法2.1.2 SCP命令的高级用法2.1.3 SCP命令的优缺点2.2 方法二:使用rsync命令进行文件传输2.2.1 rsync命令的基本用法2.2.2 rsync命令的高级用法2.2.3 rsync命令的优缺点2.3 方法三:使用FTP服务器进行文件传输2.3.1 搭建FTP服务器2.3.2 使用FTP客户端进行文件传输2.3.3 FTP服务器的优缺点3. 结论3.1 对比和总结各种方法的优缺点3.2 推荐最佳的方法3.3 展望未来的发展方向在本文中,我们将重点探讨两台Linux主机之间传送大文件的方法。
Linux命令高级技巧使用scp进行安全文件传输Linux命令高级技巧:使用scp进行安全文件传输在Linux操作系统中,文件传输是日常工作中非常常见的任务。
为了确保文件传输的安全性,我们可以使用scp命令(Secure Copy)来进行文件传输。
scp命令是基于SSH协议的文件传输命令,可以在本地主机和远程主机之间进行安全的文件传输。
1. 安装OpenSSH在使用scp命令之前,我们需要确保在本地主机和远程主机上都安装了OpenSSH软件包。
如果没有安装,可以使用以下命令来安装OpenSSH:```sudo apt-get install openssh-server // Ubuntu/Debiansudo yum install openssh-server // CentOS/Fedora```2. 使用scp命令传输文件要使用scp命令进行文件传输,需要使用以下的命令格式:```scp [选项] [来源路径] [目标路径]```例如,如果我们想将本地主机中的文件`file.txt`传输到远程主机的`/home/user`目录下,可以使用以下命令:```scp file.txt user@remote:/home/user```在上述命令中,`file.txt`是本地主机上的文件路径,`user`是远程主机的用户名,`remote`是远程主机的IP地址或域名,`/home/user`是远程主机的目标路径。
3. 使用scp命令传输文件夹除了传输单个文件,scp命令还可以传输整个文件夹。
要传输文件夹,需要使用`-r`选项,该选项表示递归复制整个目录结构和内容。
例如,如果我们想将本地主机中的文件夹`folder`传输到远程主机的`/home/user`目录下,可以使用以下命令:```scp -r folder user@remote:/home/user```在上述命令中,`folder`是本地主机上的文件夹路径。
Linux收发包流程概述
Linux收发包流程如下:
1. 应用程序通过套接字接口发送数据包,该数据包先要在网络协议栈中从上到下进行逐层处理,最终再送到网卡发送出去。
2. 网卡向CPU发起硬件中断,当CPU收到硬件中断请求后,根据中断表,调用已经注册的中断处理函数。
3. 中断处理函数会从用户态陷入到内核态中的Socket层,内核会申请一个内核态的sk_buff内存,将用户待发送的数据拷贝到sk_buff 内存,并将其加入到发送缓冲区。
4. 网络协议栈从Socket发送缓冲区中取出sk_buff,并按照TCP/IP协议栈从上到下逐层处理。
5. 传输层如果使用的是TCP传输协议发送数据,那么先拷贝一个新的sk_buff副本,接着,对sk_buff填充TCP头。
6. 然后交给网络层,在网络层里会做这些工作:选取路由(确认下一跳的IP)、填充IP头、netfilter过滤、对超过MTU大小的数据包进行分片。
处理完这些工作后会交给网络接口层处理。
7. 网络接口层负责物理地址寻址,找下一跳的MAC地址,添加帧头和帧尾,放到发包队列中。
8. 这一切完成后,会有软中断通知驱动程序:发包队列中有新的网络帧需要发送。
9. 驱动程序通过DMA ,从发包队列中读出网络帧,并通过物理网卡把它发送出去。
这就是Linux的收发包流程,仅供参考,建议查阅专业书籍或咨询专业人士获取更准确的信息。
linux二层转发流程Linux二层转发流程一、引言在计算机网络中,数据包的传输需要经过多个层次的处理与转发。
其中,二层转发是指在数据链路层进行的转发过程,主要涉及到以太网帧的封装、解封装、MAC地址的学习和转发决策等操作。
本文将详细介绍Linux系统中的二层转发流程。
二、Linux二层转发的基本原理Linux系统在进行二层转发时,主要依赖于内核中的网络协议栈和数据包处理模块。
其基本原理如下:1. 以太网帧的封装与解封装在进行二层转发时,Linux系统需要将上层协议的数据进行封装,生成以太网帧,以便在局域网中进行传输。
而在接收到以太网帧后,系统需要进行解封装,提取出上层协议的数据进行处理。
这一过程主要通过内核中的网络设备驱动程序来完成。
2. MAC地址的学习与转发决策在进行二层转发时,Linux系统需要学习各个网络设备的MAC地址,并建立转发表。
当接收到一个数据包时,系统会通过查找转发表来确定数据包的转发目的地。
如果目的MAC地址在转发表中存在对应的端口,则将数据包转发到相应的端口;如果不存在,则进行广播或丢弃处理。
三、Linux二层转发的详细流程在Linux系统中,二层转发的具体流程如下:1. 接收数据包当网络设备接收到一个数据包时,会触发中断通知内核,内核通过网络设备驱动程序将数据包从设备中读取到内存中。
2. 解封装数据包内核会对读取到的数据包进行解封装操作,提取出以太网帧中的数据和MAC地址等信息。
3. 查找转发表内核会根据目的MAC地址查找转发表,以确定数据包的转发目的地。
4. 转发数据包如果目的MAC地址在转发表中存在对应的端口,则将数据包转发到相应的端口。
否则,根据设置的转发策略进行广播或丢弃处理。
5. 更新转发表如果数据包的源MAC地址不在转发表中,则将该MAC地址与对应的端口进行学习,并更新转发表。
这样可以在下次转发时直接查找转发表,提高转发效率。
四、Linux二层转发的配置与管理在Linux系统中,可以通过配置和管理网络设备来实现二层转发的相关操作。
ip_forward转发原理IP转发是在网络中将IP数据包从源地址转发到目标地址的过程,其中涉及到的很多技术和原理需要熟练掌握,这里将具体介绍IP转发原理中的ip_forward转发。
ip_forward是Linux内核网络协议栈中的一个标志位,它表示系统是否开启IP路由功能,若该标志位置为1,表示系统开启了IP路由功能,可以将数据包在不同网络间转发。
ip_forward转发是Linux内核网络协议栈中非常重要的一环,它涉及到了Linux内核中多个协议层的相互协作,可以将近一步优化IP路由的效率和可靠性。
在Linux内核中,ip_forward转发是通过调用输入和输出协议栈中的相应函数实现的。
1.输入协议栈当系统收到一个IP数据包时,数据包首先会进入输入协议栈,进过IP层校验,获取接口地址和目标地址之后,内核将调用寻址函数,在路由表中搜索符合目标地址的路由条目,根据路由条目的下一跳地址和出网口确定发送时需要使用的接口。
数据包在经过ip_forward转发处理后,内核会将其重新打包,按指定的路径发送出去。
在Linux内核协议栈中,数据包在发送前会进过输出协议栈,经过协议栈中各层的处理后,最终发送到网卡驱动程序。
3.ARP查询在数据包发送前,还需要进行ARP查询以获得目标MAC地址,用于构建数据包的二层帧头,在ARP表中,数据包的目标地址和出接口可以找到对应的MAC地址,而路由器如果在自己的ARP表中找不到对应的MAC地址,就需要进行ARP查询,向同一网段中的其他设备广播ARP数据包,请求其他设备返回自己的MAC地址。
当收到其他设备的响应后,路由器会把获得的MAC地址存入其ARP表中,便于以后的数据包转发。
若路由器找不到目标设备的MAC地址并且其他设备也没有响应,就会丢弃该数据包,直到ARP响应返回为止。
总的来说,ip_forward是Linux内核网络协议栈中非常重要的一环,它可以将数据包在不同网络间转发,必要时进行ARP查询,提高数据传输的效率和可靠性。
linux libnetfilter_queue 数据转发的原理
libnetfilter_queue是Linux系统中一种使用用户空间处理网络
包的工具库。
它允许用户空间接收Linux内核中iptables规则
匹配到的网络数据包,并允许进行修改、丢弃或重新放行。
数据转发的原理如下:
1. 首先,用户程序使用libnetfilter_queue库创建一个netfilter
队列,并告诉Linux内核将匹配到的数据包发送到这个队列中。
2. 当有数据包匹配到iptables规则时,内核将数据包发送到创
建的netfilter队列中,由用户程序接收。
3. 用户程序收到数据包后,可以选择修改数据包的内容,如修改源IP地址、目标IP地址、端口等。
4. 用户程序可以根据自定义的逻辑进行判断,决定是否丢弃该数据包、修改后放行,或重新改写数据包后放行。
5. 最后,用户程序将修改后的数据包放行(通过)。
此时,内核将根据用户程序的操作决定是否将数据包继续传递给下一个规则进行匹配与处理。
值得注意的是,libnetfilter_queue只能在用户空间进行处理,
不能直接修改内核中的iptables规则。
因此,用户程序需要在iptables规则中将数据包发送到libnetfilter_queue中,然后在用
户程序中进行处理。
这样,用户程序可以根据自己的需求对数据包进行处理,而不受内核规则的限制。
AF_XDP发包原理随着互联网的迅速发展,网络通信已经成为了人们生活中不可或缺的一部分。
而在网络通信中,数据包的传输是非常重要的一环节。
因此,对于数据包的处理和传输技术的研究也变得越来越重要。
AF_XDP是一种高性能网络数据包处理技术,它在处理数据包时能够实现零拷贝,从而提高了数据包的处理效率。
本文将详细介绍AF_XDP发包的原理。
一、AF_XDP简介AF_XDP是Linux内核中的一种高性能网络数据包处理技术,它可以实现数据包的高速处理和转发。
AF_XDP是通过使用XDP(eXpress Data Path)技术来实现的。
XDP技术是一种高性能的数据包处理技术,它可以在内核空间中处理数据包,从而避免了数据包在用户空间和内核空间之间的频繁拷贝和上下文切换。
AF_XDP是在XDP技术的基础上,通过使用AF_PACKET套接字来实现的。
AF_PACKET是Linux内核中的一个套接字类型,它可以用于数据包的捕获和发送。
AF_XDP可以通过AF_PACKET套接字来发送数据包,从而实现高速的数据包传输。
二、AF_XDP发包原理AF_XDP的发包原理可以分为以下几个步骤:1. 创建AF_PACKET套接字在使用AF_XDP发送数据包之前,需要先创建一个AF_PACKET套接字。
AF_PACKET套接字可以使用socket()函数来创建,创建时需要指定套接字类型为AF_PACKET。
2. 创建XDP程序在使用AF_XDP发送数据包之前,还需要创建一个XDP程序。
XDP 程序可以使用BPF(Berkeley Packet Filter)来实现,BPF是一种内核中的虚拟机,它可以用于过滤和处理数据包。
3. 绑定AF_XDP套接字和XDP程序在创建完AF_PACKET套接字和XDP程序之后,需要将它们进行绑定。
绑定时需要使用setsockopt()函数,将AF_PACKET套接字和XDP 程序进行关联。
4. 构造数据包在进行AF_XDP数据包发送之前,需要先构造数据包。
本文欢迎自由转载,但请标明出处,并保证本文的完整性。
作者:Godbach日期:2009/09/01Normal7.8 磅2falsefalsefalseMicrosoftInternetExplorer4st1\:*{behavior:url(#ieooui) }/* Style Definitions */table.MsoNormalTable{mso-style-name:普通表格;mso-tstyle-rowband-size:0;mso-tstyle-colband-size:0;mso-style-noshow:yes;mso-style-parent:"";mso-padding-alt:0cm 5.4pt 0cm 5.4pt;mso-para-margin:0cm;mso-para-margin-bottom:.0001pt;mso-pagination:widow-orphan;font-size:10.0pt;font-family:"Times New Roman";mso-fareast-font-family:"Times New Roman";mso-ansi-language:#0400;mso-fareast-language:#0400;mso-bidi-language:#0400;}一、构造数据包简析这里并不详细介绍如何在内核中构造数据包,下文如有需要会在适当的位置进行分析。
这里简单的分析讲一下内核态基于Netfilter框架构造数据包的方式。
内核中可以用到的构造数据包的方式,个人认为可以分为两种。
其一,我们直接用alloc_skb申请一个skb结构体,然后根据实际的应用填充不同的成员,或者基于当前数据包的skb,调用skb_copy_expand()函数等新申请一个nskb,并且拷贝skb的内容。
其二,也是个人比较常用的,就是直接在先前接收到的数据包skb上作修改,主要有源IP、目IP,如果是TCP/UDP协议的话,还有源端口目的端口号。
总之,就是根据自己的需求去调整数据包的相关成员即可。
通常,这两种方式最终可能都要涉及到重新计算各个部分的校验和,这也是必须的。
二、如何发送构造的数据包承接上文,数据包已经构造完毕,下一步关键就是如何发送数据包了。
个人这里总结的有两种方法。
方法一,就是让数据包接着按照Netfilter的流程进行传输。
因为数据包的一些内容已经被更改,尤其是当源IP和目的IP被更改,主要是交换的情况下,是需要确保有路由可查的。
NF框架中查路由的位置一是在PREROUTING之后,而是在LOCALOUT之后。
又由于这里是需要将数据包从本地发送出去。
因此,可以考虑让修改后的数据包从LOCALOUT 点发出。
内核代码中有这种方式的典型体现。
本文涉及的相关内核代码的版本都是2.6.18.3。
源文件为ipt_REJECT.c,函数send_reset用于往当前接收到数据包的源IP上发送RST 包,整个函数涉及了数据包的构造和发送,这里一起做个简单分析。
/* Send RSTreply */static voidsend_reset(struct sk_buff *oldskb, int hook){struct sk_buff *nskb;struct iphdr *iph = oldskb->nh.iph;struct tcphdr _otcph, *oth, *tcph;struct rtable *rt;u_int16_t tmp_port;u_int32_t tmp_addr;int needs_ack;int hh_len;/* 判断是否是分片包*/if (oldskb->nh.iph->frag_off &htons(IP_OFFSET))return;/*得到TCP头部指针*/oth = skb_header_pointer(oldskb,oldskb->nh.iph->ihl * 4,sizeof(_otcph), &_otcph);if (oth == NULL)return;/* 当期收到的包就是RST包,就不用再发送RST包了*/if (oth->rst)return;/*检查数据包的校验和是否正确*/if (nf_ip_checksum(oldskb, hook, iph->ihl* 4, IPPROTO_TCP))return;/*这一步比较关键,做的就是更新路由的工作。
该函数的主要工作就是将当前数据包的源IP当做路由的目的IP,同时考虑数据包的目的IP,得到去往该源IP的路由*/ if ((rt = route_reverse(oldskb, oth, hook))== NULL)return;hh_len =LL_RESERVED_SPACE(rt->u.dst.dev);/* 拷贝当前的oldskb,包括skb结构体和数据部分。
这就是我们上面提到的构造数据包的第一种方式*/nskb = skb_copy_expand(oldskb, hh_len,skb_tailroom(oldskb),GFP_ATOMIC);if (!nskb) {dst_release(&rt->u.dst);return;}/*因为是拷贝的oldskb,这里不需要再引用了,因此释放对该路由项的引用*/dst_release(nskb->dst);/*将新构造数据包引用的路由指向上面由route_reverse函数返回的新的路由项*/ nskb->dst = &rt->u.dst;/* 清除nskb中拷贝过来的oldskb中链接跟踪相关的内容*/nf_reset(nskb);nskb->nfmark = 0;skb_init_secmark(nskb);/*以下就是构造数据包的实际数据部分。
如果我们将这里不为nskb新申请缓冲区,而直接指向oldskb的缓冲区,就使我们上面提到的第二种构造数据包的方法。
*/ /*获取nskb的tcp header*/tcph = (struct tcphdr*)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);/*交换源和目的IP */tmp_addr = nskb->nh.iph->saddr;nskb->nh.iph->saddr =nskb->nh.iph->daddr;nskb->nh.iph->daddr = tmp_addr;/*交换源和目的端口*/tmp_port = tcph->source;tcph->source = tcph->dest;tcph->dest = tmp_port;/*重置TCP头部的长度,并修改IP头部中记录的数据包的总长度。
因为这里是发送RST报文,只需要有TCP的头部,不需要TCP的数据部分*/tcph->doff = sizeof(struct tcphdr)/4;skb_trim(nskb, nskb->nh.iph->ihl*4 +sizeof(struct tcphdr));nskb->nh.iph->tot_len =htons(nskb->len);/*重新设置seq, ack_seq,分两种情况(TCP/IP详解有描述)*/if (tcph->ack) { /*原始数据包中ACK标记位置位的情况*/needs_ack = 0;tcph->seq = oth->ack_seq; /*原始数据包的ack_seq作为nskb的seq*/ tcph->ack_seq = 0;} else { /*原始数据包中ACK标记位没有置位的情况,初始连接SYN或者结束连接FIN等*/needs_ack = 1;/*这种情况应该是SYN或者FIN包,由于SYN和FIN包都占用1个字节的长度。
因此ack_seq应该等于旧包的seq+1即可。
这里之所以这样表示,可能是还存在其他情况的数据包。
*/tcph->ack_seq =htonl(ntohl(oth->seq) + oth->syn + oth->fin+ oldskb->len - oldskb->nh.iph->ihl*4- (oth->dofftcph->seq = 0;}/* RST标记位置1*/((u_int8_t *)tcph)[13] = 0;tcph->rst = 1;tcph->ack = needs_ack;tcph->window = 0;tcph->urg_ptr = 0;/*重新计算TCP校验和*/tcph->check = 0;tcph->check = tcp_v4_check(tcph, sizeof(structtcphdr),nskb->nh.iph->saddr,nskb->nh.iph->daddr,csum_partial((char *)tcph,sizeof(struct tcphdr),0));/* 修改IP包的TTL,并且设置禁止分片*/nskb->nh.iph->ttl =dst_metric(nskb->dst, RTAX_HOPLIMIT);/* Set DF, id = 0 */nskb->nh.iph->frag_off = htons(IP_DF);nskb->nh.iph->id = 0;/*重新计算IP数据包头部校验和*/nskb->nh.iph->check = 0;nskb->nh.iph->check =ip_fast_csum((unsigned char *)nskb->nh.iph,nskb->nh.iph->ihl);/* "Never happens" */if (nskb->len > dst_mtu(nskb->dst))goto free_nskb;/*使nskb和oldskb的链接记录关联*/nf_ct_attach(nskb, oldskb);/*这里就是最终发送数据包的方式,具体方法就是让新数据包经过LOACLOUT的hook点,然后查路由,最后经由PREROUTING点,将数据包发送出去。