diff --git a/Makefile b/Makefile index 9ca90fc..9943099 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk -PKG_NAME:=xmurp-ua +PKG_NAME:=rkp-ua PKG_RELEASE:=28 include $(INCLUDE_DIR)/package.mk @@ -9,17 +9,18 @@ include $(INCLUDE_DIR)/package.mk EXTRA_CFLAGS:= \ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \ + -DVERSION $(PKG_RELEASE) MAKE_OPTS:=$(KERNEL_MAKE_FLAGS) \ SUBDIRS="$(PKG_BUILD_DIR)" \ EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ - CONFIG_xmurp-ua=m + CONFIG_rkp-ua=m -define KernelPackage/xmurp-ua +define KernelPackage/rkp-ua SUBMENU:=Other modules - TITLE:=xmurp-ua - FILES:=$(PKG_BUILD_DIR)/xmurp-ua.ko -# AUTOLOAD:=$(call AutoLoad,99,xmurp-ua) + TITLE:=rkp-ua + FILES:=$(PKG_BUILD_DIR)/rkp-ua.ko +# AUTOLOAD:=$(call AutoLoad, 99, rkp-ua) KCONFIG:= endef @@ -27,4 +28,4 @@ define Build/Compile $(MAKE) -C "$(LINUX_DIR)" $(MAKE_OPTS) modules endef -$(eval $(call KernelPackage,xmurp-ua)) \ No newline at end of file +$(eval $(call KernelPackage, rkp-ua)) \ No newline at end of file diff --git a/src/common.h b/src/common.h index 08fd026..f4d5cd5 100644 --- a/src/common.h +++ b/src/common.h @@ -14,69 +14,10 @@ #include #include -const unsigned char* str_ua = "User-Agent: "; -const unsigned char* str_end = "\r\n\r\n"; -const unsigned char* str_win = "Windows NT"; - -u_int8_t mode_advanced = 0; -module_param(mode_advanced, bool, 0); -u_int8_t mode_winPreserve = 0; -module_param(mode_winPreserve, bool, 0); - -u_int32_t mark_capture = 0x100; -module_param(mark_capture, uint, 0); -u_int32_t mark_request = 0x200; -module_param(mark_request, uint, 0); -u_int32_t mark_first = 0x400; -module_param(mark_first, uint, 0); -u_int32_t mark_winPreserve = 0x800; -module_param(mark_winPreserve, uint, 0); - -u_int8_t rkpSettings_capture(struct sk_buff*); -u_int8_t rkpSettings_request(struct sk_buff*); -u_int8_t rkpSettings_first(struct sk_buff*); -u_int8_t rkpSettings_winPreserve(struct sk_buff*); - -u_int8_t rkpSettings_capture(struct sk_buff* skb) -{ - if(mode_advanced) - return skb -> mark & mark_capture == mark_capture; - else - { - if(ip_hdr(skb) -> protocol != IPPROTO_TCP) - return 0; - else if(tcp_hdr(skb) -> dport == 80) - return 1; - else if(tcp_hdr(skb) -> sport == 80 && tcp_hdr(skb) -> ack) - return 1; - else - return 0; - } -} - -u_int8_t rkpSettings_request(struct sk_buff* skb) -{ - if(mode_advanced) - return skb -> mark & mark_request == mark_request; - else - return ip_hdr(skb) -> daddr == 80; -} - -u_int8_t rkpSettings_first(struct sk_buff* skb) -{ - if(mode_advanced) - return skb -> mark & mark_first == mark_first; - else - return tcp_hdr(skb) -> syn && !tcp_hdr(skb) -> ack; -} - -u_int8_t rkpSettings_winPreserve(struct sk_buff* skb) -{ - if(mode_advanced) - return skb -> mark & mark_winPreserve == mark_winPreserve; - else - return mode_winPreserve; -} +const unsigned char* str_ua_start = "User-Agent: "; +const unsigned char* str_ua_end = "\r\n"; +const unsigned char* str_head_end = "\r\n\r\n"; +const unsigned char* str_ua_rkp = "RKP/" VERSION; time_t now() { diff --git a/src/xmurp-ua.c b/src/rkp-ua.c similarity index 100% rename from src/xmurp-ua.c rename to src/rkp-ua.c diff --git a/src/rkpManager.h b/src/rkpManager.h index 34e3eb3..b09a4fd 100644 --- a/src/rkpManager.h +++ b/src/rkpManager.h @@ -8,8 +8,118 @@ struct rkpManager struct rkpManager* rkpManager_new(); // 构造函数 void rkpManager_del(struct rkpManager*); // 析构函数 -u_int8_t rkpManager_execute(struct rkpManager*, struct sk_buff*); // 处理一个数据包。返回值:0,出错,1,accept,2,stolen,3,drop +u_int8_t rkpManager_execute(struct rkpManager*, struct sk_buff*); // 处理一个数据包。返回值为 rkpStream_execute 的返回值。 void rkpManager_refresh(struct rkpManager*); // 清理过时的流 -struct rkpStream* __rkpManager_find(struct rkpManager*, struct sk_buff*); // 寻找一个数据包属于哪个流 -void __rkpManager_stream_add(struct rkpManager*, struct sk_buff*); // 增加一个流 +struct rkpManager* rkpManager_new() +{ + struct rkpManager* rkpm = kmalloc(sizeof(struct rkpManager) + sizeof(struct rkpStream*) * 256, GFP_KERNEL); + if(rkpm == 0) + { + printk("rkp-ua::rkpManager::rkpStream_new: `kmalloc` failed, may caused by shortage of memory.\n"); + return 0; + } + rkpm -> data = (void*)rkpm + sizeof(struct rkpManager); + memset(rkpm -> data, 0, sizeof(struct rkpStream*) * 256); + return rkpm; +} +void rkpManager_del(struct rkpManager* rkpm) +{ + unsigned i; + for(i = 0; i < 256; i++) + { + struct rkpStream *rkps = rkpm -> data[i]; + while(rkps != 0) + { + struct rkpStream *rkps2 = rkps -> next; + rkpStream_del(rkps); + rkps = rkps2; + } + } + kfree(rkpm); +} + +u_int8_t rkpManager_execute(struct rkpManager* rkpm, struct sk_buff* skb) +{ + + + if(rkpSettings_first(skb)) + // 新增加一个流或覆盖已经有的流 + { + u_int8_t id = (ntohs(tcp_hdr(skb) -> sport) + ntohs(tcp_hdr(skb) -> dport)) & 0xFF; + struct rkpStream* rkps_new = rkpStream_new(skb); + struct rkpStream *rkps = rkpm -> data[id]; + if(rkps_new == 0) + { + printk("rkp-ua::rkpStream::rkpStream_new: `kmalloc` failed, may caused by shortage of memory.\n"); + return NF_DROP; + } + + // 查找可能的重复的流并删除 + while(rkps != 0) + if(rkpStream_belong(rkps, skb)) + { + if(rkps -> prev != 0) + rkps -> prev -> next = rkps -> next; + if(rkps -> next != 0) + rkps -> next -> prev = rkps -> prev; + if(rkps == rkpm -> data[id]) + rkpm -> data[id] = rkps -> next; + rkpStream_del(rkps); + break; + } + else + rkps = rkps -> next; + + // 插入新的流 + if(rkpm -> data[id] == 0) + rkpm -> data[id] = rkps_new; + else + { + rkpm -> data[id] -> prev = rkps_new; + rkps_new -> next = rkpm -> data[id]; + rkpm -> data[id] = rkps_new; + } + } + else + // 使用已经有的流 + { + u_int8_t id = (ntohs(tcp_hdr(skb) -> sport) + ntohs(tcp_hdr(skb) -> dport)) & 0xFF; + struct rkpStream *rkps = rkpm -> data[id]; + while(rkps != 0) + if(rkpStream_belong(rkps, skb)) + return rkpStream_execute(rkps, skb); + else + rkps = rkps -> next; + if(rkps == 0) + { + printk("rkp-ua::rkpStream::rkpStream_execute: Target stream not found.\n"); + return NF_DROP; + } + } +} + +void rkpManager_refresh(struct rkpManager* rkpm) +{ + time_t n = now(); + unsigned i; + for(i = 0; i < 256; i++) + { + struct rkpStream* rkps = rkpm -> data[i]; + while(rkps != 0) + if(rkps -> last_active + time_keepalive < n) + { + struct rkpStream *rkps2 = rkps -> next; + if(rkps -> prev != 0) + rkps -> prev -> next = rkps -> next; + if(rkps -> next != 0) + rkps -> next -> prev = rkps -> prev; + if(rkps == rkpm -> data[i]) + rkpm -> data[i] = rkps -> next; + rkpStream_del(rkps); + rkps = rkps2; + } + else + rkps = rkps -> next; + } +} \ No newline at end of file diff --git a/src/rkpSettings.h b/src/rkpSettings.h new file mode 100644 index 0000000..6a43834 --- /dev/null +++ b/src/rkpSettings.h @@ -0,0 +1,63 @@ +#include "common.h" + +static u_int8_t mode_advanced = 0; +module_param(mode_advanced, bool, 0); + +static char* str_preserve[128]; +static unsigned n_str_preserve = 0; +module_param_array(str_preserve, charp, &n_str_preserve, 0); + +static u_int32_t mark_capture = 0x100; +module_param(mark_capture, uint, 0); +static u_int32_t mark_request = 0x200; +module_param(mark_request, uint, 0); +static u_int32_t mark_first = 0x400; +module_param(mark_first, uint, 0); +static u_int32_t mark_preserve = 0x800; +module_param(mark_preserve, uint, 0); + +static unsigned time_keepalive = 1200 +module_param(time_keepalive, uint, 0); + +u_int8_t rkpSettings_capture(struct sk_buff*); +u_int8_t rkpSettings_request(struct sk_buff*); +u_int8_t rkpSettings_first(struct sk_buff*); +u_int8_t rkpSettings_preserve(struct sk_buff*); + +u_int8_t rkpSettings_capture(struct sk_buff* skb) +{ + if(mode_advanced) + return skb -> mark & mark_capture == mark_capture; + else + { + if(ip_hdr(skb) -> protocol != IPPROTO_TCP) + return 0; + else if(tcp_hdr(skb) -> dport == 80) + return 1; + else if(tcp_hdr(skb) -> sport == 80 && tcp_hdr(skb) -> ack) + return 1; + else + return 0; + } +} +u_int8_t rkpSettings_request(struct sk_buff* skb) +{ + if(mode_advanced) + return skb -> mark & mark_request == mark_request; + else + return ip_hdr(skb) -> daddr == 80; +} +u_int8_t rkpSettings_first(struct sk_buff* skb) +{ + if(mode_advanced) + return skb -> mark & mark_first == mark_first; + else + return tcp_hdr(skb) -> syn && !tcp_hdr(skb) -> ack; +} +u_int8_t rkpSettings_preserve(struct sk_buff* skb) +{ + if(mode_advanced) + return skb -> mark & mark_preserve == mark_preserve; + else + return 1; +} \ No newline at end of file diff --git a/src/rkpStream.h b/src/rkpStream.h index 29409a2..444fdc7 100644 --- a/src/rkpStream.h +++ b/src/rkpStream.h @@ -1,38 +1,39 @@ -#include "common.h" +#include "rkpSettings.h" struct rkpStream { u_int8_t enum { - __rkpStream_sniffing, - __rkpStream_waiting + rkpStream_sniffing, + rkpStream_waiting } status; u_int32_t id[3]; // 按顺序存储客户地址、服务地址、客户端口、服务端口,已经转换字节序 struct sk_buff *buff, *buff_prev, *buff_next; - u_int32_t seq_ack; // 下一个服务端确认收到的字节的序列号。以后所有的序列号都是以这个为基准的相对序列号。 - u_int32_t seq; // 下一个期待收到的序列号。 + u_int32_t ack; // 下一个服务端确认收到的字节的序列号。以后所有的相对序列号都是将这个序号视为零的相对序列号。 + u_int32_t seq; // 下一个期待收到的序列号。 time_t last_active; u_int8_t scan_matched; - u_int8_t win_preserve; - struct rkpStream* next; + u_int8_t preserve; + struct rkpStream *prev, *next; }; struct rkpStream* rkpStream_new(struct sk_buff*); // 构造函数,得到的流的状态是捕获这个数据包之前的状态。内存不够时返回 0。 void rkpStream_del(struct rkpStream*); // 析构函数 u_int8_t rkpStream_belong(struct rkpStream*, struct sk_buff*); // 判断一个数据包是否属于一个流 -u_int8_t rkpStream_execute(struct rkpStream*, struct sk_buff*); // 处理一个数据包(假定包属于这个流) +unsigned rkpStream_execute(struct rkpStream*, struct sk_buff*); // 处理一个数据包(假定包属于这个流) void __rkpStream_refresh_ack(struct rkpStream*, u_int32_t); // 刷新确认序列号。第二个参数就是即将设定的确认号。会自动重新计算序列号的偏移,以及释放 buff_prev 中的多余数据包 -unsigned char* __rkpStream_skb_appStart(struct sk_buff*); // 返回一个包的应用层数据起始位置 +unsigned char* __rkpStream_skb_appStart(struct sk_buff*); // 返回一个包的应用层数据起始位置 u_int16_t __rkpStream_skb_appLen(struct sk_buff*); // 返回一个包的应用层数据长度 -int32_t __rkpStream_skb_seq(u_int32_t, u_int32_t); // 返回一个序列号的相对序列号。两个参数分别为流的确认号、包的序列号(已经转换字节序)。 +int32_t __rkpStream_skb_seq(u_int32_t, u_int32_t); // 返回一个序列号的相对序列号。两个参数分别为流的确认号、包的序列号(已经转换字节序)。可以为负。 void __rkpStream_skb_send(struct sk_buff*); // 发送一个数据包 struct sk_buff* __rkpStream_skb_copy(struct sk_buff*); // 复制一个数据包 void __rkpStream_skb_del(struct sk_buff*); // 删除一个数据包 u_int16_t __rkpStream_data_scan(unsigned char*, u_int16_t, unsigned char*, u_int8_t); // 在指定字符串中扫描子字符串。返回值最低位表示是否完整地找到,其余 15 位表示匹配的长度(如果没有完整地找到)或子串结束时相对于起始时的位置 +void __rkpStream_data_replace(unsigned char*, u_int16_t, unsigned char*, u_int16_t); // 替换字符串。参数与前者类似。 void __rkpStream_buff_retain_end(struct sk_buff**, struct sk_buff*); // 将一个数据包置入数据包链的末尾 void __rkpStream_buff_retain_auto(struct sk_buff**, struct sk_buff*); // 将一个数据包置入数据包链的合适位置 @@ -41,7 +42,7 @@ void __rkpStream_buff_del(struct sk_buff**); // struct sk_buff* __rkpStream_buff_find(struct sk_buff*, u_int32_t); // 在一个已经按照序列号排序的数据包链中寻找序列号相符的包。如果没有相符的包,就返回最后一个序列号比要求的小的包。如果没有这样的包,就返回 0。第二个参数是要查找的序列号(绝对值,已转换字节序) -void __rkpStream_buff_execute_core(struct sk_buff**, u_int16_t); // 最核心的步骤。集齐头部后,搜索、替换。 +void __rkpStream_buff_execute_core(struct sk_buff**, u_int16_t, u_int8_t); // 最核心的步骤,集齐头部后被调用。搜索、替换。参数分别为:数据包链表、最后一个包中 http 头结束的位置、是否保留指定 ua struct rkpStream* rpStream_new(struct sk_buff* skb) { @@ -50,25 +51,28 @@ struct rkpStream* rpStream_new(struct sk_buff* skb) struct tcphdr* tcph = tcp_hdr(skb); if(rkps == 0) - return rkps; - rkps -> status = rkpStream::__rkpStream_sniffing; + { + printk("rkp-ua::rkpStream::rkpStream_new: `kmalloc` failed, may caused by shortage of memory.\n"); + return 0; + } + rkps -> status = struct rkpStream::rkpStream_sniffing; rkps -> id[0] = ntohl(iph -> saddr); rkps -> id[1] = ntohl(iph -> daddr); rkps -> id[2] = (((u_int32_t)ntohs(tcph -> sport)) << 16 ) + ntohs(tcph -> dport); rkps -> buff = rkps -> buff_prev = rkps -> buff_next = 0; - rkps -> seq_ack = ntohl(tcph -> seq); + rkps -> ack = ntohl(tcph -> seq); rkps -> seq = 1; rkps -> last_active = now(); rkps -> scan_matched = 0; - rkps -> win_preserve = rkpSettings_winPreserve(skb); - rkps -> next = 0; + rkps -> win_preserve = rkpSettings_preserve(skb); + rkps -> prev = rkps -> next = 0; return rkps; } void rkpStream_del(struct rkpStream* rkps) { - __rkpStream_buff_del(&(rkps -> buff)); - __rkpStream_buff_del(&(rkps -> buff_prev)); - __rkpStream_buff_del(&(rkps -> buff_next)); + kfree_skb_list(rkps -> buff); + kfree_skb_list(rkps -> buff_prev); + kfree_skb_list(rkps -> buff_next); kfree(rkps); } u_int8_t rkpStream_belong(struct rkpStream* rkps, struct sk_buff* skb) @@ -94,7 +98,7 @@ u_int8_t rkpStream_belong(struct rkpStream* rkps, struct sk_buff* skb) return 1; } } -u_int8_t rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) +unsigned rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) // 不要害怕麻烦,咱们把每一种情况都慢慢写一遍。 { int32_t seq; @@ -105,9 +109,9 @@ u_int8_t rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) // 服务端返回确认包的情况,更新一下确认号,返回 sccept。以后的情况,都是客户端发往服务端的了。 if(!rkpSettings_request(skb)) { - int32_t seq = __rkpStream_skb_seq(rkps -> seq_ack, ntohl(tcp_hdr(skb) -> ack_seq)); + int32_t seq = __rkpStream_skb_seq(rkps -> ack, ntohl(tcp_hdr(skb) -> ack_seq)); if(seq > 0) - char __rkpStream_refresh_ack(rkps, ntohl(tcp_hdr(skb) -> ack_seq)); + __rkpStream_refresh_ack(rkps, ntohl(tcp_hdr(skb) -> ack_seq)); return NF_ACCEPT; } @@ -115,9 +119,8 @@ u_int8_t rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) if(__rkpStream_skb_appLen(skb) == 0) return NF_ACCEPT; - // 检查数据包是否是将来的数据包。如果是的话,需要放到 buff_next 等待处理。 - seq = __rkpStream_skb_seq(rkps -> seq_ack, ntohl(tcp_hdr(skb) -> seq)); + seq = __rkpStream_skb_seq(rkps -> ack, ntohl(tcp_hdr(skb) -> seq)); if(seq > rkps -> seq) { __rkpStream_buff_retain_auto(rkps -> buff_next, skb); @@ -140,7 +143,7 @@ u_int8_t rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) { if(skb_ensure_writable(skb, __rkpStream_skb_appStart(skb) - skb -> data + __rkpStream_skb_appLen(skb))) { - printk("rkp-ua::rkpStream::rkpStream_execute: Can not make skb writable, may caused by leasing memory. Drop it.\n"); + printk("rkp-ua::rkpStream::rkpStream_execute: Can not make skb writable, may caused by shortage of memory. Drop it.\n"); return NF_DROP; } memcpy(__rkpStream_skb_appStart(skb), __rkpStream_skb_appStart(skb_prev), __rkpStream_skb_appLen(skb_prev)); @@ -149,7 +152,7 @@ u_int8_t rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) } // 如果是在 sniffing 的情况下,那一定先扫描一下再说 - if(rkps -> status == __rkpStream_sniffing) + if(rkps -> status == struct rkpStream::rkpStream_sniffing) { u_int16_t scan = __rkpStream_data_scan(__rkpStream_skb_appStart(skb), __rkpStream_skb_appLen(skb), str_end, rkps -> scan_matched); @@ -159,12 +162,12 @@ u_int8_t rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) { struct sk_buff* skbp = rkps -> buff; - // 追加到 buff 后面 + // 追加到 buff 后面,更新 seq __rkpStream_buff_retain_end(&(rkps -> buff), skb); rkps -> seq = __rkpStream_skb_seq(rkps -> ack_seq, ntohl(tcp_hdr(skb) -> seq)) + __rkpStream_skb_appLen(skb); // 查找、替换 - __rkpStream_buff_execute_core(&(rkps -> buff), scan >> 1); + __rkpStream_buff_execute_core(&(rkps -> buff), (scan >> 1) + 1); // 循环复制一份到 buff_prev 下面,同时发出 while(skbp != 0) @@ -174,6 +177,7 @@ u_int8_t rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) __rkpStream_skb_send(skbp); skbp = skbp2; } + rkps -> buff = 0; // 清空查找情况,重新设置状态 rkps -> scan_length = 0; @@ -181,7 +185,7 @@ u_int8_t rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) rkps -> status = waiting; // 考虑之前截留的数据包 - __rkpStream_buff_rejudge(rkps, &(skps -> buff_prev)); + __rkpStream_buff_rejudge(rkps, &(rkps -> buff_prev)); return NF_STOLEN; } @@ -203,6 +207,7 @@ u_int8_t rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) __rkpStream_skb_send(skbp); skbp = skbp2; } + rkps -> buff = 0; // 清空查找情况 rkps -> scan_length = 0; @@ -216,7 +221,7 @@ u_int8_t rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) // 没有找到结尾,也没有push。那么,将这个数据包补到 buff 中,更新 seq 和 查找状态,再考虑 buff_next 中的包,最后返回 STOLEN { // 追加到 buff - __rkpStream_buff_retain_end(rkps -> buff, skb); + __rkpStream_buff_retain_end(&(rkps -> buff), skb); // 更新 seq 和查找状态 rkps -> seq = __rkpStream_skb_seq(rkps -> ack_seq, ntohl(tcp_hdr(skb) -> seq)) + __rkpStream_skb_appLen(skb); @@ -232,7 +237,7 @@ u_int8_t rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) // 如果是在 waiting 的状态下,那么设置 seq 和状态,然后考虑 buff_next 中的包,然后返回 ACCEPT 就可以了 { // 设置 seq 和状态 - rkps -> seq = __rkpStream_skb_seq(rkps -> ack_seq, ntohl(tcp_hdr(skb) -> seq)) + __rkpStream_skb_appLen(skb); + rkps -> seq = __rkpStream_skb_seq(rkps -> ack, ntohl(tcp_hdr(skb) -> seq)) + __rkpStream_skb_appLen(skb); if(tcp_hdr(skb) -> psh) rkps -> status = sniffing; @@ -247,15 +252,278 @@ void __rkpStream_refresh_ack(struct rkpStream* rkps, u_int32_t ack) { struct sk_buff* skbp; - // 重新计算 seq 偏移 - rkps -> seq -= ack - rkps -> seq_ack; + // 重新计算 ack 和 seq + rkps -> ack = ack; + rkps -> seq -= ack - rkps -> ack; // 丢弃 buff_prev 中已经确认收到的数据包 skbp = rkps -> buff_prev; - while(skbp != 0) + while(skbp != 0 && __rkpStream_skb_seq(skbp -> ack, ntohl(tcp_hdr(skbp) -> seq)) < 0) + { + struct sk_buff* skbp2 = skbp -> next; + __rkpStream_skb_del(skbp); + skbp = skbp2; + } + rkps -> buff_prev = skbp; +} + +unsigned char* __rkpStream_skb_appStart(struct sk_buff* skb) +{ + return (unsigned char*)tcp_hdr(skb) + tcp_hdr(skb) -> doff * 4; } u_int16_t __rkpStream_dataLen(strct sk_buff* skb) { return ntohs(ip_hdr(skb) -> tot_len) - ip_hdr(skb) -> ihl * 4 - tcp_hdr(skb) -> doff * 4; } + +int32_t __rkpStream_skb_seq(u_int32_t ack, u_int32_t seq) +{ + int32_t rtn; + u_int32_t rtn2 = seq - ack; + memcpy(&rtn, &rtn2, 4); + return rtn; +} + +void __rkpStream_skb_send(struct sk_buff* skb) +{ + dev_queue_xmit(skb); +} + +struct sk_buff* __rkpStream_skb_copy(struct sk_buff* skb) +{ + return skb_copy(skb, GFP_KERNEL); +} + +void __rkpStream_skb_del(struct sk_buff* skb) +{ + kfree_skb(skb); +} + +u_int16_t __rkpStream_data_scan(unsigned char* data, u_int16_t data_len, unsigned char* target, u_int8_t matched) +{ + unsigned char* p = data; + while(p - data != data_len) + { + if(*p == target[matched]) + matched++; + else + matched = 0; + if(matched == strlen(target)) + return ((u_int16_t)(p - data) << 1) | 0x1; + else + p++; + } + return matched << 1; +} +void __rkpStream_data_replace(unsigned char* data, u_int16_t data_len, unsigned char* target, u_int16_t modified) +{ + while(modified < strlen(target) && data_len > 0) + { + *data = target[modified]; + data++; + data_len--; + modified++; + } + if(data_len > 0) + memset(data, ' ', data_len); +} + +void __rkpStream_buff_retain_end(struct sk_buff** buff, struct sk_buff* skb) +{ + struct sk_buff* p = *buff; + if(p == 0) + { + *buff = skb; + skb -> next = 0; + skb -> prev = 0; + } + else while(p -> next != 0) + p = p -> next; + p -> next = skb; + skb -> next = 0; + skb -> prev = p; +} +void __rkpStream_buff_retain_auto(struct sk_buff** buff, struct sk_buff* skb) +{ + struct sk_buff* p = __rkpStream_buff_find(*buff, ntohl(tcp_hdr(skb) -> seq)); + if(p == 0) + { + skb -> prev = 0; + skb -> last = *buff; + *buff = skb; + } + else if(ntohl(tcp_hdr(p) -> seq) == ntohl(tcp_hdr(p) -> seq)) + { + if(p -> prev != 0) + p -> prev -> next = skb; + if(p -> next != 0) + p -> next -> prev = skb; + skb -> prev = p -> prev; + skb -> next = p -> next; + __rkpStream_skb_del(p); + } + else + { + if(p -> next != 0) + p -> next -> prev = skb; + skb -> next = p -> next; + p -> next = skb; + skb -> prev = p; + } +} +void __rkpStream_buff_rejudge(struct rkpStream* rkps, struct sk_buff** buff) +{ + u_int8_t found; + // 循环检查 buff,直到确认 buff 中没有可用的 skb + do + { + struct sk_buff* p = *buff; + found = 0; + while(p != 0 && !found) + { + // 找到了一个可用的 skb,将它应用,同时在节点中删除它 + if(__rkpStream_skb_seq(rkps -> ack, ntohl(tcp_hdr(p) -> seq)) == rkps -> seq) + { + found = 1; + + // 将它从链表中取出 + if(p -> prev != 0) + p -> prev -> next = p -> next; + if(p -> next != 0) + p -> next -> prev = p -> prev; + if(p == *buff) + *buff = p -> next; + + // 执行之 + unsigned rtn = rkpStream_execute(rkps, p); + if(rtn == NF_ACCEPT) + __rkpStream_skb_send(p); + else if(rtn == NF_DROP) + __rkpStream_skb_del(p); + else if(rtn == NF_STOLEN); + } + } + } while (found); +} +struct sk_buff* __rkpStream_buff_find(struct sk_buff* skb, u_int32_t seq) +{ + if(skb == 0) + return 0; + else + { + while(skb -> next != 0 && __rkpStream_skb_seq(seq, ntohl(tcp_hdr(skb -> next) -> seq)) <= 0) + skb = skb -> next; + return skb; + } +} + +void __rkpStream_buff_execute_core(struct sk_buff** buff, u_int16_t last_len, u_int8_t preserve) +// 扫描是否有 ua,然后扫描 ua 中是否有匹配的字符串,并且进行修改 +{ + u_int16_t rtn; + struct sk_buff* p; + unsigned i; + + struct sk_buff *skb_ua_begin, *skb_ua_end; + u_int16_t pos_ua_begin, pos_ua_end; + + // 寻找 ua 开始的位置 + for(p = *buff, rtn = 0; p != 0; p = p -> next) + { + if(p -> next == 0) + rtn = __rkpStream_data_scan(__rkpStream_skb_appStart(p), last_len, str_ua, rtn >> 1); + else + rtn = __rkpStream_data_scan(__rkpStream_skb_appStart(p), __rkpStream_skb_appLen(skb), str_ua_start, rtn >> 1); + if(rtn & 0x1) + break; + } + if(rtn & 0x1) + // 找到了 + { + skb_ua_start = p; + pos_ua_start = rtn >> 1; + } + else + // 没找到 + return; + + // 寻找 ua 结束的位置 + for(rtn = 0; p != 0; p = p -> next) + { + const char* scan_start; + u_int16_t scan_len; + + if(p == skb_ua_start) + scan_start = __rkpStream_skb_appStart(p) + pos_ua_start; + else + scan_start = __rkpStream_skb_appStart(p); + + if(p == skb_ua_start) + rtn = __rkpStream_data_scan(__rkpStream_skb_appStart(p) + pos_ua_start, __rkpStream_skb_appLen(p) - pos_ua_start, str_ua_end, rtn >> 1); + else + rtn = __rkpStream_data_scan(__rkpStream_skb_appStart(p), __rkpStream_skb_appLen(p), str_ua_end, rtn >> 1); + if(rtn & 0x1) + break; + } + // 肯定是可以找到结束位置的。 + // 如果找到的结束位置在靠近应用层数据开头的位置,那么真实的结束位置应该在上一个数据包 + if(rtn >> 1 < strlen(str_ua_end)) + { + skb_ua_end = p -> prev; + pos_ua_end = __rkpStream_skb_appLen(skb_ua_end) - (strlen(str_ua_end) - (rtn >> 1) - 1) - 1; + } + else + { + skb_ua_end = p; + pos_ua_end = (rtn >> 1) - strlen(str_ua_end); + } + + // 检查 ua 是否需要忽略,如果需要忽略就忽略 + if(preserve) + for(i = 0; i < n_str_preserve; i++) + { + for(p = skb_ua_begin, rtn = 0;;p = p -> next) + { + const char* scan_begin; + u_int16_t scan_len; + if(p == skb_ua_begin) + scan_begin = __rkpStream_skb_appStart(p) + pos_ua_begin; + else + scan_begin = __rkpStream_skb_appStart(p); + if(p == skb_ua_end) + scan_len = __rkpStream_skb_appStart(p) + pos_ua_end + 1 - scan_begin; + else + scan_len = __rkpStream_skb_appStart(p) + __rkpStream_skb_appLen(p) - scan_begin; + rtn = __rkpStream_data_scan(scan_begin, scan_len, str_preserve[i], rtn >> 1); + if(rtn & 0x1) + return; + if(p == skb_ua_end) + break; + } + } + + // 替换 ua + for(p = skb_ua_begin, rtn = 0;;p = p -> next) + { + const char* replace_begin; + u_int16_t replace_len; + if(skb_ensure_writable(p, replace_begin + replace_len - p -> data) != 0) + { + printk("rkp-ua::rkpStream::__rkpStream_buff_execute_core: Can not make skb writable, may caused by shortage of memory. Ignore it.\n"); + return; + } + if(p == skb_ua_begin) + replace_begin = __rkpStream_skb_appStart(p) + pos_ua_begin; + else + replace_begin = __rkpStream_skb_appStart(p); + if(p == skb_ua_end) + replace_len = __rkpStream_skb_appStart(p) + pos_ua_end + 1 - replace_begin; + else + replace_len = __rkpStream_skb_appStart(p) + __rkpStream_skb_appLen(p) - replace_begin; + __rkpStream_data_replace(replace_begin, replace_len, str_ua_rkp, rtn); + rtn += replace_len; + if(p == skb_ua_end) + break; + } +} \ No newline at end of file