Skip to content

Instantly share code, notes, and snippets.

@yurynix
Created March 29, 2016 13:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yurynix/797d6775f82885c97281 to your computer and use it in GitHub Desktop.
Save yurynix/797d6775f82885c97281 to your computer and use it in GitHub Desktop.
#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