libnids函数调用流程:http://sourcecodebrowser.com/libnids/1.23/tcp_8c.html
http://www.cnblogs.com/renhao/archive/2011/08/29/2158334.html
(1)系统调用 int nids_init() 初始化程序
(2)int nids_init() 调用函数 init_procs();
以下是该函数的实现代码:
1 staticvoid init_procs() 2 { 3 ip_frag_procs = mknew(struct proc_node); 4 ip_frag_procs->item = gen_ip_frag_proc; 5 ip_frag_procs->next =0; 6 ip_procs = mknew(struct proc_node); 7 ip_procs->item = gen_ip_proc; 8 ip_procs->next =0; 9 tcp_procs =0; 10 udp_procs =0; 11 }
程第四行指定了ip_frag_procs的处理函数(这是仅仅是指定,没有实际的处理)。
(3)调用函数int nids_run()。
函数nids_run的实现代码如下:
1 int nids_run() 2 { 3 if (!desc) { 4 strcpy(nids_errbuf, "Libnids not initialized"); 5 return0; 6 } 7 START_CAP_QUEUE_PROCESS_THREAD(); /* threading... */ 8 pcap_loop(desc, -1, (pcap_handler) nids_pcap_handler, 0); 9 /* FIXME: will this code ever be called? Don't think so - mcree */ 10 STOP_CAP_QUEUE_PROCESS_THREAD(); 11 nids_exit(); 12 return0; 13 }
(4)程序第7行调用START_CAP_QUEUE_PROCESS_THREAD开启了一个新的线程,该线程正是我们的组包处理程序。该宏定义展开如下:
1 #define START_CAP_QUEUE_PROCESS_THREAD() \ 2 if(nids_params.multiproc) { /* threading... */ \ 3 if(!(g_thread_create_full((GThreadFunc)cap_queue_process_thread,NULL,0,FALSE,TRUE,G_THREAD_PRIORITY_LOW,&gerror))) { \ 4 strcpy(nids_errbuf, "thread: "); \ 5 strncat(nids_errbuf, gerror->message, sizeof(nids_errbuf) -8); \ 6 return0; \ 7 }; \ 8 }
可以看到创建的新线程为cap_queue_process_thread,其函数实现代码如下:
1 staticvoid cap_queue_process_thread() 2 { 3 struct cap_queue_item *qitem; 4 5 while(1) { /* loop "forever" */ 6 qitem=g_async_queue_pop(cap_queue); 7 if (qitem==&EOF_item) break; /* EOF item received: we should exit */ 8 call_ip_frag_procs(qitem->data,qitem->caplen); 9 free(qitem->data); 10 free(qitem); 11 } 12 g_thread_exit(NULL); 13 }
函数第8行调用call_ip_frag_procs,其实现代码如下:
1 staticvoid call_ip_frag_procs(void*data,bpf_u_int32 caplen) 2 { 3 struct proc_node *i; 4 for (i = ip_frag_procs; i; i = i->next) 5 (i->item) (data, caplen); 6 }
函数第4行调用了我们的ip_frag_procs,这样我们又看到步骤(2)中的这个处理函数链表链表。回过头来看看这个默认的处理函数的结构:
1 staticvoid gen_p_frag_proc(u_char * data, int len) 2 { 3 ...... 4 for (i = ip_procs; i; i = i->next) 5 (i->item) (iph, skblen); 6 ...... 7 }
程序4行调用了ip_procs在步骤(2)中的默认值为gen_ip_proc ,这个函数就是我们最终的处理函数了,在这里我们终于看到了我们的TCP ,UDP,ICMP的处理,代码如下:
1 staticvoid gen_ip_proc(u_char * data, int skblen) 2 { 3 switch (((struct ip *) data)->ip_p) { 4 case IPPROTO_TCP: 5 process_tcp(data, skblen); 6 break; 7 case IPPROTO_UDP: 8 process_udp((char*)data); 9 break; 10 case IPPROTO_ICMP: 11 if (nids_params.n_tcp_streams) 12 process_icmp(data); 13 break; 14 default: 15 break; 16 } 17 }