libnids執行機制 函式呼叫流程
阿新 • • 發佈:2019-01-25
(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 }