WinPcap编程(一)

 

0.

按着文档顺序写的。

开发环境:win10+VS2013。

配置WinPcap环境就不多说。直接给网址:http://blog.sina.com.cn/s/blog_57432f380101qh3n.html

内容大多是函数解释+碰到的问题的解决方案。学习&&警示。

 

1.获取适配器列表

  获取适配器的目的是:获取本机有哪些适配器,便于之后选择用哪个适配器抓包。

  首先,先了解一个数据类型pcap_if/pcap_if_t,这是一个链表结构,用来存储本机的所有适配器。

struct pcap_if {
 struct pcap_if  *next;
 char  *name;              
 char  *description;         
 struct pcap_addr  *addresses;
 bpf_u_int32  flags;         
};

typedef struct pcap_if pcap_if_t; 
View Code

备注:

  第一是一个pcap_if的链表指向下一个设备接口;

  第二个是设备的实际的名字,这个名字是机器能识别的名字,供pcap_open_live()调用;

  第三个是设备的文本描述符,这个描述符就是人们能够识别的文本符号;有可能为null

  第四个是一个地址指针,指向的是一系列接口(pcap_addr)的第一个指针;

  第五个是一个标志位,目前这个标志位主要是不是loopback设备。

  

  然后,获取适配器列表的函数是:

int pcap_findalldevs_ex ( char * source ;

 struct pcap_rmauth * auth;

 pcap_if_t ** alldevs;

 char * errbuf;

)
View Code

备注:

  1.source可以使用上面设置好的source,也可以使用:PCAP_SRC_FILE_STRING 或者 PCAP_SRC_IF_STRING,分别是文件和接口的字符串。"file://", "rpcap://"

      2.auth是远程登录信息(pcap_rmauth),有用户名、密码、类型。用户名和密码都是字符指针,类型有:RPCAP_RMTAUTH_NULL  RPCAP_RMTAUTH_PWD。多为BULL。

      3.alldevs用于存储返回的接口信息。我们要事先定义pcap_if_t *alldevs,这是一个链表,存储接口信息。

      4.errbuf出错信息。

  5.返回值为0则顺利;-1代表出现错误。

 

  最后,释放设备函数:

void pcap_freealldevs (pcap_if_t *alldevsp)
View Code

  释放内存。

 

  原装代码:

#define WIN32
#include "pcap.h" 

void main()
{
    pcap_if_t *alldevs, *d;
    int i = 0;
    char errbuf[PCAP_ERRBUF_SIZE];
    /* PCAP_ERRBUF_SIZE =256在pcap.h中定义*/

    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) /* 这个API用来获得网卡的列表 */
    {
        fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
        //errbuf参数 当有异常情况发生时,这个参数会被PCAP填充为某3个特定的错误字串
        return;
    }

    /* 显示列表的响应字段的内容*/
    for (d = alldevs; d; d = d->next)
    {
        printf("%d. %s,%s\n", ++i, d->name,d->addresses);
        if (d->description)  {
            printf(" (%s)\n", d->description);
            //system("pause");
        }
        else  
            printf(" (No description available)\n");
    }
    if (i == 0)
    {
        printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
        return;
    }

    /*We don't need any more the device list. Free it */
    pcap_freealldevs(alldevs); 
    system("pause");
}
View Code

   

2.获取适配器的高级信息。

  每一个pcap_if_t中包含一个pcap_addr。pcap_addr中包含这个设备的高级信息。

  

struct pacap_addr{
struct pcap_addr  *next;
struct sockaddr  *addr;
struct sockaddr  *netmask;
struct sockaddr  *broadaddr;
struct sockaddr  *dstaddr;      /*destination*/
};
View Code

备注: 

  第二个,地址列表;

  第三个,掩码列表;

  第四个,广播地址列表;

  第五个,目的地址列表。

 

  然后,1中获得适配器列表的链表结构后,从头开始遍历,把pcap_if_t中pcap_addr的信息给输出出来就OK了。

  

#define WIN32
#include "pcap.h"

#ifndef WIN32
#include <winsock.h>
#include <wininet.h>
#include <ws2def.h>
#include<WS2tcpip.h>
#else
#include <winsock.h>
#endif


// 函数原型
void ifprint(pcap_if_t *d);
char *iptos(u_long in);
char* ip6tos(struct sockaddr *sockaddr, char *address, int addrlen);


int main()
{
    pcap_if_t *alldevs;
    pcap_if_t *d;
    char errbuf[PCAP_ERRBUF_SIZE + 1];
    char source[PCAP_ERRBUF_SIZE + 1];

    printf("Enter the device you want to list:\n"
        "rpcap://              ==> lists interfaces in the local machine\n"
        "rpcap://hostname:port ==> lists interfaces in a remote machine\n"
        "                          (rpcapd daemon must be up and running\n"
        "                           and it must accept 'null' authentication)\n"
        "file://foldername     ==> lists all pcap files in the give folder\n\n"
        "Enter your choice: ");

    fgets(source, PCAP_ERRBUF_SIZE, stdin);
    source[PCAP_ERRBUF_SIZE] = '\0';

    /* 获得接口列表 */
    if (pcap_findalldevs_ex(source, NULL, &alldevs, errbuf) == -1)
    {
        fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
        exit(1);
    }

    /* 扫描列表并打印每一项 */
    for (d = alldevs; d; d = d->next)
    {
        ifprint(d);
    }

    pcap_freealldevs(alldevs);

    system("pause");
    return 1;
}



/* 打印所有可用信息 */
void ifprint(pcap_if_t *d)
{
    pcap_addr_t *a;
    char ip6str[128];

    /* 设备名(Name) */
    printf("%s\n", d->name);

    /* 设备描述(Description) */
    if (d->description)
        printf("\tDescription: %s\n", d->description);

    /* Loopback Address*/
    printf("\tLoopback: %s\n", (d->flags & PCAP_IF_LOOPBACK) ? "yes" : "no");

    /* IP addresses */
    for (a = d->addresses; a; a = a->next) {
        printf("\tAddress Family: #%d\n", a->addr->sa_family);

        switch (a->addr->sa_family)
        {
        case AF_INET:
            printf("\tAddress Family Name: AF_INET\n");
            if (a->addr)
                printf("\tAddress: %s\n", iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr));
            if (a->netmask)
                printf("\tNetmask: %s\n", iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));
            if (a->broadaddr)
                printf("\tBroadcast Address: %s\n", iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));
            if (a->dstaddr)
                printf("\tDestination Address: %s\n", iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));
            break;

        case AF_INET6:
            printf("\tAddress Family Name: AF_INET6\n");
            if (a->addr)
                printf("\tAddress: %s\n", ip6tos(a->addr, ip6str, sizeof(ip6str)));
            break;

        default:
            printf("\tAddress Family Name: Unknown\n");
            break;
        }
    }
    printf("\n");
}
View Code
/* 将数字类型的IP地址转换成字符串类型的 */
#define IPTOSBUFFERS    12
char *iptos(u_long in)
{
    static char output[IPTOSBUFFERS][3 * 4 + 3 + 1];
    static short which;
    u_char *p;

    p = (u_char *)&in;
    which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
    sprintf_s(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
    return output[which];
}

char* ip6tos(struct sockaddr *sockaddr, char *address, int addrlen)
{
    socklen_t sockaddrlen;

#ifdef WIN32
    sockaddrlen = sizeof(struct sockaddr_in6);
#else
    sockaddrlen = sizeof(struct sockaddr_storage);
#endif


    if (getnameinfo(sockaddr,
        sockaddrlen,
        address,
        addrlen,
        NULL,
        0,
        NI_NUMERICHOST) != 0) address = NULL;

    return address;
}
辅助函数,IP转字符串

 

posted @ 2015-08-15 11:22  卫平_布莱恩特  阅读(655)  评论(0编辑  收藏  举报