/*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. docker入门——简介

    从这里起航 本系列有感于<第一本Docker书>,当我拿到这本书时感觉如获至宝. 为了培养自己对docker的兴趣,不断鞭策自己,我决定开始写这个系列的博客——<站在蓝鲸的背上思考& ...

  2. 在线激活Pycharm(亲测有效)

    (1)在激活界面的License server输入:http://idea.liyang.io:或者:点击help→Register→License sever ,输入http://idea.liya ...

  3. InputStream写文件出现大量NUL

    写文件大家出现最多的是汉字知码之类的问题,今天不是乱码问题,是出现在大量空字符,用记事本打开是不可见的.如果用NodePad++打开则会显示NUL 问题分题: 刚开始以为是编码问题,试了几个编码发现问 ...

  4. 剑指Offer-正则表达式匹配(Python)

    1 题干内容 请实现一个函数用来匹配包括.和*的正则表达式.模式中的字符.表示任意一个字符,而*表示它前面的字符可以出现任意次(包含0次). 在本题中,匹配是指字符串的所有字符匹配整个模式. 例如,字 ...

  5. html 5 中的 6位 十六进制颜色码 代表的意思180313

    人的眼睛看到的颜色有两种: ⒈ 一种是发光体发出的颜色,比如计算机显示器屏幕显示的颜色: ⒉ 另一种是物体本身不发光,而是反射的光产生   的颜色,比如看报纸和杂志上的颜色. 我们又知道任何颜色都是由 ...

  6. MySQL学习总结(三)索引

    补充一下,上一章节中约束的一点东西.我们在为约束设置名称的时候(标识符)推荐写法“约束缩写_字段名”,这样让人看起来就会很清晰.例如:FK_Deptno,我们通过索引的名字就可以大概知道这是一个设置的 ...

  7. UDP与TCP报文格式,字段意义

    UDP报文 1.UDP有两个字段:数据字段和首部字段. 首部字段 首部字段很简单,只有8个字节,由4个字段组成,每个字段的长度都是两个字节.   1)源端口:源端口号.在需要对方回信时选用.不需要时可 ...

  8. eslint 人性化配置

    错误列表: http://www.zystudios.cn/blog/post/70.Shtml 人性化一点.别老虐我啊晓梦大师 module.exports = { root: true, pars ...

  9. Shift Register

    /*************************************************** /  Shift Register module /  Programing by seong ...

  10. Spring的AOP配置

    Spring的AOP配置 1.先写一个普通类: package com.spring.aop; public class Common {  public void execute(String us ...