This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <pcap/pcap.h> | |
#include <net/ethernet.h> | |
pcap_t * CreatePcapForInterface( const char * interfaceName ) | |
{ | |
char errbuf[PCAP_ERRBUF_SIZE]; | |
int success = 0; | |
// Create a packet capture handle for the specified interface | |
pcap_t * pcap = pcap_create( interfaceName, errbuf ); | |
if( pcap == NULL ) | |
{ | |
fprintf( stderr, "Unable to create pcap for interface %s (%s).\n", interfaceName, errbuf ); | |
goto exit; | |
} | |
// Deliver packets as soon as they arrive. See the pcap man page for more info. | |
if( pcap_set_timeout( pcap, 1 ) != 0 ) | |
{ | |
fprintf( stderr, "Unable to configure timeout.\n" ); | |
goto exit; | |
} | |
// When immediate mode is enabled, reads return immediately upon packet reception. | |
// Otherwise, a read will block until either the kernel buffer becomes full or a timeout occurs. | |
if( pcap_set_immediate_mode( pcap, 1 ) != 0 ) | |
{ | |
fprintf( stderr, "Unable to configure immediate mode.\n" ); | |
goto exit; | |
} | |
// Activate packet capture handle to look at packets on the network | |
int activateStatus = pcap_activate( pcap ); | |
if( activateStatus < 0 ) | |
{ | |
pcap_perror( pcap, "Activate failed" ); | |
goto exit; | |
} | |
// Set ethernet link-layer header type | |
if( pcap_set_datalink( pcap, DLT_EN10MB ) ) | |
{ | |
pcap_perror( pcap, "Set datalink failed" ); | |
goto exit; | |
} | |
success = 1; | |
exit: | |
if( success == 0 ) | |
{ | |
if( pcap ) | |
{ | |
pcap_close( pcap ); | |
pcap = NULL; | |
} | |
} | |
return pcap; | |
} | |
void MonitorPcap( pcap_t * pcap ) | |
{ | |
int pcapFD = pcap_get_selectable_fd( pcap ); | |
if( pcapFD < 0 ) | |
return; | |
fd_set allFileDescriptorSet; | |
FD_ZERO( &allFileDescriptorSet ); | |
FD_SET( pcapFD, &allFileDescriptorSet ); | |
for( ;; ) | |
{ | |
fd_set readFileDescriptorSet = allFileDescriptorSet; | |
int readyCount = select( pcapFD + 1, &readFileDescriptorSet, NULL, NULL, NULL ); | |
if( readyCount < 0 ) | |
break; | |
if( FD_ISSET( pcapFD, &readFileDescriptorSet ) ) | |
{ | |
struct pcap_pkthdr * pcapHeader; | |
const u_char * packetPtr; | |
int packetCount = pcap_next_ex( pcap, &pcapHeader, &packetPtr ); | |
if( packetCount < 0 ) | |
break; | |
printf( "Got %u byte packet:\n", pcapHeader->caplen ); | |
if( pcapHeader->caplen >= sizeof( struct ether_header ) ) | |
{ | |
struct ether_header * eh = (struct ether_header *)packetPtr; | |
printf( "\tdst=%02x:%02x:%02x:%02x,%02x:%02x src=%02x:%02x:%02x:%02x,%02x:%02x, type=0x%04x\n", | |
eh->ether_dhost[0], eh->ether_dhost[1], eh->ether_dhost[2], | |
eh->ether_dhost[3], eh->ether_dhost[4], eh->ether_dhost[5], | |
eh->ether_shost[0], eh->ether_shost[1], eh->ether_shost[2], | |
eh->ether_shost[3], eh->ether_shost[4], eh->ether_shost[5], | |
ntohs( eh->ether_type ) ); | |
} | |
} | |
} | |
} | |
int main() | |
{ | |
pcap_t * pcap = CreatePcapForInterface( "en0" ); | |
if( !pcap ) | |
exit( EXIT_FAILURE ); | |
// This could be done on a separate thread, or as a part | |
// of general file descriptor monitoring. | |
MonitorPcap( pcap ); | |
return 0; | |
} |
No comments:
Post a Comment