This is my first C app, so please excuse some ignorance. I'm working on porting a Python-based libpcap application over to C for speed reasons. I'm having issues understanding how to extract information from the packet. It comes to my handler function as a u_char, and you can munge it from there. In python, I would just slice the "string" and extract my information that way, but I don't know how to proceed.
For example, how to I extract the destination and source MAC addresses from an ethernet frame (bytes 0-6 and 7-11 respectively). Right now I have:
void handle_sniffed(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
u_char *mac_dst = malloc(6*sizeof(u_char));
u_char *mac_src = malloc(6*sizeof(u_char));
memcpy(mac_dst, packet, 6);
memcpy(mac_src, packet+6, 6);
}
Am I doing this correctly, and now how do I display the MAC address, for example using printf?
I think you're doing it just fine, memcpy() attributes are just fine, malloc() is correct. You could use inline function like this to allocate memory safe/check allocation (you should check each allocation):
inline void* s_malloc(size_t size){
void *ptr = malloc( size);
if( !ptr){
printf( "Allocation failed");
exit(1);
}
return ptr;
}
You may also write macro for that but you won't be able to use it as function probably. If you guys have a better way of doing this I'll be glad to extend/edit.
Anyway, to answer your question. How to output MAC address. Here's a manual for prinf(), take a look at x resp. X format. It output's decimal number.
It works great until you want to print one character long number. So let's tell printf() to print number with precision 2 numbers .2. And we also need to tell it that it should be "left" pad instead of "decimal fraction digits on right side", that's - (check everything in manual). So complete string for printing one byte of MAC is: %-.2X. Complete example would be:
#include <stdio.h>
int main(){
unsigned char data[6] = {0x00, 0xab, 0x03, 0xff, 0xba, 0x10};
printf( "%-.2X:%-.2X:%-.2X:%-.2X:%-.2X:%-.2X\n", data[0], data[1], data[2],
data[3], data[4], data[5]);
return 0;
}
And the result:
[vyktor@grepfruit tmp]$ gcc -Wall src.cpp && ./a.out
00:AB:03:FF:BA:10
To speed things up you may build function like this:
void print_mac( const unsigned char *data){
printf( "%-.2X:%-.2X:%-.2X:%-.2X:%-.2X:%-.2X\n", data[0], data[1], data[2],
data[3], data[4], data[5]);
}
// Usage example:
printf( "SrcMAC: ");
print_mac(packet+6);
printf( "DstMAC: ");
print_mac(packet);
There of course may be better way to do this. I tried to make this clear and educational, if you don't understand anything, please feel free to ask in the comment
A packet sniffer as a first C-program? Impressive.
In C the proper way would be to create a struct which contains the layout of a single packet, you can then cast the packet-pointer you are given to that struct and de-reference e.g. the long long that holds the MAC-address.
Can you tell us where to find the specifications for the packets you are receiving, we can then help you create a matching struct.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With