美文网首页
libpcap库基本使用教程(python、C语言)

libpcap库基本使用教程(python、C语言)

作者: 弦歌丶 | 来源:发表于2020-02-14 10:08 被阅读0次

    [TOC]

    读取网络接口

    安装和环境搭建

    // 待补充

    常用函数讲解

    note:C语言编译时要加上-lpcap参数链接libpcap库。

    pcap_lookupdev(errbuf)

    作用

    返回第一个适合的网络接口名称,没有找到的话返回-1。

    参数详解
    • errbuf

    C语言字符串缓存区用于缓冲错误信息。

    C语言代码示例

    char *pcap_lookupdev(char *errbuf);

    #include <stdio.h>
    #include <pcap.h>
    
    int main()
    {
        char errBuf[PCAP_ERRBUF_SIZE], * device;
        device = pcap_lookupdev(errBuf);
        if (device)
        {
            printf("device: %s\n", device);
        }
        else
        {
            printf("errbuf: %s\n", errBuf);
        }
        return 0;
    }
    
    python 代码示例
    #!/usr/bin/env python3
    import libpcap as pcap
    import ctypes as ct # 需要用到一些c的数据类型,故引入ctypes
    
    errbuf = ct.create_string_buffer(pcap.PCAP_ERRBUF_SIZE + 1)
    print(pcap.lookupdev(errbuf))
    

    pcap_findalldevs(alldevs, errbuf)

    作用

    返回所有的网络接口名称。

    参数详解
    • alldevs

    pcap_if_t结构体指针,用于存储查找到的所有网络设备信息。

    • errbuf

    C语言字符串缓存区用于缓冲错误信息。

    C语言代码示例

    int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)

    #include <stdio.h>
    #include <pcap.h>
    
    int main()
    {
        char errbuf[PCAP_ERRBUF_SIZE];
        pcap_if_t *alldevs;
        pcap_findalldevs(&alldevs, errbuf);
        for (pcap_if_t *pdev = alldevs; pdev; pdev=pdev->next)
        {
            printf("%s %s\n", pdev->name, pdev->description? pdev->description:"");
        }
        pcap_freealldevs(alldevs);
        return 0;
    }
    
    python 代码示例
    #!/usr/bin/env python3
    import libpcap as pcap
    import ctypes as ct
    
    alldevs = ct.POINTER(pcap.pcap_if_t)()
    errbuf = ct.create_string_buffer(pcap.PCAP_ERRBUF_SIZE + 1)
    pcap.findalldevs(ct.byref(alldevs), errbuf)
    print(alldevs[0].name)
    pcap.freealldevs(alldevs)
    

    pcap_open_live(device, snaplen, promisc, to_ms, errbuf)

    作用

    打开监听的设备, 返回一个可供操作的捕获句柄。

    参数详解
    • device

    网络接口设备名称,可通过pcap_lookupdev和pcap_findalldevs获取。

    • snaplen

    捕获数据包时的缓冲区大小。

    • promisc

    是否使用混杂模式,0为非混杂模式,其他值混杂模式。

    • to_ms

    数据从内核态复制到用户态等待的时间。由于从内核态切换到用户态,需要比较大的性能消耗。 越低的值,性能消耗越大。如果是0,则会一直等待到有足够的数据,才能复制到用户态。tcpdump使用了1000。

    • errbuf

    C语言字符串缓存区用于缓冲错误信息。

    C语言代码示例

    pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *errbuf);

    #include <stdio.h>
    #include <pcap.h>
    #define BUFSIZ 65535
    
    int main()
    {
        char errbuf[PCAP_ERRBUF_SIZE];
        pcap_t *handle;
        char device[] = "rl0";
        device = pcap_lookupdev(errBuf);
        if (device)
        {
            handle = pcap_open_live(device, BUFSIZ, 1, 1000, errbuf);
            if (handle == NULL)
            {
                printf("Couldn't open device %s: %s\n", device, errbuf);
                return 2;
            }
        }
        else
        {
            printf("errbuf: %s\n", errBuf);
            return 1;
        }
        return 0;
    }
    
    python 代码示例
    #!/usr/bin/env python3
    import libpcap as pcap
    import ctypes as ct
    
    errbuf = ct.create_string_buffer(pcap.PCAP_ERRBUF_SIZE + 1)
    device = pcap.lookupdev(errbuf)
    pd = pcap.open_live(device, 65535, 1, 1000, errbuf)
    if not pd:
        print(f"p  cap.open_live failed: {errbuf.value.decode('utf-8')}")
    print(pd)
    

    pcap_setnonblock(p, nonblock, errbuf)

    作用

    将捕获句柄设置为“非阻塞”或者“阻塞”模式,具体取决于nonblock参数为非零或零。另外pcap_getnonblock(p, errbuf)函数可用于获取当前模式状态。

    参数详解
    • p

    捕获句柄,可以由pcap_open_live或者pcap_create返回得到。

    • nonblock

    设置为“非阻塞”或者“阻塞”模式,零和非零。

    • errbuf

    C语言字符串缓存区用于缓冲错误信息。

    C语言代码示例

    int pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf);

    #include <stdio.h>
    #include <pcap.h>
    #define BUFSIZ 65535
    
    int main()
    {
    
        char errbuf [PCAP_ERRBUF_SIZE];
        pcap_t *handle;
        char device[] = "rl0";
        device = pcap_lookupdev(errBuf);
        if (device)
        {
            handle = pcap_open_live(device, BUFSIZ, 1, 1000, errbuf);
            printf("%d", pcap_getnonblock(handle, errbuf));
            pcap_setnonblock(handle, 1, errbuf);
        }
        return 0;
    }
    
    python 代码示例
    #!/usr/bin/env python3
    import libpcap as pcap
    import ctypes as ct
    
    errbuf = ct.create_string_buffer(pcap.PCAP_ERRBUF_SIZE + 1)
    device = pcap.lookupdev(errbuf)
    pd = pcap.open_live(device, 65535, 1, 1000, errbuf)
    if not pd:
        if pcap.setnonblock(pd, 1, errbuf) == -1:
                error(f"pcap.setnonblock failed: {errbuf.value.decode('utf-8')}")
    

    pcap_lookupnet(device, net, mask, errbuf)

    作用

    获取设备的网络掩码。

    参数详解
    • device

    网络接口设备名称,可通过pcap_lookupdev和pcap_findalldevs获取。

    • net

    缓冲返回的网络码

    • mask

    缓冲返回的掩码信息

    • errbuf

    C语言字符串缓存区用于缓冲错误信息。

    C语言代码示例

    int pcap_lookupnet(const char *device, bpf_u_int32 *net, bpf_u_int32 *mask, char *errbuf);

    #include <stdio.h>
    #include <pcap.h>
    
    int main()
    {
        char errbuf[PCAP_ERRBUF_SIZE];
        bpf_u_int32 *net; 
        bpf_u_int32 *mask;
        char device[] = "rl0";
        device = pcap_lookupdev(errBuf);
        if (device)
        {
            pcap_lookupnet(device, net, mask, errbuf);
        }
        else
        {
            printf("errbuf: %s\n", errBuf);
            return 1;
        }
        return 0;
    }
    
    python 代码示例
    #!/usr/bin/env python3
    import libpcap as pcap
    import ctypes as ct
    
    errbuf = ct.create_string_buffer(pcap.PCAP_ERRBUF_SIZE + 1)
    device = pcap.lookupdev(errbuf)
    localnet = pcap.bpf_u_int32()
    netmask = pcap.bpf_u_int32()
    if pcap.lookupnet(device, ct.byref(localnet), ct.byref(netmask), errbuf) < 0:
        return
    print(localnet)
    print(netmask)
    

    pcap_compile(p, fp, str, optimize, netmask)

    作用

    用于将字符串str编译为过滤器程序。

    参数详解
    • p

    捕获句柄,可以由pcap_open_live或者pcap_create返回得到。

    • fp

    过滤条件句柄,过滤条件编译出来的结果。我们不太需要关心其具体的结构内容,只需要把它传给下一步的调用即可。

    • str

    过滤条件表达式。

    • optimize

    是否优化表达式。

    • netmask

    指定网络的掩码。

    C语言代码示例

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

    #include <stdio.h>
    #include <pcap.h>
    
    int main()
    {
        char errbuf[PCAP_ERRBUF_SIZE];
        bpf_u_int32 net; 
        bpf_u_int32 mask;
        pcap_t *handle;
        device = pcap_lookupdev(errBuf);
        struct bpf_program filter;
        char filter_app[] = "port 23";
        pcap_lookupnet(device, &net, &mask, errbuf);
        handle = pcap_open_live(device, BUFSIZ, 1, 0, errbuf);
        pcap_compile(handle, &filter, filter_app, 0, net);
        pcap_setfilter(handle, &filter);
        return 0;
    }
    
    python 代码示例
    #!/usr/bin/env python3
    import libpcap as pcap
    import ctypes as ct
    
    expression = 'port 23'
    errbuf = ct.create_string_buffer(pcap.PCAP_ERRBUF_SIZE + 1)
    device = pcap.lookupdev(errbuf)
    localnet = pcap.bpf_u_int32()
    netmask = pcap.bpf_u_int32()
    if pcap.lookupnet(device, ct.byref(localnet), ct.byref(netmask), errbuf) < 0:
        return
    fcode = pcap.bpf_program()
    cmdbuf = " ".join(expression).encode("utf-8")
    if pcap.compile(pd, ct.byref(fcode), cmdbuf, 1, netmask) < 0:
        print(pcap.geterr(pd).decode("utf-8", "ignore"))
    if pcap.setfilter(pd, ct.byref(fcode)) < 0:
        print(pcap.geterr(pd).decode("utf-8", "ignore"))
    

    pcap_setfilter(p, fp, str, optimize, netmask)

    作用

    设置过滤器程序。

    参数详解
    • p

    捕获句柄,可以由pcap_open_live或者pcap_create返回得到。

    • fp

    过滤条件句柄,过滤条件编译出来的结果。

    C语言代码示例

    int pcap_setfilter(pcap_t *p, struct bpf_program *fp);

    #include <stdio.h>
    #include <pcap.h>
    
    int main()
    {
        char errbuf[PCAP_ERRBUF_SIZE];
        bpf_u_int32 net; 
        bpf_u_int32 mask;
        pcap_t *handle;
        device = pcap_lookupdev(errBuf);
        struct bpf_program filter;
        char filter_app[] = "port 23";
        pcap_lookupnet(device, &net, &mask, errbuf);
        handle = pcap_open_live(device, BUFSIZ, 1, 0, errbuf);
        pcap_compile(handle, &filter, filter_app, 0, net);
        pcap_setfilter(handle, &filter);
        return 0;
    }
    
    python 代码示例
    #!/usr/bin/env python3
    import libpcap as pcap
    import ctypes as ct
    
    expression = 'port 23'
    errbuf = ct.create_string_buffer(pcap.PCAP_ERRBUF_SIZE + 1)
    device = pcap.lookupdev(errbuf)
    localnet = pcap.bpf_u_int32()
    netmask = pcap.bpf_u_int32()
    if pcap.lookupnet(device, ct.byref(localnet), ct.byref(netmask), errbuf) < 0:
        return
    fcode = pcap.bpf_program()
    cmdbuf = " ".join(expression).encode("utf-8")
    if pcap.compile(pd, ct.byref(fcode), cmdbuf, 1, netmask) < 0:
        print(pcap.geterr(pd).decode("utf-8", "ignore"))
    if pcap.setfilter(pd, ct.byref(fcode)) < 0:
        print(pcap.geterr(pd).decode("utf-8", "ignore"))
    

    pcap_next(p, h)

    作用

    一次只抓取一个包。

    参数详解
    • p

    捕获句柄,可以由pcap_open_live或者pcap_create返回得到。

    • h

    缓冲捕获数据包。

    C语言代码示例
    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) */ 
    };
    u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h);
    
    
    #include <pcap.h>
    #include <stdio.h>
    int main(int argc, char *argv[])
    {
        pcap_t *handle;         /* session handle */
        char *dev;          /* the device to sniff on */
        char errbuf[pcap_errbuf_size];  /* error string */
        struct bpf_program fp;      /* the compiled filter */
        char filter_exp[] = "port 23";  /* the filter expression */
        bpf_u_int32 mask;       /* our netmask */
        bpf_u_int32 net;        /* our ip */
        struct pcap_pkthdr header;  /* the header that pcap gives us */
        const u_char *packet;       /* the actual packet */
        /* define the device */
        dev = pcap_lookupdev(errbuf);
        if (dev == null) {
            fprintf(stderr, "couldn't find default device: %s\n", errbuf);
            return(2);
        }
        /* 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, "couldn'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, "couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
            return(2);
        }
        if (pcap_setfilter(handle, &fp) == -1) {
            fprintf(stderr, "couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
            return(2);
        }
        /* grab a packet */
        packet = pcap_next(handle, &header);
        /* print its length */
        printf("jacked a packet with length of [%d]\n", header.len);
        /* and close the session */
        pcap_close(handle);
        return(0);
    }
    
    python 代码示例
    #!/usr/bin/env python3
    import libpcap as pcap
    import ctypes as ct
    ...
    

    相关文章

      网友评论

          本文标题:libpcap库基本使用教程(python、C语言)

          本文链接:https://www.haomeiwen.com/subject/recdfhtx.html