blob: ed0ba8239f9feef5962177ff86b9b17138e8248a [file] [log] [blame]
#include "pfring.h"
#include "../../kernel/plugins/dummy_plugin.h"
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <sys/time.h>
#include <time.h>
#include <signal.h>
pfring *pd;
int timer_timeout = 2;
int verbose = 0;
u_int32_t pkt_cnt = 0;
/* ************************************************************************ */
static void timer_handler(int signo)
{
time_t curr_time;
curr_time = time(NULL);
printf("Packet count %u after %d seconds, time is: %s",
pkt_cnt, timer_timeout, ctime(&curr_time));
pkt_cnt = 0;
}
static void set_signals(void)
{
struct sigaction sa;
int rc;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = timer_handler;
rc = sigaction(SIGALRM, &sa, NULL);
if (rc < 0) {
perror("sigaction failed\n");
exit(1);
}
}
/*
* configure timer to generate SIGALARM when fired
* the timer expires at every timer_timeout seconds
*/
static void set_timer(void)
{
timer_t timerid;
struct sigevent sev;
struct itimerspec its;
int rc;
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGALRM;
sev.sigev_value.sival_ptr = &timerid;
rc = timer_create(CLOCK_REALTIME, &sev, &timerid);
if (rc < 0) {
perror("timer_create failed\n");
exit(1);
}
its.it_value.tv_sec = timer_timeout;
its.it_value.tv_nsec = 0; /* don't need nanosec */
its.it_interval.tv_sec = its.it_value.tv_sec;
its.it_interval.tv_nsec = its.it_value.tv_nsec;
rc = timer_settime(timerid, 0, &its, NULL);
if (rc < 0) {
perror("timer_settime failed\n");
exit(1);
}
}
/* ************************************************************************ */
/*
* A faster replacement for inet_ntoa().
*/
char* _intoa(unsigned int addr, char* buf, u_short bufLen)
{
char *cp, *retStr;
u_int byte;
int n;
cp = &buf[bufLen];
*--cp = '\0';
n = 4;
do {
byte = addr & 0xff;
*--cp = byte % 10 + '0';
byte /= 10;
if (byte > 0) {
*--cp = byte % 10 + '0';
byte /= 10;
if (byte > 0)
*--cp = byte + '0';
}
*--cp = '.';
addr >>= 8;
} while (--n > 0);
/* Convert the string to lowercase */
retStr = (char*)(cp+1);
return(retStr);
}
/* ************************************ */
char* intoa(unsigned int addr)
{
static char buf[sizeof "ff:ff:ff:ff:ff:ff:255.255.255.255"];
return(_intoa(addr, buf, sizeof(buf)));
}
int32_t gmt2local(time_t t)
{
int dt, dir;
struct tm *gmt, *loc;
struct tm sgmt;
if (t == 0) t = time(NULL);
gmt = &sgmt;
*gmt = *gmtime(&t);
loc = localtime(&t);
dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 +
(loc->tm_min - gmt->tm_min) * 60;
/*
* If the year or julian day is different, we span 00:00 GMT
* and must add or subtract a day. Check the year first to
* avoid problems when the julian day wraps.
*/
dir = loc->tm_year - gmt->tm_year;
if (dir == 0) dir = loc->tm_yday - gmt->tm_yday;
dt += dir * 24 * 60 * 60;
return (dt);
}
static int32_t thiszone;
/* ************************************************************************ */
void processPacket(const struct pfring_pkthdr *h, u_char *p)
{
struct ether_header ehdr;
u_short eth_type, vlan_id;
struct ip ip;
int i, s;
uint usec, nsec=0;
if (h->ts.tv_sec == 0) {
printf("should parse packet\n");
return;
}
pkt_cnt++;
if (verbose) {
printf("---------Packet received-----------\n");
thiszone = gmt2local(0);
s = (h->ts.tv_sec + thiszone) % 86400;
if (h->extended_hdr.timestamp_ns) {
usec = (h->extended_hdr.timestamp_ns / 1000) % 1000000;
nsec = h->extended_hdr.timestamp_ns % 1000;
} else {
usec = h->ts.tv_usec;
}
usec = h->ts.tv_usec;
printf("%02d:%02d:%02d.%06u%03u ",
s / 3600, (s % 3600) / 60, s % 60,
usec, nsec);
struct pfring_extended_pkthdr *ext_hdr = &(h->extended_hdr);
printf("%s if_index=%d\n",
ext_hdr->rx_direction ? "RX" : "TX",
ext_hdr->if_index);
p[ext_hdr->parsed_header_len + h->caplen] = '\0';
memcpy(&ehdr, p + h->extended_hdr.parsed_header_len, sizeof(struct ether_header));
eth_type = ntohs(ehdr.ether_type);
if(eth_type == 0x8100) {
printf("[eth_type: 0x%04X]\n", eth_type);
vlan_id = (p[14] & 15) * 256 + p[15];
eth_type = (p[16]) * 256 + p[17];
printf("[vlan %u] ", vlan_id);
p += 4;
}
printf("[eth_type: 0x%04X]\n", eth_type);
if(eth_type == 0x0800) {
memcpy(&ip, p + h->extended_hdr.parsed_header_len + sizeof(ehdr), sizeof(struct ip));
printf("[%s:%d ", intoa(ntohl(ip.ip_src.s_addr)), h->extended_hdr.parsed_pkt.l4_src_port);
printf("-> %s:%d]\n", intoa(ntohl(ip.ip_dst.s_addr)), h->extended_hdr.parsed_pkt.l4_dst_port);
}
else
printf("[not IPv4]\n");
printf("Buffer----------\n");
for (i = 0; i < ext_hdr->parsed_header_len + h->caplen; i++) {
printf("%02X ", p[i]);
}
printf("-----------------------------------------------------------\n");
}
}
void printHelp(void) {
printf("my_test\n");
printf("-h [Print help]\n");
printf("-i <device> [Device name]\n");
printf("-p <protocol> [Dummy protocol filter (6=tcp, 17=udp, 1=icmp)]\n");
printf("-t <time> [Timer timeout]\n");
printf("-v [Verbose]\n");
}
int main(int argc, char** argv)
{
char *device = NULL, c;
filtering_rule rule;
struct dummy_filter *filter;
u_int8_t protocol = 17 /* udp */;
u_int32_t version;
int rc;
while ((c = getopt(argc,argv,"hi:vp:t:")) != -1) {
switch(c) {
case 'h':
printHelp();
return 0;
break;
case 'i':
device = strdup(optarg);
break;
case 'p':
protocol = atoi(optarg);
break;
case 'v':
verbose = 1;
break;
case 't':
timer_timeout = atoi(optarg);
break;
}
}
if (!device)
device = "eth0";
pd = pfring_open(device, 1500, PF_RING_PROMISC | PF_RING_LONG_HEADER);
if (pd == NULL) {
perror("pfring_open failed");
return -1;
}
pfring_version(pd, &version);
printf("Using PF_RING v.%d.%d.%d\n",
(version & 0xFFFF0000) >> 16,
(version & 0x0000FF00) >> 8,
version & 0x000000FF);
pfring_toggle_filtering_policy(pd, 0);
memset(&rule, 0, sizeof(rule));
rule.rule_id = 5;
rule.rule_action = forward_packet_and_stop_rule_evaluation;
rule.plugin_action.plugin_id = DUMMY_PLUGIN_ID;
rule.extended_fields.filter_plugin_id = DUMMY_PLUGIN_ID;
filter = (struct dummy_filter*)rule.extended_fields.filter_plugin_data;
filter->protocol = protocol; // default udp
rc = pfring_add_filtering_rule(pd, &rule);
if (rc < 0) {
printf("pfring_add_filtering_rule() failed rc = %d\n", rc);
return -1;
}
rc = pfring_enable_ring(pd);
if (rc < 0) {
printf("pfring_enable_ring() failed rc = %d\n", rc);
return -1;
}
set_signals();
set_timer();
while (1) {
u_char *buffer;
struct pfring_pkthdr hdr;
rc = pfring_recv(pd, &buffer, 0, &hdr, 1);
switch(rc) {
case 0:
printf("No packet received\n");
break;
case 1:
processPacket(&hdr, buffer);
break;
default:
printf("Error\n");
break;
}
}
rc = pfring_disable_ring(pd);
if (rc < 0) {
printf("pfring_disable_ring() failed rc = %d\n", rc);
return -1;
}
pfring_close(pd);
return 0;
}