Reputation: 203
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
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
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