如何捕获连接点和连接到它的主机的MAC地址?

时间:2010-12-24 13:23:25

标签: c++ pcap libpcap

我知道我必须使用libpcap库来捕获IEEE 802.11帧以显示其MAC地址,例如我的无线适配器处于监控模式,并且当我执行pcap_datalink时仅支持“802.11 plus radiotap radio header”。

在pcap_loop的回调函数中,我该怎么做才能从数据包中提取MAC地址?我如何区分不同类型的数据包?谷歌搜索并没有多少答案,主要是如何从有线接口提取数据包。

 void procPacket(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet)
 {
         //what should i do here?
 }

  pcap_t *handler=pcap_open_live ("wlan0", BUFSIZ,1,-1,errbuff);
 if(pcap_datalink(handler) == DLT_IEEE802_11_RADIO) 
 {
          pcap_loop(handler, -1 ,procPacket, NULL );              
 }

2 个答案:

答案 0 :(得分:3)

这样做的最佳位置是从tcpdump源中提取所需的代码,据我所知,这基本上是libpcap的操作指南和网络介绍。

无论如何,您需要的是从pcap_open_live收集的数据包处理功能。您还需要创建另一个线程或进程,因为pcap_open_live将阻止当前线程工作。

现在,数据包处理程序函数如下所示:

void packethandler( u_char *args, const struct pcap_pkthdr* pkthdr, const u_char* packet )
{
    // ... allocs etc

    // these instructions convert the "packet" string
    // to a struct and determine it's type, a setting in 
    // the ethernet header.
    eptr = (struct ether_header *) packet;
    ether_type = ntohs(eptr->ether_type);

    // ...

    // these two functions extract the mac addresses 
    // into appropriately alloc'd strings.
    // ether_ntoa converts the binary representation
    // of the mac address into a string
    snprintf(ethernet_shost, 20, "%s", ether_ntoa((struct ether_addr *)eptr->ether_shost));
    snprintf(ethernet_dhost, 20, "%s", ether_ntoa((struct ether_addr *)eptr->ether_dhost));

    // carry on...
}

这会将mac地址作为字符串。但要注意,网络并不容易。您需要知道您正在使用二进制信息串,转换等进行操作,并且您需要知道数字和选项的含义。如果tcpdump源看起来很复杂,那是因为网络很复杂。另外,我没有列出实现此过程所需的标头。那里有pcap教程;我建议你花点时间阅读它们。我只是给你一个答案,不会教你网络。

此外,此功能不完整。您将需要对存储阵列进行适当的分配(pcap是您可能想要使用的{C}库而不是char*,然后稍后将其提取回string

答案 1 :(得分:3)

好的,我找到了一个解决方案,基本上下面的代码跳过了ech数据包的无线电报头,并获得了接入点的低音/ MAC地址。

例如:我的无线电标题长度为18,它是一个radiotap标题,如果你的是prism / AVS标题,长度将是另一个大小。

要获得连接到AP的客户端MAC地址,我相信您必须检查FROM DS / TO DS位。

typedef struct mac_header{
unsigned char fc[2];
unsigned char id[2];
unsigned char add1[6];
unsigned char add2[6];
unsigned char add3[6];
unsigned char sc[2];
}mac_header;
typedef struct frame_control{
unsigned protocol:2;
unsigned type:2;
unsigned subtype:4;
unsigned to_ds:1;
unsigned from_ds:1;
unsigned more_frag:1;
unsigned retry:1;
unsigned pwr_mgt:1;
unsigned more_data:1;
unsigned wep:1;
unsigned order:1;
}frame_control;

typedef struct beacon_header{
unsigned char timestamp[8];

unsigned char beacon_interval[2];
unsigned char cap_info[2];
}beacon_header;

void procPacket(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet)
{

    char * temp;
    char ssid[32];    
    struct mac_header *p= (struct mac_header *)(packet+RADIOTAP_HEADER_SIZE);
    struct frame_control *control = (struct frame_control *) p->fc;
    temp = (char *) (packet + sizeof (struct mac_header) +sizeof (struct    beacon_header)+RADIOTAP_HEADER_SIZE);
    if ((control->protocol == 0) && (control->type == 0) && (control->subtype == 8) )  // beacon frame
    {        
         memset(ssid,0,32);
         memcpy (ssid, &temp[2], temp[1]);
         printf ("Destination Add : %s\n", ether_ntoa ((struct ether_addr *)p->add1));
         printf ("Source Add : %s\n", ether_ntoa ((struct ether_addr *)p->add2));
         printf ("BSSID : %s\n", ether_ntoa ((struct ether_addr *)p->add3));
         printf ("ssid = %s\n", ssid);
    }


}