mirror of
https://github.com/CHN-beta/xmurp-ua.git
synced 2026-01-12 01:55:24 +08:00
大框架写完了 还需要写main函数 细节上检查一下 禁用 keep-alive
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.vscode
|
||||||
4
Makefile
4
Makefile
@@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
|
|||||||
include $(INCLUDE_DIR)/kernel.mk
|
include $(INCLUDE_DIR)/kernel.mk
|
||||||
|
|
||||||
PKG_NAME:=xmurp-ua
|
PKG_NAME:=xmurp-ua
|
||||||
PKG_RELEASE:=27
|
PKG_RELEASE:=28
|
||||||
|
|
||||||
include $(INCLUDE_DIR)/package.mk
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ define KernelPackage/xmurp-ua
|
|||||||
SUBMENU:=Other modules
|
SUBMENU:=Other modules
|
||||||
TITLE:=xmurp-ua
|
TITLE:=xmurp-ua
|
||||||
FILES:=$(PKG_BUILD_DIR)/xmurp-ua.ko
|
FILES:=$(PKG_BUILD_DIR)/xmurp-ua.ko
|
||||||
AUTOLOAD:=$(call AutoLoad,99,xmurp-ua)
|
# AUTOLOAD:=$(call AutoLoad,99,xmurp-ua)
|
||||||
KCONFIG:=
|
KCONFIG:=
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
|||||||
182
src/scanner.h
Normal file
182
src/scanner.h
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
#include <linux/kmod.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/netfilter.h>
|
||||||
|
#include <linux/netfilter_ipv4.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/tcp.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
const char str_ua[] const = "User-Agent: ";
|
||||||
|
const char str_headtail[] const = "\r\n\r\n";
|
||||||
|
const char str_uaend[] const = "\r\n";
|
||||||
|
const char str_windows[] const = "Windows NT";
|
||||||
|
|
||||||
|
struct scanner
|
||||||
|
// 字符串扫描(跨 skb)需要的一些状态变量以及函数
|
||||||
|
{
|
||||||
|
struct sk_buff* skb; // 当前正在扫描的字符所在的 skb
|
||||||
|
char* data_start;
|
||||||
|
char* data_end; // skb 的应用层起始位置和终止位置,记下来避免每次计算
|
||||||
|
char* pos; // 现在扫描到的位置
|
||||||
|
|
||||||
|
const char* target; // 要匹配的字符串
|
||||||
|
u_int8_t target_legth; // 要匹配的字符串的长度
|
||||||
|
|
||||||
|
u_int8_t enum
|
||||||
|
{
|
||||||
|
matching_none,
|
||||||
|
matching_content,
|
||||||
|
matching_headtail
|
||||||
|
} matching_status; // 当前匹配的状态:没有正在匹配的,正在匹配所给的内容,正在匹配 http 头结尾
|
||||||
|
u_int16_t matched_length; // 如果正在匹配给定的内容或者头结尾,这里指示已经匹配的长度(包含当前的字符)
|
||||||
|
};
|
||||||
|
void scanner_init(struct scanner* scn, struct sk_buff* skb, u_int16_t pos, const char* target)
|
||||||
|
// 初始化扫描器
|
||||||
|
// pos 指指针相对于给定的 skb 的应用层第一个字节的位置。skb 的第一个应用层字节的位置为 0。
|
||||||
|
{
|
||||||
|
// 找到目标字节真正所的 skb
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
register struct tcphdr *tcph = tcp_hdr(skb);
|
||||||
|
register struct iphdr *iph = ip_hdr(skb);
|
||||||
|
u_int16_t data_length = ntohs(iph -> tot_len) - iph -> ihl * 4 - tcph -> doff * 4;
|
||||||
|
if(pos >= data_length)
|
||||||
|
pos -= data_length;
|
||||||
|
}
|
||||||
|
scn -> skb = skb;
|
||||||
|
scn -> data_start = (char*)tcph + tcph -> doff * 4;
|
||||||
|
scn -> data_end = (char*)tcph + ntohs(iph -> tot_len) - iph -> ihl * 4;
|
||||||
|
scn -> pos = scn -> data_start + pos;
|
||||||
|
scn -> target = target;
|
||||||
|
scn -> target_length = strlen(target);
|
||||||
|
scn -> matching_status = scn -> matching_none;
|
||||||
|
scn -> matched_length = 0;
|
||||||
|
}
|
||||||
|
u_int8_t scanner_next(struct scanner* scn)
|
||||||
|
// 尝试将指针移动到下一个字节。会自动跨 skb。
|
||||||
|
// 返回值:0 没有匹配完毕什么;1 目标字符串匹配完毕;2 http 头匹配完毕;-1 需要下一个 skb(下一个 skb 的指针是 0,或者根据序列判断并不是紧邻的下一个 skb
|
||||||
|
// 注意到,如果要匹配 "\r\n" 之类以 '\r' 开头的字符串时,不能正确地识别 http 头结尾;以及,匹配长度为 1 的字符串时也会出错。但这并不影响最终结果。
|
||||||
|
{
|
||||||
|
// 尝试将指针移动到下一个位置
|
||||||
|
if(scn -> pos + 1 == scn -> data_end)
|
||||||
|
{
|
||||||
|
if(scn -> skb -> next == 0)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
register u_int32_t target_seq = ntohl(tcp_hdr(scn -> skb) -> seq) + (scn -> data_end - scn -> data_start);
|
||||||
|
if(target_seq != ntolh(scn -> skb -> next -> seq))
|
||||||
|
return -1
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scn -> skb = scn -> skb -> next;
|
||||||
|
register struct tcphdr *tcph = tcp_hdr(scn -> skb);
|
||||||
|
register struct iphdr *iph = ip_hdr(scn -> skb);
|
||||||
|
scn -> data_start = (char*)tcph + tcph -> doff * 4;
|
||||||
|
scn -> data_end = (char*)tcph + ntohs(iph -> tot_len) - iph -> ihl * 4;
|
||||||
|
scn -> pos = scn -> data_start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
scn -> pos++;
|
||||||
|
|
||||||
|
// 检查匹配情况
|
||||||
|
if(scn -> matching_status == scn -> matching_none)
|
||||||
|
{
|
||||||
|
if(scn -> pos[0] == scn -> target[0])
|
||||||
|
{
|
||||||
|
scn -> matching_status == scn -> matching_target;
|
||||||
|
scn -> matched_length = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if(scn -> pos[0] == str_headtail[0])
|
||||||
|
{
|
||||||
|
scn -> matching_status == scn -> matching_headtail;
|
||||||
|
scn -> matched_length = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if(scn -> matching_status == scn -> matching_target)
|
||||||
|
{
|
||||||
|
if(scn -> pos[0] == scn -> target[scn -> matched_length])
|
||||||
|
{
|
||||||
|
scn -> matched_length++;
|
||||||
|
if(scn -> matched_length == scn -> matched_length)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if(scn -> pos[0] == str_headtail[0])
|
||||||
|
{
|
||||||
|
scn -> matching_status == scn -> matching_headtail;
|
||||||
|
scn -> matched_length = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scn -> matching_status == scn -> matching_none;
|
||||||
|
scn -> matched_length = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(scn -> matching_status == scn -> matching_target)
|
||||||
|
{
|
||||||
|
if(scn -> pos[0] == str_headtail[scn -> matched_length])
|
||||||
|
{
|
||||||
|
scn -> matched_length++;
|
||||||
|
if(scn -> matched_length == 4)
|
||||||
|
return 2;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if(scn -> pos[0] == scn -> target[0])
|
||||||
|
{
|
||||||
|
scn -> matching_status == scn -> matching_target;
|
||||||
|
scn -> matched_length = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scn -> matching_status == scn -> matching_none;
|
||||||
|
scn -> matched_length = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void scanner_prev(struct scanner* scn)
|
||||||
|
// 将指针移动到上一个字节。会自动跨 skb。
|
||||||
|
// 不需要考虑匹配的状态。保证上一个 skb 一定存在。
|
||||||
|
{
|
||||||
|
if(scn -> pos == scn -> data_start)
|
||||||
|
{
|
||||||
|
scn -> skb = scn -> skb -> prev;
|
||||||
|
register struct tcphdr *tcph = tcp_hdr(scn -> skb);
|
||||||
|
register struct iphdr *iph = ip_hdr(scn -> skb);
|
||||||
|
scn -> data_start = (char*)tcph + tcph -> doff * 4;
|
||||||
|
scn -> data_end = (char*)tcph + ntohs(iph -> tot_len) - iph -> ihl * 4;
|
||||||
|
scn -> pos = scn -> data_end - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
scn -> pos--;
|
||||||
|
}
|
||||||
|
void scanner_next_noscan(struct scanner* scn)
|
||||||
|
{
|
||||||
|
if(scn -> pos + 1 == scn -> data_end)
|
||||||
|
{
|
||||||
|
scn -> skb = scn -> skb -> next;
|
||||||
|
register struct tcphdr *tcph = tcp_hdr(scn -> skb);
|
||||||
|
register struct iphdr *iph = ip_hdr(scn -> skb);
|
||||||
|
scn -> data_start = (char*)tcph + tcph -> doff * 4;
|
||||||
|
scn -> data_end = (char*)tcph + ntohs(iph -> tot_len) - iph -> ihl * 4;
|
||||||
|
scn -> pos = scn -> data_start;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
scn -> pos++;
|
||||||
|
}
|
||||||
187
src/stm_info.h
Normal file
187
src/stm_info.h
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
#include "scanner.h"
|
||||||
|
|
||||||
|
struct stm_info
|
||||||
|
// 用于存储每一条流的信息。
|
||||||
|
{
|
||||||
|
u_int8_t modify_finished:1, // 标识是否已经被修改完成。对于修改完成的流,肯定没有存储任何 skb,之后都不会再捕获。对于不需要修改的流,最初的时候就会被置为“已经修改完成”而直接放行。
|
||||||
|
modify_force:1, // 是否强制修改这个流(而不论目标地址,也不论是否是 windows 主机),与 mark 中的内容对应。
|
||||||
|
scan_finished:1, // 是否已经扫描完成;也就是说,已经完整地找到了 ua,或者完整地拿到了 http 头。之后不再会捕获这个流,但流中可能还有缓存的 skb 没有发出。windows 也已经被扫描(除非没有必要)。
|
||||||
|
scan_ua_found:1, // 是否找到了 ua。只要找到了 "User-Agent: " 这一项就被置为 1,ua_start 同时被设置;ua_end 则会等到 scan_finished 才被设置。
|
||||||
|
scan_windows:1, // ua 是否是 windows 的 ua。在完整地找到 ua 后,除非 modify_force 被设置,否则会再扫描一遍 ua 来确定这个值。
|
||||||
|
preserved:3;
|
||||||
|
u_int32_t saddr; // 源地址
|
||||||
|
u_int16_t sport; // 源端口。通过这两项应该足够区分不同的流。
|
||||||
|
u_int32_t seq_offset; // 应用层字节的编号的偏移,减去偏移后,第一个应用层字节的编号为 0
|
||||||
|
u_int32_t ua_start; // "User-Agent: xxxxx\r\n" 中,第一个 'x' 的位置(已经减去偏移)
|
||||||
|
u_int32_t ua_end; // "User-Agent: xxxxx\r\n?" 中,‘\r’ 的位置(已经减去偏移)
|
||||||
|
struct sk_buff* skb;
|
||||||
|
struct scanner* scn;
|
||||||
|
};
|
||||||
|
void stm_init(struct stm_info* stm, struct sk_buff* skb)
|
||||||
|
// 初始化 stm_info
|
||||||
|
{
|
||||||
|
stm -> modify_finished = 0;
|
||||||
|
if(skb -> mark & 0x20)
|
||||||
|
stm -> modify_force = 1;
|
||||||
|
else
|
||||||
|
stm -> modify_force = 0;
|
||||||
|
stm -> scan_finished = 0;
|
||||||
|
stm -> saddr = ntohl(ip_hdr(skb) -> daddr);
|
||||||
|
stm -> sport = ntohs(tcp_hdr(skb) -> dest);
|
||||||
|
stm -> seq_offset = ntohl(tcp_hdr(skb) -> ack_seq);
|
||||||
|
stm -> skb = 0;
|
||||||
|
stm -> scn = 0;
|
||||||
|
}
|
||||||
|
u_int32_t stm_realseq(struct stm_info* stm, struct sk_buff* skb)
|
||||||
|
// 计算 skb 的真实偏移
|
||||||
|
{
|
||||||
|
register u_int32_t real_seq = ntohl(tcp_hdr(skb) -> ack_seq);
|
||||||
|
if(real_seq >= stm -> seq_offset)
|
||||||
|
real_seq -= stm -> seq_offset;
|
||||||
|
else
|
||||||
|
real_seq += 0xffffffff - stm -> seq_offset + 1;
|
||||||
|
return real_seq;
|
||||||
|
}
|
||||||
|
void stm_append(struct stm_info* stm, struct sk_buff* skb)
|
||||||
|
// 追加一个 skb 到合适的位置。
|
||||||
|
{
|
||||||
|
register u_int32_t real_seq;
|
||||||
|
register struct sk_buff* i;
|
||||||
|
if(stm -> skb == 0)
|
||||||
|
{
|
||||||
|
stm -> skb = skb;
|
||||||
|
skb -> next = skb -> prev = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
real_seq = stm_realseq(stm, skb);
|
||||||
|
if(stm_realseq(stm, stm -> skb) > real_seq)
|
||||||
|
{
|
||||||
|
stm -> skb -> prev = skb;
|
||||||
|
skb -> next = stm -> skb;
|
||||||
|
stm -> skb = skb;
|
||||||
|
}
|
||||||
|
|
||||||
|
//尝试寻找最后一个序号比待插入 skb 小的 skb
|
||||||
|
for(i = stm -> skb;;i = i -> next)
|
||||||
|
{
|
||||||
|
if(i -> next == 0)
|
||||||
|
{
|
||||||
|
i -> next = skb;
|
||||||
|
skb -> prev = i;
|
||||||
|
skb -> next = 0;
|
||||||
|
}
|
||||||
|
else if(stm_realseq(stm, i -> next) > real_seq)
|
||||||
|
{
|
||||||
|
i -> next -> prev = skb;
|
||||||
|
skb -> next = i -> next;
|
||||||
|
i -> next = skb;
|
||||||
|
skb -> prev = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void stm_scan(struct stm_info* stm)
|
||||||
|
// 扫描直到头部末尾或者 ua 结束(总之是使得 scan_finished)或者不能再继续扫描了(需要下一个包)。也会扫描 windows,如果有必要。
|
||||||
|
{
|
||||||
|
// 如果没有初始化扫描器,就尝试初始化
|
||||||
|
if(stm -> scn == 0)
|
||||||
|
{
|
||||||
|
if(stm -> skb == 0 || stm_realseq(stm, stm -> skb) != 0)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stm -> scn = kmalloc(sizeof(scanner), GFP_KERNEL);
|
||||||
|
scanner_init(stm -> scn, stm -> skb, 0, str_ua);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* ua_end = 0; // 仅仅用来扫描 windows 时使用一下。记录 ua 的结束位置,当扫描到这里时还没有 windows,那就是没有了。
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
u_int8_t rtn = scanner_next(stm -> scn);
|
||||||
|
if(rtn == 0 && stm -> scn -> pos == ua_end)
|
||||||
|
// 没有找到 windows
|
||||||
|
{
|
||||||
|
stm -> scan_finished = 1;
|
||||||
|
ua_end = 0;
|
||||||
|
}
|
||||||
|
else if(rtn == 0)
|
||||||
|
continue;
|
||||||
|
else if(rtn == 1 && stm -> scn -> target == str_ua)
|
||||||
|
{
|
||||||
|
// 将结果记录,然后去扫描 ua 尾。
|
||||||
|
stm -> scan_ua_found;
|
||||||
|
stm -> ua_start = stm_realseq(stm, stm -> scn -> skb) + (stm -> scn -> pos - stm -> scn -> data_start);
|
||||||
|
scanner_init(stm -> scn, stm -> scn -> skb, stm -> scn -> pos - stm -> scn -> data_start, str_uaend);
|
||||||
|
}
|
||||||
|
else if(rtn == 1 && stm -> scn -> target == str_uaend)
|
||||||
|
{
|
||||||
|
// 将结果记录,然后去扫描 windows 或者结束。
|
||||||
|
stm -> ua_end = stm_realseq(stm, stm -> scn -> skb) + (stm -> scn -> pos - stm -> scn -> data_start) + 1;
|
||||||
|
if(!stm -> modify_force)
|
||||||
|
scanner_init(stm -> scn, stm -> skb, stm -> ua_start, str_windows);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stm -> scan_finished = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(rtn == 1 && stm -> scn -> target == str_windows)
|
||||||
|
// 将结果记录,结束
|
||||||
|
{
|
||||||
|
stm -> scan_windows = 1;
|
||||||
|
stm -> scan_finished = 1;
|
||||||
|
ua_end = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(rtn == 2)
|
||||||
|
{
|
||||||
|
stm -> scan_finished;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void stm_modify_send(struct stm_info* stm)
|
||||||
|
// 将 ua 替换为 "XMURP/1.0" 加许多的空格
|
||||||
|
{
|
||||||
|
struct sk_buff* skb_start;
|
||||||
|
struct sk_buff* skb_end; // 两个 skb 之间的(包含这两个 skb)都需要重新计算校验和
|
||||||
|
sturct sk_buff* skb;
|
||||||
|
u_int16_t i;
|
||||||
|
scanner_init(stm -> scn, stm -> skb, stm -> ua_start, str_ua);
|
||||||
|
skb_start = stm -> scn -> skb;
|
||||||
|
scanner_prev(stm -> scn);
|
||||||
|
for(int i = 0; i < stm -> ua_end - stm -> ua_start; i++)
|
||||||
|
{
|
||||||
|
scanner_next_noscan(stm -> scn);
|
||||||
|
if(i < strlen("XMURP/1.0"))
|
||||||
|
*(stm -> scn -> pos) = "XMURP/1.0"[i];
|
||||||
|
else
|
||||||
|
*(stm -> scn -> pos) = ' ';
|
||||||
|
}
|
||||||
|
skb_end = stm -> scn -> skb -> next;
|
||||||
|
|
||||||
|
skb = skb_start;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
register struct tcp_hdr* tcph = tcp_hdr(skb);
|
||||||
|
register struct ip_hdr* iph = ip_hdr(skb);
|
||||||
|
tcph->check = 0;
|
||||||
|
iph->check = 0;
|
||||||
|
skb->csum = skb_checksum(skb, iph->ihl * 4, ntohs(iph->tot_len) - iph->ihl * 4, 0);
|
||||||
|
iph->check = ip_fast_csum(iph, iph->ihl);
|
||||||
|
tcph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, ntohs(iph->tot_len) - iph->ihl * 4, IPPROTO_TCP, skb->csum);
|
||||||
|
}
|
||||||
|
while((skb = skb -> next) != skb_end);
|
||||||
|
|
||||||
|
skb = stm -> skb;
|
||||||
|
while(skb != 0)
|
||||||
|
{
|
||||||
|
dev_queue_xmit(skb);
|
||||||
|
skb = skb -> next;
|
||||||
|
}
|
||||||
|
|
||||||
|
stm -> modify_finished = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
49
src/stm_vec.h
Normal file
49
src/stm_vec.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#include "stm_info.h"
|
||||||
|
|
||||||
|
struct stm_vec
|
||||||
|
// 用于存储一条条流的向量,包含了扩大等函数。
|
||||||
|
{
|
||||||
|
struct stm_info* data;
|
||||||
|
u_int16_t max_size;
|
||||||
|
u_int16_t size;
|
||||||
|
};
|
||||||
|
void stm_vec_init(struct stm_vec* stmv)
|
||||||
|
// 初始化 skb_vec
|
||||||
|
{
|
||||||
|
stmv -> max_size = 4;
|
||||||
|
stmv -> size = 0;
|
||||||
|
stmv -> data = kmalloc(sizeof(stm_info) * stmv -> max_size, GFP_KERNEL)
|
||||||
|
}
|
||||||
|
void stm_vec_insert(struct stm_vec* stmv)
|
||||||
|
// 为 skb_vec 增加一条流。不会初始化新增的流。
|
||||||
|
{
|
||||||
|
if(stmv -> size == stmv -> max_size) // 如果满了,就扩大
|
||||||
|
{
|
||||||
|
struct stm_info* temp = stmv -> data;
|
||||||
|
stmv -> max_size *= 2;
|
||||||
|
stmv -> data = kmalloc(sizeof(stm_info) * stmv -> max_size, GFP_KERNEL)
|
||||||
|
memcpy(stmv -> data, temp, sizeof(stm_info) * stmv -> size);
|
||||||
|
kfree(temp);
|
||||||
|
printk("xmurp-ua: Streams buff expanded to %d.\n", stmv -> max_size);
|
||||||
|
}
|
||||||
|
stmv -> size++;
|
||||||
|
}
|
||||||
|
u_int16_t stm_vec_find(struct stm_vec* stmv, struct sk_buff* skb)
|
||||||
|
// 根据一个数据包来寻找它属于哪个流。数据包必须是客户端发给服务端的。如果没有找到,返回 0xffff。
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u_int32_t saddr = ntohl(ip_hdr(skb) -> saddr;
|
||||||
|
u_int32_t sport = ntohs(tcp_hdr(skb) -> src);
|
||||||
|
for(i = 0; i < stmv -> size; i++)
|
||||||
|
if(saddr == stmv -> data[i].saddr && sport == stmv -> data[i].sport)
|
||||||
|
return i;
|
||||||
|
return 0xffff;
|
||||||
|
}
|
||||||
|
void stm_vec_del(struct stm_vec* stmv, u_int16_t pos)
|
||||||
|
// 删除指定流,后面的往前移。
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = pos; i < size - 1; i++)
|
||||||
|
stmv -> data[i] = stv -> data[i + 1];
|
||||||
|
stmv -> size--;
|
||||||
|
}
|
||||||
@@ -7,7 +7,6 @@
|
|||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
#include <linux/tcp.h>
|
#include <linux/tcp.h>
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
#include <linux/random.h>
|
|
||||||
|
|
||||||
static struct nf_hook_ops nfho;
|
static struct nf_hook_ops nfho;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user