/* * Given an array of expired flows, send netflow v1 report packets * Returns number of packets sent or -1 on error */ int send_netflow_v1(struct FLOW **flows, int num_flows, int nfsock, u_int64_t *flows_exported, struct timeval *system_boot_time, int verbose_flag) { struct timeval now; u_int32_t uptime_ms; u_int8_t packet[NF1_MAXPACKET_SIZE]; /* Maximum allowed packet size (24 flows) */ struct NF1_HEADER *hdr = NULL; struct NF1_FLOW *flw = NULL; int i, j, offset, num_packets, err; socklen_t errsz; gettimeofday(&now, NULL); uptime_ms = timeval_sub_ms(&now, system_boot_time); hdr = (struct NF1_HEADER *)packet; for(num_packets = offset = j = i = 0; i < num_flows; i++) { if (j >= NF1_MAXFLOWS - 1) { if (verbose_flag) logit(LOG_DEBUG, "Sending flow packet len = %d", offset); hdr->flows = htons(hdr->flows); errsz = sizeof(err); getsockopt(nfsock, SOL_SOCKET, SO_ERROR, &err, &errsz); /* Clear ICMP errors */ if (send(nfsock, packet, (size_t)offset, 0) == -1) return (-1); *flows_exported += j; j = 0; num_packets++; } if (j == 0) { memset(&packet, '\0', sizeof(packet)); hdr->version = htons(1); hdr->flows = 0; /* Filled in as we go */ hdr->uptime_ms = htonl(uptime_ms); hdr->time_sec = htonl(now.tv_sec); hdr->time_nanosec = htonl(now.tv_usec * 1000); offset = sizeof(*hdr); } flw = (struct NF1_FLOW *)(packet + offset); /* NetFlow v.1 doesn't do IPv6 */ if (flows[i]->af != AF_INET) continue; if (flows[i]->octets[0] > 0) { flw->src_ip = flows[i]->addr[0].v4.s_addr; flw->dest_ip = flows[i]->addr[1].v4.s_addr; flw->src_port = flows[i]->port[0]; flw->dest_port = flows[i]->port[1]; flw->flow_packets = htonl(flows[i]->packets[0]); flw->flow_octets = htonl(flows[i]->octets[0]); flw->flow_start = htonl(timeval_sub_ms(&flows[i]->flow_start, system_boot_time)); flw->flow_finish = htonl(timeval_sub_ms(&flows[i]->flow_last, system_boot_time)); flw->protocol = flows[i]->protocol; flw->tcp_flags = flows[i]->tcp_flags[0]; offset += sizeof(*flw); j++; hdr->flows++; } flw = (struct NF1_FLOW *)(packet + offset); if (flows[i]->octets[1] > 0) { flw->src_ip = flows[i]->addr[1].v4.s_addr; flw->dest_ip = flows[i]->addr[0].v4.s_addr; flw->src_port = flows[i]->port[1]; flw->dest_port = flows[i]->port[0]; flw->flow_packets = htonl(flows[i]->packets[1]); flw->flow_octets = htonl(flows[i]->octets[1]); flw->flow_start = htonl(timeval_sub_ms(&flows[i]->flow_start, system_boot_time)); flw->flow_finish = htonl(timeval_sub_ms(&flows[i]->flow_last, system_boot_time)); flw->protocol = flows[i]->protocol; flw->tcp_flags = flows[i]->tcp_flags[1]; offset += sizeof(*flw); j++; hdr->flows++; } } /* Send any leftovers */ if (j != 0) { if (verbose_flag) logit(LOG_DEBUG, "Sending flow packet len = %d", offset); hdr->flows = htons(hdr->flows); errsz = sizeof(err); getsockopt(nfsock, SOL_SOCKET, SO_ERROR, &err, &errsz); /* Clear ICMP errors */ if (send(nfsock, packet, (size_t)offset, 0) == -1) return (-1); num_packets++; } *flows_exported += j; return (num_packets); }
static int send_netflow_v5(const struct pfsync_state *st, u_int n, u_int *flows_exp) { char now_s[64]; int i, j, offset, num_packets, err; socklen_t errsz; struct NF5_FLOW *flw = NULL; struct NF5_HEADER *hdr = NULL; struct timeval now_tv; struct tm now_tm; time_t now; u_int32_t uptime_ms; u_int8_t packet[NF5_MAXPACKET_SIZE]; #ifdef NF9 int src_idx, dst_idx; #endif #if __FreeBSD_version > 900000 const struct pfsync_state_key *nk; #endif if (verbose_flag) { now = time(NULL); localtime_r(&now, &now_tm); strftime(now_s, sizeof(now_s), "%Y-%m-%dT%H:%M:%S", &now_tm); } gettimeofday(&now_tv, NULL); uptime_ms = timeval_sub_ms(&now_tv, &start_time); hdr = (struct NF5_HEADER *)packet; for(num_packets = offset = j = i = 0; i < n; i++) { struct pf_state_host src, dst; u_int32_t bytes_in, bytes_out, packets_in, packets_out; u_int32_t creation; char src_s[64], dst_s[64], rt_s[64], pbuf[16], creation_s[64]; time_t creation_tt; struct tm creation_tm; if (netflow_socket != -1 && j >= NF5_MAXFLOWS - 1) { if (verbose_flag) { syslog(LOG_DEBUG, "Sending flow packet len = %d", offset); } hdr->flows = htons(hdr->flows); errsz = sizeof(err); getsockopt(netflow_socket, SOL_SOCKET, SO_ERROR, &err, &errsz); /* Clear ICMP errors */ if (send(netflow_socket, packet, (size_t)offset, 0) == -1) { syslog(LOG_DEBUG, "send: %s", strerror(errno)); return -1; } j = 0; num_packets++; } if (netflow_socket != -1 && j == 0) { memset(&packet, '\0', sizeof(packet)); hdr->version = htons(5); hdr->flows = 0; /* Filled in as we go */ hdr->uptime_ms = htonl(uptime_ms); hdr->time_sec = htonl(now_tv.tv_sec); hdr->time_nanosec = htonl(now_tv.tv_usec * 1000); hdr->flow_sequence = htonl(*flows_exp); /* Other fields are left zero */ offset = sizeof(*hdr); } if (st[i].af != AF_INET) continue; if (direction != 0 && st[i].direction != direction) continue; /* Copy/convert only what we can eat */ creation = ntohl(st[i].creation) * 1000; if (creation > uptime_ms) creation = uptime_ms; /* Avoid u_int wrap */ #if __FreeBSD_version > 900000 if (st[i].direction == PF_OUT) { nk = &st[i].key[PF_SK_WIRE]; } else { nk = &st[i].key[PF_SK_STACK]; } src.addr = nk->addr[1]; src.port = nk->port[1]; dst.addr = nk->addr[0]; dst.port = nk->port[0]; #else if (st[i].direction == PF_OUT) { memcpy(&src, &st[i].lan, sizeof(src)); memcpy(&dst, &st[i].ext, sizeof(dst)); } else { memcpy(&src, &st[i].ext, sizeof(src)); memcpy(&dst, &st[i].lan, sizeof(dst)); } #endif #ifdef NF9 src_idx = resolve_interface(&src.addr, st[i].af); dst_idx = resolve_interface(&dst.addr, st[i].af); #endif flw = (struct NF5_FLOW *)(packet + offset); #ifdef NF9 if (netflow_socket != -1 && st[i].packets[0][1] != 0) #else if (netflow_socket != -1 && st[i].packets[0][0] != 0) #endif { flw->src_ip = src.addr.v4.s_addr; flw->dest_ip = dst.addr.v4.s_addr; flw->src_port = src.port; flw->dest_port = dst.port; #ifdef NF9 flw->flow_packets = st[i].packets[0][1]; flw->flow_octets = st[i].bytes[0][1]; flw->if_index_in = htons(src_idx); flw->if_index_out= htons(dst_idx); #else flw->flow_packets = st[i].packets[0][0]; flw->flow_octets = st[i].bytes[0][0]; #endif flw->flow_start = htonl(uptime_ms - creation); flw->flow_finish = htonl(uptime_ms); flw->tcp_flags = 0; flw->protocol = st[i].proto; offset += sizeof(*flw); j++; hdr->flows++; } flw = (struct NF5_FLOW *)(packet + offset); #ifdef NF9 if (netflow_socket != -1 && st[i].packets[1][1] != 0) #else if (netflow_socket != -1 && st[i].packets[1][0] != 0) #endif { flw->src_ip = dst.addr.v4.s_addr; flw->dest_ip = src.addr.v4.s_addr; flw->src_port = dst.port; flw->dest_port = src.port; #ifdef NF9 flw->flow_packets = st[i].packets[1][1]; flw->flow_octets = st[i].bytes[1][1]; flw->if_index_in = htons(dst_idx); flw->if_index_out= htons(src_idx); #else flw->flow_packets = st[i].packets[1][0]; flw->flow_octets = st[i].bytes[1][0]; #endif flw->flow_start = htonl(uptime_ms - creation); flw->flow_finish = htonl(uptime_ms); flw->tcp_flags = 0; flw->protocol = st[i].proto; offset += sizeof(*flw); j++; hdr->flows++; } flw = (struct NF5_FLOW *)(packet + offset); if (verbose_flag) { #ifdef NF9 packets_out = ntohl(st[i].packets[0][1]); packets_in = ntohl(st[i].packets[1][1]); bytes_out = ntohl(st[i].bytes[0][1]); bytes_in = ntohl(st[i].bytes[1][1]); #else packets_out = ntohl(st[i].packets[0][0]); packets_in = ntohl(st[i].packets[1][0]); bytes_out = ntohl(st[i].bytes[0][0]); bytes_in = ntohl(st[i].bytes[1][0]); #endif creation_tt = now - (creation / 1000); localtime_r(&creation_tt, &creation_tm); strftime(creation_s, sizeof(creation_s), "%Y-%m-%dT%H:%M:%S", &creation_tm); format_pf_host(src_s, sizeof(src_s), &src, st[i].af); format_pf_host(dst_s, sizeof(dst_s), &dst, st[i].af); inet_ntop(st[i].af, &st[i].rt_addr, rt_s, sizeof(rt_s)); if (st[i].proto == IPPROTO_TCP || st[i].proto == IPPROTO_UDP) { snprintf(pbuf, sizeof(pbuf), ":%d", ntohs(src.port)); strlcat(src_s, pbuf, sizeof(src_s)); snprintf(pbuf, sizeof(pbuf), ":%d", ntohs(dst.port)); strlcat(dst_s, pbuf, sizeof(dst_s)); } syslog(LOG_DEBUG, "IFACE %s", st[i].ifname); syslog(LOG_DEBUG, "GWY %s", rt_s); syslog(LOG_DEBUG, "FLOW proto %d direction %d", st[i].proto, st[i].direction); syslog(LOG_DEBUG, "\tstart %s(%u) finish %s(%u)", creation_s, uptime_ms - creation, now_s, uptime_ms); syslog(LOG_DEBUG, "\t%s -> %s %d bytes %d packets", src_s, dst_s, bytes_out, packets_out); syslog(LOG_DEBUG, "\t%s -> %s %d bytes %d packets", dst_s, src_s, bytes_in, packets_in); } } /* Send any leftovers */ if (netflow_socket != -1 && j != 0) { if (verbose_flag) { syslog(LOG_DEBUG, "Sending flow packet len = %d", offset); } hdr->flows = htons(hdr->flows); errsz = sizeof(err); getsockopt(netflow_socket, SOL_SOCKET, SO_ERROR, &err, &errsz); /* Clear ICMP errors */ if (send(netflow_socket, packet, (size_t)offset, 0) == -1) { syslog(LOG_DEBUG, "send: %s", strerror(errno)); return -1; } num_packets++; } return (ntohs(hdr->flows)); }
static int nf_flow_to_flowset(const struct FLOW *flow, u_char *packet, u_int len, u_int16_t ifidx, const struct timeval *system_boot_time, u_int *len_used) { union { struct NF9_SOFTFLOWD_DATA_V4 d4; struct NF9_SOFTFLOWD_DATA_V6 d6; } d[2]; struct NF9_SOFTFLOWD_DATA_COMMON *dc[2]; u_int freclen, ret_len, nflows; bzero(d, sizeof(d)); *len_used = nflows = ret_len = 0; switch (flow->af) { case AF_INET: freclen = sizeof(struct NF9_SOFTFLOWD_DATA_V4); memcpy(&d[0].d4.src_addr, &flow->addr[0].v4, 4); memcpy(&d[0].d4.dst_addr, &flow->addr[1].v4, 4); memcpy(&d[1].d4.src_addr, &flow->addr[1].v4, 4); memcpy(&d[1].d4.dst_addr, &flow->addr[0].v4, 4); dc[0] = &d[0].d4.c; dc[1] = &d[1].d4.c; dc[0]->ipproto = dc[1]->ipproto = 4; break; case AF_INET6: freclen = sizeof(struct NF9_SOFTFLOWD_DATA_V6); memcpy(&d[0].d6.src_addr, &flow->addr[0].v6, 16); memcpy(&d[0].d6.dst_addr, &flow->addr[1].v6, 16); memcpy(&d[1].d6.src_addr, &flow->addr[1].v6, 16); memcpy(&d[1].d6.dst_addr, &flow->addr[0].v6, 16); dc[0] = &d[0].d6.c; dc[1] = &d[1].d6.c; dc[0]->ipproto = dc[1]->ipproto = 6; break; default: return (-1); } dc[0]->first_switched = dc[1]->first_switched = htonl(timeval_sub_ms(&flow->flow_start, system_boot_time)); dc[0]->last_switched = dc[1]->last_switched = htonl(timeval_sub_ms(&flow->flow_last, system_boot_time)); dc[0]->bytes = htonl(flow->octets[0]); dc[1]->bytes = htonl(flow->octets[1]); dc[0]->packets = htonl(flow->packets[0]); dc[1]->packets = htonl(flow->packets[1]); dc[0]->if_index_in = dc[0]->if_index_out = htonl(ifidx); dc[1]->if_index_in = dc[1]->if_index_out = htonl(ifidx); dc[0]->src_port = dc[1]->dst_port = flow->port[0]; dc[1]->src_port = dc[0]->dst_port = flow->port[1]; dc[0]->protocol = dc[1]->protocol = flow->protocol; dc[0]->tcp_flags = flow->tcp_flags[0]; dc[1]->tcp_flags = flow->tcp_flags[1]; dc[0]->tos = flow->tos[0]; dc[1]->tos = flow->tos[1]; #ifdef ENABLE_NF9_VLAN if (flow->protocol == IPPROTO_ICMP || flow->protocol == IPPROTO_ICMPV6) { dc[0]->icmp_type = dc[0]->dst_port; dc[1]->icmp_type = dc[1]->dst_port; } dc[0]->vlanid = dc[1]->vlanid = htons(flow->vlanid); #endif /* ENABLE_NF9_VLAN */ if (flow->octets[0] > 0) { if (ret_len + freclen > len) return (-1); memcpy(packet + ret_len, &d[0], freclen); ret_len += freclen; nflows++; } if (flow->octets[1] > 0) { if (ret_len + freclen > len) return (-1); memcpy(packet + ret_len, &d[1], freclen); ret_len += freclen; nflows++; } *len_used = ret_len; return (nflows); }
/* * Given an array of expired flows, send netflow v9 report packets * Returns number of packets sent or -1 on error */ int send_netflow_v9(struct FLOW **flows, int num_flows, int nfsock, u_int16_t ifidx, struct FLOWTRACKPARAMETERS *param, int verbose_flag) { struct NF9_HEADER *nf9; struct NF9_DATA_FLOWSET_HEADER *dh; struct timeval now; u_int offset, last_af, i, j, num_packets, inc, last_valid; socklen_t errsz; int err, r; u_char packet[NF9_SOFTFLOWD_MAX_PACKET_SIZE]; struct timeval *system_boot_time = ¶m->system_boot_time; u_int64_t *flows_exported = ¶m->flows_exported; u_int64_t *packets_sent = ¶m->packets_sent; struct OPTION *option = ¶m->option; gettimeofday(&now, NULL); if (nf9_pkts_until_template == -1) { nf9_init_template(); nf9_pkts_until_template = 0; if (option != NULL && option->sample > 1){ nf9_init_option(ifidx, option); } } last_valid = num_packets = 0; for (j = 0; j < num_flows;) { bzero(packet, sizeof(packet)); nf9 = (struct NF9_HEADER *)packet; nf9->version = htons(9); nf9->flows = 0; /* Filled as we go, htons at end */ nf9->uptime_ms = htonl(timeval_sub_ms(&now, system_boot_time)); nf9->time_sec = htonl(time(NULL)); nf9->source_id = 0; offset = sizeof(*nf9); /* Refresh template headers if we need to */ if (nf9_pkts_until_template <= 0) { memcpy(packet + offset, &v4_template, sizeof(v4_template)); offset += sizeof(v4_template); nf9->flows++; memcpy(packet + offset, &v6_template, sizeof(v6_template)); offset += sizeof(v6_template); nf9->flows++; if (option != NULL && option->sample > 1){ memcpy(packet + offset, &option_template, sizeof(option_template)); offset += sizeof(option_template); nf9->flows++; memcpy(packet + offset, &option_data, sizeof(option_data)); offset += sizeof(option_data); nf9->flows++; } nf9_pkts_until_template = NF9_DEFAULT_TEMPLATE_INTERVAL; } dh = NULL; last_af = 0; for (i = 0; i + j < num_flows; i++) { if (dh == NULL || flows[i + j]->af != last_af) { if (dh != NULL) { if (offset % 4 != 0) { /* Pad to multiple of 4 */ dh->c.length += 4 - (offset % 4); offset += 4 - (offset % 4); } /* Finalise last header */ dh->c.length = htons(dh->c.length); } if (offset + sizeof(*dh) > sizeof(packet)) { /* Mark header is finished */ dh = NULL; break; } dh = (struct NF9_DATA_FLOWSET_HEADER *) (packet + offset); dh->c.flowset_id = (flows[i + j]->af == AF_INET) ? v4_template.h.template_id : v6_template.h.template_id; last_af = flows[i + j]->af; last_valid = offset; dh->c.length = sizeof(*dh); /* Filled as we go */ offset += sizeof(*dh); } r = nf_flow_to_flowset(flows[i + j], packet + offset, sizeof(packet) - offset, ifidx, system_boot_time, &inc); if (r <= 0) { /* yank off data header, if we had to go back */ if (last_valid) offset = last_valid; break; } offset += inc; dh->c.length += inc; nf9->flows += r; last_valid = 0; /* Don't clobber this header now */ if (verbose_flag) { logit(LOG_DEBUG, "Flow %d/%d: " "r %d offset %d type %04x len %d(0x%04x) " "flows %d", r, i, j, offset, dh->c.flowset_id, dh->c.length, dh->c.length, nf9->flows); } } /* Don't finish header if it has already been done */ if (dh != NULL) { if (offset % 4 != 0) { /* Pad to multiple of 4 */ dh->c.length += 4 - (offset % 4); offset += 4 - (offset % 4); } /* Finalise last header */ dh->c.length = htons(dh->c.length); } param->records_sent += nf9->flows; nf9->flows = htons(nf9->flows); nf9->package_sequence = htonl((u_int32_t)((*packets_sent + num_packets + 1) & 0x00000000ffffffff)); if (verbose_flag) logit(LOG_DEBUG, "Sending flow packet len = %d", offset); errsz = sizeof(err); /* Clear ICMP errors */ getsockopt(nfsock, SOL_SOCKET, SO_ERROR, &err, &errsz); if (send(nfsock, packet, (size_t)offset, 0) == -1) return (-1); num_packets++; nf9_pkts_until_template--; j += i; } *flows_exported += j; return (num_packets); }
/* * Given an array of expired flows, send netflow v5 report packets * Returns number of packets sent or -1 on error */ int send_netflow_v5(struct FLOW **flows, int num_flows, int nfsock, u_int64_t *flows_exported, struct timeval *system_boot_time, int verbose_flag, int inOut) { struct timeval now; u_int32_t uptime_ms; u_int8_t packet[NF5_MAXPACKET_SIZE]; /* Maximum allowed packet size (24 flows) */ struct NF5_HEADER *hdr = NULL; struct NF5_FLOW *flw = NULL; int i, j, offset, num_packets, err; socklen_t errsz; gettimeofday(&now, NULL); uptime_ms = timeval_sub_ms(&now, system_boot_time); hdr = (struct NF5_HEADER *)packet; for (num_packets = offset = j = i = 0; i < num_flows; i++) { if (j >= NF5_MAXFLOWS - 1) { if (verbose_flag) logit(LOG_DEBUG, "Sending flow packet len = %d", offset); hdr->flows = htons(hdr->flows); errsz = sizeof(err); getsockopt(nfsock, SOL_SOCKET, SO_ERROR, &err, &errsz); /* Clear ICMP errors */ if (send(nfsock, packet, (size_t)offset, 0) == -1) return (-1); *flows_exported += j; j = 0; num_packets++; } if (j == 0) { memset(&packet, '\0', sizeof(packet)); hdr->version = htons(5); hdr->flows = 0; /* Filled in as we go */ hdr->uptime_ms = htonl(uptime_ms); hdr->time_sec = htonl(now.tv_sec); hdr->time_nanosec = htonl(now.tv_usec * 1000); hdr->flow_sequence = htonl(*flows_exported); // Copy the emulator monitor source adr hdr->emulator_monitor_adr = 0; /* Other fields are left zero */ offset = sizeof(*hdr); } flw = (struct NF5_FLOW *)(packet + offset); /* NetFlow v.5 doesn't do IPv6 */ if (flows[i]->af != AF_INET) continue; // Copy the emulator monitor source adr if(j == 0 && using_emulator) { hdr->emulator_monitor_adr = flows[i]->selected_monitor.s_addr; } if(!using_emulator) { if (flows[i]->octets[0] > 0 ) { flw->src_as = flows[i]->as_src[0]; flw->dest_as = flows[i]->as_dst[1]; flw->src_ip = flows[i]->addr[0].v4.s_addr; flw->dest_ip = flows[i]->addr[1].v4.s_addr; flw->src_port = flows[i]->port[0]; flw->dest_port = flows[i]->port[1]; flw->flow_packets = htonl(flows[i]->packets[0]); flw->flow_octets = htonl(flows[i]->octets[0]); flw->flow_start = htonl(timeval_sub_ms(&flows[i]->flow_start, system_boot_time)); flw->flow_finish = htonl(timeval_sub_ms(&flows[i]->flow_last, system_boot_time)); flw->tcp_flags = flows[i]->tcp_flags[0]; flw->protocol = flows[i]->protocol; offset += sizeof(*flw); j++; hdr->flows++; } } else { if (flows[i]->monitor_stat_0[flows[i]->selected_monitor_index].octets > 0 && inOut == 0 ) { flw->emulator_monitor_adr = flows[i]->selected_monitor.s_addr; flw->src_as = flows[i]->as_src[0]; flw->dest_as = flows[i]->as_dst[1]; flw->src_ip = flows[i]->addr[0].v4.s_addr; flw->dest_ip = flows[i]->addr[1].v4.s_addr; flw->src_port = flows[i]->port[0]; flw->dest_port = flows[i]->port[1]; flw->flow_packets = htonl(flows[i]->monitor_stat_0[flows[i]->selected_monitor_index].packets); flw->flow_octets = htonl(flows[i]->monitor_stat_0[flows[i]->selected_monitor_index].octets); flw->flow_start = htonl(timeval_sub_ms(&flows[i]->flow_start, system_boot_time)); flw->flow_finish = htonl(timeval_sub_ms(&flows[i]->flow_last, system_boot_time)); flw->tcp_flags = flows[i]->tcp_flags[0]; flw->protocol = flows[i]->protocol; offset += sizeof(*flw); j++; hdr->flows++; } } flw = (struct NF5_FLOW *)(packet + offset); if(!using_emulator) { if (flows[i]->octets[1] > 0 ) { flw->src_as = flows[i]->as_src[1]; flw->dest_as = flows[i]->as_dst[0]; flw->src_ip = flows[i]->addr[1].v4.s_addr; flw->dest_ip = flows[i]->addr[0].v4.s_addr; flw->src_port = flows[i]->port[1]; flw->dest_port = flows[i]->port[0]; flw->flow_packets = htonl(flows[i]->packets[1]); flw->flow_octets = htonl(flows[i]->octets[1]); flw->flow_start = htonl(timeval_sub_ms(&flows[i]->flow_start, system_boot_time)); flw->flow_finish = htonl(timeval_sub_ms(&flows[i]->flow_last, system_boot_time)); flw->tcp_flags = flows[i]->tcp_flags[1]; flw->protocol = flows[i]->protocol; offset += sizeof(*flw); j++; hdr->flows++; } } else { if (flows[i]->monitor_stat_1[flows[i]->selected_monitor_index].octets > 0 && inOut == 1 ) { flw->emulator_monitor_adr = flows[i]->selected_monitor.s_addr; flw->src_as = flows[i]->as_src[1]; flw->dest_as = flows[i]->as_dst[0]; flw->src_ip = flows[i]->addr[1].v4.s_addr; flw->dest_ip = flows[i]->addr[0].v4.s_addr; flw->src_port = flows[i]->port[1]; flw->dest_port = flows[i]->port[0]; flw->flow_packets = htonl(flows[i]->monitor_stat_1[flows[i]->selected_monitor_index].packets); flw->flow_octets = htonl(flows[i]->monitor_stat_1[flows[i]->selected_monitor_index].octets); flw->flow_start = htonl(timeval_sub_ms(&flows[i]->flow_start, system_boot_time)); flw->flow_finish = htonl(timeval_sub_ms(&flows[i]->flow_last,system_boot_time)); flw->tcp_flags = flows[i]->tcp_flags[1]; flw->protocol = flows[i]->protocol; offset += sizeof(*flw); j++; hdr->flows++; } } } /* Send any leftovers */ if (j != 0) { if (verbose_flag) logit(LOG_DEBUG, "Sending v5 flow packet len = %d", offset); hdr->flows = htons(hdr->flows); errsz = sizeof(err); getsockopt(nfsock, SOL_SOCKET, SO_ERROR, &err, &errsz); /* Clear ICMP errors */ if (send(nfsock, packet, (size_t)offset, 0) == -1) return (-1); num_packets++; } *flows_exported += j; return (num_packets); }