linux tcp header更改,Linux Netfilter中修改TCP/UDP Payload的方法
来自linux-2.6.36/net/ipv4/netfilter/nf_nat_helper.c
注:该代码可以移植到ebtables中使用,但需要注意struct rtable *rt结构在ebtables中是没有的。
修改UDP payload的代码:
/* Unusual, but possible case. */
static int enlarge_skb(struct sk_buff *skb, unsigned int extra)
{
if (skb->len + extra > 65535)
return 0;
if (pskb_expand_head(skb, 0, extra - skb_tailroom(skb), GFP_ATOMIC))
return 0;
return 1;
}
/* Frobs data inside this packet, which is linear. */
static void mangle_contents(struct sk_buff *skb,
unsigned int dataoff,
unsigned int match_offset,
unsigned int match_len,
const char *rep_buffer,
unsigned int rep_len)
{
unsigned char *data;
BUG_ON(skb_is_nonlinear(skb));
data = skb_network_header(skb) + dataoff;
/* move post-replacement */
memmove(data + match_offset + rep_len,
data + match_offset + match_len,
skb->tail - (skb->network_header + dataoff +
match_offset + match_len));
/* insert data from buffer */
memcpy(data + match_offset, rep_buffer, rep_len);
/* update skb info */
if (rep_len > match_len) {
pr_debug("nf_nat_mangle_packet: Extending packet by "
"%u from %u bytes\n", rep_len - match_len, skb->len);
skb_put(skb, rep_len - match_len);
} else {
pr_debug("nf_nat_mangle_packet: Shrinking packet from "
"%u from %u bytes\n", match_len - rep_len, skb->len);
__skb_trim(skb, skb->len + rep_len - match_len);
}
/* fix IP hdr checksum information */
ip_hdr(skb)->tot_len = htons(skb->len);
ip_send_check(ip_hdr(skb));
}
/* Generic function for mangling variable-length address changes of UDP packet's payload
*
* Takes care about all the nasty sequence number changes, checksumming,
* skb enlargement, ...
*
* match_offset: the payload's start point to be mangled
* match_len: the payload's length to be mangled, when 0 means insert some data into the payload
* rep_buffer: the new data to be inserted.
* rep_len: the new data's length to be inserted.
*/
static int
mangle_udp_packet(struct sk_buff *skb,
unsigned int match_offset,
unsigned int match_len,
const char *rep_buffer,
unsigned int rep_len)
{
struct rtable *rt = skb_rtable(skb);
struct iphdr *iph;
struct udphdr *udph;
int datalen, oldlen;
/* UDP helpers might accidentally mangle the wrong packet */
iph = ip_hdr(skb);
if (skb->len < iph->ihl*4 + sizeof(*udph) +
match_offset + match_len)
return 0;
if (!skb_make_writable(skb, skb->len))
return 0;
if (rep_len > match_len &&
rep_len - match_len > skb_tailroom(skb) &&
!enlarge_skb(skb, rep_len - match_len))
return 0;
iph = ip_hdr(skb);
udph = (void *)iph + iph->ihl*4;
oldlen = skb->len - iph->ihl*4;
mangle_contents(skb, iph->ihl*4 + sizeof(*udph),
match_offset, match_len, rep_buffer, rep_len);
/* update the length of the UDP packet */
datalen = skb->len - iph->ihl*4;
udph->len = htons(datalen);
/* fix udp checksum if udp checksum was previously calculated */
if (!udph->check && skb->ip_summed != CHECKSUM_PARTIAL)
return 1;
if (skb->ip_summed != CHECKSUM_PARTIAL) {
if (rt && !(rt->rt_flags & RTCF_LOCAL) &&
skb->dev->features & NETIF_F_V4_CSUM) {
skb->ip_summed = CHECKSUM_PARTIAL;
skb->csum_start = skb_headroom(skb) +
skb_network_offset(skb) +
iph->ihl * 4;
skb->csum_offset = offsetof(struct udphdr, check);
udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
datalen, IPPROTO_UDP,
0);
} else {
udph->check = 0;
udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
datalen, IPPROTO_UDP,
csum_partial(udph,
datalen, 0));
if (!udph->check)
udph->check = CSUM_MANGLED_0;
}
} else {
inet_proto_csum_replace2(&udph->check, skb,
htons(oldlen), htons(datalen), 1);
}
return 1;
}
修改TCP payload的方法:
/* Generic function for mangling variable-length address changes inside
* NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
* command in FTP).
*
* Takes care about all the nasty sequence number changes, checksumming,
* skb enlargement, ...
*
* */
int __nf_nat_mangle_tcp_packet(struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int match_offset,
unsigned int match_len,
const char *rep_buffer,
unsigned int rep_len, bool adjust)
{
struct rtable *rt = skb_rtable(skb);
struct iphdr *iph;
struct tcphdr *tcph;
int oldlen, datalen;
if (!skb_make_writable(skb, skb->len))
return 0;
if (rep_len > match_len &&
rep_len - match_len > skb_tailroom(skb) &&
!enlarge_skb(skb, rep_len - match_len))
return 0;
SKB_LINEAR_ASSERT(skb);
iph = ip_hdr(skb);
tcph = (void *)iph + iph->ihl*4;
oldlen = skb->len - iph->ihl*4;
mangle_contents(skb, iph->ihl*4 + tcph->doff*4,
match_offset, match_len, rep_buffer, rep_len);
datalen = skb->len - iph->ihl*4;
if (skb->ip_summed != CHECKSUM_PARTIAL) {
if (!(rt->rt_flags & RTCF_LOCAL) &&
skb->dev->features & NETIF_F_V4_CSUM) {
skb->ip_summed = CHECKSUM_PARTIAL;
skb->csum_start = skb_headroom(skb) +
skb_network_offset(skb) +
iph->ihl * 4;
skb->csum_offset = offsetof(struct tcphdr, check);
tcph->check = ~tcp_v4_check(datalen,
iph->saddr, iph->daddr, 0);
} else {
tcph->check = 0;
tcph->check = tcp_v4_check(datalen,
iph->saddr, iph->daddr,
csum_partial(tcph,
datalen, 0));
}
} else
inet_proto_csum_replace2(&tcph->check, skb,
htons(oldlen), htons(datalen), 1);
if (adjust && rep_len != match_len)
nf_nat_set_seq_adjust(ct, ctinfo, tcph->seq,
(int)rep_len - (int)match_len);
return 1;
}
linux tcp header更改,Linux Netfilter中修改TCP/UDP Payload的方法相关推荐
- linux环境配置以后生效,Linux中修改环境变量及生效方法
Linux中修改环境变量及生效方法 在/etc/profile文件中添加变量[对所有用户生效(永久的)] 用VI在文件/etc/profile文件中增加变量,该变量将会对Linux下所有用户有效,并且 ...
- linux环境变量生效方式,Linux中修改环境变量及生效方法
Linux中修改环境变量及生效方法 方法一: 在/etc/profile文件中添加变量[对所有用户生效(永久的)] 用VI在文件/etc/profile文件中增加变量,该变量将会对Linux下所有用户 ...
- python写错了怎么更改-Python中修改字符串的四种方法
在Python中,字符串是不可变类型,即无法直接修改字符串的某一位字符. 因此改变一个字符串的元素需要新建一个新的字符串. 常见的修改方法有以下4种. 方法1:将字符串转换成列表后修改值,然后用joi ...
- python字符串中某个字符修改_Python中修改字符串的四种方法
在Python中,字符串是不可变类型,即无法直接修改字符串的某一位字符. 因此改变一个字符串的元素需要新建一个新的字符串. 常见的修改方法有以下4种. 方法1:将字符串转换成列表后修改值,然后用joi ...
- 单一修改高程值lisp_浅谈AutoCAD中修改高程的四种方法
浅谈 AutoCAD 中修改高程的四种方法 摘 要: 在使用 AutoCAD 进行数字化成图工作中,经常遇到线划的标高不为零,及高程点的值与实地不符,需要对其进行修改等情况,结合实 际工作经验,简单介 ...
- word涂改涂掉图片_怎么在word中修改图片的两种方法
有时我们插入的图片只有一部分是我们想要的,那就需要我们将这一部分裁剪出来,word本身就可以方便快捷的对图片进行裁剪,那么下面就由学习啦小编给大家分享下在word中修改图片的技巧,希望能帮助到您. 在 ...
- linux内核 header.s,Linux启动代码header.S研究
Linux内核从2.4升级到2.6之后,内核的引导过程发生了许多变化,现在研究一下Linux内核2.6版本的主要引导过程. (参考资料: 1.<深入理解Linux内核>附录A: 2.Lin ...
- linux mint 18.3浏览器,在Linux Mint 19/Ubuntu 18.04中安装Tor Browser浏览器的方法
本文介绍在Linux Mint 19/Ubuntu 18.04系统中安装Tor Browser浏览器的方法,本文不使用Tor的默认Ubuntu存储库,因为它们包含旧版本的Tor. 一.添加Tor存储库 ...
- b宝塔 centos端口更改_BT宝塔面板修改默认8888端口的方法
BT宝塔面板默认的端口为8888号端口,安全起见,用户可以自定义更改默认的8888端口号,环境吧分享BT宝塔面板修改默认端口号的方法: BT宝塔面板修改默认端口号的方法 更改8888号默认端口号的方法 ...
最新文章
- There is no isNullOrEmpty for collections in Guawa
- bose耳机信号断续_最便宜的TWS主动降噪耳机 233621 Zen 4400字深度评测
- figure diagram illustrate exemplify profile
- django学习第77天Django框架ORM
- turtle python tkinter_【案例】 什么?idle 中竟然有内置 turtle 样例?(paint)
- leetcode 两数相加
- 我的第一次Pascal程序
- 课堂练习 组合数据练习
- codevs 1683 车厢重组
- MySQL8.0.22解压安装教程
- 基于python flask的网上商城源码 mysql数据库
- 数据恢复——在Windows 10中恢复永久删除的文件的5种方法
- 看他如何做到4年2个博士学位,做研究、出书挣钱两不误。
- 图像拼接(八):拼接多幅图像+Matlab实现+Stanford Open Course
- 2016年VB图书253本推荐
- docker部署微服务项目
- samba服务器讲解
- 字符串根据字节长度进行截取并展示选中效果——js字符串获取字节长度
- Gephi中的统计算法学习
- ThingsBoard添加高德地图
热门文章
- python 动态规划 数塔_数塔问题,简单的动态规划算法
- java mysql show status_Java 能不能执行mysql 中的show master status 命令
- Android 向右滑返回,退出当前activity
- Android修改项目包名
- csdn markdown 编辑器开启
- centos7 python3.6编译安装
- SharpZipLib压缩解压
- 用conda安装虚拟的R环境
- dw替换多个html标签,DW查找替换的技巧
- 服务器imm口加载硬盘,ibm x3250 M4如何进IMM(远程管理口)