无限循环的抓包函数的回调函数调用了gen_ip_proc()函数,该函数通过判断类型进入到对应的重组阶段。下面开始分析TCP重组部分。
函数名:process_tcp(data, skblen)
代码很长,如下:
void process_tcp(u_char * data, int skblen)//传入数据与其长度
{
struct ip *this_iphdr = (struct ip *)data;//ip与tcp结构体见后面说明
struct tcphdr *this_tcphdr = (struct tcphdr *)(data + 4 * this_iphdr->ip_hl);
//计算ip部分偏移指到TCP头部
int datalen, iplen;//数据部分长度,以及ip长度
int from_client = 1;
unsigned int tmp_ts;//时间戳
struct tcp_stream *a_tcp;//一个TCP流的全部信息
struct half_stream *snd, *rcv;
//一个方向上的TCP流,TCP分为两个方向上的,一个是客户到服务端,一个是服务端到客户
ugly_iphdr = this_iphdr;
iplen = ntohs(this_iphdr->ip_len);
if ((unsigned)iplen < 4 * this_iphdr->ip_hl + sizeof(struct tcphdr)) {
nids_params.syslog(NIDS_WARN_TCP, NIDS_WARN_TCP_HDR, this_iphdr,
this_tcphdr);//指示的长度与实际的不相符,指出错误
return;
} // ktos sie bawi
datalen = iplen - 4 * this_iphdr->ip_hl - 4 * this_tcphdr->th_off;
//tcp数据部分长度,去掉了TCP的头部
//ip_hl表示ip头部长度,th_off表示tcp头部长度,datalen表示tcp数据部分长度
if (datalen < 0) {
nids_params.syslog(NIDS_WARN_TCP, NIDS_WARN_TCP_HDR, this_iphdr,
this_tcphdr);
return;
} // ktos sie bawi,数据部分小于0,发生错误,返回
if ((this_iphdr->ip_src.s_addr | this_iphdr->ip_dst.s_addr) == 0) {
nids_params.syslog(NIDS_WARN_TCP, NIDS_WARN_TCP_HDR, this_iphdr,
this_tcphdr);
return;
}
if (!(this_tcphdr->th_flags & TH_ACK))//确认信息有效
detect_scan(this_iphdr);//如果是TCP中的ACK信息,检测是否出现攻击
if (!nids_params.n_tcp_streams) return;
if (my_tcp_check(this_tcphdr, iplen - 4 * this_iphdr->ip_hl,
this_iphdr->ip_src.s_addr, this_iphdr->ip_dst.s_addr)) {
nids_params.syslog(NIDS_WARN_TCP, NIDS_WARN_TCP_HDR, this_iphdr,
this_tcphdr);
return;
}//检测数据包的有效性
#if 0
check_flags(this_iphdr, this_tcphdr);
//ECN
#endif
//经过以上处,初步判断tcp包正常,进行入队操作,插入队列前,先进行此包的状态判断,判断此数据包处于何种状态
if (!(a_tcp = find_stream(this_tcphdr, this_iphdr, &from_client))) {
/*是三次握手的第一个包*/
/*tcp里流不存在时:且tcp数据包里的(syn=1 && ack==0 && rst==0)时,添加一条tcp流*/
/*tcp第一次握手*/
if