分享

libcap编程实例

 青松卓然 2012-09-04

libcap编程实例

TCPDUMP's homepage:     http://www./

libpcap是unix/linux平台下的网络数据包捕获函数包,大多数网络监控软件都以它为基础。

      这个库的位置在/usr/local/lib下.在 /usr/local/include下是他的头文件pcap.h。要写一个使用libpcap库函数的程序只需要在代码中加上#include <pcap.h>,然后在编译时末尾加上-lpcap选项就可以了.

     Libpcap应用程序从形式上看很简单,下面是一个简单的程序框架:

char * device; /* 用来捕获数据包的网络接口的名称 */------------what is it? -eth0
pcap_t * p; /* 捕获数据包句柄,最重要的数据结构 */-------------
struct bpf_program fcode; /* BPF 过滤代码结构 */-------------?how to write

/* 第一步:查找可以捕获数据包的设备 */
device = pcap_lookupdev(errbuf);---------------now i see

/* 第二步:创建捕获句柄,准备进行捕获 */
p = pcap_open_live(device, 8000, 1, 500, errbuf);

/* 第三步:如果用户设置了过滤条件,则编译和安装过滤代码 */------can i use nothing here?
pcap_compile(p, &fcode, filter_string, 0, netmask);
pcap_setfilter(p, &fcode);

pcap_loop (p, 7, printer, NULL); /* 这里的p就是我们刚刚生成的描述符;的第二个参数表示抓多少个包,设置为-1表示不定义数量,抓取所有的包;第三个参数是一个回调函数,每当抓到一个数据包之后程序将自动调用这个函数;第四个参数是一个指针,可以为空。 */

/*最后别忘了close*/

pcap_close (p);

   libpcap是一个C语言库,其功能是通过网卡抓取网络以太网中的数据包,在windows系统下有相应的winpcap库。

     要想使用这个库自然先要知道它在哪里,怎么安装就不废话了。在/usr/local/lib下有libpcap.a和libpcao.so,在 /usr/local/include下有pcap.h,打开手册的命令是man pcap,而不是man libpcap,如果觉得在字符模式下查看man太麻烦也可以baidu或者google一下"man pcap"会又可读性更高的手册。要写一个使用libpcap的程序只需要在代码中加上#i nclude <pcap.h>,然后在编译时使用-lpcap选项就可以了,例如:

     $>gcc -o test1 test1.c -lpcap

     如果能正确的编译通过使用libpcap的代码,那么便可以进入第二步了,写一个最简单的抓包程序。

     先来介绍第一个类型:pcap_t。要抓包就要首先生成一个抓包的描述符(或称句柄),后来的很多操作都需要用这个描述符做参数。pcap_t就是由pcap.h定义的抓包描述符的类型,函数pcap_open_live返回指向该类型的指针:

     pcap_t *pd = pcap_open_live ("eth0", 68, 0, 1000, ebuf);

     其中第一个参数表示用来抓包的设备;第二个参数定义了抓包的最大字节数,如果这个值小于包的大小(如定义为68,包大于68),那么则只抓这个包的前68 个字节;第三个参数把网卡设置为混杂模式,以便抓取以太网中的数据包;第四个参数是一个以毫秒为单位的读取超时时间,如果设置为0则超时时间为无限大;第 五个参数为出错信息,需要这样声明(第一个简单的程序不需要出错处理,只知道这样声明就够了):

     char ebuf[PCAP_ERRBUF_SIZE];

     好了,现在生成了一个描述符了,现在我们可以用它来做一点什么事情了。开始一个抓包的循环,然后关闭抓包过程(释放描述符):

     pcap_loop (pd, 7, printer, NULL);

     pcap_close (pd);

     这里的pd就是我们刚刚生成的描述符;pcap_loop的第二个参数表示抓多少个包,设置为-1表示不定义数量,抓取所有的包;第三个参数是一个回调函数,每当抓到一个数据包之后程序将自动调用这个函数;第四个参数是一个指针,可以为空,将在下面详细讲解。

     下面我们来详细的实现这个回调函数,使其每抓到一个包则打印一次:

     void printer()
         {
                 printf("A packet is captured! ");
                 printf(" \n");
                 return;
         }

     当程序成功编译以后执行,则每抓到一个包后输出一行"A packet is captured! ",输出7行以后退出程序。

     这样,一个最简单的抓包程序诞生了!
    

参考源码:


/**
libpcap test program

compile command:"$>gcc -o exe_file_name this_file_name -lpcap"

written by Kxing <>
Last Modified 2006-03-02
*/


#include <stdio.h>
#include <pcap.h>

int main (int argc, char* argv[])
{
         /*the printer running when packet have captured*/
         void printer()
         {
                 printf("A packet is captured!");
                 printf(" \n");
                 return;
         }


         /*the error code buf of libpcap*/
         char ebuf[PCAP_ERRBUF_SIZE];
         /*create capture handler of libpcap*/
         pcap_t *pd = pcap_open_live ("eth0", 68, 0, 1000, ebuf);


         /*start the loop of capture, loop 7 times, enter printer when capted*/
         pcap_loop (pd, 7, printer, NULL);

         pcap_close (pd);

         return 0;
}


/*
*File:main.c
*Decripe:get the device use pcap
*parameter:
*      input:
*      output:
*return:
*Function: use pcap
*Author:maxingguo (msingle@163.com)
*      Harbin Engineering University
*      Information Security Research Center
*/
#include <stdio.h>
#include <pcap.h>
int main(int argc, char *argv[])
{
        char *dev, errbuf[PCAP_ERRBUF_SIZE];
        pcap_t *handle;                    //session handle
        struct bpf_program fp;             //the compiled filter expression
        char   filter_exp[] = "port 23";   //the filter expression
        bpf_u_int32 mask;                 //the metmask of our sniffer device
        bpf_u_int32 net;                  //the IP of our sniffing device
        struct pcap_pkthdr header;         //the header that pcap gives us
        const u_char *packet;            //the actual packet

        /*Define the device*/
        dev = pcap_lookupdev(errbuf);      //get the device
        if (dev == NULL) {
                fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
              return(2);
        }
        printf("Device: %s\n", dev);

        /*Find the properties for the device */
        if( pcap_lookupnet(dev,&net,&mask,errbuf) == -1)
        {
                fprintf(stderr,"Couldn't get netmask for device %s: %s\n",dev,errbuf);
                net = 0;
                mask = 0;
        }

        /*Open the session in promiscuous mode*/
        handle = pcap_open_live(dev,BUFSIZ,1,1000,errbuf);

        if(handle == NULL)
        {
                fprintf(stderr,"Could't open device %s:%s\n",dev,errbuf);
                return(2);
        }

        /*Compile and apply the filter*/
        if( pcap_compile(handle,&fp,filter_exp,0,net) == -1 )
        {
                fprintf(stderr,"Could't parse filter %s:%s \n",filter_exp,pcap_geterr(handle));
                return(2);
        }

        if( pcap_setfilter(handle,&fp) == -1)
        {
                fprintf(stderr,"Could't install filter %s: %s \n",filter_exp,pcap_geterr(handle));
                return(2);
        }

        /*Grab a packet */
        packet = pcap_next(handle,&header);

        printf("Jack a packet:%s \n The length is: %d\n %s",packet,header.len);

        /*Close the session*/
        pcap_close(handle);
        return(0);
}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多