在linux下用C實作netstat (Implement netstat)


在Linux 下,netstat 指令常被用來查詢網路各種資訊,像是在TCP、UDP、IP  ethernet 和 socket中的各種資訊。

至於netstat 則是去/proc中抓取各個所需要的資料。 

/proc是系統模擬出來、假的(虛擬)檔案系統(pseudo-filesystem),它是外界讀取核心資訊的對外窗口說是假的檔案系統是因為/proc中每個檔案在當user-process讀取/proc下的檔案時,才會即時(real-time)產生檔案中的「內容」。
 以下是Linux Programmer's Manual 中對於proc的描述

The proc filesystem is a pseudo-filesystem which provides an interface to kernel data structures.
from man proc

在/proc 這個目錄下,可以分為兩種類型的檔案:一種是只有數字編號的目錄,其代表每個執行中的Process 的ID (i.e. pid); 另一種非數字編號的則是與系統資訊相關的檔案。

在這個實作中我們需要使用到的是 /proc/net,該目錄下儲存著各種網路層的資訊。其中的/tpc與/udp分別儲存著tpc socket table與udp socket。


當我們對其中一個(udp)貓一下(cat指令)後,會出現如下的表格:


在這些欄位中,我們所需要的分別是local_addressrem_addressinode其中inode在這裡所代表的意義很重要,因為使用該addr:port的process link到該inode。講到這邊大概就已經講完所有原理了,最後只要找到link到所有inode的process就能完成了。

至於這個link要去哪裡找呢?這就要/proc目錄下所有的數字目錄中的/fd(file descriptors)目錄去慢慢找,即/proc/[pid]/fd/,找到所有symbolic linkinodepid
例如我現找到一pid=878的process符合此條件(絕對剛好是87的),於是在/proc/878/fd 下執行 ls -l 指令:

其中最右邊的就是symbolic linkformat type:[inode]

接下來我們觀察以上兩張圖,即會發現這個process 開啟的
inode,能在udp table中搜尋匹配到,即代表該ip被此process所使用。如下圖所示:

若再仔細一看,會發現其實該process其實有不止一個inode對到此udp table,因此在做文件搜索時可別因為匹配到一筆就忘了搜尋接下來的inode。

至於c要如何從ls中取得symbolic link呢?這時候只要使用readlink(2)即可取得啦。其描述如下:
    #include 
 
    ssize_t readlink(const char *path, char *buf, size_t bufsiz);  
雖然我們找到了pid,但是pid只是對於linux而言方便辨識,但對人卻無法知曉到底是哪一個process,所以我們要找到pid後,再去辨識process name,而這個name可由/proc/[pid]/comm之中取得

因此就能得到該process的name(此處為avahi-daemon)題外話,該process為多執行緒時,comm取得的名字可能會不同。

若還想取得額外的訊息,可以再從/proc/[pid]/目錄中再挖其他需要的資料出來這裡我們額外去取得/proc/[pid]/cmdline
在/cmdline檔案中,會顯示"該process在被呼叫時所下的完整command line",定義中若該process為zombie時,檔案為空,另外在指令之間是由 null bytes ('\0')所間隔。
  

 在該例子中的command line即為 running [grass-linux.local]

以上差不多把概念講述過,接下來就是大量的文件搜尋與字串處理了,我倒覺得整個程式中最麻煩的會是字串處理=~= 就是當個碼農一直農code大概會變成以下成果








 

留言

張貼留言

這個網誌中的熱門文章

(C) 簡單搞懂指標(pointer)、指標陣列(pointers of array, int *foo[]) 與指向陣列的指標 (pointer to array, int (*bar)[])

(c/c++) Function Pointer函式指標兩三事 (Function Pointer 的 typedef 與 Array of Function Pointer)

(C++) 別再用dynamic array與pointer了! 趕快學STL的vector與iterator!