libnids运行机制 函数调用流程

(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 }

终于看到了我们熟悉的switch case语句序列了,这个时候就可以开始我们的process_tcp 和process_udp还有process_icmp之旅了。

posted @ 2011-08-29 16:39  戴安澜式编程  阅读(2728)  评论(0编辑  收藏  举报