libpcap库&接口函数

libpcap是一个网络数据包捕获函数库,功能非常强大,Linux下著名的tcpdump就是以它为基础的。Libpcap的工作原理可以描述为,当一个数据包到达网卡时,通过网络分接口(即旁路机制)将数据包发给BPF过滤器,匹配通过的数据包可以被libpcap利用创建的套接字PF_PACKET从链路层驱动程序中获得。进而在用户空间提供独立于系统的用户级API接口。

转载整理至:

https://blog.csdn.net/htttw/article/details/7521053

https://www.jianshu.com/p/ed6db49a3428

https://www.ibm.com/developerworks/cn/linux/l-libpcap/

安装

http://www.tcpdump.org/下载libpcap(tcpdump的源码也可以从这个网站下载)解压。

./configure
make
sudo make install
sudo ln -s /usr/local/lib/libpcap.so.1 /usr/lib/libpcap.so.1

libpcap常用接口

查找网络设备

函数名称:char *pcap_lookupdev(char *errbuf)

函数功能:用于返回可被pcap_open_live()或pcap_lookupnet()函数调用的网络设备名指针。

返回值:如果函数出错,则返回NULL,同时errbuf中存放相关的错误消息。

获取数据包捕获描述字

函数名称:pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)

函数功能:获得用于捕获网络数据包的数据包捕获描述字。

参数说明:device参数为指定打开的网络设备名。snaplen参数定义捕获数据的最大字节数。Promisc 指定是否将网络接口置于混杂模式。to_ms参数指*定超时时间(毫秒)。ebuf参数则仅在pcap_open_live()函数出错返回NULL时用于传递错误消息。

释放网络接口

函数名称:void pcap_close(pcap_t * p)

函数功能:该函数用于关闭pcap_open_live()获取的pcap_t的网络接口对象并释放相关资源。

捕获并处理数据包

函数名称:int pcap_dispatch(pcap_t *p, int cnt,pcap_handler callback, u_char *user)

函数功能:捕获并处理数据包。

参数说明:cnt参数指定函数返回前所处理数据包的最大值。cnt= -1表示在一个缓冲区中处理所有的数据包。cnt=0表示处理所有数据包,直到产生以下错误之一:读取到EOF;超时读取。callback参数指定一个带有三个参数的回调函数,这三个参数为:一个从pcap_dispatch()函数传递过来的u_char指针,一个pcap_pkthdr结构的指针,和一个数据包大小的u_char指针。

返回值:如果成功则返回读取到的字节数。读取到EOF时则返回零值。出错时则返回-1,此时可调用pcap_perror()或pcap_geterr()函数获取错误消息。

捕获和处理数据包

函数名称:int pcap_loop(pcap_t *p, int cnt,pcap_handler callback, u_char *user)

函数功能:功能基本与pcap_dispatch()函数相同,只不过此函数在cnt个数据包被处理或出现错误时才返回,但读取超时不会返回。而如果为pcap_open_live()函数指定了一个非零值的超时设置,然后调用pcap_dispatch()函数,则当超时发生时pcap_dispatch()函数会返回。cnt参数为负值时pcap_loop()函数将始终循环运行,除非出现错误。

获取下一个数据包

函数名称:u_char pcap_next(pcap_t p, struct pcap_pkthdr *h)

函数功能:返回指向下一个数据包的u_char指针

编译字串至过滤程序

函数名称:int pcap_compile(pcap_t *p, struct bpf_program *fp,char *str, int optimize, bpf_u_int32 netmask)

函数功能:将str参数指定的字符串编译到过滤程序中。

参数说明:fp是一个bpf_program结构的指针,在pcap_compile()函数中被赋值。optimize参数控制结果代码的优化。netmask参数指定本地网络的网络掩码。

指定过滤程序

函数名称:int pcap_setfilter(pcap_t p, struct bpf_program fp)

函数功能:指定一个过滤程序。

参数说明:fp参数是bpf_program结构指针,通常取自pcap_compile()函数调用。

返回值:出错时返回-1;成功时返回0

获取数据链路层类型

函数名称:int pcap_datalink(pcap_t *p)

函数功能:返回数据链路层类型,例如DLT_EN10MB

显示错误消息

函数名称:void pcap_perror(pcap_t *p, char *prefix)

函数功能:在标准输出设备上显示最后一个pcap库错误消息。以prefix参数指定的字符串为消息头。

网络嗅探器(sniffer)简例

#include <pcap.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
 
void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
{
  int * id = (int *)arg;
  
  printf("id: %d\n", ++(*id));
  printf("Packet length: %d\n", pkthdr->len);
  printf("Number of bytes: %d\n", pkthdr->caplen);
  printf("Recieved time: %s", ctime((const time_t *)&pkthdr->ts.tv_sec)); 
  
  int i;
  for(i=0; i<pkthdr->len; ++i)
  {
    printf(" %02x", packet[i]);
    if( (i + 1) % 16 == 0 )
    {
      printf("\n");
    }
  }
  
  printf("\n\n");
}
 
int main()
{
  char errBuf[PCAP_ERRBUF_SIZE], * devStr;
  
  /* get a device */
  devStr = pcap_lookupdev(errBuf);
  
  if(devStr)
  {
    printf("success: device: %s\n", devStr);
  }
  else
  {
    printf("error: %s\n", errBuf);
    exit(1);
  }
  
  /* open a device, wait until a packet arrives */
  pcap_t * device = pcap_open_live(devStr, 65535, 1, 0, errBuf);
  
  if(!device)
  {
    printf("error: pcap_open_live(): %s\n", errBuf);
    exit(1);
  }
  
  /* wait loop forever */
  int id = 0;
  pcap_loop(device, -1, getPacket, (u_char*)&id);
  
  pcap_close(device);
 
  return 0;
}
/* Makefile */
all: test.c
  gcc -g -Wall -o sniff sniff.c -lpcap

clean:
  rm -rf *.o test

Updated: 2019年5月23日 — 上午1:01

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据