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); } }
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); } }