EvilZone
Programming and Scripting => C - C++ => : Xires July 15, 2013, 10:44:15 AM
-
This is a little piece of test code that I'd created a while ago for work stuff. I went through and commented a bunch of stuff but if anyone has questions, feel free to ask. Note that this is not exactly 'noob-friendly'.
/* cap-test.c - v1.4 : 2013-07-15 - Xires <xires012@gmail.com>
*
* COMPILE: gcc -Wall -Wextra -W -o cap-test{,.c} -pthread -lpcap
*
* RUN:
* ./cap-test <num> [dev]
* num = number of packets to capture
* dev = device upon which to listen
*
* NOTE:
* -ansi or -std=c99 cannot be used because of pcap
* -pedantic cannot be used because of the variadic macros 'pout' & 'perr'
*
* To run this as non-root user, set cap_net_raw:
* # setcap cap_net_raw=pe ./cap-test.c
*
* Capabilities must be set after every compile.
*
*/
#include <stdio.h> /* fprintf */
#include <stdlib.h> /* u_char, u_int, etc. for pcap */
#include <time.h> /* localtime_r & other time-related stuff */
#include <pthread.h> /* pthread_create & other thread-related stuff */
#include <pcap.h> /* packet capturing library */
#define DEBUG 0 /* basic debugging by bitwise flag check */
/* Macros to simplify output operations */
#define pout(f, ...) fprintf(stdout, f, ## __VA_ARGS__)
#define perr(f, ...) fprintf(stderr, f, ## __VA_ARGS__)
typedef struct capargs_s { /* struct to hold our arguments to capture() */
int cnt; /* number of packets to capture */
char *dev; /* device from which to capture packets */
} capargs_t, ca_t; /* 2 different typenames for better code beauty */
void* capture(void*);
void handler(unsigned char*, const struct pcap_pkthdr*, const unsigned char*);
void prn_byts(const unsigned char*, unsigned int);
int main(int argc, char **argv) {
pthread_t c; /* represents our capture thread */
capargs_t d; /* holds arguments to pass to capture thread */
unsigned int j; /* holds return value from pthread_join */
void *r; /* holds return value from capture thread */
if ((argc < 2) || (argc > 3)) return 1; /* 1 or 2 arguments required */
else if (argc == 3) d.dev = argv[2]; /* if 2, 2nd is device name */
else d.dev = NULL; /* or look for device later */
d.cnt = atoi(argv[1]); /* packet capture count */
pthread_create(&c, NULL, capture, &d); /* create thread */
if ((j = pthread_join(c, &r))) return j; /* wait for thread to finish */
j = *((unsigned int*) &r); /* reuse for similar purpose */
return j; /* return threads return val */
}
void* capture(void *d) { /* does our capturing */
char ebuf[PCAP_ERRBUF_SIZE]; /* holds errors returned by pcap calls */
pcap_t *pcp; /* pointer to packet capture instance */
ca_t args = *((ca_t*) d); /* fetch argument struct */
if (!args.dev) /* if no device.. */
if (!(args.dev = pcap_lookupdev(ebuf))) /* search for one.. */
return (perr("pcap_lookupdev(): %s\n", ebuf), (void*) 2); /* or die */
#if (DEBUG & 1)
pout("dev: %s\n", args.dev);
#endif
/* try to open the device; die if we can't */
if (!(pcp = pcap_open_live(args.dev, BUFSIZ, 1, 1000, ebuf)))
return (perr("pcap_open_live(): %s\n", ebuf), (void*) 3);
while (args.cnt--) /* as long as we still haven't reached our goal.. */
pcap_dispatch(pcp, 1, (pcap_handler) handler, NULL); /* get pkt */
return NULL; /* we're done */
}
void handler(unsigned char *u, const struct pcap_pkthdr *h, const unsigned char *b) {
static struct tm t; /* holds our calculated time */
static char tim[20], out[28]; /* buffers for readable time */
(void)(u); /* we have no use for 'u'; shut the compiler up */
/* translate packet arrival time from timeval to struct tm */
localtime_r(&h->ts.tv_sec, &t);
strftime(tim, sizeof(tim), "%Y.%m.%d@%H:%M:%S", &t); /* make readable */
snprintf(out, sizeof(out), "%s.%06d", tim, (int) h->ts.tv_usec); /* done */
pout("%s", out); /* print out the now readable arrival time */
#if (DEBUG & 1)
pout("\tcaplen: %d\tlen: %d", h->caplen, h->len);
#endif
prn_byts(b, h->caplen); /* print a selection of captured bytes */
fflush(stdout); /* flush the output stream */
return;
}
void prn_byts(const unsigned char *b, unsigned int l) {
register unsigned int i = 0; /* iterator */
if (l > 120) l = 120; /* only print out, at max, the first 120 bytes */
while (i < l) {
if (!(i++ % 24)) pout("\n\t"); /* new line every 24 bytes output */
pout("%02x ", b[i]); /* print out the current byte */
}
pout("\n"); /* newline coherency */
return; /* done; return to calling process (handler) */
}
(sorry for the extra blank lines; the forum 'code' tags seem to be doing it; will look into a fix at some point)
-
You'll need libpcap & development files for working with it. Luckily, libpcap is actually likely to be installed on your machine as it's needed by nmap, tcpdump, wireshark, ettercap, etc. The development files do need to be installed separately, usually. Package name is probably called libpcap-dev. Don't forget to specify the -lpcap to link with it.