1
0
mirror of https://github.com/pavel-odintsov/fastnetmon synced 2024-09-20 11:54:35 +02:00
fastnetmon-rewritten/netflow_plugin/netflow_collector.cpp
2015-01-23 19:49:37 +03:00

149 lines
4.3 KiB
C++

/* netflow plugin body */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <inttypes.h>
// log4cpp logging facility
#include "log4cpp/Category.hh"
#include "log4cpp/Appender.hh"
#include "log4cpp/FileAppender.hh"
#include "log4cpp/OstreamAppender.hh"
#include "log4cpp/Layout.hh"
#include "log4cpp/BasicLayout.hh"
#include "log4cpp/PatternLayout.hh"
#include "log4cpp/Priority.hh"
// Get it from main programm
extern log4cpp::Category& logger;
#include "netflow_collector.h"
#include "netflow.h"
// This variable name should be uniq for every plugin!
process_packet_pointer netflow_process_func_ptr = NULL;
void process_netflow_packet_v5(u_int len, u_int8_t *packet) {
logger<< log4cpp::Priority::INFO<<"We get v5 netflow packet!";
struct NF5_HEADER *nf5_hdr = (struct NF5_HEADER *)packet;
struct NF5_FLOW *nf5_flow;
size_t offset;
if (len < sizeof(*nf5_hdr)) {
// short netflow v.5 packet %d bytes from %s
return;
}
u_int nflows = ntohs(nf5_hdr->c.flows);
if (nflows == 0 || nflows > NF5_MAXFLOWS) {
// Invalid number of flows (%u) in netflow
return;
}
for (u_int i = 0; i < nflows; i++) {
offset = NF5_PACKET_SIZE(i);
nf5_flow = (struct NF5_FLOW *)(packet + offset);
// convert netflow to simple packet form
simple_packet current_packet;
current_packet.src_ip = nf5_flow->src_ip;
current_packet.dst_ip = nf5_flow->dest_ip;
current_packet.ts.tv_sec = 0;
current_packet.ts.tv_usec = 0;
current_packet.flags = 0;
#define NTO64(a) (htobe64(ntohl(a)))
current_packet.length = NTO64(nf5_flow->flow_octets);
// TODO: it's COMPLETELY WRONG!!!! WE SHOULD NOT DO IT!!!!
// We should set current_packet = number_of_packets instead!!!
current_packet.sample_ratio = NTO64(nf5_flow->flow_packets);
#undef NTO64
switch (nf5_flow->protocol) {
case 1: {
//ICMP
}
break;
case 6: {
// TCP
current_packet.source_port = nf5_flow->src_port;
current_packet.destination_port = nf5_flow->dest_port;
// TODO: flags can be in another format!
current_packet.flags = nf5_flow->tcp_flags;
}
break;
case 17: {
// UDP
current_packet.source_port = nf5_flow->src_port;
current_packet.destination_port = nf5_flow->dest_port;
}
break;
}
netflow_process_func_ptr(current_packet);
}
}
void process_netflow_packet(u_int len, u_int8_t *packet) {
struct NF_HEADER_COMMON *hdr = (struct NF_HEADER_COMMON *)packet;
switch (ntohs(hdr->version)) {
case 5:
process_netflow_packet_v5(len, packet);
break;
//case 9:
// process_netflow_v9(fp, conf, peer, peers, log_fd, log_socket);
// break;
default:
logger<< log4cpp::Priority::ERROR<<"We did not support this version of netflow "<<ntohs(hdr->version);
break;
}
}
void start_netflow_collection(process_packet_pointer func_ptr) {
logger<< log4cpp::Priority::INFO<<"netflow plugin started";
netflow_process_func_ptr = func_ptr;
unsigned int udp_buffer_size = 65536;
char udp_buffer[udp_buffer_size];
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(2055);
bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
struct sockaddr_in6 peer;
memset(&peer, 0, sizeof(peer));
for (;;) {
struct sockaddr_in cliaddr;
socklen_t address_len = sizeof(cliaddr);
int received_bytes = recvfrom(sockfd, udp_buffer, udp_buffer_size, 0, (struct sockaddr *)&cliaddr, &address_len);
if (received_bytes > 0) {
// printf("We receive %d\n", received_bytes);
process_netflow_packet(received_bytes, (u_int8_t*)udp_buffer);
} else {
// logger<< log4cpp::Priority::ERROR<<"Data receive failed";
}
}
}