一江春水向東流

          做一個(gè)有思想的人,期待與每一位熱愛思考的人交流,您的關(guān)注是對(duì)我最大的支持。

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            44 隨筆 :: 139 文章 :: 81 評(píng)論 :: 0 Trackbacks

          (C)libpcap函數(shù)庫說明

          libpcap獲取數(shù)據(jù)包函數(shù)庫說明

          libpcap的英文意思是 Packet Capture library,即數(shù)據(jù)包捕獲函數(shù)庫。該庫提供的C函數(shù)接口可用于

          需要捕獲經(jīng)過網(wǎng)絡(luò)接口(只要經(jīng)過該接口,目標(biāo)地址不一定為本機(jī))數(shù)據(jù)包的系統(tǒng)開發(fā)上。由

          Berkeley大學(xué)Lawrence Berkeley National? Laboratory研究院的Van Jacobson、Craig Leres和

          Steven McCanne編寫,目前的最新版本為0.4。該函數(shù)庫支持Linux、Solaris和*BSD系統(tǒng)平臺(tái)。

          主要接口函數(shù)說明如下:
          ?
          pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
          獲得用于捕獲網(wǎng)絡(luò)數(shù)據(jù)包的數(shù)據(jù)包捕獲描述字。device參數(shù)為指定打開的網(wǎng)絡(luò)設(shè)備名。snaplen參數(shù)定

          義捕獲數(shù)據(jù)的最大字節(jié)數(shù)。promisc指定是否將網(wǎng)絡(luò)接口置于混雜模式。to_ms參數(shù)指定超時(shí)時(shí)間(毫

          秒)。ebuf參數(shù)則僅在pcap_open_live()函數(shù)出錯(cuò)返回NULL時(shí)用于傳遞錯(cuò)誤消息。

          pcap_t *pcap_open_offline(char *fname, char *ebuf)
          打開以前保存捕獲數(shù)據(jù)包的文件,用于讀取。fname參數(shù)指定打開的文件名。該文件中的數(shù)據(jù)格式與

          tcpdump和tcpslice兼容。"-"為標(biāo)準(zhǔn)輸入。ebuf參數(shù)則僅在pcap_open_offline()函數(shù)出錯(cuò)返回NULL時(shí)

          用于傳遞錯(cuò)誤消息。

          pcap_dumper_t *pcap_dump_open(pcap_t *p, char *fname)
          打開用于保存捕獲數(shù)據(jù)包的文件,用于寫入。fname參數(shù)為"-"時(shí)表示標(biāo)準(zhǔn)輸出。出錯(cuò)時(shí)返回NULL。p參

          數(shù)為調(diào)用pcap_open_offline()或pcap_open_live()函數(shù)后返回的pcap結(jié)構(gòu)指針。fname參數(shù)指定打開

          的文件名。如果返回NULL,則可調(diào)用pcap_geterr()函數(shù)獲取錯(cuò)誤消息。

          char *pcap_lookupdev(char *errbuf)
          用于返回可被pcap_open_live()或pcap_lookupnet()函數(shù)調(diào)用的網(wǎng)絡(luò)設(shè)備名指針。如果函數(shù)出錯(cuò),則

          返回NULL,同時(shí)errbuf中存放相關(guān)的錯(cuò)誤消息。

          int pcap_lookupnet(char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp, char *errbuf)
          獲得指定網(wǎng)絡(luò)設(shè)備的網(wǎng)絡(luò)號(hào)和掩碼。netp參數(shù)和maskp參數(shù)都是bpf_u_int32指針。如果函數(shù)出錯(cuò),則

          返回-1,同時(shí)errbuf中存放相關(guān)的錯(cuò)誤消息。

          int pcap_dispatch(pcap_t *p, int cnt,pcap_handler callback, u_char *user)
          ?捕獲并處理數(shù)據(jù)包。cnt參數(shù)指定函數(shù)返回前所處理數(shù)據(jù)包的最大值。cnt=-1表示在一個(gè)緩沖區(qū)中處

          理所有的數(shù)據(jù)包。cnt=0表示處理所有數(shù)據(jù)包,直到產(chǎn)生以下錯(cuò)誤之一:讀取到EOF;超時(shí)讀取。

          callback 參數(shù)指定一個(gè)帶有三個(gè)參數(shù)的回調(diào)函數(shù),這三個(gè)參數(shù)為:一個(gè)從pcap_dispatch()函數(shù)傳遞

          過來的u_char指針,一個(gè)pcap_pkthdr結(jié)構(gòu)libpcap函數(shù)庫說明。bsp;? 的指針,和一個(gè)數(shù)據(jù)包大小的

          u_char指針。如果成功則返回讀取到的字節(jié)數(shù)。讀取到EOF時(shí)則返回零值。出錯(cuò)時(shí)則返回-1,此時(shí)可調(diào)

          用pcap_perror()或pcap_geterr()函數(shù)獲取錯(cuò)誤消息。

          int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
          功能基本與pcap_dispatch()函數(shù)相同,只不過此函數(shù)在cnt個(gè)數(shù)據(jù)包被處理或出現(xiàn)錯(cuò)誤時(shí)才返回,但

          讀取超時(shí)不會(huì)返回。而如果為pcap_open_live()函數(shù)指定了一個(gè)非零值的超時(shí)設(shè)置,然后調(diào)用

          pcap_dispatch()函數(shù),則當(dāng)超時(shí)發(fā)生時(shí)pcap_dispatch()函數(shù)會(huì)返回。cnt參數(shù)為負(fù)值時(shí)pcap_loop()

          函數(shù)將始終循環(huán)運(yùn)行,除非出現(xiàn)錯(cuò)誤。

          void pcap_dump(u_char *user, struct pcap_pkthdr *h, u_char *sp)
          向調(diào)用pcap_dump_open()函數(shù)打開的文件輸出一個(gè)數(shù)據(jù)包。該函數(shù)可作為pcap_dispatch()函數(shù)的回調(diào)

          函數(shù)。

          int pcap_compile(pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32

          netmask)
          將str參數(shù)指定的字符串編譯到過濾程序中。fp是一個(gè)bpf_program結(jié)構(gòu)的指針,在pcap_compile()函

          數(shù)中被賦值。optimize參數(shù)控制結(jié)果代碼的優(yōu)化。netmask參數(shù)指定本地網(wǎng)絡(luò)的網(wǎng)絡(luò)掩碼。
          ????????
          int pcap_setfilter(pcap_t *p, struct bpf_program *fp)
          指定一個(gè)過濾程序。fp參數(shù)是bpf_program結(jié)構(gòu)指針,通常取自pcap_compile()函數(shù)調(diào)用。出錯(cuò)時(shí)返回

          -1;成功時(shí)返回0。

          u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)
          返回指向下一個(gè)數(shù)據(jù)包的u_char指針。

          int pcap_datalink(pcap_t *p)
          返回?cái)?shù)據(jù)鏈路層類型,例如DLT_EN10MB。

          int pcap_snapshot(pcap_t *p)
          返回pcap_open_live被調(diào)用后的snapshot參數(shù)值。

          int pcap_is_swapped(pcap_t *p)
          返回當(dāng)前系統(tǒng)主機(jī)字節(jié)與被打開文件的字節(jié)順序是否不同。

          int pcap_major_version(pcap_t *p)
          返回寫入被打開文件所使用的pcap函數(shù)的主版本號(hào)。

          int pcap_minor_version(pcap_t *p)
          返回寫入被打開文件所使用的pcap函數(shù)的輔版本號(hào)。

          int pcap_stats(pcap_t *p, struct pcap_stat *ps)
          向pcap_stat結(jié)構(gòu)賦值。成功時(shí)返回0。這些數(shù)值包括了從開始捕獲數(shù)據(jù)以來至今共捕獲到的數(shù)據(jù)包統(tǒng)

          計(jì)。如果出錯(cuò)或不支持?jǐn)?shù)據(jù)包統(tǒng)計(jì),則返回-1,且可調(diào)用pcap_perror()或? pcap_geterr()函數(shù)來獲

          取錯(cuò)誤消息。

          FILE *pcap_file(pcap_t *p)
          返回被打開文件的文件名。

          int pcap_fileno(pcap_t *p)
          返回被打開文件的文件描述字號(hào)碼。

          void pcap_perror(pcap_t *p, char *prefix)
          在標(biāo)準(zhǔn)輸出設(shè)備上顯示最后一個(gè)pcap庫錯(cuò)誤消息。以prefix參數(shù)指定的字符串為消息頭。

          char *pcap_geterr(pcap_t *p)
          返回最后一個(gè)pcap庫錯(cuò)誤消息。

          char *pcap_strerror(int error)
          如果strerror()函數(shù)不可用,則可調(diào)用pcap_strerror函數(shù)替代。

          void pcap_close(pcap_t *p)
          關(guān)閉p參數(shù)相應(yīng)的文件,并釋放資源。

          void pcap_dump_close(pcap_dumper_t *p)

          5、Libpcap的主要數(shù)據(jù)結(jié)構(gòu):
          ?
          Libpcap庫函數(shù)所必須的數(shù)據(jù)結(jié)構(gòu)定義主要包含在pcap.h和pcap-int.h兩個(gè)頭文件中。其主要數(shù)據(jù)結(jié)構(gòu)

          如下:
          ?
          (1)pcap結(jié)構(gòu)
          ?
          pcap結(jié)構(gòu)在pcap-int.h頭文件中被定義:
          ?
          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;
          ??? int??????????????? bufsize;? /* Read buffer?????????????????????????????????????? */
          ??? u_char *?????????? buffer;
          ??? u_char *?????????? bp;
          ??? int??????????????? cc;
          ??? u_char *?????????? pkt;????? /* Place holder for pcap_next()????????????????????? */
          ??? struct bpf_program fcode;??? /* Placeholder for filter code if bpf not in kernel. */
          ??? char?????????????? errbuf[PCAP_ERRBUF_SIZE];
          };
          ?
          (2)bpf_program結(jié)構(gòu)
          ?
          該結(jié)構(gòu)在pcap_compile()函數(shù)中被使用,在bpf.h頭文件中定義。
          ?
          /usr/include/net/bpf.h

          /* Structure for BIOCSETF. */
          struct bpf_program
          {
          ??? u_int???????????? bf_len;
          ??? struct bpf_insn * bf_insns;
          };

          /*
          * The instruction data structure.
          */
          struct bpf_insn
          {
          ??? u_short?? code;
          ??? u_char??? jt;
          ??? u_char??? jf;
          ??? bpf_int32 k;
          };
          ?
          (3)pcap_pkthdr結(jié)構(gòu)
          ?
          /usr/include/pcap.h

          /*
          * Each packet in the dump file is prepended with this generic header.
          * This gets around the problem of different headers for different
          * packet interfaces.
          */
          struct pcap_pkthdr
          {
          ??? struct timeval ts;????? /* time stamp??????????????????? */
          ??? bpf_u_int32??? caplen;? /* length of portion present???? */
          ??? bpf_u_int32??? len;???? /* length this packet (off wire) */
          };

          /usr/include/net/bpf.h

          /*
          * Structure prepended to each packet.
          */
          struct bpf_hdr
          {
          ??? struct timeval bh_tstamp;?? /* time stamp???????????????? */
          ??? bpf_u_int32??? bh_caplen;?? /* length of captured portion */
          ??? bpf_u_int32??? bh_datalen;? /* original length of packet? */
          ??? u_short??????? bh_hdrlen;?? /* length of bpf header (this struct
          ?????????????????????????????????? plus alignment padding)??? */
          };
          ?
          (4)pcap_stat結(jié)構(gòu)
          ?
          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 */
          };

          int main()
          {
          ??????? bpf_u_int32 localnet,netmask;
          ??????? struct bpf_program fcode;
          ??????? pcap_handler printer;

          ??????? pcap_dumper_t*p;
          ??????? char ebuf[PCAP_ERRBUF_SIZE];
          ??????? char * device;
          ??????? u_char * pcap_userdata;
          ??????? pcap_t * pd;
          ??????? int dev_flag=1;
          ??????? int cap_len=CAP_LEN;
          ??????? int i;

          ??????? device=pcap_lookupdev(ebuf);
          ??????? if (device == NULL)
          ??????????????? exit(printf("%s n", ebuf));
          ??????? #ifdef _DEBUG_
          ??????? printf("device is %s \n",device);
          ??????? #endif
          ??????? pd=pcap_open_live(device,cap_len,dev_flag,1000,ebuf);
          ??????? if(pd == NULL)
          ??????????????? exit(printf("%s\n",ebuf));

          ??????? i=pcap_snapshot(pd);
          ??????????????? if(cap_len < i) {
          ??????????????? printf("snaplen raised from %d to %d \n", cap_len, i);
          ??????????????????????? cap_len=i;
          ??????????????? }
          ??????? if(pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
          ??????????????????????? localnet=0;

          ??? netmask=0;
          ??????????????????????? printf("%s\n", ebuf);
          ??????? }
          ??????? if (pcap_compile(pd, &fcode, "", 1, netmask) < 0)
          ??????????????? exit(printf("Error %s\n","pcap_compile"));
          ??????? if (pcap_setfilter(pd,&fcode) < 0)
          ??????????????? exit(printf("Error %s\n","pcap_setfilter"));

          ??????? p=pcap_dump_open(pd,FILENAME);
          ??????????????? if(p == NULL)
          ??????????????????????? exit(printf("Error:%s\n","pcap_dump_open"));
          ??????????????? printer=pcap_dump;
          ??????????????? pcap_userdata=(u_char *)p;

          ??????? if(pcap_loop(pd, -1, printer, pcap_userdata) < 0)
          ??????????????? exit(printf("Error, %s\n","pcap_loop"));

          ??????? pcap_close(pd);
          ??????? exit(0);
          }

          ?

          posted on 2007-08-24 21:07 allic 閱讀(2402) 評(píng)論(0)  編輯  收藏 所屬分類: TCP/IP 開發(fā)
          主站蜘蛛池模板: 介休市| 乐东| 绥德县| 华安县| 乌审旗| 屯留县| 新乡县| 安福县| 宝山区| 介休市| 平湖市| 老河口市| 新乡县| 东港市| 英吉沙县| 清新县| 莱州市| 梨树县| 曲水县| 石家庄市| 怀化市| 宾川县| 乐昌市| 平利县| 郯城县| 志丹县| 天气| 怀宁县| 兴安县| 文安县| 长武县| 荣昌县| 云阳县| 嘉黎县| 鱼台县| 大庆市| 吉木乃县| 江达县| 泰州市| 慈溪市| 永州市|