static void process_netflow_v7(struct flow_packet *fp, struct flowd_config *conf, struct peer_state *peer, struct peers *peers, int log_fd, int log_socket) { struct NF7_HEADER *nf7_hdr = (struct NF7_HEADER *)fp->packet; struct NF7_FLOW *nf7_flow; struct store_flow_complete flow; size_t offset; u_int i, nflows; if (fp->len < sizeof(*nf7_hdr)) { peer->ninvalid++; logit(LOG_WARNING, "short netflow v.7 packet %d bytes from %s", fp->len, addr_ntop_buf(&fp->flow_source)); return; } nflows = ntohs(nf7_hdr->c.flows); if (nflows == 0 || nflows > NF7_MAXFLOWS) { peer->ninvalid++; logit(LOG_WARNING, "Invalid number of flows (%u) in netflow " "v.7 packet from %s", nflows, addr_ntop_buf(&fp->flow_source)); return; } if (fp->len != NF7_PACKET_SIZE(nflows)) { peer->ninvalid++; logit(LOG_WARNING, "Inconsistent Netflow v.7 packet from %s: " "len %u expected %u", addr_ntop_buf(&fp->flow_source), fp->len, NF7_PACKET_SIZE(nflows)); return; } logit(LOG_DEBUG, "Valid netflow v.7 packet %d flows", nflows); update_peer(peers, peer, nflows, 7); for (i = 0; i < nflows; i++) { offset = NF7_PACKET_SIZE(i); nf7_flow = (struct NF7_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; /* * XXX: we can parse the (undocumented) flags1 and flags2 * fields of the packet to disable flow fields not set by * the Cat5k (e.g. destination-only mls nde mode) */ flow.recv_time.recv_sec = fp->recv_time.tv_sec; flow.recv_time.recv_usec = fp->recv_time.tv_usec; flow.pft.tcp_flags = nf7_flow->tcp_flags; flow.pft.protocol = nf7_flow->protocol; flow.pft.tos = nf7_flow->tos; memcpy(&flow.agent_addr, &fp->flow_source, sizeof(flow.agent_addr)); flow.src_addr.v4.s_addr = nf7_flow->src_ip; flow.src_addr.af = AF_INET; flow.dst_addr.v4.s_addr = nf7_flow->dest_ip; flow.dst_addr.af = AF_INET; flow.gateway_addr.v4.s_addr = nf7_flow->nexthop_ip; flow.gateway_addr.af = AF_INET; flow.ports.src_port = nf7_flow->src_port; flow.ports.dst_port = nf7_flow->dest_port; #define NTO64(a) (store_htonll(ntohl(a))) flow.octets.flow_octets = NTO64(nf7_flow->flow_octets); flow.packets.flow_packets = NTO64(nf7_flow->flow_packets); #undef NTO64 flow.ifndx.if_index_in = htonl(ntohs(nf7_flow->if_index_in)); flow.ifndx.if_index_out = htonl(ntohs(nf7_flow->if_index_out)); flow.ainfo.sys_uptime_ms = nf7_hdr->uptime_ms; flow.ainfo.time_sec = nf7_hdr->time_sec; flow.ainfo.time_nanosec = nf7_hdr->time_nanosec; flow.ainfo.netflow_version = nf7_hdr->c.version; flow.ftimes.flow_start = nf7_flow->flow_start; flow.ftimes.flow_finish = nf7_flow->flow_finish; flow.asinf.src_as = htonl(ntohs(nf7_flow->src_as)); flow.asinf.dst_as = htonl(ntohs(nf7_flow->dest_as)); flow.asinf.src_mask = nf7_flow->src_mask; flow.asinf.dst_mask = nf7_flow->dst_mask; flow.finf.flow_sequence = nf7_hdr->flow_sequence; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ADD IMED /*sem_wait (&semFlows); Add_flow(&flow); sem_post (&semFlows); */ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// process_flow(&flow, conf, log_fd, log_socket); } }
void netflow_format_flow(struct store_flow_complete* flow, char* buf, size_t len, int utc_flag, u_int32_t display_mask, int hostorder) { char tmp[256]; u_int32_t fields; u_int64_t (*fmt_ntoh64)(u_int64_t) = netflow_swp_ntoh64; u_int32_t (*fmt_ntoh32)(u_int32_t) = netflow_swp_ntoh32; u_int16_t (*fmt_ntoh16)(u_int16_t) = netflow_swp_ntoh16; if (hostorder) { fmt_ntoh64 = netflow_swp_fake64; fmt_ntoh32 = netflow_swp_fake32; fmt_ntoh16 = netflow_swp_fake16; } *buf = '\0'; fields = fmt_ntoh32(flow->hdr.fields) & display_mask; strlcat(buf, "FLOW ", len); if (SHASFIELD(TAG)) { snprintf(tmp, sizeof(tmp), "tag %u ", fmt_ntoh32(flow->tag.tag)); strlcat(buf, tmp, len); } if (SHASFIELD(RECV_TIME)) { snprintf(tmp, sizeof(tmp), "recv_time %s.%05d ", iso_time(fmt_ntoh32(flow->recv_time.recv_sec), utc_flag), fmt_ntoh32(flow->recv_time.recv_usec)); strlcat(buf, tmp, len); } if (SHASFIELD(PROTO_FLAGS_TOS)) { snprintf(tmp, sizeof(tmp), "proto %d ", flow->pft.protocol); strlcat(buf, tmp, len); snprintf(tmp, sizeof(tmp), "tcpflags %02x ", flow->pft.tcp_flags); strlcat(buf, tmp, len); snprintf(tmp, sizeof(tmp), "tos %02x " , flow->pft.tos); strlcat(buf, tmp, len); } if (SHASFIELD(AGENT_ADDR4) || SHASFIELD(AGENT_ADDR6)) { snprintf(tmp, sizeof(tmp), "agent [%s] ", addr_ntop_buf(&flow->agent_addr)); strlcat(buf, tmp, len); } if (SHASFIELD(SRC_ADDR4) || SHASFIELD(SRC_ADDR6)) { snprintf(tmp, sizeof(tmp), "src [%s]", addr_ntop_buf(&flow->src_addr)); strlcat(buf, tmp, len); if (SHASFIELD(SRCDST_PORT)) { snprintf(tmp, sizeof(tmp), ":%d", fmt_ntoh16(flow->ports.src_port)); strlcat(buf, tmp, len); } strlcat(buf, " ", len); } if (SHASFIELD(DST_ADDR4) || SHASFIELD(DST_ADDR6)) { snprintf(tmp, sizeof(tmp), "dst [%s]", addr_ntop_buf(&flow->dst_addr)); strlcat(buf, tmp, len); if (SHASFIELD(SRCDST_PORT)) { snprintf(tmp, sizeof(tmp), ":%d", fmt_ntoh16(flow->ports.dst_port)); strlcat(buf, tmp, len); } strlcat(buf, " ", len); } if (SHASFIELD(GATEWAY_ADDR4) || SHASFIELD(GATEWAY_ADDR6)) { snprintf(tmp, sizeof(tmp), "gateway [%s] ", addr_ntop_buf(&flow->gateway_addr)); strlcat(buf, tmp, len); } if (SHASFIELD(PACKETS)) { snprintf(tmp, sizeof(tmp), "packets %lu ", fmt_ntoh64(flow->packets.flow_packets)); strlcat(buf, tmp, len); } if (SHASFIELD(OCTETS)) { snprintf(tmp, sizeof(tmp), "octets %lu ", fmt_ntoh64(flow->octets.flow_octets)); strlcat(buf, tmp, len); } if (SHASFIELD(IF_INDICES)) { snprintf(tmp, sizeof(tmp), "in_if %d out_if %d ", fmt_ntoh32(flow->ifndx.if_index_in), fmt_ntoh32(flow->ifndx.if_index_out)); strlcat(buf, tmp, len); } if (SHASFIELD(AGENT_INFO)) { snprintf(tmp, sizeof(tmp), "sys_uptime_ms %s.%03u ", interval_time(fmt_ntoh32(flow->ainfo.sys_uptime_ms) / 1000), fmt_ntoh32(flow->ainfo.sys_uptime_ms) % 1000); strlcat(buf, tmp, len); snprintf(tmp, sizeof(tmp), "time_sec %s ", iso_time(fmt_ntoh32(flow->ainfo.time_sec), utc_flag)); strlcat(buf, tmp, len); snprintf(tmp, sizeof(tmp), "time_nanosec %lu netflow ver %u ", (u_long)fmt_ntoh32(flow->ainfo.time_nanosec), fmt_ntoh16(flow->ainfo.netflow_version)); strlcat(buf, tmp, len); } if (SHASFIELD(FLOW_TIMES)) { snprintf(tmp, sizeof(tmp), "flow_start %s.%03u ", interval_time(fmt_ntoh32(flow->ftimes.flow_start) / 1000), fmt_ntoh32(flow->ftimes.flow_start) % 1000); strlcat(buf, tmp, len); snprintf(tmp, sizeof(tmp), "flow_finish %s.%03u ", interval_time(fmt_ntoh32(flow->ftimes.flow_finish) / 1000), fmt_ntoh32(flow->ftimes.flow_finish) % 1000); strlcat(buf, tmp, len); } if (SHASFIELD(AS_INFO)) { snprintf(tmp, sizeof(tmp), "src_AS %u src_masklen %u ", fmt_ntoh32(flow->asinf.src_as), flow->asinf.src_mask); strlcat(buf, tmp, len); snprintf(tmp, sizeof(tmp), "dst_AS %u dst_masklen %u ", fmt_ntoh32(flow->asinf.dst_as), flow->asinf.dst_mask); strlcat(buf, tmp, len); } if (SHASFIELD(FLOW_ENGINE_INFO)) { snprintf(tmp, sizeof(tmp), "engine_type %u engine_id %u seq %lu source %lu ", fmt_ntoh16(flow->finf.engine_type), fmt_ntoh16(flow->finf.engine_id), (u_long)fmt_ntoh32(flow->finf.flow_sequence), (u_long)fmt_ntoh32(flow->finf.source_id)); strlcat(buf, tmp, len); } if (SHASFIELD(CRC32)) { snprintf(tmp, sizeof(tmp), "crc32 %08x ", fmt_ntoh32(flow->crc32.crc32)); strlcat(buf, tmp, len); } }
void process_netflow_v5(struct flow_packet* fp, struct peer_state* peer) { 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 %zu", 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(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; rte_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) (netflow_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 = htonl(ntohs(nf5_flow->src_as)); flow.asinf.dst_as = htonl(ntohs(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; process_flow(&flow); } }
uint8_t* ss_metadata_prepare_netflow( const char* source, nn_queue_t* nn_queue, struct store_flow_complete* flow, ss_ioc_entry_t* ioc_entry) { json_object* jobject = NULL; json_object* item = NULL; uint8_t* rv = NULL; uint8_t* jstring = NULL; uint32_t fields; uint64_t (*fmt_ntoh64)(uint64_t) = netflow_swp_ntoh64; uint32_t (*fmt_ntoh32)(uint32_t) = netflow_swp_ntoh32; uint16_t (*fmt_ntoh16)(uint16_t) = netflow_swp_ntoh16; uint32_t display_mask = STORE_DISPLAY_ALL; fields = fmt_ntoh32(flow->hdr.fields) & display_mask; int utc_flag = 0; jobject = json_object_new_object(); if (jobject == NULL) { RTE_LOG(ERR, EXTRACTOR, "could not allocate netflow json object\n"); goto error_out; } if (SHASFIELD(TAG)) { item = json_object_new_int(fmt_ntoh32(flow->tag.tag)); json_object_object_add(jobject, "tag", item); } if (SHASFIELD(RECV_TIME)) { item = json_object_new_string(iso_time(fmt_ntoh32(flow->recv_time.recv_sec), utc_flag)); json_object_object_add(jobject, "flow_sec", item); item = json_object_new_int(fmt_ntoh32(flow->recv_time.recv_usec)); json_object_object_add(jobject, "flow_usec", item); } if (SHASFIELD(PROTO_FLAGS_TOS)) { item = json_object_new_int(flow->pft.protocol); json_object_object_add(jobject, "ip_protocol", item); item = json_object_new_int(flow->pft.tcp_flags); json_object_object_add(jobject, "tcp_flags", item); item = json_object_new_int(flow->pft.tos); json_object_object_add(jobject, "ip_tos", item); } if (SHASFIELD(AGENT_ADDR4) || SHASFIELD(AGENT_ADDR6)) { item = json_object_new_string(addr_ntop_buf(&flow->agent_addr)); json_object_object_add(jobject, "agentip", item); } if (SHASFIELD(SRC_ADDR4) || SHASFIELD(SRC_ADDR6)) { item = json_object_new_string(addr_ntop_buf(&flow->src_addr)); json_object_object_add(jobject, "sip", item); item = json_object_new_int(fmt_ntoh16(flow->ports.src_port)); json_object_object_add(jobject, "sport", item); } if (SHASFIELD(DST_ADDR4) || SHASFIELD(DST_ADDR6)) { item = json_object_new_string(addr_ntop_buf(&flow->dst_addr)); json_object_object_add(jobject, "dip", item); item = json_object_new_int(fmt_ntoh16(flow->ports.dst_port)); json_object_object_add(jobject, "dport", item); } if (SHASFIELD(GATEWAY_ADDR4) || SHASFIELD(GATEWAY_ADDR6)) { item = json_object_new_string(addr_ntop_buf(&flow->gateway_addr)); json_object_object_add(jobject, "gatewayip", item); } if (SHASFIELD(PACKETS)) { item = json_object_new_int(fmt_ntoh64(flow->packets.flow_packets)); json_object_object_add(jobject, "packets", item); } if (SHASFIELD(OCTETS)) { item = json_object_new_int(fmt_ntoh64(flow->octets.flow_octets)); json_object_object_add(jobject, "bytes", item); } if (SHASFIELD(IF_INDICES)) { item = json_object_new_int(fmt_ntoh32(flow->ifndx.if_index_in)); json_object_object_add(jobject, "sifindex", item); item = json_object_new_int(fmt_ntoh32(flow->ifndx.if_index_out)); json_object_object_add(jobject, "difindex", item); } if (SHASFIELD(AGENT_INFO)) { item = json_object_new_string(interval_time(fmt_ntoh32(flow->ainfo.sys_uptime_ms) / 1000)); json_object_object_add(jobject, "sys_uptime_sec", item); item = json_object_new_int(fmt_ntoh32(flow->ainfo.sys_uptime_ms) % 1000); json_object_object_add(jobject, "sys_uptime_msec", item); item = json_object_new_string(iso_time(fmt_ntoh32(flow->ainfo.time_sec), utc_flag)); json_object_object_add(jobject, "sys_time_sec", item); item = json_object_new_int((u_long)fmt_ntoh32(flow->ainfo.time_nanosec)); json_object_object_add(jobject, "sys_time_nsec", item); item = json_object_new_int(fmt_ntoh16(flow->ainfo.netflow_version)); json_object_object_add(jobject, "netflow_version", item); } if (SHASFIELD(FLOW_TIMES)) { item = json_object_new_string(interval_time(fmt_ntoh32(flow->ftimes.flow_start) / 1000)); json_object_object_add(jobject, "flow_start_sec", item); item = json_object_new_int(fmt_ntoh32(flow->ftimes.flow_start) % 1000); json_object_object_add(jobject, "flow_start_msec", item); item = json_object_new_string(interval_time(fmt_ntoh32(flow->ftimes.flow_finish) / 1000)); json_object_object_add(jobject, "flow_stop_sec", item); item = json_object_new_int(fmt_ntoh32(flow->ftimes.flow_finish) % 1000); json_object_object_add(jobject, "flow_stop_msec", item); } if (SHASFIELD(AS_INFO)) { item = json_object_new_int(fmt_ntoh32(flow->asinf.src_as)); json_object_object_add(jobject, "src_as", item); item = json_object_new_int(fmt_ntoh32(flow->asinf.src_mask)); json_object_object_add(jobject, "src_masklen", item); item = json_object_new_int(fmt_ntoh32(flow->asinf.dst_as)); json_object_object_add(jobject, "dst_as", item); item = json_object_new_int(fmt_ntoh32(flow->asinf.dst_mask)); json_object_object_add(jobject, "dst_masklen", item); } if (SHASFIELD(FLOW_ENGINE_INFO)) { item = json_object_new_int(fmt_ntoh16(flow->finf.engine_type)); json_object_object_add(jobject, "engine_type", item); item = json_object_new_int(fmt_ntoh16(flow->finf.engine_id)); json_object_object_add(jobject, "engine_id", item); item = json_object_new_int((u_long)fmt_ntoh32(flow->finf.flow_sequence)); json_object_object_add(jobject, "seq_num", item); item = json_object_new_int((u_long)fmt_ntoh32(flow->finf.source_id)); json_object_object_add(jobject, "source_id", item); } if (SHASFIELD(CRC32)) { item = json_object_new_int(fmt_ntoh32(flow->crc32.crc32)); json_object_object_add(jobject, "crc32", item); } item = NULL; rv = 0; // XXX: NOTE: String pointer is internal to JSON object. jstring = (uint8_t*) json_object_to_json_string_ext(jobject, JSON_C_TO_STRING_SPACED); rv = (uint8_t*) je_strdup((char*)jstring); if (!rv) goto error_out; json_object_put(jobject); jobject = NULL; return rv; error_out: fprintf(stderr, "could not serialize packet metadata\n"); if (rv) { je_free(rv); rv = NULL; } if (jobject) { json_object_put(jobject); jobject = NULL; } if (item) { json_object_put(item); item = NULL; } return NULL; }