123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687 |
- Subject: ToS field is metered and exported in NetFlow v1,v5,v9 and IPFIX in default settings
- Origin: softflowd-0.9.9-5-gb4a7a1c <https://github.com/irino/softflowd/commit/softflowd-0.9.9-5-gb4a7a1c>
- Upstream-Author: Hitoshi Irino <hitoshi.irino@gmail.com>
- Date: Sun Dec 23 23:44:10 2012 +0900
- -A option is added for exporting absolute time field in IPFIX records to be able to receive with NFDUMP(nfcapd).
- -P option is added to select export transport protocol from UDP, TCP, and SCTP. (It is not tested yet.)
- --- a/configure.ac
- +++ b/configure.ac
- @@ -52,6 +52,7 @@
- [ AC_DEFINE_UNQUOTED([PRIVDROP_CHROOT_DIR], ["${withval}"], [privdrop chroot directory]) ]
- )
-
- +AC_DEFINE([_BSD_SOURCE], [], [Define BSD SOURCE for Linux])
- 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)
- --- a/ipfix.c
- +++ b/ipfix.c
- @@ -28,6 +28,11 @@
- #include "treetype.h"
- #include "softflowd.h"
-
- +#if defined (HAVE_HTONLL) && !defined (HAVE_HTOBE64)
- +#define htobe64 htonll
- +#endif
- +#define JAN_1970 2208988800UL /* 1970 - 1900 in seconds */
- +
- /* IPFIX a.k.a. Netflow v.10 */
- struct IPFIX_HEADER {
- u_int16_t version, length;
- @@ -62,6 +67,7 @@
- #define IPFIX_packetDeltaCount 2
- /* ... */
- #define IPFIX_protocolIdentifier 4
- +#define IPFIX_ipClassOfService 5
- /* ... */
- #define IPFIX_tcpControlBits 6
- #define IPFIX_sourceTransportPort 7
- @@ -77,12 +83,23 @@
- #define IPFIX_flowStartSysUpTime 22
- /* ... */
- #define IPFIX_sourceIPv6Address 27
- -#define IPFIX_destinationIPv6Address 28
- +#define IPFIX_destinationIPv6Address 28
- +/* ... */
- +#define IPFIX_ipVersion 60
- /* ... */
- -#define IPFIX_ipVersion 60
- -
- #define IPFIX_meteringProcessId 143
- +/* ... */
- +#define IPFIX_flowStartSeconds 150
- +#define IPFIX_flowEndSeconds 151
- +#define IPFIX_flowStartMilliSeconds 152
- +#define IPFIX_flowEndMilliSeconds 153
- +#define IPFIX_flowStartMicroSeconds 154
- +#define IPFIX_flowEndMicroSeconds 155
- +#define IPFIX_flowStartNanoSeconds 156
- +#define IPFIX_flowEndNanoSeconds 157
- +/* ... */
- #define IPFIX_systemInitTimeMilliseconds 160
- +/* ... */
- #define PSAMP_selectorAlgorithm 304
- #define PSAMP_samplingPacketInterval 305
- #define PSAMP_samplingPacketSpace 306
- @@ -90,7 +107,7 @@
- #define PSAMP_selectorAlgorithm_count 1
-
- /* Stuff pertaining to the templates that softflowd uses */
- -#define IPFIX_SOFTFLOWD_TEMPLATE_NRECORDS 13
- +#define IPFIX_SOFTFLOWD_TEMPLATE_NRECORDS 14
- struct IPFIX_SOFTFLOWD_TEMPLATE {
- struct IPFIX_TEMPLATE_SET_HEADER h;
- struct IPFIX_FIELD_SPECIFIER r[IPFIX_SOFTFLOWD_TEMPLATE_NRECORDS];
- @@ -106,22 +123,35 @@
-
- /* 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;
- + u_int8_t protocolIdentifier, tcpControlBits, ipVersion, ipClassOfService;
- + //u_int32_t flowEndSysUpTime, flowStartSysUpTime;
- } __packed;
-
- +union IPFIX_SOFTFLOWD_DATA_TIME {
- + struct {
- + u_int32_t start;
- + u_int32_t end;
- + } u32;
- + struct {
- + u_int64_t start;
- + u_int64_t end;
- + } u64;
- +};
- +
- struct IPFIX_SOFTFLOWD_DATA_V4 {
- u_int32_t sourceIPv4Address, destinationIPv4Address;
- struct IPFIX_SOFTFLOWD_DATA_COMMON c;
- + union IPFIX_SOFTFLOWD_DATA_TIME t;
- } __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;
- + union IPFIX_SOFTFLOWD_DATA_TIME t;
- } __packed;
-
- struct IPFIX_SOFTFLOWD_OPTION_DATA {
- @@ -159,7 +189,7 @@
- static int ipfix_pkts_until_template = -1;
-
- static void
- -ipfix_init_template(void)
- +ipfix_init_template(struct FLOWTRACKPARAMETERS *param)
- {
- bzero(&v4_template, sizeof(v4_template));
- v4_template.h.c.set_id = htons(IPFIX_TEMPLATE_SET_ID);
- @@ -170,28 +200,52 @@
- 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].ie = htons(IPFIX_octetDeltaCount);
- v4_template.r[2].length = htons(4);
- - v4_template.r[3].ie = htons(IPFIX_flowStartSysUpTime);
- + v4_template.r[3].ie = htons(IPFIX_packetDeltaCount);
- v4_template.r[3].length = htons(4);
- - v4_template.r[4].ie = htons(IPFIX_octetDeltaCount);
- + v4_template.r[4].ie = htons(IPFIX_ingressInterface);
- v4_template.r[4].length = htons(4);
- - v4_template.r[5].ie = htons(IPFIX_packetDeltaCount);
- + v4_template.r[5].ie = htons(IPFIX_egressInterface);
- 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[6].ie = htons(IPFIX_sourceTransportPort);
- + v4_template.r[6].length = htons(2);
- + v4_template.r[7].ie = htons(IPFIX_destinationTransportPort);
- + v4_template.r[7].length = htons(2);
- + v4_template.r[8].ie = htons(IPFIX_protocolIdentifier);
- + v4_template.r[8].length = htons(1);
- + v4_template.r[9].ie = htons(IPFIX_tcpControlBits);
- + v4_template.r[9].length = htons(1);
- + v4_template.r[10].ie = htons(IPFIX_ipVersion);
- v4_template.r[10].length = htons(1);
- - v4_template.r[11].ie = htons(IPFIX_tcpControlBits);
- + v4_template.r[11].ie = htons(IPFIX_ipClassOfService);
- v4_template.r[11].length = htons(1);
- - v4_template.r[12].ie = htons(IPFIX_ipVersion);
- - v4_template.r[12].length = htons(1);
- + if (param->time_format == 's') {
- + v4_template.r[12].ie = htons(IPFIX_flowStartSeconds);
- + v4_template.r[12].length = htons(sizeof(u_int32_t));
- + v4_template.r[13].ie = htons(IPFIX_flowEndSeconds);
- + v4_template.r[13].length = htons(sizeof(u_int32_t));
- + } else if (param->time_format == 'm') {
- + v4_template.r[12].ie = htons(IPFIX_flowStartMilliSeconds);
- + v4_template.r[12].length = htons(sizeof(u_int64_t));
- + v4_template.r[13].ie = htons(IPFIX_flowEndMilliSeconds);
- + v4_template.r[13].length = htons(sizeof(u_int64_t));
- + } else if (param->time_format == 'M') {
- + v4_template.r[12].ie = htons(IPFIX_flowStartMicroSeconds);
- + v4_template.r[12].length = htons(sizeof(u_int64_t));
- + v4_template.r[13].ie = htons(IPFIX_flowEndMicroSeconds);
- + v4_template.r[13].length = htons(sizeof(u_int64_t));
- + } else if (param->time_format == 'n') {
- + v4_template.r[12].ie = htons(IPFIX_flowStartNanoSeconds);
- + v4_template.r[12].length = htons(sizeof(u_int64_t));
- + v4_template.r[13].ie = htons(IPFIX_flowEndNanoSeconds);
- + v4_template.r[13].length = htons(sizeof(u_int64_t));
- + } else {
- + v4_template.r[12].ie = htons(IPFIX_flowStartSysUpTime);
- + v4_template.r[12].length = htons(sizeof(u_int32_t));
- + v4_template.r[13].ie = htons(IPFIX_flowEndSysUpTime);
- + v4_template.r[13].length = htons(sizeof(u_int32_t));
- + }
-
- bzero(&v6_template, sizeof(v6_template));
- v6_template.h.c.set_id = htons(IPFIX_TEMPLATE_SET_ID);
- @@ -202,28 +256,52 @@
- 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].ie = htons(IPFIX_octetDeltaCount);
- v6_template.r[2].length = htons(4);
- - v6_template.r[3].ie = htons(IPFIX_flowStartSysUpTime);
- + v6_template.r[3].ie = htons(IPFIX_packetDeltaCount);
- v6_template.r[3].length = htons(4);
- - v6_template.r[4].ie = htons(IPFIX_octetDeltaCount);
- + v6_template.r[4].ie = htons(IPFIX_ingressInterface);
- v6_template.r[4].length = htons(4);
- - v6_template.r[5].ie = htons(IPFIX_packetDeltaCount);
- + v6_template.r[5].ie = htons(IPFIX_egressInterface);
- 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[6].ie = htons(IPFIX_sourceTransportPort);
- + v6_template.r[6].length = htons(2);
- + v6_template.r[7].ie = htons(IPFIX_destinationTransportPort);
- + v6_template.r[7].length = htons(2);
- + v6_template.r[8].ie = htons(IPFIX_protocolIdentifier);
- + v6_template.r[8].length = htons(1);
- + v6_template.r[9].ie = htons(IPFIX_tcpControlBits);
- + v6_template.r[9].length = htons(1);
- + v6_template.r[10].ie = htons(IPFIX_ipVersion);
- v6_template.r[10].length = htons(1);
- - v6_template.r[11].ie = htons(IPFIX_tcpControlBits);
- + v6_template.r[11].ie = htons(IPFIX_ipClassOfService);
- v6_template.r[11].length = htons(1);
- - v6_template.r[12].ie = htons(IPFIX_ipVersion);
- - v6_template.r[12].length = htons(1);
- + if (param->time_format == 's') {
- + v6_template.r[12].ie = htons(IPFIX_flowStartSeconds);
- + v6_template.r[12].length = htons(sizeof(u_int32_t));
- + v6_template.r[13].ie = htons(IPFIX_flowEndSeconds);
- + v6_template.r[13].length = htons(sizeof(u_int32_t));
- + } else if (param->time_format == 'm') {
- + v6_template.r[12].ie = htons(IPFIX_flowStartMilliSeconds);
- + v6_template.r[12].length = htons(sizeof(u_int64_t));
- + v6_template.r[13].ie = htons(IPFIX_flowEndMilliSeconds);
- + v6_template.r[13].length = htons(sizeof(u_int64_t));
- + } else if (param->time_format == 'M') {
- + v6_template.r[12].ie = htons(IPFIX_flowStartMicroSeconds);
- + v6_template.r[12].length = htons(sizeof(u_int64_t));
- + v6_template.r[13].ie = htons(IPFIX_flowEndMicroSeconds);
- + v6_template.r[13].length = htons(sizeof(u_int64_t));
- + } else if (param->time_format == 'n') {
- + v6_template.r[12].ie = htons(IPFIX_flowStartNanoSeconds);
- + v6_template.r[12].length = htons(sizeof(u_int64_t));
- + v6_template.r[13].ie = htons(IPFIX_flowEndNanoSeconds);
- + v6_template.r[13].length = htons(sizeof(u_int64_t));
- + } else {
- + v6_template.r[12].ie = htons(IPFIX_flowStartSysUpTime);
- + v6_template.r[12].length = htons(sizeof(u_int32_t));
- + v6_template.r[13].ie = htons(IPFIX_flowEndSysUpTime);
- + v6_template.r[13].length = htons(sizeof(u_int32_t));
- + }
- }
-
- static void
- @@ -249,10 +327,8 @@
- 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
- +#if defined (_BSD_SOURCE) && defined (HAVE_ENDIAN_H) || defined (HAVE_HTOBE64) || defined (HAVE_HTONLL)
- 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);
- @@ -260,13 +336,15 @@
- }
- 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)
- + u_int16_t ifidx, const struct timeval *system_boot_time, u_int *len_used,
- + struct FLOWTRACKPARAMETERS *param)
- {
- union {
- struct IPFIX_SOFTFLOWD_DATA_V4 d4;
- struct IPFIX_SOFTFLOWD_DATA_V6 d6;
- } d[2];
- struct IPFIX_SOFTFLOWD_DATA_COMMON *dc[2];
- + union IPFIX_SOFTFLOWD_DATA_TIME *dt[2];
- u_int freclen, ret_len, nflows;
-
- bzero(d, sizeof(d));
- @@ -274,32 +352,68 @@
- switch (flow->af) {
- case AF_INET:
- freclen = sizeof(struct IPFIX_SOFTFLOWD_DATA_V4);
- + if (!(param->time_format == 'm' || param->time_format == 'M' || param->time_format == 'n')) {
- + freclen -= (sizeof(u_int64_t) - sizeof(u_int32_t)) * 2;
- + }
- 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;
- + dt[0] = &d[0].d4.t;
- + dt[1] = &d[1].d4.t;
- dc[0]->ipVersion = dc[1]->ipVersion = 4;
- break;
- case AF_INET6:
- freclen = sizeof(struct IPFIX_SOFTFLOWD_DATA_V6);
- + if (!(param->time_format == 'm' || param->time_format == 'M' || param->time_format == 'n')) {
- + freclen -= (sizeof(u_int64_t) - sizeof(u_int32_t)) * 2;
- + }
- 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;
- + dt[0] = &d[0].d6.t;
- + dt[1] = &d[1].d6.t;
- 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));
- + if (param->time_format == 's') {
- + dt[0]->u32.start = dt[1]->u32.start =
- + htonl(flow->flow_start.tv_sec);
- + dt[0]->u32.end = dt[1]->u32.end =
- + htonl(flow->flow_last.tv_sec);
- + }
- +#if defined (_BSD_SOURCE) && defined (HAVE_ENDIAN_H) || defined (HAVE_HTOBE64) || defined (HAVE_HTONLL)
- + else if (param->time_format == 'm') { /* milliseconds */
- + dt[0]->u64.start = dt[1]->u64.start =
- + htobe64((u_int64_t)flow->flow_start.tv_sec * 1000 + (u_int64_t)flow->flow_start.tv_usec / 1000);
- + dt[0]->u64.end = dt[1]->u64.end =
- + htobe64((u_int64_t)flow->flow_last.tv_sec * 1000 + (u_int64_t)flow->flow_last.tv_usec / 1000);
- + } else if (param->time_format == 'M') { /* microseconds */
- + dt[0]->u64.start = dt[1]->u64.start =
- + htobe64(((u_int64_t)(flow->flow_start.tv_sec + JAN_1970) << 32) + (u_int64_t)((flow->flow_start.tv_usec << 32)/ 1e6));
- + dt[0]->u64.end = dt[1]->u64.end =
- + htobe64(((u_int64_t)(flow->flow_last.tv_sec + JAN_1970) << 32) + (u_int64_t)((flow->flow_start.tv_usec << 32)/ 1e6));
- + } else if (param->time_format == 'n') { /* nanoseconds */
- + dt[0]->u64.start = dt[1]->u64.start =
- + htobe64(((u_int64_t)(flow->flow_start.tv_sec + JAN_1970) << 32) + (u_int64_t)((flow->flow_start.tv_usec * 1000 << 32)/ 1e9));
- + dt[0]->u64.end = dt[1]->u64.end =
- + htobe64(((u_int64_t)(flow->flow_last.tv_sec + JAN_1970) << 32) + (u_int64_t)((flow->flow_start.tv_usec * 1000 << 32)/ 1e9));
- + }
- +#endif
- + else {
- + dt[0]->u32.start = dt[1]->u32.start =
- + htonl(timeval_sub_ms(&flow->flow_start, system_boot_time));
- + dt[0]->u32.end = dt[1]->u32.end =
- + 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]);
- @@ -311,6 +425,8 @@
- dc[0]->protocolIdentifier = dc[1]->protocolIdentifier = flow->protocol;
- dc[0]->tcpControlBits = flow->tcp_flags[0];
- dc[1]->tcpControlBits = flow->tcp_flags[1];
- + dc[0]->ipClassOfService = flow->tos[0];
- + dc[1]->ipClassOfService = flow->tos[1];
-
- if (flow->octets[0] > 0) {
- if (ret_len + freclen > len)
- @@ -355,7 +471,7 @@
- gettimeofday(&now, NULL);
-
- if (ipfix_pkts_until_template == -1) {
- - ipfix_init_template();
- + ipfix_init_template(param);
- ipfix_pkts_until_template = 0;
- if (option != NULL){
- ipfix_init_option(system_boot_time, option);
- @@ -424,7 +540,7 @@
- }
-
- r = ipfix_flow_to_flowset(flows[i + j], packet + offset,
- - sizeof(packet) - offset, ifidx, system_boot_time, &inc);
- + sizeof(packet) - offset, ifidx, system_boot_time, &inc, param);
- if (r <= 0) {
- /* yank off data header, if we had to go back */
- if (last_valid)
- --- a/netflow1.c
- +++ b/netflow1.c
- @@ -123,6 +123,7 @@
- system_boot_time));
- flw->protocol = flows[i]->protocol;
- flw->tcp_flags = flows[i]->tcp_flags[0];
- + flw->tos = flows[i]->tos[0];
- offset += sizeof(*flw);
- j++;
- hdr->flows++;
- @@ -145,6 +146,7 @@
- system_boot_time));
- flw->protocol = flows[i]->protocol;
- flw->tcp_flags = flows[i]->tcp_flags[1];
- + flw->tos = flows[i]->tos[1];
- offset += sizeof(*flw);
- j++;
- hdr->flows++;
- --- a/netflow5.c
- +++ b/netflow5.c
- @@ -128,6 +128,7 @@
- system_boot_time));
- flw->tcp_flags = flows[i]->tcp_flags[0];
- flw->protocol = flows[i]->protocol;
- + flw->tos = flows[i]->tos[0];
- offset += sizeof(*flw);
- j++;
- hdr->flows++;
- @@ -151,6 +152,7 @@
- system_boot_time));
- flw->tcp_flags = flows[i]->tcp_flags[1];
- flw->protocol = flows[i]->protocol;
- + flw->tos = flows[i]->tos[1];
- offset += sizeof(*flw);
- j++;
- hdr->flows++;
- --- a/netflow9.c
- +++ b/netflow9.c
- @@ -58,7 +58,8 @@
- #define NF9_IN_BYTES 1
- #define NF9_IN_PACKETS 2
- /* ... */
- -#define NF9_IN_PROTOCOL 4
- +#define NF9_PROTOCOL 4
- +#define NF9_TOS 5
- /* ... */
- #define NF9_TCP_FLAGS 6
- #define NF9_L4_SRC_PORT 7
- @@ -102,7 +103,7 @@
- u_int32_t bytes, packets;
- u_int32_t if_index_in, if_index_out;
- u_int16_t src_port, dst_port;
- - u_int8_t protocol, tcp_flags, ipproto;
- + u_int8_t protocol, tcp_flags, ipproto, tos;
- } __packed;
-
- struct NF9_SOFTFLOWD_DATA_V4 {
- @@ -176,12 +177,14 @@
- v4_template.r[8].length = htons(2);
- v4_template.r[9].type = htons(NF9_L4_DST_PORT);
- v4_template.r[9].length = htons(2);
- - v4_template.r[10].type = htons(NF9_IN_PROTOCOL);
- + v4_template.r[10].type = htons(NF9_PROTOCOL);
- v4_template.r[10].length = htons(1);
- v4_template.r[11].type = htons(NF9_TCP_FLAGS);
- v4_template.r[11].length = htons(1);
- v4_template.r[12].type = htons(NF9_IP_PROTOCOL_VERSION);
- v4_template.r[12].length = htons(1);
- + v4_template.r[13].type = htons(NF9_TOS);
- + v4_template.r[13].length = htons(1);
-
- bzero(&v6_template, sizeof(v6_template));
- v6_template.h.c.flowset_id = htons(NF9_TEMPLATE_FLOWSET_ID);
- @@ -208,12 +211,14 @@
- v6_template.r[8].length = htons(2);
- v6_template.r[9].type = htons(NF9_L4_DST_PORT);
- v6_template.r[9].length = htons(2);
- - v6_template.r[10].type = htons(NF9_IN_PROTOCOL);
- + v6_template.r[10].type = htons(NF9_PROTOCOL);
- v6_template.r[10].length = htons(1);
- v6_template.r[11].type = htons(NF9_TCP_FLAGS);
- v6_template.r[11].length = htons(1);
- v6_template.r[12].type = htons(NF9_IP_PROTOCOL_VERSION);
- v6_template.r[12].length = htons(1);
- + v6_template.r[13].type = htons(NF9_TOS);
- + v6_template.r[13].length = htons(1);
- }
-
- static void
- @@ -291,6 +296,8 @@
- 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];
-
- if (flow->octets[0] > 0) {
- if (ret_len + freclen > len)
- --- a/softflowd.c
- +++ b/softflowd.c
- @@ -1271,7 +1271,7 @@
- }
-
- static int
- -connsock(struct sockaddr_storage *addr, socklen_t len, int hoplimit)
- +connsock(struct sockaddr_storage *addr, socklen_t len, int hoplimit, int protocol)
- {
- int s;
- unsigned int h6;
- @@ -1279,7 +1279,7 @@
- struct sockaddr_in *in4 = (struct sockaddr_in *)addr;
- struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr;
-
- - if ((s = socket(addr->ss_family, SOCK_DGRAM, 0)) == -1) {
- + if ((s = socket(addr->ss_family, protocol == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM, protocol)) == -1) {
- fprintf(stderr, "socket() error: %s\n",
- strerror(errno));
- exit(1);
- @@ -1486,24 +1486,28 @@
- fprintf(stderr,
- "Usage: %s [options] [bpf_program]\n"
- "This is %s version %s. Valid commandline options:\n"
- -" -i [idx:]interface Specify interface to listen on\n"
- -" -r pcap_file Specify packet capture file to read\n"
- -" -t timeout=time Specify named timeout\n"
- -" -m max_flows Specify maximum number of flows to track (default %d)\n"
- -" -n host:port Send Cisco NetFlow(tm)-compatible packets to host:port\n"
- -" -p pidfile Record pid in specified file\n"
- -" (default: %s)\n"
- -" -c pidfile Location of control socket\n"
- -" (default: %s)\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"
- -" NetFlow export protocol supports it\n"
- -" -d Don't daemonise (run in foreground)\n"
- -" -D Debug mode: foreground + verbosity + track v6 flows\n"
- -" -s sampling_rate Specify periodical sampling rate (denominator)\n"
- -" -h Display this help\n"
- +" -i [idx:]interface Specify interface to listen on\n"
- +" -r pcap_file Specify packet capture file to read\n"
- +" -t timeout=time Specify named timeout\n"
- +" -m max_flows Specify maximum number of flows to track (default %d)\n"
- +" -n host:port Send Cisco NetFlow(tm)-compatible packets to host:port\n"
- +" -p pidfile Record pid in specified file\n"
- +" (default: %s)\n"
- +" -c pidfile Location of control socket\n"
- +" (default: %s)\n"
- +" -v 1|5|9|10 NetFlow export packet version\n"
- +" (10 means IPFI)\n"
- +" -L hoplimit Set TTL/hoplimit for export datagrams\n"
- +" -T full|port|proto|ip Set flow tracking level (default: full)\n"
- +" -6 Track IPv6 flows, regardless of whether selected \n"
- +" NetFlow export protocol supports it\n"
- +" -d Don't daemonise (run in foreground)\n"
- +" -D Debug mode: foreground + verbosity + track v6 flows\n"
- +" -s sampling_rate Specify periodical sampling rate (denominator)\n"
- +" -P udp|tcp|sctp Specify transport layer protocol for exporting packets\n"
- +" -A sec|milli|micro|nano Specify absolute time format form exporting records\n"
- +" -s sampling_rate Specify periodical sampling rate (denominator)\n"
- +" -h Display this help\n"
- "\n"
- "Valid timeout names and default values:\n"
- " tcp (default %6d)"
- @@ -1695,6 +1699,7 @@
- struct NETFLOW_TARGET target;
- struct CB_CTXT cb_ctxt;
- struct pollfd pl[2];
- + int protocol = IPPROTO_UDP;
-
- closefrom(STDERR_FILENO + 1);
-
- @@ -1714,7 +1719,7 @@
- dontfork_flag = 0;
- always_v6 = 0;
-
- - while ((ch = getopt(argc, argv, "6hdDL:T:i:r:f:t:n:m:p:c:v:s:")) != -1) {
- + while ((ch = getopt(argc, argv, "6hdDL:T:i:r:f:t:n:m:p:c:v:s:P:A:")) != -1) {
- switch (ch) {
- case '6':
- always_v6 = 1;
- @@ -1766,6 +1771,8 @@
- case 'T':
- if (strcasecmp(optarg, "full") == 0)
- flowtrack.param.track_level = TRACK_FULL;
- + else if (strcasecmp(optarg, "port") == 0)
- + flowtrack.param.track_level = TRACK_IP_PROTO_PORT;
- else if (strcasecmp(optarg, "proto") == 0)
- flowtrack.param.track_level = TRACK_IP_PROTO;
- else if (strcasecmp(optarg, "ip") == 0)
- @@ -1824,6 +1831,38 @@
- flowtrack.param.option.sample = 0;
- }
- break;
- + case 'P':
- + if (strcasecmp(optarg, "udp") == 0)
- + protocol = IPPROTO_UDP;
- + else if (strcasecmp(optarg, "tcp") == 0)
- + protocol = IPPROTO_TCP;
- +#ifdef IPPROTO_SCTP
- + else if (strcasecmp(optarg, "sctp") == 0)
- + protocol = IPPROTO_SCTP;
- +#endif
- + else {
- + fprintf(stderr, "Unknown transport layer protocol"
- + "\n");
- + usage();
- + exit(1);
- + }
- + break;
- + case 'A':
- + if (strcasecmp(optarg, "sec") == 0)
- + flowtrack.param.time_format = 's';
- + else if (strcasecmp(optarg, "milli") == 0)
- + flowtrack.param.time_format = 'm';
- + else if (strcasecmp(optarg, "micro") == 0)
- + flowtrack.param.time_format = 'M';
- + else if (strcasecmp(optarg, "nano") == 0)
- + flowtrack.param.time_format = 'n';
- + else {
- + fprintf(stderr, "Unknown time format"
- + "\n");
- + usage();
- + exit(1);
- + }
- + break;
- default:
- fprintf(stderr, "Invalid commandline option.\n");
- usage();
- @@ -1852,7 +1891,7 @@
- fprintf(stderr, "getnameinfo: %d\n", err);
- exit(1);
- }
- - target.fd = connsock(&dest, dest_len, hoplimit);
- + target.fd = connsock(&dest, dest_len, hoplimit, protocol);
- }
-
- /* Control socket */
- --- a/softflowd.h
- +++ b/softflowd.h
- @@ -69,9 +69,10 @@
- };
-
- /* Flow tracking levels */
- -#define TRACK_FULL 1 /* src/dst/addr/port/proto 5-tuple */
- -#define TRACK_IP_PROTO 2 /* src/dst/proto 3-tuple */
- -#define TRACK_IP_ONLY 3 /* src/dst tuple */
- +#define TRACK_FULL 1 /* src/dst/addr/port/proto/tos 6-tuple */
- +#define TRACK_IP_PROTO_PORT 2 /* src/dst/addr/port/proto 5-tuple */
- +#define TRACK_IP_PROTO 3 /* src/dst/proto 3-tuple */
- +#define TRACK_IP_ONLY 4 /* src/dst tuple */
-
- /*
- * This structure contains optional information carried by Option Data
- @@ -136,6 +137,7 @@
-
- /* Optional information */
- struct OPTION option;
- + char time_format;
- };
- /*
- * This structure is the root of the flow tracking system.
- @@ -166,6 +168,15 @@
- struct EXPIRY *expiry; /* Pointer to expiry record */
- FLOW_ENTRY(FLOW) trp; /* Tree pointer */
-
- + /* Per-flow statistics (all in _host_ byte order) */
- + u_int64_t flow_seq; /* Flow ID */
- + struct timeval flow_start; /* Time of creation */
- + struct timeval flow_last; /* Time of last traffic */
- +
- + /* Per-endpoint statistics (all in _host_ byte order) */
- + u_int32_t octets[2]; /* Octets so far */
- + u_int32_t packets[2]; /* Packets so far */
- +
- /* Flow identity (all are in network byte order) */
- int af; /* Address family of flow */
- u_int32_t ip6_flowlabel[2]; /* IPv6 Flowlabel */
- @@ -175,16 +186,8 @@
- } addr[2]; /* Endpoint addresses */
- u_int16_t port[2]; /* Endpoint ports */
- u_int8_t tcp_flags[2]; /* Cumulative OR of flags */
- + u_int8_t tos[2]; /* Tos */
- u_int8_t protocol; /* Protocol */
- -
- - /* Per-flow statistics (all in _host_ byte order) */
- - u_int64_t flow_seq; /* Flow ID */
- - struct timeval flow_start; /* Time of creation */
- - struct timeval flow_last; /* Time of last traffic */
- -
- - /* Per-endpoint statistics (all in _host_ byte order) */
- - u_int32_t octets[2]; /* Octets so far */
- - u_int32_t packets[2]; /* Packets so far */
- };
-
- /*
|