博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从网上搜索到的一些关于pcap源代码,入门级的
阅读量:4028 次
发布时间:2019-05-24

本文共 9284 字,大约阅读时间需要 30 分钟。

#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 "

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

转载地址:http://vtpbi.baihongyu.com/

你可能感兴趣的文章
转载一个webview开车指南以及实际项目中的使用
查看>>
关于activity保存页面状态的两个方法
查看>>
android中对于非属性动画的整理
查看>>
一个简单的TabLayout的使用
查看>>
关于let{a}=B出现的解构赋值
查看>>
ReactNative使用Redux例子
查看>>
Promise的基本使用
查看>>
android给文字加边框(修改不能居中的问题)
查看>>
coursesa课程 Python 3 programming course_2_assessment_1
查看>>
coursesa课程 Python 3 programming 统计文件有多少单词
查看>>
coursesa课程 Python 3 programming 输出每一行句子的第三个单词
查看>>
coursesa课程 Python 3 programming Dictionary methods 字典的方法
查看>>
Returning a value from a function
查看>>
coursesa课程 Python 3 programming Functions can call other functions 函数调用另一个函数
查看>>
coursesa课程 Python 3 programming Tuple Assignment with Unpacking
查看>>
coursesa课程 Python 3 programming The while Statement
查看>>
course_2_assessment_6
查看>>
coursesa课程 Python 3 programming course_2_assessment_7 多参数函数练习题
查看>>
coursesa课程 Python 3 programming 排序函数sorted的可选参数
查看>>
coursesa课程 Python 3 programming course_2_assessment_8 sorted练习题
查看>>