get the source and destination address from 802.11 packets o

67 views Asked by At

I have an NIC card, wlan1 which I set to monitor mode which I am capturing layer 2 packets with. I want to get the src and dest address of the packets, HWADDRESS es AKA MAC addresses of them.

In this link, it states that, for the recvfrom()

If the address argument is not a null pointer and the protocol provides the source address of messages, the source address of the received message shall be stored in the sockaddr structure pointed to by the address argument, and the length of this address shall be stored in the object pointed to by the address_len argument.

It means that if I give it a struct sockaddr * I should be able to get the MAC address of the packet no matter if it is a beacon frame, association frame, or an EAPOL etc.. right? (Only SA as seen in the structure below). Yet I want to find a way to get the DA as well.

I tried to do this:

#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
#include <sys/mman.h>
#include <net/if.h>
#include <netinet/in.h>
#include <linux/if_ether.h>
#include <net/if_arp.h>
#include <poll.h>
#include <assert.h>
#include <stdio.h>

#include <linux/if_packet.h>
#include <net/ethernet.h> /* the L2 protocols */

// raw_sock.c
#include<netinet/ip.h>
#include<sys/socket.h>
#include<arpa/inet.h>

    

int recvPrintSOCK(){

    struct sockaddr_ll ll; // => link layer
    struct ifreq ifreq_i; 
    int packet_size;
    
    
    int sock_raw = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    
    memset(&ifreq_i,0,sizeof(ifreq_i)); memset(&ll,0,sizeof(ll));
    strncpy(ifreq_i.ifr_name,"wlan1",IFNAMSIZ-1); //Arayüzün adını verme
     
    if((ioctl(sock_raw,SIOCGIFINDEX,&ifreq_i))<0)
        printf("indeks ioctl okumasında hata"); //İndeks Adını alma
     
    printf("indeks=%d\n",ifreq_i.ifr_ifindex);
    //strncpy(ifreq_i.ifr_name, "wlan1", sizeof(ifreq_i.ifr_name)); ioctl(sock_raw, SIOCGIFINDEX, &ifreq_i);

    ll.sll_ifindex = ifreq_i.ifr_ifindex;
    ll.sll_protocol = htons(ETH_P_ALL);
    ll.sll_family = PF_PACKET;
    
    if(bind(sock_raw, (struct sockaddr *)&ll, sizeof(ll)) == -1){
        printf("Err: bind failed %d\n", errno);
    }
    
    unsigned char *buffer = (unsigned char *)malloc(65526); //memset(&buffer, '\0', 65526);
    
    
    struct sockaddr theAddr;

    while(1){
        
        //packet_size = recvfrom(sock_raw , buffer , 65536 , 0 , (struct sockaddr *)&theAddr, (socklen_t *)sizeof(theAddr)); 
        packet_size = recvfrom(sock_raw , buffer , 65536 , 0 , NULL, NULL); 
        
        if (packet_size == -1) {
            printf("Failed to get packets\n");
            return 1;
        }else{
            for(int i=0; i<packet_size; ++i) {
                printf("%02x ", buffer[i]);
            }
            printf("The Sender MAC ADDRESS = %s \n", theAddr.sa_data);
            printf("\n");
            //free(buffer);
        }
        
    
    }
    
    return sock_raw;
    
    
}
int main(){
    recvPrintSOCK();
    //llSock();
}

Yet if I use this commented line (for now) recvfrom(sock_raw , buffer , 65536 , 0 , (struct sockaddr *)&theAddr, (socklen_t *)sizeof(theAddr)); I get error from the recvfrom with code -1.

So If I change the last 2 arguments from NULL to above ones, it fails. Yet from the documentation, I want to see the source address of the 802.11 frame, even the DA (destination address) yet seems struct sockaddr only stores the source?!

How can I dissect frames to see if they belong to a beacon, or association request etc?

If you have no answer to that, how can I fix the bug and how do I need to implement last 2 arguments of recvfrom() ? If I implement correctly will it return a MAC address for me ?

Extra Info:

The sockaddr structure is like this,

   struct sockaddr {
       sa_family_t     sa_family;      /* Address family */
       char            sa_data[];      /* Socket address */
   };

So even if I somehow got the sockaddr argument for recvfrom right, it'd only provide me the SA with sa_data, and not DA. I want to get the DA as well no matter the packet type of 802.11.

Extra: As an example, how does wireshark analyze and categorize the L2 packets it captures? Such as: beacons, QUIC, EAPOL, Assacion Req./Res. etc?

I think I should be checking specific fields of the packets, for example most packets start with

00 00 1a 00 2f 48 00 00

Then I should start checking the rest of the bytes, some next field after the above (header padding, and some flags) I get the MAC timestamp and seen on the wireshark.

enter image description here

0

There are 0 answers