mirror of
https://github.com/CHN-beta/xmurp-ua.git
synced 2026-01-11 01:09:25 +08:00
This commit is contained in:
23
src/common.h
23
src/common.h
@@ -31,26 +31,3 @@ void rkpFree(void* p)
|
||||
{
|
||||
kfree(p);
|
||||
}
|
||||
|
||||
time_t now(void)
|
||||
{
|
||||
struct timespec* ts = rkpMalloc(sizeof(struct timespec));
|
||||
time_t rtn;
|
||||
getnstimeofday(ts);
|
||||
rtn = ts -> tv_sec;
|
||||
rkpFree(ts);
|
||||
#ifdef RKP_DEBUG
|
||||
printk("now %lu\n", ts -> tv_sec);
|
||||
#endif
|
||||
return rtn;
|
||||
}
|
||||
|
||||
#ifdef RKP_DEBUG
|
||||
void skb_print(struct sk_buff* skb)
|
||||
{
|
||||
printk("skb_print:\n");
|
||||
printk("\tport: %u %u\n", ntohs(tcp_hdr(skb) -> source), ntohs(tcp_hdr(skb) -> dest));
|
||||
printk("\tseq: %u %u\n", ntohl(tcp_hdr(skb) -> seq), ntohl(tcp_hdr(skb) -> ack_seq));
|
||||
printk("\tsyn %d ack %d psh %d\n", tcp_hdr(skb) -> syn, tcp_hdr(skb) -> ack, tcp_hdr(skb) -> psh);
|
||||
}
|
||||
#endif
|
||||
@@ -10,8 +10,6 @@ unsigned int hook_funcion(void *priv, struct sk_buff *skb, const struct nf_hook_
|
||||
|
||||
static unsigned n_skb_captured = 0, n_skb_captured_lastPrint = 1;
|
||||
|
||||
if(crashed)
|
||||
return NF_ACCEPT;
|
||||
if(!rkpSettings_capture(skb))
|
||||
return NF_ACCEPT;
|
||||
#ifdef RKP_DEBUG
|
||||
@@ -59,9 +57,7 @@ static int __init hook_init(void)
|
||||
printk("rkp-ua: str_preserve: %d\n", n_str_preserve);
|
||||
for(ret = 0; ret < n_str_preserve; ret++)
|
||||
printk("\t%s\n", str_preserve[ret]);
|
||||
#ifdef RKP_DEBUG
|
||||
printk("str_ua_rkp: %s\n", str_ua_rkp);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@ struct rkpManager* rkpManager_new(void);
|
||||
void rkpManager_delete(struct rkpManager*);
|
||||
|
||||
int rkpManager_execute(struct rkpManager*, struct sk_buff*); // 处理一个数据包。返回值为 rkpStream_execute 的返回值。
|
||||
int __rkpManager_execute(struct rkpManager*, struct sk_buff*);
|
||||
void __rkpManager_refresh(unsigned long); // 清理过时的流
|
||||
int __rkpManager_execute(struct rkpManager*, struct rkpPacket*);
|
||||
void __rkpManager_refresh(unsigned long); // 清理长时间不活动的流
|
||||
|
||||
void __rkpManager_lock(struct rkpManager*, unsigned long*);
|
||||
void __rkpManager_unlock(struct rkpManager*, unsigned long);
|
||||
@@ -24,13 +24,11 @@ struct rkpManager* rkpManager_new(void)
|
||||
if(rkpm == 0)
|
||||
return 0;
|
||||
memset(rkpm -> data, 0, sizeof(struct rkpStream*) * 256);
|
||||
// 初始化线程锁
|
||||
spin_lock_init(&rkpm -> lock);
|
||||
// 注册定时器
|
||||
init_timer(&rkpm -> timer);
|
||||
rkpm -> timer.function = __rkpManager_refresh;
|
||||
rkpm -> timer.data = (unsigned long)rkpm;
|
||||
rkpm -> timer.expires = jiffies + 600 * HZ;
|
||||
rkpm -> timer.expires = jiffies + time_keepalive * HZ;
|
||||
add_timer(&rkpm -> timer);
|
||||
return rkpm;
|
||||
}
|
||||
@@ -44,7 +42,7 @@ void rkpManager_delete(struct rkpManager* rkpm)
|
||||
struct rkpStream* rkps = rkpm -> data[i];
|
||||
while(rkps != 0)
|
||||
{
|
||||
struct rkpStream *rkps2 = rkps -> next;
|
||||
struct rkpStream* rkps2 = rkps -> next;
|
||||
rkpStream_delete(rkps);
|
||||
rkps = rkps2;
|
||||
}
|
||||
@@ -58,55 +56,57 @@ int rkpManager_execute(struct rkpManager* rkpm, struct sk_buff* skb)
|
||||
{
|
||||
unsigned long flag;
|
||||
int rtn;
|
||||
struct rkpPacket* rkpp = rkpPacket_new(skb);
|
||||
__rkpManager_lock(rkpm, &flag);
|
||||
rtn = __rkpManager_execute(rkpm, skb);
|
||||
rtn = __rkpManager_execute(rkpm, rkpp);
|
||||
__rkpManager_unlock(rkpm, flag);
|
||||
if(rtn == NF_ACCEPT || rtn == NF_DROP)
|
||||
rkpPacket_delete(rkpp);
|
||||
return rtn;
|
||||
}
|
||||
int __rkpManager_execute(struct rkpManager* rkpm, struct sk_buff* skb)
|
||||
int __rkpManager_execute(struct rkpManager* rkpm, struct rkpPacket* rkpp)
|
||||
{
|
||||
#ifdef RKP_DEBUG
|
||||
printk("rkp-ua: rkpManager_execute start.\n");
|
||||
printk("\tsyn %d ack %d\n", tcp_hdr(skb) -> syn, tcp_hdr(skb) -> ack);
|
||||
printk("\tsport %d dport %d\n", ntohs(tcp_hdr(skb) -> source), ntohs(tcp_hdr(skb) -> dest));
|
||||
printk("\tid %d\n", (ntohs(tcp_hdr(skb) -> source) + ntohs(tcp_hdr(skb) -> dest)) & 0xFF);
|
||||
printk("\tsyn %d\n", rkpPacket_syn(rkpp));
|
||||
printk("\tsport %d dport %d\n", rkpPacket_sport(rkpp), rkpPacket_dport(rkpp));
|
||||
printk("\tid %d\n", rkpp -> sid);
|
||||
#endif
|
||||
|
||||
// 不使用标志位(三次握手)来判断是否该新建一个流,而直接搜索是否有符合条件的流,有就使用,没有就新建
|
||||
u_int8_t id = (ntohs(tcp_hdr(skb) -> source) + ntohs(tcp_hdr(skb) -> dest)) & 0xFF;
|
||||
struct rkpStream *rkps, *rkps_new;
|
||||
|
||||
for(rkps = rkpm -> data[id]; rkps != 0; rkps = rkps -> next)
|
||||
if(rkpStream_belongTo(rkps, skb))
|
||||
// 搜索是否有符合条件的流
|
||||
for(rkps = rkpm -> data[rkpp -> sid]; rkps != 0; rkps = rkps -> next)
|
||||
if(rkpStream_belongTo(rkps, rkpp)) // 找到了,执行即可
|
||||
{
|
||||
#ifdef RKP_DEBUG
|
||||
printk("__rkpManager_execute: found target stream.\n");
|
||||
#endif
|
||||
return rkpStream_execute(rkps, skb);
|
||||
return rkpStream_execute(rkps, rkpp);
|
||||
}
|
||||
|
||||
// 如果运行到这里的话,那就是没有找到了
|
||||
// 如果运行到这里的话,那就是没有找到了,新建一个流再执行
|
||||
#ifdef RKP_DEBUG
|
||||
printk("__rkpManager_execute: target stream not found, create a new one. \n");
|
||||
#endif
|
||||
rkps_new = rkpStream_new(skb);
|
||||
rkps_new = rkpStream_new(rkpp);
|
||||
if(rkps_new == 0)
|
||||
return NF_ACCEPT;
|
||||
if(rkpm -> data[id] == 0)
|
||||
if(rkpm -> data[rkpp -> sid] == 0)
|
||||
{
|
||||
rkpm -> data[id] = rkps_new;
|
||||
#ifdef RKP_DEBUG
|
||||
printk("rkpManager_execute: add a new stream %d to an empty list.\n", id);
|
||||
#endif
|
||||
rkpm -> data[rkpp -> sid] = rkps_new;
|
||||
}
|
||||
else
|
||||
{
|
||||
rkpm -> data[id] -> prev = rkps_new;
|
||||
rkps_new -> next = rkpm -> data[id];
|
||||
rkpm -> data[id] = rkps_new;
|
||||
#ifdef RKP_DEBUG
|
||||
printk("rkpManager_execute: add a new stream %d to an unempty list.\n", id);
|
||||
#endif
|
||||
rkpm -> data[rkpp -> sid] -> prev = rkps_new;
|
||||
rkps_new -> next = rkpm -> data[rkpp -> sid];
|
||||
rkpm -> data[rkpp -> sid] = rkps_new;
|
||||
}
|
||||
return rkpStream_execute(rkps_new, skb);
|
||||
}
|
||||
@@ -115,7 +115,7 @@ void __rkpManager_refresh(unsigned long param)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned long flag;
|
||||
struct rkpManager* rkpm = (struct rkpManager*)param;
|
||||
struct rkpManager*& rkpm = (struct rkpManager*)param;
|
||||
#ifdef RKP_DEBUG
|
||||
printk("__rkpManager_refresh start.\n");
|
||||
#endif
|
||||
@@ -142,6 +142,8 @@ void __rkpManager_refresh(unsigned long param)
|
||||
rkps = rkps -> next;
|
||||
}
|
||||
}
|
||||
rkpm -> timer.expires = jiffies + time_keepalive * HZ;
|
||||
add_timer(&rkpm -> timer);
|
||||
__rkpManager_unlock(rkpm, flag);
|
||||
#ifdef RKP_DEBUG
|
||||
printk("__rkpManager_refresh end.\n");
|
||||
|
||||
@@ -6,6 +6,8 @@ struct rkpPacket
|
||||
{
|
||||
struct rkpPacket *prev, *next;
|
||||
struct sk_buff* skb;
|
||||
u_int8_t sid;
|
||||
u_int32_t lid[3];
|
||||
};
|
||||
|
||||
struct rkpPacket* rkpPacket_new(struct sk_buff*);
|
||||
@@ -18,64 +20,46 @@ unsigned char* rkpPacket_appEnd(struct rkpPacket*);
|
||||
unsigned rkpPacket_appLen(struct rkpPacket*);
|
||||
int32_t rkpPacket_seq(struct rkpPacket*);
|
||||
int32_t rkpPacket_ack(struct rkpPacket*);
|
||||
u_int32_t rkpPacket_sip(struct rkpPacket*);
|
||||
u_int32_t rkpPacket_dip(struct rkpPacket*);
|
||||
u_int32_t rkpPacket_sport(struct rkpPacket*);
|
||||
u_int32_t rkpPacket_dport(struct rkpPacket*);
|
||||
bool rkpPacket_psh(struct rkpPacket*);
|
||||
bool rkpPacket_syn(struct rkpPacket*);
|
||||
|
||||
void rkpPacket_csum(struct rkpPacket*);
|
||||
bool rkpPacket_makeWriteable(struct rkpPacket*);
|
||||
|
||||
struct rkpPacket* rkpPacket_new(struct sk_buff* skb)
|
||||
{
|
||||
#ifdef RKP_DEBUG
|
||||
printk("rkp-ua: rkpPacket_new start.\n");
|
||||
#endif
|
||||
struct rkpPacket* p = rkpMalloc(sizeof(struct rkpPacket));
|
||||
if(p != 0)
|
||||
{
|
||||
p -> prev = p -> next = 0;
|
||||
p -> skb = skb;
|
||||
}
|
||||
else
|
||||
printk("rkp-ua: rkpPacket_new: malloc failed.\n");
|
||||
#ifdef RKP_DEBUG
|
||||
printk("rkp-ua: rkpPacket_new end.\n");
|
||||
#endif
|
||||
struct rkpPacket* rkpp = rkpMalloc(sizeof(struct rkpPacket));
|
||||
if(rkpp == 0)
|
||||
return 0;
|
||||
rkpp -> prev = rkpp -> next = 0;
|
||||
rkpp -> skb = skb;
|
||||
rkpp -> sid = (rkpPacket_sport(rkpp) + rkpPacket_dport(rkpp)) & 0xFF;
|
||||
rkpp -> lid[0] = rkpPacket_sip(rkpp);
|
||||
rkpp -> lid[1] = rkpPacket_dip(rkpp);
|
||||
rkpp -> lid[2] = (rkpPacket_sport(rkpp) << 16) + rkpPacket_dport(rkpp);
|
||||
return p;
|
||||
}
|
||||
void rkpPacket_send(struct rkpPacket* p)
|
||||
{
|
||||
#ifdef RKP_DEBUG
|
||||
printk("rkp-ua: rkpPacket_send start.\n");
|
||||
#endif
|
||||
if(dev_queue_xmit(p -> skb))
|
||||
{
|
||||
printk("rkp-ua: rkpPacket_new: Send failed. Drop it.\n");
|
||||
kfree_skb(p -> skb);
|
||||
}
|
||||
rkpFree(p);
|
||||
#ifdef RKP_DEBUG
|
||||
printk("rkp-ua: rkpPacket_send end.\n");
|
||||
#endif
|
||||
}
|
||||
void rkpPacket_delete(struct rkpPacket* p)
|
||||
{
|
||||
#ifdef RKP_DEBUG
|
||||
printk("rkp-ua: rkpPacket_delete start.\n");
|
||||
#endif
|
||||
rkpFree(p);
|
||||
#ifdef RKP_DEBUG
|
||||
printk("rkp-ua: rkpPacket_delete end.\n");
|
||||
#endif
|
||||
}
|
||||
void rkpPacket_drop(struct rkpPacket* p)
|
||||
{
|
||||
#ifdef RKP_DEBUG
|
||||
printk("rkp-ua: rkpPacket_drop start.\n");
|
||||
#endif
|
||||
kfree_skb(p -> skb);
|
||||
rkpFree(p);
|
||||
#ifdef RKP_DEBUG
|
||||
printk("rkp-ua: rkpPacket_drop end.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned char* rkpPacket_appBegin(struct rkpPacket* p)
|
||||
@@ -98,16 +82,33 @@ int32_t rkpPacket_ack(struct rkpPacket* p)
|
||||
{
|
||||
return ntohl(tcp_hdr(p -> skb) -> ack);
|
||||
}
|
||||
u_int32_t rkpPacket_sip(struct rkpPacket* rkpp)
|
||||
{
|
||||
return ntohl(ip_hdr(rkpp -> skb) -> saddr);
|
||||
}
|
||||
u_int32_t rkpPacket_dip(struct rkpPacket* rkpp)
|
||||
{
|
||||
return ntohl(ip_hdr(rkpp -> skb) -> daddr);
|
||||
}
|
||||
u_int16_t rkpPacket_sport(struct rkpPacket* rkpp)
|
||||
{
|
||||
return ntohs(tcp_hdr(rkpp -> skb) -> source);
|
||||
}
|
||||
u_int32_t rkpPacket_dport(struct rkpPacket* rkpp)
|
||||
{
|
||||
return ntohs(tcp_hdr(rkpp -> skb) -> dest);
|
||||
}
|
||||
bool rkpPacket_psh(struct rkpPacket* rkpp)
|
||||
{
|
||||
return tcp_hdr(rkpp -> skb) -> psh;
|
||||
}
|
||||
bool rkpPacket_syn(struct rkpPacket* rkpp)
|
||||
{
|
||||
return tcp_hdr(rkpp -> skb) -> syn;
|
||||
}
|
||||
|
||||
void rkpPacket_csum(struct rkpPacket* p)
|
||||
{
|
||||
#ifdef RKP_DEBUG
|
||||
printk("rkp-ua: rkpPacket_csum start.\n");
|
||||
#endif
|
||||
struct iphdr* iph = ip_hdr(p -> skb);
|
||||
struct tcphdr* tcph = tcp_hdr(p -> skb);
|
||||
tcph -> check = 0;
|
||||
@@ -115,9 +116,6 @@ void rkpPacket_csum(struct rkpPacket* p)
|
||||
iph -> check = ip_fast_csum((unsigned char*)iph, iph -> ihl);
|
||||
p -> skb -> csum = skb_checksum(p -> skb, iph -> ihl * 4, ntohs(iph -> tot_len) - iph -> ihl * 4, 0);
|
||||
tcph -> check = csum_tcpudp_magic(iph -> saddr, iph -> daddr, ntohs(iph -> tot_len) - iph -> ihl * 4, IPPROTO_TCP, p -> skb -> csum);
|
||||
#ifdef RKP_DEBUG
|
||||
printk("rkp-ua: rkpPacket_csum end.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool rkpPacket_makeWriteable(struct rkpPacket* rkpp)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
|
||||
_Static_assert(sizeof(int) == 4, "int is not 4 bit.");
|
||||
_Static_assert(sizeof(unsigned long) >= sizeof(void*), "ulong is too short.");
|
||||
|
||||
static bool autocapture = true;
|
||||
module_param(autocapture, bool, 0);
|
||||
|
||||
@@ -8,31 +11,18 @@ static char* str_preserve[128];
|
||||
static unsigned n_str_preserve = 0;
|
||||
module_param_array(str_preserve, charp, &n_str_preserve, 0);
|
||||
|
||||
_Static_assert(sizeof(int) == 4, "int is not 4 bit.");
|
||||
static unsigned mark_capture = 0x100;
|
||||
module_param(mark_capture, uint, 0);
|
||||
static unsigned mark_first = 0x200;
|
||||
module_param(mark_first, uint, 0);
|
||||
|
||||
static unsigned time_keepalive = 1200;
|
||||
module_param(time_keepalive, uint, 0);
|
||||
|
||||
bool rkpSettings_capture(const struct sk_buff*);
|
||||
bool rkpSettings_first(const struct sk_buff*);
|
||||
|
||||
bool rkpSettings_capture(const struct sk_buff* skb)
|
||||
{
|
||||
|
||||
#ifdef RKP_DEBUG
|
||||
// if(ntohl(ip_hdr(skb) -> daddr) != (216 << 24) + (24 << 16) + (178 << 8) + 192 && ntohl(ip_hdr(skb) -> saddr) != (216 << 24) + (24 << 16) + (178 << 8) + 192)
|
||||
// return false;
|
||||
#endif
|
||||
|
||||
if(!autocapture)
|
||||
{
|
||||
#ifdef RKP_DEBUG
|
||||
printk("\tadvanced return %d", (skb -> mark & mark_capture) == mark_capture);
|
||||
#endif
|
||||
return (skb -> mark & mark_capture) == mark_capture;
|
||||
}
|
||||
else
|
||||
@@ -47,11 +37,4 @@ bool rkpSettings_capture(const struct sk_buff* skb)
|
||||
else
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bool rkpSettings_first(const struct sk_buff* skb)
|
||||
{
|
||||
if(!autocapture)
|
||||
return (skb -> mark & mark_first) == mark_first;
|
||||
else
|
||||
return tcp_hdr(skb) -> syn && !tcp_hdr(skb) -> ack;
|
||||
}
|
||||
@@ -7,18 +7,20 @@ struct rkpStream
|
||||
{
|
||||
enum
|
||||
{
|
||||
__rkpStream_sniffing,
|
||||
__rkpStream_waiting
|
||||
__rkpStream_sniffing_end, // 正在寻找 http 头的结尾或者 ua 的开始,这时 buff_scan 中不应该有包
|
||||
__rkpStream_sniffing_ua, // 已经找到 ua,正在寻找它的结尾,buff_scan 中可能有包
|
||||
__rkpStream_waiting // 已经找到 ua 的结尾或者 http 头的结尾并且还没有 psh,接下来的包都直接放行
|
||||
} status;
|
||||
u_int32_t id[3]; // 按顺序存储客户地址、服务地址、客户端口、服务端口,已经转换字节序
|
||||
struct rkpPacket *buff_scan, *buff_disordered; // 分别存储准备扫描的、因乱序而提前收到的数据包,都按照字节序排好了
|
||||
struct rkpPacket *buff_scan, *buff_disordered; // 分别存储准备扫描的、因乱序而提前收到的数据包,都按照序号排好了
|
||||
u_int32_t seq_offset; // 序列号的偏移。使得 buff_scan 中第一个字节的编号为零。
|
||||
bool active; // 是否仍然活动,超过一定时间不活动的流会被销毁
|
||||
unsigned scan_matched; // 记录现在已经匹配了多少个字节
|
||||
unsigned scan_httpEnd_matched, scan_uaBegin_matched, scan_uaEnd_matched; // 记录现在已经匹配了多少个字节
|
||||
unsigned char *scan_uaBegin_p, *scan_uaEnd_p; // 在扫描到相关信息后,将信息填写到这里
|
||||
struct rkpStream *prev, *next;
|
||||
};
|
||||
|
||||
struct rkpStream* rkpStream_new(const struct sk_buff*); // 由三次握手的第一个包构造一个 rkpSteam
|
||||
struct rkpStream* rkpStream_new(const struct sk_buff*); // 构造一个 rkpSteam
|
||||
void rkpStream_delete(struct rkpStream*);
|
||||
|
||||
bool rkpStream_belongTo(const struct rkpStream*, const struct sk_buff*); // 判断一个数据包是否属于一个流
|
||||
@@ -28,10 +30,9 @@ int32_t __rkpStream_seq_scanEnd(struct rkpStream*); // 返回 buff_scan
|
||||
|
||||
void __rkpStream_insert_auto(struct rkpStream*, struct rkpPacket**, struct rkpPacket*); // 在指定链表中插入一个节点
|
||||
void __rkpStream_insert_end(struct rkpStream*, struct rkpPacket**, struct rkpPacket*);
|
||||
struct rkpPacket* __rkpStream_pop_end(struct rkpStream*, struct rkpPacket**);
|
||||
|
||||
bool __rkpStream_scan(struct rkpStream*, struct rkpPacket*); // 在包的应用层搜索 ua 头的结尾
|
||||
void __rkpStream_modify(struct rkpStream*); // 在已经收集到完整的 HTTP 头后,调用去按规则修改 buff_scan 中的包
|
||||
bool __rkpStream_scan(struct rkpStream*, struct rkpPacket*); // 对一个最新的包进行扫描
|
||||
void __rkpStream_modify(struct rkpStream*); // 在收集到完整的 ua 后,对 ua 进行修改
|
||||
|
||||
struct rkpStream* rkpStream_new(const struct sk_buff* skb)
|
||||
{
|
||||
@@ -39,19 +40,15 @@ struct rkpStream* rkpStream_new(const struct sk_buff* skb)
|
||||
printk("rkp-ua: rkpStream_new start.\n");
|
||||
#endif
|
||||
struct rkpStream* rkps = rkpMalloc(sizeof(struct rkpStream));
|
||||
const struct iphdr* iph = ip_hdr(skb);
|
||||
const struct tcphdr* tcph = tcp_hdr(skb);
|
||||
struct rkpPacket* rkpp = rkpPacket_new(skb);
|
||||
if(rkps == 0)
|
||||
{
|
||||
printk("rkp-ua: rkpStream_new: malloc failed, may caused by shortage of memory.\n");
|
||||
return 0;
|
||||
}
|
||||
rkps -> status = __rkpStream_sniffing;
|
||||
rkps -> status = __rkpStream_sniffing_end;
|
||||
rkps -> id[0] = ntohl(iph -> saddr);
|
||||
rkps -> id[1] = ntohl(iph -> daddr);
|
||||
rkps -> id[2] = (((u_int32_t)ntohs(tcph -> source)) << 16) + ntohs(tcph -> dest);
|
||||
rkps -> buff_scan = rkps -> buff_disordered = 0;
|
||||
rkps -> seq_offset = ntohl(tcp_hdr(skb) -> seq) + 1;
|
||||
rkps -> seq_offset = ntohl(tcp_hdr(skb) -> seq);
|
||||
rkps -> active = true;
|
||||
rkps -> scan_matched = 0;
|
||||
rkps -> prev = rkps -> next = 0;
|
||||
@@ -398,31 +395,6 @@ void __rkpStream_insert_end(struct rkpStream* rkps, struct rkpPacket** buff, str
|
||||
printk("rkp-ua: __rkpStream_insert_end end.\n");
|
||||
#endif
|
||||
}
|
||||
struct rkpPacket* __rkpStream_pop_end(struct rkpStream* rkps, struct rkpPacket** buff)
|
||||
{
|
||||
#ifdef RKP_DEBUG
|
||||
printk("rkp-ua: __rkpStream_pop_end start.\n");
|
||||
#endif
|
||||
if(*buff == 0)
|
||||
{
|
||||
printk("__rkpStream_pop_end: pop from an empty list.\n");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct rkpPacket* rkpp;
|
||||
for(rkpp = *buff; rkpp -> next != 0; rkpp = rkpp -> next);
|
||||
if(rkpp -> prev == 0)
|
||||
*buff = 0;
|
||||
else
|
||||
rkpp -> prev = rkpp -> prev -> next = 0;
|
||||
return rkpp;
|
||||
}
|
||||
#ifdef RKP_DEBUG
|
||||
printk("rkp-ua: __rkpStream_insert_end end.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool __rkpStream_scan(struct rkpStream* rkps, struct rkpPacket* rkpp)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user