1

以下示例比较简单,只是将抓取到的数据简单的打印出来。

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <pcap.h>  



#define MAXBYTE2CAPTURE 2048  
      
void processPacket(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet) 
{  
    unsigned int i = 0;
    int *counter = (int *)arg;  
      
    printf("Packet Count: %d\n", ++(*counter));  
    printf("Received Packet Size: %d\n", pkthdr->len);  
    printf("Payload:\n");

    for (i = 0; i < pkthdr->len; i++) {  
        if (isprint(packet[i]))  
            printf("%c ", packet[i]);  
        else   
            printf(". ");
      
        if ((i % 16 == 0 && i != 0) || i == pkthdr->len-1)  
            printf("\n");    
    }

    return;  
}  
      
int main(int argc, char **argv) 
{
    int i = 0, count = 0;  
    pcap_t *descr = NULL;  
    char errbuf[PCAP_ERRBUF_SIZE] = {0};
    char *device = NULL;
     
    /* Get the name of the first device suitable for capture */  
    device = pcap_lookupdev(errbuf);  
      
    printf("Opening device %s\n", device);  
      
    /* Open device in promiscuous mode */  
    descr = pcap_open_live(device, MAXBYTE2CAPTURE, 1, 512, errbuf);  
      
    /* Loop forever & call processPacket() for every received packet */  
    pcap_loop(descr, -1, processPacket, (u_char *)&count);  
      
    return 0;
}

第二个示例解析了包中的数据协议。

#include <netinet/if_ether.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <pcap.h>



void tcp_packet_callback(unsigned char *argument, const struct pcap_pkthdr *pcap_header,
                            const unsigned char *packet_content) 
{
    struct tcphdr *tcpptr = (struct tcphdr *)(packet_content + 14 + 20);

    printf("----tcp protocol-----\n");
    printf("source port: %d\n", ntohs(tcpptr->source));
    printf("dest port: %d\n", ntohs(tcpptr->dest));

    printf("sequence number: %u\n", ntohl(tcpptr->seq));
    printf("acknowledgement number: %u\n", ntohl(tcpptr->ack_seq));
    printf("header length: %d\n", tcpptr->doff*4);
    printf("check sum: %d\n", ntohs(tcpptr->check));
    printf("window size: %d\n", ntohs(tcpptr->window));
    printf("urgent pointer: %d\n", ntohs(tcpptr->urg_ptr));

    return;
}

void ip_packet_callback(unsigned char *argument, const struct pcap_pkthdr *pcap_header,
                        const unsigned char *packet_content) 
{
    struct in_addr s, d;
    struct iphdr *ipptr;
    ipptr = (struct iphdr *)(packet_content + 14);

    printf("-----IP Protocol (network layer)-----\n");
    printf("version: %d\n", ipptr->version);
    printf("header length: %d\n", ipptr->ihl*4);
    printf("tos: %d\n", ipptr->tos);
    printf("total length: %d\n", ntohs(ipptr->tot_len));
    printf("identification: %d\n", ntohs(ipptr->id));
    printf("offset: %d\n", ntohs((ipptr->frag_off & 0x1fff) * 8));
    printf("TTL: %d\n", ipptr->ttl);
    printf("checksum: %d\n", ntohs(ipptr->check));
    printf("protocol: %d\n", ipptr->protocol);
    s.s_addr=ipptr->saddr;
    d.s_addr=ipptr->daddr;
    printf("source address: %s\n", inet_ntoa(s));
    printf("destination address: %s\n", inet_ntoa(d));

    switch(ipptr->protocol) {
    case 6:
        printf("tcp protocol\n");
        tcp_packet_callback(argument, pcap_header, packet_content);
        break;
    case 1:
        printf("icmp protocol\n");
        break;
    case 17:
        printf("udp protocol\n");
        break;
    default:
        break;
    }

    return;
}

void arp_packet_callback(unsigned char *argument, const struct pcap_pkthdr *pcap_header,
                const unsigned char *packet_content) 
{
    printf("------ARP Protocol-------\n");

    return;
}

void ethernet_packet_callback(unsigned char *argument, const struct pcap_pkthdr *pcap_header,
                        const unsigned char *packet_content) 
{
    struct ethhdr *ethptr;
    struct iphdr *ipptr;
    unsigned char *mac;

    ethptr=(struct ethhdr *)packet_content;
    printf("\n----ethernet protocol(physical layer)-----\n");
    printf("MAC source Address:\n");
    mac = ethptr->h_source;
    printf("%02x:%02x:%02x:%02x:%02x:%02x\n", *mac, *(mac+1), *(mac+2), *(mac+3), *(mac+4), *(mac+5));
    printf("MAC destination Address:\n");
    mac = ethptr->h_dest;
    printf("%02x:%02x:%02x:%02x:%02x:%02x\n", *mac, *(mac+1), *(mac+2), *(mac+3), *(mac+4), *(mac+5));
    printf("protocol: %04x\n", ntohs(ethptr->h_proto));

    switch(ntohs(ethptr->h_proto)) {
    case 0x0800:
        printf("this is a IP protocol\n");
        ip_packet_callback(argument,pcap_header,packet_content);
        break;
    case 0x0806:
        printf("this is a ARP protocol\n");
        arp_packet_callback(argument,pcap_header,packet_content);
        break;
    case 0x8035:
        printf("this is a RARP protocol\n");
        break;
    default:
        break;

    }

    return;
}

int main(int argc, char **argv) 
{
    pcap_t *pt;
    char *dev;
    char errbuf[128];
    struct bpf_program fp;
    bpf_u_int32 maskp, netp;
    int ret,i=0,inum;
    int pcap_time_out = 5;
    char filter[128] = {0};
    unsigned char *packet;
    struct pcap_pkthdr hdr;
    pcap_if_t *alldevs,*d;

    if(pcap_findalldevs(&alldevs, errbuf) == -1) {
        fprintf(stderr,"find interface failed!\n");
        return -1;
    }

    for(d = alldevs; d; d = d->next) {
        printf("%02d. %s", ++i, d->name);
        if(d->description)
            printf("(%s)\n", d->description);
        else
            printf("(no description available)\n");
    }

    if(i == 1) {
        dev = alldevs->name;
    } else {
        printf("input a interface(1-%d):", i);
        scanf("%d", &inum);
        if(inum < 1 || inum > i) {
            printf("interface number out of range\n");
            return -1;
        }

        for(d = alldevs, i = 1; i<inum; d = d->next, i++);

        dev = d->name;
    }

    /*
    dev=pcap_lookupdev(errbuf);
    if(dev==NULL){
         fprintf(stderr,"%s/n",errbuf);
         return;
    }
    */

    printf("dev: %s\n", dev);
    ret = pcap_lookupnet(dev, &netp, &maskp, errbuf);
    if(ret == -1) {
        fprintf(stderr,"%s\n", errbuf);
        return -1;
    }

    pt = pcap_open_live(dev, BUFSIZ, 1, pcap_time_out, errbuf);
    if(pt == NULL) {
        fprintf(stderr,"open error :%s\n", errbuf);
        return -1;
    }
    
    if(pcap_compile(pt, &fp, filter, 0, netp) == -1) {
        fprintf(stderr, "compile error\n");
        return -1;
    }

    if(pcap_setfilter(pt, &fp) == -1) {
        fprintf(stderr,"setfilter error\n");
        return -1;
    }
    pcap_loop(pt, -1, ethernet_packet_callback, NULL);

    /*
    while(1) {
         printf("wait packet:filter %s/n",filter);
         packet=(char *)pcap_next(pt,&hdr);
         if(packet==NULL)
              continue;
         else
              printf("get a packet/n");
    }
    */
    pcap_close(pt);

    return 0;
}

编译测试程序时,可能遇到以下的问题:

fatal error: pcap.h: No such file or directory compilation terminated.

解决方法:

sudo apt-get install libpcap0.8-dev

参考文章

PCAP数据包过滤器设置 及 过滤表达式语法
pcap学习
基于 linux 平台的 libpcap 源代码分析
libpcap使用


txgcwm
764 声望71 粉丝

Linux C/C++


引用和评论

0 条评论