1. 程式人生 > >libnids執行機制 函式呼叫流程

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 }