123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581 |
- Subject: Add ipfix.c to support exporting IPFIX format[t]ed flow records
- Origin: softflowd-0.9.9-4-g417e018 <https://github.com/irino/softflowd/commit/softflowd-0.9.9-4-g417e018>
- Upstream-Author: Hitoshi Irino <hitoshi.irino@gmail.com>
- Date: Mon Dec 10 22:33:53 2012 +0900
- --- a/Makefile.in
- +++ b/Makefile.in
- @@ -25,7 +25,7 @@
- TARGETS=softflowd${EXEEXT} softflowctl${EXEEXT}
-
- COMMON=convtime.o strlcpy.o strlcat.o closefrom.o daemon.o
- -SOFTFLOWD=softflowd.o log.o netflow1.o netflow5.o netflow9.o freelist.o
- +SOFTFLOWD=softflowd.o log.o netflow1.o netflow5.o netflow9.o ipfix.o freelist.o
-
- all: $(TARGETS)
-
- --- a/common.h
- +++ b/common.h
- @@ -70,6 +70,12 @@
- #include <inttypes.h>
- #endif
-
- +#if defined(HAVE_SYS_ENDIAN_H)
- +#include <sys/endian.h>
- +#elif defined(HAVE_ENDIAN_H)
- +#include <endian.h>
- +#endif
- +
- /* The name of the program */
- #define PROGNAME "softflowd"
-
- --- a/configure.ac
- +++ b/configure.ac
- @@ -52,7 +52,7 @@
- [ AC_DEFINE_UNQUOTED([PRIVDROP_CHROOT_DIR], ["${withval}"], [privdrop chroot directory]) ]
- )
-
- -AC_CHECK_HEADERS(net/bpf.h pcap.h pcap-bpf.h)
- +AC_CHECK_HEADERS(net/bpf.h pcap.h pcap-bpf.h sys/endian.h endian.h)
-
- dnl AC_CHECK_HEADERS(netinet/in_systm.h netinet/tcp.h netinet/udp.h)
- dnl
- @@ -87,7 +87,7 @@
- AC_SEARCH_LIBS(socket, socket)
- AC_CHECK_LIB(pcap, pcap_open_live)
-
- -AC_CHECK_FUNCS(closefrom daemon setresuid setreuid setresgid setgid strlcpy strlcat strsep)
- +AC_CHECK_FUNCS(closefrom daemon setresuid setreuid setresgid setgid strlcpy strlcat strsep htobe64 htonll)
-
- AC_CHECK_TYPES([u_int64_t, int64_t, uint64_t, u_int32_t, int32_t, uint32_t])
- AC_CHECK_TYPES([u_int16_t, int16_t, uint16_t, u_int8_t, int8_t, uint8_t])
- --- /dev/null
- +++ b/ipfix.c
- @@ -0,0 +1,480 @@
- +/*
- + * Copyright 2002 Damien Miller <djm@mindrot.org> All rights reserved.
- + * Copyright 2012 Hitoshi Irino <irino@sfc.wide.ad.jp> All rights reserved.
- + *
- + * Redistribution and use in source and binary forms, with or without
- + * modification, are permitted provided that the following conditions
- + * are met:
- + * 1. Redistributions of source code must retain the above copyright
- + * notice, this list of conditions and the following disclaimer.
- + * 2. Redistributions in binary form must reproduce the above copyright
- + * notice, this list of conditions and the following disclaimer in the
- + * documentation and/or other materials provided with the distribution.
- + *
- + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- + */
- +
- +#include "common.h"
- +#include "log.h"
- +#include "treetype.h"
- +#include "softflowd.h"
- +
- +/* IPFIX a.k.a. Netflow v.10 */
- +struct IPFIX_HEADER {
- + u_int16_t version, length;
- + u_int32_t export_time; /* in seconds */
- + u_int32_t sequence, od_id;
- +} __packed;
- +struct IPFIX_SET_HEADER {
- + u_int16_t set_id, length;
- +} __packed;
- +struct IPFIX_TEMPLATE_RECORD_HEADER {
- + u_int16_t template_id, count;
- +} __packed;
- +struct IPFIX_TEMPLATE_SET_HEADER {
- + struct IPFIX_SET_HEADER c;
- + struct IPFIX_TEMPLATE_RECORD_HEADER r;
- +} __packed;
- +struct IPFIX_OPTION_TEMPLATE_SET_HEADER {
- + struct IPFIX_SET_HEADER c;
- + struct IPFIX_TEMPLATE_RECORD_HEADER r;
- + u_int16_t scope_count;
- +} __packed;
- +struct IPFIX_FIELD_SPECIFIER {
- + u_int16_t ie, length;
- +} __packed;
- +
- +#define IPFIX_TEMPLATE_SET_ID 2
- +#define IPFIX_OPTION_TEMPLATE_SET_ID 3
- +#define IPFIX_MIN_RECORD_SET_ID 256
- +
- +/* Flowset record ies the we care about */
- +#define IPFIX_octetDeltaCount 1
- +#define IPFIX_packetDeltaCount 2
- +/* ... */
- +#define IPFIX_protocolIdentifier 4
- +/* ... */
- +#define IPFIX_tcpControlBits 6
- +#define IPFIX_sourceTransportPort 7
- +#define IPFIX_sourceIPv4Address 8
- +/* ... */
- +#define IPFIX_ingressInterface 10
- +#define IPFIX_destinationTransportPort 11
- +#define IPFIX_destinationIPv4Address 12
- +/* ... */
- +#define IPFIX_egressInterface 14
- +/* ... */
- +#define IPFIX_flowEndSysUpTime 21
- +#define IPFIX_flowStartSysUpTime 22
- +/* ... */
- +#define IPFIX_sourceIPv6Address 27
- +#define IPFIX_destinationIPv6Address 28
- +/* ... */
- +#define IPFIX_ipVersion 60
- +
- +#define IPFIX_meteringProcessId 143
- +#define IPFIX_systemInitTimeMilliseconds 160
- +#define PSAMP_selectorAlgorithm 304
- +#define PSAMP_samplingPacketInterval 305
- +#define PSAMP_samplingPacketSpace 306
- +
- +#define PSAMP_selectorAlgorithm_count 1
- +
- +/* Stuff pertaining to the templates that softflowd uses */
- +#define IPFIX_SOFTFLOWD_TEMPLATE_NRECORDS 13
- +struct IPFIX_SOFTFLOWD_TEMPLATE {
- + struct IPFIX_TEMPLATE_SET_HEADER h;
- + struct IPFIX_FIELD_SPECIFIER r[IPFIX_SOFTFLOWD_TEMPLATE_NRECORDS];
- +} __packed;
- +
- +#define IPFIX_SOFTFLOWD_OPTION_TEMPLATE_SCOPE_RECORDS 1
- +#define IPFIX_SOFTFLOWD_OPTION_TEMPLATE_NRECORDS 4
- +struct IPFIX_SOFTFLOWD_OPTION_TEMPLATE {
- + struct IPFIX_OPTION_TEMPLATE_SET_HEADER h;
- + struct IPFIX_FIELD_SPECIFIER s[IPFIX_SOFTFLOWD_OPTION_TEMPLATE_SCOPE_RECORDS];
- + struct IPFIX_FIELD_SPECIFIER r[IPFIX_SOFTFLOWD_OPTION_TEMPLATE_NRECORDS];
- +} __packed;
- +
- +/* softflowd data set */
- +struct IPFIX_SOFTFLOWD_DATA_COMMON {
- + u_int32_t flowEndSysUpTime, flowStartSysUpTime;
- + u_int32_t octetDeltaCount, packetDeltaCount;
- + u_int32_t ingressInterface, egressInterface;
- + u_int16_t sourceTransportPort, destinationTransportPort;
- + u_int8_t protocolIdentifier, tcpControlBits, ipVersion;
- +} __packed;
- +
- +struct IPFIX_SOFTFLOWD_DATA_V4 {
- + u_int32_t sourceIPv4Address, destinationIPv4Address;
- + struct IPFIX_SOFTFLOWD_DATA_COMMON c;
- +} __packed;
- +
- +struct IPFIX_SOFTFLOWD_DATA_V6 {
- + //u_int8_t src_addr[16], dst_addr[16];
- + struct in6_addr sourceIPv6Address, destinationIPv6Address;
- + struct IPFIX_SOFTFLOWD_DATA_COMMON c;
- +} __packed;
- +
- +struct IPFIX_SOFTFLOWD_OPTION_DATA {
- + struct IPFIX_SET_HEADER c;
- + u_int32_t scope_pid;
- + u_int64_t systemInitTimeMilliseconds;
- + u_int16_t samplingAlgorithm;
- + u_int16_t samplingInterval;
- + u_int32_t samplingSpace;
- +} __packed;
- +
- +/* Local data: templates and counters */
- +#define IPFIX_SOFTFLOWD_MAX_PACKET_SIZE 512
- +#define IPFIX_SOFTFLOWD_V4_TEMPLATE_ID 1024
- +#define IPFIX_SOFTFLOWD_V6_TEMPLATE_ID 2048
- +#define IPFIX_SOFTFLOWD_OPTION_TEMPLATE_ID 256
- +
- +#define IPFIX_DEFAULT_TEMPLATE_INTERVAL 16
- +
- +/* ... */
- +#define IPFIX_OPTION_SCOPE_SYSTEM 1
- +#define IPFIX_OPTION_SCOPE_INTERFACE 2
- +#define IPFIX_OPTION_SCOPE_LINECARD 3
- +#define IPFIX_OPTION_SCOPE_CACHE 4
- +#define IPFIX_OPTION_SCOPE_TEMPLATE 5
- +/* ... */
- +#define IPFIX_SAMPLING_ALGORITHM_DETERMINISTIC 1
- +#define IPFIX_SAMPLING_ALGORITHM_RANDOM 2
- +/* ... */
- +
- +static struct IPFIX_SOFTFLOWD_TEMPLATE v4_template;
- +static struct IPFIX_SOFTFLOWD_TEMPLATE v6_template;
- +static struct IPFIX_SOFTFLOWD_OPTION_TEMPLATE option_template;
- +static struct IPFIX_SOFTFLOWD_OPTION_DATA option_data;
- +static int ipfix_pkts_until_template = -1;
- +
- +static void
- +ipfix_init_template(void)
- +{
- + bzero(&v4_template, sizeof(v4_template));
- + v4_template.h.c.set_id = htons(IPFIX_TEMPLATE_SET_ID);
- + v4_template.h.c.length = htons(sizeof(v4_template));
- + v4_template.h.r.template_id = htons(IPFIX_SOFTFLOWD_V4_TEMPLATE_ID);
- + v4_template.h.r.count = htons(IPFIX_SOFTFLOWD_TEMPLATE_NRECORDS);
- + v4_template.r[0].ie = htons(IPFIX_sourceIPv4Address);
- + v4_template.r[0].length = htons(4);
- + v4_template.r[1].ie = htons(IPFIX_destinationIPv4Address);
- + v4_template.r[1].length = htons(4);
- + v4_template.r[2].ie = htons(IPFIX_flowEndSysUpTime);
- + v4_template.r[2].length = htons(4);
- + v4_template.r[3].ie = htons(IPFIX_flowStartSysUpTime);
- + v4_template.r[3].length = htons(4);
- + v4_template.r[4].ie = htons(IPFIX_octetDeltaCount);
- + v4_template.r[4].length = htons(4);
- + v4_template.r[5].ie = htons(IPFIX_packetDeltaCount);
- + v4_template.r[5].length = htons(4);
- + v4_template.r[6].ie = htons(IPFIX_ingressInterface);
- + v4_template.r[6].length = htons(4);
- + v4_template.r[7].ie = htons(IPFIX_egressInterface);
- + v4_template.r[7].length = htons(4);
- + v4_template.r[8].ie = htons(IPFIX_sourceTransportPort);
- + v4_template.r[8].length = htons(2);
- + v4_template.r[9].ie = htons(IPFIX_destinationTransportPort);
- + v4_template.r[9].length = htons(2);
- + v4_template.r[10].ie = htons(IPFIX_protocolIdentifier);
- + v4_template.r[10].length = htons(1);
- + v4_template.r[11].ie = htons(IPFIX_tcpControlBits);
- + v4_template.r[11].length = htons(1);
- + v4_template.r[12].ie = htons(IPFIX_ipVersion);
- + v4_template.r[12].length = htons(1);
- +
- + bzero(&v6_template, sizeof(v6_template));
- + v6_template.h.c.set_id = htons(IPFIX_TEMPLATE_SET_ID);
- + v6_template.h.c.length = htons(sizeof(v6_template));
- + v6_template.h.r.template_id = htons(IPFIX_SOFTFLOWD_V6_TEMPLATE_ID);
- + v6_template.h.r.count = htons(IPFIX_SOFTFLOWD_TEMPLATE_NRECORDS);
- + v6_template.r[0].ie = htons(IPFIX_sourceIPv6Address);
- + v6_template.r[0].length = htons(16);
- + v6_template.r[1].ie = htons(IPFIX_destinationIPv6Address);
- + v6_template.r[1].length = htons(16);
- + v6_template.r[2].ie = htons(IPFIX_flowEndSysUpTime);
- + v6_template.r[2].length = htons(4);
- + v6_template.r[3].ie = htons(IPFIX_flowStartSysUpTime);
- + v6_template.r[3].length = htons(4);
- + v6_template.r[4].ie = htons(IPFIX_octetDeltaCount);
- + v6_template.r[4].length = htons(4);
- + v6_template.r[5].ie = htons(IPFIX_packetDeltaCount);
- + v6_template.r[5].length = htons(4);
- + v6_template.r[6].ie = htons(IPFIX_ingressInterface);
- + v6_template.r[6].length = htons(4);
- + v6_template.r[7].ie = htons(IPFIX_egressInterface);
- + v6_template.r[7].length = htons(4);
- + v6_template.r[8].ie = htons(IPFIX_sourceTransportPort);
- + v6_template.r[8].length = htons(2);
- + v6_template.r[9].ie = htons(IPFIX_destinationTransportPort);
- + v6_template.r[9].length = htons(2);
- + v6_template.r[10].ie = htons(IPFIX_protocolIdentifier);
- + v6_template.r[10].length = htons(1);
- + v6_template.r[11].ie = htons(IPFIX_tcpControlBits);
- + v6_template.r[11].length = htons(1);
- + v6_template.r[12].ie = htons(IPFIX_ipVersion);
- + v6_template.r[12].length = htons(1);
- +}
- +
- +static void
- +ipfix_init_option(struct timeval *system_boot_time, struct OPTION *option) {
- + bzero(&option_template, sizeof(option_template));
- + option_template.h.c.set_id = htons(IPFIX_OPTION_TEMPLATE_SET_ID);
- + option_template.h.c.length = htons(sizeof(option_template));
- + option_template.h.r.template_id = htons(IPFIX_SOFTFLOWD_OPTION_TEMPLATE_ID);
- + option_template.h.r.count = htons(IPFIX_SOFTFLOWD_OPTION_TEMPLATE_SCOPE_RECORDS + IPFIX_SOFTFLOWD_OPTION_TEMPLATE_NRECORDS);
- + option_template.h.scope_count = htons(IPFIX_SOFTFLOWD_OPTION_TEMPLATE_SCOPE_RECORDS);
- + option_template.s[0].ie = htons(IPFIX_meteringProcessId);
- + option_template.s[0].length = htons(sizeof(option_data.scope_pid));
- + option_template.r[0].ie = htons(IPFIX_systemInitTimeMilliseconds);
- + option_template.r[0].length = htons(sizeof(option_data.systemInitTimeMilliseconds));
- + option_template.r[1].ie = htons(PSAMP_selectorAlgorithm);
- + option_template.r[1].length = htons(sizeof(option_data.samplingAlgorithm));
- + option_template.r[2].ie = htons(PSAMP_samplingPacketInterval);
- + option_template.r[2].length = htons(sizeof(option_data.samplingInterval));
- + option_template.r[3].ie = htons(PSAMP_samplingPacketSpace);
- + option_template.r[3].length = htons(sizeof(option_data.samplingSpace));
- +
- + bzero(&option_data, sizeof(option_data));
- + option_data.c.set_id = htons(IPFIX_SOFTFLOWD_OPTION_TEMPLATE_ID);
- + option_data.c.length = htons(sizeof(option_data));
- + option_data.scope_pid = htonl((u_int32_t)option->meteringProcessId);
- +#if defined HAVE_HTOBE64
- + option_data.systemInitTimeMilliseconds = htobe64((u_int64_t)system_boot_time->tv_sec * 1000 + (u_int64_t)system_boot_time->tv_usec / 1000);
- +#elif defined HAVE_HTONLL
- + option_data.systemInitTimeMilliseconds = htonll((u_int64_t)system_boot_time->tv_sec * 1000 + (u_int64_t)system_boot_time->tv_usec / 1000);
- +#endif
- + option_data.samplingAlgorithm = htons(PSAMP_selectorAlgorithm_count);
- + option_data.samplingInterval = htons(1);
- + option_data.samplingSpace = htonl(option->sample > 0 ? option->sample - 1 : 0);
- +}
- +static int
- +ipfix_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 IPFIX_SOFTFLOWD_DATA_V4 d4;
- + struct IPFIX_SOFTFLOWD_DATA_V6 d6;
- + } d[2];
- + struct IPFIX_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 IPFIX_SOFTFLOWD_DATA_V4);
- + memcpy(&d[0].d4.sourceIPv4Address, &flow->addr[0].v4, 4);
- + memcpy(&d[0].d4.destinationIPv4Address, &flow->addr[1].v4, 4);
- + memcpy(&d[1].d4.sourceIPv4Address, &flow->addr[1].v4, 4);
- + memcpy(&d[1].d4.destinationIPv4Address, &flow->addr[0].v4, 4);
- + dc[0] = &d[0].d4.c;
- + dc[1] = &d[1].d4.c;
- + dc[0]->ipVersion = dc[1]->ipVersion = 4;
- + break;
- + case AF_INET6:
- + freclen = sizeof(struct IPFIX_SOFTFLOWD_DATA_V6);
- + memcpy(&d[0].d6.sourceIPv6Address, &flow->addr[0].v6, 16);
- + memcpy(&d[0].d6.destinationIPv6Address, &flow->addr[1].v6, 16);
- + memcpy(&d[1].d6.sourceIPv6Address, &flow->addr[1].v6, 16);
- + memcpy(&d[1].d6.destinationIPv6Address, &flow->addr[0].v6, 16);
- + dc[0] = &d[0].d6.c;
- + dc[1] = &d[1].d6.c;
- + dc[0]->ipVersion = dc[1]->ipVersion = 6;
- + break;
- + default:
- + return (-1);
- + }
- +
- + dc[0]->flowStartSysUpTime = dc[1]->flowStartSysUpTime =
- + htonl(timeval_sub_ms(&flow->flow_start, system_boot_time));
- + dc[0]->flowEndSysUpTime = dc[1]->flowEndSysUpTime =
- + htonl(timeval_sub_ms(&flow->flow_last, system_boot_time));
- + dc[0]->octetDeltaCount = htonl(flow->octets[0]);
- + dc[1]->octetDeltaCount = htonl(flow->octets[1]);
- + dc[0]->packetDeltaCount = htonl(flow->packets[0]);
- + dc[1]->packetDeltaCount = htonl(flow->packets[1]);
- + dc[0]->ingressInterface = dc[0]->egressInterface = htonl(ifidx);
- + dc[1]->ingressInterface = dc[1]->egressInterface = htonl(ifidx);
- + dc[0]->sourceTransportPort = dc[1]->destinationTransportPort = flow->port[0];
- + dc[1]->sourceTransportPort = dc[0]->destinationTransportPort = flow->port[1];
- + dc[0]->protocolIdentifier = dc[1]->protocolIdentifier = flow->protocol;
- + dc[0]->tcpControlBits = flow->tcp_flags[0];
- + dc[1]->tcpControlBits = flow->tcp_flags[1];
- +
- + 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_ipfix(struct FLOW **flows, int num_flows, int nfsock,
- + u_int16_t ifidx, struct FLOWTRACKPARAMETERS *param,
- + int verbose_flag)
- +{
- + struct IPFIX_HEADER *ipfix;
- + struct IPFIX_SET_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[IPFIX_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 (ipfix_pkts_until_template == -1) {
- + ipfix_init_template();
- + ipfix_pkts_until_template = 0;
- + if (option != NULL){
- + ipfix_init_option(system_boot_time, option);
- + }
- + }
- +
- + last_valid = num_packets = 0;
- + for (j = 0; j < num_flows;) {
- + bzero(packet, sizeof(packet));
- + ipfix = (struct IPFIX_HEADER *)packet;
- +
- + ipfix->version = htons(10);
- + ipfix->length = 0; /* Filled as we go, htons at end */
- + ipfix->export_time = htonl(time(NULL));
- + ipfix->od_id = 0;
- + offset = sizeof(*ipfix);
- +
- + /* Refresh template headers if we need to */
- + if (ipfix_pkts_until_template <= 0) {
- + memcpy(packet + offset, &v4_template,
- + sizeof(v4_template));
- + offset += sizeof(v4_template);
- + memcpy(packet + offset, &v6_template,
- + sizeof(v6_template));
- + offset += sizeof(v6_template);
- + if (option != NULL){
- + memcpy(packet + offset, &option_template,
- + sizeof(option_template));
- + offset += sizeof(option_template);
- + memcpy(packet + offset, &option_data,
- + sizeof(option_data));
- + offset += sizeof(option_data);
- + }
- +
- + ipfix_pkts_until_template = IPFIX_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->length += 4 - (offset % 4);
- + offset += 4 - (offset % 4);
- + }
- + /* Finalise last header */
- + dh->length = htons(dh->length);
- + }
- + if (offset + sizeof(*dh) > sizeof(packet)) {
- + /* Mark header is finished */
- + dh = NULL;
- + break;
- + }
- + dh = (struct IPFIX_SET_HEADER *)
- + (packet + offset);
- + dh->set_id =
- + (flows[i + j]->af == AF_INET) ?
- + v4_template.h.r.template_id :
- + v6_template.h.r.template_id;
- + last_af = flows[i + j]->af;
- + last_valid = offset;
- + dh->length = sizeof(*dh); /* Filled as we go */
- + offset += sizeof(*dh);
- + }
- +
- + r = ipfix_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->length += inc;
- + last_valid = 0; /* Don't clobber this header now */
- + if (verbose_flag) {
- + logit(LOG_DEBUG, "Flow %d/%d: "
- + "r %d offset %d ie %04x len %d(0x%04x)",
- + r, i, j, offset,
- + dh->set_id, dh->length,
- + dh->length);
- + }
- + }
- + /* Don't finish header if it has already been done */
- + if (dh != NULL) {
- + if (offset % 4 != 0) {
- + /* Pad to multiple of 4 */
- + dh->length += 4 - (offset % 4);
- + offset += 4 - (offset % 4);
- + }
- + /* Finalise last header */
- + dh->length = htons(dh->length);
- + }
- + ipfix->length = htons(offset);
- + ipfix->sequence = htonl(*packets_sent + num_packets + 1);
- +
- + 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++;
- + ipfix_pkts_until_template--;
- +
- + j += i;
- + }
- +
- + *flows_exported += j;
- + return (num_packets);
- +}
- +
- +void
- +ipfix_resend_template(void)
- +{
- + if (ipfix_pkts_until_template > 0)
- + ipfix_pkts_until_template = 0;
- +}
- --- a/softflowd.c
- +++ b/softflowd.c
- @@ -107,6 +107,7 @@
- { 5, send_netflow_v5, 0 },
- { 1, send_netflow_v1, 0 },
- { 9, send_netflow_v9, 1 },
- + { 10, send_ipfix, 1 },
- { -1, NULL, 0 },
- };
-
- @@ -1494,7 +1495,7 @@
- " (default: %s)\n"
- " -c pidfile Location of control socket\n"
- " (default: %s)\n"
- -" -v 1|5|9 NetFlow export packet version\n"
- +" -v 1|5|9|10 NetFlow export packet version\n"
- " -L hoplimit Set TTL/hoplimit for export datagrams\n"
- " -T full|proto|ip Set flow tracking level (default: full)\n"
- " -6 Track IPv6 flows, regardless of whether selected \n"
- @@ -1888,6 +1889,7 @@
- logit(LOG_NOTICE, "Exporting flows to [%s]:%s",
- dest_addr, dest_serv);
- }
- + flowtrack.param.option.meteringProcessId = getpid();
-
- /* Main processing loop */
- gettimeofday(&flowtrack.param.system_boot_time, NULL);
- --- a/softflowd.h
- +++ b/softflowd.h
- @@ -79,6 +79,7 @@
- */
- struct OPTION {
- uint32_t sample;
- + pid_t meteringProcessId;
- };
-
- struct FLOWTRACKPARAMETERS {
- @@ -224,6 +225,9 @@
- int send_netflow_v9(struct FLOW **flows, int num_flows, int nfsock,
- u_int16_t ifidx, struct FLOWTRACKPARAMETERS *param,
- int verbose_flag);
- +int send_ipfix(struct FLOW **flows, int num_flows, int nfsock,
- + u_int16_t ifidx, struct FLOWTRACKPARAMETERS *param,
- + int verbose_flag);
-
- /* Force a resend of the flow template */
- void netflow9_resend_template(void);
|