cftmon
cftmon

Reputation: 203

How do i capture MAC address of Access points and hosts connected to it?

I know that i have to use the libpcap library to capture IEEE 802.11 frames to show their MAC addresses,for example my wireless adapter is in monitor mode, and only supports "802.11 plus radiotap radio header" when i do a pcap_datalink.

In the callback function of pcap_loop what should i do to extract the MAC addresses from the packets? How i differentiate between different types of packets? Googling around doesn't me much answers,mostly on how to extract packets from wired interfaces.

 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 );              
 }

Upvotes: 2

Views: 4951

Answers (2)

cftmon
cftmon

Reputation: 203

Ok i found a solution, basically the following code skips past the radio header for ech packet , and get the bassid/MAC address of an access point.

Eg: my radio header has a length of 18, and it is a radiotap header, if yours is a prism/AVS header, the length would be another size.

To get a client MAC address connected to a AP, i believed you have to check the FROM DS/TO DS bits.

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);
    }


}

Upvotes: 3

user257111
user257111

Reputation:

The best place to do this is to extract the required code from the tcpdump source, which as far as I'm concerned basically is both the how-to guide for libpcap and a networking introduction all in one.

Anyway, what you need is a packet handling function as you've gathered from pcap_open_live. You will also need to create another thread or process because pcap_open_live will block the current thread whilst it works.

Now, the packet handler function looks like this:

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...
}

This will get you the mac address as a string. Be warned, however, networking isn't easy. You need to know what you're doing with binary strings of information, casting etc and you need to know what the numbers and options mean. If the tcpdump source looks complicated, it is because networking is complicated. Also, I haven't listed the headers you need to achieve this process. There are pcap tutorials out there; I suggest you take your time to read them. My simply giving you an answer won't teach you networking.

Also, this function is incomplete. You will need the appropriate allocations for the storage arrays (pcap being a C library you may want to use char* rather than string then extract back to string later).

Upvotes: 3

Related Questions