Chinaunix首页 | 论坛 | 博客
  • 博客访问: 457565
  • 博文数量: 42
  • 博客积分: 1325
  • 博客等级: 中尉
  • 技术积分: 1312
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-13 18:00
个人简介

呵~~~呵~~~

文章分类

全部博文(42)

文章存档

2016年(3)

2015年(1)

2014年(2)

2013年(2)

2012年(7)

2011年(11)

2010年(3)

2009年(13)

我的朋友

分类: LINUX

2011-07-07 23:14:09

一、使用libpcap进行包捕获.
需要注意的是libpcap的mmap. mmap减少了一次数据拷贝,一定程度上提升了包捕获效率.
要大幅提高包捕获效率,推荐使用pfring. pfring实现了zero-copy技术.
包捕获部份源代码如下,在openSUSE 32/64位下可用,仅需要修改库位置.

/*
 *Author:zhonghaohua@gmail.com
 */


#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "execinfo.h"

#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/ip.h>
//#include
#include "tcp.h"
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>

#include "pcap.h"

#define SNAPLEN 65536
#define PCAP_ERRBUFi_SIZE 256

#include "ppacket.h"

//存储数据包从链路层到TCP层信息
typedef struct
{
        u_int32_t src;
        u_int32_t dst;
        u_int16_t sport;
        u_int16_t dport;
        u_int8_t ether_smac[ETHER_ADDR_LEN];
        u_int8_t ether_dmac[ETHER_ADDR_LEN];
        u_int32_t seq;
        u_int32_t ack;
        u_int8_t isfin;
}flow_t;

int main(int argc, char *argv[])
{
        //for argument
        extern int optind;
        extern int opterr;
        extern int optopt;
        extern char *optarg;
        char arg = 0x0;

        //for libpcap
        int promisc = 1; //混杂模式

        int dlt = 0;
        char *device = NULL; //eht0 or other device
        char expression[] = "tcp";
        pcap_t *pd = NULL;
        pcap_handler handler;
        struct bpf_program fcode;
        char error[PCAP_ERRBUFi_SIZE];

        //init argument
        while((arg = getopt(argc, argv, "i:vc")) != EOF)
        {
                switch(arg)
                {
                        case 'i':
                                device = optarg;
                                break;
                        default:
                                break;
                }
        }

        //当未指定device时,自动选择可用的device.
        if(device == NULL)
        {
                if( (device = pcap_lookupdev(error)) == NULL)
                {
                        printf("%s", error);
                        return 1;
                }
        }

         //make sure the device. and set capture mode.
        if((pd = pcap_open_live(device, SNAPLEN, promisc, 1000, error)) == NULL)
        {
                printf("%s", error);
                return 1;
        }

        //get kind of packets
        dlt = pcap_datalink(pd);
        handler = find_handler(dlt, device); //根据链路层协议,选择相应的处理函数

        //set expression
        if(pcap_compile(pd, &fcode, expression, 1, 0) < 0)
        {
                printf("%s", pcap_geterr(pd));
                return 1;
        }
        if(pcap_setfilter(pd, &fcode) < 0)
        {
                printf("%s", pcap_geterr(pd));
                return 1;
        }

        //Begin to capture packet.
         if(pcap_loop(pd, -1, handler, NULL) < 0)
        {
                printf("%s", pcap_geterr(pd));
                return 1;
        }

        return 0;
}

pcap_handler find_handler(int datalink_type, char *device)
{
        struct {
                pcap_handler handler;
                int type;
        } handlers[] = {
                { dl_ethernet, DLT_EN10MB },
                { dl_ethernet, DLT_IEEE802 },
                { dl_ppp, DLT_PPP },
                { NULL, 0 },
};

        int i = 0;
        for (i = 0; handlers[i].handler != NULL; i++)
                if (handlers[i].type == datalink_type)

                        return handlers[i].handler;

        return NULL;
}



二、Makefile


objects = /usr/lib/libpcap.so
libs = -lpcap
flag = -g -DDEBUG

edit : $(objects)
        gcc $(lib) $(flag) ppacket.c -o ppacket $(objects)

clean :
        rm -f *.o ppacket






阅读(3557) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~