1. 程式人生 > >libpcap庫函式介紹(附原始碼)

libpcap庫函式介紹(附原始碼)

libpcap的資料型別定義:

struct pcap_addr:網絡卡地址描述
{
    pcap_addr * next;
    sockaddr * addr;
    sockaddr * netmask;
    sockaddr *broadaddr;
    sockaddr *dstaddr;
};
pcap_addr * next;
    如果非空,指向連結串列中一個元素的指標;空表示連結串列中的最後一個元素。
sockaddr * addr;
    指向包含一個地址的sockaddr的結構的指標。
sockaddr * netmask;
    如果非空,指向包含相對於addr指向的地址的一個網路掩碼的結構。
sockaddr * broadaddr;
    如果非空,指向包含相對於addr指向的地址的一個廣播地址,如果網路不支援廣播可能為空。
sockaddr * dstaddr;
    如果非空,指向一個相對於addr指向的源地址的目的地址,如果網路不支援點對點通訊,則為空。

struct pcap_file_header {
    bpf_u_int32 magic;
    u_short version_major;
    u_short version_minor;
    bpf_int32 thiszone;    /* gmt to local correction */
    bpf_u_int32 sigfigs;    /* accuracy of timestamps */
    bpf_u_int32 snaplen;    /* max length saved portion of each pkt */
    bpf_u_int32 linktype;    /* data link type (LINKTYPE_*) */
};

bpf_u_int32 magic;
    ????????????????????????????????
u_short version_major;
    Libpcap的主版本號。
u_shart version_minor;
    Libpcap的從版本號。
bpf_u_int32 sigfigs;
    時間戳描述。
bpf_u_int32 snaplen;
    儲存的每個pkt的分片號的最大值。
bpf_u_int32 linktype;
    資料鏈的型別。
細節說明:
    libpcap dump檔案頭;
    libpcap dump檔案中的第一個記錄包含了一些標誌的儲存值,這些標誌在列印階段用到。這兒的很多域都是32位的int,所以compilers不用進行轉化;這些檔案需要具有跨層次的可交換性。
    無論如何不要改變結構的層次(包括僅僅改變這個結構中域的長度);


struct pcap_if {          /*網絡卡資料鏈的一個元素*/
    struct pcap_if *next;
    char *name;        /* name to hand to "pcap_open_live()" */
    char *description;    /* textual description of interface, or NULL */
    struct pcap_addr *addresses;
    u_int flags;        /* PCAP_IF_ interface flags */
};

pcap_if *next;
    如果非空,指向鏈的下一個元素。如果為空是鏈的最後一個元素。
char * name;
    指向一個字串,該字串是傳給pcap_open_live()函式的裝置名;
char * description;
    如果非空,指向一個對裝置的人性化的描述字串。
pcap_addr *addresses;
    指向網絡卡地址鏈中的第一個元素。
u_int flags;
    PCAP_IF_ 網絡卡的標誌。現在唯一可用的標識是PCAP_IF_LOOKBACK,它被用來標識網絡卡是不是lookback網絡卡。

struct pcap_pkthdr {         /*dump 檔案中的資料包頭*/
    struct timeval ts;    /* time stamp */
    bpf_u_int32 caplen;    /* length of portion present */
    bpf_u_int32 len;    /* length this packet (off wire) */
};
timeval ts;
    資料報時間戳;
bpf_u_int32 caplen;
    當前分片的長度;
dpf_u_int32 len;
    這個資料報的長度;
細節描述:
    在dump檔案中的每個資料報都有這樣一個報頭。它用來處理不同資料報網絡卡的不同報頭問題。

struct pcap_stat {        /*用來儲存網絡卡靜態變數的結構*/
    u_int ps_recv;        /* number of packets received */
    u_int ps_drop;        /* number of packets dropped */
    u_int ps_ifdrop;    /* drops by interface XXX not yet supported */
};
u_int ps_recv;
    接受資料報的數目;
u_int ps_drop;
    被驅動程式丟棄的資料報的數目;
u_int ps_ifdrop;
    被網絡卡丟棄的資料報的數目;


struct pcap_sf {    //pacap的savefile結構 定義
        FILE *rfile;    //該指標指向savefile檔案
        int swapped;    //?
        int hdrsize;    //頭大小嗎?
        int version_major;//主版本號
        int version_minor;//從版本號
        u_char *base;//?
};
struct pcap_md { //?
        struct pcap_stat stat;
        /*XXX*/
        int use_bpf;            /* using kernel filter */
        u_long  TotPkts;        /* can't oflow for 79 hrs on ether */
        u_long  TotAccepted;    /* count accepted by filter */
        u_long  TotDrops;       /* count of dropped packets */
        long    TotMissed;      /* missed by i/f during this run */
        long    OrigMissed;     /* missed by i/f before this run */
#ifdef linux
        int     sock_packet;    /* using Linux 2.0 compatible interface */
        int     timeout;        /* timeout specified to pcap_open_live */
        int     clear_promisc;  /* must clear promiscuous mode when we close */
        int     cooked;         /* using SOCK_DGRAM rather than SOCK_RAW */
        int     lo_ifindex;     /* interface index of the loopback device */
        char    *device;        /* device name */
        struct pcap *next;      /* list of open promiscuous sock_packet pcaps */
#endif
};

struct pcap {    //這個結構很重要
        int fd;
        int snapshot;
        int linktype;
        int tzoff;              /* timezone offset */
        int offset;             /* offset for proper alignment */

        struct pcap_sf sf;
        struct pcap_md md;

        /*
         * Read buffer.
         */
        int bufsize;
        u_char *buffer;
        u_char *bp;
        int cc;

        /*
         * Place holder for pcap_next().
         */
        u_char *pkt;

        
        /*
         * Placeholder for filter code if bpf not in kernel.
         */
        struct bpf_program fcode;

        char errbuf[PCAP_ERRBUF_SIZE];
};

lipcap的宣告:
#define PCAP_VERSION_MAJOR 2
    libpcap dump檔案的主版本號;
#define PCAP_VERSION_MINOR   4   
    libpcap dump檔案的從版本號;
#define PCAP_ERRBUF_SIZE   256
    用來存放libpcap出錯資訊的緩衝區的大小;
#define PCAP_IF_LOOPBACK   0x00000001
    網絡卡是迴環網絡卡;
#define MODE_CAPT   0
    抓報模式,在呼叫pcap_setmode()時使用;
#define MODE_STAT   1
    靜態模式,在呼叫pcap_setmode()時使用;

libpcap的型別定義:
typedef int bpf_int32   
    32bit 的整形;
typedef    u_int bpf_u_int32
    32bit 的無型別整形;
typedef pcap pcap_t
    Descriptor of an open capture instance(一個開啟的捕獲例項的描述符?)這個結構對使用者是不透明的。
typedef pcap_dumper pcap_dumper_t
    libpcap儲存檔案的描述符。
typedef pcap_if pcap_if_t
    網絡卡連結串列的一個元素;
typedef pcap_addr pcap_addr_t
    網絡卡地址的表示;

libpcap函式描述:


char *pcap_lookupdev(char * errbuf);
    描述:    這個函式用於獲取一個合適的網絡卡描述,以供pcap_open_liver函式和pcap_lookupnet函式使用。如果找不到網絡卡或者所有網絡卡為 off,則返回null。如果一個系統中有多個網絡卡,那麼該函式返回找到的第一個on的網絡卡。最後才是迴環介面。迴環網絡卡一直被忽略;
    引數:
    char * errbuf     存放pcap_lookupdev函式的出錯資訊,只有在pcap_lookup失敗是才有值。
    返回值:    如果函式執行成功,則返回一個用於描述系統上的一個網絡卡的描述符的指標。如果失敗,返回null,errbuf中存放出錯資訊。


int pcap_lookupnet(char * device, bpf_u_int32 * netp, bpf_u_int32 * maskp,char * errbuf);
    描述:該函式用於監測網絡卡所在網路的網路地址和子網掩碼。
    引數:
    char *devic:網絡卡的描述符指標,由pcap_looupdev函式獲取;
    bpf_u_int32 *netp:存放網路地址;
    bpf_u_int32 *maskp:存放子網掩碼;
    char * errbuf: 存放出錯資訊;
    返回值:如果函式執行成功,則返回值為0,否則返回值為-1,並在errbuf中存放出錯資訊。


pcap_t *pcap_open_live(char * device, int  snaplen,int  promisc, int  to_ms, char * ebuf);
    描述:該函式用於開啟網絡卡用於捕獲資料報。單詞live的意思就是表示一個執行的網絡卡(相對於offline而言)被打開了,如同一個儲存有被抓資料報的 檔案被開啟一樣。在捕獲資料報之前這個函式必須被執行。所有的其他的用於處理資料報捕獲的函式用到的捕獲資料報的描述符由該函式產生。檢視 pcap_open_offlin()函式的定義,瞭解如何開啟一個預先儲存的包含資料報的檔案的細節。
    引數:
    char *device:網絡卡的描述符指標,由pcap_looupdev函式獲取;
    int snaplen:規定捕獲的每個資料報的最大位元組數;
    int promisc:1為混雜模式;0為非混雜模式;
    int to_ms:規定讀超時的微秒(milliseconds)數;
    char *ebuf:存放錯誤資訊,只有在pcap_open_live失敗時才被設定;
    返回值:如果函式成功執行,則返回一個指向資料報捕獲的指標;如果錯誤,返回null,ebuf存放出錯資訊;

   
int pcap_compile(pcap_t * p, struct bpf_ program *fp, char * str,int  optimize, bpf_u_int32  netmask);
    描述:該函式用於將str指定的規則整合到fp過濾程式中去,並生成過濾程式入口地址,用於過濾選擇期望的資料報;
    引數:
    pcap_t *p:pcap_open_live返回的資料報捕獲的指標;
    struct bpf_program *fp:指向一個子函式用於過濾,在pcap_compile()函式中被賦值;
    char *str:該字串規定過濾規則;
    int optimize:規定了在結果程式碼上的選擇是否被執行;
    bpf_u_int32 netmask:該網絡卡的子網掩碼,可以通過pcap_lookupnet()獲取;
    返回值:
    如果成功執行,返回0,否則返回-1;

int pcap_loop(pcap_t * p, int  cnt, pcap_handler  callback,u_char * user);
    描述:
    該函式用於讀取和處理資料報。既可以用來處理事先捕獲的儲存在檔案中的資料報,也可以用來處理實時捕獲的資料報;
    這個函式類似於pcap_dispatch函式,除了它繼續讀取資料報直至完成cnt個報的處理,或者檔案處理完(在offline情況下),或者有錯誤 發生為止。它不會在實時讀超時時返回(而如果為pcap_open_live()函式指定了一個非零值的超時設定,然後呼叫
pcap_dispatch()函式,則當超時發生時pcap_dispatch()函式會返回。)
    注意第三個引數,callback是pcap_handler型別的變數。這是一個使用者提供的有著三個引數的子函式。定義為:
void user_routine(u_char *user, struct pcap_pkthdr *phrd, u_char *pdata)
這三個引數中,user,是傳遞給pcap_dispatch()的那個引數;phdr,是個pcap_pkthdr型別的指標,是savefile中的資料報的頭指標,pdata,指向資料報資料;這個函式允許使用者定義子集的資料報過濾程式;
    引數:
    pcap_t * p:pcap_open_live返回的資料報捕獲的指標;
    int cnt:規定了函式返回前應處理的資料報數目;
    pcap_handler callback:指向一個使用者自定義的函式,在處理每個報後自動呼叫該函式進行再處理;
    u_char *user:該指標用於傳遞給callback.(不知道有什麼用?)
    返回值:
    如果函式成功執行(包括讀檔案時讀到EOF),則返回0.否則返回-1,那麼錯誤資訊將由函式pcap_geterr或pcap_perror給出;
    補充:callback函式:
    The concept behind a callback function is fairly simple.  Suppose I have a program that is waiting for an event of some sort.  For the purpose of this example, lets pretend that my program wants a user to press a key on the keyboard.  Every time they press a key, I want to call a function which then will determine that to do.  The function I am utilizing is a callback function.
pcap_open_dead()
     is used for creating a pcap_t structure to use when calling the other functions in libpcap. It is typically used when just using libpcap for compiling BPF code.
pcap_dump_open()
     is called to open a ``savefile'' for writing. The name "-" in a synonym for stdout. NULL is returned on failure. p is a pcap struct as returned by pcap_open_offline() or pcap_open_live(). fname specifies the name of the file to open. If NULL is returned, pcap_geterr() can be used to get the error text.
pcap_setnonblock()
     puts a capture descriptor, opened with pcap_open_live(), into ``non-blocking'' mode, or takes it out of ``non-blocking'' mode, depending on whether the nonblock argument is non-zero or zero. It has no effect on ``savefiles''. If there is an error, -1 is returned and errbuf is filled in with an appropriate error message; otherwise, 0 is returned. In ``non-blocking'' mode, an attempt to read from the capture descriptor with pcap_dispatch() will, if no packets are currently available to be read, return 0 immediately rather than blocking waiting for packets to arrive. pcap_loop() and pcap_next() will not work in ``non-blocking'' mode.
    libpcap檔案選讀:
    ethernet.c:定義了三個行內函數:
    static inline int xdtoi(int):該函式將十六進值數轉化為整數;
    static inline int skip_space(FILE *):該函式定義了在一個檔案中含有空格時,返回第一個不是'
'的字元。
    static inline int skip_line(FILE *):
    struct pcap_etherent {
            u_char addr[6];
            char name[122];
        };
    ethertype.h定義了各個協議的值。如#define ETHERTYPE_IP            0x0800  /* IP protocol */