void process_netflow_packet_v5(u_int8_t *packet, u_int len) {
    //logger<< log4cpp::Priority::INFO<<"We get v5 netflow packet!";
    
    struct NF5_HEADER* nf5_hdr = (struct NF5_HEADER*)packet;

    if (len < sizeof(*nf5_hdr)) {
        logger<< log4cpp::Priority::ERROR<<"Short netflow v5 packet "<<len;
        return;
    }

    u_int nflows = ntohs(nf5_hdr->c.flows);
    if (nflows == 0 || nflows > NF5_MAXFLOWS) {
        logger<< log4cpp::Priority::ERROR<<"Invalid number of flows in netflow "<<nflows;
        return;
    }
    
    for (u_int i = 0; i < nflows; i++) {
        size_t offset = NF5_PACKET_SIZE(i);
        struct NF5_FLOW* nf5_flow = (struct NF5_FLOW *)(packet + offset);

        /* Check packet bounds */
        if (offset + sizeof(struct NF5_FLOW) > len) {
            logger<< log4cpp::Priority::ERROR<<"Error! You will try to read outside the packet";
        } 

        // 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  = ntohl(nf5_hdr->time_sec);
        current_packet.ts.tv_usec = ntohl(nf5_hdr->time_nanosec);
        current_packet.flags = 0;

        current_packet.source_port = 0;
        current_packet.destination_port = 0;

        // TODO: we should pass data about "flow" structure of this data
    
        // htobe64 removed
        current_packet.length            = fast_ntoh(nf5_flow->flow_octets);
        current_packet.number_of_packets = fast_ntoh(nf5_flow->flow_packets);

        current_packet.sample_ratio = sampling_rate;

        current_packet.source_port      = fast_ntoh(nf5_flow->src_port);
        current_packet.destination_port = fast_ntoh(nf5_flow->dest_port);

        switch (nf5_flow->protocol) {
            case 1: {
                //ICMP
                current_packet.protocol = IPPROTO_ICMP; 
            }
            break;

            case 6: { 
                // TCP
                current_packet.protocol = IPPROTO_TCP;

                // TODO: flags can be in another format!
                current_packet.flags = nf5_flow->tcp_flags;
            }
            break;

            case 17: {
                // UDP
                current_packet.protocol = IPPROTO_UDP;
            }
            break;
        }
   
        // Call processing function for every flow in packet
        netflow_process_func_ptr(current_packet);
    }
}
static void
process_netflow_v5(struct flow_packet *fp, struct flowd_config *conf,
    struct peer_state *peer, struct peers *peers, int log_fd, int log_socket)
{
	struct NF5_HEADER *nf5_hdr = (struct NF5_HEADER *)fp->packet;
	struct NF5_FLOW *nf5_flow;
	struct store_flow_complete flow;
	size_t offset;
	u_int i, nflows;
	if (fp->len < sizeof(*nf5_hdr)) {
		peer->ninvalid++;
		logit(LOG_WARNING, "short netflow v.5 packet %d bytes from %s",
		    fp->len, addr_ntop_buf(&fp->flow_source));
		return;
	}
	nflows = ntohs(nf5_hdr->c.flows);
	if (nflows == 0 || nflows > NF5_MAXFLOWS) {
		peer->ninvalid++;
		logit(LOG_WARNING, "Invalid number of flows (%u) in netflow "
		    "v.5 packet from %s", nflows,
		    addr_ntop_buf(&fp->flow_source));
		return;
	}
	if (fp->len != NF5_PACKET_SIZE(nflows)) {
		peer->ninvalid++;
		logit(LOG_WARNING, "Inconsistent Netflow v.5 packet from %s: "
		    "len %u expected %u", addr_ntop_buf(&fp->flow_source),
		    fp->len, NF5_PACKET_SIZE(nflows));
		return;
	}
	
	logit(LOG_DEBUG, "Valid netflow v.5 packet %d flows", nflows);
	update_peer(peers, peer, nflows, 5);
	for (i = 0; i < nflows; i++) {
		
		offset = NF5_PACKET_SIZE(i);
		nf5_flow = (struct NF5_FLOW *)(fp->packet + offset);

		bzero(&flow, sizeof(flow));

		/* NB. These are converted to network byte order later */
		flow.hdr.fields = STORE_FIELD_ALL;
		/* flow.hdr.tag is set later */
		flow.hdr.fields &= ~STORE_FIELD_TAG;
		flow.hdr.fields &= ~STORE_FIELD_SRC_ADDR6;
		flow.hdr.fields &= ~STORE_FIELD_DST_ADDR6;
		flow.hdr.fields &= ~STORE_FIELD_GATEWAY_ADDR6;

		flow.recv_time.recv_sec = fp->recv_time.tv_sec;
		flow.recv_time.recv_usec = fp->recv_time.tv_usec;

		flow.pft.tcp_flags = nf5_flow->tcp_flags;
		flow.pft.protocol = nf5_flow->protocol;
		flow.pft.tos = nf5_flow->tos;

		memcpy(&flow.agent_addr, &fp->flow_source,
		    sizeof(flow.agent_addr));

		flow.src_addr.v4.s_addr = nf5_flow->src_ip;
		flow.src_addr.af = AF_INET;
		flow.dst_addr.v4.s_addr = nf5_flow->dest_ip;
		flow.dst_addr.af = AF_INET;
		flow.gateway_addr.v4.s_addr = nf5_flow->nexthop_ip;
		flow.gateway_addr.af = AF_INET;

		flow.ports.src_port = nf5_flow->src_port;
		flow.ports.dst_port = nf5_flow->dest_port;

#define NTO64(a) (store_htonll(ntohl(a)))
		flow.octets.flow_octets = NTO64(nf5_flow->flow_octets);
		flow.packets.flow_packets = NTO64(nf5_flow->flow_packets);
#undef NTO64

		flow.ifndx.if_index_in = htonl(ntohs(nf5_flow->if_index_in));
		flow.ifndx.if_index_out = htonl(ntohs(nf5_flow->if_index_out));

		flow.ainfo.sys_uptime_ms = nf5_hdr->uptime_ms;
		flow.ainfo.time_sec = nf5_hdr->time_sec;
		flow.ainfo.time_nanosec = nf5_hdr->time_nanosec;
		flow.ainfo.netflow_version = nf5_hdr->c.version;

		flow.ftimes.flow_start = nf5_flow->flow_start;
		flow.ftimes.flow_finish = nf5_flow->flow_finish;

		flow.asinf.src_as = nf5_flow->src_as;
		flow.asinf.dst_as = nf5_flow->dest_as;
		flow.asinf.src_mask = nf5_flow->src_mask;
		flow.asinf.dst_mask = nf5_flow->dst_mask;

		flow.finf.engine_type = nf5_hdr->engine_type;
		flow.finf.engine_id = nf5_hdr->engine_id;
		flow.finf.flow_sequence = nf5_hdr->flow_sequence;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                          ADD IMED



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


		process_flow(&flow, conf, log_fd, log_socket);
	}
}
示例#3
0
void process_netflow_packet_v5(u_int8_t* packet, u_int len, std::string client_addres_in_string_format) {
    // logger<< log4cpp::Priority::INFO<<"We get v5 netflow packet!";

    struct NF5_HEADER* nf5_hdr = (struct NF5_HEADER*)packet;

    if (len < sizeof(*nf5_hdr)) {
        logger << log4cpp::Priority::ERROR << "Short netflow v5 packet " << len;
        return;
    }

    u_int nflows = ntohs(nf5_hdr->c.flows);
    if (nflows == 0 || nflows > NF5_MAXFLOWS) {
        logger << log4cpp::Priority::ERROR << "Invalid number of flows in netflow " << nflows;
        return;
    }

    uint16_t netflow5_sampling_ratio = fast_ntoh(nf5_hdr->sampling_rate);

    // In first two bits we store sampling type. 
    // We are not interested in it and should zeroify it for getting correct value of sampling rate
    clear_bit_value(netflow5_sampling_ratio, 15);
    clear_bit_value(netflow5_sampling_ratio, 16);

    // Sampling not enabled on device
    if (netflow5_sampling_ratio == 0) {
        netflow5_sampling_ratio = 1;
    }

    for (u_int i = 0; i < nflows; i++) {
        size_t offset = NF5_PACKET_SIZE(i);
        struct NF5_FLOW* nf5_flow = (struct NF5_FLOW*)(packet + offset);

        /* Check packet bounds */
        if (offset + sizeof(struct NF5_FLOW) > len) {
            logger << log4cpp::Priority::ERROR << "Error! You will try to read outside the packet";
        }

        /* Decode to host encoding */
        // TODO: move to separate function
        nf5_flow->flow_octets = fast_ntoh(nf5_flow->flow_octets);
        nf5_flow->flow_packets = fast_ntoh(nf5_flow->flow_packets);

        nf5_flow->if_index_in  = fast_ntoh(nf5_flow->if_index_in);
        nf5_flow->if_index_out = fast_ntoh(nf5_flow->if_index_out);
    
        // 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 = ntohl(nf5_hdr->time_sec);
        current_packet.ts.tv_usec = ntohl(nf5_hdr->time_nanosec);
        current_packet.flags = 0;

        current_packet.source_port = 0;
        current_packet.destination_port = 0;

        // TODO: we should pass data about "flow" structure of this data
        current_packet.length = nf5_flow->flow_octets;
        current_packet.number_of_packets = nf5_flow->flow_packets;

        if (netflow_divide_counters_on_interval_length) {
            // This interval in milliseconds, convert it to seconds
            int64_t interval_length = (fast_ntoh(nf5_flow->flow_finish) - fast_ntoh(nf5_flow->flow_start)) / 1000;

            /*
            if (interval_length > 0) {
                logger << log4cpp::Priority::INFO << "NetFlow v5 from: " << client_addres_in_string_format
                    << " start: " << fast_ntoh(nf5_flow->flow_start)
                    << " finish: " << fast_ntoh(nf5_flow->flow_finish) 
                    << " interval length:" << interval_length 
                    << "\n";
            }
            */

            if (interval_length == 0) {
                // it's OK
            } else if (interval_length < 0) {
                // it's internal error
                logger << log4cpp::Priority::ERROR << "We got negative interval length from netflow agent, something goes wrong!";
            } else {
                // OK, let's divide
                // We will get integer result for this operation
                current_packet.length = current_packet.length / interval_length;
                current_packet.number_of_packets = current_packet.number_of_packets / interval_length;
            }

        }
    
        // TODO: use sampling data from packet, disable customization here
        // Wireshark dump approves this idea
        current_packet.sample_ratio = netflow5_sampling_ratio;

        current_packet.source_port = fast_ntoh(nf5_flow->src_port);
        current_packet.destination_port = fast_ntoh(nf5_flow->dest_port);

        // We do not support IPv6 in NetFlow v5 at all
        current_packet.ip_protocol_version = 4;

        switch (nf5_flow->protocol) {
        case 1: {
            // ICMP
            current_packet.protocol = IPPROTO_ICMP;
        } break;

        case 6: {
            // TCP
            current_packet.protocol = IPPROTO_TCP;

            // TODO: flags can be in another format!
            current_packet.flags = nf5_flow->tcp_flags;
        } break;

        case 17: {
            // UDP
            current_packet.protocol = IPPROTO_UDP;
        } break;
        }

#ifdef ENABLE_LUA_HOOKS
        if (lua_hooks_enabled) {
            // This code could be used only for tests with pcap_reader
            //if (lua_state == NULL) {
            //    init_lua_jit();
            //}

            if (call_lua_function("process_netflow", netflow_lua_state, client_addres_in_string_format, (void*)nf5_flow)) {
                // We will process this packet
            } else {
                logger << log4cpp::Priority::INFO << "We will drop this packets because LUA script decided to do it";
                return;
            }
        }
#endif

        // Call processing function for every flow in packet
        netflow_process_func_ptr(current_packet);
    }
}