/*pcap_1.c*/
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>  /* 如果没有pcap的系统,要自己下载一个 */
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char **argv)
{
  char *dev; /* name of the device to use */ 
  char *net; /* dot notation of the network address */
  char *mask;/* dot notation of the network mask    */
  int ret;   /* return code */
  char errbuf[PCAP_ERRBUF_SIZE];
  bpf_u_int32 netp; /* ip          */
  bpf_u_int32 maskp;/* subnet mask */
  struct in_addr addr;

/* ask pcap to find a valid device for use to sniff on */
  dev = pcap_lookupdev(errbuf);

/* error checking */
  if(dev == NULL)
  {
   printf("%s/n",errbuf);
   exit(1);
  }

/* print out device name */
  printf("DEV: %s/n",dev);

/* ask pcap for the network address and mask of the device */
  ret = pcap_lookupnet(dev,&netp,&maskp,errbuf);

if(ret == -1)
  {
   printf("%s/n",errbuf);
   exit(1);
  }

/* get the network address in a human readable form */
  addr.s_addr = netp;
  net = inet_ntoa(addr);

if(net == NULL)/* thanks Scott :-P */
  {
    perror("inet_ntoa");
    exit(1);
  }

printf("NET: %s/n",net);

/* do the same as above for the device's mask */
  addr.s_addr = maskp;
  mask = inet_ntoa(addr);
  
  if(mask == NULL)
  {
    perror("inet_ntoa");
    exit(1);
  }
  
  printf("MASK: %s/n",mask);

return 0;
}

然后gcc -o pcap_1 pcap_1.c -lpcap(一定要-lpcap参数)
编译ok~,执行./pcap_1,可以看到:
DEV: eth0
NET: 192.168.12.0
MASK: 255.255.255.0
好了,第一个pcap程序出炉了。。。。。
 
但是(当然有但是了,要不然我后面写啥),上面那个程序除了向我们展现pcap_lookupdev和pcap_lookupnet之外什么都没有干,好,我们接着来,动手编写我们的第一个抓包程序。
 
/*pcap_2.c*/
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h> /* if this gives you an error try pcap/pcap.h */
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/if_ether.h> /* includes net/ethernet.h */

int main(int argc, char **argv)
{
    int i;
    char *dev; 
    char errbuf[PCAP_ERRBUF_SIZE];
    pcap_t* descr;      /*you can man it*/
    const u_char *packet;
    struct pcap_pkthdr hdr;     /* pcap.h */
    struct ether_header *eptr;  /* net/ethernet.h */

u_char *ptr; /* printing out hardware header info */

/* grab a device to peak into... */
    dev = pcap_lookupdev(errbuf);

if(dev == NULL)
    {
        printf("%s/n",errbuf);
        exit(1);
    }

printf("DEV: %s/n",dev);

/* open the device for sniffing.

pcap_t *pcap_open_live(char *device,int snaplen, int prmisc,int to_ms,
       char *ebuf)

snaplen - maximum size of packets to capture in bytes
       promisc - set card in promiscuous mode?
       to_ms   - time to wait for packets in miliseconds before read
       times out
       errbuf  - if something happens, place error string here

Note if you change "prmisc" param to anything other than zero, you will
       get all packets your device sees, whether they are intendeed for you or
       not!! Be sure you know the rules of the network you are running on
       before you set your card in promiscuous mode!!     */

descr = pcap_open_live(dev,BUFSIZ,0,-1,errbuf);

if(descr == NULL)
    {
        printf("pcap_open_live(): %s/n",errbuf);
        exit(1);
    }

/*
       grab a packet from descr (yay!)                    
       u_char *pcap_next(pcap_t *p,struct pcap_pkthdr *h) 
       so just pass in the descriptor we got from         
       our call to pcap_open_live and an allocated        
       struct pcap_pkthdr                                 */

packet = pcap_next(descr,&hdr);

if(packet == NULL)
    {/* dinna work *sob* */
        printf("Didn't grab packet/n");
        exit(1);
    }

/*  struct pcap_pkthdr {
        struct timeval ts;   time stamp 
        bpf_u_int32 caplen;  length of portion present 
        bpf_u_int32;         lebgth this packet (off wire) 
        }
     */

printf("Grabbed packet of length %d/n",hdr.len);
    printf("Recieved at ..... %s/n",ctime((const time_t*)&hdr.ts.tv_sec)); 
    printf("Ethernet address length is %d/n",ETHER_HDR_LEN);

/* lets start with the ether header... */
    eptr = (struct ether_header *) packet;

/* Do a couple of checks to see what packet type we have..*/
    if (ntohs (eptr->ether_type) == ETHERTYPE_IP)
    {
        printf("Ethernet type hex:%x dec:%d is an IP packet/n",
                ntohs(eptr->ether_type),
                ntohs(eptr->ether_type));
    }else  if (ntohs (eptr->ether_type) == ETHERTYPE_ARP)
    {
        printf("Ethernet type hex:%x dec:%d is an ARP packet/n",
                ntohs(eptr->ether_type),
                ntohs(eptr->ether_type));
    }else {
        printf("Ethernet type %x not IP", ntohs(eptr->ether_type));
        exit(1);
    }

/* THANK YOU RICHARD STEVENS!!! RIP*/
    ptr = eptr->ether_dhost;
    i = ETHER_ADDR_LEN;
    printf(" Destination Address:  ");
    do{
        printf("%s%x",(i == ETHER_ADDR_LEN) ? " " : ":",*ptr++);
    }while(--i>0);
    printf("/n");

ptr = eptr->ether_shost;
    i = ETHER_ADDR_LEN;
    printf(" Source Address:  ");
    do{
        printf("%s%x",(i == ETHER_ADDR_LEN) ? " " : ":",*ptr++);
    }while(--i>0);
    printf("/n");

return 0;
}

好了,编译运行!
[root@norman libpcap]# ./pcap_2
DEV: eth0
Grabbed packet of length 76
Recieved at time..... Mon Mar 12 22:23:29 2001

Ethernet address length is 14
Ethernet type hex:800 dec:2048 is an IP packet
Destination Address:   0:20:78:d1:e8:1
Source Address:   0:a0:cc:56:c2:91
[root@pepe libpcap]#

 
可能有人等了半天都没有一个包过来,有个好办法,再开一个控制台,ping一下某个网站,比如google~~,呵呵
马上就有反应了~~
 
这个程序是一个老外写的,大家看看注释应该没有问题吧~
但是大家也发现了一个问题,就是上面的程序只能捕捉一个包,要不停的捕捉包怎么办,用循环??libpcap提供了一个更好的方法:
int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
这个函数能够不停的捕捉以太网的包,cnt就是捕捉的次数,callback是处理函数,这个处理函数怎么写,看看pcap_3.c就知道了。user参数是干什么的?不要问我,我也不知道。
 
/*pcap_3.c*/
#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/if_ether.h>

/* callback function that is passed to pcap_loop(..) and called each time 
* a packet is recieved                                                    */
void my_callback(u_char *useless,const struct pcap_pkthdr* pkthdr,const u_char*
        packet)
{
    static int count = 1;
    fprintf(stdout,"%d, ",count);
    if(count == 4)
        fprintf(stdout,"Come on baby sayyy you love me!!! ");
    if(count == 7)
        fprintf(stdout,"Tiiimmmeesss!! ");
    fflush(stdout);
    count++;
}

int main(int argc,char **argv)

    int i;
    char *dev; 
    char errbuf[PCAP_ERRBUF_SIZE];
    pcap_t* descr;
    const u_char *packet;
    struct pcap_pkthdr hdr;     /* pcap.h */
    struct ether_header *eptr;  /* net/ethernet.h */

if(argc != 2){ fprintf(stdout,"Usage: %s numpackets/n",argv[0]);return 0;}

/* grab a device to peak into... */
    dev = pcap_lookupdev(errbuf);
    if(dev == NULL)
    { printf("%s/n",errbuf); exit(1); }
    /* open device for reading */
    descr = pcap_open_live(dev,BUFSIZ,0,-1,errbuf);
    if(descr == NULL)
    { printf("pcap_open_live(): %s/n",errbuf); exit(1); }

/* allright here we call pcap_loop(..) and pass in our callback function */
    /* int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)*/
    pcap_loop(descr,atoi(argv[1]),my_callback,NULL);

fprintf(stdout,"/nDone processing packets... wheew!/n");
    return 0;
}

 
运行./pcap_3 7
1, 2, 3, 4, Come on baby sayyy you love me!!! 5, 6, 7, Tiiimmmeesss!!  
Done processing packets... wheew!
 
pcap_loop确实很好用,但是如果没有包包过来,只有干等在那里,pcap_dispatch就含有一个超时的功能,下面是man里面的一段话:
pcap_dispatch() is used to collect and process packets. cnt specifies the maximum number of packets to process before returning. A cnt of -1 processes all the packets received in one buffer. A cnt of 0 processes all packets until an error occurs, EOF is reached, or the read times out (when doing live reads and a non-zero read timeout is specified). callback specifies a routine to be called with three arguments: a u_char pointer which is passed in from pcap_dispatch(), a pointer to the pcap_pkthdr struct (which precede the actual network headers and data), and a u_char pointer to the packet data. The number of packets read is returned. Zero is returned when EOF is reached in a ``savefile.'' A return of -1 indicates an error in which case pcap_perror() or pcap_geterr() may be used to display the error text. 
 
另外的问题是,我们可能对抓取的包包太多而很头痛,可能很多都不是我们感兴趣的包,别急,pcap_compile和pcap_setfilter能帮我们解决问题。
 /*pcap_4.c*/
#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/if_ether.h>

/* just print a count every time we have a packet...                        */
void my_callback(u_char *useless,const struct pcap_pkthdr* pkthdr,const u_char*
        packet)
{
    static int count = 1;
    fprintf(stdout,"%d, ",count);
    fflush(stdout);
    count++;
}

int main(int argc,char **argv)

    int i;
    char *dev; 
    char errbuf[PCAP_ERRBUF_SIZE];
    pcap_t* descr;
    const u_char *packet;
    struct pcap_pkthdr hdr;     /* pcap.h                    */
    struct ether_header *eptr;  /* net/ethernet.h            */
    struct bpf_program fp;      /* hold compiled program     */
    bpf_u_int32 maskp;          /* subnet mask               */
    bpf_u_int32 netp;           /* ip                        */

if(argc != 2){ fprintf(stdout,"Usage: %s /"filter program/"/n"
            ,argv[0]);return 0;}

/* grab a device to peak into... */
    dev = pcap_lookupdev(errbuf);
    if(dev == NULL)
    { fprintf(stderr,"%s/n",errbuf); exit(1); }

/* ask pcap for the network address and mask of the device */
    pcap_lookupnet(dev,&netp,&maskp,errbuf);

/* open device for reading this time lets set it in promiscuous
     * mode so we can monitor traffic to another machine             */
    descr = pcap_open_live(dev,BUFSIZ,1,-1,errbuf);
    if(descr == NULL)
    { printf("pcap_open_live(): %s/n",errbuf); exit(1); }

/* Lets try and compile the program.. non-optimized */
    if(pcap_compile(descr,&fp,argv[1],0,netp) == -1)
    { fprintf(stderr,"Error calling pcap_compile/n"); exit(1); }

/* set the compiled program as the filter */
    if(pcap_setfilter(descr,&fp) == -1)
    { fprintf(stderr,"Error setting filter/n"); exit(1); }

/* ... and loop */ 
    pcap_loop(descr,-1,my_callback,NULL);

return 0;
}

运行./pcap_4.c "host www.google.com

然后在另外一个控制台下面ping www.baidu.com
哈哈
没有反应吧
接着再ping www.google.com
就看到1, 2, 3, 4, 5, 6,
ok
you got it!!

从网上搜索到的一些关于pcap源代码,入门级的的更多相关文章

  1. 小白学习VUE第一篇文章---如何看懂网上搜索到的VUE代码或文章---使用VUE的三种模式:

    小白学习VUE第一篇文章---如何看懂网上搜索到的VUE代码或文章---使用VUE的三种模式: 直接引用VUE; 将vue.js下载到本地后本目录下使用; 安装Node环境下使用; ant-desig ...

  2. 【2012.1.24更新】不要再在网上搜索eclipse的汉化包了!

    转自:http://blog.csdn.net/gqqnb/article/details/6412364 2012.1.24更新 增加了“安装方法” eclipse是一个程序开发平台,它本身并不限制 ...

  3. sqlserver2000 数据库分页查询[根据网上搜索到得sql修改,亲测,可用]

    SELECT TOP 页大小 * FROM TestTable WHERE (ID > (SELECT case when count(0) < 页大小 then 0 else MAX(i ...

  4. 网上搜索到的 比较好的mysql查询语句练习题

    Sutdent表的定义 字段名 字段描述 数据类型 主键 外键 非空 唯一 自增 Id 学号 INT(10) 是 否 是 是 是 Name 姓名 VARCHAR(20) 否 否 是 否 否 Sex 性 ...

  5. Google和Baidu常用的搜索技巧--转

    原文链接:http://mp.weixin.qq.com/s?__biz=MjM5NTY0MTY1OQ==&mid=2654509772&idx=1&sn=754454e374 ...

  6. 用jsonp实现搜索框功能

    用jsonp实现搜索框功能 前面的话: 在上周本来想发一篇模仿必应搜索的界面.但是在准备写文章之前突然想到前面学习了ajax技术,在这里我也让我的页面有一种不需要手动刷新就能获取到数据.但是发现用前面 ...

  7. 利用Solr服务建立的站内搜索雏形---solr1

    最近看完nutch后总感觉像好好捯饬下solr,上次看到老大给我展现了下站内搜索我便久久不能忘怀.总觉着之前搭建的nutch配上solr还是有点呆板,在nutch爬取的时候就建立索引到solr服务下, ...

  8. Google搜索的几个使用技巧——让你的搜索结果更准确

    对于软件开发人员来说,不知道的内容在网上搜索是再正常不过的了.今天同事在组内分享了几个谷歌搜索的使用技巧,在此自己总结一下,希望可以帮到更多人. 在此之前先要唠叨几句,什么时候用百度,什么时候用谷歌? ...

  9. Everything文件名实时搜索||解决局域网文件共享问题

    内容概要:Everything中文版下载地址及使用.用Everything轻松解决局域网文件共享问题.Everything语言设置问题 另:Everything只支持NTFS格式的磁盘(工作原理的缘故 ...

随机推荐

  1. 在FASTBuild中使用Caching

    上一篇:初识FASTBuild 在FASTBuild中使用缓存只需要注意三个环节: 一.设置编译选项 对于GCC\SNC\Clang编译器,没有特殊的要求 对于MSVC编译器,必须设置/Z7调试模式. ...

  2. 【Java】Java_07 浮点型

    浮点型 类型 占用存储空间 表数范围 Float 4字节 -3.403E38~3.403E38 Double 8字节 -1.798E308~1.798E308 float类型又被称作单精度类型,尾数可 ...

  3. 【DB2】经典SQL写法

    1.环境准备 CREATE TABLE DataInfo( ID_1 ), ID_2 ) ) INSERT INTO DataInfo VALUES('A','Oracle'); INSERT INT ...

  4. MySql常用函数数学函数、加密函数等(转—收藏)

        MySql函数众多,这里只是列举了一部分常用的函数.   一.数学函数 ABS(x)                                         // 返回x的绝对值 BI ...

  5. 【SSH网上商城项目实战30】项目总结(附源码下载地址)

    项目基本完成了,加上这个总结,与这个项目相关的博客也写了30篇了,积少成多,写博客的过程是固化思路的一个过程,对自己很有用,同时也能帮助别人.顺便说个题外话,在学习的过程中肯定会遇到很多异常出现,我们 ...

  6. 自己学Docker:4.開始了解Docker的工作模式

    上一章在学习中有2个疑问: 怎样保存我们在容器里的改动? 假设apt-get假设不能安装时,怎样在Docker中安装软件? 关于run创建的容器问题 对于第一个问题.原来每次运行(当非root用户时, ...

  7. JAVA WEB项目开发案例精粹

    http://www.blogjava.net/zongbao/archive/2012/07/24/383884.htmlJAVA WEB项目开发案例精粹.pdf main Alt + / => ...

  8. ConcurrentHashMap的JDK1.8实现

    今天我们介绍一下ConcurrentHashMap在JDK1.8中的实现.基本结构 ConcurrentHashMap在1.8中的实现,相比于1.7的版本基本上全部都变掉了.首先,取消了Segment ...

  9. NPOI读取操作excel

    .读取using (FileStream stream = new FileStream(@"c:\客户资料.xls", FileMode.Open, FileAccess.Rea ...

  10. js中级系列:模块化(转载 学习中。。。。)

    从 CommonJS 到 Sea.js https://github.com/seajs/seajs/issues/269 CMD(Common Module Definition) 模块定义规范 h ...