Winpcap常用函数解析

2023-05-16

1. int pcap_findalldevs(pcap_if_t **, char *)
    说明:用来获得网卡的列表
    参数:指向pcap_if_t**类型的列表的指针的指针; char型指针,当打开列表错误时返回错误信息
    返回值: 为int型,当显示列表失败时返回-1
pcap_if_t 是pcap_if 重命名而来:typedef struct pcap_if pcap_if_t;
pcap_if结构体如下:
struct pcap_if
{
        struct pcap_if *next;              
        char *name;               
        char *description;       
        struct pcap_addr *addresses;    //pcap_addr 结构体
        bpf_u_int32 flags;       
};
pcap_addr 结构体如下:
struct pcap_addr
{
         struct pcap_addr *next;
         struct sockaddr *addr;               
         struct sockaddr *netmask;       
        struct sockaddr *broadaddr;       
        struct sockaddr *dstaddr;       
};
举例:
    pcap_if_t *alldevs;
    pcap_if_t *d;
    char errbuf[64];
    if (pcap_findalldevs(&alldevs, errbuf) == -1)
    {
      fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
      exit(1);
   }
for(d=alldevs;d;d=d->next)
{
    printf("%d. %s", ++i, d->name);
    if (d->description)
       printf(" (%s)\n", d->description);
   else        
      printf(" (No description available)\n");
}
用pcap_findalldevs不能获得网卡的MAC,有两种方法可以实现,一、向自己发送arp包,二、使用IPHelp的API可以获得。
2. void   pcap_freealldevs(pcap_if_t *)
说明:与int pcap_findalldevs(pcap_if_t **, char *)配套使用,当不再需要网卡列表时,用此函数free释放空间
参数:打开网卡列表时申请的pcap_if_t型的指针
举例:
   pcap_freealldevs(alldevs);
3. pcap_t    *pcap_open_live(const char * device, int snaplen, int promisc, int to_ms, char ebuf *)
说明:被用来得到一个包抓取得描述符
参数:
      device是一个指出要抓取的网络设备的字符串。
      snaplen指明最大可抓取的字节长度。
      promisc置位表明该接口要被设置成混杂模式。
      to_ms以毫秒为单位设置超时时间。当在超时时间内网卡上没有数据到来时对网卡的读操作将返回(如   pcap_dispatch() or pcap_next_ex()等函数)。
     ebuf被用来存放当pcap_open_live()调用失败时,返回的错误字符串。
    返回值: pcap_t型的指针,供pcap_dispatch() or pcap_next_ex()等函数调用。
pcap_t的结构体:
struct pcap {
     #ifdef WIN32
        ADAPTER *adapter;
        LPPACKET Packet;
        int timeout;
        int nonblock;
     #else
        int fd;
    #endif           
        int snapshot;
        int linktype;
        int tzoff;               
        int offset;               
        struct pcap_sf sf;
        struct pcap_md md;
         int bufsize;              
        u_char *buffer;
        u_char *bp;
        int cc;           //Place holder for pcap_next().
        u_char *pkt;               //Placeholder for filter code if bpf not in kernel.
        struct bpf_program fcode;
        char errbuf[PCAP_ERRBUF_SIZE + 1];
        int dlt_count;
        int *dlt_list;
   #ifdef REMOTE
      
        int rmt_clientside;   
        SOCKET rmt_sockctrl;                //!< socket ID of the socket used for the control connection
        SOCKET rmt_sockdata;                //!< socket ID of the socket used for the data connection
        pthread_t rmt_threaddata;       //!< handle to the receiving thread, we need to kill it in case of 'pcap_clos()'
        int rmt_flags;                             //!< we have to save flags, since they are passed by the pcap_open_live(), but they are used by the pcap_start capture()
        int rmt_capstarted;                        //!< 'true' if the capture is already started (needed to knoe if we have to call the pcap_startcapture()
        struct pcap_pkthdr pcap_header;        //!< In Linux, you have to copy the packet headers another time before giving them to the user
   #endif               
};
举例:
   
    if ( (adhandle= pcap_open_live(d->name, // name of the device
           65536, // portion of the packet to capture. 65536 grants that the whole packet will be captured on all the MACs.
                        1,         // 混杂模式
                1000,      // 设置超时时间,亳秒为单位
                errbuf     // 发生错误时存放错误内容的缓冲区
                ) ) == NULL)
    {
        fprintf(stderr,

"\nUnable to open the adapter. %s is not supported by WinPcap\n");
        pcap_freealldevs(alldevs);
        return -1;
}
4. int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
说明:捕获数据包;不会响应pcap_open_live()中设置的超时时间
参数:
        p是由pcap_open_live()返回的所打开网卡的指针
        cnt用于设置所捕获数据包的个数
        packet_handler是与void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)配合使用的一个参数。回调函数。
        user
值一般为NULL
举例:
pcap_loop(adhandle, 0, packet_handler, NULL);
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
struct tm *ltime;
char timestr[16];
ltime=localtime(&header->ts.tv_sec);   
strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len);

}
5. int pcap_dispatch(pcap_t * p, int cnt, pcap_handler, u_char *user)
说明:捕获数据包。可以不被阻塞
参数:与pcap_loop()相同
pcap_dispatch(...)pcap_loop(...)的比较:
    一旦网卡被打开,旧可以调用pcap_dispatch() pcap_loop()进行数据的捕获,这两个函数的功能十分相似,不同的是pcap_ dispatch()可以不被阻塞,而pcap_loop()在没有数据流到达时将阻塞。在这个简单的例子里用
pcap_loop()就足够了,而在一些复杂的程序里往往用pcap_dispatch()。这两个函数都有返回的参数,一个指向某个函数(该函数用来接受数据如该程序中的packet_handler)的指针
libpcap调用该函数对每个从网上到来的数据包进行处理和接收数据包。另一个参数是带有时间戳和包长等信息的头部,最后一个是含有所有协议头部数据报的实际数据。注意MAC的冗余校验码一般不出现,因为当一个桢到达并被确认后网卡就把它删除了,同样需要注意的是大多数网卡会丢掉冗余码出错的数据包,所以WinPcap一般不能够捕获这些出错的数据报。

6. int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, u_char **pkt_data);
说明:捕获数据包,与pcap_ dispatch()   pcap_loop()很相似。pcap_next_ex()允许直接调用来接收包,它的参数和pcap_loop()相同:有一个网卡描述副,和两个指针,这两个指针会被初始化并返回给用户,一个是pcap_pkthdr结构,另一个是接收数据的缓冲区。

参数:
       p
是由pcap_open_live()返回的所打开网卡的指针
       pcap_pkthdr型的结构体,存储时间,包的长度
        pkt_data存储数据包的内容,为一个char型数组
struct pcap_pkthdr
{
        struct timeval ts;       
        bpf_u_int32 caplen;       
        bpf_u_int32 len;       
};
返回值:当等于1时成功;等于0时超时;等于-1时说明发生错误,错误信息用pcap_geterr(adhandle)获得
举例:(最重要的一段代码)
#define LINE_LEN 16
main(int argc, char **argv)
{
       
        pcap_if_t *alldevs, *d;
        pcap_t *fp;
        u_int inum, i=0;
        char errbuf[PCAP_ERRBUF_SIZE];
        int res;
        struct pcap_pkthdr *header;
        u_char *pkt_data;
        printf("pktdump_ex: prints the packets of the network using WinPcap.\n");
        printf("\t Usage: pktdump_ex [-n adapter] | [-f file_name]\n\n");
        if(argc < 3)
        {
                if (pcap_findalldevs(&alldevs, errbuf) == -1)
                {
                        fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
                        exit(1);
                }
                for(d=alldevs; d; d=d->next)
                {
                        printf("%d. %s", ++i, d->name);
                        if (d->description)
                                printf(" (%s)\n", d->description);
                        else
                                printf(" (No description available)\n");
                }
                if(i==0)
                {
                        printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
                        return -1;
                }
                printf("Enter the interface number (1-%d):",i);
                scanf("%d", &inum);
                if(inum < 1 || inum > i)    //
选择网卡
                {
                        printf("\nInterface number out of range.\n");
                       
                        pcap_freealldevs(alldevs);
                        return -1;
                }
                 for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);   //
跳转到指定的网卡
                 if ( (fp= pcap_open_live(d->name, 100, 1, 20, errbuf) ) == NULL)
                {
                        fprintf(stderr,"\nError opening adapter\n");
                        return -1;
                }
        }
        else
       {
                 switch (argv[1] [1])  

{      
                     case 'n':
                        {
                                if ( (fp= pcap_open_live(argv[2], 100, 1, 20, errbuf) ) == NULL)     //Open a physical device
                                {
                                        fprintf(stderr,"\nError opening adapter\n");
                                        return -1;
                                }
                                 break;
                        }
                     case 'f':
                        {
                                 if ( (fp = pcap_open_offline(argv[2], errbuf) ) == NULL)   
                                {
                                        fprintf(stderr,"\nError opening dump file\n");
                                        return -1;
                                }
                                break;
                        }
                        
                }
        }
        while((res = pcap_next_ex( fp, &header, &pkt_data)) >= 0)
        {
                if(res == 0)
                        continue;
                printf("%ld:%ld (%ld)\n", header->ts.tv_sec, header->ts.tv_usec, header->len);             
                for (i=1; (i < header->caplen + 1 ) ; i++)
                {
                        printf("%.2x ", pkt_data[i-1]);
                        if ( (i % LINE_LEN) == 0) printf("\n");
                }  
                printf("\n\n");               
        }
        if(res == -1)
  {
                printf("Error reading the packets: %s\n", pcap_geterr(fp));
                return -1;
        }
        return 0;
}
7. int pcap_compile(pcap_t *p, struct bpf_program *fp, char *str, int optimize,bpf_u_int32 netmask)
说明:编译一个过滤设备,它通过一个高层的boolean型变量和字串产生一系列的能够被底层驱动所解释的二进制编码。boolean表示语法能够在这个文件的过滤表示语法中找到。与pcap_setfilter()配合使用。
参数:
        p是打开网卡时返回的网卡指针
        fp用于与pcap_setfilter()传递过滤信息。
        str是一个字符串。
        optimize指明是否需要优化编译结果。
       netmask子网掩码
返回值:
       发生错误是返回-1
举例:
 if(d->addresses != NULL)
         netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_addr;
 else
         netmask=0xffffff; 
 if(pcap_compile(adhandle, &fcode, "ip and tcp", 1, netmask) <0 )
 {
       fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n");
        pcap_freealldevs(alldevs);
       return -1;
 }
 if(pcap_setfilter(adhandle, &fcode)<0)
 {
       fprintf(stderr,"\nError setting the filter.\n");
        pcap_freealldevs(alldevs);
       return -1;
}
8. int pcap_setfilter ( pcap_t *p, struct bpf_program * fp ) 
说明:pcap_setfilter() 用来联系一个在内核驱动上过滤的过滤器,这时所有网络数据包都将流经过滤器,并拷贝到应用程序中。
参数:
        p是打开网卡时返回的网卡指针
        fp是pcap_compile()传递过来的参数
返回值:
       错误时返回-1
9. int pcap_sendpacket(pcap_t *p, u_char *buf, int size)
Ø         说明:手工发送一个数据包了。这个函数需要的参数:一个装有要发送数据的缓冲区,要发送的长度,和一个适配器。注意缓冲区中的数据将不被内核协议处理,只是作为最原始的数据流被发送,所以我门必须填充好正确的协议头以便正确的将数据发送。
参数:
        p是打开网卡时返回的网卡指针
        buf是发送数据包的内容缓冲区首地址
       size是发送数据包的大小
举例:
void usage();
void main(int argc, char **argv)
{
pcap_t *fp;
char error[PCAP_ERRBUF_SIZE];
u_char packet[100];
int i;
if (argc != 2) 
{
    printf("usage: %s inerface", argv[0]);
    return;
}
if((fp = pcap_open_live(argv[1], 100, 1, 1000, error) ) == NULL)
{
    fprintf(stderr,

"\nError opening adapter: %s\n", error);
    return;
}

packet[0]=1;
packet[1]=1;
packet[2]=1;
packet[3]=1;
packet[4]=1;
packet[5]=1;


packet[6]=2;
packet[7]=2;
packet[8]=2;
packet[9]=2;
packet[10]=2;
packet[11]=2;


for(i=12;i<100;i++){
    packet[i]=i%256;
}

pcap_sendpacket(fp, packet, 100); //
发送原始的数据包
return;
}
10.
发送数据包有关的几个函数
pcap_send_queue* pcap_sendqueue_alloc(u_int memsize);
说明:给数据包队列分配空间
参数:
        memsize队列缓冲区的大小
返回值:
       pcap_send_queue指针
struct pcap_send_queue
{
        u_int maxlen;       
        u_int len;                        //< Current size of the queue, in bytes.
        char *buffer;                //< Buffer containing the packets to be sent.
};
举例:
squeue = pcap_sendqueue_alloc(caplen);
int pcap_sendqueue_queue(pcap_send_queue* queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
说明:填充队列
参数:
        queue 是由pcap_sendqueue_alloc()返回的指针
         pkt_header是数据包头
        pkt_data是数据包内容缓冲区指针
返回值:错误是返回-1 
举例:
    if(pcap_sendqueue_queue(squeue, pktheader, pktdata) == -1)
 {
        printf("Warning: packet buffer too small, not all the packets will be sent.\n");
        break;
 }
u_int pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue* queue, int sync)
说明:发送队列数据
参数:
         pcap_t        pcap_open_live()函数打开的网卡指针
        queue 是由pcap_sendqueue_alloc()返回的指针 
        sync
是同步设置。如果非零,那么发送将是同步的,这将站用很大的CPU资源,因为发生在内核驱动的同步发送是通过"brute force" loops的,但是一般情况下能够精确到微秒。
返回值:错误是返回-1
举例:
    if((res = pcap_sendqueue_transmit(outdesc, squeue, sync)) < squeue->len)
    {
      
 printf("An error occurred sending the packets: %s. Only %d bytes were sent\n", error,res);
 }
void pcap_sendqueue_destroy(pcap_send_queue* queue);
说明:释放队列
参数:
       queue 是由pcap_sendqueue_alloc()返回的指针


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Winpcap常用函数解析 的相关文章

随机推荐

  • 手把手教你VMware虚拟机详细安装Debian 11 图文教程

    目录 一 准备工作 二 创建安装Debain的虚拟机 三 安装 Debian 11 过程 一 准备工作 1 虚拟机软件 VMware 16 https www vmware com go getworkstation win 2 Debia
  • Python3利用Pandas类库生成多Sheet的Excel

    一 Pandas Pandas 是 Python 语言的一个扩展程序库 xff0c 可以对各种数据进行运算操作 xff0c 比如归并 再成形 选择 xff0c 还有数据清洗和数据加工特征 官方地址 xff1a https pandas py
  • Debian 11 安装并开启SSH服务实现允许root用户使用SecureCRT远程登录

    虚拟机安装完成Debian11系统后 xff0c 系统默认是没有安装SSH服务 xff0c 如需要开启远程登录则需要安装相应的服务 登录系统后切换至Root用户身份并执行下面相关操作 一 更新Debian系统数据软件源 apt get up
  • Java利用poi 3.9对excel进行读写操作的工具类支持多Sheet

    一 什么是POI POI全称PoorObfuscation Implementation xff0c 是Apache组件的一个开源项目 xff0c 可以对微软的Office一系列办公软件进行读写操作 官方下载地址 xff1a https p
  • JAVA利用POI scratchpad 5.2.1 将Word文档doc格式转换成HTML 格式 含文档里面图片

    一 POM文件 lt dependency gt lt groupId gt org apache poi lt groupId gt lt artifactId gt poi scratchpad lt artifactId gt lt
  • Centos7搭建安装freeswitch1.6

    前言 xff1a 请各大网友尊重本人原创知识分享 xff0c 谨记本人博客 xff1a 南国以南i 介绍 xff1a freeswitch可集成ASR 语音识别 和TTS 文本转语音 创建智能电话机器人和用户通话 xff0c 可用于问卷调查
  • 树莓派安装远程桌面(XRDP)服务

    首先试用了一下VNC xff0c 发现质量惨不忍睹 xff0c 明明是在局域网内啊 于是打算安装XRDP服务 xff0c 网上各种文章都有 xff0c 有的说需要先安装tightVNC 参考了 xff1a http shumeipai nx
  • 关于ubuntu20.04中安装ros的一些package时出现“unable to locate”的问题记录

    在运行ros仿真时出现如下错误 xff1a 提示缺少 gmapping的包 xff0c 直接下载包 xff1a sudo apt get install ros noetic gmapping 结果提示 xff1a Unable to lo
  • Linux配置篇 | Ubuntu配置apt镜像源

    以下以 Ubuntu18 04 LTS 为例 xff0c 也适用于 Ubuntu 其他版本 一 修改apt镜像源 xff08 1 xff09 备份apt配置文件 xff1a cp etc apt sources list etc apt s
  • 多种缺陷管理软件简介

    缺陷管理工具 xff1a 1 Bugzilla 2 Bugfree 3 TestDirector xff08 Quality Center xff09 4 ClearQuest 5 JIRA 6 Mantis 7 Bugzero 8 Bug
  • 线程与进程之间的共享资源

    线程和进程之间的共享资源方式 进程之间的共享资源的方式 1 消息队列 2 共享内存 3 管道 xff08 有名管道 无名管道 xff09 4 信号 5 套接字 同一个进程的不同线程之间可以共享的资源 1 堆 xff0c 由于堆是在进程启动的
  • Redis基本知识

    总结 基础知识 基础命令 1 xff09 测试Redis性能 2 xff09 Redis沟通命令 xff0c 查看状态 解释 xff1a 输入ping xff0c redis给我们返回PONG xff0c 表示redis服务运行正常 3 x
  • redis的配置文件

    回顾 redis的配置文件 1 redis安装完成之后 xff0c 在redis的根沐会提供一个配置文件 redis conf xff1b redis服务可以参考配置文件中的参数进行运行 xff1b 只有启动redis服务器指定使用的配置文
  • VSCode 配置 C++ 环境

    1 1 MinGW 编译套件 MinGW 提供了一套简单方便的 Windows 下的基于 GCC 程序开发环境 xff0c 并且 收集了一系列免费的 Windows 使用的头文件和库文件 它整合了 GNU 的工具集 xff0c 特别是 GN
  • C++中string与char*相互转换

    C 43 43 中string与char 相互转换 一 string转换为char 有3中方法 xff1a 1 data string str 61 34 good boy 34 const char p 61 str data 2 c s
  • Python hex()十六进制转换

    Python hex 函数用于将整数转换为以 0x 为前缀的小写十六进制字符串 xff1a print hex 255 decimal十进制 print hex 0b111 binary二进制 print hex 0o77 octal八进制
  • rocksdb的原子flush

    如果始终启用 WAL xff0c 则无需使用原子刷新选项 启用 WAL 后 xff0c 单个 WAL 文件用于捕获对所有列族的写入 因此 xff0c 恢复的数据库 xff08 通过在崩溃 恢复路径中重播 WAL 日志 xff09 保证在所有
  • rocksdb的设置选项和基本调整

    除了在 RocksDB 上使用基本操作编写代码外 xff0c 您可能还对如何调整 RocksDB 以实现所需的性能感兴趣 在本页中 xff0c 我们将介绍如何进行初始设置 xff0c 该设置应该足以满足许多用例的需求 RocksDB 有许多
  • rocksdb的wal配置

    wal配置 数据库 xff1a xff1a wal dir DBOptions wal dir设置 RocksDB 存储预写日志文件的目录 xff0c 该目录允许将 WAL 存储在与实际数据不同的目录中 数据库 xff1a xff1a WA
  • Winpcap常用函数解析

    1 int pcap findalldevs pcap if t char 说明 xff1a 用来获得网卡的列表 参数 xff1a 指向pcap if t 类型的列表的指针的指针 char型指针 当打开列表错误时返回错误信息 返回值 为in