Created
March 29, 2016 13:16
-
-
Save yurynix/797d6775f82885c97281 to your computer and use it in GitHub Desktop.
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 <sys/time.h> /* select */ | |
#include <sys/types.h> /* select */ | |
#include <unistd.h> /* select, exit */ | |
#include <stdlib.h> /* atexit */ | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include <pcap.h> | |
/* ethernet headers are always exactly 14 bytes [1] */ | |
#define SIZE_ETHERNET 14 | |
/* Ethernet addresses are 6 bytes */ | |
#define ETHER_ADDR_LEN 6 | |
/* Ethernet header */ | |
struct sniff_ethernet { | |
u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */ | |
u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */ | |
u_short ether_type; /* IP? ARP? RARP? etc */ | |
}; | |
/* IP header */ | |
struct sniff_ip { | |
u_char ip_vhl; /* version << 4 | header length >> 2 */ | |
u_char ip_tos; /* type of service */ | |
u_short ip_len; /* total length */ | |
u_short ip_id; /* identification */ | |
u_short ip_off; /* fragment offset field */ | |
#define IP_RF 0x8000 /* reserved fragment flag */ | |
#define IP_DF 0x4000 /* dont fragment flag */ | |
#define IP_MF 0x2000 /* more fragments flag */ | |
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ | |
u_char ip_ttl; /* time to live */ | |
u_char ip_p; /* protocol */ | |
u_short ip_sum; /* checksum */ | |
struct in_addr ip_src,ip_dst; /* source and dest address */ | |
}; | |
void print_hex_ascii_line(const u_char *payload, int len, int offset) | |
{ | |
int i; | |
int gap; | |
const u_char *ch; | |
/* offset */ | |
printf("%05d ", offset); | |
/* hex */ | |
ch = payload; | |
for(i = 0; i < len; i++) { | |
printf("%02x ", *ch); | |
ch++; | |
/* print extra space after 8th byte for visual aid */ | |
if (i == 7) | |
printf(" "); | |
} | |
/* print space to handle line less than 8 bytes */ | |
if (len < 8) | |
printf(" "); | |
/* fill hex gap with spaces if not full line */ | |
if (len < 16) { | |
gap = 16 - len; | |
for (i = 0; i < gap; i++) { | |
printf(" "); | |
} | |
} | |
printf(" "); | |
/* ascii (if printable) */ | |
ch = payload; | |
for(i = 0; i < len; i++) { | |
if (isprint(*ch)) | |
printf("%c", *ch); | |
else | |
printf("."); | |
ch++; | |
} | |
printf("\n"); | |
return; | |
} | |
void packet_callback(unsigned char *args, | |
const struct pcap_pkthdr *hdr, | |
unsigned char *packet) | |
{ | |
const struct sniff_ethernet *ethernet = (struct sniff_ethernet*)(packet); | |
const struct sniff_ip *ip; | |
if ( ntohs( ethernet->ether_type ) != 0x0800 ) { // not IP | |
//print_hex_ascii_line( ethernet, SIZE_ETHERNET, 0 ); | |
return; | |
} | |
ip = (struct sniff_ip*)(packet + SIZE_ETHERNET); | |
if ( ip->ip_p != 0x11 ) { // not udp | |
return; | |
} | |
fprintf(stdout, "%s %d.%d len: %d\n", args, hdr->ts.tv_sec, hdr->ts.tv_usec, hdr->caplen); | |
printf("%s -> %s %x\n", inet_ntoa(ip->ip_src), inet_ntoa(ip->ip_dst), ip->ip_p ); | |
} | |
int main(int argc, char **argv) | |
{ | |
int t, i, handles_length; | |
pcap_t **pcap_handles; | |
fd_set fd_wait; | |
struct timeval st; | |
pcap_t *pcap; | |
char errbuf[PCAP_ERRBUF_SIZE]; | |
if ( argc < 2 ) { | |
fprintf(stderr, "%s <device> [device]...", argv[0]); | |
} | |
handles_length = argc - 1; | |
pcap_handles = malloc( sizeof(pcap_t*) * handles_length ); | |
for ( i = 1; i < argc; i++ ) { | |
printf("Opening device #%d: %s\n", i, argv[i]); | |
pcap = pcap_open_live( argv[i], BUFSIZ, 1, -1, errbuf); | |
if (pcap == NULL) | |
{ | |
fprintf(stderr, "Could not open device \"%s\": %s\n", argv[i], errbuf); | |
exit(1); | |
} | |
printf("Opened %s\n", argv[i]); | |
if (pcap_setnonblock(pcap, 1, errbuf) == -1) | |
{ | |
fprintf(stderr, "Could not set device \"%s\" to non-blocking: %s\n", argv[i], errbuf); | |
exit(1); | |
} | |
printf("Set %s to non blocking\n", argv[i]); | |
pcap_handles[i - 1] = pcap; | |
} | |
for(;;) | |
{ | |
/* If you include STDIN_FILENO, be sure to read from it when you get | |
traffic from it, or select will return every time it is called, | |
since there will still be traffic waiting there. | |
*/ | |
FD_ZERO(&fd_wait); | |
/*FD_SET(STDIN_FILENO, &fd_wait);*/ | |
for ( i = 0; i < handles_length; i++) { | |
FD_SET(pcap_fileno(pcap_handles[i]), &fd_wait); | |
} | |
st.tv_sec = 1; | |
st.tv_usec = 0; /* 1000 = 1 second */ | |
t = select(FD_SETSIZE, &fd_wait, NULL, NULL, &st); | |
switch(t) | |
{ | |
case -1: /* Something went really wrong */ | |
fprintf(stderr, "Argh!\n\n"); | |
exit(1); | |
case 0: /* We timed out, no trafffic */ | |
fprintf(stderr, "."); | |
break; | |
default: /* We got traffic */ | |
for ( i = 0; i < handles_length; i++ ) { | |
if ( FD_ISSET(pcap_fileno(pcap_handles[i]), &fd_wait) ) { | |
pcap_dispatch( pcap_handles[i], 1, (void *) packet_callback, (unsigned char *)argv[ i + 1 ] ); | |
} | |
} | |
} | |
/* Put your service routine here.. is called when select times out | |
or when a packet is processed | |
*/ | |
} /* End of for(;;) */ | |
} /* End of main() */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment